fvwm-2.7.0/0000755000175000017500000000000014324316056007504 500000000000000fvwm-2.7.0/configure0000755000175000017500000155707014324315775011361 00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.71 for fvwm 2.7.0. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation, # Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh as_nop=: if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else $as_nop case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi # Reset variables that may have inherited troublesome values from # the environment. # IFS needs to be set, to space, tab, and newline, in precisely that order. # (If _AS_PATH_WALK were called with IFS unset, it would have the # side effect of setting IFS to empty, thus disabling word splitting.) # Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl IFS=" "" $as_nl" PS1='$ ' PS2='> ' PS4='+ ' # Ensure predictable behavior from utilities with locale-dependent output. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # We cannot yet rely on "unset" to work, but we need these variables # to be unset--not just set to an empty or harmless value--now, to # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct # also avoids known problems related to "unset" and subshell syntax # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH do eval test \${$as_var+y} \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done # Ensure that fds 0, 1, and 2 are open. if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="as_nop=: if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else \$as_nop case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ) then : else \$as_nop exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 blah=\$(echo \$(echo blah)) test x\"\$blah\" = xblah || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null then : as_have_required=yes else $as_nop as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null then : else $as_nop as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null then : CONFIG_SHELL=$as_shell as_have_required=yes if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null then : break 2 fi fi done;; esac as_found=false done IFS=$as_save_IFS if $as_found then : else $as_nop if { test -f "$SHELL" || test -f "$SHELL.exe"; } && as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null then : CONFIG_SHELL=$SHELL as_have_required=yes fi fi if test "x$CONFIG_SHELL" != x then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno then : printf "%s\n" "$0: This script requires a shell more modern than all" printf "%s\n" "$0: the shells that I found on your system." if test ${ZSH_VERSION+y} ; then printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should" printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later." else printf "%s\n" "$0: Please tell bug-autoconf@gnu.org and $0: fvwm-workers@fvwm.org about your system, including any $0: error possibly output before this message. Then install $0: a modern shell, or manually run the script under such a $0: shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_nop # --------- # Do nothing but, unlike ":", preserve the value of $?. as_fn_nop () { return $? } as_nop=as_fn_nop # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null then : eval 'as_fn_append () { eval $1+=\$2 }' else $as_nop as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null then : eval 'as_fn_arith () { as_val=$(( $* )) }' else $as_nop as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_nop # --------- # Do nothing but, unlike ":", preserve the value of $?. as_fn_nop () { return $? } as_nop=as_fn_nop # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } # Determine whether it's possible to make 'echo' print without a newline. # These variables are no longer used directly by Autoconf, but are AC_SUBSTed # for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac # For backward compatibility with old third-party macros, we provide # the shell variables $as_echo and $as_echo_n. New code should use # AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. as_echo='printf %s\n' as_echo_n='printf %s' rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='fvwm' PACKAGE_TARNAME='fvwm' PACKAGE_VERSION='2.7.0' PACKAGE_STRING='fvwm 2.7.0' PACKAGE_BUGREPORT='fvwm-workers@fvwm.org' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_STDIO_H # include #endif #ifdef HAVE_STDLIB_H # include #endif #ifdef HAVE_STRING_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_header_c_list= ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS with_xpm with_xrender with_xinerama with_xft with_xcursor with_stroke with_sm with_shm with_shape with_rplay with_readline with_rsvg with_png with_perllib with_iconv with_gettext with_gdkimlib with_bidi GDK_IMLIB_LIBS GDK_IMLIB_CFLAGS IMLIBCONF EGREP GREP RANLIB LN_S FVWM_CPP CATOBJEXT DUMMYPOFILES UPDATEPOFILES GMOFILES POFILES CATALOGS INST_LINGUAS MKINSTALLDIRS LOCALEDIR POSUB USE_NLS intl_CFLAGS intl_LIBS MSGUNIQ MSGMERGE XGETTEXT GMSGFMT MSGFMT ALL_DOMAINS FVWMSCRIPT_DOMAIN FVWMTASKBAR_DOMAIN FVWM_DOMAIN ALL_LINGUAS FVWM_PERLLIB Bidi_CFLAGS Bidi_LIBS FRIBIDI_CONFIG iconv_CFLAGS iconv_LIBS readline_CFLAGS readline_LIBS stroke_CFLAGS stroke_LIBS rplay_CFLAGS rplay_LIBS rsvg_LIBS rsvg_CFLAGS png_LIBS png_CFLAGS xpm_CFLAGS xpm_LIBS Xft_CFLAGS Xft_LIBS XFT_LIBS XFT_CFLAGS XFT_CONFIG FC_LIBS FC_CFLAGS FC_CONFIG Xcursor_LIBS Xcursor_CFLAGS Xrender_CFLAGS Xrender_LIBS Xinerama_CFLAGS Xinerama_LIBS FVWM_BUILD_HTMLDOC_FALSE FVWM_BUILD_HTMLDOC_TRUE FVWM_BUILD_MANDOC_FALSE FVWM_BUILD_MANDOC_TRUE XSLTPROC DOC_SECTIONS_XML_PATH DOC_SECTIONS_XML DOC_SECTIONS DOC_MODULES_HTML DOC_MODULES DOC_COMMANDS_HTML DOC_COMMANDS_XML_PATH DOC_COMMANDS_XML DOC_COMMANDS PKG_CONFIG_LIBDIR PKG_CONFIG_PATH PKG_CONFIG host_os host_vendor host_cpu host build_os build_vendor build_cpu build FVWM_IMAGEPATH X_EXTRA_LIBS X_LIBS X_PRE_LIBS X_CFLAGS CPP XMKMF am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC FVWM_DOCDIR FVWM_CONFDIR FVWM_PERLLIBDIR FVWM_DATADIR FVWM_MODULEDIR PERL REQUIRED_PERL_VERSION PYTHON REQUIRED_PYTHON_VERSION SED MANPAGE_PREAMBLE FVWMWORKERSLISTLONG FVWMWORKERSLIST FVWMLIST FVWMALTFTPDIR FVWMALTFTP FVWMFTPDIR FVWMFTP FVWMHOMEPAGE FVWMNAMELONG RELDATENUM RELDATESHORT RELDATELONG VERSIONINFO ISRELEASED AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V CSCOPE ETAGS CTAGS am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL AR_FLAGS am__quote' ac_subst_files='' ac_user_opts=' enable_option_checking enable_silent_rules enable_package_subdirs enable_dmalloc enable_efence enable_command_log enable_debug_msgs with_x enable_dependency_tracking with_imagepath enable_mandoc enable_htmldoc enable_sm enable_shape enable_shm enable_xinerama enable_xinerama_emulation enable_xrender enable_xcursor enable_xft with_fontconfig_prefix with_fontconfig_exec_prefix enable_fontconfigtest with_xft_prefix with_xft_exec_prefix enable_xfttest with_xpm_library with_xpm_includes enable_png enable_rsvg with_rplay_library with_rplay_includes with_stroke_library with_stroke_includes with_termcap_library with_readline_library with_readline_includes with_ncurses_library enable_iconv with_iconv_library with_iconv_includes enable_bidi with_fribidi_bindir enable_perllib enable_nls with_intl_library with_intl_includes with_imlib_prefix with_imlib_exec_prefix enable_imlibtest ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS XMKMF CPP PKG_CONFIG PKG_CONFIG_PATH PKG_CONFIG_LIBDIR png_CFLAGS png_LIBS' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures fvwm 2.7.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/fvwm] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names X features: --x-includes=DIR X include files are in DIR --x-libraries=DIR X library files are in DIR System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of fvwm 2.7.0:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --disable-package-subdirs do not create subdirs for modules and data --enable-dmalloc enable support for the dmalloc debugging library --enable-efence enable support for the efence debugging library --enable-command-log enable command logging --enable-debug-msgs enable debugging messages --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --enable-mandoc enable generation of man pages --enable-htmldoc enable generation of HTML documentation --disable-sm disable session management support --disable-shape disable shaped window support --disable-shm disable MIT Shared Memory Extension --disable-xinerama disable Xinerama multi screen support --enable-xinerama-emulation enable Xinerama emulation on one screen (useful only for developers) --disable-xrender disable Xrender alpha-blend rendering --disable-xcursor disable Xcursor ARGB/animated cursor loading --disable-xft disable Xft anti-aliased font rendering --disable-fontconfigtest do not try to compile and run a test fontconfig program --disable-xfttest do not try to compile and run a test Xft program --disable-png Disables libpng support. --disable-rsvg disable scalable vector graphics (SVG images) --disable-iconv disable support for iconv character conversion --disable-bidi disable bi-directional text support --disable-perllib disable installing fvwm perl library --disable-nls do not use Native Language Support --disable-imlibtest do not try to compile and run a test IMLIB program Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-x use the X Window System --with-imagepath=PATH colon-delimited search path for images --with-fontconfig-prefix=PFX prefix where fontconfig is installed (for Xft2) --with-fontconfig-exec-prefix=PFX exec prefix where fontconfig is installed --with-xft-prefix=PFX prefix where Xft2 is installed (optional) --with-xft-exec-prefix=PFX exec prefix where Xft2 is installed --with-xpm-library=PATH use xpm library (for coloured or shaped icons) --with-xpm-includes=DIR set directory for xpm headers --with-rplay-library=PATH use rplay library (adds audio capability) --with-rplay-includes=DIR set directory for rplay headers --with-stroke-library=PATH use stroke library (mouse strokes recognition) --with-stroke-includes=DIR set directory for stroke headers --with-termcap-library=PATH use termcap library (to accomplish readline) --with-readline-library=PATH use readline library (line editing/history) --with-readline-includes=DIR set directory for readline headers --with-ncurses-library=PATH use ncurses library (to accomplish readline) --with-iconv-library=PATH use iconv library (if not found sys iconv is used) --with-iconv-includes=DIR set directory for iconv headers --with-fribidi-bindir=DIR directory of fribidi-config if not in PATH --with-intl-library=PATH use intl library (for Native Language Support) --with-intl-includes=DIR set directory for intl headers --with-imlib-prefix=PFX prefix for IMLIB files (optional) --with-imlib-exec-prefix=PFX exec prefix for IMLIB files (optional) Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory XMKMF Path to xmkmf, Makefile generator for X Window System CPP C preprocessor PKG_CONFIG path to pkg-config utility PKG_CONFIG_PATH directories to add to pkg-config's search path PKG_CONFIG_LIBDIR path overriding pkg-config's built-in search path png_CFLAGS C compiler flags for png, overriding pkg-config png_LIBS linker flags for png, overriding pkg-config Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for configure.gnu first; this name is used for a wrapper for # Metaconfig's "Configure" on case-insensitive file systems. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF fvwm configure 2.7.0 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext } then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err } then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 printf %s "checking for $2... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. */ #include #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main (void) { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : eval "$3=yes" else $as_nop eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 printf %s "checking for $2... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO" then : eval "$3=yes" else $as_nop eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_run LINENO # ---------------------- # Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that # executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; } then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: program exited with status $ac_status" >&5 printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_compute_int LINENO EXPR VAR INCLUDES # -------------------------------------------- # Tries to find the compile-time value of EXPR in a program that includes # INCLUDES, setting VAR accordingly. Returns whether the value could be # computed ac_fn_c_compute_int () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { static int test_array [1 - 2 * !(($2) >= 0)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_lo=0 ac_mid=0 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_hi=$ac_mid; break else $as_nop as_fn_arith $ac_mid + 1 && ac_lo=$as_val if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext done else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { static int test_array [1 - 2 * !(($2) < 0)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_hi=-1 ac_mid=-1 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { static int test_array [1 - 2 * !(($2) >= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_lo=$ac_mid; break else $as_nop as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext done else $as_nop ac_lo= ac_hi= fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_hi=$ac_mid else $as_nop as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext done case $ac_lo in #(( ?*) eval "$3=\$ac_lo"; ac_retval=0 ;; '') ac_retval=1 ;; esac else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 static long int longval (void) { return $2; } static unsigned long int ulongval (void) { return $2; } #include #include int main (void) { FILE *f = fopen ("conftest.val", "w"); if (! f) return 1; if (($2) < 0) { long int i = longval (); if (i != ($2)) return 1; fprintf (f, "%ld", i); } else { unsigned long int i = ulongval (); if (i != ($2)) return 1; fprintf (f, "%lu", i); } /* Do not output a trailing newline, as this causes \r\n confusion on some platforms. */ return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : echo >>conftest.val; read $3 &5 printf %s "checking for $2... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else $as_nop eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main (void) { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : else $as_nop eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type # ac_fn_c_find_intX_t LINENO BITS VAR # ----------------------------------- # Finds a signed integer type with width BITS, setting cache variable VAR # accordingly. ac_fn_c_find_intX_t () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for int$2_t" >&5 printf %s "checking for int$2_t... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else $as_nop eval "$3=no" # Order is important - never check a type that is potentially smaller # than half of the expected target width. for ac_type in int$2_t 'int' 'long int' \ 'long long int' 'short int' 'signed char'; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default enum { N = $2 / 2 - 1 }; int main (void) { static int test_array [1 - 2 * !(0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1))]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default enum { N = $2 / 2 - 1 }; int main (void) { static int test_array [1 - 2 * !(($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1) < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 2))]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : else $as_nop case $ac_type in #( int$2_t) : eval "$3=yes" ;; #( *) : eval "$3=\$ac_type" ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext if eval test \"x\$"$3"\" = x"no" then : else $as_nop break fi done fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_find_intX_t # ac_fn_c_find_uintX_t LINENO BITS VAR # ------------------------------------ # Finds an unsigned integer type with width BITS, setting cache variable VAR # accordingly. ac_fn_c_find_uintX_t () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for uint$2_t" >&5 printf %s "checking for uint$2_t... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else $as_nop eval "$3=no" # Order is important - never check a type that is potentially smaller # than half of the expected target width. for ac_type in uint$2_t 'unsigned int' 'unsigned long int' \ 'unsigned long long int' 'unsigned short int' 'unsigned char'; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main (void) { static int test_array [1 - 2 * !((($ac_type) -1 >> ($2 / 2 - 1)) >> ($2 / 2 - 1) == 3)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : case $ac_type in #( uint$2_t) : eval "$3=yes" ;; #( *) : eval "$3=\$ac_type" ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext if eval test \"x\$"$3"\" = x"no" then : else $as_nop break fi done fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_find_uintX_t ac_configure_args_raw= for ac_arg do case $ac_arg in *\'*) ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append ac_configure_args_raw " '$ac_arg'" done case $ac_configure_args_raw in *$as_nl*) ac_safe_unquote= ;; *) ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab. ac_unsafe_a="$ac_unsafe_z#~" ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g" ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;; esac cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by fvwm $as_me 2.7.0, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac printf "%s\n" "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Sanitize IFS. IFS=" "" $as_nl" # Save into config.log some information that might help in debugging. { echo printf "%s\n" "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo printf "%s\n" "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then printf "%s\n" "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then printf "%s\n" "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && printf "%s\n" "$as_me: caught signal $ac_signal" printf "%s\n" "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h printf "%s\n" "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. if test -n "$CONFIG_SITE"; then ac_site_files="$CONFIG_SITE" elif test "x$prefix" != xNONE; then ac_site_files="$prefix/share/config.site $prefix/etc/config.site" else ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi for ac_site_file in $ac_site_files do case $ac_site_file in #( */*) : ;; #( *) : ac_site_file=./$ac_site_file ;; esac if test -f "$ac_site_file" && test -r "$ac_site_file"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 printf "%s\n" "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 printf "%s\n" "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Test code for whether the C compiler supports C89 (global declarations) ac_c_conftest_c89_globals=' /* Does the compiler advertise C89 conformance? Do not test the value of __STDC__, because some compilers set it to 0 while being otherwise adequately conformant. */ #if !defined __STDC__ # error "Compiler does not advertise C89 conformance" #endif #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */ struct buf { int x; }; struct buf * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not \xHH hex character constants. These do not provoke an error unfortunately, instead are silently treated as an "x". The following induces an error, until -std is added to get proper ANSI mode. Curiously \x00 != x always comes out true, for an array size at least. It is necessary to write \x00 == 0 to get something that is true only with -std. */ int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) '\''x'\'' int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int), int, int);' # Test code for whether the C compiler supports C89 (body of main). ac_c_conftest_c89_main=' ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]); ' # Test code for whether the C compiler supports C99 (global declarations) ac_c_conftest_c99_globals=' // Does the compiler advertise C99 conformance? #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L # error "Compiler does not advertise C99 conformance" #endif #include extern int puts (const char *); extern int printf (const char *, ...); extern int dprintf (int, const char *, ...); extern void *malloc (size_t); // Check varargs macros. These examples are taken from C99 6.10.3.5. // dprintf is used instead of fprintf to avoid needing to declare // FILE and stderr. #define debug(...) dprintf (2, __VA_ARGS__) #define showlist(...) puts (#__VA_ARGS__) #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) static void test_varargs_macros (void) { int x = 1234; int y = 5678; debug ("Flag"); debug ("X = %d\n", x); showlist (The first, second, and third items.); report (x>y, "x is %d but y is %d", x, y); } // Check long long types. #define BIG64 18446744073709551615ull #define BIG32 4294967295ul #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) #if !BIG_OK #error "your preprocessor is broken" #endif #if BIG_OK #else #error "your preprocessor is broken" #endif static long long int bignum = -9223372036854775807LL; static unsigned long long int ubignum = BIG64; struct incomplete_array { int datasize; double data[]; }; struct named_init { int number; const wchar_t *name; double average; }; typedef const char *ccp; static inline int test_restrict (ccp restrict text) { // See if C++-style comments work. // Iterate through items via the restricted pointer. // Also check for declarations in for loops. for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i) continue; return 0; } // Check varargs and va_copy. static bool test_varargs (const char *format, ...) { va_list args; va_start (args, format); va_list args_copy; va_copy (args_copy, args); const char *str = ""; int number = 0; float fnumber = 0; while (*format) { switch (*format++) { case '\''s'\'': // string str = va_arg (args_copy, const char *); break; case '\''d'\'': // int number = va_arg (args_copy, int); break; case '\''f'\'': // float fnumber = va_arg (args_copy, double); break; default: break; } } va_end (args_copy); va_end (args); return *str && number && fnumber; } ' # Test code for whether the C compiler supports C99 (body of main). ac_c_conftest_c99_main=' // Check bool. _Bool success = false; success |= (argc != 0); // Check restrict. if (test_restrict ("String literal") == 0) success = true; char *restrict newvar = "Another string"; // Check varargs. success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234); test_varargs_macros (); // Check flexible array members. struct incomplete_array *ia = malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); ia->datasize = 10; for (int i = 0; i < ia->datasize; ++i) ia->data[i] = i * 1.234; // Check named initializers. struct named_init ni = { .number = 34, .name = L"Test wide string", .average = 543.34343, }; ni.number = 58; int dynamic_array[ni.number]; dynamic_array[0] = argv[0][0]; dynamic_array[ni.number - 1] = 543; // work around unused variable warnings ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\'' || dynamic_array[ni.number - 1] != 543); ' # Test code for whether the C compiler supports C11 (global declarations) ac_c_conftest_c11_globals=' // Does the compiler advertise C11 conformance? #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L # error "Compiler does not advertise C11 conformance" #endif // Check _Alignas. char _Alignas (double) aligned_as_double; char _Alignas (0) no_special_alignment; extern char aligned_as_int; char _Alignas (0) _Alignas (int) aligned_as_int; // Check _Alignof. enum { int_alignment = _Alignof (int), int_array_alignment = _Alignof (int[100]), char_alignment = _Alignof (char) }; _Static_assert (0 < -_Alignof (int), "_Alignof is signed"); // Check _Noreturn. int _Noreturn does_not_return (void) { for (;;) continue; } // Check _Static_assert. struct test_static_assert { int x; _Static_assert (sizeof (int) <= sizeof (long int), "_Static_assert does not work in struct"); long int y; }; // Check UTF-8 literals. #define u8 syntax error! char const utf8_literal[] = u8"happens to be ASCII" "another string"; // Check duplicate typedefs. typedef long *long_ptr; typedef long int *long_ptr; typedef long_ptr long_ptr; // Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1. struct anonymous { union { struct { int i; int j; }; struct { int k; long int l; } w; }; int m; } v1; ' # Test code for whether the C compiler supports C11 (body of main). ac_c_conftest_c11_main=' _Static_assert ((offsetof (struct anonymous, i) == offsetof (struct anonymous, w.k)), "Anonymous union alignment botch"); v1.i = 2; v1.w.k = 5; ok |= v1.i != 5; ' # Test code for whether the C compiler supports C11 (complete). ac_c_conftest_c11_program="${ac_c_conftest_c89_globals} ${ac_c_conftest_c99_globals} ${ac_c_conftest_c11_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} ${ac_c_conftest_c99_main} ${ac_c_conftest_c11_main} return ok; } " # Test code for whether the C compiler supports C99 (complete). ac_c_conftest_c99_program="${ac_c_conftest_c89_globals} ${ac_c_conftest_c99_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} ${ac_c_conftest_c99_main} return ok; } " # Test code for whether the C compiler supports C89 (complete). ac_c_conftest_c89_program="${ac_c_conftest_c89_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} return ok; } " as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H" as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H" as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H" as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H" as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H" as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H" as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H" as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H" as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H" as_fn_append ac_header_c_list " wchar.h wchar_h HAVE_WCHAR_H" as_fn_append ac_header_c_list " minix/config.h minix_config_h HAVE_MINIX_CONFIG_H" as_fn_append ac_header_c_list " sys/time.h sys_time_h HAVE_SYS_TIME_H" # Auxiliary files required by this configure script. ac_aux_files="config.guess config.sub compile missing install-sh" # Locations in which to look for auxiliary files. ac_aux_dir_candidates="${srcdir}/etc" # Search for a directory containing all of the required auxiliary files, # $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates. # If we don't find one directory that contains all the files we need, # we report the set of missing files from the *first* directory in # $ac_aux_dir_candidates and give up. ac_missing_aux_files="" ac_first_candidate=: printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in $ac_aux_dir_candidates do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac as_found=: printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5 ac_aux_dir_found=yes ac_install_sh= for ac_aux in $ac_aux_files do # As a special case, if "install-sh" is required, that requirement # can be satisfied by any of "install-sh", "install.sh", or "shtool", # and $ac_install_sh is set appropriately for whichever one is found. if test x"$ac_aux" = x"install-sh" then if test -f "${as_dir}install-sh"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5 ac_install_sh="${as_dir}install-sh -c" elif test -f "${as_dir}install.sh"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5 ac_install_sh="${as_dir}install.sh -c" elif test -f "${as_dir}shtool"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5 ac_install_sh="${as_dir}shtool install -c" else ac_aux_dir_found=no if $ac_first_candidate; then ac_missing_aux_files="${ac_missing_aux_files} install-sh" else break fi fi else if test -f "${as_dir}${ac_aux}"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5 else ac_aux_dir_found=no if $ac_first_candidate; then ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}" else break fi fi fi done if test "$ac_aux_dir_found" = yes; then ac_aux_dir="$as_dir" break fi ac_first_candidate=false as_found=false done IFS=$as_save_IFS if $as_found then : else $as_nop as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. if test -f "${ac_aux_dir}config.guess"; then ac_config_guess="$SHELL ${ac_aux_dir}config.guess" fi if test -f "${ac_aux_dir}config.sub"; then ac_config_sub="$SHELL ${ac_aux_dir}config.sub" fi if test -f "$ac_aux_dir/configure"; then ac_configure="$SHELL ${ac_aux_dir}configure" fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu am__api_version='1.16' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 printf %s "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if test ${ac_cv_path_install+y} then : printf %s "(cached) " >&6 else $as_nop as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac # Account for fact that we put trailing slashes in our PATH walk. case $as_dir in #(( ./ | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir/" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test ${ac_cv_path_install+y}; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 printf "%s\n" "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 printf %s "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`printf "%s\n" "$program_transform_name" | sed "$ac_script"` # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` if test x"${MISSING+set}" != xset; then MISSING="\${SHELL} '$am_aux_dir/missing'" fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 printf "%s\n" "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_STRIP+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 printf "%s\n" "$STRIP" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_STRIP+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 printf "%s\n" "$ac_ct_STRIP" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for a race-free mkdir -p" >&5 printf %s "checking for a race-free mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if test ${ac_cv_path_mkdir+y} then : printf %s "(cached) " >&6 else $as_nop as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir$ac_prog$ac_exec_ext" || continue case `"$as_dir$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir ('*'coreutils) '* | \ 'BusyBox '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test ${ac_cv_path_mkdir+y}; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 printf "%s\n" "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_AWK+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 printf "%s\n" "$AWK" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$AWK" && break done { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 printf %s "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`printf "%s\n" "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval test \${ac_cv_prog_make_${ac_make}_set+y} then : printf %s "(cached) " >&6 else $as_nop cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } SET_MAKE= else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null # Check whether --enable-silent-rules was given. if test ${enable_silent_rules+y} then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 printf %s "checking whether $am_make supports nested variables... " >&6; } if test ${am_cv_make_support_nested_variables+y} then : printf %s "(cached) " >&6 else $as_nop if printf "%s\n" 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 printf "%s\n" "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='fvwm' VERSION='2.7.0' printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h printf "%s\n" "#define VERSION \"$VERSION\"" >>confdefs.h # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar pax cpio none' am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' # Variables for tags utilities; see am/tags.am if test -z "$CTAGS"; then CTAGS=ctags fi if test -z "$ETAGS"; then ETAGS=etags fi if test -z "$CSCOPE"; then CSCOPE=cscope fi # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 fi fi # Check whether --enable-silent-rules was given. if test ${enable_silent_rules+y} then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=0;; esac am_make=${MAKE-make} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 printf %s "checking whether $am_make supports nested variables... " >&6; } if test ${am_cv_make_support_nested_variables+y} then : printf %s "(cached) " >&6 else $as_nop if printf "%s\n" 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 printf "%s\n" "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' ac_config_headers="$ac_config_headers config.h" VERSIONINFO="" RELDATELONG="19 October 2022" RELDATESHORT="19-Oct-2022" RELDATENUM="2022-10-19" # constant variable settings FVWMNAMELONG="F? Virtual Window Manager" FVWMHOMEPAGE="http://fvwm.org/" FVWMFTP="ftp.fvwm.org" FVWMFTPDIR="/pub/ftp" FVWMALTFTP="metalab.unc.edu" FVWMALTFTPDIR="/pub/Linux/X11/window-managers/" FVWMLIST="fvwm@fvwm.org" FVWMWORKERSLIST="fvwm-workers@fvwm.org" FVWMWORKERSLISTLONG="fvwm workers list " MANPAGE_PREAMBLE='.\" WARNING: This file was automatically generated. Edit the .in file instead.' printf "%s\n" "#define VERSIONINFO \"$VERSIONINFO\"" >>confdefs.h # check for programs needed to build html docs # Extract the first word of "sed", so it can be a program name with args. set dummy sed; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_SED+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$SED"; then ac_cv_prog_SED="$SED" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_SED="sed" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_SED" && ac_cv_prog_SED="""" fi fi SED=$ac_cv_prog_SED if test -n "$SED"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $SED" >&5 printf "%s\n" "$SED" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # optional python: PYTHON= REQUIRED_PYTHON_VERSION=3.0 # Extract the first word of "python3", so it can be a program name with args. set dummy python3; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_PYTHON+y} then : printf %s "(cached) " >&6 else $as_nop case $PYTHON in [\\/]* | ?:[\\/]*) ac_cv_path_PYTHON="$PYTHON" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_PYTHON="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_PYTHON" && ac_cv_path_PYTHON=":" ;; esac fi PYTHON=$ac_cv_path_PYTHON if test -n "$PYTHON"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PYTHON" >&5 printf "%s\n" "$PYTHON" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "$PYTHON" != ":" then : prog="import sys # split strings by '.' and convert to numeric. Append some zeros # because we need at least 4 digits for the hex conversion. # map returns an iterator in Python 3.0 and a list in 2.x minver = list(map(int, '$REQUIRED_PYTHON_VERSION'.split('.'))) + [0, 0, 0] minverhex = 0 # xrange is not present in Python 3.0 and range returns an iterator for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[i] sys.exit(sys.hexversion < minverhex)" if { echo "$as_me:$LINENO: $PYTHON -c "$prog"" >&5 ($PYTHON -c "$prog") >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } then : : else $as_nop PYTHON=":" fi fi #!!! PERL="" REQUIRED_PERL_VERSION=5.004 if test x"$PERL" = x; then # Extract the first word of "perl", so it can be a program name with args. set dummy perl; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_PERL+y} then : printf %s "(cached) " >&6 else $as_nop case $PERL in [\\/]* | ?:[\\/]*) ac_cv_path_PERL="$PERL" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_PERL="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PERL=$ac_cv_path_PERL if test -n "$PERL"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 printf "%s\n" "$PERL" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test ! x"$PERL" = x; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for perl $REQUIRED_PERL_VERSION or better" >&5 printf %s "checking for perl $REQUIRED_PERL_VERSION or better... " >&6; } HAVE_PERL_FOR_DOCS=1 if ("$PERL" -e "require $REQUIRED_PERL_VERSION;") 2>/dev/null; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $PERL not found or too old" >&5 printf "%s\n" "$as_me: WARNING: $PERL not found or too old" >&2;} fi else HAVE_PERL_FOR_DOCS=0 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: perl is not found, it is required for some scripts and modules" >&5 printf "%s\n" "$as_me: WARNING: perl is not found, it is required for some scripts and modules" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: It is recommended to install perl $REQUIRED_PERL_VERSION or better later" >&5 printf "%s\n" "$as_me: WARNING: It is recommended to install perl $REQUIRED_PERL_VERSION or better later" >&2;} PERL=/usr/bin/perl fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: assuming $PERL as perl location" >&5 printf "%s\n" "assuming $PERL as perl location" >&6; } # installation paths transform=`echo "${program_transform_name}" | "$SED" -e 's/\\$\\$/\\$/'` PPACKAGE=`echo "${PACKAGE}" | "$SED" -e "${transform}"` FVWM_MODULESUBDIR=/${PPACKAGE}/${VERSION} FVWM_DATASUBDIR=/${PPACKAGE} FVWM_DOCSUBDIR=/doc/${PPACKAGE} # Check whether --enable-package-subdirs was given. if test ${enable_package_subdirs+y} then : enableval=$enable_package_subdirs; if test x"$enableval" = xno; then FVWM_MODULESUBDIR=""; FVWM_DATASUBDIR=""; fi fi FVWM_MODULEDIR='${libexecdir}'"$FVWM_MODULESUBDIR" FVWM_DATADIR='${datadir}'"$FVWM_DATASUBDIR" FVWM_DOCDIR='${datadir}'"$FVWM_DOCSUBDIR" FVWM_PERLLIBDIR='${datadir}'"$FVWM_DATASUBDIR/perllib" FVWM_CONFDIR='${sysconfdir}' printf "%s\n" "#define FVWM_CONFIG \"config\"" >>confdefs.h printf "%s\n" "#define FVWM2RC \".fvwm2rc\"" >>confdefs.h # Various configure-time options # Check whether --enable-dmalloc was given. if test ${enable_dmalloc+y} then : enableval=$enable_dmalloc; ac_cv_dmalloc="$enableval" else $as_nop ac_cv_dmalloc="no" fi # Check whether --enable-efence was given. if test ${enable_efence+y} then : enableval=$enable_efence; ac_cv_efence="$enableval" else $as_nop ac_cv_efence="no" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable command logging" >&5 printf %s "checking whether to enable command logging... " >&6; } # Check whether --enable-command-log was given. if test ${enable_command_log+y} then : enableval=$enable_command_log; if test "$enableval" = yes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define FVWM_COMMAND_LOG 1" >>confdefs.h else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable debugging messages" >&5 printf %s "checking whether to enable debugging messages... " >&6; } # Check whether --enable-debug-msgs was given. if test ${enable_debug_msgs+y} then : enableval=$enable_debug_msgs; if test "$enableval" = yes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define FVWM_DEBUG_MSGS 1" >>confdefs.h else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Need to know where X is, for finding some libraries (e.g. xpm) no_x="" DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5 printf %s "checking whether ${MAKE-make} supports the include directive... " >&6; } cat > confinc.mk << 'END' am__doit: @echo this is the am__doit target >confinc.out .PHONY: am__doit END am__include="#" am__quote= # BSD make does it like this. echo '.include "confinc.mk" # ignored' > confmf.BSD # Other make implementations (GNU, Solaris 10, AIX) do it like this. echo 'include confinc.mk # ignored' > confmf.GNU _am_result=no for s in GNU BSD; do { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5 (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } case $?:`cat confinc.out 2>/dev/null` in #( '0:this is the am__doit target') : case $s in #( BSD) : am__include='.include' am__quote='"' ;; #( *) : am__include='include' am__quote='' ;; esac ;; #( *) : ;; esac if test "$am__include" != "#"; then _am_result="yes ($s style)" break fi done rm -f confinc.* confmf.* { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5 printf "%s\n" "${_am_result}" >&6; } # Check whether --enable-dependency-tracking was given. if test ${enable_dependency_tracking+y} then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args. set dummy ${ac_tool_prefix}clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "clang", so it can be a program name with args. set dummy clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi fi test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion -version; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 printf %s "checking whether the C compiler works... " >&6; } ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else $as_nop ac_file='' fi if test -z "$ac_file" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 printf %s "checking for C compiler default output file name... " >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 printf "%s\n" "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 printf %s "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else $as_nop { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 printf "%s\n" "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 printf %s "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 printf "%s\n" "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 printf %s "checking for suffix of object files... " >&6; } if test ${ac_cv_objext+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 printf "%s\n" "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5 printf %s "checking whether the compiler supports GNU C... " >&6; } if test ${ac_cv_c_compiler_gnu+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_compiler_gnu=yes else $as_nop ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; } ac_compiler_gnu=$ac_cv_c_compiler_gnu if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+y} ac_save_CFLAGS=$CFLAGS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 printf %s "checking whether $CC accepts -g... " >&6; } if test ${ac_cv_prog_cc_g+y} then : printf %s "(cached) " >&6 else $as_nop ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes else $as_nop CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : else $as_nop ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 printf "%s\n" "$ac_cv_prog_cc_g" >&6; } if test $ac_test_CFLAGS; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi ac_prog_cc_stdc=no if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5 printf %s "checking for $CC option to enable C11 features... " >&6; } if test ${ac_cv_prog_cc_c11+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c11=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c11_program _ACEOF for ac_arg in '' -std=gnu11 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c11=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c11" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c11" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c11" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5 printf "%s\n" "$ac_cv_prog_cc_c11" >&6; } CC="$CC $ac_cv_prog_cc_c11" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11 ac_prog_cc_stdc=c11 fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5 printf %s "checking for $CC option to enable C99 features... " >&6; } if test ${ac_cv_prog_cc_c99+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c99=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c99_program _ACEOF for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99= do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c99=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c99" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c99" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c99" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 printf "%s\n" "$ac_cv_prog_cc_c99" >&6; } CC="$CC $ac_cv_prog_cc_c99" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 ac_prog_cc_stdc=c99 fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5 printf %s "checking for $CC option to enable C89 features... " >&6; } if test ${ac_cv_prog_cc_c89+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c89_program _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c89" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c89" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 printf "%s\n" "$ac_cv_prog_cc_c89" >&6; } CC="$CC $ac_cv_prog_cc_c89" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 ac_prog_cc_stdc=c89 fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 printf %s "checking whether $CC understands -c and -o together... " >&6; } if test ${am_cv_prog_cc_c_o+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 printf "%s\n" "$am_cv_prog_cc_c_o" >&6; } if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 printf %s "checking dependency style of $depcc... " >&6; } if test ${am_cv_CC_dependencies_compiler_type+y} then : printf %s "(cached) " >&6 else $as_nop if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 printf "%s\n" "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 printf %s "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test ${ac_cv_prog_CPP+y} then : printf %s "(cached) " >&6 else $as_nop # Double quotes because $CC needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" cpp /lib/cpp do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO" then : else $as_nop # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO" then : # Broken: success on invalid input. continue else $as_nop # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 printf "%s\n" "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO" then : else $as_nop # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO" then : # Broken: success on invalid input. continue else $as_nop # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok then : else $as_nop { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for X" >&5 printf %s "checking for X... " >&6; } # Check whether --with-x was given. if test ${with_x+y} then : withval=$with_x; fi # $have_x is `yes', `no', `disabled', or empty when we do not yet know. if test "x$with_x" = xno; then # The user explicitly disabled X. have_x=disabled else case $x_includes,$x_libraries in #( *\'*) as_fn_error $? "cannot use X directory names containing '" "$LINENO" 5;; #( *,NONE | NONE,*) if test ${ac_cv_have_x+y} then : printf %s "(cached) " >&6 else $as_nop # One or both of the vars are not set, and there is no cached value. ac_x_includes=no ac_x_libraries=no # Do we need to do anything special at all? ac_save_LIBS=$LIBS LIBS="-lX11 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { XrmInitialize () ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : # We can compile and link X programs with no special options. ac_x_includes= ac_x_libraries= fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS="$ac_save_LIBS" # If that didn't work, only try xmkmf and file system searches # for native compilation. if test x"$ac_x_includes" = xno && test "$cross_compiling" = no then : rm -f -r conftest.dir if mkdir conftest.dir; then cd conftest.dir cat >Imakefile <<'_ACEOF' incroot: @echo incroot='${INCROOT}' usrlibdir: @echo usrlibdir='${USRLIBDIR}' libdir: @echo libdir='${LIBDIR}' _ACEOF if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. for ac_var in incroot usrlibdir libdir; do eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`" done # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. for ac_extension in a so sl dylib la dll; do if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" && test -f "$ac_im_libdir/libX11.$ac_extension"; then ac_im_usrlibdir=$ac_im_libdir; break fi done # Screen out bogus values from the imake configuration. They are # bogus both because they are the default anyway, and because # using them would break gcc on systems where it needs fixed includes. case $ac_im_incroot in /usr/include) ac_x_includes= ;; *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;; esac case $ac_im_usrlibdir in /usr/lib | /usr/lib64 | /lib | /lib64) ;; *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;; esac fi cd .. rm -f -r conftest.dir fi # Standard set of common directories for X headers. # Check X11 before X11Rn because it is often a symlink to the current release. ac_x_header_dirs=' /usr/X11/include /usr/X11R7/include /usr/X11R6/include /usr/X11R5/include /usr/X11R4/include /usr/include/X11 /usr/include/X11R7 /usr/include/X11R6 /usr/include/X11R5 /usr/include/X11R4 /usr/local/X11/include /usr/local/X11R7/include /usr/local/X11R6/include /usr/local/X11R5/include /usr/local/X11R4/include /usr/local/include/X11 /usr/local/include/X11R7 /usr/local/include/X11R6 /usr/local/include/X11R5 /usr/local/include/X11R4 /opt/X11/include /usr/X386/include /usr/x386/include /usr/XFree86/include/X11 /usr/include /usr/local/include /usr/unsupported/include /usr/athena/include /usr/local/x11r5/include /usr/lpp/Xamples/include /usr/openwin/include /usr/openwin/share/include' if test "$ac_x_includes" = no; then # Guess where to find include files, by looking for Xlib.h. # First, try using that file with no special directory specified. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO" then : # We can compile using X headers with no special include directory. ac_x_includes= else $as_nop for ac_dir in $ac_x_header_dirs; do if test -r "$ac_dir/X11/Xlib.h"; then ac_x_includes=$ac_dir break fi done fi rm -f conftest.err conftest.i conftest.$ac_ext fi # $ac_x_includes = no if test "$ac_x_libraries" = no; then # Check for the libraries. # See if we find them without any special options. # Don't add to $LIBS permanently. ac_save_LIBS=$LIBS LIBS="-lX11 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { XrmInitialize () ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : LIBS=$ac_save_LIBS # We can link X programs with no special library path. ac_x_libraries= else $as_nop LIBS=$ac_save_LIBS for ac_dir in `printf "%s\n" "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g` do # Don't even attempt the hair of trying to link an X program! for ac_extension in a so sl dylib la dll; do if test -r "$ac_dir/libX11.$ac_extension"; then ac_x_libraries=$ac_dir break 2 fi done done fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi # $ac_x_libraries = no fi # Record the results. case $ac_x_includes,$ac_x_libraries in #( no,* | *,no | *\'*) : # Didn't find X, or a directory has "'" in its name. ac_cv_have_x="have_x=no" ;; #( *) : # Record where we found X for the cache. ac_cv_have_x="have_x=yes\ ac_x_includes='$ac_x_includes'\ ac_x_libraries='$ac_x_libraries'" ;; esac fi ;; #( *) have_x=yes;; esac eval "$ac_cv_have_x" fi # $with_x != no if test "$have_x" != yes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_x" >&5 printf "%s\n" "$have_x" >&6; } no_x=yes else # If each of the values was on the command line, it overrides each guess. test "x$x_includes" = xNONE && x_includes=$ac_x_includes test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries # Update the cache value to reflect the command line values. ac_cv_have_x="have_x=yes\ ac_x_includes='$x_includes'\ ac_x_libraries='$x_libraries'" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: libraries $x_libraries, headers $x_includes" >&5 printf "%s\n" "libraries $x_libraries, headers $x_includes" >&6; } fi if test "$no_x" = yes; then # Not all programs may use this symbol, but it does not hurt to define it. printf "%s\n" "#define X_DISPLAY_MISSING 1" >>confdefs.h X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS= else if test -n "$x_includes"; then X_CFLAGS="$X_CFLAGS -I$x_includes" fi # It would also be nice to do this for all -L options, not just this one. if test -n "$x_libraries"; then X_LIBS="$X_LIBS -L$x_libraries" # For Solaris; some versions of Sun CC require a space after -R and # others require no space. Words are not sufficient . . . . { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether -R must be followed by a space" >&5 printf %s "checking whether -R must be followed by a space... " >&6; } ac_xsave_LIBS=$LIBS; LIBS="$LIBS -R$x_libraries" ac_xsave_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } X_LIBS="$X_LIBS -R$x_libraries" else $as_nop LIBS="$ac_xsave_LIBS -R $x_libraries" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } X_LIBS="$X_LIBS -R $x_libraries" else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: neither works" >&5 printf "%s\n" "neither works" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext ac_c_werror_flag=$ac_xsave_c_werror_flag LIBS=$ac_xsave_LIBS fi # Check for system-dependent libraries X programs must link with. # Do this before checking for the system-independent R6 libraries # (-lICE), since we may need -lsocket or whatever for X linking. if test "$ISC" = yes; then X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet" else # Martyn Johnson says this is needed for Ultrix, if the X # libraries were built with DECnet support. And Karl Berry says # the Alpha needs dnet_stub (dnet does not exist). ac_xsave_LIBS="$LIBS"; LIBS="$LIBS $X_LIBS -lX11" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char XOpenDisplay (); int main (void) { return XOpenDisplay (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet" >&5 printf %s "checking for dnet_ntoa in -ldnet... " >&6; } if test ${ac_cv_lib_dnet_dnet_ntoa+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-ldnet $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char dnet_ntoa (); int main (void) { return dnet_ntoa (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_dnet_dnet_ntoa=yes else $as_nop ac_cv_lib_dnet_dnet_ntoa=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_dnet_ntoa" >&5 printf "%s\n" "$ac_cv_lib_dnet_dnet_ntoa" >&6; } if test "x$ac_cv_lib_dnet_dnet_ntoa" = xyes then : X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet" fi if test $ac_cv_lib_dnet_dnet_ntoa = no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet_stub" >&5 printf %s "checking for dnet_ntoa in -ldnet_stub... " >&6; } if test ${ac_cv_lib_dnet_stub_dnet_ntoa+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-ldnet_stub $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char dnet_ntoa (); int main (void) { return dnet_ntoa (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_dnet_stub_dnet_ntoa=yes else $as_nop ac_cv_lib_dnet_stub_dnet_ntoa=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_stub_dnet_ntoa" >&5 printf "%s\n" "$ac_cv_lib_dnet_stub_dnet_ntoa" >&6; } if test "x$ac_cv_lib_dnet_stub_dnet_ntoa" = xyes then : X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub" fi fi fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS="$ac_xsave_LIBS" # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT, # to get the SysV transport functions. # Chad R. Larson says the Pyramis MIS-ES running DC/OSx (SVR4) # needs -lnsl. # The nsl library prevents programs from opening the X display # on Irix 5.2, according to T.E. Dickey. # The functions gethostbyname, getservbyname, and inet_addr are # in -lbsd on LynxOS 3.0.1/i386, according to Lars Hecking. ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname" if test "x$ac_cv_func_gethostbyname" = xyes then : fi if test $ac_cv_func_gethostbyname = no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5 printf %s "checking for gethostbyname in -lnsl... " >&6; } if test ${ac_cv_lib_nsl_gethostbyname+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lnsl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char gethostbyname (); int main (void) { return gethostbyname (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_nsl_gethostbyname=yes else $as_nop ac_cv_lib_nsl_gethostbyname=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5 printf "%s\n" "$ac_cv_lib_nsl_gethostbyname" >&6; } if test "x$ac_cv_lib_nsl_gethostbyname" = xyes then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl" fi if test $ac_cv_lib_nsl_gethostbyname = no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lbsd" >&5 printf %s "checking for gethostbyname in -lbsd... " >&6; } if test ${ac_cv_lib_bsd_gethostbyname+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lbsd $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char gethostbyname (); int main (void) { return gethostbyname (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_bsd_gethostbyname=yes else $as_nop ac_cv_lib_bsd_gethostbyname=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_gethostbyname" >&5 printf "%s\n" "$ac_cv_lib_bsd_gethostbyname" >&6; } if test "x$ac_cv_lib_bsd_gethostbyname" = xyes then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd" fi fi fi # lieder@skyler.mavd.honeywell.com says without -lsocket, # socket/setsockopt and other routines are undefined under SCO ODT # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary # on later versions), says Simon Leinen: it contains gethostby* # variants that don't use the name server (or something). -lsocket # must be given before -lnsl if both are needed. We assume that # if connect needs -lnsl, so does gethostbyname. ac_fn_c_check_func "$LINENO" "connect" "ac_cv_func_connect" if test "x$ac_cv_func_connect" = xyes then : fi if test $ac_cv_func_connect = no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for connect in -lsocket" >&5 printf %s "checking for connect in -lsocket... " >&6; } if test ${ac_cv_lib_socket_connect+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $X_EXTRA_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char connect (); int main (void) { return connect (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_socket_connect=yes else $as_nop ac_cv_lib_socket_connect=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_connect" >&5 printf "%s\n" "$ac_cv_lib_socket_connect" >&6; } if test "x$ac_cv_lib_socket_connect" = xyes then : X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS" fi fi # Guillermo Gomez says -lposix is necessary on A/UX. ac_fn_c_check_func "$LINENO" "remove" "ac_cv_func_remove" if test "x$ac_cv_func_remove" = xyes then : fi if test $ac_cv_func_remove = no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for remove in -lposix" >&5 printf %s "checking for remove in -lposix... " >&6; } if test ${ac_cv_lib_posix_remove+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lposix $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char remove (); int main (void) { return remove (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_posix_remove=yes else $as_nop ac_cv_lib_posix_remove=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_posix_remove" >&5 printf "%s\n" "$ac_cv_lib_posix_remove" >&6; } if test "x$ac_cv_lib_posix_remove" = xyes then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix" fi fi # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. ac_fn_c_check_func "$LINENO" "shmat" "ac_cv_func_shmat" if test "x$ac_cv_func_shmat" = xyes then : fi if test $ac_cv_func_shmat = no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for shmat in -lipc" >&5 printf %s "checking for shmat in -lipc... " >&6; } if test ${ac_cv_lib_ipc_shmat+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lipc $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char shmat (); int main (void) { return shmat (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_ipc_shmat=yes else $as_nop ac_cv_lib_ipc_shmat=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ipc_shmat" >&5 printf "%s\n" "$ac_cv_lib_ipc_shmat" >&6; } if test "x$ac_cv_lib_ipc_shmat" = xyes then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc" fi fi fi # Check for libraries that X11R6 Xt/Xaw programs need. ac_save_LDFLAGS=$LDFLAGS test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries" # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to # check for ICE first), but we must link in the order -lSM -lICE or # we get undefined symbols. So assume we have SM if we have ICE. # These have to be linked with before -lX11, unlike the other # libraries we check for below, so use a different variable. # John Interrante, Karl Berry { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for IceConnectionNumber in -lICE" >&5 printf %s "checking for IceConnectionNumber in -lICE... " >&6; } if test ${ac_cv_lib_ICE_IceConnectionNumber+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lICE $X_EXTRA_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char IceConnectionNumber (); int main (void) { return IceConnectionNumber (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_ICE_IceConnectionNumber=yes else $as_nop ac_cv_lib_ICE_IceConnectionNumber=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ICE_IceConnectionNumber" >&5 printf "%s\n" "$ac_cv_lib_ICE_IceConnectionNumber" >&6; } if test "x$ac_cv_lib_ICE_IceConnectionNumber" = xyes then : X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE" fi LDFLAGS=$ac_save_LDFLAGS fi if test x"$no_x" = x"yes"; then echo echo "X11 libraries or header files could not be found. Please make" echo "sure the X11 development package is installed on your system." echo "If it is definitely installed, try setting the include and library" echo "paths with the --x-include and --x-libraries options of configure." echo "Fvwm can not be compiled without the X11 development environment." echo echo "Aborting." echo exit 1 fi # FIXME: default value should be derived from computed path to X # includes. Actually, this should probably not appear in configure # at all: it is settable at runtime, and only confuses the issue to # have it settable here too. # { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking imagepath" >&5 printf %s "checking imagepath... " >&6; } val="/usr/include/X11/bitmaps:/usr/include/X11/pixmaps" # Check whether --with-imagepath was given. if test ${with_imagepath+y} then : withval=$with_imagepath; case "$withval" in no) as_fn_error $? "Can not disable image path." "$LINENO" 5 ;; yes) ;; *) val="$withval" ;; esac fi printf "%s\n" "#define FVWM_IMAGEPATH \"$val\"" >>confdefs.h FVWM_IMAGEPATH="$val" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $val" >&5 printf "%s\n" "$val" >&6; } # Minimal checks for programs: enough to enable checking for # optional libraries. ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args. set dummy ${ac_tool_prefix}clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "clang", so it can be a program name with args. set dummy clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi fi test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion -version; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5 printf %s "checking whether the compiler supports GNU C... " >&6; } if test ${ac_cv_c_compiler_gnu+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_compiler_gnu=yes else $as_nop ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; } ac_compiler_gnu=$ac_cv_c_compiler_gnu if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+y} ac_save_CFLAGS=$CFLAGS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 printf %s "checking whether $CC accepts -g... " >&6; } if test ${ac_cv_prog_cc_g+y} then : printf %s "(cached) " >&6 else $as_nop ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes else $as_nop CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : else $as_nop ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 printf "%s\n" "$ac_cv_prog_cc_g" >&6; } if test $ac_test_CFLAGS; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi ac_prog_cc_stdc=no if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5 printf %s "checking for $CC option to enable C11 features... " >&6; } if test ${ac_cv_prog_cc_c11+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c11=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c11_program _ACEOF for ac_arg in '' -std=gnu11 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c11=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c11" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c11" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c11" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5 printf "%s\n" "$ac_cv_prog_cc_c11" >&6; } CC="$CC $ac_cv_prog_cc_c11" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11 ac_prog_cc_stdc=c11 fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5 printf %s "checking for $CC option to enable C99 features... " >&6; } if test ${ac_cv_prog_cc_c99+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c99=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c99_program _ACEOF for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99= do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c99=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c99" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c99" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c99" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 printf "%s\n" "$ac_cv_prog_cc_c99" >&6; } CC="$CC $ac_cv_prog_cc_c99" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 ac_prog_cc_stdc=c99 fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5 printf %s "checking for $CC option to enable C89 features... " >&6; } if test ${ac_cv_prog_cc_c89+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c89_program _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c89" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c89" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 printf "%s\n" "$ac_cv_prog_cc_c89" >&6; } CC="$CC $ac_cv_prog_cc_c89" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 ac_prog_cc_stdc=c89 fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 printf %s "checking whether $CC understands -c and -o together... " >&6; } if test ${am_cv_prog_cc_c_o+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 printf "%s\n" "$am_cv_prog_cc_c_o" >&6; } if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 printf %s "checking dependency style of $depcc... " >&6; } if test ${am_cv_CC_dependencies_compiler_type+y} then : printf %s "(cached) " >&6 else $as_nop if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 printf "%s\n" "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 printf %s "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test ${ac_cv_prog_CPP+y} then : printf %s "(cached) " >&6 else $as_nop # Double quotes because $CC needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" cpp /lib/cpp do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO" then : else $as_nop # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO" then : # Broken: success on invalid input. continue else $as_nop # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 printf "%s\n" "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO" then : else $as_nop # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO" then : # Broken: success on invalid input. continue else $as_nop # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok then : else $as_nop { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # added -Wall for gcc, what about for others? if test "x$GCC" = "xyes"; then CFLAGS="-Wall -Wno-implicit-int $CFLAGS" fi # Help finding POSIX functions on some systems { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for library containing strerror" >&5 printf %s "checking for library containing strerror... " >&6; } if test ${ac_cv_search_strerror+y} then : printf %s "(cached) " >&6 else $as_nop ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char strerror (); int main (void) { return strerror (); ; return 0; } _ACEOF for ac_lib in '' cposix do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO" then : ac_cv_search_strerror=$ac_res fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext if test ${ac_cv_search_strerror+y} then : break fi done if test ${ac_cv_search_strerror+y} then : else $as_nop ac_cv_search_strerror=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_strerror" >&5 printf "%s\n" "$ac_cv_search_strerror" >&6; } ac_res=$ac_cv_search_strerror if test "$ac_res" != no then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi ac_header= ac_cache= for ac_item in $ac_header_c_list do if test $ac_cache; then ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default" if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then printf "%s\n" "#define $ac_item 1" >> confdefs.h fi ac_header= ac_cache= elif test $ac_header; then ac_cache=$ac_item else ac_header=$ac_item fi done if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes then : printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5 printf %s "checking whether it is safe to define __EXTENSIONS__... " >&6; } if test ${ac_cv_safe_to_define___extensions__+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ # define __EXTENSIONS__ 1 $ac_includes_default int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_safe_to_define___extensions__=yes else $as_nop ac_cv_safe_to_define___extensions__=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5 printf "%s\n" "$ac_cv_safe_to_define___extensions__" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether _XOPEN_SOURCE should be defined" >&5 printf %s "checking whether _XOPEN_SOURCE should be defined... " >&6; } if test ${ac_cv_should_define__xopen_source+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_should_define__xopen_source=no if test $ac_cv_header_wchar_h = yes then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include mbstate_t x; int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _XOPEN_SOURCE 500 #include mbstate_t x; int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_should_define__xopen_source=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_should_define__xopen_source" >&5 printf "%s\n" "$ac_cv_should_define__xopen_source" >&6; } printf "%s\n" "#define _ALL_SOURCE 1" >>confdefs.h printf "%s\n" "#define _DARWIN_C_SOURCE 1" >>confdefs.h printf "%s\n" "#define _GNU_SOURCE 1" >>confdefs.h printf "%s\n" "#define _HPUX_ALT_XOPEN_SOCKET_API 1" >>confdefs.h printf "%s\n" "#define _NETBSD_SOURCE 1" >>confdefs.h printf "%s\n" "#define _OPENBSD_SOURCE 1" >>confdefs.h printf "%s\n" "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h printf "%s\n" "#define __STDC_WANT_IEC_60559_ATTRIBS_EXT__ 1" >>confdefs.h printf "%s\n" "#define __STDC_WANT_IEC_60559_BFP_EXT__ 1" >>confdefs.h printf "%s\n" "#define __STDC_WANT_IEC_60559_DFP_EXT__ 1" >>confdefs.h printf "%s\n" "#define __STDC_WANT_IEC_60559_FUNCS_EXT__ 1" >>confdefs.h printf "%s\n" "#define __STDC_WANT_IEC_60559_TYPES_EXT__ 1" >>confdefs.h printf "%s\n" "#define __STDC_WANT_LIB_EXT2__ 1" >>confdefs.h printf "%s\n" "#define __STDC_WANT_MATH_SPEC_FUNCS__ 1" >>confdefs.h printf "%s\n" "#define _TANDEM_SOURCE 1" >>confdefs.h if test $ac_cv_header_minix_config_h = yes then : MINIX=yes printf "%s\n" "#define _MINIX 1" >>confdefs.h printf "%s\n" "#define _POSIX_SOURCE 1" >>confdefs.h printf "%s\n" "#define _POSIX_1_SOURCE 2" >>confdefs.h else $as_nop MINIX= fi if test $ac_cv_safe_to_define___extensions__ = yes then : printf "%s\n" "#define __EXTENSIONS__ 1" >>confdefs.h fi if test $ac_cv_should_define__xopen_source = yes then : printf "%s\n" "#define _XOPEN_SOURCE 500" >>confdefs.h fi # catch -Werror and similar options when running configure cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { int i; static j; int *p; char *c; switch (*p = p = *c) { case 0: printf("%Q", c, p); } *c = &i; c = p; while (1 || (unsigned int)3 >= 0 || ((int)-1) == ((unsigned int)1)); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : else $as_nop as_fn_error $? "\" configure is not able to compile programs with warnings. Please remove all offending options like -Werror from the CFLAGS and CPPFLAGS variables and run configure again.\"" "$LINENO" 5 fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext # check size of some types ac_save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $X_CFLAGS" # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of int" >&5 printf %s "checking size of int... " >&6; } if test ${ac_cv_sizeof_int+y} then : printf %s "(cached) " >&6 else $as_nop if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$ac_includes_default" then : else $as_nop if test "$ac_cv_type_int" = yes; then { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (int) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_int=0 fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5 printf "%s\n" "$ac_cv_sizeof_int" >&6; } printf "%s\n" "#define SIZEOF_INT $ac_cv_sizeof_int" >>confdefs.h # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of long" >&5 printf %s "checking size of long... " >&6; } if test ${ac_cv_sizeof_long+y} then : printf %s "(cached) " >&6 else $as_nop if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$ac_includes_default" then : else $as_nop if test "$ac_cv_type_long" = yes; then { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (long) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_long=0 fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5 printf "%s\n" "$ac_cv_sizeof_long" >&6; } printf "%s\n" "#define SIZEOF_LONG $ac_cv_sizeof_long" >>confdefs.h # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of Window" >&5 printf %s "checking size of Window... " >&6; } if test ${ac_cv_sizeof_Window+y} then : printf %s "(cached) " >&6 else $as_nop if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (Window))" "ac_cv_sizeof_Window" "#include #include " then : else $as_nop if test "$ac_cv_type_Window" = yes; then { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (Window) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_Window=0 fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_Window" >&5 printf "%s\n" "$ac_cv_sizeof_Window" >&6; } printf "%s\n" "#define SIZEOF_WINDOW $ac_cv_sizeof_Window" >>confdefs.h # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of Pixel" >&5 printf %s "checking size of Pixel... " >&6; } if test ${ac_cv_sizeof_Pixel+y} then : printf %s "(cached) " >&6 else $as_nop if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (Pixel))" "ac_cv_sizeof_Pixel" "#include #include " then : else $as_nop if test "$ac_cv_type_Pixel" = yes; then { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (Pixel) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_Pixel=0 fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_Pixel" >&5 printf "%s\n" "$ac_cv_sizeof_Pixel" >&6; } printf "%s\n" "#define SIZEOF_PIXEL $ac_cv_sizeof_Pixel" >>confdefs.h # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of void *" >&5 printf %s "checking size of void *... " >&6; } if test ${ac_cv_sizeof_void_p+y} then : printf %s "(cached) " >&6 else $as_nop if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (void *))" "ac_cv_sizeof_void_p" "$ac_includes_default" then : else $as_nop if test "$ac_cv_type_void_p" = yes; then { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (void *) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_void_p=0 fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_void_p" >&5 printf "%s\n" "$ac_cv_sizeof_void_p" >&6; } printf "%s\n" "#define SIZEOF_VOID_P $ac_cv_sizeof_void_p" >>confdefs.h CFLAGS="$ac_save_CFLAGS" size_check_failed="" if test "$ac_cv_sizeof_void_p" -gt "$ac_cv_sizeof_long"; then echo "The type void * is bigger than long." size_check_failed=1 fi if test "$ac_cv_sizeof_Window" -gt "$ac_cv_sizeof_long"; then echo "The type Window is bigger than long." size_check_failed=1 fi if test "$ac_cv_sizeof_Pixel" -gt "$ac_cv_sizeof_long"; then echo "The type Pixel is bigger than long." size_check_failed=1 fi if test x"$size_check_failed" = x1; then echo "This is not supported by the module interface yet (make_new_vpacket)." echo "Detected type sizes are: int($ac_cv_sizeof_int), long($ac_cv_sizeof_long), void*($ac_cv_sizeof_void_p), Window($ac_cv_sizeof_Window), Pixel($ac_cv_sizeof_Pixel)" echo "Please report details of your system and this message to ${FVWMWORKERSLIST}." echo exit 1 fi # 'unset' is not portable, but setting to null is not enough to avoid using # the cached value! For ancient shells "rm config.cache" is a solution. UNSET=true if unset UNSET 2>/dev/null; then UNSET=unset; fi # ********* multibyte # FreeBSD has libxpg4, check this and use if found. # Make sure we can run config.sub. $SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 printf %s "checking build system type... " >&6; } if test ${ac_cv_build+y} then : printf %s "(cached) " >&6 else $as_nop ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` || as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5 fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 printf "%s\n" "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 printf %s "checking host system type... " >&6; } if test ${ac_cv_host+y} then : printf %s "(cached) " >&6 else $as_nop if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` || as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5 fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 printf "%s\n" "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac case $host_os in freebsd*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for setlocale in -lxpg4" >&5 printf %s "checking for setlocale in -lxpg4... " >&6; } if test ${ac_cv_lib_xpg4_setlocale+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lxpg4 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char setlocale (); int main (void) { return setlocale (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_xpg4_setlocale=yes else $as_nop ac_cv_lib_xpg4_setlocale=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xpg4_setlocale" >&5 printf "%s\n" "$ac_cv_lib_xpg4_setlocale" >&6; } if test "x$ac_cv_lib_xpg4_setlocale" = xyes then : LIBS="$LIBS -lxpg4" fi ;; *) ;; esac # *** pkg-config # unfortunately, we need pkg-config for the detection of certain libs: # - version of fontconfig without fontconfig-config # - version of fribidi without fribidi-config if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_PKG_CONFIG+y} then : printf %s "(cached) " >&6 else $as_nop case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 printf "%s\n" "$PKG_CONFIG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_path_PKG_CONFIG"; then ac_pt_PKG_CONFIG=$PKG_CONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_ac_pt_PKG_CONFIG+y} then : printf %s "(cached) " >&6 else $as_nop case $ac_pt_PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG if test -n "$ac_pt_PKG_CONFIG"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 printf "%s\n" "$ac_pt_PKG_CONFIG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_pt_PKG_CONFIG" = x; then PKG_CONFIG="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac PKG_CONFIG=$ac_pt_PKG_CONFIG fi else PKG_CONFIG="$ac_cv_path_PKG_CONFIG" fi fi if test -n "$PKG_CONFIG"; then _pkg_min_version=0.9.0 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 printf %s "checking pkg-config is at least version $_pkg_min_version... " >&6; } if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } PKG_CONFIG="" fi fi # Building man pages & HTML documentation (from XML source). # extract command names if test ! x"$SED" = x; then DOC_COMMANDS=` sed -n ' :findhead /#.*define.*CMD_ENT/bfindcmd n bfindhead :findcmd n /CMD_ENT/bfound bfindcmd :found /"#"/bfindcmd /"propertychange"/bfindcmd /"readwritecolors"/bfindcmd /"send_.*"/bfindcmd /"set_.*"/bfindcmd s/.*CMD_ENT.*CMD_// s/,.*// p n bfindcmd ' < fvwm/functable.c` DOC_COMMANDS=`echo $DOC_COMMANDS` # with .xml suffix DOC_COMMANDS_XML=`for i in $DOC_COMMANDS; do echo ${i}.xml; done` DOC_COMMANDS_XML=`echo $DOC_COMMANDS_XML` # with .xml suffix and path DOC_COMMANDS_XML_PATH=` for i in $DOC_COMMANDS; do echo ../commands/${i}.xml; done ` DOC_COMMANDS_XML_PATH=`echo $DOC_COMMANDS_XML_PATH` # with .html suffix DOC_COMMANDS_HTML=`for i in $DOC_COMMANDS; do echo ${i}.html; done` DOC_COMMANDS_HTML=`echo $DOC_COMMANDS_HTML` # extract module names DOC_MODULES="" DOC_MODULES=` for i in modules/*; do echo "$i"; done | sed -n ' :search /^modules.Fvwm/bfound bnext :found s/modules.// p :next n bsearch ' ` DOC_MODULES=`echo $DOC_MODULES` DOC_MODULES_HTML=`for i in $DOC_MODULES; do echo ${i}.html; done` DOC_MODULES_HTML=`echo $DOC_MODULES_HTML` # extract man page section names DOC_SECTIONS=`cat doc/fvwm/sections` DOC_SECTIONS=`echo $DOC_SECTIONS` DOC_SECTIONS_XML=`for i in $DOC_SECTIONS; do echo ${i}.xml; done` DOC_SECTIONS_XML=`echo $DOC_SECTIONS_XML` DOC_SECTIONS_XML_PATH=`for i in $DOC_SECTIONS; do echo ${i}.xml; done` DOC_SECTIONS_XML_PATH=`echo $DOC_SECTIONS_XML` else DOC_COMMANDS="" DOC_COMMANDS_XML="" DOC_COMMANDS_XML_PATH="" DOC_COMMANDS_HTML="" DOC_MODULES="" DOC_MODULES_HTML="" DOC_SECTIONS="" DOC_SECTIONS_XML="" DOC_SECTIONS_XML_PATH="" fi problem_mandoc="" # Extract the first word of "xsltproc", so it can be a program name with args. set dummy xsltproc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_XSLTPROC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$XSLTPROC"; then ac_cv_prog_XSLTPROC="$XSLTPROC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_XSLTPROC="xsltproc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_XSLTPROC" && ac_cv_prog_XSLTPROC="""" fi fi XSLTPROC=$ac_cv_prog_XSLTPROC if test -n "$XSLTPROC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $XSLTPROC" >&5 printf "%s\n" "$XSLTPROC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Check whether --enable-mandoc was given. if test ${enable_mandoc+y} then : enableval=$enable_mandoc; if test x"$enableval" = xyes; then with_mandoc="yes, check" else with_mandoc="no" problem_mandoc=": Explicitly disabled" fi else $as_nop with_mandoc="no" fi if test ! x"$with_mandoc" = xno; then if test x"$XSLTPROC" = x ; then with_mandoc="no" problem_mandoc=": No xsltproc found in PATH" elif test x"$SED" = x ; then with_mandoc="no" problem_mandoc=": No sed found in PATH" elif test x"$HAVE_PERL_FOR_DOCS" = x0 ; then with_mandoc="no" problem_mandoc=": No perl found in PATH" else with_mandoc="yes" fi fi if test x"$with_mandoc" = xyes; then FVWM_BUILD_MANDOC_TRUE= FVWM_BUILD_MANDOC_FALSE='#' else FVWM_BUILD_MANDOC_TRUE='#' FVWM_BUILD_MANDOC_FALSE= fi problem_htmldoc="" # Check whether --enable-htmldoc was given. if test ${enable_htmldoc+y} then : enableval=$enable_htmldoc; if test x"$enableval" = xyes; then with_htmldoc="yes, check" else with_htmldoc="no" problem_htmldoc=": Explicitly disabled" fi else $as_nop with_htmldoc="no" fi if test ! x"$with_htmldoc" = xno; then if test x"$XSLTPROC" = x ; then with_htmldoc="no" problem_htmldoc=": No xsltproc found in PATH" elif test x"$SED" = x ; then with_htmldoc="no" problem_htmldoc=": No sed found in PATH" elif test x"$HAVE_PERL_FOR_DOCS" = x0 ; then with_htmldoc="no" problem_htmldoc=": No perl found in PATH" else with_htmldoc="yes" fi fi if test x"$with_htmldoc" = xyes; then FVWM_BUILD_HTMLDOC_TRUE= FVWM_BUILD_HTMLDOC_FALSE='#' else FVWM_BUILD_HTMLDOC_TRUE='#' FVWM_BUILD_HTMLDOC_FALSE= fi # ********* session management # Check the availability of SM; we don't have to add any extra libraries, # since -lSM -lICE are in X_PRE_LIBS when they exist. problem_sm="" # Check whether --enable-sm was given. if test ${enable_sm+y} then : enableval=$enable_sm; if test x"$enableval" = xyes; then with_sm="yes, check" else with_sm="no" problem_sm=": Explicitly disabled" fi else $as_nop with_sm="not specified, check" fi if test ! x"$with_sm" = xno; then $UNSET ac_cv_lib_SM_SmcOpenConnection { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for SmcOpenConnection in -lSM" >&5 printf %s "checking for SmcOpenConnection in -lSM... " >&6; } if test ${ac_cv_lib_SM_SmcOpenConnection+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lSM $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char SmcOpenConnection (); int main (void) { return SmcOpenConnection (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_SM_SmcOpenConnection=yes else $as_nop ac_cv_lib_SM_SmcOpenConnection=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_SM_SmcOpenConnection" >&5 printf "%s\n" "$ac_cv_lib_SM_SmcOpenConnection" >&6; } if test "x$ac_cv_lib_SM_SmcOpenConnection" = xyes then : with_sm=yes; printf "%s\n" "#define SESSION 1" >>confdefs.h else $as_nop with_sm=no; problem_sm=": Failed to detect libSM" fi fi # Checking for optional libraries # Default is to use them if found; can be disable using --without # These are put up front so that if they are requested, but # configure fails to find them, we fail early. # ********* shape extension # Check whether --enable-shape was given. if test ${enable_shape+y} then : enableval=$enable_shape; if test x"$enableval" = xyes; then with_shape="yes, check" else with_shape="no" problem_shape=": Explicitly disabled" fi else $as_nop with_shape="not specified, check" fi if test ! x"$with_shape" = xno; then $UNSET ac_cv_lib_Xext_XShapeQueryExtension { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for XShapeQueryExtension in -lXext" >&5 printf %s "checking for XShapeQueryExtension in -lXext... " >&6; } if test ${ac_cv_lib_Xext_XShapeQueryExtension+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lXext $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char XShapeQueryExtension (); int main (void) { return XShapeQueryExtension (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_Xext_XShapeQueryExtension=yes else $as_nop ac_cv_lib_Xext_XShapeQueryExtension=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xext_XShapeQueryExtension" >&5 printf "%s\n" "$ac_cv_lib_Xext_XShapeQueryExtension" >&6; } if test "x$ac_cv_lib_Xext_XShapeQueryExtension" = xyes then : with_shape=yes; printf "%s\n" "#define SHAPE 1" >>confdefs.h else $as_nop with_shape=no; problem_shape=": Failed to detect Shape extension" fi fi # ********* MIT Shared Memory Extension # Check whether --enable-shm was given. if test ${enable_shm+y} then : enableval=$enable_shm; if test x"$enableval" = xyes; then with_shm="yes, check" else with_shm="no" problem_shm=": Explicitly disabled" fi else $as_nop with_shm="not specified, check" fi if test ! x"$with_shm" = xno; then $UNSET ac_cv_lib_Xext_XShmQueryExtension { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for XShmQueryExtension in -lXext" >&5 printf %s "checking for XShmQueryExtension in -lXext... " >&6; } if test ${ac_cv_lib_Xext_XShmQueryExtension+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lXext $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char XShmQueryExtension (); int main (void) { return XShmQueryExtension (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_Xext_XShmQueryExtension=yes else $as_nop ac_cv_lib_Xext_XShmQueryExtension=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xext_XShmQueryExtension" >&5 printf "%s\n" "$ac_cv_lib_Xext_XShmQueryExtension" >&6; } if test "x$ac_cv_lib_Xext_XShmQueryExtension" = xyes then : with_shm=yes; printf "%s\n" "#define HAVE_XSHM 1" >>confdefs.h else $as_nop with_shm=no; problem_shm=": Can't detect MIT Shared Memory ext." fi fi # Silently look for X11/XKBlib.h ac_fn_c_check_header_compile "$LINENO" "X11/XKBlib.h" "ac_cv_header_X11_XKBlib_h" "$ac_includes_default" if test "x$ac_cv_header_X11_XKBlib_h" = xyes then : printf "%s\n" "#define HAVE_X11_XKBLIB_H 1" >>confdefs.h fi # ********* xineramA problem_xinerama="" # Check whether --enable-xinerama was given. if test ${enable_xinerama+y} then : enableval=$enable_xinerama; if test x"$enableval" = xyes; then with_xinerama="yes, check" else with_xinerama="no" problem_xinerama=": Explicitly disabled" fi else $as_nop with_xinerama="not specified, check" fi if test ! x"$with_xinerama" = xno; then $UNSET ac_cv_lib_Xinerama_XineramaIsActive _check_solaris_xinerama=no { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for XineramaIsActive in -lXinerama" >&5 printf %s "checking for XineramaIsActive in -lXinerama... " >&6; } if test ${ac_cv_lib_Xinerama_XineramaIsActive+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lXinerama $X_LIBS $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char XineramaIsActive (); int main (void) { return XineramaIsActive (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_Xinerama_XineramaIsActive=yes else $as_nop ac_cv_lib_Xinerama_XineramaIsActive=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xinerama_XineramaIsActive" >&5 printf "%s\n" "$ac_cv_lib_Xinerama_XineramaIsActive" >&6; } if test "x$ac_cv_lib_Xinerama_XineramaIsActive" = xyes then : with_xinerama=yes; Xinerama_LIBS=-lXinerama; printf "%s\n" "#define HAVE_XINERAMA 1" >>confdefs.h else $as_nop _check_solaris_xinerama=yes fi if test x"$_check_solaris_xinerama" = xyes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for XineramaGetState in -lXext" >&5 printf %s "checking for XineramaGetState in -lXext... " >&6; } if test ${ac_cv_lib_Xext_XineramaGetState+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lXext $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char XineramaGetState (); int main (void) { return XineramaGetState (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_Xext_XineramaGetState=yes else $as_nop ac_cv_lib_Xext_XineramaGetState=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xext_XineramaGetState" >&5 printf "%s\n" "$ac_cv_lib_Xext_XineramaGetState" >&6; } if test "x$ac_cv_lib_Xext_XineramaGetState" = xyes then : printf "%s\n" "#define HAVE_XINERAMA 1" >>confdefs.h printf "%s\n" "#define HAVE_SOLARIS_XINERAMA 1" >>confdefs.h with_xinerama=yes; Xinerama_LIBS=-lXext my_CPPFLAGS="$CPPFLAGS"; CPPFLAGS="$X_CPPFLAGS $CPPFLAGS" my_hdr="X11/extensions/xinerama.h" as_ac_Header=`printf "%s\n" "ac_cv_header_$my_hdr" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$my_hdr" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes" then : printf "%s\n" "#define HAVE_SOLARIS_XINERAMA_H 1" >>confdefs.h problem_xinerama=" (Using Solaris Xinerama calls)" else $as_nop problem_xinerama=" (Using Solaris 9 prototypes for missing header)" fi CPPFLAGS="$my_CPPFLAGS" else $as_nop with_xinerama=no; Xinerama_LIBS= problem_xinerama=": Failed to detect libXinerama" fi fi $UNSET _check_solaris_xinerama fi # ********* xinerama-emulation { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether to enable Xinerama emulation on one screen (useful only for developers)" >&5 printf %s "checking whether to enable Xinerama emulation on one screen (useful only for developers)... " >&6; } # Check whether --enable-xinerama-emulation was given. if test ${enable_xinerama_emulation+y} then : enableval=$enable_xinerama_emulation; if test "$enableval" = yes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define USE_XINERAMA_EMULATION 1" >>confdefs.h else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test x"$enable_xinerama_emulation" = xyes; then with_xinerama_emulation=yes else with_xinerama_emulation=no fi # ********* xrender problem_xrender="" # Check whether --enable-xrender was given. if test ${enable_xrender+y} then : enableval=$enable_xrender; if test x"$enableval" = xyes; then with_xrender="yes, check" else with_xrender="no" problem_xrender=": Explicitly disabled" fi else $as_nop with_xrender="not specified, check" fi if test ! x"$with_xrender" = xno; then $UNSET ac_cv_lib_Xrender_XRenderComposite { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for XRenderComposite in -lXrender" >&5 printf %s "checking for XRenderComposite in -lXrender... " >&6; } if test ${ac_cv_lib_Xrender_XRenderComposite+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lXrender $X_LIBS $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char XRenderComposite (); int main (void) { return XRenderComposite (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_Xrender_XRenderComposite=yes else $as_nop ac_cv_lib_Xrender_XRenderComposite=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xrender_XRenderComposite" >&5 printf "%s\n" "$ac_cv_lib_Xrender_XRenderComposite" >&6; } if test "x$ac_cv_lib_Xrender_XRenderComposite" = xyes then : with_xrender=yes; Xrender_LIBS=-lXrender; printf "%s\n" "#define HAVE_XRENDER 1" >>confdefs.h else $as_nop with_xrender=no; Xrender_LIBS= problem_xrender=": Failed to detect libXrender" fi fi # ********* xcursor xcursor_CFLAGS="" xcursor_LIBS="" # Check whether --enable-xcursor was given. if test ${enable_xcursor+y} then : enableval=$enable_xcursor; if test x"$enableval" = xno; then with_xcursor=no problem_xcursor=": Explicitly disabled" fi fi if test ! x"$with_xcursor" = xno; then with_xcursor=no if test ! x"$with_xrender" = xno; then $UNSET ac_cv_lib_Xrender_XRenderCreateCursor { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for XRenderCreateCursor in -lXrender" >&5 printf %s "checking for XRenderCreateCursor in -lXrender... " >&6; } if test ${ac_cv_lib_Xrender_XRenderCreateCursor+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lXrender $X_LIBS $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char XRenderCreateCursor (); int main (void) { return XRenderCreateCursor (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_Xrender_XRenderCreateCursor=yes else $as_nop ac_cv_lib_Xrender_XRenderCreateCursor=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xrender_XRenderCreateCursor" >&5 printf "%s\n" "$ac_cv_lib_Xrender_XRenderCreateCursor" >&6; } if test "x$ac_cv_lib_Xrender_XRenderCreateCursor" = xyes then : with_xcursor=yes else $as_nop problem_xcursor=": Your libXrender version is too old" fi else problem_xcursor=": Need Xrender support" fi fi if test x"$with_xcursor" = xyes ; then $UNSET ac_cv_lib_Xcursor_XcursorImageLoadCursor { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for XcursorImageLoadCursor in -lXcursor" >&5 printf %s "checking for XcursorImageLoadCursor in -lXcursor... " >&6; } if test ${ac_cv_lib_Xcursor_XcursorImageLoadCursor+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lXcursor $X_LIBS $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char XcursorImageLoadCursor (); int main (void) { return XcursorImageLoadCursor (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_Xcursor_XcursorImageLoadCursor=yes else $as_nop ac_cv_lib_Xcursor_XcursorImageLoadCursor=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xcursor_XcursorImageLoadCursor" >&5 printf "%s\n" "$ac_cv_lib_Xcursor_XcursorImageLoadCursor" >&6; } if test "x$ac_cv_lib_Xcursor_XcursorImageLoadCursor" = xyes then : printf "%s\n" "#define HAVE_XCURSOR 1" >>confdefs.h Xcursor_LIBS=-lXcursor problem_xcursor="" else $as_nop with_xcursor=no problem_xcursor=": Failed to detect libXcursor" fi fi # ********* xft problem_xft="" # Check whether --enable-xft was given. if test ${enable_xft+y} then : enableval=$enable_xft; if test x"$enableval" = xyes; then with_xft="yes, check" else with_xft="no" problem_xft=": Explicitly disabled" fi else $as_nop with_xft="not specified, check" fi if test ! x"$with_xft" = xno; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether pkg-config could find freetype2" >&5 printf %s "checking whether pkg-config could find freetype2... " >&6; } if "${PKG_CONFIG}" --exists freetype2; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } CFLAGS_FREETYPE=`"${PKG_CONFIG}" --cflags freetype2` FREETYPE_LIBS=`"${PKG_CONFIG}" --libs freetype2` CFLAGS="$CFLAGS $CFLAGS_FREETYPE" LIBS="$LIBS $FREETYPE_LIBS" have_freetype=yes else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } have_freetype=no fi # check for fontconfig for Xft 2 have_fontconfig=no if test ! x"$have_freetype" = xno ; then # Check whether --with-fontconfig-prefix was given. if test ${with_fontconfig_prefix+y} then : withval=$with_fontconfig_prefix; fc_config_prefix="$withval" else $as_nop fc_config_prefix="" fi # Check whether --with-fontconfig-exec-prefix was given. if test ${with_fontconfig_exec_prefix+y} then : withval=$with_fontconfig_exec_prefix; fc_config_exec_prefix="$withval" else $as_nop fc_config_exec_prefix="" fi # Check whether --enable-fontconfigtest was given. if test ${enable_fontconfigtest+y} then : enableval=$enable_fontconfigtest; else $as_nop enable_fctest=yes fi if test x$fc_config_exec_prefix != x ; then fc_config_args="$fc_config_args --exec-prefix=$fc_config_exec_prefix" if test x${FC_CONFIG+set} != xset ; then FC_CONFIG=$fc_config_exec_prefix/bin/fontconfig-config fi fi if test x$fc_config_prefix != x ; then fc_config_args="$fc_config_args --prefix=$fc_config_prefix" if test x${FC_CONFIG+set} != xset ; then FC_CONFIG=$fc_config_prefix/bin/fontconfig-config fi fi # Extract the first word of "fontconfig-config", so it can be a program name with args. set dummy fontconfig-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_FC_CONFIG+y} then : printf %s "(cached) " >&6 else $as_nop case $FC_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_FC_CONFIG="$FC_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_FC_CONFIG="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_FC_CONFIG" && ac_cv_path_FC_CONFIG="no" ;; esac fi FC_CONFIG=$ac_cv_path_FC_CONFIG if test -n "$FC_CONFIG"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $FC_CONFIG" >&5 printf "%s\n" "$FC_CONFIG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi min_fc_version=1.0.1 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Fontconfig - version >= $min_fc_version" >&5 printf %s "checking for Fontconfig - version >= $min_fc_version... " >&6; } no_fc="" pkg_config_fontconfig_exists="" if test "$FC_CONFIG" = "no" ; then if test "x$PKG_CONFIG" != "xno" ; then if $PKG_CONFIG --exists 'fontconfig' ; then if $PKG_CONFIG --exists 'fontconfig >= 1.0.1' ; then FC_CFLAGS=`$PKG_CONFIG --cflags fontconfig` FC_LIBS=`$PKG_CONFIG --libs fontconfig` else no_fc=yes fc_config_is_lt=yes fi else pkg_config_fontconfig_exists="maybe" no_fc=yes fi else no_fc=yes fi else FC_CFLAGS=`$FC_CONFIG $fc_config_args --cflags` FC_LIBS=`$FC_CONFIG $fc_config_args --libs` fc_config_major_version=`$FC_CONFIG $fc_config_args --version | \ sed 's/^[^0-9.]*\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*$/\1/'` fc_config_minor_version=`$FC_CONFIG $fc_config_args --version | \ sed 's/^[^0-9.]*\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*$/\2/'` fc_config_micro_version=`$FC_CONFIG $fc_config_args --version | \ sed 's/^[^0-9.]*\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*$/\3/'` fc_min_major_version=`echo $min_fc_version | \ sed 's/^[^0-9.]*\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*$/\1/'` fc_min_minor_version=`echo $min_fc_version | \ sed 's/^[^0-9.]*\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*$/\2/'` fc_min_micro_version=`echo $min_fc_version | \ sed 's/^[^0-9.]*\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*$/\3/'` fc_config_is_lt=no if test $fc_config_major_version -lt $fc_min_major_version ; then fc_config_is_lt=yes else if test $fc_config_major_version -eq $fc_min_major_version ; then if test $fc_config_minor_version -lt $fc_min_minor_version ; then fc_config_is_lt=yes else if test $fc_config_minor_version -eq $fc_min_minor_version ; then if test $fc_config_micro_version -lt $fc_min_micro_version ; then fc_config_is_lt=yes fi fi fi fi fi if test "x$fc_config_is_lt" = "xyes" ; then no_fc=yes fi fi if test "x$no_fc" = x ; then if test "x$enable_fctest" = "xyes" ; then ac_save_CFLAGS="$CFLAGS" ac_save_LIBS="$LIBS" CFLAGS="$CFLAGS $FC_CFLAGS $FT2_CFLAGS" LIBS="$FC_LIBS $LIBS $FT2_LIBS" if test "$cross_compiling" = yes then : echo $ac_n "cross compiling; assumed OK... $ac_c" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main() { FcBool result; result = FcInit(); if (result) { return 0; } else { return 1; } } _ACEOF if ac_fn_c_try_run "$LINENO" then : else $as_nop no_fc=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi fi if test "x$no_fc" = x; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } : else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if test "x$fc_config_is_lt" = "xyes"; then echo "*** Your Fontconfig package version is < 1.0.1" elif test "x$pkg_config_fontconfig_exists" = "xmaybe"; then echo "*** fontconfig was not found in the pkg-config search path." echo "*** either fontconfig is not installed or perhaps you should" echo "*** add the directory containing fontconfig.pc to the " echo "*** PKG_CONFIG_PATH environment variable." elif test "$FC_CONFIG" != "no"; then echo "*** The Fontconfig test program failed to run. If your system uses" echo "*** shared libraries and they are installed outside the normal" echo "*** system library path, make sure the variable LD_LIBRARY_PATH" echo "*** (or whatever is appropiate for your system) is correctly set." fi FC_CFLAGS="" FC_LIBS="" : fi if test x"$no_fc" = x ; then have_fontconfig=yes fontconfig_CFLAGS=`$PKG_CONFIG --cflags fontconfig` fontconfig_LIBS=`$PKG_CONFIG --libs fontconfig` CFLAGS="$CFLAGS $fontconfig_CFLAGS" LIBS="$LIBS $fontconfig_LIBS" else have_fontconfig=no problem_xft=": Can't detect fontconfig >= 1.0.1" fi fi # now check for Xft 2 with_xft=no if test ! x"$have_fontconfig" = xno ; then # Xft 2 # Check whether --with-xft-prefix was given. if test ${with_xft_prefix+y} then : withval=$with_xft_prefix; xft_config_prefix="$withval" else $as_nop xft_config_prefix="" fi # Check whether --with-xft-exec-prefix was given. if test ${with_xft_exec_prefix+y} then : withval=$with_xft_exec_prefix; xft_config_exec_prefix="$withval" else $as_nop xft_config_exec_prefix="" fi # Check whether --enable-xfttest was given. if test ${enable_xfttest+y} then : enableval=$enable_xfttest; else $as_nop enable_xfttest=yes fi if test x$xft_config_exec_prefix != x ; then xft_config_args="$xft_config_args --exec-prefix=$xft_config_exec_prefix" if test x${XFT_CONFIG+set} != xset ; then XFT_CONFIG=$xft_config_exec_prefix/bin/xft-config fi fi if test x$xft_config_prefix != x ; then xft_config_args="$xft_config_args --prefix=$xft_config_prefix" if test x${XFT_CONFIG+set} != xset ; then XFT_CONFIG=$xft_config_prefix/bin/xft-config fi fi # Extract the first word of "xft-config", so it can be a program name with args. set dummy xft-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_XFT_CONFIG+y} then : printf %s "(cached) " >&6 else $as_nop case $XFT_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_XFT_CONFIG="$XFT_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_XFT_CONFIG="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_XFT_CONFIG" && ac_cv_path_XFT_CONFIG="no" ;; esac fi XFT_CONFIG=$ac_cv_path_XFT_CONFIG if test -n "$XFT_CONFIG"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $XFT_CONFIG" >&5 printf "%s\n" "$XFT_CONFIG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi min_xft_version=2.0.0 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Xft - version >= $min_xft_version" >&5 printf %s "checking for Xft - version >= $min_xft_version... " >&6; } no_xft="" pkg_config_xft_exists="" if test "$XFT_CONFIG" = "no" ; then if test "x$PKG_CONFIG" != "xno" ; then if $PKG_CONFIG --exists 'xft' ; then if $PKG_CONFIG --exists 'xft >= 2.0.0' ; then XFT_CFLAGS=`$PKG_CONFIG --cflags xft` XFT_LIBS=`$PKG_CONFIG --libs xft` else no_xft=yes xft_config_is_lt=yes fi else pkg_config_xft_exists="maybe" no_xft=yes fi else no_xft=yes fi else XFT_CFLAGS=`$XFT_CONFIG $xft_config_args --cflags` XFT_LIBS=`$XFT_CONFIG $xft_config_args --libs` xft_config_major_version=`$XFT_CONFIG $xft_config_args --version | \ sed 's/^[^0-9.]*\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*$/\1/'` xft_config_minor_version=`$XFT_CONFIG $xft_config_args --version | \ sed 's/^[^0-9.]*\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*$/\2/'` xft_config_micro_version=`$XFT_CONFIG $xft_config_args --version | \ sed 's/^[^0-9.]*\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*$/\3/'` xft_min_major_version=`echo $min_xft_version | \ sed 's/^[^0-9.]*\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*$/\1/'` xft_min_minor_version=`echo $min_xft_version | \ sed 's/^[^0-9.]*\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*$/\2/'` xft_min_micro_version=`echo $min_xft_version | \ sed 's/^[^0-9.]*\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*$/\3/'` xft_config_is_lt=no if test $xft_config_major_version -lt $xft_min_major_version ; then xft_config_is_lt=yes else if test $xft_config_major_version -eq $xft_min_major_version ; then if test $xft_config_minor_version -lt $xft_min_minor_version ; then xft_config_is_lt=yes else if test $xft_config_minor_version -eq $xft_min_minor_version ; then if test $xft_config_micro_version -lt $xft_min_micro_version ; then xft_config_is_lt=yes fi fi fi fi fi if test "x$xft_config_is_lt" = "xyes" ; then : fi fi if test "x$no_xft" = x ; then if test "x$enable_xfttest" = "xyes" ; then ac_save_CFLAGS="$CFLAGS" ac_save_LIBS="$LIBS" CFLAGS="$XFT_CFLAGS $CFLAGS" LIBS="$XFT_LIBS $LIBS" if test "$cross_compiling" = yes then : echo $ac_n "cross compiling; assumed OK... $ac_c" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main() { FcBool result = 1; result = XftInit(NULL); if (result) { return 0; } else { return 1; } } _ACEOF if ac_fn_c_try_run "$LINENO" then : else $as_nop no_xft=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi fi if test "x$no_xft" = x; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } : else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if test "x$xft_config_is_lt" = "xyes"; then echo "*** Your xft2 package version is < 2.0.0" elif test "x$pkg_config_fontconfig_exists" = "xmaybe" ; then echo "*** xft2 was not found in the pkg-config search path." echo "*** either xft is not installed or perhaps you should" echo "*** add the directory containing xft.pc to the " echo "*** PKG_CONFIG_PATH environment variable." elif test "$XFT_CONFIG" = "no"; then echo "*** The xft-config script installed by Xft 2 could not be found." echo "*** If Xft 2 was installed in PREFIX, make sure PREFIX/bin is in" echo "*** your path, or set the XFT_CONFIG environment variable to the" echo "*** full path to xft-config." else echo "*** The Xft test program failed to run. If your system uses" echo "*** shared libraries and they are installed outside the normal" echo "*** system library path, make sure the variable LD_LIBRARY_PATH" echo "*** (or whatever is appropiate for your system) is correctly set." fi XFT_CFLAGS="" XFT_LIBS="" : fi if test x"$no_xft" = x; then with_xft=yes problem_xft=" (version 2)" printf "%s\n" "#define HAVE_XFT2 1" >>confdefs.h printf "%s\n" "#define HAVE_XFT 1" >>confdefs.h printf "%s\n" "#define HAVE_XFT_UTF8 1" >>confdefs.h Xft_LIBS=$XFT_LIBS Xft_CFLAGS=$XFT_CFLAGS else problem_xft=": Can't detect Xft2, detected fontconfig" fi fi # if Xft2 not detected check for Xft1 if test ! x"$have_freetype" = xno && test ! x"$with_xft" = xyes; then #Xft 1 $UNSET ac_cv_lib_XftConfigSubstitute $UNSET ac_cv_lib_Xft_XftFontOpen $UNSET ac_cv_lib_Xft_XftDrawStringUtf8 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for XftFontOpen in -lXft" >&5 printf %s "checking for XftFontOpen in -lXft... " >&6; } if test ${ac_cv_lib_Xft_XftFontOpen+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lXft $X_LIBS $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS $FT2_LIBS $Xrender_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char XftFontOpen (); int main (void) { return XftFontOpen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_Xft_XftFontOpen=yes else $as_nop ac_cv_lib_Xft_XftFontOpen=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xft_XftFontOpen" >&5 printf "%s\n" "$ac_cv_lib_Xft_XftFontOpen" >&6; } if test "x$ac_cv_lib_Xft_XftFontOpen" = xyes then : with_xft=yes else $as_nop with_xft=no fi if test x"$with_xft" = xyes ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for XftConfigSubstitute in -lXft" >&5 printf %s "checking for XftConfigSubstitute in -lXft... " >&6; } if test ${ac_cv_lib_Xft_XftConfigSubstitute+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lXft $X_LIBS $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS $FT2_LIBS $Xrender_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char XftConfigSubstitute (); int main (void) { return XftConfigSubstitute (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_Xft_XftConfigSubstitute=yes else $as_nop ac_cv_lib_Xft_XftConfigSubstitute=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xft_XftConfigSubstitute" >&5 printf "%s\n" "$ac_cv_lib_Xft_XftConfigSubstitute" >&6; } if test "x$ac_cv_lib_Xft_XftConfigSubstitute" = xyes then : is_xft1=yes else $as_nop is_xft1=no fi if test x"$is_xft1" = xyes; then Xft_LIBS="-lXft $FT2_LIBS" Xft_CFLAGS="$Xft_CFLAGS $FT2_CFLAGS" problem_xft=" (version 1)" printf "%s\n" "#define HAVE_XFT 1" >>confdefs.h else with_xft=no problem_xft=": Can't detect Xft 1 or fontconfig" fi else problem_xft=": Can't detect Xft 1 or 2 and fontconfig" fi if test x"$with_xft" = xyes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for XftDrawStringUtf8 in -lXft" >&5 printf %s "checking for XftDrawStringUtf8 in -lXft... " >&6; } if test ${ac_cv_lib_Xft_XftDrawStringUtf8+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lXft $X_LIBS $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS $FT2_LIBS $Xrender_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char XftDrawStringUtf8 (); int main (void) { return XftDrawStringUtf8 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_Xft_XftDrawStringUtf8=yes else $as_nop ac_cv_lib_Xft_XftDrawStringUtf8=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xft_XftDrawStringUtf8" >&5 printf "%s\n" "$ac_cv_lib_Xft_XftDrawStringUtf8" >&6; } if test "x$ac_cv_lib_Xft_XftDrawStringUtf8" = xyes then : printf "%s\n" "#define HAVE_XFT_UTF8 1" >>confdefs.h fi fi fi fi # ********* xpm problem_xpm=": Xpm library or header not found" $UNSET ac_cv_header_X11_xpm_h $UNSET ac_cv_lib_Xpm_XpmReadFileToXpmImage smr_lib=Xpm smr_header=X11/xpm.h smr_lib=Xpm # Check whether --with-xpm-library was given. if test ${with_xpm_library+y} then : withval=$with_xpm_library; if test "$withval" = yes; then with_xpm=yes xpm_LIBS="-l${smr_lib}" elif test "$withval" = no; then with_xpm=no xpm_LIBS= else with_xpm=yes if test -f "$withval"; then xpm_LIBS=$withval elif test -d "$withval"; then xpm_LIBS="-L$withval -l${smr_lib}" else as_fn_error $? "--with-xpm-library argument must be yes/no, file or directory" "$LINENO" 5 fi fi else $as_nop with_xpm=maybe xpm_LIBS="-l${smr_lib}" fi if test "$with_xpm" != no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for XpmReadFileToXpmImage in -lXpm" >&5 printf %s "checking for XpmReadFileToXpmImage in -lXpm... " >&6; } if test ${ac_cv_lib_Xpm_XpmReadFileToXpmImage+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lXpm ${xpm_LIBS} $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char XpmReadFileToXpmImage (); int main (void) { return XpmReadFileToXpmImage (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_Xpm_XpmReadFileToXpmImage=yes else $as_nop ac_cv_lib_Xpm_XpmReadFileToXpmImage=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xpm_XpmReadFileToXpmImage" >&5 printf "%s\n" "$ac_cv_lib_Xpm_XpmReadFileToXpmImage" >&6; } if test "x$ac_cv_lib_Xpm_XpmReadFileToXpmImage" = xyes then : smr_havelib=yes else $as_nop smr_havelib=no; problem_xpm=": Can't find working lib$smr_lib" fi if test "$smr_havelib" = yes -a "$smr_header" != ""; then # Check whether --with-xpm-includes was given. if test ${with_xpm_includes+y} then : withval=$with_xpm_includes; if test -d "$withval"; then xpm_CFLAGS="-I${withval}" else as_fn_error $? "argument must be a directory" "$LINENO" 5 fi fi smr_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS ${xpm_CFLAGS}" CPPFLAGS="$CPPFLAGS $X_CFLAGS" for ac_header in $smr_header do : as_ac_Header=`printf "%s\n" "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes" then : cat >>confdefs.h <<_ACEOF #define `printf "%s\n" "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done CPPFLAGS=$smr_save_CPPFLAGS smr_safe=`echo "$smr_header" | sed 'y%./+-%__p_%'` if eval "test \"`echo '$ac_cv_header_'$smr_safe`\" != yes"; then smr_havelib=no problem_xpm=": Can't find working $smr_header" fi fi if test "$smr_havelib" = yes; then with_xpm=yes problem_xpm= else xpm_LIBS= xpm_CFLAGS= with_xpm=no fi else problem_xpm=": Explicitly disabled" fi if test ! x"$xpm_LIBS" = x; then # Check for proper version of Xpm -- from XEmacs 21.x configure.in { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Xpm 3.4g or better" >&5 printf %s "checking for Xpm 3.4g or better... " >&6; } my_CPPFLAGS="$CPPFLAGS" my_LIBS="$LIBS" CPPFLAGS="$CPPFLAGS $xpm_CFLAGS $X_CFLAGS" LIBS="$LIBS $xpm_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS" if test "$cross_compiling" = yes then : echo $ac_n "cross compiling; assumed OK... $ac_c" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main(int c, char **v) { return c == 1 ? 0 : XpmIncludeVersion != XpmLibraryVersion() ? 1 : XpmIncludeVersion < 30407 ? 2 : 0 ;} _ACEOF if ac_fn_c_try_run "$LINENO" then : ./conftest dummy_arg; xpm_status=$?; if test x"$xpm_status" = x0; then with_xpm=yes problem_xpm="" else with_xpm=no; if test x"$xpm_status" = x1; then problem_xpm=": Xpm library and header versions don't match" elif test x"$xpm_status" = x2x; then problem_xpm=": Xpm library version is too old" else problem_xpm=": Internal xpm detection logic error" fi fi else $as_nop with_xpm=no; problem_xpm=": Xpm test error, see config.log" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $with_xpm" >&5 printf "%s\n" "$with_xpm" >&6; } CPPFLAGS="$my_CPPFLAGS" LIBS="$my_LIBS" if test x"$with_xpm" = xyes; then printf "%s\n" "#define XPM 1" >>confdefs.h # FVWMBANNER=FvwmBanner AC_SUBST(FVWMBANNER) # XPMROOT=xpmroot AC_SUBST(XPMROOT) # FVWMSCRIPT=FvwmScript AC_SUBST(FVWMSCRIPT) else xpm_LIBS= xpm_CFLAGS= fi fi # ********* png png_LIBS="" png_CFLAGS="" # Check whether --enable-png was given. if test ${enable_png+y} then : enableval=$enable_png; with_png="$enableval" else $as_nop with_png="yes" fi if test "$with_png" = no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: *** disabling PNG support will mean the default configuration shipped with FVWM will be without icon support. Be sure this is what you mean to do. ***" >&5 printf "%s\n" "$as_me: WARNING: *** disabling PNG support will mean the default configuration shipped with FVWM will be without icon support. Be sure this is what you mean to do. ***" >&2;} else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libpng..." >&5 printf %s "checking for libpng...... " >&6; } pkg_failed=no { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for png" >&5 printf %s "checking for png... " >&6; } if test -n "$png_CFLAGS"; then pkg_cv_png_CFLAGS="$png_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpng >= 1.2\""; } >&5 ($PKG_CONFIG --exists --print-errors "libpng >= 1.2") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_png_CFLAGS=`$PKG_CONFIG --cflags "libpng >= 1.2" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$png_LIBS"; then pkg_cv_png_LIBS="$png_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libpng >= 1.2\""; } >&5 ($PKG_CONFIG --exists --print-errors "libpng >= 1.2") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_png_LIBS=`$PKG_CONFIG --libs "libpng >= 1.2" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then png_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libpng >= 1.2" 2>&1` else png_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libpng >= 1.2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$png_PKG_ERRORS" >&5 as_fn_error $? "*** libpng not found, and --disable-png not given. It is recommended to use libpng so that PNG icons can be rendered by FVWM, which the default configuration file needs, as well as other third-party programs which generate menus, for example. If it is critical that FVWM does not link against libpng (perhaps due to size limitations of the binary), then use --disable-png ***" "$LINENO" 5 elif test $pkg_failed = untried; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } as_fn_error $? "*** libpng not found, and --disable-png not given. It is recommended to use libpng so that PNG icons can be rendered by FVWM, which the default configuration file needs, as well as other third-party programs which generate menus, for example. If it is critical that FVWM does not link against libpng (perhaps due to size limitations of the binary), then use --disable-png ***" "$LINENO" 5 else png_CFLAGS=$pkg_cv_png_CFLAGS png_LIBS=$pkg_cv_png_LIBS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define HAVE_PNG 1" >>confdefs.h fi # ** needed by the png support { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 printf %s "checking whether byte ordering is bigendian... " >&6; } if test ${ac_cv_c_bigendian+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_c_bigendian=unknown # See if we're dealing with a universal compiler. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __APPLE_CC__ not a universal capable compiler #endif typedef int dummy; _ACEOF if ac_fn_c_try_compile "$LINENO" then : # Check for potential -arch flags. It is not universal unless # there are at least two -arch flags with different values. ac_arch= ac_prev= for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do if test -n "$ac_prev"; then case $ac_word in i?86 | x86_64 | ppc | ppc64) if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then ac_arch=$ac_word else ac_cv_c_bigendian=universal break fi ;; esac ac_prev= elif test "x$ac_word" = "x-arch"; then ac_prev=arch fi done fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext if test $ac_cv_c_bigendian = unknown; then # See if sys/param.h defines the BYTE_ORDER macro. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { #if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ && LITTLE_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : # It does; now see whether it defined to BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_c_bigendian=yes else $as_nop ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { #if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : # It does; now see whether it defined to _BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { #ifndef _BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_c_bigendian=yes else $as_nop ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # Compile a test program. if test "$cross_compiling" = yes then : # Try to guess by grepping values from an object file. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ unsigned short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; unsigned short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; int use_ascii (int i) { return ascii_mm[i] + ascii_ii[i]; } unsigned short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; unsigned short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; int use_ebcdic (int i) { return ebcdic_mm[i] + ebcdic_ii[i]; } extern int foo; int main (void) { return use_ascii (foo) == use_ebcdic (foo); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then ac_cv_c_bigendian=yes fi if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then if test "$ac_cv_c_bigendian" = unknown; then ac_cv_c_bigendian=no else # finding both strings is unlikely to happen, but who knows? ac_cv_c_bigendian=unknown fi fi fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main (void) { /* Are we little or big endian? From Harbison&Steele. */ union { long int l; char c[sizeof (long int)]; } u; u.l = 1; return u.c[sizeof (long int) - 1] == 1; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : ac_cv_c_bigendian=no else $as_nop ac_cv_c_bigendian=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 printf "%s\n" "$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in #( yes) printf "%s\n" "#define WORDS_BIGENDIAN 1" >>confdefs.h ;; #( no) ;; #( universal) printf "%s\n" "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h ;; #( *) as_fn_error $? "unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; esac fi # ********* rsvg rsvg_min_version=2.13.92 # Check whether --enable-rsvg was given. if test ${enable_rsvg+y} then : enableval=$enable_rsvg; if test x"$enableval" = xno; then with_rsvg=no problem_rsvg=": Explicitly disabled" fi fi if test ! x"$with_rsvg" = xno; then with_rsvg=no if test ! x"$PKG_CONFIG" = x ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for librsvg - version >= $rsvg_min_version" >&5 printf %s "checking for librsvg - version >= $rsvg_min_version... " >&6; } if $PKG_CONFIG --exists librsvg-2.0 ; then if $PKG_CONFIG --exists "librsvg-2.0 >= $rsvg_min_version" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for cairo svg backend" >&5 printf %s "checking for cairo svg backend... " >&6; } if $PKG_CONFIG --exists cairo-svg ; then svg_packages="librsvg-2.0 cairo-svg" elif $PKG_CONFIG --exists libsvg-cairo ; then svg_packages="librsvg-2.0 libsvg-cairo" elif $PKG_CONFIG --exists cairo ; then svg_packages="librsvg-2.0 cairo" else svg_packages="" fi if test ! x"$svg_packages" = x ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } rsvg_CFLAGS=`$PKG_CONFIG --cflags $svg_packages` rsvg_LIBS=`$PKG_CONFIG --libs $svg_packages` with_rsvg=yes else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: *** cairo was not found in the pkg-config search" >&5 printf "%s\n" "$as_me: WARNING: *** cairo was not found in the pkg-config search" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: *** path. Add the directory containing cairo.pc" >&5 printf "%s\n" "$as_me: WARNING: *** path. Add the directory containing cairo.pc" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: *** to the PKG_CONFIG_PATH environment variable." >&5 printf "%s\n" "$as_me: WARNING: *** to the PKG_CONFIG_PATH environment variable." >&2;} problem_rsvg=": Cannot detect cairo backend" fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: *** Your librsvg version is < $rsvg_min_version" >&5 printf "%s\n" "$as_me: WARNING: *** Your librsvg version is < $rsvg_min_version" >&2;} problem_rsvg=": Your librsvg version is too old" fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: *** librsvg-2.0 was not found in the pkg-config search" >&5 printf "%s\n" "$as_me: WARNING: *** librsvg-2.0 was not found in the pkg-config search" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: *** path. Either librsvg is not installed or you need" >&5 printf "%s\n" "$as_me: WARNING: *** path. Either librsvg is not installed or you need" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: *** to add the directory containing librsvg-2.0.pc to" >&5 printf "%s\n" "$as_me: WARNING: *** to add the directory containing librsvg-2.0.pc to" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: *** the PKG_CONFIG_PATH environment variable." >&5 printf "%s\n" "$as_me: WARNING: *** the PKG_CONFIG_PATH environment variable." >&2;} problem_rsvg=": librsvg library or header not found" fi else problem_rsvg=": pkg-config not found" fi fi if test x"$with_rsvg" = xyes ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether a librsvg program compiles and runs" >&5 printf %s "checking whether a librsvg program compiles and runs... " >&6; } original_CFLAGS="$CFLAGS" original_LIBS="$LIBS" CFLAGS="$CFLAGS $rsvg_CFLAGS" LIBS="$LIBS $rsvg_LIBS" if test "$cross_compiling" = yes then : echo $ac_n "cross compiling; assumed OK... $ac_c" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main() { RsvgHandle *rsvg; g_type_init(); if(!(rsvg = rsvg_handle_new())) return 1; g_object_unref(G_OBJECT(rsvg)); return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: *** The librsvg test program failed to run. If your system" >&5 printf "%s\n" "$as_me: WARNING: *** The librsvg test program failed to run. If your system" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: *** has shared libraries outside the normal system library" >&5 printf "%s\n" "$as_me: WARNING: *** has shared libraries outside the normal system library" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: *** path, you need to make sure that the LD_LIBRARY_PATH" >&5 printf "%s\n" "$as_me: WARNING: *** path, you need to make sure that the LD_LIBRARY_PATH" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: *** (or the like) environment variable is correctly set." >&5 printf "%s\n" "$as_me: WARNING: *** (or the like) environment variable is correctly set." >&2;} with_rsvg=no problem_rsvg=": Failed to run test program" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi CFLAGS="$original_CFLAGS" LIBS="$original_LIBS" fi if test x"$with_rsvg" = xyes ; then printf "%s\n" "#define HAVE_RSVG 1" >>confdefs.h problem_rsvg="" else rsvg_CFLAGS="" rsvg_LIBS="" fi # ********* rplay $UNSET ac_cv_header_rplay_h $UNSET ac_cv_lib_rplay_rplay_create # Add in X_EXTRA_LIBS here to get things like connect(). smr_lib=rplay smr_header=rplay.h smr_lib=rplay # Check whether --with-rplay-library was given. if test ${with_rplay_library+y} then : withval=$with_rplay_library; if test "$withval" = yes; then with_rplay=yes rplay_LIBS="-l${smr_lib}" elif test "$withval" = no; then with_rplay=no rplay_LIBS= else with_rplay=yes if test -f "$withval"; then rplay_LIBS=$withval elif test -d "$withval"; then rplay_LIBS="-L$withval -l${smr_lib}" else as_fn_error $? "--with-rplay-library argument must be yes/no, file or directory" "$LINENO" 5 fi fi else $as_nop with_rplay=maybe rplay_LIBS="-l${smr_lib}" fi if test "$with_rplay" != no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for rplay_create in -lrplay" >&5 printf %s "checking for rplay_create in -lrplay... " >&6; } if test ${ac_cv_lib_rplay_rplay_create+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lrplay ${rplay_LIBS} $X_EXTRA_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char rplay_create (); int main (void) { return rplay_create (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_rplay_rplay_create=yes else $as_nop ac_cv_lib_rplay_rplay_create=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rplay_rplay_create" >&5 printf "%s\n" "$ac_cv_lib_rplay_rplay_create" >&6; } if test "x$ac_cv_lib_rplay_rplay_create" = xyes then : smr_havelib=yes else $as_nop smr_havelib=no; problem_rplay=": Can't find working lib$smr_lib" fi if test "$smr_havelib" = yes -a "$smr_header" != ""; then # Check whether --with-rplay-includes was given. if test ${with_rplay_includes+y} then : withval=$with_rplay_includes; if test -d "$withval"; then rplay_CFLAGS="-I${withval}" else as_fn_error $? "argument must be a directory" "$LINENO" 5 fi fi smr_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS ${rplay_CFLAGS}" for ac_header in $smr_header do : as_ac_Header=`printf "%s\n" "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes" then : cat >>confdefs.h <<_ACEOF #define `printf "%s\n" "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done CPPFLAGS=$smr_save_CPPFLAGS smr_safe=`echo "$smr_header" | sed 'y%./+-%__p_%'` if eval "test \"`echo '$ac_cv_header_'$smr_safe`\" != yes"; then smr_havelib=no problem_rplay=": Can't find working $smr_header" fi fi if test "$smr_havelib" = yes; then with_rplay=yes problem_rplay= else rplay_LIBS= rplay_CFLAGS= with_rplay=no fi else problem_rplay=": Explicitly disabled" fi test ! x"$rplay_LIBS" = x && printf "%s\n" "#define HAVE_RPLAY 1" >>confdefs.h # ********* stroke $UNSET ac_cv_header_stroke_h $UNSET ac_cv_lib_stroke_stroke_init smr_lib=stroke smr_header=stroke.h smr_lib=stroke # Check whether --with-stroke-library was given. if test ${with_stroke_library+y} then : withval=$with_stroke_library; if test "$withval" = yes; then with_stroke=yes stroke_LIBS="-l${smr_lib}" elif test "$withval" = no; then with_stroke=no stroke_LIBS= else with_stroke=yes if test -f "$withval"; then stroke_LIBS=$withval elif test -d "$withval"; then stroke_LIBS="-L$withval -l${smr_lib}" else as_fn_error $? "--with-stroke-library argument must be yes/no, file or directory" "$LINENO" 5 fi fi else $as_nop with_stroke=maybe stroke_LIBS="-l${smr_lib}" fi if test "$with_stroke" != no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for stroke_init in -lstroke" >&5 printf %s "checking for stroke_init in -lstroke... " >&6; } if test ${ac_cv_lib_stroke_stroke_init+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lstroke ${stroke_LIBS} $X_LIBS -lX11 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char stroke_init (); int main (void) { return stroke_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_stroke_stroke_init=yes else $as_nop ac_cv_lib_stroke_stroke_init=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_stroke_stroke_init" >&5 printf "%s\n" "$ac_cv_lib_stroke_stroke_init" >&6; } if test "x$ac_cv_lib_stroke_stroke_init" = xyes then : smr_havelib=yes else $as_nop smr_havelib=no; problem_stroke=": Can't find working lib$smr_lib" fi if test "$smr_havelib" = yes -a "$smr_header" != ""; then # Check whether --with-stroke-includes was given. if test ${with_stroke_includes+y} then : withval=$with_stroke_includes; if test -d "$withval"; then stroke_CFLAGS="-I${withval}" else as_fn_error $? "argument must be a directory" "$LINENO" 5 fi fi smr_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS ${stroke_CFLAGS}" CPPFLAGS="$CPPFLAGS $X_CFLAGS -I/usr/X11R6/include" for ac_header in $smr_header do : as_ac_Header=`printf "%s\n" "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes" then : cat >>confdefs.h <<_ACEOF #define `printf "%s\n" "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done CPPFLAGS=$smr_save_CPPFLAGS smr_safe=`echo "$smr_header" | sed 'y%./+-%__p_%'` if eval "test \"`echo '$ac_cv_header_'$smr_safe`\" != yes"; then smr_havelib=no problem_stroke=": Can't find working $smr_header" fi fi if test "$smr_havelib" = yes; then with_stroke=yes problem_stroke= else stroke_LIBS= stroke_CFLAGS= with_stroke=no fi else problem_stroke=": Explicitly disabled" fi test ! x"$stroke_LIBS" = x && printf "%s\n" "#define HAVE_STROKE 1" >>confdefs.h # ********* readline with_readline=no problem_readline=": Both termcap and ncurses disabled" smr_lib=termcap # Check whether --with-termcap-library was given. if test ${with_termcap_library+y} then : withval=$with_termcap_library; if test "$withval" = yes; then with_termcap=yes termcap_LIBS="-l${smr_lib}" elif test "$withval" = no; then with_termcap=no termcap_LIBS= else with_termcap=yes if test -f "$withval"; then termcap_LIBS=$withval elif test -d "$withval"; then termcap_LIBS="-L$withval -l${smr_lib}" else as_fn_error $? "--with-termcap-library argument must be yes/no, file or directory" "$LINENO" 5 fi fi else $as_nop with_termcap=maybe termcap_LIBS="-l${smr_lib}" fi if test ! x"$with_termcap" = xno; then # Forget cached values, so user can re-run configure $UNSET ac_cv_header_readline_history_h $UNSET ac_cv_lib_readline_readline { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking with termcap" >&5 printf %s "checking with termcap... " >&6; } smr_lib=readline smr_header=readline/history.h smr_lib=readline # Check whether --with-readline-library was given. if test ${with_readline_library+y} then : withval=$with_readline_library; if test "$withval" = yes; then with_readline=yes readline_LIBS="-l${smr_lib}" elif test "$withval" = no; then with_readline=no readline_LIBS= else with_readline=yes if test -f "$withval"; then readline_LIBS=$withval elif test -d "$withval"; then readline_LIBS="-L$withval -l${smr_lib}" else as_fn_error $? "--with-readline-library argument must be yes/no, file or directory" "$LINENO" 5 fi fi else $as_nop with_readline=maybe readline_LIBS="-l${smr_lib}" fi if test "$with_readline" != no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for readline in -lreadline" >&5 printf %s "checking for readline in -lreadline... " >&6; } if test ${ac_cv_lib_readline_readline+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lreadline ${readline_LIBS} $termcap_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char readline (); int main (void) { return readline (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_readline_readline=yes else $as_nop ac_cv_lib_readline_readline=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_readline" >&5 printf "%s\n" "$ac_cv_lib_readline_readline" >&6; } if test "x$ac_cv_lib_readline_readline" = xyes then : smr_havelib=yes else $as_nop smr_havelib=no; problem_readline=": Can't find working lib$smr_lib" fi if test "$smr_havelib" = yes -a "$smr_header" != ""; then # Check whether --with-readline-includes was given. if test ${with_readline_includes+y} then : withval=$with_readline_includes; if test -d "$withval"; then readline_CFLAGS="-I${withval}" else as_fn_error $? "argument must be a directory" "$LINENO" 5 fi fi smr_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS ${readline_CFLAGS}" for ac_header in $smr_header do : as_ac_Header=`printf "%s\n" "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes" then : cat >>confdefs.h <<_ACEOF #define `printf "%s\n" "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done CPPFLAGS=$smr_save_CPPFLAGS smr_safe=`echo "$smr_header" | sed 'y%./+-%__p_%'` if eval "test \"`echo '$ac_cv_header_'$smr_safe`\" != yes"; then smr_havelib=no problem_readline=": Can't find working $smr_header" fi fi if test "$smr_havelib" = yes; then with_readline=yes problem_readline= else readline_LIBS= readline_CFLAGS= with_readline=no fi else problem_readline=": Explicitly disabled" fi if test ! x"$readline_LIBS" = x; then with_readline=yes readline_LIBS="$readline_LIBS $termcap_LIBS" printf "%s\n" "#define HAVE_READLINE 1" >>confdefs.h fi fi smr_lib=ncurses # Check whether --with-ncurses-library was given. if test ${with_ncurses_library+y} then : withval=$with_ncurses_library; if test "$withval" = yes; then with_ncurses=yes ncurses_LIBS="-l${smr_lib}" elif test "$withval" = no; then with_ncurses=no ncurses_LIBS= else with_ncurses=yes if test -f "$withval"; then ncurses_LIBS=$withval elif test -d "$withval"; then ncurses_LIBS="-L$withval -l${smr_lib}" else as_fn_error $? "--with-ncurses-library argument must be yes/no, file or directory" "$LINENO" 5 fi fi else $as_nop with_ncurses=maybe ncurses_LIBS="-l${smr_lib}" fi if test ! x"$with_ncurses" = xno && test x"$readline_LIBS" = x; then # We couldn't use readline with termcap; try with ncurses? # Doesn't this seem a hacky way to do this?? # unset cached values from last check... $UNSET ac_cv_header_readline_history_h $UNSET ac_cv_lib_readline_readline { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking with ncurses" >&5 printf %s "checking with ncurses... " >&6; } smr_lib=readline smr_header=readline/history.h smr_lib=readline # Check whether --with-readline-library was given. if test ${with_readline_library+y} then : withval=$with_readline_library; if test "$withval" = yes; then with_readline=yes readline_LIBS="-l${smr_lib}" elif test "$withval" = no; then with_readline=no readline_LIBS= else with_readline=yes if test -f "$withval"; then readline_LIBS=$withval elif test -d "$withval"; then readline_LIBS="-L$withval -l${smr_lib}" else as_fn_error $? "--with-readline-library argument must be yes/no, file or directory" "$LINENO" 5 fi fi else $as_nop with_readline=maybe readline_LIBS="-l${smr_lib}" fi if test "$with_readline" != no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for readline in -lreadline" >&5 printf %s "checking for readline in -lreadline... " >&6; } if test ${ac_cv_lib_readline_readline+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lreadline ${readline_LIBS} $ncurses_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char readline (); int main (void) { return readline (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_readline_readline=yes else $as_nop ac_cv_lib_readline_readline=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_readline" >&5 printf "%s\n" "$ac_cv_lib_readline_readline" >&6; } if test "x$ac_cv_lib_readline_readline" = xyes then : smr_havelib=yes else $as_nop smr_havelib=no; problem_readline=": Can't find working lib$smr_lib" fi if test "$smr_havelib" = yes -a "$smr_header" != ""; then # Check whether --with-readline-includes was given. if test ${with_readline_includes+y} then : withval=$with_readline_includes; if test -d "$withval"; then readline_CFLAGS="-I${withval}" else as_fn_error $? "argument must be a directory" "$LINENO" 5 fi fi smr_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS ${readline_CFLAGS}" for ac_header in $smr_header do : as_ac_Header=`printf "%s\n" "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes" then : cat >>confdefs.h <<_ACEOF #define `printf "%s\n" "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done CPPFLAGS=$smr_save_CPPFLAGS smr_safe=`echo "$smr_header" | sed 'y%./+-%__p_%'` if eval "test \"`echo '$ac_cv_header_'$smr_safe`\" != yes"; then smr_havelib=no problem_readline=": Can't find working $smr_header" fi fi if test "$smr_havelib" = yes; then with_readline=yes problem_readline= else readline_LIBS= readline_CFLAGS= with_readline=no fi else problem_readline=": Explicitly disabled" fi if test ! x"$readline_LIBS" = x; then with_readline=yes readline_LIBS="$readline_LIBS $ncurses_LIBS" printf "%s\n" "#define HAVE_READLINE 1" >>confdefs.h fi fi if test x"$with_readline" = xyes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for append_history in -lreadline" >&5 printf %s "checking for append_history in -lreadline... " >&6; } if test ${ac_cv_lib_readline_append_history+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lreadline $readline_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char append_history (); int main (void) { return append_history (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_readline_append_history=yes else $as_nop ac_cv_lib_readline_append_history=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_readline_append_history" >&5 printf "%s\n" "$ac_cv_lib_readline_append_history" >&6; } if test "x$ac_cv_lib_readline_append_history" = xyes then : printf "%s\n" "#define HAVE_GNU_READLINE 1" >>confdefs.h fi fi # Check if Xsetlocale() is available or not. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for _Xsetlocale in -lX11" >&5 printf %s "checking for _Xsetlocale in -lX11... " >&6; } if test ${ac_cv_lib_X11__Xsetlocale+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lX11 $X_LIBS -lX11 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char _Xsetlocale (); int main (void) { return _Xsetlocale (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_X11__Xsetlocale=yes else $as_nop ac_cv_lib_X11__Xsetlocale=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_X11__Xsetlocale" >&5 printf "%s\n" "$ac_cv_lib_X11__Xsetlocale" >&6; } if test "x$ac_cv_lib_X11__Xsetlocale" = xyes then : printf "%s\n" "#define X_LOCALE 1" >>confdefs.h fi # Check if Xsetlocale() is available or not. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for XOpenOM in -lX11" >&5 printf %s "checking for XOpenOM in -lX11... " >&6; } if test ${ac_cv_lib_X11_XOpenOM+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lX11 $X_LIBS -lX11 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char XOpenOM (); int main (void) { return XOpenOM (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_X11_XOpenOM=yes else $as_nop ac_cv_lib_X11_XOpenOM=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_X11_XOpenOM" >&5 printf "%s\n" "$ac_cv_lib_X11_XOpenOM" >&6; } if test "x$ac_cv_lib_X11_XOpenOM" = xyes then : printf "%s\n" "#define HAVE_XOUTPUT_METHOD 1" >>confdefs.h fi # ******** iconv with_iconv=no with_iconv_type=no with_lib_iconv=no with_sys_iconv=no problem_iconv=": Explicitly disabled" # Check whether --enable-iconv was given. if test ${enable_iconv+y} then : enableval=$enable_iconv; ac_cv_iconv="$enableval" else $as_nop ac_cv_iconv="yes" fi if test ! x"$ac_cv_iconv" = xno; then # * first check for gnu libiconv $UNSET ac_cv_header_libiconv_h $UNSET ac_cv_lib_libiconv_libiconv_open smr_lib=iconv smr_header=iconv.h smr_lib=iconv # Check whether --with-iconv-library was given. if test ${with_iconv_library+y} then : withval=$with_iconv_library; if test "$withval" = yes; then with_iconv=yes iconv_LIBS="-l${smr_lib}" elif test "$withval" = no; then with_iconv=no iconv_LIBS= else with_iconv=yes if test -f "$withval"; then iconv_LIBS=$withval elif test -d "$withval"; then iconv_LIBS="-L$withval -l${smr_lib}" else as_fn_error $? "--with-iconv-library argument must be yes/no, file or directory" "$LINENO" 5 fi fi else $as_nop with_iconv=maybe iconv_LIBS="-l${smr_lib}" fi if test "$with_iconv" != no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libiconv_open in -liconv" >&5 printf %s "checking for libiconv_open in -liconv... " >&6; } if test ${ac_cv_lib_iconv_libiconv_open+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-liconv ${iconv_LIBS} $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char libiconv_open (); int main (void) { return libiconv_open (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_iconv_libiconv_open=yes else $as_nop ac_cv_lib_iconv_libiconv_open=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_iconv_libiconv_open" >&5 printf "%s\n" "$ac_cv_lib_iconv_libiconv_open" >&6; } if test "x$ac_cv_lib_iconv_libiconv_open" = xyes then : smr_havelib=yes else $as_nop smr_havelib=no; problem_iconv=": Can't find working lib$smr_lib" fi if test "$smr_havelib" = yes -a "$smr_header" != ""; then # Check whether --with-iconv-includes was given. if test ${with_iconv_includes+y} then : withval=$with_iconv_includes; if test -d "$withval"; then iconv_CFLAGS="-I${withval}" else as_fn_error $? "argument must be a directory" "$LINENO" 5 fi fi smr_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS ${iconv_CFLAGS}" for ac_header in $smr_header do : as_ac_Header=`printf "%s\n" "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes" then : cat >>confdefs.h <<_ACEOF #define `printf "%s\n" "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done CPPFLAGS=$smr_save_CPPFLAGS smr_safe=`echo "$smr_header" | sed 'y%./+-%__p_%'` if eval "test \"`echo '$ac_cv_header_'$smr_safe`\" != yes"; then smr_havelib=no problem_iconv=": Can't find working $smr_header" fi fi if test "$smr_havelib" = yes; then with_iconv=yes problem_iconv= else iconv_LIBS= iconv_CFLAGS= with_iconv=no fi else problem_iconv=": Explicitly disabled" fi if test ! x"$iconv_LIBS" = x; then printf "%s\n" "#define USE_LIBICONV 1" >>confdefs.h with_lib_iconv=yes fi # * check for system iconv ac_fn_c_check_func "$LINENO" "iconv_open" "ac_cv_func_iconv_open" if test "x$ac_cv_func_iconv_open" = xyes then : with_sys_iconv=yes fi if test x"$with_lib_iconv" = xyes && test x"$with_sys_iconv" = xyes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: *** Both system iconv and libiconv found: use libiconv" >&5 printf "%s\n" "$as_me: WARNING: *** Both system iconv and libiconv found: use libiconv" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: *** Use --with-iconv-library=no to use the system iconv" >&5 printf "%s\n" "$as_me: WARNING: *** Use --with-iconv-library=no to use the system iconv" >&2;} fi # * libiconv found check for libcharset to get the good iconv charset if test x"$with_lib_iconv" = xyes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking check for libcharset" >&5 printf %s "checking check for libcharset... " >&6; } ac_save_CFLAGS="$CFLAGS" ac_save_LIBS="$LIBS" CFLAGS="$CFLAGS $iconv_CFLAGS" LIBS="$LIBS $iconv_LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { const char *c; c = locale_charset (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : r=yes else $as_nop r=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $r" >&5 printf "%s\n" "$r" >&6; } if test "x$r" = "xyes"; then printf "%s\n" "#define HAVE_LIBCHARSET 1" >>confdefs.h fi CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi test x"$with_lib_iconv" = xyes -o x"$with_sys_iconv" = xyes && with_iconv=yes && problem_iconv="" test x"$with_lib_iconv" = xyes && with_iconv_type="yes (libiconv)" test x"$with_sys_iconv" = xyes && with_iconv_type="yes (from C library)" if test x"$with_iconv" = xno; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: *** " >&5 printf "%s\n" "$as_me: WARNING: *** " >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: *** No iconv() implementation found in C library or libiconv" >&5 printf "%s\n" "$as_me: WARNING: *** No iconv() implementation found in C library or libiconv" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: *** Please install libiconv ftp://ftp.gnu.org/pub/gnu/libiconv/" >&5 printf "%s\n" "$as_me: WARNING: *** Please install libiconv ftp://ftp.gnu.org/pub/gnu/libiconv/" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: *** " >&5 printf "%s\n" "$as_me: WARNING: *** " >&2;} fi if test x"$with_iconv" = xyes; then printf "%s\n" "#define HAVE_ICONV 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking check if second arg of iconv is const" >&5 printf %s "checking check if second arg of iconv is const... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include extern #if defined(__STDC__) size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); #else size_t iconv(); #endif int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : use_const=no else $as_nop use_const=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $use_const" >&5 printf "%s\n" "$use_const" >&6; } if test "x$use_const" = "xyes"; then printf "%s\n" "#define ICONV_ARG_CONST const" >>confdefs.h else printf "%s\n" "#define ICONV_ARG_CONST /**/" >>confdefs.h fi fi fi # ******** nl_langinfo and CODESET { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for nl_langinfo (CODESET)" >&5 printf %s "checking for nl_langinfo (CODESET)... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { char *codeset = nl_langinfo(CODESET); setlocale(LC_CTYPE, ""); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : printf "%s\n" "#define HAVE_CODESET 1" >>confdefs.h have_codeset=yes else $as_nop have_codeset=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_codeset" >&5 printf "%s\n" "$have_codeset" >&6; } # ********* fribidi # Check whether --enable-bidi was given. if test ${enable_bidi+y} then : enableval=$enable_bidi; if test x"$enableval" = xyes; then with_bidi="yes, check" else with_bidi="no" problem_bidi=": Explicitly disabled" fi else $as_nop with_bidi="not specified, check" fi fribidi_min_version=0.19.2 if test ! x"$with_bidi" = xno; then # Check whether --with-fribidi-bindir was given. if test ${with_fribidi_bindir+y} then : withval=$with_fribidi_bindir; FRIBIDI_BINDIR="$withval" else $as_nop FRIBIDI_BINDIR="." fi if test ! x"$PKG_CONFIG" = x && $PKG_CONFIG --exists "fribidi >= $fribidi_min_version"; then FRIBIDI_CONFIG="$PKG_CONFIG fribidi" else # Extract the first word of "fribidi-config", so it can be a program name with args. set dummy fribidi-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_FRIBIDI_CONFIG+y} then : printf %s "(cached) " >&6 else $as_nop case $FRIBIDI_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_FRIBIDI_CONFIG="$FRIBIDI_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="$FRIBIDI_BINDIR:$PATH" for as_dir in $as_dummy do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_FRIBIDI_CONFIG="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi FRIBIDI_CONFIG=$ac_cv_path_FRIBIDI_CONFIG if test -n "$FRIBIDI_CONFIG"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $FRIBIDI_CONFIG" >&5 printf "%s\n" "$FRIBIDI_CONFIG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test x"$FRIBIDI_CONFIG" = x; then with_bidi=no problem_bidi=": pkgconfig fribidi: fribidi version >= $fribidi_min_version needed." else Bidi_CFLAGS=`$FRIBIDI_CONFIG --cflags` Bidi_LIBS=`$FRIBIDI_CONFIG --libs` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for fribidi_log2vis in -lfribidi" >&5 printf %s "checking for fribidi_log2vis in -lfribidi... " >&6; } if test ${ac_cv_lib_fribidi_fribidi_log2vis+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lfribidi $Bidi_LIBS $Bidi_CFLAGS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char fribidi_log2vis (); int main (void) { return fribidi_log2vis (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_fribidi_fribidi_log2vis=yes else $as_nop ac_cv_lib_fribidi_fribidi_log2vis=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_fribidi_fribidi_log2vis" >&5 printf "%s\n" "$ac_cv_lib_fribidi_fribidi_log2vis" >&6; } if test "x$ac_cv_lib_fribidi_fribidi_log2vis" = xyes then : with_bidi=yes; problem_bidi= else $as_nop with_bidi=no; problem_bidi=": No good libs via $FRIBIDI_CONFIG" fi fi fi if test ! x"$with_bidi" = xno; then fribidi_in_path=yes ac_save_LIBS="$LIBS" LIBS="$LIBS $Bidi_LIBS" if test "$cross_compiling" = yes then : { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run test program while cross compiling See \`config.log' for more details" "$LINENO" 5; } else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main() { FriBidiChar *logical_unicode_str = (FriBidiChar *)malloc((4 + 1) * sizeof(FriBidiChar)); fribidi_charset_to_unicode( fribidi_parse_charset("iso8859-8"), "test", 4, logical_unicode_str); return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : : else $as_nop fribidi_in_path=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi LIBS="$ac_save_LIBS" if test ! x"$fribidi_in_path" = xyes; then ac_save_CFLAGS="$CFLAGS" ac_save_LIBS="$LIBS" CFLAGS="$CFLAGS $Bidi_CFLAGS" LIBS="$LIBS $Bidi_LIBS" if test "$cross_compiling" = yes then : { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run test program while cross compiling See \`config.log' for more details" "$LINENO" 5; } else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main() { FriBidiChar *logical_unicode_str = (FriBidiChar *)malloc((4 + 1) * sizeof(FriBidiChar)); fribidi_charset_to_unicode( fribidi_parse_charset("iso8859-8"), "test", 4, logical_unicode_str); return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : : else $as_nop with_bidi=no; problem_bidi=": Bad fribidi version, see config.log" fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi if test ! x"$fribidi_in_path" = xno; then Bidi_CFLAGS= Bidi_LIBS=-lfribidi fi fi if test x"$with_bidi" = xno; then Bidi_CFLAGS= Bidi_LIBS= else printf "%s\n" "#define HAVE_BIDI 1" >>confdefs.h if test "$cross_compiling" = yes then : { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run test program while cross compiling See \`config.log' for more details" "$LINENO" 5; } else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main(int c, char **v) { return FRIBIDI_CHARSET_NOT_FOUND * 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : printf "%s\n" "#define FRIBIDI_CHARSET_SPELLING 1" >>confdefs.h fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi # ********* perllib with_perllib="yes" problem_perllib="" FVWM_PERLLIB=perllib # Check whether --enable-perllib was given. if test ${enable_perllib+y} then : enableval=$enable_perllib; if test x"$enableval" = xno; then with_perllib="no" problem_perllib=": Explicitly disabled" FVWM_PERLLIB="" fi fi # ******* gettext ALL_LINGUAS="ar da de fr sv_SE zh_CN ru es" FVWM_DOMAIN="fvwm" FVWMSCRIPT_DOMAIN="FvwmScript" ALL_DOMAINS="$FVWM_DOMAIN $FVWMTASKBAR_DOMAIN $FVWMSCRIPT_DOMAIN" LOCALEDIR="$FVWM_DATADIR/locale" with_gettext="yes" problem_gettext="" # Check whether --enable-nls was given. if test ${enable_nls+y} then : enableval=$enable_nls; if test x"$enableval" = xno; then with_gettext="no" problem_gettext=": Explicitly disabled" fi fi if test ! x"$with_gettext" = xno; then MKINSTALLDIRS= if test -n "$ac_aux_dir"; then MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" fi if test -z "$MKINSTALLDIRS"; then MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" fi # Extract the first word of "msgfmt", so it can be a program name with args. set dummy msgfmt; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_MSGFMT+y} then : printf %s "(cached) " >&6 else $as_nop case "$MSGFMT" in /*) ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. ;; *) IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" for ac_dir in $PATH; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then if $ac_dir/$ac_word --statistics /dev/null >/dev/null 2>&1 && (if $ac_dir/$ac_word --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then ac_cv_path_MSGFMT="$ac_dir/$ac_word" break fi fi done IFS="$ac_save_ifs" test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT=":" ;; esac fi MSGFMT="$ac_cv_path_MSGFMT" if test "$MSGFMT" != ":"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MSGFMT" >&5 printf "%s\n" "$MSGFMT" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "gmsgfmt", so it can be a program name with args. set dummy gmsgfmt; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_GMSGFMT+y} then : printf %s "(cached) " >&6 else $as_nop case $GMSGFMT in [\\/]* | ?:[\\/]*) ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_GMSGFMT="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" ;; esac fi GMSGFMT=$ac_cv_path_GMSGFMT if test -n "$GMSGFMT"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $GMSGFMT" >&5 printf "%s\n" "$GMSGFMT" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # Extract the first word of "xgettext", so it can be a program name with args. set dummy xgettext; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_XGETTEXT+y} then : printf %s "(cached) " >&6 else $as_nop case "$XGETTEXT" in /*) ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. ;; *) IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" for ac_dir in $PATH; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then if $ac_dir/$ac_word --omit-header --copyright-holder= /dev/null >/dev/null 2>&1 && (if $ac_dir/$ac_word --omit-header --copyright-holder= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then ac_cv_path_XGETTEXT="$ac_dir/$ac_word" break fi fi done IFS="$ac_save_ifs" test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" ;; esac fi XGETTEXT="$ac_cv_path_XGETTEXT" if test "$XGETTEXT" != ":"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $XGETTEXT" >&5 printf "%s\n" "$XGETTEXT" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi rm -f messages.po # Extract the first word of "msgmerge", so it can be a program name with args. set dummy msgmerge; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_MSGMERGE+y} then : printf %s "(cached) " >&6 else $as_nop case "$MSGMERGE" in /*) ac_cv_path_MSGMERGE="$MSGMERGE" # Let the user override the test with a path. ;; *) IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" for ac_dir in $PATH; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then if $ac_dir/$ac_word --update -q /dev/null /dev/null >/dev/null 2>&1; then ac_cv_path_MSGMERGE="$ac_dir/$ac_word" break fi fi done IFS="$ac_save_ifs" test -z "$ac_cv_path_MSGMERGE" && ac_cv_path_MSGMERGE=":" ;; esac fi MSGMERGE="$ac_cv_path_MSGMERGE" if test "$MSGMERGE" != ":"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MSGMERGE" >&5 printf "%s\n" "$MSGMERGE" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "$GMSGFMT" != ":"; then if $GMSGFMT --statistics /dev/null >/dev/null 2>&1 && (if $GMSGFMT --statistics /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then : ; else GMSGFMT=`echo "$GMSGFMT" | sed -e 's,^.*/,,'` { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: found $GMSGFMT program is not GNU msgfmt; ignore it" >&5 printf "%s\n" "found $GMSGFMT program is not GNU msgfmt; ignore it" >&6; } GMSGFMT=":" fi fi if test "$XGETTEXT" != ":"; then if $XGETTEXT --omit-header --copyright-holder= /dev/null >/dev/null 2>&1 && (if $XGETTEXT --omit-header --copyright-holder= /dev/null 2>&1 >/dev/null | grep usage >/dev/null; then exit 1; else exit 0; fi); then : ; else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: found xgettext program is not GNU xgettext; ignore it" >&5 printf "%s\n" "found xgettext program is not GNU xgettext; ignore it" >&6; } XGETTEXT=":" fi rm -f messages.po fi # Extract the first word of "msguniq", so it can be a program name with args. set dummy msguniq; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_MSGUNIQ+y} then : printf %s "(cached) " >&6 else $as_nop case $MSGUNIQ in [\\/]* | ?:[\\/]*) ac_cv_path_MSGUNIQ="$MSGUNIQ" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_MSGUNIQ="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_MSGUNIQ" && ac_cv_path_MSGUNIQ="$MSGUNIQ" ;; esac fi MSGUNIQ=$ac_cv_path_MSGUNIQ if test -n "$MSGUNIQ"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $MSGUNIQ" >&5 printf "%s\n" "$MSGUNIQ" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for NLS fvwm messages catalogs" >&5 printf %s "checking for NLS fvwm messages catalogs... " >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ALL_LINGUAS" >&5 printf "%s\n" "$ALL_LINGUAS" >&6; } POFILES= GMOFILES= UPDATEPOFILES= DUMMYPOFILES= for lang in $ALL_LINGUAS; do for dom in $ALL_DOMAINS; do POFILES="$POFILES $dom.$lang.po" GMOFILES="$GMOFILES $dom.$lang.gmo" UPDATEPOFILES="$UPDATEPOFILES $dom.$lang.po-update" DUMMYPOFILES="$DUMMYPOFILES $dom.$lang.nop" done done # CATALOGS depends on both $ac_dir and the user's LINGUAS environment variable. INST_LINGUAS= { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for NLS desired catalogs to be installed" >&5 printf %s "checking for NLS desired catalogs to be installed... " >&6; } #if test "%UNSET%" != "$LINGUAS"; then # FIXME: How to check if LINGUAS has been *set* to "" if test -n "$LINGUAS"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $LINGUAS" >&5 printf "%s\n" "$LINGUAS" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: all" >&5 printf "%s\n" "all" >&6; } fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for NLS messages catalogs to be installed" >&5 printf %s "checking for NLS messages catalogs to be installed... " >&6; } if test -n "$ALL_LINGUAS"; then for presentlang in $ALL_LINGUAS; do useit=no #if test "%UNSET%" != "$LINGUAS"; then if test -n "$LINGUAS"; then desiredlanguages="$LINGUAS" else desiredlanguages="$ALL_LINGUAS" fi for desiredlang in $desiredlanguages; do # Use the presentlang catalog if desiredlang is # a. equal to presentlang, or # b. a variant of presentlang (because in this case, # presentlang can be used as a fallback for messages # which are not translated in the desiredlang catalog). case "$desiredlang" in "$presentlang"*) useit=yes;; esac done if test $useit = yes; then INST_LINGUAS="$INST_LINGUAS $presentlang" fi done fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $INST_LINGUAS" >&5 printf "%s\n" "$INST_LINGUAS" >&6; } CATALOGS= if test -n "$INST_LINGUAS"; then for lang in $INST_LINGUAS; do CATALOGS="$CATALOGS $lang.gmo" done fi intl_LIBS= intl_CFLAGS= POSUB= found_gettext=yes $UNSET ac_cv_header_intl_h $UNSET ac_cv_func_gettext $UNSET ac_cv_func_bindtextdomain $UNSET ac_cv_func_textdomain $UNSET ac_cv_func_dgettext #bind_textdomain_codeset ac_fn_c_check_header_compile "$LINENO" "libintl.h" "ac_cv_header_libintl_h" "$ac_includes_default" if test "x$ac_cv_header_libintl_h" = xyes then : for ac_func in gettext bindtextdomain textdomain dgettext do : as_ac_var=`printf "%s\n" "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes" then : cat >>confdefs.h <<_ACEOF #define `printf "%s\n" "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF else $as_nop found_gettext=no fi done else $as_nop found_gettext=no fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gnu gettext in libc" >&5 printf %s "checking for gnu gettext in libc... " >&6; } if test x"$found_gettext" = "xyes"; then problem_gettext=" (libc)" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if a simple gettext program link" >&5 printf %s "checking if a simple gettext program link... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { const char *c; c = gettext("foo"); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : found_gettext=yes;problem_gettext=" (libc)" else $as_nop found_gettext=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $found_gettext" >&5 printf "%s\n" "$found_gettext" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test x"$found_gettext" = xno; then $UNSET ac_cv_header_intl_h $UNSET ac_cv_lib_intl_bindtextdomain $UNSET ac_cv_lib_intl_textdomain $UNSET ac_cv_lib_intl_dgettext smr_lib=intl smr_header=libintl.h smr_lib=intl # Check whether --with-intl-library was given. if test ${with_intl_library+y} then : withval=$with_intl_library; if test "$withval" = yes; then with_intl=yes intl_LIBS="-l${smr_lib}" elif test "$withval" = no; then with_intl=no intl_LIBS= else with_intl=yes if test -f "$withval"; then intl_LIBS=$withval elif test -d "$withval"; then intl_LIBS="-L$withval -l${smr_lib}" else as_fn_error $? "--with-intl-library argument must be yes/no, file or directory" "$LINENO" 5 fi fi else $as_nop with_intl=maybe intl_LIBS="-l${smr_lib}" fi if test "$with_intl" != no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for bindtextdomain in -lintl" >&5 printf %s "checking for bindtextdomain in -lintl... " >&6; } if test ${ac_cv_lib_intl_bindtextdomain+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lintl ${intl_LIBS} $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char bindtextdomain (); int main (void) { return bindtextdomain (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_intl_bindtextdomain=yes else $as_nop ac_cv_lib_intl_bindtextdomain=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_bindtextdomain" >&5 printf "%s\n" "$ac_cv_lib_intl_bindtextdomain" >&6; } if test "x$ac_cv_lib_intl_bindtextdomain" = xyes then : smr_havelib=yes else $as_nop smr_havelib=no; problem_intl=": Can't find working lib$smr_lib" fi if test "$smr_havelib" = yes -a "$smr_header" != ""; then # Check whether --with-intl-includes was given. if test ${with_intl_includes+y} then : withval=$with_intl_includes; if test -d "$withval"; then intl_CFLAGS="-I${withval}" else as_fn_error $? "argument must be a directory" "$LINENO" 5 fi fi smr_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS ${intl_CFLAGS}" for ac_header in $smr_header do : as_ac_Header=`printf "%s\n" "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes" then : cat >>confdefs.h <<_ACEOF #define `printf "%s\n" "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done CPPFLAGS=$smr_save_CPPFLAGS smr_safe=`echo "$smr_header" | sed 'y%./+-%__p_%'` if eval "test \"`echo '$ac_cv_header_'$smr_safe`\" != yes"; then smr_havelib=no problem_intl=": Can't find working $smr_header" fi fi if test "$smr_havelib" = yes; then with_intl=yes problem_intl= else intl_LIBS= intl_CFLAGS= with_intl=no fi else problem_intl=": Explicitly disabled" fi if test x"$intl_LIBS" != x; then no_textdomain=no no_dgettext=no ac_save_CFLAGS="$CFLAGS" ac_save_LIBS="$LIBS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for textdomain in -lintl" >&5 printf %s "checking for textdomain in -lintl... " >&6; } if test ${ac_cv_lib_intl_textdomain+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lintl $intl_LIBS $iconv_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char textdomain (); int main (void) { return textdomain (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_intl_textdomain=yes else $as_nop ac_cv_lib_intl_textdomain=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_textdomain" >&5 printf "%s\n" "$ac_cv_lib_intl_textdomain" >&6; } if test "x$ac_cv_lib_intl_textdomain" = xyes then : printf "%s\n" "#define HAVE_LIBINTL 1" >>confdefs.h LIBS="-lintl $LIBS" else $as_nop no_textdomain=yes fi if test "$no_textdomain" != "yes"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dgettext in -lintl" >&5 printf %s "checking for dgettext in -lintl... " >&6; } if test ${ac_cv_lib_intl_dgettext+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lintl $intl_LIBS $iconv_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char dgettext (); int main (void) { return dgettext (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_intl_dgettext=yes else $as_nop ac_cv_lib_intl_dgettext=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_dgettext" >&5 printf "%s\n" "$ac_cv_lib_intl_dgettext" >&6; } if test "x$ac_cv_lib_intl_dgettext" = xyes then : printf "%s\n" "#define HAVE_LIBINTL 1" >>confdefs.h LIBS="-lintl $LIBS" else $as_nop no_dgettext=yes fi if test "$no_dgettext" != "yes"; then CFLAGS="$CFLAGS $intl_LIBS $iconv_LIBS" LIBS="$LIBS $intl_LIBS $iconv_LIBS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if a simple gettext program link" >&5 printf %s "checking if a simple gettext program link... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { const char *c; c = gettext("foo"); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : found_gettext=yes;problem_gettext=" (intl library)" else $as_nop found_gettext=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $found_gettext" >&5 printf "%s\n" "$found_gettext" >&6; } fi fi CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi fi if test "$found_gettext" = "yes"; then CATOBJEXT=.gmo USE_NLS=yes POSUB=po else USE_NLS=no fi if test x"$USE_NLS" = "xyes"; then printf "%s\n" "#define HAVE_NLS 1" >>confdefs.h else with_gettext="no" problem_gettext=": Failed to detected GNU gettext" fi else USE_NLS=no fi # libs and buil # programs for devel #catalogs # Check for REQUIRED headers and functions before going any # further. # The module interface uses variadic functions for message passing. ac_fn_c_check_header_compile "$LINENO" "stdarg.h" "ac_cv_header_stdarg_h" "$ac_includes_default" if test "x$ac_cv_header_stdarg_h" = xyes then : printf "%s\n" "#define HAVE_STDARG_H 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "vfprintf" "ac_cv_func_vfprintf" if test "x$ac_cv_func_vfprintf" = xyes then : printf "%s\n" "#define HAVE_VFPRINTF 1" >>confdefs.h fi if test x$ac_cv_header_stdarg_h = xno -o \ $ac_cv_func_vfprintf = no; then as_fn_error $? "stdarg.h and vfprintf required" "$LINENO" 5 fi # For reaping children, fvwm needs either waitpid() or wait3() # Some extra modules may need wait4() too ac_fn_c_check_func "$LINENO" "waitpid" "ac_cv_func_waitpid" if test "x$ac_cv_func_waitpid" = xyes then : printf "%s\n" "#define HAVE_WAITPID 1" >>confdefs.h fi if test x$ac_cv_func_waitpid = xno; then ac_fn_c_check_func "$LINENO" "wait3" "ac_cv_func_wait3" if test "x$ac_cv_func_wait3" = xyes then : printf "%s\n" "#define HAVE_WAIT3 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "wait4" "ac_cv_func_wait4" if test "x$ac_cv_func_wait4" = xyes then : printf "%s\n" "#define HAVE_WAIT4 1" >>confdefs.h fi if test x$ac_cv_func_wait3 = xno; then as_fn_error $? "Either waitpid or wait3 function is required" "$LINENO" 5 fi fi # C89/C99 signal handling ac_fn_c_check_func "$LINENO" "sigsetjmp" "ac_cv_func_sigsetjmp" if test "x$ac_cv_func_sigsetjmp" = xyes then : printf "%s\n" "#define HAVE_SIGSETJMP 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "siglongjmp" "ac_cv_func_siglongjmp" if test "x$ac_cv_func_siglongjmp" = xyes then : printf "%s\n" "#define HAVE_SIGLONGJMP 1" >>confdefs.h fi # Look harder for a C preprocessor for FvwmCpp # Extract the first word of "cpp", so it can be a program name with args. set dummy cpp; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_FVWM_CPP+y} then : printf %s "(cached) " >&6 else $as_nop case $FVWM_CPP in [\\/]* | ?:[\\/]*) ac_cv_path_FVWM_CPP="$FVWM_CPP" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="$PATH:/lib:/usr/lib:/usr/ccs/lib" for as_dir in $as_dummy do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_FVWM_CPP="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_FVWM_CPP" && ac_cv_path_FVWM_CPP="no" ;; esac fi FVWM_CPP=$ac_cv_path_FVWM_CPP if test -n "$FVWM_CPP"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $FVWM_CPP" >&5 printf "%s\n" "$FVWM_CPP" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test x"$FVWM_CPP" = xno; then FVWM_CPP= { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cannot locate a C preprocessor: run FvwmCpp with -cppprog" >&5 printf "%s\n" "$as_me: WARNING: cannot locate a C preprocessor: run FvwmCpp with -cppprog" >&2;} fi # Finish checking for programs. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 printf %s "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 printf "%s\n" "no, using $LN_S" >&6; } fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 printf %s "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`printf "%s\n" "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval test \${ac_cv_prog_make_${ac_make}_set+y} then : printf %s "(cached) " >&6 else $as_nop cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } SET_MAKE= else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_RANLIB+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 printf "%s\n" "$RANLIB" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_RANLIB+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 printf "%s\n" "$ac_ct_RANLIB" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi # Checks for header files. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 printf %s "checking for grep that handles long lines and -e... " >&6; } if test ${ac_cv_path_GREP+y} then : printf %s "(cached) " >&6 else $as_nop if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in grep ggrep do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 printf %s 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" printf "%s\n" 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 printf "%s\n" "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" # Autoupdate added the next two lines to ensure that your configure # script's behavior did not change. They are probably safe to remove. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 printf %s "checking for egrep... " >&6; } if test ${ac_cv_path_EGREP+y} then : printf %s "(cached) " >&6 else $as_nop if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in egrep do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 printf %s 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" printf "%s\n" 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 printf "%s\n" "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sys/wait.h that is POSIX.1 compatible" >&5 printf %s "checking for sys/wait.h that is POSIX.1 compatible... " >&6; } if test ${ac_cv_header_sys_wait_h+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #ifndef WEXITSTATUS # define WEXITSTATUS(stat_val) ((unsigned int) (stat_val) >> 8) #endif #ifndef WIFEXITED # define WIFEXITED(stat_val) (((stat_val) & 255) == 0) #endif int main (void) { int s; wait (&s); s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_header_sys_wait_h=yes else $as_nop ac_cv_header_sys_wait_h=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_sys_wait_h" >&5 printf "%s\n" "$ac_cv_header_sys_wait_h" >&6; } if test $ac_cv_header_sys_wait_h = yes; then printf "%s\n" "#define HAVE_SYS_WAIT_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" if test "x$ac_cv_header_stdlib_h" = xyes then : printf "%s\n" "#define HAVE_STDLIB_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "fcntl.h" "ac_cv_header_fcntl_h" "$ac_includes_default" if test "x$ac_cv_header_fcntl_h" = xyes then : printf "%s\n" "#define HAVE_FCNTL_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "limits.h" "ac_cv_header_limits_h" "$ac_includes_default" if test "x$ac_cv_header_limits_h" = xyes then : printf "%s\n" "#define HAVE_LIMITS_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "malloc.h" "ac_cv_header_malloc_h" "$ac_includes_default" if test "x$ac_cv_header_malloc_h" = xyes then : printf "%s\n" "#define HAVE_MALLOC_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "string.h" "ac_cv_header_string_h" "$ac_includes_default" if test "x$ac_cv_header_string_h" = xyes then : printf "%s\n" "#define HAVE_STRING_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "memory.h" "ac_cv_header_memory_h" "$ac_includes_default" if test "x$ac_cv_header_memory_h" = xyes then : printf "%s\n" "#define HAVE_MEMORY_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "unistd.h" "ac_cv_header_unistd_h" "$ac_includes_default" if test "x$ac_cv_header_unistd_h" = xyes then : printf "%s\n" "#define HAVE_UNISTD_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "stdint.h" "ac_cv_header_stdint_h" "$ac_includes_default" if test "x$ac_cv_header_stdint_h" = xyes then : printf "%s\n" "#define HAVE_STDINT_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "inttypes.h" "ac_cv_header_inttypes_h" "$ac_includes_default" if test "x$ac_cv_header_inttypes_h" = xyes then : printf "%s\n" "#define HAVE_INTTYPES_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "getopt.h" "ac_cv_header_getopt_h" "$ac_includes_default" if test "x$ac_cv_header_getopt_h" = xyes then : printf "%s\n" "#define HAVE_GETOPT_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/select.h" "ac_cv_header_sys_select_h" "$ac_includes_default" if test "x$ac_cv_header_sys_select_h" = xyes then : printf "%s\n" "#define HAVE_SYS_SELECT_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/systeminfo.h" "ac_cv_header_sys_systeminfo_h" "$ac_includes_default" if test "x$ac_cv_header_sys_systeminfo_h" = xyes then : printf "%s\n" "#define HAVE_SYS_SYSTEMINFO_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/time.h" "ac_cv_header_sys_time_h" "$ac_includes_default" if test "x$ac_cv_header_sys_time_h" = xyes then : printf "%s\n" "#define HAVE_SYS_TIME_H 1" >>confdefs.h fi # Checks for typedefs, structures, and compiler characteristics. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 printf %s "checking for an ANSI C-conforming const... " >&6; } if test ${ac_cv_c_const+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { #ifndef __cplusplus /* Ultrix mips cc rejects this sort of thing. */ typedef int charset[2]; const charset cs = { 0, 0 }; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* IBM XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; pcpcc = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; { /* SCO 3.2v4 cc rejects this sort of thing. */ char tx; char *t = &tx; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; if (s) return 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* IBM XL C 1.02.0.0 rejects this sort of thing, saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; } bx; struct s *b = &bx; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; if (!foo) return 0; } return !cs[0] && !zero.x; #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_c_const=yes else $as_nop ac_cv_c_const=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 printf "%s\n" "$ac_cv_c_const" >&6; } if test $ac_cv_c_const = no; then printf "%s\n" "#define const /**/" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 printf %s "checking for inline... " >&6; } if test ${ac_cv_c_inline+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo (void) {return 0; } $ac_kw foo_t foo (void) {return 0; } #endif _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_c_inline=$ac_kw fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext test "$ac_cv_c_inline" != no && break done fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 printf "%s\n" "$ac_cv_c_inline" >&6; } case $ac_cv_c_inline in inline | yes) ;; *) case $ac_cv_c_inline in no) ac_val=;; *) ac_val=$ac_cv_c_inline;; esac cat >>confdefs.h <<_ACEOF #ifndef __cplusplus #define inline $ac_val #endif _ACEOF ;; esac ac_fn_c_check_type "$LINENO" "off_t" "ac_cv_type_off_t" "$ac_includes_default" if test "x$ac_cv_type_off_t" = xyes then : else $as_nop printf "%s\n" "#define off_t long int" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default " if test "x$ac_cv_type_pid_t" = xyes then : else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined _WIN64 && !defined __CYGWIN__ LLP64 #endif int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_pid_type='int' else $as_nop ac_pid_type='__int64' fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext printf "%s\n" "#define pid_t $ac_pid_type" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" if test "x$ac_cv_type_size_t" = xyes then : else $as_nop printf "%s\n" "#define size_t unsigned int" >>confdefs.h fi # Obsolete code to be removed. if test $ac_cv_header_sys_time_h = yes; then printf "%s\n" "#define TIME_WITH_SYS_TIME 1" >>confdefs.h fi # End of obsolete code. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking return type of signal handlers" >&5 printf %s "checking return type of signal handlers... " >&6; } if test ${ac_cv_type_signal+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { return *(signal (0, 0)) (0) == 1; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_type_signal=int else $as_nop ac_cv_type_signal=void fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_signal" >&5 printf "%s\n" "$ac_cv_type_signal" >&6; } printf "%s\n" "#define RETSIGTYPE $ac_cv_type_signal" >>confdefs.h ac_fn_c_find_intX_t "$LINENO" "16" "ac_cv_c_int16_t" case $ac_cv_c_int16_t in #( no|yes) ;; #( *) printf "%s\n" "#define int16_t $ac_cv_c_int16_t" >>confdefs.h ;; esac ac_fn_c_find_uintX_t "$LINENO" "16" "ac_cv_c_uint16_t" case $ac_cv_c_uint16_t in #( no|yes) ;; #( *) printf "%s\n" "#define uint16_t $ac_cv_c_uint16_t" >>confdefs.h ;; esac # Checks for library functions. for ac_func in strftime do : ac_fn_c_check_func "$LINENO" "strftime" "ac_cv_func_strftime" if test "x$ac_cv_func_strftime" = xyes then : printf "%s\n" "#define HAVE_STRFTIME 1" >>confdefs.h else $as_nop # strftime is in -lintl on SCO UNIX. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for strftime in -lintl" >&5 printf %s "checking for strftime in -lintl... " >&6; } if test ${ac_cv_lib_intl_strftime+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lintl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char strftime (); int main (void) { return strftime (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_intl_strftime=yes else $as_nop ac_cv_lib_intl_strftime=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_strftime" >&5 printf "%s\n" "$ac_cv_lib_intl_strftime" >&6; } if test "x$ac_cv_lib_intl_strftime" = xyes then : printf "%s\n" "#define HAVE_STRFTIME 1" >>confdefs.h LIBS="-lintl $LIBS" fi fi done { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether setpgrp requires zero arguments" >&5 printf %s "checking whether setpgrp requires zero arguments... " >&6; } if test ${ac_cv_func_setpgrp_void+y} then : printf %s "(cached) " >&6 else $as_nop # Call it with two arguments. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main (void) { setpgrp(0, 0); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_func_setpgrp_void=no else $as_nop ac_cv_func_setpgrp_void=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_setpgrp_void" >&5 printf "%s\n" "$ac_cv_func_setpgrp_void" >&6; } if test $ac_cv_func_setpgrp_void = yes; then printf "%s\n" "#define SETPGRP_VOID 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday" if test "x$ac_cv_func_gettimeofday" = xyes then : printf "%s\n" "#define HAVE_GETTIMEOFDAY 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "mkfifo" "ac_cv_func_mkfifo" if test "x$ac_cv_func_mkfifo" = xyes then : printf "%s\n" "#define HAVE_MKFIFO 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "putenv" "ac_cv_func_putenv" if test "x$ac_cv_func_putenv" = xyes then : printf "%s\n" "#define HAVE_PUTENV 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "setvbuf" "ac_cv_func_setvbuf" if test "x$ac_cv_func_setvbuf" = xyes then : printf "%s\n" "#define HAVE_SETVBUF 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "socket" "ac_cv_func_socket" if test "x$ac_cv_func_socket" = xyes then : printf "%s\n" "#define HAVE_SOCKET 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "waitpid" "ac_cv_func_waitpid" if test "x$ac_cv_func_waitpid" = xyes then : printf "%s\n" "#define HAVE_WAITPID 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "strdup" "ac_cv_func_strdup" if test "x$ac_cv_func_strdup" = xyes then : printf "%s\n" "#define HAVE_STRDUP 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "strstr" "ac_cv_func_strstr" if test "x$ac_cv_func_strstr" = xyes then : printf "%s\n" "#define HAVE_STRSTR 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "strtol" "ac_cv_func_strtol" if test "x$ac_cv_func_strtol" = xyes then : printf "%s\n" "#define HAVE_STRTOL 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "memmove" "ac_cv_func_memmove" if test "x$ac_cv_func_memmove" = xyes then : printf "%s\n" "#define HAVE_MEMMOVE 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "memcpy" "ac_cv_func_memcpy" if test "x$ac_cv_func_memcpy" = xyes then : printf "%s\n" "#define HAVE_MEMCPY 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "strchr" "ac_cv_func_strchr" if test "x$ac_cv_func_strchr" = xyes then : printf "%s\n" "#define HAVE_STRCHR 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "sysconf" "ac_cv_func_sysconf" if test "x$ac_cv_func_sysconf" = xyes then : printf "%s\n" "#define HAVE_SYSCONF 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "uname" "ac_cv_func_uname" if test "x$ac_cv_func_uname" = xyes then : printf "%s\n" "#define HAVE_UNAME 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "div" "ac_cv_func_div" if test "x$ac_cv_func_div" = xyes then : printf "%s\n" "#define HAVE_DIV 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "sigaction" "ac_cv_func_sigaction" if test "x$ac_cv_func_sigaction" = xyes then : printf "%s\n" "#define HAVE_SIGACTION 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "siginterrupt" "ac_cv_func_siginterrupt" if test "x$ac_cv_func_siginterrupt" = xyes then : printf "%s\n" "#define HAVE_SIGINTERRUPT 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "getpwuid" "ac_cv_func_getpwuid" if test "x$ac_cv_func_getpwuid" = xyes then : printf "%s\n" "#define HAVE_GETPWUID 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "setpgrp" "ac_cv_func_setpgrp" if test "x$ac_cv_func_setpgrp" = xyes then : printf "%s\n" "#define HAVE_SETPGRP 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "setpgid" "ac_cv_func_setpgid" if test "x$ac_cv_func_setpgid" = xyes then : printf "%s\n" "#define HAVE_SETPGID 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "lstat" "ac_cv_func_lstat" if test "x$ac_cv_func_lstat" = xyes then : printf "%s\n" "#define HAVE_LSTAT 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for sig_atomic_t" >&5 printf %s "checking for sig_atomic_t... " >&6; } if test ${ac_cv_type_sig_atomic_t+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #if STDC_HEADERS #include #include #endif #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "(^|[^a-zA-Z_0-9])sig_atomic_t[^a-zA-Z_0-9]" >/dev/null 2>&1 then : ac_cv_type_sig_atomic_t=yes else $as_nop ac_cv_type_$1=no fi rm -rf conftest* fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_sig_atomic_t" >&5 printf "%s\n" "$ac_cv_type_sig_atomic_t" >&6; } if test $ac_cv_type_sig_atomic_t = no; then printf "%s\n" "#define sig_atomic_t int" >>confdefs.h fi if test x$ac_cv_func_setvbuf = xyes; then if test ${ac_cv_func_setvbuf_reversed+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_func_setvbuf_reversed=no fi fi ac_fn_c_check_func "$LINENO" "select" "ac_cv_func_select" if test "x$ac_cv_func_select" = xyes then : printf "%s\n" "#define HAVE_SELECT 1" >>confdefs.h fi if test "$ac_cv_func_select" = yes; then ac_fn_c_check_header_compile "$LINENO" "unistd.h" "ac_cv_header_unistd_h" "$ac_includes_default" if test "x$ac_cv_header_unistd_h" = xyes then : printf "%s\n" "#define HAVE_UNISTD_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/types.h" "ac_cv_header_sys_types_h" "$ac_includes_default" if test "x$ac_cv_header_sys_types_h" = xyes then : printf "%s\n" "#define HAVE_SYS_TYPES_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/time.h" "ac_cv_header_sys_time_h" "$ac_includes_default" if test "x$ac_cv_header_sys_time_h" = xyes then : printf "%s\n" "#define HAVE_SYS_TIME_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/select.h" "ac_cv_header_sys_select_h" "$ac_includes_default" if test "x$ac_cv_header_sys_select_h" = xyes then : printf "%s\n" "#define HAVE_SYS_SELECT_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "sys/socket.h" "ac_cv_header_sys_socket_h" "$ac_includes_default" if test "x$ac_cv_header_sys_socket_h" = xyes then : printf "%s\n" "#define HAVE_SYS_SOCKET_H 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking argument types of select()" >&5 printf %s "checking argument types of select()... " >&6; } if test ${ac_cv_type_fd_set_size_t+y} then : printf %s "(cached) " >&6 else $as_nop if test ${ac_cv_type_fd_set+y} then : printf %s "(cached) " >&6 else $as_nop for ac_cv_type_fd_set in 'fd_set' 'int' 'void'; do for ac_cv_type_fd_set_size_t in 'int' 'size_t' 'unsigned long' 'unsigned'; do for ac_type_timeval in 'struct timeval' 'const struct timeval'; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_SYS_SELECT_H #include #endif #ifdef HAVE_SYS_SOCKET_H #include #endif int main (void) { extern select ($ac_cv_type_fd_set_size_t, $ac_cv_type_fd_set *, $ac_cv_type_fd_set *, $ac_cv_type_fd_set *, $ac_type_timeval *); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_found=yes ; break 3 else $as_nop ac_found=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext done done done fi fi if test "$ac_found" = no; then as_fn_error $? "can not determine argument types" "$LINENO" 5 fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: select($ac_cv_type_fd_set_size_t,$ac_cv_type_fd_set *,...)" >&5 printf "%s\n" "select($ac_cv_type_fd_set_size_t,$ac_cv_type_fd_set *,...)" >&6; } printf "%s\n" "#define fd_set_size_t $ac_cv_type_fd_set_size_t" >>confdefs.h ac_cast= if test "$ac_cv_type_fd_set" != fd_set; then # Arguments 2-4 are not fd_set. Some weirdo systems use fd_set type for # FD_SET macros, but insist that you cast the argument to select. I don't # understand why that might be, but it means we cannot define fd_set. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef HAVE_SYS_TIME_H #include #endif #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_SYS_SELECT_H #include #endif #ifdef HAVE_SYS_SOCKET_H #include #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "(^|[^a-zA-Z_0-9])fd_set[^a-zA-Z_0-9]" >/dev/null 2>&1 then : # We found fd_set type in a header, need special cast ac_cast="($ac_cv_type_fd_set *)" else $as_nop # No fd_set type; it is safe to define it printf "%s\n" "#define fd_set $ac_cv_type_fd_set" >>confdefs.h fi rm -rf conftest* fi printf "%s\n" "#define SELECT_FD_SET_CAST $ac_cast" >>confdefs.h fi if test ! x"$ac_cv_func_select" = xyes; then as_fn_error $? "select required" "$LINENO" 5 fi # check for mkstemp, see the discution on this subject on the fvwm workers # list (2001-02-16 and 2001-02-24) ac_fn_c_check_func "$LINENO" "mkstemp" "ac_cv_func_mkstemp" if test "x$ac_cv_func_mkstemp" = xyes then : printf "%s\n" "#define HAVE_MKSTEMP 1" >>confdefs.h fi has_safety_mkstemp=no { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if mkstemp is safe" >&5 printf %s "checking if mkstemp is safe... " >&6; } if test x$ac_cv_func_mkstemp != xno; then if test "$cross_compiling" = yes then : { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run test program while cross compiling See \`config.log' for more details" "$LINENO" 5; } else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main(void) { char template[128]; char template_orig[128]; int fd; sprintf(template, "configure-mkstemp-test.XXXXXX"); strcpy(template_orig, template); fd = mkstemp(template); if (fd == -1) { /* could not create temp file */ return 1; } if (strcmp(template, template_orig) == 0) { /* mkstemp broken */ return 2; } if (close(fd) != 0) { /* doh! */ return 3; } if (unlink(template)) { return 4; } /* mkstemp works properly */ return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : has_safety_mkstemp=yes else $as_nop has_safety_mkstemp=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi if test x$has_safety_mkstemp = xno; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define HAVE_SAFETY_MKSTEMP 1" >>confdefs.h fi # ********* IMLIB, GNOME # Check the availability of gdk-imlib # Check whether --with-imlib-prefix was given. if test ${with_imlib_prefix+y} then : withval=$with_imlib_prefix; imlib_prefix="$withval" else $as_nop imlib_prefix="" fi # Check whether --with-imlib-exec-prefix was given. if test ${with_imlib_exec_prefix+y} then : withval=$with_imlib_exec_prefix; imlib_exec_prefix="$withval" else $as_nop imlib_exec_prefix="" fi # Check whether --enable-imlibtest was given. if test ${enable_imlibtest+y} then : enableval=$enable_imlibtest; else $as_nop enable_imlibtest=yes fi if test x$imlib_exec_prefix != x ; then imlib_args="$imlib_args --exec-prefix=$imlib_exec_prefix" if test x${IMLIBCONF+set} != xset ; then IMLIBCONF=$imlib_exec_prefix/bin/imlib-config fi fi if test x$imlib_prefix != x ; then imlib_args="$imlib_args --prefix=$imlib_prefix" if test x${IMLIBCONF+set} != xset ; then IMLIBCONF=$imlib_prefix/bin/imlib-config fi fi # Extract the first word of "imlib-config", so it can be a program name with args. set dummy imlib-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_IMLIBCONF+y} then : printf %s "(cached) " >&6 else $as_nop case $IMLIBCONF in [\\/]* | ?:[\\/]*) ac_cv_path_IMLIBCONF="$IMLIBCONF" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_IMLIBCONF="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_IMLIBCONF" && ac_cv_path_IMLIBCONF="no" ;; esac fi IMLIBCONF=$ac_cv_path_IMLIBCONF if test -n "$IMLIBCONF"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $IMLIBCONF" >&5 printf "%s\n" "$IMLIBCONF" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi min_imlib_version=1.8.0 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GDK IMLIB - version >= $min_imlib_version" >&5 printf %s "checking for GDK IMLIB - version >= $min_imlib_version... " >&6; } no_imlib="" if test "$IMLIBCONF" = "no" ; then no_imlib=yes else GDK_IMLIB_CFLAGS=`$IMLIBCONF $imlibconf_args --cflags-gdk` GDK_IMLIB_LIBS=`$IMLIBCONF $imlibconf_args --libs-gdk` imlib_major_version=`$IMLIBCONF $imlib_args --version | \ sed 's/^[^0-9.]*\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*$/\1/'` imlib_minor_version=`$IMLIBCONF $imlib_args --version | \ sed 's/^[^0-9.]*\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*$/\2/'` if test "x$enable_imlibtest" = "xyes" ; then ac_save_CFLAGS="$CFLAGS" ac_save_LIBS="$LIBS" CFLAGS="$CFLAGS $GDK_IMLIB_CFLAGS" LIBS="$LIBS $GDK_IMLIB_LIBS" rm -f conf.imlibtest if test "$cross_compiling" = yes then : echo $ac_n "cross compiling; assumed OK... $ac_c" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include /* migo: originally it was GdkImLibColor with incorrect spelling */ GdkImlibImage testimage; int main () { int major, minor; char *tmp_version; system ("touch conf.gdkimlibtest"); /* HP/UX 9 (%@#!) writes to sscanf strings */ tmp_version = g_strdup("$min_imlib_version"); if (sscanf(tmp_version, "%d.%d", &major, &minor) != 2) { printf("%s, bad version string\n", "$min_imlib_version"); exit(1); } if (($imlib_major_version > major) || (($imlib_major_version == major) && ($imlib_minor_version > minor))) { return 0; } else { printf("\n*** 'imlib-config --version' returned %d.%d, but the minimum version\n", $imlib_major_version, $imlib_minor_version); printf("*** of IMLIB required is %d.%d. If imlib-config is correct, then it is\n", major, minor); printf("*** best to upgrade to the required version.\n"); printf("*** If imlib-config was wrong, set the environment variable IMLIBCONF\n"); printf("*** to point to the correct copy of imlib-config, and remove the file\n"); printf("*** config.cache before re-running configure\n"); return 1; } } _ACEOF if ac_fn_c_try_run "$LINENO" then : else $as_nop no_imlib=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi fi if test "x$no_imlib" = x ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } printf "%s\n" "#define GDK_IMLIB 1" >>confdefs.h else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } if test "$IMLIBCONF" = "no" ; then (echo "*** The imlib-config script installed by IMLIB could not be found" >&5) 2>/dev/null || \ echo "*** The imlib-config script installed by IMLIB could not be found" (echo "*** If IMLIB was installed in PREFIX, make sure PREFIX/bin is in" >&5) 2>/dev/null || \ echo "*** If IMLIB was installed in PREFIX, make sure PREFIX/bin is in" (echo "*** your path, or set the IMLIBCONF environment variable to the" >&5) 2>/dev/null || \ echo "*** your path, or set the IMLIBCONF environment variable to the" (echo "*** full path to imlib-config." >&5) 2>/dev/null || \ echo "*** full path to imlib-config." else if test -f conf.gdkimlibtest ; then : else (echo "*** Could not run IMLIB test program, checking why..." >&5) 2>/dev/null || \ echo "*** Could not run IMLIB test program, checking why..." CFLAGS="$CFLAGS $GDK_IMLIB_CFLAGS" LIBS="$LIBS $GDK_IMLIB_LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { return 0; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : (echo "*** The test program compiled, but did not run. This usually means" >&5) 2>/dev/null || \ echo "*** The test program compiled, but did not run. This usually means" (echo "*** that the run-time linker is not finding IMLIB or finding the wrong" >&5) 2>/dev/null || \ echo "*** that the run-time linker is not finding IMLIB or finding the wrong" (echo "*** version of IMLIB. If it is not finding IMLIB, you'll need to set your" >&5) 2>/dev/null || \ echo "*** version of IMLIB. If it is not finding IMLIB, you'll need to set your" (echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" >&5) 2>/dev/null || \ echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" (echo "*** to the installed location Also, make sure you have run ldconfig if that" >&5) 2>/dev/null || \ echo "*** to the installed location Also, make sure you have run ldconfig if that" (echo "*** is required on your system" >&5) 2>/dev/null || \ echo "*** is required on your system" (echo "***" >&5) 2>/dev/null || \ echo "***" (echo "*** If you have an old version installed, it is best to remove it, although" >&5) 2>/dev/null || \ echo "*** If you have an old version installed, it is best to remove it, although" (echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" >&5) 2>/dev/null || \ echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" else $as_nop (echo "*** The test program failed to compile or link. See the file config.log for the" >&5) 2>/dev/null || \ echo "*** The test program failed to compile or link. See the file config.log for the" (echo "*** exact error that occured. This usually means IMLIB was incorrectly installed" >&5) 2>/dev/null || \ echo "*** exact error that occured. This usually means IMLIB was incorrectly installed" (echo "*** or that you have moved IMLIB since it was installed. In the latter case, you" >&5) 2>/dev/null || \ echo "*** or that you have moved IMLIB since it was installed. In the latter case, you" (echo "*** may want to edit the imlib-config script: $IMLIBCONF" >&5) 2>/dev/null || \ echo "*** may want to edit the imlib-config script: $IMLIBCONF" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi fi GDK_IMLIB_CFLAGS="" GDK_IMLIB_LIBS="" : fi rm -f conf.gdkimlibtest if test x"$no_imlib" = x; then with_gdkimlib=yes problem_gdkimlib="" else with_gdkimlib=no problem_gdkimlib=": Failed on gdk-imlib, see config.log" fi # Define some compatibility macros needed for config.h. mg_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $X_CFLAGS" if test "$cross_compiling" = yes then : { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run test program while cross compiling See \`config.log' for more details" "$LINENO" 5; } else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main(int c, char **v) { #include #if defined XK_Page_Up && defined XK_Page_Down return 0; #else return 1; #endif } _ACEOF if ac_fn_c_try_run "$LINENO" then : : else $as_nop printf "%s\n" "#define COMPAT_OLD_KEYSYMDEF 1" >>confdefs.h fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi CPPFLAGS="$mg_save_CPPFLAGS" if test x"$with_stroke" = xyes; then mg_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $stroke_CFLAGS" if test "$cross_compiling" = yes then : { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run test program while cross compiling See \`config.log' for more details" "$LINENO" 5; } else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main(int c, char **v) { #include #if defined STROKE_MAX_SEQUENCE return 0; #else return 1; #endif } _ACEOF if ac_fn_c_try_run "$LINENO" then : : else $as_nop printf "%s\n" "#define COMPAT_OLD_LIBSTROKE 1" >>confdefs.h fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi CPPFLAGS="$mg_save_CPPFLAGS" fi # Allow building with dmalloc. Do this last to avoid screwing up any # other checks above. case "$ac_cv_dmalloc" in yes) ac_fn_c_check_header_compile "$LINENO" "dmalloc.h" "ac_cv_header_dmalloc_h" "$ac_includes_default" if test "x$ac_cv_header_dmalloc_h" = xyes then : printf "%s\n" "#define HAVE_DMALLOC_H 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for dmalloc_shutdown in -ldmalloc" >&5 printf %s "checking for dmalloc_shutdown in -ldmalloc... " >&6; } if test ${ac_cv_lib_dmalloc_dmalloc_shutdown+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-ldmalloc $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char dmalloc_shutdown (); int main (void) { return dmalloc_shutdown (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_dmalloc_dmalloc_shutdown=yes else $as_nop ac_cv_lib_dmalloc_dmalloc_shutdown=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dmalloc_dmalloc_shutdown" >&5 printf "%s\n" "$ac_cv_lib_dmalloc_dmalloc_shutdown" >&6; } if test "x$ac_cv_lib_dmalloc_dmalloc_shutdown" = xyes then : printf "%s\n" "#define HAVE_LIBDMALLOC 1" >>confdefs.h LIBS="-ldmalloc $LIBS" fi CPPFLAGS="$CPPFLAGS -DDMALLOC_FUNC_CHECK" ;; esac # Allow building with efence. case "$ac_cv_efence" in yes) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for malloc in -lefence" >&5 printf %s "checking for malloc in -lefence... " >&6; } if test ${ac_cv_lib_efence_malloc+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lefence $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char malloc (); int main (void) { return malloc (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_efence_malloc=yes else $as_nop ac_cv_lib_efence_malloc=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_efence_malloc" >&5 printf "%s\n" "$ac_cv_lib_efence_malloc" >&6; } if test "x$ac_cv_lib_efence_malloc" = xyes then : printf "%s\n" "#define HAVE_LIBEFENCE 1" >>confdefs.h LIBS="-lefence $LIBS" fi ;; esac # some explicit definitions for config.h file # mainly for fvwm-config ac_config_files="$ac_config_files Makefile libs/Makefile fvwm/Makefile modules/Makefile bin/fvwm-bug.1 bin/fvwm-config.1 bin/fvwm-convert-2.6.1 bin/fvwm-menu-desktop.1 bin/fvwm-root.1 modules/FvwmAnimate/FvwmAnimate.1 modules/FvwmAuto/FvwmAuto.1 modules/FvwmBacker/FvwmBacker.1 modules/FvwmBanner/FvwmBanner.1 modules/FvwmButtons/FvwmButtons.1 modules/FvwmCommand/FvwmCommand.1 modules/FvwmConsole/FvwmConsole.1 modules/FvwmConsole/FvwmConsoleC.pl.1 modules/FvwmCpp/FvwmCpp.1 modules/FvwmEvent/FvwmEvent.1 modules/FvwmForm/FvwmForm.1 modules/FvwmIconMan/FvwmIconMan.1 modules/FvwmIdent/FvwmIdent.1 modules/FvwmM4/FvwmM4.1 modules/FvwmPager/FvwmPager.1 modules/FvwmProxy/FvwmProxy.1 modules/FvwmRearrange/FvwmRearrange.1 modules/FvwmScript/FvwmScript.1 bin/Makefile bin/fvwm-config bin/fvwm-bug bin/fvwm-perllib bin/fvwm-menu-xlock bin/fvwm-menu-directory bin/fvwm-menu-desktop bin/fvwm-menu-headlines bin/fvwm-convert-2.6 utils/Makefile perllib/Makefile perllib/General/Makefile perllib/FVWM/Makefile perllib/FVWM/Module/Makefile perllib/FVWM/Tracker/Makefile perllib/FVWM/Module.pm default-config/Makefile doc/fvwm.ent doc/footer.html doc/Makefile doc/fvwm/Makefile doc/commands/Makefile doc/docbook-xml/Makefile doc/docbook-xml/ent/Makefile doc/docbook-xsl/Makefile doc/docbook-xsl/common/Makefile doc/docbook-xsl/manpages/Makefile doc/docbook-xsl/profiling/Makefile doc/docbook-xsl/highlighting/Makefile doc/docbook-xsl/lib/Makefile doc/docbook-xsl/html/Makefile doc/images/Makefile doc/images/svg_rendering/Makefile docs/Makefile tests/Makefile tests/hints/Makefile po/Makefile modules/FvwmAnimate/Makefile modules/FvwmAuto/Makefile modules/FvwmBacker/Makefile modules/FvwmBanner/Makefile modules/FvwmButtons/Makefile modules/FvwmCommand/Makefile modules/FvwmCommandS/Makefile modules/FvwmCommand/scripts/Makefile modules/FvwmConsole/Makefile modules/FvwmConsole/FvwmConsoleC.pl modules/FvwmCpp/Makefile modules/FvwmEvent/Makefile modules/FvwmForm/Makefile modules/FvwmIconMan/Makefile modules/FvwmIdent/Makefile modules/FvwmM4/Makefile modules/FvwmPager/Makefile modules/FvwmPerl/Makefile modules/FvwmPerl/FvwmPerl modules/FvwmProxy/Makefile modules/FvwmRearrange/Makefile modules/FvwmScript/Makefile modules/FvwmScript/Scripts/Makefile modules/FvwmScript/Widgets/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 printf "%s\n" "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 printf %s "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: done" >&5 printf "%s\n" "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${FVWM_BUILD_MANDOC_TRUE}" && test -z "${FVWM_BUILD_MANDOC_FALSE}"; then as_fn_error $? "conditional \"FVWM_BUILD_MANDOC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${FVWM_BUILD_HTMLDOC_TRUE}" && test -z "${FVWM_BUILD_HTMLDOC_FALSE}"; then as_fn_error $? "conditional \"FVWM_BUILD_HTMLDOC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh as_nop=: if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else $as_nop case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi # Reset variables that may have inherited troublesome values from # the environment. # IFS needs to be set, to space, tab, and newline, in precisely that order. # (If _AS_PATH_WALK were called with IFS unset, it would have the # side effect of setting IFS to empty, thus disabling word splitting.) # Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl IFS=" "" $as_nl" PS1='$ ' PS2='> ' PS4='+ ' # Ensure predictable behavior from utilities with locale-dependent output. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # We cannot yet rely on "unset" to work, but we need these variables # to be unset--not just set to an empty or harmless value--now, to # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct # also avoids known problems related to "unset" and subshell syntax # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH do eval test \${$as_var+y} \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done # Ensure that fds 0, 1, and 2 are open. if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null then : eval 'as_fn_append () { eval $1+=\$2 }' else $as_nop as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null then : eval 'as_fn_arith () { as_val=$(( $* )) }' else $as_nop as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # Determine whether it's possible to make 'echo' print without a newline. # These variables are no longer used directly by Autoconf, but are AC_SUBSTed # for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac # For backward compatibility with old third-party macros, we provide # the shell variables $as_echo and $as_echo_n. New code should use # AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. as_echo='printf %s\n' as_echo_n='printf %s' rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by fvwm $as_me 2.7.0, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"` ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"` cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ fvwm config.status 2.7.0 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" Copyright (C) 2021 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) printf "%s\n" "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) printf "%s\n" "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) printf "%s\n" "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX printf "%s\n" "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "libs/Makefile") CONFIG_FILES="$CONFIG_FILES libs/Makefile" ;; "fvwm/Makefile") CONFIG_FILES="$CONFIG_FILES fvwm/Makefile" ;; "modules/Makefile") CONFIG_FILES="$CONFIG_FILES modules/Makefile" ;; "bin/fvwm-bug.1") CONFIG_FILES="$CONFIG_FILES bin/fvwm-bug.1" ;; "bin/fvwm-config.1") CONFIG_FILES="$CONFIG_FILES bin/fvwm-config.1" ;; "bin/fvwm-convert-2.6.1") CONFIG_FILES="$CONFIG_FILES bin/fvwm-convert-2.6.1" ;; "bin/fvwm-menu-desktop.1") CONFIG_FILES="$CONFIG_FILES bin/fvwm-menu-desktop.1" ;; "bin/fvwm-root.1") CONFIG_FILES="$CONFIG_FILES bin/fvwm-root.1" ;; "modules/FvwmAnimate/FvwmAnimate.1") CONFIG_FILES="$CONFIG_FILES modules/FvwmAnimate/FvwmAnimate.1" ;; "modules/FvwmAuto/FvwmAuto.1") CONFIG_FILES="$CONFIG_FILES modules/FvwmAuto/FvwmAuto.1" ;; "modules/FvwmBacker/FvwmBacker.1") CONFIG_FILES="$CONFIG_FILES modules/FvwmBacker/FvwmBacker.1" ;; "modules/FvwmBanner/FvwmBanner.1") CONFIG_FILES="$CONFIG_FILES modules/FvwmBanner/FvwmBanner.1" ;; "modules/FvwmButtons/FvwmButtons.1") CONFIG_FILES="$CONFIG_FILES modules/FvwmButtons/FvwmButtons.1" ;; "modules/FvwmCommand/FvwmCommand.1") CONFIG_FILES="$CONFIG_FILES modules/FvwmCommand/FvwmCommand.1" ;; "modules/FvwmConsole/FvwmConsole.1") CONFIG_FILES="$CONFIG_FILES modules/FvwmConsole/FvwmConsole.1" ;; "modules/FvwmConsole/FvwmConsoleC.pl.1") CONFIG_FILES="$CONFIG_FILES modules/FvwmConsole/FvwmConsoleC.pl.1" ;; "modules/FvwmCpp/FvwmCpp.1") CONFIG_FILES="$CONFIG_FILES modules/FvwmCpp/FvwmCpp.1" ;; "modules/FvwmEvent/FvwmEvent.1") CONFIG_FILES="$CONFIG_FILES modules/FvwmEvent/FvwmEvent.1" ;; "modules/FvwmForm/FvwmForm.1") CONFIG_FILES="$CONFIG_FILES modules/FvwmForm/FvwmForm.1" ;; "modules/FvwmIconMan/FvwmIconMan.1") CONFIG_FILES="$CONFIG_FILES modules/FvwmIconMan/FvwmIconMan.1" ;; "modules/FvwmIdent/FvwmIdent.1") CONFIG_FILES="$CONFIG_FILES modules/FvwmIdent/FvwmIdent.1" ;; "modules/FvwmM4/FvwmM4.1") CONFIG_FILES="$CONFIG_FILES modules/FvwmM4/FvwmM4.1" ;; "modules/FvwmPager/FvwmPager.1") CONFIG_FILES="$CONFIG_FILES modules/FvwmPager/FvwmPager.1" ;; "modules/FvwmProxy/FvwmProxy.1") CONFIG_FILES="$CONFIG_FILES modules/FvwmProxy/FvwmProxy.1" ;; "modules/FvwmRearrange/FvwmRearrange.1") CONFIG_FILES="$CONFIG_FILES modules/FvwmRearrange/FvwmRearrange.1" ;; "modules/FvwmScript/FvwmScript.1") CONFIG_FILES="$CONFIG_FILES modules/FvwmScript/FvwmScript.1" ;; "bin/Makefile") CONFIG_FILES="$CONFIG_FILES bin/Makefile" ;; "bin/fvwm-config") CONFIG_FILES="$CONFIG_FILES bin/fvwm-config" ;; "bin/fvwm-bug") CONFIG_FILES="$CONFIG_FILES bin/fvwm-bug" ;; "bin/fvwm-perllib") CONFIG_FILES="$CONFIG_FILES bin/fvwm-perllib" ;; "bin/fvwm-menu-xlock") CONFIG_FILES="$CONFIG_FILES bin/fvwm-menu-xlock" ;; "bin/fvwm-menu-directory") CONFIG_FILES="$CONFIG_FILES bin/fvwm-menu-directory" ;; "bin/fvwm-menu-desktop") CONFIG_FILES="$CONFIG_FILES bin/fvwm-menu-desktop" ;; "bin/fvwm-menu-headlines") CONFIG_FILES="$CONFIG_FILES bin/fvwm-menu-headlines" ;; "bin/fvwm-convert-2.6") CONFIG_FILES="$CONFIG_FILES bin/fvwm-convert-2.6" ;; "utils/Makefile") CONFIG_FILES="$CONFIG_FILES utils/Makefile" ;; "perllib/Makefile") CONFIG_FILES="$CONFIG_FILES perllib/Makefile" ;; "perllib/General/Makefile") CONFIG_FILES="$CONFIG_FILES perllib/General/Makefile" ;; "perllib/FVWM/Makefile") CONFIG_FILES="$CONFIG_FILES perllib/FVWM/Makefile" ;; "perllib/FVWM/Module/Makefile") CONFIG_FILES="$CONFIG_FILES perllib/FVWM/Module/Makefile" ;; "perllib/FVWM/Tracker/Makefile") CONFIG_FILES="$CONFIG_FILES perllib/FVWM/Tracker/Makefile" ;; "perllib/FVWM/Module.pm") CONFIG_FILES="$CONFIG_FILES perllib/FVWM/Module.pm" ;; "default-config/Makefile") CONFIG_FILES="$CONFIG_FILES default-config/Makefile" ;; "doc/fvwm.ent") CONFIG_FILES="$CONFIG_FILES doc/fvwm.ent" ;; "doc/footer.html") CONFIG_FILES="$CONFIG_FILES doc/footer.html" ;; "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; "doc/fvwm/Makefile") CONFIG_FILES="$CONFIG_FILES doc/fvwm/Makefile" ;; "doc/commands/Makefile") CONFIG_FILES="$CONFIG_FILES doc/commands/Makefile" ;; "doc/docbook-xml/Makefile") CONFIG_FILES="$CONFIG_FILES doc/docbook-xml/Makefile" ;; "doc/docbook-xml/ent/Makefile") CONFIG_FILES="$CONFIG_FILES doc/docbook-xml/ent/Makefile" ;; "doc/docbook-xsl/Makefile") CONFIG_FILES="$CONFIG_FILES doc/docbook-xsl/Makefile" ;; "doc/docbook-xsl/common/Makefile") CONFIG_FILES="$CONFIG_FILES doc/docbook-xsl/common/Makefile" ;; "doc/docbook-xsl/manpages/Makefile") CONFIG_FILES="$CONFIG_FILES doc/docbook-xsl/manpages/Makefile" ;; "doc/docbook-xsl/profiling/Makefile") CONFIG_FILES="$CONFIG_FILES doc/docbook-xsl/profiling/Makefile" ;; "doc/docbook-xsl/highlighting/Makefile") CONFIG_FILES="$CONFIG_FILES doc/docbook-xsl/highlighting/Makefile" ;; "doc/docbook-xsl/lib/Makefile") CONFIG_FILES="$CONFIG_FILES doc/docbook-xsl/lib/Makefile" ;; "doc/docbook-xsl/html/Makefile") CONFIG_FILES="$CONFIG_FILES doc/docbook-xsl/html/Makefile" ;; "doc/images/Makefile") CONFIG_FILES="$CONFIG_FILES doc/images/Makefile" ;; "doc/images/svg_rendering/Makefile") CONFIG_FILES="$CONFIG_FILES doc/images/svg_rendering/Makefile" ;; "docs/Makefile") CONFIG_FILES="$CONFIG_FILES docs/Makefile" ;; "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;; "tests/hints/Makefile") CONFIG_FILES="$CONFIG_FILES tests/hints/Makefile" ;; "po/Makefile") CONFIG_FILES="$CONFIG_FILES po/Makefile" ;; "modules/FvwmAnimate/Makefile") CONFIG_FILES="$CONFIG_FILES modules/FvwmAnimate/Makefile" ;; "modules/FvwmAuto/Makefile") CONFIG_FILES="$CONFIG_FILES modules/FvwmAuto/Makefile" ;; "modules/FvwmBacker/Makefile") CONFIG_FILES="$CONFIG_FILES modules/FvwmBacker/Makefile" ;; "modules/FvwmBanner/Makefile") CONFIG_FILES="$CONFIG_FILES modules/FvwmBanner/Makefile" ;; "modules/FvwmButtons/Makefile") CONFIG_FILES="$CONFIG_FILES modules/FvwmButtons/Makefile" ;; "modules/FvwmCommand/Makefile") CONFIG_FILES="$CONFIG_FILES modules/FvwmCommand/Makefile" ;; "modules/FvwmCommandS/Makefile") CONFIG_FILES="$CONFIG_FILES modules/FvwmCommandS/Makefile" ;; "modules/FvwmCommand/scripts/Makefile") CONFIG_FILES="$CONFIG_FILES modules/FvwmCommand/scripts/Makefile" ;; "modules/FvwmConsole/Makefile") CONFIG_FILES="$CONFIG_FILES modules/FvwmConsole/Makefile" ;; "modules/FvwmConsole/FvwmConsoleC.pl") CONFIG_FILES="$CONFIG_FILES modules/FvwmConsole/FvwmConsoleC.pl" ;; "modules/FvwmCpp/Makefile") CONFIG_FILES="$CONFIG_FILES modules/FvwmCpp/Makefile" ;; "modules/FvwmEvent/Makefile") CONFIG_FILES="$CONFIG_FILES modules/FvwmEvent/Makefile" ;; "modules/FvwmForm/Makefile") CONFIG_FILES="$CONFIG_FILES modules/FvwmForm/Makefile" ;; "modules/FvwmIconMan/Makefile") CONFIG_FILES="$CONFIG_FILES modules/FvwmIconMan/Makefile" ;; "modules/FvwmIdent/Makefile") CONFIG_FILES="$CONFIG_FILES modules/FvwmIdent/Makefile" ;; "modules/FvwmM4/Makefile") CONFIG_FILES="$CONFIG_FILES modules/FvwmM4/Makefile" ;; "modules/FvwmPager/Makefile") CONFIG_FILES="$CONFIG_FILES modules/FvwmPager/Makefile" ;; "modules/FvwmPerl/Makefile") CONFIG_FILES="$CONFIG_FILES modules/FvwmPerl/Makefile" ;; "modules/FvwmPerl/FvwmPerl") CONFIG_FILES="$CONFIG_FILES modules/FvwmPerl/FvwmPerl" ;; "modules/FvwmProxy/Makefile") CONFIG_FILES="$CONFIG_FILES modules/FvwmProxy/Makefile" ;; "modules/FvwmRearrange/Makefile") CONFIG_FILES="$CONFIG_FILES modules/FvwmRearrange/Makefile" ;; "modules/FvwmScript/Makefile") CONFIG_FILES="$CONFIG_FILES modules/FvwmScript/Makefile" ;; "modules/FvwmScript/Scripts/Makefile") CONFIG_FILES="$CONFIG_FILES modules/FvwmScript/Scripts/Makefile" ;; "modules/FvwmScript/Widgets/Makefile") CONFIG_FILES="$CONFIG_FILES modules/FvwmScript/Widgets/Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files test ${CONFIG_HEADERS+y} || CONFIG_HEADERS=$config_headers test ${CONFIG_COMMANDS+y} || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 printf "%s\n" "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`printf "%s\n" "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { printf "%s\n" "/* $configure_input */" >&1 \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 printf "%s\n" "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else printf "%s\n" "/* $configure_input */" >&1 \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 printf "%s\n" "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. # TODO: see whether this extra hack can be removed once we start # requiring Autoconf 2.70 or later. case $CONFIG_FILES in #( *\'*) : eval set x "$CONFIG_FILES" ;; #( *) : set x $CONFIG_FILES ;; #( *) : ;; esac shift # Used to flag and report bootstrapping failures. am_rc=0 for am_mf do # Strip MF so we end up with the name of the file. am_mf=`printf "%s\n" "$am_mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile which includes # dependency-tracking related rules and includes. # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ || continue am_dirpart=`$as_dirname -- "$am_mf" || $as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$am_mf" : 'X\(//\)[^/]' \| \ X"$am_mf" : 'X\(//\)$' \| \ X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$am_mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` am_filepart=`$as_basename -- "$am_mf" || $as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \ X"$am_mf" : 'X\(//\)$' \| \ X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$am_mf" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` { echo "$as_me:$LINENO: cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles" >&5 (cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } || am_rc=$? done if test $am_rc -ne 0; then { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "Something went wrong bootstrapping makefile fragments for automatic dependency tracking. If GNU make was not used, consider re-running the configure script with MAKE=\"gmake\" (or whatever is necessary). You can also try re-running configure with the '--disable-dependency-tracking' option to at least be able to build the package (albeit without support for automatic dependency tracking). See \`config.log' for more details" "$LINENO" 5; } fi { am_dirpart=; unset am_dirpart;} { am_filepart=; unset am_filepart;} { am_mf=; unset am_mf;} { am_rc=; unset am_rc;} rm -f conftest-deps.mk } ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi # --------------------------------------------------------------------------- # Original config.status is patched to make generated scripts executable. sed 's/> $ac_file/> $ac_file; test x"`head -1 $ac_file | cut -c1-2`" = x"#!" \&\& chmod a+rx $ac_file/' config.status-t && \ mv config.status-t config.status chmod +x config.status # --------------------------------------------------------------------------- # --------------------------------------------------------------------------- cat >config.status-t <>config.status-t && \ mv config.status-t config.status chmod +x config.status # --------------------------------------------------------------------------- eval my_bindir="`eval echo ${bindir}`" eval my_mandir="`eval echo ${mandir}`" eval my_moddir="`eval echo ${FVWM_MODULEDIR}`"; eval my_moddir="$my_moddir" eval my_datdir="`eval echo ${FVWM_DATADIR}`" eval my_docdir="`eval echo ${FVWM_DOCDIR}`" eval my_plldir="`eval echo ${FVWM_PERLLIBDIR}`" test x"$FVWM_PERLLIB" = x && my_plldir="(Not installed) $my_plldir" eval my_localedir="`eval echo ${LOCALEDIR}`" test x"$USE_NLS" = xno && my_localedir="(Not installed) $my_localdir" echo " Fvwm Configuration: Version: $VERSION$VERSIONINFO Executables: $my_bindir Man pages: $my_mandir Modules: $my_moddir Data files: $my_datdir Doc files: $my_docdir Perl lib: $my_plldir Locale msg: $my_localedir $INST_LINGUAS With Asian bi-direct. text support? $with_bidi$problem_bidi With Gettext Native Lang support? $with_gettext$problem_gettext With Iconv support? $with_iconv_type$problem_iconv With Mouse strokes (gestures)? $with_stroke$problem_stroke With ReadLine sup. in FvwmConsole? $with_readline$problem_readline With RPlay support in FvwmEvent? $with_rplay$problem_rplay With Shaped window support? $with_shape$problem_shape With Shared memory for XImage? $with_shm$problem_shm With Session Management support? $with_sm$problem_sm With SVG image support? $with_rsvg$problem_rsvg With Xcursor support? $with_xcursor$problem_xcursor With Xinerama multi-head support? $with_xinerama$problem_xinerama With Xft anti-alias font support? $with_xft$problem_xft With XPM image support? $with_xpm$problem_xpm With Xrender image support? $with_xrender$problem_xrender Build man pages? $with_mandoc$problem_mandoc Build HTML documentation? $with_htmldoc$problem_htmldoc " case "$with_xinerama_emulation" in yes) echo " Xinerama emulation enabled." ;; esac case "$ac_cv_dmalloc" in yes) echo " DMALLOC heap debugging library enabled." ;; esac case "$ac_cv_efence" in yes) echo " EFENCE debugging library enabled." ;; esac fvwm-2.7.0/utils/0000755000175000017500000000000014324316055010643 500000000000000fvwm-2.7.0/utils/fvwm_make_directory_menu.sh0000755000175000017500000000440714147024700016207 00000000000000#!/bin/sh # ### # This script demonstates the fvwm menu MissingSubmenuFunction functionality. # You can use a more configurable fvwm-menu-directory instead. # The line below almost exactly simulates this script: # fvwm-menu-directory --links --order 4 --exec-file vi --dir DIR ### # # Modification History # # Created on 06/07/99 by Dominik Vogt (domivogt): # # provides output to read in with PipeRead to build a menu # containing a directory listing. # # You should put these lines into your fvwm configuration file to invoke # this script: # # AddToFunc MakeMissingDirectoryMenu # + i piperead 'fvwm_make_directory_menu.sh '$0 # # And put these lines in the menu from which you want to pop up the # directory menus: # # AddToMenu SomeMenu MissingSubmenuFunction MakeMissingDirectoryMenu # + "my directory item" Popup /whatever/path/you/like # # Note: please use absolute path names. # # configuration section # # If you want to optimize for speed, unset this variable. Warning: speed # optimization takes up a lot of memory that is never free'd again while fvwm # is running. OPTIMIZE_SPACE=yes # you may use the absolute path here if you have an alias like ls="ls -F" LS="/bin/ls -LF" SED=sed # the name of our menu MENU=`echo $1 | $SED -e 's://*:/:g'` PMENU=`echo "$MENU" | $SED -e s:\"::g` # the command to execute on plain files ACTION=vi # the terminal program to invoke TERMINAL="xterm -e" TERMINALSHELL="xterm" # # you may customize this script below here. # # dump all menu items echo DestroyMenu recreate \""$PMENU"\" # add a new title echo AddToMenu \""$PMENU"\" \""$PMENU"\" Exec "echo cd $MENU\; $TERMINALSHELL | $SHELL" # add a separator echo AddToMenu \""$PMENU"\" \"\" nop # destroy the menu after it is popped down if [ "$OPTIMIZE_SPACE" = yes ] ; then echo AddToMenu \""$PMENU"\" DynamicPopDownAction DestroyMenu \""$PMENU"\" fi # set the 'missing submenu function' echo AddToMenu \""$PMENU"\" MissingSubmenuFunction MakeMissingDirectoryMenu # add directory contents $LS "$MENU" 2> /dev/null | $SED -n ' /\/$/ bdirectory s:[=*@|]$::1 s:"::g s:^\(.*\)$:AddToMenu "'"$PMENU"'" "\1" Exec '"$TERMINAL $ACTION"' "'"$MENU"'/\1":1 bnext :directory s:^\(.*\)/$:AddToMenu "'"$PMENU"'" "\1" Popup "'"$PMENU"'/\1" item +100 c:1 :next s://*:/:g p ' fvwm-2.7.0/utils/Makefile.in0000644000175000017500000003544514324315776012654 00000000000000# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 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 = utils ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.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__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALL_DOMAINS = @ALL_DOMAINS@ ALL_LINGUAS = @ALL_LINGUAS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR_FLAGS = @AR_FLAGS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ Bidi_CFLAGS = @Bidi_CFLAGS@ Bidi_LIBS = @Bidi_LIBS@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DOC_COMMANDS = @DOC_COMMANDS@ DOC_COMMANDS_HTML = @DOC_COMMANDS_HTML@ DOC_COMMANDS_XML = @DOC_COMMANDS_XML@ DOC_COMMANDS_XML_PATH = @DOC_COMMANDS_XML_PATH@ DOC_MODULES = @DOC_MODULES@ DOC_MODULES_HTML = @DOC_MODULES_HTML@ DOC_SECTIONS = @DOC_SECTIONS@ DOC_SECTIONS_XML = @DOC_SECTIONS_XML@ DOC_SECTIONS_XML_PATH = @DOC_SECTIONS_XML_PATH@ DUMMYPOFILES = @DUMMYPOFILES@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FC_CFLAGS = @FC_CFLAGS@ FC_CONFIG = @FC_CONFIG@ FC_LIBS = @FC_LIBS@ FRIBIDI_CONFIG = @FRIBIDI_CONFIG@ FVWMALTFTP = @FVWMALTFTP@ FVWMALTFTPDIR = @FVWMALTFTPDIR@ FVWMFTP = @FVWMFTP@ FVWMFTPDIR = @FVWMFTPDIR@ FVWMHOMEPAGE = @FVWMHOMEPAGE@ FVWMLIST = @FVWMLIST@ FVWMNAMELONG = @FVWMNAMELONG@ FVWMSCRIPT_DOMAIN = @FVWMSCRIPT_DOMAIN@ FVWMTASKBAR_DOMAIN = @FVWMTASKBAR_DOMAIN@ FVWMWORKERSLIST = @FVWMWORKERSLIST@ FVWMWORKERSLISTLONG = @FVWMWORKERSLISTLONG@ FVWM_CONFDIR = @FVWM_CONFDIR@ FVWM_CPP = @FVWM_CPP@ FVWM_DATADIR = @FVWM_DATADIR@ FVWM_DOCDIR = @FVWM_DOCDIR@ FVWM_DOMAIN = @FVWM_DOMAIN@ FVWM_IMAGEPATH = @FVWM_IMAGEPATH@ FVWM_MODULEDIR = @FVWM_MODULEDIR@ FVWM_PERLLIB = @FVWM_PERLLIB@ FVWM_PERLLIBDIR = @FVWM_PERLLIBDIR@ GDK_IMLIB_CFLAGS = @GDK_IMLIB_CFLAGS@ GDK_IMLIB_LIBS = @GDK_IMLIB_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ IMLIBCONF = @IMLIBCONF@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INST_LINGUAS = @INST_LINGUAS@ ISRELEASED = @ISRELEASED@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOCALEDIR = @LOCALEDIR@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANPAGE_PREAMBLE = @MANPAGE_PREAMBLE@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ MSGUNIQ = @MSGUNIQ@ OBJEXT = @OBJEXT@ 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@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PYTHON = @PYTHON@ RANLIB = @RANLIB@ RELDATELONG = @RELDATELONG@ RELDATENUM = @RELDATENUM@ RELDATESHORT = @RELDATESHORT@ REQUIRED_PERL_VERSION = @REQUIRED_PERL_VERSION@ REQUIRED_PYTHON_VERSION = @REQUIRED_PYTHON_VERSION@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ UPDATEPOFILES = @UPDATEPOFILES@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VERSIONINFO = @VERSIONINFO@ XFT_CFLAGS = @XFT_CFLAGS@ XFT_CONFIG = @XFT_CONFIG@ XFT_LIBS = @XFT_LIBS@ XGETTEXT = @XGETTEXT@ XMKMF = @XMKMF@ XSLTPROC = @XSLTPROC@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Xcursor_CFLAGS = @Xcursor_CFLAGS@ Xcursor_LIBS = @Xcursor_LIBS@ Xft_CFLAGS = @Xft_CFLAGS@ Xft_LIBS = @Xft_LIBS@ Xinerama_CFLAGS = @Xinerama_CFLAGS@ Xinerama_LIBS = @Xinerama_LIBS@ Xrender_CFLAGS = @Xrender_CFLAGS@ Xrender_LIBS = @Xrender_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ iconv_CFLAGS = @iconv_CFLAGS@ iconv_LIBS = @iconv_LIBS@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intl_CFLAGS = @intl_CFLAGS@ intl_LIBS = @intl_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ png_CFLAGS = @png_CFLAGS@ png_LIBS = @png_LIBS@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ readline_CFLAGS = @readline_CFLAGS@ readline_LIBS = @readline_LIBS@ rplay_CFLAGS = @rplay_CFLAGS@ rplay_LIBS = @rplay_LIBS@ rsvg_CFLAGS = @rsvg_CFLAGS@ rsvg_LIBS = @rsvg_LIBS@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ stroke_CFLAGS = @stroke_CFLAGS@ stroke_LIBS = @stroke_LIBS@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ with_bidi = @with_bidi@ with_gdkimlib = @with_gdkimlib@ with_gettext = @with_gettext@ with_iconv = @with_iconv@ with_perllib = @with_perllib@ with_png = @with_png@ with_readline = @with_readline@ with_rplay = @with_rplay@ with_rsvg = @with_rsvg@ with_shape = @with_shape@ with_shm = @with_shm@ with_sm = @with_sm@ with_stroke = @with_stroke@ with_xcursor = @with_xcursor@ with_xft = @with_xft@ with_xinerama = @with_xinerama@ with_xpm = @with_xpm@ with_xrender = @with_xrender@ xpm_CFLAGS = @xpm_CFLAGS@ xpm_LIBS = @xpm_LIBS@ EXTRA_DIST = fvwm_make_browse_menu.sh fvwm_make_directory_menu.sh \ fvwm-version-str.sh LDADD = -L$(top_builddir)/libs $(X_LIBS) -lfvwm $(xpm_LIBS) \ $(X_PRE_LIBS) -lXext -lX11 -lm $(X_EXTRA_LIBS) $(png_LIBS) AM_CPPFLAGS = -I$(top_srcdir) $(xpm_CFLAGS) $(X_CFLAGS) $(png_CFLAGS) all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(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) --foreign utils/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign utils/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: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): 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 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 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-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 pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic cscopelist-am \ ctags-am distclean distclean-generic 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-generic pdf \ pdf-am ps ps-am 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: fvwm-2.7.0/utils/fvwm-version-str.sh0000755000175000017500000000074514324315751014402 00000000000000#!/bin/sh # # fvwm-version-str: emits the version of fvwm which is building. # If this is a release build, then the tag name is chomped # to remove extraneous git information. # # If it's a developer build, it's left as-is. # # # # Intended to be called from configure.ac (via autogen.sh) if grep -q -i '^ISRELEASED="yes"' ./configure.ac; then # A release build. Strip the git information off the tag name. echo "2.7.0" else git describe --always --long --dirty fi fvwm-2.7.0/utils/fvwm_make_browse_menu.sh0000755000175000017500000000447614147024700015512 00000000000000#!/bin/sh # ### # This script demonstrates the fvwm menu DynamicPopupAction functionality. # You can use a more configurable fvwm-menu-directory instead. # The line below almost exactly simulates this script: # fvwm-menu-directory --reuse --links --order 4 --name \ # --exec-file vi --exec-title - --special-dirs ### # # Modification History # # Created on 05/06/99 by Dominik Vogt (domivogt): # # provides output to read in with PipeRead to build a menu # containing a directory listing. # # You should put these lines into your fvwm configuration file to invoke # this script: # # AddToMenu # + DynamicPopupAction Piperead 'fvwm_make_browse_menu.sh ' # # configuration section # # the file containing the desired directory name DIRFILE="$HOME/.fvwm_browse_menu_cwd" # you may use the absolute path here if you have an alias like ls="ls -F" LS=ls SED=sed # the name of our menu MENU=`echo "$1" | $SED -e s:\"::g` # the command to execute on plain files ACTION=vi # the terminal program to invoke TERMINAL="xterm -e" # # you may customize this script below here. # # create a file containing the current working directory if [ ! -f "$DIRFILE" ] ; then echo "$HOME" > "$DIRFILE" fi # get desired directory DIR="`cat "$DIRFILE"`" if [ ! -d "$DIR" ] ; then DIR="$HOME" fi # dump all menu items echo DestroyMenu recreate \""$MENU"\" # add a new title echo AddToMenu \""$MENU"\" \"`cat "$DIRFILE"`\" Title # add '..' entry cd "$DIR"/.. echo AddToMenu \""$MENU"\" \"..\" PipeRead \'echo \""`/bin/pwd`"\" \> "$DIRFILE" ';' echo Menu \\\""$MENU"\\\" WarpTitle\' # add separator echo AddToMenu \""$MENU"\" \"\" Nop # add $HOME entry echo AddToMenu \""$MENU"\" \"~\" PipeRead \'echo \""$HOME"\" \> "$DIRFILE" ';' echo Menu \\\""$MENU"\\\" WarpTitle\' # add separator echo AddToMenu \""$MENU"\" \"\" Nop # add directory contents for i in `"$LS" "$DIR"` ; do if [ -d "$DIR/$i" ] ; then # it's a directory cd "$DIR/$i" # put new path in $DIRFILE and invoke the menu again echo AddToMenu \""$MENU"\" \""$i/"\" PipeRead \'echo \"`echo $DIR/$i|$SED -e s://:/:g`\" \> "$DIRFILE" ';' echo Menu \\\""$MENU"\\\" WarpTitle\' else # something else, apply $ACTION to it echo AddToMenu \""$MENU"\" \""$i"\" Exec $TERMINAL $ACTION \""$DIR/$i"\" fi done fvwm-2.7.0/utils/Makefile.am0000644000175000017500000000053114147024700012612 00000000000000## Process this file with automake to create Makefile.in EXTRA_DIST = fvwm_make_browse_menu.sh fvwm_make_directory_menu.sh \ fvwm-version-str.sh LDADD = -L$(top_builddir)/libs $(X_LIBS) -lfvwm $(xpm_LIBS) \ $(X_PRE_LIBS) -lXext -lX11 -lm $(X_EXTRA_LIBS) $(png_LIBS) AM_CPPFLAGS = -I$(top_srcdir) $(xpm_CFLAGS) $(X_CFLAGS) $(png_CFLAGS) fvwm-2.7.0/default-config/0000755000175000017500000000000014324316054012371 500000000000000fvwm-2.7.0/default-config/FvwmScript-DateTime0000644000175000017500000000152714147024700016034 00000000000000WindowTitle {DateTime} WindowSize 120 35 Font "xft:Sans:style=Bold:size=10" Init Begin Set $Time = (GetOutput {exec date "+%H:%M"} 1 -1) Set $Date = (GetOutput {exec date "+%a %b %d"} 1 -1) ChangeTitle 1 $Time ChangeTitle 2 $Date End PeriodicTasks Begin If (RemainderOfDiv (GetTime) 15)==0 Then Begin Set $Time = (GetOutput {exec date "+%H:%M"} 1 -1) Set $Date = (GetOutput {exec date "+%a %b %d"} 1 -1) ChangeTitle 1 $Time ChangeTitle 2 $Date End End Widget 1 Property Position 0 0 Size 120 20 Font "xft:Sans:style=Bold:size=11" Type ItemDraw Flags NoReliefString Title {} Main Case message of SingleClic : Begin End End Widget 2 Property Position 0 20 Size 120 15 Font "xft:Sans:style=Bold:size=8" Type ItemDraw Flags NoReliefString Title {} Main Case message of SingleClic : Begin End End fvwm-2.7.0/default-config/FvwmScript-ConfirmCopyConfig0000644000175000017500000000424014147024700017711 00000000000000WindowTitle {ConfirmCopyConfig} WindowSize 500 160 Font "xft:Sans:size=10" Init Begin Set $DataDir=(GetOutput {echo "$FVWM_DATADIR"} 1 -1) Set $UserDir=(GetOutput {echo "$FVWM_USERDIR"} 1 -1) Set $DefaultConf=$DataDir {/default-config/config} Set $UserConf=$UserDir {/config} Set $BackupConf=$UserDir {/config-bak} ChangeTitle 3 $UserConf ChangeTitle 5 $BackupConf Do {Style ConfirmCopyConfig Layer 6} End Widget 1 Property Title {Fvwm Default Configuration} Font "xft:Sans:size=14" Size 500 25 Position 0 0 Type ItemDraw Flags NoReliefString Center Main Case message of SingleClic : Begin End End Widget 2 Property Title {This script copies the default configuration into your home directory:} Size 400 12 Position 15 30 Type ItemDraw Flags NoReliefString Left Main Case message of SingleClic : Begin End End Widget 3 Property Title {} Size 400 17 Position 70 50 Type ItemDraw Flags NoReliefString Left Main Case message of SingleClic : Begin End End Widget 4 Property Title {A backup of your current configuration will be located at:} Size 400 12 Position 15 70 Type ItemDraw Flags NoReliefString Left Main Case message of SingleClic : Begin End End Widget 5 Property Title {} Size 400 17 Position 70 90 Type ItemDraw Flags NoReliefString Left Main Case message of SingleClic : Begin End End Widget 6 Property Title {Click Confirm to continue and restart Fvwm.} Size 400 15 Position 15 107 Type ItemDraw Flags NoReliefString Left Main Case message of SingleClic : Begin End End Widget 7 Property Title {Confirm} Colorset 13 Size 60 28 Position 100 130 Flags NoReliefString Type PushButton Value 1 Main Case message of SingleClic : Begin Do {Test (f } $UserConf {) PipeRead `mv "} $UserConf {" "} $BackupConf {"; echo "Echo Backup: } $BackupConf {"`} Do {PipeRead `cp "} $DefaultConf {" "} $UserDir {"; echo "Echo Copied default config to } $UserDir {"`} Do {Restart} Quit End End Widget 8 Property Title {Cancel} Colorset 13 Size 60 28 Position 350 130 Flags NoReliefString Type PushButton Value 1 Main Case message of SingleClic : Begin Quit End End fvwm-2.7.0/default-config/FvwmScript-ConfirmQuit0000644000175000017500000000116714147024700016600 00000000000000WindowTitle {ConfirmQuit} WindowSize 300 80 Font "xft:Sans:style=Bold:size=10" Init Begin End Widget 1 Property Title {Do you really want to quit Fvwm?} Size 200 30 Position 25 0 Type ItemDraw Flags NoReliefString Main Case message of SingleClic : Begin End End Widget 2 Property Title {Quit} Size 60 28 Position 70 40 Flags NoReliefString Type PushButton Value 1 Main Case message of SingleClic : Begin Do {Quit} End End Widget 3 Property Title {Cancel} Size 60 28 Position 170 40 Flags NoReliefString Type PushButton Value 1 Main Case message of SingleClic : Begin Quit End End fvwm-2.7.0/default-config/Makefile.in0000644000175000017500000004332714324315775014400 00000000000000# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 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 = default-config ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.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)$(configdir)" DATA = $(config_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALL_DOMAINS = @ALL_DOMAINS@ ALL_LINGUAS = @ALL_LINGUAS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR_FLAGS = @AR_FLAGS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ Bidi_CFLAGS = @Bidi_CFLAGS@ Bidi_LIBS = @Bidi_LIBS@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DOC_COMMANDS = @DOC_COMMANDS@ DOC_COMMANDS_HTML = @DOC_COMMANDS_HTML@ DOC_COMMANDS_XML = @DOC_COMMANDS_XML@ DOC_COMMANDS_XML_PATH = @DOC_COMMANDS_XML_PATH@ DOC_MODULES = @DOC_MODULES@ DOC_MODULES_HTML = @DOC_MODULES_HTML@ DOC_SECTIONS = @DOC_SECTIONS@ DOC_SECTIONS_XML = @DOC_SECTIONS_XML@ DOC_SECTIONS_XML_PATH = @DOC_SECTIONS_XML_PATH@ DUMMYPOFILES = @DUMMYPOFILES@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FC_CFLAGS = @FC_CFLAGS@ FC_CONFIG = @FC_CONFIG@ FC_LIBS = @FC_LIBS@ FRIBIDI_CONFIG = @FRIBIDI_CONFIG@ FVWMALTFTP = @FVWMALTFTP@ FVWMALTFTPDIR = @FVWMALTFTPDIR@ FVWMFTP = @FVWMFTP@ FVWMFTPDIR = @FVWMFTPDIR@ FVWMHOMEPAGE = @FVWMHOMEPAGE@ FVWMLIST = @FVWMLIST@ FVWMNAMELONG = @FVWMNAMELONG@ FVWMSCRIPT_DOMAIN = @FVWMSCRIPT_DOMAIN@ FVWMTASKBAR_DOMAIN = @FVWMTASKBAR_DOMAIN@ FVWMWORKERSLIST = @FVWMWORKERSLIST@ FVWMWORKERSLISTLONG = @FVWMWORKERSLISTLONG@ FVWM_CONFDIR = @FVWM_CONFDIR@ FVWM_CPP = @FVWM_CPP@ FVWM_DATADIR = @FVWM_DATADIR@ FVWM_DOCDIR = @FVWM_DOCDIR@ FVWM_DOMAIN = @FVWM_DOMAIN@ FVWM_IMAGEPATH = @FVWM_IMAGEPATH@ FVWM_MODULEDIR = @FVWM_MODULEDIR@ FVWM_PERLLIB = @FVWM_PERLLIB@ FVWM_PERLLIBDIR = @FVWM_PERLLIBDIR@ GDK_IMLIB_CFLAGS = @GDK_IMLIB_CFLAGS@ GDK_IMLIB_LIBS = @GDK_IMLIB_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ IMLIBCONF = @IMLIBCONF@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INST_LINGUAS = @INST_LINGUAS@ ISRELEASED = @ISRELEASED@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOCALEDIR = @LOCALEDIR@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANPAGE_PREAMBLE = @MANPAGE_PREAMBLE@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ MSGUNIQ = @MSGUNIQ@ OBJEXT = @OBJEXT@ 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@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PYTHON = @PYTHON@ RANLIB = @RANLIB@ RELDATELONG = @RELDATELONG@ RELDATENUM = @RELDATENUM@ RELDATESHORT = @RELDATESHORT@ REQUIRED_PERL_VERSION = @REQUIRED_PERL_VERSION@ REQUIRED_PYTHON_VERSION = @REQUIRED_PYTHON_VERSION@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ UPDATEPOFILES = @UPDATEPOFILES@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VERSIONINFO = @VERSIONINFO@ XFT_CFLAGS = @XFT_CFLAGS@ XFT_CONFIG = @XFT_CONFIG@ XFT_LIBS = @XFT_LIBS@ XGETTEXT = @XGETTEXT@ XMKMF = @XMKMF@ XSLTPROC = @XSLTPROC@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Xcursor_CFLAGS = @Xcursor_CFLAGS@ Xcursor_LIBS = @Xcursor_LIBS@ Xft_CFLAGS = @Xft_CFLAGS@ Xft_LIBS = @Xft_LIBS@ Xinerama_CFLAGS = @Xinerama_CFLAGS@ Xinerama_LIBS = @Xinerama_LIBS@ Xrender_CFLAGS = @Xrender_CFLAGS@ Xrender_LIBS = @Xrender_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ iconv_CFLAGS = @iconv_CFLAGS@ iconv_LIBS = @iconv_LIBS@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intl_CFLAGS = @intl_CFLAGS@ intl_LIBS = @intl_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ png_CFLAGS = @png_CFLAGS@ png_LIBS = @png_LIBS@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ readline_CFLAGS = @readline_CFLAGS@ readline_LIBS = @readline_LIBS@ rplay_CFLAGS = @rplay_CFLAGS@ rplay_LIBS = @rplay_LIBS@ rsvg_CFLAGS = @rsvg_CFLAGS@ rsvg_LIBS = @rsvg_LIBS@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ stroke_CFLAGS = @stroke_CFLAGS@ stroke_LIBS = @stroke_LIBS@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ with_bidi = @with_bidi@ with_gdkimlib = @with_gdkimlib@ with_gettext = @with_gettext@ with_iconv = @with_iconv@ with_perllib = @with_perllib@ with_png = @with_png@ with_readline = @with_readline@ with_rplay = @with_rplay@ with_rsvg = @with_rsvg@ with_shape = @with_shape@ with_shm = @with_shm@ with_sm = @with_sm@ with_stroke = @with_stroke@ with_xcursor = @with_xcursor@ with_xft = @with_xft@ with_xinerama = @with_xinerama@ with_xpm = @with_xpm@ with_xrender = @with_xrender@ xpm_CFLAGS = @xpm_CFLAGS@ xpm_LIBS = @xpm_LIBS@ configdir = @FVWM_DATADIR@/default-config inst_location = $(DESTDIR)@FVWM_DATADIR@ config_DATA = config \ .stalonetrayrc \ FvwmScript-DateTime \ FvwmScript-ConfirmQuit \ FvwmScript-ConfirmCopyConfig EXTRA_DIST = images \ config \ .stalonetrayrc \ FvwmScript-DateTime \ FvwmScript-ConfirmQuit \ FvwmScript-ConfirmCopyConfig all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(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) --foreign default-config/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign default-config/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: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-configDATA: $(config_DATA) @$(NORMAL_INSTALL) @list='$(config_DATA)'; test -n "$(configdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(configdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(configdir)" || 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)$(configdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(configdir)" || exit $$?; \ done uninstall-configDATA: @$(NORMAL_UNINSTALL) @list='$(config_DATA)'; test -n "$(configdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(configdir)'; $(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)$(configdir)"; 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 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-configDATA @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-data-hook 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 pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-configDATA @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) uninstall-hook .MAKE: install-am install-data-am install-strip uninstall-am .PHONY: all all-am check check-am clean clean-generic cscopelist-am \ ctags-am distclean distclean-generic distdir dvi dvi-am html \ html-am info info-am install install-am install-configDATA \ install-data install-data-am install-data-hook 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-generic pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am uninstall-configDATA uninstall-hook .PRECIOUS: Makefile install-data-hook: cp -r $(srcdir)/images $(inst_location)/default-config ln -sf default-config/FvwmScript-DateTime $(inst_location) ln -sf default-config/FvwmScript-ConfirmQuit $(inst_location) ln -sf default-config/FvwmScript-ConfirmCopyConfig $(inst_location) uninstall-hook: rm -fr $(DESTDIR)/$(configdir) rm -f $(inst_location)/FvwmScript-DateTime rm -f $(inst_location)/FvwmScript-ConfirmQuit rm -f $(inst_location)/FvwmScript-ConfirmCopyConfig # 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: fvwm-2.7.0/default-config/.stalonetrayrc0000644000175000017500000000017414147024700015203 00000000000000decorations none geometry 6x1 icon_size 18 max_geometry 6x1 parent_bg true transparent false icon_gravity SE no_shrink true fvwm-2.7.0/default-config/config0000644000175000017500000005426514324314575013523 00000000000000################################## # ____________________________ # ( _________________________) # ) (__ _ _ _ _ # ( __)( \/ )( \/\/ )/\/\ # ) ( \ / \ // \ # (___) \/ \/\/(_/\/\_) 2.6 # # # This is the default configuration file shipped with fvwm. # # This config file is organized as follows: # # 1: Functions # 2: Styles # 3: Colorsets # 4: Menus # 5: Bindings # 6: Decor # 7: Modules # ################################# # InfoStoreAdd can be used to store variable data internal to fvwm. # The variable can then be used in the configuration as $[infostore.name]. # # You can also use environment variables but for data internal to fvwm # use InfoStore variables instead. # # The following is used in various menus and also sets the terminal # that FvwmConsole uses. Change this to your terminal of choice InfoStoreAdd terminal xterm ########### # 1: Functions # # Fvwm can use custom functions for various tasks. # The syntax for defining a function named FunctionName is: # # DestroyFunc FunctionName # AddToFunc FunctionName # + I [Action to do Immediately] # + C [Action to do on a Mouse Click] # + D [Action to do on a Mouse Double Click] # + H [Action to do on a Mouse Hold] # + M [Action to do on a Mouse Motion] ########### # Start Function # # The start function is run right after fvwm is done reading # the config file. This function run after each restart # so using Test (Init) or Test (Restart) can further control # actions that are run during the first time run (Init) or # actions that are run after a restart. DestroyFunc StartFunction AddToFunc StartFunction + I Test (Init) InitBackground + I Test (Init) Module FvwmBanner + I Module FvwmButtons RightPanel + I Module FvwmEvent EventNewDesk # Function to set background when fvwm starts DestroyFunc InitBackground AddToFunc InitBackground + I Test (f $[FVWM_USERDIR]/.BGdefault) \ Exec exec fvwm-root $[FVWM_USERDIR]/.BGdefault + I TestRc (NoMatch) Exec exec fvwm-root \ $[FVWM_DATADIR]/default-config/images/background/bg1.png # Mouse Bindings Functions DestroyFunc RaiseMoveX AddToFunc RaiseMoveX + I Raise + M $0 + D $1 DestroyFunc RaiseMove AddToFunc RaiseMove + I Raise + M $0 DestroyFunc MoveToCurrent AddToFunc MoveToCurrent + I ThisWindow MoveToPage + I ThisWindow MoveToDesk # Function: ViewManPage $0 # # This function loads the man page $0 in an terminal # and is used with the help menu. DestroyFunc ViewManPage AddToFunc ViewManPage + I Exec exec $[infostore.terminal] -g 80x40 \ -n "Manual Page - $0" -T "Manual Page - $0" -e man "$0" # Function: SetBG $0 # # SetBG is used with the background menu to set the background # image and configure it to be loaded the next time fvwm is run. # Note, fvwm-root can't use .jpeg or resize images. Use something # like display, feh, etc. DestroyFunc SetBG AddToFunc SetBG + I Test (f $[FVWM_USERDIR]/images/background/$0) \ Exec exec fvwm-root $[FVWM_USERDIR]/images/background/$0 + I TestRc (Match) Exec exec ln -fs images/background/$0 \ $[FVWM_USERDIR]/.BGdefault + I TestRc (Match) Break + I Test (!f $[FVWM_DATADIR]/default-config/images/background/$0) Break + I Exec exec fvwm-root $[FVWM_DATADIR]/default-config/images/background/$0 + I Exec exec ln -fs $[FVWM_DATADIR]/default-config/images/background/$0 \ $[FVWM_USERDIR]/.BGdefault # Function: IconManClick # # This function is run from FvwmIconMan when the button is clicked. DestroyFunc IconManClick AddToFunc IconManClick + I ThisWindow (Raised, !Shaded, !Iconic, CurrentPage) Iconify + I TestRc (Match) Break + I ThisWindow WindowShade off + I ThisWindow Iconify off + I ThisWindow Raise + I ThisWindow (AcceptsFocus) FlipFocus # Function: ToggleTitle # # This function will toggle if fvwm shows the TitleBar. DestroyFunc ToggleTitle AddToFunc ToggleTitle + I ThisWindow (State 1) WindowStyle Title + I TestRc (Match) State 1 False + I TestRc (Match) Break + I WindowStyle !Title + I State 1 True # Function: ChangeDesk # # This function is called by FvwmEvent every time the Desk is changed. DestroyFunc ChangeDesk AddToFunc ChangeDesk + I SendToModule FvwmButtons ChangeButton desk0 Colorset 10 + I SendToModule FvwmButtons ChangeButton desk1 Colorset 10 + I SendToModule FvwmButtons ChangeButton desk2 Colorset 10 + I SendToModule FvwmButtons ChangeButton desk3 Colorset 10 + I SendToModule FvwmButtons ChangeButton desk$0 Colorset 11 ############# # 2: Styles # ############# # Desktops and Pages # # Fvwm has both Virtual Desktops and Pages. Each Desktop is built from # a grid of Pages. The following sets the name of four Desktops and then # divides each Desktop into a 2x2 grid of Pages that are positioned as # # +---+---+ # | | | # +---+---+ # | | | # +---+---+ # DesktopName 0 Main DesktopName 1 Desk1 DesktopName 2 Desk2 DesktopName 3 Desk3 DesktopSize 2x2 # EdgeScroll will move the view port between the Pages when the mouse # moves to the edge of the screen. This set the amount of distance to # scroll at 100% (full page) and the EdgeResistance which is a timer # for how long the mouse as at the edge before it scrolls. # # Set EdgeScroll 0 0 and/or EdgeResistance -1 to disable. EdgeScroll 100 100 EdgeResistance 450 EdgeThickness 1 Style * EdgeMoveDelay 350, EdgeMoveResistance 350 # EwmhBaseStruts [left] [right] [top] [bottom] # Reserves space along the edge(s) of the Screen that will not # be covered when maximizing or placing windows. EwmhBaseStruts 0 120 0 0 # This sets the ClickTime and MoveThreshold used to determine # Double Clicks, Hold and Move for the mouse. ClickTime 250 MoveThreshold 3 # Sets the focus style to SloppyFocus and a mouse click # in a window will Raise it. Style * SloppyFocus, MouseFocusClickRaises # Default Font DefaultFont "xft:Sans:Bold:size=8:antialias=True" # Window Placement Style * MinOverlapPlacement, GrabFocusOff, !UsePPosition # Sets all windows to OpaqueMove (vs a wired frame) and windows will # snap to each other and the edge of the screen. OpaqueMoveSize unlimited Style * ResizeOpaque, SnapAttraction 15 SameType ScreenAll, SnapGrid # Transient Windows (such as open file windows) Style * DecorateTransient, StackTransientParent Style * !FPGrabFocusTransient, FPReleaseFocusTransient # WindowShade Style * WindowShadeScrolls, WindowShadeSteps 10 # Ignore Numlock and other modifiers for bindings # See http://fvwm.org/documentation/faq/#why-do-numlock-capslock-and-scrolllock-interfere-with-clicktofocus-andor-my-mouse-bindings IgnoreModifiers L25 # Decor Styles Style * BorderWidth 5, HandleWidth 5, MWMButtons, FvwmBorder, FirmBorder Style * Colorset 1, HilightColorset 2 Style * BorderColorset 3, HilightBorderColorset 4 # Disable Icons from appearing on desktop. # Comment this out or use Style * Icon to get the icons back. Style * !Icon # Window Specific Styles Style RightPanel !Title, !Borders, !Handles, Sticky, \ WindowListSkip, NeverFocus Style ConfirmQuit !Title, PositionPlacement Center, WindowListSkip, Layer 6 Style FvwmIdent WindowListSkip ####### # 3: Colorsets # # Colorsets can be used to configure the color of the various # parts of fvwm such as window decor, menus, modules, etc. # # Colorset Convention # # 0 - Default # 1 - Inactive Windows # 2 - Active Window # 3 - Inactive Windows Borders # 4 - Active Windows Borders # 5 - Menu - Inactive Item # 6 - Menu - Active Item # 7 - Menu - Grayed Item # 8 - Menu - Title # 9 - Reserved # 10+ Modules # 10 - Module Default # 11 - Module Hilight # 12 - Module ActiveButton (Mouse Hover) # 13 - FvwmPager Active Page # 14 - FvwmIconMan Iconified Button ########### Colorset 0 fg #ffffff, bg #003c3c, hi, sh, Plain, NoShape Colorset 1 fg #000000, bg #8f9f8f, hi, sh, Plain, NoShape Colorset 2 fg #ffffff, bg #003c3c, hi, sh, Plain, NoShape Colorset 3 fg black, bg #4d4d4d, hi #676767, sh #303030, Plain, NoShape Colorset 4 fg black, bg #2d2d2d, hi #474747, sh #101010, Plain, NoShape Colorset 5 fg #000000, bg #ffffff, hi, sh, Plain, NoShape Colorset 6 fg #ffffff, bg #2d2d2d, hi, sh, Plain, NoShape Colorset 7 fg grey30, bg #ffffff, hi, sh, Plain, NoShape Colorset 8 fg #ffffff, bg #003c3c, hi, sh, Plain, NoShape Colorset 10 fg #ffffff, bg #003c3c, hi #aaaaaa, sh #999999, Plain, NoShape Colorset 11 fg #ffffff, bg #1a6e99, hi #ffffff, sh #ffffff, Plain, NoShape Colorset 12 fg #2d2d2d, bg #ffffff, hi, sh, Plain, NoShape Colorset 13 fg #ffffff, bg #006c6c, hi, sh, Plain, NoShape Colorset 14 fg #555555, bg #003c3c, hi #aaaaaa, sh #999999, Plain, NoShape ####### # 4: Menus ########### MenuStyle * MenuColorset 5, ActiveColorset 6, GreyedColorset 7, TitleColorset 8 MenuStyle * Hilight3DOff, HilightBack, HilightTitleBack, SeparatorsLong MenuStyle * TrianglesSolid, TrianglesUseFore MenuStyle * ItemFormat "%|%3.1i%5.3l%5.3>%|" MenuStyle * Font "xft:Sans:Bold:size=8:antialias=True" # Root Menu # # The root menu will PopUp with a click in the root # window or using alt-f1 (or menu). DestroyMenu MenuFvwmRoot AddToMenu MenuFvwmRoot "Fvwm" Title + "&Programs%icons/programs.png%" Popup MenuPrograms + "XDG &Menu%icons/apps.png%" Popup XDGMenu + "&XTerm%icons/terminal.png%" Exec exec $[infostore.terminal] + "" Nop + "Fvwm&Console%icons/terminal.png%" Module FvwmConsole -terminal $[infostore.terminal] + "&Wallpapers%icons/wallpaper.png%" Popup BGMenu + "M&an Pages%icons/help.png%" Popup MenuFvwmManPages + "Copy Config%icons/conf.png%" FvwmScript FvwmScript-ConfirmCopyConfig + "" Nop + "Re&fresh%icons/refresh.png%" Refresh + "&Restart%icons/restart.png%" Restart + "&Quit%icons/quit.png%" Module FvwmScript FvwmScript-ConfirmQuit # Generate XDGMenu PipeRead "fvwm-menu-desktop -e" # Programs Menu # # This test for some common programs and adds them to the menu. # When adding programs you don't need to use the Test (x foo) # lines as this is only to help make this menu portable. DestroyMenu MenuPrograms AddToMenu MenuPrograms "Programs" Title Test (x chromium) + "Chromium" Exec exec chromium Test (x firefox) + "Firefox" Exec exec firefox Test (x google-chrome) + "Google-Chrome" Exec exec google-chrome Test (x gvim) + "gVim" Exec exec gvim Test (x xemacs) + "XEmacs" Exec exec xemacs Test (x gimp) + "Gimp" Exec exec gimp Test (x vlc) + "VLC" Exec exec vlc # Background Menu # # Backgrounds are located in ~/.fvwm/images/background/ # Menu icons are located in ~/.fvwm/images/bgicons/ DestroyMenu BGMenu AddToMenu BGMenu "Wallpapers" Title + "Floral%bgicons/bg1.png%" SetBG bg1.png + "Circles%bgicons/bg2.png%" SetBG bg2.png + "Space%bgicons/bg3.png%" SetBG bg3.png # Window Operations Menus DestroyMenu MenuWindowOps AddToMenu MenuWindowOps + "Move" Move + "Resize" Resize + "Iconify" Iconify + "Maximize" Maximize + "Shade" WindowShade + "Stick" Stick + "" Nop + "Close" Close + "More..." Menu MenuWindowOpsLong This 0 0 DestroyMenu MenuWindowOpsLong AddToMenu MenuWindowOpsLong + "Move" Move + "Resize" Resize + "(De)Iconify" Iconify + "(Un)Maximize" Maximize + "(Un)Shade" WindowShade + "(Un)Sticky" Stick + "(No)TitleBar" Pick (CirculateHit) ToggleTitle + "Send To" Popup MenuSendTo + "" Nop + "Close" Close + "Destroy" Destroy + "" Nop + "Raise" Raise + "Lower" Lower + "" Nop + "StaysOnTop" Pick (CirculateHit) Layer 0 6 + "StaysPut" Pick (CirculateHit) Layer 0 4 + "StaysOnBottom" Pick (CirculateHit) Layer 0 2 + "" Nop + "Identify" Module FvwmIdent DestroyMenu MenuIconOps AddToMenu MenuIconOps + "(De)Iconify" Iconify + "(Un)Maximize" Maximize + "(Un)Shade" WindowShade + "(Un)Sticky" Stick + "(No)TitleBar" Pick (CirculateHit) ToggleTitle + "Send To" Popup MenuSendTo + "" Nop + "Close" Close + "Destroy" Destroy + "" Nop + "Raise" Raise + "Lower" Lower + "" Nop + "StaysOnTop" Pick (CirculateHit) Layer 0 6 + "StaysPut" Pick (CirculateHit) Layer 0 4 + "StaysOnBottom" Pick (CirculateHit) Layer 0 2 + "" Nop + "Identify" Module FvwmIdent DestroyMenu MenuSendTo AddToMenu MenuSendTo + "Current" MoveToCurrent + "Page" PopUp MenuSendToPage + "Desk" PopUp MenuSendToDesk DestroyMenu MenuSendToDesk AddToMenu MenuSendToDesk + "Desk 0" MoveToDesk 0 0 + "Desk 1" MoveToDesk 0 1 + "Desk 2" MoveToDesk 0 2 + "Desk 3" MoveToDesk 0 3 DestroyMenu MenuSendToPage AddToMenu MenuSendToPage + "Page (0,0)" MoveToPage 0 0 + "Page (0,1)" MoveToPage 0 1 + "Page (1,0)" MoveToPage 1 0 + "Page (1,1)" MoveToPage 1 1 # Fvwm Man Pages (Help) Menu DestroyMenu MenuFvwmManPages AddToMenu MenuFvwmManPages "Help" Title + "fvwm" ViewManPage fvwm + "FvwmAnimate" ViewManPage FvwmAnimate + "FvwmAuto" ViewManPage FvwmAuto + "FvwmBacker" ViewManPage FvwmBacker + "FvwmBanner" ViewManPage FvwmBanner + "FvwmButtons" ViewManPage FvwmButtons + "FvwmCommand" ViewManPage FvwmCommand + "FvwmConsole" ViewManPage FvwmConsole + "FvwmEvent" ViewManPage FvwmEvent + "FvwmForm" ViewManPage FvwmForm + "FvwmIconMan" ViewManPage FvwmIconMan + "FvwmIdent" ViewManPage FvwmIdent + "FvwmPager" ViewManPage FvwmPager + "FvwmPerl" ViewManPage FvwmPerl + "FvwmProxy" ViewManPage FvwmProxy + "FvwmRearrange" ViewManPage FvwmRearrange + "FvwmScript" ViewManPage FvwmScript + "" Nop + "fvwm-root" ViewManPage fvwm-root + "fvwm-menu-desktop" ViewManPage fvwm-menu-desktop + "fvwm-menu-directory" ViewManPage fvwm-menu-directory + "fvwm-menu-headlines" ViewManPage fvwm-menu-headlines + "fvwm-menu-xlock" ViewManPage fvwm-menu-xlock + "fvwm-config" ViewManPage fvwm-config ####### # 5: Mouse and Key bindings # # Contexts: # R = Root Window rrrrrrrrrrrrrrrrrrrrrr # W = Application Window rIrrrr<---------^rrrrr # F = Frame Corners rrrrrr[13TTTT642]rrrrr # S = Frame Sides rIrrrr[wwwwwwwww]rrrrr # T = Title Bar rrrrrr[wwwwwwwww]rrrrr # I = Icon rIrrrrv_________>rrrrr # rrrrrrrrrrrrrrrrrrrrrr # # Numbers are buttons: [1 3 5 7 9 TTTTT 0 8 6 4 2] # # Modifiers: (A)ny, (C)ontrol, (S)hift, (M)eta, (N)othing # # Format: Key # Mouse #################### # Alt-F1 or Menu to load the root menu and Alt-Tab for a WindowList. # Ctrl-F1/F2/F3/F4 will switch between the Virtual Desktops. # Super_R (windows key) will launch a terminal. # # Silent supresses any errors (such as keyboards with no Menu key). Silent Key F1 A M Menu MenuFvwmRoot Silent Key Menu A A Menu MenuFvwmRoot Silent Key Tab A M WindowList Root c c NoDeskSort, SelectOnRelease Meta_L Silent Key F1 A C GotoDesk 0 0 Silent Key F2 A C GotoDesk 0 1 Silent Key F3 A C GotoDesk 0 2 Silent Key F4 A C GotoDesk 0 3 Silent Key Super_R A A Exec exec $[infostore.terminal] # Window Buttons: [1 3 5 7 9 TTTTT 0 8 6 4 2] # 1 - Open the WindowOps menu. # 2 - Close on single click, Destroy on double click. # 4 - Maximize (right/middle button will only maximize vertical/horizontal) # 6 - Iconify (minimize) Mouse 1 1 A Menu MenuWindowOps Delete Mouse 1 2 A Close Mouse 1 4 A Maximize 100 100 Mouse 2 4 A Maximize 0 100 Mouse 3 4 A Maximize 100 0 Mouse 1 6 A Iconify # TitleBar: Click to Raise, Move, Double Click to Maximize # Mouse Wheel Up/Down to WindowShade On/Off # Borders: Click to raise, Move to Resize # Root Window: Left Click - Main Menu # Right Click - WindowOps Menu # Middle Click - Window List Menu # Right click TitleBar/Borders for WindowOps Menu Mouse 1 T A RaiseMoveX Move Maximize Mouse 1 FS A RaiseMove Resize Mouse 4 T A WindowShade True Mouse 5 T A WindowShade False Mouse 1 R A Menu MenuFvwmRoot Mouse 2 R A WindowList Mouse 3 R A Menu MenuWindowOpsLong Mouse 1 I A RaiseMoveX Move "Iconify off" Mouse 3 T A Menu MenuWindowOps Mouse 3 I A Menu MenuIconOps ####### # 6: Window Decor # # Buttons Locations: [1 3 5 7 9 TTTTT 0 8 6 4 2] # # 1 - WindowOps Menu # 2 - Close # 4 - Maximize # 6 - Minimize ########### TitleStyle Centered Height 18 -- Flat ButtonStyle All ActiveUp Vector 5 15x15@4 15x85@3 85x85@3 85x15@3 \ 15x15@3 -- Flat ButtonStyle All ToggledActiveUp Vector 5 15x15@4 15x85@3 85x85@3 \ 85x15@3 15x15@3 -- Flat ButtonStyle All ActiveDown Vector 5 20x20@4 20x80@3 80x80@3 80x20@3 \ 20x20@3 -- Flat ButtonStyle All ToggledActiveDown Vector 5 20x20@4 20x80@3 80x80@3 \ 80x20@3 20x20@3 -- Flat ButtonStyle All ToggledInactive Vector 5 47x47@3 57x53@3 53x53@3 \ 53x47@3 47x47@3 -- Flat ButtonStyle All Inactive Vector 5 47x47@3 57x53@3 53x53@3 53x47@3 \ 47x47@3 -- Flat AddButtonStyle 1 Active Vector 5 45x45@3 55x45@3 55x55@3 45x55@3 45x45@3 AddButtonStyle 2 Active Vector 4 35x35@3 65x65@3 65x35@4 35x65@3 AddButtonStyle 4 Active Vector 8 30x70@3 30x30@3 70x30@3 70x70@3 30x70@3 \ 30x50@4 50x50@3 50x70@3 AddButtonStyle 4 ToggledActiveUp Vector 8 30x70@3 30x30@3 70x30@3 70x70@3 \ 30x70@3 50x30@4 50x50@3 70x50@3 AddButtonStyle 6 Active Vector 5 35x60@3 65x60@3 65x50@3 35x50@3 35x60@3 ButtonStyle All - Clear ButtonStyle 1 - MwmDecorMenu ButtonStyle 4 - MwmDecorMax ButtonStyle 6 - MwmDecorMin ############ # 7: Modules ############# # FvwmIdent # # FvwmIdent is a module that can be used to get the various info about # a window. One use is getting the class/resource/name of a window. DestroyModuleConfig FvwmIdent:* *FvwmIdent: Colorset 10 *FvwmIdent: Font "xft:Sans:size=10:antialias=True" # FvwmBanner # # This displays the Fvwm Logo for 5 seconds. This is displayed # when fvwm starts. DestroyModuleConfig FvwmBanner:* *FvwmBanner: NoDecor *FvwmBanner: Timeout 5 # FvwmScript # # FvwmScript is a module that allows one to write custom desktop # widgets and various other tools. This config uses two FvwmScripts. # - DateTime - uses the output of "date" to display the date/time # on the RightPanel. # - Quit - This is a popup that asks for quit confirmation before # quitting fvwm. DestroyModuleConfig FvwmScript:* *FvwmScript: DefaultColorset 10 # FvwmButtons - RightPanel # # FvwmButtons is a powerful module that can be used to build custom # panels and docks. This config uses FvwmButtons to build the RightPanel. # The panel contains buttons to switch desks, FvwmPager, a system tray, # FvwmIconMan (list of running windows), and a clock. # # Note - To use the system tray you must have "stalonetray" installed. DestroyModuleConfig RightPanel:* *RightPanel: Geometry 120x$[vp.height]-0+0 *RightPanel: Colorset 10 *RightPanel: Rows $[vp.height] *RightPanel: Columns 120 *RightPanel: Frame 0 *RightPanel: Font "xft:Sans:Bold:size=10:antialias=True" *RightPanel: (120x45, Icon "fvwm-logo-small.png", Frame 0) *RightPanel: (120x5, Frame 0) *RightPanel: (10x20, Frame 0) *RightPanel: (25x20, Id desk0, Title "0", Action (Mouse 1) GotoDesk 0 0, Colorset 11, ActiveColorset 12, Frame 0) *RightPanel: (25x20, Id desk1, Title "1", Action (Mouse 1) GotoDesk 0 1, ActiveColorset 12, Frame 0) *RightPanel: (25x20, Id desk2, Title "2", Action (Mouse 1) GotoDesk 0 2, ActiveColorset 12, Frame 0) *RightPanel: (25x20, Id desk3, Title "3", Action (Mouse 1) GotoDesk 0 3, ActiveColorset 12, Frame 0) *RightPanel: (10x20, Frame 0) *RightPanel: (5x80, Frame 0) *RightPanel: (110x80, Swallow FvwmPager 'Module FvwmPager *', Frame 0) *RightPanel: (5x80, Frame 0) *RightPanel: (120x5, Frame 0) Test (x stalonetray) *RightPanel: (120x20, Swallow(NoClose,UseOld) \ stalonetray 'Exec exec stalonetray --config \ "$[FVWM_DATADIR]/default-config/.stalonetrayrc"', Frame 0) Test (x stalonetray) PipeRead 'echo "*RightPanel: (120x$(($[vp.height]-225)), \ Top, Swallow FvwmIconMan \'Module FvwmIconMan\', Frame 0)"' Test (!x stalonetray) PipeRead 'echo "*RightPanel: (120x$(($[vp.height]-205)),\ Top, Swallow FvwmIconMan \'Module FvwmIconMan\', Frame 0)"' *RightPanel: (120x45, Swallow DateTime 'Module FvwmScript FvwmScript-DateTime',\ Frame 0) *RightPanel: (120x5, Frame 0) # FvwmPager # # This module displays the location of the windows on the various Pages # and Desks. This is setup to show only the Pages on the current Desk. DestroyModuleConfig FvwmPager:* *FvwmPager: Colorset * 10 *FvwmPager: HilightColorset * 13 *FvwmPager: BalloonColorset * 10 *FvwmPager: WindowColorsets 10 11 *FvwmPager: Font None *FvwmPager: Balloons All *FvwmPager: BalloonFont "xft:Sans:Bold:size=8:antialias=True" *FvwmPager: BallonYOffset +2 *FvwmPager: Window3dBorders *FvwmPager: MiniIcons # FvwmIconMan # # FvwmIconMan is a powerful tool to list and manage windows. This # is used as the window list in the panel or taskbar. DestroyModuleConfig FvwmIconMan:* *FvwmIconMan: UseWinList true *FvwmIconMan: ButtonGeometry 120x20 *FvwmIconMan: ManagerGeometry 1x1 *FvwmIconMan: Colorset 10 *FvwmIconMan: FocusColorset 11 *FvwmIconMan: IconColorset 14 *FvwmIconMan: FocusAndSelectColorset 12 *FvwmIconMan: SelectColorset 12 *FvwmIconMan: IconAndSelectColorset 12 *FvwmIconMan: DrawIcons always *FvwmIconMan: ReliefThickness 0 *FvwmIconMan: Format "%t" *FvwmIconMan: Font "xft:Sans:Bold:size=8:antialias=True" *FvwmIconMan: Action Mouse 0 A ret *FvwmIconMan: Action Mouse 1 A sendcommand IconManClick *FvwmIconMan: Action Mouse 3 A sendcommand "Menu MenuIconOps" *FvwmIconMan: Resolution global *FvwmIconMan: Tips needed *FvwmIconMan: Sort id # FvwmEvent # # FvwmEvent is a module that can run an action or function # on specific events. This instance changes which desk number # is highlighted when the desk is changed. DestroyModuleConfig EventNewDesk:* *EventNewDesk: PassID *EventNewDesk: new_desk ChangeDesk # FvwmForm # # FvwmForm is a module that can be used to build a GUI # form. Used with fvwm-menu-desktop-config.fpl. # This sets the default colorsets. *FvwmFormDefault: Colorset 10 *FvwmFormDefault: ItemColorset 13 # Local configuration file. For use with the default-config. # # If $FVWMUSER_DIR/local.config ($HOME/.fvwm/local.config by default) # exists, then read it. This allows changes to default-config settings # without needing a full copy of the default-config. This will also allow # default-config changes to get used after upgrades (if applicable). Test (f $[FVWM_USERDIR]/local.config) Read $[FVWM_USERDIR]/local.config fvwm-2.7.0/default-config/Makefile.am0000644000175000017500000000161314324314575014354 00000000000000## Process this file with automake to create Makefile.in configdir = @FVWM_DATADIR@/default-config inst_location = $(DESTDIR)@FVWM_DATADIR@ config_DATA = config \ .stalonetrayrc \ FvwmScript-DateTime \ FvwmScript-ConfirmQuit \ FvwmScript-ConfirmCopyConfig EXTRA_DIST = images \ config \ .stalonetrayrc \ FvwmScript-DateTime \ FvwmScript-ConfirmQuit \ FvwmScript-ConfirmCopyConfig install-data-hook: cp -r $(srcdir)/images $(inst_location)/default-config ln -sf default-config/FvwmScript-DateTime $(inst_location) ln -sf default-config/FvwmScript-ConfirmQuit $(inst_location) ln -sf default-config/FvwmScript-ConfirmCopyConfig $(inst_location) uninstall-hook: rm -fr $(DESTDIR)/$(configdir) rm -f $(inst_location)/FvwmScript-DateTime rm -f $(inst_location)/FvwmScript-ConfirmQuit rm -f $(inst_location)/FvwmScript-ConfirmCopyConfig fvwm-2.7.0/default-config/images/0000755000175000017500000000000014147024700013633 500000000000000fvwm-2.7.0/default-config/images/icons/0000755000175000017500000000000014147024700014746 500000000000000fvwm-2.7.0/default-config/images/icons/apps.png0000644000175000017500000000012214147024700016332 00000000000000‰PNG  IHDRüÇFÜIDATxc 2ø‚ØXÔVDW‡:œþù¬P°ÉOIEND®B`‚fvwm-2.7.0/default-config/images/icons/wallpaper.png0000644000175000017500000000026114147024700017362 00000000000000‰PNG  IHDRüÇFÜxIDATxc 2¼dø‡ €à½bð‹€”àTô( Âp9 a8APPÉQÒ¬£â3’Lr0œcHÀå;E†{ @z.ÿ•A CD?¾ÍP é« \hŠ úÑà’ƒàÞ~QäžTP”øl¶ tºž ¶IEND®B`‚fvwm-2.7.0/default-config/images/icons/restart.png0000644000175000017500000000034314147024700017060 00000000000000‰PNG  IHDRüÇFܪIDATxcÀ˜B˜Jv£ä?J€Ð‚A·¢ ü˰‰A¿I^ ­ ï¾08r“$Ãe†÷@’€ïT~1ôàv> lb¸…*eÏ €¡¼•á7ªÀG†IЦ]…v3Üa`Baf¸‡úÁ@_•¡ˆTEÐ _Íð¡ƒÌægè*Yé+6†9@‰ §ð5“»÷€!³ » hG 3#ZÇIEND®B`‚fvwm-2.7.0/default-config/images/icons/programs.png0000644000175000017500000000032014147024700017221 00000000000000‰PNG  IHDRüÇFÜ—IDATxÅÌ1JÆáÇ!8‰8¹;,¥'(:”ÒÒ”,¥kK¯`¼SNá<‚‹H$ ò þ!}¾õåÓ»5uoУV/æ¬uBø²ƒl’²77’Ò‡ «$+¡µ¤ µd&„OO}.’+¯"íH¶ñ“¢Î–lïÝxæÎÁ³“³ïœePýwö0ž5 †³Æµ¥~–^bн¶‹IEND®B`‚fvwm-2.7.0/default-config/images/icons/conf.png0000644000175000017500000000023614147024700016322 00000000000000‰PNG  IHDRüÇFÜeIDATxcÀÚ : À†ÿ@8›”.Ãf†@x¨ ‡¡Hó7#™ äü‡A ’‰H¼ME€\ìðº¢$X@‚¢¡eÝJ¶n3NEŠt€qt•h1P¼È˜R°GOòIEND®B`‚fvwm-2.7.0/default-config/images/icons/quit.png0000644000175000017500000000033614147024700016360 00000000000000‰PNG  IHDRüÇFÜ¥IDATxµÐ1JAÇá¯7wФÄ+D-Ï!Ägâe6UX­ÌAK­e×Ý~ì–Ç–ùÊáoø;¡$ù× ÑÄ—héÓƒ=úpAôêÇ•Ýè÷²§âܳìÖäůó"ª v&{ïGû"*&hÕñÜ 2·0JâÇmÌmekÁ›Îµ œ€¥o ,lõ¾\šYid££Ö(;” pg§VKÖNâ?6ù}£aIEND®B`‚fvwm-2.7.0/default-config/images/icons/help.png0000644000175000017500000000046314147024700016327 00000000000000‰PNG  IHDRüÇFÜúIDATx•Ñ­RqÇñOclÎÂ9ÐH&á ã¥jð`TïÀ™€àŒÈ£x^W Õy›ÉÆ€C8þƒólŒÂ÷SÛÏ‘‡U¬Ýdÿ¤VÊîJM´‚¶©‹ƒ:yG[5T}ôI‰}°vVÃ;'Ypò WK€ØÍüðS5øå;˜IEÀ@¦>{¾HAG¦Œe ò^ÙúŠ2£G£Ä/ÿ†ù¹6€¯~{èÊô€Hj à&€¹T `å"l éj@ÙÁ^| é`'"¯nïb¦£tÍ]í¼vWl)•?x!ò°HßÈPOɳýdRv÷š~©IEND®B`‚fvwm-2.7.0/default-config/images/icons/terminal.png0000644000175000017500000000031314147024700017204 00000000000000‰PNG  IHDRüÇFÜbKGDª#2 pHYs  šœtIMEà !.$;º.\IDAT(Ïc`Êð™á?ø™!¡hV%ÿþ3ìf````b`````Ái+BÃAF,ð D’‰'YEúàÂЀEVá6‚Âð kxd€D!r*³"­2VIEND®B`‚fvwm-2.7.0/default-config/images/icons/refresh.png0000644000175000017500000000033314147024700017031 00000000000000‰PNG  IHDRüÇFÜ¢IDATxÎ1JCA…áO!$îAp5‚à^ BaÌìÜAÊô >|EŠlClâX]›iæ2ÈûêŸÃѱ0ÁnJÿeWVFE[]7NÂÞZ(îú+'_n¡&\ši¬DMÔ„W£½ì݇F±–=ûÑøõ$Û8k|z“ ^Òí{a©1sQ“R“oGsYMÂÆA8ºÖµÂÙ`iNßÂNèK™)™ìK(2þ½?hÐIEND®B`‚fvwm-2.7.0/default-config/images/background/0000755000175000017500000000000014147024700015752 500000000000000fvwm-2.7.0/default-config/images/background/bg1.png0000644000175000017500000121007314147024700017055 00000000000000‰PNG  IHDRæVð¶Â: cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿ‡Ì¿ pHYsdd–ÅÝtIMEà --$êóFtEXtRaw profile type app12 app12 15 4475636b79000100040000002f0000 :rIDATxÚlý‰šÜJŽ, ê)æŸî*)#¸/¾’αdêTußyÿ3¸3uºïŸ_•–Ìé €Áð#L˺.SÓ4Í˲Løm˜×m\3è²é>>ÔÐeYߘ±oìàTÛÖU£•ÖJum[5ƒê|§ë¶k«ºw]ñë£ÒÖÔEgš¶/\[þúÿÜuçü×Z–yY¯ªZ¹ªÅ iUš±Å—έí«V7·lr…²­¶>¯º®Îë®jºÊª¶Ã6yY•ý8ùóØ–yž—s™·-Œóù8·ýùÀ…[·àýüx?÷9¼>ÿú×ï×±'þr;Ÿ;³¯ËãÄ/øèxýñØgÜ‚yç·¤¯•_Û¾Ÿë¼ìÇ:¹¡YšQo]×TzÙçaÚÎDZÎÓ²­Ëz¾¿Nþ×´nxùW´ûvœãÀßmóù|žÛºã2÷ ¯{,òfÇ·|áŸùæËr¼ùm¸¤ç̇Àw­ ¯{™ÖóyÌ£_öe³nšÚÿM¶7Þôw~£ÓÆyoõ³·~¦c^ܺØ)Œ›sÞMý°µjnÊ>ë×­«ËεÕR·Æ÷yíŠZ{ÝôC×êÑu­v󶌶jF_®©j»cï-žES·aîòZõ}YôÞY7·ygûºn”êqwöÕ”• ¾7ø=OZõÎ4vñ9®<ؾÇQêl¥tV©{‰³¹/ékÅS^x¿¦qð~µV÷MU”·uQ7zàe®#ò²ÌÓºmóàpxæiëâÕ2ùu›fœñqÄYß–€[5NÍýÞvyil™õº®p˜«Æ6÷oâ@¼‘îêriÃP•)ÝVÝàZëq{pγÞYœÇjèꮇAÔÖm‘ey_ü³Y¶y<žë8oûħˆ3÷|>8yóù‚€›a ßf~çƒ_+MOê|ø£µµÏ[87e Þç8iæÛóõÀKòµø&x9XêÎ7âëã%÷óõzÀâñâûãM3ßplÅÝà=’•ŸŸýõ>Öýy<ߟ|Áíüü×_Ÿçºìÿ‚«ÝNz€Æ1ØBƒRÞ÷jžúÖûÆÃЇÁù>:‡ƒ4Â>á:;ÚA¥ÇÆ-MÚ²o{­ÚºiϺé[xQ¸¦.àd¼µÞTEÓ–¾(ë_YWÀY-4‹5}-üvÎ{ÉG1 ãè-_ÓÀ¾[£;Z¿¾÷%СâFó¹‡v ¿½»Îã/ Ó§Ožpà‡¡¯J|€"3xšFk8›¦÷]VÑMÓàp›q7µ2™5wXq¯:¸.‡€æ,îS {7ðO|aYT5Í\µUQÔ}þ³¿ðT®Ë0 ¤›œ&Ìaù?fü?œB"Ž,>Z4óiv´|[¿g:š/BjYiƒ7ác&»lµ• ùM;Äèºêú¶Ò-@€õ}•à µE™ß5Nò¶–ÿY´‰…uŽÇQêÚ²†¯Ú¾‡“n[®•k×—êæazçl]á¨ñ¡áëãHtf:pq±ÚŽ8ß}íÞŽ£=Žýe<>!Îü8Í|•¨ Ï­o]ä)`tø«yÄKͼÈ=}IáÏm§ÒÇk:•ëqÂ':„9üÔŠ@1ÂaàûöA A¯Šç†h Æ_È‹ÁÌÏs—·„k§CxÐÕò?ðø®ÇÿÀóð¢¯À%¼Ÿ‡\ñ²¸Þà !4[cŒî–Í´n@L3†çO„+óeÜàûzã¡5,½ºªwˆ¸ÂsSÝ­mquW}áeÞõ<Ö ÁSáñgÝtßÖeóߌçW”Æéº1ª0å/¸1Û•­Ó9œ‚ò£Ö÷Z«¡ÝÂ=µë­C/³¼Ã©5j°Å^eÌîuVjïþq\fNß 3Øf"¡ÇtB7>¸‡ØíöÂó9é¿}Xå>/ ûx(x*pðõ°k: Ú·s†|}k›šò£Õºï­wprfPjU¸fíΈˆÇÚþTúv¯à`çµ™{EÛ4vŠj­º®(z£à¿züuÝwÙ­í;=1n.ÁM‚ÊV–“Ï^ÿ8á«p‰ø\ü|óvâÝpysØoðW|F3Ú)8›°jÆÁäº/ñœÚÉTv„CFdìú²´?‹:ÿUøc ·à}o7D€ºÉñ²4~.BZù첌ªÌÿQày‘wed†*oñ^î>"{Ö#Èëq ̾Å­Œ¯ë¾Ì¶_YUäj‡y,o€IÚ³÷]a»Q»n½Ík\é¶Qþ©Bï? ®ö|l#@NHQ÷ÚÐv‰·Å3ê7N?žïç8¯O u ö)¬¯½^OZÎ)©É$þ3ÐCÀû,@&ÀÌù·4Àø59âGˆˆš·sÚ  Žñ²32È‹É]›x >! :¸Éx\Àáð]/Ú=¾‰¸mg\‡ù?aËü#NìÄYùïØ+^'g}ôëþúýû9{A øš`^ƒ˜"ØV‚ðç5ÌJ;,ÛÊoü<óOV^)çðj˜;`íÆªº‡5–m×úz@±>Gˆ #lg5N0²'Ä8È®¼rˆèpìQÓ¹¹Ð§@àŸ›1¾Éo•_f¸z=\£ À±eÕˆiùÁ|½uõ‹Ý 7{@xøô§Ø~dÖ9zy&ë…ª¦íq.aZü2¸ 6ÃÇ3ó~ÚFé£ß—Àí|ãpØç£Ù`öAÌŒ?Ó#> 8桹ݼ[X'§F¾£[89 c¥Ý"þ {ët‘×#}ØàM sè5)Ϊ5?eÀâ>Áúû¾Uõ-£÷4ç€bÏ ®ZÌü8€è"qaç‰±Š™Ë¥J BP¡#£¯ÂÔ2Z`wcF<_<ÌþC)¤Yª™m>Ì­÷©J¸&¸à Ùùáñ£IK^'\b„Ȱ7äÇ0¼çeå» æmƒÇÖúÇÊwXýÒêeeFµ"sNs“E2f—G<Šûýóãñ¤ã‚ð;º‚³Mê1:!ïÜ)oÆx. ¯¿ˆãï×ë_¬ àaä'b<ž¿`ýõ¿ÞH;‘¶mânæÉáÀ N 0lMÐ>93Àñã ¹H ¶„‹ ¾wuÄÀ'[í A‚’Ò|NHp߯´ˆaº@ºUµàiÛ7ÀÓÊf?KÕì[$ ‡q ] §ŒèŒ„8ïá§‘~•·V¼-ˆ!<Ì®¹±ýja7y…·èDÈ:îz?rG~eÚfU9²rŒŸÕrâqóáÒ‹ÿo3_¼ƒd ´6ŠòÛDà?Ž|&Ï}4#“t:‰™.—‘[ªN3]CÃ.¨¯ÐU@©m£<‘Š nî=Éà8Ãf„Ãï,î :=B’÷ h WÛ‚ª…»kYr€›Äš›çãofN”Æ Î¾†‘•ƒ}=Ë`¼0œÖ B+hŒø—`èSµ…çžq…ì̼t¶¦ÇR ßkdÇÝíî_Ïu¦ø¸[+qŽ€)† % Lò¸!ÈêXÀ xEÞ–eÞuxÒ8°}f!Äl8)eOj{$ϰsš;nÐPUµ9C2BvÓæ·ž¹~@~Ýy Ykqoräd8Dµ¶ bîRÄÇ6ç_z‡j鈷FϦKGXãš,ïœS9Á3n"H¯péóù<Ìt>Vœï…µ¿ 4'¬ÇGž—ãu•Öâͪã“Ç# nÉä¿ lø¹ÃÌpÌ8f”ÞÀµ6¥¢[L€ï{¾‘Û?o¢qkcÀ–×â[ÆÜ’…4‰å{Ê6)ÄÑ¿¾~ÿþýõ¾P:Þö-na;ß_Ìíiö¼~@&DeGæHÌÍñŸ›†ÞnsËhÎã §™[Ö¡¢òàºt}Áßš ±ºƒõ±d ˜Î$·-³v ¤Ûþç½En|éÇúVáLÕøÞÞU¹eÖ…oJD÷¾È{6DCÅs¯`4·–Ðé¾ܨaæCÿ‘ö7° çñp—ÙñŠô}•Ý.+´kóQõuQ}ÜÔñÚ·Ö7ÉÅÿhçã£ýKP— Óƒ®ø$‚—8 L>œi)›Ð”øÈŽçq˜¦«¤'ЉVà,|bË¢„R½Æ‰±šÖ°™W½äÈ“½•škuCêA+¢Wô£¸mÌ•?uÇšb ÷À„è[ÝKÜ@Û~`(øíñȬªá¥šæQ‚*Ú‰‡Ë¿™æ.Ÿf­E4‡×l¾‘"Ä8ÝÔ™Â[ñÆ÷Ó¸‡ySò1uÿy7ßkÁì4Œ€Äe‚qOÃè=×í´‹#{Ê®r`o :9øä.«>iù%~?o4ïU×™é`;Ó›ewºýÕ´?Upzž«Ÿ©aimUšr05î0’yü„†‹`¨©q› xIø=Ü ú8ìñù€¹ùׯBⲋS"Ð>9VUqÏPŸ¥T<× ïûóKBò¶H¦MP,‘ü[N“:'Høg©ç·™Gg°?R²Cò¾ñ¡xÅ.BÖ Zâõæ„ó ˜á<ö+÷™=rÁUÊîbëÄð1YØR\?™Oà18#m±öóý—ä¢Ç:¿÷ àëXñt¼j€©½QÚ Þë½WSP¸¹Êø‘ÖÃõ«ÓÌáèÂÆ¦ÆyV~h‡ a¨½uˆò…8ÖT5P˜fù“²–A!î¯3ün/µ9:d°¬=kVÖ0Ü‚5– )¾€RUWüDôWðäU-.¾ºwh2

æ34s<áFU×ûOŸ]·AÕ¾ûh <Ðþ¯{ñ‘O‡ïæ¥îLVtk_JùG»º45‹w•q@;°$s#†«ùÜ ·s}Ÿv™÷Í Çcz¾f8¦yðl'ï%qbÖ…›6¬¿³1ÀópýÛóµ çëó}â¬#=’¬–~OÕpš£X$Íìùz°Ñìü„1=.3—2ûóõ:Ÿoêõùù9{\Ú€ÃY׆üíq~=5·õñɺø+p8kl´ŸÌíYg”%Y`5Ž6¼éŽ ýB,—r=Âù²³HÇweÊÆ~`+¢9°)> "rÕ#»EZ(uW;;ŒNÙI*⣦Î|Ž|p½ø]mp¨í:÷ËVYÛ»¶ñN2‚¬nr À XZ¸:g®T/Ûóë|8£/~:|Ÿê² g*ç:˜9‹o5‘-‚[‰ô®£ø‰ðR7vš,yC…ôW \0ڀÜíVçÿß®¼1>«`;ý°¬ïß/f,ìòðÙþï†sî5úBI2Ý ?Ã6x|§‰Éš‡;EVýü|Ζ•ÜÁõ1Îp”£*­|'ö<,ÖÍ™Ñ!iî¹VyË#N!²aY±Bh§}Â@=î½é@ˆb+v¶hÙGFÛ 6 Á”%3!×ßB»VEžå°ÄJMWC Ãpµ ‰qELG¼e]˜6GPͬ>_ð4pê0ë¼q’¤7¦×t*Hƒ=x"XXÙßòî#cí¬êXñÄâ“f>9X;îÂÐ.1‡Éèœ p±çö÷Öݲ®¬a~È”‘—6eÓ6žÍV™†»3Í­ ­|u}5 pÕ¸xÆ´Ü{; ¯*ƒ„x^ß3â~1øÕt5<|ÛtÎÊÀ5žˆ/Æ÷÷Ö5™ö][T=»¿KlU!©Xcz6§ä‚mbpˆšÅʆýÜG Ëc©=hÇ‹çD‚1 H§ƒÅõ°ÆøË´÷ÀS`={§°o’Ò °<' Ô9ùit󤪖-਀eé_ ËöÒOïu6¸–•½Ä:¿v…ˆ8êº{]#ëÜе¦ËëñÖ™úž×M®\WTmS»ü£rÇ8Ö°˜ªÒåÖºéÓþ?H܆$VýT½MeÙ¿î¯ ¬QäÀÈãñ–‡ŠÃûpî+SU„iž\fe‚¶ö“Hüµô…¢8Y¨pß'bR6£WØÌÕ‘Y#üZd… À"Ñ–žwÙ˜üÞZÜ*s ¦@ð#Ûtˆ0&¢¸U•Çc­ “ªõÏÏ4𥓨g2¦2éeVªú'òU8w™÷Çë ø8¿K?]®g‘E† mlØ=RiVN‡$åÇe Eà­áàu§Ê.o›ÿ,§²Ùºÿ¨›Ô]›ß˶MçX” ˜ÅWÀZ¶e ûNÐK*NŠnŽ9‡aà ½ok<£ Ø<ÓtÕMV²»§ÞXDqøè²±Àô}Ô]”EV»†eñ¾-ހȭ6»Ë«ìŽƒWVc“œÙ.Ü >š™Më®&’Ä v¬ûxdZa–Žst‰C·ú̬†wJþòA$„³@Ć6lÓR·]x1û…%3Ækñî±)õõ-6¿¶Èš‰¦¾Är«Ô}F|r‹çªúðcbœÇG îëõs×íc^Àô1^,މ‚©ø'Ý[öôµô]ëóµÎçÁÏË_`I†9!Ì<;²öÃ^F§`Ÿ>O~dÖF3J3bÍ@i¦÷º =Ð[@®†üœ‡ÄfÖvü·^jt°Uô¼ïGß—µ¶0ñƒ7`¥»bš,Þç/7¨º`æ®UyØà$êB€G^!¶<ök@ÐðB›ÝNËioqÛ°$èŒBV9:üTI˜¬ÜÕ÷¢óò‘cF9‡)é8·±T„³DK”B Eméç§«î´‡ð¬ [Dx6C“¿¤­Š;aIöæ%v•ÆÁvHK+@Ь`ÚR0P7e4Üâ®”ßÔ·$¨ãÓ+Évœ—OÕ+¦IFážòHWI¹˜GÝôÕ­ÀÍ—(!™9¼÷sq–æ=\%äX’%­Búê»$‘øˆ¸–å·Ö2ƒ”MÝt¸çàùÖ„üWóñÿTœª‚Æõ6ŒÂ‚™FøÃ~_útËô#Þ\©kˆ?αк(áÂÚB©Æî§*Z k£ŠÌ²OÎ>+“ºž¾/ï$¶)@‰&kWU²±ÖÝjr)p_O_TÙ ˜fÞâמ ¯S¸ŠýÉVyCâ‰p(JÖî•Ë k‚~^Ú}0£X?]¤‡K>”Ö'|VDkü[8&0k‚qÉ”£ž©Ð&6$¥°ø£8Qû¶¤÷”R¤x<üXá|.FöXa™ 0F´á="…U¢4ÑÁÉ7'αÎþx’(÷‰ ýõù–·ˆÿ<É꘤“r,Çï¯1?„åx"˜þþ<ྼ¶ Ç(&J¸yδýØ"ÈÅÂ`‰Ûq‡A»ÇÊŠ%+¤è#œA0Ê °îL3Þ2U’´dÕjràðšóù~?JIçÒ /Áã§Ý LZixÿà"ðœÉ‹ q±V< Ç£¨¦±b½Ž¥›ùÖˆéY­RÞNO83ø–šY?p |‚¥Èvñø+ ëÌ–R`a –‚º¬säA°º²²‚µ²HCì‰Tv$U‰¼—™±|aÍ„iÎ|\ètž"~¾rsVóà2mÒ1ʾ¬„i"%Ì™lšy–6ö‘ˆxJíZw¤¤Uf×ç"ŒõJˆX] ªÚ¼d0hË¢¦$û–7%”ø”Ç1ð:øg6€˜½ KÛñ²'ïÓv~$§]t \Ø™C¬”ëïù¯ÐR­qâ™yŠŽÇeælªMCؘðOóo03 Í•,¯‡i ¿§¨FØ69\‰Ôâù[CÆ›¦,›)°€ðÜŒMÓX<ò^âàÆÜšNeœ§ßK ·aû ®½,€w¬xtÛà+ è7ÕÁÆkxS8ضn]˜Y†bûqñ’›ñq÷± 2³k?â «Šþ%V»öSB>ïåñD|Z£™ ,dgÚŒ¿?b‰LlT°:xËé:R÷e䟆Á²€ÝÔ­=üÎÇv•ÎA~Ë Iý"uÖÝÉŒûë¯O¤‹ƒ%õ’¼ï}ìܭǶ=?_ã‚$ÿ±Œ_ïù–l§ ¶É(Òð”N÷}k­Æñ›ƒÀÞ‘úâ™Ínt8>t ÌV!ÆãfZ§´ÉB㙥éÁÈ5Y3ÃöØ VÚ”˜n—´r,ÙØ˜×ÃÏZ ÇM߀GO #˦x–<:W÷ê£ ¶„¹%´¾'dš1q´Ê“:kB=\[±•ë{k¦È[k²ƒÝñ5J%? ‚¾°•âý(„8@Q©¡®Â`¢6£;KôW¯Á^:ëD°äL#;#Ìñãá!)v—,x ‡ ™h|ƒœi³•|Á¸'"ÅOII—ÌWÆó–þ8¤A íæY7©ca[DIú°€)}Ñã¦àûÉtÓ9:*áýÙ, {`Òq‰•Æ`ƒ·ÀoÈ?ñRYãdMZ¹ºÎ[½0m`Ñp‡¸ÎÀÜœXÈÏRµœÇuÅÍý±më7/$Er1s˜æ¨É‚g«ó–­Ôb[¸îž„t×ÞëP¶BšDö…”¤©ÉMmš2Ï:ÖÓŠ[ÕÈ)‘5üžYM@P*7b"`AOðæ Y% p´¾ÔmNžM=Ì3É‹SˆÇ•®é2óõ²ôiFû8„b°ÏDHâ c‡õ8B$J ßñ¸Ìœ¹)°Wn-9ßø—?ÇbMÍô§8ˆy"ù î¾è׃5ã2ó-µÝŶñnˆÊ¤¢?_1Ù>ß³F>¿ÍVøsç™8msJJð2È:p2‘ZäËdìÁ’´éØÑ•𫘩¤#žã7ÎèQãõ&Rà Âå8›snüÜÙ ñÝÚi6,«´$¢:yòÇUüŸ± Ôt¥‹Ô&ö%2™Ô¬´òçä\ÚëªÊ€åj2"qâ‰bY+À¡è³í?Û€LQ¼ý Mí·¶®öz‹Œ/LˆsºC"ŸÐ7·¶ÔÜþ¼Ä.ö$Ç'Ï¥¯¾kªRòBüŠ_! ŒQBfœ#œ”Qf‡#ÉQqÚåÁHB! ™bïƒÐ˜µÑ¶Ë²Ž\y=à}I·ìï%0 ‡u>6ßïûö]Y'‚䯥„Á÷«·¦°ÍŽ9ë£Ä]Þ@&Ã"£Vrú9A·zã ~uc8dvlçU‚ÛŠ™øóµ su_d^Ñüõ 5VäÎçë8RUæAªÝë Þàý¯ÿþ7«søúú}>Þ¿ÿú<' ÜgF_Îîag›0ZÞ‘ÁÂ`uNðÍ ñnb8¼Ö[rÐ8k`>ø´Ýqï^¬/0Ÿ²ß)~f~$z¶f~à”¯À•VE_Àã«å³ƒñW•B^ òŒq¡néG ¿ódQµƒ-¨qœ]Ï2ëZ€ÉÍ/ü“™à=ü 2ÉÆF\( MNM†Êrœ†¢DL‡ñgyyo»ì£¬2 ˆ¬îI?EúÁH^pËa¼ûcàÈ@=‘2Ñ*¾<Â?I hfô/Þ4<×wà“’ïÞ›Õ8¾e¤B^±±C8¯ÛWů™šÖ¸¥y7À*ñ„j7ºª±+ÛŽIyKJ7R]\yÇVˆã‡Ç 'e\wBSd!`ÞÙ‘xˆc ÞöJ„°¥Yg0j'WÔe©Òçþ^i]Às|¾Ï… !œÖ‘nîD7è¡9Ÿ3oÞ‚)üˆÆcHíï†â¹*«öCi€§ZÁÛE§u ÝÙ63-ÿØ•ò¶…›éë[‰`\«ì®…ðTþÁy#ëf¼èúJÄkUx¯"Øs¾°fhéBÚ¹9~¢SE3ôÿøgÕ—52©G¤žO£ŒÁ°®†Z4s˜ ÛNðŸOÖ¼ÎãLR¨‰Å†ØÉ,-7SCMB÷‰Û ÿˆ&-}íp‘#]åf-i0#QúúˆDÛà¾"Ö… ô¯)푟c }Ÿ…‘ÚóÏÇd‡ãuÎ.ì/<œñÍ©5!s×?^ýû¿þýy"ª?¿þúë‹C«¼RÖÙ‡ñ,uä^8ÀÇŒ,¡O3ÒQ¡ûÙÑø`»qîGÎ|µ ¡—nÀ°FlɆsê½r2VÈžše拃~†a}>KœócMm‡ 'gض!lðBÏc²Ë2äºnÐé òá­ Š¬÷Þnä5r.<[ÍlºôsØ2SÒ!UÕháõdÁw‘ÓÀQI\8û “I¡G×ìÊ<"Ìû^TNì8€œÃÌ?`ùuÉÙªìƒîÊä³ÌIÏQ Öœ(ãD*£ej–E6 G&)ǤŠ;]Àñx½ßO¡§²Ò³÷«Dä³½>Ÿ]æýˆÕ(xÙaDBÇ¡é0¥¹\O, ̡͓?Ž X,¾=ø@Ã(.n{œ ÊŒœð=¬º¯¯ï÷&ˆ…BܵcŒžz£fs¯>!õëú1hÇ©phÅ€Åïôgù¹€^¬[ûÞ¶ÆÂÚ½•žɪÖ¨-.z²:”­·D'ˆÙCœiHýe•R‰c•“Aw)6 ·ùgãÛÌmä=pâ¨EøáxÓó*-RZ3½}ÍI8Ä‘°­ƒ×dBM5"¯C´?LÖâ9tâ‘áW€ç÷\RñüÖÕ·Úª4øâVÂ3t8êÝ-§-ä,|—y^K†¨g™Ò*„óÅ_Ñ¡¯/‘ßp:]ŠŸ³ÌŽHØŽ®¨·Rãá¶=kË}ÙZ@”ʳŸ³Ì1æŒyEÀÚ¶BêíªÖvrÝd+ŽåYŒÓá:Î_ÂVÔ€üd`Kº*»Á+ƒ‹gP»01¶^V ]Z†2óºåˆy |,±4oÝON¤MÏYHÅú^2(-O/1jqÖ<á¦÷É0? w¬?„uDà)³ÑKˆFëÏ»'psu—•ø,¸­îpð$WW[0kj?ÍB;½M–•ðõ°„‰x™@áè b°J¾žêsßçvdÇ·q† 0¤î“‘Ò^wc™U–õ±S˜nøâá$sä2ƽ1g$Žê;Xƒ](è°à|òI§ ‘íÂEw?fÜ1òÊHKl|IY.Ω&ª%§YÏïL^úâ‹TöG’N{\Ÿ´Röž*jÓ _ìÙ§a³y‹Ä×ór;ÏÇ)-¾}¡—z|m¿þûÿüëu“(„&î}9ä èp0Ȇ7‡A1Ðôœ9ƒe“ò0ê[EêÎ!Uu Ü,ýÍì,ãà#!A¯+e«Âg-‰îÎ+Ø:‰ùp=¡02(poá)krÞuœØ!ÆÇí^ª±¥Á(ÌFZKï”s¸“wâ#ŽP²‘Ȧ6=‚^‡ß"_ðõGÅ!%9y]x8‘{Á–Úààt¦ºî=šÛ_›Ç¡:–]–ØODΆ‹çLå¸Îª; þ2Ä3ý7aKu¾dä±°=Á?V̶rzÏš·–Sây…³‚ÌŒ5xm›~V??†âÖéªfBuÙ/—¸ÞeŸØ„b¯`mòŽDxÓGb Â!'Tz§ÏãyÑx–4Oëeðnð2Ù7û|?Dß“¾(n›Ú¾g"¢ùîÒ‘‘Aìl ÄRýž&&ö4à<Ó­0NL’C! ‘Y$C*›ôÇaåsâa¤ÃïÄ!öÈÑŽ¥a¼ Äùþëó!Õþ7îHÉ©fó~;ùøÞ÷µEJË3·œå„©YÄo-j øÏ‘sü \H3wN†`ôÎ ¼ Z·ÚYÎKv†"–h=‚tvV’™GcH]‰kä{]QdVCå•rkïj䨦ô™5[Û¤º„aQ~±B–ׄÈràv¡µˆ¾,Ýè)b%R™BHË vØw-mõ&× ®dS ðµï*æ«eIâ bº‚­³Þž•H$XJ}Ë[!¦ ÌüØFcàþ×K‰­æÉ èÕHq_HEêŠ ‰PC&A[UÒgÑ¡êðÚ]o#¥À/¡a žŒ#úfF&÷mèI|mǑӶ@0ƒžOêˆè0s3­£Aœ/ ;ÚÖ271}nº `žòr´DÃä£TUÝÀk=Ÿû{‹$Í㦯ßëòÉù©ÑKü8×óKäÁkä!Ç1ùç± .üˆEèÁÎé|^f¾¦\F†¬'™X)xȾ«ªï Öáìê<¿É¼2' ½S^õ@ Ì¡yèqg-ÙÃH5àÈ8e8Ê\Þ¢ö¼\UöT”Rôã#!ÇD È&;ŽÖ“•ÏREje[Ùkè}I>Ç\s»x"õ.ßaŒ9û:Ë`lš“ˆæ$/1Kãýxìq0?büãkõH7‘U!Ýeûõ’·¼ s…ÒgjíãïÌ™§”ô7N«ü>öÇï}}þ~¿â¬Ëû!y|bâ¬Ó† Œ¤»2†5xë8Ç9Y&™9…bz6¿aí­BJGÐn¬qC´37­æìp055%z#-¬Ä.®cBî ŒùDVÅeå²CžU”2RÝÕD4£®²µÍ‘t-Œœ|Cᬎ»à|ZÕÍÝ­¤ÚN½%³Çº^r˶¾ç6Œ’ŽÁw¥bÊÖÕp PbQ )¤k³é>Ū±[m-b_åŽc!eÂ{U„òˆæ°ûL¾‹÷aŒ#l³cV7sb‡b2+IÒ‚öX´ fâX+Õ¤öï\“AÔךš²HÀñ5JäÈ0¶[Lœ÷©e‚YµQÔ°1#iqn䌠jÂ(²R½h§Á_5¸CDÓ²UT^¯3¸ÐÑT¶ýgîº\¯lÂ?ªõõ8¿sdµà™œËö|®LP'uÑ Ssu +ã«#“’•Yá×î9¤pô~=öéÇBqBØá%ñëÏ#_$„ç²áåZÜöË–íÌŠ ¹Þ¦louÿñ«*oHÕ mšÜ?J¦Xx4ÓŠç¹LÑÌ€V—Ì Ic¯ Å…LWô¤ôˆ®j«²±ÎÃâf'CzÔÑYcc;…æ=õwö›Ö´íލ¨nì‘L³Ã܉}¹~î{°1‘…#Ïè-l²¾ÖØ`‹Ÿ}aë;†ü9JMѱ"S ŽŠÓç¬s sRˆXâ^ËJÀ'×õuŒ#-ËñúbÏìy>¿¾ˆ/iyÉ¿ó±Æâ'B]Ð ÷G^ˆ!Q”à—ôDvËØwˆÚMc$ÞZé‚ÃÐGfŠÚNFÌ OŸö}Gr‹òmo9©¹Íרeæâ>“q3Ê'¢‚°´¼éÄú8llz¶Iuõº"ß•¼ ¤“UïlK+·®¼·–*Jå]>Ñ+:­‰DÂo7$™0¹_6ÔxÑ!.Øk£>AT+ësÖ@1ÎZúùËØÔŸaÖWЉ#‘¬kŽ¿°F –ÔcæcñˆæKðÄGñ©aŒ 8ÅCÚ:n©*³œbp6œ¦è$w¶m ˆ‚_EÌLB p‹“a¸²`Yš¢Iì‘#0±H50ý¦äð7¬¤îY‡£òFä¿jí´‹1ód2dE뫌ò+-røŸ7¶Çg‚#;ÌÛç50ä)s’ˆë±¿¤tq”œœ xúž¥R/ŸOૌi&†Õå0ÿ8e‚—zQ«¹¿Kpò°C8—¡LN=4¥Hi´Â†é‚‹ú@ÂUç7Ž¥“ Äɳ¼È+§ee‹@¢äØNgÀ‰à< ‚â3fè8àÀ²Æœ*¯—™§âÇ7½0Æú89§ÁNWdžP;R;µ6  óß™„΀ó>')¼µUwñg¦Â9idŽÛ(¥:ŠTáܰä˜Ñ!P—`bE>Ø tZD+)5 Ž1y3ôœŽ,È©Igµ½aÅê^r¬~”ä3Î@H=ާžé#¹ çŒLÀ1ge¹É+à°,’’šr8ZuR7¨Y)Ѝ˜0/n¤j\„is˜è­h›·¦ì]Ä›ªw‚·"w¿cៜŸ öë$)ÅáàñÀàeïò©Ë©Gá[ŸNyœŠ,¨¦†m°×ÍD­À®Sa !)âÀàbæl²©’£R9ÙâX7èzüeæÊö£+•ÈkBI­Ž•àmމÄ3ÿûx"M¼qüòLê!5&•½yB–ÓëÀ{‚T…àTJÓG›üò¼îfóÏvjÔEVÛ¯ÿȽpÀ#~eyÛ7ˆÌD[Å1ÇÞsC/*cpé¹7J¸S€ÈUe9äÕÐßë!¿ÃÇt„aþ^Ñ[àuÚŽÇ#DÒ§|Àu¹}èáS'çò¨­ì¥€[@ˆsÈiÊ6É–#°Ñev9“¢s¨´×lM½^k˜ö`†”w2áz§²,ʹdÝHLâŽî)C& €Š3Zл҃Ìßø~š‡c# >‘@ÏÇ6"{xíÓAò6\€ðþXYˆ¥É.µà]d}Ø=“•/S‚í2Fv=V­øÌ˜¾ÓRôÈú"5AܾM 9ÌÓÇãÜRN¹DÖkÊÔhØßÁØyl_莵2ÐúȤ¸Ãò$|û?þ`m'†d©i\>ßmcÙûæç?'U’ž ¯ÝÕÒü©ù§¤ëZõuùaÞ' £Q>}|­§°?(ð²3_ž×ç´¿¿žf»h.<þ}Œ~{=·ù¯Ì¦ÎI] ¤5sU²™&jpMÒT\¦ïyf¤åÓvl¼ÏÔ„šÙ[dµ…e’ùgÞh¯§ÀDfaX™ú€¥N# Ð,¸‚ è… ýa~üEfi|~ýü÷¿>ÇÈš:ÒðÏ×ÉàLäÐâêÞïÉrüAÇ"É4ꮣ|'vËPLš*$ậÙí £4;ùínšðK‹$¸]SJÊZE6öè[)ºŽ ¡Ïµï(œ¢ ûÜYpÙD"Zs#ÿYOì‚p¨«Ì:üü #òÒ¦åü¶¡øY‡ç êïÀbø|¬1•ýVÉa mŽÓQRë›á‰ÄX"%Sš"SRÈJÜt2Ò„š¢Â¾ŽYôm—Ö®ÈéÀÇ ø,H[ØYÂÇŸx¸Óḣ™ °¶½ž÷pì[ä{@-嘻œGä1ÌUZ×õû>î!ÅËÔ¶·çXµ}™ýU§ ‘}W-¼Bw¸E‚0òƸõ X|  (ö€•L¢¶ ÝtXço‚õq>?qÙëó1¶ÿç_䆮ûK4Ò7Ñn:£› ô(´¶ÉÄã¶-“]ÙaŸ®Ìò¹†'j]^cûn]Ég¡#„rvÊsdCÁc0ʳžî‚lN ’®{BÌX…‹0GÙ󯿾^GdèHQþEµGÙqÆÆ œÔR–'y4TežØ"=Õòô*¹F3GÆË8ɱIã(ÿFÅ( v$ÿ\gá*3‹ò/gÑxúuïEOx.¢Ó†õDtXÎ+¢Oñ˜ñДD,Az«¥y]È)Xcþ]Ñ’Ý ÔÐs¶P±\Eî¹ðrvnyïe¤Ï´œW­jÎÏÙŽ˜YÝ5•ª`Jzl.FQ†efçêÎÐ~+©V-À¹A|…ÍÔ5ðLÖ8StÈê®»á'+­ò<+jÊ›àVpŸS_ìúO[°Ã S&§Äšp0¦Ã&|T9N*²áfØ¢ªŠ{Þ²ÈàI[ ;™å#Ž¡ ½‘žªXeà JgÕ2»ß’ŽLÁG@Q CsØÍ¶”Æ&Àeç ã’|€S*‡¤T»FMçÇS46Ú™TjöÔÀÙ.òñÕAˆUò9U‚æ)ý!¬Iøù2óYÜÄȬðá‡^ß§ëÇGüiœÒ1œÏÕQÜ ˆe>¸h=àzá—ÇõMÕ)Ôm—@ó+•—™ÓWDÆcäÍʃã°â­œWÑq•û>oq ýŒ¼õmµ“(éy*ƒ!·p:×Ìó ñðùNÒ›²R¢üøøü  ä„“xÇ+È+Hµ?Ñ(˜œŒ‡‰C€G±”Ü*K‘[é¼'he®ØF£NL2sÕÁ¨×J66'Dð$5x×"ò;Åsªeâ´ï‘hjŒ§´õ9šk Ë{ñáñÞ|’»MÍGÊ´ˆè; »^dpqκnÝŽóCiÓôì誒ÔQ”·šÚQãpE¡Ãd*ëÎK¥Ù‡Iå üÄ '›ë; …vÔq‹Ã8´•hUt@ãBªm,çfÙ«Ë»ÆÚÖݸ&W !UÕ{{#©¥ïó”¸uԞ䵋øåX6 3à —zaÜ¿â úŒT‘Ü&SÃED®ni¨=ËýññœÉk)O¬ÌÂpÃoçW†ÞÜ0£˜T”¿:®%RÎöƒÊ¡éלªnl 7XÞ ñá½_bªÏÔfŽG¦1¹”NQ<À©õù”݈q“ÀBH}©m.Álù^f¾pDñø-yóu°xÌ;5EÏD“F½‹ .ßöÛ‰Ä>Ê+ŽÁTª¹g,YX`ö¼&¡ŽÇ“º:[,öÇ9^êÈÎŒÀ¯¬ŠÊ°™Á#ßïÉ»nŠAß²¬üç°Ïû!£öôg»EºÌlu˜“0-ì2X?“ëFöwèìã¯sàÛDùÙehán‘!µì]6Çxæ}çg`ÕÞ¹YÔ}¤ù¼&1®Å­ýB¼ê,›”M]Ü‘«õݽU¦u÷*ÏÌñ<ÎÙI¨ V¶yXraÄ“Òe‡ W™\ë׿_^Í_ý~‹kl¬Åí)[â§2T¯qTú€ù[¸h2¢¡|FñVî–hk7ÒÊqRj³IpGq>ŸÇD–ƒÈ{šq>žÔwv >­cÆ3:»Fq˜ƒKSŽÇã|=x¡5ˆîûÉ>šÀâY®v¢Ê?Çô[4PÖWQÑÓÚqlØS.xMÝ ÆD3§L ì¦ç|$ÍœJšKÑ•I.uQ‰€_¾ ~îyiÿEõ 9¼gã×¢ãÌŽtÏ¥Ê9&™ó9R÷Ö¾Èjö¿˜A°ª®ðAס«ˆ ˆ$ ÷*d"QâX"LÆå<0Üâ'ûõ¿¨?`„¦ Ø‹R}Uå5„ xµ®Ì{aÇj25älAGÔ×ÖpâÎkVß*]÷q™9`aæÃéË,Ï´Ÿ¤—FÙ~Ñpºª·IWãóp}xIõFøk`ÊY"`Ó?”>ôQÕɺªÐ6ÂçnòzZ¨)9-Å5µÐ{Eà¹Ó°~nG®lâª1–D”8_ÃvŽÒq[C•]}Ëíz^–&sN¬Ñ$ÍYÑ =¤ $€?%Ñ$¢•Ìœ”ÕqË5±IfãÕ~äkŸŒrËùRÃþzí?žH–Î×b&a2ÎÌ5‰"—ÚÚ£Mp:yvv"›²Éó¢›9ªAÝE„ìmŒã¾¸‚)IñÊHE¸”0’-õŸzÙÀÚl‡>™[×øë¶(?ßÈV¨#cœ£?'­—W 6ÒüÓq.ôR²ÄïVùýó÷—ÚgE?3I6¦® xW;¢1šo/yñH<¥gزè*‹ºàºGÆXž‡Wx}>òÈi\ýÅØçí8jvÎžŠƒaûú¯ÿþýØÏÏÿ™{žk3lk¡<„¨3±\´ itäç%»:ŒR=Ràn N ¬ êó!ïe¬á2sÖr]ÏhI3ÇmµòrB¯ôHÞú`Ø#Ö¹ fùõùø¼È¸Q êüzÙ¾/UTÜJi5R'ž—I8(…$ú¾²jó¤ª >Ec–%ñ´†WâˆfäUùcØco›‚*S±zÍŽr½ÅGM(ìÅk {„OÅõ%Œ°nQïmm¹›©«HÐÀ'«ïhWäkÁ [|Þ­€–…Ulä“§Ç ðÃFÎáñù¹W­ga-k™rÙï·vhà¤ú{jnNÒÜ9Á¶¸öðvÀ¼ÄjÒd\àD…áË15@ÚºT 5p´ ¹R°çò%Í©3„&CšC¥±jšù8­qâµßC*ÈK’'ŸC¢xñœJƒóíkÒ"½:c²ÿño¹9ë±ùŽóönüÁv9¯\æÔX‘ž#æq¥jß%8ò»Xqß÷h8ÛDÓt@+'ƒ(ñUàרž)(#qþq2!žy&d#š9nS#C­<(d]ïqe1ŒÒá’ô²8§¼ÿá&©ÌnûúD¼Ÿè¶Ç1ɪ€ëk¤d÷cŠ›–I8ŽHÃ/‘eŠ}ý(-6 Z·¨;ÉzᵈQÈ6EΕpÑ5ÃÚÊ” #=çë yú°½þú÷¿ÿ¢·ÁÏÍ‘ýÂ\&5’^‘ÚYѤF—ÕýÀ§¬n~– Pù1çˆ3koˆ•¸š\öoТ å°ƒÑ²ˆ&ïb ΓÕ.ý]š9[o€ïc9.3?ãÜîö@vz¾Ž)bùX‰à‰º6¾²?‰Œöý<`¨gj¹4 )‹g¥ŽY–½ ì·¶T@ÄõZQBÆõÁ{S-†#h]‘‘÷ظFZ!DT2Ù‚\nBíµåD˜ÔLTHáø©m_¨8U(]TUÖäðe=o<%_ꦩ®œì¡¢AWfœ]íÈö#vEN¾?÷é1óëë1»I&⢱0ƒ¥Û_& ŒÞÜïµagOç¹—Ìœˆ­âºÖ7 ö.¡cÍ®< øQ¿è éÙ*Ë;ráÉ-a ùù$œx«…>K˜šúv]£üâðGçA@”¯†)±¬ÒÀä"ãÄÇÉ¢æ)J]_›Œ…«ÿ73_Y@Bâ(+*¦;¬•Í`/*-À¬SØp:×!î_=¯†•S‰ò„ûÉ%EðƒêÂ9³#µ°ßŒÜy}É;øA4å,Ä „ŸßžC]壽ß󞟃nx ±r¢û¬Å㯲a¥ ñr„Vy1<佋îýi “¬#âÂFŸ¿?·aØ^ï'»k¤}°†÷l_ãlËÄ‘c^:?>ÞSv 0p3f‹nóùd·Ê‚3ƒ.5äÖ¸’åq.£ «lžëæ…â ž •ùÁùˆa},²ú NžSŽøÍI,HÒìN9|Š-9Â&6™§)S`ä!Á¬²vjI#Ð>« ·£Hý ¦ yQª›æ¡kíðÇÌÇ Û!Ø·fDí¾qpȇž„´ÉôœKW’*:ÀR<8ëßQ‘Š­©MC”ö^“àˆb±z ì†ùüý–JäXüÌ©Øé]^º€@;"`Ù¿½ÜÆ ©"a“ãάàíA­4|3̲œ†ûzP0/N;a‘EWMË9fH%`dpaŒ³*¼N ª«¨· ²~/OÂcïìyô„ÀL >ËëSšé¯ßO˜ùùû1„9Æ[íôüzá7ëëŒcçãß_a´¯ßNI웆(ÂM»ÜyÆY܋ДTHÑU¾¡à Œ—ŒdWw»·N¨“z0šã§Îö~ÚUãûv$s„rcä¿NÏ&£Fa!jr| 7å|<¿þýïßœ¯;ÅIv'ܰœï·hp¬¢äÈãÆLêWíÄ)Èõê¢lûA¸Þ@ ¿ò° Óï×€ÔjæZ蜴Àëbì>×ÙXü‡= …È6h¤ó¾)ì½ÄsiܬTX†°Îf^\o§…ŠN,"¶¬¶uݨÊNqÛϯ0Õ%›S]\ج¤Óºû•S“®maßÈsó_?oyQÜ‹²FÈQÿ˜kgtˆN‘Æâˆ¢²!|ð®ë¶Ä‹!§äd¼ìŽ3“ne "ù¸ ø+¦±ÔS+˺¼Ýë¾ÿèM™s+q¯8®W´},‚rœ /Œ¿(•inÔAçÈ22ñ' Lc›LÂòö=>–VÄ®‚q’dØ8Ù©ò³Œ"Ò°€;·A“à!àYS `’5ö²S“Õ7 öaŽýÄIVJÅE)â™’G”¡š9mл„œ‡°?p»²tŸ¨3سzœë`ÂðœnÆrI§¸x¿ƒŸˆã×￞ÛñüúýùØ9RÎ q^{ù`íHŒ+³&:VƸ¾oÉ›¤°rJæ³MÃ’dàîSN¤;ŒÆË^ÀA”FÇMµ¾ï‚áÞ¾ž93a®Ñn´œfærcª1ZŽ#R‡Š¢ðøä(­Æ}®ó3gÉyQ>=Q¯v q³6$6ŒÉ-·­ðY¸\̲Óhí¶XÜ¡¶¨ËÌ/¾ÁS½ìh˜è"Iǹsxiƒ»Ã°ÐrÿCvþaæÔ¡#Ïž1¾$—Ž¿Ï95q¿Ýó²ºgÜß9 ¾!>àéËÎ?)WÃð­%‹`° ÷ Ó.¨<§, rÿŽ·—?‘‰K1z&v¹4Ú¢®²_ 9zÒ¶µu†¤^ø=\-Úö#K‘š Y‰·EÀ³¥…ܸ†#­í\.?råv²‚7™¹ÞÙ4Ez§DÙo™Äé{sY®XÛs?Ò¨Î÷„…E=Ü#ªÂZ<éz²Å¤–H>‰»n¦pé톸+j¹úÑÛ·oêœïƒu& ü’ÏŸQÔzüšsº`¶)£§T×g™’õQ$«ht®;Ì v=¢.!:â“̇0fîprƒˆëZ7Tä‰bŒ|fäs'o)"¿ì[¦/RA©ñ A~%iyéû‚¢+Ô‘mRÈö–¡0ŸcçpP³3pÕ!„㊋ݎ×ëAiº'v[GÃè%í-$ãšËØPj`ÜY„¨ÁylXê`jœ(Î~ HÑ£™;@`œ~ÊIÀ÷nÊ­ºØ]çîDÛ¨VëF¹ÖŽy2zŽuw-à?7Aø‰Z#ÊÐFÉIff›°fâ¨Pìµ\#»€$ÜE’™‹†’ . æz'ÜnMN}Sã³pã)a òó}溈®úgÙ1¨ëAßs‘æ§žbFæ]¹…ĈY‘ßáVR Gîç&‡Ö5@€Yã:DÀÙ}'œFµº¬,ç^8*3â–üxaÊ `vI»û,K§d¯S©s–ûè)õ3-‘Eñ˜{ €¦/35ÊqÊÄÐ1•x1®‚9‡”U”TÅf¼çF°æžÃ«R«¸¯`ÉyÖàœ÷nôìà¤ë©’ ‘õ¶Äû®ô‰NÚ×0²t÷|í–±³Nðy†ÒÈ Ûdž«´ìÅCÑìÞ¡÷Ïßr«ãõ>‚Ûa$Ú-g$Á"ÚGQnQáT¸j„À’cñ” åZy7‰ÀȨñÀQºGëGÆY˜ëOÉ©>¸Ñk¢Ì3 n0uîPA¾í‘¢¯¶·Á-³òænƒâÒܘé8F@cÖëXyßdŸRì˜I¼„÷d×]1‡Ä=Ž“º’Ö0s+ 1åHRÅõ÷œÆfÓŒì6"¶ÇYöãü©Ušàܨ­c²­œ}£¨AbFMu2ãÊ~DÁ9sÅÓ‹rX²+.­k••4yV¹:Žó°Kê e2ã’‰Øý§6¶åˆ™ÊˆJqV¹P¡åšØ7B êêŠRsœ«ó£ßÆžCIÕ?s|6wê.CjÏL…b‰ã g|j7säÒ Xz!3{äRv.sÆ™¶ŽyMIå†bùÏVfh;—ÜEÉfÕdº¼r ¡ž3³e^”l´‘ÛÍC(,«ýñúäê´ýù¢ÆlÒh‰û¼r„ñÞ)nŒäHD$KVD¢®í¶Èþ^úµN¶å1ü\OÙÞo5‡oà“û8ÊâÇ´{ÍP¶Bü]˜0§¶Úº_#$W4¿ÂÐUSºÌ|»¤—/]ƒ¢ç¸aŽ$øÄ—Y"ßf+ù!{ÓFµÕ?yùÈí"³Eôà*|RJ qØŒÅI‘À&Q’ ;­½H½¨éûKbð…—p_žˆ¹ç›Z©=ÖyÚã1ŽF"å„Yre\÷p~¦ Ÿ±ÏýôóS†ÑD@¶jHòpÆU·#ƒ.ÔHy¬€ârRóFNÏÄû“úÓÿ6ó-50®?‹~?Œ‚ª;|71œ1Á[D1i>ÎêˆL93æF¬¾Ê{ž¯¯ÕvÚø¥]Ù—šÙP#§‘# ¢¼ JrhÎlRUÃIª®lÍ^uÀ?t`ë.’×ñ'%VNëDf«ªñȽEV!¯G`…Ïе²ŒÞ8îSD«„°¯#mó‰’˜i¼f>¥Q[Þ3R½Óv¹-ªñpÄoävD— kÛáH?.m-kdCSj!ñ?¾v-’äJ øæd =Çå«ÒŽ ‰v!XvmÍPšŠ°J䥻)‹†Q“£ñÔk²i“kƒD\Ôçø&=[nEßæõà+1ûŠÊFùGVsŽ.î$ q‘.¿” }ìR•µêRFÍøbî §¾Gá üî‚©L_âȱIb49ßTZÒòè(ñhÞÔ¦ncªQçDµG?™ùÉ%á[‹ñ±Š zæp™ùUrKRG2î%n޽̤÷„ ´_âQqëøö=™¸êXæ› »Ê"ŸùÚÙåË_¥_p$ê:7îV­Š‰]ý‘9vÞÈNJ*ðqùêAæ(RŸ0{ênäÞÒé8ÙGID*°jNàm¤éÔW±‘°>P wp¡Ô\ÂÉïG@ÚNlYã,*åÆZZIÏ1"Ê,L´y¦J‹¬©8Žk{l-Â}má  ‰a'ÞëµlBºüM,óÆ]i月¾E‘ÅVªRE«ÛÁ…¾‚·…õeU`ØŽ3«¬fì)C;L0g4b©à¶mïºØhÞºSCgÙw¥¢ˆÍ4UÞÀÆ;m*I¢©Z¦ÊŠèž£j²m fÞÖ¹¬¢Ÿ¿«ÀÅi øÀ¥È,@2G„#~ÃJl•W°è2d‘lUÖ ?.´¾rq¥¡rëØX(>k¸º"ãžßF6^hjCpê†=F?\Í5—·0ÞKMŠk#亶cO»{ćD²§˜¹¬ëÞ×ÿÍ£T qÈòM_›ç˜¦^ ]¾SÌœÉêöwâ.õH¶›6Y94Ð.™ IŒÈ–9&Ò«Cåô.¡jÔODÎ*V¾ƒyÔ!¹då9˜!–m+äža$µᙦYZ-ÞžËÍ‘÷lŸGi[HßÀ‹®pþbîÜ“l¸vP,ßhJãʈEÓTeœ?ŽòÑé|—à®ÆÄÿÞ§}°lÔ¸E=™‡â(dd±NÐôU¿ÅÍJ‚:²6»ñ¯ÿóÜ‘aãÚÿˆGÆ~($`ô|mn¦ÛVXézpœ‚1ž uE2™é)‘ÈaWrÖ#a1}ò?¤®#3¤S6”á†Dqäé 2B&¬<"‚‰òrojÒ<¢:= œ*6.WNðIGX‡G‘Ærœ\÷#­á,×âqjE-ü Î1¹!@9†ý»~¤æƒÍp¿aFq††À_¶•n«VZäð¾©:þ3\®Ñ­æ åÑâÃ9„LnC$ÝF±{¨ý¶R|ŽÌÞ½ë€zÕË H… ¬ ™t- Ó\Ó5YœkÅãç|7`û]Iþ:í²*}™š¨F´$t'%®•ë'f꺬€‰Ö$ÆÈÐ]_”‘—.ó3m•#lHç5©›ȉÄ!ÖqKƶ¨Œ£*Nœ|Ñ}Yj®£ø†,¡íeb& Fü¥ÈÔ³D×z¬jG±DüõøAbC$ެ$6œ ‘Ošçù*Á]’q´åžK»“Ô«¸ßœ 7ögŽÇbÍ|LÜÜT—EKÊ¥“ÁÕIø[l5¥%1«$¾¸ƒß%8bWÚoÜuôLÚM‹3,`ºÅ¿ßìo‡ý˜<œÅ¿_ÜDŒì1=Â?âoÇ«HxüVî_çÄó“Š «’Ar‡å±9êä=é›[­ºòWVÉ}${©¢Mƒ}ÛÕP‹JŽÔ¤1‚kÃʱ5Ï1¹¬yƒûFÙ‚"_x<ªºß‘vUÃ5ò׃—Ët<‘¿ÓN(UE<'C"Ûóë½/Ç{~ý~Èôi¨qŸ{Ë5†£¢Y(o˜9Ÿ#x§½g[âKBX'#‹¢®\E†è­¹ZIñûÓ‡ÐRǤCZ:v™ïÈ%®ìHòœYÑÌ÷Çççëñ|ãÜ_²Ð1ê{âRéÏÏ«Ÿ(¹e‰ûÀeSnd^Fõ®É;ïºZ ªâLW¥Zò4zg\P÷@©JHO8ÑU‡˜ßOmÖRéЫÆYVܾÄ^~ÝÖ I»öÍ…‹eSgyGeUÜd,m7x½.C°z‘Ókgn¤¾ö}[Ñ-°0ðÞ6ˆBlßàwUƒÌœu8æÕÕí1â¯ý< Çå¬âÐÚØEW²€¾ö$Þ!rsT„³Oð ŠËiáW[*K+«3ðU”庚×ë÷SædÙKp²ØMd«w)¦œ|¥.í}Š£Ç±QÂëI¤2:Ci3Û#´ºæØQQ›7‡g´<ìRæÝý45]Y6¿‘ãŽD„©`uNŠ8åœÚœ:­è¦jÜÍ…9!¡÷Ü~Dº ¬ywÇ…ä”ïà`5—ìjѨҔH•‡&Tµ&Χ9þ)îÔãæ¦·ðv÷åñâ´Àó½ÇIOÖ6„[È¿º®£wÚ·9µo“²èÎ}Í|=î„©.'”‘B=†I³ãJ°3'¢Gt \¡4Ø2[N¥ºyÝÕBWC<ÁSÜÐFé¦hÇ&ÏÊ+ja‘ý"x9w|ÛSo RNØv½†“àw÷ܾLY ÊŸW%^¤6ñ‹àK‡ŽÂ‚Y ¿¿Y)•}õz˜‘÷á¸r^æŽtä^q©»åR,°Â4”- 8È]·(´ÇÅËÚ(Ò‡RüÙ¶¢Ö¼ì‡jKцC*™uŽùŽå‡¶Ô\ªRR¿ÎÊ:çä,æHïX¶«­¿¤ñ¡„¿ÓÎ{¸Ý$ͺdž[ˆÒó,áÅ—ºÌ<.%û·I³4J×ÿPÒ!ÄùÌ0oøPXˆ€÷muB‹AÔØÌ¨9îÜ5Yž÷ç×C¦pöõ5«Ž(c3?"¾;oÜkT‰ó¿{\+¹Gš;ý3‘Ã]g\ž’Óš·+.‰†À”[›J¸V¤U ÅÐEÿ–±=*ËU•ìEg¦ÊÝÃÝǯº+²F˜h¢kÌÊ U–hkZV‹À©ÇÄ%/mËÚ{I-§šJ¯ºãxH×W?ó¾Õ°-SEÚQ¶“FÁ•iÏu;/Iz?.R7ZñòFQ®k¤ìV³¶‡«mËÙ!ͶRì¦3¤-@Š,UXÊ @¥…*Sh„3‹ toýÈ…éZd'ú˜ùEèÞZú«1½^ìÑÄy¹ø,©7´Fl¿¬—Òzœ"Mÿ©Æ\ý¹ä=lÄV'KJ+ŽÂÔ9¸~,‚ë8äNsælˆl3 Ÿéîçóo ›?Ê6^#.àÖ\N€›µ}••$b{ q)QžñšÃ—Y‚sK˜‚ Þ6B”®¹áOØW<¤ìŽý5å÷íÙHK’þÙÏØµ"§~Oë©pÅÑ7¦‰ƒçlÏ1²žc凾u9l­b\`ϵl¯NôNHÖŠÖC ¥ëžKð¼*€T‰x™°Ã]ôݵr«ä¶-’Y9èU0åÅumëµ .©—l)¨'–àºQ—jDæ_0ÇHoY‹ä&z&…¬Ópó7ÐÊ'näFI^ž"ë¼±6Â$8ŠæI¤9ß„²ýý£êq7{ÛÝr£3úTÆC#lAQ v²gÌ‘¨NˆâÞxÐ\nÄÚ(|Gùóg‹pŒ¼R‹\®KÏ*åƒlìƒT¬9¨I~ëúÜÉÚÞŸûHéöAÖ·áåfKx¾'l¸<˜<Å*kÑë–šÛ";rÈ"mæcï{Fý¦°5[ý•N ÜzM½ý¢P$ȨZ–‚²%`VžðÔ(—ùª0oH¿®3ÕJÖH.—]‚òç¨*uû¦kÕéµYf½ø ?bž>OV¤â–‰öœ‹}ÆíeŒ S’VÈö…ñ õ‘iæÒ±_¶ob¦,%$3¿t(¾—ÙÐcá—ÐÑ:­||ÔÚdßpN£ÍÑËF¢ïÊé7ë¦CÖ RÍäÝ“h=…¿Ý š¿•%ÅU#m®Œ¨ ŠçÂ&z·,îB¢¿‘lW4ÚÕ5{É¿Ž$6µM‘ uQ€ ‹¥D‡º©)ô×àAµ­×k “ˆó¬Ì\ºV|íËÌãØaàêKO½w=·VÚ…¼îaªàøFöê—1‘Å—ôâh—qó¿ÑN$X²A•Áq’6¿whȼí1_/JoÅãdèɰD«þhaÅû°ŸÄž‚çR†¬¸ßk^«¤fTô—í<Ž@ч?s-Ió1ü æ‘%L ]¤ 1q~ŠrCÂM/‡eoÖ¾ ȘÔd–r v—ýÆ'—ÐÂh§ÒëÄ|ö´%buë¬3­3Ükˆ‘ðeYUCÚ«{dìž‹˜ÍiïM%A¯÷TDc‹!ß MiE› Y2Yææ‡ ¸Y¿EP÷ùzÇ«:XA;–=&szŽÝÆñÓóÚ »'™-6\/µI˜²ƒx…´@îGõÑûÍ®ë­ÈIxëÙ ²zÀT(UÇ!®>|òÏqVÕ½w ½ù¢ÖcJÒR>ÎHÛDÖX׊2ˆñ£RξñÅ{ÂõZ—? .îʼæÕ~ägÑÖ·JÃQ“‡*:§Aú¨³àö ôr@ÂË4öŠpì󘛳ëÅ;JA[ygÕç*;Ç-š"f—™3ÃDô9¨F³Œ˜" e“5pÌZ‹v‡åIònUYô2µÄm‹ÜqA±y´Ë0%LÈŒgÝC1 hßâø÷¬¸ú*LI{qþƒ–$ÁN£üËõÞ!aaCkæŒ$óõØSž)†oÐK)-Gkë²ì†à¢™Ok¢ØN\ÒÇû•àþÞ¤ºö 0FÀm .Äe·²ófc½~™"T¦W‹´ýK´IöÏw”w{¼Žx÷sÿ^%†+{À¥_9À‡ÑE2 [ÎúWnëëYX`ÿtýþù1iF1-%¸ã ¯ªœÄIcXoj#uƒ³Üˆ­0s瑨%°¸_Þu!`-9½¯“‹WewŒ”à"3Þÿà–+xTÅÚð€Öƒï:'’I@®–¬Q7´TÍv&9yšþ4„mñrýKp²‘NÉ(焨ì·ü¶^[ARn.t€é›­5½›>ŸØ9xqß$|%¹Ñ̤È5L”@5!2¦W™{¾Êê‘d)9ç2'½¼9 K •FŒk¸ä’(ÃàW}nž½63N®÷ÂMïì̶cÛÝ>D•ÆT=‰"heɤ–ÀÅçVšƒ! “—ñìs=ªªa]ëúVTŒÆmÖËF®ÞÔšƒöËI¨Öx–?sü˜‘çe _8Wme–™”²k‘f>‹fï–c¯†ÃLÀ™¦»ÕΔv™ã‚Yº3R–a8AŽïå-$À9E]å Ïw¢àâBZ _÷*üûå ’óéõbÎW±FëzóìýùJ´“ã¸x¿q“Ú~ÆJ*p$Ü#ÈP'x -Eiã»° ”-í `]«Rä'¥½W§ZW½ªê8„,6ÀŸ‹(KZñTJtßEÊÇqº§jýúH´½?¨+ºSÉí¿×C?Ÿ_ÏM”Nº¬òæž{–Özg–³lYÇÀ9sRvwÂ誼®nYŸË"c|鞢Œ0qo|TX ÀÄ@eÐrW3áÕæ=ů8qÆlög‰ÕäÙÅ×-ËH4YÛfyµßGåŽóPT‹UêéçcÒšüŽfñÝhóÊÎkاšBœµHís£’ Hµ¨õœ]“תþèus¯œâæ–ÒÅV `BͧtœÔœÙ‘d€ˆ;Í„…heXZ“Ž£, š”›÷¤Ž£Êꉵ̾ìÎî¾¶\ç-Œq˜‹ÔÌÑH³Fyæ eŸÃ’tõ£Ø )bÑ(© )Ö´º:ÉJœ±2ö¼fV%ˆžA²H3lç\Ÿg­éëªhL›µŒe’ GŸÀ ŸIœéÿ2óþ…;º‰î¢HÚØ•œkÚ†2ˆ횦Ç:Êî«Ç>9Š@2¾õøžNõ_>®uRy{‘Ã}Œ2!l—uÖ¬°]’ÊRU1\QDþkìÈ âò7–Ãúû± 4a´ ÷OfR¥¹6DFñ™ÊËv¤׉ÁÌëMTu¬:QÄ?š9kì­ë]/{ä‘{·’w µ)8´Æ:QCA#KI cÿüü|=‘“GÒWãòÃï‘•e”2€¨ŸkŽcÆ1´k•¤ˆ_ÆÖ:·Á|» ¹ùHö]]ôžó–}b¸ÐzAÂ7(¶Wíȸœ s(3.%Ϋ6¢oxÄH?"Å¥$âH5h®µªœÉ!íLÄ¥z »—­&Ü)ÚEET7rÁTÍÏm rçŒÔ†VŽyª–·–‘“ëã†O‰Dd²í2ôƒÉŠ¢ó21™zV“L8,q½õ&Ú…'§Ïoy~k¹Né@/ k+­ŠÊ»ªç'oNy—çç!°rÞŽD^¢rÀ ÛjeQ´\‡[eùéŒÈÃqÃ$€¥&¯-$?©³¸sš‡É‡({RÉðªä_58aS¯Ûw‚•j)Kb\>ù("Bî= CÄÅtjWe|Sñ-q|v8Aæëu ë!i¹§¿ã®á±^‘©ÿ.ôVÙ0».ßf¾ èâÏ!Ñ•UÍ¢HÙ~3›V´^mÈbˆ4ñSICg»ô¬#k>åDb”ÂíyŒô¬¹ƒž ô¦1†t²œKâF.&Z¢J,oYR¶Ðk^z²éájr@|.Þ•mAìÇ/þ´b Õr‹Z£*„ŸXcM˜)5dGK,´Ç,wšS[)2³Ê&g¢²¡ë={ÇŽÃjzljÏO…›ñÿî…¯*Vá’L(vàHœ1}Ã%ÃÈpfŸ¤W?ÄJäqΔ¢ï{gKŠÒž|ïá–”‰dõsêD0"üm@—%PVô^–5«Ø ¦™Ãn ê¥o<Çiñ@ 89þ“5‰\ì&h½`ÝVÕ­·Å­q€%ÌaQ^æ@û‰ÌÖ‘àŠœK—³&BuÐ>X6•†¿e%¦î§u˜ðèEt»áˆŒ÷söîߟ‡”yÂs·Ð³¥¿± ¹H%8=|™v”gfkvØž@€ÜR\zçÛ‘kw0pï¸C¢¡ÈÑSº'ܰA(»FÍDŽƒ¬1†Ã>åù³^i.CFUdÓ˩xÃÒ.³eqÜͰ…öx‡›Þ ÅWyE£#oÙâC2åËÄ}0ëâxßÞ’6ñƒ,4ð¢ƒ>ÅJùw3Hø'q·Ýt©ßpü”É”P´©j“Ðuœ—%ûO*í2¼äŠš×TÕµÁó”#aÖº$eÁ0í«¬ÈêÑòÇÌã×”ô¿ÿ,V»ãro *7òTô±§AÔ}U ˆ(ÎS*ê²W|\oêŸG®+Á±% h'Ù#Ã/Ëâ2(-²Š£!Ç8ïƒÛìl_ö’”·…”veG-Ç‘-`•ãÀzðë î‡èªIÎÄ¥ymY<÷W¶p¦´¬Óç¿@{š`;¾µñÒ«,eÂ1*ʶ½ýG$çëj0 Ói« 7/SQÔ´ùG[v@`Ï?…CµN$ºÕçR°¤³²‚d×T‡àNUf%­“õ ½âü·õÈ[sÙ„h2øgà«`;i‰#¹aª¬d?ƒö#‰rÔåžTo$ëí׃¢—¸½Ë`‘5#¯°a‘Ü’a;ãÚpNoŒr'›7Á¢‹Jò±Éßó½­Á_ãMïîgÑB”"²ô..3.þd“´™½Œ¶‘86å4×Ò"c7²‡f.¢µB$V¥LUÆ&û aKBä gW©9Él‰Cz aRJZñ›ºîK2bÒh„d‚c™)|3Fh ‡"AYÒ]*íhóÂÔ¹Ó]‰ÀžU÷¢Âc»º÷óŸ/œm¿È;’ì~Y¢(«†i)‹s,ÃÕߣæÂˆxmæžÐë-Ëþx%ÎnxRˆŒœ]òlâ»ÂNG–gÞ–;qóÜŒ]¡˜áYN8l GTÉôÑqÁ@Ø*{ÎeE ^«3ÃHòÙsê uiDÀ„I9—èˆý˜y_zShg W!»>Wÿ9íèz\ }N37²Ÿp%Ë0Æ×HA­? ãM(ÖX1¤±FÛæ~tWB§ãÀOÃ@ —Å–¦‹;Þï¨+y³‹2óN~Ž˜êe±©¡"{Ñ™ávÀÌרØÖ?zi=mãW QÆ"p³–ª[8óÞ î9Ü0J?Y Ãñíüûßç&ú9<®o¾-HìÇ;ko­LÙûÎŽŽÂhÔ°­¥»ÞÃ;o«ê Sð©æ*Î*׬_0ÀZn3!a¸fäe"c9³Ûí3”óÁ­1K\)ˆpó6Ào‰Óví7—Ü<ŒR%~à‡WB$l,#ýË¥F§ª-÷)4ˆ ÷›]õ(ƒÀ²¦ÝgÓÚ_HwC qÙF5Yz¹ìQî¥WÞö4¡¨âÞ²ã«dº¥¥‡Ç“EŒxá€Ê"àž„Í—Dß÷ GªSÉØÌRr¬„‰ûœ¶zËfXþôAö(Æ<Ê}y.!„ë]’ÐÀ%þfqž¶7{m,5ž•ȯNá›’¯Gt!9$NU Xâ  Åâ\ªW_;~–LcÁg&OˆK¸êŠ6Ýp&¾ãU«®Š•Â3Òõq”2 ØD ËzXb€˜å·$×¾$¥ã9 „Ê¿‹ GÊl\Dïq«Æ8²9íǤšSE–6H¯_HFœ‘ì …ÖÅÔªð*ë ¾ì|{ëêÛG=.ÓÕPãvmJ+ol[LÌ\*|‘mFï ¿ÊÍû„lq©~˜iðd˜~þõÞÝt¼_8+ܵ–ç_ÿýדò0,ûʘtT9…%ˆ2yËùwÀ?Ï­½•mYövhe˜jÖL¥þ3´·_YÉp^ÝG2Ï~¹·C:*ÒÇêHNúè:özMM" I®¤œ*rÉòh‹سn,ÜÎäÆm¶ÜYÊû‰@×Uj†¥b˜”dÇ1î½\7ɨ¸z{!Ïï±Á†pÜÖÇp¼U5Šˆ3ç[jø­¡BtçÎm ò±kM½ö¸Å¤¢!sîê„rÇE¶Ý’¦#ÂAÖ…·&HR‹D·àäÖ4]ÑaŠ¢BÓÕHmÚkòƒû4m›gli¶õ`¹wœf¬_ ÌOÊÜo³¬+Œ¬ÊRR¡åÆ(GÉ´ªR࢘ˆÌ—5H3P‘«šL³í4BY´]7ªÊ”ïE$ª}!›˜ùzOQ]Yi_ÕYïÂA9YmƒÛ»‘”>ÏΈ†+¯ÁÅí´x>8G,ïHe°Õ,ç‚×F@³ù¯ÊÚZ{ÓV=­ÚÁ¥¬ÜØ [ð:»[æú&aöj¨ ³ð½ö( ·3™’Ã5õl¹³‰k0ƒùRL߯p}W¶¦åö˜:'ÿ¨ó“¨ï®‰ìùˆN{‘>ºp3²Ë°8ð’v¬g±Æ |Ô˜tþÿHíÃé²ùuyHÛëùä¸){ÝŸ¤nÏ8xFß?p2e”s tÕ•·f¥¸Â÷hÚ&ÀG"i_ô‘Ä=ÞÃÆ±Å–©tž™Y8öÈ!{ä¼¶b7|ƒÝÏ›yüõ‰ôÔs‘âæn®Á` /.’™¿¾/oÝ:rSbd¸wÂæk¤§¸XÀO‰œ…¾‘žÎÔHw©@Dðˬ†u.aê¥&ÙWu^yzÝ8ñ@ArÄ6ÏÅò¸"\.¼Àj¯Y‹Øž¥ÁJõ¢¥ýuçªâ‘+*{dùmÙ“¸gtÓe°|XŽ!l“-?‘cuÌ”×µ‘YÈä@a@~NÊÁXࣴum‹>éqPÏ"‡òÍMÎðdyð8¯À9$ö^œKgá Ÿ‘ݰá{!CzŒ±j7s.' ¢FÐ+;—âDO5(Ùì°Ë¼~ݪ,·¸2–Sd­…ó6öQâ<»ÐòRŽùº%YˆoášS(íd­‘BÂNâaJÁFGut 6úHŸ!C|¾ÆþÒ<{ZÁæØãj “´]Šœ$ÅžšÞuƒÜŠ/TÆhãŠFjųNÇez?$ ¾L*<5È«¦Ë-LAÃÛ Ë”ÝiF$ƒe7tÈ0»¶¼W~d7½Uœ¢ág±õ¹äs]êØòùŽÇ‹“µðõëµâMF×ðß0(h;_/„=n¹¡wÅà†—u¢¸5s”´Z{Ükî•ýĤ(!yÚÎÔ6?g’žé–·Žk‘M-ú Á}çz))𝍗™K­EÅþÙ‰¬²í¼eÆJ½ùnp“EüvdªÃãÕ‡,èIó¾á;¼ä²,ÕÒµËD‘Ø.#*†“xÌ~eý)@9y­=‚µA~ÎýlZ6„Ý“4¡‚}c€IDAT‹Ø'+M8ÎbìàzêÅ*Ñ‘i²¬8ÿq›ŒÔm83½âѦ@]æ–KB®ñœOÂêàè €%ÂÒç%›N†Í5ð§lÇ¡ú;< µôÃNÞ(º¤¦Äš0?qªÄÄŠwQ÷}L‡’u9QŸˆÔ ®†´7®„µêÞ fsÏ*JùÁ-ËχCÿfæDŽ|£ïJ|J>S‡8*0Ïñs†éǵB!àE|f ÑhÙ߇H¿=æçͽllÕl‘/Q¿Ž¬²i¹ä8.¦‰L5¯¯ïyÙKb‘Û!˜[‹Ü5“CÉOg|³è—ãÕ¯OÖÝhîq÷ÌvAÇ?fž´ ×1ªÔ ŽËØnåƒX»md¾ ˆÌËFØÉ¨ ñ,N;rÀGuy*ÔÏȬçŠáT…de½r†‹ª9MAD£zÞÀë†=V+Ã׎»?Tþ ÝĉÐ2Ùòg•#7¬>ÙJ'“aF”lñÙWBƒ×±žŸOª8½í÷ó|Ë@.•ZYå{Ûã[’ùH{]¹nõ|Eo ® º›ÑqIüBU>Ç·¯‚zÒÄ[ÏDP¸Ì|Žá×9î(út}W€E¤qrT¥36¤Äî3·¥¿…! vXD^‘q)¥¯e‹ìʬΨØ4±FV;Kœ¬AŠ¡7²“FåØ=öÊ“@×·¥¨ºš.c¡Ž+ ¯ç£,ŸNS5Ù¾•„âË’èb2i7Žž´ &—0i¼¾EöäQµEF–ðÖv¨—OrtîÆÍm”hËæÎÔ,pU+EâèµÆ%u²÷xÒöM.%ã,»øXÀrª\í½rœ†h`ñ0!D ÄŸp>óL5¹R÷›(H¹õÉ úûÿ+šÇm {Rl¢Ø²0À“"tˆôš9éQü¸Ø5é#¯kÔŽ‹…Cüâ‚É`Ó5­È £1€Â&<<:,‹Kí"v‘ö#i`;=Jiï„E†¤Ðͱ@W¿ì~â‡É/[,=rÚž…s‘|z>_iIó¾¥’~*¯EJ*+ýÝ9XJŸr\¥!Ödg…¡™Çfe¥p_H“6ûñ¿Ì|Œ"“,îÄ¿"l9‹’ˆ­ªÂbÈ–Þ&dVï8ã!Zå&<‰xq„È]tÌlØó¤®>ì8—URãæë û•]”ówª–΂S2±“ivV\YBihŠR+¨ ²rªšÇ0ŒÛ;’GD!uùVô••„±Ã ]F|Äœ¤EÚtàòG$IÚ!éï52¤¯«¼¾ìp±wSævdU<í‡Þbårɧ•EÉ\´7½LJiœEƒj)}Ñõ†z:pa8`ƒ®”kvH‹døþÎí_ÏXË=ÿ·™§¶Èm–²Q*ªq‰ØœÖ(ˆ™_K’ëö=>Ǭý±pÅíþX沨Òðl ¹º¶(û~€§‘©™XQþ6ótQ²@ù[F•ãñQÖá’ _hç^qÊÅý×{ Ü"rgdÓ­R‘Žd’ÿ±êE&ËÝ©cTª‹Gz&ò,q°xÙhʇs¾·ooBí¢LÝ cw¡jÕyŒn´ 5ÎòÊÕ5kÉíeædÆSo­ñ¦¨½ÉªÛ­G$Ì÷Ƶ@Ÿ\Fb% Gw—8Èb4ÌÏg9_ã6¼=±Obw{O##øû¯[<¯¯O)¬qp•R[ð/™Oþt÷˜_×=—´©."BWÉO.ÔFAÎ;M4sÝ—EÖºTcbMý›‚t­Hî‚Y*š[äjù­6Ü.@A¨.Þ? ˸Ÿë1±TBx,*¬ì'Pœ¸ŠIÆ g¡ÇMãF‡®F Gdù ðš±Äfa>N4l‘Må伓@šLqØá›d@–•S1sx>%òlد ÃòŠ ¸­éf¾U}.٠ɱà/½qä[OJµ ¬P®ÇÆÝNòu„Ý07ooffî½ÄIâÖYÙŸÉk²ö>s—e!³,{‘'fçŽËàk?DSò_©[újçÊF#"ù‘ê'¾µ²Z`Ÿcï#üo3¿ÐwT¯ CTHYÖËÌ#Ýé²ç©æ6]hó¤˜kd K S†£¼‚Ûfh‘hÒ(6=ä¦$ÿí‰s·^%¸8J.ežÁsø!ÝìÅì"@³ìON|½÷@e‹D4‡¸$Fž¿'~¥³QAFoçG(s>r×à)Û¾€ç¬‡¦$êj9,ÛçÉ}A<—g¯Ç™‹‹šì^ó)æ€Vß.PØËMDß­NƒšUŠ’¶²iPyý3Ò$tßo­æörhx‚¥Â}ÜB§»œ+J|pnS‚'Zr!®×¼)„}™fâ Ó~¼ÈÉbÖl‘8äfðhl,µÕ¥Vu{wS8f+½ïQu2ÃÀ½¦(–¸jA— ÎÁ"•åî D‡®È8Äïe‡ž$š",6Â~É…õ¢ßü_ÑZJ’°ïÌÉ®(àˆXÍX×Ñ ‹Øªêž!!©•Œ+®œ&0àF¶¶¡ù¨ë¼´ap~«‡Ä°fâ ÕíóøŽii‘èÊK_I‰`Åhç)”o¯Ï7ìœs‘1éš¹•þs;Þ€üïk‡|q¥¡  %¾Ùyé¯súTæed—–ô»E{‹€–"ð[V¬‘›ª©ºÁ™ï\òþk,$îß%¸èÃ7εá=þå²¼« œ~ÀÏ–[Ô'R8HbÚIÓnD3‚zˆA"f”à·„–¸5d F*š¼½-•*¹}ÑLr€×Vp«»é)"‰çlªmá¿ã¶£šÎ*…Äð”Æ¼ÿãç=ï²\sß!¿H‡q(‹¤k†»4 =Å9KQ"ž¦íWP½~ÿëÅ! ΛP¸ŠÕ’’¬¡Q›‡ãø:’`Yè¡"»sLÐ%Ç£žè&°%d»eFÞïHØ·,+˜".cpµóndŠû˜çóÁ–3+‡aÙã€Âÿ]i?Óë«¶v¹ó«'#²M¢ù…Тd¯pfÅÎD /‰wÈüs¹g\?É}¦Ü>{ï Ç4ïx®z‚/ˆ/óG5&nW:Ÿ©Î(Ãõ>éALöPe'ö¨Å6OÃöþz̃{È´›lòK)ºƒõøßfÎi2Š„É5þ\\KÝ¢«aéEÃQdÓf0Ø‚›Zì¬-Èߦ,iºy£øü }^"ù,L_¨ ¨!žj£fG#ŒÊ²†\dÜNßpyÖÂ’ÃkO‘ô]„“¤ˆÊ*OÖJŸ KhÙub©1ÆSÞî"Ë~~QêîDz~üõÚ·ñ\Ïyyl©”}ðÌÁý$¶³\@}—cÍ>‡3bCò8¹¤a‘KQD£÷£lz§íùgÊ<P>ï†ÚSˆ»Ï÷†pâò»ZKC-#ý~{d;\+òEv\çNÛ¾æB×Ö2¤Ëpl,É¥…¾³ì˜H6 ”¾áv©¦F©["eãu-:é0# ô¯›Ž:yöꬮ¹Ä¨/ù!àÏkk¬'ܧ*:{!ÿYà©ã|qk½ó ÷›³ˆœT—Æ…\õ<ÓSb;—|¸FÄüyÓ^Üét—!_æ(jQª0°ñ#È‘›¿V'¨¨Œ¬]MR€Ís«Ç¢6[ô£›ï úñ@DÉöë+Ž•É˜lš÷e1ŠþŠs¬3E1¸ß;«6Ç‹“úO®"]¤a¾á„ÃD"ÎàæÉ‹Ÿw®x;Ḹ:ñ£Çó/Åëw]}ïØðÄ=µ‰>*_þgkáþ‘|ô\¨@ÒÜ6÷9Ì‹¾¹6/©Öð8ì’Ũ¬:wÄìfl7â¹Þ»¢Æí±LmížýØw©¹’Ô±™¡¬ä ¬7PAv˜±´ÃU‰éº¦q°”¤ Öù|\uöù¯Ï“«ÜðgÌp3»ïûb•>þà¶]óäbŸßæK *!‘š:Œ¦AjÒ“Âþ´–ý…ZÌò¶¸mMÔ£(J½¦žš€Ðõ|·F·ºeÓÓy@g·1ÿÕrÅHņ•ç`Aö«;ýÂe=çÿ8‡ôÞ+Ø’ê)sëX^ár7njÕΚ²®:ß׎b œa 8Ô *dò'Æ4K2ÃØG‡=Ž,>.™ÛUúëf*x$fµ{Îh¶Mé§çÀj€ÔÏ47Õ›eguìe$¥Çdýz‚k—”é(¹ NÆXô¨bÌ]F?'Pûþ‚Ó ÇwT®ÒpZH7!þÆ#¡'ï_êWGýýí”¶ þåóŒûBÜ£*ãœÓòãÊÅ·¤Jó=y-cJSðsdQmp Ñ#oE:ÄM½lM!=oÌ:¹ùAZ/Ö’™K‰õBÒbŽ!Ÿö½G*° w6DÐᆳý"(³E|ž4!çõd›2vÓzñÜJjc–~éÝ‘æf_gYvgÁ¤~¼#~÷uí­¼OŽÝG§î·†]6UVE­¹wä ³7Åöe.CƒÜ á»†E±³ãZŠ™Ô€ò¿…Ë€wŸ¶©n/âÛ¢½Žƒ•9jVõfMB·Øaˆì;ØŽqŽ ·DQ‹ P%Úÿ›²eFB욪ðÄ0ÿóÛÌôÇq·ÿaæ².åïü±¬B&Kà¬Ðà8A¦8d±§MÒkQ”ç$“†R¿Úê vLkš[N œô¬ÙÐ÷ÁoaãÐ|ùQŠ^UE’1u ü†…¬È}þ›™s4‰;ø²iæÒV¬êr\ ¦ž*-3oÀÚË, ÿ Ð6Ìl¸Fœ ¥(òCìoÝT9‡V{¡½Sº9.« Vz<±Ù9okìIQé’ß½J£"cr<žƒ´ãñÆÃ€Þp•Ê6}½'òy¨F†T¢¾·aå›xÖ£Y ™ùÀˆYbΙ·-žW²#R]£¨äâ”E~/v<_«9æA£P†AF»ãÜéw¯ìÇÅÞŒ«Ô85„=Mê©,ùN ÒP[RÓAl2’éˆ3wä«ÀpÇjÕôü\¸H®›¦”I –Ûœ©|Ÿ50-Ï“!+÷’™Ç’Æò7zNÊÂçØm%c²®x‡qÚ¾ébœHYâÚ…åxÆÅ¬4/œMt®Éj˜ÛÐÃ>•Ç1jeIivPe)Û8.Þ(¹»®¬çNUÔ^éÚ îusÏÈ‚µœŠ®{Ï$ÆÚq™¨y„ðMńБÚã\øI~žL§á%¤Š\aM¢+n>r2©É7‘ñÞ±ÚŠÿëýIí)“$LþàßÓV(±Ÿ]æÁÅŒÿzmT=>_²ý3ŠR°„y- æßßfGRþ ’_/$Xî€H_dãæ„²áØ·5^XäÊr¡`g§8JE|•:oQ^w —§XSVÀøÛ×p Ô·ÅRJW#2s<k›,/jCœ=àÔ·MqÏ›¦x¦5ü1óø‚¢Sˆ@Û[M!ŽnpŸèHN\Ëe¡V(¦˜¹Hö œ1³Šš½ÊT…`}¦Ï+ BÉòXÀêœ:ŠZ5E–ã)++ Ó—ÈöZÓ’¹ÿIi]•\}iåßóbwÍCGŪõœn§¤÷ðlêfXLé\¯Ê{ýŸ¹ßâ©×Öc'¤jjKCÒ Ž•s³ çiMÿ÷,“Û¿^O¯÷F)¬#Î1"<\ã2BÄލi8F )òMÄm±©>Økî=ÖÚ~\ˆ.e–kd1±…¨ƒìy°‡%ï€<{d·­qYÝV5üª¬’ šÄ”/3-·cû6ó$¦“Þ Ç÷Œï:,<»Ïß©ý´¹ñüý‰AR_'É"š.=ñ¬ÓxÏ–‡È/1’{²ôQwŠ;ó8Î¥†]“sñ€Ý½5éïL¹&{µÍ«¸÷b8êÛ]ud—%ë#–}SL¨eð˜ càÛ‰xñ\¸yÏWÞ(Œ¹GYcÉÑž~‡Äeƒ{$U>ž"b»V×ÞÑýYÆáa>dמ=)êô”}0Ç71áÏ®³´±ôïó¢q@ñÚh*9ÿÙï-/δùKçìˆL;s/nßÜYå—}S{ÜæúHç^ìëó‹ã²Ü:›qn¯áÒ6„ÑÑ™wÁ 9k]”2L)KO[Ô]ùg'dëüÇÊS«•õlü¿u brÅ-cFøÝä5N¶rå³3"¤£ál’œq©îƒÄĦ(;Vìú‚rÔ}‡Nw¢ýü Jõ]+>'áÌ\èDfË„ñ*|‘$x¹~«Ä&4`©¬mBldm H·G¤± !$ùç¯vÉÔ×d†ó½Úvþ|ø~8…£Ã%L£ÇawNjè,.ñz&‡ ÚãÎÀp.2ö¢vÙÁ©ÆÃbŸ® {œÓLÍp’ÇwgáDišñûÇ%Ãåñ‚¤cgm#Zj?!ú[VÕ­ˆèQ'?Ëk<Ùà YˆRŽÉÌ×HŽùcæ¢óÙ2ûšRSŽg±1D1Æ €.ªz½¢> î@mäE9[aÅ­Ía¬zÐTðb+¨ðÚˆYEì&íÊD•%Î4b‰|´¿Ud€UTdEÁ#³Uã|íƒ-3dâøq$™"CÓqß•LȨ#Òõ¡Û!âßÕˆÌßÌ×c|Á¸ôźhýoIæÛÌ׫ ¿_•lÎì3~|ŸÓM7Ô;ÛU#ÌÜQy‘›‡Hø]"­ã™ÇÝ5yDðõx½?E {ÛÆ¬––‚@æç ‡]­®*©ÂZQ¼‰ÎÀ =ESÝTžÒø[0_cÇIFG&O9E|Äþ§×¶/Ù`‰Žm5Ò!g˜ä íUt€ß+NqVûí4ý^YŠQ<â; ^–+%8‡îa&’ÈrÃuÜQ¸\B­ ù¢ÁÃ;*Í“Ñ^!5Ó uåH&²^ëTìî¿*#*Tv}Ÿƒ™^¯u˜ïcd£i°8ç›@ì%û)ùØ^_ÇuGX–9^XÏQŠáÓò:W鼤í$GjXÿÍÌ£z,`,ÿm:åtgß<&·IbbªÏÎôxu ‘l}l~؆Y'Åè2ç”g\:SsÁ{S¨í ‚§ð'š Kò³O ŽòK’™tdÙ¬ãtU,Ç€zâÍq<_Ÿ/ä:R"©þ¯ÙÖ8N°â&oʪ*:Ó°@C&†$<ø©Mô.²Æº6+98ÌÃ06g0#¡ǥɳª«²€~ßÊVÊyèóÛ½iB{-9£ySn°!½³+j[¸­ø©D¸c~ñrH DâDsO ·‹´mÎÈdOñ~NË$fœQ«wv!à_{­ŸøíIŸ~BÍão =áßýÊÿ’Y3U;.e(êZœçì-ÇѼ&¨ mMÞ€$R\^/о,G5º ‹¬ÍJ(©EV#ºlBI…¯°Ûì ÒÙÊ øX³%ÜÁ }p“YXËÆç2oß%Á‹Œ#}>²ÄÆ®l­"d—±ƒ ž‘ûªùg7uT:'éýdü2ôkÈÉmä°°<¦ºàf;â]ÝR^é:×qTUKQ âö% ÙÖa¹ölÏBCÿÂ̸úç[2"ê˜êªu57¼iW3°Ë¼?à$c¸ó‘‘¥ãæü ÚŸŸ»‹à}þŒk»9àduüï¯O2ŸHr¤jßcIÿ.ëOð0Þ³_¿j…ÀÅ,<Ò•‡ýZ̲nh_R+Y:/qõ¼S´Ä¸?f~m1I¬+Ò á[OìxþÕs„M ]òŒ„㦬ñÁoí4™qÆ{îÛwn>¯iR¾BT‘—uÎL’OÄ“"»K:\üDbò¢ôJ<âü;¿µ3„êP±ø^u²Êœ¼”41?mv9t£ø=œ\âòڮˊ¡æPé/.Iâ´xŸß”8–ôI²˜f®ò t§ ®(’z¹Æ»ÅP£¸œ˜šïv0UYÝûm§€ÿÂõpð"úI®#fÂå©sħ0N”Þ …Dãr»´*R˜®bæÒv‚ÿëSöÿE-ÎŒHI-Œ…²Çë2ço?×½|›µ¼Üö-äzœTìØ·ƒû…¬fš¹èU4ó9ÊòG-<9Ž©ï*+gLœD/àõäü\[vugAb©X ]G}'ŒÇ_4½íJn{íóÜQ'AߌÙ~›¹dŒì!KÃg˜'6¦ç¡„z@5}É]r2BÞ !ÁqBÅ =’$3º¶ÍÈz¥¢ŒÌ±Öõì,75(cæó¸‹ <-ø‡AN7“3il—ˆÚ÷ú4:ñ-Ž•¢â0/•Öþ«\ûZ5÷Š[KŽúÞ(’(Mk°€le{Þ…/°ŒŽµG—²c¡ Ÿç&šG£÷^è2E{c"‰Ðî¶ÏGðkDsœÈdÂŽX(©WÚü=ƒÂR^R_HËOÖ¸évÝ—4 “JpWåQ÷¤:ÛH)êçcmMØ?ÿuÚ8µ­Û¶»ÝÑ›rx¥«ÛâWíµ_XBšÿTÚçØèú3 —4«8%NœDÒãÀ©ÌgK)t!Šbj2Úíóµ ag8äÕÁ·ùÇ à¹i~ÝëâWÞdLÄx¿½ˆRàºqëÊæÞÞo­ÓU:¿q3·UÝcm‹‘ºï<ÍGßâi"(×¹+sÚ±.›h¶158JLQ:gÉGìóvŒ'p‰gù°ú“òUn¼º'ôj¨íÒâ“ÔãX¥·Éº[yž±¡æÃYr¸åA8?Ë®…€[;Zí=€KXÕ¸gÀc:TlZ’ÓNr{ÝFÕÙ-œ’‰\6ÙÇ8P7KSI@øv>“dpù˜9]ÞÇi­<ÇÒHØÂ¬tUÿ,¹ £¾Q‡±å08Þ#£ú*\mX¨;^ÓŒTßáðhà†…âÂ>kƒ+æšéŠ'A‰vb3ü½‹g8îjÀõ fî]"\r¹0ä;®¦ö…ðµÚúb¯‘:‡b‘‹VYze åqôpV)ALí@Nãù1xmÂödOü)äµ÷ûuîB5„]ñsóæ]+É/¸gDƒÅ¯i[ÛwgDŠ[¢Î.E¥klhÖOMÀ¥×¿&Øæ¨M#ek„ñß”EéERˆ{²dœ«ƒäO{<ÚÙ ~pêW¦‚Éë`(JÅQ@øKM­í6/ØQgÃzlÛ°s;…d"ðôi9Í6Æu?Ô© Käe§‘§#<úEssuñäµ. @*² ~˜¸š¢¼×=WcÉ„¯ŠÆÖ·Â ªI\ÍÍ5ÌöÅÍÇD|#gù{X{0Íõ­Q¥dÛ“Ç~ÉjˆP2?{Fïó“+Wº¬ƒ7þë·»7]?†c Ç–-UÎQÌg¢æÔ!“0çïÿŠ# ÛʇÌηÐs¢Ü§ Ï©¥÷^t³ˆA <¨¢4mEäö#ަ„QUH©0†ëê»ÓàâÀÌãEc“^Õ÷æE~EТ`¬Ìä&ŒOÍ~juRff_úÁ•·†­L¯…»oG.vÄÑW²´ºÃÕ€O3CÜ@9Eºgl I'!2ê÷´~Jr,Ñ1𽓗m‘ëÇ–¯{&º%$SRЗg0ü:çJÛ¸]toð!G|¯8.EXœ@=lÒUq(øýެ|ÑcéV? *—­al²dlåËÉ.ÒÞsZØpxAK?>ÉK‘ª·­ÌíÁÈuGŽ5QÈéÂñªl\òDB$Õe<”Cn²ýÑ×&ªyˆöæãu>Åû?ÞO®@{=(ñDë“l¶èŸ—$lÐ̯¨v)À.©}É…L¢Ñë{d#Šã"ñ¤›ÈߪNî×o1ôr4£qc°FˆëEþ½NÞ…Iq|ß×4sÚ»ÆU6¢³ØˆtõÚ"Ÿv²ø˜¿ tTuÁf(ó帄SÇ¥Š„ýÌ(O"Ïe["ÙB{Òg߯*p*Göý|­£H˜xæE@„¸³«‰*ª0¬êî{^Ÿ´vad ÖŒŠ’L|!?ÉÊÞDÒœEå÷øæ'¤ ž%ÍfI»u'c}“\©èÉŸ'2çkrPì…à+úsY~ˆ–aœ véß4’™_}ç% 6O\—I¾Š”„ù‘M#Îqƒ9‘À' ¼ïË*!k©\²^.ôŵx1çÙ“vùµÒíRlM O–!1Hâ`DDW¸m¹þÇ‹Ä5n(í:ÙÌÊúj…çG5ÀªEDG4‚Û:‚î²Véç… €¥K…4¸Ú¨8ÂÂòMÁ=?ˆKréÐvžM3æçÎÑÊ-ƒ±òM©™;V0„(yÊà-r Ss-}­GSú¶6¶ª¬Èp·}ã9V!'ÁȆS¾o?l¯9ñâô/÷mȬù$¢©º³G~bjŽKð¡åÔ;;Ó××ûõc‘ë.¼Ò-Éö“û,0y}:®Xî½3çg¢™#mMúùë7üÞ…ÏÊ&© ÎACYõZ‰Þ´†9Œ²2ž¢†¦`}¶´1×gŸâW$½]£{W[MÔB¸bx‡‰,˜ˆ—¤Âð+ºd¶0ªÎÚ!jÌð¢1GçžlÆn(œNGzM+SS(šJýîî8n";Û Äü4 ‚–’òé’xÂ/dœ°”î(ñ¶Ñj‘V©ªõ&ïOœéú;Þ¦‹T¢áÂ¥> ®ç” «JÌ¥ÙTIÞ¨öÝ3Q‚™¯Ñ5®ÆûIN»“§AÃÔß?ÈXIEV–ÖânƒXE¾b~}‰•t–Ø‚L,Æ)ú™©ß<Ìið>ª¸/«2ƒ_ãWdçH5©Ü[‘; ÛéÌpozY÷-w¸,ô·JÊzÁ¼M@¤ô"‹C¨ýI5~–Þ÷‰ï13úz®ã0í/o›ôÁ‰°B§™•—Y¨ªÌ[‘!ë°ì}÷«vº(«¼@dï$?V\9pÿDœü)zsre8Û¥uÿÉÕ”Š@%>ÈȶA¯:ßöáÖDABk=EL8¹YT”kbàiزgî$c#,*q6e SñhÇ•k\ù…€½~Q>¹“Nþ¬‡9QRa¦_Bˆá*\êû¯i^/Žùò'Öº¡ôC’‰;Ï$*J?‡ l^Ç&åšÏ85ôú+Ç:Í g´sm1¹íkÔ¹ÿ»™GšŒ¨j.ß95K.û>4ìüŸÔ·fC™&ÕC%“STÍ[ª÷swžL0\(áJB’r0µø·RŸtÒØßZгðïYêàÒ²lY¦®ÐšŒ:6ªn Õ7e €«E{ŠLQ!¶ÿÊÄŒ{88·âöv½J‹!.ˉå‘UF~¤ç5@ö8 <–‘?(D‰õýu޽¦ZZ ü¡×¢PÄÊŒ™ãtµèå˪èýZ Æ Éœ‘ ßì´ÿÒCšùJ­jü!+ˆÍœL;•ÆØ@ö[¢¬®²ëNÂ¥ãØS,ü1sÙwU'„p3gÍ|I×pË^}Äfˆp¢­ÙÛkà$Ë¥æh™õqsJã§‹èFñï8éÆÇ½G3O]›ï–1£MœžÛh˜4rï™ µgü.¢÷7·¤¿'»-r Yé8H®L•û¸K#Z‰-r¬h¢N׃u-‰¯ŠÓ”bæu“VÅ#¼‹²Äcß%ühæ^H,]ÙBƒÌë´Ø·«EÁÒ¶«­ºIr3m¹’FÄ ¯¹‹‹ƒ'áD#o_ã9éðxJJP#BéH€'N5ZN¦: øYVýuy]fœ0æž÷ ‰U€žèÄáLÙN§íœD‰ÞޱˆNM¾ùR;Jf.Q\è+䘓j*Á 8Ž;‹6ƒ,i#Íј&Ȇ"o¢åÞ”4s¼n×„ŽŒ’ï' ³?sé—™{m[¦´$l–óó“»x’š¸;tŸ¹6jJxÜúJúÙ2ÈÛ%ž¾$‘sœBˆkIC%?®gß9DÜn Í{‚hë¦ð|T·:—}uˆã;¯CG:T‡$Ǹ̺!uæ.îúµ}0&|iuXüÇÈÇ“P-U7)ÆàDŒ"žÇ°$ ñ¾-TUg¢¦–hA¶ø¡a†Ë¡$TÝ162*$J^®ÍÖ57iÂåwì‚it¨šôHEu†Î£U•E£Ñr+ìKå»ÑIáÌy¿9´”Åß”­Î‘@FVE\ç>ÏL\¶’õ9Lz HÀÎôÅýÜŠš0®¼udí%}ÜJÀg]óá±DâœLž×>³]Äê¾å×£˜:ne*ám¡ “úA|œbÙž­\¦Ãéf´¶þ»™s^›«6¢òI¢1é3Êÿ<¢ZÍAêÇ2[øNDo2à¬b¶Ó­–ßÖ¡ã ¡Šj—éyˆY.—ÛÈÔÔw²o—ŒƒèÇR–<*1sÓsý1o jºa¨ ®)’]н£¡ ã‚«ÌïnsÙÚîפТUM.[YœwT—áP:k0uYä÷¬¶,A‰¾A˜×´IRδJ[‰ã·ÞB\£! dPSÎ@¥áSƒåx9  ±á@Ã-¡šÓÊœ— LÇéûÃt{©±•r¦S3_ ]J¯Ô>\㘵¤ÊëùüÖÏ?÷Áárã®ÔiÞlæ˜}ÏÅ_Ò¢{Úg""9vý^ þ#–´WU|"®Yv©¦Ç/«ûÇ/*ª°ŸF›AЧˆq™QX^WY+˜a!$qL˜œ\ÍW«.¾{¸¨ø¢t#ÕÅåLp ~‚Ú~4 ʳžÐ­£"S+ø:ÙÛ¾*à xŽey¿"@o̪,#ë’‹¸dúzêEÊq×™Щ4/Uá§¾À£´¶)¸®3îéÔ=ûÀt+ÖžÕÔ4ù–5 óm àz7ö÷–â@$í»…YÉt4bSÑOÇùÍ ‡7Ÿ©µì>P?iãã…¡8zÂÃ'O§„„¶Çe)©ª|«WD¹šób»¬Ï÷)rÖ÷ƒ²½‡oÐN@k¦XI_ߜڸî[ï]ÖN „)qåí`*mÓ®3N€sÇý%8—eÜèòÇ5±NÎëõ/ýƒwpe'âœÒ¼±¤æRŒŒç2C,¬ $W ì6ì85¶¼çt:!¡ª¶P}tá\dļ,.T/Ëì–÷QÌ)Þ×$š”Æß×5NNìûeiõÜI¤4N¶– æáÞ àÄ0AÂá¦æV ¤rañh$I5±Þ¢X[ô×’’OQj2¥œüuRƒ]2 î”ËDN¶z¼*¥Wþx‹$yðHÆ4ò°¦Ýj³Dš+a•ë.ÿ ?oF9yi·‹¹oËó8ƒ-ÿCÞ0êå­u=÷ÏÔ¥$ÿ³3¿JpiÇSìÒ‘‰:ɤ̾$÷ó‹Á¥ªPï©Póÿû9‘ÏOáw>XeÝ€+ÿÙ”ÕGÅFZçÔÝf™)›Gf ·îœÕ<£>]ÇõÂ~¤Tñ»íï¹µUŽìBȪ’D!}ëŠÆ't®Ë¢hO“¹YÁÌÊ}PHAy˜yAêp™;.xaK+ΦK´)ÍîÂaŠ{l¨%ÓÅÈœ$ycT²_vbZ qqw£ñs’zÝý$2ËÅ‚MfK:2|.ʈB÷a"ÿGºç«{õÏ.»R¡ÒLÇ#dBÜûÂôœ Ìu­EÈTj$Û¥m,“¨“ÛÜ»— ]íþ‰Ô€€ˆQ#œ7/Òð¢fât}d-ÛAæðâÀÚ5¹W0?8¡öVO*]5UVpý·ÂÅ«.ã©ìZ= ešôäá ‰ë: ³?dzʜÒlq[ñÊ"Õ¯jË•]R€¢›ÒÖHÝ(3O:L®ª½o[$ñNÃôyi; Kg3Jí·%F½!_ö«ý±sû»Çé{ †…OÇû1ùiÿÜ—þ`‹Z2#W/Â0Dk,R7÷ä.Ø:pãÔ“ÙOZ‰íá§ž¢É:Ÿ ®LãÉ“aо „ç*ÄÅ@< Í"ØþvŽt=JXΣiÊ ®Z_#ýi‹œ÷’нsÖ6»@|ùÞyŒŸÀ’ê´qžvŠ õöówÕ"`f•î Òcø|Gܸ;ò#ä…HÔ5êe÷´ít4EvçÀFÇP+|óëCÙ²YìÊZÖª®w?K¯ݕʺòÖùa¦Öû1q^ãâgQHRÏüÔŒxɳ»Áûä&®t1ÄoÇE&¾~'1±HZ'°]Î×kí¹FÁm$€¿J˜¹™^Ä/Y º-cb)OÒ7 ÍHú%xü{Ýãû½ýüã{¶$9é§EÆ„,\Õ¬-—¿îy^4ÜDYº{ ú÷¢ŒLÎh‡cÍÖqÎ’8UßSŒigâ2„4B—ô௹*¶Foõ'>gòáa‰Ö¯ƒl1[æmsËm÷zwE){GLÃ%ekÊizUYŽ× œºB.sÎRQ-¦Å>~$zÜ0ͶqÃ’KöÒïj~†P±&«8MÁAÇ4ˆ’˨¥QdªÌ\˜’^¯‘œ9˜†‚f¥ÕfuÜa[78 ˆáH䥠aàO®$y>$FãX‘*'Šånp|EœÇà§ç×ëñ¸øîRšEâïZ—p)ZÇ­1GäÅõA®Î̧$É8EŸ'E„e•¸T£FV¯rÅÌÿ|Å¢É3_Ó 8Ä:בÌOÝ{M–·ô½¸xœË‘8ÊDd3,ñt§T-ã¨*²­Iþ'-ö{Èág’ˆÙyuWBÃj=,T—›ŸÄ*¤©s­‡žÓä®´pÒ;©JŠòWÜEC•’{£¥ Ôã‰zK(ÒVˆ¿¤A(©aHr!eõÿOן.Hn$Iþ`>Ã~Ø™.f„;î0܇»G$ÉîÙ}ÿ'Zù©ž¬šýg7«Šdf„`¦*ª**²]áî×ÜPÔpV!Ð[íL¹¼™úq¢¬{WQ”ç"GAµÏ§¦ž¡—“’ìµTÎ-í÷5? ‡³džçKl=_øN'º1›aƒróÀ‰¶ç©äj$] éô)àšS`ÍCgÜ__%{g¿ñê5áNÃãkWõØûªÉoŸYx‹›¡Ž2TÊKœêŒ/ë¦W½®y¶LIFÛ«X{ ,Ÿ¾Ì¦&£`åU4¬v_¯ ¶3g[h›û]×`eQkFé×¢uÂk¶ ‹é0ÇI·¦ÂëXqeÙDi‘Æ¥°S(ßô]Þsz­ÔḠ£Ü ]gÙ¼ÒÓëiYÆ´mús:²¢‹ ËrSÐÊ2ôP1 ¨Ó˜[¬j¿M‚~ìfo`µ\7âq¸,êX‡o˜¹×ˆÐèR0AïØrjúáø{aTüúõ}–ÐÏÿùe 9_^Âñù:~ýýdßø¿ÿ4ˆþëÔkö’Xçñx'œ\/_6Ï—· Þè?­6Ŭžº”£þ'xl›ÖÙœ°mã© ù,&Ëü×µö ”mÿÇ¥;¹NžJ·ãP9ÜÛCÿ¶n[ÑÒ£‚Ê1nžŠ{.Âøþ)ϲ)ª­4«MŒ`*²+7ì¯Iu…WaÙ8.Æ´Àø V¡Xè½GM;¡ßU÷µˆÛun„Å“X¯>€ù¦¿‹Í3û#ØÞч±5„&ÎT·gú€¨¶ŒJÎØd"­¿žçѺêÓ[uû-\·™ƒŽ rÛ-‡YQ!¨,›ûaº¥úòSŸ5ô¨XbRÔåœÎð°]NËêaîµt]ók]èêøÍ.ÎB×-ö娯ЌÇsjKƒ¤üÓ…aÚN s¿uêÅ팉cÒWØúq½†3ª­çŸ¶Äk1fV@ þõS•0¹9c”Rúylšì-;zyÜ+U%«WÁ¸lšÎÒÁ OgëýŸƒ Ú [£ËÎh‡v»µ›'Í…Ú¢ ¯Yô6ŸXógÖ’Q-ëÖ›¾w[‘^8â-¶b“'C®Oˆs@f\¸zMm"ÎÞQ¸"q¸£±`žéš÷³ª¼ÐN5¸Y"š¯]ÓÍó- ÝtƽÎì²\.y‡nEW+ÌàÏÖ}n\FG? -ûý±ß–ÍŸß_f„þ²F`ø:l^©õõ×R÷ßÿGølùÆž{÷¸—uÙaÁ~ñó9×}×¼&§'üšqPFt·4SÁœ xfŽ+)±òÁ‹}/&†eù™õÆ2¾Ž·Ûqú‡‹£«Ó×i2“¬0d7ÙÅ*í†*ÉÝÒB+ÂÚ^¶o¯žî¥bt+8ȡР¶£ ´s@ Š{<†Ü”ØÔÁÁ²ˆ? SJÛaiÚHÖ÷1¾µÇÚ5I–(¹R±Óí4“ܨ ÏËC­‘¤æ(Î*D/QH¾ŠžßÀe='@^vûw6·>Ü~ÞÅÉõhi !Ø´£ë—(fNe†•‚iš·¶îhU=¥ÙdÃþÒ£7pµºß×üœŒ¾ÀÏûå¯Qú©£PϺ^}5~}Óaóôš«¿vަ嬆ý6-Û玨_]¹^Ç¥‘un©N®êŠ8‰¢2Òý.˜NP˜7eÖ ^sJy\¤Pádë2àˆkEr¾PûY›Ÿ]¢ãåaŽŒÕœw¯œ†ï'tóR0ªl¥->št§&ÚT–0–Kd€ðäªVm“"d_ÇÔäø2 Èa UçÞ.9:F[ÊM†õ¦Ïº ó&[õíè? ßBÆ*“bÐ=³#wæa½¨bûi~¸Øq‚'ê9ÂÌlêB¿gì…²ÊÑ„bÝ[%é—0ýúx?Œ¬aÝÈöý÷÷ÒÏO•=c붯7M—Ócw/·µx^ëãݱ6y\ú½%ž5]œÍͬǪqî…£'皬ñÊÈõuÍì=h<•\ÿãš/^Åh7O*x½´·À•‘¿²¤æ2¾ë]Øca…²»ÎÕvuÖ½¬Ã|éx÷îe=û]ë÷Þ·ãÒE N0.§­^fá]ð@—{Û¥¦Ա邒'J\(?*…U¢W­K‡ ±¢ -ˆvF;˜¯Qe¢ÝŒ>d騟eÃ)K?šÕ€×]øç5ÖN¯A³Œg§¤âeoÂ[^&ùÀÊ,`"­gÓEò‘aÝ®k¾yÁœåý\þ㚟Z§H ¬ÔÅì›Ê ìæN`iûûϱšþçD%Ô«ž¯^â‰Fž‡WWôãmãÄ`®´_bX³ÿýWKÌ"Ë„ÓiKÿ«K…”p“NrÄ;’¼ñʹ!‹C•¥µs¦Di&6'¹å¸¢¶Nõ_J¯ÛÙªFâЫˬŒC˜û9VŽwErø¥7Xhìš+ÓEmzÌI’gQÞ—ŠNwQO? ‚LY7ºÅm›'¬‡çÖÉ…1¹ ™¡¹že¾/›¤ù=©"ý`3BìÌËøüKž05gñ¡ ó5¿çqºØÏe-4 ¥ÖT^§©Ö—o1¿ÂW°wyßÙ|²g {:!Û¡Å,’t71„T™ÒzVÓ~¼Æfúóÿ|OÕòÍ:òóJ†gu7›jÌfûÅ^ÝÅKòlNÃZ3ÈTÞÂþ¬-éè¡t3U…òüYœWhWòDýóx¿¯ÿíÞ³Í.ã¬r¿pYÒ@AÂ`å§j¦‡: îY7ò`ìdÍhŸÇyËŸ=˜”_×Üs¡æ‘–Ó¼÷i•¢Îfk Ã…©N±T2©äÆ•­ñÕmKFyyÎÃ{ŒXO«£’+í§alÊYéuß‹¾S„Ïë0RYŸÄá­;¬OäWËtxç®·¶ñ?A»1N¹“µŠØJ°„ƒ1L7º½>Šò±‚!a˜öœ“ôö&´ó(7ŒçsYþ´{¾ê<'“äPU"<ƘJ?_˸ƒþ~28YÞ¢[¦³'ßÒôƒ/¨¤>ùãÓ=áÇ…Æ·€ïý]¬6ÁÍ{tÿy§wYvMœ`÷Û¤™3qÂ$«ʨŒo©cyHÙ”[OòÝvzÙì¶6£çkú‘öIÎ…ÕÑbüÑÍÏï—Â3Ôö}êêÁu}ßfaÁÂ~aã(«™1Þ‚m+‰¡wfpÔõ/£ Nf2 èmG0 DUÊ6ñY¡Ê©7Bw‹GYÔ³5Ÿ¤ÑM¥~©\ì­úÚÊd›N‘ ,ȲÚâS¡AoœÎq˵›ƒ˜4|êªVuÞꌣ›Æ¬Î´>¾ž•º-´)÷ÇyzÆ‘ãnµyRV¨²>·K·÷jÁý ©ùø§rì¿·à.ޱùcóp—RÕ¡y”´ºQ/‰K¿üZ½¤×qùѳ—~ϯwy…‚l»ûÿõ\›õƒ—bõêQ'³_á§R½³†hŠnS,ÈÖÎCéÁ±®NФ³frÏù–ûkq{»¥l§mÇä V[Ä«Çi„‹ý)Ía]eûíõµ:4ÆjÕ%õ47QRf·¤oï'¼’ në˜Úël5i=êenªøˆ™3…Õc¡.­RckNnÑ?m”JÅcÜê.¹¥Š,_SÅQòQÕ1÷ÒævlO˜ÆÁ·u]»±nîå0(wÃbÃî7Ó½YǾ9l솱_æ´Žp÷|Ì#gúé‚<¯pÚ[VÛLLÃÞ —z6“YÒ¬W6@sö±…5„ÕïO>ž$1?¦SMB-t H%MÚGºÿ÷S‘Óq׫ÊÛ@MO ˜Ü¼óñøÏÚÙ£Bn{LÔ×íàÉU ¸ú^ö Ÿ\€yd[)ÞÏãU/ÀÛo ó¬É>!£_§ø®mØžKMm­×ÔÖ̬Š[œEn9EZøk®|^ bWçºíµåaŽ<ó—¶´þz“}R᧨ôEXÔÊPúÐÑ-Én‚‚Õ“ßÍWÁ|Êgœ¥ôò Ô|—üáAñ¼<æ* ²nRõZM[3ÝSÂ’ý…ÎhÑ9ÊeÊ¿—Âî5PcËé”6ý·k~ ÔÎyÄ>|®yž%¡RPÙºq}¢êüXçvþúóµyDSJ†¿7ÿÖu@ÍbCkMq Ù9Ϧûá5¢·ë_± ýv…¬Üd2úІójGã K©*Éûê3žSUFª£¦çDÖÞìy=ý¢ÅîËÎ}9€ÞŽ{‚ýñµ›l÷cïõ0¿w7tûk6~¢"‡JêòÝ»QEïPÇYÇ:ƒÞq7ÉuöY`–çñ@W¡Z. ¢°(Ã[¤Èt^sì3 ªk7õúƒÞVb†Š£‹±ËM ì ¼ËVÿ5¬§5Y~,YZhÆA¬@iAiÙ­‘j\8èt[РN*F;åg¿wãî°°W»ìË Ò§kél9³÷×_ëãëKghC@·ä í6üU¸&ßæ¤lÛ©vÞÎÅ¥ùt:Ý.¹û‡z²]RthÉë³Q…¼‚]R¹dÑ qY6†£¹&ðÖà5ënr „ ã^.—m/æi^#ŽæN§s0êú ³+ôÑ~THӱƞ#™žó¼M×Fĵée¼¨m[ßYÒ6:^¿®¹2TI/%é{hê8Ì2¡jÄ^H\9½bn®à«ÏÚLå8Uy™æ^;±ÅZFQÜbóEÁç{†Ï”yi^£·ÔyÛ©6áN袿~sŸË@~¿ó8I™§˜†¯áMÿž©´þMëË6.ª~ë²6 neÔ齘ª¸W.¸w˰2èb¶EKúð­7ÿë)œ¼=ö÷@lú7ÿÜÍ_`fÌCŸ}ÄLÓj6¿{]ÙcÖ[9¿ò:ÛÙÊ9Üàmxšã#œü·cªè«ÅÀ´MQà-%‡D”òQ•A@ÔSUUÜäæÞ1ôn©x¦™j´Ö•Êêq0#d)“§ÞUe÷ X^YÞK€M~Ì c4̯×64¯¯ ™Ñ§Êa–IMR:hY®wƒ.›gÐ ‡»6ë8Ì@™;M#[gB‹Òo¤ B’a¸'´ = Mù­îƞɗ‚0²cECÄ*™ÊÔ”­¾Ó§ª í +q¢V½n›,ÊX]„íè'®“÷ë9/?Yï"UˆI]ÜÛ¹v›iãue=®Ö’y7=ÖSþòñúZžß‹/~u‘Ìr¼~ýuοw¢—üÁ•"OêæA.è«" 4!=ÌK(»Æ,ªãa’(Ìkã±y®Tˆ¬ÝÎSˆÃ¦?o^ ×oŒÎWKœWàè„Ù]˜'Ç€Z¤5Ó´¯ò >¶G½n¿]hŒ“­Àn‡›‡í=O¶æmєʎªÉô9[Á4̒ª>ÄŠ¦T’ƪÂçC¹hThH„pé´ a²vŽó“qosó=G¶œPßýž¶Ã0ùÝŠíx·ÚÎzü’Û=|óp?ͦÇr¾oˆò(ü éÍØ=ªbš¤b™9Oº¹V0Ë1­Æ,ýÈó s¯Ý8ò¾hEêÒ˜¼4'ߢó¼ŠT*Gy6zbOòþ¼ÿò¼’ÙW¾ç ˜á}ÝWÁõÑÓ®V[hµ•ë þ8½góÈšÁžÞ€°;MMŒ‰™aY†‘N 4AÖ|n„&ê<ìËB7.)â p«BÐEyÛ½Lènû³¦HþšCcµ¥”ÚG¯o¯*±?KzQ»r_r p.Jd˜ÊËÌH•l@‘¨MߺÆíœÝ+?>‰Ó Æ/¥´Êš™˜ËhÉDØâ˜ªÓY!¢­›¾gsò<ã©kãE{«Ùú¤l³š^óûÏ4¦ë^y+‹%šÞvžægìASsñ¥ÝºÈZ(gî=SCW–ÝtÊèoÇErüò> Û—éá?OÛó*+`ì§‹'šÿÉn÷žlsuû⡜û“CueÊ%G IŠFU·ÏÁ霛×B‚lõv½r^µœîñû¾_:—O»­tévêè«Ò–sQ›ªmnIÕ¶7·<  nfxªtÿãš›ÐÜûšŸÝìK©æ¢û\ úÊ÷ KoQ­P’%u®.Çr€îk‡rÒ›Y‘Þnå¼C¡ÍN‡“Æ<ÍÊŸú\eQ¡lŠ HŠF¿£ÂÌ™âÊzJ;^Æn^ôÄœ)|ûì­nd‘’éè:‡&"b9UáVÜni³y¢~P/SFq¿³º£'€©“1÷å Öuü1ÿÝÞ^… 4ߢöÃçÉ–ÀÆV‡9Ë®*ï·ÚºüÛiÞ¹I…º|sÈî”Æ±/›„ÙØz€J¹~üÑcÕ†·)v3ðÇÆà85[¦Ê™õ'\·”‡ÛPæø¬#ßuEÁ6vTfzk’Ñzm'±Ëù™î<»Ç’ÃñÙè\ßN(8÷Ý××>µÙý³Kî â0FoÕý¥À‘R5È2Yf› ì€ß>Ú)ø¯¬UtÅ€:Bn01}U’~JŠà0"ø ià决¤5!ã*·=Ó*O²© ³½$[Œ‚?Ý+·žÇÎ _­BYX¥\³è4A@0”Õoò©È³–Žî¹€¾`䂬vîØ…ˆt^ÝxœÞ…WÒ°å#ó“ã¯c9I—û__¨áýýÿeÚÆk:Ÿç%?ÆH4Ú€ ƒU©Ë>š"ç~î£zM¾÷äÓË– ‰†4Cg$:ã|™ZF9d?“LÁ²7Íî³Ex2¨Ù»ÜÞ ¿;ØlÖ™v’ÿ&›/FÌ4o)£$ ‚4Ò÷¨U*M;¯í¦è[µC›„iÓ·qPêГbõÆØZLðuk›œ‚»%·$ráÀÔß™A0Ù¾îØö{¢àJ ÆùyuÅNÇ÷UÿbB]87†|Û§Ù0·ÝÐÜ*·Oy›bMWÁ=(ÐÇr#Ú„ãlÂlm¾Šs¾;NùX”§öÞE'³±£nµmtSiÔVÁg!Äþœõ“+vxÉTOs ­x½íeFðÚâƒ}¦õyŠ­=WÖÕèPmKW·&“îá¤ï(v S—–Ä”JF£ê¾&©ë=¤B.†öpÓdUeú"‹­óN³·Üò²[¾Ö»jsššú¬ªoÙ'Úmãó¿axO*dcºJëˆV½k#«êCÐD%8³J¢üÛ/¹BK¥[œ•ÌëŠ êÙ)GF¼BnB÷—]6Av˜£°*f˜ê;4عðn€<שp7y€Â”‘‡²KbÕ”|^äQ5²åpœ&I~Ũfonþãÿnôó`ø9è£Ç÷R%XܲºöÓþúõµ:oš4/,Ÿƒ:Ó77w ¿v7!Íòô,l±rêuÐÇLÃÄLV³5Á¨T²÷{!¬aÛíQ¶KX€PžHãÜ9E[( öB:.åxùÉ2÷f1þÃì— ÷éLiŽOú)Ÿ_ÆõèɳØ/¦ÓuÜÊê2ig†/+ró•=é~W6‡6ãDѯìêæ±a  T"§©Wè®ÁÇ)ή³µ}ýz0O²ý†çŸß·ðª®^Ú¦»WŠz :ŸÔ2«ý¥Í·××~h®Ìû©ÌXèԹ̑¨ÓciÌGÁ Ö‚ƒûƒŠõþ8—‘©=Uþ8wZ½¹Ë:?‡T?ºK¹pìxÓC!£¸ZdnâÞ°v|IÐ\ ÈA öŸsùS0ù-?ÀߘM…@?µÑ-IüPÁFbV*m…ÁT•Þ’BÉQV›ñùö<–[ZQ®t°,8'þ”èÃÂg›*"„:En êé_áÇóR7þÛÚ"KTÏ[#AûèJî16ªx²~q*å>²ÙõNßæ†ïz” KdqÅŠ‘€«þëù2MíW¯Ë|±î¼äÓï¢Æ‡ºæ]•܉œ‰rR ŇÅÞ{MÕýÚÚ)„]T7›ÌÈ„¹Ìæ¡ôØ{RöÝÿ~ÏЊäk]lÜŽ‡¾f™[¥kn&h†¬mÛ–¶9…eò÷hð$I˜ƒŸ¿ë}^­„Ópo½®ùEýóëa­éÃP× ' B¥_ÔÙÒ(¨T+³âz~3Ãlèð*¶¤x4•5Ϻ&2ï¹W§dá„k^  ÕĆ J³L:ÅW‘ö®)Rõe”’®¯ëû¿¡‡lU÷è¸ePyÙxɲS–ÜQù~¨ÅÿÁÿúÍLžûÚq¥ø±|ëín8%¦}Ö·=ŽC5ùŒ¿Æþ°}„w¿þþ￾__¶©yf?» §°³”ØÏůײogD_>`ÑèÕ øÔÎJ˜Ê8Ÿ ÂÆimtߎ’]…°^³Ër7€ÇîI2Ûá}ø(ÏÛ”vÖ)¥>0ÉÏ´.LNq_ŽeÝÓ£ëŸ×ܾÞûš¿çÆ×\™nïãðþꀕê >IÊz¿„!ª¼ô:Î*Ó‹¸9–L|]Ä¥mM#û ØØÊõ¢<Œ›&ðêËãˆ~*›ièH`ËBg~nã ¡-’e³\€®ˆòå˜üVœ­aû´sX|x ÆÍK .û×6.¯ïÇÜön\UI±AªŸ©ÓeƒMµ Üù¬eƒ7”./Gdù$˜´XÏM$ÃhÜëÆ~àVåX‡D`Eâ ÇúU¬„¹Ú¹-u:xTƒŠ÷¡ºÇ½ê2iÁ¶G‹Šþ½þT¦†AFåòÒ/¼ghi›€Bò¦·$ùûÞ¤yß–wDzýo嚎²ÊmO“/`5íð P òç÷7÷Ô»ö¯Bµ÷Ä9~ýºÎË›¶âµâçó¿]sÓ·籪]›·Œ%YC¨Š» ™“óL…&7ùŒ§ãÝŠ:Û:ï9î÷÷÷¯__ÇVÙjPÅd%7§÷á 8N?ƒ~ZjÀͼcNkÛ‡ïÆ¬ž”¹-+òÚ¬ò‘í”­½ôcMéE*$ÜÓói•†M"D™Zý†Þ3~·qå­NýÂTªrgØ¡ú±9ü7H2E|CåÒ$ùêþ2ÚöfJ—…#=¤eÁÚz©°äJ*jÇ¥IvVf²¥*Q¾[š$ šõû×÷×13¯w½ŽIß©½E·Îâä2ÑÚMWìØ.Ò¹8æUlÌÚ®)2(ÛŠ¥¦Jª"VÀËD[‡Ñ¯Ðx>¯ânf=·¢qó~ù$xÅi¤:MÒ÷wœcA]eæ(P×ÐÐä~u(OD“‡Å٪̼¿|€>Û¶‡ˆ.vñ´°SvŽ•ø~(¢4Ð÷RæX5Q-`@‰Ë2 e½×„kÞWe[·¼­’(I”e£tÏÌò©0ÕÄÝ̭Ö­¹‡yfTDáí(5öDUšhæ ˆ ÂDž[¬“²[Š»ºŒÎéÔ·¶Išq°³¦øM£Ê”ËhAFÅ¥b]„Aº•X…1ÆèmskÓMCP¶îŒ½ã×7dõ¯oëôþú…Vàãûo†çŸÿóÿù?ûå^¾ƒ¡mÑ/½[cþ¿Ó|Ñfx…ð!Æ/SU¹6Î̲T£“{ý%k´×mVÆ„Ó1^Çòª]¯Êáëë1;ž3„¡ßçZ'£ïâ´L>#ÔšgD­ìxSºüªÍov×z.Lú]ÅsãÒl–Ïu\ëa†n6©*3 =$ª)Q¤Å9ô„÷™QÖ=W³u€Hd¡¸^(# £ÜDÞuZ<ļÎ-…Sè¡A€Vh¦ˆï¡NM‚ÝO‘„w³çö†ÇŠÃ£óýýÙ:1}D´6 ·=¯U!þ~„¥hô#P¸¸[/%J¬é‘  `ŲԅrƒBA?æ³Ò{-N¡ÜªÒkëÍ߸æ›þõK[pÞN\¯€3Í^¯]'ãùë9±p9(ÇI%°£ì o$h™ÇECjÖ{1§3]õ<Êi¬VI•"àÞ*Áq=ðÓC`¹]s]KÜÉ1B²ò˜Á7úÍzE膑º—úö¨¥åT˜ÞòAºJÚS%ªZ5J‰ H‹$a’vR7„ Ü>X§(óH‰G9±ô14κ¿Ícj²ÔÕðrtmoÕ5dŸ÷åòJÙ—ËædXžV³™„0"K—Âþ¹Ëi½Óm¾<×^‡7Ú¼LÔ™\?=´!È „ /(”p]ž›;}f6ä^¦¡+²ð–Û»ôðïß-!ÎÌX%©Žq×è¦Û%Oëthu™â ªWû†‹_ÞÖÆ§ˆô?ûM|ÌK±Ô¢Þæñé å–æ§Z’}’¡ÉSvmÇm'=ÝW^±Ïæ%zZO“B‡‹²OÝÚ¡I  ÏOYç±+Ã[\«cŸ!]©Ÿ¤ê­ïË{º˜19ô²P´öÊ,¨ëa¥x.´¨ðãðfž]:é}\‰0#&u•êì~/Çå߯ùºœ#(‡MäN¿”šüܺõ¶å‡€¥­Ürh¬ò£êƳ×yóÚNÃP4œÎ*4ÔâL±Öël!Dqªhù#ÐUVòšÎÞf¹¦¥gPmk\¢x§œð³àš«xŽã봮 ðŒ*½§Ó~°NÞ©ñô^÷×Ü÷0MKÿãB ‡¾MD蛫’¬†¹¨‡‚¶Wî\¬ ‰7·²ËcŒõIÒM Z½lÜÎáÑdŒ4uüFFUz—eåJfžÄÌ™çìhÑÚ6·nR ra$±Êf;.%bR)YXACÙLL@mh™N!3g©<,kÁxõ¶X¯kÜ'“¢é\š*<ºï$ï\ïíe®…ÂïÇ«ýÏå´¾¼È¬Ë‰…VÍâðus‹¦UfZ[±0â&¤g¦³CÅN'O¥‡ ð´ï—nç bΦ¶~„õ¼ùñÿtÍ­1>èÕ§ºj4®¼`'îÊH¤Œ;ök˜ûñØv17O§oÐôûÐ_„›s¹aÝãõÓ ÛÆWË„mŽŽAζqÙG7 ¨–GÌd~Cä“7¯Ÿ3³2;ÄLà†«o邿혥*±ÚJìζ“•g”ÜÍoÿsû]•Q($2“”ÆxA§§NZºRh™³jŠƒáCýÆ0,ú+‚¬÷vjLm¶€ö¾æÃɶ[¼ËnLk_ÆAì$`÷EJÉ·Pˆ',Xr£c9áã>´†iÂx¡æÑ[Žã:u¥rÈp7MDi”ºi'ïN–AX`uæFj¬›ü6éB鸄!‹ÀúÞCt¯…Tò«Ç5ÏæÃ” 'uy[ç ´_4.=ÿTÏÙí³îrr¿ßt¯Û¥¬¦1«\Z¢ØÍöx˜µÞ¦z U”õTʘmÝ8Ù‹L‘Ï.…áLü„'s}EJëÞgVZ@iE¶I¸~ž:aÚqª'pi’‡ÅØBÙVªWenn9J$æuL¥ ú9µiÕTXF¢ œ³ýŽþPËv›`sè²v æJ¦ËŸ˜ªvYèíÅ|üúÑÃüÜYÙNÎú²ýù×÷cûû¿ÿç¿ÿ|™‚+濾ÿD$q¼Hr‡'ïÖa7/‹ír²îÑÓèÄÛ8 UÝwY?Õ™QÃ:§+›s\AÕnµ¢ îÍmR¶¾Aûewpqüÿ¡ìm{¯hFdpª¥cGÅIQ´èÛ„ ¹¦í¡rÚLC?À6ñæn變P~œžØ¬4S-C1¶vœ—~ð»í/O#ñ=£Í8ïöèl"£lÊîiU˜½FÛ׉ŽH©@ç@ÒsßOÛÖglÀ ‚¸w˜´£–ú8Lãg9é´ËIÏ!Nxa:? ïScóšÊÊeÌÇ-*{ßôGèϵŽßR‰Uy˜º@€µÖ[ljëßÕ™.yÂMWø‘¦Aä†sznÜžœ–r™Q¾{Íùãu²Ý– #s’O{¯w î2/òbçï3Ï‘õdN˜¢ËìÆn$f:؉S´Åõžê‡4ÈD)¿-'é_Ÿ¼_d‰Ù'À¤L3SªŒÛÌö­Çq<™ §oß$ϰ\¹®Çªƒ/s-EA–îŒa•1ÄrÏÇë×k]\$aè©‚Œƒ¤¯çiyì0vo‚Ö»Þ-.„«~±ÝÈÊ‘ŸˆPd£ZóŒÁ*ƾ\(òÖh•'AK”l#ë¼âÀ„€‹b]"A<ÿQd· ›F$ME½¦©¯bAâ¼¶Yt'M­Ú¼Õ᧯fìöUµW{À¢AµyÜOõ÷–Ç—]sØ>ç@Í;!-‚HõzôÐù<4³ŽÐçGå‰&VÓݲ!þ,]¬ê?¨Ç‚–þé¿¢¦¥íõªÉë"ަFÕY–Žp!c£Ê–Ê­³•²Æzʬ7©~ÔÊ0ÊqªÒ™ ¡Bçó:vyŸõ¾ÔEŠús×÷ý\NH ƒí_ßM³®¹ëtÍó²ë²Ï¨­·2Ò‰ c©(­&´2êûûK±:VQ,hÙÅÆÙ±çÔÍè·ZŸ\¸æuž.²)ËZãxüyÝ3Ü„Øô¬¤¾L1XoöÙtâ4í÷“gå â￟ú:-z“*‡¯%Ümõ–ç ­ëº¨ºnËö[…ýoµi;–V×C­c{ÁÚ®,-5dÕñšMk=[V6Ä™¯ÉÊDËõØ®<Åa¶‹)¿ïoï¶³<ŸV/26*|ÖµŒpHõÞÐ¥…] f;ÅhÑÏìhl\aäx6† ÃzÙ”¶}ä’ ¬uqÒâkÁ‚âƒzÿïýaÆÑÌ8¢\—™Uƒ–ߌȧ¬°Þ q*ïˆ]îDz>g=]?ë+¢[X¿é'£·ZkÏþªóØe6;œg'`¿è,tÇ]}„TQ9b¸êÊwwëý¨þf‡f¤ã>2+*a`Wç§þš»5ÿ‹Râ‡Àg”Û›Ë>yZW4T›½dA1ƒOKl-:šfŸh ·qÈþ9ª,µÒÅg<:ãþ{Ý÷ó{oû´øH9Œ¨”ÎíØ'áw…£󶉇‚Å·¼ñþÖbM㨲~È]TÈTÉ;Ìvâ¢ø,“ ®„l0ÆÔSWºÕôm¢fŒp'ºmö“»ëëÔÍ.3Z¬ÏÌŧ~®Y˜°S°’ÐÊõô’*CæRõÁÒ)U»†hÞ]Au¡/Ùßöª„†§ú³Ù‚£²__Ëñõ…ä}“]ecF|Dm+.‘PbÒ<ï_Éklë߯mc¤6ë÷Ÿ¯Ç—ßKY=ˆÞßVfkÐö°5ÈÆ}]M|~½°d!ËŽn[àmÅE?4UuseÀ¦Ó½ïÁ¢M%ÿº»6´ß¡Û.v•Ÿuï$êGF¼_Lr¶ë—Êå<ª·ùr¸õDM~4¯\pq¶/™Ï‘÷ Çs¨cyìñœœø×¦Ò tÄ»ÖM¨Sö³Uç/ÄTS%i¥®´w´kËìöQ>1ØfKÂdÔ¢Ð*ìëÄe·²¸Gøf È4Ÿýhº¾9~Õ-³"w;‹ÈçuLÁ­ÿKÀÃÕe”Þìè»;gûƶÕúb QØŸ~‡ªÂz{e܃™Úk®µ_{åó®2·–¾!——¦¡>|”‹~€âžÔtµAÐIœdúá á}Ï9ƒ'35íôüþÆ™Ùp–±k"/ýùynTbF· ÏC&ްL^Ïû¹­ì×ÍÖˆ5îÚ1`²]$[ ©p-„`âŠù†._qN¯îï9œÖÝψžF×ôkØà‘ç‰7ON¨¢ÜH]ót¡¢TÕ´U˜kæM£‹Y‡U¡÷Z¸IÈ)ÿ„ª Í[\ÿ’k¥’2ƒ­žFlb¦æˆl³ó-nÛ cØ“§ÙQ¥dÛDãÞ¹n úêšS¡ƒ,|’dºæmV@k/+W&UÒTH%?ÃÜôäjÛeFªÂ—é­‹ÒN5Ÿ'Fu㞴݈\Nw‚ž:X ðŽ“kÍ¡sCc´ßòhÖ³ŽeØ¡Ãèžž²oaßëŠ_r$þ²¿^Ëê=ÍùßF{ž~4{Ž­PòkÊ¢îé*ä•Ѽ­99•¦—¦š-£¹»=|gt}y»5JµÇL»B…ìÂlmú¸Yê¥Ç[áú_P4Ð_gÛ7䮚?|ðr¾JŸ'çæÙyíÍð–í ú4AÌR³2TJC¦Ñ{Sétÿ¬gã~}ØÎ‡™¤™÷_½¹¹DXÁ¡ìä„ܦBf·Å-gqsNmžÏ{±íU`'U]1EQ%ÏÛFלFûPæ!×ÓVÁÓ_-Dìq…‘ž‹ºó*;Ÿú ÛÒ%AÖeOÛÁK°ùA†×kšLâ´mQÚó[ÔšºWÞІ—SÇôg¯¯¾ÒWÚö>1@sìU7Ô¯24޲$†©Zýàkõ‚—γ-÷ë÷z;z¾… #Ø ^ìþ?úéø¢ËþuLý€š±uæ¼Ã”훟k,×5?õç3£?N“®í½iaäªͪ}ÚVɰsz^­â¤°M7*ˆS²†qÓ»õµ½¼þÃþ: òÞ[ÿh¨¨n›¨n³Xï>ëT7uŒN»=Î ÷ØOéÉÕcÑm9·+¶ËTäêAL³GìW›"’™s£³„žÞrÏâן ㄉÛÁÕ‹i«ëú4Êæ¿—P²WîÏjwm ûðÆèEôrì•b]ó8¿Ó$[˜…^ê\©òŽÓ~vükäÃ@øCé7*èÌ2V+4ëÒ{d {ÀÊ•p}¦¤Q(ŠÛcðš‹^ú¹ÛQ7«vSBèüd\|1k*NJC_ OPêÇÀe•ÜÕÙ±¡qÛâúµOz³AþV­kÍ5–r5´Kž‘±F~À%Ô]4Ï-Àúc£Î[Fa´C^y+ÕeÊU•5­›Âv0ÌÅÉ豪άÊfì$¸NªîÌê-…¸ˆËm{\‹Å—÷­@yn&nSš+ÑÁˆå½±ß0rÄÉÜ~6¶ n©S…Ä`3­U—3G!¢‰6+„ªTÖß '‘~ÓÝ)_ /\m}øfr†á§éÊl[34ÓŒ¼k^÷®É:8•ìš·S_AhD8ZY†å÷œ lçiP]›÷ÆßÈón¸®oÔ´JD¹‚Ñ BoÇÇô¸³ÁÐiUµõJ…Q¨Y`u ÷ƒvþ: f÷ì|_LæÀ/,¾gÐþ—×R^—Ç)7/—”óóñø‡J‹Ê&dQáÑ …DªR+mj*h™I UWJ2ëknmPXy û".ÆJ¨¾ÿžjtÕC¼b«ÂhæÆæG©kŽÛðèÅ¢˜º X2Ö¬ÈW½®[j¶TI)¢1oyÈB*¾2”sÍQ³¤ˆr½õKïýô~Ó!††áô¯_çÖ+'q¥ÿ/º Ñcö6•íªŒñŽB¢RãuxSÄÕªdžÃÓ(q/·Ú)Ò·Oþ0gSIUà ¶žÕ´ý`Þ^ºòl³«~§PíˆÍK5 -üLq‡ÒÃÒOb-Ôvm7243+ h :չאָ٣àÆ7@ö 1ÏÚ3ã ÏoÝ œ²oß61CClƒ’”àW ï‘‡ðtrJ]-Äœwo#þ˜”‰~½ÖÑŒ?P~=õŽýBöoµ¯™î‹"Ÿ=m»y­ /g`¶dD,Û`<ƒª3OQ”îJã¹Ô S}­ÐxÓùûX¶Ëwðbµ^cÎÀæPÄyËLN×¥¯“¢šÌôqí»Z…×ç8βáí×êérºh½mîÏáôP›C ó¦Tyž ñ¶ÍÏÓÐwô"'ֆ†"F§q­„Ç‘æe2жemüKÜ6G[s‹Œ8ô9¥fÔ¹íl¢J—ºw„õê-Nu\­’}~L Xk­s¤ÙzóÀ:Müjßè%˜w·ü$>Ÿ%Àë6xXÞŒ.‰‹ôÂþE2{£ªèúÞDcØäí“0ºAH‘Û즾’ä˜ì ¡ö3¹ß*hM1ŽËÍŒaW¯rº¦!A™†XJÓÛ5Çd²ØÃÇl´Wë–ÑraìÂFÏ­hY»r°”ö'pñv¶R XÝ‚¶›l{ô9¡ÏÔӘͤÁ®¹5õ±Õžë(È‘¨-2‡È)Âö¨„({ O#äûl MUmš =â}5Ú"©A:¹q™©Í–R)U4ÓU~ó®øÏ“ búYuˆô¹°‹Ãâ_ z…e†Ë•ÐKÝdWvDB¡ùÔ¤ŠÙã쌌¨ëÜ5íª²Þ »‚"™>z¥ÇÄE0ƒwzøñAS ~jU}4…+ÐÛ¯X"š—Ô:ýùbgñëÅøøõׯÃW篳µþºZ=Wî¸VþvÏ“_Ÿ\Ño¥Ïy<Šmkǃƒ£?øíž1–2E¯ÿÔQózEevÞÏÝ¢SñôÒf&½s»i¼a˜ë ß4/dö唑¸t®ïÿœW@6%–³ñöð¨u™éÓBN¬P#܆åpI̼ qø%á)¡ I¹+ˆô3Ýžºøç"Xì¹%«í_êøatF𥩗°Œž%M~/2ö'2‡Ùض}=¼ÀåvRSf:PÃX£­ö5:üiÛ¤WQçmEa½,¯sÛŸ¶šhÁÒG“~ÔYVK³£ $ý@sÖÃy^b$lx¨BÈM£Íd ×.³Ð*B}d. mÒW…9ÀðêTÉ¿Öiîiˆ*…èUÒ:ÐùŠû¥Ó»ºÇ¸¥ùËZ6¯˜aAVßñ _?.«2£Êm•I”¸h(¦¹s¸$ª2E>9ê;ÝivÃS×—q¨Ú|\^ûÛx ±´y¸²QùÍßk ¯µÇ~º¹Cºûu“Ô<ÈËL®®|“ê^ôuÚv!U¬¾vMœNcfõØÆÓ`Û§z“q¦ÌY$Âk‹ñQ‡u su gD+èwK{KóUÁ­º%\ãôóg€d_Ó-ت6Šþ={:¦²¶nqíèù:}i& ]ŠþhÚõð£z=ƒŸisW°ÑËŸkïeZ•¿¾Çn{ ·Ì®¼ºùUÞA±è÷u_‡Àúòü…ª.Ú¼*ŠAê£ç9̧¨é†_[^šñÔ†³Búò:ÌÓ”g ¾ncQ‡÷r¤™ekšÊ#¨DYEÏ[!jÚõá|7ìø:}©·ñ$Rèx­Õ nq9u|OФ>¶×kÛO[ 6ößßÿ·’¹½½ ÞØXÛEøñ˜cvE.ÀÐw¥éq…é¸/Û÷r9±^–›ƒCO¼‹)›¼üG²nµS`ëª÷î_¿þ^Íëwv©ßþüFäR^¤ê³°îR¼È£{1˜­ûãÏ—™Ì®^ŽE ˜^ ý8Í“BG½« ×Å:T ÒËGg¡PŽˆ¢îXÑåæ¹£‘ߥaR'y^g·î­µ{Þ«Õ)€é¨ß?Òí5÷˹9Î׺/lS ,qMC?)4¬ƒöCåí†Ø­T,ŒÑA­ã[ìöm¢§Dóno-ô¡LmÒ­î0bKr\‡âÂ5ÑtÇ!Ç'=Æq”×¹É~~–ªœSç!š((¨„«^AÄØ­]ïÞÖFZe†â3ØŽ¦õdˆé½ñôôú!ÏK Kµ¬[Å)x °U~„*˜Óz¨â¢P(Wúîô Úà^7a<€\„è”UM¤ãð3`Ú¾§7£(&£®ŸpGNT¨)Á+ÝMåÕ¡S&ô›«G÷Gœ‡Ÿ9BdY'ItO°$êèuદG( £'§ÛíÆE…L‹ûXçÚ„ßTï•Uϸ "f•ݳ:7ÉïÛo&Õˆ¢ ¹mªûÆš€}¥˜D¨¨ç(ï|µ$Üî&•ÞB¶P åƒ@q?†ÙÛ” 빤Yhûõ/!ˆÌû6{*’’e£Ÿ/k§>ïˆ÷]•*…«V«º,®TþdŸ)¦}·™{§×õ£f¨º!aÕù½aÈbÞrˆ oR~_-@Û²´SzÏŽœW]™!¹\Àæ)ñ¥²ùaë_3ÊjiŠ£-tÌØ]r'=ÀüÈÌÂp±Ïæl“Dõñ,ô=é+ë¤ÑÊ|èÙ}?–Á§ôÇ“êçcî„i]NZJºZoÑÜ7t‚×õŒë¼@¸Ú? •qÞŠ¸saÑG:|ÅÐàeÞ5¦{¸QV”îè O?f›úëϽD·­nÛègàµÃà¡Àa¸*ð~Iþ•@ΩGÝï—Dw{›aÌXêTó>Fa¤ËQ!ÊÙÂê‹[ÍÚÙYgRm3m#€5‹ë>‹jú…#átðU÷=¢LCë›v?â{XÏëoñ¦Ñ\ª¨¸ àý áL©®s­4‡ŒXéE{XØDn“ÞR oL>î}Ë×ñüu¶^PÏ`Em&•elÂßÎHôÐŒâ—Ü*Ï­238Õ“IýEW½že”‡ñÙ”g,ªŸ G¡±ž,˲"¨ Dr ÈHm¡©[³ve›}ÄytWyUúö†à¾}E³‚&Yá¹²táê)E£ÂAƒ2‡ \£Ç‘5½N~,ÙU‘>S¢¬ïvö¤ÖS¹ýÚ·>ëfæB ØÙ´É‹(RÔq̦U¢ÿ˜uR^Û²}ïãúmÂBÏc}\ÒŸ6¦ä>l‹!?[5…|†l³2ÆKZ×§íÞtµÿß×üì­¿;êÛ¥En:ð«_Æ;?"ÑÑO ±­ã¦JÃÜ­§iÕú.&$È þšP.íÐ>ú#™¼Ê¯cf/8½nÑ==jg‰:*Ò³" …‹Þv”¤xÛí~?Þ“qý¥ðkd'!k[a [Ö™#õº ÏÛ×ùü†©›¯uut_’jüò «mJÏgûÕ]iÄ~Ýå4R¸jõ'^xÂ)-êF¦Ýn‚hi"ÔzîÛsƒ»µÿQ§IíMŽ7?º¦ý1+€ë7Ê‘fjÄÌZI× H”u\O•1[²×ù‰Š$§þ GŠÚÝ›,yÚ«/ž÷<º¼9¾æ¢]I"Ílõ§ø)Gö˜™ü#u]¶.ñþ½Yð¾æŸPUOuÌv© TS¶˜°KPš*ŠX‡¶uúÐÝ ¼¥è†8¨ŠòµÉò›’wLßÊJ“Ü#ñY¤ªp\Åx„£Ö8·Í¨Ð7Ôˆ»YsÕe[ºiMë ü2F¦½)3Ÿª¨oâ²ï¹ÛYV¹"ª}…P•m<>~o"ù†ÿº¾¯9šæLïL[/!»ãTÙÞö"Íã„ÖŽmé þVhÏW«ñšÛØ~µò㱎Ï­Þs£²dÆ^óX1ÞcwåñõZºnÞ×Ñl úåxþúàIÊvÑ £8 Úí¸¤¯Íä¡>…ö,¶VÆUáWÒ鮚Ìàamþš®'ýpßûä—£ïâèÓ &UÂVeT'ßÏ4­FÉ!Œçé=ÂÉ«¶i4Z³£1Ò2iuͧOÞ£‚G‘DÅíuü¢KU~nŒH3ëšIbzµÊ’÷ºh t~1­eD€“\Z°í÷£ÍSÅsE±x¶ Óó5ë“Âëc»ïÄ(Ée³µÊ:“ˆ:#T_q¦ƒÎ©™û ¨¾O:þf°IwNÕÐÔM.º„ÅØÃUasÂ$Žú¡¹ ¦öÉÛ: Ëë’ש¿ÔI\§®yœ°MbÒ1 K*qr°Šî®×rYô1Òª}!äÒ–Ý^ÄÙ¿„Ñ3Û'íï)®¸Ipõ.ÿ¬½^Ô8 ­t¥‹v»ó° ‡íêT³5žUSDt[A´ÍsÓ÷ýòK07ÓUµ"ycl‹Fß«ñÕ â(STM4ú¿67~ýý55ë÷s¨Ç×ë¼æ¦ófÿÓ“Æ}ò<¼¢ÿá&ÐoÐü›Û̓W;íªšá½±$(õ6cTâÏpÞpÔÒç¶æø6acÃ9bÛ»h-ñ£§¥ƒÎ¹JU™|Óz¡ñK•ýºæôÃŽåa"Ç]K›[-&ÿožÐÌ¥²Ä[of¹wÈÓß·«¾¾üHÍ*ûçy‘P¨ÙÙøïTÌöf(ìÙ–íb•ÍlE}Mµ'n¸È¬/[VÁ=um„~Tëv1 -!hìŠËò” ÐRÕy©W4E”ÕÇÉÖBrŸŸù0µ>•Óö[–.UðDq0 êåÔU°qIÖŠŸTxaK]sïæ™Õ.&®˜Ôº`‘‹£‚ÙŽ`ã}žÙÆIÐW®ln¬¤;oCݘ: ¿Ê ®ybc^%fDŸ RzW ´å€WÞÉDØ„†\x¤Ì†6Ôqȼ$26ñMçÜÑ(;~°² “¶ ‚bYð‘ ÓàDËïÚüZ‰Àé~-íøý÷Ñ.#›¹Õ9”þ©™Y¦·(bnF¶¤6]tD¾®¹ÉžŒëÞõúÖE€Yh·°~ÚšØcÉéZ£ÕÓs¦Ýˆ1P½lQF‘Õ[U­Ú4Q¨\œEÂS5õ™_àŸÚ5ãÔ4} ô5Þ/%šxLŸ³X¡W‡¡ ‹ƒ*x&^éºæó9O¶±™n‘KB¤øó§¨M4Øí¿žc·þõ÷ÞO_Êé¿7ØNU¨óš¯ï¥SSÛ_ÏÆõq꺿.[B*…*Á›SDÊÜw‘„@°TºzÛ½ü>l€„¹]š ä0g~]•žøÇ“¤( •©t§×‹Í¸œ<‰ß×|°k~±ï/ܽ]r&<::0Ïd“}GF”å±Èrø˜@âŸü¶µ¬…AÔˆ \žT½•¿µÃ½ëëW×JᅫI˜s}¢‡‡~JãX¹ÔõQµU)|#VÌ5¿7‹y{ÙØÝ¤l5—Q›%žœû‘ÇMéJv¥r]’–Ì›4ø×g³ëé†0A©p]&€…÷«Âl° U ýúû¨qiï@ :sY>­N•ÃKS—ïÊÏr‚%J:èv & ÇËó¦”v袬*ÆÕ¬ßÃÚP5¸¶Yõ¸è¦WïknMg»æÊæƒw\ÓÇ= §(ƒ®WáiR ¬w!‡Ú c´H °†€*ŸFN UËç£íž½”©׿צÎÕ‡Éܾ nÁèw#²ÒÖ ‡ƒ”ÅÅA¼ÏÊ0Pýš´eg3û+Ÿ—™‡íˆÿé'ý5O™^_ˆnrmTH36áìU§!pÚ t[?ú[˜EQfÛ-Uf¦B¨Q¨h+T‡lÒä(¼ëZT}_V®#žÑn¬[ªðéÁ#² fa9A>T~áð{äÚOƈékƒ£+AÔ´jïðpimؼW•3VÃë{ëÇןGßïÚ0اl?’Ú¯5“z=Þö(^`y¿Zþ-R)$rhÄÞU½WÐËs¼•®ÝöXU‡Çx<–iJ†œ)¬=¶Ë´ðJ¾ªmšôž÷eÿõÒë¼–Ê/öØuÍMYT÷âGù8¯?pø¬15±8nOTл5sƒìi’þ¬&ˆàÓåR²¾gk¾Å8™ºX[s­×ce(IÈý¶«²ûöäf‘iaqÈt`ÆüœU€ÀwÍã `Í|¥5N~Ye@ÌîpYšQJDEÖBË¥I£y'ÙÌoŠÔqxË–×ë—ß.°cí莡÷ÝRóßzÁð?ùX0¢È€× Û#…©¬®*èZ3,loôfl–LRßTî6I—*Eg§Š¬G\p:(¸ˆ±æ´ Ò¼¾@;>‘Mñ£B`)Ï3k'ôÝ- ¤uP51•®J„RéLµCãfÌ1s- Ò´×£¸aÜMƒ²ùë}¤×?ÖêOÆ[Ö¯'\Œ§ƒxñ€IDATçkí8-B_„„‡0$LËÖ¤œ˜0#ñ¢2£‚º¤¯þãš—&Á%u¥À~ãߪ”J¿jIï®aÛ©4³Üe¤Àh­9¢$Pa@gÌ¿í½2gLS[€E“8¶”™P˜ëKÖ ù¢¸g•Ý`2ð)j:eÜÆ© ÁÜØët>ý‚étµà~}y 0†‰ðÜPû8m›ê×9BªGœ*u˜Ÿú~}í^p\M ì vÓ7 Qл¹Ùìçß_F`›µãée°|KSËA°¹Am£¶½Qá?u ÏQÒé~Ì£’ë´¿Çzz%_IjùÏŠ±ãô@(eîôU&ìÁ˾Q Ÿ)Ú6ÇÖº¯”Ö»2¸@{["8®¨ùy¯‹ ®n´ŠÂÌa¶^%Ob"•KÖöU·-e§ËuU³ý×Ïì˜y¥ —1 V%+¾nDO­Éw‚\õ@7 dÇŠf°…b¹ÞDHánå»~>8mÊ~÷äXÆk ö4Õ%Üe¼É”®¼K(ø€SÖ È Ý´=ƳèeÆ!õa‘ÙØ%E4?jˆÁ²b¾>¾¿h==p#0…Xo­hÿsŸûÙÙ:Eœ¶7aÔ6П¤É%B|ùg<Ì>“þà__¿ö:kxæŠm‘@$×;‰Gþ?|££5º/a7^jxz_{S™úk>ûM5ßzÃHÙ/d¾[hLbz&“®É“e×*¤@ŠDîÑ/šÇÙ ¿6⯦½ªÛó·}ÂdÄ AÂïçÇsqÞ7}ZÇÎa¾ŒõèÜÙZ“‰>E.šû‹ôeÞiÆÞ\¸—¹nÉ3I«ÚÜôšÎ=Ü2ŠU^ îË3e…@t«[ÔX‹$‡†¦’é†qó§Û!PÜãÔHܪ–>o¡ŠÄvŸÝ²#Gm—‰k<~mÑîº g[åU5 ñ…H[²vŸÍä†çsHûF5{=v\÷±OS½<ˆ1×@­Òãž8Üoñ”3õôØ"+?O•ËŒOÝŽU®/4¬Ã„†e]FpÖZW%,®õMÄ·bêÙexþ÷ÿ|y5B£FÍÏ}ÑQü>i§ÀðvTοÃY¾¯¶‡§€:;¼ ûÕ$0„2³<ÑeV2í]é…•1:SòÕQD"J… å²2%¾Bw–Dus¡UýxB1k£ª­è?~æ¦ t —vå=uy ½PÕ—©qøÙlN˜×ÇEvŽ UL'£èñv¶ õýX lB‰´Óg+P¶Ã‹* šâåLê±ô†äõÂÙkë†F_¸ gú”híuÅô:°y(CÍûâ5ãý¢c4/¾“~­¡^ü0ïÈ‚î÷lÚ,&Ó“›Zœ¢\&”X¹¡ìS¸ïõTÛ«0Mãó².£ßiM7¯Åï/sÅ$l:eè<KwÑ-)òþûì¼=.ÚÓö`&^ë´ì—»ÌbáMÏ`³ÖœÎF4U†B·@Ø”èéžõ4?N7”a=ÙovɆ›­ÿ–kL,{;7M0XZ7Øé›ÒÙæ¡»:†ª‡ÍŸ¼+‚ÄZ(üÜ QÑ5.ŒJZÈè–'å¤Â¹«l`gƒ!òXœتfÂtRDýu¹²Zƒå®]•rµÉ¨Óô¥ÛcpÉJ»Û4æÇÜ;BªÃÍôyÓ0ª`lº‡‚IR •€î?ËFºghÜæm¥Ã—D•ÃÁ©˜Z=:g¾ž¬_©&—ü ÝuÂô]0|Žýú‡«òÝ`b;Üu<3ú7x"ÔiÒ™ªJ!}ÍQ!RáŸMØï„s}ðÄúI»ŽŠ~™@óîU§§y:6ä•{˜—ý©æ==ÙKþúá·I®±¨à,LæÎ5Gé‡McÛʯ¨V[ öU ‹õ¥ÈC:Ê-ÁÍ4(ü5w*:ªUÙÜåîóyq<Õ ÖeaÎÚ A¶4;éLHgÆ,4ÍM…qï)‹2f­ƒ6+R¡øÎd<¯knnàÇëûËÒùëå5…á×¶ˆo:0Ÿ^Œª/äuÒ±€?/æ]«D´Ù(öõçÓáöz3LNŸÄs¯s÷Kië|2`…f•VÜ€üžÕu§“ k^ãqYflÑÎ…b Û¨Í^ßùÁ¾ôj@ð£¡Ä´0™ZΡìZΊ!ß' ïøºæ¾{ÿv®à~JÄøÖ,_Ò ç¤ëšôî&»pRíúC.[Ö·¥ÕfÀyµðÇx;}pNáÓ:õãPäQ¬¾9MÈÌÕsì”»osNhËÊ)ìoèq„whÝV¶@|ì`YTHQêŽÞŠ­gO tŠþ ¿4OBn¿µøŒÜ´êd‘ËMoŠõð8 nA‚R„‚:-¤6©†B•åSp#eMªñÒÛ:Ý*F6 ÙÌR3k„Ã^°SÑxg]F¸ÚÕágd¾g ®›_’]sæ•Þ6ryªÐWŒ í§¡žÇÕ="õ€§ L‘¶¦ÏʨpˆÌ›:ëZÜn¥ï2ÿ÷®*aØÙ£¡ÅjÖùm’ù}L®W–¦ýëû¹ ‚«Íœ˜<ÍÀˆ_³oWaô…w:M1Œ\Ñ–ù8X4 ž|r¿§øQñṕ³?jšþšã±ÐÔs=¸.m>>õçsS{W€ˆ f ·Á Ý”…Q§ëáÕ(ï¨ôTÅ-+ôü¸ñtÚm£“v¯ŸÊ\×ܯš«õrµ&ü<É,”t¦.Y³õfËÖírt6”]kM·…k¾ëš¿ž«ïæX0Üþ!/a‰Ø(eú½—Îù¤H<9gdA(çZö‡»VUwW(7ë-çxX Ü¥µYÚû»tÌz‘¼Z=e~]^#ËÉÎ^ËŒ-S†¸?ÞÖÿ ßþ›q¯êL$§ëš?l|÷†  Ž436L¥"³ñ]™÷BŸ 4S$Xüsôds¯÷Ž-„Ò÷/¯~ ±zWrTÕ1ñÄCƒ;—HÓáÕœâÔ•åµ;jf”[u™Ò2ŒŸ‚©ÓêÇ÷úbÊðÜZ%8æN©$®Ì6ÉcEŠÇ4œš:àcª‘í¯Xá3§»;^Bu#RÆYz0ÚªÝç= öÕœì¥Õ“æW®’‘eÊ´Zé ѪOúÒ? ²6Hè- ÙHª0ëü¦?‡ KÎÆs’15µk¥BÿÃÜ{?3S"c 4c1GøCe³¢›pZOæÖ¢©¦lß8rê¬ÔPá/@bn.k_7ÄŒãÜúÙzÚâÔµƒkrsš,ý&õcË 'á²?·õu`•b“8m5 ‡0of ñH`; ¡™˜þšë*¢6U™°ai¾i–λ¢®2I”ÿñÉâ ’0¨öGðº#a¶«jzÐa®+_ÃNQ=Cš¾cvzO1؃նš'c^×|1 _/ÌkÊÝ» ˜›Í²x‘ný°­ñ(R&sÖ<~ z2ë€Ú¸^jJû××6 #ø ‰ãíxü<÷Ô¬µó¼½ ³=Etð F†3+Hž¸¢æ*Rö~„;éúeõÙ—ÛçlôÖåP±—­¬¯~èõlû‘>F=˜Ôäûå¿•×ÿóšï–Ç×ùªÕQ«ØÌuÅL8GGµa€Ú®õ³ÌG^h#Ó{tŽØRduÿÀìNº.ó?.ºw£õCã45¤lô¯Ódþ8­«ÖuüÂ]:3¬%´p"A…ÙœÀU¡QŒS‰kÅé©2… aÇZ¹UùùÄÈö¤±)O6g—*¼%ž éß7Ù|oÍÄ4æÍîK·1ºßƒ[Ö´Ã:wºjuÛתTŸ¶còêIáuŠd)XMÊ[ð¼Hƒ(ûtC 1wúš*ç“kyd΋"¸²y–„I;tƒyÅACƻȺZñª*{ út+T)ô.í\¦o“xj\Ά\3 lEºæÇןÿmºÌžµ{ùý‡ UΈíksxÀ`^c­*«Õ30}yücn¸éåO¶… LÊÒ#«ˆþ„?. ½PÈ*¢´{_sžÙeï`˜5ž¾ÔŽC;TÛÝ¢ÿý‘ÆyB1 f ³ªëºã¯’²šòd«ìáÏÅšq\¨LWø¨Óç[ž>}:}׿¯¯_"a‡XBì˜û鯹÷œ^׺kÊ2é¨ûê\ˆU¢‚x€yô4{v×å… Á±ì'ÕæSï¾7•Ëæo_úYx«FK;§ŽUúÒVð²Rçÿ¼æþ¦{Ùãõ8ÁŒùW¬“ó©~2…ýò:XäFtJêᬩQ©«<¾abSゃPuxš'¢ís ¥ÿ7ÎX¯ÞIë?¢n[{÷fûQ9Ì]v£Ø-ïDÆýœ=Õ‡ÂmiH¹‘]ì¢ëÂÇ÷Û=Ò™+F–HTdí8¶G?5†Ô•ÜèÂÁ°ÈhY2 `g7¦½å¡AÍÂ*ýû²ì´Ð"•Í\sý€µ¨ ¨~¡Ë…¸§kÓ¥YÝ÷m¯'âÚilÛD¯þ^Ö€—®oÓ;‹Ýe°«Å&À6Ÿ"SWm¥Ä´Sõf sŽ^É1÷¿žªÀ×Çë0Ä~‚4 >(»¤¯½`Vç&ëZÁ5éKÄ$üÃQ©:é ÚIÓySZ ¬³ ñN¿º”­«ŽAõÐÿþLâ<²lÍÚZ¦ G0õ¼‹ÄŒêñz1ƒ½LP+¯ó`ê*‡Us êÉÖqVŸÌ_ó¯ÓGìÍbñܯí Úd¼8Ϊ³®4+E–Êz-×ÇÜž£Q¬‡ Žúqøá™ÛÞ£ì´K”Úú‹¥ÐiTÔ(ÚÒÖôz3‚C+¾Jж~.]~¿Å-Ìó½7Ï+D‘gmš M¢:­ir3Nû¤Z‡‘e³ãX.·… ´ÿ_-¸ ÷¬å]³Ïžt*'$±Ž ý%›Ô ^— YŒXqU%QÞÚ'ßË7i[ïêpj+›{^ç|¹¶]íôÌ^›h6KÄsáÈL| !â0ííÀQõmÃTå­2JjåoÙž =,ÙÚNùèŠÎxâJ÷l€°^ ý± îê (oÝfæcÒŽ†·…ÎHÙ#3ϘidéÛí†MTkYôy±MõÒlýÜâ:`udM[„Ÿïb}óªÍ>ÛÍ¢{N7ž¡WQÏ“*Ð(ö~î?@{‘ %{l&F0ÊgzéäÝàin[…ü¦ì»$Â2±¢—Þ‘ROƒ{ú¡PA%äY‰ëÇ_[ |²U{‰ýøw³íôøþÚúF ÉMÞ Ò7©w"Ãv!²Ù¼ÆkÊO%ÒÒ1Wö˜ ôeäŠÞÿ»lªš×~jãæä¹QãÙÿ„ÿ Ò¤ŠƒÔF:ŠbØàÅ‘ig:/mtVz/—*&»‡Q/;µN¨¿æ¿uœ÷'}¥É;/ïÚ|1Gže=Ñ‹‘œ ÎZpßF+…ö}tzÀ]¦è“³¡×µ%«¢ v>“)ìÂLd®¦Êv~û`û[~¼1êj‹§q®/ÍU°×v‚0x@åhdè*Eõ8ÌÄA Àœu,‚Ì^ÏõxÖèíU¢:YõZœ›îe]õeà^C;xäËlájÁ-ÿùëÄØï_~€Ãu`l•G«ZMîZ`Sé,ƒk•ÖŒÔÞiÓ©WÐ)_Î;ì&yònÁ ÓÙÃ>å§¼ó LÚ唥³Ü>{óA^aöá—ÚÄŒhò '›±"¤êR·)Æm›“_`¿“„tcE•ЭTÁÒ´JÈ&‹1q¯œ> 6öðäŠâ~ï6“S_¶KB²oÌ’{bZñ4”D ×§q…q=5I]Tºæ[³t³n]êù¿&¿NXRE—iÓÁ'G„‹h‹‘ ¢#­æ)½Ãy¨hÖ¹ÿhÁÅ·›Òúe`äQ3/`mVU:ªï„×§¶Y&]¤kN@kæ5.øL²õõüó5 §[Åoþåë¯ÇóÛK€ Ât0H6ßcš}d™Ž×Ãëêµï„Õü:ëïw…çÚÏNuÄe¨¸ãÊ}ùÇ]ÿÌVË’÷@MW&.ëk­¯kÞB°O÷¿£èC7·InU©.ª…PƒYмTÆS°<³kfr4B’eZ(¹á؆a?†YHú±¸~3™c3²¼®¹Qzé§[óèùewè2ç@íÐÁ¥È^¶—*±Õœu}ø”½fš›íŽqS8Ñ+Žc^OIÃÓÖÀ4hz‚Ë`e¥¬É- }Ø¡Q G!ÑÂ6¬²HÕ°®ù0({¨´,³õ…-fYøˆÂohë¬dqwˆ¢nª@1ùÿt¶âªJáT7z·Ú¯k÷»6W ¯Ÿw]O2./pµû9õÎ u‘*áÚZphqê'ï1©Œë‹Ýê=ÌÆ€]€²ãT¦i4,¿Y•æÙ³Ù\Ý*ú\ˆnõŸîõËÜg/ÏÌ‚Ù[è9¹´èݰzí DOÊ(Htl>n°ÚrAÌaï˜$A_YNÅ®0ŽÓ觺˜Êj#tºjªX·É4öžØ€e³°zÉÙQ‡(»§c©€~p¤ ç#¾§Ýü3Ò%kú½žZ®9>p˜H˜¬¡þ·â/Zù©¹¬DI­Ð~&ògXwVè‚ÇŸÒ%ÆûZø=ˆ~=÷f™§>C™“*s%…þ1,鏯«ëë·¬¯ã¸ˆûN5n#ïø±¯M)²³ü×Ã0üSY­qßÏŵãó¿'¿ç;­õ†žØÐÓ9^¯ÝëÞÎL,0+Ï1È”ï¸}x¥#xBzfaÀºiÝ&ª«¿ÍhA~¥ïæ \Èñ%oÖÿº} ™~`dÌâž“Ödí‹°ëеâX@·K¨†"˜3´Š"¥YsÇ<34ô.kõ\ƒ›Ó?s;ÎÑö¥ßým,8ó޳.Ú9;èS ,¶fIJ\–¹^¯'©z…úî±6ºëóëñøÚ&TÝ÷ç·g¾ ˜Fƒ‰ˆ=½J6ß@qG%S;LJÇ)ûÊÖ®.¥7Òn)¸Õtã«o°ˆÒéüeÖÇ’Á™®Ûg©¶wUÄQ±›&Âôaõ¸9_Ò³†—óv:5¥Yæ£ü|D#êTf%óþÞœãÌÏÊaUÞ>r×åªþÂrmCú™q>ä8œɲ+éªðu"ˆÔŸ…CÓÓá³YÛùGG†Ñ:éô}æõŸñÔô V«[[`°ÎÃx±Ý^ +н’ËþØïY…™Ñfš$àµßiòÖ©Øiþh.„räP†yôYúižžÈƒíáõ±?7r©G”FqG‰°{cåÓʶ†Qõ‰¤œÒè]Eb1:‚KB¬•WGý¹¥[„˜ã̺uH<9¼­ô!yÝ”TWŽ.q„ÔÈ‚³Š­CPáCø:¼ãw.¬Û4BmP¾÷@—´qVÁôмÌ; ¡°‡™E(—v‚òk·æãš6XäÁVQ=Ðvèó÷ÈUxVë:” ŸãN5=Ó†[M›cÅGЀ­7jî©åÇ~Þªu7úÆx±ë4\-”Ù6‡ª*¹Ç°Ì½„-0š@»ÂX«ÌÌ+ðŠ$L¿“P‰’ÒÎzÚõ[YOÏì|à/”}š*]:Õò EÖæ©â–¢dq©R8´qm€¶„3nû‰8¬wC~õœsÛð6ôË9ÈY͢뢬xUÓt¿72Áåó¦ÞÜœâÑ›¡®0;³¬dîó±`Ìîðg&FÇvjÈ=ÏŽ>ߪ­:„> ºkO{c昙«wá¸Úê* £°¹jëÉdûÆÚ6u ŠV(±«¹ô¬@V0$,ßNÙ(û1¶«5°½…œð€Ù̯Åû˜Xg±xoG0ÛtÍ3óÉQÑ5Q _ýmH`dÁhBQYÏÈ Mm]à(C%Ǻ2+‹ã¼}3ݦd“wõ!£¦;¶Õh[—So>6‡ïôóˆ+)½oÏ¥z«QÀ”†ÁLŽ>κM'hÅæÒÓ1wqLC7Rbá~kýÊ´¢Ý¬/§enÙÆQö‰ôeÇÓ×}½6ù¶H•Àý`³¾ò5R)[x òý ¸t:<52F«å¢Qï“uü×[\ÖB³q£[§Í®ø}K›¸(?î ѦÀ=Ðovü¨‚[„W´n ùš/=½;~Ú³YÈU!ºÌõZKiZ’(òó¯dkº*Џt¯ME6[ç«÷@nõo\wõá1ëòëa+Â_Ë{S‘ëOëÝÆÆ›7¢´þ¯é$ ~¬Ö¥÷áöÜÆg9>ö°bôúÓ,Ë&ÎÓF˜3ïXÓë!”L¦ŠõѼ¶¼^ç{ü`rcZTlbmªGÑÕPDî3Ho¡ÊÚL 6foÓÈeF¹[MÓxñäNk£zr¿Jåý3½ö­G‹xoéÃÅŸÿñòŸöAOÿl ›PÄsaÍ‚DhI¯³-ƺìmý‚YõÂÖÖ#Žý⇟ºïZU M!”Ó· ¶œY”3’¢Gh„úsߥ´Áö¡NĆ|? šâàÆj:=sªÐc;õÏ/¶‹…w¾VKîëtzè±·œÓmk…i<¡ ‹…E ‹æðcš:Ó“mô˜“Ï@Ÿq;Žj|M‹ÐdÙlsï[‡Ëít 0y™Še;…pÇcªój<¾'OauÞÄx=+n!˜L·P€½Nâ´M <).ê´Æ7fò„æz¡äîº:M]óÓ1Aذˆ|FéCŽž‚½r|c• ó"KŠ…MÛ>7æAeB ®û¦0( «.¼mbþE×nëêœggŸÇ”:›CP8¨”"–ÖÉ=û€ º)ûg(d)ÓåŸqW]×ÜÖX«éý®LÕ«ÔG™·©C)[¯—µ‚¼ÐAUW«ý d@þ$k¨Y,ìœ2¯G¬;žûØþÞL;,‹×Ä}=¶³K„iÎÔŸ‹[{oÀzµóþõç÷†y–µâàKŒ†ó;Šì+þUz;qšÕ0ÆT˜"ÌbZ’ª˜ýê|ú}¢º™õù݈VT6ÎíýLo“;lCº¨D`ö,T]‘*[`×ÖqÞëK¶c«SòÖà±é¿É™Ú2Õ9˜ÁÁÙñ¶“ÀuÒ;ÖõT0øm(Ì AWförïEÒ¹8é»ÏªcvË6X„ø«êó-ÜO•æÇëyjÑœ›ÃgÃÊz§¹`"âH½açJFª¼ó/ý7§Â»…È\dÍ;<˜6x[ ‰6´r¦œàX™×¼ ’tZf\ÜÌévövçžœì½;¼oßêÓqi9õëÌlg¯âÀpÎP—é-5õPá ¡T­××µ…SÄ5Ü<3TŽ¥SúD ±²Ü{‰¥aÚ ií‹w=ùeõú¬óàŠvÂܽõw3\pn¹\_h°£ƒµ9KÈ0dÔw<•Œåz³Œ5€S¢ÕDíü3ë«Û=5zYt êS¯õìò+ÐÅÊ{P°k)h?Û†šM[ý/§÷\§IÛ©ê‹´ŠÁ¡U“›c—Ù÷¦!®ºíx ˰˜FŽÒ¾°(6¹‰­7¬S•\sU3Í¤Š¹ßþtÊu5½ÄX·òíÖTmŽZXÐna[Î]+€:\ÓT¬Me;Ôºƒs³ªÚ°`œ!×â Kjô’¤ÝþzAwz}_àè¼äó)9öן¯ïƒmUŒ¶|']`Ýo9¬‘ìû·Â¥Mz®±Ê?̲€ %øQ©äQ˜AL‡"ÊðœÎ˜&’êi2Ëi+‚ûxeËÚ˜5Aé;ÄÈ¡j6BïA˜Ü}ˆ®MH\µÏGü Úì\ÉÙ¨³éô':›ukvf¾á6¼õ{ê°çÀÛ›®Ã¼ÏŒKÌEõƒÍñ+Ce8[ºüEíWѰЬp…€ÂñÇGNªò‹¶×5WÅÔWB>¡Q¥'TcQ×Ïÿúm©—mQõméd±ŠÕ–Íi'’¤ª¥ÒøV÷{?+ZX–±žÜ^ø|ia*ûÔàÌv%8åh”ª§ã—Š âZv´ßס÷2ÿfgø™ÁN…χ}¬R³ ëªT/¤îÇ­Tá¬ÛèsI@g®ëmÿ“˜ê¾0î”ÆŽ¯_¯uXý^ðz‰†œZÃÛ©Û~¯_¾¶é²–™fŸí[Q1u|¬cFCút’= ÊÅa™ t':Í8J¥…ƒH¨"‰ ÝÞf@nÕŒÄKncµÖÿÍeúŒïÝÏÏ(`åÅLß±¿+1Aa¡m½èVň³ x^ ˆUU$°p»é)wÛ™šÖÙ{Í-çi3ƒç·ùåx´žU¸¤ìñz\z^3mÙ'•‹ (ƽMuø›LŸÄµª'âjt)ƒ†ºF+Œ³™x©—¥1B;'Û/P¥ctYBÛ5¯óYQý²´Ð&õ/»²e£â-÷¡Riuªôj”›é Ș^ä_´Ö‹a¿Ë‹R™ø¸Ý³ÌP ð ÝÆýž^Vã³?ç'Í;î^å‹R5 iPÐB¡L«©$þÞÞBé&£…†I 4(<ìYjб¯ñÿ%ÖXˆÛìÆHDëxªÊYž‡étT?çí—X­ ‡£A)l˜?¯â?ÂÁ.¶Eš ´/Cg+._(ÈŸ­Ù“Ä3®ß«€B!0PFI»VzϪÕ+ËϬGèš'áGVÍlSx¾?Ô¦ç]BóNr¬:1Òv dX”ÍûZÙ2ùd9 XS_ ]?£þÔìâ{ºÚ]mŽ•ÑŒË®Ìt™ ]ß|k†v[ÀFßs½ &Ë0îyŠÁU£çÈÚÆr1}“†M%ýÔ•M7mïŽü¹Š´{k¾Z±ç=P¡+_à²Y:=}Š0½%MrKM¸š@Ýò4,#Ú¦@ ÐB‰j·JÐ}ÝŽy<ÅŸåÇç= ƒŒ°˜ä¦s¯GŒ3°°¤'#ПðØÐ#Ò©¯“ÊB­Àbˆ¿dTLÑYsœ®³4œ8þÜ×XÇsœx]#/ûxî]{†Ë¥hä÷צ²ÖÌÔóXa‹U£†›ŽH@£º0g/½ör±‡mx¬µ]Âjf%Mï­±Z…¥¥ ŸÞ'Ð*ÆÜ°ƒ©XešN3oãö.†Ü°kk–çæŒª7‘Ï ëw½?š_/âÃn^Õâä \-8;îÞwwo-¨}û-Á#Ca0ª¨4‘„¶„" ²"uÄÙý³¨ÍO¹3ù5òQi®âÅ)æ ÓKv¢Aè6&»± !²ûÁÌ€›ê1ýtš¢ü¬ð’vÜ0G×4+íÛløà4×—ïVœ•|M+Ü"ÁTÆ÷¬Ž£>.‚[·#ygzËËÕ‚Û“'+ЈIÂ|;­hÞ"Yû1”6 ³ ±j·"nkÌV‚3åN‘Lº'Y[è–Ìx5‘Ïi?êš¶>n UXöðP¥Üü–`RÓw”·a@S3V˜¾®9ëYºæÊ^¡>Ÿß)z¼¾&Ô“Q/mÒ¸›ûnœŽtkç£U…Þ!º,4»a­0™m?Quã>_¤ËòæÕŸËÖOfÀny~?Ø6ÌFº73kÁW=3®®è­]›Lí†Ò‘ê‘¢Ò;x&Ü>ÛÄÇh3#¦!æÁe,GP9d 3”T"36jaê±\ÈTï¤ÔQS•êŸVav‹×¸þù-`öüú¾j#ZýÝ"ŽÃòyºå¼Ž Ñô¸‹Ækba.½) *Û÷ÆQµI¤¿ae-×…pÓ4@436fÌîOEå¦ÕõSºLë•V«~ÚÛ ×Wœ€Û/ЦÈ~ ÿ£ ºâ'M\rƒ²8IìoÝŒíðØÛV¨ËÔš«=„ºÉðXïPÉTðE¼îqò²ð†¶y²5…×éâ±{‰¯Þ¼Ø€Á0ýìlEmrãºMm;?Uc %åI‚Ãë éþaï`™$ î÷ b´°|¤m|+Lë>Mž"Ý‹.Ëú©)»¶¬˜°Ÿa¢ù ÙK!¢mË’‰˜ ( #‡_%Nœ ê0¬ù«@à$ òÿvPÕg¡»*L9]-‹µµ\ÈF=>_ƒäZay½^`ßã2 MAÝ8Íà'Ý0ß0ÆeWÈ¡O²¡ýT¼êjýTC›d‹Žì(Ì©‡rŒ× ¾V(dbÖômΙ5}Rt¦­ïNæ:¼ƒ.»b—NK‹ Bže^z tÐÛ1È®¬0 Æç÷¨ùz˜XÕúžû/žðp JŒFÖåüd§æ2ú“7›mÜ0òñê¤zØ]Pz—"Ìò0sú^iè]4@Reš±@‹ï3êF˜g¬`ÞQm¤›÷É·z¾Þ‹êѳÂFb×Çy|Sã€(ÙMêÖëù(—(3W„÷Í7a×VuR;¨¼ËÞ–„²(ïúá<(Otu\Ö·êóg½¯Ób-Wý§çÌö®ßš[Ü4ØqÅiú1œÁ­}‡Í³Œº3qÀÎ[åz%ò5¢EŒ2Re-Õ£yÒN Ù´œ!c Øé §y¦GX˜±Z/8nâçvÍÑ¢E7ÍKƱSM¶K?Ja†ããèó#³qš7kmó¶ë”<(5j÷…¢l;¾¶Ž½" ½"¾\cË8t¾Ó¼]`tÕoRL×’àI7œì¬XÎ[-ÚÏçÎÒkÇg-X~¼Ö¾Ù~=\³üyBÓÃæ­ìíŽ6w­èŽá@¡pÍ£4¤pލ¨ù4'º®JGxc¨Jqìý÷ìŽÓɘ¥È™1LÖ›AýG¶¯ËQès÷Håe' gÞM+7 b@Ò`n/eŒ—…Ð9X>ë—+Ê~¼Áµ‰abxdÊÝß})æŸZjŠ…ð¥5÷]·×3Ö:\Û!2ùQÒE¢Úmi“jí|pFªJá¬ZóqÌ0ÔÁ"W>âQPì¢Òë:3v†6P(4`S¾Óy)ŒST1ƒ[ê,,ûâÖªLO`Ä{l;+p/¾À…¾Î]ðùR VÀkŒ£°MjvjH~Lõ‹&¢ô~ÏŒŠo¶„cÉ>l”߇y`W#¿|ªTðR’ µ0‹·uì„­0!]šºt×XÇSªã2Â>ô·Üä (»ïjþ…°]!±f9]Ÿ¢N+ÀO])üÑn¦Ý.œÝ|&ˆ¿ÄqŠæÉvõb.÷õhÄ™²fÜ¡øi»GÛ5Ð{sëÃvê*¤ ô  x;‘ªTE—iÄúô8¹’µX°®5£Ö'½ˆ)ì9nR“bPì(™‡'a‰²IÊ…ïß/•‹Ú“ŽóÔÓþ^PÛè™õ”jÄÛ;Ö;†Ê¶:uÀMÒ‡1™Æq-„2íϯkAñ0åWÍ-Ο¹ÄTÎÊ“–¯ð9Ðo‡UÜ[5Þ±²Âªõs(›Uø®õX|[~Q3zâàꡳšS)ýv×5ÿWš|J옢0¼gaX´µbPfé,ï»®‰ÿõ™÷_¬Š•Y$¢îqnFɆ3“”ÓCŠ”JKH…yPUÝz'è`4ñ^™w–¯I#ÕãïŽõö»½Bç”Ù3öÏZÕ¦…XO«ÀÓðï@¨*ýˆ2Ü$ÕÉÀÀJ¥Az£{–—ÓEÐ"”Ð׎å”^GÖ1ðW¨lÊa«²=nÙ9pæqL£bļdŸ»Q=šÚ¼}Ö„"qU (ðëŸg–ÏË^?»cí-J"aûz²¹Þr¬ÝþVîõkÕûYŠ.'-`õ4ÐSê –àDÕÞ²âôpmè«c|¤S«k®ÜšyÃ7!“¦G½¿Õ'RlËùM,±uåGTãMs,¶Û+ܼ Xþí*i߯¹}šúIJ«~4:¬a÷ÒÛ<ûÉB]ýQ¶Ñ½TºêàA–¨ö¢çŸ¶yíj?fKdÌÚ;¤û—FwÆW:ÕÇ9K{¯èŒƒq šªˆoB.ž}7Ø÷T>ë¦ãuôÑÿ®tz]‹d,¯"ªLåÍ.h%¨œÁ´ KõZús‚Îvͯi9}HT¯QœOѤ¹ßR‚Q`ÑÙ»—Ï·è,ýa·!w´lebÕiCxD_}Úm_@¥}^׸q¨R§ï#lØèT³÷>Z˜æ‚³˜eß6ƒk{~}æv Ú3$§G£²ÉX\³¯NGB ¸¸=¾ö^ðiØ•ÒûõkseÙï¿^»•À'Ýfžu: è$aÜÉæÿ¯ úy7¨‚³ò-ÓG‚jí'’zcÙíã!ÙŠ×\‹8ü{KólQAfΗI”ö·{ßÒ“þºÕ•þ¨bb ªÐc®9è©A`³9^—¶Â{¿Ü‹—<“¥æÿDz*w“¼O‰ÁÙ¯6Ñù]=ýÕèå‚,ËH÷«ÈÆZÕu*)hž…M[)÷Í# pÕky¹[ã¹¥9£‹ÚªÔêv­Â[f/;W ×£jW(+è÷OORÌBâ(‡Ñ–¯ì1Á6ÓŸM2çô}õ³+nlËY„xF­§ÃÐ!.–Ÿw÷-í‹åm8¼Ïý…ígWЂþô¢(Xš¦Ç°ŒõáJ¨8Ž?ïа½Ï=ÛG‚Е‚Ž¾Í”j'Y3‡ðò,F ¢:ÑϪš)†^¿ðR„éK£ãœN«÷ÅÈñAKU—Mß³â†É4!+“*6%¶D`:m…Ùñ9¨fc8¯F’ðާ`vg‹”E.ˆ‚_l]Ã%ì‡Áynä‚‘²fW`âPœBL ŠÌk|ò9ô…ZgK”³iÁÚ}:bl½Ò†¡º®3ê$áM¿{œð¢ÓÑÆ4!òböE&ÿX ´Sí”ÃjV o|ÿõµè¾ûþÉ<*,:”½+3yIïBŠMÑ Uô<Ã&=õó£–BÖ¦||ýbñúܞϬ¥Jê믿¾Ÿ¿Uúí*,ßÊOXW7€HÁjZî*ÈMûØ.9Ÿ¨£-› VòŽâÿ÷í~tÏ?CvÞqõ¢ÂÎPÒÔ¥¢]òqË*€b›Qëvú[ËùùºU}_f O?ú>N0£ á¾1Úž-üBd‡öØ:‘휠†"sËN—¾sœÍQFǰêŠ~j`ïC«´¬]›=¤’B€CŒ+"Ï£ò2úp Í•‘ám¶F¿ÜÞÅaÝeAÔeùŒ;˜Ø`ùÉ ¿®ù%ÜüŸ×ü]³Ï¯÷äP ¡ÍKÙZÈ#'GaQš§gÕêrÄŸaa˰µ-y'Myg Ɉpz9(ÿºÖc»“ =>õ¿[7ïí`[lhR%ÂŒkóÄKˆß2¨± üÝXòÎ x(dø‰4-˸i¡ÿä|0š®{æ)„eò)°˜ûÑøñ}ÍÏ}•ÒPš˜º+±Ò Ûá2t]VnȾw¡äâÍ•#•@’F?"¶p¢7«üœé'U €¬\ŸJÆYuÊ;ÑÕÊKS'OïzÉÁ42o¦Îîþ횇&'ù¯‘ ïÆªL:ð¡*q˜_^+`TX¶ç¯çÜòÁ¸ˆè´…I í–L‡-”½YovØÍÎ6•¼Îöi§;?¼Äöõó?XàÖÇ€\Ô>¶ªÍ¦œÿö…[â¶ÛÔÍžbº®±ÀTʲ\QÔ}ÄPgÂ\Y^17øHœ®;ó 8ÈÓÏ{™ý °½Å|>ÊM¸†[˜Æ"Ò¥¬)ŒV1äî¾ùã6þR×´÷ûý+€I@øOjÕhñÍýz^âW''ètwßNú„0åI¾~±QÛ¥ {†ï]P-÷ÚWÙX€5g#nµ úX*™ÝØVX¾4ºz½UlþqÝžT0kܱòCÕªx¯L;ŸMÂ2TÍŽo] x®n£Y¤ÑÀg/¡}®9†0¶“Ú$€u•{¾Æe^¯¿} D_ ý­¥ð ýR ò÷üäÿÏ04HƦ¦òa×Ô¦² O<£4þŒk„J …èžÅUqÏ L·Q‹¡eâp¦K'^œM•þkÕóÑ¿mºÁœ·-î.}c×\)þbã9”Ú+ZûMZG 㜜Ž6ìò<‘FÊf,IÃ_q–¡b bG˱öh¿Š4Æî %\Œ¬È\,؈y¡º—.Ê­”*[]hK¤¼Ð#F¹:#GUœè2q€`Fj´Ž¦¤;dÅÊv:è5CÒ„tºeTm™™¡aãûo´£óšå?Ò,¹ÝòÎ[ÈæB$KëÖ•} Ì'ˆZvîL‘³u®DàRí}ÝrÕÿÕ¼ :`"½ó˾Ël+*zÀ^Ußð©‘ý+pŸµÌÅâ6÷-쉦÷­¯Ú嘻=%u¾?ªŠóâU‚6×N\«ˆ3S‡?ƒK›4þ)€‘ÄARÅ÷¨B!9L’0ˆðe1Fa~^ó¼ô‹* &køŽÇÊ6µ¾„ýO¤+øËìÃ[žÝ"sâ¦wg}…’füz\4˜ó<{]ƒkN¾žN \ùÅÄ’Ö÷ªËu'|ýŽãÉòXƇ ‡Xƒ®°Žéú¾‹‹V×¼Ÿúl?½LT·&Ô—Yœ)øÒ­F¡;–ŸjÂóÿ‰ú*¿³I,¿,¯o–Ù¼ÕPà°/έ2D·ô,3*¥«czVCÀÈqW î·lÄ¿·à.†œ1ŸÎ5CS^­‘÷ «ýBFmb»ŠGzè:ôa,ëŒ ªO {ÙÚ,ýh«PLv' ©p%tßø}æýe1u˜a± f2=SßZ£_?Å5¹™¦÷¦äbaœ•´®Å캵"Åô'+îµ­Š(í&‰ DB†T)cªÌÖ%ºZpgõPXJ[ î2«à'ŒŒëGzNöê—vÿV [þ/šc8óÒŒÜÂØŽ“íàߣ&ÅÏ/ 4›Š ±¿æ¶¿Ã¶ï Ò°‰;s™"Nêu K+Å,GY Δz’˜öb¯d5±çöõ5¡œÀ´L)¥f´¦k.phí[=øŽÍ ;7™¬ôpûÕ íh3>a‡Œ_0shÓ ®C¢}þÚGÄx¿ØXeñ××6ŽÛ×_H¹?_«+—?­ýôÀ{jX_•Ne­®ºAÝ¸Ø X•”Âáíóg4Í‹ô~¦l5azÿäº&y»±LZOƒÝl_b¥]óÞÚÛ8´Ž#˜ßµK“±½Eü™v—fW‚jn­ÇNyXT·Øü&“ö_©*×—‰£{IB/YäU£?T³÷_fï‰¶Žž·®/ï¼»‘½R¤Ù—õ¹N_Ú:ãüx¶ HÔÂÑu¼ áÍö³í Õáì·‚Á圅%lª±²ÞVåÒTµuÒ|"€Ð¶ŠÍ¾lÿ|¦õ{Bدç)—&Ó(Uí†hQ‡C·xé.Ä®¬èÝ--!rÔhþñ|ýç@íšç{ðe1Àðõƒš¨JÂm^<ÊÇ©ÁÑ%bã\é+вø.e‚Ä-å:2Éø˜™—Q; âv¯ïÑ“rh¬—´;wM÷×ôð뀔±}Ͷ1ŽÔ:X6÷4e(BuÆ}ó )u H½`Dz¸ùƒÞá«0±¿DâÏ ºevÀ_TøÚ¹â0zúí¹ÐP¦“nì0Ût8‰_ûkSU:˜>EÝp KÒä÷ºý(:<ÐÕOÔ£o]D÷œõS=±‰Ý|…ïÖhÈf¼JHêúT8öv/¶)LÛÌ3”ùÈ×@£ÑE?’®Î-XPëñÑjúzRAVßÃ0„nX $ªLؾuéT”º>/æ^ñ'R§ªØtm\ì«0&ŒoNW ϲBjC Û8lüæË§~ÌèeÄBCOîkºåõÐÑZ¿ž“‘\CkÞ•íþµuu=1™É²ûÏÏ$>º;>ìq‡éy¬ÿõq*ºU˜¢åÅçg¤p ,Lzg"IɺŽôß ËÖN¿;©ïmŸÆxݪ~LÐó@¹9 š[Õ¥÷¤,ÿÕ—y)¼@qž—Õ•m‡^ðkA„h4ŲsѤ±äNÑ#ÛgŠ¿´Ó¼¦!¤UÏŒ;LŽa›l[•ÐøÈB²•YJ˜m ™½©îìÞD®ŽòܱEÞrÛ¢ìó¤¯>C@©í<¥æþ4†JAÆV`”=wªOtnÚ&KX!e@´Reöý­`ª+Fóî8Æçom¹ Þß2¾Ó:yž’½¿óø»*Ÿ¼É¿0È´Íì=×Ä8\¶±¢Z·=Ö/MÜÑõ¼È|Y5uEG ›Þã–%ï{ætƒBw˜:x¤ÐMÛ`¯ƒöZ”ò§Áy‹¿ã¦@¸y¹”ÖAÔè⢠“ NÍŠ°`ë”±‘ïgÚ'w ‰í|ÔIÑ·©NO~„ݺŽXfúL¤tûú{™¿žÇRÑF슼¢ŸÛ"‹¢À¯«ôç/Â÷÷so…2žk_!µU¡H¬¼;Φ¤«³;„™©¥4x¸ñÌ„%Wd1¢’j„;ËÐ:ÊsyÃxA™‡ÓÖ$hÒ¶q·Ómª¹8üô7&7ÃìŠEAGA‰½5´êâ Ãó»_ 1<©uWá îFÛ0ÛϨ6nv‰OUãítà8ž_ÖlÛ/µ.Wá¶NWÔŒ¶á ¹®mH÷’&€NJ/´ ׫²€«é;Jæwåé?Z¼2Nô²HÔeà4S €ƒ­Û6¸'I Ðœ+$qŸ5–¾ÇbO ùâ™òšþE†EÔȼ —AXUAØþLÓ&èÆî ®Nº“‹×Z%?›ø¾W4=‹XO Z¼ìÿîU ×÷Æ’·C³ÕO”:ùðçÖÏ<>‹Ø,x© ´)o’$dQ-Õ½nS᪠ïHeú¬n²6K‡†5ëÔ˜ûh¤¨ž<øžÑL‰^- ¡ƒ\ÿ_Æ…ÂǸã²Z@>Æáëµ|]M4/ÿ6Ñ9U4Eò÷ÛnÂÒUû^×ü êm‰CȋĬ÷n0Õ»Rh‰x•3§LCºÛº|íT 6ƒ«a}U]”òÍh§¾BX¦_Ç@Kçy¶x·up´7c"cß}JBšæ“S^±.‚Â$ßìEŽ}Ví su+n1\¡Ä¨¾ÂÍ=õm̰6Î;,K„ žª,§$ÕèB :þƒž8zæ'ß›”Âò:c$¡Ç:Bò¶ª¸‰ý4ƲÍ4n[’ÔÝ©ÚKµ[šy‰YP¡fXáñæYýžý[Ðß(L°aÚ°ë˜`9vÞ¶pS^×<,t|³FEñìœâv7JÝo68B÷0ºÇœ£aÓ5?Mí=Êrd)¿¨¨=ÞªÄþòÒrxëû6Íãi·èu†W+ÜV ÄxŠÀ™·öðëeâK{é8ë®éLêušu0КF^ne™†º²á'[üнê̺k*¤Ë¦Çyut÷H¿ ÕûÊeQY1HSÚ˜oföšy’Afâ:*!ÁªT*M?WuðÇϪ ïUxKÒ{Ę2áí;” ¾zí3¿qº¯Óiç½\®g¾3±¦¦âùï^Lé¬å/¡oü{'Õ-Wbìæ8úŽåC½´«J³Rá’VmÜ8äå]\e¹ÐYì¬Ä.:êÝ#~ Û®dc4Jm§º3káý¹škÙë{ûZçï×ò¸V‹NoãÿËváºæ3”FL„~+¼zÍù‹[Æ{w(àÓ ±F:yÜÁ±­Lr³N~Æ´C¨ªqžöÚ 9®búÜI1}±¦ì ]} ‡üË>Ô˜öA<]¾žzkýœÅ…ñ²àoì^ëÀ¦¾paÕèçîŠ$ªPæ$ø®UDó¯ éq³‘=( ÿå·Tq©Ÿ¶¯Ãƒ7³¶#Ìé„výØÚZ£~‚cº^w|¡’X6x zë¥K0¨Ü’ ×'¡¯š'v ¹šTÖ˜/w‚qÖFƪB÷ÜÌê zÌKÓ@P¥™ë!IâÐ×Y2VÂÇÔ×5üÜ¢È(«q ô4âœñ>ëºHD!–Á¥mîgÞNU€]H/\ƒ#YŠAË©Žt¦êù-Ÿ°z-Go9²Í×J˙՗n0µÉÍ™ ô±ì<­“JûQóñì|hDëL ½íÆ<Áøž"¢…¯$âóÌt—ñœ/äú"ÞÄÅPýW˜ÄwR'?ÅhëHe¼™›W6Í€GVçAˆœL“)3 ‰Ìé;N†.™b KöÃìýxgÓ0†ÓÛh_¦÷|íó¾†DóöìB¾³¢øó¹×yùq_쮿E:²½QõÙY·è\gª­K—éÚö¥S}—q}³²Ç¸~rITœ¿Àœµð¦©8ëÆGycbÄŒAi-"—VŸz¼ôëû¯eŸÆcýû1òž÷n»fcÓ9(;«´S~r[ß.,g¸¿~™(šÀjQç^L×\¨sÀ!‘Ž’ù-2²FvEÓ1uBÚ°ô‘I¯,ÚLºgÝm±ß/( ßfûAo}_6eÏùý¹÷sÃÑïœ!uº,AB™îÚí“Ôž£UØÄ˜_)ööIåÕsQGVÇEY#` s*öõ…ÝÊã¹Ãúúûëû{qOãšë‚Ýã~î:ïûfçÖÆ,ëë`ÿu{LEhjÂr1+²Úš‹• ¢ù’œQšþ¨Y&â–cä½’Î2’4 ·Y…> R¨pñ ÜSújü5ͺ‚‘®­3ìÕ˜ ‡q‘ ×™®9"6´©‰wÝúØÆ¸oÁP©žU‡)®A û—ãÎ)à:\×Ü$ùl¸jÜŠ‹å7 þqÍÙpÓ'ÀýNè8$Ž/ä ¯¿«€I*Wšètïž?l€| k¨hZß³ƒ*Lƒ ‚^éüï{|Üâ4Â>™d*åãœs®”hOõ´i`=Æײ@mî!·\×åÔ]ß®}íS&zókvž¡b££·¹Òúo÷ÜVï—çðÓ7Ã_ó"ífA¥¢¢«Ã€}Ô_zÕ¦bnídþ*Ù¶mõÄ;t…F4ZÇmXÌŒqªÙ/™RûŠ´p]óáT¯±ñíØUiÕ þ9µ Û£:{c§^…F3cɘ”}¤ï‘w}Ž0mRÈÅ\ÌØkg¦ßbò=,T®ò½™Ê‚>xÈÈsÂA¹ N©nµU½÷ZÅúïkîýÉè÷DA53ûvˆeß!N¢1¦î@tÓ¸iõAŸC»"ê\š¸: ïñh×ü²¹Y¬}nÅÚÚM~À¯#3¯§”G…hç&ƒÿ»EYñ±8o«ÆòLöŒÚ]×:-Š>0ì‰b•yL(ŸÑ˜Ì2½6œR˜C$±žÑççýóçgŒxå}s»b%u`Õ•f Q˜Vé¹u+J¤€b|ÄÂk5ÿŽf~e*¾e‹¡Ûc÷ÄŸç/dÜúÿífÇZ¶­òüVD50¿?žhg’ùxî¿URÝ=m»…ÆxÁZS10jJ³(Ǒ ù¤Z #ÄÙns㦾LZsao0¿ì:¡yf˜ñkçø+¤˜¨¤uÓ =üõ²8/fÍèm 鮯¿õ¼šòe–t)»^ Ü ¢QÿÐl69ÿËSºq‹,y}’Äu°_*ìïÒ²/?ï5[bæÞ*°žb ¿‡Î1ÝÂõ"çXl´2ðµ:ym.>#D³a¾$Š.ÐîÛÝÃhGn¨Ò›ÊÞ2¨{d¿•ÂxÂ[Õž–¦ôÛé¿t5zEÄý: ÊÙÔ€ÝsͲ]<ƒ~ì7 ×06Ÿ ňîRPŒ³ë¦m¬Ëáùýò }ZŸ¨Y`P8R¾Ô£JNÕæUXÒR­¬DpI…*jóþí‰ã`œWëñ-8¯¤¬mæw2?µĠû¸Œ—€4Ž*¨z·-&Æ•©Šj‡®›†rÀ½—é߆CS5ÍP×sÖë±SW\Yø—-vì¶Ä@oiߪ /qÖê&?žÇëtÁ`6fy1Ÿ’íê´ø;î·iíš_âf¿'¶ÿõõûçZ/ÃK§}FN'/ÀÞ N{]ëªÝ”FØYÖ9{yx“eõÜ’3 ;ÿU&e“¦“ðÊK[úN\£¬z¬®¸H‡®tß–Sltz·à¼(;ùƒÀM²z+]e¯[‡Ç¹ˆ¬n¨Œ!tf^¸6ONSå2¡‹éõº¶æa~î€Óú2½¤ ‹î®Í: ªpƒ´c’<7úž¯_GooUÇÀ¼2T8˜`jg&nVöú8UWDØü$þt&‘UóÔ”•Ò¶´t> ´ak3aWt¨1±ñM7LÀá*Gz¿<»«‡¿XUühÒøöGÒUËàTÉEiý© ’Þ*æå¡ºèZÈU,êÚ*¹WöC÷Eª‚DÙ¸÷ gyÂȆ2ˆ+“€Q<¤ë†¬ÉÞÀn¢Œ«]U»•8òÕ-¤ÙT„Jê¶ÝzÔÎk®R\Uí°íÊ€Ñg YS†ÿÊL¾5©;¶BŠ1 ¶‡ÒB/­(nAüQ­iù{+“{B…¹n0µé`—×f.5Ù(×§ÁK¡Î€úùßTb®_µ›vFsÞvòÛç·Ÿ?Ãà3nŠŸ9ë~‹¡D%»c¡-ê¡Ý^v®iº²»ûÿÎnŸpdÒ2úT\V/¼{ë¼ÚØDOõ>½¶pSBêH†q\§É@Co4Ÿêazýùý|>é6 “Ž&ì¸m&@;¡QþzZarZ>æQçn{=­û·ÅtçÉ'3çî9æ-‚2^XJáðPˆÇŽ-Å5ŸæÏúX“sYÚmLsÝŒY4î+jàòM?W7MǦ2¼lÆ&w#æv+ “Oe™^õh¥ã¤‡)àáé÷ï'@c5eýS¤sF¥}çÙ³]K)—»º/Ó¦ÑÏ<Ÿ8К'ê¶]0û¡jùاΩµm:¢3d}iúè¥Cå†Q­¼µ—:ݲ(ªê¸UAÝŽ3û¥«%õ}£Æ‘AMÇõ¬·£ä:o­^Î/KN,|Ï}üÑ–Öï§%Êgu· eíؼ”-uV$ 1VƒõÒžJrлlÇ‚/ÎŽñ±Ï„·¡nM“uS¡”2ZiꣻPÒ6ù%ÿsGKk¬’$Sž¢±Ä,/«måÝøXY&t…Z ŽuÑCXú.£·»3‹ôÉuÖvYG¥ñû\eÌ“Ñ[V-Ôú0úãŽä|×¹µà‡ÖUHÌö1TT@A#KjúÏMæ=U°W!g|fã2þÃÙe$Õ±KŸýãÜ{û8Mp膰svvá–ÓÃö«oW Æú7¶Ô9Qq(º ž|Þ˽‘´ÈÂ[ Ý`›F—•£úöG˜&wŹ»Ù pÇ–D¶”fþïö`ÓèY„Qp×—Í)“:7<0¨2y.Óf®X$ˆiò”ºk“wäô‹¶³W&â­N½õƒmGGãtÆÜýöK8~>A¹ç¿øÎ‘—?ß»é„pÎ_Ó²þ½„v–%¦Ü7Íþ+AsÚYj^¯bdHA­ò£J?LŒè!ÀV …*P²(Vo%Ò8þæ#ÞŸï î2aÝø30ïÖ‚ßä}̃ÆN“~¿A‰«í…ý>nÓ1\f/±¹˜mbÚ;b¿üG|ügËLãÌmaœ.2èE¼H’o³žÙÜQõ]õÌ–w§ý˜Ûâ#RÅœg÷[å2=¥x®yò)©jTÀЫQî×g¼'„)|¬#Éÿ{kx¿ì“·Œ*±¤ºÓ¾¯Ô‘ÎéÖWÝ0WÎ<;¦ùÅŸ‘vûÉ´¿N²Ú8{™¢Å8÷óv•³•sæ'Œóµ'´›ˆR7ml±¼‹WSÒZïo+ZïŒM¥¾=†®í„µ+ÁVJ[•D(6”!}IU€a3öl˜q_ÚnìÓ~°s7õ¢ eçÁp¦X¯d½˜~Éì)y¾ýæUzÎ&Q Ñãdí5ã;èÅá)3úKfJW6÷„7ýd†ñ¡G­çKGaºNYR#oUâQRט-°;@ÃÙ4èèp3³î2âÖ\âíqÌ>¸®“ù¥Ÿn7DÔi1ëõôÃX®bñ±šÒ.%±µäõ°ú*‰ð¹TKò[k]e¼EðC ÔÖIªâþÁ²ޤÖh›-ºÛ0bõ5 ôGVhIí{›'7|NZ¢ÔÇÐŽ—µ›_«b5xkÏŽ ΢s£ CŸ«*;/•Ei@oBOǼG@†V·]s¥°n¤yzÃ3Rðb?mx\Y¢µ+KkvBu¯Î_?â{ŠBy—F?ƒF¡DGžœÕ³ ŒP>ïŽÕº{úk®uiPîûh-5ÎÌéïœq>òÃ0O?'ëïEdo˜KÆ»Ìn~wFÿãšsÁÉ•,¯O]å°o«Óè#f¼˜†x¥·¸S@â"¼B'" ¶¡',”4CòG~|rcš0¶yf"¤ýÒuF½$µÍ³D;ŽŽFõ1“‡ú2ÖDˆÒ´ªü˜ÇÓKÔ§Ùì±M¨eó“‡ié—Õ‘Ö“òE¶º}öã2sµò./‡«yeÛ·z‘"&ÊC,°°šÀÎE-¸†Bê<·X÷²ø“X¶#QÛ´ìNÊáã2¸©¯zÝ´Úf­6뼫„æ½zÈtI*o¾eEƒÍˆ.ûJTCr³oÚI¨Ë¤éY2÷NÔ”W~HÒû¿;ׄ½i!ƒ7Û±°ðç×Óê,²ñg~2ÔKæŠëL\›RD )¶V“Zÿ ·‚ª·ý²ÿã…¬Nǯy «Ëù:U&7¿vz]sZü~CÌXˆ×\÷A@¼Bg …0Ÿa Ž}wý ÁwÄ?3\2j¤k`ìÅ ÚøÏÁ%j30ÝÇ$H³¨ïoÿåŤq9.lzúU,Ð>ÙØ&D¸ÚTȹ橿æ=ëDªÐì(êfŸ¾Ef¼Ì@­ïÞ»J Ü6Xüšp^ ÈËø¦z„éÖ×y@ª6ŠgaÖ®õT•n©ÈGASÞCºýhÍ!RŸÁ¨óV¤.=)¾\ ß(PäA©X†âàêMPi[–l¶×vná`=}§ýèÃÎÆ0ô×5ÿí²ç©Ðo‘ÁÃ~Ç\*€­w¡OS¢8Ž›$L³ à}%Ö‘5îWšùŠÛ(mmý+Œn÷ ÇÔŒHÎXÔ‚vÙ$©'÷pshëÉ]#ýyOk´íþ•*â\d<£Rñ9Ÿ÷¯×ó{âp^s8Yʇó±MÆÌúÚ1‡;Ð-[Ùgð™i|ø‰Ôvmº°¡³ÄmÉ÷Ä,´-¢¸Ô×Z³|dl<Ô‰£‡j@¢Ì¼ÌÛÞeŸB£P¿æ¾a‘£…›\ÁˆÎs… ך”<-_sPAÓí|ð¾Õæû¤Ès-yÃ-®S´`Þ·º/“7{oðú˜Òˆ^Ì¡ýÝhgGÕ®¹¿FUíç¾-6Ý~ ,"a­¿AÅÆ¤QX-KúÆÈ´p\f¾ÕjaˆöçìçùëþŸ×üúE7t.¥*@û€Øc:¼‡Så ÞUYvùùëžQ°f·Èˆó9Û‹» 28åâÓed,®"*¼åå­F ŽLÚJìt²Úe'!_/Ý/Ð1ÏíBä¨ï¢Uök—àð@2zæ…¡šÔò± #¸÷eóFSšör±Sªºß3ä&T±áYÀª±MÞý5þ• ¨ûåi©„ýD[O@¯A@•–¨ÌÚÑuAoÍ ªêX5ÐsJ‚á[Ï®µ š|ì›ÂÔXL»`|eæW5¬uã7'„O§­õDý îeùY›Û¤ŠÒ‹Pz(Û˜Ýá§ M¡‹•ªæNÂ2À#¡e†¦“ë±·þ…E…YÛë…1tzS1W3‚~ð¸ÈìâŸq¤K^ª>Ðû©ê½Üáw0Ì™Ï?xbú8æYêwK÷¡KFgoÐ.ùõ׋Qôj›¦“êsÖîFsá>m"¡sñøfc÷?t¨¸) C›î»´EmUhû…ñ¢± \\ÐP¨­Ç¨?Ͳ­ƒKoJi섛ẛ-]så¦ñk›Ç2x‰÷ÕFË£ÂØE$9WG‰f¤¬‡7¸µyÃåÒã>µøçË.‘Ü:bMIäccÉÊ­‰ë±ºôÔþûoû‚ö“Rç ~ó4%âÎ,4=»,+± ƒ´ê:¸åµ÷äÓ_uÌõžÒJÛW_É,6Э”|&7z«Š² ê¾SØK7ùç}PÁ¤G0uÈ?O˜ÖS´hŽ£æ^„1J@IÊm*Š~ŠP’l³0£ÈBšªóõà2 •®ë®êÙñè±½”f™˜®),Ä!É»^:U#l­2UÎϵáÿŠkU;E¤ã{jâý˜†š“sµÍ0¶M¥š@›AC) à ºÞÓxIï m[%S±èø9'Ûƒÿ‘­=û }¾‘Žs¼ésül-©ù2í¹b€µ³—‘‘ZS»µ×{1ðëÃÊqŠKw„2p¤` !8Æž#.‰3´à›©ÏÈQ€Ì¼é{ƒB\^ža¤Œ~ƒ€ÔB¨ ³´ß†‡Õ–cßö Ö¡ï(>̶¹=œ&êÝ¿ÏÜһɈÓúüõëëaŒ]ýŒ&\m3(ßà™ÖaB]f‹‡„ö˜ëK´s sü€ZÕ]=bk•ޏ±!ªçt=tó«Þåq•TŠÊ ö¥u;°I§bêë®ì‰ãIúö „ÕsÅ?Ú¶(½ŒÞd`=$>Ûãµ»fâWm~þÓÕ öÝ´?®Þã °-Ö. ÐN*d²õ‹Ä°([+±Ò>œ7cóxƒÀ®*¦ÚÖ„ÂÓFƒ†ÿÕŸM¸ï%ûÜÿÞ‚û ×m»&÷<{w¦!o•e€6üL\TŸŸ:.^,‹;dïAÓÛ†›'t9Øë™¼¹Š_¸ô×|Ö­npS -Ò?î ÅæKRãáí ¶‡EÂíëœNî]ª²B¤aÑÔ<**SIî*]òĸ삘œ÷…ÎaÆÒÄ•¥–2oØ nõðô#”úÛv#uYRB°Ëê³ÿ¯P‡Cçü#L£¼ˆÀ±©L»,sC&©>’òBq Í&¶[Ü£Î_Ïy_<¤^†ÆÜJ£[Ýù°ãf(÷ʺ†t½~B'{Îí4œ»C^Ö|}뇛Æ9Œn'ÄÛÞ~þ„RžMm£þ¤‰\æ1«‰®n SPÑZ\þùSÕVZŽ7Ķü²ÇÐNäê}Ö…¸F0£-ŠpÑÿc æ÷ifhw˜‹u FÞªŠæ©q£Ct"â0mŠ8èë¾'»Ë ]„Úy²Ú¬3qrCAËÞ‡ÁKWÖ—‡‚ðMÅ|@#7­–ãôº{¾¾¾¿¿^Ï¿þúóµ­Ç .üc:z˜ºÀ×T*]¡Ó!¹®»f.A->/Ÿ*ÄJ%{»æ¹ÀhÅÎ\mÒÕØ"vzŸ¤Úgóv]tëõï*´«±¡íöYX!ÐC²xr¿ë°+}§Iïmu­Ò¡©¢[ d¢oŽS­‰Ï"ê.½g%þ º„“¸ ‹ƒ§÷걺íd·Ïgò8 XV/$æS¸®ûmòãçÿXhl`@m¨r¤_°z˜|¦84¦jëuúóS°~Ú= Ú2j[a]Ó‹¨RÓØŠ£àg¡ o†/^µl[C©±"qQ×Yx»ÅEúÀgŽ«ð‘çaœâ³ÔO¦u<˜»ñù×khÆÇÕI^Y‘mÇÕWîC'ˆŽ´èøzø1´ýkŇǪ¸?îºÞÛ×£oÜkG#fZU<Ñýâ ìŠ1ÓkÈ Uš/[ÛgÕP¥á̹ͪ×ÃWÌošñÙ–‚oÃò|mƒNC;¡ýùhþ«YPõfU ʆM¿öÕ0 ’!1Xn4­­¡¹_ÐqÖó´í°²[üøgR„ì1¥ÔsŽh™q7ýý•öÂfçœØKÕ2 ™“öýkô}ºaöî9úým»IPÆi×DQ­«ÖêX†Ð>€ÑAÒÌSËÚJ¥Š³vÖ‰‡žV°¢–AÈ` L±u΋ |ó®N£íõ"[_þ󧝸ñz˜«¢Â@…%1çSÅȸªB6™cÎH˜U€›¸Ô›ž¾¼2ì “¢"Wo2çgS÷¯}XŒ~¦S 0IÜãr™±’â€ÌLø­O³À; M3 4ŠtQÓB¹YÉU߸S¥)ëF¯áZ±5f½$ŽuŒƒkI‰5 EšS6ì}³:´§RÖšz{AHжQ m«0ÿ˜ ¥5‚Šp¶Ý`¶ßyÝa²ZBИ³tÀɧXo/Ôo]!R¨ ±cw+(M.ÚË9?ÉÐøæ³g3³· щ°þy͹¦ÂY»8ŽBªŠÔ¨->ã2þ™Ѩ¹Yß!÷_áG N£NÏ%T!‘0°5uö†³B:Š5 ®¹E R‘ã2°E@ÿH˜BçHˆ¨”&ªÉG,“3)z²ò´ù:7ãã嘆¬çÊô›c½?¿¾tõ!÷}oFËš×_Ï•²þÀbƈ ¨–÷yëæ¥józ¬óøîå°{–Ìtê~”˜)ÛôhBlÚDñ‘Ꭳ£¬7Þ²dÁ5R6Cû»IZDæÛ6þŒ+“â(К2&š·FvzæŠ0O“çÜÈçH^,ß8—iœ¡«íá;éö ËiˆeYüÚiÙôêú$ÌŒNŒ¯iÕö]áðÖz y3*7U°úºè’1p>°MöuN¼îð™ÏoÃcÿÇ«Á~ý÷ÅÊ4v¥þý1”¶‹H‹šèžç·8 X⼊ý¦6Öu¿Z­ßÃñ ³9 ­äÓÇÙ*þ{œĨzJç[ˆ:G|OÜ~]ó“ë¼›SÇy³Q²‘$L‡gëK|› ææu^š˜C¢É”}šÂoû4WH_”õnDË^è®[]=6¡ÿØ è–)“ø/[(ð]“V?îŸw¥¬Â©./;fì¶x‹|’kõT¯&X6H6¬ã×Uô›·€À‰íÐÑ(M‚´…53 Ýô»0­»\Ü Kýã<>áïšç·ÿƒ 7 ±Ù9Vì´ªÈCd8¹æITç"ó)–Ý’,¹Õîãžeüùq 3k Y œœq¢u’ØDÐK„!ÍG®ÁœS•#ÎÛqíïqQÛ†y‡åc€¹ö­oÇÃ\Ðþ= ‘¯þ½wæ1Á`Í Ž¿m |X(gw0\qg™Í…^€k½-ÎÕªš3н½Ä2 ̾;¾œS¶Jmš»±3ÿBå I†2j‹: ³ª*¹çjvB²u©ê¨r´ RÌ¢tÆYeIX)Éâ ®iÌ7â,Þg*)ŒŒ ¶„åýÜU»tA¶ÓàøœŸY&Ÿ¿ÑŽ[Y#ë2+öþªØ˜”užêÜò¤“JÓ±fžå~¢>HJSKAI ¦†7D:…¿½ÃªýšN•És‹î¸¡/iÊssjóž”Âm†h£uü‰5÷4è!jaáâÎ÷Z쪲˜K5µY[¿‘GåÑæs“k•—)Ñ«ÂKÂã»ÏÏr9ü¡^³Ñ›MyryóÀ(c@}ÆÊC£^IVÏ$c¯¾k«ZaÖ «‘ÜõþË…© ´à=Ž:ĸÂ4®Á̯醮P³¿“Âð?NöÐæ)Ö8âAûn~­SŸ²JcŒš„Ô Ë*ÄtU”³ÛÚ_¶I™aÒÙ´°Ljf¢z9 t×õÍ,Ëß;‹“a½þݽ,®js¦Õü‹©V2|HKRýX +ÃÜÖz”µuWƒ¢ú¸+DAýL?ê‰>ƒ45u˜-㎠©<Žl« äÞá +•0Lj† æ› – âà3½Ýq¸F¶„¹úzøúëè<‰d>ƒ“²ïþµVi»Mçy­æØ@mÞŸ½‰cMÃ߿֦žž¿¼-ƒ§—Xþëò¬Ô' àK4ƒë•ÏÆåÝÑìÞùGØ Ì5óÜaKÁ—ÙP Júþ؇˜ú¾lUuÖ…¹…+²ë²„ÒE"kø%CÇ¢NŒû…Öubüöj„ÊãvªúcD®¸­Ùª°|SžV߃¸8ì^¹¦Å9¼¦µ{c÷©Qí_³:T#ÀEcEyĈ°7Õ:6 ¢6̬:ì¼ìˆŠÙÛ úÅÞu~¯Ôüv£ÓüþuºÌú;º¬o«Ê3µlcc¨Í¶ØQ r¶GÐþ5­Ô†¸2“·`½PÓüˆœÕíªÞþ£oÍ:›É%y—çÑG8<ŸóI7úš3'f:P°›4Áº’½ƒ¦«ãÛÝ ÁxµÃìšÞ g·Þ©µ¬XÛ³ìj·MJTeèô§ZBø;‚Nr[ .h£Œc1˜¬Uð7¥ÉèþК›¢­Â4£t†¤ª6P‰D­Í¹å×5׸2Îj¶I¸~ž¥XŠ"à­ð¥<™«Þ¯9c–ØÇø¾æÿé~åãýzÆÓ±Ó},#¶ü„-MÖ:½‡eN'ý÷穘N‹ÐÇÎÓOç¼oäuÍK†ÏyNëŠ…ßØ/*¨"MQyÓEgË&&øiøR?d|×ãQ%¨XY+ßçrûû»¯¦_&ïx|ýš½8Îë×ܸçŸÏÑOJϳ¿Bj·fÐ/ò¦Çßÿß}{|ï—ÌÎÐ{ÓŸm1Š/T}Õx4Õ —pÈÕU¸æ·Ú÷ïÇ-3!º–T—§í>]ºk®ÌtùÛZO¾«:AßÉSÖ†°(† “–&Çd1G¸¿/ ÁÈ25Õ¡Ôö½UÂô[;¨–0¡ÎíëaÇ׉¥GSšö««£_ô´ŽËê;Ü*&XÙml·õUzJqÁÆl[ûi}d §Úñ³Rð1sÔ úhîax³=ø^!êZ©ÙOM|„ÂO"µß:Æ¥nqÖLSÛ1=̉x©A†LXšlJ9šƒø€çãõ<,ûˆmIø¢ÝxE¹Õ$Ná—3¤c@i!(—ÇvÂSÏñ®·v?4í«û--Ø07¹Êbå#¼úŽ–LÓ 6fÕÈô££ Q*‡õVd§Àtn,)]ŽŽª6ºÙ«¿þËr]ósž¶þ†ì¶‰Þ{6¥~/p~@Ô¼N`˜æôÒÊ, ³ÏÿUÖ·ç#W–ÑD‰1AU&/¶ùô¤{ÅM«ÇÍÐ!A<.0‚VÖÎVÅ•Öee?Íj}ùŽÓÝ Cµµm;NΛC©–€M©ÿQ-þu,ûç&uuN=çM8ÿûϯ}y,ËóëØ}ö¢|~ÑF£F°žª#Yì÷¼Aد)oå|*^SÇ"¿°4‚UHw™Ýù‚U)Šƒú)ú¥WÐÎͬLwHÙ˜iøSI9/U\Õêi¥gÒ µR'¹¯ú¢¤@Äj2‡ý˜§nT4)XêëþU;8_®Ðm×û4ïcožåk¯Õè̯C1 §y«o³Îg@Á™+r6&bêOen*n™;KZ*®¡ÀÄpMTíl(| ïo‹Î§Wùá7Ùñáýzn£»øoñ­s~n`^ÿˆyEÖu…k E Ú8*)‰Ê^ ÕÏk¬[þ˜Ý~êxs&J©èxÝycåL*{“ØÅ©Ê7_= ëšBÑ0³í/P¦BŠ`#ðÞ­ ™ Öyþü()YÒ®·Vz/øeVkCJ‹=Ÿ$VÏ’[Š^•Ê)WUQBÌ "3M+†7ã”Ç®± ¾Ï]s+NhkR&a_gëèu{§î„Vù¨H RÎë/dIâØ­6f'okA¸Î°…®Š[¤ã:<×QÍwýŒlžøl×|š÷Õ­™m¿Þמ•ú]·oÞ§êã#}¬,ºßuÓ[TαFâ{øˆ[à·ù„W,ŒÖûvЂi6åB*- µèyÍ«Ï{hè‰êЦí{ô°GyM$ zæ:¢J Óû±ºvzÙÒqæd>vÕÿy!@kÎ4~‡õlÕ 'lùóë˜qâÔáøÿÑõÚ‘$Ù™.š/1gØ•@„kmæZ„²HÎZ÷ýŸèüß6Tó¬; »«:nÛ¶úÅ]êÚÛu½- VÜÌÚpÁôƬ«šç¬Xx-iCÁ‘O± ¯‘± ¶À ¼½ŽÇcíTìÞ†fÚñ”ÀÒáh§cžƒ<Ø$7-žàÒ©×V'_%>ê,¯3“T®ô™Uq”åÞ7eîÛ)p3-dÒOŒ×ãDíªHùƒð{Òrú$­‚:6Ͼ¤$"˜Ð˜ü‘÷#zA}€æ„‚¯Â©‹}ÒUmù9m‹Ø MbÓ-EçëaH÷×l/z_“Á.{Mvj…®™ö\‡~>ìÚ2Ñì}{IMè›`ZÖ7åèn›‡yx·”°ü汉UûâcXqÖ÷Ü—SãPˆÂþC¯“ùñQT‘BÝvÂXC*Eëü겉®e‰`™Ò»Ú+ƒý5¾Ö?evñ¯#:Õÿc߯ciÞC‰b5F±t ¤‹©.XPúmôš¬íé-+-¦•ÃÂÙ…ÒPbiÚÌ@WTíý{×åM%ãa‹‚õxØ-:ÔÙ§rõËG¢2xxRˆ70HL.—S$,ZçS¼çßxÊ'°á ó1„¹yI±)Ê$½D®Lbî‹¿&mò;ëþ*«ßEþ/‘¤)W}‘vHq ©Ö‰/—¢1…põDK_uqYñg¼aªXvÇ“ç÷r¥þ2¦é¡qJÒ²y¥Lvûû6Í7ㇹá÷Ã$]¡¨ °À&Æ6:¥=ú?_ûãë?ÿ×Áñüó_¨7Ü^ }©œ Î"èÎ#$¯¬ {*÷ÄtÝVù5F²1‰Lt§_z¨ &y–‡0_\9Ì¿>cu+tƒ&͘eë ©ÿw%Ûî·L«Y7¢MGJóþ¸ ÜpÜ'Õê…²ÌÐeº ®ªr1*f¨avÊ»áf‹{®84v{[<Ï'Jd2t_³Í´ÈùØón· ‡ª‚Âw¸£´Uu’DQ—ý5ÉgùùQ´º-/Ÿy•!ïè`Ͼ٦¦é‹OîNð¬Ìè2ÏÚ&Ñ]¤+)›«êk¬²çyL†CÚèô¯ °äT#éºg–»ªÃ®j¡´Lúæbw{ƒìë×ÿ~iýmÄ•}ãþz©Vÿûëûi¸®Å@£ç®P‚î+ݹªžÑnÔ5Û¬vÍ7Ó6è9çq{GÞåÆJ»SÉÙèáuzX>-úÕ :£Èë>uKã˜1tË`jae“ݰ?“ÕV¤~ëÏ`¤5©±XÇ~è õ”>«SäÙn²Yd–¢:Ðëaía¦~œ.1Çö|.=f;ƳWsrœŒ-ó«~`YøüzbÆ~C ®19f…±ÇD@ÏC¢ÑwëÌ»rt¬*õ$Ó‚}| ð?ýõ~{³Q¬h?µØ×íÞjŽç“ngãMU9OÝ>ˆØï»ÊêH%¶ºiTat(z¸ƒ7¤Éî0¨ç=€³¿½³£m¦Ió®·Úm÷/ç`p©\ .LmÛL¦¹wãnšuº ?õ„ª>›è³-‚xaÝ\#®ë4Ç×Ýñ²ºÆ³IÀ•x¾øý¾™´ÔÄËI6X°aÙwtü(Œ©¢w‡4;·Ên]Í#PLóឆËÓâ#SŽ.ø½Fe¦{¾°®¤çv8·ôÓ°NÎÏÍϤÂTB p{gT£0³Ø€³¾t°Ç­kðËiÐ:)=Ù…jÇ89m§0ëÙ{‡‘ÓNo÷@åx¾‚›ùãuœ#WH"ýß0õp}*=ΙƒR¦«r\8h‰¬yuÔ0c‡•º ï2nNéÂi]šTÕÓôѶìí¸… -“¿ÉíÎ3ÚŸmÔŠIš«a¿Í·{Àg¬žúhÔÎÖª÷ŽÑnØÓVf×ÓšŸ‘>6¥œüœ™ Øî4ðÈw@3  93 ;‡ç3H€Bªö§&J|šù1‹Ý }å{Þ~@ì¦È]W66ï4œ`¸>Þ̽ ÍtfiãN™ŽŸšUõú„”7‰ÐðæãÒ±†@Z¦l΂NKåúýûΦÕúlŒtƒwTI€6à߫糫Šþ~3×ô!0ÌTC@fò:èä …y’w´Û ­. 4cK &OYA–4¶t„!Ðã¾½êÃPçlã"Ã,úAã`r~]p@•¨¾€9–T—ìQ6§ $² ³êRíI6l~JÇsƒY¶è>Ú%ù¥[MÕnÝ„¢Ü7Q•aëé˜{ph†~°Ö …¶Œ¤\š-Ïéé£ö*ôbÅ7*“qÅçYŒ?ÒŽ@•(gù&êf€¦‘ësÝ]¿îÆí6+æÞºóí6“ºa¬9Lq² ùÉ$Ï/*uZ¸ Q§â:þÅÆaoƘÐ9fª°ûD>7¬=® ÐxsM¬Ò²lz— ›AžX/*©T>†&û°#wý“sÑø Åü¦#¼ýÂÞÞ×3—ŸBiûdÒÇ·ÃL”žÊÆ@£× 6&!í[¶Ö˜œâ‘`R³öå|ß¹yõ5ˆªU¦Mçˆò¾‘pkujÃÀQ¥»¡~ü¢+~ÀùÁuAe îKÉl›ŒIx¬S.øvDCne‡<÷o™>¢ÑßÓ73ëÕÆ×{7…gï‚p5˜s,¢n +šæ©ûn‚ž‚ȨÁŒO>9jÇ$*•ùþÇÝJWO§˜T‰ov'™î(=Ûvê῵cí7õ†ìre·Í§:A°?xMMÍ%#Ä×k†½ñšý™ŠÂa£#TÛò<µiçnU-Ô¯¯Ûè–ûMQ²¿nƒ[žè.¯ÁèÙE–ÀL†37s…»4C=ÈNAÚת®WÅgÚÕ1±"+j}‘”]—Ö5Beùgïc•—oAþ6,4ñMf›b%–¼™wó1l\FÕqR ”&Y¿ê‚x(+îLïˆPaºÌѯkÕ·üx †æ€®špl£ª@Ätò5‚«kÝÀäé½nÝK<Ü÷à¨d\ʱº^3ÐTè_u[%QꃣÂó\ cnË…죄F¶ò¼ËZú¯·Ïìb÷7u6ŒÝ¼êUæLóS(éõŠ¿U…™d صÂyÎaÓ:›EÝ„B¾¾“‹âO4Yº…¢±. WY#žßvñG™§qR´¾¯]ßfic ñ©M?óÞEIßþ«¨ ©ÆéµÃt ŠoæšÏ·¬ÖèjÃ÷\½ƒí³÷:bõ r‡,IѪù™ìòÜo*ÓØb¹³8Ö£;L£ÈPÏ¡ÆntbÉ5m¿Ü¦à…0ßæÀ¨ÓeÓŠBþx7+^Ô׎ISXäJKvsè=2`€òëu9“ èLrFŒ^ƒØŽÇ{ùm4Å#ó ^ÃÉ—¨0ô·Âî-÷‹ï_wÛn3Hš[D£«§¦Ô‰üÚ!ÍÄ`³?¾ï};=¿ûÜ¿¾—º]îk[O¯Ñ•hx÷#Ô,LÖCé'Q½¯ªà~Fâd Rtž,½ K™¦ªŠãÄ`Õ'è,oR|}òöæÀ]Ê8ƒ€ÆUY³Ñn¡ñup:{4U;0”žÆ¶ ð°A0¥ñº e‡´Y ‡š öTà]º3?u£þ ;üÕéè)oxØZèE?[§7ý×'vì¸ÕÒn3L“X©<É“TMN–$Íz[ =lø4ávyqý^€È2u.ƒë =áPÉ?OtËi:q«Â_a#´?_ú7%"èϯ¯'fs¦Ñ5:½oan*IÃ’ÿbì‡ w %tÉT毫8Úž[›'ÕVxîÄn^/{­BHZñ¬&Œè0êQ«?¡ 6?‹·Æ£ß–NŸÆd`ÑsÁj¹1o1]÷¹¹òÎ ú¢¨ UX+Ä(Bk¤²Vþ¶’Ù‚ÈÌíÝ›Û:Ö]ÜŠ–Ey;Ú¶Ö!  ˜Ö+¬Q-².-üØv:}·êz< _¡û(Ll–õØÎ±Èö#àsZ2’Á;ñW”²¨\}7îjaäÝÇ6+»"©¢\?V7‰~Ë”é±\ä.þR¹{{) ްŘ%õ¸@§/I–Åyf{«HQÕAwš4ÊTt0"s³³5ðsÌ9ì@dëÈÕèbàÕEÌø]´ÛZ§îò Oþj$-«6ý<Ú½)@ÊP÷º6A·öI ]:H>×Y¥–¼Òq¢?‡½¦™]@3Îyô«lA=áûÐZ¶Ãù…·u:+l™¥ã®–}k©^œû h‹ÊÈ8öUÙB€„˜0°Š®yÓR“ƒù¤ëqéØÎ¤õÕJ ß›²!»¸àl÷óu;”KûåhübÔ@V@ v¾_©ÔÔ¡Ã<ÌŠõŽ…H§^\÷ìlë7Ý€nTQÚÄ¿cZ^6fIIR7S÷jH#6eù5U窖€Þ?Ïâ뤛zQ‰;VæÍÖä¦5‚{uÝoÕeJA©üö¶o¿mëÍ0/zææk|zŠ!d ~ŠøMצ9e™ÎG1Hí˜ïÚ¾3S¯C78sª§Jи/__ÇcARd­õ¹]åg¯®^=L~ØkÖG2`Ceú6ºgûžž¿¤‚ Y}<¶ÁW¥? ‰ÎÖ´­¹ö ÄߘüP¹2ðÀ ƒ~×.FB߸íXàÚ?^œu½…tºÌ÷ ¾1ªÊáX˜«&‡:¤œ`cNÛRðc³|¨ÓnݼÁWêFzà–zƒüvsÜw{[0åé qß[ØS@Ûè`ì3+ ¹9-Õ–¼Ašôzy òY·#à7N»„c>P ßž‡oæ‡.…¼¿ÝÇ"Ž~C¬S%ý¡ÖwÊqYÑM: £7>EN/™á¿Âý£¥û$7‰àÖ™¶$1R&-8­6{àt¼²¨í´@‘ÚR±Ô}D¥¯*Âd¸FZû8&ê Ü>$ñ5¸ â§6ŽBY8Â|r½é“èön—c(ê_•oÆ©õdr¼LZ_¤Mõ™Î7$ÅùÔ6<›BÐîuku&«8ÝÛ8÷IcG©H¹‘²(E[ð4YÙ¨Q_7ŸúX§ãHÑzùˆx—º ‡SJ°Ð®è®¹hçIo‹Z%ŠÙÛ°>·iîYm¶û×|{Î~ßr•O–^›55ƒ²²6‚ÓåTé BxºÖGëºdúø]—Q’ý• ¦ˆá`ÕI 9vé—ú¨Í?œþt'‰ýþzÞ€73o3‘Þ{þ{ž ídÃßÓªõ\ôÄÈÒ»¾ £WhUÓû ÖA•N­b½Õ‹r½žø8êšjnª »ðY–*ýù¥CŸÁM&LrâÄËvƒñ0ô²t´-\„ÞëÁüڦŠÐ«rë›Ö¹ ¤¤Ð .e]E9¶UÛÕɼð#®zÁ¼í¾™î_Epì6‹+@Ã/â¨Êî¹aŽî¨×Ç üªRê>î Ëäup›Iym'ãc5B“8úÇŒƒ!¥Á i/§¥®t4ŽÚùØj¡u=^»Û®j¯Ûû¶3ô3Ü%½¹ícªÉdhuf ûý¾3á¤+(‡¾À«óñõPä«Xú°ûéiazC§éïÔz%†êÆ€4w.õö¹YI¨ºtã H]¯+ò¸‡©õòP!Ui>ñÁüá3&ŸUoR¬ÕT“2«‘ð«Í˂ާAv?MJ5æIV(OªÏǦUÔù:UÅ%2 `­ôóºu4‹:÷ºo&b½Ÿtgk—àZnanÈÕ°Î bÐ X–ýu $ox“… »jÝ&…Tå9îwÈ„´:@<ù®ZerývtõZµU4N¶ÐüÙyPz z6*ÍÛÆÁ aÎO§¼‡Ñ×±#Cã·m\ XTû¶wy¦›Á¯¦6=¿Õ“ÂÀÈysd"[Ñ®èÊŠ©Nfª@1º2˫ÁbÖÁtêõ\ÃÈz5úp¯¹Îy‡!o•¾ öÂeÉO«1ûd¨Ä4n^ÔgÕÞ7E®ÄþXÅ©íû†É¨RPëO}ÿ#HLn£Q;ÕƒìS¹Û€N-ìm}=IÓ».·½¯@‰…Z]w“Ž5ØÛÁÓ€ Ó˜›©n|E ‘è2ìÉ#|O|çPz*ѺˆR}Ð6„9«J½HßÐ75 JâÖx'|»<×uÙªFă~žÔ™·º×ôZ“çD:ªAOšÁ sÃì}~eò0(¦ôá”û&‰­d§hït1û¦Ö +99Ä7 mó‹NV½zkwªžg\«Mc8 [@“”Ëæ(üäQ=Î2®ÁìÝ8(¿6u§û_?!Í£ŠaÂÆ64L_dh9Z DÿØôüÝö° }Ø ¨­ r¯:‚U0=P] w×U×ruÿs‚{:-xM>”ž-Iüz-›4„yW&ƒƒdÆ3½Æ¥®ëfY|·¾˜z5¡•®p7›bçnVŠ 4PèÁÍõ·4e,WågøÝm7ñ ÂL’Yµª Ê×{€¤“¥wÉnÆ#ä¤Zµ 5rU`“£‚™2§ÛrmKÐe;”º‘Ui¸¹®ã«ÊQ#¹|ÿý=pò\ÃÔLOG’ÊÞ¢¤¼¬&±J·ä¡¦÷ºç Eá=’"~,{ aNÕ{<ÔÑÈk‚XI[šH·zÐ~nÌö»m±×48 ñ9‘LT2N&°ŒŒX(ØÌyÔ*Ì@ÐYÙAlÖ3qf¶ kƒÂîÐWxÑ{4bqÉÐ>Ó]‚ר —Øè·A!ÃÁ&|Fd,BN¸kp븟» !ýöøúóçuÛ«Rqoïfê´]ô'T„ÜÇ÷a^XvUO £Hi9–Pδ~À¢˜…5úŠnê’6¢r`tAZ@ç)$OZåºIMv®±­æÍñŒ*:˜ˆeÞà§oïHQ«éfí§8½êFI¨›Ì•ÃØã¯¤½4Í<ª7‚¸aË¢dði®o)§ £”ÿܹï~ NÿtºOJæùEæ1ü?ë!èg9–arædgâÐ]–tz«ycQNÝÇ8¯£‹ý4Ú¼šÑašèú‡¹¢UΠ”LÄ-ûÖë†õvC#ÍòFg4|ö \‰t‘k š÷Àauó:Ä÷¡ñæ‚L‰!‚°0KSà )»ÙqÕ-é6Εäüç’R¥c&¡*Åeq[½B¿ìC1Úf¤(Õœ>{[BiˆÑѤæÆ½æÆcúñ¦à¬€M* ¸çÝL DôvÍR7ÝûÐ ºuÑìÍË!Ïœ/êÅðõȱé,ëlÏ]Á$WwV(>ü¶¾D+íÙ¸=¿¿÷¥ŠTv•îЬ][#µþ–^ÚWØÔ¯³ÓGœæýv[ú°xíLÉ©hÂPÂ%ש®ÊÞª´ÆrwK.ÁlE:y›0n5|&ïU€†ÊÆàÒ9ÒÊMÆSòk.¯©ñ?›°ž Zp^¯ÜëèŽ4 ±ÛêMÒ´õJ€;å—+WšZÚn2„4³÷`¸9™¸®eK¹¶×÷WØnY‰0}¸ÜãŽ>°®é·(¤ù¸ÞÈgZn`óͲ^'нTf¶öºä ‘ñŒuÞ‚Õ7>ÒDuݵ?³ÞêÑS{[Õbi!íÐ!mlÀ^B´2Ðuåmìô-áÙ׬©ÓàÁVéþÓ³jZ3ï4O®^ÛK ¡Dé›ÂçÕ¶æW&ÊÜDÝØõÔgÌ«¸C*eéÁýB¤_a>ÔiZ7¹J³ä3eî»÷X¸è tÝLáÊ¥ÆæºŠÄiŸÖkëí÷îš²$`®_ú~_VE…:ÀÕ[¬Ÿ‡}í2{“£Y¤õŠ€Y¶ï|nÈžÞ°¡ÞÏÌcù«Pl5m3</^×¾©˜è°IŒÅ—ÅšMõY†0·õÿ¹*ô¯×Lo5FĶ]l`;Ôù‚·Õï¬5¢ZÐó®ƒdÒb‘~ÍMgœóXß¾»[P0 ®—Ч’„¹ÿî¦Û××mr·MQMFÃl}WT*óº¼ýXáÈXéºEw!£rØpt?­[pÛ'dSh³úcÈë×¥¢Ø!þ‰P’ZaûØ€ƒêfLòá¶Ø,tSij{õk*š â¹ÐÓ¤s“[`$|†yoaÞR@nhË|WMNÍÞ$Y‰NÇ5«U7´½MPt)w‘Ê⌅ ÙçQÞ†#m0;O‰ˆØ´A€úúš·f³õà›¢Q­—G*Çl__fqZ÷ÖñQÍ †O~“¾¿¶Ù<‡žÔ÷#ÀïÍãn>óôŒ •á:g²o¹H/X÷ê=8ΤSýp:Y½c¿Co:€“GKׯUtmƒØ¯#¤ 2<~hFÐa¶Ö9WAÇ=R­®H몥3#0ñ oev¯–Åõà‡B˜ÇÀšÌ,ë:5ÝçNš[[yWËľ<VÐIf§?Z"ž ÿB„¹ àþ5t~æ8¥úµ*‹UˆÕ88“åh¨iëùþf@¦'î³rF ޵¹YÍè5xÛj½\ j_·‡ÁôI+š¼°Tq¿5½¬ø&p]ëTŒ– Ö£C V×õ·ì0m¶gŸlMƒˆ! Ÿazd-`Äõ tÙ%å%Âtæwäõc$Y“uqýH[½ÈʯjÃÔEwýd ²uÕòˆ^DDùÆo´zV‚ž¤ùå‡o}ʽ­Ah¿Û8T¿4ôËã¡Nüµ÷uÝï¯~èÖ&›U²™ztë¤/sô=Ë q=Ø¡ÔR°Ûr®¨ìœËé‹Eb·ã:ë44%øw}:4£ _¼Øíw¸VØÓò'Õ}ºž¼ ¹{àM 25l=R© —MÂI¡ˆËéû^¿‹vËâäÀ!hcÉ2«lìø—yx³AÁ©Ll¦Úd—õÞšÞ¶v†o™½m’€Ïæíà9ÏJ† ‚Ò¾e_•Q3¡¬kN¡¡¥‚’[¹¼^ÒÖ7&î’*³·6Èfš{.Рêã)¬ºûñzýùï 2£ ÂÓ3|ÃýùÚŽç÷Ÿ¯ûñö{³í]}0‚%¯ë³ÝmÄ·­êJ­âúY5wÈ7ÛÕ5göx×$Рr–bI1bíFÇNiŽ}keoTüfGWT™ª;Ô4nGl•ß®Áæáýc%~ !Ì&X÷9^PMñ¿Z¤Ê Æ²óÁè/.µƒe*¸ÄY;©él‚ P½ú2c×>ö¿Øè¢m |DjV¦å¨žŒ7‚I&ÛàŠžk¾Ïj¶³ÞÚÌíÐͳà,W–zI±¾{^_cÝJ*‡ –ç® Ó×}ŽÌ•€LýœÖÀ]4†Úf½4¥ó.Àß’I£›Ô;¡Ö£0ÞЄ}’µV¡í·EPñ™ Þ]§¦ˆê0¹¬¡¹åרLpLÆTàN«/+×é£V}8Úâ5$˜ÄZ±h•ð4þ8:¾WgAƬ9€03íß÷¿ÕEí1çUå¢ÏóÖ¥CŒBEC "IØLyrÉsHEj •m°lê®Ç’ÕëŠ:‘\ì˜?ç¢è}i #0šrªÑbàr¿ÁÎ7ƒ>¦û;†”C×. 6ZËŽA\g,©~G¢ÖJ_È&#ŸcXããÍFpŒÝ\0lé ©Šbvß™®l!³0±˜§âÌ™øš|W^vóí䆤Ž0i*E>¾wêEMmÏóóœ™ó¡:·/h'˜_ú¶• v uݹU©Rû“QßùÏ×Íì–Ðz1W>ÓÁBHo'£Å²'ó·ÙI?¿ÍÎÌÌýÞ²2ft:YtÂ~ñUJŠ(¯Ÿ5Žy'™¸A5uŸÅ|ż’ý6CˆÐ̘aq”#TLÖz#¥9sòk¾[œ3S-×d*¼ µ\åÓѬ$³AÃéIíXk ƒPaò›6åÿã(+UÏŽU’æi©ÐA=Éü­øï27@ÒV1jáº,V²õ2ýÊÀÕÜ`îФ÷ûÜö7¿êlª Pºtè{˜RŸ]úW2!jHýÓ°—üã⯥Íd«êR!¤Xº\²¼™($­X:­ô AÅíÄLÚÕü=¨á­c2œ“MCÁ`´“mUf’Ý|ì£2å{¡Òõ&0Ý‹ÙÓfõNŸ™¤ôyDÑå8£Fy‘è8Õ]¦;h4#”e¸ß¼?Ágð±T¯<Å ³tÂàf¤ËgGÛØjú´Ã{‡ùƒ+w9îw¤Mõ Áãù}ÛÚ1þ­lŽH®Ó§‰Ý[ÕNQ3 ᇴPÍÇvoBM_O©îWÝÓZ]ÚĦ^t™/¯O»/•ΛaP¥U!ûC *ÔXuûÝ@ +÷úSŠ~ÅÒ¢ÏË¡ÏM˜s0›½õ»n£Ù8y‹)—ž 5F‚D¸ë{g#< ÒUÐâ^šê̼Jµ(åä§.Ša¾ýù?ÿõâ#Á7p ¬ôE‘‡¥™æÕàÕ÷×Ë®¾ÞNwܧ²•¦©ß”IÜìö0êÌÉùzÿóß÷€jÞ;{îÎï¶a s5â#H€ˆƒÙ››ŒÁg_Þ·ÑYíçœ7Èät|Ñ¡ïÛØÆeô[‰@·—>§<…#¤æh}eXk(ô£Ø4Ô[†…e†À÷²šuýLFÉH˜C{UíÇ©áóë¼SÒMj»€&¶6{mF>ë Q ³Â;Gpõ9ÒNŠV?£»ªŒ…èºê@gjcâ"M1ˆÌBˆë¾S5¨ V—Ó&oúô·cv5ÿZ6ný\J0]°Yƒ/Cïæ 9w¼ÂÕ«²Àéò¼©£Ø+¢–ÿz©nž?TŠ¥e­÷Ö$‰ºM)6$>Õ \xÖ‡™b¼n™&|NhÌo2 ˆæÞ›ð±03g[ݶ¤ëaÜîA&Q}ºr…ÎцX- 6ä%«è‡òÑ]é‘4É%Ñ?’k’£FÙæê‹téù\r@Yµ¡c˦Û7½TfAf½ €! ™‚póØÂrߌIë÷z“wì5 ٱصôZ:·=ŸçHBwX¦33d‰ê5dê¾ëºZ׸>Ð~M²¾/ÊiÈŠ¥¼ÔèBé ßI¡þu¨Óþvÿºo÷¯ç×÷Ñ8@ª´ì¥a5M5(éµ.«ãù÷ =P·ä*}Ûcê·cG8Q¡òEÔ­*“ñVµŠ‘íäiSº5‚T ¼€Ïµ«eN‘—çÊCö?*~Ü:Lj&(A]­ôRøûë뉧«ƒ5®<¯›Ì'EW*ùxf's©sÝ žõ{ÞÌ7¼“Ô•V‘¥Aä'IäUf’uÖ'ÒÙRüÖ3‘M{±Þ¿Ëh®‚½ÆšnU‹ß/xþëøæÌ*&§ÍägF}n›±õ'ß‹ÝãqÓCòMz½$dJ3Åæjò‹Mx=`žŠÍl’µE¦‚R¸È.f ¥ƒ8™œcV~\‘/f܉ڴªK®zIGîcõíŒàÐán¬œ ‹KõILá²ÒÃKF¥ÌqÛänhófÇc})—£kœ°¶P>Ó]„%²¾myïY·ÉiS¼e2tešV—Øúkž=×0K½ôeµA€ÇQ]µ_F] ºÓ;PI°ZµUi”õʶÛÕCɺˣŠû¨I”*‰¦I’·¦©²a'P}ß|œÿq> (äyzKÅ¡—i˪ 2¿m–sOm`‚®†¥‡¢ÕÛZ?@;Ãæn›[¸½ÌhcÄÝÓL]#´²F‡·w˜~¶KÄÆÂõ#$Z+È®9>+6é#C_ç=0æÔKL¦µ7YÞ…jˆÒ¼Ýg×(¿î&/¿ë‚ùA³¢»¬-Ú"¯PÃo)‡[0‹&˜ï27¦*¸ZšW=°bh gÀ´UôpÕcé¨+æýI« ô¾B°‹mZ×ÏYºÐ©õÔè_÷ýGõ¬:M[U«B›æªsCÍG`”¢-(l2NLo5xGš½4:x×Ö¢ôÞ,Á»›üDEûh« &«U¥–e¯¢š=ïz»Í-]©jËTýg@=ê•ÔýÜ™ÿ±þõ5¢äV™›(d,© #¯6ÆWÂ;#Á9| jC*™N+ùíÔb©b`»u—}3®.a¡0›Fß¡k`6†@г2r» SâË5ÇãÛÀ ñºtUvÅìO¸º·OrP´Õm¹¡fâ€Üê:Œ`‚«ÊÃì[¢\Ú8=z|±'´’ܲvà70ò0{?4ù¼ à2ÁdRWJå Àóòó0z£;nVXÖÛ€ºDªO*©”Ì;4¾²+®ÇòK•€ÒPoÊ]m=¾Ûs¦}ÅP?Ò#?ëXstc^Pþ¿‚(·Nº._]Ùæªâè¡`¬†ônkkìkP§¨Ä»LocØùüZN©öÞ†^£þßàlã~êé:àjYÕV(üŸäxV% L:‹\–Xj㉸ÏX JåMVRkT¨÷&«…=$šZóÐÔýVêì×CGI´…M¶õFƒ®×²4ãaJãI… .+KÈÕPtî)+“kÖïÔê×Ë.ERU‚uL 2¥‡rZœ#|1õÁö¦úXønmS%×fÔÇ6©QweÚ)K½öÛcCi&Íà+ÄBù<á/q\|Y« _îæÇÆn·=“®˜¬^áÜÙ¨•-l‹*{¿ÚÚmAA×ÔÒà 1ÓàÀx´ÚÊf¥oäd:æ<ÆÑ²¬†µtQágoøÉé„Ú-FXZoÀ‚Uª:ß+çëm#;‹W­¶­ç9‡–̵­Âžcþ|~¯¶eÿ”ƒ.í:S®dl]òÞ6g¼T+²Œ)ú(K6›EÅÖ& ìn·§ÑÝÏ?SH7Œ 0¸/Õ:Ãr{†Ë<,N»&ûŒ.QNªR ÒD®÷•M¡þÜÐQ·À¨¦ S&åü0M›Ûóo´owFšûÒ¦¹®k`y“E¥jpœ‹U`+I«ŠC²±§¦÷‡c;,[ž+¦ARålC&~Ä#µs·G_ÙmHWZ76Ë  èªsþYI£üŸ±3QE[• s„ Ì:-³´ê©zt<î«oÛþ¸ÏÃäÐ3Œ]ooí³Q^ØlF1[£ ©š‹á–nxÕyè2UQl Øyà¥Û˜)*Ì-i©×h<¡É± 7­6B-jûB?t±RyNfÌÔÁõnTÈ)ò}˜Ú¶ }#ËâÂÜÚ;?vߨΊWŒ¼%¸‘úðýúäo¤rã¨K¿eæWÐ{€€\íói¤rZnKÁ­‡ia†ÇãÏÌ!Rû Hcj„‘QšÌuÇÔ¶×R˜z¸kÍ;péÛs=½Õñ0O%Ûú ª4ÊÇÛëÏ2,ǦÉcWwU‡í‚Âj%ÿ!ÏÔÇÌ7“¤Âó ¥¶û¾ª»à ù3ÌõmAùiÐ[š`˜° ZCç¤|AÙΖ@äiˆ»5"·–ä +gç½ì“’V:õ Õ ªÄn¹§¶é`j+3Ç ŠÁUZ6û ØhYÅV@èPxsb/-ÌñO0HØ>ùw˜ef>ü|QÌCÀ”™U{æ¥6ºóR·•)Ã6Ýôô6ugëWv¾"1g8Ü¥¶¬˜Áù“ðÚÓ@S±Ù¸;Ø¿Gævó£‡àÕÉW:qqTéýˆÚm?ãp>žjfÃì¹™«û4zìÛc±õö¥‹ýë¹ÝëïÿúÚHkÈå˜ÞRZ°rzªÇY hÖ\·1Zlu¾u`)”½ÛµŠüØ«oí›N)YÈ8í½ú -d+íH²!̃O­RDw«åÌøþçëõz)]1,uàÀ€š«¢ìw#Ûê×i98‡‘ˆ:»vºP)WV™UjüÛ¢ôj*ÇAaÒAÑ/áUT[®OLk§ßÌ"‘@7ˆlƒ¼M£›uÀëÉpupáP¤ {IS|qTÿ…ÙΣñL ™'¶¶©Î}¾ÂœÓ¤&p³Ú¸‘­åOk›÷–Óô· *j*9 ÙÌÐÖ…´qp/èªì†×²r»O§sÀ<¶8\²èjNFãÓ“¿/]Eƒa¹«Ê“€Šk« éYɼ6sÀMàL¹ ,wg®!w“éŠ*ë¤1Êhàô¡kК­í±6D¶á'ň3C9}°x¡Þæ<1¥©²0& 3Ý>¬] ýÑüUd}™ÒÐÜLh|/Ý/Ý ÖR†¥Ñ£XI7~»óÙžò~G‘4-ÄÎ_OèÕA„dž]áÖ¥f4†"€û’ˆP©RT¾‹v´– ÈVÇÔ°$¦ÓÐïflúPê!­Z}†'ã]gŸEºqnRyV÷f3ï¢Ý˜aŠIô@õr+Jƒ¡›^¶Sæõ6=[÷!Ü,«Ú*!ßÕ(ë3‰s}LìÓ–“Šm×{ÿ~Í ïœ×iâÌï Ýg´4ÄîfSóÞî¯ÿß?7<©1ÙB§,æ] Y]ïXœ´ÜǾäºgŒ­ªníZí8Tô‚¾Žþ•ß¿ï÷×2¬·ãñÜB0àNŠv³»gŒ“'õ¸œTÙgp!±1£«Xª‡ æg”¼í«[`,ÇÃ@côþ ô™Ó4FHíŒM垈ªÉ§j%Xú9#?8ôîMyË|ùt䣢iüº…-è"ÔÌû°ôuíÙ^ßwîÔ7©dñœÂM0¤NÉžÁîÊ$ ÇX,‡¢]7I\ót~ÖÇbØGʾSÝ%¨§–»J¾0X?ž¨ÊÁ÷ŸLséÍúJ·:•v–AâoRZ¨cÖQ¹Â¼l†#pשÔÖÏêa•—®á¯ºXÍ|¹‡•} Æ§?«®Sõn*òˆKšDL)¾ê:²¢¨ÙÓ· "=æóÅ¿Uæ~†½RëÉlÈù•õ°7ÌœºäD¡ÑøëºN‹>Óoít?¯Ågž·ôÞzb ZóÏK®qŒÕ¯Â.Owp UAéý޳}œâ^ËF‚³eâΜi¢nÊ«G—DÌŠ÷¤2É/Œ&!ò9oÊŽ?#¸)LØr-¼€tŸÌ€1ÀdÙz0Ý öÍ©^û›‰ZT^~Çé5*òËõú;¡ríFp'a¡' ÚôèMÛp2]q 1kú¿¯h7.*ók±¬Cøf¸ˆœÍ»û^wß}3‚݆.ízöiù(”©{€ïûMr<æê`W¤ T£®ò-Ó6€&×  ï¶1‹…£¯—} 4ˆ²œ•q±q03açòKìâ=‚ëBjÔ—¢[ö Gy³Ìo í~Ê ]*~4CŸam¹]ÖVÎVçÆû£\¡zZÚDýi%áÊ,ã9øuåƒKãÆ±´©|4SÚ“J•ᔡ$v'„¡NœQWkßc2Íq¾tÀ*œ—]+La¼Ù…ÐEL$,_ñÃKó£·ÂBEh\ôLÒMWwû~Ùâü\Ò¶ào¬úÂ\Òûrüù?x±®/tˆU r¼þüçôJìy0‚Ó?æ:NAÛ*…4~y¼«'b… ›Væ(}ÏÞKO2uµ’t¿˜þ,°h(¨^5ïcQP¬ºÛç€~u kõ#U—¤b9VhˆJÙœœM؈9פo8Ãme^ç¤f/ªbrçolfÄ´ß–’¬0ô»¿Æ¨Ed˜Š•LñÓ‹®øaØ}ñ+¹TÄ#üa(/uÜùKÔ¤†£Ðw"ªõ™-¯;ŠÈCç‡'÷CØpã‚—«î7)ݾ1ûƒ+QÎ`¡õÖ~{/ÔkÅÔÚc¿¢‹.&)…«ëqL­ ë_›=nU×(¯ó˵H®Yq«"eûêÑ‘ µ ¬¼îV-P?Õpò‹©mï[ãíàÉó¸Ã„_³>ø¤ðyS^Óq4yQØÊô.݆Ÿ0‹™ÛÂÃÔÅuš\®ýö|"kÊžÜÎÓ~šðL½G;U_ìS—çÎWõ¤;—êÝ¥Bòm,½ÊøN‘›s?6õÝÙû#¬N3/Ó¶:HbÉï‹j—X¡áÇíe5»2>)d÷STèaMûì’÷Ëñ²ªÔÓýûû¹¢f7+™ì }¸e=ª£.f…‚ÞÊ* ,¬§€³Æ8E˜µ÷ƒa£Ì𡆹Î@£ñÁ›Â<Ò¨.ÊÓ¥‡y¸W)áÖ×y³É¶ëIåÕ&ï]ö‹¡øL†ñ÷gß^®žÅlLêÏãÜWQ·ºùµÏÏc\†’v: î´Ln‹* ”v=*p•O¿ms˜p¶î”ûßÿý÷EÐXO‘瀘|Ô.%8óô°.šEKÝq1è^Á(ŒjÌ[SfUéß·Õ»in“O½ÈDɾ ¨Sp LÔðÕí%i*ðöìýt ‹Ñ<ë_5‰ÿª¾ëùy: i†°N³¢ž;½ÐøÓÏqÎÄ¡Õ<1ÍjPMÚ5·ÆB™õyÑ„0/²Ï¢·aŸ6;xÁÇò¸«P1iˆwúà`|:¼…›Ùæq˜•Nšâ#Ž/©^y¢o Ö¢=ÓF˜gE¥ bTd%sÃÇ< FÃ@pLO.àTÃ,ðü ªƒ?6,Ié 3Åßp®Y–P»±E;m Í·Ì!3èï9UÔÛÐb ¢m6"té)Gl„ŠºlœÑâÒ°ì®_Ô«ë^t¹7–H­g:|‚ø¡)ݧÅü"¾ccé9ç„9£ø?4ÜPƒÅêr KëÝ* †¾•!Ô™¶¸a¨¹~UBì]LÕÈÁ½ FMC¨ŠzcÙ™ƒT9À7†­E £¼y^@lîºA…ÎìT*œè÷¤:¶4Hô]¨Ð4e;›3®:³„²²q.›{äÙéÌö,æAÿ*U¨«€_ÁUIåå¥ÜÕ ïÂ\דrç1š´³#”p‹SÏù؂ךy§>¿þl¶8߯Àë¡| â^Á€Rűºï"®—ní@uËÐ3a‰à2&¨ÕÀôû+u˜E˜ZÃbƒsÙ .Xʽí¥v?à X¼¥és”ˆH€T¥ëU²°þ™µ¨?žzä·=)HªµÐ?¡(B_·×£ˆCŽÝ™ÊÔŠߌ*œ"—¦i "‚0×åâT¢·.É©ŸòÒ–ëY ,?-ˤV´Ë­AŸÀÖç|!46›Á»úÎøª{°c͉^F†~˜r©6”º©‹­1 9<Ìw@&1•Á8¾ÙwÚL|»ÓújÆvìÕô—Šïßøf†sA­=þT&Oßjÿq-Ž?£ü”õ<Ö·“ê4Ms‚Õzj±ÎaMüÖžóÔòú÷}€J‚ Pª.v Ë6n ª±ÿĸíúßFoS€¾ïÇÓЗÏ/+òuÁ`\ß3 ”9ñèk0½â‰¤ÇÈè w¢h@.ŠŽÆ©žìZ;9V…*Á-}Žrµ +?Šei°úVߨ\ŸFÓR7ôTwÁ¾ï/…Ñl†IW˜­zꖘĀîþ óƘYyoŠêuiw (8¦x ¹6^H*aÚ«Ú±lz.fý\”Aa[×§ò“³+\Ö#jôz#cﺨà©ërt•ïp JÑÅ«‹8Ô™30‹=EFœ¹6NU2lÛëùúóý¼?T ?¦~ÿŸ7F6¦ð¼žgÁ{Eq \†?B‘õ<ÌÛî s“}¿m™eMó ÃAÕ¯;Æ‹wNÌ8`öd.Ù\æeуŒÒÊ/ÖþÁÐcjÂûý­co->éË~ÃT†ÉYf8=¿«BN—éRQ¸7Îj-†WËŽC“ vRŠ"÷`‚ò¿T®†|¦|zùºÂqR•gMkû2bnÞa¦ÜY׿Zãlè Ue*ºÑ‘åÚIÑj@¹dy½M-/ar5j¡Lœ©uG_'QBËÏÊHo=ÓÑP˜·©Áu2$fUŒ3z‹vºé{píuRNÁ¨S¶cmiÍèê”\Ù«·Í`¥AG¬§>÷ózC+¢GĤ¤GÿÜ|mû­·’}4Ï[ÝüÛfú]´+êðÿ(Cñ^W&¢4™!(³¡Í »NÛëµÍÛM9‡ãŠä8޽hËnZ½áÓwý¦r{±óª6«ÅïBÝ©ªXŒXÕçQíè4ö-ô÷S´,¥s/S‰ÚæjÝÃãRoAŽàñ´½B0Ô6ÔÒÄ-ñz3<²êƯ¯c9ý[÷ã-RfY:œÈ\ŒÕƒ$Šsª³ |(ùÃqŒ£ê–ö:]ÃŒÖßÑŠõ•Ï3øíèV§«Ð‡=ó[à•E¥;l{:6ñ­Õ[憖ϊN|ñܺÎ:MÄ©P¬¨O .9æa†<rþ)^Z¬?”Aò0-äñ5¿lKÏš€ñ^çRŠõ¢Ô•$”¼Í¤š»ÿÀŠA7s‹¾ñ¡+ôï?߯çãùô•9¹†š?צãÐÚ%¨0GýqðÃÆ>ŽÙd%u+Šû4‡å§éB™Ð÷pNÀÕµ7(í)QŽHѹ6Ò]JdJœc·'zÕÆQ¿ß¬¸%ò€‚¡Õ¶aÕ!Ø“É ó“7Îá0ÏÌy¬™^æe«§Üƒ&å4±£Ásì&/j‡h=EdÖS,k#E*žÓ¹’Íå­)wÛz»p Þ¶‡—YCÛ2PD›KJ©¾Û2´&Ëáûƒ^Ci4oƒ>#ZVú„9¸‚«)Ô»©A÷viêÂûóbVõú£|¾M½}é"Ea«x–ͺ¾‹Ë3Ì©5\ŠÅ¸â¶°Ån]jXÊÕ,|r 1i…wçŸû~;æå†…§žBI «3„uëÊïÅ´Ú+“ÿy˜Xç:¾Ò{²°CI¥Js R5ð;“ò*Œ÷ˆKÞ¨r‹“5AÏ€J1_“aóÁ“7“+ê©%èJ|QÊ$ØõA.ÐÓM‘óþ> ‡Rå2–\>¢¤³=·7¢ÃÀ~ÎV7UYÓŒ|reN._qã Ãó7B²ãÉЇöqÎøÉà§Þ¬ÞFvŠ-FU¤v(.§ˆìÕÊ¬È ës³¢Ê÷y4¨ÃÌ–d5ý]v©}‡"tM"ÍóÔöSçU¢Óðâ|WªaR;ø «-„ø»Ú¼Ô.èøUeª’]©ðJ.I[_’kVfÕt !ŠY WtÀ²(&}ÇÌd]`ruNÍØ©°ÄÛš¤<âãzc݉±Ò'˜¥a•Qmèè¸ÆÚ6E»I2åÔYÍ:”!%w;ØÂÏ÷èüêîÛÇÅ»ÑëŠ`‹·”áØU8FY?ä™z{OŽs&keáÊ<¿zM¡Ý¾Ýön¹ï¾o¡Œh4NëÛúIáSóu sD1•ÌÀöxà|SuãP|€¿I²á¥öÝàzz“h6•™Ù²Ô» ¬?g4KÂBÞ… ì&]øvÚ²k“5s“R§4­M ìâM¨PÀòWU¥n¿ÊÏ-"þZ:ýn6Ó’Tû ¢ÜoC«îW=žÑ¼«"Ó|bF ÃMcå몵 }«űúeš{\¢x'7®DªË` 4Nj~ÛZ•QçU”Î0±¾¾_·ÍÜaU,uùõZTBµÀ}Ø|Áx íKƒe â+h?ÎàäÆ< Ëè‘ÏÄ03aÂX§qžüþ­Ò0¾iTÊfzŸU®g’KÌ¢k^$‘.F󸶤lÂÅSg¸;Ô–w›4Ÿ$ñл‡5Ëjm)’”«ÇCa§£IAmæìÀÞ«¯[ÎÔñÖ€³‰=³úÁãñÄ2×ðJâ¦o0S1 ¹Pe»RªúSÀèÈ t9(=ªzèëdbR÷lÕ¸bÔykgòñ:p¡¢ìËß{r7 nðnrÖ¯iS'~U½yÖË¡‰x"~Æ(Ýüä=s¥Æ’eFG+Š];¥·Å€v&{ÒPÃÙ¢\é}T’9PÅÁ‚cÖϦ—é’W[t™®„†¥ŠéËy?4œ´¿‡ùΠïÁfŒ4‹ê;l_gy§/ Ä;$NjZÕY†A޹ WµSìNkoõõ|λŒƒƒéèä6_CíÖÀOÌìtbèÝmDùÖ;ÐaÔ³ª³KEÍdè~=:FN0³Ô‰ 5‡Pùý¦ òþ„§ú]ª©Ï‘Ýù‹µ7Ä"Ë8¢gvºÄÍœ¨1ÉvÅåÌ=® µ¥zHH:*U3¸n¼Ý'“uÁv“’i”ÜTo¦µ¡-v=…äØÕ~é£*LÍ"Ê…ÉBƒˆ¤Æ_(ÐL Ø?TÎø.ˆâ—Œµœ]2I”ê•ú$n`àën[Pê™êë%Õ_E ŽS÷sölÔÒ4úLûe2m5x'º¯—B(¾V³D¶¨³^Äð›ø>ªhÊ˧¢ú÷o¥‡V]>£õTwHòyͲëUXî÷ûŸ»¥" P§NFgæ>bÆÄÖ˜[Oj'nõVí«ÄXçݯ*ÿ¸ú©3$-ÇR:õ‰\Ph²A=4xhý›) ¢V²™Ë0“mr«]åLk‚þJ¥£ÛUy‡t ñ‰[ƒ“Õcá6¯¶´VBä±\QVìŠKÑ—YoœêÛcSÓ€ K“RD~Ó£YíÝÒØœI~Ü;ýÔÜ!kÜ¯×ýö­.´°PÓÒc"­È‚(RåW¬Ñ¸²ßE;¢ë¦¸jð°0‡°hæ˜@ßÍ·}ôû4n›b^EFWwmÙnÈêÙU(àÇš'ÐÊuëòØÊÓòÜt÷ôIÜM”;$ákh–%’NÇ<)$cbÛ:wJXæ s™š‚à5ªêÃö4‚óû+LÚ×ËJ”5Îny¼\U7¶]^ÿù½)?ýG®&Á™6‰‰f!w]1)ƒb g±~(­J­êûó…¼µG^Úxš¿ ­¾$S ]…¦Ì$gt%8æyì›4iÆê_•®”¾å‡t¦/ ×PµvåÛnýþ^*Uý'm0½;ÝþQ^\“ú”ÌÒRÿ_çnu—b˜0Lôyíä»ÙÄ»‡Ä«ê†´7(Eùãñ4™S›.¬£7ckª† Ø`ù^‚µWk³pOÕ¸’‘'«TŒÛš÷3+ D \<=âÒ›C›‰Þ™ü‡Úl³hò€[§£«vÐóÖ^îŽ8Ýa‚¯[ϰâæÊ1M Z…^Ø73‹2—i‹c…Š]˘§U¤tß³é푸Ìèé/ÛýõßßæV7Ú²]-Œ3]óèë×ûˆ‘ÚmñÛóï¿ÿ~MeœÅY?©6Îó8-3ÇÐÄñ¸é;PA~¬U ÷ê/úmí­Íÿ™ÍØ?íq¾¯ý¢TàÕ…i°c©£v{p-ÈHLÑVçn²:ÑmyLÖ1‚õ¸‚ô{ôËè@ªøi½²› qd)'§Œã’EnO*£Æâ|úeâJƒõ•…¹#¥3!QÁѸLw«nåµÁºä»ÇŠ¢ iцã þ¯qZT™-LËÌÀQº“”Â;[‰º¦p“õæ¦Ëxê[÷»Ø@‹W²Ô ž_ƒâ-þÄ}”åÕæbYU*luæzòoêk’Æ—¨ô›JBubK=Ü¿Ÿ«NÍíkwnû2Ñ×° öegsLîõºÿS?…}Ú€q 5¶~‚ëtVÇsµî±ÕªûÍOF¤™ºUç´_VªmêYüúx*Òσö)º¹=eã)¦\7^ÖŽ=È“¢ê-”¬Ûd&Jz¥JµWÑõzHY’òÑ×ãûKQ2UØJèþL{ØÅ~€Ü£§ÜÌ…y×÷ÖÕgžšÔ|‚eã.«ef ßë Ô”êŸ% !L·³ÇÙÄîzp &QÌ€ÐÙ€¬ Z«yRø©×U’åã: öÕøÕ†EA VmÁ¸?ã1º§šT¶ŒKPy8î©»î÷ÛÜ­ú óÖûƼσökƒ04j(U­ðί™R,ë‡ùxí˜%ÝvºMakƒvŠö0뙌`ª_¿««õfX—i .Aû TÓ Úju87ìJ¥ŒoÀ¾ÏR•‰1¢®8Ä Þȶ’ƒŸTXô(â,ªàC‡ ! *Ö°VÝÒa¢8ÓmNsfø(Uüz“³sîÝ¢ÂåšMÚ¾Gݵinæׇ‘F¾¾ÄQ«b1–¦Pgt ¹ij:ŸqfôP®Dµ!@-&GE£›·£ÉÛtÈ/½$L웳p$;ØŠt©*t!uy–^³¦úˆ³¬VGº:jý Ÿ žR]¯×KdKÁ*° ñ„ÌaÔÆí:ñ'µdžÎl¾¾Œ'œå͞е*Ëèw\Š2VÝ[©Ñ÷a€"Ü}º[µn<çœÕ ¿¶¥éÖÛTMÁx~1qÛ¶ØÎ~Åm䕱ŸN¬~Åó8²¨GE.KåÃÇsîÆç÷î tÂÐqjûû÷ÑoÁ`ùû‰´âv[ƒ`¨íhûùö2Í%vÁ„S«VX—s©šÖæe=4¨UµC7¢Üг·õ.É ©:¯–UÑ·UÔëﲿ2VXÊù]ï«Ò"õ*&Ý€²Cã»KýÛ©5Èt,ó™ÎC˜ÃF³f´Ýa[«VÒ9ëºi3ƒ ,Ë··OæÝ ˜Õ‘Ч;WM˜¹a°EÃöPóŽý/ßžª$eЦ6ç0&ßzÚé-Ø¡‚‡{‡9˜@ìÅl¬£Î­êÜÉÚbƒŽ¬vaº×½aÔgp˜!]X>Åa[ßœ ¤+j7m­7¾CÝ–Š±eE,eŸç>ªAÞó©ehÖAzXI¢·§ÒMwleêÜÌ0nwÀÁ–Ôh6ÅõÄ›µ#…Áv"qÂ4ŸC®£äˆ•èlœ]…y¦Š!DÑÝ¢cåµKêèZwꙇÐߦF(¯ÊëupIB-¬®2)¹®ßF=ᦟâ´fdÔ¶h™Úç™°ïay[qCAÉsYyù0n(›gª ¼öË1+„9æR½ Iå ÑЖï07ÍÐÄmr)¸“9v”ãǹ7Ói}…0÷AI×/&ôª?5¨ç‚›ðX¿§›‚â½f݉üªbüŠªŠNa[ݸQïB=’xf»®ôŸÒsò‘,ª(ØC?Ðn¸íŸ0ŸlöëɧЉéÿµÆ·kk¯KMå¶í—mŸåŸ—²Fä¨È’8Žƒ_9¿DUL™$*¶l\ŽYšÎupû®Ëâ68Á!¡09Y æ¥Åä¶ò4Çþ8¬Ù] Ùß´$«¢ÊDÿ‚.3ÌOrP)Ì‹é¶ °fcºíó|bÄ}PÅPè ˜6S:ÍÂþ?¾ªÍ‡Xj.*Áù|NFê9‚ÛØ“Øoèù&ivbþj^u)sÀÂü”‹ä’À\Bg.»~¦~]'Ô{õùÞ¸9X¨Ü}5<¿oo'«Ó™ÿ'§à òPT€õ1à Șf4 Ó¾85ÃþlίûP­JÊ%Ó}lüíµu¨ºfÞ¾ì7C[éYÿ}¨²/ú°RÝ{ÖLaÝ$Õ½ –d½…‘²ÖP÷JŒü-D‹  ÜfµÚJ9,à•ñl¼ IÔƒ§óR ×Ö£9R«Š+U3åÕŸ²ñf3FVÇ–øf$ ²œ~Þ4€„²Ô ƒå3÷¦‡¶¦Þ\æŽPVQWv•a{t¼¹e†ýèæQo­ ½úºÛ€ÒJCˆLak¹£ÂŠ“I˜iès_¨}ñé~Šv¼“s.mb F'{í˜f˜—jü™±P›æ¹þpmÞr$ï¢ýaúÎ7SsµÁ"†Wº!›?ŽÙˆ§“‰‰ëÂV77ÖdÄVjlT¥çõÈ:ÈŸ>'†bj‹«8柩­z~/ý¥÷û{÷.Ú'ºËìqB`ƒ]9¨òÎ4Œ:ˆ nk‰B âkQD×ôC Ø¢ W¡5¡²ÀÁRZÌÐ{ûnYÕ¦]Òè’€‚ÉL0 IXàe7.HG§×¸òC0.œ~…k•*é ó©FÕ`.S‚6ÕÃÅèF‰ZŸ1JÏ6”áA¯úq»ëEc7…úu­8T1R!üh–íy« *‘e¢góPGÏ‹áTfc Yäzµ‘‚øšs6‹¯ïu-àEUJdæ’èSa®?ŽV¢”7B¥¾oÊå×ø-Èp¯! '0òŒ]ú.oLmx=¸½™VW]Ò ™iõp¨ýo@Šýpœ˜¿çƒ–Œ4ÐÊ#ØÑ”IÀùùþõÚ²Iz®®ó*‡[¨»ogñèênn€- Ú„¯Y3὚î P*ó{àip,ž]hmJŸ®Ë}_©«P˜m7*j¨¨0×}¯ï9kUXŒm)r7††»Y‚´#Ë[UÁ[E¹ 8k7o¬|1:œŒ;‹Ê "fAâš¡Ž=ÐËš½lX‰Ò7˜¦¿{`mØ­·Íf!©[6 Ô¶ãyŸJòâÏN‡Íö:Xêt7H§½GpfF–j9uˆj¿Z!dìç 0§FpïQàj¼F‹œ‚ˆé1J=§õµõ]Ï\GGÑ©jI’qV½Ñ6-€`=ÁfË|_\2"ÿŠeͬ°,iäà9ÈO†Ü zRÕhµÓ73â„0IcSĵKõ4#5_M`~¤L¶pPÆÚÔv^CÕ+3#[¶(®"ª„éoïP:Í¢ôò™²H) Õ(›ƒSŽ c€W«6H‡AãaüÖþ!ÌÙÚ—ê›i“f.Ï;õ㺒¼m”±te¤ÐëÔŠ+ë¥Þ«ìQ¦É®UªË%Q÷¨ÂAG•Oá/Žt†¾§woܙѨBnµ>ˆEÕÈrd×}ò‘­ÚüZû,îÊ EJ¤–åã÷%ëpBÝñ¾Pº0 OWèZí[!I»Zlã81,\ˆ¡e‡-ºÓ&o sø[óÒ YeÏî8å)ði^‘T½õ߯ÛRã~&Ž::O7™ïî°1îwaÑÚF­ ÝRç“véŠ!Ëú¡¬·Uö®h|¦ÿo·>îÛ¤¢  ø•üÇÇß_÷ÛÒíØ›«gû膨}OëÝtä†v»óXÑSey˜ƒÛÆú»—{6æíé§§`Ó(µkýìuþ Mò¡/738á d²³–eë;\²ý´†ÞLú¹ÃÝ÷ú³Pcü¦Ãlü›üÉl~jN—@yIÌïÒ¤coùøz¡Ê.JYZ¯ß߯›1mu÷ÞÍê´¬|Ó†×íäŒÜ¾^·íxÀká*ÖM 1ÀÄ©w:ŠtEš¥©â«?nÞĪô–=z¿^MÄŽ*ûdß\ªTÄYR¯µ7éI•@Æäâ µ]=d½FÃ[%HìäˆÞ+é4ÕÔ¨½¦elª; ÀÚX…äy†¨Ô ¨ƒž“Z$ˆ©•U-C(±>—,*ÓkÒÔQT! ®—æ+Õ±:ž¸fÓ^“8+ÁYŒøµ»_MHA*¦ÄÝ Œqªn\M¶âžf¸ÓŧçÑê›êëï¨Bå«”1.“NrЬJ“H½Xýa$S¼ u‘H/¡AÌ(c¦ƒŽ±AøÐ­f³ÑqŽU·Ý§Õ#¬“1埜DqÒèè‘G×2àZÂ;ò¸YÒCÞU½`½­š s`Uù ,¨Ï0ˆ_ êj^×]fZMɵÙ& ¥2‡µÌ2…¬^{€…¾å NËÇG0Í]–û¬J§ù¼&ƒ‹üÒpê"Ía‰YN˜WƒÉ±6†*íLÇ ¸7Ž–®M5€oB¹f a΄NW[zçD6E]&Æú8A¯½ÿe†–0dly‘§U–·-ÊæÐÓMÊzâ8ìRðŽÕïÏ܇Aý4ØD cœnÜÄ‚5»iQÕÖjUæ©ïï5û´Ô˜HlÁúû!|Z•aqdÚt dsµ~Yù¤îò8M#5)¼àÏ -çùóóÉÔ€ËBoPdroƒ^/{3J£íëßdqûøM¡d'ôÕæºÃ+•##Ôî9pæ ¶®ïîk [$žâ2ï'šr5OÀuÆ'½l×®ÌÂúÄwi=zè)¦_ï ÃêìœB@œy£dÒûv:݃KF‚«®7æ¶L ÓÝv?m°’1F¿"‡¯<UŸƒñAþ¾ ¬è¶©Þb¬[¿5¼ì>…[(²çÑ›8¼^^må+T0àú)Ë®Š•Ý•ü˜q? µÍ±•*ëk»®Ã¸ãF8Ü úK?ð‡=H ¾e þ¼‚uûë®r¿W¾ªIÞºÖºªJ‘p T‚Å\¥0W¸/è%ûãWÜŒŒîâ.c©éïoÉÁ*8tXæg,D”wŠõŸlnÒkuÙ×ï0SöŸjã s½ s$å²!¨!ªÃ{®ìÁÀ dkàÕïë]MLc°<0ôMÚÂØ¨Æ;[˜Xš–.ÔÉWmÀăC Ì=ÜŒËü£ƒ7vø ˆžW¦NÛuãÜZaF2i×w. w­+»5Ìjà¹YA¨Ô™tSnf­yÛæ·<ÈrÚö¼ß÷aOe AÓaö¦>Ðu*†}뤨>Òaq~1&„I‹M*Uœ‰Ûò§pN+{Ó9"Ì£(»5(ÏLvýOA»u=Ͳï7‚ý%Ki:óÓöüþÚûú±ÙÍ¥¯—Zìk©O£¤¤©èñìÚÓk"ÌçÑÀÒ ôæ<çNwÍ6Q³½,·Ù¤CÌf×êæ:8 —½Q;ýôó™kŒå³¾µWш·g­q¼T7>g’~a‰'§ÖÈÏMP®0ýF„«Á¸è–àö7$T›ªìp×ýÍf!5öUVˆYµ¹2ìI8 ¬âÍŒÌÞaw¢€ç}¤÷u½iG“2l¤&Aç稻;°Òa gµ`^22-V×cþõІÁø s»JtÂj }4ßî¶±‘$.ÆƵ`æQ3<í ENär¢''—a+ÈE+6;•Œø%²Ð‰í¦SA<œ5H:"çµ<õZuÿ&é53ÝDeî–# ±¤P“ÆD€Þ_| ”·´éçl¤Q*¨òrŠ “Û`ì­ûŸÛ¢iÓȪ_¾h4¢"»æóŠ–Dma^]ËNŸŸ.)µØŽ5ݪo(YPmðø£N>ìÂ1ÀP…fTq]ý£ÞD3Z·³{ílô"]UÃ{}Rtçf¼¢\LßYyÜ…„Q’D‰‘Ôu£ Àߤ]‘tÐ6A½Æº£"…ùçµ1°Ù q'@l À †7lØ™He†9<)` ·2!Bá*˼ÈęS6ƦhPëuv3Jî3*kða·¬iÜBÛðÆ\8 ªæÛ—ÁdtmÌÓÖdUÞfì/ÛæϬ*-¬±ê`8z0^£ËÐ1Å™[HqÔ©l­u#|¦}ëoÛþ¼­¨Ü:iEd`•+Üz™ù óe¢¨î½•Þ'‘Vë?R}7“TÐëfŸ¬N!5¾:üÅ ‹ gTúr˜e2CKÞë¼Ä!Ä¡7³8Nwã"IèÐ2sêS%¥ë6¿´.W¢+À:)¢1×tGU…õó·2¦ªpxW†¶¬Ø¡Ã2¡WÝÉ µãY£^ƒwòº/CPC± ÇG}7¬¯ûúXM¡r½ma%7YRDž`=‹Ð ¹¶l'ÝxZN–Hï’¤SI¥"P—v)OƒªJCS¨ìŠ&'—3œƒ ¢Ú©¾Ö*È\½ÝÔLÜ•ò] ÈŠ‚˜¾{‡¹î ŒùߢÄoäåþÏèò›Fõ9S›æqqŽy̪øÑ¹¨ýbÂÔfsó0P‰e:8ìYͱ£j]²9ƒ42m+Åãó.© ÙÍOAZ÷aMòñë eÓ6”ˆ©ôÿæWe;ܽ ó2ÃMûj²„wæÁ¢ùjº*‰¢´ž¶ ÍÇ6ׯ–¬@ÌX.ØsƒÄ`<Îøòy¶©À`«Y¸Å£`‘´ØVÏÇÀE.Õy’Óx©ÛTiwìühòªÅ¤·ÃüÖÑ~;9,Ar‘³›Ú¸y§ÅR9w)T$«ÎØ¾Š ažåP„PômÎYV0F5@©E= Ï!W®j’´óKV%×ì#Âgˆye¢Ôa~µë|A~fº©BeÜFE~¾¼*Ù+®+Ä= Ýo_Ï› Ø-¯£Ó¬¦©ŸûÕ»‚9©J(]L£Š©RúüÕA,Jy+Ëã&»šn›òµ Ò‚éxk‘bÂ3ýùeFÂÝÅ%Êp“S…«¢0­êÞ’Gÿ-1ì,Šþú_É ð,²¦ÓÑsa6¶]~¹͵©S=ŒÄFzÈÆ}~Ò³oܼŽ-B$@çÆNw2jÆ-¾E7›‘ÆxG'ÙªnÞnï=ºaµõ_?½§Íx¦±é²˜,P£í˜Ç†m%¶yûÞqÆXGݳ , “8ÓŽ„lgŠqÁ4¨ÀÌ4¾…T‡µAYX+ÍçäW•”J3å × }ôP­¡º ~=4sJE¥.G” Gæ­qÚCåhUó¦Íª|펦ZÖ*w¬ÇúU™ï¯f‚˜,-7ÏÜ%ÍZ²ŽÄ4ôÛ9¡Ž1ýõ xù=ŽQ*J™+é¹*κ4õäÉÑMi×}Õôà¢ç¾d‹@ÝwÖÍ©_mÆ7üÅŠ¼g"‚Ÿœû¼ú^•Ií¸ „(ª—±¨t,T¡àfÎG«GHƒ_7¿J§Ã_w@ æ]¯‹mÞS&ÝÍ™«BìS¿8o^÷Ù5.>“°çõE±ä> ´]¥U’žfO $£¨Er©Ã˜Ä 2ï/´¸ñ(¦˜¼¡ÿ—¥’³‡ƒlÃC-™T.ÖE^õ~2 "+[ó4[û톿ˆ'¨cx;úKº‹HÊâzÑg]º·Ñ2U¾UýƒiYÈg ó®´Âü'Ð×Å&ô6dšqÝþçˆIa®’FO¯I0œê<ˆvVg°D:—±â~á`MQ~a—Ô±47!Ü“qg—lív/(kÓÕ”Í`QŽ2¬Ç* ©ÆòZŽM©^½U2ÇÅò\(™ˆõàm¡±˜]…¼Ú»0üsaÌ7¨†Žo6ØÒÚÛzøa:‰Œü›"*¦s!oà—Û‚DxQ(ÝÔ@·ú77“}Q-Ä>yY™ÿ­O°gf8 ‚ÉÑÞQÕéý 1*!ÔY½Œs°x [Eé|•y€˜ŠŽŠ(F¦æŒwNºƒ9Ÿa>Ÿh¡yjôÞã+EÉÛ&ûj4¬*R[¥ö¨~íÚyVŠGEÕäœâ¼ø,ïwr¢oN]™ëTŵjÒ#ûýÞ¡W¤·Þ£×Ñ ƒYèª4Õ7O¡0YðœFæM~‹ÉeÖ2AOÙgó n9f[e­§Ü´‰i¾´#–sô1©áÐëka>ðjØé7Àïë¼™¦–5k7paƒýÅÁ1†W·ÝE T¥ÝˆÈŸU°X•;?»q@ÜòË_ŸY‹' s8ý‘8»DuÅzW=ø¸ŒÑ½AÅ¿ ¦4ú1ª\«°Wr~!ôXD•Ùõ’¨ÖŽ& ¤þXÅ%Åb£Z-*Q7 VI“MXÈ´ªú­vu õ!—ÂÆôÊ;E+¦e•\f1x!ûe†m «ôÌãï1E)øZ† Óq?[ïýŽËãùÜÃdg ¯=°v d÷æv… µ> |£Ì7±[tauyá{X,æ†râ˜eì°§Úô+Šu.|gµžš&›ƒë —¦ÕÔŽŠ ,6ÍTÁÖ©¨7©¶*=ߦó<_ç·g˜…¹þy;å…mưM=ÐXlžÆªSmâÞš‡õí)|߃{3-+7FÔc…še ¼1~tžr¤ÆH¡P]´fJp¯m˜ï¯cBä_2ë#lÎÙ¹);øš­mAÆÉi°rjuÑ«\¬²"U - ãòêƒFÁ€2ra„䟮ޤýN¥sÖ÷óýü 8¹u©#–¤¬ROYZƒ†Vç9Õ1 ³ÎLw‘\ E'D¥"3qSb½bS4C^µ¢>TWÔ`Æœ31 ˜ZÁº7ŸMÞ ýPF׊½`•Њ•&úÇr+‡û‘¡ã“_Èsg5Kcf¶Ó ÖãGªc€¾&úk c…MSš©reÔ¬OŠ0U˜ÁH€‡bèÐaøe`,¥Ín1 %²ó ÚIä;Ÿ1rôy·,dV½îªÞh ñi ùüÌ™Ž+Ä›œ|na^0ž‘-kiŸ­Ê~gU('£Âзo÷çé®)87V>çÝvFùý@Ü[¿ ìvG˜fEåg¬$©üñwz<å8é,aÇè@nAiNí2üw¤ß†&x蓸fÑu­sôñ5ŠFô.M†ƒlªÌ᳘\Ò4ÝÈ·ÃM§ð“Þaب ‡4&¤nD޲ÑnÖv2$ü\GVJúŠSoŒ…YÁªØ» ‡¸×´›|) }þÎÛ#0î»…ßì–Ç Ÿ½ûãùØ%š8(.›ö^]gFiÂÿ°¢«Nk¦ý™5¶&ÙS2ëª&¤¼»\¤Ï‘Ñqd™ û‘}$Îhb¥áU3Ôeúm‹lj3x7ºžY ÷¿€Y³F,ˆœín»NÓ/Œe\¸((2×MÝЭ[ ã›7©~· f2êú£âf£Î ¯’ÆÖja˜J±€µAÝ7¬ÉûŸ,¸™û^Áõ#i°|ŒTˆ$¦ø†$û—,æÃ-!ÂD±*pZ­z²Þ§ž€ñhØ3·ÆÎÐÀgÛ” ³¬ôÊ •·Zw@‹Ãù|åæý¶øÆ¯÷Wƒ^ŽÚS³Êø”|Ýlþßfº~zpqÈÁO¾¿&³inAlÍ<%–ªÌ„W­øó¾hNDA®$ÎsBŽÿä cö»ÉÆ/r`†avZ™rìà«ûó ·2ŽþtŸ ¬Qô[m–‡½ÀY´ÛWˆñûŠÝ15yˆlÌq“~õ)úoòk~ ÂO·ÇJÓ…ïŠsý6³Õ¢ô{§Ù7[µ¢©wÌÈOM• “° 4~îqº&L ùŒñÎ7DñtÇŒ¡µŠe°Ú6ªAìlâ Ù\]ûJÜF×&„}óY‡¶m…/Ö_fÒ—¨C>+t£ì¼gÿ„ùÝüŸ¯«Dížiéù |dmÇTf_TYDZòå j×·ö”_¨²(­&¼Œæè¯”—,”Þ•zÊëg> ]¸Ý^ßP‡^ÍN„8zþý÷÷cÙx‰ƒ#ùO˜3DWÏ‚Ë=­€Á©»§W×õu¡·ëBoG7¥SSg \5”,xu<ò¤ü¸èrÀÝ8ƒ2Vf(N°>sm–umzAP³ qŠv§ÂV5¶>Âõû+xà ¦Ú2¸ò6µ ­u™ nYÐ^ SâU˜6ã¸Û®PšµÛ5ÕݱBB/ÏœL [ᣠGe1ÂüÍ V²×$cȦºP%Ac ¡ª­tcS˜—¹ },×ôãªÛepX"æ;}—ê'—¾ë7°E¬è±ú*»ú³Cv„B° ––W½ŒFÁ2÷×sëë¬oÜOoâòÉè sjÚK3[šÞ{t³à:¹Æ|éqO8 ˜ÅdÑ6—É'5– Ak£Ö§ïº´6—_ŠÓ\oÚ©àö¹®‚,÷hÕ!›öXtšô§”sPûh¢F5+’æ¾7:{6üŠˆ{eúòÏÏ©)œ³<¨’qòЇ GRÿµø¡¢*˜»À`mº@€Ç@_ ÚÙ‚jÜÍuiÏZeíÈ`£dÇý6vèŠÆUŽ.Õ]Ï)‰Sô-à2Ì ôù`êÊ(¾Vw³c£]l¼i+“ ûs[uªGV•ø™@ bF¦#OîÑ„Tí”(94Ìp™K¶Áõ‚œ¡ó1ÓŽù·¯³ åÃTð+¼ €õ<7v¬0`çãë?ÿë êÀ¥¦!Aå:’?E»Xʈc§®5õ(Š0½Å¢ç![b¬*KuuÛb^4õdáÉceª¨ðîw`7VÔÍæ5<²¥PBT²oôró–\Ñ6¿ª®/.•S¦ÕòõœñlííŸë¸}Ó–N¹gôó Û§n©3ð)Ì; Úu+LÎô)¶zmR’ŒC˜óJñ!`Æ©ÿwÆífv~ña+’sì$ È#§€¯3Ö-þºdó2`ì“ë¥4é™dq©»qÛÞбœûùŽá¼Jù‚BøZ™ tË' §hWºa ¾ä‹=&¸ƒUÌí•L–<ñQžÎáͦsp‰±þýhŽyl–fø§Ovõ˜/:œ ›ç Û±ye N[ƒÁ-³Ëµbg´x ö¶hÜÆîfªÎCG#ßf×Ϥbÿ3‚sØqÔ1¡˜€Y3ÊXç´Ê̱³ó¯ PàPµÕ3@o 6¿Œ5VGñµí>r(¨÷U×j Be|ò£/T–Ãø\¯®ì™éFΊ^Á¢ó×V¶€Ëx…ˆB¦ÈÒo”ì; ê´æÑçg] ˜·¡7×½F•Öšïµ-ÔìÃÕG[Dõäûý¦>x¾Ýæ®t¹uý¤Ô³oƒ½B̓þä «Bµ]†a/˜r›Nb/¦™S”ÒgV!1¼ù”0×íiöO*/oÿß0G Œ›•ììÉ×uzÓ^ôå']ºYY_ê6ë5K¹Jd•eQ„ŒóÈ Éç>ð«6«»¢PÔEFÊ!øí®lÞ¢‘{RØËç]¥\ƒ1„ãÕ…õ ½š>ú¬!Ì·äãiz?Lêõù|=¬9Ÿ‹¶SŇÔ‹k×^`]!‰¤ó7192¼ëNo}[ñ¡ÛggöŠE3îßþ|=v4Ôð<Ð÷èÑô¦? Ïl¾at»`‰h+‡êôÛ>Z‰‹uRÏ4Ñàe 8­xüØ›ÒÇ0ÜŸÇs»/{ß4qÜÃ8Šø\¯ ZX I¤f'Ž”û{™˜§·ŠÍÏB ½`奨¢ ,ú¸°Q½«{€ë`(HÒ®¤û¾®<¢˜LÉŠjÄDU‰Ž±Ë8VŸ‰O®ËGÕ—zœÕúöLÔ¾EPOÌ€Yû]¸»>æu.Ԡ䪲ºN°‹Ô‰¤7Ï‘ÉÒpé†"sùÕÏ•yJu˜#ֺ╖ÛÌt¿IrŒ”â<ÓÅ—ÄEÛä&²¦ˆpª¸Ql*b†aøýRuPF&¬ª”»^çö|®ä\½æûs2â¬S/ƒä©®º^! þØœI/Q ^¢­§/qm¸¡‚•›¾_™™ôíibZIz6ëŠÊñV“À?Ú,U[\‹®ø]«þï¬YË!ü9 4ú¹‰Ê%WUÀ, q[t1ëbòƒ©Œíè¢Ï¢NÕá%i“ÿ‹&®@=÷=oKRëyÝæÁL~_MŒ2Q’0;Üò¹>LX¾ìâüzÑOI±·©Ê_>²ŒHm«JdÃy¨É,ѬÄáp1¥Ï"LüOµH™6PBÍ-Rõ¯‰E)Þè#t*}cO>ó¾Ë*%EÐòü›a› }< ±@{ËOßw=ט?‹B­eìÒyê-z3Û˰DDÎLušJøªé—åmÚè¢lëdš÷×ëöž[M¦7Q$Y; >-íC'l…BÛ›Åpäùç¶t=ˆYýÁC]Àt{}…þ磓yávõ«ÐWn ¦¦úkôWfŽú[Õ—ðégÚûÓP˜l†€S7agp~_óŸÀ×;ˆK©ÿ"ïjj«ÑåÍÐphrê‡ôj¶aÇuüûÚLcGãûÓaEÒU¬Ž®Â>™-6ÄCjPÎγ,£LVt%„¨*è^$:VC°¤ ·LOr+ÞXh¸èÍÌ ­,I´µGÅ¥ÒMSçê>WQçN-E_¤U¿”6&¯Ô3ú{Õ5Ážµ²X§ô@&è½÷ ø¾ @AØø˜Z„)73mâÂùgZ9Xô™!5C˜7Ij©>¿sÓ¡úÀrÏéìª'0?/`:Þ€,®â1]’2§N´Ù·Yi›|åǵáë^ùåÌíºÖmSN/]mˆú¾´q™’=ûÖ¾5÷7!M™Å ­Û*ø³Êd Ê(ÛDõÚ´Qç´\Lz(#ÉMOÙî"üÌßBÏA.AÙáäM›¿ O6X«.cs*Zº ³J4¤7x^--˶Œ‹êB#¡¥èU„Íý°ö³Çuæà Ãky|>á ™‡w˜uæMV(>‡Â½u½Dñã ö?ùæÇÍl÷Ç {… k[Õ/ÁV³ Õ°žY(~Wóí>lóî5¥³1ˆ!|z÷7F†aåÀ‰ª æpX îƒ¦&«Úž-ø±ÔäK_‡Gïá4,j󜌞Ÿ¹b×Èr À”%öÀ–*tœ-Æ[>ó=ϪPÝæ¸­ó:öà ¡ÊŽ”DÍ+Íîi^ÄñC®Ò-_{W*Ì}u¹”êŽS#2¡¡Î >žA‡‚‘¾~¾Ãþ°Ä=4ÊÝœ°4áಓîäéš‹©Q(èÐèÍyj «£àbPB*-ºw˜ˆ‹Š:⣠« øÎøzênx; L¥“Zž×~VgЛ̌Év†„ˆ@*)ŠË‡®¥ÆÌr›_(ÄÂK(\ª‡‰ÓTªGž’¡¢¶íg`’u†VPÜØÅÏ›cÃÒƒÂ5F³ÿ¥˜’”[V½q¤‡ Y5®ˆ°‘ÀÕDÁdQ®4‹¯ ÖòêÑèûÅ\­ÂDΔ9Ö‰š¡øów¡TýçÚíSѪDgW•n\U¶Lõ5n>sÎV±¯Ò•7 „Ê^€úÚüóªÊÈ$Ÿ»qÂÿ«5²LÙ¯&* ÒÙ\ZTuTZȾ §¸¡½aBôÓH›£ÉUêê‹£.ª]Õ]œÆJ<éåÓ0œ”uÓºÑ/]2FƒU·ó®XºOÌ"CLï{Ÿ™ÆO3†Pý¸M6”°ßE»íÓ<þ)êq›jhi˰SÚ(èžïuÚúCD=åàL‡ñù¶ô8±ÒHè~ÓÆXjF0`ºš }]'uý8F¼ú5wSW;¿–™Õ Úr%ŸìzîÏW=Ý›l•¢8Êj“ƒŒh§îJ[DV¨-O½5I€©dÎ(cÔˆ¸P5N¹4öMØé>ãÒ  ¤ØÉë¨XDé¥À¶„• î£`žÔ†‘ú-Ä+GàÙ õ<»äÅ  Âf`¬ô35ùRÇå«~°Áó§éíN0!2Ž)½tÁôÔ»%x©Ómpdª[`­%LÈ2A ÔDÏÏ¢Ý'¹,ØÍÎ=V´L3m±ùž6ÈBèŠVèmËÜ3¬c}µÂ }†]Rµ¾üUV k®ªj~)ÆkW)´ººP\|¦n™Ž`PéÝdH¨êôö1UïEXÀ<‚ §ÔÅ÷¥ÉAĈ3P*‰%ò✠•)Šh“œ½VLJæù$TÛú½ÌãN¥zá¹Åj|Ìd° ZxÊ÷©ýè’~üîm—;¹æ`¿¿-½]³_n` ­¦¥_Ðía7&4N¢½>²¯Á22J×#É>¡äQ8‡€ž÷wÜ9Ô¸É,ºã·(äo+Ê(ë|š@-* g°ãiå¢GY뺨tŵî¢ÅØF\?TäeAfÏœ÷RËE¨Ú($×ݼk¶Ãös+£§ %R\§\Ô&âD˜Ÿ#8ôQ{}rø%`wË„¼X]êMÅÁ|z¹ÿ€pßÐîïÇÆªðñ¼/ÆA™UwÄ;C—éaݾïù§¸?ž¯žÝLIpçWðžC èüÚÞ<@åÑâœæPm>Ét2Xyç%£ÔýdƒÝˆÞÊ‹íuJ=Ò`"¿VއЖ®(:ƒyÃ[«ÛPœanª…ê–âÂQ^¯(pãËÏÚâz¯ ¢Ì!°À0À!ÎóPU„5 k×Î4ÈÔô¦fÅ n3Q0äº^®¼œ$!x*Š€zèRèçS«fïÆrÚÄD@ýq±ÎW ódgÿĽܠ@dy¶ÈßaÞ'™ªÐ¼¦¡b"Ÿ–Äg7r¡ãIÏvB°®kH»©Ê;69¦íNÓ¢ŸÒè„+Ì©ì#IAØ™Ù/°½RiãÊ”©¨†mq=˜K\û*Da;¯Êû¬êíãæò(Í‚QíyÞ˜]U_Ù‚-‹ÓÚVª=Ô<å&ž@~j³ßŸU——ãO.å¥R%Îòä¢Û&ÓU}-|ñ;íŠO³•®‚cõvUG×ì?þ.¯zå˜zÍôÐ ´øaWí]»ãïçX–ãê’æ ñ4¶QœÇ\¡3‡O}HÉ5¤—ÊC¼©™lê×á(¡ÝŒ {?1K÷̉ê'lo½ýSšçбj×:«zîr•‘ ¬êWCÉê²°Ò É?<.õ‚ ïqÿóçÆË^Ÿ×·ÇÝ„ Õm©•D°™]]]¢Dö^¨@3U”UÚôTtà ÓáÖÏÛ)a÷ð´G°FZuö×m¬­ Êtó%ž×œóޜŠäRz–ÀÛ©®¾o%^ mºèî?Q}Þ,Ýí~S Ù@oéz–)B/«®Q5NÅ(1Ù­BŸœ]/Y7ï ”Ð9»Cá!A N»¥¬3ëóš 0“å s³ürNºÚP$ÈŒ=‚䟇²aŒŒâ¢0Ïš@€£·÷ìðtKVHkèÛ‡¬…f¾Zøè¯BÕÃzÛÌ-›#T£9‹‘¬Jc×·A©öLR¸Å&ŽËàlÒ>ßÿ(*˪^1 :ð%F/ÃÛvj A>*_!Åú.ÚKÔe2u”™e]¸éØa ªÂ‹îö˜¨*|ƒÆMcv-0U¶bL!ê²~UÙ\ÿBׯbòóZ¢ßA˜ÃeQ‹¯BÓ]C­ÇâYy8(qIT”iM¶´I¡žÆå†Ìb0fB;jö;ºlU՟Ѓk»u”²­6xcZòoª}úc÷ÀSl_£è¯kUýΚcúËü'ðXÍ$~Qé_WgΖ}?žãüYßþÕ^‘8vèÓ—Ùê飌`^º¦$‡Jh¡‡€KDªÞ‘^Äàólœ;G'ætoÙ¶XiE•ßìýú4µ^s39løl׋ºWЂ˄ μõg>O ì´ÅÁ²¸f=· ¸’¶ì}Ú.õ×=(ï¯ïÇM¹u7¯„ûvŸ{ïÁ9Ý<ŠÝqΕ¤X§µŽé¸º¾íÔÓ#˜ÔŽ.+çš ‡5Òa÷r,ïeùa ó}9„Œ¡øóvÿúÏû¡çˆCnî²AMZ?¯+ MÇsT©1?–wþ=íÞß/ì«nÇG@ ¡ 9Ruzq½‘y0,Bü+æÎUj®œ9óRìÙ"¬y¥ÈÓ›íï „4‹ ®wÁ/Ä À S=,);v­µ$󎿚Ç<€‘ ”aY`®ùD­¤nµ0 +iT2ÆúÊFÙ=T7s?u:¶Ÿº6Êœé]3×DµaJÚá‚2¦$M…¹Î|Z°°órû~©Wš‡uQ6½Xñ\¤.q¸6ñE'Jªmü‹>Oê&‰rŸ|²vÝ5é ýðæEtÅZ0ä «aÉ¿z=ü4òÂFÕùi©Xq/Hbî5+í5÷-r’E™ýr 0}ºk”ûQ$—ыĩ| ÜM·ÖâÒ8dzÓfó& Uä×D)„Sxæ‰íÍÕLVwUmJ“Ò$ÒÒB¥Tkä6©ÅåózI+óLÂàõæVùƒ3<[ý4ùãéöåï0Ÿƒ“ñImµõŸ-Ú®À²äó³÷±ê‡à­¬Ak’Ä‘³Ð'¯«Éåen›eÅêÇ»Ý<&«Áˆ,`/,Ì—@ÛÌL)Ȧ™øPÃd­S‘Ðu¬T™CŸEZÑ+?Ç6îk3¿ÖÇ= P÷çK­ô#ð:vS>¡ÞàŽ§F²Ç8La^à6 –]îôiÃì©ä;C/³£ÀR¾…¾ÖSÜê8á;_Ï{˜Š+ \fD 3XÂꩨ‚*ø#]ä˶<ÖÿæÿŒÖ÷÷÷cøôrÎ0gØ ,xÞâ+mì¡E™•-Òwa$ËƆÎëз£¾ ›,¼÷ÁÛ¼8¹ÿŸ0¯Ìëϸø¦ÎBš0Ïóæ>ÇöÚzå¾ýHƒL)¨ ˜û`[’¸€Vß.êyUÓÜÑTÅ…™å’»ªèàÇç„&Àƒ2¹!tÞ Óyg¶rÜ÷qÁ1ë­^œÎm÷† R·?TÉÊ£ri\·&µ<ß8]Ô®kqÚÔ‰ÒDeî+t JäƒÒQ«Ë‰®ê±#=ÃüY¸g¼Ü èX§ ç8Åœ¥4DÔ¢†cUuâPâ*–rØC*Ükuš—(&ïí¯Û ÁNTöEþ S·PêUÄ@]Ê0Y(Â¿ØæœÏá5Kª|<©Ëù¶HÊÏ]:ÕUÉ6ʘ†ž…¾6íbÆ ªdÔÜ$Ÿ)ÚëáëÔëµm©}?åÔ¹gƒ:¥ÊryüÑ:<Þàrë–+p¹¸Fµ+R}üÍf˜ëÞÍ‹Ñ^Dí-œÌïcbõ;2Ë21ªažÀ¥NÛ#ð«÷ݱh1Áe†3§6.¶»ñ­ÕÑ¿^Çã6ÿù +¨û@íd¾‡á›a¼yhÔ.…zóèá¨ðeàÕua½6úÝ>W˜l#‚cÅító´Þßa>/'Õ6ì{L[ïχé•ú㪓0ìv¬0ª¾¡êxœN„û‰ißÞäõ·Áƒ¾Ÿ½tEö;Û£¥ :œãY±HmC:7z4úˆ¨%P< ·,-KêÓºŽ«ŸugŒf£¬µyÍ[~áŸ0S!3`ÎwšåƌӉ¹4zÿa»Çû¶5ˆ®Œ â"µVw©;†Æ8ºð@[ak”IA¾­$IfŠð&“Ê¿0Ù8æKFàµ^ÕŒ‰t”Ô¥f5%;@*“ÏëY:-“ŽÂ]bÔM0Q¨›·Š^ÉÕ|†¾lùÌÇÍ+ÓQ¬>×xOE5ªî1=-Š>Øä9Õ •â—®-¢D}pÖ‘ôäšQ—1³>æZ™†²¥Ö;=ª«ñ— éye îY•äj?-ÔÔÃ<´- >äÜv›ÿ+€IDATÔ‡¬ƒJϺò}[ŸÔyvµx2‚é¨×q5a vHç×ù8f™*#ý}õÛþA:uš}^qC¿ênÊ¢¼ëß³ËBéGDvøè£Ò”µý;Ìß Ô·˜åœehy €!Qü*?.Î4­‹²ûëJã°‰¥ÍX`©C~Eø Ðôì†ËÂfHÔ)T¡³élºt¬¶û ÝµÇ¹»–aºõµ»e,šÇºSÄ»’í´½ëa”­'`Ùûã¶)šÑÍeÞäygéºÒ§ªŠVŸ«Rã€c‡ºp×Í]ÖVg“ ÆÄëð-&±¸ßßáiº– 6ÄÛi1¦këùz9:ÂÚ\ʼn:sh(Ït®‚ôxÍÛO˜o'Ïkýg¢6t9ÞZLy“ÖÑ!=ÎTVÿ?¢z8û°‹2¿: "íämÐò÷|&ÌÁðc®U>úÝœÿ0g瀑`uBâH¬]y»Û¶Ü‚\°-ÄÀ7#^™Œƒå¥”aGärä\ó:1{Â`Œ •¦0¡FZY‚l| ¼vcà‚¦8ÜÁ¥î£LV¸@dÑó×û½@!Kõ}æ¨-'Ÿ0%ibƒ¿²õ¡êÍS UwS’Ð2¢Z§sbŒÁ½âÚÀ®tËc{Ò¦x);oì¶<7íí’u@—í:š7ò°ÞLH3ûeÆHR™Hºzµå~LýDà¨Rˆ°^D&Â#¯XWŒ!Ls¼DÈÖâ¯èŸªå‰Ì¾õßÂüý¸ÊÓF£È>>€xJU]á"ù]z0ýÓûïµmÈæ:0¸õù$—´ë½³5Ö¶½=Ì6+õŒVÏ6:AD©µ]€Ú{¹Ö Ï Ý\¯¹ƒÉ¬üh|íÒZÄV±‚Iì¼à,Gn Þ!d+À`¯¯Sn 9ôÊÀŽ0agF[÷»bx}<Ýÿ¨( 7j$ÒuFÜ'½;¶ßOó»‡}×f™Þ” r¤&\W€„w_Øü°Ï0qBmQ‚D»±ËÊ!&пnX"ÞŽŸ,lß}¿½ÃÒ˜gèM³@Ð['Ä™Kšï@àà®…@ÁöæåßÂÜþþÿ-Ìß¿ŒïèºÍ½­›‚DJ„äLU½ZaEzU½Ã<|åÙ_ócÊ >¦[_†dýæ0Ûñ±œîÝ¥Ñý‚Nb®ÿ=Üo€kÍ9:žÞÔ²07š:óâ"Ù˜‘è÷Ûê¿=‹Ð‘ý"ïÚ"H¢þ¹©'äaoúº)©Ì;Ío=Ù~ |ŒL…8º^‚(J‘~Fé‰o7[ Z ½ù5µ‰Al¥5ëYwÝ€˜ ?» n+”ð™b°Â§‘0¿µ-ÝQ«;¿Æe‡¸½Š¿ž0ÃSVê o…QÕ¯&½–È8†‰¡UQÃ0ßwlÆTºßFÓ¥6½øû˜dº ­Á>{4EvÑ·Ã*¿\®Q’£.Ýü,ܳ`‡¢”_±ëÅÎË·Ùõr)”hu½6¥íNýìÜ”‹ÍÖ¾J•íQÃØ›ç-KÙ3ÌßuÁ@kaAZõ†BàÖŽ‹>Çß×f&úÛy°»¯^e/{;f Þ!ëu¬fÊ® 5Ïyxòe˜¸Ò\Sâv(p®³ý4H̱º²à1p-Жú®¨Bã9N¯ ÔÆ\¡V}f#aŽæ+ÉuŸ;½•#áFa‹¶×¼Î¾_ÛÆÌì:c«]ª¡Ä8…Ás_ ƒ‡Óª÷hê÷e(#šà_T×k)ªÆht¦Qï3c¶ ìmÍ€¾tGÒé« ¤»‘¶jee·€¡ÌÂ¥J\Ê~@¢w_†»Gê6ó•s%ã gE[^ã ¯Ytfpì¬C“Å Öð3bàvrô³ëD5ºVƒñ€óËUá]]‘;0ùºw˜ƒ~hó«yRè&þȯ5û2þ˜é¬†GÝ‚cËôÓ›“UxÝz5ðך©ñ}ü;­’ZE¼’â¼oÌÔH4ì[l_Wm”Fõ¤æÒ™È¸Ò‚„kh`ÎÂ\á´a¯‚léØÏdg®slM¶ýõ܆û>·ãùýTÜ׎=î: JO·¾žf_¤ÿ±«Èß¶g`š "—bBW¸±/U±«3*sugƒ¯ô¼:RyX¨-‚L£Í;:jú$v§¼ºâ{¡³·÷ìa>ç@Ì­w˜xÍ£rì¹öáØ™×.©ªiéo÷ÿ憬ûÿ¿P{ã¡Øaà/3ú(æ(̇ÖeXñ*ƒœ(\ó^¨…[¹‰¡6Ì ¹¹9÷ ó!7ËÞ° ³Ÿ2! piÞšp›îK4C m†{ÜÆÚkäÜõ£€5Ž‹oìŽÇ:LxÚ Ú"IjV±]­ÐCÀß!uð’M¶U»ýÖ%¼òW~Ñ?xÝž‘ºzôuÄf}*óòøþFŠª_–¾»ªKçšd™Qï0ŽU=ëÜô³càÂ8´¦ÍÆ3‹p'–÷2Ò1¥QñMÞtêékÆVMV-Œ§kú?( V[®Ï㺟öÛTW¿lLÖêP÷]­^œuß`ý©noo£û•ådzÞÞL 7²Ž€ë«¶‹k}6pŒ'£!ªJ7QÇau…Š:®ø<{5û¼r£ës;—ãg©­öüim:xõ¼•h­ÈKqn4 ¨àšfÀÀèÊôû©H%s Õ VæÍ¦÷؃pÓ8XZFÃìê È[”íbÁu=!®7V×¾Rƒ–†ÝRZ¼æ~6¬ôgý6ÌÍLɆU­1Ѻg˜|ÏF_ÚsMšñ4YYÆsR£§4D¦E ¥6D—¬º–8·˜¸*~ª¬Í Šß£Pƒ®PM‚âbkO××imxÖHxû©h @„°¦µo@4Ñ^AØ7‚•96O`¿¿¿?˜iµL}p8†‡Ò6Šð1HG{0èàφÉ@º¡HûÔfÍÞŸ’>®ƒyEnE;žµ—˜ ñDסðôQ!Q·ìÍÕ7Å×ÚJpFy’gq–µ‹pMÇ> ÛÜ||¡ Ÿ‰b×]?ÑÁWwE;y7-.½¦‰1àB˜›1CXœ[˜£®÷;EèfuMú» Žö® 1ð7ÖiØÍÒŸ«¾¹f óyXC#>‡ešÑÂÓ°—SoŠýç+S;dö—Ó@Á´K0o3Hw¿ oëÈø:h@f÷9ÍåÚösÈ|°f£‚}˜o¯s]µ¿YŸ»áÏÌÄÂ_ÅòÆâìn²MĄٔ™2¬9¥£Ï2@P„XÙ”½Ú϶յ\ñlü˜ÇíàT©Ñ³©Â:Gÿ¡ÉR™ʼ›-OjÚýþ.²OA×»ÍnpÉnA4êt Zîé#ŽrÐd£€þ#Íg=±! â–»qÖÝ&Ò8®a‹Æÿ5·I³™5ÃJØ×z0ó…³vgo×€ÝMf¾ô Öv'ª#+£KqÝרe×dÜ­/0$›k³®MR]YQ+è‹Ä¿î—(Çj|¾ûm9ýÔ/2öFœË¢E@¥·O€ÞIêõ? lfÉú€ÞÂ׌º°TkêÓI²µBBŸzãô©Xf"ÅÒF%+’H&R6l“OÇ»7/ 8Æa_cùÛ3 QV¿£ÄI¢‚º5(j°CÅÍ3óÃjS¸e(ØqW1Õ"ˆ%³AKðšË³‰gŠÕÕ×Ttž4æmÿt9tšÛüËlDu9Z2×o3ç (r=Ø–ÈПawM®e_ðE%l”; s5‰[½|eOåwýåêôÆ(ÍçŽ;ƶ‚ŒÿŠäwì‘§š)ó¼ÌM[ß8§æ°Xþ*?ÀF5i–|4ó¸xc…ÝN]UKŽ&¬ùã‹2÷š)h¹‘—=jýº?G#Ëô\²ü¢³…DkWM™P9$¥SìZ1pZÞvX×s…gé†Ï&TÃa>ÊÐsà}n¨©9sE"üv[,in6scèôõrw1ÕS.×ë¾é)8•G ¦/z sزeÖ j`<¥¾o Œ­6Ž¢}Ò ÇãÆäþ”wx‡ùýü‚Pz{—í\ág|ŸŒJ…ªìš$»^ó²OW$RM­Å²ùl÷ôØ`V]È$v¾÷„ͬk‹*ú…œÏàió?W¡íYŸ:ëÈÙM&cYY¾ëbÅx˜g—Vè—€ ÐPk¹#j׳ŽÊ¬²…µ!y–›M72W[òƒMÀÆBVåIR?þhñåDz¡‹ªªõ”Èïa”ZÙÀ¤;ŒÚ[„í;òC) uåÂË%JaÙá­;t×nmšÞf¬ÛvÂ&md¹­äæÀûº±Tƒ/‹ÉÞ,t;‚º$ʵaÒ^ß©æjÃäŽB¿f1XšÛéÜ _¢óösmvʱšsUb¿f#ÓZáΆ1 ÀMxî§PF£Qš:j~I‹ÏœÌo”e…Â÷-x-窰HkLh¸\4)ë_êzÓ|¨ÙÒT´.KÌ»7:ž¬kó«ú…×ëù IÊÒÄÉè†òÛk”¡ödPõuÍ;ª™Œ¢äŠ(ý峪£¤]”GêTý©€é»i€çvɃíK–i:Ãq%ê]YöyÅ•oÝ|üû#Îl±‚ΰ²A˜; –¶§NäÅñG;«¦¦ÿ:‹òñ4@¶B¿Œ6ÏÝCé,ÚÕzÌ~`TfVÆÃÉv$W!ú·ê‚xÑ™jõ?qn¤ ËãgÙ>žîãr<Ÿ7óZú‡ÆæícUé[ØgÑ–ÝT݃A/€©ý¼ÙO9óôæÔ˜A†£Óó)z¯2×÷]»Ùµý €ñœï)¡Î‹~cæÚU¦¹¶Áj IüßÃüÇß<¨@îûiˆ®üÎ+½P·àßE»É WÃÂÜ@¿¶ s<©fÌxñÆõ¤Ü_â²­/?e˜Zµ˜ÔñðL³eß×öù©¾‰“¶É®ÕnýL7KÙB¬Ë,Ì×ëêm.”YX$UqÚ Ç<ÂÙ.Ufßk[U#;Ì[XŠl~)û4ìòS€ Q3UCþ¶÷C˜Ô­?`逭RÑ·ìC®„¤› c  'Š2öHÀ]¢Äp.e ü<ùzV…[Ìôx"jûæ>üx¾ ‘}çLDÍ`@Ä(^ïŽ5=Î[j,ðÂa_Έ¿vFä7l¡±CkDm ÓáΠ6 ãµ(ÌâÊÐm¤Àêšì:,`4™˜Î8ÀcH“ú\‹Ë5Om;ظA5Ûm7¿b6»PÌ¢8O⢊Uʼn! mw®g;/ÕkydòIÖœH8 ™ 57ÂÄqƒNÞP}üï!> ݈ÐÖw0Æ}MŒnyšE=öªÌ†ùÔ á¶,ýéžE äÝúQÜ)ÌFpod…®*+åó©óuxÜaè§ZÌcc[ ®%úŽJkÖ™‰ÓÙÌË ¿›¡/Η™½{§Í"y§B¶Dj&ú/ jÔ&ɨ?¹/q5Njëê ¾/ˆÎZ¯SÿšvC‹ÞåC§" »~6jk6È~Qí^÷kPŽ8nï†üߊvC~Þϯïﯯ·@éÏÎ$2}gËzGÏêáYÙßL*aßz€7ÖõXÎ0ßMÏÏn\õÔûšF 2Œ öÈØOS¯Rº›{µ´ ¾ÂT®I3„S¢BOªŠšßë†3‹«@DJa=©¨+7]—õYu Šzh#` /^ë飾÷p:© ëÀ5žªµNÏïv;]t°Ä³Å¿›eû8¬ûÜ€£*mœU»æ¬CÈUMsÍPHÒ•£u`Lªbk…JçÕÊbN¿¶‚ $¡Ü„ÈÃ;)›*PÝ”ÃXg«!ƒn«* Ž¯¸wg”»„zÑÂÈD”«sI©>Cߨþ•Ã"o0Õx\{Ú*½V@Ž_! ªö*`þëïê‰|^‹ì#&Iç-Ùh³I.Ì0.QÒªt‰ë&µ¬M_­P¿âz4Ý6û†ydš„0Ïl~ À¸^³âÖ86ÑEm¾íÿª`(WÔ&ÿ¨fidøQÄ˦}ܘʆYOÐù BÌz'$xµ,±J…vôýÏBíùýu¿?6îæ® ŠpUö]ÖÙgqì¡h¬M1Ú ›†“tŒÍi¤9z\÷c;}¬)ËÒòqûBöÍô#Ìܨ!g3eÚB˜ŸT/€uf^d±®L‡´/uêY+âMÈ=Cë€Õ†t,˜Ðës£ºÚz2eUé‡Ð=0¿<߆Lj´?h;Îâ{¡f¯e›CëÃ~/Ô1J³nήg *´!·ƒÓº’+ãO\¯9ùµLl€‹ìø ¿,8ÿ®ƒï°æUÍê<8ÌëPºT¢í¢XÙ6VÅ‚~%Ú8-ÁbanøÍÎ:<ªˆZ::íyצ–Åéµ $“|„5G”ïY‹z¯"JTZÖƒbóóþ˜_ÚVÙºÄÆ°Í³I„Ý»T9½®ÝÓ«­²Ý9§±®~×ô‡›PôžŒc}ߦš9¡\5ãvX̹q1y • =9M®0RKa66p@8Õj"õ¯Êé“:âVÃ;ÌQÍÃÞÅ'¨uоޓН@Þ‚{ŒE[Ù*´iÀå\Úæä§Žîù«ñ³)Ulî)U yTãð4)ð»Tg6^nLã··ùj>Jëú¸™²ÄøqãÈGüº™ä+´q€/ë—òôãûû’ý\„ñFÞL®üžR•xƒJçȹt uEí}­zG1‘c9,e;oÝî‘Aœ9LÔõô|íÁì„€pÖKã<ŠDù~{„Eš.º þ¸[6ß&žܧ*æd42«ÇÒ—%f׎ªÑ—õG<×D(Yc¾o*†¤(aÝ*ÚÃ"¸Ê©7”žÁ öU;Q¦§ÞF,xžžðzÎÍn/âË–šàòjZ\£¦KAåLå˸ñôÆ­U]ee µ®Jì:ë&Æ‚„¤­@§ ­ÑÛU;?Ió*‰Ì64müdJ$o<ÄûŸÃftŸŠ¢°5$¬Áк œZdf5‡Fa(©íÞÂÝ«÷NQ¿í“Š M8íòü~ü#îaêÊNÌ%Gc²Ñ•ìKõÝU›ì4ÄšŽ™*9?t0Áu‰ô¬WéR\ÖÎÕ5JÀöó‘ôPåpÝ4ša…èaS'™r.É¥èq:þ5øòfpÁó §žE‘¾™O+.×Gs§ Û´œðÄ>‘þP Åu3š ‘-Òâ+˜ÛÔ·HY$µ¯Ð°mX–× _7_¢ü¬é8°me§ ºáfšHqð©‡OÆO˜‡õóz Ä$y†×\‰Ñpç›ÕÍï0?›ímœgÄ •‹HD›] %} å¤WåÑ ¹SäŒ^Ü¢Çàôüh¡Ú̺˜‘ξJã¯çóõ Sk¥†_ƒÑÚÒa¨ôƒSg€ñ„Ç¢ÉÝ̌ˠ¶Q@Ìк½ A õ¥DÁ@¶\7„_![ÛMê >›(˜ó=(3žšpûv;a¸!ÌkWÐ. ûw$÷Lcî¹ým~~…E±1Q¢§í[c¶©»B)¶¬ c›¼¬tÖ+¢}ÓM£²¸ÚÒrÌîê5æ”Å…Ö°W*Æïª©Ö#iÊ&¸Ì<Šé6ˆÓÃZW•û/å ?f©ì¼S%îlWeV-€rAðE”)¶¥ŒÓÈ‚ÜñEbC;ðÌ ~ÂÜt ÒÏ ìà´¼g Š.ayÎMIš¢[íQäV‹í0ý>Ã|:s:Û#Ò¾ŠšŽ¶Òéñë· r;u<ÃyK;nïäKÁŒKNõÔà (\fáR]#Ã>Û»Ó1oök µ2 û Lšp°ÚpÖ}îð,iÓžÝ)~Éê,ȯ­Ç-§ñaͰ0/3l!ozgOÎÆÎð§?½´¹0<_wîÌÊ·s–®íp xÑYë:o “EÚôyâà éŸ/\Ÿê`‚eë2g6 îz´:}bÖŽˆ¹ë÷fè80€‹Ú¥¤€åÕðYí ZÛØIèƒ¹Í .–ê«ýrLsW©bÍëcLcç7«Vµia‰AA2’ˆŸ°³+–¡c¯pP]Œ þý˜O|ä[d±4±¾ó»E­”º< XÌúüñusnU¹L–úÂ\Í¢ªöÄ$’¼Ø€ÂçõÈ„óóÒÞÂ9U?ªX–kÕV”]z)F~pÙKoLF úÚöUÂÛEd¢ê(M¢¼I ÝWwªF«ô»øtO”&'¡ä¯ñø_¶lÔgðõºÛi:SϨÍ5}¾Ýþ|¿LÈM4*–uØQF8RuudÉ<³Æ,ùý‘{sPÁ…X Ze©¹Eµæ‚^'DÂ8úñØ’5Fš­s¨ÉŠäÿ¥ë?´ÜÊ’-[_ÑuoéŽÖZA¸“‘·ªÇèÿÿ¡¶¹lõžÌ ÒÀÙ¶M-‘œ›J$©ø ÖÈ}ÔËØóûë¸tß»Ÿ¦](ùõ£žƒMÃ(çUóàdlp~“Y¨Ô5£ËÏ;VÌI$ÿÙ„m’u KPj~‡õõó%2úÂ(,ǵÝ«JWzÌ^¦9šlöåìC#2Š[„1_¶…c’'Ò}®%ÔJ6‡#dz@ÃB p¬X´@䬨žîç“ð­U?Ü}áeßùŽo©õå¯ÏOŠÑÐ;øïÖõ¤•]G=ûàŠÎjD«p²ªKoõúÁw•þ: "MøgÛÓ킾jÃ+bb.;aÌ¡ s°íÚdMML •må€12‚jÚì3‹›áþàæaàr€Jo¥©#Ö³x#…d0´V¶m'Æúl{·Û[zRû± Pɪª/q=a쪦Êû¸p¿×)›k…¬A­2H.O]ˆäS´Ãƒ¯Œ¶Ï䎱ç9$d8»‰óÒ…G¿&ž¾ôÀüËQW½Kذtiß …jLÏã6‰-߉3¿²L5•Xöí™§%Wœâ«àä\¨1„Dç QËÍXu¹š«lc­8[– ¾…>ñ®`ΆûÏîik­†ýy?IÇ‹ƒ9ñ—²L›]àÔj] tAÒoýW;‰mlÀ+3xÁÉÌ^V&ŸÆfè@”ÑÍ®¦±¿ýõñ…—ˆÚ´[–\S‡ëéÒ§¹ ³‚(êìáÜ"ðÿæL<5ÂÃý(!”»,Ëü»h_µ7GOп2i”ŒÏAdláìÓLoi>zôôÜ]¼xàx»ñÊvŒAŸÛ+ïe Þ|«Î€@¦Z=yå/å·Q©¾–çKéûŠŽ_»ƒubÄYõ¤5Àcúµì×*§]•µe=fÙ4çö™ŽN³P¦fßäO(«/ßk¯‡”¡ŒÑQ™Vˆ,‹v”¨9ÔØqĹU õ5G‰Æ’åÊØw˜ëÛï›3üQ©£‰ßâQ€±Ôxøß|Ö¥ªKDZå'Nw¼–„Õ¨ÓÐ7ÓãaÇÎ:Ø}ÙÇÐNRÕ”{f{©„ßÂ+D•·Ä±Hçîx»Ìˆa0÷ÍUn\vÊ‘±ã¦ŽÛ‰‡xgcߦÈ"’¿K%hîämÆI<Ã-éåêanÕLr‘Õ•gÞaÎÒ„‘`Ñk‰ö;ÌCÑî †¶¥Ä€˜Uñ¬‚.Ü4ža®¹;7}›ɼŒ ó0¸ C÷Å}VßË®cèäÄ¥2]qO/¦OÔsþþVV}ܳëi1®Þ¦î>-¯¬É»k 6©Ã€>E{ÝÏQ³WåXe’+ê1M‡©ÈºáxÁ:]‚ªÃú”•Ñ®„Àk¬õéÎi/µâJ9´Í))®CŽù£ÈÚ‚®èkøz ñŠ8QkùGÝ.×ATÐù ÇÆmAª¦MÊÞz4–Aµ`p2ÅY°±Õ[¿t$Úßyt±Û*ÃZì´(FiU-Út^Z:•ísè–1®=£\ÄMW×VB°ðBïµÎKÑFŽÏçûsÕ|¤ÄN­Í’~Õkß¼˜Û¶Žõö¤î”åU+n+=%jêdj¯$l˜ÆÿukQƒêOãîE ùSÕÈ)7¨NHÜËö[ÇÞ**$ƒŒ0šaž\ÄÃþ 9z°fÅÙ\H]JR,ð‚ÉܘïÙŽ ][‡dE”ŸE;Ò[q ¨ÓÂyѰ3XWÚ‰~Ä8é~ wÇD>_¢4=žè[q^6M²×XúfèKÙ-XÁT·[þ²Oõr¹EÖ]I %»]b¡nº+ûu ã³êJ¦˜½]ÚMd¥ý-Ï.7àÂ9.æÌ'D¦Ð ^j®0ï8<Ó´œï~5tmIí û »Uä–AàK…¹c0K”j‚H]Ib°*ÞÚ«ýáÚéøžî«ÅD¸è²Ÿt‚Ý‚=àL´Ð³ƒ(2š}X~GÊx+øù†Ë™S`ÏýK€êuìï=,kan[dx`µesÜ—ðæ’ʤëRj@L,Ùv-ÖϾ¾>åÚo}Ìö°c ôÔÚæ ¢(pkÉÏ›¯Ê@ua!‡m‚„QfÍ_'ÛëãwoI6ß4N°@ì~ ­’µ«D)ò‚E€@j…Qƒá9{.;ÍÐ쮤ÄÇÈÌî÷Öa,Ûúƒ'vÁm0wÙ;ýþÑ7i=Ù½“"3Á(¤ ;ª¥Í±¿ 8Î6­.þãë÷Dµ€y¨Ö*-æó¸ôÒ~â! ?„¹ã"4ISS'4”†ÃNæ /'Ý<æ_•ˆSu½Iê’"š&&±óªkrý]½ÁY±7mìF‘Vw;öUc¿bQƒÕÚ}ë#£K$—šŸRZ:¥•@euanÛ;oØYlŸ#8ËÜu½Ájå®J)+Ø –©ß«I—ûçòí§E5 Èÿó¿ÿý÷¯Ÿ?1N]]CL»™Y¥ gŠ»œªŒi1þ·öœòå¹ñuZäŸF{ë`Û¯IuM;Dby·wVŠXß^¶Ûb0ü¿£¦‡e—»+ e‚Ë8¡&|¸ví'S×­´˜ï0 5Ç.5õ_+ú­Ïo²[Ñmá xíò(·|ø·Â[RZ—Û¥7EƒiÜ0Ç€»‹ô¯ü¾uÓq>vGáx1wöpôœ§Tc71È"ý–\Òƒ¿$+ÒfÇÝiäÿx}:Àôx뜧J©’xõu{«™àÙÿì·Å`ÍZ¤©†©ÌúT•|ÕBÀ(a„3~Ûî?O«B‰6Y)F›E³p¼~ÚϼósAEØwÙÙÓß_ÂõhS¡0§e…:?ÃÖÀã'ŽÊ.þ(°e@>îw˜³²Û¹+ÛÑ.4/eÛV6ÂVôÁZµ‘Å[“Zcή¶tÜ´rVn$I( ᤽Ê©ðŽuÀ*]±L+o?ª:ÊŠËäÊe"[xþ¼v§”Sz-&•‚ÍóøÝ› ;…TlçÁBÉÓ}›koßÎEšß…°bÉ\PxnJ;aË2€ùFƒ»=j2h²kD`/§>«0¿\Qn¤“¡³ ³§;çxWŸš—®(qzGª¯íï{Ý¢x$¬ãoñlº$¥Äk«aÈoØ9eæ]oÑoǼxG5Щ°P«¬)nÆ>C‹vî²°ó|l/èé´Ý¢é1~{nÓúù÷¯O§AÃ`rÌsðßÒbȧ¸ahѱ٨ê!µ6Û0 ¬YbO¤Ì¯}ÄYÜ­M9.R³éë©1–jX5óhÜ=‡EzÏY!VÉGåyË kÿÙk4ùõöñW´Jàtø³)ï›MS7TW×ÎÈÒš‰> š7iÂî¿yE0½ôˆÞÃÇ.1ºl&4-Åe´éXô¡®Ôa58ر­º:j»yò$ˆ¡”ºÃ­‡¬ÐDŒHmvÅU¼¢ºN¯šàÎqK€Œ[ 3¯+clö “jöÈ8êsÃtgìÛ«”Fæ~ØÖŽuUÎõ¸žbbôUÜÔóÈ7A—͉%ôë,øj.!'|hPL*Úä#½ýw>—åÜ/ƒÝïc?áÞlg =ɽKûV¶^®×kg—îú¦q†–c.«éñõÛUíbqBgÏçc®hÖ-BÆm™­AÀ— äõGÂ0.Égþ;4¡b‹”Ì©e!ƳYWD|~qþ’xi·”Æqúöt0äçIR¾ßvÙíù*ñÔ:õbtФ®2„o7zâ4O¯–¢óë÷×üšõg-žíÌÄ5ë1ö<ÛŸ³ÆË®˜Ýz›–WTœúÙð‚˜¶~ÂüÃ^o~…w‹¹4ᙿ÷M·S$Z¾Æ."¿*þȱaþ> ÁF}BìÒ1ÛÞÜʃǗÐÙ–nçP¿•j·öõ\,5z³c­…#¥žÖxÛ€i–oë3ô;Aw[’ß®EÛ\Ç.ë§f,&Äçñ.eŠum+äu›Š’%¼yÍ®9qáÒH(ofm›w]uñ¦c0ÈG§–GM:´ýþz¾U$\ôwQM·õi_/‹pù#X9í…Õ¿ÃÐŒî©pú‘Â÷<_*åP_vw àNÚ›\  –'ý`ìo½OHúLº¢hko©Ï²×É}ž›ªoS«M×±ÔøWÜJG5ÆBæVìwsƒvz§*Ì'2LSA_g‘3!ßâØ­R¨ÅÃdÍZ`T&§e¶^kkCæ-ÌÚÐÙ¾õ–œ&Y²Úœü×ù÷ݵî÷êú#&¼•†Á•Æ×äò_ig­‡rŒæ‰møb7vì¡:ËÄÂ<»u¶Sƒ’žqÞž÷‰ÅåÃëé²(_Ï}ò7´Mµœº­oE8ƒµ7¦šr L3+â©™ÕË}žV–»[ñ$ â­«±Ø¶¼~“'ª‹võàJf?öÛr¼äpÞû˜X÷“D­+pûcœxq‹Ðè/7ÔÍ·ñÇ n^3ÁsL2ªµ¯³çF¦4ÏÙ6»ºƒB¡Ö,+N1X‹–\F‰?"uÚˆDüÁ Yþìá«€ËC¬$-†©ÝêN`ÝFÝng{v#umX{ùˆ*€rÀŽûós­o—Dw¾€o\¦Ó„Œ{‡£g1Tc¾¤š)/ÛRˆûF^n%»¿Byÿ-_ ¢‰G+ËÛãs@°4‰ÉmSßq\'`Ð-›2Kˆ}ukÄÚ¾O³~Ë.-‡*Ê'¬R©•´ì]"æîÊ­Ž’ Ά’­»¢¾UiÍ»_A;§¨Ó<ÒÈT+vÝN\hÿ;¥óö8EOãS"í˜æv¨â¬îÄÀ¨åþÑHfŠÍŸ¥ÄÒ ùz£eo£ÑÒWE;Å>3¸¤–ÎãÎX³| ¹æE0¡[³SœFRrt"Ò@i,DíY° p´Oò'>§ xÛ±À ˜d¾/¿7î°¡Y»¸îÚ3¿Çî[Ò¨q˜fÓz‡yÊ,Ù器1Àž€Àb݆•$Uf ó[ÕvXÂtÛ^,ÙD޲(ù·:´W_¬Ê³N‚g? ÒI…Å—¾¶¸ kbË?u—Ëf%N?âqHnläâ–ÔÒa!OL²y«q=M®%C¨¦µ0/ŽÏÇ·Ytȱ—`êäÄTð·ÖVóæˆ ÔèüJjûö]næ¹ãÛõbývEá³0AÖ=äÊ×î²a^ÝÂ’o,¤?þºÈMC‚W:OóÒ·s¢iµ`;¾|ÇÞGj¿ÃÅ{£ånKò­yù+êÇS¤é4Xn5ʸn´¹Æ%–ÓY 4¬"ÊäòQÎ’òµ9ˆE8Óˆr‰Ö¹I¨ÚÞþq}ÐÊ摵i‰9—ë­êãKóQaCw+†¹/ì÷¥ugm|1¯V?ö£. ÜNdǞŠ¥ê­Uo9ó»u¯•…jhC[´›¯Èöû?³¹Öw·"zayÄÿy,SQܪLù²YŽu^O‰ÆsŸë’Uz÷¢• †¢ùSÑ­Müêpò[ö–ÄE¯k»œœ…9ë/ØÎ(Èã ‰­§½‚x¹ž/òEG¾(Ç»NkÞFÓD¤¹¸dZÎ߯ætÚ|Þ@#ì;zÏFôÅ¢3Ê•&KmXýbðeÝ<Ì¥ôµ†<`d‚ëxNà±ú rÊ-)‹è$R—v¼nQz³ù`{•ÙÅòÐõ Í}g¾`å§ÙÂ.ûÛµ}7ømÌ<ԦѬX-šð+ćõnï©Ãý$³ÊÜ{ÚUYp¡ËŠÆA\Í#üs hœý™©°·ó]DÉÄ5B×PPÙ-\Äñ°¬ß^Ǻ=ž®C¨2u P˜)­–w6·—7µXÎ¥*Ú¯±:R„_cÉ?|Di}9Ú¡V8}è±z˜‹0ÜÖc¨´¾Ž0¿ùuwHeºŸ²‡y¢Í{šY4]nõÖñl‘ã9¿£KMÖ:˜ÛåÚÆ© 2­ù¯k?=Ïn ŒYÙ ÐÌ¡&ÕŸöÔwÚ§ÑõÚZw÷gÂñIøHmÅä˜â¹BôãSü¹ìÆÆ 3¬ŸAX£ÑGtWmWªf‚cÿ·œmžÅ×ãa‡Ê tìf,‘$å!Q0ImQû²nÀµ?%f±ÝŸo=ö [%ƒô‡¥u¨*¸“O í¬(zãýû¹€½î©Ñ ê)w·vÝÁ©Ò+OÓ¶Îg˜/çjèœÈ­:-ÄöR6Í,±Õ´ÝzEªHU`+_uWA·È¨ͯ۲c én»è‘Ç‘ #·â¢ÕÞU­ŸºÏÖœ€æÐþ¢l×l ýE‹ÍE£ãuB¢ö#ôÆí ÕöŠJ@ÇÌ' n9ÙNvx§ÊŠpˆWå;Ìsë ®x‘y³óó0O£i!%§Ç·ÂÃ<Š®5 çч|ÛÚC×G•‚=?‰Œ`Õý¿¯^l[ÀElVˆòã ˆiB3M~ä©ÖÓ3Êí²æY'Õbñˆ¤¼¹ +ª`àÑgažilÀ5.nl¥0h·&IzýÓöëçSí_ÃlÒÚ Ö°L,ˆni%‡ZXù¹¤ËÓÜê8GpÚÇÏm.„?úù ª¾¤èZm¸€÷öÌí{á]D¿¾ïßœ|<Î…ÚS ÷õ-6øÆ÷óøÀTÚ» Û:Žëâã{,\쨵$û+OÜòv¿Ûçooù‡’3 TîbÔv㽸-Kv1vùΜ¥kJ7~MÊs¡fH|‰Ëøz¹þ¸LÏÊõï g0)²z°RJ•Ä5ª¬1ïП¸X Ää˜?cÇ]Îù #ö9ŽbŒ[ñ_'%“2¹6vv޵ŸÙ“o.â´Ñ „ƒ‚•héÕ\¡LĤ+â„˃ª›8OÛ[2 ÖÈ©T±Óì…ö¨à|L?ÿþûïýùZ&dLi³úeÖåX„7ˆý•Q‰·í°ÔY7T–éS°ÜÍøø|*Tc~Ã.¬H9×üx}}½~Š›€maÞBrYòì×Ëçc|Çù‰ƒi'x”ƒ`— ë¹NÒv½¿j.xySs~òŒc/ÚCvQS¸³J;¯­ÓÅ壚šõJ÷®o7Ÿý¡JºaVc6Á ¿ééhì&¸Q“M¹5ÓkÒžM¨”x¥4Ö=2×´ä8Zõë­î•ÎïÖã~8 óñvç ¸çÙá2ûãSøZ&‹:AªŽ‘¢È~KÒÅØX³Å^–3?MÁí²É@š¦ie¥ V£¸H噬ŽK(~½gMpëãu¿άg¬ŸšíñÛ]9B0Ä 5Lëõjø•H¹YE³fù¹P›x·£ýžë¥BÃ_ EÁ%k¿=ºUÈ‹®ûX¶À× »&ÂB-ˆ„‘b¢ì0 ˆ”2Ë™N¿èé¤ú ê7ï#š V^p\`GäÆ* (?þ•c±Ï®çU¦°Ýå&.iÙA£·gÔÄ?¾G¹&bZª³žó½ ˆ_ÆZWë.–3‘ ìáÇuöØ|¡ƒ#Cÿª»]hyÓôAÊ2küÅô¨ þj˽£§°ÖTLǃ¤½»7±…”gUsKëìÄw©Ö›ùq uC§0çÉÔ ì±_âË%G²à–—·²¿öùÖߪ:Î+ÄE²òÖ UÑ–œg8Å9 Ìy¶Øûï«›•ýÀíùsC£ë>”²ÿ³ëjÎI¸ "K)í’‚x³—·3NäƒÑû¯ýp½VŽ%çô­¿þÀÖmV z¸Ea»&ËfÐÀžq|ÃBq•Œ’7iO—|z.Ž~Aå„ÝËΜ€Xf-ÏÏÏ0šÕèJy›‹ÆäûÀ-Í´Lš¹´PCMå(TV½•¹õå¦ÝNAu\ÿ²†ÌêÀÚnN„Ô\&®•N“ Ù &£ý PÑ3FÂâà#1KÏ>ìî´{~™´.Ÿ–ß„Yÿa¼Ïç¡“ÜÕuä6çÇ#³¡I PÉQ®oâ9!;Lgj÷x§7£A^Ã$¦“ e´N«ñ㯖hV± õÊž½¯&JàéiäÔþÌïETId›,-DÑrv*ÙÍ~“åëEÈŽùw…rêÑÿ?‡ù›±òÆšË|ÓŽ’\3yÔ)xÌR½q”Dùåš[ê”I{·´3³2Æ îk ÁPN~‚’UÁ†|X6oöyu=iÂÈÃü ŸûâïhR õS>4}a^h´¶ª_§4°Rh-Ü“X]¤Ì–£xðšl×O™Ò°XïßìÉŠ—ì ps8çŽVŒÜÆR#£ŽFHþÈ®/;÷ìƒäœh­ÿíò=eƒe}VWÈRP 1,¹]_ÖO1’ãEÈÒ¼ÃYhbÞ>bÂ<*˜·_c«èZAŸÜéR3Ö5è`ä²ÉBÃŽ?^TÈÖ\ §Ï’ðAV)±Š Š}h%Ûò]DBÞØÖ‹ÒoOᥙ‡Ý'³óf¹ªÔ÷XszèByf±´sV§UsÍœ~R s»#À\*ë>íʪ÷†pž‘£“|¬nI=?¾~ý¤?:&ȹ#<•ÉŠÐ*Gù¯vaú’Ã¥:Êvµ;îkPi>”d­\?¹ï^º?°jµn•a•¢JZ|[m¨±KRÀöíOy‹ã„í{E°º+ܼ e†ž’v[¸Rys¹¦ˆ ±L ‹ƒÐÉC{/7­\á¢â›©Hþý{Äb¼P‡9Ý¿áR¾áÒ¯K‰"UˆúðÇš(Jé¹JGA13pOMÓ«òü3Ìßâ-ûoeÎþÎ \vÚBªÂqåÃÒµ³×}»å—ñÇ5‰¯?®å¸¢j>h¥ïŒi-„™Ä²IÉKÖ«irµ$ZLÊÞ[äœò#Ît˜„ÅðÙ!{ÀÖ°µ)òi´œp†9ó¤Ô>HýÃîÊr„'Æ6®æEFÆÅØÑËÏÇTcµ[·;Ó‚„†íük·¦É¤¬vG…3oqb÷nÍQí%TŠ+º²Ò½-ìM~ÜòŠêl19:“ݚ¼ÐÞ)8 C8Õ¯ê".ÐáíIÑ–L.×ËÅRlO˜m™»Xxö`MôG#ØNyRÅ× ëÍGãúβíC56ÁÏøì’O8†ª½ûÔÛ:mJ°lÚ¶¸ãª}Ýï}WD~§ÝKEv[Ø»JÊF¶žPî ¸ŒÊ1™fJ~¤H,9`¬M joðj½Ç0ÏC‹Ë9JBZ,Õ5SívîÝBÇjuÆÖ1sÕ5·rʺÅEéœô†´…¹Åõ[j2'÷x°D z”å\ß©ÅÃoÙV-åÞ´á\ÂÝÅ*—@ëW©§C?a8÷†ríû·ôȬ¹‹/Õ¦u€¤géŒ °çCHŒ4¹s=€¤¼~¿F׬•/šÝýé*¬í é̈Ùà!f½êè.ºæµÂKQ ’ìt^)t ƒ}Ïb>–Î¥:ǹEj ¹«´Kh²Û­òV$€'ºRióG1;ñûgX?ïAÌPJaÓ»Â9åΣ°O`í³À@hH瀀IÀQ¡»rÀ”ÙÝÎ]3ŽGÙ[£KIqÃG>:£œ¦>×½ˆ$,ld6â·¬ß8¸YÍ,{R Ï®vM>{#–ï³"ŠŠZ +°öcÒ^Õ* V$â¼hªŠºý¹‚›r|EG·Á¾lGjvY‚@`b!ÓbÎ5Z¬¨!ÛÚ³ˆ1ù*¸OáàÙ³©‚ƒ&ÿB¶ e𬵿!˜é­l°ç(g+‡¦é í©ÚGÕ@¾Æ2´;÷¥€mP/oëq ¸?ÏcsÚ@ ¥ lös# kÌ­ÏiÙÉKƶµr¨'›¯2«ävºêq?dQ’s’ìž'dËÖÇçÏŸŸwí˜ïaÿ2:žŠ]dÍœJ"«ºÙ• ùI¹èµpÒG!©ã37Z˜_’Tªv\X%ʆµrR–À°yÝÓnØsË›UX;)­Ä ;³¬‰q*[gŸ»ÍÃ[=æ]uüg˜Ÿ“Ç“ÿ}wC¤–ÁÍvÛXñJ yÅTe|ÞéQ\^þŠ“¦ì=ß÷Qa`‰lFGKR_åº}X›B8¿DÖÞïËa~6Ãa$NÙ´Á!œ7@®©%núê]´Ë¸9N/·¼‡.”£½G‰t]^‡ ¡iÊèGÔ®nòx€Ý§¯²;6ÖoÁ`‘عPBR ð±`(ü¾ a6iK1ÓˆÊ7Âm  ~Àü°ÎÚj2ø¨ÈÛ6¥Æç Yj½ ŠW8ÊäÑxVgέü‡Ë‹Ö°0Ïnß-6;'þIÕÕ…] áÑÏŽí·‰Sعû~éYH¬9æsæví¦WËnB+"è,¨K_­Ìjû„/ùÜ{´¨¨·çÙ6é%·<kaÀ9‹2ªQ+°r\-bô*ë@‘@ë[‡2”ö¤qR€ýBœ±`šeÓ¾>œú|<~}‘ @òíšš¤éíÖîÆ¾ª¬Ð—ßÅÌw+šØ±/ã|?–ýë<±7.åa?amûj¥c=ÄzHæÇMß´öàï {Y®<<cÝ¥øJØË M›©q´ÿñõ’¬íepµÿˆöB‘ˆ^]›n¥,ÞÎ’n¤Š¡ í“+Þ£¬Yð*¡ö¬Š? ¸nA ƒ/×–)UÍÙõÀ·i)­[ÏüšF”Þ—C”µÑk6l®½¼ŽÝŸYÚðÿ³h?%7Ïœ—/2Fqñ‹Q[ï:*©˜•pè•Ù%$·ª‚àæz°\¨RÍ’$XŠ­c;ÿ% ®øÇ÷K¹òaÏûöÖqð0?uäOqÙÔÚwO#üëÒåéë3Ì9tÀ®òv‘J÷\‡Æœ Ew.~:*Õ·b „qìÀM—ý›X^ú‚Ø+\†XàŒ¤~1ÍóêmˆôÀl²ã›^«"6<•Ë›…6Hg1­#,ò¦ª²Æ¹³TJq#—{„Fs‰ãbS·š°ÞÜÂÜþàõ#©íEu®PeY]Œݧ™.Qû¼ã[Q0]–Þ.ÿº²†„š~aaD6>:j `£ó¬è aZeØ Š ÿºÊ7ö «Ë­’žßFc…óGöQ¤ÚQMôù­¶‹Äj’à·M!eÅ»="û%z˲üÞÄM×í÷/aRž_?¿~¾¶N¸[m]ÝZŸ•Y{>õ¹eð8,žËk= ö€Ÿ¾ÓÞŸ'Âüda¼ ðÍ¥ ç‰q9[±¦¾«]`ß«o;+õ_ㆠ¯]g.Þ¿ã(2F îÈ÷‡«¸’‡2T |˜* ·[ÆÞ&~’5p2í=!»\Ô庲̌ ƒUZº¥ûΗo©d™Ef Ç»M•Þ´Š¾Å´?pzbÇ\&Ysû¸%Ý&9ùÕ÷ÿúr®Êºýs·¼ùæ§4¤ÞШ¥ý~ú­€H°°oÏÕtà–ŽM³ ”lÆz<æòvp0é¹1\’×›½FÝa7±Ór`P¹¢)è)Z?àÃ÷` ˆ‹ÍAŠNÔ'Ú… HJþs:YNÒ*g€e=ý –ÒZÆ"¯úPBIã™&ýã8ùÇ)Øoïkœ¿ÕÎóJÓZˆrÄÐØÌà“Ëɤ?½g¼çÛ’™ÕÛ–w<–ñ%¦õñÝÚQ…æl5ô„yšÀ«ŸqP©Â\Û*5¤²/ØI§Ñ÷kA}Ž•‡¼sÆ?ÃÀ ŽÓIU}ØÿáãÚ¿F% ¨±Å«%çP³ kÓf¨–g«-ë„5¤z˨("¼¦ã:þQ ’awU(ÙOäÕ_•嫨èb ‹&× $¿ ªr°ü2$?ê8¯Q<»E[‰†ß-Cá$MËÁ’W|iÚÿîbkÖ¶i×¶Rp Àe£Ú›U]d{–v…]‚IÒ´‚Ú8uÇ}Ü¿î÷×cVùŽj«¡Ùãõu§C·†ûþ@ôí;b@¥÷²`x žf¥F÷–Úßþð§è• Ì-´ýWVÿ ]»}ß¾1l•ñ _½èœ¶cmíÌ + c“´ž¦Úµ{e°¡QZÕÝ~\«±/¥Ë à‡•šmkÑÒfÖŒ½‡¹t9!UŒí(ƒ’‹H L­½Åà >78í¬¾^¢¸Ý&VøbžÑìøŽõÿ ó°'ÿC~BdPÄN“1KåçVé!³â’Ú÷ଯ™Äƒ9—jNo‘XÔ,¨eJp-åê›4»´J–y?j‡qoð­FÜØ)º¶æ",6:oBÓýóÙIŠë6—¸Dÿ»Ň¡²O²I¬E ˆ².ç»nú9—>šÇÝžÉ<|z˜‚ÞÔ†IÀZËpUR¬HÜñ ·“A„Ù7ï¿öû}Z޹·nm,Ýx jç_QÕk¸å°µ®il飱CS]¿ÇÖê8\ΨMQ õ0e×Ìû¶ié5‡l@q€6`Jísü(íÀwC¯ÊÊ ¦¶Ðbö˜ÖëLŠ~4]ĨǢü¿+`†¡’/±o<>²^BOöסéG¶µ=IHiE}»ô±}Ľ•6è¦Ñm”uvK­æs4ä™úr‘h|¬qb¨Y‹çF>d?,ÙÜòzj>ª>njÀEÏ›íF¢¸¶ËqÚ%œkLY^h“¸¼Û÷G»Ùry‹ÏyÌkÞØEq ·/ Ñ€éXÖÓþȉÃtêºíüò¢Ýâšwk™wV& ²y_¶0ÿq¾5ûákv=úù)*»=c¶ÖûÏס0pWãíTá•¢ É1ª…m v…Áè\k¿nV\ÅÊÝé­ó~ª¢[‘_“A@F:°±ådãƒÆ¨‘q®`ëÍõ£öÑÆì=|%ÁA»CKó$¾DÍ{˜@u¡È>f‹û €žü±gÛ†ÜÌwHãoFºÑåG¶µOÅHÀÅq&W¿¸–Ioø}ë05ì-;#Šc?‘§Jzì‚·§}¥­Kí¸Æ{mÝ}.\ «þØ“¯V h¶áÕ×27ÀÚìï=NÄþ2Í[ remL©\Û¤ ÷°AµË¸K¨7Œ8š]‰ •7é{Šzo}Ç5‰âoöûô@<ÌÕ_+ÌË8i{«TñýÛådA·5½{„Û‰ºÉçKÂ|8úˆ,›[ÐÆ—JçaÉ#¦i©B×ä8kë”cTu 6 ZèB£Öñ’z¼\®Q­0Ü×¼×’µÔAb•ùv#}4õ5Rë`±>l}74À¥Ø¹²™-ºEQf7ÏÄ#[@޳ÐGj'‰¾[ÙÚî#q¡ZkÕx–w]i 1œ š3±*6·†¬¶¢½fqÙ5—´ùÈÙÛ™V•ÝBö¹«ûó¦è±ûÞ›MËÒáèÔ0Év@縷Ka¿jl¬ÛÅw ¶¨täÎq8@¸‡Ò‰x¥e¦B a^H°É¾æ²ŸËj°o„-É}?ÝÏ0ÉwW•_OA[yÀ’Ðiäò|=]s H„Ùh³ˆš1%!šºö–™³à(n—õ0WÓŠ’J[TÓæD}B Wƒö•ï¡[5¯K¥Ët†yêaž·g˜ÇÑ-íÐW{+碗¼Ó¸íR‘ü'€ß«–ýœ4i‘²¬ûæ¸ å· åŒ‘_ ¥²sýQóÛÇ@dæ]b v¸y¿×[q¹9±®RÍŸAÔg;‰¿½ÞöÓaþÍ”glYÚt|ÁP"£ãNOô¨Ý„'³€¾½—smɧ [{ ÝèGiïh °á9ÓY”RN¶îö›¬qRpð‰†e˜ea•(ÏoQ|û©\Ô+îä#ŒRñMs‹ë´ê:Ë«‚ Ù¥ø½°±o3¾(¾_`Ç4éºqæ)¿FÒ~Öj/…NO]ï"õ7´¬³äja^Xw€!’¡ZÅ®’½‚±x½fv¼’Èòn]h“*ä³Fü ÒÈ’Šýn RŸÕ#5˜_m£ÄzùB;»BíýØ{TCŽ&}DÚì®¶KIÍ_K7–L£‰º…þÙ(7UÖÜ¢ÎÊ’Z£¸¸AT¡šF7€QZ…ðã¹jc¿­ë‹ŒÅs×ç©U@b÷£=œÐb Ù='È/d#^O-Ó$íá~g^ÆVu À`“Ŭâ®îe;e¹ûV%îiñ›·~ê;Jrx[=DV¡ÊÔûƒÏH3h@óó¶.»¦Q†¯ê­”üN…C€·2u•tÐQö@¤)÷§RâXKŸ~\z·­”Çi+:ÚkðÎË2þg˜#_ê„X©6-ãésG$…Ÿ ¨¸ºŽSróäšzb C¦Óa>­{,E[%Á$˜i«M,ažôûñ¼³ßaEK»b« ù2.üôr<ƒy7´Ek´–çáâüóžóo¹Mýä·þ¥koß$·5UE§…NQ«SZ×l?M „™ÚY!U[_~Tˆ»Ic›´“Ë/À¢o®á„.-ËòÔŽ/`x/-É󠩘²n¾ðGÊeíÎävYnºì¢Fʲú¬E k\jÒy| #;ºMÕ e;vm‚§ÉeÜ\4Ñv•…9S¸ÆàÙoüÝG)éSŠð]G$ý¬$Ç…©HnhIF¾ŽÀ§¼K«¥®)ßF{C¤ÿr— cïD” ±0]FnK£¼'€AVï ¢£vGGÈÌ—meMg+ ‘Š#ÙˆˆUœZòö`p˜EAÇ>rªm(£1ÊO*0v³YñƒjºÛçÈk¾ÄŠÐRPEËt–ųr,Z-ŸójjÆîÁ—p9MwÙ"`¹¨û=Ô픂‚­ÃЂTb?tcW³‚ï2{YƒÂéÛð÷7|ðìã!tû6.vu¬œéFEÍä)»6—.³‚KÖÂI’¹ ûØÈhÉ'¶Êɪ -&{52/ÇÆREDÒM!Mq‘Ä Ca6ü†c·’Ê7L7«Ôò~]Ƴцo¯Ä, ¯ÍÝ™‡ùìÚRs@uŽ'õ¢QÚ y’Ý\ø¹ôÕ@rÍ ÅÜwÖ’ƒÈ2“2¶™ot¥R˱BNP3¼Hò È¢®û½AFÿé~v·kØåžË¾ÁpñÜlN^ ¨Â•4ì\B§ °=Ë ÒEkOéPªöØËK¿ËÇ.’¶¸‰ÊWV±òÜ·¼t`‘ùÄÛoStpHµ0ÇÍ5‚pØŽ« ßV³3ä@¢7É¥+t±nº¢+…F‹æxƵ¢ì„ %4 •å.~9‘)6©êö‘b†À‹âc>x9˜™öá‹©ûÈx‘+‚3•Þš*.ìJ¢ É®ªy)ÉÜ**aV¬ árÕ®Ü>EqÕÉB€fŽå-r´×Böμùè†SÞæXªbš#Ø- x`Xiɺ¸ÚM—µ,×ÊÖŽéíZTFu‚Ë=!Ý™ÑËUÜ >z˜÷pÌ“¬ÈéEÞT½¾]éPÝŠi¾äâö;ÌO‹ÃPú-A€Âph`0°†¦Ðb].ÓN»6Æ©h*K©ót¢²vÇýóã$¼þ+â`›äIá$¥8£üt]Qw"a Ø¨\jmc;ÏØT؃)kP±c(òŸûÔaE(¡&¨–v+%Wë5!áØ!q!_yØ…º+®îÚ\¸­ÇV}»}šRË™E9^…‡pÛñ8%HÞ¬½)Úq¸•¾Ì¾$ó!©QË…¹È«ýŽKù)Ó—©¬å‹Â'|Zc«»¥Î´»ÚÆ®³cÆ{Ñq½céÆça(·î«,ÉíIüã¯Ü~¨shÜ !Ýþ¶`³Å™;·Ê{!Cn§ÁO5 8"koÿy¨w+ó±cû#Ñvöš2Ê/XdL@„)Æbʪðâz±Ÿ²Áæ¨({JBïYž¿ZqÊ86þ6jjs——·ÃUŸEû&îLåú¡m„븒#ë”äÉ÷a'»íì¾æiç5§Kð)åî¸P^´Û7/Ðߦ"`ÊÎ<’û2µ—Ó¯Ïgó³h÷Z}ãÚÐ`ãi( ¦-–Ï 7"¤ÒÖÅš4}>Ã{Û‚¯Ð;›»Èçéä*y_÷çüì_–w¯ß¯ŒqìâÈ“AZnº,«+èÙ.!#G¿Œ-„ÐçÉ-Oû©³‹ÂÚFl ÇòÂ2¯K‡ç8f5…’5¹ßíâäÉ&Ð5qä¿¿|ã2%‘=ß0ãÔÞÖæ»,ÅyÑþO ûÔ ÞÜ¥_–¡îK% 1Ô(µãí±Yž)%·ª|îÄö‰ùþ<õ-{î Üg—Øcu³:„izøæóäñç·F¨ž¨pcƒ¨Uz[†¤sûQ—ø.ßz}a¥#Q°Ç±¶”¤`æ(Å“«U¬Ðü˜£g‚-‘¬Åò/¾Å.¦[x˜[7¾¬5·çzeÙ¦Å×U‹³†…ƒPQX¸‡±åê±Ú,² ¿m˜•cyö_±ZÝÑnÂè#*jo5Ø•5U»ô ·H’`Ó,q=8Æø¯Åâ¦æ-+DG|²ÏEÉ"3¹¶9ªˆ‹ª ;¨ ±‘·$âWÌœéQ- nÞÒÈXÇh·ïåG C!µ²!úžôög™Ð¸´•IÝÔÙ9‚ƒ:Ûtå(u 8ÖÅÀA›®MåvÑ”)–VÅ·]~[›6³ôùZ^w)-N¢ø ŽâátŽà²¶/sËã‰r9šhV‚Ù mp|´‡z„¢ýÁ¹´˜0!oòƒ¦- c °xµÝFíÜHsšz»5zvÂ'lýÏx¿¿ünjʱëO‡¾º=2×Ó4 üß1ˆ¤;QžŒ…YGÝa(sv€ülˆ¿={<\ÏÙ%W®ËqîfÕ`=FDžÝʹÉn„ªN³ÆeDo\!@1óYäÿ s7е¦(¯@¤-Þë.ŽÄãË:é¿jÁ½ÃüÜø mÞ%=¿©%žqç¾õ¨“0ªæþ´\:µ“^qïêúüØõÔåïZ™_Ù¦¶ß¬Ž°6‡}šo¢Òð³pXN€SèÜwù9I%·é)}ÙŠçÝ¥ðI™àcϸ•Í¢tdH‰×B*% ²­¦¸)›±f&ø ýg©¨½Ã\Š%æÆé÷~¤¸â¨OEß¿ÿ`8aÑlw3­wß,KO©ç¨Æ¢`wÆíü~uöyoÕŽÐD9ažD5$ãZ5Š%<ŒÏŠCïBnŸu8·„y’ÙuÖ4ã< Ë©‹- «õ/ 2FeÜX€d—ì'Ñ%®íÀݤ|Vþ놼{ô‘±…-T¼äEzù×Ç5oÈòè£DY×ÙKúøïrj‘B‹LN/y%}.Ô&tQÚb¤f1]X#ÐÚ·]þ*Ûicå=¾Vuµ¶ëó^Dÿû5>ÿý|ÝØäl!]²ãé~gÚk¡fOµï¬`H’ª¯íÛñ¤{+ºæïËÊ|'Œ2Í ›ã@Ø=Ú„ë4‹IG™C» ýÂqî-1ª¦1!Ú‡y>M#Ãè÷›Ú݇M'ÆVøêóË%a\’hß…n¾ƒÂ1æE> ­õ*Äí£ìÊDV!éå–};/ýìh·º›°ˆ’ ¸= …xìEêÛ4uÐÙJâ•ß#¸ÂÃ\•/„šp±¤ü;Ì%ùeiüþº¯ûë\¨ýi¢ÄG&Ñ! ´ÃÝ…– Ôn•Îö8$m7ÀvðPõ°Øá[îc¥ù„~èÍÇ+øŒ–Ž­[ôÑ8Ó¶=ë¹ÜÁó¥gô-V‡'Øsøù÷™Õ>ßœï0Í­Hé 1%ü6Èá…ÂC˜|ÞO«¾c»½FË‹aÑhaž[±® ev Íý6nˆ®~Œœª]´gKâ–œ¢¶¹þ+.3 žaì­\€ÔëåšÝ.5Š7M>Üy`ëV¦ë¤ìR¨úcÃëÍn™¿þ+¶R»?æòúý#)­ ºÝ,Êíê·J·YJ®+ÙämaWN)±õ?é%¦©Ëªô¯e“NòÖœW„EFŠ-4È,u«§Ø³–PÝPò¿°Ô(äv˜3÷ÌÜ]UùìVJ~#Šêúú‘1”—¤be}»%Õ´—k7L(¾guËùâ2äâ“ÉŒ]^õÅn">F$^²tø¸äL:oÈY3¶Éîä Q{ §oö©J²‘t¹¯÷Õªõ¼h­NÛk[§hsc“ö]^ãî!sñàÆ¸Ÿ½ÜI}X¶vZ&ûW ˜q9{Q][ `›£Õ&­|b×)Í­Ç(®Õ‚d°Ìmåùq¢w_—OÞãóz}ô„r:võXJc¡| Šä­L#óÆ®ëFpF-#'Ø­¶–?>¬¤«Êž}fÁï„Y^7Ò$ã Ïv‘hàçYsÌ%ˆç>$MkXià"1®7R ³M|×y 'FßQ¿w|çgQèµÄÚþ °x«óAòû|¢áÇ<¡9c¹12+˜”í4u>fŸ7{3m‰—À¨ü£ØfG%ÏŽ³g<1ò-v8#p](&}ÇœtnçB 4Ò Î"=ñ‚VˆÔ(É jQCƒ¡ðs`dß:õ¶®$~¬±‡UJ—ig‡É{­b ¶1ÜѦrú2e)é-:í›75Á£Nšn>‰ö™ˆ.Y™b½{sU3¿}Û#<öÎw±ìüxÝÑ8Ã|ÆHp^Ÿ:$vL:_6éajby—äóv~Ž„ù,}|]8ZêKJæwz~jËãõøz=5Q;–^èl‘w1av]#žõu9K^hâáÖ¦¼Þ!C0Ñ:Ë©õzyÒiÌ °U¶r¶Oöšâ°ß„8¬° í°KÏrhFöwt³ô´§-ò ز$º•Ã*tû´ŽUݰp¼}X9ïòV`]>2¼‡š>?ö0Ú¯t@|2wâ©$¤Î0gü`7JqrØ#Û…û´tƒ´×,ŒvU¦·X“Bk’…¹“—³¢þï+VééõoëÐÆDÞ)Ï/QI6‘…¬/¯+gÊÎêqÆ{û¬H³Ö1Ëe]G(šÁXxlù’òn2ìŽH§ NíÒÝ<;Ž'o]s]ö×ï0÷dþ˜¶×„ÐlÕYTÔcf9¼ê,>öÒ~hùÂÊn#['ÁGpËþüúzîËñùü<¬ºÇAâ·ì·-ãŒ×Q""‚†e/+xsMÙÃxFº}† »‘±éæ9Ï0÷AÒØu„¹Ææn„/ר“È´_—ظϼôóeII”7ÃJÔœ¸tPƒìà ±ßÖ^dÛã³’iá -}3yoçÄ3Û˜L–ØÀ§b[)—[Þi&-Â'sªÆœ×h0W9‘3Ûï0w¼ÀìSç¯O»L?·¾ÐN<ï’/žÜ,s\¬;·"r€£kòfXiÙa°‡ùù¬UFøÓt{¿*t žŸ\ߟOkã_Ï(çÂÕDVŠèYÔ“\Vk‚“î¼ÞŸdþEòmjü¨Í–ÊÂ(º&é<Î"mƒfjî#„>2þvì“ýK<@ºs‰îQ >;EÄÔá —ÜÊíÛå{ÔÚYš÷­›&X ±KÚZ/×sY}Ÿa*g)®K>.(¨E ) è­! qvJ-WZ^2‹ãÛ5mò‹u¼mëp£Ó)Ñá·†ejN%IûfrDº^>¤h'ð-2\MoÔòýÕº䤮ÀÁÇ5·û·´ŸÛœÓØ÷›EI=ÌÕ¢–¥»©®'&ç[\¤W̬ÊÈÄ©¯çqã’ׇJÑü¡•l®ˆ ŠeÑ"QŸ±ïº³hßÎt³ì¯ ­•ú5bÉuμ}Η<­óñúË£eüÓXù„GX1j5¢Êû±­½VÜ@,&:°M_,uÑ#B<éþš—¤±Šº©âåaåâýõtPß<éûÛýâ¾Q[÷÷@“…`r8_ EP•;ÅÖîÂÖåi‚¹ÓøíiÑ–Ö­¯¯‡&÷;<Á,hÈö8.´C¹µEkÇlÜ–w°rÈ.­òfUù< ꣼ÿ‡0÷º2„¹+hµÒ»Í¼P—lì©ZÐuøðUá jöó‡“â„y'%ºÊR,#‘ßuN æÿÀ±+Õ꺾@a²e`)—â|D¾‚©hÁˆüÚaŠöÐYúÌÇæ¡zšO2šdö† sŠ—“™oÞ÷}wØÔ×k·Êb{2ãUÐ-çßÕí6¶®£Ê챃>XNÓ±7Æ. ì¦æ³kVÌ[ëUØ÷!Ò÷cÚå¤)h90;°þ‹eX^v’§=}´@Ý…ZÚñ6¼ã÷:ü‰ãÌÒ"âžÓŒã¯|Ös#Éo©6"õ7wÇêNËÿ+ºZžµEö°N.…j%¬F·Ó~b©öMVÄ4ÀØs§•Ä÷‰ØËívË ˆLö§A­µª¬À¨»ë«›0>…#q@忇g0ðv;-¢ýyY4ÎN‘d˜c±¬„{ª+c±Îb:³µmvó:§m²"õezv¹•7ñع‰P_+¥Óè_…]‹¹ˆçj}í,8Ú6¿VˆxVqrÅ,ú¸ÙÇÚUëZýåEûñÒ\u!ŒÞ;}EûfD+“™30ˆˆÚõMÙõI]&u¿ýZ¹-€Vœ†Ô>¼ýúÄáó×¾=¶±g Ì®öGÕ¥§ž7Zå+»Ù2•Ë›Ý*È™ÐJÂtúgÑþ–;{siqÙë’¯$£ n?ü°—([ù¡6„9ýy™³1#@¤ÝLøÖ¥¨f–¯­án:ü"¾‰ ö_•ZìÔYSWˆ^!E‘BH0vÑ lÀ¸²B*Yx†ò…÷y—ˆëì8‹v7pÓ­u}¯Èö%¤Ö?L¹4³Þ<Ì7Íz~ Ûëuˆv-!ÍûrŒØ¬F瀉Êj²9L3ߊ»ï½„Ó<Ìù¦IoBì*.r³RÞ–ãëçc>>ÞWû˹`ÝÁ<Ù•‰BìÀ=æéüë¶Ãðüü’¯Šö&cÒrW¿õØḢ14ÁŽ~h†oáÃvzˆUÅÖDŠY;LéóÜ# JYY9· C{ïšWÔYŽnߺÁç$K‚¨±B¬¥÷µ.ör«¤È 4W˜óí×eó8´û”ádà•a‰kV], Ç!šì•m¾.Â&°<Ý(°0ÿê\¬^p³RÒ*BÜìfH¬x‚×):qM^š²]·iÎÕdßÙ¼LíMÚgd £9Gpd{‹Â´©z{éIvE¢k/»³’¢Ç¡e™w¹Ý­ {Ë·?ñ”¾øîf #/Wm´<}ï3Ì Z&šìÕÊ®»%mÖ°GÓàÆêÇSy÷M@} ӌꬻýWüG›Ì2M=`9ØM= ¿ Ó´ZmeB{X °‚Íî>£ùÏÜéZðî͡Ԥš5M!)˜#`˜ì.Ó›[_„ "œY»ÞÈEÅ›§Åª5[v˜*2;­<»s¡;]JíÉhÞ2™Øc-EKÓ "‹²“PšRŠƒYtKF‹áýÁ½ÕÃ.÷¬[àÊO.vFÍrœúíšìÚ1ÃaLÍó\Î^ ô츬]ŒbžÙ€Ãò°cþ¿M¿þm}ÙWNo¾•&é”OÁòâîö[ŠícuU:yéý#8{Ê€6.QÜï¯ÊË8¼»ØÃœŠk…iV:ó4XøóñclQYä÷óÔÊ+«Àž<‹~$ÅâOÖX½6í´ÚÂYå…ŒJ‚.P‘||äTCƒ)+îé4iGº`¸âŽ»sfþÙ3§»ýˆÛ¬ 'ÐkŠub’ÅSÅÎGòÆÐA/WTl%´›<­G² ¦·C^µóÜÚYi­£/¬,¶lTþøždVìÛåÐ$e/|Z;¦y‡Df[ÃãiÏ…š '2î쥗õµª¸TŠšë.i»¼cË·/¨cS»ºñýÃn'¤?Ý=΢ýdû¿ëýÙÆ³.m\ì]\ÈäâûT6Ÿãl%ß«¬Ë¹8ú¹ÎVXž´XfŒÕO ¼î¶äfæòZ‰ŽNÙ|í&z›½Ö‡&øÿ\¨L¯wÑŽtn¦ñ?Ã<&Ô–Ñ陯x…Õš¬BÆIšjò»íK®v³6ˆ•° õÁ<º1X'jÍa­ÅM“Hf‚¸a+ƒ™ð [½²V¿Î¼ˆ¶}P+۶׆V¢/ÔN†]ÀŽ‚.£-rÃêmySfœ*)˜íTWå‰Tl7 7Ú@ÀÇ‚ÄÂó×^® aº:ë6Ùò@ãS³0÷•Dø~jÃg¯Ü‘Ô89Ê¥G‚”šä4[¯…Ù†y‰_];Êp*!Z»¯Õe¡îç(N¦ v²Î…šÝèUT–e·jêòV‰£¢ª‡f.oB˜[®«Fwúä–×…' ŽÚr5% ·`WA1È@´þɧ ÉÿeA7Þ×2®à¦É| 2}J¾¯÷Ô™ÜÆu¥h†i œß®™¸»Tî¥õ½¢¬%‚À¦ÔòÙÇ^ëÒ[G÷¯K"±,ûçnÀsZôÍjLK qÒëG¡U¢ílýêRqGY^ÇM¥]Þè¶Ioš#éWGM“2d±Ü•ÉàÏfÞÚ m¡™žI qd¿žDe_Øãjd•ngb}nƒ‹,+‰Œ½cFuE¾hò§($¦Ý ™ï!A¶/ïšÈšk U8Jûëóé@hzÆßj…Î5™ÅßWk:Õa¨yÔHFv\ƒ])>¾E68t{ÛK+e¶åïÿúz!÷´¡‚ (J[»+6ÿ–]`iÎúÃüHî£MþFyµ¬j° „Ñx+T Jë`Ç@YŽ‚ ÃÌȺg»Äð8™dxR‚!æ¨r5‰3€×@è¤:–©ú6I0´ï‹Õøž_{ BÔ«ZëßÕlúUÇÇ#»¿ïûá±~î¬Ç''>a µ¯S+·‰¼³›så«·ÇÓÒö z’° Çó¬’¤GtA.ÜôŒÛ¿¾ŽÀ0|Û‹)Hô<(Î?ºo•‡ÄãõšBÙ‚&„l+.ìxƒ¢œŸY©—E>Jÿ‡ÉÔ´ß,Øñd4ËéÂÖ®çyýžSâäÏÉ¡JÖý‰–×ïI…zÄñ0Á˜ú#ëÀ«Ră;±HÛ˜Js»czdäNÓ¥"’ ŽÛ¡¢iáâ©©yº2…2±:])þõayøš@Èè¥'Hº¢èc¡ærüůü¸Y\fÍÒ«ÂZ¬ éƼ q‘¥d¬C˜F2{[Ë”ˆ;ˆ†Þ>®ÞQ^¥4øô{ñý³×ŽJ.4ëÆÅ"òØ^³]€­A\²\¼ã®ÝÚàs.$¤ý³v8öÄ­ŠÛ 8'Ø ²H´(‡ôÖŒG°:¼‡0üC””Ï‚ºí¾íyC6µŸZY½¯æäV]­åxç°#ï,Oë·Öé¥F|ÛB0îÁƒÍ!h¹y¢8à©bÇ:¡ ?ê%1FÂܶõ9uÛ³`MÆ2ß/MØË çî`Љ’›ì¯2Ý-lòÐŽ+Ì #•KäU¢Š…•òŒÒœ¹²þ1YßVÿ s±XÁON¿ó°¶ôbý ó»5ÂÖµ‹‚½êÛõõÂ&å„«‡É0Ô?]K­Ž&¢NëúÏ0N9Êzö6Õ ggÝžÂ[FHÁ{ƒ_9N±·æVÉõ®W˜©yÀ“Xl7ú'ñ·oÐ:éÃñ b Ú:Ó²)”DE=4+öך¹ˆ kŸ5Æ 3q …Õc};ò±&Ú·Øîû€*'ñ:uŤõµ|Ϲv²eÿ2ÉÆø¾/¯j;$–¾³òáã¯ïqùñà ÝW4RgÖXMÝ<+G»º¸|ÒÛ‡%ÞÆwrÓT‹úRs:ø’v³2¦Æ™éÀC;Ù3•˜,åö§“Ú-T]š ‡Þ*Ë„XËo}+ì³ÒbÞᔡc°1v@NÏ2àÎóÇ u=žYÞá[^Â0¯¾]­ e8·ÿ£†ï³+ÌwU¡< =Ff\ÂvùqS÷RreÄm];ÖîÛoÏ5Ñ °W8"ï{ לÉ/@Ü×É¥âeK_aj!›³Rx RiŸDÍðÚÖ?®Ç·V†gû ý(ÔÛ®Þ+ŸõMê:~3Lý´?¾~=–“V5ÅHM½¯'³í­{ZUýsgͬ›c])”ôªöw˜?µ²œN Ó‰¼»šÀÃ…Žý,$Jáfó‹<@­ÎY@áö,,SîÂ6àŠ©K©øeü6ž{ÔVú÷r¶a'a8„aÅPÀóÙõ[ZK¬´ ºcWzEɸ­16´ç1V­S\L ¹Ùµ»Î ’b㨈¾–3µ:–ÜUÜÝÕ¦ê÷³P…(b ÙõfW »¶KF€ˆ…ý¿`¼f©£°ˆH b/)iòË¿Àà’HìÏíÈÔ_¡$£8dŠžLd$BEŒ­GLÜ‹ËÝu"úg´ ¬¤lo:tL"Àµ‰<^[yÕ®®æ—û:ý¡Ýæ2 ~Iï/ 1­ä˜[â`n±§¡{SKÎpü=‚ó…¼8¹Ì&ðI&´þï0·¦aÞ>,V\¼³÷á…©çŽ}?Á´ïk$|ésÇi¢t‚©NöOXyÒ±¶Ä¨Ó~(»ô›‹ßa^ËHÍŠ:ºÖv·â8ý‘8—¼´}¸0©jkܧi<ã&æ°ÄLä ú«‘<蚎€¥¼ j{jd½5òn?~»¿ÿV+O—¿쮤·×ÒÉìx§î6b>±oÞLQ«f»9›iÏ0?NíÖC"]›óÉöõ,(„J%ðŽýæûïâ4ÒÑBœ9ɼ?>O1°ÇÉ<=ÏÁ9 Ù¼Èêe­jkÔ/Ug˜w®¶Ô‰¦Ø³Ž\[H9J2¦¥Ž¶}ÀuVœ>«k,ÌÛ†^¸”è–³Ž²®/ié`&Ø™R‰¢ÄšgkòQ€H’8„yK‘ {”8Iêù«Z—¦E;û‡=³›«$Ü“`ÊhÍzwÑ›¢A· Ö‰üÅ“2Ê Ð¼ÙÕÚ[|ln­F3¶½=)ÔZxj™ûjr„’¦¾^Äz!O2úZrE+3 sÕÖXÖ©{{ë©€ yÂ<3‰„,,ûiABÂÒ­Cƒö±Â3´w'ò›¾~®¥€£Ôl:Ky}XœÜ]eæù:ïo÷‹óM¢´`˜jøÍÌ­¡‡Z¨×Ò~='ÚÙ7¦oá°ì§Þzh·³·=·gx€æ›,ÎåjVd¢œX+ Ú—}EçWõ,kõìêlÎ0‡4m×uY\‘jÌU¸C…¾È0W¾³8£«dý“M M…0§– BÌš#ÿw˜ïnûö._~—Ï¿! æÒÎSi:.È>þ±¼ ¬/d¸–±M–êì.Öy§¡òæRˆU¡†¢öá×M¨‘ìW^ë?Âü¤ ¼\ä4Â{(Ø3çfOéu¸°îó¼–ýæQÕ Ü0<é±m'ñ¹í"¬|RŽÒÿYþ6÷ÔèÍP» J^â왦Z”î¨Y°ãôÅ ¸§®Æ!‹.%BŒœ –ž˜¥$EÛUNÚf7^aƒm…405T$J¹†‰oÍÙ`ïpœº^[“²_\~NòØžp nùKœ%’*±˜­0Û*]×)‘çC¤QYZHO–?„?±‰@V`^â3¸ËÑ­i®?>Î6Ðb˜•ƼvúàBÑÎY¶³š Õ„+Éq’«”Ȯ׸ù¸1A{<¿¬¶¦«ú£h*Ù{é±?­çÛ‡qÁœºÛî­•„Å•×8â·Ã±kÈqCì#£ ¨Ã¥~–¸ºv|°x·Ò#ƒLË!ZÌóãóØw<Ý7y×«Ú ¡O –ý”L;ÑdLí:sSLi2çýhŸa[…Ï\@ž¯ŽT¯Ï0çÇgE;(ݰMgž—­{Tˆ(Õ Nëfˆ8º‹ýúošÄ8Y Afí`ê¸X¶œÏ[óŸE»kmo÷.&šóæŽ r£h¶”gO¿{ýæã‹ax¼~}M¥¬šQÏa„yZMžEûá5ر8Í}>¿Ñ#ÜC„¹«À¼ëoîï0ßüénÍ?.X’!y8Ôêù }÷9á±»Ë@UÂ<®ÙP£z]Øa )Y‚\öÿF ào=Èõ²êtϲ‡N„Èá­¸Ò™7¦ dwÆ(¢­× ç¨ð“‹Eo„+ \îÜâ~õ[ꃈ½4ÆÂ®^OÎè ˆ{¦Y[c×€Q©Á_™šÙüާC’CðÐdwþŽö*®ƒ^yV .Õð¤ôd¬ØøñýãENqà‹Ëøû)(⨨’Û-8ºfv5Ô)-CÚ „¹V¹,ÀêÎi}ò± Vä"ÂÚKŠK¦ö.˜–Ñ{¡–Š¿ŸÅVÑX“ÐÖÑwüÇ/ö/e_ÆÛ½r+9 Ý|H ê¾NçBm˜¥¡-®ÝØ¿ž‹õÌ‹5»vYð4ÝÔÆ †Ó®Úr¸òÛó-@¬Còxü}·{ÏÊ¢|N,‹Û…]¥®qsaj™Ìýõ"eœ×Åzö !ʧÓMY~;ÞŠ“5V¹Û䥯ÊìJꑦlrù¢!ÐÌt×z˜š®©B(ŒààÛ#mã¬)¬}*$ÜRɯS¿s PõÁD£üÒšŽ2¾Ü<¾Q#,Þ“v+ ‹·¾êd­…Š‹®ª.ÔN5ÿóí óñæ¸Û[Nt•†,ߥõö±uµÂùq|ýÿ˜e³q¶òmÞ‡ÁÚˆÁ¾P£¥¦¹=@/ÝЋ–ãëo{î¬ÊŸÛ?ÂülÎE¿´í­ÂºàÊÃá÷âLûùÔ»Ÿ×İ&dŒ€ÚÁÅ Šˆ„ ZÔa’Îa.Ùõá[S㫲o£”¹%rQé“ÕhÜleôBÚUR«ì\2unKrqå–_@»åvãï×v¬s§µ¥™}S¤÷Ï’Êüš^/–éV +.l|eÄ»+ØãŸp¾)ü=²d]Dÿuå[ }„ʼn•ìLÛKèáÁ_]Ù¡,ýø~Cö•5ßõ¯Ë¥žûiŸ¬Wµ¢«œÞ†d$ä©WKMPjn–\FX †¨däú@Àñ’û¤¢­Ë§ßŒ2ÚŽ":­pXÿwËý…æ1Ê1\ôŒâÎØ¼úfÕÂßÿþœ}¥dn³zjÀIÏå~6’'öÚ®ù×cÙ^VÍCn¯ÅÒ[g¬ÐÆ&)7)ïZtÓ2Z‡ÕÎ ª‡×›ÄzúÔŸ:ñ§L¬'zÇs$×dLcµ³¸´¦Œª¨›ðU{]ÓåáƒhЦMQòÐ¥SàÙõ\¡ÕFQE,ñA"Ê5(·f½µ‹©Šs¥™ ‡Œq}= 0»Z±ßÌ/’+Vã˜ÕÙ¥ýu¡.EÓqr «’±–3L‚Ô|J*>7ÎùH–UýmE2À¥ÅþøãüwfM’«£`ñ˜Û~Þ-J˜wB€IDATŸÇ©0r½Œ–5˜ðQÄ’â\nëÙ/OnÞ†l ßß ¯¿_Å;<8>i–‡Û+šì‡?ïöR{L\†^Çäxýü|ÊWÑJa›­"ZÚG€ÓÒ§Ñ­&µRn3X”Wl;0TÀ¬dh—+Ⱥú&w>ž p¥ ¬ e*8/)7™úÒâ<ÅYzüš‹D"ɯ´LÑ*ä¯Ò—ªgœ-Ñ<‹ç:‹‹~¤…÷xEît4”–­sNù+ARŠòšÁ«knY³Æ¸Lå8b0öOÿŠiãz–1Ø5Œl-ÚS™oi 0g(gU>SþÛG5X4ÐÕZHwÝ X4fÒ±(%X iåîŒöòZ™ ZÖG–= Ë5Ù@:{-«Â?9Áq[,2âyÑ]Ya0¹B¹+þÙ™Ö²€vœ|&E’÷s(;Ãäh;å,𦵦 Z^Üq§9J1SŸ—R×dÜÔN" ãÝ[úýËÐs¢¾Šëšþ tò‰×ýgà̬ÛÜÈ÷QëokŽÞ_Õo&#Ê>F§±[¶Õµìã²¼ù_ß­èì°˜h­±€Û:ûÙ®Ïk¡Nº¡*ÁÎy?wxnêÖ–ì¡v0€ Ár#ŒÃÅi_9JU夀¬|á- ³{rˆô³ÙWK›xf‹S:I ‹K󜔔OdpïRÐÕó… >¨mz秺!!™="¹„ÀPÔ£µWÈÆýç]×è¾>uë÷OV,–‹àÉÙŽÇ ~UòÊúÇóK¾ÇóÃäãl»Ä*îö‚»R¸ôû¦êaDy ÑFÌ:ê±l¾ÔÖÚ×7ÐJ„y+„ö›êú„6·$@PÖУ…ýZg©Üb°oX|ÄQR0_§`¶d|¹Ü1OÔãX¨‡æ8‚©îŒ\T²eË¥»€™Ý¸0É\Ä]—ÌzcëŠ6\CyµÍ-;W;"ªYk‚Ö6R,uÍÐá)»™Ký–^Ÿ°è­gí]†™NAa޶¨$0­Õl!k[xbÀÄ·”S¥:‚‰wz©1˜$~ýœÌ3P·ƒðõIJy°"{ž+ùÛɤf§~´oÔŒnYøn<ÏNZ#<ØRö|ûÁÚª¶I{ EZò¬žn’;µWî­å*F8Aÿÿ4z={Ø3Ì/ü|(ô8ÜÝÊÑ ´$ÎIœ‰3È aª Ü‹zD¢°­n¥ëLøV]oŠQuÿŠq‚éŠFØD`âË$k4Ð#è‘HŽ m?ÛÕ´T¸Øæ¥f²Z—–EÒV®Sv‹‹žæðRÙè;‰ÙWf§zê)æÈ¬ ØùË5qwWqx¼öY’óôºc;9½zæ>åñj Gñµtt ÷.ÏjûK¸Ö}LÇs¦MØq2}[aËumÖäÜ>X+Ê]yÆR½Åøc“„Øñ…–Ìóu«œEšaŸŸÞÄÇOˆ AOÿئ~oPÙ¯»ÏílóáψÜXA?Y)o©½¬ÐÞî¿-Qäq¡êà§EªÐ­2«ê3ΚРæµ]¬ôˆÒŽ$ÄhÓ¬?¾]Ҧà /AÉŪ·¡.Jc.†RëteÓÌ ¨µdÕ©ô«y›÷/¹ÛÙ‰ 9FGx”KRÉÒ·ýt)dCäÉb/ŒŒJ)Å%î½MÈ (¿a²ªv˜‰ßQê§È[ÈÝ£ðpÞ”(Ù´"[XqÛ'E>òJƒ,üT±ÂÊR¶æ®ŒæÖK\8SP RA.ÇÿFŸYöAÎÑêc&ÎeÕ¯.Ñ*Ö‘Âïl;Þ‹¢ûA!Ý.§‹<ö{V7XG> ÄB¹ïôŒ-Ú¬”¯—}¹ŸYàO\ý[ îç7µCôŒz­-±·WmÁ;ýæôl4qú¸ä7Fe¥¾[ƺÞj×x³îˆD‰7Ïœen·"ξyPÉÛ ;°¾[Ö>‹‹.4Q\!xä%MG&uqÞ.R«×¨s;]¹Ïý¸CÑéy…\ñ÷e)ì{š!Ú{X¡øþ|êG½å!uìÇù¹ý­ÙhÚ¥±²[·!\s !ïçè ù¶Ñî,:sŒª‘˜C-öḐk7™}=÷üúTÕ·ŒäTçGP¼ëØSüûçSý<‹ Tp”E·Øjn­€8‹‰f¤c'Ê«¿áÌçl—ƒµ¸yåI©(„-NU-“kÏçö4ja›­B¯-äæQ¥*n²9.ëkŠ˜Eĕ҅YKÏM¼C©sóK¼Ò¤5 fÚ%m²¾÷ Ǿ¹SaÁj³.ÔÊ8 £ ]©v¸ž½«/o7ë@IÂA.Ð˰9ÀÇÅÖËRBÁRËbGU|aÌë,õþY¤ e§®›I*I²«¦õåa-˜{’Œ^&y§Z¶–E¹>k<ÔFía#";Báj_º=¾>è%„y=îsøçÞ÷w˜kkŽ\£Å©²¸êª¼´Êœizƒ™©ú:už"Ý\6Y6Œýú‘Q‰üŸaþ6â Œ­ +|,skµ:¡Õ@Š?kòŠÏ¨kê°³øó9oÃMÝáyû¾Éu@ɽ@ÓŒdR¸\løò± Cµ½âŒ³”Y±Y±{R E2¿kûbë©€ NRÙRPmþ9Ÿiw ~1a·:ÈE*>V­S;HÓ‡÷  Ð1.Ú4¼)iºˆ¹žm~K[%þ÷d ¦BÀú]+ùE!q=GWDP˜;ßIÈZËç—]cšï?¿¾>íŸr±a!øùùùë¹nO»€??ï³*(zýñõÓjÝg¢{@ÇQòoÒ ³˜m•¢\(˜Ö.¡– QÍÌ>ࡨ’Mµ±VûFÈÑbÏkµuͦƒ‘G‚z€dÔ2es°0–÷sŒTIÝÁ-Ôù–z°{â–20·[¹“*ëqkº4±•°˜´’· Kæ¯,œ]òÑŠæ¼³òñ,¦€ÂΘ  ¶×M?¯æ˜;¼ >½ç l¤u•žE3•£H:4EÓÙ ·~Û©ŸËê>ìë¤+G¢!e öܪ:'°èÁVMN+e}íh]pµ¨€2ë=ËòDgK<©¥ °KkW+sëάù=ÌÔôØ2b“bu÷.,ó&󜰫ÙÏU¶G¨LÇìY5t©*s{²s§è²g1B>­…ŽkÅ«í;¾‹ö»¯ˆ–í»L¬×÷žø”_€ ¡IzŠåå2R¦G bCå ìB ³„ ûüJ#:`u%§ye‡ÌÂ";]ë’â6ï¬Û‡Å ¦'T{…0ÉìÊbHÉÙ^rÅ\"Ü g].ý·ÁûýÎä;¬u¯Q ™²K~e£¨¦RßÔ!ßgè íª½´io³ƒSOËý×fÕRI¤k£lÖNÀ‰'ue“ò¼;Þî¯__O;¨öqÏ›•âJkO² 6VùóçÁ{øIóüõâżˆp4«ì~‰·j¯ùh2¬Cᦡ;Í|˜ó …Ù>>þ¾a5“…ú`9¸ë楚ìóì¾ M!¸rmaÞç«åkm9|p}*‡èŸÛƶ œDºr]U‰-ÑøÀì†l‹â638Ô0úÂ)y)æJWfoyökšJÿÂæuX± MËŽR6Ájî¶›¸3Þ»uì!7÷–$è ÚvXŒ!̘å5š IfB`Ø'jÖàö-fÇ•FDœo ó2ó;®. ¢:µ5úÊ÷®(:»®ÐX†2gº†jKaµk"V¢ü“u&P”f§ß‘nT½¨Ï¯›÷sMîeë ÞÚÞ°–C™}Á|ÅîºÚMLT¬« q=-f#e+;:a÷ÞËþc÷Ì®cè‰VÿµžÉ¹^#¿GlÌÇÁß9Î¥L­lbB#÷;K’˜ÁšÜþŸð~n§u>²9l4/ÆY©Ä…@ÕšxôÐ¥ÎîÕmcð OÑNâí 1¸¨] r7¹¹«8¨Ñù­½j¡–Œá¥|¡í—†åäzX¹8íÏûä~Uaîiß@Ì.@0|lóÉ$yçö“²ü‘¸¥4\ç`õ2=v+LÆõ°ŸbA?¹{>}Ý×—¢öþI6§H迼K²sjðÿûÓζÝI‚H!V‰¶´›†mêœ[Fîô­dJÞ±VìÙRÑŒokž[{2ZNʧ)ÿ¶Yh¹NFȯìA _ øS[7Û(©‹­XDõ¸ÄJa(í˜Ûµ~y˜PŽÓŠ‚ßa'qa­ñõrï±Ìn½IWˆÝ$úatÔ'ü…«É(|v«Ü@M×ýbgáD¿‰’³ˆ4µôBYÓ¸O÷z°KŒ_o'dóg9fÉ“O*h‹øžy)$°ËÙ‰úb¸qò˜ûaÅÿ F!µf}ÄEW æ ¥]“R:££Œâz”ÚÕØÚÏoí~°Ê…½´EY•l¬h÷ûׯÏ=§(DêÅaZ‡Õö;Û†0%"`Ðþßãaf2¡ùCçb!¾ôµ¶¦eçh(­M½IZÎåF»ër2·¤Ki?Ô›_r¼è×N¤"§ƒ‚üÁå4-ìx€¦‚Ô¦¶Ÿú¢hàAáSh‘*K3X ŽDÑnäB¾‰ ãÐëÊ/¥RÖJ·¨² »?ëØòSrA®°Š ZAÁŸ¶î®ÓØÕ²¦æivKÚ·Ö̉#÷ç=x§ý|¬wØ\le ”O> MØEö¬êûÓ—IźÓšš²×Æ1UJôÖÎK¶Õ¦Ì¯Rx-ì­i×þxÖo¯åþ€æ²3y©#Œ²½¦Ušwë¦ "°”í ©«Ý:ç–uvè–É‚,í÷*ï‹R«ô¾M•= º `2Î7f½d`Æ1’o´ Šže¢["7…1H¿~~žONöc&© ˆí¦VUðæ%̱‰¨ýßëÎR½[›öKUMmÑ¢Cð „œ(N•ZT{>À^¬lÅŽ ±ûtçäµZ_P7Ö[}øØ”êÍ )Í•!ÅÙá¸Ñ´JXÞBÁòZy£–N2qßñ•l(r%»[Àȉ°†B#ܨ Í‹÷3|Qs“Åĺt'¶¶½ËDÎýÛ\ði; ëpÙn°êKëÉÛå§5Γ>ñân =#­´XoÆew+Cå~„:&ÈÝXçL:89…ŒSû“HKíÃ|†ÖÕœŠr‡¸b§ò‰¨J·æñê>æ’ŸÎÅGí‡\ˆ‹ª±ÚlÚ¦†Ö¬ aÔÂN£# Ö/(7ýç«#ÄœÚqZЍþYl›{Ïrâ#Å…ëz+Xïk¤†à2I‰¹›:žÅN_'Ã…qæ’;T–œ¥+¼+µ0¾pœa¥Ý~ÝRZ—¥ÍXiRöRÊáÖòŒZðp–°éâLÀs»¼;Wèq7)8”Ƥ éÒí‹CÐ×éÔ[?)i§zÌïëÖ©"׃ai¼Î›íë8Õ´Tº‡:“‰ÿáÌÞO+ûŸ_íÜ™¸K¼ÕÀ#?÷ŸŸwëľþV± ÅVG±¯”t/x’F_Ë)#Ãâ” ”x¾2hGŒh¦í†Žl#e2÷à£8ühqÀ`†³ºVΧô5±&Ò†Å"µD÷ˆŠV|«N¢ eÐð;\iâØ\’É>%snxAßL§óôW^'¶Ýï“ ­®{»qÖZœ„4ÎÆ+MÑ#‰5•º{ìnñýÎÛ£Ï7fliÂßÃ`iõú<? 1È,ç$ ÜÌõ“!HÔ~CR&UWa*Y‡O®pIѼÒNGë2{ ûóA‹1¡pµÙË!²’,]ûgöîYnu‰œcÊ }[+#¨– :™¦“„ÕWá¼')`Ù3ÿÝNóËÖ…»ÛÀ‡©çν>…½Ù)š…1]`¶†9¿6÷™¡Þ“E7oSðZŽËóf»8ÈÌΖíùù”õŽÓ 2¥{>~}=´ {qõ/a›OËdõuÕ&c•m9E1øQKŽ02–….g¯ws+x§Èò[Öë«jè«q­uÈ-›;1Uu¾VÇš†u1Öp§ŠDm³µÉtIûÆz è¸×j­ÊCŽ´†X]ã5X‰§Æ¬>„yÄ%5p GÕÿ§Ê€/´@áÄ×´s£ÍFzñPg°‹Cót¼{gós-•G Óêæ8œ{)iÉY‚8ÊÂe }°ÓМËÒ­Bêê0ùùgÑ…?½Æºõåö;ÌIøðÌlÚ­XÎT<)Ìå‡z§µj"ÐKw¿JBaŽÜ_ÏÀX:‹ÀÓœç sÙð}›qúýÞT6£å亂-†‹Õ<"̲„…Ètú˜ÏnLx*¾©K0™ÝeªYºÙÇó+Häìn(c.„SfF2àºv}¡áת]{;RŒÚS»•å.ëùwø~X¶2!ºe ý”·='ÏuÝî–,L…|p¸íxK{Í6Ï„9 ÇIò@AÞcÓÞ?(Ól "êº êër«ç$ßÖ7§o<€„©-Ñßèêq*I@PW:wÙv¼,“¼.æRû”ïËîõˆº>—>̬,°´«þf_‹þqbH+‚VÉhÕð®¬"æ÷ˆ``”¥k±Eé~5kóø–¶á_›NåbÃAY|øÓ£Za°:ÛçÕר1×2IÍñ$u`¦u£û]m§VàŒÓ^wN)>EÕ´gVG²lFq:¶µN[/ÙßE{F˜Û§<7˜»ä]í0=³LdÇÊ$}–CµÛ§êìM¼hÿéF÷{ÛN3îSÎÿ,ÚQxcŒ:[uÑŽÇÜTÓRwS)bËŒ2žEÁ8€³o¦Á@Ÿëÿsߟz÷ÇŸ\-w–9ð1€i¯¤a]$ʯ4lYÑO¢L0µ•rÀPÈ@€1(·bXO`žce †iÃäm0ŸŽùı]úxá0¦®så+˪É[ ôEňÕZ“Œ#è‚.oûœm0=À²?÷iÚ÷ X‘Èa'ÆÐ­Ðì/¾ûVD†&hsÃðU8 ˆÁ£²¨(Пaî|.®Ô@3Ño'Mü„Õ̧¡´³ÌŸÁë,ü&5Iú~ kKGè,ÚïBFÛ-yUbC.2Œ™vàtF+27g6ï´VîWè³k':r^( ½eöN˜kMqf1…yV]i95ÙeÐÀ^­p|åhm¯%¯ÑbÇÚý ¬,8ë\hm¤Ã‡ÆA¸ 7ïÊØŽAY­¹³&f^­—á¡%Gè£;‚~¬¹¶i8«½s¿Ú÷ˆ$˜ç¬N­Ü–ßZ@îÙç½¼r¸?›àÅ&s›Ã)ÆJ˜jîí—:¾ §>M"¬"Ÿ–Ї"£åh‘0o´w5X#¤.'+ÛÚÞj?À%à&c ïûx+£…kÄ.[*a÷„º¬Ço¾·+VŸÀ玊«nÇeê–¹^îZ‡fÍZë7Lö]Jµ×|øÚnßÞ¹ƒ<î÷S^N<è@Œ!a<-$6i‡oç†Mã£YÄiÊ¢)ãb’ŒAQJú¬3Â×™;9E»(ú‚(Ñw¦5  Mõ2Ï×í÷—8ÍîR60jìg`ažd7öŒ„x=-E³ªìÏŸw ñ­ïWQ„TŽ^÷î Õi •òSRÇïÿõõ÷¿' ìöc Y}×*fÙ ÷Ûý·(žï9ïŸ_;¸”Ñ­’zkOW•»à„óñ©Ã×ö5ÀZD²( C|{½¯Ï¯Ÿ¿Îœf7aìwq…â]Á wæùKðZ 9ʤÎTmݹD£‡¹ýÖ*g4mçÕrrÓØmùý‹¦qç%! «å8‚Øöq[¿0X”ïûÐø„M gí=/½×Ž3‹4Pj²0åî@O˜—ˆJ1£ƒl¨Z¼”,BÂ\£•ä£H¡ý§®nyÆøq(v(H§ßc¸qÑó™äªaUÆ=økÐjë"ŠYx;ÂHŒ -6uÍ4îÑ[é¡ÌÛ©¯k—‚L“s’)+!cWÓ°8œ(L;%Rng4‹šÜ—LíÒÃÔÔ3ëÍÒz$QjêhàÉë†$Ìó\¨a¹igì®i÷æÅœø¤®K? 5úï=»nÊõžŒÍÔGõ´2ê|òú£™­î>ž÷Õsƒcã õ¨rRû™çëÓ­ÞÞÓÇ*Õú:ôÔqÅsqœÆÐ Ö½]vET¬[·š»S´àeSÄpÞ Õ¡[˜»®)ŒÑ¼?¬gKRëîC˜·ŒèØübÃoJ­ž„'Ï=À^ÌúX‡õ§U×÷m ¤÷£lïÖ´±_Xî÷iØÖ¶]Ì`ÖBm Õ=ìÖN‰ÓñʯÛuøgI4Yë<<‰¿ÿÁ[±_|þüÉ´?:ÄÂú%Gá™ù8¿¼ú^ä19­zóç6øíºCžØ‘Iæ#`$Î…Ú ’—Ýüöƒ‚Ò«4ì|;~67«fW–˜Îë°±í?sÎå8²Æpz°Ã2Y˜ÏûümhìÃåÆ-}vÄ¿•YÙÑy ¼ à$ë}éß¹ôžY­u›,Åt£^Ò‡Ô¯Cs b.vðá¨Ú³+¢›5U\¢4<öc³OÍl—|Þ´yÑ äqmCÉ=a«* "÷±¤˜$ Ip/Ç×k]Ÿ=;ÑeÚÏN[ä{PF§¸ŸO±8’¥à»Þ_ºÃíñ¡KêÔØˆ’y:{ù`²¶ÍÆ7/»UãÜUY«>¬ïR8¡¹,Ø‚ôáXuvDÕÅй›†Ç˜Õë¿,?^÷“ ê©Üz¹=0*5“°«üKȬÏG:ÍÌÚ–i³‹vµ[ ì½µ¼4`Ö2ç`ÅíjdOO"?w¿‡Ë÷Û™ó‘Ó²¿íßh}ýqÖÁ¨B“ïœBœâNì#¡9;ýzµ·\”±FÁÔrvâ’²Œq:ƒ…ËJ̾‹ìÄ.¨˜ÎZ0tIÜvL{UÌRfö3ö~°ÀÅ®`ÁW¹8†˜-âBë§ãþBëü󎜆{êŠfônÖŽ8¿µA`&|%G«´TcØ´ÀG¾õ´ù±ª*¸chj¿ûá6¤Ø2ˆdÄH¾GÔ¨Q“ÒBòÙíÕ=}¿v£]®Vð>,äŸÏ¯_?ŸBå@5J’¡š½ÖÇÓ¡;V]¼ÖmÒ¸=}Þµr{Ùõù\ÚσõÚë\«¹†‹6öyaÃ58¨½kZQh¼Œw;{šb®“ôv»ù›_ªVaÑ5Y§ÇÐþÒJNK€‚†õ¤qõÆÛ–É7À¦ÝÀ¹ˆò½{Y:iJj9û×$Ê»†€¨´$é#ô*ðY=ÒrUÊ x#¤U§ê÷O&Ní0k¢F}%æz(X3X ±[+J¥ÕE€°3ÛKlžž{{¸¤WYÂÖzSÚ·=‘¦fƒ„zfÕT¾üDÿQhÎúàe‰ZFöêGl¦Ö±°öÓ*ôï«V¼[Ê[ˆËïžL{U»¨ÃÎk{;iºâ ÿ;”GúÌ9³0Q¬«ø4 t¬Jª1j†u¬-^+ÍÎ0÷nu?'ËK âI¿™iŸÖŒ£Z24iÐ ý=÷¬^y˜k &ªOv+ìi§ySºùMs‹§yò#'ÿHNž¾)߇†h°ê¯D{jÀgºcpW%&`$Ð?-¥í]´/+½æipïd pžB ÃÊIÖ–åŒ;Y¯vvAµÙÙ=VÑ!dmDl—(9r§Qœª=§¸í÷/Ýwà)0U‡ ÊÉ >N–5ËýëéŠú„™³¼¾~ý-bé0hÀæüóy8œòúº31Ñ ÕÊLò8±j #8¼sÝ6^¯¤-‘vÔt­bó\aDU1\ó§qÒ)Ž#ÞªZ‘;õ¾Ú»JÖ¸½EÑüM=«_;ÙD<ô6ë1{)Úo[ìÖšÑ8 3é`l˵:ûØrÔÇ¿Xy[E·L4¤ÌÊsËðÌS DPËï+fbìUŠé’^]~@+]·º›G‰¹€ß@aÀÌmi0óó„#i—Î5KÜâXøå®¡U[%cwîHÏS‰%V |¨}+L'—’ìÙY`íw-»¤Ï¼Øë?÷Û¤Uƒ×çç}~^+çrÐ"0»¨én;Ü”ìéY÷#š£Ëi½w"Ù×`%øóðsÎYÇU¸ôò7 / 7`·Fï¿*ÏM ¸ È,’€Zª•µ\£‰4Xçj=žG°yq·,„ vs›®ñ]¥‡ÖUöñi} úÇêkÖn€rß&MUH…ÌQkaO¢YÁâ^¾äÞ´WÇ.mœÄÍî¦Ç¯*,XÞ¸þÒþÍþüõó¡ÕÂf ¾°{€·øE2Ï®¹*y¼ÿ| ˆ'‰¨m?Y«Œ ”»ŸÒ™`êævz~j]÷‹õ×ÏŸŸôc‹„i$ù´êUØÃ”&;YÓõm= j]Îuóu¯¥(Ñ)Xu±åì‡feUО׽>KÝ¢´/:|§G¬E†ZaÎ<¤…oN"œr ›5@´¯ã<­°kiÄëÿ•§`÷ÍŠ²ÃõVúc윂Säâ°–Û"X;Ϧ#/:ÐÖ¹nG•w#ºqeЈÒzïWCÙJRé±ÚÐ#ÜŽög:ÔˆìñÈ(¡AW¾"Ý[[«Xwãè™2 ¿f×Lcôâ{vev²¤ýÆŠÔ˜Àƺœ€F{œ Â\›¤Ó¤,zrÿû¿¡G¶£°àçV æÒºD?FÒ_ è|ø€oÎÞÚo‡{_äŒÉç¡¶†Ï¾—õÐPvÚ¹„Þ9°º¨!Þ7`€þh'SãMúàiŠösòü‡nsXÚó¬ÅÓ^fù£Bõ0hYªx~+½æoAW;vUê#ÔJzá+–m6R¶89S°t9v™£/z€ÚµÝWû<×y“ð'çë€dÿf*€t¥¶UÁê/Øàm8âk5{?îóñóþçßÿm›Ôàþãó#ĺà)4/ÇSó¨¥÷ãø>œCy´¬_߇fÖã/råˆ%èÀ½¥cÇ‘Érñß¿~J‚’áó'Xv,ììû>\¯u?¥jÍñõìcì¬ÁCõáÔIu³èƒŽBL1Œ¬Tö>sofÀ}Ï¢z PZê©k–Qš mc1¢|$ yîFÇÃúÚUÖMþñ9O.•x‘U÷Mfïˆ]ò:WSÏt8x”•UÖh2Z‰ƒxÍìpàyü:ú¨špH°Nòþ°0ï+$sWVbÊêãul4ëµÄF-FÕYKÇyv»I 'qò@›ªŸ®)-¦Y ƒB(vOr3Rø(oš(ÿHÎa„§µÈxìì…ö±,ÙºÙœ æõ“öøt<‘ûØ«½%o/*¬s¶0·%FéÎ8ÅÒp0_òæÙe$\*HºŸ¾ ´îv6FÚúf c·ìƒ=ݺ™êŸÜ2ÕjFkÂà÷~Njÿæçðø,?«ŸSÔ¹EhÞ:S:°$E>Þ©:ïML©0¯¢°=u­¨Š¥Z7õEìƒ@ gü#KÒvõ“Ü7t>EjwÈ,ù¶¡ùI¨÷ªžµ:ú;„b“f㋚a»î”5yå ¿ŒnM:KSl´ß:9²îÈþÔþ Kä¾ Ýéâîöuûü|°ud„ô {V˜!ÌÏñ8''On‚¡é3Y C>)`ƒ2®QÛç®®áü•yžzŽŸûã™Cû¶ =¨ûº¾Â@;1rü¼Îa†±‡ê× ëÏPaœŠÂº‚–Ò~ƒµÎËÌë&Ö¹í4sáº[»Ž{DG¾u+°ëÛòï°['>{Q4V×Výn“Gù¨Ða/ߛާJð²¶òAi)cåZ Lj©cL/êAfAû÷GõTÊ¥©Û÷=÷zoÙ?ã삱j{lQÁè×SEY5 >èi'Ñ%+â´­£k0@NµåbVàpR'VÎô,4·®ý¯–@ù~ü‚×|Ï9î(U•2g°XoC:g@Y­Ûh“­Y´Á ðCžZs< eç&ñÚ~á8\ÎJiìá=HÚÙ9UÛóÀ²¿ýÖÓ;„á&c[Àë VW¸’À†ÁöÚžX–—igï ¼MJq¯ûr.€¸þGÑÔàö pºÿ€,‚0ëÌÍ„|da΢]†‡VÂH/@OÆÁÁŒ^º&,RÑø«êäãŠ2(>ÌšöÎ :Qí°Õ,«XÙ#m8ÔÁ€hWÈì'iü1Ž4Ööôf¡Ã ˱uÅIØâ_]’ ³*xoEîO7 ¶þXZoÛ“QeÑn/GqWލ²+bFðÝgŽÙeyè´ß õ£ÿ†˜ŽýðNöP…«ö÷,3žÇIò±\ãëÔȈe£ ãìñ”ƽ>dÓ¯—DµwǵÖ ú€4¥ºÕ!Œ™qZ[é¨v¬?œª¢C1¿Ç1o›°7îÁ ÒSÏMáüA¤ò›o'Á²J‘ÝbvdõÐØ<çø[7Ø¢^GÇ“j›«ÝŽ &Õ5•œ ¤kä¤Û&*2Ù¼Jc†vÎÓ«ó“†ñ3¨ßûÍ—a@2k— ïª_VX†M„“¹ÍoI¡÷a¸“ÀoÖä`tõíCV.ü`–öyé|{¥oÌ6ÙÚîDµêh+‹®9ŽBwÚ= ñ» µJŸÄ˜ÇUûDç ÍtÊš|ï"Ô® ‡óµÕ<‚á#ˆÁ©.Úzv»/;%“fÀ?èàÏ÷ cq?LYõÍPœùüß Á¾öõ(ä8âl™²ë­u—|슬X0~“Oÿ1‚;uËÏŠý7 $ÀpaS ²@t·ï¼›sÂÜ¥¢Ò8¢”]C'ÃèÚM² $­¯Wû<˜²/ÛöLx**&qmie¸X¡2%ècÜ$O>"RZ?ùúÜNÁL{ÙÏϯ/ §vìALÉEª­'î{Râþõóçk_Nî‚]³”n#ŽÈËæ¦‡[®Î=Õôá˜Ô;€;ëâ¿b¾,ƒ„í€æ#f†Ç<Í•`/BváóöúõyWç„ö›ª níýñET³ Ñ40Ç4xë*É»c·C:ÛØœ#Nðì’ßg `«ªÆÙ„‹HšÁh¶â(÷{YuVÜw©òÕ7×`(ÒÒr.§O{Ðò,tiö—fê1Ùe=¯ãKû©¨úµ¼EäYÑèMâü¼ÎÑߎ£VŒ¦ìú_æ– ÷ï7TiÌ·,&å¥gõv‹!¯u„Y<=€••öË© 3‘„aá¾F?nvÝ—7˜S×ÿþKƪ–Wb–ÿˆ‡;ÛM+‰{‘ˆ×±]Q²¢Ÿ‰®doIa¶ŸÞ“PÏC˜Ÿ½)“ûH½J\WL† ÚÏ`ñeÙlž 6p-þÑûÐŒuÙ53m=;µ^¡NÝåÁ–` Dc(:OFÍœ?ksWWCSÚº<,]5H®×BÜŠ¸ª Þ±úçqŸ·UÞåÛìÖmóŒ}¶.ÔN{˜À½¿›ÁNöæìj´­-(³³7?g½¶'et¢J—w´ú‰Õìþeu×5ŸÌžì‘b YK,èÙRk z bûa ’Ô,9¬Hþj- `d#ŸJ³Êv¨­û9h´X—u¨’wÛ´ûƒzW:é+õŽ5³8÷ûÓMnî¯Ó¬Ì±’¨QX¦}Þ)—¼Â¡3ÊìÑ](·ïŒæÚîñ¹„Aßd×Òê FÛ§(¶ÃéìY)¾t“uÜöhv¬7FCïÝñuANj’j³•_çÊŠÐmŽÍÛãSÎOcqÕFî-UOUå²tušŽcÝ,k×m”©VéÙ=€·Í¸u$GàÎY»·Ý‚mוß~dugN²ß²?$x‘üÈzÛÆj˜%2Ýñäé¦**%/QV‰ý(L¾'‰•ªôYa¯jÇ“ã$·ò¬´\ˆšb»Ú•ÐÉ‚µEó¸íÊäVµÃ±´Ä¦Vó¬`d·w&‰nUy»ZÛ<$qä.‡y•}Dy”H–5>™H :‰®Wô(º²²o†YÍyŒæõZ9 Z´Q˜Ø;Ú…¥Y†VóòzðjY¹”.Ð-º&õ”§ )VÒÁH0TÅ9‰¯%ŒW´ eEÔ$1ÆAšIÀ–ì¬k¯V5Ü=¬qk,t±˜îfÆEàM¥fåѶcRRYW6z• cgtu‡Ùï´a-&º~ROŠ“švmÏ}¹öSp¼ÞcNqÿùõDàœÝ0ÇLMª ë±Ô‡äŠiP¿ãI€ª×õÍajj¬¸Ò¸¤™)¢6‰*»O§ÝÊKæè ØuhîüÄ‚V‰ýñ¾cªßUx‘$ʳ‹Ã¨ãd+Ì »¡àb8Xë= Ÿ ÜzÎ víÏ­T¢Uïìµn*WÎ~íOIºRüà ?Þ¶ˆLh„M—æî¶S2¸å¥&ë||½ÆLfE–ÖÐm'·¶c¼¢ ?‡ÁNŶõOªs6C7Ý?_wøgØ,ˆ´‚%ºþú¼Ÿ”%öëó±ŠXUÅ… /7.¾e¥à8«tíõEn aÛ\`Öż¯v_÷ Œ>KúÃÔCg÷Â7¬êè“â¼CPv>˜Ar*dƒ!¥Oþ&}3è ÂÜZÕnªY9@¡±[û.‚ §ÞŒý¨"²œoÇ CÈ)IípOÈÄO²ÕòвUYYóùXóÃø¿t06y"°Ub}«¬.ô2½Ä¹Äú±T²¢áz‘‹º.#``˜Í"G%EøxîèæN“‡iñ0Ÿú.hº­I\”EƒV3co(íÖ¨ÆN =‘û–Îÿ%QåhÓ;̽ €08¶€[KˆöIJÎÒñ8J­µŠ ͧð­G’‹`L1[5V´…*)êk×Z»²zÇYœÓOZb8´”[QþVxM¦ …y*Y-„±è°Qu‚~Ýês"g'iÛîÜVýÔæq^H]'€× ò¿¶ëždq ,̳R²aIÑÏb3ú¶ Y[vc­#Mn±åÄ#QU¼iEùÙ¯7÷ú†ò‹ªîþz½|6qü'øw'oqÖ—Y·` >[…þùóµ ¾O­ gi½oïŽa—.QÌ_€ÈˆqêœÀõKáÍ(N²]2~8¥jD¡ Æö@‰7œœ¯MU±«ybÓ—£õv™ëRrjãTTŒ«ã‹šshÌ>íÎnaËEù ±•6µÖ¸™}@æëí§¸ BóÞKÐÓð`³¡k¬hQa%õ-{ <9€ºn]3­¢dÈ£ÈÒp‡²y…ÖgšÛUX/K]t–éó60ÌÝzý¦_x0äx(æÒ”*­¯åØI‚"¹¦5¥Tä¬lÿñã&Åi¼IÛ‹Õу5U°¼æm ãü6Æïb0Tm‹Æp´ å[V‘a2»Ê8!º)g5ÚŽNRPoݵr^bÀÛ¿Þ5¶{Fv¨ª ù‚Ö h0d/[I Øb7âu­»Qò¢©çÆ>º®v­o;ìbL x'Ìgß+ÌÝlû4öv3³óà ¶Ÿ«Å7’3àÿƒ×UÙ…GkêM 2&Kt¢î]÷5¼RT«*øè9 6Šð”šVÖÅYîúŦÚb–¡RRÿ2Ða.¡˜ÝÀÚT©•Q𛓸rž¸}a~ÀúñŽ»ïþúé"33û÷]p˜ÕgÂ˄¯ŸŸ*\d8nuóß?_JêË7/ú7 .AUGŸ“z¯Ï/ÈfûÊB[AŽ oIO(ùžZùܾÎzVH³|}QòË¿`â¦æló¤3<µIU›ñ|,ó{Çò‰þ”}þ &“x ²în䡆 ÀÛÔ•ṗ¹³rM”£ªk–¹ìØŒhèVã D¹°+¾ñ’)·¼fPGû³žÜ¦aáe"çÈ„ÁÕWRüPbM[µ–tøÒB h§bÄM”¬ˬ}¯6ûÍ<ß‚zÏú–v]ʼëÐV¶Œ0ñì¹\0CD$Þí’2 Ð;¯SWk@½=¾åÅÅ'ñ86Ü>>®VÏk"_Ôל…låÞä0zÕæ3åñ žÛì<ë7بk§!íõƒÚ¢PÂ=$º¥mQeâ;k·£êÆ;s+>ì1òËò­)-ƒ÷™ì0êNÊ›½Æò~Æ Ç*š>.ìC´¿ÃÂÈÔÙ²ƒËò2ki,¹îË]¶(Ö¿½žÚðïr9}ZŒÃ†vcÜíw û|í8=ÍÃÆG±ûoîÖ)[pZ€«FZ\T˜ûLMØ6þ%Žðp]®•„A ×òµCtÂnÅ µ">fЈØÎi†–4¥–Ëïµ#ai¼:Ã< ¦›@*ßj‰ =ázpkó5”!Î)]ŨÓèqrX›è“ƒÈ\º¾§à•8+Ì·R‰¾Þ?]by[™0ÚÒRy.íþ<- A<hôŒtCÖYi öصzXk´@ĺ>]Ûyw¼¼ƒê%Ä,÷•§|Ѭ{=æåñ»êbku¸8›àçÅjÄS±&ĉ8æ )­ª¹t¬>ì-¶ s­;øBhÅ.û[Þ'×ê&¶p³>»ãÁV©×l'žlXï I<بr{Qõ®Šk(Yn ݉Lr™¡2ñ†OlažFv'­­²}ÛgYÜ=­j_&{ÄÈqC&Y©Çj·hp«Ò<(ÏT°`{ÙìY­ðCÛ3Ã@Á²yTàö2õìÑͺƒØþ)–]RÙÙb½Åj@â @Rn9éƒÿ󩟺8Ò±v¹³¯¤NÊN (v\…®sÞÌ<E)ÉNZeÝæ0ªN‡ÒœºÜJ‚w˜»¢fKôw³ÝÇ–ÕÊÞ1”tÛ£ö"ÖÈw˜iÔhd[ªúÂKùÓŠÀÏç×ç=D?+f-_§HÉy\NæÃi¤ù[ôH"E„ùv¶§êèUq.èµtžfæùi©lž-¦Ï¥0ƒZ¡â«+ÀK̶ÅJv{ÕˆèN¾dÀÊ8¼ôB.ÉC‘w­¥mlêa¸B†f®Ó:o8Ãܲx×ë!εçœ>@ÃÚk NnŸÔ‹¾4oz뾜tÁo™¬0¯<Ò ¾!ü2NÊÍSZ‹šÎ0·Ÿþ:µõ=q/]Ǭ–e`3ÔÓ%î?þ|Ž!wŸÞË<®—\§$-û‡ŸhQJo=\¯Àxºñ7r”öyQ¹æV'g è½ë ¤…Hk„…‡½ée©šêq,,þí. ¦J+ÖÙü}5ßð2©¦ß—U4Ò¡/¥Rk'šu½îÑl9ô<†@$ÄAB#¬ª¶)똊ÑOTÖT[y‘"ôÚåÖ1ÛK·àN‡Ï©G®2$nR‹ÐË-‰rÜS¥óZjoV•I¼̲¦sÁ_N]‘EEhàËuc{'76o–í›ôZ´·‹Eص®–ƒœ…Ž vík×zF­úí«E¥½êW)Ž£{1Ô}b-uKÅýjçWH† ޤkÝjË!׋^`Akü?êögÑ.jÚur÷Š˜•ºóU·ŽÎ\y}°Ž\ãv+éVk0­EPÜÀHöã²é¸¿>×c™Žçë¼Íý»únìÌáÎÔub¥S6ÿs•“†µØëÇ~pë¯C˜7ÌÆOèTÊùM”Ëʪ¶Ž,gžp±zë–±\­Rû†k9tejÜcNð´Ï¹äSKðQT±°kBí!¼Åù. }<öàDú¹ƒP›ºÓs"º¤u·îݹÕâÖíüsææXO_e7½Ø‚–Í´ÜUŽlî…tòg¹1ºP‡öÔÒÀÖôÛ YÖE‚â´vÍ8—ìµ:_fËéE‹ :âö%êjUÙ6E]'E÷-E7ÌÞÉŒšÙ>ÍÒV­%Ú]š™'êA:ÅËHÝÀ€ØŽø-QF«ìµ5‰ BB€æ¸R[˜GYÞfÌÌK«^›¼;:  ZZ%õ¼ÍD¼ž$«òëõ†¯uæve•Og”÷U —¤ô ¸¸h]*´H£Â%#KüOÑÉ-«ã[çî3ô”É—0Hx4;È ùþçκ•žñž‹›ÕÉgk¼ ¸«pŽÝÅÃ}¦U´’iä3+– Š›dtÍÇûá=‚©,­«¢ØuÃŒ3!.ö™vË®ªŸ÷×s}‚¬†ÙöÚQ µ0§^—1²Qo‚_l éDŸÙü½½]ÍÃdøÞ\çM6¡èª¢.±80fQé–ÎÅ™ÍÑ}+]ÓÍ=/#Ä=]ˆ,s…^ã¥Iƒ,KŽ[£-¼\ÙÉ×}é{ø’¡›Xý*ÒzЭ½5ÔïœQç®J«­ôúÜ l½°_𬾺|î* <ò’jvKCçÄ~ 'õÌMnŽlY7TåbÉÃ÷æ«[ÎEñþ¡Uº„²¡ìÄåb×ë@Ňˆñ׉Àl#ëñ/¶ ¿õðw°íòR³j$´÷íq_ÖçÓU ¹á•¹e6énI©ÑÚíIÞ×ÑδÁ è}´æV¶.SÙVêc÷[³ƒË+feÒ¤IÛ~kªþxîNàƒfɽv}ð¦‘õ‘åö"ÌÉC+àøÖPFpqzc,fy¼ÍZd·Ëì½PkêäšHzAž_ei=éXUs©þÚþu›HôvÝ×[rq­ šÝ [ÂŽÓ®³³+˜ÄƯ+Õð•idµ˜èNFl‹±5ðÖ?H0dF?h7êiÊmѧrÿ\¨Yúí›s¼¥jèÌòÆÂǾ¥”RÐ*ä3 aD»:{ɺ±çé]Ÿ0w¢Ü0œ µ>p×–“ý¢|ƒ^±îŸ“%bùsV¡ ¢Ïý|þ<¬|¬GsF±Çëu„$sþúzýdCñ@-7W?9ý³C˜¯»{:=åÿVL J¯¢íN2dà-º¾,‚°—ʲØGpµ>ç (¯õ!uZÄQÕÕY2hæÎH–¡ùxØ'neû¸R¨XމРã¡Úª2ËÚvöÒ´ƒì‹?[³ZÍn•Ýø˜íìÙ8á ¥†5° ®NñÖ×}f+©Ù8,n—2)Ì, &VzB”ߟ/ϵ+ÌR\¹vû$I¦½{õ<ÂÊ¢$`—Ŭ½Å*Ák>z{°V<~žé¯‹Ëû“Í”«Ç¬lm}f®Gû`ÍÜyGþbÏ¡f\wG¹ ̇\ȾóóhW¡¡ê ¿[ØÈáw¡aVáanŸL‰iåé\$–zì—DZÌç±& ¯¥n§ÆNs—•tˆÅ­½¦Cý­èàgÉý™´-]Tk”› ÉntÈ–}UVLÙõ¼ï”b2§$¬¼ìKݬŽ3û_•µè£Ú½ÂkC—Æ¢ãú‘Ò14V™aÉÔóu ΩESLCl•v•uL[]ç±´„mc‹:Í㪼‚„ëëb$Ó+üí·‘YêÚR<×@…ddÆ`€†²l¢[’Ûå£Ìn–ùÅ y¬Õg:êÙq+±$»,½Ën/ÁÚAŒUMPŒW`x‹ÌÉU…PtL£ºc\ë选–õ÷¹9=ÝlºW<´%ó—Ј´VtƒDÃâÂi}|~=/©ö烴¨ãÈû ”uHBPh5ÒRЏ«;”ÇI—Áó±øBéñ;œ··*áæl¨`³ä¢d¤¹ŽÙ¸6ÉFÐ2­­w–Ú{OoV6ÕES=éÓAÆW$²7f\ä삞ýŽ¥Ä6wP¡`huy3YV8qÚOäEW'í± Kßï+×åÀîf²—6ìèÛLÝ)ðKÝdEX·Å2z%R< ›Çë¾IþuŸ·_XÞê«î¥¶-Ž€FGÝ…`ÇÚN÷{{=]j¶Ï¯}Ú^_v¥J_ª…!Ø—Ñ"†™tM‚×e¨Ü)HÁ`¸iíf/`lûýnïUa‰A•W9vcRÕ–i¾ôvÚɆ,ëG”°[Ík:1ÑÜáŠ]¬5?¦À %7œêKºBüåôÀY¾=^ìï/ð0Ü|c‡G-)[@£éÛó°ÿÍ;‹ŸÑëLݪH“ѣ䜙MkJÛÂ÷óUS5e„U½øíè"aÖ%]\Uœ+/¬¢O¬F±fÜ%¥|•Å ¦";[Y_Eu‹<Óµœ¼?Db.$rÕíI¦Çúf [‘‰ñbÅ,ãÊZÐ w"¤lÞ»”T |]z²!ÎFÜìĹ[™ä6Ò’CZY'…«~´Ïk‡ŒhÛ7NbÁðY†´j¬ãÙj÷åæbõò“·þeÜ)áþp –ܽ´³µ£ïÙ"ýé±­¸¾iÁxí.FóÝ-½}Öß_'VþÜÏž. oæ+;y .279o.*`Kƒ[<3ÞÌÄ<¬² Õž¬cäŸN¿xÍgµ›ãmõG˜‹ÍVBlÒ/{ëmåÉ-²sÇĈ¦Ì< ¤ŠU[…FA}{¾\_ca£ã5¼×$ÞWë#…2ÂNݬ÷…,ûVÜ“¯Ñîbƒó5ÎÎòwÉô}µ"IצÛ+[à[!e¹ÿáÆÂCOÿIù ö0‰ñ¯bF8Ä­/kÀô\s—Ox|~¾¬ùõëŽVgÓÃÖh˜ò‘ãjõQ_¼o:æÍr¬sR„sñ^‰pM‹ö“öϲ×UÕ™µÉuFÈ–>­Ÿ“Sæñ;kSxßK †0W;„Ý•bÝàd™žî­ú¹WJRXÖã¹>övP‹;ÈU BÚaÝÓc%Æ.ÝÈBØsDü\\ÈÞ¬µEM턲©+’Â!ò>?e ŸÆ™ÌTÜ‚ÒÉøZ3’gøèîÀvîüú³4#n×o×ñÛëí~÷ý3è2p„êîA¨>õû…U—’•ËnQ1AÈáqª#kÿN”‡Eݦxž×{øà•¯×“UÛ›“ëñºÛip/5MàT4)YÚõrŽÐFža¨ˆv€Ý =P,,ŽªÈ&™v`9Àï§NL&ŽS »˜4šPT¦9qã»óïhTÚØâF«Ï2«§¼Þ¶o»ßž.ð³˜hÌ­q±|p1ÜEW>u}ÆÕO«iib §Y ò-e¶^uûî´Â¾ ¢²*¯²×žC¿Þ{ qJé&½åÐÒæYSd£–ÕvSjŸ^Ô]ŠŠa6ŒEVq=V׬‘Š"ÎjB”€£b~j½ 4F¶î„f‘˜ "«£hŸÌÊ•Èû ŒÚa®wž}¯>¹µE_eÌsÖ ‚«uûu{×Ôè€-­Ä AS¤ª—½·]£E·îÅ^¦<Íæn!ÆZ\ã"Á’rmƒûS½¡%¤ÍÐeZ<†ÉÖçôüp'  õÿC X'[ ¢?tíÿI.ßÞIüßs–Ðg¹D)’ðÄkkÖ%*ˆr£CÞ`ê•«è®Þ¾ á L_¨mF×è±Ïó¤I@Ê*ƒ“ à2$¹ª?¾7ë4õ³&ÎN|&K#h,Çšc;ß‚$?™Ðcd Îã±/uû$"Æ´n:L•6W>Ì¡­:Ù_*"^ªÂšàŒo7„¶{xÍ€D†·Ÿ/¤®û± d_€)mÃ$J14Þ,êš¼®5ùí)ró·n¢Q£€ŸXC!”ÖmÜ1ÛÄ Ïšp¶ŒRÊ„ÎlŸPâêaÛé*­÷ÞÇ^xÈi·¾ÍãÖ Œ¾M€¿·vJO‚pÜýsÿæÕ ¸ä$±Ýíˆú­#ÔæpøíºÐC¯Ê`ÍXë\\® ™‘†°Çy‹³¬êÅ+ÞÇÆoùVöõ•ØŠ\Ľ=­ô>s4ê,_´G«~„eBŒ[›|è,kdIÕ•7,A³‚N*wPA²¢­qˆ©ì[û"ÎGEi’³*´@|æJ¤·‘ˆ®õèsvÒ;–Šà)YOZoî]vJðç,êA¶uÚ µAvƒYy†Ž¨'ŒãÎcµæ&èÈ Åb×P/Ìê s5UìCuÿøpkk¯—&ˤ­ç§š)ˆK°|±ÃûG˜o‰bõ_»+Ê—÷ןR1¿e$ÞQ~ñ“ÅuâB­ÃË:- WWèéìC•öÌ#Ë0ä9§Þ¬§ÁòúTz М•Bι@Î H·Úw* ~/>ò$îfßž1ÅqÐõý¥E3#SÛ)†¡Ÿ†Ü¥ÿi\`ymè»ñIÌ8f]ïÞ“¿¬üŠš"ȺG?(SJW_Ïö(<Ð$+íЧØ´¬ŸáŠ÷¸ùÑj-®HêMÀW½A{õö: ‰7–Þ¬(š ö¢@4E]XŸ[úy·^Ò*Ê™V[kh5{톈’Oa”kÆŠÎt! t sjYÒöEÑ7q‹F1·gZŒ“5WÉÔMõÛÃŶ„ “/A+f‡_•LI©Q@o2s±ÿ1df1µªuÇgʯQŽ T¥Vo_nTÌßXXsæ22TngqO³,D3ÏíACu±g—¬Ù¨ãÈ‚Ck—ÓÜ­µm%m†Ü ,êâÄJ>ºBWu놲!É»½2){ ÙìïcûT ÝRŸ½RXÑ×;1\ï3Âv³, Àét²{*Q,«ä2d• HÖQ—ãP–=_’yh€¡}H VÅ>“w -ÒƒÐ"òæx8jª;Iëwˆ³¨^]‘ÕÎØçÙ“¿>_LÐ'ú‡‡_(ÚOmòåÛáv‡f-óoûŠé\—ïçuÞ9Ã#Šy‡ Mc ÜŽNñ³§àœ£•IqeGZq¥uÄÆvÑññõï¬gÅ¥%6 › ¹I˜8°Ìjòçé¡MÙþ@hÓçúÎvõRìH·õ°Ѫyú”<•^ßþ¹:ÄÞù½Â¼¬ÇΪÙNÞöç¹™:B‘2\0"¶TYåý”Þ“;ªËç\uSÓO…l°½ŒÆº¨½v»!º1¹Âň²iJ㦰ý&9Tæn«#Á† ¹PÃ@þÖ÷ïM[ï6Sȳ!ôßiåü<Ò©¥ñ5êœG—„¥SViÞbÉÌîñ ,¤T^”Õ—kiu“Y®ÏJÝ..Ç"ŸîB‚‚·j¡›ú²[¸ÊfAD¡> âÄL>À:¯Ä/AÏÂÊj?©FŸ˜õ‚ÇL’,½^#?á«eQ¨¬ÚÎp --c©n­u¼J?!V ïVZñ@ÛßCªåƒ²­Æu\Uªy‘‡€w[;Ê ÿs¾½7\Â[g˜Kx­Rß àÓ7ÒK8yßìRíô>ØÓ>…f}Éyë =ÿ”ÁBø:Gpo ‡wìïl.Akœ`ýë ô@7w«•í\ì"‰AU»²tó$8 Y¯<¢k¿±œaÍFëÂmV Ñànã$Ÿ€Oƒpm%ÿÑÙµ¡¸yret)dˆ› Fh5þÜnv°šyËaÐT˜ø:@±œ–`Qá,ÈvÉ|û8k§©‚jÉñŸ˜® ÇÅ.L;C‹»nCßÜ­R‘.Lðß·+Ë|?Ü'måÐ#¶é–…cS»`ÕøGüCž}öwìòÚwØÏeÀËçƒnZ8œñÑPéC—K†ÅlU¥%)ÃjÆ~*»i”7_ ì7û ŠvˆQc*€\éâ¤[çϬi¢[ 1À伜÷_4(߬³{iÿ”ýÌ2[0¸F›Ï£B$*{›ñMÓr¢5þøq• 5¬²ÑêÊ¥«Úš>>Qe`ÄÜé­Ž›¦í)—vËä4­›VJ¯iÓ$1í•ögÝ2nu n<šøvu¹/½¸ØžÚÑȪà ÔÿæeÓ—à–íû <µ¼uJ?>ÀPhw¶O„}ñmYÞ²—þu.Ôǰæ>Þ#¸‡¼jÆé¼Ù΄>˜VÀpîç‚ {u0¸ëúĘ߱'N°ˆmd~<°M/¬õF+áX‡a•k•‹XS ø¢é¥ƒ‹ ­ÂÜV—]ìˆ[+G™UF‘ìVí«GÏýñµLˆlOôÚ ‘«D#Ü‚M½ÿŒÐdè-ÉIËî[ñ˜@£òµs%MlÇ`9x>ÍÁ¯Z|‘^74ö¡àØJŠƒíÔyßÖPHð~Áüz²l”Ó…Y›¯¾ÝnVîuäQ)ûAFËOk+Ûíww„À˜•aëŸórqøày5Z³M.Ã`ج˜Ló¦šÖbжNe9-4¤r²_â¤HÛ)Éû>ËÄCiÁĸFSt·-‹Š5¿ÖO»Öo§g–ß6I$€©€ÓMP,!8¶ ,&Ö’V–ßaÏí$ÙCÖØKèo»Ÿëõ~0°?f=qv³¤ÎºÁZði-ã[‚þ2Ò=¬šqݲ€g†ÝuU;¹÷X;cce /_  ’ø­Ò´J®e|iò Ô€ÐÊÜu1+ƒ®zjçȪõ4f,˜%§Ó4ôâ:î|…Tê4?³Ýq\×É+·y´V1K¢¼oš<)‡¾¨{ëŠÖ1A\Q£[? 3?ň²^p¶'m7Y+¬o)šð í·ö[ݼH&šq$ÆŠ œ±²Øþ?ÿþ…ÞÉ|NÔµkµã÷…f ¥ôÍ^ùƒÒ*h½<5yœÙù¤šKK…?ëzÆ2c¥ uaóçFsR2F\",D­3³#=”Ÿ¨¢OEßFÐÐy>«ÇÚ t- («ÊÝì8B늖™pkÁgz(5èÕ…b,q':;+7€³}Ötbøªu`(=ŒØ9ÒˆV#Õh• Z_˶Xv©?UÅoR­GOaJVŸQQõSDZï×û>mŸ?­¦_æýùëXçaw³÷N¿Ê„aë\çg÷Y¢ 8|g%J7?ïáß4(wÚ¸R)òÂ/e|­‹[UEu“Ç·ñï_Ÿw_—Ñ è&Ç1(Ï.ÃóË •þmZ`¹55Åho~ªídw•ñ+pIˆ×ˆ8vu=®}’£Ë`¿ÿ'‹˜ï­¥:i²Øe1¡rg;ÍÛœsìܲÜØY ðáïë›–&ìiÈÐË-«(§aÙš´oœAYu¸Ú[>öq)˜Œd‹jµXN‰n/«™ Zìf7¤¬ÊF—Õ˜I&'¤#eå3O¢½Î[v+ Jõö. ê ºÇ„ ZUö!g7¶uZk»w!Ë6UíYB˜±µÙíYê€#e—) ]‰“5¯,f•‰ØKHÒ¾‘½Ly…u[Æ•ýC3ÙqDÌÞIfWÝÊg/rŸÕPöÆr™ƒ"9͉yb%B‡bä ˜C‡$í ê0‚¯ÓrœN(¤ØKÿ s*v2UøåÇ©©´¯ýî9%rãv¶ò€éçDŽ0X\Pöxœìþúùë§ý|ðQ–¹†Ýò¡ðú4¬b^ö ‚ º¨­Oi¬»û*º€¥Pªd¤nXË E{g‡¤piÎ|niF‹öZŽc•Úˆ«¾Ÿ«ïuØxLna<‘ º}›vZ¬ø± gac Ã|Ü~Ž ò¶ýÅ ‚–ìš2Žs¶*3äБ×D™6ïÐh¶ªÂ[­Y0švÜÂäØ÷ãþùy,vÎ2éa5Ssñ³@DÀ:¯nUr«‹Ø²€ýÇezýýóuw5:¸)n˜¸»D» õÓókŸ×™dUrÊ«¹)Ç&i†»¤Ô²îÅ\–gl+Êâ´ö™Ëô´V½¯ƒñù8âI^Ë´˜œLÈdSI°T±Ýš5BNuwüú\æ‡/k¿1š`˜Ó ^¢Ð›â!°º~ÖÜvóëï/‰^Á)lÏñlÀéΨ¥-3¦pfØÃÖs½ {ÜwÉÕ®°A ±¶ioüÇ8g ‡N7®kÝ’ø†EX¦š¬¹É"ñèÚºOÇZFˬNâ:‹+„j2Á2Î0ÏÃ-±ûjÛPX”G‰0vö”4BüMH ­ `Â|FÙS~-³õáiB”ƒä«áÓÒK5PýÐ.k (Ç¡Úúç¿ÿý7{]ŽwǺE1ÊÍÁûdkOìPJÓng:ž€‚Iæ´â:<Šñ?Â÷¯ÏÓs ù K5M²í4 Egq~òɃfì©v°¼¥ë5CÖ‰L’¥}´ßOjÆ!G^`[”°Ûôø|Iýõ5‘ŠÅùçXn½ ‚­9™w=0‰»o.Â¥•¤´²0½²¬a%ŒëºZ ~»fvZû–Üb&³åò´£VŽ®ÈF†BËh œîÇÐm?]ØqÀÏOÕ·lQÞ#óñwu—qd-A§Vw² 9¼‘±î†æÂµÛxXs?î÷µEf»=(«úÇDÉ‘ñT;¥ØSÓ“+°Lê4ªÊ´ëÊ®d àö«Ë*Æ€[«‹òçªV<_¥Ùkî8Ìu3a R"ˆ6L¨üÊ$Êž~Õ^k¶v¶BM±ž­î1Á­qQa³.»û¦œª¬‘?Zm±b ¹]œ¨,õ‚éÛ,0ÞóùMÞrëèAdW³¶Öh?sPí¾”– «v™ ÿ¨Q¼Švû-øMX毮9›j¢pjóg”…Dt³—ÖÖÖ–Y<7? 0Yš@ZÖ©Uk' ÑÜŒ lŒÆS¥‡“ÃÊÁ}ØëÞùËlãòÔ>|„$ æºð£ýèÜ=ÉâH[¾ÛID¸æ ¨ÂÎ9 AqMŒe¼› ø®«?³Ï*$’ò cébLÖ€+ÙÕU¶î¿*¦Z³X³Ï Þ@)3%Í%†³¦q]¬nE”ƒ ¼O³4ű²ehóîùóÓóëâV'¹Ì‰â–éá—£pòT˜ï¯“º²¸áèãd¤I§Pex°€uéÓ¥ÃúÎ^‹ì ¿¥!Ã×$>­Æœ°s•†}ÿù²“º=äÏÌÈ¿9ä—‚è¸Èán¶*ù«í!aÅÎ Æäç‚9÷8/%^uë1 íÙ}Ùgn…¶ªúnÆ-!ÍŽº¿¦ª»®uïÙ~rt¾H£† ö¹O:‰nq"eÁŽÁ¬sP ÑæY?ÉËåñ%úåÌZ¬±^~FJ2ˆAñ9P¿´p >ëH‚}¦¬[Î4¦A–eª¢ïÒ"kT¾Ð[Y¨ö5¿ ¦6Îã ÜïÐ×m¶Wj¿›AzÛÖ“5èL›)ÂqIªÑÁ·+l±@0Åþµ£ëƒ jÕ=ÄÒx­ÞÏŽ¤¥•¯Tp¢MnïÙ:ÚÈN¬]++ÒýN2þf $Ž-Y· ãØnÈ“ãácGÔ›ÊhuÍ­Û3Ì(·*âòs•ÍVâÒÂ6C“fQb)Q‹±M³îGŒpª}Lny ¾HØ·ûÆñ1¨Ù…”•j¬ EÃ*§ÌÔyãðjÑvFWˆ¡\šKÈ9ƒ Sªn·Þ$ŒiEís¿ûÇâ0®?šÀM´mVÖµo_—ˆ”4áNü4m·ç}z(E‰T©iÒ?/§–ŒDºÅ>dêUŵò–…iÓk>;›—:ŽóžK ~%Ñ6KÑmò|œÊ¸ÆVÌŽ•»Ô]*™Ì´JdàBæýñù»÷úõÿþõÓ¾¾M³3¶Ð]³¬Ú&UßZ5<¸jEeÅfÏÒ·›ö•gWù •3*F½ÚÑmæåvŽà %‹&_º!°^oäiß1(‡ž±JiŽ.,“¸¢J?²J¼ôˆ)Šõ÷ISGÖüX'(Y×AÛ²’ÆUw[iEO/è8²^=„yá4v{äÖO1»ë5C'½Š(-ZÇñ³ pçr·¢}psåõ؆º 8ìBXvB-kî» û*©×™áOïÓÑËÇ›µžgÖ.{Žàþ‚€„ŸéVê2½U·,Úzú§»[ëÜï„9÷±B9ŒàöÐJ‡õîôÏ\PxÕ^Ÿ+‚Ñâ,ƒ]ÇÖž#¸ÓœQ ¦3¨†E¥|nŠJ¦U2Êddl'ÓÿQDûºÚ¨8¹5* ¶Gƒ]v¥%²[¢$Køìò³N½ûv5º³œ‹+µGË#H9J9ŒFï©9·[®±#Â’½“›Ÿc³öáñz²4Wéh!~ŸÚá°Æ_” 5õ®sìÎËüÆÈo._2ÝWß8hþS"ú…$e*«ì7ñS¦@~v€¤h8Ž9:•ÄÊw¯2fÌav‡Ër‰¶+‡qM>;qò­ÂpAj뚈“åŠjDçu]ï_µÔù.Utt8ì·MøÜ3!.n4ÿyêz´–¯ìZG µtŠKØ8Ü)ñAí $³,.¦3O‚{üœûaÅIaì¬?°WÈÄ:Ä»At§ýö¿ZK²iiEp=î»{:Œë×} vûæ ÓÚp:°‹`òAéy=k`B\Ô¸åvö÷¬]ʨËQ+še±‘øÉ¬YìÖ!iº"ë€ÈÕiÖu¬¨zu…R†óEE¶¥5F–dýc¶®eý6Mæ=8–<©jzP‹ŒKÜÎÜ&ã ¢xô¡jÉçˆë&@ddìf(qüÇY¥[­'ÖmÌ ®*µÃDÚ±É÷»ÄÉíG¹ü·°ÁÔDÎCÔJôfi=Eë‘ÖÖòx\ÖÉ-C8’©ÃÞbŠ^jy˜cÌádÔ”§hÚ]¥V\íß2ê†ê–â;‘G–Îí–Öia¥®“ž0hjÒºàÒ"ºœò¢îr¶½xäÖVb#ïnÜe¿·xi°ºËÂltîuÆ^Õ^|é€ÄË…0ˆ€¶u?CÇ_±w-ée †é ¯ß3¸‡†jP}*î.0¬½¦µÊ=¦ÂÁX]Þÿôe³j doon.² qÙâ°²À´Ó€ÒÚR„ÏZé;f‚h8€À³®ƒ~p& ±$ï;§ ¢2¦ߥUegÚk.J˜þèä^Ó§Ú,Qa †~}¼ŽÍÅ]ßÜIýྛÒ™•ŒVÀ÷rX'ù‰'­KþBÄúi´6Áìa·´5©ý銄±2 ?©ˆ b±OS/ë,p¹ÂMã8,ŒTV…· â®ú²ÂÏ2ÃZÔãkŸ³Ô¥–ÙÕÝY È1‘Ù³ðœ¬*·þ"Ú¢ªbÒÀÍ*ä­ÐDN/èLæ€hbuûüërT_󼙥ðÐ . ºÏ›ÃE“hûÚ-ÌQFj-t#¾S€@šr˜p¢@ŠÈz;UÃŽ%Öƒy731ׇQÅÇ:)zR:Ö3퀇ò<¦–ã§¾ÒÖ¸ŒÑŽ_]Næ,ªCG¾?]J8ÀÐA±¸ú‰ëƒ»X0•"Õ„OÈ)ƒ­€k ÙÅMPI‹l•öƒzI«·§ylÇ e[rK€ l?ÂÜîÑY>µöÜEGžwm¥=ª­…jZÏk¡>unŵ8¬3*÷=ùÿÓõÈudYÖ.È9´µÕŸp¯k­ÕU™YÖÖóPïoíã`¾×öX•d„p?gË%´yПêNnˆL¥ê̽f&ë·Å6Â’ ¸Y`mµ'È^qf”Wš½ÂǯG›”£iuÉ_)S! VZÉMöaP0ì6o¢²ut÷FÜÙ¼0HÂdD]ä‘Æì¬Ø-¹q‡´ÌJ/'ëx]óòÚd ¸N·#ˆG)Jߟ¡wÿã'/†ߌ5v5EÒõZë„ÊmYµKe5j+ù ÄnûdÝ1Z§Ð–£e{DÒ+K¥ÖƒÂú‚h„l'ö# ­ž¯/ñ·ãǾ–´ÈÅGÛÄ(! C‘ÚµÝy?+]eç{”®äÄË}ì¯ Š ïÀÞ¯;‰‚1grÅM»n{¬d·Ó^ ÛhUvß:À.¹Å‚$ëª÷¤i,.å¯Shð•Pq]ÃÒ¹¶Ê»š ;(SŠ—u¬…àú(W”]eýÜn1áâK~ù`nŸ8b&Ë0Zõ^2‘¯;ù0YqábR«e«ÌgQq ³˜C>uvF>’¼rÇÄ´ b=NïÔ¾ðb­·^L½N§Ø¶ç>Pj|s&ù]4©zkê‹¥O€_÷•V†a'ŒÓéZ¸§î0ýu¤ŒK7êêÜ¥´)[‡‘»†^Ƿǧpß¾ôÊŒ|…{ÀlO‚ˆ¹þÙ © +Û«A';ë” ±•^ת즭 ’,í qèÛ ™$ ÏÒºöŠ,x&]÷]ø i\)¯—ªÎÔ4A©®,¦œü2·¨8*“VZŒö“L¥€²­s…†7kIøemrÎø4s~ågtCÇGÿùׯ׃«mÔúÙ–.ÖÒeêIJ~{‹}0×iº¬²f®›€Ä•ÕxÓÖ¯Ÿå^mOù掹]P1{ÐíØÇ Hý‡ïO€j; r(°3­À º2•’»Ô±Ãž’÷*E2½$ð2 œAÝîççq<®"²„±+‡á!&ýþãXò‹e×*»8…rQGë)»©g:îs`!-Œ?¬$à>] ‚̦}Œ(BH$ãšÇß׃g¦±ÒÚL¬C«¨bËâÖñ¾EUÛÏíý¹íâä”C‹uq·‚w£‹õqѽ]S¹/hîngЪÆa¨k´¥¼Z ›D‚É0r³_asÚàïÕ pXÙkiDdªÊXDpêåg%ær{¬5Jù[œÕm*û€V ~}WmP“±JÉÕ[îŽS;A¦‡Õm«µUJV0â@ç#ÕZµR¬mÆð^E»0s[èpŽ\Çäæ þ·Ó^a9í:ÅŽ¶7ÇÏŽûc;<矓ݗ«üKpâÕ5ßæoŽ™ñûÞ…QرŒŽšpžÜbñâ±Ãúü|­Ó–Ü‘mí.Õ(ôKÀ ¡jGé…ÏD-OcêÔæ®SÚÓ$ßmi[Ì·µ4(z„Ý2ïëÁ‚”b¯•7áŒõò¿³®^ÊUÐѲjùm¹­Î?¢¦ÇyEøü´iËETÖ™4:)ÍŽ,›ì!?iJí+Åøpµh§ÉnYe±ªSD¸b­L´°JA²Œ½Eÿ¼¶›6ÿÙ’½ƒ"öà¦l§u•@Ãnæò {ÂPuœÕ0ŒŒ•Ñff˜ÕØM¡dŠŒúJa5ãOAX?ÞêL×¼èÄ·–7i ˜øö¢›—›+wZæŠÅ·+½è˘¼Û¨ë¥·ÚWrµ8Öí4óö°BOžDB=q(±ÒègÐ/kA-X)Å\Fë¦ícüWÑîÊ8]“DyrÍåÞñ…vr Æq^˜²SÈÛ…¦ÊêŒd3’%ÖU@!äªeí%Ò©ËœÛ&]ãÅs)þZ=(3Z­vMhÊâ«ÇÍ'ù ôƒ•ö‰Åã®õú²º\è`[Ža´3ª4Ù»tbAÂÕ\ušQL Ó«”¶“×¼·e®})åßfÇR%)Æ4]ÈuUyW”.ÁÅä5ðºäšC¶ïd”´~à %éÎ…l/{_ûd §½L󱻈×öóѣŬK®¥¹*Ÿç`EÕeƒYG‰1Š:žŸöÍ<ÛÖeá$ÍÁŠ·“¦Œˆ5¬ãìd§`õ°žŠ’šðmòmWwª]{pi †/e¸VžŽâ(È‹Q`’°Øœ‚éÓB›O£¾Çö­eWw²L Í-#®Ùã–Öv;¿º\ I‚". 9pMAÑÊZBãÊåÆ4~™;Af I0#¨Q/¸Ï3 „ú:q œi íLå I(Mªù¶þÕŒÃc²L „Ðyn£Âש£4t»?›ïÍšu¤ø “•ûô}kaªh³EMÉBS« z[FxW`®ÐÁ‹¶"H¬Õñ®È@e“V农@Wª]7;žË4ÿ°ò9vÝDüêê1+ð,²ZŠ-ë8mžÛV`øÜ^ŸÖ¼áòÊ„q#õõâ"MÖõZ‰.,yŠà¹PS¦þêšñξi6ÀxÙì¾X#颕ZóœaÛØ5Oü@beâ}°|_Ù×V¦×Kœ¹| o2%. ª¥¦jÕ{UŽ·U:×ݸ?õ‰$Q°>!®–£KÒNm«´xÖŽ ,–Áêõ}–ÉK$œ‹tló Ai®yïÒg\O ªõ¤!£/a+67ÛC@ÆÍ[ü–Ùèvif¥Ê¡f×5ìzppaâÐö9Š¡³Ôœ(êY]רe%|Ä"£cÓ7'ÙîO+@gÃ7¡µæ¹[ù¶ÞÖAt¼“°3º}¤c^ô„îKPFže¼=ìÊwÏ“Dûs à¥åòÆÁ¦«¼eÜËi ê4+ÀNwz²+xØóüûïߟÖ¿Ní:WªÅÌ Å´Ççﯗ˜9Ûë÷×óq,¿ŸPú×-;$Öxs¤Ú¶J Ê>Ž˜ÝÐ/íôÚ¢K“—•ËAËÛp:YÒÍ=m·å5»0õD‚³ 9‡|íÜBÑåV ·¤7zl'íkAdPÓÁþxoî¯Ûªõ“=ÏÅžòÐa›~wUíÝU¿ÐM¾ëäÖU”v-hÞWø,Çr‡å5tQ‡©¤3ôó:»Ä±¬mc…^Ä*åN‹ín¼ýæ dñx¢dÕQÁ¶‘ ‡cë›éGÁµîê¨D[y–æúÑÕÌJ™|Ö´8¦Þ–NûQ­ 4’Æ. ‹ÆeDLµ° [ÄïŒÚŠB~hö&^Žšnëñ÷ïûº*¶¶^“ ,Kí)¢!5"*Ý” ȲgËlÂÝÊ¢]“ O=ÔÁ% ùå’Û•‹rFÕmy)Ä!+¸¶W`5Ù‚Õ43«yhðÍÆ”k~Z¡Cu,Ü»ÄOHÀ›Ž:êÅçW‰ø-ª3h´e>4>+ë%‘dç&·{H"žäì“UøãœNn:¼5”Š k¸òlCæ®R‚˜ìõB|ë;m½O—D™|e^ô„…ú°(%¯{µ°ç'^ºw»pª°U!°jë ËKÝIr„žQÃaFmK:¹ßƒ5âˆOÒMÐp»«æú*i­ ¬+l¯XôȘY||0>N‰@¿U„ôÜÌ86‹¸cYÍÁdAv6zrÚKK3„'Uˆv <æLÓáb1Þ7»o‹ýZó´nOü+ì{\ާÆ+s}ÂêpÜÐj]W$YžŒE”#,ì H¸KID%C•ÁêÔÎ…ifY%¯H¼jDDªòîܯy-Š—°ö’UaµÙ~{ž{ôãñ’‹Ú'k»ßa(àƒ‹˜\*oµ—ý•†]{t¿ì{뀭40¸Z‘”Î6Ù¯ídÁœ²° ب°FP¶öB‚Z`ߺæVã‚ßþÈù ·°~–óƒõa’st4™Ëʽë×µ§õØàçk8›Œ³G?‘¼©{‚¤NÛ½[/lÏþ~¾nÅ0öhÖSƒÃÈšÕ%¨@g$)š5,Õ’°`¬)Žd}Âãaé,wŸgUè|¡¥—•@PÁéËrøÈ{f½:1*#Œæa}ŽV)Ë—§Ãiv~žÏ£h½7‡¼®–ÆgøÈã‹:ÈYK¹ ‹öÀ.Æáû¿y*“,–[Ä8;¤RºÓvdÜv»Ó+Ê»ÝoFår2–—PÛ¶ÏJJlãð›F)µMc‹]½O^1he…{¬Œiøn|š Ñhgcß‹àG¼Ÿa4°PÒV·íŸGgÅóH˜¬zGIP&:*öç?Þ?,e‰dú-õYy¤¥š{mÕvÍû-§'×(…7âŸ+Þ²` X€(äÓ)ûw¡FéHHµ•jÆ>§¶ÇL´wÂMøÏZ8P[E¡ÉkíJIÍg½Õƒ–ºÖw`Ê.öFKý¤¤¹…Û} *¾‡úZBî}Û)y|¦½ÀºvBï®9nÁ‡² ë5” Nõ[0ÎÝoR’ ZDrV{—}ÊSÚLܾ1ß—ÏÖ< b±ìÀý~t…C+馠Ø= ±¾IИiÔˆªï혤”B °gkÕ‚´…ÃðC¿ÁRI‘ q_YûÈ>¡[µë²‡ß»Ï¼VÌ$vì•¡†SîNm‰y¨eqLq$‡ÚÓÍO‹»¦féâÛzkeô“í-=­Ví®o ›«ë™A\r­¶DpêÍÙ°–à5ÒŠÅ¢¼%šÂÚ³‡i(®Ťºt Öƒ²¢5éO`Æ@5~+ØQvÀâ4…h€œü±ß}Y-O&;¯ŽIÅÙ~HÊÉùÛ„”øú²òÝz¯ÕRñAZ;ßì²ö «{(¾v4‡cºë´ê‚iÎzÛЄ¿ß;XÉ*á;":¾šhÿÞïÖý?¬§®!NÊK4î,Ÿå/qwí{]ÉÙ!VréU] :Y´ÅAÕ>¸5Öq&h›ªÎnjµ·Sgß}_ ΰ¿4ƒÜÅ¢(ÿQUm`&¡Z±ž°î±h#”ȼ]‘ÁJõäzu¢Š}ÂË5–ƒ!Jú²ƒ¹4¨ëqTeñÒ1úÑ-‡>`…V<›£9dŃ{œ¬®É}»£þàQ äß5ð7xn%;Fs±^Ì­À§A‰YT‘°â“K5Î-_öQ¸æÄûi>ŒÐ€;X«PlOÙZ*‡PÖºŒ½ @Z‰v8X†T/ôªO¼Ñt éèìïó±`N ògâ4Íœï²yy†=û·ÇŽèi±Ñè‚g+ Ø©ûNõÀco’/NˆÿÔÒì=žGÀª»Ò¨7aÌìñw°ïUFWö_Í΋y/£¿£ÙQŠÊ)#(T)å6|ùMkÕ&ßÂÎ㶉•ÕÚ YÕ%!ÒLÎ2 ÏˆAY :‡ÊwÓÎ Bñ¤1ÈëJÈÌJÈ „Ø·Ö¸â@b…®å£l´ë¶ÏMÁ5çñ;ÞH®c|…»÷æžÃÖxî*-üñH#œ”— Yï¨Å¨ëþÜ÷ðÞzë7×q}M¨P>­˜;æqÿ|.žFŽƒi½î·…¾I¦÷××çÃ!p É9þhRöÊ…¯¡T %Yïì}á-ÊâÜ9 $˸DùgZ¦ ijá¶AÝŒ)z/²Æ²4u| †…ÅWW¸`]׸F´‚:˜ºCÁÌ‘’Üu¶$'µUùÉyÍKxßU#•Ô¢wÙÒøÇU%!ʸC™ãØ3—u HŒÑu®GÇbq¡ºÑÓµ+Ôj":…ÂVî°AøÒŠ×6l^ Š4ž×¼’gU‘~´#ä” ÿ&8„Z‚Æà©›Š°6 ½q@ibÀèʯy£kî|vfÚÛèIP9®ŽlKeÀK…j½ù·e9že==Ò(â®ùãáƒùcÝ-<߸ëh¾2"¢ˆãÁs Õ˹Wç»9n3ÐHkSÉdØ`¡x&“ÜTNÜIää±×‚ɵõaÅ‘õà le±ëÒ)°Æ-f: š…)ü¾›þŒC¿‹Ë]L̩;ª&ƒÃpºÉÍQÐQ¶ÈB@<ËÖ]ž µ•a§Ö¨øfU%‘µŽl4t:Üc¨‡ /Jdv^sYlgh„›°ÓU—8ûyeUR¢–@d†¥È\gÝdCh‘®Ö'¸ÝôÅkÁ¯ÝùþäæÍ}MŠ£ÂòQzWÜzu܃ðEϱîèí–ðo‹½Ñay½s0¨\W"â’~c09Ï–Aݼo?À¼£–n߇®y™]¯’ñîE7À'wð¦T/“Kúðn§¡´ Ɇ#LQ©¥›Ÿ_쾇>J«zä²Ñ¤µ¼T²§_†ûÓKRª²Ú­Ž+™b…ÈÑe"Jìx’’kÎGiAêÓl!)‘º(T–_s9,eÒ„«Ü{¸sz™ãØ/„ý)»8œ ªYH|lÁ„oÏÎç¶uìbì+³F¶Ï¢½ #¸«ÕñÓ@–¥Ö${'²Ÿ.…Ûd±Ì׬kÞåY´‹š^Û5fbÚ6š— °LÎÐrH´mº;ÆÍçÎÚ 8'ÑeY‚<Ž›=ð}a»ûX§úˆè&l.#÷=ù]¶-Ä&u ö}dÕÉéȸˆàkGšéÐV‹Á¹•ܗ廫ÚÜ¿~B³óÅŽ÷ýBƒš‘?ÁäøLIìýúŽÞ\ŠÀº*>xžtè‘Òä`ÛQme„òk«‹v‘²ýáÚÚÄØJ|ét°†ËËŽ|€\½ÈÕs¥Ø›|Ëœ+„½Æ&° 6;CˆRwTÝ–‡Ë;’ì:|3D‹¹_d<5Y—¼`» 0xQ„l~;äúlŠžá.uÌÇ+kœ-%qÍË:½\áj*·Y!v›ì~Xõ£Õ7ß*¹\xÙð_æc*‘U†,๵éڥ˭žµô#­r¨°5y%HÁ4àZ¶9,r°†’œŒö—°Å36‚´ÛuÕM"Ç>TW&Çk[²¦ÌDL6 IâúpQRhäÚC(tR Nhÿ»]š›é®ê-‘Ù]p0²zhïeýÅÀŠ}Ý9‚àµä}÷P $ …©Ïig¢×ðÇö`½Û‘«‚I5]~Žàì~##Ð:›¾#Qe»ºÁ~\DŸrg:Ø-€QQ68ö°a ¾æîŶœ6 Û÷Oœs$ê¸}9­Æê!5­VÁÿfCï ÆYR ÏÀwëJ+‚‹ºw‰D ¯Ï¯-t¿?ïš({ÐÙ°@ˆ¨3 ¢”"ÙÏ¡øæç­’zßœúïgÕ±Ý?ÿþÛ>,WfΫ¹ùúÂ>ô)ã§9Bù(®ÛÙ~=‹}Ε Ž@ßÉh[­›;“À'ª*Æ`ª´Nð|ÛÖ£éÍ„‚jÏ\!f&KÂá“g¹ÅÊaë’FöYìh¬Ã|Ûž»Lúä{N÷ÕÇÓžÔ× ÖÐï'â2Kÿ%‡'ƒ3~=_;$Õë4hþþýù|}ýýïãõ¿ÿß?î_â•â_ƒ*Ÿ¥Ç50ŽíïY†ßío­ÒéDË0cBo[¾ßçv5äuf…O?‚•fI9‡j¨¡ÉwDö˜JO—¨ivœÝx½[DT†BŠŠvÉð0Pý¹öi»Z™›dùG£Ãç }p¯¸k€ŒÉŽQŽñ[m½‚ó™lôØÃT©Ù£×’vÆÆ¯yç‚ ¶ç5OëkDw^”×8úYó]{¡vµ€¿ÌL)Úlf€IDATÚ\¶Ô÷åõTøÿjÿDIÏ“×çã±!YÒäcG0Ï…šÓK«<±Úà8ºR"1í0»#Û²hünùr¼0 ÷±âš·é¹P³ê¿ݘ‰¾×uÍQ»C#¨ÂCø+$Lü4¡^âÉâ¾A bj‡Jéj%r9Yeþ ‚×ѪãÂlw'MåýùuZ©ÙCÌoVzNÓkÕKeоT¬'sû¢(\†J;Q†z‡H2ºV\£Tc@"Ø_:4»Žÿþûs·ŸZ'úùû_¿ŽçͪœÛ¯ÿLA&1ÄÇeÙ­¾=>¿>¿þþ¯Ûvôÿþzìk/ťɳ¼=—¦ßÖn±[óü¡Å`'¢ñ\ƒ#I¥9"Þ{YIù¥yõ,;‹aé¤È¡ú µkÁTPE!‰È’P|M¯14â}-ÒFzµe;™…d»æ£5Ó”hthïÁ!¯,-I´3.ƒ4žY.û¹e×'CÏçßuÞÿº£©JðeÁþïÏ'Xj„ÂÅf]—;ò=”ÿþm7jñ’‚([òÎ/r#°Ü–ê[L„ŠzË“Y7¦ÐÁëmÖ¾j¬aæ®[o‹à^N«! Çv°¯{aÉ·ï¸!X­ý––V4qs›¼?º¿J$œ¬v¶„ )µ—ë´UŒ·Åúº§FL“Ö­m‘D ]@–¹ÉB‘_±UL³î¼î€TJíê‚>ᔑHb¤#k)Éé(íþÛEÏÒ=ɾÏꑨ\½Wð¹•ÚtE#c1{¶§¹çâyvðèý~J‚ ¬kIÌJ´Òœ5]Ó~TÓí÷½){ͦ !¢ÝÉÝEÑØûî·?íj<àG :ߨuº¬\!eq±•,XšârÝúròdRÑ^õÓñð=¹²'¾ûîzâpÌf÷êÒØG9uŒ*Y³ÅÁúúd=o ÐÁñtö ÀÉ”·-£Ì¶‚yâ\¥Öt5EœÊÀÃt-Â?ô …5¼$á/ûy×@gPi«Z%{·’æ×æª7XŠýÑŠýÇÖUý~ô,b|#’¬Âщ ×dÝ~ò²ß¬Tg‰nX¶e4c¸´vóÊñV]_ŠJËÝ¢kҶϪ¦ìré!WÒWRº±‚×J™›}ÓÙ{Q¦²bš¤ÝG‹=·ÕI:¶ïÅBƒngóš=|(‹&,|-סÖj†ªËD³ØÛ·BÚ"ˆP–b»I2NVÁ7xªÛýD!õ÷þ>ä¼:»½ ¾NZ«Ø-¾YÂ&—×L³Kgàñ:«P±‹ur5{”}³õéQ*g(¯–x#rUóÜfÕhqÌ”u¤V&kب,/Á»Ãjo¨í‡m¼¼ÁJAäpÛÖóÔVÝXü“±8ܵXfËÖp ¾ƒ[YÓÞÈWþä4¥ø9,æPC¯qL- ËØùàüB ÜI)]]èúKêÑ.¼]s¼–˜¨C‡ßDj6Bj£ò¶Îý ÇÑt—±Ç.o®0ã º Î4;ÝÀ×¥]Ä–Ã5¯ÛdY¥Ý¸Ü¶aÔ:Œ±ž/€w/¢%ˆ$Ú‹ õ4$­°‡º ÅÃü‡€X ™4Ù¶4>J‹¢]ÿú׿~[ôþ’¾£ÕÖº†«ë¡Yµý<-÷`Üûæg¿6TXcS²(mž½ÅyÍE±Âb*蒻痈즪óškènU®7oc†òvc¡¯R>Æ—Í÷êð ŒgÁçYlÇZaŸO{yûzäŹÝméF=:íý¥E>ÈSid¼×åñ÷/g$lû¯_¿¾Kr–:þHÄÛ‚fލu¥+ÜXï‘×I~àµÅ§(8ç $Þ+}—pUà`vŽ’•ºî­ @ ÐŽ[”[J¶<<Ôí ƒšœôƒ½¬7G|wë®ïÁ‘ÏH0X{ìûCü8‹xÿþ²¶úñùëñ ð dárÉ•Ñn¼æÞl% ͈ÑK­õÿÊd×vWS¥WkÝÑÞF?¬¬n¹¿Eëy0¼(­ûìŒ5âQ-×úz QXì/é!ŒÛÌ5ŸÛ—`.‰wV5XH«ÞãëE×üI56 5t°^SI&r°Œ Ükwœb³-Þ# °Y1 Úì«ÚĪ€×O¾RšgI½-Óþ¤l*œ\T µª-½X+eõ˜&ÁãùcY÷ØâÖÍâFŸËîª/DœðɃd>_e…®9Ÿ®dšdýˆ½z{~½X¦m¦^»j/ª®‡F"£[üÜï¾ ?±nn,¡‹p’Âv î‡8Æj`ºÿþÏß_H¹ZÛfÇÁ½S‹}>?àép®¹Jõö=‘?›t§PlY²®ç5Wîä‚KT\¯!ûæE;ž×\ÛKk.*1KQŽõÂ&…á&•[[S˜Ò½ª<“D‚òËïèÐ.@Óî#ªú{úµ£3š€¦ÒºK+}«V;õKPñ¯ýûq{Þz¹s”tù:û\C«òâ’$¤{i·µl­…þDm\½U†QÑgrä³Ô¢˜$ó^‚_ 'ÐRvCñh$¯çmÈé!+—w®« F8X7·ä…ýehÝHyÙz«JìÎ ÂçËáyÐ÷y*ÛÂÜž«.ØtMWð!Uráà!  Ö-nƳIsÍžÅQ‡Dyýœ²ô]¨•U`~ÉÃÌYìÔÙk¶üÕ«Ï aQ„\²s=Éc Söé_Î[I’NªhV• -Md=²Õ9{/I(“ ìãhm¯M1Ç's’Œm®C/ ;QÉ[Œ;ZVN•ßòL“M+æåÅLG#Òžà¢=ŸWÃî$SÏd¿a×<»¦uùžvR èƒïŸ< Yº.yë> J3ÚšskèÕkãòa_³}Q”1Žop9ìÓìÒíàôg‘±íTNÓü-ÿG—«½} ¯—½KK;.¨ne&,\­7Û§Nþç ƒÜf»oâݸU/†5· .ó4þY¬=Ÿn—z¨ŽØ7‰úõY–ø¿—^±oç±ð|°øMÒ6™.ÝšÈ~¹ò±¢>¯¹Šb&Ëx«‰_dnfFÖ;É\ˆCo–ãî¢\“Â,‘0ìÙGÅ +gÖÐoÝÉÞ"FÀ,öSÀ⻩„¾BŸ¿;RëÐGãßd3øæyéFجvsȤ-g²n-\Phu£uK9¥V±ãM¾îÙ%ÎR ÂL×| ¶ëV½÷Œ…Ëh´ ªƒ>(qÓñyd!.4- "ˉ©ÌC,JÚq¿§ ³Â²NÂëÁþákú·MnÆzXB_Fô{×Ûç Q7%ÇÔÿŽÛ´8X½¯#GßL.à8è­_ü³üK+HP©-4·׉á?œŠ_£ÓþA{öб¶×f)mYÛè'Ç ³"š¡xt©nµ˜V!T±ªê¢d©žù2›áÇÚœäCwÒìÜÿ¹'ðVÙ5òBiZ&W{ÜCô×kŽy!o„ÆBnGgngÔåüšóo”f­t¿dÓðG÷_äxÜ¡ -ô·Ü ÷Ç™Í= ¯;´­&Ó5GõÀ¾H r–Íß»Ûó¹ø5oÄý¤°ÉƳìË*˧KO<‚àò~{=Ð=¼Í֕ݬ°:Û®7Ýüíé6ˆ°¸»Ú•Þfÿüz~;cúÍ\UÉýE_ç2¯nÁDí÷„2……Á~jÝqÃå@áëüïk.ƒëivñ,É“f¾œ‘Yçß×¼@ ¾qýAÈ|§k<ˆ£Ðî¡=Ш»¹’e1†ú Ž«Ò©²Ÿi.*ß°LuÕOÁZ{ ofÇ€ˆ$aáDîm>Ûð½iVTYŠ‘^pÑãsÛÒ6dq++ò®ŽPî6IJÈñg›Ž­/ò~;>Ä„å°ëä¡+˜áø5ÏÆÌ ÌŽd–Y@וּ֡W„vùµïŠN+£FLøíùzlA¯CÁhß|}ðøúýë—½µOvo‡ /îVö8¤  Å«6ûÒé?d ç·Ù‰½Ù\¼Ø ¢yȺMªöÙí]¬Åå‡+öŽ=ÔV¢Š†µ° SW‚IÄtÈu;0þr×1«Nšy?¾ŠŽ¤š ¥J>.í½¾ùqÍã”§À¬’Ý8˯ ‘ÍÑ;eö+j3ÄÝÚ2¾Ø5ÇäÐ*q»¡‘ÝîÖÕ”¡´þ&ÌŒ"gž û–¡EY’ø~7ýf'"QFš T˜ú6›gÆð ³ÍÛý?+ʺÄy8.4®¦º/+¿æh¶êšçÅÏ›^*x¼0(]5ìZOåt»Õ¤ñg@38ÙXÞ›íx}Þ7äìÐf²ÿiûñë÷“Í™ÅÑ[ƒê¨¦cÿÖcW^çš3ƒuõP/¾%—°iIë£ëå¿« å m\ø³zª•9Vé:ïUy[`òë(Lä±zxèºmq û¦ðj'èrI®—ܪglõ¸9ÓË0îÇÜ0¯Šk\‹M¦bÔ‡`”ã˜M7è±dÖ 0€öÉR 2k ,Ý}K–…ü9}×tQ10¨°£4XÖ»Ïß_û8PðÇsÔþìË *hAìd²xð|ƒtTÄÁ·×}¶ßÎÛpd'Oê ‹]çÊÙ–Žü´±?h穼d?Õ‚&²MG«ø­Écù°àyšz‰}SCÔ.ÙYg—ÌîõÜÖýZUyÖZÉ ¢ŒJ3{TOðo«êúWªÉYƒ©‹‹q¬ã8²[WÖM¶]Cà©Q”7¨¸fÕtÃÕƒ8×NHuÈ3ǤF0J‘ðyÖà[Æv»ûÒR½}$¸è1¼ô“s#Ìí×%8®¹ëOT}!©ýYk½€:z9ÆŠ×*ÎÍî—åòåv›§`‚€Šˆ'ñ[PUõþ.Z/¦Ì~Í‹l¨Gw¹Öýn>‹ÿÊR”¥^ÒäFå\g8ßu³#Á­à¦Acç-ºâñذCã†åâz{ÝV¹xÞNÖŠ˜®Ö©ï'Ž–.ddûù Ì(ñÅwg¨v0ãgôð4Ùöù ðzðÛõç5w}Åyd`D—"øÝv d˜7ß½¹ öpqUˆ&–K˜-|YÖ E­egë?÷u¾ŒÎv*Ʈ٠@×ý!s¸}éªáØÚà鸸êÌ<ØéÎ^.WX'vÂ"»æ…c-œö™JgÏêù¹5¹Ýº¸\_„£¡Ë¢¬*Ç꽨®eãñ>ů3ΪÁCkGNK3”è?Uª×ù£ã¹P«»¤­Š¹&—ØRíãËZå©({û Ôq• ŠÛ¶Ž° Ê€ÎA¢)“1ŽQáOvVHtë}­}¾‹’s‹bÆCÅ:¸9,Ùºåf úb1ᾃårQ y"Ö‚¹+¸"¦5äãy߯îõõiÇy{²ì;œ»æRO´7 ˆvÑ8e—÷ÈqƒdÄ\ͯ߯mh×cíëñmPÀ—‰Áº´Y³EüSjÌöíUÖ”÷m <k5—̶þù¯¤.®Q÷Øís]ªMkV|ôžÒ68ÆÁ½›z\ž’L˜Õº°ëi)º¼Z_•eu‰ÊB¯Eßü¯Á$&ç’§Qt½Æe}0Ï),D‰ÌQ•œkؤú\wÊ9\éýùy›†íuìÞÄ:Mß7šdG9Ú8½I´$µpR§¯²ì:ÓØVò‚çä£req8tCí/ ÄÅ>'¡Åî>¢OR]?÷§R–šÜŠa@9•ÎöÔrµ”?((íËù‹ÔjNŠŠÔÖÕ»‚¦Ôcm»å±OÁH†`ÿ'µ?dwrÜ5—Çš¨}Õe3?~}ÓíñŸ_ãþ”#u!grw­¡p†*LÎ LâýV8§Ø½ÂAƒ×y¿ pò—"ÝÀˆ`’ñ“…Ï@'¿¸?žÒæ³……âlÇÓÞÌcï›~ÿÜ[V'IøqÅ;7Gø[rˆ%m ?Ï­WÅ—]£Ø4ÎELiÊ ¬b#ªE;Ö×µ¼Äüœi|žÔ[mÏô¶Qꃬ®k‘©{¯qûúbo¹kèD6UdŸz»-Û –M—3|¯›"b娨1£õ'¡dØŸMmlj+ÆT‡„Y›6Û ÛËûÝ[ò)$õ-T[o¼ß–_EKˆÇT–£]õrzþznÓ¸é`T‹Ž0‡_ð½­z˜-},ÚÑìÑÀ`‹ ÍR“¼`z°4†2ýˆz«–ì/=ÿïßÏL[Šr84£ ãü¤ºþרöUúþÿ¾\£ëåbý‹]Ķˆ¸‹Ö\pÉ!´¯ÀŽk«?â,j,¤“Žübµ‰ˆ‡vùÉxØkM=ì¢ö”Xz¿~¤È&ª·ð™n¬I²ÿÙ£ÇñÊ`›’"’³fËDI´âêœp4,ƒÒƒõ€z¶–yqóø î%›3(ï,­'÷·œNu¹‡pÄd‚c?±³oP@Étø*Nò×B4ׯ¯×SõŸ’ìg7°†¾90Ûn« Àvv²»{©‘Š¤Ë­Y󌨇ðp0(oA ½´²£›-aö³ª‹Ó<ÉQnè­~Шqœ!ºß¾>é5Žý Û™iöHK*Í“ó,襺¤Uay3ßÇÜk…/†Õ.Åw&ŠuhìfaD6ë\>‰ÕpÍ‚?ë¸ÝìH©½vŸy=‹ñ¹—ññ’Yý†ñ ÷Üš³è=+.ª{ 'ûf‡i´ÃµY&’ÙGÐo†aÇöiꬼmg£ÕŽÖÅñ=Èx3)¤“2ï—¬–¼£]Ð`´/Â:*mk J’–54g·(ÆF—5®tÆÌºŸL+ÝHh³\h't†,*ضk¾ qÈàñ°”Ôï¡•Ü­Tÿüý·f­½­cžo¯OÔŒ0~›×Û‰`u¤°~¸qŽ2„=Ùþ9·ç¯ýõõÀÂËÖÿ…¥H%ú£µIX\âɾJìôvtÙ ÜàœpÏY‡µìá”â}Yíš'ñO­µìôÙ[\Å—.h^Ø Aû¨ÊŽÝØ7w+Ò‹f•1ÚÄ¥¼Ÿ¶Çë±i ×ÁKyØd—:ÉÙäWé%A‚2FÓàþ×Ë^Ø~×.6§1ÊÑ»ñqZb0ìÊ$ún«h'÷í–»ÁMˆ#‹6‹²ËÜÜ~ Žžì°˜Ž…É×N±)4"õ~³€‡Ú-µÁXE6c>q¸ßedjï4hÅéŽòyüõüñßœ·øÜÇvôx=­QÝÎùò\€XÎEL¨ã10–ƒuí.ª’4%$©ë~Á§Û ³9VzY΢]%úhžÍÇÛÒŠ¶ËÛ·ø“‹4ŒáóÞÚ×jLÏÞ ˜1áÐÉ#ãèEú¶xS½ž–†Ÿ< Ì[Eüw¹•¸ÅéýÓ®90F¡T5{á´L§ðò©óÆê´m-X†~sÇ£µCWY·üÛDJb‹Pr =§!9ޱLãêÚº§íh¬Fc Ò¨€)ek Q‹þL;¯Ö*ûÚsªág4Ú&+pƃl¾½~;#~woNö°&Û¿^ZìL)¥Œ±Úõ§•vbÌJ ufÉùr™³&îc)T1Y|½ä-št}s£×ošÆz³‚¥šæÝ|¡5mxøÌeÞàµYY5Ø"&•EôÍ]t-kÄ×,‚¡ó)‰]Ü={õ8’Í oEr½ü¬¶i`o ÉoëÀÎseìZ#ŸTYá@ƒÜê ~DœÆ|¤Å湯р»Yùã-Öo÷¯ßöÞábûùÜ~ôh#à¦X©z·$^) *Öº%”z- çR¡“–þ(Yb[-6Æd½¸+âôrÉŽ#GP‰Àéåg1ìDé­µ aµØò|a”ý¸­žŽî4¶L†÷ ņ¾l“ "¼}˜¶³K{QÍ`a7×bÔzŒšçŸEÅ5A’â-¶c€ór‚A¤u`Q.'°¸v½„µ\Ýoóo°ç<û‚MÍ1)>pHW_caͼìcÆ ž tø|¶<¸vuœÅ\{ɪÐÉȰԜd¸ãÈ¿åaßËÕ%o çp*S|Š“r|²uÿú|Y Û­©þÃBOqü’Oã©Ðú¤pºžÅ6Çøød¨‰Ë[µÕ©}?­Õ÷ÜCÔXìyƒýG‘–Ý2WIf˜9â™PŽ5fÝhÕˆ}£Sv]ôà,®ÝaÁþIx·Ž¸-Ü'ï´d«'È"T]—-xœ¦Jðml¡2ÃB…t:È!n˜v.N££âæÈ+X‹ °?˜:¾Ç:´œ+QW™l-·§‹»,BÁ¸¯ß¿à±<ŸØï\m´z{ðk˜W+ªø½¶ÛXÕýSÊÊô}줈ÝKÂ^³C-ÚÌ}ñ¥i‚Ÿjf?‰¯¨/[kÌ3VOœXJÀH•vž e/oç ½±‹xh½UM6‡FØf2ßZ¹•Kì­i“¸È<Í×ud¸-·Ú‹¶"òýjAùž”!ìK°"­šÄ¼Å*8Ì*ÀÛ()dõðǘö„í¶ñäÇYEä徟èÏÏÏ}´tƒ 8£Ùåøý÷\AýGÑ„ {¼NXN³›«´¡Ês¸üÄ®Q™´ãnè±íA¯õø¼ ÷üV@µÞØÛªõùæZûû¶áù עˎ(–uH8t×(|8ûw–.»£É, NJõ°1·°ôS̳¯].Ãssíòk\5E¤]f¬é’ð#v%ÔÍKEyÁúqfƒV[Ë-1Ç}b„Þõ·uPª5pƬ<ÀØÍî,éN,Ø`È`qÝ_‡˜¥»h#B:¡ÊŒ;‚F/*‘á£h…Ñ5âf€’P­_»’k®:¯t¬yZ—ãP´”_òèC«£ÄXI‡­ÏŒþXÝ5)¶ˆÈÆ ä3¢nŽ\Q28Ê‚–#fxåÇ"§Œ ´,µ¾ÞþDc7fTÕc_Ú`βÀYÄTüàŒ:zs+S†íq›-º© àâÑ?«¯vq’Õ‹=‚Œì”Ç9.¬$;¦A¥—Ö#ãÉ^ÀE<òÞå¥TàKÒÊ+HÊ¢«/?kìå뜳íôÐA°džºÚ%¿ìSvV1geD-nÿ•È•§­ÝmVqŒ¿˜˜WÄu ;~ätë_¸O]'ØÔ¼?4©°Ú!º‰ã¾šÅ] º%É<à!ü¨rº*+Å­¶¼fÕ{lß®9 PY5EZš]@žºÍBNú cëÛ‰ýv•Á‰ð¡ýäšóû\«l´è(·ž]j—éžó†¦djíÏè Ø7ïÒo-§ý‰’$û¹cñÊ]T. ­ÿµ¯ßæ<î¶$‘ C \_´!…3¬²ö<‰SÎFÕ/ì4D3µ6Y l©ƒ€n*ß·ÄÔËÛ/綨<7¡FÉõ4¬Z’”W²àPm÷y°b€­í©}èÚJ´Ybî“#ÕûlÝ´ASRœ²r£^ÖEIjfÙ¥Ì>®Œ^òðÃz`z¸BJŽh’aÒYL值 BFY‹æ1s6»ôÓˆdŒuì×·¤×yid|‰Î½}öný¼ ±-ÎÜì^Ul3akª¸èq©Ø-ZŸÚ£ç¿SÌŽ-´JPnO¨¯²0+²&ų,k…ʳ¯ ,PÏãeç©è. ÝÍ%`ogÕç¥äÜ»mf8=hï±Ö²Àcª‚ª„FÇ·OÉ´(„ÐæÌÜsÌS¤¡ûa'MäÞ2¬#ëŠv©ß߬ÊÀ­£ì æff²8”Öš¶ëmaâ.±«Øêkœ}X°ˆ…û/¹…Ä)‰.eš´W{AY’6ó2H=Å ›T—gÞ#­ÁuC¬@u¦¬t°BbfËm±ÒÁ^Iš—\§.¿_{V¢¦Ü,…¯iñוylµ½U VM Q´o/@å­ `}na¼àžµfô‹8ïX+þë…Ìÿë×C¼h8 >‚ûÜ;&˜, c;Ç9›^ÙE-Ëf4hV¾2§Y cÁ°~ÑxO‰® þ ‘©Ÿí§ò'¶ì~ûü×ïXïÙ÷­^†S]Ef)ìú8,b'J+êq!À­ÉJH{ç§WµŒo0¬ž|ÔÅ´Ž Jw|p³rä¦d_JSðøz}Y^ð÷.ûá%K}]ášI 2írwï#ýýÍo¹JšÎ÷Äm»Š¡6 ­”7‡Fp(÷k€‡›ààÂ~Tãw †K×q‘¼GM•…É‘ÕtVSXŠÕ8àÏsÂŽ´!«c,žÇV<C\ö]I£lõt+Ýã~¬³æ¨XP‚Ó„æqÚFÍ} , æ‰Œ€‚EU±qmòj´ßj²f,®iÍÇŽ" æTËî"Øö·Ð)´è0¬½õð n,ÀDxøœcÁ¹TZôÛÂŽk¡Ø~îm7läËo¯¯æÄ7æÃ7T™ŸÂ=+ÉV 6ÞŸŸà-V"Ùí.¯MQ/¢ûë××ëñ³P{˜Ü¢Ðka/³ÎÞÞ3KÖÖR-ëquÂ4'½Œî ¤ykÓìòÏ÷ÒJì~øÇ5MS«%¬…²ëã‚©=y÷Xæ€v¿‚†?1t:ÌÒó­}J¯_ÕÉG\™@ Ôó"JËT’æ"î°·YY–¾ÿŸÜyêY,~ªuá±ü%ÛRH%ûx—TÒžn׉¿u8a' @ÑÐWÑüv{ÌË B˜¡•Üf*-Y.ÛÖ©¶f¢o­Îd>\Ù?ŽìL­ë”œ³NÿmF¤É>˜Ä!Ò{[ú²prÚ© wÚ/¨•Á¿Ü·{&"Õq\XÕ?‚­“+$w]޼"…YœîpzF;ƒ¢ÞÚ9‡s¶]4Œ~}ܦnX¿ùþör§æ+ï‡õ”×(±B8ªçξZq}ýƒ3ƒ{è0G³Gš*ÑaDÕäÀŽÓ·Å˜«²n’䬪~nâËÛ[T\²_ñ¬+[YHÚ•°Ãàóíiñòôx×<¨ÄNç¯;'-µnrÁÖá`Š.Xå1èY‹ÁUFlw¿¬JòtCiÑ3¹6ºè«ôÅ!nYžŽÕ×]’ÖFpßxv5F“_s ”^oÔÇûê€3™6 PñÇÌ5Ç2ú¶A¾Û±±eG«Õàù{Ͻ{°ŸZiH5ñŸ~[¬~O¢\˜» '@}¯k.qg:âü3É¥u¤Ω÷öTt–Ê™7×dâøžúp<ü‰áõ°Ý/+ŽŠé•j}îÆ*ë&MUA%î'…˜š^XPpw3&éš-Kÿƒ¤SÒQ.cö… ¬r ýõxŒýâ£Yû˜äpÐî_êßÛ™ˆÞÉ#£#cÝ;K68c,Ǻ™Ñ ããØhÔ^Vš˜ !ñ"~ËÜ@NE´è^ci5™£¶¡¢¤:X<ŒRÊäôÁÝaû:‡ê¼æ£°ÍûM ±X— .C#+.T†êãçÕÞ¸ô^Òk¬ØÆW%Éd˜ ÅU}uõ5µ¨T¾f-‘Jj¸æCÍ^—am‡ ŸzZp€òqûL3TÇ,úYݳ«»ÖkÕÆš¬y[˜åñµddÈwTåa¯ÏŠð!úëZÒ«µYéÛ” 5‹N•µIýºÑ´_k;³eù.TÑÝ›3¨'vD˜µÜ?ýþzÞ¿DqQ®Ýê×1-×Í–ö¼™ÛßD|[-ᔌ¤„ %ÔŠ¡ÂÕN~ E¢åÄ2!{*ÒûÏrhø1¡<e¿ ®¼>Woÿ¼2fKwM­®ã’åV»ÓöD•JC:Gëm„×=³¹s’û³¥¸oê¾)¦yr-š&WàÖ! “j›æ–V;®­Š©ûâjŠ]yA¡)UÕëÂ…Å=µ$0-/_{—óîÀ· „Ë9t¯¯»›Øì‘%t€øöõ­pÚ)_æ o·/L––v¨²~FlG|h§Ú+üÖp»ûêÎÞ `¥¼ÉÇlÏß&[¿ˆœ¨ðo-ÙZ×ÓìüãÛò©]ò‡ìT=‹%v?,ûáûùc÷9íí>¡ ‚9÷´¿¥×xÇgµî$·L² ¥>Z݈" `v‰\òD–bç(}û©É^¡Zð€.Èó¸2¸ø òÒûÏæïãkAÎ`ØNIDsפï?/q”DŸEµóÀr9×Å‘˜ŸˆHôÒ"©ñë¶c×m”Úñ%.]Ñ5K}ð]‚qcé0T…ušß æ]\ÚÇ5c€5mÓºæs•¼ÒßFF¥®Y:H± px’c?(¸Áñ¡`Ù¤E/Ùi«èRkÝÚv:Eî,'Øm§ÀÏÃþk=Q– oFëèN0õMn:ûa¥¡{4 À_<é:Œ¬¸ƒÊd‡¥û(>ò±s«¾º®i\¬ÈQcç#Yo]%—´™å†nçÄq«J®ãîºG<Õw–½õðI÷—µTËÐt³Zî•æËu!ô·çpø´ØÜµpÕ,&päçÉÀ4åÝ\³<žû<¯B-:]J²9I‘»@ dŽLÂÆV;ÿYQ”‚­o¬%±Kƒfúž[sÙ1˜|àFÙ¡1’Ëïí·À˜Z¾µœ›¨J¶›•F±ÝuÔí¥Ÿ ¸^5šÇØßg±?'ïØ­€\@X?4òã÷¾¦e~Ÿa˜šËã(•WeNÕîE»ë»çÅðVNu‘0•‘Èl&…qHj”q„©éÛ· ŸçÉ›9Ø…‡¾\×Oó"ûïò‹-{÷úÝ·_7µÖÞpoJMÒ“iû~_­÷)ÇJC8#–Ý$s£›NÚ›ÜOÅ&-ËIœü~:AÎõ›ÄêÀáôùüT@^Ú2©Ö};­ƒJÅ> >øO6ßÏU¼ÅiÈ»úÂÆß¥ý—}•é>†‘Ð= ËŸ¯µ¸||¼>u)&ˆ¥F…Ifk¯¤[ب…ÓŽa×Y^ í‘‘j¯Ô š?×ülÒ™öùˆ½ ’²tæx4Z*ºpŒ2wÇ ZLv «è’w`'¬Èž<Ä Y´ÑÖ&VèW $¸Êœ龡›Rá@`'»F©M?;êQ1}@*Ö~Àþs×ÉjO8®:ciصE›«ýA‰á¸f&DÙWLMòž sgÍùä&v*Ú—8ÇÇã7ºŸ¿~½¤ ð|½þ?ÿùº+Ö»Ác‘Õ¥]q5ï·çï_ŸÒ êªÈ8G/x}þ¢4CDˆœ;2½lÙTÚwÝ5VâŒlE Û_éŽÓt¸ItìK˜bÚó¿|m“Š n8ÍnœVü§‡^O9K©—¤*"d]©± aö3T_ìÿ;üƒ,¶ƒcIä¶ÞÍqâýòº;+ DY ˆÕÊÝo«¥ ÿ²„ѳöi2™Œwv RæjפôOÝ¥{VeßånÅÌ—ZboÖºYÉÝæ×¬mqK++èD%”½.Âav¯í+Ü,êç–z`b¡%Ió!Ó4•Úº|¾VŒcðmy#+Këþ>>êÉ' €/à Q†MɸŒ«U8 Lò¬{d—ˆk—é«öGŸY÷<12¥%ç¡!ÔfÝ%µžž¢Zh¥y×Oþt#ÊA”+¹F‘ÕËlÓè…û먳FÙõ¶ ÷ÎM?;}rǨ~¾×z Že}øá‚…ö”#Ýv½¤¨Ò G]-OW)*ŹPóŽ-Ï»ºIº.ƒúsLA'ʤ_sy¥ÔMËb†®Î.>d¡ùl—׉9ì“nÏ}_æQ®Œ|»ËíDî—BoíUV7y½ Ç>6iÜtv?“ØŒõð…»wÓ^ P›j4½m=¯÷ÉÔÚîÇhyOm•V õp\Ǔһèä=±B[Ýûþì%ƒ/À ý‚/ð¼æ±óëÑåŠ&+ñ–Þûov\ulmk Õæk7n-ˆ½ÚèR”—ˆL„ðÏ‚qØ?È9¹}}‰êAƒš<®j99ð¹)•¹½²p7ÍÇ€¸ÿaè;ð©¼jvÆËyÜ÷m:àãÐ[²+ì”[©Ð¶ÌÄua®ðÁ% ïÞ¢÷øº²´ôç³ÉÍüî¦æêáÔRÌnä…]!y±aåµí÷Ûë¥y‚‡§mÛºgT%€3Ëžqʯù,üƒœ‹mü,R­g^:áBf‰‘k^Ib€Q»ÑÞ%# ›5cðOXÏëìãuµ UƒÐÜìƒücçõ”§cœ;,Çcܬ͵7Ziê‹È½ñ *gÆlpy+ýk•“ª¶óUe]ÍŒv³Ž’MÆ$Vïˆ7õ°h™J[…©_ÛXêQ!è&+íü§æÏÎ"FtÜû;ÎOê5--lõU”æñ5ë¥áõ¤'¦­¶ŸjÆfßSE¹%”Yë֦Ůùh‘ùsKv£ëßr¡F1m8lÛ4Ÿ£û?×\3Ò›N§„ÂÖ»&=Z½hò:Ž~zqÚ2EŒס¾ÌÀæXc‘¹þÑeW+…s¬d¤ÆÓ[v·ë’§ï¹Ä´]lÛÎ"¯?W_øÇÛÑ_SÅZ'æ°WK_~ùÈšRø`IwŽ®A‡íOtWÇG¬'h"Ìiç>H&ÚŸl-²R0Ša T&E¼ ‹~X·òúQ—È2<©D‘‹¬!ÀhК^>biƒåÊ( háÞÏŽQSñ{Ó(ÌGé”` ¾•œ-`Ú‡7(HÍÖ%cß$Tsƒvpoe¤usýØhÇrÕ8Z‰7àéD°ÖÑëóh ¯÷¸ŸÔ_!«q—Ró8Rq–›Ü¬­ù~ LƒÌ [1©Öxƒ¿ÿ?\sߟKb‰Y“^ñ<=ˆÍ‰éK;ßJµ ÿVºPqáº,jK„.#CN.ZáDÈ-¸è @¼PÏî*anÞ‡³#²Pdé.`]ÅÙÒQÖ6V¢cÑ'ÿ§®yV8TÊ땪tëí5BA´ß±W.‡o0Z™`Úi #ší˜º±¯{$‰’kLa›2LÅìŠ*Kr}_kkƬ§üÃ×ÒŠ±TžfLv,b±›ìƒùR¦ €Ä(^ÔƒÛ8{æåD‡Ýd6×£/›Ùr^"Ks©ð 8¾ËÈŒÎMVUè#Ö7ºw: ÉÙÊ‹±·fy@ÁÑ…{8Õ2V²:üÄW[ó 6jöl"«X!—NiRÿ§5‘vÁ­=N$: ‹ÀȰ¿öù@nŽÝƒJ}•,{ÓæÇ]‘ŽèM,Ãwö]M_¥Wk^&Úüo×5ÝóÓÉwØûUö?q–aJ£ý¶ ݾ^þç‚hý$1ƒKê¸æÓ‰Ã 0ÈÉOZp§°l¶ vúÙwû$QìïUãŸ8kXΓ™›¬š8¶w[6e©WŸ`‘ßslʦ§ÃCNõ¬f]s”Ö‚ÙPÒ|ݽд .KŒàhçµ}i©&ëby àp³D´’Ó:w…Î…Lì_§zÌ93»}ÿðA›×aж›9˜ýxvÖìtJÔ*ü­‹¯îLeÊ‚ ™¦e=ÿ³(ÜÿO×üìèÖ°*qÉÑ-³d¹Í ”T׬Ä%—´8×.©K°3%èçr‚Öå"ÃÒ u¼$¥âI²óª qõÚçÚűý‘|DH›±÷d¥ø)%Ÿ$ZÑZŽº^KhÊ´*ÈJn¾ÝܼµTÕH´Ù®d”50YKô,UÓ4®9²ë­%õ\þ®EJAÈ>´wSÛ¾Òþ EªT›ôr¨¬F°Ç$ðàú5 á:m 'm³XÚOë(¯“‹•  |Í&Úô£ç¯÷-1anâ¾Á/š‘/¨¨#™æSç`â!,ÖÂHª¢ûkÐCáºðG~#7‚ùnd9šÆøî×\ÿ¨“+N&µ·_eÞñÍ·Cý~iµµÿ¦*ø„:n[Ä+Øsa¡j/†ä*Àåòëåz©@Dõ€!åd݉Eòsfíïk®ÀõjêÀÇ^×Ü^ì;š|1ÇӜ؎RllÏÕªùÇ „áìÚ6ˆáàÑ€ (yE ¢ò.q/â[§[ãš[8s¢$¶,Êí«¸} ûtïï©/'FN«t6æÈGè¸/][Ííºö9ána€ÙXº@ü±X6©osŠCu„bo§Òª|ÕÄ9TA±ž×tÌ6»*³Åš•ç°LA3Š/„Òœyüº=a»ºÈžt‘f¬íÿ÷\¸å“àNàÇ‘[ÇG§“þKïÑÖž?Hx¹ò%l측Ëç‹åE7I[gscbMÔÛÝÑ:³»î›ŒmqïýxÌÊRŒ»Ühc$¾u’½GIÒw©È2»äç¥:ù€Ò­¯Qûi 7f…ØÆ­¤Fàà4RJ›möäj' ³D ÅZ ÷œø«–ÇÊ xXM×~[]ªÚ¶>³Jµ6Ù2peêM—·ÇÆÜG B±H–}²Â¨ :p•ƾʛeÈ£Ò.‹…g@ä íX ë…iKÉQ“rÅù)ÄëV~«fFT·ÓNCç¦;;01óZû!ÝÞvPCÜ# b‰<ÉSœw¯o¥D€R½ýÃÚÖ´ÀUì_]›C=ªò®…RÈé³Ç­§Ôâ½d#9Zd%€;ŽM"•)¸4Ìò`•Ú›Ëꡌ’†­/\{£¸›ú†[겚vnÓê=ªFŠs¡¡ì£øT03*-#$bÁÒ¾¼X"-xìõuZN=`Óº]$´,‰L\R¡ „Y ¥âÂÜ„M¿…©5‡Å±VÖ“óú:Ðû[­E÷y8G±;Íû}tÔø`·ÄE°+DÜc#béæG_"›ÉùiûyÓæ—¨µFùAr:ñ Al¶©{ r—XN¸mq)¬‚+“8‹XoÅIZo‹í8ÙS•²'ôâ±ÿf†‰ 3ž×|¶y”ô¬˜j}k—þðG\3Šãs %×û–(bä×X•¥š‹2þËòÏ8|EèUS_&v×3¥„œzZÚ]ÕÈÙþ“›‚œ–u2&ö(ntî³€i·Ë²DÉNÇlph{l[Ǽ°Òlo)sk«ÒÊ4)´­Æí¶‡k¾íášû}gi‹—€óŠ«‡®S\ö±O˜¿&•XͰËŠH±Ý(ýìïù5_ƒ¯£4%âjgkð‡šã›’IW¬w’÷Ô–èÈHX•5#0YB+$“À™û${ ¥)â«W]É÷®í*;Õ m·œ€ùðhÐËçØ=Æ6Ýþ%Þ¥onÛXÓDV?W±¥ñ6‰†.Ö6…‰[ªR,ËZueˆ;!(iíÐX—pUº¤$¿Z{VÂ#­¿¯y,Å8™,5S_Ä¥fk}:X%}jA_†©¼ÆvÒÜ 7Á^¶pIr…7ûvæÁÚö·‚Bjn £×H’Ú‰Šÿú@PÜ’]Ùͦ·`f\ZÕÏ~?ï€öI1X­Ç+¯ÇnYáöý^æ¥ê(_þ„S>9š¯Í k8;wÞŸ]ì©ã ïqÜi÷1k¿î ñŽM ˆ¨¥_%2f?¬•¤ 1yªdNÃéG>!Þv*nn²ÃåâZð²ït{ÝJ»ä|ò¢Ê¯W;i×eWûõåRΚÀ¸ ¯Š~.}zð~Bi‡qá7LfqC¿Û ÿ¸ãÝ7`ÀZ^?¥[óŸ"C#iW¸í¹• ¿Öñ³j){û¨zD\¦©‘)CÁ¶H@$lf ŽDbo–`LZ%ïh¥Pð’wF¾ö C¹ðC(!¹‚ê{"?œ™lëf™ëÇd½·cÜÈî£ÌÇ­hš§Þ*¶u¹}¾\ðöãù ¥aßìùýnž¾WxÅ4 cî¿~ÝäµÑ%è—u?Ëåñ8©6ÉL†Z¥:²iðME ”6÷'ˆvkZ6~Ï ëe.9s ö€nÔõ<æiÃ<5Ã74±jUD•tzs·›¦Àª‰yx'`í®9‡›S9B5É:výz;•g$m‘@Weé ja£HÔ3¶ujWЮŠ¦¾ŠÓ®Ï³]î&þL«dgV Ph¥FO*ï +“;ŒÌHâÉOûªíã[“Oë]§BGQ\v-8‘¶-º½{ïK·c—ÛG/r}“ÖWOM–;жÚvš¬^Œº•Û^cOb9"³ê?ùëg„B‰u ÝrªüäÙZ$}ŽÉ-ÎK]:æïíTdÎÂ~¼¸ V©ž:a&#*—8îÀó #²7{brÂêjÍ–%è¼ÝdUÃ' ®Ð½·º=é0éFUF_ùS+hX¯a„*³’ªÉÞ“¬Œa”õ©e­`A9L®Ô¯Sòv‰ÞÏ}¹5©0X‰©×ôqÐkìæU”,mÏ`3‹Kà÷0“OŒ³¦)lÓÄÓai{¡Š­9gÃRq%þžéŸ!ËHE&{»ÔVØ5샽92íZÈØ1¿Eo¿NÜ~·Z,³õÔÝ¥«„Rƒ‹€¼ýæî7(Wƒm˶!ƒÛ2ÔËÛfšºç\æ-òȵ4°krû¾óÏM¼Ò„“µkiå£Ô_q5þ°:®v pÀÃ*èÄ’§+buƒ¬û÷¢lQKÜU»­ߎï`¤Ød™3ˆ\zì£mv²“+Ì^«n$÷*ÓÝY¬ÿîm›H;p|JWnöaé[kk:¦ÔÜ%H 5)¼,G°¸Ý$yi!ÑG2;Å(›…õ×Qö·e +ÁG#ÎPê´":³ž2IÚð«™“ ÀMÖÅ,[{&eíP«è·R ¶3‚F±Dhó‹x¸éÎúöÅ’Õ‹võx›óbFè±ídZlíœûZ³YFŒµÕÖñÏr\:æNô*ãªï³‹å–ÊÊÿŒÑ€o,šj+Ó.%\€¬ kÏíV'#Ïû¦é[Åç„Â–Ï mXÝMõ^Ÿ¹èEYü/öÔX—ËÇýÑk·kÓc:ÒÛ»µã׀ɯ‹ô¾)"¸ÈiY÷Údö¨[&•ò´œ„ ³œêþ_Ò3gmÞ,}å9¢Øì)]|­µ4úklKÎÁU©/È­Ìà¾ÈMûĶŸ­Ü䯀t+ÖËÃ/¨±Ê^g(:>]k«q×%úÄ*{»6 eížw. ”Ê™Lþ+dÙ¸8F+û[éÞYKUXai¥îè6ól7U¾ßÏÅÓû”Ct‘è8þ0µsš¨{‘QÛ{ ÝÈâ#‡V/Êíy\±Ê–V€ìwè/÷0ÚÆnÍ €ûy[}Ý&Ùɉ˜:rµ¥n¼.­´¨k¯h@mQ¤Ka D&Lcù#¡Ñžk+Ôvýâ~( ;8/²Î[±k^ó]–ŽiGñ£Ò`†¡3"^ì»å„_º4²úÚ2gŸÝzYT=À€ò¥»^.×af.Y¨¢aˆÛX“YÛÄx«TbåÜïUÞÅH×@ñÈrï«´íFWûTg¥7Ks¶Î¡Ù:&/gÍeO©G¨HrÇS¨“1Èêãl+¾úâ&¶ÛMÕ¯:ëA¢´ uJ´ª |?°+ÀÚEàí‘E7÷ù•Ö|Xt % åÊÞšÛPÓ×4½äA®Eâ"xÛ ‡™dH†AZ|ƒÃj¸æZØ‘ÇSœÉéÕAfÄéªÀft(káG†Ö–_RYžú¤ô„†ÊÜÑÂxöÙë¿!C? •<å˜å !Ö…V°$ÕZÇe.aA¾Ä(lí³çÀ2”²bøqò¡ey€Q-J$ˆ¬µãfA;CÝtÁr'ª~Ì“aî{¶[ŽœEïëóÂOÜdŒŽ5HËÞ\áQö…`ž%èlE¯P—EUtµïs‚øv?¦%,øOD¤eŠü={°ŒåÀ$2{¨¨ñÅá°k~ýÀÏÓfj‡lcµØçè°w¨‹«e{É|Ž@¶Pö“¹gú ÖKãã¶ÊjsÚÈæß;ªâD5de?¶V¸ôV e•ìåFïøË>1Q«=ÒB±Ûj(ù‘ÆÖÑÓM%?{ƒM;£Öáj%=sÜ‚‘bø€ûNHþ¥E¹7hœFvö瞪ÔÓŠ¼€½±Ztr{­‰ ugß#¸vÈßrü€€SµÜG*¾¨~`Iæµ–[!c¥LÌ‘—yS.Eu]çó+ÑšÙׇ›xÝüØeN·Íî»Sú¾—*Ðîz¿Îu—¦#OiP®µHz­$ÿx½Pv”ǵ¼Sœ¢éÎÔ{îV7$¾Ás''Ó1•V}å$ ‘ŽÙ—ë÷ÐÌĆN1®YßÃÃ1|N¬ AGÉuìv¶åÏ·¤‘x‘÷vÖ òÙëã1¤MUÚÙ•ƒÏ/ˆJK°EÝÃ¥Ú•û¬uoàXá㼌ƒ.{ …|7Ö½Ú´ªéºoià¶ä ]À­2ÅÂ1p ƒ+ªËRú»Mb…=‡í¢Ûœke- e²ÊJ!Kv­¶WJðÜj÷?Ì×–Ò¥"Ñè$‘ H.[&DZܲîÌR6€†Öݵ7D4µ 5D 8.-FÎU­±5ÃJÆÿy¿¿H¨û©|¥@H—UpÛjÈ<þùæÛ|šTtGøK÷y[D€¾;tyù’‡ ð¹Ñı)mXy¯s$z@( Q»·ð:Y ÆøJ€²òǘ|¤ö ´¿uG]QÔÉ?/ÝÜuÐÇv =^ŸO«÷… ˜‡6h¿ex?ƒ9Ïz²@ô?xSÕÇ×C ¶ú±cáÛàõDç\¤'¸nßârðØ&kzWƒ™b3^^G^­(õ§‰ÛÐ3l“ÊZ³â{¡v^sÁ¯,µhzÕMú2!'Ø}IÁ>UÓ0V}KÍeh”Õ·ñÏA0ϾžÐ~Û‹(©­ß:ˆTÄ »5jö‘ºc!þôvÛ¡o3µ-nET´Ûã8ì’¹gÎ××6c^.¯œM6Rï|h,Ž=½_Îí××'ªÑ·¶+›©NP¢íµ´§úV©W›h]-(1 ZËyÍeèYÃÐhrEýmI‚æÿ•V²@‹“"ÞŠÝæPz”ÊÊ ©f½ë-kvϽ®0"²bèZ¹O€Ö¾ Šß¡2êƒL‹ýî˜Äᵪ¤J-bÇ1$5Æ™,ª³¨`¸ÊÌ„fÒ[`kVø’¥«¶ŠT‡Û×¥’Xt À]ÓRcš9ØumÀûد\ôÀ‹F«¶iHJN˜­Õvºy¬Ë6-ø–‹Úµö¨Aµ³¨—$c<§@Ïaàˆá'ÍêF¤\Š;¿Tƒëq[…GÛG¢Ml¡–•õ¬ê–c £ßŽ»a‚lÄÍ©+Ž'AÅz:9hMǧeüÑJÈuø],&‹¶í©·íF؆4‡›EŸ«ÕªWá]DUúžÚ%vö@¦nü{Þcø´=eÌdµ~5µ¥=¡>—Öš™˜eèá—yd ¹EÀèòq¹ 8Dàn5’ö1»ð}Àt°øVÑkq>ËŠá¹°Û[X¾ñZ(#`±¶L¡ –°Ò$¾^>ªì’´edï9GÀ2éòæò'N £Ì–ð¨¥züÛ/ù\¦ŒHGIÃYGéÛþKmŸðv<Gz “ çtz¢ËhÖ®†˜Li©voUCßYñÐGifÞ¦õu‡ødI¾I›r {ñ›€‹ûz,Ûë÷ËeÀ–ýñªíË­»±lH¹Œ»äå½(—NšÕBŠ´`¡í¡>,jL÷ß?Dñ bOØn¨œ1«o-bŽ`˜„pάeц¨h´0÷÷AèEÀÛNŽ4#d%æ …R>X{;S¬Í>P›ˆDOk³ËµQý²Ò»ê¿×Û#½A|ßA9t•£}´ÜEýD³p‹íþÀY\uþ%íd…x%ú7›7:.»WTªS‘1óÚŽ×á_J?0w%Rn…€iEmå%±Žµ“jê­èd’Э5œ¨òv‘åýåÖHÔ?‹±K°äq ïç"·*&‹‹4ß +qLËíb>PbååZ¢®â²g`‰=»Œ©ÝôÖµoQðÀha£W¼G¡è®>K{UK„ŸôuÓr¿QB{óöˆo»ãÇÔÏGç6š·%ص|@\æÑ7*Vq_.%Š~út°v[ðí@mÞwÙõ£[ìÞ!°é"®u1í£BêèÞâ`—”® –Sûfq1ÉîÂ2çìU„Æêš˜+Gô½;tiRÏpÚÿ€õâ!2ëœæê¾}^u £”3%?ÐІÜbi^%eif<þÄW–ÝÐ((v§µ±é¯Å`9©öQJUx™§VÇWöt‰5 °Ý·0ƒ THã3#žÂÇ4u‡ÖðØÙ'jí†uö’aã×ãÓNMUÒM¡Qúxäþùxüúu÷žyÙNétÕ-¿~ý-ŠÇ±Ý‚G=-²dozï’Y'IsPê`·ýùùõ:¨ å)¡}µiÿ/‰íªB¦>’‘h^YôSæôò‹‡Axâ‚{--)Ù¡`çÇgS–äU¼‹ºâøˆ¡·–"êY˜î9Ø…©†o‡‘ª?¥ÙtÔ×VŒð¾Ñv¯îŠ0$³Ú‘f»s…Fk2ðt±_ŠåeÍûÔ¢¬º²G±Ø ,MŽö7±°kÞZ‚§Í.ªS,J@ÁM•ÙSþ.I–æVJ%Özw‰7¥öû2µ Ùºïè3¢Km'ÿxJH}»í=M;Ð\¢ª«EÒÄž,b&³ä$€‚NÏŒ ©MÝ«#}Û¯žž7 ÄàI¢lÚøàõwx„-ü´ßà¶ ê@›¶æ žT™¶ÿX`ÝZ¸M´CV£k’KXšFÉ“¨9=À·Å*Nu«A†”Rªæ°ã¬ý:³kØÐŽ¢"ÂÜ ah›T#MŒ–@BE…»tÖVÚöÑÕz Eì w¨ .¬5n-imù+-ú¢¨ö”zŒ ôØrÙníòö°gêh"ûûa§æ¼4”UGåK5§v’€R´öŸXÄZÊi/i;‹1†Zk ܪb‹ ³o>vQ H>^÷evõ»ôéü\O©µô¸Â…pš–Ù“ëT´K2V…ÒIäî+ «±,o”Õ0¶²?ÙÂÄ f¢µ7\ó¯!»¿v—’ŸÿT e©dþž>Î gŽ1²Ì5`×î9G(°×˜™W»7™ 5mòƺ8´÷š©„¥Š3²F X¤í?œÄÓ ùÓK3ÔLŠ®’LAr²EÉгP°~Ö^i1Ûz ȲºA+º±vºhuè~+©+ŒÖ@ Jww%24ÃÄs©jCYNÖ6÷vS¤á‚þÒ:ÆM±²úp,í‰å—· ¡­¬FK/¹å¾ÌºÊZc h’BF´J º'öðvßìt0 Îíš[" Ú\?¬c²FñUÞVKÿøƒ*pRRPx!m×myI•ìö8îÈQcŽÏl±êñyŸ*‰9P5t]Hx;¹$jëÖd¶ +r-F¥W¤‰É¾J_Ë<>_X)“líšã6=,MôV£Y¹ý°ýl8¬j+ÆÓž™Œ½¸˜då¦;±ñ›3úV·ÒÇ%XBv½+8w®å4á"]·z”8¬Iú: ”ˆ¼˜²¾ÎŽKß¼½‹]@÷Íú`¦XL SÝWCÁ/á/^¶Øñ¬HÂI“ë¶¹ëÉí~=èzÛ'a šÔµ-WsÍGÊËjeç ¿>??7rGزΦ°à¼î)lõ©6Ÿæ ¤{ͺwkÝŸÇú@¦×®ß*W¼i΄=dÇ^K¼ ªlpÓ›raÊXè,*Ù»û8Ö"ýØ;eLŽó-jä׿’nÈn˜Úš….+©Yc Ó&PBÃÈÏãcK£^4—d¨¶«“wÆ5âòaô¬¯û“¸xhá‡ÆŽEdYéY3ÐŒÀÖâF¸³´<< ¦äV³µ¯Ç†:µ>Ýî;ÂtðL­CG f $ÀD'¾Òç´ R@sy{Ž$ƒ©C¼ RZÝN£5^ÇØ”ÄÖIW–f, RÐ`ÒdQtE~®­'Ë…ý²O2êb|m-jVɈ3•ýïG11d¹;ÁÌÒú¸bÝle$Œ} ðºÔ™žîv}AJm\zfÕNdrÏ{2Ì×Sº1–ܧ¼ëÜL‚w 2³å÷g±•-ñ~ýÂ×Ü÷p\¬é\%àfÂÖåªìÁqŬ[ç æÊ~Â, ›~h,—Vóh-YÕZÁ[ge„K:NIÑÎ'`Ù>¿˜Nô²Í¶n‰ßNZAvMvˆn¢Ü«˜gR‡Å¦£U“ôãíçGŠÙZ~¹¿¬Scé²±/T×<«Š(®¬WúçG¿õ‚Øw¾Á‚´°B?ГJ‹ UŠBOé*»ä ‘(çšÃŒº…hz¢ÑE{apÃ*%7÷æ ×¼·"ÝÂ}êׯ_–”WëÂjí,ÊŒ æÍ½Ô éÙù @°»GÃóõÂêüùzðg7¤ƒäˆ†VA%œÚ×øÂ•FN²p`Myð·h¨ªrŠ‚¦HöoŸvL¨´­?MÅg‡J.ª¬a{ÿXd”:ùu¤^l' .·‚o ¼ò…Rå^£öuHgŒÍ‹R®Wª/Ñ‘F¹€m¡v;»ñi Õ¦¯ÕFbµ½ä"z¹òë-‡RÕ8,örš›”udgÕ¥±úÒŠìU‰žáˆ³‹L2EìÈœ€ÊÍ„·}㤮Aò Q¹ÜÞW=‹ÆÔÒa‡”¹%o:ÿµ«Ç Çœº7˜[xIeKœZ­[7sD÷çµÏqR´®ÀÒ3Ò$ÈY$²¦û2l7ð½ò5Ø÷ÇÇÚ¢kÝ¥aª*Iªyù΢ªþ0Ó‘iY]þñ”=«åw»äªðÐ üÞ¬«2?N¯¥¥šëúï¿?oh‰i1 "À¾¬´GŸ±üˆØ,—ƒïOJö‚i–¤Ó Ÿ]h­VRX©,Ò¸E†ôŸ%¼@ë÷,æ9 ÄôÍnùŒ7`»>0ïZõæ”k“ Ñ.¡ÇÐÿ¬výÎêÈvØÝ×úiý˜,O.ïQ3o뮽ûìR°Yõ ²º”q_çõ¿åóãø²«¢¢GFýä¦ïXùUi\Y$nµO§ø´S[ãYa=îÔûz<iZÃ*Ó ³vßjy94@¥* uag©Ü®¬¼fìßPKð8“RC ,•ñð ˜T@¼×´ªÛý%‡$@OÂ8J¢Œqí´^¯c:Ô©­k÷Œ“à…Eî›»„¨ð¿kë±@TZ3ŸÉá½Î^™}Þ"ʲ l4† â[¥YÛDÜàDa2ïa§Ø×H©jyÑènq–Oè{W™1ú-_¿aOS(ÙøMÝz@v™XÒ|Jc>irµ{my2+â³wf]?›:³Ú¢íQpr+kPÀ_epf6%Mq© ¿C•É,Ó˜Ë0 }?Qƒa$i©ª¦¶/b³Öœ½´Ÿõ˜DLæfšAœô®ŠaÝ[¸)­ g YD©îi³íýx¿õa›DÎݬ`²†”uþne#b£YtÍ,ÔVö¾Š†Tw—;ôíåHÿU›uî9B. ß*¸“[Ù ,I—GPš¹Ý¹î‡Û&¹Ã2»Ç¥ßœ¸tȵXyjòÏp!Gûè#–u-AÎ¥%‚p›š:ÇÈ€3imÁÝie:£ñRº®gY´ ¼Ç¢…q<‹õ–cØKů÷~½I€Coe@ï&’ãÑ8wª¨iNV‚!ôí“ïB&”Ö@»HvéÏL?ÜñœâGQðd>­_¦0v•(THêát 9#3süi’ †\"ÁÀ,7x+Pbª:IÚ6µb-}·¯9{ïëÈâ($Q·>cº¦IÛŸ·X_ Ì,3GÔ<ÊÆjւУ唺ž† kÝ6¿\Þ©´¹¥eÞd¥=B>+äÞA5&ýdu^Û×ö-›÷To3æ¾Ø#¿dq^^¯¸8Ú»!|!E?a‚fÍÔnÕÞ04Ý@5uÒÀ°F½³ÞaC-@ùÅr{ºr¦ËðHÈ›Œ¸L] (l'ƒÓï*l×-à™Ù }=vùôxñÔãŸ`ל‘3CŒEôË0ÖÛ:2 “]«þ6/öW¾nv Ü/mÞÚu¾-Zo˜½_»æSûùx׫‚ÀH NÆîÜ:9c@’æ(ô·ÿeœ<º€³Cµ4œ`ë‚fW€8 hÁŸ—jšzÉÐoÁQÊÞǰõ âÒÂI)yõ3êi‡}¡6z,Yw)´ØãCÍCû(D²jàÆ ”QF™†ãÓ.~…A·i;! d÷Mò· br6Éõ0Ÿ#8]s«¯õñõõùùKxÑ ;Îdp»ükÂíüÏpî «o÷¸³û®Ùø~ÿ|90ob°ïË£JK®J kê0ØY0|™Ë/ü)ºÑŽÒb°çµÍVTÄW{Be“ZµZj1X·S¼§Mª…š=s¡B^è»u·/ÎÙ‹[K°ì…°ß­ôÅè¤SȬ¶S *å®6ÀÔÒQsÐìYº»1žÓbÈÝ´ 9®¹ Ϧ¡jÐ~›¾Ê+ò«}Lf eÔâY?×ï¥ÆÜUB)8YÛç2¾´G“0adïh±‰¥Š®™‚r­•\C-‰á¶ß—º¬ß®Uò9#¢Ê>ª¬J 6‰@6ºaE¡Ôå>nVÌ÷ó‚HûÀ^efª`Ÿ„•ÔØ!Ê@7û“EÍ 2ʱ c¨¦—å9/ö&Ñ݉ íÕZ* Gj«2mï–Å4÷…Ú\A–9HƒìÀx†ãIuyûÖ'°çü<ÁÚûd~]oó0?¾^·}bª5´Á¡n¨1ê1\J’ìÇ_­$ºhj s’4×ë~ë 2ÿ†å9<î}ùñ^ÚkaŠ“÷ë¬Mí 4ºÍVºåíÜJj‡S¡™…//¸m]óqt˜– ³ŠØ 59 û).vyž^.qžÇ±]÷Äúž±øçψšlr}SPÉ´96q¤—ùú³¶ºåâ2Ð÷ ¾Üfà”´²(~SKµIÛ—½§îØ?I¬Çô6å0OÍb2|< ‰™•<Ý8X‰G¥iÿo_J?0…¯«;ÏO ¸ˆS¬yáª\Y/_¶eî.ðoë8u-+¯¨àš5í²wÙyïÛMŒtµKšX=êÍBÅ'/±É díú¶Z¬œ,µô«õ¸Lw»²ytMºKféŽ.8i‡,Ž/%ûKtþì±Ñ4nÉ|¤×ÀK:z…õo1ۦYmž0 MV‹ŸjuŠÕqïôÉ´!1ká–cÓ¶ÈtÔÜE› [0·.^ `‚jêT%v²ì¾èS¿¡„OÐ µ$ïtжS··?×<ÿf°-iÅÆŠLð5`í+ڤ®u×[äï{¹8vR‹‹ò~*Öã"í!ÊDûI™ÇI%. ‡ÍÙ|Fèih»i³Ä¦dØ9 ÝâdІš%öeB –¹EˆØÒÄd-¢!Žû$ìÚ, þwa³ú?>â±(Iò”Ãv)&„xGG†b¥±õÓm«§iµ¦ž<¸¿¾ì%?fD—z —·Å jÆÙÄ-2¿ÿó÷}l]³bµã`1Ðj¦·Thd\eŠ"ù‘$¦uèKmTÓ˵b&ÕSû²ët²· ;ìÃË_Ò§/’Òþ‘"9Gš«ntK®q ÄÈÛ™Ôý¿ÎZ”ñ³Ír}’AH›è›[)w‰ì}I*—:ëx®ÿ¸ä5ÓÈÑ];WiÛ_8nתËc«¾ª·¿¬.j81ýeœ(;Ù¬ZN´ë µ¨Ã%›™M”y»oûãõðÕ¹œ„…%/1Ç¢ ´ÔcϺ­FK<’óî€èwTñðuOŽà³ä6}tf?ÒÞ…¥¼+PAÆ5o 9МsóÍyäö¿aâªàoËé‘a /̘jÒiªÊ°ÝìXòSIË-d)±÷ðr¢´“^w^ש´Ùº»¡û&úó´|;ÝB¹í3Üq%ÐŒ~nf×<ð7ííÚSv\)šŠiÖ¢Úe;Eh3§mìêyÙ¦3‹“ïÑq '’@<â£Éθ(ŵ;×¥9»h¦DxùHlÒw¿¾éí0å®ä\³œKK¶R éÇB¨A‹‘ÜÀuW·½èºK†’’ê“Ĩ¢Åñ>ɳ2˜½}™­e¦qŒkŸÞUì6ƒòIÐ$k~¾Ýoë$4f×ZÝnhHˆÎƒ†ÊØØ%{Oæ' Z£euɇ…Cì:̲Ý·¯Ïp÷ óÔ±ØD†pÙîT¬g¨ú\ üÔãùŸ}ÞÄ;÷¥æxÉÕ•%Í`\WxýÑd(˜õS7•ùX_óä’¥m–B„EÞ¼o–.ºÄ inQO€€Òî!kÆ2«Ñ]ìá×…N—ßi$)N3k@Ëòm`yçÂvp~b¼q‰­ÈL¤¼J‘ˆ<Ëû[‰bÔ$‡ÆSçÞ‚ÇT<Íñ{Ùfù5·qøV0  ß9õ7Œ´P¢X @ßê¯<¶ob›ÿr¢”d¢“9­G'.Ú©™ú¢škkè-Q•£^_ƒcz"W $5>0®¢ŽN{Ýqß³¨ž[íUcÊ2ØÝ‰æäT©%"j=ÝZk[ºˆ ³hšîZ07v7½Çɛ՚e_†!°ö¢¶rnµͺRhß2ýÈðãX ›­+¹Laó)\²ýÒÚÜ¢véO\ ²*Ok ôCŸcŸEO”ôWSZ±¯bÔZã ‹S–Á2亇¢mõýyßÉ@¼µœ^3|‰E*dñݧ—¬šŒ9B AÔ; “ç«Ó •¯*K¸Ó0©é²ÆH ÍF—™–?LUsi…Ô kÉq«òækcws)ÝÆ#dHh+lë:uNEm$º™è£°Þ E h²MÕ¥LþÀ²*ýw8ÞYƒÛÓ†Yf/®oÅBÜ)hZÚ—A «pùe†i²²µ2´EÉçv›îŒ…,FðwÇÔnvÔq½r!QÓ $›àj¹ 00®ÁýbáN lû a%+a„5àídq¬Škqýg½·í: VË$ؾ+Ù£ò=/Å ÀuRâ™(‚–±Õ@~<ÖïN-“Aø2ºùùü­3I§|;raßK— ä)š¡€š?Þ®q”ÉÃ4AÉîûÇ_f`ŸBR’ë{W4Çzî/ïUcý|³© ÷û[ù´» HÒs‚Ê"Þ‰}Ú$*ÓraÜìDoyP Ãç[ؤˆ¡X—KWÍ]R/Ö7²SØÈÍÀmÆVqèsI”øy_P/Á18·|TµµúÀN^/ƒueS§ÈlrÚºoþi›úE%‡ Ä­÷.ÝÞ>3’ßУgÈWµˆ“çÕâ*îíG Ž–EŒGkÙcDÙKEˆ¿[õ]ÖŒ3íès €ÐÝ"ºÒfÊÀ¥Í2¡‰£ ÐÐ7¥ÔPÖÉ…h¬˜\­w  WÆ¢ll¦¹¼FÒê¬ëLf\É%‘;ŽÀ¯v¶pdác•EãÞ8nòâ6°HÒÓ™âiÿP0'HO¿è-Ó\Ø‹Ó9 °Ê»ö]˸ÖP•è±ù€ØO‹Øs¡÷ŒmKY[GJòb%ßÐì­õ,°Íì³ÔV\- Vví¦Í˜^ï[_jóaw®í×ÇcíÛݹsj«+ðα¶LÆWí Ý0»oPï7†UvO‡é± Øö7íPõ㙵΅…Û†8™Q…®n—VE9(ïÞ½8F?bËÅKÛN5Xg Uo¥]Íi™°Jï,ûVÅåíýjɲ%¡Ë톙L…ÍMc)4BçjñÉ…z“±î·7ZïYu"ð$É8ÏhßëšköÿüëŠÛ­õLI ÁÒzôñ?…E«&ã'ƒ¤T/˜7×}À\‘çfr[3¿ÿîø¹}óÅÉV€?÷©aŠS!=PöM'ÆçQ.ƒì¨6·”v™fíÑÊcHÄ5oãfvu ¹jÎÞ"¢Õ¹;`íb˜Þ¾ž #,ŽæyÍOMÆçó6ÊgÐEPz÷Ú*ϼ?2;íì|”°>¢L/…ì¶ßCš´Ô$ÑÈÜqÖ˜¬¡<±þ¹µ"ºv°\E©Ý€*o-óä/¶ ¼=ÐN¸Œ=OE5+³9¶8yŽ×Pƒ”•\oÛÒˆJ2ÇÇ×PõùI¥f=À¥s‡ìɯ9"Lö­*¬ÉCˆÄ¯yÊÀÏ3øfרìÓ¸îá RFÛw9QGª°ßv®PÇ´Âé5•;µr+h”i©dÙ‚é8Éñ’g\s—#س#—‡HÂ0#ÎëÅ~íj +ÃD"K ÿBDRïÒbŒYŠADZ¶[y_Ž¿–c¾þõï'Îxè¬$q«ÁoÌ|¬µ¼œ±äqeNk-ë®—^€]Ó¯ç>¯·cÆï±­»µèŸ¯cd¼µHiK¦`ªûGCðæ.©Z/ûEîì׌\]}=òãRY]j§¶ŒÐ[hŠË²Ã"|ƒb#-ÞÞ¸Ü×¾¾Be¨¤Ïi-—ïË©%¶ÊÙеkhÂCknMZ׃¼vÔ‰«E“M¸°ŸRÐC#’ý§"{û}™0™šNëç4I±moa÷§ìˆTþ¯gwfpßE{ Ä,ÂŒ5½U#I>4W;3If§ññ|Y“üxñ¸çcTÃÙ*äŒn‡É·:m¬†oßZ{R¡ú6¬}3d×VR‹ dŸÇ¼ÞzµôýY´/ç0u_;/êZ;µo#‹Å¯û<C­ßŠûÞuDY¡!åšû¢O¬jH}Û Ð{(*ûŸ.ŠnÛðú`´Ë  Êìš÷¬Qëk[|‚£wl䑆 ŠøÙ_Ñ Ã\wo‘€”·|ëY”[]Í´Öƒ]âºü—Ú¹×Éÿ7©r Ö^W,ZëU­<ë“ÔšI#8–²M“%A_Hä:ØáVœùè"N\lÔæ¾D‘¦'æ¼Mš8löAž1¼Û~œ#¸“W<.cËO\ /XÕAV$wîìT­DÙF‘Æ*>…5m\VúÎZ–vëB¨/»7ëBÛØ¢¶h¼\–=K»™Œ†Ðd€©×Ù5/ËÔ*óмV™Ëtš" C“¢< …˜ý¸èFÑŸIεz¨”)¸,ÐåŒKÉr´ ;;ñÞýа»Ým'(IR« µ¨T“J%—þkdæön¹ 1Þ¤j“kŽŒQņ xg6·²û Qé¸Ûß¡£ijßë×@Û챯x­NmŠ`,ÛÛíãZD }8êÂYë–Où ˆ‰áŒ\÷õkÒ’×Ä뻯)›‹Êê>Üzš&n*‡ëÙu·´µY²íÛen¥Õ„wz‹ô —–íÓ…Üæa[_VÈéR&5äm–sâSø Ì 5R* ã¸x¸ÇU~5óí{›¬ð< Oˆét å,G©d¢¶o£Äx¬”4A# ­~43DEKäs'q$Íá¶]Oÿ£NSë^‹ú>&öÀÖ®†,{'·Þòñ\-½Ù!u7œÝt¹å­†é¡j+ú Yî&ìQ'"Ü ‰ä¶ôV`Æi ÃÑ¢/k»²³7fÕÃ{ pÕÏó:ñÛ(‚N)¬Gè­•šºFŽ…^´§þ?ÄWý,Õe«É¸1 zLÒ…LI:yÝÐAöÎæ¡vU©`i&»Zî·Êº`?ƒ“Aɤʽ̪6o k°bD(÷ÅyÔáKöÇT8ê ñ¾ƒ<¶P"K x/yŒþ,QEÓd׸lʤµ“…#Ö˜$( dÚ›ÒÀÕŽpeâ±  ×©‘dÕµ•_Û7Óڃɶ./‡u²jdÚ‡¼}´ÿÃi²ô\x5’úNzT³†¼·c«–G‹.Å“µ©ÞðŠD×¶ŽS¤X®mŽŽqÖÔ–qîc˜iõpº‡AÂE4{íÇû}ìׯ;»Ñmºï+½ŠÈ:¶ªŒ-@ë,ÉFŸ[ÁC³Ô14VÓ}¾öyv}ïã5ŽÛëëqÇjsÓl쫵ÿá’¯¯Ç¨ ÷©Q{q¹\­é$eJ@dáø£›í3¶õ”v5ëËQØêé¼Xî–{´4I{z-Ûqªp3°ûYŸWîS9ßÓZ_\IÎ}§ÌãÙÍ Æœ@–Pbp ÷Õ ªv™‹·ÿsÉó˵ªSèÊõvJã·¨ó`ÇŠç°ßÃøÖ{uï-ußqmHO§î‹sÌ‚WÒ&Ú>éCjÑÒ®9¯)¯ùîþÂ.Ê ¨ÎèiÅ5¸(º»¬Bq!9Hq- …¨ÔqÒ|3ƒ 6iaˆO0ä>‚c:úï‡KÜ1ΪžaÆí>¯¿_–NÚa¬;ÜVn]‘_áñ“¾Ø4Îтʨ NU&d‡·wÚi­¦±‚&i%ø5»¼C*åžPÞæµ¥J: )‚µÓÖtû×kx€ÅGܲiØÆYâm'´M{ýv÷,³l-ãTÒ v|.Q=±.å_0˳ ßÏVˆ bØØ~Ú¹ ÄÚ‹muF×V¹2Î’öyÓ§îâ”ÉŸ‘*+¸Þª•õ<,Ñ*-§’-žÕQÛÆ,76â­¸²r¦bÕi%R»Xø/0Q’ûˆa¹èË–£!ZT™ê î:šÌj½< Ù,æ !˜¦qùöW×]³.²ÏEÍ=5T§e•…õÏÌ[o·±_˜}³Õ –îú ñ§©?Óʯ©hÖûãás¶n¬zOú2®†¸ÁX„–£’7(*ˆ ²›ö‡5™³'Šî:»:ñT쌽»:ëç¿~?W÷ç ÷m@¤ýåg̱œÖÚZôºcªZü@ ¤GT¦±9¹Û•°Òý¸µÌ&r+|òjÎcª•ßlXÊý¹®_Ç€€ö~ø .Å n•é6ˆÖnŽÛÞóOÁôæá{4ƵÖ:*ŠkÄ5§zCp9ÏÊìS4ŠŒ …!†€³CçŸCê4sÌN·q9²?rö*E _J€c¢ÏÙ‚K†ý°?ö`v¸¦R[Ÿ×œmL †Ï¥€n²ð€BXoµˆq”–1N¸ê¯×óØ?ÕTp}êQŽ:Áe_^«<rZ|Ÿ u³ ã°Í’(°ÖgâÍzø¬CŠL±$ à4Nma^ü=Dh‚riK6H]¢¶Ÿ±e»ú–,Сåf'@dñƒ,õÉ®ç¸YDÏ0¾oܽ„M‘¿cÑ5ÓŒª”üÅI5‹|@ YzýÈg Åbo¬S>dpæÂ¸„¾qvÅâm¢ê1jéEýÑG+H>yFY0Ѥ½Ê/íVT&§¨.;Ô ò¾G)ÇÂE; áno:h©¹»µacÏ* j¸½;–±}áy¸ €–‹ àF‹=†rÙ…9M>»ÝÎÊLij"LËâ#ÊÅôö‚H€Ö3öí[£ñÂ%…•ÒtšØÝÖõþzÈûÄØxo*éó5”‰•½X¨¨8®[Ý‚µ·/XÃíSÂÏk—Cãb$ß5«Ø]ÜkwDj4@mkÊ©„†®gÂØ•³àkO:`r^¤­ÕqÔ `ßÇvØW áèï÷ Œ8WÌÆ­çêöÚ·ÇÒß¡?ÅÕ×oÕ§©ƒÌX¨ŒÃz³Úxv¯(4Ãúq]šäŠ!y©2®rôlem ¢<€We—}ª¹óÍ 4Ãuù;ØÇ î½§çç¹x+J+Ý™Ák}r÷uÀ˜äÀNoQ%¥Í‚5‚1E¿®– fËóN­Òƒz—‰µ³çy`‡Ã¶¤IcÝÜ87×R³ÍA0ö 3@Kms9Â\]Ž p;|§k Úo÷­·?Õ£àP9ص®ÜæÎvÅZOén‡I»¥O”ÎzfIL™Ê¬±Ä i@p ÔJö¨;]7Û·b‡¶³¶)µ{„ CÉ|Úb6aö"©”¼‡.(¼ûF»Ø$Êâ\’œÌòN-‘ÓóV«^OK“5hÔ3÷…›oý[79j__·¾¿Vì&fåìJÜ‹»ÙŠt¸bE¹Ø÷ÓÕãÄ‚“Va¹½‹JX~ ~µji WÏ€ÁÞ8´kCã]y ^¥´ÍìAØGë§D}ÜtÑÚ³ï|{ißÞ%ã¡,¶¼“\Ú8úéÞEZ”îü»;§Þþ©Ð;.wé <ö[©á°àk•Ü¡‚$ÉXRŠ.=Lwyv®[7ßSοôÄö£›¿-ƒÛ-úüû—]<1˜Y ϸ.[‹€EÂ83gN̉±­õ8?ì­µ9]ŸÅYœ ó0öà!Ð^ß.4§à[ $ÀËÜŠ+Œåʉ‰uèîÎ0à g݃IâèºÁ}¥_áRO§÷±PÇ¥ðëõ㯜Qnw²Ó­QS¿\¢fŸ¥´¸ÌîHR€Ôm>™nj¡­QNÛýtK9•ÝÜ·@™Ôqþâ–7ØÛÚˆgy/‹s¿†ÎÞÖfFà+ؤMCÔ²«]ÙkY ¯-Û¢þCSÛnÆe÷knái5*ªˆÕö ùè7׳~þÚ*ñ/hUéî€%—×àN5]±ôÇhUU…$ë "û}qáEʲsGáÞ5vmèìÅ1ã’ÆS»ÆËB>¾Ò5VkhK׬  u¡ßNÛú5— ECûŽÕ“”5«öaÍe|Éúôz‰hV˜ìb6s!‚Ç­’ûÉòå!¦€"ÔÔÅ'Å“…d†ÅüJûºóRt…y<ÌNZmz»fîà5Œº×÷ÖÏ{_} B…¿£ìÑáË#úbí·ÊæLÈ ÜÈÙ" „ e/ ¢vX?,•_ô;ïè1nV¢²Ð¾“ÁG·ÏUDNs¤ÒUfsÉíùWou€IDATy‡i`Ù»ŠŠ¹ÿ¸ôýU¾ÍȸÚÇÞŽ¢JÎýó¾ m7»ŽÿÞ¢cðØAbv˜Ý|z¤÷2nbòéM»› Gð‚öýf=5Æñü…Ça»ËíšSÄ8EmÃlA¶r•œ¡Qn­Ð²B},1Öµ–ØŠê…̆.›`iÝö 7¨¡‹ß æø­üR/ð…¿¥#ŸŸ ¬ñÖœ•ƒ<¡âww_š¥~;›ÛcÎ+ß‘©Ä&u×¼qt¸qú³©¯Y°_×µIÓ*`½9IÔµÒ¿¹fpæeYù¼ àð‹±ýˆ¦1¹,qÁ±Žòõ¾âÛL÷¯a{~=¬Ôþ¤·Baö•Ìú�d‰‡Ãâ"D³@ÄÍØDQÍh¡dñ§AѦÈv?bØÿ¡k=½Eh/àëëµäIÝ•ðìæ’};ôÕ_o=λ%é98à9vÝìš·®Ž™þöÌê– í—[0þŸ¬žz¿bì ÍLuöÕZ<Í\6käeI’D#=eoÝy'8~+?ƒyÇ·†)AjT ZÓK"^6Ä ö sï?‚êCfy!Ь[®¹U;MÑ®âPò욢[†TÞbM«#Ómχ_ó‡½ðÏû}­za÷VÎ⎻KÚÍZ5ÚäºwÝõÚ[A²jYMÇ}Î8£v#‹¡Øf‰‹7®“Ø‹û~íBƒ×ˆ¹X½gµïHë: ‚¢.R© ‚X="Ç”ûAί—ÜNÿ,r5]x>KWÖzÖIjýÛ÷5¯«®if«Ò;«XÒÁ.Y“fmûöÔ’hkqäãXÃ}i6õíY´ï«j”°¹Íþ–ðî…ìÕï ¨tWÞÙu¤ÞŠtxU¯•ÔWê´Ò«E55öJÆ"Ê‘œÌ]3¿BÂr7ÕýX²`Ô¦Êꔩ¾ï1œÂðÊíù€yŽ"djt«ìzäˆ-Û³Eä"É»$îâTö¬ ÛWPKm”ô½Èì8¡Á3ÁÊdWbÉl–ßçºÝ½°^hÉ C¾ìÃí6ñl-ÝäiéŸL·§g#6·ÏÏûÜËaa»Zd|!ò+±¨ãùu*ÂÚc#4úúØÎ­}·U”Jt m…zœj¤qßì±ôãiЗ¢Ñ¶ÛÔØ; Âµ®ß’y‚V— ²¹=!ë!ê´ž†âúWrÜhÇ`©ëG×ßzìhúöÚŸz¯Ü¯¼%RXþ¼ˆ¡Œ¯jå…&‰ôƜŀ>W{Vçh š›ô!)ýÇ/]»2À•ç”]bY“C:zV„öfæV‰u3É]EðzÄÓh†ÛÞÕ`V"vÄÒÛ»o”JØ·åÚ§×i¥U¿È‹æY9 ÉJ@ÉÞkU5Û ¼]¦s8b- WQ48óÚw5HÈUµËž¢µ{ÙÕª €fCS/½õ0 ²åxµTec­TÊ'´ã[:ù=^¶å¿Gp„ÉÅ/>¦q·`o-EVÆ-–&Bï$RÀ–5-[mÓk¹c Ho)¼±"yg{òüªÔ›¶°•ðÚ[;oMg½‚èihe·[œÇ—(“xaüW“kÞÛcBÈ™~¦ÄHš •.yË¥K¾Ÿek»Ñ2¨^\¸P³jzWNV38 RÐD{¨’´÷8ÜîCÑE;Å,a0uPmV¡ÜZÝ ÷°Õ£ðãóÎdκzûÎOËìœ1ÝDö¥jrÓ*dï*'5©j±8اIÓeÿlx¶?Rûþj;cÖ ‡»#À`&¼]ŠžQ'\<ùÂMK‘{ö~©Û8íÈN¹wBß®:çB ŒÎªZÝjˈÊñÐ2ÃW¶ ÒÑ[TË^IÂolrtEÇCR)½àÜ4¡]e¹Agé²½îÇ Q2"¹8¢Ô~j¹,öí>‡ßh);²¾èqG*mÞ÷ ;[c“kÉãŒ:—ï‡1!jG{zVîOCJOÇnË*¿|”p¶c¿Yoeq·û¨X7×x@óýv{êw÷íyë10´“1âK•uMÍlR‡i£=Ÿf­ï›óLCÌÖjþ P×jÐK­b—¡Le<©ëª¬Es»CÇÌÝeãלëjYÚ^« JJª*N,Ú´ùyÍùçÔVó|›Áаÿ!oÙ—eáõr±$0o5wxȹ¦‰}ûa¡¶½ºníÜ×ZH –Ï:L^,T72u—í¬ÊðÍYìdcOÆÄ˜°L Oà¡@¢Ì¨fveíuʨÐþ¬¤5 Ëaå0[ÛY@íÄlC´ß“"úç?ß"ài) ,#ôÔ¾‹È¥¶7[•ÓÛ¯0ˆ¨‡êšöÖ¨¤5,ãr[èeñHæ°õuvë¸×!XËT5 [PìµC¹¿>…t$#ÝŽ¡¿ßùóL³ o´dwÐäñ%®,(-mìöÅË]¬î÷¯ý:¦Ïû:ZwÿëiǶ„)0J-H(Ι5-Q6¤MþóÒ5ïo¢ø?X–Õq³cA4²gbÉFÞÖ¡ Õ'ÉãTe×——k³!¢I¾¿î]4€k{RUðß±c׉ zJ;R0wÝ‚½ŠÒ••?ã”Í.·8†û–B´>›ÁBÑRš%y©ç£é0ˆY€!ŽH"l»”Òä!G@ž–q²NM¯9P–NAB¶Í–¿¶»}£ÝhÕm<ðí3ìä²¶¹fC×3Z"–¸Ë¼Gº¿Ù²|;§)0"í† ]Ñdï?sýçÈÖÈbÇNeßæ—ŸËc=Ö“Þ^ [o¯½×Ô¼Íd3Y*PˆÌìÖµ—z¸dº…MŽ ýp±jz;ìei\O†/ÈeÆèÖ!B¼ÊºÖ"([YúóÓ¾ñ|O–%nÇXÆ?“JM@z©ª¾Ž˜ìçÛÚt‹´ÉïY¬€Åf‘0Ь±íàY8ž•…ÈróÒ½àµB¯z‚ffÖ 9#/"‰Ÿ-,bŸ‡ñ$*‡¤.ÚèR•×ë”UiÒ—ï…U튧—lh.*¦¬q hq†:í@c}R6K`Ø—<ßoÙ?>ð>âšw,¸W×¥3i(ЦDEt­¦¡L¿E‘]=èÓr´ætÚçc¶eðžzÄ,=‡Ïi“eÖc ¶9Ïûóë¹®¢È±ô¸?_ºA-æ|œ±ÎK‹~­ÕDu§ýPÎ`ŃCcè勸/ÃËt»*ƒÅ™Ï_¯M^ ö™íÐNú×±YÍß®MdVÑöâD²µ¬Èã2j6‹ÌËçÖ««f;0#¨dU•ÝÙ2º`ßÂ.ÉÚRbLqÚ *çK‰ Ô{N&­dù1¹UóùO¼V,”Ûo‹èwµób·¼âš'…›©]ª4ÿHìB6ö ”³­Pn&vQH3q‹±\-ýõV@lÔŽöyŸBñ ^j\w·&Á´ µ)Eýõïß»ÿùþ\Q.ÚvûT\…¢Î]Ë Û‹ؗ5ðªºé¸êÀ´Ú..A äG'‘Ã:ÂXÓ"t”îOöÅ7LÆé,ñÉTŠÌ²=¯¹%t»±öÝ”ãڎǰrÍ9“A®Óh©«Ã-oTqÃÁ’SC[;AhÛ}BÀÒ“¼JÀ¹ÖK{o./Ijz哇ª˜ò=SaÝö4§.vÍ0Û‚”#‰%h¶¤Íq}c‘YÎJÐXl ²´Xþ3…>£}¿L^´·+¬êo6\¯ö­šì[÷slõ°×—ë…Eœ•^W¡åxjc‹á±uû`{ˤLØ@T¹ö{C?¬°§5¹3°.Æ7 ¦‰Õ%Á „Ïï‹o’ÊqŸÆå4Î>œzÌþ<¶!ð?VËcC÷ÀB R¹€µ’˶ˮ¹š…¿–ŠE ¦û\ ç³ºeUdÕ‰+»¢–QZÒ›°q†ig5MEÇ]L–†‘¥ˆ•˜®ÎÁÊ,»„@„˜ Wr‹Žâl@ð¤J‡*oƒÈêÙŽ1_—•ηOž3Â6¹Ó·e =¶X,v„—\SµE|R‰JÌÌSµ Ê$þ3ÜœɾµEWdMI´9æ¬d-kÏ­.9br.j®zÞNóÄé_…3][Ö™÷q¿/ÅûÌ{—Ná¤D:°/£ù°¢%_ëxß-›.ƒuƒÇ{–Q-gÞ‚P Øî÷ûÂDyÁÓ¦—û×h庽š½Ú!WÎ!µBj(ÃB)ÄZÊbXûiïýšóŸúýnbLÃ5 œqr÷½u ¾­¹=ËœöºI0Ñ5/ê0©—«òÿá‡æföõDâZéw-êkR[Á?Yh-‰w؉"t “Z¢u•p8­!p^Š; µµ„ëÌŠøÈüÎk¾:Ów9GG'^IróöÆüšƒõ°V=çCt±öÍ*¬ø.Ò†:¨¶ô •¡’8;s§sƒÆ¼´›Æ|ÚFœ¯^KÌ?ߊëÙ"]UX^³ˆè|hB!”‹GQ‡™Qû³i㌽Z¦¥—¦oáó-"‹’ƒÿÉ©s°?À-£ ±bn¥ÞåîzÁÛ±ù,ÖjN¡´E(Êa'}2ÔM´ôÎ"ís[ët­5¦Î¹¯‚Êßà™Í·'yÝŽÈP44pwh0¹.à‡ã8Z޼À¬>Ëñ*0-­]VwýŒ°9æðÖŒó™¡Þ2” š±NÙŠ¶˜ lÿÍ›œYÚ8¿|êÂpÛçÍ5J‡Ó¨av/·…Õ×}Bg'±R!Ž¡áÂ?Ë{…ëõg:Ëp½µÇÑö~ª‰É8ÎÒKCe´”bqЪRFq˜_eŽºaÆ$õj-UèÜ—@ívÏ0”[™Í+ÁŸ&£Zkø¦Àã<å½ P3°†´æ/±ÌµôU;žQ«b˜-#£g SüpI¾Û]ãU»½µVÖ"¶û¼Xn"²ib9&žÀá‡D‰ÂX%l§ŠfW‹.ñfW‘ŠLr9ë4hÖm+÷`¾}¼8Ÿ=Opi³¦I˜è öî“Då´œ;“¿½*¹°}c¶E÷`y œ[ƒÕŒ|"‹¨"±Ô·ó‡üòK‰:cÉÂó¿RµN ÷é‹ËÜs5¾³¹L$þ„™N3¥å¶ÎAãß:*<íNÛ¿,wöžjÐð”º(°9bùÝjMí\º’á[ß•«ýFÑÝ_õ¸ÿ¸”׿ ¦wPL-HÇàk`  eǜʊ[.§D»`×®¹D’Oslv¹¨ÎÝð])[X(I4*EViwëívÛ†U‰¿‰Í{ºñüxÈ….ÛëÏ¥|ho•õ`kUG$ÎQ§“]"æÁãê ’6—0ìÉÚ¨›Ä":Ê´½ð>ÖÕX>îQÄö%•ªæ¨—ÇÞ5·¹ë!¡D‰Àˆ[ˆÅ¨ãj¥FØ´º™ýö5l¹†ªvÆ€Ã`ýöAëÉ?w,:åÂ&ïLÊê[ŸµQdmUåh][hÃVKºÝéGôž/ÌíðFï…]óÊ’Sþ‘!{“_u,ím×Ëh‡|˜¥ÎÁ æ’(âƒ(rc‚eþ–™°ÿ`ÍÑfEöç×cªUmX,µYÊyS;¶x• ^¶RÙdÙ<©~çPɳp²œœ´!oÇóKzë¯ÏÏ›¸ÅvcÑÂÍÓvý£Ó~ hú†‚ªÿñLˆ¾VðGGÜã¼æ´¢€àý–·íyÍ+¿ðý, mxl+`Zãƒð…]Ù=O®å(¦Ÿÿ°àµ eô&?P;-»¬0ëVDÇz„ǰµ4Þ.UÅ`„âø•ö§†`¢ä¦åR¤‘Rÿ0¢ïÙ÷SÐ4Y·óšOÚ”àóíµý©`”î¤= ØÍ,¶òÁjõ¨³ÂÖž&ÉYÑp=`’Ž<“ö ]1³ËæxíY¿–Ó«ùèë· xJk±ÿ²â†®*|ŠŸº³$£}V%žƒ³ùY)•h<#‚vMʶŸ,³vãÚ›¨A{C98ÙÏ]°Ôg/ש°Jš? Žô¼Iì;¤ŸEcœ XÙ?Ã5Çé³<‰Ð#SgÏ ïU¾–;BúzËFgÕ}Ii…-º·]U¸cXeM¿^.ˆÚ!±Cöc?ЧiWœÏ{™‚¸’ª9à@{žt3à²f̯eT­÷ mçŒH‘‰¦ë›Ïã‰%W‡5|OY¦o_­Åri0&»­ÿ|GR®hëÆÏš÷Á·Ä—|ªŠ·ÄZ²8j꤭qø#c6›ÒeÒ< u”r4Q··œœV‰ëXˆ¹ÁîCÑ%ˆìÜt÷ ©®©-7dä|a7Pv|êÊêEø£^òUè@6#¦µªHæŠV@­gØïÈ»¿¤OcQzEIÙÉNLžXR²(Ç:}óHÎC’¨¸Wv¥gÑîkö²ÒZÜ:‰ƒ‘ûÈÆÏ‹öBX•² ·¼=‹ö2è§»¼€ÛŸÍNLªÿ§Îj²DJ2*â+ µá¿dÔí4ÄMhϪÂ=•ކÁgÛKÍ‹•xøå°Ë€%ÿŸ¨×ÈŒhNý´:Art{i¥»¯_þëš{“Ü„œÙÈ;-&Ÿª_«øÆ®¼“›K6äbGÞÝzhßE ÃÎÃÑ€Å>ú–­¯zXþñ*úgY[.Wç×Ô[ZØŸ2`×…œ ¥H$kç@¤Ëí¼_2ªL;s,Õ©6¦àýÉ÷€ìï!'¼Í©T«7#V¹¯#c6ðç'×Aš:jc„ÄÜžOÌ?¬á>6;¹ÍOÑqOwš8-ñA8¶ÏÛÆiŸöq;<ƒr-@›’ˆZ1TdPwìc Ê–ý'½4;«¿´°A‡î°þ”°}ËqbÍý€Y’}®þŠM’Zw1*úñ¾[ƒdÀ J€}ö¤jü,ÖѤŠÍ*vÈIK06˜Ù¸,ã¿,›NÉ%~kL_ZæPÞ£+¿ìë4¹¤IW–qUà_o1âã"ûäT’4Eç9ù(Ó¿>dòÕZ™W5›Ë…ÄûL‹HS¾Êå£é&Ú›û:ow¡Ä*0ö¦ëŽŽÏªd¬;†Ö …’ Ày×Ξ;€Ÿ¡]Xà‹0͈ƜƊDv%S“7yÜ óíXî¯Y=;»ÊÛ>áÔÖ~ëÝb&æûØÉÑjîòÒ:îÃ-ïÎÜ)í¬ëÆcÅ&©ébíš³)Ñ5÷Æ i TíŸÚ“[nMpä×¼Œ\÷¶íoõ4}¿„¾ë6o¬G½¾!ÒGiùW0è2¬ÁöVV@vÞOȰUá £æÓžá»hŸ]°Ý}X×­“e˺ғ§1ð6®öFkŽ­ ®.Ö)çå%ƒRÃ`½¨\_Ú®£ÕÙEšVzY"*goÍZŽc³Ûúó§ÕÖrÕ¹uy‹K)-Iû8º¸¨žÁ>…›;¥óÝf.­úíQ“««‹]B{TµÃ·ìÊ‹5c¿w×û¾`ÄÓ_ò-ÈïËg~óq—ÎËY´ïö·Žç}=^8]ö0 v×gè‡Ç…«ºÝu¦W Ôr¶ ê^…µ÷€ä4c»"C®fÊ žn`ßvÙG×ö«æ¹j> …PJ㺈i‚ã¯V·k‡´Àa£¨cª›õ~saªi\ƒ…1.èX¾~«µH›êöM¡Ö Ÿ°@ˆ¶1”×rÊ?8biÙ71D„ŠŽ<¦Ð¤i”¾_ì3á·–ÈZxqFqÊCæ9•¥¼E­*¡;UÍ„¤¦#â98¾M7ígFQ« »³|iöÛóöü|q4­¨8–F#ÜóÅÎbÅа‚¬íšãŠÞPÇ–á©–÷¥-û*NÓ‚Vs;^õÁŒ =푨$¤fò¨¶ÏûüøÏ…êˆ2†rÖÕ_s©¼Qx[yå×|Ï…Z?‘ЛÙåØOƒˆÐ óÊJöTõc.r+C­ác ’Ù™xú–+²(byîÓ(¶Û*³lP¨-.2Û¨Úñ^ÏKÏhC>¬PS[ëÍ+K+ð˜íí S‘Çvú™»À0¥îÄ€ðÛ<7ÙiÑp^óSfá1Ÿá&ÐÓUû“ñ½´Ø8Y·»õÞgï9>uØ$"7ÓFÞ¤·i$0jаw,YèÃ9¯¿måõ’6ÑGR[ اlXÙ*OË NK^·äv?¶9ÈPŒÐ-vKƳ+£¬gÿÓJ<+¹ØÝèËK¤½6²¥“]‚Q¾â†ÏÙÄqŸDL½nÚ{ö×ÐÆÌîµ›ä”×C m²œÌ[È¢Uù ,Š ÐÏBAÉn#Ã'‚ž5õq6.–Šªzî¬{’z^•5íµK/±êjIäÝåÒý`rf­hÊRØ>×5Ó+iƾñ¾|û¨-~²U\ﮆû¿$Œh)\ }†ãt{n„oÎ\u&²7>!”Ð}·"Y 5Ùªî“õßùGÓ%éÐG’2ú™X*jºôš¤ÑGT!Úæ(§ô-ê™þÂnc]hgÚdI)О{3̉²>»]‡ûv¯›#îíñžB¹_O@„'Se™-BN°ÂœÈÒvv ÐF*§±™ûf±àd¢ãÎëâ#'_Z ܬ£Š²U9ë¾/S7¸©ÜŸ÷>Éú!££N[Ôu1[ý¼oš^Ü_ϽƒÙÜYзÉjõgI£¶_ÖɃŸ¡¶vL*ñLÖ‘dØ£Z?tS ¸§öÒ½¥¸XnýRopåQsSùVY&fûŠ«. îðœkG%÷bohmÑ…²?"é7ëW¦¹©g(e,9A²ÙÀ §ƒ.ŽÓ‹=x«!£Ú2È¥&Lßüâ{©Ž±ˆ£oÁòìUgibÛ¼öñØ·ÿö8¬gqþZ §)‡Èš74!»ìãR@˜ëâ÷*¿X1›[N²Rs¶'ÙÖ‘óóªî¶äQ]Œgª*«(ª-(Ü!"Ù³d,j{ŒSgy2‰ÁøUÙGm±¤Î³xYD1< y\ï¹&vJ.ÅX—ó}vØäàäÖ§í¿~¿™5ûñŽvÛŸ7±WÖáxáßùXöÇççóvüþzª ß|#¹’ 9éVWŒ­Ôs‰xršã©íç8BZÃ4a;mUø¼ÆÉ`q¯G¡ÃÙ²ÓÜ%ïmþa¢‹†ËO,Màzn[ÿC[U‘ãVH¨hÙi!²QÚSÊÛ––õøöŒK¶/RÙ·ƒåƒÀ ™ÂÐÖÕœ$†_Ò¸=&6:c`…wvaz¤.&šäã}T˺&гÊN¯ÅÛš3^ûÇ[„Z´KúÅ5ë$g/¯îJÑÍš'zyprP°å¥ú°¸kã°¸‰É ÷tìVЧûýd¤vòJ"ô÷B¬72v˜ŠAÁÖ³|4N=â L\-á'u0F‚×´˜-€,’ÏÙƒ§Ý±PIlw8”íVÍÍ€ÖÚa(§*·$JÉ­ŠÈE¶)®yuVl¯M.6_”·^Ö·ø/T@¹-Œ…å>®õv_8(#J¥`Ï>í×ÖÙµž|ñ…åZgšúüÆú$í‰å‚Ô¶}ÊR•E•ô²ìdÔ‰…` ¿íS÷³ÖâskÆ0×AàDÇLÂ0n6§ø‡ rg\„’¦Nö´[‡Ý¥6—è+¼ðÚÙv…ÕIyÔØdŠÄ‚­úR°»vT-â]®H,k$Á¹N¥T›Ÿ×\Åèéµ} ÖZL «ìs`î±ý&G¢òv«ß£ôz}g5-¾Ayù˜^³\¿¾‚j /þÆáB9†â\´Ùvzó¾=+°Ø×ë©éïï/´ïTóõO’Ò:69I=*LŠQ­·r å'î¨ô?³¬Y' vD'Iâ• ëªÍ2· ”Æ-jÔYt)ìÀB®ùÑTNYœªL£•2Ɇ2_ª¨nÙlGû¾7æ™îwäb¤<áåj˸µSÀcä»éÍjÒŽ‡¾ÒJ¤sxÕ.s³R%‰®×kÎù³Ž‘Îå ¥M\?~¾Å•}o>±;Uá]«e¬ß Æ1 ŸM8hÒ~ì ÑEu2úÖÎhrUƒu–±1oEžKœu;Eo•îZ4‘&ðuÍV´­¦9¥g‡)³ÚyZ­ÂÉÊlzi»°„v ¼³5g]úgÉx>Qú±Ø~øäï€% B?!•ûtWhD4“5À¢ÊÈ·È™ð¤ :—­ ’Pü}ÃS+á¨À5_îÓVï¿–šª¤ ïað#d Dz<²†Gà“²Í~LEl¥ªSi$–ZÃ\kd|ÉÅÐé]‰µLš!}·®É>…ûÒûÞdžÿw]ƒp 4äoìSé•1-L¡ØwùÀ}ÛÎ…ëñØç©GÚÚ5v­˜dí^Á#µÞ*Ï’Ø.ý{]eÖÛ1 e"e8âëå€úPZô[uýˆa‘˾•¡¤´\ëïkê°E”Ê|Œ4YÆf")Ò¤jâkÕó÷Ê¡OŠ9ý«lºtiåmùv=¾z¸´ÂwÎ><·‹Ý*ì-êXjÝrëÕQ`ü|Ý8—Æ–’´wåìYÞ€Ø×ñÜæ6ÀÑnÄÜ#ÒàrÙ1(âb€ÏŒÝ{ee»(Çvá" qÉ KŸMq±wu»å¹‘Þ~”aèÐ!y'L‡­Mš¨·š{]Œ$鳺åñº¯Óiy¸|»EHfZäWM[v¾îŽUŠ%®Cb”bàéJRÆÅ gÔ†’wFA¿5L ìš·öŽ®ï}@ºpùÞ¢h Î"x1–Œ-é£åî·|å].£û4ÈA•tÇ~óöï¯cž¯‹pJŽÂ‘ê\U­ £µ±ë¦ÕDô†º¡J— óz!뛤}Æ"¢Ú?]¡K3–ãñ}ï‚È[{)img½?TÚ?žÐØ@V€€ÃýWŽœ¸l˜Bvö–5ógh •~±‚ˆãÃH,¨F .-Zk 7Òøð¿[Žy«o¯žyYWy³SæßFÅ¥¯æ­«nE ‹!+73É·BÍú,¿Çz6Ôd­À1vøÁ&âé„é´Õ\»µ4ýúü‚€P/ÁóîöÚýTHóžúìê*shé×?û{‡Öh\?[ç ;èÝÎá6J¤!7÷ÃN/, ó¨r«½ªÈ>®u“Këú1kü‘æתÂ`"—î¸ jŸ×t¼¥ËXVÁÕ,m‘·]šÖM¦µ5]s– ƒ¬|ÈWT˜ÆÍ› Ž%¨™ÖÛëS5¢ôé4kµCa´¬ýüdLG*Fæpê³ÕÏCÃIˆŠ’ËÉ%öÕW€/ád…ûÜÙ—T1´Ž ¥˜²-œ¹8ÆÙjµ—&¯G öY…õ~ä¡*΃HÎ0eкnEêt_pä[æý9ß?­Ÿomï.iN “¯0žik@¸i˜Îoºÿ‚¼‡%Ô¹&êèËñSdñµÄñ-’•@l’ð¸\jvëÁÂË)11«D˪$:ˆü`—g•ô¢e­,^lLètâèóüš³Ü ’öÓ*i‰=Üs+”)çºAŒOËQH¡Û•™u¸SÙ`Þ&=k_«z*Ò±ùÀ†¢îއSe¨¬/{»¼Ù%ŸËal’„šs{<÷àwgQ‡¨ˆ ”/”²ˆ3ZcrA“wç5;ú‡i<6~zÀ™•RE±ØÔ‡ô.¬ý¨ óoÕsÍR¡D*ßÄ•(ÇHgÆWó œ;qÁƒ¥Þ¶ö–ºV¶ P5+·´lFfôµp eTÌökªÛ¨Œ—ú+Ürá¦gjVÖóØLèK ›š0~LsCb40h"'Ö¤é0Ö„=A_XÓsS6ídåµ^Æå-À=E$ûXÔl®ëÙ’›²WØOŒmï÷¹fžß–Éç%ˆ"þ²½9oΓ‰ ȺÜ0lÏÚì–矗 #ÝÊKarÜJé–ö30êIÖ2¼ƒyÚø^ÙCkx_s¤#¨b¾UùZYSB³Ä±êšK]$¹âƒ>nõåZ~ZðP ×6‡‡„J)§*ð§Çó{3€V~±R†;¿s* ¼±Ñ†ß³›‰yìé}ˆÁï¯××÷×cGªr@¤·‰/ÎêõÚü7ú"U‘Hø²bE¥w½•ꬳ¢sÕí´QÉ­ö?“þv»Fó©Ñà¶,\™3Wìr¯&ïñû »ä‡®ú×sŸ’è–´¶ØÌðïD$¯+R­ áÃ{Òþ~9ãí4š1Xì¼–õȹn?ª‹>¡ešH2bÚ­Uf ¹·4¿^ñϲìmËr±‚5\ZEYDtÊýtž'öâÜ5 ŠÖãy‡öIH}à¬uØð^Q™á½ÄÄÓe‰aéy1à³æB¥Î”#\»Y¼¶J™¶ØDpÌ@‹ÿl/Ìêlš‚ –Y¯vBe™¶e}<¶õ˜7@íðøWc`q¡Œnò'†nÐk*†÷®³Á[$„­m±fìD»@ÊÙ¤(Ý©õ¨Èßû©ú5%åÔÃ0Œ‚½­ÑzN±ïW¦©ŠÜyͧeƒ®Ž¾"‹ªÿwßÙ¨ £·ÐßÝni–5Óf¾èªë 9b7`õÝ©üh’£o!¡¸P‹Šðãú^xžÍ¼)}EMnËÛ´®ÎÏ!6´é6‹\¹í¸§6³œ$ØGdyÃXNj©.ðfÍ—žiš]¯5‚L&.×zƒ¿J‚ï\i3ÇÖÒJ“VV´ÐÕ¨ÅÍÊú–2ÈS×Uýý¢ˆaêŸf´<~?Æ„§Òb4îº?Ÿýó_ÿþׯrŠûgB熼\Ñqž—ïûº=¾^÷×ónãšhûuØìæ¥Êße·zèÙaöðñµèõ?øåè Rw™½T_è5Ö*éaX%ähÙÁ°hb÷éðU*#1œ¡üQFú|+“>T…óËñëþü7í6Óauº}7©·ƒôPÑ‹Û3¼a‡i›Ý{Òn ˜°¨ÜôÄrh”4‰`DÜp íö·¦Ï;zš¬¨z£š$ËLµ]íÍy…z ËthÂÖ 3æjœ>]8KÄ 55$CŽÊ †{/ÔN·ˆÍB¨j¤?ªR®n7äq ðÃCW»il±Y@x¿B`¦ A×¶ôMí¸<>Æ[æ”$T¼-£A¶LÖâx>Õ,½˜ <0^ô+œ›ƒ´2˜{yì BQÖ3t £«Ô4¹jƆ½ûòíܨ-¯ïøú6ÀIiŒ¥Ú*ÿØNEm™ýz¾¾l›ªçB¦Åæ>‚5&ÆÜ0TM«t›Ä&|ïÌÉ¢ëL¢ 8Ìkø Šâ§ºR¨{¹²©€3[‰<š•踫Òkª¼M sHó±óZ–‡É ¡§l KŸÓ?÷«íñlZ?0<=I¡Ü—%ÞiÂæI`2M7=t3üå¨ÄÅYľ*ÀbËkAOÆC' †–®ûƒwðƒ14»ÓõjóŸ·±Oõ1¼-Àx1ª¹ÅÝ^?lZÁåÓ\¤iw»™FV×$©júL]G—áSèÔë¢05ÇØ·V¥†=}“uX«˜k‘¨˜Ä”q_ª N–TYÐCµd©²Nï2Û€ ¯;þŠ…y‚qÇÏÈ«§YÛ–ýëk›-Ìq^¶:kxnpöJêd×uH.0€—¨¯ÆE‡ÃÅ0ⲯÚÔ•,)ô¢UÐç&ÃÑhª7Éÿ®º¼"ÕÔ?P€ÌóTúã멃¸­üerJ‘}¦j‘¡†Ð£ãòF¹S “Ò×ß0W`ˆ’``ž-¬ÿá¨#ºvú½ù ãÉò}ÍmÔS¦Wœh»ê–|&¦©ˆ8@Ã"ƒkn²(!ÊL˜u¡]sôªoN;Ë8ío!ÝÿyÍŸwÛr‡c@SI½~šà‘eó-ÚÞ]Uô×½1B¼Ýñƒ‰AÞ›TU•—ôo,‹«Hj¸æLátüÓé4êš÷vͣƘ{hAý¦þ:­Ìå~ks†¾fîRE¯/Ù=Ù>šó÷ˆkNàâ5©ìS©\öo¾áôGqŒÉ o¯ÝvMonC þÛaæÜàGo†œa †yß̹AöèÛ9º_O¸%V Iš\ò±åùFÃi™›õË€a§š¹ª•Î÷±Ð¡¾ä¨c™=db‚¯“ 5~JfC­*ÃY¢î`f›lHgЀ"¶6&ÄqCrNýûv’ã MÓ»9úëj6ÎaB”­>«„õÚm§»¾“ø•2£ÏÞÓÀ®ŒiÄqŸá=èa8œ(¦ÀˆpLE07áJ8ÉÌÈ'—‚{étnË2P„^•?EÕzuùϪe …ÄßÜš;·<Çùþû—átv#Z ¦ïÆš¹8M"ú[ÉõÂÅ’ƒ¹ !™,2Ø.ùÑ£¦Ê|Æw½TÔo{åò¬lNdrÃ8ip­s£5ÞE%H†íàŒNëÍsºkӫ꘾:¥²ÚgþÎ"‰þ5~pÓc;}Ó ª¥§øßל EæWU{2Fe^ýêu n˜‡Eç]ÅV„jºªV|*ê°ÆöCQÎ$AtlÁF‡ÙIEŽc_¯‚î‹o ´íâ8*Q-EåÀD¼€Ý¨ ÈU™¶ºx9 ŸXXoLÅŽ‚’ì&túŽ›?­%{¸dáákÔÆLÑ=sJD€ð|¯ôu-ôUõDæÿ¶søõº(\—ãAqvŸL‰Š)ž €9‰Ò_“6 a}ÃaN(Û¸PaËn~=˜ت“¬­¾ZNí2÷gñ¦–.€¥d#:ÌÇ{BoŠ$süsìóÒ «flnê¨}{zª•¥*Ú<)l_0†*uw—µåǧ'Úq‚ŽŠ]qS÷ÚqÚûìÆ~ç]õÛ5(@s!R¡£Fµ²¢ˆã f:"uxð²éS 0¿eF—å=ÉÝã!·Úö¦ßXonN»w\¿éÑã\f¸ëi ‹Žƒj|;¶:o9žÓÇ|*Kà•FpÙŒç?_=0~ ,^G,k»8§é(Õ3:5ãS“ Ó¯@IÜBm˜jÉßÜÑy¹ï#ôi #‘Î샩³N{ ÈÕ böû³½‹¬û:¿ik+«ÀÇN(;‹Ú÷â ù 5uC‘&™‰Ø2Rç^AžÞT?åÅíãš³Ë6òÖ6š“šÒ“ÚyßëÎùX<ùn§ç/fó4ú]uˆ>åW|oÿ×ü|+Æ1ÇÉU«™v¨?ö<”…]71õCݱ‰Í\M·¬Û§vI©BmÒ)Ô;Ogô~¡GïÒÑë vYÚ0̰¡Ì¾ñ4ôÚïfµ¾ Àj‹ü”eŽ™2ÂΠו8'åÖ¯´ÍéR™ý0ô%›W™—-Ò1dàæ£øØwa§òBÿ -Ü„Zëýá35æ;ð™©7rf¬9Ÿ}3&¯û[§~gäuŸÙÇâØV{²¹q#áväIR¸ÑŒg£RÇE°ç@¡Ò…Æ·KÆ)Âi"P‘º¡‘32/¨ª˜`ä~Va‡Õüzvúÿû¤’§4£³–Í^Ö1 ?i÷ö»¢É¡Â£,Æ­ºUåç5Óhœ£ôFĮꊤñÔd«®©Ï£ ³J]óZ˜º™,S…ÃZÉ(ôX[ϱòœý¸="…>îcß[Îöv–ï<ÿó–0ŠbäoóÉùR"|‚‹óú‘é;WƒStêHÔGèš×l•Y.UnÛ|?˜ÔŒ^¤:̬顕»€I­à>ÌÀ¸ê¢H0]4dþzŠ‘æú àG;Þ¿¿•j¾Wœ©·]ayèÇ%ªF`]ye^Ø k\€¬oÑ÷a,»c>é ÁV(o¹Î9*ü² ´ÝöÔÞ•C .͹ÇQ5ŒX<Óäãfj†e;a´ª® 0Õ°[8ñÐ1[ üëÏE…mÐæ5Ú#¬ïãö§7·`¤"rÛ•*Ÿá.Á€¶œ«Æ êO=°Kï,¬1õÒ†&‡ínëÎÈWâß-âð`†Ã–«ÓÂÍfPûñh4¦8g$ˆ'o‰‡A3Ìu<@k°3µ&Ûs7á–•%2ªÖ+áôË4$8† á`×Üu³dZ¡žáš›%yF<-íüš‹órÏÓó`Šéþ)>´¡ŸFÇš+ê5ÔП:3FùÛæ•ÃíËóÉ4f«F3†7Uå]ÖÿG_†ƒt:RoÓtšÐGë­ÝÛÆ=.\ù·¡Ó/§—TÔ”¶/0•Säi˸æ3Gf%‡¼ÍPU~ñÙå–g·[Ëì…9Vå ’ Ók5!o iuìºÑ·öóÖäלgÅ«fÅ’*'%l%ëh¡9FoÇ÷5?=w#?í­f‹´ˆ”°šOgĘl[¬þT´¿öY@iÜ~›ý—(  µC—VÅg‚®SV-sUŽTE_㸀¸%³÷¼Åë½`ÉÀá°b¯ï”êìg¦7öcB°MWã1¹ùŽÆì‚tâjâ7'.Y‘zôÛùÛ6ÿ¬ý¶jŠuTw«Û&ˆ¹[ÂÛþÈr­©‹èkª>N¯éåR‚Ô×¼ò£Ï±ÄlZE]ø¨J^f †÷Ðh’a&½,µ–j,v†~|ݸ“FˆUºÍbö‘JsÈF/êÖó‘F§¢æ¯MÒvBEqÿƒashâÄ5ºÜ»éÍïVµ§U·Š>¯×Û®üT_WQ~˜ÛÍ’UÐ÷úè°*ñEG“µ#Z1R·Ími£¹m¶£Æ(kXþLèª ÒA‹HSLÐëz8¶lÒˆÚàÍØ2€‰ pU{Ä‚ÚÐYGI×U%±#R«—ƒäª ¡íiMãÄ…6só¼­¶¼Y^ôXöt[(¿µerMÕEyLzöm38½°µÎ³ŸÊç%*î)©gjãõ¦!›S s ÏE×<Ï.I‰é3OªÅ‡ÓýÜ¹æ ˆŒ ¶r¬1¦S¸× ³²:v<É7§½R4 ºx‹}*™T lp•YN¹ÞÈ{¶lAÌ–¥/.—K¾BÛ6øv\‘**Êá0)–±SǤ¾Ñ$ZXf7êçÐ3òõÈšoAFhtÝ8–~i€ pž~tìX&a@¸ƒáÖèEܺM}¿< &ËèüDögÒnD…i=¦“J¬0Ï[7Ëòùpº±ŒD>šäê¼ÏE’ÿü[é#ÄkŽwÖwi[~|Ô¤1xèõ¨ýdÿßQà¦Ù­ ÿz …±x¯ÎÁ¹¸]lÊø …Dnþ»wœvž¶÷5ëý¾†¾›\vAL9ÌÌ5Ç:g;F¸ŠÉí ʈ¯ÝtuDÊ]_tßûJ!¯9+pú3ž6«„’Hi°Ò¶ÿ¸p춉۶å±’†±‰WœbEÿ®Î;e-Á!ZØžR*Iûñi}›Îêw+òú8ó.”õæµ6êÖzPÉ n¡âioÕ ªh¿¢ø6šÂ)0M¾Jý¿¼`ꟹÊâÎÔ'Ë.èš« Ê€¿Ùõš(ëÌcïã¿¿~­³q™f ¹œ ¼‰»ÑÜmÇ»9ˆ~@ :wößÞE=dåÉ «Êu„ljᦠe¦”ç 6¯Š|Ù5S´2:^ 0Ú„›M3;³ºR:tͦvùø{ÙÔÉM?ö?Š&/½ËSÏ_vx¦§}ÿSíº*»4M>’º¼ ¾tJBLLÍeoRÞ3+G2θqAl°¼?3©ýþüzEôÀ[ ¼ ›•¸ ¼ýúz=Ÿãvß¿þúZÎ2]'cí0ŸKɇŽaI‡`ïÀ³SË–ýÜÍ«~f¥‚iÁùìÚ.êñCY-MZ"^‡ø¯c¡rõw×/º¡ʼ(4ôúã—Lñ¯ÿˆÖ~×uÖgŸô›œõ¹½GÎIUèh×^>.Hƒ^ºn÷î¡vêŽ0îÆ7°É*ôµ¨"Fõ =óbwqö-%fX(ñam‘áru9Dñl5~&J"EôMb‹Í¨ƒÁU¹¹¿*#ãå)p,`ö¹k” +4øh‹Ž¸^¹c@¹rV}·Ы¢ÈP_Í6·oõ\Ê–F½åQøÏýXáÄÓCj¬°Î6,ãn¢SJC&B C-£¸…‡^éOµÔòˆ£º µuÁbm{<¸êú¶z«õs›~lÀAþåEwcÛ˜ÖÛh©h 4îÞY¦ÿî»0výhC¦ãèv½µŽ:öä@àû2e›ê2h¬uÎ19>ú×yùó–ç(NôºSh–N•™™X©ÔaóéJÜ{ÿÃ\Ábw:ýë13Œ0’ª×]ÁÜîfdë߅ןl~ªIŠQçlÙcÁ]‡ù¹ê‡LoE9³pQÕ¦„ õµë“th’~RW>ïSçW•©j]†1¯Ò¿×ݵW^µæ¢ÔÀÈáœy°X@«ÒHê´Ÿ]ú¼¿þ­HšaÚ__J Áæ@¸fÃØEƒÍ'?¬1msÆ#Gây_§h:½¼MÃì•qt%_¶÷Ïk_ê~ÛÐQŃąâ­íï¡ST­¼Šîñ¹=¿Ö¦ì×¥sÆz®ÃuEµˆÚ4S†ÈYJís¹„ùÁ£q§¬Ô\*ô~zûç&::èc¸£àÝ£a‰ƒy×~?Ì;0ë¶G¦a¤Ú-ôPÓ©‚s?Þ@Æ·Ø—"Ý3"…Š>ÜÜ|^/‰-‘T!·¾Q¼MÒïŠäx? XìªLŸ¥D Æ4L¢î-×?žáä,(UZ™¼ ôM´‡‘lj5z+l’ó Hõ!ì;*€´•9gÙŽ×_ÝôV'š¿Mtë8ƒBÈwÿ×_ߨC®¯{<컹£­ÌdÔÚÅ)åÚÁü#…b|_sà÷»©öqÇa6F+ס!®’Ì{wnŸS@¶£j”£L Ãõà£ë†¥ w×YFLÊ¡BaþŠõÃ`~Q¨çy;ê·ÓŽPÍËâš™èYWÜô©îáG÷Ãðˆ*¦nåÄ`ŠRô±Ñ Þ_ã‰[§@gú9G @k`8Oï1œ™/X¥±ëËÿø—‘x¯9æÛ†¯<MB£Ê2ÇÅ»é’[W]Šªvó¾Ý¼‰^ K†î/2òu1ÕõFVmÁ£.\쮾ªOTW˜|ފ륵ï»Ú±µm eœÔŒa)9Î÷?#圻žWöçÔz5ö ÿǪçn|¦ã!¸ù>oA)×ÜëÚEÕ$ÝÚ÷ØÇ…QeÇLNÅœ^÷´7.Å›åJ¸…#²¯Fï–`¢@9µáXFëåz% –muóã¦ˆß Å׳½Úk¸04]Üá˜t¬N%Zì8ÊÄn8Þ2k¿õÏ«‰ŸZ-§Âë|Z~Gqæ”ÆS7nsÉÓÜza"tûö¦ž°È»*ûlú„c p½@‚1kC¯ºŠ¿ç5Z$ p¹½áËé|r˜·Ó*-ØÎH)Æz(øË‹Ùº­UZ±S§D]!¿ÒW°ÊPk7ûqÝ”²wS½a@^H?ÚãL‚Ëc‹bÔ5¡{a\°Úp„Q+oÎÑ×<Š‚Ù57Á?vçÍ®yk®.Cce†-¯’¬6riUÀ‡Ž×œ, ÒŒ‹®Ä•¥{U7>öfPŒ[kÛ*md‡rù-ïÌ=9/Y¸=5ÿ^Ë雥µ9óàÀ‹í>?uê‹.Ïg7eE•6mòYÏäµnÊ'ïçr:£EVʺžÈ’ÍŒ‘»?ÙFíÍÞL´÷PÚ"H ã òs'c#4Y<.>1©ëœÃ©æsR]¨…JÚæzSÕ±…&ÏÆ^vÙ¬u––åå“)s™UCo Y8§ ´Û”È ߥ-²1Ÿ*ÚU*O¨0¹®P o¬®öõ2œ®ÖÆáÛqiŸ£Õ»ÁƒØ"?Æ( <¢´¨åDL¦lÛçðÇ;7˜P½²¹ûè¶¥K©2¨âa·ãTånºÏÌÌ‹+EÅ´¹KY¶VA+¢Áñ(Õ€bä™§æ„ØtÍÒC^.zÅ~ž¢Íšš68%® @/Kìo“Ba°0eE…u¾Pt‚âzjÒÉ#žI”8û‚íMÙÒÆ:ÓqrÄâÖÄ`–G£¯Ó¸6Ù¢&¨Bà¦Jå–ùÐn‘:¨d’QWž‰Vt|ÅÉìÏâÆ•Ñòfpƾí€;¾á‹±hþÀ1¶(Q9UI…³?úµ M«f¥fcnŠ:‡+*õcVy¦ôûÈõþy­~'pƒëRPÎ[N¾¯/Õ¬È6mL=è.Þ×<^ûCÙ}øV&Åá¨@¤®¼õ´Z ò@qåÑ«d‡®í¸~ÖI%—ùOŒàWh±âHÎùBW]Ý{U”.o\“^sê~è ­AàNØàõ£ifáUGíúKÁ@]ßæ :”O+U?å-sÿ¦çûڌ䰱Ç0Y¨þËxNà¦õ”@tFqoyßÓ˜àp|/LÎäo¾w—Ruu¶~Lõpíº—í€š¸C¿©ºì󒨩Âô©ž3µú#Ñ»ËM÷¨ŽÞs\!U†Yt-›1¿uýíZ2v¬šaŸBWè§© m;­ÁL™ ×g0~¤%[÷s ­Ì¿^åÈPwËöÜŸàÀKÎnµë€­Šz­àé3`ޝV¦`¾Û€¯èÌ=˜˜ãÞªHdö»=ѤôàT›N¬³o_Ç bƒ.Æ–có¨D¦º-<›ÌAÉ¥ý0½—åHî«xIDåõìU4S(ÄõlwUÆQ†µ|¦]µ³m¯·ÇC´YÆa}S øêxfeqÖ®t‘«¢gC\6¶Xa„­gß%W%]®¬ç‹(?ÿ Ä.ûOѾÎÛs­S%~[›÷ ÷^{mþ×5‡y¸… j³E3ÇY3?DàÕY[]Ôç&qºaËA4“º”fOßšüí»hG‘k^«¹j&¤A+£Ob†š©ºuüic&ÐÞAv·äÖ1™*€M©÷Í“ŒIâ–ÝXazœ·Ÿ·ôzm§Q†€VXçˆÄ—c§Ó™@'1^sÜ7£õÐ9)ïÜŸ=óòö _befD-Ø»ª}JCvƒêW›2£q'qb®ôÀ›ÄÑ•Õ~Zf×k:ô9ʶ±®µžDýáí¢æ%ËkÀ*KýñærmxÀŒ U,ES%I«nf4•ÊùÄWÍnÛ–Íç°dºÎþóa¿öÓmã4V‰ºÍºÎçß=ÞMеlSc°ßN\i ¯gœµ²zÂ]Ö®ûxÊÝÂaç¡™ÁìuÓcU"ÅË!ÑOç÷)ÏúyTD®׆M‡ƒuçØ7ÍP^oðÍéxtÍÛÜh×%¬ 2“¹Ð™-ˆ|i°K0tñ]"äo1QµíxØ ÝF©§kýÁ~ôȶ”ˆŽ™ÀR¦íyèNælMB‰zt¸£†¼yZ ET<_¤qA«`Ž÷s¶èöÿѽ'n9hÔp¸ê ŸqJˆÎ•‹Ã º¶Àõ0B£*¼ÃAjdX›42æ2Šk¦~ #šš5Û †ˆÍرü_ÿúùoV½Ø¨ÅúÀ×Cš2êÕSj2¿°5Z¢jÊòß×™nh¤×N™¥ÜšE_küÓ&{+Íö§¡9ÖÛ¤±ºµYm0©ÊBôÁágË– ·ßWíŒjnPh³øTÍ›–ÎÐe| Ô#…XE±½ÓH±†æš^¬ú ´”¨ uð7EÜÁÖ•Œ˜ ÿz€ìåcºq>eÿ˜6™{ù4ù“ËõÖþ#äý»ïë>œzf„v7²‡~Ä.I«„”ÙÉ£ª…#:Ô@°°£9£) Ô¬ ªì³Põ—‘°F®Aþ˜…‡š–ñýÿô¦×(©% ó̺LnI¢â¿V›Kè f†Yÿß› ‚Ò/’DÃÛâñÜ4-4 ĸ?³ |ئ~_§÷tñt%z£Áß“ö¦¨PMKÃ9aÔíçFµ£rEÃ[€Q¹NPçLØ·Û<,”ñæçkTGC2¬S›ýÊö¡ CR 6(z½O&3?*®o‘ö3_šªg¨’<ÊÙbß©¨3óKÆ€Œ^™(¡îQ‘WÙÇFlÚ•ÔŸû Û÷¾–ìz·ìvà3Úe×f…˜[£Ìúø±o?s§°Ô—û¡ÓC0²¹ŸÕ®<ÿõ ÔèJï'üe3@«¾É}ÛŸw&m”ÿí… *8E\#Fž@Ä]!h¦õÉSJ½íµñI½²ÉªºÐ¥ªKÕ/MPÐÌŠÖpdꃹ¦Ë‚?øyµ.úëñ|½Þ 5õæCy©0ùÈB“ÍÙ¿³?1]ú¯kN1:ÁZ³ÂœÓCæëŸuŠÝè"u#\ƒàÙDÕ ÔLµ†òešÑšß µ‡¹@ C‰}WwàtèõℾөOni=d#áŸeæeÐU‰Ie”ÎÓ¤L˜è‘wÙß“eņÀ쑼^ç¤^c1‘%†6 CUß¾ýì±=‡+x^cuÙ–ööó×|‚Ý­•B@p5péÏsR®uàÆAѽšÛ@QÏ5ú¾yq-]—gW[¥M+š¤­?KöK@å:帵Q3êÊ!ל_ˆki“6ëæv57aµ6*NyÖ2Æòx¤ «ªéu{A…·JŽ¡í^˜>Ö(jlöÜ SRš—7#/Î) Nf$»fx„* ö•¶¹ŸÐË®j^ v惘¦ ?Õàý¼tp½žóþTŽÅyD¨G¦W KÂ(¶ažÜ@A¢zaØ~ J¦ ç.TlmJÝýTǵï”õ+˜NéÏUÍEÐâ²oó n‹ã“S-ä ¦á‡ߥq¾œ{íÂó^^ñŸÃyۈά¬ÇÔ²þL†ÕéxC l}SpÄË,I³7Êh£-Ç3Í!ÿ¾.ðÊFÚs^ áÉŽ†µ²ÙEÀtV8ÞõŸÐ..ΦÑÈ…ÁÌ“T¦>«è먘¨Ÿ×aذo,öÃ6 ¼u«"’cYTæ‡2 ºqm7öû·ûëû4J}|ª1buT®Ï§ìŒz•¾¦–2 ÃÅYU:=žÁF3LôRÓÃ7ó/¾¶CÛúÊŒP)štF°ÜÂ!¶;pBÞÃZ{%»R÷ÙdžŠÍ׮د[‚L£º{²ªWºûÌÆ©6ƒ{ýù{™5Ëëg¡ÚÉ·lc›×Lr›²¿¤øBßߨ°7ÆÛ€òD¿mQªË`2ýÖmÿ#õ§§ œþ-÷¡1;•7¯eÙV*Ðä8ÜI”¯×ôgݧŸÙä¯é²&ù(.?•RßÞT—N7U¾YÙØ'PÅ¥nUŽn*?jwM{K¯ùUçÑk–c–ÔzJ ’ð9â¾»ËbHV=*º¿¾ß ìË ‹q<,’EéùúÆàáP¨È¼ 4ARmÛKuàs6í2`œ1ý~8U´ÑªÂ¦9K}µnî“j…§ œÝ„±z°\=»B°;ש*ü]8ü€@@ç°¨ÞõlðôcF+éÇ÷ãu÷nžª°òÖtõp$9öÙæêUp¿1ºè³Ÿ™j‹Wâ=ƒ­c†û™HcÉof1«68Hóò¶Qœ‰ƒeª^©e”ÖÍ&ž§çûÑÌ›¯ÙH©x[”ë`(ÿ×"† ¾ah "B<Ù÷5:N4êq®1Ny#ô lÊfjr<Œ}oy[ÞÒ©AtÕE³;ªÄ`çqYºæÈþ(…åƒÎÀ:ËutA‹†~]?äÉøÆ»G7û\ŒŽsp7ÙrUQÉhÝðF?°7Ãà ºæÓîòŽæí³2Ü­\sç'úm÷ f"ëLÛá1ˆ9–>†PðË ´Í±ÑŽlIÕü6t«(`㎣ŽÒ¯Ÿ·ëµG°yÀô·>JŒ\©dÁm5ð…ÌÒë'¾eúãôöÈ;µ–· ö9( ÑKå8؆+Æÿ¹Þï_qxåו»åóëµ6ýÕç”%mˆAó?§:-ªìzi}‘ù6íò"'{4¾ÐØùRS–å¶î†ä³ìpaèû¶—Ðçjý³°; 43Íqªxrð¿õ…ãñw=Œ­Ì^åd>̃7]B›Lë‰)Ù`nØâÃxE# ìæ°>M:°Œc{ÉÂ¥¨Ž{C#áUë–n¼©£An[0J«ýŽW¢ú¬ÈƒÒWLºàì2ç_Lpª;ÐÀ]èûÝ©Þ ZÔÞƒjV'ÿø‰’­pÁÅ™¤ã´Loü>uØ©mµ›˜LìÈ(álúýnª‡¡/Ìh\†ÉÚÞ.gö‘){„B]:(í±+i+û·9QîÁù›MRЖ²qºyü¹æïIî{ä?ÙaCMn<“ àcf¢ŸÑ‘U¾:,9Ê$ÅaÒ{cLÔJv;ž-J¯ ’Õœ§<Å2CÒFúuTšßú†K©–o¶O«ßòõ4ÜÐó~œƒÖ³\œˆƒ(V8(ø™ÉtÀž" ;‰H8õQxÖ¤½L+øR}S¢^•?{ 5}þšÙ¬/ñgG|KW#‚¿]°…&RâFòjºhí„"@…N®ò*U(xû÷æ €Dy¦ð¡ÓMÏ®2qc³KÕÞ²ž°ôÇØÚ:ô˾œZ €ÃL*ê®Q–s§ö¾äËé1WÛâ\,ï ̇>M‚gʆL¦n½zÉü¢®#©•üÔyܰ—_Ë:½væœjãy‚dë µ¿ú‘ÌV¬Í>¯EŽ Ñw`>å2ø…Qu÷þv­Ê£§8ëš=ÐjŒª´TDö·¨ B¡ÐØFÓI]¢ÊÁºÆd°nsDÉœÖ,”ç1ªTw*ä\‹æ<•cÅvÐ/ýÚõUÑÔÀú¬»¿âY^ oàqÕÅeyS(·íÄÓpÇÑP¡_-§:bÓ«75¨k©fx2x˜~ÛÓ ŸÔ{Dɶ._úÍ#ƒT´ú*²n´,EÞ©)UÇw³í§Í0r1FP9eü[ˆ-¨§QêšÞšWúOꋳ<6þˆ94Õ‰õ‚°…ä¬Ë:8ÌÒŠ¡6UeöŽq¡9ž'ks°-öàoÏkþF'½ÍA–S¬‡­Âß$8Kµ.ukmØ‘4PÝ‘0øb„^4a,JŸPG˜ÎßR¼%æ? &´Ÿ´~Ã…™³žù¬€YN¶Ç cúsÍ#œÑ¢$Øh&¡zÝ\#h}•V. «^Çç¾Æ2»˜iÊÏ[?o¡ât)—}’=L’ÂËÄ ´æ±û(/IF}RöwLË}WgM“\Ô T¶~4T ›ö)Æ)Fk‹î“@ý“Ά­W_Çvÿþýõ`möüz=¾^OCÊÜOœL´^ÙìÜp–ìðZS‰¥WßR£µwfâÔ Là¶×uÖµÿ™¸á<Þ µ)Ú º–IQßú:,Ö5êt~½6eÃ&¢™:³/*ô{‡e‹2ó Ç6«þÂÕë®”ð]¹¢¹mc†h0¦‚‰ ¬*RXØï«GGÕ ‰²4YCÕ\™¼ëòUýö`p‡õT&úÜëóömÒA7®\`¡‰úzaukÑYgÆ.ËÓ)A•U§,¡œŽë×ט‰aHðm˜ÛÆ%vê@!õ£€7|ï RÔ²—h‡T'âó£ÑI[H,^/e‹ïgèŽOÇ6ÒծجªòV$ù9 d‡^EÖ„ÑŽÊžk‡Ë{i=£Îrš+Ù(y[§üþÁ½w†¹/Ë,m‡*ÍñÓž…åq™_3×YQ‚Š6Χ½‚jP7&Æp& ó7ùu3’†”ó½FðÁöga³Û@tÝ´œæ0¬\u3ú'Ex<4D€1£PŽý}œ] rÿ8~š,Tµ^”ŸÑNÙ|ÑOQv^dZ̯íw§Dy {Ü®8:ù£gS=Ôj W¯‚èµ)[›ºÍ¬Ò(ÀÍr\Ê–:ÁèD6mW'9€_FE í£3%ˆ!Ô㨘:‘s±&n!Ò•À¡@Ñ@PÄU—«Î¼ê¬ÓY5 *nÚËßЭ Ä'§•2Ky¯êÔ1ë Žÿsw:fNçœÄ² ¿@.Ô¢¾Ý­þˆE¿lr WëÂü†÷¸YV@V)ûÄRmžçm–TÂÍ@$Q V íËг¦Én ½1ùml’ª R¼ oŠùBšÐÞR§ÆpmÂæù¿*8R ×…ÛWoEïØ›1êÅ ÿÛðûX j`ÅÆRÔðÆŽF2L\O/E“Uþ4ÅÜÎù[®KbSÖÀ§j}YŒGSÜr,ôú¾¼µÑš…œ1wy‹ÈX“øjà›ÒªD§ pSÖyèætÛëPë穳Hø1ï£S…>) Úzßõ-˜á›Z[E¿~¤Ö'ú7¼SÉÖ²H,·Nˆû¼#¸Ó¥`|/Ô"©åþX— %»v,o9,8=Kºõ\i³N¨­’cý”æiÑUy—w³ÙLE+ o ³èEˆ×Æôj»ì³7?÷“ûY=¡¼°•°.…2%`÷ݱh¥Ý‰#—"-á,¶^Ùòøç=˜òï1€ûòÇ?h6‰c5¢¢‚ÛƒfżÌB–³£¨ö×{ŸarQÞ¤ÆÞ¾u¶oò§‹ î¨R¹ž¾–}í¬¼åfšj˜Ø«¢êÊ­'«Ö‰Ça{q©éb­;|ݱÃÌJ#(I!ÄÜöÇ,\4ÀØos3îÛYð4½öÓ¾xœ!Ì#IsE÷¿×ý{š_n+¬øS9ˆº rpÇ Í¬ £“éÚÅlÎXå· jåh±#š¦–1ù¨Q´êÂ’Ts×b`yùè\šØˆYGûÈ¢Và ìh—[úZNq+4ÿ‡é”È…sNUkœ 0ë³áÅþHwŒûA¥j~¸‚²¼èé×hõ©ŒWaMo*(s8ãÙg9Í'xöØ»›žÁ¬¢QñÕPÒ0Â'ø8}7©ÂPvÀ¬Ñåz¬ÿ!QÍÂ$„þ„3ÐþÍc›¹B»Zƒ½!O£¬ØN¯ ÇÑØ ɕۭĤG§3¶Ñr_8ò}|[¿™Ö-uë£ÀuŒ·æxèŒuÙG6ÔI¡6û·HT–´õêÇn1ׯÞÝV•ÝAý?žÇú_bCF*ØLi'Z*›ÞÞ{{œéîÛãZfå’¿^ÄÞ˜aƹ5 rá˜5W™™G!=²ãù‹îƒØs_ŒŸØP ï¯ï§²ÐöøëŸÇÖ?łʘ »ˆ[níÑ«*ó~9¯h“iˆÆ(Y®ß¤ªŠŠÍD‚mìÜ¥èCg»Äèc ˆ]qc9ܸ´níÝè:À|†d¥Ößè|€÷hô[—Qyu™­Í±ieU{WûeÜôÂÖ 5èõ9D¬õAQ‹ëжŽT «ÒSµ¾ý¼ºI!´ÃC3׫ò^5nš©m Ö.÷×=¢ò©-¼¨¢,’vêÆ¸Ž}<öQ‹|=…¾§·¯&ïçyF/®i6AîL„×ÌH^˜hˆê€örm5x@A³”ƒ«L^˜Î‡îiUv3wuttfûóû×s¼ÈרL…JÜ í5é„û$Áƒ°MT%Ô cûÑ,>ý¨Öû¦¦^…àJ³3RÑÙ©Ù6pÏô&ŽÈ` Óã×Ìè½Nǯý…¯Î±FוuX»š` ó¤$]n€gÈR× píÅäïU„MUÖb8=£3ÛäéØd ®Ú™¼÷Ý3»rbÞ7»¼sG°`†°BSª;ïGÝãÚ«?šêö÷¶Ö¦ÞeÞU]]âB×ûRtjÌ;Øiè.¢xŠÕGk¦ÐQ(¯HRx].u(#ùõ©“OL57,#Ï=:Š}:lÎLêClÔéµðHÓ* ™dàmÕñµ*úa™ÓùîÚâUÃÅ]þƒ·™N9öHˆ`ZÃ'#3{.‡™‰ƒl*=ËôqÌ,|m@¨3f²™/¬º¶ùʺpÍõ7¸ä¡+9àÿ}Ñ2ýˆ7XS.Bj]YêFêk%Y7¿oU(S¦ôø¤…·ù<–Ùûš®¶isΗ¹Ó¿¿n~ÙÐJÐíí_½µ{§Ó0àǬú~À¦@)§uo!l«Äý:íÃ6ê½Mú‹þTãÀü0ÁCíŸ6wÚVuuŽ >:ý¸µª uW 7¨Æw0¼êâzIõ"ÀØMG¯ÃÚ!F™Ù‚ªªU ÝÔïiÅÝ&¾«øpæ˜ÓP•9³öýõ––°¢¸Õd°²…Ì?)·ª+ÕÇÕ>/Iš2¨:OoyT²RŸ}ùYõúT‘h¼£d†£êæîR˜Îv v}ð®´¾@gU(4uöúnX‡¼÷ª*k¥æ¨— 2ØÔ² kÑ‹Âíf@}ºRt¬ã´?”¼NpÏúvÝ ³}Óžo³Çû©¹"8¥¶šm`š5îŠtwG¥b3³шÉé臕JW¯¤:¾МÌü&4(’zusÚœŒïŒ$J­ÊqW›“ ýÉ7Ö`*-ÕEOcþq.hâž[}ZOmþ· à%M[ßš§³Œ‹„Êž,­t6  äEû[Wº‚ë‰î?sØX¡2)·Q#»câ=N‰þÝPšëç–“ £Ò¢-Sö[$ÁÝÿý*ÉÑæ¹úñMÓ 9Eöö{¾E ñÑãÁ»ŸƒÎ㟯^] €î*š^º}øúúÂÂ*&ú£(ª"æÁÙeFžÎñü‚‰°Ý÷?ö@ç¹§ênuóø’ݰð¬+8Õ4ËñѦGÉYS›Üœž­%œŽ9“¡µ{„V¶æûá†-¨°SSåÂzRTù¡çÝ ºþÁ0—~Þ´ŒEÍ_Jê}ºÇÜa=Þ!Ȭ[ØÚ1òœzS™„ÒR毥쑠JÔ}3™ï9‚-V7jiê©ë‘É ¬€´6Iõ«Å³©¸é:§ÚÀ;ËÙ)7†iô® q,÷gðv"bk0¤^Þñ›YíŒÈ×óho¤>ÀzMWôE…ò§Ûw´• –ùë7÷ÉÐU©¹ fÔèq†7¼€^®+ˆ±Uýd°6k+”¨Ö€²ú:ÙÂü "²ç˜ÂzðYÌ?&i_—³YQþÒ+ʯi©‡œäÎéC-ð'èl@ôÎ1d-›ÐgÕŒ–e¶Xó°µIÉú%GÁÌÂa꨺ì6À}€¬Œ€û¨L1)Išü§‚eÿÃÆ:Ôutº W•[õ¤ŠÖÖ2,^ r ?hGcÞN[2ú‡ª@Ý»ÇjŠ˲½¯„I2©•[M,2ÊSÓ ú,” ýKSDë÷.R*wý?»æê”9Òòz½‘ãúp‰ªEÖ$N'¦lP¥akˆ¦R9¬CÙ¸5­%“võªU(?ÛP§/ª~hWØ ¤jAßr9UÍyD„\U£Êþx}=ï¸]ÆÃ7m–;·(bʾfÞ—íõëëõ}ߢÿÒ y£º>ê›ÁŠ7I¿”YWMm퇦0-¬Ëuƒ=B>¡®œÓ·oФPI>?wÓ>Ÿ tfrf>¬¹žI˜þXº1µÕ m¼ž ;SÈ’]qÿ£ëb2çKÑíÓ:,0¿ûØ -… `<õN ^ýCis¼D¥vzS[—;¸‘¡÷ÿ!"*>º°˜XžjçÝ ¡fج /D… ‰Åv…Ù[L¼³Ï›S)ûüKôb;ùâêv«Ìô×sg›¶[õýˆõD¤ÌYo’fhFMsÁ±ú|XgàX¢¨>½ÐŽ~Ý´žq„J^×0Þc¹ÿ!PN ‰ºÑ´gê¢ð,¢2‚i=ÔñþªéÅ’¯-yãGƒm€Û€ Õª‘<5«›û¦\SXø?–Ö}T:ž¹öjh”îÝ6Ì{ õ(~ª«C·»Èç»ßÃ}q\ó±Ÿq§žÚùÞ©[E –Ý$$ñRŸÑÍ*‹€åü_–Þ•×ÔÊ^#öö[ÛëpÅA³ûž$Ib¸¥i^ß\Ó3kÛDd@ÿÑ3Ãy[–wÑÌ5òIé§°,wÝzÏÄÃZ^¨-MûW™XX?çúvç'C*2èH% Æ®O”ˆBsÕaÓ3…ŵƒ“kr½©AîÛiÈ‹ P s`y¨2X€s÷e2K'T€©î^ÏÇ#BŽc‹ïÐb£5«ë¢·*öiâhX‹“WnlJû¡ ÉH’5e7ê'Ê’Ý€u²SND xôMA_®«k¤¾¢Ð›ØìšëQ)Jà½3õ36TfV2®QrêˆpðŽ,ÝvgµZÖª(É«FE£—Q†yÚÑh£HïÛ¾-ÖÞ­¿"KX¨Naûx‘úyÂÈÌËR)}7½e[¢l!3B>. fØ™8 x-µ›æóF¯ ±wÛ•þÿŒlN‹Æq~ k›£H;x™’¶šq3;‹ÍЩ;ñ^´Ýÿõk(Ôa =F?¨øZ€¬íËDKý|"¸» òt:Xꆛ/c˜_¨ÏáÏHÐc‡±.Q‰;ÜTsÚ0³g%1 ôª«G6g‚YáYlF”]ËÓ¦<|ìZ©XßN ©èìÏ Sçu`d+¶Óû­‡"}gØ7·¯,×{·øcq£îÈÔM3’ͺ™jq|RUÃ@c 8 e™ìZé^±|ºæ8Q{tŸ;sÖUÇé)`ÖÉÀrín7ÆÒè2õå5ãüEFtMá™Ù|^ÎÇN{‚?×ÿºëjV’¸NZ¾ß¡{F÷"ƒñôb×*¬0 8¾Ž·)Ô)g°Û_ØGC¦B÷Öô%JšWp *¹}Õ-\zmš4É“K­¥·©b2QÑZ”º;H¯fáíÕ´‡C·‡ê{‹˜ËÁÅ¥ß0t,tk#˜w±-ù…½Pt\y¼GoÜ=!êQ×eZe²"m×è_ޱSe`Wo#Ê=ôއ)O>Òqò&Âf:Suš©º˜ò^ùQMJ µ"³)ÐÎËöwZbý€$¤B~Vù‡¾²ÚOtÖΩؔ& (û¦*x> Mü-ÐЦ)PŽrêÆïyRa– çlP¾¡ŠuV¤;9gJvóþx¾8b CŸWj Fš*Ð}ÞC‹pz­bfx)++ŽÃƒsÆÉ:Ÿù?ûÙù½¯=[s®×i@ JJˆ Ûµî"XixÞÛô’t òny=£MÃfQ×ÑãQeÀûš›z­^#ò¡ª\§ ÷¬Åã¯&„*…‚CÉ\·Ãþˆ Äèýä1Áª,£Wz?ŽKUð,Ãûšc¼«ë_ùh¢âš¼ô†n¥ë‹fšU4Îa1È0"L“_ö»iœ©ôÜpö¥fUŒÛ‚J+EªÚîÍÜïso×¼§.¸²Z×4z³\R\å†Z‰Âbšius_zÚÓ>BRïCÙûšÂ¼¹þýZ±³YM9w´­¬«®?Ÿ_˾«úâSEB»˜³žJ6Ó~ŒÛvšr“9›«s`Þ µÑ$»Âˆ+8ab‘™lt»Þ÷±¹Ne¢7ÿímwoŸî5ðp××MCg|ùKri\Õ7cŸ¶}V$ "àu=ŒÿûÖ\úü£pEº|OÛïµN2ö¹Ê~ªyX¡¾‹_žùùx˜Bîˆ#7ûäêºiMº·¡‰F,ǃGMò5Ñýñ}"0œFÀI”?½\úš7»‘2 êLBuø#ÑXù žÖ.-úÞ>òeñÓcð®>Oj|Ô²°¨XQЦ°¾$=ÓXãnfu1ͯµJ×~ðÀfR—?n9@@[™Í›BÀºšÙêôë¾L΋0Yæ y9R¸8½tPlȲϴ®ó4 º]N­a^A ©o©·»ãßà¨÷ü3ÅÐMc™±äðÛæc®A•oS.Ï}8ÆMÕZÑÎŒ‹X¹àuˆ"É`O5Љ1€³ög2_õÍ içœçz½ZÛS@8¼Žè µ¸w3×Ô~?”(7#½Ï(îgÕ»)ýÙxÔ[0 UÓµež”,áÔ¨Ô…#ás£¼è”B‡,uªǸàYŒl=àlŠ*2ŠÊHã臩ô[äÂ{î¸z«ÄTÈ<*ÝÐÊ2ûD:h]T¨)ºé¡†®uøcHJ¸Ñ˼ÿ+”wyÛáçJÿí×M_ <\×>׬èÛÒ©Ó-‹¾Iòa(Tr³Íl.jÝñІ~_”leƒ @öqi'ËÒ¦{ŠNȯfýj³«ò<½f-È8rÓ›²"wDy“E™é€>šÝ‘ã9–( ø‡Qx‚igXC_¿ŸóérpW·¤”ºy>qÓº@¸(¾!t:!*T²KªVç”K dimQ¶,¥Ne§,ï·ûܯËä=ßÜú øR_Çýë1‡©LŸ„4/¦ÊúUŽGç'ësÇ;V n»íu¶ˆàŸ7üÛ#M¹ï«kVßò^-HÓ•Œý@Mò먎ŵ8oû–i¥Nj Ù§j²cS׫g¹lœUýê•iò•q3…n&;´Ihrœ‚é,X•VÈ{Qy“¦]_üHAÖ+‘&×ãìnUuç×n(¯•d·6‚íÛ@¢PñÏö’Z´`FœÜz_BG)‹l €øš¼ðJ'u1­±Ç)¶°?Ö#»dæB‹ý£3ðÆ`]Á½*MUf¸aVë S›(ÇTHSù!B¼ã“µj Ãyô§êÈrš;FŠ=P—±½ÚlÂd ê2g˨觖¨ÍÇ×sß_‘R°?L÷kÅyÝð‰ó“m˜xcÛtqûÝ”Á¸á¾ûÆ1¤`ø¸&ml.ƒ…ý@†Ì —5 {dtñP™'¡œqÃjSYòˆdAB‹NÇ È(§7åÕ™«BDw4«»æêwAŸ†åùê ÇGgWTÎÜlðv@C‘]¤€ïŽ©@ýÊ eíФZu·‰ivmÕÿ!æ5ôÛ\@Ñfr¯/˜|\k&´§¦ÃѶ¸&¦(¿£dqN=ð†ø˜ýpú˜s…ÛéTÙ£Ûùz£É–õ­êwfF®ÿüá<õqîÉš@§0Á?ész†oLhÏ_ üJÝäªïÞlúL HýBÖ5¹¦e_£Ó«P¨Ž`Açeò³Œ‰¥ž{¶³‚•ý¸)|-sP³eC"¤êLêÒ™0¢)Ÿ-8¬<™Ó=ÕÄ¿}Íß>èŽò·hÒj𡚴õ6)‡?ßúæ ¸ÕVº)ß{(˜‡ÉgZÝSÎ{G;Æäl³„Ï´dÂREAJ¨Zs´©SYü!ª8uEß? ˆw]Xãzp;í PIiÓÖ7r.µ[÷?ŠB“¯òn2ƒ:t\—/7î¾Ù¬§S(*u™nqŸgpVGwá© ïBr+L'¢7ë?õuèÆ£&¬/ZèGýPÙ¹Þ×±¯Í¸+Os°vè«´‰S˜§ÖcœâÌ'¢S÷ÇÙÎU?Úòé]Û¯Kü¹îÛ±ªáH³í¯c\ï{TØÞâ"Nç,B×"HѸ2fâƒÜPƒÐ³qT±V‡=¬ÏÝ‘Ô5z82Åøm“×U -ü4E8²áL«ÉÛ²ŠÕ,sÜ6r=­J2ž!ü½Lì£Îjr3&)«íò–º¹æà£û~˜¦ï‰÷í>+}0ßgЬaɇK|÷Á<ºÂâÕ„ãLÐEKÑ[6Ðn ZªC34 ÂLËX´f(ÜØØêšãf3¸Íj.SclâÇ„IYšd7Áø'›Gµ5o«Õ“vcN·Ë|(-ºF N4¦?×Pé’Ê}$¤„ Á»5=pU æƒb´!CÃw¬/?Õ‘ºõ®c–›l ò=¹(»¤§¸z&D&T$ýõй¥3`¯¯~`–†¶AJÍoB½éeªp__Ïu>¾7󜷷¦Q ´˜³šjZÚR%Æ`mov&…>ØòE•žÍÈDØZõ°·WõÝ¥/² –…,tü~Tõ­Àl¯1n:aüiõgÔ{†ÓÎn]Nmè`Ó¤„l3ç‚«~ïZô®æ¶Ç=¯ìGsæ‡ÏX>¨õµÙ9Œ ûQ!àºæŸ7;Äü®dËœ­:FëÙ­V‰‡UŠ¿¿ô³”*ëÎÌA¼kÌsámý7áKêT‹´á8&f(k#ÀVèûäLü¢¬œÝúzÑ=îËñ8Eä‘­VÑ_ÍèØÖ·c$ !Nwß”ó ÿü;Ö?¢bMwmßT#ÅJg¬*²4E–ˆŠK'‡ö€„)%„ÊyÛ†Õ±?ÎÚõiûÔYOZ·^Ù£@ïž|™ŸM;‚Ã,tþ0n°Ž â7Žˆu\‰5Uôç£l“ý6é;¯9÷—ó7|é© ¹Õ0Ê»5r}·h„Á)”·üã·Ò§oº$éztÞ<—vŒíVuÕ¸æˆL0ÔS©¯0®Âh£Ž †9¦À ¨­²D¥˜7ï•÷5ßâóг²=Ú¼„8 E^!ª8# †øíIfZà&wµO™´iÃÁ¥ˆÌ`¿ö'¸#w{|ÝΣÀ{­oþÚÖ¨Þ\“.7)˜º­yfñ¬Š®¹ÇAdîL ©/[PZG•óóëû{wºízNËîõ½LjŒÆ§"ÍÅŒa³Ùƒ,Ðl§8ž`ÞÅà6§ØL²¯B¼IáÍ\†6tß©˜˜ÑòÖx3>OºPguVNÇ4é’ß÷åñÏ=-¯å}‹¹Ž.‚BYù,S5ÜÂÉ硪ÁÇ;|®X36ùœpÇ“»ÙöÚyBWìÙ¼´(cö6•/Œ¡ßÙؼ «´òc“$%&»QéZþçSo¿Éo%hÏÇXnÇ4{“é'ñçÔì²áž*¤Uã¶ûº2¥hŒU¸kQþ©ðîÅ WϖΓ ]”šÐÏ>Ä*:3NÓn0XÃ]œÒñXaë£P2Ü¿~ÿâ¬ØÍð¶™ù£AúÞwFÛñV7³VºìM=à+„çŽê¯ÃïqÔ­nù°žvëÎÒT—Üô8Á™ê¼Æ12ÜXç-¬¤í5Hjqu"ïSt½ò A™Ž§­¹ÿÏ5çûK jß謠黬æQ •g@ˆqVoº± !ô]N .F3¨âN/Iû¥Ž”Ïè'7 eÿçšWWü˜–?×\åŽO/Yû.ÚMŠ1ËÒŸI;ò¤ÿç5zùËvJp¬s´´üSᛟ¨¹™D\”^ŠØ÷Ùäªu€W¦Í»l­_î(fÞ÷83}+¥{Û²C”/›¢n>Kê&¹’% '5=t6][g¼ÊEIbwº"JRU–£ I^dŠ ‚~ª•„®Ü¸î!†!N‘i6*ïÛ‹†z‰$œl>öW´ÒÚèÓàZ'eIÙkP#å­¬1øìfÑ¢ÇÜ:lD¤Æ»5O«¤ !AõX§û×x˯¬VâÑKi¢Y f@Ì’ÌcÄ:Øi ×ÊdBÞRzýÝ^ +Q˜F×ýTéúU÷+Á—I­4\$§˜MÔ0d{ljÊ{n•ÍoA –®…©UùÆ•×k5}=¦¶£¨¥Ko©)–V-̷Δý £«Ü—˜‡ð¸«oǼõUźLiý¶Uyc*Omreéð]T}:–ý\ÓbÙgp’7ÀrÙâölS6§—ž×çïÇ´þR`7ý¨Åü­ö·™ÌügßijHˆÐÂRT eÑ ýWRo™èæŒ]÷ÌëŸÅÎHvá;Yyvþ*-¿«Räçø:£!£)Ǹ‡0„râ/jlú¥9sã¯9‚èà­U’©ÁQ‘Ã>ŽîŸÕFÙ¯ö ©zN”ã:`)’­)°ÐdëÒ*»ä#I/yP*A` ? 8¹E{ò·Lí­ä9Ïí¾µÙÇGÁE?}Õ,gû®‚p›ÿdó·zЂ ÷2Ÿf+&òe* ÍnÞCÀ,"oF]0:±a„û𵣤b 1L< Íb5¯.Cƒ•I 5Š´ô@š&)ÃG›\‹¦0¯ €¢~”‰Ìhˆ“š„ù¾´È &I®Öaµ¡¥·=þè¢ÝȪ¬ÍÌmèϽ+aʧ†y~ªÿz²bž¦2„Š3àÙ¬¥(ÉÒºÊjÓåvôG2M^öDI#ö2ˆ¯ºŠBoNï2gáVT—úxA{ÖA·#¹ÖÐ’µ#Eë·ÝÆk¾­ÑŠ4æ&4„?yiŠ(~$8¦¥Â'X¬{ûeuÍáìW-~›æ76ŧ5R W­*8yPX-×\ C?[ú·ÛôrÓbæº#Ö¬™#º2ÚSbÿ³yK¨ó 4Өȭ–C¯ õTAƒHŠ̃4Ë+ëFÊÚ­ÏûÔʼn§Ž,ÍÇnΣa+M‡ÉfhhÁ˜‰é×ë÷Ó5º ~~#?›YÝFcÞmöÅ]Ô¼4FY‡*ëq½¼°"i‡«4ºÖºƒSÝCàöë<8‚4…‘èuº.‚ H¸úzEt¤®à"4üð4Cƒ!ÈN‡Dp¤(UõŠáJÀÞF5ÓèÿGo>†vR€[ã Ùt‘WF€q\Xÿ©Ô SP·Ö7ŽÅ2ò ÀnuI³[VäŠ\HEëó…Ä:HÁÝþw¹úþ­g:Oþ9\óäÓ̪ùáTäpͰ`,ß×|8Õ£oœ&îû8EÝrC0Ùe(ÏÁœÍSL®„fcð˳1©Eߎ˜ÀªÏìè`ðJââýL¦rpKï9]Í%Ó·r£Ù‰ Ë£û}q zÈút½Ê¯À­T*ˆÍ3fðXáÓö·××Cýú©²½µ ÷s}¿—ÍuÛ±šëöºšî!Œ©±±Ü0#ï©|òS Ç`¬ñ;WµŸB½ í˜ö&úRQžá|ƒŠâ@É›[Ž8ccBäðå°2¯"^ÑAµwíP!_7 Ýûšl‡®´”{¸”Oði‡ êBýê­¿o̧¼i†1ÜÊ-P!?kW×Aç©TõTêÕù½«‡ ›M×¼Ý{¡–ý£{-£êæs¡öügý¿ò¦XMNI¹)Q·¢ð{K/‰Dx_óhU0K„ïóf‡»™¨ØþõÜL–å˜V¾}ã"lF²ÀØAéÝ/ŒÆõ`1RÆË#½)p¹ÎE3ýå›ÎP¦Ú¼ù¼ŽMZB±-h&õX{– ˜@-´]”j]¸¯u7‡*! ^ Œ!ÑæìÛaÛGôàÁ¸±3™ð·æO±ïMÈld‹£‡öÀã±¼ P6…Ø,À<#Ö¨±ŸÓ™^~›ûèfß ½z‹îÂ{P!6äépti;!wÜúêÿÝÍ_€á$Ýfuk“& ÖžU p䋾JøW· D>û = ,0M?ô™ºAdü'˜yuó#Íú^×I@§ªFé4¾§ÕË¡8Í!:óÅtnƒ–¼MΦáúÄÑ¡4frï›òÂ|Tœ’q}ùß(üQau{©ºW#®^êbPáȸ¯žìØ)”¹~ÌëI/TÿÖZ[¢`frM‡I`ÚTéû,muÇ !)}(‡eˆ-.ª{ )]ïº6q›QèDªNé?Ì&å¨cýPÂ{€Gd¾ªjøÎ*Ù™]-íA;ŽEÖõ©ÚèI…/ÁkÌ0‘‹Fç²@á…ÑÚõŒ¯Ø×ÚcæÖL½a§»¾C»¬h( I´Qò’%:M=Ù¢ÄpŠ¥êéb@åÑÿÂ9˜…l]&«{Œ{~Ñ5g oD?‡<ïUàu¸0ªjW€ HýÌqkò#áƒQ_%Ÿy¯wäÍQ]u^lœ•cônüí¦È¦s{,¶¾Ru4$jÌóòín¨øRÙü\\¹ó׌꼮UÀD¼+…Ce¾ŠÌ6ׇڃý΂K!Ó8Ø<ª§åxëî±èóèbï„<ÒÅÄ–½ÿù­‹ mßTÂá’˘ru†*se;Ϊ•¦pÜ·j©Çq»ï³kúùØg´¯§z=!ê)îeƕDŽ|£ºÍ¼?¢Ï}Pïp߆>ÒÀgiø~lì ÀÜ2T 'Úd3…ýÑÎüe͵~ª Y%¹RßN}gw­†II··©V © ,Ò⊛¹ƒ}˜r±Wñ™.B9µêzF¯°²êµ^ Ú¨(þ.76hûzñcC W²M÷£ÃL¥íÊÏŸEåVÄ_"ćÉ3£R¬ªõSÀeYÊ’õV¹.ÿìúkås³-®VÓçJ~ iåô=*w»úßmÈTmzÍÜÂToªYïYÈ™Úu†áP@e;Ôe[]³ášº}PÍMCZEƒnuç·kÚ.χNÐ÷¯¥þýÚTʽþúºcîþx"®Ë$ö©CwÔ…Õ¯>¿U ÞC?üqw #‡î©£jßNJ•kM=ª¶ñ êZ_—–Hî¼SZÁ¸å¡ì¶Eˆö':aƒŠÞÖ›Ê m×Șu`- h@ExJª˜Á¢ÆÊ¼Ãwº÷NÅ +ÞàfùÈ»BîaúÙ©]˜÷ñ€þj“œ&WdP j&Fú\Ï.,NE¾ M…]nÚËfæŽÈ D'¯*9†E—}\õùð Y¢ Ïσ=]¢ï£Üº›’žªï¾¾|ª·g4Ã5G|!ÉÛú¦H˜• Q¦DŸCeðÓA©m&›ºAµ²Klª߯չý×knuáú:<^£®ÚsiÓðë¯#Œë¯§ÊòiBÖož˜m¢{®ôþý ¬ïÐÏ_'QfBq”7È]ŸÇúÒ™<Ø4þûé›ñë¯_ÎFkAa÷¾º&Ü__"’ÀúºŸŸ¿^‹{YP€Ä£*ô§¥ñã‰Ù0N´ãþÚ‡~~=îqk‡Œ¿_Í à¾DØV0·U†LºiUžWNÕY ìÖì|úÐ'Õ8V”…úÈÿGf7¿åi>Lçðù­~E¥6˜UÖ­îÍô_MÑ·-?Ùä?d~õ›{o2õ Ó®ùaž ŠÉUézèmhÍ*²€Ã@f”`¹ºTS˜—œ+~V=ì]œ6YÔ6+Ë1ÏKc’vQœç»ÊÅucÅ êÜ8tÞðÜ:ôú­Z!ã¯ûC ³we¦:>ŒeÞ9PÀ:K±@dSæJç~é·ï‡*?\W,Žéæ>¿³ûõ°ÓõuNF7#‹<†\Q?ªDœ­Éåu7Ë Q ÁD½›ô#(Cà“<öÒŠÏñW c²V¤G>¨S¢ŠT—ãW3ø«Úˆ3£§Ñ‡ÊV»bŽ®Í´’Q¬öàŠ /h¥2o9äTãâÒ·}œ^ ÖÞY6YÃcß úÕz)ºèg¹æ8ú),›ZsP§ ]Ãj’Á¹M‘¾F·fÍQ×:R: ŠM†.ã—aõÕß/ßϱé·ÇÒWÓópU·|Iê÷}‚ëÈ ô±ù²TeÕP%U _{›Ô«:¼¨©3†E?2=¾¾?¨ÇW'å—%$ÍdÌ-¥qµóö5wÃý57ŒbFõ©lžÛüú OIÿϮ}æ© Ëïvû­€¡B7…Œ5Ì»I™MzûüÆÇ+R–\W&—L­pŠ¥ Ua‚Ô Ï 0e×jlSúôÞD· ó†¨Çû¦[ª ZÛ"Ñ#§~¾^% 3zÞ*ëÉÌ–Kí:Ê·ty—Û^&vëYâqþÚ¡úù‰jŽD#µ̾½æMãMó&-,3ØÄ^©½*zuñŠÍzÕä†V?ofm ?úªƒb“·ù2µjÒãöïïÕÃ8 S¹W'£ ›ÖìV Q1®È­hP!¿ûªß_›7W u×À¤æNJG÷+Ÿq×àuÕF­j-ú13}ËMD2m킞@à*ËÕnø…Ì¢fÓœ.ôʼÉ@t^iRý…˜ŠÆóŠeÙI4gÝØ-&R¦²È 8"ca³ô˜Š´pêéË6k̪—õ&’Cw^ó¦7cñ “¯c6Ðf¸äs%çÉšü·÷•¢­ÃÀ¾&àD@„ˆDÏ)&O#3³sENsoðÁ i}3[Ú}ƒßPÒº4—')¸Vt‹dd–ª̩<Ð}$\)b\S=“¨'­ˆˆ…ªHãÂÝc^£þµKtÇ9yÛ]ïo{Ì­[Ÿ›¢Ôë9÷áþœÛzþ~M«».ϺãŸj'?Rç»âçϲÍKÿ겎:¼ »Ìô–ѽÆytû}óŽr^ê¹Ô·‡)n°5S»|=§aÿ‹Q©CwPï·Ï?þa†‡Ë8a–_ÿ÷oSþÛw?â}¶†W¨ýëŸwÂÈq@)zàö}Š^­Q¹7ê´«š« \Š[ÓIý¨-Aµí•ø wŸíTµ×á%|cù4Š:—röQ)W1æ˜tþ¯*ä+UW¡D”w¨ËÐ(kæuÓvÛŒj ÇÍîÝdê’5̳šê¿EB7RÑU÷‘ì‚.vC:%ù?~ʲ*Ô«)£ åY ŵ€ZZ¤•¡‹Šñr;o–(×`ÊWƒ àÈQÒQôm^ *»T¤#owYž#žJayàCÏËÐðEë[þî­m¹¬¿5¨2–ÚÛëðýö׿þú6‰F]ï×÷k_‡ñ Q‘ëëûnvÓ÷‡Zs?xžk¶åÔ“·‘‘ ìßMÒ‰FŤã´róx7Øö§Ûä*5',ÄØê<\ˆ‰7÷¼?FÊò¼+´* šè„3ÁtÓƒ¨2fÁ©×¼TŒVfqs¡»Çr®7Ázõäö<kj¦áPü5;‚- …z Å?ÕAÄS(*ã±èyë[ªÔCÁ¹ÊZ‚ÝŒª§€»4¡…Xɉ޻æKÎNl0í<°°ïË?~ú±ÖÉã%°`h¯%¦kÎTÖò÷Üš”n` 6x#Ô‡ >g?,/}´_ßåíýŸóöüB3¿Ÿ± ÷×ÔúãksƒRz[¯_kß« —2p>Êkz½VMvJydEØô*¡öï*KôƼGÓ †ÎÏçÜlJ nùõï·¯G¨qÆýëµø Ä„þÄãUòfÀ¹óÒ@…z¶€¤mycÿÁ&Z“ǰL¹•£5 ³Ù쪵$Êx bû¸æ‹rœ \òg‰Ë2œÝšzð· *Z}p§äèàpðêê[vUæniò÷ú>G8Ô0¬»þ„zõšZ7©yD„³sD<Ï<íA/E“Õ¶Á XƒëÁ*èòG „NeQqÅ%«jP«%GãL°s®Ln*ÆëƤèP¹G¢¦ /úê³0gªœÉ–nA'SÑejù®l|‡ŽiHç­FïªNq|vM•ª9¾ßÕ½©b]6úÊõž†éà­èÊ”õiÄœ7FTÝ×)"ØÌ}ý€®Þõ{óqVþý:»¾ºÚ¦õæŽæS´è-[õåW5ðƒ+ÂF\Fô‰zïv'cÞx(z,=Ërîåþáõxý‚åôÙö®ò®ÛŒõÙRÏ¥êFd-ôãØ üÁ`\_„šQíaÉÓgžoè¿õLŒ‡ÕëCèÏV˜¥µÕ€ý»‹ž‰~¹ã®Úø[¼¾ýÀPo謕d1ÌL¤JKÔ;õÞÛû¤>jÅÖ"àLkŒ‡y6¹O,ù>~ê€6yeìÊüãSÅ(,¨,mÕ+²Ãq•a„º³·³îÀüxnøØ¸e–0?¿ö@s€pÜ}tó}g]rð¶ö‰ªåj|¾ÒWËÔã¡V_~&·T­]Ý®Yøü›Ê#_•£Êp7š†¨H¿ Ê¨Ž‚n<¾^we?ƒÛþ©2rÛô4TÊíÁó­YL(µ(§RΗÃýû¹øîßß&ÏŠ>+gëe#z>wÚòÇ:üZ:õw°pÓ´è=3ñ1ç,ƒ²«˜SQxØPµ…p•v58V¿-¹×å©Ó\?A¾Î·`°U¶ŸdÃrG·½¾ÀÒ1N }–d—k_é+&íÌuò&cÒZXªÎ=†ŽFغSÄ ›×7ÏUQó©7+ž¾NT+C£F6Œ¬×I>–ì#Óoàœ5ªø‹®hèF•â-¢ëYeÂÑ5ÃFoê y%ª|ëš_–£u¥^HQLøo—§Ÿé0ë!­*o•ÙÐ+K¤©JþÏ—^]c^¸âÚ-]ÚEŸí \>^Oúø¦?-##ÒQþˆlÛ÷sÕ?=l-¡€uD”¸£WÃý1X› L  …<;Rn²a[¸ÖÇëP Ñ×Ýìþû¶0˜4V¬#­õ!ïGÄÐo¸ 0Ó]O=ÌÂ!¼TãLÜ77®cUA¶(û( §%‹Ð›‡:þ¢7¥­yCd Ÿ%Õà•Û6=Åç÷ñyCg½UÚð…²nÝ F‡`j³A´ Ìûô¦ç!ÐA:Ô`(‚:Û¶ÔËÎåÕ0Ácg19æ¨Áø¡ëÝCM¯ðbŸ_!ì:>÷/•îÇ« hvÞ6I¦C©ÃÁ7Ïu¸Õ‡h9ÑOxÕ¡gØ“~È_®õl"l!‰g{q7Ðq-Ïß½6œd°ÜªyòËÇM·ûV¸ügBq•çµ+?M?¬ñømk8Ñ`82à¶å×ãP-0*®m·íþ˜•yWõæ [”ŽaÄÏ&ît}ß}N•êò¤„—æ±äT½üPóP9sÞv(öˆ^O¤ÐOÔfZŒÔ€4ðÑ÷T-šh÷’¬Nœ TòJE]›Ý6§zÛ\ƒ_*ƒ»¶ v¿\só Q›ºÛ?”ì|tZUÐë©&ùZ*¦Þê¹…åij {Ø")l#mcØaMª#§/ú`®æRÕ[ÿ0s—ze[æ}÷ÉC÷sŸÕÀ†zÄj³½\u›Öƒ*º~Tãá«v ]ÙyÕ¦ý»UÅ—¢~–B Kò[¶ýõ×c]§ÚÈí’êæ1w×1š]ïáE›!ŠwjôÛ9IŽ˜bÅžuö&þjưý>®[ûº¸ó|cC…ï:×ÞÕzMC‘'×¼Ï3ìZ,k µ“žºªl•Q½ ÈÀu{¼ÐN™èè™#6É­¤'W"2eI#ôéP¤…¸Ÿÿú¿^ô¼«Ù©ƒ—)—¬UW8Ãh3Ê€¤¥²´Ëz=¿zTã——õ­{>¢—.ì?ë¯ùY§ãûk7 Ägöƒ¥Ùi³Öéx ªÁ@‰úµŸY<00AÍX¸eDµ(ƒÅ½ÜcܧÙW^÷»Û)ë' ÈÃäÍ´F-)£f˜¨÷| Ç) ¨®Aï2¨5‡… Ðçœ?Ö±tFRuX†¶DGÄÙöÀã€ÝC§°IÇè÷æõT²F÷øŒb§Šð|ßà¯Ôê§á‹ÁwÒC ¾æéÕe«*ú¹uãZG×—ª¾duù3ZéšÜ«´õ±ŒtQcÓ UÁÝ~$qæ±èo%Sá Ý™’±ZHóg¢Â1"õ¨Æ65OÆa9ö±Ý#iV<-DAWÛÚšŸAtËÒšf#ÂÚhf×]¨MUñÝÒªÎJץʹ]‡i9©K³mHô>—wVNÖÒåß×|Ž×âè¢x¢ìÒ ê†SDp)ªìÓ|¿ÏÓ}Œ –X%÷s#+ÊøqÛ©D%S‡°ú4íô­ê¤;‡n.âÓh~‚ƒt£ÚaF>w.»Õ木òJ?\‘da?¾<1Xe'nRýªpzõTÕÛúÑäêuYa·:ô&Je|ŸÈåØ#X¾B¾²w?Þ”Š>kÏà‘‡Âõ®y¼íç5K.pÇQ/5qî•§¶eÊRµÛ؇᡾XqsìÖ@!祋®/‹†‚ ÑÆTRÚf*2å¿q}½¾¾0˜'›é©¼¤ÐiœvðÆQǦp£^B/­`q¸%嚢*•ó(xF©àhYW†ûÖ7á±NˆVLs;?ïŠZ»±'/| »d†OÀ¯ô’ ª£ª…ÐÒxr]‹Ÿ¹* *º(¿ë©¢>Ôô™Pça>òˆ„E?—?÷Ú.¹™=ÇÓ}ÕTZY„þóoé7=¾¥C'g.3ÛÓþÞÏ×Ñ̺ؔß÷{D½\ß Sκº²(ö¦¶¼/@7bƒ3FÝNﻩ‡¼œÕÖÈèšÍ|$jçz=%"•/§[ CMùdLˆpÎAé¹ÒšFéš=Äžp÷¼ô÷ÃæÖì¤3\UŽ©€ÁúXº>Ëc›ªË%Ë’ÜÊ5Õ8µåX5ó:ﳊ° #ÈcÏÀ„vÖ¹½ÝEwßR°¾”,-Õ>-”4ÌÁ4ô~y,^/T¡l¨’Tý:^S_FÉXØ%³›*™æÌ÷7€§-&½·æä—î¦Ê§Wô—¤gt~ {½™øaz\Jù_»™¨©wÚ¾=¾ õÆTü8×njÀi¼¨°¡Öy *vŽZܳšWýðŸUmÒÁWÍé^¢þ:¨07ê*G€i¾ÕîVpìb1u.(¡›!kk Dv5${C}GKä¦En™ëùiófÌx´¯ *@áCÕGÚª†¢TìÂRïm#Û™è*nõª¬×"|¾n†Ñ)ýd<*¬1<~×ÇÐm½ÏÎhÐu­ÖuÐ×A2|¸fʧ,ÐØïdÃiìÜWˆ™A«RióÌ^DÉxbÂ-m·cõÅþõœ½ Säüu(˜ÔiZ¨^Ìë¡SSÀ^§6ÿqõ¢e ÎW™Ýëm>îæL»8ÛJ¸?†×§Ø÷bhã#ÿ¹öhóÚò›Õ(t‰êý}†ÈLI­"LùnÚ_Ï#úÈßfô¶„Uƒg»M gQú ÐM­Ê ‡RÃ@ ¥ì œ+Kôt ³¯+zÛ†g­¯Y¤—×›®û•ñ`Cߦm“e= è+üžÕž³Š\U¡*ÿ䳚(O>NÏ]•ŠúWóq ¹XÇcÇ`î{ºkìõ>ÒÔ8/êP·iU‰mÜ%)RÅ×¢ï‹÷¢@pìX¹‘‚'j †´¨ ÇÖ&Ë-k'»Ê‹Ð´œ®Ð\»‡ÚŽ ÙoLvÉ5EöÐàªZ+7µøX×6ª+•%C~ëŸmÇϯ|ߨ°©¢á0ŠÌºnº!9nÔ¨™ºæÌziа˜(\4ÍoÞy“Š|èq<ޏr³¥²þÔ:™áº~˜ýkG¯8Z÷øZ=mzQôé©ò<ö…뢟ç0ÝßDÅ=DŒÑ!®éNª`ùÛt]‡¨ßÜQ¦Ñ<59þgÎÄ£ mj5;U{×2rÓ>ðEÂá·­MKŽ‹tìr>PôoÌ×¶cj¨ÎçÍÔcõs ˆe7º(Y£¨ƒI³™=eYÆ DymœÕ7/am‘iïÔœ"½ZÌF¯%»$%r(Q ÓDmü¿X[!°g¤½fù~MÝðV_™ýöÚÚJÕŸiÆØ(ôxÞÇÎŒ¸`þr´Ò4ÃÈ­¹åQÿží|eÄØ®H¯—‹NŒ­9ÕÖ?¢*Ó2$»ç¨î²ÍïkÇx‹à‰“3›´7ˆjK»T!=ÿß×ô"“¤´k~7,+§àSð"fð§”Vê‹E°í­»ÜÉÛk”%„2s1zvYa?â»8»¡à†6,zM ZJ ¸HÛ4-uuÜôzm»Ó·V@¦GɯܩôÛ²&a^«{¦G„²:Z'E1½Öø©@{2!:îË©—ÀókÊtxôyÌ2»Ün:Dн}«þa›<Íåç5oR¸Hå[N ,R·tí4fÕ¦úþ"¥Þp͈ ‡û¼qã÷…Ý¢þ¾ûž×'bß¶ÀÚÇnæ‡Ó‘Mò ,©W¡â¡cš „ÂQ¡Â¤«®úÄzNUŽ×]Ö˜V·±bïÎDïçnLäiµY€‚+õ+ÎLª·hvCˆ8QC‹Aõ—ȳ×+ŽkþÒO¿þùØQÿzdêŸy :­Ì;´áBè_ŒÌîËéŒhÎx{lÖ9i "Y©îæ?ß™’ˆ™.èÕ—jlàCü¼•é<"_SêyXϺé€ýªk®Ž­‡ø‹äD ˜óf *”æ¾_Æõ«o¡þo@v¥)ͤ[î÷€ûS;›”{¼&WƒªÑ ŽIÝäuúnT0P6|éjŠN#;a§4Eçk´»ë"?ù¨:|eÎÇ@uQ+ÊÊå{hÜ~Å ’ëÛÐ…{r+1·ý±¼c Pºê$ïT7†x+*g œ"+±“ax_?o·kᣎï<|¿‡iÿ“xªˆ^Ç ¹÷µ¾Ÿ¾fﶘuœîÈF€4Î/õÖaÿU´£‰ú :œŽ#¹²µFF#چϚmøk#ÕÝ܆Ѓ!KÁ4BÕ­=ö#Yƒ’^Œm˜t1aD#Ílʘ"¬÷¯Cæ8¦&O®?u)ôÎÅ£ˆ_4Âö¾ˆ ×nb1é)š´ö:@Û–m² 6'õéÒ •ª…¢T¶Nnêùu„ÓËök7&\[Xq ¾"¯«hÆSëÚ­J£MV©ëýáHÛ¨Ç+ªfë »Ûƒ_í«±kžÇï¿Ç×kýÒC±‡6rÖGä~kJXh©Dpå? ön.!sîTîWy{ûG“¹êC%›7 Þw´ï)R,K›v°Î¥MÙñ¦Œù4ªÈ(Ï>m-jˆfðO볈9[4™ý´b̺>_ÐZcTTšíÒRŽþ“ªô¡E}°¥ «µeûn{K õ¯§’žþ2FÏ0|‡žéQh‹30LjÞØzšd/’¾£2Ñ\Æ*įåt Nakö ×|^‡Ýí«î¶Aw…ü…½wðSç¶qü2Cúw޶4ZQ‡(˜ë'_v£Šq›K=×¼‰võ:êü3©¦ïú´ØwNAWÞ$bÌ;u^_þÊ”â«La%3$¨"ÇÎ|Î1I¾„‡Î±¾0)Bx)nÜ¢XçvÛó>Ã:¹›þ#2?|3S²§×Ï:E¬­pŽ¥.¥Â¬«ôrC—o±í¥¾Eˆ•‘1Šþ¾í›Ö5 ×?Ù÷6è/‚¡‚‚JUm—(4E×\шÿU uÖëÿÌW¬k”L†C÷¼¡u?;ÌaÊ,«¯;:¦h®¸&åUé`jÒaÔWƒeæ%Q£¢5WW|$ÊKƒ©‚ n™Ï2öôͯð"±c`4¤PiÎ401œ×qé‡;N,ëÜ ¡èÃà^ BåR-jíRõEéý¦.o_'T¯<“àQü|µÅcþš¿þz>~ÿó5Ïw©SsðÛï쪟³*«¥)z_êŸõ” ŸkNìsÍE9)ËÛˇ^Lþ÷¤ù3R xÃD„T¯·û{ öxœZ¯áe8šç¯ýtµOÉCŒð%,>,ÜÜM‹AÇ(fû—žWï'o^!¨9õØô ÚË Îb욃â˜^G{¢SyµÚþÙz%ì%nd5Î]íS==w°¯»?VÃM¶Ôº›ðm°u÷öx/Ô¨¨‘7üs^ÀûkRÍÈÒç®oÒ[Ý™H~:çBÍøŒ_¿ÿ¹œ¼»å†ýñžËžl´»>Òþ8Ø«WØÈ°J€KaªU‡ä)f˜³Ç‡!ÕÃÅK­DŠÏ¹e)oͰ(øª5ÏðdnФôæ¶ò÷E ü—:LU1T—fCvÀù.ºÛ£·BZßn¬?Ñ["Uc4ÞßcŸÞhÎìªH¦l®P“$`ÙQcÄ¡7~«¦¦SÛ3©ž:^\8gs^–êÕËꢖÚ=U¾z8}µZn>Vý塼¡dø@IÜŽÅ#Ðò|îÓav’ÛCïDùr ŸISÝ*U“*)«2Øýµ¦/þ¨&™ÅÐ!RgtR™*UýÚ›–Ð2çbÌÔJ ¡.ˆÄ M{11{TÅÐáz¼Å‹Ì4²íÁ‡©¢Ü'½Õˆ·­1N kB¥Wi‚zn¾ƒ\/NE¶cÔ0\·ê6¼í!ÞºãÛýõ\¡“Mj ¶bgƒwµ7S§¿ ÊUÊÙ•^Zg•eQ€içïÈî"KÍ&|v újÂ%‘!84Ì7•ªCXUÜcG瀴[YíqÚìû QY§öÉä½ôTûÈ<ÉUçY’ÕF¬«´Ê”x&]$ƒÔ‡Ùœ0¦àMhlj’¢Hûæ#£–6õ{„ H¦J®É¥à( ÓÆ€õØ&„kH0щÝ;B¯ê¤NG´b@fªÍÈ®8ƒ«UÌêc4×ÄEX “¼úÌjo^Ô@Ôöi¦NR5°ÿŠÙm{ “‚¬.yöx}Eb²Ú[¬›A¶-Ä}œcÄŸ¶³Œ…Ò;Å÷]Ǫ3ÖùΪ6Z?šM¹Ø§¨ì¶Ï×Þ¦5E_†>¾n^ßê¢;ÕÑ0~/WW#—[áN—ƒ¾£ØÆ·ÏÖ¦¢ ¯KvëÛKù2™Fš˜¦.?oºw:xªé1BaëR•eÊ{õn²Œ5sÈnió¸¿6š %g¼¥—ýu¨,VÇ2%7%p[¨Q „ñœÀ+oÚaÕ£BΙ"xî²Ë'˜Ì™kOˆ†d¹W‰ [¦n=ÖèÖ`àbjûz ëøýħf püØN¨«ßÈÓkÀÊ —ã>»uéæ@‰f3$jVÇú>FUõûÆ÷ôÈßñ@zΧ`ÿ~2Iÿýcè×ÿ7‚ÿÛ¥Ó\›üú ¡=fÝš~3nØtÃ=4°ïêv<첪Xc¼Øg˜9Ö@ÝÄbÕ#cg3ÖgÌ:­ÿÕë8>¶„;dh´(zÀKèºE˜‚š€Á]?¡æë! Œ ãœê}öËâ–'`e¢ÇhßE×|Ü–EÜ€9¼ÃžtPT@XxÛ•Ö †Nw¨ Þ0™¸@¹Á›w¼˜µµ_zßðxÓùÉ6¦3cD5![·mlÒº¸¶Ý­0os5SIÜÂ7hbVJ/é5ïléý¬âòiÿ“K6g£”›‡ÆMTw¬–«¦JtªþD;vèXyaKbåù6+Ô²·M´V¤óG£maä©Ùnëö=Mèÿ 5ƒýÎÊrYˆè½s†k¡‰÷]P;¨Û¥¢»¬ñ­Aq{}àø¤£k|×·OßÙ͸ŽÙ·Þ¯¿þz„~{>B]d)NyªCzføú1j›Ä rZ£ªÐ®1Kiµ~ƒî|ãA«5¹Ö׋ê˜N 'têò¢_ôÆDjL^";t%†HGV,K‹Ž–5˜T64øUW}œ_ÿþË$ƒðöƒ1UÜ„ ¯ü3©{,öØn/.¥ª¼ÄzhÝu’)ªtºõžM5½žNÉT9“ï/Àã:r;ƒ‡ …Ücü ƲÛC#ËzåîNÏÑÊ/saÂκàÞîB™G2Ô˜Œ:Ù‚ dÈfó/ßgòn{€WÞ©ÇõڹƵ‰ûùÝõæâ† 냱À¾Ë±(Ms|‡e3v£ù»]›¹ÁúӾʂÙ%NËaåÊ ùP¶gøØÏIÜzîóX¼@ñ4ÙTpχ¨ãË:ø ð ™ÆKwݳô³—=dÑÛìšOvÍåvP©µCŸÕ®yèZo +LëÁ•;5ަ¨L³…œXz§u#"!HV±]c¥W”̉PY¢"O«4QÿFÀM6íà§Yúì³+?‰ ì°3š8½6ZFÀ ÜW¢ÃÁÜÄÂùlÛD³±y¶TT#7¿G«¥e¶¨ i t¸ZãöI¸±—Ég*$Êa=ý©Á·©^g*cEÝrqð‹þý ÚnÚŸ›·¹ÿéNlíéŸ?…óDCì¹æ˜¤ß0®ó²ñ¥Á¾è''Ÿ¶\øãqDGÖߪDÁi±ƒaùx^…P]rûª:äuž¨èÍl6:ˆ("—¬¶ítú*†j¼T1«.5éòíÕ‰l¥Ó×z7*œU¼ºá‹®±§Úؤ:§®V…äUÜâ ÂCpY©mGVêfŽX‡E'¥ÁÔ[àaèX…¦âý ®‚°¡&Œ<Ú\›/‚ò†RT-ôÊ]ìë›ó—¡ËPØEð0IÌÏ™ý]~»Ú½E}ùk;=~‘Ì£=]±x©SHiecZv”èµó‚Уíã5·ócZ}ëïáhòo†7‰¹~Qj`D‘§†”=Z”¶aÒ #òÞ£7g¡>»e:Î0 LÒtxõñø¡ÏEiTÒe؉ÞþÜ7ó_úÝÏ—ZiˆÈ6t¿/à@|s-™ñl{„5í6¹û]‘s[Œ‡mxmEççÅä7PQí‡íÁèAAZiÕ6Q,þåÄ ¿´®3¤‚kíô6Cÿ·nBš¼,B‹ôRÑ™O?MÎæGÜÖj==ZõRpÆÚˆƒhõ^!2•fhK5ØDz{?Ñ]éxèÁŒ§—hhš4WÑ^dj·Ôø´f¿¿É3/ÇëE/³¢˜k‚è!:¤ÏÕ0<ÊÊ~f\¹*êZ§¶ w³­ÓLHeÆ¢öE…152·ÜD”mÒmëåàÚ¢5üOÙä­Áî–¡)M,ÇÔd «u~Ø+GtÿÐçYo5L„GDÀ`d)*OV¦ËþõÏoÂÙþøúõëÅøôy3Xïê<6ó´{šÛ†~ÎÃÀÏúÑŠ„/?aÄQyÕ6ù0™Ôºëi6ÚHW¾E_zT¡zÐ+ÖuP¬×:BõÈÝTßÜÚ õuæ§ÕJËOsaÖ›ø~lËzÿþmúèëÐÞ¬~T[^¹¹+j¸-Wv=¦´„꤭ýP*m îR‹± ÝŽóBOlbÍ™u½ž‡ ûGoÎŒ¡Sí¬+î üU¸‘º2ÅêX%sv+éFÚ¨¤¬¦°™Æ B°õÌaR–U¾í½ú®ð6Ý÷•¦xZoâë7žž[ e³²ªM–Õ<°dšZ·ú¦™ÚzE„ŽºŸ(ÐDÂP–j¯êäDîÁy¥?®¸ êÂzüQ¼.Þ FWOkPZÓ—omovõ°ÍÝŒ#˜b…› Ù«$f0TêÌ #ÎxliÆ*¯(îg·äv+ ^czá§ã ­–9kT±ßm+“{¯âBV_Ð]¿•†ºv¶I†¦-8ÿñK34ªù“"² Ï B Ý\aʘŽ]™+™¨áG/ÍŠ«²½c~®Pü颇;r&ƒ1íDgµ2Ç×± ªLž1çRåxÓÅÐ{€-³ñ¢—ïG«ÂG6gq³Ç¦³ô Å%ž_ù‡ ì¡ô‘÷D1¿›ZÌ®[5Ýw4O;©o>FWä1{ýëŽLñW å´êùT›ê„«þ©>ëŽÜiÚ:„–zE¶¦5¤XÚ;éº`@–£7¢ž~ÚäÉG†©X„÷lÏ•X–q}~¿UpÈuÍ3²U5êTiÖ ãÀÛ'dA1—>ìš¶è4©+èµ².,Ë:Ä™'Èȸ ò¦›nQœrV‘ñ0s'fËdËsˆö˜3rœ:XP¨–0’ŒiGuó7é «ºÿ\óž\Ø@é‹_Qûåě闒Ýëûq<¶Ø­Á8£CÜãþz@ö}3„ÿÂpÒ$äCE)`5CzÓU놨ÙÕ`ù´ŒUk†3´Yl2'À¥rÄrC ¸ùn“¥OÅÍ\ÖÕóa¬žA†!íù^烥õªÙªÂM7<šÑÕ%¡1™u¦ö!cK³KÔ_Ü@ÏÜìFU¾2#¥(1Õ{œ>tü‡û›§:ÀT Þ†Ë¦Ój_ÓÛ XѤBW3O¯vJyKÝ1Ï3˜*¶…Ôï/Òò\°:<;š¦0]ý¼ ÆG5ãã(4`y|‹sRêž»UQ33ö"M’džU¶àš39èJØW-Äάʫy·¯a֊ò/6­XÔ`ßé( Ö:eˆX†ùXýx~㯭ǨýîÌ["ÀëåPAÁÈ»UøæAq|Åðzð¦/¯õf’X½ÇèDK£šÂßg¶­Ëw+‡¦!,‚‹H:_¡R’¾šHeY™º ŽgÓ'7 Vuý^TÅ?’´<¿á—À7:=»U¦ÎdŸlsg ñÊ4沼˳|c´lX½ýUÐ÷Ç÷#ÎÀØTÍÈR”"Î-=í²â"ÒѨÒžÞÌP½ÓRy¶®’BávÂOß‚^íТÇ0[À+Çí“_^¯—(˜|òkÂ[¦mn®9*,yB#^fêW`r™UµéœÓ³PZê{ÑÑ(´+‹ê‡s38š‚{ô =Ðîæ.Î΄mÑ’À©MvFc¦²/¡vS¼×5¿+°o™ûüZÿüðJÁwæ‘ôãã¤Æ'ïÍô,È%Õª¬Q¾^”zÔéÇý+î]ž_Q›æ8Ý­uÄáé2îÕCœúztœ—ÖÌ Ôa¾Û®IÒ£¿mô òcŠ[«R¼<°ÞFóJ ÆüZ¬‡*Háj"ô˜Tm(Pè³æN_hÌú€ˆä ÏZ§öé–}D`.]; ¦fh×°:<Ãø%Ç {/"TqláàŒ¼ê[Y}&êWÊÏ’ÞY'¦ÈR5Í~rª=;‰†YZ0YˆÉG¦Vûñ™G Ÿ}{íxšP>¡§ŽŸ>NëdÆà›g]›Üš®ÈËæØu÷mܧè< v0\Ò¦[U›‡U˜¿.Ãk]7c9DÁLW4.*ÊbÚ§&jȇ·‰’ù%íÂx†ãVÄ¡Î{Ü|Ö³ü±Þª‚…Í©a¬½a.uà|7<þúÚæò³òiÒAN¨“ÚWWï2P pÎd1‰Õ2Kƒ¥o½âÄ@„‹àæšèe†S=B_å9Lò©O <}]³Ñ8 ]t–îÚ!ß›&õPU×b¢%˜—ï­ƒmËÊ·ÏëôšþèT«—úJ*#3‡S˜ÂuéV+=­Ú‚À„ª_ãôÓ –2ëÎ]¯ƒ^X„ú n,8‡z]cèÔBcM%ì—ÝqÜ)–ǯû8?<3SÞÂÕ@\ò­¹Û/(à{º2É[Zw1Óf¶MÏÊ—¨MëDmê½8»/B9ô €2($&þ§•Ðý¡ìaP¿ éTÜ|éÚ)ø÷ˆw¥½Þߨ†#_4´³,;™DûÖâ-V7¾^w•‡ÇÓÂÊúˆëwF|Ç×_¿ïçÈ)èÁB¬‹e†‡¡ÛØyf$ ¡]U_[ºræ«XnU©Âß֧jƒ×A FŸa÷”»n>†iir+9l% 5U×¶‡ SuMªºKÿS ûØ8•®«j:ª'q1/»è¼Þ4ÖúÖp“ÀÙ߯½žo¦*«›ÕL= çæ,%—»ÜÒŒ_y†â3ŸNMš,fOÑ%GåþcRHBÅe§ŒZü[Œ+Î×Ñ\ƒJµªžKÊô–å{ýQÎM„Yw¥ê³ŸYplQ•O>“*)k7½3 ª€âôG›äJ€}¥º&tÛf¤½)ÝQD+¢Zÿ1©?Ô7Í£ ®æZ»Ž:ê³`}y¼ í¨ÑVÏéøºOaÿõ}oÚð‘q{¾ÌxÏ¢Qèýõû¹í÷ÉTù‹Û5SQ^c‹Öèެ<¢m]5$ÝœŠƒMgx>×f·Z™qòIê²ëÌLç®E¡*ÿ»2½ÊCUwãP&¥-ÂŒÔ4uÝ‚©©ª¨ ™ùGó_8Ïo°¿4)*I¦…2ôGô7Än§ë‹²)¯^ñA…"FÒKÔ>Ý—ËßPDŸe^›]jxŒ§• ^T(@6c§àºÌ-ç·ÿ4-ÏþP·¥t&ûM‘#jK+4í×Ѓª1Z±¢Ð\†Pɾ…x¶jiÖï_¿QnÚ£ÇåãyŽw¶?×|Š ¿H] ñˆT’S„`Œvô3žX¬W¦¦PÁŠG|5`šó·â¿ñTÓ‚&EâØë}²øÒ Ø_ºiÇ¢/ü hzÑ&Bµx_Lô6ˆùÀÙÒcR¾Öê‡U‰Ë´ .øfÈíΙ¿oŠÑ×PÓa@ wHußü¸/p—¹ÊNùX•YæEÎtJ£ª±f0®Æ~†•  ,µUbþb]kU.´¨5BƒOò‹®·\±s_»j à üË–VUf7ѪL4²4uv³Ù‚jçÎä:Ç|4Ôcäzýáã歷øøÚÌU)ôù-SÞ£ºMê\5£]™!AÕ̃5†«UÙç°QÐ+·#´a÷ïE¯ÉRð9zL ez-w®çóëÁM}ËׯçÜ3§ÚTpé+í N­uî×íŽzãý;ê;š÷ï]/FÇHÍ«ŠyZ&¥ôef¼·M]‰éß^_ÈŸ„±Ë.M‡.k«¬ ý54%ËA½Qz±6ëê”ccveÝ—E)íV÷EáË,rdÃ`E•žk᪲‡È­B톩ùdtLìÎ=Lмl¤¶p¿?çó`!Šqê¤ o䇾¬rG56 Ñ•Ëoªª/jŠÒ) óP¢Å ÔZ”‰®`“S[tå­Ôq]b˲èM«YoÙÿ'Uеl°Ž!îGÕíÜÿõý<Foqát¹¡_sR1»ó—Ç‚Â3{Æ\”èM°¹f¼Í]g?[$å ˜ â­öñ&¢E¥êÙÎ-ÜÈh3ד‡ÚN_Zý@Œ,V³i8XðëLæèÐj”èM«Õ\aTnp9Ñ6)Ú >Ü¿Uç+TÐVΚRœÂñëûKd:"XFŸÊa—¢âH‘ÏZçeè†àÈ…¤ß†˜…h®/^“’þ§¡„-­Ÿ¾Â8Žã®ëæ˜Tú­å #R3>a’Ž«´ZöUW²÷ñÃSÁ«3\¼Ó]s‹Ü"¤ ðÔƒ˜dnš(çz±å€Áê1ósè`-íråÖ6ýÌ\¹‘Ç¢ð3×¼²ª6uV«@­Ã¶ÿ~Љ÷dT0eÓ…g’£ÂÑØÖ­¡ýÍYUv;96ò*ßÆîÆ˜Œ=Éo½ø;žjÛäš6ßSMnºé!Rèý§že¥¸µ55i5í¡ê¶¯]Á€–µçØ éxÝVuÉŠuc1>¡q cqd*3w<–a\£ê̘ÂÜ¥ݨüöë÷ï߯¹%ĺö—ªI i8TCw…צõ »6UµŸ¶DÙ±)ê!Ëæ5+ú[‚Ô@×öPP¸Þô,Ú,TE?¨$Ë«®¨˜Ï”ÓÝ5Ö[­äÑÎH%*²ù¾N¶Ë6 §Ò ®…vÍõbXç)¦£Û_}‚½mô‰fš*$=Ok:\³À|u³ô:@I«òÆŒ¨•™ýâ0q­Ð l¹5NØzÿó®.øN}Á†fÝ^¿ŽÞÄÇLŽþ}Í]Üç™Ê D] €T1ô©P¾Uô×5§‘â×q‹-š-&±˜5"ýr44^žqÃÇß[Ç~ 5]s¶]æ¡ £NÓ8xE[og¾FÉÔ¦¸[ž÷!}o¬á©d°gTñ‹SÏ  J…bXisF:—Y[sï«N™|Uìó¶ª9=Ô1º¹WkYÔM£¶à9;0ë„iÌ$]o*Õ±PÖ»£“ ¾¶´M…ΑÆ2ƒúkSâý+KõE=ÜõÕˆ†-íÃ&Ô~UrÜaµ¾Ϊ…çL5ØhF@ÓÕ¡ÚÌwé­E3Ê6ž §ßÚ£íÝUy¡‚vð1ú²t}wKî¸Ñб¼dC{ùÉ8Ëß5ÐrL{Û…«Lý̲[š+-6‰êË&ÅOFÖ]âö kÂchhB*úwÌž_/užMÑç·NGòkîP˜õ÷‡‰®ÿ|íxëMˆÄ<Ÿûü´Ïc|a¥Âó¡l¾ª)ñú`^¿4Â}åØ@˜¢5 ËÞUƒºqUØÕ€nxbâq­à?öWÝ´´-’–Òb‹ÞœÝå³°J®6¸|TÑŒv–©:é *Ët]m°Ò¶N›Ó#]ÞÐhYÇúÍ"Th²öOÕ|&QŶìÙ/KbÅ®7Mê·ÉûšwÃèQ¤ÄN²2Ù7´(È{GW~cº˜¦%hPg¬œ“Qôv?³ûT«£™¸¿™D:g×|‹Æ¶»‰ùð~”EªXØLêétFZ÷Ã:zUl}9ê2 ëeË(e”èZt£‰Ó¼ŽÑÓÍ™ˆÁig¡p‹#!oƒ²J‚Õ,"ó«8šë5;œÎ¼G<12ÎõUzÏj2›aÂX¡â5ÇZÉžòCá´*‚é쨨7_txÌoFÎ o §™!.û@fz¨””y‚sü“‹£ÁŸ%í¨¦V 3ÕóxUÂ)^¿Ëì#Ôëa©¦3¿ª½1ûê6š±d—Ž®~¨œy)õhIGIbt©£“Û—”UöYÚšÞEÕÖIî|8!2ýwuŸxÂRU¢æö ꤙ¾ìÛõï)ºáWµçºñÏÄ©‘@RÇ9þÞüxNµ;~Ý]3~A5Yžÿþ?:°-u¯ µÏ‹~Ó¯Gpëoæº÷×CµWÝNû6÷ü ³Éˆ‘8–Éwýò×ÿiF&L«7ðB‘ä˜$¡~£SÚ»Ò ¨¦²Xñ²å”•Y«òÍSS§¢HQFf|Þ‹Ö@¯úy).FPÚúrA;µßy¯lË{gÚXg]…ô¦Bq}ü)Úßç?çÕµ†ÐÕ?J–UA•QÖ`žÜÞÔG°ýÌ“kÚŽfÎQÝ&[løÊ|ðmÐËøüÙÌÁ½Ð2ÕµÕ9úZn©Â³¤²ÀtZ„C ޤ´l4§L[@G‹X°csþŸGѸ«Ì‚ 5?êè´+dú.EV”ù1q qËñ¾ì˜]kÔ{´b‚°bcxS̲¢Ý}0?ìæÂÙç<­Ë´Ûåñ¥ßÒÛ8“Ó5oÓEWG55ɪRnØ”cuœ[à]ÈÚí;nŒ!ÞÁU]ÊsgÁÍ(W]×{¯þж9:Bf•¦v„[Âøé=b¹æ+Uö„„RÇ&¿µ!^Áeyܽ`šbÜŠ±Ò±/‚<ÜõN¬ÒÓÃ6F”3ŠrýÒêè£S›)LT Ðg‰äÔBonàACAð(Æsÿ>ÆÞ¤é›<;o‘UC}þòqígP*ÀTcÕ‹)>ä=Æ4U&<\QWå‰è«:»ê†äe5³ö¼¨¹êû ÊǺõcòQuØ#LKlÄ•êÄAýw í¡+i3³"Õeõ€º4ïÕÞ,ÇXæþ¡lí”3Çô¹ŠÑù¾áFÐÝ.I¥ú|zLnzýÚË}ëó÷7G;:íšÕôÕ­ñÛÀ­ {ð–4¡‹ÓYMñÛ<Ô?“Ænl©ŸÇtùîHqéìZ£ 1ol!xúéù½uD=ÀiÒhïëÅ©gªB¥³ßåМ×<}tlT¥U·¬nÜEUò?ê8³¡ŒMñäÉÞÊ8¨…˜9šo³LÝ5é1i~÷æ:Ç¡ZÍ(`AnU]Vþ`«¢Ø”Í;æ®N2½öù³lŠnßõ½Uz?kP·Ø”¡{Så·fÚ^´ì;Ë‹q²¦¹T}úÑMEgˆÍay®’¿Æ¶]U nl^¯¯}™û,2gÅ_˜èè›H½š¶q;ÕÇÏ¢ºüLTedx‰Â»áÈÁÛæÊFeÇHKa;p74ÞjÊÁàÛ—7‘ø\¨™áuƒò•‘á¼ÞvPÐ-oí:u:•Û†bÒÔèŒâB1ιî4g·nåõêÐé“ç—´ØÈšXŠ0ú;:®n&$!jkÃsaofòúÐE[TõÚ¬Ö¤d7("íÂèDÒxÍŠÉ6é¥Ùt«îí°}MIÒw•ч)OÍ)xQøÜô¡ÃœƒU†«>’®ùìÆ¹éNœúiÔ©è%-̪Ïí¿Ÿóã[Y˜áuÞ)Û¤§ð«€_ª:»\*Ó˜j"àG#ëæl㆙ý- UÙ*¯Çc5zðÃ|õŽÊ)Ü>”+®J¥é<¶ “¿téç0µ¡Lò’SÜ××´/ó¥›_ß ¿X{}ýûÿ~Ýço¥xw)\r¥Š j:o%f¯W 2ªª•,íV›íPÞ¿¡;g~뺺sP®PëñË‚ó]ý¾ÞÝã˜pÜÝ aláÅÚQЊ³]øûë©Zqêq‚¾åGB?v’ñàCÁr —¯ò±êž¦{¸*‚‹«AY¡Gà˜†iàš’g¥"ÐÄ¢‡J§ßÐ0&¨P©û¡Ò ¸ñÞðº-?µÕs7ž¿ÜÖ™LÛh ›žuÃCÍÕ˜YóÝRÿ9V·®ÉºâšV—|Ÿ¨µ¨ÏÄ)J_¯-ÇF‡5Ïæ©›_¯þ¯¯ïÃûÈøÃë˜) È{ÀÄÿ:ÆÎàÄa~€»æÑí°7÷µüôãâ«æV4ÖK¶n„W_ò>»ù6᪻D—ù#+)åVàíTÅ¢®S·mÊÄj:ÍeL)D5€ ÂyY¯_¿ýÔ[:ž_¿~?Öê¼à¯Pð† cñÛ0^w9›ê°n[úõP |ö(¡÷ä×\åúU~ ª¤:u[%(Ä R§ƒA™¢†663ljQSÐõ%_Æ©´®AgQm¦“6)x›bV™¨<%ºÐr‘×GžVïX_éõºÃÛ_ž¬ ݦ¢d„üsnw]퀟­³Ëê¹oÇ«5¢­ŠÑ€ê5‡™UP{vSYpõeZõªS^¸àv}iwW…½>s;¢hjþ&®¹‚x¿¦A9 …ùŽQœYÇšS3RyºrIé9Žºš]H€» e$E~Íð7æ-—z Szæ:kÕµfóUIÑdõñøëÊéãU:K¸3˜2´W¿ÊŸy§¤ãUƒ†úõ¨£ÙvÅ¥f¤*Ç"FV&w5ç€|x~fPeý5­§ûcTÂß¶ˆ€‡%¯MF\*Ûéb¢¸ æÉ+Ÿ•°³ª«.KÌlŽB8aß•^mʲIÓvvy£ ¢N h{‘ª›öq06My€Î›Ÿ©zTŽŠë“¤–›Ð*â‡ÛbRUõÂ’Åÿ_ßîºý¯gäŒÐ\˜ï‘‚k˨ð#¯s½å[ Ú@^m_éÛ¨4Ð×ÕqöQ.|1x‰îs@ ´Èóævñóü »u:žOò–þ»‡®M@EçMëõñÕH!nýúýµj§JñƒÞM窫Žë¡¦Hš¤AÌB'ÿSá9-Êhqn’ÁŠezf%D,\es6l#«k£îýì©¢“¢óK×\÷ÏO&QhÈÏÆØy5-uŽoÆR‹_TßîêeY®vj†Ôp9­ÑWÓ¡ˆª¥G׆åµÊü¾ÍûóXÛ¯¨5òúz<¿¾Áßèùe3ŽÈF'Àª«³¢¶Ž®¢”gzÔ;mCÛO©4CÖ‚ÛvØ|㡘 ü 0Jך•£»¯SÏ‚6cæèE£„:1@xTáÝ$þk3s£HGe-Ç1EU®ó8«8ê‡É&õQœ)¯½üïÇŒt¾*Ž"Ío Ó&›,S"矷.îGj(ÊuÄÒš ì|7Ão´¢&¦Ê¶€Ü×[Áã0s¦*ªKêuª‘r WcwIê4¹]êÑLö³F»‰Ïz<öï-0M—µCVÚ ^}yú,×åÄè!b¬·³A%lâ*ü6¢ÎúÏÂZ…îSG4Ò;Én;+F:÷çþ6ÓÜâLÙ†@ã8UÐT?#4Ý]¸?ŒN¤ÎÑ«4«4½qe¦Ô©¹½é­^Õ˜j‡2uRD#í.Qc¬&„]òwFÔ³œM¥o\JóËîé˜P–ÃÏ\µôÂÊÈäG0£hGÓ÷XÊÿÀgXT¤4K¼¢˜t>ö!j`-û°<è:^¶Ù--PžE´DW—ÑŒ€9Œ¡Qòͳ¾ÏK(.Í¡9ŒíôxªÂy¼ÔÍì÷©íÃ~ßÉó¶øtœ²ØÐáiå|=è5uõ]Å4)­ÿ¡ÿSqëTÅØ%/úžÒ³¶×ã$•«¨3_5“qqµ›ûŽÑ‰˜ßÜ—ƒeP &$¹Á®`¹ýØìª*œ=Ä46sõsïÔ"5"UVÕ“9äû“‰krºà·ÑŽþ„e¶i¯ßºâœt8ÄqØÕDÛá˜×?„.ËKUÂyÍÓÖp5}7!äË«§1˜No]3ÒAôÖ„(ý7õq€ÊõÖS?ׇI^Äm5²@Ã0m3ó¾ãã*»åmÚ‚YU‰õ,C<:ôª.tHá9‚ÃS}©XÕùꚤ·¼2ìbzž%…éÏó£á¹é”Œn×Ë ¾º1® |Xº˜¦çun[ÖÅíV(2j…ÂÊ\]ߥïMÇ&ǸòÕçmͯE‹0 ÷§"ù†ª:?èÆcÀ}Ä\ÖUMdõPu6ù`Œƒ¹tzMM'’bî>û¦h>ñý5OmÕäý¥T]Þò¬|íÛ}FwŠ5én©|ãÝ˜Æ d¤XðîTH®²–·Ðçxjé²õ¬.Ås·ê}YDWT'µå-o0íqqPl±M¯Jj®R1£‡aZ撚fçëÁŽ%ª¾ÙAøÇ²ùöéîãðøeÒEzÒÇ®êmX%UýH¡Œ´¡è¢p˜º¶º>©ªÉ¬šŠÛ6<˜8 †óýuÇ8ƒ^–ÿÔ­|èÎ0‰GöKE)@ÿÎ/!OêZ!^SS‡ß„À^c;¨"ì†ûï'öó__”›ÆkYº®œ6gò£j’\GÍ+ÊÔyÚº„Í­Êå àh*"ç¥# tuõ PºõT‘;fìzN¦b£rŒ?Ê­çÎí˜7]©Ú&ËP„·‡Añ¯«›kvÈü˜ÇVUí¸Êù¬h [ ×ÁDÀVD‚`¹±'댢6¹*ûn UרÈUämK&u0è‚gF¡¶¨P\Ž|Ø-ÊC‚ T´ŠCì:¶Á¯„`‚HÍ1/;ñFˆèU¢f‡†‚jc¥>=HÌ %Ç%*Œ0ÁýÜïaª/)’¢­¯Yü&X½‡!»aÖ„Fƒ'³Þ¡zï ÄÆk$F#sSþR½fÝEùYïõßÙ¥!Õ®SÝ÷\ýO¯žc‹F€ËbããýÝ”m÷`ç´òKÜ( ׂ Ó0Ü-­ÃSÁÀ2Œ;k”JýÒ ¯»P7—¼‡…MÇbÊÀ~1¿=Ò¶Sh>™‡‘¹ }âš—);&f uV™.³L3]1ˆ?Ë‚æ:YÓU n{Ð lðÞéûסº%·L¿¹Ÿ@+ç¸ «"RçÃ×NÊ*ø/ìÙÛâ’»P`»^k50:‹ºí¯×Ú÷+й¯P¿Ù~4ypw  V³‚ôÿðè’'CáòNŪ—þ±MSul¬ŒíÆC†p¸=VÏet½Œ<7.ëcf£¡¬üüýï¯IQlWù|~ï:ŠHä?׆á«Ý”ö¦›õÙ$9ì4ŒÛ*¯oºo¨eöÊwÉM×od)¬hM?à“˜§˜·½:äÞ\Ȇ˜ÜÍÀfj¦÷è²B}âö0P¡ÚdL”x™Ì`V^c±ß¾ª¤1ÅgÕc1öî è 8ð-xE&¾¾ãú«È·4嵞w(+󦨦ÿùËБdþˆ¢\ãÂöÄž¬V¢ ¨Âðs³©¸µŽì iß(Û¾DT­È\¢t…Õ0 ¢+“A½U¸¿ðˆöY¼­&ýP*×êgè ÁhÌÂ) «0¯×œñвÜQ#èûýDzJÝ`Í$+cç^ŸÝ×^=«Å¦N‘·R-Èh ÔÙ ÈUuHê6-ò,ÌQŒÌ¯ö¼ì‚„j/êö´´»zGý³¦š“ÙÑX¢®Ê¢Ùÿù× xÊäÃv_õ‹*èñµ÷j«#u7ËiÉ&5‹(çóÂý±?Ã4´mؤ²JŒìŒ­ý‘—AÊŠáŽùz3ßi…è’öˆ¤•eÖ1®õå˶‹µ­­¯TT·§K»Ï"(’­ã¨:9xÆ[ec:ê,v‡c€#WøªRV+„7º:¾×}S7òÍÌ-ú¨¾^Û‰¶ëœG/¢îÏÜO/04ØkãI6*;¼é ˜¿Gpïk® ¨k>µ7õ6óä'KÞ°O÷³U­ºéXBÀŸh~‡>×|!HD„Ðõóìð_‰¢ñ“yþ"4…®šz, [Ü[Mö 8R…¿ñs½ÏJ×uvÉÚh7_tiÒvÙ5;»‘ö„;uÆ»lÆc‰ôÁѰtÜÔmT}”^»<­Y¾AÕÇG"¾)Ój"Qž‘"m‚Ÿ;óPyC¶‘%‰2\û1¶­µýìý»r¨oÿ?ÊþD7²$IÖ„ã)ævUFîgßÌìì›/$#³ºg~`æýgäSsf5ü¸D-‘¤ûq3UQUQSŒ¯h¬SÈì–kn°w¤ÚFbc94púɵúÕì·Ð‰EDw}}™Å%ÄQÖ¯„|§—¿FL}(ô> –+Þ•.µkÞd8ÖQ©‘Ûz ª ”ëTˆ5à®9a! =ûzZ]‘^m˜n_•·Ò´"e¹b6çÀ9Êhª7B‰5póÎ8ö›-ÈRbÏf–î9’¹½UMãFAVºY7´èÜÐT“CÎ5šé~›”Ʊ F`ÀiöÖ:(Ãñ\z!Ù¥«÷Ò~lÓJ!¨© -¾?¾tÉ·ýŽáйlOŸ_s·ÜŽÛ:ÖÓÞë<[öœÓ‡Õæm›ÔMÑ®[Àlä¾Â죄®‹.’ ó$E¨È-ƒ-˜`#fIQ,lŸM$4)Û=|Õæ]IlÎ@…Äl&ƒÔ°} ×${o6´£í®F5uVϽÞI1è˜>?Ãûmk/ºæ¹Ã˜Z`>õ/nçãëë¾=ÜóÇÝ t¥ž;R%e»æf‡xf%:8g¬~éñ±õ‚aÑ÷@íʼn×3ךé¿Íz‹«i ì…Q«aófZéÉC>Ö‰®ûÀ_\äDÃta߃_ ø ùÖ­ït–Ûc†X{„ž‚ØÊ¢É‚”¨%sX”*/®?³±Êïÿ«{vaKèLöú}ZñeÆ—âçKZsž‡h¼Ñ˜KºolØê¦§‚f~+kCv~bkɤª  ¾¶ñ–-¿›êÙ„Z:º¢Óíæ®iÛû·:”YÞ¿çVŒ´¾tô_$RÅ×ù±´Â~l²ÁE¡2åM©”^8TšO8t'3—×OfJ¥Ì‚5û.¬±ñrÂ|¡`c±C·‘íû4ï„Ìn5ŒuéºÌU×z*ªìK›±J5—ª{{Ó‘-TÛUÉufÒ&|}žªž}Pyó|ܼâ§Ð¼NØ¿ðL…0¿ Ô%›4ïÒª‡ô™t£Çì=ôS9\ÿ9ž”õöa"Y¦i¸˜Ú"Ìžcg‚Ûðc_:ÆõY¥Ê_0·~£°ñ~÷~nLÔÆ;ÅÊIJþý¯©yu®¦ŠëK·U_Œ¨Gç`—ц8_²å/Ø¥êˆ5—Î׬ëò¬Yuæg­pÆèŽA¥^ïÒ_¿ªž-òC½;çPW»Â.>M- !<Ë›~¨’çõ%Ñ´í¦ç~ÛM­}?çghýõZ­N8hÁÔŸÀ©Ì¼tÍ{%^U½ŠØ3öXmø–¦4pcçuú¦;%i=kA™»IH3}9HûOÿzМzA€8~LmT×.šØ(›UfµyÁ Òž[g:¡ë×QUƒG>h]7¹Æ¸øÔM@&¡çM)¯4X1~0æ·ª5qþ„®Ð´aðÆ­ ÿ¾æ‘<ª3¯‚eTQOáJSÓ‰u&ÎÎýT´]¸åÇÄïël³Zé–Ô_áYPÿ–fW¡s]·Zé˜5c4”¥Zâ³}‹Ù°å@ºäü-ÓÊQ¨„SÅò,lÝ¥E=5 º2BÞÆg4ù3kšúXç›1{]E’·qÛT‡T wÁ¼§0’¥„‚ß+BB£æDôÖÜz+'Ã7ÙÑ}˜ž¿Ãeµe}‘®ö(Û|°ai+PJn÷ÀZÐűð^z·¼å ÓºfM9à›AüF¬{™¢™áçÖçcm§Bp:B¢*(Km`ÌàL8®*M>±©z­ V…ƒ’d¬M–ßB^½Wï?[è0+Æ—NÖÁëfÊhc7ÿC…q™2¸Õk,jI+ÏxŸµ@¦ü‰Ùíùu·Ö£Þ§ éó4yH,•C8Û¿õÏGÛòUkæïñj°Ö·¤M¿#¨’CokëT¡~'̽uïú°;ÚôºÁpŒoÌLôYÐê"¯¢K«_ÛÜ8@đڮ8#`UŠiáájP½4†sß7)vApeaœì<©x7Ú®Øî€\MæPðb©m»p±‡%Šq0‹ê 9µNV (—ºXçºÅ•[ðéy~péá{ÍÛбò í ×å2 ŽÃL æsW°s)$†*¶°r–L®”çü2¨ÌúÓ?#œÅVÞ`’ÓÔˆ+Sþ¢†qåÛÂZ‘­mmr§ëóËÎD©­ÓÀÁ¢WجÆd‡¿9¥êޱI¯pÖ(WŒ#U=·¼6}üš˜–z´”’ª˜Š¤Äy ÉàTw…¡{TøTÑMcÉ,w/á1zâ(Ö뢌ZñœŽIa³¶‰Z –)æÖ~Rô¸¾µP9Áü¦  /g3ÿ¶U!èy]žWuÒè¶«XE§˜®¿UFz‚Ê[òI?WíäËòA1ݼ1™/ ÃVWžK3ï%´e?æB# ÍÊ—óeìn÷ $ß«¾_öæ-/Ê\—³«Š.£Èȹ˜jôÕP¦h €(¼9Ĭˆèþ< 2Ï·Ïé¬ß]ý+cý¬gñ×t`«Æº¨*\oÊH½ò`/PRàŠ£ê=Lá†KÕ?ã@ç·±ÆÕ,ÓÌ3>Ì­a]=˜¿ ß$½2xÌ= ›Õó0:îÓ¾(€ã‡úz Ði\ÉÀn K H¡›:Æ5úáSåEãFUF ‘Ù½é±ùc&ÔZOØl™R¹q7;nÛ®¡¥ï*„Lk¾pt£Æq3ç*Ý{¥³Z§¨ÃÛ@±tO{¬‹)ˆÚ*OƒÎÙJ/ ”dÿaQS7"5¿„¦{»¸¶¬8³Òc˜^»h†ªs/t£PSõ8O! H•.ènÃ>Ö¸öx¦ãzW v®uJ1«ìLµ8J\ÌÆØl,tÍu¡ms¨ Ñ®1޾Êë÷JèwêÁ¬Ÿ*û ­÷Q+wV•)±²LJ¡¹ÔtC‹.ªè7“ 9%µkÔ7 5ÖÇ8òa!<«l)ɪóÜöǽ̳‚g´@õÑÛ.z¯\ó~aVBÁ÷¢i¡gÆÅ¦ÐЍ ,þF•¬éÆ£ªŸä&¶bsȤÖ5w.{o ÏôÓs û9Á‚^˪Ñü£už¹ÎÄD:¸ll‡-–]g´a;Dô ØÓ×/­Ï/uö&HÐúKÑRvô †¢m}U|7 ³ý˜×8Ÿ›ãfÅ~†q|ÜfÅ×*Õó‚?º¬ð¥ •×õŒ ¢^?É’õÂógÈ öþrÅÏËt|~<Ìnäil×}3Áp½TóuWDj‘7ëüõûèØšCâÉ1òQq[ý|‹^UãLu‹ÁÈ%3ç$Ž0’‹ vÛDÀ“jÜî_ýç=M ØÁ(²æ:jrþA˜“ÖyÆ}ÍÓVcî½êÎŒƒ¼Å+{xZF½­%—uR[ãªd%Àú±é =¡pY`Í#ÕxlÑlé¼½¼p,fÓ´Œ„©Öd+í9.“ÙBw\…4²´$ë®(e¸e¢Ø¶¸ØˆéÏdJŽÐo‡.ɧ]%ÊÆnÇö"EÃJ²æ,²OEm¤\®¢õ‚!™ÖXÑëš'fµã¼>b¯Ä[ ·ÏÚ}€ §—ÂMm²0+G8Ï*8J㊷ûÔ:óJbQ—d®È6ng n,½z®y°¡nʼnà ô&5Õ¿Ú’æŒf$N‹z¹U_f½¯Ð§E‚rV«ô'UÈ´£ë¦ùµÊJãt<•¬€°kޝ3U …Mš4óƒ·oﺡÅxê‡Êƒ2Kû!ÃÒ¹-æUfuí:ÌÇЉ"e¡e/(fÅ"Ç4ÞD—΄‘™¾°Þ\%UÛ›x]9¯“ý­¤;¬rWɤKºž¹À,: èã¾øØQ€| #:×ëbaEœ8(,pîˆS­]/ˆS^C”úNôEXÖ*Ym<ùüؽ[~?¦ºð·¿æ— È×cßn[L¸ëHûƒ…>4}“©&g¼½™©i é4FÖs`§¬1=W¤6»ÔéÏtÙq£„€ù=pŒFÀ B LPú¨˜öã¹q²ê+X¯,1–oW(×ÃX@AQ€ë»n¸Ç½Ìÿ°äà´é5SØÏaíZÁপ½·CìbÊ39D„ötÊS„5êî²òôãKA¼V×\éªoSæÍ¼—Ɖ¹‘±¥„'õ'ó¢Cc¥+Ûk‰¸vLÞT;*@Lê~?éeþëÏÏçãñü˜m‡eìyÉðŒŒPܺ?Rظ›éµ÷êëÎí»/á¶aê6Á„io»ÂÆnéºyø^Cتf“Tøé­QçWÀž§h8КÑh×ãë „øY¿ŒDIhÈy59ÛCØ®šË¹3v¿É¹q` kwSÓa ÜûeŸÝšqŸ0ëñ¥›FKmÂ@ÿSæÐ{Órîl‹&Eô~]óèó¹Ìcô$CìtD}SåA• ;ó˜ùSdms½”IÑqtô]•]/—¤~¼è æíP¼ý7ho¹æ®jßÓŠI±®÷b›mö©Sd*ÁaÅkР*Œ(äKúL3¹âª[軬®Þó!jÎD+96ËÂhjž¯ñÖjŽÆˆ~‡"©ll¯¤*hqml.ƒXšÎs×ýª:áÁ¢æ”£å»YE‚ &2{]Y˜A£{Swv¢_†·Ì8õ„_[?—¿p¨ªÉ¬ºïCS<ÙiÙî=°ú㷛Ɍs°Jˆutô'kFçêòfškÞ^®,µyèEm0*'>òN/³›ûì­a&PüÏüÚŒ/|~œw£ ¶üly}>ž]wè__÷óþù#’ÈŠ7ÖKèÛžyÕG塪 óíŽïA”7_ ÒÙ<Ñ:jfo`İ=îwƒI+(ÙãMsHM“9 ±ß¬bóé{–ˆàª–:Ň3?æzùúë±-`‹Î‰Èˆzl§FTÛxtoY¨U™bÄÖZýYš¤0ì×ÇÍVL‚ÙgP‰lÊ› g¾ëA“JŽSot’ºíÔ¸mP³PlåÞ6 ê3ÏÛzÞ¶ íGö&¦A™Èµƒ2zS±Œ”µQÈÐXóßsóŽbX#Kßµw£¢} p1˦l#çAïªS¬Ó{AL¦u¹ù/°Ž‚uºkÇ6„”yÀh6lÃ6Æ­‡ŽžP¯8&6ÈQ7û­hS0 èZ‹¤³Íµ8âòÃ2c‘GbÞq¦äžŠQÈØZÜTcP°Á+üÕì¹ÑjÐbECJÇ)” þñÝ‚ ƒR« çXðÊѾ£¶E79Vn²¢6™êÎXPZÊܦ^º­Ôc:"ú5|Yoå8\úï.2¤å[Y#{`B­oQF’l‹_¡1 ²îZy½k¥Oƒ3ÛŽæ+8@ýp–¯ ZÜ¡€—‰éÙ›O{däÃë9ùÙ´ÑÙºL±Pi6è˜Ýöñ»~}.têç\‡ûóósežô¿†š”&ñîÉ>÷€ò¾>YÓ-¿âͪ²-Ç+%4Ë|]¤×©®ºKïòk¹¸0Ôº6-®û}YY*¼ 20¸¡&ÑÃy¿=ïzX˜«Ðø1Ÿ‡WUßò]|Û &hÃÖf‘…õñÄi‹ÎƒËò½ù5›µÐfsL4¨^š‹P¦uìLÔDŸaO„¿ ÈÈÁí ˆ g‘%{·,Ów‰áÍq}íÑ6!#wc^šA@ål±FP~Êô?Ó¡©BG²˜ÅÊ&L*áõÁ,Gô½;oŸ7úΛþþ3šw@–©Š£sO‡WX( ÊJ6 ERÏ÷»>Ï9´­v3_òÂi9†:\+E4=‹ž}4h‡‰r÷§í½¢U& ¦“å¦JןQ˜Lf ´`ÙBÒ©ÎÀˆ $íkì;ö52¾òþ½ZÚ6¶ÎúµWQ‚XBÖ}~èàƒÐ©âÎF¶Çˆ c:ã±Aͱ2æßëšLTÆLŠÕt~¹é”x\Òx4#ÃJŒTò4MRAFhìá^¨ªÎƒ~o¼Ï®~¸~ÔWWÁ›PI“¿_«j¸=„=–sè)me~}¿ ”ô²y²Å\…Ps`í—E×Áõƒ€i—&†ö¤PëØoQý0›)X>먓=suUy~ÍëêŸe—]Š®½ÔC_çíX¾ÕcvÕ[K€< ³ñ6G-ôÚ”,Á»Êmº/67f« ÛG?®óçh”¸GÚçtß÷ß­½ÿ¾ÍnüÓÝn£Ò÷s{¥_¥äóµjƒ õºþЧHéŠ+Œø<ØB/Þºò½ëUFɉ.:ûZNGÿÙ¸M£U¶ÔL$¼• Ù0lœG4atƒºP–ã>Ìã¹èF_s¥ÕÀ¡6"7æ º»õ¥z†„ WÝ&¡0„9t­X…çn(,÷A$ï”Ó·ð«„=¯8½>Dáw!Ük­ø¾/É7\oŒ°Ñ./‚JŸÃ• Â*t£¡tí0tã˜/¾êæ}êr=L·¸Q f^Ïm¶m…M®7±Æ1ÃqZQÑh€ìÉ xi]ÀÁ\N~Úv~Ü—ýc­›*šš qS=›”jÅl=klµpºõMÔÊih2‰¬0uS:š&m3Ó‘ÙüyÎLo—ÖÓF×—„¶.vÛ÷õnÁ6НA¢ï©õYmó𤃹¿O½Ù½Ò‹D]i®mtí•3%ÌN¡Fe8}2%h…ÇѤ-ÇÖOŽK‚ivé{_+›OMˆ)FFåÏôWQ †¶òÇü8ùþ×”Ÿ¨€tÆ`ºÞƒ’•ï…Ø²ºiÚ?б 7¨w·Ý§6}ðëÚn’J06'Qøå)UIÚ¼é~Ì`²zpI16=Þå­¤¢Ò~RMR.n@§Š»væF¯› ŒÌöC˜œë­ :Ž£Ñó ! –Dž¿?~Ççíó¯Cöù¼óãÿ÷ÿççÇçŸÿúý8ï0¤Nsþ¸1wy≯W¿üúó_ÿùׇ‚‚93¦Ÿ%Þ×¶V®^—eXB§Ï­ê&ߘ?<’C4ªÙÙm–&uÅ?’"«f¬±¸³* .–/6¾F߯Z"JP¶OûcãÜwk¬IKcQ¹jŽL‹hÃ4~¯ oÓëÛ}믯Q;âäé×-ˆ,ØÅ[nåÞÔí¤03nc†B†–/+3Î챈ÊÓaö©¨æ~Ú¾Ù¶Ypfár¢›5V&®ƒ©º³ï«|LZ%õ”­lmVÒ*½â5?ãCdòÀԗЛƒ/ýéÚä¨eWFaášèDÚ…ž›®zh_·ÛñrR¥èŽ×à\JT:6ýömªãi›Œ¶®ˆÁ9;*×…²Wý©o…Û C÷G p¯âZjЬŽwÖ™‹ŒQ›š»¶W<¼RÈ´&/ô«Ç=œ;sÒyvÞ.ôò­”ïz 5"K)jïµÐ-#§»4åkú~Ä `쇬‚‹SÚ¢5«"šª9÷TÝ€ ‹®X!…m¤ÂA[Çöïkn.?ͬIËF ¶.·ª'ÁMºç5za·ÛÇÇÆ(\x_ápž”È‚Ä|À?iW¢à‡Pwñ³Z{ĈGÐÙí†?—É(U½@%Ô 3G=»€UZê¥ÌÓ$Ç‹F!(»&ŠÛw¤ó‚‡®¸isxiæ'4“?¶âœ€¦‰lÞoß_ûó÷=Úù®ÇóÏÏÇ×^Ävÿ¬ÇÇçmlËßÏççóÚ ÉMËI"‹éWSÒÞ?þüÏ}ÂÔ=ï÷å\F–ÅûµÎÝ,`÷]šzl»ynLR®aCŒÅàNÿˆwO£@«\¯çÅ6¢MŠÎ§Í‡ÝNük!°çWLÕlR1þÀ”|ÆA«0v®q³¤ þwÕ{iÂ>|½Dcþä úÜ—iPù´D44ÄŒÏ}НÍ“ar×<ž½B¤ÅÆ®$5*Ó]Q_úÏD!ãU”g¾Iê4Wèí*+Åö[É×5*†êQU¬b§št í*à «k¾Ñ@ù¶›‡š†Úæ=5×ykázäl­À}îm–­÷n[ëÞÏC–º|=Ÿø:Ú!;¡t·ÐHÖ¹¥æe;¼(¹¢è8‘ûíÓÖÙ'`0KJ J½âÆJ {ß4 ¥tØ-ôALƒÅ˜æzÿ t›º¸6RR e6Qÿ@+ã7Æ}uÍ»^…ÒÜ V O †é3Û\&ˆ6âtÃ`ЧÆþ£d:Vu ƒ½™6m£c'†5ó†^5uÖåùsaFÏ´þûš›]gvc! wz>is^=,³_¨0u¸X€¦(5dŠp{(ª ´Q1YðF:V:ƒ“nO´ª¢z¿~ÂÌÜoϯÁו\Õ$o×Ì$¨s‹wÊ»&ÿ‰E¿®Á’šžËXÓªmê`ÊÛp,l•ªït<Ž YWZ¸Ö±Æ[ãx|Ü–õ~ŸGäëþùçSÈm¥ÏÅÚÂíøøýqlÏ}Ýg·ÄŠk´ê5…ÛtcöÂQ4Õ"æ´z™ïøob§a ÜeÁrÁP0sDˆ]àN¨„ n[Ǧy_T}þÉ·&"ÏØ$R)l} &·izi¥íQàü±lÔ-¹"#°‹)iªÊÈè+eW¶ƒÝnÓ?_¢o¼¹Ú¾P«U‹rèa¬`¤NX(†tÑd½4åIX„!Ô˜”1ëŠA†‹ê¦ÆGkëËôç¾=tŒ*1×Ip@nöyzx+ñ‡jö¹ å¨SWWÓÂX§¢TtMyivbý= ¥Óe6’CÛ: ³‚°âP™èÌ@+[9¤2aCÅ–^×¼F·ÉîÙj²m Š>Ë:…•†½>.lS(•X$mfÞ¢?ŠjX¿¸=Ñg Ú!¸ÔÝxðM‚ü-Ô–‘¼3ö]sÿ½kK˜³ `óz†»+ ÛdN¿„ +$o9 1MÐGNˈɩM5ô‰ÒçÂèÑ@Zý% #9˜—tŸ8QéÌ­xB_"MÛå9b\ìþ–é%aOU)t¯ÇËHþuÍ)ÇM½Âv/LÇ`¡Ìdu‡ž÷À°[…c¦©-†— ”N¬ ¢ZHg­BT£18w>»45ެ$jÓá1/6e×ã¥{d×}bk½ÜŸFAÒ¥FOŠª¼àÙª&‡¦]¶/Ü3º¬ƒ@oÖŒŠ=¯Öqo_Fâ‰û…¯´¶àä½ÿ°ò²-ûãó1…mËkx¬šßïíùÁKRT¤³˜ø<^¬I05gm°7àØ‹ÙBôÙÉ•ëLã9Ž” úKð±qºD‚®aÈ’+**ã„GIrù5/ò~79¬pðã:U/'^[áX´…z ‹8cך½Ì!‡88_Ðæ` ÈÄ6õÛ4È ™é0ûÙ»Ò´­tÇCl?ëÀÍlˆá–çÚd|¹!¿å\7é dªÐ¾A;´7žßæWa]=ð‚!p<«Kx®™Qš†²ã S¢yÏ4ÝVAà §)„_w¦~bïð¶M¦ÈÏbö¾õõö’F´ü%÷ÍE³Y TÒåK„ju¼J•oÊ…Ý€² õÃ}ƒŸ ™°¾éqùŽUAïWüZÆ=²ÂªÃ¾¯ùË“Ä4í^qJ§óÇ©—8ÖZg ÑQþ°H¡Ÿø ¼Þô6˜ûíqãü8Ùæ­Q}á̬ôYl'¨ý#ÍPll :¤I7ÕSP©³ Q+å…¢§ŽgšÊcIdƒ<%þ2¹tu껹AØ7P›Ó¡àª²6MJ‰• *²ZÉØèçóü½QÑe,“T=)^LäØ\ášÐeúNCn´ }â@ Ó4WöP¼OTŠ!ÉmõaˆÂóÀ Á L¨h™÷Aéãêðh<[{œ_Ÿ4lŒé4ã₽'meæÍàmJ,ïâ8©Æ-*ŒíkE·e$$ú¥zoê|^™žÆUb•aúíÞM«]sÁ*hͮȂ<˜7í5Œ0ïÌΧ3›vò&ŒTþМbqFßZ÷:˜ 3±-ÊRtKyï ÒzþA鹦£o%Çöûš·QˆÜ”!L!ê–Š(/0=)~¾Ux×,S;Ý{Hþ×Ë´¥š…ö¡º˜QŒ¢`é\ÔJ¤Æ^¿¯0Nß‚MOç›@õ°Ýñö…Ü Wã0iÍãvãàéÇ…¹m²7>^Ûn[n2 ežÀ £œ4V±yúx£ýø’²6™þäy_Ãfåéº>XvGlÞ«ÊIýøMeÄIÎf2m+ªAü!BRÜJ_࠮Ѫ7 ”-ÿç«oò,ÏÍi¦&U‰«!11bW­c1·U,€ãJ.À‰^!q›:¬ˆî›iºõañ cA{¬§—å{3РöüãœÇjÀfÂØ96‹&µ]fÁ¼¸".¯ôß6MqB# È®dì§oÚÅ>‘*¦]áA¦+U˜Ô(¯•˜Š‰b÷2–øÈÇÕÝë°Òc´\¦w\” }çg:Ä•hT³fEì\_¢ÂFcTüïýTe®ùÍ0{íS%µ4êˆë(5<Ñ©x5»:#ƒvdYþù¸O÷A\%DY{žŠœT§p0v%6I¾j@1á†nïáÒíx+ßô#O´çød¿·©áR¡C¯s_âƒY‚>­W”!4Q€5.jFÙÝg«fjv<—ÉÀ5â¨ìÀ»~Úaå5ô~ÔQÁo.˜ðu˜”ŠÖ$#Î5Ž <ÈÁÒÜ¥YžÒÔ}rÖÐwJëÊûúý’™جÓOÃvkÚNPVÖ˜ò$×4WöS7ß×¼y1b-ÜD{VÞŒÞØ8éü#c `>YÕïP"o¬WŒï¦`;û ,þ÷ צÓ»ŸuyUi.ïv%C@\×ý¹lþÂGlM£o™˜lˆ šÞUJq Âþë v6¤õû>*M@z¹yžaÞõ[õÊS¸ÐÙY¶Û}t„NUÔöwuÞ‡§q~þ>i…ÛñüýçÇ>µ½Ù¿s¯fK¬ Œuóæ³þùFáom:s§¥Ú™W\\ÁÞ/«6(´q‘&„–ÄL»t*û†6QIgºØ0íš:ݲB{Íך¾Ÿß-¸ø´^– ö²ˆC?XŸÞ…9»±‹OþPý‰¼©Bª_ÖZmN0} Ô³uW4ê# ÅXZë Ô”âáS[ NÉ›iÛ>²¤œVêß4y‡¼®òu€IDAT|T£dzUD…µ żÄè‡Åé/·Šám|ÈÔV“C/‹¢.¬âù“2÷ãUo;¸+A¥`“7…ì½¹qÍ÷—9ëmú# üùÖÔ”.:Ý{¿(\uÆýP$6+>>ýáUäëHSê!7ƒºKÂ[_ ˆºí²à›ˆÈßPçÂ…ËíƒÁ“!;++:0óP½Άæ:V]æõ' FÇnqʘ5 =oðÀÖŠñÞ6 Ùª)p4”ðCyèúmR0êåv7.­âÿÛ1Zߢ½^Öé!jKµF^@£Žk¬´øa€O×EõUÅ/ôÄ…T0UûGF¶E©Ùl²aˆuýÞ„êrͲ‚ó ôß®¹ ‚,Eª¸‰OzEZäïé8}¸éLŽušZËÍ‚~t~!B˜Z%þ3ªÿ‘׬Ñþ#OÒfQ¾ŒµíyÞ·IAøÜjbøGÁ›öÏÇbüsžŽSp%˜ÛºþçsÃ4wÿöÅVN ôUÝ¢2p‚tm™•ýnõ¸®{/¥¯ºæh—ëe¯ &ºþ›jôùÎnàí†ì÷èj5Ó>@=|…¦7 ©mŠ"3CÔµµ-[í2å##7×kY¦½ùö¥s¦Ï”vMndg6oÀ Ù/½Ì¾Íz—%M[Öc›7ù?Û£4u·ÇÔyMÀlWÅ6%­°Dõö°Àt4ï4s›©Áü¾¬\¦W\çô_{`ûóØe:³€&›f9ºœÊ‚NåÞbÿä'¤=ºªS¡—¥Ýùù¼©þS.xl·›Ù5(Ú¾*8C‘»-0ÐvT&q ¯]a.§¿¢`^Õzø^o%,Q$ªC\gbE¢ɽRÖUu¾Ön`wižšq©ÚÙ›M%.”5à ×oÇêPÚÁ= ôšõýEçYëÐÏlÔq†s[H˹Ï.WYÌ\›¤êiã!J×5¹>­÷Kš——¤Òmn{Źâòž¿*¯Ï±n…ÅudÚ>Aò¹R†Ð1º¦Y"öÃÇýó¡u-T@ ]NÑaÖ€Eï±´Ö#ö“a¡êvž`w­kkõaßk°€Â²Ú¡ÐÂÆ}WlޝûÁ°\¡iÒXví ’õßK­¦ÂÃÀôòÞ´I>¹&«BS Mš)¥U½‚k•¦̦ë›/©£eÝ%M‘]Ü”Wíÿ ÷•ÔËÒ¢WË¿¹ËÍx éèôï1výøÞ^FùÌ3ÓõUæR ~šaÛHéÙ1I[i›êš[£gz1¢ÒükžÉ¥Š"vð&Û=a”ow›c‹ d0 ×ô(¤bEt{ ­%Œˆ™4BÉ EÖô‘ýöèÚTu°måb Ìžy͘¶5õ-§Š»U~ñ+ûÁ7Óé³½‰¾´ÁÑ jœkô'1˜©qgbo½a2­z\nÖûÇm@‰ËÈ4ûÚPÔLiEXëeë#”%*õ7õÙÓcÕG|>uÛ•OƵÎ:ïnìu¨±QÒ»TU⬋XÖ=®@ˆ À'Ýæ¹"f×ICÒ-øÁ¸êÐÜG_yÝÓÚ\ý„9CÝNÝddÌÀs%i;†Tâ·¡8ühe‡ªF÷óŽÆ@=íxv®;ì‰÷FìK0«¾¤¸aV”å(ô ï–1“på;<üë5ênðŠ¥ F)¾¹¢^u6 2±j ]]E5—e-`ô€g¾©H²KÁú‚*ÒuÆr@ˆ•W¨1YnÆŒ6·/~¥½QÒ^¶Ö‘diÊG¶ø¢X–èäÅ˯ðþñ|>p¿ͼo´•2ðrcV›jgå”Ùsåî|Å¢yl®“k¹¡&»¿M6 ^mñtÕc°n£ËfL[¬€it¯ÑÓ™8¬çÁ˦ÐG÷hçuF=›‡€~­pV@ÒÖ DlrB³úÈ®Z==3ú•<û*/®¹ !Âz·Ñ䫯B^F/AÊíe¬bZ³ä¯?öãµT‚DŒ©Õ°k®ÇïQ̆Š>§Éë0 TÜÓ?ìˆ×LJÝí…¥¬Ù–Iª³ªÂö½´ÚNß´×N‘ÔVhÀ¾¸ËÜÇözÔt`ÙÒmGU5#ãûÆô¢×ëߎCUAPœ<èš0ê ŽªœcéK“¶}ÈßKäóÕ¨Ì-錖Wèl¡bìV½+mpãìdÒ 7Hs*þﷹ尲ˮ"•æÔ@á܆9š32›²—@}åG¥Ù¬—… °%â hœ,úK9ªv fÌŸ!qYtÒ!|SÛÁóÖÔwÍÁ³¾€žL4sÍ]TvkçUOg>ZÓxÝêy©ëÁ›æ‡žÕdúX¯¨Sáµµžs;Œ a7bÎKÉεž(:”S'³ièdzmBùžéEc5(,µ,‡#ò\ú|ê+ &UPå̈ @¡äÞ3twËÒ6Ïê"iÊL¡­M½ª=ï6ø6Ö¸B$¢Ü*ŸÆ¢‚h‹%ÄôFŸt0}s…aÝr‹,«“RÈmÞ^}ÞùÕ‰Û㹋1ܽôi†ñ0eÝAÚ]\©J®‡)> ícÑO¶’H€G9q°» yRõÁÔŽ¥r®Šý`à Öbc¢²¿T‚¹¹ªúqc™÷(f3Ó!@^ò{àü꬯öÐéY¯£NE! +À>4×vqWôãt^*£&±ÒÔ¦yß\„â]n\ñœÞò—ƒn¸ 1‹À!¾lQMb3ê?‘ÒqV O?^ó?Æ$¦ßCûB–Ý„µ3¥Çvšq¶!J Ñé;M&¡k¡ÉÆgƒ-Fë»Î¤ú,th?‡«¡ ÛÜVB'Ós `™”£ÞT7LŽ r:u§k§ÏÂfÛõ³Ç;“£ ¸)À9À6Ö‰œ (1Åq0,AÕšéµÙ˜³.ÛñÍuÖYõkŒ‚f~A-½yßeÊ:—ø€ !be‹bQmiMpåQ›¨Â¥ j¶ÒĘõ’uËÓzXoŸ7¨ìFÌRµ¤h1ÙbN×BÀ`øŸYñwŽv—^4÷xR[D¬Z¤ªF:ºÐÓíšë®¨Ÿ`ü4¿íìN#)¢oï¦A¦:~ ÝH*$WCýXƆ þÛuóB›ŸÁn~ÛE×aóUÑgÀÜSAzÛ~óªÙ¾5æTéêûûiEƦç^`‰©OË@µeãk‚ÛR‘ëçø,᢫›™~1„ºŒ0¸n JU?¨x ¸Š`üf=v–ç[êq˜sç|Ütmm/íûšO± ¼ƒ_¨'D8œå6Za­±:ÁðÑ:]ÖBsÖÕ1m’RøC…©rˆ 0æ£]i Àl™¢ˆªî4;,Ó—_˜>¿¢ Ë_Ö׊—{µ#~˜yø“F¶gµ rŒ-m›´¯å¾Ãü’x€Å·-ºuž”ÞÍÞÌ1`­@L/9ã‹Â—ïe—¿³`@—ÓåLz.ͱh¦›º^Ö€C³ÎÊèh ²Û6éG¬Ï—l™Ò0ü=zãD* W¦§­“Ñc3bº®Ô;\sd³Mæf¢:È4K ée^ÈD«ZЬð,ÂöyÖ%ú~tëÞdoÅt-˜V3ÐAí|:z˜Í:‚tÄxn^¿¨lÑ© ô”†Ê\ûH&kÃ|Á'W¥)í¶âS‡Qˆœ™dl·ª8}¨¢²2 ³èì&: ü•nKl b/äËZ 3!é–…,0CvòËÍ-ºt(.vÍiÅ+é}>n÷Çç×Ç]ÿw¢g=°4ãÑaœâjòë<ÖŸÜr‚Ź·Í³H×Iè̾KÀZèqÚµáî`CFúzŠ´ôëàªv*æ­÷] в³JŸU"—~S/ØÑC7ÝÆ¸…û pª•²¼¾ èw¶ìDÛW•§Y…A+’ì™ «`Š]ܶ3 Û–Pj=Ná¥Ü±§Ç¬ožc-$Ÿ3¯GäãÊrFßTèVžªžÎMžå¿~UäûHRYfHTã÷"i"Vi¹œ ÷Õì8NƒèëÌœL˜vžìb°‡éR¬\ÇUh«hª«)g©…÷¸YN6¡ÓyÔ÷{Ýò~ù™ÙføCd»:빈ŸQðy¶Ný@ùïŽ7éÃ|¡@f3 íyô‹s´Ú«J$E†_¢ÿ2Rc %õ9‚'%-ÿIY¿˜* ¬jlÅvðßa+>6¾Sűîû±«]s˜FGܿӓÆ$M2o ôÜ´™©ê½hÇvp°öâ¢\÷ó:}œJåmÁôŒ%‘×¢eÓ­fŽ7Ôóùu«KoºæJ¦¼(Tâþn›gcƒ‘è ÏœT õ:¸æRÃðàªË6ºþŠü¤ôÆ 8UþË´œ¦ƒøêfþ´*`/WÔ¡õ.ÎÓI7VBH¿z¤þ“¼E®¼¶ÝÁ}ÄK0gÿ¸ÏÁüe¤™:îHMLsÅý5&™ˆm¬UWºÔÖ³êŒ-8Ý/Ü(>>ŸºçÏs?î·m¿?™­Ìè‡BG­ÓPÚ6a¬üõ”Þ/ø'@Òs}ôVè¨\˜CQ%.n§D;*<è½sVs+yüצÉGAXýòO´Ejý+Ým`,Ó‡†‡¸Áð {º÷q&nQ O­Ê‘ ÀºH“®¶-1½mq‰â<µZº±½…ïÂDC+~&tº´xI8jô}úÕíeª·:sXgÞÐÔÑwÇo—>ß]Ø%.÷¢gÐß´'nÐ2° T9ÍûbŠË{´Ÿ%u"Ù¦ÏÓ jݶ¡KGúÃããúQF½@ÿ²¡Ü²ÍНÛdè: çÍvÈÌðÛ…ÌÝ`ß·×îÂ>7d§ÆÃ¦ì/{½Žï ö«g›&îÅî‡*óêr©½>ƒ¥¯è¹Õ¶íºõzm‹¬àmŒZå²*¹ºaßÊnò^HÜYL°ml° ãªdá„“À½¯ß }´R&ÑkEš4 é¢f‰">ˆÍS”tf”4†ï¨3èŠÕºæ):‘úq’ùéÊÆ«Àæ¡’„åÂ+›MŽVBUÝçIÝàáQ1üEœHŸùè]g©>Ö²Ð1,Êk{¤¦ úP¦ƒžu9`í;Ú½œÎéª2‡²AèÄ­`r^·ì×Ã:s°KlDd†&»ž×Döc9Åë&4WXá¤טóhW}Ϲ­ë¤‹‰ˆjÞ¸ÐûúMñÿãØY•nÏÝ÷Åòµ„H:®¶^.|>·ž–íˆ «g,jæh´äÌÀCiW̚ך8t|Cø% 6’`Ç ^9¼EÉ=hÛ…f¡`Æ•ÉëÚ6`T`¬¹5)B™Ÿ¬Ž6ò1Ó„ÆJÝåè”–¶i£óU•ñˆlü\乎JY!ÌHïV™'¿&m™Ìª.rÒw!ò0-ªþ[óÍ í;ÀYCNß^á Qk#ÏëJ‡h\{6˜mÀµYuü€çöÊçðJ…UU{©hcψ‚E1ÊH*`ç±EÞ—‰N<ÞãE¸¾µÊ²S³yK[Ó`§¥ÅÜbÕu ÿ½ÞTÚ³®†L ‹Ï57H›§íáÀx »MÏ£ "¬VšG™•ïeI+=^˜ÏÊ$miÛàúÖ#¦aPÆ×샪š¹H £Ó£ï@Ù¥Î2A“n)23‘¡È&*§4%ìš3QïtêÁÜh×ù‡ÑƒçК¼GOöweóʛë¥^¬¾7Ýà µsÜ‹ôõÁdcõ·IŠ€SZõ>+Æ>CòM©/0ÅêXò» Ömƒa Ǻ¼û¡oÔU‘²WPÏBg,ø˜x•ªn]ž$(Jëè¡*lÚ…úöUz††ÑÔAo}èæñÕJ[" a`Êc]y“7¡ê¡ôÅ¥÷ º¨Š‚_uˆ´‚󜬿ºNÈk4e3Ôè31Ç´6 &ÜciÜ›…E^"š…ûyhŸMÊó~@)þøB}žÇíö};¿~<¿ûóãÜ«*nçÅï=ZSÅapól}¶àÌ6¡‹5,—e¨Ñ6Ð(Ø™7ÃR&qo”ZÓ\T®d§ÿê™+ /‚«Èõ„dÔá‚A)ݘŽÐ<9düBm†%¬Ñ˜²ÆwZ Y­0™Wî=˯×Ê<å{¼qóÃCÝ×úš6®N»ìZÑëóªZì²·Z(ó¹|Šªëó.”íˆÏt(’Á<Ùu·¯HÚA³æì©pµm)h‹n6S$¬©èE¢p uö³dÉÁHÉëí±óïwáhÐŒ¥OYGÚ¦ð]riz7üñþnûti¥¸ß&*I<„y}0Ï­_Qpšh—‡p|nô]Ød;ž;Uë}&¶¬î>öñvǘmØLOeÝñI‚Ÿ¾YièüÞÎoR»~M㟠¹Î%Rœ9´)›ŒÓjº¥uØ&}ÎÛ)>/Ö÷Ë2üü)Xõ|.¿o»µòMI• Àwï}@¬´^]©.óK9ôøm·áG´oEÀøeÛPÔCù–VY]§¬éëþ¾µHAS(š ½Õ:£ùk ÀCjÌÝUø.ÉÚkçxLG´¼ºYáŒz^÷ ìxŸ/Ä’•}_PýgæÖ^G­õÈO‘Åü2d—ª-T”¹Dôµ¦PÆÜ©¬ªjkªßº©dEßìÛ_l S5°>óÑo¤œêïre¯±t(ÞÛ8 >OAéq:¿¢}êà«·®ÒÓ¢©n4÷H&e{…‘ãPf¦ƒT¥~*J§s‹'Ô8ÝÑØ–zý¢Ÿ·ÇÉç»ÍQeâqWé÷†ûS•?>icO‹¤•þ¹QK¯z¨Ý6™Ï&Ôô.Ø¢LO]m3C$ õäëy©Ò¹Z[ŽÁ:{YêßÄ9˜µš÷ªÁõo[Iaì5›¥q˜Ztõ8’4 + àÄʉ€ :%®VÍàƒ×î î*×â‚V~Ñ™M…-KR–a,³”š"[Ñ{1ÝòýªêJ…KÞÝ ª­—E0tô æ ÎÞÍ'øý%Љ×†£×‡±ÚŒKiÕ{¨eo\{F]Ÿ¦yÑÙx¢z6®ÐWPê¢Õy#g1‘“I÷)M;—·!Kß;¶¯:¸]Ýõiú«Æ^ ?îøÛñµ÷ÃùØ{·=ïS˜n˜Ëëê?iöS&l74 ·q9Õá£þQÅñ“×þ€ózBÖùÎâhVp0×q>64ôÃ~Öïi‘$Íh¦—JWe®OQYÛ¸ZMh.ÙxIZ¶—ÓRçÂ[Ö™¨ÁiÂñ·çòúz•(Ûý®ò_8Ñš“ø6uÉ;öcÊpÃ4üønaÚÝÐ?=8a—kžÁ÷Zéक़y÷zí,ùÚf-Ý£²ÎÍÎU 73‘XΪ"ÌŽ8Ûz¶§#i±hÊÂ{ÊK=êh뵿½µ„„a`Õµh–?²¤RXFíܺzáøºùzkûû׎³Ðçïmˆêå*¾tÍ—‘N˶Þu›{Uˆ¼<£ŸÐÊó6¡×;y0í£’žp·/%\MìZt¼˜&ÍüH:ØÌͼX>E–1‡l¢*ݼÎmª0ÛñmòÚC;¨©g¹Ã”Ui_+j–l0ÂEÿ1¾„Œê¢ЫŸ] TveÙÒ¦—b:·)ZãåX¼¢ÔD‡e¯i”‚Ñ3#"Ž¿²Œ@>«gútk:íÙ{ÏŽbòð*ª†Æœn÷ kÞ9t ‡•튩i —æk(ØÞÙÊf% _[—°é0Knó‚úwÃÄúÅ÷›ÖÇó±9Æ‚ö<ÙO)2UŠÓâž_l™(f›º€­ß?>?ë¨ ™´Ÿ ¼Ú ©}Q™f:Ææ—«Ò^¡¶¨Ì#¦atÕëé@âÞSUë£ecAðèšô¸ÝQÕ»ßTWÍsO)®ËŒ “ ¡…"Õï‹s¯€‚öPuŸÑêZá6É»jY‡çÚê ÑìMšý4Kû^q³˜™¼?ké)ã©fÖ£…-¹«´Ÿ±ìãþ0{s«]þnz.%‹äYBw¶.,'s|±ÏTÏ”_XÔÃNЙî‘YâÕ£Ž[±<çê2Áä; fßÔUŠTuÙ> OFgâÜ}seT÷(Pê“_î›k–/#jèç5¶ìóSO•”MS]/Ì(0ªY·¡Q úóÏÛ¬fc”Ìr‘™+ÒàÒü= º÷¯¹¸Vúûó”xà=¦ÓÙ×õ6‡~´á£ûåf5µnÊ rA³Aלéô“a -)*×AÒ®ÿO$#™•÷‡Àü$Ð $UÔ*ßßõ¼'·P?NýŸ'’¤Ç³G*R'ß›P¨Š¤®Û4Óa mß;,Ųî¢H3®ÏícƒÖº?‚p?@×}<[h1»VŒ¤KiõêSà×µqÃêejX.@I1ªÙ‹¾²­j®.‚Cí¦`²m.ÍŠ Ns©1á<7¼”ë[3ËjôÛ J˜:iÖ0_†CðoOº¨ï2Æ[®“‚Y`š»½>¿ª+/—Kêl3yþ±FÒŒ]þÁ)Y¬·½ÇÚöbŸ¥yÖA|g‡¢«E·[$n»ÂX_âêÚDHn9«JnBsÍ›NᡸàNa—<° ( º)ÕÊG[Ë+ÞŽ:B¹x zƒÑ³€'´:ÐdæzU÷ºø8T4U``«Ãô«Z²ùö}Í…ŽKSÆY®u„Çîœæûc½}Ý­SqÞî¼¢æ¦Ï3§±vµpe: º S¨hø•¢iRA(«wª¿¹¯{æòËÚÚ"¦’²MïÏc» Â;sUè“ʧéúp{–Zè†Ó"NXqÆw/Î`‰úѯKÎŽ*¥5J)÷Þâ£Í§LE3^2 ;|¥õ‚•P(°&è Æ€‹BkQèÈ•pý>ù~U>¸mq‚*±ÐIK9|yæa'TY±#ï7&}´ý¨(ãiM²~ÁB “„ª+’޵EÕgÇxß \{øÎß×\/Çí¼ù&}ËÌM@Nûëcl§Ç‹3:!Z¬ûµ •gÑ«§éØ{Uzêûv“udÏPðg1äiUÙ¢Å4©T2É|•›?+]â€Yä12™SAþÜ·>諸3§QÅeΛºӨ޽ H`º ™ÊžK–©0D ©tîQÆ´ Q0q…žµg¹f¬¹(—Àù{YY¨I1#€« ûÚg¹ÊõylÂg`Û8÷ßÖŸ±C¹ÌNŽí_„U³D…Ï{ªCŠBã|üˆ¦GÆãåBT ¬ªÕ2ƒ½½=õyÞ^1ÁvÏÝQê¨JÖøƒâvÙ˜ÌcÇÕëÐmì GƒîÚhöé(ÔbF@TPVΪêúž¢Sí†6ab„éýj!’=†©ëÚŪ¡ºÔœ:ÑíB°IHöú“H‰ãÝ7hW€»ßCnKº mÍVïÏãöñqžÛaÖjTY„æýe§0Q!ηôÖS×­‡iªâó¾Áå¦ìßÂò>VÛŒél+»t6ïî뼟'Þ"ÚQÙ€WÈ`ŒVy@†=0åòd?›u£Ýüýs»±Íû­/-ȤêÅó@×_BÜk·ó>iT˜\Œ9pÕ•qU¹’½½ýAW#°* !6¿;ß?nzàÃtœLŒvYwÅ{Žåg¨±æIÞ{¤z«Ñב™N“Ð]„ðmÝϨ›ã¯Bé›ÜëˆýÞп£‹7p!Ÿšæ ´3Ç cöúN×÷&D}éñ±(«Þ†2Z4© œAÇF'IŠÜ+Ädµ-SydUO¦½a‹i8¢*zt’«ú-[Q_ŸU@ ´8¡õPW—¸sµ ¬€½ƒ•T´øùv_õßžÏÛ¶œ˜&¨~®½ä¬àÜF‰zóàœ¶)³Â›Ä7¢6q¼×ó`Íg gMfÓ¡RÂS¸™]ö^ÀOBÀÃã=·*ÅuG’ÜđӪóÜÁWÙl1–æcä…œ‘И¼£uÑ7;šXnÈ•›ËäR0ÃNíöÔ_˜œ›B®,+³‚?;£œŠQ51«ž£5Î Ï‹$üÉv&ÚGó}ÄOÉ[N/!(i¦]]3-•_•Õ+D¢Q9UÞOá…{]öâý½¤÷ãHï'äådÌ'Ü~ èÌ"¤Ë2[¦¬ÒBX_õ£D€xq-Ãyr¶ïjˆSþ €ÝË:WxÜï_††øGPÐ(Üòl‰Ö{XOD8á<ŽO^f|ׯĆ Zº«:L¼F%P …òñåbÞÝòr@FžÖãEiÞ¢V>\ç9…ÞHÖ !¯lní󈚅Ùùhík £€÷æ¡Î;š¼¼-Zi¦=PÞp/Ô}÷÷5æKŸ@Û+=ÑƬ( Ì'Úó'µgX4…iÎJÔuW±|MXÀ7K½²Hõ‘ ¤’¼[4GC@¤]á-3“ª­uˆCoJ{hPU¡Ö‡ãº?ª3}¶¸a³˜ÖšõqûÝ‚ó8T°"ÄÈr PMâ ( Ž2ê) ôªQŸŸ·Y!?ûuU”@Ï X%9ÙjÝ¢mÓ.ôáG~DE2½¤…Û?{eªÇ¾<瀲¤Dšn¿?þü «Ç–Ëcl‡çŸ‡óÇçé›ùëy.ÿÏu0¡#oòŸðVrцk®{Ÿå\Qeá¡l‹¬a[ÂÅ0«g…K{£¤<š&Ëmd” u*öÐDAVŽ"†ò`,36SNÖcªÿY/з·xZ_c¤%’ê(ò0ãhJµúÅk‡¨¼bR’¥uÕ3cþaíõí8ã>Û2©ˆ<ôŽïÈÊc–…mQ™–¨`˜Z=-?dûÉ0éTó—´Pj«œý/]mO˘d?,®û´]U>´øœ±Å¦½àOž•ù{|ÙÆ‡¹ôcZ°ÇJ=¶~šÃ¬Òl§- 3s®m3vïÙÒ½w›Ð{–ÁË̲e¸ßˆßÛ÷“@i°OÞƒÙ„²F¶žÇóCŸ½ªÔmr#Ê`ã´î0\x Ux¦§rè¢ëBzZ~™Ñιx£ÙØ•(5ã1rð”AVÝtƒB3fOŠaÖy7ŸqÌ«—ƒÖ:w:¡ûìþ»6P × R²ƒ‘ÑŒê˜AÂ_µ>3R9TÅž F®ÊøØsÙ=­¬OA®øïZ7 Á«®è„õ‹!7%ՍއÐdçû¹«Àhl/Ðütí¢rQḡøÅê4í5ó¼PÍÍ(-SÞû£›Ê7=ìT…b3,^GwgÔ£JÌ›9û1*TYÝEë’²¸ïr_IuqesâÑ«ª¨†ª Ìξjx'àšâCyÕ_f…Hhhî?vÂóÁ.èű[€FsZ Çèdù¸ íÞŽÁ+K”ç[Øt#,üBÉgôI6ö̀ц>ÙíÖ³ŠÙ8á†ÛÇqâ—¦OiëÚù~Ž~¾}­ªÁlÕ ÛÄ._ztból¨&É? —½%¥{RVWHì> øÖ×"¹(© Ì/ïעΒļN¯‰îëªrøcx/0å왈ëÍŽS%T’Zõ”°:- yű6»¶ÿËÐ'Ï( 3Fµ#G”1* é$?¿nz\<¡¢$¹*çooUØšÿñ-©WÑMÇWv5ò£PžæÄ*x†PÉbYzÕÜ*36˜º+øŽÔ·v#„gc]Oæj2ÐŽzèú¶³JÇ^kÚu|<ÒÅ {.ØwÇ\upàðxͲÌw‚:×|‡¯ŸŸgŽ£7Â5š¡ž:š²uï‡î=ÁúÏT@¶ïõz;ÔsÇP¨qUZý¾=?ŽÛçýfÐüïµåÕìäã¶ÓíožŸi 8û¢b¾DÑ ë ¼Ü§²ðQ xåk¤>í ~*Ê c÷®fÂÕø w#ôÉ_«k·vϼNŽAX·ØÈ²ý3H­÷Ë'[Ô>äó }1\ªpÍB‘üzËë"¹¹u¨ë‘JAègV­£ÝDž]½UAù·B0)Ýb£O—Õ²pÿ`Šx¥ÕçΈ_xXgmßu[9lõûÿ7Ül_%Ê<|ôóˆühU(«†«ª¬T%4®‚Pö;fßÛÿƶ_£5áµ·Fý®ÔI¢Ð§Q±vÆí$åp~*@7 Ã|ðI¿³o\5E2&Ž(>î+^U§cë½QN±•W½ðn<ù‘·ÇS_ý~ªæ› m×׎¹ NÜ_hJ÷<ú qwê.î…Ï0tšvämªÄ Jº]ÚN¾0dçupn~é´êU…Ó÷ÐÛª§AAŽ%Y“ª³õÜ .FW°“íîÂó~¼„þÛåÅ?ÒngýN¬n¢o/0pTdu[ùÇëZ¥¼Åó"wú(<ŒtÄŒP\Ÿ»…'û• )5×¼1E>fYá¦,­‘¡/B ÊϺe¢øCÁñvbM&ìM=”+Òþ]ñÖìktXcÑ“Êqx,ðlº\¹F¥»^ÿ¨¥¤NeûSÂÒÆ1QºBÇm·õežÒ®ÚîŽ 2#&]Á½‡´ YîrÔ¬YÆÅØòÿµÃS¤Cp/*8g¿uz ®md]€ÒMpTçýÙ%ÐØ‡Z?™4é¨7á`VR­¼8á·ÑÖÝô‰ÅÜ}¯ÖÓw:[ºI!ù~_ ú(vü*ËÄJmZ~bAÏõ‡íŸÛ—ñ]cÛíi+ë™qQ34#–‰Ç“¶â(›£õ´Ð×Ù¨k ˈµIÈ ?àä3-\sgöœa ®Ì1ÏÊ®M“NQL§LÑ@aÚK²4“L¡"‡9œ%.ƒ=‰J-FÓ òóЩ†¡zÛ& /çÝTÈ\sÔzØŸûf"›†çÿîf¼ì%–èZûF ¾=¨'êÙ‹Q¬Qôéç6©ÝT^YÝ¿ú‰§3 +ÛmôÅÕûämüé ZÏæûüüüÐ×/ž©ž[0`#ðdØ©knN}K<ÖëÀv¹3I×±,2iÑsL!wž›2Œ­æ¡T;Ø‚žÁ† ’k¹86W:{h>˜¢‚yÚ22œøhâÛúy ‰’]¦Í6jù†Zs§$©›–]…ä°oÓ‹°DòÏTECÏ{m³\©“ϯÀE ¹ Õr“gÇ5”—úöu›ÐÖG¶„m¥¼…- a;¶,Í­Eá1½Ö?ßaˆ¾¶N#º2 j¼úLAÁ'tªf«&k‹âú³œt˜iL¢ Ö›¡Þby-™”{UáÕ¯4 <„Æ•çù€°.ÑEðË8ß6Ç=ìÙ,çí]ƃ=2r×¾7iEw!aõ²HKϘ›Î>bY^ý&t/4Bé¿4¨B : wöžm ="Ø&l0©šˆƒë:wU‚.áê‹Ãønëøßè0qeîõÅfúLΛüúž”YÒ a*ýª­zòÚz»ØµžÊμõ ¶;´8î4ß]Qz6±•܇bhüèƒÜáA/¶ð·®ÐÍ$ˆ˜Ô»éeëø! Ñ_Ù }¡íæ/%3]a z««îiÀ·Æëe¹µuúÖ‘ÎËŒ. +²°íio®2Ëlõ1Þm³$U_c]ÚQï6ïuÛÖÇÝÌߎíU¶£ÙƹýûËöƒ¹ã÷;ÛOxèU2ÿUä§p@ó©*}Î:^ÊÑcCplGåP· é§«« ß®‡ #®ùÓúܬ_œ'-²ûÇï°NDÒЃ/•ñpÙ¨]¿¯¹+joÊ” ¤ åv7÷ÅKA½åz3"‹¦:$hþM£’uŒ%}?87ý÷l;ÿ“uÜÇIUM*0V$LBŽÑbÚS¦{]# ¦(uTÕ¡Rï¿ ¤uNJTXEiÌ'.9c3Á±Éo3,)ÜOÄóª6nöµ¬ñF1Þøåâà½I²ò?./7t*3›Ö#únREϳ¤í’¼©»ëЗ÷F/".žšRëI«S?"…|•‡±¼ê!êm}<¯Ðwb)_¿%½ÎÂó1ó1ÞÙ™ 6øÈ92ñ2Å®ºÓYåŸË¬ï0 ©z3‡Ãâ(röòéÖš³g:¯*ɇ&KêYÅ3Vh„6³ŽÓ(ÆžFHõ‚JtÄÑÒ ,ž èr²BNƒ ŠQÒ{‚Rùxö……¢>Ï@Qèãéœ@oEQ“¦¬©6G-Œ«¬8ÛÆüWÚ5÷Üwv€û½Uâ»ýPi§'„mrÐ65‚iëtTZZä/ú«I"Ñ…æ:ë`ÖüÛDP½Í…|v?¬Kùqb$‘Át È{§lÉ ùõ"¨ÕotuZ ‡t}Î~n†J·Ù­£›Û¢Åñ§³·ñù\ncÿÍã¸m$º.oòŸÀåá$ÚÛ~ûømÈJO[¼>kýÝBé )sŒnú+^ñ®VÝͧÇ>Íë·¸û¶Eí÷cÿ´ïÑ¥øÆ¸Þr¦+èe<½f)^=ãñ#Jð0wWBÔAüó¾@ß:ãBßäçfã dkö ¢æý÷X‡`º4ªÑͺJ &61¡gsªWÕèÌÔ¨ì*ßc‚¨&ö˜çšýCO“Îû2ˆ’[ZŸ='(â Õ)^:˜¨åå%ÏÃC¢Ë¶öÙ'v”"\¦^ºÔ°àÝzC)N%ÝÃÖXe³çe¥ê÷„c65!g\‘Àe×ÜÜ;ÛÉè Ȇ2ëÊ÷l0jêÿª¢=ùnòæKím‹.»–~<,‹ûóùÁºùŸÛs¯æÏýë•ÝUÛ}}<ž7gËdŒ‚Úß-8—6½Î‚måvªkH·]eÒÐcŽ ‚VfUÎ`…v™¯GãÆ uÏ=¬p¾ZëßÀe^o7d‡U[ãûIBììO&RŠñ„z†Y'AjÏŠ0u°ÈKü-… uÒÝÒõL$—P^«±+-õù(æµðœ!“Ž˜g5Э3‹FCwµÉj6Ñ´±ˆæ‘ÂK—ÄæEßÒ+Nûƒyþ¤\KãQÉJ‘®NýÕ¾e›jDoO¸¡.*„‘•Û:¯*«Ê0?hØÏÜ ´;’©„‹ª4£QcºbQäm¡É3{àTER®¼i:„² J1BX0õóÓC•˜™u"º¼Žn­µ¦ô ÑcíÍ:·Èǯ}äx’Öü ‘BÕk3(4C§øÉ„h¤‹P 2Q0,œYmŒ÷rúnñëß×ܶaùdcWI×!ÖÕ’+„Sèט­úhÅ·!}"Ø>zL2¡ŽBîIÌÛ­ ¶ÂϘ*ÇdkHÂerIª¶LP)"¬`¤“ã¬ÇÌÚ©²iR=‚î:öi]_›ªïY^,”»ÕJJ;E¸-©YÛ£*ã“Ô)tTYÑû$ëý%E;¦ÉßÊK‰ÂÍ%ŠÆèE˸G5*­/ÝóñyWmÝ4ýókQ´?ŸvÍow„­­Ív˜Ý¯¼W°Ü#SV_¸Ž BeÙÑnŧǺf¯~ùòÿÐû¢g-qÝm!Ý÷4ÑŽ£IÞ!2ÖTLÕø4)ÐÖ:ÊK{µÿf› -ìN… …Ôà©jŒ(ÑõßµQקȇ™ŽEXz•O ƒy±/ôt p¦Ôu´â¶èÜ)åÅPg%bQ óC›µgŒd³ç»òÞì<Ã3û{½ù¨†Þ¢ÞÔ»Ùvß'ØehP§hwItvÙI4)Boka«O]"ø)ÐetƘ»S3!WYw¬C0ÙBY03V¯°i¥`°Hß=ô&[QæéµùG¾;7O/ßÅçûÞˆ/±ž¿§>äIÕ7‰Š§~Ͳ˥™Fo…9òø†Q·¬­’zðÅP¥Û;øcõó6#Q×í¬ŒÔþJHãl|‰bÏ}Û «‡M\_êêºïóÌ•äjM––9ÔTá®"«C—-/±q†ÿl‘ýÀL«Q–üÐweì:,'F7g‚ÖT1Ÿ7¡)¦Pš6\®2Íû<©z¸@àM9oq3â¼Å-÷ƒö>æÕnÕß¡¤Uv…(*(ã®dhküÐFI~DF Ö#ÊØlU¯݇þy"½ï>,îÍãd³ õû)®¨Mú‹S[¤•IºËõTm—ׯwæñùûëÆ7Ù¸do¡{»ÖúÈ“Ÿé`Bk`u=ýv5…°7xèaF¡´!tØâ(V”yÏ3¿Aé.ÝTvŽ= Á±ÞØÌŸ#Üm»m®›·‡àÉj³Bf£÷—4Þ27cXÅ»yºmú“F–5&Ár¸0+j_CÝ !»CW6]rñhº—ï—zk§§¶6Ñ‚T¼òT‰šBÖ ‘\âeÿr£s«œô¸=Q·6W ý8æå¦¢1öÿ×%XÑ=ôcŽà×ÀP’B_y^/´£½ÉÏ™7‹dY7̽×mÚ‚gÈg´µU¸»sª”ˆÜÃñŽÇçKó‡€`Ðmt¶ì&¢Ä¼DÛ cÆ"®ˆ1ÍùU‘A®¼K‡ùªP/|,á…i¦6#˜ÔÓ¿AѼ¼ÌLšv^vÓišÚè ½fŒ&„̰79ûºäiICs±e.Zqõyq#kŽ=x…‡ò§Î’ÀúÊjLFƒËºJ(aƒ½z/g¯“fÝ®}C+Úú©y[1Îü·Eg™í¼°»¤8}V°êqP…ñ§Æà¨JÚboÝ5i9 SPšªZO±íe¤Ù_r•¶ùC Bq¤–ýöùùØöÇóv}S]Ÿêvgàý£ŸQ;…äîHë)O1agÕ´™î·ïŽÅè«×¾Ç–q¤ ÷¢sî»Áe6µ+é(‘fxWÕWÓ: ëõd)H;…qÓÅFù–Ü×Çòݯ …Â-/sLƒD¯êICÊxö$j[hHœ›®ž•_ðBk±9c¸«<Ü™&ªB_‘7JÒw¾¼Ì~˜ôŞϿìyì¡–M϶¤}&ˆVá§–•­ #ýJUì-?vÍ*ÁÇýe‰§¬©ø<5-ë#«Ù^DhnM Ó;ä="'FQ‚®\l?Źܮûª£xE°u²¾Ók†KJVJ«é1ú¢bRL†ý™ÖtÏ•~ÙÁRÖ/˜­}>bWßòöùç×u8œ5¿0o¸í¯ÁÑö"9õÞÞwݱ ³ ¦²Ç¾Šk6Ùé8­oc ½{²ž›Šä­é–=À%f ­ÏeG&²ñÏ˯û§ãJ£æþXA"}Òýúüý©ÈwØ>UÔ—¥ÇÚ™D+D }X²k N­”´è »I]Nžž=‚ëfݬ÷Ð",Ùú»ªý„}¹Ð\¡ÙŽ(û`z.p;KDg9Ûú[J~‘:ýñ²üþâD{!ÿ?ÊÐ ª?È|äïoœn‚ŠyB.¤xPPøÓÅ9–„Ø?S (R÷‚y* «Åú¶Dö“6Ê1#œ¯«Û„¬ P˜-Î,èÐÚ@AœI]„öÚÜhMeUçáê“£KLúJ}oÞ©"t@6UÁå»Ù‘VSý«QÖLT•(y÷l$þó 1<3©ùW•õ7æû×Ö2E‹Ä¤ßú¹N3³wgK‡Ö@]¸¡J²4¨_ÏçP»ý>·‘Ó¦W²è“–MOä|Þÿ¤å¬¸Ña }ÈTàçÕ SVÐW‹Š~¸”¤Ó¨Ë8!¿Ó³¥ÔÂÒ@Á´T)T\u­³R·F¸ŠË Oét#”tÑ_Ä.Œyþk®‚ÿzdæòÜÖIB;– ÜKüoVkîæ„Ê-éÍ]VË8Dï¸5"Ö¿¡ëAÓiû»uGç/ÕWDØcQ‘ÑyS•V®r‚È‘—…?OL¼C‰ù‘­•´ °ç>ÏhPuwÍx° \ñ`z®œúøüzBkzž¦ÿH{éó)àŽÆÒº ‚£ÏêÍN‡Ð¢_KM€ÁóÜÖ½›ºôêŽ6;,7”ßt­ìWô nE³ž¸À±Áï[_³öÏ»o6´Ã|y¢ò:îMØ74½ÿÞ³I»Øf|0ÿy¢žBûZ×I&”œ.ÏQÏ¢Ñdr‹X 3×o³€›ûü•d>TBOËíy¼¥64¢ Óy£Ê¾½Nù˜'ÁfÎ5†©ÝÀˆáûš[9JeBÔªhþÉ,íf8;ù5«‹â’ôÆÒ^§}BÆ»N›ž‘u¨Ò®/†¢YÛÅ¡´/RF›:y÷×^ç6íD¦PBíëŒ ®x1ïJׯÀÞÕXÞÕ^`R‰ßùÄ/!ª•¶—)Uɵ¿fyÕß?ŸÖüQ(gÍi߬)KŒÊkI­Ä™èíè\Wôî/•âXPYÞlûGÜÔ™·ï™âߊ¶‘ܵؿä¬Rn먨G1D*q£Ï\÷MÕÄ̤ô‡ß?nƒ›Ÿ“-¸ì–îÌžë|„:ûÏÏû¬ûånEÉ@³˜jÚUÞ]Ë.«õ²uúSj/¬ë¾³–;kº¸—_ b™%×åI¦Ø-PJ§ÅÚæíì:S²ÑÇ2GòÎõŒð‹ÂP/râ©Æ5j‰Æ®Á9…u”¹* Îe³?5ÁXrÌ17YBÜ”ôw\)m3&.W…'m@® Î?|™d§NÒc§ s~NøêÓÖ ×Ý(SÑR°¨UGg+¯©`9u­–3?nĦ3àTg¢…ì¼³Ú Œsã*‚pĺŸ)v¯k-½˲ﳴ/lˆœ'?ßœÅÚÿVýÒó¦&Î:¯Ò•S“à`­ý½RŒ>–Çâჩé÷+?ä#‰Ûv¿½ìTG0ž­i eé5;îcÜÉZËFnò½Î~¢;hL¾šO00cÏ¢ó¡Úüv'ô&Æ1¦â"à†Â0Ê‹€'RðºaFÇ×Zä¯m[(ÈF“!ec¥½pºi"×¾º6Cs×|{ŽkìÿíŸüíSA|4KÚQP7bdö†ƒ™‰n”0Ÿ 僪Sͤ{üã)˜rûØ={Ú®Ïcìõ#nV9ê.žåîÏy}üë¯û<îG,7-)€§­Úâ½ñIή˜"lh°ró×´‰Ž 8ú©P¹^XM²¡M ù¤*qg›Óm²çhNCH½—­ýB¨§´•f”˜*–(KÞ¤*#æN0ÃéÖ©°]°O]Ú»jtäÇç÷5·ù?oŽ9Í-6)ù‹–É_ì)Ðü,Ø™-õ“é½P›2P 9ê°ÂÝ©:AùÁ®¹ƒXh)JäBslð<¢FÔiDœýù2úô÷ÏûnbÌât¿¹)ó¾€m@8¢ÛÆ–-sêÆ“Š­àú3áë¢7Ì6¬4$ÑÐo×ÿ ‚`BÀìÞþ;È®‡©,±}{ZMb“ e\òU0Íï±Tß°…e-é]tÁêŠ1få&y¿T;T&|,`Ö ÿÖ äѺÝf@‡ e*r‘=r aëÄ›·6Àyg×ÜlQ£whså1:ph—$,a°Mm»æqCÃVrqwÉA¸õØýR@L«~ðåü£CX×ÇP]¡ªjUyӂ˦Ó1Á(9os!Š%µà­ë²¶¿üÊÂÇb—S#ewõ[©X¶sÞn®ë(0º.®ÐšU<Îk]1 ³uaò¥ï®—ÚãÖ¶üåzÓf?QV#ùš£ÊS«›Ìæ z‚ûº%SFišé§ù{w­“²è„Êþ¿®¹µV^WÝê4 Möþ–6Juæf¤üª”§ ¶™Â²?Úù¾ëœ¦[ż©\Ým A°ý ?X‰h~œ¬p­Çç}Ó¹||Í»yÆ­vqÎÉ%×ÖëÕêM\ën÷…°D™uÁtú¦yÏZÿ÷"¤—Ñ_­~HR ùPa_ÂȵØÔæ*f\*ƦœƒA)¾(êÖV(áÉ VéWXtÚZž¥EZ |1Õ•B óÙó{¯~‰Q}ÒK‡wDLÄÄÁÊñM…U.Bí9­‡A]”&-|‡¼vZ¹aBM ù>Ôn¤ä‹ZÊ€½‘¶@ÁdÁäL?úx€Í?–8Á¹}<,Z*ÝÏσÆò~˜•qDŽÅ¥g©Å/¶­¢X¤jɥ͸,Ã|CE}áUé:ÅK_;”ì\4c:¡SÎã9¿„Cî·ÈÙ×(´¿!ÛÚÓÙÝFׂo×Ûç__·Ùü†áUW g_eeQ†1X×@‰P¤VuØÎëç;ÎÙ¾¾f-í?!W]`²iöóØ\¢)x9µà¢ 4|S)Ç([žéîâ×½}ƒvóÔÑ4µWèôä >¯Âìÿñ6®¡_§ÍW®)™ À lÛ$U±±£uÀ`2ìlþF¤õRÞßšýÞ¿D—W“³è¾’lò¼/ú^ß¼A"Ö˜ –Õ‘ÂS®)Bž£ÅUå5ãn4™T¬dE;)L ¸¼ÿjWÝŽÖÑ^Q{`t¬ ’e΄…‘+Cd̈õDKYá'½¶]¿/·ÿ Ú×××w Î,_V˜ XýV q¹K’Eò´ô)ÕLȦù´ S%C~>£ó²´a}~}ìc¬½Ýfw£0°ÉÇŒ½I¬Ü­L]ts,u*կݵ¨W¸ºù]FTÍMä+©½±÷«>©V,ûÌ:¨«yÞëšÃ¿áĉ@³®²C¥£ÚTf>ã}¥›“¨¤‡LÕ`çKj/ëSˉ-‘Ì#Ô°ýj?š¨åôíÜ-y µ09\OáØýÇœzÞ£½„Àjg*‘5¾gŠ:Á ÷´Ì³ºÇ«Í–Ò„ˆB¥›äP3c †Á£ÞqP)—ÖÛ‚»½.òïûã ŒØL_‚=aû¿ûÃ\–ÁQ·ã/+Ð8±]ªÚí6¸S ®~›uqÎÑY¾65 è¼ m&E“Û÷Òû c7)§#ža|“ûí%&†¨ž‰á-q—Û“Èß_î.gAO‚B“¥2{ô&:ùXI¨È°Žu8?OÑ<›˜îB ®ÐÃa“zïžS;Dç;x!pÕï}i¦°qž–#~‡ïß-¸ÑŠ:¬ÝXR|á};³ÐEÌÞª qĬéý¡µ­À•ãÁ6B‚ŠþŠ,ì@$,Ì®t†ù‡Ã$ °oiÐpgh[³[Ð(G›ùzmD\ó¡é"#×vêy:ª,„í(7t¼sýýœ¬\\ó†1ØHsÓ”ß7~J¿ìƒ`uv¥µîU aH”3„ý< Ä-ì…¾öã¶à¾¿¾¯½és¢TÞëÄØžëÕ°NJø,ËÊTáÃNÿA¶}"ƒëEmgD˜l^ÿþ×~ËvCCéãq,¦QMÁ:±Ó‚…×~Xn÷\[»6¿‚Î/Ý}Ÿ¾5ž ˜±Ñ…¢Úòg1–¿tTmä1ù³žærU¥·ìÌG¡´Á7-äõ¼v¸ª © c î*4€a'Ó˼À/ÆŒÜîŸÙuœÿü|ÜŸ÷c8È”Ìï·ØUÿTm|gMÃúžËm}9k²“5´ý‰K ¹ž¹XBð‚yÒ¬cQ6ùe@>Ýæ£Ït…šb„H¡ÂÝ)pâ íT7c_6Iݼ—Æi'-ä$¦å )ž_PŽv£ã›¡´Ê÷Ïç¹ô´ËnôY5­åfXþµjâjœ½à쵿N·å¦bSÇ¿-ZÜ#ªuN¯I¯bÎÛó÷nSiW+›©÷ÌoæÀs°}üÁ½~c™ç£Ç=|¹i*ïÛâË ‹»˘tmzч&Ä=)÷ºê×B™l0úÊ®d^¼];Â: ¿9 ûã1÷ø GMb>|| û¾¦J Áúîùõ½å:LÃþwmÝXW|Ag•‚j×_Õà[ÿÏ_톩©bÝTW?øëµý#ÉG!uÕbó|(Eíæø¬*ÌgWìj¬ÿ(¶¶‹‘Ó÷_Yë­é C˜†ÕNÇÎú«U;v5|Œ  ©6¯„¶PMÇ×göGÓ½ÿªêwö4\Þ(PnÃt>”•ÙÙ&&Þ[¸èø'Ê}^–ª+ùBÞLÐo’7ß¾+û~Üô²ïÿs ö}Í¿[p¶ì=ÂW? Gûª@!²¤ ÒWUõþV9RÊíü¡Ú{BD­‘¸ª>Mçן0ªÌ‘m«`xŒ ?xê“£CeÃYØZ—¼BþåB¬<ê—b¢{ö^û\åJÝè"òÕµô‰é^ì¬Õ˜ÈÆ®,P.ºa﹂héÊr“àhLv¤ÖiÏ<[ÖŸ•iÇý6¿¾ÌŽáfÊM–¾¦ÿs{ê^Ì<·Í$—íy «m+/ÆžC"bDžÊKd\WÀÏÚU‘ÐÙ‡òªhÙꇱ™,PÝ@‚d²Ì­ŸÆ¶Ò¹Þ*U±Ýž[@¼*LzŒñ…kik\U¥læ\×}Ö§VR“¤¿Ê¯c6eô¬ŒhiæÍhÄnTá™3d­‹ôš¼•]š„í=}×:½ú¬‡´ëýåÂZMП|=h\!»föJ·cø¯'| ¬Ó`J™ÈJòŠiHªB2Aía쑠ПQ ËËòš*Jé³ ÓÉR“êèvÊòФ¥Ïu šePö­S„tÍ{C“æÅ%lpõ–*o°ïÁ|;ÌÈèoz4­UmµœþUS4«÷[•îpâØìz}™x3]4;Ö‡VëmÜïV|8³HXqÇЇ`“õ™ããqY/l°Ïƒ¦Cwp½-Á• sp¦JÌÇ>rÖ+[\P3Ë"ÎúH.ÌïÊçÉxZŸý†Œ¾‘Ýöífì˜}Öq|=¡³ »ßg‡¸2J/¬ädÒè˜+«7h"ƒÞ‡í6FË'½gAU¯'¥âfØêFºÒ­-áaŽu˜éçbMÕoÏŸ=zôVzBl0ïoçíñ­D{;bõ³õX]®(#4FM¹ÞÕÑ%½Ôú)¦lSg9&ÈTßÊ€ÁTȇ{תœùµl£Ò<æ´MR xʸ>MY¼¿×P-ù¨æËÁÈpƒ«YíP>Èòû˜¶zWZ©Úü?r?÷t臺`«ùeð\¹~=Àò=‹†øÑäºÞ¥êßw¶ëºª¼T:} š´-â¡AÛÖh嵊ÜJe;2Þ,ž,ç&*Ö Päè7™gÈ¡]Ó©½\BêÜæ’×r»þDÛã¥wžcÍëìK³•6ýÿÚz8N5z>ù¢WäËóÒ ¶¼SÛðåàš¯ß=ˆ\È$ëÕéUû]±ÔèBª,š+º5•u@ÇÔ»ô’·CÜ3ÿá.TÚVYþ¸)Cì›>ÕÑ6¼¬&йÚI Lèô<…Jº·_Mýó’é‰ÓÅõÓ¾OúäÓ´¸^«.¡X©¹iJ¾“l IA”VA™¾)UŽ`G1ì¸?\òæ}“:´£B®pêû¬§N ’;:ÕQŸ]hºÊÚ¥IX,°ª(×Ï×./éµíåŽûbïû‹|¶b®æÁ ýùÀOÙþDsé1è¾NŒïi«ïF}5f¢™òë·%–p±±¡ÒƼÀ”:ëÀ ŸTø#§¬Ù¬ë@É;©˜0µh•ůîþþ=ß4{0§Þ•X‡†a QØ·(¶·­m®¨`ì;Ýû^9Q>ñ»R°™|šCª«÷•S8N÷çÝ~ŠÞölkf¦[œ‰¬¯)ô ósYTC<£Ý/âÓËu”©,ˆyTˆ€‚®[jµggc<‡ $RîÕ€£*7šm.O³\ñuÃHÙ!Ò´Öí~ŽÐâ¶sí!™†­Sb@÷rõ ëØÌ«sÅÑ 2ÔMLX|{õu„‚X蟃PqbqáúO$Ò4Mp½¯ë2W%“§B0c•‹ûSçÙ$ï]I= WyyÇwmö¨³²äq^†ÂVêt—è`ÃÇÍi¢ÆœÃz¿¾ækò§ËKj« *(Øïãh 2nmÙ?‘ |ÜçNøÜ´Ç™ æ‡ùiãŠ(×ôØÕëµûʯY’]ô)šÜèÝÓª,D‘ÈSq)•+e(•¸îú ÙÉÅ€´PªÜÀPDß¹ÍJnôád~ŒiîÇaÜf•zqš¦ì`>…3Ô×¾›ÐJ'ùºùõæü[k]:}VMtJ(òüš·F†ã>šò\… °9ëýU½[çÍ„žŒ;«!öY×§Ö«šV8@N-áZ³îÐÍÖh3Rìw1 .Û¾L:%Q2¸V—_~ŸÆþ-ød¬!s¦ÞãûÛûäzãng X i™´épþGt¡-=š8j6*1ë4¬ìUý1ǹ3¬©ÍqËŠw¾ì„üƒ[¤ŽëZ±Œv¾>4ãÅè†[5¿Î×<2.\g·íqó5ó¦‚ýMÏ/iS§T@°îÑFnYà <9¾<sQ::áóqjˆ†Vó]±‰ouÍ@ö|-®œF‹˜!ùÚRÒýmÇ—æ4:av³OaÓˆAxôÚ*:%2I4­¸Ný²Šì`\¸ÎQkèe·ï›ÚS+«lu®=¦}Wù?s…î ƒNUÃE]—B%ÂÓ£¯’–½°=‡J3‡¿.ΊÌ…Éà”ÆZsëçf˜wfÓŒ©§@@žTe’Îú±åµœÍàÁdöíYvV"Ô±êê,mõö NЮÚƒCÑ÷YIÇHñmÖzOç’©q•Ví´ ¼º™2¨*3}ˆë_¿§j~üysõòû±MÛçïÛ4LÇ×_÷îÂà\·‚ dº7ï3†üš$-ö} ¨Çž0ÍÁ5s®¹à(v³Jó¶IÞI¥ Ám®ÌrŒ4¼ê1dú¼.ç50M›¦åÇïß¿ácÎ^i¾úçÁxDµ.<’eðpœÈíóðC.ߊò‚›VžÙNQ…¿7t@Õ8E¢òÕtPOAï&oB^²“Ö^sœ •]Qd NÑ2¬}ÀŒªR9[ôש€òœ©|b:Ûƒ1nDTW¿@uˆºÂp³òòæ6¼g¿÷q×ïþïk®j<ÒX¬EŒ>dÙ}e‹|2aãu¯Æ0°rØUkRÉ&”ßä×ùî‚ÀÛz[â8›÷Á¶nÓ]îTUW-.uRµi­8;ŸÛññùEãšû}ÿˆ…º]|«wQêà'žŠI“y lÐ3ón>yzýÆaçÚC~›¨È¢À}”Tú:>>Ο”ªë\ÁL7š-¨Î ÒÍII%ŽgÞÒÑW’鲌`ÌZÝ™Z;÷„ÏÝ%Ö׈`©Ãä®Î\´ž\þÙöÕ^õ–/¶FÄý6µ³e‚òý*°gÁ6ÞÃ&ˬDXUÙ -Ý´¶^¨¦Œ÷Çó÷…}ðf“ÍŠn#ÈãfÛm´…†• NWyÊÅÞ+y;ÚVدº–.QÁ×ßž÷Çúç(döèn³ïvSu_ÿ¯¿îBb¯ýxnªì(ƒp·W’j&ºÙ!¥X’»É¯_¿þDDr7ÏzÝ]H;Ø Ì¾æ0t¦|Ì‚ëónéàÆÞî &ƒv“¹eóßÅ™+ìy7¦;Pª¢ÓÔ`%ì–ͪ2õÈ$©Ø­×É   ºNš•‰p‡®¤’^7ÿÊô’Ã4(e´¶ “˜0âôç¹yOš&͘êþøP±V¹Í¶_áyÓbjtÖçoØàçƒZãõRÏìxÞfDWV•ºÏuö¯¯­›ïþëkoß/Xòè¥+ršò‚ŠëV¸Ý½+ßn« c óas™ânòUfO®Ïyp(á§Õ{^é.vƒ.‹J:=%]˜K„‹v¸\3¥7vN3ŪavÏi¦²»Jñ~é;AwôHTu“ýÚÌ–EdLé-”(U"“§¦tTülƒA9$qv—JOá¶ÿ»6qÚϸ¢ñÚZfŒ@‡|1]½u\KñÈöµà<|~Þ—åöùéKÚ¸‰.ÂgSÊ·i;È$€ `⇅ÖZÓ–INÏ”‘Žk‹MO])¡ÞÇ×§>pÕåŸÏcå’³`þ¯ÿü¯ÿú¯ÿü×___Êò_ŸŸú3qÔu>\òÚ©nFæ' &Ȥºÿ þóSùÓF÷%“ÈÖ¼éÛŠm̦™qUgýK8PŒT[ØÚé> ~±°N¾:Ö¾ÖwˆnÙæÐþrÓ™‘’‚öº-ç‚U›£FÉÈÊJà Aóïôª‡#)a˜¬®5\W7ö ®¹à¾‘ j3¾±‚]!¬²Z‘Yà`ß8¯ÃÅBÏvz…úáX8dø(UÌ\`/ÔáM¾ê}ž]ªJ™×gI^ϽBÀÛ;®‹z¥É4ê&‹Ü‘ñŸ:ÀNõ3"Ø3S6oU)>Y½‚‹ ×èÛW‰P<e¤%ç¾ C”ŒQ6U¶û}ÿdX÷uûøÐ;×"zcî6·Ï­k—÷ç×s,¿TéßþšïÏ £„HêÕkh…µ}“º¢èº,­ò>ŠBê0éï%^ì5ªíSô-XöÁ9“«- K°†ùòõõdW"ÕP&eú^Í eäÁT÷ï´Ô׸Θ½ÕÒ Ú5ìÀü¼–uV Á®J(Ë«äZbJ/àÔ¡¦Š„þÈø³Ä^_»¢I]^óZ™Ì³º94dò~÷ ‹sNO]Ûž~]f® Ý„ŽÆQã³7 £~B›ЧeßA·£këÊ÷êÕ}Žùûš[0D$†öØr^Öf–zSŠ*ˆJ6Í ŒbQÇ­›©“_Óœ¤B“Ðð”Ò/”ÙÛñT±÷ußmq•FèÀ÷êY\ ^Õœ¯¯ðÔCÇîýÚ‡Z`ÔíÞzz~~š¸Äùüýññ‰{ÛþÍây˜¾³ê¥ó> }uúÀ_ÜŠ³ç¨ã­H¾a[¶¯ç¬pÿ¡Jÿñ!X2bd¾ªŽT™. ¨'Þ7=\&«ë˜ÛúÐŽâÂ>5DCˆ&æq{ôAŸ ¾„ùú͘Þëš³ž¤k~ÛéZ )¶k .&Ǧ˜¢äáf`ëF£,L+T.áÖßg5ü>¬Va‚Lw­åÂ÷½2€Õøÿ õ¥_ôép-w“ù³)ÅÑS¯ûâÔ²á›eszM ¤(ÑUù&Uñ}ÉL%r°&[;|ØóæRª˜Íu¾–ãñ˜+<ä”ûÜNXöÊ)}—- ²Î˜%M_%axËUÊÿËí¹÷Óíã±ÞO=¸cXæã¡Höû¼¨:[gslW@wJ§ÉuÓIׂ]…fÿºJ{ÞJ_ÁmTêuÁ¹Õuõ+ ·½õs·rbQ÷yI _óqŠK&­žq•§™O®v™-»By6 æšÔúîKõ®Úïò¦WëµD¦Ç‹z¾{mCkþi5ÒÊ|fŒvæ ÕˆBA<7sÖ:I›úZŒUázý ¢!Þ [äÛ9`7Á"U!´Ù{Æô¤ê{šÐ!ŸBL1>ý`š< ª*…åf²Â"™ [5×´ël…¢âw„Ú¼®Š¤ì…öÿ(žªA£-3ˆÕ¾hâ ÆˆÊ¢íWévÇ¥†›bl"èÞœ=Çžäu¹ýõ©²¼Í+Ô|_½ÇÝ* çïíó¯ó6¬÷u\¿?ïû€DÅ™@»Îì„ÍÖblÞ«¾NK¿£z ðÆÂ¹°ò¹’¬éH<ž6ôRvÿóã¦K~ãœ3™ÙìÂÐAQ²­êD:bOÃþñqƒí‡o:ó$õ_™Ð#>Î/‡+†¨‰£'qÞO]½h|(Ð.TZQd¡fÊn™Êº^Ù }þùÐ ŠUNôR;üvŒ(¼Gùy¡Í\¦ÕÈÓOÂÄ"‡*-Ç ­™Öñ`¹Ñ áÙ ôW`7ò ‚†ësÎ.Y'°. Â<)ÐXšƆ@?ñ$J®ÇÆ ó;›Ã5êfôïc…â>΂BOm“æ—”'­£ šÉ¡Â¨ZØ!ݨÏO5»woÅ„ÖiѵYêô‚ ò÷wÆïËhó?žkY/Ag;/ÂPÖ#‰Ç¿TEB/C2Oñç1mÃpÓöØiò!z7Y#:"«r< £]ßy1'¶žï§Rîû…Ðå×ròI±fc°µt€Ë~Q€ûi£ÉVHT8ÁHÆÚxt¥®C{©ŒŒ KÉ🠋¬öõ{÷~oóxRÃÛ—jï<½Œ˜ÈBFÖÇ pÑ:ºLwðš[…V° S–BL*ú:Kiè”[&Õ,b°à„èMÑ(̪|€ô17¸ŒÀ/ãR¥q€ëP€¾Únrײêð°>A¯¬ì*óa-AecŒŽÄ¶°`5PM㋲ýoðδñ¤¤1ýíó%Î<þùV¾ª¦-J Þ_su®?¬?,ýlÇBɉ½Š¼ËÛÁŸý_ÏϯõyûT"ýúýqâ–tÓ3]"6MÒ1ìv¼œf¥Çùi²®ª¸LÆY—ûu͹å´Ì?–v÷¸ûÑ–ÞtèóÐZe©›8 '~ +|]óC‘á~W5ü]»ª`^¶¶ˆ™ +k”2-®QÙA0ma-j*­Á\̱{v¤ÍµÍ¶Q[h´#8p³4uÜôgÐ@¤ËU[·/2ãƒUÙE€s¹­ÈSf¥)$54Äm‘XïB5f—0¶G_±êÓ š†Œ¬/ËhËÔ¾½)ëÑûg6!Oz³p¨éDöe̓®+ÅUx¾§¥ÎsÇ‚¨-2›Øy‹¢ VºYgùʵ¦I((ŠžJâyÆCäÚ4èé|}ÚáT~?FðÒu­¯Èøv%;ùµÊ± ‡Û ªö<×ããÎÎÄq5^„TPP$£"»Œö/ß›­Íow¥ˆ©o7]é…;¨Âtë“l¢@ñ`÷ð|~‘Wë`DÂÐû4‘š2O»úÒöM›y¢Š¶w­®9MLíØÂSœôM_ë×?¢Ú<Å}ç©Gë­×Í]É–±/”]ó¢¸\r3GPu¯-e'Þ5¬ï ´¦é–8¡z|,QißÓ:É^ôÈê~ñ: eXEE÷ÄW¦$Á•i+”ú^ÒÈѧ–½c…W¶]Á’¾>ÒP².¾³>ßÂÍGØm[_s´¿gÒ6§¢yh+ÇÙ8Õ± –úño‚0bQzÎçóF³9¡ PUï¡WåS¥µ/ý:ê¶ËRŸÇ}U9vSä{¯“ªWbö;ØÊJx­^U¥éòmG1öºÕ_ó›MYQƒ<¬ÚWÙ= wHìòˆF°ô‰±SÕßþŠßÈ–ì¨.Žqj…Yû`ÒÊJcU™à´!þ=î£ðÆÍq…›ˆø=RB• ¢¢|pÃP.Þr¸3²^ûÛB³@¥H%ĕլΔ,qåM•^2‡œ˜g±ƒò¯£Â±Qð#™ ‚P˜÷ÔTbWcǃ¥[òõWuý™Ž;5©œÍ–+8Ü÷Å)@õÁTO}@EП^òšõöš§ï:7/Auc¸ÖýÐ ¸ü„9‹p]37IWëšL—Û6N?4Í>&ÍÈ8§§äûÐŒ÷Y°µ3[Ö@kW‘±¡ÿж*sSÈ,¬ápT§FÊý·ÖÎK‡Ö´m@ýççÍ„D^s E*$Í~3ãY“7—‘tJ–.+ÏûÎfèyw:k_÷¥‡‹Œ"ÊkÓˆ-"ÞÙûÈ[äy¨Þê)ø|Ì.H6`8­«Y$*ŒŒ/˜1 æC°n?^Þk í<ŒBݤ$°ñ©Ð3®÷O–…DncqÉŠ$£òg¯¶*½Ëð_/£5¹«LÚÉ»£^ÔŸqlU)G ÛúUUXGSv}lÉÜÒ7aÂQÙVÕ\†rõÍz6Œý‘¿nÊÈnª]a”WFvfS+ý rÁÌú7hçñ€_ ʃ|ž_4½÷Ñ”dŽçKgb¿Ù„AQóñ„§?¹4õ8¶ÕÜúá¹ëáPV›¦®O…”׸ê aA»3s6èŒWª¬.\Ú[4ßo×lO¡œk~ÿûšŸÆyE2z$(¿+{ªVè¡Ç ÃcÊS(F½ÆFÊFn91Y»ðmCÞÓñøèúõddƒïç¬:À¥ïŒ"<•( Ÿ#ÔV‘ 7ÔˆôKú¼"ê{Ö×f=øíÔ‰MŠ¡ƒßý0å ÛMH@šÛäQ8F§RË·z™…FG¶w’’%?#_*ð¦cïj¡«¢îQÇÐÓý¾æÇ' ìqL¹ýNg •}¢;œƒo¥Ì~¹=! Óïùú8mPÖ"¤ØµƒËpßô(Žn)T$a¬0P<ÁYiÿ}_g࢙b{ãþñûÃh¥¤k“_¿GWc¡þk~Åûý»6¬Nô¦/¬À”ïfÐ`_¢êßyøê3ê¹Ø*õ uá×(?Æ5;ͬ»Ý®þ&Î.:—žYºjP`SG™ð–ÑŸq§žìb Nl¸îS–쮘’S­: x:›‡ëó°à2T×ÒV•JV>„$Ãí*oõó!2‚Ë51jôê`ÄöMö«Ñ+Æ”õ¥Y:¿Vêþü ÍX_Toû±ëæ ‡ÓÜz¾n<ÕHdvÎ*MdÙ`¡¹žÕè¿vi…9˜×ZH`ú#G¨¯nöú:”uÁJªiäê®é˜3bpÔBU+Ën,ƦŒ» @Œ¼§Í¥ìžÏqî÷½·þýkÛûå÷õ9™D¾qˆ·Ñ „ðž;˜ÀÊRCÆÎþ¶ùßÊóñÅɉç›If¤4a«µ2ê· _ÙVÁa,Ñm˜”F%† zýui”x‚<{üˆ¶è-cBÔ´ÊtBlÿ\Wœµ@_ XeײL²ŽÙ%ÿ Tz:)dU=ÙÀÐÊuÚëõasì9›~ï*ïÓû‘cª;óx¢o¶>‰_’ ú~²™dÞ˜¢•ïUŽë©·yÑú ÛN!Õ@uÀŽ ú¶ $æbX¸æÛü Ú¿“yÌi ŒÍ¡}lH¯ïÇ_¿Ù`ûþªN]]®ÛIËûè•Åu7Tí-m_ÏOAêg½ffº ³‚òÌ­í¯;röÆ;’ÞïÙoþ~Þ,ÆÜ £ßn ßc3î€ö›Š7ýþcgÚ«Št#\ê`êö]XMÆrþäm]?ýþT•¶=͹Ag§ “˜ІhrÐÙV¾-t£ÌjQí…€ Ä›2Ô¬­R£·ÚD;vÙ¦ýDÞ¼fƒ3H¶ˆÏ‚ ²¬P$ÀÌ?©Á1-©¾aA¬HZ,Ë€ì=žw¨_xsf§¤Ð­*¯©._PcŸºÍÔç¬9$ahTÚ `5¶×£~nÁNzF›~ŒiECÞä€D ÅÍkÞ乊/îg‘÷?U9ÞVAŸB¼O Œ ]®˜CÉ¡²\ц®Èd/»gºN¥y¦Aª)ßÀU__Â×öX„ vÍ¿÷·(GHì@&°+ЬÆÝ¾ËË¿ç|'ý‡Ü0’èÆã)¿ÇåÅ5J>‚¡¼êÍ Ë]sçrç+ákHÔ{E¹Í3ŠìW×Ofž¢Å±ÿø)g0ø~´‚@¥¿ï£H^T‘ °Œjë®5jåº@t2h¡Àl²ŽÂ*½h壾B̸«î P,ë1ä*±:ÓB`…Ü$]I˺²#ìW(|ERªä¾*ZùAÈBbr&0d b.‹¢ue £NÇöÝ‚»¿¾lO…þoHÿN™]¼Ûþo‚œÕP“5çéëùø°%U¾ÅJïªÃ.íXÎáøÐiÞ’=…"Žˆ½ ÙÃ|ŠnOÛoµÝÝ™=·çb9Õc«¿ypàï–Ìÿg n¿=mžQ)É霹ޣ#Çþú¸¨¿}«ºßoÖ£eˆ«Ów€]’ÐϺ2Yc”~¦ÁÍ<ÝÝûªîQsæ[ E#x#øu™×BkzH5ËU¬šxÍóŒÔ?`C¿rÂ{Hg„þ«@•ƒ-¹³]¯(QáhŽgÒ"D’5f(ÁK'¥ õ´¯}zul¬:ܤ&Š|·ÝWt-¯?[0Ø0{°ÉºÁ¦1øî)¥Ö™B jÚ®QS:õÓYŒ^XìP*ÖPÀÝn`Tç¥Ù±*͹¢ë°{ß–UeÇz$hÅ+,醘àOw À+v›J½]ÄÙÙtµ© ö4o«^Pø|Üã´vû6õX–B¶õµ2uƒ©z³~)íà¥pÈw•Í?È`oõ¾èP}ÞLsñÍË—9ª¤Ã~3*»Â*óËåjÎ’m…¹> &D8 ª†˜)€BN,W4÷âë‘uC]å0cöpU¹ê‰¤¶Ò±nÚõJ³¶Éò.êÚÒÑö†ÍÞ J 1ku0v? ð;¯‡ …ãm°IòÔYþ’:ßË·xmyÖe…rMáFÝÖAé¼®ßñÀþ£tÙ»VI&Ït©Ë¨ôÚôYæBQú.ãàÔi¢Ë@Ãfù¨ýíÉ8íõЉ±&…2n÷5úfÞ¢Úõ¶~=؇z|ýß¿Y¸~Þ•HŸ_'êŒçñçþª×uég=·Í°|*çÿþÀYó8?>þüóùøü8?oÇ;îÿR‰?ê¹Ùðó~lFfaýôÛÃì ÔÖ&‹ù¹ „z…·–A²)8¨<¸?m?>®œñº÷×5GÛ× * ‹àwÖa¥e–µÞ#@ÝëpatËãf‘L‹ð–òhMÚè~¬;ž½a)äšÍžõx§ñŒ#l Ý6#ù¬b˜Š«`t7°sø‹2bY¸…]rÕæ£c¤w¼™Jµˆ±Àu¶^™Ýcöë}Ý­«ëæÛÒ*©†ï‰ÚÒ$üg>Ç@W/=ÍýˆÑË,Šâê Û©ª­EiP††k4€ Ml(² -T’6Ëi¤­™Çg‚¦ƒòV0-;ŸUhú¨CTØã&ü¾µ I®ù5Uö¡mÁ|ÿuµ¿jæ¿g`.zú™¬ëí°ÑÁþ8z‰Ä9TUêJ˜WUt¿ Wy²í Š×ç:ÎQÛa±‰æ@g+ÏÒë¥Ç­Aë„ÎÖ£$Ù19j²¥MS}ÃÑw#*–7ó;ý1DªEl:îû¤ãá‚N6©‡]üvºž!{ë’‚©{’%49òlK/¨¶2FòS›Gý^ÅÒ'CØØc[£—¾HXÇaÓ È7µ£Š ŒAúµïÂâ¿äÍÅ»7¡à,RûÛºcMÌÔí)É뎈ªÏ]†`@‘&Û:Åq‹ÊÍÇ÷ž¹MËUë¼:•Û'õ¶G¨ù¸lŸëMyðöõç×Ë~·¸ôq‹·j±"|‹†6ç0¶K%?ÆöÇùýEÊÖ‡ÏÆœ<6رB^ßïøJ®ºïÔh¯ß²v¹I0Ò±RÁlöÛî²ak6_ÖB 7}Sîùó#ö»£QÌùwç^¨eETÂ7+(_'Õ\=fxQÏé Fzë`¿PíB4Ó˜Væn4tß_ÄÏZŸ[UÀ WýW𾇢üp>”Ž–Þü“ª®JÿåÊLGA×£ÐÍ9Yñ[æšùôØ]Ô~òG3ÒàÏ¿í Ø:7áQ•%Ù§(Bóó­‹Êˆªîðñ·sÁßK`KŸ5ì¸yQ_¸ášùq½ÏðuëÊ쪳_;ņ-`áu9=É^5u^LCfòÖÞ$»in“Ê5ú>«'Ì(V‡;J›d éˆUÓXs(GÉ›i*y¯~èátL¢±pa ëbcW©H00¡ ‚lÑ_x~ió ¹4[°ë®3÷K!NÏuBåVeÁåÝ«g`6Y)}4’Ĺ@ƒ3û“¨;{Ü®PÓP e«ÊÔ ˆÙ¨¹ó×N`]`#´(.ú³gúÂdf~l/ëk+%xaÜî&µÇêÒl^¥‰.pŸ«6¦¦H‹AHMÐFß±¢Ûá­ÞƒàjæemßÓ…¬¦&) ?GÚuM“2âL FoØUHÒÿ 3,H½©ÚèP#8H¡hzÞA _TK‡G%A›ÖÙr(qï/š‚íæZ“s2:zO§u¹Ty´[`ñHOÔú[sè ›¢ŒE»™²·(yÉâΑËùô}³à6ÑëCœ|ïús]Í5/ó^õ;*SݘªÞÖ—B;7«¹(uq’‡8ý,:‚Œm„»ê=ñ“M>ñ žUUŽ•&f­)‡ndh}èc¿ 5+)d_^ _¼e/Ñ1çÇMXwhQ’˜Ý%Âê*¨È¦÷›‰âÙ•UÎdSÕg£ âÄûó¡/ ß¡6pêÞ•K”QBS©^6UÞåã¬# ÚCµ¼¿º&öÁìKô:‹-aÁu‰é4k)rÙË»™_O´ÉNÓÐwúDÿb¨9Ž’#*Í@NxþTÆ6à/Ú’¼} iíÍmA…”}ýxÍwdãéEX0‡L3ë™M(XWC)  cÓ¦XΤ9:3¼på;KÈFQ!I((F ›Ð6d…@ d=¼œ3Lj\tš»NÏ¿£Å9²ÔÅPãŠÅǪ¼šÑ$µ¼ªªæª: "œÊòWýÑ]\:®“ÒàfF¶Oýºg¤åÇLJéŽKÓ¦í^Þu –ÇoKáÀë(ýz{éžTÖwÖdIþûã£í…þÑu ;¶íÕ6·u±Ç7·¡¶í–ÚFœÙŸßôÓÈøPTù3‚Ÿ–Ǻíñ?l„Gîk›]®Wúü °¢þùa9?6ôì ® ²nøwâ;‡roçæ€ ËuŽ¢98[`¸âë`,ë†ÅOÈŽ®xuß<:ýœõ:¸Q|XeÈîZ7Htj;f¬\ã¾–*ê>帉7¼(¸wC'`tÛ‘‘ÝÝWˆe´&C@/ØE1dèyÞ"ê¦|ݳǾ•ʺMÞÙ–bVé8µ½>‚… ‘®,-eõêš+)æ6&h”hT|´ÒçÒ¾*3K´z¥1¹¾¢.žÜˆ<œe¥$Sú§Jt^ž½AΟƒY˜mác“[\Ûò¶ŒÖ ºþ šcã"ÅnÏjù¶ÞŒóA£ MXK{ŸÓcNXÂýůüu)¯knÒŸûÜÛšžb”‹*ºì4 Y‘ò&¥æPÝêpTmëkm¨~ ›5OA>¥yo²Ë)úÊÎÖ·I?³ƒm„bý‘ÁöÖÖ¹º ¾ôMs5cæNØ®ÒÃmÊ·GºÎU¶¸©jãVÛk°É Õœ»f»Y`«\ç]g|X·ìª̓ÜÙ&Á<2Ö|`lVÖ¤ l")2ax©÷TùªëKóÞcœd«ã¯b6Ý¿7Ï¢¤žZG?‡êi²¥€ó1.ç׿þ|l±L¿?o1×ÞìžZg;† ~+á·c»ˆÝ:ô²OÏxÏ}£ºö÷Í$év‹fWÖ_<¾=–ìÚRX8дٟMLPVšÑu·ýüü¼S\Ø5µìn_óÄÙÓ,CGÓ‹¹Ñ÷P ÀÁ&˜€½¡1\9F¶‰çõëÒÏkؼ—º¿¯ùØÙ»§…†’WnªÄ~»f»Û­-v³—©‹zÚ‡jœ«ª UŸ5Ëj–ÁC Ý5Í)»º²#[>½¾3áÂâ7íy:yÈ6y©·+hØö“µ™T2ß³ÞÆò˜Ð2l¡ÒáÔUk]àÑõsoe4½…˜¢ÎRE Ô„Ê,ÅEÁ#`*·úB—…–o›"S¾õ\QôŠyŒhðÕ­£RŽú…`(Sm6¨ºÄ!Çï­4ÉQE϶¼86Þ›4k—mšŽo–Øx·É¿ž%^$ÓµCvktÉ¥U¶Á¦¾×¹ÑvUd3Ò©m:O:e“Î)ZâÛj—]Ò<£sƒÀ伯¨S¼ifÜò( {É?ß>“/о  „õî—ùƒ-TˆPfö­kÂ/Ž9¯|Šv'*JâúŠ@ ªZ­â g Ð:Ö^•‰ÈØöPm]ð×èO °fŒÅ† =ÖDø³8Û—RýUÒçEþ"j€R#šc0îOgì4Çl ”æ?‡ª³F 4žg„ìûËLeù62þÖq0¡e¿1§$ÊèP3X] ×-?LZt3Ýá}î–va2`šºÍÏYýûšÇ_?ÿ­†¶–þ=vØïßýˆލÀ«ƒð"Éᾤ϶¯”ªdŽ/ìöÜ_Ó÷oÐþ=Iøûû<ïž5øùeðCM ½—Õ€±°6—É»Ánû²³8F¯¼ýö«Ì".8 p“§3ÒõºóΧ¼R6ÔYôÞt•\fýHÑ”FœÏeû7â6~ÙëúDª ¨‹Í£yèÖ†š¢Îª Œ¾ß·oÐnE4= ³nbÃh‹e> <ÝbSX3 ¶ØèÛ_mgüÉÇçÏu'‚«†ß€|a…ïËýͪú¾æŸŸì±~Üž­»?᳂b.Œ[Û6#žÉ9Ý“0«òò«]ÛÀú‚}éÁÏ[—¦|ðgj“V]©](ºµÞr" ]º‡sG­î’¤ñˆí3úÕºàyŸõ3÷ªhc§ˆî5—^àäôÑ“yÙX÷Ë¿e$î÷ PËZÐlJÀx7,䤀ñ“›§¾+ÄðN9Õ›1{9fý2,°Õ×ý|±úÛÌ Sv2šFÕÄì²k­²AHe˜pY¯»¢¡Ù`,£ÈÒ§Î<Ôœ Ÿº@Ôéâ†ã…ª²t^e¸ÇV$¬Õöšënß ýåLùŠûÇ™¨Pa…GX¢ýùjÇîU™ä¹YºÝ·ç¡Zöx~™}Ü5ÁĬÍÓœ~tþ ÚÑÍâ~‡]DE:'@ÓÕoAeõrì£-(lë÷5gïCÈü5ö~ˆnSÇku ‘9F¬—_Á]kfs¶;Yè(” Ø1Q ‹îô|¡°¤Ò»CqxR¼ˆhÞ/˼ž{Ðç×uá[?u”oÓŒ—Up´Í©Ù‡ÑKÊxßãž >Á†9Å+Áä1ójðû '´oo°í¥ÊÂ&ŠìqaeÆ-Æå|·¦Úôñù%à²Ì¯þ7%tl}¿@u”§8ð@Åcj– zn—ŠˆÛm‹]s6Î^-¸{œ¢ì¯E‚xû a ›ÿ=8¿eä·W§=ܬ¡~bM脵·O«tÍ-&Ff$›×—.ù×§bÁqÛ¸Qm£¢/ÜlT\ê……‘ ûeí6¬Òñ|}©ðöó:¶Å4—2§aòEZã#ŒúO™» ¹ña…ó*­~nçR(â'oBfÈ.Ãkû,e]´iúÉ/Û…,G*À:û,~Câ}5´¯‰Ûl5™ÄÔ#£S¤3WõC[äø'&Y`Ž¡Š7ee_›…²Y”6)R÷ž;Ç K³÷k•][$m&ôô¡ØÈÊ•‰òƒ5ê,x&$ –g ª œ´.ͧîÚöpc¼Ãw —= Û5Ò¬‘s‰¡ —”er-š—˜ÊÐGmámû¨Eý"½† ²“~寉ª†r«$UÈIB$Ýx¶u„€Ì6E1ÄØ4Ÿ ½p½­×@ ê·Y8ÖÐÙ«¬o²TXè*ï?žfÃj’Åqïô‡ÅPjPT†i16œNH€\6ö÷Áa£ûŽ}2{‡EãJ¤`Ú Sœ¼0z2gûií°–a¯3TOð A"MOåíŸ×y? QUE·9¼!teËŠ*ìË:»â6Ø´‹ê|âxÚ¸,©a,òÂ;nð½GrãÂè@»­C§ÏãX_%øb iìOÆùkì›ëצ>W\|}Üà|ÙÂH¤›œÏçíöñazé&Øð~ÂZºÇ<êåÊæÙTlý³¹­^~R>#¯æxƆúU¶í»¶¶ãoD7}ÑVûüº›Ðyè—¯/À»¾ç×çãTŒúüs~>”â·Ï‡ÍÈoƶÀòÀùåP¥sêáhèÞŒ>öiPu;vHùeìú f³>ƒaYÒöh. ²qL×øˆÁ³6..2ýŒäÙ²7×6ºb­™ìá w&7+'×ßþZY%|OêìRë éFáû¼õÛ} ý~«Þ›ÑU¾é̯Ëy¶ï•0'Ô]¥öÆDãÙ›ôpñ”(ßßÝ6ù°ë€„ùvNU@çMƒµÒë4 CA€[g{Þ¥¾ÍJ_eù”¦K©K•¦`š¦Yžt+bÆZy™$¢«+­üÒUB0[]nb”. ø< lb™†ózö÷|0Ö°{ýoõ:oñ…¨.NAÛò?ª@§ÒÈ-DZX|]טˡ¿ÏV¹£ÝªJq…›BšŽØŸ'öe~½i±Æ/¦Ûvÿ}~¬à^ jèÃâ«v\ª¤DË%\ ¯B£ykñŒ®«:$õ¶r—¨dÀéGìÑô>Ö6e[|0͹qX‹¢ÎŠü—jܤ…αªh¹±ŸT5(s›GÊHÀ)T°5ÓB±5)«¶Kßò^qm4AK +œÏK•tª‰*!!áÿÎ*¿n‹wYY¤z’¹²–Û@ô¯<ív&)•-Þ…íX¾Õ„Œ•bùùe¸Ð!ØnÄtz;~½o]v(ä°`£Ä±­â© íïlËu=ø4 yéË´bÆíV¬õÞôÿÛ9VYÈ´Z¡m`ŽY¯Ê‘ë8*{V¹2¯þ3µ%6ÝHÛoÔ?˜ú¿@ Ûäò¦u]ÒºÑ?´?ë‰Vò±¾ôCèy¯*JÌ‚[ada` )Vð:6ý”§:KP’”Ž~p^Ùê¥5í ØÎŸ" 4P]-k1%Iš]uÆeŽÒáXæEžùµï¼/ÃÉó@[¯¿Txæ¯kþRuy]ò ß^Nä¹nA/%½ê­©Â)kgŸŒŠÛ ÙÓ¶2&ñeÁ R°¢Ÿbø¸ü}Í¿é1Qñ»5ҞЅ_¡¸Ÿ×ò’!ÇV"i#z.…™S³6ƒ}=w>OrûIº‰…29sÏâŠßm¢42l÷µÎØU˜ôl¦1ÎÍõQc©žÑZ8B=<ÁýúŠ dšW]!A©Æ¼Éðl)¬°M×8À É£KØnWÉ(ÿ‘'Ãlìãy®wÝį¿~?MÃa?/žÉ°·Ø/9mFßýñº{§A„ùxTGwªÀÀãz¾EOÕÓ´˜^}sk¿Cv|ù#rÝm0®ôü4F òÇÇ}ßN*ošôç÷5?¢~Ûß:v‡ îïÐéoƒõÛ¯*?>îÔœ“Šß©5)×uæîôw]:¡vÜ7.,{›_¼ù€ájÄKeü­É^F´ý=l³~ õèõ›º ¤¸QW¦]Ö°$dM4¿¸DȘ¡©Ð6? ÅN¨-Þʸº±š ˆQk ôÓ9\¯•²\‡¥cO4Ðó&s:Ý.oG[¿~L¬qؖІírÑËð: ÎôÅŠBpÙT:$i71¶¯ßߊòú–ÓÛÝ_-YjcLͼ[êªï)ಫÈlÑbñˆ‘ôãÉêÅjOI`ï¬ñK†®sÕdØSíˆÀ­R`ž@%°Éˆ ³žVı7÷ÑÍàš öˆoIN¹ŽÂó÷5[Qóô->~ß o FõåX¦q¸W¨ê‚¡÷\vÍÛš'Ø æˆoq;˜³|_ó¸Ñûc²N ‚6¶·e¼X%nó*wú?ÒFð o>B½d˜K!¿nlLb’M¡6%è ¡ß/®Øìe¿Þ»mÞŸkþžû¿¨ªôzØÊ³:@˜ê|-Ð^º¥m·^O²0ÑéJ½PÖ[&ľÞ+Y÷Û3’M(¢WÔNͬ€ÿi"wh¦áÚ-ÔþDÇåù0¹eþ¸ ¬¸pè·ÎHk»ß£†€)¶JYåo4÷pÓïǦÒcA}';£ÿrÊMÆ„úž¥Ey ãDéß¿˜kQûí¼ ˜›Õùßó^û£Ó=yeó8ú¯çã{ªöüúó÷S?P¨lÐ:XOóÈÝÆöŠÃäTÍnX1oášÃwuc/Dç-§ÂhXìs yd §~[ý¼¨¤—1ÌÌ®‚0|Ô<ÒÞ‡¹5—yüºººY&å9Fä×:@N×òŠ $[áú(÷Åo##ÂÎç©Ã[ø›e§†ú¶Áiy :Ä•þf–¶ŠW_˜@\V6h£-CïuškÌS¨"-ªAнU0 W ùYHÙ† ¶$Kßuò³v=£,ãKÕÊØ9Û<„°]¶ð5kA™&Éâô@§ž9넳3Gº-²{†Æ,íl%Ó æ^‡ð»mï@Ê«ëÅCÚl‰1ö‰âpå{ºkéè&°_Ó<¸\ûsíûïk¾¿ôgâ%7¥‘X˜÷ ÚeŠØ3ë…ㄨ•yXé‚´Í{G¥÷—¾¥¦.«$Ló¹ë÷5¾˜_óÓœ¦–íûš[œß¶æWÞåu_vÿ»×ü’W&€zyöǯFèã6eA&¬| }6¬â5¨c‚’Z[Ö£NL_ùûPÍ*ÎËVˆ‚ŸTÙ›>BçåMÛ÷ýy3›îÛÿ¼æ‘úÜj?#ºWÛÀ¼ßm”Câëš«||_óHgA†âüî{Ù5ß^«ßןqD`9ì5†¢ß×üµ·ýï^sÈë—`œÕê¯knØd½}|_sVTQ¯FmSÆC~Ç1“%œ:øÌÍü迯¹Ò9«^%UÃ"{0þ+¤W˜qÁ\©»iDÚe\2â5ÇI°eqýDUõú*‹0! â…;u¶³úø¾æ5×¢Ðúºæl—‡çR¦?}‘4ãèý%R£ø2,;c'ö͵hóK­`ðºæ8ž†é° çX‡öô8@Ó°ÁѪlþç5GÖF××›¶Ý l¢Ú?ì·ýûš«A<|êá­ªÄø¾æ:„^§L$c ÁBÞGw ÚÀÿ×5'Ó“Ñ¿¯¹sé¶jÃl eQåÛòydQ|_óçæôìŠ7%+[SùÿwÍѳoÒb¨¢]ôi/ì JRuYRå÷5Ïzz­Óþ?®ù7h™Ëà ´Û·Ã5gK,mþwAûµ`ǧÅî¢k.¿ È(úL|Ò¶N^æpæ YtÒˆê{Ù,¦é¼Ü»ëé’„=%‘B /·½ª®ÕÉ2"MoBØÚþÐþš÷ÏØ]Ìç×-¸uÿþTžV¬]¿Aûköo‡YÃVæAA;桬X~ƒv¦¦#Bk/ÐþíWù Ú—×Àü´?ï/ŠWgý´C•Û0N~vO¬NöA§ÙtÛ‰ËJʾÙê Á= Ï ´OCÜa3)·0ßÙüÿ-ì r¡ z•ZQDDÁjMÓÞÿTùÊ¢Mš.]‰?÷a˜¡f•"ö#Ú9Ûxµu®@»„ˆp©OB×r‰¾áú :£D2:ìÚQ—Ñçû£@»Ï·´o ¤€ÙèEáSœÁ¸¯‡/ñèˆÊW‹yù„vv˜Ý^nÐ/êÉÞ;jÅ$$1eþ‚ö¡½hžê¸Î­[ Š4‡Ì:•Î4gÉraÓŽúj ´sÂà#Õ6ÚŠ4Q[¢l7ѽè´G­·i ´£Q¯˜±àE}r¦×àç'9Þ=™œ[Å+/Ð[]Ù$7•ÿA»e*IÕ&£êžùÀŸ¹W]hД(.¨ÆÜXõ±@;å¥yÙ^ŸÐþ‡·z<¤KÚ%tEXtdate:create2016-10-10T23:41:51-06:00ôSü„%tEXtdate:modify2016-10-10T23:26:33-06:00Þ—¬IEND®B`‚fvwm-2.7.0/default-config/images/background/bg2.png0000644000175000017500000206364714147024700017074 00000000000000‰PNG  IHDRààò¶)ÂgAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ pHYs.#.#x¥?vtIMEà --$êó€IDATxÚ,ò÷—¥é}v~Ÿðæ›oÝÊÕUÕÕ9ç89c† 2 Ò”DŠ¢­=¥µìÕJgísd‰+{ŵh[I "r0ƒÉ9tOOçîÊU]9ßøæ÷‰ûƒ÷ó7|Ð<6`L;`:Àå¯dæh'¥ð¯¿]>[ ¢â·3w’óÕ¶à›æú¶1ÞvROa† OÄäŒu!ß°e‚Ç¡¡­ÿÊ÷PpE 9DŽƒ}B³nÊßFð%m…ê$TFðs‡ÊÇ«¬§+ œó· ŸüùV’ Ž}{ðÞ^Ýib 4ы̼àà÷“è}r mE)Ñ2I bräé1²-nÁÓÈz6Co£ìmM(r¨ R£bŠæ?ÿFé`?^›Û™ÿ¹W#dµà?ôµ\ÕH±m¿:%ÿøµ eè´`†}f1 _qדÖÕ¶0Ó“ïÙÍI'»Ó.Ínî(÷²l“Ër;mÙ´€h„å<³±8¸Re ë\&C»Žª>ˆ»ÊÅSµˆvç–'õ¾íƒgŸÂ¸Ïùéë›¶[Ùàa‡çÂ3+¡ã%ã«4ŠY‹;ý,é÷ u©ö|=ÜÝO²öäšú·?‘‰eÚq’R$}Jã—,çç,øÐà&#ÌtMb#ÓÜ2T[! ¤”BÛDO1}™x·µüšæ…ª¸T„ßÿJ×ôÏê5 ¿[éÝ%$÷…„úº{×÷~u¿Þ\Ò>PŽ¥’³èÁÉ8Â÷5óŠGˆwH:ÿ"ŠjC1†_§0(Èg„¾C2¥€Wœ :XCÇkñpµhwëj9›´l\ë_«Ì˜£œ”È&ÖÌ5ãFF÷ŽtYl=È8 ¶™Q"„+3P"]1¯K#¢RMÜÈ øÉkrah"$‹Z3W¸„C9µ6}e™ {¬~‘µ74¤”€’ÒDfŠ ‘â °”v‡õNr{l´xf¤u¨;Ú=øž/?ÛÚ·§«RkK†9àH À@ KëëŒ×‡d#S&`¥…Ô‚éLó l"4Ètö(ˆe‰‡(d)Ñ8i“®°ÙIzû‡v=·Õ¸î?e»Vl`ž)¼:Ë Ô‰SX T¯¦›Ü„7&À³âŒ ¡Ìß’+® ©†#Šë)*Ä*+[ÝZ„B:ÇØ„1à‚é)­ I2°„Ã(òdSY$5– ©T4àÚ¤“Ûn –L¬ÔR/°À%üXš@–‹”׿â ³ 8znBï¨Þ5º+®/÷ý_Ÿ€jšà–RiI±HùÏ8–I`>­O;8Lb €9²‘Ȳ´†#nYdI EAê[@@è„§X3T(àá§{—·Ž¨–vEãsÎT_›·æÖ•€mŒáø`y¼.2ÍUÀJ6„7(¿®E1n£äS}ZŒ¬Ä‹4‰ÖrÞ'Aû»¸8@T ¾%nX‘Øêé‚ „wvà©(6+E(R´‹ewç‰sF¥ßó”îèB@%æÌú…¡;’¹ p†Û4ÃpÄÄ»SÕBFÛ¢Ð-*”™9YYÅ›& åû³ÐMi@xS’!ÿ¿¾;˜wø¿cëó•(f"/kZî RuÇÇL*@%Sd [1 p¤¢‘¦DyŒ#Œ\S ”Áï>—‹1¾>©>¸“®Ì–Jœ{ ë´NœîîK4¬m0œb(ؔư‹zƒ<ÅàïHµ¦@ @96Ñ)N¥=Šã“ÚKƒjîa-p¢4 ðŒ"K[ÖÛ×Ãr]F’u¶Žœ¤¹ &5A†v‚ÈlËš\ q…ì1ò˜Hà&µ…lH¤rE@öªpÖ šA•öz({KeñrÑh³õTCÝ={¨éi·­(hbð(¶D)ß•ŽOÈXóB!í•U‰¥ÏB41»Qº¶!oHù”±]³Œ$gÚYbtÙÀ‘µ™†`#?Ý™\S³¡¹¿À Žeö³TÔÞ¬špç­ë (Ω Ð`Cal:¤èX”·´DFtO+ ¶m;‰h$*¦ z•sbÂ]j¸HÅ9 Y ì¸DiF…é]+v]{–ëÃj™ßíÂ3gàì!\$øþïN`pYÀ°Yâ„() XÈ(‚d!âP1‚@;yL…;GT§U ]¾Y½õðˆù{Ñiøì_þe¼qÉÈšItH±á^8›‚WteO9¹6W4n £¡ÅÑUµ~`¡™L0¥5KéCï œ¦cT^@ ››C%+OQÛMr…êÔ=3€À…’€¶öÍì_}³·«„ÿà—ë/6AEö*¶©ÜÒVB@)@EW2›DÍ0@•xì:d¶BN¹IòR€‰ H ¿û\A#úÁœøøFº<—>XF\”‹­‡ðãg+»úà(‹Ø†H}‹¢ÂTÀ.l Æ ­aT(˜4M4¹ýœR–”ž‰Ôí€gZj„ ­Ê ÈWÂs½šíl¯œ8cXÇ1¡ ¸+>×,L,Lj-Ó1dÒEÝbÞ |F(3}ÂRŠŒPȽig¶èb.kX7·#(:®“ªj·©í$»»GiÜòP®£Lä*%–@a´Èï ßâ½FR@µ(r%²|‘R„¨ÝK² Ö› Çd‰4º,y¶Í2âš„is‹‡Ì¢AN-ãÙvn1ËãÄ‘ìà~3a–»L…ýöN)ðÀ¢„RD‡”ÚåMC:TL ÓÁ‚Sd¤:‚Øè"p’ET ÈuG®-F€(f†k7w±­ZõÊÿò­d¹nQšQ–Ölxüœ:B*ý7eXi|­Ín ¶â)ÁØ ¡P¶ÉÄ‘4—ð¤Ä(¢½S e_·@Ãù=蟿Ôûò_ýU}&L,Ì·º­DUu_>å!3êÒ¹=µÖzÛ\Ö¸¡d ð±X×–-:™A&=ˆÈ¤¥w'꤃C…­,»áÈvdƒÚUªÐHÛð›O„/œáo}Z»5“¬¥!ò´»¡œ­r•ôóz޶ÐÉŽíQÐ|Ì(¼v¤f¹=q‘•`Ö+Öv’.£™•µš1ÃD² `ëñЉsèï_*|²¾}wø½{[›™ñã/ê?ùBÔräÄ>3ŠSЦF 4 Î-D|¦5d&À(1Ëž»*Ù$O-Æí#;2 ;˜€Å(pÉAƒÀpÄ*'}ôÓkä×ΘåB¢˜¹Ði®.™¥Ã66•ˆå¨-1GÔéÂa=ˤQ–q­ì©;ýùõ•Ù‘½]c»ëùÌ,÷Km\– »HÚ;›iõ?þç†Æü¹Gì<¤iïÜrF9°ÇÜX ÐÚ”ÙŒùwŸ)Ž–˜g[,2s ÖæÚÐ…¾¼e¶Ö¦º‹|m'á–ÔRYšÚ$}Nd\XI;ÄüC<ØM‡‹^O7íΆ\·P’­ÌûÉg¹{;hª€ HP†e˹bW={«H̱P¼ßµû•ÝϸÒB­œ¼6 ™¥”ˆ˜ø‹Oò÷æä¶¿£ÀêhÈ.ìxùÌÆ#½žÐá×1Kw3Úq|ÍN§ìÕ€RÝS²+…(£ç=êgɈQ8~ž½¼ÖSµXEäŸô®ME~âÝqÒ³ sŒ‰Û9”‚6ȤC©8mà”ˆû¦h§67“s£º‹t¨aþæc—»õ}¶Ô¨k´¦]d”ڶ˺ ž‰@à(› ùIû¢[úØo èœÎu-„ cÙÍ$…¸n']† [–QTÛ3GxÕÆ¿}Þø‡òŸ®4ß¼½ëƒ»Û›‰÷×W‚¿¾Â+®yú€F±ÒdB",M;\"Hm{ ;ï¹ë &Ò¶ŸŠ=@5uÐI˜% —Q…LŒc-58`ðÉ–ñWŸæ¿yJišZËIº¼¨6wÈâY¯·Yc&PͤU&q+ÍLãˆI Ć87T^0?0Z:| mG*×%M·PÒ0’£Üln§ÝÿÛÚ¶ {ù²1˜WJ.®qžföC¼wèô´Fœ¿üJaOe‡¦¥¿ÓŠAšÛ MÜ•ÿòf²³´4Ô]­Ž¤YšI@mæ˜r/…%Z1üñâÁn1R2{{ŒÞÑæ€™Ï—‚vRúégô^]%Ò ` 2ÅbéLø‚sÛÓG8 ä¶J‘ÆCžsŠ8Kh¥*µMmçB ¬Ó”ýðs|{FnwêT[  }yOå…ÍS#“Q"’,vU!±c¬D˜ª€ˆA‰«¬‘d8jÀS ñ¸[½¯¡2¬$Ú!9W„ŠA (ç Ž·`Q»$äú.å?Ìž¿Ðî­ò$²ÒGœ;m?¦w\v:†Q×*1c}Ý!ûS—¼BíYÍ- Ý„vqjñ‘ÛL¸Üù»_“’$̱hÆvåÍ£'ðžÑÀRdeµQåB(n¯šÝÔ©ôNó šöâCZ—…ÝÀ”þÌÔžpC;­úYlDúSÃ@°k>ºÁæÔ䙳i‡ån?°Þ#÷çãû›­p’)º¥:BÍ­ R !­ œàª[{Ë Õ0×!r¤æX XFÀµzÒ4¿ªc°œ‚4¯>DàIE-„˲d*•Êüä ßnǘ¼÷™üìC}o:w­Ó J26kfê(œŠ\EƒÝ*?`=í: OϾõ¼g˜¹íé4áËZ‡´hT®dëS±á=»áý÷ó³\˜]ëÍÆÑÓúÞzúÃN{.n6Yõ”ø«·ÄÂN)U¬`•ö f¶Øƒ÷E¶JFJù§ÏR޳‰ii…艇Šß~Qtdƒ»H÷pÙÄ1²ÕX›ç áÚŒzL¦Wýåtân6µÁv8}ëvòÖMÚ,*–‡ŠÀ>–&£¤Ó.™Á˜)$9‚¯°|hEHcEϤù£Œ›2Œ‚A\ÕV[f7105O…VóFZƒC]Lv ŸÏ"|;ÈíĦ6µ´’Ogy3bRâ.Û:hân.G¤¾ˆ¬ÃˆÎ麩ó<ß±øcRïâ)´¿F@8Î’à £u¼¡Ý_ÞògVpÑŒ?H¾ÿkégÍ^‹¥L¦žG¬»G||Í‹ VŽÚ—骶î `ý"¶ú–§ R«ÌdØUSok…ýGÏ;š±§P÷•Èsá©m·’í€Ï´Øt³ðñ-1Û±„k©½Ä[³ø gy~dCZN„«r¡ÍJX>…­29H[Ʋ&BgŠYÝüÜdîõEûýi<þ ½»îG„c†l]ㆎ8Ÿ[GZ3P¤‘>-PU[kb,)8‘\ÍÓ'ô×5Ú²’@jh¥CrQëmi l[$í’5[ú‚'V¢vœhïÍÂ/>Bw§Íû«qÝ/‰ zmiJ ǧiY8ýúÄiïøa8s"ýÖW\“zËÓa"ÓWµŸØg¢Vyþ³dc6LºÓÁxï=g~S*³{§Ý<~Ýû•œ|¯ÙžI×b>pTþè]5½‘ãBNñÄñ`z[<ø@±%:R²ž>K8æ÷§™á£³ä¾þŠªíΆéàpÑ ¨€³f„ˆtsD8Tq¡ØSkþò\~üN6µÆvzëVúÖM¦-)ž×9­œ¶‹2ÑZZ`˜ ´â6<•™Ô@7­s÷±ÌÀ¢“A.å*»EAkCJO­×Bа ]\hpXˆ,Q¶ó[™éuä¥WgYÐJ ªmï·p»¤º€¬C@gÍtÝOä&~ɽZœFvÒyÀtxŠˆË¸³Ú¦мq=™ZEyÒ¸t~ó«ì™‹F¯a$Šq—ÄQRê_uCfÉý̬*³EÔ]‘ú”?G8y…ÈÔ&CwTö³Ìg¼ÜטOo}jþÙ[h'¨Ý›‹À0s—÷tÞW¬nßͬ€"DªP!]fÖ±œ9öëå-æç¶Ô.Ò£d4­Ø¦ÍòŽ0=$™%£À‘¤™~(RÕ¶š·g²_1?Oî.ÇÍ4¢JW¾Ô—÷÷…—FÈ“§²óΗë M‰-ã,×9dlUͱg¼Ê˜+öeË6»^ç;D±+ çPO£<—Û¶ç…ØQ˜«Yf"¡R×á±Of¦ðf[º’$8ÁJÂÎi7Ç–Õ}Øü'/Ë'÷«“GJ;M³FŽÇ"o]m¯m\6·»]p¯¿¹¹{SU}¼ ·Vzç—‚©ð·ëtÏp­}§¾‡ç‹Èé˜aPéùÅ;a‡e¬V‚ýG«s¤WͼŸ.ñ´|¼ô׿ªÞ[oe`39u:Šn+§“¾ò|ùá‘ðÂq˜J‹ëÙPժႎ@! A…³ÜÂ3sf'T–e,,c@ÔmáXFZõbqÔÉt¨)pŠU~^·æ1Z·A Z奵GPåh—»Û¬oB1†Å- miÅÁ"¿óhvù°ØWÑŽÕrrJ‰îVÛÚ©G×âO'Ä›÷Ìû³¬U/–§·?›ñ˜(Œ Ê…©X$õ¦†–¥ú2y^ýPKT°zXìy¡7YRKÔBPÒ˜^j¶ðÈÑžo¤ŽôÒñŽÒ}PôÌ·¯v¶›N]ÃÆJñèóÊk›#k| Ê-¦Èê/½ùjÃ1dÁfÝØ½»·q{·(uK\wcïyõ­Ð2¢­gWýÓû»&?M- ¡¿ÈXùXùGoÚw—VвøÂ!£à™í™§Ï}¥x~,:{MÆtc#¨‘.dé”h’hœ’.·Ìé9«`Ë¢&OKØrZ(†ÂE-ŽQ*À‹„›å@iuÖ9Y¥BØ ¯ ëÂEQ8Ÿ/äë:GlÚ2GšH¢Ñß{"»|8ÝWRžå[.Óª¯Ù¡fru-º2!>¾eLO³íVÑÅÀ‡œŸâ,2ÆÐ%¤©X¬aAÛÑ]*»( ô…*îìãûžëKl©ÃêÉÓ¹ù$n©GŽV^y4ÿøÑêCãSá•{ÆÍÕžWßÉXT=vBY©s«…:©ZwùP–åÉL}&Ó½HÓ€Û£ä$¹î©»–ce\‘/?­Z;Ñ…‡ñD]½þeÁ—5vº Ÿ‡á]ÎÒrB)ç È—L·R«_¨©±_+Œ÷ëÏ?\Äø[Ô^LE ™® ©Hl¥«@Rƒ!  eXy¯j£Ã¼·@óý…n3­joP»¶Ó,ê?LÜÔ\jB[ ,$[(0{J{‡„ÓŽ»{Q+@{€ìfÂÇD(V#_ÈÀ`¡V™vd^ç KÛ&I"å¹…² ±Ð–¶0òv[*«{(>¼§0êtÆFäý¥ÜâÏC¶Ny=ÇÔgoµà.Í›¥köå§ÌÙé*–9½´ñê#×Û5»P/[n¡â|z5ïÉè:ÂòíÚO³'Þ†¡ƒÖŸúÒF;\û¼ÇÁ[|¡ÖºÖæw8дìþêFkr–)`Œç@kÛ¼ö1ïZ/EIû#§ñÄ3hü¾™-îXç2 o/-ÀbìÝu–e ³(Á.£¶I(±ý´Q*Ñ *A©œD&<‡¸§‚&¥Rï5x)T±ö BŠ5qø”ám¶dÁ^íÑþVb!åœ ”Ô{¼Ò¾3éø´up»«ÛJƒE©{l"í¶7ã¹fÒ pãAÈDÙ¥±CL[¨ X°Ï²¤±ÍäÇèˆl‘mŒê7a¶‡Eê‚­Ê3Ê-ÒéÈvÌuŠªvYiF™"<6 8i× ¦‹E¬TŒµÃyX5…”´{H?T6;»‡Ó‰µÜÌOÒôAãÎnóé3ôÚ[¾o9$÷ùFýñÍ™ù” V0ñüÚÎk_ZÅ‘¾Å•Í"UNÁýü®YÇ(ã=‰±I¿ù~ý‰ã¹ñBd÷^ëÏFe,ÀWÝ&Þzï í©­Îv$‚´RøÕÖÄ4Ëc|Motì›Åå¥L'ŸÁöSÏÀü4e >8wÉ>>Ü^Z  Yéþ\»½l–iF9Wh%‚‚aà Ke¤-„`ˆHTðYÆrÚ-`ו]=ùôsò'-™˜Ä¥}éÁÓÈIlêÕšnn†6'U>šzwNî?C&§J‡÷Ñ * ;U_™í­èA#Ž:X“4ΘÀŠºÅà"Ë*ÕSyê”]•ñGµ¨¶SÜQÀdDz|…¡Ú_Xb[ÓŸêVX ¦‹­y•E„‡3üfòò3êA[~0-–2øYNr06ˈoI‡8Ð=îïi9—¸-É´“?ßËþÑ FO™Ã6¾pººÕâ³›%áÖ%/K‰¢¥±Ñ¬3¥L51ð/è¨÷<˜”¥ÝczÿXeÇWÉf:*0d*UfHŒ5S7•HÆ9`B2 òÏ^v_9ÎN÷^AÚŠòüÞhîuÕºGŽyCÃø §Ô ŠXŠ]´±ohkÔº0ÜiKCh¾õ.ìíÔN8:G£ÇǾ^Üs¼±ëœ+‹´>ø8™)ÒÌžT:Ú‰XDZKySp,š"¿mÄä€q‹ 4™¥Íh@R§ü§?N V ­,~î˜eÇ*j”‘ç.Z´G÷UíÈü ÃÉ2^Åv)ÑDI@y©U €#¹ëÅÚá'Ä®ãA¡‡®~áQc¿!ºx>cÑÈ>LèsÒ™m"w¸‹`œ£uAÅhÛ˜úkëŽ ãæá“ó¬¿79ÑßmÚ¹ÜúеÒì“Bª¡¡nš\[B˸Aø~¡79SÇ^)O õ¸Æð²©Ø}¤0‹™âœUýŽHyê·m8C„9¡b¹‡±ß}…:ÛÕj5ÛnÅ÷°Õu´Ê(æK™y§u vXyC7rѧ©OÍz&[Çw±ú<£1v»¸Ú¦—O”Öƒxa­4Lˆ ÂìDš%f§!”2UÃÞ>âýîn <Þ3FGÆŠÛ>kñ€Ø”\bì[Tµ¤dM"=bÎd<÷^ºä½pŠŸªu •Ìž/Š{ÊÙ×Xû¾;Æu%Çg˜a˜H‚§Õª È.ãÒpeDi¶ô®õkûœ$oÆLN¿\8·Ó{Ú´»Ýh6xx›)2àž„”©Ç9×`p!º»Ð¡ƒøè)òõËÅ~~¤‹åúå›×ÙúVÎáÖ­ÙäОR}+©¬’œL£^•çÓùhÓ@YjÕl¶1%Ožüp)­µGöñ+>Q˜çûi‚|ïcìQ¯vÆ–1ܸ–˜BźÚÎGeàz]x8aÝ)é/÷Œ¨OßL¹‚¦ÄÛ†2AÌ´w7ÒqÛ} 9…?ù£Y14´´“³ÇL+q=p/yú<µúT_¥¾€A½,˺p¡”d@P* !bT'™ÉGŸõ½€ºŽvº+ÖÒ] 1ÇHs>òÇök3sûÌp©nù›¬l¡I†} º„QÎp×­ùŸ6·nÓ°“8.@ýýþ™jxz„ØùÜâš±àG@µÄø V…š–- R˜ÛDîW°Éhn—ùè¯Ùƒ':å0!Z.Û݉& S¤Æ*×öŸ©ÖŽ……ŒÁÒf„>³_ÿÓ¯zV‹z]µ³K£jeÓ^å^˵ԸƒÃGls›¬@¸®s¡4x.)içëG¢ðò.í¿úÀ]je‡ª=i}ì°^êðúšƒ<#ëß½‚¿öhy&a­v¨…e ât›ÈR¹ñõB{Á˜É2·’B´';tÊ¥‡ÑÀ ìœOö¶š|!D‹Tb ” É-6vÞºO¬ç2œæ{ò5ÊнrWŸŒ#-•óK<™_Be†Œý s ׋ùÔˆ¶ÑÕfq—׈^“1ÉÃ4'˜vù+é­Uk#¤Ôhø¦v0»»k}KmPÄ{ñbþ«ÇZwVr?мÅlr¹ûÕ•OX#€v>6„¾3“vLxÂXÒĬ8:®*FlctƒCÎFq;‚D:³ lƒ³¤TÉjNnÔשּׁ‡Áê–7·l:[Y™ÀŠÐÛ©D¹Ì{"»¸š:|»ý#ƒƒ¸ñÀ*}q?ý/ïÿòã0ÖñþÁZ£áH5Ö.8ÝÃòò+X‡Vå0­Ñ›N6zCÝѺ‡S¹UßS¯…Y¼¦Û”´²\NÒ“‡‹ÿϯv=¼Çk K”™iîð^ñ^RC¾;ð«ñèÆ„{t„?{¢'Ëâµ *ÒN»¦ñβŽ´Ü¼Tq ̯^R¿óð€t;?|¯ºÖ tõd±ýÆJ€·7™Çý0¯`«èl‹dv j0à#HPoåMF!2˜i”:,mÑbÃ2W’yøàDZcŠ[×Ä•5k™CÒ%ª°’É@¹:p¤³‚BæK—«ÏiÝÜbÛ?r¶°æ©½ÑÕ«zÇ'ÍBldøÎ¢8y®štüù¢Ú¾ïó‰,mgEFv\UÁÒâ0Õ¢Ï=žÜm}£Á${TfÓùE3òzžï~o|³iÄ‘RdŒ–÷)7Ñ™ßNÂÛèÞ´½gNœÌ†ý]œ]Ç“ÝG1ó“ÛðÃ'–s ðM ˆ:ø‰óÎ W>·=ÒSºþY Ò˜YhÚ½8YèB®j¦-”¢b÷Ü\BM{'dí„W¶š_ù^ß¹½:VÞ¯>j¦Z3[Z”ÍRÔêmrp¯õç? $!;Bq@J%©Ôy+or >¿$,‘ˆmÎ@ƒDK–C°°<úPþ'oÂÂŒ/»¬¸­F€ŠZpñˆwù¬rOU^}k#lQÆé6“»,dF^­êÅKÛcÊų‡˜?øËv`7ó¾ÿlåòÙàØÞ’c†6I™‰€è¶”ëÛÝ_\1ˆ¾n:r„ï9®5÷Ú9°Zë¹×Hã»o¡¢yU\ÀÅ%™bÉ5Ÿ9Ý5½„×5{È(îm:üþdB/6Ðéƒð/¾ªŽ^›ˆ•‚]œb­‡´;Y­š÷wÙ­v~ùNéRdÁf¦gec^ÔçÅÊLl< ùÄIp¶‚AGÉØûîéÔPÙ;÷eVê'ÿú7D¢Š¿šðÿè ÷í©Ü§;»ÇºÚí³GËO5ĘP:À†©95ש僯‚ßù 9wˆfQ;¨%ÃÿøNíúL«¥Õè(<¿m¬¡¹–“§þ÷/e»“«ëzv,§‹)Ÿ%ŽÄ_×÷¦D:n¤sÍjµ…N&n3ë­èËûJÁ·mMuicBÌt:ÈÛ™Øüï¾ýÆ{!‚;Ëôæ2¹wOëœØµ;‹ÜüŠ:ÞñGz>¼ÛØê(,„Òæ^Ú=¦P(³¸‰“ y{ÒÞ3ŒNœÌ†ƒ]œÁ£ÉÈaM1¹6nýð¯ ÷—ÝÕ1°Æ´†\Þ¼xÄyé‘âSnï¨\ý8á©=3ßÈ ÜRlVy…µd « …L­D—ÀÚvð•%Ò¨¼úÁz† 4 •à.Š4ŸQ+°ì±þô'¾ÒR:Q€‘È´24)´EË«Æò‚JLh N±´ÈØ5ÕÚbzá¼ý7+³a(5MŠ´è‹ÐCj§ 'ìzü‚_=ãýòoüv‹såÖ%õœÈÅ…ÁB·x°5BhÊ“b¯Z´åŸýÄgQÎËÜï™å?xÝ{ç[é§Âï?ÏŠÞœJ8‡nÀ ÅCÎH9éõ²rÍRÊÔ™؆͌LIN4gøâD„—©º)¤«D1dr#Û³‡ÿ/ìÝqá'Õó5õ¯¾eqÓúÕ„þÃ7Âwîåž>“uêathŸùèÑÎri’)™H äø»ÙåÓðÂɾó{2&É›ŸU†öòªß5Г›XÉf}µ´Êo\Ëuxü½çÐæf4¹YJt|}2!Ò¬€0·XòŒ&U‡/0Ù‘pP‰£@VAÍ»Ê5ýaÙYšŒç7m£ÂÕôJÔ¼¢¯Y´! ÔqvçÌg™»qúØ~ëwý:YÞŒ¯ÍÊ{tÏ »>mô9üϾŠ4ŸêlŸT»€+3ë§F»*Gví'Ò ¨m:a oÝ?~U±l;¦ÁuݶJuߨxô¡Â3çpÀUÏ®ÚÝû05‘ÅaqîÞw¡%íÕm¹ììèÎýI À´¬-¤Í<¿ååqñ³OÚõ­þX«ÅÇZäZ’÷˜¥öFpoM§uÔQ25* ûJjmåX†lÕÛ¹õM’JÖÑepÍBa2dtåQ\÷öbº4P£ºš)KÐ(S† ާK$¿qòTö~ÎÍ!«BãØ¡VÑS2Q߈ìë¦3=Êáx×Ohw"Óõ̽\>)¬­H Ñó—½®!;ÑqRÃ0t±¯Ï¡û×,‚d­h–Ëf¢’DJ©?/û3\#ØNZÁÆÉ Kß9¯{2iªäÏ_E¯™Ëb¬ÿyçïœã5™̼=‘̧¼Rÿ`L`7Ë›äã·dýj{?f¾Õšµ¤'à”FXóE Ô€«ò‰šÓôÐËèí[}µA^ÈÜ‘ž¾™­ÎD/¯è>Ö)ßyÊi¶Ú‹«Ý(›\ðÞ›0³ÙR"•<¥¡fÚË\&\Óì˜âËX­™Ú0ØÑ~0-­Y¤Köï’³KÑÆçêKƒ•G†Ñï¢Ï*<´WžßSk,¤‹õôÚ4ŒÏÒêp|èátïkWÅúÓÏ›QJ‹˜díWdH'šÊÃéX:î®ý†08âØNà³›÷ÔÏ~%¾˜3±‰5 ¶g¹th7âBî‰3‰HqY*Þ»Ggç\jgAœŸœaû)'íhe+¼…[ã>ÅW”…\æïX ›õç•o|±µºÒ˰ØJ T>¨â|}ÿ¿*e›v¤ˆhBm%•²=Á1Q+°V×ò©[’ª‚¥Æ!RõŒ¨ ÌÙ:ž»0é¶Ý|ÊŒT76M!‹æ^œŸ;~PüÑÏÒÅÊ(»AlÀñdœdÙȨêî“wf=dÁ™òOB›-Ó€Š\.ßÞs0·¾$9 ^|¬Ð5hF2©E)ºc˜îsòî—Œ¬V$岑ª,eq>œ·zSÖcPŠ2*Õ5 (“ZjõÝsd×qeM›HýÙÏô¯®Û<÷wÑ¿óŒñ·N‹Q[&Ò»1©CîHÑYÁ‘Ȉwùû‡ñÒ&þèÝú¼5ŠbA;󶤎a,p6/hµÛ%¥çˆµn-èlÐ/§Í+ Öãèw¿½q;ýÁÍk zS÷–Åßy´$wª™ï½SÞ7Ø9·Ç=u¢|öRzæ #¿÷hy§­9 „±‹üE{fF\8šô!àpb:oèàþZáÓûÁÃÇjIr}ݪ›QÂ<ËÐ(=&Õ9:ði&_ÓzÕ°×7 ï/@Nhz+U99Ý+Û‘YÝ“>Áóú>d±eKÞÚ3˜9Q¨·¬WN!éauTZÚQÛaabÜŸ}@ e ²þê=[qס2ÕìâÃïH0dvº]Í.<.±¤ ËøõOã7?î¿ÿ,`X¦DÄ)5Y¦~ó¹ÒמáÅ<ùìµ°xÇ^ŸO˜l uo)n Ht c|.|üÙei¬òÉi£#E#-b5âòWò·Å|‹/×¸Ñ ÀBÒFFR6 ‘ôM XPðü0#ˆF‚I¥ “JA ¦Q0ÓþA§R¦õ0 ÎwL"µ’ŒR qÁÑA&¨³Ã;EÃå:uuEÈ4GÛd=Ø ·PWqh¢’¶çg`€ôÉg+}'•,ýù‚z’r+ÞN EéØAÚÑÜ/£òbarÓ¿ô˜õÔ9\uJŸÝ $`ƒ%pJ“ûËÖ‰ÊêN3g½e³ÒGnMEVÂiÆSdx ;—ÂEùT ‰Õñ]ærÓÿË·õ'תK%hpboù×N*Õ´™^0úÜéõpi+Ô$<9¹õ>+ÛÊϼ†¸ï­nåˆj+Ï•"ÝIäíùüG7tb ¬ S™EÔ£vÞLa¦æœ%†Æ¼6ú¾ú芹µÒNd@aWoòÌÓ´×öü <1ú­|.œÿØ9ÀR„l–³–›¹õíŒb‰5鲺rÍ]ß>q4gäâ×_M’ßÈ2aHêQ”õwØrÙPËm7ÞŠ,³Ìq«­akž—Ê%Ò¶Ñ?þžL:¹õM7ÓH´Å Ɖˆ„¾þì|y]›–ÊJUfª|GTuÛ-þöËÙí)F‰Òe*å³¥ b2¹! Pë™2Ìr¬:‘Pð‚’mãÌ)Ž2úÃÿ´Še·‰¹b„6Q®`Z]€ìu9ˆØ–Èõœ 'Ø¿øë¶tñ ñØÃ¸™¨ÅPS›àom©{3åé­Ô*pƒ»‹›ÜÄnk*eÑËgY¢71%èóûæãj¦bËÖ’ÑýlÆýÅõèµøõ[òÓ›áöZ5cvYÊ¡H¼Êr/†^ º@K-¯¸]› ÊÌ °cOˆ@K"óõI‰@µµ²M)rˆdIÑäïß …pD¨‡ÊŽ”ñwžÉ×µÿ¿¾¥?ŸDŸ®­uL½qÍ™} ÎÎÈ‹§ãgñ­»C§ÇZƒy˜Y6'·“å-µÒÈ=»'Jqtg¾‡0òóüwžÌ§N|cÚ¨@^ðÔÁTru£ÚÁj‹ˆ&Ñ™T¦²ë€¸b 2é—2ÞE0QjÙE`7~„:I‘àÀBÀûjù‘a¹«R©â$GØPôZªßã•’èvié.7ó=+klJ%ô¨©I³-yé|®ëP~<-O­YwnòΖÌc‰3©Ï5¿þLéÙ YuxÓÜJ2“X÷îèBÙ1£Õ¹"+›».×n6ãL -L¨¥ºÞ™"ÞÒ²sc«ÁZ©’fN($RËÖõØ&‰=úo½d}r"Î(22Ì9Ý4‡pöÔëòžl°¿4>×À‰•Sh¸è˜âaëὕ\¡ñƒQ´ _hÏ”EŽsvçï~³kÈí ™Y—.û\I,\içÔ°ÿÁw ÉüNè{¦ÁêœçÀ#E¨Ü÷òNÂÝÏ?Žwâü²jJÉ1t™F”wdØ Î3v6«›‘å>ío6r?ûI†l+±•áÙÏ>§OïVö)äƒuT4‘n7Èô¸³Ø(’’wä\Y÷°ÖrRV¹ ˆ7•Ó)³«å!¯U6¡T…!—ô8ªßã•/h9’7v÷— ÅŒ1#Hc¬l•·ê<ü¦4Ìc 9È1qÌØ”³Xj"K’³ è'rÔADT-J­1u5uê„ùÇÏ¥ÿý އ’‰Å2%øùóþñ^ï~ƒÜžá€Ôé*:w8[Þ)þÅke·\Ü«’P}´DÇïŽeýùdqÞÚáË-¾¸ža¸\Ÿ§/ílë÷^€ñ[óNU›k {KÏZð8&M-#s‡ˆLJ$¡Ž9B‚–®w^¤% Û"-º‘>  ;QÎðbC V©º£‡Í¢k¤¿»ÝyÖã±*‹U³Ï“9­zÊ¢¥,€‰ÒÙ˜§d¹.ÚÅ3Ví`Ïw'WñÝ[¢µ¡¤ÎbESÎv¾ñlùù‡y×ùø–µÔñ5àûwT¾ì¸{øúdw\ÖgØ7[\˜ÛDwù|%P ¦=s‹i"ó+i#Mî4)ÎA=Â`Q²§‡þ×_µ¾˜TqÆ´&œJĽn#¯tòØ ôÐ^1º«ëîlƒD4Eit¸àšiöÄ£ùGötõÍÔҼιv¼âêBFMÓÿ¿^«F­@O¬è®|;Q²¼¶\™¦Šþö÷4GôÁzi×”;™I°0=å(žuy9‰¬w>OV’êÚ6@"ÕyvÑ¥‡èæzuÉÏåŸn­o;ó3 ¶›ÊÈ9O?+Oï…c(±°Ž-¬Úu19A–}‡ G.TdwÖ^fUUØÆñš°-™1RìÙ_è¸DöWœŠ#‡r¬ÏÓÅRRµõXWa¤–ËLrqÊÌÒE7ãÉ“‚U°Ì$"Èó¨hÿ!RÄ  ÓЂpÌ ¥ÜmâýÚèØè“Jc¨ÇP+ö9Íÿ‡ç‹yâ?p t¿p±}zýÛ׫SXœê2.ïGKMù§¯ö¸réHD•Q­7 ¬|tìþ¶¶{;:Ϋw&Óÿq'÷ÏÓ{ëîÚƒvíÜñxwûÉVáÛx“J©< pœÂ¬3™Ó‹ÕºKZRÈ4Oª`wÆ3¿.wöjðÌZ¦¢›ŽßÒ ± N‹$[Iû…QùÔ‘›<õI>ƒŽé\±±eKÖújÃ?ÝÑÉLÀµâPÔm¶’­¥5…8 ÚÂDÂ¥Cpù4•¾9ÿiÇÚß?¸&Îâü²×p_#9{¼ï+¿ÛAfêÇH$¹ ‡ ˜d J€Ë>Yð³híÓ¼²· ;¦SÄp©eÈøônrì`öõçò¿xÏ«¥æ•TEŒŠ½»óŸ\#ÄÙ|üRáí·LÉë6qý Í›{«òWÿyƒ(8ü´1×í®µ(g‰mv½ð4,-oÎ'¹Cû­·ÇÂ0ä6Yršæ7„xöYrî i®éÙp™T”0•2.6K´ÙŽ?ü\r#k;Y Gc4 Y =yÒÍ•éC¿ÕN’äÝ+}7îílE4)„%Õn‡-hÝë[žk?r¬øÈ¡èÚÝôƤ℃Õö£–¥‹«f䊂^€qª°&P˯ÿ³¯‘¢]XꦶKU0‚°K—›(¢^>œ"º-’4‚ ò ý%I‡™•7˾}—+ÇîÞÚK8–(`ÐЃH/'ÓJHC#º¡a\Á…™ê©{¬ÇON˜6Þuõ3Ç+ÿÓô½-QÂå‘®‘°m¹ï~ÑaÐÙi¸¡LªNeóA˄ͷ¯½ß² #iòi._Pã³üþšüãoþ¦ÖœÝ—N‹±š~q·ýÁxÆ3Ä„´…8p Ã<ó'…]0Ò]ÏK0ÁH…24Бºû¶Ø>à’îT‡_XíÈ|l$`aë×Êâ…Gó™ LW„Ý1SÓ±–ZÈŒÜZoÄ2ñ¯ KÛzðÉì)Vn/•(7œJs¿x+¼p¤öôß Ü|KŒUÞWAÛM @yž[ÛhÂö§šgªäˆ|‘iAP5Œ’ã#èøQöÕŽóÚÛFWêÝdÙä3)W=ÔõÙõLkO^.¼ù:&¨m Ýìø+ÞîBðÖŸ‚þÇédÅ\cKЀeeRyúiwc«>5IÈçÚñf8 ^]úGµ¹…¢ç¿R»x~gsKÞ5¡K%R#ÝQ$fÚ®¸F=h}v  ˜¹ÍÒþU{o†8Ò6,¸üý†`ü­Ok_ÞÙÙP˜‹«ªÓiÔE<3´2¹ñÈIç‘Ãɵ»É­i`—Jg °ûPª«4ò@EQ7@‚ µÜÆïÿ: œí7ÌXC5&ƒ´[w´oå[Hæ?™²þw‚  f+L¶ qEÂIæäŒb[mÞN­O7×€V¹È'€;%“æÜ •ñŒv ¸Ç•N“Œ‚´Ç{éþPþO¾t‡+ËÏŸ+ý›?Ó·V”iP›Wz‡‰«Þ¼Jêxµè›1ôÅLk+¦]vþ¿|Šüº`Fž™È’ìí„ó Ân#4+pC9ŽA (9*"8&–HÕ<$s.ŒÌdÑ7yQKÎ@>Fä^½›Î,‹=ƒÄq•Ÿ) zúËÒ­ŸtÖn¤f¹f:ü¯Þ53„¢4ô#t[ãë[lj’d•Ñ„q:XEßüF÷£Ä¨aßÿ….&ÉÜtÜ7bÌnñŦÅyæ™Ì´½Î·Òã—ñæ \½Ž153F„6hC¶ÍÔ.BéâiüøÃwnµ0!q.BhX0™?./É^ ¸‚¿X …7DhBúØY[¬Zéç­d¡`ôgÐM7W-ƒêHª—ž* y”ÖM[V³0<ï|2ž¸Ø²t~ßñp(Çv~i«å¬¡ÌR¿šYJêT:&îˆè¡'é™®xjRŒŒ”§î[¶L7pŠE¥ Ó2v†^yj_¡˜¶Z(aZªX „TgÄé(sl”8þ‹×Ôû‘G £"ÈÖn­Ué_&Õ˜mLæv§Ÿ`C#ÞúbÖMÃ$/OÌ·¬ #1÷"Ä©1 H nJ¯ÑIŸ<\^_Ì]ÿAcõ–Å”ìB«)+8j' ÿá—êgŸ¥5W=þháö\˜ÓZˆ\Å¢ÇDÒÖá]3ÿbKY‰mºÚáîŽ4çUºFõ5ϱb…XËZe˜$6‚V}§Û?¾/mG¿ñèØÏ?ÞühI/e îSÜbì£÷ó Ë©ÕòV¶ ªJuȽeíRú äxf±6*5ŽêéÐt)¼*vm•SyÞûw¯ó‰@žòþÕ‹ÆžžàÃÛùXPí†;©u$!êcUá*o ¦ð#~˨nËxKñÌK¨r7„zšª WUÞ7Ò “ààv‹¾=™m¯–z»Ò)ßœ|û†xœRGºd¿~Ázýš¸ÙÈl"•ê1úàZ‘$u éÀCºß»ÛDÂ#$®¨»d2ây’-­8oÜaq'N ÚŒi/ÄÇÂ|·ÁÌIU™ ”(j6Hô÷QOKê ÅSÓ1¶åàG¬Hëà  c+ Û…ÿþÅø©ÆŒO¯/²/îÀH!¸¦E˜¸ZÛÖ=„mYÑ¢Ù}u23mÓ8º/oÝNð¦AM‘ >Açç:GÛV@¹;.ÑüÔõx«Žé$½ÞÌBJã Ó¼¯™–H™šµ`v7‰¹¸ç´TÊ 0¡[i•RècÇãWÎsÓ`wfÍn‹ÇÒN(ÃXÙ#u2´þ†LˆÂ‘î\!Z_ÃÀ®*üWÏ…â†pBYÓ°ÙË_sS8““EòÊWùÄ=,ZÁa`ãÇŸ•9gÃûóäw¾‡n_ÍöÔµJÆéÇéÍûX)Jȹ£öþžK?Ùè¬@Û¨Yn0¹¥WA–Œ(不²O[±š¼ƒóß&$§‹)IL©zµé[i½ îßÊ­Îd1#!ÊÈ,逢\wÕJða[nf|ߙ܈?̯/²B7ß;RYo4#¥»µÍðœ"*Ï×75Q(á`û1¬ÄÃuÔ/ɢȟôû´útÿ¿_Å“¾·¿ðo¾n¯…ï{mfä¼p+‘{ˆi8ò£Ì”Ò¡S|Í›Ö÷qW' }!Q€´+‹ÀäFšö–ÃD,•'Û-õöÛZ+÷TÓ _ÏÑ=ƒ¼’|†Uß¹4ôêÉõ¸L Éè©QMwå®.R  I÷ÖŽ¿w—1ßI7ÚæÿòuõíÓ¥æ­et¸Ê2dD¥«,ÍÕYèÞÕæ#`l˜ªÂg9£ l”°tv ’@ N5£Œ£Öã^áÊ®q½(l²“o–'—TØ|òT ôŬùÁ\¼iö^êID‹.Õ»@gï‰Áë3ÙbrŒRÇ*Õ;¾Q2}‡ :4Òóò3ì© É­;v§ëdö©õ…QX\ìîm·?ø¬…\[Ä)¶¸t°¸Êü¬³ˆE*¤\URòè‰'Í¥©4k½jb†a,*سW’»î¡NRµ‚çžõÖV’8†ÁQ¸ø˜ÕJÒå5óâĹjoXfËSÕçŸ']ݨ·LÚ®[¶½ÀÌñŠöÂŒýµo#5l’òÂvÖ1qï Õ{”,®Èd[êƒo½`O±~¬^îéFœßs¾òå½6¢Œ,Éåw_(×lw{'êÝí}ñEĶië@ƒUtlÁ3—¸ÍeÝiF;-#ëp N)ã–i!ÓË—»€µ—ë}ÃÏÉF ?ý_Ú´ÖÝyë·¿w÷X» "D éR‡K·×~båðRlžê½9ãKw×à¨6¬ÿèFßy¯§ÞwNáßyšŠÄ/ööà4½±Mi’QâYš07é4® ,8" [ ¯¡hVÖ®Sihð Å\W”Ä'hÅÔ¸SY•à•¼ˆÁª™Hμ¯íW¿ÿbzvþù64¬öõÔþä­Ç#B$@ŒS5)¹zoÆP¦ ªØÜû½%­5Ä|ÓøöfHzk¥ÏkaY4°„’TÉ‹jdoŸï$dì¢1AA•CL¬é’æWp4¹Tà¨,É ÆÛ»Þ>ȾäbN˜aœZß9“ž;èé,xü¤‘Óæ§óäÕh•N@Òv&·Ù a‡¸z{g)L©ä1Å9?Lí’ð(Íð¡]µ—ŸKŸ>_¿I£”ÕÛéì]T,‹Â¬oŒTwúOö~úY‹ÒrC8 I©°aéb;HÂMÇ#$`)wóLaÄü@ëœÂÏ?o­.%Õì©q)´¥M©žº¼GÏ'ûª hIµÎ\_~@†wë³@"a¾¡:|âážÞÁ 7ÀçòÚÛ+‡v+Ñ)Û}ìYbåí|UÎϘ¯|ƒÖ¨Cì©Ýtd×IT;nÎo¦þŽÞÛ'¿þ¢9såèv­ÂãµXŒ·¿¼› ©+‡_{ÒëÏ76;}»s“¼ WÐŽ ³ä†@µNwœv=иºŽC_(få2.=[1Å.=VrÀŸÚè{F·bõ?I6#¢U5gýÆ×ƒþ>JUy~U ØK7B%Ì~_u´ö´•–}}a¤t{!ð­ZuoÔµÏüŸð)"øæ¡ÜóëJ…¡St1à[›˜Äd¶´È„g©­4‚ÅoB8E@bËÀ€”LQvØC»´µ¹Ÿï­ä膵 Dk¡LYB`ÙŠU–¹_? þÙ éù]äçwiï ë-ýùÛ aõ¥i&±·¿ IµœÍ×Ù¨-«nÄŠ"75E#NýT÷PO8¾è|¹Š”-´Æ´b€¤| £Cö‹¿& E±8‡ÎvX^ÛÇm·Î“-òÄàƒ D?Õ9îqàg"ÕRÆ«Z¤Ø2]`í#‚0™õðdçà‘´+ïÎÏXSKüê¤ûÄCÆÐÛ1ÎJêo1©l¢y—íØaæ æ³ÏŽ]<¼1Peèùäi¤&ÊË83ÓŠÜKßêœ9'WvŒ©·ž†>(ail³ÌŽ uóüé®g6¦3‰¼Ãt„‚Ãà€ìOŠK¿Bñd88 Ú\²)²\Ñ6Ÿ:V(T’R5®îi6ÙN3²ÃS) ¥"¿Þ>Éœdý{¨Õ‹þõŸëÛ“Yyß=s) ê¼Éº¤5_Ý_Š-£A² z7ò¸ ô‘²Æ™PJj†a+jÙ§Ä“¶³GÀ“Zµ² OšgNÚ›Ëиds°0f”¦&ðÌ9;¨/g~Öõ7Si·ÝÚD Ûé`1,QÖæb¨Ëh§ìÞ*Û寮ú‰FÂ`.Ýì$_=³k¨‡Í,¢«‹RY’PÒÎ2”WüY0Ýzâd°’Ì- ³©Ý“ˆ3(¿Á²ªÚZy “È£?ù’•c+o,oOX¦ã®óÎj“ ÇÒ^š„*jù÷¿ë–mc|M¯J¡U®˜¯¥ÙŽ™—&áèøQyù,×dz;S…?Šv„Ä% ¼X°¬‡¸¥®°«ÌºF‚ «·˜çxFÚXs ÊkõسpøT:°ÛÊõÿû¾9‘º’þÖóî µ›ÊçÝKI²ÐIÇ$¦ãÅÈkéè€@G¸SÐÙ!“pŽŽ82$5rÒL¤êUú‰|~/fD8tü1óðYÜÜÄyßnËH 00b”f&ˆÔ93¤/žà~VûÕl§§ 7·Œ…-cO hë´Zt¦íÙ8úý—K}£þÿôººzo§g¨¦ÂöÿúnPÝeÜ›N,MU¦˜Æ\é.ƒ\Ô…þ~¸ôÒúZI J÷çn¦gíä—iâc“XTce‚NV©ÞÕa/”¾ï™,HieJ~q…ÿô} "bkÅ2¦—øÇ"¾v^ÿ§àê­(«äݦ?ŠMÄÁ\%ÞÅ}ÁcßtÇ?Þxð7€KµƒßÛà9ð7íŒ)ÖìνÜÖ<{ñy,aØOîÙ²xNp)UÓÀ…’Sˆ£¦c‘£»üø·ûÿä‡ñNï¤:³²/î;€wšr$ŒåÝ«ã/ýSÛâÙß"=ƒÅ]¥ ò„ZÜ_QVÌõüòS¹“l›åêÏÿf=g¸-? 8hÅ t*âÔ•ˆ/å¤â˜Rj0¤I&¨Š` @Ì®º†î»y3± a»#ÝüK­©Õ⾺ý"sÊå±]¡IQïpáA;ùµGÜ3û‚÷Þ›ÝK`¨„V¶»=gÂÜ1ZEŠsfá7ÿkkOÏÖzI¬œ®–dQg›Ø¢†XÆe«åÝ¿•mdŠƒˆdME!a[N`꯻U+Ä—–~çï9WN¯;RûCˆJ ªãWÊ÷ׂož‚?û þêç"È;w¬/¦­?.0–IHµ U ‚ˆZ±AïPò\ 'uúY–)ØBåP&;6J|Áç3ö5 =H™u¤?ß½¹žKÙºö–õìrõsÝn2 TB€L~>Ã?4›kNUÚq>Z©Ÿ: ÿäyÚØêýû?Ü¼ç ‹‚kóö|­gdç^W_Þ úGKvþðýN÷ ŒOd6`Í %Hˆ´HÐòPÞ­~º]ÙEÁØ“Ÿ»‘òÔ»‘a ØH¥.KHABË(ÄÏ £pêN$Šø ãþêVôËO€‚Á@8& ÖÖºJ˜µÓ•°øû¶ôìqø½¯ÂkÓF ÙžÑ2-‹g0‹éÅ}ðÂ+¹{WV§ ›…®Ñïí¨"ö7Ì,À9¬ ¤îÜÃëSÉ7^´#ÏéD-ÃaÆÌLu°Yé7ò~Ö¦Ý×ùÍß©üéY+ˆ¶´ kv_cm38›·SžÞ»»þÌï[wÿø¨w o¸²Ñ÷ßhâærøÕ‘¯w¤ç¾ýnÃ|Ûcºe ˆ* 2Y“ITë¹½ØüÎ øá½úkW DP)Ë/§j?|’¬ˆ!@ †1ng 5ÜÄð à3*5a«$@-©©Tmp äLÒù¾“ÀÕžZy¤³Š:Ï¿Txãie³ïc¾ÝäRA…D*ýÅ4_zßh­20ÓÀøteûøø/9­íÒïý¤=Õôˆã’^9å•+Ñ”ïÞ›ÕI'”àvÚÁb€¸˜%JkPûž·rÀ:lŸS-¤¶Ãv)Œšþ¢•êsd4µ©µˆ:•"Bµ 9ÇÙ]K%Lb‚©…t¿÷xñä¡‚Aê†ÆØêžÛÌ:)ÉXZ4çèþ†š\¨Í®¥l'Ýž´FÇb¿õ›ƒ/]l­/ëù·âs7“ UZÜžE˜:©*qC“óùF#êtÆó 3¤3Š5à¸?M­\zÊoܯLÌnz̸µ¼™å‘´${øªx|ò´.{+öÝ,Æ®VÏ?Zµ[Jc§­éÛWñíµø½{ñ‡×ôôŒšYJƒ”7[À£BDRKA”ɵÁ5•‘©‚i{†v¨HS…„¨9*‡l KC*ÏδPHÄLj™„'ùVÀü4›]S³òƒ{ÙÌìlZË÷²(îkéò`‘|ÿ¢‹dŠ´½µž_‰’á‹«ÐñÛ Æ’ zìHíÜ#æòÝ ½P8ªo|V¨°ÆM)bŠ`¥LÌ9¡jÇ·oŽ£N' ÍHP©RÎV`¶i—ì~=±µ±ÅÜ3`)ííûr. i`:¤ó:kuu¼ðöLÆ ”&1 ey£ºFïP©¾o@[þìË–æ ¢™¦™¹®V{³²ó1”±»6Ûüõ߀=¤ïÝ¥ZÏîÒήÁj¹§¸Ó|àÚÞ«7ðô<´³pg+½ ܃“´‰ô(aÊ€\ΉišR0&Jaæ#DzÊÂ6¬…dƒN ¶bKâ"1‘Yȹ-¨žM°”~._j*ïR„saKm×™ûd~%èªÿb­q`Ì:ÐÇF¿‡Ë¹Ý»œÍ–JÊ¥œd玖Î?´qû¹Á´´y—œ3*Û¼^4y\tx³Ê<Ÿ:n,,‡ë~–3ÐNdbC)èDwa«Ç.æÖ<ÎQVD•5]Š&fÉ»_î4Sv°¿¼·2šîÃ}Û[| 5 Gð²\î#D«Ý»’Š–‘/íÀþÃÿ¼ÕðØóù6ä-%³NJq™‹ä Ί9Ã Ë ê*6N[e•¥tÌpO>½µµ0Ó•›«{œB’§lÔ%a› ™2°4†å¦ ÈG_JÓ ÜYßÖRlÒ?|§ÞÝm½3žb#O” €Å °Î°¬Ò!-ÏÌ ­•Ðæô œìµ‚±¸÷âØƒ…9ÿ¦wYŸ·;Höšp‘ BžÔXc<™òX¶¨’ÑÅ…/ÖüOÞ‡ßþ[•¯ÿW%Kt¬lËÏ›•X“³~§‰nûÑ\\ܧ*e¹Ö&tWѳÞzmÝzi\Ösý¡Û6ƒ^§rÙÉâ$H³@t›µd›?z6ÿÅ—A¦°Ð1ÀÁ`–a²h‹Ô߃>‘«OÍþÚoÉŠÛ}åªoÛñÊû‡°û‡¢4¢¼ùþ5ûþ\ÜŒ¬z}á3†,b’àJÚôœB+ˆŠ¹BÆ=‘T‰ÜBäÉØ7PàËÔÜÐf¤$(Úà"f¾`iOQ‹XB¦ù‚×ñã¼›ªi1Gïˆ:^ÒÕg×S€®.ó_þ˜Úã’Õîæþâྲ¿Å½½tsõâ‰ü¹Ë[wÿÌêó[B™¦E+­´ã™*í³I=Ì PE§ŽºS«éªïÛ¶¹B˜Ô-C/˜=V±`Ó@m1(ËKPÓ7ÆáýëÍzšpÃ(:]´§µ¥ghÇ4á`.È—ÌÑ=ÈãñÈXV0Öû€x%Xìxü_6Z.ì‡Oæ¤tTÁ#ç­Í'P±Ã£u*ŠVè‚ .<€f)æÂC•“æ•k…Õ]Ñý•^‰G-gäi×$ÌP«ÁL,4`f8 ™uõ¶õ?lj4,C‘” So%‰gÖ5g6à€g q…kpØgŠ=ÖÖc·´ú š¾Î ΉÓÌ êA¶„ÂUk©o.wöét/±OÚÖ ð¡,”ú˜ab1,ä]ǽ‘iÅÊëÿö‰žÑ üü¾y§90L,‹º6œ÷z-‹úâÔ¹šìêZ›`{À*©æ² »ÿ»_Ï׃lqI‰_[-ãÈÅ*ÝØìÄaýñ5¶$œj¡JJE`I­K„¤»sÏ>ïÛçm®d<Í99³™Š&È=ƒj_>—Í4û)oG¹áÝòñGdäší¬µw@ßû,÷ÙLvo.þäs¸¹ŒuÓŽÛ‡kù.?ÒÖ6ë6 y¼j‡›Ò.®e[ Íxv˜ŸØRÄ:…Ä2«\DÚÎ3á[PŠiÂrP)†–²Â0{¹ÃR=áCÚqxSñ-É|ÿZ˜„¦"\0d´ ðЬHE놄7c>¹èNßÓ÷æ³fÛJ×1­„+‘ØXÿY®è­xØ [Œåv™›ŒÝÞÎ,P]Ī«'|ç«¥ Ç“¹i¶é”VRjX—,#%-à_}Z§ cYy_ñ“/åë‰(RêSûK¿÷¼{£El5zP\±Dè'ŸÙõÂ1×mŠ3#…‘’mh7„p¶eþÛ?oLd¹¿ ¿|ªïêl3 …)!BApT²2U'>Áu·LŠœ³ó¢Ù]™E‡»àJìß`b+êÑÖ[.þq¢¦HtH¢ó*ÊPZ K„.¬O™fRÔæ·äZ,”p \sÃ.lDäÁ–Ã24\QÇŽE a˜~LàG$îûS,Þ „_€K¬ì7ÂÕÖž•~ÕXÝ÷ 8®Ý‡; ³Šb5EŽ™¹Ð,°ë4©åPAÿî“ÝûòúõM}g¦ÝßÃÊn†Ù]6z¨N:Éåã}¤»g{¡¹+Gµ6€äö—þÉw•Œí¹…DEæõ)±ZGGÏV±Ž9¬NŸ\“A” -T®É3Ǥɞ~xþ©ìÀXuu»#Bw ;

  • ÚO÷w%|’R½“ò±ÒåÇZ’F´»fnxψ¯Öo]Ó73A}Uƒª]ŒÕYlZ¥D6·@neT:嵤ÞF,²²¶ ·S#2R&R†©#—2ýÿhúÏfËÒó¼ó¼³üÚ~oò¤÷¶2++Ë{  Þ“@Q¢QS *$v‡F=RÛ‘4…ÔÒHl5E‚ð@¡”ÊgUšJoOž“Ç»í—{ì=/ó~ïþ×¥‰ðíh øÔëºÛ ÕÕ²H\Ý™º²¥‹MUðhl%9+¨.I‚mHØWiê*f¢“˜«÷Ü+—Š¥®¬ñtÁúÃù­äÈ þë/êtѴϹ“4-,º£¼çÈ ŠklÊJ îpœ}õS͇NÀ;¢Ÿ™©*èƒ!×-\c<´/>gLUÒ]XÛ]~ëCýÝW•̸Õêøÿw?ÏßÚ2÷6’’Öi£ê#ÏŒr?qüÄ0ì \š¦ÅÄü‹oÈk}úµSî ?¸™ö$z”H3DI²KÓQÀ“<Þ/í°Ívš©× â¾Í:G‡úï új³Ô݃ÞKþµònÓä€!§5ÔcPß4(37Ry¢QjôïmôW ‚ºî¢Ã –P-³Ä#®¥‚F1#ƒÌ©¬æO>%f7쪀é'üø@åÎbgm­vç{ý¬¸¾áßÛl!º.U¡±RWº|°Ì’õ;Ð" üŽMDhEá ) •{‘E]–2ô¨áeJsjŒs¤Í(CbQS(‚ñ³(“)]çžœ†Rr¬pGYF@€u®é3Uðò I;rhËmå#î!U)êÍoõn.º\6ý¶3:R{“:ÒW×%θ=ë/\Ókí²p9Êüàáð‘'ÝZ¹×¨”._-Ï'Yj¤!æDF‡ðôƒ²\÷É?ê¯l¥#îOë“»:§ö—k;¿Š ‹†2×nåWÏw+÷Ô¶ãÍ´–µÓæÿñµÒó?v*ýòL@«>2rõJN!No…ðmŽØ#Á2n|n¬™2A!q 5FÞÞòÜ\´®ËFOü]KÞÖª„\P]³´TæœãA(ï6ÂãV“¬0Tz™¾’‚ðrÃ-B[Imî¹RY ¶æ’´ÂÄ)ß>•Ãi/d<“ž{­W)¥œt2>ä—"QОè¯ÈVm*$µ#ÜIP¹†Ñ6µ\à{>D•ˆ¬þäÃ{ÖŽŒ;I.޻߹í>¼c8¨wÖµ}ÿ•òÚùâGï÷®ÜMƒÜô¸éyð+_{VŽ1y}Ź3§-ø"ð»›ùüåÔ­D?˜E}íëžÍ,%FFÚéyòdnt:¶»Ê ™[ÌlTmªá™FûÑg‡fדuÅšOF'ìܬ³U¿t‘¾q]|¸Ì×6z!Pès«D©ÃŠ%–o橸¡e¹‡BQæÙ¼È½’%¦¬MNÑåÖçh•£µ,<êiRx.e•1–Yž¶Æú¦ލ.t€¨Œ¶Œ6™Ÿ%Yj‰Ö©Ÿ÷˜¼œdý®6ÝnjÐg8„R™jgn#½·á¾s^Ф\«; ÓxûTŸ·ïtAŒ»}$\¸®×ÚžŠ•ƒ‡¼Çž·£Õ¤ù\YWåÀX…VUöƒ0"ŸÈ'ÊøÎ=öîO»sk¤P"hÓ«5G:OîQ﯎Äüƒ¥U:ŒæÆ<}ÿƒN<+Wº%gçÚB‰êÿû»|¡«?÷~úq邨N¸g?¤`j™ÛZSµÑ`°S[ß%´¶ØÚ³¢Å2¨èNy»5?½Á"­Çªp‘Ùפiè(eyMÓR™3jAe¯!·–e}“R"Œ¹¨4çàX'cm,áq4ªtÏwŠQÅÁøaìï‰aWîœ\0pN«Ôõµ¸ŽµRÇd¿ Þ/Š×bß+œGÐæñÖ/V½*®(¶*ÄUé@I ßr@ê1Ïë¤DLWàKdžü@î%½véƒEõέèð.6\MϾÞKÉ*À°o»ÚîÜú#ŽÊñÊE˨S0~î®È-håFž”7·o]”Q™Ì-¢Åh™h†ªŠ†ˆ.Y˜< Šst¯–=TìÞ[oß(> Gö—wà0ÎçþãWz¯¿í®Î÷ÔEQbn"í²†5Ïïš’Ìs4ÈÕ’:ž6šëxàëêráfàÚØƒe)!%ëZFÚ*Í”C1T$ >­¥ª®áPÖÚhð'-8XÇw…d`Áñˆ1Ʊ\•|´„Ü€UžÝ”°Êyj´klp9dF-Ï‹³·Ãëw{ñ°ø{è4úYìˆ{sŰ+¿ôüÐÌX¾þ·Ñâ9RLeÝ"YX‚€bªÇ4eJ)+U* ³oüµ›õ U+€–X<|ƒ÷æ»Ê‰‹3§ýn×[都 mÍ{ˆ„‡=’ßïÿé¯jƒÁ‹‡õ¼h{©ñ Œÿázº‘Ɉ±\Æ4Ùn€ù¶–YÍjרJ'Íö‡ÌÔcaz}uG®;ñKÜÏÕp]GA­É‘î öŠu¯"¥î¨5èU<=£Ô˜LMÊ%8•qYdÀh@´òü2jáCz+»¬>ˆ½‰ïž§ñ{²X¡¾e‰k¨ìa¼+¿ ÑÁ Ë êþ|ͯم®§NÉÄU0i$•„ï¹ÉßkçDNUà G‡8”'À Wz%{ý–wd‡hÊ7Ïâ\×,k0£ w?÷¼k ¼^Î$ƒ‹·P3Ø’E1¦Ü»ËÅ¥sž ôÊF©Ø¢:$ +¬ª† _—”;8ßû/}•9Nv,¯Ýnç¦wìœÜëìÚCœ)÷~"_~5{å]¶>×åDqÍ|„€{=‹–®³°CXÎ¥Òh(‘TS‹Üx†+à¾UDRé:@e‰mªú€5K &pJ…–Š0 ,hê Ñ> S€«‰¥ÊR­|@nyÎJT b˜åƱÄ—B•`5±Òö®¯ù¤¯ÐÕ¶IŽš+WîgoTnÍ·J#Ñ¡˧Ïk5wÇKõ‰OF‡†õýo5gÏf8";Öl,é€ÒD7$¤!ãS×sXøŸ~ çf]À”e;u há Nv©®¼úË4ŒÌé“^' V;ªJsI¼ž¥Ö/y7úî?ý¯õåþÖÇ÷Å¿÷‰œf ‰ç ïÎf¾žÏRÜU•ï`\—$Ixù>²lDO@+ ëº0ï©@2Ȩ§å"µãvl> ¼ÈŒu‹Çž “eáî¢÷{I[±’"çpï¥Ê–Ÿ%…¶.ƒ$þΕ·îÂÖ¦“ôôG‡ë}ukcpåjÊìþwgWsM\€>žþ”J7¡ÿrQYUkY‰Âìm1Ì­îYÌФ(=—nyl2’@Œ®o«kWX-3rrn—·ÒŠÉïäúä³ä™]d~0T«±­®yéµô§¯êù9­¦FuÁ¢e[V·ÐvÑäh- µ* ReeN¤ˆ(‰– h¡¹!q¨¶¬¬¢šCN>m¡\ÖݤäÐ1I6Á8 tO¤j12Nß±#T‡ûÊz¬Èj®Ae)‹sµRÊ–G.Ö¥í)"­WŒWTø\€’(;`; ¾ÃƒšM“ÎÝ/Ψ–úÂCêýñg`h»¹øJ~hKmG±$jIÕÞ^—9’Ò!ˆ‡IÙÉϪȻp¡°HZÌ Ðf<£Ç];özýK^éF7¿gËÛüGÏ (%WWêž’Ä‹inÌŽo¾ÚZäÌvøÇƒ wìkWÉŸžåß<›‹þ0q¥e„Éf—ìö1èÜw`0\욟Úeö‹®¿oºw,·þLºN\aõ¦2jÊÊÚ“·µÚôœYi'ø¾ù¨S?At°WFÛ©û€1G³Þ¯2-ÔqMކÑѼÿ¨ j»C¨ìnOícIÅ H\Øb¬§Å>3)­S<ú8ìhX6ƒ+yº^ªáça×…jËI2 †¿ssýíy¶¸NòžyáØðzÞÞ\½ž3{ôÝÛT›˜êÂy@~ôÓßrÚ?Îëd­[§ÓpïvQã&3X0›)]Pt ¿q›ŒÆºpsækŒYÕ„&0G:±Ý+ßn‰†MnföÄ ö©ì~¿Z­xí>ùñÏ“ŸÿRÎÎZˆ 1’F ÒM«Z¨û¨r´,52deär×([4e¤G‘'R–r¤ÖBK¯i‹Ï&,+W²Aî[œ°¤g­aÔÄ|ô4Í©FÅIL5ÙñIi«¾Æp #-ˆÄ22Æ0/™¦Õ™i‰:Ú'eµtÈ>˜>3vˆY°w°yÅ©ßèûèO¸gNœßX®»ªH9ŸPm'ÿú•֊韙úêSpî¶þÉMû§oÆßx?—I ÈÀXC0o5i”ïò“y0d¬yB=r€ë×mûšu0ø±ÎÖÀÉQoj+xY¢´:žºO`=ðçµ£ÆuÍг|ß 7¤QŒ9áãH*zÝòx!دøŸ–ËAªZr0ó+Ãɶ—$@|ýš`ç -¬P×5¦†Š‚·E±ð©È@ï¦0ŒÑ²´;›–asÄt‡«f6šKÒ—¡MUÉ¡aAM ›Ÿr°{Lß¾n?ìoß5ßû 5¦¤-Vµî!XBØ©êsÕãe¼q±-–&x~Çd“3ã—o&m˜$ÔP.]ã–>v¦ôÑÇü´e:‚Ó~A!3ÄçÌþ öî´°Ëèè$nßÁÚFÜháÝkÙõ ~«1OC¨ûdv¼b€&b8Ñ”jJ€€EÔ³–:×&±¤@Êýh(-ú– ¸>¢µ4éÜéô[뢢ªÂ¹ÅbA朡•¿z§õÚm{«ã›Añé¦Õåù’öŠ2Ô2ÌÊnUñjexèÞ±}Û|Yž}_ö"Áí9£ðÜc} %ê×LÖnY4€>ÆèÝQÒ?ê£{Y2ÝX:·9®=·Z Àް,öL”†JM›tæ!ÿÒø§ì>?cÚ½zY.ÞUà®P ¬ŠP¤]¤™ïVñ ¸Mä÷3Ø9dü)¬5í`tXÜòîçùOp3’5´NæZÔŸxãà6ºtË|¸æ¼}×ùî¹-k­¼L‹­{]_k,k[À¶ƒþGŸ’£CpãRÅ_ðvùr^%µ“W¯÷¨Áx9!ˆ ÐX-~òñà£ñAKõ{Š‘l °°1òÈ^¿vo¯ê­êvÇ.èòfÏܹjn\ ·:Àƒ¾îNjë }T9 áDQÐ "Hˆ îq% r”¦…@’!÷‘Ht˜|Ê)ª5'sœpu_E-°ûŽ•cÑØcGЧÀ±06bú ­¨Dˆ]5,͉Ў)¶sh|#íuLá•´Ö(¡  õ¥-Q—ë¢2Œ Ha ‚Ešƒ"`(aQ!)°Z àPâw7£;·Ôj«ˆGé®É¤á¸Ù†ZLp™Cm¯÷ÆÖcÒj5ĸ‚|鋾váÆ¬2ÈzÔ" rC ²*j¼“;‡Öﬔ¾2ARË¥£Û‚»ínkÝêPW$[È¥v Nöï¶Þ¸åÝÞ´¼G^x4س§u¶dBhdSr·B©ªa­þ‚êˆñËD-ñ×Þ²ã½Àºä¬–Š:¹Cú†ÄÔ+éœIÀˆžD‚8Á¬GáĉҾ±db7Kf†Zï¯ kµ’2£\°£~ Šïët(“rQ´gfˆ«íí…°}ƒm¹‘5ª]Kið+­{ýëï}UÙ~8é*q¿¨xÀŸv?¸Üï#ö™§AsC5ØÂBÅ:GÇ‚3vFw;µq7iËÁ€ OŽ>:Ý<ú@6ˆ0Þï¸cð‹³¥¿ú©ê­(•+C²`GW{@§Ÿ[mœ:FS@Ê£hC ü²J Á8B.¥ôho²š¦#5W'B.§5©­“¥è£)fMu#Lˆ²Ï!_~Ñ{ô°Ü3äïc{¦Ã“=Q´W»$!ª¦êã*÷,™Oõ,¸ÆV#ãD4Ý;Fö7cm»ŠBæ¾ ŽÃ ‘1+êPSPê ¡ÿÏV ¢s×)(Öj#]¦ ³B:âç i7¶NØvæL¹»{íÍðÖl·ÏüX;û¦ðäÕ§žÅÝÉÝéý5wÓhM0$aqlì°¸Ï=„õº¾°!p§ž>½~ø ¹²ñðhÝO6-r€a´ÒèÕlЈKt¿üþþÃ|ÿóÿ} ÈÝ9|c¥ï£ßåbª0üІùå žMé|“Š® cuh!ÁüK¾ñ$ZŠ}ÜžÒP˜ ˜ô††ò”°K¿hO¯‹~í?fk Z q` ‹‘§ÞU½ík®ÁêPih\¯lºæ¾sHå¡­IòØWH·Sõ%U=¤ì¨ŠŸÒþN©Ï|é,ôòÁX-ù¶ÎóÆw‚ªdš†äèýÿü„ª{ÁÏ/ç[ë•ÇÏdC¾|qÔ'ùü,i2_é$A~hWå>ƒ\U6ÑíP±$Û€IDAT^¼›-ßòœ™¡/»°e;ï|h )"€eÈ ¨ª‘ïS5}ãO•;ÀGŸ¯Õê½|Õi ûÔa}h:ÞÊÉ{WÙ¯ãâZÆ©ça¡zoXÛ'Z‚Ak©V6 (‡3`Ë@§8LY}¬±¤ð=¡""Ü÷Ð_†þÁ“3'ö¦´gŽq+ò¹õ|MëÒª?,\µølW~÷cvÈï1I® ,˜dU>Ø¿®Ý7›YÌ5Ùíä]_´Îg´Ÿ=,ïSåOžÆ¶gŸxdtlRg2˜[ 5xžçLYsœ&!`Ĩ± Á8”¡¡CŸŠD[+‘f€Õ€¢(ñh¼¸:¸~ÕMÝ`÷rt¤ÒêÞ¹&GúÜ“ù3Õ[ïÀÍŸÊjmr¹·qgÑx~)’€c] ±k8ŸÙá¥ûê }ã•þ[·Œp#_çqÙþ£¯¸KmXÞ° u-t—þΧ‚¯ê‘Š*öß|·|ccð¿òXv! ¨¬ „κx ÖwÒ­•Å7úSƒõĨ23X#ÊI¨Õ./Sû[¦¼ªÄ†å¥Fy§â8¥C·0 Çee/=w#ù¥Þdð ÓEÂóR¹³Føµ8B‰-šîå~iùVqöލ¥ûFÝ¥G¸r½†"LÖK2S{”þ¢n\õs¬î å<†Þ´Õ©gb/ö“Þp9ÿžMÓÆÊ[PQ¤‚ã±æŸ|NÅ•Òk³fs½òð‘Îvϼ¸ÓmlóóXdž4yBðÐnïï¶üÁ¥z2-‘Kw’õkž·stìyd-ôú{W°§ q, aÖ!Ä©r ˆ¯æuç¿h‹'_h ¤9h[xî ßn¦Þ»·Éë¯óµåG#¥FÞ³á:= ZI,BQ´j€Ä@'<†·G©F 8¶ó9÷÷ž9±K<~T=rÄEQÌ®e ©kÏ©G=OÂM`](Å¿ùŒœªfyf„–RJnIÕëìÛ×ï]ì&ÐØ9CÛÄ÷°õäâ¾Ð|ñ„=¹;ýÌc;w¨<‡åUòRÀqJë34w‘”˜c,Ñ€RBÐ2оGEª-*trª‹–жÄÑáÑêJñá5Ûº{[td4ît;o]3#PyñÙþ'ëíwñΫ¹çW:rpcNS/̵rГ1j|e=O>ðPv`_ÔßS™ëÛ·_OÞ¾e xZ„±ù“/G«-w­“{ê^ä{ðw?m¿;á¦nSþ›ïûWWÅß}ºôëO¦7×åFâK]øà^§ò€³7ûÉáữv':>w䘲Ӷʔ×Ei· úk¦¼iÕ©ŽÂ]B=`½ƒŒdÄõ&qø{ÿJ¼QtüH÷rê‹(ØÈkE®Ì”GJÄǹ™1µ:c;›ºWòYé™5k2‘+P©yG¯'—J[;~‹ †(ÕÒ ÝÔßö¶rñ_Y7$¾RÊá°·fÿä+¥|Ç6o~A¼³$`Oïóß[ÿå§©#´-ŒŠkÏ<¿ñd7täúbéN/_ÁªÖEˆúÎ=¸üM×2Ýh,ÍÕý…êy¹EQRŠóú®=õµëƒ]mvå­%ùéÏUNî/º^%k¥¯¿"^}7_ݰFœg™V[Œv,¤`xàPðP¹BÉ·…öÑXm­&H8Ž8d˜ý¾wSé-[kÞ¥ãóÕ™ážÜêäÀLêxÜ9X KÎÅ»m¥Å¨TÕoaOhõ÷>ÝØ§…$ŠtZ±Ru¸D¦ÍÐ-7q¡M Ÿd>OnI£!ûõºŸ~¼æ¨T&FYf½ñm|ß®rsk¹%Œ®Ô¬9éû#J:ûŒöÀJ´Ú"tbjÐPDêº.s¢D±tÆÐÓ’q &^ØH¯\÷®¨®£ëÓ¥ßý¸=²?þåדñe3Jùõg“•;÷G& g!ñ˜Ÿ³!ä¥phl*xóç½üTÜŸ‰QÖt9ñšŠîíœ9ÂM\¹¹C.|_^L¢lÛüù«îK—£cÛŠßzº¹8ù,\Ú¹Õšú$bh3R›¹ÞÄ2³é™=ö7>=:ÓLU«—Yf â}ìhÃÍÅ»}­å¨.V¯š竟pOLÚn“`¢ßs”¬òÈš~½2^}ýƒ»Íõ»\ÜÚüËÏùŸ|,Š©MÛÚÕ ªúð¡aÙ'³K©0tÚÕû(Œp8pÚ'V ÒHÐ2@?¢ÒXJ€r‡æfÚÍ@Ü’BùT[®nŠë—‹»×uD<ýýOCûù[ßì-eÃTßLLij÷ªÔ °œzÌauTüpxdWøÞKí½nfĆÁ„ó€òƒ£îé½GÅÕo,¸ ú‹¯,qMŒï,ý§·äKÄ4ÙW? I–=tœÞ¼[ïô‚›ZP¾›eƒâ*z]=I°Ml×ÚoûzN…2S6'lË1×­éƒÕB â^åz˜jªezX ÛáóßÞܧë[^zÑ€Ç+y‘æeL)Ë}ÃÙs^iŸd‹²¶³½‚qWØj„×rlX×e¾ÑÖ_1’×ã6§&·¬z—ÏÇ ï²¤a>ËàPÀ9ºÚ€l,¬yaýC;½]Êçz¢¿Æ¿¾ }n¤ë•åsÙiê\~_؈dFx×XZòÀsÕ4-Œ èÕkF òú©2€ƒFn˜Ôæ;Ç´‹ÙDAŒ¿;œÙGï¬dWozæ‚ÍÜ–vÑ´[@¿ðEfCË}DA”fF´L¹×W91²Ä­GA@ÔŠÆ@G;KßB˜ û¿û©`¨ÜÞè«6”7¨ ×7z½Šã3k[úþ†ôU˜†rM’í#£?Õ¥B'>l-Å翱±rÅúè5 ž³ $7æ£Nš;žÓÍE¢Gö†_}ºªåzG›ò¨W0AÜr¿—{ÉÞáêõ[²¥ØH•L°+—2@ ÄÀ%¨´Z‹ ¦'ua˜´nYj§亊4`EøWû±§õäXÞ¬:kKX¬ ëZ9Fd087›@à à  t_:W¯%«]ÓU–ù)P¢Í(%Ñã øo½¬Ç*tÇn³¼É=ª3uyÃÙÚ ?¾™Ymþå¯ò*Ë—’èÎíÊ›7!•š1M]©Ü ìä·> &bÞ–Kß(”DGœKÃ×´éxž¦š—!ès3Á¨v”k—oˆ‰ L@ÇF^å†UÔmŠŒ˜2ñ˜ea8Lq1iÙl» ‚U¾Ûë–×M À:ê‚/¢±ˆa9b6C»ß ‡_Drù#@P –_[7oØ«¸¡Sq:»gØ/É厖kÞw>@è1¥˜ÁGgÓŽ½ôA¢Ã87[Þ5š2=×áÍ•Álà_¹š% Ž”² !¢ ¸@Mz†œöÛÓ+Ú8ÖÙI¦v‹å^vé²wî^¼¡L¨td±΂¥O ]5! –¨$·rÍ$0›ÅܺKX¬hSèI²²6!ã¾ü»÷ÆëõŽu*#ÂëWGK«­,"Ù‘é¡­ί¡§HŸ‘5#Ç+á§N[;(dY/ÏÃ…ÿš-]Œ“êDæÅݳÍvJ]¶3Ù~zWùwžUjµgD4 žl8iÝM¶5ùµÙ¼¥YèBµ .àš1Kb0¦èSkŒ()E¼ldb¬DGhæ:J±¡=—Óa«|ó*ºµY¦6™™Èʱênyƒ%#èÚ±éÕÅÐjDå0MW ¿u»X^WÔÖÍ)C£‡‰ ‰íÚ/½ ñÖ+­ÑØŸÞ#–W«ý¬§2~qƒu–øËw¥ÈÍ?ÿu¯ö{ÁìÑs7ó®d–XF,ìlMõ‹½„n¡ªrÓ!¿”J ·Tû”jðÖT¢®v ø$ê3½=„ºòX¨ç.ç-@B/¾m$AðuÎðç–D¯«²y=0{b¯´ªÞëÄ»„ëS}EÛ>GÆÛL!øÄÍAìô-­²iʶƒšÔ&ÓpÖìz…÷¸ 8Å‹Iº©_g>ÙÒqG³Œg“µÁGN V¨Kþå‘]EQ'rn+šéçιè2î03®ÍX„‡DÌCÁÜÍÁše¯”¥B„õÆœ ÐéÌÉÚò«|b%Û¸¥¶=$ö‚»·”qL½ëÍ÷øúÀÿÃt³¦¾þVôׯÑWntãØL튷Ö\b¥¿í(ÏlÛ†ŠÑ«>ö$3„žÚFX® ÊǹݠAJ²@ÛÇ ”Lýõ.jç6äÆä+Êôõ u…ÃXcÙ–ÚN¡¼\)ñ& Þgý]žv¶à\¿ºG„Üd×µíqk¸¿ƒ©L1`X9íó ÜØqp&ˆÞ«Ô@Ãy²÷ç¬íaD­e\Kíí; F¸/]k]½Í6;dl\î­ž½ä­nöFSšQ:úË_ÑÃ]ü–ltíퟴohãzŸ@:ÝŽP]ëš04EÆ´9þ¸ÿÄ3ÚÏn*®u‡AŸTGŸjÚSO‹ûÚ]ÎöS¥7^¶_½ävú5•qÔ+|x¥@Sòh!¸µÂ ð¨&P Ì *ÆK;GÔL3lFÌXL -4Ó@YàO)rGÑŽ_ž†öOд‡áݫɵŸTæ:;÷oóE&I5Þ¼Óß2~GCîèm5ùôqI(ØrõêKßdÅ\§4qJ3a¢ zïVo¹=·XM8½g 'jƒþ@»Áž÷_Jï¾Äíïžlªõl¤6vgл»fjEåÈ9Ï»k`Õ`|4$»†¼±††:µ5)»&$­ëh`.L9dG›5ŒÓ™74&B¼öaC·²]gJi\K"yò±@¶Ø ,Aø´‰*bpø÷Ô‹&‰ï]ëm"i¹å´p”ÖKê”ÛYz F—³•[ùôI¶÷D÷îí@9Eµ7z^·ýÎs¬1œïü‹Ÿù/϶ãrÖÜÉÓ5GbÁ|—÷á¶ç³m?¶+F-yv ÝAûfÒ‚0àó@Ç€E ¬ðQ=Y ÃæÙN·Ä êü9?SJÉŒ€,•e¿ Ãgù!–‡¶³CúÓFšƒrµ+: ƒþØ•¡qÇZNá'Þ ñŒÅï¹ð3N/F’\²·VBؤÿ˵ÓD[ñ.´Š7Þ¶|§Û–—ÊÁÿçà˜¸zÎ-’ÑZyQÙé­Íç]Š[ŠxÌ•XÜQœó²¥/²øƒgŸŽí—Ot͈õA£Ý‘\´1¼LÃzÖ °¿ÈH±ÄX¯LXÈåµ5÷Æ-²{›yäÛ}÷v1¿•­nÖJ»O8Ï>Ìž<`&êøÞì~ßhNs-€¦>儬_ó̶=¾w»3¬``,ч™cÇÆÎßî§9÷´¬ƒh‰ð¯^)>ìIJ½?8.?úBýå7ÛU3#ÍÕ®(q% ŸÊŠØ—û£@Ÿ¨JŠžuICA~Š íÕ…5áŽãp5ªîÜÚ± s$„NÖêÚîÑæ“Pú…—¶U5pÍóˆ?|>~þ(þ„ypwÕøþµÄ¤é@PŠ~>HH/÷G¸ÆˆÅU§rÄ?zؽzA®eBr[Ÿz€Tc…Ó#d{#øå_µ[WôÎ2á=ì­¯eÛÇdnì_þP½~^šÒRruJ)³a¨¼@r ‚µËVÆiªÑLYÂ-~ûs|´âÒdÝ™ðôÔv¯R©¼3g’]"2÷øÞ!sh›ŸQЦ~÷r#"æ¾&ÍÝÞd¥Äµ·ÅG^?ŸpTO²Æ¦¤ƒ~±§7ÜP½"oÌ”ýÑvs±÷@ÕIºQD/v¼¾/|?ÎJk<ÍŒ:s¢2*ô£^ŸÏ_Vô–79y”zeJ…¸½Å..!:&ãÐFþ;Ï{_|¤@*óNæíjÆ•w»ùZ2;à`tí OcôtF pã„ÒgÊ•–¦Ül¢4ãek3òþmye*+IgŸ;Óøä3„/'÷ß4s7t}Gps¥twkÐûo1y`Ý®QfÊs>ÿx­kœ¥µ¼zÄ}8º|K¼ѬvUào£j÷DBÂ.ÿñ³ÁÑ}ÉÙ²·îÁo?ë}î³úþš^^·Uâ¸)Ù0Cw5ò ÛÆÌA§<©D‡³[Ä!•kvÊÁãŽwœÉ)ßâä³%ÏÏ7—,•êØ®#´±9„„*·ªÄK¦÷XЙÚéíÚåݹ18ÈË2½Ëzsª{£lhšCž=eôNZ¢Ž½áéïÐUÍŠî»ÆTÜ#ÿÁ—£‰˜¾rIìÆþ'ÅG••ç_[óT¿]QØO£!®Ÿ D;‡æžš¶Å†­m:N/Ÿã›y_Q#MļÜ" "Äæxer’¾óõlë²Ï<ïNø¥Öýtz‡ÎûæwÅ´‘ªRÃBé9ªSJP9¾òåspHrº“ -–Šè3#úï}:kX2(³R'{`¯U+ïÎZJ EÊ+N–€{h v2€LF÷®—<-[Þg&š1Éýn{å|›³â´SZÏKIšÜMƇTšÒÉ™¡êøFý`1s¬¦e7ˆøÍuççïˆH•¡Ñ2d裌Žñj§ãÝ¿Š.'›Ayú¨Ë|â)ÿÊûp,3*m ©¦¿ûbùK(Ê…èšçTæA<°'LW‹{™k+ÚÛ‰ªl‚¾•ÀQÌ—ž£}`^Jõ†Íê®â†]¸Ã?¸a*U‰"_¹‡/¯u7÷Jòâ±·–‹3ûþÆê: U¨t†•cG¥†¿¶€këÁÅzvaPm4¦Žmt«æ.ܲ šaBNˆ£dè:CÆ`³Äщ¯Ã>ß¹¹’o;XyæÁv<¹ýÕ·“÷ÞÜŒWËfQ©• ¥qÑh)"eÂJé4“àí#¤Ìì‚ëœÿá'ÌT-S…pʰåUàDtj3>5'†_»gVµG©RÈ=äÏíÝ¥T›ý¡q~‹æ ùÀ1UÞJð^Ÿ[¿¼ Çaì°»Ñ1fC¼Ã{j‘îcš;Þ°+ûƒØ…ÔÿÆÛf~™îüÜÓcžì³gªMÛi¦_r:qtâ±¢ÚìÑLV½ÃóNo)E"Í’ò„©~ì‘âÓ's“¢å€U¯ÃjG®dÝï5Êøæ Gh8æ0%cÆL0ìX¡ ‡¦€"7Ð_ŠfgÕK7Ù{—yw€{qø Ç7º}ó%sšÛuWCÿ^7#›J“ÐjPÌ× b×68Œ5íÃg2o¯âåý‹‰øùÙ­÷κ‹«•Ø>SÚ?Óß\­GÇ.ì߆'¦Û‹ýáùæcyhkä‹GÜ{KÑ­ÄrN(ïä–n¨Ò¢Ö#MŽ˜‰"ÑÄË@N¥’óF³C#gž# é`ÎÆš8@ÓF8’˜. d„†šN 9ø¨†)ÃsÂé~þà©h¹¯Ö—R±Ãl «%°Ê „ìXIŒnUÄ/3qUz) BÖÍ,Ëbï±éò?ÿ‚uDbHqsnòµûöÌ~>í˵VÒž_hE*G¤ÕFi})_YÎ_·wï÷Jõɣ3ÓO­×ƒäÒbdÖãà“9.Û.QVŒ+ÃÆ5²Ÿëëóvçù‘œíÚñÁ[Å{ï¸yJêC¬«õÌö‹ÖX°HÑQ ³m€¿›Â¸Ë6i[ê¹Î¿Ègª½B*' ÖKå€sND‘ØÛ²–†÷¼k-•Úñ˜t>rx&ôüÈ©±;TQ‡ª¨•Å„¿µ¼z~Þ ÙÚè%¦è@¨0Ø»£æN’ö›ÓQ³ÄL·qHÑo½mfWÙ6*ö{ƒ%YIÜlÇHÿt9„þV4“÷bÝ-y'ÂJ+Êuý¥«Éý-íœÏꅦϞN?ÿ ÉZBS$M¿Í*Ík)jn6T%¿¼Á¥2 bŽ1ʪap(³f¡š¢‚¨ö‘ä[Ê“TNU ü³—+mý¥/}ú¡N·|åç½£¬bXn¸wbÖ æ×µÂ™Æ¼ìÈ…f]?ñ”õ·â汕zvùµ·íúzh­šš)ïÙÞ[]©Æ˜—PšÂSÓ½Õbüù) ‘ê')£>w$š] ïöz^H€ÊŒdëÅЂÑ&*êQÜZCâú~—í¶ÀU2›7ÂÙ=þ´³µA6ïä1Ø ÌBÝú)8’`¢ †Ôº„ù Bž×d7ÉV´yˆ4½nTS«+Às°Ö”èPCµŽ@1](¯;Ù+I¾E òJ¾¢]C(fx®ÓƒC¬YkbpuÃØ0Ülñ¼‘r¬ ‹Ó;Õ}Ü/¨¿AÀÚ“,-e×î¶îÜ´j«¢¶¹®<Õ !ªÛ$¥ sD¿G¶5ïÝØÔ$V±»ýáøËøŸÊ¼›5œ¼ r.牭:^(éÀP@)3…&†r"¸Ã±#®sÌ9Ÿy*^ég%V¿}ß¼÷r¾¾PLNZDVñ8ïܳä["è¨âÄ9&D÷¢CGCMRÆPè‡;þì ÑÛ‚ã¨Eh–¤;·R´îñËSðSÖ,9)wþâµÞ+ç¹vw,bM8÷-í™ðÁc£6 Àmx`oÆyà‹¢âÁíMñÝKJÌ!—¯“‚ü«Ú!ÇU襹~ãM}ëƒÌsh½J6­Ù6^¾q×YîK×q™¸j3æâ&ê‚M­´`-' ˜¶6LUÔÎ éÑP÷ûúâ<Ò0Úá-Ü&Yá/©lê¤wcA¯öB Iª‰íù‘WËfh}|ã·˜@¸·éá XHßž›çoü¬Ó+†§€z±# wø¹Û\"ÝÏD[”RÐû':Û*’(É|rìè Ñ y‚ÈmZžù/o% {mƒºƒH®Zçîš+“ÖÉ=¬Æ­øFšzÙÍ©óõW{?¿àp âb(w(¨yC[Eüà±IÃ6 Scdßî€4\É Ó2•?}¥í©êŒ-Úna™úõ“0EÈ}eñÍ7Äõws‚Ð(—ZXl/߸]^îÇבԭæ[ÕzÓZŠ¡²Œ1`ûtgb[Üõ{;©¾ú®üñ='ºàβ*̯K e’27T:ö˜'1XTS9SF—âqK7rgðørx˜çKE|þGÙñ•áNÛ‘q>9!‘–9Å—ßO”ÁO–*¦€´7–ÒöÄ®´9¤Ú'1ê€û¥ï¿³ðÆM‰ŽÙéÑ1FAÑײp*7——n«VÁ{¬¼‘…oÝþJvö.NuºGcÒJR³·A¶{Â5›‡w5ã…èÁ}ÕŒ›·»ò?¼šÝ߀SÜ=ÂýK¢ T|öA9$ Á[¤w®|l‹ÜoCó°okÊﱞº¼&+fx¯Ù*htM«q`AX œV¬ 8W£IéHeKœH­ÑHuén‘exü‰ ¡½ãg¦ªÛ6Þüe°jEiƒuš¡c&'w×–óÙ+½N 7<&R•SÁ©-‡`N?’8 µï`©ÛKfWdÝ”îß¼{_U(þá'u¢ËÿòoÍw®õ'*õIïÍgijR"l䃲K.^¶º¯í FŒ*=Tëœm~äØÑAa±Åpý<¯Kúù¾—*Ãõ¨ÏÇÐnY£9ß"â!ë*¢ †=Šå‡ŠFFF¢Ü]»ÕµX€¬9²/Ý~ŒÅ-DÆ#†™Ì|B¶ŠÞ~õio­çüäzov¾¾mBn²/Dç7[wbB覧ãW¾ ääíën[ÔSåºÜ£¡’`Ò.½wËtRoûö¢è W#äj¤k!gEœógŸKÇwNõƒÍÝ—^{·øáƒP¢%ZûÞ¦©ö‘¢×â_ïÂ¥µAlk{!MxpCÙ% þ›gDðy]+—s$J 5–ƒd¤@îñ€¢¡Xœ»Yä9ž|ª”ñÁÁÓÕÚÔúo8[@zhCG< ëh9¾«¼Ö±7Î÷û‚¨0>hUIp(õÐCýr]ï=TÙ•Y…ê½¹þ{óº.õoAåYô¯¿ ߺ˜Ô‡ê/Ï®ÎVwÖònn ªmÈ´Ä5—|hÅÀà8)ÅT¤ä«v?7~樰ÚvŒ\»è7kûŒü ȵ¦ˆvØåì$ÐyWr¥«N0V0롻ṇöAOÄ—çŽMp—¡ièÕP¾§Ý—P,ÑRÁÊ ]@ì`ªf>÷|ýË'É·®å#aðÇ/ºÝ¾~{…~ÿÝb¢R L¿ÑZd>hºøÝìÊu½kïÈÕÕd£—8Ž·e=Ás]NmTãÒɯ|¾ðTyª^Q&iynã²ÂòÃG½™m|öõïõ£²—­W,]× ‰P†Y´ÔGi³ÆGÎ8jƒ6·ª¾g-k±e¡êÀ$<±Cõ‰ —æ-é&m’5÷ÔX3/dæ’â•+ÃÆ v:c>Þ–Ðâãç®õ|Jræ¹Õ.|Ø1ß|_>§À%3œíN+šõ0ä}c×Dªh¼•yWæõ…«ƒWï&ÎÒV!p4‰&¨ãBÕÔÅ>®Þ£³-°q‡ÖåÃÛã"þÙÛìn§YÖöA›RU\ã•€•>ujS•S•ôyûnÆLÑ«‘‰#\'Å(1ï-áU;ƒv’¨«”ßrUOY+,e4d®£¨…LT•PÔ·¹Â¢e¹¤v4„ª†¥s÷Vñäã0³]¶zÁÛçÜT ×–¼ÞÞIxñÌøg?MLˆsg»Üu=”gSÈuèqÃz•!ó豱׿™¬¾­±R¶µâzT¸œìš® öÿÉ7ŠeÍŸÜaÿñǃ·oòÁ¿þJ<3m—UOrpËFÂuz/ ¶N• õ”¬v˜³Þ,:¦TþÝ›PרeÈ€ßQÆX®~Àð&Ñ .r5cR_!lù°{=Uúú ºÐ6v9¯Ñ¡K~÷¼p^5Ï §C +š+ÔÉxÉ~åéðsGéwnAÈ?ûb£Ý7o-á?Ð F?6ÙÂ"9}Â}z\ü›ÊÕkéöƒÃWVû½Äq½¶êv%WºZ`©É”ýÏ=ÿluºYÓrÐI’B—›èh:8z884•s¦þìo‹…%Û0˜;zCÁ†â‚æ2¦9"•ޱh¹µŽ&”¡j ÌA¶¹bN8"Í&¸›ï›TOl£T[6XžW¶[ ¨,ï¨cIš7¯^.ÔiÓµÀ]N'®/ y\‹=Ž-G\éá7_'?=¯Ã§gORcЦWe.y´!Ê—Ä»×{ç>œ›£Y`‰KU{Úƒ†Çs‘Sæé³ðê,ÌõЖq$\>ÔCxóþ_oʹ®[qÚLèklÌJï³gÒ‚+ë%ü›…gĆ;NôlbG¼»œ^[…ícq‰Ðk ‹h %àã ëHe…ÌJí$ÔÝÐYbíXàG —×ü[³½ÇŸ"SÛÙVo¾¯#놱ÛÛ1Ïžšúì'¢éivþýwù¢¨§ÖíÈ"µ*¢.8ZC=rtøÕ¿MWÞƒ“G4JÚËܧÒçdfºÄÐý'ß+ºùØ”ú“O‹swñƦü׿62½£¿4}U‡XåKVp÷¢*z¸/· ¯MÙê0v„•´ä+3wÃmhÛg†vGZƒÆzæ„&ì£h‡ýÈ@: ®àh€eº¦÷^®.2y–xðm“~бe^) ®‹¾Î<ÌŽ…ÿøãS{§—é½»îܺ->Â}þh2Èå|×¼‚vYìcezúÜ Þõ©‰¤mõnm2o;kwˆ<åÝ*@KAŒ‚‘‘¬åvÝ”˜úÑɉæ²nù´;öoe?þQdŠL!Ìø};p©ã8ZmB´@˜ }4îC;ðÅÙ‹ï§3¥‰¿”ÖZ¢¢ƒ‘í–Qxê0ƒDW^4!ïÙ`x§Þs‚ŸV¹¹Ä_¾œq›œŒê®J]nW³~×:×n¥ï]t~>¼þ.ûহ»T„à–(a€æË¥øBGP1Ô$$•c]ÇÚuÁá:,!•«ѯ„)vV Í`hî·Äíûö­óô'7Ì›ïàÙ»bCùðXethCõ¹Tvæ˜ÿöô?häd ìЀ”ÖPœ[j<0VS‚”žÙn^<–üáàñlGœ[ê.*mÙs!ÂF¥9âbª› æOà¢.ÕwÙ' 1f|vžÿøJæû@4æ¨Äåf¹èuP_»%ß¿"~9çýä-çýkÎÂRQeœr©…&¨îÖkïwÓó|©÷ÇjO{ˆ¢|%BÆ4Vn¤2¯Ä9¦+¹‰èýÍbn)|óýð¥käÍw»ç”ÊÙo‹ÝG?¾n¶„5Ç·—§GHT½¢‘ÐÎXýàéH XyµôgOjÄdƹl ɇöÏìŸuhðÜSû%«¤+;wÝû…ÎÜÔè‚ÐwYƒ0bÏ>ÏÌúÃwÒ*ŽÎoöý_hé­ÍR²^[ür¶†•þ‹Gÿà*Jã÷VGœçµ÷Téû*+›½ö¦õ R.Qd^ÕÌÉÒ*Îjòrýž¢W°s#[jSì‘€0l*g AiƒÙCÚ²»d¿æÌó=Þ'‚H“[mÐÜm;÷$}/2×”ºƒE^‰˜Bßd…ˆL+šùÊÆ£[­Þdlo2×ÏÖÛâê ß6Bw”ÅÑSl57Ö²sÖ!8ptð>1Ú¿w‡ù­œÀÐô(Ûݹq#¬õIn‘{Z‚["\Š\íÚ±=ݤ÷~1KdƒÏ­±eÞ¸Ç1Ëß)Oíã’Ð7¯óï]˦‡võa¼¸è¤–Ó¢ÌîçɪÛaÐÍ0m›Q°Äj!áPõ¼ {• 8Žio·¦Ã+$¤@cØ¿[˜‹±º&å,Wýgºé^*C]re Õ‘êµîÐP0Ý4¾«×{Ý«+•Éf±oD8XæýÊüü Baƒûš?ù¼"ÆÌÍ÷œ©*yÛõÍóºaŸH7òº ‹"!¶ÙuéÕ~ºÌeŽ{®x⸴qôƒïT¶V6Ñ$’9¹g»²#€h¬&)hJDOï= ¿ù¬³gR&äÁ™°5èÞïū䆃±k™˜‰McoA•|˜9ÜÝÖSRU¶Hì“ÿð†·Ü3;9²"ŽÇ'|MJäQ×Ŭ[ÊTP×Õ’¤V¾·É寠àåæ ë» øÂ*ã‚E‡¯™ƒ¾ó: Wù39ú•NËA:H­Ò}ö˜cÀrc 䨫 KÖD¨PžºŸŸ©ÒS@÷ìPå~“gy›úo,xß}¯µW ,’¢püÓ3ý?úhùé¶Ñˆã°Ø;fÎ ê%vû²ÑÜd íË ‘%C.±•• ãtñ½[öÑ'J¿ÿ™äȸýõžº[÷“–ƒmR»t#QNT(7e(µŽ›@›ü±§FK]¹I@u{#öðñìþànÒ¿³GŽ•vðÙSµß~š›¾|wQ½|_?3cOnãÊ1o^ ¾{¹­$+zÄ`XIû<ÆD‘¿P$÷@^õM+§I×iš‚¡q,¤.Vw›!û Æ.°å÷xé¢\×îm¤¿@}.€+ª¼è¦™1R 'Qa¥!XGF®ø•§ÈÁéʇsÙ—ŸÄR¾w)M‘Þ©ˆ©¼vy„ÏlãïωïœWÕÄö­cj¥¡A¢)Þ]^Q©ÕYÁáó='“ÚU,gÌUVÔ€„€Ñ@$“‹XG\dYõ!¸>_øe"»’P“‚“ªz¦@¸Ê:–˜À 3 ÔSðñçê_9>H•‘ú°$\‰tšUrjJ^˜3[«|´«‹…ÕÁÁ‘™Òx+“E&4 •b唿ýnþîuU° ÂÕ4¡ É%£n{Ê2"¤ABEC5 P”8H(  ,*é@MÒ²±J´£5×`І)¦ˆ­ÛGbÁpJêœPÌža™±ÖCm”Â-Q¦D-³R±•£¥{vM–K¤S(c½zU/Ü™úÓ×V[ Ûa0`°£ZüÉ'¡Z•k-„`úÚ,9ºÓd~sn65$DOXc«r”Ü]!2:p(pÕ×]Cëu¬?ÿ3wºHKº¼¹(³Î&¥z0 †±Äœ¤¨ñ”ïêèïØ=UÚB¼}•mvëÝNGî72Ýp³ƒC•¯_¶óëäKzÛÆñëoFßøeñÄ=õ}÷ŽøÒ#'&½…%‰FëÊ‘(¥Û„"ì@™²‹¦|#*κ©Ü;<¾){w˜?OíejïØð2·mpAÛà}è髊mÒb ­Öµ C…y™ûœ¨4tÍNWî®^œ|é‘Ñ!Ýýî¹ ‡â¡iUôú=-Ýâ£{ªççÅ7ßÈ'%€c¡¨U*ë½];²cdÃÒ æÔ_ØšvKç.Ò–›fŠb˜g´‘CŠÖ¹± ÐZL›”{XßZ©}ðF/ë÷9e9q»º2ÐJø ˆ°À| ’øÈ>ùLí+'­ UŠâ × ÷«öÑ1}}Ñlô±A‘cPÑ^+öÃ;z…¤ìH µr$¼‘u¾s=Ë¡TvÄ$T{—PÝöТŒF 7„¢o¤æŒ+ `‰%à0´"¥àgH C´(XJ´+5Ã8µž5)2 £Ár€ˆœH-_3I,zÄXc4qÑ3NP.Ózº™U>0RD;“ÔH¡½J]Ïß‹ÿó+i+×CÈ5º=_NWÿÇgt¹\,&&¶6Ò1!æÉ‘*EyN+‹Ö·†X`44N¡(`Þ ÊA(|ª¹P¦—óê°7–Üz[n﫲†2]“þÖ Ð2£Æ Cirf) óé Çïhb{ao¤±ïIgµ›¿Ãë†ÖÖ4jw…ªúƒCò×/¹s‹öó'ØÎmÑ×ßþ¦|¤lŸ>¼vO|ñiÿä]êx=a]‚!Ô t…Œ$$·™¾l+Ìœ'Î-T›ŠßBq;lÞ‘)ëz²­ÚË(eÁN-ÍÀR®Í‘à2‘;âŧÍ?–ìÜ¡õ»šéíðùç¶Ï.ˆ7nËÍEþôý“b}¹:½Çù󟤤¯mˆCÊ-É¥¹Áê\¿â^¸ß…˧ʣN0æl^ÙĵÌo`a!5[ÖPÓ¤úÌq¼Õæ‰ag­\kóï~{°‘P6œ®«<ƒÀˆb¸ƒÙ6ÏVJE5&›æKOYj*œþÂ}Úne2Ë6tTŸ¢Ö?{;eá)®•.îåpsÅåN4¡€öü¬üÖýòuL©0Ù° ìµóÌžŽ QÇ]Š„#eÁE Ht¬AÄr£]´%놚ù–p´ R´h‘X°NÕ: ™!Ô"Xd9ZÖs@P LCF`‰Â<ƒ Ëú ="ú†ßh³…nr0^Ø÷û9ýÉ5üææNKírüÞ·j!ñðS§JûwWÒU ç «zµøåÌ•<§¡jz}Iµ³(”Å´…ŠgR£Áú`\" MѰ fNe³'n^ÏâÈ9µsäÚ=ºÕ(<ì^ºÑ»Õ‘j T=!"‹3n=ÕrÏ„úø!Ùí×¢òœ¼úFvùíêÝ{ùêV¿1ͺ“¥úÙlÂáà'o—3³õ»O³ÿó‡ô¥«ƒýãäïýÚðµõÁü]óé'ÒGö™ÏK{Qx}1õˆ´†Xžib”«}‡ JL½xEôZe»Zè>óV4,‘<«ðe) c îS†^æ}u©t é …ÿì¹s&sÜôí 81­?ÿbtwÎ}óniž:ˆ?º M{ÇÈØà¯g$3}ŒŽ:n¬—æäú\xõÃʹù δ7IÃ)Ò»¾.7úþ°-I›XÍF­É18²jœ‡7Ú*ÕÕ“:7zî·ÿ¶»Þ'4ú”¬Ë,c‚@a¾Ýµ% ¹¢@ý©ºþì3ÈI… ’øÉê¼›n8™«UÖ· kÏ­jO:§£P¼›èë[v  ÑdµðÜ\¾­¾û¾úÉ5;4pešãÐTÏs] º @†© Õ–jBe`1FV6,1Ä 5  µ.5®…ÐϰPŽÑŽEK4PmQ¡å`ƒªÔhÁÓŽc€[äÌxD{ f4d æ9Y3Ð׆›<çʹ·Õ÷‰‹€RšÚàçÌ÷.šktÚSA´®œÍ¿ø`cûŒ§Úni\Ü[0Ë~y(õTÐQñÌ„½rŸ¬§,V¸ƒóŠk©ˆõÑ"C?CCc¸ñFOܼ‘úe~ffäò=\o˜cgè•éÕ–öI© ؓҷ¸Ã©¥ZîšÐŸ<,{ƒæbIÜ“í×ÞÎ?|›ÎÝ“+›ýÚiŒØsÑ–óæÖ—ß­ Ýùêcô?ÿLþàC>3Œü ûðzòùÇð©½ÞGut€W Ƥ¶`œÜ^pZµ~áJ Djª=oIçí,æi Ï@‹²ˆ²¼ ŒÙÐq6«N²kn]®ŽðA./œmÿÚTXÆ¢FËÚsó0vbãkKÿÝýŸÍñš?\¦óÉæøë ZH[%õßþ8ãÒúë‹‘vYKìAÿ"\ÏÖ_EØ5ëý¨¡µÒƒºeJ´ŠgÝžQ¶™nkŽW?»QxâÜÅ⥕›n(1ëÛÍé8”éV˜:¢a/ƒÅji+Ñâ¶Vã”t€†îÕ÷Hñ¶PPìùbeçŽIÜ1ýzvCe p?'=¯|w“.½k~ö ÁËQAi/3JZf!M,ää(ÀgÌQ@g®²Š€å`,* €Q؇œ2Nõ™å6à¤`› %ëdR9Ö™tÀs•4K¶Ð€µ@ ¡à`–ËëJI H¨5¨3k2Z€ƒ %j•ðß¾bÎÞ š?DÌZÝ^@ò›^ù(('ït€ÐGg<Ö땆ÅÜíøÊß$œÈÖCðàiÀ´S.ë™̯[ÊÝ%g,÷.RÙ· œ\0 ¶LR…Ô§òð»?’­§ý}pÜRgkËs‚ èN«h2(ÖöE«Fó‰ÿ/¾?˜_Þ´U„ô)„•(#)ÝOœ ÿæßû„lÁ_üÀldK;'‚ûSòîîƒßyÑNøkó÷#÷lÞë¹W®ªÉR-t½Í5yp{uŬ (zUÏÏue€¶êpŒâð¾"\ž$´MÊ,Æc¬®1o³îg‡vñWÊþdxþœø•¼ѺãiÜ›KšÃ×^„ÿ2ùÅÝR¢ó©a:¿|ïÿú›r‰— 9p]òw>¿qYübÉêpÐ˨êAÿC¸™$?»kÒ›Ïl¬À,Œ`ÈøZ¨.O|Jú›éd}¢ôÙLxí>€Ÿ½\j¸¤yŠ­€ô\R€pš¨öìsaÓ‹»‰ê3©áHÑAΙùo(a‹é_mŸèËÁý33ÿòÛMó²Öljߣ¥ù5²ÚV/½¦ÃJ¤i˜ ¤”†€ñ‰á2#ÀXˆ§-£.3@€Z $:£¬…=”3q0g!H£)É‘˜²h©“`F®mÚ1(K p€#¯+YXJÀX‚J ‡ª…•4Þû·ðÂ]6T Ähƒ"CO í¹Æ´+˜£oÞÜZœ×‘…Õ’¤}OÙ¨§< Û+Q§Èo «$0K­õ¥%=41*vôËﺭMÿ«ñW[‹i.X;ËØ˜ñöLª’SýÓöε‰’råyÂB¿_tP‰Èƒ=;aº–~åkÅß|c<﯀Lúν%=[²6ö'Ï¥5w·ýeËÇ…žáÃÿë/ŠÙÍþÿò þýÛý­¾ù»ŸÂ;øW¯ë÷æãѸã¶ņã—$vŒÀ¦ʼdÊÝ®'!G‚{§é} ÂuãðÿîéÑöíî?}©ô¿ÿ–B9pýáV{Côi7þ“˜ÿñëåsK}¢+>öâX@¢J¬üÕßH§G×÷kxûqJ<ÞlŒŠ`+è‹ÙM˜»¼ußî¯Ì†ÜŸù7˜¡´Â,3£ð5H‡Â‚aã†Å¡çM¸v¾ý¢/Ê]§Ó Fw^»ú‹~¹ûwõ™qóš,“HY •Ê C™1ÌÍ¢µ—£i"T&ÁØŠU3¶Sh¨Iâ:åÍAP«…±Æ$9çB¥O¤ET†º$sGPR€ ã 'ñ¸¢ žFM‚L§>@`˜!®á‰FЛF¶)ÜC˜Cè;@™ñ<〧I‰€sµÎR5áÐZ¦,0ˆ K64+Öë»ãû–.Ì™~öœÎ ²©ŒÕåþzΕ,³]¨–æó†9Lƒ¡L»P±¬ÚgªK’=Æ*ŠÛ·åÿžÀÛ§«•ÍCÛ²#“" cÖ/OŒ'{¶‰_\XÊ>æ5ïd½uH€ôºÃdd6¾Ó)EÓ¯|¯¨í_~êéþ_~/n꤬UÛ¡Ã`ÿè·—ª€¿Ÿ¬¬öKõšçù½Î5ýøå“Û³¿>ËÛÅu2CÅÝ6Ü]Üxd¦Zdƒ–lýÉW¡Úïå´þÿú«A’AàƒÃÓ?øZЀV2ÿŸÿÔv‰ãûþùù¾íÀ¤¯æŠ­œ5©÷ÔÑìÕyûæÕÎ_~+úµÏA\ÚZÛ¬Ìç½Éš yÿŸþVÿ_ÿ Üj÷'Q8ñgžêÓ~ö·“Ûž ¦¦g‹;úlMlJ[´ˆ§(ˆŒ÷Ôê3Ç v‡6jÎaÞŽ…¸·Žwï”Þž+gÓµ{èHí;ì&Ϋ 9È”ŬK@R°[…3ÏÙv€†ãïææš‘kB&åïÆµæ[ß~ NÌ´5q &·Ú ã0&9:’Ö 5âÁm©A‰À(Cm´m(qÁ”Q–I°¦‚ví†ÀÖ9uxH$a¨]¥tZÌ]3.”ª…Ö )%E8åC̆AI]Ï“ÄúÆSqzÒÐ F¹7¶wþý[ÐiÁþ3ƒFƒl(#Ú4m>³ÖHèXvµÓs9 Ä(ƒÊµN8 ¤Ï²½yXƒlöÎàÿø¦8¸§Y‹ýã»–öŒyì“n<9‘îÛ>øåÅûù€¹Í;i¯š!KÃNŒmוêèϾߩΨ}Œüé·ìèšìmì à÷?¿ZkJ¢‡ú ¨Šá øËïoÝZgñ§ö&/¿Ï× §·IŽyöv×[ºÑ{d<Þ"‰¤ÿè·¡šôDÐø­¯oŸ>T¾x£/ürˆ祅–Ý7>õ`ö‹«Îÿ}ÞûŸ?¡T_Ú(ÆBdD|ñ Ü[æ/_×C“S• [Mí€-Ü”àH ž:6üÖ{­Üø}\¡»ò7‘î½ØÑ(-ཾQÀ"ªR(·¬Œà{}õù1@Q¯o[ð  $­Ô‰íÄq”¥}ïÃvÇ€³­ÔÙˆ\Ò Õ%ã° ˜b´@Ò¤€.,hwÏÂæJíõvò«ÏéE’Dgÿ*wÖóË‘%_ª.tdîgm¹©9€ñ˜ZÓñÃ>&°«éοºHo5–.…££ŸùÿñO¨okãªõÄÃ#árb¢2t1„‚ˆz5øé¹à‡W³±¦úìñ¾ö! K´¹NDìÿÇsDe䙇ôëgÙ‡›>hô£¼£œÛ¹xüÁ¥Å/ÞOeT¨i ïîÿ­ÿzÒ4Mïü¾ë¶}}ú̪,ï}uUwUûéžîé1f3Xb±X‰’ŠØIÔR« A1‚± +p¹†‹åÂ.ãM»ißÕÝå}¥©¬ôöµ½Ý¥ˆ *BÿÃçäú|¯5zî ûÆ‹ÁÿCï_ßÿoÓLÜ©1ÙŽ‚?xF,oÈ7gÊ‘«­V$VÛëZš¢kXµb_zjJýbÙã­ ÓçÏ©CcwþÃzì|¹²·ÖXt"UÀ¢À=@ºl]Eй-²wµu믳–NM]L/|þéÞ§3äOZDéd –K 늂ÔFu-@2p!xr#·›*;ÀáÜŒ)>ËØì–ÚJ+Ã1¤™=vÆöøHlk¨ÔY½ÊÔ•ž¿´¸Æø†Í–HXb¨G­ÌV¡à´u™ìOr+Ó”U¬ ‰%` (=å¶Q-XT€ °#œ;4–óÐ(Ó¢‡Þ¨TH­\™-7ßw"³À¯ˆ¡s°û$‡ƒ~&ì6³ׯ¤ˆÛÎn¹œ;:eì`°‹ñS”—†&DÎR}“¤«¤ Tè(*¤%¡Zùέr,ÀÝe^ 0)¼T£3¢Oí{Ýòw ¨A\/Ÿû=¦ áªØµ–»¾µR”p üº ŸT²ëiχj!8¸¨¡¤DcµéýýE±„zR’ ”›KÍÕ¾úoØçŽÂZ"oþyÉÖò›%¿U}²­S/ß)·íߘal‰LöÖšKoõñAuã‹¢úŠûßýÑÏ7¤–{-yæèøDua'ƒ)®5çýÜœÞýò*ÿÛ›jï˜ûõ‹e††*­Tô|þß},2¤_ÿ’÷Ó[îó 긬ˆö&|ÖQ»öRö{ÏE?ÈǪ줾·¿{K?³ÏÿÍ øp^™/w7HÐÈ~r†¸~æ oú0V—o=0³ý 7ó<:Põ ÉÏ~XyïÓðÊ|"´Rr`’ÿ£×ÔÕ+e£ÍFy²Ò)<¿wv7Óž ¦ ŒeUŸ”]S!òC¨µ#GT'?ù±i÷l˽'çRxJÁ8€)(Ž*&Êãy®§À/9I É5öiöüÏ9•ç0Ye`³~FjqÔèÿî=]ôEx]¥zȱc=œ`1EP(§°‹gǸþ&—K˜¶Î0ÓÃÂZGP \ð‡‚}âÔ‚ÅÀÁŠŠ%Ô‚t@ðè%]÷ŠHêÁvÁ0R¼KYu:Û·O{T n×®²fá<ô|ÆsÂ9wí*Ø À@„uŒR «`§Œ=éàY))-(5à€»¼ Z€Ô u}6ëӔޮöËË»êõZÖîêˆxÃuHr"ªì_}œ<˜sð}fVi£¢àÖ:WjÑ£¾ Ž8”†²¾cTèZÞÝI:Ŧ9z°¶Ø—½Ò € ú;hîA?É¡o¨ô|î T”#P¥F«ñ«/ÕÖ?íî‰ÓÐó×.å«ÝÆÂN§éàæ“lûQ3¹¯¦„Wä_̇ù9/Åäÿ5ïä¸M-÷v¾ÑÎ߸ g7ÿþSvqœÿo^³÷ž°ûKæØ91¦to=¶¿s9<@÷àuU)Ç)ÇsG;¶T «è¦Œ9‰ä²¾,”2 ˜´ƒ*¨€‡¹c EŸØeKÛ ¶ ˜,à™±êȰé'škÚ¬8­¡âsçëÿþWý‡ 4JÀ.[œuN#úXJœK ±`= §”:ðt˜yA[y­Àu“A¶^=Ì—ÍÁǽó+wZñüÃAšCßÒÐ @k, ƒšÐùP¿úÜtûúâ&u¿R|éBº5o'Uë®’Õ{¾]ŽÆ‡ÉEóÅ¢0Yrã¡WŠô?}žÝ'ÒTüòzÚîäß¾ o­Ê?ÿLŸÚÿè9÷x‰\_TÇFøù1÷£ëúæüîÅ?ÓêSâ½ýqù{—¢Åu°2¯ M¨bõåSäÊcòÓ·à·¿€ò}ÏÄÎî|nÊ~ã™ÚÏ>N¡€²mãßßÙ“õð@OÂDdÿáW⊳/½»ÑÛéAý¬×<ñ þ^ØS”ÒhKçÚ: v€¤ñ–ì³ çšövòc{ÆH÷¿úkH6ÃIf¸2«)×7àTI+ ÆZÐäðˆÿê3îðˆ J>Ó om5þùâM‡1) ’‰7ï¯2nþðÑ ŒÆkÀg{ÿÍ/t¾á7™ËÍ çªL0tî’@³B¦©@1)ØI®öjWW$„Fm°IeM'$Ú6˶DæDÇâŽAÀ™ 9'¶L­å‚–Hjžˆ¢t¥'WC#$€¤±ä5µEæóÂÙLX§Ó* Ì!¤„@!'´Ð…qH"¹R‘*Í+7‘¹×a(…þ–,gܵrÝ1€‚Cî» ´ëÁ’å€: µˆÎÊðÿõû[ÿ‡Wk÷ÔSÖU– û²°ö¿‡½y'|H™Î=°9¡ÞçgGÊ} ›ûôá¼õ)y°npÀÀ¨ܦ ê‹lkx{¼ðq'û/ÿ”üãßÎgžÚÿÉsbÔ‰f67 º“«(ÌZ¼YÑeäÕIýÔž™kÛÙ˜¹üLìñÎ÷^Ðý®?¿š‡¶vvÆævª]Ë ˆ*~íÒÄs;[Y ¨õËAþ7?ÛÀ¯^d¦´áÈ#ÉJÖ0ƾu• GíHøãëøÇ/‘v?Èi7n¶”ÞùÒaù‹9ó‹ìˆ‡¾¢ß’¼“ôžç¿ñlëGdeÆ=Ð9½·IÊÕö@ AI7´ÃÕÁ÷¾Òl6Üô!yu®ÌvHýÌhóØJóWqÐÆ·ÝVŠˆÚ3vÑDI:’]Ý”ÝS#§`ã¿úQÖÖ“óNõª¹xíŒDÀ5Xy`ÄûÒzdTW¬˜í„·7›?ýüÉuŠ!ϱA&~yUSý'—ã(Î äQƒq¯Î$ÿü}½µÜ IÒƒAàH`Ùñ ¤¬#ä$óùqVî/ËÅkPÛ¢ÝØAä-?`´­9ÚŽ“èNÛ.B2‹@,º²p =–Y QqŠYzv=‚ÀgƲuBj­†`-É ™_’2_H 4Ñe0ÐÉÁ „€@Z+UY¤e¥c& ö2Ô/±|3”ÎñxE;cÒƒ l$%œ­cžØõéÿò§‹ÿäåÊ騉µ¼nxéÔ¿úÈ{óvîó]Ê<™÷ U>XüúÅ}çFvö´T&ùƒ-øÅ§ffM[Q ´×f4P÷Š&¥„mÖ¨šô¿fÿàéÚD«Ã…j0z¢.ŽŸðÃ^z¿×DÍ|Ò7B0« pšZËxU3çÒ·õï=¯äÓµÃl%{ënÐå™0~•–†ùÆîšØüůɃ£P Å`ÉÇD¶˜½óQô“;vÐL‘1áåÚ¾»|ß¿+çB1U³ÿø{NcN­aŒ~q?Xêa»[휮¼ôrÁ-¤öÊ]7<œ³€ÿòŠ=|¸öõ…/£mm½·gœßÙÊá+Oå#ž`{Ýê£Ú£µ¢ë&žtú5éž?êÊHèέ]¿×ÝLœeÍ&<¿¿ñý{ÉŽñÃfQö°yc¹}ÿzhmšì÷¢Sͳ‡³-ÆððNâ³Ìº)Á\KëZkt€6¸8VœyÍ·ÇȱýÏ~–‡UE²-ø6”Fr @|WZ“PùÚ‘Þÿú«Á¥]"(‹ J¦ÇÍ #t÷”ýü®ÊíÐUG0Ý–nfQ~<[ý Íâ øã“~æºm!A°F”À­´LXÔÚ'Oiöj¥|¶š*º¡äÌ5š¬ÔùB|á^~¾X\û[(õ”BñîЂÌ.Sñècž'aÒö#ظµ®<¾«ØsFMœ—‡ŽãعrzWø:j}ÅÁR)zþ RÎh¹†¶pŽ=M+cŒ–ÎðÈOµ‡£/ý^º{”vG¢{yÞÂ*&MyªÓA¯T~O¸•CjDŸ€ÒF(MJ?Ën¯©þ@lm‡ï<`ÿÃÇúú#„о”+`lD¦óŸ¾áþðé`"Ú¢A9$Éјœ;[“òÖz 6ð°oƒÊLF$5DÏâÏ%¿÷bÁžª¸Ä:‹½·ïzÛ4󰲜ëi§Ý«_in¸Zì·÷Ó|„f‹ÅûW*ws0è WäÚ Kä6š‹ÏW”‹[qjWƒü3ì‰A…ñÜè«7+k‰H z4Ÿì_rcºItåVÒª%$Ôo^åGö¹oœ°ì;/ÙDÛ/r]6ï,'I>ôÛ/9f‚ýEÛ÷Í» í-€|¸â^}~ìÆõþ­Ÿ§Ýò•għ÷U®èpЬÞ|dj,ëäÀ9ÙRª®~Ü…;›zûNñä^öÅgêácogÐÜLS™!ê´D–÷‰"PkÏ–ƒ/_PLÃýƒÄïˆõWÑ­pe"¤‘Yj¡àÞÕýý¯/ãô _”1ß±¥2ùÞ=C””7žhWç¤_ÉiÆU71÷WÔ'sùÕ\êTƒA£|$1pB„!ˆÙMì _µæ™ •wD#* CÏ—ÜHýʯ‹£œrQ=Z»žzèXlþ½+ïº"àrp¥s°îíÐ2 “'‚ÇKnïñJsŸ˜˜Ylëíw;\~Â:E¥pñ–5wœë[–'+àKhæÀ\ð”Ý<ù¨JŠ…}»ùʧiµ  ¦@`”Õµ<›C™Š¡à¶(ZÖQ0 Lqb\™;²ÒgמØfs«*ÏL$Ýy%'½§‹Ü©ßz¼þÜÈV²¶í;!‹ƒõ~R¯…{÷çç=SW…uÄÙ€ˆŒâ€hné.ðliÞ›Å×ÛÑJþwïB¿”£ˆYݳÉÁª,lžû̹Öçï§W>Ä™»ý…{ùëv½ƒ¬WXe§/¸Í¥°ÊòMÍ«»‡æg¶7r¯AËöÛÇ_ˆ{µJ¤Þ»W{™^íæÄùðlòœÏ×5­D­¿ûœ¥%´»áÂ6}õ©îáqt`sš^}XÍsfÃï¦æ·Ÿ­I Æò4¬Ú7ïKy×5Q3¯]~t^ÿåPÒÉ_»$¯Ïؤ€&Sb¬ùŢɊ­ŒLŸ$Ù š®šéº[ºsÏÌßܽwˆµß3€¢n5±IÐ穵~• g¯_ÐÂÄÿÍl¸­‡­¿v™ç æ¨s@YdG'Úÿà[‡þ¦î©T÷Rí[=6{!Üz¢K«Îµ*QNK,{©¹¿R~4›¾lŸtÉ@¡"Æ̳Œ#3–DC̨0'|ÝÚ‹!‘Y 1'TKç<ô¤ÔfÏ~S4Mn”#ÃÁʵ¬bmè™?#æž± åÔ’‚Ab F–ÛXAÙY”ü>8aX7$”4 ~!0' j; A€q4@á(W´Ó ’å»¶h?yXή(•Ú˜Ù‹…?ÆÉm[䨿÷ùúåá­d}3B'x§Ð•8Ø3Í®©í$t™Ò!q@0ÎC>f9G÷ÎCþÆé¤?ÿÖ;x®´iËî`BHË,©yYF?ÿ8¹yݺÚ]yX~¼ˆ›=R”åîs$m7=ÓëÑj¸7^¸ßßʽ€©ÿÓ·ª3•7?j òÞðñálµO–vúÔyÿàåôùÀl—¾Ê?^îéמRÇ-û#iÉû·¼Åí…Z8þ¥Sk±¢7Ø7q$y° ë[gyÕ‡³SÞí¿ÁÉž[#û7åÕù¼£íú¬•YîÄW.ØßúÆýÛz;cÛ¡×(4²ðpUC‘¨­µÞätã·³ºw¤wøÈ°¬Çí8- `ÎzáˆüÁ÷ËÍmô_ÜDä’ò’¢Eô€jž«þðåxïH9db¨µ|C¬=ôuÁIZ5R·?°©…iF¦6@ OÜ¢&‘å>z(…•œKDné9žz-çl£ð:UE÷™DZL cK…ª¦q|”@Pï"ÌØš©–EñÈÒXH ŒP&Œ,=ƒÙ]žL+}ÒÝ€Ñói•’¾¥™cuNf‹3nw§XtúMÌïA±LMB¥ï¸FÕáÄaä{­²VQU“çÃá(Ð_»[l<ªú’«•›AƒH·“2Ky,ìn‹#” ‰–d :$øœz‘R#‚LKyÂÉ}HúÌÌWóÝ +LgÆ¢ª-}64Ø­ý‘îíD«ÁЇ·3`™@P #‚gY¨¤FÃÊ’’Ã;7˜$¢8¸Kî:8þì9rö@rñÅ¡õ¶œ¿ÛÙ¸5ë¬Úú˶ZÖ×t8†ÿÝÅ~Þ¿³DZàf7âù"1¶üÞ‹ÞÞ°zý'vo{a%¯ìŸÜ²=ã;Û<³_ÿÚ×”*¦h³“&Éü^‘,®’Nýæ¥N­^: º÷Ùýé¥Îr;+‚ þêÙ~e$ÛÎFÇ3áúš¨ð.ì‘·~´³¯g—w‚Ý{+ÑHrm¡èXž-¦LQ|å)û½o6ܵÛ_—¼‡qh$xb¡È“Lw7‹ññÚ÷~Cžì>Ró+“#~§šPLÐ(?üA¶ºYV[\eÈbd @-™ãß}.<9ZvÓ‚EÕ{õ{•¨e}ßè$Ý3A¯ÜQ}¥˜ÊÊaôÁ£fÑÐ øÆ—èq¿pˆ®@B§ž¦ô!ÇŒ$[.¼´ªÜ>•ÁÑij¦™f·ÞÝ3ÊÙ0žÎÛ–®'*{d½. A Õ „ã%aó¬˜ué=–OsÆ©¼%§ÎbÆR‰ã!8dq´“¯Yý Hïb¹6aÜwRƒiu(¬Ã!{,ÔéР^î:'G¢0#ùÝÛju¦šÙÔRhû#â@ÖÍÊ"c)&­¡¼NhV8—8D ˆa@¸ÎZOÂ&OYÿÚ®·¥­zö¿èêDõ5¤±üÑXoCŽiä;€feäƒ[}"³¤ ®Ç‘ó2‡ª xÊK1½uÓ'yw”¸£»ã‰ƒÕ §kOê=ÿÒðƶ[¸?hçð8/¨ð´‰Ö N„ŽÀoJû¿ýAõµUÇòΙ”Ö©ß~…†î½•à¢:*¯Ü³m¬‘'÷’¯™$ƒQo¨—&éGj3x²–}ëé¢Ö’¼³ì¦v{‡ùÜNHT6<<×j~ô}×YZÛÎ\:£ï8Phª´TÖ:PŠþ¯?%æ‡Þ»»!(ŽOªgÎC¬·Ÿ£~ɘéIå„Ù)LE]Æ„­Îï8=|ô@ðè&)wŽöÖ¯÷ýq~á«Cã•Ù"ÚÕšß»º‹¾ÑíC‡`÷ðö•*çý‘¸/+ÏB:‹©ãì…“í…{¬ë¹,ôÉ;0¢»Ù¦’ä{—ýù'áûz-Ïï;<¡Ÿ}šÔ¡wôŒ»÷K8«íA‘—Ây©"re~ƒdµÓÇšŸ|îZIçò±ÿ«»Ûó÷ÚõñÃ6˜= Ö/±œ7 Þô%…Iæ¯Ú¬×”bÿ®.Uuáuî_){Ÿtà ïoÄÕoúJ% <<®?HŸt³ æ<Ìã$ë1MŒ/L”¹u è€ÄÄíaâ²ó&¢+À¬pc/“Soš¹Oʵ7%ñ­+‚~k»Æ§úX^g°¶Y`'|¤²ˆN„ƒÌ‚Ÿ•5Aª ”­„ÌÖ6•î’Fž<D;ƒTl*è’¡jàÑÂõ±I`8 ¶™B¼.’O©Q sqã'½… ÿÀ -!¢¬±ØÙjq5@Ñ:Sœýºê¯Ãâ#rçsvr wÙgÄ â°óÔ$J3l€ÛðaôPêŽ‚Žˆ¥Ì®ä¾!pü`0ÒÐ;ÛV¶¢[?ÿîã€ÄU/!+»‡Úu?ìÔ’rÈ’6C±¡H‡ã†bô>Îon›{?è¾t6þÎ.¯Žn'åë$ÒÛx¥eë÷ µö Yp£ ; E``¤¯>íþžÊ0Þ·ß^¹ëIš´yØh5¦›Õå89r¦zpüå‡í‚œt¯<ïýöoçËëap×ÖÓ';U úKÇüaîßýƒ»àj’×’›%R³?â‡÷³ÙvååÂ~Én·½åmÓð‹2%K¤¸p~6B|M­­¥^Ÿ.ï{ð­×1íﺵ·ÿ X[f<Øè=Ê#c›ç¾ ŽU&lªgÖÞ¿]Ü\ÅÑcÉÄÄðßï”[£ãœ-y‡fÆBŒ¼ 908þqnÚÜ>uú¥ :T¾Ù~ó8áÑ…¢˜>/+L8WÜ\®?ÚÈ"MSšÚ-îî0kRM`)¥8ñí1ê_ÿœƒI§){‘ymß?òFÚ ¡Óþ@⃙JóT6õ”½ô’Û7egóŸ–“e³UÊv–ªÕ,O¹£Ì‚Zp‡Pñe£¦´1¦N““§OaÁ GÐyrSÁ“OúR™qÖDãqÎ2Š!*ÎSÎe._ £Çª;bZ‡´¸»šˆfþÂA3~\Ã$XO?4wµ»d#6EsH¯\­¥ë³’ƒj ®36ÎÑ6µƒX†@  s[€øC®j0_qÛªC­øÄ¡,cÂV»ïuw[âh%©fÇûyé:YùÉ|=Ó¶ÂÔ ·]$¦ FpîÀZˆªˆ,ÛyõâXjÚÿ0Ý;Ÿ-/9V©nöê×çÚO¨JÊ€cÈ©-µÃnà U×/‡W?(;¹<|„]yTŽ e†¤ßeÞÐh0Y[ðÚ'ÎØ ¿ø içâÀ$¾ò}ôz¨S®®d7¬n¤‹ÝŠsäÕSaßÝþw9û Wó™=u®õËëè¼þKGk»¦{£ðHJvì¤7å7gXÙ‹‡”®ŠY¢o>`ÿê—ý«¾Wã<|¤ì|‰«Dm¿kâEÓÉ=?™¡§Öm\QdÒ¯åÙ AIÐTn‹an{E0|9û³Ÿ”3ÝVë¾C 1°‚8wÙù1@(×KX"ªgO V»¥Ù€õòqæN¿DF†)ée®*þæcÒ±C#sñ!Ø%ÐÚ¡À¿O§X Ð$â«Ϲ¨‰„€–hR@Õ…²ŒETì+¥ldpè¤>8©wMÛRC¬muhdù±í&)Ioy rô™Ñ” Š˜–ã` :]·å·c»Oâþ‹„¡­}´:¬ EMÞEãX *NñÆ4™êا œ) k©t²éDî…À0ˆ‰5†…§h¶G©´O½Xk`: phŒÞ§]c¤¨ôAÐtáµw‚:x=’ƒC‰@G\°ÇÊagV9/@XH,À&â2€Þ=?Sal ýÂ9Ö©Tèõ9ÁFñðe᤼ØV»~öE[:J`—ýP‡ËÄZt±£¥C› Cé¶:}˜ß&GŽ¥Ûˆ!°‰½a}{~s0€né(knJ, ÆS5—CÇŸ§þŒõoÈÇ"§÷VÞ+'yÔ§Å»sòWŸè4OÈ>¶¯6:ÿšQeí_f»ýàñãçNƒ:á;^}∗ýîóõ¹ëÑîC¹hݱ“Ÿ_ïcŽ|¸1wó[ 9é{âØéêHà®ß“·—&¼®g¹wåjùïÞIom„Ð-Æ=Öàw_@R’­7Ëð‰ëUŸÌ ÉÊ ZRÇAz6Ï« &L&Þ6&Ø+ÃÑçËÿ#ýø!p×îëlÍ/Š ž'Þy©+ôh­Ý³'wÕvŒöe•=Y-WMtê%´L¤JåÁ_]áMײ~Eõ"hç" AdŽS"âUg0r”a‰ÌäÖBbÈûÆ ^29‘î;V˜ÄÝ»í@A tµV2k†¶Óú÷¸p¥ñ‰s$pŽ#quʼn ¹ÃšÅo…z7ÓO yÈV„㼃$âJ½žUZø¾‹ì‚ñ>\pù¬6}k¥eMÄ 7ÜDà´ øËö”*¢^l4]À`×´†]me,‹sƒböOîÇ-ÊRª¢Dp”´ÐŸ¶rÄ™uÆK(±€ø÷_f6– áHg‚̈XçÅ¥§œg,Û éµf[å©—b††²¼‡¾ÿá¦ìÂ!îï5Ьy`Ð @YU^"|·Õàãsè¨Ùþ0•°f>Æn.,·ûР" JZXWòsë&N¼Àøƒ"ºl,d¤åNôÞ¹oG)&Ü~0¿÷I:P!{§8¡É'·]žy¿ûb1íÇOnK/SÃ'äòêr(ù­üÙë½ÑmÊö8ß3•ÃÇ·?¿×ìɳðé3™kÆÝ0) ÚÂèå;¢ÀØyü’ÙKˆß)ÌaçgH>„ì>7U'ªH( ˆtž`Ž“‡×èg7ÕñSÔ7r¥gb²»·5pÍ|s€f¨È¥¿lÝàOœr€–¡TÄqb‰„ÆWÄ\ø&ŒN뽓üázåÓbënãÁ]óøqFœ¼ÈƇ]eÌ.]žâçÜ””hÚ9K¨×ЛFBì‰u`;jÆzË+åp¿“pá©°|óo¡·D݈ç~­ºÓöbbǺ„ zÝÀ4“¦p·$X-#ôR-LÎLˆUŒÊ¤¯Nnî©d&·£57|Ù›>õ8-Š¿¸­ç¡JåE‡)±©¤rlê E,yü*-âÀ¿¿šÖht~ÿðÍNNCt õÉõ„™fHýÕ%)(€åÎV"öÜ«þÆý%ÑÆn‡ò¹Kx/ó:k½VYO°Ac¶×¿û¿û™»¾.æ‘$7ž¢CÒÇÛžÛû\|à`²¼•^™{‡à{/ géü=;@œ:;Q\Ÿ¯îtóËûͳçÁ ±í8ÜbiÑþtF¯bëÁ¼øËwók`!Ë™W ŠÎ^W¸´q„ÿÁ«Áìý°¾˜ìâ8W½_öeÝ ¦À«“ £'`Ôº´£ÉÓ—&Á æúð̳ã7–Ì»7‹±Àw–]-CªMpˆ°ã$¤XH1Jè õ@ø®Ø:s 0àÙ¾ÓñäE>gF`À`¦?ôÃO3§l®M†¬íå@06¾~É ‹ìÓ€ß.ÍAd‰#_`öˆAEˆ‡ÄCڅü]òþçxõ†Þk&ZêiáíN·S¿Qv¢6õ]ZúǵbKh¤ŠY‰Fyæ´ô¹oñ©]j×´?{ß|ð™Ú¾Ûœ¹oçgS´pö"kèæˆ[ºIÅÀ]® ¨(hDG(˜×߃èî´>9ê&÷¦Y;°bÔlª¬BøÕ÷u U3¼v+ò6·B*,šª£]à3³†nÉ4¸ã®0lúà ÐcŽ¡sP}Ê{ )÷süpã`%s…mTÜÈóñä7\ËJcAÀ›·Íƒù¢&‚óÎÄ8 x—ÒÄh@0PU:`¾ö0žÙ²‘³—Ž _]ÇxÒ™zóʦUþHXäE 9ÈlÉÑÆ¾ðš÷÷žµ[¾|éE®ÇvÖÓ¦jX—h¶¿sëž{û‹ìÚ[J&¸Ñ_y Fý :ÕèVÔø…êÑ“õNñÉ ªßyÑY×–ìÛ¿3Üh¥Bë­9»jŸžÕíþ{©œ+‹O¤ÿþJñÖ-`¡Ë$é!¥´"ÐhSî'X´žü'ß̆¤¢^¸Ù÷Byê¹æsû³ÁjùhÍÕ=JJUHrIì`‡š¼ŒvÅÉ—_åcO¹ûYú˷ˆ .Ëuç2æ;º‚ƒðŒèEWÌL06jX;ÄÍ,ÙìÐ#£ÑPÒÔ6Ï3•”ð„£­ÔþÛ¿Þé·Ù°59ðŒ(páDe)Õ!b¿•çM`¤?ÃÓ[T} p²IÆàz` ¦º]‹nkþš«õtSL6t£Zf¡”$Ü¥ݸêó¦;x¾:²–´hxÏ©&¤Ç½Fª/îK…œ:›{2e:Ë“íÝ=ÛÚë%t#µÑhjÀ3ÚSfýN óòaUâϑܡ­6)Ef^åf÷Ó^a×{Ññ×H½¡kÌY›€ Uì<;Ÿ ÛU~ûa *9™ŒnCgh©œáÞ¯<5O¬†z&µ“¹Hñ„•Ëž2Ì„€~NS Áp®Ò…ÁÓOÕ@aM¢4æ_[ýË•*ÌnžRTs~‡æ×l™ðPX ÎÀ5O[h¥}ô‡Nžÿu}ø@ýÊÕ­k ­MÛ—{‘_˜l˜¸á°jòâõÃö×Ï‹Œâµ U>|ŽL·Ç'è•™å0ÇÍ"áPXàÝ23:/Þ¿ÿüN{.lÅjƒ“hzƒÆí%s~—=1•¸PGû''üÖH&u±½S™ÝH/Œï)7“O-.ÅÕ{ƒûAòáý¨c4²l»W¢ç5„)2S”˜¡#QüO¾•„Šóp«/±òÐÅÊórÓU3+<–¨‹‚UHhqƒnÝlhB®ÿÆkñøeý°èýè¤BHZ”ÛV&4FÖ&œBYJõª-‘˜1Êš–nqÜ.]oKœ®ç5TYD[QxDQÿ_þ ·¶CG,õzRAy–çP–¢Üö7rÿ¬ñ•”´¸!Ô{Ä­ 4IPȉI„>àv¯«­ûw0xR˶x³YNÆ:©Ä¾îHf„t*Ž>¾Âý:9v"nnõÇ({àtKk•¢Ð~•T.S–q>q¦ @ãzKÃ7ú{·J¿—Ñ6£µ±Ä•P–fù~ìgùIV!˜µ¥¨ƒWî¨~㢻ÜP‰[T¾JF+eà¢yƒ«7çÃõ+‘^Á{@˜ÞSéÐ*t2çØ#æ½ãéfQRZéÕŽÞ¡’ ¸Z•Æ  MHœ_Ð AÔ S_^é?ÿT)jë@» #<±¶l.Oüow6»„>«ýÍ#¦oSÝ6ÆCQ©9€(j…²UB8sËAãèàùoægÚol|¼P牦¢eË*>1ÏO«oœ%W–³p¬qì­öžÚ­?š v²Á8ºA+IlŒ ñVV¨²¯…ýè!ùñäa;Ùq…Ce«lwäóÑ¥ƒ3»5„&<<Ä®.¤×nÑŸ~‚³]m¾»Ðç!Ü]P‹›Fth¢0uÔk™r¹jä`¦£Ø+KÉG¢Ð®ïwÚ,ÏsÜÅG÷ïjÔò®íc}dnЬàòݺHÁQ‰¬LMùâÉrnuè?þUꤜ± Œ5([“˜ 4²8GÜ$nш­J•IáÁVߘí·39Bcß鋨Ý{DÿõÏʇk34\@kÜQéçÊT¾ÆÈË´ĕ¥kUí ³lˆ£¢GÈG¤¸N C¥Ü¼–¢¶Ãg¡èоanò¨‡Z%ÌÆ4àÚøuSÛgNœÑ§û7¶ÑÛ.ž>FÝwmæÓ¶ÜgKêjiÔ«í+C ¿Ýí”+.*â\¤ì`"¦âŠ2›X¿¹¨Ö)–@Í@…÷UÏì¢ÉŽòo|CLîMF™ÝcÊ+A¿KÐZTàÑ'²ßëpöYÖÚLžÐ`è?ÒtÎÙ  )ç^a1:mPcݹxBºšå´û95U\›¼KÝ)øìc5òÉÝP' j½v‡ýówŠí”É"¦fFÄWËt™AîÂjœ±ÆéjèJá†55Bggfp|d|"Þú‹w*6Å’¡@o$9P‰ÈTQ à /V‘¶…h¹±‘~³ÝÏûæy¿'µ.FæcWó‚„çdÅ„¥£†ç¬ÄdõÈ£»úWsöêbÆA­·í/¯Ón‹Oö®YÎnìþ‹?ïÄ¢'f­µ¡ µQÎó°ð˜CKw… Ö¨Y´l§EhR¢¶¹2ÓmÔâÝ5? |ƒóáß¾•ß^'e†¶D_8ÊBë´÷5î¿*KŒuÚ`µb³Ø€ÚÒ›®øŒ…&ø[×3ìéú ‘9šPÊ«'=Rdâ!Øj•Œî…#g‹ã'ƒm§V‹™ˆË”ɰÊÓ„®RúƒæþÑvÝäœ'Û}÷ĦIÐWaNw¼é°OÃÛ÷¶¹j6q°ÂÌ¢+Ü4º×| iBT÷ ÷k_•#ûûCGÊ}cyXB¼&TT"ópÏH!€IDATáëîô†ÿ4¯öUBI±ìF¾ÏÒ{èvˆè#VKwÉ”À!j·NO38>ë”ÚšG¥6…KÝ)Ù½ÇE3 {öò"A´"ä“»äÿù‹övá· Ö9å³·ÄÃ_äÇ€ú¾æg´T/ ÷"J%û«‚‘V‘[ÆXQ$<-Ç%\t´J¥¦Rªáótm³%€êè â>ƒÑ=âEœØU©¯ÈSÇ´qv Fgåã 9ÔH* €Ô=ÆàÊŸùTñyÖû¹À”ÄÚñrS”Gú\L|ËÊ&$9:ùQÊy†÷¶[ðW,­XHx‹b¬¦hÏa¹» •: O¶ÉܶeѲ„0I2*À/çÞhRäÛÈZФŒ¬@ c©OÀ¾¯eöùø­-àHmîBFÂXºëd<¹ú.ü ×ëªä òÜAP)ä4Ž9&ÍRI|šÌ¦À•ÄQΑ2Fë€}´u€X XrÎ5Póÿ‰èX*y‰ŒflS” SúN7›Ç\ûÞˆ iýÒmŠž (@r¢E i¤yñô—9¬’õ{nËZl/ljUôÙWZK·º³ëÄ¥l0•N7 ¬Œs$uo¡ñ”MFÛ6¨-]ªˆÜ7¤Ž§r¹‹m­2Z͘‘`;h!€±’½ÒòÆ7² ´ aKÛUk$z“ÁC§jÎRp5¤ßù…—Eö9g^´ÕÂ]ø£ðÓï7±»IºƒúãÍì䉪°Ëq$nß—s?I÷:† ?÷>ÕHà¼g€„²Ø)AŽ4ûÆ1ưß÷JÝ`”1ÖVº‚×ë…VM_ö×¶š|W½bÔ§PÀËà¿‚‚Z eóµàÔ Mµ)‹‘Û‹ê7^ËvnP–ë~ëãÿ‘Mv;÷iùCç-™G+†gVQ ž= »„ø5EêÚYÀ¶2þ{¿?üÙ[i{M·U¶c¼q® ЄÑT›zf‡½üäDpêbmÞ¹7Tiäû-ßn{‰gÿ§¿`´ <ªwÕV®#>Bá D9é-ïkñäD©]¢1þä®÷Î|§ «ê,‡Ù äÞƒŽñ•,­C @ œ°hvr`G2þJèê¸æÕº¾«—ª™ò¸c’EªúÁÙœ` t™¨°Ø¡+GfÈN?¶uÃæÁ¿ÿ¾WÌ·óm»‚åÐîh´ ›‡Bøw4±V•NísP8 eLt©`/'fm‡P€’‚ô¢-:²Ë ò2;[ÚX0„h ;Œ 9 øÎ¶u”l=±¯¦1þ h§7~™,rÏo•éÆñ3:”½Žì=Li†ª,ë‡ Kè²R(ˆsÖÑwóÎ9t1y–¬3è…²ªÂÝÙ? Ü[ÿ¸¶5’ˆŒaŽ2o+ƒÊ*ö} …qnw‘Pû|½Œ+aòÚ‰Êå“RŠm!¼µÕà/ÞÝ~¤[ ’Z‡N¦N)¦+"ÞØé®_ÃïþQÜ€A½á?h%}{è ™šØºµlŸpÜIT›SƒzŠ"ä#&—^ªüÕ¿)5Q2™½4ÄG·ƒ-Š7]²A!s0H€ äTÖGfµåBšŒ2ËuDxˆ˜³K¦ó–ZPŠ<2ÊuÎrU·Ÿµïñ ôâ;ßäWßc :0v£ôcŒà€g ¢ŠÏŧ/V×àÁ£á 2ØÿkY·ô¸úó¿âdGÓph`¶KE8‘R €°Iû·¿Z›œ2Zw4V?¹ÏÞ¾U®‚€¾6¦jvGÌö´‡\iD À, AZgÛˆ؉‚]µk#[Fæt2j³aÁŠ’mPõ„”¹%€¶ŽS°;Ä ² 2eíðŒìfU=¬“»–Í¿Sï-íô–·ú`w{@™z“{*ë¤_R«4wj/ÁáUHl j³Ý A ß9G§![[ !`P×?ÄHšôœÙ2hÛ„œÞß:áA5ɯ½9˜o±UÞ80tê4eÅÖ¶€`C5+7€e‡8B‘I @¨E§9†Ô š CbÈIèÁqK§~ÕUÎ>…ö ƒ³Ö†hæóá”%àÁ §È·_Ô->¾Uæ~Ð5d„t¨NhD­-Ñx|R|ø·ií^¾4§xà?s¾úþµêã;›¾‡tg¬ ZBK ¾ÓäÛ‡³?ùnåàT¢ ?r¢’œÙ›Ÿš½ý é˜bÄ™&(@¸q©Cîi!­¡4åè—3—¤÷UCJ/A€Ï¦§¿=²ùD‘®ŒZÒr§ €€@8#Ž(ÔËÆNíyñëâô¥0ŠÝ¯Þ3ýÏÕ¸µÓ¢I5pÝ—c·náÕ··†r`N ´“”=E½ÓDúÌ®K×e ¾֚ñ¾Ã.åmÂÖŒ]CÓ§´ïlIYAHB˜ âãZ¨’ƒ–ttœRŸ:Gœ%põá “Æ9k,>J+«á1é³"_\Æ-ƒÇN‘³‡Æ÷î÷·Œ¿{s‡å.1Â0â(¢C PZZ“{Ôz’‘ÒÚr*:ûGÍmÜNåHh}·ºDÁ10¨@hß³ŒZa`Tã^àç¹Ûí쪵³V7#øgßi¼r²7d|êìá©òÒ‰*î¤Ö=J¥%8fdh(êº3È«¡¯œ÷ï])ÿ2m>6s+Ùžƒþ»Ÿúw—õá]Ï”ÀK+s¤ø$ŽXŠ¿ù¬ýÒiÚïÈÙ•2òÖßÏ7wQ=p\’gMpŒVkGæžö‹ÂJg ‹Ä!ÕÎ" g™5Â.b4â,B¾ŒñYÏ{ÄÂ94·sÙé:‹ÏåßyêT¾wS'a£¯µ£ØGס:ñÀ(í\NOî&~?¯ÞÍg5¼gÎW?¸^|{Ó®¶ã¬uTxNÓoJþä·üCS©*½˜ûñàôžâÔÔÈõù¤WæMmQó &H4t-HY ÏâÀRî¬Ïì3ž÷†! Ç6À•Ï”ç~k¢÷¤Ÿ·Yĉ"âS¢ƒ@#ÊdéFuùƒ=û&/½ŽçΰfŒoÝäÛÓÖírUÎÂMš¹hÏÍ/Ô§¿Ú®wUEéà.ä'=†¬FÜ@b‡…ÚºZi)û躔ïP¶jÝš3Ê2€‚$eÜa&ýÊaÊŽ¢ÐÑ–1 0 ž¼}«³®£¶l¬ÝO‡—ƒ#"Ä2[\Äm‡ûŽš‹G¦ ×3±{§ë—®c)u¹B¨¢´UOX¯B©QŠï ÿ^Ô‰+³îð=ŽÛÖA+Ü4õ÷ž¹Æ) {©VxûL¾ŒfƺáHý_¾=}éøfu}p»Ç:O±YÞÝ”IB•³ÌO±ä ëÒ©A64²÷ËgÜÕò»Ym.½·`•oìÝ]6›„ý½çŠYŽ>¯€Ë²ï¼ ^:ÕËû0³jê>Aí(ëLƒ™´pŠÃs*8•ÈšI€T0H¬#Ö8kÐ:@ü{Z\RSÆ”DLÈІnNiú‚ÿ¡(gu—‹zàÏ\´÷>¡]þéËþŸvG|“(È]€6›'^Hr6ó0¿sš¤ƒú± lk–kùÅ­Í·I†$ö€·‹Â `¨ÒŽÓÅþñÆ×[ìÚ:ȨaÞ“%¨á©äÛ_ÿíÛâVêžm¨¡]?ó“¿T2Q«È-)/bÐ_fä0dÚÂGAãÐsóO)—k¯Goþˆîé!Žr“3€HÐL(ËXƒè¢:ñŽŠí›ƒÇ¢¾àìqí/3ÀV‚å/ÔöíÕj O OÙR €·O(ë;ØB±eô†ÈIY‘0 „€C“ƒ@,€°ˆ¬Wö%‡:’ ÇÆ€ÄCªk"Àdê¯_iÏ\cÖºIÊE¿ð«|ú´£C½ãmÀ ÆgX˜+ÂUßÎy`ˆqà¨ÓZŽ›K#äõ/ÓºYÚý\ Õ§ Ͷ.’ð¦ÕÀØHª\_;À$™–a!;PÙdJt1ÿÃ/Ñ‘ÝíÞ6õ Œêå ³««Piúo¼÷:p¥OPP |¤”¶¯aXâ;o¯ÂÌT*DŽzz1+îm‘G}BÒ@kxÆ3*žÀ©sáØYþÙ]{ø•Þ{ ¬è»uX}ÀsŽO¢U@)Áq°»¨àv0–Ïõ@2’;§‘*Æ m(ÈH0Щ/€9pŽH[K¼g-iYÜÇ(@ÇÉ/ŒšƒË¥ôŠ _.oß ‡ìÙ§ý¯ìŒø¤_bŽ1h\–†1(=;SÜy ²¤~Ì/Ú†—V~~só­_!‰&{yé8ÁATSª½-ñÆ7šŒ¸µBFe䓬ã•PO%øþ?Þæ2oÚå#ªº·µ?)ý5­QC …crÀ³ ˜W)ÂB#Üó©ñ¥ ÔãèÖÇßßñ:д£ à Æ9hÁ’Z`Ù™Ù™‰Z´®äpl¾w#ôµ="{ ïÜYhZ~†r €Ëœë1ÈœH®9¶bm›eFA†@X$@,8ÀÀQBhPM 16^ÒQ§C°!ÃBdm%³#^°õi{õsâlMo+€¦ÏÆç‘Ù_5ÒÅ]Ø'ÄÃ’Yy¶«(0;0`=UZãzsn.¿-k⌙ð«_ø'yÿ„–€7­ ÆV²Òõˆ%$„—Û\n±æ¬* žÿÁsá®Ã½t‡x4lTIZäëm¨Õ~ý[þ׿»œQ 4•”¦ç`,‚Ÿü|á`Ã"’Ê ‰|Õñ›«êÑ£¬÷¿ðœ‚ñÁŒÆ ìØùpò¤¸qSz>ÿdŽ¢€Žfä’æ“ 52ní.Ðpõ¤€ÂõµHaXœZË~ʘ·e"ušKtáÛ’< ð3R~"¬q0Lƒm"®IÃB¥î˯›=÷f¶2£§OòÕ¹<Ö"uŽ0P ÎQâ-¨Á4 ǦÅýùÇÔØyù‹·°4¶Ã‰ò °Xæ,·ÌPh¾÷%q¶’ïYmr÷Ýûþí[y£U¯Æ©LôîqvoF¯¤œ;cƒäsO4G¨øÀ,Ø\”“¿j£3Zp£7OûâÔ—Âñ§*OÆUÞ~²Jg\¹äTPkÁRK*À4º” `ª&mÀ>ĸŽ!÷oÛqÑŠs¤arR[°)åO\÷‡ë`9³jI×Qj¸³È qqÄÆ\:mõ%rg,ó9pG90 `‰°þ–…5p÷¹¹%Ý}v€¬‹˜¨¢µ8F}Ž9~66u¾ÿ$­„ÆTê÷V!ý¬î,ÿÂË´ÎÀ(ˆAÎ:k9D–dBdÔŸ<1:zv³ÞÅX7ô°¿rŸ8B‡r=i¢að¶i¹C4uT@¤I¨­õ˜·*rîš³ËL)ÿ“ëi*];­}p¥ÈlsÏÑñ´»õ”9JË›>•’*Djtô°ƒ¯ÿ¨•8E*(Ôø ûà1LpðÙ-J?!7òöP @" aŒ!p¡€ BשnÐæv±£ˆ}øYåîÛâ°ÊÖ9Q¥ƒ4ð®|ۺόך9¤[À å’ˆ:R€áÎ1F5Àáà(3Ž€ÓÄ€5`  h€tÜãÕ"q`,Õ†÷À_ñPòëš,£VŒcÈ3­©±R™ËÅëÕ•”&V¯ÜÎü t»…v…BéÀ£<å‚õéÀâc(B]ìió%¡GF]wPÿñßöŽl'–2âªì$òÁ5k@˜¢ÆG÷„sŸ™QªîXדîÒ^<è¥h ‰nÿ¢À»ÞöƒxvxÕ¹–BþüZ T2SX°@!² !ÌhiJ™ç?ý9z¢í…¿ü‘n â¨s¦PP*Vhb¸Âó¯»qòªwOÊÝOï¤Îm:®‚ºÅ¼5w¨Ø±l’Å5ëŠÀm¸‰‘­8Ȫµ±iQ Ž¢MmÚIÇ¢nÄH«¾ÕϘ }KWxí#†¹f£8z‡OB „ïUÏœØXûÛâ,XYŽçã[ƒþì#1“PS:å©s Há{;ëú×ß=tÊŒœõ®Üˆï?ìF¤QÑ- cC…Ú’8ý{Ïùq d­5­;ÿƒ_¥;[¦µ¿bhEÑÖœºÝS%q¤~(¼xh]à„²a‹¯ƒ8jE  ¡am{BWõâɘ©Û×]ïWbA÷Þƒ"¡@üýb ”BÚ¸—ްˆi³£Ú†Á½Ï«~Jwc*Lt‘IØ`0GÙ[Ú½Ñ-—ÏkÜqÂ" že)WHrgŠÆR@@ãœqÎYGœÖpŽ”0É=T>"Eb)ÍÛN®€xä‰ù’ß#åvÈ¥d[çŒÓºŽjõZc¾£3´Û i‡”uÆ™[@P”2%XG‡`J[–‡ûުʧ§`­ÿø§ù¡%T» ‚›BÑ °fL NSD{Î_`¥O ÅÔC§;¹0A.àÖǼWß$ñC1˜ív Ÿœ.ˆ#Bà›W­¥!³¹F„Ñx]_7ºIÄ{þëÑ‘BŽû–Ú¡ÿÍþàKé/çŸ^Û¨tü¦îoX©‰á C¹àÖHá+_d¾n&©bZ¹ unmæ%­E "] Œ€²ð}å%ƒÎ†Œé„®_”'1þ |lϲ„Qˆ(m.aУ¬';¸Ñ¼ÿ³Þ °Q2ÿŠu!Ð䑃 pÛ!hgãÚ9û•úþñ¼>l¦XZ g¬—×Á¥æ;ÖL{nìù ¥v¥¸Œƒ=²ZÇŒ*h…‹F¿)ü›Æ}Šj›RpeZF.ȪÄ)F¸Ð ]©ÀÓÓÑÑ}úìÓ­?>a¦kõ üåöÿüúÄ>~b¬ñìîæW.t¿}ÉìtÇnòÒîß?£Zû“UÜ»"©5"Ó>áh]ìô•3Êa¼Íù}Ý]†h^’JN&¡Ö²’ÔëAøcìo;Wâù(îºì+ _Tv`ø¾À¾¨«w]9vÎ_ QŒOÝ]ï«*Æn—Þq1¿HÓä°usÍ ä6’ ‰Uœ{Ú ²zž=ŠÊadÓhˆÜÜÉÃéÊô3„r*¥W¶¼Ïî¬ « ö×y?M#À­5¢­·«ŒH!n=ñ»[o½³ÙwȬ¶T2j@7´ ¤ç”ýæ+ÑÔ´€ã*ß=¼çÒvPVÇ'ÙzG·W‹!ÝRø„Z€JÀ‹ªQ6›¦L ®WÉ(%ª¿:¾¸Ôߥµ4£SCݰ$Vo­Ü¯yoÞ¯uIoM¹âA(¶¬®Ö£°ï ýÆ—št@¢£;ÊäÞ§pÿAk$«7«Wn(OØšf‘U› 2Ê•'ÅærìÚÿWoö¥©–-(k¡´ÎA„ùñ¡ Mt®…tÙ‘áᓹ~Üj®¥áã$=ým%b@hHq‡l® hÏ§Ž”¡+R$Nc#Œþ¡N±þ¸[/±|”Å ¦‡z¹á=ÿF}ÏhÚÆòÙy8 \Æò›N ÈC«/ʰ•ÛeŽG›$Ÿ0¼ÉÐY;®ý ftöŽo¸â²M D†:(‡ŒSš; êSux?œ;?uªþ'gÍ®f哼|Ðý³ß·çö°ÓñÓ»+_½ÐûÎe»5¨=Ø ÿèRå÷ÏÁÈá`wS 1Oy„ ›÷Q¢3US—"#¤¢±ì»x{÷‘Ï3VS8M¢`ªP ƒê/©Y¦©p1‡ó’núФ/›²gɮؾ¨+·\9zN]01/wíÞó`­}¨;¾tª'øƒ'v?É;{¯.ÊDŸIí¸.Ð1jTø…#™Õ®ams?oº«zà©ÌQ5lèuïÓ»™³a Ê ÙOrCpçŒèÛvƒ`þ%ר5ù‹wÖz(À‡ ¦ß Æhù_£Cjdˆ(ÆG¾´¤•æ¸ÜHøÚrZ!á-cRV÷hƒÖAP1é€xÃÏt+9eÎf«{—:»á‹û§/×j›µªõ•5„Z°=ÿÔní”DXN’ÒùÎCQr]Ùê˜þÿÚ è2Z²z™%F¸*Y4\9{N=[©Ø”‘"uC„nCäãàço/a·Ô,ß"^-½¢ ¹¬ƒ=I½ ­ÒðC’ 8Ü\­½tØJYÖ>ùÕʨA™€v<ô®¯ù×W{šÆ¾(AkŸúžÑ9…‰Ð|·ŽÝ°é ¯²‹¤Œþf3©ÉÆ+ßêErË Âþ yåµÖ[½üÊ·¿Kžþõá«3ݳ÷âߤk³ý±w» M£B˜Žðxs‰ÁUÛž±P–ˆ °Luì¥y)Š”]eïdr£YO{ÿ÷ßm e‹s{st*ïï}ZÍv2wÖô·“¥7ÛŽè=¯ \̬– ´ë{ÏëÁ§æ‘‚“§&þñ®~g›ýçÖn“±£ÉRÛueÎ_õó¤d2ª-e=(‚%âF½Í ¬r0æ°%d9EåF¦Ú±wB¡Çg!þàÈàÕ#Õõt?åfìxüÊ× ¿Ùç¶6:¾ôÜo{ïþ0XI²×¾ísƒOCyçÇþa}{0ø¾¯ž(ê•® ”hðn.n¬E[©ç±Ö!¸|˜ÕÁ€ÍQ3¬NÜY“©lK(Oc¼/…*õnXÝË…c6¦•;˜ÒŽÛ÷ÃðüiwFÖ[,é*åûš¤‰Å˜_»…?þLxÛçeÂÙp¶¯=»Eëô(A–:ï}ZÎeô Iˆ1åA5ç,‡ýþ~_5ÑJí-Wê›ÍÐ:ªÒÂ)¤ñ»Y¯Ï¹PØ¢`(Í`c§ö_ÿéfH§tL­Þ¢ý£‰Li}4¸ð”‰V“°\—jDÐ5å…¨úÖ²n—È’u±¤‰R‹*è3DÍåpè¿çŠÌÀgsÞk{›•r#ãí3oDŽÔPrDÞôlú·Ö:Š>·` ÏÑŒÀ„¿_”…Ç ôsoÔN¶ëh~´dÓøúïi†[´¨ôÓÁÓ—£ûìó;e³¤'¿Ñ¼1Û?~7ø(VÝ`ªQù¬ŸµÊd’Õ™ëç*,˜©Àv{9#iÀŠÈkÚ¢ñ 3¹Ê"B`ìÁ©‘¥5çÛÿÅWäÞÑê£Õ‰ûF£Þø±òQV‡»Ã–›+|ñg ,9½œ=\AtI ÷_4ý‚5Syþtmß¾v§ýÓ×È¡½Ãë7‚ž Ppeµîl׉æLí‹Â;b+&9i Œ¨`ÓÃS! *÷é-ô•õ7Nø~œ|L³±£Ñ«_÷z›mé⑉…Ë¿å½ýwñã$ùõ×¢©8½dz? S^ü»Í?÷ìšÏ( R)ƒ JÀë+ÙÕðÂ͹‚=ú¥}þd}×ך|ìú†ø}i‹“íK\ÈÙM£{…o‰ª0oÅ–“P°¾ÿãå §Áðú(lªžŒ¿„,Óyƒ]»Îñ¡þè É2.e­ÇW®/0»ã¡Øêå±"eзu:Cï^Χü˲B0¯rù–°¯öÀƒrŠýçÌ&»zË¿v 6æåãUt[¤ ùCo¨KÑ@êê '8Ýp6)yOöúz9tz~Ö/ ‡í¬Ü*-¦Lfýמ/?ŸÙ­úÂÕÎPP=vÎ>{¾¡\ôñÇ®%XͦÍ´%ôÇÔ) ¢ÝT0³–FQïøÁ‘L²SÄŽÖPùR+ÿå'åÆ8–ä¾Gdáô~þCYšy/¥~á™~¶Ž¾W\:VmL뾦_È\pž÷óÝÇÔâš;xfèÌÙöÁFëþƒnÈX–kOg;Š„[Ì¿B»ïæù:ˆ@:Ë53 P:,âñ˜œ9ä½t¡÷žÕoœrŸ=ÐmíÞM¤Àën¦×ûKlÑ ·z­këI·¯Ní 6æ²± êQØðR¿EþêýÒ18ØðŠù¿±×ìÜä~Ì>îÄ>a͸÷Ÿ}·xö¬N«ŒÚ4êæTG™V ¸fÂi7ËxNë­°ŸÉxÌUvë¼Áp˜D{Ê¢%!n›foüÚоý;ŽÔº¬÷òÖôÁg‘}›‚¸Ñýä¹SAS–K<3­–âÚÒÒÎpiHÙ1r5Pî[›Qtàe;Ö¾|(¬Ð,R'hWUaå—÷¶þüW ·îœoŽªn”¶G±ëœ$HstuŒz«ßüÒËäõK-ýG¢X´GE/½^:üâÃ$·°‘de"Ò4ïji“eY$V”A<Æ–»¦ÆÁ¸šá£ž‹ŒgýS^.ˆë8»¼î=Þ ‡Òéƒå‰òØ13±_×G¢»×`yÁ[]!Ù¦­ÓâVXé‚fÆ71çc”mhWÑ »ƒb5é·;2í)Ìéfžm.(d/\Ð/Hõ†õ˜gSˆ\cŠœãyú0}éâàŸu_9«¯Ý´me¢…šþü¯õ®'ƒ…YkÇâåÕàÆR©yúPãñÃ^k›EÔnP´Äß|¤‰§÷GS@zómö/©ùlô¬XèÃÛMÕëýÓßÂW.“Êp^GÏ(±ÝCËSGTB;ÜAþX“u™'>¤­ÝZTXûæHjÇQ¤·ÆàÕ_kíß×ï¸ü¥¯j›æ¨–›JÇ_>3ä³îæŽ=´GÍEÑæÌf Ý©ÀßQbK‰g\BÁ!í:†œß c (”†ëíd˜ ê?¾·õï÷©ÅÓ¾9\”5£…‡Š‡ˆ€ò‡‘6{•—__y¶Ee{Ö/‹û«/½V]ý Q ×3“§6MuªÌü¥2 bÎ*St­çj •«jšq*m`˜g£Dm[º¼.·Ù‘ƒÞîCöø)Â~ó©"âNøá-{(n,º»9½¯±«4˜Òú…›TV:e¢èõ¹“Àò¶%-»™•"Ù1½"mgJOûÆëoëÑ#øÙ_fG2PkùbiGZƒóÃD TvÉyL‰Æ¡¡®biõ¡µ°!¢™yU”ÉXÃî ä ·Ûµù“äî‚‹°¢Á1´œ`Nô˜G^5¬©µ  J¼ÇíŒáþ!¼=—퉩 Ô÷ êQè©ÊŽŽ÷69TëéìæmÉ*õ>«÷¢\àm¡ßSɆâ§P„%”CtH•ôødó¾Â¾òloˆYz/‚@LŽE?þ,k§˜¥Ùñ³•î2äŠ6­\¬¼}}y;ö$ üÓGËÕû¢îÀ³þ'ѽeg ›Ÿ;5¼uÆžÚ®`åÿïÞÌvTK˜o_^aî!?|¸|ý¹âÔT«3ðÛm¿ÉYj TÕªP’±…º"=âäQîïU æÑ +Ïÿ>ìJÛ™·rpðt¬ŠØ€#`Œyœ‡:ût±瓌¸mÞÍ÷)!¥'bÕsÔ”€AND ×¶³ëÊp8®ÔM…ëZÀwJ÷ö-ògoËâãΞr¦Ð £uMv,vÄWKô¬ñH—<ÙV§vw?{Ǹ[zB¹¹9Z;îÿí÷q±g»Â´é  ÐB&†úõÒjØ{¾ù²¸1S‰ ˜mSçPjW.)ÙØdÉÆ ñúš>}"h«Ñetø[Úþp‘|QàCM6Kc85 'JV;9ò'ßllêîò†Ûέˆ;¶¯CÞv.'6pQw F޲/þÒìkëb¹Ø0ÞðpçßýxPvË”¸PІÚÀ‹rSÄ%óH‡ÃÚS7½ÊǪPÉhÓî²¾…»;Õó£ôÆ‚ ]d)±‚’‚˜/:bòúV;é¨ã-Ž~ðËûjo„äHJb#F!3¥”ÇNõ©A9Æx78ã}v]µT$„=¯Ì(·¿'ów]¹Qzˆ=†…çÜ0ŒcŽOýñkêËé°TävLÃÊð8ùå'j35É 8yº²õ =”Á¯µÎ†×îlì4 èºϱջR;ð‚x´ßzL¬F,ÛÎ o_+Aºé{Ñ3ìoßì¬ì¸–€ßº8¼6cè½ÊÑ݃¯¿\¨ úµvy2HL&±éYÍÁ,}Ha§L¨ÎÃÇSgh{_Òç~it¶“h|oÿèYYf593”“ŸYúÎ|oï¨l ø¢‹+¿ÊÇ«{`S3Œþº¯:h9ñ¬smÞj[ÝY¶^àù­U\«´{æ×ÌŸ½‡†',žÆÈÒ ½ m =)$•”$¤kBJ8³°UŸì^ùP‹ëåtŽ·æmåTøóï³Õ.¬ÓGÐŒ ˆV¼:0eØtV»÷çß~Iܘ«Æ˜K›oSgAù%jPK%[Ñb°„Õ±¶Vœ>a+Â(›³ß8ÃÀ.ÚÇ+C#}·äÓë<ïp,=ß³Zç+1AXíÓ‡è7Ž–ÍcröA™´=[P’:ZªjßÖÙH·²NÂ\Öú¼£Œ<<Ú)à½/t-¤+†å´²>X0Œ¡T…–kÈfx¹m5ž;·ÍÒœ ß]qß6Wè+3Á/nW~u6v€ )$Ž‚¹°»,|âQÌ ÷‹\ÇiôdƒÔŽðï? º;ªyÔ(%pO‘!XXƒO~®½IÞ¢Ö|tÝÙésÆÑKŒºÕ¦{‹ÆÄžä†K$Æ™(wÉøìˆXO»•¡Úw_^7‹õk?Ëölš¹yRÛk®­˜^Ÿ÷údhw:± î¤ÞÔ>yнy+$T»þÎ ¸°¨<ôhwÈp äªM®ƒ\–¤gAQ©…åÖ8„fÀ…6½º…ûjŒñŠ™K\ËŰ»¨èÅË„ø}ë¸ójf¸@R[‹#¿¦¿ù[ÞÁRÚlªÙEtxA…ÔÍqJxÏ OSŸ$Ý o*. ,rF^9G]l ƒ•ë¢ÒM›Z.H ¸”™ÅÀé¨ô‰®~饬•zÞ–î§KÓ”#ÈUf)5&éçaœ ­ÒÐɳH®±p—;|€üà—š ±flG;À•4¢hY 9H¤,U.µ)Ì岃Õf1ÈfÀùZײæ;Åh’U³ØˆBd ô ¹ÜËzy[¨Ôê‡\Kl½IÊÒö#û™§È€,?jãÑqûé-cŸ Ô¶RiY6œK©ìVù£:¡š¯.^N:qº•g™²Ušh«qDÝ¢‚7£P™ß2£ãèümÇ$ꀒ*/[‡)%ìQbÉ;1yøÿþLÈß\g;xó¼mÒ:®œg?^À+‚+¥Ë 4¨½{‚áròѯ³­ Ê*yÛøì#Í<ÞÊsL,2‚‡Yhz™jw¼z5ÿÜúƧºŸ¼›]™7•‚^K‰Eœ“Di ˆj£Ë–õÄ‘q{t¼:ðv”% 8Û¯¢]” fÂ3¨T$Ï2©rßm ÊfÖbk^Ãtèm£9x Œ•f1ï9 *Z_RêÓ‚ªwGßž&½\ì8 —ßµ³ï–Es»-öÒÎ{硾QÛi7cüšWÞÖ],™ËTš8Æe9ér)Ÿ¬ðÚ±òdäFÙf}JÞ½çn5åÆ=pU²å¶»ó g×8|r>ivsê¦ëM§ZÐCƒ‰ˆÝT•þæ5X£G'‹óëñömbwQ(_Ýô¯Þ5çÐÔÆ­ÍÊó¹‡àÎû÷í/?Å„ ”‰~®>wŽëRy¡• Ÿ¢fþú¯J©LvÖKO?×Y¿“ד³GYX4ó«"¡™‚•}ÜKír>Té¨í©æÈ‡ŸôŠi4¥|b’¹™Rd¢ÁöÂ[ñ£ðÞ@?ÔÎ_VÒ¡-3†åf^$—˜Ëˆw¤¢,4j¥uÉÚŒ"Ã]¥zÐ;¡4"a*K§€–PáéËL»ìÙÛ‹ÇÆ C… Ë g\«­£°ò &ˆ(Iú r½Kü<{ñe´çxá½[ÑGWÜ.(ëú¹.$жˆX!5 œ15êÞþ‰œ[T…~ÛAtcSq[ Èœ à)Yï';&Õý‹„ØëºW.‚RÙwùŠéàÐ<¥ƒ'Á,gk"ÒÖ@fÆ–† Ùµ_ˆÕ˹?\v·ã‡ó–»ASÈDäÆ”Ý’‘w›<ôòÏ|®8y =ÿ¡¸øúŠv5§{I¤±@˜Õ:Ô0Ê£ÛÑcõ‘ŠßK’nfwÛh'§BÕ¼ªey’JÄ=º(mõyDv!vÛÈyކ €ßÐ'Ihó[yþ'ö¾Ãk=xè.mE{NÀõí½7‚ – æN–öÞù•·úÇÔºb…÷tá]å’ŽÉcf“BDŒüìÑ/ F5JâVÿny÷¾ml‘õGæÀQ¿4­¶ýç‚Ý;ÉÅ›=Kˆiµó°l‡jyœP C?ù –ñ‰É`vykhXíÐJ¤W6èÕûÉÙ©’Bj«á¾t„sƒ/ûè^ø£ "m,í·¯=éÉÍ÷ÐÀ Gé÷¾ÏL–ï(ž~"‰¤~;iâ‚gÛ^>> „1ÑgŽF il||©òÁÚèÒ MžþŒÞs¼ïüíÞ‡Wx´ñ‰åu4•V‘eóC§q?­ÞúéÖ£úL ±†b6Vʆ`ŸÌÓ²0€|ÊIb KŒ˜*»6.cIÎ+lQ*d»ÊŠIFF…\Ì«ØM×2TÁœ…Y”ÁK/'fapÇ}gÐOg–Ù±/ÚÅ2ë¤.c¹p WÙ °èHjÓ]ðOî& [Ý¿x—×¹ÚȬ°V Í•1¤ %é|îYïk/áçgvŠ“cøÅ#Uƒ³+­‡Ž.`g¦HVU¤LÒƒœŠ@N-zœÕö‹hÅÈ[åÂÅnš2Œà‡ÜÌ¢~Èw2•[¸)ÜÁ<ÄÅlÛR¯\ûµð"‡Ñn¶ T¿_rakÙØ˜¸¦º¹©%4“ÒTœ>™fÇGõ¿þvùä4ó^S]¶Íʆjzn¡ÉÒ¹ÚËOÇ;N:Aµå!ùî¼»Ò|êpas­¹Õ¤ÇN 8žY+_¸Û8¶Û¾|Z|pÙψzuG¨©úîE·³‘þÝ—z*s—ך»·‰áºlúÞ÷©›]}lya£0ØoÎgå‘hòDè•ä}¿>—¶0C~°½¢Ö~RDÛ›6~îyþÊ!omQ¬µ‚‚SNÓž¸IË-±Öuu…ᾬ7 ~Ù˜`JÑÍm{dµ–y+qþÌX.ÕÃ÷&ªÜ ñ>‹ß7ða¦Lè²Þ±ï_•±ÆÖèˤ èQíĽa#Ê,{Þn[Éî—N±ñÙþ§&ÓSû¢ãûÄÁ½>sé£9ˆ¡s+H© ÎíÌfet,q ü—ß· "c+—T»GZ'ÚªVÊ_ùBáö_±ýN·Þc±çî8ݸ+[×жzw »\N.ÙRVÒÖ5ú‘*ø¸ì¹&ÉÔ /$j¾:1ƒ† rzÉ9þ_~`²nìpå.PRÒQ€T'ÃÚ±y÷ÌÞâR»ýGouHÛÆfÊf6wU‚©š)¼ü4ûæ+ô…£Ùɉìh¿zîpÍqkµ³HLØf“HVLê¤,ÖÆ)’Å­}Ò©TñšÍo”‚‹Q"µWÅñ/X6C¨ÛûEfˆµWewPTlí>êT+C—~•ù©ƒLËRì 5Å«,[mpô‰Ên“$Uu‹r£´KÊ:#Gjù÷íÒÁýÉÝ:ô¼ÓœÑt¤8·h;k‚X__}&ß}Їõ–Îã÷ï„«iùÌ^ÒÜH8óxŸÃz÷‹—ï¬žÞ /?½ÕI˜~f24V~ïB=jÄ¿÷b¤¤~´’NMê±Ñ Îßü:Øl·Ží+/nÔªÕô™qÿx¾m?­»ÿá»|>k…† Öñ¶‘Ú½?OÝGhEm>ûÿâcåÆj´²éP•ª+=I²¡º j+˜í4jçLà˜d˜#m+&Ûöö+Ñm­:ÍÈý+ Jê9‹«ý¹-Lót‡FQðnšÛB¡6ŒqŠ”m9 7ä ¸g Ýnµkî¼C»Êö>ÆùçŸ<7ŸÜ×9¶ßÜçPÏyôE>ÆF‘œæSC•RuŽn7ª;†“ÐôÿùOÔ:Ϥ¤¾MãX°!WR…¾üÌç‹Ó?1{y2Ðó#—ï8ßš–ƒ£ü”ó(ÐÆuâÉäÀ‘lr¯,$«Â4”¯ýYïÍ¿tnÞe}êtÉŽî¦1ãÚd…ve—“#lUŒŒÂ‰±VçI÷rÇvuw{í/¿Ê.(¥K8 ¾6î ¨²”ýùùèGŸVª&ƒ­ª« .jB®¿ý$þ­>òˆ­·ñªk¶ö{Ï:_:‡IʦIþ@(ðtå6ÁÁ„«À" SÈœ™>O W„ njûoˆnx$7Þˆ,BD¨:QVlžúZ¸ý€râÍǿܷ6ÐP¢æZ*¬ÙZÔæ§´pEÕõ" Ì”rüIc/Y±ÙÙJ:[ ÒYn$Kœm;U„;.ÀÝ­ÞŸ]¨”²®‘>Š8Î3@ÍW®í-‘{‘º{·°ÔU†ò€{¦J+ÕÞ­§ÙKóž¾q'/{äÈxP/˜ÀVZ­2Xºc¯¯›ýöµcV2u]°‰çdÑÎÞiD‘F0±³#©D«ŽdsÕTš´ìlƒaïòRẠ]úogð£¯Q;Yb$'¡Íû¶*âÜ—ë^¶>±=öM§]‹†Ik( ö‹X-ˆ†ÃÍ% Á->tÊø‰´½ 2T#)åºZ©‚@0Cô5èBÏyå¬÷Û/€!« W´z&ë’"£¿õTô›ÏSÈ0Ü«¼h§¢»óQð½óÝMWOkí X[¥¹’2àÅo~¡<:»›·Ÿ ä‡íÐè¬bQ4é®Vócd•Àødx|è+^˜–ógν¿H/~7~ý?ûWcèhvî Ö°£mŠêAÒóm’¦¦>HÎ ö{áÖ# ·,ŒŽ§»½ÆW¿ \^S"(¢låýZãö,XÑóâ?»Ôþ‹k5S+"@0XSÈéWžÄß:ÍZÐíBf`ý·ŸE_|Öë>¤rQA¤A«Â-d[~J%æJ€I€“¦',̰¾Ëš[€O¹ú· <Ê—~Y iÝÇq\lúj°c¿"ñêÙߨ·› ëXSÄØ–ÚZ#ö熞ðU Òȱs¨èÛ s» Ý.ï¦Yo@lµ‚vîIDÔƒ{[½ïŸ¯´#S§¢îä {_8ÕÚßç?h;—/oV¬d͈B­Œ ÔÓû³A»%‰°×gR7ðïð†‹¡$°¶U¨ø°üÀûdm}|íxŠ@R¤&­æO.x·=ÏeÑý}Ô¶cË>ˆ“5ÈŽ×ã›Ì‚š,·R·"wEP¹£à¯­½OѦ5Ò5ŽNÊíþìôKEÓßCÎþV¡UîÕ]¡0p°o¤zU572øß\QApS›®àOÐ.0È*k(³¾)èZwL™!º„á–nƒæŸ=åüöã)§K]&zM€VPîïžé~í©¢ 20 S»nY·Ÿlþä#÷O¯l´tTÉl 8B®c¡‹*ͲÌzNøí/Vv²æäTó–pñ³Ã£vdâ¤Fq¾ËÛ â‚Aráí; ‡ûíá»8?ÿ~qú?'ä«Â±šôo“µ!“Sˆs»qݯ§…øb*$•ÉÏŸ.LL(>„͘`ÕÊè!wi‹ÆÙx³“¹Æîª 2v8ß±ÞïžÚ5üä”N„¹~‹”d¶ayæ9©²!urRÿþ3¬HÈ" ’J…)/­÷Žˆ[sþZ;3ÔŽjrÌŒÍ W1IYIÛß0\Sbúh†•ZÔ}Ä®DIN±Ô@`ò;r@H8‘Q­rE*(Y§kª‚㜡ۖüHÕ”iꄵîW÷‹ßû-¶°–¸½ü8=Ü—vIðþU=V±ívÿø »”è¿÷Y·¯šüôzVqô¹#4yí!ûÎ[>Ï/DOés{‚{èr7Ü´vÛá ²ÿõOECù'v‹ú»må÷|Í2dcVï$­K¦Tuô€4ÜæÓÚAì3¤Sßnh¿~XÔ9¹º þÓ¯zUâ y+Ãg÷°ÓûÍÂVµ©ìàI„˜ùï¿—gY°gJþ«ßÔ•w–é' ´´-Ž·®kLA~ˆÓÛFõMâC%‰FvM {¾t6/Ïá´kµ$9bSiR°`˧QûˆV0¼W‡7!°eÖ"¬{`¸‘ GV´©;ÿüÕœY/í9<È[5´K¬ì%v笭Ãê3¨¤p& à HE‰…,8XO>wº¸sÛàÞ]PÖÃr0ï(kŸ„åR80Tˆ¥kP#µ3­í{«!N8x—g;„ÙNF'¼¬$üŒÓÁý’ZaÝ\5úž»=ÕT‚ àf1]è‚%´×”† 3KiÄÜš[™Ü_DÝÒØRáGª-Þ“FñÄÜv0ì€ßü†WÂüÒýNë}Î'Óg;®wé†$*×ànBn„@„xŒZ)ù‰ˆÑ$ö<‚Äíõæ½dp2?ôd+IÍNípï­wW¹ƒñ-”Ëxâh¬ÛOSæáZÔ¥šU™þ’‚u–,IÈ( kAKˆ“=½1+¯}ß’ßô+}ê½EÉ´>àƒîÕorñVb€D.eÝ6æÌãò¾\>X ¨Ý<=A?½GŽÿþ"þg¿‡ŸžìŠ~àIab\Uµ¾³àßý ý7o¨ÿGÕîß@zù¾ÍgŽTÞ½Ô»¼X^êF˜ñ!‘Q~îPð§ï‹·äD«ÃsCžëñQS¶¹žÜ\¼<¿rêrJÏ.I+‘ŬP «kæO>±èW^ç§•¦Ø9‘qž ÌcÿýÝð8$äÌ„ÇlüÙ“û¦Äÿò†‰Ûz P¬ò~™89ägmý(oܼ?Wòñ×HÔvïþEÞÄèH+C ¶ŠÚ‚‚*ð/kˆm ‰xÀ‡'…ýá9•~æ$(¿ƒr tÉjmáÄ6Fmº¥Vv.(W¦³ú„8z\Zä¶{v·wuÚÁœ ë*!‘fë—€8 âçÔ«ÞR´~ë“Ì›/Îd'Ÿ/7…ø«G7îÃýåtÉ ¤Ž‚ÀwEï´©«Ë(óžå.ߌç|hcæ6<Ñ–h'Kå2É"f13$KðB‹Œ£®±Øöˆ^N{Ž_0I/ Š÷³ïÇiL“XÊìí†Qnfg Sãð›_+U¸p¿Õz²‰dßã­_¹¡¸Jf‘¡ÒHZ„f&8>…ÊA»‡ê9î]ÿm<¤Ûä᳉Iôh¹zj;»³‹VߦxÚheÀÕ<õ´cœ3"¥i¥Rç¦æÀ7ihÚˆô0&‚"Š3È0³ÐÛÍàÎ_ØÂo9Õ!ûÞâôŽ>Âå7HëWmN0@XÄ:HЏýǯ¤{·×±Ú8»]½C7˜ûïÿ,úƒ¿‹OíêQßq0>œCG}å3øßÿ¨ðG¥ƒÃhjÔMrÚA‘<6ºõì±ò;ºŸ®.mFÀÉè(¤ˆ<±ßÿã É{ÓYÈ…‡áÙ+¢ñTFn³Ñ¾õ¨ïúrëø^ÿøX¶¼iáÌakMýK|åy~a¶¸Ü^ÚÝsMpð™õ’‚þþ8jq$zv"DÐúì‰þÉIòŸÞµ›©‚ά[)gmu)+¼ú¼©.oݺ ?ÉzO~ò¸0û}Y½G «Á((-°1 < uÀ_ÔQ¯i²Leý~ᜀŸa“¤,gò6Ò¡%°àÔ„ÃŒmÐE{ãc»|”FáôsŒ˜b-Ü<·Ï»4k,@4bà¬ÛîÙhÙ=ñw5mNØ[,UO‘“/™– ~ðãöõ{û?€"…Z) ¢’¶™kGj 8÷3Á±e1ç…ÛÜ@«yçT Šœ.AœÖZ¼JׯÑè¾ ]p|1»K*ò0M!olæ+ÍÚV‚u6(ìV"‰dDi¥ÓÌûû•0½Û?À“-±¶nV½¼céÛï´-ÈMVŽi”6Äs´ÎldzùdÑ÷D‰…Åþå7ÒmF,®V‡ Z9•Ô¹ÿÎL‚-]âZIp§Æ‘<}B°³uQÍJk%kç}rÇ¡Á±TÙÀ2L™â:£°ÜÃÀDåÙ†X¾‘;ÓÞ”ÚYö:°u§UmÚàä\™áqüÿýo\ìÍüJn¬úÛÃçoùYÞJµûñ­ì…µ"N²S‚>º±m³³ü÷>›p5ði#ï´œ§ü]λ-ýÍ3u_GSƒú'—U¼EÛ"©…âÔ™öPÔ5‹÷ÉêRÜX•ÅàÀ¸ÐÒt‚ôþœLs;·Æ·ºé?{*XiüⲨöû¯îeÿáõôƲóÕÇð«çÒムSã¿| wmXöD;ªÿëïF]Á­ŠK¬üågñíŸò™7#-£o~Ž/Åoh¥…« æ¥ Û„³•îÌ,äkÓ4X‰›^ÒbPâwŒ•V[qL7½ˆÑ –¢ÁUë§&/ <6˜T@¤J¯z ¬À~öÓ7˜„Œ¯m©Û¯ó} Û˾;ìºQKaA½7®õŒŽ]¤¥åÜâÜ‘Š]ÑíueiLÏ-eÝ÷a²-oßå ÿw¥v†rgÒëwÓÉÍ,kwt»‰c«\n[Y\Ðþ*öšs飫rùŠÌ Š‹Âx6IH{-\g+7p<­X{A>#È¢´±)d XmV·„4ñ¤0ÝXYI|A "ÅvÃô÷¹Â6nÿ€íhæë›°îˆŽÁï¼Y«7I¡kÐÆEœ,Q‚-}êdPàQ™eçêK¿nOX±¸ îfý•4Ü$ô_¾’øAð‹O­_ÙëüÙÇæârþÕõמn~ÿÝËáÏŽ=DËLvTí¿ýnÚÉR⹿õœ½ü·döõ4LÌKŸá,¯+ Y]‰Øe+7ÁɲaSÌZ|vI¬Ü#ΪëúâCÈ1#Žåž¶Æ(àd=HªÖrâ¼bX¦åX€³D-8–(‡‚ɉÝÂd¬}嘿}¨çÕ‹àÖOí>‹T`{Ø[I-ððí¹‚Ìcã,]‘ãB-ï®G²2bV–âÍO`ß–¹5²ÉÖúVøÆ»±tIMªŒEFkÑ‹·¯ey³kÛ-”fyH¡%¼/•ÞšÕ‹Wœå+$ž¢ŒSÑä) eã дdeDYXÏR-ôuP*Ä ±¿ó•‘µéN¨ÂV-^•[®"1¨Hq©%²|~6Ÿ:â4oâ¢ÔöÂ)ÿꬳ²ÌÇ8# ,åZ§†r|Lö»,‘Q÷$Ò j¶6{!\_²´/¹… eeFïDö Øi+ñ@«x5‰–«ˆ¯åy[O4c (Bá¹<ܦ„ w»q˜(ûºÃoòž¸©n[ÀFº§Oõÿ»/w«öÆ;ÞÜiE•[²™4 12óÁƒääd?wqÙî´c1úÂdúÔQrã>¾:ÕütY‹Wž/o$ÐJÓÕhÇ¥¥µÍœ¤mç“ûê——_¿'å7l4¬ÿá-ùë+Å÷o§Ë›nSÂRïì8¶Oup©:â}x9ÒžðÀýÑGù‘áò?yoΛ_Üô«^öÕÓëåËáõ×k]¡C+}S»äŽJßÜ'k§8»¿‰·;¿6¾žx‹Ë¤à"cOo là dZ…Ìé„4ÒŽ &@¡0Í…T@´Í@È@Jm(í°uj&ñQ!±þ=ˆ{‘»¦ô²5Yk°hG¸úà¨Ý6,eâH,Ú 5uÏÈáãY_àQâÎ5Ó§­¥¦Äbëʹ+뤌ÕAÎZ®P“ÂÃö¯oIÖÕyOñÔFÆ‚¶Î*^gUÝŸð¢Ÿ}ës“wfÚšA¤óÝ °e£ë†, ­ÁZ#UãÑ´deË’0¥F˜« ¥ï(D~ï««ÓP•ZõîJÞtT5‚8›¢4]|~6:âmÝ$©#ì§‚k½å•8paÞ:Äš$Œ²Ô`똰S"O¤´5A²$†÷Z‡jìÙé5raQ%O‘M\Ë=Ê|¹÷¥ñ­_p¼XwIÛÒC*Š´(£¬ÒȳŸ“¥m"…„6q¹Y(˜¨Màç®su׊Ø:ªtŒyöTøï¾E6…ßì<Ë[[Iyj`Ó¶;[ŠX™óÉýtÿxP©å¾%7VÜÅ ù™ö±)gn™^U7›Ë„ì¨×^©v m&ÉÜæÈõ•õ­Üëtøù»òó…7=•w1´„ÿñ-õë«Á{·³åF¹!ír/Þ;ÒdO²©Yiнp#ÁEä!üýw£}}õ?|-ë¬È_\ œÆWNùˆø«]óßü°»•éJn°ËŽŽÇc#…Å·;ÇYxk«;5~ñŒN«+Ki†ÁuÀr½Ž³uî*Y·ïpWr7I2á=Gh XÚlˆhÛ#Æ—0lƒ>Óñ‰Ÿÿ>ŠewchY²bVbn´f–if÷«ÝãZÄÜpÙz¨‰UGåPÙˆ,·Ä»÷Á2c$0Ì™ÅÂQ$Ì3ãŽÐt|![¼‚ý´ÓH½ŽB±Õ‰VÚº`ÑÞrªz4áE7ýÏo¿9×¶ÎD¶CB¤be Ë:ˆ!dKÆÁR‘ÌÀðû”ÞPþ-ÐwPx ‹ÛVc¹´cÃä /õܲ3{»³¦Œgxd3Ö•Ypj´Ê¸ª%±:ø´XË Wc“ä­×ayŠœŽéYÉ5`€ŒZŠt€GÏî¹*÷+gÄüúÔ“Yß0d±)ƒ÷½«éÒ&PC‹Æ¤”K¦¿"½¢É–½ÚãºÓszÝ"òz§s?ÅÙC ƒÅFc¬&˜…ð€!Zö¦ÇË¿Òé“3ƒóLí™À+¡o:“#âášê6Œ œ<&,ÄïÞ…]C¥#Ãý·—¼‹Óƒ’ÑŠºðP/m¦g÷óêœÛ-®¯=`VÚ-ò`móo?Á?ºªZÔjQAv]Cf”r¤¶ÆhŸC¨mW"•ZeR[ FÄ£Nð·3­¯$÷f£æúˆ%ý—æÝAü_´†n5Ó‘7¯vGFÄ Góù6üÕÝê ¿´×Ç„,vó¯žÖG†ùÂR_k«¡ûÌñgÄ{Óìâe'EqÏ”[œS†Ð¦Ê{ÖNªÚB ]Ãî0úÈäVƒBˆaØj FÚ³†}N£¦¯Ú:hÕ:Áq½ÙF#iqÀâ‹,“ÚPìôi“bªäT=»;lå±_‚êdÁÄî§Q},ÝJä6¼~%¿½YýÐf©¥€ZƒAg\ûhº™>q®V°x_¸"—– eŠ+AˆAЏN.“€BžÑ~“¿üåððÁõ{uã1{ÝÒÛˆÜ"pà€5ä¡!÷šö€;×”{“Ø[Æ¿Kä-«0f™ÎƇÙ_’^fouÖ$ó,JLDKN¢•eÌåJKáØb’¨ýçÄzjÃq1¶ƒýúq<±nׯÔ† £5C®5âí÷³ÅŒW¢ 8ñ ûÏ:}cy³rv±7×´±ª2s¥rÌÌMPgº€Š§d72I’ >—»F-hM-X°’jk-ƒBÂ|¥ d5PmV|Se÷tÎ4Æ’‹"ªÙ†1$ŸÚ‘¬,°¸•›á¾ã'¤¡ÙwÍ®ÁòcÃw–ýk íýx¨*?˜Nšâ¹ýaà´N ÛkkîG³”šZÜvî¯nüåÛÙß\‚¤=,I—)Z b+³)Ér‚­È: ùƤ©Ô¦*…"fXcU»åüb&½|ûû°»²T˜]Y`C>ûï¿ ÁÄ]þòbc n^8ž/ôôÿô£l}«øâžA„ÈR'ûÊsdL/<mµÖõ L>)̆_T±ÊàÌ("dì–)aÌ/ã.(í1·©Ð ¦«ZXe%hK Â6C,>_|¸Ü#\­(Ÿs”«œ t;`"hÇ&Yjw:#}y´bûGzƒÛ{¨MKEXoë¼§# †’@É”0bÔ) Ǭ¿h÷)ÿ·N2§&›’D+ÙŠï·±4˜ + `¡æR©9_lJ´9.²+.‰ô¶Å Òf,¶úŸ}¦„l:Ý2îš¿zV‹c§XZã}oLÛæVþ_}¹éêèÓyïÁÝüàÔ -W/ÝZ?}ÆÖ†*Z÷–4½ñ0;‘`b5³qì€Ç”j­djµo=í)q£„c”¦ÚZÅC +ES0‚æ†#†3 (“þâV¦Q.tÖÍ“£ûðþí (=êDï]Ÿí÷ÿçÿK/eâó{ó¯<ÑùÎÇIùß~¦Ô]´3õGú÷<žÿíµêÿþË.äéþqÿwž¿³ÚM„Ä̱ÒmetR°¼`­Pè—_ĉQ0(c9ÁQDq…‰°™õöyûË^>Z]ðYãžl¨|iÄAÇ3FÈö™±P›ž&ý;…0É7Üz=¸ˆ~pAµÔÎä MÐH“ŽfuåÖTžyj‡ÈÃEÿ×ç;qUOJ«¹[Ì“f±=ÇZ~þ+£c#ÄÑI…¹n+×!À6”h€nh¹eäȆÕx$ã,GRSëA˜œ¢Ù¬„<"Ûnåì~qñWdí×qXU}#•ó¹ƒÜtŒôç€νV&ƒö½üôNC°ù¿Œ©è\µÃԤȀ´ÖÒpسX9[<]…ÕõÞ Œúº!ÝÜA5åÉÂfñÿõN»µá8IJ¬èa_Wj‹ÚÞöôä¹$׺¿`»wç6¹˜Æ‹Ö³œŒ \6:Ç0ˆ¼v›Ä"…ƸÞ)˜«‹¿pĬ-V@¤£˜øW_®ÝÙ)™ŸÜB†s‹½l1|æq(—{yR ‚æropf5:±}øé'¢X¢Ë˼q?¨:—WDÑun]2ÿû/+Óó9×>š:h5Ô=Á î /”…í† ;’çuæï²z ÑIì—“|P:ýÔ1V2fÔ•ˆ™UÔ¶¨1!»8ŸýâB1I£vTŸ^îí þóÆ­ÿÌYûíϰ¹…Ò›·Ó§Ž>µo%Ê‚bY–‹ð^Ÿi¯©þåKêèn]ï/}ü0ò¤¾2H-SˆN™r®ó•íœqÌ&ï"”"Y7À íx¬+u¬ƒJ™ûšÝViRïsÚ‰jšÝRßdNªMD4p^ÛJޏa_Kúà¦Lç„VâV÷ÿx#»Ùè Üd¯„£Ã’<´9¢¤E¥8LAsoº=¾K°”|÷ÑŠ&©v´¡)F†E¬}è–u=Ëõ“g+ŽØzð7°0o÷íÉ®?òâ(a8̵ ÔÁF )³˜8)¶ ÁIŸ"a¬G­("ŽuÛ«÷Ÿ=ؽð–^Cùѿ͹9 >ªç¦­sãlʘÓJµFý½™Æ™Ýšû™P(¡ZAfRk¸bÚN(zœ«óÍ‚m$••VtdJÛ†t'³qQÖ’b­5Ãÿ÷/zk-ÆÖ˜&ZL Œ}C¨  1!Î< ½$®ôo»§øA§»b™rQÅàcCØVΓA†¶q=& ï×^¡J1\”Ѿýg_~u**òÍË\KÚÅÊãOèj5½BÙk6ºÃwVº‡ÇûŸz&Í ½ð€­N·*5}kA|õzôïÞ}(](0 )É ª¤ÈnN-•´@ áö ”íÌ騌š|„‘  ä¢O9eD,œK/u yž1…[Ô6Å’1Æå¯_ä½tÓ½ÅtÿHø«·×®o^?£J¶ìS­ZÝðõYôÞî6WëÆé)æzYª¬SÒùkXÂí˜3¸Ã Û…ðÊ…ná¾ÜFª³Æd8ùš©£ù ±Ç%݃={ÖûjN2ï£øº¡i×ø  ¤èw¾Ôïl4®_s¦Œl;ëë y_æ^ÊGJ…á‘“µñ{÷}i7ŸÙNNx#~ð—ÓÑb3tbqmUM7(’E ÀdAc[Âqí6ÐÛ5{œ‹# =­Ð0SÈîÀt¿VS`÷c=¦²í„MºhRÅ'¬Ù hœÊ‚’!a½ e¶g…E—dJ8_[woÏ%žÆs‘;Óîü“W«ß<`™‰tÏ,†_=¶±½LE9»u¯ò¿üP\í¶]ü<>¹Û=r ½÷ê;­£Gn.äY¬\SQZnMX4¤ÕQV©Ùµ'±œÑ0§g€NØâUÔ TðYæ•’ÞÍ e«ZÜ,.bÅøŒŽéü¡!9An–gnI’8i ½·¸…8-gi–äá…Ûö{WÜ] =ÝÚé~VâY·èñ–Ð-â9&Ée\V‘™Ý áWÜ­žC2–O 6¢•Æ¡t{¾iï›R¯žKf0zœ6Ô4*Æeö~TèÏM» R«°Å Vˆ0,ƒÑXO Z.˜£RõœðÐva½Ü»àQfåQõÔ+½-#:ËyÑñ[:æ…q ¥…Êh÷Vé»ü0˜lq§~«‡ýJqÀÏuÙ­Qeš*Zì–?œU¡(ø˜ b{]þ“{ñ¿}+imlW¸©™ S)-ùeƒ0˜ØsD?ŸrFîQyýV¼×#Îc„•ß2µC,aöh&÷0ßµ¡çD_Ѐ ¾ú¼«Œ0>BLäß~µXØÜ8ÉÙŸÛ´²¸°ák÷~¿ÑŠ£9‰´Â¸Z/ާÇ`¤ü`&YZH’]YÖ7¬´ Z 4 SŠÌõͰ2ÔwÍYiŸ—hœ™ƒÌÛiÔn‘LpاìN«û¸³ßâ=Vì·â¨†1ßrRÝr§A \Är¦­$nnÑ›sGã‡]oz#úƒW ß8¤]ÜùÛKùý•Úk× ƒªfÞ*üǺÛSàËää¤óØ)ýÁ¢—îÛW½6+A ˜‰5€£ ¦§¤m¹f§.>Gõ–‘=¶|·} ¯r1‘Mކ%)Z”¬®z5sX¡G”ÉÁD–…¡@™è–½ÒÍ©e†"ÚÎkÞÿøNïæ²ëØî„ÆGƒ¢ŸÄ.uº†4 Od‘8ù JÚu]¼pŸ/l¦& è1 ¥)Íp2`ÂÍwîV¯=Î|oèÚÐmºUE¾kï¶ýJ.r_÷°ÒÚð´Df¾Èˆ B ð-Y1¼d«&·5×ï$Í/=ï„~åÑ­Nn¬;{ògœÅ9´çÀÐmc¸×O¦&Ⱦbzè(Œn]ް ‘²‘fXKµšà¦Ìh.ÈαU§¸!;M¢/Ìô~vKüä¶¼rݸ™´ÄFQ7wµƒ5Íökzƒh-ÖäÂ4íVL­¯öÁ{Ïý)“Ôx>¢ÊþXÞìå#–øF8ÊïQn‹‹œ^Pƒk0 (Èü_ü–O6[Ñ›Pkx­”MœqÞ¹Ò<¬!ÓÊËÍ7“Ž}lúÊá¯n÷º¦ôâÞ4uÕõ&_ÛheØ€g±96ظ’eý)z'ïVÙxŸ p Æ6HcâÜ6bÙ»L3ƒZ½é˜MDè1Ë$Ѿe1";v†ƒXlké)ƒ† ÔË“.b}Á%åq)#’øH_ñ‰C¡Wß4üÉ'>èö?|®HMò§ïÀw>ÎÚQa€‰Žìßýª»òºÓ]3ëú­ÇΆ×nçYVIÆÜ9úu§ÐaT¥Ï&ŶŽ0 ª$æ4dG¬cg¾%g³?séLÏU¤Ì1jËê5‡bâ²TKˆmç™3}ŸŸæß»ÿôZváaÔSRùIêï’9²I†‚å±5@°&ØJÌ4v‹;ù±£|çX:€LmR¬;qx'ÔDëdhGðͯS›å‡4Žâ6;Oö ›O.õwT3ýÌ’Åà@.µ „‚B8´¬š°`]Gã‡]ÙýçŠ_yt£[›ÕxßžäÈIÿÑ#»ÞH|§œªMaIÿ ³s˜í®'†±m¥ÛWc$H"mGSe­±ÆGhÒQUæ¥aÕ4ªà—U§GÍåÙÞÏî¦?¹]¼ƒoܵ™@Ø´0áž(Ï(¢(ï0R±VKhÊùiØôÒ°Ìß{[R÷Z) ºôÜÈd:  DÁÕ¯í~Uè"÷¢5POeBÃ/@þÓߪyÒû%­·íF·4t¼õÉMc<â;ÿ`©»ÑÔ'¶£í¥ÂÛW⪜žêJWbQ^kе(GÁ2O™¢ºzy˜ÀS¸vR«ƒRl«ÂȘ¬@8ã¦.™]äæŠgûRh~×Ñ[Ât¬î'ŒYUžÝ6î “|¢£àâ ¸-‘w¨0†)ªÀJÏÑ©2*ÉÕKO ýZƒ&ôoj›Fø\?u£?z¾÷o¤QÓˆ0¥Õ·¿B›ï—ùíV:CüÑèìÙÊå»0«À”‰;­ßc%Áö¨Â˜ÓZÊACV¬Ì¶9±>¢ÕQœmbw±e¨Ý_êMÿ ðý¸„ÀŒ*ˆˆ·h«Í1ñ(½Dx÷îÓ‹÷Èwoä?¹ž]z؉ „ÚÇd¯ÕHå3ÚëhÕµ~n¥Á†hn”. é&G;{&ÒºÕõ!HˆiÇ%àÐ"«²‰à뿱0ó÷‘H³ÑãGÊ;¶_lœþ(KʸŒ+Qb©Œ2¬Nˆ¥Мª2Qô ô¶•ë/?-‚š°5iK¥áŠ„re¾òHš4â/Ãg§ÈÓ/àí›gŸÚ½£gÞ¥OmÑ#MéeY›bæIlR‰1çãyÔ¿)m If\W͘Ü3FH¦y@Kšg*'!d1¡Ä¨—õiª¬uŒ¸îB×-¡ñr{Û”€\_24á_úfPšÂ·âýtYwì\×=¾+øÚ™Í÷ÂÌÊÐÆ¦Ù5¥×;úÖbçèG3èÏß]ŸîæV»ÒR«fŸã({ªPy^ÑM•_ª?©Æ9ÞwíŠnr`üS£XXÅPÓΆC¯Hµ®íbÇ)k=K–9ßñ ì9ÖwgÑ ^G/·Î²¢•M‰•ñ¤-0êxËyïÊ\GÉbÍýÞíÇ÷Ãþ)üþŒ¼1Û§Pü/^L£ Ö\2ÏïQgz·¯õ*ºŠGµÒçÎ$åʶ®n T ÉY;ƒªéÕU‚Œ;Ç ½?<ø*}â)úh–0¯e2xL<ý/9b~Å}tíe@¬1šù–2¬nY­ˆ[Pqj9óUÖ™d©pm9‡Aë´A3Ë6¼ Åû´;'Lœ.’Ú"°¹LÁ¯»&üñÓü™ÇìÁ}#díš(œy¾9U@ã£ã‡{d¿(z% çÒ/Ôg£;ózÈîÝ-¬FQ_ÀŠb¦ˆ%¾+ ÒyˆA(8V•p\)âfVkŸ}2/—$Ô¤¬”ê§rî›ÆlqÞäyG¿|”ŸšòžyÉNUÂ!-žy±°w"ÏuáüǪà“-éfÈbœÄ2-b… 1ç¡>²*MÂÒH9¾ðjÆÃe\¡ㆬ*‰4Êø`z$£ ^D¼ßjm=˪Ás‘ªmóöË= ‘I ¢ŠÕý/ÿ]Œv¢ívZ¦"8‚9jQæ¯û­¦P¢œÿæ3ÏißúÄ“k Ûäù“ç*8A7Wñ‘ ÷ëOµÞ» ñõUµc*ßÌñÕûö©ÝÛ>šÁþÞÆt¬ö¤åV3f<“]6zÕó¾–VôµÒÎszxŸ_±³wѰÒ²›þ–ÂnipK-‡ªueg±ÝÁ£D–}‰ï9î‡ÛÒζº^è}V† ÀrMQe\©\—q%ï]oj”ò>oOŽãcSοý…þÕ]ßÚÞ?~Ùâ°eI<»O½t¸p÷JÏÕšK/+¯ž³}åê;7ãPq )ÆôQÛiTEÜLej“ÃÂArò‹…'Ž¢ùµºõ{‡õ™çT÷斃奞´R#ÌCãß–Úx…’ìE\¹”#+¬¤2uM]É­q0ÎÖI᪮Ý'½©›`ƒ1&‚à²6Y/GIvøyáqt`o7øÎÉðÔ³]E˜¬z‘ìƒ: ©Lä"pê‡ÅöݦèFs³£ å~c#b-Kˆb\k¤òß}³ïÄ$í´’õ˜H‰Q ×F÷B)¹u+\ÈÉÆ¸x=yÿ=z÷¶^è$´_zŒ?v&zx»Øü©ÂóÑÍåhïàÍ÷z WBor‹ ÒVä ¾éHH”ÙVÉ[e GêIJ@Þ‡`ÄÂNÇof­&‚‰GUjé  ;¶%Ý;¦2îå/?U¢Yø£»R÷»ù@>RëâíÇJkÓí sr#»¦ÿoÜ^ª R±c#Ó(O"ö«žr¥Ë>U«VúKæíóÑ\+þí§à3GÝö*zg¥÷Ñ-÷øŽÒƒË«ÍÛw`=U€0Ö¡´Øã:ù,6ûµu„Oq'S02åï=Ü1DnæiûÅT0kA‘OˆV&0RÇÚ6Ø1LWS+(„%ýå¤>h;«<¾Ó)㬠¼Zá–k™3ž2*ÑÈÆ,/Ò‹k[¢gÎø?77ãsC𯿄·÷;ò«‘ð_|à جÖ_›‹‚t »ÿ)}}>çãöZŒMPRZA©‰ÛŒì·ï$Œê!ñÜWð(NP—‹ÁÎ|Û9ö ¶s· pŸÍ¢ú€{}¥K#ÍM¹ )˜C×êL-5·B¡º”Ǹ7Fì„1 ÷K³"S`7‘Z<±Ifƒš`¬¢ÚXd€+GæÌ„Ø::åÿðÏšüf"¦Y¡<ñT†x%ÞX³·àüyú`5îP’0¿½‚ ƒ QÃ3¨×ÌLÕ±GÅ·Ÿ^8Yxñ±Òþ”tÄz,s )éЫ 톡BrëV8Ÿã‡[âòìÃ÷èÝ»fq3c¿pØ>u.^¾ÎÿXÐEtóawÏ~ÿíÒÕ5*Q´isƒ4ÑVø ¬gz§‚wõÖ=0Ú©s ï7iÃ(À.7håí&R〈ÈcÈ=Ë¡¥hŒ†t×êî6xîL`:9çÞðάt¨6³šï>›kR/Ä£`i^ÚŒRZŒü5#s©c r«©U gƒ‡l ^ÆŠûŸàýÕ­¢'/\A³­Þ·ž/.6fã÷ÖâîúSã|~^^[ܺy_¬§À±Q…>ªëø³ï±#O¢n[‰±mìÄÞž‡ó®’›—'š[ ŠLjK3\6éaÎ&€í´ö°±ãA¸ €´aìª)Š2p àçZY Ò¢5R®M™ sÙ=±¯ðã?k±ëI6Í ÷é§2÷ƒKñÆ¢œ¾‰¯_C×Ä)/%Ü®Îæ¥Òà\Üìn9Ú¤[Rw± Vî“ßz¾òü üÎSÙÔhþÄñ~ îíù-J|´QÉB’Þü$œž£w7ÚkëE!Qæ¹±ÄÆâù»ªº+¸ÿ¨Ý·ÊƈØrê÷öFÂ|hJÝÃ@‘GŒTXkå ­‹®·¯æ¾°Ÿ×)…å%D¡ÊØëfLS‡ʤíU6[Qð¢¡Hæ‹Åûòf7O½âÁ—«a1’TJkudÝ@œ>º­VïøHôœ™ój('¹•ﺽ „õ3dQbŽìãeέD¿š5í5²÷¤{ðî+l4ÚPQT¿ºaÓT|ýpéÐXsl°rçaþÑLj}Ýé€0Š;E”{ä«TmC ¸µ^ÑdL\uÑܺà#îp 7î±|F¬.èËQ˜[&AuYÞ²kZ€`rGµ®[M-ÂJ#Î`Õ>júÓo'}±Ñ\ÖסRs½ÝÂ.,¥•MdõLR•6#ƒsiFø6ý/ûß8ûþ¤¯¯°W§ØÓÇÊ«" ɾƒ\Ôk?|?û“¸ÜËæ×"lUÉnÛ”fÐÞ“A¿¢›]Ô?ŽƒŠÍM0QËöMôNÛË ±”P7,Wæoª";lÚܸݼjȼÒ-dŒµÀPAÁARÏ´#MØŒ³Tìµ/î¡ÇF‹DÒ®¶I¦”t Ç ƒE%’P.âG+r÷Π9íQV!º\éX¯ôýï¥ekÛT¥n–¥xq³4·Ñ\˜ö¯\ –²-ˆ2À¸­™€øËçŠðÅâxµåЬêå“ýÙsgF’[ó‘ËÊ®–F%QzõBñæ#rw³ÓX«˜ò0, EAb¸7š*Ý_î–ñ„G70ƒÎÏߊ±cÛÒüߟ©Ñ  ®ë ¼¯æ>7ÅOØœâµ%®¶™*!6(혦”†dÔãÄH”SüE ³Å"æQ»k¶ |àe¿RÕÖ±šæ6aŽÚSš¨e± ±+Z tñ»=G¹Ö?+D‹©¶tp“äÐh3¿œ½uÇÛÚÌ÷¬í;×ÝN;¿/puíÒ²…H|fŸ{ìPo°^œ¾—\šÉóŽ)9s0%’a½_ÛW1Û2wu‘ÖlŠ¥ÉJŒ-®ÇlØ­WɃ ·-!Ú5  S&l#–cYÑ¡Š êƒ·×:Û¬-#Í•|ÜíT ÝÒý7“ÁHjm«d(®tôv ;‰”FµBÔuNt¶•€è sÖEðža¿}¶[wKñizõé {êh¡ÙN«éø!Ú*Þþþô}ÑLaœóƒÑìRn­ª9Û7²n+°»9(q#ËûFr·¬íߪ#{ ^›GžÐB¡˜q§T¯/Þ5‰Žäj9:lËšå´j ­D«Ñp{Î|EšHß5ÙySãþ³»Ð©í!Ñ´™¡\#%Å4UH mè³ ±m»Û{ˆv )-Z«D(¬÷»²+M`P—å]¤Á⇫æÁRÞxTûøJ²œ$$‘–AdAûÅsÕ?üŠ;Qm9‘o¼Ú·±û*Þ5æ´’´¹a}Kú4v å…"^K„6o-WBãܪ¶kQ«ÓÕƒÇ*í¥­f λaéÌŒ°žn©PZAm‰#OB€=7ðþ¥—ìþ~s¼®ÏíaSÛ½åu˜é²6/Õi\Rú®Ìî7ÖöN"tœ˜UP¥§ø“̪‘>y¬ÙT(h¥ìÇ?¢4”¶Ÿ½õóÞ`·\¤ÙM¯ö¾JªvÈuE¼=Ãâß|ÓV}û«™Ðïl‘÷¯¶WšéŽ~Rí uï ½wï·9:´.¶™¥¥úƒ¨c4.éÁÔñikñ\±ðxl нË7U©)å¸M|9˜vL·ZîÄ}¹ÙƒD¸JàcGiźH š ÀéÐbp—'XCÁ ¦«ó ¼s¸þñÏ!]Lj.x$l‰æÚ}K;Ö²½’´n_ŋ㨫mÎê%]ʨ´Ÿ¨|ó%¥´zÔ„\¾R¿ÿj™Úf±àµæOÞIÿè^o¤n ý‡Ÿåß|ÊÌ<Ê—[™Nõ=‚¸Ì‡Æ|%Ìwuÿ.´¸œüø—åÉI@’b 2·Ç:)Fë¼ ï:çŠDsjÜø]  ˆ ±M3ƒ| !¹îØ Ô(³ƒèï¿èüÎcüììÓO–gǹh˜åN®|¨ KŒÉ A¬RèçÅbÚxÀÚU<]ÿÕíF7)í!ÓÕ¸+©o½Ø´ ýUÞI›µ2ª8(‹CòÓ‡ío>hÜ^iAÐ?*-º‰“wwŒZQÒÚ̪Ü÷¸g^®Çé„1ב¶)°‰0ƒ™¥=¹b9i´9ª·,š™Æ5mJ#¨-¹ÈÏQ ï³ÿøeòÏðÃæì09·‹Úæ­®óéÞ¢þ€“–µ¹%³ÀÖÀ)Q±luåÉâÁ³¢¾túX;E"P%°±f:4¶Ûïý(,”#Òß4A׆!ºŠ>½>ji)wOÐÿ¥¤6Xyëv®í`Ý3£™€IDATk+yÿJguKNò°„\ƒyï^o-B'÷z²©mxe¹ï^»E˜ëå}¹²¼7®ôsÅàlŠ ¿Çœ·Œ7“§Ã¸Wv\ "M­–·k’/6Lw^p wÞòt¦‰´Z(kë+Ø(¡1÷œ´C ®!a–Lº{‡JçŠZ:UÀ²6JßDø×Ò³ˆì“ì€uúË~/îö´ÎX50(`(=<àë鞦æ~3ûñ'%ŽÅ?z±ìê&¯»k øÞ›ÙwÞL67°(–q„ÿîçÌ?xÆ^|¤ œ«VÍŽ,Ú†ãöéBõâz²ý€×Xhÿà-¶m$)X›QÁ°ÀˆD*òzKë²2<Ӝcræ/ÑPAd"ƒ|Ó•oAÈ}ô¿x¡ð{§í©¾l÷¸óô89šÛŽ^j‚Â&€~i¤µ é AôÕÕê4Ù DåñÁ7~BÖ»Ñ%,»ŠEXSÁr91å‚‘R¡ N˜µöÌóOyNÔÜl3T#ÇkqÿØ0È^討ô§ïicáÀÞÁ¯¿>˜ÖÚÊ0Kµƒm9)¸Tõ–õaË4ÊsóôÅðn6t´ïõ÷cénJZ†€Õ`•ADÛlǰÿ¾:ÔWØœkŠ´(5pÓËw æ{úü•-3Ó4©QÚ1ÓÚ¶ Zaí–!9ǬQ*Þn=N†êƒÉC‘ƒ„"–'Ly: Ó÷>î³ùú¬œž û»•¡dóŠ1¿K…‘V$0ñ‡_Òí9׉Âbýæƒ i…"Áz‹tQ4;ÞöJ0<ÖÚ~tÏîî÷ØûŸþ:½6ßs%wµJÀñtôåjñI‘öçy`Ù n*R¬kh£fô¨!Ec&JíÌ%å·—ò†Á?e¶qGé ç–Àguaʺ7ÜÏÌl–‚-<›‹¹|“'&§™ÉtaþÉóh£S*{[ÁàÐõ™%Ì çþÆfå½KÝÆZi÷0ˆ£÷ï£e\&ÿã÷ÓOç{Ž, ™p\Ýør¥ú¤ý¹n:ùßJõÐj  YÌ•Þö=ÚlÄ•€aHfņ%?um  «lBsÃìkº¼ ØMžP-£šæÆ4v©uk°•ùKçÇp¥„”Õä†Î>âŠÈf«Ìí„7‹¦8L•Y‘åÆ-d:[Lâ«‹á¾}•• õÓKñK‡ÍSGQ£éýô½êÿ¬5Û¨(—¤A÷ž9<·'¹í=vD¿¿Ä„R¹ŠŒeªW’rLÇ”¸—æíÊ59ÞPÓV÷ï0à€›hð†ƒ¡Ãjp°\®FÔS¶ƒ@MúPç‚XåÊ)[å ÷_”þT?ù§/ŽMv[y/€NQ5i¿¯'wÕç×µV ˜ÍU8—ºDlWÃs/ lkƒ÷/x+KȨó3ŠôWdECÛPЉÓWHÿàkÛº¿·¨¹uŸ:nöŒÆyJ‚òÄÌ컉û·a!Ù{“Õ†:ÙÇ£þÝþì<¤Â 1䨕ZD•°ÐGó͆ˆ±ÙMäŧOeKóêçï³2™éá-ßCV)IùG¯f£}4M³b_ÖâÂdNâ®­Žl 3akL·4€!TÀæ“,?í£•<èÜ92‘¶UPµï}P¸ºÖ®ôe¼èK,J—Ö +ï:£Ò«+Ë»šÙVìÂUå.™ £ñcÕ-ýö³H_óï_d séÓOtFõ~/ ¸>»§¼`ã› êâ½h12Ï¿8×¹¿ùÎ]"mFrHÕÌX‘tÖZÁÑí½Ý»éëoTß¼ÞL‘µM³Ì×u¥3iíMøxÝýÖ׳¥ø~®–*i=Íý»¤öö%½ðKœ>¢kqoxÒQF¾{1]ݬèy?ÓRA@£\¿{ŮϠ]SYÖ0#h]+÷`2 Ï®&à“ÆF(]Er)ŒÒ×NÑÇwZ-ƒ‹DÛдa°èjcW¶ÞºÁ ‹}d ƒÝš­r5{…}ýûÉ[o—_¿¼Õ3Ö:<ËSGBj@‘£;%Ç7ŒöÑoÿ¦>Ug21·”)A˜;vúŠŠ™KÑì¯ò ò›ÔÝ}®ô’ ï6Â0öÓÎ¥&oÞNöœqfæÒ󯢔Õ1‹X;°ÜjÞâùˆTskiBü¥¶Û˜ïä”6u[X*±gG"¯y_zÂxI컥»7’{¿²ïJgÔ”Ë »¬2„>¾*cQð@æÈ«9Ф…Ï“b)‘ÒGí|‘mýFrýõ´oݼWæ<¨–[ÎÿeaÈ4a R¡öÎ#!‘ºðùÑKª³oÈ=R¨òZñ©g[î±ÍNé§Z¿ÿ¸¥ˆ,µÜËÉùÙ­ \\[Õ­4ÆØ±ÆÓ¿h·½w«ÂÞòá# kÆÌ¹¹Q$L@FŒU¬w»­,šÁv’£¡žË¼²RÌ3›H­ d«T‚æåûBݱ6r<+Ò,· rô^®¹Ds¹s²#yö»Øô^`nй²4SYtÙMÛ9ZG’zö`»p4ü6Yd­eq»GêCÁ›Ÿ,_~àTBòâaù_ ľ~=/‰?üz¶8ÓGn仵YjåÇžd\Ë;Š´Šº¸hbWÓý: HkÁÚ€&wW‹Gã¢Ò7ÖÞú~ñ¶Q‹ËýÞΗ>é©* Ú'‹ç‘Ä*ìX¢¸p”Aun¾þŒºž[Ró séoÐêU¥1ØOIÖñkèÆCÖéJãU„ØXi#‡DÇn¹ÿÊRòÞG=ŒlÍQ€ ëd%UÊŒòÌ•¯æ¯½âæ÷ä#CöÜnár±evP¥À¿wÉékGàŽãí9LW£ôü; Uj8ûÚiÿJÇד}§Ë·–èj—›nêݤ&8Â¥-Ö¬p±µ*;Ì}Ô*®>lQÌ—pÓ,I ÇÍòÁ:{íq㋸7;-¾anË┓vÝÊ0ýôzeE ™ Ø:,V}•ÂÔæ6ÛÉŠuúÊÑFzí稸™Ý¾é ^¬T›:0|ßÝ‘´ "{V×dåºEïë¼èÔ"µ´úÊTôÌaçáÏÉq‚dääƒüé§{—¦a£]þâÁÞ?~‰úŒ=hÈËsÎ'3m§Î7ÖL'È€P‘ø=úJÖ­K;ãÀÛ–m);çd‘Ñ:a™\jéæ·PyÝÊe“Oxl[[ÜR¨ª â¢AôšÎF¹Ò rR¹¥òi`…Ä2›F— ê  ÝùŒl«¦ ß¡:Òf ØoajœË6WIÞÌí:ˆ¢ƒ$hBÙ̪u‰ËÔjaÔJD¶Þütý⨂—ÒùYëYôúM9ê£ô›éò£u©}€ãµÚ{†\]] -KJ¦¾ÆºDÑ=¢ 8Æ(³û«Åêá¸ßÚ;÷jo½îÔçdk!ë'Pêûà¦\ý$öY¼–.€Ò87¦€¬Æ€ãöIõ[/a¤ß—ËMrá‡ÞÊP^^ï—4Mý¿6/[¼bˆZ›{,`ª‹‚Òõô½÷SÇñ¶@¹šúGŽr5·z‘nM†AÕ<û’ fíÍÌ=4Àß¹l´Ýèê½Çìr¯ÜpÚ’låŽs¤¿?žŸ/_½SˆHšíõÒÂ÷Xi3k®ÉÏ}áèÜ­GI^–Aç¢Bh0EN.±gídÿp¦[·g‘Íd‚qb 2ZƒÎ< }姦rG£E·øÑÇÑÔŠãÆÙ®Lì®k“0›½s—$Ê—2¶ùT%–ž`jgÚ3u(z=Ó˜W«Kù‡p`S3¤*6Y¹=\Ýé˜ÍhuÉAÄdÆæÁ¾M Ú*C¾ÃAú¿ç¿¹±>luãr}òl»Êa²4öÑÃwfôÉ=èµÅã»ÔáQ6¿âÎ/¸:AÇ™Ò^þedw©–Ä–/¶è=$âÖêÜbm³‚€ÓæÊdªj̵%­*'d |Bº‡ Q¨¼`(³"ÂQä¤(7`ÜÃ~õ3É)ÕjkÓvI¬s/‡²¥™J%3Ø„Í r¤ÑH!eYŒÅqD}ä´‘WqįRHQõ­¢ÙåU÷=¾zJ½6U˜idÿê¯wò?|uÛx]õÜöÒji%Š;«»Ou÷ïâs·Ú›Ù¨Q›‘Ȳ~œô[ØBŽrÍ’âÛ÷¤lùø<ŠÞîéœb9 àõ õne½ër$beæwx¦mL/#¨ÔX +ŒK>úò)eâ_ûúfå° /aÝh¨œh‹‚›x£™ ­Áh#0„QDZf£îÄB/ÄȷʳÖ"¡x:õ*jýÞ7Žl¼½†oæ›%¼OG½fÛ0„ñmQ‚ÌìbÖ¡rçS08?š¯]½]è84ÛÂÅ¿„â2nmFŸûúÁû——¥q¹›'ù@àÖ4M £}6¨÷Í8^œ³*—ã.¶Ô¥˜Ì30ÒWzñ ƒ2Ñî«¿÷^{ç’$0±íSÆr®ã·nB¢|£2cyHU,ÙaÇl·yîè**zh}.´œ²»Zº€lÉÖdE³ÂØ­üáf°PHÖ4zè›FVIÊKûxóÿsƒt}‹ÍlF@LžÑý®7Õ7úνõä‘ üÙýäÔçРZݬNÏ3J3„ÒLìg2uˆ¶3k9qZ}h”ÀÜ€²Šd@¸Ü-¢p.Cƒ2ÐãÜ”… ŽHÊQuÃSÁ@9)/‡Ê4CqL"_!#ݸðYOêI³± Odv9_GöNN+–e&K1 í œQ…-¡ÒXkxÌän@ä¤Ê²5„·U×`¥}3¹ÚFõ2ûûÏѯžD¯íÇ÷ð¯”PÆþÉçûwéVׯ£­pG8u¶·c›ž½!yÍʆ645hõõZLhæ-I4u@•vÓO/ò•wÛã* ´ªü2ÇÑí,¾!†{¼æx'È× ¬‘ˆ’€¡â{_>«s“'ܹñ ˜Ž¶©ð&èƒ~® î-ðV;Bƒ–J˜U[™Ç-„зÕíH0„‡ØH«¨×­Ùò0i룟l²Kfí&;«{Ý­–"¼4: woËcLf—2òÏ XÕ ø¥›äÆJ q{汪×qý…Vz« “G;G…÷gÛ†M  ƒ‚ªEOòŸyš¿p²11a?ø@2¶”Š8fŒA–”òôQ7M3ÏÏzkzk=H8”Çãá‘Nœë"ÁoÜ-4» gÚbßS"Gô…ÉÜ»XÓÀؾ®ÿ(5?•^‹ 5B;{ŽT·¹Õ!µm—¹;eã2Ë~MÄC±âb’Ú•Ì^y˜¨ß÷-*?º¾Û³¤Ô7¸N°½ßînúû‡aIÙ‚¼zÉÙÈš®OUª±o>—ÐÀeÒ5Ûr·eÑjÅ!F1¬Ef€!{ Ñ.¨®¶€A38ôTª(X~Êì?P|w&Þ&ª="©:Ê-æº3è`OY¥u‰U–³ƒBùjÐ;ýŠ—aß…‚‚9µ¹«‘Àb¼b”¶Ö³Æ#^ŸcŽfJ[;nìƒ2hS=ôÈ…D0ì{4Oëœ=ùdo8Ðq/ûÎÛƒ+"øâñèô‘NÔE“Lî7dÏð脺pý§÷Ò¹-å‚iq–[±—x¹Á,;÷m21ÅJ~AG~÷¾T€ý”[pbÓg\Ž‘’y`@p~;§’¸ emz¯îÒ&Úlu·5wâ;:q'§¡óîUÕH„A–Y`Œ&Ú€Q% IœþÞWàä‘ÞÔ¾p¨#ˆ±.¸iIظXI~ÿ·BŽóo'ã3Çý4¡³‹2–QÕ·;F¨W»vf¥JŽ$¾x ®-µ‘§s¼csí±-5eßžÆÓÏÖïÏ´Ú „Ž`tctМ~Œ=ù„yádzd¿zûCM¶µêu1'V+b©…СOµY"I[‹¦±f»L MÁÄö¼“ˆ2…_Ý ·º)#pè«<ÿ1MeV€E”qEƒj=%Á-aŒÇ H>¹¿\ßFúÕÀ^tçNÚ§°ƒœ7i>ã׈zÊtK¹—fSÙBSÇœÚɾÓåS\é8ýƒ00Wúâ.>4¨¨—ƒ… çóÍ´«Á8ØÁž}5BeßíÚmÊM“£Û çÈARX‹1瀤ÀºVk2_•:‘YÇzÌ;Z|ó^:®«]*%»Ú)äº;ê2‡™¶Ô©,èÆ^‡ êÚ‡…îÙ/’åò68Ú.8~—…àR{„‘-eR­=%âWµWh­M?²›dÈî’fÞ›…”8ZÇ}<}6*w£®þÎ{ÎrVÿüÑäô±v´ #VŒNíŽáIsý¶ÿ½“,w]œYëi¤HÏÕF£=P”6Þ¢äô7ÔÄnÖÇ 2 ¦ScÍ'ŠþÔ:£¹ylÃca̲ZÊPCÊÉ=ÉHsâQ›Üq^Þ—Z5£»›äѪ]‚†“;ÑÎËûõå¼i ˆ[K J­FeJ:Qü;_R§Š©½Õm£ãÉŽ‘x0\4ßþ²Sàâþ›ùÅHC·_ö±; "Óyž 7ð²mÇ ä[GcÊ)°7/v{i™eøÙ#Ý}#é­ÒÒzèT÷àTiDúLG/>>tìhþäsºjŠîƒvP6»†ØÅO‡ !ǪaµÂ@§`1 Wú‰qâ•r°¦:Y K;ñÎýÒ „lnÿúùÿ“ôŸo–žùa˜ù{â›N>•«º««Cuè ‘ド˜r8"EJ”(R¢EÙ”eIVrºdYÒÚ{-×+_Zɤ‡a0È97:çT9W|Þôäý°÷?rgJúÜ"[0&+sþ¬ä MúÿŸir†QàÜ-šß«àµŒ®K¹ãÄÀokKRÝÎüù«ùNËo;x +ЀÁW(?=b÷·Öà ëá»7éæú†ïöê#~Bˆ}` Væ“â‰RqÏ$ûÿJÞ_«`$…1†º_ÉÇGKnâ׫Ù.ôB?0ÚN›w´ Šz<@ò×\tå© ë~°[˜¯8ÿ°Íi¹6N÷nëgA)½Ór(8„4„t×[(¸ŒdŒáS¬ÒQ•§£¦Uk¾Ò\ŽšlÔ•ÐÆó±¦#<ÿU]Â)¦œ[8áÓ–ŽXA9Ý0%QÍ÷ý`‚ܲSIå*íØ\qqR¹»™<÷@ôöÍð‡WšŒ$¿ý €#Oo˜±Ë3É_´ÿø\øÙ]™u¼ Іâù¾ÃšZ—6¶ÑpÒå[ùE/;Imwp³¾±œÜž•Ô°GÔ ”#«rŠ*֯3€L¤v޶gHMŒ…Y׫MW ‹»Ý‘Ó:ä–y·èŸŸ=mbfªœÆ0!$&…ƒû¼öb¢f²};FO>''³ÁÚÒBròxux\úU+µÙjÓnyˆ€²·¯ X\ðuòH䉌¤–ð!Å·Îe½x„ ï©£öà(¹½Ä¶T2r ŒRÑ·x`þ~òÔCgB?bv²Š[Í=’íµ7>«œŸÓ-kŠ=°Ö0¤¬Ú>2Q¨ DÔänË…Â$ßÿ€™ö#4»JÞ½ÉR%9uÖÖåeî=£ýAK7¹2Vp+ AÌ IçËl!ÃëN~øI´Ú„º$+,ÜΨ𶵯s û6H!=2ªò›áÕ&zóJ¸±¶N€¢°8ö8!‡†ìÖfúÁ}1^ñïœøg?\¿·R0Æ9úoˆíƒ‘üë…x¥¯º^ÈUÍØ½¦À,œzHÿ-W\ðÓŽ =²=3_Qá¤6ð`uÜß3Ýîû‘¼Óñ!ºâò40àÃnÁ„Z©¥U€ä)ì#-JÏÕ7Û«•î\¸²í¦`”΋a h=È=άQºŒÈ>Zx$7œQœv5íÖÍžïŽzËf_»p‹õ§KàZÉà½Fãùc•wïˆ?¿ ÎŽôûIî;] Hà ^Yè¾þEÿ¾(}rÛ¦Äýìð„˜k`3ç`ÃzÌn7ºìÈÑr9HÂv¿²Ç¿“—>\ìßľtÃBU ¨ÍA ­eËËÊ›¡¦kEÜGRQïQ{GJ[}¯º-GTÛáN¤Oã:}ógŸ©®@À3Yd‘µƒÔ ¼â°­ïÛk6gÚòžÞ=1øð×ú“CÞ@µ²¶”=\žÜ© LaiSÇÅâ%AŽ/ßr¨îqõÀQ)Mr!Éo~} çÒ{ÿƒ%äÁp ŸyJ—Û]ÆÕáBïŒ.ž îÜëg ŽìxöIѼћû©éÙÏoÁ辡ssôÚF³„\×9ŹÖÖ9e-†Ü‘°€Oí±Y×a ;GÃpT¹Ð ŠÈ•ÿôvg~Íá›Üƒ-”Nr±‹M£vcÊ[@ú§ÜÞ4z @Ǭ@ëO¸þ¸ÈV@„#¬0@ôWùx"†ß0yƒRßhD eÿèoŽ=;._»ÒTØ4î¤ìó{ÑkçÒ[½ŠÈ’hèÈ¡ðòÝðê½öÜBõâB¢XÒ¢Dù÷P¡Bãáïy»KÆçs³xL˜Yjߦâ:Õmd²=ìºLÌ8s/qÕöeݺ¦Æc{èЀ˜õ/usÛuVØÙÑħfXk"\LÉYÁ¸èeÇáÅ'ʪ×oõÙÆM‘3õjDfŒ3R)p93-—ß6À t¨Yôä*Î" ’Þgdúq¼g°O…êNg'ø×± X!wí^Ö–ªo]kÕ*ÿðŠ&-¼=þ¿>ýϯ7>½§º9¨<5pþo¿çï?SyûÓ” Ð·BO:ˆ4UäF[>ðëæøêÅ”ÞÍ*­£•¦¹Ó3VÎLÍÁ.Ë×AõA•…î¾ôÁY‚µ!žÍA9z|w½ Û½¢ª ˜íe¢ Ⱦ.•¿¼ÀÎ/;p€¤#@œ®ä` ÉZ©^¯?úãæx6îºúDrú¶º:tév§Ûä7®³÷Tu[Õ+m{‚ wüPß½iú¹NE:6j%U«–Â2‘¸ÛE~”aAF‚äÙg²âBÓŽ÷<øøsñù•›÷ûƘC»FŸ>ÝZËîþ8nê;wIåøð3t¡Ùóµía„ë¬Ó#X:û‡Æ $ E°mP¶Å]cëi…TGÿã­™Uäð==ÖËÆX¾"'ï–Œ2¡{Ý6¬-³w.ÙZ-üÇßuR|rÕûŸúðFüÁmèfÖÊĬLÕ¿~¹zä‘Á×?k Ä=c4CÂeûmHœ¸Ô‡Î’5 —¿ŒËד@¸%<ÈúiêÌ}kÎq[ux· 6@õ¢.§öžævÚ³ó)¶—õ@ÝM–±5¾ê‹BÙÿÑev~ž²È‚¤wÄ@ÁØ%••+htxøÓ?éï±fõTÙÑÓyccôËÛ¬ƒÎ‰æ6¯B‹»'Fí £ wîÛvÚÊÙ#GCTë„0ôæçîõ0ÎH’¨†I½uÎ|ù©¸~£wé^’Äh#égH"ÿÚ­ÍLfÕ šÌeq8‚í›_ÞL¨.g:O4f`u £!B)àLÛ;«záþmj°Ó‰Î}D´Æ¯ë¼zÕaG,ÒÎîÓð1Û©*ü&r—(tGhNÁ°nÁW†íÖaµ”,ÏzsÞÊbjnv!|›‹Ïx(ÀH “}ÿØääØfìe/xX+²R,rcB2°^/‡1n™Óó°€à¼68w£¿?—OèÐ'bØ¡iW>ͽm"Ù¢°ýé‘A¯R/‹ì浼蹄EÖë“Ü”x1uÖ1^ÍŒ¶Œ8IReN³@KkýGÏ[2;+yk²´u ïvÁ-‘YG²t;‰3‹¾õPðÖ—Ýß{³ûéB9–MDñ¾ÁR¿gð~9ŠyQS2W—[ sŒ\G«:";NºÅù^:w¥”]@ÅÌjfgU¯‰O[¥,¥+}NtÛÀ^‹ˆ³·±o-§0âԢź·w‰0‡´ô5®q_óü¥?þ(³ÒÕŒ0¦  € 7޼ ­¡‘^,A¢(*í«~t­÷Ú›­ ¶D¿‘æ"¶·î¤ é­ûêÎ*WZ]—,U}EÎÝ¡÷ÍR_^Ro}ŽÞøˆ ”• kœDÑ[_Ø/>”7fú—o÷â®kæqÚ‹øÌ݆U/ò{4ò”¦U;ÞûâZ×äae5Ä!8³ƒGÚ9¡Ìýµ¨ñé Y‚4N”£ÐóÜ+Ÿ&¯\sÈr‹¥3âÔÌåUåÞwžC“±U‡g¥Û¯Sð#>n>¬a0ÅÍ9os£2³¡ÌoÂè;Ø~nÇ‘s mþK§'¦'SÉçO—.^Îz†U,Ú1TL©^Új_¸[xýRrg£wâÐè'+Í{[®f=…¤0ù‹ jA±ø=óÀ¶´…%án¬ŠBì‡À^UJ 82Õp±#…ÒGXËIEæ0ÄmÀå®ÇQ% ÈB6Z”ú6Á«eÞëutà/è{úþjÒ»ÑSè¦U_›G#³Ã˜–öcjñƵ¤F¥„Õœ=aéÉv?^Þ1 x-zï^¾v!zzÚfÄ›3Îw]¨ï«[·Ò¹ó9|ãHøýSùüÚèí<©úæŸümÞ¼ã®þØlÍ©Ãû/-·[‚zŽä 5½Œؼµnê9àð§^ø*­öuL´"&@ ÆëTÎ)kÏ`4H½a¥VÔÖžFÂä—¶°‘:ëqè³|Kã›äÇ7àÏßU‘AC 8»cyÓpÌ&‘hÆìá“~-Pw6äÀ鋪ýö‡\ÝÈdßÖ1GF«R9q[]ÒØ·ïæ-aJÈ"fg3hö —î÷¯ÌšFRneù„'ˆq«Rߺ•¯o˜4/lê¸2$©ŒH:ÔÏ5÷ÕýÕp ÖÇŠsíÞÄ[%Ÿ\öhgÍ@„²ÄLt{žÈmÙ¹Y¶’hÌ‘ð¤ÊíúFéß¿‘~r%Ï /2&t ÛˆxDÛ^phUÑE#W™sÖÃÎ2™…¥±WÉ&òˆ¦“÷WÕ„S˜òwÚËK-Eò;'‡¯¿¾rù Dä¹—Ä—×yƒ§;ý¡üÍÆ¡m¥z¾ž»ùÖð«–;æƒËckOÁè O´E®›²§a@Q>f !Ë3ydÈâR‚ËRÖ êSÞ3ÊB4J¤À @¹=„]M™ö˜«pþ‘ž³ƒa¥ß»çá%ef€­sÙìw=/d¤˜\mÍß‹cB¶mîäÈ ‹ˆä¥ÖŽ#ÛS4å:a-©1¯tк6QgÊû·‰Î&»p7ßé#$Æœ(á]÷p:™ë3{ë^ï~«82nÏîï¿||à—ìÍoÕogý Ãÿäo6nŠË?Ê7ïõ,][J[‚ú ¥£¡½œ štkÙÔ»YEëOhøS[HLætHd5ÖY>'e_ ¡AÊG´Y *®ˆ±ày.Í ™oÈ÷—õ)GH´s:ßH~rÃüñû4¹ÜvB4¥[ZbpØÁÁ˜VÄ=”¼»[ùЃ“sIòúGÄp¼Ø#UR”K«ó@þèâ§÷³›ËrùüÙàÌ6ôìþø¹}ã7–“NÓ–ß¶½Ð6k£Àguéê½4£xÁ¤Þ\µƒ}]ä•ÜÊimzÑeèQí4‡'™ •rš`Åij¢ òöM{¯¿ís•}®ûç”õÇnˆî263ØÞOÌ"þTv®±š‘¤1¸v§Çç¨gø03@™‡h¸;WW('V*’?O#ª%0ü(+O©~Vw£gÌÌúÎû™¾ËG¶È¨aY`·gÝÍHlˆ ²4ÕrbÔû×/¾|¤ñÈd84‚^ýDþ캩ˆóòx]Ä×ßÀÇ•ÊE §…ñÒ¥ÔÑ2³*qz sbQ…h…h j)4.K\Õ­rà£ÔX0–À˜ë½Ní¦•EœÌ)¾0( .ã¥~/yïŽ~ëRðá]ñö%6·4X`}?2GI°S©‚²[Vo8„1€s‚ò²Ò) je{â´Þõlps«óîk¹ÏtK;…=éœëKeØVÚùf»®Ó¢¨î­ô×<Ÿ 6©SD0`:óB¿.r•òAæ ‰ÒîJ^nô•vñLg†&È@Uª™E[Ø—?÷µ}Ì~~·~q6+[³D1¢žg°ÅzT»cZ…Ζ|¶åNå÷V«ÞÈ?¸¦ß¾<øó+Ý^fRWâ.ÁÖhd °³GC}Xò-”_åÖhJ²Ö‹ r>¶gÆÑS^‡­n3F±Ñ®ÁÍG’d X á“gà ¬¡‹C§¹»µ˜Ÿ>Ïò+&ž7 »µÅû±7ãÀ’IpEç!)€ê6•Þà&NVð“™©;—üc‚·^WS§¼kKâÆ¶w­VMË;D¬#Êúb²–Õ‹2#ÆFüýÝêËG;ìqµøÑ»êÕë´^ÌÿÍË#¨wõU÷ Eý~ óòvvu>\c.I(:^ )ºbö¯ Xb¬=°‚an¬µ–#d`®¦Úêë(]ÖÌ 4XFœtP)ï¥Ü2¯]ª¾{/ã Ü_,E8+xî¨ìÒ*Ò¦aô&XŒÁ:˜×,¸TŒòSåÛçw›7ßHKžm[•`eÀ*Úå¥\zÅl4ÅÅt`»ßnrN•D¨grJâ,¡˜EZqlùO¿íUGÑ¥›”åsböx.•q¡¯Œ@š¶™%Pž¹ë"0‡‡ƒŸi·íi!# {Ø7E ö³_–L­HŽü 2‹ PöûƒÖŽé$FÖ â F„aß< 5·Ái§¦­»S†Ü8çž$Kg™N•¾R‡>'¹rT}jé)ÈVµÀþúKÛCÔœ½šu‘ðöÔ¨‚‹Ïî+ßYí}1ÚéSã¡ÁÙ;·ù—7Á8Õ'•b@¾a²Q †D]¤}''‘3¼1Ÿf³¶mÆ›¦¿C†§©^×ø:Ñ¡ö=ã[s ¼HîÖ¨aíç¾¼¢Ê÷œ¿ìLÆ3£ó@™&²VqN°£g¨ë‡ µßåÙ†I×´ éQ1nZó#wßsNø.´ wHúGŒäÊÌbÓödzÛÝömµ-á“Úæ {ÜFˆW´.s¸ç¢.öˆKujx÷TÆóð?}&þêK³c@ÿóoÕÊl3 ¡Ù©®o$}%'7»v”.~©{¶ã…A" PzÔfÔò„±»Z\µ…n”ú¹U®žyi$MÀ]®ò—…>c\Å+~¼CzWlfŒç çĈ#Z9æ°g‘ª:™€ÖðÃeýx·0leѲg f5S¸@¦Ô‘åÖä}ý$~åò³·\Êõ¢éMsxÎ&¾¯¥F0÷”αúêóôëGä+׬_ÈÄßi„#˜r•E¾®âömRq×g}­²2Ô"ÌQ¬Ê98)ÚÕ«wó##ägŸZÝëI뵬L~I}&pÔ€ò€Kwg‘*{kÂ1Ï`aÀ¢0È‹Úí2¢‰ÁsaG”~Æø.¾ §==iõj`¥L=n©$JØv)õs’Ö­“E¾4„Úsªµy¨H¯7Žä%­I ¨ÁÅv÷ ¬#ºHÜþÜV9“±tc³ÔÈŽoÛññýü>ˆV£ßþE\ÄØã¬ä±ÚD‡LE#gX0šC–¤µ­ïë^è—ˆ'Ë^Ïš¹üÔ†UŒ¶`±q·HEq=w/èHSí@EÊ'ïô)ói¬|lOøÕɼxäaÓ_(£¬—[IÙU£¥`>µëÚv|£,!6„ MeTÙcv¾¾y®O¤±†@@4S•)a£iFk… ]®ó¿÷KµC;»^×ܘѦŸ\hÙÔº¢E)€&(ÌôH)xö@:2nîõn­—ƒïÃVN½`ò&·ÎCć¥Ïir}A®Ä|±g¡ÃÖ©44Çv@kü“ÊÃ+>¹©H›¸y•S`ž«Gr¹Û¸q3R+Á‚5‰1¬õÙˆ6Ǭ ¤cÎx„OÉè†Rõˆ#Y µÌYƒŒXq‹ÄÓ#€u@¾i§TÒ¹àµcv×ÎV0¬ÉaTŸ N=¬*„:GàÄAÖX|÷&R®5ZÞó{o.÷­+ µâ„¢ïS×e>XT7ö&SŽã Ü›ät¤'tÜF½<ØÜ5fìÓ &]tCÒסû¶gr‡r‡ÀõŠ%/M+` P¢àœ‹#„$Òž1%:c²œðBKØ\Æ0«Œ‡£)ª+¾Ø2Ùª¡‡Bõ¬ gl* €wÖZ=ÿÎÊ>]Ìí"²áçÖ[µn ã9j÷d0‚ð¬I2Š´3«Í|zÇös7’?ø¨°­Dÿþ¯ÐzÀA5§vçáö xW'$Ñyg³ºº…”üŠÊ:“e–[÷¡—¿GTÃJ¥ 8ÐÄ2ëP8 hȯښñ-Ò—Ôcn¹fÔa÷`±VÊü=|Rç} `Ú6Í94 šRkÀÎ'zÃBÛWJ`ëõEêo9·Øƒ÷.¤Î€E ©á&÷ŒZ":&26\ìc§h™þî/™êÒXݾ£³¾ ±ß@ÂÚ2)C,$5eLq"<²è­·ÛuóÈÃ¥­õ|½mFËCýdÑóH–QÌ\[¹mP9\-TK3·º]jimíl‘.Ùpº³†Ó‚ÚÚĕڹ,{Â×6r‰”æ†3uTQü ¨iŽ|]—4ÅÚ´œ¸Ð’YD­ÆÔ×8Æ8ó4ÄàÂ=`Ø ­Îc@ZŸI›íôg_¢k7&6WD'¡óJ™uºÀñذ޿Ÿm.µÞ˜1½uz³‘€Ït.v0} ›Z}]«O<·ˆaÔ„¯8u¹Y‡­"{®+ÿø/LAc½RXÍò]=øz€вtùûJ~îT CP”(NŠ¡1¨þú)4Qá÷74˜zžVé“{øÉI²ÞÊ•ÂQA 0̈˜4 ±‹ÇØiwZ_(jšø²PG`ïA{ðìvñy´ã>3æ]¢®0¹l`ı…ê3¬¶„­°hÄ&›žÛ´ˆ4Im§A_¹Ñ~p2ý­_Æ ]“»FžÎ'òò­Â¦ÿå ôöGáŸ|¨V»‰€¢& Ö3²îÌ!Es‰ cÀ€pãŽx\Zg\†©SÖj'(ÏYÉ¡®k<”1¶³ˆqm´SÖÀ>cG!ÉîùæË>š3íÂhYÄn›6ŒQ¹’Ü:0΀³V{Èsª™¹½û·o.ý¤\¦hLANC–7÷•¼¸¯FÇð×¾R¸©9{F§+—IÞ¬1úJ™`Æ£ŽÖH¨­(nG'ŽŒ½õfok…?uº¾²•­5õöJ)‹7läB42 ¥6QµG 5æv·ªi óÜH‹)8+­ê{8æcëYÞõ²uewZcã7Ò¤Ìl¤¡ 2W⎱‚Xî@cz™{¶Òñ2bLϪÛ`;˜ ‡ˆ´‘ó2æ;N!¬ ÖîŒÄ‡ ¾©Ô5 RìWy.Zɇ磫Ÿm_í¶­©ß›ï+?w J «éž}.mtÞ›wKÞ­f°%ÆíðiîæýÜáOM¶z/ŽÞ%ò ™_‡!vÊ)†¢“ß³…F;Šši¾#A/h¯ÈßÖâ}P[UPr®ˆvÔXf¤ ùúI²}î­kŒeLiñøNïÄ”ÙhK­iÊ\#Œ-s•@{}3εŒÜðö¾Î<–‹vDÄ¡âž#Ù¾ÇkýóÝZ›]æ-"n"¹©Üˆó^ñåE£·ÔÃòv/s·eà èuý7n¶NŒf¿ó7‚ñ°o…Ψ·˜©÷/á›kòËÁŸ–ÿøCµØéIW±4K{VÖœ=¢H*ɬ¢ÄQB˜ä!0kXž°cRŒBʵFÔ†¶È¸ék3ãG¾Æ!8f½nc­:NßÕ…ë† ª%2k‘dK„}ê5!Ë5`ì—cb™CÛ\y+Ú>&Íâ$(RZ×"¨ÆåÖT:=51N¿ýäÀÌõõ™;nxOíòŠÛÅ€¡¦2¢È8¥,ðY.RȦ÷ynv]ãõU²²ÚûÖ¯:²¹¦kö•‡Ç wolm~e¥> vAn¨F֧ѪFJÛ\fÉ>£¢(œÏUfÁ÷+[[MÍýgŽŽÍ5퟼þäSóÓ/ê?=ß¾²ŽVÚz³‘oŠDFæà¾±2]“;¡­W™á~ãf9{ÄxÎ!;‚…ÚdÛã}¥ŽbZÑ¡Þt–ƒ9àœG¸©Æ¸»Ø¥‚Wåå’=5EÛé?¨ªo©X…¡$Æ0ÅÐn;g&õKO&ÓÇat ˆÉA ‰¶É°óINöí‘ý{•{¯$õÛ`š^'ë˪[\NóÁÏÊÚ'ãÄ®ç2FpüXwÞôÊN.P{âXù̳éF¿4¿@šÖî/~õ›,è׺Ÿ¸^‡ìأϑ/lnÏ jCö°BËÚ¦Z+¢éÐo}3xfÏèáÑ|¤(Oîª=y¼º°¶¹Ð` ë §6jB@µÔŽ¿¦‰a£¢»Z-CŽ´q–Ü5ÙÕ˜Ø'5‘ÞKåã"ß‹]IÚÝÚn8÷÷]*½l\ûµÓøW¾• ¸Ò RC39PÕÐvvbs«·²¤.ÜiEØWF¤Î3J>Q Š1w¸Ç¼y’RûVoº U'ELhoØß:ËãÙ¼àØ7"%2g=F;3,EÙ˜S`§AÊ@aî¦rµ‚ ¶ªhÔ¸FVó¾–„$ç2= á¼ãaßiABÅdßð e=4•ÿ“o?²'Ø7¡¡3Û&2Ij–60™±†à²Ó™ ¹ á¼Zõ÷W/½QŽ/ÄSScO~ÃŒú.ð½Ùzô ûïf^}pÝí(1 ëÂ6ïî}¡tÖu0šØÂEpìpÄ{Ê­³’³¡}ðpáìÓÙr<0»è?±G?y°ðÜËÄA÷c¯Û&S;ËçÏ7æ7‚¬àoÊŒ¶È·V8e¤íÑÿõw‹OL׎mW=½+|úØàâêÖ\Ç6t%3rÃsmÍSÆú@ÏNV«`R¹ --º«Ó&VšÛ“ù¾ž¦ò)­¦ÁU”Û¡mËÁAÁHìHnUý'èßùfJmõÞ,l *ÛmõX421¸ÕŒWWÝåûýP;‰L&=d’SÎʈh”Q|ÃWHp°*e€V,L!{•2):,(íì)jµ-¯_B3:xÍÅk8‰§‚‰bræáŒ—]cÍŽÐÆPqd Ö×’ŸžW&Éø š[4'Ç1ÕkWDÒ@Û&›­øÐ^tàîÆ:#"UËËÒÅaK¦§…ª©¶0®Vè’&fÓ@ {’p…ð¦ÕÚZ ‹öpŽ#V{vÁƒ8¶y™‡—V6¯ÞJÛ]Œñ8õVmƪ×îb ƒÎ{éaú[Ïçe|r5¤4ÑŠ÷8=àô€Um»‡ª<Є؃-2mÁ”­ÞaHfò»$o!•í©í€.ù<Ñi¼@+krѲŽÑÇwëßy¦øÍF§êñþ ôÐÔèá=,W°¸.„‘Ú8ŽHÚ'AÀäx‰6*_}·Ðþ8Û5½í‘o£q&j/4ð©ýßø^ÄøÒ5=)Pb(4…áüŒÌ”è[¨ƒ"¿þõ‰…¶ ²R&³#‡³]Gªóín#°ûŸßÖÈáÍ÷âÅÅ IùÄãÑãgûÍÙý7ºEg©‘«ÁÊ ×Ýê·Už±5†€eÞ_ú¥¯W«Á–iwcdZȲ@†²õø±w—ÝR7Ýòt9+=ä„eþ4BÇœÝ*Á‡ ;N±ÊU*K+ú2Ö9‡aŵb¿)GBap–zE„KŽ\púA!±¹`[ßF5çÍx½vꌘ[ÒÍ>ñMøüiü›_ËŸÚÞ{â({è!2V©|/ ¸Ê/"õUd¶ŸSm ÆdN––NGšZà£À¦,ºÏÜ\î·“p»¢Å·þ8\ݨ~ªV€¢ó©–¹¡‘‹~ý(úíab¸òÞ 34”îdŸ\O?½ç‚g¶ÛQŸ_Ö—fÄkWÉýûÄ‘²d²ÙAÿý¿ó@’¬ðë«h5î|êL¢ ­òÁîðæbñ)¶ÞLçß—Svì}Ò.YÖÅ´(TF€2€J‡ÁŽÐU¡ËV¼­ljH‰n¿ðháåçä׎xß:ž|û9gLpõ6Mr˜®Ù_ÿëdw‰wïÇ#{² ×òvy¾“Z¹1Æi欳(|PÞ`^ƒ(m!pàŸ Ç«¡}Ä+ô—ä€BëÔ_Ç[¥-™l£ =¼-úo^ôÉ’Œôf‡dÜ Ä®½cíÌmf4ð‘RàåE7ëHÑ* yyóƒöÁ$™Yh{“écg•¯ù½{¤e:sKÀø®‰}øN¿'kèyœ¤®à")†#á×)ìß=¼”@yž>˜í;^™ku·B6ý•Z/Æo½“Þ[Ö Üó„O<ÚY½—Í¿LÒÅ­L™Û+a§ÁÛª—QÒ ƒi€9´SÿêwJƒ~C´ûJë†!uˆj=r|×½5±Ü‚>Ï›ÈY©5–…Ó@Ž8ÑŠÈàÃå©3¬2¥;Õò욺 &Å0¦èI-ÐÅP*îPFH™ð‚µ—ÁÞ¦Bù´ýݧYr•9ù4]¹£¶zÄfø+‘ßýù•iýØArâ¸ÝVúx6÷¹UÊ‹\þ5Ì/¸ž¤ÎË”’àvEÇreöSÔN(Å”ìÔC~éÍ? «µëj­ëhÁYÏâÌG¥_8‚~óÛ²6\ùø: ¸½#ág7á“»ðÙ]ÝÉ賓x{[°—fò7nÓ»óæÑCeë›ÍNþ¿;ñ’/Ì(Ц®1š¶l“jRZ_©›"›[rå=±³s&ˆÀö0µËœ@@B ƒàÊ×MmPÙ·‹’Ä–à‚è'ö»gÙ^`ß>Z}éHçÅ't*ÍÕ;AbÂébò¿ì«y½›Ý¡ɹÛy; Cf¤5u-§0 )¤O¢#ºPré"öz¾Ñ˜D G½mÇÕÄÉ­ñÖl>daÍ W­ÅNYb,6­ŒL‡ÿõKåm~³£:]j¥Q¶ÓãÕt×þr«“/l!Ï$Fc†ˆL X• dùþQaî-4 ƒÙO(GñÍ»ÐÏâÍE`Þîò¾l¶›f58ý"ïfÉÕ‹Øcaa0üÚ£rÜKfZ‘—‡ì[OU(k×ê"ïÙxç º²9ô{VñË7 ÊhoÞ„*DëÊ»àüb‚ºÎ£QÓtý ld¬Ï¬ú¥Çñöz{£íªå²H¢„õ= !J Ð+÷EÁXË<®4"§µ*ƒiDþË•l_Ñ6µÜÂCYäØ(Ø­ó=,õ³Ü±Í W—ì%bcvÎGvÚ¡]zEÏžïÓ‚øk/‡nε.ß˳føè©°èå427ï¢ë]Ïd¹ú0V»œþoX±Û.ñRƒ4ƒt­"–tÌúæž”ýPLçä>.¬_¶3›É[ЬÈcF_ÜRÚDÄ$8(ÑC¸€H˽ƒ®uÏ ¡Jƒˆ½Çü¯üáëN¸nÞ…µõçnͬm¦;vŽ .ðóŸ;ìµ×Ú&S”¶gºEÜÇ ì·Ÿ¬~` ”aùÞçñÛ_…­¡´×¶š]ºe”Ækи¥Ê¶²nÊå]É…¥ ºØã¦)Àó=e¤ÓaàÔwŸ°»Gú›Pª×óffIÙñĈpÂß¼×3+KÁÙˆZI‚“FÕ@­ñé³hh,=X4Méñ[x€B`½që»´ÜÃD(RÌ×SZ¦ÂàC#R¥R`èÑ]t±;¯¦Ë—¥Áéo~7껿һ|7k.¢°¡"øU¸y]ÛòˆÌ=Ï?ªóiûÖ³ 2i4`Ør­=€˜ › –µi”ôtޝãhþ²i¬ô^c±#dM;fHФ p«=U”.×~|µQ è׎y×gõV2Ò—}°ü›'üZ¤Þ½ÍRRKôH Z/?̯.Çë[ðäö¢TÝ÷ïé;]Ô–Á§™eÁ¬Ì“ÒÖrç^*+ËôŠý Kïz6V¬’XMa”9;«-Üw_9â‡Óž4¹b¨Â8šåÓ§¼ ïDÕòŸ½Wü/tSO>Vùo¿éî]ë^þIº5ƒp…m¬ô¸3I` ¡nOX $[°®_ƒî6cvGIÕÄë$Pð0x»m8ú ÿôî¤X’Åz0{Ë™UŽÞ¢’!k4w …@™oq u`ª8Í ƒiZ Ò¢‡Ïݲ¹ˆˆ]VçÇ<Ù7âZwØ(i‘xêüéµá¿x)Æ1,7w»}c9ßµ;:xܯùºVñ®|¢¥«;ښЂœÞ frepŸ z…ÂÐkŸæ¯~Ôÿ|^¥1$ODÚq¥˜%ˆ¨™™4-¢í‡GæÕæÀÃxçvþ³…ÓÃ~›fÊeETvË_}pg=¿>tûRúÞ«zùf¹±B%ŠQâ Ñ‹·LGƒ'²X[mŸðJA/òÎE¥Uõå’óf–g8¢&C_=‘nßlÛàüF:ÒË2ï!#© áÜôŸ¼†ó‹z/ø[´0¶»ûp-9:å]Y3:æÂõèԸĞý¼¢h"º£g@Ñþ*'2ç˜3Ɖ“ÿ¦-¶!‹©ísl´¼p1u_eFle÷[è³Pje‹š]—kÐ;«P*}yO|¶üø|ì ]õëO–»äÞfêc­åìfþ¢#žXÑfc¬7¾\xÿö]/Ô„ºˆ ÁƙȀúä¯}£’&-K‡ëÅLî^ŒO·O’Ítª:qa¥×hã ‹Q <ðEèùþZ'ùæ#v‡¸—6ÇϾ±¶õó÷{]$b‡$r»ás—Çè³%yùZ\Ê\[k£ŽlâÔè•È£Xß±J¸a£Ðü­õV‹«WÛæŠ‹J´ aØOŒs†í†ò•žóÓg¾^?µ³ñfñîME¸X7ÁHD¥ ‘Ü>\9s¬ËÓ›çß/œÙÌkšÏ`·óhePø­[ÅžÊÂt€ËUÃN̘ŒK™‹F}â¬ÖiFÛ.Ò5IaÑÄBÁ+{,ûhëb>hÉm^3“é˜ð7ž‹3#gçý•’Ûq2¯b‘ÕêýÇ÷!ÑàçúWØzL¯/PŠ´†ÊC†ïw¹2Ðõ*êQ  xëY”^ñÀÏ#©©EÖI±7w âˆ÷ªµ ñ±oIîvM•þÙ‹aγ sðƒ3õ"î^Yˆ¼r&³8qv/šœ”Ÿ_w}æqßþâ©4dðÆ}+q¡ â×_àil^9¯PRJÛMòÔ4<¼wè­«Ý'€øT´à¤¥5-æYÑÉq4–5XÚ('–kŽ^gê.JÖ¬³ˆƒ“‰×=ŠÐ„¶ƒbl7Ld@ I[Êþô³`n£svÊÿ¯Ã¶²ŽmG™T¥Ùµd–“'¼C»Ý‡Ÿ-Ü`ÊhL†|\צ zâ/ól-é‰kw´¦³ÉhdB—¹Ë$[l¶Z˜‚a÷lQi*Ql#Ô•Yñkû2D«$Ÿ}Êw/ë½y~WS‡š<«›pëÖÌðF»©œ0Y—(/â„;˜gÏÊ¢Ýþûç»]’“0²¤QcÃ) %Ú¤A”§q/š»Ûigt½LÅ´É9ˆ» êõÉÊÝÍ­¦e†nP7býE¥ºaà}kó§lxm­giþü·ýÓ;ä¹[Ùí†ûv¥N—A&BdƆ¢3‡º\ŠhãÜųk¢ª¼{Dn?Ú2~ÿNµ#{ŽPg4Æåª%g¡ÖÑùB¶)qˆ¡›Úoqh ƒ rY–Ñ­‹Y]ÁF/k Î¤F€~ð5Y7ÁÅÙ|ÑϧN¨Ú¨i84"ÎìÝ Ï-õ¾¸‡[¹yÖR±ñ¡ô¨59%™6óŤ$ÓÊ ž8=ɼaBe°ÃÊi=ð3‰—rþS£šPy ìÚEÿÙK¥œÇïÁ¯<8\d­+ó+I) ÄC{ÈÔ}þïbëGèûLjòµY§°)ý·¾H?ù"˱OJi»ÃÙi?4öæµöƒûÓÿîùÒ\‚’-­PY2oY¶O³šÖ¶é§[²bP‚Œ·©¾“9cŒå™ ú‡-™@PVúnUd`ü-c~ü_\k?² ý½—õX] 7,Ã.¦Sçf›qˆê'£#Ûä»We"Ó"¸áAãZZŽöCAÒJš™k·•òjfÄT49ªêgìþF­µÙa=SÖ䎋rÇ4Š‚5 ‹/0ž^)ùìs»}!=¢ÌmYÝy é©šò7®ÝZoµ¥mk”siä’†ã#øÙ“I8]xýó•/˜0´ìP‚优(J‰'ÍjàEIž¦þâÍn[Zj·#×Ùm½\w6o”FKHÂê*s¤p¤Ã…±D®*hù¤n¸ cøâªJ|¥ÜU2sªL#)C%·€‚cA´©lf”‰³B½Z³·ç+=…GÆò$G!"ª,™ ½ 0æ™Dt‹ûˆ¢TEËååÕôSÝ}òëpf/œÜ-û)Îúê "#ÛŠ}Û¯pˆsE(Ë»BcÀ™ƒ€¢Û$“ùá½õ‰á´nG±äd›“NNI±h~çkѱýÅÿó]xõJ6®®isÀ¢Ž+Žâ‰§UcBn?¼A»K¹‡–µ_V¤ b¬`Kr´GƉïåbå›bþ×NË{HX¨¼sA¾~yùßþÊ0úSññ|É ºY6xWn=±ðÅ£ðóó±bj r/®´Ú_961±·ÿÁÅ$…ÀkÈnðôöÂï¼ ÿà÷ÀÔ¿wÌÏ¿‹4OB¥…ÊÆçMó®^°ptëËÜÌJWÊýy°9VÙ ɨÊÖŽ‘rHk½2@“'L×4äo_‘Õýη g§• Zi?L”ÎÍône„k?ßVÀ½8Ù=™]Ù@F;Ð(–@PÁÅI?Íù$4³Îø$~þ{Žzqª’/(¥÷îzïþÌmÇiäªLµ±Tšs&sÌ¥ÁĪ’òsÒÏQ4.o\‹¸RÛ¦BƲ´‡hë,£e!Ø5Ë›RbÂÃnš¶ÿöÝÁ¾·qc¹ üîe±ž{€  C’6HÊ% "mİsJosv³ÇÈåð(M׈É]ƒy6;h ˆp¿w¤ã…Ñ<]“¨Ç}œštÆK #çn˜~+ýÁ³c‰– Ü•„št¦’  ¶6¹MpÒªþàxro¦ÚQx`°—äPñ‚'2F<‡ñ©½*ÅÌaÛƒ0­¬­åŸ™ôÉoÂC@íîe’÷à, ;®3R€îR)0\êi Ö â;ê¤(ò¡m¾÷kEiôd½˜õ×}äº×ìõ5{t_ñÿzÿôB“¢.)p¯£ vì ^î%:½eWfµèY¸§ÃH‚ò)_rÎ 6™å½ ?‡ ‘}Oƒ`ø{GåS~1xïKñÓó‹ÿî—ë.Ÿ,„U÷L}Y5ŸØQ}öHô£/–΃´NË{}±ÒÆOÚ±_}t¹™Â¨ÇÖl7:;Dþî7àŸüpÜð¯>¨öŽôé8üÃY(H“Ä÷¼ODë™"<—ÂÈP3&›ÏŸG‹`äçAÎÈI“.À8‚±-ج9ÈXØbgï_2~ðÛßÎìVàºÊ"€†—ÂÔ®†ý$ÅZ$±Ú9äͦ(±9¯+Ï3:ËæÐ‡xr¬ðÜ·ø:Šô€ßö(ܼ¯ýLí²¢W- ©2†{ÌäØãyØ„1Q_$Ñp¾ˆë-kªÊc4K{B[g9+q€Ý"•)XЙJ—[ÙíÙñ?zsãÎr ŠÉµl3à ÊAˆÒ 7a‚õ×­›†"7ñê<)ã«ÔЃ'&®¿¶LŽ"Ç·³¿|­0³´5L€q˜K·À–(¨çØxUÖP¿Àìú£¿èòÊFÐM“rq¬µ=­€»¸‘4³hçÛê´>8º:±6Ž+;wæ²ï0ç7’Õ´e €00`ãë&PŠ•Ê F¹JÒŒƒ#Vð2B̹{ùÖ Û]§‹[º ¹AhÕ)ŽK9A™aó}ö»ÿwÎp?(Ë X¥ÛW7NFø)L’‚7¢4ÂÊ’¨ôÈ~HÚOä àM³Õ4¤S‡mîä™âvSC*‚‡üGXß@ç.r† ^qÅRÿ­µç ÷W£Wε~û»¿I¾¼âa–t–<>Õxô„{ÿü`}Ì ¯‡FüÆúèÙˬ:«„°Žpü(ý_É^»œ.lŒ¾þIzs© ‡ 0ÒÈó/e®¨ ߤ>ðô²áË$ òð2dvªþÓÀ4j¤¢`z@Ž|à­r‹vi™ñ€Ñ^mýðKŽ-â8ÏR@^diƉöŒíô•ÉËÊÆ@˜¯ÉªéÊ Ú[¼©y3¸½)‡ö°3{µ2Ú f2!%PÎêé.P_`çJV1`¬€%°’u/nÁ#ÅÉøÄ)77hÛ™žÜl-ÔªáV^š[k‚ À¡ †Žƒre8î49ãwîòkŸÏÏÄ༬—Ø—‰å2°Ånz"ˆlõõÉí¿òMÿ“ÛéÏfÁeá®…0 _þé½o¢ÿ·‡þßƷ–;ø†/%±Õ¥‹ P¼.ksЬøbf þø/WÃÁ1ŒqWôJ…ážÞpRKK[Y;+ÖÑV³sìÔØÂøê.NO;ƒRøJJº(ÑA`DØ9e|€‚M™Ö 8”ç©rJø甚s÷ÉÚz`˜Î¯ç‘£Š¡e™sˆ$åBç÷³Â¿úƒ ©«•¨‰v̸„bÀ¾Ÿ¡4/z1BÈÈ¼ê ·Ñ>‹Äq6bïð_³+3¤à‰T‚å2™ÓkƒŽ?Ê¡ýóë Ã xΔõÞšë ©w>îG¶´°¾q©ÿ~‘È·Øg#C›Íí´Ÿ8Þþè‹ÑZÀèRÝêP¸¹=vr“÷ Ù,q.¬àû÷™ôUûÑ[Øã¦÷Ú'±>=ðÎJB]\ .7öö }ûý Btz+ö—Â\sÈtî–Y †ö³06«Ï O:“åólm@‰FA X×<Rúë[?¼ú9ãTu¤ñ)‡n'«T}שÓuñP‚ÖyžóÖMW#oñ¶Dl©…Š;ãǦ•“‰f,W¦çñ¢m ms=`¾@Ê­Y ØP¾MÎ/©³!!ðà ;_Õµ'j“[Í…ZÅßÈŠskm§=ëp…@ÇA…:m{^ßú£«Ë³ N¡“Ä0åªsÓ-õRCo_`k ‡¶U¾÷UvqE¿±”›®~f„ûkûCÛ é ÝÞC%¨èöœ‹´cÆÃ…¨¯»¡‚^´F˜*ºg_ðü …¹9ÙïÒJ%˜ï­9j¹¡82G@ôɱC¤æKHâú( -Uà@Xá÷?q‹ëó[«Œó¸·ÓmÊj°™’Ç`öžEÈÃRÒIç…péÒ@÷° ÝhË!Í3>ÖÚ8OsÆY^MUK=•ub诛ÈFRìˆòf'éX¯×I5½â–H(w.u3¿Æ–€'±²¢úÝ"lH]¶>vp‚×LJΔ­Ý‰Äm‹>²FPAɤF‡Üµ9ýêe¶¸U—QÛ1H–ÍCàwÉVjVWÌö¡èðÎ<(²<jëÉÃ%Îí§wºÛÆÃ³Glƒs÷¢ûKä±cðw^È”ÿà/“ ["V|¥;·ª§êx=“‚vÚ1³¥ æpÍÆ÷­]@.2,Åö4®¬©Ù Á9ñÉC2oY€†ç–=1dƒû¹´¾5™‰ò2³ñæßÈÉV_÷³R«tsÝt¨ÛÔ=‰•öªY˜™•³Ç \FšŽ–ÑȈòânµÊJþêìþ–_9%™£šùIÒßV¬¥Y¯Pˆ_øz”Y¥[œhƒ1Ñ:m±`ñH–y˜=õ¢ýîÅ)ž]º«—5ªãÉj I¼´d-õö {gwf‡OT\ ·gD  1üR¢e¨Ì0-[—X„Šî?¼ôõèîýv·e*Õ…^ËX‡- @4ÖŒÙÑC¼ÌSœ÷à –ƒ¨™qQ±ö‡_{ 9 Y©,¢x/ )9‡L¢-»Nk¯à;«ˆ5ÈXêÃÕkCý‹X-ôÛ7îÂ.–ƒ R<"Ê÷SÖ§¦ÙqIæo¤º ´DÔŒ“FÆ’Ò6iúÏØDœáEC¤dÎÓ–:ÉþÐ ›:«_ctœæ!.9ž€Òv ÜñÞ1DRÉI=-¥7gÔÏÎóÅÍJ¶,7Ù œyˆœÚ!:º´¸$¶×Mõ‚7$²ªñ BiåÜ\d$|ú4©¼µ(€–¹:ëÙ¼wŸeÇèɯ•¿ó¤··`¯Ü‹[C‰«¤KxaPv³\Å>é ½ðzËÿÁG ×6íçLæUV ÍUÖÕƒ‡ƒ_}Ž>p&¬»—> ò´ÐÏû]À?’¢˜¾”¹AáÜŠÈvUêE—{|¯RÄÞºyõ‹µ×/‚}Ï`ƒŠÈ¦ðiŠ«·°ß%rC–“a8~,)B`æX¿ôq6mDÁJk ²t‰Ã%¤‘±§ÄÙûƒÂ‡\¯-E·š)„qrOé·_ìÿò#ø[°¯Ä/>^XŒ[÷›–’ª³G÷ó&÷*ÍüA¯¨Óô–s9‡Üc@{Vc§@ìœobçs_ ƒg9ñk¥ßzz¨Ñn¶RÚ€ÔŒãÑgK0½¯´ÚÍç¶ÈéãU”ô§&Ð⬂p}4XâGöf\Ú¼ýå‡vz²ÿ/°){õf÷âSë8`Sõôמ¸Ú`½X0Í5Ô#0â Vš1(r¼ŽÕÆ_Åy,2ò )Çy}Þà¤F&Ÿ”#¸8ïîX¡Hh~|ò»¿T{iýփ蛘Çö©N®ô{Vú®°w\üú×ùKÇÉëã$s0=xÔRŒÄ µã‘n¥íÑ#N‡µC@¹2‘ï]š­µ»(&B¸ pVsWY€HÍÓ#¶¸&™IFv ˜úËÒžü‹/ÛožGÊDÆIë…eØUë…*´RÈãO˜ÓÅ“œÙR'¦— ­_5VÛž?þÂSQoÑ,|ÒI uùùK©TEÕN^ìlÅšêç”j—?úÑfHNŸÂw“b¿Û÷tRb6DÖØÌ¯šÇ¨þà{òá¨Zn]ü˜gI±Ÿ÷»…tG¹ç­J•óçÖAýÉJTb*P‚–HØ#;~ôÑÂ+çtFD:GJN§Ø¸3×-mc¿KÔ†*f£üøÑ„ÔÚ"ç §¹%‹Ÿdûò¥%Ë稾 –8«! ÷?ýJx|’´b$ÚÕÔ€öÏìªÿÖ‹_{‚í{ñ0{éñâB¯5[5®²38*>\?P]jöóUý’ÍâûÆõ/JÚ€\¡ sîˆ#{ øÐ©%%()¢Ès¤îÿÎ;­fæ”Ñ ¥(Äò¡ÐÝ ®¼·":Í\¬FÆíÎ!âF’lxÀîÝi"”öqá•/ñ¶jï·^ŠvIþÓkíÏn¹L#à µÝ3(þöWv^ÜtÝ8'š%@!×Ù)Lç_Ö¨îxÄä)`÷Ê5X?-å„W›Ñ¶[íÊRYD·M&éeññ½É÷‹¥wã¯Á_{?µÛ´u¾ÒF:‹Ê$?4a~ù™âwÏØŸ_Š n]ÎÌà!ƒ¨“cÈ ùjS«9w@”Í)h§#ßÞ¾vÚA‡ä9}§v÷´µÎR…L±?¿™Ë´»}|÷¸O„1**]7øçç[¯ŸÇÚDÆ ç„¦žÐº_6>‡p¸LÎ>Ö?v48>&i±°ÐêƒÒ ßÑ’VÒôƒ±àå£d‘/~´…xO$ÏÇG]^#­NZAN98|xtí¢Þ¾,²-ûì{ßÍ®Çk©2¹çÁ³'øWÈæhú‘n§²:&¾8Ÿ§yLX1á8Ï›À\Ñʲ£}í7²õõHVx[éÙ,<·Þü³/ÉÛ·3`¼L¼XõXmà!‡ØdŸÆ²šêù®ÎßQNµ"%Yeñ âýLYsË9 LQmM½ß9Ycï:”MîAyo¶Y§Ýž¿£G‡ýÉl¨ˆ6Eðïæ©óÂÌRžíÕòàzüX¦L¯§ïmeÇ=ÈÑè³Öî%bˆAÉÉÓ XSŠwË+#Ãäí®sážÍÍÿþ;Õí£½Îò6­‹ûþ™Cyð€á©·»Ø(’®®*¨m ²¡óÊœã‰H«¶¾øXêeeúÿß·a®o‡=»Óc¿ü"þ럽޾µå^> ŸÞE7r×êp„xÓŠ]@v—踒c ¡pÀˆmÖ1óˆOöwIgá^vä«öÐÞ.i»•›É=œÏÚÝü±#lw-v_]~øŠ¸¿–ãíÙN^þZ÷ô 7‚Ë¥JïÛ6àœÕ¡EvR;û\.ML cû >Ø8ë„L²Õ$öG`hº=LSE,½ ”S—iglRäQ†í•u}«E:¼Õ4a3Éovj?|/ûš´d¸hâ’5…Sçº~䪦¤Ìvâø7÷ê}àiJ^z¶áxyCzDH>þú/ÈÅ‹ºÐ›Ìa͈֕wëZ^áæîVº¾¤-Ü#ÛÖ¯¸=›qg!RáÛßo([Ê·¬:`ìŇÂçÄ’M>FÍž«ŽäçÏë4Ëð>ÕÂnŒÊV•3Ö—Atk1]Z+¨°‹U[ût­ù‡ëwgîiÈm*-˜Õ–< „X í§‘®j0™ÚÀB©g5B‹êâÂ: &ÌG”Xq×s3Ôa…¶…È|÷,/ùlpº»ï`š¶u«Sj´×go›zÕÛ?¡ é†fú±ì§Œ †ƒü¨P»Èkó1¼.ùújrã½ Só°¶'M>Ž!Àò(EÇ<Þ’É»`s BÀÐùÞ~{`Ÿ¿‹ekýŸÿÂÐÎɸ¿D­ãÖ¥IôèñH¤päF±¿w ,”[;®Çf+ ‰ˆo½…;ï–q|íùJ‘¤k !}ôdño~OÞ¿Lý+ÉX×Ü6Y¼~5cÈÝïæôØX¥¿‘x˜ªÕ¶±uk;<èÕ•÷ü‰tf–¬åäŸÿ@?·çÝÎ" w®ÁàÞ!­b iªca4!à 9ûX}x½eï¸n¼ ñ'k¹/+ ZŽ‚Ó]ðð¸È…ËIµ¦»-ƈ0Œ+°*Œ£ÃÈ~ 5nléÌÒrQ×@Ø6ÛÝ †áùÛ¥ Î@‚ÊœÝS,¬­çÿ¼IXaÇ‹Á¿ùkñû÷Èk•¯tºÿÛ|ÿüÍE‰-@ã|·óÃz>8Éûi2Uýߨ\žeß¶S3]Là®ôsLê< <·–ˆ;¡UŠpF´Löï~ù«Qgµûþ\~±Yþþ™øÝïû'~›}z½ÿÞµÅâ[·×ž?…Møúhy&øéÇâý¥5{=,@£"jy¡y| ž:\yñ©v² ÞDóçŸÂõ¡q÷ÌxðÆzößÿ‘¡ë× ½_}¼8:Iï¾*×>ÈÀ+ çYþP „Ð@dS:`ê픎Ëò…²:ót´&®ÑÏÜà6 ÁÞ¶Z=/êäÐíô®4á?|Н/8^ ž~B>´ß¿Rºùù<>üƒêÞRÞî) ”È@™F+Aà›¸ Z¥8,"ƒ¡›Š­özò,¤H„¤]¦›ÎscQ&Eå êvÇZ¡p÷~÷Þ<8Ý¥PP¸M¬’hÄôöá ª5:ˆ@â Ï 7ªÈ1ÂÅn£4syioœxwpo²üýç̓ÿë_°Šì}묫)&½&Gt!Ó<,zžîôÞ22w§UXÍuVUOfA¾ð¥Øñ„^Ztký‡ß·‡ëêgojtI”¨»~…ì©(v2kÜOI_Âcƒå-rßemW¹¶ˆÎÿE›‹’…&ò@‹li,Ž£¤1¡eÆJl ãèÐYÝO¡€ýƦJES)mŒé¦M-AÖ GRÁRä@!”9¼­(·Öƒk¹Ù5ðÀWÃù+É¥[ê'ŸÓ«ú_¿C¸¯ÿæq—:ë €Y¬ÚÓŽúfp¼ÒÏšSe³ýÛř݅O>$û[rêF‚Žü´î •ŠË>$¶è!,iwïAÿo<ë'ôyw®Yüwšü·ßç‡ÿÿôJ÷káåðÍÛgÔ„—^ ÖçÈÏÞ³ï/$º‡{ UR~ ÏbÏ>”÷V‹×/ˆË[õC£æ±}îÑÓ¬¤JÿÛ¢V{•’ø;ÏkãúnH×^ýÒ`’%W| ý,(`‰¨ì·Áø$t¶•ÎEpæ|ä0X•%9 M CMw“Ä©ïµ2ètÛW;ðŸ?ò..øpp0|þaxæwþ¶óOhzâÛõ½u·ÞÌ1b eB¤5^¢!bÙíKäHÁj™éõ½ ¯žd±Šƒ2îeLn_ >¦)˜ŒDU?锄Xs°´˜þÇ5ãT+BÅ7 |Ž˜þ~äêÞÇ!1”'ZA.xØÛXYºµ²'éõ®ŠöHåûÏÊ ÿ׿ å¼÷ÒC¢˜ z*㊙j +ø%"ûÇǨˆ;]Í"®w+ðh6êp`pp{ï¯>ñ?ü¤åÛˆRó?2øy?ªö›Qp„±XC?c3á,`pš¥à&¼§»-ÝgФpSLjºVÒzØ ŒÑ¾¦dJÔgÉúGi ËsE=Ù\aÃä2R^?‡·*y‘ƒ•ú¶Î‰Ãæë¿6úþÍ»‰8'8Æë§½¡îýu½dÅ—]蟨„ï•ÓûåÆõâ®úWf“µƒ;jQ:XŽ)5²^i) ó•vè¢Ív»b#±]—á¡#Èî4Ûº\ydb€\ßJâ7Ìua]¡j£°1ÇÎÍWåR»©H÷üfá|Ãýý—úßž„GvÖ?\XX[›­°8ôï^Ù_ÅK‚—Èÿë'æ“ËA‚ú@Âxö!ŒY£áýy7~å.{ôóLêîÆÚ*ý'›_90TÍ7g³äß¾í®®PRyŽïÜ'` wæÖÊu{½f”ÛuÆŸ"G&¢æ:ÖÖä<…%ôÉu[Úѵíð/Í)´Kq=r.,Ò†žðÝö?}£½Þê·%:8@~á¬?r ”µèõKÝÓ4ÀÍ¥n0€í]ë!†!F ‡9êM.žeÖÄ— ¹X6²<6iQ|åqs—É cÖcN2îÅ™ Z´÷…l[ZhD}dé=[ë°ÍXu=7´ÃÛçPK`Ì•š½~1 ¶Râ ÖÏ jg#ëˆÆ -*8ÖžÛªþéÝxÞ–yñù½þƒ§*¦»”ç[½±°§Pö)lä†õ7i?÷HRRØ:V…U_¿+ÿé_¤ýÌ:‰ŸhC®-T~¿ñÕgk¥û3Ëæà.Tt<7›eŒÚ>£¹ MñEìx( ­R@2j9–Mƒä#áø¸]Gz`ƒ®oRJrgˆÊLaJäEÞ÷SoÐ54/WE³SöbØeu5&Í®×’àN™º°ûÆZk35ˆžÖ³pÐØ£¹‚Ê?ŠðÀB¿6¹?ϦRÝ ‡"¼íPÿôA{amà•òç[Œu PÙ)pxÃÜøÏ=ñH˜Ä Z<-`dÞ (ŒïÉh³C<¸Û‚­,$’‚ :¬¿”üîìip¬ÀXÄ—fà÷^ƒß}aÀöž>¦»7Mÿò7.ö"d;¾ #¯³AEiG’píN¹Žäïß/´­ßzI|ç, Xw­½X(þ‡×ú·n;ÊûZ­K¿óJBYËi0€híZÜÀ¦†)Œv‡Êlï‘b0³QºËãq§v‹/¹c¸¯{‡[¶Å Œb[ÐAk­Vn7ä£Û‡^~„ïßÞÇFfâ¼À'âúdxãüÆT¹×¨è iÓÀÁš>Í\5V83ÔÚH¼~ÙصVYÚgâVOmÒhGI7m±YI†ªîÈôM(€/ ã]Š1,ŸNF°~Ào¬ÁÈëf]CB)¦eŸ´Ú¦Om¡÷9POÉœô,{”Ì,‰Ú ¤¸ú¿ý~«›Õ€µ×ibüü\V¾¡8P<ý4ìÑ¢Ý$õÈß”íõÁc(/j(jì‚ ­¿y³óîM/Î,BÈËŒe×—*ó¸õÒsµò ñõ%8¼×Õý!ËL7Õô’ÆC¾'@8äi„m$eÁʇÂÑbÍWTµ7SÄXæT¨TZÓ©ÏýMšóA½l¬.U¯Œ:Ù´ŠÂò.»•#sFmsx$[Y*wy·JäfŽ9PååZâú ñV€otüúî©VÇÉÔ®ýæÔþöù³åWß“-lp†  H‘ÝÐ#+ÞÅ?p¾ó;¶§ (Vú)Á– ×ßòvO{Ž)²Ù6æB¯×õÊ€d}† §ýÅÎ?ø/--}F4(‰c¡û¿¿ÿÓ >ê´Ÿx`¦RÂÿü'ôB§:æ„(Ýë§ålƒiÚk±êÈ(…ü­K…åÕ­ß}1ÿ…§‚R²…f»Výý·Ú®JLS”0¶ÿàÕžï§:…„(ÍÛк´;¥-¬Dî4Ê7¯ª“ý¼x ¯°”¼”kE¦MGCT„Ò“Ü:½xmÚVùæYzpGà¼-°ÊR‹÷–oÎ1ä;†ƒŒ3`½Ô)nØr.RfeÐcÃݾRÞ†Ée6LÓ6÷è“`¤ohOÕòÜ'…J7°X„Í";˜vG’ZŒÛ»ÑÆ=2pQ7$² «¹ˆ°íØžÇpVÊ/¡ÒZ ¡Ì>ÆïϺêpÖÇõÿ‡N:èXc÷­†7¾Ÿ\u¦OEccÐo´üBÝÆ´§€¦V ²©4Ÿ¿×þìM³|§Ûe=˜YS楈; f ¯ýÜn?оû„©Ñ—z”øÂÉØ0MpŸå ¸®¹+]eÙ®µ|E@¢”{1 êïv²!Ê'Êr{¶é…´×!†O‚À™cõA¾3ŸÛ~¼ RY9*ƒÄ£0=¢ós½A«YŸ3ÈÁÅHƒ#4ñÐCØî?Ócu¬±ªWVScÑòœY#ÝÕxµßHbCHAå90G«f°MJ„–¤BEÂ[Aü]äv—èÀ]ý³ÙÍ_«=¶;(pHf„°# ô±M"…ÇGkQ¥“¦YcPæç™c$¸~Cý›~ãï|Ûã”ÙíÿöÎÅ5Nûp$ÐÓÊ/ª¼AûÖ¡á6škFßHã+©ÿ{ïÒñÒ X™w5ø?ÿ*¾p·T C|“A{h Â0Œ;þÊJ È2È ÖÍHãöV¶¥Œ}qܽ}XUò/õ]€é¤º‰ÒAÏ/iºj¤®f6鸷ÖÛü/ï¡J Ö†ykrpö?YmK±Â{§»ìBð—6™v€{Ö¥Ò1 InÐ2Ì+ü ¾ØêöR©2·ò~¼Ü&…΂(ÃÖ³†)l’Ú8º!IZA¹X_ư!üU-órÍe­;9™ƒ‡`„ŒxnM•©îû.JU ÈÕs×Ð@ã.>|Âì&ù^qþr@1Ë`SšZ¦HÍq/ªûé9yóœ›Ü?tæ²½moÅ‹}«Çü‰L4–ó± ?%÷®tÛØZ >³kÊe¢ZôU[ž-¾þs7ùúÁSd´nî\Ôl Ø*à^æ ¢‘.¢KØ’}ëé]-•ºŒnx~õýTŽ2Òu½^ h·C”o˜¶ç9(ˆA½‹æÎÙY ºÚEø‰sÝ,+òîÔ>UP†n²bÚÕD1¸²´N%Bè,xûOä´P°ÌT+ËË›ÐÒ¬Û”ÃÍõÞr¿õ ¡Ê”cª¦Òªt}¤rÃ@z±™'äaÛJ00#Þ[7ž®?¶ËŒV£Î{Mƒ™cÈÄEŒGG«…j7Mó­u0)–Pô\ÿöõÒÿÐíü—EÔ4ù?ÞI/¬ÉfP³×ú•o°ž‡ªåØO ºë››ÈÜË{7×éÿñ.üӗʽû™0ÿù'í/o8fÊøÜ­‡ÔíØŽ?ì÷ª«kyf!…PXÞŸí˜SQ¥/.Á­w¶Îä ªìZ—s•O*!ÜÄi´,XDÿ,ýç—¦ç}Øyþ®p_wzb=•««ªsŽèˆndL"%{‚dY¶gä=3ggŽÏzwÆ;»ë9»¶g=öʲ%*“@€H$rnt£s¨\]9<ñÎWÞ³ÿÂ÷|Þ‰¬ ›ƒ6\¶Ùëþè-Ro°¡‘¡Aws²fü v?RªžEÇåµ+ø/)LI0)ØB– roìè ÐIýi»—g܃Jˆ+ó'óL”È ÇçŒz„Rë)ŽpÇÝêp]ÅMÛœ“älAÙ4,cÛ¼›•æAc€î(.š²îª8Ë\­3!—›È –¦ùÉsîÀÎôçøsWŒ±,³›•ó{ÐqDªàÚ'jê#½÷Øð¹–ç1rKÏQŒJ\¬(kÿÃßnnjgOÆÝë9¸óá£êÀ íÈÞRÑéL•S€+­Úç7ëÏ]Xý‹7—?› ø¾²}.†›)× j×9XXcêpG ð’™MŠ› ìß¾»üÇ_…÷ß™èòöo=¡¨ôj;š'êß«Lm¢Ë³ð«åe!*€¸ T2gñ±ÍÊõµpáòúÄ=÷Y…öÿ·(”¥ÒQYx“ÀhŽŠXÀJû˜Kæ¾¶^»¹”+Ôö Í«ÖúÞj¿ãýók›„‡I†P*°Öšöiº¹eï,h›ùB7]†-ïyL?"1¹%¸úyQAÆœ‘‚ZpÁRQPÜ ¯¹*`ÛitmNi{w úëÐêÕ–ŠN¤óž·a£zãF‡ŽÖ±_ž{³Ý–Þ`û—ìAÄtÃq‰Û6B`À_㼄*xC¥äWÓ훳ªª ·›©&V)¾•ñïÿzmÓ8cNŠª*¡Ì"l'.0ƒê–óÜt¯5–ï¦ßø­"“qF]™2)‚ºË ÇíéNF ð<¸ 800ä‘Íu–Ì©ò¦,ÕEsØ(MÊ€: €ñ‰"(/sDz…îá£ìG®yÓU†“ ™í›³SÌïOækjTcˆt@mj±BÈ|·4÷NºµÙ·Ô^hëx;mD½,d"“›®-nßpuÛ—ËTG ܵ’ZKæXWEpÕÚ7©¶’—RýßÒêc¹Ûz9y{_>q®á6S°¥)"”EF®­n=9¸ûü9uh€n;ÝÕÎJsz0£ùu¸yyç³ÎýìÝæ§ó  ØWÁ_Š $õt`8Œi`s `Ñ'Ç85—ȃn,†þAô/àW?ª¶ ö[K¦ãpggo­2è£ùVé[úÞê–ßdš,çÙ,ðSëÞ͵ðÁË“S•ça¢›&yfAzðˆ€/"ð%_å…eq—¡uêDÂaa¶±Ùwg5“·6+”õ¤Wéó«tu‡‡†ËƒËm"C¬s IŸ€¢i[M|{θ™—MwÍ´Q˜{.€c¾ lð9ïøµj^(JàXÊ™@€ ÷q-nu,l± µ»j÷2w±›*lÛxƒq£;|­S P‘EÓó!–þ\Ôs6k?ü ¶Ô#:a™‰¬^ȶPÙ’@¡ Psüí_ßí\¿Í]ß®b 1¾€°äQ†EHM³›«]ÓcÔ¡ˆ*¤VA€]* €/•œ;«íŠ€êÏCIS¬vhHJí)}ñÚ7”Õ¡J[€w$Ü…¾ñЦ0q°UåÂÊK9ßz¤4Œz¡—¶r:Ó ~uÙ^›íY¨ið0Y§Æ3¶) +ÔÁä̾ڃE»Æ[„V8†XF€êb.4ï‡ZíARÙíq"H7Q9  ßR`Ìõ岬èe˜ê˜M‡PЍ¥@†úL>Rlôg·“~@+ØZJŠ#ìÔ¨ƒmzdûÒywÿpZc:‘åHWñnòëRä: . ›Óš£ì}ÉZáüÿ=w}Ø“¸Ÿæ‡V²Â}ÔúO€^‡˜^Z.Š-rЖÖqò'TKå"Ë™E¬ò,PéY-°oú÷ô>4éѱAÛØ¥*þÅŸÀF 8ýðË*õ4i£µv‘ÿ+”Ý&6äeKé¡dÇudzZ{¾ì¥=ã©\×\xîi˜]•W®{>ìñž{¸˜Ü C:ŒtºnÒÔ†˜?þ?²ùî|/Âp¶±ùبë.|˺ÆÈWžTð4uû%Þù†§î®‡øÿò½0¬¥ªîU¢¢Q£Ý²sÿVþö§ðá4$·}ãµ×ÞŠÚyz9ƒü;ºœÐ¸fÁ(¯P¼ÊÿÁQp¶Ãh¿¯ˆ0Ó©fd@blí«Ì».RL¥ÿì÷!´Áò^_µ«yúÙ2[í È€ZO‘0€ö±Í­¥€´uìwR‘@x$­t=™oy…õרût®CÒ—‰¶.cô[®›@:¾/[ ¤ª)«ž~ˆ}é,rÇ5Í"Zî ½ü~v™çÒÃ` ÊPƒxxÀ˜Ó“õíV±ÅÚñE±ÌÀp€"Ф–5¨HùñU–g*fš ´šØ¥çkAk½“l…ÖÅJʨ›k”E®#ìŽ0ÔE&‘yl¼òÅgŠJ5½{jŠ¥ÕDú´,tÓuvRýÓo“ƒ•œi•e&È‹ëØSu‰¸·žpôÕ4 ;R´Wi…BP¶Ðú¯´dt[(c¨õ¡í¥Ôˆ0^!øÒm°7ÀZk™[°ýòÉ€gõ8§XSF•.쉵'N¡ÉJá ecúãü¢Œ U}™Þ«Ì*ŸSóÛ…Ä÷`ÀUk¯úºÎ>DzWJK}O­1ôü1ïžÎÚNᶩεâ[wÐæ§ÔoýZÉÍ¢Á€¼zÅý¸Uø*,u!¤‹›òç/îøá•èVË*:<ÔˆÿoߥONæ­^xÃ(Ãu.´“«û,ü™‰ 8•Ï’Œ5¨_…sZ½îˆY}ˆUµRj«d4ñTä}ó(ÂÅÈß½ {DwÛ}ÖR‡d}‚‚ÉRõ©Cdµe$ö¤á`á²UPÜ ¡R àÜat‰Â¶â@"4˵0÷ºð U’¸$ä8G,”BR‡kxø¡ä‘s>íy÷:‘§ùh¥‘ûe®S0bسyÉ ©fGG“ßûf0ÓÍãm­p‰ߨ|çNò{ß`½f,ÚÊÑÌdÛÍ@ ˆË¤™(—u‘JlÏVðóO›z:3…«„&Öd‚RO2¹Ýœžüäp=u•Í2ª¢ôŽì)»¬˜Úȸv(ßÖsœRƒÆÞ¯´Ä!Ržc¡)ôÛ¬ô€ ¦•LjØ6-eHïæE‚O}lDLôç,`p2ÐçO;yRs Öw¨Ö\ŸxâD~á„ÙQÉ¥ q~ò^—°¡ªZ¨#f­ú¨÷Ô’hãPZQ=íÖÞ€ô2Nù0êCm•Æ`áËÇüø…üì~xštTu¾_¿AÖ—RC»%Ÿ¦Åp¿ñYù£­”J÷4Ñ“w‰)•¾æ¢HÙeTY%ô˜Ò»ˆŽ)q­ Jg>Ô@?z!® ßÌo›_¼<öÃ÷{w;Àaçè€ü‹<¹3é¦ÞÕ\ƒÂ¹ˆÍ¡§]ÿǺ˜µÀ¼zÊ;BJ¨ºòXxÓÓwµ®XÔxZóõ’±”‰ØùÆ3BÕÈßµ“Øtz…µÔsV~HJ£¥ÊãÇ͖έƒcÝG,XRK¥/ÕÐ{>ǦeX0”ÜGa_Áë@ ä!å£7(YFÈ áB_¤bA}ß+¾|ŠÿÖ“ÁwËöraEà@Ÿ÷Ðáîæ¦n¶Ž{.ó*K”0ˆJ@çOÄ]¤¨ëO·S¢ä°_*„!aYÚ”d@1Ç4¨*ÿÐx÷û_¶½±%=·Dµ,\¢6Ô~—.>¨¾v¥x0%tÔfyWFp)°d{ÊÎ#OÇv÷ú^ym,±ŠH"Ž'ò<ä×ÿ{/ÔŸï)H@5¯*½ï–ðæógðÔ‚ù|Ã%U¥]0J@¢eÂ*¥5¢Šà#™xZÀRl§T:%áÅÙJn`Ä…5Äq±ÂZŠ=„¿ÿTï;nïÁ&½z‡Þ\p—¶F¯Ío^²®ˆž=âÖL  R¶!R!ónSH Æ›"6pÁ扄îvÖ¢”à²F釢}²ÜÅmê÷+Ñ4@Ö[êÁ\-’ Z]0i Ã&¶ŸÍÕ?šÓ§¿y$üåÝuÐlÐ-ŽK|ÓG‹\ÕZ±—˜%àK˜ò ÎtÛI'½ã䑲oL;éï¥Í_¿7|íª, ŠJ´LT\ļi×fëyë­È jg;üú'¢£lUõÍn—•Á&RQXu¨M‰ !‹B¯’G Á*εmu=3\—}ÊóÂR&<´g¼±zjoñÐa9> Îø‘DHY—am(7‚ÀØ£ËX~"S@%€%¡f±Ø‰a× ðÀø€i!$1áNàû<¥{ó¯=TÔT– @µÂ:+øvV.Á Oí˜YWKq«@©ã‚ÎSêRu(oïÞbbTíŸ/½ÿfºÞiõ¹A ê÷=¦\©{‡w±G/ù‡wHGB§ç– ‘Pp …^Çpå?ø-º¸XýéGÑʬѽꈫzº ‡%q¶»ì\|Â;wWúýŸÿ,“`4"FÕ,t%‰R Òw¿ÒGÕz$! Zµ^ÜtèÖsçÉü‚ùtŵÔKºHÛKíR_7`YDr>E Pè8䃜?°ÓŒÖ(jC‰0+¡©Ë ÏG¿ÿxò›O«¥¦¾vßXt7û¯>è]ãŒõN¥uë+ˆ@h°¦†úAR€0 oSÏEϱJÖØæ…ÖãÈruÄ/™¼£‰&Àë-±4W„­.(T"°Eí»óµ÷æðécñ·.:Ô«¿w³ ¢4覧¤sÛ· ¹nhX­—Ú`:¡$ó¾69t±sᤠW™^Pþ»‹ù³²ÑI×^|wô³«ÂÀƒ„ºGE"’Ýbm¶?+­ÄXEРÒÊZý•þ“ž¡¾Õþ›yÇi´ íÀºãB†D²„ ëºå\€%…Ú1ͤøàŠúè2¬“•èþÑÒâÅ3êØÞxbD# —§|€­ Ê ƒƒÝ0,T“ªOx*-P %€Í\΀3â˜p4ÅLÙ€P…´bR²íUJ…pwW“oœßn¦;C}ë¤×Óq‡ºðÝçwͯ‰$K¹Ì‰6'>Æf» åîIgø[½ý w~¯÷Ò†kS.©rëõT ÔÖ¾ üÕKå“9ÎD/bÆáy‘PL]ž g\¦ºzýU¯­]8íŸ>âýê8‰¥‡ àZ|ñ99FW¯dŸÜö~>õ`sˆØ:Eu~ì`Þ(K™òšójᲩí(ö=ÚHóVÝÇžºù‹fÑ“Pš5[C0¬šb CÓ‚çX[Ø`‚¥g@/"ù5±#÷ 3PªA9`Ešè@6Y¹>˜‰.<þæ—{‹fïoÃå©þ;ÓÅËò×?V‡*Ì"Ÿ"ƒeìC¥ÆÅ†'2žTR@žqD@TÁÉK 8§ •¼íL¤qá—eÞf€ ©|¸Ô™y‘snRK±.qƒE¿îÕvdŒÐ¸v`S '¸ˆ²Ðà Þw½+Ú”r@€±‹…ѾD‹…¹Gð0¡ QƲB¡¡kyÚåy g`ðÆÁ‡po+¼Ÿé¢]F€#ìýŸ~±íyÐì%%¢ ͤZ•=5Ðî£ ï ‹UQ2ÕR(Ò.»´èhQOQÉ3꺓?ý‰œïðChýëµ÷7:;'aå^õê¯óîžÒÄ® ×…¤Ò7D[XÒùŠBî-`;Ø•(O,¸a nsHM¯g`?@U¦î©,QÄ:O=4ÐO»Ì¨êÀÍwât)?ëŽï¥)o 5º‡÷%«×À¥Ö ˆ%!.O»äƒ¿Ã]üæÓþÍ5óágšhÁE¹ñ=þÍ“EK¯vâ±Ê©'ÃRi½³ Ãñ’´s4xûõ¼9?ûÈ90§üW_IóÔxX9P /Ò“;Ðò§ÉkלG¿Õc ÌN‘, ¨”Cšˆ©üèV_ʘ࠼ußYø´¨L¦Çî+T»âÚÇN~¾Ü,RC} 9–Øe•n p¬!@É„c D´ð˜9U¼Œ‚ÜŠÑŒïH…Ѱֆk¨-N7® ,ί;ïýæó­…•ôÞ&þlÊ»;Å^ú°÷ê'Åá²Èw±¶EB¥–'-ßä¡Â•噲¤.8ÖC:r3E¼óA¤ÊGËé•ä*5 ™Ra ¿Šõ­¡A\vL§ 6ØŠ,Âú±­J9*áÆ®jQʱcbA ­79ÌztÐó9g0Ý.PÔn¢¡Ï];uºœ4û§e3Ý@YÇÒÿþåMσf‡ÜG„R¢•„¾Œä8èvÅQÌ„TE`JR óHµ”d b#k„P#E—8¡2ô?ýÔÌvâ a*{÷{—v ÍŒŒØ•…ð“·’îþòÄþLÛE`5a©2z Ô’A.Ð{VHLˆ"¼«b¾¼+ljEaÅ~€#€@ƒ2`"˜6QÀ/©ì(‰¥´ ¬rõƒ<™©ï<üÝ‚*Qõ»Çt–>KË8+0T,´}ߤƒ´kßý)+ëÖwžñînû]1TfPªÈg¿À\¡µÚÙžx4p+Ûv (¡TMÀ·Ø^¾-ïÞÈOù#÷^k]øûüï|è~t%8´‡~é ÉÉáÁŸþ›Eœ 3»qÿ ìS²Q(,°ÑåŽÈ,H§Œðîõ„Í $wú¥ö¤ï6‡ÃáSû]žY§Y*}㛞ébÂsDc=•m„}À9ÁSÄn¡Þ»&ÉB€ÝÔ“Š(€2"`- `em`éW›“Mÿ8cdp`$+ç_ß×ífj**½~§XºÑá@”pîå©$g ØáÒÛ2€ f'H}²­ÿ’mW•ïH[+¯e‘K¨€ÈÁ‘Ö󼂾s®_Œ•y0¢\ï mž”qÂõÖXÏ, €Ál(&iM'_±ì}L¦QÊ åic%ä†ÂðÚ"£µÁܽ6KŠž| »w•ʺV­÷HŒŠlS¯vñgM¸¿…Z¥%FÀT”Ä.2OÔl‹ušÌÔcø~w¨‡ô+¨Ùôù˜2ç < bƒxêZ:Z¸@¢­:î=vÂ;åwýR7-H°9Ìþ,Ú©ñâbJê;¼p™Æ: $2Zhºþ6çaíbÁ©u5ò4Ž3˜€Ág`qa$“žBvD­„DAHÍNÍlg ޳­™WXé{Õ¡A€„¬}`º©À‚å€((”«$Luú ánçK´þþµãø©õWÞ¬-ÌËGÎñ'ywðÿØ:Cmnæý”rOXᓈÈZ(çê=}÷z¼O ÞmëÒüÓÔ{ç#öáeÿà.ôì“ÉCcƒ?ÿ_—q:Ü'6–~éWG’͑Ępâ@œG ý*†ƒÕ’-R"»[øÞKñ1§¸²Ý?ÐßTø£&ÇŽÉœ\XKno+ƒ'Çù'ƒ.+3Z¿»X¹û7Í]?XŠýê(ó×܈† @ƒË°møD6C6@Æ‘$¦,8ÈÑq:#ëÐÎ}î9ŽB$bƒY‚]&Œ™ãËF£§Ü ÉÖLwëÝÊA¼6õózõ÷‚ éîªJL&] ¤e H9p“ú¢1÷–ZÁðü;¿ý_íóddXè#Ù)\Šá<6TøÔJTPAkE'q+ÐÑ´LàAM„.cØR® $H ŽÅHK#€:F„ 4îäLƒW»$PR@È‚KÝB lH ;'a5EQ K–v8x¢gA†¶ÐVK„ŒqÁ…I)T±³FpŒ à´‘³L@@U캚ƒæ¨ …A 2@Ä¢”W™’˜´(È* Bœí¬ *kXË5æÈ€RÂZk)R@ÀaŽ2`ŒÒa `0Ò`Á#ƒ€’™#pÑ\vÒ2mµ+3­rå8 ¥Œh !ˆAP…˜¶9è Œ@@fMì Æ±ÁÄçœ@˜J FOÆÊxem‚]D´AL`¡ÈL­A´•®ÏL–EH #k$0K‘EÔP ®A\@ØŒX[d¤C]$’È©’¼RœÊ 3@í—a»!Ê)á,@ d@KßH X¹t[œ•hЕ™Gac*`?xm=$WhM·–7†þ·?ß̲ž¹«}Aàþû²à®^ä´@439• ¥Á¥–»lt+N{1 ÛáBk¾ý뜪€»©‹Õ„W‚Qê ’K­€ðÜŒ oà/‡K³éѳNßÞõ™9¸· ŸÜ·ó«F£U p áÙÃ"‡\W“]vÔ=È<bŒšP¼Š{&UÅ©²ê^ŸcZêP©zXêÈ£0Ê‹bÐuVø­¹  ÀT{ìdØ(ª¥Íož€¡!Tѕ°„mU,üŒ‰¶R®@D¹Ñʬ5žwU—Àof°Kt»Qq–+êî–xéDi#é:ó°¥;L$®zº°¥8FUOø9N,°‰y_Ä÷«”ÄÊ*œ"û¯ÊPÀàõz‡d›vK§EüÂD˜)¼Áþì~÷òý. wÏh÷Ò^z¸¿³güŽýJºo¼><žÄ¯ZÄÅ<'0Pˆ|Èy¯rÇdÛ9¢€´@‚¶Ô=¬ø. ©… ­´îB€f†càK7˥Ѩ­ŒMîX¿¸µ½€žE!Éd ÈæçP•D| Pa±±oæ=ðá•;’‚1Tccò$šþ8t¡SØÎž 4W–Ú‚"(Þ¨,ZFyrê@, C°cŒÐT!PPäè2ÝäÙôèN–¡9×yh-êšYæƒXSÅJš y*5E$Rß©ÏÎ¥ñ 2TO>ÎÜ4;ð®ƒYo¡V†¬=:¼E ¨™8´(ø.€ªã”¬]½ËÔç–2ÄHÊ"ª Òìˆ' ΀'¢Ç€yÅ,l£?Ï–æ£ãgüÆîdf¾¸½…>œræ6rÀk`áXÍo¶A1(4j95Vô.3yÅH¤=‡8MÈÞ!ñ;nìð@  ¸]òó$þ*TB*s Q¨’¦ñPCÏo蛋4PÖ&Ä,›>¿ÜǺϜåãްÛvg„çªÒYü¢ m-K ( -«Á æ¾eÉw&¹…Ç Úð˃w›³¿¸fÓÞ(Óyc²<Ö"Ä˨º°S‚kÄ…‚ºçÛÂ~(ãé Dƒ¡àÀŸÛPáÖM-þHdÛü^]·®lÇÅT8Ú 7æzÏÇ ðîÉìÒ^8>܇#ß®~ÚÛ7948šÇ]%¬c‚K§y2äB£Pº©³uƒ Œ 2€=z¬Ø<(2¤Ÿ ÜwÝP%2.È‚‚ÛÙTáXÊ3›Ü¹ýÅÅÎtß0A‰¦Xž&ÒÈUË’ÂX¥5]Ï[šÁ«w «IÏÒ"³Ô<ˆ3X?XršKÛåJ«†ƒ ™mÍ”)nÔ˜PXƒ•Ýþ|fpé ÛýQb1«´“ˆC‚\lØ›,ŠÁưã$eæñÜô‘¡xYvLSßZ£×²po‡šž9$Oïv"È »6ìCj*¯|@Ý>š5µH)Œ#îÉ<× D£[š¸ˆP¸1R`£S¶@ÖÁÌCBÄ:`sê‡DÉäå£Èùð¿úŠxЪSã5üÌI|î€ëkÿÿCYâP(©\agH›ic2l<ê{Ö:Î3¨1ðr‡aâ-ŒP•êN»F‡c´¡MúÄ>÷žˆ¸ùïþjm»p\¤òÌÝÖ¢d|ôB?ö›!*Wû£í®³„q ÑÕGR¨ƒ}à¡û\ °€"}Ä%;3Ó!¨°®ÅkDfJôE>AT.•§o’6„‹K¤H¬ßÏàþÞ@ŸÿÍëw¦#m Fœdø}k²iYxaÚ)À5PFaI…§a‘ÜcýEî9P€öÀü7ߪ ®N‰_]ƒ9ü7Ë0ÑHÞS:{.ëG "ß-%@eÖ%B‚Õ`+íÃ:ƒ¨ Ð+F%)á&Üü¤ò5a>1ZÇ‘TVqŠXj±W£Ù–zåÓèìÑê°×‹Ú+'Ï:þ%ê9V¥nÔý.½±Â{*ñ˜C…Æå dÓ3¬i»à¼jé¶‚}2›©–—ebš©–|Oð~/¶k=öŽƒˆ**Œ”XiVè¢(5ú²Ù9”áÂÁkƒ•¾"N6²­WõǔÔh°CмÝ(Q^õÃTc?ÀÙõ"Ò.M²ôÞ*žéýVtâ˜8x„‰4'ÑÚ€‰ª½öÙvVhÚJ@)ÆÀ‘²”A†ý©$;p–A1@iÐq¡©å‚* — Ás1¢ §{ŽÆþÀÈ'S[—_st%ñx²ŠŸ=KO` þèßõ‡¢F‘[êõ)RùÄ«íéȤPs³„……ˆgF}VŽš~©QÈ@ôØnúÇ_m%òŸýÍöZâzÔ&y±‘SáÄC¹ x êz¾˜®¬Ô–¦íࣅXòÈm­¥ÀàºËµûsÛ!¤ØƒcõÖD™Ö‚­HÛÀ»{«•ˆbHÁéwÓÿù{}µÐüÛ×ò·¦b£eÃ…b Êõ탵”5X‘…A±Xtj‘4)ÖÌBQŽI 3`ÀAEþÑwK`õÛ³Ù{—íÆœÿ·KÁ •ZðO!Ã…U=U2JH†P®,ìrË»‘¤E²­ÍеXp@¤ GprÌ`C ¡Û1"Á@;´êñ^þòÇí3ÇüÑ o5OžöÂ÷3ƒæºÎÝ%ëÌ÷]§àƒN)ô!Kvk\”1Þ°[dó¡«$ê·|s3Á¡Ï˜”ãõ®ZJ¸îß!óžåL2B¿v°o÷¤7dÒiáý¿g.àïýÎÀ>ØÎŠêªQmÕï9íõ¹ž®yw§ðêüÒÐhm7#‰µÄŠuqm`H“.îGìÉI2Û–qáß Š3ìôX…–ê!9ȉµzʵ»2}ƒØX/Ÿ(J| Ùc£áX?€ß~2þÒÑâ×—K/¤Î)mºÕ´äÉÁJèa-m›õšëtóö©°üA—Mëpuxº—J ’˜a- [~Þg`’“‰%01àqšÕ|õÍ“ö[§Øõ&yùºûέÎRdW/·~r™ ÖÔ±]$I >`¤ÁºKca4$À~êö•JK†OÉT(³×ª–¥¶M€sâ@M‚H%@ÅV ŸŠíO.{_?c«%ÍÌ&æ¼»½AzÙBKóDïö3–cå–\žæ˜s¨^yGy}qvh¢¼_§ÌÃÊÇ/)q°¿DÐö²üýé–Cå7/y;ËÀÍŽ© 阘  ÷6Mù_ßOAÁ÷ÿ^ßxÐ6ñÈÙÊèá½ÞšŸñüRùÁT{t¬*ÖZ™òLVà< BH†ýJÈ#åªvêþõôކ˜¬ûÃýÞðÞd$ð¼¶ùÅgνˆ(Õ €¥ÊA ±0*À¤ÀZs(” ÏZ´Nœ›R€ñìV((²` 6*`Ö¥º( @¶àò/ß+ßY›Ñº°ŽotqqÿðWϬï÷€ò¶Uq^X‚-$è%©%ã÷;°AóÉ0=%‹Tn¿ì7ÞË—R Ï8.š…㘤 “š,•6RÇA%¢?Ïóq§tü <{au´Át‡hqa¢rõnÔ+èM_ÍÑ„ïÕ³}汃‚ìLãb<ç§.0¼¸ã@'Iíù=x3ßs÷éÕNÀ»|²ÒYŠ pk¸”ºÕ¬âñªãaʵŽÅZÙAí´sÎ-¿ÇZ'K¥(Öɱ*#1æ¶+\ û3ƒÜ´ `ÖÁŠÞòôïƒ?<^ý´½r“½y­·!à'—{?½ì „üØÞr’ÖPÀ ¡£˜k ©&h;wMªiY(i÷[/™Ä©H\Ó”ck°BŨ˜I½Ÿ|Ò÷zå’U"XȶWéV=hŠÕM-c½Û•TpË´ˆSA“LŠò ╉p{u~t"ܳ;©)Sâ1Ÿóƒý!ƒö½Èÿ?É©Ð_;ïÆÝ¬6»’áû¹àdìÿO/gËÑP‚‚{ît693¯§^«>Q¡_<‹˜G?¿™TS÷ÉÇ*ß}A÷í(&v’á]UEŒKåjn‰ *D…ØÆye+ö¦–{æ*wo÷׋–b¿¼š½vUPâ‡:lÅÐ ”G é1à€dZ¹Ú+¾jYBì]«\BNsvB8T¥l4iì ‰\¥š1JI­æ7Ý®°Ä29«¨(I»1,w*Eá9ªýøÃ%‚i|À+Mº0,ô¸6;†Ù+Ö™ e9Fê Æî×ê„%–/3Ãhi ×áê–ܶµ/góK¤j[Ï6ß~^>ñ8ÙésÑÃݲ)D>^|ëz‘¡=8$ ¡6·µJ°ý2f“ÏhÉ #: qú=ZBº$øÇÏ3 íÔ÷|®Æ;µ#;Ú,…í´•˜©m>Û­¿õ™H”ëºÚóõ~l Ñä9UÙoEØ÷ˆ¬›r×+X=‡Ü“âzfdÃõÖ aµëS_<-…¬Þ|¼±@oÏônoä9µ6'©qà‰1s«5¥SІRb9N¿õ–@c¥À´žŽj)cáiâ|Së OÖ0Ç*Å9ð%lšÚ€]fªªÏ…XSÿöB¼ÑÉ#î¿þQòá;öîýêõn3ªŠÜíŠÀ©+'í#Î|è|ãÄQrêÿÞWˆBsªˆë)÷¹Ã%7^x?ÛžMí„7o¼ÌlX`ƒNçäCpí5sûíVr?ígü@þgoˆ•îV²@ÞųÙT'yð–†Õ`ÿH~éxTï«}òY¯–ÊÇ­~÷=¼«›`C“eä ×áK‰u5$Öç¸U¦W{Ës}wn%S›j3§¯\ÍÞ¸VX U£Bè3(r8+¤jÂ@B$ŪD€!xDHaåMk¨ñö¨äâV[C¼—à~ëH]¡0ÉÑÓ[A¬±1ƇI¶¡lâ8Ê"2—Š<|ì±øói%‚h<á±} H»Óè Ø=Œè ˶T¹Ëàk&A'¬ùš Ö —¡PP熭·Šu¼üy6·¨«6ùÂ^òí¯çÏœgã¡æZåÌãbpT_þ¼ÚÕFzê `5CÚØÞÖ¼‡ÕW˜Ý¡ù pjì8f}µ@}JaS» ã?zÎ5¨›V´—ÂX#¹;ôÒ‰©·²Íû©Öãêõ·Ù̆6Úl·Nž–7ß°7ßêïÕ–í僣/½Í tú‘Ù\Kw©ß{;:¸âQw‰çÕcîi¯/ ‚´%ùéÃe2¿iËiþ³µGwfž¡31^ß#8$LXÓܱEYÑé6~0_iÅ!ðu2è:³*,hlðØã.3KLŠÎêxÑO+ÐV¡ê‘°ï¨Ÿ@å=¥æº[I…$躃©ÅÖHä¡?ºD/Î÷Öýë>–z|»ãooW6“·o‹—ná«÷ÄF3,#ÈÖL~N(åXÀPUºbDjì‚ØCCZ=ªœg †^¶Ozf¤X²«]ÒDÅ…1dfÁÄ-ûÌéþo_r¿x2Œsüù\~í¹µ4ôƒ·äáÉãÝV\žê’Nn6};!UICáØóƪµGë‘ʉ,ÿy ÍäÔÁÓùŸ´¯}èÿù›ªÛ¿9—­t£!ð=:ºo"}ïÆäþ¢ -„Ö"8Pw}«Ñ.¢ ‹'ð°#‹ÛXnº(”ꔄ= ¤@`…ú±p9í¿\ìë7íº%Ðbg·‡Û-ue=yç®üÅMtuFnµ+e° èM-/•QãèWÚ5"Õ°Ž! ì°’§ïÀ#FË­Cüøsx–Oª2l5@0½˜eûÔñÑïy½þ þÁýÛIéúƒÞb‡Ôôøáþ};V¾q·9õ RÖAØ#úep°êìÿÍN¹m´Ã Eq‹¨Mj¬/æ0I¥¶Æ£À)„…ù¹,¤ÁÖv2ïö¼üÙÇþ›7’{ Q«£›É@=ð†ËѱQ~q·óôq8¿#¸Ù´VHdÁb8-Ml«ßÝ÷\80æãr=Пwù¦c,ñJ@4âFU9AƒwKß–j€;HYÙçT*VM\F’YyÀ4óÀÐ å˜ÚŠô'[®š‘8Lÿ__<Çûù½žÛ#cûU%ôÞø¤·±å´0l¬Vöן½¾:¹\ìÈÃÙD²áêÛ¯ÆÈI»[mox¤’-$;Ò ½k{»û?ý •Öô°ëoÝÀ{Æ;‹2ÖM30ôë›ù­™öˆß„˜žIzMïÓ7ÒõJ®ò÷iç©gàÎ}Ö^MÀc'Ç{s dFT®ÏGÝV·YÁÓ w<š[ „¹<í•Ê „µ ´!Ì” “Ê‘¡rËV‡ÕÁè+.  È/©ƒ§m¥) . ¡îVŽ8†Æ" ÃD™:O§¦ð‰Cƒ,í>è[myÛÆí.FkÍ$Ž¡åèL@ªÏƒ¼€ò]-3 `v¾%qÁÑŽ ÜÈ’(9ð\øØ1\—^•{ë}®e´)ËÃà[è­ßù:[ ¤›Œ¬pÍÚùãðì#ƒ¢£þ³'E“w§ØLÁÿ60Ç)9”“~›Ú7ÖŽ£"4øÓ²¹©`1C`œKÃöïI3zü‘ûQñwWÀµ’‰ˆ³Tï? CþÚF¸²ñ‚jëä€Üù\pmœ¼ùÖò~×ùmꯤÖ'^?3¹TRšºuq¶p:æØ5nb« e÷'»ûØÀx_à‰ñ¾ÌÚ­ 2¸ÑdÈF‡w˹ëEVh€4”0õŠP†îžI³<¦YÏîoä1Æå³¨Ò¢½DtR[Ýï54jcn™IçIR-ÑŠÔ Oº…)·‚ î*î«ìv{vš;Kå?“…èönÿ‰“ùÕ75ºå:ÚýlCT^Ð 3DT©»°Ö}ås§±sdiy«B°^zï6í>£5ÊÄß½Û|öTiêÍHì>äþì£f¦ KaÚú°ñæ»oë­‘¶ÈÈÞÊ+7ïÍCà 1JgæQ{›}ö~^_¬æ&{×i}ñY¸ßçó)³pî’|Oü`®3Ÿ—nÏdÑô±4ºÂCAR…ÁqK]U=7"<祈6Æ E‹² †Ap¾dMÚÇ®7FO\åvÏõ…)Ô]M L@f `Ðvºþ¡súþ¼wì@0܇‹î""cËÖ㺽Ï´Ó$‡ _‰$`]àÈóµÍl‘#ØKðršÜNT¢—¾AÓCÏ|}_­Êz¯ŽEƒÍpË‘PA44üqçþ‡y{2‘ª ÖBž<Ï=ÛNôýGJ›ôÍ)³˜ÃÏB8Iè1îT·U™XF‘S |=…a©Pœ³ƒÑ·ž`›=qþ ÿn²ñòePˆ1 ¡DÒÙ®PßÃ#°¾@ -ÀA}¢µòÖ™ìû’wmœ¾÷þò1D¾ízk‰õ¨;‰Ldµ0vH¸Úe-’÷¹$åzKƒ.+‚áÔHÒßG*ýe:Z±˜n»Á@'D±uìš»ÖÍ P²ÄGºƒbÒ_Û=¢*.NnöXw<ã #4<‹P„;©J#äå¨áT%åZ+@* ^Æ·J~­,86“ .;u´dƒ“êØþÚ„ÓÝ»¦ÖëóÛ éÝô‹gÔÕ×µ½Aì_ÞOÎBl3ÕÇYV·RuÈÙ‡ÛQ#öv5*#Ñ[¿Œ€Â*—ÛžÅVîí÷’V>Üâ>¸É¨Änõ?ýMVµœ øC'],eÒ*ßC^8ë¸;l5„,-D˜„Iž 9A5³L< ÅÎ%U“_)zRŽOªÃ´y#ÞEËIPS®Íû”[4hûþ:3í¢Œéƒ k±ïh©KûC¼Â¦ÜÛ¼Nb<«‰PãÅÙÁüÔn7ìo<Ø æ{=„©Å 9Ý…MŽÈºË p˜.H ú!·¤”{éóߨ:¦PQ0=ωîÇ‹F+§¤LIÌÛËi3±…c=ŒrƒáÒ±ð¿úRÙn¥ÞˆÊrvzW²´×dåj‘»7pÞtaSÖ7Px;H^7æ~æ¶•‚ 83¢þñW j=wHˆ¦|ädi½¬lZ inYaQ7ÇIÌâpð4)ÂX§ Ÿ|œŽ5ùžI;¾·²^`»’ïÔô„ÕÆ5¬‰Ý5‚­"ª¯Ç0À@¬æû_y¬üü)~`¸Ö ²þºóù¯ÅÂbóóD”íçª~g&s]†„`O›»@'Ý‹;ã˜#cÕÊ›z28ŠIx¡4~akè„aýµ|.M¤½&¤"¸Áìhf«N¥—sÆ0Ò¶ØCGƒcgá;çÜþÇÆlïpQt߸ÌW›.áíébß$Žš¤±$›ËAʱþ`Nn,‰iÕÛSöÔ9ꎗ²î¾cðÞ¯T¢%§`u8êrµ-!{ñúϹ¬©?þ¬ pÕè–Ò1)Š&~øÙªÄþ®FeȼÿºQȬ ¼íù‹‰ lòzCœø•?ÿqòJAaúÒq¦¨ØŽïòŸ¿`¼Q:T÷âʸð<še¤Ïè†@Th žÅr/…#v=åyR:• ’Ù›ù~ìôa”{MíÜký× ½ßDjK5¸¯Ø"V¡ª0å}ˆ¶ìý%›7’,GÏ*"ah°}|$;±ß-ÕkÁB³Æ#IAchj¹®Â®Ö:ÆÚ#ú€¶1wônç©o”ŽŸÈ‚8q\´¸øf6eJÒeJccX–ˆXè­®å²dŒ¦$ÕP½tTü“Ýê GD»—_˜°ËktÅT’L,ìI6™Þ–î*¨ëµìC£ïq·­-bõã£ä¿¤JÆõRm«G¬EbiÓ³$K¬Ã­é&‰¬[á*—5L§H|ð"ÀóÝ{a÷޾͞M×ó ‚¸•Ü*q× W±Å¬RqµpLH=‹•ûªõ¯^,?wÖœíÕ´Dó¾½óž½÷RÒ¼™çÜ€á[Ó ¡„âiužALÀÝå]ÜÙÛ&~Žòå7Ìžnã¡ÐÔ)Ïuzò…Ò‰#‘‡ :ÓqS%W¥õ,; IMÚÓi.+¡^.í;¬ŽŸ.ýÆE6XwœÄÝ5˜VFÝ_]WkMêæþõéâÀ.ÒÛ"}˪¤s1èæV|4'Öýr–”Ê$oÏ;ÇO’p¢/ªÇûŽº¿“µ …ƒ°(ÌUn×à'¿T&¿õ˜ú“e É"R0åúXF7êå¯>â„£ùŸÿÒ.4)Þ] èˆ›óçGîD…ãµ3C?x±‰´Y¯ä&+9ZŽ07þÆ«ÜSÍ»:¢¾|<÷¼OïêžQÇNOŽnDMáX â(h±-I}/:|Xª¬‘wï¡mg57Ë{:ÃÁZÒ{°–VËõõ<ÐfÛUì +¬‚Árá[¶ëoTÄ¢DG«Ë7úüúWo–þöÝ8Σãýq«JMOz¸"k»“Ç¿‰Éá|èPƒOfc»àóP߉ÃÉ‘b…äÑ\°Ò ‘Bk¹²ëdáHTBc›?üŸ¿V}|gþÖœgÜÔÁ±ÝòŸ<¯G³¼ðoÞL>»Éï—Ïyom­œ¯[Ôf ¹¼­«1!Ô ƒ¾xˆÿñó“ÊéüèM¶ÑáGF«Yw÷!³œ¸›. 2dkÿökò+_¬-&Eg‚+¦ƒ$ÞzÞ¸@³¼…ÕÒV‹L]ŽYo8~2°Ðèi×?“;U^jeK)Ý`V¦d÷ì™ ÓÍæŸóϦÄ 2äô O÷Ü+×Ñ•ö ØêßÈ{‹²²°d/¨SÀ’v-4Ëëy~'Sm4°ÅŠ¥\@à>ÌŠ>}r9{•-+À„Ž) »íz ÒݾуÙbYZþú#•Ž·/o˜­ÛÒ|2»Ê}òòg¸•{å®'̽|ô\_Üg+dï¹ï¢«*mûº S0Ó&/|);µÇ}û:¾µ˜2‘òµË «ª‹ â IÙ-þä§(×}ÍÚ(÷8 d–•úí§}¤óƒWÓ.¬[»¹ôµM:ýpùVdH`û.ŒþàçÛ†Û•[NŒÌ†÷»7_¤å{Åú=Š÷{_9.©×÷áT3%pð¨ÏTe-ó+ ‰Cïkˆ¥ã‡Ùä!í(#ÕÙ9±&E”“¿1™ ŒÔ6²l©GæKƒ[Ü×vÞšu‚(’JÚþÁ°?ª”W’IKšŒí±b6`·¯ŠûvõGïÄÛioÏáÞVX1‰(ƒÛ¿[á,Ž%ãGj0ŠË{Ø]OÜOKCY 囋Áv'`;ÞÝ0mÉ{ª¯bÂÙÁåñ|ýâ¡ì£EH:²r|oôOžƒ± åaøë[ÝOo°Ãͳ'úU­o Èá©_ÚNúfQgŠnv(Ó(«kçkg³ÿú }È‹~øvi+* ôóͽGôJª¶VKÈ͘uÿå7j_x†6ãN±•eÒ"E\8â½[j¬WçƒÕåp™÷R)f"¯˜Î;þ>]~(:™ì>G×»Åb\ZÄÜÍ•cwOîÄ+[í×ndŸÌP8ìÖ©²ëλwÔC/)ت—Wyov ¹ZkìŽZuš‚§mÏMK\ †¥íBÄld%ëœÛû¦ ˜cn|Ì?[õ;%« Ò›Œ £Çjõ‘ýùZêHŒ^¸TþæÙÖÕ5Ôþóçíì³Ò>P›]Ô©>wo.Ê“çÞ–÷}¶ÿ|ß'3¿—ÿƒg†ÏÖíÞ4HœÿÛ¯û¯ÜÏÚJíÚ…Ÿ?ÀÖ–ƒÙ6©øÝß½¨wd—WÔÔ"8Á 0ÉWìO±z`ïÞÑí{¬˜3ÁÐ5Ø+üŽÚÎr†ª©G ¥õæM9ÝÕ™ÔE-rã¿ûZú;³Õœ}¾D>G·ïPTMvîó% n>È8®ì{¤üá­h3VX d¯Ó·Ë©ÉÓOn’k÷ü½;õÉzl2ž<ìNžä»Æàãkô/V»·\ŽMDqVô¨½òÊv·ë%FFì2\ Õ<ÔÊ ®«º(Á_ü¨“&>ãÁo?ìÖj¼Æ4r*kê^¤–IÙjë¿ÿZö;Â…ßXÁŸ/›{×% ûLNÝ…9'"åã\žj¯ä†*°Èt*{u%ÕiÔÎâÛìöp÷.uü„ŸŒ&ÐÇåî£ÄqáÓ;îŸÿ¬zo¥ÔÒ=í‚U`-b ïÒôÂ#}O>Ü<°£úù™Vvn>®N†ÅZ¦§Ý±Àn›Tëën’Én¡+€ÀÀÊfñü÷vŸß—ß}éí.׬M5⸤Æ*YÔivàð^ÿ¯~Ö)4ŽAgÖ`¢3i¶e­^Jp:\ÈNd=iÐRÙ ®/ ÷SBûVÀÍ$M Mì¹¶NK›çNñóÓxfÜ:.²Àö£U1±‡÷Ó;sÝËç*ûçv+è$1*éäd°¶AP©ûÌÃáø˜ßÃY’Ó²e õ”Þ˜ÛŸ[„äpÕj87’€Ä§ƒÝÕ™¶X9¯h±€d™”2%…ï\‚Á”á›&ÿ“—ØKŸ¢LòSÿ¿H¾w®,ÛÌ–>¹)„-yªÞsâ™]rr –·èûoè­Ó}À»n1Ït í9,s´A; …š±"S ´ŸöœxÓÿì|¾>yÀýÃß(^¼ÜùÓÉgaC×4ô?xºj8Nªòµw÷Õ—g§fµŸ÷Ÿ8¯ž}¨ï‘=JìÀ•n}G£6½®ïµ³móѬÀú[OÊÍÍtv{0íÉ™i÷½{8Ï=j%Qɳ=:¯m,í>,O[±è¨EWûí´í¥{é܆ç6ÌØ¸šZΛ«ËŒj]7F öëÖFPrnRžÜÓ—¯šíøÓ»øÖ ÞÙÞû°=}²>Téýõ‡ER@™– ,÷3a•eb; jÏ™8€”c$8Aà$±üü¶üé+òÓiWøØŠf•¸¹gF'ÔsJ/"Ú(w`¿}/™™•8T½¨ïæM¶÷a/ieKÛéøÃNÌäç·c×ñ40b=[ÎÒ-:¿Þ{þ1ñêÇí¥CÁ-dæF…‘6ƒ¬Þ[n­Ø¬ ±Õ‚"ÖÖÒ¿$òw’p}£–‹¸c¨z:†@š–•;½…fo¥Â„/̤SØ–@,Lñ0)­]<©þýߦ³sˆôá$wò}$£\îÝãÖ«|qÉÂ.ðªüéùJè2G<躇vúÛKàaõô%¿6‚3Sä)ÁÄ‘¶ ˜}2«î^5„ð‘>V¯;p®‰K½YggŽ 4’Ô 5«çA”ÁÏ­ä~ó>J¼sŦVÿñ%ÿï>¥iž«¸øç{gŠ~_§Ú½|:cf çöe¸ØÍ÷Œé¥MöÎ[¶ùa{ÎcÆçÍ,\´BÑbIGxŒ±²PKšÇX é=º¹MîÞ¥®ìÒøuôËëí¿ü;ùÙ<[Óõý}ÑùXwx¥÷«_׎÷.Ó‡‡gN;gó³Çàé‹ð•‡‡ÎMö¢pãàðxRм½c¥éu¸³]Á÷¢Ãuûƒ«qšBh|é˜ÝJï0Rc>æx5ïØÚ³\ÓRàÆ=~í¾þÙ/Íç÷(Á–Évƒ”¡‰ò™Óþ“§­A…dp,¼}×ÌÏìí´|ç&|´w[ë[bðœUúÑÕ„1àÚu •´×„ÙõΗž€W?,ôsBڨРŒ be]¯ËÛ+:oÚ¶Ñ9DN¤¥µ~”ïÛ^'iº)ðƒ4[°ÈÙ°T‹´ìÙXHì¶tTui O×´Ò›]'w¯ã¾ÊŽûdH;€a$01O<ß·÷hÃŽ4þýOÖzÒ/ܸ™[ŽäþcF5‹™_dÕù¾ÙíÞÅÇØglï}r'Ó„P‘8FDo-•oÝk¬6[eõ‘ê ¼6û·eÖÖ¨h‚¼¬GœÂø`ôÓùƒ.ù»7ôÇŸ–t‹²SûûŸy¤7ÚWdPZk“ LWc3ÓÌsÀTæÇqim$à•»oôÔª9å”/Ëìo¤™ÂîmcúhíU]\ﶪíAVn)ÑĺLY”á«ìn›7ÆÍÅ}Þ¿~±{ui`2~Èã.Ö§âO_äó½Ö™S(ËdSé4 öôÓÇnwüÂv¬ÖYè½xÅLÍõ.âã]Ûš¢M;¾¸6ç~6“^:Úßäù§ËöóµRÊµï£ø>k/AýC•¼dèÔæl^Aåÿ䈻ʹ&xIÂÁÐJ3^_àܹ×#dÎܶ"¦`ìøNs|êv' ‡í‘!‘á…f¶•;·È¢êâ–›—nk%K.UÜð“ w¹2ÑĨ éö@~ñiK YXƯ~T¼úÎè­yã"áh©Pˆ´¿ù•úo=«†Búö«IíóÒæB$+ù&Ðk‹j[ǹ¤ôîTöůŒ:‹†Ž”?¼š¯mEq,‹”ðN^›(Õ³M=½)—º¥n»9EUÕc–ð¨FqÉD* 2’V˜Ðb`÷õ¹Ý8M5.¸rÑ ¬áŽ6–‘Ž‹h¡$ö·D§B™¥ÜÕÔê:iK.­„7nª°¯r¯¥1d–‚V¢âRê§¿VÙýÝ»þÝß®ä2烙C¾çP({ùí— ï›ßN/<æ>÷0* ¼«göTÁ¬fß]ªÝ¼7°´Õ*3g¨NʃÅç3q)æDÐ̪ •¢î‚esE/ì+–×ìÏߦï|ÀV{ƒ;gö޽ðpg÷lt½ðY.Ej¾Å…Ä®á{QØêcÉvyú­Ø]Ö‡¼Ú•"ýi¦0»Žì¨½Å}\äJt$èkÉbÓ1%°IAol²{-]SÏù׿Üülap]f¹ÕO¿vA== í°ûg¯¨©ÍüÒù ÛåM+²;TµÊÒ†’VP¢²þٕ槟ɧÎÓþ¬×6ɼÛ¯W‘·æƒî$í-m+}e±¸±VíÚ©‚ù1pž²Õwdò p¶ 6y•ÿŒŠ;Š^2Tö‰ e;Z—…3x?¢Î¾cyäQ Ù‘1ùð¡°“…‘Ò÷FwAå• g£[š¹›.ÍA­„Uó—7)KòÂÊã ÷º2Rài–Óhk0¿ð”rÀ]пº¬_y{ìÞu‘   *rêF‚ÿÖ3åo~Å4úýËïïco}.•|ëkø:B‘òõ»ç¿6±óDwçé¡7ßç­ŽÎŒW <µY§ÇÊ~o æ[hµSm·Z©!ÖXBtÍ-%ªçaÆIª,I8sJ‘HŒ5€‘¤â2¤³Æ€%ÿä»èî=&uª5Ež »…(ÊÇv™?ø†¾vs^HkfÕ…BRŽ•ŸtøÌ¦[÷؃dÛ¨:¹4Ê0ÆFpþ¬“µÔßþ`é>¦* }ë8–ö‡;…kvŸ¶›Ö¯_ŠïN±—~ÒS@/sŸ¾`7¹Yìa‰Ozpã~8³)XÙPáÍ7•+Ë H_[⇷AæZZëЀ^¾buÏÙˆu…Sö(7šîó¥?I_¼‰^¹*®\-6Öø%žrèCå`1á Q-Ce× 7ýÊ6ý‚i0àwU–ªša'¯+6mMχ  RäuO½}+夂2«h N ¿ûåÁmhýË·Ôå{þyç&S(³¿zןZŠŸ;î„þÇ÷â{kÕ‡ÒU;‰ûòUgVd“ãʼnñûSbÕ  l*[B_™‰û‘èä |‹i.Œ()ó$”šÞEfÇÐm,|æ®KÑÐ~äøŽ[Û“o2¤KÚ]¹ËyÛrËwtFÊèmÕÞþ<þÉøÙ-ôËËêý©Æƒ55લh&ôý;ðÉ Ä=l$Q:ó<îún®ÚàX¼blÐsŠŸ¾eÞýonŒ{¹‘)ï›_’U±»µifîEÕ!7ìO6Þ¯ÈcDUò´V×"ƒŒéXMÑûŸ5)‘rúêËP¼Z¹R²È_•;­l©ÊÈùøÞœ÷‹Gpé0}úqÚËôBd1d.t×7ÍÍéÚô¶`áÚÒ̆ðt%²Â3Ö +wO¥Ä(+>¼!?™r–Ó¬ £R½ÙöÞö^ü,{ñ:~åšüìót}e i9©DuÔb¾˜ÖÒg ²ú=§²IÔ p £ nÚÌ1XRQEhœr_ÒUmZ`O*f,¨þõ­nn´¨Th7üï=ï­óäß½­ß¹éõÿéïð<ö–ÖIÅÍSÕ®t• H\õ‚ßú Lþðéj¬ä‚®~O‰• ”KÙï«o"ì%…3µª|\%(,}E­Paÿð»(I`n;ËבÛ\—)FFD}%·àî›ï›¼Ú±­ž6Äøˆºq´yêB)júÍØaO%KÒk?1ÔqZb÷üÓêÄAttOÍšla•*[rPÑÛ&Swý¥Ø5õƉóî‡îŠ(#gʦÄÀ¬Ò¹S›è¯6ûˆ®ÔIúE­B†ÝîhCUgÇŽjPçB{Jf6uT-hòüÛÆñ‰*¸!(âª7í—($ÈÑ Œ$¦äàÄvu±–cc€ù%£,¼xŠÿ_ª•IkæAè8ÃÏŸëÿן©Ï—Áxölåø.4·•ÿäåF­¯87ÂS…Þ[2wnì8±§3Z•³³öóuXÙ+­êS»ZÆç—ï–=ã}ýTö_©/w“ÏgXŸõÔŒøZˆ ctóuä4‰É´ 5±âÚr°Ú.Ь‘cqjÄ µ;mùoP/¯`·K)èÁáÊø~[ó½>RìîwúhÒï’Ñ ­z~=”ƒØ„!pVKÓc£ ÚçÙÚëhQ=ã)Ýç}·WÍ­k¤³. R¹ö¹†³Çè·Ÿzâ|44ŠÞ¾ÆÖŠ"°îÍ›†Ö½`$]Ÿ,jîèüÉÕM®´Å ›F÷ºJ ¨Ï,¤Â–W6y—k@’r“;!ÚN8LíÔ¿ý‚óÉm”‚ — ܤeKäNÓ‹{ÄŽÑÚ•{-œ'"—0¸(W_òÝ?8Za©–ó32pYlTÝ×eA0îþÁ·Ã}}E'¦wȾp Ë0¢* †+¿ÿÖãÙâVZ8Ž£zb€›ºOcâTýn¯­êkb³e¶ƒ.ÈÀ+¢¨wáa­Gqƒ<µµ¹þìg9òXF¼çž5'w™ûCcäÂU2dâm{ï^îù¦Òw₃º½*J˜®aÙ’3ZÚÊØÎzìXÝ?ÄêTÔmŸ‹*¥hеãõ`|0(•rÀa/M­dªâeyú âU‘äS\"rȦݒ’…Õ!Vú.±l7»0)(š±Fí3Ö¤(*—N‹ÿáyØèîb £àKç⇆+ÿÏ×ÅÇ÷<@ü±1ÿðŽl¹£ôÒp0hÏN¤Æê_Mák·j'egf&¼²ÑÞìšùµÁ§w·PY^ò|é~ýTñGÏõe¸wmÞ0%G IJýUÚóú‹¬M­Ñ`öxpFy‘–ì”3x¼:•Önoš;Ÿãîš2 RäN%ßzªñͧÔÄç½ëÞZ’–•sï6*ƒ;ÕÊBÖÝñsÞ§×â\`ƒ4†j—·•y~ÿ­; »å™Q¬€C¨©6YÀf†Á¥rÏúÝà“[AnA$¯—OŸa÷ã;j·§;4 9) eGb ýÈy¸´§F?øQçÈYg®Qšî$bØ k§e‹6çyéÐ~ïµ[˜°ÁOO“ò²Õ_–]8cÖÖíÔ X® @NDè•%õ²¿ÕÍ?¼ÊM7S¢˜Ÿá•¶ ¥CáÖkr×wh%ï\ûìÖÖ6bà¤~Rn¯ÝƒîÔèòTôØqúäqôÑýùŒÒ )MH+í¥ÝÅý„ ÕÚ.ip5!`ƒ¥¥ÎûTG•é­92àb—t½E"UŒßšöþÍ|šj`ˆà(‰\Áv§¢¡ßñèº,\·¶Gu—)(¦|®Š†u1#‰rÔ ¤Úîja8ärǼ°ßß7Ô͹ÿéŠ7QY~òXõ_ü¹Ú‚!\Š «­Æeöæë^¢ÅDG5æp¾²NR˜}ëãÊîß6A¿ ÚëóœSñÿ½þ¾ï½:±}£ï‘3dçÀö;¥_…©àB+nŽ!8È`Nä÷¤rÁ"_1.AÕHíÖ-ƒWÔÖ~õsħÜnËØ %€ýŒˆÍvó[Ùçža±QY¦¤ÒF‘ñÉÆ¦Ñï`]£ÿ?#Hc z4 ¢ÅÀ Ñ.ßXض: ¾v-’ðð!¸t†êØÎÑã}ûWlšè¼²t´)½ñ:¿ttìâ¾T çeËG2½ÙuA;P@d¿-/mwaûÞäºÏÚTäŠ0¢QÃ÷eGv™£Gå möòë^C;·Œ³F¡ŽÄž=µ÷¯Pìo~ñÑÒ›o¸ Z¡ãgE¾³ÌŽë7þâ8ü›nøóqË21èôáY³¶Þž¾Cí/½=U¤Íx¼¦ÊZò¯>KÏŸÏV[êÞ …k@cRP‰ˆi×JA7Ê^I…°¥ MÇÁÙàyÊpÚФžznÉ9þ»ëy¢>úläúíö¸ÄɪiÃ$­N¢û+Ó› ?Á?¹Z\›Î4W&o¶#Pg¸Òóh£àã3`ˆ5 q?ýgß!>ª¯$„ì¤×óÃjÇÄU' …÷Þ|ðÿùu¢PêCm9öc'ÛŸû%·ÞÖ[ÓJ3¸Wm-RàÀú²!C6¿ËÉ$QûsÁ©2P@ºø™z߀'¼¿¸I'û:Ïžjü‹¿ä·ÖÃzYÆq£¯‘Š |ó×Á¬â¶ÀØ÷šÌûÚÛhä{EÿžuôÑŽDwç“ùCÿŸ~¿ôÒ`{jµúð)³´ù•¼òÖÝHdPØÂj8aÑ9Ç.J~Ô8™4h,'7–;¡%PùºŠ'3Hê=”}îE“z)â`v”|£®¾ü8¢Â64Î(²ŽYló°¨ §ÆŠÿéçÅl !@h¸°L‹ÕÀ…œØõå-UH È7Ä`çÀ¥ Ôvåâ']Ñ)Õm噼2Uê!^j½Ÿ?Öÿìßo;®‘6 ª”™f—ÅT#UDÐ-”ÀÆ…¦È¨.¤Æd’>ˆ5ÇFñÑýè«_¤¿x•ôëÒmÃ'Ù`®ãÞ}æƒÏJ4Ø~òbéõW±©‡Ü8çûûüÃâýŸlãy?’fð$¹<Å}̬ñNž³£AÚzÅÓ‹Y„Ëå‘bv)Û¼¸Þ{úQ|ºß¹û ÛÜû”Õ´n,Œt ”¬¡\|ï›ûJ\Z4Ö™'s­)3ísÿà^ÁFоäß¾“Õ´Ž),Tµ?Ö_ ³éŸtë¹]¾‡vrN?¥&w¹K²›”‰#\éÝž³›R}ÕÀ}"¥ Îf§xìtiõ~ðÙ/z×MÆ‚þ1s‡zET ó*ú‹ŠÉÿ‰SÎíÅ̳à›Qâ8§TÒSé;ÖýÙy›s±q¤Ž Ý ¤/½ åN[óéEæœ.JUkÖ\’+£kJìƒúö'wøÒvþ{Oî{ù£øýe…ªyd„¶½ï¶¸®Ö:~Ï DY™…õb³Y>y‰¬o$Ÿ^M#¹J\IÓu¹_ðì ýøÅÉ;7#æ:„òB#@xRZ‡O?‹VVì¸C‚AøôAb^çµÙ“|»v¢é0œ0yÈ·7 "1ðí¯ d73Ù ™è+âlÇyÿý;¹”AéÀ‰t¢,7aéšn©ReLÍ/ñmZ¸Jt|éñÊ…bn1ßY½z¥êê¼G“È!¶‚=ȳßx~l°Ï]].¶ ±Qº¹ÖnÅW'Ç'X¥_¿øªþôfPƒHPíõUŠΟ§µT¬Þ &釞»ÂÍeÅÌe40ÁÙbfK¢Ü±h–©\ÛŠ‹‹§HóAåí¿ÞjÞF£»d[Rë1ü/¯™¿üLô…æËçË÷fS×k*ÌØ#†G8»LÜw˜šÊ*Ç /¹©” P^S»SÖ,‚^Ã올ö[´ 9®aØh%Ã#û“Ûbq½øÞc“/}½¿lm)ΊiôåKn\¤óË"ÆFÈê#'µÈíO®’žŠ:ÛúÔ^Ôç•Þü¼“"nËr©«76ÒGŽïýt¦½•Ùû³Ïâæ:ÜÇ™aH}ÁÔú”ówD\Aøžq3åV°±žØ…,Òžk1MÄ ¸Â©‚¤¸ŠŽì'&æH>sÚ‚-¿|CO/žqâû2–BûöÎgõ©7ðò•H–KÄÓöë 4FÏžtJ7°|o³˜ºcjÚ箲¢:R¿ùÝú× éy·ÿ.ï+øÚ½¼r€m­êNÛë袎ňBKzc‹½ ¶6äÕÏ DU]¦¥gcßz%Ý÷ðCö±K#÷nDÈQ[I´Öz§¢i<ùÅlu]Œ»ˆÖü+K]ëÃj‘2HŸ<7l7dþaÒ®…»SÝÐˢ9)ó姪ê¾N6<ò°—E”>õ nÏÐ8Ÿ¨:¿ÿûùÇbÛºÔª„žx¼þáuG{™ÍÔÙþÞ±‰?^K@Ï©±RzkÛD!%Jïqpbýo~…?{>9›º-«®^£`MM⼊lŸr¶HQ4J×Þ­.Ï÷„ÛDpmÇlŃ3^u²UgÒðUE÷ž ·dúþÛ•K<ÌŽU›@ˆ¨)[@¸h˺¯½ÂÁ³%‚svh¤lÖ·w®AC[º´ëXêKqgÎû/Ú»±zh¤úÏ¿,÷åܨfŠ 'î*·µÔUïdô¨¶À¬8nÑ÷¼þU‘qjºdɶb_qù¶Õ Û×aY”*ëÓ ~qŸ¯o–wÔù½nqsöNùØÐ2¿ñ÷Ú§Åõ-ëSB_8\×à¾òIâ‘b`Ÿß]ûvªUHì4×—ƒi‘ôyjq¡úÊí^ÔV¼bpæí€ô4­2û~,u„ƒ ee'­ý]4ÒÑ|DáxžlwtLŖ½…¼žM¨umÿüËò‰ýô~·zc9»zÕØ±R‘•áÎû•±M1ŒÕz<ÀÕ+÷â¬M@PÍ7×tÁ)c•(4>y°žv´…²ÔKBï~–ï¡6!¡Dsóå 7µZPÂÒnrcŽn¹¶¹`m[+| PâLNºÜrzútñµG…%üæ,ê7&!ZL |úЩ×üU¾u]U ú\_•˜Ø*Ô~û F\vjBö£b–ªo<¯gïâ<'«îW¾Oß%¸“'‰]öÄ3¶;ã¬ÇÅŽ’ó¿O®’ïÝbÀ$ôô“äòM¤E ÷Â)ÿàÀðŸnôæ Fe\kÎoZáâ̘ý¤ªôµ//{Ø“Š½þ‘Cˆ-à;ô‰Ã#?¿ÕÌ™(=8`®/æã¨bg÷׊?»§›&wÀVV(ãsn50ùJ¾G}Wɤ¯Õ¨€ß§ƒ›ª·<·[@hÆvÕÎá€i¿ŽpLÚDY˜ÿâ«ì¥k¡‰.m°Ë7a&(N”séÂÝKÎèZo¡¶§:ÅK÷3Ï ±Ì‘e—àjFwmSaèëäþrS5“IR§o¨[†Â½Oø$Umdž2{°b'I?±kÀEa¯›-,&Å Ë(´eO’ÜDSjcÅOŸ±?sFÚ^vû¡]Å*C[itì@ ¼¾òƒ$º‰Ã#Ô*šeíašú×^J²KN!æ£=Ðæ¹×ðÒ+óUû+Ÿ—+7hÖ‹É‹ G_âvH wáóù¯E“upQinuÑ\7+[ݼ G†Ñ¯½V»þîò±–_t=WÓ'÷\º³)T¨«™úüsh¢8¸¶Ñì÷®|ª;¹ 4ÍRH:´dÉ´ê¶Üfw‡ zÛmw•AA˜3 ®J^x´`Xo©9<ñ¢ngúÛßæK;)€é+¸ÿèËéȘ%%ZÙ¢©ÉµÏ—#©œ‰®Œ4–Æ"}™:98|u¾›õþƒP˜Nÿúãáÿøócú+'‚?z-ÊsiÑ<Ënm‡ç€bz)ä`Í9ML¢ÀÙõ÷Eç¡)myñ™³5F×}˜;­ȈcÅ$÷©F\5™îIïsô?}9;3‚þþ6“ê_ü*Δ±AÖ#ý(ë‰÷Vˆ ÖÄÒjóøÞÚ\¯·ÙRÿê«Î×.pÃí++*K”« Lfc_¸FŠ£zht$’Œ®STÅs’S0¶4¦ËH^‚x µ¦BØJA÷I×ßüC¦æõÌlûËÇäé_ÇÉ“'tA7ÞÏÞz«VýÄh*š…µmwMÄŽ]žëÎg23 kã2 Ä©ÎF÷Õ_y.}úLró¶—d|«•ß½bªuTÙC—– ã»ý'Þü vaGy9%Ü@FX Õ»^kÍlïJŽƒ—šˆ¤* çP Ñ3ϸ+³ITGÉya¹¶€¿üäþîeu$VD,Jùôóը׃ñ=êä£&Îõ|“ìØäøc…¡A]‹÷Š/½ŠÖà$Î;VP ¼”9! Ëάÿ¹¯õ&àáâmÞtLýª#óioö ¨/¾J–/5ujý2݈ cT/ßhk¡ Ø5B~î" ƒ[;»ÓÞ­[x7‘ž°µér:®”šú¿¹Ô‹¶$Eå®ÕëCÐH8 EþÔ#¡%º·×ë“Ï%Í$ÿ«ï¨Å-fÝ(y¿õ%18hé¬lé-³åž^¬zqE#¶Oö]ží°`¬ï@T˜ÿûÇ}þ‹có•ƒáŸ~ Pš¸Ei|uËÂqNUâ°ã0lfIÄå Œe6u Ò°±¶¤r¦ZœŒäÖ1tqeË¿ƒ´C8§²LŒ¥t3Õ‚ù_Ü+ÿÙËüì¨ùÉ 1>ŠöõýûŸµr2šk ˜ž*s[ã7îYÚö€T·våžag%·vÕÿüUÿçaÎÍ%•Æ"0Êu¡‡*̵x&öõ÷Z)ÚDN‘> 9GÚ£6(¼n«wtô©¡€uæ)¦Ú{þ ˆO¸šÓÔÆR÷ËÇäéC%œvŸ>âZà¿ÿÀyc!Yµê§Fò¼Ì7½•8:uíþöBWc®2¤±’$£AÐU½LøS£Á+¯È§OõnÞv2.7v³;ŸBµÅ)¼¸<Œ·FNŒþì½–ñJmáG˜bN‹®³Ýäí]´uœCjc‰”c„/‰E¤¯ô Ï9+ŒâÒž)q÷6æJIˆQÏ?ºÍ3­¸|Qò—^i,-'1·†&ãÓ ©ôÝuÑ,zGO—§Òþ µ|«ï™—Q_ƒŒ«4ªã{Èr‡Ý¿­$VÊ¢H°Ý²í&C3•¾ý]°ír±´u?ùò«}û†·–s{e­#'8œMÝX^„$)Q™¼òYL-þpmó6Š¥ ­v4×ÈQ PAfÑßü ñyo›´´H…–‹YÞAŠÛÒ) rî„uþ XÇ“îúo¿u•¦*…_ö¼‹G AIVêYcbÿúÖN'’APÜ • ªTe¹<ñŒ8x’Mj¯áüëoêOî±"r~í%ÿÅÇzÉf¡ËFVzd«mß\IýÐM”ލ<Šû9­a6åP $áŒI…”°'å ÒÏag[/fj›ÈsOã#§½åU{8q6y/7&0È5$5ÈcáÅ~tî8[×õ_^dž »Ûèþë/GE""©&Ë$aèêj:ÈB˜ub +ÛjõäONõ¥ó³øÓE£,åBb9udþvœ/|––ÊÉýYõhæ–´8î¶…Ü1ºŽBD+â‚Að„ë7òlF2êÿ„È»N\ç§µi È}{ÚzýÎ,Ì.òK·¬§¡£ûãÉó"«ÁŸ¿ž*QwT6ä‹+×÷{Iâ‡ô™gÇ/žíô•Xö½”d–˜¹ K…s_n?zB­vØÜ}§›ŠÄàp™ð»¦åAáå³ökÝù»ñ(”Ê¢@©¯ÉGxeá‡*ºõ wVg]ÛÖ{Ô£X;i/®‘me‡çóGgºuom^>÷lµQK+¬<Òp'˜ƒ*«ÙêŽÈ²¢Á…¾Ùʘ˖Ûüþ]ÕJ2))5‚5‹¶cèh0²¿04Óµ,Z/•» Éo|vààHú06 shÓ(ÿš8±½ñ±,´•¼øŠ™Ò«?iîÜ!Nà­ñîj4Ø6uà%„ê¶õ›ŸÃ%æÖƒ-à‘*ÚÅãm¥s\ÛÈS'͹óšœ7Ð÷ÞÎw$Â%q'°­ 3õú`†Ùè}[›½f;÷Bj‹ØÌ5‘²´Ú_Ì#S(ìÇÿã7ÉõûÌ×Ö?|Éõ‰Ns Ú¢¾œçK]v{9³I5CbÛä{>$UMáÃ%›”q‚ Ø´é7è)âLbñ\–÷°:ý=~¦¼ôÐ`µ Þ1 l‚9µ˜% Ύ£ÇyÄk?¿¥ûÈNÓÜÙ–ýµ¼LÓˆóé’“¸²ÌG yPèµS‰µe\k·Í^<7:Ù—Î-à÷W„t•m0+çV@Ås ÷ xO|^×ëÙÒº{´ƒ¦rt‚c¶1¨¸¡ÊÆ +z”Z'¹:ÃQ¸?×T–u<ðÁ »™Yð<3ósˆî#_‰.œ0Íž¾s›FÌD¦­læø%–‘H›¯ž)~ñ±ÂÜ-¥1óöp4æ÷Úõ8¼ÿCžÎ&^1;C—ïDåt¿¾ðo§Í¹%Ù£wš?= ÖïÞžnd¬,ŠÅ¼>9ÆU…:++xe-Ës vwéÞjêœXôo?F»Bq„ºâÞšKxÛ&ÆPãSÇvÀ¶1 U¨_[M—Zxß@¡ùšòªÖô¨oÙÝÑÒB»ûùǃ³‡âŸÿ¯óCð±=÷pcrÚ¿=Wë„ÛÅ Ê8ômõÕ¯f†·×% kPЖÄ4nw¨å8; …`öÀµ6úÎ/Z;Ü kk  âe³ß+Eà>yÿÏþÔzë/ÕÍßE‘Å‚ À<ìæÕ¾{Û;_; ÿñõôG¥)X¶m‚¢õñýà?¿ m)—”@E д úK?ÖQ¿äz K‰À7ªtÇØ-ƶžG0«0œ¨†£V½øZòÉOkh­ú¶ÕŠ3Cˆ¬r-þf^ÜyÓ^ÝîInòÄwaëôQø¯_´zÛýú­­«=îPÇÆðÏ_)ŒeÿËÏõ‡WÚ££5™GÿæíÝÆºñ Ç@‡ £Tцçx¥:®Î¾´µ]U5YË÷?ÏÚæ‡YÔ¢,7RªŸk¼‰äpWƦˆ÷”j FhÁê¶õƒOÄ÷•X@8x¾“6XÛé±åˆþÙ7“Ï]€p>¼ÕËKÕrwg ¤’ÀãþÙ½½ó¯áµ[½ëÿŸ$ìá_[•ènÕ‚Hyã6¬ÝÏ¿ú’ÇœZ¯º»ˆæ\Jâ­ QÁ Oîëøÿp䛳¹Ý3;Rå8­èÂÄTqw}{¦™€»Wg?ûß–Š<ûÖ[´1X®4^(<ü›7!Ê ≠Ч YFܵn <{'@¼ÕÉZÆ»ˆhÙ(îJ±,Ù(,jà‡+£Ý-ºýüçƒ_ïYkÅOt¯É5¢Úiþ÷³|ùm«µCq—¼½Þ<~ýóÏxM÷Ͼվ!ÂÁB⟽PÚÛþ¿ÿÈ||mwl¬¡˜þþrgbÈܹ“#@(`J}ÒTÊãìÅ×Z*H°÷æ·š‡Cýz,"lçuÓ¬¤ ’Sº&Ø4wŸÑ"ô Vm „ HÔXþýåø{ï ê,ב£ý½z«(^ŠÍ?ýóÝÏžƒß¼?¼¥ÕºßÛÆA'R¥ËÓ{:Ï-Üh]û·z þxîlØœC‘–úÆm²»˜~ñyO»Õ4[t=Ç•6çœñ–EÜ®efÓõí©};¿ó‡Ãùý^³e­e»Ž+²áïl®oŸ.WWo·^xű¥ø?&}ƒc¡§¼¹‰ÐážçÛ¯_ëÙNXøÙO{ï)Š´º+A¶à©Î òÛkV@H²Ö}, À%„Ê<ð„Q+ †(.XylzÝ<Žó…96¼u'ŸÝͶwÒÅ«(a^ÜÑzò›ª¸æáâ"^LÅÔ£¨<@n^‘Zp¦íc3Þ“OÍß[ŽÛ%ÜÇî\vªÀ7(ª)ÁH…Z1BÔn>ºI”Ç^¦m’órèšrÏuÊÖ€¾¶s²÷—ÜÆõì#yé@á£{9ãÜrõ°D,‹³ˆ|x»ñú])À€çÒœõr²ÑîT½Ñr°9>Œ_xªÿäxáÊ*2,s ’ªe„ïà~½kdWÚÜr²'åU•íp.²JÕ#ö¾³éÁárœð¼GîÅÄYkŸ±&Ä:Ö@$)ÙÜa-.°·» ¼ãû¬—êÃZÛÖ­ïwžpÝÍNk·P[ÙEšql{/H+“4Å Ü^¬¯6Q³å:ÈHI#aS!°˜`\ëÜ£¥Ý;øÚÝÃOÇ`Ö6†c|©»`ê%¸y q(—}}üÔH¸•sl;ûà yc­ûÁ|þ«Oؽ;î݇YÌx»å‰‰s!´áƒ‘Ž­[¦‹ž_´IH˜È%(Ýç«r]B,ÉCŸ©‘M¤Ð*M É ­^ÖÍØì¼º;Çß¼ÍæwùÖv¼|C¦i£ƒÌ`ÿöù6Â¨Òæº³’ɱs:¨šÛ×5•)rð@ñɧ««7רn• ÷®] ûU²c2J´€…‡ °‰{öåk´e’Z‰ñ ¾(‚p¬ ì×ÑÍ­ƒTÏ­ÃÀHøÄ©¤²·qkEöcY|X{*‹ÒùäVÿOï'yÈ'y*#UYkvᣨÓ]÷k«M¬YÄe²¢œŒ£ÄJÑõÅÒÊï$i;L ÕKÕ¤ˆ±O= ;ËúÚ­ö‘³ÕLn¯lˆy†>ó,és?ý$„=u*h fGê¸gäÒôêGèÚJòö½ø­Ëæê´²)Ú;qš¦ì͈»®+3©Œr¨}C8.S;@ʳæ„Ú™³«¼¦î%[ŒÄVÕøŠ3Gƒ‡ À€ù“0Ø%R_Q‚ãV¸Ô.^zМ[L’Üþð~²ѱiaÚ7#-æWšd/>ÒxþÜÎì_FÕM?Z"V¿·Ø“ÌˤSµ¥ÉUÁX%”ž9†ZMµÚM1… æä1•Q©êÆj÷ôÇëKˆ¥Å¤M=–ïØ?þeº«Šƒa!X Ôg;ÝÒ­NÏõóL6øsTNÛ_|B½z2ùì ëÕ³VÙ ¾óÝõe”->hE†:J#ù˜ MbµMV£â[Ϲ(>¼*±Å^3ýÔèìõ­Ë— »ïk%ÙoW­œN:Ü3(GŽ` #`ÂvÀ∆!ã®®ÈÍ]üÖÝäΚqp ·ÝcÛüÆ‚õÖUe¥ž`Ê-)3Û€Dj¸t«§ˆècvÍ÷²¥Nç&yÐr;‚—Ž·¶;…í²üM•ce† \Dî}šGF(ú<Ëè÷˜Ø4 l[ªøìDð0ÍÔªxù©â×ΫGFÙ“dÈõ‘{¥%xYC—Ê¥å÷Cg:—Žî¯Z›™Ê6ÁRIeŸ³~_÷Zõ®§û÷æq\ímå].cÌ3cRáøTõ£œ?ì´Ö3e¥2@‚7H(²átÞ°«­pkió¹—òºðWW“Jµ|ñLïÐhÙ;0@¦v*ƒÞÇ ä{ïØ+­èέøö¬Ùj×ó¶Ñ‘E¥§I×±IžËBàå"A$àÆÎ ‹ýR ÓÝ”'»š\w„J¨RÕÉÜeïê$Ef‡»‘UŸg¹À¡¸" +|–«bPÄ4Ç̧1êµ¼ùfíúƒ­ù‡,1ÞÕy±[ƒc)ž43O ›Ô6– *Š¿pºöÔ#­;ßjÕ7ʻˌå&31î]ó@å&»ùù“v³  Ýõ´È (B¹®+g°RÞYàŠjáSz{™þàÑF¦FJAl˜röµzöÝn×vÔÁ¢œ¬«çà ËÏ_/Ÿî}é¸õây¸åï}gkV± SÞB3ÅE1Æì#¬ÂÉ.µº†—z¬-Ì•2ÀT(XÌŒá‰W볟ìܼڷôN·²L&í b0îq!޽Ä0bŽ„ †-uEmîèwï¥7–´ƒËHºQÊ·Úù½çŸpÀ±$34Ð&–! ±.Â9‚¥¢’áR-Ps½µOåbÛóbU9>¼uaÝ«’pCeL©qžÖª£ZRT¼LìPëwµXW`lWèøôžp)Mòeùêã…/œçÆòçÎæç±™Arx\ÁÊuˆXÛ’…N½{“e.¯×ñ.ÇÑj`Yš2;sA«2×®îM£¨à1) \8U]™[2yôt°½’"Àp¢´…ʾM2Ÿª¸_¹µ ;»}ñ5ð¬ÒæjâRõÚiµoãUÿˆÔóOîà¿ûÀYëd·ouîÌéõjÚd(ñ©´9c#…<Çï‰Ürû’ 0Àj›ÂF–õî)ÖÔ~SêÜÖDRðL-1-ä•dÔéËÕŽÈU7]Â"O·%Ú™U›\z²Ä!S9¢mù%^²TÀ)o'üÞªýÓtaCmî |U‡ÕýÝôè‰ðËO¶òM¿uMѼ™g… ½!ÌáTŒ_1î`¡÷ÏöŸ;šÏÝ“»9ĨÌHb¸!Pµi†”tüÌ3<k¿.MWÞú8ùÙÛ$cg·r³²(²H4«·ÛtæDX<*È`~ê ¼ó±\rA@]ê|idèB¾oHö¢<<ÕØØl£”–¿ÅÓ]ͦûíC”߃Q—íöôØt*‘4›€IDATøèã]UªµEsf®¿ç}8«¯Þé½ÿútŽçÝÄí¹5ðì"W®ÝT"Fé í²­Ü£ÁÔJÒêNlÚRIB5g¹íÙýBÆÊõ¹dÔIʉiƒ()lw0“›"×±+{Fd®jÊl‡g4\Oxnå– €í]{^U– åN~kѹq-_k¢Í]’®j·ÁçÚÑñÁ—žì°m§}8én–F¬]ÅoìJ¤D %Ö˽¯}~àÔÑüþýl;ƒ¶.HÔ6J.8.ó$ø^}‹’Ñ{’Æò›ËŸ¼%âDeŽí)üÞÜ{da«ÝYÃ7Ï>;ü™C®£ã}0Õè÷”¦|6ÿúoøÝúýóöÏ ¼¯E’j“bj´<¦MæZ8+Ñ á.ÒGpሶDZ¼#e²o¸{KÄŸ$t#j(ó¯þ“Ê`yH¡ójš(ØÓ‘@”±#XιB—l‹Íœ*éR$„È©¬Ä0»î&œjœK®A\7 Ϊ6ßÏÌÓ?®õ®–äSUÑc¬œ5“Õ5Þ| 㺽¾ï3ø¸Ïwœò’duMbg’ÀÏïù…¹1i­†BýŸïßÀß/ë›7»ý¸äë@…Óõ°ÏqqŒ9æ“úôòíh/r ¦9oÒâLãϾatŒ®pÖ5—ï›õÙs´R>ð:uX¿õÛŒsaamªJ§àq-}³ÃƒðÊÓâÐÞzs½c«ø]ÖÛUzÏ094 ùMwÌjµs{dÏð™'ÖÇ5Ž˜îGw/YoÏŠ·?h_¹„®, •rÒ²«ÆuK"ÜRyP²r†›kq+·Ëë¼îê,BI×’,Ç\ÇØªHS·ÁM‘B*3ˆÔÆ–RçŽñ™L€è ¦ˆõQH“Ä”°%qçy:¬‹DîBÙmŽv NL˜BAEC¢ÌJ+»»J?¼&X§Ô×ïø*•c…ÔÇ ÛŒN¸G/†ó·Óv³˜»JËìðóäs^¥Ô.ùîµŇ‹e¦1Ú0)äAèyêŒj4Ð; ÙG¯'+»fƒRj¤ÞÐt"¾pØ®RÿÓM¥DV7úÆ|çúոהּj•½ë­^ñ_} -%øåGõ7Î+Avˆ7~çnË¿EÕ˜ÒÓ\êFŠs rÇ6Î6$~Ýr'+Ö+[iU˜Ð~çï3(ÝE2PP÷¡OêsÚŸ–lÉQŒ‘FÛ€b~²ŒQm$åÚHÛÌdØ„S@Oé2VghòBç‰gÓÔxè6‡¨"ÛB±:æ0Ï ™ðeÑ®‘jG$YI¨ADšXilÊÈ4D¾ã·r•B•hnëüµÇ*G§¶Xy–´@æœó{,§œ¬ËÞ‡¿(l_ëþø“ìÞ\»O˜òŽM~ýbãë/ÈÀîÞݶ$'«Ýåxí~ÆŠÖãÇ3›ª÷ï;m¦»RaM1(E´RÜ%¸î–Ÿ8CsÝiì+)ãè̸zîa,/QòË@JHÝ–6ÍC}H¹—Xò¦„‡5àbûÀç VÙ,1´™:Eá•5K©$|ŸB[6KMÔ(Ã7N–Ê.Ï!ô×ÞÑŸ¬š÷ï÷ŒÆ*æ“‹‹¸NÍÁÛRŽû_yÑÑ »yMb)I?çŒzíT•Ê‚æda™_½e¨ «[>kÂÏ’ƒ¬éåI9¹ŸQÄ/³Ú½©ŸÑÓ3AûnKéÞá#p䜡ÎX¸œ·^ÿUò«wŠ› »I רÛ©PËÒ¬Q¯‰„ †«L`pléIĵ­@*–o4a³@¬B—åÌt0-h‹ •û$’+Œ‘"`i)­µOfcK¬\¥¤¯ˆ¹´m¥EÀ¥ †Y¨ =K( *C)ÐŽÙÑxÓ¶R)]D¨æa­²ÕÅìÒuoi5÷øÀ©ðÌ£ûí®^š“e“æåêþ>¾üýpå2FÃlä‹à#“¨Qf2SL= ÅÄuÝŠïÑ÷=¾pßAZ’ªÞ‰¨É1†ºa¥ìtú³·â7Þ s&ï2_ I‚È]#wî•€Ö`q´Âùv@©ÜSТ…0¡e rà‚#ò’Ž«b±wbÇFÓ wµ–dAù½§Ãþ~ˆ[U)snDèDCRthä“õZ‡ñ½‚dŒ£]GDB[~?iLd@Q»Ä¤à˜Ã5A0GXb, –„!\Õc;!P ­­òܺÕÎÂAv`Ÿ®"ÔZá«-µeCßQ釥k³*F¤jXÆ0sdÜúòW‰v³;uŒ ²Œ“KJ ®`¤¸st}wní€ð¹*fuò˜è7ÚisÀ7n-®u—¸¢àLþÓ‡íwféܦ{å¼}x‚_Yò•Ãʦ˜3ûX+I].T¯¹Ç§_?"ý=KZÖÇ*çÔ´)`RŒî`¤´€IK„Ξ Ž 'û<>>øð“ÕšÐÅJ¨ ÏŽŠTàÔü’›ä«*ùƒgÇÇn!zë†J°yÀmKZˆPA ßh©QHlQE”> vÕÐuަjŠšrMõú«ì¾³œ³Ÿš¦%¼"X=[VûÒ¶w˜Ü»ŸÝÞ"ï?”߽Ą ™æ¹Ö;óÌ’\WµNõð!þÙWÔPÕÌ}Z),†IvÛ¤}SµÛ·¢ ÊP a.×@¹bO=i½ò˜wX¯­²˜ƒ€´|ô@P+öæwÕ.†Æ€œÚ6·åÝ;âÚ5o»my–¦–î0Ü1ƒðȨ ¢H`,0ÒÈ( <@]$d¤Ah üb#Jµ9× ¦žP,¦ìÉþZœî!h+É»€sp,%<~&{ò¨95Vj ÎNI Æ@úNÒàâ¤kšdª¯o+J"“Ùe“çX¶€'Ú²‚¢D9è ¶Í$“¸¬Lj(I Sa@jÈ bfZQd7·ý÷ôv‡ùýhÏXR³pº%WcºJUy&w¼ðîœÙ‘ÂB¢a1*Ì̈ùì+ èüª`G–Öग़€AUH8§¦ë ›‡¸ ÂMKìè TŸöfÛÞ¦–ž, X\ï-ç@À ý§Ó·ïÛ³JEðÙG¼#SÝ+K㚪 ²=„‚P¯X}Å}䈱KÀ×ÈÛo‰ÁØQôÿðœQ·§UˆIA2 ÐDHJUä(=I…ÀôØiÿx¿>8NÙPq÷rsC©\«$z€æÃXUtØW¨›¤ÙQé¾Ï?{ÒìuRß«Ìݱ£æ²5áDIíÙ&ƒš€¹çhÎ-0À0tÄdC’!Y)‹N_ÝÖRó:0¤O“Øu /îLgfÔš[`7×ñû‹ø;—ÛÚ¸\؉ÌwÚ¶PºY&&Žò/¿Lyï Vëc–¸/ÛÉ¡[·»X“p ¶"2·‘)”|òqïåÇHÜÖq‡#”G\q(£.ðjñý Õ¢PëSS{LBу®™»­oê­ïJD”pTÂin]Ã{F¦ÿ§g‰‘Á 50‚•1Ä!J ­•q¨£,%XKŒ &8hÙò Òp–Yl+†C¦»®%ÓÿÄqyñ0%ÿׯð½SêôÁÅÑj¥WøäØ •½–X+ÒͰ¶@N ¹{C I¯—(%ý´®bßË}N8R9F!0ÈA˜ÁAå ˜Ëå0å*•œÙD§©él‹_^5q·¸÷w§B:Î'ÐÝÊýÕf Pǫ̈:}¡òÌóxÏ`2wÍ^Zwšˆ+ ¶ò8`eI‡ Çà—%¥ßh%d_6|xÅûñ·œÍ5í5š#¶…KPÀ•ÜLXÝ÷.*~ýóÇéÌÿß_lj«Ìí¤Te¾[¹egýQV¸Ý~g¨"n/¡æUwÒ°mœuˆˆQR{bÃN Øt%Ê-j ¢ê C.pÕRE'å×cª¢œ,¶Å _ÀN©µ˜Ü¼TêˆÂô¡vGDs¹=sŽŽ—o@xD-c(ÖR)A–”¼Ï?wª;0ãTª½Ý4I|抋ƒãµ}'{YVÐÒ¨õÆûþøi¾»%PŠ‹H*”î`½ …ž!šö"P62[JhŒ£BÐn–¾ÆmH‡ bf¼è;DŽ…¥¥Ë1R¾ÖÉŒ®ZmŸò'÷³øùÊÙ~t8œèî›ä§y­wI¨,&†ÄNAÒµˆ.‚mciI13ì ‘éôâT)TIÅU¸2à„ƒA@ ‘‡)F*ÉÈ M€£¤1 ¼,“­Ýô—!mãǤ5Ø“lÏQ»µ]™}ØŒ”Te´–Ÿ¢ôüKtª?^ºã=XÖmLkª=  -íä)üòc4¬©››9Ôãg¼÷oáïÿØ\A•zÉ‹w”CÓÐB¶CÃí?wD}ã<ú£ÇèáIõÿý)X$}|²qg«kîZ¥;v>ž)ºnÁÉî­¢Ö RæÛ(kÿÏJÅÀN"èÙÒ Hg¶œrÐ#ÌIJè âF-î~ÿÝv­eÝJÿo- 6ˆ µà»yözΜÀ룰Ñk “]Ýðv¯‹q##bZZajÛD˜50KL¨ ®špaœ‹~€•ž㨯OÏm6zßÊ6¢Îß»²€]#¢ä³{Ã^o{i5ü'/á/Ÿ¥“™MËyf­5£‚d#Úh›ä¶ßï ã£={)Øe0º_¶!z(ľcþظ{éV¯«hdS­k©€0m*Æ9Þïœ?ÛÜgWFÜÞnLj¹y€Õ±ê3YìCý°S¥o~þùÏxg…‹9T =UjjÙÝLqÚ‘¥1Pl´g<¿LRž`K‡!e™ &õÁ‘°V"À‘ï—yž=¡«F¥Ë0¹N;.²Û'þÑ—œó‡££c”¼|¨ %ÍLÐ;Kh—+"ãiKõl}© bÙZ>sÐýýÏÓÏ>’žœÊ¾xbbl$ÍZÝprÇLr}ZK‡@ˆ‰Ò`@c6Š ãz(c ¤žbˆ(]°@ûT㯭GwnÛ õöN¢£ýÅÍv÷›b‚WŸÏ;^i}„æßd®_nfÝû‹Âu„s–¢¹!ÊÚ%òÑG’=ûM¼¯o±ã½ûFïýYÎ=ãp„ÎûkåÕ–\ßÉlcªv¿ãÄ¿÷9øÝÃv™v eño~\¼Õ‰ÿø™Ò7ϯ7ùF„Ì0ÐGÈêA²;Y\}7‰ `gC‚ŒšJ§cŒöIäïÈÒ¶aMäX¡3ÎðYäï—yDƒâ¸)Œ±_Ü êï£Ì1߇œ!§ú~Šíâ¬t®Bj¹ÍÜ»tÞý•µ¼Þ%Ø«‘‚½Nü ”§Œà`„Äii#@ tð(EHŸ2Fî‚+uѰìØý­§ËðLíÈþgNª =•²åmÚ…†´X=Œ@Á- ±öTÔ¼júK•³œekR¢Ñþizg¶…À¼³×1 ÑW´Ør|¤ØÓûÝÿêËî+g»çö°/œâ,§k[Fö)™äp1ƒ±ÖZƒ"Æ ¬ðlÌ2e 7E"Ò`0¢ÆøXy$\ÛˆoÞ¢=lï‡ÃÅN'yÿÁ¥gžè<ÿèÀÖÙü¬X^mo/¬(ãø™àl…AÒ“Ú²äÙG“cÓ~ó@é^bÞ}+úäŽ6ȳU†Ëê_|­²Ñ–ë;Ò6ªâ„ž ¿ûú;‡YŸ—ÊâßüØ»¾•ÿÑÓÅ_:¹¾Íw{¶R9!ö#ްö Ê÷=øEw kÛ6ü?=wQ>)€ümY^qò]ðBßÝŸ’Ǥwа¶S “zhB¼;ë“÷uŒý¿K;Úrc1nõ¤s½èK£WIr ¹¥ |·âòæ*Õ³h¸ÅL£¤@*g@}CÖ¯ú™Ð¤nìCÊ~R9SZu=]Ö¥Õ^¯Ù(÷¾Å:iðƒ0Ž`œý{Õ¿übZ í׳mÿñÉŸÙã6ÆØâ4t]è$7úÈ^÷O>_¾> y/Ù¶²[‹r}^á±ÊøÓ…³‡“Dt>¼Ó±%K¤€à L•D9«Âà‡¡¡Éž|¡2Зv– Íà‰CâØd°Û—î¡wÞ Ëë]J|Çp®iG»[†· äÀÀ¤ ø6Š" th›1Ð'"zº EÃäúèþýÿê…àø¾îÅ“úÌ>Û¸³˜¥tD"V/ôwtÒsõTÙüá«Ðç¥X‘,WäÅã ä"XÝ#åþ·.Gð(Ø"½{œ*íõ…§ýPäе0+°ls`JÍì­t7³µ&VÊ©(vÚ£B[–‰tAs0ҀьU°(ۘб,dC"E*ÃÚ3ÐÒYÙJîÜaËwM›ðÒ ûy58²ßû?·†Öy³Ù<7ƒÎÂÃåqŠ X®¶QÛýÚ ‚úà„ÿÁÏó￞,>¤Å–‚. €ÓcäÔÖ#‡lî®äßro¯ò°–5ö¢¿xÓúÉ•àÜ0ûݧq/e'Ï’÷ œI©=â^‚ΈÂjÞÖ±b©Ž&ßqØ¢2˜TèŒê] ß5*5\2ºMEE)¢3~"÷uß•ïíQµmÚ»ÎÀ"EÅ“vôN²¬PKväݸ²Ôªïo¬©ÜÎV|Ëi’4cX7ÁÚBlÆÞ´Ì’ ƒkY“ùVz©¸›±ïº‘£\Î93ÓWøÇ¿% 2GéõÑB1ÇêàIsm¾ùó®Å¤É%ójÏ?¥~çbÒt}¥0×IWL‰Ë<0ran_6ñv†êÁÒâ•Ë\Ûܲ)¸T™²4Ès÷p6ïF{ÚÌoë{+ñk_8s€íZ~Þfï¾Åßø ]YçHÔÊr)VˆVF8å`ö 躥Sám¤ÑDM¿…`}@šF@ïf°««Ä$îU¿ñùÆD_K¶;F–!Òá'O”¬0¹ºÇ U\…µ{O%BÊßûÌè¢d¹’V1éºL4ÀXòz€Jƒo^êc&Èð¶ÝâÄàä«Ïé¯^ ÊZÊ]@"drkpÒìÛWëìô6šX¨J²Ó¡†ˆê!ôRŒÆNˆ„Ò¦6FØI¥Ȩ¦œ;” ×¶“[×øƒÛ"A²4^ø½Ù±Cá‡ßin°>¤n¶..¯•ë$`,äR›”„]Ë+4ú¦¼Öúñjå,ß2ºmŸXGöÙC­ GŒƒ{K.°žï [«qP‘}{ ñ.ÿáåàÌýýg¡—%ÇN£…ÙÚv7VF•¼ÂGd·Ÿ™ü¶A©Ü£ñ.ÈŽ&ßqÙCe„6©PÑMŠæ¸LŒÈoRrÝ%©\•ʃyC—>ø»î1ÑÈM:k$ÆÆ"îšm‚òLzÒÃ"?,Ä~è¿õpkx¼ºfµÑM¾†à{6î*ˆ³$G¢cÑU[R§Iƒ:Hßµ²:¶¥nsЋÎN–׋QäBè‰>õg¿‰HD  kú½EÚáêÔ¹ðúbï/~"­”hñ0xî ÿ·žâÝÝ\wæšxEƒ”Ú°°¨¯š¥ª‡\'2e¤ã"gÈ ÷í/mß§›Øk‹»Õk_lœ?ˆw-;o³ßÓ?/YÛä }Js¦xËrºJwµ´¢H»6•M3b¤–FKd€˜> `u@AÃõîetG—°ÙydoöŸ¯N6"ÕI ¯@llœ;:Evm®)¨:ÚÎK÷´Éýƒ/†ûk©ÓJ·‡Iõšö v9A©²ÝüÎB¹•F–·9ttùÜÞÒïo3rç>Ûhçmn¨Íµ„®Ñ©ƒ¹Î»¿HJr|ÚZ݆n¤e®¯nZѶý£»Œ ù/¿N<’­&Áùò•{¨Å0ÁS%¥¾çê‘8Q`{›:ï Î Òq›\;ƵlÊöÁé!1šNP.Þ‘¶±@JKË¢…5,¥Å2Á¨¶)¶ž5î¸Æ±¥û¸YßΰÂþ] ä-e 0ާ ·—„|Àp¢eŠôê€IJXJ³ï[R3@HQâKí¸D:>¶H‘Æ3“¥]“+ÝDnÃ÷>è‚dž[ÐÏ>ž[ö­ËJFquiAeV軀0†$Ñ|';wy–ê~Ÿq¦µTÁK¢¡%Øá ÇQ¹ØPg¯Ù#W;ìöýÂ'³ÞZ7 µñt­à¡4‘\„Ƶ¸N…T¾’Bºš!%BK; €* ]è ²dÛ„øÉï¿Vªlowµ]ÖþŽ_qvÚ¢LÑÞþúvV¶4‘JXþ–€ñzõµs[TòØ1[+å+›-_ãÞ`J±IŒð;s•v’Ú^¶ËtW—™.þ£‹,v»L—ú=æôDPíFiÝ÷†7ä-‰+¡Æ„‚\ÓfÕ@‚ñ,l¤LƒEJ!)J)ÅÀf ¹L†©—oñ€`Ýg˜…`‰{³»>•bz,«—ñÒ‚È7y£vF;Ÿ,ÄÆ¸à!À<+‚êóY—‘»÷Ò‡-™)é ”›>KµÎîá¸Pz÷çY)ŸØc¯mº(9\Ù :+ðÓœeê¿ÿu§ìu—ºÞÃûý—ïg=NµÑØÒ"S³e2ÚË÷ÜѼ@ê¼Ã3È`â$ l mC,i+»¬®ÓP”õÂÕØÒ Å.ÔïЂÉ)Ïrs§h0¨PÑ0èf/rL7ñª«¯ hK$žÁ¹½l”ÑÆÃ$=cûƒJsŸ…½”°ï[Bç€(£6VÒò‰îÇu¯äø¨75áýôN¶Ü”zW~ï„»ˆ LCóüãdÄ2×>͸ç&’Ý\dŠøŽ.œ!_eÜ´zæÖ]Gz¨çŒ 6Îe@è–ÔGÆ}[ElM¬Ü=dt_¾ÚNîÌ?™õ6ãÜ—* Ð¥á¢2•)/ ×€æD) ph;™8SHçÖ6À À•¤)t¤\u MPÃVò‡/ Uw·{Ò©ÖÝ jîN‡[‚Ù;±²-V·µ#5sÕºàâ+§¤Åeâ›­ÿê_aòe[.uÉø9L˜t=ýѽtA‡WrèOÐÆkêÃa;‰–gÞùÑúì»U@½=ƒ ±ôWïuº Û¢.#:›wJó 6 B2]÷ú«–íéLxLF9dÊd;ZK Ï0¥-ä ˆg›Ä§8!2Ÿ¥I+óVM첉Så¤Të…½sOÒl[_Z‚ËÖ}\÷»pò€÷ø ÒªÚs÷ã-I#'È„Ÿ‹PÚ‡=Og{ÎÕ~î mÆ[÷ì±3rï117ëHdÊ=k®E·ã𿨇ëòoÞ÷þæWð³»m+ÈFöX»[CNÕÜšµ¥öŒ™fEªUw%ÊVžÑ&Wš¥ û‰Þuà ˜«Ä“¹*x¯co&‰§þ£Ëßç¶ÔIËÍ‚šce$Ž‘ÿ¨ûV¾hË[tsm-îJÓ#¶²½IÌ!4q@ñocN•Çîˆ!"ŸÂÌÏq‹JI©aÂÙwĤLþüzrõ.lgøÀD¾§n¿u­ÜÞ²™Û#Yè¢o|êZrù»º¯«n/p¼¸y+©€—ëvK‰©¥¶g2„>õ„÷ô“È–¾ìæDð6VE6XgäÜÓæa®ÌDiâlðÎOÝoþ*€ÝÝ>‘‡ÆlyCMiY°‘– )H¥ ¶C7‘™LF±=Ö§Çê~ݳA± ™",Ë Ç¤˜ÕIÇcÇÇ᥃uõ NíÁíÞÇ?)¬o²ñ}Ã8iz,ÎÝê{÷#Õ&—)ΆÃôÅ“®”VºW¬öð¸É…¶=|Zc¦‚À|r7^M W:ºÌÉÎgÎë“ÅnöGÞÿåîìU£óÉÁPîäåñÙnk~—W>høÃ0œçfËP@dÐ'S5§¿j{$Üg²—C¤,m,”M$óQ– '°IGç[à"+ìqUfQ¢Þ¸YL×ã#ûºßs³³OV¢5ts ÷²¨©(Yñáð!ïɤU±—î'…[v¡%œL+—Dýš]XzC­ÂÖ={ì\¼çˆ˜¿W”˜WzäÁ.ÞIÂ?¾ˆkÙ·>†¿|Ýùå½–Wɧ¬Ö¶eLæX®ŠÑ¬M,>1eZe¥VmÜ“(3Z¸r€)EŒå3€ÔŽWLLêhùÆ(|Ð#3ë\;øoñ͘ˆ–k\°©+?&L¡Ôæò=p¯Ø½½Dv̇-œ»e‘ßӥƀ5hK) &n|Ò¥MÅÁèdM+9¡d"Ô%˜xí:Úà 69+Náë×›7—ÄJMöåGƒw®5:ÛÝFâDH¸þÚ¯©†k-}Û”[òÞJ=yþlúGO¯ž×Çö‘‹éÑñ|«Ûhu˜¦E,c”O A\¢˜ÑƒÍRœµˆ-$ u­ìÊ:^Z¢÷ÆçOÊJmàÓE¼¸š„Æô‡äà1ôì…§Ðñjþé{x1¦£LqMS¬êÌx%+ê÷ÔØ4Å×ù¸Ã;ÌÂEûéóìð¡âÕûI®¤«œÐt{þ«_Š+-AQøûgÅ /T~þn·A¼ÑFq½«ŠVÎŒ^ òu$ 6ìÏÌqPç]¡â® ÊD›S´>…®ÐsXN*¸ö·÷¯ë5|lp  `c˜¢æ· 8¡ý(íM¸‹Ô^ã inŽÈmÖÊ:}REžpTW|°3—20eª€áEö)9gë×®xŒ jËÔ@°·fW{«Ùûƒ_«>â¨kÛî§Ù;—L¤B¯½SÂ:ÃiX1öÛÕCýûŸº|y²• wF·–x¬é®²)ØEF+ËãX£%^~BNøý¾)𬅑P>þAtæ`yd(ÙIàÛ?EW–³"î9Êݲnã6ê€Ñ`—ØõI†)QTaªY $ f†JúRò•GªçgòÇ5•‹Aoe‹¤–h¾_ª pw¥|áÌ ]Í5K/¿Ž5“ÞZInºÃBeï] R—»4aÄ/âɽާRpÜ8»s…-éUeS#VÈx…ŸÞcí,, nŽS¢j¯œOú|¹°¶Õ‹Þ(îv?ÝãûóÜßΛ]qiŽ”µ…ÂÛ(ꨂo³—ÎË?º¾tšž9fž:'Æòí^©Ó¦Šb¸–ŽçÈ[ZHȀǜï(`Æ 4 izsË™½¯f¦’ çU¥Qûp>_ÉBDª®9~Òyê´÷™Ó¥á0ºþ1¹×2»‰ŽÁfp¢pÉÏêLL—Ìíí>%3c1O0&RzWIibúÑ™ýÑ‘x7±¿ó:¾º$K$²”³ tݱ:VˆL9¦8±|e€ŠìÀ˜oü³çš_¼|tŸ~öœ¹°Ï-Ó%§£í-;:$膥¶9~f¿9´7Ýæ%%Û—fövzb£&ª›Þ¤…±t%ŒUÝîÚNT?T­»¾¼ª‰<‰Å•ăÔ_~7#=S-ÈŽ%IŽäÁ½âŸüz8V¢oÜä{µøì쑃ˆ;öíÍ’ìä!ºXII±ƒ’t¹Ø_SR/m³â‘ÆùCÎ'gKsÖÿ³góû¢ëç¿X„ß}ÊùúgvW·Íü6-X%;Î"Õ¸*±æcJž¤Ö´Lz½)-©AºGŒ¼`¼S"ÝW컑'û5{Cëþ×\Ìaݳ¹þ/픪" ä÷ Wˆ6©ÃÑ…Ê=5mïÛ[¼;Û:`9O:•ëßð%UiÔQÌN¢t¿ø6Ütõ÷Ú–•²nRE#Låÿä×¼Ñ2}ó¶™Òݯ^‡@N/í ØÄ61S/‰y‡Y™P0XÞ…#µs­ëWè’j%†#ð,šJC%Q®²GôðHù¿ê´¯¥C ëɗШ]ßXîí•9"ÿÅ3eªZR=0‹FE€” wá`I50ÄŤ)Ž È€Ï±Î°ßÿ*Sœõ FôdYééQT Ÿ<Æ0å˜5dRjö÷[‡Ç ¥.×táÆ ŸÓ¦ÊLÞ)óÔîÁä—wÊž‚úÃI/;´Ç¬Ëˆ±¾©R8Ô&¿ùE‡u#Bb ~û}µ¼A÷;I{kªÑq:ã}­3% ÇQqŒÄ´sæqíV›T‚šþÁ•d¹£éÕÌË%yù‚úÜ™T÷¨¶”kmË ,´,Ùq£„ß¾…¥45$NPoH‰Aä–Ã$"’% eK` 6sÊ‘œ(ƒh9_/vô¥/õ}ýôN«CnÿP=fê¹ë¥ÚÞ [)GÒ–²=.b[‰AÆñÉó‰·ßâÐ:£¯°öÁÇhs-dY>³ßíÏvJC2òlu`žHîÉÁÿåu1à×/žˆ‰xá@ð`=P‰âÚóy*éšPŠ’ RÌã%,ì(§p’“ŠC[&_Ф|°þäE}§g³nUËAm †²Æ9PxWËEÈ3„ÊÒ»‚ùy £ 45œ9imµñÖzb!ÑÆv É2 S×=ݳUÚPàï¤ùî3êz¤*+ ½'¦JÿÃW a3éÍÙw×õ…ýt”𵬻¢]žqT:v˜—káæJ¶¾Q¼zG=Xî–êÕуO6+vroQƢ̤Ú`×q¸ñÀS¹©V|ƒ·íƒÔÜ]Îö ?{¦ëL¾õ1{÷‚#ÒWÃëR.'FJ[eM¨A Gø„¶"Yµ`Qèž¶\Ëúã—ùD#‰BY³K.¡6åØï=ܾþP˜Ê)§¹kÌ–r¶Ží)û2qÚ²ëeKv¢Ð‚Ôüöûj~£ü€ï¨B›Æã}½³eõÚ¥ ùb×vO>ÍýrÓ7Ž%FrS,íJ‡êÅÌÍUá¹3Ñ—/hÑ“ í+옰èb‘Åõ@ Ö¬wïÛY®JŸ hJ;Ĭ[:Sk‹(, ÒTj­ðFN8ÒÓ5ÈvðÇ×˽œ~î³åß8³»Ý¦³?ãçŒE½ì×Ö²Œn2ެ=i¹ˆÙpatˆœ:Ÿ{;Åþƒ«ûÉ{ÛodïìÔÒC#¥½SíRXäÑQ85ÒZφÿÕÏ Ÿ^8ŸzådøpÉžK‹D7f5÷6 £«˜¡>!‘­…5| ‹cFIc· _diõ@é©‹öõž‘³yQAÃ6PÕ^Œ,A ­Ó%àZJü=ʪƒ8°W˜ˆÝCOŸ­¬$Ùö óAD`*vÑ!8ë,IÏqOiÿNÿ*׸“ÑB»)"i!|j¤ô?~•–ä†ÍÎ5Þ^‚£Ç¬}:[jg\ÍeÛ)9˜Ôû*ËÙÖ–ûémü`©[nÔL]l•hvçaÒË€ÈVÈr$/‘R¿JhhcEŠ7ƒã8½³"G×?{tËŸ˜zëãü½(Šp_ ¯K±œ)ld” Ú d0F¤“Ÿ4î Æ5£7uÞÔÁèO_‘Óõœ1.«m‡È¥žæ<Ñ{“äÖC{]%µr’Y/Ûõ–Ý + ˜ydñ#G•ÛM< —7Ö/ÏʪœvZ©6Œ'Á>´§ä‰HEÙÀ€M¾~Œ „GÖ_þ²ó‹ë޽¯˜×¸•i½¤t¦íG ÞŠ™ƒ™£™Ã= å>RÛ úÏö2æí±x4øê·Ï †M¥©ÆYúÎ;Ùý˹cÑr¡²ÍÓÉ‘ÒÍ;îV‚ˆ-Ž ZTÛfSé]$¡ ­À€¢”P'‘N'·mÈjNÒŠøµy›Èà@¸|š–y>}ªpNÎGˆBV€0VÝb1èa&ˆ¹úåâO®uî/õš]ƒƒ‡ì`˜¥û츑±©K+@Y?ž¹˜‡¨+;Þµª ÷S×ô¡í¶µc”IÏ,°…ã€_"𤄃FY€´«pÍmYu¹¶jœÔ!J¤ŠÖ1eFÞ»”ÿ2滾‡¨0±‹€Òy&’VGÜdï¬åÑ­]¦ðH3jýð £A13øO^ôS¤Þçš*aóvÖV㻢¹Ù\šÚJ7Ø]OBÚE‹'ºqÀ¤pj®<9Uº}w'±‰v Ó[oÌzßþ)Oš½ a]#–3š¨±†bWƒP†¶en´¤Ú°P ”’ábhGÒìo௾>læUß[Zuß{#ï-æýã€lÄ0¾<+5¡o²ânÙÏûI˜9žÔH¦Â69Óþv¶ÓT‡¯b[zr‹Ù·PÆ[ö»U¨®Ö×JvN¬¿|£û‹+”:æÌb-i/SÁcG‡5ßM„×ûe íšÅ(“Mãþ»7vQšPyË6ÈE¿}Öô;Ž4^’‰wÞcw?Î\ÕÊÅžô•î<Àk=é»ÖAe:*7•l! ‘â(EH‹DSåtR—«9I§Ë®ÎÙ²HúûJëäz‚×M>v$˜_Ît±…x`¼Hµ eÕ/à2n¤BÿâòƒKÉ­ÅN’r%69aì‰Çñ¯ŸC·¶E»i+ãß_‹‘Wü¸Eo-7?s]D@å=V]vtº|ëîvî”§žôyß|÷g*Þí•IþÿçiPˆPªs ÊÔÙkãP¥–ñg-YdOÙ|íÉp7ÉmZ^[+|ðfÔ^ÌFÀXÊ92æ£Y¢p~„º»™f–µ§Ñœlp•õì§{õ2¨!¤Rwìo>;|Ÿ†a¥r_­rëá6âéîÑ=nÝ£ydᄒ|#ýxYveµŽ»ÆKÃvE,µÛ’.k›©Pà´-}jÂB°”…ÿ¯ì.uÈa䜬ÛiŽÀ|á,Û£ìÎ]»wÕ=¾ã-îÂÀA_WÒ g­µåÄ—•ý8ޱsOèpYÁ×À´‡T¥´ ÑD ”²± $•Ø"6 *ÿè69÷l¥gµž«W¶ßy7Ø¢q,iÜ:άœq>¸·öp-¿uS”[€²s¢uXµðÙ i¹O:\ÙMåÝ5‚³°ÜþxŽU9ú“/èDÿ¯?,ûf«?ð?{Ö»9cý&ÉM$„h^òëšsjÚR22€ßBfÏsœǢTÀ&F›W¥Mu ÷CÌ„!Æðe°»Z' ›V|§ZaÜÓ´ôXÚ¨ZƒC(s‡×î¶FfZV±êHtÙÀAÌJIIú^Æäè€îõàëÕ&yýv÷ÁÃÊÔ„™—>ô¯,owç- fGÑ3Ç­o|É&¤—j~ÿ–Ó–åDZ6qHÀ@Ú……{|'ç#ï´ Éꌶ7À64çÉ'wû&iØ;ðÄÀ/?ˆÿî­®§.]K—b ÚnZ$Ã[Ô:t‰Ëu¦(¿¤8ÕZ{Û&ýi=>©YiÀlYzÿÛ탥d7è9éÄ8¶p…É›—{™Ÿ/ eY¶N͵¹ôü±FÝË™Ö(6.q± \§ðÖ޸/À2“®;˜¹?KržÑÊÝÍøÚ¼è1'!¥ ~xóÉÇsÆ¥¥Ó>æ€ÇÂv/HÓì&žÜ=ºgõ°NÛÊötÙ 7dé_ýÝævDk|¾è\I3þ•Gm™€z÷fqë£ðT›Ìoó¡C!×5Ûyc›M}îÄîK¼jc€ÕµP¬©÷ª™áªÅþ‡w;L' £7Ü0ä Ç, cÛÊEî9xOEïtõWžr6·ÝïͯԦFñáaþÞeïúÂng¾`a²øéSê×>o#`¹ÉïÞ°z| §Œ žU’L©4Æ ÷Ó͘ŒîQªËT’õÛ@ oÕHƒ;/½ôÌÎØteËO÷Ÿo¼÷Qó»ï&®0¤tÝ-]ŽÒVë¿xÆÄ–:pmŸë,À~Ir*•=ìÊ|^×{n÷¸9ÙoË á©wå{½‰uWnÙ»žŸÀñt…|p9K¹yÁ)Pæ{°“œ¤c•þD4uBd9¶cûá÷Þ\ûÙ-®ì© áÔó}K‘Yå{ñí9ÙNâTɇ÷âË h;/( D´¦- ræåõØm„®/ÃŒ *+ºÜÓ^«n û†\HûÜ<{Œæ(e÷캇êŸ;×Î1O-wÜÖBKÙ+ãÉc]é>¬?ZÉïmÁ¸ FßÀtÖâ‘£Œq€P 0eqj#® R² -fdS³ TfÁÊ6~°Ð|þQØ;.6’â»WÛ¯d¶ª£}£ðÔñÚk/»ããèÚ•6PØõDXMΘ‘¡cKh7†øÙCåwþ6_¸Œž˜)ËR¯¹fÕ´0.Þ7 ¥ÿ»ïZ«‘õüAûÏ^·n§bøŸ¿TÛ[¼ØRŒf‘iÝ0¦ D{²a¼ _w+©Ú¤ÊŠTVnÇ  b¼2F!GS{‘2KÉ¢‚ãK¤}Iwmkú°æÁÝñR‹ŠU]!îM;»"賊MFŠ =‰Qép_z¾ò¥Ãæû³¨ð/¿Úhu䫿ˆE ±MOFjMΟvŸÞ«¯þmñÎÝxò@ãÖfo7Il+lËv‹”µD;%7EJ~ý ÎÅóá`¡ !iK‘h{PÚ’ÆGOX‡Gc™ÿðw­¥e¿Ïäó% [“Y)E%ƩܖH(¢±¡Zc¤$†ïx’P{”ÊU7µ™&ç‡9—F+²¹Æi›'Ž 'KN'‘…Ò}ì@€¦»A‡ßgªcí¹t+r v«‚q“fWýWïé_V`¡ bOªšÂ§; ×y¬LÐêù·²÷oEWnE—Èvæ°ˆêŒ9ÐpiÎòRZíQÝÁèú²šM,\KžpeØ!ò½ëúß¿ƒZ¥Pêó&ÁŒß¦û_|$5g–‰ºxg6v4kÍØ¡2>ìñWð­55¬ù˜;´0ç°®0JPÊÅ–«meE˜& ‘)=……6»:OÀT†0,ï˜ûóÑ‹O˜½cx‹Þ¹š„y)‚ F3ãøé“ÕϽâNLЫ—º»Ë‚2ä´%ó¡nZ©‹óû'Þøngý#túh¹ÑîqAøš+#IÿÅ·òÕ¼ôô^럾Æ/=0÷vóÿǯUkczkCt2d„íq ­º¬Ë›EÔÇéÁ"v2“9®ã,Ý$u¥c¢ L #5Õ'4m ˜õxÈ¥«à!Hk‚¬.µÆÚJx÷néÕ¤ë²L«wÜø¶ðÞwt×RyÒÉ a£.|éñàË'É÷çTÑ ÿþknÂß[Å?þHÔ("ÔÏc5 YjÌéÓ΋“ðηÅ[ÙØ¡Û۽݈[nª¸+©«™Šn’g쟷>ûÌð`*è5EkgD¢''Žâ#ƒØî_|¯µ±ˆ Ji"—$l d µL®–a¢ ÕX‚-BFdÊAôAH¥!²]0;JìÁOM‹Nʤa­M#ZGÊß[u¢¼›+›¿ñ‰ÏiaÞ® µB­->xm!"ûµ¼ ^—äŸöôŸ¿~zE‚mM |(® ÔÖ>íi½‘LJ;™û¡¼z«E… Hbi-˜Oí—n$Y·$Y¼%™m¼¼¡nÝõÞ¿d¿ù¿ñúè~¶klˆ›§5*MX¼’l犟œ* ˜Ì‘µ WïÖ 3âÁªÁ= ¥ð›—yÜ5©¤7u–Aíа|iþ™Gì'‘©jJ)ZézÒGV 1 mkÛx9Û 2‘*Á »|y ©ŒÓon]áåzålvîÄ +ÅhѪ7’å…haž¬pHHj@ßÇH”¤ KzÿÁBû=´¤‡XõNÒ|úU¼µë>l–Gd´°_.1‰¾øhö_¿ÈÒvùß½)K5ûó‡;{ûå…±ÑÕíN§Ó#QËF2¡EµÆJ7ir“‰~] ªÝû°öEõLU!ªQˆiÙà0UKOTÀPlöj|ð8r¥)6í–Ø¹÷®£lEí ÂD÷*À:Ü0A9"VnÉÜ1èØ`ðß|¦¾x§Œ½÷WKó ½Ïñ/èHÂlêë+ˆ6Ó’1mS›®}á »÷~PŠãÂŽ?»m¼iÜi ”¢ØÚñ´`ŒÆLB£±*P¨GŒ1'ÏôO×[í]"œ8Z~ï’þÞJÝ—%"¼¦â Õ÷÷å/䯧Ò½X³ÒuM@h‚£%QàHÛ¸ìM-,kº'"e䇗 =S¥­;WpX䯜æçNz:)A½/Zš‹ç„Ë‚0ÛH¡€(1}–6V¾÷€•Ý5C yE÷=ÜŽý]Ý‘;ͰlÒf;{¡FÂîó§Òÿæ5A¢àßýˆñ‹G»{ûÔ£“íí¤ÛpC’†”ã­¼xݤ7”êGw!îÜ3Û+¬µ,iû«ºr« +•l3#µ‡¥G`FÒÃc`!£]ƒ#Í6´?åÍН“mSøï]µŽ Äê–/‘ЉP‡ëôŸ¿Ú82Ö 烇•…‡ÝÏwßß` ÛòÒ2Á­dPèMlOOÖ>ÿÙöÕŸMïv®uwƒ²Ö6–ÆÄhÛAÀ21F.ÊF¹“ogž];óHi²ÒÊ¢¢ÔùÄ¡Â{WÈþ¾š™(Enb†–QL %XkKS¡1Hs,#ƒóò…#éËØÎÀD˜+l¯õÊ-Öv‘­H$M±¾pŒèHÕë6êã+Â/O«ƒ§õ¡d[Ë+öOn¥Te§BßÚ¢|#ç]w¤Ÿ\ñÞyˆßøÀ{÷&z¸Ê<Š|$ŒÐøZ9¸Ü5VLçà£sÐÑ4„ke\S4:é˜ ü`³—®db¨âiË.8œÅL¨œõˆô,b2vÊ)MIØþzŒ’ *W™ynHZ½RÙž¨pNoÃà€õÖCûï?á¶ÄÒXËåvx~²ûÇÏúí‘•jX)©#còì!Ï·øü­,bšI$0‰”m¦wÁ¦66“×ËÏ]L÷5s¨Ïzð®ÈnÁÆl….m|z·Ãq™Û‘™Æˆ Ôg°ÈÕÙ3á`r'*ýÅ™Ãé³GìùVëNË/cBQüÚ©Ò×_¶q—¿1Ëßžs/ŒNï)qÐÞ‡ïßJ†«}(íõ\.íb9:£4tæX2kô‚ë'‰ìõXÝX)RiNø€G > HC[#J+T%´äXÜiL iŽÔl›>dêZnåêåQàc¡È$ó¥O2ž@Á@ÿl³9Qq÷ôçÔÑ›Þ͵ÂP5;ÐGŽT­¨¼²…„4i0s ÷Ͼœc&d]hÂëÃE{ß½œyÆïh¦Á-ŒXÈâ\MÏŒu·ØÒÏ{°â£ÿÿùfç™'z¿'½ñäs* @!g€ 0“M²ÓLO‡éé ÝÓ3+i¼öXöeÉöxW+iw­]­×Þµ.I+G;š<»Ù™ÍÐL H$"P@å\uò{Þô¤Ÿ?̵kÿ÷ç[ÙO>ož;Ÿ›P|ëÛ´½1 Ê—‰`=ÕÒÈSm­5LÍ0J‹~ã‚üý¼“º²©‚{~LžÞ]èDÝù¸´•§h¶s{pïÐF¾½‘Ô÷É`dwj”*7™ï¨ýK²Ñó§˜tòÌ%f7Ñè–µÖ)vˆêåi’›L+_˜61ÊÔw–˜^Ï5 YÚãh,©j‘µ[0À5“`зE´IRkQºZ°‰vމA”dš*i·³AÄPàÆ>d½SŽÍ-ÙÌ}EÒ”Å4ýänNû:5pdŸ)OW†ÝA¿iƆë﯉ï^J=e W@f;7ÿÁóÞóG¡R Ë%}|yäWìýÛ(©Ê1àZI5*„Xš˜6/(nJe-,ª™ûâé'à>§OMÚïâlíNÜ÷=^»z·i\)â4 ˆÂ ë&yþÄ…©j›Ê­ÕQØž:•âXð êÏn†!·@¿rªøµW8mÉŸ/É_,á{Ò û R|F|çvR« ‘4„AÏW}×…ˆP1(…dwÍZ@âÛé‘‘ÆjaàØšp÷vR‘ªÀâqɪ®;ÄœØÊ7¹5’˜ûmþ wÞ ²;™œGÓ )—!·ÝܸÆws„²¢Õ‘áÙv¢æì“"P;›Ñ­õ°>Òß_ÁÓÇ*A>XÒ¡7À;{ÿð ™³¾Ô5ëÚanqX‡äeY0c3Öß¡LeÎät5i±·R\¡ƒ–úÌ+öÂ#Z¸æß÷¶Ös_÷R'Hå–´ 9ÕÆ¢a!ãH$þúSø;/ˆÃS*,ŠÉŠvRÛ4åß™êm¼‘âÄdåè.Ò_KŽ«WöE$×µm`üÏ¿Ë}½ ‰“[ƒ)'çªÐ4©äÐN»Ÿ…±É‚bˆ)&ÆÄ¡·ææ[‘U… '{ÄX%CR À1`–h°5xZh¦KÄô ¢ Ê´ƒH4Í”¥¤˜ ¾fÊÑ=®×YAµv÷þrX„v.YnA…ÅF>?7ù'oo·†²ÆAÄà@]þÑg X§«¹©æ™§a=H“s{læUŠYÌgux Ä›ÔÜ,˜;i¸i 守¸Ö|ésî“»žþÕÇÉé=£×æº_~<¨¥ñ7¯aÕcûiÒwÞY„'Ïï×Öå_¾— g¬ÊÕ¨Öv¢DÚØ3²ƒ¬Pœ¨}fejW?Æ&‰´eš×Jc³PVP~ “«¬ éŠNǵ3ëõÞd}É)ve­o¬ô$%Ú#  ¸†)â#~ê¹òo?žöÝ…b]ªóe*j5rfB]} ·%:FH!"ùÚZ|¸>2¼w òŠV±6º\òRQúþûéwMJ¼æ£Ìešß3ù¼‹™ ™Î˜åÈr ¥f¡ÕÀ‰`ÓÌååÄ2`Šƒ¥c Ñ`-£D"*&<hy%å` g@‰Š€vÁ2à9Ñ ¬ÚHcбŽrUBô*/ËNf4Ù¿o¼X„vškå„£fn±ðïßètS¨ƒgô|»«ÂþɧlyD­ X-—¾ÁMU%2zx·‰Xau1—肟X0œc]£)ꬌ†#¦Ó:Q22¬Zw‡ðλroŸ4˜Ý)‹Õ”ô6…˜ôÂPbB %,#ûÌCÌ;¶­âZ«^Ûÿo¥êƒ±Ó+wÚ©ÔjȺ´Ssú‡ëåoÜf +öËgÙÔ$ý³w¼¿~+}¢jŸ»Po¶÷Å SÇ'š  ³nYÒ”KãŽ8I© ½9fo±êÚ_0Ú•äåË:½$‚UÌozG;s&½î¹$¼Îù²½‘°%*ûVU8ž…8ÌëŒ;Öæ¾ ŸB.^™‹>÷äHEw¾sÙä’>¾ËRúŬ¢!¾4íÜÚÆ?{#Þ-id8¢.W½fœR#{†;`D¡Üøìö.2qåºms•i0rîM ˜‰e _rŠ˜or5|^Ïm5Þy=–QN ¨›ÚÑžL2OÚ¿ÛV4xȵð,yîqïëÒTª® *¹uЬ©–ô¹ óÑŠm*pµ!À3߬¬¤ûÊÕÚ¾2?Ó”¶X¥WþáÅè½Y™@±ˆÙ.âxHo)x(C‰Vh­%1.›JÁ„D@¹¯%‘¹'Š©!†i‚ˆšVÄ¢‡Äµšb&À*4†‚ۦ¬µDÕ”h$GŸk—’\ €„Â*%F6zÒÊÒ½·ÃÛ=å¨x¼"0;F¿u~ë’¾¿#Qç!æm øÒ#Åé=•ÞNâ™ w«kjÎe1'nu8¿;§{¹ë(œ3âšDK…3‘eÇ(‰W¤ne§ŸÜŸIƒbéñéÂõy¾^œ~‚Þšqît3aƒº5©ÏÚ=¢’}hB}bœä#‹_Î[ïÉko‡÷Øí–žtK¥B[å,W7·luWáo ¥jçû’÷?}_þøŽ<>Qøû¿U¿³Õž¿o?÷t~áHö…Óv[àìfì‹ÄH°6³¤¤|â‚UŒK#µ‚œºß-ØÕÜôÁ]³t‹g¶-v U¨•²Üå¾c#—Zb­íxÈ‘¦M_|Œÿן1ûvwÌ×å®ÝÞ—^~°dÞy 6Ù§aß¹2tFG§é_ü4&‘Õ¡ñÜ¢^]H7æÙí›ôêJŒç|7ì¢ÕIº~¯)·úl”–ZEƬJ­1UGþØÙt¶M¢¼ôè3b¦[üæ7[[¿>`l#OS0„‚ Œ§hL45Ÿl˜_ù U±ŠJg°ºìö¤SOã-T'Ò+Ké©?"¬1êÁ€Ín rÉË#q5Ð,‡Ûô.›ŸÜ"ýŒ¹LiEÖ»Cô<˜Ä"UÈC>!‘h`šPJY`iŲžá†@Î2K•%ZXt,suH¬`¨b­5@µÆ\3*I0¬ Õ„ªÿÅ3N5§ ¹¢!%°ÊÈ"'#ƒÕ=Ín·ÈJ/'z0V€‚ç&¹xý²~õ2Ìmàaƒ9…m }£~ó‘êÁ¥þ¶†åƦÝh†N5æÖæ¶ÞÓ³Ëj§82ß…0ìÐL¥=†žb£áA¹•f'¿{7vCþðDùö¢ØÎŽ?ÌoÝëÝï3‚ºµ=)}‹Ón=ÓêФú•ãº5æ ÉŠí½ýa|ûý`v6YÚŽ‡Æ½áqKžwû‹1¸uúÓ÷F%6¿þ4üñOìoàt þðkûúôöÎçŸdÏŸÆ_=j¥çÝZI“ÒÒ8'&ãºÊDÆ!Í-ZºÍÔ6Å-£º@V i¡Ú`Ǫ¶&Ú¥5ezAÄ©…Ã:\8qJ/=Îÿé§òý{¬`ù»×p|·ùâ˵¹Eòöƒd«>y$ûÅŒ¬ ïÞÃþäÕ¾Pd‡ê±±Ð)f«‹vs>¸õqñÊBÓŽj¾›ï¢¥)¾9³-wb ÊdFÃ(J aç£Ì?w2¾ÛÁX—N?†3ÝÒ·¿½³xC§Û* ²@©&Œ»®Ž§„­‘K¦‘OTÔ—_á]”®tã•UÖW´8šÇ›X¨Ö¿2—Œ™ê“BØ\.Ä|i3Ó¹SN+¡å9ܾ¯¾sYÿäí¥®O 7¦IØmsL%Úm9„, †YÂ4ã8¨Ñ³*p×£©Ô ƒÈ,a6ä§xŒRBQû†äíH…qW"¡\HÂ-ç XÊj9f[°VGLE€C`R€Jÿ½Ûøá}Ï)·*T"H–BÍ-CóÖ6-è#Ó‰v†]¼_xð7N<÷‚>÷H nè‘ëgœcE>Bâ{¹™AÙF—xËÀhhc¤uTÄ£…ïýÀ‰Ÿižü4©°z´Ó¡žÛRÉ”.Œ»i×Â@u=óQáÿñ“Áâê–AÀ*dRX,Tü¤ìèTöäéð¿ÿw$ÓÀ›þŸ|‹µåÂXþõkô—÷K{F¢ßy±×€èÞ}+ÊÔ ¬‰äæ->z¡ËšM{ìxoyiвY–”\­„ ²}‘j‚E9E ¬J%d$+T´Ö k´´3\ƒ{·¶&scgo§ñÁrÁï•ÐU6~°Ðjœo}õî¿ú©ýÅ"—oðñªXÙÞøŸ¿Up5Ñ=[úý¯úoœ½µZ4.oå€=]ƒ;Iç5t÷NÁJ¦Ó<ö9”8XétYî3'Ú‘“õáÊç[ï|t~úãZU„’Æ1¶zÚ¹ÑR§@ò#‡l‡A{ Rb‡*Ø)vRZî\rÓ÷”´jÿ+Ó{{4^ydߨ¿¹²G•<ê¸MFÎ?dЭ™‘*½³AºÇŠÞ°‘÷¥žAÕ²x<Ð vä ÀC÷Õr|±ÿÐÿ†Ñ” ûCÍÅÔòˆva8áe}„^¾S K‘û/~Ð_^kZjR’”04 Ôðã“öɳìøw‰@è/Á_v‚Íd~Ïüñ/wfÙd-þß}Þá«ßÌ ðÀ8ªÛVÑðÙh¬\ö…ëo›£‡Z +٦ƨ_ ü4 P稸(‰´ê 1ÚH–5¬ ÛÚrnòØÕÖH’[7 nƒçJÜý8ÏñJA•YYCsa¡?|>ÿ½WÔ¿ýùù]ÛŒÉp1\Œ¶þøA‰(S¡Súý_©¼{«ÿæQÚN¬éAçÜN»?·bÿ\Œ¨ 2µÆu FŒ‘Ðf±/ÄÆR×g†ë_èĤu÷ùÑwÃ’ð%O°Ó.K)“‰ŠJ°C¼í2†«Xw[À;Aò.IuzèKÞé z[ç¦Çí/a]õ/€9„¤ãTg[½µwõ·ß†BÅGâõ"©s@¾öšŸ:JAÁ˜n@"Z{Ä »,îÇ % ! öA#E¤Ë“Ÿ|ÈVÛî×?¬­mvS×#º5áš³û؉} ÓŸý<¹Þf(̰êvw cH¨‰‡}Ó°wdçk¿Ë¿ñ×Ãr°í[5DØÖN°ÑFüÉÿìÓXõQ§¤ÝÊ1äà†ä¥ÿâç|­×úçŸñ~p7íÅñ?ø|#YÝaþû×ýÛs[‚SêV&¼®í5zé6†«»Ú¤­ºŒ9¶ÈÝ7,ÕTŸ¦¿÷ 0JFªµ´°é4à‹ÇËÿò›ù?Ãù¿ÿfCÓ üN[Ê„í)›ÿÛ+•ò·•·ç¨rëeVR¯ÐøÂ—·v7úÇÁû—òveP(ò† ¨lº[WWY= _ÿtœü朿=Ÿ®H[JŠ$S}€ÍþÖèhã[?Ín.䴻ʋҌ*`„f•–ÈÀ É9]¨DQK­ž ã"8îVÒ[¹ÇNr_iÓYvò)ô,gY¿ì@WÈ.…é<Žš>^ÝÒN€ „P°ˆÐ¨˜ƒ.‚±JIJu…ÂÂ0’!ËK@êiP C ±²ŠTÉØCžÛ%z 2À­â‰1d#Äeò¯^Sç—G~ïWkë‹I&& Asà2°¯„Õ=âЄ*9åÿðjÿJ‹¸’†ÑÒ/:Q³O݃èôpúµ¯ó?ûóŠ—vó~kLðµ w±×¼±ÿüÓ¢*:6+÷:,÷Ħ_küß·÷·Òÿüsô'³Ó7ø™¡^¯/Iþÿ~Þ¹7 ®Klqº·:e¥º„ù©×S¹òIñY\§Úíl `*Auz¯ÿ»/C¡‡Âÿ£¥ˆâ÷ÏþWÕþ'?.ÿ‹¯: R;ìw;äÿúJúOÿfâjk‘JLÙ 9¾öýÝcý–†w/a+ÍS¨…ÜWq§LÜ-¡./³ŠK¾úr‰xÙ̲»y?YÊ`Ù GI°ÞÛ)}ûuÿ£[ývºZ¤@#mÊ(èœRÔ;…¥JÜé²L‚JÕ¡š?0ЬFfí®sÂ5™…öBCNm FöýJ­;0®àtï•ñfŸÇŽj ÀqÑ7¹à@Òœé( R]]FhhÊi <$®+£ÉÀ!€ȨÑÜ'È#kŠHî1a !Ô1¼#†Y®m^@Q@€gàÎ 5ó>È ‹›Ú@0Žk81X$8`µˆ.@³iFF À=ø‰ö öÑ’ å™9¸|gú½lú4*Õ®ìÖâÊv7¥ö §®Yd²%ÍŒ 0k­kZ‰<Ö”½ƒÚ5<¸#ÿ‡(™Þ[«–ñÔTç蔟{ÂËÆêÖ¡=Ñ[Ws•ˆ*+-©´‰"ÀÝa62ÚµJ¥Æë?ÌjÒ O5_}£ä%ý=:qàÿòµÕB–”Öúýn£RÛhŒÁü¦¾·Ó{ê¹p8þæe¾yr r˜ëÒ™ûÝǧk2ênaûŸþ6𴋪ú_~3’1 Oÿþ—ظ5kòßþ™¤¿|ca‹ ààÙÙÀµˆîŠù“镇†|gû?~~óóPó&.¦fWy¬TÙøg_ïý‹ÿ+:È™»O?Õd1üäû°÷©‘]Ó[é=Xu#^Ñ vL—H2¥4Êú²óÌ w§1yÊí{q¾ÐÒs³å‹ózýƒÞúRyœÍà´Î,ÕcÖ íДØ> v@ènNg¬^ÞìÇ-¯ãwêþÐÞc;·ÞR¥2;qIEʼn'hÇ M˜chµDx¹…PZC RfµU€œ pDæ&\É2m+Zï#0Í`Ê—yL3ng•%*4‡mÍIÁPEµ¦9±L² aM“œpêA—y’uÅ(´I`¡na x®b\S-!ëZÕ¥0gaÁBÄ€íÆW£Í˜B€s´B½K¥cPp×)qcåïJå–ÁèáÅ;÷¡×Æ}µ5ÞN°–†Í^Âr€³ºb£W€¶$£Vr¤QikVé’¬ƒñ1¬ìñ; sñ¿ü«î™£{Šar`lûä^®*!í'Ʀz¿¼º–Ä|ÜšMzÛЮYÕx5ìÞ¯ÊÕ¡×l‹Sù§>eþø[tÐQº æ@ðÅz¬.,e½µ>+ìÈù«W{w¶és‡‚gö‘ï~,eiwGOóÅXšÙzvßèv²Aþ¿Ó¶üwßN›}ð(Üôï}ŽWJ}S0ÿ¯¿ì¡f• x}¡'w`ª`v¶ùvErnºõâ#Þ>nýù·ýßü5(–âí-g)éín;øG_¾÷?~¤ùdº#*_üDT4ôgßÚóTmrϽä>øÌßÈ× …¦u„¦» §i_v_8å ¸ÓØ{ŠwX¯¹Þ‡›“—Š›WÒ•{8Œ z#*6·`Sf,‡° wRç.Êi€:w÷»ìV–-®·uRïÐf½Tš>Þ½õ!;qh‹!dE:È©—‚4¢ª·(ó„Ã"£Fsec( -p0‚;y)£:¥9XSÌÍÓÆV ê3µ®ÕòeF¤e°a¸,H°Ìb Å&pTÀº÷q2yÐX„A&n¼Jû].³Ö[ÚîØÜ1zRcŒ0„ô,8–²ˆŠY¢>fñÍA–8¡­­µT[’i’‚…YZŽ /7 ­lƒz§—}~ä`hhªuþË ú f»nÁÇfÌleŽcšæ oyx-O}t( L2"­1h»:à°0Ì¡ õæòÈJ¿÷»/{†nøñßôakãV œ¯ -5û±—ïdɬ+ŠUw¸³ .®½Ñ·3áü‡ƒ½Ÿ«>y1”L`üü¹‘«%¡ŒZ¹’æTPþÙeö“{½]#ðùS˜;¹ëD¦²Ü+þû+Ôšä…Gõ//ò•U ñƒ¨=àsqþÜ£ ¥Ów®Ç¶R)’xËø÷×ìéýúSO9×ÿCøï?0ÿågu‚9-•©DØùÜÃpkþän¥öªøbº’"è¸'kU¿ý‰Gwý쵕ŒVÑ‹ž|¼·Ë/-þuŸ öÖ‚eHÐë Ôç:æÀ³5Õ ßñ§ÖÝ[ßéV¢uY÷ÿzøôãí÷ïâŸüLºQµ¨·c›Ú‘©<Ó€€åðÁõ6Ól‹¦§}88 #V F3ÔbÐÖQÅ ºT7Òf”銆¢Ü% ïƒ}ä B@ÄVl›<‚´¨“‡•ümCÿˆù¹ÙO]3¨bR  ˆÂ_bö=Àwlô,ãaFÔϯA§S¥(Ú±p¦j\Ç9s’B|ã£f³ ˆá3„}œiE¡Î"_v™í¡Œef@» Aà‰HÜÂ:”cÛ(Ñí·ßþÅ`y“,·<½¡O‚®&bnÉÙ¼Ÿ,(¤>÷•A$=h¨„n°oªÍëÝA?´¼×JŸ;´øðéRÌRaø[Dö§…Û¯zý&ÌÏ„ckÛÝo¾…è%¿ó”31æô3®£&}áeWÂæùáéðÂ>5]q É—WYÅê+³ žÙ%ž=ä o]¨ÂÍUB)‹sñ¹}úæš¾´$”—Êl r›$ή²ûõ§yÆá¯ßŒ7º¢éƒ;!gpãõ?þ·¥WßÜ `s?>¸×û'`s­9ì°IÑŽ—:Ç:Õ2 6 ,¢€† "Wf+ëa5qcfZƒ¹&6»ðóW[,’Užt°Þ¤µ3(á Âwh •CMÆlT"q:Fä·^Ç´eSX/åñÞšç†N°ƒ‰¯ˆWqK‰BÖ ?ø(ɢǩxÓ$oÓ|™ É< O¡bsÇ& ¢™`½óîàÿÀœß5ð˜ÉK,ëѸkd®!N„»&Ä%°ï¡šE£,õ)fH™R6)×H!4aI£+Öay«âíX2/(–‚ã8Æd”P¤Æa ˜£ öÁô­%HLV 0J[Ug­ànVìéZÂ?GJ=ìo²ÁœËn›p;GPyÈG•bì6-©J…4ÌD¶Rý¯¾×ù‡/ÓýSe»ÒÄ5—æÆÿ“·ÔÏî KƵY»åB,]ú©‡v«ojˆ.˜…^øÚEœÝFã€E°¤hlËåCëÅfNŠð~+ÿg ÿç_ë=8=}íãy:l½boMq­¼!È—Á‚SÝ«‰RU¹¬Âé•ò±ý‹7:ñDöèCu¿ô8´;v£gÄ@îäÐhöo®m% @¶# ZòüØùF»•ôB*\ÏgR$ýþ÷^ï#¯œVÆÁððtX)õÚeKŒ0l;T1¾yIõñÂú6H¦½b¨mï…‡£÷›ägo:Ÿ !/TFÓ*¡[}õØXú+þð½Í”‚ƒ°‘f77£ÁB« Ü9°»Â~ë),øpèáÚÛ+Q·TÏ8µ£ •_z‘Fù–̱ r­èª2:L²†su'ë;NÚÿíß²ÁÙþ]H“jËvJÛ”õ41îÁaï™sêðˆ)j±¸ãÝÜ®½zyñ"É™‚€Ž¿y{ÝcøµGÝFIšˆLðâüjò¯~aûkõïEÙf—⺠ó"§ <Ëz±á)q‡]û˜ˆ÷ç0"¡DJ}”-Ð+%´eæX£«ʾ€šõs‚-À %@)P+s¥­3ZG@Æï ÝrX8\’.ƒA ˜]áÐ̺šPœPFEFHd!"Qê ëYé[P’ÄFÉÍâ,lÛ©?A1v[,[ôém¬äHÊEêêb‘r` r°8ÒI ÚþçßÛþ‡/{ûwù ;™‚šS’$ý7oº?¼–„|u÷®£cíƒáŸ:Õ8^ö70u³»Ûðú‡dv 5À¨`Ë:þë•R8B½å¶ý¯ÿÆþã_±sO_¼<ïSÏÜh±‹ã#ÁñÀ$%¬ùHË•døÄjoyâÞåÍtB=üP9`ý/<ª·7`iGnîÈ1,õÝLebJw_>[½0ÑÞÚö‡¹†;°™ä?~'u˜yåPWIðkE(èû=ò4?»÷÷»-/”EQûùÕäwŸ‹=Né€×+ºŸ~´ðþ7ßÿYöµ/pŠ# wœ\¶¸|r´ú+Ûï¿­Tìû Û’ÝÙféRG"„feÒþïþZÃõ²éc¥ïçQ“–Ϻ#;µ7ƒAœ!)î¨DY @&AYMÖ(˜B”ÔùµŽì>ë&ÿÍߺƒ'pO'y=É[eÄvBË@z†[›Ú½ ñâ9º¯–Õ˜3×önm×^½²xƒ‰‚ÈM¦}ãÁ¦ãÄ¿ÿd±ÆãœENÆIqa%ýŸ~©¶—‡BÖlÉÍ–€B°ÒÔd\4H ¯{ôÍöËÁ˜„ñÚ z`ûe“” ±Å¦æ`:B…‡6 ãÖWÇæ9¡MMY¸EÈ çØ¦¤(û½¿oŸPãؼíÝëÃÎRÖß¶‰†;¥ôœá[F瀇Ç_æÆ`žÓQŒ.¼ø[IcÛàn–ñ$g”UÆí—á©°g]÷H¢µa‚iæ¢UÌS`h9è~â\™Oî®fQov ï>ðÿâ=óÑ]ëý¸±†á–©:ý§/á× kcßIëO7Øác" n6CG@×0f Æ‚ä¬näæ‹ê·ŸËÉÃ¥ƒ«þZöڿ˽ŠèêÒ¨èÒ/¼T<\öjÃÉæ”›Ž8ñúÎ[‡~/:$2,’ž4MŸ9É/ÍÚùN ÝSWø¾¤}Í@Púæ-o³ï²á;«ÝÓá“O17WQïß‚ÚHL™yëª9xÀýä±Ìqý»=gs=Þ»‹ÝÜÖK+ú¥3ùdѧ#t{¾pk=îçûWZiÉ‹ÏÔ¤¤¨Ž27fôNŒSh0ýø®Ú÷ïõÛ¦à•›€Ò…«Ýå;Ãy™¥ÒÙê‘Ýý†b@î|,K®Nòª`P£©!Á&͵,?2Ú9ù ŽGÊÇGå?ýqìï`ɶ ¢eÈ%ó!Ó¤à±â+zï“Þ“Ó®3H ¹{”œ7{&äõ=p껸=¢âU×Þ_—éÖÀï ¼;+ø½“ï_ÂͦË!룶 ³ ,Cj,MYf÷¸&ŸñåÃjt"Ô€iÊ»,¿7ÆKgÝG7'^Ì—Ö|¹¥] DBÜŒÐY£,ÈÐJÞcæ„SôM† ·Kv1Â¥:6F÷žH'O›Ñ3f÷I=: K÷a­¥ÖVè`=óêþ)èuô–Mn(ø&A™è mÁqš–Ðî ¿ ‹¬V¾škÞï ÂÊ„T¤=„µcnOk¾ípPê+V0D»$×H- I£Ø»4—Ý[Ë’ØÙè†oÞ·þ6^¾g¡ ŸJ­uÈd缤ï|eO¥Ã¤HìC#Þá£,è%³QÃJ°žr]Ì3¦€pÈ© u,þd.ýÚ3Àn:‡ÑVü³[N‹¥Ì¸E–#Øܺ8š_ ÷CÆÆT GU²ˆoä½v_Eí†É#áA,Å61O.Îõ磒–ù®2ÿ‡¿YÒl®Žzÿc³O•º»ÔÙ=.^~‘‚±i^¿r5-ÇN`~x™ìß/Ÿâ!g7û¶¹–ÜÃn¬‘…5û©ÓyݧXá½­pf3kE£«M Eþü’»Azè!¸ý1iõrBc^ÜUù΃¨© ~-˺֥õë«Ý¹ë«²ü`à:wœ:­ogo)ÎòÌV|×ÖH®la“H†‡G:§_rôÁ© óOÜ÷wLŲ¶C; ²(—ÂÃD“ 3ö“²ðýØ®bhR¿ Scæñ!2>–xGeÐØÍÔ“4‰½»â~8›‘ ¼ÛËøýÒï]µA oŒ ÊÏ C!-#¨¸çÖô¾zTíÉ£QËs`-Wª@÷Ïœ·>©—7+ÝËq4&RBæ©Ö`cÊW¬zOØ#ÌãŒHa¤¯–#ˆvȾ=vßɼv^°ß¹e Ò4~ù­fÂõ9ØVePÁ<1÷¬Ý:`W”/YuËQr4™iƒ9ü¿HC€SÓbç’,¦ŒYä´Œ²RÎN—ìþq)Ñ\õQÄ0¨%$ ˆ±z p©—7Èû²™¥,Ȳ§)·æÃm)sT¿þ,~öÑ¡A»ç™Ô)ð ²õŠa}ß¾øÎB6ЙKaZëM)FDs“èj©ßœ5/°£å컯c/ssK¤ܘ)×G–%,´6¸~)ë—ý…{ƒÍ;úÒ²Ùl!ë%R©±3|}…¨iY§º¯>?Ú@ä?ûÊÐüeüø­96Yí£V3KV]­+¿}aðpQ÷%Êâû— ±‰£ÖþÅVþò#úÀ„ÑÄD&»ò¶£%E+Õ²ã¯J4©RØ»›¬]JÒs-#T&”@YñS=œ«22ÃllFÑ* £ˆR€E•²Ü#­˜÷ïå÷Wd›×§so‚Àm¥V}éIøÄ“Cíh«ãë,:Ûƒ´T öNg÷–’VZÔŠ2•»Œ; à€[G³aC¨µ¿˜É^:Ù¯fßö¢R¢3„|È›¡åž1…â 7/g—.™™ÍåÛòÒšÜìhå©L§²Û«^‘ä](nÌÝëoôHY˜ÿìKÕ{ó™w‡Œ‚‰ý…÷¯÷ÖcµÜã~åÙüÏI4C÷[–º2iǵånþÒuxX) Ñ—ï:YÒ¸·“vcö¥'­|ÄdN^»énè¶UñdÁ¾ôðèòréµá¼9xîÑòÕylì nÞ–!M·Ü} ²5Ô]u·kînËî½t¯}íêàî¼ÓÊ+[æ’|”*ïÆéQ¢ÊTLŒzá¬,pþß~;ò¶±nœ%ÐËL„ŠeÚ"G®¡@ÝÊžbó¾ì”‚òr·ÍAäÑXfŽ’»vÕ„go.äRËE¯˜Q)d+R·×ò‹ ùÕõ¿óŒÈÐøL*i$­!vÔ1'{AÉsÓÀ‚""kpCùÄçÄUh- W¯ JÆ|ü+¥îYpmXDkÁšñ´)®Ù°·b&¸¿‡Ž—Êw4°Ä…ÝŒDÿ %}¦©­ûöë/B‰šžÑ¹­®|¤£¶nôóv³àbÉ«½s3C– $Š äèa4ÉXY&Íæ†v‡7®—ì ?áÉC»œñýÃ=ž™n^xvxsÇŸ»»ÙÌäšÎ95åËŒÇ|ÂEúŸ~½ìÈÁ­%§òÆ’¼×Ëʯ~ ի?íÎíƒÅ¸²Ç¾uKå:@3~dö…Of±ÚåW:QG¾7;ÝL¶7¶$çø… YXñ,)¸${÷ã©åæfdd°Žêr'Ýud0»Å77ë5¡°MÑ[ßïìÙ«îC¥ÒØàòœj)ÜZÍŠYžXþÒCæ7~­6sGµ¶íŠ>x¡õ¬—/%ØMw;ž˜¨þƯº':»÷‹B8¦5ab¬ò ¼újÖjAѲ5ÀuJy¹› Pdšää+ÏxGGd7‰¼J¸p wfu¡– •L á;·ØtÚ° 8’›>Cb¡ ˜k]ã8ÖsÜ4GksNÙ§(=pÔX—ÍÜÝñS¶OEjˆ°X+ÄÀïd^Thï7Ü+EV%²¢©Fr0o m”q< šÇš”ÑEÔ7 ™ñn¥µ*¯À䩨qhÛÚÜ@ ’Y=ÙVëVÿû³>à:cž0D *"Бh«– i™‹¬œO<†‚P¡¼v;ߺ7Ä@*›'tüº8ï¤v;fÇ­©:‚XÚ·V#ËÜ€· ¸£Ñ¢Lqç„ñv9ÌSrôï¿h+L ”fººøáp´å6öe§UPò‡Þ»K8É $È(õ2k30!:ˆ¸ôh¥qëf@ÒönN†#ûœó§«g¦£g^]ÝÖ‹÷úí)\ªuy ÜÜg¾v†Bù‡ÿI9ÈÔíe[‚üÆ’žO•AõÅ'áP8|÷—zºÎ/öËûœ‹7MWr«‡ŽOÓÏ~2K²ÑR±ÝÄo߯¶Mwy=a¤ñåsr¸(_š©¬v¶Úí»WNEÅ!÷GÆv÷lºëëEŠ3{l¹ñãdo[ïl…ãÓ¡3Ö¹}ß´­]Xíg¦ÎËgͯÿjåÞ]l&l“ó†ñ´‡K™ι6˜˜¬ýÆç‚ý£Í=‡Gb0YPn¿ëj¦òJ}wá[ßêllaÙ àE"S¨%‹ˆ"#yüO{Ç'²vœºoåfagF5ÆXNd<1b?¸©3€=@¦”©§ö™%ŠŠ;ÿ«çL‹#lÊÒS”ž¤pÊ ÷Y;u¡‚ÝYÆ2;°Ú¥Yî”û{GiàU{€Ñ}]Í˙ކp îP.‰fÈ#¸™5Ñ}žŒZõ°6½!˜:1p9Æ’ðr†Ô…XA›•ÊDw])!u8Z .jŒdÐc9Pš)’:ü² |+ë‰sõÕÞü„söÑ:ó‹qy>jW|.ãLì:38÷³½É7çùKê`[ír¸Kh/¹L­2V€4Õ€@¶§28j¬ ‰'`;sR€sÓáD)ßikZ)ÜøžªÞO-$zøôaUÞ?Ñ/g <Ù¸p· —ZÐÂä«\!Š ·Öáæ7ÓÎùgFôîÆ®Šo9€IDATµfÿîmYÈÌÑ“b'’Í室GQµåDÖD3°%zOaeÓ{üa¸¶@¶Öx1ãŽàç§ü_{$_^v|¤IÓ#Y‰ÛK—’šIž=Õ[}ÇYºÞƽӟ ‡Ê·úëÀ„7UÎwO@sÙaèìÚ {Çš M®s=RKªÃï¿ÚŽæÔî³ðÄáÞò-Þ‚$/‘M{MœÛ8aí_; ˯Ý^óµÊX©1Úâ<”¡sô´ùõ0Úï3™d~F º9‘lõÁš÷lu÷~‘ÞÌöP²û,N6†–š;÷{îø©"}6°ÍÅ ÍÀºCàî@ß¡dœ:ë:§Ö÷@NO*GÕ=¯}ï}oãÖÀ÷Ô§¼Á@×«æø¸ÿÁ|º¤ÔnG I((Q¸êB¤Õ˜2i7 ‚¦øˆI@‹¹µf¡Ì÷?îŽìU!uëtóÃÐcY*½¸ÚbÁH§—Ùï¬MÙ=›¦Ôi»˜i’ 4 †œ”$´¸‘å*i¿ìÚ¢†ÀiûXØæºÇ=Ä.0)p”>@†&æ@­µ™ë\¶¢(I³+?ŒæÇر'xic'Û¨¤†N‰Ï~RooŠå»tþÜ3€½À£sð"ä Tg²¤nl:8>€Ã  TŠ«ÒÏÚŒ—d³cœJøñ«Æ{°¼¨a`«Ÿ4Å}ã]Re$IݰC ¶"I‡‘-Ž í¤â·:òÞóOœ/«á®zm«=¸+‚$;y¦Ð–ƒÍ¹8å.OúÆ&)/‹˜+êÈû¸Ð”€Î]Š ¹ÜÑÆÕE׸ćX“œ£B-@Ϫ¥ÀŸÃhªíRìöZR*'QS¤Êrß.DÕéGÍPдћ¿æ K"¢„• Ô(&X@ÝæŒp'! 4‚ÆHPƼ¦<¿ÏÂ&æÆÊí€q Üz½·i ²®íg™´$÷ŸUó4+• ¬Pƒ„c-Ú®ñ÷xChJ™]ÿ쳓ÍhûÒÒ} Éò|Ž×׃«sým’Ìuôƒ$1rœå¾†¡¼ôxñú;RBýÀ>sù†*ã™—÷œZ¡âLk[ÕèÀÙò¡ÉÂO/ö»)×Ï\ðç¿ {»ƒÕ-ëtVVôj§®lï¥3¤LÂÛ‰Û·»ÎH^] BˆU=5J—~HçÝûk°ïX]—},Zø'ÊNÃn:êÄÑýz’¾v[ÏÏuÅ€”¶ |éS6éOÞ¾ÜÛÈÝXáétß2 èÀøÀä±#K“µñ¸¯¼¯å·6ÈÔ):µkä{¿\l„ã»dL‹äZCyR`p‚c4ܶ©òŸ‘ÇŽëÄg‹3„¬ûc.[Ñþ³¾‡`¬¾±Z¹»™øÔ%lùŽ w¸ÕÁЄ‰H0Š|{‚°ó48ma—É3›·˜â6~ô¥(ࡵ.S3 Åò¾þð#ùùÇaïˆ}p/½ú›iíǬ½,*‰ìB¨A9š‚¥Ps‚j"&e¹¦ÓKšŸ?)´ 9%ˆå¬HÕ‹ Óº¯)ê°¨óØÀ¢fÌ‚ eÍ4ÒÈÈe·~_õ'õÔž4¼µÚ÷ËêüA2uHÒqÈ<³8¨î:›5‚ª%èoÊ9¹¦4/­S>J=‡@-0?¢l€”Xƒ-Œ8öÌlºì7Ü?žÝŸhptѹün¯r”öÓŠ<~ÈMsÝIäûs~Ž&ý¤-T€®‚Ψ”[´RÛÄ”ÈÌÈÍ_{ao¢ã„£³ƒÍ¥ŒUK]÷ãÅx™è$-øPŒµ¥T†Fëäå'+oë ‡öÌ?ž·a.]p‰ß_—¼ÚpöM>;GÞ·ñÞ ›Ã¡Iúœý‰>ÐÉ—v:E77ú›íXó±b͵Wþ<é͸¶Lx!ÿxû öð~þû݇ãluMìZlmÛÕ®.ûü•ó!w·MrêìI5’ÿôJ¶°™}VTyÓƒÏÂÆ½ñ™+ýéƒÎÆ g± ˆ KAÕ’šå™­Œ Eîþ s`‹^[5#GôÄøØÞ[‹7K7—Ë&͵Y—¤@áóO°°‰iN]ß±“%¢˜®=аZæjIfûÏ êÆzef#)²°Ašòmw˜ÕAÿÿyvíQæ>FüÓ'l.Aö"s[„~9u½™0öÞlX?<(Ÿ“O\€©19·{å}3š„ͤðcÚ]ñý8‹B!g@Hà"‚bÎ÷(¯ªóÔ1ë=yœ%.¦Œ²¯<^Ù‰Nˆ¾e»Øè$mšÓLÞR -tÊD¤ÄZâ+J87(žÓñ¤Öé=ÿTµH{)À½°kÌÙý°ªea|Í_3T€Ç6GŠ@êàMX>¡uÓ±ÉF¨CX¦LÓØuJ™ás<΃‚ÌóçN[Wé”™J\YÊéXväqëÐ\xj+ÿ镯ü0…IÅöYZ\%Æ –-KeQ{‰¦ ÈB‹:ï¼Í‡ˆMb»œÝ]IÚ}ÝÉAøETqÊý‘ÐvrïØ£^pß²ëzónŒÑ½äâ’·Ûs¶Sùæ}~éŠÔ(ÌžôȔŸûî €´ôÕç±¢ÿfB­1Ö¯Ÿ Ê–®­o$¿õ|áÞåÎp/ Π̱‡ñõëDóô¹ƒÇj;½ë‰Ðué‘“å‘€|×+ùùS‡3Z¶÷ ÿø.ÿÿü¼umÕ©¦î}…¿ó|€¹ÚyMy‹*ʘ=Tž{@|GnÚPóÔå )+ Ò<òÂ7½qí kç²?ÿY[RI{ʬq©-”‘å`ð,ñÏB@­DË ”‚gÏŽ ›Y¦ü,mÆKRx–V‡€Ä¹ á{—œVªhHÜ„ÀqÁäÊX—r ÖR h†„ó¢ÁGLq)‚䨠a‹6"Sc™«9é>ií2{¦17PU¨5ÖçÔD;Mhò1g+͵̷.]a…µ¦bøüd…ñÇ€¶á¬7*‘QeæSê´-+€ŸÑ=¼1N'Zx†Å·$‰-sÑó,HÎŒÚa”kÈsàö,D{U–6܇ŸªÃ`@ÄÞÉl¤Ž{‘•‘¼SÖn9æV¡$Æ  ·´ŽÞ$:#Vnqž Ô€EŠ`ZˆË€ˆ;~’ÊgÏ`(•"&,Âõû‚ÚÒ€sÒí|âgWû9ÊCû¸»×8ˆfK FôµÕq  iP¤í~ ³›ÉÞýIë=ŒÊ/t«ùݵÞvzÝ jU+wµ2áD)ï絃çл¯kÎúƒ>£»Å;ó4ï­”Þ¾˜F± O9{‡{.È>¶2 ¿òN‚ûw-ÉM yã˜Ï˜÷ár‡£ùõ§ƒ{7CmÒxIégŸ\!PŽŸžÞ=Vê%7œ®«×¨9x: ùµÛ4´ùÓ»Ó°€sÔyû†ùë7š×Ö+ºŸŒ»î’b¿ò” v~®‚eìgÄ*-<àÏ· ”ü”ÇM½Á×®ÈÔea5!’ $h©%äóÆÝgbÙtIÈèÑlüp¤ÚF…~«# ÂÇPýìUì¬Ss>¾ˆVËBQûH[D\A» ¦d?3&3®¹€Ú ­+€J¦c¡#¤m¢sâ¾:~ ¼·˜êÌVJ8ú˜˜>ÎJ~¢‰&~r]-¬ÀÒGÀf­Aœ§‘Q€`P9Úô Yyf3)ð‡÷®§á”¬ŸØýÆG}“GüJ”öršƒë‚Õ>¡¡O~‚µßS%UFw‹…ç.¸wM;1•®êZ¯>w>¾­ß¼lo­•V³Ñí—2uß ÆÛœì~Ø=v¼·ÑI?xÀ&+ÞŸ³`øÚ]ÙÓ…ÉÓõ§’+3ÅV’<6^8Ÿš†ÊÜ]ÇNÁ؈1/Îòtf6œ?Ý\¹gW’>õ=/‰÷ÚÊ£ÊþòW_Àù»aei0%àAN÷¾è/Ì&ý".±JH9„uBt;ÃÓg†ÈçbõÈcÕ™þ˽½åRjÈ—@(D¦¢â(xÄÊ“!`Û¼’ÇåÉ‘iE,ó}Ýëì»Ð(=-Ð!vaÐøÁÅXKç:ÑtSD­ãc˜2®>ð¥\°NlÉ%Hï‚ô„S%̱࠷BJ¥1÷ÖúÃëúÐI Ia»'©˜ˆš‘[Î:žo2pÌ wŽ|ȸ«&¥H¥¥Ä’ d†0}Ò89èsŸ#ûÕô$™.ÊË쓽Lvqhbr¤ÜŽ-õróà†Úü¤a“Æ€) ©Z&ÔCý ƒ1Gž«¤ØŒÊG_fµR 6²…B1tæÅ÷Ëdÿu³Yv$mlˆ^nÁ÷uÞE¹È\É]ãbp\û”Óx“g’0ÇúÚˆØ=ëd[¶¹=úPIYUÎ…"maâИÜ7›«“ùV*s³×sŽç » ÉUÌc8@{Щ¯Œö” œ["“ÑŸTG§ñÃÛ½w”z|àš” 7!2Ð0B9Sò•ÃöS§D*ÈÕ¶òFF§ÏÄ»JÑÑñìÒL9‘ѰƒÛ2gBjcf[±Õ6ÏÁ¼{~~+]ÝI»Åd]øÁ:M³Æõ||¯=:–ÒJì¬×N–êÃm7Ï;›]‘MŽgMó>¦ërpéfúWdoÞðº˜)“µ#%Ñ”—ZS­ ¦¸4Ž÷úU3äGÜ ›}Ò£–Ÿ˜NÓíìþ ¨¶( 7Èd³éBªk ºöùO¹cê™~ï'¦HMšë²ˆ£pf5a Ó&³ ǘ[5° ¶£qsUÛ3>Tí“D,5¤X&)ÑAñß|·ÝjÒ!Ä£ ÷t2jS–°úKyñ¼ñsN–˜¼Cõ/¨Þh§ÈhŸ«”¨Ýjd.o.^·lµ”µÜñrÖ¨ª4 ¼|à;@\×ø«—K¤ O•÷nçu*nÓ|ˆˆÜI³úEî=†Â§:fÞø™´”Õ6^žÚ¼ÝÚÛ–^7·ŒTÆëcÝ\3™äÛ·Ë\'§5ƒ`Á&HLÑØIà@Ô'(ájê\¹›ÚõnxôZ.©aJæX(²¸=GW.ÕÕ*¹7“2O‡{¼§,äÔ¹#Ü·h>Ï réQ]äáÑÜ›ÎI—Ë-¡”5º½„d€¬‘j‰lq=zü‘ª¦Ö`Z¨örȾ±8ò7ïÈ<Ó“2N„ò.Ó7¨ì(í"§”kjÐ ¸Ö‚g¥ÏíÌ1tÜ\ø¬>y>¼Ýùål%fŠ«ª¤v4à:É_8 >{s\ÞŒƒ1ïÐiw²Ü=1¥>¸ç¦y<êz[¹!Ö„Ìf”m'y–õ%K3¥×nõ—zƒ( MJÊMÝìû-øœ™RÔÑÅýõâI§6²å)³ÕÑ ›ììÈ°ÜÆ‹³ôúBö§ïäoßq·Óôc¢0+‚ä­Þ͸±Üÿýç½Ý^o»çÜ%ù¡s¥ û2ÕNg×hѱ:CðX(±qÓµ¬´§´ó™ÉäãänD¾ýÃl$¤½(m[Öƒœ>×BSj¶L Ds§aÙ;†nm¦‡&ö7š"µÕÆäEt3—€ãÿñw;ë-Ò«‰;4¤® îÿϳ,œ7^Î`Ýɯ;æmÔð«„$ {DíÂÑ ÝZ¿FøJ¹×bj^/I%\:ž?]¬|pÉwköø‰âP{P'ü—E šÑ2FÍ3Â9GXÙØÈqöœVLƒ'm{sªw­³·mØóЈ ÛÝ%ã^bì Y›éVâòÍæ‰^`¨8`âed‰PG‡½Ï¾"F§£GäžñŒç֠ߥÚ5’ν‹Fu“QÂ>’å­<ñ<µ`ßâñ]­ÛÜâK{LÓ= 5”;TÈ3.T(Ÿ•< ¢|fhn¥Æo*œ]JG|1²[Ppª^ÐE{y©ð¯~Ðë¤b8e‘? …rµÌŒNe4GB\-µ Ë`Uh·V(w•º;c÷ìÞ5ZìþÅÏ¥¡D ¨§Xi(q u ìÄ `ý€ ñF)jììDîsÎìS_ ŒcçØ²%isÇ#dÌ”"&2êTÝŒìýYõö¬¹²k®ûöÍëäÝÛìÍùÞ3Ñ;·É>¹-«µ¹¸Ü{í¾¼{ßÎm Ý!*ÇÉ]ã•´ h‘!j_ƒ3ÆtUùhIè{‘½Õ)æ©Q»ÒÆÞF½bЇzenNg©ñ)R+vٴįbD?Ï/œÌïoìþÛoìø`´óÖ*߆ŠIã ›ûÑZÊÜé¶k—dq»`J\JÆšºðá|¿V-M–ó0t•PÝ[ÿñ5uk -ÚŒ‹„jßáQæì%Æ_ 4™šI£d-¤«–(×I¨¸¦’)”aX;ÛWˆTõ dÖÂF{R¥‚>u˜‘•rVÙ›>“ܽâÄQ4bì%9¼¥’˜{¤ö ß3¦Ë܈ZWÚcö!$¬aL‹0òˆ°AÎç±ÀhBlÁeTk-°–Ò÷–²†ÇöL9÷…C3">ºþ?Þi© âäCÌÌ ïªÁEbSK8’(BÏh¥ë¡ML1ßÒ¶ "@}ÿ¾š¯Wò¿ýIY¤&vÔ|?S±A!Ò Š§Ÿ«#éÌcõA#ÝIõû«üþ¼—v}›I¢5õeÏR0Dsëh(Ù¢´$嚤&nãí¶¹w?ûÙ}{yA ’m´éϯÓwgÙ{âK³ù{wÙw?´ Û&“棕ôséÝy³°e{mH3ì+YÆ °BÙÔ4ÊÉY¡ndÍ–€Ëy”Ú«[N.u6šŒì›¬•è;¤1ro6Íër ²0‰YH½aY/Kž<г;å¿ùÛžVQoÎåÙPseB× ¨gFaƒ˜Èu k¹7Òú¶©œËs;EßÛ]aè'®äewvÎùÓ_ä×V A+9(dL•BP²˜99{ŽóCãå²Ï%`Ù³i¢à+œÈ˜\ð jŠí¹·uåO F(Xí„çÅYƒG|ºRåÉôà™ìäéâÍM£[É“šïµ$²z‹Ø€À´…ãVçXÉݨ´·ä@¸ÉæŽ]WWÉq¾:uœ°XU:/üdccœ1e‹—¬zßd`Í“ÀžA©ZefâáñÃRj5Ð#fóÑŠ®'¥:º]=‹•wþZíÑðQÜyC0Èy $ÓT¢á.ð6¡{¸ó9E†H£Vçg[ß8í*|c‹¦… ê„wQžâQÀ=U1T¥Àò;Û°ØrA朄Ú*äZ C \ðd¢Ég ù]–‚ “È'ÖÙÓPGsßzX˜¡åÕÑÒ#¶Ä Î(|ôNânžwLæ(˜q† njeæ‚Ï‚¦L¢°ša€œ7‚d>C/7)E#ª,“”¬u-C4†;Tƒ`°„2 s…ÇMD¬²‚ ã+ˆPJûx®NÁ óµ–® Õ÷˜´)à /uy%ÎòsÏ…¸‘ôLžX_¦^¯©sÙ¥Öâå|ñ#6¿MÊŒÀ6–c¥ `‹ñP¶‡¬j¢Fƒ¢ ª B@AC¦ÝtwNÔ ¶›¹M”³Ô°„h(ô‡‚®÷áå±pb;vLY  ¼gS¨P±cýï:fÁ¨š±hà’;Hr‘ûöImžáµ<òÛîÙŽj4êÀN;ÜèÈý¼‚Øv8»}Ï›}5>̃àM¢DRƒðxÏ€›»ØV1Rîë\0f{™“è (“M¥2×Õj¦d#ðãµõ†'Lâ\u $x–Oƒ°˜.€yÙ9uL´‘¹?›ŽVÄP-.T íÚ¹Ríò¿Ãýƒè"ËŽ>—ÊÜB’çV3D›ÂcŸSl˜e=c°à2’kO‹öV¾½Ã% ¨Öc(øŠ¹`yˆ{ª|¨ Bf#r³eY*ªàçßRFŠÆÔ ¾LLOr]Іòˆç( G©tAYÃ÷Öõ¡³þk¯§”A€ÅÚ‘œ½dȺ8 ¾)|?ÌԪ΀EÏÆ–—´×·Zªø,v[™Ì´ùj”€ÃAH0à[šg.Bî0ßT¥Í5H h(¡ÄZAk™Ô@N©G—“¬g9£’@º €e` ÉÃp÷ˆY÷R•‡ÐÑ”hËQ¡4#„ãIÏ)öãÁ£/”pÍ êê> o®¢± ¥wáÁÊîýufAå¶I;ŒF †Ôôª!êõÒ6jë€A  êcH”;4fŽÔ‘ ·g  SO7¢3¶H K²äù"›héjè²È슊¬‘àçgAW­¥¨û „YbZ˜ž”êIV[pþ·ƒ¤L¹;­âÜZÿás#L-z.{°XœùVw¨eþÛ̼es°ä:QÜ´•+gx82VPfû}‘¤uÎ9ÓtÂóÓ$ Ò-…@[Ý€&„î^€˜Â@€OmÁÑåìÜtÅÐ[è5WW_‹ëÌ ‡euwãÈéÌa­®0K=–Ú¡¶û!O¬b„I G À;4@À )²"K¢ ÝЫèòž­Þßóé‰7y ¬.€fÔd„AÌ[Jšh4PV!Ýer¡ïöt¹àôž>G;T/;; èòNå¯ÞÜXŒè Œ AdSÅuÅ+m6›«oÿúWCʵlaÆäI°ÿ`s÷(ýpI-\TžìP@š 0 qN2°»|^ Ï\Àïý)j ƒæÓ*2¯úÄTBj ¦CàRŠjdʘ¢µ.\k0£ dT%¼„Zˆñè àÂyâ—ÁÏxr½?§<Ð8ôÊ‹ñÕ·½ÖzJ _•8î'Ñ ”³¸î¨ãæÄÃd»ÃnÜj >º·™f^S“o¿Z×Û;,ê›,ãó4&,!€ Æý/¿46>Zµ56.ζ_¿[ƒpÈòƒa¢ Ÿ‰ùÜŸke.8R) €hß ClÏŠüXŸ<噯F¼æ–»¾­çQ5Î ›v0O M¬íƒ%@ä …¢(KiÔÐ=ÓêlAÑÖ»÷†ß]nÅÛ¶©óÉ1S›£ c{üûÛRDë\ZyÀBàäHšÙ ¹Þ©!@-‡1‹1Ñb”0+%ÙÞR¼N§`ÁIT‰Â14  ‡€˜l€ÆŽóÈ¾Š†È Ò¼Û¿þó´&˜ß0ÕÝ•ƒ'Mí츠Rèçå²#{%™é Ãs0í; ÁõT>¯­*ж³gGþ'y£ïÝÕt(s,M™IAÌZ1u9ɸít~ÂSœá½¸¸Ê!’=uNœ9X-69ÐåÍÚ·Þj®t«™FÊC Ɖ-J¦Bn·zÛ—ü/}Ôi2VŽæîÖ›}è@xp4º²e—ÞÃv¤z,2±a YfÔ ‹Ezþ•ïü©q‹='Z=°‚ô[ÜÜÖÑ&­ÀRH‘“œPhSœ¸¾Ô’sfò”2…D[\0´‚ #ÆPÈyf-x‘  0pí28‹Á0z:„Ëíå6Å­~öójæws©ßÍu+/N81;àRèçCŽè3ç{kÛîìÝa¯”M¶Ûíð®PßøÀ6ð°ÑU™dœp`Lx›_y!88™h“õmáý™øâu½5p†Pïssdx'Ö3[ÎÌ–t8¡¨ Æ3 "Tá¨öžÄ¬ÚÒQqüã´7Šñ(8‰v:/ѼÖFhK¡C €"´ÊÕð}Õ&°tzK+¥íîšìY½kbizä)¯Žò^ÍßÌÁÍTQÊànš{C‚jc» ,‚ ÜjdC@Î 9¥9BL™öÃ5 ô¸uŽZ:a 0ÐP$ÜéöÒbÎëK÷Å5ÿ˜²,YXT€GŽ‹GVöO‡-îj¶­T=–QËj°œ!!¹Ñ)·G­Ë¹M­É'Ч~¯ÖÄ­xÙÝ£q? ”c6A+Âúš(Æs4!JK=nà÷ŽQ3nm[ÛU+'Jþ}®öÌé~ÃO\ô™¡û§¢Gs¶ÝÞâ„ Ârcˆ‘‚äÄ™Á´Wõ?u®xó]:ÿÓ~mgõÔóÚ¥pf%ï€Ósô€ñÔðÌ…zžÈ’/<©ž>a£N¶° E7ÀAðˆŽŽ[3AàaKNç$ ÓÂF‚0Ê´Q„Z£•%ÆF5"X4h  !`]N„Ã÷ü$”ÏyDë#SXÒÙ}9Þã¥ðøaõÏéÀæï߯~èGŠ#¡‘‚±c- •²&a§¦õ[«‡fÕ½»Ýb¹zú¸séNaîú–' ¶m´¶®AMhNÐEM?·?ûïàÁ ©ePôÌD!:9…Ç'j7³n&‡Pî#0JÝ gFªžÇQŽg41  ³t™zL¸ŸFVPØ´ôÑÏ5z‹}ÝsHΛBnk ” %Ä¢ò(.r²[æO Ÿ~ñqîœëÍkïëöGj—6Ó¬‚Ft]ŠÑ›×ìÅ×wFS­`Æ {˜ºgÀq¹ÙtlJÒõº:W.‰ˆíÒ¦î¦áÛ`Œ¦”e”f„Ä”)Ç‹¹Ó7YƒÂq¡lÑ‘ÒË÷ú½¸²êÒ½¸°î!ËÒ•»eɱƒê¡ãã{­HL6»D›TSírK ZF’ܘDàQãéI%wy¾â¥AÜ™ÇÃÆÙÌxt”Dέ§A0žkÕRÑ1´SÜ9EÉ4êUcï[3ìÊôåÉgjŽŠAE|MöMöÏa²™Ìn F 9Z®$(915“A:Rþô™àã«úþÏ£‘y½¸œŽsÞ¸èÏ,ë6Ю£”'ÖÉ ×àenÌrù¥gÓΤíVº´XR=e{ûÁî²xà‚qOÐr`õ±=A#Ò*k­2 @Q0ðwžÔ”ÇwøN‡‘¼b‡Ï{áQiŠ&[L'¶¡çÅÙýñ—ž—efߺ.m¡Ü‘šèhÓcfà‚6h5¨Øž˜¶o“Tï –ï§Ì-?v®ôÎ5¶x£ïpè€é 2è”@-¢‡ÚûüÞÁ~•žÌuúޝegö£åÛ›ª§CÆ0ê@Ý2Õ¸‚KÇÍZŤ] çXáS@FlÍÎÎýæ®õ…í8œkü]"WÀR $#€sP°[ªçµÝµwäéO‹SçݰhÞ~W¯_ŒGbÜ¡ë71¡å=3·Ø‡oîLD´˜ËКQÂO ïu*¨cĶð”çu•TŽÓGÛ'¬Eè"ÿ¶P €ƒ„pŽÚS1e¶fè.ëŒñ‰õˆ©Z(X([[Eëbkö*UÊŽeQàøñ£†«Ä1IVÕ†ãÜ—u¢ב@JiÁPmµOi•VRºµ9B^xŠvqêI¸ìçï¾[>žtcÐðšQÀ‚qY®zDÀ¸ðžcY†ú|û>2O~æY=¼§Ýi‹P¨Ð'äkÛP,×_þt~ý¯åìf (r€N’ ê´ôÆÏÔ‰ávŽ¥¢ #"]HÜ;;êÞƒ~h*¨–„ç`¬Õc~drgÿ©ÆÈ‘üîûÐÓüÝYhǹç¢ O(1"%Œ­# ƒqµìðªp03=—`N!&™›çˆ` BPû €5„‹‚±tˆöC`zÖúI Î{$›Ç¦%%—f=-oÞ¨ÖÈ39ï]ì„¶ŸA.XJÇ>MÌe·6:%²Ñx7íޞßþ„1'fÐÍ2#@8”H Œ•{jâ•ÏV(ћ͞`!„´ ©ô‡§:¿ýxð/ͪò˜TÃÖßéI‡¼†|mš˜ ARO«Oç±Ô0ã{žSÏ=¢U²Zúdíƒï·ùT±áÖoApDci†Œ ¥u¹[7ãE§ž˜ÁÙ#âòšÅA«Hƒõòþõ­ × Çh) @››EBˆÛ(šFïÐØH¸¥Êà&À€ ŒA£ ÜrjCŠŽ.2 [6j3n¼K½»×"£aœ@?kg^Ñ>œêÊÛ[†ÆpÖs9‹Yàd=e-ÂCBµ5¥eVUvscž~j|{êœ àõ{gmÿq€:‡×Œ0 µËrÕ'š”‰þ’å6‡·Ô‘°€Åü·/”LlÇM‡0é—l’fÛ;0Tmüú‹ùlOͬƄ\ ƒ(×½œ”ïÍ7»GGâØBÈøâjÜݬÌÌ®w2a´"NŽI>êfYÏxC‡è­›ü¡gú-°n(’ü’À“†O¢Ž°»ÀNMÁì@Åuh¬Û‚ÛLƒj¨›*Ô€%×!: „DkÀuBmxÕv$¥Ã‚µs•ä1ˆ÷uSn^*[ýÌÓjþj¹¶×ž}¬ðþGñ°—'†&‚@;%'ǹ›[$îUën¶•a®‹Wo­¾þ3Ðå´›&F€ãÌ  O~¦ÎE¾¹3œA1 IŸ&†7&£/Ÿ3ÿÝkävN¤ºjýÝÐ?ð::[ÄϳԷÀ}'BéHxžÂIg&x—¸Wòçƒ0È'«w¾Ó)ô @F¹Úd£ Ж0` „®ãÀÙî¼­ƒgÁÑpü„øx¶@ã>šØš®ßZ ,§<´f£SC7A¬ ½Ã2­!`4`¨ÀÆAPcÁ´0À­c´Úݱ°ö6—×={[ÀeM`kŒ¨(V8„‚AÎ…›‡µ¦I§OÑ‚OT1˜YwÒ* áCWJ[€!à1¥µ1F,F”äÜ8>4|ºYî@¨Jfˆo̤8”á.í5€5™j¡"ÈøšùFkt͈’e —l¾†ìp%ûÊsÄkçÖáå¾ÿ6‘8:~Œ%Ö$‘*t?š•@]ÇKsË ‘.`!}ŸÊurä¶½V\ïæÓOóË›þâ|.©GHÈ,ºŒ3ÊC£G ã\=}ΛÿQoë2ª€ íŸxp¿],¥+” çpöèŸQ=£³Àâ$‚o2.3!4P@æZ[efeƒ˜:EO›nl€àk˜Üµ0oá'4¿JÌ`Œ†k.ŸkÇQ&Çç_˜r;xý;E5ºZëÊMyb c~Àj† °uVÊNE÷çIZ(ï{ªø½äHì6èTVc0èŽè—ŒƒÑ_x’?ÒˆZQ^ÚÞº]ýøª*×½R!öœç7gÕJì(“T\÷`.w%„¾et³IJ?©ýÓÈ…2[~ =~òÙp3Ü'å9ªB`žx¤rç;½íË|1qxÿ½™¶ëË&¡ã蹄\aú‡`ïRÉ Ö-Læ¨Ôp €¬m0¬5ÄLƒ€¯M „0¦àjé›Ì±°bàG$û€ª˜Áú댿çh‡*œ‡Ï—ÄÝú^å~>}:X{ùƒ„“€#* –:L P7<2•ß›í0ŒŸ7?¦™n’j¬ù-xŒ $sÁd_|:|t¨½ÉâäðÜlpócáÖ¼B—¶w7¿9oמ1!»ÀŠ rj„¡šŒá(8¯ÿŒ!Lën!H9>8@Ëývlöd*ÚsÅ̳bó §ÖK +UhÒéÌÓYL“‘Q†Û–Í~`C^ (2#w1¯ªuèÒÔ)}äД\µöm‚¹ z H› ž3e(‚@D+8# |ô!V XC rPœC€X=îâß]T+ÞÒ| Ù,ÅV¬™S¡H•¦Æ¸Ò‰¼­¼‹LÅÛ×óJÒ0t§ zÁ«À¡N"hC¬€a¥«äT“.s54‚Ý~å‡ßÛIÑáD×,˜q„ À†±)—ðœHzCxÔ5!/[ >= õ2«ršùE ·yû^S90²·„iÊ™øÿÒðŸ_zžùaçù»âŸX9 P@PÈ™ ‚ Ìdç ·º•œ­±½»£±w‚=Ç>³Þy1;cïøŒ³,Ë’ÜjµZêÜ$›M6É&H$ˆœ (*Ç'ßéÊûÂgÿ‡Ï»ï9ß·®(Gf c´SÀQ¬‘$e†ÓþSõ$ÿ´:c“ùyµël;ÏëW2«lŸU8Z4îbk °L%Þ2Rf¬Ü -{ l{¹ !ÔØß2²éC:6C„ê•í$§~©gÍŽ.Œ×oÝŒå÷\²¬,¢ldP=žÍ7y‚lÚEi2˜»g{€š T«Õ@mÙí%þåÏWwï£c§Ã÷/e÷ï‰*ç%Ñ),F¾uÂ*‹VÀ‰SßzÂ/EŠ•vÌ]jÍÿ¨ËVicKôMûT\¦èZ3WÔMs}›Â‡2’ä%BÈš†— >Š#áH P^OÑgs½]u]é]¿Å…ÒÝtëW®è!°œú–0¾QYUÅõÕ¼!@Ý¿Pºý›tiPie C'òn+û¾uï¢à¶Qó@ÖjL¸£5‹=Œ5€kÚÆZÎ:k°â¸éÀYGÁpg â&c]øà¦3¥iÛz €oStMÃ2¨‚P’\+bS²äŠù˵MÕ¥nén^Þ.Üìݪ‰€bž{´Æ,…®…y'¸*vw¼,ÇFm³YúÙÒ™Fª AºnAŽ;\ð¦L†•XñzÒQ¨}×è®oÏŒ¡'§@8+aðÚ/uÛÛœÝÌŽíªânŠ=ôæeãpÈŒPÖ€ä ûZ8K0÷ñã/™™#åh'þóºŠXi…pJ¢Ü‚¤0¢GÏzcA)¼À­{ôîÓÍ$ã‹›Ww²ßÑ- W0l«’ ²yá¦Qz¬²YrI•uœIsËphÙÒªåÑt8h„ú¢­Da¯ÔÃhņçHG†>dø=›Ì+Ç,î+‹×^ä7þ¤u”î ¤µæÎýýwî™6@Nmaµ±–8f1È7ÖÜk/—`Õ£øâ5zÿvÚ5A§Â[k¶à´EYý­'h5P™¿”.þ°ÍWãõf{`ªŒ@û‘×|(¯nKAô$·(|Ä|¥S°²L˜YVöeí…@‚ÍS ËøÓ;h"Bƒé˰þ.,Ëî ºvà`ˆC,‹à9¥*C¯¯ènæÎ^¼=|ƒÎðÂË¥0…Šá¡÷yW™7¾§õ’FŽHFÁcÂ% ¾±ŠcíˆqÄú_«*M¢Õ:­Ës‘`“äka„a‘¯\ˆ"œa (f çò¾…9ÇI¢÷ùñÇD¯Œ`*hv®”æîŠa8_ÒöˆþŸ A¾j$pŸcUÀáµÐâTfÐW´/¼Î:ƒ£]²kåBviš¸Ô:Åä7ÐÀ/tqõOBf쇚ßÖ¶çƒífŒ´ÖÖ‡´kò(g©#£Läá°X%Sc‘õ„㛂ä¤~ú9|øq¾k°üÅ}Ù¾=Äm¢‰¬®".š+]6~…¦_<"æîõ¯-A÷÷º‡‹wê–¨{“û*VwU¯,¬·Ùæ|i~í¼aº¼aIÛU5Å»Jlk¸ðAõwžoüô®½øYRa¨ÛíLÐ…‚PŒùÈ‹t$\ÞÓ %‚a’V£üÊä®G™È\ÇÓÈPíèeÑ„]\µ½Nˆ["=lÉ 4ö!5MB!&~E¡ò‹¯ÛµZcðÖÏ:OØ¥)ê]ÓÎDdDQ¦ítÓØí@ñ 2åŸ%ãm9¹ÂVa~ú8vŒ‚˜-¯z Ìí$7à@ºÑà±”µ‰s£L CÀ1§ˆ{Äë;çœsR«^n0EB»Â„H.0œŒÒØl  pß ÀLOLSï$å#2­bàt;.¥¡ºÞ´Œ–Ûìœ8™4BŠõ9^,Þ-ÏÜ~nª¢qá'0ó­>]ÎR¡*ŒØ"—mØÔXrô›dðm“_Å=êa/— ÃkØ^ÃEè¼079՚ǍDº­{Òƒ®+½$ JÃRÀº†'=Ê G HÇ‹4…Q¾§*ïýòJklGíËS[ÿùݾ´ÚU"hsyàgÒ” *3ÃñÕãpwÏÓ¤ Àéä¤*Iîßc&ôo½œ‰ ‰´îäN ÓÖ¬ØÅ°çE¢5§Ðºb×~ *晢Ï<%ë! L.<Ül{Í‘€ž˜i~xÞ œµß.Ò*#Ž6t·•:ßÂ'ÕþÎçÚ×oá>±ƒÚ›2\S]aQšjN<&Œ0(sÒ(ÖPñÒË «ñ¨óoëŒv}HjG~ 9Ýgl‡ûm]²ø9ê{.u)CP!•º2Ú9ò7QÓµFïüdûQ¯‰wÉhF ŠiE¡6¸ujj¹€Ä¥çH‰µmvó=UíÀ.¿+$䯲øªsÖjD,Ò8Èhµ |a}°9@ácú¿z憯„F<ç Ž]¾§Ä„D™â¾M÷L–ŽVEê o0ZË¢…Nvâ9Ò?œšBÆÞ¸‰Ö·1Óñ˜Ã8ÒE×§h_?ýf¦)·\P{ ·ª8Z‘‰³+}Á™J»Fd¥Ž2›--Òã–‰•SõWŒš Ù¥ž +•”nb©ÚDé0¢UæTî& ŠŒÛVð¦Ï¯*ù±)Ö±qÖ£TòÐxy[¼š†°bTóàÀ8‚ãGª÷¨Ù5X»¸¦Îìîû'¿™œÚœô_;ÝùÆ“tÆg×ó¿óD߯Kk{ãéÈbšPcV`{N[ÓUJ çˆq¬‰È]޷ļH Iì×´sÎ ‰äòuÏ€³§}„{ —?Gèó:ï)=¸Ut݈¡“pü4 ±¼¶Ò¶™«·xÄ–ö ‹rÌŠC¨¸çûí\) ”¦ÜaÊMAêñƒ¥*6)„ËÛ2¯íy‚Ò­Jts3¼p£«MP1]æi^âaNœ¢M³Y&À ¾v߯îêó—[í)œÏ ûª±Øam¾pÎ2ƒýÉßw¶$ô=²¸œ”\pÛâEª­+a\ôcm©à<ÇiÓ_ÈСt}àá|:n|²Œîh—s *Û¸Óç§Ý6Š”“9c¬©Å÷ˆñ53OïÍ¿ðL¿ëvøt¯Q«M öÏ–²Ê€ájÁ™ªHXm $1NFml÷j»¿ÿ&@¹’ëZKÂ-¶¥¾ÍöÖ˜È\¡0sz÷Tÿô˜ÒE/®‡ "¼—w}öm¹PÌß½d×¶0B(%ÔC@ Öû¿í$ Ô¬ˆkËÞ.?È;`¶Êá#¯•§óZÝuX¶t NB…ýª5»b|_ÊSq…¥r,hºŽºˆUQ…œ€JIã5­^¸áèÇ&ßòkV† pUÉë F!U ØíÛ Çwócûã¿w Mó«ìKÿÉ7‚ǦÍé‰>ºôýyûTuäLvm-wž%åîôqÕù@,wƒë;§š«ëÞÿü'Ý6­ïÜ^ÛîK¤ƒ3ÕØ4»àU‚Õ¶ZÍÈ ¢¦zÌ÷Æå"0“€WAvÃè´±LtNψò§{›_š®¬¿Ùûˆˆáýñs¯òÎf“Ûò莅Ò7ÙÛß/-©ÞŸõû+ò&¿Œfÿ[½îw}µ(¡,!¼9¥8wäÚZqe#80è<ÝCEžZôb8é¿°hº8êžÄþn‹+_’¢W€Æ¼¢È8mAþâG³'ÁVî³y+?°‘å½*Êá•kô§ïÂ{—Ê8s„².¿¾é­>Ã;‚Qì4¶Zƒ4ƒŒ¨òy^Üò×Y@  ¾4§>èxÎì†-=ŒPÞód½¾@#dÅêYïªö*mAkEŽ« …ÂÒÍfðÿýÛ—qψíUÊ%/„â•áøÈáÄo«¸ä "GýÄ[Ëq@ô^ŸÏ6•G`±˜±DIÈlÉ'=²[ã•¿-»=ÝÙé:/6-m}1F¨*5Âп¾í]_ok†Ä€± =« ;Bó•I nitøœzä„^ÑþmʤÿÒ¯¥å ‰zqÒë=ý\ííVñɬÉÅ‘?Zjœ%ß„êvÞ‰Ñ'P‰³ÎNGÊ Ø*ǹ¾hÅ=2À ÈuY‹”‚OJEyb¬½²]õ²üŸ~a`d`un«úp6d;»5Œ†û-‡‡7Õ›K@Ÿ¯<ª¯¬v%SÊßž9 úRºÀÏ>î&ÆD«eþ_¬º~m²Ü]k¡mObP˜Z`{9€DøŽ€E¢?&ÉIíW”ØÌ’dÌÁf¦aõ êa“}Õ€£Å…=ôÅ=»æÞzðÎ÷‡Ï}ާ[mn˃cÎ~“ÿòåÅ"{õ\0$o|ñ§tú¿èš¯{ð@CÕñ¦´š”‘ŽÒ·¶àÒ>2ás­†§\uÆ/#-óîA)ûx©èqà¨}ñÝÊ•\Vi/£C—–MoLZl[ùCqê¨=‚Ë;˜Ú°9cÎ7&NÕêŸ]ï^įT‰Þ`¤Öåk×BÓ¨X¼Õ±:†X ´Š98€è=ž^•ð5î˜+|ß4d*Þ»a1#–E“åú ±v– °¨m©û¡în˜I„ M­(YÀÜ Û­ò¿øýÍ€ ¨ kl‹uÆ1Óin*•Ó¢¨mµ93Z™º£+† ¸ü/__k6ò2À Æ$ðTž#ðãœï-Ìzþ²pÂçÍ«Ó5—o$¤yìå’E%–'€«z··øåõL¡À#¤ P@,$€&ˆø¦ïÚL>U<û¸·&Å×qÐêþ¯‰j±átµÝl?óHüVJ/_Êk©Ûÿ…êí¹âàMÿ7oËîR¼’ÈŒd#¶TEÚȼŒ‚[\AbÞù))I·x%ª— “µhÏ'v|8\XñcÛü_¿PÚYwsK»îߟì·ã‡ÅÝO yïa¨·²hül•|áM?‡Šùóó|¼o deºø°cSß¾K‡ìÜÈG¢Þÿò÷üQ[L†ôAC¼Ð» î2òÞÊ‹5ا˜*‡™tÂR«ó¨/ÐÇf¼gïýÎ âÌ \¸f¶¬œÞaj¬tí;hÇÃõ¹»®T›Íàò|æù±]dåA«¾ÁúYg)ésßyßs{ªb‹¥?'£ ½ûw‹ÁCÁ|[¾s—”Xó}Ý<ÿ$)÷çŒF¼ÀÝ„‹ ³Ô:ÀtØ{R´B?÷Ù a;¤îc.öŠ™Üt=²†ÉK_Û»w aÖvâÙW•É Œ¤&?°C{³3‡K"}¨Í‘x³âÝ K9ÍXC£ §5 lFœµÔ Ó2æøÒGÓN`;E=¤^©ïí+ëÿå…­=ÂðT¡b¥…!çY«PºBüÁPowªÏ>^z|€û²ußïÍ¥ÇöUŸ8—„Púø½†”l5íå‰Í“"QöÁÏŠ\§ÖeŽ Žó‰Cµ®ë[‚—1†é(º±î–WâÓáø>s„LïçC»tß`íÞgxíßX¢É¦8rÛã-§¶†š ¦; m( o®\MÒv;H»Òåd#ën RTFâôáü‘Ge&/§¬À'ež,¼û+Za¹DhÍ1ë$Xð)Œa³tU¨H äÙmkæ7SZNöíò@µÛYìÈQ‚̰ÿô‘X_°1el@’;=Cƒ¯zÆeÅ–…Ò¹ÚóOØFjΟ**Bz¦ ®Ã(µŽŒŒõ·áÐá¾C'š“ÃC7n6" çšáxð(!UʈwÓ±k¾}GªE‹@q¿¤1(-Á ‘G¦Ü«ç¼¿ñ¸zñˆ¼r+oCm|P×Êöâ÷ìØR{vV¢‘ÚÆûl¾…=¹«äª&má°.43#*ÇlPúo¾TÚÌ{ËÛÕíVfHXÝÖ= ¦u‚¦IkK DŸüy¶·ëÄRºT¨‘‘ì~’]U »ªCJ ã%eÓX;Ž™õ¸ÇÈÆÊ¸ Jî=ÄJt‡«fbÌ›ybl»:Ö¨` Ò¨fHÑô̰QÀÉ@T:˜ÔP¹µ¡ƒÀ­…J¹GW"~gY Ž©Î•T“H¦™&/6ÃûéƒÛE¯Yr b3ë #ëé@T`¸Ñ6¬AF«]ÔÓ6:8Üè틲“ CRû¨$r€2tÓ²»·AC„³M$sÝwcżw[]º­>½ã¿}¹ôöXØætÁ° a\½ÃÀç 4äò®#qµ–¦E…Ÿ<(vñsd•ñ†krm3è§Ì«™iHQ>ÌW-ÿè¢eáè:iã<KÄö"žâŒÍoüV¸w¶uwÍ•0$6TN{q9³ííÈŒòxÚöÐxß¾fÝ9”³Ø¢fv~ÈëÑ-Ÿ\aiæɇ#•䀰æc cÝ£^9œôðçîdI³¨÷@ QA– OÄz¨ÓÁ~å)®uQOioo_W³7?”}±]—AJ‰±N Ä [àÍ:µá °V!ÜB¹Ò}w—Ì…+æ“Ûòüýè«ñ7ðÃâF圖„3¦Ç-|ÑFƒ.Ï<ÎíJáßXõÃå[¿ê.|j7Vméx€r‚€‚—±nµàÊ®Òe϶B{ç:àyZçŒ߯ò#F_×éœÂQ9¥(°RÃÎÐ?<€–{º6}í©-ÒÀ—~"'Öñ•Y|€_]7:©L`Çg;dpöóÞ¼R¬w•ƲÙK¿ð¬ÚY!¿ý…êýùôêÅ’¥úŸÞ»9uÐØÕvg¿ÿ†[n bOUzi|JÆ6Œí?Ý÷³woö° ~÷7Ìsx±ïmlÛš×Ha€Ú,t÷ŠbÉC¡R»)¯åjk©2×É÷íøèÇ€ï'K÷G˜ æ‚(Róî~¨ºŸÂA°w—½Æ¬a 2XÍÇq5IAE x„F HtÒc—i‚¬ÙFº)ìò¶l*L‹¤ÀFjÞ&Þ#È Ë,)kK©#˲cÐà!­±´² îþFpöI•[ºjÔÎ'ÑÇER¨m‰´†: ʰÓ1ˆŠ†A½ú4Ôx­À£#üü ´¨¯µˆò³ÚÌh·×aرã†/_aΈ#„,_7C]¹eÜ’2DDwsÀü -1Á‰¥_}Ùv¶ÙðZºW0pR %kó~ä9Q¦(q!3sê,̯ñx/=Êþü§ ± ®«GreMòSÌFÚ–¹‘M µNpö‚6$W[ïºù†ÙR®P·R{ŒÒ”PÃ`¿äJ;É"Í#›·É>/ìÕ;q§zóF§=ÇN2×Ú„‚ðÑtáûtî¿òÃQ¾º½¼UÚµÇýƒ¼÷qyJ ŽÜu§~ +EQ”R@5/<¯€¼Ïƒ×Δçslß´zã ^ÍÜpmpñZgÊò7õôWŸÑ6‘ÂÔLj¾ò‚>¾“íϲ^úç—h®4 Hóá£ãÉôÄ «ÀÜRò“' ïÖI„žÝ›ÎÓ{&ª}{ºðVùa—.£ŸÝãu¯ýˆ.;xfà­{ò­+ *£¿÷kÉç©’5¶ó–3Å\[G\^%s2_bKôkA‘6—ûl»'ëï¼Óæ·Õò½?ƃƒ¹"ŠÖƒ{çUç4ÃLû!¿»àU×e9'¼W„.ì* £2¬9ºLŠ.&Ê(έÒçT×£Û‰XÜÊ;†RÊü<óQ& ü;Z4œRÑ–aGe÷_n\i$­*;}oÍê#À[×jדèÒgªÑ‘M‰ ©û5Ä9“Ç®è³Ðá‹gÕ8*-d0:îÎ_f¡ó:Y£* 3´¢â©cÂÃa‚@˜Eœ¯_±õnÖÖfÞX*9Wí Àú0.ãE¦K_|9뾿ÅG‡ìÒ,0¬„Ò@#kD€²Œ:í ñâçK78Œ»OGôº 2¹†a[Wµ•ÁÃ…¶˜c­K {™ë¶<;¯ eÕj‚9b ÇèJâZº!l‘g¡š3k…%Lªaûe[š2¶)‚-JÓÀ»~ÈÊÒ"´nâƒÌô¶¼Ô¸]§ˆL“€áÅ…Ê'ß©•­{Íx×ÞèÝ_ óAeJK„á¾È.:øDë¢ 0U%YAeÀ+gý_;ÇNÃo|–¯¤ n¨:u÷“Ʊ€7%9D>5› ÛßJz_~™Ûí8Ðnl§ß¿4šÓ(èýì(ÆGùµGÓO–ƒ+³pæ S(ßÞ®¿rÌó­ˆ]rñ¦ÿúÊXÇJY£êåsAR÷¶ZhðI)ªö;N”Ò{†£—^LÖïc‚>4æÇluu»ÀÒrÝi*ás‚öé|Ôvmsâý‹IØëì±Uêzï=›Œ„‹oéï㽑¹ïÂ×ýÜWî°RNâ(|°œ™+ÀºÊî%$3‹±1²lœ Ôøvy@öB©Oû”ÞœY¼HKjU#wzo|rÒ*÷ŒÈL¡ b! &d»@i=¹õ.ªéü…ϱ½'K^K?¼Zjc‰Ãº¶åÄlY¢­†a‡G'ý¤|ý‡»Ë¦>Ä ¶·„4×® ö¥dqŸãÜ‹zÖì9œT˜ôÌÁ:U½v%—Ž+ÏLÉàÂ;êh+ÇT¡ŠSvS‡¼•âÓŸ«­O„?Rò&ÐýEËýRK*ÈTJ‡†¼ØdF÷šaM|ñKƒã{Ò÷ßI¯>„ZY¯°ç‘LY@kk"§†ËÅñÝêèD0ÞÏ[‰è¨z؉½ŒŒ*2¨ÖŒ§r-m;ã*Úd³_Fd#7œ]ðȈ0ž¶¸;¦bÑl¡>ìG¼k”í{ÐJÕ®£põ=;ÿ«úPÑ·a+ë~ò™iNŒ©”£wéÀû᪔fÊ@È”Ë<(Îèÿ‰Á ‘ÝÜ'oßæÛ µú„ʰXïcOÆÓûÝÕ+ÉV…F#¨ÂÞA“H—ŠÉ¿üÐUíÉiX\ã;&òÝå¶QÉÕàÒtf?dFµÚµ——",iØýÕ]ú£óÜóLº‰åéAUómÜÿ¸fcô;â ™íòl¯9'j¹wzßHµ†æ6:9Öy˪›9,£ÀâJ5!•­‰>nT{zÆÔë<œõ3›Ž‚ ?×Þ'ûc=oÙwb9ÒA#NÅÂÍ+LÅÈ~ä §Ýà*À,mtã Í™¶y£Ý&”jF©}@M P¸N%´Í”Ní G*]' Wh`§‰0`¥ÈPl6z¤$Ò^Cû­||£wþJ¥C ËR´ŒcTD¸‡ù‘ÓÞ ‡®¿¸³ ††¨†`kË"H#c€—«ü”ôõ(2 Ö¨:t$Cæ…5Ö–n|–¤;ª'Müˆ#S%¹(A¨‚€©™ò`U\|Kn~*ƒ‘ÈÛá=XÈ™7Ø”]ç“Lå€Fp(4!²x´óÊ«å½Çíù_æÌP +‚L#T(p–q¢§Ý/Níb''ñ¾ Ñ+RjSFÎ0<,·¨V(–¹ÔÆóu¡µÒ:Ïê— žAlÖª{ §ÎcÞCô)y¹•¾GI?˜Ú+sÑl»wä\ÿÀ]~'Øï²ªâZ$o_ ÕöÀ¤ÚÐ8ü¥-½ïåH 6ŒT™r,ÔG«Ÿ¼6é°s­`,¿s‡µ›|i^Œ íJî,ð‘*;ö©ó'ÙJ›fÈ73å´'|ƒ*ßý”‹Ó{ÇW¶Û£cjÝ’ß|ÌÿãI·!çÕn!‚Åõí#SzGUnVjú ºÙNNZØìíOžŸÊó™G˨bÿø{å‡i/ ¼‘Èìö£»ß3ê— õÏ¿/®®ÏgÛÍRD«-ו1WyuC¯uÔ]:@ÃX)Uˆ)#];c“û‡dÑi­ú­ÄûžÁÆÉe Õø-YºÛÝÂ|ìøÇB¢rËdH;îõ­ÈÄ"°&P&­ïHu2Á\ŒÂeLß 3­³/<êÿ·¯ <¾³85“? ªøQiñMB…#Ò §88e Ÿ»›[tfBp~ûG|› )L?VD6­õ!U²¦¿O¿ú%ÿæ÷Ôa_ŒwJÐŒé^¾i8#eÃcˆö¼xÌò±MpRìÙ…jå¢-Áªz.Ñ&Õe å?ØgJ;]¼P É™YqH) ý¢(¾ð¬s‹c³þŽZvwÙ?ñy¶|ߨnø‹0®ºV…‰vnµ'[ØÉi¾ÔîýÉ{¥A’·Kµ•NDAÎLE‡/?[úÆËìÜÑìÄ„zdîXÍuc5™ Mɱý†îFªds–myj2¢= ŠZx’×ËtÅ©k%ÿb/G–õ1ü§VÞãƒgï+ {Ý…#"¢¥bòîëýäÍŒw(g‰Á¤,Õ8ðärÇ÷µ½£z™­êfº(¡!Rã}Å?û«ÃGwuî]h$ƒæ-M†kó+I7‰[Tn.ô¿z.ÙûXT­7Aèó³|¹]ì@ØÚìm%ôÀQŸ‚|°m¯ÜhŸžÆ¯Òï_Î{.~n:ôœûö…ÆöÚo¿È…“ëîÀ®ÎŽŠëÐèûoÒv·{jfǃMZª°'fšÑ˜8t—†‚û‡îa.7C:3_ý® çÈš]áEöÊ¡¸±–/7H‰õyj‚À)Ø26£uF&Šæø!R HDµ’¶›ó‰ýC²è´W¼Vü©VÚÚY£wûýßÃö~ˆåê—$úH*ÒAÈúµa¤²aŠÌ8€Xé4VpR²c8A®Dü þ‚÷¬Ë¿üXüß½:rfB<2Ó;¾ß=XáAùá¼M#MŒ%Ò «ka€ãkÛ°g\qÍ¿ýº ]ä ¬ÒÀ¦ÒCX{ÃÌ•5-WóÏ}Ù›ýÙG²]IÁèá‚y6ÖÕJÓ~gDæ!—;Î…•ãzl0\)¶rÔ“U-½-"Cîúû|´_Ôw¸hEií[ÔqWcßô¤~öÕÌ,ôí›%Ãqw™œüBiùAOtSßwyQ¶ÄÕQ3D¢S8ˆLgž>~0^é¶~ÿç|™u¬•dÖ¥¾ÃZ[9ïŧ+ß|¥xõxñÈ„=6Æž:ÌËo.çË\:?ò&¹ì3E\x xËÏ™–¡uO‘Ú>ȶ¬¼çÁP}Øu¾ãe×Y¥Š»oi])’¢žÇÉ‘Ã~\ºðF^í±‚v1†²°c~9(Ö7 ¼òO SOCbÑ>—¢£ÕâýëõÓ»“…:âC¾qSÄ“µ¥ ·ÞÔ=bïz/?%= EÛž‘Ý©¬$ÕSMcC­äôðéjÈ{wWâK·¶™1/Wï}f LŸŸòÈsƒ?|G–äß|©²±èº–MNTÊoÏéošŽá[/ˆ7/ç±zn_˜+ß§íÿ|~ôû +qú°®û®¸¥&›Ó²vã–÷ëY¡ìžÈlbÊ¡ *ˆ ôФ˸4ê!Yh)‡0U¥å¡îó_ªº-oÔì-ÏÏuÖ‰î*9ò €MÛë(ó1C‰ì «P7ù%›`›s°Ô†EªØ$ÄÆ¹Æ‹<£¯>…þÆSÔÔW.EF8îÙÓ“ zyQ;]öH!zOXÂ,z±­t~¹ˆŒ¡(¶‘¡ æ ¨LÂßþZe¦ÖìnйíZª]|Nô®ÌIÙîgØNÓÞ.·uÖ.ó³/Æ{£b¸/ølÖþò/JÝëé½Å­+uǧðP)¯”‚[7]d­Ÿ—ív ±R÷ »¯=Õ·ÒØ\{@W šØ•œ8’Ð׃ÜŸe 5ן"C ê6ŒüìaH7‚`VrÌ+‘ýÎì×Ît1&¨JடS“<>§ÔÍßq Ç ÙŠaÜõ½Ï²­XBA-¦Ì©€sÎXçnòþóÜ[½Gµ0ÐUé’! ¥®?0cqþè×Ë;§u¹[ Í ]YÛòÛÕ—Óî&‚7tù.ˆªLÁßGû¥u”tsýôþ°Çºw…aD<ä<»9/›]W@õ±‘FîÂþļ9¯7Ûæ÷^ë®,Ó»Ûzï°>Öï..Æ>ÌÏp8üÅ51·!^›AÌÿò-Ѳßý]Yñ>^Lwï8¶;}€ÿèÓü` ¾þl÷çWa¨š¾r¨¢eT‚ì®Äçï$8PžpN±þ8KïŠÆ¿'ŠácÒtàG—ƒT’qw;P:²5 Ñ$+*¨„È7Æ,éAe{¨÷ôWú+v³4 ñ¾øþö:±©²ÅwµhÙRæ#Ré´³$®:>nå„¡M0ÛÄ)¢@sç›Tã)WQP,½Ø$¡¯<ÎÿÖ9-d#õ dÖœ±àÑÉmàÊ,â!’3ì8%MãÆP}7)=l›û«I Cd"ÉhÉŽwBi¨²è·¿Rš*5󖸳%•ªSù%×Ý®êö’æd['—xìe:‹±=Þþi5»Ö}pK^¹Îñ#û{»Â¸>à®}eMüØß™RÅØHüÍÇK^cñamÙª»ŠãG{Ã#¥k7ÂÔh޳2¸šéÄ”ŒBÆÌlùÉ|D6SÄí|ЏÈ9猪JÈ_=ëãL SfzPHÚ‹®Ä™ýLÒÒí{ ©4 Œ6¦öQ[qîÀa»™=ç),è]¨ÿ’dÔ“ç‰K™ÍY&0Hcú9§¾îOeaÏ í¼µ¾7Ë ¸bºpIªáu\ºïd䆔u”'ÖO½Þ¶´gGƒ¤œ.N$I› ¾É0/'Ÿ=0>…FFZ(z¦¯ÕÄþâ¯/æëÛÅï½Z¬®ò…ÙYêÙ—æü–²Ó“Õ¯î‡÷o‰[[èåÝœŒMÕ/Üé¼tõ‰”Þ½&Çúìééø÷ßð—{äo½Êû‹]Õ}!<~TW¨¸òý§·Zý­”\O™³ûýS{ý•®·Y˜±ÇfüÿQ[zø°ýǿ㉭äÖrl¼›Ä‡²¼yÉU+ô¥ñ°\ÆdbšMÒ¥†1íÃs¢~ŸÛÖ€,Øajl[ä‚Ó(9f30~ÀñkØ"ãLn5ÛgñMn;…™/ÿ÷/8’û8¯z\J=àù%28°Ë_X7ËëÔ€¯Qn=Œq@µ«8¹PG‡ÄçNÇ»wÞc+ÃnbÄöÑÄý}¥‘ñ¨™æ}“ƒº"úïM*~Æd|åAËQÙU0]Biï Ì8G•u¬¹¦ì=:%U]øNÓêxÚ7ªµ‰ Û×x%EEÈ>.„dJ9ý¥³lj—å#LvñHP2¡‹o=ÜÞ7L ˶2΢õL錛šèã:d=ï™Ãäýòî2zõL46Z ®/¸½3[†¿{3yé,9ÒŸ%$~ÿŠÞQ5'öùÿúÏñZáý½/—ë•ìÇWt=€'Žiß$·Wè¿ýi¯æ—ûêv»çžÜœ=Éî¬ú )wŸö\Õÿ?þ(]ËØ±ÝÉ?üÛ„wéåÀ‘DûÉÝ’Í«ªDH1€óõªÔ•i|ø0°<×ĉ\u®VŸÏk÷I¾m° J@©²=l}ç?鎄ÊÃû,¹iMj,ÃÜ!‹8ª{ƒ˜¶c}ÞÿðŠ¢S]æ^ž‰2ñ2Èrc`ÿ®puÝ.®!±B3Fu UœÜÊã=Ãé— ÷ìÞµ× Èþ=¢J#}&"~­æ…©ÖñhúõÎGÓáà SªK·î¶KXnk®¸XÚ^H‡aîk°~gEáÛdº(úŠªéúˆ–Øu µu­Ú/tÞç_èt9µÊºΠñ=šb:Øå£áèúr«(ÌP³E¨ÎöÂ(-Χ&Ý‘ƒìôôÈSûÿÿžµìhª=¬0A˜ 냰Çvâo>çt¦=gHÝ”‡¡õqQÙ;М].¯uò$€Cf±]±…µàqØ8úK…‚  uÒÑ™\w11(9H}(Œ£Öý1À…Ž1CÔ°Byuµµ/®Û1ÔUÊÞÈ·E©k{,êwÅ–ö ÊË_:”þîoø÷ZÉê}ÿŽxd Kþj™ñàèA¼‘ÃÅ»t¼B<[¾µ¸}` žÍ;B½Ëm ûÕ³°s¸úÆ5—%þsÇù·ôíüÊcþDÐnùèÊC=<^¦^ïEή2ß9®ÊÀ¶6‹[+—ÖŸ8ž‹«Ì)Å%µÝ€ÿx_Ñ}tÇ[k‰©ÉÂCúÐóº&`V“ÿíDU‘ÐO +)»_{bxrGëßœw…ðLº<ò”ûyÞwÎïž-Êã­Û7àš>ýou›\ùS9èÄ<ØžÑÀX df`øWtžyЦPb(âOö'„ jü‚H߯’ ºìŒxt‚S4tƒWËŸ—«÷“¾òøÈ#·OO‡—ï̬r¡Vʵ ºcªl±^9ý ZJV.÷ ~"=þéÚàO¾Û¹5·=ûíí€`L×8óÊ”KÖ bè÷­ö"?O¹7²œ­ít¾ººY”뀑íHd¨K¥á ¦i†VÛõUsrŠ3d–ó„û‘+Ò"Šï.‹ó”ä)0…†$[ÖŠXâ¦Æá7¿<ØçÙg³ö»%¶;9øÄöXÀ.] ‰*,›Î!Q‚ʰ‘åǦ°Ïš Qq¤¸þÚx@‡wñ'¬Ëí¨7xrÊÜXM:è} @èHÐŒ#ö1Ø“›™Žàð ëØ[¶YN€Yš!€uÏèÐ5êÚŸ:ÿ·¢Ê z÷/qÏ ÒÁOQûmN™@ÑP–·Á ²¿®ôÈ®]*?>ßf[~üÏÿCãþMýâtÚ‹ ´Þ¾ipo’Jtæ´ùÃ×ã÷žø«fÏ.[ H©ž8Zß<{¼ráÓtvc¤ÕZ¯“`×ëåìÉ}ì/ÞNÞ»Ò‹|xöpä 7¹ÃU‘רJï<½»Ñ;¾OJ¶{^†µ)SÍŒüëw5òågÐGw*€7÷δeÛ;õ¢ª »@«ÿŸ'·ˆ`Ÿ;rÈ^8246^ü‡·I·ƒÖñj\Hºâ3èØÖ³YßÁjãÎMøaÖ}ök¸Hâ«?6µ¼· :3`X;‰­`@Dļê"^O¢BõÊ<)ÑiIY /Câ–Á²NÃãÓ~ˆý,A¸òžÝ|ÀvÑ#; Õ>ÔxlÆ¿<Ë•G¤åVZd½uHû3+“5ïÌ+ábºyëã"~X §_Bm|÷û½k³éÝï@ÙãRo•b^¼ =/†‘’ËüÀS9óFéjÝy¾¡­u©R¦S€¢®­!´ /x£ÅÍvKȰÝìô$xÄŠ" ï?×LÚ$ƒ\¡$[7ŠhXð8LÁ¯½ÞïãgÛí÷JdWïàã›ã¡åÛ!Waܵ\AÊjðÑÜÄÌ jÔÚ”¥Ô÷Šth§9ö´†DŽVûOía×WaôMFçla, 5ïù–(þIka´–ªf.+~ ‚aku±ëÆ‚:B‘HêyœÌ`}ëQü[Qm¬xÿûYq=;Á‰»¸óÓn \»RUuÁòw?ÏO Öiœç.;á—ÿÅŸuÿÁïØgvI¹¨@´“d€â0p_zšüŸß/ÿÛóâÿ9àö튈q€A÷Šãý'OT?ü4¹q¿½ÙŠ€îµD“§†?z¿÷þµ6Ûjg9:¸Ë(eò(½ûPõ”[Xõ¶»ÝÿþÕ¢ʨúë—t}È{~ü›7ÈÕUøú þÊÙìÛ?Ìᑾ­V£¼ ü/V4Oò.Ê¿uλö»óF£Îø_yUͶM¯I'|-#÷´l‘jêÏÖÝÜR>Dk±Ï³_P¹Ž Á#ÖJ¤A]ãµHPŠúòR ›ºã…q;ÊJ¤xëP…„»\ÛUÏ…¥sŸ?â÷ ·ëÛäúOãý¨ÓZ ½¡þá°ÑqCéí]grÏC|n éYÉ‚²È6{¢>&—íöGp°¯ÍÑ`:_ŒßûHIV*À8 ©­,]Ë]£…­LZ4´ö-ì 2ËXë¡ÜøŒ®^†æ’‰£’r¾ë¤³Š7¯xë—Ñæ]ÁSR ÄE—4 ‰ËAloáÕF¥!”Iw•gFTVˆcJ:Ûz°Zµ°qó{0Õ´kd#(:ÖþòíÔÞ¤a†7à(ãÚ*›j‡_~¤GÝ•‹Ë}+o§;m¾´Z9 úJEÛ¤JïßȹUZ“ÈCL— ž=.à‰ªFžO!—Ñ…P]¤E]±Œ[«Q„#O#‘Í©:LÀfÕû µxUðYªvDñð÷iâÛ²¢RPffœþÏ…ª{èæôÖ:~Ì~xÍË“¦„Ú'³âé}þ`¬²nlŒ¸xg¨Ýkü?~MR_”Ý®÷Ôþà r«k¿uf°n’#êõOÍò–n%",‰CG2Ó¥=‰½æZ±±&úJááqaµíÆé½²ð`­¶ÚÿÓçÌpª¨ýðì\'Ÿ?äýá/ÃK+ù—W¾t®ý½÷SÈk/-Ê^Ó¢›…ÿèÏdG„Îö|Ì¿öœ½ö}>ÿ Zõå—Š-[ZÛÐX'·ú¾³™ Ê2Ÿ2Õ¼AÖäâMkA…o‘b Z8S€檚lšSR/Ê>%Àº©²s=ò€ ß„ˆØÂ˜5B†ÀçFåþF)$í\v«ds¼1g=Ù.ÀðçWºÊå>²Öz! ( ¥@õºUž0 KEï˜n™Û³1ÝÕ]ߪ½ùËTyE “Ô9e4jeC›¹ëµh»#)|-iÊŽìäJe¬q¿XºL–.»Þ8Y¿&ȵs×^¢ÛWÑögÑöý”öxÄÒEçÏ[ìy8ƒ¢³‰¶·këEž$»œK%4©HÂcím=X¯Iظõ—0Õp3T=ï¾:§¶XÜ„ÂXK0c„h›sGž;÷±^Í7—ËK¿» XÜô§JõZ31:3Þû·S_Á µÒó}ª}A²³Ú?ãK›¢!TB´ªt¹D>V¹"ÆYTq”bOr­•EXîã>ÉÙÜv6ÃÒ;¥½ô”ø”Þ…ŒbÌuO›"T°sÜþÓo q¿rÿÇÝ•µ`æyo66I#ÿâuñÜ‘¾ñzÖm3„Õû×ÂT$÷+=y,åí†ÿÜÑÒëŸÈÍ–úõÇêMí´?ùXµš¤ ªÄ‹SG‹<ÁíD-/–î¯ä¤ÀÐ1Ñ{×Íϯ”>º‘-5¢mC–Ú©¡úÉCyË…õÑê¯>mØXz}ÿ#u|¬öÿ|°½þôZ©ʯ?Μg—·ûþÑ÷6Òõ+i(œœÔc#ý+ﯟ tvO“ß=‡¯«ÚòÂ9¿À¢RG (ëàp‡‘ËhZ 2“Já0*Í2ií ìBÀDÛ¹ÐÀ(âý&hœÛøt= ûÁ[5zÕY‚œ³Ä!OzîȸÛ9&TA$¸ÎBMÙ³jì¤,3B¼¹MýáœqØ9£ õ‘Îw©£;Á¤.Ö˜íè·É=^Õt“ðÒáø»Ñè¨r[£žUÂæbäè"Ûô+dgâ_ÙõÉlq¦´Øë \³jÐØš1}Õ1Žœq9T0¢Å+êHùÊÅ–e?­CO#ò×¾>´v·ër³?Ymdü6Ø•] ‰³ù»GëP–$AQ¼]žóWVMäÙEÄÁÔÄ™ÑÒ0ˆ?2 »‡µS61z릦LÍöMåÀ¯Â½%üñ­h-F– ¢Sƒv‚ú öÛZ?°¦l뜺Ôt×Û¦‡¬¯‰4CŽ:«aÌ=+Ë“F@”óMì§q`’Üš7=ï ëb‚Íê(êúÌÉù[éæ²»ø:˃[­vmO_S·:ëÀ@$N¿O›Žâ´Êƒfu£ËÏMˆ'ŽÄwªËsE)-ËU&^y±Ú)è†Ì¶“©Ï666{Þ'7åÏ>ª¾q½XËqÇŠ‚¦ó?¸¦Þþ¬ò«ÛÅòvÔTn±“:y(ÛT~Ô^¸Ö¡5ÿλ½ÃÃÿKYoC¿ye(ö¶¿~:¯´Öƒö³t³g<—0>zØ¿ÿÞÖQ‡gxzÿòÙd1©Ím*®¨ õÔÏsÔ@W!çI µÄM}åˆ)ÝcÒjL¬-Àú€v²±!ã„ @/ ^fªwmâ)ذlaƒ‹vbʃƒczfÊ]ÞUEkÁò.#'U•cL¢¥­â½;8X 3â Tþ0Êy‰ ÆêNÝwDÛŠâcôû?n6Џ£I &·¹…9²Ž¸Ns^вo}nç­ÙÌqÚ³ù„sžÃUdú†´p¨¯ Ó¤„iÍå}Æô¹4²Z´ü)VŠMæþÖWGV—Ú ÂV¾5¹ñ20)*zIe0 óÍ=‡Âæm( œ¢¸t_ VWlè›y 0XM¶V[b™ñMÚ™!'…Ô5n[—;QR#ûG ̓5rqQ•5ÏK…˜)c^#X‚¹gLèxà—×YRE×ð–`pÝÒc´Sîó²¼K+QÎIÊÍzÙv[ØüÌg7lBk®“J¡ŠGïûWß„åïúëùã±wg=‰÷•¬6e¤U—¸ówÓƒCµJŸö”»±-m«Wgàñ}þýUüÙl^)©¦ÄEO¼üB¥“³-•n¶w~²²Ñ0A£É®Ü1?ý¤ö敼íâÄe„¸@[!‘®@¹-aj ½nùGw’÷/©{;[ëÃÈ+º@‡Cøg_F–l7ò¡_\ÎÇÇÅóÇõÃù¯½Ý>·»fp±žš_{Œ’ó µ¤ÝMõ‰gÌ{Wáâyg°”>#–d©á€ÖèbØVh"¤Âˆv ]²tÙJí@ƒd}pKଡ_4¥V)oëj»¿=¢·þhî ;vÉ+”qyÆæ˜j¤SÏí‹Z…J¶:y4¶÷ièŸHš™Ùé£×?ËooÅ‘‚(ŒÚQkè‚yžrIC<þ¨ÃF.„°û)sþ’ÞX;Ðvž–„¤ý(Je'¬$ Øô…/׎iݼ¯ZÛŽQ¸ŒÜm‚gytÛyw-YÀ| Ð=¥îšÇäŽa×€_#ÞMBïP¸f$B47bbŒ}ù%ÔaîFwC‘pbs¿åºF=&‘’¾­¥Irô)´š¡hGºcŠ¿óz!!(PÔ±=¤Cƒ¤sšX–b©èm=3ã–rRê“áP9÷‡ö?©F‰P%µï~ÒYÜÀ¾sKrFµQ@ÔW´7dƒ{TyT7{"MCçååÄéÄ:p@"­ÁXî`À²€bµŒ\Â+oªì–•žÅDqå„8Œ³b+uöM¹Õ%ÓmI9X9y4 xç¶Ý=P:<\¿³^^hŸÁåìÒJ±ºçN„mŸÝi®lÄ¿šÅ Êy°±õ£óð½Ouc³jMÇ“YÝ+lJ”ÆÀÆ8Ö&p.Ñ` §uî*e‘#ívõ‡w:®Û˽•¡Lñ‹óhG…ýã×RÏ“üøB{b?{RÝÛJþÅåÒúÀ+ûûÃ/wÍŽë½}ÅÂÂHž6»ÃæÈcò“¥ø³ yá)´Ž ·*§t˜†Ôm©ç·Z¼â”P`îœÂÎ8n¼/j¿½,êUŠø¹Ñ êÂØè³0Sö†”K¤=fÎN”zJVhß0OØÎÉ300‘gÒ›Ð/.7¶Ê< ]^PЈ1Œðl„Í6²³Zðì‚Ý/à WìòR£Ds#0¶Hî “T(ËrUsÅ+_ªŸ:Ò¾÷7¶ €¹EaÓÛØ¿ã¼{à-ŸsnÖèY ½ ìë8¸AðM W0Y\ Ôè_våa7{µ·-£˜¸žÉY5H•B8ÖHnª½^ïÐSn-ƒx"Û¹›¿ý³¼p~nýŽKʦl!wÆ"kYà Ãê^û™c|¹gË}**¥^ýÐãÑÀdGfÕ ó_ÿ¸;ÛDhÝZƒ¹Ö<óe[ªw¿T®É[‰èt*Îë=!ƒùóFPp€œ"Ú9GÀb¡‘Õ AÊzœw½øß1w` ÷•T0bÓM#™8°[nÎñV+·#õGOJÂä;7ôôpåøøÐõåàÒýîÁ>^—æÒõíÒé^ãSãîæVéý;ØdQ·Ëç·¶þò=ó½Ïl{³N¡*8“ Ý¡‘UÚPˆBš€³!§HÏiÍ´¥˜@ÏP.^éH¡³¼èöTþø ²w¼ïé®#\ýÉÍ<—ö|­‹ÓôÒ™»-OF¥òg×Û'O›¡Ñº2ùlbï.È4IË]èä8hºˆ+P¹ƒ<Ô‚2Æ D±¬ÃÆzHA­¡lÛúÜBu~=.]Ú-í32äË=ñáe8{f`tÐÿ¿þˆ>èȯÈ?÷dçß)÷~÷©ZÕëðÝŒT?©~p§þŸ~`Ó=5¿~nhö¡ì&¢pÐÔ L^¶¬ŒP£;3e`qàÚú   ÅŠ‚ÂÐÃÁÌcé˧jk~œÞî \.*p„–­nÖèÛ‡û”Úô™Ÿímõ×ò|õõËÕféÏ.ÈFÏÄ…™]¥´¬±4Ä<³´ÌºÖZJûžy bsëñ;µ¨®°Î² Wª÷ë€ÁðP鯭›v¢hP³²°ÆÆ LV¶åèÄЩsÙäûÑŹåábEΙÖ9!¨àÝSAÛ.K ·{<˜éÏGv%„iš8 ëmñg¿2=å,%¡Ñ9¦ÔÚLj;á–•äIþµG­ëž%v£Xã÷LG9BRÄ 1¥mí| Ö­=AˆÐºÔ—„¼é(vU…2nCêz¥žR±¶¥Ïß)¥Ô{éi©wO<±x¿q1ʲ¼•ÔfWÒƒ#¥Ÿþlõz·üêñ7>Oï<œxûúöÙGv½²wc]B-tÕ:ùÞ_D?¹Ñ4<’ þáçÙñ=zxпéåÖìÅa_.W#žA’3žñO5¥N2Ž£•UùÆ%.{¼Õ-ÝXÌì|ó—«W7KŸ?£¾õRôpið­;Ý3û†Ÿ=¸‘¨ ^3q)ýãïÆo\kÙjŠâ¯¿ìž;ʆà w{ÚàØxéØ>¨ÚÌÑlÕbJÈãùÎæÔôYˆ5Í0n›8o0î?õµbw±å•!9»m]˰ö*æÂš.µ@¨àŠàÒfvl¼\Ꙉx × G‹Nò½™]Ûèx2­íÉ{šÞ7Ò2‹5F•4Î@Qo¶™œ™–,…ÿò§½5%¦°Î·HRÑ™‹QëR®’gÏŽ…¦ýð'rþ¾Ú3en®U’¼m™éIÀ,£Ä+Àj¢1%)Q´ö¥ÎD¾ïd‹Äô¥cøò[vþ­,¡ýss.æa® ­BÆhÉhµ-{Ž öf{ÍLáß¼Þc´fDÞ*)—JcÜNCñRÅVàšI½ÑLºòŽŠna›‡j ¯D•ÍýßÞL”q°ˆfV[„Ëœ~SheacT<ö’H´4¥îÞµÊû]³Ê­a¤jaÈ@ÆÝóF ßf6.܃qc±¥çYp…*‰”õ³P!`î÷¾Q:{XpõúeDüêìRs{µöì#bçP¶Ñ ú¼ö’¸¿ÐÞ3é%T€øhž,]íô¥Ÿ­ÚzLïÝÔÿü‡ñí¢âbCˆDHÕWþ€J»J©b6ŠÑ”„ í¤µ6'¿ÍÐN£¦ßéÓI+·æ¸†LGú½°Í2Èì@•d…Bí²k«þÍe*´Ðew{ÙÿðbùëG2ÅŸ~Ò^Ø®ýàÊ%^è€IDATDŸåCôâ¥àÿüK÷i¯ãYJýô>ÿða÷áOIäeûöÍ-I‘1N¸»mÂbÄŠcšÌtõ§˜™0É#™p¥Ox¯¢ƒ/ÐR-kn`5<\ª[Ùætm5Tkޏp$‹冸R¨ÀW ºÍw—·E¶ì,N³è³;þ?#™môy¢uÀÀ!?¢y•‚¦Ô]ˆ}×ËuL˜­ÙÜÝ@¥®–7[ÂYžÒbغacÀ1…»ÃÄúwè {áT¾ô£¡c6É·¼Î¨"Ê>Ì¢JâÒ@u©vN{46Fx|‰¹5Îe¤ªAY¦£F2^0³g7pÄØg¥#8ëÎG‡¿öz¶³š…ØÏ\o‚ ›#d;ÄÆŠhHïo–äÁêý¼Äò†‡“ÌQ!7èXàùEVõ#%p[¥KEtéžb¦2DXâ{ç¡û·ov76GíF£\*çUý¶Æ²œ1Ì&öéá5­»zâ;½1WYPõëvà-F™;¦ÌŒÇ<]© ä«ŒRŸ\àÒ*!D¤uÌû;Ÿð[[×/EÃGŠ¢Sj.w”q õÉu=PªŒî)Xâ°îýênˆxòô$~dÌ —£¿œËnFL䟮d÷¶˜ži‘Ôã…¡ÚàÀM:Ø/í1ß<)áI@»ÙÅÉ!‹flºÁ4vû”êçt—3®8©ÍI þ-)Wr$õ "zJƒ©yÌH[gÍÍMruU– <ìà»ì>_ùêA÷{7Ò{‹õoœ(våªb®Þù?¾g¯¥=b!ÈôÉi8yоÿ}âྛ S1œ¹.1Þ0SG-l·ßÕ^ n‡Ívcv±]¶ú ïÅ’¿†ûJÅê–£c¤®¢Skk¡^ÇŠÇMzßY ¾¯Eá{rÙúÅjCQÜŸrÅ=þòZþ¯~žßY|ÓÞG‚C$ˆŠÌgAÛÐfÜ…ˆ$WÆäZÚÿàNu£™9ëg¨˜>n•%$ƒÞ âe—MïE¯>Ñ]øîÐ ˆNÔÕÉîo÷IÓ-éÂjg´æÌiWvŒ Œ2–:b‹,VšŸÁha3ÞC0è’wÄö\åÈkÛIW´7dìù]#]ÿ×µF&ÜUŒ0HÌ®G³]²5¯«<ß"8Íà ‘¹ŽF­|4¤q®K¬®­nØt9©žŸS;Pæˆíu½×ç’ùv¶µ:jy9G¤±@ËV}‘ØÈ@Ãgzg8=éהͬþô<£÷zSàæ Xþº:Á’ )ì4° ϾhtÔ¥PáJΉHüõWýz+½x‘"EÂW³È˜ûIñÑÝl‡ÓÓ)¤MãÃ;#é“»ÃG‡ÝxTþÞ\þp³ÌÒâÊŠ¹¹áQ¥8@† ]EP˜²,|¦GïFö1ŠO+vÆÂ]>Ýë`F§;8C~ÚM¡P–7}1Q@özƒ²8œàÃ,b†¯ÈÜÄΨPú·ÊZK«³|ÿpéÙƒ1Ü üidëï=Wöüƒ·Í_TÍ´TÅEJËΦ¿ùåêÖû–_7é}Oä§W>»Ÿ¤ƒÖˆ”—°"á°é¯»Ä™$Â×ñ©`ý=u‚ˆCVyø '­ÜZ·~Ä̽´êTLE`qðš§ö½<4 ©ËEÎÎÂ…9ûí«éO.gç²Ä¹PåO‡µCK™·K¤%¶‰%ÀŠ5"Ö…ÔKZʼn|÷xVcr¸‡Ó,°AâÙ²ÓéÎIþëß ]&—fq/O7‘Úuª¶{<üøÓfÐ<§54 å&Œë#A< B0" -é'ƒ$G‘ïI™}áœßçë·{¹¢y\«îy¿9ë:ÅIŲ¶Ñaµß˜„ÉX?cãáK V4UÐO%{FílBK¢Ä8¸¯®ÈnÜÅ{Én$?º™}<+®Þ0R0ë:‘P†& šû5>à#´V›zuž7#Uø{ïˆÐñýÈ xň„dú WqÎh5ìôAWéÿÌÂÛ@‘ÆÎב_ËMñß}#.e½ÞÏÀÛȶ[¥é§ä;—•öÃ>„6sÿWºEמÞûËüëy×Ä/̤à™@Õ¶zk½[8­lè|U+xQ.ÔY\= }¤>ƽ&.#b˜•þ¢©ù4‚J=ƒ~P²ÛüÂì² µÌ?÷\XõýûwÚBƒŽƒ¾Ãùé'Ë·çÝÚvÕ­kCÇüÉ!´»¦Ž“•[—S¬iO Ž&ƒµÊóØ^¬*Ž4Œ›N[ÛÏ*t;Aö½Îo¤?¸^|r›\¹©sÔöÂT—‘ï Uû =†pR«u1;ï2.úwõ½ÿ®©2¬Å(7CúÃIžÃ`îÅDig†;l ó#W`¨Wð äEžÉþö_ÁU'š?Æ#M³µQ›y¢ýñUÒóp™ùIâ¿7Ÿ´3stÜ¯ç-S~d_×ùëòzKml¥Àú„*‘sí™RáçÕ…òãX=^·õ!LìSÌ ¶¢Š+.û®¯ Äyô𲛯ÞFnܦmUáUNN})Þ9ãùSis4.?4¿iãÄ••Ø4 m`ld§~°"’+:J•jÞØw?ÎÝ-Žî÷þÃOùOnVM¨þÛs‰ 6׏ýî…cüúǽ¤¯bY)=÷˜Ü=0ôîå j&W¾·”óIÚ QÁœà8~èÁÖ^æE÷ä3lyÁ‹m±•ªè¨xúY\#Ùâ߸Æz˜€Q" ôu ‡±I¥óY\ÄŽ£3§ ‡Šd}spÄÎf :¼ë>Š{™nYÚCÖb®0ú}’¦ììãìé“úàQ¿‘Øå?ñœž*±ÉÙêD}ÓqM#ÂÍÀ,|ÔRï=èE´yïÎèZ/Š<ÝŽÎ$8âwIC´Â°ñ­!ô•õ­g݉êä+ç6ûÊýVÄÃHÒÖóœ­Òta¡¶qÍ?êKdœÑ.Î@ß§pTÒ©pDH<¬ŒrZr <`‰o¬µïéåÝ #7QkAª¶¥0!á9¯>NQ»ðŸ<‰Ÿ=ƒî«x-¼wªtú\co MÖk[ÝR´×õ ÉXܿljPÖ¹é¼ÂÓ¹ûÕÕ^§ú òÂ%ÖX±À§5c  ˆ È~š”ñzšìŽ&^|~«ÒoЀŵúø ‹Jx}Ñ.A”·óO £Sö™—ÌÞZ4nÑó¯ îë\½ø¡}²¥¨@ŽP­,ÕZn4gô–O·ÉØc¿À*à:¨9±BqÃC\1ži) ÂààDÆM!ŒÚáz÷›É¡lt‡U WP­J¡âõ·«°WÜÝnUM(ô¨.[ñ¾‰Û¨Ssš`“çð»ŸþÚ!tù]m·€xj™ªÇžŠTÝÝ€ÓS寜m~8 ë;Ö6Ìô¾¢™¢ë½Çw _x€ÿó{Û³gu ãËBDv¢äµRékEÜr¼ì>O.OûwoЉ\Ènqø3kV ZuÄÒ˜dŒdŠHO°8k#š ý½©a½s̶VÃö|¢qf%¥ú(uܨŒRé´Q‰E®—Ã꽸²¥:êÌ‘¡û\Ùl?: ÿÉ7èŽ~ôïßî…ú¿}T½$¨®u‘1;žNgÄ?I›‰Bv0/åZùàZkezTì´ÕuF ë—ïòtX¯Ú^Ü@'¿Aìsu”É|` ¼²ÔÁmMpÐr°?â©®õV P®úµ>åû# §œ2v•)œha³ŠT×ö„+I¬Q¨µ´à1¢ Pëˆòœ &²ul&úñlã.™â~þÜÙ•¥_].–Ö[÷®á«Wós¢J"tks8Ž‚ù¤Ûm—MÑÞÐ&÷F±±‡ú‹oœã_8ÝwîHùà¤É›ùV‚+™p«0®MmW£»wjs¹¼·®ÞN>|O]½á=Üj›Ì|ñ4úL¶|³¶öSk¦7æ’™ÃÁ[ïu×6¨Fé6H–J| (2=…2tMk=k”3bOìIǸDz¡Ì¨mg)Á!µ™c'1=Ã][ó 1†iKgaõÂÙÀÓ* wv‚ƒøþ*ÌN†‰WÎÇO µ;·Œ#®€™ÐfârG9‹±VUcZMYÔ±8b›¹ëâàà^/5ƆÜù °˜gó~þo®Ù÷–ÛÝ OÏÔîÝk_\i\¹)¶%9)±ÍN:õÕ(xDH`áÒ̺é}ñ©ã¹Áùƒ¬#.RF4ÂN8tžY©p 0êt.ÀS¾>aH謠ÈIìm $£Ð]÷嬬 ïIpì™&2:³’VÑÅE©SùäÑÿê͵ëëîÌHö?~•ïÍÿý/{,×÷k¨d~e`¥åì°™x6ø0ÿËO“v™ ¢˜ÔSÙ]‹ÉþtH„]GX6¡_û íçk’l¨»°JO~Ã8u¾›©b`_^jCÛq4êzªkýUL<—jF éêÖç|Ëi G´ÛÔ–”U ¶ ZC*AÝÂÒÔ!ëk„Œc´æ¡Vb%ZÇ÷…ùG-~UŠ»¬T‹Ÿz&ÃÎÿÕ¥dc1½{Ã^½Œo.t„_Ë}½6§ËñÀB¾vÂBd esÞ¯•Š<Hæ>ØSÀ¿ÄS Ò¡Äøœº ï/ué7^ÆÍEKn#ŒmHk.mÜ¥ž@ºçd ²”óè¨ô¦µãÌ0Ü¡xÌŽ ¢…V|ïz Gq””{¾6Tï·Iétƒ¥œbœ+ÙÊ4É'ZÆçUôëÇìdý§óøÊÔE[k`R2î0+M&4ÐBü>6s´(<Ø9/ìã'F=û=A3å¬A@u¨I±jž]Ø4{v…Ý9Ø«´tt­¯ƒ£úwþ4m+Sî áÜ[&÷õæÃàƒÏÚëÊÙŽ@º c¾úDÿßÿ ÝÙßó)ôGÙØ@þâéQÊù•ùŽGÊ¡‘Öå+™¼sݼ_¾¾Ø^ÛRÒ¡LÛHù ¡¹[ztoíÞR§¼Ê'™mPÍÇãŸý"1Dv,ô(`Ë=° ƒ@(õ©±çxǦPAЪ0)ÕVÈ âƒÒŽâ³ò}w96°±ñ^³Tq¯æJýùv×öHýèKau¤+W"Åõ’>x°¼«^¤ÄÃ>j<Œ—~»s"­úIÜ\²EÕ9íþ$ú糦ç}àùý®tç'Ÿœúœ§sF£ÑˆD€ H‘„DJj¥Ñ…™‘fv’7Tm¹Æ®-W¹¼®Ýµ=ž•wVYL "¡‰Ô»OŸœó9O¾Ó•ýbþ‡Ï«o}•|öøÊÄÔv÷Ëy¼ÖÖ'í9}¡=Æ’n×û{>ß¡º•}ûTtüHs`¤[R²ƒ LŒ©ÿ÷wETò>šC¹îßÞm¾{£Ýmè‰Q¿ÒçÑf:Z+\Ÿínwàüñ êð(Z[®ÎuÚÆÐ¢ékÁ&9Œì ½ÕGãHý¡?GA›Šä:눰#+ÒùÝloÅ03>t•ÖTj‚%ˆÑŽÁ…‡N"zÚ5†ƒC½×^'íÕ¤†• ÝúÓŸ _avVÒÖé«úY7m*#IOw¬ÑÞåòëχçkûÑß|Q#¶õ_)¦íõD{ õ—oçÿÛÛéÞN$û£¯›þ¤½¶nšuê«FÐ-±Á!?Ï,µuÿ¼¹‘½þ³ÊèX»¤ 'ˆ‘Œ7Õù°o숾C…#O!Yt’%1ÐAxÕ:È!ÄŠ C(øÈ=|H£%Ñ=Ñ¿÷bé{—ôÓ#vb€<ÿ»4šë–^o‚2¦„{S `¸ñJEœ„k¬ZÛ³n3•'úß~¶;:….†¶ÚVbŽŽx¥À3n‚-30"*/žÐ¿ö¸ d¼Û§Ò©WoÅAÞ‰v²¤¹Ã{‰çEÊ-C·-X4x`à­LsS•`:$'MOUŽœ÷äfºßÅþ£°gÈÌŒ :¶ ¬¤¶äÓH Ô7êÑøG¯ï½äœPçÆð•ãôâh}›ÌuPÓ-ö²´¤ì”RóੲçXé2Ê7Œ ¯½Ä Ó—Zå–GÄÉ‘2Žc óW?ñ¢""‘ùè8jº…ÈÞb¥ó¬ª Rmùù~øo~-žùÅtÞUacOüâF»™£ñÞb¡WÚDý‹™x—ÓsÃÆ‹Ô¡1¼¾V›iu´ÂÄ!¢;¦áùbðD†#AÝwŒßAΈi¸Ú )cŽÛYåÀ¤7_—Eí4gÍGŽ4 +3&]äy[œõ²ÄŠÄ˜:6«Æ5)Zk‘•–»u}ïœWp â.»!äǘ»ºgÎ6û [²øƒáJm5•] I¨t–ÛÝÛ[òäÉha‘½q;yå‚~ú¬Ø­×~ø!ùO¯'÷ãE i’_¹Z:w4Yàž>‡o®Ú6Ö6† 7«fê„{ÊÞ^ÁõOó‘Œ/h>4¨ãDÂ!À‰¸¶4tº[ì ††¤ªõm ë!½l-·®UB³¢2yæ´«’œ ÿéÕÁ #;¦îD¤æº8P‘ãÇF¾\è¶S 4°&5Ö( $“-!Ÿµ:4’ WÕ²z_Ì­£pWæös£ßu%ʼØtm3Ÿÿ»WýÕ g¨–:½ýw7<×áÔYÞ ®}Þmí÷胑!‹üÓ˜ðœôþ.»={*pMÞµnät¾Q©œOÓRš¹ ïò £”ذõ >ÊŠõ+[[;Çqê.©}‹Âì>@ªM—ä–ÙWdñˆa÷]!¬Œ­Þ#hÛ! .¶½eØé¶¾Ø¿€‹e`ÚØ/A|X‡÷ÎA½Çš0Ašf0Tª¬¤"ƒZQK¤³•Žº½)N«-¬7z»ó•3ðÜE½W¯þäC÷ÿózw¾á)'”j“½úLñé£Ý‡ý'NÚkë4q”Ì»H£E'íIäaëJI¾Øs»å½q¶$ÔðKqŸŒ}éCïÈ)]êñûò°`7ëDÕ¥‡õš…\;Ì(áU•Öˆê‡Ö$›ì¥|uèÑ#íN]Ä!é”ÍÞ^Òã«ñ#µ¹-g?æ@<£SVkB„ Á6…zñåÁ¾‘úà“æƒÏÂõÝDC‹…œJf¥"¥2ж…™Ai¡‰?øµ‰—+k€mé±spfÈhí»µ±…é•ÖfÜwxò¸ÄT]ús3Šh:qdà׿Z^šj¯u…ëZ¦n*‚-ÞãDjyØpÞÊ~囼÷é¹½ý~*:¦ÃqËb°[mK“ ¹ÿúWF”›³¹hV”Í1Ô³‘Áìdy£!gë’ƒ1>“P÷0H‰AöÕFêxL_|Êõ¿è»˜8vÌgR§1Õy¡ðÍÇ×Ty­Îgs;¥hÍ’B½C-I \û¶Úß{ È^ÉF[^oÿ½¥½’Cº6Xß ßþ²YïôLcC1ÒæÚ¼>Ñã–ûñÿùùgK]_Fžå™v}½÷Z¥ú´ý\„÷]þ%°X‚­‚aâ zVwö×+³yÈß3½ Öªãë³¼L~ *ŸBLPÃB]ˆœFþ°÷ßë=­Ú_ñ&-ÆxTÿøÝÒ[w£Àe4Ó`cM Sûækì –ÍïüVt¾\˜e[s&±%ó‡qNÍí/ùæ¶=ã4hÒ;d Þþ"ßÝ ¹?;GܹÕnÚUŠ-§ksUÆô¨‘{BÂÅ]C¥÷Ì“y}I¼ùa¡`s cm\÷=‹¬Ì GˆþþWâ‘P)ï+ÈÛž qP´¼T†ê¹"÷ø®u71îm0äk'\~%@ëyØû¤sþ`ÞÚÐQ¼ÿAts³Ý7,ÝBU™ŒR³¹Îÿ )w€pR·†:ƒ{¦°¦rÇ¥Â%66ô¼×™–³¿ ‹óâùË`cïÞnR2úÒùhO©;ëñ'M½›>{ùàÝÅøó9}÷¾^X!ÚêœzÜq&¼ö¯ }¸nyÇ‹öŒ£©]ÀÆU©~¯ŽVqö¾tÓúIdïîÍê½3;¨‹¢›`{eI#+^Öµ^ Ÿx Õ€­WÐaÌ1êÊÅÍ[ÿ¢pÎtniþ׈tˆvÝ¡µ$—›H ;‡ƒ©Sl"ïLx¢áuÖQ(­C¯ïVggÓ/V™ËÐï¼:ò“OëÿËÛÉuÎÊæòñžx¿ÕUæ«ýåמk¿ù×v層à||˧AŽm(¸´,p‚dï¦ÆØÓµS>Rè unS…›¿{ÃY›GÇ'ÙŽêÓM(m=d#>ßefOº.PaÒ‰m‹¶‘ChúKWì£gšõ=åõFIæÔí mPCå½÷î1i“VܱT©ÖL{»[:5²{ü{ûݾ·n5bmÀe9W¾êÅ6•Ô¸º2+,~ë7à‘žúgË Iª´ù©#Çɽ/“õ7ƒx^î(>vÈJ¼sƒ×÷{Û>z¹óòÁlxÒŸZçiB|㦬%,Å™­bÛfÆH-îq“ºÏ?‡÷–“×ߥÐ ÆÚh?ð-(Í!ÄþÅ+¢·f³Œ÷²šŽƒä~èº-'`‚Ïg“FÛïK šyP V :â9W-Ërí)÷ɉds J%ùÁ§þ½ÅÄMj•‚RD¹¿ÉÞ©ô9ØÛ×ÈÜ%ÑŠê2h/CÜùý«UóÀÿìšÚ^Ï\N öoïò‚ç\™DuåÜ[k~ú…XSâÊÙÑ»óÝ[ èî¾»HnBþbëW)èdK~êú[Ö.,0MT†’…]#ßw+{ùî1fëj{|êÌ»EP…Œ!Æø†ê'S€¹çøJŒZÝByÔ ÏXgEp¶-÷ô7Vía±à»w…ò,pní—w3ØÁ*ðÍ© ðõá³G´‰Ú‰y3%}ãègŸÔ¿\„š_ûêÙü¿~ŠÔ}ó¾,©ùäôTѹ/Ž"½Ú$W^( ‘Üß«*Ó.Â*N<]<®(X!c±îqÓ©ÕÂĹ„j5;ÛÿÅBwYîl$£ãÄ z®=䫟gµ$/ R2Ñ-›8D 㕎ô¤1ý¾ùµW ´( Èvnþ@lÝÌH)ïôl·S¬VoÏçØH(b±Ò)L¤º¬ÜkÃ|üQ—:¦A­(»qÅ–REJ$TÄjo|ÕIÆë6<_ô?¼e¬ÍrŽŸP¥Bùî'ô`ƒPÐˆŽŸ-¬6Û7®X.˜ó«–îïv¶fÈ©G*«›™JŠÈMóÜFP‹ýŠrU÷Q§ÏWÛkfœF·¼¸ØŒ·XK+ÐNAºÌ岯×ÿÈsêF³3Ƀ7âÕ‡†ôC¡,u§Rë—×ïèTaÇH,sl&@~‹”J‰Ñowò]pǪ•æ^|ûM[Ünàúk]Ú÷ÿÆ;¥”89ˆ²×÷lø‘«4èšLù§øÕÓ¥¥·ÍI-tfÒžðÙ'ÛŸNáýÔÿÕóÙ?|V8„¬îúŸ¯Ê4ÂjykÛv8§82ÆÕ¨û" ¾ÌÛ½îð¡¤[Ê.ú©”ЕT ‹-Ï‚ü>ª43>CÕÀÅ4‡šÐÈ•»Fo™¼Ÿ).À’Òœ–÷@çÈÕÀÇj˜¬äëGÑ- v¥Ã7}øskºÊYf~Œv„ÒšP”+ìy7TÚr[ß¡g¸>$Àu.‰uLBƒ“n"šiÔ? ~¾ÿéô„ÞWŽ¢?ú.zùû·Ý¡ý‡¿–-ÏVñíì8FÛzþ æ’ìîVA³®¯z·l‹"|R " bÁ¡Ó™_)õžkUL/•Þü©SY•ÛkÉQ‚ËýÝkŸÄAÆ+’õÊâg˜›kBÁjµ5å ;û‚Ãxä…ùjC|ñºØ¸Áu`{{0K[Q…Ý^¶Í¶ÎÝ" c@##Çcªã”K·7Ó?Œ1]TÒÂOyŠ ]ªÒ,RZ•_ÿä³é†,œ®àw¦L¯i•½®wãjˆ>ݳ‰ÐÑÓh;áï]+¸‹Ã_yÌ»³—îÍ9'ÎD›[9OJœ¦J£’­¦þ~YÖ4 ºA»Ç±ë$s*›ÍlkI2â­¡º5 ‘¯ ž—‹Þûå'‚ˆ1s–ÖøÌ[ùÒ=å š0"y×­ Ág÷eš çÒ2@à;6ÑâWI¹˜i ñn'ß6R­6ëùÔ¬ÜÈ|†‘WîémêÐ|ð£ÊPº7gÂѲ¬é}VzOvÂÒä€ú¾v¬óÒÅpþÍüŒ²À½¤ä|åÙä³)´×¶¿r®ø»Ï7C¯4Ë7ÓϦ³ÒZߤmžak0¸œ¤OëÁoÉvÜ ïZZ—hÉKckuÆ2Š7œø.ÕûV®j} A!qgµ‰´®"³cä¶£ÌX W>2Â]N%æÚ=è„/ú„bžÒ{crâ@ërÅÕS’Ö3"ëPÆ7[äYŒ¬FÒÐâg¡ÈáX÷éýa‡Ýór%L¡pÎãf4Á?yÎ}íJöâ‰âúü?}?õ™ý7¯Œ ö§63˵ Õé9X9·wô8šû0Y’²UôäÛ÷¶°Œ6À¬V,x„ÈaÌ%Ó5[ðºho)ßXïÁÉ=[Ar{:Y24:ŠÐN¾ºjƱ¶}mB¹V&7ÂeýGÙÞüÁ^w¯^\jÆI¥ÿÐSíþM”†¯/wÞŸ—Ñ_:U>8¹p ZÞ"ËkÈ nTÄqªŒ¯¾eÉaÙàŒ‰…k %fÖjn°6ŒYÁO‰Ò\scQhS;o’îióÊ?ƒ§å`Ë˜Ä Í=CÁ'há+€3®gíþ$ŒÐfocóP@0×y† Ò¡° YÍF],/Ò‚ƒMFÌHÞìñÃ)lTæõ„ý£g_y }ë|q­)þõ_ Ëä?_›‡ÔË76†7ÓfápáУ­Éq3s+oê^$÷ŒE©Áƒ6ë·¦rМG'ÓâaòÁçxûƒîD’W„*ôóuïçÝ;b¨ËÊ,h9¹¶90½f] CB£¹ÆN)ß¹‚¹R©ÝþÈ럓£yñŽMûNGÈ%óïÍÓVWJmAKЀ;{D®·|fx 6c®ŒWÀXî[©‘6n@ÖìÌ$+Æ º›®®†Ôµ tIÛ]Çù)3 H[æõôwÿð·ê¶wv‹ Ív§âx,®ÑàôðÁ7ïí~¼f/U/tž8CÎ ÛåÍpv a$¶B[]°ßè<ëäØº´úÐH™±Z ”Yêj.€%Dj:h#ÔÏtÉÈ¡ó¹ð°·oÓÁáÈÝâ&Ç æà够W*$Å]Õ<‰ð)Þõ;/ýrµ‰2ùÐ2ig_€–FK EdÎS¶mµ2Ö7Ö'^ÍQg¸QÈkw-Ät"ÓK‘58.R"rƒ§ŸRýEÞíäö^ߦ@¯WŸkÅu<ÉácYtü@Ï1tã&üðã|.v AĵpR#Û‚´j›™'~ÃLca©Ìþî¬L\}Wz?ƒp8Õ§÷=G# P¤¥(+H\:­I ¤$.FRZS-U^=¶rÙSå}ØYwÛ6ôš“‡EžH¯~pCï%RÃ!ÜX]Ä Eü;¿L='œ°ƒ})‹T…äL^,C 'ÿè{eí-¿+Æ(0Ãó‘ˆ ˜åÅe·¯D&GQPÔ}'èñ³…r-CÒ~qn­·g»z1 ùöÑÈ›ÛMk'ö^¹Z¾;Ûhèáê õÓÁAråbö•«êÙGÐä!uí#¯®e×€À$¶®#/?á§©ô}¼»$ê{¤KøÀ3>–u„ 1¼õ°ÜN2k±W°*·ô†q£-`L‰ez»þJ†^—ë¸wøl¥oŒö©øá=^ê[ö¦#W³`Ý€Ñ ÅßÛ¸S:y)ŠÎÔÎÙ˜pôv ·r6 ÝÝʉÁí°¤!¢·o¢,ó<_eöÕEžçÐF€•Üp±ÕÖ‚[DÁ>†háLC ÷t•¢Ç2«,Ž.¢³ÇýfGx9þ®nk Õ¦PÒ¸©„‡£ Y¿ˆè!~êv.3 Òi((»â£–cŒÑXá±3šÔre#`A¢ÎKœÙ|ÈÀvh3#'¹]ÀÊ À©Óµòמ†dûô?¿á-Ç¥_¾ª_¸ÐmîÛq,ûŽwðÑ‘‘ƒèÆ]ögç«×I òѤM™1â8v…:ãÏ|'ê?Uƒ*íû3YJíu€ ëìÒn@5 ä;)ÉCÂq¦´hnhhuf©ãPõõ“JP=ÌtÒ„µm¹ƒ]2’O¦ª#ªEÿýf?–Rk€Q P„“4ýÞ·àÒÙxòh0<€)I±ñœ4Èm^)A wÿá÷"Ú+ïóT­²A¯ØÏî-f™êôdò[ðõðQðl¡¿¢äÝžrï­ÔÀù+¥Bàùý£‘7³Ÿõ¬íÙêÙF  –C%êÒþáø©Kèêãúé ñécî{&Äà¶Ñ ˜X­(8Š_x„µh8-§Ë’êÍ3®‹Þ|PhÆŠÖ÷DžavÚC¤†<¢ÐÀ`+XãðwÒáØ:¾Á":rº20J‡ûÕð1{wZ–sìºÂŒ1"Nä@;9Ü[ËUƒž|ŒÏV9ß9^0{iXªlôU£/ÖP}+¼|8g^‚JìÎ-Ó "àÑÐ8â«1Ô¢rCó ávÒZ6 Éa%, …Í“ÀÚÄæJsÍÀñÙe©C£ÐYxäLùÓ©lP;*y?ïb¯¬E§¬€ hد9KßêsÊåÐ,½T<~$ÝZºËá#&ÒQ¦•}«ÉA"~S¾ )8Ñú¢ ^Ôl¸ã9 åtz²Éßê÷¦ôd\û’´¥0 žÕæëW.Ðï…s³þL¿ø§/%Ôl³S¹¹•þÝõÖ÷ßu?Y´[ ¨0>YÉ—bÀ%[VP5aK»NÜ*(xYÐŒkãÎý4zw-yn^áƒRS °ÖVH¤8>íùÆ›e:ÕZ[FˆÒQÄŽêÞšw¡Ð«tE‡ò´Ïs µíÿàVÞ–0‹0u%2Ôš*ÂáaÇ¢öªÒ‹êÄáË/óñ>\ë)®¯$—.V‡…[Ñ\é½éй3ÒR¶|·—’r7/ž¼nF,vyJ°¥áÈ;×y;®Ÿ=mNø÷Vò¶•Õs0|¾‹6‡âú*æbéÒEsù9>Š=ºl+>çw¯f× .‘;ZIADÃ-H ¸n¹K¨è] ʇ‚ƒ'’<3åŠ3³¬¯M…™J¬©~Iª–Ö™+0„ ßÀ4MgŠx%Ã;\ïyú)ÁêMCL#÷wˆ äÏKûS”ƒ!¡2Ù¹>»¹é¶âüüìí¬!°¨g¸¤èsƒf})½¶Ü*éÿáûùìf¡˜©˜þ­l` CÿUÏþBw+ž/{¤>¢ ŽemÔu<$~EsN"TPôØ‘T¿b£–¯ÐJmЙ<ÜŽ ¥x¦chô)ÊD¤¡@Ž&˜Þ©R©%X}Ê-&ªUøZárwo­²¿æ×Y¿-H¡­ïbƒÿž,ÜvR ÔCä„F/€3¤9s ¥ŠÍ~~â—üEg¢[œa­®á¾íN¸°Õ~ùréã%ï¯îuŸÊþñ³ŠÄP)à]Ó{{)~çËÎ_|VúhZ§ æxÙÉ~±Ð¶È0kù6‚N0|‘¡sàb·Ýé›`“Ò[kñ,T¹‡û!9#qN5Ç´Ì)*¯¬Ýi¦3-qá!ptÐ)îw³â ²Aµ4Š.^”žÃÁF½ð£/ㆰ€€YŒ°#‘FFW1Ré'Á‰£´³‘é¥üØÄÐ#/æÃ=i_e}1¿t±Ü?’¸‡+±×‚Žëœ¾Ø Ü™ªxNQ™ÆÙ ^'Ø*s_I Ÿ~Ëx€*çÊ…äT5ÛbmË+g`è\”˶@¥µüê¥êåGè#Ï5 Š»®"ÆFÍÌíèá¢K70ÂÖZp 76ãꉡžB5á*?pXå#ÎäYm% vn½wßI•ò-¥Àk¾óœp‹–6™ÆZZ$†ÐÚišÍ–åjJw…>p®ÿ©'%«×-3Mî®NÉ£ÜY ä'˜P&œÌäÇz9ÂAk'¸¾iߢ»›ûŒ"ôWØ~ಣռ¾#>ZÍú½Â飅ÿáûñôµÆJc9ðßácý‘øb²ÕÖ­Àg²¬ÌQS`†5AÆ<,ÿ¡6™+°aéHž¾*½óuÒ!çà‰Ž +™†cƒ»HtzqQOªÉ·}°ÝÑú+¤˜¸sž{ÜAi¶ßˆ6g¤"âÍ@ÞÇ’çŠYÒ¡j—äÓ@ê˜Ùu&vh^@ÐÇéœϛ£C-1^äÓ p‘J {­¶Ý[xÿþ~o¥ò¯~­WI÷ýê/>)þOoµo.úyÇtQ¾î—òÿò;½Ç ßý"ìùŠ B$¨ˆ"-4Ì…gÜ$Å_Ü˃é¬'EK~?î&Òê‡VßplàÚÛÇ23ªìª6²+º€¬EHZæÊ$ïrõìù?Ý‚ìí£ÇX¤3]*“ïß2_¬ @Æ!Ôh€Ij¡ hxµRíí)}ôç­ÑìÌØž±üòÁúfåöÃf«N§8gUi¤ì F®’Cýò;7Ò¶’MÜvû\^ݰJb¤gÛôÚG+ Ï‹_|QF½Æ¬4|l }~ï}"ÖVLÙ±ců>ov§³ÕËÞŒ~þÀÖŽõÜœnlïÀ4±UÓ¤Q`ΰÃüö¥#8Ù·Œ–Æt0ÜUô¦5éÿêÃîü:3TRÚX þc?ªí¶Isƒ ¯`ûcf(¹c©HÁuû¿¢;ý2YGY­× Ø›6pÈ÷!oi†¬òmQ¢ôßüöÀ7ùoÝnånn³¸‘‡Ý7>ww‹2ÏjQñìÉž[sìî\kyiàË•®¦©ïD’ˆï@P¤Þïx‡Š;à+Ët KÌ¼Ëø=ªš ‘4lÛŒ/p\ŠmŒwBÔcTW¡¾£z WN 7»©­ó*-ìäÙ©X_¤æ˜2ÍLÇØ<ãzEW3O?•ï¶èîCžõ“Ík+…P`2¦${ hܤv•åMWºÂ6œ‰çðù‘fk$@ Ù`ª¦|ëiOÛîVvVÜ7?ïD¥ò¿ýv£_,áÿï§…ÿôÓÖÇs¤“YÁ;še®åÿáÛåãO”Þú4Á¨à˜\1–ƒ™ÄÆHòeÛ}â’×Ìñ‡S‰?— dvrÞóF~æèŠCÆÙÙÕKdâ˜yé(ÊíYêœ>Pˆ¸N‹²¯O”@¤â´X¥?¸6GŠ,â€XjlÑm”Ô*Õžjñ£¿h ǰ3mkÃüÑ'¼­±ÛÓ{}çÁ½âýÅvy´Çíï½Ê‡ÇEHõ­i’reÌÈÒH7 ‘WÔ8›¥·?ÍTâPòâ âÀ@€U÷\d ½ÿÅóêŠæ1;~¼ôâÓ²»œ.þ€WÛpw†ôœ¨|1ö[%À c%B3c”QKâ»a÷âA„¹æ¬ñÞÃ&Eº'îµÅà{?^Ø2†"-4€kHtÜv&™Ì•l[µnÓè2uݨTO‘ç|Ue½"Y…´6à:ø§?Êû÷p³·µØF(b´Mþ'¿?ôñÎ;÷Ó°Í“f†>šE?ûœßoô«<­ÁÅó•3ÎÝÙÎÊêЕº Ò£‘¤ù/ƒWñÒÚ/³ƒÅ]y s¨W¨ b~êò),[ÖmS°MÏ ƒ­íb¶Kùæ%­bŽzKqm˜Í¶îš+ì4»c™~¡Hɯ)|–ô\Ž‚jÒZsáÐ+Ãcn)¬i”Єn1ô)Q “«gpÁ«€cÀØèõ6¶}dÂRb ×^æWXA°øgw½¿ø07—A÷3"pD”c€-†„ ><ãÕȇœ[®^»¿û³·^ä7y²Ÿäy‚ÎÄË+ÉÔB6·ˆ .5:D§¼ãoËM´Ÿ»7WÉ;Ÿ«·>8¥E0Q%¤aðó/ÓÏ>Ìï/‹û÷Ûí–ZÏEnT‰9wç)ÏzÂZgÚ-x‰Â‘ê—ŸOí$J´-€¥€´kl? H)3·éG¡{dXÔ0‘©•Vº˜"v=ýû;H¦@)>cÒ¢„w‰½å@ ÓeB–…Ý·]p•Ö4.ˆ2ØZr¶· Kë=pF,Lq]C€Š€„°Ùo\:4y Ñ¢âåÇ*7ïæ ‘„ñž0!f·Ý¹9ßû£ÏëM{þþx-_lãH0/âÛ¶D÷ÿ†sq´…†½»Ö-t‚É»R¥Ä+…Vìò+Ü-Q¥TÁ”êF˜ ˜œxž–\DÈÒÀÊÝöIÎ_ôkç¤ØÌG设Ȃ¡´µFìè×G†¼$’$)ãý»yÓ/R§`Ý.Éu‘…)l*k°#ZÆ@ëœÛGÀ×mV“o^ÄyYWåÞXiÿž9+œÖ!ó,—ôëOE×n7ÿç7â_¬TÝ] öxo±ÛJŒ‡úo»9)6:ÒÑýõ³ ö´.i62mÁj;šr:_@oÇäØÎè$õúcÏ69N4J7ºNTSÃQƒ(ÒÓP0–ÐkýÕ–òd÷ܸ%„H¡°¦Q`¹Ã~Óûþ»LèÁ¨‡"°Nf-P ÚP‹"—d¼Ý?ØÄ«ý‘I8‚ÂÑÚÇZ?}kÏ/¸ žÖ³$ÑÔt²²šÎ,ȇ+ Pµ‡¶%R¾wC¯o9›Y8·•½õ…ú»2CååJ}öΧéÇåw²©vK­ç<7*DøÞB3YÕëïL‹¢«À-Û±ÆÍ©t!yƒ±Ä ë3î„ÊZ.ôÌ– CçÈìA%+ý\'.Ââ7>Ïzׂf†jk aÄ}Ú¦U¯ý’A‹ À êˆ6B_ã›Ö#ÖD™Ý\t¶÷Šsk ™rG^ðÌ5©ˆ qaø¯œ;1™ånüÕÇznÜm†RU£˜êíVëó™èÓɽ¥øìI÷ú.›ß넎Î4ÿº²¥Ð¯~‡žjû”…}°!¢$€¾!%G0¤.ÛBSðÔ:ÂÃZÊÈ:mez}Ë\sü1¯Ê”×ú—ï´'3~5(="ƒšÊ‰»äÙvÜÑߺQçV{q-ÙlK˜•ÂÂ=‹¤k˜ÐûŠqb0u‡•dJf„•9oÈËN>ôÈÔ.ýôžÚÿ<ƒÄŒ±9”¨›B=9u/_îà~úıøWÏ×¾ûl²²Õ3ŸórÀþõ÷ÂlÆ\ÿQÒZ'õ¹¼×‘à[—[£±9 ~¯MÚ;¶ÐÌû ùØ ^Ç%®ª#ˆÀx›‰e¡»ÒÍ êGÞ°ÖKT´Œc· çÚ™]•7×Í€Wô]¾«ÙBG¿>Eþú=SÒ^ˆ£ÖŽH Ž)5ÆPd3 ƒJ×}å’©0gv;ïbhÝ6~þaE€ÜÏóÄ”0³JÊbÄr¬wÚÐlà©™l'¡1¥À¬dd//9Óºµhö“b#KGÍ”Ùðða¼µk; äÆx!ޭеÃmAáD»±^î?àñÚVvøŒ‹:\w*&ßE EëQÀ¬¦Öë\Ÿ‡&P Fú’"³ºVø]3×ðXÒ±Ür°Œ1<á° y¶ÁüÏ1ÚåtY‹m×ZãºÖ*‘!C˜{ÎaòœÐæÙ¶·Ê2ï,;$eR«°`~ëÜП¯O½+½žyßx¨[Ž=^+üÛotŽö•ËÝŽ¥·ñôÃ6ŽÀæª,…èy§r í¦Xå»Y=…a\B=`i¸ºØ-(:lBI™ó^KbʺFFqÞF»Ú(8o  U:„šMûù/òîç–y%é…¸5S KÆ®"² õ¤…‹¡Ë Ù½t~5ÞX½-ñ´–†ÜAŠ`=nlSø)Á@И¦Dî¢Ò€·KÓƒ•ÒÝuzwVn|c+'´ôœsV +±ï‡|z*[ny}ôÊÑî·ÏVýJº²[™Êº5†þÍïw¦ùóíyþxñîj·«|ß ‰@;Æì¸!k;ºÐQ# }NÜ{å̤¾@š'¨!d‹ò%©båjŒz©;$åV-‹ Fb!×vuW~¸û\¯àŠŽÔ+ûèïï{qPKúAN‚†ÚЖ Úf€`½ßÅ_ò+žšÞµGÇVeãÝ\›Ü#ÚâKXŵ<íлŸòÍÛàÇx˜¥«ö çd9€Å íÓ¡OóƢͷs/ï ,O7Õº­q2HM Wˆ#^ߘˆg‘Œ„•…XqCà VÓIw ]rV¦ÐûïËl¶8ÐðÆ´VâûkÅ|;+–5W9Œ÷¸ÿáWJß<×¾r„õô˼¥ÞxÈz ñÿø­¾AÔýü'úŠ¡i§ˆ³hØ™Zf@f®ýWPí™jkµµ.­ß1˜aábÔ€A:Ò€JOžÑrÀ²H.ç˜C1’Ú"á—›ûðÁyãKúþÃäí;|~¥àCìôYâV²vǘ Ƙ3¿"'Q­@.>~)œÚIß|#§·”ÖÄå ¸µ`½\„u™kª²T óÂá‚Ú-FRí;85]Ï-á9Ï™[èL™ tÚ¸\YϺ—€(5íá° 7"CœX(Ø|eÆT'ÕK¿­j}Ù©êÂ&ó|ß vC-UãÖžWºDq5 V„1³Z¼ö ÿø!üèã轩l¿Í»¨ìBŠÖ@C-³cX\ÐÅ}ßt Ì,! 0Žc\£`iéã¤3©*;HõR”j³íš¹Í0X‹´߸TôÑ®½=‚a~K?vÞ\=Ù÷é|üpQÉ¿ú¾4 Ïɾz²çîJÖn˜*Â-[Ï¥äà‘ÌÇm²µNn/æ o<ÝÙ0½]Up+™æ“ZŸò¢ÛСÊJÇçƒ,вü ÆQ+´Ó^ÂïóÅöð9ÿB4oäfɜʚ›FÏ0½–šUwðË´}[%‹ÂAÙ:§L²>¦{-aœŸbáÁLÜu\Oi튗Q€u\Pîa0^5tÏ̪/ÞéÂ`'Ëó¤Cqs;Ê⬌4Î ?ØKþû¯|ûòþ³£¨6„~ò¡üÉ=Ò_Ìÿ¯¿ÜW‘ûSo‘K’hQuF:ÕÑÚÝå< BŒÐ0æÐò"Æ•„ ”c·3Í)hÎ@RœQ¢ hãÀˆÉ£VNÒ²M7€ZL)b´°Žñ³ ýý—î;3âÍ;jn5 q+òù$ò(QÒP½e5X „”¹M°_)˜‹—Õ¡¯ø÷›ï½ÉWìr0Tçqp¬%™Œš£0ä©Šê˜“×‹ÚæÜE±ê„˜æÐ ÊAAoù$s:ÈpÇÏ­,t”ÛR9#e ŠáQæå­õ… |¨ûÜwñð~cÚ½·DC‚60 Ì pÔ°‚“"÷®Eá*Í È¥êµ©Î÷ø÷þþFwg7Oa€ØÔAH€²€ÀèGŠöxÆvp>‹ÈT“ÌA‘Õ€•BH!ruêhŸAŸnpÃGïfŠyD*0Œ<ù¨;àgòsï5S êÊ#ô™“ÕO;Ó›Ú¤âÏõžh~ó {ú`ø`Å]*Ó±=Åú‹¼‰<=!Ó·W£{+y;pœí¬ór"{p¹cóI­/±èKÖñ¤ÕŽº¬É¸s{{§ 禰»­–îË/“‘™n>%ºw¤]D=÷l{ŸYBbšvp{ÀµÓuù¶H÷ÀÛÔÇYŸ„C†pôÉ×Y¤:0À Œ"ôrhÏf:ÔvÙQ{tBLí6§ôx1F@Üpˆ~IÉ †‡Øï¢À5iœ‘¨JOeÀ ÿñšýÉmy ?ûo_«–½Ý–Kë­Úîn“cgàñ||´póN«£Rã@nò8W9&«=Ô…=Üd$TµÕŽñв\¡/ þ8Àën>Óë$÷MAbO³lBðHëp©©¸e.ÙÕô¹­™ëèȇ9Æ‹¨Ìµ±ÀDçÄíyö¨}ã“üÍ·ÂÈ}Çhír*±ç`Á LZ“×-p#°|õ«î7ÏÈ×os ×)`/Ï(æ8!‘]ßÇûHþ÷¯¿¢, #D@­1y*W)£.³kºKAzmàӽſÿ ›V×цÇHÚ6n©,ðÓŽ  ¤qÆt>ÆÔ‰v!§µÇ ’Ã%¬Æ™]Ñf™’‘!= .R甇Û׿KÊïHvTZ´n4DnQM5`d!7-M xƒÜÔléyÈR\ÉìYBFA÷bUám(ȵ2–¿ì‡XÌÕr&’Ù½öN¢IƒRÛ®hÖ§u‰Á, »˜P™f‰)ôÙɃœêÒÿï:|ÿ31TÍÿ»×Ê• žÝ­Vyy»cu~è)s|¢4u_훎ë.]…–ǽ.Æ›–*µô¶Tîùr-¥)x¤Hå dâ’CŸ¦°K^SµA’Nj³€0€ %šjÒT›QW¼¦AyÄzÚ¢>xÙ)h’i¥#ýî á€cï¨=Èð¡ZÏ)ØÎ'z§wâÏ—Œ4ùñ‘²µÝOK×îµ02‰í‰ø áÇ%IÁÛB~Ô–Âî²è,óu2¼¯ºÇyvÙÒCXoþ€ºíæ– q‘øgANjÓâýø–væ”ÚWª ™r¼Ië)š¹Î֮Š20ºà0®µÊ±Ÿ»„ÄtóButDªŠ£ê6 t6à_ÉÕ‚°]‡š£¸q¢\˜Ú<½çð êÚì[½CíQ®ó®“2½¹Ÿ>xm!ÿëáTýñwu!†EêÔ†:t¼\¾h£Ñ˜rQ_ówÛˆ[íûˆpyÈÁ)Ø\ñ>É×@¬€&ÆR¡ã¹‚÷úð•ãæÀA}j2\X’‰À·õ¬DÝŠud]`ÒZ \¢¬’õ\®49êD{,—®fy¯@yXâiÂV­³±¥·)^‘ u„È«¡s^Ä´#v°²e›%R1ÀÈsû5?cM ™’Q6&»‚§ŽC,Ë}aÁk,hvËò.O=ÕDôa.›”(!k¶|v8´¥Y×Î ïÙ¸Ëð<ïb$Ʊ~6§9LZÖ+ÃZ‰liÛU ŒÁ÷j5©Uƒ2Y ¹ý¶‹èãHß2:'Ä5ºßšŒkL=Kj’$í¹X3ÃY§ÉºÂa‰3­ø8ÖÏ»vP£Ðo“kL.K°²/ÅØ6u@ ¬0H[8–Œ#e’«‡óc°ÝȤ@^¨…b¡K°Ü˜¦5˜Ô‘é8-˯zi”š®Ïò“þáGùágFâëùP+ÿ‚Ó°¹‡Õº‚>ëßU»-p•ûl·N펲$5ñ®óéýÇúø|¯<Å*7M™­çÙÝy¶ÕBŸßw¯]/ýíGr½•+pLà*‘æ–•Œ>fp¬ÈŒÂ`À¡¾¶.R¬¬–Vbd´ A²Vw˜ñuѼe`S#‹À` ç$©á\ikŠÎtÍKÇ`ª1tëÞUAê”:Ñ@; „Ö" ΰqY~ìtïHSIœgØÇQ•p‚{-åF4Ǫ}q»=>D¿ñ•ÊìÍÝ…9Û¨üÙ²%LmKÈÀå¡uŒöú<‹õ‡íÅså÷ÞI·Wí õ®×ÕVCŽWP7mà;.Ô¸ïcq Ξ+zEoîAÖk¼®/ã\â#2•'4l»Ãë2¯{É–$k =M‰:<.cS4ª+Å´ÑÀÊ)z„Ê£ Tmß±ÑMÃg„(ƒבqsêZ×Áƒ²XÃcŸÑäSŒr%À!X¹küíváþØÒ¶Ìu¶¶“B!Íeb9ÚŸ(67º?\Îv6Ùl;j­4‡Œy–ÁŽ.üœ¢k ©ƒÂÛL|.ÔC°ÔzǬèàô? ƒF»TڳюyÑÓ—e¿ÅÉ5%?³-¶U-6Ú0æÓ\pëZùK—à@Û28u)³«‡½ cºž(ÁÝ0Ð\1Ø hQX´¸nò>bÎhïWhÁͲF(ø‰èè~ô™þäf»·Ín(ô’wY70hÃzêS õ ÷¸åaÓÙ¦f[f(I!iº?›n\èô[µÑRfjðÎj’ÝžsÖøæ½Î§Ÿ‡ó^²Ñìh /q”K 5¡IÝ’‡Bàú1k™k±ÑH`¬‘)j1•gµb¶¨ú<ŸgÆÌYBQX Ç…©²Ìæ2¸'Ù¬ S :*í¦¼åäuíuQ©<Ó4h°ÆàAÔ“ìèÉòh?±IÞM¡HƒAáÉʆ³ædÑ$m=8ä¾òbeáæÎü¼8\úlY'¡¶%TÁUHcmJ`(éEžûù{û[«Ù#—{Ú[‡í.¾Møu©€ÆœÄÂÅÑ™ïöR¿Þ(Di7›H×\{X3œý\ª Þ¢Ö’­¥± |2(»þ˧H(—Z)õ41¾(ÓÿîÕž.uv­7³h¬ÔšàŠHcgŒÚ.ˆpÚö;åeÞ’—œ+Ï‘#gÕé±êü½úÎõ¤¢Ð»6 Î M˜ PqÅRnh‚ñÜÓÖèÊAóÒÕæÑÓl|dáF¶Yͽ}¥M3šägëïýJôàïšýón+‹yÉ®­¥fUíùZP;ÂÕ(;|,€…®¹o«›ha¯óêï”ZûIsÝõ±–V†Võ©Â‘cñ«/ô?þdüÔɼ»æÜ›Ë\/Oó~IbÈs‘ç¸B“,Ý;TN?IŸ:%/Œ³Š šYkË¢fÔc é!tAó êû Œ¥ÊªçŒñ´5Á‡’1CŸ(V§)EYÑ—ÍÚ»¬¡ŒyîÚëAø=­Ö‰F²ÀD¢¼w+o7Û­f6¿!o¬;oßÑßéýh:ùxÎn´ÒÑ¡ÁÕ=´±Ý.•Ç”h{Oª£˜}ߊ%¥{{İ; ð¹EVxÐȵpº(õ‘I»fPºám3öžL?§nêH¨–¬ì(¦aV ,{î‰à_¼Ú99P»6’e«Zàü·¯ ¾ðh¼k Ós hD\›»ä’‚crœmY/“²JýuÑNÎù¿(&ω“ƒÕ…­ýÏpYñ·»¥€#Ú¡¦€Ê«çg¥@Î)î†Ñ‚V"Ï«¬ïï\½Ü7µÕý›÷³ŸÝÄ?ý¼ïÇ_Æ·‚™å¸Õ[I’FÎùÉ‘R Ú21©Ò^©ÊÕEää>Y³ü¸5çÁÒ*›pV4:wç /´¦m ˜Vx°‹Ò@ÂçBÔ5–=:ëÃá¢C?¡¥%,|/yêhty´õÜi]ˆhð˜ç ÓBä)¥,%Œ+{KÁ~.áÉ òêóñãpx¬—긱e¦Å¸ÆÄäîãâ·¹´úw­žE‚N+KxÙ®­åB‰ŠöB£0D9—(›˜dÞV[ß¥Õ ÔYK^ù­`£í¬² ³ŽÈh¢ØÉÃäk/zü©í§Oñ|Ýy80&™s ;Õ>³U-oŽ8ÝsGÈs§í©AÓ‹ »­ö…5ã{!¤]Õz ù>ƒÜ`lÐ%b†•Ý5”j€_Bh¼RP©è"-Œ YÁÕíaí]V¶FeîÁIBz€þÂè5FˆñÁëì1Cãýkq=ÍÛÛ-3µšÜÙÆïÞ3¿¸QûàAúÙÙlÛÁÞÝ`q·MË(N]Pçu½´óPK@.B1ì.âxHŠÕ9­÷²¼@²«çûKû‡ÉM[k@þTŠÛ4H©2(Ž ^JU¦  2ÑV_}Ìü«Wòsc½Ÿnäû-MNŒ9;âÒ°µ¾|ë^ÞÝÃÃcÕz£sò;iâÖi¡ÜRgø¼×2ƒÔŽqIvyãF oÅý®³¡eŒuÎÀ`ˆEN#4Ó'r8´OR]¤Ë–r‘ÎäÜ™Ý_Z”d¢lèÞá¡¡L4ìpãõÛðÕ'àO_³/\¿¯‹!Ís´Yôª|@Š^ WÎ`+(w=[b‡Y0ªhä¸A侫³y¸öÀºm Žä9ö1S©.})EÂü—Îuÿè+Ñ«çÇ«ûÏŸ*žî¹p eZÝ‚\§ÚJŠØæ)éR'$ª·ì´'’;ïEíO‚‰Iç…_2ýŽSrÌæNtå2û‡¿™û­òÝɈ@©Â¤O—ÆÃåe¡¥h+[VÊEv_+ÇänÎD¨.Ô¦ðÙSŸÕ?©·âòÂ~f¹z¿ð-æt*i·›Ž¾øÌÌïF¼ˆš¤ ÂZd²eë ž=¥ÿù¯VŸ;X;3jª4¿zrø‰ãîN«;·kš8ìp½Ø–ò<ÃS`F/iÝ!Ј(ØŽ5–ÌÊdÏHÌÍÃÐN:ê9-ŽX(+—ºöM70ÂôD:ë–ëéà}“£$Ø]÷:àz‹f¸VKä^.zw÷Òõu¸;ßuµÕZ¶2¬MvÁÓ¹¯„س|´o$ÓjÛ¦¹€¡Šô˜óÂoÊ<¥AåXÊKº˜VÞ5k {5÷4xž£ŒÂ²0XH®<ÁY»;j°×m°ŸŸ=‹KéO¾Ì.cýew}“?2BP¿q+MöüáÑJ£Õ˜<§Ž™¼Éî"]L¶´z@Döt0y„ˆÑÙ÷\²ªú€4ŒJÁ& ێȵ¤ ô)Ï+q›øxUbŽ5y7öE» ©(ºwx¤/—ÍØºœ¤=.þÖÓêw¿Öö™óÁ—‘ub) ûew\§½\TŒ½ p 'Üc0"Ä(ªxdä°Â©5Gå7+ÖÉÕ ÁŸÍÁR« )U±Œ>S"±ÎñÑî¿{µôòñžcÃÍ#ƒøÊñó'U7Ñë»–ë\[KpŪ4lj†(*4;y2¼õ.J?-8¾ôKrÀ5®ìùO]öþÙ·“0Ö?Ô)J¦}ª2®,K%yK𢒨š¶Ìh¿Î¼®â˶†Í¬¯.QÏ=iöº¥éUçÂÉðÉãúÛ_wÜLÅŸân O¸·¾àË»ÅÌÇû`’Y-s¤™VüécöO_ë»:Y:3ÂO —&*Ïœ‹êÎ|¶8ÁN´ÁdÓºžæ¸%Äa¬DZ Ý´¼k53tNeŽfÆ^p‘ï«Ã˜_Uòˆ5UmÆ¥®zÓtŽ<Ȭ _»àü“¯ G¹Ë‹AÇqѽ%;ÒÓÓÎ÷9ïÛ­w76ôíù.Êc‰A L=†+’R™¶;O3_+ÇÈ›eÔR£ ³r&²¿Ø;ÖÌ\ãðÊîM³‘yoCgÀë"…•Õ¤¯Ð}ü²ù/žŽDšYªÎOx;›ö'·³þJ@®ŽÒ{ÛúΊxã>ž[FÏœª'¯wìŸüæÐ·Ï&j'ürE…j:Âîè8h ­n»™æ¶Øy?;j«’¼¤q¹]DCi3Ð ¨‹I¿1ƒ5gC«ªÖeÃïJË ]ÞRôµÇjßzQ}í4ýæ…쵯"c½³&|ÜGÿø÷åd8ÐYÜŽúãëwT—8H5hÔ  ëæu¥’ÊŽëb?³u´6¡Á¥ËÞÄ9Ù{…Õ(]³E®6­9ØW‚ƒ#C´ì´8“'úáŸ-(¶ölÜB¦Û8ë°Ÿ<ݳ¶¯í↎ÈHÉŠ®‰]GýAà”×ÞÙ¿`Z³óIßpöÈ3\Ûâò|’çÉê °¨4t´w&näe8ûU'ùÍ[4b·ÇùúÞ‘Éþµ¸èpÉ3yþl6yÞ™ßVÍ:õ¢ŸÖßý 9³–^xîYýÄ3éê\¶òFçTÞ^Û5>ØË[;ª-sq rVp)aç'Èï|§¯7Ü{­Lò†v„»_$ 'ÆÖëxy[tHÚ¤# $sœ5ªоǃþ“ÚÕÍraqKMt˜DO!8)KçÄ@Fi‰:Vw¬¡„ aóJÀš¯>Çù¼è/»oÏšÝ4#š|í ÷¾•¾xˆ?.|äí>Yë2ßJ”ú&5žÆ·EŠ+–n[ .-Ϲ°ì(aó>‚ËñV—ÈAþì/üýÚ=³Óµ´ž+Dª©Áož5ÿèS(|ø÷õÁá^öéøhŽ~1'Û¹ûÜ(ŽÄkøÖRòæ´™]‚«gÊÒkí·ä¿ùµÑ_?-i|¾Ò GjL "›*+'Å­Íò¹ƒlw—o¾§Ž!çSã„Vµ¨×*”Y¥ú„ €­•ÍŽTUƒ«ÔÌ)–Xøy3‡o]®¼ö‚þúiïÛã×^±€½;3 yÀ+þ³ß8[©v¦²¾‰ôæCÑéF…g:ïÉò Às‚b´AãNyÃõ÷¨’Èz–DçÃᓼç„ãGɆîávÃaÛ¥´¦œïÙLøè`þ÷¯UûÐ~JeC[ Jö¼Š8tt¤ÑË{’8!V Yc¼Àv“¢¤'Ýhç=q"mÌ/uýñì¹§µ¯£©²'÷Ö·ÀóMªùN–•왯ânÌoÞ¢)¸5÷kW‚ÉÃî¶(ânóäüé|òlyv;níéç ÛùÐO¿h.¬pÚ ^|R=ótº»&–¬ÎŠlµ™«¾þÙ]¯]ßk™9„i&mŒ¶ÇGí÷^ëëó7e·£”ÞÈ8*u=ݺpt|z£½ÓÁ{*î « ¡V ¤ä¬æqÀÊO–Ž?Uð‡óz1\ÙµÓL§`‡$»(ù9U… `sL*Ô´¾mõC‚=âZ#–~ýY×m_Oïé§›[3þ~ :ï\¡ò]ùÕ#úé“äÂ5ZëûrƒB&m¤³W!t-ºS6 ­1±†° Ááú :†é–¶Ç¬Ç÷49”÷¥ŸþUik;¼©wê{@”Â0¢ ß;kþàU;4XüàNÒÓËö]€>}|p«Y—ìé1K^:J¯¯; R>P0ñk;7VÛ{uüLqUòÉ<Ìó‰#q1£°¤[ý]ÜÞ¤3.nåïÖôµD¬2hijDô¹´mQjq›’¥4¨ïG'˜H•]±Ø‚ÒˆåO=*‹ JµÒŸýÐÿë_t è¯<6ð/~•­ÞïNý$_›7Þ€ßÖtµ­ ¤¢0áGF‘yiâ@‰P®R²ëôxÓCÊÜÿÊÉ̲¥¢3A.Œ…)‡­ÉÁàèBÿð¥èü¨h¶$Ž´NûåÊz;«c,áúhÓ%¾+e:á»TeGzpý¡3貆%cÞ)ýíë¹PÐÉÔr}øúýdkwûÈÑêé A苞Èùìº%¦O­ƒV%íÆR´S¥~ëÙjÑg½C¸£ôõOùÛ_6WvÇãnKC~kÊ7¨2RÓûHÅ:[&,I>[¦x ×uú}2oKãûHÿúÓøH_{gßô‚¸%sUr )âPv„Qrz.U4J¥y\¨ ˜zèœ{VÇg˺©#ú•1fŠU6#™:ìuÝ´ Î6'%`Üs¯)‘(¥ Ú=z0¯yþìÛhév Ôï~»ÀIïƒùæ­YïøO\ E7aE9¿¬§6C”gÔÒ‹6;á¢w@ÿŒªYuA¸ëE%b›<÷€æ$x`ã!:¡<ÌÉ+ìÞÅËÛ·¡³(•&D«ÀDav°—$ðõZÉýúyïÖ´¬'c)‘œ¯rŠNvm6L0NtÕÉwŸïm´vöá•Oek³üA]!c#ð˜SÈ5¶Ž»¨ãjB¶×ê3)-nD?/©k<ñQ]þ—Ìû]§k 3ZÐzZXæqžKµ 9Rcÿä ú²­@V®UþÓ÷¿ºÖUÚ>y¾ç_}·»yúÇÍŪ´#ñf=`fŸJ­‰=ÈB$éšÆ"°jPéQ#Œå.+!zž8¤3zž½4©‚~ìDjúŽ ¸4È>Äà ­­k@1Ïú™ùåGä#£FXÙ¶‚Á¨Möýr¸Þ’µ ˜þ|Ú(U"¦M¢HåñÐ ±—LöÚÆt©— :²“ç¼÷ï üÙ"1õ´ [;×§—Ö¶ò#Ǫg.ú¡/z#vý3ƒMŸ :‘‚$YìVq Òï¼T Xs ¯ªiøó[é;Ÿìo.&¶Äúæ|Qêâ`”ï>4E­)ŽÃë{¦…Tª+‹]­•BØ/9ò¼P=:ÔÝ«Ëb©·êõ[Öu4”˜ö˜z0#‰CµÃ¢Ú¢à¸–cFl†ì쳸§Ø8X3ÆTô´-rZ† rؤ$õó{;-["÷C-b©8âFÅp̾>ë°²þW¼ŒºóíÛ3Ys=v†öMPAfìm­³Ñ ,Âjn÷HÙæ{ðúmæºê¥sî½…öž,¥¬ñž?ÆÈóúOs׿Jµ^>^>_ü«b©£ŸÏÄ7Vìõ%2|–˜hfAÅFfÖUƘ®“]nÅYô$¦‚!WFú¸Då) ÿX›Vl[éY‚mÈØàïœ`²à&JéÀ ùý•ÊÄÎóWþGÍîhEÿËÕ׎tc,Öß-žh&‘"ÊÃãøæ”éÇý±éjŒÏ :Ùì·“/žzZ¿~:™=PZÛÏjí\òŽQp¤úrh_}"D‹rlCL²kÝÑÉüJµyv¦vͦ¹7UxtXaªÿ¯SÅö56âe„ÙåV)ßÓ„€ÑJQòm©ƒò¦ÕªÒBë=ïÚ|/]«“¾ÖJé€GVt1—Æ«P­nΨ/éO®wBqC|÷‘,ÏÔìnËÌhqå¬ðû÷(Õ‰±É³È«ôýÍM)K?™n¼·ˆnm°rÅ-!¹/!CI¨S¹Ax“vüv¹ºO’üÏS7DÌHaö ?aáÙbóM«,ÄA½‹²s‚™a SçF•„˜Þ¦/Ÿ(+ÿû¿p®í4GËæO^D/Ot:ž¿ñ çØ>T°®ƒï³ŸÎ게Ý4#è¤kÓÕA|à¹à‘ËùäXžEž3•>c´ëŠ-É[Õ¬2fvZx ÌïÝsÊ»J¡"À¬ƒäˆ ²Â¯~ƒfY®PµQÇ¿ø>»[ߎtÛíÑrù‹¥¬Þ "%¸ " *ê±üæÓµlhw]™Þ+nn¨Ÿ|°ÓÂY ±NlëµYÞ[ÈnÜÓÓ›2×¥Åí¦»"1“ûì˜{Ý4ƒ¶­Ð+ÿìÃÎ[eω¸­BrÝm@ÐF¹µñƒ…nÛu†õÏdû…G¼‘Ñî?¶J H±k£]Æ”Ä}žú½çŠ¦Õ Ë#ÓÓÝŸýL-Þa=!í)d²é ˜Ûó°•;e2ßjk,G§­ °êã §ÓNì:Lº’4óªN(Ã@¹Wä·ÎóC'Žõ®í¦ÕN&-ý9ÈÜB”;мòR®óÁyÆ-¬´Ê§÷ŸìKOãû;öNÇÞŸ.]L-•ÿóÏ´Ì” –ju ÔPÍt€u­²Jœ7úp¥Eó6Ò]ªAuÂíD>ï9Îvw»A?f`”Hƒ´  ƒ5Ñ£«þç‹òãuÿû71Jæö÷_hwÛ‹ëÝŠ˜+$ä[ÏŸÌg‰õ¬ýoè¦e\79â^Aï5ÙsG§öþüNëéóúOŸ‹6bÚØ•†TS›"}Õˆ±;^º%¨FÒK;D.@¾ ±ëm€g^ó¤Qc=q6ŒgQ¦”É<ç‡Ñ…öÓÙ?{ÆÊ¦¥ÊÖK 6ÄR ‡Ïy“£Ùû×yu}À1˜Zä×$iIyì)J«Ý$Ó_N)ås×ðƒ•ÚŽ\byam½ÔÜ«»û:TxÉD)fœÅ$påÕ‚ÿÚ)M ×aüÉ5çÐ:ŸÌÅ4/ŽŸØ#‰ÏÊûŸÞŒilA*FQî)PU–QÁ†ûý/§Îá¡×?Úÿð&…ê*H1XÈ©ö(îå&w«5ÇMØ]à­Ä i¹†’Ó˜MmnÉh–ÃÖRsiǦ9ßgn¯Bû`Ú@=(t5¶Ê™$µë{šÉç_©\9>ós‚"hXéO3õüæÑžñ+g7@i˲/߇ [:ÊÐÂãç÷mí¼ÿ°ÔNs‰%ÚAÙúORÖ i£'¬q‘kÓQnB’Ú.-n™øÜ);V|?Ï…Óþ2;¨`™ÂmkXZ&Èï~UºÝ]ÕÛÌöŸwý0×¶4V¥I'¼³Øü| oh˜]’´‚òOZ±K 3°(_ ˆŸ[»‚²9¸Æ0­©­QsQ0Ë‚+ÑQžö¤—±ƒÁ¿{¹˜²ìö"üÆå‘š·×}\á:ð¥‹öظyw|ÄÀ|óq(ö§wÒÿòÕ~÷e ~þú'Q®˜ÍR÷éqýÒùÑ÷¦Ûëý²»•á½}Íl™c³éħ ‚µNÝ|[I,4ÙòaÑê%E)*¹@…ß9eñ2}:ØYSŽI íXøñ'°´×ºrþøx´jöD9p;aaðÖj«iíðcö‘cöí›y,Û¾ÛZ8hH¢TÊÉ“´7`B‘g÷fÁ:…K5V™ µ€ÙÔŸÝööë±ìj&ð øÜbI2í€.‚¯Ë<"ÝRúÅ{ìȦ>ÄùƒÌŸÉz¸L£ÁauyòzðÙjûæmIçö‚ˆ:¨ø)œ² g«d!JÝŒPk qÛ Y¶h!—žÖ¾%ÚQ¼Ï…³Ç¿cMWƒð Íì¡1ç¿ýj!gùÍøõGûË4¾½â°(Ë•)vúÈÞ™1¸9Ãv}ìPûíGñZ3—Ò§O–áoÜmæ0îºË¦Ãž+ÿÑ·áOÿ÷%0Õ_¿ çßÉô¿_‡H$qÊ9…÷UãyÏ~CÁ,ø˜vîtIbG„³ 9æØæ½>U:]:…iµ QCŠÓ˜×üý'<¢ìO¾^=b§Ò-ÊóðÈä—£w¨‡uÛÙä@σF'504 Ö m&…¥métx(|õ;à9~ð(Ú£ fgཥc¶Dqû®ï#c%½0© ´µXì$,S8@î? #ä”ÇÀuÜ,V’¶É8®¹ÄµŽÊ…7—¼%í½™ÂŸ¿½ù`pàLɆvZ` €2“gün9S´¶3ÛWK+‘¿»´Gð°D]Lín†³µñÉZÚ†í=Òë± 1³T¡€nªê®™A_æITp¯ßë$î÷¾Ú+#Lâ»a–yÕ•¤ÈÌÓ±qª5J!ª¥‘li«¼‹þÁnʡ䣔%2ç‘6{\å† f$W&m†[›ù=¥_ø{á˜ÓÝn†ò$¿$¡”e¦[t@qYbÀoåPWجVôÆ{q ‹g‡{´…P½%פ‰kLSÆÔŸ¼Š;Vý¿ÿL-Ö!ÈÓ–‚i…îòrŸíyÌn%1öz¦éæšJR„–!ô€Ä4=îñÓÊ4rz„è<’ïÆ<J!ö4ľs.;3a©Wüà óÆÍùÿÛoõÂ_g¿Xñ\’'Æ,$…o\B߸Pøþ—«ãÕýÐEgw_>q²÷ȱî)ÌópJxôè€üão…ÿþoü'Ï«ƒ%ÉîA¹•#Å1c÷!ôä«FQ1t:SºŸB/®aÓŒ¹­1çL¿ÉÖNPÍ § q?Êj Óù[·¡â•ÿôµè±ƒ<Ãíܸ¾mÑ9fpµ·¸ȶ;Ã}#Óy'‘±‡X,§ˆÛlX"1äÇJ•òwæ7$Űí8dnÞû~:¬¼Z e+`^h²®1Œ"™Qr¬“ÈpHÎ< ¸VK|æ¥yŽCÔ”*§eø v¤"Š~ˆZI}»£¦K?x³>µë?ä©òÀEšz9ÁLgÁ´×)ÅÖ+:—*Ùx9ÜœÞÔY,Ò€³™z&íU¦7w ¿XvÚéÑe\ñ݆àM‚AY¸%vÃ’±!~¨ók‘f¡6 ЦCh!S*PÌÏd¾ŸŠn.YÒ,Ô¢á ¹¸9ÔÍÓÞ¡$‹!bnŽ:<Å^æqk1R'êJ¶^j¿“Ý•Ésß„Eê¼M„¿·CçºØëÆ4®¸&Ü—HÛšb¦ ÷=g¢yª{pÄñ}¨˜ˆÊ0Êê6tI=·Õû/_C—æ‹ÿËÏÉ>k8¬Ð–P§êÄI•ôèi»uššF³dwÙˆŽ†áù§ôÅqe°f‡I½üÚ€}Ð,7)E¿v_<âJ=ïÝÌ߸µü?þfÍäâãåÐ’FÎ¥ðò‘âÕIôý›êPÕ E”bD{k«ì‰Ç¶ƒ†Ï‹ÌÝN$\>ËþÙKÝŸÞàKÛý!JÞº›+µ·×ë”{ø¡lÊd¥¿K|²kÖÛ‚¬ÎPæSGK €Hx@®¿!7&Ë–}lŽ›BEA³€œØ:„†¾ÿ×·÷x+é íæ•Ý|¿ÃË$Í3¡ µýÂ6€†D« “ò«Ößš¶Áž?×Ö•CÎS'Rmö„A*¡CìÚH¦‘j#'0çJ3l´ÕRæR˜2Éþþ§›øÉb$óæñó‚ø2—õ‘áÃËëõ¾(Ül9ë& œhSH)”ƒzksó»þ~c]’B¨wsuÐö.ç]í™SÛmKñÅ ê N« gFúþéo…?½ÞØšÑf‡^èé¥þ­¿žÇÆã¯^îýÿÙÌ-ÕÇ sYר"CšAûÀÝLÛaó›öÏÿnE}9õ,©VFº¼]–Jš—Ùªi7²ÚP%ÙiuO>6:Ó¿æ'þ™óÎ Hïn=©•¸F"‡2:0z”¤D —¸A„„ž5å‚OC(úlÖÝ\ˆ—ÉæŽ, &(ZRÜÁ}R{uR'qåßþq íš“ÚÙgT¦]Ì @½œ¼è “§BëJ>Ô¤'M9`혷 žÓÁû([v A#dßH¥˜–{ïv© k]ç§–M£Üsf‰Ç©ÄáÛ+ÝRM¼õqæCqi7úÙÖ?ÿ.Jß%_Üp©Ãå-åÍçÏßûr¤oTZ¬±aÇusâ™Gü–J7‡9¹NŠÿôágkjµÞë ùþûôñÊ»›UŽNàx A÷Tr€^Ñ’â#A—­Àò€â „ÍÝ'8«v_"eŽlW5ûÝ¥›"Ý*ù,‰2VÉM›ß ºõc\I0àVéZ”cµˆ»©éШ‹bP•"2›¢e‘W2îö¬ öýùNRWŽI¥s‰Ì¥Øw~0Gl¦€Áš~‚ëÖxÈZ än–_ß„«Õ‚ðËO™å £îÐÐØöþj_­°ÃÒFŒ2 —±é«õôµ÷×0û3ÎÜÍúvX'™7a‡óŽðTE—w»ÜâÖ™ÈJt;pb¼ÿ÷~Ý}ûFweTÛžºÚ_öɽ¿ÚÍ ¹p,{úlõÿkò`aѴ²aãíg'é,oÑ¿üÛ8,—@{N:P;²«:TfF »×•™*U´»Õœ<5¸\Û0ÞÑ“T¥ ,{Ð0;8ÍPŒ­ÑP¥„XÝ]œËÊŒeZbeD=ÕT#ùÅi,“UºU×Eé +*§¨¨2ËWÿßüe[è}R)û¹ðh’Y†pƒªpΈ*¸ƒ –Jôàá}vÞD7ã|ÞsÜgtð>´HÑã‰í¸6€Ý´P5î ¡N½ = Âq(aÔI èâ[+;þìÝ:¡-,ízoÞlþ³ïÐüçì“›e ­|»ìÇO?ªÞ»5Vêëh·E~ï%øt¾;4ä?{V)n-”§×Ô“ç‚ü•8·•?ûARwKÅÒzõw;+f Wíd¹Â„šTÓTP4~Ù‚50¡vr¢AÅÐeë&ˆ3/|L¤MPÝ·ëŽèÓá<Ϭ¯uÝ ykk—4µ»Óæ­¸´ë. ­vÞÌ€s§¬Ü·±Ì˜³APv¯™¡º»fIotìÏ›ZiŒ+™A`ç>…~w¥ÖjcvÚ@X EA®¯•ŒsöäÆ×»šUðÐ0àÖ~¡ˆ×ýË7ÛKû@B‰¤¤Öf §¹-ã<©”økß-káŠ-âS )#LEÖqÅ)ÄÌIº¡GŸ{¥ôÛ_í¡[3Ëîâv͇l¼Ú²¾¼&-žbW¦çÎ×H™·Áá&$ÅÜ£™éPajÄs qmˆàÈQïë_+Ì-µZEt­» Ô¸Òç¸å›uóS'KÕ ¥i§Xe•(ôwº 5sŠÿù:^ZçA©ç)fÖ{áI Âë>ßÝ~ü …]Œ€Àóèí[{ŸeÞ4wUM;í®i¡g) YRU‹M‘Õ[YW…í8ßjW»¹¿—g‰ Ó¶q3âJ[4µgp —]OàvÎ •k`ý±Ovd:(æRX€nIy +„¦° ÉÏ¥5®õ,‰æJöó»sâ§7½ÕÝ*†ªîо|_>(wîÖ;4à?àøÅd‹KÉ[Ï]‡ªÏmÏ`~õ¢È0½[š^öž8ŸÿöÓî_üˆ¯› Üdkwìoo©‹Cƒ|—g1&Rwµg[Ü–%ëÓ|Æê9@½¶Cr…„ f*ÂëXítEñ–IpËÇDõªp%ïdÌbI 2Òise+i?CÍn¹•›f.[€÷÷’޲qBª¶i""ô$Ïwœ@È݆°ËxoÍÚBõØ‘X¤ÒjiÕˆQ,—oñC‰—°ûÿ“ôŸOz¦ùa˜û»ã“ÞÜÝ 4rNƒ0Àä°“6ró.ƒHQ"e-K2­²Ë.úè—%Kv±J‡:²˜Ä%¹9ïÌl˜œ03ƒ 4ó›ß'Þù|ðõ\¬Í¨šó(¬V“,Ëdðè^_÷{¤«‡wTÆFsžõ«5^õ»/uïn¬"L¡=D“ƒ¬5æG™,Šúê—wmT‡•AÇ*°Hú:)7öRNâ¬äù=Çç“Ã;ÜÖÜrtoÝ‹ ˜ªæ(Ü[T$Ù݈Ÿ;¦ GXç^æið]Q”ÛÄ×n˜†05¢$kGOV?÷ÙÚ½»½N§©UïvW5²!xÎ`RÊ•‚¬ëNeU¯`*¯ºÉzÍ„%àÊá÷Þîl¤QyØŠÌìàÝJ;ÖÚªÛí¿Xx5V¦H´L ÁíÙ¡îeÇ7\o[X‡î¥ã3ÊÅPo¼À¤ÛOº:}ÛQa'ŽzYÞÊÉ ­‡$ÈNÔ±9 …»ŸûŠ 2Ì0bòÙ7ØVÅõ ÐgXyò²er£ÚÍx° ÉëH†¾€’JONˆ+ ú'ð…­zu·é \¸ˆÏî*Ò¬mà=ãìäãUܦÂ"ï>qÂ'_:ê5ô}ÓÜÓy'ò¾{)™ÿôY=•úÏßê´¦¹³ÎZGfÅï|b×G]‘ÅÚÓãHPK\áÄ9\é˜oÜɇ »Ìä[¦ÔâØÁF-Oh扚‡Ê¹m¬ÄU‡óóÇ‹ö•ês{à Ù'/ÊGÊ^^^dZÔÆ;8n÷ӥϞ…? ¶Vpؽ %ˆÕã ÆÓËÝøQ£ˆÅÎ)éØQd//A¿”³Â¸(rÚ{ÏXâ€Ò:—;ºÑ²%’ï™>4]ã”{¨ßo” …á~ÔýùûpÅYá\úž7aÌ€ƒüáŠýô'Ó3ÇKìÎX¹²ÒP0UÆËU•2¶WÚ|ùIO¬—n¾´€jÁ šÞº­±P¶:´V”:ÛÄå}ç„mW^ýîåµsøìõ»IÅ‚‡³ÚZ‰£âá3áï<œ½ßo4z¼Åó¬Ôiæ‚R´¿¯¬W³&Î÷6¤EÙþáRÃI0¶ÈÕpTáž_ZúéÂÇÈBáš³ œ½Ÿ¹)ìÇŽJbºE)ÞQ;wÔ1çŒ @€³wÀ º6`PlÞwyš*cqâkú'¿S?}„w»…ê×Û‚Q’Ÿß7ñO>½þ;Ï_9í?µO?ù_ê·ç;¬^Vî¥Áfòhc¥MÒÔ *u­K|B0<§¼6䄯‘“–Nü¶ÓkDˆ*¡á”3Sbÿíc;·;Ûí¬Q ¥$"úÁŠ›Ù7âbµÒßʈ€IDATIΞÍm×îÑ{jC;*r3]­ßû’mPû£ÙÞñÖ>…¦ þ‹›ù‡÷°4Fc* 80Þùý§÷~ØTqIê+eO2Ö\0Ѫ+Ú¯¡`È¥z›ÊÄ¢ó'­š «w”î7ô®'C9eÊKö¶±)ãÁàäì<³Ó}éAþŇ陉AÏ ­v-ª §M’ßý”÷ùóöçWµ²yàdî¹]ÀÇŒÂÎN83îÛ¶JvœàçeVG>ûh¡Úi¢–•КØYãrcº¸_ ëKDfúÀXˆµ5<Ï+tUít^x”©kÈ,.ŽøfBºÌShŒŽ {ŸzÖžÜgwñ¥NtbTraE)¡ºÞö¥g«b;´Jƒ@Ô’›·sÐPT‡· Úof¹NxÌ&kðþO{€‚ó’;©7h§‘µ0 ‹ËùÅ“ü7>!Î=ÄG†º½m‹>ÉŠ¤O©çMö…Ž‚’‘‰r|©‰¤Kf¥Z(}Z¡(s|ê{ï¯þô]`±‰²˜§8²0Ö¤‹‚„èmÙH'ÂsgszB–í1KÉÆ{ƒýÆTíJ@ç=û11DYãrfüõ›ôÈš÷­ðJÎåç÷ ÿ7Ÿlÿƒ'øgNàgàO?-'ý{‰%v´l²3Ä#Òñ#Õ¦¼T÷Ã"OîYpÈ~Zym$Š „OX¼ËÑwÙð7Kp†sÏCÿçv7;[«@:ÎYˆä%8z¼¼Ö'w×Ó3÷•\œïËŒâa0äÄññŠãþSJÛ´ñ™'X5/ò þg/Ñűb÷þÞsèï=„¾ùb|oÓûâAüè>¼,m§‡-Æ}­Ž€Øç{£ÈL@ñ‚cVŒ";Áíc”ì³îC“Fû+GŸ'ŽöQ[­ß³!Júƒâ‰³Á¾F¢Lz})üþ‹âÞf–ëèÀ´ùò§ÔýçÜ”_®TJ/]磻±µõ°WX¬•ér5y¨QõX“œ ¬ÛŠÁS;ã¢àaª°EWœóÊ B E¥˜˜×ÌÍmÕ÷Z ®eFßè‡ß~E¼|M­›¬d5*¡0®‰‰²¾E-´gOÀìK¤ý dýôSa e«›Æyòþè|½X¼ª··g4¾‘1¨ {”P& 2îžï?œçÛiÖºñêÊ=˜+íLŽº¦aö¼T†*`a|´ûO¹³gr>Wºµ98AÑANý4gM>†Ásâ,'g8ßTÙKà$€TxbÔûÊ!8<Â?¸ƒló¿2¾kj¯P‚ÂMYZ¹p¢œÅêäqÚ(Föu†ËÃe<Þî×¶ÀC^¯ÌwÖ©LR‰Tísè(a=4ôÍwÑBŒfº›š¯=å~ÿ©áï¿Úúx|ål§ék´¹mÅ='ö:±' w:7núR8jä”q;¨}û±¾b‹ð`íÄgÍ}' Ú·+껜‚ôçÍVñÔùáÃ#N™üÚûîÏÕÜV¢uåü^ôÙ_“ݧÇyЈø«óy6JlÁaÔ˜û4†9-{AiòHpÚ?BÔgHmÅ1VãGx"˜Ÿhlá²±”’X;âÒ2nonÈKóýØOd4Ú.ŠëÝÆ·_ÉyU[2R6YU+`Xfu Ób7€d÷Ë_s½7JØ£¿ö\¹Â³¦ó©.QwúBí÷¿nç¯úê­æ ·bÆv t9n”àêfºÕɇ(4Ýw¨Ò¿åM.©x=Qåè+_JË›…”’Qxò,ýôÃ#j)¼9ØäõqýÑû&K£¥¾‡RÝfêHŒi ¶”…þå|n…åuOº‚k¯-oþů’Wg5Ÿ:i4U<«$<è(—yS¨¨©`´·{7(RékC•åkSYþØø]­ ŽhD­¹ŽÅ"&±[õW.Œ†%2¹wpøÛ@Ò­4ÛÛ+ ®^fvȉªnZÿï^“qìEÆã<9,ÕÎÓèþû²Ò”î·¶>ØÇèQ3sQÁ9+v`ðAžfä#]‘¿JÌ@;éØHí89P×çhÖYû}ubÏΤ¿ÌÀ›Úfiå¡Ó%“eGNä¬í W‚A6ªC¾Õ¯ÑÿíMŽÈÏÏLûO=¤¿ôD«Ý4 Ï¿³}s»zd‡~úyà4cûý]éƒ>Œ–;¿û$m̨[?3ë¯ ŠG5Íßgp.c!´0]Ëý-0öؓA•*ÑÙ'ä±#…Sy’ÂèÄp8Ú:Ð5ó¤]„^KÚxо.àß¿·× 8;=úpúàQ<yèúÚwTëø¯ïÙS¦Û}„¨es« @nñ²p.[Ö™x#…Ðo£æv1óô£4¶Y­ ï¬X·ÌQ@"…µ©ð}öf<²ä‘; ñÝ%»É *HŸšÀƒÒÄ'™Ç+ðf{@0$´ ºB˜Ë†[ËÞ½Ë3ãßÎäÞáßý yøñà_~Û/éÁ—g ‡´×‚HçΩtıFµ’õŽî –n®–J•Šëo˜ÈË%b lÕTð™‹òö8úŸ¿†ÆiòËK¹½ÖŽ0ÜþÆöM(1š¥z sësRyX¸‡ÇÊým9kŠ-~ÿæà͹Q áÆAI ïF,7x@k ¼¢´WšÔ‡.Æ[Cx»¥r•ª |D0´Û4ˆy4¶C¨2v…”XÞ]vËÞ•¿ng!œz®ü¯ÿ~öæÕîÏ.ñ«mýÁÏÈ}cèŸÚ;5’üi8r,% ú æÃ«3{Û5ãrݦ¤Ón~¤à/>Ž®­z ²£õÒ§žˆ?{‚½w£vóošÈÅ÷}iÇÊ`sÉwLi¡RgL™Uî•8jÚD¥Æ/iíCœñÀ yü|Ø'Y%2"#jSyšbì#&@¦®RÁƒînj0´Ûúo `6©J×$6ð›´ò&~µúV·Ÿ°V±ˆQþ`slþÃ¥iÚЙ®ýwîAÿ_}Û/‰þg.Uék•½ªÈtƒ:áj£ˆ{ž$Ö_º{7ôÊ#Ü,eƒQÑðháþˆ¤Ÿ=_ܾ£¡þó/™i.Þx/å7ó «»±}»„°Äk”Ëx~£ YTŒ­l꛲ÓÔþìºþøTÔ´É8X!AÆê÷ÁœFf´À²4­Ž=,{±)1mËõ…c>­` ºèçM%C § (ƒË-@sdñžŠÜjþ¸m 8ùtíÿý›íë7òçߌ® Ò[¿$Çîà?8g³¨¿.¸%²9¥©WÓ;vð$Se˜üµèîžð×ͱÞKbãìëàƒ£!G©î&òf‚vÄÏŸˆþÑ' ÕL^߀ËÛ¥?ùÛÞ?ÿu|êƒ7>î½tÝ¿¹Â~këÙ³À{ð…O°ÅÍàg—ÜÛwÖ; ‰i! ¹DÍ-Ç?ù/Õ'Žä_¶Úo·[­à¿ýdÿÁ=6[éÿñKt½I!´DéöÇàš«Ý‹â"CP¾nÓ·ó1òØD¸¹‰¥5’çÙ ºtÛŽÌôl×½r%›¢^'Uß³~54ißjÒLÿçŸekÛíB†w²'ÎÀÁCÅâb;¼ýa÷(ØDÛ›kí`Dà ‚A0D}‰€Ÿa3‡K÷†úÅ7`i."[©”F×às_õ+®DDFÕM±ÕÔ/ei$œdtFŒL mâ-2´%š]WÜø4Ýg0TÀ¤‚õ8÷9Ú–e†2Í­uHuÒÜF,$‡X’jÍ·FÿæG½î=ú•ÿùÿlß.:x°´¥ôÖf¶û~º‡”d²:@Pêm0T¤ùÙ`Æò# XU6½Ûÿî›á«¯´k´‚ŒøÎwì—>9ì•[‰#ÜFq¦å à9¥PßÉRnÙD9²xÔñ:NÚ^±©Í\1”GýR¢Fde'M]{ãÊmØÞD(Vö±Ô&|@”Xé|TÊcóÒs;?´ÅHyx×ྣñ'¿ìeIxùnÚ{×ø@‘ °Ð€‰C2×skt¯Àèæ;áÁFùÑý[{£›ì—ÙÛ·é?_u»wLդחsÀ5keµ‘¤Csñb5£óílŠ ºÇ{m^Ÿ=fƒq·Ë2àáÑÊòvºø²½ÚFà!lQ+wÉÕÝcYo¥•hƒ»ïnóñ"üÑgú_˜‡÷ ¿¶¼¼±:¤Ú­ÿëïu_›S}ÄBˆG¥?o¬¶ÎŸ-ÐìlðýkÉ“÷±ß½¸'í­¶šÑ?zzës'‡ÇlkÑÄü¢yÿ·•®Îë³sx™û‹kØ:“¤È…³ &C3þ¤>Vqº­µæ› lG_»ª‡võMÏûÕÇéžµ5ZR †bYnÄÌíú«—ZK[mì‰ûÌ£dï±b†2»Þx¿sJƒÔvv1 ê@XGArçyÆ¥)dö”Þ}Ô?ÍHÊ—ß…­åŠßLE–ÊŠýì—p†ç¾ôP—cí…~–Æ«÷÷s¶_Ž.W[Æ™{*Ü„4Eq#û‚Öv£Y<îøZW–J|+ñ¬PIÚ.H… é„&¾Çq¬ç×pw©3ñíŸõâå8"¥ÿõßÅÜß篜vÛÍlúL{~–6sK+­uÕ¾*¦Y>©ˆŒ†ÑΙúO/¡Ÿþ¼ÒsôýÁg-…‹ˆ58@]ÑYïå”k‰˜Ÿ§¨0AhÐÞdˆ¹¾_̧p«hÀN1>åuõ¥zo`®/«ä½<4Îì,’Õi¸»ÙKÄd™^}?©?´«»ÿXºz ~q§òÞÎÏê‘™ñ(ö)ZêaZ¢j‘ˆ£ë½8ÌÃ-Ñ­çÌŸ”/éòÙcŽï°ÓŠû@FF¢ån±øª»ÞŪnéš‹þÕ¹jšmn¥‚äý&ûÏ»ÿþsݯìE{e~q}±l:•+òBó¥«ÃжˆŠ‰4Ù&ÏÁÐXÐK‘6™_@:›EK÷ò³{Ô‘ÝæÈ>g»y^þ·?ÏÞ¿íNQ¢Ý‹w’—>,Z-ˆÁiF2̪ªuûö˜½Ój²”íÞ¥ ˆ¶çè®ÕâÀ–˜Ý–æ.¸›dó†·z-§}é#µà˜ó@ñd+MÏîªýþçý_8Ù5¦©tyÆ ½îo­Ur”O#!YºkÊ< ,¤6?€ˆ€ïð?srà¨W“×_s£sÕýN÷”?[*5ú™ …éωITY-ŠM<_£Œx%¶_ôêQÏŽð,ðv4Å p0åÛqQ*a¡‰Ò6êhÙÂ&p@œ"œ7ŒV>qßHe"÷ñÄ20å?ÿ~wn«fübÛ¥±Ã×მ •Ý© µÝ;ÒÌ ^½7gùÀ¥•´Õ |üâ`ç´ók¥+Ýìç/Ë+·´ÅP…¶Þf«~éjkz÷p4“/xæð2Ryû£vh ‡ÕºD@Ý]…·ÛJk \^x9±©áF¥³éã~«"ì!9ÑÇ›³ u B¶y°ËšûH°A¤:`#¸¤‰Žî~ vi<hhmx^¦µCŽ+9\sK­[Îì…ÎÀ3,TbáŽn*2zíz •uÊu”íž4ŸtGÕ“~øÚòº#9¦ÈÓ°Ÿh/…íÂ|ˆó›r{˶6ÕÅE[*2†3'j'eÃ¥Á¤'ïdlåvÓhMŒÄ¤@¸ÓÍ~y={þ*Á¦ VO®÷ÌFŽ5Ùú¡ýå]c=+äŸ|3m»BUаŽÄ ×=)&ö)>ڈѠÊ+YHj7VÛç§ä‘i±{NAjÃÿòWé;×L‰ç… m®ŸŸM^»*6¶LêˆÐÚ)nÔÎ ³{Õ=1¶SJìoÌÚÉ-½§å®­K¸‹ÜUÞ¼FÖ>ÎÙÀxV-‚—6ÊØ´7ŠôÄÄøï=ãÿÎ3r¨^ÔÁ[6£½l#\^ô%‘Sg SÁïÝS˜ ¡ëônªû˜‘ð‘C)´W^…Ú½ÆNm˜ÃÛR“ #å^ Ê[†ˆÙ´¤ùªPë¸*£œ÷ðʈÎÎ"ЍØK§ã[ª¯œ7ÁÅ”Ž'ÕˆðõBv ªZM¥â†0«ž8S§ÓÛTOŸ‡‚ÿçï´î¬×2œ·Y1Ðpc]º®‹ª9fhj*‰EréNc[¤Õ["µ…ÅUÿ™ í™)MëálÓþìµäÃhÁ¤¸Ó©}x£;>±]ißÇ÷eU¯òÊõA•úmì¡<ÇÆzb§TS#g¢ 16àiKƒƒüjã(kŽæAÃŒXÛDd[×jUÙÏðŒR©ßô…€TF«É%9²ôzz¸\66¼M•ï<¦TíÊWÖx²®Ê!}W BQS$wçNáƒe´vG­ˆ`x¿:p"Ͳ¡ã™qõä1»ÿ@)ͽVZzš"ªéãȺÜÌ]ë‹ë¾¸Ž³%ÞŸÏlAY*eÑî“C'dÓQ<êÉ»à7ßõî€2Ü ç FÛÝôg7âç¯#$#«‹0YéÇ+[pßÉ!3èìž÷íŒA™?ù®}}5*¬°ôT2 òyêî3æ(ò†|«‘mv£Ï–»ü‘cãY¯ŸWÃÿïOú݈ˆÆ—\QŠôÎi61Röq)OòÀSFj@Á¨ Fˆœ:QËpùµkÑßëÜTºŠfã×! |«&1kP†Œ¾™L8¢(¥¯’»+ùyz·Woö îqRLöëÆ ³ïHΗô[‹ØJ +¤OàÒj4v4dBêa¾£ËËÙU©{ªBU`e²tÉ>pù=Ï †éu,ÚÄr¥¤CHýÛ"ñ‚³Eð¡DiÙ·xÐ/È’Ëg+¼½ËrKTQWz.T†œ—*VY §’çP}Büò*}ÿ O6Áƒ¶æ±®h›Õ2N¯¯Û»á…v%j„×.÷2Ö-©mj°çÈô o ¿ðÃl~µpEÄÛ’r[Ô ¡Øµ|äÖ-7ðògž„™þòRqõµ [´¤¨'xê 6ZWí„nЗDsÖ¢(ÍEÖØ±>È;ÖÈÈ +nd4Ç„9Ū0}Ô$lzÍÙÊuØÞB­Å`M‡B,`]>©föC”Q©Þ½†+ÛF8÷EÚbdŒ÷›3êÐùBM¹êI¶÷xµ»™¤²|cY]Z~í½ìÝ[ƒ~?‰Edr-­`¡}\’:ÂU!HU.°E‚ZUUWÕëWÒÍêèÔ…À»õv±¾R™Gܺ´ävj<Ú±C5êÒéL‹@PSÞÞâË­ÞñÚY‰ïþ×?7WV 3âW<â‘g =¡u‰¸a”Ÿ±î°æµÀ$Vw…iöùJ—}âÐÞ¡À¶x禸yÝn®˜Î2_uøŠÕMŸNžÝû0)HVî^Å|CXe>X(˜Å¿±Û;rævñ¡ÓlÏñr«•º²š}8?þúeùÎõ8îå©‘6 œW…û”›±¬nY@€Z¯Y7T¿mß¿ž­óòðE_~CÞÚôW€8“–CÝ5U›šRE 2U"ÚoµÉÝÍþуu?í|äÿüeþþ‚-pû§Ï(ï˜Æ"´¡‹%€5OÊñ”Wuwûâ£Eúí·~ÿ³ä‡o“Ö`äkuÍpF­VM0×â—çéË·Ö”•@Ž…Íï"8»\]VÞZº]þ$Lõ õ—ªèž¯Ä£ îÇPp袼lIdN <. s4]ܺµ’·›>†\‘zuºæ­v×hãÎZ߯¶ ¸礫)¶½ 7æ-Ê£b¾—/ØYÛ%džRØ]‘Ú qVDHú@¤ µž± !héJž554yCØ‚àÎTr9t§µ ºx ƒ3ý „(b**m’@Ŷ2×m›Vý[ƒ–ÛQWo!îd% @i£o-7RƒÇüâÕÙîí{Æ×`èVH*…vпù³•&À±ÆPÚA‰ØXä!×M–Pw¸›ƒJîŒþÇ…ô³_Ì2E+!‘Œ‡ÌÏ‚æV%Ä:cK"b$ÇÇ&êUÖ½«×Zf!¼—–æ]2€Gë`›V%Œ“¬n`n:"ë˜" åJ–ö’g…¡ ‘5Váöe(û 40bË• ÜÄòp€•ÃЖ¬­½¯m²åÍ,õÖÙ¾N¯7DÚæy•ËãÕq¥J¤;5iæÑ`­s!€¥è*†w DÆ”…û}ð>#†ç¾×eO2úø^²·Q[Z¶½™ž¿xìo¨76eº˜À¾¹RyûÝè³®ýÙÏ—¯,úâ@ =Óƒ –w|4¦aåÚÙ5 ÷‡¦:Ðùk“ X@ <åܘ’–@Š]ÙèÈ€ìQ ̱b±Uk‹Œ6™ÁÊ‘©©© ¬Œz0Y›Xlöˆhph c<Êr0T£1 ý&¹·¤¨ÄËÝ´CV=}" øMÈ]æ)s@ÚÈj„樊¢‰+ƒm -€AíÉT)¤y¸”4²¶Y%6Ž $EaSÕf‹G&ËJsí6Þh|ã/ƒ•^©o¶‰)”ŒÊ4AÕÃ8ØxQh^º>¸~K: šE C*7™uÿן¯ 0;Y[q%P ¬ÌÔ–pášåëýÜ%w«ÿæ®üúßK‡ õ¥ÎDÞsx"ˆpA;7š£!Í2º ¹¥Â èöR2h¶`V{KÖ¡;“)â׸iæò<ŸÁÀaS±@ú.é™8 l–KÊ~å tJç»—õ ®4y*Ût3PëARÄå`póquéuh7‡›ËÛ.n啸e‚b»¸ˆÑòT£¬çSÖé¾õ‰H´{jà.›ü… ñ²ø‡,ú59|çÅí7îå;ßK׺ ¤£x˜HA­•Þƒ'G=îoÈN‘/¥ÍÖ0GèÃNýÝÊÏ>ÔúÛ7ä{³>85¹gS}Ç3£ÂŒAþ>¾ƒŠcÂ=Êý1M:6ûfÅÌ  âÁŸ|}ŒG[²Žæ²^Òm-Î¥/\‚×ï@pæ8ì¨üòÕ¼+Ê<̹ËÃUºnPw W1JjJDUF[~ç uÏÚ(#Š9,ðO±3MRcÃðÇÿ0„­%XÝFóIqc u2­€IE±8@‚R‡¸_&¹‰ÿ@°}šÎ¦;Óz/”ƒŒ€ÿ.˜—™3Z•z)y»âˆ=äcg xÍ‘kPÍò]Œ€P‚r(k£=Å>ÿp4Œz”%Åî5K¿|Ï]]ˆµ”Q¸è2 8r|TÊ.àûM¬lÅëƒA*©–’JmmàNá(-²š+4v{Õ¯@™ËAL,ŒáÈú^¬;Ëš7¸4|9Õ!ˆ5GCŒ1fšÙ4`‡Y02Bî6“†… 4"EZ¥>O÷ƒÝ`Žž{ÐVu/î…úÑ»âëØg>¨–=Þ7AÃðƒ¸ý¬Ñ6BHÕ.)ãé,|M'ß$P6ÁY í㌇Q\J“MºÂ%<ø;ž 5䂸Â<È@5 ôh Ÿ?Œ¦K‰!96÷ÿÅÿ/Zk9§Ù€=kz¾„5¤aüÄËï"3•Õ3jÙØö­ç‡ZwˆÂo˜V‡2•Dµ ~òÁpq+¾|Í <´_>ý žÙG…í§¬åsÚKM^ý£¿Ûö–í老fh‹éw”½æ¡¯@¤‘ù©“cB?á…e¡[DýœÛÙà?üÖpc¤…kµz’ 7tÏoܾ=øÕ»ú•0@pò L6Ø—p§¨¡@nðë.êÛtˆ3¥ÌÄÃ$üSš…¢Ò z‡4úŒ-å$ŒÛi¼.×?¢áežêO?øMÃ3¯ßñæVð¦ìÍ­G­$µ1³ŽŠ0%Y& E€Âå¿lŸã³¡Ép;ˆó}ÔEÊaŠ:®QÕäl|¹Øê¨ºრû˜ê¿ãYþ  žµ™«”ò0Q›|Dë¨ÿgÌJÅInAb¾¾ ›CÜ]Øåƪtz Óš{ú_þßheÛ9`{ÿË$g éÁ¾O~ ñ-1šAñÁµ 6UntD+ÏãÁÀq‘—ê|ðôc¥Å­Þ»WXô=âÙGíÎ}°C–"ß †µ3á?ý¯iGðÝñõ_Ú¦ê--®„ðy‹Hð¶ïWh†C#n¤ xM‰gë$¾°§äDªKvv•}÷GÞ·ßWû èÔøPò/¿†Û]´{lvË(È ·CèY?øŽ)f-øa#)º)8çЬ}‘«ê–PdW Óõ |Ú ¿rÄc1SW{w?PIo|qE3¬5ÎÙ1V{`&leÈú¡q9²ú˜±U§)xÑ@V„ºAñÕ­ZkkÁ B¡E‚|¬ wvx‹N[.}ÓÈ —˜SùAúÕÇÂ1Ø`©Ô†Ú?dΆå±KM%¯»Ø÷#zÂó4BÏõ.œ¥¶ÃovrT†RCaœ&Ê ¹« ÎH¡†ŽuÿÞçÂ{è´¤C•‡Ú Æ'Åï~-èwŠÞfÔ•±¬Ef ´öóB›dã”ë<%¹o(úÄSùðˆ¸sù5 䯹<³ u~FüÑWü#CÝ@£,Õ¬Ÿ×ÃüÌÑ1†òk‹]…¹Mth#Cì¤èQ¹ œö8¦0o²ê-+;Ä2«5µ ‰ Œ&Ьœ@@çdŸÙ« œÇÃä¹£LkýÄÃÈ0J­”§vVŸ>Ÿ?|”ì)jZ“~釯†¦Â8×4ÛGÙ¬?¦ð.‡\òLëžB¡U“’pèÇhpÝèNeÄ1ôz^õž;Jþ»gŠ3û¼·ç][ Ïw{^æR=ÊiŲ¾ ðÏ.oo:¢ýóÄì–¸Ï]•äí€%Ú.€Yáä¤6»™mZ` «&È Œâäáe§òÂ×7×ñ7êÿÍKé.îÓ½“µüÿ*}pR&Exg½°(Åqf Ò÷ ×Â;|ý‡_G³·*/}ØnÎ,›`ñv¡B_Õ<›ýþÀ£ìØ¡‚ðÊŸï)…yà1@à ‡"W s\‡Éßú¢õÔÊ À)+P#*U‡·7—†ÜÊWˆ®ßƒë›¬PÆ@ç”Ú€FŠÄFâ–àž-^}kjç­^°ƒûï>….qË,¥~ÈQ¦X°5Š¿öH÷ëeXÚŒ.ßN?ž­Ï7G.݉/߆J]>~?F*@3ÔN4 œ)”xm[F[¢ƒYÂr¤Àå)“†Ýl¶L0"TüªQ£J7ÝfQDבÞvŸlo޵Si-›ƒ·îšwîNž>Ÿ9µÑØ‹9ØÞ'½¹Ua†¤Û¬ j¢æ¬±Mæ<[äv`wˆO r5(úš¼1G>õähÏÜûé[#ï¼´ÙóYÍhÐ]!óæÊ®¾É¶»RY ¨7ÚÛRõ| )¦ºü«,F5pyBla†©§SݽÊÐ^ÌÊjÛÕ#Z_+ÄõwÝ ¯+gáý ?8YYºÿ°:q0ž™0TØ·Jý#„0Hn ¡.Š˜Ùõ®É¬Œ!´°¡Ñ=ä¦@>¦Xc }•¸Ó:fæyywY|ål…C/s†MRƒvlú1óìW>¹cíoTÓi‡eªºÎ³%iRÌ#§ÌžÝ¤úµnãJøÎ«¢—ã%œ(—[^§ÔõCßµöîã_¸8<½³Çô:¡!-„M9tút2²ður{)zÿý|nQUáYW!Ñåªfy|¨gpÇ÷»¨R{ùÕž”{®’›Ô DN"Q5¨üÆç)3+I 1!P‹(è'c´óÙsxnÁ¾»:†*awÐâÄJ¦F‚ÄH#ß•i`ÁÇX#»bÔŠMÎ2zÆÖUák‘å˜2ꬲ¸‡ûá }¢Xݦ—oê—Øbsêã¥íg ?(?rŸ>ˆ†P9±]%$ ˆ”H©cu×9°Á¸ÈC…ÖØ¤¢/d±£ 'ó­x :†û«¦T…¼¯qo£§WVFÛ‰”ÝèfÈ ­‚ŠK #'ŽÃW/´™ï¿s×™Àø~áÊTV¨bñðaÈ6÷tG[aÜ5ä¾³éqÔ¹ÇÔH%;Y)’9¶ÓàE·çiÒOˆÜ¦Î1´‘ „d¨ *†0†þé÷å­Á@[ŒqéÈ~wáPÿÐp<³Ë®Ì¢ËoÈÁžêôa„P_Ç‚1­0) u–M¶HIÍùËb%šiÐÀù‘¹CÛÅÁ~€Ý°Å!NF%) öÈ™‘ï¯çÆ GÞz½Ÿ.°ÝêS{¸S[µÒÖñƒò­YfHdLL$a“ú 5BTgýð­–p>øò3h¶Ã^{³¨bé"ż(êiÎ ±øÓÛ½©èäcmnYð)âƒ+¢a]¨á~’ôV7¾€ô)öÆ‹m”h[¥„sèâ|v'o~dß»}<«ÖÀanl€‰­•\``Û=qds´¦MœWÛž7 xh´uäâRí’)ΉnlH'­,•Ì! F˜5dÖH9X£@­Ú€áAûB›B^‚r r5 «²à@)B £Ió£ÊÂÝîý÷—¿ôL÷ÎÜÚ„ç«÷¶Ìwß?~_ ýû È ùc±èGVx¹•&qH€YhPæA£´§ÝIóL•*EÞõX¾µ”Ýú»u™Cnr¾1š„ùŽ2‰Æ×”9€oµ[ª¤ÃZ•¥KámŸ¾Ml=ëˆ 8©,ÞÈÍM†jÍ,g¶ŽÁ·^{o‰uWp¤šGÏB¿5´8hË$äÔ´ û¾»$(ãÜœJEkP*©DNƒkÖ¹Ð}f˜*ª€ûCe`t™äÓÖ~ ŒN*NiôOà[qp68²‡<|´r:ž™t[÷Âw‡êÓG Œ “kꬶ 8kV]1OÐPÁî‘ÂbŠR+”u!V¶×2Hl–A6°2 ,áëçæâÑÊŽ²^KŒÃåË/g«7K“÷Io/¦yQâSGã×®„:ÄÕ¡Žç¹ƶßÕ/} {*ûÍOó›ëî÷u(UÕ:(é§ž*³\̽p§µ³vòqŸ–6Ý&ø´B©”:®×2AÇ®ü"i-,~Μ¯þòg ¤Ì…Ð)|ñ~r~w¸zI½ñ!¾ïÙA©N4FÂJ©îÒ6é‘ýéP˜.v^yûnp÷åíj_¼0nôVÛÇN_¾—çé{[Š"KY,ÜE1¤|ߺLY :.JÚš5‘¿†"TCdûåi@Y0Ú2Ë`õfya®}æ|ôåO–——nµá­Û•÷È÷Þξ÷–9Yãö€`#*M“@ °Æ€ë(l"d30‚–‰¤ç±j:íˆú—Ö’{?Ø9$Š€ òû#y­ð‡f¶=z[€ý®HJQQÔ¹«(³ö-_Ö¢œ>P¢¹\»ÂG×A$¸4”1 ]ÏCJ–NNæ‡wR©rŽ‹YŠû(ošØÿ #îl[^-[‚j°4‘ROú`›ÉJ} µ¢ò;E´ˆÍ›ÐoaQ#ÞEîS‚€±^Ž 0¹uÐëuáÂIúÔáàPiP®Ô l{.ºûÝÁ. ÷RW›.Wò8s!m¡ ÃB·„yÉ Â ¾s@4¢ˆ¦ErÍÌ!2žT{- Ä€I%Áx%¹W”*(˜WØÊµ­î»£ÑöãÚoOVªÀs·»â}$¡#Œ*3ö¸ð Ò u¤&n¿ÐqKBÂÈÊ[Íßü'“gÏô~ð<[[´çϦ?dÒîèkߨ<(ÇÞëlf£2ß‚@FJì!ÃnÂkÅ~˜øè'Oü£úÿQúâ+ìåKôÐïSϧƇ¿÷oçQ¼£Dú³¿”l¬†Q,À—¸ •^S8*JeD÷Ô/èu’›ß㇃íëË£«#Û'ñ@{øXaW)bšÙœbÏÓÎ9´Ø71³ S¸hÍc”Æ#À‘Ÿ¬ Û±,U-㤒Ka}À#‡WÖë›/övp÷;†}­¾£ÁvU¶¿rÏ¥#¿¼Ï0° [ržcÏ¥PÁl…ÁŠžÇTåt¯ò®ßªÅc@gºý'JãD<]+é~B´ ¼á‚ć÷ eØ5¬ÃaR®ø“^¦dÅ …üãöxAWr-Çò±„fu ñ7€ÌRé”CºFeP0qpΚ11+d^A[Î@7«Ü?Ý>9ì %—­ß0®h‰å.û  ïÝQžaºè¥T»²$ ý„Ï]K,xÐcªZÀ߇· y1/ê<<¬è^©h0ˆÀX„ù —eçòÏœ §lod9 ‹«•[·¹`n¾ õÜÛô­¡ˆôœU•¸·-ÕÛÈR AÉ8jQŸyŽ€>ôn’ú=+–ƒ>Š‚(wsÌcV2EyHŽ Ã ÎýµgãÁëý|ãêó¼öëÕz=÷Ø_ÿPM›çUGY+_h#]ì‹Úí_ Þ²F-¿ÑþݲóôéÍU^XÐÏÊG.Š4­¿ýñN;úñÕm9Ê”q@£¾.@Œ¨èÝ;òÆÍôt1òÁ ÍÏü7åÿéØxþ%òÆ{ÕCû¼§oŸŸýñ\Ó­‘ d×_´ááQàÛ…†YC[…pHz!‚™²Ç¥p’¾ù½î>&f׃ÕÊæ¡Óå´ˆ+% ÄÙ:IxŠóª B¥s÷°~¸€ÛPÍ3dŠgÂÉ6ÀÇ Óóî k‹Yâ”Z­ýY_÷—_ÚžòáÎ÷’ð C;&õdeðô>+{ƒÙ¢úÂÍtózbÐÂGÖË £GŒS:›w4,}\ׇ¤ùØ&”0>(Ä (ëwRahr‰p^‹m|x†Ýž1†‚rÀ¦ÂÔîy’ô£tÐQIl\V3.†”û ¢ob|1ŒÈ25(DNc«2 Ä`„…À:‰û)RÂ` ª‹A¢‡@…FŽ1n”Ð(0(  rP/`@Å!kœ@,` )€Cà,XÚ–Œ)Ie,ÂÔ&ıĀ¥Ü juá霱ÖZ ˆ !@`sJ1ÍsíAƒ¶„8®0$ó@µ åñPp©Ôt¿_Ê2‚SG ëD@]‹»¾¤ /á,)ÃñÛYJ·/¥±a5ShÁ,i.ððï^lÕœ§_‡…õѹ¿ÞÎû2ÏÝe?çV)b«kàÇû"(·šÅ~ÙbÜr1V°ðWbº‘ ¯Ü ûchhö½üFÐY§ä@¼.]CîV2k¦ç"¬ê“ …?H%2nM€4ŒË¡~«Ûݧ :vÌеRPX‚†lÒö©+ÀÕÇZè#„°v8ˆ0ËX@@‚PŒ‚ÓØs rl¹Ç³ ¨Ó’˜ŠÇ !AêBi«V;†ÀZÉ\F”ø1ë„€!´€°ëƒ䇃ؖâ 5ÀÄqSh `¬ƒ.)çeÀk²#‘ÀÆeˆ+²Â%d  (B°1GŠéÑ µ Ä-ÆÆÖ ç¤,P0 4 NsH|e-®(0K³ˆbTOe ‡5 ‡ÁÀ-8€œ£,Ï€oA2à²B&'Å„ dÁÅTiÀÖ:uuy ¾Sž£ÚR 8sV;àÀ !!°(0‚¤ <¡4M9’LYÖÓÐ 6dÌE(ïbÒÊ:!-gŒS—b ’û˜ x>nø¦óSV@#¢~ Úº5?ìGõ ™’z©Ôí¹°bhœ%š“ö Äÿâg› äe¯¢þÜj}öosÝÓ=W°pÏ¿„¥Bœ„Ʀ†ºV6³ÍõŒxä*‹+ 6¾‘ „y‡÷†Uyá²›»¯"´?k"á ¦Õ ^¥¬’Ž*{Xi°1€õ"¹§²Œö âò4tËb¨{žpVHÄ%KË"Rê+µe¥ ¡á˜6š°À ·ÖæN%€pÄp¦(4Â(p° QftaAcÔQ*µU¾fÚðš>-\Ë€ k¯@Z"ðs !ƒTh#í0°Y›‚š6aP $ Bˆ(e”t(ô•›Ù’'äB„<¢ûD0@†”FÄŠ0 Ä È” ¦ç@[¸ÃÅa_•°7W]œûj,Â[Ã~m~ÓüârÑa·OÖ nD¢-\”¹kø°Ù0Ve6¯‡e’™wòtnÈs©d€Oþ-o⬠þ@áWIÖb°GqYxbçäaµïßê]ºÞÈì&‚ccÉÌ!8ì—?¸”íœðƧZÙ+&sÄhí˜9ù(Ç­?mì[½ 8L ci ET:”®õ &0”È&’½CÒä€cdq·¥£é¤Ý‡É™ÍÇÖç½=÷3)`:0»$Â`<3›i¾ésZµ è¾ýá:ÅABÚÂx¶—ͽUã0È¡»/(5—Z±óÄ›°º+55 €C"5Pn‰­DXå&g„k‚‡[yaׂŠ© ¬]ë¬#\8áîž#ˆ‹Áºë. ”Lw5PêIU&TH'Vf·å!P|yì1Xü@ŒN“éÝ£²¿X-AÒŒˆËΪ ™d@l+l%v\ÂL¾žoÍ3®”tg|6ð'‘9ŠQ”&HÞ/:ŒzØÈX…G†7àÙ`}1?r&9°9{>\÷çÐæ7þ686^A-„©SÚåÜ\bæ#ÐØpܥŋC5tôIÓ±t¼L6úA6 Ë ¦¸ŨÏ×Ôµù@0®œ¦»•¡¡¢Lå'ŽV†Æûe„€ŒÅh¥bòM?¤jD]à“”tCK¤1wi¾fÑoKér=®`ÓêÝióŸ~,tŒ7;µ&évãÌáP¢ì¡’ƒD(„¸oTh-ˆ 7¯÷“;u}#ŠþC¸);ü.¶ ì1N˜à®á4©²ç»¬uAÂþ=üêÔxoïîÞÉß©¿ÿV÷оÆèÄvœš ‰"Ø „xÈÑà]ÒÅ `€c 0 €G{äæ1ÚÁx¦Rhee¥ ¨K {Û6˜Hûýtz×ÎöcË÷àÀ!à~a XvwÙ–‚‘Tok+=d(âmÝSüäJJ¸èa‹LMwâ…†ƒŠ}A½½TdPU‡‘½BQ 0H#0Áò h @Æ"°‹bÔÊÎLú´= ¿0j)3ØÐÝRb;.B@r , 2ÿêíÞcÇa„óðgƒ{à‰™òžÃ^ÖY.W°Hç¹²ÎD$LAA 60S@‰B€Še¹yÛ ‘:¦s°ˆ½q€Ã!“9«£,• ‚dE²ØwáÙhéž>zFöõ—ú··áòöŠGl #Ø;TZïjɤSZË9ø€¹k|`ŒZ¨xžäP”c¸èj¥Ò´>*c>‚¢â²$TˆþH –6ìÍ¥ÜjΉC„ŒpÚhäuO«NÛŠÂU{¸Y*¼E‡¾CtÛ‰@€XP` ;ÂÜîB·î¤çðÁl•}áBFEX½vÉK`U0çhçyîÿó屡ÿw?Ûxs©«0ö³–¬Vnçà2®ª@Ô]ÖÀ PI[Cî¨;’rOéÂQg ÿäk区Ë7‹×>p+ á·Ö«ß0ÑÎÆúý{Ù©ûkµjÏ@¨â•¨Ó±Gg-˜¢¥]Îð(›50_hɘp.Çû(œµa#T:aSÐ9FáP)k¦?»Ô9{¢2ì ’Îò‰³š^t¯t\’ÝØ+kzP ¢RP¢ùDXr‚‰ TÒ €-vŠ&åÈä¢Ìh¯U$•2áY*õ݆΀xÞÞÝ:o‡¦œ!Ö!«œ—áþ|~+[¤´ñ¨Û¡õZ³Û+Õ¨Ð%Ïvušî½Î7'+¤ò²¤¤ž7Ü–-ËËqžÜZÂsÝ`ߨS2rÊ?„Z™ííÑ*ĦñÒ»… 4ìwÖMĵµÖ2R"ö€ß„šÑœˆN#`p‡Ò”Dˆž¦Jeœ²P›¸ìc¦@ÏCUQQ?AKS;Þú(ÿèE½ÐªèÐÓ5ûìýôüA9ïÿSÜ".ÀŽe¹ÂѨµÈhKl\fR(±T€Ït5Nò;œ~"àÕN³Qsù#ûÈ>3 ô?ýÍFKPb pzs{ÐÛž¾ï|ÕZu¯^î­ôV,@h‹ÈC)l¡£ÈwÿÇoìÆªøË·Å+³©°P#£¯»ÊÐfžƒ³ÀëA!¸—öpŒJPVÇNxc’S&t8€±ÜÉüÕP þμ|õ X™ó¿»Vý>ªLVV. 'ÏUvO§Ø gC2±”N,Lãh7r¤dV,ZÉRM@{ˆpd3ë$ø Z08‡"ö•›#¨Ô+ñ¶|þÁùcåÝSç=ˆ"å©1‹ýàヨE<¡Õ(´ƒ.&HyVÇ¢FÙºbØ •ó\rŠãvÞ­T1ï«r£”Úõ€ã`ß’vBˆbËh¬¥}?œwæ,d?Üš ÇŠ¬í°×ìk?ˆ)¶i‹€`R£5Ò¯ †ëõ4SaD$‚5Ñ' gº±B¯·í©áêH OΨFð¸Uò ‘Ÿ¿ßJ)å¥`І@H°`Ñyâ˜þÕ›£­nod|'«¬—Æ:5O7¢`¹$\‰–)“"—bÀ4oEôSazÆ&p` ÚÄ%;ÜEüz5&üb?á~þÿ¢À¡>Q/jµáSZ Açj~E÷í/âõ‰QR<Š‹‹SúãMÜÓîJ(Îd°3ðjœ¢Ì}ѽÂ#Ÿ÷ô¼•ž±ã„ K;xƒÛ¶âe¬ï™REVb‘P3Ãpè\zp¼”l5³íA1×5wZ¥×>´œT˜˜ J-"§µ=éÊœžÖð:U[‰ýl˜ègppÃQåf¬„a+SV‹á}öaÕ!•ëËÑ»³ÞGwÌÕµ\øRˆÐXîŠÌÂ&2N©¹O5˜‹†ŒXo@îRž¨j$FíÒtT:÷ ‡Q¦)N"'¨M±èÌÀU¥a §UrWZº±7y¬¼_¾_z nÏV¯­:q#•hÂWÄAÔ㨘æá´:~¼|ô:{F}õ“CaÉ_ºÕ’~ñÑÒS©W„ó—Ö¶ïehÊNìÒ¿x%\ÚÔ‚ oõºç‚—_iufóÔ°ÇÔ7^(Ö{cJ«BóÄj×Îý*G›Á‰éê'Î@u¨üú;Í0ÁO?Vþâ§Iy"ß3Žï,¥(‹jfÚ“Q‰èˆØ~RkÆÑí¥dq¶~óCymSl ÿ'/~(hÍÉ’i s¿b¢ŠN' KCBŠŒ NK05Ë$±þ!íß`‰ÀA9É€Œ‚ß1ùGÀ`d¸·ÉzÖ€ÃÄ60ä¬nzƒ,Î`»æy@BìXòæÓíå¾$û¼`/3#ÊŒs±“Ø¿‡Ó¦5WÏúi {tqy–o0`¸4OS±ÐáÚ¶ÙvÕ^Êî-¢Šm=uÈüæ'Ý ]Qar–D,OÄÎÆè;׳¾ÖÚc"¿KìMi ‚?ƒè4ÉÖmn¥ÝAHMÑ‘w™ÙÖÌÙàŸ=3D¢vV‚„NM°ƒ§ü£ãVèvkÐÊàÖ–¾¹½ö¡K5á, dѺ'§´:¯Ë3 ¦-¼‰UhƒÄ+F¨~ƱãÎVn0ðñ&[¹¥ZE uê¢î£êÇ+å·®›‹æÆ¦ÌI† âãéŽÉg—„³Ú ‡11V]>ê‚U°rJsA ¸!\N-^%J;}ÛǰQ`‡œ5ÜQ§œQëÆt D^QÉ˾í[\½ºÐë$y_„¿x#~ý%wíNíêÖ 7¨[Å'|9bTµÉéaçOë£'¢#‡Ð‰ûÄWžba¸q»kqþ…ëŸ8øEcñVs61dzŸzé¥òÝ-­ÑÐF§sòŒ»ñ"̽ÖiÝÉ ÃÆõs¹ÚªÃ/>Plöé_ X«<]g/ L/_ëF}òØÃå/=«†wÈ]{‚‰©øˆ±ëH±ˆr†q/§ÞнµæÊ\pýqs[7óè…Z/¾W8UtZsCØO …}T*™xÆð¬íDFá¼´ŠÈ«D ûmôvrEƒ•%xÈùQbgƒ.œ5w6XO3p†Û)äZ¬¤ã¼?Ha³Sn/Fº\¼ÇÄŽíÃýLLH²Ë’ûCpÏ3ëªzhëÏ*9ä LG@­3e¼h ªB[ÝbËú?ý°˜]4—>±ß|å9xü·»¤Œàq‰§I>Qyûfšhf<{HÒaÃ{Ø^5j@ô§ˆ"¿†Ý^ žGvJÜuù#<_P„OŸp÷ŸÁ/¼5ô7¿ÄýÜ¿u—otM5âhìÛésê]»!n-Àÿ3ª47]#Œׂ$Å`OÿðAtñ°Ü[÷"2ð#0z¦Û/5[òÊzúúú³ëüÚ\ÑîÕêçÌnÁ…T ê$rem«N¥Ö­ è•ðtŸ–fJ«z‡ÅÉçf̽bv ¶Á’Cî.ØA[âôð—àOžð5஡Këåï¼&Ÿ<~,íõÍ­m¿#e³Dwæ*TFp8_¸NUŒÛ'ydRm?)£{)v¾÷ä1ùÌIñËkßø•h¥py‰,w∻'NØFaùÃÓ»+X9ÂLZ;.£ÃU¾÷Kî`àuÝ4/KqŠmæ"cOi7ãuÎ2ÀÄP¿2J`Ö€0VÑìüù7øË×åõn³m:q0V›ˆZGÆâ‡ö”Ÿ9)/îþ`³@´³÷ø€š >ó¤ßØ)í>¾þµVÞôg0a|_K„ë`ra0w JüªÖ-'±9UÃØ¦Úé4òYÞ'÷î”Wš ”í“\ ˆ\°«dKU¹Ô·µä>-ž:§Ž•õ¸,‡÷è_om¶IÁú’;xܾý“ÖîU:–²…4÷§‡_øq3 6x»Í÷ík_ÛžQÕqç÷mOO¼ð²D¶;ê »•Ÿ8:zçåΡù0ìuò¢q¼ô·?e-$ÆZKŠãûPÑôŠ®%ù¯=W}x&}ø>ü¡¡÷Ö²‘*4("2ÄårÊ*XmWçæ’nÏRÔðT{G„¨_]Ó] ´*9{Šc‹½TâL«—VA¶lRÜRÃF¦uýœ©žöÊ{ÂN“–k©½Nœ5Ì‚æ˜üÞƒ¥‹‡Š½ DÚ^ ¬ÞÕì«vG¼·R¼q¼ú>½.·;>EJ8]¨â´ÃY׺äLb`  @„²3ÚtãØÈ­Ãrß³»Ð|v'“=#%üμNZðø‰¡¯>|œ¾ñóuû.ª2ï­íî…§Æ—7è*ªÜ[É_üÕ÷O,¯mF„„Õo^5 Àºwtƒüñk­'ø¼Ò€ýG¼¿Ñék8 ô8…õ7®’ã ×õó„àðð/n®Ï®ÈªO4wæH·‹Þù Ý׬&ÞÂùg> wfKb~ÛspáÁ҉ݽù%z/º~·Ý_„!”ô ì ŠQª§yÞ-{‚YH´ÃÌ’Ë¢¨XSÅ(,¬ï{WÉÓÚÆ.㘲]æè^y+Õe¾<æºÛ±Oœ§œdmwVè‘ xö.9q°>>êŽE!Ë"íŽxs°ÔêflbÕM…¤¢APA^Ɉ¬CvÆuL{"œô‹wùê±gG>{ˆ5xòüÎx¼UZżÐm?(@ÀÄD°šµfß7-HpMÓñ#‡Õ#جŸþîc‹ÛéåUv3#*RÇ)+È –1*;¹ö-ý b. ±@èÑÙ¯=PÚn Î>Fïvå^ÓyD…<3lùÚð$ #2²Š•qP9ø¸æ‰JíSp÷§½¯“—^]=…È™¿•‡ÑvÊXëlÝúˆ¢6ˉ.©G±°¼?<êUKµ©†:8áG| {“ÛiT÷Ô1»p9ÕØ"N•”4t‘¢ãÞÁ=çf¤áÅ™Û7=ðÐrzœƒÒƒ¤9–] ,è’\:¨pSÀôÛ<ëV"—ñ¢”ë¼I™ù#»Š3»K{ýîé½°¸­ý0Ì's‡êS÷Åoþ0ÆïA…ÓK«êþO“•EbÁÔ_Ü(~~×÷/¬·*”–Co~ˆÛÂŒ ¾I‰yñµÎc'«/÷#G‚Ÿ¾ÑŽMa)Än´ ›¯`÷6Ú r v4~u=»r3Ž"—³w¡}š½ÿ¶^­iH_áÛÏ~îÜöûó1\x ¸ÿ@¼½Þ\•ѕۢ½èj(Î2HæA(pÊúùÖXÒBRh `P¹.‘¨aIçCeú®yLä=b=ÂÈ8ø ñó„òÆú¨îl$¾…PApÂí(«SússüôÁÒȈÉûK@£•6Žó©ÕÍî|;FÀL%€ èã*Pߢ”¼{cóTí¬!(Ô/ùúÌÓ£Ï÷*¤õÆt~`»Ög:× f™30¼£¶Rôÿë%ÙkB¯‚°°’€|ä¨xúQ—·ãß¶× Ïpd)ѦØ72ôÙ‡+Ÿ;¡Ž *5á;Û¨«÷ŸÏW~ź7Ò$ÞUpoN†O,Tœc¶ðîâçfº}ä$½ñ¦>ÒªœŠÈ>m3’œù’·ïX2q6#áÖl¬º-”r~ÍñiÁ+ÜôsÉå*>rB½ÿÖ¹`tا±pT6jðÆûºÕôQ~çF|ä0îleê¼WÁ…—½v×ns'´ÎŠæœºï<%“¥¸Ñßw\¼û¤FlsÃdi¦­NñfžŠ¦ÏEÛkïJjm¦ë‰×vMüÈ£0¨ŠÒÞ©Ò°~õ§F·)J¨j°£aû›jºW޶GŒWâßø–ÅE9ó‘ Ä…ÓÜ—&ëúG÷£ç.‚·ƒú§©Ì$ Rà)ZÊ2G@KB ì0vÙÉÏ4Ž~Šì:ÐEzýCyÚ5ŽEt—@™NöîsFGÓÞàÎ6²Làšp8ò1í÷ñŸûV²ý1ÈôÀY¹Ú9&ÛŸ9ļ‘Êüfx«=8ä1?†EŒðÇ)¦žÁ}d0qg-ë#Ï~Æ;s,"ÅÔöí_OoaH¨l¤ )bÝËèvr Ѡ输ê|¦D;Cl'IûÍ»ÄF6íPšâåÂÝ ºíá–.o‚û°š¼*ÄÕÜï;^ãØ¸ùgŸP¡ZM«X}âÔðFšÍn”ˆÎ»N37^œÐNÓhTw˜QŸfé‹xtˆ“{÷‘é=Ñv ÉFqá-ªŒ²øm1”ÕÃöv*âÈ" ùþÑèË–>{­jCªJq­V\{ÉÎþDö¯‹<ò>üîÉ}ßIœ=Ç\š¦vÅyÜ(Ü`åõ|_·zb#@ú*>x2>Añp)žKuaç´UŸNLƒ,å4tR•#yü”wüBôÛ÷yõ]|pTL{o| š=gÁ‡7‹£‚ÞZÖ‘.âºÍˆyãžjq–¥Aƒ‹­»èä}>’¡äÀ ÷ÞK®D[PåIœá–Ú”ìyÌ} ê2{ùÝ9èÙ¡ŒÊÖèmóУnPÉÃÝ“Ixåy©¬d¬FÆ¥c!V‰ngê·’DÑŸ7£Ù°äYàOÜ4òBl³ã»ëŸ{ˆ°r¬:™’"לFq&ÖŒäXS_ê 04%SíÁO6Ž}6lŒ‹+ú04öú°³ )ìÙ xÀF½äÞK›²Î`ÑxG\»L³CŠo«{Wl]Éâ º xQ™ldçÇûÇ¡R½ÒÜ n÷RG(0ŸÆádS°ëÌf˜ú&Pp´8©u»€b'{ô CÇ÷Gz)Åj- ’+bÎ:ÍÊRSm]/Î’‚lwˆR¾W!¬ pú¨ü_ž«àíž´*íÝãV¶Â5]Šs½*ø5š¶³­C²Œä6«ÄÒSQRs¥Ï–ðù†Óé÷ß©nµ‹CSÕºÜ:t/÷ÜúÇQÌIåß>—~»½"îkå(7Õ1Ö?†á.ãš_ðW–ým5R\Ž™šÑ{Ï…Á.U;GØ™âü‘ñ«ƒts`—‰¡À˜œ<¼+˜oo?ÿnzk½ª‘ŠFüIÀéVøþw„‹“@C» F OˆÏ;³!§ÖA,@«¥G²È:Ô­·ò[kþ§ƒÈY'ZT:ív7&'K}>ûìCß9ѽÔt­ è^<»N{{ä+oûQë 5ƒÜ]›×ç*Çí|¶‚Ž?¶ûµ+™‰5-HŸË‘ÀÑVÒèw..¿rÕûhASl¤dš%”¸‘»+É“È*ÿüwéÀ„…/{ØéEHÄDL”Ñžà¥é_þÙnlB»‚ŠC…Až±={jäƒBÚ’»}÷ûBi¯Y‰¹.²þÌ‘èão…áÇÉöUŒxÏwÀ‚óÌÂþ}^ «ÙI]½b²:3ØÙŒZ•yrò@N%ô“‘Õ•|Y$bˆ÷‡Hu·®OG›‰XØB÷ñȶ­h·„a!Ôh=Q•%76½8¨…jED‡‡£ÐÏûaåãY÷_^¨þÍ‹}ió£ScíMn‚Ž ]C 4EþD=<ÞŸ8%cr䀷ÂuiöL¨V`zsµ˜†Æ¬ÆRnðe3Ll7¤âà.ö¿qøÑ=ù‹óÐTéÄÁü¿Ær™„ìå«ínTíO3¦ÕjC˾Wk¦ÁM°l‹–àëeª‰äRöýÇOM˜òàÏŸçM!ÏN eÍ݇øf¬n…:è—põ߉?÷ _ÐÅæ† ƒñÇ 8äQØg!kwýÕ¥`CƹVwÁæqê¤ç3;Î2u"9t¦¾Ù-Öúf5Â*ÑÔî90ÜÛnÿìrñá\׆ɘOý.}åŠ9\Â`ÇÈRÞ½wå²SZŸ#`$îÕ8pÐ< ªÝ¢è‘ é³UÙs!:qĬ™½òž¾´Ý#©‚ªµM0Fb×pmòP²–úÀkŸ~0úüÙ­××Õ½o£êªX^ö’ÝÅ›Wü~hÓEY €»ó@ãÃï[v½X¹Nà¸úÌQÊÂÒÛwº}€ûî¯yjx+îiV Št€Ý]J{s8”—ú`YxgVͧ¹-÷ª`Ç`h—mI³¶Åî®y• Q±pϘmŒAjÜŽ6ÕÚ¢.£ù ïŸâ›ë¹tËýå/†¾ùJ¶•ÇGfƺM\_ UE,œ&O~¦¡j8ÛmK;ÐlÙÝ”wÍÈM/‰çKóIH mÅ*ßÔBõl¹ì2‡Õ‘åõ©ÊƒGÒ7—DdpjŸú£OÛ‘DŠ{íÚàõËìÄ <|6Ä}±Ò bçˆ¯æ£ ¤I*! ½õôéÝü>é=pŸn¥6â¶:ÅúÕÈû·³Â³33ø³GƒÅ{l¾Mk•äwµ»ÇŠ÷×Ìì`oH»ø0•S¬—ìº{Ó+æ\xغÛ'­bbj Μôw4dHŒÅQÿ#5Û̺¼!¼õGÏ%_:[ÊwÎ]^¦7oeÓG ëUçVòm'μv»ÝIÒRY¾í3&qªßþUqy¶rlÚÝwJÕwuÆÚýGÌÁ#TpôÆMﯿ[¹²n¸Ø1ç ÒÓ:½pÀ~ú¡¡Çh훈.½SXiï.$¥ÉHlävOVõz¦ 2¾²œ”·cS ,ØêdÏ~}úâþ"5îç¯%…†EF‘޲C¼wzí9²—óûýD«–vãDª"C¥“†.¯èåEœQº¥$A@)œªq²µ¤.ž ¾ÿK¾p+Ît°hͰ7Úw©²vÐõ.—gå åýЊ”hÈÛ9kD½ .M”ñíõÝ!‹<˜Û‘øó¿Î³lÜä7ŸqžéßwxŠðA'c6AÀy$Ñjµ5ñÖ¡6fdˆNÌ÷œ€CGƒ#Ç{öÙÞûÅ7±úHè6ެ‰pmÕ—mÁ´ƒGNûóór‰ÀÑ'ýÒÎîË·àï~e~ù¾Ù…cîŸ=+ŽŒ¾†ô”Oñ„–ÃçéžF1]–õqjÚÑÊ•èlìšr·éÖ´}/Þ*è=Hî«%«õ­'Žã_8Ú™zù–J’ðÁqö¿}-ؾxÓþ—_éŸ_«<|¸?¹‡‹¬ÿйêÃS•l ˆÉ¬aØíÿÄtï<ïØA\+%#Q}õýÁÝÄ ¤#5£ÖÿÇOÇ_:+º²Âß³·nyPK÷ìæºÎ.Ùj}¨üÎÝîVÌU^ì´åØ н-\SÞæ{§Ñ©ãrÇÎlç!:u²Ø}Ô|pGÿõ*wÖªmÓ1œRCBðª£õsõç~âöž‰Òû¯eJÙÙù^mgÔÝTxVí +k(΂zÅ·zs=‡*‡ðÚfúÜoì½x°paðý_vR=Nñ®rC¼wºí.>¼‡ýíâÌ¢me, cE¦À£ŒJ#”]\……Ü'Ð2‚ Îˬ®ytu¾ÿàÅàG/ãÅÛY_kÆ«óêRÌQ³ï.ìŸþÄ…Aåbé;/Ä[M©N--¹Ð•&Ë‘YŒ(MhAj¶]¶ñ­N7 Xüæ§£‡Î¯:TCA‘&<϶ù¸£ÔòÖÈâ±aرßì;펜$‡u2i‹¿øwQú‘0]RS¶ ÕR_0µ`ž95voU.qä±°´¯ùÞüÅóáO>Vk}rþü/Ϫ3GÒngÚ¡†BÔAljÇéž‘bGEO0Û/ߺ^ÌlH{µæxûž¿ðäœ n“á QKå}ú«dÕéŸßЉ:ßpÿëW¦C/ÜMþãÏàÅk¥ÇN&3û]’¾°¯7âÊ:ÎXYò/~¯òÄCé§NO\Ø‹îýì5>15\íÛÝ“ã·VÔí®˜[T—Þ¡ÿÖ'Y³©o®UD†nÜ oÏyqæ!]ø.{ZÈOïi›(·ËûœXbzÑw>®½r§˜Û.yCfÇ”š]M:—ÔÜÇv¬éxD>u!œfò‘ƒæÐŽrº¢—;ùÛ7ƒësldg|øArðhu¦‚þë¥$Pá\atÀà—nÆ×0Œâhì."E¤ ÞÎí»wìó?&oÝ!`:U?,s:½S=z1zîX¢á£»Âk·ô½9BB9ˆk×nʃ‰¤¿´Ž'/ºØË>¼©}jxê´!W–ävÜú÷«Ò•…‰ÔP‡Ø(&P'~Ñ*>^ºSÏI2n m-F‘Šø ¶ZõµuQÕ¶¡ ¨Â!EI½â² øwšlö£®¶•^¥:ÈqAZ±‹8&®¥þ¹ûåŸ~¯˜½'½ºŸe”B€K“lf16ŠoßÁðNÕÿöÏñFæp¹Àbt¸šíÚ­6šš†Õ'/šÉ)¿Ù  !x…í<¸|ÛÞ¾šƒ5#5(W+†“8“4«ÄwõLA‡9³X£×™‡¬„Hf0Fö·.±¾²ØÎŠ¿üõ㈸ü`ÝÿÃçØ?¼ÿÿÏ"Ùæ‡aæçMßxó­œPÈ9£:¢s÷L÷dÎ ‡ä”˜(i-Êk9ùèøxíݵÖÇ»ÒÊk‘")ÃäîIf:' (U¨œoÕßøæýA~þ†‡S›âÕ;4•¡Òµˆ¡Ý‰Jw¥‡Fau£ú«×ýèRûJ"Jg<ZuÆr|N#!Ù°GœLNY¥¶šV«yá`ÝüÓ«|¥ ‹ö÷ Gv¯]<=ž?Ç:Oª>s.}þŒwn"OøÅÇ;&ö`?¢Ã¥þ[;-ÞÜ"¼/2°ßxÒé´»3kÕN­,xoÝIä3¤^¨l•ÛT˜qG7béEÇZ×6­»SÑýF!€ñA5¿Òk^‚w£¦ÆV©ú£•q–=¶NïlÜ‹6"ññ]¸õ@ ï¡GOøÃÕöß][m×·gR¨ “#W6d}S ;öÊÅ Hâ8á×¦à•ŸÓ7ïqɰU;‚©‘ õÌ9÷ñ3Æq8p¢t뎙yÀPu{•ÛSfà묈힮†¬¨¯ÞŠjAMaªbKö&Ìo¶¿øŒó‹ËÍ¥ÙA‰Xa‹skŠ9B¸”4â›+JµiÏjíí –TN}È:qmq-HEÔ4DäJƒbd¨äôB>hÓÙëq&ü¦WN•ßÓ)sŒ¯Æ<áü)õo–ß¾§m/xÎ@ÈdÚKöp+•ÞÒ<Ø ê(½òy³ãc7óT±âoïß6Ö\þü¹BeŒÆ&Æ„æ22˜}²@î^Õ¡Ñ]*2‰!šdõö]2šÃ°C(äXëÂæqZ@TkÄ•ý ÅáãÊ;Ê»–ÿÙOÈ[W»½Þñþûϳß8“ ú¶cÝϦL’ºŽéëÐøHB“ÉäÀ²º¼÷†Óù ½Ã&‘#g=íI{8Bùœ¶Òà!‡V¤^Ô" I/ï:-6uÇùp5¸0ÿã_C¿ºÃÿê•üƒ)g]úûúÒ?¸XsÛa^’¯ý*Ø¿«÷Ävt¿æ,zè(!ÿä)ÒŒ%7Êè8 ƒï€¦ZãA•F¸wïŠiؤÙݵò{7{ØÈ¢OõÕµB”ë ¦òƒ˜^@•eüªe[¶2 Y ÿŒŠ)É® QÕpº<Ô^KffSÔVÚ:Y@”nRNzl§~èu½ŽZŒÆGå¶Ú±Òîmt*·nëùÔ×ïa›ÿð 6Vù4Èlr†d“õ¤q””ŽX‰/>e|Ãî/áW?¿zgÇÔQ,w'8ïëpþ›/”¿ø¢*WÙå_æÁ'k³MQÎÖ¬¼:/·8ä LoÞë¾ðâÁý§Eÿ¡àãër}ÃXR(Iq¶Ü-ì,šKùFÌ®²N£kŒ±EÂ2™‰0LE/ ’X¦2Í5c%,C6 zlܯ8Ý8‹À‘Ò`` 5Æ7D96çÚ-mˆ­{^!³q%W¼Dº9 æ‹37”ë83‘T˜#0.s¾}¶<~ˆú»Gþ¿»Þä4¥b+×’vö.åëüÞOD}ÍÎlÄ?å?{ µOnD‚ G%¡Ñ˜êÛ˃WîVZI1p†jY}ȹ1±"B¥`KØ´Y>e­>œ ûÄ^o.¯¾kßþ¸´šU5Ú:ºw÷×k ‹nêl¥ð¦7³¹F”ƒCr¾{~"¶ëS¯ »®yÕ›<ù;¥oSï>Ò5\yMꛨÿšLñ=n©cå&Ö!qº‰½ºåßoçÅ‘üÙ£•ÿç÷ÛÌT7!Ö´Šäsç²3…8ró?+ÐRŸ/¥í^lÒ¤UÝ_Sã^Ò+™iJ‰šÔþø3}¡wú ´QKó¥9h(ÓpèÕï³ÙöãÇvmèìƒ9tsµ2Áê1Iá¢íÿ0ï½béT§mZFÅ?§âޢׄ,*¸@ûV·ycAÄ$¼!g]W"fFÑäø.8{ÐïvhdöÛ£#¶I«kºÒqfn˹EQé#V²ßÎÒ¤À“Aû˜»¨íâi©<±^çŸ2TãÙ%óó²×Þ¾5 K|™Ä¥žLë¹Âo~QMô;×ß+¶ò Z3êêB¾žAŠòÜ:×oÅÏ~e÷ÎS°ÿTå·:kmÈU2‰o¦…ñ’m …^nV[ n}a) ¼ˆƒH·] 形ߋ¸2$–™TÆEŠŒz(ïDÃåNÜKK)aƒ°±¸‚ʼH!Í3ëlˆv™…Ä/EB÷ÑžvÑýŧWLiÀ[mùˆDyJtË/µxáËÎèî>ú¿ÿx©Cæñõ4M'wy¬'§œ–îÓ{›É£O^xFеK·b‰,V[étwièÖta¹³¿¼¯·’,ƒŒšI¹Üt/ÍþöRô£köµ+úãk½•…¾\äNËœ0.Ïez1.&ÂŽpòž¬wˆce¹ñ½)‘c œ$uÇŽxÒÏáž±.ÊSñ"¼q=æ¬ìæ® 2©²ýúí/Öâ ýŸß4—ïø/t.Œ#ãçß{wèæƒ­O0í˜?ý8»¶Ðwî¤õÚRËâWƒå¤70jí)?˜u66R„¼¸–8—f×k~Þíbj¦<³ŠjûaeÁï½Â4hÚQ Þ¢áUí§Ä•ŽwB¦dnŽÖçód^¯[ÿ娬m½Fõ½­ï^¶?ºn~ö™ywªomÃwQÂêRr³Þ»ÙûèÏ½Š²Dèù˜Ë ÚÙ0–ùå»6?PíºÑßï^bM‰Q”jѧ¯/ýÒ§ÄØfìÏdõ ß­$ë¯Á.ž 2$«í¡µMF1£JŒöáÒÝ+«œ/[œÿê—º¡uK› ©hª':Ùj•+‘ml3êiªš,8Ö®1Bõñ[6­V!¤±!ådŽRU?³~ãל¡ÁÖ'Ÿæj)¬°Ö·•î1=xdwô_•Wné4•C“ÇCq&ÏzH©6¾×Áb’§‚¼$ËÁAD‹Ü×îÑCH ç?ý圓í R¤-RôðL˜·ÈǤÞ2¥± û³îÿºE }ä˜÷øÔŒìLG:¤Ëp´µi?»Ì5¹_¤.Ðù5ÍPÐB– ·¹H´Ö£ ½tÅþrÊle,ƒ<‰¤YïÙ¦‹?¾š½úüüªüàj¶±RÍD† <P¦¦¶”$ qé>›iÈ> ÝU„û¸+AL©œÖTÀNPî)²¢u4õ„rÀÈ´ŸÉ7nwbÞçË„–­T|—ëÿÆË8búÿñKúñM¸x°ÿ‘É®õ¿û„NÝOŸ?£ÉO’Ô®Þ*žÞÝ+é©ÅÞÔº³´%æÖüç÷¥‚%7燈@ß<§þè© ¡É­ÅBÉ`¢Ç*ùH€¶¨EÕ:°mbRÍ©!ÛHqm8€öÃSYw„0Š˜°|Á)|ßÄI‰…]ƒ­T†ãŠïîª{£E[0½ÑŠ3èe>ÓãÕ HdÍ•M6(²˜`¢ÁN28®J±ŽûúNñÂÜŠüøš]_QLIa«"'Ž©_¼ð¥óªo ½ý1ÞèÄD훲\ð ùÊL!­²‘ÓÞ'Wº¹$IjK=7•@Ä0d–,7’íT-¦Jû¾ZÑE׊ޡ ò›/âKwi’sLÂKnɸââ1ôè^=>R½tc•fü<;àz"N/>ê>}¬¿¯XíétvN—\&ˆ;XpêÒñÃÆ~½²¯?muõÍ[+ 53ÛÜ7ÌHîÒðŸ|½”$[i±4 YǵU0q9pÊï|˜7²òßh‹ Cè/¸õÚ'Îëöz¹•ÔJÏ´ç¶½Ÿü5§.iŒŸ{ŠÙoì®Qæ¶ßŒW®Mm¡ÌËIž+=Zp Q=ž8Ð?¸©ÎlÙw´C‡Ê¬–;Äiüá7Šû³í¶½»õòh3•ÜdXf$3Áï}ED\ÍmkéVÑû(pŒï’Ô%õŠ¿x»³ÁÒ妔ÈÔˆ¢+â^ïÂÃ,ZìE5÷¹­íà›iEŽv‹…çžÓ§wé]“ õ`Ķoã»w½åžÅÒ±óU=(:K¢fŠ œmhžk¸ÄáàxØ­Ó×Wë#r¼(GB[sã×ŒÕ ƒƒ¾WÍ*¦IB¹£JŽÐêaë¤b—}B{*›f¡P¹Ýa–i”#é1;`è$&͉}`Z5kœe¥§. ùrʉZ`ÜPÉ ÙëüÎaxö˜•N'Ž¡–b"3·²ºÊ=B‡GT»ù/Æ×8 äkf€ ß*qÛqsn#–¹u bbNïÏD¢G®|–ÛÉzé@#ÍD¥õ ©Ó~=;u¤üÜový$ÚãiÐU½˜X ¨-’l³—­|ÀrikØêF/cRó)F*õ<86Á.œ V{æ•×Ò½ _3jÜëïæ-ÎÌá}áÇŸxkÏ^¬þâ5H³6îB²3¤»«â‡ÿvM8úš/¹K1-ÊóuÏxæÙÚÊÚöô÷èÑâ/ïogÍx‡-lªíýÚ_‡ä‹Ï×OŸ7Wûîol“ S¬± ˆé2‹k!ÛnÇo¢"ç$j‚—– C{È­^N_Ùßù<Ž[×î]¾¾Ñb!ö£bRCIÔLu{jd}ºóôiúØç½+êÒÈÒ:Ž[q'‚™Ý>p·½´œóaÀZju_Yþ«ßBãÅ‘Œ !ÆûC­÷Ûj‹D^±Ê{ç®ó§o÷:J,Ë2Õ¦ð)R'eµÊÊ˰rSH†&öÚ¥%r⻜9ˆ1Õ-TbF¢ Ãimfæå Ç!sqööwÅçï®»ýdñÜößÿÿìýVX&*ÔM\(¾óm«{t;ȼ´äF͵ÆÉ›ïÕ¿ú¥u2ÜÌ…K)<˜Uÿ¯ïØñíþ7†¶î5ðÅóöà`ÆÿG´Ë}Î3%0:¢ÌY +Šß·^ò fe@R¨ErÒ¶þ0_?A  ýgܬg-I¤&$þƨzêyœC.8uyAyPb ¤¨¼‘1–Dý“m¹æõ¸bÈîQàI±é§÷ùÊj+  @œÞÊÛ[÷¢ž›ëN®-£«Ë=ìá¼]$ü…Ç ´QI>hvøÅ½Y^ÔÍ f65êk/•ùm Ý!¢ rè±ÁOo§$=ì8…jù­ˆ—Ã|~%ßp¬±¦©’ç*žOo/vwíôoX-@ÜsQ*¤(@©#Ì—_œ¬•ÑÆ*WÂ:ZÐ\œS*3psuhŸð†á¯~ŒoÞÉŠÚ&NYVʃþ¾¸ÖïÜÿ»n5—+Sfßò¹g³ýF×fu+êÒ@Vo,ô4 JÙa ÐJ„æDž9/=vÙÿG£w‡K‡Ùu피|£ÿÇ/Ù÷ßÍú¸pÝžËC0Š”P§MAçc‹?tÍŠJ¥°Ö”\ƒØö“@x«Ò¿kÜãóŽw" ÇKᜒû± H°­¼0^f¯Þ [éï=;ùÆåü£ULŠIʵï˜_{B% úË×â-äØ\<ìÅšýÙ§Q^p·NLÀξú¯.#a¸!b9ÁV—f·Ú™î÷ñx/¶ë(­”ŸÊŸÌñ(}óëZݱA¢hðÕ. HûÜØÈYÅ8:aΈŒú­ú”±(œ!DŸxÈá¾q“ßÛ„ý¤ìèµ°#—nNÜýisõ#® A¡†ÿì§Ød™t¤cðCOaÿÚ¶½{TE¹ÁhÍÿúWûŸ|*¡vÿ'´*øÚ4-ñ··Xk+h°Äƒ´_è…íh«S8ñ˜ÙjÈKpEh,¤{؈Ps‚hìñÃîcg'>½Û¶D¸Ø ƒÕ;2æšÒŧ³õ->î(9×ç#·\X—QÑÉŸ¾PZýâÃv2Wô÷jQâÛ›>B2·è›/ä·¥*¡®[!ö³Â˜<ö ‡+˘£™Â»&Á÷ßW7.õ˜ŒÉ9$÷ûjÑxͼ…9Y¼#'÷…Ç/Æ»÷{«3:J)fšªÂÔl2·$XêîAX0:Ö*ŽuÐì%ÏóÖÍÇ×î]•=Æñz*˾\è¿ù¹ùÞ‡Y_Ñ^|¤xg:*€ÒºP¦þaÝêØÎMÞ³¬4„à€QuˆÇ}é7¬?ƒ`ÎÊuìW¥>—‘Mª™µ9¬çÅ>×|÷VkaCÿÎ3C?y_¾³˜@!3éAúüÃVåâ¯ºŽ¼øða—œÝƒÞºf XmkeuáüÞÂ7šD`Jõ®umÉ_°ªH²……¾Ÿßîdm;Zi9¬ä1Z©‹t(ð~Ù" $tÍš1 ¿Ëê›*Zž2êhCõŽmœžvxdè/–Ê6µnÙ þå—Ò—øw7 —Wôg÷äD‰îª)^€{ïWF7zý˜tC=Ãàæ]FÄ1Š"zæSAÚày*§>Ñ<ßÌ˽4Z'<) ©Púw/÷v8KG‚ùYp²^HjBg”†D7ÙØdmV\ZOÊ9ÑÈ‹áÒÔKwû¦”»'ÉŸ>Ó󨹵ìMhµ  ‚üìAWEÅ×ã•Ïòú™ý!Ó«+©¥P!c߸hÅGY_Êw‚ZÍ7?çÌÝ¥2®¢o¼ +÷]mûTdyô©¬9MÖb9Tò~ÿ›ææ5yx]»tÏœ¦úáõrl[†Ûs‡‡Lô¯o=™…®×O+½©Mž5áhiå†_zA~ñɬËíýë,pÅbˆ .I›×l^V¨MUZG—? 沜+¡ìÔªº–õ1±êìÐbU¢ÝçÃ-iÞ}“¬,ô*£æÔNou= èãšØpÛP1nHY´Uãé\¡¡éî5=’{ùÀ޳½a%>œÇÿë/ìg[ážáê¿zí/G?¿éI£,pA½]Zº.¼iB!+„°8?aÄo£â&Ï6‰‹„ÚćpUè¯PÓÈ»¶ÐtâS0²Q~õžl´ªÃ£ÑݔܾkMX©ÊŠ.N¾}¶ÿõíµM[qMÎɹC!WðöÇ—·2 ²޾y{]‹ÀZ;®œF…£hj1ël‹ý#ð—‚Õë«Ç}e•¯Fþ®GÐ'7ä¬J$Uô…ÇðŽje«ÉKCÎ[¢Ë•›¥¬ÍÜ>×Ó ½Vmnµ+ÎàîdÚÚ ˜å6ðŒÂüÂeÊ;ËÝÁÉçœV–ïÉâº0`êeô÷¿ª'w–¢lm³Èåw7Ĩ¿cŠ…*¡zZbxðÆƒæv¥^<Õ†ñ¿{gð?~Ð[ð£ä~¡œ¥¤ìbJo­ƒ«0ר5i¨öœ¸e‰– ÇYÆê3Ìç,PT+‚#E’Qy®”žœ¦C ÜNmI"ìêÄϪ4£qÖMIÙ7ÈÿëKÙéIóÃ+bç„:06ôï~²ÙÓ‰È0cÕ9æõÛÖøe­K­. Ëy´Ñ’ÿúeö›ç¥#Ý[K2ë‰@è‚-†ÊÊË•|BNŒEÍ1a6rɹ¯3‹Á!‰ÜÃ?5ù" .!À}ÎUû1¿°ÇæŸI3«\ Ý'Žw/œ)‚JŸ9YuS¸ü€¼=•åÎÞCã-«-w5OÛui¶1•Ù%Lf}Q–enÜÊ Õþ® ô¥—ðS'×nxÝH¬µÒ™¨˜U÷³󃥉íáÓCo}ÐFa}•J¥b1D!˜Í6o®²›Nn#¤ ¶L“¢ÔžÇ÷/<­Óy]ÀC…íåy–.¥‚zéÙ}ÉM{°©G©Wíg_ª­®t³Ì™DçŸðÛ©xÐÒM{lx`"ªåó·êO}éÉ]:‰J…Šsê%Y¡âÍMû_ûh÷ rPqj]´}"Õãlj!–=rpóKxæRãxcx@g¸Púô3ÁsU°+óÕgƒ±B¸´U& ×nñf¢Šq›ëB˜ëXÝUh7ó€öm²­-.¡R \¤löðã%&’»›ýûžõZ<ûOßUsëy€ÕPüÖW`xDjí-7ÜRZ‚•H ¶³«;\ãñ¾˜ž¨ú ÎñÁCyy§ýÎ¥¡ÿýõ–H /ïÿôk>u:9Å–o¬Q‡g*ÒC2ãÍ8]…¤ÄÊ0¼éÚÏPrOµ@-ª/9ƒoƒ‡zÛÅE`ˆJÉdYGÃvªyî}u¿þ/?/.ì ?¹AFGÍî±ú_¾ÙîpƹÅþ±2&U1½)vúPqtcd˜ðm#M¿|vb|0¹7‡//Ã4F[ʹSüI2Ø7,^ø* ÔÂ}ûhBeHÐù¶UUì k,&Ôòq†wý Ϧ8¡þ/°NsÌM~plˆ2²¤Eëð^-ÓóäÖbã³;Á3á‘ÝùÎ "­é?]jéûl<à"nSÉU©<üøøsÉá~¨ÙòûŸV¶SEJ2ܹû Àcß0§óÍ(¼zIG\nknQ/ôz^¦Rß­}þ\ñ‹ùK÷´ÔÂGÆ·"X2÷àN5d¯ÿ¨›Ýއwíè;Ü]˜6¹;úäÙ³­v­nòJ+§í…éHm~*}é¥ñJØ#ÅáñÒ^)Y_ ×·¤R”º¥9ºÙU–RåÛµžœ›Áí¤«¤P¤;u‡YwW¸ãèxÿÁm‰eÁ/´¤¿ûÅ#ýéD®N‡›”ލÑ}Ýù{ÆZSÕ•'^Ö»ñÞ…Ÿ/o\ñüreMµ—¶]ŒßjjMÒºÒ¿ÿÕBÒ{¶!ºÊÔk…jœ5µå¾b>à3§àáSŠWßo¿‘w¤CêF‰jÕ|öö«Éظ-Žo·ò¨—c‡* n)¤·Þj^x1ÞwZMÈÿð]õáTÓÅ¥ßz¡ÿ¹óíÖf»'`=Òfß•nP ©*µÝô¤SÞŸ²º“žÊµµ€±uù‘+ù‚ãîÀîó‰ÝrøÃϸGÎzK 2‡ëIGbã,J Ÿ`ä[yåÕKI_ µºhºeeœeZíï º<¿º¤öT4uÛíÄ8اÍòÔøž¡dqѹ¼jRO„€©q²œDö-FÝg¿NwàhqÖž–Å’!g¿-yÓÈP¶ÈAr„˜ Ô9£õin#â¿nT‚ò­Tüðκï@Ò+çñÖéSYµF§à©åüòýüÅÒÄþ|çÉôŸÿL(^sMVÓÙ0Õm•%*{äéñ/<ïWNÝé÷:m¦ •té™)eª¥s¿Ö½xÆnDñÝëN'ɺmS ªQêg˜®?q¤ôÂé`þ^F˜q$óÁבFLè Ô¿ðÃ<šJ†vWövçf=DòÝ£pæŒî¤ÑâbÖA¤vÆž;بÌß‹?ÿùr¥ÒžPaÿHi/x–®.³­f¶èÍ¥YÒØæ9¦*0==7ƒÚQGi?`VµêŽkƒ]ÕÁ½•‘I’Gý}aãNþ;_Ø=^nÌva}NõS=êNn,Ìè\ø%ÀO}Qï4»_[_½ækê-äÕB€B•”*Tõ‡ß úCÿþª^ÒBëB­¿«¦ÌÓP:L˜‡NÑÇÏz½µ(?|Km( $+ÑÚÇÜ(óáÝG­F³)üдº6QJ›Òr=ö$>t"Ûå…Còúk~é^æû­§è—žL“ˆ÷òÂz®V¶‚;‹Û~X‹¬I~D{{”é'ö€Ã"BX)"71hÐÄÝeÑSR¤N>ÉŽŸ+­Í¡º(4DW+p1áŒHéÜ;3œ”‰|sª×ßO[ÎÌ:ž¨Ø¢Mz&) z?*9¸÷_}©Znþo¿‚®çc“C«÷N¯oßœV¾%ZÇ(U¦Bñæ´k¢{þiÕ©¥%£Ã÷¯6Eømžu@èvòlØÒŽæ9E‹T÷ôç(KA~llG£ã¼ßu~ñéÆO> ³ öžIS¬BÚ –¢äOþ£úüyø§á£ ¯……Vw?*Zæ¦Ü „»&ÆçûypuëÒ¿ëöMÔÅ—7dò­b7Æ”‚O® .ÝßüõŠ Y3åRà’VªÙXaldÊŠl• #{÷¯}û þÅ_—;yc­Gâ e  kˇ(úæê­û/ýuLð—o¤åAZ¢ê¡guã˜o£l°6üÚåv#jµ±W¼Yf…v»Eq¯7­ LWØèæ,1&C”œ¥tŠ1Q(½»ä:z  „.Ok àtH¡~g5ÛÜôíèßüê:ó‚=»s²‰½Ð¸nŸz4¿x½ñÿ¾5 ãÆZvèàÈÔLÖ c›f}ì7^r÷·×»¨)Ïf:ŽÛÔ lNµèÆc·zÞßþ|k3ëç°•"Á·Bf¹(Ï/åðàû£•µÒ³òÇÎ[·æ Ò´\€C›*Ù迵ÑþÆIøÞ˯~ˆ˜UÊŠ?¸/ÿìgF—`à€7 ±“v,|è‹Ìà—`71P¥]ÈBÃ3çóRÙÁ3ÆÀÑa¼±í§/>ïú ‡ÎUß³Év,'(ª„ÿûÓâÖ/‹K‹ à½à½¹æ¹‡á_¼›sµþ7­«íÙW…þ|µ4œþ7-oL'£¡æðïÞë¾9îÌÜÍD< ZáLç5Ï}ÎÔj»Ðù§×E³ OT.‹ 4~3ƒ„a`4²®¬È,R‹ÑóÔí¾BQ/G!œÊQ×ÿùGÍ×ß×"ÙlÏnT¬¡µLý‹¿Üøò#î·/ÂÏnwº¥áJ{}7â|‡°`êé/¨…Û«oþßÒá!_ÿFC… 7­ƒ¾~îÞMÈË•Ìay¶E(^'!i¾á8u_–2Ö‹£{n~«RûÛW»Q¯Ò–iÓ&T—wíáÉÊÖH ±«Ÿ-½ø_y¡£þâg”Ë%¯sá©þ•}Œtu¥ú‹²f–û•ñW´Z JÝV´l§)²¡1QÐÏèœ0̨6C@µH ä&SK ‹!Ò¿à8Ú¤A¡œ@7»¼¸uw•<49ºõ•ÕBÍ9¸K†¬¸ó ³ðióÙGÈSgÉOþÍÔN}™^Šì«Î.˜ŽÛu,ŒP¯ |奸Èd·ÕÄ’™ s-·¶¤è{a\X­“¤v{:ùÎÏ·Úq_¦»š@/$äYa«0÷—¾ ö­ðûúÊ+Χ·Cía[(ãxÑöÒ¾©ô›ÇÙwÞÞüéÇ!ð‹PöðåYxåcP¶À³È# #Љ-ଭá#á•x{–×8eÀHéSà°Xëe“}ÃŒtp°<ÚÞôš/~1üåëÜ]©|lã–TÄÁŒKdÅ«3zùm§³žÈÄÉ{îG«›'Âý²×Û,ý³ônu}%¨V¢/e##ÙõM6={žBÖêÌmé^Ï¡ç ,CV}1­±VI@Õx±"²hû®Hò¥ëˆr<#E}sVK`¾ Ä%»-Ÿ؇2Wຎƒ5çŽóí§Ç)³…$²´<·Ñ‹¹"’3בҽ·fæú—Wy¶•î?+eIªtYãׂo\ä­àæâ'Üp¥ÝÙ‡¬K©"ër[ÄE!I ]{sÎ_éµâD ]å ,‰Ñ‰v‰pxþéhs¦vóÁÖá³n&ìÊ–u”êƒç#n ®Ü´JöפûÇéÑ!»~i”·Ø{ïö®­ˆ÷fíWÓé›èÁ¢juã<•­f¦8D¹RV#˜— œ›¢ãñ‰ÈSC´­z6$n@æÜeBIc-plâR¸±¨U®HÁ€­®çjI èþOpÔÒŽÆŽEä–!GÂã0#§„êP8pAž(ö⌷ɃXû+ñ9pË7 M¥Øn%v~+ílæ@ü8ŽíÖ/T:+~°bæ¶äfjk¾ÿÒ`¨_Y……µ ÛmI i'_ÝÒÄu|Ò3†i|تÏ3Ÿªnoa 1êgenº­¢"É[ˆ¬! –ú 6ÕeŒb ššýJÜ)à÷yfŒC)-8&¿ýÌäþƒÃ퇗æ6»¹4šg.EF3«Áƒ²±.ÅZ4 ż§©6úÂ7ÃÏ=Úé­Õoý$9˜ß3)O÷ž>9psÙ¤¼ËJCÄðR^èyÎ<ݲ ¦ ŸFþ*άi5Aö˜ÁÐèY}r¬Gyœ{s휭§§œR¬ò†1ÀǺ—“•¦hmäÜò¤g­{x~ံ&øpV%)·•òX_›/¼óD|OfÊxÖ$‚ƒ5˜ºS=…õŽ*çdÌóÄR¶<­çµHÅCGê«ëÆmSF¼-•‚“<ªé?ï1bÑ31k>jÓ€r¥ãs;‹sq¢æ:_Ž}ù|úÄ~{þ xäÚÝïÝÏHžW±ìbXÜæa¯2BÊ ´g+×–hk:­ú2œÄ«÷sÕj†Qm2ÝÚêooEÛR:ƒÍ#D•s:P"öA2sßk{i/;¾c±Ó.o)s*ÁZŽbû4öï±81dìs„…ï+¹ªÀ8®2ÉC{KóIJ×:Ÿ{ùTþô>têhïâ´»ŽŒ˜¢1}˜µi´Ø°Åöà ›Ù¢ê+•6%[ŸÉ‡×÷ÓõÙ,j•:.Üe¶Û¥¬…Ú¹Lp–aÒNX‰±¶”FGï_]êdˆL°ÔÆzh±.;ñ»^eµÚ¸½òô ççùxÙ¹ø?°§TÙ?@vDÞ„¹rßÿá[x½“NßoÝ™5+Û}­†à=†¤ƒˆ¤„Ha™˜© È-&*íÂ)7•È”´Jr—ðÙŽÜ-í5I’»–¹Z†¢ŽSŒp`­ãPlä:waýЧ:h{ Ïl”¯Î5W³D»ïO¥ÍÜ© Ÿìî:7qz7™[”ÞËÇ«Ï<¾5ÿ#Ó¿n<0yÝ]éF¾*n ò „¯XÝÄçN:›mµÐHIÑ[ɉ"ab2,Ó~S(Œ.¬ÍÒ#q½7ù0ߘ ö¦X‰Ý¡jØÄèlÔÚ4ÕKùÎ>ôô#áùÉWŸ±ÏŸÌ¿z”¼øTŠÕ_¼²9¥òs;ð\Ãh–k V°]¸;  -Œ:H”A½Î6Z™ìIV)¨1wòsýÓ—›·nö-¿×¬,ëI/$9›ðCV`7±V9c–(Gy®lnøk òÖ½ÞÍyéŸøˆ„kŠß_Bz`#!Á :‡"@6ì©=¹yRÑǵì‚ýKª^ÑH»øLîÈfÔZÅ­e»0ôæÛu~Ç ej@ò ƒ0:ìéBÝ ×5AIŠ&ËêŸ<=2QÖ?›!wnÆãe2)ŒTóþmüÈÉ"˜˜½«&¨)Bo^gcûêÿýWh¬õü¬@}xǬ7èñó#0Ù.±‡Nï_mnÅ––)™¶ØÑRðµìİ??×£²@oJ³.Ò};Ü=E–Nõ†¬ÙŽÃ‘½Þù‡“¼PYM·NíA×/U~öiçÖø£ÉyÅ#éD¢¾ãqðXzûÒ˜&Õ M¤S[½M£ò²]Í8PiWõlÊX&{Ú­¤ºMQ©‹³XXª]»-p(¤D¬?3 Îu™²ÌɺÆlg‰[YËá"¡u£ɰ\rI f#ÒNóϦíÔU4³­Öˆl0ÒßXN?\üæÅvwÉíÞtM”+YÜ#:Ö½¾™Z­ëÒ+C0RŒ~çå¡ 'äÌÕK  T¥„  3Š’ÎK½¬‚äÞdäøàOß~òK!Œ·ÙNÎþ{¿×ZÞÌzâá4tŒó‹>¹¯`s|rÌî¥>­ÉT,´ƒÿõoZ3ôû*_8‡¯>°½\U˜é©A×+S÷ìq€ãÊhQ¡ðSÝ«Ì0¤w´n®EŸ¦ÍÏ„YLF¥ó³ÿGSnº[©ÌVm€ÙD[ƒú€q%”ÔZÈÑ{«Ùjnò„æ9W\"äoflj…æÚ16Ò ¥\×€¤5—Lá‰_PjÓ¨ïñ=a£‚>ìf4½aĪÓìwVºG ?Š‚3ž7ˆÅ ÈÆ”=ä8DM uÏ ¯(¬‘µÆŒ•Í?zz`oÑþì^ñÆÝÖþž4¶åÐŽ„”sýøñ¢šœ¾ßGžk¶çt\Û]ýo¿ê$ŠÞ]ìXå|<%–;òĹÜÏÍ€8~X¿ù‘ØLòœÚÔ”…I”£¬­èì$Ï<íÝQ[XéØÜTYØÓiÁ¾qz°"ó;þ¤ÓíåÞÄÞás¶\oǃ{ÈíËþû7’+SÙGëK³Rv…—àr¨¯)lë¢Ú˜zÚMésZ_—†6Y¬ò8vpœabpj½,V¶›6uêŠØ®VT#h+dB"§ŸÛ­<Óyd:7eÕÌTO+â•[’[§€¹TêÐÄ)aÇŠBÆd/ÛîØsΧWÓÙ†ÝÜÆrÕ‡²é­äØ)ÿ[O'Ùši^fý6Ê´ Gœˆˆ+kœ*KÇÖçF¿ý…þó'ôÌÞãhCú©‘Få˜K)ÓÖ¥íÏ=¨ B{aàÀà{Wz¯üJd™T&?²ÏþÃ_ó.õØìzoäíWžyvè‹GŒˆÕ¹‰ÂP‘Ü~£»³óï_áw¶üß:KýBÿ§ÓÍ®"®Å’¬Î[µæ!žTxÔˆ˜¨rÈ:;ˆ™1¼q¨¬®æ­«)^vHòfÉùNªf˜8bà¼Â5ô•ÈÓ‘D*„ø*O„9x÷·º«9XYa†íp0R+é3—*Ä\ÐÚ"”Õ?Iåsž€9 ÷à6·SĆҮjrcÌ¥³-ã(©íçýí¸'ªÚ­kQc ÁÞp.V|_šõ;Šá±þ£»×öãÖ—ìµ¹ìì®Z9h4µsùu/û$úÑõlê¾T®V‰O¾ùxõ7Ÿ Š~ãê"Ù\†HÓ^ÁSýàF“ô¹ÏžM¨›½w³Ô³Ð1Ê1žk‘DšXI¨ìÌ88B2-f7tŠºé›¨ô.< ó =Ÿèð\ÀöÛõÙäÁZñî]ýÎêò²\îd®)Z#¶tÛ]=‘æ´Ú±YÎ$UCncä«B®ÐتJå9!´ƒÜÜôÒRƒcAƒ¦ÒXÉLÀMDU‘:$Øhe¨íÇ,yו+/ñ¢¶…Ä–£´Ù §Vy×DFu…7»Õ»º Þ¹¬E^ôŒu®ÆªÜu7š†õ©gÃ;7ÓV{L– æé‘#èñ§½áB³Rp¯Þ.,÷òÈJ –)–e(ec„=|"-–ô‡‹ø­W[ [t™i™ëzµÑüÂpïÐ^â:üÊXiC°7aúv³²w’²?  :’÷ÿß_mεð×ÎW¾òhjINÃ`nÚRÇÖTÿ¯³#7Šaébcí¤. ‰ðA¼âí/L/–6yQ躋ßFäc%|ã´ˆt$ =ì:mªû”`ÄpªrέK²ÂBb¬¶YGZÐÄ¡S 9P S] uêB²Ï1s8O|„zÝ"º‘ëûŒE]a ƒc^§i¥™t×L¯:–V;Y" ’ k!E©3lDÈõ^¨Gû±Ê}+¿ðXýأìK²OVȵ;üìξ¾ÁfÈ'¯²ö¥ìÇWó»sQ5ËÚŠ·(þÊ#å/?™8,¹:›Ï-])Ÿ´·aþz·gñ‘Ó¹æ­[¸mhKK0–ZÐ`r•*ýîÈé#=C²ê¾Š%v~5˼pÀz“åôñ§Ë ›ñºÑᙚj}{­l¦8^NïÌÚÙ85B ,.5l¾Ž¼Ž–±2è‹d9 ©˜ñb®zà2µ\õ# FY©„À´ tSÈ¥äŠÐÆHIŒ#tL‡t^Ã6WÂ8°ÃØX舢؅î6) u’VSzM‡'š8–Õ¬ÉAGÚYnÅ«Mçò!âr±âM܉ÑZk=ŒFü³O:n‹Õ(0¢y¶ÿ€}âyo¤Ø-xôƒ«þt+ œû[¨ä¶Ë¨b=ü,êËo6ç7ì*€G˜jC;Ò‹ûòó{K}ž{e!-*&»ù€_½Wîó&«PÛ¹ü_^KîmšÏŸ£_~Dz´ëWÜ›·©µ…õ6l8d'¤±ÄÀµ1;qÀ ߯iÒ/£Â!w~qp-¯ƒ-P¸†èÛ†×K¨hT*Œõ!]Ú­rÏ1'\&ŠÖas‹5"à)‡“a”j…ʸ¦UPQø „x¯¯åNÀèU`—TÞ`Oå÷4c óÿ‘¾ÁˆËŠÇó<­5}> jh!Umz‚ÖAv¨à^u -êMs›Öá[§«O ”]Üët[äê¢{ù~ýèl¨–¿ÿ~8ä[– x¼­ì®Éâ_pD–ß¾Ê)PMé§ó<¶¸'l¹ÌM†–Wȧ7vyÝçÛP‚3«ËÆ¢ ÈнûyÈÔÍ¿óâ›þáÓ|÷žþôAfl~ú¸=¹ì=PpÆü--ßz7}ëãÊæR“C0 ­Q”È|ÃÀ3ÀÚ3¹aÀ0C-M$ BŽÂ‚0 "4Ö€›Y¨4QF¸à+£ 2 QL‚µò…ÍÀWD‡\sÌ®GäîX„‚æÀC>“9€k€c¤X¶ò á(¡m¨UÏ*cbTc)ûô~iy­[A»O±s¹AÀ7šza>Ôù—Ÿ ƆÌÚ÷k ׳|B¦©ZY3€ JS‹ ¥Ôw\ç}wÖ¤`³ªŠ£@ÉLvôØ„||I õчÏÑvÝ 3“*[«{ø|´ÑsþÕ_­t{/vÿðÅ<ͱq±+Ý­Ì<› ئù„Ç·} 2¨6eòt˜ï>‡v_,ñû+z0çU~²!ͨÜÁ‚j©txñY·p›ç)5£%ëóÌ.i|g„¥œ r O°˜Rkš~¿‘±ƒaÇtu”%§v˜³r€® sMê.¸-ïÒ’k¤ðíë}’w.ˆVþIºØ<ò¥BXÃó©ÞLX*TÒDBx…@SN’Ûd ¿~ºPa&…ì±½¬·Y¾²Š>š)ÞiJé—Ð|bpúhJµcÌýÆ‹>ÕffŠRŒ™Ë®Ng9°T±¾"/*çö¬¸y›0Wo·}ÑÔ6ps– ,ˆ€*À¾}=[‡;Q#wìÁãúÄÞâÆ|”:vÄžØowîqÜñòšˆõ¶yíÃpi¡MlŽ "V æÚ.[XÇ´‰mNWRY ai p|2„Éa)ЂŹU[¦Á –jê¦ÒHð56®’Ö1ØWF! äÀ€Ä–Ö¦…¥AjãÛ&ØMqiJZ"Ф2@µÊ×—âoç–:å‘`ÿÉàÔ9å•ÒFª§ïË-¿ð¹ú±AµþãÒÂU„FóÈæÝU䃈lMRaü¨`¡†˜5Çý³WøÒ*Ðɨ#Hrö0"¢úÖ;q±¤ÎŸ%[YoË:QÜ®e"§OGëþ×;¹Ôí}n¿ó{Ï¥Ì2$<{·¶¢F¬l3zFMXÀÈGåûé ˆñSfâ±BozuO îz•WAo Scþ+@knÑ‚E„>Íet/%Sé÷ò ¡3 uäR(êË ò"hs®X:“·N‚]NpÔ£#{¶'Ÿ÷ê,Ë€~¬Õ¶ “+׉L!Ç¢`JM‘­b¯-ÓIâf‰òÊöÜ9¹»ßò¬cÄJd˜sÙì½^PA–i”¸ð^å‡w¶ÞZ@ë:î©gÖ{fºÕº}—{øÒ\‹[Ō‹É—ŸÎ’M·÷zR^›YY ™ùY^f&Uš[HÄ ‰kw-‚P HqÁR×¹Óª8X‚™DÎíÊ‘–¬kXÐöì úâ.µÐ¨ÔP«K^{'zíWùü¼–SÁy†qdͶ1-0‘µ9 ˜×aE!_#@PV6!–l+nQŸ±Ì€°¾ã ã[S÷Ìneêè&%†F4Û6ÆE B0>Öf1w`–f_9ËÁñ­‘+]bµÐ&d¸â˜„ါL"¬œÐPP¹çÒÈ  mM ³ˆeŒTTuíÌ¿r/­sň3 þ?ù’Þ‹î¼kŽ6ò1-ã0©â¹u`ç KºÒ¯C?¬ŠäÚM¦Ø¶6-8RNúŠØ{ÐÚ[ÅÂLÚY5Þ˜}ê¤ 1Ü\ÁbðÑjN5Œþͯ¶WõÖùñÒß{R}6“¿~WýûÑw?áy·DkìVÕ Äž1è,»$î÷=gö¨Ñ{WEç®õ´÷ •lˬÞT†Ó"‰-µ¹gĦç=ÐdœbæÃÏáñ3AÙv‡5=›;OŒèè¨WOóÝ Ã#ió1æ§ÅÓ§¾cc×£(Üeø¬ÜÒô7C¼drÉP&dž" » °EHGæûÁO¸pKæÜ99YÕxÒ¬'ñf}„^ý׊™Ÿõ”Í=¢7ôÃ©í·—ÌFÃÆõ܉ÒzOM7Û7ïf]šoå`€ÊžFÏ3¿ö<îvœõ×¢òªŠÓQ1œÎÏÊ"6ÂèÜØTéhfÑýYà ¥`9ø ЈrS&‘¡tl‚ÒiïävV7é}矷îÂÓ[Åþ~’Šàwz¯½Þ»¯d×–±4L5•n‚íÍ1X `ŒˆÞÁ€ ¤mJA„¶ˆ´°0€€ ÈQàyÆxÊôx§Ô¥²NÓºµýn!‘;Ä„Öx VSÆdo@F…t]b”bŒSmr ù¾–¾©ÛÕ €øˆ(…Àý)͉›ƒíXÓ“Zm v(©Ø<̓YqõF¾¼!9Sjíþã—òþýhús¸!ÇLºZu;¿L5ÁÄ¡EéÐQÌ»UЬâ¾w¥GMÐв &F)g€jìá½õ›P»«EëŽ:ÎÅ̧÷ÖjŽÌs á:ÞŽï¾µ½”5Nõ³¿ÿ¤¹»Œ^½)ÿôSïo>îòNÑ¢ÌX@7J>;whI>šOœÏ>lœ¦‹wIó¶ú??#'3j]+NŠ$±¡ñÍ ’›¡?oô—È¡'ñèܧ:{¹?„':žôöa_–“¿çB¿rðTˆ²OÇ¿5ðø‰|ŸÏ¹v§î‰í‚¡q­bä`É‹VQð6¬Ì}†+ޏ¬.ܹˆïÂÁEÛõj~-&é먅%*!¹RòêW΋=£túžžÚt?ZA?þ,ÕØÕÚM¤lxç.w¬éZ’)ØÉ\¥-FÄž? Ï\@é6êu¹CT 23êÑÃÅz)nÈm€a¹{éa5µ)ç¦ÔÝkávÓE®2žîrÈÌH qll†@3,1‘ˆDµ1 œ8X«\£ÌðKýQ&•Ò‚±’JebÈšç&ûº½ý¸ÔHEèÔ(l™zžâOñOîdý5ÕnŒR¹U>Nê™9å†ý6ß78°ÙëöTî† $hd$2­ýpP&FZ94TZj„­Cˆ$DaЄi@ÍM5±¹ bÖ–ÿ`Ê4Ú<Böå}Äk.åK-µÁ`è¨BÿÚ´éÁêÇ“hψ~ù¥’[fÓó"–:œ _HëXèd$=u°¾1Ó=,ŬhOœÑ}»Â-o§1V!糋é"רxÈAõIòî žYqœ¼ðÔ18X2Cl€K²˜ 9o7KR^aà%ïÜåÖP¶ ï½§wD¡bö²‘9C= *mBEn "@í$¹ÀæÄ9zªdÆ8b¢¼y£US&èó”í#yŸuÉFŠušfË(þæà¹“顲¶®ûà¶’æ•ë)—Û?Ÿ.f k;äo.çoM³™u$;ôųìÔÁìÚRÁPYc•8ç‹°]ªV*/²³%-Þ`ï¿§Ç:¾vಖ9™ƒ"âUn÷°É¤) Œ´g€@>[81”íÙÅ¢ÉõK›“)­ª£¹vsrœÁ+œÿH¦Z vƶ&÷;Dª¥õJkŠ©|ݵëVRƒí„A~ÜÀâ B)Ì8±»¤êÔ’!×~ îoTÚ¶…þ1Ó¡-bgV^Ü]íôÚËÞñ9ûõ‡‚Ý£Sšô ínYñqíK2†fÃbwÖÜ»t4›8¨š&ZêÐépx”|zS$Ô¶Y`ÌRa¹R6äP]|4?äuÛiäYâpG0žØw2JJ¶zW'á­êú3™l‘!B8ÇidL[º–%nœ*cÁ:ˆa FY°«J@Ü2OrA) &¸b&«ðc›[É‘@Ø”,@=ÆCš/Àð2éúØ>¾Ÿÿ½/õ]8$NLx»†`ßNôБŠÈz=”`U×öYPáZŒæ,2Öw ¨Þ5‚wöÕ\'Q¬Œ-‡Ø(+UVöDAŽ8&`µƒ<Ì€›Zœ¹,±D€ÕZR$¦™jog¯]…¬3°çxìL :{Ž;ÛÍ`z¾—:PáX¿ðTøÔ3r÷P´ò€ÝÍ:XHc]¥EK˜îçñÝbwªá{»ùØYóáâ«?0¥,¬LÖ|ÞBÆâ•ÚØõ,ïó:dýœÿ‡Óc»ìÿç'¼Ès£•™í3‚Òâ]ŸÇ¼<˶úH­Äï,BçNqRå[ˆ·]ˆ)(£|™ÍOèA-@îÈ=:—óžôœ!:ZÌb×»úN³Ðu¦½ò_w›K<À |OŠŸ™Ä ª“RgííÉ}އäƒw}Š ¹ -žBD‚öôI ³Úø) zgƒBîØ¡çŲžZ*Fß<ÿ±o]À*Ê@=±»g½¥uöOŸ×_¨´oÌd㈬µâ’ã¬Ë2悺•îbtûZ©™;´cÍæÅݧñø\¹cºHö0±–" šh©mðÑAçÂÙáý´:¢-'¾ôT@Õѱú‘SiR@¥cN8†Þû¤ø–5r•ï"C³ØØ¦(t,ɼ8SBY퀥@µÆ ‰EÔSä•E’ BiàSÉ3|¤Ä÷”‹Z‹ÄpÀ¶`5*FrT;F'«hbš!Ãg'ù~­ÿô¾ôø„·g¼³Ò}è˜/òîF§˜"¨™¡ Õ­(º¹óÀ¸5>ÑŽ5{½=ý>ÅY/–Jë°Æh©òÀƒ×9ê Öð±ƒ-(€ÔBÊpDh©´ö¨$ƉsµäkW€Gå=ÇsȘÚ{Òi6ë–›š2¬ðè yø¼ó¹ÏÁÞ}ñôm½4o6­Ñ<íJ« U|‹ž;oê5¸Úv·šx(¼|^ý¾¶aÿÐP7,GÚ´Â`´žñš;tzŸú­Gƒß?Gvê?Ëe(:7Q¹¿ÙfF{´4ÅøNi‹p«Ÿ•<9³N¶¯{;ßByÇ…„‚2Ò×A~†A‹(G˜<ÅøNf’VH…á´ã8¿ßZsVYé?ä[+6/»@ZŠÍV\ã²û&:ˆØÈ²nVŠ}£j~Ùê%zÂæ6šæ%?“jTÉo›Ê%–[æ–”9aJ­3¡y’ '«½LíjÿušdÕ¿Áj©Õ\@xxŸúトª%öæ|Òl‘gOÆu/ï¥}ãvaNöCEª8±êØ^òÇ_ìûä¶ÔIÒìµ™lõrvì~¾pj”¨è£«*R&aÀ CýNHu¶sH”týý?‹ýÌ<ñBµR‰ãåB[ЧOØc“a“ëËwÜÞEK+Á¾sahÛ†›–Ç$H0 keýë`clôÃ;Àž²Ê‚×ÃŽ0ŽÉñ‰Iú»ÏøðÄð‰#«OQOÈ{|¹©»¶È± cà¦1‰»«æ>o½ˆhÍEžrá ]q¢}pgo)„ÚCEÈ+Š4 ä@÷â>ýÇߨ¿x&=½7þÂC;‡Ç³\» kž&ŽãÛ1eN"´1€!ìX?@¢gŒÖI‘Œ XÀXiŒØúš¸wG„îßž)nw[ïÞ2#Ø¿øpúÌ£å­øƒ_òj}x+jÎ,‚ãy©T°bÒRC¥ò˜xìBtp¢Ü=A¦3ï½_ñO¦r‹\¢4.uÿ›oõ¯5ÍZ«ç(Rõߥð%ù{‡ÉP±ãÓû¦{c3û£‹ýß~R^ÙÈZ½š1Xr›ýyÏ‹öÞêâ»ñ`ÛAŽPfÔ”˜ö; Œï”ŒúC]Z º‰üBHÕcÖ9hD‹Vݤx@]½í©÷…PîEO”MH’«uíÍ—²˜õ0Çß6÷‚ñº^Û*Ê%ç NCë[©xÁç–Žcý›¼zÛËrƒK–VΣÆÙaLâiG°­\Äcõøª›àE&&|hùW_vúÊå×t ç¹Ó½~7œ ó¨ßöIç îõþñ—J—¤îˆå7²•Ù Ÿ¬O>§ßcè~t]v9¤L±HSUgñ¡JR…¾Oþ‚¡¦}âóáÀ@¯=G;ÊüöA–iÐf[æûGhÉհɺRáz÷µÜíLM‡—¦ÕŽ*j€ê:áœ$1™ £Ör†(é“Жª i] àP ¤mI‹*Øžô<ÜBv4ˆÿè ÁPu{³¥Y­ÏzM¯F·î#qdlçò^o",…öaCØ/ŸíQ!#6V W¾»½v+Ç ¸š`AÑLÍÖ[Iêv;×ã=²¿ò»Oô#ÕlJUaœÆÈ­ÇÝlÈ÷ôyw¦¢–b}.©ç˜Z3fÙÚ`0J)àŠ¡–‰ÖÜaXÀU’|˺!ñÊ ÜíÔ*ÔNŽGƒÕòÂ|/_·Ø§v2œ~2·mfCc¨ÈËÞÍáÞÝd® ‰®Í1b)ª¸*¹p0qkµÞŽGÊήƒùÚZ½wE‚®lzeï'w2cÿö×Ä@%¿¿eV—‹—îD=錴͵´÷;™«`;H•‰¿Íࡹ!–hciتæ@|æeLÒ²q{Zí¡OQUÅK7Ò‰)¾ïø•í,‘+ªWaÁ¬FOùå ­U;„ÝîªLKwÖœó7z)1¦Œ!G…À=+¢Üµ®‹‘pÀ`­ä)„SÅAK—€F ƒJÊÔºÂYòHÁˆÿÑü‘Z«Ñ6¬R×nÛ¯“­˜©Ü×?Úh»+ C¤ÌÝÐt¤\ùò#™M„(²Õ9÷Úß6×o€?ì“JŽ„%qo¾ÞŽ„Sˆ: Zªtf¢øOÔŒ´)  mšb¹%}^²g°r{F´­¶˜æ.Øum—Á&X@€ÁÁ ”`1Ф¤d¤$7Œ+âd"L(oÈ‚ëÑ~›! 31žo OìàÕ€77æŠÐüÝ^G·/ÍG¤qÁ·œ(^²rГ]a¦§³µ†êY¥YЉ5jL€LûðQ­÷}ü«h¤äì<¬­×â8V)úl͉VË?½‰ýßöjåôAfîVn,¤íÌE!ªd¦g*d¬›íÛ5²H¼&CH-,ÕHykpWTލkå+T4~×ÈÝ)Wõü´¬µqL4¡¦áƒœ#  ást.PþºPKXb¨SU÷pÇÅâ¦R=¢•çï0\kŒ•Ô!Õ#)1û^'”9”XmL°û°ŽüæÍüæ=o+'Æâ}ðÞ­R´ë)Ë/8Þ·~„jáï ¼mî,…þ±âÊí8À~­XšÈ”S‡¦¹ÆBœÆyøaîH_õ$–*a¸£¨ãÈGGÉñG²é–aË{.T~õÓÎwÞ¥xÛÔEZÕ(”æÀF*._I7°±ÑÊ b=¦ˆæ:S6§n8^uÆ«¥ºçm¹AÆ œFÜ—²ãç'wÃçŽÚ^'ô óSúãŸ9›vt÷NˆZ%ÔébòÉ\–êz[âç#…乓Zh”¼k?…½‚`û`›Žœ*LÂû·{k ´E!A•z/#G‹8ëí¸ôVzû‚eÑøpU6³Zuèv¯;ßå%Áát)`3RmXîÎZa Rò|KGêˆC¤cYš:Z»S ï µÉªâq.|!ÒvòÆm‡o¦Ÿ$m?ì…ÙÙ'h´ìÜÜäm .ÕƒR 9öøáÒ£ÏS),N§M:A­­ÜÔ¤.ÊF _/}*ŸÏµÚmwž)}ð†þ«w6âPf%0‹îÀ²BI×Ç‚“äÖ(i|O‚&7À)õÇúaG=ècP¬h¦±B=B¥3J·ƒüØ$¼x`ÇÝ‚_zpK\y=XÛ“ûw’¬ðH†áw£Ü ¶ q4QËž<¢0¡™çÜùÝ•¤CD>ØGT™b|t»»œêvÖßRÁš_~ÎT{½ž•ÎÀ‡o6§?®!-vªÁ‡êÃz­ͼO ƒV-údFéu @H@wÕÂZÁ÷ÔxRõ8Š­c5&.Sµ¹Ö®GQ[%›È¯4"ÓšJ¢ŽxÿN)é%»sTPÌüìðã6m¡› &‚ÐsHU©ƒÃKO~ŽøµâÂÝxËàmVLr&”th\×(°|×…ÁÙŸê¡eµuŸO>D÷IÜ-k–×£ÒµõV$Ê¿÷¤¬§ßûŒþ§_„oÏp¦ÐÞrŒÉâØ„L;˜Êûp»_© õ¤“YP¡œ €C-+Èv‹‰v´x€¨Ï:°»‘‡üXðוP:' rdzZ“߇ˤË@º>[žÙeüQ-òýù:å>eü‡-/A}ÚJÀ]q‘I]6F<vŸ1«!üÁÕ  œp®´w°^*¹¨Ñ‰ÿä· Ç]ýá¼{}+þðh]2ív1IòB™ýño£ã£Ù­¬ÈQz™$‡’ö¢Ím+†€r’X«}×`D†¸üâcvÏXØ?éÛ¢H¶€)íîÆç÷ï6cûÃ×ÐõETÎ4Ùw…¢M­Õ ™0SÁ‘ëX«0AJ.SÅ÷ ÿø…ôë¢s‡ìËgȹ]¡SŠ7ÖKE¶Q>¦*Û ¶¥}êì=!!ï½!N4Eg5p&ÞÅÖH%>¾ÞŸùQh’œ• ~qo­À3ÄÂn¬VçÊ=–NfãNr¡Ã7ïˆVz(JAbí=&ê €`m«Ûz­x,ê|¶aïÏ„ÔáíHÝžfVÔmá=š5UXö‚çΦÿè‰êKçĉâé£ù±1±Ñªv»\ã’ccm•KmŠ©u¹Ê©u(^fd¥M‰aáha.<²O;!«õ¡ÏÔƒQSuC'Ùc ΰ%~íç^sbr“Ήñ¤õÊNVffÏÁÜj “ɲ ÉÃDzSÇ«7ïÅYšÄ+˜HÑâ_¾&®v 6ÁïæO=[~ïRV´v×PÿZ'÷@(Äæ‹­ek*öˆ°N‹ð³¨uS„ÉTA¸¿/,ÕÖ¶¶þùoU Ô•…ð³­öÛahEì%Êô_üap|„ßûÌ‘KÙ¸½,Áìö"O”×4„ G"  }ij¾üˆ90æ;0 ¨n ed‰°þQõÐÁúøH¼úß{\[P%øÛ–lP¡.X£·^`ÔÅ$á’¸ýF‰Ýcå?y*ú§¼³»Í#ðÅÝår¡·¸äm„ÉN^ˆ©Ú΃gNÈ}y"ÞM>xËœìdí•"Œ®…〠ä2ýຟ‡Ü5=îº^I?¹§Vä ½í8Yš-m™°v"Þ9솉HQð³iÞI ÓɱÆ*xîtRõm^„ÕFÒùEõp¯ýѺ2Ÿ-+êx¿u2yé™úû—IÙÉ´ÖED¹†Åí¹BvçP1,¡ô!ÅFŸ²ÚÓnŠÍö~´ÒÞÃ6£0_Ç7w4`?¤¨®‚D×ÀòŸª1âX¤°‰—„9*UÊìè‘ðàoénï„S8ÅìòEkÆÓZ YÒ;ö¥8( øªëüMªšz°À¹g-GúÐý_þª3ôÖ~ɯ]Ї!ÌŠ÷VÃ4ÉëRn;Hæ‚úXpÕ¸oOŸPjqWONœ;è_þ$]B†l [£ä*Ì«’áþÂßé´ïÚÑaï©çÅé_[IöíP‘?…¿}U3®ëeÓ±zëÃR&\Gy0üÿ™úÏoMÏ<¡ïý]ñNOÞ9Õ®ª½+ç¬Rj…–Ô­VÇé8iðƒ ^6›s8p°áàaá¶a300žaBguºÕ­Ô*…Rå´+ìœÃ“Ÿ;]ù¼`-¯ó?|^¿ÌX#öY»››TÅŒ{¾jç#Ce[–ª×ͽJrn/‰öþ#lj²¡ÞÀ&Áìà0;4ä JsÌÏÊÊ_3º4í÷õ—‘³-<òîÇ ÑÉÞ·%H7ÎïõFûTšg£“•òp½r$=x¸L²v!Ä×ü‡K_Ÿ¢Ñ¶êi‚?ñäXµ@ÂÍm¼z—T0ßñw P ™±wVáÚ2ÈÊ€ÖµJ ÿ­ákOX qÞ’¾U¾µÅþàä”×\N–sÉTuq D`ü®6ˆg¯ÕHY’`¼m§z$BYK¼÷@<\…þ~ž´Û;«öå³åO½„x]n¾íogt’ÜÛ*nì$-ÍÁº"+b( Ôm'ÃðÓç¸À# ‹ÍÂAo÷s}WÒnÊÕ¶îf34 írêµmøé'‚ßþ”}v*¿ü{wAÿW/øŸû|¾¶ãÖ¶M?æ$Ç[fàž-¥Æ„Ç ß§E›ê»@œ®ÜrÙœ—jšÖÈôð³d¨(ç·¬v™ÖX¢¨Zh€›I5$ºAR°ú v]ßMíÕÓûŠ3z‡hé)Dök³¬{wÊ ‹~Ã’Î)qˆÈ€Š›aômÁ¶Ä`$[‘- ’?hþî_.ô{ñ7å”I¿ò˜9zJb68³®Ó˜(Q§ØC|”&¢#èÐþmÌâ¦-9n^a«¶-¹q&ô¼DYšUbÅá<<ªßù¿trÛßµ+yæÓdm¬v¦wi ä?¾*Þº¢Y®û*®ú¨¡¨g8·> f]®µÞkù.$Œ- ,”“ êßþbabHœàÒž¤A|zÊå𽇀¬°^S¶¯_÷Œ*Ìß*i»aHq÷õ—œ!]6òÎÇ]*ó§Y´“—’vvtÚŽ én†v÷Eõ‰ýÙôÑ ˆNT"wwøkšÎñp[õ UÏ=92ˆ"ÞöZ¹‡Êœ¶ýÚà¬<’èÁ*¿6§4Òº[B'ýµ _¾c¬eWVù. +¥SÓ^{Ù,f‚b¨špŠd¡†@4eÒ£*P”u}»¦3ìÜHQ‰D}ôÀÞ[€J d¯W_…øü‹y©á;•.?ÁPi¾å¶í¬S(¢B#C;H£É ôÂiløàùN´Ÿïùduq¿{µ»Úv½„ B FoödóÎÕþöóÞc‡âÛê·Óo~"úÒ—²•†[ßròÄÔíàM#ƒOšì4ÕS ÚŒÞvÆ™ª¦ñ„IÏ„ü¬I§¼Ê­<Ÿ~÷—ìÖ’ÁBÏjsa,`Ž€çé9•aRpáËúAè—¦ü3ø£–Û^‹=­$xÈ/õˆ~ Øã³Ï„øY~UiI‡ |ËcúäÞê?úåº ì­™ÑÖÕ±ãÑÈ—®¹Òí¶ÎÂÓ‡M­2°¹b6ÖJWïØ…Vy°8yfdâ鹊g,¸4·\§– Ï÷5)¸pHǶ\ò´í¿Ë`sg1›:¾r¦ãOì~ç²x÷Ã1ê#kJ.%FiîÀZЬ¥Ô"ã\:MÉ‚¬2¾ el! üo}íl‰L"î톕n»é½"ÖÁíÅhSFˆ&ÒÙ²ÏíS®eýtt¸ôÐê¡“éñ:lv ˜ür±qc^ ºâEÒNÛqFôð ƒ^ž¥µ]¾Wƒ¼—„b>òí÷õÂ*9Ùio@­Ãzãý³%Ÿ¤Ò¤}Øáä±g,«ìøŽûbâ§·ôbS#jW3?7…Wž@_¸Ðµ=«)ØR©AxHÖyÍOGûè¥<ºâä î7‚˜ÕmÀ·4ÐÔÒÜgÂºÒÆ7“œïø—®£z[}é ¿zn»Õs~bŸ`µƒ•r¸çlK8Ï3Ú¥K+ŠLU†jä™gq°o«oHp°ï©gÍBœè{W@†l˜ˉٱbLNPÁ±=ÎU±;ë`ØbìzD=Û¿ÚcÛ«"°YËáå;Z=æà)Cx³åÂ[Iþ±4DE¶mpÐ%òâ®Òÿû+`:]â¡{Æß]'Nz [î´šK¸–§MRºpL–+Û+vc£xý.©ŸA# ý`µ~cÑôëÒi?n¹é<ƒ¢#SU_·L{ÞqqHøØ·.©¹U|ÒÓ$i›‘î õõŽW*&ëTvû¹çuhtê ˆ†š÷\Vzýzw±n#ßÍöÊÂO^Ⱦþ8íÜ`€Z°iýˆ¨\ä}Q>Þ½÷À¥Â” ?a “Aƒ1C' á#@9`ËÁ!ÍÖj¦j8ÙÆÞ,7côÊgÊ_;»“tÊ7ØzÊÈi³ÍÖÞàÕ´¦™eÊÄenjÈö×ÌÓÏšÂþfyðØ–Ö?ýpý­_¢µµ‚’nd¬v`ooy‹—­®vhOçÜh\÷þ/oe5L_<«-¼r /l𙮤„š)ÇV…ÞpŽG•’ˆ‡•A4P~ù„¥„K­^Ѷ0]}þi´Ûø¾ò¬«`@FM ÉìèŒ(d8 ¡ Þ‡¬¥`©Fý¼–åÆ:ÐŒ8ë ¸¯_7ÎùX*3ÂÞBæ-‘õ ‚‰$5ÎYå8Oòv™ÖöUÈH-ÛȳëÛãþÍ^+Fº”@>=ýö§Œ¡æÑýØR™w`e5¿?+ÞQŠDë=¿¾žE¤O—Ì›ƒÄ-ä÷ûúÌtåÎL½çSë§Ÿæo> þâu‘Õ{’·^Éxbj„yÅÜ€Ö–"îÛÔM†¬9@!ÒF[>ĉ ÷y_{™Ì×EÕ+¯¬ ËïÆ›ft¨i9¨·f‡tq;"ê¥òâ~¯tˆŸâéÓÝA§Ë-ˆpòßÍwäJ0#¹$ØÂè¬yvÚò¨î¹ ¾2Mÿã7[¿¸Ê|0S¤­\Ô$–ÑSG&œÝɵ™€ƒG3Oû!ϱб ~ÿucŠ»@$ Î~íŒê§HC5Ù¥÷õü¼åRe[%cƒþ½…žóBsØâ¢É‰§¶¬kh0ÈZë08É($N!\LdÔÊsŽÔ½ÄÍlðÜóFÆøÊ=W—lI%Ó§½Gór®`“ôÑáŽiùv!R"a9ô~ô÷Þåxf¡ÙŠ‡ÖªÔ3ò…gÃ/a·²µ¦#¨ð`)v•‘ë[æöj祓âŃʳ•ŸÝòÞ~ÔJ Cð¨µæ~ &(ŒyþX½‰\¨H”!ðâb~ä™´â'ݘ;$Dn¡1¬ ÖÀ\9“S“c‡,§ÈÄøc§‘#sËkGdÍï°A¹¶ìü”a§Cètû‰PNä&ãæM¬ÞLòü€#Ù‰ § 34¯ò¾½ål¤¬ëVÞ¬ç o¤ùk¿ÈðØéý{Ùï¼LsœÏßO •’‹VVWò™Ù|þ¾ÎUu3ãíuä¡¢*`“'Øiw­áðÄ>ÿîÃfƈö‹SOWß|¤¾õS—Ô»%’µú¿=K{´†)Ó©5Š8vî§žÎ9 Gz¤t Æ¿ñ,ÙN$ǃ«øý·ZÝE=8Ž€öáD:$>º¯€È=˜6äÜ%‡*)RŽ!¾ïLopËDq2œúO¿”ÛÛúˆQåQ¾.Ñü–¯³Îñ)S‹Ì”ë‘"7Èû“Ÿ7^»Fèý%US¤{Kç²ðɃCL6R£&Õä‰n@X9JuBþðÍÓ…q-:gPþk'ì° äʾwI,Üç—*^ݪ‰v÷A¸ÞÏLJ­WкÈa[é¦°Ê ˜[)˜¬šš •2 b0HâXÞ^.’(¬Œ»yWo &ƒÇ¢¹íÞr32ºÓÏÊ=W#4¤B+ua¸*}õÏÕGײ{‹õV †j†r¦ÌsO{¿zA\Þöâ ·× J×›Ù•ô…#ø¥Ã"dÁ¯™wÈ8ïC¶-œ.âùxÓ¨û"^0âwe½£¬3 5FåŒå†ànI|./FI§‡ômðŒ9<¦ÙÐ60mœÀ† rÚ3Nc»íÇg A×­=-Êxb÷ØÐÆ£^ŸÓl éßx»Gb’ñ\¥%Ÿ”tžÖ¾òd²Ý.þø^çÞ¬=v¨89”~øs©ÙZÖÈñÈÏž.þúW¬Ãi®äƒ»¤§‡z3äk&,¶YBÝKBOLú²Õ…4 €_sÔùª”Ï=½345””:‡žyóÃäo·}à´ö½-W¶¼ÁH†¦8P. i›Ô QYIb PD žGC1j?= 'GQ/’TV®|·µÍß©GÚçû'¨Æ"û³ÛÒI÷b1²-k;»Ù=tpp´B¬Žm >ÁH¿ïÕ–~_#{}É‚0]©2Z~°ßžÕMÅz´´#£÷ª?z3»<©ì²ãxi¡Y@‹H·º"2;ÇöÖÂ!Æ*Õµ~lÈâï~g{#¡¾Pòî¤Üמd%¯w÷žß¼Ìï «éèÑŠ«$a—ìtÝí­$2Õý.Nix_z«.”enPna¤hM‘‘À·¼TòL¹bf£œË“ìÊýLepîÙB—vŽœìk¼ó®·‰uŒu¨Ó~f=©¸cû7wèýkYW²¶U.)£\J%$/^L¢š8v´ZOÍýMW°ta¥uyNÔü×_Ö]QúÝï»oßj+Ÿ=+gæË#ƒ¹ÈmÏr§ù¼Jo˜ÜX4tÈÚ®³¾U;Dï~¡ròL*,ÙÐnãÀ*ä†~ÄR©€;=Ìh™:¡\æÈ¦'O Ždw°õ/º²›²Â/-?Œ«r'‡Á¶ßtø5â? Õ¹e? UžG¿r5âð'3Í{üÃÝî!ùñ‡¥ ;õ%‰mÐDÙ¹ãåßøªÓ8–Nß¿KZ²–hƱ‡"¥íuðìÃ^#áSF6SÈò~œ®m€£Œa>ù‰Æ®=»Z•ÞáO”Þ{¯ûçogv´ñý-Wùÿ÷L˜oläÑ@šÔ aY+æŒó<j9gúº^÷‰½pz˲UYáê÷›‡Ö ½°Çéî݈b–á+R*x©PµJ-|o¹wühq¤Ð§ó&RŽƒ‡t†¥}°ü³ᘛòƒ1áB_w¥Q~ø`³{ótt% ƒ,¸ü@ÿÉ/’æ€²Ò˜ë  cÍcÓˆÂj QÁ!ÔÖP°eÌëyéŸ}-õ§»P wãœ0÷õ' wÃwªíKüt#¸·¬GŽ{¨’G=´ÝA·6“¢­î·´]_D‘r¹uΧ5­Å–:ã…Lq,ÁeŽPÇŒÑV'—gR«½£S‰½ÇùðþÎ/~ML;Æ2æ–9º¯¸ÑÔ÷¯ÆœÅ$׌.&š†0¹üâãq©l§N»,µ3k<¤tq6¹²mö·>‹rÌþÅ÷Ä·ošáhàåÓ½¹Å¾X Û2Ê•Êàè’7Lf,ô6ªç¬ïÔà‰ç«gÏ¥Ñ-£ÚWyÑZ6ÁîGTf,ز-2C•®h8hŽçضGâ]ÝZóÛ˜¯‘~CoÙû’¼É¼%Æ–‚ÅŒ0C²ñ¢{åÉò¯Ÿ§ß½“ øÞßû¬ßlçnùß½” à¸Lñ±åÎÛǽ_åówÓɃ»îl¶wºšS¿iZ=Êø=CKž#VÿêËÏœ- kg%b )¢QïÄ zhÔPæþð;Í¥EÀ …õ’mMÁfRm©&“3…´# Ñ#cpêd#Ò˜â bV…n!yx\]%B:cÅú #m•ú²4鱡f/ÏÖ?þ¨†ùÐt¼3Ä傱ëP»ñ ñ- *¨àx‹Éë÷§—è¯dàÑIðN¥e-ìãD»-•(RØÉüë òý{½7ïÇ×çp#‰œ# ÛãŒ2âåÚ—}1“-Do,¡G™Ã}YÙW¾ ÛØüò†ýýwÐ|»\²î‚KX.gxÖÁ+gâÔe)Í“v±³Ôò5$ƒxôp§nœ³ÖÒ»k0fù¸ü IºZ[.ÀŒ+n!•¸kˆ‘ @â édÃPCi•˜1ÀK;èþlüé§ÐÔ¤Ú…_^ë…²ªX©ÈÓ©ö⹉/¼ìç×®´xË™§X¹­ÓÔªû˜÷ª}úÌôÄ¥ïvç®ÂÓK¦ÜÛ\sÖZœ¨Xíÿƒ?Ë× {zý»/{Ï…wv:ÿê7Ê•Ñ|{uzÔ¹¬¸áÐCÖ*ȘdkØ4'MÖ2:.–Puþé×У†›•ÆÖÔžrh›E☱emO#_!¼ã»©#cZêÙµÔÉÅ*Ñ‘{¼sW…ß7vÁy pÄ瑦f,2/?ýæcìÛ÷D?÷þþçæ¸¼íÿàC=QŒœòÓTõ)›9}ñ\ôéI}éûÅûw’ÝwÝÞlït´Çƒ†i·¥“Æ«œÎ²¯}ž½ôTßXµšënS¥G£’÷xç̱‰ñÄúÿ<ÞXÂE0é% Ûš€Í¤ÆP1"FPí4P‹,‹±Ñ(µ²HÎ ƒRmÝ1ÙÁqõÌÒN¥Åq}-BÍ<á¢8ú#­^’s¤_ÿ¸^´7nŒúî‘t 6|å^7Â$(geR¬£äzÏüÙ%òÃ+Ú¼ ³Si_†Û.d±µë"8ª§ÑíqíNûí{ÉÇ d3‹´#Dwö0e ÔpÌlÇù3‹t%f¬ª‚@ T©{å6ù£÷ìL{&½H”ŸÃ}t:øÜ¹N‚DÎò,&‡¢„Q·Œ‰I‚Ç<|yUÜYqVƒñÑ-,Z4¦€,rb\b#­5H§AJß Ð)±ë§¬fíÒ*,-ÆÎéƒü펼| @úÚ+D¼=5 /œÝý+Ÿ+Oì2W.·1ñÖM˜cÖR2³*¾£½bI]<:úæ÷{›—Šgp±]_.†(y¾{bÀYýþB¬f#O{ï ñ ùÝfö/¿¼wpRon‹NL@qpZR¼a£«Žn:Y-ÒÝ"\µ®=ætK¡$,™àÁŒª×cÎG|AF1{RQòiç(C–œuxXN¬A(Çh¥‹:¥ò’Kn¾£º74mü)á…ØW)³âØùû/ï:º{Ã7êƒmòðQþµsÁ§N%½Ì,4õ‡)iwGŒÚp»¦¦’¯|Ö]~ÝløQ f›‚OËm„I¹!Á¨V™@"·fñÝ}½É! 1qgÏŽM×6:fœš:^½t¾÷j¥­b D’ñ—`‡12Ž[ Zk-hŸ‚õÏNˆ—O‹O?ÆŸ8€÷”òÜÒÍ^µ‘w‹¨ ˜ŽÁ&=}áLû꫸62)öžLMý7¿Qzãf ¤y±P¥iîù|-5=Íï=ì|pG¿=Szýc}yÏ-ebpè>ì/}Ø”­pÂJêQ2°‚œ¢ÌY-}F\¾Ý“½j!•Í e°ãá•íìþ,~ÿ£àü7>ת­Ôr§ö›ì‡°W½£›BësûÊ“#rÝWÍ-¢Ûýåý%»F<Û0òÿø‘Ò)b(ÕþUÕÍ!<<*_: >±ôÌñ`j ‹‘\í€ #_º’3–‚Ä@¬µoÀd,×$Séµk#ÛZE#ÁͳJÉ>s¼ý³{“öãld$ßZ>Œ3/%©ÒØy™> ÈÏ3ç Ì™1Õw«»õÉÏâÕ ¾ÔªêÞN/{}–² ûÌQñ÷_±: þŸö*CúsûåÞ>þôt´Ùˆã¢`07HIˆtW¯zÉûR×\qx¥w`m6Ûé Ú¶‘± ß° ¸EeÏ‘vÐâ0íÈKö:lÁG"­Øm_NZ·\¾Jë¨üã¼yúUTšP«X(}¥ˆÉ×Jÿàs'÷¯ûÚ~°Y~0×ùê™òó‡;ŠÅ½<‹i«=bíسí ɵŸ„ÓmÇh¶.ü}²Ý4.Õ)·–öY›K$ceFØÛ§‡k±i[”Î?VœíX:ŧÏ~yÍ}÷{ÅX§ e,\¶’ ŠqÔPX°Hq&<»[êDö™ÇýÇÂD!Óˆovˬà¢ömOË”ÀÅcÌôôÀÅýrI*SÙ¡³‚†®ÌÙÒjñÇ·RlãÇ ežå˜Ùµ¬ëðþýηƒ·ø?ù®>ÂsKIIC!^*õ]iÇ9Ž´ãÂjTÈ­“NGžp’p°J„¤¸t3QÝþ‚N·¶´¢ ÑKõäÞ¢þè2ýå ºt5¿4#VcTÁáí!¸ÿµmÎMW¦ÆqÊdÙh€íêžsÍ]£Ü5ñ~¨dŒ‡|Êò5•älhz {~_ö™ äÅ3Þ‘ÑÜ9·Z§P¢^Æ"«51Žf=g馕ŒM9—Ä™¾9SØÈéÀdåæGq±FŸ;Üyá¹=ÉªÈ ˆíæÃ‡hQâIm4° üXÇòG,áÁ‡²ÏvÒ‹_ð7ëñN½€ˆ›éÏÊÌÏ>{,ÿ»¯d ýý#YâŸ=TŸï𨮷ÚíÌë‡m‚ rG®†ÙÛB–Ha` :wÑüB¶ÞÁ¶kB Á€fý`ªú(׎|†ÂaEÆ0<Þ‰´‘Î:g6øœpFúŽÒ¬HË,,w™QTyt’k >lvv×ìô€áoySÜÛòû¢ä`¿ÛÔ±ÞÀÆz»„¢MV<}|ó¿ý¢G˜\ºCP½‹‘ª Õ¼)óàš.A©nr‹€èKÈ #ÍÔÁñöV¼ð³^gXeŸz^öªÇ|¾m;M³ÜfÊ”¼~«ã LÆ‚%.ê]AЕ]d ŠÂ™ÅÎBHQ(xn°#ºÀl–ëÜúÑj’.‡6&G³(Ìc!•Ù±iYâ€{Äy'<‹ ©‹ ‡R‰Ýª€ÆrÖósPûvÙþƒÅ~–¤u44Dß[ö¾Y„šg VPšÑ⹉øo½P|z¿¨ö‘R)>QÿÛ_´ `yÆÀvb©¦»åý«:„ í”AÀ¬°~x~– ]Sƒq¯ü¼g–Á%ôó/ªÇÎ9/Rþ=¾±Úó4R¾lEiœ$Ê!K‘µÖ¢ØÙ‚r¿ö$ú­Oò£c²±]%ïâ¨:15º­…f°“Ü0°vCÐñ ÿÀ¨ê®šbàöž¬ìN”på^ðÈÿùZkçc‘ %ìW©ôQØRyv‡àf/ „‘>ް5RiÈ—‰ÞÊS]¨´órŠÓŽh°TÑ@ÓÜmѹ¬ír7ÚÉRdð@ib8 ¢¼+2‰¶h ‡`ŸŸ=P~wîÔƒ &>Í^<\úÕÏa‹÷VÔ/î‡OLŠÇŽ;äàÒ}ûÝ;¢V<޹V4) AÉܘÝtù}%æ(ÕíµD¶Ì˜À@¹gãÖ¸ÈIæIåcÓ›µpé_:t‰ÃuÍ7XÞ±F¨ZD%Aʬ£4¥æWžÑGGî,÷~íé°ÔN¾sKôº°[ꌿóGüü½µþ~>œ³2c²Ji°!RƒõàäèŽ*„•Rÿ+}®|ùN–Ð\¬˜ ¾/Ó¤b!Â@ ÜjtÅV-^CÉ฻8tå½nÖ“CŠUOô%e\³ØyYGøŠþÜ‹µoœéuSÝDŪVÛyçúÍÙq{mQn GµõO}µºû剃2Û®b—ö@ Ìù•|Ðûð¦î¡Â€Ë†0rŠ<2fž¨˜B¢ ¶ÄQG(xÊòµÃÎ*@à‹´PçY'X0 g`v’øà˜Ó k <Ž0ÈâœÐX:‡|¬ˆ±Â…– "š`6q”í¤€éôÁÁ Tm©™Ò2£Õ~µ4?ðÞj42讜lS·«jÿ_²Õš]Oq¤ÁÒ5e”õNN‹”T–æm¹ 5XKwÈZÏhâ@§>q :¢gHµÏï˾g÷ôTUÓ"]IXgC`"bÌ”Äbðã‚CŸ;_à'ꪹ«Ñçí²Ð½ËñNk¤Ûj)%†\õFÜØ]uûË¥ÿ|Û,6äWNÚÝãøÿ{©ïÞ²û²gÎÕ>~Ôûòã#‡³µ-ߘ\óÑDi¯ß Vw½m7Ÿ ÌÛ€»Ýdx5Oo ¨ çHtO§áá[@®øòÀ `r0F$ k—¢@˜µFsf?w!:±7¸1ýñZŸè|ëF)!æñ]±“Á›sZóäSûü{ëöÞèìV~r©ób©²“¤£¡©þm‡¼h¸úÒò˜×wù¶ˆ‰ši&ÃNÉbÎ*,C!+2¼œõ»`ÉăO¨¹õ‘ßéeíœ#”舾D"é ‹m„‘sÈ€oA‘À‘O?SþÍÇ“v"[TtŽM¾ŒX­‚OÈûëf« eË"(ulº³šŸ­Œ÷„ yªŠÕÅò÷>ì¾w[æ¶V¥Ù"`Ü=mæ<#‰Ë•s·,w`µB”)ó_²Ï˜+‹dŽQ ˆ€ãP€8å|Å ÕeÐm Ör Æ8K ‰C`¸sˆÆ œcÖjÔqháÔŠWÎv„1âÈ¡ÑrhꉴVf*(÷Ë…•¾÷VÒJ]Í1¸èÁrþ> ÅA·˜š²¾5›®èTzj¯ÊpquQä–A(ÀYj8 m¸– lXå š)ÙËpmÀÊüÒìM ¤¡3PÜR}›+]Ç’ÄYDÒ l0Ò‚C¯œ¡…S±ª×6j¥Ï£v&>œu;­rk#ñ¸+ ¶àÌÏ÷û|³²°•|å4ß7®ÿèÿ?¾­ í'ƒwWåמaÇkj¹Mr)R’­ Ìt  óআ>@l–Áš0sV?dÅ9•.Áó:ë„dSkÃüT[‹œ#Ž[? =‹¨S ®3)™|ùâíÛ«)°nf“{½/½0ühQ¿ûPÔ×üÏ ï^Ë[}{‡ðjç6ç¦<^ÖóÕY}ç¹µÖÆ“=:ãPÞ[ìÝ]7; :É«=“Ê\ïu4w…œízÖ­‚[ °81NÊ?³EÖ·º$F‹Ôô(~ç:ýÖÇùýM¼àa[–'L~õ|ÿôT©·¥‚a±²‰¶vŠ^µÉ”ëAu°_ß_¤à)± £ŸÄJ)í#ã$±SÎ+í´ó™;iTöÎŽ Þ^L¶ú鱋öÞlò¨Ãˆõî‚›öú%L˜Ï7ínÿb1]Æ/?ìÝúÏ< ;Ýþaè瓌Ý^·µ]Á~éç2þKÿæUýÚäpIþ7ßì[ê’;÷{Ÿÿ¤xæ,zåTÒáüáš*0«%²8Ф¯}L4#I¦­%]p;Ä49Þ0²i`Õ¡5'š!l9S—NZÐÆw!õºÖ@œîz–9ÀKÛöEØ·Gð ÿàºØc¾üéèÑ,{w®µ]/<}LýìŽH·†wMâÿðji´CôèHÀKre!ßš#÷n‘ëË]•l7ÞM ^ãÁŽku‚!&[ »,ä@¦+Ö{âºÛÊ£Ï<Öw·å}û;Û›]A_LȆHS°ÖaÐ ]º›™¢†LcÀþDMù ˜8$+KÕ®ˆJãq²- }5ãj—{%T8[ÐÂäó9¾½-z:É",} íŸ]¯ß£±˜“˜Dï"½ˆlfWŽ:°(8‹bÀrÚ5J7Î:§(ÏhÏo(qQ`ï4v‚#+­1ÄZ(”…q "†1ÿ%ÔçíaØÖ!XF°DІ…ž¶XAêü;u²°Ó p6ZJL†Ü{WÉ?†{«ú€±“hÇâž“¿~qàÀTµ[WÑˆÜØ€Íz™÷u¨a‡‡õýeµÓ ¹»)¤ÚJÃAq,‘8ƒ¼h±Ñ‘&QŸ9Rx°êÕ¼éíûs­…ÄC²8€LG(ßÙ½¼/5êà¨ùüqÓíõ­õé5Ü}ç£ôúÛøá½±•ûY¹âZNé&̶Œ?¾ö1Nòäo¾àý‡×Ý÷îÐÑ‚ù{ulKÓ«7â/?‰^>½x0åÒÍÅn€5lPì˜Í¨.Lb+(ƒ{Æu<×ðržµÑD{Ž¥ `šæyˆÔLøÈ©¦;”›‚G3cÞ íæé­ËÍlwTTÑQå`v6þõé7?•ÿë±×çPö¦?TR­û§.@hIéo|ѾwS¿¹î?næ%ÜM;7òÛÞ›ŒLÚå^¡ÀLK6X5Ntê5hBß\ÏÆ*£Å/mÉÀܸ¡^½Rò„V:V×äL€” Âgö`h‡»©ëq<\ÃÃaF:„þ½Uú~KwðëÕ=“-ÔËÎN þÛÝ:¤M~Ø ooª{ëöG$aµ ét…€ÀQmŠH0E@BÄG~8-A £,VÀsài8ȇ"¢Y„+l‘vÈ"œdÁ…ØmÀé€0VfÂQÕ øÀ1P´*‘ @;ƒŒ±F!Ô*¤øå‡ôê<”*ž‡lÒI» Áúyå(ŽIžÖY ç& Ž7Šý°x¿xë/z„6·Ïâóç)ÎZÃeª¢‡;˜9v¤Z]ÊİMð4OÀÓFBÓfœBÂ_ý¡ÕÏwNý-ƒc2\hm®§ŽvqºË”Æ|;ÛÊëÅÀ_îùÿüÕxaµn‘Q>$1f¶P)åQ×;µ+}ê$ùß~ŸàýƒoËí¤=^õÿÍÁÛ³ùX¿ý/CÁέ@ýŠ¡FâââÍÛr$¨•Âh{[>¼µº¢¶•Ë’°.ê" ‚ @¼Ì‚# ”J8LT‘²HÙ\ª*áƒÅøÐ(<¸7âªJXýð^Þ; ŠýPr\Y=;÷Ÿ‡o¾ ÿûkðúÓV¼ÂVºýïþÜ Â¬ø×>¾s;}sµ¤ÚÊŒku:×á^ÞzKÃø,vKÜɺ>‡~„q4qÎmïtFjÃO}ØÀ]½ÒýÅI„˜Ä*E¶ÍX @O¤Ðô‹ÝD·¬ØÑBêZ€#oæcš\jKí|­<µ»‹ºÍÇvMþž‡êq/ú8@Ì*‹ÙFÓüäm[,‡ÖzÝ®’Ú90$C‚!,b3iÁ:ËX¢­¤ Š‚6¦<ÄQÀ$„Ž1 @-`ç Cœ‹0"VùDáD¹´g¬°DHЀ2@Ôòš’9F«{Fõ0…²ÎÀJùÍàk³l°ìyØÆÍ´‡ SQõޏ¤Z;8·áx£8èTþi‹à6¿@/\`m÷—a ‚Ü&K†Þ ’U03δ– Ok M›• +Pˆ¨÷½oÃgžÏNýNlZt¸0þ­Ÿ¬vXÖSÅÑ íèˆz% –bþÏ¿—¬mÖml¤¡Ú–ª¡À)=½>ùÿÿ®%€š&ü_?„¤±{`ð_þ¨{eEróß~ÃõÑ•ë7¨¯ •¬QÇÞ»k*<,”·êêè±æú’ZH!ï•Õ™£àÜÉÜ 0•$¤—@«.mWp Õ¶ó¼fM×q`økŸ‚èøÀèßü§Ëȃ¿|ªô¿ÿˆüߢú— G;^PiuÚZöù?ü¼ÿ÷ÿ¨öÎüȳ¾H¨Æ<ìûK¿ÙÚ;ªw²à­E[ë TäÊy[A¥î5VQÁýW¯T2ع±õe·nD €h%¦¼®×ú‹ßz Ý[î"hv ëZÈ2,Á#ƒË¬² ²¡ÀÑ…R7!ÎÁhªQµÂbÅÙf«ôqîiIšKÁØDËw 2_o`KÕ“$žaæ¡ v”ÂkŒç€QlÁŒ,„ÆiØaN «¹sV %S“ô#RÄP î«Ø cPÆÀd + ‰ K N)¤,÷9¸sP‰³]p lëXnÙ0 ´@0hTtVl¥ âŽ2d°uZ%-MH`„PqšdÅ,[ô@s¸HÁ÷r#KÁ•„âûT÷(ªx„Qµè[’­\§SrpÐób½8×R@Öpel”pS’ÿé/òÇv*å3Þâêz'EÃQÐJ( ²=;°—ï3­þÁÚ70‹\!)*%£h ·MšÔîßg§GÅ_ú&ÿ³oõËNÝs¸ßÑí¬ö¶jôÐÿø¹õ~žÊ¤Ôi2€<€$ ‡þÇ¦ø‡/“?ê6cý׿4*Öë€à_ý’ÞžŒÐÌòÑš1í~…Ó”p©êÎLk¡“‘ Pµ^¯3KŒApbþÊ‹a3T+ý÷‹Á üÊ1ï_ü¹ýG¯—ÿÙ_’ÄÄ~0Ðn×UÂ÷¢ÿçgàŸüéÀGõe×å%’1¦]†)ßüÕÞîÞöAôÎDz!º :`â4€Ê6_Û\¢në¥òãëkls6ßq¢†Ë ÚBW¶âÍþ¡ð?½ŽoÏÅ\C±žƒo’û¾¸™S¸#-p(‹À2å§% €s‚Å´-ꊃA$**!ÏË»,œÃ¹]a¤½€hg sÊá CŠ­KhêS°šb—'Êvœ­;h"]gº §9k²3À°w뱬Rf­™aæY˹½T÷’bÂÖ}Ý£€2lU×Q?ÓicÑ#!&îæ#Ó9 þÛ_.€—Ò^Zû…(¡&ï!5Œ¬§$ 5küço‰ù-ö·ëkIR¤¤§, ’É¢íÛMë2¯þÁ«Í+MSѵV/Ea9…œê„!¾w¯™¨™¯¾õg%w¹íNðÊâf}±ôû»ÿ__Z ˜y£„÷¿ã=XoýýWü÷5·sñ×¾8Ä×; ¬ÿÝ›äö,ØÀS1+ë<ëרgIв-J3åç›ÕbÞiÂÿöû;cUË£7f·  c%,çõœïÁèÙãéÍUôƃÆþùµ/¹b©½¶Ì'ñh•¼î?þ«ñ?ý®á›ªÈA•¾ülzæ'ß±'Š»ë³óPóÃõ|Ë hC oÂ+ÅI«žl¼ø„åòF­Ä ÝlÏï蹇ô—sáÖéÖbTÒà…JaZ¥à###ˆ%,£v+…†¦ô1>Eô]«6Z]•¸ÝW®MKo¿©‹86e±¬äÕv¼ÉCB3â»2 ²Ñ]€ ÈòT¤œ!ÊÈ´Cà…HH‡ H×B™ª3Sv#(`D‘O,aÖøJÐ9E• ° L•´Qà,µp“0‚ IbJ|¶)/!ÔIC€~ ˆ@&ÌP£Q–:³BÜœ m@œh¤ëqdrE4!hR¤Ea¬ösNbˆ2RR JRFjÖ.ŽNw®ÎŠn\@ýåÂŽm³¤¼ÕIÇû=ܯHOÚe€Î¬™¶Ú·´ÚE¶Ù!ãM°ð(ù_ÿ¸}üÐHÑÏŒ4ŽOa].@+šË÷ïnýâã5‘ÒQàaÒÞA= ÀãÕ.k ã{ó¨4ð³WëÕ}úɧê?|³ÀÓxPŠô°ÿÝoÌsAÜÐj²µÞ,EUÛÍÿý«½[õä©ÒSÔ÷oð© y(”paãüXŤޗü½__¦y¿ûÃDfÈ9W Ô_ýõ[­a÷{ØÓ9”ÊÅë³ð$ìë‡Æº¿ÑëŽ'øÉ©Â•Óòõ{Í?ù^á×¾ …bcc»´vÆ«A„Ûïך¿û'°B ¤,txùW^è{ãGfì©áñ=ëù(°¾z¾”aØ´À¥?H‘&=?{‚¨ºÓ?lȶë5°ð]š ¶? ~IBè—®kIP‘:†u[é¦@d¶SºÌÙU§˜½gÕvGæÝB‡oõƒ{íÜyK”JôØ”"–dÕ¤­}þ`ŽKÚç’Q´Æ8y2LNsa°(i˜.fX,Àê¢Ò‡(Lè("ðhH1õ˜SÖå=-2$†MKl‘Y…Œƒe0AÁØÐ8¥Œq„08"ýëG¹‘q0@0—À$ÁÊ)eD dÁÀ¢….„ ÷,/#ÄA¦ˆƒJˆòÜ&"õüÇb—”C 0 [ÖñXGØOÁ…µÇå¡éö½ûY§ {àþrÔT-Ô–·›`Ð.ʵ¤Z‹µÇ•€ Õ`¸cÕämè!.4há!ýWqçÐþ L÷ïêìF0Tt­hb49¸»ûîõ5‘ÒQ¯o.ëµX["ë²|Èës Æ&e¹¯öÓµЗ>%ÿó·k5½êî_$ÿݯ'Ã# s¼•™­ÞHà­MÀ_üˆß^j]<<Üûºk÷@¬éÃ,Ϻ7»õøh¹2(&¿ó (÷ÚKÿðûúaÃÑñ#ÑGqÊÝ(Rm<¸ÞMÇ/œ·Þçÿñ&ý'Ÿ‘Y³'}l…”Ä~ãqx¸ArÏ ŽT<·†6Å6Ç1ö†¢ôÓÇß|k]@…éKÅ(+Ìÿq‚·š¥ûú–gwo€æ÷‹´ /©¼ÂR“-¬öÝúöv_*ò>{âת/”·?x$ÿý똶 f#X×1P°Z)ˆ+GA8Ö“¾ŸÄúMw"ØŸ¨aÀ0ÌnëFF" &E‡Îà=»Êœ7˜àQøp;–à‹Ôlí¢h e©È @ÆW#ç<Ìœ$ u̺#N¸phÑ)â,ÆÚñ„ÛAjŦ\d,ÓÖ¹>tä%^.fÔòÕyX}—,3$ò&ωéCTã¬Ñò½ÚM³Öv«;[w’J5.ÜØ`€’Sˆ„»ˆ>BúJ7XŽTcNK§²”8ì Êz€‚¯Ð36·ØR7ðn;ýÜ éõïé=þ•P Zªe¶C 7n&@€IDAT!4sþh³Cr:d}·À®¤ÂÙ „„D°3NeJ+¦W-®f¶D ¹1üzGüÖÔ'ÃR‹ßúSA6³ÛEG¾Ú¿ÖNR/kËM8%´¬Tƒ ‡C£«¿ˆÑL´øq2ù…¾çž”ï¾²4·êÙ #å¹f—Ž“\AÏvö÷¿qÅþ膜Q_9§EñÜtræýÞÇXeö•O🿇¯.«¼¨ 5ãÒìÉ“}Œ$ïßîA­¿„uJsèÐDòùçƒ+ ÿ݇êùœËIL«Uæâ5¾tfÖÙOîgµªŸ®‘IdÞÑÞÀ€øäÅñ_¾µ‰h55õ§Î¶Fƒ¾Ô€Â|¯»·¬¸Œ] <• %k&/„°Ð`{7j·¾»Ó—æº&ÿjí…Zó£ÅÖï½j‚ÎT gsóyq0RÀ4æ!fÀNÒŒ¼©²S!L%zHÓyJgwòí8ì+€MìÁshÏdHøÃ²SõH룶×JòøIÞ^e¶a£G‰Ì,šg8Öò0EÒiǬ7áàŠvaZ! 2£= ÐKF[ŒËV÷j@iB´!²z™—K9ÖÞê‚Ýx—Ú+ÑÝgÌîCÎjõ؃Ÿñ^ƒ`N´6 ¸¦5ugˆÁcN‚ó&9Lé]Àú&$«X¢êH§­¨u¹¡u¬5ÌCAœ$‘ÎßÙÌ ÷·Ó¯ô#-Éàž¬ô•PIêd¶ER(/·ªéˆ´Ã݈_UJA,1BK¡UسKõ+š¤¾>úZ£ûÍOËO¡åvtõOÛÈï4ûzmµ™gAÚÊ90@¢‚•1÷VÀ¡¡¡úû1º]~ôQkø¹òg^²¯¿I¢»dáù'úw Üߎa 9tëøxõ+äÏ®v& _½¦ âÊôš>ùýËEcÄKOâ]wWïsíü¾0ér~'ëŽîåôÓÞÉ•ÛÉé3|eFI%&«Þ'öèŸOûïÌŠ÷¹±‘ÌZ iyö›Ÿ€ü-óo+ê·‘á‹ÊÓÇÕÇ?,ÎÕýû¢KœÕEq`ÌÿÊùîO_5„ƒäÁ½0qíŽXévhÏYêù©ÐÀæ#5ßÇj ;aó·a¹…lïþ´\•@i ¸ö´/ Š1ª]htŽ¢¾Aœç ·$`Œ·¼É¿¸Òø[ÏÕ3IìvõçÝ´êx¨(ÚèÇW’ AÀÈ¢F³.oN)ƒÀà²e9€Â!€ÔÉŸeŠ‚Ì‘jƒ" "ìÄ: ïQwÙIeá¡'¯KÕBÇ¥ª2K±r¾‰-7¸-³z04ÂZ¢³yZç,„{î»m4gø"¾rÄ`+IÂ!T$ü‚Ô§I^)ôSØAEp”º^hÀ†a;·@ì¬2s †0ö£>O%þÁGéSÃå‘¢ØÞÁE¬¢>Ùìc†ñ¿×hô ¬‹\ ð½\95ÜÎ5Q`¬0EœQ¡•¤ 'A9Í85í Ï6»É¥_è½5ºšyr«óÀL̯ÍÙ<²[y<ÏséC ³¬FÓ{*K×wŽ”`£ËÏ=v6£[sI%q?¿Ô\¿]¨’àõ`Îó»º]ÿîV8ù«ñ¾ j ›ˆ ~¹XùhÖž› ONæg<˜•ÛëÞØÞú/oå á¹ý÷í[Wó_ÞˆœƒE+¯§G{çö±KsáG‹zb¸“¤D`•f°«æóYýÿÂ|ûm;È¢¥‡¥#gáÁ¢»ÍîìÁ´v•|ÕÿÆãÙ¥÷C^0ÝÛ‹pä®[÷ZëÝj g(€ÈºÕµ2VS~Ðd·v`¥cEù ]dÛ=ð×kV亃 ³®`UŽ §"K)Ó €9(ÀÅÔA+µß¹ÑüÛŸ, ›¹ÄޤqêZ;0\ð:½Êë—:˜3¼¢aÙ¨&r©cƲr Hšçç¸`Lsw§ - €j{¦Rä;*Àadæœ~ßZcá *Ëc y+WƒQPb3Ý FKì!pÎY¥©ƒ¾•x‰Î Q°†änÌ‚¾ÎGö1Ƈ­3bƒR's%ÇOk{ËØÕ õ0ƒuY‡‰j•4PËØn8¼ŠR‚ B¢Ó^†OŽ}µ|{ªXúäf Œ[¿¿÷úÖf <‡;`o[t7•ŠB u"ÒdÁZ‚b¤³L1 Ž@®ÑvówßPS}¤Ž¹ÙŠÏÜM½ù²5+C mó :1ji¯9F÷®üxkÂ%ŒAc«þÊgðöNíÒÝ!à?~k}ýFi²ÌG^‚¥ÅotZþóGݯ?.÷¢n×vu`ÞÛ,0cÎMv§s+á5Hëëþ©‘îåkI®áÓ‡+ôTŸ‹Þ¹ì¾q†o4˜¦ª6Ü—gõ'ÒwÖèko¯ž å‡A^tÐRpqD¿òXéõÚÖh°•É[k¢ý¨Ý¬PGæ/?Ç=Ç.ÖÞßÊ[ÍÌ?8ì©ôCª0²´¡Û€‘Pr”R™ó¹<~ª?ÍÕ¥mPG'Gqów¿I=šÀzÆŠ´$d×% ÀS$75H?yž$‘Œu¼[[}¯¼| A€3§ÂÈkw6(f¿q1®a+ÀzU˜ ÑÂ’û×o$½­îv:¶Þ¤> Z2# (dŒ ‡4m“ýƲRz-0qÕ³e/ì‘JS›· ƒ`;Úk!À.´Z8K3áªõ0N­;Œö<ß9h8V€0Q`³FapØ ˜tÔX—¤ÒŠ#GÚL”Æ€vJ¸Qĸ ¥®ëäeÁ2’­áÞCŽâòFn!Í LqUŠMרyZôãЂÚþŸ°ù?<_œÚô É ê ¨té¼ã½v3óÉ5í»Ì¤ƒö?u~àÄ`¶»˜‰P?ئo|ˆgwŒ¦|P’€nQÒ·ˆR¬b:¿cÿÙŸëÿá‹0wf÷ûWƒÇûòùåOP;«rä½)ø¢rR;ò¨ùh÷­«‹z¤vöœ xüÕÇI§­A IkKò±m¹~j ÕË!SmÈ$Ïœ81¹Óè„EAè°ÆY7ùá›1pxù,`«y_ x:WGçö—~öq—"¶×Û)ÂÛWì_}¡°|ÏŠCCÒm=s<»´?~ƒùEƒaA‡Yç‰øüÅÚÞK²¸së ÜZ³½Ùuà3¯B¿Ÿ~ó‹}˦ö}4›öaù´×wt¹ï=žKÀo !€5À­(¬’®)¶’}µ éÁñxç_~’-20¯d;È]&¬‰¡@ XŒ7Ýç={†Ö%Ü›•Ÿ^]¹Aqg& #?{°Áxç›ùý”(lxÆiiq­ñü\í¬FµP6²f€c]j5·ÎRÓÉ`2èÁ Û= a¢¥Ô«#ݽZti1ék²í¹ªaŠâ¶€‰tˆP!„Ÿ0«TÎ(d!ÚñH‘{ÎÁÁ…“‚ó3 F[„ˆ`Â)3uµì:×3”cÅ„'E¾^äYœ—[z4£ÏAx‘äÌ4KŠë Ù<£L1I”Ø–tJž ´Íêÿä;ç%zÒW& j>Q(ù½wØ«×U@j?ðM*(¸èåS}GÓÔðôÞ–ùùÇîѶµÜ:)ÐfªìR}ž"ùRþåàï|šÜ?3õþÇsÞ ñúò¹hŽQ½ ðtZ‚R•óB9 §f*Ç&?ÞLúÉù‹ÀQúõ§ÒF½:»Ó*šòN«Û×tw×* —’örÈDþéO =9¾¶Õá}üJ@V•è‰×>È’ÏŸL o bxgqË’éÚ[ï7†'Ê9ùõO깸º¾lïÍn¯æ«ëîé#¦¯Ï„#…9r+í¹åÍr9h=uÄØrâÀ×gd3Vj8½8>ðÃû½¦eåÇƇÿŸ$^"›w¬6³@‰o…6%„¯N'¿ù…Ò'†1Ö½R-Ù=€Îº]ÃÙíû2Áµé‘ÝõÀÎÌ“[s|§îdìîŠ}í}ñêeµÒb2«)ÖœòÝ öéH~BŽȺCÄ‹±mñìÁOûgƒ£Ïë…•b¾å|NA#N€7ï$PH­Û±ü}Ç(ÓDQl{eoI³¼¡öNˆ]'ä®#Ñ®£bè|r`€-,±ÅY©K>g¸Åÿ–‹EBW••àÀ)Âk–(ƒC/ÚpœL^úµ¬6гJtSd~,%ÅB÷(rXV¦‚h¾á\¹áŒÂ-hßJØ@žÄôò|6³¢âÝnÞ™ãÿé’½|W#fŸU.§jÕJ:þ›ŸÒ¿q.®ìDeÑúð09wß_/8ÇC—+‚-¤8œæ¬b„}cAüƳ]r¦´÷„鮉7ï±&Ï‘ÂEló=ÇYÂ4{é3d!¨VÉæn?1ÙZþËËşΘv“Ú4/FåXŠeß=»¯òþB6ŸD\ª]÷7~Ó!£V@àöÚ.¶LáÑjwß~îž”*Wôê Ô_ëùܾ~íÝ[ùÔ)á»ðA›lnô¦ÇÐ ¼´¬^8™ŒE8AÛ³¥™Í4FãËÛi)ÒOI]¨³Gò+w’Fì /Pïé½£?xÔÞR-f&°7VÚ‹÷û¥èæ"~´tæ )Z!½Spd”d ùJ¨Ò6ëòOõ«ãÏúì˜wh4ýŸ"`ÇÈ5ƒ ­2«ùÔì)e !xyòÛ_OL{e»wP¶{ÇÔõ»:¦ƒ{¹=ª’uÏ<œç×Év7ìöøÃ÷ƒËé.ÛÍ  ¤2Æà*H5uLajá„0ðL¨/Ø‘C"v.Gh•‰•ÇϳSO™óÏÉõÕ¨Û24Äaj±õ¬öa¬ÑŽ.vÝÉC4dD‡v±\O`«Ov—C'¼Ý'Ýðétz„mÎG÷cØÚ4hQø aRø—?Äþ†Ê4‡áœñÿäôá}ãŠö™µ ¶ñ ¯ÛýEõ[çK{Š WNJLë‡c§yäwšEP¾‡{†û c®À“"Rµ˜H÷Æ\ò«O)vÞ;x>êmµ_»íZÈ1gKÔIÄ=¥öR…¤þÄ‹ÁÁq1X-ì E½ œou.]™øþõnÜ¡<€…4ÁÖOžb<‹½ŠPùDIÿí¯†'CÍÇ7Ðv2ÞöÁ\ºk8øôKE#ón^¹• WSÄäO®‘é=ú³§ùÚ À|8ã25xw;ï¥Cßx…À³÷Ù›Ñb«ë 3èÁ§/ßû˜Ü~s(iåŸz<üð®Ls7Àª^»—‰jØ}w—¥íÚ‡MssU¶gÔʣΕ㇠l;-mw¹ó~àRõ˜ uÆ"&>{Aª$þÝð°­l¸fHPâŒ#I ^TÜ]jüÖ—PèU×»uÖ?Ð$L†T>µk#y}I¦"?p–#GÕfOÞÜ-Èk«n¡ ] [ãajsÔ¤œ³X{î(àg@?ÑÁØ'`cš b°„ª&ÀÌóŸcýØ+iÍ߸Þ+xöß{ËÚ„PëP†!¶8%.¦oÍv”¸KÉ=GŠfªÜúLs‡¬(¿öTÜ`«ó¨V5*n}d[»(u̽ zésÜ€ÛNý¬WÀI?±S{ØæG¢$07ŒÎÁXçÊ Ÿ© ý™¤j:Ö*p`±¡ÓFÇ –Zpe ¿?›Í,‰<ÖUßlˆ£ÛZIÐßxʽüX··ø®Ç#ä—6ºÝRTݽ7¾7'Zº¨”bˆ…‘Œ¸ÖÜàqÇÔo=d¯œ$}ù«o›vVš ,œÖÓ…b®3åó/¿ða:{7Ù¼'>\4u‰;B(5|Ò­¯ðÉ›Ô&˳³Í×@þO_¯Ì^ƒG¹¨í.¾÷Aº•u66üëO¨óEÕa±PþÎGº«¡•ô­´ÂOŸÛ94h,9ίÜg"x°%Ú‰÷'™J!MÀsïÌT6zTËaj^~|×£{êƒõC×<ó˜÷þ}-râ`‡Ë7o%¦ê©Û{’Ç+R¶ÅlÓÜ\­{ùÚl÷úÕìÁßÉKÛ1á‘@Ê6U1Œ Œ”(òÅó’(ø_¿“ó (oÍ™5$µƒÐ!£ÑDaƒüp2êþõ¯D%h±µMúÂwB+¤äôäeêÚ‚2?xž"š‰Žº½š¿¿ >^G‹uÛ“ ©5>¡s Úm­Fz˜›c?iÔS>êË82FBb`š– Æ@žú¬ßÈhMËÅå«2’º@èïûòž€ ‡LÇY ÖÃ@ÕÀ² ê €îÚû˰ÿ0­\âÚÃÚÓ`lßÛßÍ“[ts7³Š°Ñ¦Mî;³mU†€;Ð ­Ûì!Ug(G¹Ü{ø3¼„ã‘{öêÍË2ʱ`œìsØ–4?^4û•å„RlZ` ¤0sÄ`$˜cÖ¤¹[k¡«kpéQ~w-o¥ÊÜÙÔCp׈Ìê¯>é^|j ÙÛjF1Âyi§•Ô±½Ƀ¹¬'|£V($ÔsÐC.¡–[2l(±ðΜyéX>RÍ^}:ɨ 5"ïxOÉÜ®]¿Üýè}u÷FsóüåœÝª›0Ëã\ß¹¬ aí@ÿì£ÎfW˜úŸ¾R{øa~ÿýÁÌ™êöÖùºh­v×…o>MÎÓNâÂbäçr±kòV2¸Ô/Q‡† ùúS—%ïÜ]j'=•ÂÊgŽoW*rGõзÐÖf?vI‘ã3“úÎ÷ÌÁÄÌ­ù“¼2–\[Ð;™]žm"Ü2ì•óú+Ÿ«Ý¹iz†n{¼-½"òŒçV„é&jg=Ü]ùµ_ &ûÚS‡HI QUS ÛTˆ€—‚W,¶›*´lì6€±„c–ak0‹ ‘ì›ÏùûGó$éyƒåÍ»°õÈû# ™ïä@E½ßæö ·[ÁŠz¾í0Ë53ˆ[åLd M:rÑcà‹43¯í 5-Zfš+°QØÈ¢¤Ð!̯tN™¢­öd6뼆n9wZQD Í8]$ù}ÏÞ„’'ŒrU6t6ˆkKÝs8ÄÎyÙú#˜l‹§ßpém—.ƒ)¡Æe‡00eí &,ÐjZÉÇÏðÈ×_¿+·”=cEdÅa2Ô{*ïù!‘Ó és9ÜÆ k„)æ$A &(>æ‚)ãRl˜­øö¯<Qg­­­\³½¶=fÝz‡ Pûø¶r$gKd%âVãÜ9.pX)·²œ£š»~5„$Ÿ²©qÔ·‹?q¦|zOó‰g¶lî^½ž»Uåñ±.,¯}ðë‹àw~+â"¹³L"+ç6Ô£DX¤~ý)ØŽÜxÃi'kóyi¯~÷®i"ä잣ÓÉ—?¥ aµV¯¿=;Ð2嵡ê×/tûJ£†Vœê~pop¥¹ÑJeà—_>Õ.¦n{prO÷Þݨ— ‘ˆ ““pCô`É횊÷¨ëò­Ü­.ǃRÇ–¾pÆ~ãK•ûwM#ÛœõÀ+ØÀp³šÛv,wÖ{µo|ÑÛÝ_ß{p˜„|¼”„Ý4ÐåV;+Ñï}GíÔ¼‰`Àêc–!c €nH¿þlõØX¯•Å~Í[›!õYS¨Í™NGúÝ{w´D0aÝn‹«ÈÓÌuˆƒ#ŘcŠ1ðË,2.w€0š4è8ÆÇŽø¬‘û@À^»­b§­Æ¬mнR{rÔù~¥ëd<¯J¶’¨ô¡Cm Ú’á€ËÌ3}ßÈ›ìœyOœŠ}Œ:ZÇÀ `mlÝwí|Ó¨ŸB:Ù<Ò ¦à€`Wt ;ëj–ìEªJÂ^Uî:M‡¢(CúÎM·ñp¸„$²Zú®ëõy{Óz*²˜ÕœÙmÜ à2PcQ¬F`±s&ˆ(Ð@Q_# ¸ãô¨ §¬©{ˆL‰ë¿ö‚+c™hCLuéºIZ¶ÿ@¤:›nkÑà¥;b[,ˆ`ˆEóÔ¦àh®ÔÊæCÞí[%ÝÛfzzÔÝo/ž>6Õzò¥Êv7˜»µÓèÚ©]à!YXž3WbAÍ·¿ý›Q‘Èëó¨ òæŠ\LuêKOÁhàþ;vº‘Ï/$ý‡õ͹ÂvO95¼o¢ùù—q*ú ¥N/Žß}TnºÎâj 0ðµs¢¿Ï§ núìØz°…@Á@uƒ>x-î.«ñ“ò‰ƒrù¾k9$«6æ~“åRö¤TB_>æÎÖ>^îŽq¿ë¡÷ÄcPEñÑÓîÕ·dÀvåkõ’")@]ˆ2 ·6©,=P¼õ †â®3b¼h#Ùº¶Öÿ¯¥8ls» 96Þx[¶‹1 Qo[ l=ŠÄÔhneÅ'í[x7%gîl•O~&ì$º¿ˆŽŽïϦ+ÂLr ²÷XFÊ߬TzP;—é Æ(b´³óŽ9ë çÖ#vøoô€õúÄý·“úÛ<@zÇò´ÒÄÁ®ɯ¼Ón®H›ù­ÌH3§¥1(sØb€¤ °³T[$õz&JxIÈUŽ5WÀœ% º ¯ÅT ß ÙAĪ̂ `°jb `¡ 貋JZE »úãîì;z±†¼(®®ÀV0ºÓþͳŸ’½U¼>‡n_Æ'ºv¯…iËVz‰E°ÀhY2¬¶Æ5`w4‡C`}HËî+¦Ý U²¦¦}… Ëâ9 *œ> •öŒu"ÌÛÆS F™¿isaõ*í±B…µÞ²÷¶ðƒ•ž»­­MT§7ÛÝÙ¸ª{SS^ŽñÆÂ–@X„¶“¢D„UÚ u•»,5ðÌYRu½'.¸+¸¾U*ôb ø©é¾¯=µswnÁ( 6¬x•,BÕm?u4½ÿ¬_MË…/ãÕõëà [Qz×XCْ㾕V¤(ô¦mÀˆ0ìvìácÖ‚Ĺy†w}‚Œí'•²]¸”ϿŠGmôªÑ`4&âê»­æªUµ"#,c<3Ê×|‡0ð\‰Œƒõ wA=Ó=\Íò^?…HEš´4$¤ÂˆÈ9®ËÀf9FŽPÀË&PP–u<ÿ#Àƒ¹³©»þÃxaŒM?Uà^!é[ÝÙ.<Ýs|àT|þeµ³ã-?ð>ÔGšf/ ½À¦Á~Dí²Â€t*®*@@·™âNçèX1c°*ƒàôd8VVõ–ó*…¯ôP,[Ø–ôÌQHÝÕÀÌÏT‰@·O£&M\E¹6A[Ô"e÷ Òfv÷ÛøSU~e°998²¶“ÍÜAý™Ú{2_m/´-”2¬ÚÚ™_í2²vk'ƒ'Ÿçý8=wT_™ 6—³jÎ7µ}b¯÷—ŸËî?\ÎsdÆJ秬g”i÷Ù 0{m\Íûƒ“Ÿ.ŽV¶z«9VØÙµÛì¬VÈÄœq}Äãáý%‹€ï«É©ÝáýÊ#"™]gSÏy+éf‡”ýúÅRÐWØäɱ£ûÓ~ó‹vg[¹†¦Rf¾÷åÏ n»:s5Û0ZYÊQŠX45  NS@º€¹‘£åAHÙƒ6ÇÖ“‡==š ÿäÒZR§5*ê·L®,0L»‚ÇœG«.Ó”sîž>¢CІæf1[õû8Y½}çCn u}©øp;H0Œ´6Õ9³XKåÀP…hF¨ÅÄyæ¡À?e`ÜJ‰d‡X`á:'§_è•H„]¹IõÌl¡ÿ@ÒwNœ¿èö çt¯¾g&“h++þ˜¶–|?NSêhäd,( A…Óš¬k2¢ÓÈfÊtNŸ 3ÏYÆ€Ú¢Ã.%A–7ŒqÚ/ê ¼ M‚P‚ˆµ\Ž TwBì•üÎZV²óûô®ƒŠN ’Ÿoì15R¢ »ÒÙ™²/l³zÌ8ðQâæv˜u’ÅŒ¥;íÀØGކlQÐü!޶Ø7T:µ7çá(¼õ‹ö^f®`+jÏ~ ©ÝòãajTÁÙ§Q±dÜ*6 H†ˆ1Æ‚IMÕ< 2·þ+/ õôÚG?‰w=ŠW•ßW[o/?lm‡.Î6ÅPb³Q’‡†úáSO”n¾g$”÷M¹î›A§Á’ÄìWû‹ã•]ë…ÆþÓÅý“•7Þk×s80.Ÿ¿X~ðc;ÕN×”ìv›Ëf«Ù¡÷ÂIÛþ‘êÎ SF¬$o.„ Ó%84=zµq@$ ›ÞþçñòjºÖ’%_¢ì Ä)w#‡¦Ü ûè!º·ÙÅu;hôVÈ¿ú)•tGï]íî;À7V ôtºk©‡TR§íHyHòàÕÖèš|TÇO¤»v ¾þ~Ú[«ô1±ÅXS €cÖ À=n½Ã¬ã<Ã^ÈìãGó2rØgk¬[­ Q¼({SgýÀvúÖjåþf’`41Õ ˆVÂ!C3ÊbʱŘ#Ø{ '-Œ!Au°s„o1vô¥^‰DL:>ºñÈ8” ž’g'{íÙÞÇ—ìÖ~ŒK¼‹ŽÔ·DbM d@´CEÎ+²4!mMfegrÕ¹pkŸ&žSˆ9l „/¿ßórÙVFê Ôœ{~êœõ1²!ÀŠX§+~a^6tÿtNﬥ´š?9%‡épÀj¦W:Õ='²Q¿†+ öV®GÌ¢.Qܪ!§G,%>¥n“X~JYŽhÆv¢(t±ù/n¹o¸pz*шë"¿ú^g·*IæµüÐ~È3ÝÍÝ/EšÈO@¡áe¤sb)¡ÀjÓ²bO;SNÍê+Ï ¶’ö•Ÿ%“ÄÎbÌú‹K öñݼ呮 ˜c„biÄ0Ë"ãúJðòSÅÛ¨žˆŽÄ×çT”Ëìõ6$ëëçûÆæIýȹÊþ=ÑOÞIš’î/=Y{ðC´¿Ó]Û*I²½Ù[oTu/­ÕBsíORò¶«Ú?I~z=Ó\={` ¿ÔèÜÒ†@—…‡O£À»u¹{ú@‚ äžÓ7gèz§wu™Ël",¬Xò¹ó»ñ“,Zq±$ù^o~ž|µ®Í2{¾JºÆJ™×àÄl%…Ê9ñg¯ÚµÅ•èšÊëEG2dÀ¹‹Ö;ïB JP¹ÚhôÉó…º&&‹Ý¥Ž=CkCz™)±o¿‡Z!Ïx)}Ÿ¹U)ë¡;ãµ¶ê{/H{Ò‡¥ é À8¨¸M1*È¡qÁ$ û{ÇŽš}“nxŸU ÎúÖfó±¦Lpz‹a”;B¦¾3Ô2T”;O;W0æE3ÎÕôYKöÓâ-ù©Vœä·Ô8¡.Œò.;Ör§°œÏXÛèÀ%âÖaËpd¨28ãâÝR§ýäìÓÕt»¦'ìè=“•ûe©Øõæn8q“We.w´ßù޵Ãyb2‹4AŽ;’[·v cnØ}K/R¹øÄëK­‰JpsYÒ‘üðSˆ£œz[Œ¿q5‘ b˜Ð0 vni ®lqæ\ì9?÷"·Óíl¨‰=bûm6† ]êºýöÖ|§“è–ê…2 êWˆD[V_Àá#‹¯ÁúýØÂöxïÌêa‚ÛξóÐûåå438àdò\åÚ(€0`ל^¥Ø·ì^а 3ñì)J¥‘‰Šhf!÷GòcÑÂ5±ç+Me²}öQoaÈ™ufsr ÁK®ÛÍÌm›Âí_âšV *%ÃêÎ|ÜmCWJ qNr㢒¹+{Ú§÷„w­?ÌXŸ9° ¿7ï €n óîJáÒ‡Y/Ñ…|bL¿óþ­Pëà«çÝîÍßÀA.º.8æ!ì}¸Ô"_ÿDøàV{°EÉ>‹w.:’_¹7ÔÈâÇ÷gOžq¶XiÁ‘óåj_×(üî=ÑòoÏö¾õ¿úÍemü‚Jöº¨¥’êð·>Þ½­kkr ¹9e÷~²<¿ Ücm™ÃPÅÈ6•;yºÊæ;Ù±'ÜLÓ^ºnʆö°­{eœG %H;Dä Òmœ !ºÔ:DXrxÜHãGžíÛS™¼ÐW-µ1²”¹‡½×/åF›L+aɶ— ¡ã Æ$PçÀ}M¨ŽgŽ\qù,=ÂËÌ:ÏÆÉ¬_ecäá‡îúÇêà1K]°ÚQ%ÍœT²V‹ºu–º™á O9¾è¤uÈ!£)°„hàæ´p vÁ4ãSèÁŒ¹ò®Z»]Y¸c-¤Èâã³ñAWq+W%æ•‚8‰A[ªC`°ÓŸrá¤ÓȺÝjÔ#û3ÙàÊl×ã U(ß~’-O°;÷ Åf»b0v†aºNè‡NoZ;ìÈA'L–{°ê3AÉx Ý#RZÞå#ÇæÐÁòh)Ë„é«Á੉]S~±ëœhn~vEά˜"à ¤ÂyMdck …²´ëh€EÁ³wòA?<·oàÊN«2‰£ƒµ·¯¦Ø…E[KU[ë°À2Žž~É«”L§ m—ýgž"³íB}«W‘2© +ºõwÉ®Øë[°“ÔJ*þÂÉ ?Œ½ñÚŠïM^Ї©õ†úðQ8Ñ/¾ü¬´†,ßõ:N,=ѽ|?juó »ÕS祮ҹ¡Úôùh j=WnÉ„õÏ̹%.?â‹­ºõŠE”î¼%’â¡Âo=ÇÝó+K½KŠî}!š»×‹3Ò¥(Ö&çÊ A ¡¬)áô™!jå|šŸ8.tùßO‡¸×‘Ð §DnÎh˜ðÎs {$¼N‘ÐØ§ñ¡IŠ1Žúwû»/U‹ –q7›¿ö~¢µÎ¤–oñÜ8(8î9?¥|}Á¹¯J¹ßÒÔâ+ÞGÊ'¼ÏÐY %o„ÞùÈܸ¦q-/'’²~ÙLI9ÝéY·…§[™9Ì45c4r€œpÈRGÖ>œÊÀ€=û¥Âؤ˜ØÍÍäï¾/w®—ï£Ù…ÄX|â<ëÒ}vé6!)\§ZƒÍ©³Æ*ð~Áñ½®è¬7æž‹ða1±/ÎÚ`ýB«žÅ¡yëU—®1ÒçÏÜ,ê‚CÚšÀáÂß#j˸ ÀÓŽé\RØä`¬ÚÀ:k©I™êÔDšžtÕ‘éÒÞR¦…­”ÜÈéÁñi¿âIió,¹ ï«ò_£EƒEkΘӨÅÚy€S§—DŽ>(a‡‘®¶k[öìøhi8cIhFq⚃µ…ê¿þV½Õ"5§Lcª@xˆpALÙ«>« gœï¯ðü•ïX½æ „2¤cª‡Íà’jl}`Ê+ÕF—&l­"h†E>è tíZ€jvÿ‰ÂždØ¡ûN ªŒ´`‹‹O[9ÓðÃÝÇϱ¦»:^wµhØé@*•p$¦1N…Ú˜)øB²¬BÙ¬“\ÁÙ ŽØ1ðÓÉó¥nî6ºá‘q¥&*Ô(S? Ýz€¶?è3+äÚýžéÉdp•´…s{,{ש¢§1Q…‡e0%qe›LjL¸óå=– âÕr™;²´Ù»xª@¬)®Q3²‰ 0»²=ñý7E"ÍtàNrt‰kVÄ`=G 8Ã18:qe}ŒîÏ{ýÇzNÜÏ>¸Ózn  MbcŸ³Ì’¢ÓÃÄ'B¾´ß~æÎ(\k¨`¤¼÷¤ÞU‰O £÷±IÆ Û p(i  º)ÏU7Áð‹‡Ùë·Ìb¯× e‡³j6º¥Ë+Ù¹ivrWÌv÷—ކ#-߸­†™Û„³#Ó°9¹ÓMoÜ|)ùá5ÓÀZ€¨wmÒ÷Y¨”3D5×Ú ã«v ÇÈ‹êÝà¾Ë=V~|o’íˆÙMRc…U„”!®·åA7+LWëŸy?‰f…ûÖX#­Óئ²Îkƒ"å| Ó‹6SL2> Ý[Ækí¤wí¨siB¬ŒU¡Aƒ+ÿæ{;õ<`mŒPì'Ïy)‘9{œþr^8oœmžßdê-gÖá¿xÆ ˆ.Òƒnx[Õw>2Þj¹Ñ楾|°* ˆë©Ãœ¤Aõ㋼ˆö-6ĨeóNW\„,’Ö`‹>ëJO8W&*¥Áà ç§Jk¯Ö·“MDÛhCe`¤4£Œ©WgŠEë(ÛbÂ")ÚÃ,îÏŒtdq½÷øùª&Îä° (ñAç±¶1ðŸß×I»‚âi ‰3©¼UCÏysEüØšª2)W;3û_ÉB×î¶/=¬l»”Ñ6-xùÿ‡ÿzÒ4=ó3±ûq¯ý|~éMyï««Úw£ÐxÌã8ŽCíJA)BA­ÈE‰A)bµZ#1V±¤Hb,Ä 0h˜6h´¯îòÞ¦«¬ô™ŸÝcŏþ‡ëèg.kªŠ5ÑVy~—}í(˜Ø;¿.£±‰ýgõD-9¶Ëœ{òtÔçk…¡€w€f+´¹!Þdzé>T‹ƒ$RÛįwa{à}>ŸÙ78=cˆ¯J»êìÊòàý;äÇŸáíÜ)}a©ûËöÖ¼œßr¶å:¤†/S¤†¢åÚ±%ô$ æÅ¾ßÎÉ•5.•Sã½æî±‘†À¶kTææuž¨˜€Oé„S}ð‘EË»J?u¬˜Ýûá_m‡µçßEEb.]9v©ãP8Çyœ9»NpAÛ®W y’ù~;>»ß©Ä#M]®ŠœŠ ¢³ýÿôNzó‘G eÆZfY J¶”yyørH^ðmU™ #! Cg:! dŸ™üÈ Û°{%ÁÜ ¥yßpG&÷ñLˈ•˜••’­í”‡NÉS‡£KkÖmªç€NSìr·Î@Pºô1â [“Ñ ¾¯©ÊÊr¿Ó馫P‘±HE9Û™”f‚.·¤?´u»#Šx äªÃG4uû }Õ±M HÄo¼îïŒ43“Ú/PaÜMˆñ¸ÿà‚t³IB.ñZVÄœs#?`ɬs[„¦‘¤>JèN‹’Œ·2sÒ‡°9EDD™FùZɵ ;»¤†cob‡ð€ÓR ½x?ø¼ÙÛ6þ(ÏJL-Pñk©[2äŒÇè %¢HIíâÈ&&›jŒDNÎÎÙ™‰‰f¹ó—oE4ã¤oª‚šÆpú…I&xÓ–d³5H؇ýû=ÙñXŽh‘†Ø•¾Eb=K Ö±’[4ÄaŽyßî˜Ûwô/ïëÏsv¥e~™}r—Ÿ›O>¾—|x—ýè3\Ø&ZÙK+é;³æÖ}˜ÛàÝ>ô¬Ó#ø†i*¢hF¢ ¡E¨+¥Ò Ç.oF©ìãN]®6xJººV^\Æ$Ñ>@Hkã6í!d¸âXk=wÜÞ[ÿë´"ª­œµÄ” „I0 y\ lûP²­Ø’2ÏmüâƒvX­ŽTIµ",³^9¸?çýÇwò;+–‚ÍZÇ™©—Áªª¹xYø/{ºlÕ€*æê‘Iw}‚+—MþÊT´.ç˜Úæ1H"ñ¹7q (dšR xl•®Óút~øqyìˆwkÛ±Íü1&vLÁ®R˸›&ê„5Ê–ûQ:¼¯¦*Æ ±Ýé©Gª …Дr6ݧƒ>±8hlÞn‹"ž„âJ†{){és„¥P´÷_}=ÙÝÛovOhÏ:å6¨˜(ÊùìU×m§S>-¼MiCLgéØ1¹ï쥉/|©RºÛ`Á†|Õá!}œØ2ÐûÖ HŽè3.¬5RÖ¶öþüð™AÙ8ÏF/Ü‹þÇ¿KÚ‰W ²šW<ôü Ê,0”.ŠÜ‹=›kU °k*vËØñBgï?Ȧ&†&kÙß*ÙŒ÷HŸÛhÊ¥…гÌR/ ¿1‘6ã¥|h»ß÷Î/šùÙZ2°:NKî›ÃÐxÆ·BC ËÚ9iÑ3¨ºôú6Þ}ýòžù|N{T®¶èÏ.ãG·Ù'2â_£Fâ ˆŸû¾4“Š(Ј°DØ€Î'†ÔjÓAQ…¶:Óçš G,SÌ£qgŒÔzÉàÌón)ÉÊ:#ú-™¥¹Ï¢'^–KWíìšç@å@¶YLI (@7@h.EM(Âí@2KjŸÖzTÚÚ ?RƒÃMH´ºþü¦”9Â3f˜ !ŠAuÀ¿6iÇ6‘é å…ò¢°Ñ[çPW˜… ñrª­ödìž±ú‹P_ðÉ©$ޏnV&ƒ6ÝjÇë]½w¿_õ7<áݸã-þ"Ùa ûÜû-’Ç‘ž¬rÓ`¬"eÁËó‚ÜFŽó–¨¼¡Xk=–·Al4¹DÜ9ÐܳŽ=ãb‘âŽWÃc‡¥v.1ÃU¤–•‡0jÓ+¿øÂ}:}ß >‚ Pz‹P”%cîòǪ—”iÉ,¶XØ@'F¼ - y%®ª Z|¼È× à˜¡!ÆQX)( kHWXÔH  #H(2>P¢Q9j8©GŠ z” sŠàl‰9c“MµRw`d3£ ­€P1Å$§à ? ¼¡A–>þJÙ=Ä‚ó¶hå²N¤ôÙ/ù‹—‹ù Tå@6IH ”€C>!TåA@¹<×Î) 0ÊhË2ø % õ¾&bZÛífWAç¾%Á€˜u%=  ©áK dCV`Èp›A7tPr°áÛŒÜEYuHÁ ”ڀɜÊH=øEºGô©ß÷Oñ<«šÎ¦ëö‹ëé±5Ï=*—‚ë·ÙƒŸ¤3Œr]°æ=,2Jž`þsày`×0õÇ*ZŒŠ4-ØÀŽBÈ…hé$Ð*i­‡ÂRi»áÇNÂEâ>#žµâ`ò!µ3_ô6l¢GçfåXM4kY\sÐVÊ¥+ÿNìîw.Eö&ä2‡jXJ17E@EÚçbñV4IæÐu*JZ–{L'•üß hPÖCk)–àDäfêb¼dBŠ÷züz‹CQT1Ö@‚ ) îEÑ OÊaÄÁëeZFÀKyæ pá5ÑÎòÝCæèÓåŸýl@}¨Š‹¼,ê^©" ÝÁ.~X” W-™#›iQ¯­SŒx‰²ª‘ÛŠ$Á¨ÌÖsÎÀp >ç¸bFÕM8¡PV¨-J¤P ÄQœ3&µ.„EB˜Ó-ÕEª¹¤„îÊ^j{ØxuÇ €KƒURí~ôozŸþB¥–ö¥IX½Ä¶-ضëCuìêÌÞ`ÏÓíí^¿Œ±‰yÞõ;.úáGTg‘ÅÕÚ*´àÎs„:@B `Ñdyù›oLÏLt¤ÅBO^¼—œû\®›h¼ƒåTëüNÁnµü[Ý̳‘Öˆà³àŒoè"rK÷ àK)¯À†õJ¶&ÕHDT·uož]B€`b`´˜P±•ºhÞƒv?reÍæH¸ôiÜZØH7ÍV¡¦'#Z…¼à#ÓáuÏliD£ÝN„ÂA¦©“FO°+=@€(îQª36N +¹P™†”ïµ®n@QÛá>ea.Ü䮲%Ì“ÖÊàê[ŲÈÃ!Ó˜iì;ÝîˆäAf­®Õ8íV (<Éra  Î8g»ÜÍçÐ ±a­Z]æ¶JµšÆ½ë½ß ý_§xL УÌs4g6)ßNHD! -H¿fä¾|’ϧñjQjzò à {ž·ººÖüOŸm®ÁˆÔ å‚!€ R«·%m¶úËŒû{ëcžWÒµ‡ÕÖœ8fÆGìõB¾ÕÃq€ƒ*€@(°šÉÞxàÕGâ³/FóŒ ’R¾öRÕ sÌ}ìnSÐ2€ Hèwmˆ„3*k<ÎT‘QÚ@‰ç¥˜µd€:€ÊMK¡ILá$MË3AîªÍO4^#»úMZ®›™mDù;F: M•×iq|Jy,ëôãKWØÐ(›ÜÕ J-Ë~ôãq׺ËâjOoŠrê9Èe„|¦´ñíׇƦÛåøÅ»Û¿¾ª7Z‡`WY;§ç¸õˆßZ3ÀÊD PGÖ·ÄôP Ç­x õð†lEÃ7LÚÀlšˆÌòM’/9Bûà8C ƒ …ŠW²X¤¥[Ð4 †ô¾ W>©·×z«-)wL«É)H% O·K¶…„HéPï€û¬l:¥ÀMQÐË}€€)ÀqÁ¨Î)ÈŠPPX) è€êÁSiHøgzŒÊ @97ÓûjŽ¥^¨µÁ•·²:gaÓÖg‡NÅ5µÝ‰Ø½ÂvÒ¸DiRH±Ë$7PD´Öѳ θm”ФeõV¹Yµt²“ÿq-ø°knvzDø„d ¤z­„^÷‰F JÔ@ï/2¹Ø;E©ìO<{xl¤¼©Šd¹5üã [wÖ+hœEðSŠé²(mµºï¼ÛüÖïÛCQwm¹¶¾‰Çf»›xqÍ.}¦ZÓ¦€¤¨ …žù˜Wi6ÈS/D?üóõŠ([¶á¹7`ú맔ˡ«(B— Æ}eŒLåŠ Ë pèÀZ‚– úŒíe|œÐ×léŒÅǵ9há)ë†ÐVíÞ §&n,ô·¤yÀÀx‘/T®RG/‚ÈiêÀP±¤Î'æ ¥_`Èè%ä)yò›Í­‡’ô¥ÌP~Žê‚(!TÀ9(Ø¥äKÚMíùÂWĉ§Â¸Œ~dWÎ%c)îÀ ÄNzã·oKm'¬bLpŠ“ƒ°Bl‡ÙoØ(ìiô8ïݲMÇÊ3ê$³Š@N¹ôK ¦#ŽœðiG#´Ö0îüÝ$)*Z¼;(­„GDÌeþð!,8yX<°s÷>‘ä¥É­u)!³Ârâ‚AÃ(PªœM={È1B 7IÿñÔ&]U‹0iª‡©V[£€ h6ð £Æ×DÜÉøcÄí@·jܼ“õ€þ«o¾pªÓ ’ˆ†°=ÓÙSǬ¤w¶£¡1j¦µÇ&G^: ×â[?î-‰[óÉîýÞ»×WÔ6å½Xêã'Nd@`X¡¿ý\þÂqÕë¸Å W‰84Nc{?ÚI ‡99c‚}^‰Q[qJ1Ö±ÎG-"jŠŽ X°† t>.Øj« ¿€ÑI‚O8‹$ ꑚhcOÄüä®ô7_6Í~xY¦~0°‘#9±2óÁÑ87Rqb·~ÿ¯hó¾»;)W'NƒÏï»Ù«+aÀ–1C‡¨¡ÄGí½v°ÿO¿ËM$<Ì/µív{§‡.OýæÄö£´稉÷Qóà2G©¥ÆAÃnY¼lìøŽæs¯³Çž‹Ëøõûjù\"‡)1â·…†ÊŽ›×àÒG­‘ *[» Øiðr¿LÍݶ_Ó¡Ÿi<ÚG7`¼CÃM+Ö͘—Q,ˆQôxŽ9’"=þqÂfÆ`Ѱîâ½A7 ÖXºŸ•WýC,`¹|´Œ«ÚÞ§NÞ¹ó×ê{3­G:u`Áq”JkÏv¡œê´;^>û‡#ëdeý!=^ˆÝÆgë %2Ï…y†-ŽZÜÉÅqfw#®7çÔ˜Àñ±WŸì×yÂmr±{jpöŠ-ykC0ex R[ó0/:»&'_9¤oÝîþ4›zHoÝIwžßÿÄ¿±$7€u|[×–gH  2¢(¾õœ|áTÒkë¥6F!@¯ü¸í7nñ”ƒ§œ¿Û«V „-|Â8Ѭ³èˆEM€GDZljMŽî{eãèÙ΀6жˆ«: @2ð>¦j–æ™ô±{þ9³pyxê€Ú³l{7ä¨ßî)ÀÑHC Þ›ï…ÐðŽÕ `ÉúTª>1€0ü;ÔxR´x³ãÖ ×1ùÝÉðÎÍ´̲F’¼x´µfãµ/³[?*n?P4pÊv {•·~^n¶[$*UeÉ·¶áîÜvx JÐ{ bÆ£ 3±ïx4zˆß¾ÉϾÜ=÷@ô®Iö§˜B8‚àÆÁMRã1—˜*©ž`  ãL9ùŒ˜,H ß/G9ô(Â$ðmbˆÓÔ@øUÞ%ƒÂDuë^~É<ºÑÚaáç/Ë‘(ë(ÀÁ˜®¯j–ÞŸïßÚ&R†UÞjz¤$·ôñS>LªÍ;Yî8pÎÁdÀÁ*µ«üÖ—j!ÒGímV."¿œt©éѽcÝßz–ÿ·o©;Y}dØ$¼§Ô ñ²L•XàuAE^8,2¥áš(7^‘/2¨¼7†¯ý`«2€!=FIA}FÀX*€* @JUdûyë¶|TV@À'üÏçcÝí9HBðZ×èÕ+‹eK­€Vr‰s©sm «Tlq³F ¡p@,‚M>ç,RÆ(q D6,Ì Ÿ$ìÿÏs æ`<7Îõî_Xë& ÈžðËþîC}Cik  <ù¢šxÂÓ¹q@(c¡!ÚA` F«ÎnÌUÄS߀½÷å§ØåÈ~úžÙ£ÕSCÞ1z@lÙLê.Ñ`˜zß!…1¼ ÷Õê²#á7¿£»¶»="´Ç67je*Íòë_ñnŠ[+)ó€¡ ýB—‘Œ„Cÿ³öF?ÕqÉçå<ñDxu¥¸;«{ÀŸkÙœf,NXŸ ›‡ÈÕ{üÈûŸ>bƒÈ?Bx Č՚ 7n?3†ÚÄ58‡Ú‚QΠ0ÌO•eߦ8D14¶J*Û·€#ÀZë¬a[’0f¼`üøðØcÛ.ĺŠÃÑÊ-‚„I;m¢&ðW-b¨ó8„†øX.Ü‘%G?wòãû‡ò?xžyé°’Ä>5™>\s½1$¦LÎßSÀýp  d:Òè÷É âås³pú¹Úù¼-qÇÓÁå_Y”RÖxÌXSQBœ"¡ÇåsO„s¿¬]4ò¡cs³í¸,×MCà;rÌÛh眬˜ÑàYékø–”‹6¨iÝÓX¬8!œ+‰¬,;Yq°íø;LŸ'*Øé‚  q-˜ô?÷Âx”Š«?j-?;Ž[K…Ÿ3å¸#¼ìyD£y(´–Q¼g,Ÿ{hóŠ·ë¹à'?Ë‘º ”YQÉ€ g8 L1 Ö~û9q|4kçéÐTõÁÕÆK²ÚäQYSÌLñ;³v)‹ˆSÇHP·cº¢ƒB@h™H‰›ï vÔ·f»Tê;õju‡)«AZLe6ßwoÉ>tfÈ@QëÀFÈ"€L„…Ù´ôMÒp»Éè#Úµ4¹«ÁP€F89Ný&@àAîUnQz“ωû5ÃÏ©½Ã̲#]˨1h‘w^€>õˆ5Œ!7€ÿÀ³(xÎ94Æ×BñìMª®ps•À@—ú›~è;R9j`”x sƃ"lnêbÿc´ù¦âß^çªÎØÏ¹SºgG€÷Á9‚Æà ²q¡¯«ï?Õ*u!²¥`¤tçŽõ‘Õ 7mÂ&áf¶©&Vx*ð4:ÎMÙ©˜VÍØ9¢þàVJUN §*Ïc/¯N¬¡l ÎÕÈù{i—n€>pWÎ]Ç÷‹{ ðÔSµÕ¹|MÛÉg‚[Û|aN,D˜q!0Îxèì¸á11Ï>Y½ó3µvÅj»›Vâb‰Óa…ç™ùuóNqt“|›{:÷‹o½Ã÷³´¤Ð€lèDâ¶Ö¿6öÍîR÷i M9 ‹>ZB-CÌr Ö€°Ô: ` 'Žº“P;k)agå@hbˆpèuµ˜wpÏ™k†-ƒÎBÌ k˜1B« ·¯•Ú}ì³r#í7 i…ž\¥ ,ø”§ Á!°8\+3’ð6Éëc^7)¿ûŸ·w¶*D ¨u §Ö)¬k›‚ñ€+ªÓGž‡ÌÔXqËbà3Søøž¢%¼úÙÏLxZ÷z©Çwì†<É…`o]ÕH}a íþá¶мìCZ62× žÿ ²û -ï¨üÙÛ›,±¨A)ßb˜%Äš3/#Üó.”öÙÁ£y³ã©^!ùUC Ž8ÕoéuÆ·P4À/5~´ZO4¶J0¨Šž3Yá8‹¨·­í„$‹Ú@½ºÕÏ‘…¹u ¼O¬D±øYŒì>¸i³¦¿ô"\ú~ûƒHïʇڣ;ËwæÔ0ãº@eeàœ@Ûíe÷Õ7*NàÄâýóÅâ¬ëËrA_iC㌡h4æÌï<ûÒ¯5\Êï¾Ù!ë~«ŽîjH„p½‡ìz?/¨ÙæÏ}”óãUÕâ«Ö?¡—·:3áå;x*æãòÎ%·ý1Tô>„|@Pø‡š¥œs!‡§BUg*¶•õ´…½±|íçîψd&KX§î>’·µyÏŠ›h i[fc\ø” ‚ZçטeÐh™qÐ:‚àuÎÊ<&J>—>"!ÔîÐëÝ]4W­XF%)ňæÆ2k|­K?¸TZ[ÏÛhVfUy3bþ « ¹°Œ8d6 } ¤­wõeÇâÐ(´Šð';Ø·hë† èI¤uFÖŒ õ€)ªƒ%Á‰o¬¸«]/‚§fÜó{¢R¼T¿úS§ofù\*…W’\ðö%ëHÌlaбBÇJM3Ïæ‹ßòfé`,øÑ›ƒÍÔF©„Ö …£é‰ãñÀ«G]kiÞx®3H¢{ë7XF9ãø2a×ï+Á}Ø‚ñ¢ §ôD}+ÆAUôÑæ¹á<æ¾ã~ä&ž‡‘³ºPÆïÐK:Åa›:hå«÷=ýÀ§= ìøÑbßt£=Kkí5²¶ß•_?+¯^_W7,vu¿J¼ ˆÜbËhcÕGŸÄÿøUùÓ›âü%Ý´ûH»Zs-\ Æ`8uŠ{ž~᫚8‹ª<ÍCž_‘ð©DBN “b@ù_ë,&dAà“Žì‡òK,ô¡uzŒCqMkèb±êöèý·¶N²Ö>J®:Î=¨^–ØC»å¹pž†ÄgÓÙ–³Ëí5¸³aš]<éõ¤…žË¶‚ÊU§î%™ç¨žúAY$¡£!@N@sÓ P† <¨SÊ}è3ã‚–‚ñ´Â¢Ð„›Ü¸‚4´.ƒsŽ – žžU0ë8é‡ï$÷F‹´Êá´®ãÂ}8põ0f¥“©z›”ô·JRF?ƒ,ùšçf†»‘N듟‹}ÍJŸd A+•~æ¥-L­ƒQäßc#¿²ù5:à>õs§´¸F‚ÛX€0‡œP+¨²T·±ª—DKB®ƒ;B`4K¾8jÑù,,PXÔ.Èux©%í Wó½ãµ¯Í¿ÿ¾¦ ¬G+ B ™v\^Æòˆåpð#ùõdÉëö-ЉÊô¸y숚¿W)„¾Có”Ë9æ„Q„#M'7Ue<ôª¯‡sÁ uÙ­¿~áƒAè™§aôq'5DýèÒZ$ B/W¬µ@®r5Äí5fcô¥²/<5ßÍìž\š_Y· {üèÙSú³s–QÀýmÕipÊÛE§­¡äìg‰ÿâ«Å›÷Jç/š!‡yÌ@„öÁÆrÊ406qÊz©Î­ ¦y^õȵU̘‹b¨da'È`fø[ÎæP 4 °Ý÷ƒ®.!yÕH社#ÔEuØ0ýXÇïØõúÝŸuO‰MEÙ9GK@›ÈbG6Àl0@SÊaÀã=I›àæ Ån¾£š½à‰8Ï$l›¤T.›lÎ:HE1(BÁ“H%€e¶üƒ$Æóx•ðx"´o s–i©TT`¡­¤9B@b¡`Äh)ÁÔÓ³æ€ÓDî┎i‰ÂÑ˰¥ESaÐp›ÌÕ‚Nÿ?Ó˜ÑÁv !…QBÐý%_‰ÂõìDnù®Û19$A¦‰Ø4¬ðóÌåÃÀ¾ÇG~¥³k$a!ˆ‚\ÌB4Ë $  $ò¶³|kŸ‰ý®ÌuỀ˜ÌyXh  ?·Ì:…^–å‹zàÂ}5³3úîAü«Hn °¤al hz]P±š‚Æ^òÆI5ÿP­1K8„•`Ǹ<~´{Ö‹¿çgõ\­"àPu¤“¨W¬O+pøu¡‡sN\ûªY¼œ²ç(¤Ê–÷ìš®oy†Ô ¹s=¬Ëb‘ÔÖ=»J»jä«Ò«8ªÞË¿ú¢àãíío—Æv€C{ñTGWo'TO›2³GûÐñá@{[yiêàÞéò"–¤xhÐuž%ȪN ÓLKç.Û·§z¬aS]ˆa¾’Æsýþ©Xs¨@ÃOüìn·GÕ‹#‹6"2wèL8T#ÿDhÓ›¢\}FtËbd5Mg^ß¹w¨3Ü„%×ÖáYÊBæ7­™Œù}£Ÿ)U£”­1Ö!a¼&Àd8c£’Ã- ¿ôƒkϽI :Ÿ1íG.Îk ë%$>b}`'ÙQ9ušÿñ!±»Ù¸¼d_9þ‹ïíÇSÃã툿r&ýígM¯3ô`»ø“'Æ~ç1UÝ[oººGzÌY+ jT„ÀVhE‚!ù¥we¾ âáMI¦!Ž ZtŒBáñŸšb¢=*Ãc%‘éü7<ï1-·´9â±/ÙÚ ÌÇϸãgiÉK'ÆÆolôljc«VÅñ¡èÞ²Ùc‡ˆºI†œï¤`€këÀ«”àÙ”K\1:„W×´ÛSÛû´a$o"½º~~s`1¨¡Ú[ciž*!hgyGuª<\[2µ©Éw~½Ñw€€Q@»^ @¨%Z¾ñJyb\M ûtÄɱÚágºå"ƒÕ.n­%çÝ¢v‰‚3 jXÍë5Ó-\iÇ3íaeB¦+æµFM¡¡¢Ñ™Éé­º&¨º+·†¼¬ÝaѬ—/YtP'Ä<àº"¹°Þ¾½ö«ÏU½Tñí^³¼ë¸ð€2 «ÃâÚM)‚¢$iìŒÂ0àB„­n c;þò]ç!£f=+¢Ò ¦û+LJÈ´ð\¶g';9äú6ç£áJÏ÷»'_"C#Jæù佫äᦠRGh„T#Aÿ\HÕeŽ}ÁÏÆ]Ê€ÚÙ/–wŽjMÛ7nyÑ;<¿‰fGLç´~¼\ n•8G½M›Lrî1ƒ ÷ȨŽdI«w…wÛÆŸ˜þ œ‹ϘÀrQ² ,#pWjxì¡]pò@åÄaÿŸœ(MÂù¥ðÙýò¿þ.=µ_?>:ñ؞ʫ§{ß}Òö“hv[üÉSµïž¤Õý¥™Ô)É„s¥dÈ # ”M‰)µ.ÜFvO'·D…K¹‹×†€;£(BÎáMg7±ÌœÉð±À_uÅËÌQeã&Cúª,_wÅôcpü1yùôôÎk‰IlźµC,>Lî=‚½*9ê^Ì)q ¸BPE™ouH¢J¤Ÿ>Ìi8Qå!}cU“™ê¾g4±y@é½­ê¹=kË50{*<É3Ã⎺ŠsÙ˜uÖ/Å$É0žyj0,mÌUº6þða2eBÞÚYO`½­³H0¥5á2çâ-Ýi!0K8$Y!(¬Ô¥…NúßüÏHÝ8ÎÒîVÙÖöIƒ†É¥âÏ=•RÁX®<æl5ÎlÏç¾ë½ùÖv$ãÙ²a!‡Ì8(D ÔQàû»“èSVô>Ÿž˜±Âïz-FRá6c%7¶ýë™f¾2õ¬ï£K(™‰òï `ÓŠãGŸë?û™ë»ÛPãÍ/|£‹Ø­ô‹þko4ÞÍÔû·£ÖzuüÚâö¡{ü l ºû¸oÊìt¬a(ÓðÙ’çÎC1ë È} &*y*5¥³"È“"÷tõé©ÎêZ¹Tÿæ»c3#›së•»7Èö=–Ï}œ)Nn¬…ú­›bù­-¯ÄcO¥×WˆdÎEkûΠüÌ_Ìâ'pçÜÞ"ÿâû°íûã|­¦ŽBB…#±¯Ix$\¸LÔ„?8ëy ŽÚ8gÇ€lZÙÑY‘CžÄ SpaŸùúž‰ö;›Ótôpùå¯ðd³#\<:µôÌwÅû?©,gòÕWag^ þ_G§~ˤozdÞ@E9ËüBf\°½ëëý«›áÁº:Dž=(„°XLX¿ø¨’ŠsùìêÓó¯ÓEßQ3ÅÈI(˜„ÿtùÌ 0¢6 l dƱiBŠzéÂ¥ôOÕG×BZ¤OEëâ:¸VèØ ­|ÙfÊ“ÔG€*|èè¨Î¾0ê4â ‰ÖÌ4l¨:—ò^©º%Bn‰¡ÆWXhNÞUÙ"'|ŠÜª†š¾r‹múßü;J|ˆ'ýA¬wéO”ˆlžMï¹g‚Ò€iÝ-’ܦðñz…ó¥o˲߅¤ÚO{_x¥ún_]¼L8sìËñµùìäò@±švö‡Ñ’¢T%\DÈJFs·#uQ™uG²„´]-Oj»‚‰_°¦Ôã,ßµ3ZÛ¤aÒûׯ”öŒöæW§æîõ›MØq¢3{Þ!ˆ»8ˆ ½ìæÞ\eͼ<2ó…ôæjMÒG9O÷?æb¸*ËÓ'ÙÔž­V»ü/ÿSžÃ*«VãK¨ H¥žšHêo2Ò’ý»çiç1ÁJÊœsÈ&(ÝPŶWyLdÜÙÖš_ÚE¾z`ïü{‹Ÿ°bìPùåßàƒŽ¥‘É…§¿ëýúÇCËyþÚ«|g”^dôú¯‚Ëôß ŠE MôÚ W”Óž‘·ÖÝ…GxhD{F÷úÞÀóè”KZŠÆ/¯ÑAžmC¾;S1ƒë.íJîFÌ{¤‹iWþóOåé£xTTÆÝø¡oHš5_¾Nß»çn6HÑthÀZÖÛC–­vlaУ,­è€) ü€æ‹’¿Î9ÇÜãÜ…†Å\Eí|³€ýW@G÷©á!ïæ5ÝZà‹Ë.ß$Õ þH‹¦VsäºF*SA±a l¨ ©¶zr+3k[Â%»E'ckyŽI¹êìKÏ>Õ ²á¹ ëU§Ÿ±)kˆ>øD5(É=·iË”¦¥v‡pǸÒ¦ š•aSáÜF^IîhÆ*/úÆçÌ3E@Xé:—­=t„Z°”fh÷Šà7¤ ,l0ç¿\~éDÑêñ±€Ü5÷›ÜÑ>òHQ™¤?µGÍnØÃGGNž^ß16vùV;òô.…€ü8ÑG,óCïÁ+è¿“ç« ˆÇ˜/xÚ€ãÆI>Z’§ö‡/>nþô9üÒ1}íŽm¹p÷4„¾<ÿ£bæQ²rOçÃt¥5|m zƒþ©ÝñêÝÁø6–(n ÕðoÎuAÀ¾Æ01ÅÊŠ±üÎlQ=$ºî³Å`,îý_¿é^>E‡Fl U“@W–m˜M€x^€Æ#[ÚÍå¶Ã-È$ãÆÅÌÕ˜w¸ÐS}¡—…þÒW‡öíÙàdd›ô^|C™´ðyè±Â%„8²7áH­ŒíÛ»“¨qkykt3<ÚBØ@ ”†Öf-rPºmÍóûãV9béÉEVß{Ðù«3NìÙº†Z¶ÇmÛ:D rǪÆØêW^ü‚x홡°ÜîÍ“Þlïø¾êS_¶yáö‘µå¢Ÿ ¨LåÀȇ«J)?Ñ«=lú‘%~î$q™Øý®Åu³¶ ‡w‡;öºCÇÈžƒd|7 …÷®dëKdu™÷·hHÔ(îrN¨˜á$g[ÆI¥Ý/Z…ZÛ œÖYOuR»!•7h”4qvPvS®µ§O<ž;Sç½õ kÒBq¾áeçrí´pÇ„2¶J ‹qCãüzæU“ã»G*V'[9'Sb`]ðÿ>—m,9Cd*4P0"Áeñ«T{³Ú‹Þ+§²5w8}h7ÙÏjaJú |é³ržª‡Šù5sìØÈ±ÓícÃ×onFLIǵ¶Ü;æÙ“ …[»LƒsÚ­§8’û1MóPc –„îÈ®âõ/”þ·O»×’‹W- wΰ¡qîï\m±ýð~ᦢõÍÒ••K}zWyþno´CT¯±”5Ý_~ !2*»9¦síÆVó÷õÔ ¾ÑâÝ¡u¿÷ü÷ìóÑP7‰g nv‡5 ³@M(Ê–™M‹³Òµƒ(÷éÀ”2 e!K7Ahϧë„~éë“û÷?¢ÌocñÂkÊfE "e& °£ûóçVKØi¥°gŸÄC·–7öfÚã]›ÔX`1¸Œ!:Êv¬{æXX¡šK$–êD–¨#^åý;[ökÉŒ=å‹ÃÊU¬zŒ´¬0€V^e8Ò­^é…/ðמª‡¥^{Ó‡ƒ#»ãç_-Ú \Haj"ù«_¦ºcè–Œ``X@ŠÄ• á40aè¬V¾q°á—îÍ)j²‰£u¦m‘ xÐþ·Û¹¾èbWÒ´  ©õÈK†Ž¹€ís}+ñGãN±¸ôᢙ,›<Á­†j¡ Ž`óðS¶1ܳ™7Å»êDðÁM=¢JÆ';u±ÛV×@¿çë÷¤]·èA‰qÏi£"U­åÁÉÚ~!~ã™|Ä#ü>£‚OL ÿê|o-UÙ ;r¢´zK7´m¹xôñÒ'×¶W¶ª”™¦ÛoWï°œñ=Ï‹k½û‘Ô‡Þ©ÃË^MÈŽïUž†¿­;i•Ã7ž{´Dè½pßžÁŸÍNïêçQ{[Ô)˜-»ÈÃpηˆÎ¨6ì+ïÑôË™ö¯ÄòÌ÷øÁÊ`Ó¡ÝÉÑSBå Ä r¨°¨ 2í>z˜ìž®•nÔ÷GŠˆÔÏ‹:å+í[+8½¼å–¼ýP•Fkµš.q] X+wïÝ„?Ç*^>¢Í À-Ïß(`Û`—ÊIž‰|Pž³K­üØt÷󸤦 {롊Ñ_üX­õôF9O4 ’އ‰!¥²»w¹ßúbýÂÝÀÓ}nH×ׄÙXª\Ëû]Ó‘|d†º­ <} SÈ¥UeÀÂÕ¿ÓäÜ]ò?/ÄMM7¥ªc1 K;ëÄèŸ|£ÜÏÓ­®aè8$FJ.Î*?§ÊõZjòýô/ú{:Ö¬˜•‚ÎìHÿê¹ì‚d摎IZÌ-€_p:¨ÔZº”îÏ[]$£ »sªŒ4ïZ¸Ý®þûŸ ®Î»’+SF¬¥h˜mzäËÆ«9b‰¦¢“ËþN˜DíjþçÔ®rj9÷\1Dhª¹¤,<|"kÉ,žðÛxŒÿúš©›’Ô>­ÇuÔ÷Iˆo9³¢ À_S@c«ºd<4UÿÝgùO™é Û\ÇÁðTôîÅdSš´[;TíÜèNn“7êÇØù[ÍÎ0‚l„á™lñZîz&¸õ(¾¾H©#l>Q]¾`G=³Šàiþƒ_õv á«ï>>²yÏ‘‡Á®ÉäղÓašNÉG‘Ù>µ¼ e¢y“Ý ±ü¯î+¬ üžr×óäïx›í5åSúè)_æuÀŒYÂI¼‚€çYü`>Ý=UÐÜìÁ­÷’Ã…O"ôS7FÄCjû>%Îj œòVO]™×åf©ZQ%ÏV"ÚÉñýä/ß¶…àG¬9E|K]Ûg›Îµz> hT gcdàìÒ¶<6Ý;Ž‹KÅ´²·—eå$ûùߪծ[’Ô8„ …¼’]®+¢ÈîÁ·^bWfkæÂe-f*?Ge‹yU]3˜?2µEÜ\s'ŽÐÐ7)äì7Ï@Ìa˹»Ëã®xä“["-„ICßWZ3ç+œéò'Я‘õ}dö–ôPÛ8Cž9Ç0ÌCUv^×ud¬Ò'=âÀðVbÞùÜV#²¬¡ µjT0ë §@rÞ†cH±e,Gªú,ÍÈðµ…üÝöÞ’¸±Pùùgþ[Õz—Qg ACŒÒœ›)¿•q›õAõj?M+»½¬&OG÷?M®~ˆ­–;B1t„KÈ_ØÈ>~—ŒOð½V¤Ü7l±ZGD›o ¸Åƒ·M¾ YVÀ)Ÿ*c IaŒã©áx=Mj#ã¿ýê²]/¾™O¯³Ë‹ié0½ô°ØîƒîW¦'ú#c¸Ü¯ –ã{Äû·e§¯,ê^¯ø­¯Ùx¼Þ<âMü‡7e¯ ˆy\a/ò £Vl´û ³,å'ç†r’ Ò£»èG?èíÛNo/˜}»`×Ñä×÷qÐî=>¥¥¢}‰à$Ré!‰Xy^™; …ð=b}´(¡%]IK;AA_âo:’OúTj´¢E<¸s?³‹W˜M 3\~†W˜¶Äø±1ºAÔV6­lqð!äÈ2a„1ݤòÙUyã~¸°VyëªüŸ¸Ï˜‚ºí1DzkX\C³Š"¢…µ=t>ã9xÒâxÕ­m±‘!Ÿ°Ø,.äX¸NÂs‹ÆÖHŸÃ* ¬Wá9Í‘²ùÝ? vûý~Ï.­¹*`‹–;fÐCFdÛA1Á*»´×‰‡ NàvÐŽnpû`¡¥tÛ ¯Žöµ¦#!f)CÐlçÚÚ3ûÌ‹§û£ûqî–ëu" Yaâ„˜Ü ŽµÜ˪Ðèôœ_ã‘ôk=ÖÕ&Ø?²5°ož7#¡yä‚”ˆÑ’ åÌQ§¬Øpü¾ËÚÎ2 °Ë²L ÝZuÞ5×Àåûñ»W£w/ãÒ¶p#¾£à@vœŠoÚòˆî·Qˆ(BIyâßZWÍ#þà îÚ;¤µí sÑž¢”å¶‹îÂ{²9D\vBœ½Ãè"«C{½íÄOPÎYZ£%fµ„Ü r&_­õÖ“»A¥¶ë€BÌ|€-/ »å´¡$&B@n2Zµµ$Ü"c‰ ßÿÐf:2å3)á[Huè>û…}xÑǬp£ñÕ_#+ÂYe½ŠQdä–Z¶©¡Ž 9(n]¿~zS^š‹6j¿ºRüù‡î“yZÐzÄúãN 𫮸âÜŠ!¤Š9«‘£‹„ÈAhkÇ«vm›5›¾ç ™ùA &‚%Ã?¿4šØd=^Ô2D ZVâ9¤´áoÿ#ÿ`#ÙìèÙeSð²‰!PQˆt;6¾¿×T;cÍænƒ8Zûâ³4`l\/š½´mÕªnU:§‚LiÊ™Hýöë²_”X×6FØÊb`¬4¼È 5U©#އ"tô3/{³kÚßÉw¥?~7 i¾ BÙ Y(Uv<ÃUÀŒ' WôX¶v@¹6v·-@XŒüÅMù`³h0Îp[(AM¹¡ºéÜ7IuƘ,6"Ù öp¡G¤¿Qº}'ߺÏÏpÒÞdV‰£ÚA Èìíò•ŸVü•Þ|¿ºwwðþYñim¯RÃyk>ò™)ò §™ñrÏ/H>äÁ—Ÿ®üþÕ{Òw®ë•¬CŒUw/Ýhíu¶O`ü9ÃëP“™Ñ$-¾þº;¹¿1~´›tŠ¿½8”¹4¥^6zlº¿c§ªz~Qýôó1ÎPq©ÌØ‹û·œÒ‡÷5ö¶ÿÝ/â¥nL=[eæÅ½~몜2bøäãcïÝ´ïÞJQVþéwÝ‹O”}¶±Yt´¨Rå5²÷Š¢Í(Ñf<ðëy1X¬-öòý»šï¿ âA¾ü`<ˆéèˆÔLòFxÿcÝ¿D]|D—Êòj…%—-Â~¥Ž@Þ¯ä;c¬O\Á‰G\¿–õtרE‡¾°‰&`N*„&5µßx-I´çµ£¡Q»º ´U†Ù8¥P Pæžs΃4é˜^ 7(ŸQS§Ù߽ŭ”)@Ë6ÐkM" …µ ˜F}?wEÑEmŒYíqª!S_阹-¹Y`¡e€Æx P[`Šºußrµ}Ò&‘r± ~ lQJ›yíú¼nß §BìlІc}b]áì}¼öã)o¹7ÛŽvï+¿ÿ~a>®î6Š2²`Ôy¤Ÿ8UD в<.[š5}xý‰Ò゚<ÂÞ¼Ü_éb5ç.¤‡=½Áaød|î®lIÔvÚÊî÷¾v<ÖkmþîÒ¸=<)†›I§Æy0’Ì>4o~> ÐÓÌI]{eçÀ Ø7ïÓù6/ä8ÊÄÐ6z÷Qms¢8¯ª ƒÀl¡Òº,]QA:·.žy!QL¾°Ùlå{°B\ÿáƒ0séøQøì-;ÿ!=«yÿ°’ 'xÐ:mév!0eŠWˆ7Ðn?ãêû”Xk*%£¤\–*)1³“”v(»;×»†±´èg¶SòñìŽòÉɸ§ ¥•”; ˜ˆ#u¡1r¤^Sä‹o”÷Ÿ©~z½÷ѵ '4- ‰"ÇŽÖ”„P?þ6…wýoÓÅUŸòRo¶ûÜJ­t Ø‹ux,!u_ \çöØÏ1s%m˜5÷.)ñ flý xÓ•bK1ÐØg›:T)%7ޱ˟Cu·‡£Þê:5„g®@ä˜Z¿>WI•AïË_>üXðá»öâ‚®¸µB çË•EJ:!‰äÑiwl"¯†[ýb ‘ñÉ“Fít4W‘ƒªWµ~QX‹qÉ:$¨V¿AÈAÍfAßøxO‹2]76”–èb5±Ù],Üè›X7ÏöœÒW>p‹ïOÛSé ÿ2kôÆ'Õšð3Þøˆ Ž‚ÖÀ«‘&)˜ì‹+ß9=6Å ‹ÝòTvÿ~¹ÓvssÙÑÓflw¾°Y}öí¯_¼Ôßèei¯C›%Ø7Òž&C?üˆ —Ò'ö-mo¹}Œ»¸â_¸S<±¯ì¸iwù«§0p¦B³Oïz?øÔ‚ßwh&òg#î{ ©L“Éú÷ÿÚ9•ÙûÄÚÉ‚iúìþ©j%˜ÝÜι²ÄAêêž×Vv‰ÆH«5Ø‚Tµ§?>ßm Ô^[¡ÐøÀOl6~οã>c9ïÄKE3¥û¬ÔÖmåRq[¦î<ÀÀ=„V Ì2bœb,!Ì’Iz7«ÎH·[Ê} ÆImÞ/§®SÝ㻃S3ÞXu@­r¹³„B-±G‚¾2r¼„ «äæå×KGŸ¨Ÿ¿ÕûôjµÃ ˆ¸²C)kJþTU,'ºÅœÏˆaˆ/†Ã‡uºEÔ•rx1É ²º“?÷Ì]VBõ–RZ™ÛȧuI•qúˆj†S7m@ªÐ“Ω²i:¨G[¼KÜ%$6.ʼ0ªLFyÁO6óóGc'w÷gÏ·²óQ÷çcùån¿_n ¹½8þÚ Éî³l¸’ðÜ^šõJg­ÍΖ ¥‘Êg·¢ó·[gG/Ÿi}x9LŒ{cHÿüórkÛþÞk] ÑêzïÈ>]¬”J?xnô’3‡ö,m²±¾²«Ó¨Ë=_Ðqþ§Êù¬[á0ÓÐS5²ð7¹™ ·ÙÆ—_‡¯ªt–äZ§†T÷•ï/»­‡U×k’fɦ}"©pÖ@/ó¦ŽÊ¼Û]ö:iüW®àÊÎ>RïÉøn™ÊÝ'Îe†”£’êXôüæŠJs¡QÉ¥Ç08å{­“àQ¾ËûÚu¿ú¸øg_~n|òhrú¨=v<¡·<Ç¡Î0É%É mmS«[¸w2õý‹¿gk,C %m|“XR-'˜mhÆÅ׿^[øqtTôšIœEÞŽ£[W®‹1rµÙQ(4 üdòW9¡'÷ÃdIöŒ)EZÌÅÂ4›Hêê ø«½&)JZ,ÚÈc~X]ÀK/÷‹…ʾ9˜Œå½Ùð©ßˆ—î¶ijB΄ð’îÕídLyy¶â=y„/´¶¾ÿ¡«I¥k;ê\Û¸´q´ŒÞ+Ïñï}…½vV>¹Ga/¯X¡n­÷ª Þ1ÇrÓ`ÒÏíø@eUŒ®ˆrÏ‹ú —÷QÝŒKï ’PÔÊyò·evÇŽ6KÙO%ú†žW8.}Qf;ÍæðÅ·¼ë¢o4 ›ðÊ~¾Öä¡.±Aªil´v¡w™{¢^üß~·yâhvûó–þÔ߼ɣÝbvÎë&Y²…úKϤûŸ£µÂƒ÷¯{ëió©cQw³¿–Úcg†9÷ý›¯¬¸•W^U_>^﬛•V\õBöTµ, ½b[ë‚4|1©;#1ªRL8£¡›ò™C£F&½Õ †f55nÖárôŽŒnVŠƒ¹ûˆ„Ÿi##ÞÄlØXÁª›&O­’6µ8mƒ“^1mtD¢%ßÇu4M¾úxôÏÞn~üpþØÇ4éô˼vÊNÁ±JÞÒ˜˜¾ûCýŸÿLܺéMï×/7é¡=,5LQU°¼MYÏ$09)‘òêè[:Ýßßë'¿ûå2å ë°j³ªÕ%¨ähÆ6ÑöIògŸÂß~>R–N8ö0sšBDœ„²~ïEï÷žL†<϶DoÃôy&èæŸ¼@¿ú ƒÄ_„ü¶‘mßÖP\2`nì8“wÈ=Ú¼¢90¸nðôaIüìü2A‰¢P޲ÍFçé߇3a¶ÿ­á^9‡¤iIÉè³Í- ?5쾂Šc`3ôƒi!shÏDöÈ–-¶—`'5è2]àÎ=VC·¶“¿97ä©6ÕHƒt]`é·Ÿìî«Ò»ëjឪÃvr#uòôp4VÎ~×%)Üž“P>>LÇ~Îq9•2,ß̯n'†Ø×Ž®?ÎERƒŸø?º°óÎea|Rå.&Iž<‚–”Nã­Dhȧù„UÂ%G¬Ù©ë~ŒÞ¦AMZ H ‚TÕÚ#Ùé¯G%³µû yüÊE©W.›ŒðËŽ›·¥4ùzæVN4À[›ã ÞS*=`-£.L"7g‰M«]w¨»ÈÅkOŠ?zYï„iÒõ]ê4üƒ§²o½¤A FŠ™ €ÀЦ1?ü´üW\KgÆ]l)¯+a>,0·àüÆï|³4ɶ{Wo*¾Îo¨cSþôNæÒ:µj¿Ÿ–óP"´Þœ³ñ•Yó£ï—>ûKûó¿¦?ý~tõ¶Þ»O?>‚'@×ùÚ‚Ðâ˜ßmarÚsOM4FFÓ%ðïh˜Øk÷Ç«¿û5F¼ºÕ•ªÔQÖ . k‚Œ•íR÷g?ü¬T—:@»áÀ– HÈ!Šä;ÏÑü\6Ì#Ý‚¤ë·ý„Òí?y‰~í¹ÒxŽæ÷¹k»˜ñÌ·… …¯`/…ÓD¡…{¬ú¡ü3üV2µjVÜw$%.ŽLRÎOþ&Û}< Úë/~cb0ÓQªIu˜ù$sâOÑ»®€M‚)µv€ry»…¦-)·—aŠp©ÉÉ£ÃÀóñ^§õ“óÓ¥,-ŒWq^;€þ7NojĶƒû·;ã6ºx&iœ­Wk5~÷‘NZœ%pã‘‹=öØŸªÖ­°í­ *»Íþ竽#uøæÉ>…Àqª´^Ï‚?¿P½½Ze„,ÌŒ4¼)±#0ÈV #&êN˜þ–UH!†hü{cRè’~h1p‘’Í¡ü¹ßl–²™ãôôo‹~µ[-I ä\vÕ>ü÷>½í Gvé=(ø+µ‡c` ã²Ôô5‚*‹%Â&êåPðWÏúôJFÙR?ìg=f:¤ñ=ßûÆK'4eK͆PtÔß~þÇóE˪¹©CLi4ЕÁ‹”F¿ùµ½aÇÛ&˜îOˆc»ã‘)N³ZŒö ¿YN‰²°á±ÄããÅÙ!qažþè¯*Wþ2eßÌ}tld—iŒ:I1U¸y=®ç`ªü|F­¯ ˜¯>QÛ½sÀ'¬›.Ȩ?òØÈjO ìÐj‘‡& æ•&öwNáñÃüñ½£_8d ƒ7îðšÎ¶@d~ AY„ÔQé³;íï>í íHîÐ×¹áUæ²Álÿè¹²·{¹0nÉ]Ln-pàŽÈše¿ ±ó9 ©CŸ¹â‘sª">åGéPQ§üOåhnÉäé|Š›LZ1Dó²¹íbš€…;ýkUÎ]Á+cJ®kßz胃ÿÝTæzéÊ’ÿöµî3G¡T‰®Ýž<ƒk]ýùl8ZÓ1„·7Oy3Cy†î×7p˘o=ƒÃñ{·Y¿#^9®áõöÇÄXuP ¸ò0?¶¤eÂ÷nt¿ö4}lXw!úø ì­â™=ä߽͖îO^FGÕÏ®ÙÀ™'°Oo®ŠÿÏϺußoÔH;sÏóž9=X ¶”Ýùl Bøÿqáñ£ä_þ Ë·ÒÅ¥ºæ=FPžÝ+P­Š¢¡‡fU›Ú>vü$õŠTS(Ù¾Ry9«?`y‚ b¤Ì¸„¢ÃÇõÚ ›‡7èŽÀÐ]¦zZràŽèÌjÊiÃÂMaÛw‡ÿ‡W ×VèšOýÎR¥-ž VõÊ:·)(\äB±¨í¼¼<ûæãñž©ÑûM³)›f\W¦êÒqµNÅ}£Ã©!ÑÀÚÙl×ñ°"²ÀÕ/ÝïP_'’ì«ðJΤ'ÆYZ@Û]G3N§Ø(4E6s ìê¢ú÷¿Ì+,,—²~Oï÷ÏÍ·ê-ãO¿Ìÿ/™¥i¸woþ/ÿ˜ÓÞZ)™¸BáEÓiÖ»èJ!35À(Ð ‡wÃñ“TÉ´lì†Õòrý¥´ö€fÛÎH –AéáÙ!Æg1=ÊG?äø5g2nBç)*sã¨MkoSÜVf¸ÉÿùšgÓÂã çyy_J8º'^[w6ˆÁØ€tBPæ¡&C–-ÉèØpï+O“½;›‡öºÒŒ AJÃMI¨×©Œì,ogE0UÃQ:3Øy”‡, lùʃžؤ;Ë¢"ýÌç#‡¥ˆ£®³îÈpWbÙÀ&žÇG Fn ÅvÚ‹WÅb®[tÚén…!¿º:8—ç½»àÓk—Èå«Ý~šî›°ø­Æ³[Áe|#ŽKÙñÓppÂÿäSXÞJ9à2EB¸JQüƒÌí[Oð3{ä¶lè(¿rŽ]ÿ¸ÑÉzõ<ÍhݶrïÊb6àH ½C´²¢P à_D;¹¶Ì9¡Cž=¡á”R(¤pÄYBEbí(â(Ñï»øpdGð×?‘½ëêx¤°h^æú- JM¥dõ¦µ‚yð¿~I½t¬Fým–DŸ.ø*W®¨¾À;š“5ÓJúÖ»w¢ú¥Ç͵ûên‹™±ãÃô£;åµ>¾¶×›P }veNíßU¾4[,%â÷^t,¤ÍFô÷—r+ÄbÛ®lÿøëµ!ŠyþêSˆ¢¢T«þè\~t?û3Å ‡¿¼Éë1û'`{ÀþÍßK“{¿÷Fu³SÚì¾ó¢©h?b2Êß €IDAT,Òºøo¿/;¾ï´ÿítr"=4<6=Ô¿¹å'×èF•[a•åݘl¤ë+nvC6OÐLV.þýbÌ Š ,  ä(ŒCôyæ ÚS&EùÖ3ò¡ˆ+|%±¦9c³Ä¡…׎WOÏ­ÔSaqá“ôƧî{´Ã‰ oç†ÝZŒP$AÒ‚ÈPÇX Ùo½‡µvo>©.Æ3ÇÔ×_ íWûw—Ò+×û7oûŸ^í¬®ŠµGüâü³;XÁ|—Òo”çÝ$òÈ„Q€ƒÌomÓl{:c¹؈…’é)Øî“Ö|àefIŒëR„Ü}xCŸ;'WüÙEüèBëú%¸v=dÉîýGß®¼ð4GèW‚8TÇN»Cá¹sÁZ»‰Þ€R†9X°†Ø2-ñ4œÝ[tõ¨ò? nž‹»I¿ºû Šý~á_¨ÜÀ›\è| 3þoxØô‹u©Ð K‚WæõD –2b…£Ì ç;ä`ÜéûwUt8 Ãä¿Ë¶®«ÃB{jô*À›Ê‚g ÚtE—ZÂýé+âKdž [EM..xƒ¸|õ¼|þeqöè yÄ6“<ùÕ•p¬N¿ñ¢w᮸ےÇfìÎ ñö•`#_Þo÷%+ExñAv`¦vq.[î‹ßy‰D>j†o^,´ç­n«Í5õ§_­ŽÐ ýàB9Zú‹;Gö‹ß9kÒž}ë6*Ù¯< Û=òßý dæ~çKÕ^lôóェ›Ì5v«½{ 3ÿ÷?p›ŽXÍó´·{G¾§ÖÜ=i¯­›dÀ¤îñz•I²ÄF9ôv¨¡ÉáÁæ²»µï: ¤v÷/1äèn@!rêR”‰üêÐÃÜbêŠR@}ÄHç- Óî8’Yæ¤—Ž–NOzM J.}¢/lvLc¯ãÞXÉkÅ®ÏÇ(¨%,‚f9ÉGGë¾ùz½4”esiø0Øu$ÿÎkñ±£ÁùäárzíZ÷ÆU¼z=]Y£ëKxᆊžOAêÒg±»è Å3ÏYMB`xšYE]Jõa†˜VZæÁUÞ ÷‘J¢ôÏÁûÈ9ß3¾I•Ê {ö¸ýpp‡ÜþiÞjU?Nß¹A0ëg¼|íŽý‘J3.Šœ(¥?º2ž¨­ú-EŠæ§«ƒA½¸ÛûÅmlmëß~r¨Æ³uóóë.m‰”Õ²|f¿¤Tµíܶ¹”v׋Ñ8<5cAº4Èæ•)ÜŠ·ÚÎþù«l"¦Î–~òYZò¾z<úwïÛk›ök‡+¯>³ý7 <3þµ3YY„¤}Ùø×­Z®Â²†¿ÿErí—þýŸ J|íeµš“Á¦bj´¨lŽðýª.vêªjû³KÅÊ]ŠkA#ÔoÓb¡Ç%1àCðµ ÃZ3ÅpÂÌæS!`A<š€ R»ê#×L¡ûÚ‰ ÔìUÞé{·Þ•{2¶µœù“áLE¶”V"|çZâ\æ5Ä÷U¡4¤¨þ §ª3°¸œ>†}]¸=[ööô6VF~ñaßDek¢Ô'¤Ëx?k<¸­étòÂ¨Š€®Â±Ýž¤t{Þl^ V.±î28íâª!ú™è®Øõ‹¸~tç뉊( Xv,æ$ÕÚ$«Û<×ÉŒSIßX1p¢4Ø4õŠ"­û?†½[zcËß ‹ˆ_¿7´[‚õ¬DŸ%rîø³Ç¥ m0\xÄ—ÞÉö˜`©]Œí †+&ã¹Uþ¯n@½ê;+ýH µ\qõíŸ9Ñl,(ç¦(Tévœ/Ò29q–’e„(­ë uŠƒËksmµ|]ù÷Â=¼:PòW½Gú”PÏÖ&‘r;§è¿úv5Ÿ—wÿ^µ6üýOÓO¯yÒVX;O½p°4ZMÓ>gB}|£’Êîñõ, Á'ËY¯ã½z¤ú÷×L§¥¾÷D£Ê³cæÇçMÖ•×Kúì¡BhÖ·î³Õ•ÁæššðüC;”B'ýì΢î[\^õ–;éõ%5+ƪ?ýÄFqå+G‚ÿ𱾸¢_ÛǾùbúwç2”^=*k‘ï]‘ÿÓ_d¹ EîÅñï¿—Þä÷™U(~í%¹áâÎ(–r%­³‹]ð¦2UchÝ»¾)7n·æ×<ù.+Va%ô):I,xP3¤çI_„•¢âEi„,×bo¬hŠs܆.tÌhãVCB‘_?ŽŒ'±o6¶éõ·õËÚëÆ«ŽÆÛM‹~y¥¯1÷Á¡ó`:R’ŠF‘o$¶1ÁÖVôÖ9{dËÞZ é~«3òîÃjš€rž T纛¯f°ÝaÝnžI]¦ÐµPâ|",tŸvçÜÊ•`ù2K3Ϋö²¥±#¬CÓd*Pè[Æ4¹‚RGDQøãoîZ¿ßŠL©Sƒ5³Í\y›¸-úNôÁ! .tvœ)ç7yE»„F•ƒñåYÿÑrê X4œ É4qL ËÑËøã3¸³)œ-K·nYO9SåÃûr:(デðù’­_‚%–¹3»À}ƒ„]£ç­­@ã˜bˆ eúÄšy„çà(:ë,ø’*ï´’zE°MI–\*ѽíWÂó6ƇŠDúìs•û \xȯ½›=Éksލ’'í­.©*ܦêÓÙâøLµóšGß¿ÝN’‰ç&Ó§Oлsñ¥ƒé&½×Ë„v_yµ¹°n·'//ooJž·Ã‹wÍßZýÕm9°AËÉ>À€•?¸¦Þ¾T:wW.o…ë…~”‡&GORÛ6¨ŒŠsWsQw ÿò½äàPõÿm•nÓ·oLFlåë§ J›…ÿÏÿ¦½]Ø¡Â9íÉÆÇâ•_wN³øæj¾ûHãŸJïCmnÞ:GMäü2[b‰t¥ºÕ ÌY¯ÄúºÁÓ’%ÌÄ÷…r¸ƒœ`”L‰«1ÖȱE™—{Οçy…±›×ph †ÆSž9:iì±2ÕƒBwÑO•0~2¨„…Ç¢å¾ýà¶FÄ‚Câƒg„Ìi0 RcA8Ý òåÆui9:ÿ£Î¦ :ÎSHzÅ’hyU˜)‚š_|ûë;.Íå ˜Uù^ ðè j†­®Sv"²H ÆŽŽ1Ýt8LÐ×:+,^@ëJanÜÿ껳½@Çý‘l¥è¢ ¶ XÖs´k9PïáÃöä‰zï"Æ–%(J‡õÕy²²âJY€µšG€°N8°ìÔ~¶¯)U¡ [÷$…,Ãøô¹b!Ü[±Ÿ/ø‘‘š³å*³¸áEÏIâ*R×õ²À”t´ÛDš;ãªNô 3h,DøjQÚa5)eÞ&ñ¥È¥ŠÐw¢ðkCÀ‘¨‰¤öºòoO.¯Š›¿°OûþÍv¿¾§ÙµÝþ¦£®HÐ|4[›êC&D¼±\~´mÞ8@Û/f—èÅÅPT¬;®;òÕWJ-%ºi¾<˜¾°¼¹¥½´~v_ýòÓò/ï¨Ä„ÛP$}Œ>¸e~y©|þŽ\Ú·µYêg‡¦ÇNH:ίùŸ]í‹:‹¨ø«_'›ãÿì7ewÙ¾y©Ù¨$ß~¢¦n§á¿üIk³°åBò(85“옩-½Ó9ÃãÙ-7±ŸÿþémZ~„ÔRã[ßS+^¾!¢²QTZì«:O+ ¨-=ð•3„9ÈÁ…H¨Áœ'0ŽÁ˜Íkèi>€”!ìf|]»uuÄùÆÓ°»v“q…¦½„¤£ûÖM‚¢Ö‚¾ƒôB|ŠºZ²iØøU‘^w’!å¹Ç3á<*åšsBÜ«VФ‡r´túDßîÃ;03T=6V»³î]]HN·+ú³Øj©çO„1<·K]Y>›÷u÷;þƒõ?¹AZ› B fL•a[‘ Œò´#lŒàYOi' pÚ@H­±Žˆ¸ßboÎö/Þ”÷ækËC¹®^Z'Kü_=A±Ò?¿ØÚ¿Û{ý¬¾·þßÿs¾Õn|agÕ²‘ºï>g5ó…ù±¬ß5ÃîÈSù'sÞûê–BL4É9j·ªbÜ+ÕiåÂkiX¾ŒÊ b8Ÿ $è(<©¼¯!k—t[…íF§t–lvØDVs⢗)c9õ‡­+(7ÔnŸßUîK^¶áÆÀoì|*ÞÙIdyÚ7ï^/n¬†q\Å"w` ó­rà”ïJy±%Ÿ9cœgÖ÷¼FÏ]Ñ«+Q‰òf‰!172/{¼8êò/}³~ìÐÖÝ9»¹©Àu·½Ë¼{=@>ïè"ØE‡÷ΟãÞ [ºÆÉçßfú6A‡¼°Åø0ûö—]<ÄÜèµ0ŠœKä²ÖP!< *)ÙRg`O>¯ÖR,í(¦ö„ïüÂH SŒú®'°¡3ZSç‚ PšOFýÑUVG’¸9–…•#O‰æ”Ì3QaÁ/‹[„¢±BŠPÚ ¸û®‰ªW†ªáÉl­£4Æ$ÊÎd¡Áà>—à"©q€€.qÌâQfŒnr ÊoÛâ†Î™tÄ·A„³4ÝÎ…#»q{Qw:JWOÏ¢ˆ¼wÇ슎 Ýߨ]{Ô>²“ÕíÇ÷ÓN«ôÜ‘FÉßzromÇÞ#˽ŸßlÿôcøÁEÓo ž9cë„l:“[¥=§EäÄ•É5hÆå$¢µõ@´Úâ—ŠK7ü;³½•Õ²fÞåGÞhHþÕ×Lä}U}ób{zо|F-´³ÿáM¹´YzíÀ:¶Ö7_Üœš2 óãio»?¬O>k®?ªžûPe2U>'JYëmÛVoyt/DLôKÚº0H4[ºì´¢‰êPëä×Tc¸TÄ㟫4wõ;©˜‰ÌG×ä•å ¬Ô0Ë(8 ¾Vl´jÑß’O>æÖz.OµÛ5DÇš²Ø„±Ébhª+¸ä½°V¥«­ôo>ÅTƒâ¼âÔ€2 îygt4ýꇾwF°j> ~²œÏ3zÅW‰áèa`C­9Þwvž«m€ƒT”-1׊ôp$±s’ƒ£ ÿëׇú˜®l¸s ÍÂã_|J©‘ÑÏnìe¼Æû×ó–QÿçßLL?»´÷®ã™S“&¢Wn§§ÎªéÝUmŠ… ®Íæ òÄÉG:ÖÄÒ6L£p=ðh ´r®d-‹VQÀ ª¹tÒ2 TÑS¹–¶s4WíÄö;ÆÍ䮯¥ô³«öù'*Cåøßþ™دìË~÷‹ù÷/>Šï>[Úd¿¦Íò±'ÌßÏ5þý›BêäÐø“3•«+hµô©¯IØ7Ö™¤A°Íè'HϱÜX¦ƒB!(h2 ¦Tâ.C±ŸžxR¿rthŽótVMOY±ìˆc¼äTצHáÔ5^ TËya2¹Ðh¤é4jv£þÅyÝ`µpÓ`ªž×f€–Gœ§–ÕXåbø¹WíÈ>¿Q~çÓ>ÄÈö% …¸2’'½ºO¦È´þæ·F¦'| ýFè߸MQc ¥eqÃæ›¨;`ÛàÚ$Ü‚x Ì&)¹b™ŽÅ>Ø‚Mµ\ ¾ú|ØRÜ ‡Æ+·nv§ÑCŸu“"ŽÊ®PhdÝŸèå-3½»qö5s@|üùÔÜ£œˆtŠ硲Žs2LÙN Lò¤y»¦Â™†¬¹‘‰dl×Àc¹ë²zÙÛìë}â -ƒ²c‰‡Îé'ÎÑGgÏÒï½Pò§a¥¯äŠTkŸªNŸRˆÌ1ãõ¬1÷…éÛç…'ýœ^ÕùUÆU¨•Ü1$òŸ¿¥L­®ÓOîù 7_zÖˆ†<¿5îë˜ÖÞ¼åÒþ³ï `п´,æo뇛¢ºãÂÍå'ŸÓÿ?ùòYÓ4? 47>øâaÌ“ÌLÅL]]MjX-É^ƒ¤‘ cŽñ®½11;³»³¡{låË’[jÆbÊÊ¢¬¬d8y˜éå‡nÞ{ý —ïl6›ÙÛ‹Jô2Åôrâº= hâÀ˜ÌYpP„(2RûÖ8L,,Œ˜°¬@ʧ¢j‚ .5 ë¤0y[$'‘ûóŒÙÍÄ]úÜœ>íVþÃ_²û[ÅWÈo>Þþ³ò¿õdizxîõŸx<ýéýñû#¡TïÀ.ôO ^Ýê‰ …)6µv&Ô¦„{›³Ëj ýˆY P0Œ4.c`S¥Í©pÏ#Å gÃmª{½~ðK Ó²3mFÀ‰q31à\‡û~>¼·].wó 4<¤W¶£ï}lv[.ܨ2& Ú˜ªŽA(ÖÃhøÙaà ̯ã÷>ÈŒ%”ÛL8cX92y§Î½q ‰Î¾öµÁÉ1¡vÍ÷¯ÝBµ ²nC‹-0[Zî8µéÔ6èø$£X:ã˜Ã8'bTF.çØã¢å•9šòßx')õçCã“7›»¦0&ÄÌjP˜•š*MY%¹Û9¿[8¤ÿ—WÎJVÈNIáÂY¬ÁÁI‡Ž‡`$nÐbÛT¶ÛééqíVí„Zk«<ÅzÃý¯é†g˜N{NÁƒ˜ý¦Ô°íæü#&ÙÀ°%ûÈý»¥Or±l0%xT"lAaܰAçí0gŒq{@’XU~ÊÅUnÀXÇðØýï?}¨7©ŸÞÝ_ÞÉ׆Ÿzr»˜V6>vLev9=µ{ä…Ghâà“9¶v·Sï§·e½Ä¯_7òƒàÞ‚ñl Y&¸Þ,ÔIAÁÉh4†½šÖI°«(ªÜÛv” Ë«RÙ¨„­FŠGà2_k)Ãu¿Deš!Êðâ‚xíJ$s²Ù¬ÜYJÏöúÖg襋Þßz¹4½^}ófçá³£/îkîÈÊ@X”úÒ¿øéØOnnXV1ÚüË/ês‡ Þ_út)S…± L€—­„°•ØÂ–m8ÊÛïBßABuŸ…’¡¦)!­‚×jäÌ·`¤ªÚº)ß[oÑ> ÔmfÎ$Ä'9™¡ëÛîÄ.[íÇ&¶^êk¥ùÀ¾¼»ó¿½!®­×J%±_è3÷p8-{Œ§¬+¥Qš÷Z݇w+–á¿ø^wÅ••Í”¤S-‰ ¸Ëû!îhõìÃýÕ¢3û“|vÙì=b®/•d§e©ZzÈWÎQN5†»Œá‚çÂiÄ‘Öe Âse'šË6ªVž8U|üªÜxÃV]u”Þ]b>÷Ú:—QFµÄhS˜Œ÷îé‹û2DÕÿò«&%¡¢ÈKÄËœ0ûÀ?CÁš¢]ƒÍny½—2•±ƒ¦×ÁtÕTb££ÿ‡ŸÉævàˆ´%R}¾¥‚œËõýðh·è UäÈÑúÂÍú«íåÈrCkÕ­ëq1|Òøë¾qÊ3³¯À\‡oøæ#¬­6Žiî,æö}{ì‰Sbпøœ`¯>½ÚÝY­¼ðp^¯‰^»¯Riod}÷ÖÒ“#}Ï=È+3¥Í™v­No.&åÞ¸Ùùw?­Þ™×ž‹<ꥸ\©©8ÐÝÖdÀ·Ü^À£Œ Q'ñ>"'ë×0&ì”. tä\Ê b%¨Á’F 8BdiEýì컸—ö}>×=³ðÍw7>[£¿ö8þ­çãéÕêÛ÷’ãª_:œl‰ÒXÝò¸ýýÅ?ú|DZ@ù>K9CƒîóÆHëpÔ¬Ph"|A÷+#—H¶n)Åt¯õC@)Õ}• ËÙ$Aòá8xä«p°R4 ÊÛm‚¶Í1co!žƒí2 Œqçœ`Ÿm«ãã´R2v~RÒR{ã½Vçß¾)®­×kQ±Gš3 ŸÖ™ó‰•œ–€9¹ßhž?*êIð§ÿ%™u^†Qn¨$ÓZ‘Û˜g üÌfÏ>68`’ùŸäÓsz×u}¡Z$M`^¡NÁ1Ê b 0 ¬aÔ“šPB´•‚屓u"ÿÄ¥\ŸcÚ[Z>÷Òr'‡î†ˆ Ê¡;@üIm°u dê¦* ·ÐŽgz幬„å‡,­r(.ÛâD@½ÜÔýXÙQùb6xã¾´Àª£7Rþê*üɯDssLòPfB9VÅæ+X§ŒÁD4º— ¨KôÍOüàn{ÈðŒß²õsÜŒ`sΘýûP‰PúŠÂàCH?õ´“à&Ú±þÞó¥Šh^ù€Žž±¢n¬msÂïõ:]Gc}åñ½MœHªåûjZOO©sãh¬ýÕLº¸ᬸ¶fîmxN+ ÆQÔ%&”9az7°½à#ùIOit˜¢c¦9#Ô1k€pzcû¸; úœq‡4ìDz„l ស:Ùµtìá°ÃÖé[äÎFQÑ0׊ú|å[§ ŒÓ¿þHÌ®Å߹د)RÊïÍTÿûïÙkí&×*}á€=~†]ú ®GòØÁþé5$R̈sNoY®¨ƒ8eɘ“P’è½&Bð0ö<…%eÅ_>,»«ZíÞíõÞ$Ýj±…ˆ &\o pn™/… |T¯Ýwi%•¡« /R¼£â÷î¦ÿç›âê&ó´Ü§ý!æy"¿ip‹žÖBG4°U#µp[,úðz´Þ¾­tEhÂj„‘°Ùò™-ö0_{(}ðƒ¬ Ûå:g,[ìð¾Â4"“9E­µ,ÐÒÆŽ\ Vi „Z¢5+*!ŒæAJÔáà3`Wã£íÌFÇ¿œ´RÑÜ(úÁS`K,Ói¨ILGÆî<ØŠ¦Sº5«*L4΋0tI½QK/FžŸ§õ ªz¨ë²•nüñR¿Š81h'á¯Îäÿþu½±5$xP€”rÀÊÆ½Lmhp‡3´«4¹õTÂìå÷d8ÓCÞ‚ôS\|ÇŸ¢ùsç¤>À ×A„ŠW,`§¯€¸(' ³„j‹Cï»/…µöΧùÇ„èD«Mß°™,{ÿF1^ªìÚ›y™E.}÷~ q÷¹ÝþC“d öþj.Ÿ]Ã8×¶åÝUÏ(탓(Ï"M” …`ž3°‡¡‡™=«à)ƒ¶‡’=€OqÁ^§Ž8ò¼ýŽkqÜéƒÆW2¶Äl+ª `*œ”:å9ô麶(¸µómþ`+û{/–¾};Ü{í“âþzé‹gšÇF‘W•Ý*ýÉOЧ;©'ôÅ=äìyvé'P)±ýêו8ÙPÄÑÞ0¶GÛ!ê(Ôžæj·ÊÆ\4dªŸ±^¨Ý+¬V.z›TŒŒÅ5­{”o¬`²Š)”†Qr@cß+ ɹ²2íõ]Zî‰ê…[Ö3¥wïÿù-y}…{¦·Ø ùyyaSã6"¾Ír]C¼èw9X7µË·ÙZKQLs[ìElÂjDýŠAãW¡80É_y2¹÷_OBǵƒÞ°Šýüövu@f:p 6Æ9p¡5$àA Ñ”j$Iäˆò+¶¯¦HCîé"ûÎ}ŸWæou¨¼ ã'ȱ‡ÐýÚîå¯(ÜUÆUÑÁÉpªÖ:uÔŽF7¯6°ð‰ Ñá!»h#=k­¥:¨ò>MQ<‚,Á5ây°ƒiçB‚F=¡m¢4U+öìÇ=S¬¯¿dI_ý+¿ ÞQ~#Ó*§An|¬‡· û3R·FxЋj ùo¾:þܱäîçÍBEnªââ…RÚÓ‹ëä܉ú7/4/ÍÁôúØv<¤7:êÖ"âÀØÛ³ðg—w{Nj_€§­‡Á÷ =É“•ðE·¨*=?‘O,U+Ÿ™’5-jsp?ræ¸5 5äu€~fI»pûʨaš„ùFtðHXÛ“oDdÁ„ƒT–M±­‰u2sœòpM$7æZÊ–c>ü½÷zÐ{÷ÁŸþ2xínazÿà•Üùƒëù³‡á…“üÖlj§•¯"YŸ½€Öúy£ë[‹!cŒÌŠè¤>)¬œö7b¶4§¿<ô(l¬F‘ÉwR7O>Íë4™[ð·‚£ c§”}Ó9ÃÈdÒrXcq–€WàŠe%k1„€²%Þóg}q?Íš†&` í…`ÀÇYÆ{Ä{òŒ9|4›êÀžÚÅ'åž²Û]/owÃÚ¡nÝP±ê>”‡|ô”Ü{ÂF¼;{l9môÇwYn{9ÒX³À ­×€u9g(ˆOÔ|¾“‹‰êî/<½Ñ_U®ß™¾ÊÐ9D#Üœ7+y×ü¤º°=ù Ÿªã~÷Åûî- ªò¡-‡lKÑžS„vD:#l0o²Õ2›GýëŠ4]«gQÙ¹²¥‘·R[_ã2eEXà‚RÈ„e€ô Oh/A¦âÈdÏ6¥?d÷ôçSûH[æk«¨ÜÇQÝÿµïö¡}òÕÝ&¯)Žqyñ¶-~%xæù c;¹ø§_ÿÚ1÷ÙÄl‚¨M¦´n:ú^Ã;°üGÌ ¹•‘ƦÛwD®öÌÍÑËKø?¾·ukKäÖSˆð) †=4}¥=;P¸—‚}å{Ç“{ƒ7LÍè6)Á?°rÞÁ:‚ò¤£o1³¥Ü,v{vÖÀ)ЉoûŽÑh\4ÆÊlKÙÆc”öëtH.=Kë`0¯ô¥;ÛÕG‚òŸ}‚ÎNúôÿäUñói_Ûôï?PZYNŸ> _>ݽ’“"ç:¥ð•§ÝTT}ýn›[ŠmB ¿/¼ÃNÔ1Sx$š÷ìözø÷äÓþêb)‚t»ñqûÔ³®Jº‹ËÕÍëñÉ Pȱ#˜{Æ8 mV ŸGY …VEœ¥¸bXÉY ¾Çå ×Íà}Ö›²gYÛ9ƒ  ¸ì¬ìg%‘Û çüg2Gz q`oùâÓé¾2ìéó·z¥ø`oÈBâÊ$¨ˆŸÖ{yU¿;;WÞÎuN*+RƒARj-19ù׿žDyS4sQŸ)zL)CéȾÞ«Ÿ« Ð ;õËŸnzÅ|~­lõLV|íáð‰‡Š•»ñÆ/À̪»‹íƒ‡£Wßélos½md€`l4ò96Ç6µ$ÕA×4¶‘ì9c­óÁ\ˆèa™ïB0JÐ./Ìdºí$!8d"sô¢x®­ü 3†Ù¶Ì›cæ¥'ʾ‚R©:¼;õ…w–ÄÁGóqÔÂö¾³daV2åK«”œú>ˆÔv4öX¤Œ+i“·UÑGóø èJÚÒ‰'üÁjkdÐ|ô)ëvþö³üùc|gY½»Òýðnx~ez¦su£uý¾ÙÎç´¢ êÜœQé09c4.ˆÕI¡åî㥓ç‹Åj’ŸRB5FN8ü>uÆØ Cq -±A^Áõi‡<°š ДïŽö»!ݪvnì64=áì)Ž<#sJ¤3Zg\¯pk+øÊÆŽë™ÇOýÉ/ÌíÎ#øŸÿš™õþôÍŽWèßÿ:Ô¼Ì/÷­¶-Œº©gŠÙÙì‡WŠNª ZÑ‘†3Ó^ Âcj,íœÐ¼¿øòw£IVàk—[«Ûìø×Ý©“¨L©(FÇ*Ïì°ž¢8h9Œ°?â«®õÖ0 ÕŒJ…û•=z»°Ø¯á˜qcq}]âÒ6æk.ïÙ^ªpî( ‘³ÒRLb-‘•ÄÆJ6NŒ~úg=z%s×é³n‚÷¯7–Vìô5që*¹6—fÁ€ åú¼âå^7éyJf iSV·F«©ßx6úâ£ás§ªGw©î¦hç‘ §zžÌïÜÓ¯z÷î…3E>»ܼÛþð}uó&¬m¨<—_}8xî\¶vß_ú¨xð ·÷ˆÿÎåluJœlYiÀ2†CÎ…:q$ÕaÏ4¸HÀYçB>â'!D0„`/:¢h8‚‘ó¹–Áô1:’'„r ‘mèç }ãRip*óÓ«rïCù(À@)Ùuœ­- '°qFˆñÚF3€=²‰J [Š[#gpAKzGŸðúÊ­ª¹|Í6Ú¿ó³ZGÌ@NÝ'”ó,Ñ ò‘-¨•öõ¦úÅÔ.Hwê­Û;Ää £âq5‰…Ó™ÖJhXZ@Ÿ¯$Ͷyô ý³Wó««Å…ÁÚ¿øFz`ØýÛwžëßÿª©Wî_m(þ—eÚ0£%êX¼9—ZCý°¿™·Öy븂 [ÞΠoÌ’Pj‡s¿ÍD%‡$Ç‚„ܫחgq"4j[Ü]]·lш&¶Ö*à~IëàM ]1¨Cý[H-ºT°wŒW¾¹ÒÝÙRมål]–S‹÷ôؾÊÌJ·´å[Ü€QúË·sÄL[»ì8§µ8VVbËì…ãÁ©½H1XÏpŠ…Òºîø ÒE¼¶ ²¶Ç¬‘Æ@lá‹ÎÃ2Ð'ãšlôÔŽ‹O©Ô?åXð¸"Šv÷‹ < æbiõ}2UÂÈŸÆÍUDÖ-VÎèGõ‘\_ßì}ú€lné#úMG⤑By¤ÊdõÊ:²½âgê÷6&†+3ÓŇ÷‰ÍN¾ ›" ‘½€É7¨·ŸêÜ*ÇJVsä™>Ï[\î:-“íU„ï:†] µ'mœ –;ÓC²Ã´/XÁ!˧œ«!ôӀÊ{£þ!yw+|ðf>–+ßá2l›Ž aÀPT‹"G¨O½Tç“’¾±`B‡ÿ ÿ;t£Ê¯ŸÎ²/œª_85ÔŸì>Yí xo¼ÿá]Y4¡Nâ}§ƒÍ…ÜZÆ¢¹Î·*˜°ÕfêW©WR y‡Æ‹ƒûÇý¨ƒR¯ã<õ/M“B¤nØ4|à=SvtÁˆ6²VKðü’6‡?Q˜šÁ-æß5g{2€©üìAzv, †¥š§Ò‹Kßx¤ÆŽD>YÛT{ö½9u °Ú¡ZŽÂñ¿ø/iG«Øù=Br¦ÃskúÞB²>Ç>ø,Û(Ë  kQ¡ôËâ?þ†`¸ùœ|åñ¾f¯‰ƒShÇäY›F…ÏCE'3 håMwœ*4-ÀÏ×PÌÌøOLd‹;ÝܰÓQðƒ… lÇa¶”º’´©‡íc}ö_&_ƒóîÉÃìðžpc M÷H‹Gã8+{Ǩ9ð,’ûÎò ˆœÆvëÚá±óÔ"ßQwþT+GEÉUÁåŠØÈØFßûQÙ‹›~Å{ë§Ý~áS.nûcÈÎ é—Ešœpÿþ;&®Fï>PÚU[êõÏYFp¥G™.{WåJÇœÚMüPïÇK˵™n×hT5£ ‰J&Œ}ª>,plé{žÿª GÇm‹8HµL š¤Õ=¼û Ù]0ʸÛ>e+ÒE:gªªo cT²öÍ%ßBæÛ|í›üàW/e%°>b]Óþį¿!¨Ää¤À‡¨•ò¤ÛÔZ’ZÙVs›ZbÎÖ¿ñL‚¬]m“ÿã!ûûÏÅmûñvÛüåëò5ÝÚD’•…vð%ÿŸl¿1C;U¯‚†ÖHZgeض@fšbÿÙÒÜbç‡?-OŒý¾LLQâš™rGwvUzKËnhŸðI*K´3'wÜCdÁPÌØ\Yç[1 ¶ÍÈ»,^QÉÁA÷/ýæ™Þ…!}xªôÌ#ôìh7ßQ$’Vx®ªuPZ¼Ô0¸Ë‹+ÞÖ¬Ë=Q{¤ö³_ä‹IÞ@tESºÄ9¤™aœ)G:U¦\†*+c êÌaýëÉX§›=àÕaæ•6¶»ýP쟴›R¦MTÒaT‘QZ]Ij´-snÑx¹Ð©Ž ¨ÜGôÌ ;pº–.ö’ŒÐ“Q‹˜™Yc<Ó6%é$¶¥‡Â圑‡ûõ}‘|ózlÎõ‹'£“¥µFþ c»¼<€óØÂ´ÊçÁ ¦ÀÌD§QÅ ª÷ Ç)Lõ›ÿ×oýÃýW祈‰š;æÝ«í®¢{†¼j?…¬£äý½íŒžØ ,{Gae¹ï~¯« -›á¢Te{Á!ÚÒ#¸¬(W’ hêbëîó¼C ß@ƬE'¦>þ%O{rΡ¤ïþ»:È¥9¥ƒ– T|iòv¡%,ƒTŠYZ:3TùͧÖssâç)Ýþû_¨ºéõEÛMû—¯ÿñµtk É œKúû¯è𔹼鶷€È´ŠÇVI¯„‡h¯j%7Ǽ•Õü¯OMõ*ÖI¦*(àL˱ YÛRC»‚Oâ¼ÊÛKr‘³ë„åÊ:߈I0M†ß!á²J ¹¿ùBùw/ØGG;1ï©‹èá)-r­Mµ3F€åÔÃ>ÑØÚúﯪÒŒ öðèk?U½^ù=œ·MÒFZU`¨ÆFÆ)¯r F}ø¸þÎÓqP´6€ûcòÐHo`j¤YHÄfáÍÝœ3GOûßy¦zóvÚÊõ,ÓU÷%pÈSšúÜH-sé²ç¿"†÷–jgð/ßèÊ.t hZ Îbç€1ƒò©aï¿36^n,¶U; Û‡GÄ‘êÝV¶Ü°Æ(Ñ̛ԂÑÈU[¸¡ø‰F /âÍ~pS(¨9˜,÷Ï®o>²t{©ØqôçÌî8èÄ}Q—¦ ¸ÇsáTâܵsÆsâFÙv/˜¿¼u†E˜Qæ}`Š÷hÎåдÝéGnP˜§'ŒTk YÞu¬Ÿ¤L‡siûÖ–=}´´°èýüZúâ ÷ÔY³³Sÿé%ïOÜ{Ðô1dÚæ¯…Wj•‹RVó<¦înì~$…ƒË°ÑÝbcƃ‹ÛYĶ–d¢Ñ¯(¬Qh£´Ä=o*_ç…qºcuƒÁ<‚Iƒ}ê*ƒd«ðæ?Ø:‰KƒÔRð®[ñ>UHô­â³ÅA`å"ÙåàHßÐÝ^/u¤ê Sj&i}ºÌO*­¯ë¿þ${é¤}úœÞܪÿìï?ü¤w¿á› ”ù©Ò“{÷ Çé·—x T l4¬ñ¼Vˆ“àv¬¹±ˆw>”ãÌI1ºÏQQ%.'> piì¨- xƒ£"ŠÌÆ&±Û:ÂvɹÔ10Úz5„‘óô}a5¢ÿä¹É3{݆JcÜ-›íFÞç©Ýûlðí^F‰çŒ°`”¡TªÐA[¨g¿Xu£Oï]Á«‹*qyÛSqÊ3⊪Ȱ.­U¢ôïýÚnƒøô2M>!÷fZ฾{n~ì¾SÞ!Ûý#Š“Ò›Ÿ¥«›6„âðCüÅ]½ÁÃ|z2]‰‰LÌv}¦†~'»ÔÂÜ¡*xâñ¤³ä~þ>¯€–n°‹Š¸¤Œ4’ä`Ù¼,Çû°LÄ@yXt¹&:(AÖqõÁL{!ß°x ™­Aã—Å»Y~1D+"|ŒÚ“·VMÜoÞ}Ÿ_[cxž[Jíf+Xøeuð a“0-»!½¢ÂU+²&. 'ÿ‰r÷™yŸÏ>Ïœs¦]¾½ÓòùÁ}¦úúRïíë¹°ú±³“ŸÍu®ÍáÛwÐôÒÎŒKæíáÍ_g°·›/[øõ· µ =À†é4F^¿‰ç¨|3êK{'1L7ÇfÙÆþUÔCñ5€ª*ip†@ð²(ÿˆön½²)¥HŸqÁ.¥>­©«å“ªwÔ÷PÜÆš êº,H©êàðâWÛw÷Fze›¬&Œ²N·¶øÜ]}yÎùeõÝ—&öaã}=½²"hÙž;TKvÚ=í^¿ùTö‹ÿbv>­Rìó?½ËPX0 £±ójQ²¯aÇcº¶µ…ÃÝx¨¢S¥2æ _ýôr±±>œÛr¨n¶l´9íMb‹¸¦ö=J¥ÉzN¬XØNYþòE}îp³Ù0¸™`$/VËi‘–â`¬¯ñÖM¢¡ È0›ª­ÑÞz;¾0ÞÜÌþäíþ_~–I£e™0ØEà¨c ‡N€ ²Ñh-øÍïª õöŒà ÓIj¥‡Å‰ƒa†’ëŸd«¿ŠºwÉNÆŒÖúµ«ùê.S±çŒxz_ºk¯?»,Óð;¼iõdX çiäh‚™M‰ðÉ'[;kòWï•"+¤ïáf"«•°9ûo¿(¦†ˆNÅ`i2méùȺ¼6¼m0¹6lÝล¥5šaÏshÔO27¯ÂÇØÃ»ÄÆ†­Víï¡Ï×ÄÐDA‚ÀXŠÞl…~Œ9qŠîÈtÓÇ× ¼bºãÚ6'ÿÉzrî^Âs³ò¥ó¹îòÛÛº’‡zëNÝXí]þ¼ØÐú©“w¦{Ÿ,ÀÕîÞÁÆà’û»Êíß@nO/ßÿWœojê<˜v6Ðbd\—›È½£F±µÏƒí‰E¹~d vXü¶ƒEÙ¾_V°ƒÄWà9¯¢c¥Í~ÏŸêjÅ4®Å§uú™…½m§©7¾*:¬¡r(‚ã½OX»“æî’n`µÆKÎYŠõf#˜¿«f׫]Òû»_™úÉÛÿß_¤W7$¯š3ªY£—XóB­ò­gÅ«ÛW¸IÉ…óÁ¥k€üŽGh.AqÅe å-» 9¢Ã­ ]ÙWëóÜ(U‚®±o~Ë3tï‰,Û4}¶cÊ[÷éd ×|½!ü¡Óˆ [ŽV¼ü°9¸ÙlX¯Ê·]:X ¤4åJy¤²ùö-.M/¢« 퇾¤Û½ðèhïÈQòÆÛC¯~Öì¸8–¦¤má¦W¡A¨àßûm÷ØÄöLng¡°oÔáÃeC‹ûŸö¦AÈ—Áß𣧂åVûí÷kããàÛù×vŠî´Ú÷Pyf©çw#ónáyÀ ¯[ÖV:Ö;ÈÙÚj–áòvmi¾˜¬¢œ“Ÿø…ž¿þ¨‰ŠŒúþôýÞÝ_å+Óšºj ²$¬‡7TªB„”A0! ´“_Á¥j® ä«]¹‰øä@g«¸úª,­Ùé[5VŠêõžäèÝïõí’›3e¤¶lØ^6½šçeH)õ¨yædmá5wDi]@:è=óDû£›°Ñã¿÷8ù½ÇÚl×.?ÝïÔ†‚åeÒ-ÀØZnA=­'_ÒÍQ ×xG“esq‘)›+f #m˜_EAK§Ë`vc4’ák)–‚xªÍ†)†¨‘ ®=0æ6hI}cŠ]HoCQÜyä¬AÓ=r*QÛü¥¶-‡ç·¸‘:g cZ ‡®ÑbLìó¹9d€ª‰¼ƒG™kJÕ̼‘]øÒgÍKwxµä=qXü·/CÍ'¿º^ÙW·ô4}»æß Xn؇^ðîÝiD†¤… b|PQ•e*ﬗǎ§}9ÜY­üâ‡|b–./÷Ƨ(+ ]¾)–>-‚L*:¬ËïÓ‚Ù\ĹÕjUšýÎ#œy~Ë-óùÏíÆUО6,KÃ8¼¶„[mYÉ` Ê`' ˜IHiøêJþÁ{=FQ—Z$MŒ TI—„‰kÔVT ¥_þVwÅ¢ŠODpé6bN‰ µ¸<}™ulÝáuJ÷Ÿ k©z÷ŽýÆ#ñõÕ¢¹;[ž]ÊL>ìHš T&})êVŒ•àç<fzqUôüúê6_ŸíÌÖPÛZ,!4!çB ú_}Ì"7ŒÍ.ˆéײÙ†@é¢G‡&ÙG7e¯©)4ö9ŽDö;¶H¥ hµå:á#ƒõÞ¶¸ñ«l‰[WCäÕêMÛ7ÿÒß-»Ìñœé»²D·yí]Õö(F€øÂô¥sÕ¿è·ÆæÔKÏ?™tlw¼¯OþÞ³†ö`-ø|Y}4Ý †¼Õ5ÝË4!ÖXltwµxýý¶ddz¡d£„(ß„ÖÔ‰W„ŠøU÷…¯zÁLv;«œ¨¯^5CÖ¶;fß11T?ø”Mµ ™¨Š=›‘¾dy¾|û~Yz™?ª‡ùæ_pº*’–{á Gæ®/XTo“¶oä¨ïJ1JÍ|£wUë™êܸ¯8 аŽcÖ‘‘¾è‰ý†³•>¸œ^¯ÐŽ\u•ñ=1XUfú—×lRPN´¶”!œçj ÅmÄA×m/¨õeõþ–;ºej<‘-ßI6=/>DÅr{}‹#ê„Óu ½ëtj­Uóc¬ûw~1¿ÕØ gºÝ¢>päñ¬¯DöWÇ?˜o¿y?¿pˆ~åxõÔÞäĨ¿°ÎÌŒ$¦PhmKæ+Ò`Í %~ð¾ÓÖq¸°ÔYÁÀK¨F…­ÖÅnȳ}JŽž½ ‰6Ìñã×g4v:Ëx’ÒœYl¬˜•¾`Ü#ÊãÖntS»]Ñk\ßÑP¶D˜,§ÎÓaf¥C`Ã4‚„˜S(ð)Jœ™¤­š¶÷cm„!Œ8ãÚÛ, Áï?þýúÖ©úb¢þÉ_f”¥÷¹`÷îÅÉÌRe]å}{û&N¶ê{pupʼnDY—Z3‚Ü(†IÐ à£û¼Ò÷Öçfû-µ7ÏC$ê¿“¢»Eë–ÚÝá4Üö ‰ ̬ñª!VÎ7FóËaþ¥S3*üúõËxðž/JŸéNÿ‘(Rvs–uºB[£ ŽòÞèù̦%4ÒJ müáЙÀÐÜðlÈVj°óÝ_ß·ùö ºiwnö½×KÒ˜>0ÎÇGÚ…÷—²“»Ÿ°£Ãru¡|ón”¢n0.ÆGÉÖB2Û*ñÂ׎Ýûä>b¥<î±<©aÓÇ i U/…½bçÞ"Ó¹”-ì¨Ãư"˜¬>3¥:ýƒ¿úEkï ­|IE»Ö8׸H_¿ÂÆ`scPDTnÙI®§P!<[CQ¹‡6çåÒªüp ŽnÉȹ*¨õ{ɼ¥ñA ÛÅÒjÉB!­©Ø$ì5‘f°²<>Èvþð·1 ;›ÛÕ•n’T÷=ÙŒðúžw¬0ÏÏ0¯ /"‡‡ÄêVíÁÅ8#$FºØ½"Ù)ÞL-0ì'€ÞqJ!æ¬Ø“X–ëº zÈŽ2[Qªïx&C¬›“&8„EÔ7£èT,a)µÈ:ÿ¯¾lñcšx6¢ÑÝ9^U[È\×´b˜4E—6Â…gœ¦^a)¶¨Ëô^Äú˜ô™dÊ«^C]c­çƒÒY·Qx4úƒ§Ão?D¾uº²”ˆüåùßyÖ?v,•¤µ°Ü·¦óÚžò‘':{÷Ö¦?  [Ù5àr ÃX XׯL3˜¶öà\گ߻ê–_WûЬ¬eÕ…ïæ®qW4®«Ým¯^£TH!³óÅÈJǤE¸^&¿vÁ $0ª]¹ÌªÓr¤ˆ?³½¾“q,„‡Âó´Õ•Ê8k©Ã ôra“G0ÔÎ cýE’%j…•Üï•-sùoÿÆÔö‡ëþ¾uÛ‘ƒô~·×K r}{ÆÉäD·`za¹ ûo•†kàÛàÚmïÖÒŽFpê¡rœ•¢ÙV ã–ÚwFœ=Þ¹ßÆ"9òeÀ;4Z<|Š|á)þÌÃíÃûá£O ¶¸mLŽ "œX«åª!ឦ& èÖœhlû=R íwS»Š^&coܯ´SƒœF”Aæ€ÏyhOá¬D|lXl` ë/öU6´ˆðÀ›8ì*íšj»Ìýû¢ª=êÈ[LÍ2 eÙ!lz.“`ÿE\?X:~b{ÄÓ†72¹ŠÜm•;Ûµ“ã;QÕ¸ÞºF·óãaß0ýJŠú*Õ¶.ö$ÓfÃ#ÌùDËÜ€=I“ÙDZ€?Rh ?êÎ,¿·8¨ê]“½&ÛØ++Ó§8@ЕªìâuÓôëdò°‰Â²éÄ;I»àhø@§v¦Ÿ (Œˆ4(Bï’Ø/á<‚„üÊÓ³j„ô:[xq]mDÆÔ¡ý>¤¶¿¼ñ‰ÜîiíLÀ³%„ò,ý¯Ãù“ÉCÁè A(Ã:öŠ’²y¹}¨ø¿üv…Csþm=I±º3ÄâQ¼²¬R™ °{Ôù5;qÌÛur ¿l°$Wo³»KMÇàÔC,H({ÐÝã‘Ùm3t¬ó£å[ÓC9ƒ’ÄñÊðò»O¼vBéÝd݃8²` ¤­ª³G<ÞÕ:5À-®®rsH#lÕ %«±³Nïn.rXú”c«Íd¿ð¼­¢$IÓûKo9­ÿú#手Y²â÷ž<è—O–ö´?¿mÿêƒì^¢iápH‘†žŒÖQ¨ÞÂæ‰o…ƒÇIÙ«²veó~'cpÙ» èôN€õ ÐÊéHáü–äž“N…qÀBþÜá ( x²Ña««&׸4$¦ös‘êZ•¼õ™Úêm ð+ŒEJYüÎ7á‘SéÔÑ`²ß ”cPæcGⲩ:òÝoñ²¿sçWîÁ¸nÝ«ws©eÝ#S´V"»Ž”Èo^PR2 ¿ø¤k²a&ýGΤ‡«éER4pÖœÀÒ…J‹óÙ³¹ žxÑwýx©U‹ÕĈõ=ïÈîX§00â9c4vÀ8üаTLÄÀVQPÙí;žXeÃN/™K÷£T Æ9ƒ,sô¢Ž«–4¹ANƒŒ ÀÙ;TÜ ÂUmª|âTßSOi¼µ-Pš!¶vSí±þ-kÞ$4¦à+ÈÏ ©²³›þç‹ìÒ ²ÔnTJP÷‡û5vêä¨]™/.-öÆ+Õ»Üÿ}1»Qµ[Œ…•¿#GGÊ0øÛQg©gº^À1»M ,Ù@‚¼êïÙÒ&’mëEÕx´/€Ήe(Lxû÷di©œÞï  ‚’u€˜HPÅÒµA&ÔÈœ£%Ðíè‹å½|®ÖZôº¼B¢\iDÒÝ(ÿ®üÉ1ãÔ¸“ÀŸ±lÜ*Æ`[óbXîúv=žF‡{ýŸ@Á ™Þ/_ð/ÍUÿë'‡Õ<íPå*é&ý7v’~Úúá{åæÈêŽí÷ÝþZ±˜fBkÕ2ã˜Ohr7q²/,uýN6º» “$ðÖÓî]æþçõ»óÜ#vÇj…1#Xk¨•„ÒŒQ=•FŒO1G|ŽœÆ8ÆÉʶ÷Þ=¯'RŠr±sE•ògµ7`Ù×Öin!À¬™Áâ^/æxSèÉÓýO<.Y£e©mÁÊíâ€à0þ1p„/#âä ÊÙØ>^doÝÅÍæªïCÔ74ZVÙƒ°µ&ßžïŒÆññƒÑÿí{ÙìfŸ±¹Å ]þ;r|´¿µ—Ú¦ÃÃÐ(sÀ”=Ç: ˆÇ,ÿ&”V™î (}{ò싚ŸqfÅJáÞƒIV­Ë»=çØ' EÍA™î*HݘվRµÃò Œ.¢/ô˜hnmÖå½`ÍG]‰ID(2ÆåïÊÒÕ°•1;J¼G¤9äc¶ayo@Lýzy†ìíV¯m‘; ¤‘ÐÙíô¥óÁ‡KÑù¬÷ô˜ú»Oh*HP2…½²ÚùùõÆ÷Þ ßŸ†­6-3ud@ÎwY'7 | ŠM‡§Îû~µu“‘=¥EðÚZ: £ºâJ:» “úÚ ˜T,÷­·€L×iƒx@¤´ ì2ûÇâVK”‡œJ»Õ‰‡¤Ï%&.Ùö¿5oJp€2O:CíCœWÃþ©½d{3cÓzjÿà/¸]ã¶…+óÅÙÓ᱓@raÍ´89ÿh!ôÑu/ð*ˆ´OŸ÷KY&³‚üíç«ÓEåõ ñ Mž{NN ú¨§âPÄôwÓO>¡óËi;sçVž}¼Ø¸•/þD÷'êóÛhèøž«sìÖv»‚   +ã,ÅÔ ”iˆªÙÅ^ÖÐ×'U8ÞÖêIÅ–*þ^rÕZâ81Úr ü¬¯Ü4²ÀnT±d~ÌÌ-c¶,ÈBFqõEÝTé²Sõ:‚_ý€ŽìˆÃ/­lh $F&ÿ'¿7ôÜA|ùj/ ”™há÷îùßû$™Þ”ÃÕ¾SÇ>{À®Ýo.Ì_]ì ”ú¸$Iñk–×y>ô-oy Å|~–K;ËÌ«L\'2E ÛÁ.åâqZ3)óMP9UÃàV®ã#õ|¤N?OrÚsÃae-MvÔ9f&¬I-yŠÆ%ÛíuO=é{©XÍÈÒ}éz›¢Yã¬ÔÜVdÚß³€tˆYòÅ6–1¸A‰g;ô,ìl«©XÜëLZr‡(îbÇ’æ¬-öÿäÓ­jTúç#²…ÿñ|þŸ.ÑÿÏkí+3(m»¶M,…>]üß¿=yäbðö•A‰ÙD3"œ9ä4µè³Vrî|©›Êo$î¾Nܺ ºh,ŒþÔ³e„öioT†tŸo*]vU†Ak5)K:<æ"+›¡a½»Ï‚óuW–ëþnfŸÎS@–ä,9d˜sU@ëHôUúú*ïÿyc,ÍiÛ?‘?ô˜·¾_»ßé´Õí;pgFT'K|,ÚNö¥Q,oß´-¡›2ßuÕC5R)Ç¥X¸ìvê½~Y¢"`æùçÔH•á°SÆ:*¿û¶¼t¥XZÊÒž;r¤ô…gd²ó?Ì«]{ó>­ª}tÏÞÜjÇÖt0(Ì´uÎiÄRÎãåäì> ™ª4Ò—4)Ò}YWúÿôÍæƒek¹sÊYG .C½#D6µHÑlÛ1}͘¶ƒ"þ?ü‚î©tåýƒ^0Ä~þ½´¾ãj”ýB[YbSüÿ=þ•Ýü͛ݜ®HÛ9yç6ùùGâúvÙˆ¼?>{:¾r'¸ñ µ´\ýx&‘¤ç“HQñu`Už|ËÛ]Ú@¡77ƒF¥cæ *n1Ý•ë`×åbÆY#]O™5O´˜ì×nÛº½~ß@:^#×{)m»á ²–'û:ú\`wiHS)5<Áhl³Þ!õÔS±—'[ÒÖ½¢éÉ×=9£U"u¸CM‹w4`ë:Ä-yù6²12CšÎyÞÞ'ô±]½ÞˆæÕ˜¤w¨ôP¬ i5au±ü³OÛQü‹ïú:§Ÿ.˜ÿø¾÷ïÞm]º£óŽë ˜_Qé¿ùÎðñ‡¢7?í:s'4ƒÂéc„ac?Þqž¬vróîͶwGôÌ2qy–K°‹VÂ\•’½Š7±I¬ªs[P3mp£r†9FO•C-Uì†ÔØ q8&­¢ZñÿëÝì£Yà8a`±0àaÊ€^Qëí«¾ùçí©,Ýwƒòü#qž |«›vÕåzÓó(Àåõ/…Õz^ ÌÍÛ<ÏPVäýû½‘’‰Ë5Çð‹Ëúûïå.…ÍkÄ…üWdŸ|êݾ•~'ïtèz"íÊ~ùî½–r²/î=HCj²^k™Â“V÷0K#ß™ (k¤q3ëazûF‹~ÊLa(cDì/?éýü&8CµÆXìÂäm¥SâGJ£ˆ”ºBd&¾³F–,o*ÔçcîÙÃiÝwžAªohæF{o^¼ œ¼¢eͺãhð±Ð̺[û¿01ôX«·Ó6˜ÏÄ (¨4Ç ¼SNóÈR ™µÖíµAŒÙz%yþ¬‡c=ZW›SQ÷š8èÐ #}§eVþk—Þ¹ÞþŸ.>˜ë_möª,ØÝÏ7;ÊX6¢?ú=ÌJÏñŠ‹®-w= åP4åDÖcywn¦š~ê†T=2õs[𶬿ˆ¯Y÷n`¶œ;¥(2ú6áÎ)0aŽ®u¥/‹ƒ‡ @Ìå¹S¬â#‹å«7‚ÿt 9u”ƒrä€XjPëÒ¢;4ØBË%È,õú2½ó×?j¢ªjwm¡›¨¥it}º;}?Ù¶ÚÛ eº‰úþbeæ{¹6£7óþ^nöÆIXNÍô]½Þ¢;ÝÐÉn+-Y½gRsϟÕU\Þêì;iƒQïÒe;D傉(uŒ"{ÚQß( V~iÚ6-vDèP2 Ë«Õ÷.|pC¦Ê+sOØÜ9 ˆîöÝy!Öhð ¸mEXãÆ9ÏsH«i‹|uÕŒÕcŽÚysÑ@¾òØ;Vm;`à'HW¹ûÎÙñ¯¯Þ|êü9úÉ´N°=>Pù‡_ï,•Z]ðn¯¸{÷º(kHìDÏÅÏà]çÃdGd®)ZêÊÅ.7li)¯jv¹ “~)út(Íœ*›dEjœ¡ 9a¡îl{X5:èú‡Eö±ŽåÄ­¦½éz0kÜÁk>j$VŠˆ_îÝÍgÓžG—Aï;gØ k,—n™ Jˆâ ¸Qšµg¬·Í²ýó©C*™wW@û³"oˆ#¡Ï;9h‡.ÓE¹s'ŸmGCÃñ#å·NF_¢7¿ZžY)¤ÿì»aqü£¼±(í¹¶²Ý’àYZ€ P0ìÄò–Œ:ňbaý}ZëÅ""±ˆŒ7°œS:QžÆhó]ØÞÑYÛa`ÈhÃçÆÎ¬¨O›¥¡€–Ù•nnÿä&ùó·-X6Å>pãÄe'”Xâ\x2; ~äœ_÷õýMÙqjIµ_×S”le:µU N]ñC‰ìv‡moÉ›÷ó¦Òe~hRh&•g:×çÈzVo%j77Øàu§ïæK›Ðɽ\šÀS+3ã SÖØ®o˜¸üô–húøX埥{xl°^ïn$|1!·o¶Áמؼ-XùI3vÎ Y¸¦hKè7Mpxu®(izLFiUˆ>‡ÊzFi`“ÈäÄæœƒNbS×(¹ñ¡Ì¯R ,Çf%MT‚9e瘿™¤ÅKe”:÷:sËi³fǨ‘ð9"Eh©±“`[š1 #´QP‘ÃŽ¦$Ûu±l¯–«üÚŒZ}/eFióáY—„ õ|OÜ»'g›ÑȰÿðÁì׎†ß|º·²50%œ˜ö»~rG]û…ÝzPœ:4úùR³%‘ï°pÖ9@ù˜!‹[²’àaA>¦ê¯i%3W’ÈÜ!fZ'b^ëžâҡ湂MÏb¾s&p¶ÐniÛ\Yæ>b¡nX÷ A~t›þå;¸¢Ã:dûÃP`ÜA#‹,@÷ø6KøCƒLÞÜR#gÇÈí_¾Î #+™¨t­ïlQöP†kíD´6èÕ{"Íl`v)ó6’Êõ錢¦z' XÓÄ#‡µ[Hz kÅÍV€£Ó¸.Ý20á×áéW²/üóÐleïÞpвÂèœç(³ÎXY²°ËªAÝgWx‚2xã£êŸ´ËÈ^$ áÄ×Ï #dâ X©† «C¸e²ÄG,çÜâ®²ÄØ#†k• ¢vûE)«¯ád*€NnšX/ 2€¼§.ÝtÉ[xÚÉ—Ô÷‰ÿùëåúãÖÛ³Yý}ôë_qäªÈéàÿó§zaKÆ ZPÞ[nžî6SÇ4m-„«kh¾ÚÛ{—öQ6 ÂÕü¿ö±éMìöƒ¿´È@âŒ5c~©•õ¦X¸ß¤Zy«oä;ÂlÁð6JZ81–p¼×ÚdH) ^âˆ7*{ë§UèL>˜_§tHÐJd_¤°\˜>/,çÙ2B¾qŠG¼Ò¼è{µr‘v ÚÃ>úÈÌ\7´k˜‚bG§ôÝYK¶Ìr•jj˜ü£çýÉþMN"ÊÿücxwVVûàúrµ¦Ú¿¼„žÑ|f£Þé.<ûÐÐy«] Ë-¬[¼Æäf{¬é:C„ÒpÍ•ÈX¡vB1Ó`‘ÉPšÒî ·š;g m`z¤43-þõ´ÂÀyI§©Ëcšzõâñ¤Ë4,ƒ±Z[g€Æ4ÓRïÁ‚yᢩüîGoÿ4ó9Z7Îq¤LSa¾YÐ2èÁ¼æJ-o<¶wyP$A@:Åö9²,Ñ;QèGjCyð €ÙKéFX ,jåX ð )L'Ç6TªêÌå÷¶Ï?Åžÿc«ìõ+ Ø€àž³€‰gÀ‚ L@cןºn\À•[C—onW"‹ä@Ouˆ‚ôSè8kÀY@Èì ßyÂ1-(² `kr!Ò&%y?ª7q6BQϨÜC  ©ÈÅ“a"–ùBõqš_y'»pØÿ¿Ù÷¯~ºóÞœ©^‚ßþµâуÞo_ÈÚÙàÿô£öü– ±jAu’7ω¶tô”FÍ…¾•U4WßÞ{”• 5"üåâi¿~Õ¤“Ƽè?»® ©:®`2öÛ‰˜€øÈBU–ÞélçrÇ v]Ú…TaÞ®FoPe´ôºŽƒ²×¡¤[rè`»~o¶¹›(êÈ2_rü~šM¡>O5æ¹rl*æto;3ïãcÝÐ\”µ>¿if¯#Ò* Úv™ÓéÖBÉ̉:Ïp†Š=ãøHQaJ5^(EúKÏÓ/ŸÖ¿¸m0ŠÚY‚3Š Ä!1AâHŠ‘º÷Ü!³k¯;²/œ]£òíVB"œËnà¬4Vú` 0ž_Ÿ¥=¼ÔìxmË‘ bJ†™ Î…sŠ.…ä–È@UÇ!{ˆ™§ãà`^§á ªõ—¼W$JÀÈ㣠OXç)Â14Á5!2/ð4îø…cœÖÈäÖ]q‹WÃ[ßQ¶úº®rz²zôЫëè`PÙ<§Cã‹(±Ç÷‹æjß{·u£!׿}cµQ'ˆ›üIG¥þ¡.öÄêÚÌskŒWwÁHΚE+{¢—Š­†ëÑ!¥z,i¼+Ô1T-Ø=Wúä—B7'¨Ð5Å‘s¬U•"F¹Ñ6t…&ÖC,pP *SaD+ö2=°bÕ ®tíÅ”ƒÞôøºëóÂ/‹Ò‚)zUû]ûh½:³q ÇˆešÀ)& ´Ú"nÖ™=üˆ®ˆa”r»½S\žº4ýÅ»°ÏÓÿè7ÜäWüphƒ^ý8 P®¶æX;á©‘à Ï¢ýÎ-¼ËÅ› V¡0Èji@Æ2SRæ9ˆµg=%°ÆÌv]¨5ÒIÁ…¸4¡xé${Bß`Ñ1ÖbÓ1ö†³;q´XИn$´eÈ„ŽØ ºö;´˜Û¡¿ø$uDe6ÂÈr ØÂcy¡FÊÈS¦RrðÝøÔ¾,JѽYb{†Ó¨á g¹uÚ€%QYˆ¡ 騛ÚoˆçW‰I4aºY?œ°¢ÉœÀ@$–%¤wWóµ$X쮃×U T’Q\$’¬…£›Fµ‘7/Ú™ƒÜ<é³3Êí3dH÷W#»¤LÏp–r:dÌ1„kœÍÆv«ø¶9õ°ÃE -îœm1¬¡â&Ï{Ì :º+y3¦pC¸tr”ŸÜ‡½àŽ'«ÇÎÈ0¥¥öÔ~¹µT~ç¶«14^Úó'?_hŒ­,1xÄÚ“š^—ƒçk4dñ"Š<Çm&;äBì†D¶e“"#|¸ïÐ.Æc¶*õ]ËÙ{1ÌçA®†$%˜P#«JZÌ1ŒB,5„b#k¸Ç°Ñ]QnýE+nq7¯5•q Q`Ö™Þ°äxÏÉ`ÎtEˆñžZãaw6O(_K—Üár—…-c׈Ybn*‡’Gçeb¨+°ÝÚ)Î O~x/ÿO—Øh$þø7a0džóXy×.uR>¯j×óË´ÕƒžŒ§¼©Èd€ÞóÌ[X¬¸Â"ç 0ÖiKL¤°¢¸šª—!´Ì›GÚ£Ä.b›P[Ø‚#8Tú ÿ©R|¸h­D©m§ ±mîƒÛŽÃ¹Ümi× Œ¶ˆ¸û91~ Qîå+=ïÇïZ YÁ CY:Iµp0•;åh/¦ðëµsGD¹p·gµéˆ ¨¶Q¦tLbÌÁøƒÌøˆ=y¬üæëùæ¢;s®²µ#; =ÅÍl³­‡ÇôÇ ÞÕgNó‚ÊàýÛí²CÛ„k+ xÆ©mÓ&Ü1E7Û† Ok75ʤ¨õé¤=.—Åmg ê¨"è!P8òt½ëgÜØŽ•wÚ 㨲#Ú†À=ލÓÖQø°Ãל¾é°P8Íç[É/¯è7Æ7´fny'·Q&uï·G”š ¿š‘›ù݆FAÉÙl.*½ô]‚/˜Çj„ozò’’·Ac§¬áÿÆ8‰›qØi‰¡%¤ûS >û)u[NY †™r(­#’¿t Dd~;ó½0Qªûä^tvm¶¤V8¥´^ÑZ'Ø®X†Áž’ì+U?èÊ&ï‡Ãýg½Ã/ %W¶ú7ñ ðâòÎ4 ãê_@þ‘²G'XmÜtšÈ®g=—ètƒïÏ6ÎúòÿýýRç°™÷f:ùgÓn[x×ï”~ñ¦÷ƒÝZGçŒÏ9U]íjÎ1´­`Æ"ä(£¾ÁÒœ À€LèÌ–¡3»ØöyÌq”:§±qŽ3 B›tÁ}ßWTT^´®Eǃ†©wQ°© aSÈÆÄ`L,ÛÉÔc}“ƒ¥:Ïh‘!¥U4,ü‚í#Ñ@–´GÇèËÏ•g¯s3dt_éÓ%‘4=JmG¢˜p8¿Zg6gNUßz-_[„ §+«|«c¦*夷¡ˆ ÉÀ0(F›p¼??yÇ•ÑÙ;iÕè6 „•À|§ !mh‡וè–å†À:²ÚÖÒi 1¡±u€ÔcXŒÀ8|ˆØ£Î¦´Ã ™Ôkw&4$'¡£å°†G>fñ]m®Q# Rã-´¯^·®Ïm CíÒ¶pq¦Tc31€í[‹ïÏèÍuu§% ôSÆ=‰èªSo`ú.*³‡DoPù±wAbÇ÷#ÅItö[£(nö¢x§—íNÜ—=8R0 â²+”lYkuì,‰Ä¼ YέüÚy:ZÁs[’SP*uöôÞàÜ^´ÙΔà~`¤… (pÜjÔCnPré‚Í#<“­G¼ÇÑ‘çúÚW6{å«Â¾ ú¶KF\ôƒÀ\Fn³€)ZŸPímjÖ´‰„í.ÿуÖ)_üÓ¿;p` 3¹ÛÎòévú騔ðÙñ_½gÿê²Þ*z‰ªbËaØ,zÃÚÓ8Sè¾AÈQâšxxˆœÓ(£ÄWÓfèåC¤ª„f©ÀÔ9ƒ-Bp\ãÑÀiGìJ‚ï[ßr(8ß‘®åÙ† {¨ÚÄ©´¬5€œÓÁ$D¹Ø} ´g”£<ëv\ —+&§aB2l:S¼F‹dd^zy`áÆöƒ{fhOùÊ2NeÝQ¶Ä%¡à…Ä“Af“ýcXÌÈ=Ò·yþô]ouKt7\?§` cI`‡Žík¾òôäã·?¡òu|ãAÎÛ’5ãRÌÆ6Šb¡¨SÝ!ž^8 ï×禠ŸDã^%°Fháh×Áš£ÆÑr ‡´äq0+´RòÊÆöÅѳ Í4‹ÿãÕôǫׯÿü³î­eïÎl²Ýìm‹LDjßîJ ;:S)¸ Š¥:MüÔC«ÄÃpØy‘Ü´mP3*7\üà~~yÆ®vŠ]cã[Ñòfƒ}²èx.zõƒAô3šÎ* „âQ`7\‘;*2$ÏYØ*d•§êÛ8ˆîZ·½Œ\Dßêc 3†EZ!?è#Ìc_ôÿÉ×òýõøÒ¼ÔD"_Ô<ô¯¾8òâÃÝMàwXÐÒPä´á‘ÍÕ¡Kq¾èpjl-VD–ž®=ö’Ùs4?5Q›»·½rÉ8ý*Gë–G»ÔĨ¼dH¡p¨MÉ1#HÌpVÚØnù$|ñüøÜNöç¯?þмzmò§W;Ÿ¯x7gÄz»Ý(„ôÕîÉÁ²—·m&»ÚðÖâeiÄV: î „F:íºñŒŒ¡³ =㳺n©T¸ Ì'y¨á‹aÌŒu¬nEj>Dodhé2+Îï Ù—]8h‡b­¢+ X)æÆhL08@&ªu{<þò—ËëÍI+=û«÷Ö¶†:jË8[Ò.5V IŸ8lþðëÑÓ{>„Ç+ðÈþ‡³­^¶Ü‹SëÝæ¶á|j¤v4xlƒÀfÕrIב‡´Á÷t¾aµ¡î”±ý¾9†äsRìw¶lܸ6« ~Ùz¨ónù×åóå®K¼EÖn±® ñz_n¶29´¶•,¯ÛÏg;8/”s©aÖæO—*zÎj±!Ѽ§¹&ÌÁ޵XÀ¼ß˜ƒN£8Ó¢Á½òd£ç9_–Öïu½F;«T2ZªWìCXÓÖ¦Ü=ZÏz‹“{Ùö&üìóâÐ8íó—×Õù1±ùŵ´·íÆ&ëVwïArì°ÚË(&š˜`Ó¹;È X™=û+¢–öDrýzHVdÇM¥ÛÄ`sÛ¶ NcP*2'9ù@árß-jdQÀlQõJWZ·î¥­Û/íÆÑ]ç­Â)Rqñ+¸?þŠŠmõòM] ±(`#öö‚rȹ'­=l¤f‚2·/3ËX«#£öXO5ÏU‘nE³ÂŒY|¼ µZ“Qµ-ù ãá]Ü“þá Ñ+gwïÞ:1â_˜=sŒdE±¸É•K´R—•òÀ«RÖY¶ÿHõÊÛкï+½ü%3Ìh™…Ê#Ó?þVÎ[¥÷ïe{2×S ÚòT8¿PhU´´­hIœé€äFðÐ;]am-WLBÓ\†¬±ÖמzÎŒÕ=ª7@#>ø¯<Æÿð×Òg¦ŠÇŽÒÓgh5¸º•qŸ+#'¾d1³ö–§ÃZ¤µK•‘Ê© s¥‡€`Þ-®ŽêR»•VÆì¤WúÉ_EåÊÇj½ihŒp`q.ïwÁór118ðÚ59¸U\º?¸›¶ xiO8â£O—ÕçóòÕ[|zA?y¢¬}½Õ0ÿú×ûþÆÉÌ­y7Ö™4¦”`“Ú¶2ì•æ—ñ™©j¯‘n¿—ï³C¯›¬ø›z@ª„Iâ¤Ð(¥ã¾ÙPfع>¢o),%¾hIøâ¹ú×_Ô_;üÚÙìë/k½›÷]*ž~çotÖ&Òå-^ë}tCkR“*íFµ: $¤^;«5ìC•@›,hR•!W2´|*:*ÊÇX4&+º_âUê­c F˺T4´ÖŽŽVþ›¯C•öŽM ¬¨pXµýþ|ϱí³¸•ßãÎ`ãk¿lòVèÿéþ Öü<ÏÏûIÿüæ“Ïéœ#F#5H0€$$fʲd[’“T²$ì»\ëñL­µk={%{W–dY2 Š ’ M"ÝÎ9œœÞüþó“÷ƒ_õ»>ܸBß¶"¦ùâÊÈlÏŸú˜ôtóÆÝa¿ÌÖ– êÛ·5®FEÝ÷)æÅÙó6`žÓª¾ðÈØÞþzÞ$O¸zàp¾ç~vsU jøØ3uY°·ß,ç7±”êñSþO§›ËbñåÁÁ¼XÚ´fÆ»¹)‡mӣ«ڕ¸DÄZ ·Ù_úÂÔTØ–I¢¥ÜV8݆“ïÛ6½Ø1Ë=Ý…¬dTip¬VN´ᣒ]¨>ÍÜδèUƒ… {“êã¸úF ?œj›cT§,2æ<Ø›QGØ" ÿÜ39^““c‡ÏÖn94÷û™Çøböôö≣þý÷“ñÊ̇©„\áŠåŸÑ$°æZPú Ÿ HµÉÀ¶ëp¥Æ-ÚGE¤@MlæÁV3ëWð`q£þ®ZK Žö É rÿ7÷Ão~–üñ%>5¡N5Þ»®>¸CÞ»ž8||»»µªÞ_ ²Wo wÍã‡ëÚË;Cý/¿²ó«‡Ö÷Ï,ÊÊšB ÓtE¥õÄÙX;¶Ãíö²µ7Ê}:|ßâÈÀ¸1@ÚŒP:0噎ã`[TßT$Š>æ³ÇÂ/<‹~îXãÅù‹Ï øÒ-’ »#b¿ô‹£Ã­ÊèÎ0œL>ºêe’ÈŒCZBî8ŽD ¤¥ÊTµVëØíSjëiBïs'ö—“0›òFK¢¥`•±MЉRÆ8…§;œë0˜®êòµ±íôu7'Fç·%víííB» ÅB‚eÒ¯Ö†&Týfûôè`Ò_(¢ÉòÑ'‹šS»v1)¾º¢+c•ÙÙ‰[q¯¨ª#Ïã,] >YËûÌcy´žÞ›´<”ñ¹q—Ú‰Y yãlüÆ;xi©>ô•eÍck3žˆ¯cÖ®i¿±‡¿¿PšØC®ÄC¦0$ô°ü¥gÜí“£õŽ©áZâ1p[ÀX êQåâµ!fÀ@3×Q ‘“JÕ@wC÷øSrÇ88®G6Š®¡1l‘aã’¸3©Ùã*‡—†vKZENê³×µˆ­ÑHjî“Axý‡zþ|Jjâ—>W/póÊÞÙ›"Ùž8ÁA6õ⢹´DHYZËÇváo±àû–_ç<ášò|YÓ3[ˆ=vò¥RçuØ•á6l_ «Éa”ºU Ž–Ê(_êšjEb®nº‹ö‡WE%Ÿ=V½pCvË©Tk°ðÙcAäª7oCFj©˜ TÿË»—ãÍ.yf+·XŸ¾k¯J (Ò’b‰ÂE­·d°>¸[o•¼V#ïéü*RòÁ¢•3Kâf–æRÝÄúª1Ø ÷Qp³b±§”ÄѱmâÙGl ²¨êãÕÆŸÿtËò¹‡'þþ‹ª¿(Îÿe6ÃÔ¶F‰ew6ræk#M`WYE´5,¦µÚím¸©é¸5  ¼K»[O:ß›×gWQ7/"ŸKeá:+… Â#ØWæ…cö¡½:-'ŠªÎsTñVc5ßœ¹(ˆÒ:¾4ñÏTb7>4¡ãkipr,·ßï¾sµùß~$„ËÍΖ3WÊ•ÎÆÞCÎñA-¤“apö=LÍ$Dý=(†,Y(5\È¿ôñ‰ÐAÓX2ç݇?xÛ\[« GkØ¥XCu*²ƒk¨n¢M4öÎ.h;ŒGõ¸ÀÔU:†TéYgÏD¼¹aªÕŠH9b“$LMS5„•¹v;EHŽ ±„k½#XmÓ²[wN<ãÌm÷7Tb"÷:jbä)6¡)žMøVz"6¤ÃYî;ïX‘I-¬Ð{vÊÉÝxÅÞþ™pôË?J;yy¾þ¦H6ýS8­ ›jy_XÈS—„'”8æÛŸó=WsÙ7F@Ž©#ÓÓÒ›¸nÅ­» ½¯À7p´r ú«ñ«h¤qÅÚqH¡":Q•ÛÇÔp-ÿîE^õá‹O¿6ÚÛFJîD¥ê¥§oT2ZOUÓñ?<îþ€IDAT—u/­%múÌœ•&~sÙ\I °`5à€JZ‚•jeápmt+—Õeö³q|:Ín9¶£ˆ5F9åÒL£Ìàð ,®)‹ƒp/æ\˜e‹(kƒsò¢ˆ¢º÷¯Öÿät’+þÔ©ÉôóÃÞ]yñ[dñ–¬laCÐ÷:Š2ƒ„Rvyh:oPZ³ù“ïvÓ (ÛnУÔÛküÙ‡è'÷SsNÐÀ·/£ T“ëHS0Ú­E-phV~ý»‹V”Ž¡bÒá«7VGe3HBŠ?¸.”ö±.©_“º?ã9D:#RÞ?ç¯zMSRÝ~Œ¾w«ú'/g‚x”Óž‹×6Û‡Œ¾F>Ÿkç΀‘ué öQKé7.ÇB¡¾7C¯þƒw»?zS½}Kà˜€S UYâZÎ’Ò”wn—´YoÞÜ.eý±lßNÿåÓ%5”h¯O„Á¢á¶²RL×äß~´IÊØmŒ-\W?øZ¹V©{h¬*¡5tá&jKãJÀ€ VF©§ÀxUo8?P1U‘¾|§ rÎUÇ5 ¦¶?E?ñ`±í -c+=16Ê¥&§­ÒˆÖíLa‡Ÿ~¶å,ª¹%¾ËÒ¶©LïJ›Ü·‹^ZWçGêʵÊóœbûï¾e¬íjÓg´Â¾ýNTosu!Y°‡þM6ÑU)g,Õ@%ª"÷¶´ŸAvØËWΦc£MabÐáÖº¨Ö*g®³Wñ+]ÀDäâמŽÃøv{è#!µ~úa/¨Ñ7.F÷Ÿ;Ÿ<¾ôÓ‚Ëà­ÛÑOïé³óÞìd9Øslj¹)]a íA&¤ÑÓ{|úgyVW3` ¦†ÅaÿH6VM¶‚d€]&=«2¾ÏÑã.Ê­ñŒ¾»¢ŸÞ[ú*ú—ß©¼¾´1^3ÿôsäSAÔòOj‡†yËø1ÁÕÃìÜuÔ2äÜÚ5¡&kϱƒÏ×N>”Û%’ÀiÞÐÏi8ª <™Í§¶C:bc!¿tÙ¯#¤>c…E@ EZ Š[>|íóU5ºvl¸RùÉ÷ȹ«™ç¡-{"Ú/¦"ï½[e/±nädˆ­mÊ)‚’^®^üØödfí–Ê›§öÝ^î¿öƨDeŽe®'cÛ§A’føíÛêÒu|w#SPOyžwU‚vê¸M¯Å¶@]w{^íÕ/ŸæoÝ–qnu b‘æ8ÄWn‹À 'W®=^ìž›xùM®7¦:¤…2àcÃ¢Ôø§ØäÖ6L-óìSUoÙŸ](öQ±^Ln90zt&¹o'¹ÚUç†æÊµè‘9‘þýo“BWá[‚Åê¼l†ÆcˆeŽ+úxlD²!Â)!VC•9íÔœ ,])î ñW)­UÈë)ŽälmªzÓÿð&ýp ¾÷¡k¡ôÅcJéâÖZ?r%—êÔqVË×σ‡F FÏì†OŸ¬}ûíLòêOî~vÏž½ÎLxã˜ÊFiÒZY ´ :N§^„­½ äŸp,CZ)Õ±8ðwM­ƒÅªÀ•aM-Ëä°«f,\¦,å+¸¼AŸ8”3pþåw*?¹× Ì¿ø4}qo_:ÎÒëìÐ Ÿdh£ð‚}êÂÝjE9â%û8x¦lÏ¢}OG§áÇ·r¸ôfñ¤ÒUG•ìO¥ãÛ¡Èœ¦—^8ïV1bJÑa`À°Q)ÑSnð¥çŽs«›Ý rú;á•‹1r`nWË¥[jcgæ“^ì†ØË`HxYH­‰…üÔ)/™N–¬Sy´uq8zýÕ¢DªKxijBŽj˜§üôN~õ&Zh+¡›wG¶ä]’½‡<¢Ë{ Þš”|þZ7„DéU ËŒv2@¨ñöCãÌb›8æã/ÔÚ‘ž»Z¿uS!§\·²ÈÚ²ðˆÜ7>t$ÕyKÝ3¯FtÊšqVš<1p`„¼}-ê‰Ü¬­òP½nœAq*³·á„‡•”2•î†ô´@¨¬šlÿ!h„!R‚—¬>m ç–v)m‚Áüò³åìÂr1ôØôƒÁØd’'õíÍòän›Žð…»ÙÙº Õk÷ A˜Öcš€BHøz•Ä®nP4ò! <Ãk¡uK[ZGcVB¾Åƒ£‚*B¿kÊ ¬'¼ÂîÚáÿ“O‘—ášlzqÑÒFÂ3Çhqâܺ͞»lGˆC^<™W‘ye^ V”üµÏHèËgGÆFɰ‡ŸÛ‡?vxÛ÷Ï÷9dþÑÞJÉÒM¥¨W8á²ÊŽ)Ýc¶«Šyže ëµ7_3¡WÛÜ‚ÍYzÒÓ ZJ\Ô¶ubµ±îèo¿«n­ÅOìu~û3xÚS%4 …Ko­ê+v?èOÍ•§ÏØÄ XA`Æ÷ƤØv5\nd¨Ryî†,ƒVΤš gfPÍE‚{×7jÉp¨:ªnÜ;P-,V$·dZ~ó3{2Âiæ¼ëî_µûò⊨ï<(¨ÄÔfœ6Á+jtÕ* Ð]LWè‘ ¸ç½¡t®}Q’ê];È?¾Q:ñù»ð ÍF¨}aÉ¡õLå.2æácfn§>{Ñí# .ûü ùì‡7¹ô˜Ÿš¿õy0à~ûm%±Ð®N†áS;å³÷M¿r¥ò@ñ»ÏGËv¥ÅAéÁm›ÞõÀÐ)VVà: cPî€\“¾AÅcž°ô° wUãFP¿­jÚ&މ† ÿêm|k5~t'ùÙ\l]“Tã‰VÌÐÂØq|l7{õ\)5w­_€œ ̤†>7ÛM·Ðš9:C[,¥"ßêÏm±MòœÝÝltûC3ÒUAïÙŠ6NøÀ†Nõ“{ sµ;‘¿ÿ3¼oYïâüNæNPéùnvk>šï'86ÔRBQs%Þ̸ÿÙG»Å}ûLöîåv˜\2(7.XH‰2öt"Â2‘ÆÁÂa’K¬·èïÃ@?šð´,a´47;!Ól9–!¶NQ¹ÅF1O ™€Œ¡ 2uxÿR–ô³¯?&6¸¬ºžž´CÐ̰°Ó—PZ‰xìÓJk{qg}¼ËÑD«—Ç2O¸%ÏXÀi»(çq!S”ëp©º¼š¾gó§^€GˆcÛxÎi:⇠™˜ »ODÞp¥ Tê ,²»&ü*Žw¯Es®6jflÈ x9Ó‡ÿé…ÊÏvã?8¿ûn—R§TÈ8½†‚>¸¨ú1Ý›Ú:ô‚»21ˆÝÖž“Ú.*¶yÅ}”¢{¥¹åÛv±Œ=¹‹¿ò@þÀîŠ:o7?8wïÿ¥ ø‹ògKPci*ë+ƒá£÷מ<¯|¤¦¦äxàù6ßË‚¥^ñÜ}µÙmî[—Ú9LÁ†OÍz¿öiõ;v tóo=ŽL§J—¿»¡à¥Ì1Æg…xÜ…ç\/ÂéEwTK÷.@‰J„äv ûlCÉöQš†xb zsJœÁm±1êµóªáWósæ‰}DÐDjÉLÞ¿Ï©Œaw3ì¾knob¥ h Ëpå$/½ín'˦g£¿˜Q—‡‘©û cpûzãådÖQÕf”Xle5€fT×j•¡vcaìDòá¥h2˜h̦.¥EÞ†:çnÓ…äçºÊ±;)KoÐÃtl–õÌp²‚‡Ë…)áp¨¤µHP¨™šCTìÝE§þΘ4j| TßT]gh…ç‰úïg׫¿ÿ#}ë]E1‚è×dŠÖHëéú¹Ö,¸CÒyYjD®ƒK ¢r»“ÕÝ‘Ëܵor™b™$Ê!uÐ׎Ûöe®_ÿÉ9úòÙ»ÿîoM™ÿV¾»âº¾È‹p1)Níöž:üè#9Ù»ªÄÁô`Å,®4Ÿ< ¶ïˆ?¼ÖçÐb¬‡³æSâï–ýß¾q ùKéãâ+'øï¬C=/Ë´´ú@ªLBäñê4¾@ᮄjîÎ*p Hng°ƒ×<>ÚÂc J[ˆd¨ã2'×ùëçuÝ‹þÑçýÇvcAG¥u‚2ÑvíÛpfhMEã“JéxϬ{kQFQÃ’ãz&/d<œY95]ýÄçuyšZ˜8ܾ ¯½œm3(@õ@ ×u /eé¸DØp«ªœ–8NL4-®]dr|WV œ²[b ›ÒNcdÏX©mHÊqÚ-ùÕ©?{yýÖQ>½À72ÄÂÀ(Ȳz‡¤aê(¢zTlo¡©°Ú_€*|hx´yñ¯ÚUP÷íÜMÿä[µÛÝvÍí`Þ”Û,¨2ɱ€’L@}¡è×\¿w -åv˜XЉf"²•Q¦¤B„rux6ú•¯U^»Ø_¾ †³Ã'¦µCξ´éß3›=ÿù‰ÿôìÆêpÜÌ¢ÌMY‰I³Íg½Fw×È{iγñ )[µ½Ý"ñ„bhÀYî úE4×díþàà‰éÛ“ó[Qcû~¦R‰=çZ/YàC€  4Y¬PP±%ã*ƒ–EE^J$¤iVR&Î܃•äÀ”{oSzÆÑ.^æ‚@¨™ˬˆƒßýoqaaÅ5ùª”Ö'´ÆJCŠÐiiž)ªL÷²c„9„Ç¢íy•'‘> Ý»¸Åô©Ò€u€¢OûrK|‡À5[z.¦à%QÚûñò¨ÙÄ?;3r-]N¿ü~÷ÿ"úß~½sÑšè‰jÜ>u²|óül½)µm§4'ÙÂJññ§âÊôÊ6×p…Žýî§Â7ïñùvÍÑêõbüpõõ ÒÖwˆ^ÅyЗ¨oMvÞ:ËH€0R‰4]`µ¬÷˜ô%2Bm¸Ù©7­¿I2PŠ|×ýæÅö·ÎT‰õ\'ç%ÇÓýRWqÙSÒbÌ6Ê)NÁºUKÄ"K–nqÚæcÕÜRœÜo¥.5a¶ä©b˜ú-‰§Í¨«À¨ @‘Ð `5ë_èѧš5z'6wJšþ–Öt¯·>5V ¶Úï6 p2E4 Ze9‹Æo~´~'Nt\ÀvhÎóLSêZÌ‘‚xd¤ÈK ;*Á/¾ÈÏÞ®ß#|ˆžýäÙÏÒ~Çh\ÝÓbË0O–|–-¯"Xó"ÒfœÔ>•¾ »÷EŸúTýî]5²z5\LV ÖÌBN” ;|ˆ5½’¦IcOWCÔMÝ\ÛJø­wе"ª´Œ’J×ó ²U Æ UõY[›}ñ¨µ’m…õ+ðÑGcékõp$¦µ;Bê]£0ñ¤¥ŒB%K»EÔ+õ0S)TCÓN‚nôË¢W ¢_V-ÈAªB‹¸~’VGN®\É„Ië€ßün¡ª€©ÃŽ¿ªJ5mù8èm”ûc£ÑŽ¥cK%Z“åµ{öåsÞâzPFÃtºlz˜>´³å²³ìîšDGvZ§ÊV*xüØ}®ëªwnª-ÛèãÇ jÉÙã·VÊSGѯFrhüñKñ&Ë©åµño_Ü]±;ÆÔFÎKWi+-¢Mš·ŒºmÍ_U Ì¢Ñðºñ «©[}ˆ§}+±…>s—´LpGä PS5àùÊf1PN/Ña«³a™Ç6ê÷øH€äa¥È¤ÚD5™•{ ®]ïsyF›®­ÔìOenÁj@T!†‰½woó‘$:—@-ê9lÉ(d€lÃj©xÁÃÛ,–ãN°é-&L†­†“Sö—?)ï´ xZKÎ,V®Íòx®âåe…éó/Œ§‹NäáYZ¥Ìª<6eͯì¦>Ë ‡°Ç?N~ñS)“ÜYr@ã¹f_§ÅÊ æíŸtÝž9ѰUèß~ UR))Îô0zœ®K‰ÎCYÛµÏÿÔ§*wç“ÑP7«ÑB¼©­q, ÁWOðáõfà$Ü UÆh¿ˆ ½ô®½·i¯E±ÂŒ ¼]ƒÁ`­Š¼ h÷CÒ\£%6”b>\¾4ž|„Ìb9˜YG¤|KiŒ#I°KT#O6‹ 5¶Ë¡bý¡ê•¯v³d$¼¤-eQÚHd¦]m ñ0­ (sb‹ˆâ2o:ÕçuK,¨C^¸"„ƒ*ÜŠ˜íV”wZÛI‚dáé’Ëé‰òâ]óý+òÎj ×S¡Ór¿?xl:ÈýµU»kºvhGæ†tÃE?s?¸Ì9»(ÇÆØ'©©4¿¼J/Ï›‡Žò¿÷qßý¯É×u¡ßhÏ|ó#ug9Ý:¡7Ò2CHØÜ:¦Ë¡iü–w­Z@ªjŽùC4\Þ0~†á‰2I@aëÖ˜™ÁáÍ<µ.è‡eÀlÖîšM›g㛣êPÄuzí²ŸûYŽ¢§†B–)[€:à*Û±%Ú]smX;°/“™Fí;”èù |£±Ê‚5¶GÈABJ±[i”¼({b;r9‡xMغ¹IÜC ¿ùZÿƪg+Ârå"$˜æ|4éTŒ"`G?÷¥í½”ÛQèaŽ,­j4O ¯ù•Ôcyá~äîßø´¿Û%w–Øí• DY¨zãÅ(×”yˆ«aôî÷:­<úPp¥“8Ž”ôŠ(­§ž8Þü›<ÊõÞ…÷(Ïœ˜÷F¡7žj€ ´"7̯[C’=cõqT"mu Qjgç_~¸ôÊ’ßä…%u092úAŒuÁÕæÕ|Š>pŽui!kiÝ…Ÿå‡°…B5ƒ ¾DÓR‚ VþÞ/àû8½n!“ ׎%Ùƒû‚ôÉìëϺ?æ0~öIo9, ­1-ߦ§užp·î­,ô²¼ ã^ óø&È’Í㈴”¸¢µÙ‡Ì!Rý©Î×}G ­cÁ²‰êo<µk³¿ÒÉc8pƒÁ hñD Ù-Ê«]uÿ}u2JvÏŠ] \u$Ëüñº>° ã‚gNõ›oöÌåïº5v¿¥î®›Èc,ÛÞ,þÖss»2ŽSTMºEšÛâ!ˆV­¸§Xü.5ô2–‰µÈð'd¶UW”Êhú™f2Ñ’¸¥¤¦´NïÛ—ÿÏ¿\{a/ùôýúÓ’çÑ~VYtÙl€·oNüÒsÞÏôøQ© Vd¶`6­ 5aÔl¤â\NfP¨’o..„þ—QY* ¤˜¹. ²€pƒ ­ ¬oªš§¶Ííi:Ö`ÄŠ¼0Ô“ßü°÷ê*M¤LiÝ:7µ-m’PÐ*«5#ç©gÔ}ôÁ9 ³ÔÏ‘æ>&¡ ªJjäLøŸÿ„'6œ{§;̯õÁÕÒj(ëÕQ;©qøá¥VÞþ«N@'OØ í“¦&>r\Ìí%÷~ñ9ôÀ£¤Õì^ü€” Kx2¸³©Ö¨â˜Rpç7ŒÁÃÝc~Ã(Äß÷‰€Ù^½ü¾ @=Å «ƒÌ°µ')jÒCÁ‹ 3ÞñûR†„Ò€4¥Ü¥wòCV‡RbkkÆY òª­´ÿ÷¾Œ÷ïv³*“ 05c“÷5~ýý/>¿pÌýÄõÜSÞF‘Þë)5™'„=L®´™N¡æWŠb´`eâJí³š¥Zd´*:z®¼«Ëj*Ô-¤¶ŠZ@n#úµg[I¨à´£”l„üa4Ë}~¹“?î°¾Ø=£÷¶¼£†óÙ>´…û"ï±àïç»ÇÔo|Òß©ñ/gïß"™2¸°{|ôËÛq½Í™²&²{"•Fž µuSÞ3N^ hr™ÈÄZ¤ËÇy¹+œº%ô0BûžßVNb÷¿mµ`ˆ$Çöe¿ýµèÓ»ÑçN §ðã{T_ªµ’i¥ÙYõ‹ÏV¾ð{åÊHjIŒÊ)šClB—Á”UÓ®åÙôaG Ê"„˜A`Î/EißOqY@€ÑDß–ÖZ‹X ²[¼Ö‘!.g§wOø€Ci^u 7ã/½ßûþY¦fm½&×ÈÁ‘6EÝ ÏºcΩ'z÷£Ìf$ˆú ("X¯ª$W±3Á~îùˆoz·ÞèEõ&¯÷®\)…$œ ñ('+tì¡É{ï v½b™óÀ|õo¤Yág›šRJ{ú¸óùgù¼Èß&£B5gÔgDZ”Õ† >!äUa©ö ׿¾”¯¬G²îŽ´\ƒæÛ˽?:þ쎲 #Ј­íÃØlo=‰E]­tçV4И:VaŒ Þ\¼nÌ1®øˆ`#n»øÑXBN£¡¿øh³âÀ–£åÎÝ*êþÇiº6¯*Ú7m&+¶-Ã?ÿ)O êºr¿T‡ŽÛŽe°ÝIcïnwt?Æ;}6 ò G­œ%PÕùY"ÓW) ÜŒÑ_8êlìù»®nüÓŸ¶L‰lÍämj7Ëí©ã“e™ï:&PQß]ëo@ð­{íÒïILC`,œ °ÉbÌÃO=ÆœUÿËi¶ÃL ç€~å9ýËO’ïžæWVè‹ûáÙÝd³°ý˜!Œz–ïÂbgàÎ)=cóÇ8¤å3Ìœò=F_U¼±cìȧéÃ}›ˆõKbÞÁ¦0N%Ê3ûà>²-L½ˆÜZ‹þø¥áüp$emï–äs/$=L§LNÐ_)Š!kµ3o“Ü£!B^ÉyLéý¾Ç ¤¬q}L %r=ãnË´ve+$-­†+ˆb«`bÒ–[M­úhQÞXS1¦¦’—êâ°õŸ–¯]. ‰T^5‘$7zä…´nJµ ”Çð…wÍèMŒ}ï…OT+¤\ïhŸªÁ±õ_ùŠ]¸ì˜÷ûû º1 œmµóÒ¦O.wÒöf: „½Gg6/ØýÝ|´C%üÂWJ.¢¼›+Í?û€óñ‡ªz5LÞJ‡…›Ñ|¨ÒB2§•»(ç] (€¢&h·t‚KåêzE×¼‘Û7ЏMéØŸ½wGtÚA[ˆúò3úWŸ®ýåéÍëKÞ§¡'÷¡n¡Ò ›Vì$åßÛ¢ô d8ðy~Ì¥{µ9/Óh_õÈóä¾C}2Š7¯‰ÛŽg¸°Ž7È'ŽF{›QymÙ}éùõU®,˜Ë>ûyöԃΤ«'ëÎk×Ë4†@:0¦Ä^ .s…ÄF‰!¦ø>ãDí¹˜`JÕFÊšž8@“{™Â€Ïë(5›Wý°~~ ®l˜¾3ˆq5‘Źný;§ËW/Kð&«’·4N2-‹j-t BѰ,ËÇÖwÞÄé[5 î Ÿ¨Uh¾ÑÕ>•!–÷ÿÎWäò5ŠÏˆí™¼Ð)ÃÝáGçeDá^šÓóӣŠÏ¼8u‘Q…5 ‰M}öQýïÔÐ þÉÔ.¿|ûŒG/eUD®_@c»fe™Ž3)RœH _ÀãQÒu®›t]gçÕKC¦+Ú¾E!€Â,¶FÊÄ÷ Œ©ƒKÅ|Exu 9rJÆ™©·ÝÕ‘(,ªX°£$é 1ÐÔŸ*â Ch îÞŠÝX¯]ýæbì ÃÏŽýë¿9zë¢|íƒè|’~ôŠó£ëâW’Üëµ%€>mU„Õpsrj/m¯‰ýŸóÎß™þàUz ë‡ 5"g­[\uÓÒIj/ùYÏìÄñþ#Þ/}wÖÄÛëâÃÎØÿñì·¾'ÿAôÁÅø'—àòJíG×V?u8}ø…'éêBøÿyOüdq1ËÑlPâDN½û±mì™ûjŸ{V×R: oœå×Ú•ƒSâé#ú±ž—‘óçäžjÖ’¿õLoóo_¯ÿtl‚Ëâ¬+MÍ„o:Ú¼24h Ê\ù<8¶ù=¸O`[ÆC˜kMÞm®ï¡E'ë‚( YæüÆþã»òÚ’„=~ ®\ .þA⾯G{t4d PPCÀ–/’IǼtZ5c s™ŒxO?Œ ›».\Ô¦XÓŽf„¹V 0Y…"ÎzdÃÕåäj ìƒq€´‘ö}N©áäÍÚ›½¦Y(KUê¼â`d+ÃÍʽó+ûR‘]†ÑLý«Ïê“yÿ—XÄ“-› [ÒhXä¦TÝiÕ#/Oécû+`Ðò­¸á–Ž×e*²Ð·dý:gŸ?¥ÿí¼æàýî×ð® 8ý"—{U×Σ‰Ýs¢(,Œr! Å‘E¡æ‚'&¤íÞ°ù¦uÏÞC, \Å8À Â`‚p‘ñÜiîŠ@0WÍ‘S:- ²Q·' k«U ÒRм ©%`Ý`:—Ø,(0@±¥Û¢¼Ý >üñ¦Ia×g¼ÿåëïÂ˸—òò+øàþ' g£v àŠŠHç¤ãVÔÜäX6ZŸ«Š±Ïú÷vN¿õ3|8IöÒ„~n‰¡å¤uÐqf/¹â€1*e|à ÷ŸwÚ›ñÏVósýêÿëOÌïþ çýúì ï•ðõ5òÊ•þ'OAІ¯~­-“ÿòúéR78CÈ=2 Œ©6ñÃÓÑsæ?ÿô°¿zÚüøüÚùÕ©ƒÝ'¨Ç¬6´óoÿ»~kÅmEÉ/?C¦v¨Íïê×ßÎ&µ./`ópªÇc1lQÐ8ðR;"ü¨Ü÷øàÄ1ŽdÑí›æDÎåÛVø]бëKúWbøÃéÅyGǃçNOïCçn×^JAxÇ_ßÛŒ»pJ—È2Dsî,RPÑÁ©âÂo(àÈtwè¸ >ö0ÎeDe„÷”«Œ]J PÔjh4š!°æâÛ ÙÝÕ'À„?t /§¢ÓC`'jõwFCäÃÈÒ8ÉB¨yû^¥»ÒXº¸²c0B=5š­åYùÐ)ÿ_‹E"~áUDÛD 0@ “>'­(âirhj–Ær½«ƒW÷Õƒ;g‹;­fkgöÍ7áÝ÷‹j¥Ì¾õmöÕONX§­0ó@0—d:•R$LÔZ…2]÷¬›&mY±ª@Çæ‹bV²A$Í\Ñh¸Y„I«h¬Áæ:.ÁÒ¢P, LçCP<áç½ñ}îgšy &›µéþÉcúÓ_‚^¼”fçË*A¥¤ 0uóÔi™«½­JYn|482]{z÷hßÁbùzðÓKõ÷noü³Ø2Y ²@“N_ãXã*Y‡LlXß„í~\Õ¹Ü#޼ðh‡Ý3ôµ/ç&ý«]Õ{•^)L5åà£;ÍlÈci4í~Ô©ÿ¯oŒ~óùòÅmpjWå§÷Ú«+Aw¯×¶ý›ïÝ{ïB=¡·ª<„F9eaõÏFñw¯æ'öÉßxz7ï-.-‘_ÿôðéÝã-ѹWdÿúÇìúfhý$σ» 薮ϯ´=Y1ð¡yÏ$*ÐzÆ<:MÓ$”7p³tÕ|x-¯îŠÜûÁ ½Ï‡„O¥’`¤3ëX„°ó¿¼6Xé JNœr?ý°7½7™æmNÞö]ÊÁb )ÅÀ2PÙ!„v•ã‹Qa»’W6aT8ôØv§;çA+ƒ[í¤q5 º)u€rê.\á¯~€ÏÝa¿»Ä·NM†¥[–K9_aÑÅãk ÔÊha˜Ž)ðwòŸ,º'öÚf·¥¾ñù®–µÃWB¯¥Ø@Å•mF`sÞ¹|wªÓÍŠÏõ½ñô;Ÿ/?7oÛqúÞüÆr#Xæ’ßÿîè­óQêÀu}]3¬] @àwFün*¾}ÑùÄIõÕ[”\ë´«¿öìÆóûÆ[¢³ âñšwa‰â°HE´°à.ƒY]8ò2ö²²èñçô#3îp¤öâ Ì×ìõ«<Ü–‚üôb9 •´•T}Ì ÔˆWÚ’ e»ÿøõîæp˜åú¾–yá±pç!;¡íú×Î&(Ãuvua)œ pSYd@b(”C‚ކ»±)B}út—þfVd:¯ˆ¾ìWI<óÃ(&9áxUž€™–£ƒÚ!šóh„1ÝЭ6l¤ŽÂjl7éÎùPázZ:É(÷(^*"ŒsB'µÝ8ÏG\å!ÖÑl¸2ûæâlITYô¯~?}øÁÊ}õ’jÍ÷‡ÍC°·æRC;@¼b4“ÂŽUî;Ðݺ¢Éú¹¶þñO³›wh®eB¸F¨Óož½ÚÛ²³åî(–}³ûjz­w.ö}€!¥Z@A¹E™‚K¥|(ŸÈœ¢-0³É³Á–½ÎæDa¶ªª@Û.í9FépNò‡q¸HExÄmL¹4Êz"Üs])3¢à‡7‹7/§½¶ÎŒ(•+XlÛÇI­’Ïl—È›‹xϊضIî-KrÏ—Tr#¸s‘ÛW¾ªɈÂéfœ<8ÓüÛŸõ¿ú±|v6fÒ °æ`¸†ÖV£ž-wC©ï\ºËG!ìAj ÇzÓÁ'ÇVU‘‹§aâ^¸]•fGZG'ƒV£è`¶!lqS6œæF‘m€>†üº·»ÌŠJÅ~·ô¼©6i ³LMËZ„Ka9²Áˆmà 0Èz²)¡°æcÇX8¡î¼vŸ-ió¿Ý[î4 ÎS,JóËäÂÝ¢:îž8ìßZˆ2=³:.â˜S"rj” ¼ð±“ƒ­[߬_³Ÿ¼Á¯Þ1šØÜÒ˜þpìÃËý©¹juŸº…õá“•zèþ(k8dÓZ#©Æ¢lV¦³ˆ%¼P6–8y[:NNE3GÑ`–£iÓ´hs³ …ÀS ¢#Ž;^Ÿ)v˜Á˜©×Ä{÷λ4šUjr£¶iÒÉýªòP£¼ÛõÊMõe‰Á$4ŠÛÀ{kÉÆu²ª`z¿¿õ¡¸Èj!ç;gÔÇŽášÝ.þh­gQF˜‹{ÊR°¥3€/8½«…XÑùµ­ÍÆJ¡÷àþúžûŠÝ6©VÕ‚t×ÏÙ›@5ÈF¸?̾w¹÷ê5Œ8³JG­÷õF GQ8ªm“©#ËóWúg+®P‰/ú.ŽúÙ>1¶Å’j=£Bîs7ÖÃ+kù[ÅÛøþÝò¼2þŸ_Ë?¼ ,Æ:V:?ºY¼qVö:8”Y¤…U $öl‡Ý³dºZlÝax½ÛdËŠØÙ3« î’ø†^VÏh’Qç÷Tµô¶q»LͶþÁ Ñ/<Ç÷N¸”g²©D7\^tR[Ž›Q½~ñVŒ)!Š”Ö`ºt­3åêHÖ/¢ráM˜¾nS6@$Ñ"xVÇÊTÒUiG·D“‡«"Û ! G®7­’}¢U|ƉÇðxåZzÓŸ’a‰BKÇsºBŽ@–€ÐÔ!un4˜Ç„ÕiyÇ¥õ#R8còÁr»)QšÁ-,­Ó³—¤7k{°²GžI~aÞ%žÅ†DÔŒá‰Rµ·ïÿÑ[µï}os~¹´0zFL;®Ñݪ‰îÜ&¢f>ñ¤Ü±Ó__…³7,¶G"aAûÚh¬É:¼\ƒ}çDï–Í7…-œÒÔ&VF| •i"‚3Ò«))\êH¡¨­`u?8š+»ê ¯wo dS·—¢eA¯ébÃ5­‡Ùöý$ŠÍ0¬ß¹â¸«©Öð>2Ò"­”¡æ—w™ƒv‹Û|ÐÙu8êuÒ¤ô¯,Ã{«­·>(Î]I“¸O‰Ò`UÄ;­[5@´¬‚¡˜v­2VuÝ5ùÖ¥,*Õ9ê¸ìÞÛri£µB¤¶ièr¤ÌìDenŽ´* !%“Èst«ÓF+£ô¾ƒSx8ŠÜ¿ÿCýþUn÷í#>ú¤uî+UÙ-ƹ_騭EÀ©–ÅZlÚCüôþ-r8(«•ÿørzîJ Ù@›À…´æéÛœéVÅ£•"É]&Œ2€½ªl4h¶ó ¯°÷Þïƒo·m¢²á.Ä8dÌ’È*©Å4&“Š–FÞ‰D!h…BÙäÎj1,Ç6ûÜqÜ4å³GÆüfâ¨9t´ˆ6ðk‹ÊÀHkjC$•`æç(ëx#Ç7ÖôU!V•geàj¾ø>œãâ¶ë§r—C¤A)ÇñËLì¯ÙÒ+ob¸^àK‚e‘'aÔ/aI—w´“»Û7TO9¥k<¥-"x¬bs°ä¾Ñáû‹æúÙ5væMB4ÙwkCák(kÔjlæ앳ÅÊp›_?úpƒÙ©Ì ¥ÖM2%u²ïÈìßj¼òýäöbn(øˆu¤êȪÁ”À°Ak·n¢2Ò/<Çvî0ëKþG×s„¡M‰¸i;Öd].Öñseïm‰ Vr¯¹šê\ékASV¥·r: –Zm¬xæ>äè\š7¼É/ÙÍu=X×5º¤Ôša÷>R)į\¿†¼e ÞÍ-ÕšL~a':ü Å»Tãxcû!¿»™¦Ü»º‘|0ß|ë\~æF<–¹aÀ•åTÔ#mC^Œ6e€Yºnq­¦Mýæ…|ŒE3„0zçüÞFeicÏHª¹ÉÊÌ´êÊp¡$¦Ê€u7½¥^qø°‹úIÅßñ{¯¨ïH¾—™'=ò …kí½Ã³×8Qh¥#ŠwbXë™gŽì⃌øJïƒËž‚9ƒ Wš((¶Ì©™IêP¯Hs×åJI„Ù¤j¶ ›½?à,|ó {û/‡ûÖªzó%Ò7 „V)SÎa2i‰yÝç…V¡Ò’`GåKkùÅez£õ3 ZðlrO£z„TåGÙpSþxÞüµgeím™„´Ìò™Û o#gW—åe‘oT@K±ø!JÏ©ô.õb2÷ .{ £‘˜BîªÛ¥·±¹£¼ëŠõ)6n<ȽU-oh]°é¶ä¼N׸–ÊE, Ui‘wx‡9ú«M•ïÜμ傂®4ÊÐØ²á`©•Ûè̹t=kŒ‡ç/õ|S™!UyÅ@"1ü§ÿÚéo6 e>fâÄphM?å˜@´ÁQÚáù‰Í[øK_ÃóÞ@ß-U>˜Den~½×t(d€ÒîX§íÑné`9vÆÔpÆ*ÏiïXGB¤Æi‹¹2)l¢t%Ä‹éÀqÞ$,lik\xßÖµ'šo˜L ¢°£`XLο¹ÞéK½Á@¢N6=©ª“•ªM€ýh¶:pFN™®i‚Üò”@PÓæŠÉ¿ÇÀR¿jòß±þsbbõ{½·¯ñm§¦“Z„¸D;D†À¶7“Ãs3'T÷Ž©‘)¯­ËlcCÁÜ[ËîÏÎv?÷ýÃÍ¿µâûû¹B€«®lX˜EBù¼…6’'b¶à;º]À;ËÞ¾¾ò^D¯¿M7“ÊWN:nW¶}ãÕиK£èíúÎzÇB•ŠzÀeÞƒ×*ç7*·Ï®m½â=³èÿ—aÞufÅ3'$¦:f Q”æÔùs©®D•9…BÚ¨âÓ‘íÜè5Zx| %웚òÈFßô;%ÜVáº+º?e%*B=$ñ°Â(¯"1×1Ž]&—Ë‚ñÓŽVàLêbbE_ú"g û\n¢Y¨¤,‰´Â"”Ú¥Qcåg¶3R «Y׺y-êÈ%©ì{†a£ô‰ö]Kee,+€¸*sW !Á„zÓ¼††_ÅÞ§ÍX÷ûÉ÷F»ÚaVáŽ3,5PB¬rL3ß7Ýzò³½^¤ht}ŠDÓæ[KÁ[gáÅÇkôÆü‡w¹-0ŸÊ *íu¦ÆÌWÀ—-¬{äDÆö¼’{œÝ¨ü?»÷Ÿc§ßO:ƒéÏ>$¼Ðšu7H-powØû÷Ü7®o*p5ǘH©Ë›÷oT.¯UWÞ_Ý~Õÿ4Ì¡ÿÇ"‹ñtOcV€z¥Î¡f€ .šT™?¸¾R. p†Iá×ëS5Úž©˜É:[ÜĤ£vMƒ¥”qbŒ$c†µÛpmÞØœˆE‘-zwDz§@Ê' oç%Áý-FH(r8“0PÁÓÈŸ¼QnvKØ@ a• ½mãÐÄäá½Q×îÓN •†à.غ,ÛÌ…Tyw†CÖ©ÿ÷?ó—‡nm?¤eV—*A¨­–ÖãšØm®¿ôê¥þ¹ Èðaƒ &šÔ‚š[iË5[Ū) z|F(¢ÖX†ûT*9íù[梳w:-€6Æ% •'XmÕ0dPÞé~ü!ºg2¯2al}%q^z+ùàö™²k\„T Ý ýÏ"Ò™õ «°Ä~Lä÷,ØyRáÃÀ$Ô!ý¦F•Ý —¨ú$ˆAF‹0.€¢kFHMØL„îΆ٢KþÙáÞЀrïcÁóÎÐͽ¾L0¡ð#œ]7ÐàÓŠµÙC]º4P8Îm‘êŸÚXâ†È¼ºÓîÉàÞÚàÜUì<±×|ü1ؾ;œÅ0%—ÐA©‹ÆoýÅ`$`[_ËpxmfÞ)ùe _C!`þ +xÂóÇ%íëò›‘¼—ºðÿðK4j+l«®»NíÞÑOÞ‡·oBbáøAØ5[yõ,Vu¿"¨M¿€*²HB„ÁT¤N]êþg›Wteà&»-<*BfÄØ1 Æs^bέ$GÀgëøŸÿm£¡²¶DûÐígç×̆Ð0ê% (`ÆPDAúUëìÔÎ-°d6 ú®)x ¢K _ARóÇ2/oE´žÉ”D)ý6ÀeSÍû0ÄÄSº:^*þÄò©“tw Ôän'|íC¸r/6$Pµd)°mÀ˜‚Àƒ»+Ëxƒ÷$Kiޏŀ5%kÐÊêš­(–ÔrV%i`‚8S1”` (ÀñŠ<›Ç \5Öƒ.jY¤ÁµØÇ0$e„ԸךœÔ-Ä-0 ƒ”˜cCÍ6 C Ùáíîó8»'²ˆ#«Üøö›ééó’"²BK#­T´Î”ÝGãOZ+ ÀЇÝyøŽÍ¾A b¼“Æ;ª )s¼¬Uò¶·[;8û#m-+] 3åI0€„ –;>©‡úè6o[Dg&aj’:ùþYíh á^Ïÿ¢Í«>HÀ”¹Á+:¾mmSVGDÿ–!k(‡V”é[ã¸Ñ÷MZ’f™¹íy¡=8sW {d7îر&S³éë%ƒßù Õ+ÕöªùjLÆqУö§"½è¢/€G”|ÔÏøA3‡u(_óÌ-xnþï¿Ô¨ÔE½â§I«A³ ¼uyôæ9xã¤GÂî™ú?-F¢…¥1ƒ¯ÚÊÈ$-L ¹J'PøNòÚfÐßnñ‹º¢DƱ7Ä¡ä[–]ÖÒ2¨Á?û¨ÑæÒ*^\ä]¡/.æ›C°XäÆâcc %R¿¢Ù.ã^ãÌæaaŽ|¨]ñGäF~ÐóŠ]‹ìX!‡¾uì™FŸØo·ÕS4J‚W߬ZÇ¡*í3å’¥ßgö'Dl m¥áš@ Sh¿ñªL.à²åT’"ø×•ØâOµÿàÙôÄÞàíÛd çîö†ç/AgÙókkN¬Æ½è‡çã÷6°¯üãDnQhèâ V¹"=’˜Wþšãœ”°ÝAl\Ń5 µM–=²;4{{ÕýöËÎ7ß,¯ÅP ™Ù‰â_}žÚÆãÜ¿±! Îy'©ÝÆÍ 7ú¦‰ç¥•VY¤¦`\G·´zÉyMÄ\«;%í»HùŠÝ¢)Rîo‡¶"ßåƒxzaIPê`m)B³Aã±ýáF_ âjÍÁÂ!€:( ¬’GéyL®ûì®Ñ=£°MØ ÔxÞ’[i×·°Jмњd*…- ) ?yŸøåOµ¶ƒb3–ÖÖ‰ÝÝ„ÕÞi>«f(14ÔZN¸Ž0èáùÃ'|;tâ³z:¬§¹’„iàÈØMB¬ †1CïÛ’ÿâçý{£¢Û‘Ìkð¥É¦fÕßùJ”ô³ÁFMRÎlQ ‘F;„9!)õs¬(€ÑCý‰OCÔHoÜqF;  ì_9&”¶ã~`NýÖðÁfæj›ç¶bx…”ßYKÍ’ÌÖΨA³ïUZ‘¤Ë,t…~To!Ó#ÚÑJ¹&!QŽÐ¬,üPj`å% 0òYè§ŽENâ¸N±p SÜÜ¿eü™£êÉ£vW%«+D†ôûoUE@j›¥ÜjÅÂËH¿é˜A‰í&F ˯ùž3Cªû%`rUBA¶{luXHìhÃÁÂ! 5$)8•Dx »êÊ»F,ÅÚJ@w˜eÍb}¢\¤Õ:!kqTåXhIÙ}þXñ÷_œÝQ‹Gó]ìªröMÐcû“õ ¹1 ÅÃ$Pj¤šbžFä¡c£Ça¶ÇnŽr×ÈÙj3/òiJPr&„À‘ A œ£;ò_þ ¬ŠÕ¶q]Fy‘[ ñÀwÔ¯}•Íßøö[ýõ{…ÕiW„u ¤âxGDŸx6:¾oH½ÊÆš‹%7BÉ¥ãCY&€:©ý³ ‹ÕØB‚nDk½a»ŠÖ¾ô[X…óK€BÆEF Æ£^ŽJ­,øÆCyokáP É; ’?8{ åXa¬ÆÄÁZ0€}—þÂs›_a°°œ¿f/.ÊÅöÄÙ{£ozn¥øøèÑ,4îÄ’X¤d Â~Ϩ®4@½u„¬9.­Õ =L5©+–œÉ’ãQm3ùÎd¡7-Š;‰³±>s«Fk.†rߺ)Þ¹Ù:þ`õ…£«6¢oÎWÁÕ°<*èMVKÕµ`'770€-Ü‚Ýñ@å¼δƒîSìB$3î¾¹Çõ®È^>=sæ]¦aqäÔ}=”j Gª·õduÿì&JMœ‡ ’\&ZëÀ‡Ñ€ŒyâW¿Ênßj¼rVÎßÈ™œgÉPHß1•‘Lï®y'N‘“ÍøtõÏÿ{Ø‚AÔ02@nÕ~ás„ªõDAF‘÷4Žòa7ÔíO?€ïܳgרâb4ÄÆ–X*‡ø„‹°’SxSæy?tÁ)ðP*­<ß© ÊrhtÔæz¨„$¤ü éû¸ ºxCË£Õ:Š7q­iÏ’¤=4Ó½\ª¤ j!úÎ]õÁÝéãÚïß Në% v0á÷KzÅU+²ÓjÅ?5 z¾ÅK®a¥Lºè€Æ:+ñÏîÑçžeI¯œÞ~þüH@Þó\&¹¶MDº6Õ Q/JH­æL øz«Rû iŠ®þ8â*è´ JU‰¥ÆC›÷©Ýç¸V ÀP$åņ¬lºÁÛø›o¥‰ @´K¼ÉhôðþðÈþtÇsdòÞ’“ C¹„`ÏÓtÅáoK !°eSÞÑÅ€¢cìHKiW P` ` ¹Ìföð,|ýIL’{›Ww¶FP$I.b͈ýʧ¶Þý£rµˆ…*‰ &G "! ‹=аg§379<²0qúµxeÐo0ÈÕÚmø”æØÞ¡]ðÙ‡§wíP™Çq8/JN v¬Á~CH=uñe‘¬®>s¼Â…?z5Ë3í"S–À<ò0¾ Z?—¾u%xôÓ–0­€8ž¶eáØ–å1Ä <º¿Ýª êÝÛìÞ‡"Ü2:òä„ÎÚR¸°8°™¨‹0h…1l½ lˆ\- ¢´ ƒÔ]®"ãǬÜ)Äv¥!Êj  ÊÂ:º/‚•KÎü­á'ýŸÿ”œ_ܸÖ1^nÞó^z§üÖ‡åÁÀÑ–"k±’ ùŽ„––‚c•²¨ € hX’;®Ó,T– Jk…ìùæ½y»¥Ó. ($€±”Uù‹ÂVn`¨ ¦f8ˆëào‘²¥L.áǾ3ÐØçˆ&i¤©–·$\rQ ãû h!ØblbDgµG>D\¬í<„Ózª†*u -Èo¿´á{¤7¢Œ6‰â1ô‡Í꫃`Ï´ˆN‡8³8¹Ñ°) \ŸPŽ ²"‰"žV%òüGß×s^ íÃì÷7FÛ·Áâ]|þÍ,Ù]Û~@È 7@i(4R+*_pI…; `±Cïíx8˜Þj´*í£ûóöyÌ¡!†Y(\,·„|ä¼û]§ÙWž'-ëwÏ_Çu¨Ä~P>÷Dº\y%‰§üÃÕJ¯‹"MŠ­Ž&D!š—¿[ä Od~ôêQ+”°zÜå­Ÿo_pN}aÐlbƒ¬6%°¦¹¬ojË#û:ãu¬dýJçŽ7F°íñƒ'›¢ì×ô±ã“¾×W‰t< ì²JׂUÓÚZ(¥bà”®@°Zo#?%jZÛ•ŠHª±E¦,‡»’µÏN.Ý[=y¢þùgóËp«M?¼]¹rOçÝü»g‹}.”Ä"m!1¸#ŠA–C1À ´`²À)ñý‰d”&9Õ<î¨b‰ÿÞR÷ö7Ö‹2ck(f0Û,+µX‹¬’ŽÃ»ƒ¤*¦Þz]©)ï¸ôŒ…J‰Pp# ³"áF@–-TáXgˆ%q>Œ‘Ê,§ ÛÑ´ë¥2Õš!«Gý“omø>lö±Ëš`2Í»yXU‰Ø ÐmP1º’–¼Á$ôÄÏÁXI-®±  P¢ÿÿû}r³›÷î1îIO‹ÙiØ\ÀgOßÛš=PþµgmP©±XÖÅ"Æ5ÃæKM€‚%šÈ Œ‹Pà‘k…é¡AìØN ²`,„4h›kbÝG×'¼bsÈe5:ûn¹y­ºã1Lw Gäu?>~xØ> ŠD¬Pª]ÆŒ2Q(bôÖwªî~ùYza¿{Ö¸¦p(@¨k?ñ,­"õôâðúÄ‘S¾[é)¦³\—¨(íG×ã;—’]"¼ñÃäcoâ·]¼þ&}ó=gÿ>çÓÏ•Çg'¾õï ™ º}ýULNhÛ–ÖÓT–N€p+vÖ#O¦†´On~/Ù‹ÊùÍé•ñõÃ]‘C½ÉÖº²t$Q®%NQ â,;ê´ÖÀ]€Š®K*  *‘c¡ô`ØB—#¬€ƒž¯ l°¨R'UÖ‹ÈÊzsùõÍí˜Þ^¾ÓššË·4Š÷Šd ïäc¯_+.Æx&¬ ‡Zîh~ÁòO‰°ÉÅ_)© ÊG|ê‹bI ¨è"K‰¾W•,ß;©×¼¹: §¼Zu8M¤ÔÜó)ÕîGq‘h*tQ…±˜ñ •|A²ŸYt sªAßZGC®‘Ù§½'4ŒMRᕇ ˜»Çgè¹(£ÅjY¥–÷ì|_ˆí­ŽÁÈ‚–XP ù0f` IÖSmJff2òE˜hcý#è >¥õaM‰”™2dÔÕˆ G’d=ŽV>¹×=èõíÖÚöó•{ß˶gþ^LÂ)?Êh¢Jb£¥a¡ƒ6…x J:à"\KK€:Ø:y:º“·mWz†(zH;^Á»¥ATaפ̵¬Q:wúÃ÷Æ÷âÎïÑêW›Í1p„ÙÝðß>Ài”cc¤rÁðŠªÞüg«i‰'çÓÍ_ù'ÜüáO¢ù;òчŠÅpìôŸ öˆú¥Á°wdL¸ARÒh+@ ÿ {ýrqÀL]üÎÆ“¿ÚúÇ¿>xõ4}ïl¸o?{î‰ÁsÓßûÃe3œªéî—I°=Â6.€W cúÒ¸€µÐ“ylÜÅ×þª€ªË+õZÿÑ MdØ –…ƒ@,ö¹bwqþ¦L:Bx€‡ 1—%q]T%igú´6§¹5É97Pq¼DJ/bëhõôÊ 7çsöµhËTsgséó»HQfW“Æk·øÂÙcY!€ƒQixQmbjž(;%ùSà'ž‡’ì”äKÂ?È‹„–Âu¢²;é!mŸt݆߬s®§tÆX@»PÄ…KèM•“…ËÇÌðpÞÆô6.±ÒXFaSjÕ>á~ŒâmÀ‡ 2oH‡<“÷³][¼\$¾’=ánN±!7‡î…¾¸ÝÁ ¸Ì4æ4@iš`žõ1´ÅB}ªª…þo%`^‡ÁfPNJô¦dÉ\ƒ‰pJºxèhôØaÿ׫T°tT tùý—½}Ý\Ø0ÕÝ^8üÿ÷0Ô–â,#,S õ‰&)HKÁ¢€gÙU˜¼ª‡àpØ^¹yŒ€jê¹R#(]Ê+µ0Ém¥Açãõ7*;ØÆ­ïúµ¯7Ç&ÆÓ]Õ¦§ãD—¥@Ûž@ ˆ1e¨Ænü8#k¥²c‹ov~å7¶>p¼ýòO‚…»òÔcâcË<¯¾ý|RG—Úm5Ö#“ C©WZ‰kK Ù_®šÐ°Eë¥6»ò'ªÕR;=–n%ã ìÕ˽eŒŽòv¦*22ʃ vš¥û¾GŽ˜ŠBڤ̷µ2µ¬êy Rå2ƒBÅ@®Ý2 Ç´‚=k% ã!Yºâ ŒÌ,( ka(‚i‚¨”Úc,„²Db h„(!ÄŶ(l@k@@ L ÀµVH ¥` ¸ àû¤‹ÁX0`±R®ƒL0€mŒ5Zj­­Ñ€ €ÑBú-¦ûŽfÍ®ù8åµ!ÀÖ"€¿>ŠÀ"°`­cY È"l1pf)€pA<@e u#†%ŒsÉxV•  !ŽRP „PR ÍР°ÜHƒ!B+kŒ ° - @”‘%ÐŒšB@jƒâœ[Š XB€µö¯F€À€fiJÀÄhc-"À°­Á‚Æ$pB§`2‚(U*¡Ë­Câkmg[Cj$혭wÁ)ÎF3™ÅÀ´¡Ðh¾ %p· •E]>Þ¼\ƒ?y¥SÇ„[Û¶ƒ¥õÊþÓ’§ºgô¼E©a×ÞT¨$®ã"! zKÅ7×y„ñšHú nÿiáŒñTR–e¼zë¹z·èRÿP²É!0·˜ÕÇ£Ú€d.Îò¤À4PTøLsÍ”©+Þ¯l 1ô¥ã»£"³ ,ò!E  ˜£bÔJØ‚5`4RÀ”£M‰@a Â­¬µ`ÁH[M ÒZ#Œ) J…4ˆ@€†‚t,h‚Œ¶ZkÆpެT ŒÔhªJ€i PfR(Gƒñ4$ óÜ l]€Ò%HY_ÛIiÖÚ1À 0ƒcAÄäZY 7L`ä2ìM€kd1ÅPBfHD™Kë„EÒ"m2€ÖH) V;Ý 0 `@"@,h‚(uT©2”a@è,Ú ÆÄÀµFaTbãa‹•áôlñ¯UÃÿP Œ¥€•´%h‡`Wi£±Ñ0¾♠à dªÐ¬£…2q&KÙ¯ºVaÈ¥‹‘2´ÄjÊV6ˆ3b®xr$b@`À„°>ªI( LÊÀ¡ƒ´¿Ò®‚«ÊZ\ܘþƒ?].DÁ”déÍ7³²ô#h…°Ac†@ =FÈëŒ<2ž¤q–¾Q;X¼ÖY‡bYÖF¡”.ÕŠÅÞˆA¡b©Q–Ö¸uo×Påö§ÈÒGº¾SLîÛžZ5Ø\¨—†…¢¾ò2J3V¶ 9†áñ4sr·ÈîVç @”ØU ÏY8®Ž†I@¥AC.¢J˜OÈsõÅ[½C'ÜÖ¶öÂ\oÃû7ðÍEÇ@‡ØÛ¬¬Ž,J¥ÊÚ(qÓe„ÃÁ7iˆ­†%‹­<3î¤þií»>ÁIÆÀ3Ôb8fÍâ:\[,| !saÒ¨Ò:Ï?­†çËQõØíU,[øã­|MX‹K’h nÑ¢Cܯh;×#’×tÃAµZ½Ùî~÷R©Ò`3“+"”ÉPY¡"¤&t!S¹ãÔAf¥5~%$y&Í.ŽQè)°x“ðßw€$¢‚­ ´êòû‘Ý-Ѐ9¥QÔÕNN6Йëé×JÀΞxl?›6[w¶ïûzãƒ7»÷Ô§¦{<¤ÐŠ0ì€*x1 ô1kÇ€‘r€Á@´¢hzÓÙè #›Yöe9´p¦Aʱ¸S­Ìðn²¶eÇlçñîò‚Üq˜—j†T^[— Ý•¦ ,ÀP#pá;Å®S(qÁIûúÖ:q€sHöD¨»¤FÚ7 ZîtŽc)ˆ„Ì2@¦˜b R•ÂÑ @3XUñt»ŒÉ:©šṯw{+w#íºjƒ!B­¸bsP„ y)-`"¸ðœÖ…îãGÁ%À(ßõ1X>cšÛƒ‡Â¼ß j4K€Xp¤B@ˆ¢J‰r[ >Ã>Ð%Éoy„”’‚!ºàà”%™Öè$à6Ð Pi3L=¹ä€Azv"sŸ¯Ìߺ·¶Ç‹Kñõ.|x“\»çXÖ &*¦g#¹°8¹ÑWˆþ€”Zx¾qL~ßOJ,cxD„ÁkÕdÔ}Thh LCrB‹|4Þ@ó+奻rH)7˜mmæ­*­àüÙ#º6É“‡0•°HÁ*ÀKLö´ò±`4âJ*AhÞQ=k¿°= @| ãÔÔ•Mùƒó8+CÃ=åfi© ÁÀCj}_'&v݆#MQB5ô ƒŸŠô£ ±¢œJ—üÜFH"”Óum&ŽY˜ÆÒÀÒØ22jÖñ™ëñ[7Rjü[ôÃûáÈl¹mëúÞ/×μ9Ú¾§13™)( ¹R„aǪ\–@Ól̺gu± Ä"D­$F"´êL&ëÇ(JLp逥Ó -* ƒÚd›$˜²ÓÛ·¯¬½t£Ü~¿b†4½¾€\ÖPº¡¥!¸ÊS?¼!±táT±tTÜx»åARÂh—ïlÜÛÙŠyäM¤º/%€äæ¹ÉstÛnO+iŠF¥ž-Ýq¤ŽëWñ¬¿IëÑÆPø>íP’Êg¦ã¶)†ºCz:§c´‰Âl#ÏbB²2¿¹LnÂÝ5^£lìHzh’ ·Ðò!SÑOÞjëz [vˆB_"pö¶‹×™Q@Ñ•!ä#£,Ž Ì:ì€#pD˜”¨%€!Å²Ž³Ú‘ÂŸª~xÅüáOðRg ±9Ù§DôÅ~ó?¸´†A¡Ò ‚!«ñ*Ú2dúB%¼ ™‰dš­#pk~4è1oª`ò§ö¸ï™FÌíÿüÍÍva ÊB¯òîØÖGb/ìF×Ç`=K÷ î`{°ÐM0KÜ(  à}ì(Í ë *2ËF¥ÜÖBŽã€o+þØÕ µ!ô‹hèh 7™ùß¾y¤>é“Áê±ç0lê–X܈½Kky"×#U¥§ÃH¨…ëPÔ6°Á¥ SœoTª£²¬"(Û©­U0K³j³¦ÄzÇ…¦Šöï`Ý8ôÙ0޶¶’êŒG“Íâæ=Ü!|Ò®ÏTšY77^´Y&žƒ]:ióu(!gsŽ]¡}ŸàZà S³Þ¸u³Õ"+ M‹äÒ:¹Gûk| ³‰ÃrÿÆ‹‚$ RU{õl¯@@ë1³%š*{q°Wù`uä°Ëe‰ 5%œk ñ˜ïÜŠJé $Kh† D\,©AÞ¸/ñ¦g?¸Ú>÷º¿8D˜hùTˆ?~‚žØK"p~ý?R¢1&„ «•,C…‚*¨ZѱÕàcY‚ Ø/y~‡z( ýázèW3dmc¿ýÂT/•ÿü¥ #)1% ömÌ>x¢6ÒÉÊ–ÖÌêz']b´gq›š¹m€] ìµÂJP€!°h‡o÷æx@È € ‰ïQId¹­N›´û/ª^½¦§!÷(ëÔ‰ý_¿4Ù ñþtpúNÏ"@ádm’Jc9H”cš¸Ã†P€%P…ƒ3°! N™(hY0ÿÁê¼woÉ÷?‹ °¼î½¤ëSÕ‡ö©C§¼³C",»®â‰ƒ­ØBüíH›P¬´Á…ÂBQ HÈ. ¢š4Ô‚2 F¦ÐÊ"‰b¬Fd,øn÷¡Cµ©`Ôî,;áÑ£@J7{+ö.®‰LŸ1%§|Ÿ/MS@P‰Y^fØÉš•r5ô …Vˆn!³,©5¦¹^7%vÝæ–Ý":$èÒöL7*4[ÌñïÝÉJ0÷‹ÍmhÓàm·âÑÈÎ\鯑ÔqW*k÷ЍåA?‘ÖZŒB©Ò`”WY0!JpyœÂ_üE13iæêÞô„;·}´Å«{•áPÔ¿û®wkÀ ïj@Ä2­Œ1–8ަH”Á'†Íe"oHA4=мi0õœcÐÀj/@Rq €Y›—òÏ_›:¿l–âAÌ¡®°ƒÇvÕž{¨ûà×¼b ­g+œhb%7Tš¬iÝ:˜#§¹!RjkõÁè¾Un;;èW]¯,7€¨ŒWÄÄÄ–sÛ–k|ÒÃÝîÍ­‡W……AÐò “pKÁXhY&^Y4¨_"sy/ÿúbטÞ^uǦœÖÎá\ànÔ/½ïW> ¢F)‹0Pa¸† Q„Z.!% >)ª+H].ó@Âæï´>*R ÆÀÈX?°.Qeþ?>p“sûço‘ Ëvi¸Š,rpEjñØ®­håäV…r]܃GJ½.Òº ¸‰u—cœ(%‡ (v¢Tœª´ÞÎפ†çh õ2#ö¦kA£±,êTÆÝ'1÷¦å³¹8Æ ÀrqÅUýÌQnòÈÎ`Æ_ üÒdžŸ9:|ã½à½§‡%À4­.Õ¦†­@ŒU"j¨Å©É6ë.MËуAå" ôàìbšচ7AV. 4ÑRqS”PG‘ºÎ¦}uøaýw >ÚÈ_ÿpâôÅÎjìþ÷÷>‡'æÛ)}0i±U.‰¬ ° ð8„Ë`®Y¥@î§t«ò¦‰Å°„±/|£¢¥%q¦ä  ¤¸Ú¿üÀù¹‡+QEI‹–ÓaçöèÝž¾ÛÉml÷¹&,H`ˆ ÄAÒ`Èù¦ ŒŒ¡dm8³}zÇöŠ Ñ$¸Á´Ïåþ†Ïôò®ý»ÿ:rlùåGÙ¶Jš™ÖÕ L\/LÆó?ý^±O䂇Ö;ñ`q­[Ü}#£mvÿŽÆÓÇËJËy÷Ì V¨bò«ŸµÕ™lj7·ø ßEk|Uˆò±vìÜZ.Þ­Þ¸X^h—›€¿s®øÑG¥¦®oJ¾và§aäÓI‘oµAð€ ›Ò0DY¶,A6œ6YÂÆ€&Èœ#† b„ZÎ÷ÒÎ _¨ WLRðB¸‹k´#œ¢‰ó üà&OGk2é{ûl9¥ÙNìQzŸGæ}µI!Õ”Ÿv'ØP¥ Ù:5Œ7 ǤY o­“õpôòÙìÖ‚‰LúÜ~û¥O §¶J:vÆ‹,Ÿ Þ<ï¥:Õ.’Ð4l€Ñ5©†`?ƒœDݶ¹§ÿ4òå×­éfþnxxó~™3sÁ)8Å *I-h5¸Ýív 1÷š8“gVf¼Æq²fìqìåÄv'­V‹¡¤*µJR1æs^fÜïæož³æú.5H­>N»j›SÇxÿàyÊ•Jª/¢>|à˜p€¹^ߎZ‰žmñÙvù·_d±Êû®åYÙNìÔ‘ìCò„ð‚Ôæ=à9D.ï³ÍÓŸPêˆ1ØÒØÌYþ:gÚ$•â´ˆ¥}Ùýåy8/ïlv#" —ÔÜJ:*Ùˆ…ÒFiB!欦=ÚYÆ…-<#yµ3 ËX+­±éã&Ž-S À] Z*-–5l*-ÛA¢ J6„Šx÷ÂíN‰Ü;—»¿ §+÷Ö»õv)ÍÜ>—ç´+T©e›Á¢ç óCÇzöìÂ'Žñß{i$W(n<ÜVvúÕ§Ý“ô,~oÏ·ÌX²cBÿê£Âªd´ºÝ¬Ÿ=j®¾3ï5¶ÄLСé·ßfóíÍ9€sîL:Y §ÞM½(·«‚^»^]¹Ó¥¡xù¹þo¾lªciÿ îõ‘ž5=øDØÔ„q¾Õq§7:‹³…{wØLMÖ2÷¯¯µ~}ƒíæµÌGâThð×g‰ #àÄ–ˆaà cb4ãî$îqÃÁdØ Z½¢á^°3¬®ac°…$­fj¦ UQФ%ózÌÄò¦“$ñ0¸ñ§Ó²ÝMlAvQo·áý€wsJ¡ J–=QÃ&~—X¯(µK³“@+À×A€ÌZ ãjÆÈVmhxó:Ÿ^49ÕxjüþËøÒ“îNÏÕœwíB\×Ã}ø³¥®îJ SÑN‹ R¶A »ƒV”° Œ§Âu Äe¶µ"ªçィ $‰_q³l¸šÛÊ;<:)lÔÚTεÔ\§òÛË*EDz+Ý‹Ü ›÷KqZå÷=¦ô‡Žò•—¼Çƒg%9!ä>@;%3ž»™2ª²\•|T5Á»¹ä}qn- ‡ki„"8PvÉtn#æFeA›s@{Œ»üÿûÌ,Pª‚ibô*eÔ‹<…2áÏæ&‚I¹¤MKy,JEEUlÓÑVpw)\kdäóIøéûäÁTéÞZ¸Ý.¤Ìís¹«,©Kq`Wpúù¡ã=Ǻ‡¦¿÷ÂP!_ZXç(úÚ³ôÙ½cóŸ6 ]9îÜ¿þÐ}°ÎhÔ¶OœT·Þ1?l‘?´*¸ÝœøÅûŠªÆ¡›é葹÷£˹Rܾ±V¾ý3]ØhÙñƒ™çåÕ¬,fé—^ytGëürWà•l°ç‘Å2œ‘Tá +²T'‹s¹NÒ¾`½”lLjkã`ƒ@ñÎP¬=#"Ê]®hoÝv8d€yÏ9|–T'|ï ×Ør ±àXߤ`5Z€ƒþ«s½çög»Ë•Àn»•r¸Ùö¶üêròù=üéur2­u y ¸d±ÌN)@ ¹#©ƒZ‡Ì,SˆA-y^ҽЇL·u@ì}qP.Á\Œ²K­TkkrN´¶Õ §¿ñ¸÷Ôa—|w!¼}7g#ÿÝ÷;œEݤû°´SUËÁ(y‰™g¹6²jBµÐ(ƒ¶I˜™„‚ã=q:ºtÄýåÿ»ï‡´pw‰lw»}Ž~_áÀÎbÎ/^»>˜e[QÊÓáŸÈ9»¿QÝbÝÊ6CýR&3FÔ-d!qšëýJhË ®6\Ê¿Ö)2º: î̲~‘ÿ趸·mÖt3ê)ç«ýùî^vn¬üôQuvhäV-¡lj‚Îkâ¼ÝãîxÖ*XfO¶í¨{ ^CšoPY®bX ‚\Z®àF×4AÊ„•0T,a„¶-; åÂL°V³AëØŠ4Oûƒ¾öŠj¡#*‡ìò²xò@|æØ›ÙòØq(ð¼ðWŸv7¶uÓx›Ëdï!÷Ó_lŽ­¦ýQ~.bÁPÿ¿Øª`ÝÁÝ­¦µw¢mrk/+õ!kƒv :üÓ3iÚCÆ,o&ûôL¨®”ýzm¦ÍrûJßË¿»*lD™OÌò¹2ŸdUÎ^}vøÂDûÂQ|[Ó•t¨—±Í3̬T‘Œ(º´]]ˆ:1!·TØgIì”Z&mC{ˆ8j㘛ÌZ:T:¬ƒ½LP†@Yÿn>p z÷ööÓF“æBƒ¼e‘I(ú[öÛ«w”ü ½¼Q|O£©·âÚûàýå=ûî\ÖlóÈÄÀ×Mr^IÀJXÚ7¦¬DªÌ*‚ÈF”>&ИéÏ oìç»_SËÙF‡ÕLŠp¦µ5½¨£º~êHõ›O8—ŽÈ¢·¦¢«×­Ûëù|ØVlèøQ¦ûM¯Íd͇. ’pÎr=jDÄ.¥-—îਠÙÏód&¦Æõ_:?}ØþÍÞ·? QñÖ‚^ˆÚ% ݛ۷#—ó ×oÇ“sDŒHÌdì#ÿ”Cv}­¯Õéö5`˜öKܳDu–›ƒR j€_aÔ»2͈®Zv—{3SüWÞ¹Ão­ÆÛ›¤WK~¥/èìëeçGòÏ燮oÅ ´E¨Âp^×ZÕ™xÚ® ;xÛtäݺ¬E±7¬í@gFVÉÉ÷°ÀÑêžT›€…d Å‘’ÔvÃŽY]rV7R&D‘&ÚÑ²šëŠÊaû?›¾x”;ÜK—;VKì<ìçýô¯?é®Õ¡hc¹°ç¹ü×õÑ%9zSELJýózY©l­vò#{‡·ëÓ!zÝnî9ŽÞo)#²¡“å\Ô¼r#é-šw8¸¿¾Ó™[J«^Q¥ñòª‰ƒ—ß]í]ë ³îÇxé…çò S͇àÜ£Þá±îü"žO ÷g»áŠUUWº¨Q€”BàZ$N³r)UB&D¹²ÔC4'gT`9·ñyNU;W‡³¬ ¦ŠÁj?jo%D­n0h #åí£ÀÌlzšT{«vÔZѺ¼ZÇÛ¬¿±Ö]i7Ó4Ý„I ȇ„Ó€#?“)†L“Ý@}.-e]—Cú¶³:ñlþé#VN·?îg;·ª L$®—Šú ‹qsò‹¬± !Ç` w©¶.îÁÏ\lEuøƒ³ýfúÑ´3•ðùê…ÃÂ.¢¬HwŠó@®ä= © Ž$çñAÕÞxâYXly?û,JlAy‘ Ès’ÞAð ¿?·¾Õ¥.$ âöO4WåžgsŸŒÑ¿þÍê1†¾šs›Cc­tNËX-K–°ÜfSqP¿#}­±¼[ê+ñXUÚx…æzê]-“öуzáZ]¤PŽ4ÈÈ0«Ï98¡7èó²ô®ITá™ÄDŽR;R,2Q†u×$Ÿ &ÇB¸„EqÉ¥¥‘IíÌJuX°9“Nuï-ï°Ú{Æôƒ¥`ù¸»Ðœ=ä?²}ø›u¸ >¡—ݧ^è[X¨i°KÄ›_m¾}K—'F–ÖVóÈòŠ•ßÞÆmÝŸ¡ mÉŸ}Þ¸xؽóÛ6h˜8ì¾ñE³mR‚`M÷#ØúíM4ÑçÖ–’T«~0ßXLʇ¢ti‡õ+Ÿl–æ+‰JÞ7ËÏ?çÏÎ’p¾cxü¼wx¼3³LæYñáT']²Š¸Îõ¸q Ulw¢0™ì(`ØaÀ„r9³%.!¸kŸ“&DqqýQuèqìµ:Ôw§uk- 4Ø  ÀµÂcš¹y|öpOoU&w¥®¶²ÞÎj¸TY ›(ëJ¦”HØ`˜ 8F» * ’T«$­g×ìµÏ|e¿gÓÆ¯'²¡ížuˆ2•a· )ôU×dó;—y{š1 TÖúÑ]ðÄ#ëIKÿñÅ¡­vçÃ)gš‰ûú(…ÃÜ® Ù†@hÓ7“Ÿùæ‚¥ˆ°Î”Ù7ž(ÔÃÆùKøÁϼ_|ÞD(*ÓNÔ;ž7Ð_\ÛêD.ööŠ"X?6„÷¾žût’~úÁêùý Ë[cÈH9 (#FSbÄ»í °¤É ä\¹iØ3оPµûûúüh¨’b¼aÕvtÖ>|ØÌ^oId@Já àMàVŸ}p&Y:Ôï'¨]“¦3 ˆ€ŽÐBj¶#ÝŽ™“©ŠWUª®¸ò×¾—fQÑóL–*ˆ©,KÖ®X†I·gB9P§í}0µZXú‰ˆÛ÷vÂèYû꯶ñ5 ÑŸ}ehiiCƒW²ÉÂjë7·IÏØÐÚR-À4_Î}q³µ…Mf ÒkØ*üà]ùøQçê‡ëô©?ª¬®±­ù¸hÉz00›Àü8÷•x5ÏsPõz:Ÿü"%6ÒTäíKf[HC)ÛöÀªIº°Š¿÷è ¾EÄÔRzñˆ‡ ‚5œ½Çó£OÐÏr{…,-„¼M u·Ó¨j÷ °Ó"¢HÔ¬ˆ]FžswïO,RÛŽªë“óÄ͉ Á‹{kê4s…SfM'WÊ ,À ‡*Á¯“^zͽQc€ûNG¾b›ìL ^¤;_¬õ¼õ±Î:M°=„G´ínàpyîhƒ˜ †+ÞŽ qÄúòãù¡ÞT‡©Ñ¸¸Ü©mÌ<ƒ ‘D€³µzMĹe[É‘®DÞéé?¹XM×-؉zýo?§’„^kûKQ¸ Ögv²Ç\V0(‰ÝlR@Úµ ð‹§KìO/¥BløÄÖ¼¿û’¤õî}×£PW8Kۋ¦•†Å„È`!Fq£¿Å‘0œ½xÒß×_¼úyZ¸/ö‚Zu 5@8‰Án¸1Rp¹mŠàh¬•N“¾Jù•'éé¡ ZKbØÍÕßdËW­_[‹Är(æ(Á'Ð%ÚÍË~Ù­3K·Òì.œæý:ˆÏ">úT¥¿TK ]š+lþ¸.“ŒK° "8îÐ|3Œ—®=_ؘ€39º,ìN‹îè5Õ‚=·[”Bbÿ‡tø}¬í^H©Œ#íÍ/'ÍÚy›†á¿ç«=Ý×Mj{W~¬<›´ã°Ò€ÓnÌ&Î~÷ôßÊ!mº«ª>õh›rhw‡^½žÿ†¬;Y^ö¸ýÙ~É,Ö" NWñìJ—"(ÊfŽx†Îmïþ8ËéÁéô\rñ°»³Àâekß±`×#ä£v®ÎÌΧpRÒíôƒCB¶e‹ÜÓ–ÚÕ#ÑØQQâfÓ_šNp»`S‘䧦¶ù1$¼ŠËw2z*ÊM±r8n§W,nÝÀ ?mg@+‡ý‹_±]“¹Â¶8å|º\~ûœt›û˜Za†Z¨]Ï#GxùTb­2[””UÖõö.ç¥K呎ÝJ‘€Ên7µ‹$ :˜È :¿Þòº:‰|\“ÓÍÃÉãé?{ÆÍìà­õ¿ó<$ ºÚÉ-‡Ñ¦!Ÿ;éŠY^€î’µØ´;Ilçè@ö^¾ÈpDæ~ ÿ;¬?¾SÒN»…,…Î ³‰¢"ÎÀ2ܶ²žß\r¥¯õ W¯}ÔÅÒ]€ëT'˜"!XmJ)R‘”<+€§¤1R'¥|ù«ÒÑ­6›¤ôI nüZÔ>£6{¹pÛ²c¶K C Õ!Õn^õËnƒÛªg÷à ïïó¦Nç”}¢4è7ÓÀ[˜ó·ØH°Üä‚‚=.5!4‹ ¶@(ÉÈ3çËö\L¢Ž³³ª{v)!”˜ÈúÙ/Èp™)^¨ˆÄÕÖÃùh+Aœ¶»x€ÂíwÕk_j™g‹ÍVcÏ!þÙšb R¡´Pr»Û  ùß"ßzZÿßUÌTwI‚µÞeP)Ø_yÒ³ÂïüƇVlj¼;#¶¡çÏ ÜØÎœ@ΔþòmtÓc”÷$q4zÔ»þ#ÇŒÖjs}ýhFìžË "&üÈžO{›q½Kì’ 5LCn½pÏnµÀ€™z€·8‹‹AT)[û=cn3bËÜü’©¬³¼†e0ëÈP Zª¾ Ëk·¼Œ{üŽRgú{”×­9äÖó?,ÿðýŽÈ’ÑѾî¶ï«ffe=È­öècß(ÓƒáÐngcÞ§y9v÷eu;íÎç—£ÀEöF$ÍŠY‘BéQKž“Œïöÿ»//îbŸM;™ÝżrdoøŸ‡~‘¦…òGwÃÏn{‡Fð 'z¢¸]Û시v ^ƒõLÛ›KšµeÐuµBóâIý÷.M€×ýÉûÞz—.ô²æÄ>X ÉÚ†‹ÜnÎxÿ×Õ—ŸzØa*a˜3ezóÐ>`o ì--»Kë¨)»&ÕWÚùöuúHŽïccG\8“Nœîoo°UAÖq$wÔàñAwq«þ‹ëÙåÀmõ›&Ì_¾Nöšn¿„™B¹&ºs‹@©ÍŒ˜Ðê2h­èp2KŸÖR½mz·©YI"í{O&¶0=DߺÂ>]µ¶–Zä(rÓ €ÏõíN6cl°õêïk§¢›5Xû‘åÎDK‹–Ú#>¾ém´‹a®ípvgA:_NÚIöœ«|6©Ó©l¸¨ßÓ$ƒÙ(xñ…î…ý¹î’;ó] ÈœpÅéâܲxöq;ð²ÿü‰bB³2›Ûyl"%ßûÒ&·3üöÛ¶i0 nьƄX;;x³ÙTö_(þÅ/:Bà†“`á¥):Üý¹åÝmo>tø!óåcØöÝOïw»ŽŸr ëÙL¶•]Éñ´H4U°ŠhMÒ\= t Ð…¹(^l—ýòÎNßHµÉâÙí`qÉî«qWÁ–kX!‰”R#½¹B7¯Ö²ãX-`gxt¨è­­9¥wÒÿíƒêÞKXÜ­†MÛ×-F³‚ö{FÕ“_¢é±¤ÿ@I  Ânw:Çîuóã;²6 ·—ƒíº§‰ÕÛR5M;"çéÔ!éѽÕñbåéÝÑ+ŽD̈üñýÙ?}z"·÷Z_Üɳž;^Œ#±µ•‹nbÙõ¤ÒÙXRIYí\ qH÷¥súï^ìW^÷ûŸ¸Íß;R¬ðîáÝÎr—,oXŽ“‚þ?/y¯¿½ÉVº‰’ÂRÃGÕFýg×’›3È·ÝkU€Z[Ö'¢ƒ­4°Vd]ƒ&— æ 1&ò°2®¦Û<`Àq6„ÍÀ––+Y oÿ‘ÈÒ³åýËò³%²j9Hð2(‹Š––€t!è>ȉ“¼þDå¥Sé:«ý³h~©ìÓÏÍf7¨û xvNœ9ﷺɎ_(\}(š!ïÏr5¯ÛOpXè ¿ðâÆ…ýùOî·¦™HçR;µ‰äÍ/Ä=* êªíš³-ã¦ÖQiÁÒ&jk•Ÿ;íþâ{iª{YéŠS MjÕm»¯y¼»ë Ž;ácgz/Œ‡}ÊŠSAÒ®V#Ï£Éh¹ï…ÝáýBåâI; WýªÞh‹ÿø~õÎB§‹ôĘ÷üNo}Åë˜\.þ›õ¡qqu-YCJ’$G}¾?¢lÅ<¼Ç›­xZyS†¬Â.á7ã\i‡<{˜ ô'y à¯ÝíÜoñTAfäºÿ›ÑSG¡Á­søãµÔßûyùö‚ëX"C‡¤åäsÇÒçŸÈ?þX}|Ôýü΄;¹Ø vZÝaψ}åê¢èð|uuRrÑ®q(‹5Z­µ_üÖÈÙÒ¸=o}ÐàH%Ž«3²Åd‘æÃV·:{wZÿç;ÂÐm¡%¥³XDz0ã™d ‹tyQGÔ4„D¬Hg­·7Òs§ìýÚ,M³Ô›Ä)ÓbK…6VÝ?”>Î/œÃ?y3i5ŒRД&gɲ—ëq9cÌdæöàº+ÿêÇíF‹TTåkOãg.Ôw¸ÄÊÚ‰ÍR­A# 5_Û¸vÕÄôôÚ{v˽GÍØQ²÷øÆ‘&Þò~öK]ËDBäPa•”—dF”@”„xîDnfÍ4±ë)\Ù]ÿ|¾÷–úÑ}µÙ'÷ÁŸ=ÏïO3Ÿ¤ÌäÞÅõÀéÊp>.°ÑB²L_/žO„Ù0…3´1Oæ'Cwy¡É°Ø°G–°²={²ß;“”ÿö>ÏÔàéRüß}ÙV}gVþï¿oßìyâHkç‘FɹcÅÇv¶ût1ŠbGhÁPUö jã/íöÿ«ãs‡b»H¶XöÞ.ߘÍ: ÷M8Ïî# «îBÝô.¢=âú¦œ™Û 2ÔØë²‰Ì%µx“×'Éö¬ ÓÊY,ßLúÊãpê Ý[r¶.@eóŸl‹†1³ˆÛúû_Žž? -aßX¦® Ù›˜|÷N®Ýê¢ÕPpäBϵéx%4–R€½]Vß^ B‰¨‰’Is}ÒßÝÇN„¾=í±Ãf÷!¹û Ö¾g¾óÓüýE/Ömi€Ø…ÂɽôKO”.]ØÜ7jñ±Œ™=7•ÇP¼fÖ/BM$ÌíY]“ ˺ò@¨V«[Ù³¿·ûÂN‚ò[Ô %˜ã¦ÆU»Ôm7ê-Ø·ËùÎOZ˜P;±Éæ1Ç ÀG¢ÞÔÂ>ÆÛpE@€IbI…úŒ‹ÚyXC ÷ÂÌ-?È8Nt;ÃŽkˆ­û¬üâéâßÿ4žš¡^g±MìBÎ&Í0ÜÐTrznžã pŽä¿÷}Ö KŽ'ˆ(W«öÈokSø…è‰SvuÌT–Ƌˮ±ì/faöºâïíCƒE"¥jc$ü¸ë Þã3¢ÐàEÌr„de ¿yO»ÎÉd ±ÿôúùeœv$oÿÉSø[粊gbí^¹§cî9ªºéŽ®,¥c»ôô–ýùÛtýJû˜è6]1ké¼2§ŒÄ´‘†ŒØNYŠ»‚1*@ÒxËþü!º²–{b"ýG_±~s§û?bß'¼°¿?þÏ¡–ˆ<ñÛÏÜÝÃÝÇX'Žž<¡Î¨>sž?K_8e?¶s«óægxhÌs»tb°:µ ÷¶Ìê†øâ Pÿú%³¾b¦¶ ¢%çìïA7uRžL^AP±½©B©v!~܈E¢ãPqP†¦ùâz õ¢Ñ±:­\k¶ßRy@¨éO}þÄ5Ño×·a±‘}üÀ½>zöD{ŸF»÷yCCé_|Å) ïÕdÔ¤šªaêõÄ{d¯%l¤Êåtëë÷ÕOÞô>L2›´[u½Ä1ƒãÙÓ'½³g•G3[»ƒ£þÃûjqÖw|‘DåÉ»bÏÅbw+«ÅƒçPˆû÷3j¹™r;ÛÖìFëå§Ô__i,-ôr„j’K›Ì%„µÛÙŠî¬*¶äÜ«¡¥Ñ^Ž1ãkt½íz%Ê:utÎnˆ¥ é±Qärw¾Iî1 þ¶å¥‚&z[x/,Ëä©_»p.ù÷?䓳Ú)û<žeša²w/©ùܼ´w!ïhù'ß5'W%*µ{Ùð0j¶}åðg/ÐÞa§£Xœb›Ø\µ…í^›53—»¬·Ïêó!Q“ Y.»OÇ™îq,…2¢Ð†¡sˆå1$3Ð߸h÷¥Þq±‚ø·éüìóbGGËäOž"ß:'ª¾L‘wõ¾3Ç’•Ä&ˆïÌö «õmûÃw¡ùI}EÊmisAsA²a"ögbÚ°TnÊn nÌ8WK§jÿäëî'3ì»?ÇÝ5ki~_O÷<;„8˱·ÞñöOÄ؇÷æÏŸ!§ŽÒ‹û*OW/É?q ™(xÿæpÿD˜K­ÑÊÈüº¼ßHÖëúóh„Å×.Éf-›ÞÆqÂgçÐÇ“(Š}Û¤ø%EFrt•«®‚a›ŸT¢fÌŠ…U€ögõ3ñÒ–ûäøZŸO–¿Wmšª‚…i‰È'NZ{òêé½hw¿®›ÅVöÑdpk^v'ž¤cðÈ ü?.§qHò3@;„5™!²ÏЪ!”x#Çóùd†§Fh—ƒ >²“?y*8w‚ƒ ŽA##èÁ$šœ)h_%qqöavøéÍÚöò–é9¡¡Š¯ÞŽKb‰ðqµ0³Þ|õiüëË[K‹•ÓºNJú *ÁѦ¾½"x 5•‰-p¦…¥sâ«ÓVâ‘}ºJðü8ᣑV¬âÙ‰R‡.”]¨eu€r›ûB“<®EØš^q&o9•béaShœ0ðÔQưç^èÛiʇ&þÃ÷ÖcÙßzKF“Ñ”×’å·Ó`Úžk²Çžòž=‡z½òç÷bma›%ÔpìÚ“sÅû{[ÍÀÅ%R©ò/¦ZA&0©ÆEm?4ÚŸPL=½OÍ7á_É÷>&+qPtlOõKF="a~˜æzÊÁâf²ÐdÜ`*³@#NÚ,Þ}««×ôÙ ÷ }OšiêNTÁ…_©ì6îHmKt•š†møÊsH³m®lº“5Ù7†ž›íÙ\:vQ²WΉ“¹njÛÿû[äA]]8‹Úa„ÛaÈöõƃFµ»(Ñm£x–w¿ÿ1] OÄC\…´½05 ¬®Nz×f“gÎ ÍEÉõ¹ìò åå<ô) ÷!Wo³ î<E(ý9•“ÚºÅE^Ããùñµ­le6áVeªc`Áš285 ìøÐóô±JgËÞRªÒÇWÅfÖ»ÑínwÝ…;¹Õ•´¯_:™ÿó™PŽ 6ƒäIÇ Ù"‹ˆÜî˹¤,CWàíÏ); €IDATù¯>¾?Gm,‹Ê(¤²ì÷_«üÎsñÎ~ÿ³»Á'öÖl(=±.ѭŸ)¤„T¨Þ“µ§_Ûuà¬5vÈýüóhv¸e ÉBH›YuÔ/v¶ù|S®´ ÍF#Õ–1&¬Hs‘hùĵ­¬“˵Ú1B~WDR*D´àؾ•õ €à(Î$q®(5\(£¹'¸ëra9uÑ©8fb‡Ê ²ÝŠ(žš÷ïÞ’½¥á‡­TAf(¢À\ èÒ—rÕqYØ{ðß}w±Å€9ÙF,IG1 ùôϓ‚ý°–>û¸wé1ÔSè½q;‌sškBg ÷ô.µ9ŽMu@\ž ó¡ ŒG °nÛé}­,ãs£©Fçv+›íŸ½o}øYy£ëhÜ:¹«ïKO„Ugn”z+ÁÒV:×äBb[²½4ת:Ýzîá»!Yû½âu–ý@Áro‚Ô…7 ›2þM„\û=¯- itœ©ª‰‹ýú•sÃÿï_Ô>|XZMã ¡²–¯?*N廩'þË_ë{›ì±ón܈;:IºfOIù­v$$N°Ží¼qƒß¼%Nî§;-ÓÔ™)ÒÈHÝa7æk³ÉãǶ2sy^ÝXÎwcã£lAQp5?Á°JÜ$+ªølîrSe  }k[Õy!¬Þ©.†yx`Xbˆ²Ã£ãú…ÃÕ¬áÕ¥Î÷±eÖ†þµF´ÕÉ?¼“­-ZÕ 88~ã*QÚu‰—šèÊvYVd­9³ÅVræ|B2³¸MyE¾ùËž›ÓÚ²UN;FdØ-tÒäo¾\þ—²‘ïÚ{¡ó…»1Ýa\|m%¬ ) UÐsåîÆ‹¯îÝ}¼½ãLù×t¶(39i¥‘b¬0øá¶Zhf«m·QS]V:£X,?mq0V·hÇ1³œ Ë´6Ò`m˜›wl¤’J"ÿø÷ȃ‡¶‘TÄø ÀÎËÝ¡þôËòú=,•N¥Œ}j™r4PXÙI—Moøßžë(¯Ë†»h>((öþËÿ¶B鈋˜Eij¬ªW*g*¿¡‡”h˜üðùîƒ9çg?ì ²Ÿ|Ú©žm9Xw,ÜYÛ€{ÓÁbM8‰ ]ØÔ¾ ºùY÷@óTJÀØríÏ®™ß< ë‘’ hÁÅ™\­{M?¿¿q ¿yM\½Ú^Ûèuìz<xÌ)°•nò0J<˜ÃÓßsÛªÌ6ZK×½'RcŒÁ²`ôREãÞU,E‘Ö,É Žx÷^©’Å4Î'‚Á„¯¿õ%7Ë™õ»|..L0å«|”{0ËŸ?LŒ#þÓ'âÞZîÂ)^N»áþö–¿Æã»Ø®á¾{÷£ m*ØHùgêEÊXb”'©QÌÂôKàÞG°A¥¥P*ÇÊmHU‘4r÷£aݦi¯¦ksakUFȾ§âÀãš[ÝZù³›Ûß»‚Þ¸­Þ¼©.ßïß&Dg´`§¬½Þ5צ½oj!‘ÐÜ%ú 7O™i"Ô™³Äø!?´ÙÏÞ|æl¬ €0RiטrúÒcVÕòj5=?½È-&ó¿ )%¦i!·Ð®,Ö¦Zk”÷½ª´^Û8vÔr]óÖ›YlA+Ž(òµ%Gºb±DèJXL6»®“7jIH¦HRç¨ÆXýão‰°áÖÛ®ƒ#€~a¥¶”%'… ¾õUoßîìêu…‰äÂH[çqo‡HVîò:¿õÀdŒ ¡cl"˜@½yfé i²©µ\É‚…¤i WÙWRJâbC2|p/¶°ÿ_þóEàd*EŽAŽòŽ[Vå.-7µ?~.º·àýäÇà³ÈcA£©¶²qLu»V77æêÒÉ+Kçf6¹‡‚Ž2Ž;Ü3,– (%Žøø:¾<Å—2É ±¬DI³Ùv?œÞø"~ã&yó:¿v­½²R‰dâz<•P"na>Šãb%úc§°‰uwR-'¸)ÕFXSÀ¶„¬ðßyÂ)ùÁú†Üšb~?†|¼õ.=˜e PR(¯5ûk›™ ÜrQX¯­œ?G%ÉÞûݼ©uJ²-¢Ú|£Lðz·mEŽ[ÀVÖ2 +!":°€"ûŸý!;öÂ:)ØI¢JØå–4 ‹žõ{_uÈßyºÐ•|~A|¯ÃEžŠáç éŸ~9¿§'©·ÍƒQ°«™¢L¦ðO,Èÿ½oZ0^h&¡íڢɌM¨íª¢ë$6B–ÓûËß6ꪼœn¦¢mC?!Ê#xë캵ÔÓ¢ûTs£üü'+&œî3Ï©3{ÑÑñR„ãéu›šÀQq£w§­­ŽmJ•gʤ‡µÖ’œÎm´¦ŒEl®Sô›EO÷÷xÍÆ]Y­XÚìËÃH¯PT`Ø+§¼«2¬‹…vÚy “"­!€€n@²`çOÈÖXiA”Ga¹C¶ÞH‹ÎQràm&ÎÅSúŸ?‡]Ý\*;~ùËGÇòÿâ'É­û%d%çC#éZ¨¾÷óžÒ 91–(N?YrÜ®ß͆‹éäBrs-X¨ÇKuë¹ÝŒäì+*–Ô/nüã— ÜÍnO*`ƒ)rgç¼d;Û”o`§NdªѸ…“ŒƒVžZ²QI²„ä ý¨ðs™F9‹§Ø£b Z²{¢žJavÆD‘z·è<[ߨôú6Žˆ´÷ùô™ÝøàN;ðpUÙ:GU¶ÝÀ÷&I­é«rþØÙ ®òæZ–‡ü:IêÊêp)T¾°«$ÌhŠy]´Ã¾ õ…*…ã±Ê,U¢8|ÑR\Ç*@ ÄÓÄ“2“ ;e2~Ev½O“¶«¤4ÆÉëK¦ù'Îéÿöì™îýù’çÕ ÉéÑüÿô«ìò]ÛôÂ0>4–®…ú?Ê÷äO‡i,>\À÷î§öu|X^é¹ÝPó›ÙF»ôÔî.vÓ›÷ DÛ¯ÿÉ •ÈKnMC¯ö|£m;—r}’’g°{ ‘uG¥Fú·J çZ‚ížÐ|Lc‚ˆT²jà .¾!;aɘúH÷öåñPRªÆr¤‡2×Ï+¸¤#¯ýyäV-³.–€ b”ÂiQhšŽ’ö˜fþÌ*úør²¹*]P‰®¬q}h¯ü“ç Ï=Évíõ~sÖ’ÔUôþ]çIÿ.§6ëvÊÖÈ#ÞÕ› Å,›`­ Û¢Ætj»Þû’¸Åù•nf(3i¤æÔ£Û)Y»{È·^ƒÏHžf€†80·.¥üé“öÅ}ld¨x{2´Ä$ÒR•Â㧃G÷8ôÃï·œ"³•`¦;È"Jh°Ÿ{ÜY¯5§'­#GóïÍ5³F:¹#Æ[Aá+—àìIX^3ó[ ’Œ vÌßùh­‰w댧¦ :”–$ô¤¾WLN+a¡ýéá«··6±kh”‹K8ÃP…G榛¯"/ÁïÜ”wh@'°Êb?Œgwçè Õô ”¦C&cÏÀh¡õÿ]ìzùzM7ßSu츺ҢQàv¬Ì{oÊýócfÀ²]%5j ³Çä1uB¨?P@dÏ.T_ÆÀP<ÐY¿ Ã:}Œ$g-Ó˜’Ü1€ƒŸ!ÇF[ß¿#‡¬µ§—ÿ—ïªù•RÅmw³|a¸åK¾‡èn֘ľ‡ÌöZÊ¡ñáeoâ÷q0dsÔÌytj6ø×eþá7Ôø@m®Öÿô9wW_ûéüÚíF´Äðq¢Ï ˜…xŠùý4@xˆoœTp F!¹Sv,=~–ö*L¡7ázÖf5¬\î˜X‰¦Œ¾qÔyrsQ–uIžæ¸ÕN4Újj›Å|K°õS>»Ì8ÆÀXÄÄmp?í$›+[)K€b×ö‰GÎ ˆÈÒ'í+hâ„!Ù³á×ÞüeôèÁ¾KP£>ãÓ4—ªfÛ€ e€`—æëí¶¯6“ȸƒé"•j„Ç%8;2fÎ^kåßø•}‚ë"†\f"íÈ“Çz¿¸)³þìãùwë6ø¶ý8Mv¬Cýúo/€}{E²¦q$c¾Szú’¨·[³SÖ®]^p/c-¾åë(Ý•é ¯>éŸ=ÓÙjV¦6›,*´\‹ÊŒˆ=Jº±zçãå®1N2:ÁÛ#žKꨧ ¿¾¬8|zkä“[ëÛà`’zI ’(kÉÍى٩ÍޏÏî‘ïÞIo=DÔHa#mØ1,îé€Ýö 7MF¦ˆF쉠ó/¿Ä9·Ó:ƒÑ+Êê%šo’$çvl–{wÒù/¥Lƒm{¨Õ©¹BùÞÌ)º=-½=%¸qûvªÚ0À™ñÇ 1yœ¤‡lÛpŸk‘e$ ø¥!|°Ÿ˜ù¿º¥GŠÝWÏõü/ßå·—½ª›¶³ÀïëÄEï£÷ ]³µÕ" 9ßÞ\ (¾ÿ‰3ô»íüÞõèóŠãš»“ñ¿êúÿׯ—~=P»[/9µŒW§¯æòªÛ †KËw ÌæÕgÆz+ÖærbX2£Fj[*¨º¶Jaï~S'?zCܾϨðƒ ö@O6ÔcÝúI{4 óxôˆuáq¹{Ü][×õ¸dÙÌ=7æÚ3[ÂÄøBÐŒm1ΆíP^:ÌL;W¾Ûn,¸ûù”¥–c'õ:üÅ;îw?OúýÌIûáBФò` (íýºÚÙÇ}ˆMMº‰TØØ.ÖAl¹Â—Þ–´'5¬@¶JñyY,Xø¦Î´—˜—2¼––{=þƒÛñÒvö'ÏL¼ùiçýƒ‚0J-òëÛÝ0úίX×XˆgŽ˜.Øß¾Æ9A[[ññ 3Ú ¿þœp%d.[jáš|âØ®ËóË›iÖë{yómÚHQ©øeJ ~â{‚ß×´­<Y”F»A1ƒ4r„D‹*¾g+cYC4.Èä¶Æ TT²|ú ”ÔÅ×dmËО#SíÊ&”gþ:ž½n¡À‘Åô'ïV2•m|jŸÓ0ŒÐM®×ă,'+Êe†WÇÊèkßð{*Ô sï§²ªù)“ßi/Õ`i›„†a•ö`µ¸Ñ]íðú¦ú⺑D’Љ")‰]c?º×~æÂŽ›“ ìWKfa¥ô¸4Ê?õ,¬¯Ã°EqU|±Ÿ®‹0 Ùã§\½îG×£™¼3®S?ÝÞò‘a‰Ñ_}±šÜ‰EÓ3iIDÙØ£ùϤ.²°ö÷ Ç‹jý ŒWEbW Cbv)Ý$±ïÚ]?õ„ûȰš^fƒcþÍO ehµ,œ2ð\miB¥xý…Ñž¢_ßà*ST›K ‰RÔE¼ ¼=cØ2?{Oݼi¬‘B€4N9ÝY¶®ÿ¬Ý‰¥iì>ûÛ¿»²¼”t’œKŒ+*wæ;S["tn`“Lqmd»«Ÿ>î/lÁçÑnM»Œ´J;,TŽ-š øË÷ü¿ú,îµÅ¥öÃÅÌ7éRã#*ëêô²¡ïÛz)¤¨&ޝÄNKFÇÚk*oÚèUÄæl8Íp“eãq“Ï|IS¹û\öÓ{l±–þ§Æ~ñaãýEãÓnL-œ½vž¦‚ÿÕ_ë&æ±"÷£”¢ïÞ‘é®o$ÇÇõ@P}ïj’J ¾Z õÆfüäÑñO·¶S3ìÿó )·Dhû*¯”¯AoU8¿°Ò+ʺcÉ,³‹ ‹ Q%:'¤µ¨ã‡(R"YG·54¡¢·$¿ô8;ꃫly“Žê¢-£˜£î ÜýUºv#Mýœ×ßý@Hîh-0¦g”ÚE¬ëÜ|\Ëf°+)/‹²\oA}ëwü'/&¢w~ŽúÛ°0£a6·ÈZ6 ³Q2‚Íäzw³» ¢Muå ã–ñ2Ý‚Ô6(GW”O¦_˜|ÐA4Q *0ÈÆ¹*Bðôs|iKضSp//·­¬¤±G’‹'{I¢;Ý©²¿K©Þxu [§Z½z©¨ZÝMJÎÛYâO?/“z+ä9çO¿w®°=MM ÈŽ8ûtîÊœ„dêÂÑÁƒ‹?ÞèLC+—R¸×Œ"·ÇÃá¡CËúêEõúsf½Í—'=°-GIUÑ4)(·(ElgI\ýØÌÏGVŒDb çJ&DÚìu̲3nó•„ì9Yn¢èÃì…Eô¦‡ÐLCˆö¤j« aò‰®`H‡`›ƒ)ô w»;^ƒ¾Ø_ήcq`7WÈ¿y˾ހ=•ÿáËñaþÖqÊI»AÐn0UïÊœýu¡™ÉŽò¤²e’m$5®6>‚-å?c§›Š “bËtcne¶ É[÷ÙÆV¹§'½¡{Ófï cíÑì›g o~Äolë¼£ÒÝW̤÷ÞÕÌ721€»æÜŽÒ;÷ºLæ= }âæŠ³`Ò<ÎV–z~y¯“4¡ã"PjX¥g­r1ËÊvðF¦sˆdȆŠÎ&°ù}«¯nÔ†QpôŽšìžµe¨­_aœ˜ ;Áÿ\öü!ëN»úÙJûÆ5ÞïìðíâûŸä‡7Ù–[^¶j»—'»òs†q,{=ý€ÛË€‹”)MÃOìÊuq#j’8õúY Ê®¤ûÓFØ ¢‡“@§PˆMf¡º^XöÔ]\HzužJme À¬h”h#ÜS°/]ˆ)÷]Os†;9£Ù¡Ý̰üÆ[Ió.ï=1`S{k+bòºü{—Lv…2чù¯¿dfà$å'Šök/gÓ÷mÓJ‰Nßzâ’hLÑZĆsäoݹ’íÛV.ÖŠÎ<í~qñn"uö`ïîþá…ot åü<XOB—R!' hË~ýYùòcq;5îZžÃ6=%y¯D‘­õ Bu‹·«…™/ôƒ‡Yù¨Dè"|18ý½vºjïõøf’í>ênaóѧÁæ‚ðz³±Qo±Çä¥UnÍ”“ ½¦´eò.Ô¸Þ³6â±M¨dj‰ì>Ø,qusÕÿ·ïˆk[rg¥ú/¿Ÿ#¿yˆf›5µÚ¥Áµõ{Èb|< ¡Æ„©ô?!ÕM“4µLˆ´´ñ‰µ-ð“”v‘ÈI½‹D¬¤ õ¶z{Š­mä‡zÙTlßE{‡y'¡ PŽªož´ß½"¯®È‚ ‰T'vWµ ßý£Z0 d<±àÛ‚;€ÔÈ€{gUÎF¢—ðÉç­û*©¥¨pÒøˆ]èQ¬ÇŠ̉ Ø( `#þž*× Ÿ…XaƒŒ•3½[ªsÚO¹†¿Æ^]GSî8ÿâÅô™£ên£÷êbvgJŽWÊûò±òàî1¼– 7´å²…>Ÿ’ÔªZ*¤ôó@XëÔ.h¦4NL)i§-%vïPV†Êƒ/’=9ÑD”ø³óD%mª«©J ηšÉÒ|©ŽÑÜ¢,>ºÊhTt•ÇéÙsèÅG”’û˹"ÉRd¤í!Ãí&çÖ–†wEþp/ιÛk±º`ú¾þ晨;·Yy7Óä? ë#Ý_1üèéS­–jvX¹al嬘%q‚k Î ïºB:±K¹43w6Ê8F½ÔÄm”èüœ³Æ´äDh‚6m} Å“ŒAÔ  *Vêx 2Ñ>Œº9§f/€cB{v«§&ÎÄ«»å?|I³ß¹ËF†`ÏPß·ßMbkWÆbÀôÑ~‹JùΤ­lÇêVïñVY´VWÿæuò­³L |u u#™ÓÊ¥$DŠh,•xÆv †­I¼¥¼5m˜Fà¼"îb×U6g@‚g"¼{]É`V;6áù_;¡.Ξ=yÜvÓÞOæÛïÍÀ"ÊE¢e­ÕÌ¢d;Oì¿<×^j _$‘éQD(îÊTJk¤ÏyñùìÕÇÕ{n˜fkÛÙô-èé·‚q55S-Œv*'èç7Bmy Ü3'³¢^4:Ɔö»ix怒*'ª±¯L™âóÏDÍ¥$ Ãþ`ÒœÉsP\d®1/_ÚÃîgû›xˆÓ|ëùœÕµ´@ÿ¸xì"ítÃù¶Y÷ô‰3åž±¨2Èîô>÷*ì—âÓΑ Ǽõ›Ÿ%•òK›NÅ ŒµÆõŒjÚnZÉûÍÙè[_Êï®OµÑò¼Ü²µ¿/7z`q~³“¿ðt<ªG×µ¶rSû…Ò&‹:®¥ÛˆÀˆ"^AþäµÀ"xfÃkê,–¥R¡’du¥2OQàìiòøYiŸð®-°OÞ“-éAAjmhéâ>»ÜƒwœrÔ‘[ÝD^Î4(]Xí4/^Rû³‘¹ÜýŸ]¿o—÷O^õ^{¢U[•µÐ[Š¢•6º³˜¸ž hav¼½\–Aít\eàFq@ê& ô$±'°~!vjŸ»$ŽžFK+•‘(¿)k™ Œ@˜[ZqûÑ úÈ™ñ·n·F¼f<¬%½…N‘ˆH¨=U'ŒÕtÀ~!iÅÒ"ޱh³Å¾rvdgo<7Co.M…‡,"3Rê ÔSæ/|÷º|yR>žZ¶EOÓ`[È@9c­ˆ«ô¨K¥Ò•IP×ПϰcH½P`Ô¨j&mË…Ù5ïþ¼¼}_?{¾:ºËÛyZǽìÏß­  H˼#VÐfq,õ`5ö‘ž—Ÿ—Ã…´`z>ºõ„ œÈ˜ŸÆ¦šìwãGNÊF¦ïÜ0)³š:Tƒj’A¦#Û.?Î~õlnþ.Fxr˜Û@ÇGؘéüYÖ}ØßQÜßZ™EµwŠs¶›XX϶Ο£íïŽ V§â—_-–ŠþQ•ëÈíÖíl¬ZkLð[õ¥E{»+”e«ÀYívggy7å‚U,««;çyÞ4¶¯:v´I(¨¶&Ã?x½¼¨>Ý1˳tÓMü½¥±#‹Ó‚ Ë×Þ£Ïñ=hÏÊÛ«· PÜÒÍ•¦M,ê •Ó©£Í°†?ýŠT¬©%{CÆ÷£ÀÏXÃhîb_¦ìÈ¡ìâ„Ç÷æíOßÓÛ ¨ s ´÷±#ºXÍví"¹¡z3Cm Iè#¤*¬µàñKêàÑddÍèõWæÓû]{ð¢ÿÚÖ¦î¦x+Ö[mzg%Îåi—Û šî—öIìì`PRe\+$àvc C€ž¤în0OeÅH«£OfÇ.¸k³~5ëi©m£U&¥³°f•3èâYÁ¡÷í|¨·;þµ¤Z¬—,1ØU†D¢ëKl$—ú¹°•(¢míY»øøÐÞ~µ8‹®-!eI®HuÑ¿ßzækd¯Ÿ®.’cÜq9?Gr[2khQ;%ˆiãpÐ âè,×ml~-­ˆØÈcR¢#µu’8DÓ½{6û*Óóîô"¿ó@_z¤<¼‡ì9—@oú·c¦s L¿“8Kt*A÷–s§|ái/£œÊ}|‹6 Dš˜ùi¢+…Ǿž?.;2wý2cÌj(¡”ì)÷…‘%PŠQðôqë• tá`‹û’ØÚ '' Ÿ’¸0ÿ3?ä=;Ç«;¢¥yE‰½sˆŸ?ßéD0³6 N9OïN‡†ûg&£W^éï˵F†‘?0îì…ªl¬[µ“Ú'^se4ºÆ¸>ýË:\0‚"ªQtgžÚº† DJvâ@, ìÄø=w–ãå͉]îÚk];—Ûµ£íÙdÇnoé*»ôXøÜSèçÿaæ P}3Ú¹»rymÓ°¥*mWí¾?üjvt¢½Ýî5n¤mAÔ­SË£l­•”ÝNùv‹üèWï°c™u„.77lülpzacìùwþHüú ˜_@r³äô$¬¾¨[ieèÞÆÖ7Oêï¼WósX´m[úÓ›Åïü8/jÝn±^äi."»®RóSÞÓtež¶K@´T "À±B!×tú*…Éàx1?ˆš>{ñ•å+¿ª •Þ/Ün=u\!1?›³ïâíõ-ÃTú®ÔNúél÷þÃïmßèf–†œÿí+…Þ]Ù¿þ…þìNs|´ª…þ·Ÿ4«ÃäΜ `!!­UÁ†ÇuïøHzþÙ¬YÊ‚áÐÀÌíÍÇ y+ebeµµêc$€ÖAnÇ/€«…’`± %ïÜÐobĘô)wî ^Ðê0Xêþ—_z ~ÿ ¸|Òâ ßÝ›Rn±Ð³ûwŒo¾øšž¿Ë>ÿ5GG'¾±bJlÛ,D>2Èd7o3Ùï¾l…(<Á6v¥‘q·f»V }Ž›%×;º³ó§\ùöj;JVS%pìÈ\ÿâæÚæËHS·§_ø¿|Óýþ»¹jïH~{ð¥îÂÁ>Ùa}}î;WD3c^ÏØ›o®•ÜB»ÕÅš 7h[áÄ*»3_Ò"Ë”‘‚Q£E,›V ¶J(ncäz8ñs`QŠƒÄ¸•›‹li³ttÜ[{­iüÝ£Ì÷ñŽ}…Åkígµžyx}*úñ/Ûݤ ð®WŒ*ë –¾?ÒZ_Í=]û»Ë\ynÎø>ŠlÞ'ÿìU`¾ô—µÛÝØfž…ÄŸ=WÞÛùŸi¾¸UïLÿùo[ŒÂíI­1B2MµÊŠ>¹( ¹öüëm]dˆ;T˜ÿ"zÂ…÷²¨m  æcK® ÝçI \Á¦ ÚÂ"vœwïË·?ç%L:®cý¼\Îb!:öŸ}{õ•GÈŸ< ¿¹…¹/Z­º¨Ä¨uGúgžy9Ù^J®ý¯Û=Õêî¯7dÂm'ë ˜ìæm*ýÖ«vDz”l¬Se:j7Öl»„•Íi·¯Ò{rÿ6ù½¾oÿ¢ÕVÖ¶’L†™Ê ïSÝu±Ãµm‘Ý»:}é¿!6ߟTœ¡@¾NN”q–•‹å__·d;ß;ôÖ[ë½vÐiÆ¢mÖÆ¼ÃÀ(‚”î^›ud±#RU¦/€"õË¢Bäs )uš¨(ršÕMøÔ|69ÃÞ¾/´eÜ.¯Ï´ÃnoMê‘¢ó7Ÿ6šñ02­õÞE&FψbÏNX[ÊÓGüÇ/ÚóÍÆZÎm_¿B{m’” …‚Q*TluÈå›&X›péP¦‚À‘>fží—­>vmýT ?œVC#…çžIsãÞý…¬Ç®KG$áY' Íçr¿zȹ"`å÷¬ÖÛ.*ÕÆ†Ôãgé…•ë ³ÔöóJª†až­ú-ë¥ZZKJl‚Obw-´4š`8&q‡¢½ç²CCÕ0Y“!u7Zg(‰¥Ú4XÆ…Œ®l§Ñ“–ßmu4x'÷Û/žøï/$ËmÙ誼_9Y(G3­âƒ9E!;jÅ‹Û2꺘`€zݶÙN4ÔkŽ™È•yoÏÊ€Ã0k`dü¼öç©bˆ|¾°Cf3yë½8@}×%2ÃÅÒ—wöÅ3,C€‹µ-žæ©dÊ- Åïm’¹yw{-“µp?䙯»Œ‚/¿ö»½_»”µWèä/ój¶ÚõBÿâ–VŒ!ê2U@$1!Üž\Ú6í0Î2Ë3D€ÔÒÀˆd¡ ¢æbþîlëð¹Þo/×ìDŠ˜ž;/J¾˜½”úfC#èø€µ]¨¨†ûÅGÑýä“™ìÝ/ؽûÉÌ2¯5Ò$Â­Ž–LFœi"AµÀ³%bªhùE|ÊY¦ABÅÕìºçy—ÖHÀR ¦*‹½Z;‹R59—Î̉_ßêÌ·eÔέN¶:rMÉÑ2ý“KOÒ¨k¶ÖËëŒ œ4åº|Ÿb¢…îðÎ?Už»½ÆÂk,¹ÿ™ÈnM%”H—`KˆQݶ}å†é†YHC 6Å¢oH×±í<"V÷*X¬ÁÀHîâé´÷@ÿ½eÓÀ²Õòx¦}õAõW“Y¦=°(‰´àþz³“³Æ Í¡ñèEçÂÒLÝåIjå}‘é-™=”?µ%„ Ä&ørWQj¤áZa G¤–>ÏNV“ŒG)mfd½sÌî튤 B壸ÃÉê¦jo‚¤…°ÈÜM¿tL¨¬øñœYnñF‚[ù¨?6˜N6èƒY«Û %%I­ÕE­ë5€@+zø+ŽGEØÚL @Îè·’©NcVV9þˆ:„‚Äž–gqe#®©Í)¢xJ&KÖ»13F;¶c$ãÄ|óïÈ”EYÑÑ1\îvÚ5JBŠÑÉU2¹@gkšmÅ kIm<ùâëÖィÒzþÊ÷§'ÑV¾giÛ(žaìfªˆ|.p1Ü›^hlE©H$ɼ ;Bs4›\œ¶Ðjz¾MÜ5#G)»kaÂ-,UY©l©dPt’ñŠøæKxÏpïêjÃÍ¡Øðº{†Jûzdün%f|WåñÇš²ÜÛˆëGwÁýËùwï%7FW>¥_Ì1ÞÉÜ®.BÉ ²Œ@SÅ`rx“Ûܯwƒµ›ZóÙfql#–af"Ë*K•I« TÛ†BJᙡºÒÖZµÆRÞ< t4OÕº!µ[ص‘HI]BÚ&&±Ÿ§žîš8jFpcFN݆Åm¾²ºnùƒéÃÍèܹ·ž Í–¿v&HÊ,·×鸾ɌÒU»R4¾gÕç•ÒãçñÒ¢ÚŒuCY £8`Û¢ØÑ&pâ×^È«²®WV'Nõ|z¾ÿvˆ+¸8µ¿ò§_v/‡da«Ý ¼‡æWÏ=;þú |h0îúmª0›ÿ»E¶ü?~ÌúÚ¹ÁÏ'[Q¢\)­ Hj€>Gs'%6<}—;a™9Åë‡~=ª_AxMŒùn¾›x«ntÈyiWuÀµÒ¶ˆ¥’Ò$…\¦ÜT¦6ÍÓJ-¹œZþjŒ§6½˜a…™` (¦rHÒnÁV;„z\ÃcÚ Uö††°ŒÉÅ(¶£ùšnMÉf¿µ½íÙ pN8n£,’fŸg5Á³I¯pE€!H=À?x¶º'?›³®?ìõËŠã[Hí­ N”Îz/Ì£¡¡ÙÙÚãTt¸¤Ynoñïÿ!ó!¸7ÓF]~(ÖÛöã%:ÑÉíôNUŸßÄ[Ý”Y uI©l¡”—³Ò±"|ý²g¤wuQ9"ïà4R¦ bb ¸³E÷ôN¢"æLì-Ÿ>¿ ÕÑz¼ql'ºuÝþàNrë.ÿô2¾5£ÓVꆲ”ºÀ\±,­¼¶-ë)¿¼Î[m#…/¢Óµu–anËí*!VSmL ÌpQÚâʈ€1‹˪åqmR) U‰“†iC¡ŒIÚq;mídÄÒ(B¸CJ‘Ö–‘CDd”%‘³ÔÊî-ÑËWE’z¥‚¶ìTŒùÍ×ë)U§^tïÝ‹·š•ÌÕH&‡XO¾è÷›Å¼sí®·Üa‘$Êa9ãhíg(ò:ðècDzÞArmZ~þ^4_wcÛ™po¨Ÿ?u =€T¬àêš&@«îηoܨ‹ûa-ÍûûêÔd<îùŸ¾Ï—Ûò[ÚßxÔÖö†|8Õ5ÆŽP©n©HìÕQ“SH#?S¬“¤‡7ƒÑÒL£¼É*Röä#¬>ÍLÑd-cò|a? ön¥¨£3‚¨R ÎaÅ3'¯X*,m”Ãm(7ÒŒ9Å œzÚQzñ—œAŽc'ÊÕ“yh´+Íš”Ô'ZseÕE¸¶ò; ´FYAÈ!bµ‘@•ˆ) µmÁOŠuÙeåÑòñ=›»{MFÈåeuo ŸßØ^³®Ã/ÞtjŸ·~~/½3Ë*”Œ(üÑ“=ø|\qÃÛ‹j£é4ãTær†X¼Óuz‚Ç/¤.5ܳê\µ…tˆm–‘2#ÒÊçOhEÛ}‚LÀÜfÙ½%¨Ž÷Ôžzº°¾טÎ.û§²Í5^[«ÎÌ¢ß\g×–Äv3&‰Cp–³¨”xô¡vZŒ1·§e¢Èa³ í¤¢m¹é—ÒÆ/íÔbŠe.öD”RZ"šØ ´Ã´©è€Åª´Ì $hÐyפ­,á(öÒ¶Ö)qÃ(í*·c“Dë€X}È0#å¬4ãÉUóÙu ¢šÏÛŽˆa¬P£jqSÀ(Ý}ÑÝx˜n×Ë`S•µŽìƒçžóÊíŠ wnxk1ïh…l•“>7X´à;¾ëž9Ùª Û[ÎG¿ìÌ®ò¨àò(u‘38Ο8Ø9·'W²œk«6Ôc²[séõ[-ÿAÜÎ ¹=1i–yÿÏÃL›¿~2ÿú£]d·½bïÔCF è ² t”f‡•%˜i­w€Ç4kâ8ªð¦»ÓYØìß0=Ø”q åÞ—¼¢TMW‚Ÿ˜¤‡ ÞÏU€ A$Ó §)£˜ÙIYBµDKcÁ…2ì`«’§“€ Ã^öLlž@Ô§<ÍÙ7›D!e*ƒô˜SÌ©4_Ϻ[ºYä=!t´§HÓ®’‘ ±web݃_ð  Ñq éKäO©éó¸T—çåìTåÂn┺ë¢ûɯñò§ñ7ÚfâžT· ßòàOùãR:nÔí²°J"ŽYàÕ6µ±ßãŸ;Õµlõá=¼ÍdSÙ¶á(-8Qt´š?}„a¯;p‡i²²¥C'¨¨ÞÑêöÓÏ›j;Kó§úÝ3õuÑX–7—ݯ²; ÞZ;±cJµt-i´µÎ:æ]e·y”¡6¤]«k˜+¬4Qò°Å{5¡•sX–œsDòR†ÄÖRq†«ÀŒÐF:ØMd Ž¢¦‰›|€2å)!‚€˜ ¤ Ò6ò STft‰É˺"؉…rAV1±Abi1ûø†·¸VÇéΓީG¨ïÉͺZZH{mùÍg{wõg? ¦nád‚ñ4Û^Bd, ’dÊIŠö;&äËúöÒ©9d´F¾ÖÕIŒÄ#‡‰ÌìO>Ó¥²8so5ñVWU±N•'K$Ï–íòÿðÃüz˜~é@þo¿˜1`ÀhSút®Ó*oѹM/ ,=(ìÈäf-Ò©f;/СG}6UßÕFÓnåçX®e¢×Î= \JP`ípä *^c,±r{å5r²’Cf(a\"®¹ñÜ!#"iÀ ¹´Ü^Ê‹¢òNèÊ.h ð~f»ºŠÌç\oÙ+ÙCȤOpësÆ>°-„¼£BèRkÏWsn–bÓÊ[Í»T! ¿°¡Îúó^›h¸¾~<(»Xqa/n×ÐõU÷òlÿ±ÝÑPQ}þEa)J*¨Z¦.Ó‘qúµ—]ÅÅÝÛ 458¸ú0NÁisT 2WÒéåôî}°]g­Ix c’°4'½`nïðV¹xç}ùÎÇÖêBâA ±4÷‡FmlR»i´²…Ô ŒÂ@#4R kÂv¥qÎ(ÖˆõX„Ã!’¸4Í<‡r¡ÀP.É+)°0€ÁR»±dûŠñPæz“\ e)ÛÅ€•Îc8:rMEɶh„;àëÌs 7J`ÐÓ2&6°ca{ÐNÃ6LÍˆë·ØfSh«ÐMmÁýðØ©oÈm³1•.‡~RF ›–eÙ±“/Šb.K+ÎtýzÂ4ŒŽXê!À®ÝnósåÏdÑ&ÆÝ§NF˜µ^ÛDMaDþåo—Ö³èâ÷o?í~1Õyó&ü§+è{Ÿ· )ú9–fÌ5f«÷ùÄN'š2ÌL°þÓ쉣f×a³t×HK¹oÉh¬ÌÈšÔ)ÍK#ö¤%'E¶åâY¡¶x†î:îyªq@ø§œà1ŒÆ’æN7Ø“™]BŸ´‚ã¬ýX)wØÎÓ¢¼µãÕ 7Âãy±nÈêÚ,µ¡#-E1A(X t 9m•í;fÚ-˜sgÅ®^#ú³–æk]ÓkÙWÍÞë¹ÄOãLÆ¥¼ÕiV~>ÕygŽm5MÒ‘Ï+l…æáööœè—盉(`‘6σßyÆo7ƒµ_¶ ë<Œ‹|(\Z”"3%SeR…B0–vï>TÕy‰ìŒá¸àh/ò4ƒعçiØ¡…súùøÉ]ìa­ÐÓKSîÿæ£ð7ï'““‚µuA3NƒØÐ¦R 0]£S €´ö2vÁ½tÎZIÚE®%B®E-­=àWrñÌj`èéÏvïÑ …ùÈž½'n]¦kÛ;r¦›Adú#ÈB-’`A@`bRÆp((àØFRde`c¯ÐÆ™MÓ D׌ QõTu0îŽP¾àˆB¢Ú¶â<øÄQsq?92U¿[ë²Ã ÊY¦ššcB|÷@e£“vuìcIJ‘H”íå Ò¤ S¤”eÙJqòFkC-ޱ@ ‰áBa€éÁØD40ãf­0ûÀÞhÅÁ0;¼ÇôPÚ]fK-µaCÿaáøù›“¬©¹E² ‰ˆ4{Äk¯å‘çÌ­i®PqeœÔX M ’pfOowmë@†2‰ã2;}œÈMm…k*&¼ÀåÂjº$=äèï\fïOZ“+'¹§©³GåµÛø(¯ƒ”‰¨U¤ñÜ\þ’¹x Ùœ¬À'ë¡/ˆùÜ(³!TØÇNY§  ‰±ªÀ-PjÓc§½#ýb÷·=–_»Õà¦X¬.8i?Õyä‚Äé† w}­ÿÑÓlwÀ=\˜½/#-æ46Âh0‰±‹Ê“Ù×â®m„À`ökTZ÷Ûé‘qßT#&ê©_‡mMÞÒk–rs º––¼øõór× 35ÅîÕòŸ­’7n´%L:±È¶f›„Kž7­Ðì>b~ç„ÍÕþ8œÙLMÇ’±nQ¥Šxâ±ãê±Cšü÷¿‹öþéäÏ7KÏû0Ðü=éÍ'ŸÊU]UsB7 ˜£(Š¢d%k$[Ö(Œfµ³3ã½ì±×^{Ǿd[c[–=’HÁ,’ @DÎCu¨®O|Þôäý0{í'Ïý7Ü{ó³Çü|¬µŒè!=3¥:¡­­+M™äA¾wTÍû®  ­:}ðŠˆZ…Á !lµ“!ÅÙ—,áŽR¹C¹ƒm’éÖ¦|í"Ä¥éSÒ›üI¾ïÝÞ©ÞØèäà—”?V><ñ´Ú?•.\µó+¨ƒ­Ö†i_ ¤‰ñ(¸}üA¼ôFK…ûèäiçõKö{ßÍ5T-¹IŠ.…šÐBÉF*‡BÿôöK¢ðD°wDýûŸ2·îÝUºÓê­( ç±GX÷ºÊ¦‹¾“Îo±æe’;”wˆ)h£| d§ ìᚣˆÜã‘{¤É¹Ç`¸–&žþå¦ß†y}/ímÉlÔ€øºÎ¹Ë¢ÝR¥Yö`è¤ÉÅ gç*Ý+E×AMË©¤õÍI ‹J†`(Ìô.Æ™2¸)|˜Ö¾¯îl•ÛßHÛ\ýÐÑ!*‚ìq,™õc‘̯Ú?ú$ý©hÏ$C ³¸´ÑéE’Ï@`N˜ž(øÔ©õWzs— mÁföû*»“fO:SÞù븲‡±µ[¥¨Ñ`Š Ÿ-=toâ˜.yÝí|:ä€#»F÷Ÿîå%]9jËìå·£¿ü‰n-e*C‡N{ÚvdÔ·4ó’Tq †‚¥ˆiÁ„¨5¦h‘[ÊÓ\b‚¢Ðã™d†FüðÄë¦ZqPH)kZ‹í„&Z«5;»ÊzЇÈßø‚wîhïØ.²wîËÏ ²~²Ùõj†Ô®]ºSÒt}à-\l<«÷ŽxûGfñ SJ!3ÊH#‹®)Hšá!cµƒ<ݱln1x¬œ\»ÆŠ8A*ËLoǼxÁð¸º÷„dÓ›”{NÐFyn±»¸(JCåü'éS‡CSÙÝkèö’j!®xÖ‘Ö¢"Ç ÿÔ½Ì÷Å•–¥œÉÓÞ[çå¿Å·×¡0:\vD›8T‡M"­ÚJt™Nœ9œþâÙà·!Ç÷¿ý± qßdåÎv—Y…qxÃã3‰ nÃ`2,ÙÍUܹŽiÞ |@!ÅVJíƒMP~Ì…˜hÄ"»jÖA÷s«È#“å4¥Î¯·GZlÙ«üeÖÞRéaáG‚¿ÄS懭îäíÙC¾ËÅ­hkŽî2y? }-CͬFYŸÕpL`‘ÀÆ2=ãÃD&ÆÀ´­#‡m}H_]vûÏ%N¾C²¹FÆ™Õí®¤i{u3ú½©/Þëï!X“ÍvÉ|ÒXã8™ãÒ¢dn¼ÏšOB]“-ehö »kÆùàZ·o݃1Ä*‰*8=Z|èñè0F:2N|(ŠáÀ®¡cgz³£‡¡:é¾ð~éß¿ˆšwc™*ß•dO£ŽÄ‹R&S“0 ,CL)ôÿÿYãl&#ežrÒñ‚<0Q÷=:Ç’ CÊ;¦dù2̬°®càá}ð_(ܬy| ȧï1D£ML;7V¡©$Uƒ}®‰ »hÙ6e5; þþ—JÏœçöËÏž©OŽÉ< ×¶ ÚD‘ëÌpyŠ=°!&Êh †Z@ÄÖwI.Œ5 ‹CbÀê’ 6dŠHoi³ý†“R÷ð >9RØî'¯Þ3PyâÑÎã÷…­wôí—Òj}tµÙ[XS®$B  š¥–(Gꀪ‡HϽcÕ[)¼þóÞ;×¥Ï5Ü©ÁŸ|©´ÖR«Û µPwF ñ[ŸE¿vˆÔƒ8*fÿŸçéµnò»_ûúpMlwŠ`c@ä¨ÃrX/dÉáÚâK½á®ãzf„ë)S¢Úï‚оS°ê7lé.â=ÃhÁ;’âGU°×ä¢}jjR¿=ç×^“œ•ž3ýÔu·‹Äfè–Åó ‚.£l¯[.­‹¥š3³Ën-úf‰í³¦~¢eZð@ÒƒJɯ0))h8kJ(2cdê"WÐõ^&÷t¾™Åiù¸‡-#„¥‡÷›ÿᓬ^,¼8·ºþ“§ºC$ùÌ~wd–,.ˆ![P:Ž:²ýÞg†Þ]l鮀ººÈWîVùteöiþÈ>>0ýw/å=nS¦[¢ €®;Ô3z´”V`úí¿îÚ–|ìéÒp-ï,š¾„#'fQW‘÷æäk/³µ ÎPÝXY·­½M›Å¤Öj¤µ \dµ€A`°í²ökœb|›Ñ3äkO8¿óøøñƒOÜç—U&Wš*H9ìg ÃUÛ¸j_ ÿ7'5g€’Rs®©!%:ø??ïHNDŸk{È^FfÇ+2#ÚMçsÞ³gãégÎLN¨T:Ë›XcB2)í)"< !mŒÀÖ„5aÖ÷ Ï,…EŠ §@Ûˆ ©²ÊÝÚ\¿á$È=°˜¨´{ñë×ø$)<ñHï‰û£Ö{ùÝŸ«Zuf¥¹3¿fˆÏ2i(P…8´r˜8{rp_”®,ôÍ/õÞ¼©9 <ɽHüÉW*k »Öh{†"ßeÁo}FþúQ˜â°”ýÙϼ+›Ùï>VýÚ£âºèöËR«ÑM¤Ï¨]Ù­n|xhñ•ÁH‡§F…ÙeKžòû ŒË"п¡‹«Lî€Þ”<¬ƒ#6o»Eº[ÕvË÷îÃWÕßÊ;"ÒÀ5)tLt±L¤5K&=ÍüÒ¦¸Y÷Ç'Lw•å °r°©I8VãÝF|E—¯¸9\çéU¸v—zýn`.Îó­yËfFÆuî?&bÝ|ç ¸0H!{%¢}cǪñ™~çoú¶¥y²6:”öVXSè‘§w{­„~x›¾úг²6À¸è›Déš°aQI‰-€-­ï «™d €õÁN`˜´æhŒí´*é<91Cå‰Êo?^9~hû‰ÓèC™Õ†ØHUócŠá2ê \ØSßý¤7ê´±b’kòÔ‰9b¨ Kcµ×ÞÐ$*íÉ•\ZœþÂãð…ÇÊU0ª#°qDÒÙE¬´–P¦X6ò¬çŒ*ɨ‰ é#+À(ÖPÏ­GqÙõ˜Fz EFy”)Ž(€ôV·’¹ë|qζˆ¨L¿ó4;uÔ{ó[ƒÉM¨Y}£‡ÑXammñ­0Ï0ˆ¸3biÖÇg£Þüí‹êî-IѰ¶M‰cññ!çþ“íS{LÊÜùMLE!zm%çµ½ä?½L~r¡pv<ûõGq*ôá“zi!Ú¤YŸz:Ýj"ômª{|¿¥ «ÚÆ<ÇÄ¢BÒŠTš “–c…郔‚·™sÙWe­B“ÛcÒAž×=$‡vPzY* eǽ$²I¦(*•ß h·©¼·Ö..6å®gëØ~Û—=i.9Ö=ìmá|˜PŠ€Ý¢lŽÅ§ZO[²–«dŽ®Åƒï†qˆ|­…5öÐhéï}5wr8P—‹[ìÍÛ¡bøðIu}Kÿõ MÍÓ<ˆž|„ýêc"ô+óµ[ÍlÅ–”É -/ª›—eÞP/.̇×¹vŒït¨…ªDÌžÝïo\oÍvU±GînÀ'?=uzŸj2/ïço¾Î_y[.o€Õ%·i¸-aûÀ-6غԔ¨µ«¸ ¬2ʉS4BÉAÐGŒ Ñ­í˜:1ù}{ù/¦:;ÒÕÝÒeŸd§OGN_^Ì U\ÃTyN+.Éï|¡t¸6H3¬'$Œø!äy-Ò¥±òkïI h•Znv•S½_ø¨úÂca€jEÎ7ƧìáCýFo½‰Œª”mr.$cÜ8Ä©ÓËAK04 e”kMè: S›(•‚Éq­vÊ]k$s×ÄÝ[f<÷þîÓöäÑâ{ßͦ6TMÃå ã¥àùÀZë;eÉ*Ö¸aiì åõÞw–ܼ…‘T- âRå¨oÞ{˜+ÏŸ[‹Pû\]OÊu=º·ð×oðï¿çŸ&¿úP.,?xÄ®/Õ¶“žV¶>tõT§W4á°G£ŽÖ]kŸóÕ-À©á™¶Üà›9¥+s.Z”\rdYkOeê¯ØÊ›ßoíõ”d×RÎónìÛ-—ñ„3‚âÇ©˜Q•++݉ÝõyÜDWò¶…o‚êÒ1'"6°A¡­ÌÀ Üؘë,«2K=jI˲ÖEÙHòq—ºX*µoÔÿý_Ö(ÎOL¸7ÌÛËGôøYscCÿõO9˘=îO=ìÿê#1!±& 4—¾ÕFƒ‘†bsDÛ!ÝÊiËÔÁ ÎÍŠ¯}~d÷hWt;X–ÑÀx$;}º@¢øòBk(»šêê ©¤$¿ý…Ê‘Ú çXÓR#R¿Lƒ J«œdŽë¡¹e§§Žow2Ý5þýûüßx´Äl«ÃEeÌÏi¦ƒ¨çÃá`¶^¹|“w -{¢’åÀ††U„ÖGàXcŒŒ©ÖZö´6Ø!††1G±+vl±Lh¥JÃ|‚nv 5À»vŵŠ]^|Ãì4IH÷ý…6Ðò­¡\T@xª›³·ò››y"UH2ÊÈ@Õ…v\4øÈ …Á…·òéagj/m™$Á:×ï,CÒðrSòœü£¯F!Ž×3ÿî<º8?èó€*Åí|Sƒ|F=qÞRFXj‰öVÆÙ”9Âö”+Y`p_Ë×”RE|û¶Ü»Es«µA!+­KS44“|àX„£ÌGqqF[ÁôTnk ìn¢åÈ\ÍQ¨\Æe)ºl€"Ã1¤§ 2:jØÎ+Vsþã"² jµ¤‡ì®(2(+ê©QûÂu¶ÐH¡QûÆ[¹l.±>"g†.+,i5`jyàyKf5ÖÚC¾”jZxظ k(jSèIgÅÃmŒÆÝþßý¤7^í4:Ö)WMØ ª¬Ù—Uª MnµÜ•MÌ]½)åôpô‰{4áhà©æZpñëfí"§RMQBƒÍ-;í8ažéÝRÅÓ“Þo>Yb¶•XRv§KÜÚ ý}CÞ›yK¡ºƒka 6Œ^µ(Á`|ƒÖŠkpY)ÀD‰®Qư,Ê%K±£ ŽGk63nÇv¾EÍLÆõ][²É¦BÖã˜;÷ïvÅŠ! ‘yô¯zݺÅ–uOö$s˜5¥C{÷Þ›Š£ï½OT¼Ùý|m}¨÷d7‚îjð·7©¼?ý¼Îo5ìêRýýÛÝvîBM–êÛE<™Êýµ­¨ o‡¡7”’–hª=Œµu¶ WØ#L9Ú)ÖÓj6ÂC†ñ‚Ù¹®êÛFƒö±WðëwòÌ RåJDÖ—rü)nÀ¸D7™«I´A6BtQ @;çk*Ãe#©JHNlnlf¯Ì(h3áæ*vÉ·‘²¦žÍs‹ ÒΘ’€ß?[ùÛ‹ùjרmxîme: p<ûô#d·ç.q[%I¯­pn(Ö$p ñm–›µM}㎈ûv4Ì2!A2KK-R¶¥zÇ÷¨Çb•eF“i<}@5’ìÆMÿýÛÞf*\¡Bªû4Z‘*%º+°r $‰´t ’ç†#-|d(…Áb •¥©ô^ñÊ-ÄÇÝþo¢2^ml÷+‚ß *´ÑE*Nmuý•mEµo=]úø)E¤HBÓXw?ø+L¾ä¨»-wò,Ayî¸ü­kùF vM(qÿs÷;' ,Á¦ß~¥7÷ND­™ l›×‹ãsÝöR'¯æú8À‚ÜVfÛPÀdȧ³Uo¸êx>êäÔ@&P¦XL¦¥oE¦ É:òDP˜YAf¢¿<¦Ûñ±ÇËÝ Ðõ“s²þ†¸Ö@-åQj‡„qàäþè¡§%­xwn÷s  ÐÊY¬r&È tV?Ušÿ ®.Å›shïƒøÀ 5w „5CYx³AvÒðwŸìÏŒËo¼ã~ã%òâÔõœ‘ݶ½Ãæ;6g·°qôÞ=¶]Öjݳ=íp‹d ¦ âКŠc´Séù”¡Ø/t܃›2eð_\þ¶”§;$Ϩ¬¼H2…¨ÆòŸZqÍá3 ¦çlwæ®)=ÀŽñ¢)“åFÌ‘.Þ!š(´‹8“VTZbx×ìÿé Üu(BFYì=b8‡ç/ö¯Ï—7{øØ¬,Š·®G½VVOüÍ#ÇýÊWqÍ‹ß2å}qÞqΔ×.ÅeY6íZhØ(a˜A®9œyØü#§Ì¦9Q²OUOŸ™3Cù=©Û}ffk{0¯¾ þ÷—Bp( o÷]M%=òÌbó>ôµâˆ|EË–Ä.Q(Æš¿líÕ¢š!ÆÛÖçÛÑ,÷€äsF¬¡^0&yÇ9Ä.¶¬ &›±zŸ\;—ÙÞÈ-W–-h‹”1îî#Lrýâ¥ôÒm´“f{‡åk—jÝ­¼–’˜¨‘¯|Uølù9[nŠk‹%çpaåê€W±A"ìŽ`2pŒÕ–›S²Ç£T)ÓeHʱ]Ž|y¦.O=hïö<´·°÷!úÆËñ_¾Äò6¯ QAf‡ ¥'UAˆH>’ …IâÁtMV½šOʼn¢™Â( Â)-nÊ´çä'¦á™Ãu4è…~uanðáO‚Õu9µg§­PöD¼9×ÍÍp[äáñ?™J«U.þÈ™NúdÒÔÇŽ¤ûF™«EÂJ/ÍñN…t`5€ >}&)¶ÀöFoëåòÉn÷ü¶œ=Ìc %‡wzòò¢[5z„¯ºiK¢rÈž>Ë÷‘ñO>08yH}ä;9Í×›¥^_ZD*Ìè”RÆ”âÈjq.TÞ·DYˆ0!˜_Ü wæñáýü‘s¼T*¿{›¯oTÝŽò{X~ì™.Ó‹ïx·{©uL"8"Â3en¼ˆöª¾Ý}”Ð+ƒifI´[}øÞþ©£3Üìp£=L«v0°Þ7^4²•ß¾'yüéÊ«ïô‡*úÛ}åƒP$X,µW°B°7‡šu:ÔžÅaæsÄ0E0§Ѯ1ÜäF~ÜÀ¬1× E¼¯·Kmšà=m‹¶Ø¤e!û»ªpùo²&& ¥ê mõŒ«¬wXu’Òž„WP{©r—´ë€Í=uƚݶhA>©Ìm–\ø!…‹n +ǵ\Zww-(´ÑüþWÃcžü`­pa§ûæ»–KŒziÑÇÅBð‡¿AŽ¥·>¨˜Õ|Ò‡~ªƒÃN{!‹mÞ6–bT€A.%ÔšQ O?’ïÝåN:Ô'ƒ¦cA†˜ 8çŽÔ§§úíL~û'ìâ²-¢ÌÑnè6¥=Û³Ú‚©ˆBj´ ¨†VÀ¨Ý¥?|bðÙG‚GöåO܇š¬û¥x©E„°Û4;¤Â-Œ}â¤Ù?.ZXÉD¼ÿ¢:Òi#Ãí`ÚBèó—i ŽÊ‘xrÅ·¹õ£V,¶çK›’ûÆßä¾x•wâjÁéb°ž=+ª®%XßîõZ9Üí¼Ù'÷  @œ|+Q—æ1mǬÿ*åå…ž~ê4ù½VŸ>ÜOþØA{|_m±28 63V;`2ʤÒcŠYž˜¬«‘Z@#yu›ÍÏÛcõƒ÷ªrµòÎm¹¶©BÅ(<|Âyêzæ¨éß#‹½4š© 9ÂÑ·8bqŇéý¹Ñ³šCÄ}þÈ)8u¢xånˆOüî÷ ûÎ+úýMAð׋ǟÞùÐDšLy›Ý<ÊM´\ÞX'!ØÇIȵgPu§wˆ.ɰçå÷¨à¨Ì4øçs³0^ß<´cVHø&Õr­SbÍÿ®:ì ÖvÄà…6êp9ÞŒ‘;‡ø@z{²hM›3€ÆH}UK Žeü˜c›*hú ¥§¿ÚŸ:ú=2 ˜R•(pVüzXÞnmÿ·¿>uØt/5j6û¯¾é%*pÛíõ2”Kì| Nî2ó½t)™öÑÎ qŽær®¨×àšÌAj¬(†aÌ”Ÿ}2Û=k†&( ܬ‡$LØñIïÌ¡úÔtg`Ýo=Oß™W$}å6ÁYè¹ R#êdÜÔÅÚ "õ†µJfǽÿöñ‹ Ý?ü~d¦XŒË[6WdÃÕ‡¸»ª©Éãì=‡³­4ÙûàÇdo7Í7êjtÍÅÖÄéÅ+•~† RìÅäñƒa¤„uJ¾Ü^(’¯}):Qª[È­-öãwx £ÇpaÉôrO=þÐHÉUy½-´>g'[õ‡'Ž1·hu’Ï·Ü÷—f2ØV&5Îßy}é ´Ã»Ú·Ú·2ª¹gw{kBQdÊÒ?ìÈ@:;ZÂÄ"G[j0'lÀèXŠôD¢¯Þš7–`hÄ“ƒd}ž¹gø™gSÖL×_¢‹—9U×·ÝÍmh*…D$4Æ/±RŽçÓ÷Wúzh½Ñ. ǨÜZiŸ¿b×;º7Ð)‚Hë­Ž×vÈSg+¿ÿ±öÙ=æò»òÕ%ó«¡_ü¼¾».¶[P²”eh[V®#áùÁ”æÇ‘Ü+yÁuFŽg^g†wŸ¤ÁcãêEž~&§Ùú¦IŒºEuJrª@ £ õAÍQ ¨¶}'gØìÃshŸ;y¸tåfç¬Sx̢݈-òä¦'¬7¬RÃ}’qOÑEÏû?2ÝVá!  é#íþaì•kù~àŸ¿ß?e-®ÜÙ‚¸ëÕM¾I°šRd¨/‚¡.ze3¨œ®žÞ§.]«ÂHŸ‚ª»„ «re Ö/Oe£ÃÞ[ÿ%\cãcò±§yÝN6×{ûwéÑÿü·ü•óŠqY+™Ø;XÇKÅí¸Ö#ØÑHh%g ÛëjÎŤu¦ª~ï«cˆÔ56h¯4¸g7=ç­ÛˆRYÎCw_UØí÷­Ò¶vûb¹.ým«»Åh=²Êo±ÝÏ_jj›>Në’´òìÐ~¦¢UœŽÏT¼‰ú!¹ë´§T¯àù·¶üçßÉűµuÙQyp¢J `³×®“ q;ÎØÈa$îz{.,Ha­ªx\$†üæSþÈËÄ@xÚúVïÞ#ÅÅþªPCQ¹GH§bµf \Í$sž³©$Ãf,²| ß¼)æ–`hØ“q¼¾hŸ8WøÔã¤Ø•󯘥Ûy0Fî4ü;´Œud@É(‰@fYÁçuQ_Y³©GË·×ìû×Äz_vúbi³ÓwZÌ{ü^ö>jï;^z‡¾|'ÿ͆ŸúTo­k \AŒä¼!F¯cá‡0%Ḧû¡×!pÝzJ—ÊZþ€S<§²}^ñÏ<…†ÊùÝ5«¹˜Çfà £,5`*†Ä æˆÐ\ƒNJˆ9dtîÛ£³Þ®£áµÛƒS¨ð$µSš,¨îMOU±(9¨ì9™DÜuù 7|N9;Y-’=GyÉ£ûÔ?øew¢$_¼Ìw¥Ý_ùøÐÉ=áx‹Ý ßôJ7­TX@$7}E«»+Yš/n£ò‰©Žºï½…VtÏøŒAÝšX+W =,‡ÊcÉX5|ÿ?ëüª¿{‚=ñQ;,ÇÚ;½Ý“J"ò_~È_|7§©.Cךy¬Œ(Ié2åjÀ@µQjÚÊ"*qœqÉï©êßþ\}v”’´b“ €zé=Ó´R.¼5oÀäÒ‘ bKÔ½ÝCÚ„%®ííËŲÒm곪:äYeûÎÈO/î(«>õ IvxvdŸ7[Ö:á£Ó%o¢E~ïãn| }ëmy§A&ivÖÍX×éO—ãÓ…2Iºµ]nǧ-êû/Ö:$GÞ÷í÷{k}‚¬^>7þ'dŸ=›Xk&ª´±«%¯‡ƒ‘ ycŽ aBgY´K™!ÚÊ.(ަž%lŽ”A:ØäfwÑô ¤›ÚO~¼þK÷5:}róÇö~b`à­‹Ëã4ÃÊJ‘ ;Òp¥U“ÃøáG$Ýßvj£ë ~éƒÕwÞó—V]“{û÷G»&Ò­¨q…8Ǧ{ç&¢uîý“Ÿ²a/øØ}i]¡g–·ÉÍ$£b2SXáqÓj' k IDH”yô¨²§$·5¿cTq_õÁàë½¹ƒJÊÖ ‚ª „¥©-+– Ï,.k XËû4L£0=ÎÃÇJ«Íxe+³VIžÁ&p8²÷}P8d.À¯¤â¼4œŽ†Þ–ÅN“‡f‹ÿóô¸˜ësﬧ'N”"±ÒJ;+NUö›¤vÏá¸V­o¯àõuÿâ yw­[-LÝSÝõèêP@®ÜTýÔrå$Ö“X»*©z0¡„­ {– ]EGykEî9T~öl£8½çÕ÷øoS4À#u².åJb•t„Ñ@ «QVj›N#8m½ýH‘pEǃ#ÿi³whÀ…D7£Šï9€¸˜c{P××Ýue=Wf9ªÅû¦FËêî¢"¯±GÎJÔÏ)!o­¯]º¥wéòøÝ7vËx葽%×’<)ïrÇC'ã€ÆϽ©o5Ä$Éî!ƒ-]éºñD½woÑÃY¯4cš={æŽu=§Hã±Ïç‹m„faÀ¸.?}¯øòC Ò2 •`[•j´Ì‡ ñp™¼}‡å¹.€>âim+VV]«5ò"I 9ƒd°É ìî’3Ø&ï^¤>ùlýKgÛY®þ0}È/ËVÖ­Œßí6ɶX…s„é;f0â²]Ãѽg¡r¬é×näâµK;¯½å-¬xY,§gGg¦»[[c%Ü)~tÜ?3Ñ_ç¥ú­ üéGL™ËÏÜS^XsnÆ]×eŠg5'Û6w‹¨ž‡”ETå~i±{fÊ´€ßU"Ú_úÈðÚÎÓÛPÔ0@j:HˆÃ ´u:O„ÕÈÁÁ>ãV‰<‰ì^isf¿óÀ‰p½›/ne ¡U U•“4ÜoÑÆ8àÝ)/%ü‚ ŠN37$õȽ“Áÿó‹†ñLº½8óÆšn,Gͮظ‘ð@±‘}û’ᡱõ¹¹Q¸p æ×ÛµñÒĉ‘Ù'–kŽž[IRiû‰N4 'ò´ò¬? ´‚0àêõ`¯×¹¼’M)>ußVufÿ+oÄo¾ËHL˹¡ÌZj¤bÚë °”)+Áæ{9ƒ‚ƒDÕ4ZSYÛ¡ø>I÷ÔzBðÐVXó‰ÃH.R³ºÖ[ -[Éy¢‰ñzöôl¯·B92UXIèä1tü^jºŠ ®·.߆!Y{ Z=k¶µ¯;¶§ìè~š§Å]ùü)R-QØß¼Üyþ«Db,%’ieÜbÌØf¢dy·Ú{4ÁÊ)cîj³!ð_¾Þc¢0‹óbÀÍ¿všÕ)Õ¤‚¿ý6Z¼,£*Åúê Ù;]¹t•m§8ŠôÞ\¬ˆ|Ûˆ1c\ƒ°²@!©m”Ê€² Éû±¾µf>Ÿ(®^‡¦2+Rì»'¼s×Ì÷¶q G}Ûñ"TÍ]¦my²žòìGß7\éÍ/'­G!y=üüâYçúŽm·`n‰;e÷ÍÚ•õ­§ùÏͰ¦/ÏÑ—oÄ É| A†Z1Ÿ6Œº•Kå»ãŽ;žõ¡xL¢²_­¬õò‘lÿ“ªˆR›˜ì*+";mQÝz+˜ 3ƤžÎ(PÁ(øEŠÓpØ+Iõ J=5ZŒ3º€ÆÆyû´—O¦"wœW‰ýy–ìy!ð$5Ê(ޓ佢SÛ[ÆS•¬‘‰ mNhq«ïÿäå28µöÀ~ñ;‹$Mæç„$©pe¯›ùùîëÀ©ØÊÜΖb¶*C¬ys ¬â=äT\|r:º|³Sm½‘Ýû/ÏÛo?¯’f¯Lò¾•Ë)It0—£8Pêz&7V»&0:깎̉ÖËí™à@Íûå§¼•f^ðÇ×–Ó7ß”]›Pü”l_»ÝCÄ£¢­¸÷àTC=Qoô¡A¡Ê°àaˆíþú[íFÓ?Dt„mÈmA·!ãí£û½1—‘®åZV£H"ïo^iüä¢ë ÄX ’KФ"|ðè¨L™ñ)»ïp "£)ä\‘Â~eǨp\‹Ô£ å_= #žË-Þx]ß½`UËÕõ$Ù³«tuÎßèR‰ìNEÑŠ‚kûÈSÀÔjáYˆ‘Ô6Ld!æÆAy…佺µå[ß-;kwóí§yý8»»%VÚ¾£ó*±mG·*ˆá¢8J,¾ÿ yþª¼µÚÙéÇÂ%¹§ôCЯÜK¯5ònËhpï¬%8þ°¯-·Ÿ:ê>{ä‰I¡W¿†äK™ï{®åƒDƒKA™k^÷Ʀ¼Áì(ÝÌûW¶Rî8½ÄþàA)áÊÔGñÿÅbNù͹ØRžÞëÀV#¿6—Þ½¥5öWº¹ !« 2–I§Ž•µ"oÈ÷í-ݾÑL hJ>ê½³@¿ñ1è j$X±ÊYfkÌ Š™%­C˜«3c³æ #žPÔz·¨qá`}åI»“*ŠÃ­àíŸçý¥lhÊóHЬÅïÝú'Ü`GàždG²£k8{(.×9ÜÕ€ØôsoèÍf~€åÄÒP5„»¸Ö?~ZÎ-E#—¦/µ J`ð]™^Ò\[‚pÈð¾âȨ 3õNã)§› [ÄLN¬Fèy”q‹Ì aU`m¥9²MŸÐÔHŒš–Ïf#‘ÞSbTZ¸Ó£`ûhPè| ày7…’@%a¹ÌË[) ‘”¿ð`Ò螿ѽ~Ç;Xš¼û®si!k¯õ‘*5l~öŒûKŸ/ZÖÉ…¾}ÓöÅX¢Œ¹q6^–©ÛWýVƦ¦Ñiˆë. ÐkÆjÇ)¤òчÛû†’bzø±ÊKï¶¿÷³ÄÓT^°©‹1ã´ɰÄ`©²E®Ð™&nA "¥ò\êk¹`†º´óÐrÏNƒdõâß¶gW¢ö¶ÏCØ?M@ú&R¯]å<7#$é²··’ã{«e/W±×7.xˆ)ë—¿óîæÏnkð1OTó°ˆ—Ü©Ìm®ÜU}ád¬¼¨ÜK7Ð7~Ö{c ˜[˜5ý3.îîDd d»Ç½sdw$ò’‰f g'/þËïn.%ά¶ç"z3É‘£ñ¡r@m@ÑÍÛ°ýzùd›Ì­ &—TiPHœõ¶ºÖH‹Pß-)qn wɸYÀ$m$Å¡R!²ÌÀ^¦p–CQBHWÚ*.>˜K•fÇ$6Ô3Çñý½Ÿ½Lºµ@”!/KY;6;º²)/Ç]ITHÇr¥š0¼ÿÜ 2,õ»)¾ºNÊ”.,wß_@U!ÿÞgU¬Âþ]õÜål$*òŒºq·49šŠÜö´2~Ù*gAÇ—u. #µ£rj̦µSUNëƒ ½,]¼éDFk€„Âß²LI`VO1Vºc¬Ó Éid121ùfô\:\‡± ãlìîv6SñÖ= 翈ٜD @2“i^òÂÑ’Äì˺kMü“ù¥âî™ìÐ.óÎÛÞµ µqSºk"ulOðk¿â[Òä–ß¾Æúbt žJµÎxáFÞÈÈøŒ–Ž’lÈ«J› Â?ñXwlv¦çŠ_}¿ýƒ—)ÉSFŒp½M] ¢YAJ$!ØQ6ô‰Ïuª°°¢8ÕÚPÂ"›-ÁHÏëß?­×•*[+Jï}§up­8hø}7žFUX½z~ <¬)±xEÛ•^<=†&Ju…c§¾$E& ¿ûþÚO¯æ`àˆçs¿eÁsVžÛ\›×}éåN•¼w-¹~o¦‘¦D‹Þ>†sîË©¦gbë\^!wS'*«²'*¢´ƒÅ;×ð¿{Y.§u–¦RaÒ|έA?q¦ŸÙ8!"镺ËmWÉxØL8ªF}°Áç6`X¡}\£îœ+{Ri‹‚Ë\׺Ü$ÊO…–Ê`È1±´¼m˜&PejTÃJ“ܼ“|ì!´gZnóðõcO¸C"··œ>}ïäç?Q7¼ß%Ýn¬d[)nuÀ˜£?}¿1W¸½{.ÒZc¡|«já›mž°Š£w©ÁZ:[ãH"±o 7â ì_y^ª¥rgKh.¼¼Þ^¤o¾rÛãCûÞõd-‘ƒÃ&Û±è¦3È%:³/Ú3ec¢ê+­n …{Îæ3cºV{Îù@ócÖÿPô9-ÌÖ²'öðgN»=çÊòõ¦ß*X¥l@t[Y`“ZÙAÆ/ߨ¯'´:m?|K*â™3Ù¹{ÆCÓŸ,É‘áÞÚb~¾² ¼ºÆò«™*R,TGN¸ü–š¸#˶¾´³óÐçÈrÃm´j%ÛêwåOïF^˜}üèà¿û¤0Âû³ŸèÂýÌ‘ÞìPöèžñÍmÛë †Râp,ø:/^p{¯‹¬lƒ‘»"½ª¶nÊÞŽ²m,bëÚ«)cTtìAeJÖ¸Øì7ôˆE3@™6®¦] ½m»z)Ù¸l` ·$ûŽê_»­}êj¥y)HJ¬øÉbñ>3yfÏfhõ›kÞÝÕìN•Ÿ8Ò“XßÞ°ïßÅ´•WhÖ7#ÕQò‹_Ðk¯þFs¤79·½åïÓÍ-¹Ì]ƒÜQbefW¬NôdIìÙÅmÏ`ˆNÜí®µóž ùàbïß§™”Fû¢E¢P¥©EÖ†`-BÂu@÷LåÏÞ“ìœóà~;[ȸ¥Ûqµ›õ\ä fúJs†:áë>¯VR+گ쑇N[êÓ’‡–×ý]N=šž Æqäã î5s}íVÿâMôö öÊ{æÍy1·{.Fš;Z3ܽ[‰Þl‹>+d­æ¾Hsª0q  n-T„LºC2·{É*3ùLIe<²$íÜ0iiDsu/*ABc¶™3‰³ ؚ̟¬W8Ý?ÇÃa¦ú ]¯¡wªß{S,öòK÷O¤¿ÿdéñ}ùP…•£äø¤yèp¡ä¸woªÌŠƒ"2 ÁZбÅ\'(à>#ž´«küÊÕâ~ëSpb¾ýZœ]–;óq\ôÚ¸üÞõ®‰Š‚X¢2¥s*£q0‚ë¨ÔwßhžÅ£èÐ!ý±øv·{§ù˜0›}æÌÈ?> xñ†~kÅ?7•Þw„yà½sGûz¯Xé cÖÒ2Ð8(ŠX’Ù ó¾ŸÆyÒ3E¬(jA`¨:î8ÂdzvD›F˜[rÝ\ º‡-u³ ¹÷n˜]òŽy‘Ñ$$¶µ+½› KëÞéôw×ÉQÄ|´¾-¯¯»C%±¯¦Žœ$¬Wonu 8j8Þ‰ƒ?ø’dVoQhô(Q¥ú˜³7¹s^Pé@ªŒ¡ZBèû¾ÈR¾k÷H¿)W_Èe"ûì3ò¡³Eø»ß‘en åÈó°ÄR¬Œ±†(ÀœF(’ö«Ão|Ô=:!JÛUp˜§¦£Î ³Ü‹ÖÔÀ²Ðµ‘ÂìžÒžá|°®ËUgïÑpr"µ¢v„ìÏ^­ŽfçNDí¨1Äx[ZàˆvÞÎDO*.³‚ǼÜÉ ÎC»fåv*iæi­¡,ÝÜPëÙX-mŒWÔÙd‡p m÷ZKž‰•ƒE, ²A– ÙIÏ‚´9 ÉI¤\M[:Ü&™EÎb:xv6Ú'+{£Q÷·M­ ç›Õモº‚(ÄîêXù¥3Cýß²ðì1;RsÊa|lBÜw ¬áâM[‘"°Ä³ X [jT;¹Cêon¯©w®“ÇsïSÙQºôžR×ñÆõ¤ë±>«]˜k id<«¥ÖXÓ $yzß#…·­ DÞv9ö|€IDATŽŸäO.܉wîî8)`ÓûÔ™ÂçŸÊiß¾¾d^¾‰Þ-ÏD>BïÜõž»Ú)׆x’ä ,uI게ÖLvMËÛNK¯Ñ²Ì­5ÄBìØ*s÷(|LB‘™Qe)xl˜P©dBLnMŒô|‡.gø]_^’ù,³Ðqx ƒ5áA1—@ GÆït¶w “ƒì¼õvÿúze´œì©È£' a^^]镨·…ìôžÁ?ü¥!‚Ú·®ér³ÓJµ\8DæÏ‹"”[&“R“ã "¤À³ʃ¦ZøiB6•ÎÐ3OòÎz¦D¿û½psEäF$®Y±-ÚÒ`aµK5΀Ê2ùÕì¯=ÎNͨbÀvÜûÆÕÑq·Ÿtï4ËMK(!c62;:NÈdKgÏéÊØì@æ²´C ¡ø³Ÿ£õ™ÐÚP$¥Q’8ÊßR±aдÎ6cNã\z¬äæHY‘ø¥5Ä·B?OTk‹JÜád¢‰•k¸ñ¸£‰(2ÙE`5ÐFYæ¢2A,ÕÆ(¤ §TI‰"ã(Gî`µM ¦“Z€}ûËQH;™Â™íTFÅ;õÿôz³•Úaˆ¤=¬ ™?ú´ª”Èzn“»€z:°y|l7i¸²¤ ãjÐ[dA¨$€•žf±GD_ ;4îÖò«¯ÈCYT0|§®¦¸·‘jÍSc]æ*£\k%áUB>qom‰æèÎÜ÷°3Püý[¤Õ­¶;)`ÂkqooÍ̸Þ7æèR#þêY˜Bÿéuÿ?½¡*ñG޳÷¶³/Ü?z¼–Ýn l2Ø‘F¸Zûe–¢>d·‰¾¦ Kþ:Žp/8ÎO®2º@ÍâÍ<§ó;Ò½ŒÙ«H_Í\.ô!×r$Ã%KzžÐÈåV&ø“ÈãÓ{¯.¶¾ô@¡«ç.çìÞ·;•{mÇ?¾7¸¹EþË˽Qî÷ ÇNV.o÷Badº¸-ˆW.—>±± ¾I·è W`˜¤Ž#%”¥ Ð^¥UƒÖt2v¹µ1ôÁ냤¯(#²ý¼kœÂŠ`«,Öà,À·øÙÇK_=7èe¢O‚šRDç+W+èÔ¨üpY6%0n\êÅ„omgGkcõÙX§®)W&*„Ê ~ònúÁ-ˆI¡hò) HÑ«ÖÞŒAÀsmXJÀÑRkD5#-`‹¬µR`R @¤•¢V €"•™€'ºˆE3¬±mŒ¥`+Rƒ@PLÐYäš"ðR—s©Ö7¸2öàáq/­XP : ÊS|i¥üç/d\UQk2ðødÅþégleH¯&Ê7ÊE¨cBÄÓ£{òÄ —4c]`ÀX„íæ‚‚Ê<ǸR†µËMÖÉhmÜŽo¾ÆgzªŽ`»P\NMw›ÅƲ0”;a7 úø=¸|¤7èVåðàc¨•òó‹´Ó¯lo$ guãßHÒ©ì-ÃׯDK;âóGéÁYûç/±¿|-½×#OœÓïoÉ/>\>\Ž»…\fx`QŠ™ðÛ¹õ5í.9ú5 Ê,ºdùVØÂùµÐ»ÃÙM•Î!|ÅÀÀÎ×`>¡+X÷­0ª’¸ÔZáæ>uÒ™Æô‹÷á3{ËWú_xÐ/ñôû'êøl *zõ'nþÉ}ÁÕuýW¯§c¹Û³Bk3>ThçM 04[XWýb4^üäö$ª¼w5k’4×TSI(•šW•dD»^±”éÚ†.ihج|?^ܨ|øZ/íEÓ˜—:¾c©Xc š"„úèCѯ>,úBv¡P•™l áZœ——6óF ®Î¸)›òh}wi¦£²4ÏSúØ–ËûAþö5•ªb…æ“à#c.+;çs…@*k‘c1ÑV\ƒÖ@´à†@gÂ¥ÅÔ` [c1@GŽE®Ñ8ÅF-±Ñ–€ šRI‘P–ë‚v‘T(;0v Ùe Û§Ò"l{ÝiÂN»2/'T;JüìCúýËúÖìÃøñv´›‡ü3'Â=ûøÑó‡Ìêz}»åx•>4uØPÝÎݵíÔs¥™ÆxÔ3‰ÔB2ÐÌZ–Ce½±R£›Í]ïªìžÑµE³=gçîöou‘ µŠÎSm=k¦iI`}hJ?½/NóÑåRÖð’·?à_+]¿™®4âê(ÊÐÉsGÚ K0²¿öÜ+RYñ»©ý‡Ä÷¯¥c‘úï~sh5Á—®%_þˆúôýìéCÙ&w6³€VØàI]MŒÕ„¦¹T z€w¨l»f]膂5 [X´hêiÊ­Ê ‡:,O|V·=í*«%†=TúÇŸâûöh™w/çS³ê‹«ßYÊÞ˜OûÂ#GÅOæT¿96±‡üûô\ŽúHŒŽ…ÈS‹w²ÍùàÎÕê嵘xÛEÊ3ÎÎÍ&oÆÞ°¹âFÁ¸Q™!™ UP§ç×w /𹇊—ø»?hoõö*l·Ϭ¥VhX1à ÒÀ%NUõg·®`ÙêJÔ~q,K¶e4T¤™we…×LáAJÑ·{xy;)ŽäåÐR×ïÈï7Ï_ýÌñ‘íÓDä6ˆePJG[ = Ü3–(À’A‰ÁØË55sDÅÊÕj×U~¤}ÇZ°Ú N<04ÒZu­AI‰6Ø%ÆÃÆ£$Ç@ÚØ˜%ÐKÔ4,J´U:Ϭ{»…×Ý"âc%@Lõ‘zõ-ïÇ—àÖ†> õ}n+7†ìOŒí>lâ-FÕê¦ÛhVR—); N¥,n/£Vâ¸ÊLZ¨QÈ•’†aé°Ô¦häÄ­îô²›7z…ª{f¬zeAm×õÑ{¹»½;]—!§Žl“KFínRë>3­?yB%Ie¹ÈNþÎùäüëìÆ\¶´•”+¸R³£HV¼¼ÅË»Š?}eYþ;O…þcóãëÞD5ûã_ÛÝôƒ‹ƒÏ??í={¤ŸDÁÕŒ–Z–Y@Gcc-#©Ô`H— ¶•ë ¶%ßÒ°,ô6ˆV;‰S@RJ #xIJÐÈ.Ó@˜È {ì¤ûOA˜Í]G½}Aï†/¶Æ*¬Ül}¹Ò˃âxïȰV ¤sq‘ØðAêY)3¿ÆµBÕ‰<À<´°°a¿ùVúƒ‹v3›¾µÿÕÏH,v$Æ’I©AiëKàÚ±Ê)Œ”«Œkˆ¯|zŒÆÈF˜Á¼‡¬r°IšƒÐÒàãXb¸) àCH#ƒ â ¹o^bïÝ £€!›'½~Št®HG'lÎD·.¥ø¾] ÷[Q-ß*_z®É(jžÅgîE$æ#%­ºóìjçHÁ²ýb&o[Ù†P; 0£´MZBi€!`ì‡ß+¨§Z§þ¾A) ±©Îú|jü˜µ&LaÔMÙó,õ£ù“ÁòÚ67V• Í$ŠÜ( ÎîçþÕnç|lþ·çZ}®† ô_½Äß¼åLUåþqvÎ_„!Ô¬·9Yp÷6+•=B ÁͶ–׳.Ò:@¬C-D”ö@§Ü`”s×Ñ–’ƒ2.¡¥™R ò*°v…%‡g`ávª4æêʇíl¯¹iÁRi`a1>»þwžµöcøáu±»eOle÷M7´XqÒòo<¾vU¾¾qQ®ô¹Ú†í|>xQ¤{fÕjì¸ÀSk<Š Œ "Tì ¦êCÕ/tL”]½¨Ÿ¾RÁ‰ÈP§gAy€Xf¸áUl¼à ƒš^¡›˜àá2 û îbSâ7>€ôMÎ5?ð ÁžÙ÷Ò{÷Öþݽ†Ì±È¸þ6ò¯5’…Žr_‡BÅ·ÈëÇRfÊx!  ™ÁŒÌln±±>w)XlŒ›kaA" Ì€°×EùX»>b; ƒmJ1(h‚¥Ë” CAФ«Á¦„ ¥`-€B‘‰‚­ÉS£R¬€‚§€Ð<|NxÇTË>ź×jÇ6&qüƒ’3™í@.-œÛËp7+«¥ÛþÕof„šÒY{îÅ}1V‚Ѫ{«E|å/ºUÕ¹­ìM«;à%€µPб©ÖiD!@ä?@â‰þ©¿Çq cáPg»ŸZÚG½}&Üëñ¾1\4FYÐèºÿú»qc¥Ý±V ËA«B=aîŸÞÇ?mþ×ÿÈs%qÿÅsj[¤•ÚŸ¿Â^[ȇiÿ¾ˆ‡ñü…+€!¨£:ï­[¹}]…5Ïq“–Ý=³yçn2`@òIZÂÒ˜ž5Òbð]“œK°X`c¹¤}f=ô”¬@`g»J²}3èæ\™–uyKwy~JXh& [¸“Ÿçùo~?žS[)ª‡ÞJ²ýï¾áV]·ŸrŸícÁwÒ7%pùZÚ7 hô­›^6ƒ½»`yPp-O ÷\ˆšn»Àƒ­•t×ç¦F?½ûñÅè…ç¼¢Ës"SÜë.ˬ”À½‚Œ÷ÚKq×u7¹Ê-.Cõ`4r/¾O²·Û¹°û¿XÜ=;@ýö™ÝCð®³ÙO\“DN‹w:fómóí×L¡TAÈMRqmtâ€dr£ÿ«Ÿ±µ ÍAdÁÆÖuçZB¬eÌX­ÎégÀfFÊ‘M±„ €fȈŸY•Û³¦‰L‰m ZS ` Æ ¬km\@d€ÌB º}Ä`¼=,=auIªRСQ Ò×ùÎ ÛÅçÖmqਭzÃn•£‚ÆM®ÁöxÁêƒ,H¼<p) ¶Œ+µé—`@[ñ7^6ç¶*¿ùYµtk~U†]HÍB>åš‘½ôønŒ²Â_ý,½ÐƘ™¢(&½˜c±Àí$÷l23“ïß5øò/¹_ÿº²¹f"qívv¤‹¦ÿô“Kc4©lu3‚jÌl›Báým°ÒÜþÓÏàÜÎx¦þàKã&"úÏ_´WWSÌH_ÑzI©nI™4#®‚®ðPÅ1ȱ-vZ-Wallvh<úÝO‡ jeý÷ÿùºÁo?Tý'ûŸžþ_~E1Ýóü¡^§eÓâžPý?žuþô›Õ÷v֠Ϫ˜ŒÀоü+ÝÃ{ºÛ ^?š©M½ºL›¡¦MÂ/¬ªþÎÇÊÖÉ®/ºÛwóUfÊ¢bóN¢¶Øªü‡¨«K_ï´4ÍxF„)JQc>Öa)IZ§`¤rT);±tƒ­¾Z›³ÇÜ\*h.•§&¬ !ÎÈ0lp˜áÙ#ºˆù‚òS­:m $«Yà€A 8pƒRj81i”CL•ÀŒš†*@¡9®H…UDƒ²Žë(«ÁX… §:‡Ôˆò(KÃÔðÄ@lÃèmÛXv”¦@Œ!!ŒŒÖ4†§L(kÁBÒ‹s¤pìHO ([oÍÍ`‘ÌÈÐ\¨æBeÒÉ(s·‚þá å7«FEkw2‹ª¶‡½B&ý83ÂX BØd ±Æ}ý%¸{ø7>mVW Œø^;³Š &Êöè,;1¦ NýÏ~Ò|c ¾-f1^Téɬ#c׊ý{ÌÞIõµ_w¾þ(ë+W§uålvãµ®ÐÉøùîxÔµyØiŒ‹7! þáwåÝ­ø¿ÿTøý›-Ã}y²Ûì‚ÍþÙ÷ÒÛ*PîŒÛq+Êû10®!Q`…r¯Ñ¦–*åÉÉà—? Œ%SÃãð/¬Š¿pœü‹çzÿÓóÕú«’ÚÜqGz®‰ ³¡øÓOØÿñ[cçÛË(&€"R#ÿK¿Ü?²¯Sxí¸Ÿ™Š±i¿AÐdéùZvÍ×>V´ÞàÆÚ˜ÏWh^2‚±õÕ}»Jß{ÑþüJD›Û ψ Èb-R äx`O R9éöå@‚cÕ¡Š—ñÌm$Ýõ[èõ¤ÉZ«Þød\Ô‘R}/@=›ÄN$ü~à·wŽS0jÆJöÀ ˆ:Tp#´aþëŸ]SCP“PÓP5PB8Â4Àާba,ذƒ×c’&6ÔEÄ`‚ˆ£q—ŽS0(/h;¤[šƒ«ÕD ›s«W¨½«aKC¥Æ ´”ƒ‘X@0Á:. ¸›ŽÔ3€M@IJu®Ú®V¬GÇfùù›¬ßãÏBµPiâÆHZÚîÅ”Á^Ç©+ól¡¦ ŒJP€$Ñ ¨¡õ’]”BÙŒOî^þù`ýÀž¡0ÌŽä'wDÅºÙØp­{p¦÷Ú…–HYWDÖ¤¨¡Ùú+™OÌ@¡P}évèØà™§Ýç~¢C™–rÖ¦²ªÕŸ|u¹RÎS•·òÑÐß‚ï¾Ìmo?z¢ðÐõ‹l{rKôÅBn.nÜ;]VI¯çæôYpÅ é¿øWilC—ÿÝ_ #4nVõÿöW)2å¹Õœ¸S•æÎªÓÌ`·)>rмsÿ|¾ùï¸_ù¼,D­fq!íNT >´ÿä+íñ7°EPI[$l•?÷±AØO¿3R=«'g6—¡î‘m±Å¶Q­fpI$| :9 E?؞ʞm÷Z°<ÏÞ¾m½—¬Þu  ~t‰+BÊ 3Ë»Äp Ô€¢˜·[ńԺ™ëJmwS™†mÚ­å™#ÝË?'¥Btì@C–• ÙA+±ï³‚0Å8D°¦*ÄXmÁ‚± &Ts$sÄ‘Q% 0ÌR¤€À!J´t47`8R+‰¡!(„ ¶†* ˜“1"´¦Å3×EŒ¦‚åNæH¥±Uh¾"Ä0£@vm‚½«å‚†L¬—ÓÄ¡Vç’ø“dŠJ´.isR˜q ¶uâ8 h 5ªæ¬GÇ÷ox›ö;îÁ3i­;:õ’ÒV7{]VÕ´§åŠEÍS¬¬Y­)Tï{hG¶*gÊ‹wâö×鉃{ akïÈö±=`‹‘Œ “ɱ©þkVò˜ŽùÃËY§†‰7GÜZ.abF”ëõ—~Ô­î1=¸óý—‡¼lgdØ1ð+K£Ui±!’¬æÑÆÐ~î§êò¾oýÈòÓÛÕFÚ,ögŠñZŠW·Û÷Uš²Ã=øÃ/A´P¥ómµÑC‰ñ¯} y½¬ÿö¯{ذ_ùpa÷aÿ˜lÉÍž3¢öéóg¢®´ÿæ{ä—?OJ•ÖÖVq1îL ±€äòåÁ¿ü:¬¯XÀÒ6Iø…g“‚FÏ»:~ebz~q|VØà«A×–™4S(ȳA_&„¢WiÔÇR§á6õ­>_ºÑ½¹UøÁE¾u+Øï°Ä‚q))1p@ô‰åTS ’¾•Á-໪íñÈu®WѯtÜ©Ïj^~E•‹ìðN É*ƒ¬²~êD- …ŽY!Æ¢ªÈŸ`@JHm­ô‚0O3j£ÿêçÐb—x”9 4a¬H mÃl¤ˆ"Za‰,“tsjÏ>H¦÷+hÑ«?¤½. ÚšAÛšG™)ukr€º%§Ó÷Gê N7p’QìRD”•B+ p.Qlx¾‹hÉ HhQ¸H?ØN>YÈ õÝû¿*ék™é™(„Ž`w¶z$‡ac$ØkE8gÆx†`9`…AZR¥ÌlX¨Å:€õíõ¡…föëŸä…å¦wᛲ½}=”îW†—[ýÔË›y7ÃÀ±ï«8Ã8÷€Ÿªl½ÞÕ×éÍ÷aú3ðèƒðö»)4ký'Þ33tm3Iên£|`¶NÕÇ^<Ÿ}ýÃÖ®øâý逃|í;Ù®†ô//xÆè?J^~ƒ]X#£JUµ]÷nÞyøtˆzóJL†êuˆÛ(ZØR'öÈgv.ý%ü‡ öŸ|Ú5ÜB‰$•þêCänÓþøv^ý ^òÑnp†Œà=Igêê“μòÚ–!žnõàîç¶LÜzÏî!~E¢?ÄìWî"ÆZOïYSµà#¶ŒÀ]Óø}›Ÿ±,µÃˆxá]Õí—¼È[P`ÉäPbbÜ< +ßú ÙN€<|“Ы9b*4 UNL†Œ |†˜@º‰3±åüízý»Úp—z¹ÝÉÚ¼–¹«þÊõÜÓ 9˜9œ„…ÖQ<=:3é´oËQš 1ÕXÊ¿z¿Þ7kL€¬Î^zké/þméÚßÖLfo_wèv{ó;¯ Kͯ=Š' ÐïÈ2€—ÌûËÑ;7áȽ"ž(;ÀÍÖ¥J¼~i >²Ïýè^Ç xëüÀª¼³Œ­US%÷¾ñø}å‹wÌë7MF•ÔÖj‘fz¢€ù1ʼnýÖ¢·@Ó…Û%Ÿ…7Ÿ¯þÅ¿­¾øzËð\†éþÿ—€öASa?^†½»©ç©$é3Kš[f©'0°|=]Ý,Uç åz'^nÃÊüüÇ=ÕN|Ý@qÅ õh)Ôå`D!0’Yž‡Uhßu5‡9`1aŽ¥Ý žû°¸uævl&¦†lD²~[¸EÝíÖþöž#À„Ìký6äe¬Å>àÐÇP¶Âƒ\EÈNÒþ97þmŸü’…G$U™ÑI¬ò¾Ámâv]'æg˜¿æA óq˜µ>HÈ“¡T]YqE©‚‚%`…VxÕÏÿÏÏÀslE²’q ò–¿ æ-#æ­Ž ÐØÀŽ JÊÕü—´ýc |ÔfùùDñ²6%'‹ÞxU¥w,PVˆAüðüәðŠqÒÖ,§ê™É2ÇÉ£(úöùv«‡m{ËTƒœ è¹±øÔ.çÊ]çüj‘µ±™Î!~í'ÇðÍŸËÆ I ,ݪ̽ñ£áÿôçå^m€Ñ2Ìöîò¾úl­n2:ÊÞRgÏ,Hó¦k ¬£RЍX¼|C­m•Ì9l3»#–c±³ /ý0£‚ÄzGâ퓟Œƒ-E+=$2d¸o³"Î5Örs t,3¸9€¿~»úUêä:†]CiHûq˸‘Û ?z?ÀŒï"üäoaµTT­äÊÚR•¸¼!“<ñÿ«Ï¹‹çüs&_ytË”@â<©…¦âˆª']œ+¥XÚ¬ †||—JË1eXJß"Ž\kLÀAÄ-cÖ`iQjl¡Y¢ÍÓ>ú¶ÎÉç(éª|ó»>›3Þ6W`´]P‰ 0ð<¡‚ ±]ý§?iÿñãÙÌx)¶=®¡ê‚ýß<<0ùÀÈæ¦(Ö´vi™Ûj%?|±K(zö~ëð‡ŠàÄ -÷ìï¥ ŠápØötXøów寜ó×¶­¢ªX‰(í>rD¾º®^x•þÂÇÈ‚°ž”1´2x`>uýGoÆ bs`/¯£þB£”RgàÀŠûãÕ€f3ÇÊoܬ7¼Ú¹‘ÑcË•W™HCœÓ2£À$«T˜&uöaKtÜãgÿì94‚=DßÒy¿$eÏËcpÀ„Ý]"ž¶GÆqÙ®ïðë­¡ί]Ä4b©ÉÁøOolP·ùµû‚:¦+§S¤´¸1ø7/óÎjÕ…¶p{‹œ€‹(’'ŒdfuŸÃ|¯ˆG‘ו2»VÒq…ú1šjjÏæ¹éè¾Ö€‡E`2«¤çæ "Ÿ„–Aâ¢Õ€¸/”nZöiä*‘hCp Fø e™ƒ0ÁŒc<ÐhêD÷!cFù’€¬†Xd¼ÔƒI Ÿ”nÎø*êÎÜB~Kaȳi©RAUìƒV4•i³þ¿üxý?RØ3U ^.QÍ¥ÅÿñMóã«â)iV¯á$Ö0ìÙ{¦ÔvvW½”¡Å{þ-~wÇ Oi HyVîPRYñâRqaqþÉ7Å÷Yéøì—ýaˆjr³ÏHæÌ`½” äGŠÇUK WêªvhAlÌÜ}{]Œ¸'î‘S¿øPÞÙ,­›MqCäõn|}·%Øv9H™}â±±‡¦6¢T×Ú!ÂÆ4îe/¼š3=vRPåá"óúw»˜L?~kÀö{íR‘GnýÕ÷_}˜¬mC²¨Ve´ý‰ûÈ;?ˆôbÿ+Ÿ“–½/(·êáqö©ü¾!3 ‘«k¸w·ÑEÎT±ýßz¦RpÓÉCÑûwÕF3*œðª‡£o³Õ¾6¬cr™5j њ髨›ÖÕù6ôî:†»ö´ºdˆÊ5ee›ô:€xl0¸ ÛÙ*yìçð¨-¢p9¦,~vqíuªQžw5Ac?_Üò_ïýÊ9§îPÊ)À‹–6[ÿæ%ÙX)—™lò°0Í™æXSDû½ÜFCŽ=ý#Sšy1êaý_ýìdVhÕ5Æ"pˆ[Á¤drntÆXj´ï@`1HØ(eùõß‚é{ò]£*»ÎnpÓY|Õx0 ÿ=ˆ9¬Ë\a0”܃ H+‘ãù]åÀ¾ÂS¿”Ž’N=šË2/‘ ¡qןLå!=4íõ¬tš`%€‘§©+•t5(ð ¸ ›=r鎼½Î;ÝêïÜòÿæ ôî ¾z‚Û©2RÐýßxBÿÖ}…ÙB×)%Í”÷ì¶a?ŸOFtN|4PŒ‚ˆƒF *¹~y™ÿòã©s¶¶÷”í®¦¯ÞbmšbÆ\–æ;MÓè¡gÉžj46ì5Ç@MÒl=yóƒÚçL¯—«ñ‹¸ÃILÕ©S¥o'ký@Ð|¼`ÿôó"s¸µ9aâÕÑv?ÊdñÊúàØ®ê£h›h.£÷¯$•ªãÓçß-ìžÏ3Ôuov ëý}3pyCll¹9&ªŽ¡¤µR¼¾žvEm­%j!¹ÿ ° îE¯g­DìWHúÑ}“ß¹Ön›‹b“ ê…ÍÞêÍ1™§æ`¹p²|`Žè­k±ÇrmFªÆ(´åJ©üû†ÇuÈ©ÊñÞ?ýAFw¬oí6Ã}£tˆjKIh”´eÇ–ŸÝßýÍg½‡÷°‚Îh!;8gFÔìD~aN$¤>Íôa•¬{ææ»´È:½ x×Víw?L¾ÿ®ÞÙaçÆZ-8&È,ÒHb¤,'>Ù/á)GßoÆgy¯f¬D¸ç’å’¥gèÉͽOȵµ ×2®O‚”j¤–.a. ÍÀÝTöM*Ž’ B1Á8.â^ªZ¹>6nw0#'J3'²ÉSÙÞ:ÚºåÝÑvCòð4xå**,h.±%N b„”’:b^Ca»/|ò—Óú8É+…‹R†}‰pPQd·fMqw¹g¶M@‚%–‚„%¥0ʽy1½±ÆÓ>ÝéE¯ßuÿóèýk¾y˜ ÍÈ6òeû·Ÿ6¿~¯?[j»¥AÕ‘G«òä‰ ìñ«*hоdÙ rPCEƒAè—ò/>Ń£Á‘£¥F·ÿÃ[¦¹kd@5Å ¤uŒä#­ לÆT˜k¾aß:Ï~r5ê¸I¥y]nº`î=}0ÇW[eùdQýñ§¼4Lp‰Ä[—ƒÍØP¹±Ò¨ûÏ>m°1ý´øþQ.$¤bŸÜO>}Ì¥Ž¼Ö+ll ÏÒ‹ÛâîŠýøiS µ_ÃíÕàêoëúêN©RîÞ(E!hHff7®˜ÞÀæiúÌþÊ·®ÇMí9Eб^X“Ësu­ÚzÝ=œ;¬Š£ݼÂ}l”v™A2×µM§C˜wº˜Ÿ~²hŽÒCSýø|Jw h¡MYë,LŒE,@ZêšÎS3éóiõ‘=u_ô£ªœ)ó‡Ç¡2‘œ¿-Ó¬²ŸÁ~o1}sÑ»¸ˆ;=?NÜëkö{fß×´®EBé\¦Ã ˜f!m¥Oì¨fÏößm£œ(ƒ—CµéRòHtÏýèÞ‡øÊN%nKåL3Gjÿ•ÖÚÄ¢yKß³| Ä µ°ÍŒ¥]½g·ž9š×NGt$W¨£Ê/¼c*¡µ*CvP3µ«ˆ•yÝ´®`ø¢:—©EGÏ9(“!9KøyY–ݶÇàšþlæ*ÃrjîXº@ô¦QÆÄ1H#›úej5ƒÕE€U*Ž:ÃûR·Nu_iÝÏ<ʹ¿ºÚY—¾!ç†ôf§Y+×>õ™øò_oÏëPHää`\À16ë6·–îUtÓõC÷÷?Ý›,‰¬@Ä(½Òrúˆ•±Õ‡ý'iã’ˆcùX»uÙBT~H`h4‚Z(CpdV›y*´ß,J†8™kät`Ûû_ÿʫżª» 6GJÿ_&þóGÓ4Íü®Û=öõïÞ¥÷¶2«²¼¯êjïfzzzÈ%g8ËuX`!­+  @$@» ’(îr¦É1=œžîéé®6Õ]Þd™ô>#"3"2|ÄëwÛKH`õ?ü¾œƒƒƒ47à´ð)csåöïKT½æýÞf¹Y+u²ÓRÃW6‡iög¿K–:T)Où"ÏW·`q@#ÜI@à+à^{±#¹t)X f\ÀœeG´®o Xëx>Te4¥zÄ·O?áš=EîôYüôr®‚ùÛSgH„Ð-|€­÷º‘u Ûïe äÛeûíïWÇ`èaÊ^|‚–9A–o-ˆ}m½bõïHz‹ejR*Pœ DZ0rHcä×L©{ÂCçò/îê;O 0†RèG#nï ›Ú"áukö8×Ö@N€u‰3("@ãÂðªBçœ `B°ÇU<Ë]ÔŽUßüÉ+¦!p 5³õŸûi›Öö†zÐ) ÐæÅ;Äô€HÉG}gi(Á†Ž¦™ÛZW|Ä¿üYÉeÅ•{ÆÉäÊ çê'÷vŸyud½ÍÞé RýH;'|ë*(/ŠhÖ ËÿíŸòXÊ[+¬æÞJv'QÈì?}™Í±‘/~­ÎdêÞJVÛ§ß»á ]&¦~l¿úîWLjFYµ“%é‡÷âN–luLó;úÍђѻ܌×:ƒ^jK%ïK§Ûå–êêÖÔáüÞZi{§21óØŒwû烃¼¿&¦÷„ÍÙâò²ÞÌÜêbwÔâв×ÏÚï»vç¶ÙMÙ¶/úÖ‹0°ž]“®—¨ídv¦ùƒï{Gv÷Ë´%¤_$ÎÈRu”þâÔÒ&‘o€ÛpÈ=Êsâ, L¢ã:þÃçãã­¢Ÿ§~­ºrïÜóJ-ŸˆBèbrÄ}xÓ³÷Z%¾ò±#VѺ7yòÌø™}×_‹Û»p]oÍ#SV±$xd¹ ¼T+,ÿ· Qfo¯Bõímúp¨,êï¿LÇ£·ÞÊõõâò ¼?¹}å;]:½~û«˜Ë¯÷‡ÃìãûÕ¡,­¥ß{ÒÔš‘F/ êw—Ç·†ínaQß}Zú5-úÍ=ìmºÙw¾äÂ=¶ÏÌÿœÌtqsÓMð‚‰âæ¼ë |¸ÖIp`ý×Ϫ?üNóÎ-ÒÎpË}EŽ;פí§jg-™žiýá·‚½£íýGÆü&"ê ´°^2TÑøg?q½´lé*àE@¯ä¸'(2E”ûÃâ“Y/K¦ÿðݹoýÑȃ,”Åøˆùð®ì'ä°„ ÊwáÀ’Šâ>%DžÈ48[ PJæ¤ìÁ“ã6“rßçlŸJDE«Üj¥Y”ÊJ»Ü'A©Þf®w§hȲVòs[ç!IP W,ssé;"™@ý¬ÖiËÛ<áûÚñ²q‚ƒ’0`­:êŸçlĨÀ1 ˆ2°HAô.qëÓÌÄ•è?˜ôÎ>Ñ$~)¯-¯ JÓ\ZŒ<“yÝ¥»ÁÚ ¾ð?Ú3ûÝb/`n…Y…€²t‡;pBÓ£Ë0ô9,å$'pnO_È×­= ¬vðDAj.ù¶ÏlSÒ1é64 P¡t%ПD笤`7âÒÄ‹0qÈ\à‰‚Ô)¹`Ÿ¨¦¢£Êmp8@LÜ^"ž | Ñ9GÐ, 1ñ2î=ž7›nþc²ð›’%&g¬(µëÁÌ€ÉÞï¯oIRˆ54‹"c&Ìb@hp Ro K›¼±+;àB0Å]‰é¯ €Äƒ!‚Â'³€ ¨E ä!†uPݯ«Ñésc³S«´ÏŸ&`ýAš®’û ¥Ç&Ój{´¡ŠðÐàΕrâ EÍè½H*V¬ÓàžPWQ†=Jè–)D,8h=Oö$ø !DaRây:ËÞyÏSÊËû:"Éu¡(1xÚ…ë>¦Å& }âY]* fI9ÓÕÕ¥ß{n¤Ý}x÷±w5[¬Uf2ì›~/Ä, £¤ÂižJ7Í4ШÓ3GøÛoBy&xã¥âÿûÆò¼•“aÖýéòlN<Õêt>1]ß[¥0ìÀÌtßltï_óýEÿþziìÔ˜³P£løô±êÒídño†aÏ7çOçK†ZÛš5ÃÛ—òÃÄ.~¬ý—bïŒí®d³•è‰/×vN†sy8üù¢×ÛÓ1;àâõ`mgúÖ•Õc§ü£d{§°ïZAÁBVI1weÃSýðaÙʯÚsàßßðÆ¿¾qpzêÇŸízt¢Â:ºèr 8ƒ '­?EÂß‘ÂÇ<,´5 ü“ëcÜôÌÊFÒ²ï‰\æa§.ïÓp9ÚÊ}&ïÂh[Ä7VúÒÃΛµ®…IN°Ï!$ÁâÙSé«bõœyØhžØ»5=Ú~ìkxƒû7ò…ñ$­/¥7Å#ˆ[õAhIN2p€t c¯Äz ·!ThBËñ ]0(Ÿ ² |’Û½è3°…(¯Z¥`À JJVH²"`:_Ê'÷¬ëëvÂRrá0™#Kj¸Än>¨ž;Ô¥íx ‹ò‘ÎÝËÕDŠum8¨8¶Á¼û\] Z¬sJ‘…HÜ¢ >'ª«¼È*-DX˜.õ}å{KíîyÊO»:¥ž,2iü8*2Ùÿäù&·`èOèIТͼucqå»OÏt:½ëïåSkþ#ÑÙãžõ»Òî&Wæ§E*aŠ%¨ Ñ€3GèÛo†•Yÿ—Ô¿þq6eŠ ô¶:]Oΰ³/Ö×Ö.웚möI–€ãsSjÿ>zóÏÌ®^êÔÖŽ“¦oæYÝZxòp¥½6¼õÞÐáÞùÃìÆj ¨ñd’»íOÙ!š,|ý/+33ýn:0½áí.´OÕ@­û÷_ô–·×f˜`ôÈï½ä­íŒÜ¾Ü=z*<0ªvv¬ÞŽ Æ%ÍŒmlYâ––*$e~ÕžÂþ 9ø‡[ÇŽÿò§Ææ“#Þ Þt@C‰Àƒ3.œ%á{˜µáœ&·”úq˜ t•®­&È+4¦™ÉÊq]šyÑIxÔl¾ƒ-+2!ÚµâΣ´Ó1]åü 6fh¼TÛpܧ]GžhDøÂ[»?ð&ØÁIòáC2íû»¹z{^\üÂà°Oî?@ì½{1¯ÿñËt&Š–¯(¡µqªrT4¯ì¦N©?z™?¸œ67Mæ‘5GÏ_}C<|éhm¤º›\ ­¯w;QŸ¬°k·EÌåÓ2QƒÛnÜåñ^þÉCŠ=¹7(/høîCvÞÒþ’̪,,’€ëMQppà fUÚæ@¥ØòGœMÆ^°þféŽ t?C²T#ÍÁpOað8†ÆŠ›u‡…¤ÏŸÙ3VÞÑš x¸šoXqòEÒhšåºÄþþS±[hRr^Ư.`Q`8 s–¢«ùá«ZxÌQ† ‰Ë8„Š !7<ÄÙ C ÏŸê:><:Cæö0E]èr­±¼¤Ç{EN’«œrUk4q!R‰ÐÄÀ¢1€!¸ï–Ä> ³OÛð¨ª2#­°c1"%ÄrÏiéqéxÆŽN¹±?ƒä)2´„r¬á@ µÜùà¬"Àè9Læ”Êšü‰jM윣Ó#|ÿ95:™—ÖÔÂu07ÚcA 8B[Î1†¦ãy©-FˆGXap×Ù J=äw¢¼K¦/žq‘2š˜¸B®-I>‘y†D܈@wÌÔ¯¿È”SG)ÌYv"‚°J´uP.†–ç¤d;Y w7“ûÕöG0 Чմé_[Úî ¯5õ|NúQc4º®ö^¨F¸¯Ï÷Ĩ8¶‡¾¿ÀÆöˆùà¾ÿÁ'EêHp&§ J³O®™Õþèyµ/,/Ý?“¹+ZÇ|ƒâòZÐýÑK¥ùKƒñ]δڤ|ß±ô­« ËÅ“Sãsc½Þ墊ÐCÿÐcd¤^úü¡Ÿ;’…õ` ýo«÷ÛíÏ–G!M&·¬Èï¿1‹»¿ÕÁ²K$µ‡Ë ó4àêóì1“É*ã ¤¿ëMP“š‘ø\ò¿I®Ë& ®„©ÑPEš£pçIô†è $z•ÚBºçOÏLÔûÚ W×Ö²GÚ<öœ(M’g$fÿ©ØJQ"&%wLÀq€s†€©Áë ƒÊrŽ©É B K~aDÈÇg3¤6š:2Ø7 “³Î8¨9S¯./äžÖ¤¸#¸•6$Î"¡HmXÄ%B~/4û©™yÒEûyõ Ú®x…‰­èÁ|Á…xî40ÓcüÚ%Š=4Ž#„x”C¢yù:cñ@d}ôù;u0Í:õFÛa…{¾¯ßý[l{ySܽQšØéH(F蟃ÝD7éÈ  Çuš \ LP5ȨÉ<5°¢Ç4!,ØS‡«sqᔫWÜäScs‡y%XJ¹ïþþ‹þò†­ ~i ’ ÄkƒÉÀPDékV‹H2²Ø1MV>9ݼ5pÁ[:PýìŠtJD´™è¦b€4ŽÌó¯Ç;ç ¥- «á+ÏûW^o}0eJ’K¯´ÐÞ¹~ßÿÝçxuU¯¨F ôWÇFÉ•[ÕvŒ=NNŸ•6³ÏæÍLµòƒWe–k ¶8s¶yøxvévÐÍòçúÏ<&‹²îUGÏ”› @Ìß¹‘´½ñÛ ôGï$—î{ YÏñ¸âÒiëuMV?ýÓ/…÷n‰Úr2 ðЈ½¯‹·“´`C¡1ms¡Ì4(-:Šœ;?ÎQ¯§ùÉ Õ/¶à·—‹qÇ9„ÛÞl!5r ŽXÀ1"Ž’Aöh1JÈŽÏs«c¯ì‚ 6ãJ{ž©×ã>%(„›Ï&~õa¦­Îµ-Ùñ”àŽ‡+F¹g. þžRGÑÏQ|Å=b!ê„ ‹ Ap·À|1£î\«_˜Cû¸g½­Êd¼ØI ž¯æh·¹õÍ wœ†ðÕ ×HØ¥î0‚EzáÛbϬ޿nÑ·?Í6®Wî.æ— ¦Ù“gãéVu 7ÑrÑ u(‘¢sÈ‘04¯ ŸMÑì+»ÈQ~DMÊT‡ê°ÑÛM*Ôóbýöß»ím6˜×îÔj;ݲcÖéØ1»iÍðƒHOÙLù°êº¨lB® :áj¬CãA:0'ÔöU2«\­‚cçÇfÆ•@JK™_^Só±D§(¦D ‚xmp):b™=ÕVƒ¢Iª7vUµ!?X»½”Ó~í´ÿÞ¥„èɘ™J¥ã B Žñü—ÄîÅâPF•ÕýrøÂsÁÄu7’ŠŠ´Í\Lÿæ·ÞG÷“å!Q£dv&-OkžþG¯õço‡µådÜ {_©,Þ$Ò ¹æ— ¥Æ A‰nK|ìü(G¹Ò'Ÿòï¤âÍÕ$DÒ©n<š+¤°H Ç   †¶Á=žO{Ç÷#±žç±ÉýÕ¹§&¥¶ñH€v9û»ƘTš y Ðw^€qAõÍã¿'õQÇ3¤_@q—HŸzuJ} ¡€bI‡|¯¾wÃÞýÂ:îE§Û¯ËÍÌO·©&/èi‡‡o QˆH1ê`H$Úç¿éÏͺópû®~ï¢[¾QaßîÚ1å™é¸¾3ÔÀ »p=“nŽð*/ÏSi€–ÕDHP½Âƒq!'Ÿªæ©[DG^ƒfM•d…bžmtÈE{O]¾N•â„•—‘Lˆ¨’æùêNúÄÙ²ÔYFL¯îÈŠÄÖÊÌ[8íyÌíñ›4¿de è3€ÎgT#Z'‡ÂÂüJ0u®8÷¥á±Cìú½þG÷kL ð”&º:óˆ–_: _=krŒ/uЏ5µÿÌ`¦’žã—ï†E1¬Ú–EL‘P° {0FI'?¼ã~}§Xî˜ÝfºòòïöjW–ÌÓȹ½9”¬˜«œ(OìÙ® nï–ï­á³žÙ•Ÿ¸x½Ð—ï÷~ôEö›/®•’~¡ ‡±`†X§Ô”µÆ7¤\þᄀ¦Ê ÐpwÞ!ű§ªÏìË‹¹°ÁKÂé cUÂ(·|楯¾L[Ï›…ÄÿõÏEÉI îªÄ„%øT£¬`v ÅÍ8e£šîPÑ5¢³!ŽLOÔK}_C@•ÖÊ $EWÿ_?iïì’t %‰o-ûNX0’ÓÄ|K—.¸’úÈϯ ÷žÓë@›4n0^P5`fL—7ôpër+½]œ˜£M«il±Sœº`äúçUQ†}'+Í®×á}R´0° g8×hùIÆIž‘¨vÖPi$Àpy2¹Þ?Ó!A7},Œ•¦{FÛ<×nÅåDí%¢ÊÊó(§ÂÐQ S/ó`LØ™ó#½”lêÇ_ᵚªQ§t.ªB¶±Æ}P+ìΕ,ù©tnÓkg(Kà½Mäu”é‚c*Ú§x—¤›^¡9\h,ËH(Z¹ÑÈ—7{O?Ѱ CA†Ickt‰o=jýè% ˜óÃÓÊ)Ü€ü’+Râ|À‚»®óª MB#Ëó‹a븸ðì±cŧ7’÷î×;.÷!÷ƒ0CU³ÐäèⵃÞ×Δ/wñèØþÓr¼28;^¼¿àu1MȆÒ(HÕY…¬[È"JÀÏ„¿¾™. ’aÝmаÙ%ínpýaõ‰ýóûœöUx Y;Þ˜ÚÛRïöÄÃ-~f4¦ ýØØÞ`xíVò—Ÿš_ÜÈÛ†(6ÜMiŽ…àœY¥]6I|A‰)¹ÿüër_¬ˆ'vºÛ{*|fä»éÂÄœ8I4se óMáú²´¿ºû•—°ñœ\RöþÎñYj’MÂz*`¼ƒ"@ƒ@hÆÍ¦)èq.ê–ní;k£86s`´µM3‹\Ûa@ã3Þÿú³ÞÒ.ÔH¤…o­ #ô-¸œgS`¾©ã .r„mˆâª0ï8½æ A #ºÇ̈+Õp÷RÉ>Ý[PÍ–ñœ¼+¨‹}ðJ­Ï/†¢¬,ÕÙ÷P—Y ͈N^‚ÊIX0q¢0™qÛ›­ôZzt—±!îWe¸¯OU2‡C9²q«[’¥I,VQ­«©;HéW-¾dàäàÿ/ã{³ÑCvï¤õ´µXê² J¼±øYšwåòKFle¤$÷MëoX6v! y í)Bf ­YìÄLŸˆ ÌÉCI½{šiˆh"œ¶f;…Õ->^Š&ÆÁ"¤¢ãÌ'ËÑÿø³nOúÍ0køú>ãŸb…+åB‘d9Áš‡™µAmØK›Øìæmµgvj²Òý·¿’—¥a¯•º’LÚR)xü¥ˆòLx1ŽŒ£»ƒ\_¯Î/évê'¹ÇŽ­z¨$qd«CN¥³E†f7;öÞ¼úímsm93Ônñ×ñ£{âíGƒ›‹Å»×éO¿ ÷·kõ¥õüWwñî‚ZÜ5f‡u%¦Nƒ7¥—‚¤œözsž®Zß1ê ž+ïæ:ÏL¢ÇadßÌø˜JißV ¬Ê´ÌC>åÔ!®;ÚÏé3'ÕÂfý¯ÿ¦çцþ‚qÐÈ0…¾p9g¨œÓÔ/À¶)YUnÇH• ÛŠ_¾ß«5«õº¬–8'KìÁZé‡oË«•Ck88ô©*ÅÎê å’¼ˆW„©5$9`=Â4Óî> V8¸hÒÏD¶AâÁåD 4; zdNÀÄÁºÖƒ01!ªZ1Õ¹ìàÙì̉àÎ6Šíá³È&)é2½KMè`¿3'@±"£ÁØÁFZs†‡éN[¯ ê!0qÓÃhµm äã[7w…¬c¶JÌ’°Žºƒ„¼ø"¡QÃýÁ׿æMíë¶ÊéÉÂWN‘xšZS"pýJo ö ùÈ´ú2‘|ðÈþ”¦wŒÙäÞb¨ÝÄý¬«ç¢[qædBk·%YR¾¥Â¹BRkÀ´%Ü_5­˜Ï̀ЫˆLÓ«÷Kÿ·_ívRoÔ³e/YäüÓB,s¥\*–¬†.Q®Ù>únÛòªˆc4‹ ÃɉJ½b~ôË’ÈYæõ‰a{ŒRœ5y…^ŽK„ÁÈh6ÒK2óéCz¹ž¥D§B:Å|:çÛ0ó”0¼å* Iê¡JLÒu·Ûxïnþ«{úÓeÅEº> ¿¸ŸÜçóKËÅ;7ÈÏ¿ [¹”êÚVñæmugQÝߤk9IS”8xà4x€ÚGYYuž¡ÐòªV‰O7Áe§\mrdbŒä¼­J¥G~‘æ8•=(Û‚L·œhÒ—Ï˽Æ_þe_©„¿ ­ñlh­²ad2𜳎º@2³Î`ÅxmŽÌ7w›&úti·ññVÊ¡`.ö—Vø¿ý ûì¡#Î!†0Т ZÆ5<ã+6­.¨ \3tIô6Eð£ÜuPŸ!x¬%‚Áå·lxŠè„H bòˆp6Ox$ ¨ÃŠ«N%GSgÏVn¯[¶‘?NØkr4›Ä æö :§Íª*L‡ÆÒšÍ¼ ßìëeä&"ÿGoA¦bV©–¤”~¦ëiZ* \"î"1ܳŽ=m)%r‰º½_‰OUÚè¿7Ÿ¨{£Í¬Üpq®ùÕ/~h÷ê=ÝŸ°HQôLhEnUÀ(Z×ãb–°ïQÇa Ã0Î…„Ì l×Å_·‹Ìc mÅÀ2Vu5âÈýS0{€êæ6€"Šæ0ËÏ>ëèV87°….F½­,ѾàO¾jV.Ó…MŠÄv BH¬s8]ò äZÆ×PdY@xÌ”´Â§•>-0(N”쉚 ·Ýƒ…uÐE€,>±®‚Ðç¾T FvŠ*ÄÎã™–¨‹-{„Á¯™[@U³ÀÀ(”çÔ ²LŸÑò%,?ü±?§ ÍJvØ¡;x³§òËbË÷ÄíûáŸNõ!z‡˜_Ò<ƒþ‹ÄW\wuæW‡N1ư_ˆÄÔXȨéh­Â€ÖkƘº/ÒµF@¹®\´êc” ðE𞎘?;ùFpú¸Õ¨‡zlþ~1U÷FkY©¤ïÖüÚ{?„½ÝÎg%ù‰ÊýÌùÜS Ð0¼CÈÁ¿­è(-h‰×rªOÑSPìLãOW]¿³:Ú>G!6!GíGfï(™.££ôÞ¶›ï­ý– ¤*ЪàÀ"Ju¿© 34R²*HêiPÀ•F!ˆ%ÈŽ›ƒç½ßýÎZ´ehF#ÊE.pv„%—Þ…R¶-3à,2™ƒHG=›ÑX„„ÕtÑ1< ÆTº&AÂ9€aD—Ðx@Š’o%‘ÖYG€P@K©%ÎÁ8@ €¬'ZXôô PÀš Â€Ê ÃÍÀ€¬C¯O˜CítÌòØA.|yÍaZœ{ `­œѵŒŒ{»©•` ¼üFsùzçþ:w %a; 9‚‹ÀÉÐr`zÕ†¢çÀà7@n@-¢ I8=~|wbdûÊ ]æ²Ó»l4ZÚU¤nÔƒ©™ÚÙ úÍ¿d‰Ôuïù&mÙr?(†€C Fà z"ïXG<ÂC$–tFûTH,Çpê H€p*\ÅÏcmZQ7<÷ì}ý¨/€‘øË_1ÿÆá÷‡²W±@ ¼˜º‘¹–Wœ˜=9ÜØ«_Œ7'‡ã3:ËYÛÖÿÃÏî¶YØê›BΘC”£Ñ4ÝþÖ«þìÞ™FS¿xM½{5ÝΠÐÙÊ^NÄÍ4ºÙ¤ÐH8PBˆ‰!ÒXôÁK}ÆšÖNщ7tÑpýYÆ2å$_⪈Cp€!ÐeÀƒPy2Pª¾,zIˆ· ëZµ»¼l™BMO†õ)ÒkMù´ìbÔN°P< 2&Ê“.0ëýfÁ NÐåÔz£@¹Òz}@€g.†áAÀ”¸b±Ežô`fÅÔ µZ\{+_"léælkö¬ ².p A”æ5Ϥ:èiМ3@hÜ<‡¶Ê[¨ºÛ†QT’8»šýg>ýmÂ8øCkd¬»Dosz9èJ]ãÂ'öAvŒ?JÓgž°çŽ5ÊA›ƒXÝ)ÿÍo·Ö’fáRÂ8qæÀ-·eR^ßì>zwäk¿¿=*ü‘¸½µ:ºÞ±§Nä{›òóUïÏw‡¼K­8ÍzÚ3MDÁH‹<ùbøþ\‘ÀéÚÓMtY—á‚îrÐúI˜X”ƒꨠÚ8ƹ‘Àhhµ¦ÄYâ8W„'F PP4–Á$¦†Ã1/Ø#Å „7û›C’W¿ñM»øQ¸³Üß*T¼¸˜y[V;©¨Ä*¤Ç'ÃóÏlnî­›Ay{ÿ!Þº.F?þ™ow€G;ÙÌ0Êq@)ñX0Â7¾õ:;¼Ç:°F/^ë\¼$;y5³ÏO| 7S;¿^º·–@`yŽ<¤4-’2$QŽ9Mñ€W}û“Û²/æîáF Ô8­ 1½ E ösÆA—  á9;Ͳ7¬iô‘«ë»7³-½Sû§Ui ÐDqnªqÛ"‘Qíàˆ­l9© Æf½[JZ°BtA/¡¾ê¯4°Ê€I‘ö¹J|,¬VÆùÖ;1¾ûWtd¡¸'­4ã3'ÃÏîÑÅ«Û=âºN: ¬Ó@,¢ç”÷ê¾þÿîEgç$Ký ð©Òðø~}`vdqYoI=Æô 3$ªRY¦)%.Š©æ Œkµà!#ç0ø*sã¶ü¤½Ÿý½½»ú®c=æ+B?&j# A œÇ÷+óª1c³õó/šcgƒFÓ]½Z~øAg"Ã9(£eƒÈê`êÎMúù{;㈌ŽÐÎ~¼sàÅÔî—ÒŠÂ.ŒOà†ŒvH°iÙº„ñœÑQ3ž1~”2/%r„’ã,¢ÓÊ’ŠqG‚à4â´5›Æ=pv´ìþûï¿p¶=éçU…Î$çNsÝNïoÅ„p$š"8Br0 °Â +ú3£“_:©ïÝõoü}gn‰Ý_HgŽ·ÞÿDßx¤·ˆé…XÔ–¤Ä¥Ä~N¿ûŒyù4tÛtec߃Áøã¼{̹Y‹‡N1ç—µ-Ÿ ¹¤ ¬á,:@ ¨™qÿÉ3 cÄ1‚. ©'Ì~ÎÆ_Äø Á§œ; pÖØÀÊe91„AXáÇæ¿÷¢å콫y^ŽSDåL‚Øã* ÁÎxŠŸ˜#þM\¹Õ}´è¼RðôãÕnËW»œÃ€B•±žCÅ„ô_ëýwÌÏNÛ ©•¬œl ŽÎ‘Ãsµ[ë$MM‡|ØGDË‹•çœ8ÏC4:ÀdÄ ê.ÐÒWÜòÌŒî¬&Øæ~à´Ÿµ(€8 ŽÆ ˆÃyþŒÂñ}­×^÷N?ˆšýø³þqÚà>Z¢àírm£©wƒßÞ‚¯dÙÚ½ÀΑà¤*Ô&èú¼f¨orí“>Ø£âoÎì+Ðè<“RÎê–΂?IiDm€ªb¡P·nd—ïlïܺÈÐÑ Ês3€j½|òhO”ÜT ŸÀ‰dã!ñ´v@sX4Ö €2©öÉvQ"'¿\Ÿ³wö<¿ªÁÕ_uG,>/`á-´©%ô Q Ñ„x{‰xÉK})Œ$t{…ù*Ðß{ÎŒÏíôzP¤a’[U_ùŠ»Ò<ÜU\°šøuЕE%àU`¿úeïÔ˜íô«M¿ëž6áÍNïÞ"ô’€€ké”OåD6ãOÕ'ç÷n°§^¾˜'½´P$üÌOK:¢$„‚oœÖ¹­P29dˆ–Af€ðPikFA"EC©Ç@€£%2L)!Ø¡¤jÉÐû«ûl=w¤Å«¯ÂÆ­êèžáÑ â“Kƒ‰º9ÀÑàÒÔ÷Y®ï/˜g¨RQ…µG|ÞËÒ; ðëŸG£¤1E¯X<ÆPJ"ÀHœ«ñï¿Q )}ÔÎ\)+ùþ Ç­1ûF_šÿ«ßèõ4˜[ïI-Ïý¸â§©¬ €ÇÜÄÖ¾Já°0…„yoX^=MÁÞ÷¿:rý¯ûV-T T¤žÆxý³ÁýËCãpŠŠaÑ+üØ;} #%ˆw¶’ØJg=1¯8åä=GÁ9 œU¥uÖè“^àùš›µ÷<çý¶¡®ÿ&œ”ù-~ku‚.ÐÜÓt Œì[ £wYiHÈ#`*þÁ3¥;I‡ü©lï@½ÒøÞ«îNGÞßLEP8ǹhY~3lüî-ujbÐMI#â$‘2¸¾¡îÜUSσ¼° @ù64—úÈc¼qœ]™·'^Ï?Yƒ¤c6>7pžˆ:QfÝ^í ž.²PžC"‘¨‘KCœ f}ç8ÊCÏ"„:N÷Z¾ëXÆtÉBüsánë…8Îó—_‚•kÒ¤>þxíƒë阯»‰áh<ÙŒšx~±¸Ù¶ƒ$:¸®.ªòÙÕõßýj„ (vòD{ÀP­ ­ÜlÅûþëõˆêÕv•ú‚“$ eûFßz‚ÿO¿"‹†Ïe¶®ë£O1¸hýUNò¢ˆ° @æx•À ž‘ÜÝ$µò½—Ë\±‚_iÜú›ŽÀˆ¸IJ!Úh´`ŽØ@°ø4oßMñq:k,;F®Ý•f²çƒ×¾JîÞØô¤>-üÀHM ç"fˆã6˜¿ã™-—:±ðÿï™ùŒ†sB=a¹sÖܱìÌM&¯0sÁ.¡]îíxaEøu¢Ç­%ŒØ”R/[[:Ûÿ8”ÂÐÖðÞz£ø¤ :ûÌãÊöà(ˆAGQëD2ÆçFçNn–‡ت¨ù‹óœZ6¢Í¤åMô<Ñ! ã ,÷1.0-­*@?FùØÑ¦úÁ+,( ›G¾¯sŸ<æ½=„ʘ~1¯‘úž#–*'hm©GÒ*7K+îìóniQµs7ó$¿Ú[z0,8ð¹a1õ'¡UN”¨yê_y»˜ÿX‘V)šªo,dµ8{(Ý$ŠèMnßv ]¬ÜŒÁÐI¦eˆ9¨¢ç;Û8jÍ5p%gK`9b8nTÙ*ÏÀ²÷ˆ¹",A£Ñ–cŸ€ÜpW}æ…é¨ïÝúqºrOí=UÝXÊJ êAœâ<ªP¹"§ ¢´ûŸ™øû_Œ3Û"Oe9Cƒ¾«z†ùèŠï½ŸQ›ƒA©Õzp³4ÝÖZ‘ ìÞYqA?̆æ Ù͘¬k?<°DHÁ¦©ÿºòOYÖµKåÉÙ×k{l¬†i>•a~àÞ²yvÅ@Aœ%N8R®ÑF LÍ*­†£Ù¸n´´ÀXÇâÖ'ºâµ«¹Ë'©?‚4ô¡ðË7,r‘ào8^"öše dÔmFyèÐ .PÛˆ0Œ"u€< ˆ–8°–ííº†öUר½E ´OD›{>唎Ž3Ÿ¹Œ‰P#[¦˜9åÈ Q»·Ã{UÁŠâÔ“E8Š<å 1ÖX ±…„RÉøÄÉÖè¹ÝzÊX7 ±q›j‡£ÊNj¿^ß³¡FŽ‘åå\+&ôˆ•eô.ºb‰’MýO_¤˜IëÃ0‹¾xÛ8;1y,ì¶GB…~vOÂ¥ËÀnbcã vý(½ÿž~rruÞ¬K=ýœw»‹ ‹Rs‹„1kc\‘ÅQÇbŠÏ=Y½ûsµy 5&N?¸›WKú¡)ôÊLÜøÚEbcS†Î„Z…¾³e‚±sMÊZˆ£ŒV-;! Ä8¦uÙê²…e$ï8u t_À~Œú(>ˆQðÜ7þ¹'ËA!nþt°u_<]ZYLüì?æKS†¦§JsÒ¦¢yl®¸½ˆdZMœóùV& lZȱ”£Cßµ™a!ºâ÷_(_˜MV‡yi´²|3Z¼•F"¿Ôã9ÎM{7WÌÚ ÙÄB:ïã² rp!øŽz)1£È¾áYKˆ6EôÁ;ý•`„J”šÎ©œ\|(¢^Ä"c Ñ€!–ƒ-ƒ."œÊ™K[tÎÙ>ò{ŸCE4}§üQw¤‡,µ6à34Œ¬]Õ…2VØB1\÷ÃtÅ—ŸHj¾<gO„Òék·Þ2p;÷zZÐñýžË3῾¢=椱p(IÌýµÃšÍ¥Þó_)í?êJsü/~ÞéîˆE£É E•g;ÿ‰çJ“âgñq®nßϼ˜æýòúV!ŒGoÉáU,¿Æ…óƒUP8Ûì Pµp—˜Tº€ÆF˜]£Û¡—ŽŽöC4dÈšÓ`™•>´V˜Dœsâd>÷õô•WÔ•×¹àk_ÎÈñÝê1?'`‡TK4£u”%ÌëlßüZíàélⱉ®l<¸ö´/c;È-!¡s P0††úžcU’ÕæÃfá·Æ×6‡{/ck+x«/ѺƒÌ^ ìÇ9ÈcÊ꺱¯[ÿ p)0â²1Õºro;œå|”ݾ¤·?Ê–eñ!Éÿ1 :Ê8pè*1œ,¶®ÉêìAï\ ¯þð<,œB٣ЋÄm­ßÖö·†Ý±æ£;À,P†¼j‰ ¨™á¤¡9â*GФ}¤Ú!"Rg:D !ÌãuDPj¨Ðšõ[DrÝUÃÖQœcD2m˜1Bëæ·oVÖv­•f}ÑÄÛ!em?Æ- Á£^.Çá“k›i1t<w=¿ýïSàDrht3Èš6Izš8D\‹,2hp{Óê„éggéÓG¹ÑF’Úßy·ï÷´O'ö ‘d<¢¿ºdÐ…ÔJ‡Ä %‹Ñ$‘Ì Pòü×éž“¶²§ü—?íw·„ ± µ¤ZrG¬œ~Ç|&¾(€Áò‚>ü|/I½…uãŒ;3éø†Æl2oÜ+¢#ÜBÔc;QœT*t™,„`–¶5Ð/FGûA@šµöpÈCš9¾ê¢·™“DÌ";ë‚»0¼k,×b²Y|ãËÑ¥vO1Œ²9Õ쌩߹C‡ wµsÀ±Ü :»Ão|¹uô±lôÌȧד;w@ÙÒ00©FBb‡Œc€†0æÌ?zΫ³”ÕFÝ–‹?àz´¼±3q P|瑺±£±3¾œø1 ¤+´ï¬B9âìWhxD»¥ek’1^¹×­LÕ¼quï’ÛúÀ_*ºoCžR`ÀPb0Ns¥>ítÈLÌ«i;Gsíjùáï¼C¼ iÄ =ØbxKÛüBám´K†´-Ó–QÆ!xK!uÄZ”€$ ^®é²ód®RF³ÜQ–HíRÍYh]Ê*b@ŽH|ýÀÀñ ‘‡„†z#rk8à÷v¯‹…y3r)¢ülî¿-8…þnd!s£Dà¬ã«žö%Ì1=»Ûýð7bb²4¤Ù&xÇ¡'U<У©ÆtIJà´×œd,(9”xIz‹  Aºž`4SŠÒĸus6¤ N)t|Ž^Êîåž/Tn536@f —r¼Eá>ý"Û?A¾~Tþ¯¿)Q•JÖí0Èý¨‡¦´)\ÄŠ—ž 7k=Þ'ÚNLMÎÔÒSçw«ó+\ ‰Yp €Ç&B³^Q18ô*ç±÷à†]ÿÙ@€õýR§õ¸œ~&‘F‹qýÇ {ñ(Ö(j$°%gë¡»e•¯TüÒóyUЙ½SËË«nu¿Wzídzå=Ŭ  fj\DR%Ö¶Á¯ýì#ö_|ÙþôÎæ§—m¤ÌŸp½D{Òs1U§…ò˜gÀ/lZ‡ÜP٭߀öËÑa†¾]ÁþVey.„ fÌë[yØ „‡$Yà %Ä·qÝx›}Ç»Bân0ÿKy–ç†ÁeëQŽUÇÎíxn@¬°+Kç#DƒYïoàÍ5×dZ9èc¾í•®ƒ¹—HG ^8` …@1è4€’A›P>OPá_PD4°ÖB³¬P€qY…>…ñ,ç€S…ÄsZ0(PÍ[X@†ƒâàgY0®² ƒ¶»q+º9ŸyL¹í’óX‡¾-8¸¤IP¢¢ÌÛ ÏìQ_õ•ß°©±VØs5–;-¼ŸsÛvДð=(½Åª)Ñ :)]ÅâÓ"ßhåaf…ôõP¹íUuÖ§ Nú)í!ðM,‡áš§ ¤A) u>„jШÉ·û³{Ë¿wHÿÙÛF¤`¤nMÈÐ÷;VF£)‰Á—OˆÅ%¶’Qˆšã³­ääa¸s¯N1¿å©¯× Bë*aò´h`Ü9ô˜Ñ`¬{Um¾ ^^ua©=þ„œ~*ÕÖ°ïúAõÊ^©?p°&%ü¨·ŸûØ’ÁÐxO?i+ž™<0¾ò`3ƒÕÆ_=>¼ø¾%92ê PÕ}¯áÜŽ4=ðÀO?Âö†ùÍrûË®.)û0hßr©È9Ï¥ Á/0¯Aße¦ #ÆKæÓh6‘ð»žbšEÀå€ðw •BDbl×¥1<ƒÑ3ˆMVC@„ÂØ :‰ †P°µøÞ?¤'ÅnâJ.&‰çƒí¶æüvóèõíns¹+n½«G†ö`ih À6XtÕɇó-h— 4å!PŽ€“FP°Û@x=ýÛ÷Ö: SÖÅ±× ªXây ¤ûΗÉô˜ár„ ¦‡^ܬ922ë¶»]”¹KøŽÚ4MÆ…V ïùüȹ¢f5£Þ`k¢w¯WÇÂAžhŒL¶æ’‘”Ò]¿Õðd›GÛ,[F´f2áƒ5ikVHÍíïíå L9ß¿½]©Ïœ‘GÆM£åzS¡ ¥`Fh(Œ&¾Gw6ÒhvÏßþ–y–æV-éÄß ë©¸ähC$™)Œ8uxõd †Øg#Ñf.õûç^àÍVçÔäkdy›j2d€ÑÜ:â,Ÿ‚ÿÌ ú>DÕçkÛ‘7¶1è·^õŸüRev$›ˆ»:]]f''},kóçf"q_˧ƒR”Ñ n[˜ì cN•f*£´²¨³ß¿…ð‰Õ[œ£ HîcUŽ.³¡Ph‘Û(ˆ#¡O±³Äé“•ÿú´ÛÓ¨}º.ŸÝßú—ÿ89·<6>ya6úÊãùwŸ”IzäÎn÷¿zjÏNõšûFGªrD@N‘X¦Aê9ë,bÙa)¥¶lm»Ê"dÑ[öæÂ9(•,"Nxß÷ß4Ù&ŽêÃ28Oø.o„ÞKR¯hyÈÇWeå )šO¸§£2¬MÏÜØHhjB‡ËÇÃà·±E' ?xWˆ¡¦’8ε¢TqOIÀKøÔÒøXÔjäÆº5{Ê{žÁ€äUKoîV?½1°–U 8X¥i¡¬ðç¼®éÔ(xοöë{æÞzwc 1çLÐ+ŸäÖ}ãµ`z²oZ!½±øð+»A!FgòÍnø¨•Œϰu¦Œi0šŽc¤³NdöélTêˆxéúÄÃ•Þ¤É ä¹…êäÌäLRÊq•{õ ë%¶z¿œ,E FXV+bí쑽ꛯ–h¢Ã}Ýn4=w–9¢A¨R=¾|KSjê†Æ*W²"”n¬gÉÈèÜ_¿ÅE#õ2ÊÜ"pÖ˜­R“£2A€jv_pbŒMŽVWúÞò ú˜¾OÞ¿Ml¢I¨—£!NJ*œƒfÕÿ'yzæ–(Eç½vYÔ7†C0[àÜëþÌø 2â P®=d§-+S§ÁþS£÷ ~ËÏ%‘À&1@ƒŽÌPáùÖäv‰ VdñKÇï€øÌÑmX8,pQÑDPÎCë¢7(#öÐ,œ<,N‰ÿ›3°oŒºR}æpþ/¿ï]8hŸ˜kò{»–¿·ž6÷Vb¸¾ÿ —|ÂwáSå‰Ýõðø÷IŸ5ç&v·v[]H   ƒÑ:f&W°Lòå´ôÌiŸuÁhŠ Æ1¸G†€#G]JÜÓ‚ÒŸí5ß:8Ó~«ó±§ë‡J/¿F;[ƒˆÕæö®Ô~à½ó£ð!ÃW^–û¼þÛ,Xÿmk–Úï’ÁOÁ­ð5(Ê$f”’œÐ›æÆni_]ùž9 Ïò<á¸ÊèLиø0H(N¹h¦gC 7T¡Ahâ"æ­™bšä¤ÈÿîgÅc'á+7n 5MRkZþõëÞo>Î?ºV'YG°æ€unm×nj²ÖÖš”2™ôHÐTßÅÁˆ5¿GJÜ Cá»™odi-ÝCVÌ8wå$Z©×;,’à$1€nˆ4xSe[ „­0Ø),”‚¯‰J·:ü_ýë¡À16ÃNZ1ï|°å¢Ò ÉF§ëGŽ$lG7ê"c4¨© ´fmLóøåf±Sp›ÀJžŸh …_uøÁ>-Ñðc¦†F/ϲ’Êï=þÕ’£U«†™EQâ·ú•kÛ;@|NWó*NáÜ&_iYܵüÈkÅ…S;-y¯CßøÝ(·]¿Ù^o?ýBðn¯>ÇtÿÌkc——wOÜgõNÑ?â‚­:×o± ”jwOØ›ÐÞrþ– ÛöJa¬(L`¤ë²4rÞì˜ØìQžÿ‹ïz£Õòƒvøè¡ Ú³Çq>m#ÂÝÍ6’ÑΪ[xs•"{¥4ú$½½¾†ÎZoíÀy.¯îŒÒÚÞóåñYµÓïþŸÿ=öÅÄ^°Ñi÷ü>äÀlQ‹´H½íÛµÜ,™ˆÚçYx¸(ƒÔoÙ´Ëê/ø=$ø˜ñ±ÐïÓ¿¿nãÝÞ'Bׯ/¾FºÛIÌk{ö,7þ(øÝßTJ~õe{0´ïDÁƯ£Ðß%Ù›Œ.„áŒ1 üÚZv}£tlD{ogyÂs\%ÍK«¥¡h —Äh_F¯[ÓÑÂSbÞšU3\Š ~ü«gŽÃ1Ž ³iuàé!Yo\¾.û)ÿä&£©ñ<Ò'é­5꺾%¦c;¡©X60rô=èGÞñ‹j^ü– CÁ\ÙñÀèòZ1ËV²qd<óVÊõMYƒŽ@k,Ô~f{Û9帔öªh’–‡âÿúoú1Ù#K«h6Øõ2BËaØàÏ_*½6“WmžÓg¾YÏM™h֢ۻѥµ]ŸSg´¬ŠŠÖ6£v‚»?L”ŒF·2<õ|vêét]Šwwʨӯ|êñ’Z§÷ì‹•wûäæðuÿË/¼»Ò>›ý)4VLgºBä¢- dA¡[‹¡º¢³-G‡a9/º~$`‘[G¿'$LOò‡ÍPoýËoEGš­GFï<¬ŒÐ}gìƒÏ s92ÔÛ|$þb›½Êp‹+Q ~|qà(m;“-þXŽöÔ­yÓ8j7vè‹Þd”ýŸ¾g^|BŒŽ`ʤl7qÊÏAW€É¨¬j6ÑŸ·2hn½QÆ&l2éùe><ž»i.}íÍÃÖ…¨<҃׿ª¸´¾_BèÛÄ?nNïcûýȲ“³v‘ðõíÞhX°ËùšÕ@ˆg]€à¡Ôm0/}Z8éˆ%|¨¡Tk¾ó£÷2î±+t­çc±ýÖÑJàUcÝîÇ/½ Þx¦”ÛÅZÐ_ì=~bô¹WÏ6®~ey}³èæC"Ó<ÑöáÏr­3K2ŽØÝ$ãDa Eªw¾mxÕ#A$EðhË®¯û‘}ûÉþspàXgä`16êß¾B: Áêº'7xî~uˆ4†"/j4ž Ì–ö¢† †ÕÎ ßMóf•·ªŸÑõ,äéçêKÏF¯¾œ{ÉèòÕíF$N?Y<~b¼à£½ÏRJ·-C§!vÆs'…Ñ:F#ʰ¥ñÁFF›ÃcÇb+û;…XSe@ÿ¯.f[KÎßX((ä¨³è æH½ˆ:~¹öìcIª‚ƒÚL‰öž e‘é]~xe+ƒÙÃɽ•âØéÑÇÎoí›»r»v®0Ì@NÙ㌞·9sô:—û‘†Uâe±Ô2÷ÂX!·D‚ë"?6G¾ñjøÏŸQ/*>»–o™`ÿ[ ½Ï:™ï.Ýuv6w½+Â<—í÷ïvFwÈè­@õêÞO¥G4·ø#6ñ({°L÷×wñÃ;^ÅÛù?|_=õŸª{%&òNÑ—^ß)Ö”v»ð‹¢ë¡â•iÎ'Í0¦´¨' ×bdÈüuB_þfý±½ë&Š×ÕàK_7\9Ï‹‘ LâÐNœ´ ¦!]¶¯UìTêV;Ó§-í¾‰ ¬MZäTé>ºç…ùOžY¢I\k¾ýWï$ݹØ•ºì´¦K\Û9 „È‘U ùV/|ùEñçÆ‚&Kaº\œ=R{îÕ¤Ìê_¼¿«¤·ž¥Y¢eâc–6Yž•åzáx¾9„I© 0µ„»Š‹Hõ¸?`=-6×íÚfxä›>‡O»}ÇõØ>Õ+Ý¿›øÖ*M·]HÓÛa©­2„4;GªÛJ†#$ÈÂA_­%io¥ý¸•dÛ¹åÃRŲçω'/ô[âÐÖWù…çðüÙqÏñ·¾š$Õ@׸O¤tq³žô]K› j¹ ·s1šž<2é"igÄÚ Ñ1*öÿþ,_è,ñ3¾…‚ú0 ¿ÆEE©mLí‹ÑógúTGM”‡xs§I™¶‹Ì+â 6y4{¤sgY<7òܩ֞‰7û-jšÎúZÆÏ {^î#—yø‘q+ÔåÕ*AYALR[õ‹#SìçÂÿâYöÍsòîM“éÒl³(Uðí¿OãGéÚ'ê;âòR‘I|l®ú`¾;Ú£ì”ïzQÜXö6k˜O:'5¶.‰Q"»>/?íÿí;ƒ‡m[òÔ÷.Œn=d°ûöÊ/?K5«Ý²¡_ã¤_hB}.jÿ‘vwH!CUþqËöå¼Ò@±ËQ~áã‰ú`G{õ=Éñó& kiœÇk¥ §èK­ïìØpį ä‚q‹‹™¡ë¡« ÙðÝí]z!xvå%U­Vkª$l5¤Âýúºûw¿±Ö¯Sæ¤ö4!½0Ú±tWC—8Á Ú§t`"…çì£Nqz®ÿéà]“3n¯©øyóïŠÕ]IÐP?!Zy¥ž6A]ZCæö…¿÷¥Úå»$”™r7ôÀ+‚µÎ{d„]åñCì®’gŠX˜!•Z›@ņ_üÄðqkU.õu£ ÄXdᬒB;åÕÿô;v>\kkSƶd(DÏÊDømÔ¹ŸTÃ]5wÊÿðßõöÁmšù§&†?üEVôuNÜš©PRhâB¿¤¬ÀD%Ô¦¥…5t;ˆïB½ÃF1Vhz)ÊÎÿcwºžì,Þ—z< IÓ™aaQ°jä }iô­MO„ÍÌ- »ÿQ2Ö¡ŀІƒ ßõÑR ÖA¯ÁF·¸¹¨Jc•jM–…«Fÿ›g-ª';K#Kh×¶4´ö8 ƒ’´y€Ðs±€œ9³Þ–íë}ô¡õ®&sRßZ)â“ä—?qzvÍ+º5%CÇ”ç÷µò«ÊX˜›‹¾÷Õà‹~,¥pùn€G‚„X%Ù0,_µ%Ü^'§Oç2(4æeÄWlqžß}D>•pÝØ®Â²‘¹dJŠ’M©ÿñ4²Ìnì ¨«N&ý`´¯Úg]ã$UÌ@g'=øtðÁ¿ÛšÙ’a/º×ÁÙñÞ¿ýmžìfŒÂ©=ð0 Õ%C"i/ ›š;Ç7ƒøÚ¼úM;1â¾:XÉFÿòWùÅÙXã̇F˜‘€½^Ði#3†”Eoà„2±EàÝÞ0“‘|/t²l1) ¨œ|,ïÐLLy}q$üðJÑPeàü¨Éfl4ògmíš!Raíª¦l´>:9úOž ¿ö¬™-Gp X5¦ÅÏ?O7rÖK䙳|pÕîÉÍ6©ÔNòÏou·ºMh†Áù³vé²ÿê›Ó‡úÿæ²-‰%YXf¯ñ­QkÖßÿ¬èä£O¢mmÜÜŸüh8»i—7ƒ™©âÐi÷ÁB«ßÞyv¶Õ3M"-PHGSutÐ2áÂi‹”²ÀÔŠòE8(èÛ¿¯‘N Ô œ×w¾ð½7ÍÊçÜHYš­¿ûŠéHW*vŠá(±3PÙBÙæàCÈ‘åÂpcúƒø³ëêæBô`½òË«ùÿò!~új¬Æ´;jˆEzÕu°ÚO7΂‡."¡¬¨ÚÍ1>iä’* -·êÄg_ÔÛ^Fò²t(Yˆ–Ç<ƒ„Äîÿ$<%:ëâá6Ô<è¾e:D: ¦ÐNÑò4sÙHµzbÐtœ$èé0BlÓâöJ¥24ë¹2 £c‘Ó’_S¶;H~ëd^?êoÙa? TI¥”HC¨«ëRVÖµ~¼ åWî±qb3ƒà·µ’[ÓaJYD 8'ŽÊz›ŽÍc¾c@¦{,+òú÷Ésõžûb1üõè—7ÜÂŽcèrN#Ç(°"4D|×UÆÌp¸†_±R©ï¸Ùƒbáóágšî=íçûhl„K[öÒ{iu”–œ× Íü¼aª5DJd'd—üÄ‹ÀÊ< q$E«œ‚Ù’w¢á­'Iedäû¯=‚õðꯊ™MþÅrZ:WV\§*©ÍM''`¹W®:Uÿå5½•Ž»AR|ûålbnl⨙>¨þÍ/èV*\G%öƹ@§b`ï¹àQ‘}øIP0ÝlÕOÌyþíÖ̺\X×sSêè…ìâÒØÎæÆs{üAš¦š")”±à²w¡žrÁœdŽ(éz16Ö„}IÞ}“ðF62å¡VhÄÀy:À÷ß4?¥€Ž…Ÿ½ ñpyPšt‚ºRÛÝa(0`Hs¦=cÛÃèóúæ|ô`£úæ•ìß~€Ÿ.ÕvÇ,wÈ®ºìŠ3kŽ'À´¯Ma=ç"á¥4²HÆ*zs‡Ž6# ±zdž#tƒ‹Ÿ#/MmÑ‘%å"É”Óq, È`4dôÇô¨(¶úüþ–­2Ll¨H—•£U;r<>à°7Yk6œ zèÇÎìr5¿T S½í±Ë"Ë8Qb´ä²Ìr0fÆ‹{VžÛo¿~6iòço%ƒ^àÀh``™‰8:ÙŒì¤W%¬q›&Åþñé/?3£ÜmB¹ÏxhrÐÖʈmËï»t,fT›Ñù5÷é¼½|Ï^yPýÙ%ÿÍ+æþ¦¦à @u,÷õaßÁJÓ$Û€õpTšfôn‡MÌŸÙ÷?Âö#¯yÊÌxE@©´M|´k.¿KGÆz^ÁÌâ­–Ë#ÈaÀ?%äï\±HY™ÅZ‡9:åÎUðd“n “yBN¿€IDATÊXåû¯®ºMrí×éÜ&Þ›Tò«nk ‹ ÆÆÌÈLé~JÆ÷âá³Á›×åf_[^ô†é7_R£{êìO¾Æî??ùtŒx踔zôÕƒ»ÇÎè¹#ÆþüÏ~+í_5BŸ;¢×¯’9§—l8õDý½;ü­{(ñ¿ù÷òsÍPÈÍ-»+ÀzK#RUÜRfw¹eÚMG¥fýÅÆb'9¼·òÁ¯ܑ닓qÍ+r—“ ¿ÿ±I/{û vWØ­•lªÛ*ý í¬+`8Œtœ†K(”B(æVÐÐ*Œ¢ÂͯõvsB#áçzºž¶=‰ê…PtóŠ·¼ÅÂ}nÏïG¿ É-„­¡×Õ–62â2…Üy^æ²Ô‡ekŒíƒ5TêÀ[¸Åmµ+QJé;k=†N[ bêÔ}ÛVJ;(éRH;‰n S-cÐi\\ä7á8ñ²¶ÉIØ:@PÛR‰,=¤×~2Euú•ƒ¢÷ßËåGµ½ªð)>0úF>•FÕ2BlœUˆ¦EÁ—Ÿò¾÷ZøØ)÷›«jmØ ´Ê{.µO¼Ðfê0¹xÙtÐ+ ’ðÆWòý{jOÛ»ÉO¯ù4¦£ç÷¦3cµ8ŽçuòE |åœVÐzýàî±Órï\uüÀà/~UYî ÀÂC}á[¿“Ò¸Œ¤urú‹UøÙ• ªáŸ»øÊ+s¡¯77T ö<*#G”¬Ú{©Ú¡ µÝ'*A½‡ítî`í£_+w[®/LDUo|\æ® U~ÿ¢M/yÝ]t׿c;õV9æA'“¬d##’O°xó!!–Ei9õœÂ0ÜÊÝüz'y^®÷ëY×zó]Ê¡¡´¬†e}GI ¥Š5fuK7ų/¡¡á¦Õû_`—¯˜ÎPö žÓâže¬©`^w¬ÁëÏà,‹Vr:9t|ô" }ÏZem„eð T'œDvßã1š"hˆ×T­/»F=°À 0“ä€NxÓΆ™%ß~úÖç]3:!–îF!u¹ „sI%(ËLƒs!suõÚ×GÖ{I=çþú—Ì$Y&`]•Ú}G­C$„'9Ø,k›pn´Ý‹Ê™0²“ñù­¼‡ž”ydñ9¢±DDW©ûŽ«”nÉȇ4%¤à5]Ùn][îí̋ǴMû´à0rˆ•Š¿´$¯þd‚.wôËSñçoeùǵQ[xîYõ£Ÿ©bJ$€eY©¢!myð• ¥ï¼HϤ¿»mWÓ~$x+ÞsÿRç¸`ËœL\0WïÆí\IÓÔƒü;o£³å}gúívòw_L¢ ÅÈsjvưoŸ——·ùÕ»êéC…E§¼~†(ZEçó[âgŸ1u­5UÏ~ó¥V¢G]VrH'å_üµ(Tqbjæ™vû+ùˆ«9Q¥‚¯>/ã%d\ÛòûœW3»-L’ÁäGŸ÷GvŠ£¤n°{ï6-L6w>}-¼G{ÅFßÊë[0nµ§Ü0 †VØkÂ(wˆ³Øé»„8§+%a¤\Íó~™»=´2+Ý\@2‚•EÚʱWàüžòɉ¨& *j ±@-±!C ¾Ñj¬Œ[ZÍÝkßðýäfAj(Y%½œ ,¡èL‰€æé'aÄ7~2¸³*#±Òn[[—eª^+¹s¶1 žGƒ„‰¡öôQ5φ–Žƒœ¼r FÒ7û4?Ï̾· heË€„øGÇ£%ùÙ;ÅæE[Ýë“Q²¾V2¬:tœ¤6ôüšìJÓ뉱¦úÆ7g§öË‹o“ÏÍŠÛ–‰¼0Öc]ìøh$O™3Ó•Ñ’è¦j ²ÉCXðÙh¦Bƒ Q¡2e½0ÖJ‡ˆŠ°æK‡4¹z>­T æ§Úú’÷ܺ_W å¼ìöd®Ø{Ò^zÇÍ¿Õ7í½Îï'ï˜fov\njŠŸÚ. L!xIè T¾|¢öí'«œë†“òέ°×3k‹pö;:[ÜY¯ù{ŽÕ/_Kv–{io7œ(ËãcYRPãþ퇺U2Oe+ÞÄd~°9°Ø¿²\º>{ÔåNvÛⵓՈÐÏ>œ·ÿá"Åp¦ËîžoÐÖ†êùaioð¯ÿ\)©ö5F^~5í=Ôµ‚Ÿ?Z/GÑÂZ_r€„—=×Wü!%Ö¯µp·e“d0ùáçýZGwUã:÷îÐÜä{OÃgïó…wé!?¿¯Åß7ä\B²ˆ \׊Gh÷9å}mVF}€µ¶F0ã JY bnçhyV¹¹>¤åe&s’臭žŽGK1Ê 9w@5袧ž(“í!­Èô•¯’£ç+ŸÜ~x¥ÒÆÂ¡6A]Ë ¯Ì­ÀêéÇË#‘ºñwêÎZ>2†Äî.:, e _*—×ñõ<æiË7‰â˜/@ʼn‘¬ž¸ùM1²œîqÑy‡+jY‚u¦àœ=p¬>ÖTSì|¡£ÉJ8'—œûý"… ] rãDxé°ðö×¾6¶ïDñÉ»æâ‚ í¦ó%’ˆÈ‚¢æ!zŽŽêÌŒ;1UjUƒ¡Ì4x8qÜá’MUÉ`™—)/²ÂPã"†Š‚gíW9¤ñ>èŲ¨å¦Epƒ›8%9&«Þ¯˜Š)г»óafõÁsê³ßÉùߌݽÈûiöÑeÝèï”뎑xã]H2í"$Z¡_Ž –N_:^ýîS£^ЦòW«®]Z€3OÒÉ=éüzuï“ÁžêƒO³ ÔI‡NVÝÉjÞU¾!Õÿð!mÅÙ¦VÛíÉI}´eØ>ÇÿýÅ8Ùqÿìõ.@¼ºÞ=²‡5Ózù¯Þ¦;½ôÉÃ#6G¦šéKûŠòH>û8o±ÿù‡Õå"©0;YŽöãí?ãv´¿ù*~ó|cå~¶Û-"î°LûÜI·5 -È[´š,ÂEΗ‰7s`´›u:ë¡ÊË…Eš›G\ì-ᯂÆg2=­ØG1ý8ÑP*2™p†#k*Aãc‡uÃÛग2¦E+«aüÒ5dðõ'Øÿþ«­ç¨§NæçOÙ“'b扵eHc ÖqE-<'4Ú–GouÌÑýÉù_ýƒÝdÒio”»ÐHíGÄÀçckÕìkßõîÿ4:̓龟TèÄ©þå* ⪑ó{²åhÙμŽñÙფÙ¶•“2tÖßñ‹’7¨M(ïX^Ýã*Ëvą޹mY¯á>ÏTöÚ+Ú< ÷-ðñJq{¡ôÄïñwº.O8…”²`²ÝPqŒÜö}xòßÊ{ö;[#¦‹Xh^@X_S«4]ðòóâ¿Æ¾t^=sÈœ›&¯žiX¡nmö—…i¢Êz‡˜®I¥'Qô1«¹8eŠ÷‚hœÆ¼‡æV¿“¦À„4Ã5Âgb÷cÚÁYLè+ËÙ£a¥Äß8§ß¿’§¼ôÒþ€sü‹ÏãÁöîþ†Q W׋C{Òñ–ÚˆùßþºÒéŸ:<¶²ÍZQ鹃ƒÒt:uZNLûÿãŸÃІöŽÙ}­Ê¦êo“Î×¾â¾y,î.áF·…å¡JM™,¸v F¡JÒiS%)”&B.SöÐx/ë´×‚,‚:-Ì¢!‡ËÞÏyí&3'rüЇsG+qYÇ¢µfRMÀ:ßé¤jÙ œôÒÃÖŽÊ£ ú5ôí|í¼øï¿Úzþ@qáØàÜ wòDÀoiѦ!óÁ0í–ù.0N5ÀÝ첓ʷþ_ÿƒ¿Fh¡êò˜f’¢üqO–5TKÅW¾kîÿ¸uÄëîïEi긼r[ —]-‚ê¾ =¡i g_wsÅÌ12QMÚ †:t*Úå2 ’樦'³Æ¬Ž×䘡ž‡K²ZçAÉûºxé­Õ÷ß¡3‘z°ç¿a6îKÛ—1÷¤ô3-ĺÏÛ™!qÞ¶»:û׿&MÔ…œ Ì)„Ši žïØ+ÏñôUöõ êÉCö±Yú© úúFï¡PÅÎ’`UË×$÷-ñ{˜U]IzŠ(û«ž%EÏ™ëaønšÅ…þµÜÀ¨UåoæK7lD ƒ©ƒQ£_ù]î*è)nkŽ«QgVŸZ÷©È «2b)³9>Ù(þ/ßo<~¢xðÙy?\¿•F{ê7z½AØ÷åæbõåg‡‡Ÿ%Ö€øô^°“Œ?uw¶ò•?ù|ˆt~­|ùöîS‡Ü—Ïê÷¯ØŒ±÷2št¢óy½”?6S«S?gÐÎý‡•kòòÎðx¾}f@ žáÔwE=’Ù_¼ß¸ÛÙ¡Lå&gwóF,Ö~m”.ÍVT ÁÎø]1õ•ç¼7zKÁO°¼fLAw)-›¤Ù©'g¿Ú=ÇàéðNµFP´û‡]êïn[÷ÿð͵Ä1 W•wß‹ ”Ïæú0ÀIÆOc³è4ËÊ ÷@߆„¨èËOyúrƒ³^”º5ݧ þä¹ì;/802@à‘ƒœèM¼€†tõÿﯴ7AV ,òúu›WQjm-ÿà›£ûùp|vë–ŽŸ–õ¹éxlÌwyÀxvØï7’º‚t³T>pŸ+ÉÙüêBüw|þCõæ_eoýpäÊ=82#N©=¥]Î%•4<ô(q ƒ±1òؤˆšfŠ[¦÷vŽDï}KS¨ÄF·HV³-ÇD ·®âŸ]üõ{•Va‡k °1‚æˆ!Šo=Eÿäé´%Ûõ{Ò eÛú"ÿæÓ>)ÄCªæ)ö ºñH·œƒ ûœ'ž‚ÜZ¸-ZRî#\ÏÅÿ“ãוüé€úÈ0Â~¥{æ¢}§T9ß~îÛÞô0ËZ6 ›mÆÞ¢» Ýäjðè1J’ù„ÊïØbãŒS?"˜§Å /ãyäàî`íçgy¯csQ×±C`ùמz´¿"vƒ…[é(ƒ éåÊõòÙÑF­É²|hu®/ßQ"ŒŽîóÇ*aÁa7«„°qW]_ë¨ÁËç¶õûN0o×4ý‹Ã;í”{`¦Z‘ÉœGÜ>b‡«°ÛÏŠ;4¬˜-ˆë4×Á†m^wð”m7t»‘žÎk½Zzæ»!•«‡Ã…,zå. dûéV²öšÔÿwÏ]/˜‡ôª¤ ¼Œ@Îéü0âH6Dö>:‘7„y,ˆ”ñúãá?{ÉûÿñðŸÏšžùa˜ù»ãß|Þ“SŸÎ97€FÎÀ`r¦(1Š’(Q´eK¢VÖ®6Ô–W®•kKµ–)Ò"M‰a8CNÄ 95€sŸœÓ{ÞøÄ;îWíÿp}¾0ÝìziÒ£¦ÍK”þÚ£ñמÈ‘¦8GÀ,J74PÌû•þÁÅâ_\–«¢SÛ¡ån¨¡f¡ˆóL ÎË¿úµú.–M\¹%ÂH¡¯}l’ {6/NÑ×- ”nR²o?7gúÕ¥9ô·^û³üÍÄoüuùê¶{·~¨Ç÷ðxdA×=åv¬J{Y<4€Î׫^±9CÐMCãéž|ë«Ôáa.I`Óº†‚éÏ4©alsø³kùŸ¾W(I…Ìgí°ƒXê_{Œÿîcr pâ&im‡]‡dçwžò¿úé­àlň„:÷gl²Cb°Cgv ¡ÓTKeï³ðcC¨aŸ%ä)ÌæÙ’î¾Ú–B@½¼[Rç¾k÷ŸìzÎc_élæ¢*LÚrÀ«ÈýØK‹Äæ`œ½‚h÷vëoé,ºC ˆ…´£wíacBàÞNôã+£¬—dÒ-&Üx Uó«'z†‚íºs½[h%]¨VŸpë%u{–´v²{ªòñ½ÎÏÉrÖCá…›b¼¨NíõÿèçÞZŒç ÞÀ€ü镤ÈíÃGuÍ‘·–‚?y£UfÅ‚G"Ÿ8äžœòç¶m)&Î{ÄAÿúOÓ$cÇŽªóÛ4ÙLg– ŠõÛÂ`+m^µåÍú¤±X¬!<¸—:bD×0lÝùØ^ôM“´iMÈP¡ÒÆÄJ[9G[§… €PLp²Èµ\#mUj´%¶ªí ª·sµk8øÏ&T**‹óÄv5K¥ìÔ ¬lÁú63È,'€9W¤f++‘ß‚R«áwþR”zºGÂ*S­Œ›/LÿÉo‡Ë­h{‰½yµûÄ',ú÷šM”žtÖ;êâ¬S/Xׄ·æ7 †{Gòf*?¼¯7Rùµóv×pù×uyO±—nëËðõ3ÞˆßìtmIMŒTèw{˜ÁùÓU#Óú‹ ›k%—6ûn®ïœ>ÊÎŒ§MC%ŒÂd­¡ÿç7" åï¾È/Üq6ç·¦&sùã_ 8žÕá¿ûÛu”šÇ†µVù·ß=¼õ§—x«©m¼aQþ&të¬*î/7g¯Â/~þE6“¸wþ<©#9ÝØ(Ë0J´É‘Ì2cˆ|G¡ˆ9;*Í,ô{Å'üÂØŒšPòÄ$,E‹ÄZ g¦X@ýÍHb?º~An/ëÙÑó«êx¹yn¹:ãhÖÀ 2´3ŒI[é üY¹-ܽ îš_|Vž{z6ü‹ï·ï-¤ÿù¯¶}F ÛâœU\šA/(ʪæœÐD˜ë­N! Ö6ÖIZ (†8²É Kb0²&N`µ­ C­n.©›]Ž"û°häÜ}°b¯~_ôšÂCÞv$Í……4â6{†áïýʨg›Ÿ¯‰èݪ3Ö=zvgÈa׿Ou÷"âŠcc)ÅPáün]-wWºe¶o~ [3åÝÛÇÓÁ‚sn?½Ö]BºDàHH“œç!“ŸtSå Usà»þ¿¯XPÈöE4! %ÅD£ÖÜø+ëüFPÔïü Šî˜#.°lè}ØüÈŒèêrY‹†0Ô-¢ß9—œž²ùú¹I|ñ.nº•ÿÇÝþÛæ¹‰(ñ‚cöïð.TkÁsGì_þ¼øŸ>éþ›>Ø5ˆr€A’fû6=\¾_Z/­4¶sÇÆufùãǽ?ÿ´ýö½Ìq2ÇÇO„`Òú$r°³ÒŒ¯¬W–7ôÉÉÎáḕù¸È%i—($]ç/jøÛÏzŸ>(m¶×ìëáÜ=ýb£ëiëÿ‡?SžÃ2~fT•}ãÑÁ=£ù~Ƴ-”UV(ÊŽþÌ3¶ühT>Xnß»?Œ›O¥½àòT9é.ƒŽµ Ö¢mŽMÎ,’P#ö+ êôJD¯æÃã^šėNò¤ˆâ%d´‚÷8¡›oÇ‚†×>Ö[³å¾)sôáTCXEÑÙ=ìöB)ÁVXÇHc5ÙÄiÍ’;}þ%¶’®ÜÿTU6ŠþÃé©Wp[y?øqtó~ò௠ä¹BmB·ÄA²ˆtÝ/N¼T#2:ßYr€!à›y `‰b‹¥¸Ut”õ¦kµº¹`(%z­ÕÖ„[+×›_V·ÿ"mïh†xœ“4[Âfƒ3Ø;÷›Ã_[Ž›ïd2>üðòïÿ%´)Á6ÁF0k™¶“îÉÝz¨/^Ù®€Û»õ]Ÿ¥ýãщǘíP1|t/¿½E—‰ºOòi…2Ž¡9ÕD{/r…Io=…ŠÔ|-‘m¦ ]‚þÏ‘®ó`5û_løÛîÈ€ýÛŸFèª9ê“]‡Þ[wuyÒFnÀ Ðo<ªÏNÕ¥Xl€ÞA~ÎÑ¿û“οü-úø¾¸ i°gR‚¡Õ‚óÄ9ñ¿¿üñGY½OïãDsÀFö’µíÇO/^J®mõ¯$]àÎĘébúðQçÏ>rc›èm9ú'Ç:özssRå0¿îlµ»ð¢èw ŵ}Ò ÎËœ?ý€ÜìØ/íÏ_y2úÛbÈÉWNÛ«b¹Ó•ÿû÷TÄ4ë8¾ÿkϓ믹÷_‹K!ÿò3ñjD ,*Lõ21 ²iùîÌIÉ]%Ÿ.'íÜnxž½Nò Ø7œ“[ª oû1E•ª £JˆeJMø S¹À«Ìlfô†‹ˆÄìûåZ§èéf׿ý–Ú››­eá•ÇËÝÍeØùð®²&u‘±ÄgÊJ_V+ˆ$í°Ò8Ì/ÉÖûh¢éݾëúSÝõ­ÊïGÖ¯§ ‰ÂY*»½ñ•(i4q£¡…V!ŽÌ<Œ1¢bÖžM–¯‹¥«"^PH¹,4†ê(cÝuݸ†Ö®Úíû’E¼ÄÓið—uîc•hÕØ«;áFåQEh‘h•£‚ 3ÖÞ¶Cõj[w¾{¶ôúÚðò.FÞ16-·ØÑÓ»+F©úâ¹Ðó£2 k°ò×ÙÊ&>„ûBÞñá÷#dÉ7ZBÀ5NÎÅ£Ÿ µÎÙ0ñ‰•¹ /‡èS—5I‘ÕȆp ‚™\ÛÈÍ"£“ÒL#_¾žó»î.öDöx¢ÜjY¢Qše®€={ì¿|Y“µþë?éuáþóì½Ï‘È»¹)~v_>¹ß­‡QžT¤Ž/Ü®tzíÿöÛ‚äáÇ+6íðgö8{]¶;öïàÕËY"Ñüƒ;˜+¹ÆL*]ìiª˜Bù“šžaæ…Ì$Yîß«Ðϳn`QFÀ êX&˜Î´í:ùQdTVZ_˯O‹êMw„LžÿyïAS$:—=/7»wñ?ø’ëôîßv¶· ÇN{oßá*݉¨wå®}â@m Ø™—Šô³ûåv¯ýß7· úd]¶›üé£Á›—ÕfS|÷¡ÊJ§&ìÏ>•Û«ª%ò€æIUJE [+•ÕÕˆd-ã_¸¡ßº^¸“®5‚—»½Ã•ûó-åV†Ý.Ǽ‚|ä|ïýÞ²÷¯¥ÜÝŠqÅ/»úË'‰ÄyGöÿÁ_7¹ê™apz*꯬¾ÛÛ".—y2¥eyEÓ>Ëû$ƨl5¶ (:H¡®U € (X„µ¾b¥½T‰øí©é–+x·Ï¬É¦« m“eTtR3êÍLo>U‹¯¡‚d]컇ѥygyY»ØÌçÆ¢ %FVKëX£ÑCSd¬ž"i"M·o)GXUâ}{3†ŒW´Ó‹èâ’ $HcÍ0G±Ñ»±ù¢fU„öu±è;‘ê.I³(5„" ÆXPÚðBR˜Ðû ßF¬z&€ÞpÝ«¤ÜX„­$Ù§žù÷/G[ ÷Ú/ÅÃĹÓnU÷öo&¬ óȪgÅÉ]}¥BêSçâm³¢çÆÕ¹cáƒ9þñ\g ¬6„õbõågÊ›‘íX1O^]ÚØN¯å¼_¾ûIõT#gm“õÚ:üø–zëjðþíle»Ø°Ô‹§Æ†éE’×Kþ¥+±SÓqÿóûÝ#ýÕùMÝZ‘¿¸

    uì¼ølÞïC!¡C†b…3Š,låÙ¶Gœ*ç]ž)AHbø²%+Fh ÀÆ+0h OHúC^¾­ÜíZÛ? Í‹KUK/óDkƒ±3 M†¨DÚ#òÑ©r7·å:®Ö+=·²ëa¯>Ùˆd¸§@Þ¸–Þ\v¸ã#™{Jhdp‰ (㤠ûð)’)¹eÉø£ø³[z~™Išd$—ª¥ÒfE†eîö›ì…o'6oßcÍ-$¯crð=êÜ¡Ù}C—,Ø`Z«0ó„?~]ӛ̽Ñ=†®ie„0ƒæ›_Ì‚jqæV§ ÜQ›…4Ñe4·2Ç:Èuðt²k>ï¥o¾ž .´LD!DÜj%°µ¾ˆÆÂøéx-÷‹}©?PIœáC‰ÚËR(ââ/uv€Z3&£\è ómÖ?(ââYÙê‰8 P?’—"«¦1 °Ü‚ Ö 3mû ÷¹”j)j¾ŒyñMßR)UÈ5(-}RåëyPÅ“cùòŠºyÖW>}<ã\¾wߎWÜcC}÷7JW—7OïeåbtmI,oé—N9m=1Н®¡Ï|‡í6°½õãà§· ±V2¨K,)XÝ’&¶¹äV‹c‘£q–™ 4ÉÀÇÔj£±;Wï¶/^×K›ÉÚÖ`+E—¦ñxÍù·_N<.;‚¿z¹=6Fž?Ì6Åø¹\Ù.=·»ÏZ´•Ã×ÏÉýñÌt]DF%=þ¤¸½Q¾ø‘ìÄQJ-…¬k3µ…TJÙ sK¨k¥!Ìi³ lÕ e‘ÄúÿïÙ`8£¯h·æ½<è3ïŒØì¸õÌêàrke(q‡¤€$(‡êǦ ‘¥:© ‘ˆ ïz\÷M&±¡ã.~ïZz}-p E“¤4—Ò€e!®æ›æ±SX ¹¢`üiúéuµ´ì%Г\g„¤¨ãf&*W¯fâ—¾U8qhëþ´³½¥17ÜÃä6æwÀ}l³ycç´š1lûÓTݰø&7¬s‡¡kÚXƒ…ÊúÑ7^1^ÎÞê´ ðº:qJn¦0Ç¥¹™kJI$öžÕ+=êå㻊ïüÒH[8liáΙ5J Äá™DõBïéãÎzÌKý=¿>”xŃó¾1‘'´ˆƒŸ]Jæ·°”3ÏŠ˜ùsµZ­xÇÒõf® ?9»¼{8Ũ±‚ƒ­EÀ5 X‡¸™ôÊÊàÒOp6eÄ Ìœ"M9Ø(ÞIXÁŸˆ‹:j Q.;¡Ð^¸-ÇJôðpßòzߏ{¾Bzy%_ÛpŸ>Vö ñĤssÛ{÷¶µ¢Øi³Ùí}hð¹î4jʶD£R§ 7JsËĵÒ]kÁbrkV@(E‰ 6îòŽRFHuòèÌrjo”þ¦ÀŸÝÊ:V«…Þú9Ý0_ÜßùÕçÓÿrIrã~÷±`Ü‹ð~ëÅ#e¿˜ø“׈}»á·N¯®I+Œ1ÆBÇÚ\Fý’°Ð5 ¿fÔg4Ó꘠¬1‚5¡D!”Kü¨¿ÿ\öâÉêšÃº÷³Kœ¯jLC#[#³NMåÃ岨Q4hìéVkq² }˜^Ðß¿j[=4ΨÍ\@-bASŽlÛd%ÚER9¬ï™/äÃÇñ|³òÆ…e rDOk¹_È£fÉe eJ|㣣˜â( îí{¬8«àn™dÇÒm-Öl!Ù°¤eI·LºnÓ$×QÞÔª$6þXPH¥úêÓ¨^“Ä)UGØ­Û½qëÇ z©ä…¢Î„ÕÆwa½²)&ö{Iî:`?ù´a±‹i¶(ÃÔX F0µÀíÙ¤+íž!g°š¥›vp$ëk1’³ž[)£õfúýt¬¬d,Ô"¢´:àŒvW æOøïœãT厄xM¬yî%H"Ë8²[¢ÁeØÃLI=ÃDËÀîºÚ)º*’+.b›µÜÓðl1Æéê–þpºl§»¢tïcCýéÜÄ_þØ4Mëh?üúSµ;I’Bˆ¹À^Gi¢E»eŒ[_vÅJCsM-(ëXÈÆš¬ €¡Ì oêÑøÅS¥-êçzÀK "%#w«ò NN8#¥‚hpæÅÃ{ò¾Z’nâZ¯5ý¿º˜ïD6Lõ8¨ aml”¡‘=mJ¸eLNYñéW`èYjo]è ‹‘¯:€f~i í5 .”Ùä«_ï%Ô&Eêߺ‡«¡³"ÃMm#±mDä¦ ƒzPÙØ´ùºËFo€ihè"!o­vuô…ç µ¾ÜeîÀ@éÆV?u,ÂQš{nY¤+Qd@±^ßÌ' =ôb>yÈ\ü¼<½Ô²,YP‚‹­AÈ–ŒÙ…±£Ý6$qnÆØhY¤;fp¸Wëq³«õfû‡Ù®1ŠC¨hF-Öê,‚Ó@3cÔò+O…î¬tó|UõŠ•òBÀR \J=Ì´RÓ\­·%Љч2™ÑÈà‚†œ( Dü÷ϳÜ1Û;Îû7‰ôɳ“¸dÏ[,·Nñ³+bK ýíŠ:—Vœû7’SÇFl¡|ùæÖÉ3ÙÈD]éÖ\FnÏeI¦–º¦c`È¢â%¤j-¢ -5“)9Ç`œTÃ<í3¬ì’L[ìXšûÚ(_¬<é– ÄHº²ˆ~QikÖ¶ý é#Ã7ßÙ¼´E¾ôþͽûkõ·ov95ñÂÞõ†ôû¼¼X;ÿËÁŸ\ÛTØ×:ý7_äÆÕ»8› ŠIËÌ*†„»Ç’‚4b•‰MË8å{¬çôˆªj5M1ݶбh°<üMow%ÝÉÓbz°£Ü–=¨Ôæ¥F÷ˆÎ‚,'c¡cˆEûMär’WÇIZC°›TŠiVÓ¼äp€ºŠgN†5ÎŒ'ŠÆ:'H09÷7äkŸ0®+Ý8¼6ŸœÚ?øö{kŸ¯¾þ(ùµW 3 …7îu;Øÿ±8ÊJ•r^(Å?|µøãÏ·2‡k™ý£Wè‹ÇyyÐ\¾#…R†åÙeБý¶ìJ9ÇÒuM)¦»µë]3PÔ,¼Éuǰ ïѯçû+Y+Ë‚!q»iyC–p;©6]ªQŠl–²[éÑqUˆ¥n¦ó ñ´Ûù÷Òë«ÕRïò”K}p¨y ŠJI˜‚¢Þýøá]‚Åô¯þº·†ƒÈäÚ:)LK"Ö”*Œ¬xî©r)k,üÌÙÉéíµ0nu11¹– ùÔPJ„˜Œ¨”ê˜ÉÌH…A`ÉM@mÎÆ¢ã+/Ÿ½™-¿cÝA]&3ó”?1©0b\i‰]§‘‹œ uîÆg÷Ä€ìÿúZÆh]çq»hPæê “Òì§þ)†L:»Ý.÷bybT†ƒ¢Qé›>d}Çü»7Äú6×®DR Êñíws›tuÔ<ú2íf’>\™¿Uúe§±ìb*QÍâªÁ=ÇigT¹«\ƒÇ‰ÕÄQÁûž½eެå:0F õϾ=ôô)]÷²_\FØ)ß[lu6*?­‡ýx'/ »íílìÁrkïÔÀËOf“‹3dí~«È\_ývíf÷ùqpg‡Æ3ÜMm ¨ài¿OÅ]6·EØwFê3xÂ5^ÚKù €ƒ:?†¼}œOuʨ£éƒ-]cӮŠ ” ð+äÎF¯¤`v'¼ÓŒÿàùê7Ž¥ŒÊï}šÏ¯•óls¤*uUÞ™«ýO W-°¯Ì£GøÁãö“ŸãÀÉì«\YNiÊ|æ%·yý6Þh©#¶ò$S2apβIÛw‰¶KÚå8ÙâI½îWL}¾¹ìä;€3b’ ™a®È”çhȺíâÇìB1¥ˆÊÃK7Õ|7»±¸¢½G³#œ»"/¹aKÚ&ÖžI• 5ýw·Ú‰µîŒa>dÂB!Qƒ6ƒûÕ³'²…ž²qÞäÝA„YÌ é¦>Ä(•Æbê}Ĉ̙fh®ÁÀ6Ó̸!P§dˆ4¿VØfu¦rìK;y*Z´l+²«!)\ËšVùÈǶ3³Q˜ÏƒõÙÔ£iÓÅIâlÛ˜U§ ÄÏdÕ«fYÞVùrÜy&fØ­N¬×HØóúÞ’Ëk5ãÄĸ(K­uŠF½ÂsW9-ÈDmhÊkãÒçÛ•ûi¿ek„tqú-S9Åõ0Òi½‡`Ï<Ôû²måg .2ÐZ9@©@64¿óR=LÛ×>öjÇÑñ]0ä^»÷áM1^*MLõpWÉ>œ-Üyn °µýñýt¾Íl_Úîͬ»RJb c¶ç+šéàfR჊ž§ò¸AÚ‡ÉqÂ÷´O'{‘=©ð„–“Ü9Àè~•ŸÖâ †] Š-î8=£”£ 2ŸC޹ÒÄWgSÇØåØ½·ýãçÝïE£7®È™ïËíLôË ”wo×þ?Õ—16àKsv/=wŽ¿ÿSðÐÁÃõë«$¸HË™I¶5öq2fÂÐ.S‡Låiföèl”ÓsŠŽAñ2ïú2©óÍ *ÆxUzÞY-F†âpÄÆ3ÖJp]™ Ç5(ÚÞÇ˹ñݪ0¡¤Ñ÷Á}ûçÆ×æCÇvv>Á+ny.Þ–º¹£“LxØÑe-­² 'ü亿ÖΑ H'Œ;b07ƒt¼¢íîÚm¾x>ý¾wJ+Ѫ´Rm6¨H䊤²JcÇJàˆr)™1Ø€BÜaµVNN˜J‰ÂúÐJBŸGLÔœuŽ}9éD¶ÝˆÊ–fVTY0ª"W’è"ö°î­ÃRV^™I*~¼qWCÔÍ,Ñö g,K+a)OiÛÆ =÷Òῌµ¢™9oÌgÿéM¹²VÓND ÐÜh„ Fxјm§`Ǽ‘½ù˜ä¬/\ˆKKQ¿–”M¨ú®zÈÓà OKu4 à¿,|bãË¡Éa˜ÔÒÅ¿óåJ_oûó‹îØ‘\´ƒ•¦«ét}t5 ŠãÊä8GîzÌ´ÛÅN¢þÀùáB¾²]ÆQryEOo…"ω•¥yhQª}-—c–ìxœÂ×r?F\g7b‡T6Ž xϳÛÒc†æÄø†æ˜ôOâAÐû#{è0*m§IB-Ӆ̱Tˆ#©T|x4|êPˆK-“™?»ècÕúÝç8ô'ïØ?ù0é$¼DtÌJÚF¿úµâæ{ʽaãiQË:1øÉÝ.®<É…{_›²ÏËÄAÍF …ØÓ¤Í™è·õ8;IÄd6œ`>Ê÷)Ü_÷^uÕýnd@„k  dÝ‘˜nâ¤=ÐÝ.»}×|>ÿö^þ·—“K3Yd‰—ç“âA›R$SKbkRÈcF„–Q$-“„#’vÄÉ“l÷hºq½Ž4’½Ø—$w,³º75^øõß °ÔkÓ4Nâ-,&Ï”wxŸ^nqZyVæ5¬b(!¥B%P¥3T4óŠ©Tˆ«“¬H=«¢/?W,rïþí¶Ò†ÔÃãÉɇJ÷§ýn 3*l¦5­ ‰½c|¢Ø={†G‚Û—#$h¤LlŒ 0ç¢JÄT¶®4MŽUHÑ P‡‰ZsÌl‹>Qº½Ö½óóLßKŠV•¸p44m: “€gžEÖ5*Í‚wäÇwõï˜Þ5—ôš‘-XqŽ{uŽl"Q˜™`ݵT[«1B #«}Ì£VvæŒ35’öã¼6­¨dI+ÐÄš¸Òÿõ_s™¦«œ,M6P2t¤¸o²øÙç;Œ:I.Jt€é²ÂʱÖZR.ÖÈ€£Añš)ŒËŒ íiùòK¤êÃܽž”X‡}Ãó§#7g¼f7c¬”ã¦6P¬›}Ã¥ñjóôa32îÜ»®MêdÂt SˆbÈB‚w{¶Ì¼Då6ÏG¬,ÑÊšê4 |:ÿâ¼zË^¸Å¯Ý‘0@=‚‘p°fú€fgARªAäÉfÖ\ñ6xR(~øž`‚RÀé "î`’$¸/g¤¤UŠÕ8aö&…hAÄÊúÊÅ¡4â÷¿X«›NãUÛ·«;þî'ò‹7mÌøv¢4¸°ÜiÇæô$(y_ZºðÐá”U%C›[ÙÚZÇX°Ñ<§£dA:y)1£ò#Gµš(C½ŽEÊÊ€15Å–•ºoõ-®‰H™°ÏÁ,+˜µ‡…”cÐ:§Ç¾ì;è—'“­!Ÿ4ÐËÆà²dÄŽòø;Fceœµ^zs±Ã½’SþÞñØ^v`7ûã×Ík³#Óö‚1aÿÆzúô~ý çæ'=×(WúªRüÊz´è¿y/©XT¢ÏëÒ!ÕåÄ2+.¸f{Ûÿ¢~ì ¾²!ߌeáXþÄS´„â¥Uwëº{„c R)ð1¤nZ«pê(3\ t (ca“§ÆŒÂ–p†V¡|3N¼˜«.Z&5ˆ€É´%ü>âˆ?vž=yZì=VæÍôÀDýá§õž²˜,­v¹ïp;Ì}JUm7$ÜVOš}‡YÀÚnlËF¿ïX™µu* ³9¥Ì¤ „k©’°`&©RYðœf–Œú}/=»S¬b]“¶Ä‡NæÖw6ØoÆ­úGè¹=âégJ“åò˜×yñe~t:üìS ئ ‘U`…’ƒN™•rµÈ–ðÐFnz6N­SÆÌ‘ IšPÚó”Ò G" …47@>‡`ÔðtèCÛÜéO÷ Ä“»Y;O7×´RZ+ùïYç¿I™R/ÓÖÖÁM)¤jÒD>È"/4Óøß~¹úÒIsç 8kZ{bÛD?ä÷:éÊ&œ<ê|õLçã˜_i6ì®rµ­o/ñçö޲ìþá›K÷šZZO€£ƒ Êœ€ø Æ¿# )ÊݧÝC'ÒGŠ#»Ý¹›¦¨TDtŽñ¬¼vCŸ¡=Ê?±rAÛe°{Љa€Z„þZ}ÿѤ2a£˜4Ó—åÀ «™°*TM0å+q÷óÙJjAø_ß•ªÝþ·Wã_LâÿöE,œÒêrüôûâ1~ç³ÄS"Ð%S-~åa9Pï{ûN«¢¸@= l)s÷XáÓŒÁQ°àÀÖ^ïÀ öɧùÚ’ë›x;aÁùä³¶Bã¥ÅÒÆu~ÜÏ©AF[Ïr ê–…ƒ@'¹q4KK̵J)F3­iªŠWÁQ–¸Ü.›ð*ݧÝùLõŒß±R#+µÅ‚º‹’ÄyôçÉ3ò衚Ӵ{§‚‡žnï-Àîj¸Õ+„ûTŸ¶ñpçè;c÷äÞ¼w»¼™F®oM·¥;¹Í!ÇÔbª(€nâ K*g'Vcaí‹F}% }Uk}g… “ÍÙp•%IÇâ8zdÊyò²âŒù_OJ—>¢¡‹·DV!+%˜Ì˜žàÓy²Zd˸ÞP,%™ZÏ—é,áÆ"á РGR&9’YV=h̘Xh͘ëη¯ËýCùÔž ™eë«Ê+2Vu¾ùë55•>@ºÓr‹8Ž ÷šRþÂ\¦E@ÜšH™õ|ßÏå×>¦fÓºn¾AòG)ç;ùÝu|bÊÿÊùÖG÷`zy`£!öH7ÚöÆ"{ljì³5çß\¹ÓRR»c]®ÎíA”|9 ~%+5!U_ð&N'…ý{ÜÕk¶&u„M‚ÑŒž³€cN$ʼn¤9‰/O\2F#[䉇kéè.ˆ·‹Ý-ßä¡dǬ:Î\bº1Ê5F`ñ «™éÞ•ÍDwÅã'+ÿË/Äõ­øü€ûÏ¿®v ˜?z7rRù{ßDe7 Êýk-ƒfòéte)þþµ´!CÍ3ÍKH6V0=n÷ål» J ©—ÕN:ÚnTi.m’3ß¡‡šª3Êe^¯{W—š¨#v›q‡¸êYg ŘVÉòÃ3±‡ÂIa†yy^ÅhÛf«6Žm’™rl%òsd‘f”H Ô*”y ‰ö…lÜ_xõï8W!^ä…*î|B¥sázseÃÞ¿FnÞÎïÌgiPÖ!4J9\H£ÆUyÖ2FûˆÈ×Ä7žt¿pÚæ´{|„¶¶³FÂòµÊ˜Q> GæcÕpf6\QjqÛýüfüчòÎMguͤYü•Çìó‰õ{ÎÒ›‰žVs÷Íî£ÎëïuÖ·˜Âñ––fAS‚­B¡‰5Ž•×Qm$Rb‘!ÔÀ#Œž"É5U#§‰DÜB˜ p¹É =…é£Üv$s6T¶Þ—~é¹2—*ðûÇöghY#»ÏÇcàVüΞ3daVRéI#•˜úKØ‘$Ö´hi–ËBQŒDQÇ•ƒx»KV?|¾ÐW쌎Ðw/¢ÅnôkÏ’—Žòî’x{-ºp×?±¿<7ݹ½Þüìfº•ö ÄXc³²³&…ÑcZ3äE¦ÛÖòàÉʉÓQb²eö>C’.€´ø]Çhë„q“ NŽ%â)S'»ÄhF vdg¸.ǧP¼]îÞH|‡Ò;ÉqF<-»F§V+‹£Ø.ÎÛ++Q™ógØúEtcM>T¯þ‹oÇû†ÐÿöAä¤úŸ~›–Ø)ö­5µé—cOfs‹Ù/.÷¶bìbRÐ&iBá Êi«ƒŒR_øUgÊ•¦…»åÖâ?ý]sø©òI.óúº¶ÜÅMà$hjÄrD×8k˜86‘ŒjíÕd|Ä#ã€}ÂÂx¡´ž»9ˆm“¯C–Ø85…rëKl­f„*c©µX8Vãå¢yboðã?ïðkB<àŪ÷ôSïÂåhs9½A®ß47tE±f+¢µÄ*åòL'ÞÙ-³¦±YØO„:ܧ¾õ¤óò)ú¹â¡wÕf ð1“É¢_Û•Nõã™ûÃsžoç7t/|è_»eÖWYœD_9OŸ$Úx —_7ršÍN'û{o}­n…ºÛ  ÆpL¬EŽŠ•ßÓÍm”õ¬Ê¢?ÂÝS ©2ÅžHÚS '9ÐÓÄ=Ïm[â{TKÉÕªøòó.dàŒî‹` f×èÁGÒ Å0™<í¬®¦&Š­ÌG¾í2ã÷IÛ3PÁ8‰@–!©Õ‰ šÂ=ö”W/·ûì¥kîRÔùî3äkÇüdÞ]ï}xŸÝ[ž‰nlǯuwrL¼5FÛ<„ì¬Í_Fø˜5 Xb:=Pû„çO$ÜŠÍ^–\&>aø€Y©d ë ÒCÆÇ¥Þ!åìU¦‚”DÀ5ô³¾¢~°á̼e˜cÊXßR9Iö`8æ†Âš ›+“1J 8®0Žý|V±øíçÂ_9×Ù[«þñ‡ù­Eö‘ðáÓ¤Õ”#ñø±r«BßzýÑ»uÐ@ÀÆwëÖº’Ly…zœöVÜí£†M¹™¸•~Ê ¹ÂüÀh¾ψô v3”e$‡y}}‹ R 6-f¼žª¶¨ó&6ÆJâºE©`oL*OBÈ}+yša»kÔ¼pž*CŽºB%RkI¹‹]IQPÐòšÚ¿·Ð»÷£]/·°WþË¿NvŒ¡Še4ë€Õ*x°šÜ›ë³¥÷/m¯&’KãÛ´ñõs¥ßûÛ5÷¹NÈåÞÑøÉ3E Õ[ ]ÎPˆ­b5S×?ÖW¦ÑÍùhcešçŽì©¬¤L‚ìò}::YŸ^Ü 7ƒq’E”Ø!þꛂ:º£m—[¤±2àK­=L÷Ðs‡œ#“&ex%Ó1•R‰>Ìû3]ײ²ÊZ1Rj ¡/Ne6S“AYlwe¾\©˜ÈÄÂ("‰_g W»)ò°£;Ë¥åÈTÎ2“½ZÜÙÌARPì{ô8å1š]‘ïÍ”ò8Ýs>xø¼([‰îëz}k]Ñœ}ãxißîöØ`03­>º›a_mE@”[àÌf6ò1/øóGef ÏCJe•’ùõêgCí,³ô®*[[±¸Nù‰aÆê*ZHMCðvcg 6ØX¨O’zY?Ø ÓoÒÁØpœŽ4iK;n쉢ƒ, ¥5„nÚ¼Ñ\P—§³@Ã?~©øíS;“aßý<¾:Ë_z¤KqYÑ–ê|ÊJŸÐ0Cx_’MiÝ_ d&:å¤R!nb þèhß7žÛ±6;ì¯>áÉÿñ3~`º¬Vh¶Ñ_¼žüÙ›ÉÖ6ÎH¨-ù½Wø?{*~g¶š ¥qY½"ìç½\ʵƳåÕôo~ŒÊ"Ê$•L y‘އ¼ÞÚôïu÷?IóëÍŠIÌzˆ,Z ¬Êék Ö°ý” :ß}¡ôgááA³{=uÞœŸDiC¯u¬¶Æƒª2ÄB†px‰Î``Ò <Úœ× ÓŇê?}­»œÈ*Æ6 ‹‰!ÂÕ µå@+eü²õ°%™czâ¨üó^ Ûk=à¡G¼¾f£]Fù®Q½åq‡:|AŠvMP¡Í\`ƒ€†ëYš7ÓšF½™…hï‰J4—$‰Ï›Ô<˜ÎÁ·SÌMŽuÁAnfŽÔã}ðß|‘ó%|dN×ôcûñ ·Ý†{-Ô@…~¢ŠÖÌJ<‡lf Ÿiÿ#^<ãœ=MrJ´µçÏ´;2-aŸâ´§d¢Í®úÁÏŠ^¡å•ÝwÖëË\ÊóÎÐ'y·lú´î`J†Í~[Ôû.<ðS;›èÍ+ÝvƒŽ ùåšCZÙd­öÙ´]ìñ]àzùÔˆ]^ê›îFÚ  t-Gª7æ©’:RTªÿ^Ž€çÛ5AËͺiõè¡âƒå¤½¨µÛÄ~J¥•¤keÎUŸ¶\CÂŒcQÁ žä` 3ù”Þ71üñ/Q¼hC›8Ú*ûÔÓ6xOjö çþæYþèÞ;¦Ÿ|D=2ÎĶYë e­¥© ã‚ëÄ:ƒþI·æ3¼é«òùÁ7Î6….¶‘R.± ҂²VTRƒšÎðí‰cò7‡PGk ^ͲZ¯×ödgï¸ÓŒóÖvVã¡Ëu¹b{½Œ÷…Ý<áZXd—…Ni( O,Q:;+ö*ôæ;½Äa‡+½À>¸¯¥cb(dÂRaôhŸú½—Ð7Ÿ§GFÐÙ!õÔ!~hªÜhÊûmÝÀ¼Ž³Ö3"ž+¬âQiNðÂC ÖŒöŸ,r¼÷Ú:"uÛBZçRæŽÊþ½Îü¶îMK«í] —ˆ» c&ŠÚ’Ç¡0‡3¢Dô–kL̸ìw¶ºáüGë§x±aBœuþ!ËMÚ7m·G3e‘—æ‡K‹ÙNO×ʸí(½Ðë~¾ ‡Væè«W[_8aŸ<¡;Ÿ¼Oþä§Ñ½WnHq&Yò•§Øã»ãé¥à¡ýüÂJ”ÍdnYåq%•'¬Ý6òê"i|$GzhÎÆ»¦ÄË(Ã9v|n c'“r-Ö®'—7Á´Œ‹Ô’Õ¹á £Dñ¤”Ãã‹99X¥ÿÍs£ç÷u›ÛiÇ5QÙ´;Ù@AîÚÓwg5㜲ÀèØX+ f™ñÁv¤|ú•ÂÐP2ðhþÎ%¼¶*cc"®4 lµ"ýH€“’²/÷[C‘òVW°6ìô±ìx=Í sú÷,ß]í4Ûƒ#»m.Gö„7{/Z8H¾òTuþA¼Ò5”¤qªBA €ÚàÒ‘&M¹Ð쥯Äû!8Cßx'Êš¦›“¦°†2 + TàŸ|gx¼ÜZéÉ^I*`Ї†ÅTзÔÖ‹]ehs¸+e—:ÈJÐn’LjÑZGöôcx¨nÃJ¸ïdìÚ:&ÖU Ó^J8þ;$µzeVß\F} éÄ·¤ú9Š@ø)$º@ ‘ÿ·¯6·Ýþr÷¹·—š€•rÜ…uúÑånÆúòÑ¡¤§ŸÌÂÁ:+öëÿ×ÔÅÅ–™Ò%­ç=çQcjR¸ÆÜtÕ/°ŒãÊ Ú ­»®‹`Ì)-n6»E— “.ÊmÀ?bv Ö:ň}Vö¿ËE22f‹˜y £€]jú¼íÈY¸Ð8A }Xâ}¬ã˜´¸Jze ãZÓt ÃWi+SW@Mr?í^Yæg÷W²ž}éŒ~áÚiöÿôCöŸ~ܾ·Í%u$€’—Ÿ)>½»33K‘-1)Pd(¨tÍI+©:nC¡›Ë¤ñi>šä3ÂŽîBYq¬€ÊE}£GE±î÷f^Á¬mc½£¤— dŠa+®æÖX®g5¬è`Wÿ³ÇûÏìmv2 h¯œo7TŸ›ïÚ×?½Û]Ah&ÕÖ(`8€V®žy©oh¼5ü˜þࢿ¶ºÛb¾ ’ƒÌMÅW\C„)¶‰Wpä?úV‚éÊ2(åž9¦Oô‰\{NÿÄÚôrc«=<9¨³¨È½^^zp/7JíÝWü{Ï»ó7³ÕaLY…:Ö‘žgP’ѨqÎM|ù zt2,=ýòí(k˜Ž€¶µÖVm0«û¿÷­êX¹»ÜYÕ*Œd[î®${Ë••[h; HJé]…:˜[$±ö 6œ#u4fÎ<Ãu}g#G"’yJrDRB­KÞ»W°ù{ñ\#ô×ñ¾¤wUˆ×1ÕÒd µ¹kÿO/{ݨ:+þHíÆÜzè»1æëåw?kwvj{‡ñÐ`–iññ¬9Òï†5ø(./å¾=”寥°ó¢ÏÏ+=„ÀÑúN¨jò8.¯«Í~0#Ì«¼Ûï[Új4C‡SH§EjÈ/±]cÐÐ*ø=o‹äy¨^æÂjîÈ æê dòÊܸ\>&;×mþvˆ$¨²!s¨~€ûÈÿ˜±ŠFSyo— ¤»Åʹ¢ÈŠV“NÏŠÏ èÉ_eü§µþè­äóeÅ«êäÞrÒìu´za`à[eoü•ܼØç^›ñrù'B1äŽ %·ì8²L‡Û ZÙ_(û½DX]¢“¿uM¬ÍŒóí¼¿¢·uakšzéµ;Ò3Ƭ¶Ë;(ûêytâøÎöªâuÈ5‚n_PID·PÀ…Þûw¨Â‚áûX(ÑcEÔÙêÎìÚÙuDÿøíúë×rm„C!,·¶JqËôN‰û†ðÁ‚þ­_ NÕÚÓ™X™ŽC¦Îì+g,½r©½ú*é>¨n›êhà¾9]ÜTËŽœæ/Œ†vy7æ¥Ì¼f k cAk—×pšµ±šÛÂ(<ñX´±š¾þ~10™ÁÔp Væ&‹ÿù7íD¿“uÓZ0u‰¥WDi×Ô‡ba¼kÓѦ 79ï)m ¥Æc`†ýüió"¨>ÎÎgk›ºZE|ä¾ÖœØ­¶yŽýЬnô-¼AF,í×¹Û&d×'ŸëpM猀$Žøï?ã´ïFÓ¸ ³ù3g´Ú¼×îV1;qÔi˜ôÚRrá¶ŽRýÜC¯Í´¯,ÚkôÝE„ŒµØÏôZß4æp.×-{Ó. s³Öú:çMBeU&oãB&ZGÜZ¯o°Æ‘UÔ"Á d yˆ¦5†§u¥üªy¨ÃÌ)ëNHq1d›×Éq‘]…äûÄt±Kqy=“” yŸ§×qõ=ÄÊàqŽ×<±…‹¬¦jgÓY¹«/-p$ÿ¥ñŸ}Üø¯÷.-ç84gV¢vƒy²\øÍ§å/ÿÍNpJO„ËÓ¡v›.öR! ŠnR4ª¸©&`YÞÜ¢ÕÝ¥j 3ÊÀíYñÖU´<§ñ†®ëTÚ¸ËÆ¼|‹™†t8€´6&z ëM‹0Ê¿øyäh³Ñ§dŠB·0Xr•ËÞP¡õÎm¦lÌäÜJdÊf¨Bz›íÂñ‰ÆáÃøí·û^¿ºÕ3œdBzºnMª0vP§â n•“ßü»ÁùñÆLê,Þíu­âLÛ¤8¹úy´ýóbkVãÞðn¦Qòîåh}«@ =ñˆ|x/?̧W£$¢Ìx1µå™iR¥iâ#Ò>·Iá=ód»¹©ü.a«`¬…Z%y†4 ç¾M “Š¡âdÔâtý"ÈÈ­õ°+:Û`·|ÔSÂD­Ã-äù3Ž^•¾ÇÙù]ñƺ.–Ó>-]\lŒMM|¡2ÎÉÊf°ü¶; aÀH¿a=“7)¹Ãë ²Å×®`ÿÎ#,›%wÞ‘KsâÙÓL6Ê·¶Û!Cí%ë o¬ö>¾’mhõÌÑñ‹Ñ•Y{ùž½½D‘’xŒI½Ôý»ÆÎÕŠ%?Çl¹›c# A¦¸ê=^je[‡¸¿3º$7ömºS¸Ì /õ1èœY@ð Y%s€27äy:Œô¶Í b:0DiJ埃mµŒ¼”î€à—J¾ŠE7“—Éô~*GІµœsÜÊe«ë×'ð[Ÿ4.Þ£¡Ïž<šÿ³— Àñë7KS%óO¿Ýž«:7³Ã 6ÔÙ<)Û÷»Uiâ‚Æ+Ì•;iÀ;B’NÏ…ƒgc_Û…¹÷â–î‹•õtt’8Aß{wÅÒçi-ÎË’lá²M8’ …šf\–¥ÍªÌþW4<§¬–pí§dû†°A>ÒÏQUt}‘´ÚR{E¡3Œ@™Äu‹Hvxyèö&¼ÿ^›b{DçÊÝssO¹Bñ"É ª@+/½ìè9=ŸòSeþöUëÛ¼Û=G²>VúüJ°—L¾F ûO˜µnþöÇHÁuõ»9—7e´”î?é̯KHx†òLË6X(Gá aÙ•‹«iÇéÛÜ 6æšÒá;j'·Xa_Š”šì÷¾ôˆö³˜ùÞô\|ÿlé"ƒ&,€èyµáü“k&7yª1Xë8(OIö-ø¹Î!m¶Äáµh³÷ù4\7¯N0P¯¶¤ïÿ3ž´À`c•Ö5ìNP¿·JÔMP¦ô¥ƒÑ3Çk3?GÇ-ÈÒþÒ³o|ôÀkuË÷ÑìWŽ€ÍØûx}ú`Ó©â•UÖŽsJ™1\Aòœ™|E4vi¸áyï(³jÔ'•Rqßæ-/½JÊM)î#y±Ý±¸©X „&b™”2榰añeèYê+‚Ú¶bзgˆˆ4,¤þù.¬…ú/ŒéH¼HyNš™Âk¤ö‰ŠZÒn"E\u2‡C¸™˜-nk“-v>¾‹¼ýñÎdzÐWdÏì–¿÷ T}ýîµÂhÅûo¿eççkèZóµ‹ëúÄ“¶»m®Pjº¬sGº‡,'H¦0¨"Ïî-ðᓽbs+å×_u ÷dk] ·Tÿä–˜¿»Y^l@–.° ¡‰ &%Ú±Àj\ý—— äJË^ù±]»L ƒƒ%IPî»6·#«xQ"‹´ÄV1ê0Ý *ÕO7Ó·Þ  .€2ŽGpDr×pa<ß3ÅÄãåô•oä~s&¯ž í»7ÀC:oÛÑc²è—f?öë-UÓtËgûáµ¶xû‡\¹àëaÿV³»½€­ÏÎk-‹ÈÒ yØKI§¤‹9b=ÖëcbiU'A}y[,ÏjBœÜ´4sEàz‰¨Ðo?Ê "Æ]Xì>x«;{œ!øD ZìÓ—îè(÷¹I%ö¬µµ $ß5'79Äv¾hÙÐ@9méK¯ó¾µüòm/ðJ}å()èO¿¦ßÐK鲦·héÛ!”• ê_ؽüpýÞÏzG­)éV¼gŸî^·Úä»gìß"eˆ.·ÂKsù'³¯ÊVVy;KÁÚ0Eåãzøë¢]Wpßïc¶)ì4O2‹HÎ2Ð%k:<½Eñ6ä  a(õÜ™«j Ú¹\Bb[.Ààʇ6!28µÂ8{‚ò‹„žË ¢³Ëgv-_rímCêÒU*ë“+”ƒV)`V3ÐÃ긜@jÍ8É*Ý•ÌeÈØ¬µ%§ðžD¿ùtðÕ#ÅÅ®ú×?ÉÁD¿ÿrqr"/¾ó \SimwyòL{÷>÷”¢GµÝÀzŸ†"·‘‚²[Ê«în—ú—/âå×Ûc2)0Sð¶ ›Y÷ºé²[Nj!GÄ,`VÄrYÁó¿ñ°4È18¼z÷=ý²pÉôúŽ„¥4³à\qÚ]a­µJccaì`¹Úf2êL”›D’BuSeRNITD¡`Ûÿè7¬½½j¯©îír¶WÌ$iÔƒíªÛÑ‘^̲…µ¬Áåäé`M¯.nÝ÷3’z£é`?_ý⋺×/~ißôÕUƒúS¯ák(k¨9›åN ‚ѲßKwf–BY Ð5YmÁX¥ðÜ!âhµêû¼›ì[ñhGnÚê®}%m’‚£^»](2jréIWO‚Ì]S#Åb×n/ŠåUùɆٷ™×„F,Ýé®Q/ØkÅb¼Ñ¨PÇH¤‹Æ®3öZÜNÁ‚Vˆõñ~ÝånskÃŽ»ÝRpðÑV1€=Aå­™ÍçÅãéWNÕΠûBx°,¬ F5"&SÊôr{‚5{ÆJÎ;†~™ Ï,ÊÁjcsà9RTè*°˜Ãˆ£¹”õÃ’¸l` QþqCs\ž7Ô ¼Ãz‰UÌR«½sÖûØSÖá¥x`wfVåÑwr\–i‘£5Ë­ìm¬±Êòåg‰óL•£¤UÕö.€)Æ`mm³ÀsÿéÓÞ7"ß8]ÚˆÕ¿ø¾–þîS|ÿþnN;3‹å•<©í)|¬31Yœý˜7m22€@ƒÖÔ­mc¬9Ÿ<:,ûް ×Õìkñž<­aéKx?FÛ·ÓÖM9Ña}Øßò²2z¨™e ic(ñ˜þÖÃ`3¤pýc§ö@öËÂç¨[;bi¹¾@:]),€È€Ä1ö‰œoQžç%;´“æ ‚N]¢5‘˜¤UìÖTôë¿:µúáª{ÍÛº¥Ån;¦Qd}48ѧÇG£„esYÇÉ'3µlu!¼}·”°Ž7,†‡ñö)y ’({ñ“÷?]À,H‹)ODB ¸2ViÙÇÂA§¿¯Í¯âTë–µS«U™c`×Põ©)צQxýõîø¢[ÎlN§ùV'%n.Üw;‰£Uj/±¼'à”c&@×Tq©ØÅ[‹ùòš¸¸‰¬Ë¢£+BÍ݉֨[Ú£’µd{;DÌXŠC©·9ÿ…èÅÖk©3°Ë‰~ç78ö››[¥åNœ‹Ÿhޏj¼Zû`¶ñþ\~n?úò1÷ÜÞâta¹>»l0ŽKR!m½’¨3N/AÛ&è#)¤åX+mIpmrYi&tYû=lSyíxš†„5õ!œä®Äåû °ÎKIÝ‚ÐÊ#¥õ¼q`Øn9ñ3_)ÇA·‘Ñp³LëI£ ìC˜®!)v¬õ©s{47©€ª 7Ú³x¦¤4`+&ËÞ—¾¬yÖM{ñ~½ºÔ€ßz?|,í­{#¡ÝgJG§ªûÕ•èo?JfsD"B|dJ1•D³a¤U›ó¿¢¦ÎKÌ϶IoÑJ¢ßÏðGPéÏä‰m—k à­ò’‚˜“{š¬É1­ ±õrý Gz‘%/ïl›5ÕÑŽ7˜íßÃe¢ƒŠÿÁç¶ÑfÀa<ÕŒdžþ£_…ÓGã½ûÑft¬§™VrÇöùO»n’Õ…÷ôþТ—WÝò`.7"é½ÝSNɵµCîðÁp°¦]Ûw庱°£œ8Ã$,ÌÊ*1›³ç„9}ºtën‹º Ŧ`‹”ÁðXþØ)üԣ⩳Ñáýôƒ =´©TàŽ­6Èb5×yö4$‘ }§µ”uAL²þ)9>Úëæ:Dðæ½¾v–‚¶„¸¡Q&§Ú—™QÊ% 4®tÜå^Uå¶Ê˜)Œîålj’V§ä½»iaŽè‡ž1€1°Ð!±éùx~¥‡ò`ï#tðHýÄÑÆ°ífm×®¶Sä×î8Éf°g|“td’_¾É·¢6&š"n¸~%†¾B©r¯v·PN¥ÙpY†´I­EÄœ#NÓ\)TL…õ©Ä‹Ê§ÙÔÉÂ÷’ Yk‘üuÕU<4&fØÇ^[ JùŒéuí¤?rz'¾Q“$NîA ìœë¶ À#æ0Å;çR…;˜×ˆ8-­´vØ8wAVË}㙺’CT!›ÕØ+Oª€ÆÍ(ù¯¿:å¯?!Ÿ;•ôÖÜ!®Æöº…Cc•ƒéõ;æ{$s9Ø"Ã:œH@¾°v‡ÛóßГ»E·`¶¼hÙ$D½›“Ï Ò—ŠS *ä€G°Í´(Šo\0Æ0_«Ì0Vð½/É;R–ܬӀµUѲ6”vd&‹ô½ÏìN,¥Ö€œ[Vé$Ù?ø <|<™:VW÷°â&õ‘ÑåŠ-(ô;¿Ê¸éÌ¿£w;Šè ‚A:;¥*òÝ“.+ØáÞðábÙ¸Ö¹z×¹µØ'ñJ™‡îÉ)NæbðHï…Çøíé$²´œº®.0/O?<õ0~úác‡È[ï(†IÇš·[¥(8|ŠŸ=kòad²m¬¹õM‰ññ4—¶ˆÑ«×¼fO9TZãû*K£ö€@s ªu¼åؾ¦è¦”u- ï &Fƒ¡Ý|hnÜKúÃF_({JcA9БT4½¿&p'cP¯â:)„ü7uñI­Ã¹‚“–?g؈•Ć,äu1þíþð>>÷]ÄÛ ¶ÐŽèµø«øïß/|ïÚÎ3cöw“4G^EtãêÍ­øÇŸ7ðVáâ,[ÝAý.™(G˱²ÖçZ­23iù žcNV8n‡­¸Ÿ{£ã½½œ< A\LF”د¬ÂFÛLb•¨kß·î=®se•¡)ƒÁÁ…½ý½Á/deH›â@°‹=“»4lš«ÞO¯ç-©BÔbL’XSE7êT÷í†ÖRŒWäÉÁ3Ï‹©A[*ôm­GgO Ô‡ó "_Þ&½ž:Õ%XO߯sãånóШŹ²ÒCYhŒóŸ]ŒeTg ;…Vº–YÌó¾“0|ÌÐSPXšé>y¶ôÈizê©î*³e01µ î_+Ü™ñÎw¬Q8qµÑ[mAxxØñÊ1¢Y}g¾[Üì9k ~Èf–ÍûwÃD§X[j­*só´,Õ ÚæÊZI•$Är »W„UÁ7r1r´øÌ3–ï´3]UX»™NH:KÙ/LN,Í%ÎNÖdœ éMïóy÷ÝÏÍ|sËq êTªÕžÉõ¡ºjlØVã½C}G÷àóçÑ%Š ·„ #C ¡þkAoµ«Û^ÅÕu »¬†l#C|RõOty–vJÎ~¾J§uº@«áÝ¿§×óÃì~Ñà²MEhÁÅ'c†0ÛÁˆ1s„hU^¬<45WÂÿ„JMAKc}+:ÈÅo©ð:¬‡ðaã¼Î°Í(ã Ãì„(¿Ì½ûöD6|½Ð‰µvºhv#ûÂùÂ' …?¿Ü>_O~÷íKä6£Ÿ.·^½ÞøÁ;þûwõF•¨<Ø—ÏÇ+Ïh¹…õó&4ÞÄùØñ*8í ï.ÝìÀk+Ù®$ÅNÔ956]–[« @ÕºžuïShm­k!·˜2Cö‰¡7TuT¡äOæGÏj—¤˜BgÛþíÕ”,0‹-adtgÕaì>èôÖ35ïí?õ\:<–ÃÂò\þØ£Õ]{hq ,m¶¶…׉z衈"3¯_aXëøaäèÜ‚£ÜÓBð/?ïÉt˜~þdï`%¹·Xî@·vŠœèÏTSÛúê~üxpæTþгù$ª“¥ž‡³Ý»œéÕ›3†ƒj!#0 @ÖZpˆÐ6úüP9¬õr!Æö˜,@þ(=p\"ýÍ®à×.ÛÜ@à‚ÌB^âäÉÜÞp¥Ö‚ëœÄ­}`³»¾!½õ<:Ò÷̳ÆÝÙNq³pCïÏø Â?#9 ÆK =Ô'´ ›ëÁ'óÎÛ·ÉöÎó¬W¯÷—º6…ƒlc£ûἜì§G÷–þ/?èÜ^tÖ£\‹¿¯Æ*N:ô[åÖbWwy•Úª6{mÉÝ‚¹NòËpÑ‘™²$,H’/ vÄÈ É`ìp/)T¢»m‰½k8O yx Räë>Î:"Îò—X¹‚ã­#ú™‡i¯WnÜ“]$^ƒøšÍ³¾q%ñe ¶€»X4 ¾ÙµgF-¯ÞHý»YIÀ:6Q,­¾kõÇô<¦Y«ÌȲ£ Ó¢@@3¢™ªÌªGøŠŠy}0Ÿ(k<¥åšó“Ûñ'3a[ƒskA‘“NÐ_¯|ö½^[o=°ãûÑ©‡ðêzxã~'êÚÛ·Íý…¼2Q`ÃtòyØ3À)K¯\·‘°]kÆ„,óÂbèƒÁvZùo\P*c½ð™¨{êpž:µ¬h_ÿ wù¢·´µRsöhý…§¡7ÍýH”[òÖ4é?2ðÉy}«]#¤ F ,µÅ`% ÕÈ«Dçö9ICZí—ÞXW:¶—_þ‹ ½éed¨b¬Å gÝì Á ™&†]±æÇÌÞÒjÇ4#7ð¼ìÔE²F²z¿ëö³×~˜ïØ2w)³m %c… ¬Éþåo |á ýäJ' Aä‘ì² ÷Ùß^Žæƒ³a·xêtxá¹vµ½¸Ôa®‹HÎHA²ìëšWݬÿ;ޮ œÙi<žëyªß¤â±µTØ.61N6H‰²xÍê5"ëÚ¤†gãA²·î_b½–ya]ebuÔW'²|=WlŸÇÕ¡$éÔ>Ñl7ƒ­;yJäÏ1g„É„´ Ý¥âNn˜±-jq¾íçTÁ æÓ?"ÎíÏåTµs{»ëérmC²Ö…ÆRõ—Ÿ6übõ_ý=âåîÅ5ø³÷½ÿðæö'÷MAG§À¼>þÛoÕ=Vyãb¬Ï!VKl"ƒ¤¹–äŸ.DBr¯Ëo¡¡Än:å82‰y­>eº°[ñm+cPUnSFf¤‹-rœ\¢r©Ÿ?R"—E­?ÙUeÝ“¥ªóãÛùÅû°Á¬EÒ À–[ÅlËDa¥Rî+\ü¯Û=Xž¶µqùÔcÅvgøÊ½Fk;ûü*¾6ݨ9Þøð¾W²©:ç,½vÍ6„MŒž:R¨ùyÕ)úÓ$Ÿ…7?²Ç‹(yþy51P€ƒ²[M¼ÿ~ïËÎâR’ÄÉ‘£ážCí¹xö‡Y½‡n=`Žŋ÷ä½V¯ ¤i̬ÑFÅ8§žtOïÆXX‘¹ÃÕ´¿M‘éKj*ðÿüB<·†‘Ke–p0/A½CÄ´t’dìO¹¹¡TÛ’8Ï‹~õ1 å½ ¬ A¹Â~úC;Ð0EÀï"»60Û©ôŸÿÃÑ—v»¯Ýlf,UyÔKÑ…[øÍ³»kêä}…àäÑú'·³+7ÍòšwiÚj'qpIâôkšõ¢òuº¿Ö¤wq޹LÌ«^vÉØ+Ð&&Ù4¤ 'í&-*ªzúözÃ¥¨6D/EY¹aFpa&íîMÔs"ß‘ö8T ý¾´µHÌž—'Ü4Hb´p/ip¸žñ;©•–s‘á®Õ„ú‰Ccl&ÌYRN‘‰úã§Ž)¿Õb²9Q’÷øDjnY¢¨-èÊ^;§è;…¯]lÿÇ7“w«½n™Ç ^'M…Å£®üƒß-ZÖTc×VÖ Šý–Ík&5m6y;G÷®zíKz(Å1ÒwD;õ ]7Jµ1”­1r« ûÆV߃ÐX©­Â¨¡Ë@´o 0B:UNFJŽQžxãné¯/¸Bè*Ò}„msÀ–i‹­ ˜£mw`¨‹–ëS«‚=Å÷®·ßz»c8ôŒl&²¹­ïÝËÖ7äí»ùƒXa³)QoÇæÓ;ùâ²ÝQøÞ†|ý’ùÁ;ÒĶB²ê`É í›Ê?C7o&7î‰v6"‘¸ÞÝ»ÝTvK|¸w? mÝ™Œ/ÝÌ@¡TªÔ‚ùVs”ɬ½»â³w< ŽHØŒ XþòÓøÕ4Ç,— SD„OA\ð>˜Ï94 ]50§ì&rÛ¡£¶ÙÖ9€ª  Ìúzi­òŒ[4ëÃBºPÐ È¿uläèþ¬ÍGõn^Í{GÆŒ— Æ¢ÙvôɽðíK½MyüxxqALwSO—ÁJÄ—$\¯ïWœS#m‡BU¡Û+’E£Â2K,â*m<Æw„ŠÄiêPÝָ߳ÒɇDPõ¬¨ ÎÝìÌųaíHÎ=È ÇPéd½&G¾:9Dž–¢4n$Ml>OHhx›(Up )ßÔ!_2Œ€¦i®O•˜uëÙ³gòuÑ“Ãý0ã v’{ @¢™¸›ç«O?¼Ñý?Kßš«n4“ÓÝýîNOJÍÆ ô¿û‡…-†uA__Ùäò[:«`½Ë8­&oI¸uÝk¢G3#ySö²°Sº)I,¶‰È{®Ü8&1E⎠-€E™1”Z³Ü¶íNM(‚ˆÎ´'xÍ'ÊM_¿YüÞV Ô‡Q"0,‹bÚ`@EŠ:º;0ØrgëIbF‹û>¿Ùøá/¤ Qn[RȦoÉû«í»·åÌ¢@¼´ÙV £Ø|zG,.›§ê—Ÿèï¿—É®-á¤2è¸aðöÇéÇe÷VäÕkQ« *ËŒÜ]Œ£4­ù•Þƒ$ÄÆÐ~´{óÚ½ÌʾTD1e‰AÖ³v’ÒZ!ô½U]ܽ#ªŽ+Hù©Ž\ˆ&¿ü<ÿÙ5cµTk­(Ãîã:*+øÙÏ9ì¶jМ´ˆ· ž&O¶cHùüŒ\Ùöv6Óôº˜°ìW+Æ76“6ÿÚ‘¡£El¿üPñê¼§!0Z)ÄÌYkõ>ºÍ~ñ™šÛiŸ?¹ëã­hz[–T!Õ‰´âei«a¡ðuxh2æÕ-½½"mÌ|DßÈU®À WmaÓäÂøÂ¥EÙò¶F}.v¸>üˆ3JŒc@Uúnµ÷äùÓ¥ê1é„&#`£Äã^[\Ã\u7_XMrF·3­g””芅”å®…!f»ÒïbI F¤ú,œÔÎ&÷?Tš<€{ øê´n^N³Vz00Ü Ïá©. \Nó;·“•´ðã‡ì×ëï>™Í¯{ÓB¸ýó_-D·É¥ŸªÎR~|Wÿ§;YF åT‰„Áaðú‰\]ÌjÝ|y¯ƒ}—€¥&£HÄ…é ™ŠK1¤Î€”knJ«‘€»±0skæÖ¶?äú~!ݶænCÿè&ÿÞÛÖ•¶ò}V`Èm#Œ‘EƦÃZ÷çì)R é|K×ÎîZÈÚï_ô{Êv5îªJfE¦v⬗vvлÉvWû¡«‰¿šU®Þ‹¯ÌØõ´Ô‰½~n,Gpÿn¶¾C›½‚å1óJÍL BRUïHL=¶ºX. tjcCkÛíÉCÈ%}¨C­– …e0 ö0¦E% ïãzG"©ä'°±QùÓù{WÓXÑ€xgFSDÍ$'çD¶ÌÝKÆnJ¶¤Õ5Ö8,)Ò9ø P6~SÔ;‹ÉªuÞƒtSƒœˆj`¾{fìæ»K7ÞFe§ðijÞÇwó„Ù#}ü_|»w´ß/Цpçšáݛۤ`(sIÖɸó¤Þu.ˆ·ÓͳVn« »p¦ÙâR^Tì>ˆ˜â>©k€#ŽbƒŠSLÅÈt™4ÖG¨†´#;]tå½D^Bõ!ëQgÞ¥›- Üæ¤´¡¼Ä¯Ækó½ Ÿ5º9ܕʒk@O!d'Ý‘NDsKؘQLËœ¹E­ÎÝÆùÄ#xò J–azÍ¿ÕÉ[éßõíþûh'„L ìzòîx±]¬8ç¦â¯v¿ñd¼´QyÄ ›õëN÷fvåUÓ˜“G÷__m´0Cs£‚ƒ4˜0fz-.Er¯*¾k£±ªb˜$‚ŠØb® ÙÀÙ¼R‘r"ƒÄ”b‘ë–æÒf`™GLªøÌм±Á†x¢aéƒøñ-ô½·µ+ý~ûA #)k`ØZm2€Ib:=þøY·èˆ;›ràá‰Ñ~í}GS¹×”F9G"A'wÚncݸ›¬÷TÙ€ëÀbâít˧ã+ìzÖ߉ånOk +‰¾›¬·i«&2uü Ò2V8Ó}\EôÒ¢SÁµá‰å‰Ci8É>þˆqÑ]PÄÁ¤† œsß(¥%²ü“9¶ØÜwr'ÕBn7+ú ýàz¥Ž H˜œpŽ-ÔuïIkW)¿bцd‹F®1c ÇÖP‘Y¥ÀE—Q]ÙÞ#@QK7–Ä>Ê ¦o#¹nÁ±4¸ö;çFï¼µ8ûKä2ï¹çüOoɦgöö9ÿükÝÝ#Þ@™5r÷Þ&¹s{Ó0M¸&y"ç)½ûœ×kŠD6DOC)Âdš­,¤E€I ©jQÔâ,© &BÛó¨ÔèÒƒÒþ|CÏ/¦½ËH2n8ÚéD‹!›ÎY.Àt7_‡¾ÏE÷¾«)éîô-OwÄ’ös>°G]&Ä·TSé´1¬tÅsÌ™le•IÄýzôQ2{K~ô‰îÝ-T¶ù¤†Ò#¢½ÆMOÖ¹R£CìÿüŠûkµGãSá«o‹Wïøýåäÿýõþ ·÷Ù«ñym“vŸØèª_[ÓTƒ´Òjb@%)l–™>&~tK‚ƪb”¡V%Æj¤‹[ ÊÕǵ6x…ç‹ã€R BÐâöV÷[êµÏ‚ïç¯_Ñs+aw¹'cwJɲ±[VoZÖ 9sûôˆS-ꇅÑ'ÙíöGodÓ6Ö©1šÃÀ(.”׆\{YM©Ÿ îzÛ^PdL{ᚢTƾ£ÇR/ƒJùXêöŒ…q#Ź¡9ÊS°¥‰DyQFks¥Úø©ïäý£êÚÝêõ9Òl•b˜À ÇŒ=jmÅæÑm–Q÷— ÞI?›†W/^¿‘l7’ 0”*­Ö@|c²}4;®m”Ýà”ë"bŒ¡@%62”PÆ ö„O‹˜!—w¤lzöÃÄp‚RŒ ‚gÏzu§]rÏ tw-yøäÿDÿ~×ô¾ÃÌÏ·=ýí§Ï™sæLï} zA,I‘-Y’cI–e[.±œlìlì+Éz¯+ÎÊÙµ×òÆ’#Q…bH€ˆÞfP¦÷3§÷·¿OýöýÁÿÃýã?¾7¼¸ß\õÜŒ?ýPéô¶ü™3Ù£¥¹ ±Ù34§¥†?/Ú†©iAm7Z[t¯-ñB‘pm¯ÊáØ¸~¥o³mŽúáUHI8qãEÉ ½¼x‘ƒØäŠ­-Ø…+b®;þ Ï?䃥ºn»*û÷ˆœ5æ®°³ÑèçIûªJoÎÚ“ë7»hA3Inh ~€F;ó↩PÊUÏk‰çŒr÷Jzäîš½ø1m]ò&áv#$'ÄÖŠ§r>Bµ››|ºnÿÅ—‡¾~®ùÄ”žÜ‹_}ýèª7TËþí7ã¤wåU|6õ²¢†'ZåñÚõE„#¹…I‚°±€å…ˆ€e¿Q€”Z«±Õ€|mhŒ‰k &rñÝ$š‡| <Ã$F8ŽŸb¯ÝÎÞ¸.~z1zûºùÙ%~ E”»9LÙ.ÉËÚVoXc¥ãEi6"uèßõ¼·¸5xë•ï[™TÐÖhYÞœú¢¦"òá}%¹á…M"s“X‡ ìºë»ÎdN$ 5/+dŽÛa.ùHOæ1–nyNb#äË÷Pig÷™_ &§õ'·Ðåû&Âl"e‰c8jRÃÎ=­k¡¿B91·Q{ëv÷í«ò«C/žnl©ÄŽ“F.Ë­´Æ‚UÇ}sLûm\\¡ÆjæÀÄ I´ïØ@›ÔbPô¼_LI§ªyYÁÛ̾-,vÀX¬=wOU ÿØ=ìÉë«ÙCÀù½•Of³Û«‘›æ_=ï‹_:YœŸ¢÷·œ´gh8ŒÞ3ª=½=§dP^]rïnš~jª{ýþ¯¥ªÆjmÊwh}Â+]¦Ÿ[‰Õi‹·9Ž“ò“ƒ"×åõ•|õŠºÚŸø´È—’äׯ ÓÛt€`¢Ô‰%Aä-#7­·lu¨*7',ÛaŘ,çŶ¡õ¹‘»´y!²Ç ¨(yÇS[ø@:·Þ¼nF{t¯Ñå=fBä)=Dí ¢3[ŒÊbQaû·q ô?¾Ÿ}ÿ"™¬áÿû7êõp³Et«3¶ÖL2€§ää®Ò¥«Y!rB!§u$ø>&HNŒÎ+}WV›¬ï( n/ë(– X}MÀ#y*ˆ‰˜TÎ$Aj©G}døn-"rd¸aÔs‚“¾óxÂÆ-ïZVb:`0¯‰Ä‘¸´P6̵°Ò3‡Ó7.ÚW^ {D¬d«AÁ`eè+&Ä0`W™Ô—^ _:Ê^¾RH ¹€Èë`ßQ\3haõß~Ù†#fö¾O 9Lh°æZƒ(c À|éžçsr‚þèCGôÛ\ãfÌpÅÊT©³žqŒ)l8­Än¨[åÊõ±I´´ÌsŠ:ƒí&MŒAÈ·ZÓ ìו«ˆh¿«§@/ø²9®«E¤5ÃRêrœÐµ.ç®cßÉ£EªˆgW%†~å…JÕéÏ_fí¬îáš>t°ve%ûhÞöLñàX0¯—ß¹ÜgÆËqÉ¥ƒo[3¥AÒ¨I´«ó‹Yî,­ð­%›}ªy¬0ç™¶z]à[ž* L°µäŒ›1°KÓ&‘Ÿ0ý97·¬·Axj)(aJè)j Ä®〦`½&õ.–LM”³JbN:v›1ê,I»¦ÜXcuÛ—l°Ï¦ãF\Gf+؞Ͷ’+fbÀ¦ÉQ’ZÏ7rÃfRðC¥’\W†ÍÁí‚û߇¿øHTÄÿí«ÃÃåfAs3j·“>V;÷ç{÷–>%ƒ,®8^Š07öå¨IéºA·e¹fX ÃÒªj¨rˆ¿)íI£#äÅ$Ÿ”î›ZØŎã‘îÓ¼J½Ä(…G¸ìba=tÄÍž)‚1”· ®8&d0§œJÒÂ÷3ë}ýï§ï%?xʼn™»n6Ž–È / :‚0’J|ñy÷ËGÄ®( ¾¶9ƾÆZ†´­À^Sü¿ý2T'õí{˜ºB%2(@2?0Æ(«cÇh[^šË<â¯ýøbV´¤¶NK b•q#—§\0ë ±[![®¯¨”aqÍU:¶Æô¤‰¹1…ö´P˜°x9Eõ„ï‘r)´±ÔˆºX1ǘ†˜MX¨œbÄZíR(Êeæ}Yd¨PJGÌþÆ3•a*g/ó 6=2rÀ¨{våö†þp^÷µ>¾³&»¸XyãòÀZ?G~ÀZ/`˜Ö ¨×CÚÑùŒ’à­eÕ¹Ë7Øö®Ìsá½L­t TEù¹•Û->å©£öÒyÙáwþÔØ¶¤öܾ•˜ä˜W8„h‘e„gM ãÌZU ϘñE=˜óðœàÐûD¬[gÃa§ :/ô27™É’Ø=Lgçô\Ï”Àõ7p2®pGã&q—ˆá&üÒ©ÃZÍìñ©÷îð?y—ì/»÷›y•ŠÀ +¬Zß–à)æŸF#û„zeƉ›€²¬` v:87è-V¼ brC¬²`ˆ±XT¹’H†©zÉiª¹g„õ± õ˜6…É)ÀY¿VâÞƒž{R&ÇB_ˆ"%²odGÛV7£`¡ m ýH(Ãö-Í‚’1qPÌ®Go|lÊ íZ¦ˆRÓ˜:SIΑe`« ò[ß)Ø Q‘Ü™·6–އ:Òjë[,­ÛpH>Vwž>ÀgvÛ#{ƒ{,ˤvU+§eŠå=Ïh°L”¨¾B¨eÖIDATÇpr}­Ät!îÛ¬#*`¶¦0J¢(ØŠö{SʘE!¨«¶KýD蜔â öë"ª¸z¡L Æ8dš S@™P „Cé4n ž1Xœ{…±šÕVJd׿扫†-–¹!x߉DÁGPùð„sä@—U¿—–vxŽ#~ÈjÅïE«³á…Y(´-šùß^^ê) V•ˆ=gÔe/Èr•5v–*‚IU±‰6âfðpCÖÍ`MIöAQX¸OKu>îš),«òk½Gì}I¥© †´I°EZÕaÚrcv¬§]²‰óm:Æl1Xff7‡0óž™ØjŠ·M<«þË›zÆ•ÿà;f4tu·<ºÓðQ×Ðnß+³B,.zƒ^Ô7ƒ}¤‹=‘›YûŽ'ßDrÅ Êj@HkGqÑ”ÕSý%[±ˆûF:Ú¥T/b“PkUèÂApÚ/—„ûhÉ;Ä['˾EO'œÙ-%¯Ý*yK¹mc‡R´gœ\bQR¬ëó[Ϋï1Ya”!X탡V0²7Éõp8p5 ÕØßþFxr_R•ö΢=N×¶…±e@Nº&*ÌPÙ>wTìÜÉí)ÝÜÂY¿  dP.í–É–gdÀÖ!2}äÆb¾–Û¹65±Øb`°Ñ†­+'·j¡p±Š¡³y‚‘žÁòÉÈ;ÊÅ>`£r¤Ù-ƒb«hÀdÂÂaAa@åuìŽBù.¹%Üøðc¶R"³ Å5R$Ž2¶pÐ]I›(5sÏU&Hʇ+þTpð˜ -cÅXا[«åwn¦>ÀLu÷xc©e=¢ò2Qç¬=nœ[ÒzžDc·¨T8ò7¡X?mç°ʻm3àþ^­’™UzvŸ"f*‡eãþò÷"t›û]=¢z@„,–«]j qœ²PÉùi8¾Ý´cm ñCÅ¡H)crIÚT­’PsÔq~‰‚SdÜ…ìÀÈ®3zÿãõÞ'ýmt“ú?Ö½‹:ß"°—ÿ‚åhÑ–vÚ‰ÆxÖÆzËXíxq.»1|6>YRÿ×껇S#Õú ˜ï¥7æý¶Ð—¯V^Ýûþ‡º5°Ò€õ‚E.mÅšÃÖéH5g˜µØsBe¤X#+PN¨­+½IFLîBYVMcó„¹q¤àaOYBBïRŠo[—;$Ǩ¥ šŽ)÷MeÓô„¶VY–å¡pÔ~Žö쟜Q¦(’T•<Ø&!s‡$a¼·7ÊÓdtž|Ì[º:˜Ÿ—ã;·º”'€¢ ¯‹’.BV»c>Ò“pâXå½7óæÞ*Úhò~WÏ”Jt#su#ÓV#XóÉ!8rÔ +µ¹›iU‡]p›êjÅ…Ô} 1oÊ¢‰MLèg9 l ¨úÚábŒY.ä=Š%RÄ€Fø4˜]ÄRôÁŒ~ G‘°q\àȸ°² rÔàëR]#P(ŽÃ,šïů_ î]›Zigà³ÕŽÉhGYwñÔ°süPmó~û‹zc£¸Ý“Ø/#QìÅò1LW ~Ñwµ˜·v*¿NøGR]88â(fÙñ_qýö¦ zbd_vô YV4ÝÊŸ{f‘*‰"+¸BP „–n€ÓçÚñŠ3ßÌ)e˜¥ÒÇvº'wØÍ^¦D†u@K J»=ªWëƒ"j?Gߨ„nÌ7ûݧé¡gG’Ï·Áü@'´ì!؉kÊŠ´IÅÞ8ÏúÌ4 ذ¢Ý3ykpÒ3ÿô¿Ù¶g43Ünæñì ¹t¿hIuùºÿÞÛÑŸ½—o¦©Ö®rŠÀa‰£BÑ,pG#k1¦žq"ƒ\¬¤ËQ¬ò­œ¢Ò-)„¦LY–˜E”ÐX#G5õ8OãÁg)»k\áÈÜñ›Bôèè¨gJ[*ÎXé‚;¡£NVìÞ7¾m˜€HâÌFŽTNz 6L´öõ"ËÆ&õÓ×VîvfïÚ¡)ïâ¼-ºUϧ=Q¨p(£¦l-C 8{|ê­wÚ[‹âØaÖÎL;¶cAµ/ZŠªÎ訉 ¬`²BŽt¢ºïZQ1t€«¹I «]p!ZÚIñ ™ö"±Á±-¡¢¨ô4É„l¾+ò‚”'÷-Ê Èâc®=‚S%I ETGç׬I ¶À@k,­"eK  °¶H|ÒÒëR_%”# Äó!\ì'¯_$÷n7æ7ŠÒÕŽ õD*á3Qeûv—ZóýŸ¬Êå5q½É,Ñv†ÚDZ¿¡Ô;Žó¦NgAíe¥×þ!/nAá7á‘ ýÒ6×mwC¿3(vÅö‹.:"‰Š7°}Ã'óDg:å”° ‡^Ú«øæÙCz8Ò‹î:¢Üb¤ ÿòˣϞ4Á¿y[iFŽÉ\_ åb§V,+” 3ìâ¥"ÍκO<êÏœLŽL×–>ï/|–ŒIýC\lb"‹‘v•»`[\XÓ%䀒,ô„ }@?¸K×}àí,‘Ò·\òµ‘!­”oLÅZ˜G÷gÏ?–ìØK÷ÌŒZ^t» é4“$ПÞ'~å[¥õóú=R¯ØÊ+ÎÒrŠâ@׌ëYé˜^lÓ]{\˜Kð R]6ƒ¦üâ¯í¢·ª”Pd/¥bhß^þ…§Ç>Ÿ>vDŠ­âÖ-í¸b l"ØeÈw=ŒCÉ»Ã~zj?<}Äî©Ë'ê$ñ*²óŠz„^·pߌŒf <£‹MßÔ¨P‡â™ÐÇŠ4¥¨[òewÚøg´­S‘»èˆ1{Kɀɉ'ÇÊbdª±Q ºƒn³Ã¯Íå×7J¯}–]¸5òÁ­ü­k²§ðÔT}~Ã]ßèZ—Yê€9Cð×û‘Á«´u¸»—Pž7E$¥êGëq^Ž’GuFÛ3»½[>Þ\àœyï‰â2‚41` |Ž7a¡•!O?BÿþÄ‘ñ±·çz©–àÉ¡ù_yölwË·ï#PÊPK%w]%žI!_ѦvÄó–ò´81|þy½ï„:0ݹ²Ñº ¥^½N¨$,CÆSþ‹PeIÇ!ûg_(!¬ÇJ[­Ã*O>Îöÿåuñ£äk—v¼üiïÚR寽¢ÕR"M¨Ý3=2ä¡A‘É ¬3luzÔñúZ§ê5G”‹ QªoiÉ2|ÒÐ'CVðã÷x„‡ .€0ÓÆºu“W•^ðƒ×…\¥ØqòÓÓøÑxdŸ©øÀ[E&¹¡n¥he52V+OãZ”Jï–_|¶»ë€·gzT/o’’¶Ûh¨„˜<È¿óÍÉ¥Ÿm ÝrP׈\ÖÈÂRÚ£¡l ÐµÆõ}&´ÂÙô.ânÄèš__&½¾þòßðšk|°aÇ•H2WEc×ôâÓ;~¬ùØÅ×éÛ9%*Öin¼0dÖÇZ ªƒí~zh/<}Øì¶#´Üì÷ÖY²ž —‹À"¢@´Æ.Óð€Õ ¡6ÀõŒvµÛpèTɳbÐ9hß«ø¼;¡Ý´m‘»pÜóF©ûŽ‹È­Ééªß>¶œ´Y²ÖI¯ß7ï¯}&>¼ÚøànzqZ"Û³»2{×,·2·:IdâZ{Üñ¦]ÿUÁï#m¦»—¡ÈÎÁfTž6I$ ùc'‡JÛÛ£ûÑk7—mQvß*ħ45–4d)è\EJ(€ÇϹÿð âädãâjÑìçdïnvÍûŽÌ?K»[f|¢ÜëçûºGöCÚ5Yá!Ä™v›·°sj3†JYiR¼µ^ZIª´9pËRÊ B)Á" }}\¸‡‰â4÷œ¥ r‰)j®ù~ûÞ]Þ([·»oj"ýÀœ…u\yþ!󻿨¨©¼]»ž•Ú®îÍÇ…l(ó¶û_SfÆ5,3…­®hµ“xÒšuj1q›UÁ¤Þ¦ñ`XÇh‰K„µáG…àNùàdúû_®íøÔž±î‘éðÔ¶‘‡TšÀr ke(*#“ç`xÿÎ×¹Ûß½•ìHq¢|4,Ê;JósB(ÞU¶ª$2¶§´g5qÍ©“5Ò•f•Ô­¹‰G÷øO+ÖÕ«+îñ½â¡½Þs_VQÎúØA¬fv;Ÿ]T ›Ûs¿º!ÚÀš@š´°Ÿß£çÑc;†Œ«C;œs»¶?|„l´ãÅnØ4FY¶EMÛ0f”D~„ÈóVv1´j ´ ‚h–Ü’Ù¦UšØÃF‡¾ÙÇÄ“Jì6¦¦ìŒP„_õ-X=*D}ûÁè·¿jLj›«´kJó2•»Ç'ºÙz?š½âÎ\~})&9°‰"Ž‹Î;á#œÈ7 ™ ¬µrÓ9CfȨ=`¦Á(CWœzy¢‹jÚ“ÎúG¦'Ç~ˆ›[ [6Fƒn ûü샂FÐÛÐÛÇ*y’y5yl§»¼È_¾$Ní ÆêhuUÙŽmT¼rYÆ›trªÖlf‡÷AÖ¶ƒÔ#ð6­¹ç™¯Õ±ØµßdC2‹ËWªt•U=Þ—¦Mî mm_gÜJ…”öÔqÆfˆãÂuµ4Èc¦¨yþgsñµ[¢Ûs¹åfùàLÓ~—ƒÀ$$ä‹Ão) }÷šK½\)Óö¼ƒZŽs>¬àa€=Hd¾Ð®™.ø"5ËH‹]š%VÉ1tëŠfÂÀ'ØÍÁb­ 0U Â$p/<0žþó/|ãôÔŽFrt‡{frÛ‰C"Éôò&“Za\“s€ ؆ŠJÕm:L¯¼…ã îônüøszˆiæD÷šòÁôo½¤éÀ¼}CìJH¬‘¥Ñý9®¤ì*]VÕ·Ü5Ò Ñ‰ã¡“(±€j ï"~f¯wþ)¾ÉË÷çÝføƒ»èÃ_2á.ôÝpçÎúç—ÚóëõÌ«m©ÄO!dN3¦x`¦ø{/ =y¨vb»Þ?æŸÝY{üxØìî·Ñ§@X“š-èQy‹ÅRZX&ÖàTåÂZ"›:[b,³º™½D>eÔ^k«ÒÎÙô²ãiC¢,ã¬÷Û_Žrç‚ëº~1\RÓÃC±lÅi}u+Ÿ›3ßÎÊJ+BSnÉOœ•.2µt OSÇ uÍ3Œ³‚ «O‘ʦâ]ê„;:‰ ´ºr“ ŠòQ¶.¬G< ЍpØã<¬äö¶Ò©)?K¸aÅÙ}~{ ^¾”7BBž˜bW7íç³Ù+×ñÝyóô±¡‚­¾ùçß©ýâ¡T·È§+T#𭦎ƒÜYÐo,o¢“3nwËl½ÕÛþ»;¥5©ûJ•€j¥Á.˜1SZWrÜ&×€s˨k;²xé”÷õ§ƒ¯©åTÿ+/eðõ{N!ÌžÀüòwûGË“jq‹ÔãO¯)jë…Î@Ä’‡º˜Êb­­D3¶4jÔ&ö»H®²ô¤7r€7ö#2êÆ«ª.Ñ q¶00«¸©+6¤,|wfˆüþ×jC¶™à^ÛHe%+úÞܹw|«)–›œx̱ªœ:–k‘ñºù¦8œÚùÅA¸[<ý¨rDùîýAl‹Í&„•᱕{ý.¯æÇŸ«'yûÓË(Ä#Þ¨ýÒ¹‘»ªkYÝã*üä±tï o~Ó"tìéz,×?w·€åêŽÇOVVÄÊù¡L.mI9Ü^cÝV»£{¹Sñ-AÀ5­íáíð7¿1:m¡Á@k³ZpqÏvNœ¸·ëý¢eeÂ°ÖØEZo§†c [®œòFj»îV£¹uu霡R~ÆB2k Ê*„E>7ò6F„P›»!‹_|”£Eq+Vo®® ŸýݯgÏï•®Ÿ:EJnxi#g¾'õuúi)¨k®rËžÑ(•& Gà †€ìuüE«öÙŠÜ„Ór„•_þ^´¼Õø@-%Ö VÆHŠ­õþæ ü;ÏÛêÑ×`|ŽUÞ»Z¼w}x;ïsxvÚóÌÅEze>}õ&ÜÃn(?kvù?û¥ñoÎЀ}ºd ‘±@¼Ä¶Iܘ./6Žìôy+ÝzÏì5þϵó¢ iú Ê–HŒ¤Å®µ“9f]‰qKÇç&S™¥„©Žä/œ¯?‹¾v¼öõéWŸF;×o…)÷÷…è¿DN ë;š6’Oo ҵ•–êºà{ù®+”¶D¢ºº˜eê˜æÆV4qO8cÇdåvGüÁ’¬+X!î&AÄHcÜ+B¨ ¢Z_»—»͸ .3¼³FÕ‘ê—³‘m;Õñ†èȽ‰ÄzÊQ”lOÄ>/óò ¹ª#}÷]ÅS¥%åÈxføxÞ{ æ¯$¸dýk•®ôÖä'wsÙ÷>鸶72E—Wäµee™Kƒ3º8VÆïÿ¯1¿ÍEZ \æ*¨¶–̺}ÆnBºd`1*Ž sÝ-ͨ[›âç^*,XÀ3žkuĸÏ÷Œ™´ëÿè’¨–øV>½Ytø¶‚ cð³{Q-´ïÞ ê%²ÊâW×Ú[øÙ”ødEÝ(¬À3–POXPÍ3“Õš[ùž$kúH¿+Å5Ãs8@S”—­Q+pb„æ\qSbîNÇܬ ehxdyæA/È»¥Jø½W£?}§›ªü™såßI­.'7¿·nÈhÚëY³ÔT¡WXn$²»‚I2gQQÃÉ„Ê÷øÉŠ®;gèŒukgÈÓGxuWëìÞõŒÈ-lRÚ­ePòi2øçý““¹!˜EªNEFKå•.%}z×( ™Ç3BŒ m%v‹½#оåQÙÅdÇAÿÃÛÞŸýÌãÂd¾²<öÉ­ÍVwfwåôa£j'ªÎ…¹ÖUö÷1@E¡W¥‰eýâ ßï48.ÞêþðM~}ÁO6þç·@ëhf”lÞàU­)SÙ¥>_îÛ.8$êp ¬Q˜ø_,88™¶Ú* ª")X0aYi¨yÊÃôúÝŒyX(lŽ˜Ê=„ô„•͈œ|Ènß–·Æ6à.ŠŒˆrTR8˜â|¯;EŽ­‚V-“÷¾á‰Ò’(—S|²;Fo]l¹Cæo~±dýÚõ¹Î¥{EÚtΟtkŽô+znÁ^]òY‘$8¢ò=XýÜêŸbsÛ˜¾²œaðlÌ@éÀÚ £[ ïZÝ-‰]’Þ!Qó’YZ‰ß2ýBìjŸj¢ÁhÉ|:ÉéÙ\/~ò¹ö=xñDãÆ=µ™'B°gŽyü”ûñ¬r0·¶ÿÄnóì±ðÿz3±¨öÚ x{Áýp^m›  W¶8Î ”.˜*ßrÒZÏ×óI×ÿÞ@—QÀ´å‘V'ü.ÛÒrÝדÖÅ;—y瘫Ö¹FPj•«Ñì <T8ºô/þ’¾µùä>«_:ÔË=uû­Ê±AV¶^ÓcÞ>óÙ-âC댜äȵùê8ûÒЙÓÉÉ=*u)›—+9²«x6–oÛ¼ÇêaöÙ%'BÈ3ð©æÀÀ¡ «¦K•/=](% ^[¶Ÿ½Ü¸y±‡KdjOvâñ°òñlÒЈºNÀáU±MÚt åWٞŠEÑxpü^W½úfoE†´´ÃºžŸ¥xw^\½•Í®# ¥û™¦=•ðƒíˆ´ü[‰P¤ãLb×/ýìBëgï©wo Õë‹ÌsS’"ÂîKZ GOÌ‹ÖÐy»{ûðO>N­°Ûº~S^eÕ\Ûá2ÿ;OŒÚA/l /\W/ÿL¬\ŽxÅ­å"޶¡K·¢õ"sŒ «àq„I z>:d \um6Ï–Å”¯ÏJ„5ñ$ùÒñlzÀxm¹Y riéÏ­,‰t­°ü¹G‡¼•|b1ßgKëÜŸØß9¿-ß·ÍÜlÊOšâÚ­ð‰]¾–É¿ý+% m<‹´~ÚËÌ+ÊÅph…ÅȘ⸵¿ƒª}”gH¥ ]i]ŒZ{ÔsÔfÖ8”S•J囚°}¤ މ`¤vñž{aÍþø#­ÁÉâïî[KêEÿ£û´Q *ÀÛÊ+@T ψpûx‹%tÛš ñ%ºje¥´ºn‹~×c#ÖAH„\N»cUuŽf9×)NŒ¤Ò,¬Â“û²ÀøÿÓÂ×—:Ãúg/9/ìKâ_ûîÛ„q0«ÈÇÐÕÛ8RÃ).dN)BM¶5‰?[}àtvr¦ˆ+%|½xNãŠS´¬næ3;À¶Üj)»|Ù+r´þD LÀA Œ*°÷ñ×_`E‘h\mmDïýî|–áˆNî©Ðv6V>¾Ÿ¶4"^N`*P!ƨ—«¯>>’ÄKÜ ZÚL_ÿ¹ŒU–aÅ¡š@L}ÙOì…E~ùºº»Rh[]L1çM10{¶m‘kƒD@LG˜Ö_ý0ýÙÙwù §p(s! ¨ä$!¾žÍ Ì·Ÿ[Èuãݵ{ðÓ÷™•Û5mõˆ4È„Ž'ž¨È¿ýìjwK•m‹÷ù˯òÅ«aÝgJ‰ë;Ì>»m7 5DZm±%§\4LäVH=Y$ cžzw)Mf‹½Ž9gp@¬ÿ„þú)1sÈäÐj‹×û™°äç s‹¦ÑWÙóÏxÎgG}ºØógg§‡{‡¦ÜMùY_^½<´1Æÿ_?Ò…ð™Ã‰£~ûœW¬ÖUäK%Kü÷ C–XÔŘ\¡îbnŸaªhæ‹mô©'¥¶Ê+BÎúTåÔ•áˆÿÉmve…¾ñq ó\þÆ“c½îÆâf¯L¥ÀäôÉœ|çaïƒÛYl£QM¿ûUÙôú+œ E¼ÓAOíò?°íÕ+íóGðï>î®$nÞ܇ùó&=ãza—\ÕSYˆ5ŽF¤CÕ]”,"ÐÀ|#3äNû¸BÓ†V•H½`Sø 2ehá†ÿåµb~3}tû;ψ=£:Ö 2Íü¥»úNhwg‡‡åO>WÜ \€ÂÒIßUj ôŽh(2«R\¿) ˆ¸‹ò¥¡ =±,§·Öký^÷t(È=ˆ88¥–‹l-¿|@Y#I)½üa¸gMNñüŽ §öw(¬ŸÞ\(mve„&ó€£n™¦`bž>•F{‡_ÿ¨xÿR¡aJÄ%鯶³GšFhÅò oÙ³ë&2° ìèé^”—8^u¶Ò \¤ñ Vµä,pÅLV3º<æ#¡´RÜC5¢-ã¯ØôÀ>S%sE_8›ŸfÛܧèsm‘cŒÎ¨_~Ú ûènÞö‚á3ƒñ /+‚ézqj'IùÒìàÃ;j ;wï tí´OKÎ3rÙA±À*CÜž÷q> W¾6žBZ™.±ã©Äý‘‘}踉Þ9Sý'Ï@޳ë‹ð«6|Û¿¼@P˜+AVǤ;vÙÏ®Ù>„_8Ñ |÷õký"Œj‰ø[_F©#_} &”kâ}dž=9þú­Î™ýêŸ>-¦^ÒäÖ)ÇŽÚ²ü€®ån±¬£™ ˆ(fR€E)n£@¿bD –ÓÁÞ ´/Ñ¡¹Õ-SC`…u4Fÿ×ûêÆÆàÉ)ü^B“c:O"Œ½¿¨æ±š>Bì¶ï}‰I˜U¹“Œ k™k³ã ­0nUgÙÕ;J¸å>Sùö`Ç”)9vÀéüV£÷D[•ƒRaÀ¹e˜h3Ô¾|  TÓjqñ]g÷:LùQžÜßvu„ueNov¸µB¤;p³ˆL²Ñ1ü≼²«úÊÕü½‹ÅvYH¬cr")F·«¬äyÖ —î :1X;R1£3fÕ¼¬ëeºz§Ójƒæõ•0lK›.¦`9FÐ6¼½É â?û"~xÇàÊòÕÛ™qû-ˆŠT \ù ·„Îü¢!Âõßñm#ÊÜwüLK ã¥÷oÒÍ"׬6.®G†<¢yêë´ªUyÔÅH ÛOñÀ”tV¥³ŠÓ#ûaØk œÇœ¶>OÆZ¢î%ƒ+es ê7 ˆƒîÞ)–X¸ãt2<î˜(˜¶²~º:oÚÒÿlBÈ Ò8fõIËû´uî©§|ksK½È9”Îa(l`Œ£#ÛJô`†sŒßÂ(®ªbœ¨ÓÎ?¡.ÝÞ•;ðËÔBÔÿ|ÁÑAOŒÝ·¿{p·½tÍßr•éK Õ°ÜÙÈ8ì훜|ãòJc´Ñî±Ç·…ïkôwþð.˜¡ïœǦù?[Ó¾-3„Ø'yñƒ/iz|ìå7\ʱ'¢0 Î4ÒuVaZdr½±^²¹CÅøVs‚ˆýëpäw_Rî7ÒéÅTH‘Ø@M6 ÃäîF…88o¯A¡`ÚáZ‚Çtsi]ˆq6øÏ|MSaY—Ã.¢pÿüü|Ú*¢*å„b¢S@1IÈîåNÌ•3œ]¹ZrÇj“qèºùVa}Ü‘² u1ÐMƒi|ÇsúY¿/åÝ¥Ú_¾Û¼zŒO¯ðvÎ1¡ŒQàEy–å^Ð*jf"(ÁDµº1¿"\ox¡A7G¢¿cz$ínm%ÙHT"=s‡ Bå#¦3ÓëÛ¦åùpõºR±ýæSãMÉ…LktXj)ÉÀ KÑXŽ×º:çÒØ¢‘R}*_š¯ÇÜ’–Iq§]Žâå…Á.Éy¿JH€)ç:\«¬ü ý²'^‚sö¶)Mûä¨Á#Û‚äUx*<¼ŽÔQ£…ëÒé5äuJ;*Þo¸Z'“#¾³2uˆŽ«ßû²=µ+øÿ¾íüõ‡]‚\Cµ…î…>8Ugô»6ĵuÃ{([Pª@pOûžed;}yX)lg&{ŽyGŠ ¹T',‡œ¡¯ïžÝ_©U÷nÀ_~¸ò¿ÿZ }Ï|´\ Â$Mkóýî£'¢Ç“W>åbŠ9ˆõ÷xál=q`tj¦õö¼×÷‰‰Ù™ü;/Áïÿù=°C¿öß?’ÿãä÷q$”áþÜvqì ÜM]uߢ{ÒfÖ½ ˆÚkpZ!¾±_ô":¼ýí¸xwiAƒ~øy1T®ÿ“¯˜Gf³¸Ð?S vïîWG „È®jÔÇ›;·ÃÍyƀх1*é"îå|j´ÒþÄDøÜW%q”êz8p¸w~þãb¤Â J]F°J´5Ȃ͔éû¼¤Xžé°žÞæå1:VïÖ¢(i&àBAªÒAB( Ea¹áa¢žI:F_[/ýøµÎ•e,|&7 ˆLÀ¡ yõ¾›ùÑ’ÓÌÉDdFlóþZê²[ p‰›7S#õØÌT>´Suˆ7ðï^Fæö­ê™w`Н^oñ¾ý¥çê-Í¥„º­))qœju¸Ét …u°WLÖçF„PõaÎ3ˆ¨Û#I¬ˆƒB¥4sQÆ{%B\Lp†¢ÕÊÚzzA%¿çÜÝϹßk1tdk£~£Œãn2°¸´¥„20f'GPöë»ÝÑ_w3÷»&)|'ì 4ZVŽ> ‡_þsêB¼oª÷ì×¢ÿ'èÎú`؇ºç߉±ÕÀ….@NFðð}Ѭc{{þèGëac›Ï¼åò1îßëÀ]†©a¾$¼w›ÅèºzëBÊdy+i¼~µý¿Sûg?ì_¹ã ÜUëaiWòèYx÷ó]Õá–Á}[Ã;Å\§þÔc­°¯Õê™ýc{Å?þ"}ÿ>]XqmÿÍ9>;ôóÕ”ñ,Gˆä^ ø -U^t¤‘ Á–( ¬ ð€î=D\¢lj6KLµ—É ‘“f® >a?¼ÖúËKeG;Hsƒ4¦H6Ó(kÛGñ¦ñf:â‚-éô¬S ¤;Ûnp·©Gwð3û¬”™¡®ÍóT;˜¹ …ÆÍ@ Š1¶`Ê6 RaØÈŵ.{´R"ª{îa4;d…ܘÜ1±¶²6\õ;–Ü_èE V=ÀµòP>Øô1¾q·vùãæz 6±„]hx^¥šŒâKì g¦«ýÛJ¿ñ­Ñׯ´ÖîƒÉÙá§~`®ü¹ԜٱõÜ¥ÿô'üþÒÖµŽ y&Ój…Ø>‰¡`ã¬v—o4ÜY?úA§44éS•§ªQ[O¥”»ÒÊ;E¹1Œ7[½}'GÖj[®õ`…"D¹—¶¥ca€ÂȆÒÖ3vÒdTˆB„EÎ5Æ é“ÌQgÙò,9:â.¯%ÍrÝ/ A4Q"IªÿüO:±*‚2¾ÁŒú¥Xr…%aYèŒõ,`%LÍŸìæ'ñÑMש>ômÛœ§¡—´ë \€Ì @±§|µCFAä5)ØР PD¯Îµ†üÃK¢d+ŽþúãøþÄ/Û‹·‚»Þ(íl?ü@ñêՉ갼N~åiûþýbt;i‚®À§ØÇÈžæÇŽÔnŠúq4ƒëeo$nªiµüòÇÎ¥´ÄJ†H)R²ðv%%XUõ¦’»Ðnà!ÐH+b ñáúµá槆®êÞ–±nÁ[RZãq˜ƒ+‰ØHóD.ÄX·ºjs°½ŸãͤhƘw!Ôªhû‰ÎlhaÀÏ:iDLŒk 3œaxŸ–¶TR7^pš– ›a5¬Ì.óÆ{][‰¤cUæ.Uc¬¸~O½|9\\ ÉP¯(xº'Oéó{u;a›Ñž ïðNIC´!r™'OŸדŸÜ7ÕºùÂ9bRtkË»¾@Ïá¿ùœANã~®™X½Ñšø³Ëý{K|笥Š3Gª ³%Í85Ï[µˆÁ3eŠI´ŒyE{¹5–””yl¥ØÄdÙºyj)HnBË6_ê™õ¾è$¶™4š½Æ@öcävš¼Ëý¬Àå"^ÕÀMm¾—¢: 7º©º'㊉¢û™d `¢£ÔÎ]ʧáDeÒRKº.[ÖŒŒC·ÂyaTp~»eš£X³QÖ˜”Ñ`P)#î–øNÿÆ¢BŽ„ÆYϤEÊo¤Bº¡~ñ £¼°EËs‹K˜U$–WüÒNæ»y†=ú¼þî £ã¦3·âί…–“•žÎ³Å%­hißpøèL÷èkÝ¡®T5¯žZë~ÅÚxÖê€ò’Úu?û\}öN³Óå <Ÿl€‹ 0+Ú‚LØÉ#^ÅM!MkS¤ZuÐZl„-Ñ÷>vï-¥e¿n Ê2‡îÅdZ)  AW=º¡õ®³Ú+ù R”d\¿1ÒúÙ…8é˜IÛL¼#Á¡äPRÑÏHß”ºƒ‚Kg£µS§•Ðn&šëµuCè¢õMDÙB<èÔ &Ò:ªp~×)7eW໣F½}OÍ5– –çU ±müù…櫟ƒR5mSäÕ¸&ÔVµM=)ën¥šGŸL`g¶sR¦ í$÷ ­_Q6W}6ì~ãÅ_÷î½ÕôJ•8jߺ#A™¼<ÔÍYg+Q¸8|Zè8øàÇqÄgO;w{ÕA³Nc…KÀÚ<·Ù#'F¾ö¤~à¶­ZÜüÔ+x¹›óÕ¾™J‘Áe«Rim0¿)¤{†+5Ë•±HâF¹ÞÎï_\øéG…G"…b5±ö,E MÚàõ‰Üâ•|œœ<–S+4 k¬uI®ðò‡ù.¥9×\" K£mæ`ù¯¿Q;°S¤)/ú~ŽF§öËß}vðÍ'ÈW°§ž—úå ®—d~žxðx0u°´ÙNó Æ(åƒYc¶_N å<ŽðQƒ÷‘ð=àËŽ-9žZK ÓFô[m[ÝXOt˜e,’Ü6"ýHì#ëIzm+;}¼Ž{é̈<0– ÂF˵CÛb—ënH¾ÿ‘Þ1Öÿ犽|«ÿÑmš Ôä\í*~åé™k=(WW4X/ Ú* ò,DË æ5*_£ùƒ†Þ1°¬|Le»œòm«²ºÙùHm0ãsê:H«§vòü­èÉÝö+gà›»§v‰4}YXCÅ® ùkÏV¿r½zm •t´M©šFx›ÂÈò1Ó¡m'éØa&‘EÚ`ª¹èË Á ë'L§Ê‰RÄÜ‘ÒXR€¥-Qñøöíûê¾Õž—èhø{¶~ôT2¸00$J&â¨p¸.‘r-‚gŸŒì·GvŽç/´S+eˆp~E©BõÙûÚ e½EÅÂrQé߸Uh£‹R}C8½fj‘8~šã¾÷þrß-Ÿ9ÞîénoP±Ä€±HJ§xê\å+óÓ¨mÕôæçNÎý.OúÈf"#†¸‘à™¶îü†!t°³R®î[Ë¥©¹5låÂÊ÷/¨2Í¥¡UÐ98K ®H œ˜¨MQI†SÇ $×`5ÃÐò‡ñ~£K\SëÎRu•hGYe2—èýíèØnÞëI× K êÙåýÖúëqï‹GÙó‡È‹‡Kiw.±ØWUv’ò7q¨´ÞLme/äÅ`Î@Ÿ„Ì Òm¢¼€@ 8¢É꽫ò5>"Ba­˜¥„Uü_{dtmk3·C¹Œ1ª)4(18í™ãai nl$'O»¤-vè½Ã~arî@ÍõÓÚrˆ´ /¼gž¬Ñ"OIð‡oÐ5ˆFIºÃa_| þÛO»?}___f¿°_?¹“l¤¦ ÒÕj7ã‡#9ŒÅ£ ö>‚í$ÒÏš¢ô¦(*ûJ‡Ÿ3Gg²«:7ä<5Jb…,ø¡CÁL)w}|eŽüÕküöz‚T}ûtò/$gOàñ0˜b¯^.ò Péêa¥öìQƵ¥[$ÛŽ ÆX?Bˆ ¬6ã‚롆«€% ºlFV›WW q¾Þ2S6ÇNW~ífñÒ$û4ºW¼­|åJÖðëÍþf3wŽÐû×·®©ýMÓ›ãP…—¾ÙìŤh0.çù¯>SÒë"¿ˆÒ"m4Š÷?äí,V/|nxÇ0]–€­-œÚÅ|y˨pH¨¼Ã¯lýÇ7³7ïJ€`”¡-ò©VCÄ› ‘m§IQâÁH¾k4õ u˜’˜à4¯,]&A¿Ð$ V_Ç|`ÀF!|óqÜ(‘±½hçnžÇi«ë÷{ÉÒ, ÕýÃÓz¤\l(öý÷Õ ÷¼Âan~L˜‰ÔCÇ“Ò]•ak=žöèa£T—æŒÉÇ1øVž`pŒÑžL_·ºÌ…fß:€öÖÉg÷-Úÿý׃áR_4©¨Ë*ñ@?||ØÆìàÑLöjûê©:¤bÌøt.×­|¢­¨á É¥ìŽ|á)YÊlâ—þø½`¾oG]± ð7ž–¿ñLðƒ7’ë«ÅWö›§÷˜L¶»§¥ÅŒ5#;våOÑbÁ³O2QWDAvU޾€Îìu¡úWÅe†ˆ²Š°<ƒ¸»ëE’K÷É_½VÜ^åZ‡»¶w¿þ’}øLc’ñZ#ûùu(2íÚ ;¤öˆ‹-âBti8¶ß÷)GÊÏÄ8D®%Âk úN)MÈÒö:PZbVØ$ ƒëÏ–Í ;½¢Œó«í¡¿x¯ÿêma"²ÝŠ2‡‚ô¨*L‰•mYªâÁÃjñ#Òü0 ½ò—ž+—h¶ÞR>•–‡Oz¿ú‹båVÅ\hïSìvŸ±á¥+y#‚Í|£Ë·y8æèðÑÊæÕ|ï†mÍg²æüÒ7y^¢/µ.µÏ=è~õñ¡lŽŸ‹4/ óÁ‡²™q`Ã܆÷5…È&U Êxʯ/f«+¡òd¦×qõ£•ö½™½rOq•Bi 8 ZjxÐ"†L6L'Ï`YÁP63 – ×(ÀñÒòìv9!Ž‹)X~×µ÷1ü×uíTà»gÇJ <¹+ݵ¤Þî£N/[…j…í£µ¼ Ο¾Ã“Ä dèzÉ~®¦Oˆ³§ÒhÜiñpe=ÞëàC¥ú!gL>AÀ·âÅÇ=ÚÌÓwM-–֪曇ñÞ2º2ïêló_~{|¸¾¯°4Ó1%q\zülºhßqNúÃ{†û“åR–‡2B«…KÿùÞrX0RÚ8½={¶ú­Çäfg‹5à­«íÛíò®jçųðÐ)V¥õŸô‡m3T‰¿ûLNðÙŸ¨ÕwŒ‹ÆRF?sã£1¯ú€wóòÐ5™ù DWÃêÉçÕé}’ë¸Ãt}ø~£3ÕvïBÊ}ØT º·üágÞ¥yPoøÏ?<ƒ—>®^û³ÌÐìÜ/Œï+çݾä€ BPH´Â‚©M˜ÜñJÊ$-l§ƒê>q LzðY®Ä†v4ÆØa$:U¾GòdŠ¡% ³÷³¥50¢g4Ó¸MŒï 6aø„¢jõýnÏ!б´ÈUnUÍñ°©ô·‚ùÏöÅŠôô`¼ög̓{ÿË÷YIÄ_>_Ô5Òvà—弃q[¯–0åù}Ó`éâÝùZ†”ZÏã,¦.Ð ÷ÇløÍ§ì¿ÝÌ.ý“¯‰=QòÞ'%õI\Çpç4vl7ÐÜA,ra%(ð<2TÛâ¶ÉÖLxáÿxn+ÔeÌDä@aE²…Ï@¤„‚•ÌÓH`]šÔGV½ØT™×lÛT¢ZÍ!FVkž5mA ÊH0!,›i 9 ÌŽHolÍþU¶eš‡ŸñÿÇo˜ ·ÍÏ> .7ók?c¯Í¯¶œ ¶4€']ÙÞÎ*ÃöZ5Ž7ÆÊú…—ªsS¥wÞ%G“Ánœc>€ÐZrã1„zyqÙö\Æ8Š÷tý§¹¿·’¸>dþ,ûý_.?|Ú¾ið“O{·7?»½ñôiðÚðͧíÖ’÷^€7šé€¶¥dvR4YF'¦ÕS'ªß|~}uÓaòʧ­«kõƒ#ê‘}æÑýªöÿŸBÞ_ÍÊþ[Oã3æþÏôúë)r\¤Ÿ:ê©„5"¥‰m*}׿;¤2ô³hûÉçíá™\Т?€Ñ‘ñ¥Êúî>,`^`ܲ¶›õgSøÃKîÅ;@)Ù?Œ¾p=tnÝpnþ•ôtð—F÷×:u­µ´IˆA€ e7<ß‘º…bU8AU†ú™jõ˜Ëœ'Ï!nræÂçÊð5åhF™‡@€@àÑ4tÉ FwîÇ «€yÏXVÑNÀü1*g­ÖÊ{M£AÕ™ÔÒ†˜¨l¶j³ŸßŸÎt{³Ó*ó)yö¼÷¿~ß)ËÁ×Ãu\õhž9…êM`·…y¢Îj€ñ—îÞ¯D^ÙŠ !òÜâ¦[“þW…»"EäÿÓ_ûªâƒO¹Ö½ý9 Ïì6(h?‘†k‰V*mµè]“öUùÒ2|üýn$JjQP–a¬¥²…@‘RF¬ÂŽM´M9/“"5[¼0¶\Ö•ˆR¥â\nê,½`8å%°…± €ZŒ§Ñß`¼alv~Áÿ—¿¬.ßT?¼P»Þî^ƒÕÿÍYÈ¢Á† ’©æ¤tœŠÞ6>”%[SU5ñwvçøûï’#ƒl7(m?„ÀZñú£Ø Ò⦠)¢Êöd¿ý%gssðQ«¸¸Yùüçì÷ÿ&:{ úÙ½­W>©Þ\¥?º¸ñÅóààÛOÃâ&ýOï£÷ïuÛÜ+´¦Ü0t·ÝåɯÏÐßü¶¼×™Ÿ¿ùÂàÙ=ÃC²9'²ýãìv³^œÇC·—º‹Ei~- × 'rX³[„m‰ŠC­`"ï`U&²ÄëY¬ ²¬»Òû«WzùR¬Xð?ýAvþÁÒÁÝl!‹îwó™Ga; ™›Êýî¢D΢0ìqMð0›CÌi„ûÒï½é]ü¬¹[˜Á_&ßz¾êD= nÙ ‡É¶.ZEN°Uˆ€zªEÃ/hÒÝeƒ É7\ØÒ°¨GRŠw«’;þï_Y~ï³h@{@üPPM8Ö`‰w;iß¾Mx¹÷åSåÏ5Òx©µåýÖçöÖE±(‹ÿñgêÒ2Ån^oaÕ¥ze«ðxf=h,¹éÀ‰ g­……¦ ÷óuøÙ|24‹"üô¦¨ •SèW+™jFj®YSc`û¿—%[íÍ8;8QúÅÓþ¶ƒfB l;ºñqr¸1ÇK£Jß7aÉ r¥!©.òý|ÿ¡ÚI? ùóÏ ³T 6ó<3EI¾ø-7D>cÆØRp±Ô„ `(ˆâ8bÓ|t.袗x°i»EHqɃ§Xï½ûy×ÇТ`„ª"•ÛlFº;±TZº€¨pªÛÜD&4ÚvÚ6vêÅíË!ëeÈV‹`›Rgܨ‰¹Ô¡c( 2­†n¿ßßcÔ4‘òšl;®JÖì-î­ahFÍ;sëbO(gûB˜½-·Šp|—Úy¢W¤aHâÃðÄgÿ¾¡vÇýtyKÒ\a Š>N¸ Å«ˆ\ ã«ñ` rf I®Ãðà¾ú‘½…_ííbÅROß¹ 7ŒF8,à&hv³¿¾µõÆÕÀ–K¢b±ÃûæÁý`útæXq`X`¥þÍ_Åo/zZÆöKöÄ~1ºœÈ‘²’;¨[-ïöRç¡êø.z`§â­TÔ*ÿû«ÅGWC䦚{D;¯ÌŠ·/ñõ5“VU@«a“îœ1G'h©ïÙʉÒëfdEÜB+ëRÞÓpÕtnK—%n©Õ³ e!vp¾ÖO ÿΫß}\îй”J†´šæ­òܼ߆bÇ —£Ë÷r@šj£°=HDá€7Q~áhOk#½ös›/O@AAö¸}°RªÆ:hI7½ymÔ„Šq„JtFtvÈJ‰ý4 áN1ÐÀÆ™²NÉHns×E1'mx@Zª€|þh=Ío`S9&9úÏ?hÏm–˜g¸(4Ì-ÃÍ;Æ(?ô;¹=×&¿2;œ¦:ĵ$ ÅQÅ}äxº}ÒzÞRG½úsçÚlc Låµ{#Ÿ~ÚÚY®ïæ³¾ÝuÐŽ•ë|Ös4ô\O²d”vø”d“H"J” Ww áèäaâ ÚœÐx›¬s´¶Œèº!à¥Ã ÉÏw#Tî>\a^%KDp÷ãbÐíÖ6Ö¼u•n;&‡ˆÜYÏ76£d]”<ô©À} y”ÓÜ>xÄÝ] Wnå+:šØe§Žtcz¨Ø7Ïe{÷T{]çóÅŽ‚B3—hö.xŸ,]§ü²7¸ž%ó<_Ö;WHYä> ÷¨Mã;Xo"âó9^¾„>×ÓH˜ÂX£›¾|§ùÚ• ,leHéROÜïÁC‡ˆàíáàHl´þ7ßOÞZ/«"”ª{ˆ¦»t@ÏægÁ€¨[eq…ËÅB^^€÷ûÝoÝõ^QõÿÓúWnû>ãVíòa9½Ú(„‘ϳúÚzÇÒ~šƒwCÆ÷šü°Ÿ!ÿÊtçÕÞ.Cd™}’ º¡ed(‘‘®v”à ~UåE FŽ×›?x](‘êXe$S §³’í{²T;©ôöîLý ø{¶…T€3dâܸÝ>Þ$uRJÝ’WžÁW–â¾NR.swã§Éœ qOñÌ©¦¦.€ ÖDäQ¸ÜNÓrÚ¼¯a²YÐYPÑ¿žÃ]7‡q²ñ99Äy7â^‚Q·l¡oIÓäè)wlþá»þìgßñÚkøáC;""¦êõà“÷óýGF>çtÙwKëé2¶0äÖ Üi‰‘‹7>ßèaCJq¶Êµ‚!€dÌߢ¹ÿó×é£üž…‰¡ðÆÕÌ¥¡°Y¢…p›p°¨ñÏ»L“+é r-•À*õ*o'ù:*Õb8ߌÜŠ‰!8ȸ…‚0mµ JßAW?çÖŸ։‹ðÐÜämÏìeWRØb¾ˆM)W9²}$-0â씖ä¬V¶8«9Kë‹Æ†‹Ë¬™A{=^î÷²\ìWk¯ Õ˜ºÖrÙÏ1x–dš|v[•ùwùOî¥3/VÎpéÏñžbÐ6f«€fd[ûmžÅ½&¸Sv7sæ._£ÿ&W¿ú¢ë,C=ªÿÏ?TW$àt2‚£D(œ-4`¤&n“¡¾…a©Hn®¡ÿÏkøï~5È7 -ÿ»êÏo0œð©2tÀÔÇ Œ‚"-¯­w,¤9Hp›v"»·Ÿu¸$Ÿ^@7Þêîç`«Þç=SR¸„µÖ²¤äb³®Ò¬–›TðýfÒüË÷ÐÏnÑ¡Ñʤ/¦ª”°óQ·zŠˆŒÚ›FÅ3¬s‰ ŒÍ48½˜lÒjDó^ÍÇÔ‡ížäƒŠp÷ÝÁ|lmš™, `‘T†+“ºsÚ±FUÖÖ­Y iáÌ‚NÝl|“Ó%PØgËû²î‰æ.Á0 ­N­"ýdpä¤;²KýäBõî›VÓîzÁr¡UÇçåéJ…Œ­”ÀPXE·%Æ_ûk|ë³Õ-ÄÈs è@0]Åk‘®¼þ3´÷(|ã2Tñn^ébäh¬säq¤8å K¢–_îKv/%w (ŒV’&:}¯/§Á™‰L 6#Ý.•Š\`±Â>Îß#W/çiˆ£RaâðsÐ1¡“î8ì¸eËÚ¨ãDYßb¡b 4š t§»Ž¤ÞH%•v´VnvÚýTo¥Ñb†ãf¼Ðm1æš\ ;e `„‘@JeDà%û ›í‡.ð—ÿ(Ýõ|õÌ;xp‹o˜a„;VmTCÐ…™r¢žHãî–2ŸÀ˜Kço^óÿ×<ÿå/a´^ —Çþß?|¾¢€u§{œ‘CEP⨅e¨· °å¢cz@©¿ˆÐ|Ž>ÞŠFÖú­—¼¿zßn%ø¥ÓUFÖý÷÷6ª3ÞÐUõÑýö­¦fÂLIÂ7d_¯‡ï·ÂÙOÖ÷]v‰ è|PlTü0-Sð€è¬Dƪž!ˆ–\šÇâÞFíÚ\–ßêW,íË0,ëÌŒŽÌ­›Ž´€‘r©ÌÍŠ67ÌÍÀ9îÝÍ·Ö¼»–φ¬xBøâšf.‹¸B`4‚Üö±‡¬ôzZCÖ¯…ÃwTs%ƒ)Pw&j0‚P&+w7SðaË,øÉ– ~9(‹¼M}ˆ íwl³üÞk]äBRD˜Ú´3ð·³ÒjkÆõƵþõ<0 üÌš ²J«A!ñü‡­Ø?\ÉmÁ­¯¨EVêÞʫۗn–ÿòOÂ{ŽPæD´‡„ ©ZüsE&\(Ѩ÷æÕøúÕ–pQlX¤5KM?ðþëMpöøA/GLО•»Ôt ‰;PÐOŠ+ÃK·ú_ûVs“#'ÀÚÊØjÉóbÕ¿Ó ]à)™ °»G*êo Í‡yY]KmÉö·Gšy P[1¢1hÈk‚°$0Ž—¡,sìDK' ]Q—?‚²;„Ë&ÛÔÓPîCÊ}bsŒÀÝîØÊçñòl ›’­tFŠ ØÊ(¸ÊsœÒöZ)×uð@i2€®1Ô ¸ŸhõS±ç ÷óï‚ûˆ©µ~Úþá¼Ùwn­å[еD[Iá[-×·Î=wöN8ͬ3¿1?X¬IÏ^YÎ/]¨~ùéôÏ^ï½µÊö8ô«‰.ƒ¾î%U°ãЯ0üc¦žóüZŠW¡øY o塇Ìü†r}Y„îç(l9ÞìýöÀ{wIjÍñv÷Dù­÷U«¨8NÁó^Iñ$ǹ ›Ž‘èßã$”¥¦ß߯à &ȱ)G€ |òª±·¹´FèŸÿª]i/º«²Ün]Þ°›RA\¨pÔ 03ÆX Dkb]‘=6¸m5Ý–ÕÛ(-lÕÛ`ß@iê÷ŽoTòá8…ÀÏàM†îÊJr a‡#pEùàóåsÞž!lìV?fÛöõ ôú\!˜zÏ…²´×À¨…>‚÷M,.÷VÒ,ª}U$ªHƒƒÇwÒ"ñõ ­q‰ÇÇ9ä]ÃÁÂõu‘taÈGÍ  å¶å9 if±.,Ç+÷£F YÞ’¥?»ÿÁuëP'$YÁ¥­Q%´té=g´ôP½2ê¹#û_ˆ >îy`M4`Í+Ên8{L°@âO4Qž1…Šàš*G=(Ã0!L9#•ò¶a=´CaÜûŸÿ6Û{÷+†x…Ø@F;$DÁ+¶Ãp^Épö‡æ2÷°ïJµäÉaVý Ù³¢S à‰óùú*¿tÓu1?¹‡|ùQ½sº6¤D¯H[Ô#íB ÿŸþ‘Û”½%øÅ5h°ÉÌûy~ÃEß2žÁòÇJÍXxŠx IÖAü„ÉYé3ÀðkÆsQ +I:E½’??ß|õ]x÷6K¬<~öNVÞz_4óÈq3BÓoé Í²©k%(ó™ó=;ºÒ z{ |Á”rÌ WÛ,Í|ö>Gšƒª×ñ¿ü›Æã•Ù-¶Ö!kÝÎåu»ž+H€é’$1` Ä€1”PPHýmËv*÷6¶-óÛ/D GW~ƒ úEBŸ’vÖµc’ (Aœ[°ã貎RêK,hênKyvî€úÂYzpÜUªÛç|±½í'u¯ÍgÆ(KZ”Ä®…Q ǧ›Íb%I1ñ Ð’i.4Œ òC?)O7·ë.H5:b;(h§éö5‡°2 ΗuTB žOк¡(N†8 ))4v|7+˜±¨4<—â‚u’‚TSEÕVU‡¦ÝçÎÁž!(9 ‚úz|ÿþ7Ñm@)âºì[2—ô18€f{Î*ÿÔÚ’öï!àMÈ¢0TÓ|í1Á* þY¥] Ü5 µHfJŸUg¶³©Ruj jScñÿò‡°ö_=;î󎹊8®¯ÙOhzÛz^àü74iY?zÝÕ^T{%meªž)öɇòõ5qé¦ëa~r/ùÚ9½sWTÐåI‹y¤[ÿä?W»‚Oùù·rVGN›ñ…ºÌà›Œ’ÕV0:¬ô ˜Øj¤A0§$÷TC—ÏïB6-”÷7å~ìüùÛp©¥…3³m¨øWßÂOì,ºƒàÞ†–¶Î2´-3K¨ô=ˆo![vë)h¤¡®ÝûýÔç«F5 ¬½#UÛCÈi/øÖA4Äî¡tß4 ܬ7˜XX–”9X±°-¨?´/Üè Žk%8‚qÉp As¤` `)@‹X®i…Ù*ö"^ sÅ(!%£g-ZµÊ†Èza IVEyÿõo»ñ`ÐlU}"}2(»0`±ŽG3=Š™Pt¢>þD2:&oÏ"×ÂÓ cã×:ÂlQ¤Nm3¿÷ ìÐPê§ÂäÃÑàØ¾:¶É½¥8§‘²Ld™@F#t;©ÄÄ.b›…ü˜D÷)´°r´Ò>ô!È­ž‹Á!.1"Áúsaì8%pŸ8\-ú¾aÇÑ =55ôâ©øÜa¼³–J’ÜûËwÃ$´Ú°0 lôCG¿ItW£I_+ ²n5Žê?³é5«Æmu—Ò당ä¦@Ž}öûûÏ¥ggàÒê¯/6ûW®:ë+ÔJXàÐXŒDðÓªµz¾²'ˆÝ®Mßµ„2M/;l zß B£–=ôIabc‡=t@8—ùfê_\ìQ5õƒ ÁG]ÝÂg‘I¾ZtywmÜx°Úns+(††QÜ4µÚ+i_£:z-”=ȹB¶[¶u¾j¼µV)0ùä¶Ÿ:¶@?Y+º²³Ö€®¶{…æ˜À0Œmæ“¥Æ;E7ö†ÊgIjÊçÊÕТL‚…î@>OÔÃàyS©Ä*ŒA£ÚºH~M¼õÉ èšv®Žû›ŸŒŽíɉQpi>ŠŽ Ú`®¥aß:dÖð‹ÅÀb1Knçú†-¾ÅS‡ å!J)$A;¥Žêиýa”-· øÓµL÷Ã4¦Ì~çK;–ÿ³^J³Bö)[ )Ý7ˆ)Á÷ît§¾;Ø»zñ=׊}Š„plËPvò­cSî—™œÙ$$q‰°¤‘ª(ètÃOüoÓë÷†/¼oïÜï[Õ¨£X*`êeÂf¦æœ;Çyã­—XkµK­Q*æÀA&¾ýUMõæ F±—@)* …ÝÍnüâyw}Þ_°1Uä†j¥˜)ìK‹(¥Vú@À'9Ñ÷xqÏèc.9 ÀD$\:GŽC”Ќ֎K¾ýØfð%:»@¯ÞÇŸÎóÛë¥kòÊ{Q?vŽ  ì+ƒP™Aî5,Z€ú ®ï¶ªˆ­A ^‹cÆ*â‘ö?¤ß¦´!Q[[ÞlëîúÄ` ‹¸ ŠÕ\X'æ•;äí;ÃçΨ/xåÆõU Ê-‡ü¨ðî|#S @Kq¸¸eVVºå±!¦¿›2ÐÝ’w°™oÛeÞQ\"Ó?¹"í³û2´°¸-Ñï}=ðÈf \Å"I3öʵ®ÜæFÙQißÚÅðû !—}j=Š‘ Ð4kâ21x ?ø y+ɤrh9·7ÞWw쀥ûøòûI¼»ºc¿Ö&ÉXC!S`Ve2ïÂ(w樵8VRç ɹ™óR"Í$WÿÿéíÇ®ª€ðoÝöå\ö93gN;½Ñ{§÷b¡P•`€ÒDŸôÅD411!Q_ü7|41¾èƒ!$ FŒÒŠX ÅRÚ)C§vngΙ}ö>{ïµÖ^üþ†¯[£Åæm©dP‹Ú:JΟJV®jаûþÕ2ÿ2Þÿx7ÜǨNwÖN͉áM_#æÒ2´-6ƒÐXÝ`¡–ûþŸ£„éžÐ··׿¨ª€ !šÏ=„°õ¿.¦ÛùéoÄI˜O`Ž×*ýRV3Ÿ^*ŠûwŸ<'ÊìÒû²È½Af,l§¾œ}HÜÿH½{=>ÿâVÃxO¸†½2£Ž 8yt½×q&%¬¹msÉ,|HzûåÃô¶ŠÍížz|Çÿ`œNµ6O›¬ÎÓZp¡в~KðÚ!¢zâ®þ)h»â…'ì<¹òž¬Ô„Óaâèø™gHôþ[ËÃ~ûÌ…fØ\u&ahµ‘–õÛRUñõËj¼¼xîÑÆ±ãâíffbÚÂjØO<‚‡O4×®ªK7íW¿¶º°ÞƒIbwS͈N`½›œœÌtƒÅ½Áúö<š¥Ÿï+5h}þÔ¶kK## 刜£±q^«u‚/Pƒa""ÐÚ@Y ”‘"XQê "M씪ŽzZ*g`,q®æµrñ­klmµ8s’\|J¯­ÿóÀ|r¯»pË¿zE¾úŽ9=¥‰8³Lm$ÜT[ÂXê¼1r„$Dª@][Dáþ²BVÊxzR#ÚóKé˯Œ -3G€ Ôfªåfw¤½N‡Éq^ànµqg˜þCôkQÔòíFš¶´á „[Ìdv“[·ÏˆgvÁkT±!£a©šîèß?*ª¸è®ld£°Ú°ËCòá°¼“ZÎj´æŠ40Îò€ú gr-FPi_Šcf!¬ÿëÇ©—=žp9£T༠€Hb]¾2ÀÜáè¹ɉn>5+áAX{´Ü¸ýúh»Å·SÞÜ5 ^ $´ 5Mñ¿Ëê}FS ´l̇ „‹x^ÝEïË2ƒ0ß ð°¡N*aÊ]K¸‰ãU¯ßÎuvÄýÏFëÿê FŸ¿Ö꼤:bEõØÇŽoy§ º&”ã„T‰ß½py€ûª;'ùÊÅF‡¥¹Ô¬ðã'ÆÏ¥j¿ûûüؤ}kÐ=¨ZNHäÌKXÚŒ–ëÕœIn½•yögo^vÚ›•ßùVur6¹ü‡M7Þ.ìúÂeÖØµƒ±Õ²&’8´ã ÔÆm*̰PÃRRŒåç¯c?ßyÐ_nöŸ«‘Zž2Ý2q¦Eê4À™Ö¸'Ì5 ¹!M›Ô49”¥$õI¥ùE%|Ûãkjk Ð"¢"U󵵯âßWg…»q/íþ`úð^}xçäâ©ñh]\Ϻ—näk730Û¢ 2«p®¦qΣ*Ú!9“Æ¿ÁP“ èfæB¤Ï4¸Êŵ‹xkV»w„úúàTОV½$Ú6­B·–ˆ†Dûz¾U1=qib{ã@÷\~Ѱ+Ž,2©ñhqt4É©Ö{©¸ÀÈ.˜qÌšULiáÒ±xl{ëðó®ÐêöRŽÓPýƒ”_‹#ËX›Z£¹B„|2aŒ<ËXš×F`“ØFa~‚þmT°IJÊ6Ã9±ÖSScË8(ÂkšÝâÐþð‰³Ó_Iª™~Àú8_K>{u¸ôæâH4öÆ­Rd>b4÷®v¢² ¥®RÓ&‘á4à%1–y ^ÕÕ-ßYrJòI†³$•8xÄ*Ò@éõÔTkœË(a_dƒ+#|tóöÔÂN‚PúÖð"Ó¶ °&-¯:dæóË…¿_)¾såÚÊ‹/…ûöæûgwõæŽfO?é´Kæ›íuÑâ0ï ¹'ÖëÊë(„’¬‹èβ^^¬–;æ/­>ýÓÎ/V¼ñý䣿ž‡üsOç_Û9ûÚï×ø°að忈ØÝwdÃ1á”X—¨ÃØ3eCÃÀ‘Oô­7ÜprcuæîÔàÈ©0/]ÜFãP) jB±ºªy‰÷êÚ—!CÓÒ͈„±µi0pDÙ@㊃&ú‹³Q[ÉÂ24aµ ZtåAgåá4ñ jêûýÝ;˽}sñtž>_ÏfßütëÞB^Rxƒ Ž²Z“ó6lq~êa-§3¤u*kþiMkÄ»Ks¡‰¨®ÒJ"!ZºHÛ6ÖÇj÷Îèɾ:8¶gêI£ÛNNvš²ŽoŒ!¿•˜fÆÙ6‡ïj¼§£ÛLXc·ý£P{ú0ËÏò%tEXtdate:create2016-10-10T23:41:56-06:001ô %tEXtdate:modify2016-10-10T23:26:33-06:00Þ—¬IEND®B`‚fvwm-2.7.0/default-config/images/background/bg3.png0000644000175000017500000120073514147024700017063 00000000000000‰PNG  IHDRôôD´HÝsRGB®ÎébKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEà 4¢æä€IDATxÚTýé%Y–ˆíÞköwÈŒ¬ª¬êÚzcw“½â6‚ ™¡I F€>Ðü ÿA€ôI @‚F3"$ ØÓM69=ì.öR]kfDF¸¿÷ÌìÞ³èñÕò‰Ì ÷÷ž™{Îïü<¿úÖ¦¸3»š™1àðÁ€î`D„ˆÀHÙˆˆÜ="‰ˆÆ:€ÜÝ5@DXŠ«€™qe3‘16w/HÄ\"@ÝÝ„¥ðXG~"ª*‰HDp5œ™k›#béj­ËºŠH%îëF¿õ[¿õ¯þͫꡲ°°”ÀÑ|é½qfX×ÕÃJ)1œˆÌ,ÀE„"""Xpt+¥˜Y¾0wg.ªªn Ì"4Mõý»·ª½Ö)" €ˆJ)°®7wŸ¦IDTÕ,Ì»™µÖ¸Ž1N§½ýê]­ò/‘©ŠP„©ª™MÓt>Ÿ=ìz½ªª€ uv@w'dð@DFP57tÄ`F!êªÌ „ªZEºj^n @`f.`S›i]–y:@›­µ—ë²®«¡år}ýÉ«å¶2s)Íû÷þîüÁûº^Där¹ÍunóQU·m#w%0wEZ§üL^=½ÿ^D",4¾÷½ï½ýòún"2M"Þn×:×u]×uý¥Ï¿ùòòë²ÔZ—eA FZÖkkM}¸;‘›5’@fŽaS­¿üÏðƒXè¦33sh¨ê`GDww÷R ˜çú®œˆú ØyµÁµ(ºªF"®ë6ÕæîDT0êÔ–Ñסù¼L¥¶Ö¨{¨WaæmÛòï2Fš»Y0ó,"Æ6\ÐÝ+ !š"QþÆišÜ<‡].—e¹nLˆÈ€­´Fâî×­O‡9 œJ)×ëÕÃ\D²èfÌœ¿ÉÝÃ̤–ˆ¹^¯\ ØPND27$Q7ˆáî½÷R ­·…çy6Çýñ1`æcÇÀ äÛíVªô¾Îóñt|u½¬]ýxš}ÝnfcŒq<Uu¬ÛçŸþþå¹÷."ëº ²H‘R ÀÓÓÓOúÓëö~š& l( öÞ a7í½»k)……("ò-€ªS@>ìî^*ÕmÛ^½zu¹\ÜÀk­ëºFVWDt7w©³·ãLÇØ®§ÓA¸;—IÕ=°”bµV‹9`âLM !.ËRÁǺy¨ªN‡S© /ËFDÛ¶”R†nùhèX0‹s9"1’…"ÑþÎÝ YX²Ä!B"xìï ‰ˆ˜ÅÜÑ#IM1ÀT!`ª•™ !ÂܤHä½ ˆH"ÅÀ0ò;u¨{ D¸¶Z¶e=ŽñÅ_Øè­w $Dfbf¢|E¨[ E„»#R)YC‰ ÷wîÁÌ_D`˜ç ªCuèˆîîBž"bfž¥3/?›Y‘ÂÄ6lô„¸Ü®",Lˆ(\Â=ÂÌ”ˆˆöŠ“/~èˆfvóˆ@"ˆD" wD$ ˆp`" "ß¿Ñ#òe"ÂýCCtˆÚjXLÓ´¬7DBÂW¯žÉLCuô jiyêo[||å/ÏÏê£÷Î,­Íx[o"åºÜò' UBBÀRª» …÷Þ§©ª*1ýì‹/¶ÞK­°¬‹º‘03©êº®ÚÇÃ,(Ì”Yj p7eáóùlfÌŒDfˆM ˜jcY·m3‰¬ëÂÌLÏóéôhêÄ‚fn>BUk­"æ¥uËÛ¾”"ÂÛ¶–Ò¾ýí_úâ‹/_^^ÎÇãqY–Ï?ÿüº<›Ycô!E™Õˆ‘"ÜÔÜH˜ ˆÝÂÌ™‰ˆúØjkˆÀLî¦:ò&ÏÛ•ˆ#ÜuÛ.<úp·óùì®Â²®KËÓ«‡ççw/ÄÌå|~Èr8†JáˆpS"Šp€ªD´-«¹€¹3@!Bt5€ 7]¶¥•2F_×m€UD”R˜ÙÜ„Qø¶.af­Vsë:†é:¶iš\…ùát¹M…x¨2³A¨3;!¢uc˜Y¡}&¶îcŒ€ @@D&BB!."Ùg‘GäS7ƀض-[®u]©°b,ÄÂ"Ìp~8›{ïÛr½6‘Z Zx!"BÑ»ŽaaDxœŽEJá"R <8<À¢ÕvšS« j€Xj9NÌ|»ÝÜ£µš-dVw@æìÞ¨µöøð ¶u˜Ã<Ï­•ѵ”VK[·^ªDøårQSf*¥¬ëšEÉÜ—ec<<<¼~ýúñññååeŒîî§Ó1ïßÞ5žo_™j)‹@lÓÄR ™ó!e"ffDFä¬×@E¸TŽ5u73Í9U=Oˆ½¤l”`š&óèØ…˜§iŽ0ˆ#@Õˆ‘z諸lk˜aT„¥fARíæ.L­5dž¦YJ ¢R `)„`6ltŒU5s&9¨™™åB÷®u¨aÄßhÃ=0÷/âüDÐÝÝ<<"[ $d$bÌ ÂÑ<0ðc·ˆÙL˜[Þ´{£G4†™{Ø „@"&D ·"Àív»a¸BÄu½1 21 @dewó1²à"Ü[sˆ DwÏ£ÈLÝ=›tG #²‰#"lmb&3aŽp0S"Ž"æD²'2f†´7}D,"ÈTÐt´6a8¸G˜08x @6€ˆ¥È¶Žo­ÕZ?Nî¡D\k%Äð Ä,Œ„ˆ9Ü#<+;0qV®l7²£¬µ"íãH^]â¬8afŠ€¦Vk)¥ ÑårAôZkž¦‰¿Õ:•©-×%O§cï«™ºƒ©m} €Ï>{óË¿üý¿ü˿콷6¡§CÎ(€TDÔT„oË­ˆ0 "Ün×R¹T^×EuSaU›Û¤jÌ<ÕFŒyµR¡ŠôÞM‡ ›;1K&Æq˜kûö·¾ùþùyYn"Üjéª1Í®æÎÄsk­Ö¿ý;¿ýÓŸþÔÜ…Ù# ‹š™ûáptó&eªmlýP#mËz<Õ”‹l:†Z‘âæ „¾éÈrÌ€"âfD2Æè:²údK!̇ژ(Ì…³ßWU®e˜Z¨ƒ†˜»šW‘@ˆ‹DÄ­o^[EfÖ>ÔLÍr\e&FÎ9"€PXòGdbB w#d)ŒÙá¹¾yóç/}ôZ«ªà4Tsf•RÊñp)Ì’“«ª!r-•`ŒÈ˲Aø¶¬à^j™¦9 jm§Óq]6‘2`¦cŒwïÞ½{÷ŽYƪc]·W¯^ß®7üÎw¾ór{îCÝ‘JmR*#÷mºY–- $f@U ·@áB„êjnÄ<´#î­ok"Q)˜ö¾0G'$b‰À6Í,…XT"""C ;Ló1a t÷pDݬ¥„Yïóø@`‘mëhf}h©„«yx˜Ž¾­6úÇ•õ™§Ã“¹GDVjH¤" „dï^ó`ÕZÃ!QD)rqsÌ›qïûˆ‰)O€ <÷?"Œã+î&±H˜š{¨›YÀ\™‰É# œÀ®×ëT‹‡®ëZ˜Ü‘¡ Ú;ø¼26FV\F Î9vŒ¥Taa³}è€ÂDÄ;rµÏ䦆†àîºmÝϻРDhLfE10‡åfAÄÞG ³y@@˜3#`ø"‚„ÈÈ}ô1¡Ì—´ƒ¼;D€„HÂfzïÓC$g ˆÈeID„ä3™½$JCä¾ÿ@ DÀ®£Ö çÓyÛ¶Ãá0t a‘‚ˆÛÖó®`.>ƨ2•RóË»ojÇZ&©<µöþÇ¿øó?'¢¯íkÏÏϧÓi¹^~ó7~ëíÛ·0ϳš«êa>˜¹»3ó4M—Ëó]¤?>>–RÀˆ öFv+Aˆaô¾F¸‘`ñp$BD‚à@ò¨T–Ûuèh­.ËK%ÂZëõzSWwχ‚ˆj)®º.ë_ÿÕ¼‘Ê¢ª[ïc PŸÛd[ÿÚ§oÞõ^Ç8OLân,ÒLjˆ6M9œU)ù9#1%8cfŒ‰<ÝñAÄÂâîcŒìÙaë=",ÕF¾Zs7÷Úꔇx´ÖœcäŒ_KÍëÞÇÐ<^TÍ ³¸„çy·†£ª&Rt‘r;@D`æ}ôpÀp”RÃÝtÔVK)÷Θ¹o:Æè}ds#Â6ÌÕÈÜÃÝ‹”RjDœNÇyž·ufÌ €×ëR¸¹CcYV®µ!Âããã<Þ¿ÿøø8ÏSnàz½¨å‘yŒA$$"µBX¢ #33aByQjA"$dUUUŽÜ`1Gàápè}dáJX‰‰³ !€½TšÇáp$®µµ|µL²,k"RjD,Ûš{M¡BDcha±¡Ì¸mz¶eY.È#Ao!d€·¾­ˆP„k­½wÞa à§×_ÛK‘„h³¸çø‹:ÈLµVLŠ™Ð‰K 3f.ÂYk<"<Ì-¯Sb<Ì ±wÄ€”ØìØöŽR›…³{¨@Dj•Í,1ÐÊ×0zˆÒx¨ ‹é`fb& Jô’ "ï9wƒðD 7A9UP6ò@˜¿Gïª}è6ú–ïu/ºÌxGës @wg HdÎ÷ €TU¤@€™1#š«»ù÷&"îy E„HÝþ/æ¡pw® IUóàÉoËãÙ÷ó›9AaWõpBÔüfî†Á´¯ ²ÉGÀ’Ü4ÙïøuÛDdšgD–RZ›EJ™Z¾$anµ‰Èÿò?ûOÿèþ`žçV¦Ã|¸¾\zßj­C;ö¾1“õ~>Ÿ^¿úäååe¨êðVZáúÿáðî˯j)ËmaB!9L&êÛöêé“ׯ_‡ûóˇmYˆ™ €À{_·u°€@páàac4’Çãáx8Ô&q¹ÝZ›Î¯^=}õá+5ÅÂNï}Œ1Õ èþéã«Zëív;γ …ˆ‡óùº,¡°ÝÖ¹LM„‰ ¶ff–M ÂpC‚’«ó*B̵”\T:#U€JÎ…döKîê¡}“ªD£”2TE$Àïª{m3ºqžú ¦U8M³CäÎÌÍÙ #Ñ@Â+%Ø=)+º“pá\…LÓ<Ï32÷¾mc0Ó<Í2¶­©S½]oª~8"°oYè|~ˆˆmÛÜýááñPgó0sB t3­­>>>-·ëºÜòN,\†"Gí*"Èâ1´«Ú4ÍŒa}Û–å B¬ª±ŽM„K)¹ÿt7D8æu[¹p!„£‰²d‘YÖ¶œIÞ÷˵NÛ¶%ÿ‚¸ñJïM* ”:†! æyè`)RE q)¥ fåV3Ã{Ï}:ŸÐÌÆ¶¶ZÖm €`̱”Zç6/ˆ…˜™LÇÔ&±a[_³²;“º3óðÈ} "# 5HÈìÞm8 `Î4„lÚEDXà f.µ‚ƒ3EÄ>†…yÜ[üeˆ³„ç-…ˆ”§PÄßÀŽ"ë&áâ>Öm‘ÂÙÌÓ”SØ4Oˆ€{Ë nÚ·Ø»ÖÀ{ ®î {  @ß_ZX^QdBD–Z̃@ûØ"Lµ—Zˆ‰(±”¬ˆ"Rked èÛŠFÄ‚€ÈI(2s®­Ý–k„•Ztôûü#ªš7œ»12%ÆJLY€‘kƒ@B·p¢Àý¼Ì‹GD„œãåFND!;GDdâì×>žOy¨ bäþYM‡ær˜9Ôb>žó¬3s",¥P­m]nÏÏï¯×Ëèý×~õ×þñ?þïÿùŸý ¯ëMç©m+Âñ¿ñÿúÿU&\1è0…Ëÿê¯Í}žYîƒ!2‹v'‚1†ªÊ¾ŸpýÍ×Þ˜ ·¡£8R˜™æ/Äq®õñááÕããÓ«§X·µ÷í¶Ü,ìåv s'$*¥$æ~œ GlÙôÐ1AJ!ƒ§Ç']6·Õóù|¹¼˜»CDÞöLa.ˆµÔ¼@8Æp„Θpš¦V+Ü1·@7÷œƒUµ”âÙA×Z¹""å+¾·£o„¹mB6óá&EtÛ€°µ‰k55@ðàrh³”ZkE@.D,ÕL‡‡D”",Å!¦yn¥å "P¤Ö‚Hf^©ådÃD®C¨Õ©Öv:=˜i­UUÇ"òæÍ›\›1ò².Ûz+µ¸ûÖW"¨µNÓ4†@©“¸ÅÜŽ§ãÃÃãc©eŒ1FMiÓ4­Ûb¦QkÝÖYó„®Î„Skзe]nCˆ9Üî¬ë0ne<’ŒÄÌRÊ*Ì Ýd‰Í%vòöêâÙ av¶½kÒ‰XÕ—e#äÓñ¬£aáî@˜«ˆˆH¨µ©ˆór»ö±D¸‘dcÇEÕL óÜ×Í\«3GB3¿­+SäÈ\§s–QÛpH”Ävä&!çû„¸©"‘x䤂Žà`†nÖûffRêããããÓë~[réçà÷³.°"3 柞^e™Þ»Va"t·düä¯ÎïO Å}н&a¹Þ®çÓ)ÜYÝÑ#©@¦nF ¹!L¶¥‡š»oœ#Ïöì‰ó‡ ¢ÈCžhëƒBÝ­¶â6ˆÐ=À£”¢cÀ¾dAæ¼@Uutâd$V33oµZíü¶ &w%ÁÒ²²'˜XJ D5Ë 7Ýû"f„}~ôw-Ò’Û’›Fsw7ˆli-<û»ýŸ´ô¼iï‹&¬íøøøäê­µmÛæy^·•™5Ðß|öY&‘ËUŒøö·¿ýwïï1Ó_üùŸ•"ßüü—¦2ýÉŸü·nºnëÐnaOO/>´Zÿâ¯ÿŠ‘Ÿž^/Ë:O‡mÿìŸýOã×ã¯þê¯^ž_<܈æir3BécÛ¶ÍuLÓ`‡y:§ùx¼^_lèèÐT{6ÌDUDH(€ëTžo×kßÖÛz 7` @¦Àܵ„5 ñYÚ»¯¾:?=nÛ¶Ü–RK>WL »™¢F”V“h´nK °`Âë­ˆPªCÕÂÇyÍ}*mš§<>U•ˆ)"öý“jm™[kYz`]¯j ‚Hai½+¢€ %¢ÖZÒ„¡ ÷¡«ö¼¦éà€#Œ !uÒ¡D%ƒQÍs³-èèÛ¶–R­«º¹»fSèf.(á^DXØÝJk­M·ÛÍÌ—eY–›™µVÆè—ˋ۶1† zï#±(Õ‘3D) p#ÜÚ<)}tfž¦¦ÃÆÐu]ˆpšZ)óa‘¡ºm›™©ŽyžÍNdDDwM®vIbHØëOßÜn7‘r<Ü@„[›T ‰X‡1åÐà9ý2îU˜ö¥&"¿nÍÇÈäææ^Jq¤‰+3C`D Âõzá>V"r×Dz…jm½çêŽýoý­—Ëóº®ÇÃaç³ 0³-™<ÎÐæ>º›UÚk›CsãÈ4ÃÌÀ§yÞtpRßJ©,ÙeK˜€Û¨eg›Ü–etõ€àÌÄBµt05ä‰Y˜˜b #–W¯?ݴǹb "a@ 1µZ+„“ÐP#,Ef Fd¦ÒÇ ‚ºƒÊLDyœæù¬îFÚûBE$8"Â-Ù0ˆˆŽADTD™€ÂÃÕ«”<­µ« …@ï=À 郔’yîÇÝ1,À!@$Y( LfÜÂMǶK‘‚Ä¥Ô(ŠXë-¬6ñ0$6[W³aêî]G^òʈ„nàHHBLÜJÕ1 Ëq>’ïBaAÀ©†uóðùñññá…?¼û \õ0Í·Û ˜Dèúò¼^žŒݬHÛñ¶\ôã¿þÁ¿ÿ³Ûz«µþüg?ù7ü¯œ6õÍÌ(<¶uã"×Û 4Üìv}ùì³×·Ûåë_s:¿÷½ïý«?üãu»©n曇’$ù¤(„é Úݽ«.Û¸]n±m7u×Þ7DDŠ‚‚àD>7~8ÏÇÚ¼Çû/?üüÝOså ¡CGΓÌH¯_¿¾­‹›æy½ÞžÎç§ÇÇËûg 辌Á_=½Z_®3UµŽŒËz+µ–Vɉ/c‘VOÓ±ø0áª>$¶±–&LP8B]mï‚kQ5·(RÄAh_µZ/×K¶–[_T¤TfVSm³4ZŠ0©6ƒ>}ýéëÓ£Ž-÷¥…ëÜŽ•KãªËÊȵ žÚm[o·pi:´‡BÌÓ€‡#™Z-…‰„Xîàa!G ¡¥÷"­qZäú|nµnëV ·Z»éðADÄ ‰ª*–2¯Û€ëv†Ò˜ q¡>¶aÀ¥>¿|@âRJ˜K”ª}îQ›˜ÛõvYÖÕá¡ÌL$î!\¥`iO¯)çc5g*´n/Œ}ŒÓùÌRÕ܆™J)¹õMž¢¹õ©Uðnb`j]‚Ó¦£Õy¨·é€H§Óƒ[̇#÷®Ì<Í3 ™ "`×ð€ZËŽæÙH2t2B<|]–d™GøËûçÛí®]»ƒ$ásCB‡¸#íó"1Iž]aIùéJD]µ-YeÉ(ºoc÷F€Ž|á{ucbdCôDîÜ"™×R[MjšM."m[ØW¨ÄBDÉU€Øaaq÷RšH‘ZÝC¤˜Yv⪚T?·H°RähÄw² @°0¹;˜G†ƒ'®±£lªj¦ Ößa sÕˆ¦TZQbÁ;îîɺq7w%$¤ðü@HŒÄÂe§%$'\1tôû™-D˜D! ””•õuSg¦}íânyM>r{ÂÂòZÓ¾*9¶Ï‡"zµV‡ )XŠävç’"Š‹ðõryþê½0à¶mÃtš¦25 ë†Ûº%uEªL·Ûíx<,Ë­ÖòüáC«M{߯¢j£«yª±4q“Vk„#Bï]‡½¼\~ö³ŸÿÁü7憥pï+‹$Ïzžj.LE8¤ü¤"€ƒ T‡û. Ë0 0QMðÐa]×uY¶±š«¹››™¦˜ ²ÆÎ†ì½íc¬½ÖBR>ùôÍÚ×ZXH>¼û \+ñ²n1O ¦Z \mľTÏÖÇ€™p˜¹[W…&>”©°JD”R,œ™—å–J¨ãñx˜æˆnf½÷­÷Ûí–K¼R*KÉëÙsäÈÕj+¥€Eß¶———Ö —¢nÌêºõR«Ú`¡ëm¹-W–ò?ûOþ“mÛ¾üòËyšÌG)…ÜTDæ6 ɺÜ X?êE„ùkŸ}ÍÃëÔúØÖÛ2ÍÕÁÄ›$\–%woç󄃹·6‰È¶õZ z˜©;3‰È²m½÷Dƒ[›–¥Ã4M©?Z–ºGáV˜™åüðp»^¦‘Ãá¨Ã@¤0ÕÑû@d Z×ÅFßÍgáÃñ°.›{–R",Tužg"ŒHé%‹8JiæHÂ\81jsó˜ÚÌ¥ ·©AÀããúmmšR÷Dˆ„áfªœJ•DÞÔ:b „ªªŽ¬&uÙ³t‡Z|íkoæyîº!âØÖÞûÓÃ㺭÷—\¦ÇD vJ#àa>¬£çF¸üÿKãÐݩԖ Dî'AÇHÞBÑriÉ©11J¬yXXÖfAbÕLÀNèñ]ßD…ïçG 2±D3í¸srk-îN©T‚„p"Ìsÿûêcï—%5á¹rðý,q‡¬þTòÞ¦TˆD„™î|C€ „À@À;­¨µ&ÂyVªõ]R¿>ì|p€  K²ƒE8ì;ñ»dG`!<¡gD03ƒ}!áèîAI`ÛÉ«DÄá"r½-‡ãј+— @yø¹*˜ŽTSS[— ´ wIÜÐÕ£÷mžgS«µ“™Ûˆ‡‡Ç>lÛ²,·RÊr»¡‡æçO,».ŒÂ݆öˆÇ§'sc)c¨šC„ùXû-ÂY(ÜSÌÉ(‰šZ¶"B@Ó$­P-¼®7]˜M•xǯ1G“1´oÛ²®Ý»GÔRJ‘¤Üä ‡D©Ü€yš(àõãÓr»ÝÖ%¾xû®ˆÔR^>|x:¿z:=Û)Ü=|ªµ¹Û7¾ñµ÷ï?p)cŒì†Öu€ZÊP%–m DÛzš|œ¤¾+`kkÉZÉ]‹™]nW»Ofq€[kyi‡éƒ‰YØÝSýäjˆXˆÁj©ëz[{¯¥†ƒ›×ÂjZj ˆR H©ö§z»ÝF_#œE\-ÌÓ¡°ôÞÝBU vö0ä}Q˜“ð~¹^,\ÍÝít<í ?ö­‹”yžmÒ>RõHH[ï!\jmEÄt¨d‹b8Bàºnf;ó§÷޹ M¢Ð<Ïë²§eY[ ér[ˆYj3)åüðÈR†šH1 )Ú5À!H¤ô®¶ÃÄDû³ùÚˆ0"i¦ž­›áé|f*Ôj3‹ÑÇ4·m“Z§Óèúôôêv»]®—|ûyùR¸,‹öQX¬d„ðmlÚGJfulNùkóÎ Ô¦ù—ù—k“/¿øBÇÆH½oc]¥–°*—öÄ,DìI÷¦]u>?¬}«µ²³LµFxRµr)ìîD,\úÖ݃LGØØ˜„‰³Äñwb)uŒN,µ–ðp¦RkÅýSMRç‚…RßäµNªnáy ¹™%µ#T{áöòpð]B†‚R !å’|G3ßyì°ëzö’$„]JÉóÃMÃÂóP ‡@‡°€&%W˜ ÚÍ ÐSûÎLIrIÑD6Yw.§$ÒÌMÝ ö·Ã’ë ³ÀHü»–âfµˆ›sOQBJÃÝ#ì΀Hz&Ám¯ìŽ­•Rj‘öôÉ›@æ²õQ„˜v:¡[˜;!“ÔRÀ!£ÖòúõëÏÞ|vy¹ŒÞkkADDŸ|úæñüôüüáåå9Àj‘Þ·;ͦçñVka&",µ0³‡£{Ìóa¹-y¼¶6 ÷¾°ªÎó!ék¹qd‰8¤€0žkkÂ×ÛuÜYF˜‡/€še£ž]7çBUŠ…%›K‡²Èºm¹MÕ1¾ñµ¯oË:—æ‚îÑj;º® ب§CÇ6–ËujM{÷þƒ¦Ü€yøG6aê8"B¦:µÒ€)Ð’FÌÓ4m[¯µm[w·1FRk¶¾3š¹–ó|Ê%Iîð§i:̇"e,«0#’ Àr»m[GÄÚ ‰\®×Ãáøé«§ã|8ŸOk_—uÙúdÞ¶mjU5ioÐjZûú׿Î$뺎ˆÐUI¸0Q)%ÔG8ª[-5%u¹\‚|Ûòl«OÛº‚ãa>æ;ZnËÃÓª‡A‹žÔOð“C‘Ò¦y Mùb:ô>ò–ÐDÍs§Rj@P0¡îËs&D&$â©Í]ó.´ZK©|½._}õ"žN§e]úè‡ÃñíÛwÚõÕ«GµþòჇ–RÖõFŒ VF}¤Øçä‰MẮmš˜Ë|˜Çj+@aïÛ¶mó<=<<¨š«…[Þ!i„n>ÍRX¶å¶-«›e» ±ËÇÑCÝÜU‚Xpèps Õ1<ô®¾fæu]ÇËË #­ëÚµW™Z­Ùz:?<=|òõO¿þÝïþú·¿û½¡±õ®}Dk³¯£çžÕîúç|Í6´° À§¯?±>˺¬µTvw½J½÷yžQ]1ýCÒ¤ED¦ÚÖeí[7·À½­AW›jKs‹0OÊÇñtøôÍ'_~ùeW=N}í·ëÕT?\Ÿ§iš¥„×uc‘Ûí²m[kÅÍÀâ|<Çëåâî?ûâç$4bä=\¤¤Ð©¸;Nx©•˜D(|Ó¥w%ÂÖÚTÛr[£։ Gw ÝÉr½L”Ø ÔZsFom²a§óùóÏ¿~»ÝN§Óív{zz©òæÍ׿ùp8„˦CÕ™ I)àj,œD¾óé´®ÛívC ðhm~xx.D‚»î°¸ç–*…>¸#š©ê"¦b¦¥Èº®ÛºÔVqí+3Ní8Mó¶ÚÚºl}Ûb¹Ý^}òêr½Ü./DàÛmQëµÖ¤äP+"U$©2˜–!nn–2Ìðv˜·mp6ÕPK` I–‰0×sbsfÃÌrtˆeíˆÈRˆÈ-ÒdG˜“ü”IöˆHPŠÔ2¹›¹2‘0…˜†ÐÎò"fa $U„ªBÔ–Ÿ¦ª¦ï'—†Tíx8z€HY‡ÖÖééññv»:x)ÕÃ1 ÖêjcX)ÅÃóüÏ•&@¢ dæÌœà÷Gª8QŠ­S™Ÿà:«ë.ÚaCÄZ«¹Cx'‰ž3!Ñr…N‰ ±yÐÎ(€}· ሞ²[Hv¤÷‚œšˆÜ¾2#3ë0Ue¨µ®½cú(ì'Ê~ò"“0IÜmß saa&.•¨l]‹LR§6ͦN„m>æha}ôÝ®€Ù͈ešçDÛÖm}´VÇècèÔ&p iž×u}ÿþ-¸fÔÑ‘OË;h—=¸û.ƒ@¤Þ·eYÍ )Üõr}&·1µÖ·^KY×¥HIü 1ÑÈàáºûår1Õd³™eCàùxcÚïÄÎq"HöqÛI©²¡ÇÃñ«·ïæÃ¡ÕfÃf™¶ëµ•r(óõr{óækÿÙÿêýßû‡ÿà;ßûÎýë?|¹<#Q0n}ŒPf6÷€H꺻ó>`‚ A2ÕV[mŠDDj¶m©¨jÁĘ­¶T…¥ X¤”€P¤¤Á3³‰ ³//Ï—K/k߈¸•j><â²ÜhßOŽÃñx[®¯^½Ê‹¤°pY–X¾óýï¯Ûò|»¸ä ÊŽkß¶­—R‘˜‰Ž§Ó6¶ZëåöB@1µÉ¦ÚR“.µ|ãŸçËåúp~ÌýÄ4˜è|:o½«êèÃÜíz]®×Ëˡ޷Rêv:>ç*å'?ý©ª­ëHµÖW¯^_.·¾-i/ C qj!¸ùÔ·åÚÚzÑ ³L9VŠHk5ínÜÔ=9 Ôî’VÂÀÚäv[ÍŒ™L•˜¦¹©j8–:1sáæfv˜&ðPí¦ÃmŒ±šéÔj¢Lq—…"¡0s‘ðè==,Üïž(¹ö£¾ÞˆÂ†ÞÖ[„W©`Ã9«hï¥=ì=‚vˆdQFÂ,"uÛÖÑ7!cK!Ú­©Ò—‹({ülÆÕ¸Ù†œÛ9$ â¼÷"0´wD2÷p,mªµB`x˜kBØÌ¼k<˜ù0ÀZkfæmš\ÍÂ’ŸúéIJ)M1‹û`á锊>B†H²£br-ðÞæ’ìZƒ€½ý5DáÈc6í8²Û5 "pwóTü)"1D~ø]Ždá»Ôˆp¯íö‘8K;Á_l2ï}™¢Z+¡HmîIS‚]¿áþÓ÷ý1 bòPÿÖ7¿S§ùzY>{óµï}ÿ»„ØÚCï–NáàR XJï K)û¢Ûºç6ÌîT<"6ubîc©…Þxa„øÝï~ûíWoMÔB‘"Y=Û41‹'ÉÌôt:Žm¸;¼zzÒÑSÅSk=½o9¿s亅;‚‡™öeÛ¶¾vWÏÏÐ]á²Ë€Ä£sÎ@æ:ÃKÉ¿yšBÄñpØÖužg&öÍ·Çãibyõððüü©F þµßüõŸüüGÿŸÿï¿(¿zyí4¯½ïêkˆd.ælUXr•µ-×R N‡Ù"ÌmÛ6K°Û¡µæîÛ¶µZ¦i2³_˜»y¢pŽŒIjb&Œ@„V+"©*$Å <m uŸŽpHzÙóõBŒU*‹˜ûОÆmëºO25JAÓ:úÛ÷ï|‡MŒ˜éÎhXjAFj­1‘™;øWï¿Zû2ún@– ÓáܦÉ=nË*\ùÝ»¯DÊè#¯èí¶€›K©"‚„DÜûH{ŒZËétJNÑåe)·ëí0Ï燇O?ýôýó‘ÒûðfHyjZ±.Ëíry1ÓÑ_úúx<3 s1G³, –N½oiä'RÂ#÷À´ã©HE*¹³8@¶yf,ùø½¼¼ˆÙÐ13¬Ë-Âj+¥ Q)≤”ÒXÄÍtt5ßkU!åøI@thÖr˜)ƒŸ‡´“Ë™˜k}DDd@@7cãÒæy^ÖMÕZ«fªcͲ‡tßɦÁV˜ nÛfaʈ!¾sÖóV tØñÄ"µ¶)T…9_?s)-]k˜è0ÍÛ¶å‡ûùçŸ?¿¼$:ÝjÍ6iûC»©ï^c»ƒÙ]KÄÈ„¸›ºìf¹M!+1 I)‰Ü‰ÌÇ9_!ñbËŸëai%y÷Šw'ÊœîÂa &@âRdW.¸2b¾Mð¼s ú<°µÖêÄ" "Dï}žš»Fï}>L¦€>|ˆ°7o>Õ1Â}Y–Zk¨·Z×mƒ)EDh§"Ù¶-„±.¦†y?Î;3†ï+ È ƒˆ€æµ”ctíC5ÞB¼‹ m(š;3³3;ý£¿÷~þ³Ÿ,— xx½½>ÿåÿüŸÿ_ÿ/ïŸß¾ýê‹éPWí˸™AÊ“®žgo:ÚÔûr>Ÿ{ï¯^¿ºÝ–e]Öuݶmšg5K…pkMDTÇ4Mi‚wëÝRŠ»K)I`˜¦©ˆ0à\ÛÚ{ mbÓ1L—më¦Ìî̈Ç!¤¥L6jv8LµVw»ÓÀkWEáËõª¦ÒjV³ÄdJ­­MÌ{ÿþ½H)L¥–ézy&¢u[¯×ë” ÷1qŒ…EØ|ô¾™kï£÷Í#¸°ª§Ï><< ×u½š92Jám[ ±–Zkɵ<‰$ dÒœÍ-˜9_vî®p[;èót|ýúÕ÷¾óÝ÷ïßÀz»":!ØèÛØ’r}[–y>X8±Ì‡ƒ0÷mÕ1D8©Õ@ˆ˜âDÝ‘Eh ÀRªˆÀ/Ä™Áu:Åîr)L(à@ñQµšêáôؘÜÍ ©”€>,=ÿMªt3›÷ª  $椧-€«@ŒÞ¥aªLÌ =Ô˜Dj–4[ÚÓ­-Ü–uE<N,…%!{G"â»J6} ˆ‘0¡žp¦ÞW¦`a¦¥°êFȈá †€\š„ãn¦V {xk2úH“5ÜãaC;S-¥ÝnK‹¨™šÖÖ Ù}nI²D ßÙ@P$%©fæ¿à6±0²‡;º†&ó‡ˆ  ‹ðcžgw/Òdb4wb*R<¢§í$8ýÉ¿ýï¶ÕZ›ß¼ùìïüÎïýÅ_ýð_ü—ÿÕ‡÷ïͽ Q•:µ¾D«³«µRSÛÝ{W‹ œZ“RÝ<×a $·eå©ɲ®EØMY¦p„RKϵí i® æHØ}´Ã„Èë²i×RÌÓ•´ûN"„‰ƶšv€Ü>!D–lÕ¾0!¸vë>· àL8úV‰ swf#…‘8Eµ´Â2ÌüΣ¦B4–­° þ×,Xj×\ÃŒ~[~úã¿þéÏ~2lƒ¸Ž.RëT‡Ž:Oæáæ­Ô©Ô6ÏK_IŠƒ[øuÝ‚°Îóp[Gw÷"áS«¥È¶­1ÜYx¸#Ó¶náÑ̅D‡’Ènà"¬CȺmk™jΧua×Lóñ4Í_|ùöz}o¶Š‡¶6#ñÃÃckÓ‡¯Þ÷u›[ûÚ›7jPJKÌ ýpœH0 JåRåòr;_ÍÓQ /cy8UûºÜL­¶âÔæc2¸ˆËÞêTÛ¡Ô i¸–6=<<>¿\JU­¥ ³Rêéé z~¹½}÷eï+PØÝ<+GÇqhÇ„¨,`¶.7Ãl$ö+¥°$Ü ƒŒ:©` „IŠS1`$WSsÏ´Œc‚ Š@„Pþ2¦‘~õW~MMçy¾\.¥ðÔªYvwC DPUD:Oˆ±Þ®ºÜrÅ»P-<·,µ–ô¯ðˆÖZìÆT»U±¥SuìøÝn:NĉД"®ªYQÕ lhº$!k®Þé/–xÊî´»ù¾ÒdÌ}ÜIìÉ Oú ÖzÌéÏÆèD´­«HQ5ºO@9ÁÄÎU¢:•‡Ç€X–%i6$R¤:˜šºYDby¦aþqµ»c2ù–;‹ð”DÝ™é÷½Sî¢8˜k#¢u[˜ežçeYóIU» ˜Û”OZæ]¤5ÿ·¾õK}ŒmçÓùG?þÑÿë¿üþÿÅÿýòrícIaƒ›ª©Z,ËZKû¨$Pí¾§—Ô©Mô}ŒcæÝtÔ8unf!Ì,¾ûÝï½{÷6"Zkn¾,‹&aÀÝMNÛä°8̳ê6ÆHÝÁÃÃ1Ì4ÀÜ]û¶³Öµ5f 3¢ô¬ã¤~ 'M͈ûH‘ÊE"Îó´®+"–"‡yÛFÌ\™Y8À‡u ÂÀ®`}€m>¤•ˆ„ðèfÂÙ†ÛÐDJ)fžÄßÄüR;Ü{¯Rj)sBhŒ‘ÞMI•è½§3³HÑÑk­ù™#Ñ0ÕÝ ¿ÞÝü0{é„3—É{Àá0OuÛ}Q×.R2½\.)¡8N„t:ÏçóéôÀT6ÝúÖ…%ܧÃWÏïK.|»¾”’æzÝÌÚÔ< ÍãÍ›¯½ûù»Ã<áËõZËt>=ÍóñÇçóÙ4èt:®ë’Dr3–ÝÑ$8}¼\^DÊ4=ür¹„"ùP›ZÏ›ÈγMc©í;ßù.Syþðr>=¸p8gãÕ«WC{¢Z­i2ðêéétÆ–4zò°d9!¸¤­©‡¹Ò<ÏÂ{æ åý™ã*¦½(í*¼Ý=ãSÒæ ÙG ¼ÎÓˆÌ4zG $2ŒÍÆ¡LÑ»ùÍ6®|]–RKï[’¤–nÊÌ·uUÓ>Ò“ŽÂ2Ò BDÙÔÂý0M{"s­5IbÆÒZ».7sxxPÕyšÕTw¨EŠ\—ÛH¹xÔRo×Û§OŸ§ã±nï/"ušÊõr{óé§×—åp8úº-ÝÌÜu(1€Ý"Y$i@ËÏDX̽Ö*¥´Ö„eèØz?ŽUŠªÈdá(\§ºmÛÔq˜aq>?šù¶Žëu)Mˆpl}š*@ í,`¡·kÒa½ÖjÓ4§,(ºžÎ§—Ëåx8¦‰V^µ?Uäååý¶ÞzßTÕ†¥Å»íf/áiî©„ ÆÊ”öùy”æ»ÈÄ\©° qDzÝ$·=5In\Ú ›9'¤&ÔÙÍÝMUGßö¡;iIy¢¥«=x8Œ®fc(#Að*…€s™\$nm:žÆáê+ºb¦f*µæs·côî!Ìì;¹ZkXjC^¦ð¿áÅ„ô‘Pèû’#Â03bÜö‰?<<æ¿›y$¾LRdš¦ã¯ýúßþåïÿ«wï{ïZk&{!Ážït—«!b ’¨ª»­}KÖZ®7ux„¡!Ä0ƒ0¢ÜŠù.–Øß…ÝÃOàŠáÝÿšDZó2Ò¾$t÷Òj½M“Z”ÚjÍ]Jûú§Ÿ^.ϦJHËrðãá€$8ºä&!†uscë}‰°1¶» NG"дÍûȼIã$DìÛâaLìai–»$äˆó<ëÐÞ»HÙ¶íÝ»w_}õ^M§VÝÆºÞöý DVW݆…‡©eJ$÷ƒ91q0KŸÏ=S€…Ð’T(B˜±8»Ï²ÿM<¿/Ù!Àïkû ™q4fˆ­–Ãñ°­k"ØÃ†›3†Bôœ¿˜m:ÍÃÆÔšGdY¼õµ÷!µ¤Â.‘º\æfù.¥¦C­5Ü3z ´Õj8†aán±¬+#ZØmY$×h§Ó)Ñü˜” »eØ×¿þëõ¶­):ÅßüÍßüëýðx~°ÐeY ë®ù¯ýÚ¯Oóü³ŸýÌœªL€ÌÒ®×åOÿ즶nýŸüþ?ùoÿäß .·¥TQÓÌžÛÖ[-¥÷q½\¶¾èØT{Ø`Ó-³•p÷0cÂ,Vˆ€¡ÞÇF,Hidò+aDÂ4ɺÛQ&Ò0ùŒ\Ú))àît· Ãk­9•\¯·©µLG"ó0H}0@ŒÑÉG›RF¼¹)B S°ß#â¤Ô4s(HÄ92§2…ÇÝ ñn¶‰œ•ÝÆ$I?Uª©1¦±Ýn¡—-?FØý¦VR ŸGBI„ :J)Ó4åïÝc: ©Hkmþßýoÿ÷ÿìŸþ“þÏÿÏæ}Ý–¾.óÔÒ~_[b.îöPYâ‚뺺kkM5厌ŒHaæ6Ü4 ‘÷Fò£cæ¯Þ]ò<'ö<rg¾[ò¢â^ä˜ˆŠ´çççy>2ó»/.œN81M‘×m1³uí"Ô¼”º­«ùضռ{h€3s-“¹U%Ü…ayGåkcƃ‘˜)ˆE¸!—ýÓ@t³”÷1 .¢1F­ÕTSÛ{˜ÚÖ{>Ep!ïWfª6ÚT#îWÙu%Óß0ÂÌ2P& «Ý=Â5©½„C?~°¹Õ¿ „$-pwBp8¦j^`–B‰8³sU‡áH\ˆhÀ0ßlë:ÂT3 qŒ¡áóñèwEtDLÓ´õ °JIÇ~–ôAˆiƒžÁiÛIÀáP€’ <†¾ÕZß~ù¶”RK­ÉžÌ4cGX—…Þ¼ùì·~óï¬×ÍÕõ;ßÿû¿ó÷ÚéoÿÞï®ë‚Âë¶½~ý 3——›[) ’敦‰[¼/¥GöU9ߘÙèÆÂÛºn½ï×PLƒ@w„4Úc‘óù|˜§ÓiY–eYúº1ËñxÂ’2ÉôæÓÏÖufßÓéH„çù˜© iŽÚjýêýûˆX—Û¯ýÚ¯d@(°ŽeôõÇ?þqD\—Ëá0ÄõzÍ,þä¿û“mÛæÃîDx:uèXo_½ûÒÂZ›ÜbŒÎiÔx½^GzÜ&©!(„[k3 Z sM7º¿øó¿@Š>ú4¤Èû¯Þ#áápx~þ ;ÝÆ9Ö[ïy|ºYB;Ý#Àܘv03ÂÁÓ3ŽRÔ³Ë)=åæwô€”ë3á¬ÎåpŠ=üh‡t™H sß6)åz½¦Q’Os¤4ŠqsWw pA$BˆÖš¹GP„§az¤ôµ0gi3qC©,IHO%=š©j²_ïÊ$¢JÌ!Bª†Œì¦ÉsIˆI>2L>*2÷4Ô]¼™]6)λésê&â[æ ê0¡üèG?ü£?ü—ÿþÿîz}×Óéhc¸YìÎò~§@ìŧ6uí»=€ƒ0Cƒ¸«Ez‰Hj2Ýõãç¹S0‘¥I ‡¿ñ…»MdÜO¯pX¶­Ö ‚J©×ëòÉ'Ÿ.ËÕL…è¶\=ì=¥ö k›ˆ˜©xÀ¶­CÇé|X–b¸jÞuÌ¢–\_ïªãÖ;½!,Ì­Öse–°ð\ o½#â|:ÚЈ˜çyo:ÜÖu};ϙ˓FCi"¥–œ~‡Cæâz0™ënfi~߬@.uò–FDaqµ=‹.…¼g1£t™²['ÀR‹›åwöÞGÄBÌæ¡¥ 2uU½S‰ˆ3n# •:O³Ô¢¦›ŽÇÇG7ªÙlæÂ­”âf(Ä ŽBHÌ´ç(€¹£ï* ;N³«õm;ÎÇu¹OLjherU+ÂÓ4-Ûš.Äx<ÿ÷ÿÉóËóÏ~ü³c›¿ÿ­ïÿìÇ?ùæ·¿ýûÿô÷ðWÿþ§?ýéáx\—u]—ÏæéXEˆ%ÂS³;«€†iª'wED§ƒªåœt½^EÊÓã3 ÐÃÃCmµ«f€‘´V®× ®[7!Bq3Ô>0PM×uuÏÀ^ï]Ý m‹,ÛZJ£ÿô'?²°Óñ´nk€Z ½\>\·«_.—a _^^¼Mõáñ¼,WSí}Síˆp»}ˆð©–ëmQóéát>_®/,t½^2²•P2¶zn›Öi†  µ_Ö¥ˆ$÷áÃûç6µuÛD(Í ˆ¨Ö–†Ì8´ sšö't¾»—$ÛÝÕ"„…3‹”’Ö¶éM{/”4ÙÝÜë®’a¢R“‰½+æêa×.Þ34ˆI0Ð-Z-H$’WL#ó Rhg¦c¬"[7s—RŽÇy_º¦vŸØBÍ ‚ÊééÓÏ¿ùÝ¥»šc’d! 2I#W0ÑÙ)x„§¹‚ˆPzzJŒ2ãŠ3+ ñ.mÍ´Ó›a· ˶ÞÝÕÔÍÝ´¤‡5" G€{dìÃx_~ùÓ?ûÁ¿;ªé0íër“‰Ìì‰Fî9LíÑǸC€ÏÓÈAïÐ?í¯BLj_DëZÜmCø#Üp×ÌÞ!I rK⻥Lis8šY)ÍÝ¿ÿýïÿüç?c”Ê,bª"r>?¸ÇÖûé|¾];s±»UÂ^Ãö)UË4^g¦pwæ=¦ÏL…KïlàîÌÒ˜¢˜Y2”j+D\šy áiT¥0KC$ÍDÓ=[*ÜM¸d\Ñ]ß°Ç1î™'FÈp7ôDŒØcìói0wõæFLn~ÙâÔíºëÜÙìQ%p½^wÔ•hë=I Ûv#¦ Pj#\™°qsLwkbî£wÓ®£o½÷žû3þ ADQ¤bð"N¡u]Í,ÕY‰ù™Ú›‡§œãZ©aþK¿ôÍÿÅÿü?ýþw¿÷göƒÄšjmRäz»†ÇT*!.ëúïþìÏÞ¾} ¨Q~ïoÿÎüðø_ÿËÿú6¶Ÿ½ý¢¶éx>d‡”¹Œc ³[_Ìu[o™:)ÌušÓ˜×ÃúºmëJˆÂ•€…K«a!Î\§ùx<ûØÜÇùáHr½\ÏçS;'õa®C;QI±»“ÐÔ&)r»]Mbä(ÜSÕŸ‚©pûHT¿÷(÷æ#Åâ,”#>qÈÔeè1å ‚-8Ü…‘YRk“öšà."óaÚzÏœCNW™]ÈJ@œ):úŠT—¢C óË €F¸2³ÔÉA«Ô _®×À`L¿|Õ10˜’î’ñbY¡œ§¦n™͈ßúü[·Û’Û3N[¨bŠÔ0§íW«» æO@­Z«î±m[ö¬;”¸¹©.„±,7æL[õ0Ÿ§I}ìýn÷šKI|ÛVK)µšÙ4Íá6F),E PUG2l}ìjçD“³ñü(QýˆÏ|œë)+>fB`¦!•vc0—DÃþóŸÀñ4/·k)e`SÍ´âyžŠyÔÒ‡ãº-µ–{ •…Gr98Ȉ™³kÀÝK©ªÊ"’Ô‰RZ•Yd™P˜ÖmícqW$¦u]…€YRĘä}ÂС}š+¥5æfÎE_ÁHŸ¼úä|8®·åÔŽçÓÙt<œNmj¿ù›¿ñGô‡ÿîOÿôùùeš¦$>äI_jÝ•ÎÄÄÔ¦¯^ýÞßþ¿þá_ÿàÏÿòíóÛã«óW—˺>ÛÔÞ¼ù´¯+ÏÇ9çøµo[ßÏLIv„çž)9ÞÝ ˆýžl‰ˆªˆ0£¦ÍÃÑ¥ ¸Y˜ßEgäîÓ4ç.Ìæ;C4·[é€ÊL’¥‡Õ­Ö©æëº¤gBö¦6ˆ‚˜é6÷œMÜ´¹Ý®C-À‡ŽmÜ\$[±˜yÞFó<•VÔ hO2t.þøOà ™º<Ç׿ñw~Ïiº­ï¥òz{W6µlÕJ©SÝ-Õúº"Q«S¸„ºså ÀÚzWt’ õ"eG*! x7¨1Ù/™%pÄHTÈ»iá’j^@,µ2£ct9$û òeD •žV‡Ã¡0Þѱ– põ­³”aÞ¦¦nªªjÃMêä[n@{’1³A¨ûÃé\±}ë›ß¼^/P›lÛz:ǰóãëuYÀTE*z[”"PKݶõ8¤TöãÿÄÄ›”~»§ãïþÞßýíßùíëívyÿž Žóù|º\.Ï—«ªùÕWNT¦Všü£üþõÿ«Ÿ}ùÓŸ}ùóãÃéÕ«O–Ûõõ›O{ßž_.AØûÈœœ‰"ýîoÿîÏös`JoÕ|DTJe0¨Ò(RPÒJæsMÓan3Y<Î$HøXgßFU –e]OçGPÕm³VŽàR<ÆÖûF"R$"¾ÿÝï»Ú¶nÌõáôjh0Ëãã£ZLí” ¬©L•…‰¯·¥MÇô¦ê}dø†ºuíÝm ö¾-˜½,àaž[-ËíºôešæîÓ<•Ï¿ùͯ޿;J™‚È-DäË·ï2mYß«mJ¨_½ÿr]n}ë¦^ Ìã8I BuSë¬]û¦¦fCÍÒõÕC=Œ˜˜R2’Tä8sD „h©„s± dŒ]B`¦Ú»é@4*Ìf;õ=ç1rÃæûŠ–™än@z÷b„@ØSrh‡ 3Z(»{ü*Mˆ´Ó©"©&„ù`em."R "¤‡qZ¨ ±‡9 ªMµ¥ŠÑK‘ä®ÖZ3ñ5]‡˜yW}œ3vþážô]JIó:Ý=ùFD$EZmÄicäž!$»=Á½ƒî¦Ó Du:"b§æ™ê;f+é:iwA£|„Ú÷ÄZ"@tÅépp1‹¸›º–"¸g?ï@JÚõ1îÆA¦c<>>¦ñ§ªZÐããcDÁãÙ½<¿0æÉŸKÓ=¢WÝÃïD…=v  ”:M“©«&:ÌÇižçÃq>®×Ûó‡/LÕueƤ9I)[ï‡6×R¶¡y…GÄ({x1zÚ½‹2RJJ¦ }ä}âÕVj¤{ŒêGƒš¼¬û]Ç»wôÎe»§)¦{&xì²ÞtúØ7ÑiŠŽD4·– ÅLJG@(¥XX)%s©òçïIX{(B(¸ºU))â.¥Ô²;Þ¬ëjªµÔÏçãËó3³˜j-Ò¤lëZ¸¨i}Ùn#|z8­£ÿéŸÿ€„¿ñõ¯ß^^·‡1ÆŸüé¿c)ÿþýŸýä§Û½ßû»—ŠÜ®kZ€÷1ìÝËWÿÕÿû_üÅþ‚*õ1.ÏÏÞ¿O¬ùýû÷æ6¦=–>O>ÆŸüäÇÈänÛ¶"Á²Ü’XVKmiÂn^[;£!A€>Æqšçv($…‹ˆd—SZs Vs+ã\¤H»ÝnµÖÚæ0¯µ©* •ÖˆXXj)ÄÔûxÿþ}©2t¡Ý9aˆë²~ík_7`®ç‡'øäÕ'j½•:ÏS„gÜ‚ê@³Í²Hº÷¾±u[_PuœÏˆ°, ~xþÀÄmšú6°¶év»Áan×ËKÀfÚ{;‹0"„9‚W©¶­1"Ìu¢ÛšÖÖ;ël¿U#íóÉúˆ{#"QÚA ˆàæó| D sS3 Ó°ÜáyÁ$-…ò8ÌóNÕ²›q)•‹q€ocˆ0Þ•;¼(3³4‘¡äS@šâÞiÚ˜jNJ*4:„ùÛ‰Akß €xOØmR"„¹ˆŒ1–åúp>_¯WüÏÿóÿÍÏþÅ_|ñððзž·HVU‹»™;ân0{‡È¡•šûh»ïÍ2qè2î†|fv·ŽI¸$3³û§ì²™ 3gèx®ñîóq ­6Þaà¬úêÄ/ã~íÊrNH‘’ È8MóápˆƒØÃØLsìM±‚Ú)iö!hÁÌÇÃñv»¢0¹»~÷{ßõÇÛº& ÑjEŒÜ¾ÖÖæy2U "ÆtnÈw•ka"£ßìz»¾<_>|xw­ËÕLçãüþv‰*—mùâ«/J-RËõåe®3D×ùpø‹þå»·ï¿ÿ+¿úÅ?ÿëŸþäË/¿|¹\~åW~å²Ü.·Ë?þü‡§ãþ›?|Y/Ê©e¹]{߀¡T €eY";bOÊù˜Ò~·ä sÍ'!˜¥– Ô‰D “<=<banµ¾ùä3µ±f˺J)µTr:œÏ½w3O$°¯ÛoýÖo~øðÜû6×ÉÝÇÖ-‚·¾±ð<ÏIUÈÿ³l ó¶mo>ýìÕëÏŠo·M¸ˆðùñ|}yaæÃq6óÖæc­ÓÐ5W÷é°“üº wuŒ )µôÞ@#к­çóùóo|ã|:¦ó×<µm½ä¬½Ge çNtæ¾np<Nó¼¬7B ï:úÅb?ðîˆ÷þwvÅ~‡RŒ„… ‘‡#rn,#Ùwû\§£ixz±F`)åp8õt7$4·Ñ-˜9‘)•ÓÜ*ÜM‰0 ó òEdìlIw°›?šŸ@ H! @`Äf,Â%u­žåu4%¼\.§Ó¯·—ãñ`6þøÿõ‡ç 3_.—ð8§¡ýn¸…츬Gj`£L­A¦¢dˆÝ^ îz("JÚoRL!å¿DÜݨM3 ü­ßø[oß½M¥av•;Û“²§éÞ-"ß}2ÍLZ¤>ºGô1H™J­°ó¾!‘Säy´ö¡CwÏ ÄÈ<Š ‡\'ìNœËËžúðüüêéÕº®9‚ðËõååùyÏÐ!.¥¬}1ŽPÊ~Fn½·Út(!PNƒw)ÌÉWfÌU¡¹©k-bÞulÛ¶ôѳ¨•Ì÷ÐŒºÏt\& Ó±õ>ÍSФ8…ÍÙgÊÊ~Bç¾ïjL7fnÓ¤£çc°ŸL‹ûneö‹ÇÉïq!@äàéƒúqÍ“¢€ûfõ®rÊš—²÷^R›n&R `ÓÎÄ¥µŒIRÄÒ¦æfOŸ¼~ á×å­Ô¹6Œh­81F`¸OÓŒ$ëå%…ËõVKy<ž 0÷u]ûz|8-£ßÖ5…RØG̵-—õz½ϧ_ùÕ_ûòÝWËíúÅÛwôwíÖeª·åör}qˆþì¯ÿü‡yÝ®›õ¡ K)æ&Â,\J±”Îಬskq<.—KD ÓívË$ÚÔÕp˜Û\JëV2¯ÐúæuY„ë<¶Ûòþùe³î„ê~<ªTB¸ÜD<ªº,·×Ÿ~úüò"LE K!¤>¶ÂBÂp:ŸJa3]·Em°°ŽáæJÄüêé3¦:µÙÃ[©£/:Fß6 cô>˜éñü€Hužq¨E`­eš¦ZZÒF^¿þÖ­ç¬(…Íl[íÛßþ6¾ÿÕøWÚû²Ü^ÜGì±5æ–Œá0Mî_-R¥°Àz» Ý™öµÞÍ;ï<4¼/ØöÅ;í¨ snS“Ù•ƒ¼¯‰ ÂÒª3‘gäROa %¥”ÓããÖû¶®I½`¼/ñ%È5F‘’; @ÄÝ*Ÿ$0µ³é^˜Ô Ä{0l}t`&b‚3Íí\*ÎóüüòRKÍWŵ^žŸÍlnÓ#\[«î>f"RµÖÚ6„˜P"Òà’Ú©¤ËÛ‘!½ódc 0ëÛnV[Û§“$uˆœN':F¯R<}`">æ|µi€"“¿{Ä|Ü‹{8üøôøúÕëÏ’ñ•r°Š¤ËÝ?.¥ýþÇ ó(Î0,ˆ}ŸIÙ™–W÷ôGVÕÛíHîÆD1zÇÝiö³$‰;x:žNÇãý¶.y¿r ©2óº­n6µ9mÜ£">¿¼ÔZ?ýôÓ±m·Ë5­w¾- ^—åp˜mØír™j% W‡‡§Ç×o¾öý_ûÕÿøGëÖß??O‡ãåvÙF„——çM;*sûâݗLJ“jWÕu]U!¶iNMé¶n·u!B3ß¶íóÏ¿q>Ÿ¯×ëáp@D»Ç@,»~*Ü™¸‰—1F«õt:µi:ª 뺺Ù6UNq#ZWS}ýÉ'óáÐZ}yynmº^/ÓÔJ+Âõr»0s¸ÕÖú¶]n×ëåšú~:Tkám],L˜¹”6OU}xx}3Õe¹):t]Öml-)ܬMGwªDTJKkåtµ[–5"NçDœæ9uÿm:!À?üÿè?øR,×ëk­â1R€™Õ#»À"ÍmŒ1D ¹¾Ícô÷l­1FdS)L”R” =ÚÑùsEøc‹H€œäžÖÚNÑħ™œž€Ð¡„ÀH­”yja¦„Qª¤&8—µV›¦ã/}û›oß¾ Rx]—ôLfá=5áïä\ï½çýÀDdR³=úv wχï= Fªq€PÇ8OEêíz=Ž9³ŽôíÛ7 YJ)0Æ`! ÕpGFF °(åG$"{JÞƒº3±öN ”*§ó) ÔL˜ÇPU+¥Fi±¤9\yD]ŠæÃËËËñx\Ö‰æÃüpz@@`¤"”é¸Ûè^J+µ|ë—¾ãîót\×MDRzz·ÐwÏ8Pwóm¬j#Âs÷Å€Á„鉖‡hÒN¶e“RÞ¼yƒˆIL\–›y˜k)iš±®=å ™Wé߉µ¶+Fì øïß§¬ÔLí[îHzìÿ™ˆù]FÌC2¾“r¢ô½úï~î¿ÐÄADRÍÖuÍü ÷(RͼÕ6µêj¦ ˆµÖRK¸o늎Œèj˺x„1UíCÍ¡–Ú‡¶RK)—˵0e˜åºn"Eû8ÏŸ}öæåÃóát¬¥P&½Ü.—iª Ds›—å¦jçW¯d’Ÿýüç×Û-‰`Y× ¸^/Rd눞_ž¯×뺭chF°AxmU‡1â~òÝM³Ó=—e¹­‹‡oÛ6MSï=wZLœÁ¶îááµ!ˆðýr¹&µŸ×m5 Äm¬Û¶¶R¤”ÓéH$·ë"ާӲ^‘àǯ"¬ÔiݶãéT[i­-Ëâjnc½”n~8ÎëºêÂìîuª)2½3ÓTkêŠÏÇã6z@L‡6z¿^/S«¥Î¸;M8d&©¹pùêíÛéph­Ýn ¾ÿüÙgß@¤óÃ'Ÿ|úæßüÛ{»\cŒÑ‘¢IÑPZÙ1fj…ë:z©MDºv#¿g,g?¶ïùˆH݉XDÎ. I$Ù4"t×ȤŠÀ}1˜þÏ{Í©½b*ǬqxÏÛK…$ÔÁ,zïcô<¥³ÃÂûþ4ùð=q†ˆ‰ î6XÈô7™|é”Ip8œˆ‰¹ì‚YDd¦Ã<‡9BèîÆ„¦[öCù±$tžKѾudz¾c ›ça½oi:ö ;sÄ„jÿÆñ¸7¼ù/Â-éíxßÄæèn°k&÷G$Y,µ–d°šÚÖ·”)÷ÞÝ£µ†ôÑx`'3ÝÖ•[kÉ'¦ZÄÂÜR¦‘ÓKmÍcÏ ¹ó¶‰‘^ÙÆÄÑ{Z¯à&v·Œ¢eä] IJ¿N3ËþkŒ±-›Ž1I}z|ðÏÏ~8†YZÐÀ—_~5Ô‰øó¯~¹^rßë"¹¤uD|ýê©Öª¦÷Ï–ò\TÝzß2{$&jµ¦BÏŸ_^®×ËŽh '&É#Ö̇j GÝî‡AjtKk‰~© S]–Å2Ùb—}l¢ó(Â=ø7‰I´ÛüîxÚ?òÈÐ]€D;= ýAÌ¡æÇã1·2iA#ÌAH¥!V3Ó´ƒÆB’N}ctiUŠäå¤]jI…µ›Á}ˆ$Q6Ínz»^ÿ£ÿð?üÑÏöôúõãÓ«Ø–žq1‰Ó¾<x:?>¾zõ£ŸÿäËwoK­ËºzØm]¸òóËsÆAÔZ{ÌüêÕ+Só3¯"yZÑPUÕRêét:ŸÏªš~Ú[ï‡ãñåå%á¾}Ò`ʺEL•`O øÈ¶ÈΑ@J)MÀÃ]™xÝ fº^/]ûétøðá})Rkùêr6€ÀÆè½ßn7Dœ¦v|ü˜†1Ç@îˆPUoÜv™âêßn½ 2ìMîìõ œŸ±Ï__÷iû)eö]^Z}…Cĸ£öF9ÁN@`»·ûê ¼‚ï€ÍŒãpòèÍŽ$V œó¶ÖišbÊ}Žø0®ÆÌΘ6uÕQ[«âÿŽ”»Nî×8É.Á¢W(tu`z݉G K-½ufö?À}CèßpfB@×U|5_z$¬Öê,u?zœí~Ý0ì‚̳ū­ö­-3õÖ®¹ûÞ‘‚®aq¼VmP$PBL1FæÀ\ÖÍÉà‡ÃÁk»ý4ñ£ÍýHh Ò™èp8ʶ²©6‘ÎÌÌ 3Skéµõíí.…%j­"XŒIEbHCÊ—ËÌ‘™‚Ã{Ws¹«›€°J1îŒr¢ˆAEÀL¤ù‚k‡yžSÎëZºêºÕ”3«˜Š^æù ƒqBÞS¶¹µZjõïü•;Ä@Õ‡Ã4M¦;ŠE»tµÝl3C&âZkŠ"ÕÒöâ$f·þB "‚}@[kn³Ž!,Ë’‡ÜjuY†®Õê×k“=_<Ž`ô]ÜLÍâ^¯º·¦Ø. ‚ÛŠž7äbªfH$;êºx¹½½E€LölS»«†< 1@—f¢Ú[K!†Üv’SVËéxòJ¼q‰#!µÖ8P¯íoû›tœ~þwÿîoû‡m«€¸•Õò8æÆal¥=Íç®ÚU>>>„K+Ì|žÏþÞõǾÖvœÇÃ1Ä8´Ú<â•ô>Û‰H­Ö²z°ÖRkÇ¡”BD˲8Î/YUkm!†˜€ˆ ¥÷Z›×ŒÔZbާ›ÓÓ¼xG›bC ­Õ³V}||Œ‘SO!ª¬ëRÕˆ©–R{³+ñmFN±Öšóà€¥y¾˜jŠ©k{ûöͧÇÛ¶Cjµ•µ 9% ,*iÌDÆD—óãÓãcÙ–.Ñ8€öVki­!†ÃáÔº¼ÿùñx3Ïõ¿þ¯ÿDšN·ýë_/óCzñò¾lëÇßÖVæu$aÞ }7h.¹.Ë‚]»jóÔ’t³ëæß/‘ªæðZ»ÖKx˜ª2 9 ³‹Œ)Ä£»VzW7òyqŠ“´öàI:ù²Q\C%īЙ‡±v iè]Çãv™3GÕºÿ£¦`Ýa̬ÐkïiYÀRäV7Ð&½U5%BU1„0FŠõ^1ìÉHl½Rh>*$&3`ìo ÒÖ"sï}?} bà¶m)ÆZËsë5€îÝŽÇÛÞd'¤ƒ¢Ð]¼fŠÄüâÕ»ÖEzS³q{5SQ ä…Å1eé’âÆª†äÈx2€Ú«!„K«Ì¡Ö8•­†bÌþ#´¶æ‰i+ÕЈéñÓGå4ЧŒ1sÇÚ[7@fUwܳî©1éÁwæÒ „È[Ûˆ±k‹)ºc*D@‘Æ!ˆîýKªcòÜé0ŒR‹¡ `Wæk!ùç#÷Ö@ýUÄ[Ùüú `€º®3€•Rˆ±ãþò‹apFŠ)A4³ÀAk•Ö1¦\kM(PJyÇׯ_Ãxy|êµG²ÈœS~ñòÕããSÖU¶.Æ "Þûƒ(µ ‡˜Bb Bwzh@±ë Ø­rî«!Eó/9ó.q~þýÏ—e6éˆàCЍ9OÔ™xg9 ØÝR¨«45CƒÀœ9œ¦cÛ æiêj¥+SDŲ¬u%ÂÈD™ãrÙê0ÄÖjä "ŒbLC¤õ²mÒZïmÈi]×®jˆOËü‹¿üËË|6Vd#¦âRU¤˜bP“¥Î”©C/]jo]Z ÁÌy`¤)åÞàG?þ©Š\æsJz«1„œ²ô.Ú=¹îŒul½iW0ˆ!¶ÚZo†`L£™ªâáp àÄÜçnà'®­ŽÇãež·Òâ0L`H!”ZDº!®Ûåq^BÎHìŒ#ª&Ê€@ÌhćlD!å&Qm­¶Œ1ç¹lŠVª¤8\.—¨•BŒCNÿûÿÃÿŽCúå¯~9—eÝV$Çi[-uN9”Þ¶Z[b,u‹!ïí†Ö›Ä˶–²#…$7w÷Ÿ>¥˜Zí*SŒ„,ÍRLØwµ©D™cÜ¡KGFçx{™÷BŽ1§40B#bÖ®1%rû¢ô€ VK÷ª!é9"¢yÑætÍå{'úÕ8¥ÔECŠjv<¾øÁçËå,Ò¼ÊODTÚuüí"=¥@ÈÓ8!¢©€™Ô À5æ=^éo¤ZZȉC !ô¦”‡„H"=†Däµg»`í•ïU‰œ•£^4£¶× ¢c`÷ZòTk?L7`˜³WÛ°¡H3Çž°{6hÝJ­Û8äZ7S%"0uz`lï´áj.$"õôTP3fB+˜š‚jT:!ª¨©#Ž]à35õÑ‘Çã¶m]zŠqY¶Ãéè‚ßC[kÛ¶Îó¥–JDÊײªeYÜyhWJ¼–Ì™ª‰NÓØu÷/^·)H„@ê?¬}׎‹CJ*’SÒnu+„hªx­cD¼2÷|Ë×ñçùϸ d»3y苨Híͺií½öf¦1„!§S ×­4i)&U{ùâEÝjïõt«Ip] …ò0ÆCm}È ‰¼ òÙ·ãçTïpŠOä+¬ÅQÅ ‰L-0(9ôÆÑ+=Åõ @–@D&û{ÀKÕ= ½Æ{“<ëRîï_¨¶ƒß@×u­µ†€ž¸òådñ\"1´ÖbŒnOvqsH˜µÖ ®ŽÕà»›`®•¥ßÈf¦Þ»ö;ˆ1úqæÃ ü1ò÷Ú”³ËŠ;tnŸJŸßûªÕ£ÞªJ Š}WHD€­èâßÃñ°•íõ«×>öÒÀ´×æVº¾KB†Ã8Ø0ŽO«ªrÊëV.ëbÁKÐDM̺âÖJU1FQi­Im!E1ÑÈ!Ç|÷·/´É8M—mÝÊê¾3¨­2ÅÞ[²sRiDíL̘ITƒ'c GF"âòa8 hà%<€H­µÞ;(Hï99%@p½€qH‘ 1r”ncm=¦S¼îMàx8p¦ö“ÿè¯þú¯D„)™ÁíÝÝÇŸîî_|ûí7½ sxûîMkÕï)Df¼Ìç¿øË¿˜/åÄÞúë¯u¾ q ~Ãc*jM»·]×Úݾ±mK-ëå2ŸŽÇ§óãq:ȯÿê U­©633í­w_L.Ëåüôƒ«ç»YýÊ%4ò­•/ÿ\†r'¹™ùŽÍˆö6g "Œü‹¿ï\bñF&f¦0 ƒ«ó)%„çzcŽ0™{–÷.æðŒØ½»½éµÌ—§ZÖu9ãMr€°iï&Á˜It?Ç¥÷F¦`BDØ%œ‹˜˜1§Øw“Q¯­Õn >Âûjv[¡A—côÝÀµóGKK03w¶ìh…yž×ÃaŠ1þùŸÿ·½·Z«A3³iwïaÉ9,Ër:ÓT¶’Ò "H.q¨G›6åÈÚET8pëb.¥ª4"J9žç ˜yÑekÍ—„aœDœRt|±*3G'—zO¤×Z{lЉÕÀ¹†ülAD@sÁƒQp@öt<´Z‰CÙVôÜí•™ü !y[Ⱦ4tcÕÎÎ$ünB€ÞënKŽ{÷Z[µ7%òåýÐ7€û·Ë2§˜¶mk"1äãÍͺ­¾@n­ûS4ätwwé~²ý­ˆèåDc 1"RN¹–Jϰ€ß-ê÷#wZçwnÈï@ÿTkógæyûâà9Š"y,p-Ãþ²°k^¾[™í²;³"TéN>(µ‚¢1Àa8dÎ[¯½n¥ô.Û²Çc0ÄHÒû4Rh°,Ë2#Ä¢·umëê£M†!¥QDÁìöt÷þÍ»7¯Þhk¥”¹nŤJ1³sæ´Õ-Å4æÌ@m*òúÕ[—Kiµz„йwÇiȹwqª¶ÿ¼„Xk ÑËÐ÷‹BŒИ©—î«Cï&&ôurª¢™µ*DBbâÛÛ“:×mmîà«ÍŽÇÓ†mݼq) Yº aJ1ã¸Ìs“þ‹_ü1™õq8´¶“Hÿøð!„àl÷ë aw.ÂŽdktv€v/UsyÍá†CJéÚ€êt~kµ‡{o"öƒüàßü7þ­¿ýÍo§›Ûƒ)º•¶y¨`]WSé*&Ìä`}Ÿ}¼iüæææýû÷¾ý÷{Ûwa ؽM{ âÏb¿ó@­™§iòëÿõÓgͯÉÛ½2åùƒØ¿R;ßÁöª¯ÝÑÌÌjÖ{‡+M(ňЕ k©ÐUEŒ1„0c)%RÖ›ö›ãMޱÖ:ä¬`µvQ?Ò÷"ÉV«Ã?Á ‰{m`˜R52üüÝûôþá¯þêWO— çx¼;3SHÄ*Æ bâÄ…’4™¦é¼\º´˜‡hã8¥8¼yýv]7#^uBˆ!Œã ]jkÛ¶¹…ˆzëÞ3B˜òcd Ò…€˜)&vªåº®Ã0ÔZnN·!01X)«˜Ä”Ü1EHw§›mÝJ©·w÷¢:Ïs¯íÅÝý8ŽË:bˆŒLÃ[/)¥ór¾½¿ùê«?L‡ÜµÅ„óü°WAx2Ñ5k½µîpøøáÃV‹—Œ·Z{¯µUDÚJ !¶V»(1G0c CˆB8)æÿô?ýO¾úò÷Ëú´.0Ñ^†!K«Û“ÞÝofpµÑ5é^ÉCVóTü~ãôÀ sò“ˆv'S`m.Î^ JèðZ€ÝÌâ4o5?"¯[L`Áh*ª33w‘ZkŒÁÌÎO9Åh¾<1³‰Ïø c`Ú™“Ïtûñ†Hf  £*´&@!8ewk=0].E‚3„È[)½íá£g¢Ã^˜9ÃÍím«ÍÍòµ•çöTØ©2î‚­Õãé´mKŒ<Ïg3ÜËë\Ëõw†Šº’~½­×u]S΢=DD½µ},aŽÆ<a/Õÿ%¥lÎ[T“Þ3¤”º 1‰(Åh†ñÀ!µÚ_¼xE;DÞ|š¦Cˆ­7iâ‘ßd„4ÄQºì}C»_øz@ûYCDÝÔÔ‡#2ö&Lc0US Þ+¼‰ ({1 !†@1…ÈÌ€ bøº¬ß‘ñÈ 1ÇbcNè­„^SŽ!íý*¸7Åx¦‹ØÛ¶ýúoþöx<ŠJmuÝVé‚3Ç니4ÑÖšûLzïfßá»"ÝÜÜ>=žÜæä³ՕˆÙ¿מīב\[»¹¹ñ¤[Ô{CÄ€„ôÿÇU¶?žýÿøØnØeúî_N>ç0¢ti½IR:ŒÓ«/^½|ÙJ­­¹XERJë²r ÔT×u ÌjJ!uSd2bò]‹—¸º¿0pˆ)1“ÛÀn7÷ww)ä¹lŸÎUš¡µÖ"Ç2ŽãÔ[Cäó‡Þ{ˆñÛª¶­•iš¦Ã¡÷>䉀Á ÔÍe@·…˜x†óùìÆ-æ î'ë=„bFÄRŒq&º´´&ªMZ“Ž„9!†&òty˜×˼Ì"JÝ@÷Â[DrÊ<_rNþé~üô±¶šsPf~xøS˜ç9&úðá›Ù@ð2?!ÁÓù±”æÉG±úí¯êÖª˜¨¹¯ºmë2N!"0L#³.Â!ŠærõÞb:¨j“æ‹S“n˲¤ý뿞çK\Êz>?ækm¥®½·ÞÄWwxX=û}rF÷º`à“%"yå3« ì t×›á®åoD¬×Ã]£^c’û*Äž…}0@ä8eÇ‘Æbï{ÃSo%„p~zb&\× Ñ¡€LŒÌì{672“Q ’]Ôß=×_ ¦i:oœÉ•RE5m¥\«Nª±ÖÅëuÜÿ—“ÓøÐT}é[vþªòßÚÖšß¹ˆXºpk’RÑ«î*JL¾Pf/»abbŠ!ÄÛ5ã}ký÷Œ˜ǃŠz®gÛÖë çáò?3Ò²\RN1¦¿ówÿ~©2L'ŠÃ÷?ÿì?ÿÏÿ/ÿŸÿ÷¿¸\.fz8Äú²ÌK뀠­ûè#½1SL9x^ßKUá Q¸úGÔ­/]3óÍñt9?qª6 c/Õ¹q÷Ž4øP lHj ]嘋¢Õ|œ4°Öš˜îÏ"!Qäq<â0ŒÖT˜ÙYª–‡!Ƈ|s<­ëÊÖu 1zé]ku8Lµ0TQ2 ,ÆDàiuÅÖ'z5½»½;ŸÏah­çœ¤7"<ê…ÄÌ1dt¦?€ÛT ì»ØšªÖ­H—uY§q"‚¾ Ý;ùž¹NËñAä;eçtžcpëƒ]‡z@8¥AU}ghЦ°Îë¶n¢FŒ`0äT¶-ÓVKÌü^rÊ1¥ZÊ4šH7QA­Ò ‹80Ž9”ÖBŒÆ(&[ï]™¸”òÍdžnèÀÄD|{{‡H9Ìa+…™O·§OB EjL©÷>ÏóñpêM¥öÃ8uå@"ýææÆcJ1Æbrï½we ÓtÀ}ÜvöWjµÖZK­îݪ¢Ë6@ÝŠ™µ.®~ôZ6·S’ˆŒ)bQÍrÎã8¸ZÐ{ÝÖ¥ƒ¸ Ð¥Ç˜DôÅ‹{ùôð‰™z—”rWÃ!ÛVòýýæÍ›ÖD Zk"r{{›s޶͆R vV× (¤Ä¼×ï¡AØÇSÐmÝJ)1&"ÚjiµÎó¼®ó8Žž…îÚ™ 8—ÇÇPÕÖ»¿öÌLMœ#â0.DTëþ ]±.° arÆ@ˆÉKž½¢Ü7úM„®ìßÈA½}ÌÃ×±„«ëx®RrŒ§œ‡ÖššNÓ@dÛ6#j-ë%4­H6@iDÐZ%¢u­1­ R`Š! ) ÍúV‹"ðµiW CL!D3¨µK0.CŠ7Ç£t“ªøþý»ÿéŸ|óíWÃлÆ4vmÒÔZJ¡”5Çd¦½UG®x<—<}S{µ½?Ó˜€i­‰) “1& ªfh];Eöê>"²@ÒÛéfQjÕÒ0t2Œ €(ˆF&SPQÇÑLk­§Ó©ô¦fˆ!Æ xèJŸ.—8L/ß}˜î¿ý´ü‹ÿêÿ[K¹¿?ÍËòéü$•§éxÊÃ0ÏgH9s¨½ÇE¡ÕêŽPeb ¹«6Õ’qh¢K)œóZ q @½KmÕ ÊzS|YgCË)öÞê¶2 ´V9 Äѳ֘ƒti¥‚„abž9¤øþ³ï}õÍW1§ÖØŠ´ªÒóa:ÔÖ8ÅRÊùéILät:˜éº.þû^{»½½¦c­®Ó¡ªCïb¼¹»»\3âÞ‰ëºïñÌš4Ä€«JoUR‰rHÙ sTÕDšjˆcð{¯"Ed6t¥¢@¸.íŸÝ5×[)îÑûŽóLDÐz) A×..9•°¶aÉ;ü<ãjÚ¥ó«ô8˶MS èõ8SÌCHe[™¸•J€ÆTcL„$½@DfDÚý•ˆ¦²–…D10*’¨å”Ðì8Þ¼~³mÛ7ß~Å‘[¯ îkë[kµu¹½½‡i]ç!†bL˜ÑSÈãx£‚ˆaHÃétWJ‡QZó£õvwxÙE‰9¦*²¬KmÅL;T@kÒ JÛê ^:Ö"å˜ XZOœSÌD)PÌ1×V§ãåòôôôBX—¥™¥”~ðý/L L?ûÞ»/¿üü<5ÙJ­ÓaÚÖ Ô¤Ûqº œRHÈaN½C©ÔNbŒ‡e[ÝóTÊVÖ­·9„œK­1¤1€  fÒ*£!©¹|§½ö¶E„õò„Ú§!ŸŸ>Ú4æ@HŠvÅ邺Ägà4aôìºti­KWòvbóИx€IDAT3!0‡ØÕˆ8¥Ì§ñÐje„²(MÓ‘9íkXB1UmÌ ÄqLbV[¹ÄbŠÌÌi¸i½»ô½n«o$̵œæŒl2ÓZ»/ ‘Cm] !†¾µˆ)Q×îS!2Ä”Ÿ€W³'†À½ ÕÚ˜ƒ+*„v™/*CTQ0PÿG´wmMÁ)p@ ÁÜ÷}­ô /‹=¬dNB߉S†hþÞS ð÷ͳ.ü³ŸýìÓ§­UDŠaxõö]­(…˜³ˆŽÓÁ™˺å”BJÃ0l[1³œÝÖmȃj7¤HoÞ~v8¼`:´JÑÔBÄ?|ûñÛÓÝ}7ÈÇã0Œ´Ët˜.ç³#´RŽ-7³@{âWM‘h1E¦àùt…ƽÊ÷ÆAë­î~|DPs¿´Žˆ¾ù`Æ“ˆxY&˜u)Úˆ)Ƭb)i8ZLIÆa‘óùìÅ7òGAÜÖ: pˆ@È„Žh¿9=þîp4"žÆaHÉi‹žÊ9­kÝÊ&ªnãƒÞjNÑ38¢c 1Þœn}VŽHªF8rkýýû·§ÓééñÑîžbûîþKÞYŒLLBˆ1ìÉø?Ìÿ ûsâu¯º»iºCÙÝÂfÑ‘¢ûF×M/)Á1OHj"aŽ —­LÇC9ÞÛ2Œ3¡Ï@ì–0·s8{Z»h—€rLþJë&¥8L×u+­mu]·m«+nµŽÓøúÕëÇXKé݆œè ­säÀÌ{ïÕsÚhÃ8<>=xÀkߪ‚ŠÝZ_ ÷VÖÖ½­ÀûT<Ê«) ;n1rôv]Ö5å„„®™Ùñt4€Þ´l[-žï‡y9÷Þ=ÞZ[—•9ÇqœD„íNnÛ•:g!tUé"Ékä ÜtgCŠ1‰ˆH÷·xk™9¦ö.Ò"më¶ëÕfµ4W/Zk[){!õ.î‘+W¢šbL)îæcU&J)Õ^÷\:Þ‹gCRSë:Y¤µê%!xݼõÞcÜ­Õ·w÷´íÁ—¨®`"ñ³˜É˜&Kyz€‰H ½XTÃ5ÑGD!e1ˆ)ŽÇã)åAÌ8„“GNJ­;½ÝÐ-7¢ßvýkã„™"rü‚¨”m›—YZ'Ž.!"¤”˜ÈL³‰:óõææÎ SΈtõr\¾÷²Àtá¹pÿ 3²Ws<‡|ïüø¸¸æ(¢Ô¼~ý½ûWo77Ìi-åÅý}ï}¹Ì!rë²VÆ)q,Ûæ±ÏÞ…ƒ!E@¾ù Þ½xÂéöæÕtœz¯ë²vé‹HÇã!q#˜I×ãqúðá…P·B[눔‡1PP3¤€„ËRدÄ""ƒA èHcp¥*#™ª^-প`–R3@ôäp¯]zƒ=X°?Lïïþƒßüî÷ÃáÔº–&†ÐkwŽ ªæÑ” càÈ)úÞ$¹õ¾n«öî_£V{mů¥ïrrô›ØÔ$Ætwo­U@ ‰`Û65iM9ÄbJ©VaæÞû0Ž­æH[)‡ÃTk]·Å§3oå~6}æa†AA™˜½fˆCˆHÌ‹k;󂂈©¡¡]Aïà%!*fކ@œBÈ1Miò .ÄÀ.—[Lñªã#õÖ©KGæéx¬­©™x-ë0©l#OÓ´'ÔÕÌ+g§qDëB Ð5Ç4 ã¼®DRôÂßß\¶Yµ;ÆÊ[)‡SˆñééiW/ƒ(KùÑŸüèñã'4 1‡``µ·ÚËZÖu[ïnï[ïÞôë*M1ÅQÌb HØEmoTG>Œ#†RÊî#¢ã4RÎ)¤˜‡ *˜rŽLÃ8lµ”Z׺-ÛjÃ8¦4æ”ÊÖ´uÓ„`ºn[7=O€xœÇã)¥ b½oÃ0ºixžBæœÙ±b¢*LüÜØãèãŒzï­UWbÇ”$rXÕiç²x‚’˜°ÖâhWîbàSñj$õ‰G¯­LLº³oñŠª#$" ˆ‚¿™¼ÎØÇˆ1Ĩ ~)$­Wb`US3íµ÷R…˜Bàè];*ÊiºÇ‘Uô0 °ÔŽˆã4N­µî™@1f"Šq@ =>ÖRšôqš^½{÷âQøôácm}ÈC­µ·.Úonoq;Ä”²¨5éjÐEnîî˜C)[­-Å„D½©ª¾¸{q¹,hÈŒ"¢ÒA%Æ Ú ®‹{Û‚ÌlàÚ©ÄŒ90B@À."Ý>=>½~ûnÙÊápC!®ëlÚÅÌrJo^¿®µDë²y…^Œ1çt{wçŸ5ôÖ[½–x‚0¢÷’÷Ú[oˆÀÁ‹hžWŽb2•u]|D8M ›¡ˆ`J)¥ÔšHí CL_üà‹y™Íl¾\Ä4v£Îž£#äÞ;ùy†תoð´ÄóðqÜÕ½kÏs=]k‹MÔñÀHÈÃ4Œ7Ç›e]¥÷.bNó$äRʽî…fæ˜&Q3€eY½‹…ZkÃ8ö֥˛»eYcL9¥ó<Àñ0!¢ˆªWV©‡€yæyA&`l½‰È'Bœ†ƒ¢äœ=pØzŸ¦C­­lõöö–ˆÇ<Ða8ÜŽ7§›ùré­¶â•BÖˆ9å@Ѭ÷–RUœŽ·/^¼‘ñ0@땯ö¤qÆ<ªhÁ³þ0‘t¸½½„o?|X·ÍßR—ËÙÄjk!ÅqÊ^v{{[k½¿{µ­¥måts ¢Ë|öO‰B`æR ‰9š™C“ˆAšÌËâ‚Ì0ŒÈ,¢*ÍI¿þF÷8}ŒÑwÜ!Út->ÂVõp8ìyÀ<$žì‹@än‡—qÏ ù˜ˆí ¯¾>WàùUwy„+‘tÏ í^ò@*y1!»Ö‡AD·móe°™áét2`òÂjfb"tDØsSOÇ—µ¶Ú*æa¨­‡8ÜÜ܆}vð´Lïbf Ö›¾yó®µöþýû_ÿúתr>_N§£¯–D„‰}cIWV­ºuÅñšªBððé0ŒÄt˜Že+½«§rTÄ㦻‡ÔñÅ„lÄlˆOOO®uº‡.î½;Vl·-‡½ɱî¾jC5È9Bï’óàõö"Bbvþc¼¹}•ÇÛûoÆÃÍ0þçÿòòô(½¤c fÓpw÷îŸÿÇÿɼ¬?|»Î«©üüçg[·ó²o^Ät„Žw7ù0”V¶º‡ã<_P½ƒ< ãˆr>|õu΃vM1¾{÷~ÝÖi–Ë| α§ÔÀ‰Hó<»ÝÕ®=ˆ4ãÍévž/`ÆLTUÀŒJ)¼ ùYað¯‡Rˆ~éñ”j­õtsâ‡Ã¡+pÌ/_½ùì³ï½}÷öÕ«×ó¼B)µ¨( Žè{ S@ÂR!’n“·`ï™9 3goŠt@Š)úA)]Bˆ¢¦HœsÑRkˆ¤”T!¥,²»BŒM:?>>Jï¾ÿ•m¹ìHj !ä<Pï Ÿé^*®/¨‰yœäzŽ«K2W‡åóÎ|ß»ú1vÕnü©FD\KñÑ^ÿhÒW°V›¨’³qDÕ-ØC Ê1Ö­F¢^Ûéx4T³< !%÷¤*hÝJ:L[-.&Œ‡i:ºJWé¢ÀTzõÚá1 `øÙ»÷OçG5#¦Ö{ i­´ãáS\æUºäRJ·77_õ•©ù}ßMTDÕ›Nj©½¹ 9ì<ÛZ*šÙ²\j)¾Q—n1Ä7÷˜‡Á=ÐÄ9¦˜{×ÖÚ<_šxÛ\w8¶jOCŽ9þö¿‘û—/Zoì#KëHÖZ+¥¤œ|’†QDÇql¥ÃNÄëëºÕRæuëM»jJÙ¦@d)8n|]lf)Å.BD£ÛZ~úÄ!¼ÿÞ÷ Âï÷û_ÿúן>Jï[©µ”Z{œŽ¢<îþGÿÖ?~óþý¿÷Oÿǯ߼üõßþúæx[KY–KÎ<ÍsïVjC³÷ï¿÷ðéññé©·òù÷>ûÃï›S”VŒ€öÂÁÁ~`77§››cJQU¶mõ!¨Õ­è5G„LÔ»„À)%sXS%?hÐÛ©K-ÒÅß)§ù²‡ãéfÙÊ8N9¿ÿýïK­ŸÔ\ûN½Kí’ó˜blÒTöÄ)1‡#@!…œ‹›RDD‘¦ÚETT"­¦N˜ñÈmv1¦››»a<ø FUÇcJÉ].ë2Ç­¬î:Æá|~•à¢vd"bÂc¬µ¹«Ý«ÌUeÇè_ßlˆ»‚þ]ŠéAÙí4¾ãW›¹Hï¥TdÂŒP]–6ëÒ[ïîÅrÀ\ˆlj1zÜO‡ÂÝñ&p콚ٺmhb\·í|¹p H(Ò§a\Z“Þ‰)¥”‡˜–º•ÞŽ§›µl[-!Åœ†ÈáíË×öOþ,çá·¿ým­Mºr !Ä!óù\Zó½KJéG?úÑ~ÿ{@œŽ‡yžÅ´ô¦ äPËi¸’¥ÍìÇOþj¦ÄcC"§Cݪ!ǵ”ÒjÝʳõ–˜Ì´K#‚!%"².ÂZ¶yžó8ÜÜÝ>==Õ­üôø "12bŽ­Ët8ö&Ò$ÅÔ{÷ˆ«m\‡<ݽ|9Çq˜qÇq¼­±÷îxzj½^8ÆCr‹a)›§rʈԤíU `B4ÿ‘{ïªv:Ýô®½Ïü¹ñö<»vyªayp—§ãÖMŸ»nPcLÓt8Žu«ÄŒHä©Lf3Od¹gŸ™E:–²Å”sŠ `L{¶.„ìÞ›4p÷òûÒ‘ñÓe)¥—ÖóÛß}õõ× 8¨´ÖŧéPJóÒVªˆÀŒ bÜ R~¾p@Äi: ’‰˜C@¾šô™ˆ»Hˆqk §ñRîfjþíPFn"!%C2Œ ˜Â†Ì„)‡ÚÖu»˜Iï¨"¦æŸ ’W’î1Cˆ1 `ˆé?øÁÃÃ"1“ŽC^–ÅŒ~ðÅÏΗ¢þÿçÿÓ/~õ‹ÇSNŸ>|½ÎëºÄï^¼úÍï~_Wh½¾}÷ææth½©HÊcÊÓtûâõtsÿÍ7ŸÄì—ý7Ò¡Vyº<‰ÊÃã§y]Äl˜/^½ª½aïóe.¥0S`~øøIz“^‡ÈLäâ.!Šj­[­5Z×åéü°¬³hç@^é«ÍùË»s‘9ÄÀ­µ< „XKÕ¾†Ü38xŸ”_}S£a@Õ¼jY¿¿®ëv:ÝŽÇ㋯bß¼ûÌ´¹½ß‘µ-[¦á2Ÿ[í>ùöÞz¯)%q†³‹Žžg`âÛ›[ÞU-¥dˆl¶/~Ç“«s0ŽcÎÃ8N­ÕÓéäP„ÖêÍí-Ö²1s“æÀó4Mf Ò‘LUÄmŠff¸ßðï¡ 3ÜáMe¢*J¤`z-ÓÚº*€¨µg‹ 1sÄÒÞ¢j`;)¥Ö[ÙJò¼,¢!æ<¬ë¢`µ‹:L Qzó»º Sd_ŸR>}R‚›·¥ÕÞ¥•®M¾ýæ›ÓÍͶ–ãñ4 iø;?ÿùçßûÁ·¾eÚ;ÄEä2ÏçËåîþ¾›`à˲lµªš‰åÆ86Qß=‡DTTÇi‚€ç§'…}Q)­—RE”™MS8žN—ev_¼‹i9§Z¶®%åÈ„½vRÈ1UíUº˜áÃÃÃaœþÞßû{ç‡Çµd @Mº™nn)ÄÞ,r<Ž›“϶MÀ8†ãéÔEcÊ„Á—ynÊ(Û«ŠS_ÔÄûjmê-w@~D¸­pGïƒ ã4 yTÛ÷ b¢ª¥1×/_¹"˜ü]hbàÖÚË•|sÏœ˜»jí¶w14 7—眜¿sfŠûØÑ%&Su«—öò0¤œâÑv9?št_óvoð$V/úCdaš‡qœçYJiÃx¼¹½:_T5G–ÞU„«©ªNCʇi {ñ!Bdêf)%ouÞ͈ÁW¦Ö»´¶›%É…NâR&¢Û»»u+D DÒÔ< è><"ŠÃÈ̦Öd§ù|mµ.À{SJN ‘½áÜãÏ–¯Uõ¹{Ú ò0üìg?ûíoËÌÖ¥‹4$fJçÂáóüðÿúÿø¿ÏëåéÃÃ|9CüøáëcÊy+9š.¥|ýå—€:Œ#Ç_¾ywYêÍÝëQzxxú“?ùY/ð0|||ðæÆéx¼{ùò¼Ì¥ ‹ñ4M¥l9ÅóÓã1ˆøh]štíÍK¯kí­õÞ‡ipý–ˆ¶­ Ãp~šU,dÂgX˵MÔã9 9O€äá!1QƒÞ«yÔ«µ¶e[DzÓ,±·c0í[é.o‡Zkï½”­÷¶n šrô˜ÕÚnnï~ø'º.‹ÿ›™"ß¼xÛêZZƉ‚»hóÓÃDAÐÒޏ­e&Pv Mëýx8¶Öc ½·ÖÛaº‘®`„„­‹š˜ZWB@2p¯‰wQÆ4†E¤–¢bq†8P'nÚÆ!õ.J(JjùæO~ø“ÿÍÿúû¯þ»‰`­¬&51…ÞjÊ™™›vb k«;7Ñï¸ÓzCŒÝz+_ýîw½5©µ‰êñöa„˜¶VB¢!‡Ëå1"NùÓùé›OEíþþþöæætûâq^‡ÛW¯^½}û¶6Yמó1‡<Üœ‡CQ»2Ñ»wï÷ÛßV)·)½¼}QKýìýç?üáŸ~üøiÈéîîvùôi[—LÆ!]æ'"ØZÌkm)gð!Ä8€(2ñ‹û—Ú{ïâ I0Ú×ÅH)Ÿ.k ÑT3CH›j`F5Ïyîu±{)i@DSÍ w.½b¯ÚkLái>+áéöv­õñr´7ïß-—­×Î"³˜S-…Ð$cT7Ï 9‹¥aH)m[€m™[ÝʺÜÝßÖ­ÖV9"~ýî­¨FÕuY˜XTò˜ÕtȱÖM´Ã8Šf8 ÇZz ˆH!|k¦_Éùð“ÿürÞÆpzuÿf¹ÌhÖ[yùâþÃÇNFºâ9„à²{\Ûæ¨Ö”’—“øá´C°‡˜Ë¶€hi˜Zݤ×À¨ÒTkŠÁZ%&ÞjQ³”ç<4 ž8©ÄÆ×uQ•!°HÇ‚‚i ‘¡ÖhlÖJ ˆRʪБÔ@CàÖ«IèÇô•…AU]hbn]ÏóÙ+ÚÇi#§á湨h_my]ªKŒ`¢N€²³:½¡›ˆzû{ Qv÷Á~{õAÞT{¯`FÄέ1þK„À­ëÝÝ3?=]bLj Àÿ³ÿùÿâg?ýé¯ý+]çË0 Äìˆ×a¸ùÞçïïno~ñÿjž4Eª¥ #m‰ºJëÍÌÜõ)*ϼ.Ál/¤6¸v§!Sˆ‘cn]_¼xñúͦÐZ{:_RˆeÛZY†œÎë¶Æ?||xýþû§»×w÷Ç÷ïß}ÿ‹ÏóÛߦœÿòoøôétÿ"Oǘ†éxHy(­>žÏÈÀ!¤jo"BøÍï~»®+Çt8L¿ùë¿5Y× @Ç#‚õÖsH)Åq˜òYj%bŽÁ{µøÅŸ|üôÁ›Ë²ÒÞDjÂZ¯1†ÚJŒáJ‘ö:X´gÒ¹¡ÑŽ^¸îfÍD‘ DÔÄÐPM»v!•~8§i\—åéñ±nåÅÝýÏ~ö³Ëù9Z“Vët8 7I™yÝ©YoJ„¢½K@U‰1ÅbŒÌ Ã4€¡å¬•öá÷fÆ1zØTE:"¶V.cC˜é¹‚‘C03NÈÑRŠ^Ý ­–Þ›¯\gºÂÅžé1pí7„g£î÷ÀñêS¾¶©ÃóÄFˆÈL¾l b°ÝíæF¢ýåZ¶S&Š!#àj‹)­e³qTDEooîv "ÕZ ŒßÜÜ´&ùtº™Ïçi<<|üHŽãAUÕ´´6ŽÃçOe+ãá0oëë7oþò—¿øôð©öÂÞS–‡!ç$]›ô˜ò2/ª"ªCJOó,"pGy“¢ˆç˜üÙòs Öâ× #r“šØVÖ­nîã~ºœ ö:Ù£ŠÎËr8.çó0NîòŽ™¥Ë8We ¹âp<Þ˜Â4‡›^¥uøÁ¾µu[\%vgGí¥”-çäÀ8'¿ÖVTw8`J9†œsN) Ãà™Ï›Û;/ÀÓ.¥lûý˜Ðû`K)~ñm­–RÉjS·Ë yŠ!5wÅçùìæËmÛ¦iò²K£!ðêm‡i+`íU{÷ÇÐÙCB½7©þ û©{ejùLH¯_¿ªe[—­·Æ‡›WnÞÑ8¸Ýx·!¢îÝBˆˆ|{w‹Ä¢9ª “/ ¡”’sv¸JŒzk‘i_TňHL1å1l[qËJ¦R5åñŸüÛÿÎ?ý÷þñ_ý—µ,„pº9¦ã¡Õ¶lë7_}ù¯þõŸŸŸb@µ æ@뽫QA®qpCÄ<ÄaÈã³ÂÐÔ4†`&„Ð{ó qŽ™¦ÓÓÓÓr¹p „´¬³)<>>l—Çßÿþwï¿÷Ù›7oˆÃ~ú³çßû÷ï_½ùgÿ“?û³?û·ò³ŸþÍoóñáéå›·Ÿž.išjÑW¯ßnµ®µ¾ûÞg¢‚‘Óò“Ÿ\–õº(€Ä1p ¨jÒ%ÅAѰµj½‡œSLÃ4šÙr™½ÂÔ+ÛºÃ;©K)nP¹½½½Üwr–Ø¡ëq)È×Ü™7"2£¹~nˆ(Šì ¤÷ù|1µÓí騛|üðñüxnµº§v˜&ܯªfÚÕ íZÞ"33 朘€™Ú¶mã8lÛ(Ô^—uó7ú².€ fÛ¶;•µ+3ÖV§ñØš ÃÈ} JˆÕ^\›V“²ÜS6êóŠ׉9hïx- xÆüzÇ»ïá÷ŠÑçÝ_Wô µÙÿàçØ„ÿEUwÚ¨ŠvAÄ”£_º§<ÍóœBÞÖ•‰ZiCJÛV4Eæ[ëˆÁ ¡# )#£[nbŒu-èéáqÌãÏú³uY¦ñp¹œ‡q¨ÒBà!粕cÊù²Ì¿ùÝß^–¥k;ŸŸò8´^ ìîî6ÄXjõרºm*Òj5Ø¥w‘ÖšZ÷¶z‘®²óŽG´öV õâ°C"p"X“Þ¤Iï¥71éÒ)„ŸüøÇ¯_¿~:?¡ÚºmLÔE¦ÃÑtw ¯ÛbÄ|{{;M‡Þ›K—*¨jÓtòÄœŽÇ[Fþøð çócke+ËðüO?|øö›ß@kÅOÉeY¶mu xk½–Šà®A«µ!’‡Rš·0’H'†Öjï5¥ì`Ô]&bVí¥¬îb$âÒ0M!f÷ߺkfDtïVï™ÌIí}ÌMäK¯˜E”ï¥K{Þ‡aŒ1:œYU=ô‡hLäëuë‹Ì„O—˶mþBâñø®MÄÈ{wŸ\Ë'}l ΢¢Ťvo‚³ZKo½lEUBŒ1Æ.m[·V6iýÙRí:¼ßþ ™ƒ:Ë8¥TJ7 ”†_ÿÍßþÿÅÿíééZÛL´l[oM» S&¶õrN‰‰Ô¬‚Jf6²}Uˆè¿®ë¡½U×Ô®_;fF7´õÞÁ= 9#ÇZê¾vïýÓÇ^^1 Ã0ŽUôîÕ«4 ‡Ãažç/~ðÅŸüéO^Ýò“ßß߯ÛöÅŸþééæþ_ÿå_ŽÓ1åãñ榊ÒÍÝýÓ|>žë¶½ÿì{¿ÿò«Ò~øÃñ0Õº=Ï?øþçÒú0äBÝjNQDÇco’"眈üX´Ò*•&Á).¥8:œT9´¾1“W´¬ëÒ{+eC‡y™YWqVç5•EÕ@Ðaj¨¸?"û+ЀÈ%Ô[k¥Hï·Çc ¬½rÌ—Ë¥—z:œRŒÿìŸýûÿðüLJO˼ˆº[ ÀóÉCNÒ«”ZÁ›ñTSˆ”sò¤1…@Bp>ŽwwwÎ’Uúü‡Ÿo[qÏÕÝÝ‹Ÿýüg_}õ „¬wÙJ†ªF¸§ù¹@U½ ô;rëÔ3‡Àœd½×wã¡ç–òçyo{>ÜŸ6.õ:3RÅ40ÇIA­ "–ÚNÇ#äaH) 9‡ÖVkë8ä8H—ÁÝÌÀ1ªio½¶úý·ßÛåÍZ×ÅaéËt8ÞÜžnîn>=~r§lo}po €CM¥Ö¢&­mHFþèr†ã8Ä <×€žÜVŠ Ùbà»û;Ÿ¸q/De$/ÅAtÐ3‹ØóßcܛނƒDÄÖ{¯uG™6Õ¶ï®xç$ˆ Qˆ!ì mˆ?ÙùšÑUS¡ðZUêe[ ™’÷é¨@NCL¡Öªb)&$'£îàzÔÓóSÕÃá8MS­åx<åœ[b.­Jßz+m[O‡ƒç»RJ­W±ˆ@­÷V‘€ÄÌO4ý£Ý‹Jó'qòîÛ @ÌD}s@MÌŸ'bXç3˜x6‰‡aX:þôo|ýðÔEùË¿üæ«/—ùò£þÉoÿö¯ÿêW¿úþ¿þË÷ï>{÷Ù÷žÏ:žnÇ#‡aÈß|ûa𦻻ÛóÓS¦ïÿà‹Ë¼|øôá‡?üBzÍ)¿}÷–˜ŸÕ,Z—5çaYÖ˜‚Cˆ0åÄb™8Dbj¥â±3É9z®ÖÊ̾@o­¡]›áÀƒG$ÙÁð‘Ú~צ£»öîPŸhý4ó"r iTÒÊÖkûðñSbÎiH1ŽãôýGÿ¡ª}ýõ×OOµ6é•ÊB§šy”©¦<ƶmõƒ•§”™¹¶ €/^½l­å”sνwBrn­=]ÎÓtŒy0 µl—§Kë%pX˶×q ¦apQJÔѵ‘ç°’îøGÔE44ØIÖt ˆ?ë{ÜEÁã×èÖ¿î1@£g¡®¨šàö'wÚ@JCJ)¦áõ«×çÇÇ›ã 3}ûñ r)¤÷÷ó<ƒáýýý½Û3,ë ˆ­ sà@¯î_æ§§§ÓñC‡1Æx>?=žžÎ lwww···çeFƵmb ‘÷äÍñééÉ^¾|…ˆî"÷w^]W¥)zMz_)rˆjêZ v©fºƒ››åŸÑµ„V¤‰¨‚†Àk­Ÿ9ða‰9ÆØETµ–NH½wíýx8ÖÚ8U-[I9$iµ"Ê9>|úTêv¹<ÓV–§§s–ú¼,9'$U±çߋޥõÊnNwîûÈC>NÞüWJgoõVÍTmßÖ˜9†Ú3½”¢ª¨{nH<‰jfàèo•c\—¥Ôêcã8nÛÆÄf†Î;ÄsŽ1?öO¯ Ú®›‰ôZ·.ME¹‡cB`ö;²î°Sÿtö£ P¤E`RÖ9Åps:|||ÌÃ0¦·_üBüñÏöx¹üô'úÿþßÿ«_ýÕ/ùËyYÿÛ?ÿïæyyùêÍ/ù×! Mô|žCÊ!¦eYžžžbŒµT¿¿}ûfÛJ@­µþú׿|yÿþý»”òãã§?üþ·§ƒJÛÖuòá0noJkµ 1Ó„ÄfÔºÜÞ½0…qœaÆu[¿ûd‘‡£ç'›7 cÙ{þ(03ì²p@¢!ç!'&ì­‰H œsª¾¯c'k9Ì |w‚y¦ÖZïM¥˜nËìM}··wÿê_ýë_ýê—¿ÿý­”Mz ‘c †(Ò›H 1¦4sAe…qG·öæaX–%çt9_ÔôíÛw‡Ã¡”6Ïbî"1%ŽiœnܼÔz%€Þ[)MºPcR³@€b çn_)z¼ï‘¯ª¹×và.#~—‹°ësâ}O3ybÄÀ—¨¾º÷Ã]î b ×ZVpg„"L‡ÃVÚt˜Zï­4@ò0o3G·‰·Zß½}óöÕ›èÄVí[)ÈäN>BšÏ—o¾ù&æaÛʺn‡Ãäoz2­–ÞÛ|üð׿þud*òŧ›y™·uf´u¾¨v5)µ„aœ—•™Cˆ¹‹1‡ÛÛ»ï}ïûO7w·æá&‚ǧÇ!Óa¼>ûV°÷îSü¾"f·™bc0iµôÖ ÔéÎ3ŽÁ®¯yS qD ¾ntärÁñšÓ8¨èÛ·ïþÝ÷ßý×ÿú¿||!Ô²Š˜ë{æ1c35£½Ì(Æ„FˆSV_áôÞ}måD'êÕÖÖuug1À4òx\–m˜ŽbïmÌééñ)QJ9 ƒHWóZ†^[ë½6÷wŠˆxø>¹ë³æÙ ×A‰¼EÁ­Gn€nU`f‡!ùáî_urJ ÙU¶†bÊYUšôN~¯&õ¯uo4xõê}Òù|n­3b_y¤OÕjë^ˆà³›/g ê¶5ÌRˆH­›Ù¶õ/ïSÊó|é]8xe#½ƚ DŽã¸ñÂÃÖ G§¡õ†Lõ²ÜÝÞÕ²–RöF4é6¤Áý !p­Evܱw=ï%˜††àxsF×Ú¾+r´€!(¨H V‘kZ×8p-€zŸ!q\¶:N÷ww?úñþÕ/þ"åá¿üÅ_þê×µ DZ÷>¯Ûx8–Þ~ÿÕ×çó‹×¯à‹ü™Ça¬k)ëF†_þþË)ç»»Óe¾|ù‡/—år~z:Ÿÿú—yss¤¿ü‹¿˜Ïáp½"#ùöÕ›ù²ˆŠcµ{—Ö:Å4ˆÊ·_‹LÛ6hŠa-³ ”RÍ Æ$]ˆ”Rv8>˜{>‚'æ™ØÍÔOvß1Xí5§la4DF0„< •Sö¤±‚ BbÌó²ÖRÿâ_ÿ¢·†ë²ˆTb`Ä.µµ¦fNt:àý‹—‡Ãáöö>Äàhšµ¬ŽFÇÑ SÊÇã±µ&­ض•RÚ•Ê*1F#6àtss{>? 9oË©AHqÇÛ»;U•.µö@AúLè‰su‹‚]ííöL T³ÀÁÿòÿ 6„¾í÷Br›/îë…½„OUzï¶·Ò»2©.[@ …››$ÚÜä·”e]àzLÇC`2(Û¶®³nµØéöäb«™Ýßß#¡Š¶Ö]9 ·m„S,­qà¾ûÀjVæõÅ˗˲‰ô”21šY /ç !‚BÎD"‡q¶u[—µuï¤!ryÓË,k_úS”.^€FÒa¯ìÒü1H)^3>{~ ¦S*[ùÑŸþèüôb777> þüç?¡5ÿ®k¦óÓåÕ«7̱”Ú» àj_óN‡AUEÚ¶­Õ?Pÿ{N§§“Àñx¬µ1¶^ ´K'b]×ušÆÞ{`>¦y¾ˆˆ™Æ˜\ó‘Ãáè¿ÿ˜!@oÍ›¾óSÂpün›2ÔÚö±ÉÌï®ÎƒŠjJÁÌÜeäÞ|¦0Mã2_T»#A±×ví0Ã0!Ò^«ÆkéH\JŽŸ%¹"ªj" µÞP5‡P·-†@ˆ`ÐÁ€(¥)¦ALk«FÁW dæ*š#·Ö‰©—†)GUí½1€I$ÄÓ ÍÚÖ"²“ðz˜Ãõ—®ªM­{ÁLµ‹ãCÇq"LU@ÕÈ(ÄXKucÉétê½3±”úþíÛu™ý‰ñï’ÞÝA„ª]MÅ ‰ ÑhøÍo~7ç‡'¸ÌõG?ý{Ÿ/«´µ·0 qÈ·÷w§›Ó»·ïÖu].ÇÃ1‡1ÅIbm-ç­êº¬Ã˜z+kYçŸüé~÷·¿½œ×Äôøñƒö&µÌó¥´ÂÎÇÓPÊe?i™SµÉý›·ÊôÕ×ßxÜDÖe‰äþîUˆ±u!F$ªÚ8…fÝ MCZ­ìÜ,èD†Ú¤l&BÒEÕ8Æ"@1&L)€3E¤oÛá8æ!•^ĺ{KNkf`¢½I_s¦Þ–Þ6í«IïR}MÄȨ@Æã0Å4 QÆ&r>?õÞEZ$½¥˜zk‡ñðúÕké ¨˜‡¡÷bÒ!┆r.Ûj ã0ôZ³t³ÓéFDQ@›€B ™Ç[@¸Ì$¥ˆn§a¦Ö;‰Z—~½Ø™©’4†8ä8¨™t/àîÏvI¸ò¥Ç"‚;/Ï8òéx¨µ¢\;{k1„!箚rVŒ¶×ÏÆ!çÞ{Ê9çñþx㑜4ä&¢ˆ j€Ò›¢¹™ ji"úãý8ÅìÐì­®]ZóΣIEއC—.¦r­–=Lã<_b޶m###RIÅzë)ƽR±ÏË¥‹éEJ“æ÷ã@ ƒ)0±vÆ ¨wÀaKmÀ‘1¤°ßô}ûbj¢§ã € 1›èr™ i[×å)™Šèï~÷‡­5¬½¿}÷þëo¾¾»»M)„ÀÛ6ÇH)‡”Bm—e.¥nÛ*Ò—²1Ã8å­–­l~®Û–Çä«Gm½wiÓ8yÑ[ÎIµ±ê|>›HkµÕº‡BÔZBßûìõb½ÖºúAzœ Ø[ݶ%Ç´-%Ä<Ž?þéOMm¾\Z)‘™ DÛ>IuCÄãñ(Ò{ïy̆î­Y áŠmÑÖ›™´ÖèZJN¹Úņý*ô¢©(Ö¶ÕRöZDw\Ý€1&×£k­Îñp-ï:ã"3§˜ï_¾É9öù÷çe)¥€Bkõ0Õz)ÍÃx¾\f×jkïÖE(DŽétº;o^¿yõòåË8LçËœSb²­1rL¹ÖšRDdº=ÝÔZ?}ú4M!´Vz+&ÂDÃyvÊ2Ó³çÌ:ÏôUUÑ«rcˆpoIò²C"r€oú‘zí1¦ÝKø —$æý^·VM‰Bïj]e^—µÔBom]—À9QoÞ¼y||ì"9¥Þûéææññqžçu] 4Äè”Þ;‡HD]z“ýŽ; ƒo×ÖZÈgØ]/õï${½_íÅP9Ç‹wÙk¼€³´Ú¤;R…©‰Ó^C䔲ˆ ÃÐ¥:èƒüöí[ÿÀÍ,p@ Dlµ¹EÄ“­ÕR¶m[µ÷OçG5éÿôŸýÓßÿþw‡ÃhÃ0|ýõWDèLªyžÇ#ÇCNC­5 É Žµ–i:®Kñµð²¬`˜rZÖ­÷~:Ýle5TBì­bp1Ý·–]z—Þz+µ…a˜N§Û”³‰_¸÷Cµcï»L™L“ªÄàvßT5"Nyà†a8‘#®ë9gbÔÞÜŽÜ3½RÙ¯b-õp¼™ÆÃñtÐV·£4UØ-ìªótÜ댎Dˆˆ(jã4ÍóÜ[µœ³(÷/^5iOp̤͑·æ’¼/¦Ý#Ú @‰ÐLc¼z EÌ€@¯¥À¦CT$%ö¥+¸AÂåM†1cŒÁAĽuLýóm½í4;„R«×¢ò¾"wõ†RJË<Ã\áÚûjj‘90õÖÁ,pR±VÛ¼\ê¶>=}ªµÞžNç‡Ç/ÿð‡xœNóe& ×/_%ŽOO„t§y­?úñOÖe9¦ßþöo†Ÿžž–yÃׯ^}úô­j{y{~zX– šiïß~õû2Ï`ý8—ó9†PJQ“­”!) ó¼Óq˜¦< ?úâ‹_üÅ?ùp>qÀÞ =g;¯ 2fS Lµ?uSÀÀv!Å_ùžšyþCuç÷ñu»z]·îå|ûFv1Ð)¸Ó4me€”¢×°Žî›¦ƒˆÔ²•REµµn!fZ{Kãp8='ÈÀbR×sšÆqY–˜b똗u1°Úšoó|¿Ò{ëÝïÄØzsÿ¯ªÃà•þ9‹)q;ÐϺÿ`]zi‹hG2bí¢]ýÛ‚ãT{¹÷|ýè~Æ?û쳇‡OÏëÿ;ooo—evÔ¥í탘RÜ›­ºÔ½ Uõi>#A©[míááÓëׯZßzo—Ëâƒyž‡©Öâ;Þœ‡”ÒÍí­ª§R+!ûÿCŽ1Ƙi_ÒŠyóétT•V˺,óü4Žƒªwkôƒ/½ã—)ÞÞÝòºmë\L!…°®+íUÏWÞ¯R 2QBìµÅHe[¬Krn­«·b„¸,ëÓ㓪odõêm¥h—œY¤‹z;†!b ÑI'§ÃMë"½oÛÒZ»9œü9FP&4Už÷.QûgáïF3)‹vf>žN x™/;"Õ9K¢½÷*" ªðÜjÚQ“еwÝûo¶ˆ€)19DT<”¨ÒE[\kS ™Љ¨Ìëj€)‡ã [—i¤ï‘3W£8y#b—N;Ñ7øWÒ85óB"ºÞškur‹¹½$cL1…(½3´m]—EZ­Û¢!&“ž˜­—óçËÓ9‡‰ï^¾)e#ÓËùñòôÐ[­¥zÄüã§§Óár~x|üÐÛ¼ô®Ô²,)bÝVíu]æÛ›SoÙÖu½½{ùùg_\Î[ˆ©H릿ù«¿ÒÖSâ×/î‘lYæÒ«Ú%†‘ZG)×¶©zÔžÜ3n~+"f‡X¹Í‘[meYL¼À±òÕßCèµvé;-‹ ˜1Ý¥äë h1†<$ß—øµ ÄÀ}ß]ìp8><>2LJ‡ÇqÈ­ÔÞÛµ§:8ZÝ·(OOOÄbP€RÈCÊcª´m+ãpðkÐîdǘcˆ]4Æs¾Ì3#õÞÁúº®½×@ä 3S `×òbQ½ ?V÷»‹šûÞÙqÛÄîJr†¤ìßð‚úÐPêBÄ)yÓ¤Û©YÄ’´îèœRÊyšN·ww`ÇQÑÆãáñññþþþötóæõ[4#æRJk˜¶mñåSq6¾ÊN/v >¯0T Lìé45K)u ¬`!ƺ•Ö{—®fjÒ¥ûAo¢"^Gë;a—½Í¼ãÁ p`b0µÀ¬j)‡Û»›ÇÇÇgýÊQ´„‰1¦”Öe !öÞD¬ÔÚZ«­´^9GhRó8¨ ! c^×¥÷úéÓ'/´šgo!žœÿ}øVÚöôðaÌüõ‡‡q8?=üþ·3æü×ýWæIp°”Ã8¦o>|YÖùt>2€öš_ÎO ½×6ú,Ò›Çyþá?ú7¿ýðàÝíï>{óÕ·_=~ûY·Þ¿ýðõ<Ÿ‡CW†!0Ÿîî>~úÄ1ŽÃÈ!¼¸»ÿúë¯rŽØÕ¯Øæ²h­Õ™;½KJiÊc+ISŠî_öœAkU½¾Õ Ý{¸h7¨ÏbÏ®$G”<ÇDÄ]ˆ±3o¥¨ ³$`^–ÛÛ[Dt¨lÎ9„R*¥ÔÞò0”Ö ©u1#G œSN1ŸçËVJò0dQ™ÆÃ‹×¯Ï— 1ÇŸZk/îï·m‹)ôÖ˜8æD€^¿Ì€æý…t¦‡~…¼3ü1fÐöÆ€?>ú)'/÷ Á/² ]|Õ"N™$R a_Áíµjµ?==QÓáðî³wOO?øÁ>}øPk}øð1å|>Ÿ¯]ÞS*¥Ä!;dðšQÆg{©YóÚUïRgÏàÄ W¢±ˆtéÝL°·oà¯ÿ¯^ï/ÏûÇBôL)¹gcŽ­µu]õúÅw6oŒaYȹªPka)åB`1†qSJÞ{÷úÕk‡[kã˜×u!æy§Óé„Û¶¾ÿîr9Ïó"ÒcЇÃDD¥UÇqš¯^½º»»K)¿xñ¢–^kC óÞÆ…æå0ˆt™—i:1‡Ò8Wç«Å˜T©µ¾•6‡iœ˜q†q.ç§# †D5¦ìˆ©Ó.6Üi'ûgx<ž¼örÇskTîîn/—'5ñ™ÝiN"=G.µªŠ`™‡[™`ÛVé’RrŽ1€‰t &f h"C:¸mwOvˆzÈ·_Û{e¢Úšˆøož/!’ªì‘Dˆ1äœ\´UdâÀ©Jßÿþ)åm+Ò›Gü‘¿ Ám÷r˜brÊö_§œ¼ UDcÊþÝÈ9G""dµž‡¡õ"ë?Åó£ûfߘÈ#²úÌS6ÃëtÆH(»ãDMD °¬ë¶Î„ ÒÖe>9Ëå u9/—‡¶]¤•²Îµ,hºn˧o¿Zç§iÌOOOÒdž—7ïÞ”V¾÷ùûïÿýùòôñã7ëårÇÞÊ|>Øã4MÒ…ˆB䜓Hã`ÇO?¦¬Ú—å‚Úõéüà”™Zëñp,­ÆœÁ(cÎ1@àày8!殩˭TÐÝ~CÁ,çìŒlµ~}ö ¢s0Ó¤ªr=ò<5Wkå°—azrÄ?϶?3èþñcN9Æcr»­™†J­H°•‚f¨fÃ8v‘aîîïÇã²®È|ÿâ5 äHy˜\éÞ¶MLK)xæ€D­Ë²lëºÝßß©Ùùé„*ârDÆ1r$ŽXö€791 a昱I÷“}?.¯k$Ù¯ßXØ%>B§»º“Z½HTÌÀg®ýÚJˆÎEpËA ÀRʈ€Î—K¡Ô`Ò;Õm«µ–R9°¨æœ»4ŸÝ ç„``ÀD;ÿ]ÅÔ]\Aó¨9·¶{Üwn!4FâNp$ >¼Á|Å0øë¾bØqšëºúÁ±º ÒSJ¸ë½Ç¶m;Žþûâ•Ô#WSÖuÀBkM¤ßÞÞn¥‰È~ü§_~õeˆS¾Ìs©e‘Ζu~|z »Ò-_}õ"„.çùÅ‹WˆDçóÈzïjÌép<…ˆÜÆŠ^iè}ÉCÉ•k™—Ë6_.çsŒiÆnv8?=

    Ÿ/­õi§i¼»»óSçFà¤V¦èm÷Í´«nµ†Œã0&v{sRÛû®¬«_Rî_Þ/ëìã•?:ðìg€ëÿ@C—á ó#pÌ3so ÈÌœ! "Z·­‰ӺΪr^T·åŒÈÃ0ÓÄ!™Z±Ö2¥!¦ìM¶'NKo®3û³V<¿Ú{Ü×ÌÌÌ€˜\¡sª­™1û;50³]±e^Zæè²­c?~úc˜—e<ŽÃ4j×ÃáðùçŸOÓôîÝ;ÿ—Ëň§é´Ìk'Â0 ƒ˜ªiÊ©÷~¼9ãx:jk£ˆ‰ ÖÒ–ù‚1†º•°w @­Å—Ãbct§xLˆª™‰¨÷.jôÇ';’1@NÙcر…„BT3QÆÁ¿‚g¢v&ì·Ið_(†Ö›IO)öÚÁ›ªD<‘×z3ÓËå"]¼æp:½~ýz+[ ^²X‡am­´^›¿Š¿c×ÖB]ÅG„ëÛzÇKïã4yÌ’ˆ"F$÷J‹3ÐCº~¼ƒî»r#œ/ ˆ™CŒ)„È\žêâïÑ=íCò@URJþ¦0³“_Îvì½—ÕQ ÁK]ì‡u[wWïfR^–•˜òÿ¬?{š$ÍÎ;±³¼‹»GÄ·äZU½UWoDƒ œ…)^Š4ÉŒ÷ü$ýe’éR¢ÉFccF‚+È‘X½×ž™ßáîïrÎÑÅñˆ,Ú”5Úº³ YùE¸¿ïYžç÷ ù·¿ý”™×u瓳|¤Km½æ—eÙv€†OÎ8™¦éññIÅþàþðã?é­!ÁW_~)Ò4¦±u a@@oñkm"*¢!¤â\–È1ƨ"¦ÝíD¢ã`ˆjps{ýt<ÖæD„"QàäRD̄󲈨g޶ZZ_ -Ä "¸aˆzdò|¥˜w›‹¸1ü.ìR¥Šª‚ÀˆŒ¦Öš Àäª?ã<\ð€Û^Å[$ª¥€ M¿ûÝï¾{ûÀ–eÅ-yΕ‚j­µŸ¿pß Ä”žÝ¼"dUñdê<¤yžUΩºžwEzí!¤i·÷QfJ©w·®lc"zx|<gŸˆ1QàØZ¹º>8;ðReDÛØÎ"÷ÍK£1¥÷ÄùÍRC@L3%dSÕ1ÕÌTb 1rYKï=Ĭ"½T2¨ËÊ€‡Ýb,kÆi7âÓÓc΃t=ž–y]OËiYæãr2ЇLJW/žÝ¿{{÷ö«SYfãÄ/^ìö{S{xxÜí&23†µUQTË)vé"kY—qÌÎÅ!æ<œæùêú™¨ìö‡y­§y!´ãñ(*‰|ݵKA¢—/^\]]?Ýß…t‡ˆÒ{«5ňªÊLÈFà”ÕÞ´‹I¯Ô.¾D‘v~6À¹]¾Ôj­pJ©.3Lj´…ÅHd⎈_¾|5M»/^ÞÞÞ¤”Ìl÷9ç·÷9çÒ0¾0¼ººªµغ®~øáñ餪···Ý”[­WWB”Þ³ˆP†˜˜BLj­ÌAõ":ö,0³u]]»IÚa| z5×lnÛÆHEd7îZë­õqœ\Õˆ°wã0¶ÖÝU'Ò̉+bˆ–Sò4‚Ûë›qÈëZjïã8–µ´ÞTµÕz|z‡™Ñ6‹¸… ·9l´©tóÈ„0MÓzî•k­ß”ê/ëúêõë»»»”’Ô–RrâŠÓÌ/`ÆÍè>û0ƒ"«ZNC )§ÁÙèɯyfŽ!‘Uc µÖsT8™Ú~8NÌ$¢Ë²¸ ewŸÐÞsØ÷ê!®˲î÷;@|||L)žN3½|ùòt:‰3OXU IC„Rê4î}ëpŽÞõíÛwù—ÕZÿñO~x<>={ù²¶z}óLÔÔ,çÇ” -æBžvû<ŒÌ[è<Ï¥¬D˜‡x}}ýø¸OÇãáêŸóMEüÍ"ªµ6Qª­±ôÚE|·¤Ús޾¤q_[Á ÷æë.Vë@‰9xñî·¦ÿ €æÑ襵ö2 03°Þ;‡ç½uU¡ÀÈh`‚ØA11;ÆúáþÁg‘])0±önf9gÇ&|ÿã_½~ùîÝ[ 1¨Ù²¬­7 Sèf:¯³ZGÂÈAM[ï1±çº"¡Š”µÎó‘L˜Ì¤äœ2S$€Zªö:$Rh¥´^üN»÷nȹ÷ˆÒkNqYN1„ÞjŠ[ïN•i½%ooo#qom³#QÌM¥9IDBN¥7EÓ* BÔ-ú˜Eª‰t©ÎCÆ€Ä  Ão®v÷oÞÔeí­NÃPÊ©—SYNëü$ËÓÝW_“û·oO÷·WW­œãZ« ¤qŸÆi-íþá¡”˜Cm¥k+Ò«š6Q¢0ÆÀZ­9rT@@Œ1 Ái>¥z­9òw¾ýÑrš[Y{M)÷ÖCŒµ‰Ö¶˜ãvMºöæv9/ Üqèc ·÷ð ¡«‚yÜ ƒ¿À1™ç‰º¢”)0£ aŒÉbˆˆœR“«ëç½ —Ú0„›Ûg§y)¥?<¾×¯ooŸNóÓq~óöîÙó—”" {6æn†±´SŒ)–Z†a8÷1§q·+­´K[†ÝÈ”ˆb«M¬±¯€Â– Ü=®ƒBP5æ„ÄnЇÜZõb‚‘Ùh©bª”j–rRÕÞÅÝç@´–’‡¡›–VÇq,ëšR:ͧÓ|êÒ7±) 'Ò©HJÙ©ö:/óq>)(ˆŒC–Öz©»al¥æ”ETnŸ?Oi(µ–µRo"Ý­ôîk)çÓ²’˜¨¢¤µ÷-¾• ©(a•¨OOD¨ !GcDÕÃáÐjï½mþ{ÝÊ>ÖS Ì!´êo“n` S5Q@óHØŠß®æ¦Sì¢]ÔsO Œk'Bvzf¡÷ÖZ cJ†vZNCí­÷6ŒckÝH[)Dx}¸B„ÖÛº¬FØ[)QØÕÏ @‡[×€úu‰¤WBEN_¿}ÛU¾zóUÊ#=»ºùö‡Å<¤”‡Cà8;U»¹yv{ûì믎Ä2 Âîp ”B÷×7»Ýxwÿõ´Ï»ÝpzøáuNúö—º•S@ÀCm=Æ *u­Ò[óö¹¬ÒK¼¬Ëz­·¶)¸BE¤÷ã»·_ù˜àúù³?þ{ò­oçíÛ·§yîÒ00ƒ¨(ˆÏˆöÖ`ëEÀT=Þ…9x>IŠ¡Õ^Öåúúj—»·_; ç¼,«§îà|| LCØji`àób³s[Uæò—˜˜ê†ÐòÒ ‰rJNµÄ.²”“Gè‡å3™#JZ":\BŒøp8Ô®ßzõz?ǧÓÓããéé¸Ìós•þîÝ]ÎC—îüñxB¤µ¬D´ñˆv»OäTäñña·›nWã0œŽóýýÝ8fi½÷žRäò{oþt«ôýa_k«µíö»’ˆÄýA 1ÆqÈ.–uLô¥°õ½‚Ÿ]d¿ß‹©™í÷ûi[­ÞMz­úM¤óœÚeZîJw·—ªzYê³fwûÃétªe!ÄZЍÄ  ôâ†Ï”3"vŸ½€2ä¸I!»ÊE¼Dçñš˜Ô˜¹”RJ½·m1»¦Ÿ]<él:on7~ò™}ïÇEÑá‹cW!âÄQš€!˜[ÈÃõÕïÒ[vÑ4MµÖÃþº:€7%"š—¹¶ÚJ†A\íZ[»¾ºóà”ÓÇü£;{YÀ¿i¤5ì½/µöVÖ²0‘ÛôʺÜßßÝ?<Oµnf(æ Ò[ëÃ8NW×W××7¯^}4ÏË~¿w÷öþîÝïüôwæyVQkMápu ËZº½zõ: CnMÑ®æ2n$öhÉÖ ¬ëê±µUçŽ8Æ«[^˜)¨¹àÒâç`0ê°µŒjÆi: €:cÐØ@AÁC„ä*ÌM•Èĸ0òYÁÚ{÷q~­u]æ< *ÒzÏ9÷ÖTМkãÛg3ØúGv*±Ïjƒ_>ªr~®ˆÑ3¬8mâUÌ­7$è¢Ä4 ã4í °wã<2˜t—- pïÞ¾#æVKŒ‰Bx||ºº¾5°ÀQM³‘ |@¯rØïêZö»©¶ˆ{ë)Ń¿ÌÌÔJkUM™©µ˜“i¯¥î§éåóçO1¶RÆaä4ÎKý«ŸÿüË7obʸßO]ºŠÑ¿¬¢­VmA×Ú¤·RjiELaÒ¤õ.ã8”²ªô«Ãþéá¾–•<ˆéúææƒW<<ܨtéÍÅN&ŽÆ½Ä|êf¬÷EÅæLÀ& ÍCÛ›¿½Ï֤̆3QïÝ—~Dˆ†Ìb *JÌÎýg&¨­:ÒšbzþâåõíÍ‹g/ò0žŽ³)"P °›Æ›ëk!X×¥¶ ¨ýøøbôéÿÕÕåœwÓTK9>=­ËfÒËóg7Ò•‰KY{+!òZ–µVb6ÕÂñø¤¦¢ê@Ê)„pss»¬ënÚõ® æÙ=!@ò”0Ô‹8r£Ào§$qŒ1Ù¦ÑT4PX–•ðò7ã‘&ÚM“Ï Æ´–u†Þ;Æ”(ð8M­÷ÚZÊy8LÓN[ç¹·ŽŒËº6éFÈ8„.êk/“#oUïß ` }0$ x†ø“{9té˺‡H Ɖ) Òe­@—¢þý \οx1I9{Ç?y΃ëà 21!ªHà˜S–.„á²ŸßøÏ*뺆‰xÛ£ @r©eæ€]Ìb¾f ÚŒi뺚Yë=¦(› »‰4Cm½J[C Ö Rt^4•RJ)§ÓÑLNó©K­¥y÷ð0?=ž ´–õÃ×Lc~¸¿?ž–'WÀNÓ~-ŇaHy¼º¾eæe]SJóRcÊ)!Ç»0SL1„PÊruuåÚ˜Zê0 µÖÀÉ•#çÈvÿ°Èˆ=ÊÃ×Zì¿×¥óÊý`Úá"êòÕ»!Ê9œµUgé±/m6²®*uâ^Öû5>M»úȪηúùÜTAæjÈ&Ä„È~»šBˆ¤¢®¯rÿ”/Äœêq‰Ì!bbê½ckm]KJCŒ™SwW‡Ûç뺼þð[ëÚÁçw½´Öû8§ã1ôÛçåææyW#"¦Ðň™|I ]½q¹ººRÕÃá ]bÒÇàW)3yÒ¹•Þ%ÄÄzëL™ëº à8äÓé!EfÂeYWW¯_}x?÷iw%ŠÓáúÙó)Óî°ÌkÌ;àÐÅ0åä^SñL2D4Sf !˜i-k)3˜©ô^ûãÃÃéx ¬÷ÝÕ¡V)k9=="b««jWiý¬i#DU‘oî'Î{4³odW 4;g ƒn‰·t>²ñoˆlÛï‘û¤¶ªJæã…˜Rö××!¦y-1¦ããñááX»PL˲Çh¦K]ŽÇÓ4íˆCÎyš¦²T'ŵ֗e5Ó›››‡‡‡ZëétêµÌó©·*ÒÕôþî^Mƒ¯Lc ÄRè"ÈhÚ$„°,ën·Ç@átZRέ5PPWÝŠôMÏØ=µœùlÝZÎ%õ)³‹¾=¥ábs]é ®²®9çZ«™¥”»ô< ½v‡‚@)Õw­µÓ㣪šháÙ³[ŽS$æµ.H,bŽÓ›¶²9UM[«bê)½ws’·š;’½I Ä¥ÕeYE”9˜éÅm0¤Ñ?g;DŽpÆÙ_ü½~xx[à¯v7¥À)DÛÑHE‡Àüe7»¾ºjµ‘Cq÷û½ã_BˆÜZ=»›1Ƹ•úE%§|£·îkõ½ÚåCv×ëG¾¯ëê¿> ÃÅ< Y¥˜ožìpx"¡çlˆ¶ÍÚM–Rb‡ý³þð'9fj¤Lôôøxwww{û€¾û½TdN9ÝÞ>;žæ”Ò8NûÃUŒQ‘hwŽÆŒ1 9ÚZ—ÞªÑ×W7§Ó|8\µÖSL~" šø* ÀqÝq£²#ÓGì¬DDÎÓUmÕlÛX‚‡’ëIüÈ@&‚sÞ&ºÄÇ5fÌ—ÚÜÙßEbÌÌa]VDpÛ&¸g¡®û8VÕÀ iã%yÆ×‡^ CJ±KSÙâú‚É6B²‡q·qÆÝãq6 Ãáúi^CJßùÎ÷ĉ@.‹1¹¤6Å´¬m¿¿ž—’ÆØÌˆ#s4ŒüÏà(¸§§§â2oqÞ—Ä™"]´#¤qÜp«cRµ^ui¥¬§ã˜­¥,sAN€áåßÝï¯)$1<n¤ãÝ»‡ë›gk³Æ2‡„@­µÚ;1¤i¿ÛíFfv©"’X²t15@+k™¦aL™ˆÄpY–#ŽCê½B­+s53A„°i­ô"qô(¨§.l`n,x@çØ91?ÙÀILƆfæ,0&êÒ°‹¤“Ï1]-H8¯µö¾;\!ÓZŠ!u뜒™MÓ”‡±µ€×××®»Þq«FçÓiÇBY°nàì®Òë:ÏóѼ5•®jÛ¡Ðj­5rè*)& ‘Žóѳ¤‰¶X>UE?Ç»È6«ºx›·ó·‹>zk»ÝnÇ^›Ÿx¯ÜVÐls ÊÃ0/ó³¿DÃ0úˆÒ% Ä$½‡MiŠ>·é½•ZžNÇÇã‘OG—™ô&ç‚Õ¬ëæP5ÑîJüóá«"²Åš[U±‹ö.踎Þ‘\º:¤ìg¢¿Ú&ê⟟\¤Sÿ žeC)"úàó®Ân·+¥0†Ï_þÉŸüýÏ>ûüéé©KuO" Ùãáp`뺄Ȫ¶¬K!†h1DÝ .D›B¢±ÝX!Ř˜Càhf¥¬~ÔøŸ9„0íöÈÌJ©$`µ÷Ý~?ä=3yÜ< ôãï}bxz:™ÒnH)=-§<Äû·÷¥–e]c̼þèúúÙóW¯_ð­RVéz}sÓjSÕ««ë¦ö½ï}¿¾zõÁþj/­·ZUEJYá,fY–eï3üÖgço+˜ù³„DÔ»˜Y×¾I`<ýj?wâÆ»Û½ ˜:E^U1£Ð=¶¶”I3»d}ûæÍn‡yáy™SjÝM¡›ìpË¿;ËTÐ3~ÀNàb ?eTõññÁ­@Ër*ël¦)…µíòêÕkBeÂRfŸKºJ EºªNãXÖ LŸ|òƒwïÞ™©´NŒ*b v±-™Ž"ê>,×Îïv;3ë]QMÝñGHã0)€lú¿.ô`@¼:zïˆÔETdG׆·Þ[ïnpm½ùÚǧ§‡ýao!Æaú&`²!GWdoß)9ØÐÀè5{ïÕ9Å›¸“ÌȱbÓnr=d­8ì{xò[ |'©ÚCä.ͯ(øuÕÝ›“+ÅM—,b¢ÌL„»Ý†ó<#â‹—/—yùë¿þk1A¢Öj—Š„¥´µ”˜bNƒ7Š¥G6æ<´ÖÍj-Ú…‘0§ùþ'ßÿx¿?¼y÷pûü•®oʲ̧ÓétúÁ>ùðÃþêg?Ûª–§ÃË—/¦išOOOO­2r*k1؜ϭuD˜¦½Ujæ›Eæà:1ƒ¡ÙŒÐkü-TÕ€x<¢ÖcÌ)!1"ÖÖ½-_ιYÙr[ÅDÜä¡€HàvÖ,¢‡ÃÕ2/@лäLŒiÛ™äÄ1<<Ü;<ÆáÙ‹WW×ÏBHµÉ›»ÇÛ›Š)šAo­¶æåmƇÞ%¦òt{ó‚89># qLH‘(q¬uefâU] –Äñ¼±F€™8"‡,¦Óás@Æ©‹´Vìéô„f—ÆÛ¯®n_p ëº|ë;í¯vyÈŸþùõáêG?ü¡ÔZÖeé0FféUz©­®eÑ-ÖYED‡˜ú•óâÅ«Ýn_ZY—e£8•*Ú†œCàãÓ£Ùp‹ *Òôñ¥~IŸÇÊH†`®±Ó‹Ç\"ƒÞ#ž£¥ÕÏ«€ó×¾ShÀ~ (†½­I1!ñññÑT@´‹šy<¯€S¨Þ¾½;¾ÖǡֲßOË\‰pY3K!\®ÖužçùææºÔ¹«§ûZ]—ãã£jCS0%@3ð>ƒB­ ÇóÀ!ì¦ñþá®–r}ØÏ낞¯‡&Ò»ºÆŸÝ DL€0ŒCʹÔÖ¥ï3ïܹ–ŠÏnnEä {¿¨ØZ½ÖUu]WŸ{yÌ…û0|6Hã8æ”c ˆP[ûàßçyæk­µÕ”³Ç22q½w«­Ž€.~²‹³”ñ|k# #1S »q×Zk­ú¥•R.¥ÖÚœVßk#3ÅsjÕÖgŸ'NvŽ'dŽžÖ+¢½‹ÃÐSÊ9§Z«Hã@ãétD¢«ë«ã|ZËÌCâÚŠjK­&p:=yÃÉÏŸ¿jÍu_-„èʂ֢9Ñ=úöbÑÅp‰P†ÍåbïŒ!•Öj•Ûëç|ëÛ1/^~0MW÷w[ÍDc|õêÃýþ0M»/¿üêÓO ­Ö˜RÓžRúòË/Çý>DN)þì¯þJ~ú»¿wûìöë7oÈ@LçG?ùÝŸþ4†ø³Ÿý|wûý5…PK}óõ—o¾þ²÷™Dú².Ö«„EÔÕûýÞ7Ö~KµÖº¼7Ÿ“z7{o 1ì…‹÷” aT1ošÙ4p"É{‹Þëõnç<ÖËuýMv„Ï cJµÖSÁ î—t00µs褿#< £ˆ" Åvâ5~Œ±µj ˆhÒA!º]ÂQ‘Eäì!æSmz:jíy¯on[ïÒÛºÌsd·cr¬µI—ÃÕuk¢FO§y¿;<-³¸I8zN^NÃ0AU‡qj½§4˜Ú4íC `@ÄNõ4‡P2ó0NÀ8/+ ´^T%ÆP[‹)231}ÿ‡?yûðô4/mYOO§Çé“O>ùÍo~5æa™ç¯¾ú|9Q…Ðj™Ûr²^M»ô .i" UF\Ëó8Žcí}ž—§ÇÇ”²¡v•î7·§Ý¦!:§°u3¹|"²åížOöË ÌÈðÍúÁgǽvߊ'ǹ™ 1‹i ö‰ ˜OÕDœ†Ý¼.ˆ4ÓÃý½4 ë<—RnvóS-ÅUä1¦C8 éîîn>­€[UÁDµÖµ,9çÇÇ5)e ìÛˆ:äT×%ì]˜Bï×Öw»i𦇧§a©Öõøt„qHˆª >ÏUqX!n¡—½w'%LÓdçRÔ‡N+Ë)­Ëê*3m­µÖôœN·IPˆÌlG3CÚ*f¶¶C˜¦]ë ÌD Ddš¦gÏžO§ZJmÍ9Ò%"¢)ø›_»g!Yˆ1¥„DµÕÖÚ–riôÔómcN)‰C­ÕC?BàZ뺮9gO.Ëì3n÷Fzœ·y~i¹Q¨¶^Š›1ß/ubŒ­¯nzXÖuÈ£/¨Ÿ<ßÞ û’rdŠ˜B&ÂÖ"„˜km€TJý½ßû½¯¾üÀ¤·œsLqYæi·ómÇàŽ¹Þ»Oöý\꽯eݦa9‹È0í{•a˜ž=ù“ÿŽˆýø'9š´Ãa¯ªOOÇW¯^ÿ³öÏþøþ›ßùŸþ»ûïEd·Ÿ>úÖ‡Ätÿðèñî×77]êg¿ý œJík)÷ïîë²þ臟<>>üùŸÿùÉ™øH@t:>¾}óõéñB 3Ué½®1&3¸Ú_•Ú¼e÷NÈlª¾ßóЋ-SÆ#òTS߀ÇÀÃîÑz/¢•i[‰LÃÔšpw€` [†¤´º)… (8XÕý\&äÀ¡U]jkB@.‰õ,1§{ëµ"ë!ð“Vóи›HEµKâ8 q^WäD)sÊȤ\æUÄö»Ã²¬ÃngD)Œ"Æa­=ÄR¼½½Q­Æ &b=‘Cè Í4ä,€]åêêæéññåóW§S !Oûëuí‡Ã³ÞñúêyÊhk1Ðrÿµ”‚DßýÞ'ÿîßýÙn æÏ>ÿ"‚¤T;",óQ¤(‚Å¥uPKq@¢Ãõu™×))U)µ‰W˜ ½5m=§3 hr¨ë–äN¢Û½BHЍn@æ€ÀM͈CFf$?Ö}8'½´^«£kÝšAD!D@D56$ÄÀÁAD{íÅÀnn®¤—ùôXËlZkBLàò :K/ëéɬ­ói̱õf*¥öÓièËié­Së˜âîŸÞ©ÔDL¬¦µ ‰{«ëºÚE×D°”%çáù‹—kE´B[–Þ#ÕZº(bWéhػĘcÈR%…¬f)åSï²ÖZji½Ÿã¼%3ôŽˆK+¥û¦ÁÄ´3¡ìÕÒU»#“ôNÈLŒ€d8äq™gO\K ):)åÍÛ7k)—Á‹ï»±k¨ã–òC!¶nHøï|çÝÛ»À»´#–µÆqà”1†”‡ýõ­¨ÍëêQmµ,`Š )r©UTk)@$*h€ˆã8MÓnYׂ‡YÂÙ´Bè¥Zܘ¬`Ã46‘ȶ–‚9"ÂìQòȘT¼ cL9ß\Ý.ó2C“f&_ýåë×/Z)>VQâr6÷ZçœÝŽ"¯½€AØ¥ ‘A­wQƒišÓóÿè'ÿ‡ô¿ÿÉ÷OóüñÇõÕ›û»Ç¿ù;?üýßÿƒÏ>û¼ÔöúõØ[»»»ûõ¯?›—õx\‡ÝÕ‡ßþΧ_|5×B1Mû)¦aÈã?üGÿè[÷¿úÅÝ»wÑàíÝ—/_ÜüÞßú›ù—ùéŸÙ›»/SÆåáíÓÝ×ËÃ×}9=‰ô.R›(DCw„LÄŠ(y`h½™(°µ+¨i7‚n&ª8r4%m¥{pG—Î<|gj¦„î ±uŸçnM÷æDFPiª&€vvw*´Þ|’ÎÞ{aïm31ƒ§T«™)ˆ:u]ÇWŠŠK_…ÖjÊ9Ck LRJ*Í̈sà¦Ý¾ôzš×.*KQUTÌ9›Â8L··ÏçãŒÈ­7 Hˆµ,Ón¼¿»CÄa pûšU‡a0…&}^‹GD©YoõúöúøôwÑZKLiS1ó8LÇe^Ö" bèØ¨AÔmTJÙﮇ?{öÌ=„¥”aLÓ4ªôÏ¿ø¼öf*l:îöOÇÓ¯~ýÛýèÇ/_¼üùÏ~öúåKi˲̭×ÞÊ~¿ë­ÄÀh(Ò\%&¢1'É)­Ë\ëꊈȄÎÝ^kQuÎŸŠª‡ÿ‚¨Ñ6KߨCDèP'WѸóÞn}D»èÒÎuýVˆšÙv´!¾W]¹^ö¢§r§¯×Ü8¬ªèëÍ‚%ç¢÷Özm­W04C›§¥,Ò»ª¨vÆÃHLWWW‡ÃîéøXÖEE˜Q»ÔºÎóÌÌã”{SDzšÓí™™Co­¶â¿ºÌs­«ÃODÄT ¼C12‚' ¸@³ÕÖjÛn¸ˆH¥3£'ál]šà}³¹‚©³BÎYTºˆœøš?x¹ó)¼7ÊùM!¦ˆˆÝÄÔdYׇÇb20WRo-sˆÄ´ßÒ8ŽÌ˜¥ûçQQÄCÀ“‚¿ØþçrÌ­ÖœsŒë­–C 1ž“¬ÅÅõ`]\Šc!ðöGvN‰²¶ý§sÖ·öÞJE$ðÝFò8 ÇÓ1Å("†B@"¦)†ps{;ŸŽ„Ф¥¸R *RzïÒò0ä<€Ñ«W/Ok¹»»ÿË¿úÙg_|î†øþ‡—/^æq‡¡¶ö›_ýúßÿûÿóŸÿœ9Æ{ïoÞ½=ͧÚú0ÿýÿ?|ÿãï~磧qüè£ouÕûûûiœx>=þ¿ó‡···Ë²üìgUk½º¹º{¸ïËÒ{“Ö–e!"5µ˜š®àeæÀ¡K7UЋIHÏS;$/¡Œ1)€¡áy`cÌyO¸À‘˜0 ²‘c¿Ìèf90˜‚ö3ÙÍm,ài’"ºõ}~˜gœõsM$Ò €ÙYÃ0Ïs¤)Çìú3·c´ÚOÇ'é­K•ÖRJ­Uâ9äÝî€T Ô>†p:.`–S³ÞÕTSˆÃ~o ó|³œÂ|œSŠÚz¯™™¶f ]”"¶V‡ÃÝýÃá°g¢ZJëÍ_½~}¸>¸ §«ŒÃðx:u2 „É0ä¼Ã0¨Ñ4dS¸¹¾}õêÕÓÓižç›››Ó鈇î”e9¿úê3@3‘"‡Úå÷ÿo‡ù‹_¢I :>¼aBØív„PÚº.«š¶Z0ÇC­ÕÖµl.qϘñ.NTUCÎ1æÓ6x$d"·BÐ9=ÎØ·½¸3s‹PˆEÕzsÞ'\V(ΕÚbÇé܆;×6zâEâÈDØ“kT¥wq•÷¶ƒ9?½``®…R‘^Á@{¯ëÚ¥«xˆASiÓ0Ý\_B«-%•ûû»Óñ`»€–ÓÑøt:Ò0 9dS0в¥€­Kâ@D­¬"¢Kvͺ˜Ž~UŒ9s†4æ±·ÍYËêËdÿX‚£›b ¤wK¸`Uô,+¸Þƒ™L1Äàºÿ:\€äþ‹†Ø%:¾À¼Œò=‡ˆ<Å#Ç×u½HÑÇq°Ö•SS@zöìÙ0î¼YÄË2¯Ë"½1³³€ðü`œ òÛ\DbȦ8±s[ë­v÷ˆ1ÖVÝÚêwÃ4d_¹»þGͤ;DA\œã#œÞ›ª¦”Ö²æ))¤)g2–.„¸¿><=>–Rˆ¹õöá‡>>>ª)#™jë½Õ"½/ëêò‘ÀÜZ‘yY>ùäûfPJçS7)•Ò^¾zýððôñÇŸìöãî°vØÇ§ýî?ÿçÿòéo?ýúë7>7.µ}ðúÃòOÿŸþö·Ó4ÝÞÞþÞïý-üéïþäøø¢ÿËÿïý/ñÌñÿî!ÒÕaøoÿþßõêÕ‹/¡JÿÑòìöùé³Ï>Uñös¤øn?1øx]zë*`ÐÕ•·¶¥¤šma‡ŠÈä6(4Óæi çÓ̶À ‰½TW‘@[q‡ˆ¸‹˜C»\ƒ‡ŒHf›üÀD½,]]ÑÛ­ŽE—©@YZÏ9»Ñ*ÄàЄ¸ßï À¦ÝèYÒí[M)§˜9ÆqÚçaœç…A‡qdæÞ[ˆ™Cµ˜òÛÇ'0}ñòÅñéÞ“nPÁz—ZŠ{ËCÝDÌ­‹ÆÛZ^¿zùôø0©•SàiÊïÞ¾Y—y2˜1ó³ç¯wû«Ýþ¦ Ü<{ÒôâÅ«çÏ^ÝÝ}-jLaž—išTužçu^b¤Þë|||:Þ?{v».'0Ƶ?<>ÖÚæÓ¼®«ö*½ÍÇ'©Ç@|<Uú²œzé-¦4æX׎Dª°Ö’óÐk½šv>—ƒ¶í7CV â™=äž{?MÏ2ÇMø$Ò#ÇËN ÃV6ª¸ ÆE¶ï×­ßp?m6c×Ý«Ê9€÷½Ýw¸zª©Ÿh¾üñÎff„ÅäÖBÌÖ¥éñtZ–YZWikYMeÈÐÖå8/'s¸ã\VÛï÷)d3袦(Šš–uiHhªM:¨!€‚j AÄœ¡˜ÓX{Ûív¥Kï’òФ™XïMzƈ–uõöÍ—þɸr†Àzï½·íTèêÆãà/6Mã´I¼cØú=€mƊ爟}ó<_,B!Uõ˺þÇö)yιÖröN\áp}›s–ÖÊR{]×eéÒÁÔ—L—Þ,§à6u·¨#§”TõææÆñD~ÙxóiȵVÇÆµÖDu^N¦0Ž“—çˆ<ívßúö·ß½}€Ž efD!¢j3µˆaÊÃG|8M;‘ÚªõãñøƒüàÝ»wøîÝÝgžÑ[ç–ùh*­GWMÓøá‡Þßß—ÚJY‡«Öåþþ{×ÖåÅ‹/?|‰„ÿþ_ý›»û‡?ýWú‹_þª9 Fôùó¥Ö”ÒÏñמ¦rþÛëoïÆi¿~÷§?Ýïvóº Ç/_–Z@áOþÞßùè£þí¿ý·¿øÅÏ¿úúëßÿƒ¿}ûìÙ·¿÷Ý1ðgŸ}æ~õÖZHép8L»Ýº.­•^kÛ&ÞÈ!äœzÝØúäš-ÜŒôR1 ™ÍTq[wŸ]DãÁåC€`Ì™Ô%CÒ Ð̤w0Þ*SB$Iúð‘¶ôÔN„)ï&l4F€œsëð¢¥$žv‡Ö¥‹Žãd€Ý”Cê­—RÕ ¤U0 ÆÚj`6ÑzToL €bâÃõá´œÆqÈÃ8¯+Æøt:£š0€ÕÖ"óRÖ!e0 üæK1逴ßïÌ`†RÖe™¥×ZæãÓ}+óÛ¯¾\ËŒ*÷1ФéðìÅËy­/_} F×7·w÷»ÃþúzïnÌǧ§ÞZoE¤÷ZÔd>>¶²»?xu<>Õ²ÆÈZû~·ûƒ?øÃO?ûüwþÆß¨e}ûæëe>¢”&5§4Nã‡~ˆ&D$½‡{k¦„@8M“öžB\—µ©"(ÑF˜ò««4!"ö]ˆ‚! €ò¹¼¬Ru«Áyó43ÙÞëºm¹zÓl |oLcÞÞy3 6 —+`ÏU§¾ï.ôz–‘˜meá{—›¨ZJ‘£ŽUk«Ú;!¨[¬´‹¶²®ózl½öÖL«‰xàRÖ2ça£Úk Ñ5¾jBh¥•¾¹®ˆ™HMLÄ̘ØùªŠÄªšÆ¡”¢Gž604S!¤Ú+‡ÀDhÐ{÷“Ôåktž\áÅ&î‚™³ªB1%èµUé¢ZÏ38›ûô›^!ÿŒ6˜"³˜úñêÚ¤sªÀ8þ+>" nU%f$–e9žžz­"] ëß&¡ûûø¬“>/Q}Ýgf.N‘”Rk-¤ˆ9çRJWÙ¿1y@¦o¬Ž·|´uY½ÁQ¯KÌ ”•É"ñÇHa¿ß«Ú<ÏÍ'úfOO]$„@Ì×WW÷÷÷®o)¥„ÖeFÚ>câe]?ÿüóskíööù÷¿ÿý‡û‡˜âããÓýýã›7_Ÿ–Óa¿/u½ÿúݧŸ}öËßüÚO)U{þüÅOú»÷_~ùe ©Ôrs}»ßïwãîîÝ»7ïÞLiüóÿòçôwÿè>þþ÷µõÏ>ý­Öå/ÿâ/þÕ¿ü—ÿåÏÿË|š_¿zõ—ý_|þÙ_ýÅŸŸæ9nˆ˜R:N­÷¥Ü¼ÆRQŒ3ó6Ðd ȳ}ÕzSë]{ëæ,;ÕŽÄïEiº†"Bf!ߤ# Ç^y©štõ-¹—êS1C·!FŽ@è¹HªÈn]Ùø3Þ§4æ<ô.»ý‰‘øå•RcÊÈ(MT…É/#"iÍÕ”¢ÂD§ù$]ö‡ÝÕÍþóO?rÄ&mÇyY‘ñūƔ8©âéxŠ©«ì¯1ïj³ç™ÅH!íµÝ½{ÇŒóÓ£ôžrì­åœTÄG“e^±t«­‡˜OëúòÕ«‡Ç‡Ö[—®Ð<ŸŽÒëÓãc™O·7×ËéIzÓÞr §ãÑc'×ež†±‹üú׿¦éóÏ?¯µ”2§o¯w>$í­Ÿïïï#‡gÏnïÇi2³&Šîø'¬ÕA£ j-­WD`b1C¥ ×)æéì|v-]´­¸ÝÊtÃØ™Kôžq©Ü/‡ûå’@2çíÚf¢=Ü@L/¡š.6wúå,ƒ­§T/â\¶è ѦâwQÑh­ÅÑÇ&Ò[ ÌÒªóàTu·Û}ÿ“Nã®´~:Õl·ß#À².î—B L€c"ÄKüüZJˆì^ÜÖkJ™ aÚíÍlžO½5@wj‚4É)Ù_£ŒÈ!ø >O§°QÝÅ›ìùvpjné~ªþfÕÚ 0…B$$킨9§Z –²îv“;ˆhkúÙ‹ˆ¥–u]4蕵ŸÅ þ „ôt|ªëZK-óЦ‚} ÎCÆ@çÜÏÔô@c÷½Ä=¡ÁÉ\Ïž=sµkê—Zøœ•SRgÇö®†1D±86+„ÀL"ÝÅœóº–pÆýRK?óKo>Mu1‹€EäÅ‹ç4Q‰ÜÕ{ÇóI¶ß_Õ&‡ÃÕ³gÏÌl]Ëa¿;žžu^NöåW_¾{s·Îó_üÅ_8›å[ßùÎn¿»}v›rz¸¿'¢ãñ˜‡áÿøó_ýå_¾þàáßýûÿðòÅËaŸNOŸ}þ9 1üËù?ý§ÿôK]U:þü¯ÿúÓßüöÝÝݺ.Di÷! µ5$ì"Ä8ϧ^j—æÜü˜ò˜Ç”ó¥Of& |9SÊÈ Àˆˆ9FÛ&3@œw7ªê‚XU#bÜ6?@H¤jç~YÍLz±mç$î?oZ»v_» ¢;k‘Â0ŒLiÆZZLQM‡qHœRF !¦œæ0¯kHÃÕ³[9£}[-6ä,­-§ T"JWµº®Êh§§ÇHøôø˜˜TŒ˜¿ó½×²J—ã'ßÿøÓOë0[5D$Ž)—Úš4§VÃ(ªUl™D\æ@‡˜,nÝrJmkí ¶.+…ÐZ)€"´Þ)°^]M×7»< ¥ÕiÆiÐ.RVR)Ë2i™g9Ÿät<¦œPjë¢yÈ**ªRÊZ×ÙÉnoo[k(­JëÕt§Z›!`à˜¢Jg¤8Ä”øFÔã†Í̤™¸×¼÷ÚZ­âÛ÷T <+”™ˆÈã ·£ù¼!åsz(]&¤îŒ¾ˆ¸Èág±÷Š`Ž‘D4P§g\¤´îœŠ!nöj4$×\"yjÊ0 çØn5ÓÖ*žO #æ!×Z8Ð~wX×50ÖÚÏ¡4/ËWoßžNs2 ‚Á²®Ä(Téjâv!iæTi ­BÌj£1…Ö*SPÐRÖR ¨¥˜óbL)ë2÷Þ·Ä>plºÈ {ÿˇÔÇ—(oCDO+ Ìf6 cÎùÌÿlÍÞ@ÍŒc<_“glw €ÿƒ¼“ðÏdÛ@2¡4A÷ߣnó-•)"FL1Æ7Ð:O k¯HØzãÀjžóhF1ˆiíÍé‹.[ºÅ˜¦q7Ž£ŠxˆyÁ´3¿O¥5³ÛÛ[uS(¬ó!†¦]A`#ECÈé4ÏÓ°{|xJ1¿¹{sw/ªË²ìv;‡Ýé´LÓ@ÖRi§ÓRzëïÞÝ]í÷wïm>=ÝÜ\×Z¯®n–y½{û5ê¢/^½|ñúå‹—¯RÎßÿä“ç·Ï|åÐj{ýÁëëëë»»»×/?øêîíü­¿ýoûùóçÿê_ÿë¿üóÿlÚÿ×ÿåϾøü·‘¨¬Ëa¿›G5E30ÞBÈ)#qm­Ö*Ú×u !ÞbB|, @]¶vWÁÌ_G4P3U$PGzˆ˜¨™7„åˆH<ìo¥o¯ºžS{ÍD ÔL6‡šGÉH`¿PU¡¨šãØ (¥áúêf˜v»ý¡Ô•™Ú0 ¦h1 ­µÛÛg9_|ùeWåoŸ½óøôðØêÊu]\ãìªXUÉ)ªZ«+"„îï¬÷e^"“©:Tg-kλÒêñôøöÍÛe™ÉCᘆ<ç9§¤¦`Xkñ·EUœBÅLÒºHg¦8 ÄiwwÓ4í›Xï= Cœ†Œò4Ü?Ü#©j70ü«_ý*çô櫯Ê|’Zãa¿+¥¤çùiG5D¶.ÂZj“®f¥®Ïž=;v§§ÇRʺ®ã8^]í¯¯®Öù4K3yýúõͳÛ>úð«/¾D³¦½‹˜ŠÛ!/稀¨«£Ü±Í`ŒÔ»ºÕ팼Ó"ô;Ýù†›”µ_L+ßÊœ_Ç­ÍßÂ}ü߉ÂfÇ­ÞWq0!˜YQΗK#¦é *¾™ôCÐÐ)!ùù‹¨·~©ï 0 ÐTº·žÞ 17€¨BŒÑf)gŽ˜Ó@ˆË²bÒ{†lÒ™Cï›kLc`‘ž‡ä”RŠïÒ˲šioÒ/²ñÀ¢¶–*j ™cáÜq)¥ÈÉtƒå‘ÃóÉQ'>ól­9ƒÌ Ì<£ˆŒy†Áýèfâ‹ÖZë8ާÓÉ/æ<Œþ=¸›Ô$ªJ1B혗²6é€ÔzgC¨¥øÇLL²Ñ+ÁÓ=¢RDÐ;³œsvädW9ós0r“Î! Q“¾¿:¼»»ã\Ñi Öuõ;&'$wázÈÔº®^x¢j­µ/^ˆÈºœ<« 7QÏí«€´®°, ‡0Ž£" ¸ƒ,„PÖê!èªÚZI1…4üÑÿ7yÜ Ã`ªµÖqO§ckËázus•bþ'ÿôÿüчß~ûî Lûé;ßý^ÌéÇ?þÉŸüÉŸ03š}òÉ'ã8–Rbˆ¦ö½ï~/¥\µGâckí¿þå—_~þõ_<Üßµ6?~{šÚ»G;[”ãøêå«.úÅ—_2‘XgÂ<äÞºïGÝ<B&bƒÍGí"C0ð£ÑÐ ‚Wð&èû{4i?äÜZÀÃþ "hðýï~\¥@í-„dˆ)f3ÞÅœRŠźû6§|u¸j¥¢Ã´ë¥­ÇÓ›/¿8æÈ§ÇGÙ唟¿|ùxÿf-'Õ¶; »Ý¸¬KÔ®!„<ªòÁëWÚûãý}Ž‘ÐÌì0MŒªð‹¯¿\z À½V,½™ÙÓý}««€ä<.KåSÞÕµµÖµ—%Q0íMªhWQ15$Ÿ>#šã*­kãíœÁƒ› ˆ T-ç¼=O§ië²ÍÏ…§BCS3æ(l`x$CO‘æmåHh]ü@Ps— aïÍÓq‰è‡ŸüÈ”¾üòMNcجwiÎQg4V0TQí¥‹¶®œ3Åœ†¡wI)3µJi((ZÆò¼T¦Z"ð&#­R†8PP$!â<"©J lÒ#ãi>Ŝ沆Ÿ½x¾®K$R0Föe‡<ˆ Š4“^(0{Cp%¢¬µ,eBScb×l”‹À9çaZf>Î3§(*‚ fT»yL’ô-Oп ×!m£TÏúI©«X—aAÌ8Dê­Ç|,Yk% ‡Ãa^—<]Õii„œR–®!ÄÞœQÓj÷Ò) y !ª9o™Z¯ÆTDfL¥7 l¶Á‡ß¼yÛZw` JWÁÈ€\«šôCL!¢âáêºwQEÕŽ€K­Š0î óNc?øÑOþé?ù?ýâç¿üå/~ùáë~òã¿¡b_½û2çÈLË<¯ó< Óô7~ÿ÷ÿ‰ù«ß<{þz¿¿úî÷¾[êú£÷p5ÌOëŸýÙ¼ºº.¥¿zõzµö»»ûãÃã¯?ûÍŸþÙ¿ûÍ¿úúóßj]î߀õòôôÄbL1ÓÕí*P•†éÙ³/[+77‡e>¶º )¢Yµ^0¤0x/”­óBD1ÓîºWeŠ D†8ä8²Â&ta$ ñ óEšÞ½{§&›­ŽÑ݉®fK)Kïµ–Mã3-F{õÞüQ2µRëñøä9Jg¨ƒöÞT ÉûWm­.ëÉ rNƒJ瀭¬½0CbTD0 €­˜óym1„¤£"¢! CSž¿xöæÍW)¥Vë<Ï8M1J4Юµz0¦™µRâ]µVkµ.ÎEDÚïviHëºÞÞÞ¶VC oÞ¾!@5˜çu˜¦×¯^ײ¦i³IOOh}Yf°‰ìîÍ›e}B´¹Öz<cJ·ÏžÏ§ÙDcŒB¸»»G„>úPZé½T_¦”Þ=<„Í0¥ŒD3–ºÎ§“ô6 £ƒJ¦i !ÔVU:p«c|y˺t:«y·Nä%;J—Ky~¦ÈPÈ䣔޻!vénO?·ŒˆÛ@”â–à1,DBâpK Ü(¡vÖb:ö}£;] \J½¿»{xxŒ1„ĪêñŽn•ðMC/ÔÁÄÃ0ÅÓ<çœSJµVïÿ!†Èˆ‘9±ö~6ýƒ ¢F˜¶ˆàMÏ©@D)`àsÂ8ôÞM|3 µ”iœZm1¥aÊZLíx:土Ÿûý÷¾÷½ããÓZÖyžq¶ég\ÉÞUU‡a”íw|÷ñ1K ‚s¼»/Dz)¥{R—œïX×2l@‡˜ûUzÞ•œ,xÑ¡^v³>Ïñ›ÜôÔzG ÇÖbëÝå:îÔ•ó_µV_«úÏtØè¡†*Ö¥mŠ[ÄâZÊn·k­yù˜Á½µCÎ˲ Ø4펧Sk—²qÎYÕþøÿÞnøâó¯RJˆ¢fµµÒn·ûÖ·¾ý»¿û7ðÉ8Ð?ÿçÿüwú7¿øâË_ýêW÷oß¾a¦ãÓcJqña€þöÓÏ~ñó_üü¯VËZÛúöÍ›ßþöW¿úÅ/Z­·×7ÿâÿõÿùÉO~òñÇÀOú;ôÇt<=}ùå¿üÅÏ>ÿòó§ÓýãÃÝ:ŸîZ))ïBÆiÿìÅ+ épý샿ušçÓéøêÕ‹»ûwûý8Ï31uÇæ ÇçÏ^(hmÕÁŒC@æÓ8Œ¤½ÅÀn\0ÏéEï±ÕLÔŸIcN;﹜/Ê[Nt­"‰8DçÔrˆÌÞUysæò^@Ò--Ïq¨¦"µõJ€` &¦F` >=Hœ‡‚* CÎ)Âe>–µHo>§ôƒà›aÄgu¶‚‚©núkxuµÖ¥u)ev©™´Þ ¨Öú'ÿ¿ûÍo~ª»q¨eE4íÝíØMDZ3Umm[¬!˜jY˾:=c޵–&ýpØ«ÚnœJ­ã´¿ººf"ë­¾ýúË!ÀýÛ¯[Yëºh¯Ö™I[ ¤¬K-u›'Ä×ÚžÝ>S5Ú¸z0ù‹/>éÁÌ×'§ã¬f 6N“t…˜òÕÕUŒ±KUtÊ8¾çº¼L[ëhfgyƒã¾34Qñ·zJª8û/3wÛ SÛÄ–£!„˜Ô,î­£g=ÀFÃÙD^ئÕcŸH¸¹-ú ž9lüàM`‰z—7ÿŽZL¡¶bjb²®+ )j{O[°-,I¥«Mãnœ¦<Œ`–rÎ9K¯¶#þúê*ÆXÖê‡øs׿)`B@ó¥¯lû… °Ò0Œ·ÏŸ»–ÜßCÎ ZKc4'ù]˼„¾÷Ýï•RLd¿; À~ðƒµ”y>MÓ´® 1 …M³C aã^ùf.‚3ß t1ŽÛˈ„€TÝ‡Š„¸yV·DsåÉYt´E`n³ÿpV:^ ßyâ–|‰ ÈÌ)ÆqîIP›îÂó@rÎ +3:6eçÙªv^3ØeUài^!áóçÏ×u%@‘½5ßL@Ja^tÄ{6 Cžççe}z:þáþ‡‡‡ßùÉOðæúæ“þ€™Má§¿ó»ÿðüïþÁÿþ¿ÿÖ·¾Õ›¨Ú/ùË»»wµ­_}õ…j7ZœúI)_¿yóöÝÛ_¿|óîËwï¾.åt:>´VïÞÝÿ›ýoîî?ùÁ÷c "í믾þùÏö?ÿÏÿÓ<×õá‹/?å­®óÓ¨~ë[‰èßûoÿ»_þò×MìãO~ÔŒBž^¾þè?ú1‡p:UÚW_~>ÃÃã#"”Zxœ¦”Uœö‡RŠx:bF †»ÝÎ³Ž‰7ïˆKÊ02^„¤€hÆq8ˆˆ Wk­Ä(‡¼bQæHD½°q€—GªšŠŠûu-H‚‡¡P« Píüƒ¿)„¥®fj*­7i]¥Kmu]k+>E%òúh;bèü,ÒæèvæðUß,¥œÁ¨Ö.¢hj"ó²øþö{ßÿä4Ï÷÷÷˲¨¨öR¤µº¬`Ц]z 쵂JDµ¬hß?Ü 9===ÆÁôñé)¥D`•~ýêÕa·{ûöëw_±žN÷o>]–“™¨´ÈÔʲÎ'íUÑjf9 €Ü›ˆè<Ïã~wwwgª×ׇ”b]OÒ+#úše2 Qàu-Ã0PÌHl*Çãq=˜(øM:öÔ]³ âCÈÚ»ã? ÁÎÊTÜdä[ÞæVâ™:Ús;…é2šñ9³ÏkWäR ³íðÃí”Ù†9þ»{†€¹Ö 8Äíÿ«»]{ǪÎBØv®zfæâYˆÙà ó8”RÌ û¢ä| ùÅÇq\Ö"½‹uO/™¦‰(œÍ±°®K­Á3ÔZ MD´Wß@Úy'y¥˜†8äǧ'o§q]F"âaÌdRÎy0s¶8.ór:Í1°ŠIï_ýõãã£ÀnºÕÀ 1™˜/Øä­|&t9|J©·æ/•î›¶3‚{ã,… *DtQ³f÷o’cˆ*NËÙÜ!D×_ª"ùà΋t&DÇÄûÄŸ¼2Et™£{Yý'ê½Sà.ⱂ!$U5s«3;¯ UMÍQ½XJUPa&C©–ç”N§Óþpõwÿîß}ûî]“õþáaÚM1æaÿðÿÎõõÍÛ·oý«_¨êÝ»»uY¤õ7_¿ùüÓÏ¥õu=½ýúÍ¿øÿ‹ÿñÿû?2Óét¼¿·ÛMªZKñϰõîü}éýîîíºœR¤ÖfB³ÝnoJ÷÷_ÿÕ_þùúOöéo~ûgÿáß½{÷f]çu9}ùùoº‚$0e ­µµ¬÷Oë÷ðCä(J}ë»×Ïž¿}wW»®§'føõ/ÿº·òðÚT§ñbRCâàº5Ã4ä†*Ý-Á]º™Ç¢9š ™H ìâóæ”Ã4Šèº®WWWãnç/y@CÚ!˜{|Þçï'Ðù¥Þ" œ/¸Åˆt‡èŸc½HîˆÁTzohˆ¡K“Þ|õÜø¾5Ý`ä¹à*€ ^¦™ª—·"J@1&D¦iSŠó²Žã~u­J÷wŒÄÄcŠ1„ùtsòFJ‰b’(ÕÜÖj#¤Íë)^äò2ŸbŠ·7×ÚEUûý'ÿÿöý¿ü?ÿïÿùt*eIÁ5X[3UÚMcŠ„H¤kë]ÅR|ké¡”Çãã:ŸÆœ†œÛº:ÑÁ@Å߃aÈW×7½Ui¥•ÅTsp‰ r‘C×&ÒÁ5× Òé<‡pMƒ&6³ÕîÀE¤37Ì­ƒ<]¨îÇâ&†i­m²uC^²^6Ïž]K@ÄæšCð3žU‰‰Î76pˆ‰cŠ¢êû€1ˆ‰ÇbÄäÍÙ~wåqòD—«^cä!ïc ¥®Dˆ­w†¡”f&fºÌ'WCûQµ¬‹‡6m¨tf6•m(çâ"È&¤qw0ÓV«™2`Œ±K-¥Ho¾ »ˆÜ×RˆÙDi¿ß«jˆÐD5¦ˆ€¥Cg»©Ï¡«xȉbHbpPKz\íg€ïånóÞ`«¾Y=ïº/`bþÆ-â—âvƵ†ˆÑ1MT i8H )y©«›tI‡qˆ)Æ”<Ýí2Xs)·/^nžx¢3u`ÅÎËÉk¼ÑzKij’Sj­MÓTkûì‹Ïs1¦Ö ¾{wÿæÍÛwwoïïŽOaØú²¬Œ\Öå׿þõŸýÇÿð§ú§oÞ¼}|x8>=Ùn·{|¼?Žê÷bï~]5‘F¨D µÆ9†x<ÍfýpØOoÞ~%Òžžî¿þú‹ÓüZÕ4D<öËqbDO+4üø“Ä4„”IÍZkï–ÇwŸþòm™Y:™žŽOWû´> s1ÜÜÜÆóUzkÕŸúa ¹wYæ™ÕüžÜ4Éj~o'$¢™q¯A-¦üÿñ?þ⋯WWói}ñüå:Ÿ\<`æ¶¾î,×9ˆßÌì»÷m“æl2Cd3E:ìwhÖjµÀŒ.ÚQEé}Ëóë­˜)9†Ð—ß×XÑ©þ¤™˜ÊåÄ÷ »[ïÔ@TÕ”‰ó˜ÌàÙ³çµiWˆ)FŽ!ðõa·œf&ZŽÇq—u57«™aë5åè„^51ÓØíøËéSÕ×/_†€e-§§£ˆüÕ_ý쫯¾øÖ·>|||ò°®5Oӳ篱µJ 2v­v5ˆœjíÌq¦”ó÷¾÷½»‡ûHµ3"žŽÇã##†˜›Úx¹Œ]E¬_4‘ž/|1tÙù † À"ªjD†Ø¤"ù´ÍÝãŽp¡óºåŠëª•mÜì&2&Sç™ðû~ŽÈå•CÎÄôúõëÇÇG[ Y)ÏÊk;§M!ây1p¹t·lÞ›:ÿAU´¹ ½”2 ƒ·qȬâœf˲øêxzšöQ½:æyÇ_`½w3éÈ TTE6û”càæÓé4Ïõ, z¼¿‡±Õš†<Ï‹Syb µ•‚šÄAtFŽ)¯µœžõÝ»7µ®ˆ†óüD "MZËc^×µÕJÈ¢Zj›ö‡< ßúð#0›Oó|:–6›Õ»wo–‡wwo¿©`A#c+%å8M“j'¦ë››ZK«e]BD f–‡1¥¼®kY=¸ÑÉb$z¿CDS¹ÙxÜݺë¯þsdN9燇R‘f`Ò›×oL„„ªâ)|…ªb¼á"ŸÁ²Ç/ôÞ[ë®·óò!„`"‰)" ª#2 %ïÁÌc` ÍLÅ´Û9h#–žeÚftN«Ù0f™ sÞÕ&Çåù‹WÃ0¦ùé~~x赦1Æ´ÌKˆ‰˜ò0–õ$½ù?ÅÃQ½Ò…c«­·vØïžîï àÍWŸ¿»¿k­@ïú›ßüº”r<>Ý<»±¦h(Æe]—yã0"‡¶®fôüùó4 µÖ/ß|y}}E Ú{-ë:£¶M2^ß\ïvÓÃÝ[í½šH¯‹õF&Œ¦–ÒPÖYµùÐ{ë­¡!!¹›ÿ’üéÑ&—¼x‘D|x·‘ªþ«ÄOÜfî>‡aDé‰ÑÌÌTáûºóá¾ «Á@½±3ÿ?C05÷ ‡„Äj‡Q̺ö®H›©€( :bÌ1åqÜïö×̱ÕFTºS·zohDjÌDºô–‡(Äœ†qX×¥÷F„¢½¶â‹»qœ°uiµ¤‡²®d(pþ¡\2@€¢}Ú_‚J !F°ZÚéø˜s®¥šên·ë½—Zõ5Dó Ú‰8Æ8/«™Î˪)çÓñ8Žz¸h[–%Æ"}†iŸžž|{8Æ”zÓiÏA”BBâvVy¦ ÞÜ!©öRë ÖSŠÇeáTº´^[­µ>>><==”u‰Ä@Lƒ©•µÄ“™Æ=]k£©;±Ó€)0d$NÃáòíÆ˜æyñØ 0ÑN½u7#`áœj `)$Bjµ…ÐÅ2rägt)‹—`.€k­¥”oooÖyݪ9U$ð^—æóYT»XÞ UÌ'I®¼FÄH1P¯;€ýãB`í8¥ýõÍZ;!¬ËÒ×å´.ëeɳ®eÆÞÅÄÌJ­1Fô !¦¨]‰HD]òLË|J1`¤ZªˆÍóì^êÂÃÃ@¸yþÜ0œæ•Ç”Tz¯µ‚‚Y©€SJ]íáá!ÆØz)eUÕuYJYP1vóq€y=Y+…zo €ÖkY݆ÚETºy$¹4§unímW….Ò ”6#¼Blæ9—ØDð¤Ã÷ÈË’ƒÝ»ÛLÌT‡RJtü›ŠùXÔý>^æZ 4ωAá¹kÎ9¬Bô,@°«ý^¶ÐÉ9#žã 0ħiR*¥ÇÃÕMkRʺ–ŠÛøKBàRj-«€‘ô*Òc ðôxŒ9Í묦DèÂ>_¶—RJí®2vR™g/‹ É•y.Ê" 3àd]‘öFhÒÅzoW‡Ý²,!0˜­ë‚9åÄį>øàÍ»·µÖ4 e]RÎ×WWËñä11$B‘Þ{Ï9ùÆÏ^fF"röZ[ÕÎ îB‚÷£˜-ù³÷ÆÌ½é¥ë¸¬|™[2ÑàþÒM&¿m,(†°uoD¤ ã8©ôÀîïïRN½wŒ1Ó4M¥'¤¸ñË6êÀ08|`[ô]v<ÀŒ¥TO¡Š!Ÿ#¶™»vÿ0ùpT ùrsØV±ŽãàÐ|fB¦ucL­·V[LÑÔå@@Èî\­µˆlÍÄë>ZÖâ¢Ûœ"3QŒë¼¢òÕþúîîNM9b©K) 9à0 ª/Ëéx| 4 óZÖqOÇÖÞCJGÏ1Ža]gi¥·¢RÀ¤[뽨È0ÄÚjm= i. ´„¥”ãñˆªZ›Æ”EtY–ÞûíÍuÎɤ›Biv^•›š“¼üž¦›V«šÆ·S”.W7‡eYD Áp˜vûþjÍ!ïÆ±••À@;Ó6Õ½ìÇÏù  fL@ìŽ)0 kÚ7+E‘™™Km)E/ÁyûM@MÙ¿õ )M€‘cRpÌ^:NSE3 ”¤ë´îwSoíp}Ó;¥ï}ÿ‡_¿yÓE»O—Ça¨­‡¬w*]$¦ÔÄÌZ©Å{ CÓ²¬ÒeH1F<.1# ÎóiH¹+«Áé´ŠÏn^ĵ›u«€ˆ ¡kgæýõ¡ÔBÖ¬–²ßRÊDÜÕã=už @j—®¾EPU²ƒºlƒØLÔBˆŒ !±ÈUücòN¹£š¹q™ ¬ 3£ƒáˆ˜ƒt€‡Aƒ¨"˜˜¡Ã!Ôˆ“(Ä€ ™U¡wADGÄ(ˆuiµpÀÞŠH[×ED´÷‡‡{U4˜†1¦Üš¦<†À¢bã~‡RJ­öRÖÖ•Š&hÝz[—£JI9W§ã“Ë9T5ÞïÆu]v»,ó©”5çDÄ"=qÈC*§Q !’Þß(&0BDÀ.m2Hß³]§Ök`rZæÙ¥>Ó´°®Ú»552F ÇûÇݸK{mc˜ëZ{•”‚'—¡¨íÇý2/C\•›sNiPµ˜Æµ4QðÁELqÈY¤»ñ±K§±Õ:Ï+b4#×é“´ÞbJ]ÉÑï6wQq 3FÍ݅͹è¢-ÉKT ÑØW¦]]ïÔ»”R±Šš(;€À㜈xCQ©ÅaÛ–ƒg´š!€µÞCHÒ»“Ñ` Ò‘¼g/¥yô´Û!8çÏxµ‚3ÃÇagj„‘ÆqêÍÌp˜X–ãZN!ªb ÚëÓñLT›¡j“¢œ‹º¶Ê1€¨X 1lŠd Fª#Q ±­%…0䜴uF“¶¤/¤= ª–fµ²jm À`  ËÝ}íƒS(½©6B3mÃ0Å1 ;º–EEÊZ3ƒëi˜vÛ$€Ó°3õã÷<»D°”CY‹ª"3…Ít-« ¨J)Å>¸4S|–z‹îB²s|lýþ`h†„¦Òd³Š¸¬Ò%ìg‚”¯û±µbf!$fN1ãYùwþgm6zÛ ïXZuµAÎú–².Æ´[×Å«ÂFæ‡û'çõœD‰ @ †”ˆ(Æ4äÉå_jûý^D95ïlhw*–ÇCƒqœöû):Ъi‰ÄDaY–›››ï|ç»_}ýuŒ‘Ѱ”¢jµVSC$/‹·šz]HÛôô,ˆØ~™»£Ôþ«´¬-Yi²ÑC¤ËÅ­ŠNzGj[,œºou›Ÿ%¶Y–ðR¡(lHHò?†+Ù» oê—­ ‘ÞºïÅý÷…ËôÖõ;¢½wñÇF¤#c΃#Á I#ÆÖÚºÌ Úk3íÚºôªÒÁ`Óe×SòwÞO©½·Ö`ÇqL¥®Õ…ê<éÍ¥ºªê™>pž\ù˜¨ÖŠÄCЇÝaYÑB@33aæÞ$pXkÉyìjø›¦ˆÎóüüùógÏž=<==1;Ù™Äk­w½¾¾VÓg·/îïbL‰‘¤÷< 1F·¼œDÐ{gžÙtálD­•ιá½wGö‡<ÿåý± ºY¨brŠßE˜™ÃËØ—vY9ø—å”ò˸ÉE;ŽÙò§Ñ꽪t3ÿƒ‰t‡x€³ªè¶xàÍa°½VçÍ!!ž™p±àn¯Ð™ál&]{­µÔŠ"½K×ÖU»©Ho]Ú¹6Üšæm*åB35sš{†Ìvfèüö7òt•®¢þ„¸Ý‡ˆ(ÅèPi0å8ì]w¸‰ÇÁ<|@LÝÏÂ䎨*MÁ¶ŒòÔ×=¦êá<ÛáêÛ;0ÏNÞNßmùß "ì?¹·àÍó9æ?á…@’c"Œ¨¢¦zYÀv¸o‡áùß¡¶c¨¥ÞÜ\ùÙçŒØjÍ(¦ÓãÃ~ÚõVÏÜŒ¡”š3ª*¹³ˆÌ€™ü&§œ‡a˜Ð¹!Š1D5PQ ]µk+¥µZ–yYNRk“ÖÚ*ÚºvéýÅówwwÏoŸÝÞÜ~öÙ§ÒEEz«°¡x†”’¯³zkþúçë½3è!"¤ ÐÍMCÀÌÓ8™óLBØð€Hhˆgƒª!B ×AÛÝRÐ/ HDbò”LnlñmÅ€©ôî=š{b>¸õ*ŒÉ·âÛVÐc;Ô{ȹK°Èþ~z —¸ºÖŸCå@1 ÌL€`½mͬ›ˆj÷á81Íó,Ò7™ÓY"ÙZ‹‘˺ÔÚ.¦žœÓ8 ½Õ‚v1é}ÈÐlSó ôs?ÊÄ!˜YN)¥b8ŸÊZ˜|!‰¦ÐZ[JÇI Sžjm77ÏžîïSÎ?úñCŒ_|ñÅn?¥œÖRö‡½ÑþÝynCk­ÕcL)2XóDÛRé]a†óÓãq¸Õ–†C$¨¥mý&C‡aôX’.Íc`½BçsβD:>=ÝÞ>g æ°ÛíMLLTÕËüs9å?²_üçƒø,«ÝÎúóˆÏ¯¨Íøfæ×Õ寋:Þ£`¾±á?ë=˜Às½>8W4[dùMÜ{€’;ªüƒj­’À«¹C]§/½¡Êl5Q 9­”óbÏ>ìÇ£é¦ÍõÀÑ3B•ÒÁT¤û' .í Œ*Ò›ô¦R·V°w骛MÌØýÌò˾‹ ¾wð¥ÄTºz1µVÏøèí÷OfÈϨ¨-mÆ”‡éšˆ\Y¨ú~ÃÖjuPƒou<<×ê~I‡}:‰L¾Ql^е³ô¬”Ã÷‡7S s:DŒDf`pþî]9÷˜Vé` ˆŸ‘—# .ûU¦B`Ž)g§9–e! už§q¨emµ€IïK)K—–cì­ív’Š´íd€D]{àPJÛ  Òåªì­§”EÍñÖLB¦)žÇCÖk]{¯™®§teÂyž¥õµ”ÝnZ—Ù3£/3-$"SÕÞ95qé!˜‰ÊÙO`çw =ýò.1 É¶-¾^‹!º ^DÜõ ¶%þœ¥Ðx~È`“¾ºøÀί–Ôª*Ò\«|_à‰ìH(No¿¼«^ñÖ¹ê¾%fö9OŒÑ‹&B‘@ÄL`JŒ@~Ç7 Ì`ÖZ‘^=#´›4'y;ÀF´#‚z´KŒÉTÇiÚ°YT4§4œ÷§Ó‰rN)U-ëªf1¤ÝnSˆ1ÂåÃÁÍ3‚½õ²®ç•;p ”RQÔ…”‡išvU:QLl§ã\k½»»+¥ôÞ<ÏÖA1%&ÑÚ°[¶ãr;¼üs>šÈÒYÉC¢Ö[‘Eº'1ùG À¯^½V5W‘/Ëcjµ3Ÿ÷¥ª&í 2¥À!ÆôúÅËu­¯_`b)åÞ+9RøìNò‡Õ:rÙÒÛPìÇ'4Ù9“d£Ò}ˆ®Á’Þ·˜€Z+„HÚ¥1…Ëîä|ÞmÕ½èYÅç²×ùû›aŠ|ÀÄ.ÏñËIzo@â©÷&ªV{ï­›‚l¡m—¾½—½ôöÊ€ ñ]bHѶCÐÀ ‹ví@]ø`¦j—ÀîÍ·o€@H]:"ŠZJ61kó_1ÑkÿØß+ÎHgØÖ$›Í˜÷W/‰ð,³5ß¹©JŒ)ç{ƒ£›~U5„LÀ11™ø@÷s²¨¢J׌ÛåRߏзþ†‰m ¢ožì›ÝG|Åå7Á¥T÷‡Æ•3!øVZ«±¬ë˜öVçõ1F|||+½´¶€ôVK`¨}­µ¾ÏJDè­B—ÞÏkiÒæø)åZën·{öìY«u-‹©šu"O7VfÒ®½¶²,ÿ{Òê<ŸÜû ½UBÂÀƒËË|š,Å(gù3˜©v¢‹õìÙa¿K)RŸ%bÛ$¤q†ÀL¬çc— ÕüÃï{ˆ‘»öÍhïÓ<˜Éý g&I÷/NUSŒˆhÞ¿v ¯ »¬bºv3ÈyTUïÓ™@LQz 18%‘âfˆhµ¬¾7ViÒ«_né 0ØÔ>)æ!çÞ: õ.¹·æõ¤7¢Ú[K1ŒÃÀ¦)­ó:Ïs)eG ¬eu Êå-ÒÍ +ÝL[oÓnŠ)ÖVM¡Õf€ãnW›¤”N§ùõë×÷÷k]w9­eÙïOOO¾(v¹°‚õÖk­˜Rr¸ki5pps¦”ZÕŒ˜º¨Š "sôážKɘy8´ÖSʪZêz³ªÍól¦½÷q‡Ã<Ï67aäBÈ!瘽K1vWÇã©÷žBœ¦ééé©K3?ÒÀUU`.NñqRÕe*ë·÷Þv0óeþà'»žYÓg!–õÞ‰áB»D ÿ›·¿Sm‹£­ÚÞ¸t.ì½ :ßmÆL½‹¬ýuH)‘‚""¡!‚¨5àÍ ÌÁ7÷œe_àó¿hEÕ@.G\­ŽÊq_‘¨¶V Tä᳕6+ "깡ÝJ(¹Ýtw«o}4Ž!ŠvO+còªTDEøü#»ÖÓ¿n¿áøêæ¥[“Ü*†g!T«¥w)¥,¥´ÞÁÔÀrJ)( 1E=Óþh+=åéÜp¢!n3o÷·‹ 1ÄÄ1(˜y"„k¿Õ@=“Õƒ"Wbk½™»rrî m½£!ºd[jc¤yžC׆h]ªôU¥¶º2+˜µ¶r ãéIzWq”kƒ7×y‚gUûLY ‚ϲ‰IMC ¢²®«ìÕ„ R kj–SF°·o¾í½VéÝTΫ»Š\¦ÌжÁÅùFìçáú器‹žâˆz­¾ÇWSqi ñyæb U…Ï~.ÁÜSŽ‰Ø¦5Þ€ª9Hg{ Þw¾xñ>Ãvü×'û6[ôòΛÜiÚ™bÑš¦âÈoF2q ŠyúŒ|ÄH*ê'‘ØV(‰kÌÜdXÛöKb¬u[„‚[Þ"ÇýÃh­===š©h‘É —eñãfYfqÃöŠžµßž†êÿ­uA¢ÖûþêzžçøtšÇ!f&­‰´.òƒüðí»w˺rä.R}Ä!¥ˆ]º EBŒ¶ÝÙÑj˜óL!„Ì@þ1ª¥”ò0ÖZ=~³ÖŽH9 `h¦Ë2Xa†?ü0Q´¯ëŒH•C̾ ¦qtøšonŸ=»x@ܰMú–¤ÈbÀípÚ\/™-ç .5»?6MÄ¡âxnºcŒ1¦-F„™‰Ñ½Z‚uõϯ Ÿ>¢:|a[¨Ò¹qôiF8«}ü|4aðthUñ)…Hº™QŒ!ÇûHçì¸Fô$ZŠiµÃÖ¬\<•žwyÔ7Šë—6>‡ù;x¾+ì[û4ß™Žça®Wv;woÝ· Á…«zùë|€ØeÀ»ë—Äì>Ì 'lv¾ýüUuôDL)ÅÀ„!¦ØºX¦Òkë ™¾q¦ƒËPüÒö€ ‰=¥7H)Ewßm*¨m†îånœ8€Ò[“.ª!FDæàCÆ-êO/–Hï½õZˆ°µ™E„Íeá@}Dk#é!„e>]Œ0—i #hï.|0ÿÉ A-F"¢îØ@€&õÝýCÍyr·­i7ÕÞ»´^Êz|8[oUêê‚ 3‰!öÖÔ€‰b Ó4zÿXËâ,êûyÞä.[`!n+QT$P.GPß 0¡÷CÛd]Õ´Ã™Ü çG ¶%‡ˆÂõ®®˜TQßÐÊÙ‚´ýy6iôÙã-³7•êH£óÉÎK]¯Ä'°¼…‹ÇÌÚÙ℈€îÑp‰žôn¦ëºôÖDºùH¨â*¦mÿæÁîþzÄM5øpÀËÝæµ„´™³péú¶™™½‚ó£Á̼oBªµ¥œJ)€ˆH1æaÚ¥!—Z»ôÝ4¶Vµ7M‘onnžžžòN§yÛïIÇÉu_Îne¸W«ûÓŽˆÚeËZñÀñQs !¯ÎèœRð~©ðÍ¿¤›Š¥aL)ïv{×õÙ݆8RõÑ¿ŸÌž^MgÓVi!†œ?F̼»zå`¿K÷t ôBÕ6GûúrƒÜ:QZSµa7•ZT%å„úþÒþæÜ7¥[«…ˆî¥·ÞÍLœ®ø»rÐó²%øáîI»½wBö{SJç=ÁyY°±7:›Y QDöû]mÕ8u!‚nÆ UÂàqã½w3ñ›ÖZ¤¶ ¦Ì›GVM[o×W‡‡ÇQãÀKY‰†!Öê”úí¿ ¬ö‡Ã²Î¥,)†h]Æq³Ö{m Ð6ÒVæ¸ng‹Æð—$åÍìwÖ›nj—’Rô`u/ÞC°·ß³ š¯˜àBëW5ƒ8¤ó¢ŒøÜƇä¿ÃYž´ýybN簷лoŽ;€ª˜n×É9éé<‚Özï²®+j­z÷×ëû$ŠCŒyœ&©µ¬ëº®+3_r½7<™ššzp7sÛÊËgS›œÖðj¿ß–µÎ}ÝàJs7CHÉ3 Tšª¾¯ÜbJ)¥˜R©åêêÊe!M¥Ö> S©+€z [æ™s ¥,NëDDUósç’Žd®<×RѬkO1×Úˆh¿ß@­½” ²Ñˆaœ¦ö÷TA‡œK­ÖE°u™Osާ'Ç4žÇh]MÍB1¤Ã~ÿáë_¾|y:‡<ÌËâѵÄáöùsU=k­­µÚÚ¶&%ܼÄÌÞÄ\ ´t¦ù_}á–ëèaûÌ1„°Ûí»ýiž/KÚÖëùtî¾1&DÙ RôkL\híd›mˆä#~p+²ž£hU¡©xn¡#´E»´Þ 1§PB:wºß8ÈÐ<æZ†ËÕåφÏî&ö*ƒØçRZ‘í¦…÷†Òoœï®1›O+"Íói+k`#µ÷XÌÌ|ðC¨­ÒYáP­¾Ý0Êÿà§Ë²vÑ<ŒäÃêº(öІ³õSÍÔÀJYs\™BÜ Óüt$7H§˜©µDœRc€ÞEÕBˆ’¯‰|»3Š»‰œÉ•ç"/^XT&f¦îm!ð€Jfÿhû,G Fö3R+ Õ¶€ ‘! ©tG3qØ>b)uƤ­ã¶^îLÈçý­ŠºMGÐ`35íŒ8¦dª b¢²®9’Yg@­ubrºO \Ku×h¥Wi¶! ³©Ö¹  yâ¼*ª¸BM;j÷¬ p‹93Å´«S¿]/u‘.:ùE½¿†í¿Â†ìR;‹ ñÜ„†S)õƒW¯ŽÇ£ÃRrL„Nâ4Øxï@LÜ»¸‚Þ\5 æ¥x[áeFlh]úYée ÂÒ;ˆ¡˜Ó!¤  ½·œùp˜ž½zþðô¨ÚcL~žz2SŒ!máÈž K›ÂJµÃ¹­q\šZWïã ¬µ ¦CŠL ˆ½¶Â4M)ESa²œ¸ÖRJÉmŠ4Ž»ÞÚ2/­·q=^cYÖÀÌ„*MÁ–eñlW‚&8HS&ÚM»ÖjŒÔê˜sŽÒ[ä|ó˜Ó0Nem¦8ì÷»ÚÛZ—TeHCNYUwÓDD½·Ó0 Þ¢¶V™‰b10sˆ1”µ!zÔœ.oƒŠòVWRðêçõ«—?ùñîß¼y|z@ÆSY”,æ4NÃë/îß ¡š8ÍŒÆÓÕþ:PÆñ4/¸ÔSrR˜š…»útE%œ‡8zº©¶îz:DŒ!qpáã¸r`»'¶Q!ÿʶ¹Mï}Sv«ËÈ# ýêÄÿ?a»dI’\ búeæ~ïˆÌʪntƒ@³C²ÄÈ Èáå+ìÎ[¬ðE–·¤Ì®¬Èp(ËÙÁÎh »ª23îu73Uå53÷ˆ,!--Q‘÷úu7SS=zô÷æh’(`¨ïfH½uLÈ“Chnî¾®k” êèPèõ ˜UÑñ"Žé™„fÓxX“j´çG6|øãÿx½ÞjÙk)Úuž=.™-†òzo¦;ÇÓgf7K,¦šSжNiµ¶ZU‹63Ëyi{€u½|ýúºïeo-fGƒPKŽŸ?þr-e å­Ú­ÉGŠpʦÏiAŸB"òîÆuÐäE$˜éç¡ÈXê<ŒSæBžÀFkdž"!M…ˆÖ—SìsGã7N»:» 3 ? MäcãÔZ‰H[£Ó÷p…Î;ÐA•1k¦Ú‹iÖüu!%ü‹NáîÜk=pù¸ñͺ¬·Ûm‚`±GJ)Þi%dî|}þu/Ð# 3Ъƒ¹ˆ!.FiŒ”ˆ˜PLm]ÖhšEÏ-,Hî÷{ÇÄãEµÍPbfnêèȈ')Ìäz|°7Šˆši«‘ÔS¤KµÖ}{DŸÍÝ€ÇXZÌRB?I‡— •˜ÉZŸ‹Hà}n-Ò1ÜÓˆ°ÇwG¦ëÔÖmÍÍÜ,Ô. €™?¼|(µÄ->8"IâËå""ÖY§X›2‹Ž9è]Y§ÖjÖ$\¨Ñ´µZ÷8;ç‰ö vÁ!‰| è³Á¸{L™A‘ÎiÝaŒÝRkMÃÙÌ»)–{÷.¸OGdww:=ιÐãòˆ$I²Z»¬<žøÑ®½C¦üšÇPÕÈÐU‘ƒ„wÖû Ÿ€oˆ¨Ñ8éì^æ6ŽÑ˜ CÈÌ(”v“±ZZ+_¿~u7fljçþ^$ªëºÒ „Í‹™E_a/…˜ðz}jªðØŠZèU-ËŠˆáJ2ñѼo×k-½g÷»ßýî/þò/~üãÿò_þËP†ùüùs€ 檪6Ù¨pg‰‰w‡ì3!ÝžŸBŽé±oà^´UÕæVku÷u½ìÛ&""ùñØ€x½,f^Êž—åv»=¶}YWÕ:9‚¹Ì ëîÁe˜at?؇®™ *˜š3§”BV3&GöÚ½±°úöœIëœú™ù×ì!a°Âs4Ä6y>îNãzÌ ¢ ‰I ŠÁ8TÕËå2›IcåÏRÙcú®¹†€iŒ¤Âi»uÿJâ¡çC…ûüu î=Ñ%f.µÂÑ|ÐO#O ±eBâËÓ¡ÚØÇîç(m']Á™ÔHÄÂy{ìqÖíûN„OOOÛö…™ù&¥äíÈÔlÄ»OAPm·Œ†ãËxlͼ©^.W"2{ËŽbtféF?Þy…MzµÑµÉqÒ?/~Æ£ø^­‰ˆé ItÆsºF!"“ 1¹¡»¢Û([l €Ûíö¸?Dzï7LU}}} ê‹Hzzzv·jГÂ%™›kÊ«j¥ ¢Y zS¬e`ôòc<º?¸™¹»0ò ÝgÆN-7@ÐPr÷Ñˉɱ(mZsØqíwö˜ƒ›×ÏÁ ¡µºannÚÌÍ<ÈcB¤çûÑÌñU5fœUƒÖåÌÄÃIn|.ŠI7&¿'šgUÔ­ó›È˜EUÑi¬Ï›ï÷×ûýußwµ–º¼*Î83†u] "ªöi£¢E`÷®QEÈ‘ñÅ:q·õryzz zòóó ŠTmÍôÓÇ¥”Vˇð~¿/y}ºÝn·Û¾ïó7ó÷ÿÿïÿïc+þÜÀc^)¡VÀùYâîÅâé£=µÔu]…XRÚKiª_·G^–ûý.9!a« ™¶²×ªµ5"º\Ö}ßG:fÚ€oÛÅJJ)‚OUÝh{ž¾ô¶§CG“fäÔIxã„YdD€³N5œ—úÄ!é„“ô)ëXPL"aÀÈÑCb"WsìácQƒ;QmeÂAB|½\µ)¸Gdc$aéÙ†CÀ̬…\9 Æáˆ9£31ö8'Ο.ΞȄãg}žy 8d!Cƹs{ÌœŸ>ü õÑ/ŽÌ%ž Zþ‰LO’ż3…Â;Æ0  ¶zÐû9„óuˆÈ´á¸²ˆïýìÞN#f õÆó’ƒ Ö«è¢PøáŇÇ~«#ä1ì¥îSw—”ñD9ÂØ’/­5èÁÏÙA&"bŒ9ø°"ïíVwYÖ‹º¶¦X/ËZk³ó`eßbçGo°”jŽiIyY©iÕ¦èÀÈ’—ÖÔU‘ÜÕ"šˆ:ý0†HXi.‹‘‰Ó(')J®®]$tfîóÎ&«j_9¥É5ǃ} N{5ŸX$Mï¿pŠ•™ših”…p?Îщú/EnÎÌÈ]¨]ÝPdxryç³3Œ1§™å”gnÔOwwg’iÆ€­iVúìi »~H ªC¨…ÅöR/—ËL­óÒâtá8¿gŸd%á%¯"I[׿ î/ÿé»××WUM‰™¥´4y3oÚÜìzY³¤PÚ!äbz<ÿ÷ÿõë«»o”V‚&oiIQC¨Õ ˆˆøˆðñãw=ªê^Šš•}ßKáŸzb˜!ì1fÞÌlÛî—ËÅ\K),IM×Ë ˆnžRz}ý:aÖ™™õx(>åÇ)-`îµÛ9€ÓhQE—~ä¸~äñ±´×pru,¾Ï:±€Cà·3zò,¼À¢Û9"CÇ—hLörˆ\›ÕZ‘‚%]–¾ ›VmfÍ[]f ¼DÀ)Y‘Üãóç֨慈f²;ÿ‘s2wS»ÑŸ×Ý]Õøöòëy˜9Œˆ¦¦Ì½ 3³©Wj»¬k-…À‚ípß^#­s÷˜¨TUaæÐÈ€l¸öeû \Bd‘Fñ!T´qXº<¶­©!` cîÙ¬Vƒ€ aàU!jãnfîF£Œ0µ“޲ŽÐ9äIah˜) ¥hiŽÊ¨s]¸µ¢VÌ\€8IZj+,³3q¯ãÓÐ8Øân@JiY–¢š$¥”°µÞ3íRÍU‰P8…&tkù© t *xjèDóçgÈn&;8q½Ùèì!2ß>öL>*­ø,¡¸ð.s?°™4õÜÂÁWÝ•(…®A JŒ½T÷豊wžÀ}""‡®6„hÐ'igú[kÉ—Áñï•@\rìÆh@…\¸Iâ1SQ 8 uwЧì²z4³ÑPmœy:KˆIÈ ªJÊKkµAÄ9§§§§Ø÷ûëã~wwf,¥|¹mU™)œçDx{b îÎvð<ОEpÜ8Æ>9<É I©A ±ÇC´àI?ÍÌ´´‡ƒ‚mÞÈ5(¨%ÑM%âÀé›ëÜ0£(EfÖ„!·±´ Ý££[œ÷‚:’¤ëó¯âÈê*ÃÙD$2&ŽÉ ’Z«­•uYJÙ”E"L÷wצ4À¯£âǃÅ L6÷À“‚ö'"ÔÕ”Bg¥IZ¢G§-ê\ED m"â` bwê«Ù ܉ºÑÏÒçˆtˆ Ì×ëµÖ:\"ÜÝÐÔµ£/¨ 4EƒÎÍÔ‰’ä,²nÛëÓÓSwUM)wxy~Ž(9qɽ…éeÏ‚CÛ'¤Ãµj^Wa€Öªõb­6Ÿ)è k~SdçËmô|4¢qW#hGˆŒu[–¥µv¹^"#˜èöLÛcéÈà´ÕìMÍ)ìºÂüVɦn (ôc  ª`Ì»xtÑ€<Ú*Á`ô:Ôzk¤·Æ—ª·V‰i]×È‘GU DPéFÿÿâ_”Vk)‘³Q©µiC¬µ-Ë*’0ªUæu]G ÁUïúK¦’4¡OÏ/ß}÷ ‘Ø;šjj9ËëׯL®Áhˆ™ˆ1çeÛàBL„µwX–¥UmMsÎ1ŠÎE–RÀÈTʾ•×uuíl‚7xšûº¬pY×§§'f޳®kHªÕÖ"¡.µ-Ëòº=½Ô=€æõ×°Ýp›dmõÿô‡}/‘´ÍÄ%lÜÝlßw?Q­˜Ù´{ìi©­Õ!7¡Y0ŸàæˆÝ‚Fè`…(%«“Ò²,È*¤aÀÂÃ*'Ã'à¬h´0 Q×4Í9?ö-e1³ÐµO)-I\ãÔïxý¾?¼õÒ­¶FÝ?ÃN˜pðÜB"Ì=‚;b xEªNSK5výĺ{%Œ*0’Ñ IºYP•z/u{úè€!»q"Nžd 6‘6‹õêîà–œœ šî}^1|™‘z …D:ìèNBH§±vã>ÑŸüÛ¾+Ä\­{µDBÒ%ŠÊ¾Ç€,£ƒ+¸™VwbBjÍRNLIU‘XM9qwWÓ™ ÒP룭è@äÍññúŠ`ª½å$„Ðzk‹4Ú¥½ L¨nŒȦ@ÞO>·fÞÊã‘“”íþ¿ÿ«ÿíO?þ4WH) Itbc`ÏÌxYDWU7mn*>Gjqý]{Ͻb8€6x"±9˜CõÞ3I¶Q½B†!ìޣ춌»:"´VHUCý;¢ÃSó –kÕ à䃕b ®îÞ ±×‚Þûþœ®·5Ø„c´½EëÞz†OCõ[ÁÌ¥Ó›kà¹änhÍC<ä‰ÈÕªÞ‰\Uk-dfÚŒˆ B÷\C1"òµŸ~ú©l۾풨µ=€MF’Z5Zj  L`eßXDµ™iÎ)Ê»ZëÓÓ“» s^×ZÌÌ!Œ\PXÁ÷ý÷ǃ˜÷Ò$媵©2Àóívýš“#!“BmeYr©15­[Ý.·u¯{k†D)çfz<ö²G>z½¬nʄୖ=§DHÚÔš«Z’./¥¦÷Çã¾½6kæVZÉ’‚h‹út»Ü_¿dƦ-Ñî¦ÚRJ,­‘Ié 0S„K©(D}–3Û÷ÍL“$„.߆á=Û4®Ä†Â ˜·1­,4R³$¢êDLÌQ uHpͺ›@‹AëXÒj¶—Ò´FªGú=pC×À‰<42}" Û5_ZÕ$¹–*™L ‰ŒBœ«Ymè®NfPUKÙU K¨|õ†_ТcÇ9e1óZ%7Chà•9¶íI¯b¼nt™™]Í›2‘¡9ºÇîY.<@ÎëK´é¢=5!Ê&a€ãvwh$·6Û7r· £!¢»F‘jáÝÙÇ—;X{ð!Š·žršˆè£jf·ÛMDTµìûðt8‡Hè’Kˆßör ÌÐ û`}”ç@ÈìCñf5tÀ%'aávn¡lsÎ ¢çÖ ¼“üIàæèŠ­!âý~¡Á%å$Qmj-ÂW]RZYd0 ¼7}¬ë4™7Ö½'Á˜²¬ëº¤œÆt>Ë9m9rž‘¾M0€cÐôÖ㣠Ò稵¢‘ï“Ñ3¹_cc„¨G^¯ÌŒ"gžÜgnCì kZæÛÆ v€^ wš¸µ:x,€Þ”IBÜ"D—"C½0Äž§ŸÚ£Oöè<{t«‘ÍŒPàz½Æâïõœ¨6M)E[2šˆxP§…£åµ¬ ³„©™ˆt´ÓŒ˜}y#" ¿¼¼”mÛ÷°@Nkk­jCa¢P5Éy‰õoî­DO^RJ}Ø/ñ¾ï¯¯_}J8æî¦/85$#ûö1Gp§¾XoÅUÆ'ÅAhŽP@Œ­ÕVÛ¤ß䜯×Ë^‚Zjnz(#¹›Y)%ÎE³˲<@cúÈe–ø˜p,O"ã¦áLO&·¤“¾—†HÞüŒEÕABû¢¯®SS¨ …õiŒ(³ÒòÛßþix©ïûÎŒ\>û™#9Œ[ÖÜa®;m´÷]©¹zµ(jTØšª*ì¡ÎÔ+—h8†TTt¤ŽÏ‹ˆœ—D$’B·¾×òÖÕ½cºbˆ åN5g‚ŽrG(Áx® ]ª—è<Ð@rgŸ¥ŸbèÀŸ…k­ ae.!‘Âw7* p@ «Î9>€$ h±öô5NTµ®9e'–!EtØ<žŸ 1p—ß90¢®f¾¦ôúõ rèŒ`‚èý" 7mµµV¤hêä€cb¡®F€˜òÑ*+}âè©ÚÞ63B˜4ÿù¼f˜;ƒñ³ásÄúˆŒ=N÷å<µúaƒÇ0Ýèà ™žÑ=;áþOA­ZW¹85„£ñ« ‚½îÚ*ȆæxKSêôŒØÚtJ°1§`_8xˆˆEÚŸ9ÓhLÀ/ÌœRÇÛõÚj­¥ ¾À6¢L¼¯ uÉ* Ö&O–亮¾àÎ”Š›*Âûý‘’ÔÚö}€/ß©ªZ#"!ŠIòZk-MDº+Æ„)–u}<^U5ˆw̬‰ý±ƒƒÙÑPaU⾎ «¢Ç]ѦAûiZçyLD°™È¨Ï µªuA¯è|ÿÞî¹Û„­†9Á$#ùdINUH@K"1*#ó3³Ä ÏÝñ´BghîéÙX–8 *"¥(Üü󘄱qÂôF›ý—ÿåÿáoÿöo[k9g7§ˆnjæSæv¹,àîÑÂMÈ8q ©Á<‘} (M.À!ÄÞŒŠ“)­ËEMOŸ&®5x(Ühç;ĺ\>(iáïJöªÔ1M$8©À̶Ž?6w§{@xÚØ}Š6Ž·¼½™MtÂS‚1ˆ¦`Ü-fþÍБ€b¾Ð{Ã-Ô©0äþäz½ºCbÙ·Ggþ8`4$ÎFœÏjФ Ô#7F0Ó,*Ì„Àµ””GUÓ¨6óÐ!jÔS^B›³¨}³¡;"¥¹”ÒZèùÂDæNK!|Ùñôõmòþæ?G$¤~jŽlcØ¥‚ƒFņÃ3Î]“¾çwŒ×tŸ‡Í©³Ý½c؆:= P[q3&!‹¹$@D¬¦D´^.ÌLÜÅu膯ë5œ.`ÌCÊèºÌ¨¿µ·u]öRc·‹äèè€û¾ïAúîg13Á ÙÅÒAóh™«Y€9¡Ët¹\j áhµ¾¨Ü‚ÏŽðgög¿ÿ»¿ûôéÓ¶m·Û-¤:`Wln¦fÖºâyx6û‚™·ýþõë×ÇöJD|´‘USJµ¬ó^PÛLáûŸ˜Qʺê>¦ðÄu™.˜8Ho/;ïûîªàn¡v`c&`¾æŒ=0ìGd'"U ‘w›Mœ³—p$Ñý…CûÍÝ\bWdv£+3u+Ç^8bW° û½Ð¸ù¸^®ÿëÿú·x½®Ð¿%zXÚÄè÷’H[m=t cˆ 6"" ͤv–³KÍ|TÉ jn˜óòüüRÊÇx4˜ŽA±ïëœáqZ^FõnÚssžt "šòR}¶‚FÚ3nG? ¡'T=,ÏAS8ÒòI¬<÷VCÜÛh¦33sg6zˆ !Ù5‚´©+!º©õ8Ys~€Åc| ¯í>ÕÙ¹û,ÍÜøõ¥ìn`æÍT’g€˜h° TÅô^0â.Ü64/bÕì-IŠÖk¤ICq36¸Aˆ‡0‡S‰Gíá=öÖ@·>è|à*GF€C*yÞI³67íù©žÖú©BŒË+ž²ûCŸ 0¨Y[@1§–fÄðh»ƒ;t3tYÂ)²¸wó.lb¡¹A 1˜“)ŽîÈ)弬—+ E3à3Ž17¾¾Ä nmZ„Oœ*ô~×˵î¾@B€ZJ)[PqF¥Ö…`µsºÑ»œ\Jaæ”Bö`13l­¹á¾ïeÛj­n}âX’ÖòõËÏ)¥}ßî÷Gt_ZmE[ð‚ãî¥Ä€" ƒ´E)¥¦º—âÞî¯,±Õ{ÔH)mûãz¹ÆnŠ7-¥ÄÜ83¾Alº1Pç»{‘S õ‚Øë3Tu˶¨AUsÂ`༩ü‚üVJ8¼ýfžÿ¿ï{m{gH4¿¯B”7ÔFCúüg\ ‰Á5èÛ¹«ìŽnèÕô®ßÇøË¿ø‹üqYÖm2眷mëÒÁÌèh}α•­”ÒûŽ‘{#€ðal2 Š^6N˜k\s\|Ç$™…Y°OFW¼×@,iríJk$DˆCHŠÉa¼ðåéc×Ô†.$ËÂs²C‡3´\öZ!-§Á$#ìÜi³)DOØ%BˆOŒ'jàŒ#ó,pwWÄœrN)@ºbÐÈ SJ{+@á“kŽ-²ÂlÆ\ZP^ ÜSÆ!Wc†ž˜>~xi¥Å»aJÙÌ­‹%te0$I8J“0„[œ4Ú”ÍLDº=Þ9”vsH`@@·ñ¯†ŒÓê £‰Iï?EW°wÞçÐŒ(Ò¢ÎóÞ…9çž9`“(˜O ‰nA« –L $æ¦H>& ‘9<@F9ùè qk³ÎÍ·ž¢†s,€9!÷ex~~Qmu”·L ‘Ý“Ün·ç——§çgê6¡p¸úMÛã蕌Ïkæ!þ®gª…Y»‹°H°‡™‰ÙOã—¡Ô»4èí—Ë…˜KÙ[U@2ídm*!PÁZÝsÎ_¾|¹^/)eWë Ýñt:¥–¼„ÚpÓæàI2v¹}ß·¦eY–È¥hØ(²PkMH¢ò0ï$$!¯w —õ-/"Ó“g°×:²7HÒ'tÞ=z µÖëxBt×¼tÜ.R ¢1eAʘud ˆT-ƒÛv¨ çäî+ÄÈ“Ác®á9­‚D6Þ±W–èø¼>ùÑŸ{gúÎ0à—Ï_ ËCÏNˆ8è‘"‰™Ü¼µŠƒYJɆ\v÷.ƒ¨}ÜÊ!ùûü©ï|„Ù`镂똛êÒ CKZæÌjç­E½e•1„Ñ»$ǘ†‘ ŸbÊÌ(…û(®š™‡hµ0;º$¡˜g8’¸Ñ(jjà}h fB„ä‰ QV€LÄñ—ÁD_¿|®¥”R‡wŒõtF¢YPD˜xÎdv› µ8¯†ê FÁ±Ã Há …1¦Ô+šJ)Ð<_£ƒ4'Ü"ŸHÔûá<ò#‹¡§¡¦pð…aôÉ¿ìxÒ6xË}ìZc£}‘qÌZÕ!LJ'Þ|ñ(ݘÁ†D2 ú~@L975·¡O* ‰pÉ‹š}ùúåõ~ÿñÇc“ç,†D"H1OÇ€è,âµ"àÑØ?µ×Ü»ŽUÎÙÝT+£'’0mDc&$J,DTk½\.0„e"¾Ç³n­-Ëšr^–uY–@Wr†ò"¢­Ew¹\î÷×_}ÿ+3+¥23'¡ð­´²·}ƒP—s'áû××RvUEr"HIî÷ûÔ/SkqI„Ø´Mi­”˜…R’Z aí|hˆ§{·õùÑà­“ª.’"™›F„k^[mÓjëΡÄ̵DŒk‹— ¯êR{ÛöØ g±6©û‘AÿŹlfu8ý¹~9Å®ïÝøÿÆî?‰ qÓöñãÇ¿þë¿þz¿ÿôÓO÷}»\/___¹·*‚ú2ç9È[­j>J &î3ä](éíi¤óÆŽ+`NÔ¥¢ÆÈ„´I¨Tô9S"2@3ãÌ¡w:^ BáDµZ'|/—QÓØÐëyx§Çµ~‰œ¬»jS/€Lƒ'Ç®ïhÇUïšà0™.ŒD¿úõ¯k-ÿô¿¿ÞnÐï>+x7’†ã€N"©Öçp—Ž AD"­6bŽöG¤íÍ4ŒÏÌ»¤ôÔµ3À&À dd ¹’ ’Êx"|Œ®…r:tjZ­Å»‹i8G¹'Ì9ì·‘Ž5×ß7ZÚѰ®¼1“5¸ƒ ©G@D׉ѿ†y @ô-‹'> 1Î}Vá‚Ð1ßp¢ABä}ß‚”q¹^hØÝT;| ™zÞÆþozÒCvwÇCu·ËåÒZµ¶§”l~@trM Ä!ù µÖ˜hÿl­€ˆ\.×RkkŠˆûc/e¦¦µî%PRJFR’œóöØBUU«vz1ŒL+D†•ˆ—å²oeLÐxX¯¹û?ü°ï{m%.&Î ó¨Ö)µÖº›ö¡°é¢wªµà„Ø)qî8IhqwÇ(¢>^wõùééû>øýþﬓýëº6-D¨Ö‚ÙT[ ñÔ¹÷i88ÂЦ!D#L“Hì©QÌ<; -—(/(|(ƒGnÃCÆ™b°rÊÆê?Æ'ƒËðôtûüùóßýý?¼¾Þ0%®ÚÔ”9Y‰`0žƒ[iR’PSmµ–¶V;zª‘QÅÔHW;j†ñþ9g˜’©6ÕÖ™ÛØ'z(t—uѦæžX±™@ÊyYÒàM:óõ¥š²äè22¥”ZÛã¤øIÊ¥hÊ´o;1iSóÏÖš«2cW&‘P!€qfù6LÝMcÞˆY(Ô1Â63ÐÍAÝÙI;sò:ê©JÝÁ ‘$¢°<ß^=¥Ä,¥4B žŽŒ„…âÜÓþéŸþœó „Eµª~üþÓ^Ê*¬­íÛ¶¬—?Pµpc饲9TU¦Îj‚^Æ"8 ÷f{?áÂD*¤-Î-âÔGïb,>F×" ˜Y Ž>diÌZ4–´57#Â9 6ÚÑšà#"!1!‰š»V{º=kÓœ’©ƒ÷6W‡œGÆûʬT¡‡$ø÷|xÌ(OHáÍü1L Äwj"0)QÀ‚æ°®kZ²;<üøáÃÇÖª™=î(ûŽÑÁ@‡´,eo­Ùº.ÔÝ&KÈÛ S’°‰:SΙˆ¼–ênœˆ“€Æ\©º!9…ÈasLËŠ„—õbªE!-iY–mß·½˜ùóÓËr½îå. Uã²ddÙKÉ÷ýÁ$PjI9ç%•ZÈñº®×ËÀ™ù±o)IÀ'Âü¸¿; •ºÇÈëãþ@į¯_ÚPè‹çîêjC7pY/áì¸SdWÜåZx­Äù;úu†-I"G­­–æ¦$\kmÚXRÙö¨êÖuýÕ¯~Õövîw7#€Zwh#‚.ÆêàÄǦ¨ô|p³Ž/Ds’Åóô5yÀº=¸ëgÈûœüŽˆI§ï{myúåOߌ®¼¿ºóË,Ëår½ª Çÿ#‘šÑ‰ û6Ù?^|þû)yóŽ'îœ?öÉdw· Íð¬2%‰B>†Ü 45 [/×}Û¾ûìnx$ÎQÌfN­…Ìdoà‡8‰ Ö‚[Õ6íŒÁÁÁ9º>A?•I¥/…zÃ¶Öæªe/Ëå"’D8Zgµ¶ÚÊãõ¡ÜßJ+L’˜sZj­µ¶°ìiÍ¢yªìgP¸”’DC &R\JÑ[zW“JˆgûWµnÛE„SÊ89¯Sƒ$ŽÌÙªã3­A[D—”RJûöˆª&fP[kÛ¶ýÓïO,Ö-¢ð¤ßWï3p8Õ¹{Àš¡ú O-3Ó“RjJiY.ÃeÉãuF>w•bJqvÑ{ÿ\[­%J™”R­…àÓ§OqH¨ëüeâÆ4é¤$ÚÜb#߇ÑâúP@oóÎÙ$˜³ãHæ9»t`¡ch »#adý=t,‹‘óå%§”SRmM[TZnݰ5%’”’6W³P>zzz¹ßïá§¼,Ì›¶7¥ýÅ:/;03Ãù‘ÌB$ˆ¥'¿ãƒÑBvƒ0ãôcáD „XˆÑDö©¼ó¿ÿ‡¦u„õ­ã\ä¦mÀ zßÌ”[­DôÝËó×/Ÿ©'2´aYBÉáËÝÛÙæ6dIÈ\#âM ‰‚à/rµ'& œ#{¼ ƒO¡µ(O|Æä#^Ÿmg½?ިм î“`¶m!k/’â¿ÜÝümd‡1'ïÖRÝœ¢ÀÑ  8®‡f‘L(À‚ÈW$&N@BœÜ‰öýq¹^ËVX¸ó9ÔZ5Dtd&­Õ£lôÀ£¬ 1õ¡î`ª&ijØ•-dÉ™]“È’cL¦Ã;„LÔ:%HXPÓœelDnOOOÇÃÍ8ñã~¿\®Ñq}~þà­íÛëìïû.ÌyY"—šmpm €)'‰êy& #ú8%>–\š„}Ä1ÛëõöáÇ×××8Z«ˆ˜s–îÖkBtv“™Ç¶‰„Ú0IÀ5µÖÚZ7òEyHû…-u§óâyýÛi#¼¡H޹ŠÂÁÌ ˆhY–©àîÚç–ùí¸ÐØ|§ÏOžÝ­•”¤ÖøIJéñx¸zs·J³îÿbŸó¥Îæ?à½hí=E Ð²¸‚Ѽ|GÒ?‹YòÀM» Mtßà™˜7€{­mȪ÷´=Zyæáa`À×—ïã3Ç”]×îéBõ)f:¢™ÎˆdÖn·§}/L¬jµ6· Ë)¦ÏÉ4«­cµ>dÂf¡KS":2NV"w“a z?ò@/·[Pñb¥Ž&Äê §¤Ëeùî»ïrÎ{yìûÎ 0¤"Þt¼ª>??o¯_×%¢YC„RIR¸!:QJUU2+#€–ÝMBzï‘GåACg¾IÃßüdŒ-M’û·9ûüÉd(Οc T|óú£x“¼÷èÜqçï—R½˜¤.ÌBÄÞ›À>_ëÝ•ÿÿ¼Îë&|‘z  ÄÇç‹t”8»ãz]Æ !"É’`ΙÛ#çeßÑ_)µ˜»PfηëSÌúäP†A*­öRѵA9"p$Cà$)‘›» Á#eÉ’%‰pòÞ&æ¦J$îÀL­ª1§8±û+èOÖš^ÖÕA­)"Fù>ëëº_T›k³”–Z[Ψ²0³ËåææµÔRöÓ-Dqóm߆ˆü ‘=uMÜç½U50L o–ék;8äÛë+D—_˜… ´éõº"°™Eô ‹ W›ŒjÕîf½âÖŠÅü' axÖ g‡º…gçœñUÑ­M‚t'º#B¸N—RjU‘D …®|Ó« ŠÙùõÏ Õ¼ÆpF$yû¾ÕRBNjfåcƒ™2KðÆ«ÙÍ,K³bèò5Ý ºä<³ÏuïL€ ;ß`;èmPîC¨°ÆNغ‚Û< âÚøúü©Ö"ºp®ÔÆyåÛ¶»‹¼¾~%äj¿ùÍoû’%À²o Gìk}€&áNkF9f‡ž¤hƒ·Žˆ“¡I05mÁƒ™oJ)CÔ_µí?þøÇ}Û–e1kƒ=:‡QI9#3чç§}ßÝÚãq_×Uµ²ðº.] Cö ü‰ˆ íP"ã¹àñOvº-ïÂúé þæüËç§>#æ·¯†~Ò9;ý&~ƒ«Ìx §Ì°BÌ,œ"Ÿ@Ó©”˜ÿ¿_çß# }DëüÑbµ8„ ª†=1ôÄ>[èâÕv½^ïÛJ­1·i %-×ëµ5+e7ÕR­•(p`xö*Õƒôë„ÌŒ,îà€­6sGGsm­Z³¦V:!bм­Ô ™SÔN½41 ¼¸¶úë?ùUylÌ‚‹Q­ç¼¼¾¾¶¦×ëUÕ˜ÓËË˾ïa„ƒ8˜R®µÖZSæeYSJÞ½gÐL‰zîf££Ò§ùCÀ‡cºÉ»5@P0žfkz¿ßsPцÐÈ”oL’k­èt½^Ä2˜ãu й;†e34kóŸß pv7w°Æ„ÝgÂ~Z«èÖè0Wêì>êf;ò¨)8Ö•\CKnî  Œ÷²»CÍG£2eñÓ¨0³H’N q§PxG é*poµ¹qfà㘎@„ Ýî âÜî&ŃأÑ]è5ÿÄ|ÌsŠäà Ç²cprDï„Ä®Kl][ÂOþƄ漮À cØ,DŠ t±E˜YZÓeÍ·§g3KIZÓRv&þþûOæÍZ{lw™Ñèû»žPÐ Ç $'m¼Ä¹dS­ˆÇR0d"êÒ—±^`04ÀT×u°VKHTŠPìdB×~ bŸxkÍÑÔ”BRU{¡u.ª­¿Ú(-€úÑÚã ö @ ÆòhZ|Ѽ?QŒ¾ ëçhþMq÷æ\+™ñýô·øí Æ!4¢6öõtºíµ¶ !Ú ²÷áDÃwÆ|‹Îß1ˆ’,<²#tð.Aª«õYê¦ §¨zÊŒL̦¶=^ÑZ›î ˲ª*Óšs^/×H¨Z#o5îl°n)¶³Fù‚´J)唳££ZC bAd `– €; ‰È‡/÷{`ÐÎ=陿z¹ÔZMõr¹üæ×òÓÏ?3wGÉÛíöáÃGUE ¿ú«ÿÝo~ó›ÿüŸþ®YÀuYb9Â`Jyßî êÚ<§EGFe—f|*•"ü×Ö*†u9ÌHD˜¤;ΰ5U0…ˆÂM%Ê¿R7 ½›šC7çUá¸Ãwo ŠA'ƒŒ¨§ÚŽ¥5é6ïjQÙSæÖ†aä\ÉqžÕFº î݈ K¥$Ñ™Ð1pD“s•÷XÌ~'2‚·;Ô=Ø[¡Þ­þ:§n¨fÍm’S~s¶r Žq§Sr†C¬[ÎM9¦™šGòÄëõcPLj8dâ3ÃÎ#­ÕR·`üóëëë¶?î÷ÏÒµ^R6¼ïð 9Da=–~}Ñ'Á£a:c–ŸˆÉzq÷A&4t —ª¶ècˆˆ»îû6.€ˆ‰Çíó€£õ}¿%&f¼\.{+U#¹‘°pJ™–5GuÖý®[ëÃ8ˆ$:D÷Gø?UçàÞ«xzóqÍŒ‘¯7pÊ7XGËžéI?ÿG|?åGðØÈ8a6sbî4TËG‹’‰(lS}²ËQèÓU¡Ï­þ çÆb;òô>›§WqÂoÁ│QÎÌ¡ljMUyðwbú1>T–µj‡¢­j5+µíD $ˆh`®”¬ Ì#¥„ÃÝ7Îæd1‚èª¦ŽˆÈ㓺RÙ·Û$„§Û-TKá(†ÖtN?þø£0£Ó?|ÿÓ?™ ].ׯ_¿>÷7¿ß?ýôS)õz[U›ƒop¹“RJk5ç±â²^÷»ß}úîû×û—mÛæàÛL'GEÏÁ{‘1©ÛõRžR·§ðJ²'è û–¦”Ò ¹ƒ{ ¡y2ów'F„æv¤,CK\Õº®àèÄ„ÊGf7 Køyb±¤Ã>ˆ´ÿ³«ëìù›Ž9Ûc½¡;­ó]ÍðXÞøØðÉz×Ù á˜SRÍÙð^t¹*PˆZ £ñÐÙ20ÄǧëûQ’Ì ?4Àô¨ùaÄ}pw&Žór:‚@H×"`NùzûIúT¡;ç%Çã &,‹°;„»HüdYr-•jÝq— ¨Â¸ N"ô¦Y¡ER‡˜:ØR{캼™™µpßëê¡„±ñû!5WfK:ˆºf†È€q°Ú˜ÚQoaQ€(ÂNp¿ßÓ’É[Ó¼äR*1™!É1ÐZk¥„ í»œ:”›ß€m§¨7 Ï7±˜NŠ•ßž §ñã7:.Ió=OÔÓxž,r†/× `¨!')µ³#xÕ6üö†öïi ÍËèWB½_ð¦>˜ñ½ïŸƒÝWÂ@:cÇ›ì¥ѾïZ!5mfæfß}øÈ,¿úáû}Û£Ÿ¯ªi]>~øTkUq¥fnnM²€"ÌÙB ú±HGFì"af¦`<ç%<¼ &ak¶ä¬ÚJ) ]í²ßáëzÉ9-yùüúE$1Òã¾ýøãsÎÛ¾ã¶í)IJIÕ¨5}}}u‡R­éº^L[ΚVfBtf1ƒP‹}<?þ9ì¨`TÃ:ªC" ÂxJ)‰„Ò*3·VRkjÖ%½b Ör–JŸYThÑ”Ržn·¿øÝ_~øðòúúºí›»5BÄœsÏm‰ÌuRã{I8yÔß}u©>G è,Ô‡4û¢êÁÆ2Î*ŸÁ=2ìÅgBF2+†IýA3[–E›"š.Ô'“0¦€óíCäçH”—…“¨ ^–›6«M›Zp=cüAI«J"o¬]RîÞ¡³Z% $pŒÖÊ«63pa bŸÌ&dTWv%&Ppu A°6œ‰‰0 !%NÍ-fŒ¢CJäÈÈÁ-%âZKt–…ÍÜYˆÂ'/<¦ˆ³™2#1©¶²í‡x©……L›Ö½Ä:‰¡8ÿïƒ1£hA>ïÆânîŠÀñ¤{‹†k˜M"ULå‚¸á›æÏÑ$q¢Ïÿ)IÏ qœ¯Ô‹âñ;SÄ|&/,yGb¢h³ “«7BÒnOèˆ Èè€8ðqˆi´Gb Ó”êMüpqLù>¡šRV¤È,}™¿kmw·`Ë;¦´\/ÈÜ´J5uôuYÜ¡}ùòåÏþüÏàÇŸ⼬nª­Á²Ö¶;Úõv­¥"Òz¹¹ "ár¹6–œÒeYž’¬ v(!ûJœˆ/† Y²°­$\örÊn®µ5-ĨÝ=©:  0[m9çÖJiõþx%¤%%mÙÑ­µ¶,‹5'BfV ‘–f^¿ÿáÓëý3º1a«ÅÌšÖ6Øè¦FÇîZÊVëRò·ë±£µàY8I¯fp¯uð®G†ØTCV!ÒÌéwAß v±ÝX’¤aßöRë^KSSÓð»ˆ|ŸbjÝQ[厀MRcT3Sƒˆ‚Wù€¬—˲®€¨fµµR«¹“ƒ¤rhf)' ®o.D§ÝƒæX¨ƒ¹kˆç ÑÈ'€),hüÇRmN!ç:¤³£AÃÞeð5iLÆvTœˆgdíi¦‰RÈuð˜¾@fÊÐ³ïØ‡L,,YhAàdÕOÊ;XÙËë(ž;籟 ‡%‹„DXmÕÁ™óÓ¹Z4‡/bÊ9þœF‘XÝ•ºÎ$!˜—½õC¹÷ ú¤à¡hÒ¸;sZ–¥uŸcëÔ ììc ¼¢+>Lý™C—à¼ïž‚ÍðÄÌÝöÁlx4÷ßìÈW<,Ä9§yÜX¤©R0·Ð³ÿù  ü™Wpú;Ç·ÍÕ™æÌ|ÿ”¯Ï3ฤÁÔì-F°“gÐr^„‚-ëÇq:—ÃóKX:ð×ÀïDôo¥¤¼DA¦­‰p«­ÔÒTøJÄ;'ëºQ5ƒúñ§Ÿ~FB$z<­æ.ÉÛ?ï¨,´‚Ü__9ç$ËëöÈ˺—r¹¬àæf}ô‰$9àßÿðxÜÝZÊlªM[;)'ÄW‘%/—õºmìû~Y/æ¾,¹ÔBD Žî"2¹Äâ1dKØôHåDÄݶí÷­‡¡Q­F½+ˆ]CT£/GXö-z§}fÀ§ümó†:g!žtùÞ—›èÖ\cªáça¦ºïû¶ßk«æ½’³i{%ZñddçS¤!uÊÌÝ9ef!–}Ë{9ŸðâHlÒ£ñÈÝ€hʈñÕ.îõÝ0Á,cü»‚t¼Í:ûšk¬ZûÍÛÅ÷žú2WÌédz=FcÓ{ €Ó×T‰¥|€EHAçá¡4ÐKˆÀ—Ë-æZè 0é1s“ð¼ìóYECˆ*~ÈÌ Ø8D)å¨{ –̈Ñ;(Œ”—ÕZïUø°Á 9wc’öz7Àõz‰[’„fž“˜ª6ã$ýÓ!¥”‘äz{jj˜ó"áÍ{­ew3M’%¥¼\CŸÁÔÜk)C3–À=„HC80V¸„Úbà$ÄXJ õ&G7UbŽ(°,kSžØ<çÂ߈¸ï{üÒ(ÇÓâ †H5"fZŇ\SG<ëÿ8’Ý™bdŸ…‚~×=rÎ9çÌØeÏj¨|Cb æôän#bŒMŸèó?áIøÞÇ4PÇOB“CuªÈE2>nб÷Ïú½s·„a!œÒ¦‰¡Ÿßñ€F}Æë¹dyÈÂ|C&&žnFö¾‡¿#PÐfFÏÐú–u¹”8†çÆø>¬Ç|êæš„ºÁ¹— Î<o°G  ÏqQwé­ÌqàÏá]I¬ªn˜s^– ‘¼¾¾šyÓMk¹Hâ fA"Cvè³Ë8h>ñ¦ÑÝ—uœ~Mg2uð “2!BoÁ#w½lœ%R¿Ë„(Œs}„zœcf¶‹'É¡ÎÞe" ¹A@w5G wz“›ë'bXöŒ¬xÁȈݽk§1ŽàLú¶)z|ä¹tÞ./› çó~ûkv>Îk("ûQ"D_!-€†Ñ¾Adf¤è5â°¬ ñÛ6éˆæïS†Ó˜Ø›ÆÔüÜסF Ì\k5kÑÉ'3Цsï7 "Ziá?IªŠË²\VDŒVîûž3A÷íÃŽs2;b­ ˆž^Ô ši!2ÞW;¡›‚¹Ö¦´W5!¾\.?þx·VÖõ’X^__S’²=Â.l¿@¡•ªÕ€\c†¹66³å²ŠÕ׿PJÇ”21q5%€ ¨@0hM5ç.s=)Û3Ž˜5r×( cúiß]$ÇÐußY#úÇAºrÝ ¯t›9@£±0â¬Säü|Ô‹–^SÌt9z´µºGÌ÷2ÁŒé3°P"^PÏù ÆPúð±škûœ„NŒÛÌÞŒxœV "†QïdèºÁÀŽù›£ÍÛ¹sCw¨ ê2œ6TðKm8;C¡‚‚¸¼Y|‹î>fh#;®gngò ±bï"Õ¢X‰,uÕ{fä!Pz¾ÐPÞšrZž#¯¶+"Û¶E±°meÛöà„FìkZ€QðÆX²wOQE{Š0ƒÑ˜¯S-¥¼Ëœ#jãù…Ž#Ç?7}£Ì0ç?›ËéiŒâÝX%V i€C¹ÐÌHBp±kE"q’ÇjX×ëì Êt‡‘Î÷š{M}>ø›\à]| úŸˆ>ú‘ôîOëíÝ1C¤ãÕC>å‘ ƲBˆÙà˜Cÿ‚Úº|3Ã{Ȩ×ûÔ%/Î] –Ô|Lóždˆ”–\[sc"3Ea"¹\nÈÒš¥”;^<°WU}åf>DøñÞĵª¹HR3U 'ØËzq‡mÛƒöºÝ9‰š%f&&­ªªM29@mmYfZÒ¢ÍÛ¾¤å_üåñùóç ¤”…%:A7ˆ³?ç´mûº^Ì@UM+"¶n2N‰Úb4>¬ì°7©µ&IpøÑöðê½=¼.KØik­¶œ·¦Ð ˜y°ž"ƒ†#Ǥ3Ð1 `¡`ô7­™á£©Ñ-ôð ±è,ê4PƒÙôXß …3 þ}é†R1¼É”ÏgŽ™Õó7:µöNi8=¤É !mÀ§ÑÿÙÌ+xô†!|“B!¢› #Ó(¦”L ¡¢þ·Ô]Žc2p(†ÓEÌËŽÃØ£ˆ¦Ø;ª:[ô@ÔçT˜&Ìâã!ž±/ìã¹Ü¾ëýÖÑ¡—'FbNI–Ëz½Þ.×땘ˆiß6…d$èÂÑ´îcÛ‘yþ‹<õ²ƒTÚ§Šým…9iÄêŽt–…º€Gj­Å<Ìðªª1cÛ ù3ó±.§Iwèô~6€»áÁX >].—É;wÔSw8 èBXæàô6ç…oÛùRããow>µþ “wômp?]ÏASJ“ó º<eDHÂΰQ(„x7  ˜âmU;á 9¡u¾0œNf>ÆÜ=4–ñW¿þu)E˜÷mv“°äår%ducI˜ïÉ\¢¿ 8˜!q<³”#ëÄ,ÉÆ€Òõz3wá„̰æÅÌrÎ=OäÞlh¥D†ú`B $4íûÞšF"%"’äõ¾ÅéIÌ!MXÈËjæfÚjmÖÊ^ÁT˜ÕTˆ µ&’С¹ÇC¿˜“É÷¡ÂÎ #d‘Ôû×ÝÓjm3ý73÷.¦(â4å8ÇÃñgH43soö£ãF'1"b·ò GG¹ø0вÞòî ‚Ç?%cUGöß-?‡;Í\ºG&fóƒ §pvÞ=̉Lº¡PïôrŸxwt‹A:­äΠ±°Oð~Ü®7`×\çã 6 ,6,Uh(ªŽ“5JªÐ§;d±f˜>qàfƒêI¡<˜@‡=ÃlŠÄ˘ª«¡CbÉ)­Ë¢ãÜeæÜað±uX0S­Í–årY¯ÁmÀÒÊår©ÚKÊY›qk*ÜÉ=ýá›ÇÌQ$ýÑÅ;x›ŽÛ#Ë>Å©9n‹ “ÿ—îšDŸ‰ NVýœ€è61Ú&C j‰ˆ"¬ª~ŒŒG X9Œ6ãè¨t‘x)³è×óœøš·ƒ9‚GxW.迿Шñs˜>wÙÍ;zûñÈ,ü<,z÷u]gÉ”œNPtu0$faa 2wôªjHhæ)sHšÝöüvxš¶xW„Å?å”f9çVˆ¨€á%´^®¥T&T35óhî´»»†Šï`:ÆÑnfˆ Ä6431š¶­5Z/×ÖZJÙÜ–eu³œÒýþZJùôéÓ¶=üz¹Þ· BÊÔÝ–œÂΩµæàÄ™ˆrÎUµ–êˆt¿ß‰C ÌM[gì"¡ìûîê’ÄÌ/×+„º9AØß ‘ô“_x/e]VÄÞk§=ùãбÒüx¦3YQÕu¹ RÜ&DÌ’˜å”ÚÇ¹íæ†L"’‚©ŒÃó (÷wÑæîª Çô{s½WÇêtå|žþÛÇ @ŸÄ>œÓ¯¥9¸º ñ¼ìî^DGX8³6Gù Œ˜!æö 0ìzbŒŽNa§µØíóNTˆA±?£Fs1@¸1wè Æï#¿ ÑEbÕj`§T©gîÐK.k­ÂÉ㈠{P"1%p4 ï9“É€L$Ì{)“¯É’ŸàÔߛ֦,,’X20·V‡¹=??oû=DTÔôùéú®ÖÂaZGˆ·ø0ƒçÞûþÑaF:ƈFªwz`Š/1ö‰ˆ{°ˆªºïûãñècÐý"ú¹=ÎöD3*X´//Ï®£F3BðÔdh~ªòºšªÖªsºgj^ÃpµÞ˃³3(Œ"&~@ÒoãàyC|Ü#À¿™ÿ|Ê9Ùs99=½0ç½ãC,}3-¡ÜRBf3mªŒVËN,ˆ°^Ö}Ûá󛞲·}*ЦˆxNEû)+€’ÓO?ý\kuðëåRʾæò5U­HJ f‰)ð–™QÖZüåö´•~©µúL¹Ýn¯¯3kÚ–%—½¦”rb3ßö=ƒª-)gIæf¥ìL¸m›$vð”SPK£æ¸]¯ÌüòòòÛßþö?ÿ „Hj ˆÑò2E&ÎY^^žK-8œ»¯ËµÖ«_rº¬5Càç?ÿüeÉIU )Iª­šZʉOÃ3ä¡“°ä¼€ƒ© ‹Hº^oû¾÷…0ç¼.K,õ1Ãpp™âa çPæO)圙S Õú.3¡Ó¬71 m‡3†™µ6›oއ¹NÎ5ÄÑäGD?RàCÍ ûjáðoè2m£dïƒû¹Öñcö¢/ÕwgÌHè¾ îqn7ž@ºâ¤4ó9gsÈýí2Ža:3ûæˆ,ÞR¦àØÁ•Σ™Ü¶k­Ý½ïÄÔäõú±ÇPÀîSJPÛž×µ5%&k-”2EZ3,Ûã•ÜÀ=¬lƒu»—½jÕ>#e@€Œ@6„H¢·åC†¦ÄœZ £HYÖlÚ–%'¹4µf jˆÄÄZ£MÑÀµ[ƒº1af¦à“õxK0°õ²>¶OzªúúúUÍɱÛÆtñD`ôxÑA[+ƒº`ªuÀ-ÚsðÎßïOk® <ªÇ Öü×Yî"“c7ÅqDë]¾7CL§ÐùÞ9äIGš@„,⥖f:Ž`Ö®¡H¤ˆ.s6w­ÌÈ5Ib„ºomßÁ4»šÈª¡ÍM†Œˆì@®Nt8¸#¢«]/—²÷ñà $3ÇmNènÍjN¹6Óê±¾%åœòâw–½Øu½rè{Z(¨ìa»ˆÐ´šÕèS9¸ ´R?|xþüå³pZr@7#¡ûã5¥­È^î÷{k- ªÅe“”"—w”õåÇHO <(Ø?þ,ëZöBÂÇãr»,iÅP($KKÊ˺×RŠŠäëåyßJ+%X///ÖÔ͈xß¶%/­U"N)—º›Û¶ï9/±Á£hH”(†¯'I®×ëíéÚöýÃËËÏ_>q'@°ÇvWWdœ´^·Ž¶Ú˜ðW¿þ¾”â`áÙf¦¥ìjőռ–ˆ.—KDØœ³í¡GÖ9ÆÊ Ž@ß\è*Ðj•!g†§Ñ¤ž àÍ{H!6c$•ƒ<ãë+–ºšÆxÊŒÑÝ.4á|p.<; ’º³$’ðµb3_×ÕC‡ ¿¶j¦“N®‘¯º#ºyAôZ÷àD5ã!tkˆÁ‹UÕRöeÉÑ\™ÚmAÀmMÁª5•Ñ€"÷^j47'Jyu D–´´ª,ÉŽDÊÍz ¹¹`w¹ab‚,u“zäËí#SæIO)F*9ØZçLÿmd÷š Ž0G³*œ_ÑáØ÷€8¯×uY¹µ‚èm:á 3‘ª;Z¬GŒÜÃ$‰jkµ.Ë. c ß+Ë"îc¤£Œ¼—£ˆ$)¹Š„O©£3‰03 ¹™µZkHÈâ§jÑw ô\›q«ÕÌžnÏ’HJ$âà1PjYוÃÀºÖ Õ];ïÜ´èþUÐGE¿?==¡{J²½>Ððr]Ílß÷(“±«´—"’®—õååÅÝU-fK­¦–$==?íûV÷²ôQÏžÀ¦”˜(:=///Û¶].—”’ª>°ÿî»ï~úùç(΂ü³®KšB›t¡Ý ü眾¾~E¤ç§9çÈøàr¹vT—PDB³¬«´3z6ŒéG‚|ÈCMóÅ3iPRÍЀIDATñæÎ¢!ê2Ë‘cÓ ò±Z×HƒàüŸQÖLÀ$²f[¡ËåFLiøLÎß´ÍLÕ 7Ρ¸“s¨kdÇnž$ §”RÔ££)% NÙZ×5>,‹LîC‡¤ÀšVÓ "©WäŽD3§Z•˜CÊm²º'[§pìlñËì½ìùëÀ×§Oxæ"„ cŒ²D+ ´’Õšy ӣ܎÷s€“:³QX`Pk-ƃ²20D]— ¥”Ëzì„% Ó¾ï,ôòò¼Ý¿~ýòSN©¶]Pì9„™GRìÁÄÜm/»™ím.Çò†ÕÙ&Ñ­¿…ðŠ<ÅòÞVk©ß=ìÈÚXøfŽé›~êìpþRʱæ-&ƒoq·ó)ÔŠpžÄƒéP<‰Ïj¦y]SJy¯íßü›ó‡?üþÇú'r×¶‹Èþx¬—>Ü«J ˜‘EÉÌÍ,1‹¤p£’$)‰ª2Q”bQF!õÿ}üø1>RÓv¹>u3@!N)3K´}Ü͵µÖT‘1“¦ ˆÅÔÜ¡5M’LmY—(ÎjiHtß6fµ”xà—ë%çÜZKYT[thZUèO˜FS@‘ä‘§(Ø» pi{uµ>ý€×õ–$݆’A4ÎyÉyýøáƒ™o÷Gmeß‹#‰#ªêÓÓS)…M\.—Çã‘—<£¶ÖšæœŸžž¶m3³m C>NÄáQÇA7‡AÔQhf“é”’8PJI$|xˆYAD®—Ëý뫹>??YÌ/ëe/ÅÌm˜wžÁÜ:}/uõð86ÎDõ·KüÍ:÷vÑsñˆ¼Hs†¦‹½Ç—Ž”ëŒq£w>ÃWχƒÏ  ÂaodòBDóÍåDd÷ðO§ðQÕËåì&åž/óÌtYrXW«¶ø2kª‘ã†Ä9ÈÌ’RrCXÖ5>β,DDHƒu#UmèÑvwubÎ9D®ÌÚÚ<ü8-7÷0jî­I`™Aµ †;"2%l­¶ÖBQÝÃ’ô‘ÏÏB~ÞcN!úµI|¿½^Ö”—RФ%ÆpkÕe]›êöú*Â)'pO9Yó¯cb 3úñ”¶ûÛPèÎ'â×<‡N±>6?‚»â\çÎg7jê‰Á éBü|šŠHI„¼Ÿ¬ü^h^¶½iŸ’ôÓÏ'^‰ƒÓ4þw:jH&+ÃÚ°ÿë‘õÀÑ=çqY–ÿñßþû« º µ¦Ëº"¥TKI9w™š“ôv‘Ä¥¨HúðáÃ^vƒŽ8Œx`q @tÿr/µä”TURÞ¶ˆ.·Ûãþ8v>`Tß®Z[ô w«†WQ"â°Ä‹+3'+cY$Iér¹,ËšDö²mÛFD˲¤”n·Ûý~ßË&1ÚA«Ó…tZ«€ÄÜ]+P2áº,×ûº¬(”¾|ùámÉÉ£RÐêe/µ´ðáÄBbêM­´ºo5çô›ßüæv¹~üðq]SÓÞ¢7f¾\.·Û-I2·Ú꾦 "⃲5¨XŽY!ÔRÜŒ'š» Ró²ïµ´ÛõúñÇœ( j­Çˆèñx@ìa€¡AÔ›p‚ò}Œ¼&³QÿÍ¥;%PàÔ±t?žúmÁ§8Ù9L|ŸÆAuÞ… ZŸÐ§þ@#ß³ñFîŠ~€æa0;Ø©´39ƒƒþqüÉíö<¥Röœ<Í真ŸŸGûBUÔ=,s“ ƒ_ŽØš±Èíé)bôËË Ä^mY–àà rΠCmU˜…É"ËdBhõë—/—Ë•™/Ëå‡~x~þP·Â)´Ñë(Ʊµ¶,«ôØî÷¢MDRN$RÊãñúj­^Ö˜XÍ›*†ó\©Ûc»oÚjSmÚ\»+á’R·ü_'¥EqP3%Fy;¢ÓO]ÐÂ1ŒÕÜÌDä§Ÿ~ÚËFD­Ôžü–c0 :"ç1ø †ú9‘0#@N)ºq!nÃcÓŽþ“ÏM5#ûiw Ìü¦o¬òŒਦãE­£õ‡–xŸˆîŠ 0(D>¨Ì!êévÀS@&s$0‚›ˆ;¨Z)µ5]×%ú%á"’#}_׋HRíBÃfš* ’±Âæ˜HÝÔÍ5”/$´×u­µÖRf›ÚУpBD`–ßüæ·O·§ûãQje {n#<¤ ùrûDÝŠ ´/"”YWe‹# ͈X(Ì«OZð‹ÞØ©øK ªA†…èB8¨$FIIdÛ÷%/yY¿¾Þ?}ÿý÷ßýßÝñßþ?ÿí—¯?_Ö\ö-¥œó¢j3gîÍÙ¦n­§Û½ô8¸†Œ]?=}HÇ•waþØwd ƒ¶G&zŸÎëÂ+8–y˜x¬ˆwÙ÷™-ð.¬¡œÞÄú#I?~x ûh£^yòû{{à 'áu9õúQRÖV£'Á„Ûãnª—ëÅÝ›µëíöضPZ¯­!!ôê…‘(*ܦ’’jûúúÀ–ÑZ%¥éÆ£žŒÃÍ–œMUk»¿Þµ) .9ušœýùˆå  “F^"9;`ÊÒT³ä‡s÷ëõ©µˆj&’Zk¦ÎÌLjYœîA2Ù÷f´MéNufBÇ$$W4WkˆÎ—ëZkÍyaâÿö¿ý¿ýÉŸüÉ¿ýþ­µ!µ”"œù7¿ùÍëׯfŠèÍôr¹¤%›Ù^êm]î÷;! 18üæ7¿¹==}ùü¥$õxh¬2€3v¡¨œ³~ õQ·]i{qßb‘,’‚ÊI„jZên¨AùãŒì­l{«õr½æœ·mëR'ò"ô ”S21Ø™ÔõÖÃ×Ôæo}FŒSúf¿œ âþÆ/èü…³GóüÛ~$ŸôM\ÝÌèxꓲctr]‚õI#aäHHÐõabV‰õ—óR‹2§u]Zkv:kK)û¾«éËë`vÓˆ(Éâ¡f`ê²k«µÕAðkÇݺ‹–»;vº—˜æÐZýüúõþzoÚLu¯¥µÆxPÌy½~ìuVIÍ€hK¤”4ä4{²f®Í¢Ñ0DÔºÆãqÄǹLfs‡B¼…ˆ‹;dÉKÎe+뺖ÖþÃÿçùïÿûÿÇ×ûO—uo­•Röûý‘sFèmbæÚ¥ÕÞµ"©^²3™1Ù¨ìL'ÄvZ»»GGh]¤£°‹™±NVÞ‚0œ¾èÝqñÍ!ìZ ·)˜¢Q;<«ïÎׯCX·}iœ§ûÞÅ÷c£ÍTÍÌB\ñ8cb2‰ J€²o)'ÞÊæÌ²mØ'­Õ^®ºGO?¦Ÿz(ô ´¶o«Ga6³sã""ÁÉY›™˜3óõr•” †9‡D "r”IL»½rŒ ¦$-,p ,æ«™™˜HDú¨ª"áÉàÚL8™z’ èÑ’ Ë\ÂÎU¸Á¸hµZS·V¶;˜>¶×Rʺ^™åþxüáŸþðûßÿþóçÏí5÷ÚJÙÛÓÓÓ¶í"r¿€u]Ì€×VÔ=/ÉZ{¾Ý^žžqÙ —}+®¢ejCLDˆ1bGm­­ëJ€A¬L)å¼,Ëân¥”¬<(qӖºìñ¸GÛšFv4fF)%GÂ\{xÂR"|C6|ÓÑéŒû™©Œ1Ÿ7¿ŽË3zƒ¡{°$í° ÎàÛåoŸQ Ÿ†íßG†ˆSÌSŠ™`æ§§§ÛíæîEkoˆ3èÑLTÊíSÒ¦>|÷_ÿ×ÿ—íñ¸ß¥µ‘z®ëjÞºý"öN@áGáÈ´b“5«µíaVUêVÛ®h¦nÚâ;n²ä×Çë¶m’$ç< ‡§ç¸œn±u;+“ÍT‘H$-Ë¢j,‰IˆX­FJC\î{€»–_i€‘bAaA 8ÈE2µ¦´äÖ9Q-Eð?þíÿRµh«µ>´>BÑ—e 6ƒwýE“‰uœè®ˆÈ“÷=üÛZk]ù+Dï²§åÄâG¦€f®®'(0ò‚îô}ÐòÏ+ÍÕÝæ4Ú ¢Soó- sÞ>5ó&÷ÿ “g.ÕÓ1ð6¾ÇûÆoÛx5³Y]Žç‹½;óéãÇRk-%¥¤6#  Ik­5E "—›³$¦äªêêH L{Ù—®­"RK òÌ\ÓÐ5`JKV5 xÔ½ÕŠÄH(”¼ ão ‰ÁU­ÖB„˲tÑWÅ85kêæ=ñËËKªU˜¯—«™ÝnO­é?ü0&þ©Ö’sÞ·­gC“ 2µæ ÑT…9ä½Â­,¥¼í[Ù[Jé?ÿç¿û§?ü¡¶Vëw µzY¯ù—ùúzÿòåKJ²ï3‹· þ´ä\œÒýõÕÕ˜åëýõóçÏ˺¾¾~€eYžnOy=÷m·ÇŽ?ÖRc‚áûï¿zzÚ÷íë×/fŒ û¸ Rä§Z÷’—¼,«{¨œ¶m{tçy îÅfá¡wæg‹vÀspŸ‘:õÁç rá î8 ðwçÄ\ù3íEœfI¯fü s¿€RQú86uo€ ŠÎÎ".yu÷XK!ˆRkݶmªÿ1%& 4ÖLÁºF¼™­ëåv{Þ¶RJýÃþqÛ6ºêñÁC`¼÷QGƒœL}-Ó8™ÅÝÍÕ­²p8Ôqp³tl#¸ªV­Ì"’T[­ $Œg;XæÎ’oË’C/»i^?ƒ;‚©iLN¹+‚1±›©+ ± Sb`r"¤Zš›O77U‘  ±K¼-1²w^5cá8S„ª¢7ôêY!PkV­ Û”;w÷°™½o3 ñwŒœ:Ô»B³GµC„¦CýwûD›P`w Ýžb‡Ka¨E˜ƒ9ºÓP>PÕ9=†oVðY'o"6€“‡5À,«#èm˜´ë:é´ÏÚ˜ã8ሓˆYZkˆ´®—”rT]Dò('¦Öš0-’¬Ut5ð$lÃE:®ŸPÜ8%N!€dMëÓõ©–b nÄ”`Ū걻¦¸¶UpÐ,RkåeåœKm¼dC $GNëíùv{.µ"P«ÅÔbF¯Õ=/y4£¨Õma¶VµÖD¬{Ͳ¸úåå»Òh)Å®× "Ô½ ɲ®///÷××ÇãQw·’ËãuÍ™Ã?—É¡«{&d‡0Û´1Ä_H’š5f–ETÕA²[­Å¬º›Zý»ßÿgumZàeY…ØZÓ/ÕÚ¬jcIû^o/צ Ð÷W`B&äVtI9âjÓšòRZ]RFÄOŸ¾{½¿îûݬixIn™žŸž÷m¯µ†Îx_lèæVµº1—ÒÂߊˆ~õ«_ï{ w÷1ÿ¼Wmn1b ÕÑ~<9‚19²þ_HÒ™9*øst>ÿÚÛD~$¶Cö4è›}@ÌòãÃv †÷1“å8X7PÏ€Á£³JÊkŒ A¨2¨¶Ô‹ˆY̼”ÝÌ>þ9œO„D—|Y/U3W·f I²¤žªK$bAskáU°G`Èjч@2 p05óÂÜ›Ä=‘Tm­01!2#!¸º+²¸5mn†D‰¿ûþ7q['U1¨Çs@Ö~I/ø`ÍXʉ˜o·ë¾ïÐJ%À”¤wnYÆyïîFÈól“{T­Ûµè€I›±Sçz0×xÜ`ƒ¨F<¾òÀÌ GvpßH9#¾3ûŤ;ÎÒ™œ›gûy?/èØ«3טAjÑ|óŽ·=²­q7ÞBù#øŸÆÇúps$¡Á 3?^ï9ç¿þë¿þ‡ø‡¡Æ§sг¬KbR¤‡€Ðj3c–ؘÑÇ#¢ œÆ{…¤¦9/iYTM›åœ—œY8%I)o{‘”ö#™÷íA„,|(„››9=^_—u•Ä)åÛÓÓ—Ï_?|øÐà¶,Ï//Ÿ^__ ]S–R¶ÐÕØ¶­Ö@1ÞÍòÚÝJ{&ÕAÜËžÒbfÂI›¦ìfuÄœ3‹˜¹3cÐÛ…eyºw¬ÒTë´bé­¨žævÙK ·pÁžõ%´Zö²•LfÚšzÓËåâî?þø£™}÷ÝÇýQJ)_¿~)¥C¬sPS×¹³¨‹–X4NSJ£ËF·Ûív»íû>;Š3@÷¢ö$:?ÈćRÐÈE:í¿ÁCNݦ£„u÷X¶ßþþywQÓ êü“3L><1Ô8B˜ßx@ž¾Â*ýMí1fzùÖ_3N)š0iW±nðû•B jÛUU˜:Yæmo-&'phmYSÕîëc½Âè×Ü=ZaÒ#:uÞóÜ2c¸ ÃUDøÃ‡_ikA6è»Q-ˆPÝÝêm?°ßë1°ð!! §s¢0.p÷ Ù(ÀÐü'4ðø_‡ÖÀm¨êXpDO=>v |\ð‘Ïå‡vͼò¹¸Os´@ß-¬ùó©vþá›Ó(N¤cŽô™Î×{äïß÷Y‡âé¢|8hÅà OËúPÅy;3‚!Á÷KGÑñýÈ ¥!SIOOOüã­Êô&‹Ÿc¢au³îºGD!€¡Ôà"ÉÝÍ:òx\ %wgIsþBU…EµE Õ˜’6%ÇRê’Ô4XÆ9g&@Äß}¸ßïß}ú®”š—ÕÔn/þßü7ÿ׿ù?þëÿÿúwÛöªº%æRöbꦥîàÊDQð ˆ~yŽLÄIâÚrεT"ZÖåñx0SÈS b3WÕ½”$òñãÇÇýÇ1º9€;NØL›†çEÿbäafBÛ¾—Z«V$2Õƒm1‹»#†°lÄGÄ×ׯ—Ë…[=4”ÖuÙ¶ ¢«4OÓaY7ñÕ >~PÚúé':xÃÃ,-ÖíÐõœiÇ9Õ›+yά¾yߊ*y0¸îà|9p×ÓÊ“¤¨ ¿ÐsX§9{ |DˆÈ‡mËyúäøóÑ›<÷ß» D¼ Dª«ãé¦n®}qÆ(@€¦DëN¼>wo­‰ð¸¤cî$ºÅ 0Xìqg£#2[ëîNÄn½k‡¡vN¶khQ]!s^ž»Ô©ª£q3O©ËªÙ ‡Æ³PЙMûØbÌKië^DÄÕ’ˆ›MIÞèîœÆúÏâ$0× z€: λhf'¨õõ盟ÖÇîG>MÜÏôÄáŠ{|¨øúňÿîw¾ ýã_ÏÙÄ)vÓ›#áÝ~è) L¸ÆPð¼'Þþ„‘G•òža9_ß&”q”Çà]äªî ªK^Üí÷¿ÿ‡éÇ6‚;ÙåpcQ5'èõÛ¨TÌLrŸß©µÍ­>ª‡¡ OsE)室fjMk3µèÞ/Ëêî ÜJaÆRvÕ4>‘®õ±ïÛ²,¯÷×Hœµ©™7mÅÒÇ·ûë¿ûwÿ“°ª"Ïy©VÝ´1# aËGð2‹¾ý^öe¹4Õõ²:À¿þ×ÿçü§¤óºà„œsN)}xyùÓ?ýÍßÿ§¿wˆàNjš!¥E¬ÚVdDXN9Ãé‹ ÎŹ&[)K޾ŸѾ—Nz#Ú¶Çã¾u¸š!¥¤¥"b­U]gÑ9"`(z ê­U3I(è¶«~ o‘·-ÐsõyÞ)Ð)1ï—ÎùĹØþo3žA™x³Ñ&)ãÔ::JdfN)÷6YN>7ÎøÞr‚OOÍuê2ú©‘MËYßpd*×ÇÇ*¸€8aC¶^úÌjL)œ€·€¹ú‡%aJ{νNAXĈE.¯›w¨Ã%ªÁW= Ì7S;zqдEÕIH“@mf”Ⱥ’¤”¢¾h{uè¥G›Y0MWïóºÉFÀè›c¬B<•! ~:Àá˜äG˜C™FÕ9õÇacçsëÍÁþ ó.Œ¾ûçàô‡çaoªÎq“-КfÆq¼ãñ=‘udަÊÝù°Þ2…Ýøóo3ÔRpÌGàÕ¦“ÿI÷Y9)R°c |t½ |Êφ/c`ADÇI@Í<¯‹+P–uY÷mcf‘ÔÔXR­m]WSM"æ/—ë‡Ü=øû¡ðxhÌC¦”[«>|,VÿÃø÷ÿéoÿçÇã3¡‚;"ÕªÀˆ¦ª-¯1¹{eN- qœyUÛÓõéñxˆäÈã~ÿûß×Vÿê¯þêçÏŸ—eQ÷²×XÙ¯¯_þðÿdªLìÞ•›ˆPÕzûgx$ # sNiø¹™†#U¬ÕuY°• Çܬ…ü€5K"1µÆÜ)Ée½š·Ú xSU]–%n‘ꦔf~ÓZÂàž›ª›ºz«5æíƒÅ8«@b„·ñìÜßmÞIj€o’¶qÀ9Hý‚pÈû#ÄÏ0Î)7£Û5“– 1zïx>¦$Fß›§‹9çFMcp§×y85 …óQ,wë#RˆÌQl„`C¼81"Pt¼£B dfˆ#™Æ¯4‚^œÎñqxØÐÉ‘Q™BF6ç6çåòd¦ˆ ‰ÑQM<¥Ô-%Tw •%ˆÙMèúÅHd­á ä–RB¯‡˜©_Ù” èÓ¥†Øü‘ô€jîSUÜÂ\;:]Ø55#v¹£OUœw°Ì»ôa~Á7¹ó ÖçcþΘIy³ ߥ'ß÷þ;ßpÛÏGH¿ŸçÌÒãݹò怂±:×eÿMS‘ûÔ„‰FLïÇÌ8¥å) €·ZÖËÚZÌMô'ŽDî8u#j­AN»AOwáÐ>=¶±[Ÿgå`¼iÎ9kSa‰ ù*á$¢æNî·k­Á¡”£Áç½\/S*rß·%/ª¶\1 2·RëÁkÓR´ÇðÍñ~ö“㕈±k®õ.tm·ÛÓ¾ïAî2SsûñÇûr¦œ2†¢/#vÙ“ð@˜Ž€ý‰ºdYÖ¼2¦Ëra¤Öö$ݨ՗ç¦í9˶í¡áé\ÔË’÷}CÄu]ýý̼ïû¾ïÇýr[£VÀaY™ ‚GÁÝ ÖJB³€ØU4±±rÞ-ÈS áqO„ÃTíM)‰ƒ~~Šõ6^ó¯çJß û8+ïH<ÆŽFDꚈZí)ó4]8]Ã8œìݶŸ¼E¦™$Š Hppo ï7¡kÍûÔdŽ+4×H§‰iÎIµÖ–%ŸËĦEU1\ÞI‹Œ¯Aú8ŽUÕ?œÆÑ!<Û…¸°·x”%­‘aæáwëxá¡•僋ˆ ¹ZØ­2ï-š¹ÍÂùu¨ÌAÏl'ì„TOçƒ`Ì…Ã|ž›á ;ž?ïžîÈ;Ì}vÞ¡›Àl”#BäYß"3ïÖÜ9:Ÿƒõ;’ú±‚ñN‹yµ0ñµÙGÀãéíláéX‰Ÿã¹%…ˆæQ§ÇÈYÎcç °ÙmŽç2ÛÎÞëʸšŽ¹3%"nÃR‡[«f*œ Œ^µ9’p8± Á ‘òe5S VÙ¾ïªÊn^[[–µÖ’rªe7«ZKÌUÀ°î "ü«~øòõëõzÝ÷}Y–î·ÇÃZ«ZÊ#'qðÚôv»ÕºGW7x×e!B[Ü[S5eæ´,1B•T-e1×u]ÍZ­Ñ²³ÖömCð8W¢{ÖZ£á ) DªG´ÈrY.)%&”//¦m¯›™ q+•‰Z­fÍ àBdÚ´UƒÐïë,LDµS]×µíÅ̾~ýòU·Û-%ê=ê®fg°j7¤‘u]Dxºu#bØ-ô»42î_Ì6Æ–9~ßÞïÖÿÜ>D¿5û5ãøÁu惈§VÓ4aG¤ÐªÍ–8þOo=â‰÷aÌ@X¼”ÖQ÷ô_=d©Þ$ŽF$ª:ÎsNa!¢”S Šû¾«Úå²€™km­UµFÚðK½=ïV>æ„;—Qaêk€Óˆ–Ö!lœ‘%-ø%„ÄáÃÛˇ‘ßŪ¶”R–.éš%$S m¦u½´ÖX$DØ­K9dÓÃUß=õþÁp¨×†ô£ZÀ‘Cña,ŸY/yèùRê§è¸ø !ŸÙ‰³uLrÎç7«Ôs ?§ãoÏÊ)ÁyŸ¼ÀùÅG ãÔ9DÊà­mØùFMW„˜Ûg˜ z§MÅ~ ™ŽpT¼¦ˆÔÇÃâ›RfÐ<-ýã–|MI<à#3wErY.ApŽ×Œ4ÂÌÁz] ®aFÄ9¯1oÇ(AÉ9ãTp®¥¤Ä¥ì)IÕŠHá @D¢öÓO?ÒëëçÐ_¬¥.— ¬aâ îHΜÄÔÐMˆi<å$pZTÕÜ£·îžSÒæRÚËöÛßþæçŸê¸"Šè’rJbµ…w3 ÔZ“$5ëÙ¥98$‘çëó§OŸ>|ø (­ÖVìùåù~Ý·{Ù÷¼äR¶œ—p¿I)‘kK)L9š0qÔø9çûã¥ìÂüݡ/6³Ðæó˜˜ ê"Æ ÖZ‘zƽ å÷88mð¦p°¿bãLw³sÀ}—GÛ›aèo3÷£ãÅ#ÚN¤àŸ ës¡Nï‡Hý€oŠƒXªÖ:ÓÀü­xjôW¹ï#:q+É›Æ 1ɲ,q—ÜÝ¡ó$B!dB&‘¤mà1³ÔÚ˜C4X픚¤”ï÷{TŸáôBÓ;Ö'cÒhFGf‹sœ¬"’%1{yŠ 2X´ùÆÓ’oA׎zÊÜÁƒxÈáž=´{B^®;‡rgÜ¡º-ëÚLÜ—e]óÒj#&UÍ9­K6UpI¦š’z­íz½•V‘èr½îeGIèîä®­ˆ°6'b‡À¼8LpƒjÌNýw=Kêb:ÑärÏ``æa9[¶Ð•f;~Ôc:¡E¶9²†s\>‚óðü éòóêÇ!:6'iÏkw$?1Ð-ßA™çŒi-ÆÂ1y«µ¦œÝ•™S( yè ³DI¤A:?Fšޱ!#*¦p¢ŠÎÕ ª1 °†0µÞ‰uDÕ¸ÿ9¥ÞÀ57'U £]Q`dJ"É£ÊEF"’äHŠÈ‰k+BÄ„uÛ“$5— ú$bjÂlµ)Irð”—6·”5»\××ÇWdÏË‚ˆµ”œ$æ4‰X‚cÌ’Ì»yHêó;ÕÍ9‰äE‹¥$µÖûý~½^J©¡"•Öírë©Úжjöt½€°01_Ö‹©‘ÃírACÆôòôbj¥ì¯_¾lÛ«jùòùÇZ¾,+1 8 »p¬ÿ0åHV˜… Z«êµ”‡¶F, QñÅDAk5,¨ <¯I4d’L$ÒÞ÷h5"† ¸GÄB·l»scÖ‡1G^1©ßÙÇONÝÎ^1Ï&Í8\Cq­§³'4¹ó63•Y°¶Ö|$g3RFR $&:\RÀP c'–§ëEâ‚¡pçÁc"sp`¤%'¯eoµ0akÇI€ˆs‹ŒªæîËš—u Ç$gf$&f«µ”²8°7«É1 £Zs0d$ Ìc$ ÀÔ X1áÊ}œÀ$I„ó‘ÍkÌ£ S"æ¦{IÙr dýœ?‡"a¿…ÒhOyàì‘7mû¾0Lˆ’„úÕfál‹i/%Ä.Ûà´,K.¥sÝKØžzÙÛ(ñ`|ø`CÝš¦‹DnˆÇ#¨Dºª ˆ·ËÓ§OŸ˜åq„‡T«{ÎùrY)\GÚ 9çßýùŸÿøã­5ŽéæœrT«îV[E (›:#Á²¤X_æL¢ak­¶AFçÏGýéûó²œiÌW̱»ñWãç3)±Óþ›¯ùž™6_ÐN|ǹ¬ß½ç=5Ö¬Øw=„”5'cˆ¡ƒ³§µ5Ó¸¾c¿Ð‰ªÚg<€¦Ýbð]á2{¹­šÄZ ŒQ=ôWÓŽwDõ-´;šeCŒmÊëòè N´9¥œsFîØI'‰RJ)‹$Þ 0¥ãžÑ`N£; ‡ „š2}‡yS×Ùò  ;§œ9œk^ï 8 º¹j”íª*Òf–R®”ŸöÃ󋈸) hUD\–e«…N¿Ãx0€75×{PìˆÈæ '›®±xŽÎ'p!ÀNòŒ–ø0™ouÊëßDvÓ}ñàz§= Nîìï¢ÿùs½MÞ¶Šé|²æDÒÙ²ãÃØT³Àt+†®»o ò0ÂýØtÞT,8lûèpTEKÊ±ÂÆGî×Û\›i©5Ô‘™RZ̼—¥ª—Ë•“SÓ5û²¬M¬ëÚT qIiÛC[5!" «Ù?ýÄB­UD\UM´ ^ÂãñÈ9Ň ÿ €P·îv9eÜYCó°óž£vnÖj+×Û%¥\JeD*¥JÎÚ´ÔæjS ë²º›$™,fþôéÓ¯~õ«ç§û^î÷û’bøòågBøÝïþüçŸ~Ž'ÌLTµEÛóÏþ7¿ý駃 Ì„¥ì^[ )ióŽªÆú ¿”ÖJÎÒZÛËÃÁf÷h5;Ë‚Â`Fà?ƒþÍq§óIÿníÍÔaÅŽ+¼ îs³¼_Õ§æÐÔ—›°á9aŸ—MDjFßúHqIçs‹™ÁàÝŽ@€:šhíÄiPÑB½N¨è+¡‹àø¶‘Æ”¢Ÿ •©Ö ç0о#ˆ¦â Å5W°C3jžeCH¼«Æô{Œ?!!GP3í”0pt³P(é €åò4ÌÁC鯗K²SãaSWMC4òÙjMÕl½¬ëraæ}ß ä®ªßx!$1Yíf|}½G°¸Ýžj«$œ—ÅÌÞÌ;Ì‚<Ɖß@ýIÌH=×ëˆã#céËhF||÷¦çµ~ÎÜŽ5ôîRñOzOެá–þ»_ßwºKø¬#缄2®y>' ÓÜå>Úüç§:xŒÝ:Ò½û[Îùá9mà0'¿#׉})Ìhnjê)-D2bvs$v@‘ H„œXšjðó9×ËÅÍõ p¸LÄäÚõr‰õ½^/îXZK9[ÛM8´R½ËšN¢÷û]U㩊È㱩ªE›&K}ç”2"mÛ][;*9pa‘5‰ä%×Új­¡2ÆÌUkSu€eÉ‘"¹-nN©ÆV$¢RÊãu+¥˜Ùãñõñx½Ý®ÏOO¯¯_^¿¼ö} ‚1¯î_¿~ #@U%¦ÿî.爮n1 Ã`µ¬ë*‰ÆÙŒfo{r Ï\ä™MÇò{»­šòLG:ß3à¶"2 b!Í&Ö9ž£ó±%FfÓÐûôËißœ_qPßl.`B~þðòî¸êŨ¾k˜Ç¸äicM"Ã<æ[ÌsQ8Á «M:&…7µT<¸Ç¾ÝK˜O);!XèßE0·óƒxóñ‰¢7L{rˆ“ˆ ᜜mëîÚ¬ÖJ̃=™ør{™Í‡ñšý`GBƒ)å;>êp ~w¶7PfÎiÁÁi­­lû~YWUe郌*ƒM[äb¦­µº® @ˆéPJér½ýÅ_ü®5ݶGO²h àŒ¸å“Ä ØÍ9»yøéq¾I{möÞ¼—™of8ûbxÿ·½·ÓmÌÏçÜ/Lmô—ùçæ¡ÞJ0}ß¿=TpäñårD;g(󈲷,£ãÇüÞùR±³ƒßø÷Lˆ†÷ ñ?òn]fç—'b'dæ¹I%,ÄDRUeÆ”‚âr¾_ôi/;Bg_ÔÖ@rºß7u{yy1€V6èb#€…£$f¦æ†LÏ·'Uµ¦&3Ã$ÐÜB l‰ðÐÓÔsw÷ëõ¶=‰S^ÖpØ÷ýùÇ`S8`-ÕÕÝ`YVâ0·Á”—ÔMÔ`ÛvWÿúõ«»®KÊ9ÕZËþض ãšgéîuíçÏ?G™ö›H¤¦KεV5Sè§Ñ Î,f™Y0Ü6ú¡²w%ƒÐž¡º=ïA0›ÿ΅磄oˆaî:È<_Æø÷yÂè]ˆ÷óN±_úÔ[†ÓÎÅ“ÜÀ¼€ót…y…–ò\Ï3@½qC âøM¼Öî%↓Æs¾->”Ï£l÷Ž[ˆÚœ}¤„8Z éz½†oô6‰h0xÜ—dÂΈÀHG„›:q"fG$è>SÞÛ£}šÁN·‘—ÛsP^æM'"iM(†¢“°r°ÌlÀ¦")iÓqã,¥|½^?}úJ)NnÖ31K­5r³Z  i­!Å`ª` ­mûÆ,_¾|ŽZ;’ê±XÞ‚àçïGND†@o ÷7ܘw™»÷ Çàòø8éçN8f£ƒ†³õo3£w¿€ü9ï¢oçüezhà Ò²dÕ¦Úb¶N#»ßlovìøfŽtǶ?ƒªÇzà˜˜`bFDî `4“Ï"B Z+x' ¸cJY˜ÒßüŸþæëëׯ¯_—eY–¬ªÛãq»Ý‚­4fP¡5e!s¯µ.ëZjQuɉˆ÷]«"Ĥ‰Æýº®­i´ÖËz¿ß#cj¥säa¤«D|ÐZûðü¦ÃxÔ4®M]MR'æ´^Vl¯÷Ç+ «6abŠÎ±#T5d/c³Õ²_¯$/û–R2³VÇÄ_x´F*Áªz½ÞÌœYRÊû^b ©"AkeŠ3s07c}íe€Ð5Dà°ÐŠRã[YgÂÀà§ú\œÝ4Öûäùñ¿Óòñ1Cƒ"ð.ˆÇó1ˆ owëymûøåÈ5ÆËÎýÕ¡×w[øÍKõb€œ¸”}’eÏ[ORekaˆã]&tŽÃ¹ŒGÄ?€ã °E’š’šÅ¬IH-yŸË £»}†Q ¨„)¥œsÙwëˆVTáîê -¬÷U»Ì³C7\@îœ/è§Ž™ò²,ëº^.—:ØÌfÆëí%¸ŒÖ[ܼfq°ttÏ €‰»L·Ää0ýf‘0(ÀÀãÚýqß¶‡ ™6ž«ØëDdâÖj©›9^Ö_>|df5{}}-¥¦$Ó'åÝ,¢±ôÓ–ƒzA$ŒÜÝ9è-Tr„­É.?EØÀ3g\ë‹ïíìÆ9ÃËý]p‡þkþë±ÄñýŸàÛÑêwÿ:aD 9—Rö÷¬Í‘qPlƒášÐ‘§éѶ0<Ïï{ÞºUÝÔ Ù­Ÿ]zèmí 8 sb " ‰,f¨àÿñoÿcSÍËbªµ–>XÓ²IiÜX÷Î4%D &5}z~BâmÛžn/D”sneÇ.Wf˜w{zN’¶V"º5S-5çhˆÄâ]r¦ûýËã±µÚ‘HzÀ"øðü²¤}/¦Êµ–œƒ^Z…ðGI9·Ú˜yY–x^Ä#t`Aw+û΂­*…a˜—RG2脨Í©Õ6¨ÖAîÔÕæ1¨AÄZ›™¯ëEµ™ºZ B'ˆäÁ] ok›Õ6`À3PãÖÇÖO¥g—ßOq‘4þ™Ãc°'OøþÛ¥ûr‰z%l¤àÈÇû7ÝeôØS“ ?* ï0·÷ìžDRÎKtAX)%ó¥3#”0˜‡˜¢žª5G53*$bfÀ ˆcL„xWÐóí!!‰ÌÓܪµî©!,á¡»{)u`q7M­ª)zLuÆèuPÐáœòÂ}³:1/)“0„Üz?ƒÆHd]°ßÃË„CqœnÖé + O“³ fÚ"cÍ2Ÿ.¸'‘uYYrv03m¥ÆW7S¼\.¥¶ð‚S­Bt¹®¿þá×­–ÇVJ)yYÔ!-©î»º¾Ñ±¡›ƒÕ?Óê©ÍÔÓXö>Ýi‰B §¢Ë[X&ÓzpG ¢ÄrNèm¬?/Ç)ör>H~q•¿IFÆ3ÿ5.à]>¯A:—ö¬A^þç^˜ÂÏ|‡N©@D˲ÌÍÈÀ·ïkf$9ÈNjÊDAœ¶ q´LJ²™‡´²™!2 IJÅÌ 8‘¹AɵeI÷û=¥äNf*"&JFw¿^¯¥Ôœó§Oßþüy@¼,‹š±PmÍÜa{Ýš6ß¶MRz~~ÞïÄ]ÄFy¸G–ÝZq‡$i¨ÖûË/Ë5¥eß* ¶Ö¶}[×TkqS•”bš/"Tm-’Ìácç)ò;ó%˾ï)ɺf1õ%g7øøá%¥Tk‰!Áy²>¶ír¹äœï÷{L”Rˆ($ˆ‰9®ˆÑ!¥£'qñ§í{ø«ŒGƒG2ë}TEg𚦳ßÖw §óŸÃâgŠÇ¾°áwVk õm¢ç…äCxww¯µêp™¯?ƒûç„ &Œ¦":ñü ñ;gü¼B Î¶Œ—ÑÚXÒh¨2FàÀ™ü÷#ãFâH1©ûbw¡ ÐÖÜl {ÔuA´¨¶°xŒÏ¥æ­5ˆ-ù©NqT°6Î,Šƒ*É*’ŒÀ ÌÕMyŒ¤¶Úæ(8 D±”òx<‚ʈ™S~Ê)›5'P0\¯7$k®jf·ëÈ[crk*LèîœRÊ«ìEw…ç矾ÿ˜î_¥vda,ûýÜ í1óý~'rÕ¶,‹:PÊ«äEÜÛõvݶ⦄jVˆ—e5óP4İ95jz[uÈ–¶ŠáÇÔ /—[±”Ÿkë Eİ“>àš~úÃ,·¡ •Sý“i/â޹Ûð›5¼¥pÑ;x—4½ èç/€¸ªFU–DKØ"“ª{@úñËs½2“0%áªH€Ôªö)(â`#±šIJH¼^.!ƒ‡Äqˆ¤V xw¾¬Öÿ/aÿö$I²æ‡aßÍ="³ªº§gæÌÙݳì. ¸ˆzÉHðQ0½ÉðHÊ@镸FÁ$%3°Å^°ç>3Ý]•áßEŸ»GTõ€,Û=ÖÓ•áþùwù]L[•R…¶]‰YÖ •"K!!!o†Â¤ûVKݶ­+€a€%u‰AîÚ–åš#¯2ÀµÍÓ÷Õ,Ì ³̾÷²\ð¿øÅËË‹ˆhÛ¡¸“h Ä3À)Ôk] 7"¨·²™ÓQÇ©©Ì,Dàæn<cÌÌȽ8 ¯à:ž™'=D Ôc!Æâ¦aa‘mTJ%d4H`` ±¤+‡…‡Ã$úya !3‰©›93µÖÂ"ËÐp_)ÂÚvBh¶³”ZVĉ‚9¶{˳&ÂÜÕ¬A¸0RAsOáßîÿ• Œ²¬ ëÃ;ÂòüòÖvÕæfH DÓë¹T "Éiyïw<^’gž¾Eµ®ËŠ„dªˆQëm×û}+EªÔn“ÑÒ"YÔÔ¥€Gk{Ó­í;BÔ¥ €ª^®Û¾Ç€û`(#÷îx—0&r÷„'ò^éYŽØÓ9Mê‡×2íHáû ªÔ›Ä,É5©ÍÚ,îø~pˆŽüJÓ0šàÓ¥,kÄ““øÛ  ¯…hfJß[p¤Exú9ïWÿSø™YŸžs¡¾öO‚|qz³óñ0¿W~ûQÞ¾Fª¡ÏVkÿÏ¡=Ï&KénJK½D¸™8wçhêH ,‘­qÄ|.™Ÿ6ÝTw@¡YUsSm×ëÕÝÍÂ<˜¥®arÓpÐÔ8ßïÌ´Ýw,¥¤Ve ŸP‘ :¶ÝuoÞ4¡`ç¡ß°‡î½ ˆR–e͆CÛ5s@sݶm©EXLU «š‡µ]«”R“’cÑõG©˜öE›]šÑg‹¶ï¦ZKy¸^÷½™jÓöòò9Y ™÷BÜ_¶ëúð?üÿê‡ßþîùåóõryyù æFÐõÄÐÔÙÔK)///ˆøþÝ×m7"qw"Ö¦¥ˆªe­sF’¼*…ÝkYÆBæ¿Ú‘ÚÖ&H‘q½\NøëA;kâ© ÞO”ìqÓ P……wpž}l`Jñ‹ežõ÷±¦1â›ãheuÚç¨>öw7sÄÞG¦lHwÌe•z®<1Yµ”íd]ÔZX°»R÷ÂZk6|_Ï?%a5}²e€‘VÏ]èÉ>|õkÜï÷‡‡…Ú«¨2öø$ˆyGRÆ´OÉÉu}rÖö¼½ù¨ö}‹®•ˆ À,DjÚXîÖ& *ö½!àõrÙöû¾o®æ®áa¦º7 Œ¹™®ë¥Ö%‘Ýz-+ÓèF\dɆ!%>/È¡{âœ}çp9+¾¾æ,°cýåä‰ÈÏð–Û‚Ó`úDÊ€7M·‰Ìé)ÿÿÊåmp ›,g7|þâË7ÌM2?+^¨N;œl¼ÆÃÌÍœþ/)ú= Á’na]Ð|kÖíS  ‡G)Å=Ø< וZ’`—51ÔÚYlL]ŸÞ=äB\– £ÆDÄ *Âðôø¨ªˆ¼,ëÃÃ# ‹î-"­‘ZâR˜¨Ô’\ô\of.,‘%g†WS&$¡áÚˆ-wk-ƒxsO;\H[ŒëõAD=ÍÒJwÿôéS]j˜fîª ݹÇZËýÆ]1 R¨ –º.+Q÷ØÝî÷ÌgÃ=1þ„”Ì÷¸¿Ü¾ùúÛ,ãó›_·m×1Vq×ð¤J0skmY.¥Ôu}X׋ˆÔÈúÆ4•EF[_1r.GTí©–Rî÷{:‰§Í@u ÿ`"ZÙó­SÜ锊ׂ-™Q"wõ‘ψ˜B„G; •mü5!Ã:ž?+Àa8YŸ6B²ÁqaùŠ1"KÃ5€Þ~  ¢±‰g èDæª6…êòªDdL~G‡Å[O VÑL[kiíK$ᎀÌTˆˆ³cbÙ¶¹d"ÂÌ¡%ǽ󉰋'ztÒoRfO8ÛTIËcàÐoLæq&ÃÌ L^¯,B(fÁHe©Ãƒ µµí~×¶G÷Ãe©Â44 q­õå¾&.R]V)%UH¸™vK"5c¢R+s¹¬×PmL)ÞN”§›9 29L|tÏèû“ö ”4CfbADs·ŒÎ)YŒ4ðÝ©|yÌKuùzúOÿ¶ ÿ¦'ó“™û›ãOïí±<†_¶e&†}‚T66fƒrhÔÀ—Лù6i'P|:~‰Hªª’˜*KMkSä”IHb@0d&¡¥,Ú’I„µ.ŽHµH)€ŽêÁ$Ýð¡í;ˆTY2MsgbÇ$Üw•Úâ½ÄJ šIz˜9#1Š 3³° 7…!¦!"Ùòö™Þžz=øžœžÎ­;_$«-ÏZúO÷ÌG–kØ÷ë—é|ßÉ_dåp~C€‰ÊŸoÐýÉÞú×ñ§ß“XTÕÌ ‰h]׺¬û¾åÒ'bUËûLÄȈD»jJ8—º„ôœ( ç—!BI©5c©€@ëõš„6Ý›”D ,Ï÷{.UÓF˺äÀkÛ¶°"™Þï÷øáv») =W`$ê:Ö|Þ³5Ê£µÖZ qŸà¦ä´¦÷Ô´iÛwL’³C¸#‚ˆ¡«éÞòžæH9à~»`-Ù·lÉuÑÖ‰EÂÝ|H‘Zª©73mDøòò¬ªR¥ŸÄç •”‹ˆ}߈ø»ŸýüŸÿóÿözyü›¿ù©F+£ÂèÑgö¦Î?¹–eéÑÙ¬ Ö¾Ílp"J¦û¯ä Í5.2*­#Ff¶4¶Ç+¾¯u¹íw3[—Õ´Àý¾åœKŠ˜5ÂXj½^/á‘£ìËrñð”p!¢"²,ËÃõrÛ·Ü&éÀn¦ªHÑ›© ÐÉ8–˜µ.éÌnc@€j- 0ÂJ©j„¨m€kj¿©ˆ`îU "ªYviE¤° b!$³–¬&R2~¿Ý/—KÊ=6Ó½íÿÙþŸ¥á”‡§Bçî9ŠH©ußwflmˆ"¥”åoþæo?~ü}ê½{÷´ÝoK­ÚZF”sÎÞËJ"áTöæ®óžzÂÞ7¢÷ò$ÄQé<¡“æâ, O[#r!"b€ÃðVÌ–IZÀ!0áóôfÜËP™—ß!ž,ãÓ¹°¸wýjuí^Þc`†C7mîñSÉ'Sò˜Ió8Ɇ—²\.—R Sp3SfªE€@Í÷}ÇðRJ)KþoEJPW9‰žõ#q©UÕ±”ú/ÿå¿ü7ÿæß|úø±”ÒlïsJÓŽøèÍ™W€ºIÚʶOfŽ|yxG„¥Ôìò$‰Yšµe¹äµ K·Ìö0©¥03¸oÛ}Û6WKU¹07wBŽ€¶74k»U"‘a|WF·mÍ‘ØÌ‘‚ÌJ)Ž”J~È HOO·ûF‡éö«îƒˆ¤Lt”·07ÝgpÍ'=)§çà~n¹œ2gIÞ78Ÿóïãõ…ýDtF<ÑEbº¡ÏDÿ§þ離'D&"¶‚ovÈqm²Ü©¦ó<@a©9l 373´ÀÑK%d¡Tb´ð€è:ãÌ$b…kbFÈSÔ\¤$øÊÌk]‰‹Üî÷@ ·‡Ç+`Œ"ˆ®×‡û~Ó¶ £©¦%·š!Pv×J)ÙCØ÷MM“‚f-µÀò›û@}@¶Øò^2q_‰å †>vKh¬#a濪J]àÓ»ÍÀå²¾¼¼¸5¸ïÈžô²,¹º. ‹,µ2•\û+3" K].êžêÍjúpy0S7Ë'Sªüæûßiš»qè=O\–eÛ·m»E„bbóøÝoó»ßý–º™¯k}yyf掀>{Ìr:è, u)Å»©C" 2'ƒÙÞÍà)€<‡“Ù®`‡¥Ù6„NoÎ=ã‰ÏP;ÒùAÏdÿ„hœ³®¹ùb u¤$’ÕS£wºñdÄL}î5 öfÚkC{gÀ,!Â"òÕW_™7 ÷0@À˲^ÖkbŠ-uØíÃܳ5¿ÔI„ëõñÛo¿­µ>??ßn·¤çZ.Dî±·¶®—ç—gù›¿ùëí~‹ðÔëOj\„çÉž³–tUêƒÕcؽv™¸hS·Øö=§M-ë‘’ÌÚm»·¶›*3 šªå§º3Ò²,©cf„´^.¥w ‘Z%S§LçU5)æ¥ @Dݘ6F‚NŠŠ9 s•mßQJu@ˆ(µzDÛÛz½Ü^^j­ ’™3ÛÛŠuU×䞺;FdÁ”m²™t»Æ£‰ñ*Jžð¡ác:pÐúÏ32å·¥SÅúíõóñ{.&ðÈÌGf}üý«Îé‘=ÁX÷1Lqg‚öæbæß‰<«l=-u"Ço¹zJéf7àùölfD`¦"%Wšª…J­„ ffmDLq.’é˾7©rßî±ow5[ê²7@æu©·Û‹™e^¥@B¼ú°„0}ËADhìùyOŠðTÏi ¨2"²‘$vû9ðàî.9É擄Äo¥ÔŸ}ómk÷Á0‘’Aí¾m²ˆa¡š3êž^Y,Ëòõ×_ߟŸ ‘¥²Èí~@",R.ëz»Ý.×k 7kOïÞ}úü˜(À‰ÙÃR;>ª÷ûýz½lû c©k6jÜÌ]‘ÀÝn·›ª¦ÝÄ\o’ŒÒáöžä¯çççRdß÷¸aÁFΓ–™Hõ·ê§ûl; \üH>ð ÷…ìéìXÝÍõ˜¯œØFˆHIó˜xй’³`NŒÐRkîRdRÎ^eîg¦Ugöô®‹ù¾ïI¹ˆˆ‡ÇËó§Ï ýLMïTÕfL¬®Ô'¸n¦{Kà“˜îÌbæªÖvýñÇ÷ûír¹Àð$ìÅùë²ìmc)ÌòüüœçkÄ@‡ÍÐé;HœN¤s97“U±bÖP550$ F Å 33Ý!\¸:˜˜=¼ýyGªºon@(u‘Z=@[ŽA"=>)L-<˜8m̸£ BD Ø‘œ ýçÿèþðÃLU¸º!)jšEîÞv oièJQ˜‰0‹ifª…¶ÛÒ0.5W P bdgÄE Bœˆ¢Wà“¼Y âI£‘LÜåÚO¾H§9ÐÛŸ D£ÞŒ7×ÚoÉ+¡çH©Pa tÉ) @ɤœ6"@Gá§í„;"†°ˆTv£rä I²G~¯ÊÂà{ ¦§÷O˺˜{k»š8&ÈÁ½hÓËêµf—ËEƒ¹˜åðPX¾ûî>}ú èÂYÒHÄ\_>ÿ âfNˆµ.—åÈ`ÞXÀ¶M˜¶m#b¬KðüzK­D˜Hÿìx˜»êŽUŠ™…«“;ôÜαþ”,ŠTwØ·ÍÌÐ!Ô½YD‹©¢pa@2Ëz@°OŸ>¶Ö24Ôºª*3U‘ìêîû^J}÷î}öŽ8é©¥”ÏŸ?É;_øö_þ_þåÿüÿù7HÄÄ+‹7â˲ºùËç—*•¢ íì­™%l7ÜôöòŒ·í…ˆš 뮵–ÂÐÀ[kfnÑ­‚ÀÁÔ2Ê&=1Oü¿ø‹(’ß÷{’eúì"\Š,΀ìæà=Ú¢$‹Ë¬e”¼o(F$„aö6Ø•3pt 1`7› –K‡MŠ?3!¸)„%[ÈÃÜuÛî„S“5Ž2–HŠºo=ðp5d  ´pdÂÛ}Sפ13 m»Z psµ05SóììaÆ\™¸À¶ïÈX×âáf Å4É\Amßk)®M«H¦ $!¸êFèL ªL¼ Àº¬"Òš%»*‘‘­í#F.Ø«%¦!…(ÌÛtÖò˜¤'Ë.&U€e] I îaѵ†ó5ù¼§ÞEfLŒ˜&lˆ,EÀ<×ëÇ~$„"âÚ= “÷îLœŠ.q6e"Ž"ëÔˆ˜åö«÷¬ñº„Ï©#ùeh&æ\™«OåèyÊ›j÷ü3–˜¢­_¼à=Çý3vÅ)ŠÏ÷9»Ç@jº+ã{o2Q’/û¤i©Ç|&À2C/"»êH{ûà$§ëz¹ß·õ²–Zï÷;‹\.ë¾·*µì÷;"škNqRÌ]=‘kmjàððøp{~I½¥œë´ÖÒüÚl4ëú˜„3‘ôðR«0ß·{ÞÒ}Û:\ÕÝÕÒ¡" '@Nh]?ÞÒ-õ[0éüéÐÄ£ã\º¹`r¡ÂÙØÍ¹ 1¦,©ª=<<`§2í°ï»©]¯Wˆ¸o·ï~öÝ–òÅÄæÚT‰åóç—ßýîw­µZÄÂp'…EÄG/"©•ùdͬé–<^D¼^¯æÚZs3!Y–Zëj{„ŠÁ¬¿&bïXQÃQïåeË©Àض0µs1à°sÊëI.ßmU#¢RªÚÞv’E8Dhã _ðyc¾IÀOð›‰ÿ«m’ÄÑ׿;s—ƒõ2R™4˜Î˜ƒWC™/vÒ†#¦Y6ÍZ™1ҪЭ› ¿¾¼l‹'Ö¾Sˆú`ÑœºTtô9x&""…Ýck[j'´ý‘ z‘ÔåBDÞݦ’B˜ÕG¸ê>â˜3—…ˆ²,EÄdç‹DŽGòûœ¤½K¦Ph¡f†1ءªªMs¤2A.,8•ÿ³×c¿SFGBtÓZëår¹\.I¼F¤ûýÖIxîŒaàžr˜ó>e£%×â¹-~dÒÀ|ôÝú£Î¿ìwjÎVIŸ—Žã@FmØWÇAXý‰Þ:œà•3¸Ñ|?^6?w^ç|óñçñâc?œŽ|õ¶½åÝûõƒº2 6 vDdáìñ?%·(!g)m<àvÛ™I›fÊ ÂM•93TiÚ±T¢mÛÖõ²µ†À²,Â5¶û}xz´­ ³¶ ",:ÝFUIØrÂÁÂ>öR@xø¾m—ËeȘí{©¬Öú.gʆ;1¥lÃiäÐïªC(åÈ¡Ïô:6œh«3èd‡zô+j‡—ËU¤ì÷ír¹Nù„l|øðáÓ§OîÎ$û¾c1ÒÏmkÛï~ûv÷DåS— ë{'¨pXþ»M5c†Ñn,Ï,ëºPkІ,‡«ª‡¤÷$áôa€@à›Mà ½½ÄDd–zV'ÅŒöºèÛÜÀq:4ˆO,$xM+™q ÓEòõ´ÿü§¶Ûë}ñv˼ÙGç˜Ð7ôˆæ£§Ÿ1ŠGRÇõÌ”ÎÜÁû3‚“~äø<•N%1Uu7Æ4:Ï‹S±fÞÚþüüüøôðçñ—×ßüæ×½É”2Ž\êzyÌNAJ&äçš5ÕvÆÏ—õ"RŠ”œÂ!0 uõÁˆþœ²1H Ùã€À ’Dæ# ¹¹y¸ˆˆðh0 ÖÐ|Èg?Úf("ÂÒÙjÈ‚u½ï·Ûó­íömŸ È#B}Œ|îîaóá½%‹N埌¼}t£¯žÊ5w@µè`Tâéxˆ1—|}œüôOÖçh~þù2ÜŸÏŒÌÝ&¤çü¦óà5snŽ™¤ôîÔˆdPäæûýÂÇ„µËnF,–朘€_D3»^Ü£‘"=¯VUà’BKm¿/Ë¢f)ëØ ~þ¿§f.×ÇpÛî¸K¡~L{B ©)ᇥ”DÆÈfa¸ÝnfͶERB&“J" Ç`3ýò2³ª×Z¹”„-Sª«GâÂ’i#Ew¹„Î È0'¥D\¥$üã믿Nï§Öì¦nv»Ý–Z÷í¾H½,+ïº_.—ûýF„\Ê~¿1b¸Q„°xø®-Ü<Ì ˜ÙµE¸ƒ#ã9ªvM=ì-ÉjVYƒdÛ&J0‹WœóÃ\A—ËŠª NÓË)Ò2§5K§™"2Móî’ʾÌzÉ=¶ M%²/–<¼2 x½~°~¾Âù(Ï[æ\µŸƒÝÌÒhdŸóœ˜©'#‘D$”q嘀UNõú™‰>³sOñ q˜qÏža‡>Fb]¡…Ÿ_^ˆðñññ¾ïÿñ?þÝ?|/Â<¼›ˆÈ<¹”Ú<„`oÑi®ˆ–°+g©+³±÷†#’[PrQfÅŠ$ˆh½1BRDD*¨Ë+c­qÚyyf<Ïç·Þ#çðĘyݶMµµ=ò¼+St}Z÷!Kƒÿ`Ó d2Ö¾ îôz®x ¹\f1ä@fp‡ÁÈ›:¬fÈòO!sŸðëƒçÍ2ÿò·^eî‰tú┚R®Yä ¨À!ŽÐFŒ)œ‰ƒ<8n—gáçʦKb•Ñ£ Ka’G0$ÂÍr¾(̼$±SM‘ˆ¹äøèýûoZ³Ëõݾkxìm×¶#F4E‚Ö¶R "¨ªA—R ,¥fywäõDn¾,åg_sß¶ˆPSLÓz„žd% #×v>ÉŠ@¢Ëå²,+¦568¤²ñ‘ˆÍàØCï¡”’öö×ËÓsuÛ¶P»¬+!Óóí岬nÆD® áûmk¡OOOŸ_ž!¢A€¥.®êfR ÔÌ}×–ŒGî0SœyRòº±Ã$@ÕJ)IRÝ3ûQŽ¥I%q÷UútwÌúã è¸Ã1ú±^Gu7ð~£~fn78á ¾dÖ}™ÄÄdºÎ:{òKÌNº?ß„µ¼ÉßÏAÿM|Ï@CeÁ»Íç’¨G!Áœ%F˜+"ªkþjV±óhÉ0}ìÍÙßìbwí½Û7Åp—nÎV¢™‘HI\}JøæWW3@d7P3Djfà:ιÀeN¶óŸ˜¤fcÈÕ1ˆFåÕ‡ ˆÐšsÂËåJDáî³T¯©¹Ø½”S8¢·“pÂû²«€„ýÙŽéy””²¸7 ¦ˆ`‘ÑΡp¢µžÄl'Úu´¯âÍžkúX%ð?#”r`ãwãD @êKçL§<ÿ{®³¬WÎgÏO®ò8µfH²ösgb\Îõ&À«fÇf@¦r:ÔÏ0‡p JŸšWêÁÔkØ‘0æA+ÄLîøp½„¹»ýü»ïš6Dúðõ×f`„$Âû¾_¯@ˆÀæ±ïv]žßÿ³öOý÷¿ o`ž$)¯µ¡G¸A­Õs$k¸KT¥LYF"ðwïÞ}xÿÕívÛ¶­HMtJå$Y¤ðó.LŽq­Õ=çT$"@Éh Ð@@7Ï9v*ša·lî÷½;À¾íYL˜YéZÿp»ÝÂÝ…¹J}¼>`Ä»÷OÛ¾»YS­µlÛv]×ÄBñhÑ!æás é9| cX÷É猈ašÔ‘‚p’˜˜Obôc¨¤Uqì…™‰%¬å·K÷²~ :VR&WÂÝqÈ6ÁX23¬ŸÃÓpüHó¶ÃÖëô£øQ˜Æ²ˆ™â©uøgKRøO'àÇ*= g¿É,Þ¼òËSèŠâ)»á“)ðÁÝ»gW.2Fêòrg˜=XWíÊJÇÔ »jfÔÐ×P)¥í;bˆÈý~¿ÝÛmO[WSKî{8¹"—ÿÝ÷ßÿßÿÕÿíÿù?þ?>þq{yAJ¤iª} 1›û²^Õ,ÓóÔªF€®¨GT—¥Þ·ív»}úøQUk)\dFfÏ,¢#Ùc¶ef-Ÿ™©»·¦»)H˜E9Ζø„XíXo`’ìœZ‚UõÔH s+Eêe}÷ôNÛ¾Ô…®—KÛ÷˲¶M÷}cÆe]u¿×Ruo@2(XB晸ˆ¨µÂÛÉ4ÍÝ!0©')‘Ý S7·Q­b,s¸RËZëâÓÐ#¿Ö(ðsŒÜtãdË3£j%`"ðfÊŒ,4HKÔq3É͑èÀ©ÁøfÛ"¼NðGrFÕ7 ƒs¶t†)CÐè*çx‰(R¹çm))“˜+D4Ónƒ‚>¿]¦²]>¬7:o`žµó"óSzÛ½ÿ+GDJ`RŸ"²ŽÖÁÔÍ.!'=P%Ž¢'Xy„Ä[;­yÀŠ "Ë²Ž‡Ú „7¬@ d@† f¶ÖxK)"]€­m3ÿÄÓàt¶¢ÎÁ™[S¢øQó¦ÉXÛ‰‰„‚‹p)ê¶7EÆäÞ6Ub΢fDÙmÏ z>xÃzÇ@õÈm‡Œ Œ&ø™h0s4šHêˆáãÌÜOòˆõ_âZæS?ЉÓxçMûèÍo}ù&ÝÄk ^óœ€8.r¾úõñFSZ¨!Ð9FÑÛJH©PxPøl~,yvÍȉÁÌ{k"¼oÛȹ2‡ÁÞ‚p·u]Í\ŠB! )Ëßÿí/ÿú¯ÿÿÿ·ÿËÇïǂʌŽà®@PJÑf\j ÔR<!ÜTˆó O4·jK!³¶íëºB„AÚ»{$”8õ^²nÀÛ#›¹Ýîe]j­nÞL£ˆ(È3‡ >,pgÓ9‘_c€‚nFé)ŠhƒÃÌ/÷¤l¦y!ö¦x»Ý²›„ˆª{Æ®Z*!¥öKbqp 3[k)œÇ"H`æS‡]XÜ™¦V¥ˆ—¦©ñ;ö|*%Ha*¥ÔÖ4õ$RVÌýŒÁÀ¶Máû7 ò~.ÖzŽÑ‘u³Œýžªœý=s>12÷s,>U¨çh~ìS×û4˜e–™u™Y  ì|Lf9ÿqB¤!Æçïºwc&¢ ! ªCH:¿lö̉(Mf¾Ü³%º;ÆìŒCD0PŽs&¤ÖQE–çJ†‘ Ð¥”ݬ–’Äì삺¥I¤™žDu8û‰y-¥2¯nAÄBáNHÀ\$q(¿úê륮,µïÖÐÂÜÚæBb-ÂWp #ÂZHw‘Èim6¯‡bˆT!‘f¶«-ëº^3½pqUG$NžZ®„¥. ‡z)"è q` HWÜ —ÂæFÌÚS²Èï«÷U‚*SŒ·g Ù­¹šéÔ˜vè}(Ÿê<§¦P¾f¯ð”½ 8u‰¤”Ê$Cãqöä›Dz3Ò¬1ûU'Œ1)ÁñDÈY‡Íà ÿ`¾VÀ¾Ü‰%Õ½bð®FµëCÛ™S›Þ`jmBê·f"&DR³@*¥\/@q·_½7ÍÙ¨»íû½°qxüê·¿þ«ÿðWÛv'aµæÜHØÔÜIJYUÕÁ«Ô*¤û-ÂuÛÒe8Å‚0ÜÛ}Yj3 &ìˆ^BPwdâZ°×³n¦ÁUx‘ –u][kNHœTJ£°œ›"Ýà ­‡©Öêû®I¥7W5µE #¹!ªm¡—eMí´E}xxxÿÕû—ûÝ#4âéñ©í{!"fNv5¡Ãº¬ª){S”Rûc<¢R˜T÷ˆŽ8Lçô<"¬™š ‡ykû¥^.×Ëõzùôü)eÕsé«Z¸âðE·¤%ÀÄ`Ì´¯§hCœ«Ÿ1"°oÚ¡¢LŒÐ±Î†*ݧ)ãˆ/]q6„R„eë¬Óžz9•¹­ÍL~ÆÓQ!ô&0 ³TóÂ~»Ý¹¬u¹l»«yY ¤B‹"¡p}zz½>í92ÀÖv dd¬iž&r \Ab$†AÀTœ…ƒÉ˜9µÌ¢™ç J1Uýg?ûù²\L558³GÏ¥3cí¤Ô„ˆeÉ쮃JHÙáÖvrLjȗ§¯º§_D*µ!šÖ²Dö9GC¹µ ˆ»—^¦¡µ.N‘QÊFW'k N p Ô]Ö#µ.ªºm›»#¥¤‘y`7™Í!̘§} ¡º½]™h„H5ÑQ7!‰OðoL6iG ÆO¦¯çþú³N=ýÞh™¿rþßS¥9‚uïâx¼àÍߨHvÁŒÍ ƒÒ›,4ðì0ÁÅ1ΛiÉ]0/Ï9ø¢~4Ëȃ÷È´^Ö§wïn·{'.Xg‡§‚…Aätî~¿‹Nl­1Õ*ÈÐͼµ]‹”RÊý¶sºÜï·gÀëõ’¦Öôë^žŸb]–eY²˜DIý¯sÝ“Ÿ1N­êt¥Ë{“¹[)¥²¤ `óÕ€@(9KCFÄ>·ê™cÈPeÉükÛîÉ஘o›ñ|»µÖHÒÒÀ÷msU¸o”R4îˆ)„iæˆMÕT³Ã^¶mëÞ~øîñ‰î·; axlû†ˆ—õ’¢@ïÞ¿€ç—ç¼I©e¶®k&˜j ÝzçŒtNÿðÔ~TÓ9ƒ9P‰@Ì$­?ÀÐO?™þ§lxŸð#≠ä÷UkfÎQ_QLOTä™;åëÝuYV)‹”5"¾úú«ËzÙÚž’Yw™yKÉ,@3céý$ê’±úf`—ßà€¹{ù{†M{S£'Œ8O©¦-Û.뺑›æI ÚT57"S©µÖZ„ó(íÑ•AdóÔ1;TØDDtT† ýá…9¤¯«¨j ™áẺ; 2£™‡ÔZ¼r×¶íÉaFT¤'§î¦ªªißKá*Å\#(+$0CJºö8‡È¼šûTÞ÷”Øp ×“ÉÓÈ$_ô¿ á¶í¥”¤ƒve×9æöƒ»vT^=+yÕÛúòÏo~â‹àˆ¿ÇÔhÄ}Bê“ç/ÞeŒ+Îá>ß¼*{0§FÓì;<",MÂÓ“únFŽAã ŒÇìv\óÜá½e‡Läî­Ù¾ë&#åÄ ™‘\s¯–¤JºûÃÃÓ®þòüƒˆ°\D𾿴v'dGD`&aVBȸç®VSÑhËÊ™â»ï¾ûüñÓ¶mwÛQÑÝ×u¶7@:Ž“œØÝï/NiÚ©ª ("Ú"F( ó¾T‚ǂȜÁ¦Î>!Ñ2Q hÏÔÀLc¹ˆG˜ôƒ½™y1FDq×RJŠg¦ p­ë¾&³¡†ˆèÀ€ŒÔ"˜@Xf/…¹¼|þô'ô‹ï¿ÿ—ËM÷][Fê šî¿úÕ¯’XŸ¥}߸ϓÞd$ÈDA³4ÃhBàÏæ£-96Nñ` šLn9Œ“¬ä ÍOü»Î÷æ~ʪÿâl ÿp Bz³CGòÌr¿ß—õár¹|øêµíã§À, #Yĵ®(ˆHÂî–)¥¸/€0t,w'hžfr,t&å4ÑÝIø²<<=½O{¼¬kû^<"îC”`ÂçsÏ}ŽÐÉ}‰ s‘Ù¾"àº>xz ¤N1 I¶œDÊår M„ºy³}Ûî©Ódfº·}kZÊZJ)©< ,aL)¢Þ ˆl‡åРʵ.KjÓpè#ŽS8ŒY6„[ͼ;,Ç“•¯:™žF1³œA0ËÃÃÃýv÷a¢â‡}]¾qÆø2s‡Ó°t&çT=:hü'¢üiá´Ò/“Ž7¿‚¨•x5Uœž«-˜¸ó¹xäãá|hËä 4sOüb¤-²aïI ÿã›ŒÝ›ÐæÞ¸df€¦:EP³ayè¡·ænˆ˺`fž0 Dx¿?oû­µ½ÔŽ¥,eYDävßK©`VŠ„îû†ˆDÌÄ¿ÿýï^>^/iR±d7öv»ÁŽ?¦ÚÚfááA‚Ôkµ˜Rîf&BëRM[Þè,ìfUãþÀ¤Îfà[Š0K ˜zx§..3¡äô•{û»ˆ»åùÝÚ–š9Ü[Ò©pEYt—¥tD„cÖ¥aNÍÙîЦaq]Ö0øêñýRäùóg'Ô¶³°0‡{kMU™¸5‘L•Â=O»œ¾ÒèûíªÄ}€¨3)ÈÅ|ÖL?àÅè‘ këÑýd?óîÙ¼FDáŠÝ ;ÊGõ؃où³˜£¯ Çó#¸{D­ qY—ËÇçÏ?üþûÏÏŸ÷Öˆ)+#‘, S‰y_GëŸJß;jï-VPfþú5oßfú3回{ýŒ8íÎNxi2©˜fÅÚ{;]”±·S`|—NDŠˆ|Bé4öÌjs{¢o`š½×¡Ê}&•8êS6}R˜8}9@JQõûäD(À“f6H ˆ÷}#aAt7m»ÛÀ/ ™ÙývK(ɶïiˆ…¥[#"D4Øç´#©FY·Í>[€gÈn­ ¥Ü1"¸^ˆCNÙºâÊàâ¬KmMÍ­»ôõIo%O(3"çÖ "ªˆ–eiM¢ím])"ˆŠ&.¢.EÕÁ<B ›ûÞZÞ UM ‚Â(‹”¼ÈZJSEÂ"¢¦)Ø™ýŠD:æ#ΰžã»ÞŸ¤ ±¯q Ó g¸u¾J_˜ÄüÈÐcN#dRÏŒJDÖu-e©µf/köTµËŠŒ–ÍÌFgâ|UDDX†«j—øNšÒº.ª¦êµ,ëå‚,´,‹Y¨3˜ ;nÌ5(]'Ù¨ÛeåÒwŸ,â¾ØzïÈÏÁ½„[kéƒTdYÖZë®û좎—tó4òv³áw9Æ@DÌ6é¡ÔÖa3óÓYʃ»ACe@p¥–›iU ̓R}¾';.R„а ‚[SÝ}ˆs"¢‡Ow³\)Yd¹Ý^î÷{Ò·òU ¾iZ D,âfÝr%o¥;¸ãyìxFPÏñ¥ªºi„«6z›–fè<(mó_OõÔ)ex/ìU;é<|yAçºõ\̹+~ù;I©™%éìÚ ½ýÝ'¤1°ì‡¯¼GäD踌Ów즺C©µÛÉÙ\‘ù‹ªV¤s*jt¦J>Pf³éͦږ¥bêüF¸…¹ ײ,Ì æºïa^„ 4bv³Üç·—{2³‡¯K½½¼ä,à«÷ï÷}g–]›q7ËNÎ:mÛ0í˜Eˆ…K)©©ª‚Ýs&q,ØÁÝn±,5_¦]ñt6p;6”™)½4Á Á¨ãŠ,7HL@äD„ŒTˆ …ópÕ@*»û²¬áPê’•1‚AlÚ 0Å2uhß÷ûÞî8tQ €/ëÃýø?þðû¿þúÃË˳C!¤ž ŸÈŒwªŠµ”"柃ØA“"2ìçò”NkÃÝfÏ}ú4$€/ýÜÆ Ï< Kú¾B 4K è⃔Ð^3ålpþààÑëU LG8èg 3{kX¤˜››îmsw!Þ¶ÛÌtå÷*RKiÖ“EHμ ©þ„8€Äð†U3Ô)ˆÌÌ]ãU“ñññ:”j€Š0‰CÜ·‰Â-²í—^€Hª0Ù‹JòZNõ‡!ÅÈ8ƒÉp û ˆëúD£ü„Ñaõ1[‹ð¶k?ÒÝ›XJÁA<>4UIÙ–t",µî­¥­+“a)…Xæ”ÏÍTÌqÌ‹»Ú—#€iJÇôéhKÀDÊtFâC!³¸ îj”«Ï"sù ädÞÓÞ4"–R—e!ÄŠ’D™‰›«EG%™‡«›uùCØ[ÓùB07èRc)~ßïŽLiCz¹\jY·ûöùÇÏÚÚzYvÝ_î÷’: ÐUï©»è”T7£!“WD”q*±³“^EÏó–$¢ Ø8&®0hY)F€Ÿ,5˜¸K±œ›~ß~ûGî¾m{¢˜<4¢›ôž!˜½1Õ|‹ÓC-O£8ò¿4lP ‹fMÍÖuýðჵ†­ÝU5Â(ÅYS»¥é>Ðä ¶ËmŒ…GÃs¼tþßü24t/ÌÚ¹k”á‘÷ýîËz!âZWIöu?’=â¦Þ5œYçÑ;gÑÀÌäT$;ïáFÔ§b¼\Þ1¥ &%ê+/£m;RS+¥x¨º;˜Z²$ñP×Ûw% UµÖ:ÄÁ“·kw_HÌÑz‹m{QÝÝ\Íö¼Yn‡mÞàa&XÄ=¸ 3„{rÊ_ÅbÌÌ=¾Xn<áe©j… °»¬}á@ý&}>¥ÕÇ@u¦½4x‰ˆÙ|êR’­ðô3—¦?ØëãÐá}}xjVÀøÎÅ=^5 ï…¹H}Ý„8­.‰Ó7£Gš)ùi˜ ]Ž€‰ÜtÛ·TnÉïׇÇûý>Ù9,JØ8×e½\¯Ùpˆ­5ÕF¸Ö"j-G ©»{¹\.×ë¾ïH¸m»0!„…»*"Šˆ†/RêR/—µÔúéÓ§")±Ý2Q‡Ñ>ê·ÌáuŠèÝL#–eq·}ßÀNë}çæÚågé­·1„ ÍÃÜòI`­õz¹ê¶#"FªUZÓ]ݰ ó¹Gľíy·K)T¸[¡©á¦MMò2ŽhÚ0ihးÔ%<©·msðt¸~zÿ´¬ë}»#bzººûËË "–ÁM}xx0÷Ô˜LgÑ1¨ìyúü€Ù†Â>Á;ô[föêÙ+8¶#Á õY謜’õ_ýWÿ{3¹½dû;™iââãèû%è~ö ºãÐa‡™rõRËÃÌ0œ…‘9ÛK­ßÿ=#²î÷lùBonò¾ïÀ}R˜Pf‚ÀQax8ØDKœŠòžKEDÅ<ê Éø¾,%rU»><”¥ªêçÏŸ¶û¶·²®ƒ ¢*5í‚_ýãç@ "¹{YjÊB‘%2~x÷NM¥È®-»=й‡ISe‚lÛÕRÐy¡î©OƒH Þ,:¸i¿¿¦f[xÃhˆÄBá¡à*Œ»ïÌDL`© “Ç1‘ $Vj!K)»6ÌN<ƒ¶F$`¡ãMmõÁÈ-„'ù¥C™†#d%cÔ#˜â( y$Ô}†’!bx½á Dœ°1Öõë³ã=CÌ+ÜzØav>TF J #ÒÒLÝ&0AùÁ'Õw8¾FRM?|óÁÃ÷¶{8¼ߘÇIÞ0ñU'È,[hA€€S,^Ý< o÷=2v˜î˲¶}/¥¨0ÐýÞÌ"D¤mÛ»µÞžŸÃݶ–J^‹ôá¸jaFˆËåz{¾£¦#®« ùøò ˜ºžj»oLdjNLM{g)3"´0µœÊ÷³™‰9%ÀT!Œ “áÈHŒâꦣä:Ì”Ó郙ҧ E åryøê݇0\J…ð———ð6ðf˜f„–õÖ"%"ö}G¢º,̘ªªRŠš½{ÿøüùSX+E®×µmwDLvn"zÍœ™«‹î­Ö"•_¶»ºŠ”Ö4lS5Ý4œÜÃT´µ›©÷¯A,Ï/·}o—õ1Ðú¬"Â0OÏ S·½ l%A'àic-L¹­9|Ó)¯ØùÌòñyûøésSõM«Ra.l­Ïêqh!øÌ’ß4ÜÀ£©5v·Z!„0"Û ÌH€÷mkíŽÔEx1ˆ¥ˆ¤owX7Ÿ(R1ÜMÃú÷NTO©rªªÑÁÍÕ»#'Žn8 6à”Äí}Pmºoa…˜Ó• ™ÂÜAJU/¥"ÒårˆR–@D¸.«ª1†¦L²ªZš†D€©æ©˜ÅšÛ˜ A‘§Q@tÁXÄÀDWÍÄÀ=u¢™EÕ»€s3ÏÓT»†¤¹Åk —ïSŠy´;J÷ æ¤ø gwïë1öéŸ{…ø&5;¸£÷‚¯Í韎™Û¹-€ÿ‰×Ÿ2#ŸçòàËŠáMKçÜtòžpö ÊCè|ÂÏo£¦­µWÉûH(Ο8/~þ=M³ªf?ÚLID¤«iÓõáÁLïŸ>q­¥ÔŸÿüçÛÞÉ’˜úîÝûD¡Üï7€Øï7’>8Ý·­®«0ײîÖR ·íɳ·¤r…íÖ ÜÍl©u½®ª¦Ú2µž–iêí„ëz-H°p*î¸þèà‡~;(ÂÁÆÝÏ!@Cúve‡T2³†ç€ƒIr2”LHDl­¹ƒªåË…! µù€Dd»vM.À"¥²¸jºTßn/_½ÿ÷ÿñïD¤T!Dm ™‘I2ÚL\™(ˆû¾5kÉ5ðlÐ1¨kZèa×1÷>ºN`'c$/z˜î䔉¡Dœ”¥\$]çÚ_o¼Ñô=N®[¼Uy„ÜpßTµqg꘩6ŬÄ!qHx³hó/ëJÝz—½#F`ïÃδµDTÝ †zv8ßPý»o~ "ÅÌÆzWŠæÍÄÅŒÞÏyµÓû{ªvî¾9¬X©‘³7$ˆ¨5u÷7—’(=5G¤RJÛw3“Z“‚»mû¦ ±³´¦k)a`v]«»×¥Z"Y“¥Ã…'b)j­Mµ–E÷¶C@ŠÀsQmûÞxÖ@\6D|z÷.µ®0#ÂâîDÙHÉÌÕѳuž¶’©TÛ»ˆsDØH`yÜÌÜlMµ–býÄj)‹ŸÎ"žã„9°É°u]/©'Üu!Àã²®°½Üšî#å‰}Ûq×¶iËø•ãÒµÔµÖì­{˜†jX zx³FÔ§*À‰4w JKêqÿú¤gö@^·YÜà,@ÃØ _k¬b*åÎ쀈8•ã}Ò¾fØš‘l^~d@§=8³±VGœíˆ€¨ïJ œ€HÂÅLÒN‡æ‰°ø8º©8T§bØ-!2‚w \?VÏ›»Öx '¾¯§ë&þœ…X(ÀÝM­¥£QZªE7óE°´" @¢Z*³˜Ù"ÅÍÖZSO?!È—ËÅÌ[vê›er.Ë»>WÄ'åP˜Éù˜ªåI~š‡D§ÊxÎîœ)`öÂNœ¸DJgN‡PÓžx`”´BuîM:$âÂ$$Â\¸Ô"9}v„í1óx?ȤcdüÙj™¶»L¥Ü›HÚ«¤cÜ8{6'1wœº.˜9ãO†c¡³žj,ƒõjzþJÊñ§Þ©«î9¼l„Þžy;’Ÿ¤Gq5f½™`’Ó{Òܽ_~""w“Òƒ À¥Œ»£XDðr½¨ê²,›*±šn÷ýéééó§Oøßýæ×¿ZªÜï7.læêŽïÞ¿¿ßïRŠ›/‹L©RJx¬×U›…îá exªx˜™Q—™wMƒ‘D_H­É–:nì„®õá@öð²M‡d9wF¢G8I8°ï ‡05 "©C@8ºnI&: ¸Wâёݼ”òððXX,µ ÜL˜èÓóÇÇÇmú/þÅ¿øîçßþêW¿òˆ½µ 43 ®RGIw fØÚ¾«¦ü[ÖÄ$úÀáˆ`á­í"b®‰(™=ÃüZS«dN¤{С3{€{,iH'Ïù«Ðs‘€oBŒ½j@PËgÛ.Àpèùþ ¢s„ŸÚ)cks‘Ú›Ü"ª6Šˆi»êÖúpñ5˜(=¢GÙ1Œæ1{ÎqJG°Î!ßUzüJµ°G% é¼Ál›Îf.f{+3}OÚ¾1 ›zkíÃû¯Tbtô‡ÔϾ·T±‘ñM‘ëòU€÷þZ8³d•‘hÊñ=û|–ˆÒ…f¦à1HÀ‘(ªj)Õ!ÚÞ¢OB"2wúÐü w KØbôÄ<Üíáñ¢šx°®_ˆÓÆïtBŽÿìYÝ_>0 ýó¼Å×?Ç…3ùñ7|š’Ã9õÏ$9Ï„^ •Þ/O8_üO­WŠÓ‰22&ˆÑE ÞÿéßùÕžäI¡w]h¤ ¯’‹±Kš¿…ˆÑ·™@WTäZk­Ë¾mˆ¸í‹4·u]= Ö.ëåÇÆO?áývcÆŽ³B–Çǧ֔ˆ›6t‡p5OkõTÝo/UXÕ‚PP$G[Î(Li’Ûq빟÷¶'0 çûÚLXz÷‰  Ü%FÁ—ƒ‘£>—ü1€°I›HùNt#F„†U©©Êã#Õ†Lª::!É™€"¥–²m;mÛV„…%íkn·1™ûº®ÿßÿßÿü×ó׎`á:§sy §ñ6%šÕ#ÔÌûó Iúzte6WSˆ¦ŠË\Ì©?5¸ww…¾äæÊaâ©hÈæ#ç=ªÆi´”s°Lcz‘|¸hžp¢ôªí&æRˆ}Îêg4ŸËy§¤.XŠÂ@RMú(#wµçÄw§%2‘Ù s©u–ñ4´úGäN9Õî3u8Òß~K±ÓÛ²ýõ½ú8imž÷{Jèžl¾ºÀ@.¥æ¾^×õøGî®ÚÔ£µ†#Æî{KYØaÈÃËõ]Ž8r.̪6ÅÌú#ŽšÍ 9Sl Fb,¹¬GŒ>"¢»; çt8a*™t§*ºƒC n8”R‡•`2!©SÈöíîæf-Á~I¨AìÆooóâ“*Î aùtÏ(½Û3E;LøD 8Îçè«ù#ÝBepNÍ}èÍœŸ¥MÐÎ(Æ¢2[šç`{a|ãÿñ ”ž$6#:<œ¨»lfkhc‘gØ wOu„Q•ƒ¿„ÜQáÙjp×ó–™Öv/¥ºC­Kw6ޤ õ(ëèL!ÁÝÉAf©uyvO!%n_eM8¾`ÞÉš#F‡=„9%Â)†œev°·^qÄHONSkÍ=¬)gNùñãÇûýˆ9³H‰ÿ¨Ëbf#l2q]Ÿ˜S¿W2ï5šg›ÆY– Ͻ53íò€LTKYÖÚvë_‚z'Ä"à„€@@„‰ÛÃî. S­*ûæfÖ7°K=“”:n˜C*²Œ§)+"šÖZE8Ôöm—Â™q#¢…J)|Û¶][nÛ†LÛ¾ó•˺®ég™ÁÓÌši•EÕÛõ­R(ÀµÛ 1Ig'b ‡"%W ³ä‘’¼r ħ%ÿzº˜»O>”p’zûh¤ ¾> c—˜&Êì!õêS¢1âdd:P["Û<]":Œòl§ÅÌ"ËããSNþ±cUC©éúü.gæSÜéÌãÏçiª§ {Ê«2½;áßF*×Qö¹ã²L9vŽüýupŸ•ñüt;f™Ùw¾Ex0 "–RUuÛ÷ÛvŒ9øÍ¶{ SŠxïr5&YGâ÷û_yV$‚¦«Ù)Ze³IDŠÈý¾ò ùtÚ“w/¥&ð«JYj5Õº”Ì™‰{ÂÌéö—“ë<¥‡<R”Âã̳a[|4MNm¯à¾'¨ÿÌJð,<”ül< ‘ÎKöÕaýlñÍ‘À.Þ'wO®‰çóåíáqúŸèƒÓjð!ê6¸3¸#Ò-õùQЧ}óœZMç£Å|¾Ø# »"‚¸¦˜è8{&;¥¬—Kkû»wï¶¶/Ër¿ß0Æ¡ŠTDvmfšÃྺß7@$®ˆöû}oh³°R—e]¿úêCú‹ZkáD[kP–%a‚mßÈÂÌ5BótsÖÚZê»Z²FÝ}©µËÖ÷Y;;t!”qxb$Ÿ2¡5D6.%eNÓœŒûígÚÚÍÍ‹Bˆs-¥"se©¥YúªUwf¶ð¶ïµVM a‘½í—‡+dI¸kËUƸâXkõˆ¦Zk-UÒkGwõFâG†BaÁÜéùÝ="u7;_d¬yfN™ð@ê/b¢ŒªxÊÆyß Œ1iî4S=c¼`"’j] hª*¾šjF–ÔRJ©µNãån£áZkMÕ³™*1ówßýÑ»wï_^nª=´yèqÈŒc›( Û½1Ò…rfžU˰ìËwü;É ÞlâüWò|8²‹3É1æΜ¯qK'13¿‘Ç AHÜínF\2S³nÂnf]»)ÜÝ™Ž`—ë´}ßn;%dI½™fÎì b†®7µ%[ÓÛËnÌÂLÚLª„G6,èr¹2sÛv¿\/ÌÔtßö½»÷vVŠ¢…7ðè”@‰0imÏ@YJIã›ì¯%NkÜ÷@„"ŽHw$ÅÓ¦d>¶üOK"v]õä§þÈÄz‡y¥Âkg».Qr‘ø~|RœÄ‘Ça)؇œ,%})•ˆÝ“_,i0½á’Fâ©Ï<ê½Tà gB&&Dpt€ì­W¦þÅ@fÝJa¹!¹ˆš ³™1¢Gˆ0¨b¤¾”eýÃ?þãO?¾´}/Eˆ¹VU 4fÚ­ðÞ”YL™Ð÷M·ûR˜)EbéùùžrÄ̸”’®í$b͈àóóçûí†Èj^·í~½^Ìl­ÅUÁ)4Y)¸˜ôQªµRÛ÷*iÍD Ø™rI!1w èz ÂB…€3jáPé)…3óè²ûáÙ÷OÙsçÃJ€IDAT,3ÍînŠQg ¾¬«y‚ÐÓŠˆÉÍØC"$pÔ™€À!}vÌ16M?mNE u¤…kÙÛÎÌH÷—{‘º.®ÌHK-èN„Þ4 L[*F KêØSWœfˆæôE`)©[LnfRJ" ¤VbŽ‘d,FF"®Ë’5¹‰ !­ëš–@IÉ8ðb#CwF„™™ö܈Kú³š[DÓ–!‚„€DäÝ»wÇ•Ÿ??ÿðÃ÷f `˜ ¸ šÔÁ¯4º¿êáîЉÇù¿E¤ˆ´¶Gx)ÕY‘K]"Ð;4°G˜„ö^æ°3KÐKn¶ÔGÌÎÃðl0Kø0á£,¢½Ï0™ˆI$[dˆÈ Îe!´ÜKfA¢ƒ#˜+b``¸·,n‘¥\¢£ =™¤ÐýHÏ5þÑä“kîÇa¶Ä—u1ÓÖRâX|pm8Ì €mÛn·Û¶ïÄ0 WN§.ÊPdΞT$°GÕ"`Yªû‘½«è˜§óôÈRg7æœöÏnÚ›“™OªÖó× ÷ Žº5E(²ê£aÛA¢ þ)šYž9³>辎K;U?ö+ië6_œºq×{f*Éhí2‘m HÝ1DD`âueÓ3h„ÙÓ§-Õ®ó[‹0 8ZX`¶ÂÝ̦DBš„ÌñZÏ£!ˆ(KËRJÆÉlªæÛTS K­4I!v÷ÂT„[Û—e‘"®jfFážb¬ˆÂÔv¥Ô îĤDäYŒû¶33¸#‚›…5N23x¢™X2£$¢ReLųšž°A $ Ñ Œ2F0"˜å]JOˆ5c—;IýK˜0QÎÇ"ú÷¶ïm„ZJé| ˆ²ÔtB@5SfRSuCDu”3l­ÝÚ®f,œŸ’—]JÉæê9­I­§ÜFÌ|½\XØ'Œ=3ŠˆðÈ~HVª~†Êe/¦©ÍÒ‘…¹¥Fkf¿ÿƒwí”S/ÑÓq;&ÜÕ\F£Ò}©éŒØ^^^òx&"U…ÈônLhᨘ'PÙòµŸ âs^TâÑgªD)Z90Ž£žÆÞ\ú ÈY¾dL6fèÏhvBd)ŒˆB©ªkj¦VKI™ÕSü‰ÙP:zÐóî&pº°72IÙÜ‚¹Ûð“‹ «˜OñŒ˜ÎC/—÷0fvWV~e‘”CwÓfˆXJ1×y#æ›»;üw^ " 0 é¾ç—L)Tæ2<´Þ¨Œ€Žóð8RxН£WŒ ì…yasAD÷.8hÙ³Bd:/Ö#ˆá²8—Âù䘨G·³pº¯ä5Pr&h j 5DÆw±Ã~S"S×\}«¸·mĺÔQsmíï¹"J!3/uñ4‹R݈ªšXŒ¤Ñš™šFk;˜›ªwºYG° ç€ ADb‘¶oÈÄHqYª¶=̘Áˆ¹¹!¢» 2x˜ÚeYÀÔ…ÕŒ˜ñd µ £«WBÇ!¯ææYöåyh>×à]ñ’•˜HÄ9õÝ ™Þ„î@‰)Ê$Ì0H‚šF‘ ® ^UmÍÂȹJaṟ®jzß^ Sn!§mîaÖgʵóÝ{(2u&é†M§|(—âÞöÔmˆÐÖÁ‚‘.Kq‚©äÓ&J˜E—ô8¶I ›!u£MŒㄱ­òž1¬CI†™DŠéžÐoF²¦yJ¢ôÙÊ `8eØüû™at<…ßS¶:¿Ú¨«y(SSijBœ(ƒneL8X¸Éa³Sw`¦ á”ðÍ—ˆpÓ–ýy iukë] 6·5Ì0 çæt²©`I-ºq¾ ' Ç<<^iôü$.Û÷¶»§´ÖÊ8¯×5‰­µ/eƒ@° ·KÌIGž øé|<éQëº'B&"®×Gf&U 8$7³AÿåAŠxXuÏ«ÿO¹¯óˆžì É"rHÅÄ]6ÀO›çÕ»ŸˆcS´ó©G„¾00)¯O ó›îN~Z æ|CΆW*¥è£ÀpáH^wæì™EfĀȃéŠÌD,E*‹¸±á{…}£`*ê÷¬—‚™Àµ[DWo† "6ßóK²”äÊE¸ƒÛÖ:˜ÌlY–!D ÀEÍkYˆ=R™95ʳR(E’ô–Í´´QÌ{µÔŠé¡‘"PÔ©+àaîk]˜Ëhë„`aésè¤ à°ñDäŒtCð½Óô‰L=„…„¥ WÌpOµá¦šolM[Dˆ0AumÚÌ™¤ˆˆ`x# Bk{®š¦ Ù·è´¼*SE€ZëÇÛ³u˃¬œhÛ6U]–55rž™Ú«­)t¥æ<ö¸SØp©k‘:§—]Zà e®ãŽýa¦y¬›^eùç…=aŽé'Ët€ƒ§’"#cË—1S½ñ‰sûw=ì–,vü.Í%qlóxMt? ¼;ÍiÖ ‰KÖqt©AôsaG!q3pµ âHxúø¾yV½ `1}y ·Î²F踻ޜɰ;‚¯ ~^ÿ©am3èÌ€ÃíLDrFâîàÌÚöZËëà5š!ý†v+êKŸ=&Þ÷ Öõ²®—ÛífæµÖ¦Ûx>ók“™ãÖÏù ‘àÿÕàþ†€w•§û0%ø(ÎõAOVFœ˜ÐÚ8iΜ]–Ü=+¤3úžR¶9%؈83PL§&ÂD~c/=&c:ùè#¸C€»uY7S"éRvà!R0-к*Sd8€à.(†žæé0åÆxèÇAïN2"в–Qñ3gs/Ä™/o{K[J&f"¦o¾ý¶5UM l—H½$)bîO÷û­7SDä"é•£¦ÒEÞ1ÂJƒéY¿Nõàù‰µÖ8ñT¥0@§ïBÛ~*uƒž·ž3´s!2¯á(M²ßÐ¥`F›%ÛKirŒ½eGz:øJ§Ïy•Ü%€cÞÌ^< !`)•©D¤•`)’Îßo® ˜$/¯G§4Î Ÿ”réBwzÍ4û©o½m€£WÑ«àÔƒÍtS¤Ë7ÖZÝ-5瘄#,:Ñà'Bð9†aD`˜z@ Ž¡¼ÝnÏû~'’r`ûü§Þá¸%0ó¯þäüÑçÀý&Üÿäæ”< šµQ³GZ§Ö|dÁàè_¾>cO(oæfo½¿’³yuäPZä"B ÊØ98žÇÕR¤ÒÌoÆõo÷;Š,ëÕÌ9=à‚,œ°?]pˆAsk…aßNBfîÐRÉÁÓ51"lÆnCtp’ب‘=×sk–Žt1p/ù¿j»»AP¢¦gš•%V¾,Ò|[ … Üdð:?ÇÄFž!¯ƒQÃ! EwM~.¦‘F¸kZPß¼“G7ûÄ x…¤œŸ‹ˆ@‚\¸,äîRÑCƒ|^›Ï#pVìç$r¼O`s],‘¶c€ÖåPÜ:ºÇ…˜‘Òòug¦}×ÇǧZ–m¿q8 B)…ER?2—Ž6Mp>ć>&H0<à´3Ž*ßµÕ¥"$kaPmÙ#>Ãcóh´Î˜Æ©–ó~ü§d àua¯3< ƒ§a)õÕ9Ñâçú"&Ò×—4¥£<„ÓˆÓƒÓŠ¸¦GŸÇ³L£$Æá@åÃK‹¥¨ªG¸šÔZ—ÅÕòÝÏ 94‹Ô¿ÍXŸjàjÎD9,•"%×wïSE÷üdB¤ä173#BBD" 1uY–¯>|Ý,¸.¥.$%ïî¶ï0’œËåºm;ö@CDmßÉUë²dë<3¾œë¢É®Ž_f¾]¥›‚… .µ,>—Ñ‘©a:otsçÈdßÝq„Dæn“ÆŒ Y‹\J%¢èV¤–.n±ï{k[r&ÁÍ»æbô>Rúv5a¾\®9K½ßo˜ 1‹$É;Ë/×ë˶ß^îÁ"„à¦ÍL'¿W?½=²¤¸3 S)%n4,&@¥Eù@“Ζ2€Y$EoÑdêÒ“Á€©9H#I2Ô«½–r áž¼÷ÜPj ˜yY– îçdôËM:,ÝFÛ;!©,õv/c—WaÈó/ç 8,;&º?¡´!|pG`ô0 È1)ó˃æ,ñ‰¡^Ö‡¯¿þÙ·ßþìv»wŽivqN¼Å¡ŒÕ5ਅK°¿' 3Iøþ.¬‘œïDê$5ô<%]IG¯f2ˆÈËrùó?ÿ‹¯¿þðùósFŸL^¶½™¥T„g&UEÑÎoF= ÃìDwÅÛ®…º·=)« ‹t· Ú·,»‡çL!FÕ7·ø| ç…òfѼiÎì¦昋• :èJ~‘c—Îdµ7¥ÀHØó$Èä ™ÜÎz{G•÷ñÈDˆ¹sÁN`VšAôµÐ+ÍØÊì3\D4™¦ˆëzÍ °m­ð´aäáhÃ¥HÛ5sÉc»™êÞ˜“ñ×Ïf335H&¡Ƚ3{² j)@ÌK¹høõúðÍ·?»ïK­—‡åòÐî[Z.?ÿùý“òÏþôÏþÁo~óëû~Ïã3K¢!uøRáÔÓ˜áÀ@p°üJ _»@tá³¼þ\w„ÔYÃ1¶/¢ÔiBâ#"2¶½}üøãï~÷}‚Ô‘öfaÝ,C3#‰y˜mD™õ€ID¼–JH#>˜»ºWL‡ß@HÄUaï@9mˆÓ|#ïc>-|­x7ZfÈG!Iêño#{Oó…’¿œÔÊ^gg½`Aàp °ˆÄ Möèƒ  ô£°ê•Fêc³GDƒ›Ðš©&…¥ äqæÍLƒ…ð°÷Ê´\’öåà1J¥1ZLÜ&1±€pÀTÙO¾\šô ¡0#akÍTHº ´;€#‘x;€¦tw)Žh­­׿@NŒRëåúîÛ?øs^>>oú§ñ»ßüîöòòîý‡ï?½¼xx|zw½>Ý·ÍT)·—ÝÚuYÃB—e¿ÝÁãåù™ÍÃk]ÖK¸o·a†0ÛZI:»”nmß/—º¹R]Ö"ÕÌÔ4kT"º<<ìM‘hÛ÷õr!¤ptD 0s5wÀº^V)L\D¢™H"¤wÂÇÇGìv}zþ«¿ú«¿û»¿3ßUÛ¶ßÝ[¯§Éß° ™áhºëÌï•b’WÁ}<­.™û+’wÓúë³ýÔ1”Íš©›i—ý*å‡ßÿþÝû¯JÉÚ­ÍÊ¥ùÐ$T¥ÆÓ¨êÜ©û¸5Õ*: (CÏÄð`D’mâHÃѧ×—Ãõ¼¤px8øŒ®Ýˆ/NUä볡—BGpc*EDÊàJLîà #3Ç ;ÀÈßcb@O-¹Aj=s}•utÒ¦úP(A£?ÓCûº1‰è˜Kg®‘¼°Þ^4K`Ö?aÖ†¾Jn*žÅi6`˲a’Q0„Y–š­ÒZ«6­K©¥>~þõï½><à¶mûËsì÷Û§è¾<¬ß}÷3Ähmˆ}ß=B»¸|ÍÒêvßÌ’äG°.".ÂëºB¸™"b¼pDÄ"µGŸÁT*¥,ËB(ž¨P¤®ˆDæ^D!2!ª5Aëá*ÌOÑŒì‰÷ÖXøñÝãvOF.MbxØõzÉø!ùOÖ"‚¬5Fs7›špÌœÃi)Å»ì·g/b© äykææM["Èç*ʾP.®Úš™¥diZVñ1Úµ!b);Ⱥ·Ô³9 L"eˆŽ¥åÒ׉ÏdNU‰$§Ð“+>ão÷7ñYN{-rÈ RÀOѬwÍ:%&n-ºÜwösú[½ ë„'bæT¹üïqåh†k6ެ :o áÞfvHóˆ÷®uˆÝ,WaŽ»õv½ß·ÏŸ>ÿð÷Ûs„GXg·õÓîèÀ¸Û&Kâg ŠRÿ”¼JF®ó”£CJ%^;‰Y§ ê×éK#+”"ërÉȳïíýW_™y)’c%8:DD:OiÊS9Á]’ׇVLJÌfåéªh|³‰éÖÌGŽü*ˆÿ¼=¿‘¿i‹€¿ÍÙ<¥Ï¥àžåeÒX¢KS ÊÏ û_°g3KŠ£Âè·tHNöÈÞo¥î\ŒÏÄnÑ6’‹|(÷IYöïÞMß;…˜ˆ™Ãø!צ)ZºP†™e)݇R9SI§C^RBÖ@ˆ„¸ VŸ©RÃÃÔX®—‡Ô±ªË*ÌÛ}k[Æ~üa×X늦÷ÖöZå׿ûí/ù÷Ÿ>}Êàe]×u½oígß|“²rR‹°Ô² Iyz÷žZÛµímÛZÛ¢Ö:†î=å–ì‰3Qо{xüðÕ×µ”¦šSÁT–f‘ƒHôþé)Á9.L̼Ôúôøh·M†>!¸-u¹ß7f†H„}"†1Þ==D8:˜™îÍ´!Q)R‘ k×ò³€¨KÕ“¨¬±¦fQŽ9‰š Rx¸Úž´ºänÅ :9ûóŽù釦·3"/ˆgÜz?fßaf¸3Í6®üO5í§ð¬×˜¹í[Fvf»³ÃÀYMŸn7¤”ûðMç®Eܧ4Î*B ÂtI/"‰^pe]ß¿¿ßfpŸiÿùÏ>SƒóËÞ$þçÿí©}DÎaTw0d}r5dëèõ)sšhÍË#„s©v~Aq”ð¢M8µ…ßÀ%OÇÉ J@ô§ç¹V¡wïó¹÷sð4¨µ""€ Kš×ôúcj‹C IJ\2a™ÒQ=#¥:"¦÷K–í²,÷û_nw³¸^k­p»mß~ûó‡ëµþâÿð‡?0fŠˆÇ‡&~y¹?==m·Ûý~w÷e©{k¦¾^®ß}÷êöéãÇ}ßRù–K:øÃÒk)"Eµ À)>>¾ûúë¯Eäe¼33âõáA‡<^ºȉŒ³·ûžÍ ê˜7צæn¨Û޵Öü.»nènM)Û³ffš‰\•2ÃÓÌEQÃÔÔÑ_î/^jM Û¦¦fÙ¥É 6óÖÚH› ¾Ìîê²4mªšêI8t?æt*†Ä]¢‰zΛÍÊ HÃY‡Ë]ÛŽàÞÁˆh3Zâ”ßNåÑÌmFÖø ép$õ½3 C¥óõZ‰D€ÈÂò«9„¥æÏÑü€‘<õY.Ä‘tžÝ‰²"=í'RWšŠ)Ãz)托W2£èŒÅ8\™™»c)RÖs31MCÄÖv35×ÖöœÕy>Òln#ÙëŠ'Na¹ÿ§{îo_„I  7¿}ì0ÿ2zZQjÍû&\ i©ë_þÅ_>~Þ¶Í{R9 ðÒ_7œˆH^­`D„ÈDsjŠB–uí| #È"Àò?€1wqÛîçÌ}~Ä›`}þÏn28~øµ~ÃÛ_?º·yÌw¨1稀:Ï¿“zü˜éM%A8´Â:«·žN‡n¾ "ùìê BOFfÊ3ÿD˜tG·,™g ]Ä{EÅ„Ìqë² ¡¶-1RÉG1™Á=w°ð ¨› GD¸y„’ˆl¶¯ëÒZÛ[KΉZ”ei»^ßë®ßÿðûÛóǧ§ÇO·¾\¯—?~D·¦ÚÖuu÷mÛÃw€XJY–e߀ŸÞûÝw×õåù³jS×ÃÕMU%å°Y˜…ˆd8Ü÷ÄÍ;ëâóËËó󳺅‡Ô¢nµÖÛýaÆDÛ}€R’@¤N= ©›ºmÛ–LîÆÈ—¥º9# s„fëÀP„9Bsš 4”³½@CrÃ0n÷{³Ž…`¦4z $M¯¥ÌB›6÷"cX“y$Ö´©ªÃ`ž‡3qŠ¡e”t÷4¹Íàžò©ZÕ÷ïè/ç&ˆ†°QöâÇß,)¦ØÉúÓ1¦3ð&$i¸v¾Á¾ Í}I!NyBDz½†ˆ»ðW‚º Üç=pÌc  £Ìíh@Ä”WëX’1aÃѧW"–"¥ 'V&>¥©Ñ@È¢;d]ŸúqYšiJ¶ä; | ä„ãtùˆ”ó<¨øуû9²#"¦[ÍIc뀇ÌîÄÖ7·"u]/ÿ×ÿþ_ý»÷?ŽpºÓÒ€ß8öoè½ ž•³°÷Ëb9ª Ä³ˆðh 0‰…ßn·fW§Î œÕó÷%Úq#¾gdzÞ?‘MÏßÿ0®L„+•È¡ŽŠ9šíc{ä}OНã@Òµ~è6žÐ5%²;$Ä…ˆsð”ý!Ì$¦TÙé<ÇNE„~&œd~lÛÞ{›Yk½ËCÌŒ0îM›6  ç"˺á¾Ý¢H)RRq#0ÔuŒ»šAYV‘å¾íPWdQ ÛïÞ?þö׿Q'‡òòüI˜ŠH¨B„m­©>\|{¾ßïÏÏŸU ‰¯fð»üíoÿþóÇ ¬®ËÂLMÃ5ºo6æyÓ£'r¶·ÌìÓóóçÏŸ[¹EDLZS…±BR7·ÎÊ‘e©ÉvÁ„ä†CÀËË  q ¢Ë²¸; „µ=1ìá )‚àL]x½Ô*¥sÚ æÔ<¬L3 tùZ@·pÂ]÷‰øÎ¶‰”š[»€o(oûžû.ƒ’æ?Ì€TjMS§ë²vˆ§GOØSy§çi R…Õ'‹˜Ÿ“xÄÙ:pw¿\.û†:ûÌdmy²ÍBt ùr×a=ñŒj”jWTê–5YÏj™Ex"#;³k~T· ãÝ2’PNvÉ'û^1òÈ#Œ#Þ kÐñŽM‘P!÷ ¦`*I‡”^@O\RXÝ}ŒÇÎÓˆ.‹tŽ]ùOðoŽH˜e=å…qÄÓÓˆ5Î?¯¿·Œ /˪ªµ®//÷eYÿ_ÿÓ¿þñÇR3¹‹²"¢»©Ží\":) úxƒGÉÖÿ9K’Á'A Tmùº¼ø4vHâÛÌ}ÆÓÜ»ÆD•ü‚‡rÊåãu;åô¬?ÎÆèQ ¼üéH 3šæÀgœ$‡|*(;‘1²ëGL,A )‰1ž™{Ÿ¶ €×î)^_dÓ\ (“ 0—ZE$ëÖ—çgζ:¦ck¿{f–×#RÜÝ·-ˆâ~¿¾œ@×BI…„ì ˜ K©+"#ó×_keùÓ?ûó?ùã_T¦ïû›ÇëaýêÃÏöv×½¹îÂLfJ@n¶Ý2è–ÂRžžÞ;àóómß>Š`vmপ÷}[ו°[CdæŽf"„©ÐîîépÖ¢— /ï1-µ2s¸æï¾{÷ðñÓsSæRËvßò&»™3óýù9,DScý¶½„uªJúl £»µ¦ÉèŽÔñéka ΦØZ—ÇË5–ëe8bFi Ìäá&ÌÈhYÁ$÷jtb ò ¨µæ²¼^.6~¼{p.†Mn€ˆ©÷;³fDt ƒ1YEŒ÷ïßµ¶Gן“!|‹fÄœr•¤OÍ"Š@J …20töÆ¡ì©*Ó …GæNDµ\tF9M¦ìå9˜a‡‡ˆÈTçÅŒòÂrꃈ,ÂÜy ©ö³¬$r æã©-&DÙLíM‹ÔÚlºçCLòI[PdÁñ=¥­ÏðÅ/“ΘsÉ.¥N¤ öÄ“ EoÉ s)ù‚©@“?­7m¬VaÀ—ÏŸ¾zz÷͇w/ŸMm]ˆNüxºhyЩ #:™'œ“E !†Q8nÞ…ñͶg`ñ€R¯)i ™%5±ö~ržãtxuÐwß`¬³¡ÙûEó¤ß\Ï% Žy KŠ&§rþ_ÐHç©#‘ €œë-º‰e_*Ü ˆ’#fXƒ$¸2Q€)‚3yo¾GyR¦r“1¥E@vë"»?"Àû¼ z„á Üloá$Ð ²È¡´ p #’.³“·ˆ™s¼ u !(EdÛvª…KE–w_}Ó ¯OïþÝw€ð›ßþöw?þÈËúÝ|w¿¿lÛç…¡ÜowuüÅŸüƒëõñ‡ï`—ëuÛvfÒ¶i»?"ضA‘SÁûv/¥QS«ë¢æÿèý—?~üÈEÀ!Cݱ©£ªa $Je®œ)3yhÓ݈ -Iv,êÚÌÒžP­…+!.µ‚pAm{6kŽŒ·mC"#||zºÝnöx½ºY˜W.-@­iÄÃÓc†xSgªu¹\ëÍ]½Ö‰…*趑Эm»©¡;†”¢Þ© ù%YÖ#ÝTM˜%a 4‚) ™Gk.²¼Ü7d2p$FË3 %{v¥ÔZ—Z:»jŒnzéšü£Ú¹˜Ù…H¬@VK}+A'Œ ŒðpEÓ]DöÖ¹w±ˆŽÛ©<Ýn“dhº%¼½ÖåÝ»÷·—Ï¥‡î^‚ÈÌòôôîññr¿ßšµTš#æd H8x—jâ -9¯ša0¥ájÖËýlCÎc¦ãv–Ëåòð–RŠº1•ÖlY¯ûÞˆØLŸžž¾ùöÃïøHjžjÕîR*zs×Þ„Á£g5ÓMô 5àªP„9µ/§g8á2/ëzPO ,Ú5yÜeª¸Ô¥isð›Z-õ»ŸýìŸÿ·ÿÍ¿ýwÿ^jùôüùññáÏþìÏþþW¿^.îz@J{ÚxäÀÔ{îØ•›™‚ÓÀƒX–åÒ;ÈÝö.`»# “zÄ9Ïf]33ëàN €/Ë¢ãïg-qÎ;ºñò¹£5«¤ãݦúhðMf—Kó>ªNWˆ¬ÜPdY.—§'mªm'FbNkûôMãÊl­p/ºÐÔû©b*Q @àh#"Q6 ™…ˆ;î~ ôÏuÇQ õ•åA’Æ#yωÙÔÝC¸˜«”ÂTeÛÚÃãWß|ó­šýøýÿä¿ø/~õ«_~üøiYÖº¬¿ÿþ{„ÈÅ A€òíÏ~þòüüòü™(5婈âÃõ¡ÖÂD÷çOžTþ¹ÆºÅ¾ïÛ¶%ÅU™¥”BÂDĨ{“qP¥¥0 ÔDÎñD1ömww‘Bĵ.ûv+ÄïÞ=1Qv¢“¶òüùùÝÓ“6%"míz½Þî÷ìª_/×"œOfß÷eYš{€ß·ö}¸^™øñúæU*9®ËeÛ›š3’«rál¦)½ûgD6ÍÈDC„ÝÆfOÿä——"^ê*RÀLÕÚÎéÔ“³´ušÓÚ˜®Ç€çèû¼³ŽXñÅèkü!Ž ½ÉšŸ%Rò6vƒˆ) 1Í<ŽL.ÒÖÚ¶m­µEÊ6Ǭ ñåå–eAÄûýžk£‡<”'& /±ªç­ÝûÕ£Ÿ9h+ö˜x„èš+ÍLó¹,eÉ9°™­ëš}öïø= „wbOD TÛdØŸSõâ¿ÏÆ»» Ôf5¯j¾4êò§Jƒ)ND,’‹@‡åv\@€Éð–Z(ëv „0³ÿåßþÛÏ/Ÿ·¦ëº:Ä?Šð¶mˆ<™}&óÍó‰`¤xA¸¥ïŽ»ÒÃãÓ‡o¿}þô Ð)Çß~–é¡´.xÓÁ5ä£|^vozëçŸã4rçû¯ŸÁñž'u·œú$‚4¬ëÞ"ŸÙ™Šì‹J®e]¾ùögnæª"]?=€'\!<­‡ô€ ú)YÈ)­’ìˆ>܇Tï†é óäëÆY§T¢?Êœê¢6± R²ös»ÀÞtÛw ÒÔÍáó§çßÿðûëºþæ7¿úë¿þkD$æOŸž-0·ÛýÃ7ßÜ7ýóð—¿üå/Û~X‹5%BÒ¶‡y¸m÷›î÷¬ µ½ÖC‹QU™åå冃€“[: ö¶ç†üðáÃRk¸g·}µN鈈ÔÂËD2}àj]i]Š7E kºm\.—4c*¥¤9,DÓÞš0—¥êÞrÌi‚QkÝT·í~Y×OŸ>===ÕR.eÝ÷¶býË?ùðíwïžÞ#ñóçfz÷ôn]/RE›Þ÷-<„%Q§n>ˆs*fæaç½7uÀØ"‰¦aÚ;q‰Ë„‚d•ÂݱX9á$².|˜„ Q¶§è£ÇÁ ™ÚPpþ:»¢çH&º´'Ì£+µ4¼TûÅ„™öÇ„}”<¢ÖpP˨ƒ[‹ù˜ë»ûovèzn·¹=ç¨9G_S s¯LÌ¡Œ (Øu_ÖËÓ»w»¶­í©ŠÄÁD2ˆX™²hkg¯ãsÞ9ÃÓ9”"¦Ýš™¥ÎÇ~‹ÛýþòòCçÈÃ÷}¿ßïùxB$¡‹0@DÆ-Ñ*âáÛýåv¿¯br€çççmÛÖË #ˆ³Ñ ƒŸé9ppŽþ÷¥0"u‘–òððøøîÝoûË>OŒÎYíG+J­ “¨5wŸ¡pÖ ¯Óð™Ø¾m¬¿É5àhËÄÌàœøwró«_¤±¸_5ÈÛ $J”žäG1±äÐ'HÊv»oÛ¦m7sÀ®T$NÈ®œãBº®XéSëñe Ó®,kÈaT¶˜<˜…2kÇÑÄ4˜8œÓÁó<øèªy‘"䘚®Y2 "¶½½{÷nkOï޿ܶZ—"°Tùë¿þïß½¯µ.˘LýÃW_yaQM‡4»=2m`ûvß0…Ü„µýêÛí§DJ J€+D¼^¯û¾[¸™K)éQòòÒûàD´Yƒ‘ë$Ä,©×†fªÍÖu%JÕu×mÀ̊‹HÎÙZSÕ¶”²Ý7Bª"¥Ô}ß—Z?}þ|Y–ÖZ*³%(óùùY#Ÿ¶m#¢‡Ëõÿüú¿úû_ýå/þìOÿð•Ê×¾þËøÍíû,̎Кîm À"• sŠ­ñ¶¤ïCP…^Å©œ&·ërY3æîû–gÿ݃Ÿ#ß‘lÏU=ÌŒºpžu5Kˆ µtˆ©µgð.Œž¤#RÏÓ"¥áñ0ž¤þÓd0›á‘ Í' ÒÔ}ËüUD";G{?Ïœ¤lŽÎÆkCm""`ê]š¼‹NÕ>°”ºªªèƒ%°o-Q’i$›¥|Nbµ{W@2¿Ì/Ï™7?µß‹¥,3+™¿8§ªîûŽ„3îS†k9‹Bm¶Ô%<(ÜX¸¹}þüœÆ¢ëº\¯—Ûí–ã#&fÊœÇ5uhžaßáÖ67õéì­vßöÏ?ê¾Ï=ÁÛ„\¢s²;Ü7 ~ŽÃ_ô7©÷Û4¼†Ž<ΉמÚó~†û›íÑ3ýÞÉbJæoH‡±SÈ%ҷ݃ˆHÒÎ8û9¤nÂæ?ÊÆî×Q¸d”fŒ^9¥y3fw•ŸÜ®ÌŒÜ“%› ”4|cÞæü5:IýÅDÌÈ4àÒáîœR&}Çòz}0õ¯Þ Ðûoý›ËeýêÇwOïT[ÛR¾†QŠs3ûôãÇpÅhûËK‚½D¹Çt3 !€’Ò`ãéd‹&·Öz½¼ÜnPjñ7'f#Ä}ß¶íLæ®fàI\°g"óFŒµ,úáðøøhf Ú€3“›oû^ëR¹ì[[ëZHj©Ú´J}~~¹\×o¾ùfY–"ÂÌû}/U¾ùæ@úôñǶ·ZjöD~û›ßýæ·¿Ó—íÝõ©Hùƒ?úÇwŸ^>ÿÝü[)™ž_^¶mgä"¬îî&µô]9†cG Ù°‚Þ8gæe­¹ï÷¶eî2$«^åŒÑF'µÞ´lžÝÝ8ùL¯þVCôjòON=7ÓQ;öÃÌiËÓ³·þ}´CDŒI„ÉSÃi°QÓ *¹ûU;ˆY’Ö >†ÀckvM‚ì8#’PÐ19Þ³½BÙ&"B'÷r÷€HÉ "7f; Âw·Þ&Ê)ë¨òÞTô£a)K}¸>n[Ê„¦=&þ $É^+ DH‚™é Ð" ðe02Jß±yšBÌÐ9®f‡³ ŒQ{¥_" .‚Œ$¢¦ÉºCc–º,÷mz|âR¿þúë_ÿò×h»Z$ùðõן>}üôñ‡ÇÇ«»Wá—OŸß==Ýnwb°ý†¡Ðü²\’©nÔ•¤\JE@©‚IJï[D€M춘:§ü¯´Ö˜y]ÖRY[KÄËõzUFê‡Øo ¢Ù÷½ÍK‘ï¾ùÙv¿ß>,,áÝú‰îÛæ ̶µ"Rk]—¥Ôúp½þãòOÿé?ùÇß|ýÍßþíß~úôéáú ÍÚ}OåŒÇëC]–———Ï?!ñõòPI~ñ'¼Ôå~oÿúÿý¯ƒñÓó'"¸<]׺V)Ú„/µ‡·Ö…·<œG‡a;×ñŒÌSh0ÍZ`»Ù+œ SèÒí6†3½>ë¢ÎÌê-3îaÉô!Â!|€ÊÝÿ0“Áa襤‘‘jKyß'ƒ€(!óÉvô,DÝ­Ý©÷-§3mƒèµd:?à ul ÏûG¡âk×=‹0e!FTY–gcãÿOØ¿69²$Y‚˜¾ÌÜDäëÞ[ïêšž®šžéåN/…G(\®ð7p6E(”åÌng»§õ¼y3#¸›™ªòƒš9Ȭ٨+Y‘‘Àá0SS=zôwpŸ$¥”®e%–@Nr½^fID ­ óëùœ§ ‰DÒÓéôí7ß,çË4M¼¼¾LÓt¾\þÓüO÷ŸÿnY–išZm­µo¿ùæp8 Âå|¾^.ï?|(µ ɺV"&ÂeY¯ËõÚÊ¿þͯ?Ÿ?ýîÿâ€ÇÃüt:’#1å9•VΗ‹÷¶§Eu’$%·uYo¶[Øu÷Í%<jx× ëtPÀ­‡¹8T†~œ[¨Ø@Ìm7áÀÜ#Fod=¨Fð ò”¹«Ùì·ÕÈŽãâc`jÛÈqVuèTAú쇟zˆ€ŽËˆFÚV¯t IÕ¶ÉßÓ)cf‡-vwC¿µÜÞ¼yëC¦Öjªè EÆJDÓ4Å™90S$|L„ÄQ–ßG‘;öÇÆÑè­K@`é°p¨[§}×%nTÜŽŽ 4ÆÜ[kÞØ§»FÄ¥¶$ùí›÷ñ¿zyyÕ¦ª–Ì¡µ“[­5Pc¦­±³!×Q.…cj÷~aýàBÜL0Í4$Mt°W÷™qðyžÃî]-<µYU@‡¤ûšœ²Cñ6ìîfÆ-Ž¶Æ¸ˆ]%4rã[ÙAÛŽòŽ yÌôwµt$§†øø ðP”fD2è¿HÄ8ºÁ#b >e÷I¸2šoPXœyx(±¸÷מð0Áf¼ Xpgâ`ô°˜rt07uL5ðÏð——³»Wõ_üÅ_¬¥þ×ú¯Z.,œrVÓœ²¶z<ÌÞÔ–ó+!±©º®çIðéøîÍ›·¥¬ªæ`9§u]D¤™S4TÖu‰Fâñ®ÍSžbaÇðHh•„‘t©,h­¦ æh[KhVŸÏçúÝo‰åx<ýô'?ùþûïÿ‡?¨·×õõÝñ½üéåû¿øÍ¯ä˜ÿ·ÿò¿®­\Ö…Õõ²œÏëåZ—ڈܠõ¡›¿ÔÂ&`œÒÝ[Pȼ¹[JÙæù`ÃýuJsX†²DFÍØš‚)a8ÒŒÜÙûÇ¿í¥ ûÚHk㘇mÁ4 wÅ{Ý í¨¼Ão¯¥$"Ò%}ˆ$%‹¦ äœu¸ËÂp %”˜›­¦ÃS)€ƒÍóÁÝÁP«1ÐʈdÖBŒ(¼LÃ1ÑMcÆí¶ÓÉÁM˜úÌJèÈs8øx?ÿæßý»ïÿô=‹ ‘!¢"¥”š‹ŽÇÏ/ŸÍ=ç÷êÍó›ëë’zËË@Í!’‘L  Ïm±„&S3ÕA(ï UâDÝ’ó6K‰ØÅÍéiÑ&¸¡R7è¹›Ù³;ñår]–+0“j‡ð>±í.ÎLoZ£Dt8œTÕÁ€™L5¥4Ïs)etì¿÷Þ1ÇÝtÒÕƒ¯}ížÁ·2óáWn‡äpíØ’ú?óTð >vû~#MÒ ´¾×Hˆq“Øž(º918Ï,ÑöyèêôlE›; ð ëô‡ØøŸ[`SÙÍŠ}…ÐÍAz{JUMkÎÙqc ËȨ`|›þƒ!‹ ®êàLäR®€8ÏkZUµy+õõå%åÌ,ÏoÞž__øüiY—e]Sέ™×bÚ.—KΓ»óœRà{¦ÚZm­bô7Ýý„QŠ™õ,lX4DLÅ)v¸!o±.kk1Æw Ö#þ2úkB<\™KY˜èx˜Ýò<ŽÏÔÚr:Óáz½†PpieY¯E›O93qN©O–"æù¸®%òô¦m­Åjkót8/õ6¯¯¯úþ/¯¯M[gò Ä`Ë"4GÙ@¼ ê©à&ëAá åwÒ ·<:nj´¢·ä¦µÆ=|ßà”øÅ›ÜÖØ[þ¾ß8Û÷6è2›Â×öø.ƼaD9g뾦6>_Û:·ÛÓÞ 6Ûr|èÊݘ4^9P¦¨ƒ»Ó´ †;®†“Á$%"bºù@õdӸᯯ¯Û·]äápÜN#p«µºµãa~÷æ]]×®¾×õ\1LŠÀÇHù†+ ƺo+yÔ˜(!â6ãrÓÖ! kÃZw'¬Óñ•iš_?Ä¿ù›¿ùÇü‡”É\Í«ëhÈŒr¬Gt‰‰Ç Ç«p3|ûæùx<-ËâîSNϧSNé|¹|O=$Ë­;†@,î2=°¹ëíî>òîÞÂdÚ•BýhSäyøõíJþ\p¿vþýŒYÔ3DBÂ܇޻ùKõ˜YݺÓa@ ÛØÚ;")%ÀðyABBvtFébd¤`’íO¯M5:æèÀ€…„{Èì¹{×'Œ‘Ÿž¯;ÄyŸ‰q>šª«æD!càîµDˆ ï®àÞe-܈½éXrä ÝÈÅ4ê˜a`a-éãS%ÈþG¶@() …ŒsÌjb×g²0™3ˆG B]ÖÖ!™êùåõ8Ím)„àêk-áp€E+ R«šS qö7oÞüæßü»ßýî÷¯ç×ϯŸ§ÃQ]¯ë²®«Zû|þŒBfíóù¥©6Ó”R­„9tw‰Ø†ýwÐcrÎÓ4m3+n[nÖc€™š6¤ð|"Ž#!ojÐ…a뵪ªôa¥hÔß´’ðÞ›ôKüó1=ºá›·ÈNDÛi‡;»×iš¶hÎ]¡oæì)p=påyr÷išˆ8$ûUû u‹Wçz X{§‡›]hB`7øîŠ"ÒeÖaÓ¾á91–s–”Î_©¥åiRu"œçÜK)æ­jm/Ÿ?ùð®P·(é±{%Yãô™·€Ý›àc’Ø7R£ß ÚQ᦬?"_ìÆm]Ü÷¡¬ežÂòúò™c-{sk=õã)Tæ¼÷1OOÏ?úñOއù‡ß—ëÀk)ßÿýF1¼…Ñ^zô-{£ñ[Xßg¸ðõ¯»à~Ëw¡™áA½òÏ=ç®1»? ÐÔïŸa +ÄÂLiAÂ.W6pyêò ïݣ<IÌ2 AWddò>>ÓLîæ}PÂÑC˜[›+tºØm)ÆG#×îÃv†›7J7Þ"î…"Ç¿ã U¢ãJGaq õ473BN“dW-ëjêOÏo~ôÓŸ}÷ÓŸNéð‡?üQ„k-)%s›§)çœY´®„~½œ¿ùî;u@€²,!‰ˆÂ˜s&"0;·u½z4z…Ê0Ô1{ã?Ä*|Èo†l“;1šY"vVÏ AaA­w}z“É‘ôxÔ)Ÿ‰3‹ æC-ÕÍ’°¾¼¾¦œZgø8š;LÓt:~úÓŸüᇥuW×¢õº,iJKYš)3½^ÎçË%Bmi5XŦ5­Á*™oDö-V†lS„2ˆ{,©à•2¡6#$ð'ˆýЩnàîh¡Ó» @gÁ&x÷°U·jÀìqgA¾%·ßä±ŒŽ¯îñÈ­ë»ÃHû MPRÙfVK¢Á1¢ ÐË‹ˆ¿Ë©µænC‚BcœŠE(T’µÔ·œn_Ä@4üŽÇcp âÄeGÉîžó´U=Ͳ,׺3çC|F’21u× ð ob;=&DÉn%ȸEÈÂH3]HþïFÈnýÆ®2‚{﮺yJIµ•²¦$µ•€;þû8§oîC vÒ^›®×˧O?œÏ¯œ8ˆü‘0>.‹8$î÷{— }Oö+ã \寷¹Ë/Fæ~×;}xÎ}-Š0T»`XXø °¸‡î63r¸œ3KŠ  î0ŽN¨A•oІP~¿î]1ÁÄ1£É0tPƒ˼Mc´Öpgƒ`” bI‰€ š*!­%èàD‘ªc3 µÒ.ÎìÝ—€:mzpzQéJ3!5mnî,y~zÎÇã·ßþìóËËëë‹0Çõu¹¾ž¯™À^>š¦ùº–ÓÓóõr‡º^·9 pŸçy¹œ#g7sD¦p‰B€ÞÓC§mă$Ãá²Ä nD¤ŽÌLÃ;*›H‰‘´¸«DÎЇ|À‘„YUk)Z #½{÷ŽVk)O§§§(ãT•‘¦i6ÕèI¬¥”ª/ç×µ­$\­iø84¯BdîѬ ýÉÖšðmr²+}!ˆHXmôä`æNÄ}1 ƒˆ‘²w\…(Dû®'¼á€Þ .ÜîKÊÅs²Gf¶¹Ñ+ïR´ñ¶=ÕMXˆ(!{Âö$Ô=žh›HÚ{£‡¿$Ó4@ÎSœIr<ƒˆk»S]×­Ü(¡Û±øµ[c&9NoNOèÐjƒÙ÷Ó3Â,¢Ú6Eâ µª9Ok-9Ï‚Ëù|~]×EkCPU箂å¥6w' ³8>a,¹p‚ìSÀ>æªÜ†3âøb’bƒ·43à{äÀ+7 " ‡èÔÍGªû?ˆ¤ëõêî¿øÅ/~øô1øQ}HaÃp#Çdæy%”‡Þ8.ËRK¨=`«ÅÁñLakdï#õö¹ú@^Â.trä]Ð߇ò-¸Åz[k,³_µÿ‡‡ÇC&²¥ŽÀ$„ޭ"mgèsX˜13o‚D4Ük7¾[d'‘$¬êf*;Žq¨Z ÂÌŒ2Käj0}&ÉÆJ¨7!Ê ÔF{OSJ½»‚¯¥Ô¸3@·„P6>Ùô!° P-æÃ‰—µ^[;/år-ˆ´.×Ä´\¯fúæíÛ§ãS]¯µ,Œ¤îœ²ÈÁ @ËhxçY«¥tP­Q&»;³„™­›õ\¯G™Ñ,ÈX£ý°35è\YfÎ’Â 'ºìàЖàæè Õ¢E%) ñ<Í,’D.̳È÷ßÿŸŽÇò–—Ï/Ä]3R$ YO¸.ËùzYêªn=¾×ë²Ä0D+5çüæÍ[3æðhÅAVÔ"öçñxŒlñq•FƒÅ½Ëxt JŽog|4Ø:ûâ5 uRÛ¹§Â­Ø}q‡“|¸·oö çí0 A«uw÷Ö9¸­Æ‚¹S³ÖúåÜZzæNêÉÝK)ˆ´)$[˜¿ß%ûr’q‚€ÍLA'"4?Ìóóó3 ]¯ïGûH¹˜I7•Gs…ˆŽ§§œs p§ÓIk%&&¾.+:x¨Yš÷%jêZÄʯîÛý'â`ånXÍ]pLj,·[ÓañH psÿæ‡\îƒ;€×eúøÃG–%‹û "“½±¤lð·B ÍÑE¸sgÝ$‹Oׇ4Ù݃ëf`CMå0¹kÀÞç·~Ë}¸¿ûà¾-Í}‘øÕ¥¼Ï_n—:·½ô‘4p•. Ýu€Rê¬|'qóͧ¸SÖE¦išçY€L-üYât7 u'ƒE¤ÐiL»ñԞŕ øèJ£w1¶Üã<f‰Š #ØÇÈ5 Чþö‰7†Ðʙ堮 ŒˆL8¥ÃA‘žß|W–ë»·o÷ÏÿüüæÉMû$Ž5«u]×Óé‰dþÕ¿úËRÚº. «i,"ÓVªªÊhX‡Œ„(ž! £{ìk#FÜ ¯½g$¡:ðr ¾ZsÌ9ô³œˆ„8ˆ„Ä@’R¨åצîv]–u]%å—ó«‚/—ßýñÿøOÿTJÍ9«¶€bZiÓanª$¬¦×uAÆ4çµ.­ÕOžRv‡$ éí›·àPj‰±—¨V#ô¨Z ü ‚Ô6#:Ræá‹Û5±7úø& ›Ú,`°w n6™»øþ˜žŠÙr#ïÚ¶»Ð¼ÑÌÁ¡ž½I´oÁÝÌæyÞ"õÆŠ ;à‘mKöºdû§îcûo]¨~Ùãê¸6Ê,B ½\.Ëå C_lK¹Æ¡Ø¡P³ãñ'“¤TJ©ªµ5poµ„hžgdQ5Dg‘)Ï9gF©Ý“¤Tà@@°å»¾KÁq‡bShËìc_"Å̈pR»µ²ûøqi‘:+d£#á`Æíôñ¯`ÝQy4ÁÀj)€[^à,ŸþÕõÑ''5p—ÈßÁ8[p¿[î3÷]Þ¥Þ· üØúòû‡óã>‡Q¡ÄÑÈ]LÆ$Þ QmA0 _Êm˜Í,xZA‹Õû'sj­¹!ª›»Æ‡11`¤"‰˜À; ;’ô¹"áys+3ÕfjƒÖC€ÈÚ)ØTÃf¥û®:³pÊÒ£v’=Å`7Ûµš‚·ÖÜáééÍüü|]+Éützúøý¦œ´ÕyÊe-¸œ_üt:©ÙR5ͧ²–õº&ÒÖZÓÖZsë¼ÑUÌzÿ=$¸‹Û ˆ8¡ª9ôyÚàò{ë¢1ˆhÖDX: ‚TU›ÏóüîÝûZW†ÚjÖ]'gd–,jjæÂôüæyY _–KP_¦i.µ“jK"O§Ór]ß¾{{] jªNV­™©¹1ó<ÏÖb°¶‡Ä¬­}xÿ~>J-àžsº[Ïà ØÛæ…³;ÖktP»~èÙ!býFPUØé¶nº40Ôl7ïýðç}Np_d?ìÁ­æ†ÁaO’¾ù曜s|Ĉ("¥”í̈·óôôdf)¥ˆN‚1jDÖw‡oýL,I3˜½,R站ȗ‡G?u‡ÿvø¯9(¢!¹#A]´âVMÛ”“†ØiÇæ˜3‚ƒkmÕÝj-nš„ @[ AD3ws@sdÀähÇ+­œ¨®5nÇ`+rm#ì·Ø¶ öLûóvšÀƒ•‹„dàçËe õˆ±³“Ü^+$FÜ]µm­¦È)Ì5þSë¿¥ÚB†€„ÃîC­™µðŽ„3γ…AÇ"DŠ®‚4Ó¦ƒ­Ì)œjÀ5'Aìûñ0O¯çËé9fõy>rJçóym Èu©®.”âCàé&bê ‰åÝÌ„YkË$àJ„ã=’ §¢‹Awgä|»é~ š­Ö8'#”«Y”~¾k2láVymI ŒV‰ï1»q¨luâöQÝÆ{õç|´ ‚"ú˜øNônKõ¦ °¶/²ì›R£¹ï.„Û{õÄ®¹©"øþ1™Ëƒ2’Fbb°>ÁP¡ †QS<(½ª4•MNUµ5ëÞ›ÜÝ0»Q½…Ü)Œž.ô¾ƒ ‘HÂÇHž¦yr‡¦ÍÜš©º)ôilðîi˜(LàÜT›kó$&½‚æžÒ ¤ÑTñ˜§e¶ÖZ«iJ‡y.Úʪ¦næ/¯Ÿ×ui­¡Ã4§Óé´Öâæµê”§R‹“&’Dˆ—óKY_@E„¸ó…ÁÝ:Ù̬Ôbf¥n;,iO÷q<îŸlà@ s’ÈÝ0Fm‰$‰>£äñ0±t&:Îóñpªˆ²$aa¢DœDZm¦Ú†–açÂ"§¦9´ªUÁ´ÕF,9e74õ,™™j)‰§4M‡”³£×¦ª Cº0¥ô0ÓHÃpÎÇh~ü©èyoË54¶$fûo“[Ù dßÑÌžçË´f{Ì>ëÿjôx†yü°s¿Ø‰7äç¡žŽ¿&N`Mu$ûªü™ J@¿Þe„ƒÊ|÷î¶knmã×;3Ç€("¶Öžß¼Eâ²IS)µ¬ÀIÔÌÕÕZY—ÖjÊIDÌŒ¬O„ˆb “¤ˆ¶^_Z';E<òÛ„Z'¥8Þ§¢:púm)Ø8Ía”Néjœ¥Ô½ôz¯w¬Ì}]Cfœ;e„fwß8³[p€ÎÐ= òHHÿ~²ÇÖû;À;™Gà˜ÐÛÊ‚(!!ý]ÜßϬÞþ‰£±Ñ%07Œ‘Í L™™Í Ñ"›tê_ð+‚¿ÑÉ’1y ]¿¥“¸Á]#+ñ10.3tÔ90uYÌM[µZ 0M‰YJYƒ îª`£gHÀÝz&¥„èªÅ¬u—÷dÆt„#`kfMKÇÝ-ÏùùÍór¹¶VÝ|YDz~~~ÿá›išÌ•…©”5¥‰yšŽOïÞ½ÿp¹^‰“¤ N‡ã¤e)×p" Ë„âQÜÝJÖuu$p(¥y_Ÿ Ý€…çi®­ŽøP œÐ·p—ÐNp$æ ÷$â…±x9Ná²Ö²,,غy±«™©¹‚›oÀ[|SõÇßýäoþæ¿+ëúz~½®×4'qóy:ä”ÝCòÈAÕD2³0³š^–¥Ô;™)†sîá5d:Nf7áÆ!tµ#86­7ÖÊ>OÚÔ’ãIÔˆBýÑw__Ý û]°=ï7ftõvOc¾Í4ÑãuîÏ’Ýnñç¾ö—”Rö®HJSÊ@ØšŽ‹†ûí’Îê;5’¿»È¾…0Ü€\ÅLéóë “ŽÇµÔÃáð¿úU©­j ûÃ0*­˜µišTµ•jMÑAXˆÉÌ=ÀØ~¾ÆìQ§]¹ p(‹õ‹ïºÖàÀ,3Þ›˜lÑmëŒofj+`O Ü´º`ˆoawççyƒ2FLÄqBöèo~ßèÿ 2þx»÷‡Íÿad÷Çç§íùºÍæÖ^¦î î0Âû× Å/¯gÿêDBû6ÆŒ …“aHSÅC¡Ó§œˆdlÅ[æ2:4t6FÚÜ»ôŒá‚®Š ›üSç3’±„›¥œçÃ!„´tÇè#õ‘5"’(MQÍ´UÓfØ×_7X‹QÕ .GÖÑ¡Yø”20PLºº¤$œTõú¾Õ6åLZ«k(ˆê3Çàüéé 9|øùÏþ§?ýéåõ¦9›[¦,œ™Q;š)’…Y}]×Rë4çãñ„€„‰…"ïs7§ŽHBÄyžkS—wÛd#†ã`7Ò}HÝW¥îJ™Á³ Àvÿ°-^5ª[Lyù@^|›ìóŽŒuEß½ôÃõìƒï>“£Ýhì](Ãn¥—M€®ŽDƒ­ý µ=ó¸5c ‡âFawV¹;!2q­íí›wDâàïÞ¾«­ýñüüù³£#cJ`j*"eY½õÞxì[ôVûì1ú8MC•“`ÓuïqøRÅõ°piª]ËMíëC@@v;߯ñ>*Ù¯¡3‚Ç”3ãýça¶OÆ … ¤iå·«Ú8N_ÖýðÂþTˆì»ø¾7å~ˆþ˜Þ+¾/W üùÈþðOûï‰åþ)†ƒ$J,±ý˜#B& ÑScŒì«%oŒ3eLØeJc u˃mDË4ÜÕÝ’tWsmMÍÖu¥ÛþŠ&2…|l}h­h­ Œväx­÷]‰‰ˆSн[kH Âæv]A.¥ ’ ­k!–Ã4sÊß|óÁ݉¡”µÕbjD¸60ou]|ô¦´,åzoÛº5ˆ²ÒQHj­@Ý4™àx<†Ri«-hàB쎭4‘Ž+ÉŠÆ»IL4OSøGÇæéôä”ÄÜk­k­µ$Z[+e­Úж¦ÊY8‰»Æ”F'ù9ôapA >Üõz]˪îKYÌ-a½&fd&’”RÊ×eYÖuY®—u1k)§˜ÑIch4Co6†5yè2mÉ쾦¤1çá¬MoÛDA§l¬ù= |?žº_ùxòàÖŸ»å^îŽh{F í"¤,‰àó°/ã¾ î0Fð&£ªÁЂf“9ë† ¸ãM„f¿»ƒjÿ'#÷·!·1Os­åt<µ¦ç׋»‡k¶"TÀ4¯¨qóù ýµ„H[¥˜.‰^ø° Á²q¯‡6$Œd 8h ûŠ'N3S k=ÜT FÔÀ¾L»õQ?· ~À†UcÈ2Р™ßIðô»Ö?3®fû©„MõÈ84óÑüÄq:܆)þLd¿ÇtÓ¿Âa7áÏ…rüó__-ñWǸ¾±^‡×EϨµ„½ nóG0ª¯ ²Ç¸76ëŠÚ½Œg"é'¿Cp.¡W*·[ÁCODÈ`Ðbµô¡¤04@$`‹A!¦¢ÁÝB™’,&èˆBõ×zõ`„ˆLàj¦­("NÓœóä6ÓìÄ—ë?¿|´V[­žX˜pQWtði>"@[m«j%÷æU¬¢õuÈÂÌRZ‹)üœóõzUmŽzÀÄdï{,ºj„‰sdÊÑw5USÂÌ–ÖjmIØ: ñ0ϸÍ]ÍÁ©Gf‘âãÓÈVýr¹„Wðõz}=ŸÝÕÀRÊ‚2Iš§9I"Db‰©®ãé¨Z—Z:Ù!¶!iëÊÜŸá¹L[¾¿[ÀÜÐ& GD÷áø ~n®¨Â #òíÄneÜöt£Á3ú åã“줯ó ÷»-ˆqúõ;VVôÁ­”àœXG2>Šéƒ5£0R7%&$ yf ™蚌‽U@L©«Ôíoù­’%”H¥º QÐ&¡sÛ#cŽÒÀºAÿ°Ë…`ørÀD"I$åN nmU³@ú¹©ªZ5ŸæcšŽÓ}ú¬Móœsš˜Qœ™ùéøt˜gSSmêVk•$ÕZkŬ5k뺘iÎ8†öËಒ;Ф”óp9‡`'ãàG>¬Ïž‘íü©÷™rmÍïÛH$LL°kqÝ¡¶¦}lŒ}‰~5Uò«8ƒø'Í­Gøåf܈ˆáéÃJ{‡ øxÚ®¸·IÖÞÞ/ã‹]åP¨å¶‘ ýÍÓsN©¬ÅZ«Q91Ahµ‚»©† pˆú†Uˆ@24UWeÀÖ ·Z°ÆǬL¿;¸½#ìîn.Ò¶Xá;i—í¥›yÓn¡Ð= ¯ï޳@†[«ÛuJ(Ç0ôpañ×)ç ¼u3ˆR˜èÝóó/~ñËŸýôçožß˜éõzMsnÚÈÜT³¤?„ØÝ‘ *HÕðbÝÅ=èÜŒ˜‰ÝîçQQ#gvFXê#Úûr 7_žÞ+BÇP”"µpC}õn„ý¼;XÜà´û¶œ}·`ëitè9–»o¬ìY?<ò½ÆSÝõˆ08Ò€<2ܵ࿎ÀŒä_ìØÆ+v\É(±ÆŠÜ¬{ôlŽŽaè}Æwÿþâ*{« pHÔúæÇ Þû%eŸç›£yk­šµè&vâITAM€˜“psF&¤ k1‡2›n\‚hÙÇ™‹¶I0"uåt&$1"ôAúÙ˜]ZIXø‡×Ïk]Yø|¹~û£oÇùÓÀª¢ƒ¤œkk‰¹USõV[-¥5çtóZ €QJצfÎYLÕŒœDŒÜˆI ÄÁÃŽLÕj5«*9 Z©e©2 ¦­µJÌiÊĸ88 zÊ¢ÖÜ}] !SdN)¥”ÊZ&™BO\ +t}cª¨µnø9ÍsJK+”躮’hÊ Të§ÏÍ[ѲÖEÑhž¦÷oß.ëbj€PJSsvP3ì2¨1 öm2)î¾,KhË„¯@ŸÊޱþ-ßt–Z*¦$ÏÏÏ×Ë5ˆç  5Ä>΂ÑGC{"WS72u$!²Kí“ô}doM§iv÷Z[Øx¹™öûë7´ë|Ej0Z&Q±oDá¾ùF1ßyî€]ÉnBy‡˜çÚöIä~×GãæˆÔeë‰H0æãëëë¿ÿãÓÛçRÛÚªš!ssocbJ›ºÃ<ÏBƒ‰ˆ½O ¡F¹\ֲƵáÆ/2ó]ï:¥ÌÌk)ÞÉ|=1KÞÃO@öôG´ú%¿6£>" >@WÝû`mÑcºK8DÄ»uðØ%ßÒý9qÈÊÐmœf_­Ñ¾HÃoÿLÛ =§ðÅ×CV²ÏÐwÏÿPÇí „Ý3;ù­Ì Ñ¿w­ðX§=Ïèæ¸“DÓ|DâÈßSF¨­šy’Î’dæ<„etZCÜ‚SÊSÊCÅÒD¶Ã‘|HCϲ+ËwoÉ ÷i·nAÂp óLf7î6åI­]^>¿y÷¾´¶œ/OïÞ.—«¹___SÊ“HWaeJijVU+3§”/—’§SšŸÓtZ×K+ÐÔ!†zŸ–œ‘út|ŒŒHáÂÈÓ"º‰0攨×ì= Ô“S" u5³¦Í­…±”ªš6m [mn†cªsžçu] ñx<.Ë¢ÆuaûׂDx½^ß¼y>äyžçÖlUEF5#Fk–XˆÈÕš¶Ãa6€iž—ËâîNp½^ܽ–2Í3üæ¯~mM×e±¦<¶­ˆÇFcoF—%BgüpËHÜ=ЬÀE‡nøØìÐõÎ#sßWÈ#é-vD”ÄÛëBWpÔ} ¾mçiš‡ Ebü‹°æØWÝ‚=Áï Ø?˜€o€~‡õöðË]¼î–Š»È6þmÝ‚û­É‘³Ç`p-õº\_ϯ¯¯—Ëuyy}Ä”Ò6ªª‘!E+‹‘ÐÁB=:Bâ®ÚÚ(б›Ó…FßFybi™jÎydQ,]#Mï#Qpnïuâ­ë Ý$Â>¤ŽS…!éи'¶n¯òjoŸŒ>‚wÙÍžð@êúŠé-¬âÑ÷€/búî¨x ë÷Ÿ=lã¾û2Üwì<§[ªßÏïOöôDD¬Í<Ô”¶çIˆ“9¨yÎs Î}G*ä,YDX²›ê [s3C`ìU¹õäÅ OÁ Ú¡: ÛÒªù6 æžDRJÄ¡G¢]A˜‘¸Ôrz:9sk•Iæã —eM’®ç«–îe­Ä’$§yJÕV×e=NOÓôl—â?ý‹_ûãŸ_>µåŒ®§Ã¼¬k+õô| JP?‘ún…øªî.C– ³7÷ÈÄ¡¹9¤4Ïs3uu"¬µ„RRÔŽL„DYRø¢q¸QšÍólfIÒétj­KoÛ:¨jJi —Xk!ॖ^Ôš5BžÓlæ‡é0MsmM$_®ËRÊÓé´®kmõíÛwÇã©5f&Z/×ëåJH’K«]H oËx¿D)œ}%Òí€Ô"?V»STÀýn»ÙŸFêѬ[µÖGkmãð|uCmgÉÍ}0[öXÍ&껵‚ú¹=Õ&‘¶gï¸;!ãèÞÞoÞûœ„w¿îî4’ª/s¸}”ï §MER¦e-,ép<†’§”}š¦.L?˜k­h¦æ6ˆˆn]Öqå¡#ÕûÍ€ÁoWÅ̸—d–·‰8Ô«:’póûZdßcjã.Ü㻞ÉC¶{;îwáø. ÿ™seÿ„ÝŒ†vzîãë6SwwÒlÏ20,ø3__^Æ—'Íöó±.Óùþ¸É‡ŠåÇo!ž¼«ñl¿V^Í5{YgK°œ˜EÍ(O™„K©åzA@f@É"¢`ÐTÁ-¦›ºV¥™ª…D8"Pw”[ô¶Îo˜¦"bXÔ"†F±…ô4˜{«64:˜£¨M™ šƒ€sF³q œx-ˆ[16bÎÄ©¼ùðÍø¿ýû·ÿþÿóÿþ•˧)Q-+¸?½y*¥D@÷Pì´S¸YÍDTäZŒ¦±›¶´±`¨:GÓb­+ æœZ[e“Ï&Šá[ænœÖBíOk‹&[3uðiš@µ{`#¡…òáÛoʲGIª6@?‰åû÷ý×}yyEÄ××WN)ž0ç¼”òúz¾\Î9gæCž ©®Ëêca]{ Ow#`¨‰E)u#|Ô1'Ø2ñmeÞñK`Õ=¸ƒ¾íý(Ý6å2ø"%‘ï ÙÿâÊa7;¢³û"ûá×a´Bý¾áÕšoðô—ût{Nd‡ßÈpûÛgrî>ÏÇ’dæRjHº'ÎkYB ÉT£ %«F§Ð« §Î‡æ­8ïŠÄˆÒC„÷98¯fÆ;#6&N#m'2ÚåûȾÝÁ¯F«(¶#씣•²£¯nS¸µ¤aw×ö¿»‡e¾|ÅqxÀxò;â}¦o_½fØÁ2ûÁ„{¶ÖŸ¥®?<ŒLw5#‡•1ÖnpMnK?~D°û-'è}¾NEµÑHŠÜ„™Ó”[‹‰5"âZ[-­i…ÞÊ%¹„𳫹÷ô!´–1úª #rDÚÖVCl”mëäKf‘IåjÄ è×u, Žºª>ÏÇëåúöÃ7?ùñÏ.kùÑO~üéOß'áyέ®=½y#’š²5?==kmàUëoÿÏÿåïþ·ßýý™3B-D®à`} ‘|Ô] 2kha˜>ÚƒÑ?°Áe²ÍM‘B½„râV M)ÇŽUÕP/H)æ¹i£0º-nÚ+¡°¨Žô3çLÌ××…™%MÓéäèµ4×vœ///ÏÇÓ_þå_þÿþóæ$àÐT‡C’t<«¶”²7c–_þüçúãsÎOÏÏ’“ª–ºÖ®}fxß]ì Ì–ö¸›7ÓžŒ‹ˆš! vÉî›âXŸ}Ùé¶w³¯NŒ¶7a vöo‘ý›tŸîÇ8¾Á&ñl;IHܧ}{óËäÚ‡˜9Ó¶*¬ëÿ¶W¸Ýâ@¡ý…úÈ ï¼‰ý"S ©_pbF¢išjQ!é6~Ñ Æá#4qù&ö[í›ÀTDh&IDQÞBD‰‡ÃqTÞînÌ(ÐÕû‚9ßGíG‚v7!é;‰N¿g2m°Ì>¸c8[~qS`΀îO÷d©¯)÷Ë.PÚ&*}{¿ÙogÏ3jïÓã¶O÷ ÜIñáùsoaX\Ód¼ ¡ŽåíꉆÎulª¡šÝÏ'tw@vwB‰¨ˆ" îyÊÚZ?ðÞ$q²¦f ÃÏ]»¼3àØÇÇlC`M»ê7$GJHBœ<(û‘ÓƒCß± O‡Ï¯/Dèh"àm¹¾¾¬çO‰´•ˆó”™e].’²uwwÇÎ2UwãÁ¸ š»*tÐŒùÐÚmÕÕL«¹ŠpÓêꦪMµ) —u=ÌóæoLînj)%÷nO=ÏsŒJ.ׂ‡ù”ršŽ‡ùpUmz˜h`ÍÊZ~öó_¬kYÖrzzÖu}:=óíw¿ÿx8ž8±0k«,ùr]^Î/˲„rEÊÁ<‰ä”xŒŒÇŸ:ÆnØ´yŸvˆH:ƒi'\ˆîÝX®{,ß‚»Ã-aO)øfË· ²?|m±ed¶ä7KŠüŠ€ î ìø<»Í¨›¬‚Ù]§”‘€‰‘ÔºAÐÆ…ü² ŒˆˆhwÝ× Šé”ÐØ¯}–k©9'"L)Ïóaš&w#âwo߀{©u{ÑŽqiÜ+M9¥H¦Í44Ñn_qT8€pxEù0‡yžô£½¾|Þ®“™2 1ZLÕÚ–gïÞ sbtÛ·íÐë$^óonŽ1i}ï̲ûHn°Zl¿‚6çYß5!¿¼û·¿Æ‹Ü>§xíë‘ýË€¾Çûû«´wc>. Zö[Ñ7 Ça;”™ø«…ð@ÿcqlS@$È¡EÎŽ ¦ÐUdž+…™!±ˆ¤yvw"N9…„4„m¼`Lša[¯àŽ‚DÂ-9O©µÚ¨Î:ØFÒˆ9XäHH X€(å9ç™$9ÕÁ¼™"qX"!:"SIoÞ¾-UE‡ÃóñéMS¸¬«£ BP+î–Dܬ™¿¼¼²“A»\ÎêõÍÛg4m— 6ûüýï§ŒÖu§µµe9¿9Z¸ŒçÁe _Õa£Weót-Z±j&Lî Ù¼YÓè'a9ÂžŽµ6B@‚bV´XSUÕf rÎ+eYˆÍ”E¼K.;Ïš„ Ž4ô 2÷mëî\lóƒ£!Àž¡ØÓ6Ù[ÄÍÞNÚ¡ðºW©nxdÃnoާ²¾B¿Ú“Û½â†ÇYõžÆƒ÷‰æVI‚n¹Ý˜³¾aû‘&€ÈXj«Öjkµ)E®PJ)ËJÂfÖRmÀ)¥œsˆIX33ÆF"Ùo­á®Íãµ"2Ïóùõe‹<Ì”X¤{~w«6³=Û$ º”rJÉ´Á×îËöÃívÜ>ùÇNcdëQÝ®{ð¹cËü7NÔþ°€®áîÞE|Xˆt½íO/bwo§ìíÜïßÅW«Â‘'YжLvŽ}ƒ´ûœ6ŽégîUD1³ËiˆGl ¶˜»élÕ°Ûûâ².„”RªÚz j9M€¸.… „‘LƒØê²®Ü¡åW¿NöžYŸC¤t‡°²‹òƒ™%Ò˜B ÃÜXˆ¥ÖæŽæ´ª¥<§ùðîý·ï>|xýøGnue¢Öš™'™ò4Y-¥, –fY®K[×Cž30ø ZA+‹ủ­5ë5OŸU!ÀïännƒÕ!¡îÎг3‚n¡_" jÖ4 »»ZYë²{¨ËC æCYWp?¯—31§œ×ëQ÷x8‡ÀsRJ ŽN)%–d)'WŸçižæVê²,ÏÏÏî^Ze‘Ú*TUSDúæ»ïš39z]××뵩Xm˜‡¹Û9Ä;Úêún¶nÛÌ¦Ý "Ôºh«¥§ÛŽëmàÜG&{é"´…KçÞÄËFÜØÐ•ý¶Â²<:p§yï|í£=»&€Í9+FCâ<Ûi¬5íÌ®¸¬†ÈxS”Ùd"b×ÇÞ¥¤6º,±®‡˜a}4–;úßç¢0O3@@äRK)e_:!TzZk9‘†G€©ûMkl{£þÁ´‰ÉçÚ;ŸÏ{6&¦žÂö~‘ª:%#jyGÄ”$%©¥ìbÙö6oÓª¦»V»Ãöm(Â(ë†}D)æynuÒ*¦Éðn1Åœì4K‘óoÿúŸ÷/¯Ÿ~¯m5SöžB#°ª޳js«äæÖB»EŠ6BdDp“i2$2vfI#™»V…DȘD@kK)q’¦ÍÌÕãB“LˆLÈ }Êbq‘ Œ­U$b™˜YK òi– @@ÍЌƒܕ„Šª"˜š¾}÷\ZQmVKbLóô Ïoßxùöý‡—OŸý¯}y=Ïó|:éôtj¦9çÏŸ>WµãéDÌ®úúòr=Ÿ[ÓÃá¤uum"4fN,IDr’Ô´å)×VÃÖ‹…k«æÞ#Ah¬·¦‰ SJ×ë•»S ËVÛ†)"~äJ„ꦮÞ¿v«ìaXX)×ÖRʇÃ1v}Γ;„( ªÞµÌ[àø½K×µûþí‚©£ŠÖ]€dOy¸iŬFPo°µ:—!‚HÀWÎ"jøgOŒa Ñ« ¶KÀ é÷ 3èíå$I8Fqá$L‚­w[–ë<å$ÜJ¢uY…å0Ï Új1°fÍÁã¾ÔRr œÊOÇcYKÔFA£t·~ñL€jÆ,iL@Àþt…Œ1:>Î>ØñðÞÝê!ùÝŽš}ÎÝo¥ÓrT5ìTܽÖF‘ñ5ÏèægCëò¾÷ÝQ¥¿JNÙ}7ò¾:° ½ëºø¾ØŒfüõn˜¢³á6"5ÒŠM_›‚q—ຕ·ÛMÛn#³QO|‰Ü=¾±Þ˜DB„E[7¶|:\›"! §”kmáÀ Eß?¿½¾¼>Nî`j9›ÅTŠÈÇ?}:/ç 3¿¼¼äœóüþÃ!>_.nö³Ÿü ˲¾¼|&DO’Η‹Yknѧa¼Nˆ:ìc¶Öb¾ƒxØg#¸óFŒ„·”<ˆzk-!®³åÚÑØì¹`‡]-Úç-†²Ó(÷¤›oþ9ÛXiqbd»Üh`¤†&‡xcñÅóoJÛ·h€}ŒwÜ[àznì”tCÿy+ îÀ÷‹æ.žÄ(2’ç^__ ИíNƳEï¦ÖZJADan¦­5þÝ­µœó<—eÔ8Êå]·«ÝÁPŒ’1Ø£­7wƒ›’ÜCãRÞ¾yãî5(H›Îü™¯½óáöÞ çÉÌsÎOOOññúú"yf ûû4>ÈÃḕ#8ò=‡©“;¶¦àfÂLDjæŽf®­Ý&ߥ;¶Ì-ØÝF»6ÍOwÀŽrÜÎ|jØ­¹ÓAï{X0ÔÖ‰ºæ—ƒHòÑ3‡î¨WM„Å0i$ °h~ ßîàf`´#¹!T­Úx %h®4æîÖêþÐ$'$njSšQ[„9ÏÑHŒ±%!a$èP¡£©†Ï¢itNɘ§”ç©ÔZ×ÜŽ ëZ±µ àœd-k!”»Õ™ªª©I ›H"}šº‹šS˘0s$ìx`J Ó<##‡"‚j ~i§1ôBøæŸSÞZ…­UWkµ‰ðñpz÷þ-¡ŸŽGfaB5«Õr·ÃܪÍ9[©É)!gɵTÎùùÍ›iʇyú7¿ùõÿåoÿöû?ýÑ´›°˜jž&U}=Ÿ÷»ßà¿þW¹¾\`š&Iâîµ$RÓZëéùÄ’JY‘è0Ÿñr^N§SÌÓt fJ)çhëuþI }µÀ¸á6týöý;5 ã:ÚžˆßZ Ç7Ûa²†póc¸e:DħKäf:d³lK/6CæÛvÞ´¾òµÃgè6v¯~CÛnà­}Íld;ÃÃ}Pàî7ûmƒßŒÂï®0ÚòáSgH3k­¡31 ÖÚjm(¢æ"àn:°PJ‚àc(=8Μ¦i"p4ƒ”“ª8³ÄǺ%Ù±—™$Ñvöâ½$aD¥­×ß|ø€x€RJ‘ZÞ@«Ý}Ùòýû»ëÆê™òáùéÍ÷ÿGÖÙ~ü Ã?¥‡þ~ðôu³{TgƒÆ,~/8¬çaa]jû†ÉŒ Þ° ¿B0†¤îWCÔÛëéoíŽõZ–ü= ðB³쀾i탻cóÞÿqW³¦j ”K‰¤+ªn G½4µ^¯l<‚Ž ¹™¶PŠRZu³tÙ< ÀÝ™%UG& ƒP'‘ä<%&!@p´0˜AâÄ^ ”â}ÈÆÌ,)ü¦Õ=(RZ{óüt:Û²€×„úØ•­) ·¦nV[%”išRšÞ<¿ùéOöñãŸÜª6w`2î1Ò5îC˜:š[-‹«ç)—RÀ©š§<©9:„Vm%ô–U›H Wñ,)ñaF¤VwGðœ1O)³HNy9Ÿ—e©k)¥†DZ­áÖ†çßüò/¿{÷Íå‡fy½^%åççgÉ)­—ë?üïÿòùsØ6±ðá0_—õõõ5 ½Ã<—uMÈBÇêuYæÃEʺ.­”R¯Ë5¥MS6÷VkÊ™™—eqs™ÒLe­9eÓööÍ;Ø,aFy{[ç8` a^Ö%öB¸î#àz¶~dë[µ dØuGo‰ã¼à˱í¢|…ÿVßÑ(ºaäí«‡ÿ»‰“±³F}00€½p1âŽÿÁ=Þê­®ßàÿÝ– ë˜Ù4M)¥Vk³jµÖÄôáý;G_ËXô´Õ¨ÜÝÕÜL›ÒHv‰xš&U›òüæÍs 79çMý»µ¶™Xm÷„9eÂ[|ŒàNwz¼ýCÝîigïG“„9uôv÷ÿu»Ûìu;e! 5£eA×ë5Úw·›~GvŒ_ˆâ¸õщ»* ¶Woª‘,‡s„™ÑáxܺÉÛœnäyð•¯Þb½½»wç!޳‘ˆ·ÿ|wÇl½3e ßdfaNœØÁJÀDÂ,ãA!¿tZ7F¨Ñ ì’<Œƒ‰ÀBÙöã„@Ø_X9#E¿tȘۮGD€‡ªwp,‰blqš&u'`RmHD†`àH l³L­GÓøô‚fÀÄV#À­”ÖÏyª­5k±VBm£ÆÈ¾$ÂÛfèâ!jFÝ‚½¯ïžxÛ¢qŠ›z®—Rz•cz>¿F½¬8üiQ„´ÙOGñÔZËY i35kÆÂB”„gI×˲,ËõzEÄ$éz¹ž__N§ãùÓç—~X.Ëï~ÿ{#à”éx<Ʋy:rÎ///—åúôü`øþûà5¦”Yd¹.O§¨#Ñ|8£#~~y157Ky:Ìx\’Ê!O®îB’%¿÷6±®çkð#÷‘©OÐÍ=úRÄËuNqom â»&ò(ÂÅ–ÁRÀ}>|hU­†ß½škT“3ØÁ¢ÄŒØ;Æ`vñ{(U*ìB-v+ð;qùí4n°Ì]m½lC‹¾iÝìܽ·sh{•ÝÁpgÁ ›1QNiʉ ÁM›ŸŸˆ¨ÖÐVŒ4ßm6WçiÈÖÚâ®þéû?^.×ÒŠšÖVT5Da'Ë…CrÚÞI4ˆœn:îÖ €‘¦uäAUCëà!Ýê´û;ÞÙ3ÑA %ÒÖšj½•Q{Ji|¨ûÁãÞ¥A³¡é "<3k#"Ñóóó/ùËÏŸ~èܬþ:ê_¡uÒ~QÝÞÎã§ w$w]& +œ>ž· GWÓ ûH'Ba h˜˜ÙF/´û‡#cg‚«#8Q‡qÆ@)b¸©©õfŸˆƒ»:`èGg`fàñÃ÷wnñ‘´A7al<?–Í<ϵªƒ31µj( iXF29FAÜZ«Ð:g‹ØÝSÊÎìÂŒêÞ” æ)׺²¤FÉ‚Ãî¶® €ÕZƒUiÞ†Ô±ï†Å˜Ó´}RmmYWIyÊù§?ùÉ<Í///)§O¯/Çç'«Úl>ñº¬äp˜çëù2Ísiµh[Ë:A9=)g&Ì)™š©Íiª¥Ž'DTµër=ŽÓ4MS€æQ Ô‰'IDâIX˜AUO§S«U[¨ÝÚfûpwÞ¢¹ê·ÈÊïªÍºÛ_7” ºÅÙøÚ÷-|oéÛAã‘Ó⢶-ã²öZ˜¸›ÇÛôúo·—o©.3À éÝ2÷¯²{œ¹u#Z+îD•7ÁD?Ÿ_# –²nLI©£UãðCsîó¿XJI)•²–²‡e¹¦)›iʲÝÉ~jîî0#K¼ç`XD7£©2…$,§4§4™ª3§®ÄÑ»%Þ;u»àýç7šãw”ð H›“ºCÈ@ÇT! Ã8u£]ê;±‡¸«>t;1¦-¾<óÝ=^ñ~Ì4vùõ|v5èîh¾o¹Œ+¤ýb6⃆~#ªG(è¥a¡FC•¥Y‹ùipoÖ0ÖY¤Îàª^[©àNnÞ*šön…G† #fn€$(ɃCdVsÎNSu¯æëºúœäzþ̈)çf r<ž§ir³º®Êè ½&ewr@¢„$v¥” êªYÇ×µ‚‰d­öt|Ê"Œ¤I<¨´†`È$)ÏÕC9ˈ«¶i:SÒR„X›†jù"!—V…Ü…9O1ÕÚb*‘´UpGÅIæÄ9§éº\‰¨h]JæQBdS07"‡é0Éœ9 ˜[(@§$Çî êÍøë>Yö-ÚláàÚä×;šˆÚm|dÙ#È2%2 cŠp#d" ð ±ßâÍv`löÏ‘ay÷ Eßi¥tè'ƒGë}L¶žµV¢ÀEa$d7ý2óJ=wìvÇîñIJYÕJ©(’ˆ¸5­­ZS·ƒ&:ìn`çD†Ÿ­µnÍÅUu·Mâ}[¦ßQßA(°²sžÞ¼ys:Üýz½2¯x8`¹AæùJ“v ß»>>ÿ>wˆo¾j¯u{†}Ý·#G9lƒÑþxµ_\Òî9¿îÀ÷åUÁàÎG1ÒÛ¿ýùÇ[ó HÛ¸Æçé¶Áb½Á]\4­AøQ5dr b2‡R›0jkZkëfpvE©íu`ÒQUwY…Q‘Ç8Ȱ]ÞåöxèäÝMöì6.ÒíB0ujâ(‚vò v¶]Õ½ÐØ-Ëz@{¢²ƒÁFÿR·³Ï yW_Ä1¢)Ãx‰Ç«@Ím¡<°¶wÒ/úò{ Ê;­åF˜Ùçñ ðÖgð!C,DpÑØÈ>™´õòÖÃeÆÃ´ÕJHSJk’N¥TmÕ —oˆ@LÝ %¦ÇVQwÉ®†€‡Ã)IÚ¢6²ãa.­¾œ_‘EÔLR"pB`BsmMcåÄì‹9KÊ3Yë8,¢©©ƒ¹ðæzxò©«O'è¾ îòIÜ7`aGmÜm´[i¾… xX?dÇ|Ú~£Ýèè½)Š6zg‘ò#3mdÅ}Ÿs î1\ýy’ý/S·-+äœØÝº–½¶yÔû''0Õ×A“‡›Cð˜ªÛ^þlçZåþHð¿eî’§-Œnu̘EÙ{BK88ïïÈ>®}µç°518À¸m3›)Ü?I|wÁ·ãzÿŠ»²ì‹·µûù€a69Ò½Àï ópôûùe¡°»I7þì݂؟®1—û×Ýãã£2w! 1Ááä ÄÔ;¿£+"! K"N ºC’§)F€DÜœˆÍZ­%æ1*QÄ^˜!1K¼Ó!È7>JàNÓLo3¸´Ó”ZmœQj!AWkMœðx8ÕÒºh®j#bsw,µvˆG+¸Ç“‡* @Ž‘rJµU ÎŒËt855s¦Ï®ê$‚ˆ$“`Þµ Z(ú†c×FbIÞûÛæHç-$JÂLÝÂN»¬- jš« mñh}‡ëwBóZë7ï?¸BYËéxú_þ—ÿ¯»ÏçÖjï' ‰Èáx<Ž—óùåõóùº¸"^®×Z«ºMÓdîdnÄ|8Ò<ÑùzNÓD))¸dq€µdªu¹¬««Fkär>_׫¶âàK-ó”³dBÌ̭霧V[µº®kfä)gPÓ²”N•q¤œÄÕ˜°µâîÖL7`—zÿ"رJsÕöÀÎê›(‚x˜å ‡ælh~sq87Åft·ÞëÚ¥C©6àŸ1‡›Ê˜o’Š¡ì¡ë{ûWNƒZFá;©{ºÞö+ªŠ7¥»Ð²A߃‡‚p§ï×wƒ˜6)ã=¼‚;7ÐxÍ­’”¼ø,R ”ζûP ;pí¿°ä‰P0þÄA‡ÿâýø 銆C2¿£±ß"黿Q#?ÞúøQœØ¶Gc¶ï-ûÞÇtwÝ%7ŸØÝóo”ž/y8w•Äž?°ý|ûœÆÝ¸-Ê=“r»ä€NHÂȄ߉ˆ¼E˜’ßC@ÝZS@T Ã[mužçÚš›å”ˆ`]–œØ[ëÃ~ÐÕWÔ]CâÁ‡ÀpÜ-w7$sg‘VÕ»ªŠ#¢Ö:¡ôûüü¦j[®×œsˆ¡ÇZ “˜99º*I Á¸øR™ÐÝš'@dI€ÈÔ}Xƒ Í¡Ô ÄÓ4øÑOü£Ÿ¼ž/¥ÖÓi>VZTãý“²Mð¯º+†+!K¯Ë29L‚\ñz½ Ñõz%ᵔϯ¯­5$ôœ³¶úÝ·ßNÓüñ‡`æ)åe9«ª£unœsž§¹µ/Õ ¬5Õ†Œ®¾–õùôÄDnv8‘jY ™:Côy"Þ¢¹E3sL]ÜtZ†”Õ#Ç #33%&A =’û.©¢‡Ø¾mÃN·ïýèì]æý ¢ÜúŽQÌéN k¿Áqc"náµÿ+ñ •ÙÅý}¼Ã- è­ÝÇܶsG³Ù_íÙwdc…vû倷“¤ûñ«~ÜìO[–4t.u´×"Ïó~CUQÕ†w×öÂ÷çöc | ôa+¾¹ªî §»ð}71|×wÝŽ©ÙãVÜéúî1ô±ÒñßhìÞ½ÜWÜÞ"„WøÝÇ÷Ø$Øß„Ç*Œ0²ã‡üˆØ ’£Âæ/ìîNØ#ý8v‡fÝ)!Mi>>±H’„‰e]áTKµfŽ`Új]%` êÕ‰t'Â!?Ã/$zEˆè0L ú¨ˆÄR›Ri^j+eSu8­45•0ïe"B–ऴV„°–Õ½ÅOL]D9¥D$ê­¿sScI’!K>8Ð÷HBërUm­V3àœc#!‚:‚Iâ.ÁÚýyƒšÅÚ€s·>vss' ]ì®.d®àŽ2äÅ;% :8ö¿Yü³ M)xw~}=Ž/Ÿ^çù’\.çu]SšSž–ºþðéÓÇ™ùÓÇóœ ÙÍsÎ,")™# æyZ–…™Q:òŒ£eYÂùÒÖR̬–>}ú´,7g–$Ã"ˆ°ÖZ-ž%¡C)k­ ˜rNfˆ°¯‡©”µÔÕLKYÕêùüÒ´VÕjmmÕÜ[Sm Ã"í <†7,ŽË Îò¥}HÝ1§”7#=wÝ,ÌoåþW+ƒ-1èVÌ,’6òe¬%è¡©oü=dÔ£A;æ͈ÈoËÍÿ2þo“¸ºÃ‡ï«ÿñFqÓÂû [„¶Ë]¥rú{èH9…VÚ.Øzpá·'æÔ;³œ°ÓúC×uÇyž£? ª9Kìý™¼åû?û­!07¸q?âr•H¼Ÿûsâ‹W‰ó+¿µ?áǹú߈æwŸßÕÿò}mOûÙ÷GÝþ(îÑœ)¦ƒ‰!ÀGâÞƒ;Ǭt~{ â­•Þ†5@4Ç@b’#88‘Ìó쎭•vm¥”$ÙÌrÎè°¬WAè !ÚLÈYnÒ7ÐÍšFI¸[=)g":NµÖœ³ªck¥VÍÓ¬Èm­§ù "njZcÙÄ ©¥Í9s¦D1çÔ% 8tîslÕДÄOˆhûð0ÍŠ¸®ëúñâ ³üâ?ý‡¿ÿßj­Çyçup{‰LÝÀK0k}¦×=OS’©ÖVíjn®ÖTÁ\[½"2#u¯½ØÿÓ4ÕZ›j¤IöŒ Ö˜K&3+몪¦P—Ê,ÞôZ–Zê_ÿõ_ÿã?ýŽ™#¢3ñº^ßœN—×sÊÇoY.çÚšæiÚrÌ———§§§ªíx<žÏçëº"SaW{~z[–z~¹´ZéÔæ”Í2œ¯g8æ >¿¾¼Šdw„æ§y""ˆgv3UÉ ¸,K3}=Ÿó$fÖLÑÕQš2³ƒâ4MÓaº\®ûÈ»÷†Þt[·]lf]?É4pZDÄÖnˆmz|» ‰[öŒÀìÆ¨¹ëm>lÛ8H6êÄVaXSØÀ5 ë8ÝþäC)d»žm¿oØ­ðÅi´ýu«b{¶Q(`pcü܉(<–÷¬è!Xðèï}Š)‹<¥§ÈbÀ¬´Rk0®­ªi¸óPÞ»Ýz´1vïìÿÛ¿ÓûȈn°õ3!íAëFu0tê–Ü; Øæg´º8”¶"M Ä- A½ó ÃÓ‰Ü-ä>;ëªëÏÐXF©íTÝÑz;þ6'Ä>n÷ˆéD¨ÁÕ§nˆÕgp„ ‚¯>:¿ÝHš=„­‘8%‘ Hj.ÔQ2ôf®Dsù aY—V×ZÖRDp²Ðp3r B XµŠLM)!rJs­m(FWUâ`3»äˆ¦–$©«»]—km5t1›çƒˆ;jc‚b>å©,kkæNÈ)M‡PЧVbhÉ[©­µ².IÀŒî0E¢iÊîÄ(Dœ§£}øî»óuaIÓœNÇɽÎSúüò"Ž ZsήãVŒß™7mÌŒÐ)ˆ$)#amצ¥–­ù5§PÎ uOSZÈ4·fÈ”Zk±ÒÌ!„žN'sW×ëºPbz>•²&¡oÞˆò‡ßý!²i›Ó\—ò³ŸülY 'Y–ušgWèHºOIQi…ŸŸŸ×R…år½”ÖRæÕJsÕVU›Z[×ó²^Ìš* óñ0¯µ]ÎKk~<š‰üäÇ?5·º®“$dž`ˆ.®èÀ)¥Rלe©ÕÔ ¶VÌút˜ ·µ€ûœYf+vH‡·§çZV5­­©êóósW6S³R—œ“!ƒaP×½¢ï¸RÖˆõD¬à>H’QÙ÷œ(Ž=1o¡“Å®ª‡Ã!çœdÒf)‰™ÕZ·YÓj¤_eÀ…:•Ö8 ±H©5H¥1ÎÔT±¶–§)dŽúpŸÃÆq÷`a=Ê&: wvüâáÝwñx³ø¯ß}¢p;«:‚²©t+÷æÜx;F‰ºEdŒWIÑ눜w{»£uœÌDÄ»¦¢ÁWÒð‡,vÑpàíp²í!{É·H6c°¿÷F¼Ã¼ž^ôá¥ÇQsóóÝÛŽâyÿºcBuØÉŽƒj'ÞÛÓ(äM9Y¹ÿ;‚÷‰§‡ ùmb‘=Ò-Q¢€î|gš†6„ªN]·ñ8kÁ‰ÂfÉR’0SŽº:#ÝŠå¨èѱÕÝlf&@ÈSŽæÒ»wï¿ùð~š¦º®ˆ(HŒt8æiªk)em¥óáx8/×Óé4χZJpœ×Ëå¯þꯈxY–ùxˆ­t]–œóËË9OY[G„_^_ ,ål`Úê(úÔLM5fAK-ÇÃADÀ¡ÔÚÅ߈´µææ‰!&–”¸Õò‹_þê|>—RÖVq]@_בʺÖRŒ™"“SÕç7o/çËþ¬ºµO?üIúG€îÐÜrʇÃ'ç16ëŠÌÚTúè“ÏóüæÍ› ÿ›…Z’Pm•Z]Uº·V…7çI$&æ¦Í­FK€Fåï±ó²L©“=qžvÙ›½¸– }èTíåÓg5†àÔShÑ\Îg$Ê9)ص,OOÏ0ø ¸\¯9§OŸ>­kËyÊÓ,œ~ú“Ÿ©y)5¥TË:͇eY6®ÎåzE‚Ò– Ûu’ZC¨ÙÜsʵVm­Ö–s®Z[SJýÚ1³¸¹¶öúòÚ¼ ADÞ¼y£#P–bZ¢Š[)pE44'`þÉö?ýßÿÿüOÿüÃçï¿ýî»óõ\[=˜˜Y¨ ޹Gä )ùh#mxú•âw£‚ñÍ0z“G}œ‡RD ‘ M»”ÌÌ Öum­å<ÅQRzzzº.ëÆÖÓÖBf<çlC=&ôT–e‰ÎÁ4Í|ž§[%âu-DL"ÄLØ)dÄ2æÈof&·èä¸w¼ÇÍÿ\$ܳ9™ \Ë"ÒÖAŽ#a{¤wã›÷,#ògr(,ØÝ÷‘ÌÞ®lŸ¹?€V_}3ÛõÝÕëšÐbùâ  AÄâ=¾ý&qç¡o8¦aÏŽ:ûênÆë¦J7<yˆTögý2¬€ï“ ûL?ˆÉáÎ`»o¸ui±c¾}­P7¾3¬Ä‘«z—ІÑ/²Ö˜\ÙæÑb.¼Ká»éPo7SP7DÈíʘÏ‘RÎót¤ÐV³nc„H„è@è­)­¥˜¸5mÚJ`/ MÐ]Ûõú£§WÞÔ8åùẋ£V×Ш#Ä„®ƒa«UÍ–eùôç֪© sÊyJS)+Ô†>eqÐA£q$B&I Ž1ïÞéõ~+Ú†th¨ô‚š3ªê”R8pM±°àožß|÷íwµ¬¯¯/sžÂjfÊSä×Õ{Q9_¦|È9'â”R+õx:Eæ;ˆøúúº–aVs:®Ë‚LÓav¢Ër€¦e¬ó.Ž~[Ý(5æáÕtYÕ~2hÚrʉåùééý»÷üøQ’äœæãüéóD”sZ– t=ìˆeÆÉ×ëuÎÓœçVÛÛçwSÎÌÒj=œæ×—OœÄÀ/×kGùj %çx/„üütšr&$¿¥™û]@Ä[”7wÕwެz“ö33b ÔÃê'¥¤ÍƒbôÍ7ß,Ë€)å7oŸK)M7qʾ÷â¾M9¢©šj(±4O‡@ê‡ÆIoÀû“H¶©…6vß]@ð[Å¿‡&üsÿÍ^àl{~Üà‚zt§›¦÷íy˜EpS3€ƒ§GÞÝ×öò·!L»Qy¶€ü¹ÓceáŽ@²CL™~ý׎NµBG@f yK sæý#”Ö Zín«ûÍ]oß]Ù¿îîä¼óWú2guçiyØÎuvcÐ-vsÁÛØ«„ïv˜ßh”€Ä„") K¶C9âØ4eG7Uóo"rŠ.’aïªisÓÄÉÝ{Õ áÁ!C ¯lˆ ÅB0¤©ªÖ¶š6"`ŠOCG55÷ÚÌ͈Ü[]Üêj­CY¯µ¬ù0™£v…lŽUlͬ6Cæ)MCœ<Ì ‘iÊw•AMƒ£y½\Aµ¢9 ×Z¸O`# xV7ýFT‰ûœóÔ3Ŭ»Ã4ͦ&’(åŒDH|˜ªVJ›§ ×åúé‡âTlM‡#.Ëâ’RLx]®×y>‚ãÓédê)ebªµÎ§bk­j[ËÚZq‚4%u+µª¹¬ZÍÖu%‚ž(Œåk;’QÔøårvf6·$r:žæyÊ"—Ëùõüz½^–ZžžŸ®ËZJq=_.MÛa:8hSuw’XZܹ,fI¦§ãÓÓá¸\×ßÿöw/ç×ßý៛Ûùrž‡}÷Ý4~õ«_]ÏQ^xkMD¦œß¼y‹HËr-ew ¦ù^ªøÌèÐ>÷ "¤”ˆ%0JRó÷¾)µ¬¥0KZK•`t¨º¤Æ¬¶öt:yÐSJ§Ó)`"IS´:ãEÒét<¯çs·0 ÐnŽ_çL[7b‡M£8Æö“Œ·àé“q›GÇfóýTÜ"ähÿšìj@¶ã?æÎW äåýØMCÝa {Ld3{üº›nêÛG]óEVp»_9<¢#ÌÁ×É[2î÷gÝ@œè¡D[cw—÷ã-“ÅïÜEÞ-²ïg‰È ðéîKÐ'&|co‡ŸqÎS·`s-µ†üQι©R Q75\Ö¢æA¦ y^3¡ w^®ç AŽKSÕj¦2|F·ðží¬3öïwÑãn‚÷‹¡-SN΀Á>¿ñg¸ªm¾ãô¥•û/¼ Aˆ %Ã?ßPÅ­yN·¿ÞEöÄiðl0ìÛúˆà—‘ýîØmÚýÚ,ñ×ÐÍÝâÿãâ)ù"Oß=Œnšîý‹IU‘‘a ãd÷áJxû,‰ˆ’D@Gâî Ë„„2J‡nº ÈàXZUÕ 4·²–¦C`g(Ñ‘19 S‘^s·¦’8t1 '3wN‚L’’5H’RÊ f#t`«k L»Y £w5Ô˜ÇCr)Ë"D¦m¹^k©n-N ¤4Žki”¦œæÐÛL)8JJ$‰…µZƒÁ ÔR‚GÌ’rΪÆ)µÚ"or3&2U¬­ "“tjDì &ÑÖ(:/c<Ô£c“HáœóZŠwOòèZ»©±#@Θø›o¿=ž>}~ÍÓÔª6kIòÛ·ïæù@,µ–O¯ç²®øüùõåíÛ·ÿñïþ®j]µ>==—ºNó$9-ëÕÁ§ã²^šCž&`T3NéÍÛ§OŸ?‘«¹Ån‰mÅhwù X&ø$1É$îÆÌLṴ̈jºÑÁÁ¡Ô•K)ëzçù¼^ÃÏ1Æ£zí™ÐáÛ߀j«Ö~ûûyóî …`muY–ù—)Ëút|ÎoÞ=×RZm!‰|¹\‚Kƒ£³äîн¯Ù«ê ¢‡ÁS0M7àïE»Bö#æ‡Ý=4éŽÇãÇ/,ôÃ?ò>æTý0Ïáˆän5|=§ép8¼¾žqXoF© àèñ´ÖZ+~8j­×ëÕ¬¢ã&R¦u5ÕGn1i“Š'–}Üð]æþ 7cúqÇrÎ #é@ÂíûP{¤1ݺ18÷2àv$‚mâæŽ°Ë”·^p\z«rΡªí~Ýh6÷Ó.ìß̈‰Ð3€ùÆÏþPyĸCÝPñ X1p0‡1YÞ´í¯<…ÂRÜðþÈùZÚ¾£7ÝK¾ËåÇ[Æ@Y0@7!!"C”œ%eGTs5$$ž¦yk©c¸‚Cæ©;¢a$ïŒÈDâ®ÑÄiM#SoÖÀ±¯³ÐÃB2³ÿè窺\ÏA\ ÂV"š;O)‡*1© &ɈN@á»M›«Åö 3÷pgO)NÝš ƒj­jí0OîΜDð4;ດãé”sަ¦ª¶¦„ˆÂ­Õåzå›a/™£!Bm͈èz]sžÜ”I¢kÊÌ!élæyJ­©lÖ1}ˆI•(T×ÐÍÆÔLœ¡c3—ð€}‰šª0ƒ{ˆŠÕRæyÖV˜ÅÌ.×Ëápp€V›™3#NijµÕZ®×ëùrQ5Îy«¢ÿãÿúŸÔìº^ó4½¾|&á¦ê®—åJ ­UΉ˜/×kÑf¯¯¯ï?¼?ŸÏ—ë+…:t8º÷í\-F%æÃ¹¢™ÍS`MRB¢²®@Pµ!µÖ̉J­)çµ®ÖÔBï@˜%¥Ä‰ÝINǧÃt8ÌSÓözyuòËz]Ziª9çu]Aí׿þu–üîùí¿ù·¿ùøý÷øAMSJk)+yø ŒSEa£9çCRN¡X·¥´éäà¹ç<™;3GªÎàéôüñã÷ˆøæÍ›××WïE4ÖZ/—˲^ãWâñÈln,ÌÂÇÓ‰˜Ÿß<¿}÷ör¾´VbäJDÞ¿½^KYpÎC^4šX8˜ï_¤á° ]ìeú<wÂÈñZ[Œ·9MÓ»wï®ë²/4wGã.ŽGp§~Ö÷/&ÎЕ/áft{DäF nêIx3U1w# Ü£êñ½ocøñ™õ> aÙAHÁI' Â~H!„¦y”‹_–Æœ¶›‡ƒ?£fm5m,s • Z’¨»féF®¿ÙÜW» ÿ s7U‹¶2#ÇÍ ¾km¡cýL ˆTSB`7fNótDôºBo­ ™R«žó“;½æ4i©®j­²À›·§e½`?KŒˆržÍ,‘XóÒ®×ë Jh¨quœ$™ÃeYPP $gG ¢ª-Èø­¶$Óœg--a^×+!™š5ôÖê|˜K«ÄÄÂìnÚJ¯Â‚щB’)ç¥4 ^×Í ®µ“!ÔfLiJsÅj2scI’±µÕ±CWêîÞj]‰É°wPDdžàhÚJé Ä]öpΓ¶5Žs5Ÿ'pcæiš«5uuí’gƒ Þº3‘PÈ®Bq·ºÖyš×Rrεk j#óLóœ)å÷ï?|üឦÚÔ”x¹.sÊóqrpÎ)•ó‰\µÖZ‰IÕš+i ²8ÂÓóÓ?|2ÓÞ-Ø$+ˆ¢Ô‹.’˜ Sm5NemÖeY—Uˆ´67gGž³£Ë¥yCÁóõJ)‡•93«)üÿ×ÿé¯ÿúßÿ×ÿúOêþùr.Zª®ªU[C¢CšÖËrLÓû§÷?ùî§/_./×ßýóï/¯—óëëùüˆóéèDŽÄõyš›*a$é¡zÇã1¥IÕ~ñ‹_ºEî{>п-± #%1ÕZ 2‚£ª#{kÅL‡y9L“Öj­ÕZ#’ÎÓˆN§§R*ç|8Žó|xóü6ç©®5IúôÃg58Ìóá0/Ëåx<fjÍZнuéûÈþ2;™õ-æ Å{È@lnD¤¡=Bu]G{ùF§‰e ¦Þ-q\l Öî$_€C„ìËÇî&mäA÷l¾€ÚmÜVÝ z‰#ÝÝS]‚fþ•d¹—uñ÷ÜDXU”~»ÇܲÝýxí‡çÙçìûÆò‡ l.²8P£¤õ©¹`¿3·ÖšrÞp´.:LDæÔsPWu°£oÚšê4Í(YDbÞÒ‰¤#ãkiÌxßðÖJYß`“ÛN)TÑÁÐ#ÂîÖ2 "NI̼֪ SN˲h©@YÀµÕº Ð z†½ódþNCÔ`t¸}øæ»°ŽžÛo~ý›?}üHD,Äñ»½ZgsT3Aƒ®Á$Ca•Q€F·-$ê™ ` ·™Æ1WG’(ªÌ9Ëéxh+h1ÌÔÙe7¸3§ž4ä”$Ä[€)O¥ÕøIm ݯË""S:þúßüZ„§Ã/ŸZkiÊÄl€sέԷÏoÕ4ìÖžGNRK1WQ3w:½ab 4£Öë'¦®Ìo,fï&´”S"cƒ°nmú%Ò͇bE ÉZ×Ðd'¢­ÀV 27Óµ`J­VDøÓ÷ÿå·ÿx].¥^[+UÛu½"w¹"pS³Àr®×•˜šéº.k]¶ÏÈMsÎÌLÜ |L¢Í¢‘ØZÀwïÞ™µÖÚùüº1¸c g`ÙÝ-»*§±!áúɵ"¢›µÖÖuݲÚß#DYÀ̵¶§§§ØÅñ°°ò,Âîööí›>Äi]—Ãñt:O§‹”u ]ô}¼õ€ò-°ìÇMïÊö±º»ûÿŸ±?k–%IÒ1]ÌÌÝ#Îv—Ì›[eU5Õh40U„ €rø@> Áß(œù—).2ƒAcc£WtWuU.÷Þ³E¸»™©*ÔÜÃ#Î-pŽdeŒá᫚꧟~_ix”_DºŒBgXÈ9À`ËP•S!?AXDF'/ü18Ÿ¯]ve¢ùÔwÓ2*F1œ7KÛÛ Ì)¸¿¤ðÔP=M-o í>Ÿ>²¼ó”wŸ9£:L¿ÝÚ6¬Ÿ^ÙVCÛ½Z€ÚN¹m,DWŸA[_)DP3Q4Z+$B 1P㪂 ©š˜I-u5"ÏUDé³Ï¿üßÿþóh¹”‚ª!qœ«¾}óîùéƒ+xÌ2ÓScŒPk=´'Š1ù|s04ì\KDòBû¡ïúΠávn…"K.ªõæzo¥Ô2:FEÀ‰Dv½#3 e.¼à¤h˜çYÍ8°VÑ\Š€¹Ú rŒ"r°’Í}?‘ ¼éçð36€©UUqXtã\m®Ï~éw]ŠÀtžg @ö”G¡‰1x,Bpiû¦1FPsÙE¾ïç’Á¬ïû¡ëˆùÛ¯zu½ÿÍ÷¿y:>âáøÌ±5Q×™¦Ù'cJZª=úIó™8qšæ9Ïh1ƾïSеV‘ì}#¿¯ñ}d )%B¨¥ºrìš7P{kË{üêÇØÍ󤦄Hîß&¹VOÛU+è<çãñéÃÃÇ"¹È̉ PçyJ)A ‹1‰jA¢©Ì÷Ó3Ä”b*:O#…º®{||8Ž#-#—ã8:nãB¸ã8NÓä!uͶq€Mé%•j­©›ÛÛaüSnmâ7˜#¾„ø³é¾(}?ìv;XbÃ0x¶Ñ÷ÔZÙŨZ#©EjY“Aö¢°ÑKÔ@Q=öqjÐ ÕÈÁʻݾªu}Çcð…_ÕÔ€ˆÕ ¨ºÝ+˜(1­ÆÞ>T.RTÄL\úØ-úŽç¦dH18¤Þ´0–‰1®ú€Öæ6 ÕÁ£óþˆ‡®C‘j £¨V©~¹Çqôí8α‹]×÷»þýÇÃ0 Qájwý“/¿~~¸g¤\s-Õ/ÓÍ0Lã)ô]?ÏCHÓœ —<ÍyÎó8Žï–Rª–•=‚ˆ‹x0²ShÌ-|—¨±ÆˆÀ×tŠHT‡¾Ïs%bÇÛ4/±j ,— ]SC¥”’sö©]—#"Zxj­Ìy1Ló(R=þ†À¬äB̪úðð°ßïw»ýáùÐC)Õ“R²ó\SJ1¦ý~</KüFÕ;Gÿ~ìîïßK)ÌŽóTÕ8Æa·³¶ 2FbF Ì»av{¯Zœ ’RÚívµÖãñ¨Zñùùɤâ"¥»r~¨)ß-òS ø"^¿ ªˆ­'ušÌl_°²WëÐÕ×:žm¶åˆKðQ=#‰œ÷‹½\ .~±F›÷À÷éàŽˆ‘c» ]×¥”QŠ€¹'P;*]’õmóâdm~wÐÃy “g³„:’®ú ÛÌÿep?mùüxO<¹OYë ‡D^£‰™Ï΀5‹s‘Ý0¥€°Ýúæí‘*e‘‹iu´ˆ¸õUíR8”Z¦é9&&¬>*R‰I¥6…[f"tÝàA}ÇmÊÍd¡x¢ŠúÉX–"pUï(2³“˜¹‹É=‚w»HU)*§.•œ»i*V¤¨Š© ¢šYHÌÉëî<ϹÖa¿Ë¥Š›!ƒUCp9up­¥@Dn©¡Dä~ð€¨µ€©ZõסÉ:™µ°ë‡Iæ³`‘"Nó8碠ÄìnP 2¯ ÎCDÈš æì»Ô—Zj-)¤R NCŸçYTcŒRkŸºi*‡ã"—’SŒ±Koß¼eŠï>ÿü¯þâ/öÍ·’s? ¹d Ã:M]JªÖõý_})*?¾R$¢Ø8ŽŽK‘HÛ€ *ÄaíïyÿØ×¿µÌ'æö`“çí‡Á¤e|C®Ù7¨ª¨¦µ¢!„r-ˆ(¦aA?ܤEUÒÐõ)vÞqrV:¸˜KÉúz.ÿB¤f···Çãqžç”RÉ%†hKr…›s.[cdï©øRA';ìêï/µ˜šøðªŠ‘‚ŘœS˜Rtþ{ß÷1„•ÃÎ1úP±Ÿ%§ë|øðaš&Uy~~4‘¸”c(¥Ð"h¼28 AM 6Åøyeÿ[½-PîúW[“ÐUdH+ ç"¾oãmb×¶éÊ+ãð“ Îùd\¤‹àŽK䤹 MÖÆÖ1Á…¹ñVµÍ¼ÃË¥e=.h&ÓËŸN6jÅó~…ÎýÑÇÓŒÒËeéœY¹Ídä43w¸p<ŸòÔÉU°™oŠ™˜Udž'ïÿ¸<¶lš™3Øíö»¾Ç` ¥æìô®ë»”B`¦HÄÔN Š湄Œ˜ÁÔK]/f]©~½cŒ`¦UcêL$¸®SÎ*2MÇ2MyµVBàr.U„BðuÕ`5Ž7WNô±isÉâ1ïSb.Õ®¯oÍìîînGЦBžùQˆ614Ej°—Ê„ h†®Ìç°A›Î]Êb!ÆZ„Cuù*N}Wjæ©9™øtÝ ÌD%0§Ô©èll–»J[ûAl眳—2ç»W¯æiòAv)áUˆ]úý?øýý°¯µ|õÅ×?|xus‹1îû¡NÓ¯õ7`ºÛï‡a˜ŸžnîncH‡ñ(ªb:ÍÅT‰)u.Dé¾ï)’Z37ýlH:"ÊâEUkñ@Q‰!ú3è*}߯âs.]ß«¸Ë0@sÜ,rp^“kQ0ÇŽCŠÑçæ¼4Ïs×u™0¤ÕôÕÝ«Ãóˆ "t{”7 À¡dO?Çã1—c±®ë1¦ ­—[|RÛ˜­9¢ï<¶Y„¦Öh‘‹ëž?¡µV3(R=s7³ãñà"”0OSß÷D´Ûív»}áãÇU¥”RkÍ9OÓužSŠ9ϾÙZk Ñm=÷jÀ`ˆÞä9­/#غ‡ë [ˆ{9´Æ_¥€p‘s™bn`s9©ço·ÉİŒkžÙâEg+ãû%&³ÙuÜP ׿’!’€º,Œ×mG…7ÆuÜéR4¬Q\ÉѯÎpQ“'@uÛÍ3ö¹×‹— "¢ ­XÈl¡Ð/óP§¡ XóŸBáO?ÀÔÉv 0׌µí­/¹þo$"ìR®…Z•U ¥ ¹àL»Z ¿1Ñ"f`9yD+!š€ˆûÊ1“!‰YLÇáÝ?9>g5˜§‘ ‰TLT‰`¢À!Ô¬RÚb.ÕSAÃ*€@ˆUs—R•‚`yšB`B¨%¨iSÈ@f/œÍQ)GEW¤A2• Œ»„ˆ6ô»È¡Ôj 1"ÌeCç¹S ò<¢†àb³®& Bˆ A$ûÅ 1p^:B×õ¥T$â\–‹•R«`êww¥Q8ŽÇ®K ¦VÑ`-Ïɰæ2t}ŸzŸçˆ],5Shcd¡O?~ü0Î…jꘀSÜõ”öýnßí~ùW¿zóæíÓÓs)õùp$DQ­Eæq¶*?ùê«·7·ÓáÉæºKÃÇû~Wͪš1ŠjUSt£@%çR¼¤#¡À¹ÎH€dÌhyœRŒR«KïŤjààPs$—Ý%©Õ‡ï1SN‡ Èd,Yû8”Z«jHÁÌ´ÖŽ£Nyޱ#Ž1 R‘5ü_üÁ»Ï>¿Ú_O‡aèSˆ÷÷‘¨º€šç µÖ@œ(t11ˆù+ˆ(j@bPA5Ë9“û.´ÀHÌ”RÚï÷®àYT­Õ“HOÕU­ó4 †hê¢j•<ç)sÉ(H©ãñ8Ís¿Û‡˜bêˆ§Ñæy)9Ïfª V³W´Ì!pWÔvûëªFœbìºnˆ1 qê­¨¶ÙžEÓÛ‡‰Éµ/<“ÃV¿®oÆSpòàÈd›Þh3º ✈y¦¦ª‚jhÀ>Ô¢¼{]œ”xå­Rœëò³Y(ÎTÝ·!o›ËÃ’Ñ{âìØ2™ÎÊ“[ð…ó ®$Âeé[t ˆè4‹}¾‡æÖ!‹ä/‚S—x·l*¦Ó:wñ†Ó‰k\D0×.ã®ïUÛ¤èjìBDÀBB@'¢ ÷LÀD%r !¡ÈÚ±ñá=q"R³Wï¿’A»-¢‚Yˆ‘8ü“ü¿ÿîûãñy¿ïJÉîgVkuš¬5À|<-pÜ__1S©¥ï{§÷®ÏEÈÌèVhÃ÷MDM ý*[û’ G¼>S0DF„8†j€J©(jWûýãÃc•Jh*•Íݸš›ŠIU+Í+Ñdu$ó[¢iœú;bJ½g‹ m_÷ô¿ûßþ7*òãûß6«U´˜/ì‚Ý”ºîæööõ›7ó4•Z94_rµfýüôcB y™ùj}÷ú5•R9„ÃøüíϾý³?û³ã8"Ñn·S„À¡ï{­’úd"ßýø})õzî^½šæ2åÙSߢˆ–:UQ/æP¤òÕn?#q臾ä8æyæãôöÕ[S .Áƒ¨‹U ‘L¬”8€BÓ[uŸzQu±K ³ájßï:ýÌÇ,RLn;@9WTëSÿ{¿ø½W·¯÷]ÊÓüøt_KáÆiäŠÔÔu~·Æw»ýnØ©h™‹ß-˜£óL¤©R­5WlÕãùÕìº.„cjêFs›&ãB{?õKì¬-)9—ZæyÇiGÉå8¥Ì9Ͼf6­Î|UÕnØWWO©‹±£6»¹b¿âãD3ó^ÂÊYMy&ɵedckŸ ,:´¨T]§7¯Ùó8¼”žg UGI°9bßnêbýXÞæ÷î#j[ðHúBfÝ)мaÍ;sßVÕí uÙoø„ÁÅ~ €V%bv Šš‰UÂ@ç<ζ6+€A`6µq±vTˆ1º¡¥›Þ›]›Õ¥©’!¬ÁÔ„ŸýÉŸí÷;bzøñ»«Û›R TfBj3s1Õ!¨J7t~ÃÔ\³ä Uë:9‚Ë„¢.¸Š:ìmÖ½­;H´6VTŒl©ÌH ÀþúºVË¥Äj-µ–þÏÿW_~þîáþãÓÇ8ÆèÝ”6ÁªZÁÄLZ“fAõÖkä}ÝêÞ \Ü ÷j*ø÷þîßÿïÿûÿáùðø'ÿé?XÕª‰,ro­Ûáguš¦Àœ—Ñy3ÇÉïÀ‰¨‹ãc‡«–·ï>{:ŸŸ qœ¦Ø¥,ó~¿3•Ïß}ADežk©ó4]_ß$N©”"`1¥ª2Í3ÄÈH¨"¹T"L©ëº.PPUz¸"ÄZjú>¤È1ÅNÅvû} ìl¥®ërÍMÓ0r¨¥È€} É¹‹‘»ÝÑãóÃXæ"Õ›“B$¦’µO=(¾ûü‹2ÕŸ|ýÍõÕíÃýýÓý‡ß?=> »ÝÃÓ½…wCï,ÇèôÇ’‹ŠÄq1fSGDD—aÉõ¹_¯ÂÚ{ó±¯iš¼püÓßà3M+|–ŠÑ) c(TÑZ‹HÍÓTò,¦>¾@„ì­P@ª")u!$fä®ë={¨Uj-Rs­Åk/ÂÎ64Ã&©]¡Oµõ£?O4Ï™,›¤øE\½ì}ºòøúE´ÝÎY¸ûíÅòn½ð0r;7¢Ë¶ä²|]²b.‚{{q)^V­[%–|Î3÷åêúH‘Ûé5„ÆŒ<}ãxÚœî- £[ ÿéB5à‚W j`i¡6/aÚè‰iUGZˆw¢"^G,c)Nro@-!p[ÕÂÂnZ/N4®RRêJ-Ï!…«ë]­C,µ.š3èä4"0®Z™ LËœU5—R›&0˜º »— µefþ'¯À)3Q BV·Ë4«ÊcêbêS·öWW7¯nïÞä<×"]×yRíf{õ—ù«¿þÕt<î†!¦àƒ-)vª ŽfÐzžž!x§šÖ‘ÝgñrXš™û~w<Œßýæ7ÿÓÿøÿyxü# ³›–FV×õ¼üŒãÈØ(~³¹`¢ªaS*oüfæÐÇØ]ßÝþƒø>ÞßõõW÷Ä4ô}ɵ‹¡OÝßüõ¯´Öý°ŸÇÀŒ†Çã󜳀a œKÓ.¥©T­VkêZ NDi<¡¯¾üòzw8i¸ê¯j®»¡vC©9çBL¸ÖÊ‘¥Êg¯ß2r )PË´dHjhR¥Je ¥ÔZ%Ë0Q­¥K»ãq|÷îË¿ý;ûêêªÌõþãÇûû{ÉÇiš~ñ‹_ô]ïÙðÝëWãáèßîS}è2™NÍZ¼$šÅØ2¬Ý´}]/%;ã«@­5ç¢z.ôKì›õ§ÄÑÚ5®ùµ- k˜†ª˜Šš0¡,__*Á‰dªv}sk@¸PòTUµšªHõA hõð‚%m˜-x>¤ºÇnVáiÛd¹[xã‘/Áa[‰—o~‘¹Ã “á³³sf‡ªëtÀåb²ü¾â×K\^p‰õ;ó2[±eŬÑöì`l=;K¬]#{#dà'ƒ»Q3¤†¶œì_.6x¾¦¯RöòÀ½T@@æä®Š¨ LÁSi4steùv‡=¨µ6:ç¦H¢þ$¯£ÿÀ€ÄKošœ qÓ-ÍØÖÌ}_¬ ÝýÇ© H6ŽÇâáùSX/pCDD5L}Ú Ãñx˜¦ÌRιOp;™Í0´éúH]yT¼Ya¢UUD‹H´àª:‰ØªYQ…*0ÍPJ­1¤››ÛZòáð´Û !„]ꃫRjÍ)u1¦Zª"·ù2s|B@樀)$Âf*80t’CSú^2zf®¹æ2ÿú׿yx|Vç|)¶(¾;Ào-ï¹=Èd)F§ð¶‹é3Ÿ`ž*¾zõZ•ö×·FøŸÿú¯ï?Þß?<:F:OóÕÕ5‹=?=ƒÚ»7Ÿ£aç’Iu7#³\²"„œÖ¢"€úJ)»aøâ‹¯¾ùæëF?ýú˯û˜®÷ûøáúúf7ìò<ã\æÔu€˜Rb }ßGâÄaÇÿõ?ûgßþä'ß}÷Ýœ³¯¢ÕÀªp ÝÕ R]Õ UD¥ŠTýì³ÏÞ½û‚ž ´ä|8<¥@ß~ûmJá/ÿò/bJ†PKíú>—⾞"‚ˆ¨H‡ûƒH¸q˜˜l3'PòT™|_ÖÿøúŸ°xLoq¹S°®l¶1Qq;í¶,ƒËåê"¸ŸöІ˜TÔ€8v·wwý°+¥V7±ôïÅAˆ)pÕêhjºÞ”nHä¾ië!9w]–@·®lúA‡ÈÌdµ‚iHáp8ö}·ÛíˆÑLs.]êhÉÛ Ýù]I…´ÖyÑTrf&3u«E¯#±3ÖU\¾Õ8lÙ–w™\}“.5¿J­J¢Z¤Rˆ]?ìBŒ0OÇÏ?ûüùùs–Zº.ÕZÇqŒŽãQ,Ç,çBÈ]—Šz Yù…p_ÎcS­! KU¾Ò"Wh DЍ¸šm)yœŸº»Ù»Ö;Ç=IJ®j‹ˆ˜ª'’1Žì8câ×·7OOcŠ;ʹ^í® 9çòåç_ž÷Ã>Ý\ߎ_|ñå/~÷oç9?Ü4±´ïÔl̳4;y?‹Ý›¨z ®ë‡aW%ÿðÃ÷®ycøå¯~9M“CÒ¥”û‡Uk䬧.õÒÝÍ­TùùÏ~þóŸþÜþèþ­)tC‚ªµ™H, †ã<æœÛŒ·µQoUM}×õÇ÷Ððý?>??Íyv}êøùùé—¿úey~~Þ]í]ùÆå‚Ó¿ü¬Š‚OÏ1!“³6[¬MÁt凸¨1¤å:6N°gè§ °°JÖkwÆ>\;|®û¶ê8˜¹þ§™1‘-ÙŒË~8ý¯”˜|àVjñ½nù»s³|hxÉY·…,]?/uýUYá)ßgOËW!/Z~¶ œ3ä} [X{Iùõâœxæ~vŽ6ÉûY€[¶ò 0Èõ<Úãjßq±µ¶ˆÙæ­›ø¾Õ3k'oUYh/â¢íÒŽÒ¡¥µ³Ü¦½üÚ:tq½RX!—-æ~Y]×ñWĆ¢õÃîÍ›Ïú~péj¦•JꦄH®¾|›1u®åzëL´ÖÇòE{,ío5ƒ@$‹¢$pSC•RMÔÈbLD<Ïã8>»äá4Íî‘ÝGÍ]~¸äi¥@ ‘çš„1³ÀTk13ÑŠä¶Ò¼xd¯§L§®ºnpÌ‘D”bÇÁIcL‰É€Dôêj÷üü<ŽÇaèÇc`x!)%„Às™J­!&Ÿ°¦ÆnjîŠè“IÁϰc¼ ` DL|"ï/R×`fW×»ãñ`HIÍe®j@Åeĉ»®KJ„ˆ€(µº"±ŸÀÂ8C?Ò<Ϫzu}-B@©ÃÍÕmäô³ŸþNºo¿þöËw_ýõ_ýòÝ—_ü£üOBJ××7]?ü›óoÞ¼~Ñ©±K8„¢‚VÓÂ<çCˆ‘™‡®†ª===þú7¿*¥>??¸¿ÿþýÕõULIUÇãø|x,µR l ¤Z Æã1†ðüôt}sóÿýã?.µÜÞ݉Ö\æR‹T­ž;ÔRÅ*€E¾L¶0bÌó\Kùðáƒåy¤Hã|H!~¸¿7€Ø¥×oÞŒã¨"9ça´T_‡a¸ººâ€Ðõ ¬Ö:ײ HÓ2¦ÒÖUTfvÏU_¹À'’T“VØ}ÍÙ/ÒÄÓÄ‹b­b Ô¬À¯gf_æ TL}žD*"HÍÔ í}ûê5D¤v¢¶?kPnÐëæEhsàLgydÖ4öǾHáâ÷‹™ýå{VÇ̘C\x2'ºèúïªßœ¸в]X¶^¾«mêÑ|§¹¾Â‰å£Û#Ü\8mÜZWÍS·õ°ÛYhK´À²]Etáše>}l2\A°¶Çpÿ·{›ëDTQ BìsÍÇÃsѤ¬‹A›ÕB$¦Õ¹T º®73 1IÉm©ré;$Ïå™ÉE·°ìÅK`Š!pD4—¹–ªª&ÊÄsͶ´>û>A)bµuæ"5—¢L¡Ô©ë"—yJ)ˆT캑cpœ4šˆ˜xÝêFV‹®Ë^šEUs˜¸5E3£"BCÍ`Öq&æšgçW¸®‡H Lr1]&Ð1+c0%D@EA0Ã6çºy®|ID¹ä”â«W¯v»]ιÖì,—*9ÆÄ1ÇcJ¡H !Æ«) ¦€ELJ†aª³sÝq?ìVC88 @Ÿ"‡0çlÆ·woRèj•¡Ï2”Rß¿ÿðêæîŸý×ÿüÿá?¼¾½ýwÿîßsä?Äïïü¾1~ùÕ×÷÷Ÿ‡¹äj’s®*È}øxË' ±:ÏSèbÜõ]Éó4Ó4ZÕRs×÷†Í?)ÄnÇ¡ëcŒ>úáýûZ+V³yç<1yRAH`xAÜDu)Æã4MfÖÇXëlˆEÊ\3tÃBzPÀ,ÙPsÉ€b¦‘Ùýb$ CäÃ4ÍîWç'Á9KkÞ àŒCR•ÖñÖb EXD­ÁëN"k6Ö-$Q©•™ ƒg{ÄÀL1Д³s{€^¥`š·Ä&l¡¿Áùí«U’ZkZ.©Ðê Cp„æ ¢†ÍÀOó·ÙªWóhF€Œ$LA®õ'POIµÿ0-ª„•Â<Ï9çu†øt0›ba»T^¢ðÐÀ’­ Zã/ËÎ&´ñ¡Ëͼè#¯o†6y |Þ&µóëå?EÏ_¦–ÎÄÐ@ ©,„Q¥n·Û‡Àó4u)¹ÐânBö; bx¼¼¾º~÷ùç?ûÙOòí·w7·_~öÕŸÿÅŸÇã?ü8?ùæ›»ëÛ»›ÛÔÓ?üÐ÷}ˆááñãT²¨ô»>ç7ϳ™‰ øTG ÌÆéçœ80ó\s-‘œ€”KVÕÔõRë¬PÕRk­uU„§ ²–RòN;ØÛ:ÆØõýx<Áõ ¯÷W̼ë:1;»ÝÎ̺®+µÄ ÆHyBZ5Ï@À%pÀ»?‰QP1$Œ1-šOäòÎð1¸ åœ]Š}=3k’»ôáNž ëþs›º8ïoZh~Ï/nÝUÅñôu‰8ÿ"€Ë)ýíâÉég‹dlCÊeo` DÄk²Ú²©ó7Àæ <ÃþøÝ÷ß+˜bÓ„`m©TsŸéb$Uõ³”Cd¤yž¿ýö§Þ‘QoÄsàC.3€y”­.KWkYIxà¯Fˆ]L@ *îlµÐ §qt¯AÄ Š€¥gÀîúa:ޱ† ¢ã49‚a)¤.¤¡ß}ñÙ¤)rŠ!¨«¨)äRý2“*ˆx[B‡Ãqvµ Æ%aÚ2gpQ_ z8å¦Í_Ý ¸Ü ÚeÕ¾úÚ0sSÙµ—Qî¤Ø¾E/¶‘äBy‰ý®}_ƒ`ið2sêúeîétP[¼ˆV^D´–`³«p§ˆ¥¡Š¶á{ îëê žµ¡?±(­G-2ã)Ù_/†ï„Ç®‘¶gKkcÝ\œ,\ºD¶:.Gð—üÿåM/ÿêøÄ qÖ¥¡FL]öåm­0ò´X­Å D —´¢a·§…’/ª¦šçéñáTQÅ@LÔœÖTyÚ´ÜÀ¬ˆ`àc©µÖ8Æd²e#dfr2q¼Ð.0SôJ¢áa¦Îb=»ƒ‰È…ÃM½çËžÏ"ºt ¶Œ‰¨MÀ¢³ï5…ž<£h.Î…U Ô»ÅÎ_S«¿2E lH!ECÐRü€6?ånºí »nû‡ÚD^#A/¬$ªµV)!÷Tr<—‘¥¹ñµšVAE…18¾‰‹ž¥Ê”Ç¡ïçiª¹ªsØïö¢õí»/†Ýþ׿ú5Ý\_ÿËù»»½U³Çççûïÿmºë›kêwýóxœ¦éñùÃÿëÿýÿ,¥ì®w÷÷÷E –:»$3×RQªš©2ª8ÕÊ™ã>-ÿðüTkíBŒ1fC¨Rçy^[…à%8`óà¡µæ ª ,þÞêº*rJÝçŸ>z­ðöÍ[™Ç.¥ë«ë>zLD„"5t+=‘ò8k…úþÉÿðù¿þßÿåÿƒÀQJ&SA"5¤P0eƘ9Ƙ†~ϺÔ;1¥8/²_¸i¹„j[Ü9Q?ˆØù—MÚ¾°Åq›ô@OÞé= f§pr"ïÑ¥ÒÔeº@2¶Ïó]_M÷W× ÎÞ€-s¿=Œç=ÂVbÓÖ.g˜€*³]”ð%­çŒñâú¢Î[Xqíí’õ[•ÈÚ/ì¦?ˆˆ)%çkŸ"éYŠíùò§O–ç“.oðÉo¼\ ^\«—Û¼¸< œÂ @tq¶ÏþWìÞ³äRÛíê˜+ ¦Õ´JÔêå°ßsþvRëž®œ~§é7|ÇŸ|³¡ï‡¾Ïód«PAÓbtb%’óìÍž†t°#âìFMëwløXDBÓC'²_3 !9¼ê1ƒ.u]êæy^3¬µÖâž&¢.¾š2W‘nèó\únw}uMøêöÚ)†ÇCÞïv»~xº©>~õÍWï?¾œ®wûÏ^¿ DO÷÷HȈIjSJ‘"%Å„Œ*b`.ýÊÄdˆ ¥„FZÕK¥.%·ˆ*¹T-ÌÜw½YhŸºë››i*Ìšé9#Ò2Ùžç6"zÙ´mj7ŽD¤–â@ÁÓÓÓÕõ)#B—¢_š’s×uUÌŸ•®ë@M«º¼[Î%$Ÿ¬®Î|%D# 1ÕÚœ¦JBóËýÛ¿ûûÿàÿÁ?|ÿã?¡cq1F]à„Eo‰ ËCêuØ62.©Hû¨DÌI´¼&û¸ 9^-¯Q`)h×ÜålÈ0xd5Àf@èT=;‹0§_˜k¹¶EÿGDWÑϼ³"h£ v‘Šn—.o¨.™ûÒPeŽ/ë:×$[rv×þ¿Äß7å…sdÎØ&¸¹™º®ëº«…´VŽqýR3»€e6‹ÔÉw³X…Í@©Ñê÷ýið‹6Ñ|»f ÙVs—1¯†,/ÑÐNÄO×ÐY2\v Í_Y;ÑAU‰‰‰æyf°’ÂÕPlE>3é zI®> îÚÈ!JÄ1F@«ÎXfF@Q"Š1V'xáÕh[­P DB §û4µ-~‹´‡Øt«Cð•WÕÓ-_J¢¶,‚KŒ:†C\k]”Z".ó‡ª:ŽãöæÃ¼Š!æy¶MsÞDc ¿¥›a[b:­ï§›£¡7hf©K!D3óéÍ®ë]sªëú¾æ9›ªëG ì4UC4 4Bì‡Þ¿‹™JÉfšR|ýúÕ×_~›ç||ïn_]_ß<=@MÂÏ¿ýù/~ñ‹_þõ/_¿~õýßó3GÊÇrw}ó|ÿPçv}7OãáxÇÉL§iÚï†2—¹ÌŸ½ýìùp€6Ô®NŒ!"å‡RJä€Ð8<)ÆyÊ1ÅUèÆÓA(REÔϘŸ=¨ Y{…t}ÜÄÔ˜YÜËEÅ^V‚J{°¬âJjŠÀ!°”üêö®äÒõß´b6'©m‰TL¤în®Å´äk¨bÈ,R‰(DVS'[`a<æï¾ûþÏÿìÏÍ4ÞíD*%ÃÚº;ƒ‚=¸¯ˆâò ¨g '^ ¢KÊ´¡¼5މH3¾‡m>ak¹4ûNà¥ÚÊÁ¶%¨-Ú//ãŒBûTOi´3Äœüª*1FÚº\ÎsÜmpwòüúg‘‘œ-c€b 2e+¤¾®W¸p.VóòWrKÃ6^‡ÿ´ !bEDSE¢R…Xº^1{Ѹ8•6D†€J‹5‰Gè†Ey0^(J¸Ð2èxú—æÜzPËá"òâ?= »ÛO»ê[ºRï=“'"FC³Š&&U« Š™J™ÅïC5÷ÔF§S5AĈ-´<žjŽ]gÚr$TS7¢Li*  ¢]ß‚"Lyv ÝYÔã3˜¥UÕ@Í=H}Í`æRÅLC[€¸Ô€ÌÈ•AjÍynrój*ºŽ“”Rº>¨ÖZ«€ÔRržE*rJD,Í¥Ú5¬زÔ2UјºªÑG¹LUªJ%ÄÀ. ‹øª8¹‰ (¬²šó<€He&ŽT!Ä^€h.SH!¥Xkå¼þÄ€Iêû~§¾ß×··Ÿ}ñî§)t÷¯÷×L1×:•Ò÷ƒvûæ'?ùÉ_þç¿ÎZžŸoïnßøƯ®w¹äa?<ŽÇ©ÌðéáL‹Lªruµ7€iž²TA…H€†ÝÎÌr)®†i]è¨ï†.%D1€1"Vf°Z‹{¬çœA-€ŠÌó<çÙÌ"!™Ëf˜"2@i²àjbª21#i. ê•„„ŠÄÈû~Ÿ8=>>2'´x§kÎåj·kù ‡,åêÕÍót,5k» ¡©8¤@¤ŠT©Rú>#=>~)j•™‰›8A-µ%¾N<'O&B(µÆSš#s®#c+®uYÿZÆf^¶ueÑêåF,#W˜P•õ_ ÿÛÇY|¸ÄŸ@Æk&kÐ*úÆ>7:)hM#^ĽTÀol0lË5³Ir! ÿF—ªòAÁEKƘ(´Õfäܘ-¸Ävº„A–´z±ë€²ÿÔ$Õög»*^¬-}&Üþl®åët¡|â²ï°Iîλ¶®À/ÖÕe@aݵÖmß,KÓQ±©Øv‘¸ØÃeM^*€µ ÒeoОݭBdDtxÇÔRˆKs«7,UDk"G¾ç~Ó‹5UkO‰C舖ÖI‘9 £¹þéù”3"V­¦JÄiy‚À 8xTµ…_ÌS,å4]²&0DäšK-­V\ˆHìN¶T‘Ëbޤj¯^½bâyž=¥b Nªtp 6†¨"LHh}ß•9»ÏC—º·o?~~""ŽÝR*¥2“ˆÞ\ߥÔ]_ßhµ«ýÕõþZT†aÈYr)ý0Üì¯Þøðî‹/ˆhšF@Øívd:ì¯8:ž¯¯®ó<Ønè¤TS•Z§qô2«”BLÌá8NµŠ_“·¯_ãè–§ØR "zš(º1œp³=Û VÖ&Bl5… ݈EL¬^̹f!™f­„9Df,¢¹ä9Ï}Hû]ÿôüÌ8$þög?EÄ©Œfvµß`­Ò¥r®ˆÖÐÿ–g¢€W’YúpµÖ†JH"Љ‘ÈÀ…!§œó–¨ˬ‹ß?ÐuÝíÍݪ,»SCJ7%ãbЉ¤Ð%@Óµ|÷BÐÛË íòðl>Î×Òål51\ÆŠõÿOVíCËÁ6s„†¯¸¯ÎúÌž“3Ëìtã–ˆˆ ˜“hL¥‚Y \Kf$1„B Ìè–)´rq¤Á¦zÉ}?˜™ˆºûe©Õ ]ýø$†ÈD,U¼thn!!Ä“-âLÄn @HUÊÂ"°R²'÷Ö™ÙådŸî™8†Ž(øÄ`LAÕvÃÕííë¡ßпù¡ëz©òóŸÿN)5öÝîúêp|¼x|xxýæõ4ŸÏøpÿ¾KÉ«œ¾ë¶N)}ùå×O0ôƒŠ"Ò”ç.v^XúpP­â·‰ß£Ì™maLr0³â‹\›siýýºpjq ñN(q~µ?{„€‰Å”‘©W ˜CLÉŠûaœ –kޱÿ‡ÿø}ùåWúç¦"}×íw»ç磂š(¨¨×¶ÓQ4ÅÝ%NQŒ™ D¤¸»HÅ µï`Ñ‹. !\í¯ ê`̓ß…¯£Êûã¦Ö`3à<Ù’ ¸Â0¬ÀJm= ´ó¨  ,kÙç7éß&Fxo늰4Õ‰¬O‹´fØË@'Ë[ ÎÐ)¾ÌjϺÇð©åëœÁÈHÔ<6høy’ègð¢ð(¾l‰tƒð¬ [ù6íÄ5q»FÏúz8ëFí–ùT8ÞRþOñ}!ùèB©¾Ô÷ù-ëçZD(­N©°äžDaôA„Ö»náLKžÌ Ɉ@UÄsŸ‹ó¦RÀEi˜Ã0ìÌL«ú¬“¿ËÓW’ð, ‘ {§8D443•*KyKÈþdR`ùkM-0;ÑUTÅ-ø6*ªâÔù–Ý»¬ ¥¶—}kFðxSg†1¦›ÛÛqœˆ¼1ÞÆ¬iŽÌ¡ù$Bf )ÅSΣ­S¦„Ëú® †ªÊT J–iš¿ùò«ñx$bC1ÐÍÝm©ÕÔ˜Bß!DÄ   BøÙÏþ{ç÷ßø€D©ës)ïÞ½ûò«¯~ùË¿º¾¾Ç]ß眮'ªÔwýÇ{©õf¿»¹¹ŽŒ1„ýnߥ$U®öûWw¯àãÃãÕÕ5‡ôúõë)ç<—”9ÒícfÖèžèÑo¤j&j¢æƒ?jZUÜb”øÔK3Ä@ˆqbäà¦êsu¡‘¦ùé‹/3#ÏP]—º®Ïã̤`Uäy<þæ»ïþäOÿdÎó«ÛWÏ!2”\Þ¼~óøð¨PÛ @©¥Ôª¦n$éO·û¢ÓýDJ.YµÙ¬-Àm~Ö~`·SÌóì†ïµäÅ€eU¡m³ºàÝ-j™/ù;¸Ë^Á&¹¼kX‚é!z¾Œ±m™YG/±Íöۉ黥Ò'&ªNÉÿ²D00:ë“ÜÐ!„Óbu®çþéŸõ«×¶çæ^ÆMX2å Xf9ežH~"F¢2:½bÐ^hÊœB‰™].wñÝìŒd+¹ÝÁöÍaž¯Õ§×aiA{èZ΃¶À¾6ZùEÛ#´E‹)€)3×’‡>I]Œå™ˆ)z´rùB4"ö13@âRJ)5uýrœ§7&±ßWƒ¸ +,Jœíy1r²ÿét Ã2*Õ×i])wKZD)Ƹ:Ç3³w…‰™8/í»®ß}ýõ×sÎ*Úuižóóá™)º£¸- -‚Ò¨*Î;ò©Zk±&%æ²ö S‹!`3«5©k©Îo1jR¦aw% _û³×o>;Žó4N_~ñEººÃÓ‰K.û««ë››¯¾þúwþÖïŒãøw~ÿ÷÷»}ÕúpÿS:<Þ½{7tÝ8Žˆ”µsÉ%rL!ä<ÏÓj‰K.ó8sˆûýNÓL!ŠhˆéúöæÝç_<ž\:"u©Öª¢DCpQ>&ðÌóD sh04UEƒÚÜ—‡?pçlòV’Û\ÕZkuÛ¦55q3[âeö½ûB**µ$`;¹äØu"útxÕ>õó<]íwÏfv}}ýã?¦.Ön4•Ñ:ïDd­Pm4JGrŠ+•6». ã3zÅ2B̼’h—2} D(c•!CD" LŒŒËã¿ä.ºÉÜ?Á_‘€—~kˆÑðw<5õ^|ă›Â&žøém4˜ó ¹>Å{µTí‡a™Îºˆqç;{fÔýÉàHÄEó‚ç,¦¯?ÛæõŠƒ#¢z“mKlÄfxI}C›Ã[v|óNÚN;ÎþY  ÞÂj›ådÓž¶Õ±‘q³!G†6š3'OpËB‚‹åwýnb©91ÀíÍõ8À ‘¢Û®úô‘'³(âì”Õõ„ˆXÍcd]ºi‰1¹€ªÇ\C@®ïcì|?\wx³î´{lm¡I)~ëWXG×óºn·ßw©[½ bì 0„B 1¤;>Œãáp€Rò4OPE˜Ý% Ílµ•A301¬,¦ÖíHD¦²mU­hž?Éþ´ûÜœ™Å˜Ü ‹c@ƒÛWo 諯šº+ ññþIja#uz¥a™K7ìèæöööîî«/¿¸¿¿?÷?~¼ÿøñÃÇ@t{{WJ¹¹¾yÿþÇ#äœ?ûùíõÍÝÕ ¾}ó ‘Ê4¾º{5Íyšæ·oÞÆØcß]? Ãnš'@zx¸ÿùÏ~çû¾›æ9p¬UŒb`TÑ.¥ÈAªxkHÛ¸©!"‚£âD ‹d®c/<ÔD¤Š@à@ÜuÝ;<‘äÊÕº4Õª©”:ô]qëàq!uID†Ôãº.Žó(*jUª«ÿS 1D"Ò¦5·´Ýæ1Æè"7ñï¤x‘Zœñqr³[+B"rÝ/U}Z0ÆP«¬÷Ø*Û{©Úè‡h­UN#²´‹°¾@›X¿D¬M,^Ûæé/Â'.Í<€æ´ð@6ÁmÄ?µØÀyöÍMŒ©!˜¶´ª–rNÍ«ËÛÖ{°ºOm‰‘[Bý™¤ÁöDœWkÊæ¡ÙÎâ2,CLÛ+p:ÈKBâ¦'wAl§O®\ÇåÐçK¨½m‚ÖéËõ•%Ökµ¥ÌðD¤D×¥kýŠö-j>aÒuÝ=#@`~õú ¾zûö§?ûÙíÝÝ—_¾{ÿñßþ§?1ÑyšïîîñíÛ·÷Dôã÷?¼{÷¹™«1üîÏ~Þ…ðë_ýŠ‘þOÿí{|~*¥0‡¾žÇÑ †aWJÂççg5sV•ïøMß÷ˆXraæ”bd&¿GT‡ÄTòl¦¢RkSì!„ÅL‰ \´‰˜›¯Ó݆H‘(ðI6µš!›ª˜ºwZ R»À|¢b,µÆKɉ€æ2q bÌRŒÀE« úô¶GÇý<Ø8wÖVOykP¥¨‰Tkè·¡òÖªt]怈ë"š{Ä_»DŽÏ\`,méR‘UJÌ 7`¹ÛW—ñáìyG>VT0ÑÇû‡7¯^u1ö1Š”Èááþ‘C¸¾¾1À”º˜º§çÃn¿{xx1\ß\?<Ü¿z}÷øøhf*²ßï¯wW~&ÈÁbW»¡ÖŠLŽVSäb20ç䑵 ¿ Ò4ÍÔ5:#"3R10X],kU ]ZÒLL‚v8„Øw¾U‘#ìû]ÎÙL™IÕ”±Š(65HB,¦mdÜ}çSJºÐTj›BàÙmê—fjM–d¡ ¹±ºW†¹&9¢©—fMNÍà ´¨º‚K¶ô'i³tãB}1S •Ì´0cýÈNS® p2Ri²^äVv«˜œR£7hQ_ <)kQ˜H¬Š™È ú˜L ˜C–j)¥Ç§'$êûÞÃzß÷fV²XL1UwX$h£¹F>yD(j53b@¦à ¯*1«CÁL-áà€D1uRgަZc×ÕRD„É0…¨R¼k(ŽÏÇ> ´ l!ì†^€x=UfdÆ‹ªf¼»ý¬Þïßh%«y²šÑ°Š8%#p°\ËÍííï¾xxü˜§iêâpwûö'_ÿìwþÖ/þÑ?ü‡Lø«¿þeÎլWw)DBìbwÿðp<Žã\Ç"iuœfânóÇ÷w·¯¦9_]¿zõú³çÇ­%3‘¯¿üêÕÕíóãsÇéþõè°Û—*ßþìÛ9ç?û‹?E¶j&*¥Îó|DÔÏ?ûl<Üsn:wÃp{uóðáÃÍÍÍ4çØuß|ùÍó4Ï9ÏRs©!r Ô8 ‰‚h{Tˆ÷Wûyš‰cà@Lj¢¦ EüfÛƒÔª¦¥dCƾï\ù"¤˜sF@îãªíbˆ©Ó*8Ô’]õ—šæ’Cb ¦hFª9øP Ÿ«ð»7¦BH)ÕR MM‹dQiY„z‡8¤Ø`¿ÛåRJ­]ߥ°SiÍÕª*D0 ƒT#µŠ „ RM-ÅÎBÀ1³ÃâÈDÔ2C‘ àÛ¶òkmcÜʽÙÙ€óaOr×J°qÎ:ŠŠ.ÊŒmD­Ââ;è² -Åt¯Š%ã\õ.rÊÍR¡K„ä³åÈÀ5ÁØúÜ/ .¡ùÍþÖŒñe¾ʦ/?rþÆ5j_À)ço¹ha_PŸl¢ÚùgÛùZYG—Õ–¯¸|±/×ÏÅaøR…xi¡/œÎSwZ;_ž¿~ o߷މ7$Ò‹ upc&sOºu½Yl­Ð•&UÝëÊï×ÝnÚœ³BhjníL‹ Û¢ðÎŒè¦޽´oQ63DFB‘jˆ†D.ŸÑõ½«£¡wöD«æZÄl×ï¾þú›¸Ö⨫Æ]e•Z3S•Ö‹²]·;¯î^ÿ‹ñ/þôOÿ“Z|¤×9'"¾˜ÑqœTj@ÚõCLÝ7ß|KÜ!Âø<~üñÇ·oßL‡Ã«W¯ú~¸{ófuýþýûÿïþÃ4M‡ã¨jD4¦Ãó¡ÉÊ«žyšbCß=>=Ÿo®÷?¼/ãÄÀ?~÷"J­OÏ÷)uO¥üãûïÇyÇQT9`)s­uÉ1)¥½§P˼ßížžk­···¿üÕ¯ž‡Š ˆµÖƒAg "ФqœÆ”’˜•RÔ¨Å,°e]—ªf!„ZkŒ±ïº@tÍ 1³H!qÄi§›»Ûû§§£‚åœEkXÏf°#ÊÄ)$¯DMÕˆ9ÄP¤ºW|R@˜s®µ‚aа™ü¬-—ðeæý~_j-¥,0ŽçƒÞ˜õY\ B\$ÌuÔC¡¥“¡ÁðŽ!áI×àÌÐbü=¾çÛ0Ò -ö²ù 3f_šˆB‹o.±ÚÉâBÊ܆—*8‹KgQñÄßãÖ¦C€&+«`*¦h¾\騆~ª?­¹IÿWckp¿ÄyVc“ˆkÓÿM¦±y¶Á};<°yÛÇèÅÞ!.Æê^«úò ›SÙ6þ²í|¹ó¸–)—§bÓ>ekKöxÓÚ²÷ÓÅ]gd¯…ß©$Ff \ F”Г(2±®êlˆXÍ4Ÿ…3³£OÄí¯öÓqUѹb¾„&©ˆˆj€„}Œà4J¯^9ÄØ¥˜Z댂ïpi3CâȺ˜´-0&"AŒiÎù8ó4=<<¤~÷oÿÎýýýýÃÃÝÝ"™Õ&GÕN/q]jÉ»ýþxÿäOþ8&šÆçZgüƒeÂÛ˜ pØõóqtœ¾ˆ""v]x|ÊÓ|x~ LüÇÿ)WùÅïýÞ÷?þøü|øƒ¿÷H¡ÖŠÀ?ÿÙïöýðþýÇš«»%:H= ÝóóÓ‡÷?Îãˆ`5·W7óTq)ùéðøöÍE!Lóñ/þò/?|üSÜíú¾KhZæ,¥~öö3ÌÓ<¦aèãáéID€@]q“-‹ˆi‘RJ‘.E DjJ1&B@œç)¥cUXd{•äÉ€IDAT5½›ÚãMüŠ1ÂE¤J%"L±#&&–šíígŸ{+Õ J×××ÓáèѰO)bA3 b^ªt¬Rͬ”ºm€ÔÊÄ‘nòÔ¾ð‹xAnf]×}þùç%—*â×Ô´‘¥›‡Ñ‚Žøåy·’¿åWX¯ñø—´>€¸4ä·d°õD­Tã5Û[É<Ûà~z?‡5²/) cºvü^1:‚tAi¿Âç™è)ò04z.\‚브‚Ÿü}ó"ý–×`½Ak|‡àÑ —-µ®íÆO$ûgÁý™u ‘Øø‘[!³- –º–œ.0´sõâ$l×O§Š½\KWÐÎ3ý¸ÂUBs•{p³q.Ùë•E;³`ð$3­Õ@ïQ Ä\«;»‚¡±ûõäBΨ@s³`QEÄš«im&Ó%«i¼ûÆ’ C,¥"¢Ö|BNɤ«H1¥¤¦À‰Âb0b>KID"®CŒ™ˆLA9ð0ìUež3#šÉW_}õwÿà÷ÿôOÿ´ë»qU%E^ -ýÐRL}êÕªÓøbä@$’‰ÐÐ"G—a¢ÅµÄ‡B½YºßïKÎã”Çy>ÇûûOO&òã÷¿ùÍo~óöíÛÛׯ¦¹pLEê—_ó»¿øÅqšûn ¦Rê8ML”BRL¤æ9ÏÓÃýýþzªãáñj¿úNr½¾ºº¾¹Q“I¤>žÆ<—2s •Êçy‘aTõææ€¦i¾ººb²yž 1¦0M‡ÓTÁŠT$T°¾ë˜*µÔª!@¬RCŒ]ßB­ˆVjQŽÁ1åœ/2t=!ÍÓC¨¥˜€ ]O@!°J›@‡LJ©ÌE  ‰Èñx Ī:5W©•‰T”µu´Y¬ÕmaRL1F·)7ÕRĪö©ïSUL‰©”¬ªî›è 3‡iœR—|ðuͯÍ,„䈂…› jËÏVG¯|µ O-þªÚ¤i–æÄEp·C÷fi< qgˆñ')ÔˆMô{íX“¶oÍá3*Ê&ž|*¾o‚;Ÿ‡°Oä¤ÿ…ŸíFÏ ð³`Ï…eáeËx›È/³„æ…’x¾´6ÃËÈ~±‡ëo‹š ,ˆXKQ³£µ <-¸X©nÖ¡mdß~éÅÅ€E¼éâ³gû³ù7]*êØzâ8¸Ð#º(1²ÛUk»0%ïx|>±¾Ì  äB ñ'¿»U’s¦Ø©4}Í!ˆJ Qj !Ô*f¦µÅ@ étQkiºe / Ž/$ÍQU˜‘ç¤!$‡8Tµë»šgf~><þñÿGD˜æüí·ß–Rf¬¹|ƒjÃ5sžv»]Í³ŠŒÓ33«JLÉÜMÊŒØçW›-F­9ç«««Ãñ¨fÇÃ8 ƒÖ:MÇäer`$êúáó¯¾zõÙ+Eüõ¯ýøôüÍOÂîvûýôô µ(e>ŸÇñyèû›ëk• O÷}שáþz÷ë~mZÆéøøøtsw+Rû¡ÿüóϾÿîûÃøèchµVUÈ9—Rnnní‡~Øïö"Õ%çˆiG÷~¾ÚïE$…èLPa]×UUQŸf 4Γ»;¨¨¬,ŽB‘ fÔ½œ/,´ÐWœHË‹—¤Qÿjuk…|^>—Ï/É£›Só²íà@ØIŒ¾ëûÍ‘·õ‡ˆÖ]ÅUN³],ño^Š»³>ê6|·›†Ðthû†‹‚kýÔ…û•´77(Á¢[ämED&¤àºi¦¢à áÖ~TS1‘XLɇJ8Ÿ©YÐy30“Ö ©*CPUæ0O 2²Ô˜™‡ÈĆ „èNóÖ°Z !Ä]Ï Žð>R 5“œ €C`¦Z ˜•2×ZR k¬¹*"¯^ß=?æy6'ï“3 ÀL«t}wÿáC×¥]׿º»‡£· š)º& "bJˆøøø(¢oÞ~v÷êbà~ø®ëBbv»ãtìw»÷?þ`¥~xÿáîöæ7¿þµ¨Úñø|»æù¨µªÖiSß§’g-²ß÷}ãxÇùæööÃý= MÓa}¥`¥d7ó3ÍeŒ1£ë‚¸÷ôáp(9w]º¹½õÖ£+€ïvCˆ)†c˜G0 »”J­ÂÍí«qžsÉ!uEKÉYM§ªbØøg¹íºŽ§iºÚí]œ8†,Ô "Ef4pEK1ŽÇ£˜Ìó4 =2Õ*Ó4¹Dµ'×µ1E¢Øw¶€N C"Q1€®ï`¹á¥ªË¿™ˆ3±ÜA^DC mq œÓ:‹Ö©_efòñ繸&!¬BÁºJEã‹è gbä·n}ÌW`çeúx–­oƒä‰–½¬lVkþ'ñËÓîÁ™ôú§Ãï¿f丟ÛÅ\&§®0~RG;Ë _ÄÓõÅmÒRìO~v  j«Îvìl ؾížËS¿Í«/"û’ÌŸà÷ùõ1K'‰`[É·Ì–¡#"€_ïS÷í¯|©í¤.©“Ì@O‚ò¾´oVÖ5­@Dh„e´Óu@F×ó)+²Ô„ lsÈGÕ]϶ÀâªÞTåL÷†,.,bß+vN½S_Ô|­d¢››Ûù8"´¢Á¥Bš‚ ˜h]ªU%â£v>L¨¢€È!ˆÔ°P¾ªVÙív±y [)À¼éwè^!4æ h.µïú¾ïK™§iJ)Ŕ̰–ìĉófBØívŒ4噈æœw××¥f08Œ‡œGÑRó|<>w©ûÍßóÍO®®®žß,ÓLf~øArž‡ûïw}©&]Œõúæ*„ðüüxsw›çi<>u]¯fðÿ‡?`@“ñéé KÉã<§”r.Ó4NeD @S§fU¥R‘²ßíº~¸¿ ¦»Û»Û»Ûis)PsASß1ˆj)Ylšç¬R4°juèûqœªŠù¾šš(; ”Çéz…ËæZP ºÉ 1¸0'„Te¿Ûy:^j-µt]_¤„»”˜9¤XE0‹š N&îjnJˆUÄ×aâW·w×»=(îvC-ܱ±€‰D$†Ë@¢,:ä]׉¨ª±¯ú²g>ùáá‹Àd .FLm™*_3Ë<Ø=­ÃÞ+Ÿû\þ„³ãy˜€5]„e½Ÿ<_?Z"¸Ž)*kÈœÆl#CODŒð#ÐÊÜ DC]ýB׈‹ôÅN\DöÁý´’­gál©Ü2 g?»-³ç/7ŽˆK)pÑ*=}?6>bC³Îâý&¸ûvkk0®¡v¼mæýÛöXˆN=î‹s² MO†iíÅÛºë›×•ÙÖîÍyu¶È+ª­Áuñ’u»pU­UDj`æW…(¥x²cfÆÍØ^ÛI­k'ygÀDSJΤ2€ý~cüüÍg^™ÙR™!"S "7hn Œ©—ä°Lb„Àž‰#BQDû˜j­€Ø§Ìá×ÌÌ13aæyž¯¯¯cJ󜻮C[ÄÖ6]/UÝí¯LužçZÚ|Àœ«W3Pk bLfv5ìÞ}öù‡‡{3§Ð†«hÎÙ»}SJÏχâóóQ ÊÃ󺧇û.„.¥çÇÇù8꘾vá#© SŒS@$ äÈÄ$bˆsN)y‡¸HPPæÈª¤sžô‡€(0˜©J©’Í„(Gtš“7çû®+¥ ÃîªB“ɰª‰§XH1° 2!VA²’KÑÅ\‹ ¤@sEÖÈ€²ŠEŽNÁÛ¶Ìcˆ*`R«ìvƒ¡¥Ô«é_}y|zvögLÉr©";J&!h™lÐ}ùú5OãñIÊt<ÜKe×Å>ÅLJD"ýÍWs™>üøH}>¼—ZK­ó›ï¾ùÉ·Çqš¦©KÃóÓ‡\J—R ¡æùÝgokžMj)ÕL HÝwû|Ìœ"D~}u¢šçñp<ì†þöêêz¿W“€±*æi»>q µ±ìânHE!×âñ4Ä€b ýn©~£Îyžsظï«£$DÆ$€ãtTB%ÈUp!}?ž²a5óÌ1ˆJ\ïÏÿ:×RÄ IŽ‹Þ\_ƒØtœÇè‡Q h§Û»›išÕÌíºšTS¢@ÄL ¯ö{¨U«ZÕ,‹zk©iæ8+ÝV–‹?…>Æ«€U@Á?ˆ¹-@vymŸÅÙØ<-žDÄÖÌ ÍÖZÙó7Ý»+Í‚—qjÐM€‘ LÀAÍ|Hx-^•OÖ¨¸¸>Њ¬’¿¸DÖeñ¹ëo?zæQ»d­ özÑí|‘ÝÃ6ùÄÒŸ’ú/üà‹ŸõõMm/? æ¾]^nÇ–ÕzË]J35"Ú@W릹"òÍ•Oâ ¥ÙŽã.û¹IÖ¤À}HÛŽø#Ç6ÔJÚè,a@Bði¬–t«— Q7•fŒæ(Oc‚‚Òbô 1¥RJŒÉ ®w×!°ˆ˜J•¦‘íÞØ`f °¤¦¦" ÖîE"Ìe¦@}KæˆU|𕈘›Ù)›ŠÖRQÎ7³Æ\V+¥¨ZLÑaQ&r½GZBŒ+X¹¶ÈTÕJ)5h[͇ã8Ž÷ªÊ1‘І˜înoß¾y3Ó8†ÈãóSŒIj5ÓyžÏcˆt{{=—IMnn®ŸžŸŽãñùñL§i*¥ÄÆã±KéþááæúfžçZåöööÃû1ðÕþúj¿;<~èR²*ãx¼ººÞï÷Ïã±H-RŸª:ô=âáp©N6wíz—l„§Ãs­â b53ë‡^TL1Ö"fbÐ\sEÄg‘}®ÅƒS`vþIÝCïdZa× L¸(h©˜)‚Luö›ßÕõ@[­ÙÒÞnè=§]ÿ|<ÀâJÐÀç!X¤03]§>àƒl mž bK­j튫ªHñž »IG](/KJ¹—2·=híÁÄRšòÁ>EDãXró­(ȶ€†õv‹öð.YǤO¾õyßN«nÂÒÚ¤ED}‘Œžá '#ìó„µmLÔÏŸl—ƒ –~cY#Ñú}ÛôúÎO!ïÿ¥è¼‰ìp¯˜ýV&øÿ¯x¹¾l–Ÿ  ^®„jBðI‡•Å®‚½bñ@/¾³ -Ch'‘h<_i΂ÖúkÙC_-¬¡1ÈÍ0ÚUw<=V0Ðê*PfnüdZE¤º^€3Ê©ÉQ‚3LÅÅZ10/z߈€!FSL©g Ó\DUL¼™å ¿LlVhoâ Ž!™Ùþêšð¼»nØÀ<—l؇½R6b ÔLÕ‡Ô9á]E³ÓØ yíh­4V&vxÊù<.‹!„\Êö>\KZ!*À<ϯÕZj-¯_½€Rk­´“ëóÃcdV‘Z²· SL¥•Bèºt8>!A­ùññöû«žB)¹ÔÒ÷]Éùx<>!Å›˜ÝÜ\‡MK©Óñz·¿Úï¥V›¦±jöÃÇû‡Ãá)F& HüúöT+ •:›Ù4OĘK©"χÃÒÐõ×ûëyšó<ñ8Ž"R‹U©L€ÄÄ)EdRÕ)g1AÄ£ß €St»spôÀ_2\òË –k-*Y‹¨V÷§pÀ쑚˜2ªÂ‘‡QL]DÌTm )Õqž€°Ay€$aPmÂîÖáÁUEÄ_‰|¼Íõœ™ˆÐ‡•Zí  L„ÄV%³ÓDMµÍÓ¹y ºy%±-°ç7vÊV¥r3W¢ýËEtŠ9´dW;Ï5pcS޲OÄ/» "§÷Ø¢æ» î§èìuÄ !´-„ 9 ¸á{\ >ëf_æÔŒ+~CyüTô¿\<>Ü?õ×O7+Öà¾}ñâÇБ3›!D\)¤ªK§ÅõQÝ`7P–[qÿ‹“°žRCäˆÙŒÜºÕËM` ƒÔ ÜJ{ÙsµZLE¤Ú¢²ä Ä.®jh(Ël´ky ç'G‚ﺮTA`ClÖ„H!€{I«T\”ª |ÊŽÌòb|BÅ\€¨ëº½A¤E·¬Í5¡e#Ö\ …0 =€ùàk«”T·®µ/Orò1OÓ´žÏí'dÑFkëRç€ì0 ‡ãAÔˆ7]|2]A ©ï“ªt1h?$¢p÷æöp|ªµÔšU%¥nšÆC×w¦"µ|þÅ?~üꫯrÎeÊï>'"¥”®ëa:ŒÌ|xø0>ñÐõ€PEŠÔ9Ï¢RkîûNæ¹ãÔ§¾K!—y.ùñéÉï´”Ò˜gïE³{¬(”œk)ªj€)FdŽ!rˆ."ãú D¬¥VQÓ6¿!n‹¶°[¥Ñ¡:ÆE &h†UÔûí`@H‘80¤È@‘¸–r}}sf¢÷>쯮êœ=ù¯ iÜás| n¶v&¹ƒŠ¹f5dRb®’·ó ‹PÎéÙ\*H@kB¾ÐÆl[„]Þ¼ÜÛ{ 2ÛÙš5¸/¯´×gôZ²Ï'Ü|L¶AÆã@{åSŒÿí·Àúk¿|eÝû‰Á‹à¾þè2KcË¿ý—EИ9¥´ÅvÚÅ}2úo¿móÊéSÎË8þ_LÛ·¤ûL¿¥Ež÷NÑöŒf~^ lÞãr!hò:DÚòK[N”Š)¯úú›î|ëy¶Ž„ˆ“ës!9Øgºx„’¶{§qòº™/¥"´<[NDḧWBO6÷“5]UUc"ˆ1Š!Sˆ¢ç;HèÚ[µBŒ1Öœ¡‰T¿¼}:ì:…”v„ɬ3K@’ûàU[|P |– ±Y ¢!Y™'©Mö„)šºnwPƒ˜:ï_9˜€„ì4ùm4'r¥xwî%dUï“PJÉ»µìJÁÍ¿qàfyž‰ƒªìö½™¥ÇãÑA†Ýþááþááã4®<>Mc»|<88ÑÃnØ!@-õz• ŒÇ1¦øñã‡a?›wb—DMÐ|1+%Q—z0­¥d­àôA0pO>À@m@oéZ4p9 T¤Š*Âcìbì<ÛGŠ.¤†®ëRz|xŒ!Ì9ÿîÏç‡ï¿§Ä´H­Zemz¼ïû®cÀª2Ï3a "…ˆMÕ‹¼‚¨ hnW™Ìƒœãz¦¨K2´<цëC!VU~yb.lkñ— Áy»!mâÖÇÜÌê2N§ñ×—pI¶›'tÒ¢!¸_ÊeûÛÎWˆà”!IaìÒm‡†-]îŸàl¹µ³¶ÀúŸ/W§Ëäøì+.ÏÈEäýd}°]KÖ€µyó'^÷å÷âƒp¾Þ¶®öôÔÜŸ˜–ð ´ð[m%J®Px›B=Am %i#È禣m€ÂÕ Ü?›(bd–jy–Ô]‡°ÏE•Z«i!¤æÕDÄÆH>­R¤J­%DD¤-¥ °þÙgŸ€Ó 9 ¸¹Oh4ç3IX¿Ë8 -4$‘B¨*ó4@ F„6°c×u.ƒ\¥ˆH)µÔê#Å÷fê–‡ÞÎ…’ëõ0\ßÝzïúáãÿøßü×óW¿" Ÿÿô§ãqœË¼¿¾**W77e.‡qzüð~ØíöÃ~¿ß@ ¡!F‘²ï‡ù0ÀXòXæ*•û®oÝK‘àx†»Ý U Ð*@Hñ0U\‘C3å(.öF„!„HÜÅ´(ù ÛÒfŽÌ&ª`ÄTT*(1¹â¹Î%†˜bdbòá@F2Ë%³3Ó¥þwÿçÿîþÍ¿1—/Õ%ƒXˆXN^ ˜Í9 "V•ÀÁ¾Ã¹‘j'æ[c"ÆSêKÉëzë8 ]ž|[#þÄVÑ ˜a;ãYÿ2€yŠ?ëFpĹÈJ·!q 'KVµŒP-Y²¹'вfà’“}"0~"ùùSœÎãêYˆÄë‡G7|1„ª¢îÓè#”¿eLö·§Øg[ÿƒû'׉߲å-3©½Ù!¹íuùEÛÔ‹fì2¹¾¾÷$ÖlËrí×ĹÁ‚¶hGl–îõÄ:L Ff 0 j^§¶¨½5‡¡¦*i„& Ë©_{IKž·FZHê>òÖ:–{‚)öÃàÀ©™‡Z ä9{•†ÄZ•9º¾eUc3U—jæ6°†ŒÜÒ^u·¿úæÛŸ»ÝáxÐz«H€¦M­Ó@U39¸Ü $¢”"朙úÑõÕíñx@UãfúÊ®x8®¬UQŒ1)1«ˆ5ú=„«H—ºZkžgUu9ŽcL `‡ÃçyîûÞãÈÝí+3ËeÞï÷9çÃóqè÷wwwï?p¥Ô.öµÊáñp{}w³¿NŸRŸχy<Ç,Ö÷ý®ënnnCLRËnP1Oùñþ±ß Äj`8Ž#qx8>ÏRVYP©¢¢)ƾë"ñ8©KLfÅ „jû.u]ì‚‚É¥Ö\ šµ~8€ © Ä!T«ùU8ñ4Ž ç<)6F™•yfbnUé"ËÒÜa•`œ'5syƒõ¯þ•Lyv;lÏ QäcdŠ  UT%ÆXª(€˜9óØÜôÑÌÔÄL‘S^£0yzºNо|„Oÿeþó'‡QliYorÁSSmU1Zó÷5(¹ 3c”_']?IWlÿ¿Òãý[Í÷Õ+µmçS8ÌËØ¸(fvêó)¸ë¯Ø¦Û§Èþ[z˜Hb<õp±!Fçw:K΀ @ø¿ ¸o/ÉÅ~.ËæeÐ^z•cø­{ø2Þ¯ֳµÿ.­¹ªáû3 í^B ÷xÒ&/w^ìÁš;„×Ë `¸ ¢Ô·Ýf„&´àÊcK²Pz<Ïžì#Rˆl.ylý“kœRˆ.ÈNKêh¼ÇæqšcŒšRôîiß ^̹¸üs@ °âævÀ­i¬®Èe®8ˆ!ð4眧§ÃÓ”g”90BQ­‹g‰u]1Š6)"*¥”œCˆµVçËûtUž«Ï§ðBìñèxËÐ÷pûÓåDZN©Õ]J\(Íë ÅÈÌ¥äREÍ8ð{><&DÜõÅ_}ö†¡iÛÑAlán €ÖZTçZg­`2ÏSÎyžçZ‹ªªU$pùܸ”P©nU†`bJL.»("úaDZªˆ¿£Udßïvû]©ušgŸ0Ó*bjb «j컪z<IL½éí£ÚëÝ‹ˆÙûˆb˜KqC\Œ¦ M(‘‘­å²Ë+âÂÏÑÍóŒuçZÒÀKúÃYLk­Ú–à×Mp_õi—Ž£™ÕZs)xºÖÈ'“QZ|ºS¹¾.á0lÔ8vM4÷nv{û-¦Š!°ª0ÄN=F€ÛÖáø%:Úi/·dOÝR!?!2³Uu_#ûEëˆíæSŽFQk!¯­O¬=ç'ÑuÜa Ð~'ž“÷ñ¼U°Q#ï'b'€Ï8¸A•b&8KHLª*DTkM©s½äÈÑTCLÁo<§è…&VÄL€´*‚ÆÀ!±Ó ‰ QÅD|¨pÕ—·å®ö[°K;U û«$ʹĤ"QdîŒ12D¨¹r- Ð,ʦy6súz;ÓÀ̤Ö<Ï„p{w3 }»vK™¥VDè r$î£ÖÂÌ€ Z‘Ak–<¢fC U9"âK&¦iÎý0ä9»pUˆažK׿ŽE`Š*2ôÝ<f+%ça· ç)§Ôyß`šg0µRf‘™îæêv«¸ŠLù…\Ýlˆƒ˜ŠÙTf#$æÀÔ¥˜B°\‡ã󑃩Ĕˆ)†NÕ@*öýþîÕ« (dÿù׿Ԅããý°îBìÆ1¿¾~{Õ]Ý ×û‡®+Ïã>v2ÍŸ¿ýÔ í!ûa·¿º 1)jÖ,µžžñj¿¯s¾êw&¥ÌÓœçÔ'¨•ðp8P®%¦ø<ÔL¥LLkFdêú¾Öjˆ¹5wà 4#@QK!…©÷ìLÁ¦š qèbÇȨÆ!d)hM(1E_}ÉO£‚!Qê’Ç»jšMª©’`ê9uÉé7¹š(‚Ž¥xŠj*ˆ0¦@æ,m#™Dœb"dSÏJ˜ j.]ê™;§ÉT­˜9ÿµPˆ"zsÜ-!ÏÅï|¶†;.‰y ¹F!ú Ñ–ÆžËHÀ2 Ôæ UÀ•´­ ¦˜\„£Y…jVÐÔPÍe?œ¹†¦…ã뙓 †e¹B$ß«Þ0§-,sÎߨæ­tžŒ¿ÌÊ·´ž-¯|ÓXhs½¾"­¸ÛËÅsgO¸ÇºýmA¿ýÇýRé¼Ql/ƒO.[ˆL—‰Üõ 4çn &ɬ)s1³/la/BŸ,j¢I 85èÍ(æP«TqÊRTý|ÁŠ/úAmg£·R‘ÝÛ‰™Ác˜–w11±gn݃DtuuUkED‰1zÛ2ÄàÔþ2gh¨üª~WKžs.f˜D¥†À©ˆ"‡¤fnÒÑN]„ä$ä~èͬ”ì²!ÌŒÌÄÌOOOÁ«"³9Ï}?lîfWÈ+Ô”K̺n cº¾¾i²î8¨Јe°änb"*¥d­5&—"PQµBß÷‹0·©"v}rÍ(T‘ãá8—ÜwÝ\3ŠJ×¥ýþêp8>Þ?…¿úâËÃóÑ5¹ç9¿{÷îéé©H§éöõkW꺽¾yuu÷Ùë·?~÷Ãóó=½Úï¦ãñíë7?üøƒ ýîP&—½ !ˆTæ ¦9gÇ k.^È…‘(Ïyèúœ›bâþêj–""Öw T=ʤúÔ9‘ߥý›çEŒaá9Ó£ª¸X#‘k¹S³‹Â{$€>¦6¼‡è÷φiŽÞ)­"î‹í\¤bL!ºÊîúnÍ«ÌÌ{õ™CðH¹’w×áUùÍ_s$4uŠ6+è¹…€öxîêƒ!Ž É†ãçi{<±×¶O±j]Ø3Vk-âÁ·L+úÒµ* ÍZ†‘¼¿ Þfk¶B-^wÒWPßm:)£´©[åo—°Æ®mÆMtÛÙ‹˜þɨJg:}|Û5^&qÚƒúò»^DùSpÿd ¿@yÖuØÌZõ‡f°g¨Îâö²ŒZ[Í´ôE¥'$îœ »ŠƒY¯×i£`1{mÕ–èíÁÜxKˆ$j~µŒ|!@¨µª ,²ckm±ð#“Ð'îÖ3àWÁ‹—ÓºÖ%²žž óaŽ©s›4UÝívDˆEM¥¶±85eÂ.žK%R«‡ˆRªQª ÑK±%2`Dhb„mý`fDðd‡¹­]ês©"%.µ‡Øw}­5„à‰`Š} ]-z{÷êýû÷f@Äfjµ"*/ÑJ\ʘ¨ÖÒ.:»1­]{)eq_SBîR¬µÖ9û—Æs)ÏãÑ{0¥–\ª‹ÿŠ»ÝPņÝÞ RìŸÏ÷ªT3Ý]_ û] ÁŠvÜ}ùù%—ççƒYÙ÷Ã~·ïbœŽ£ªbUyÿðfw·w×7WOS™§<‹j)¹K)uiè{W Q‘§‡G¯U5¥„ˆÏÇC)%u†ÈûaGH`(UÉPD‰©ŠxWÜO>@ó‘R«.b³þD»!j’DC S$׆4€jªÐ4°Tµ¨Øš"uáI¼{7'S RŒ¸@¸<Å«"£'%§Çy¥o"¢3wû~1"$¢Ý°sXnM€ÖƒµÛ`Ùàª(é²Àëq-¡ÌŸš6¸×Û<Òì4급çÕKÇWUaçù±ƒY…YPûswŽS¼%Zzë~Â:^Ó …¸òr>I¼¹ˆ«Û`zÜ7™õ9Se»‘̽rN_~Ë6¸o놃º:PowɬÑÝqƒ}šÝÖ"ÙÚ鯨,77!9Ç€½ÁBD ¢*NtW§{›ÕR\ÅsZìµÈIb†RǪsØïö¹˜º.#:˜VV,­ ô ¸usO®1d¦'™6DX¨>˜jH4N“›#ÇØ9—KUS—<ÇQMMˆ\•IUÔ|JžkÍðÁg´‘Ô`½w=æ¡£IÌ¡Ôb ]×§˜TÔ°™Í»ˆ¹G™’K×÷ª’sF&÷ôFO<Á‹«% q|ûÙgïß¿ïû.çiœÁgƒ}"WU˜´I¿6õL•Š)¹K¸Šˆc Þ7f&És`Š!®ñÅSQERPA Ê\ºnØíöy®s.××7¯_¿½¸O)!Â8C`½ÿøø“¯¾AÁ7¯^çZýÝwÙjDC¢¾ëî?»ÝõÍÍÕ«Ûï~ø¾Û ªVk1½¹½1Sf.¥h­ûÝîÿÇ׿þÈ’dybØy™¹GdÞGUW÷ô¼z{Wäô,!àJZ’± ˆÕ7~¢ô׈üÏ"(@ °€ äRvw°3³3Ó¯ªº73ÂÝì<ôá˜yxÞªe¢Ð}«nf¤‡‡Û±c¿ó{üüþð«¯>Ün·½µu]ýÄ×&æµ.nfê¨Ý*S)e©‹« ©úÔ÷:x.KSm¦f–ƒÜÿÀ|ïÍÝÓ9„y©µˆ¸'lLdîÀ¤fM;€{€…÷°œg0sY$?,RÒeÞÓo­ffªá1d%˜æ3•wpx¨ò© ñáP‚'¨=·.÷©m>qZŽ…Coëf²‰DÊÑ?¸}„á£Î=‘9äoÓ\FçJu8ÂûÜVaÚB 1àT×>ÚlJ9ñq=çß2y"£ª™4;.•‘Ëñ£ðc=û6ïðƒ€ßxÅ|YÜÏ;Xbˆ?Ö¶±³œ6ÂS©ŸnÉ3ÛeÒx2ߎ,+N ë¡\Ϭw4†À9ëϿǢ$<ŽÝèíöA—Ëu]—ˆÈ»Íáô¡4E2³óÏœRofã³,+pæÕëósSw5O垌m‰ÀO|èicİŽéb>4BÔ&PÈ<ŒnX,ŸuU-Rótäîˆ,RžŸžÔ4yâ¥f ³i¼iT`ªÚFÔZ=,/—+°h·"³ÑËOÑÁP„Ã!ˆÑÃÔz@Ì ,üú럘öÞûÓõz¹^{oµV$I:ê¾uBpaˆ*@þéÓ‹ˆ,KQÛ–*ÚzRüÓ£xf~¥‚Fu‚¤0É£‡¥‰HöòîΈª¡n‰õH-,¥w%âeY Y¨Èrôo?~lmï½===]¨üôãׂôÕW_ûÝwß~þüûÏß_?>W„?øÙ7LøòùÅL7m¿ùíoÿýw÷}«µ2Ó¶oßþÞÜ?}þ$¥)(DëåÒ·ýûo¿m÷ÝšÁe]³8α<´Ö„"©ïÍÝq]È*“Shžn‰æÉ‡ÉiDɇCdu (¥qŒ5%k®µꦪˆÓˆ ¦"RH‘J)LœGR˜å¨z ℙѠFáy¥bîèÁ(ààj!̬Ös?F3xø5=ꌽ幟0çµD ·Ž£tŒ÷¹¸òû3$$ç—=x“·™ƒ!k1‡užâäV_ Ó®ê(î“J4~|ºB%8…l'WÆó[ýâëüéMÑ\RÀÉŠò8ìà ÿ·TöÉ+A„Lá|ómãã?;Ú[|‘«Ê'rk=ÕE¡÷½®ËÓóåóËç½µ§§§Þ;üô«¯×R\‘¯RIDj)½uïÚZc@a¼, !ôÖÌ=ÍÌÂ̘QU  °P×z(«#ÂÔH¤duæ [#¢‡§8 Ò‚&bמR2šÚ9'Œd io߀ï9ão# Ñ˜Y)ËÃñ˜kºƒ{Ð KJ£=‘"¥D@­åñ†ãПLEáA>c¤À7IŸÇÉà”xY]F5Æ7QY̲+Ì6Z³3UúdE0ÊèQ÷'*4<G¹#1Ê Þ°û`FýAJÎç«!Hî…âþ¨~ƒq·›õq2ˆS׌ü¦¸ÓQÔðÍ€ñÔwŸ·#øâÏÛÔQZç!âÑÇh×Wôù{çÓ0/hüøÂÆ7Óã¨u¼föYö`†Ûæ3ÓùýÛ(@ÇåûIfõø¶1_ÄŒ0Õˆ(¥x {”R³†&Û‰¹¨î8QoDbaDt fÖƒÎH4 I>¿ÞïÛæÖ!œeØn„p= Ó }GZhúØ —q¨óÙÕïw{½Õe©iÛ‚(½75mû–ºs_km½AQ®éF@D䡪J,ˆÜ{ÀeYÀr~:Ó •u L†5³j»’ª×ZÜœ™Ý”Eö}swá5±æPíDlj,Dt•²’,åOñ‹ÏßÊõÁ’œj(ET³ùi›{ŽseM-ùHù@Š «÷ˆøûÿàï~ù|ßî,ÂÂf˲,õz»Ý<ˆ{³R—wï?ˆ”û§Ï˲¸»HYD¾ýÝ·­ï°éþéõµ¬ 0/Ke"oûÇëSkÛÇï¿úú«oû;)ôr¿Õu)‹ì[o­-—EU·í¾·½í; \®×ÞÚçOŸ®ë…@½ß·¾·(t¿ß{k{kLÔ[«R¬k"Áˆ„¯·Wƒ0O#Î9¾C óE¤ˆ„y3í½«Ù£¸³ÔZ3˜ÉÔÃ$À"R—ÚU³£,¥d颳¬¥~ °f]5ÐY ;€¶iËLä3>)×ìÀH#˜Ø`J <HƒñF&"JR¦ B×–Û³»—RÍ<Ó*˜ä4¢¥Ö½íñ©›­Ïa'0ÖH®–’Õïìlµw·pD>VV)%¿íP¡§¯»#3LÞ‰h]×ëóußZÄ ‚ž‹;N¥"HÓú†Žªˆx.žÈƒ. áÄDR ¦Tž›Ü+‚†+ÖA·4bŠiA‹×,ýeYÝ#-DjZÀ»¥Ò,ÑÍ‘¹¸Ã7$‘bª@(¥$Gj6ñÇŒé¤ õ£­Îáöc/91Ûó/ÓL4uŸàáÓÁD¯ÂLSe>\|Ïü'<Öd"qv5f$JZëƒ0£Ú²%Ÿ¼û·pÓiç (,,`]·…Ãú$Á\‰!Ü]¡^Ö{ÛEjN žŸ?D˜[ò Jj¬ÜÍÍÓ‹¤Î%0< kÏ¡£ -¥¤ª)í¼,úºVU$@^–K)‹ÔõÃ×ˆÄ Ýó s3·¦F\Ì4ïM­Kl‘ª±ë¾\ÖnÊ…Ô[a^/OL YJ1°¥Tõ†Ìøt¹dg " aLènµKE`5»¬Oe}÷Çô÷ÿ¯ÿÕýßþ·ÿ÷××ï‰Á\¡µVÖêùî¥ q!"­\›"BÙR sa†7`üöÛßõÞsYŠdÛÉ"UêEjmm¡ûö* ÛíõOÿô·ûkoí~úÍözûé7ßH)»¶{Û>þäã}»¹õOß}·ßïñõWßX€÷HzW¸ï{-„ûë­Y °oí®¦LP™b‚d]EhY——íóÞ·ÑzSP©tÛ^o÷×§ëÕL-íYDDÍ겸 ñ²,23ó²DGë}¿.µ¡GaÇXh5ˆ`fS%ÄZkß·R*!ŠÈÖîqßïÖ{CðRK 2S2K©n¾–…€¬ë"ËW¿Zjé­gÏ.,9¤!ÀϚͥD «Á¶máP«´ýÎîµD\Rú1ÎwHÚYŠ{0ó#žaŒˆ¦ˆ{Wbâ$NÛP½ ÄâXìY”›6f˜™31xSJt˜iNìUûÊvwÕ!»KÐÙ+A—ª;™9a.æÛ¤n€£Ž'‡õºÝm¼N8 ùd²""×ëÓ”Áà«ÖºxXœ ïpXϵDï¬AÄ9Oœ¦][*ƒqjÉf³Iž´èŒSfy"Ž”,H«“sˆÒ™Cg å|*9Âlº{ú Dü"öjœ}FêôÐÍæar(ÇTûdž9 ðå/=þõM.bD 11éÊ'”`£}`d€H-±òyžŸßßïwU$baáÉîD쪈˜ð馛¿x©qd~Dï}o­µ‰‰(Còûl"Ò¾»á5K!bŸìÝ#â¿ü?ÿ_þîoþ6Z÷Ëår½r-K8°p­µÔ"²Ün‹ü³öÏþîoÿj) ¡HÁ¥B>Ãî‘ ÈÝÈLDTµH‰ˆ§ëÕÝ®×kÛ·Z*´ÖŸŸß¹{)‡u>ä­(R™Åc¬ÿÂîn±ï»»ß__à»o¿ ½5)Ä¥ìmÿôùÛu½¼¾¼ö®mß×eýøáýËç³TÃ:1{xÛûÖö—ÛkDìûÞZ"JâE)åõ~'¢*öíÞ[ß÷˜¨V@4Óû}äÂ% ÚÞ<ŒÀ½ÔJˆM{ë=‰OÇrÎ^*½Ýz0òR,R¢–Ò¶®f½·(E®×k­5m“6ÕöÞ¼Û´-«R8²ÚµµVˆK)¦z¹\J)Ú5s‰ -G‹]ÃÓl~p¶“¡ÿŸþ§ÿé_þå¿v÷u]»¶u]Ú}é]é©,šÁ¼x@µ‘ÓŸ£çPÌÌÆÁÉ&áÄîÞò 'Jàˆ½÷Þ{ª"ÉÌzÒä×OÅ›2“$ý€z|¢ãîf™‹:oµª’Ðð³qî4Zxw¦’FªXÇý×FSÆLD\×kL[DÊ ŠeYÍú¹›<Äñ,"I:8LŽ¿>WÒ¢ŠxÜe÷ ÂÌq)¥”ŠHmßxÎxQ8¡sHˆ8¦.xÐ]Þb)¾-î_¼—/Š;ÀÀ HXfðÄ¿œ»>^ñ8ʼnmyÞ*†÷FNœN{âaaj:ò祰%Oœ%¢ ?fÄpÏ|÷Z«Hi­H³>2uÕž[l†Äç3ìn)§E"Fq$Ïà!Ä`¤È }øð1!‘}ß²A‘ã‰Mâý@U$µŽHÎSsœŸ¡8ŽVcDF2ä2Ìb毯·tÿŸþÇþéókïF"½õ®Z—%ñHwÛ{só®M=áoþú¯JeF÷èˆYÓ,]«•Q& ?ÕzY/ªš[®¹R†U’p*oÌUõà2•¬&aÚÜL݃˜ƒD(Ñèí~‹ð­ï¿úØzÙ^¶Ûíz¹®µ¾z÷Ÿý“òúé3#šõc®Ó{k½¸j)E{ËåŠ1Ì/#3C{G"7u÷[kÌ\‹x×ëúTyÕîÂE„.e5Óe©,báBJ„ YMvÄACL¦ÖRJ˜¿z—(FF].‹ˆøLæn­Ý· rˆŒ$Äfaf€(R’³X—'N¾T¤¾-Æ@¤±ëbVvjÚUs×rwm=­ÛÞzkß÷ݾoˆ Er^’zH"LÂLD¤Ç:¤h>"ÜÕƒD˜“ŽùqCšµ"1œ€W©­õÖZÞ¢Ëår¿ß‘hÛîLŒ(ÚC¸"¡»„°¬ë%ÜÝZÛïDAL­ï˲˜k@݉S˜¥––ÉΑ{ïËõ¢fDˆ­ÛåúT–ZJ1 䮹g'HÕ{­µää=,ÂrNï?>øëíeÛîË¥Þ¶íåå³õîf¬½!úv»‰pAÆp@X—"E¶í55é·Û-5 ÷íËeu7Oöwn]Ý5Þ}x'Ä ôîzýðîÃÇ÷_ÿìg?w¤Ÿ^>¿®ë"LÝzN2‘PmÌÓï÷Ñ—¸üðÁÍ.÷××¥Vs¯ËrÛ6ØÛŽˆëºâœKBÀ"¥ˆ0îZ1†â#BJ!fs„e]ñv¿ÃÌH»@@’ÞûõºvëéÃ5 Ù 0I->ó qY–u]Ý0Ï=ù Ž"z–¯#2K­õézM‘áœN1 €cɤ±×qëˆ$bÄ0å3?ʺjË"oñýóTÜÇ)¸ï;0gÞz˜vˆèÛ~XãD“•‹ägßüô~¿}ÿé»p·CðWfäZÊ#P‰ˆF%ïmÖ· ~›bÚùæý mÌևʛêçâžþcDîæï>|ø³_ýê»ï>¿¾Þ<]5´€Iˆ0…|!Ì‹ÄiÄpÞEÎ×s¨™¿(¯óÙºL-ò[ðÝO0:Âccxè†Oûð˜Úÿ{ì€øpW{FŽ ¤ºoyÜÔhöÝ`ªRJ8 á»wﺪ”óP€„„“˜à qfÀCŠ÷½å£Ü­›!qxä± w—lúçó—§Å8dßî,L,H,€’N€DB3K­†©j©2ª$@‘²¬"Úw÷RjÒê×u‘R>|ü("æÆe!ª$źêz]{Û´wÞÚ]„ø¬ûÞÔŒ‘Y†5éˆÖ#²nÖÕcÐÝ=„% “ÏühuSS ,,ÙJûè€Råæ B///ëeÙ÷­Qµˆ fš,½õ죓iŽiöéžÞ”³Óz<úBB¹¬—ï?a&ßËÓÓóôü«ò!4(K)‘S&’ÏÒ\•>ß„¹ûÄ–Å2÷‰A=ÊÒ¸*©ÕÔ×ËEU™ár¹lÛÆ|À¿Yð j×ÏŸ?}÷ýïûÞzß –9Á›]&KY ÓjgnLO’˜±üóäç[¢7I¹ƒ)ð<êé£'>ù1>ªîé_ç™À¥.eßÛoûÛÖ¬÷6¼a² ™{éÈõv³yCÿŒøb'Ȳ/8ÇŽ?_äq>kîùJ~¬[?† ?ü¶ñª23´S_36çù˜Âh’@×ÈŸB¢u]U½ï=ÌÃ<ÁMIa+Ië›yL9p ¦ µíIô$!$r „Gh2!‚™òéÊr ˆ°Ö%,êÆ„@L¥–Þ˜6Æ3–JDY^‚ ÇpÕ6fÇ€$ôÝwßîm·lž¹"Ò/ù÷ßøðý÷¿'¦*©’]Öºï[žÜÁzˆ(J)È\k-æ~½^n·[ï=Ï…E¤,ÕžÞ½'’ëûÏÏï>¿¼²Sg&‘’>õLÉž $ˆÖ;RÔZšª‡¢¹¯Ër»ßHè»o¿ ˆnv½\¶~/Un//ërÙÛÎÂjÝ!œ »vS ë½Yx`t·®Ý‘hï­õNÌ>R²€„3b)¢êHüþz¥€•+Dì[C¦ŸüÁÏŸ>¾ûö÷¿ûë¿þëûv p)‚DÂÃtgÀ"eö)Ak=ÁñçwÏÛ¾‰ÈËýfîÄGiëÊÌK]žˆ1£O‚ðÁ°8“´q®çrÁy GDˆ}ß™©÷vJÍ+½ c©Ëv¿™æ9rð³Õú¹²1P@3Ù”äf0kÓÑÔ#¢»ºøÔõDžZOκIѧiäq¬¿[D´w"‚A«€dùj­ãœ³ðç ÇQkÜ>œ Ûy78ÒóO÷}´Ãs`uº;HÀtàìãž„Eø)%{ª;&Ýêíáàᎉˆç@íd‰²É˜þ3ù"¥Dt !I¡ !!€¹ÝïëzA¢×—;MÚø1Ü173¢âÛaÚZrÆèƒ82ÄA(2)„™÷m“Rj­"#±‹€`¶ÌÄEÜAÍ`©Ë¨¶Ú9Ü¥ÔõriÚ#¼o[f‹ì§˜E¨«F€!pF€n™ZÛEJbÒ+òõOÿ«ÿê¿þÇÿøÿßü7ÿ7Õæ-mUÜzk0PDAÐOc2‘²®W$¼‘_ýêÏ~ûÛßî Ld×ë5‚ÉÝ_^o^D˜¨‰ˆÖvU j æœ3 ?¿{·ï[¸"mû}½,½íjzY/½7&¶ÐmÛ®—˶ß"Âö½×e¹·{Φ¬÷Ûvïa(ܼƒÇý~?ž3ë¦R$ivÀˆDˆj^¥üÃçWŸÿý¾maŽH›ö—íöéõõøÿ¿~ÿíïÃÕÃ<ü¾miÏàAˆ"Ìʨˆ¹‡-EÂí'?ùúóç5{Ýî‘‚²Ç%[zð£BDÂ!K<E„'5CH˜9§ŒNÆR<¢w ÄH·!t$<&´nÈ\J1 6³/eŒ=ZkÈìÚÌ´ð@’L2d%Cõ“8Ãbè¼$ |p Žf1•ßé?af³4ႛƗ¦ž^ùù: X¹[þøQ6E˜;â£&á ñ<œ`° =õ*ã>kKvU‘ŠA€‘4‰Øµö~1f K<ÜÁ#À“‰®I­&òp3­\ €‰!Çù+ÀãȆ­µôÞSwˆI4Œ75ÎH!©×©VPÓ=c"·»Ül!5@)¢cöGLÄ©–HÚú©7?ÓZ(÷]Ï„æœrz ¼ÊCŒÃlT }dìÆñ‘ŸmÆ3qúÏ„ˆá<œŒ²)¦@Ôd‚"”ZIˆe)u©ÞÚ]¬÷4U@¤R;ÕUèÇ´ ‚¶½·v}z·m›ˆü£ôþú׿Þö½.‹¹»wUÅL;l „îypS3k‘ Í;†!@áJ@„@Ì­µ²ƒu1dŠ€wOï¶ý–¦Ûá„PDBH½ï"@€ÜP˜¤H5w&º>] ±[¡û¶õÖ |)Ý€pY×ëÓ3j×®îкýÿã?ÿþ÷ÿýËíþrß ª»1EïM„‰‚J-ª;2shÄõéÝ»*•PˆäÛo¿ƒ )âî˺<¿'RšÚr}F*jþüîý²,/·©)D6^„Ü\„³S[—…‘·ÛF@Ãë‡ÝmßÉa-“nÊȤjŒy‘Ž]uÕ½·îŠR’J_©´¶'L¥–?¾{zî­ƒzÑU \ €ïíoó'äB=ÌÀŠÈöòúoþâ_ý›oÿÆÑÕºSð­ï\ Uƒu½˜::&·JJU&0w¼·ÂÀd­uŠ€ÞúZ—¥Ô¶ía.‘‡ˆŸ_^.×ËÞv@07ªËÚ{G¢zYº©Y—Â}ÛÐÃwÓ€HÎWe©õzY.‚% îÛ†÷¶cí2ËR2Z—•‰¾Ïª–ÇX÷’¨ "’¨)1µÖfQ·ä¼Çç"¥Mi ËF­w5ëÄ ÿrÍ`¯GàºÇàC'aa‘’®÷aáà9Ñ=¦¬„ÃÊØ"„) &4U'}è˜^| íMöæE`Ê0ÉßLFó8%9Õ{»É<Àq ÀHÓ „œ=ÏY9é¡ÄŒ‘BGB÷‡ í{Ø´=;aN ™pRŸx(ñ¶ûž{ àe?¾ÿ‹ÿ£Ïqãà_%’~´ënó€Î‡·`=!ÿ BD0'¤. |§Íò1ÒÁ·8ï{øO¦?˜ç©6·1a©"6žBfæpßöMµÿý§ÞÛ×_}õ'ú'¯¯/îM[sw„ÜÔÓÀ]çpùázš‡*äѪ‹”OŸ>-ëEÍK)÷ûýér½ßî €0ŒÝ4Xìàînª]U3¾ 3ÿ(ÉFû¾kï€PkÍ ûa#è­«¶H,Kk}ß÷Ïß×ö[-¼ï¯Ll®`fE ‡§æ#ÌĈ@) ¦Ôç'ÍÙ[Ûͼ·ÞÍ år}FbÓH ª÷VEÌÜMÍ”2+UD–ëÒ˜‡Dºµ–¸ÄAΚ €< Ýñœ¼‰óŽÇù.­í³à˜êív˺Ԙhß¶Ñf"Žu&èæ{o[ë[tS]Öêî·}óbDH‰ ¤¦„yDÙ&(=~}~Bù¤+Ysƒn]K)­7fþ|{ˆÞûõrÁ) I8ÑÝY*R ”*ÌmÛ…8XÊRVaf)÷¶£ÔÒµ'PÃ,ÎŽì4ëšGö]U{Õ#è—Ëå°qή6!G­}~yÉÙO\ç •¸{ÄPåÅhß´€ç3Á¡ÒOè' Ói ÷Îô0š=¢A{Å£ âô$cõÉ4ülv#`2s> 0¤Uædõý\sðÌ3¥=¡»ZÒ®q$Ïš¥'"б™ â‘ ‡åïåÁ‡Vƒ7“Wþ¶^<áöËðÀÙüMç>7B>DkˆÈ„ç×? úÁ=P ù=’Wy(™½ü!¶‚i5“WKtÞ(æšG"D¶È[Nîf¹ódð1ˆT`O3º@3@™ìÓŽH÷í^Š”"ïß½ûüéDS38NˆÌ"9j„- a˜»+¦`û ð°Þúõé uÓ¼¬L8"sÖ‘Á¼›6s5ë¥ Í/X¤.UX€k¬fæˆÜ¡Ô4í‘@ˆJ]ªÔZÃ!¢RD ¸‡®5}>÷'ήmئ"ÕRk)n–’ï½!¢‡FDNÜãòü¡ÔUêAÌ,…­ko{˜»A@²ôÓ( !<]Or¼¹·=)kÉÛÎ3åyÀÃÌÂ2^ìÔ~ŒEfÚU»©ªzïšÌñˆ0릚Æ—ËåÝóóývg"¼\.ææfî f»wCƽïæNB{kÃl½i]–fšö#À!Ô ˜…E„¥H)"Ž€,’ŽÇà„h­·RJY—Z&Z—Gé„ä{oÄ$¥¸y7ÓÖ+×çõi- víR*xÚáE©uß755Jgìq&†É…ŸCˇÂc]fNgœ11ó£Dî "e:Ü['1æ\¬a(Q§@1lÔÓØ/¹[ó[†çBŠAgEæH¶¨{ ʬéɧ<ægbH28‘Ij Ïã2B~ÖéUÅ089”Dê‡àaù;^õ$º™~€p9hìD¡J"1÷Ï„/}nZÇaä Bdž‰†Ufœ;fÜ ž‡êãõ(¤G‹Ž_PØgsŸ ËÀs!>_"!ó[÷gx6rîÓY䋘U‘ø`ܤ،b¦WÏ_Mˆ”†÷0x2€G­§ 4Þ™ ÁdVaÙU€¨”D3 Ët©…ädÑ4ë®Ú„Q{¿Ý^·ûív{ ßÝÒl€Ý‰$"=èù0u€ä¾Dp2&o'M*Ñ=„YÕë¡¥Ô#§Éœ%Ëg:[v÷"õr¹1ƒº’Å=çíò\©`ø•|:ÆÞf–šð’¬H BN]º kÈÁ*|kù;ëûlriÒ¿F›™´hã²¢­¥ÂØ|$MèOdösM<ÿ™XŽ,¼éŽ`Ú`~©ß=‘CáÍ?>cÏDº·l<}C6îYdG÷šãô¹Õñ² hå Ç0p¬R€™ øæ9@ !E‹yˆ™G³ÔhÂÄR)H\R_T¤@{¾QJEŠ™µ¾!a׎î¦0Ü´·½÷»§Ç× ª3c)eüyÊÐ g´=zxŠ!”9ž’?ýåßûío/¥´Ö—²„§0ÏÒ—Ø"…ÅYl5rDóð*Cç PJ©u q‘½ 2‹¨ëíö9ó ñÖ6ë}½\2“ŒˆÍ¬ÖEÝK]$ÙÁṑäôxH´s[f–px}½kï·××}ÛÐÖZë²dK›9²Ú5Ý6ã#ÓÑÁ€Pò¤â™2ëîvø‹¤ðòð°óÐ =p",ÌÌ$LËr „œË¹ŠðZÂòüô®”Ú[7§ë3—º÷î@̘z mÚL•„ºv5-µ¨éXDC¨>ΈDT×e]–*…0Õ˜þ>C›!ÄáÁ€ÄU»ví¹ö—R—ºñ¾myÎÏYQêZ?~üXdaÄ…ÊO¿þéÿæ—ÿ`YÖ¯¾ùú»ï?%~ûáý‡Þ{©¥µ]Í×¥ÎÊ8ˆ‰Ï >*æÑÛæ7¨uf6=<aòÜs$)Wæé“¨>̧³zÔcxö†AžØLÓ„HÑõ$œ6Ûˆr ŠBaÌôö3¤sà3ç*¾;€#šÞ ÉÈL«Ñ#§ÍµÏ8¸„eH ž¾Rm <â÷ ò`6Ûs#Ìõ{½^kd N=ysXšÓtÿm M™¼¡šà—àÔ›Ÿ‰ÇkžEC1ìßüÞÓø8?<öìUù›ù±1œNaoÞȰ†þÌÛ÷xþrN»4?¥/€C®{@)EÍ¥”RWB17KÊ}ÂG­íyÙÁ„ª¬Fx­Å¼„Á ûF$–R¥Tpë"’yýÜ=Àò“3‘"²äGÙÕ#à׿û}‘…/—ëÖš˜i©YÙ EØÌ=B¤Ô˵”ž‚<a.ˆX꺮k©õ~ß!bI‘"~zzvsÅ$|Z—ðè­‡Û²¬`®÷û½1õ²n}gÂÐÞ[ßÓ­'£—Âtõ°ÖúR‹[¿¿|³Z…˜ºö—ÏŸÔ¼TYÖµ07ÝÝ­ÖI¸HQ³Â|©k‚ìf&,9cÔÈìÐ~§ãX‘3…€Èè®chDD240¤n‘$=f^je3Sõ}ßÛ¾#Qx4íj&KUk ¥7!Œl C@)r¹>çk:zê8Ä÷1Ð'æò¥Îó|ã˜ûÉ$(÷á/~c>» 3àqآ쌎8ºË×ñ[æ³”Ó™Ûž{è`ñŒ™i¶GÓÚt\'°»#z‚1‘iMIvd¡R‰Í-Dgdf¡Ö·HúD@´Ö‰Ì\!À a¿¿¦Ì¸2C¦²ˆ¥°”·nƾ¤ $6}@%îÌ…ˆÁÑÃÖõRJ-ëŠHÛÖÖËõÏõÿÛ¿5ëJ€ñ€Å ke9$d ï½ÃœbMd."áRj]kŠSÃE@ÚÍрܔU-#aÞ÷-ŸŸŸ_ï7`u3wˆðpí8-4|4C>}˜ó*µm AµH„%Íãéz½^W&Ø÷¯× ˆ”ZʾmÀf^J­²˜)Œ®-DÇ·Çñô掟â„#íIÃÓÖ "K$ÍY{×RJ)¥÷ž)¥õn¡é­˜K!ÓÆ±7]j¤Ï//æqßï·ûÍÍ…%pù–\K©ä…©²”"$ÄÌ=õE=ÀãiY׺Ü_ï,á?ûÙÏÿ“ÿä?þêãÇßÿþ÷ªz]/@("ÃÁ& ½$ÿâ_ü‹ûí.ÈûÞJ­?ýéO×eùÛó7wÝ>þœÛ¶!ba:-;<oï$ðD%òŒÝ f¾^¯Išt7ag{ôŽãÆ?šÎQ+¾°öËŦFé\Ùì>f)º¬î° ™‚1‘ €P5=£Í§òå§R“ç„7Ô’Ç7¡|´*ã$/Ï(ËÑÉ_Çï¡1¼ýÜí‰è~ö³ûý½÷0_–¥õ̶Ԛ}w‚JéóQ©O&™o2U<‡[Ó›}þhq²{¾lÛ#Òœ:}<½NŠLçíΟÓ#s;pî ¾Ø¢Æ-ŠAn ìùyC6ÊDZ#†r$ÿÙaÌ I%ƒã`*±.—«öˆk]˜h©•˜k-­ïáŽÉEQíëRRÞÙ÷ÍLÓØƒz׈)\Šx€{tíœ6¿ˆ ÂÖ{×™Sø3Ò’Ég—ËõóËKŠ,+===µ½Ý^¿UÕçt\ÍaL…YÆ(yLJ&r 13I7ßö)ù!CŠ’>ÔÚÍ <Ý…£›e@6¤¶HU#üéùúgög¿þÍo.×§­íD`nÄRX„K$[‘‘ÎpsHRjX@­ ³¤‰Ñ08W¢ªaÖÚ#]1y@UI³‰1äÌ f‚EÊ~¿1c×ÝÍÃmðÌ2_IJ}ÿáccú»"¡ˆˆTî43@ í™ÆÄ/ÜÓhgŽ@‘¨UD ÔÒ›£›Âýõff½oj;HIJ( †‡›©­kN¨m ‘1ˆ¥L…XjYÖå¾my7+—ê¦EÄëmc¢Ëºlûöúùå~ßrwFbÎà–""2°ÝÙ‘yœž &ÁÛ͇{°Š‚ 3±ÔR–R‡¥~èœëò\DJà€€©0/¥¦¥kzG–l$›vW퉆-uáº@`!Ž·þúúº®«©æèïúôt¿ßÁ=.—ËíåÂK÷h÷­»ár¹ã}ßܼ֚&w"òúr{~÷î¿øÅ÷ß}··FDÿîŸÿÊÔ^>¿ ? úöÛoóÝß}úþse½7ÕžGÕû~ŸËjÀ)Û6‹® Ì8-!+UôS¦R2bø4XMê0Þ˜ØL~ÏÃïÐøõ`Lx¢Ê_ÂýC›ŸC{DL¥kœ¿xÊeµÓìô˜ÀÀcr²'– €%#Û†ó^$¨$OS#鞌µT#<Š;r9 ê‰?<Ÿ/Š×@æ?yã}Øþi‰àÌX«㟪žC"‡³Tu3«¶ü-—õâ¦FLYÎåò|…›øæ:ý¸R|̵ŽÁìÆ:ôF?BËÛà ;ö€Àõø:r¼ˆg?Ù–ó±@bÔT‘ô7à"I¶I×õ4M‘®MJfcºˆ˜wè½-—†E6Qº31s$!–“1$ä$¡CD„%åÙæjÏ´¬$Î&Wá/JüQx#bæC͹ÇIu|ç™ôùÅkfe<1'Ðæ|ùÜÎǫ͒—Å=åÙm@º°XXWóˆBœ&j@L³¥UÍp>ˆTñ¸YO¨Ì0 ÀL1-IY Ð#JY’h €„”3TØÌi Cð|Øh$“PšýE!:8áØj-Ñ{ƒô60 †©oHŽ ¢ñ»wÏ¿ûý·éˈ‹dH¦26™Bé]“nõ)A.R£¥3Æév¡®Dl¦µ,­í”Š‚tâí]3$·¶ïf®æËºšã‡_™ã²\^o/DT¥îÛÁ{ÛDЬC0¸yo{kTR빑,µ RZ’¥‡öfžy¥a€¡£0Eº9?@ˆ3Ól`cq(I9Í‚"i npP9wíÄí¾Í±wÓšA&ëiòÓÖßK)GÐDò/ 23·Ö.—KfÂ0³H¹ßï€Èˆ¦ºÖ…k©ëRoÛ­k“u „nºkC¦%i”DûÖ˜¿ùægæöÝwßmûÖ{×p³1ßî®@¤àó뿊Fl”é4 ?J©ÄãV:"•ZÑRY†ž•ý ñQÜ߬S„ƒË§ªˆ#ïøïÈ'öÞdQÃÔ.vá?€¦'àƒ ÃÇ " fÁ|ÃçÚañ”Ì©ñâL8¹w–×áy²^.¥æ’VQ"uY/¥ÔnŠŒœ„K»þ @d:R^NcÉ㎸;ž‚¤Á#æáh¢ÏÇL"‚ÇO?ÆãÏgçeLˆb"؉" æåéëÐCÁÅýÌÀyû•/Ëc· œ$§qn@ŽìVŽÒI3;°ý±þ‹vþ¨Ý~ò-Híß±ÃÅé@>o­EX8Õµ¨ªHÍ}oͬ RY<¶¾—ºÃårѶ«uŠh͇ÂÔKÚñ[~‚D4¢’Zk@#¥ÐÓ œ0,ÏÝÒ0÷±Íý†;y(¤>óNájàBŘÌÔ"˜²‹X\íóçWw/"yaA˜Þ9Un}sÍ–³äÛ¡a©1ãÔÃ Ž´å$¨“{j‹Ì=Ôš™QöLAD(„Æ´˜¶Þ¢íûºÔÖ´«Z×km³î±®+#°PD˜5mûÝÚ®½È5Ë ežåÝÓf$«šîfæÚ½ë®½z ¾„˜@DiàK †$ÐR™jI¦JÝ×ÃÕfãÊ\€©™†NS*w×áâë0΋̪’[¦GYɤõ|æÇzI¿%&3«µjëOOOi¬Ÿ¤ïÞßn7!nÛî™÷ýçO"2%§#M;Ûåòô“Ÿü¤®Ë¿ü—ÿrk;)9ÆË톈µÖ—ûK7_0ìÓ0<8÷d ÃÖZ[K„êJ¡R9¹é08Gøaá äZ¦ œˆ%HäÄGyxÙ{î¸ðƒþ§4îKï3³åAW'"ŠÃxòñ  ÓÄû|y§š3zIH2Ìl¦™K6…fÁ¸ï-ûÇ¡¸!Â*R¤ìÚsóvwfY&zx‘cD€ÐÑðB@Üï÷}ßCUªdCúo«ìç½äØBßtæ‡q2,Ï¥|°ÑÞW¾|2ÎÛo.•‡ÁL‹=îF21D3>ìÜÃ14ŒÓ ".uU5"fáu½HS ¢ÖŒE “-‰ Í[o*Tk%¢º,°åèïPlçd4ùHè/ íŠÌYs¡RU9ÇÉùΠð$¸AÄCø0 ñ©PU˜–ÑÄøîùƒªöÞÍÒ±³VmcMçêqƒ‘+‚"HyjÎʳó‹!є΢ª–"½k©‚Ì$R#@¤¨Z)%Ÿ3_–¢ª9Êfm !ú~¿o/ÚZß·ûíÉ¢”™Ì.\AX1ó£ia ‚¨½µ¾™vóŽn€ž âð<šDÒÏš…›äD"ÌuÔf6YúA1ñqŠöˆR$Ý7â`£9Db)"…Y´éèÃ…ù ñ-R pÈŽr6P¡î¥7KFÖý~OР÷žÃ§ËuÛ¶wïÞím'¦ ,eaÀ1lc$ wâúúúú“Ÿ~ßúÌ÷í^×5ÕLêÖzO§¹Ö†È+FêEú R&;öÞÌ4IGqTí>Tèè˜Ñòù0ú¦4À‡$–ƒw.©yÇnãÀg͉qšÄá6|¤Îµ?¬_t~“_8~|àÃø‹Ñ ‚O€.}úpøÑbÚn¯ë¥”Rêr½^K©ªj¡y¨Mº”º,—õ²÷öÀÜ¥¬1ý*ç› Ts[8¦ pèƒÎÅúñ³ƒË~ú†“8èÜüJ)éÅCLI6y÷îÝv»I)ù†»¶|ÀñÈ­4žJü[@&‹'M¹# ÿ”ñÏøöÓ7'Ëþm/xþ,cöGÓøu9÷99ûï‹ú;ÅóÄXûñø«œñr¤Màèù"]αÓã‚g2{TÔ½·´EËÏZ§UŸÇKèÙOÌe™pÑ!¥ãÀxÌNØàÁ„‡¸ôaûf“œ à/€ì~Ø\DÒû÷ïÿèþè¾m{ÛÒ[8ÿ–ˆtßãˆôhØû{ÇEÿ|Þ¡7 þé>Š;OÌý‹ëÌýñâÇßg«{Ʀ„xò©¦3›RûqI‡=rÆ_d‰€Ëzy÷þ}S3Ó}Û‘éº>×ZK©Ìr½\LÍC÷¶W‘ÌkÊ |Y–ˆØ[K®ULÜ??Dó`„L8"ưwq×n® ®]wbBÚtHÏÇLµ Ö½·R—õrÉÀI3Œ0C÷A“M-n¦houY—e齿{ÿaß¹m€TëR—…ˆ»J;H7sX¸"äiz­K©õàÿF¸›²HkŠ˜‹˜ªé®Öˆ 0¤0QNáz8¬ëâ®kæ?¸.¥vÝM{¸»v B $l}'d3)Ù·e³…™ëºTð B4Sˆ0¢ˆ0í=‡¹L²GJ¯Çs—'ÌyüzœöˆÐÑS šôž„%Ý•‘ ¼µ.…= L{D<¿¿m[kÍ"–ZÓïÔÌÌÓñ<ǼVk¹¬ëû÷ïï/¯æ†i»1mãÐL‘ ´õu] ‰–eA e]^_^ ‰™þöïþîñ‹?ûó_ý›¿ú7f ȉàgج”×××½õËóÓm»‹°«ª¹º»šf\­©½~d‡<~U& ðÙåæXñ´Œ>™…ÜléF6¬È0¿‡%v¼aØ‚ P»×²0ÒzyîjÙ#›ëËíóÔ¾ ¥a$F€õ¶§*]Òäg¢SŠÍ{ïÝLÓÆÃÜv¯HÚ6 p5ó@æ>èžù ƒ@æn¾,K©rµnº«î±w@*¥X #)Eª[¯,ÂBÄûn¼ï{¶Nû¦‰þ½?ýe,Ëúôôñóç]ju e¹ BŒ•‚‘²\Àº.u]CMÕÜ#O0èê’¡™#1{÷÷ï?Þî›p)R¨ëNŒ„ŽBÔ{³Þ ѵ¡›L?¢äát3…ðp0í/ AŒ€á]½ ©î€áª}@+h€ØzŽOhYV&v·d/˪¥ÖÞ»Ô¢624D(’8Àµsô±d¤H J­ªþîýÇm7$faó|èb×™¤P©Âl®æÊµ=y&á9Bëj©ˆTD„å¾oKEÁq`ˆ¦Ú´¹)tëÝT#~ÿÝ·ÿâ_ü‹û¶Åð­ô§ë“¹!!Æ bÆõZ ,ƒ^»jâkLLBŽüþãG5C ó† &k.ÛO3Ë|öžv³eYÑÌ¥TD63`rfI÷sD pD!©…{kÙ,ö¾×ZT»%I/m¢óĠ殪ájŽÉ÷'~ŒRGk?Ö&í2—2(*Á¤ÜW+‹1Âqr_“E޹M;K‰!&À*„¦¦ª„\!†ˆì‘ßãæÇ9@]Òe‘K½„‡©…Ç{ÌVåhc#sÓ¿¨|_˜-Ž8ÎLCpî²EÄÄÃ@&’ •v©¦á,’|й×QfÑå& ÃWrâz:%}©!>5ûÇ6û8›tœ/G©Ïéh»Æù&ùà€§sIVU›Þe£ág.Ì2Õ]¬?ü,YdnÎÂ¥Öûýžšì¥JÛ÷gB*!7Ó–Yšc ©ŠV8ö•ÑoŒ·ÂÈtÚiµt:Ž\cW@f)RqääÎÅæ.R¤ §aCþàR.ÈòÓŸýáÞz>ÓEøv»#•Òš®—k©Ò{áÞZÉLz ÖÚßýú×îNH×ëê¦)þSëµ "^Ÿ®ïß½Óî»¶ÖrR3³0ʱy8K|;À̤p­%4£è½[ï˜Þîõ5#)Ä„fÝͦÜoxÃw2•fÄÉáð‡dÆÌìr¹ ¢{,˲o{)%ee½÷ð°°ëõÊÂî^„{連þ…"’y³M{Éà:Áí¾3óåz½ßîf'jo~`HD´[Oz±¹çÝÁ¢÷®ª1Ñ"¦ÍlY–}ßÿäOþäw¿ûˆ,u1k)›"¤ÌpÎÓ>¦‹ý²¤ FK¯@§çwf¶mqº"×R»û¶ßÝmo»šuU³ŽE @¦úpI> ˆ´¾ãì- |ü·c=ÖRÜ]ÍÖåšnÆ@ÂpBfå™Ë>ÆT6çá]Í´”’õ0‰ùùu(Eð„”cÒfÆ+Àæ‹´Î7´éƒäŠ«ð1;qq˜ç¯º.ºïù¼ÕZ[oRJreyØtcÚÉh×¼Œ*S‹ ¸#•Ùº>ªm~ãqYÇß~QÜÏxȨu“è8¿ƒ)IKÈ"#õí¾G„cä˜T)uYjú¤¢:Bö5 ó}"u‰ŽyjJÍàd×yþßÃ ì ’:áËdT8Ñ`Ï“Užq%Ã}å8ä>î‰0K[Ïû>Ý_™S³AWÇ@óp7 ".²m;Dìûöôôt{ýlÚ̺0»¦.Ì <£["Ücx¸ðœüxx¦É wF¢E¸já¤Q œ pŒ8ÐK'¤.M_mïÛvÙ¶»ö‘Nô¸¬×ðþ_ÿæwë²fƺ.áÀ\èz}’"ªZ„óüÛ»f‚š===íû Ûý.ÌáZ¥Ü¶[­•_^_‘*•""lÉ*ÉkL-æó7ÄB(LÚÍ\‰ør¹<¿»â€þ†Ô;m¥‰æ;-’‚ršÙ]Žÿ¥cü%Ì2š•|ƒ™a¤=‰@ÉËâÖ"–i.ÄM[f^33 …;àxµ$ÌXøóÓS@Æ?Qf¹µëÓS]j©…‹,ƒœbT±\e:”MáÀ„DB\¥ÔRI˜k­€XkÕÞ?|øðýwߤ¶m®–åV3—‡N7–™s3Ä­íT$îÛÖUÍ}Y–ôÀhû®] }o;Õ²µ½öpUeb÷À@~º\.—‹të­ Jû‰FldH„§òyýö¦ÄòîùýýѽÞ^“8ËÈêÓ½g4¦¹éªÙív{zzZ×Kk{ ú„¥ý¸…Ǽ¥<×óõ¦<~ïø\Ž+?^2ÎÅö(ºou©D\ÒouY€¸õ€HÞkéìanG±…szõõEû0Eà‰4=îÒpŸ;ÒùŸ†“ãÍ“–r&xNiö—uEÌô¸3D27m¾^/­µaÆ 6;t$ÇÇöN3P 3ƒmŽ„ë/?± ÍÓÛ&Î¥ûÔïχüxQúP r^5HrÃ}l ¨ƒ inš˜dÅ?¦»#( ‘˜K©R˺®”F"×Ë¥µ½ £9a´½…k¦½Cz1º™ú™r9>³8\ª²­ŽR%E.L$RDJ- Àx/1È[ãÖËT´Œ5Bd~÷áëü§ÿôÿô¿ü/ÿ?üp`ß7€Œ²[͵µžT®R„iXrGx©åz]·íaäæf™pMÔ{ë¦?ûæç½·Ûíµµ K)Ù*DfŠæ#žãe"ÔÞ bY×7uÜû®¦Uø ×Ÿ/ÍÈžiâG†}ÎJN³ôA‚Z¤ qжŽ:’žkD”ÎK”Œò,ù¿}o¥.ÌRëªj­µ  ÇÁÜ~{ëÌÜÚnî]5<®×§mÛn·Û¾ï­7µž¸MÚ8;M0ï©ìÈ…–νjèQˆmž Ñ£í»ˆ,¥"ÀZ‹PÉ(8€lYÊhþ¶ÖQ!(G|¥F¢ç§ççççÜrnÚ 2dÕÍM•‰j©8¸ Dƒ‘žžTùä©dŠ‹>0ÌÇËRJR˜ùvß–eÍ#Lò¹²#"-˲m›¹%Åóåååéé¹Ô “¬¬ªy•q*u€ ˆŽu£ œÖ×XQ‰W~îDz†áØŠGI™ˆ¬Ïµ/g{n*"]ÍÌIKA©€Q8e0šù™¨œù „‡¡sÐŒøš¤DÇ âÄsÿ1Þȱìgq?ÎCÇŽ2*ûh±2jàr½~üø±÷vTþD"F¼œ©2ao 8gK©XæÀ¡ƒxøMÓœ‡èˆÊ~ˆQß~Åy€EƒÕðF–4#tú:ŠB¸ÀYëŒÈ,çÚñ8ÓêpôÎ8eQMÂ¥yz)jY·mK†hk­ÝïD¨½ïû–šUÈ™Ôñ–º¶óQd>…ÈD4Ä…ysÚ `H)µ,¥”Rjª`"OÜ›’LHL…ʲ\.ëõþäïEÀ÷ßý?’.$LjúôôÜ͈™ˆZ×Ìh'@Dß[/µLë6SUí;"¸vµ¾®‹ª~ý“Ÿ´Öºõ§§§o¿ýÔ{ãÂ,äáj–ù“ã®"ÌU–ga”R¶¶«91»‡v+üXœÇ‰Rf¡ªÚ̺YÏT¶äS>øNYÒRRÍp¸€©¶Ç®Oiïì3jjHs‹HdßÐ^Zæp %ËTB©RKÙ¶ír¹”º|úü)÷Þchö©î\غ€ Ó,%uk”õÝ܃=ñv»}üøQ['¢çççðLסtsLÚ¸†±sß[KgÄ”¿‚z @"òÇòî݇——×Ûíî%Ö˪cöX¹,uBûèX/)k‚Ù9Ñ8Àë£Yœ0&C<Tï}Û6·!@…#·ü¼ô ·6R;pˆ×u%¢ëóÓÜÝ#õ€­äÌL´„ˆ’R1¿ó¢øÜ%œ[@Äá§rĹ=Ưڗ°L‘}ß3ñWþçŸ>}ö@"~ÿñÃðgDG"N×Ù£îÆdc8°¬—„` $SÁlxby?ŠûIxyÔù£À›÷‚óŸñ¦ŽÏ ܽµý¨z8„^á‘[@d=ò ’ôqôÑ‘ c™ ‰¿Ï]à-uýØ“¾ÀÜ ã¾ ËdM>ÿëi·ð a9öƒ ¤íï€w6 Ge ‰×å™#}`XÍÒr mŠÄD¨­_.ÊáD¸¯ë%w®CÎv\¿›2ÚùÌ1Ùp\"FZëô¡¤T1r~NÙe' ˜FíÎLµë 0Î"‘üµVµ¸½¾|óÓŸÀëëçt%omc.ëºnmg†" ë*í~ß».KH öýaÎŒjZ—ÛvŒìpK)]÷}¿÷ÞAD2MmšL4ÃØÌLˆÒÝH®OïÖëµÔ­m>ÃÅèd+îjÍ]ÑbF9Éy;Ÿ§¸!Ô79SžÆþY;¾úøQUÓNCU“š¢å˺vÕËå’ÞUH°®kꀷtW äL#ÊÁ\k{2¦ ƒÜ¥™ED¸°p$w"çXî6šžé‹'Âë²ÔRÂ'ÄŸ{Ok­.µõÖ;:‚Z€‡;B‚éi” ^9:¦µÃüÁ2ѧOŸÌ¬»-u5óeY(€1§D¬¦€\KÍ–¢»öÞïûm]/DD˜>þɆÈÇ)%5è¨E÷û½”²®kîgÚ;2±†Åþ©¿‰°u]~õ«?GÄÛý¶®ëqÈ&æÜÈs/£axJÑÛˆ¸¹ ßGËûEMa„j?Vý\•žÇ8Yž.ב¨”Z×Ë7ß|óýçÏ­í¸o7íVk½^¯RÅM{of.R`Š4À=Þ^Ër9¤IǦcÔö¦>žÑ8èðÇûœ È*Ió‘Ò5zkí~ÇчØ')CÉK3fžÁ†SCý@©ò:³ÖO³Áö$‹Ò€IDATçOèôN=ü”AZ϶ӂþR»›ÿ{²88<Ð ¤¤ͧ|ˆƒàΓHAavKâתêµTs‹÷ï?ä—Rö}+µ¨š» Û¹|kfƒ5 tvÃY䨅2™rtšfš ÂàÎÏ>%÷$í ˆEJ].Izsí{»ûí§üä=\­›››^®«v%!Õ΂¡}ˆÞöår•éj›±E"\J¹<]boÝ—uݶír¹Þ¶»… ã²,R8µÙ3ùõ¡Ž&N ]@7%‘õrY¯ïd]zëRʺ^òó@F>Ù¨ªî†˜c+Img»;4L}¬¥W<„13#xêw’èD*¥sf.—Kï][/Kýåßû¥–ï¾ûÎ\š˜O©¥ˆßT³ì~ýõׯ·ÿGÿÑü·û7fšÕ* À‡)ÌÃC˜‘C­?ŽYˆ„hááž‚›uàøe]·}swG(µÞ¶{øÈ± @icH݆â‘âp¼É”ÇÖÚ¾·Öûí¶yÀ¶ßÝŒ‘Ò\6Ûm}½®Csd~o»™çš3d¢L‹´Áy0á褠ԽôÜA³Â¨öÜuÎR’Ò`¿ØaÛÔMî,êÇ1çç&2 êryQY<{çÍrDЮr&"ªD H`šs°4?Ix’£„c ÁùaÀ#Ä¡®y³'ŰbÀÐ3µî<œÅý(ëÇWn~ˆëÎP#íÚG›ÅÜ 3ÚrXÐ<t37ÀÞ{)K-5,Öe5ó÷ïßóÍ7//¯­í?ÿùìm¿Ý7ÐL³Ë¡ ŽÛH[š˜ v¸{Y*feÚ´HÖ" ä ‰æ)ú Æ¡ïBJ/—¡Èp7a1µÞJ©D覽÷¥\ˆ©·ÆÂ­wf¬•o·K€õRÑ´A€k¯µ:Pê]!™nˆPJ Ünø/þ‹ÿâŸÿóîãƒ0ÕÞ›vËó{¤|ô¤ ÏÛÌD¥ÔРu½<½{çO×çËõé~ûÞ“‚Ù—Ž² £q ƒH:]E$s=:žósb^c›Ç„A·mÛ¶-‰¤µÖmÛˆhßwD\JE”ÏŸ?oû&",èî½5(¥Dø° ˜ÀOŸ¾_×K©å¯þò¯h.Z˜‘§Ó÷ “X=^¡«0 ‹›±ðˆFê}€Hîp½\ó}í­]ß=oÛ¶·¶^.ÀÌÔÝÔTÇÝ &n½Cê›.—0G&U LŸ‚ˆ­õçççÖúËËËårÑ®ë²öÖ…¥–5±AŒ€œÜ=Àpp¥™¾¹aPú‘ •‡™‘P͘¹.% q›ÅýØ,óßf’jZõñÔÁt/¦”£àˆ»RœsÁQ¸ã±¯ƒ;‚¿ÝŽ –ÎoN¶Otó(0†€?¨sŸÎN`æK­Ú1’V4Ý41vm˜\Ìsq?ô“Y»@Ò½(m£4CÒžcl?³v'î@@#ˆuæE:DŽº=DÇΖÜX÷cÏ9Y@&9 C¸£¯J7ô¡÷;ÍT§}Ëøey`>oš'q*U)»èÑK?cçɆ)Ù`Ç.„Sqj1F³”ÜÚäŽBé½EŒ¬²¥.éÌ 6E¾ä€øôô îN…Ì­Ôbá@à·ûýûï?åQëÓ§Oî*„À€)¬s³Þ»»1“¹fJ'@¤ñI~HÃ Ž‘!‚¹—ppÆpíŽÃ‹‘ÐÅ-áÔÈ f. ±·&¥>½{ïÛÞ¿úêëû¶]Ÿ—tÈrw„s7-µš¹¶®ûNnaZˆÂX¤23v½Z¸¹[­«;zÓÐðîæöÿýŸÿg@€ð"œ.ýž¾1Ä„,Lµ–®ÎéZN@RÖ§gŒ²,+í÷û¾Ý_>}nûf[·ÞÔL q)…ˆ3ÉÐ óTk]æ‚Wt Z× ²•jd.$Xk¤Þ•…‘)aŽR„¹¡;ã0pJ×´p"\/+ì­5ÝM ©nSM&ÚK& FsK‡ç0K?p&€B†œ–‡L,}ïEj•E¤víRÄÔÔ-ˆ ™,\ÑQªH˜]–eáüpä~{Í©’ÄØÀÜMÍg&ùh¸ÆÉÊÃm„átµRŠ&Eí Àÿ–¡ÐÌÝLÇy‰HJ-¥P>¸i4 ™tÈ€„$Ì…¥\¯OŸ>¾ßoq]–ð@·nfYUç±&aƳº/#ëŒC ÷ÈéM“œsl9Ó, [†œ¸tSí8%0¾={i׿îª`"’©ÙÈ£©óØ=ÌœI’~}¸klûV˜Û¾ºÙÓå’ø±»«õÊŒˆµÖ1‚IÎ𬵪êõé2ìW‰<¢–Rk5Óƒ„‘=ÔñN?sb.4'ÂȈ€t<çê÷%Aã˜öߌ3àÓúñþÏ«ž0‡#B2!Ÿ˜®Y\.fl­µÖr†‘3›ÃKg2ѱ”âö°¾Å=ŽŠü˜CÆQ²Ï%˜§µæÑßžëãAšdù/ðîÓ×a³yF¯Ž9Nþ¨Qô˜Q×çôüfy?wÿòC8c8§;p>ƒÃ ¿!¿Ïáþ£—÷¤a)9Ûœ/‹é:ëãL9‰Z–ºï-"˜1‰Í§ƒ31šiÛïIqƒsKaNŒNaÜ®7Ó¸AiÄÅGºétÚsÌÔcÛ=PV6bàL®Ž››…™u‡,u½oÍÌ.—õåó§÷ïßíÛ–êNNó(€1idÂ84>^–5ê²t5xd³ {2Õ®MÍûpk˜Ë7¹ö9?à°0Wd¦€ ¤tÕA’<‚~õõOÌtß7ˆ¨Rñ²,Ûë+€}°Å°ª¦áAÁ”^cÄ"ÃÏdz}hï¥Vš×@ó)Ím€b¬²¤Væ­} js Šƒ‡îî]uЫ&ÿŠðmÓ3Có‚™FÝç™ê®yÌ-,k)K].ËêÙ»Q¦0æC{¹\b¼© Øs~¾>mÛF„Û¶›91YWb^×õõöºJÍçü":#„ 0}ð/륖zßîNááO×K‚ofîÖÝUϳ‰xx·ÓܦHIEf¾œùá1ùx²£ÿäºË \Séš)Ò)ï­'l{ª9ÎÈñŸ çõEqÿ¢èO^åû\?‡|nþÒGñ!†i;ŒÙ>™é¶ :€CfO6JÓÞ:2_¯Ox¿ÝÏ™‘%¦£*À´ÑÉ_ƒÓ^æT9Nëé¢qvîG}ô`¤lX ðøÃ9tü\^]ú¨È»ŸCB8š€FLHÄhŠfHêô?íÇ/}ÓæŸ6¤óàûøþ‡ìíÕ>jýcx€RŦÕå¾kûÞ{;&™9&òÙª¤¨XR|‘á±¥²e x TòæîDp4“mn!$¦nîI…ð0ÂAæaâ DÄÁ¢#âjºm÷ËZÝöÛ-ýsÁ]çñ3Ý ›âœù çl¿é½³HRrð)úñIpnLA)h†a€Yð4Kx]JuWƒéO’QËóäìÃdÄ"DæaшI…d¸!@)bfKƺÖúîé©·Ý´¿ŸwBWCÄ„þÍ0ñ SSpˆ­í4O'Ù8 óz¹´}_Ë’{¶Oˆ5Ϧe©­5¨¥æœ7+#23&ê­µ¾gë%"Ž@Œáãu Â󼚧–RjêéÒÁôXÑi7™ïwP$3-q¨ÔóÛR»óX¶²MÃr݇»¸¹M¦Ù`ç9üqÚ÷$†¼ýïÇ1†fàÄ©¹ÅýÜ)êÙ<8‡ëG¥!Ê‘<˜©ö–e5"[ïÏïÞ¿ÿðÓP‘Hć( €å¼/ù£w~Ôô7í¡ê¼šcmßLD<„DþoëÜ¿¨’lžüíÝŒ¹_#…9Lf:âà@»úö÷ÄéÕ[Áêãz“R“ð~<%:~¢ <¶éèBDÙG¦t‚’øÅ$ᣚäéÿà¤.ÉÍ"!Nó.ÀBÓñ˜‰™…]Õ´§ç ÌÖ‘œ–<úãÍDL{¹eYi˜,"2 †õÔSÑ‘.ûÞºz¸umÃHÃâúüüÍ7ß¼¼¼°ÐëËËï~ÿÛwÏ×}ß3ˆËsxŸ^©ƒë‡¥”ëåÒ{Ä@áÀ Jîe4‰Þr$¿å" R"0 ’Ò C=Ù¾iTÍ\êš0z'mÛ†R(ÜÚ¶1BÛ7BDhðÂà BÐá&Ÿ s`éÁɬªé0ž’i8¸Ï¹_ ‘PÞ«Y:rf8² GÒd²ž™ÝNï:Y@ü <Íè /ŧ·þì*‘ wbòt´GØî[ë½>­‡ã•Z»õÀ”Ñ ¥x˜2n‰–eM ʰè"r³„ý@-ÓÀ! ͺ,)µËõbáÉqD€e]j)ëõ¢Ý̆6!ÍEhø;z­5ܘI’@ˆ™éqú²óJ<ÍöΈnµâ܇EÄðmO¨$“ &°v^òÇË2 Ây‚8^é\ ÎøíéŒçN|ò¶Ñé¥U& K†ý∿`/LÚEïír¹”ZÂÊ>#DxÛ¶ûýȤfÛvWÕó50äž3QŽ88:è1M¹ÎR=œçÎ,îpÓ§mà8Eׯi"7ÿ #˜0ËQ9'û…νöQF'G\Ð\ûÁÈ#ØêÚŸUo+;ä@pÊÊps}Ž·ü[ËÉ3Ãù¯0‹¹2fùtˆ!1ËB,µ®µ.¥¬À‚(,EÊR꥔ 02¦M5Ð3¥+À 0ܼµ]»Ž©årC àáíˆÇ0ñ…ωšÅ¬# a†ÇÉɸ^.)ìÌ&7‰Ò„·Ûëßûå/^_>çÀí~{]–%lÊ>ÖË%¡À®NÄIÅi½á°µ&Ò©TÄ™.€ƒÑ –MCgn˜R¾))EÉÝáʌ>¿|RíBÄDf–úȤÕÇ å¡Þ§Nu&?˜¥»Gd†«ª™¥{ɃnH”˜ ¤{lºâç“þ‘—7 ÓórÈ óÑu@FJ/eœka^a°PR§ÍÍ\³ùF5+µjïHØMïÛ [¸£0dΗ¹·Þƒ‹ ˆR+õ¦—Ë•0.—kJꈨïÍÔÜÍ ƒ x,4Ó¿Öz]/­÷®]JMc²ºÔ…‰DdY.ßüä§ñÝçOé1÷ôæa&7@ÄZkÌŒ Üz§N¸lœJøãy,È¿Uk6 ½öà0ÎCˆD˜$ňɡ<°£­ IP.5†òmw8K\Ö ŸûÍ›ýå‹Mâ§q ÂG‹5eáÇSD4òï€(É$æó9Lÿäy–uÍ(ã±Q‘Ôs-˜'¦ˆLV Ź8íêƒ%–þèjÏú¦@"£–vŒçß“îþƒ[áã˜öæWàÔÞ›_4oÙ¹:ŸöàYøÎÿ~ôÌõÅù¸Ú¹3l7æ¸!0E+IšŽfÉ’jT2S_–•¹Š”ZÖu½x˜ˆ¸«»©©Y ¢©Ó1(e(ö1ÝOc<äÃqeˆˆ 4"TÀÃ$ÆÆ€ˆ@…»š°0“Yï©#³Öá׿þõýv[ÖªÚ?¼ÿjÛv9&ðèL(L˜zm&´í–LÉèÖ—*„”âä€TΣ;¤±Ú¬­^¹»'8°šLR%ŒÁ×BB@TÓn{¸¢ö¶·{€[oÌáÛ¾½aÈ.¬ùܰP€g)o‡9ïfF]‘@#‰>!0ÿÕg>­°QL7ÒÞ,öˆÏŽ|j$¦ñ+j)Dæãnï ÄŒZRj?&5¡mðî†ÂŽ`juY–Ëå݇÷ÄâáÁ“Yïî1–¤JV…KLÙÎH ïÚíðH‹0Ru]½ÀT}ï—"¥—Öu¿ïsÐÞ”ŠB`–R ˜Úº@Œò}ᜣÆH+<‰(ç,ðtÈÕüñëy`èJ:£)ŒÍÇl¾r:Ûc9“<ŽÊ~.oÏúZ2-ÎSÑHçÉéRÌÆ”ÒÚï¾)DªªõÖ‘‘““ãnHhnª]÷ ×u1ð¾oL·œ7ÅýÄî|d&eçqAsWzCT?:wšÕæá€l޲8ž÷¸G§~¦¥Ÿ ò›2ýà…À„„N[Âë_GbÆ£XÓ~¾ý‚·~Ío6å¡ù`D 8FóIâ&w¯uMp&5A0ƒy¶œ‚$H‰<)tÌR¤«BÓV¤d‚Ípíô~±ÖÕº›ú° ›3½qag—Jdfs ”¦Gú©æ‘! ññ™"RÓ¦jEª»·pËycŒ¡8¼{ÿN»~øðÁ¶}ä¯cÌ_ àÐj­K]>|øðòò‚RäÿøzSUÍŸ‰E$j]ÃõÐë3'ÑSJeÜ FÕºÂi¯ÖÍ:D¨Z2A÷v'ÄÞ{aq·Ä '‡*›»¹¢ˆ¦ ™+“ ¢ÔšúÌRO3“\ê‰/O&²2q„˜q°8,ÜK©9^›GÊ9šÊ¢PK}~zÏD½wôèÖdzê€7DôÈ<‡J#?}Ùö˜ÔK)[Û#á,€×ÛMM·û½gzWâ<ˆ¹é¦1Öº®Û¾©ÍXŸʘÝ7ðvp ÇXÖå~»1£æŠ(ƒ\Dá¼.  ™îî63|£›-ë²ß·2‚ØK¿Üöî†LÝ8ivX¸º{e^Kùðîùw¿û0µÞµéï~ûû®ÊÌ“ºb†á*¼öjèØ÷tˆH4çéôôü.`ùùÏÿD¸ªÚÏ4K†QZV‘†æ€:³û$Næ@2ÛÄI‚:FP”n‘™Ýä°â Í”„)BBSÝÛÝÒ„ž x ߎá7¦ƒ!’˺l÷›öÖzóA¥IÇïñÈ$·M"xXðçàð{Î^1F-ëêæLøP›{¸ù½ïHdªÑíùéi©µµ]˜ƒ̽o{>?[Û¡ÈçÏŸ—Rý·Æ"ªZ3¨ºw ë‡!Pßû²,"p¿¿R1ª*F@omô!Ìa½,,´í¯¶í·£in„&ìáS^iÀ"…Iÿ C„3—RYa¤»uS3ì”Ò%1°µ¾ïíz½"Qq&±Aúróº^̦¹ ³˜™öNŒÉŽi­««¶ffÛvGA 5 æ:¼é /C’«ÂÓåc].j HnC7È,¥ÔRJë-" ¼÷¦­ˆçåry}}}÷üŒÓ¬øOñK7Û·;"˜)3Ήû¾·Özï·û=Ÿn¹\.ÄîNó¼("nnÞ'$'[MOžUJ@™˜‘/ëõùýûwÏÏ·Û äq•™òÐ=LŒÒ…Ó?@mÈw="ùš/"D<ç›G-=™óNº¬$rµ ¸^/MûÞ[©%çÂ)a¯"€ôÅY F¦°3’ Ѻ^Mc©×ÖTC °HYëº.‹p ÷¦Ê„ÆŒaéHá&\ö¶_¯×®]M™EÍ÷}ïÚÖ“A™)Ò1:bÕž-0ÒF&=Í,#RGU€yw7Õ=MTÌt°ë†ó&¢P™¹K‡æß~û-R¨6m½ˆôÞ™DÕÒÁíùé©÷>7‡ ÷™þ±<éíy:œDR8¨igŒk<'ˆxmù”aB<ˆR€&žF“ôòÀ…#ÆÚ»õ½w9$>]ÂǨk¶y8 Ê0‚XÇ 2²}Œ»¦ÀIãpjáIUd"ëÄìÌ’L33ÕtF¦ž*ŽAï„ZŠ›‘«= 3Ó©µ iY×}ßB=¤”ncÛvµ\õÞUó{†mË[˜à¡ò?#1mK⭵7"Iƨš„¦Vnô ù‚Ãä||²s@I²Lô0bf–-}§â~`8òô¨ügm¦ÂÜ‚ˆç­ Ñ4¸ƒ)‚®|@vo Ý£«aoŠàà× ¡HaÔ%D?Î5ƒs’?rþIƒœ~Z?è|‰èùùyânšvÐãXqnµ¿è©Ï¿htôôæM0Ùé뽯?Ÿ Þtë1<š3:†³íÄZ–<\ççG"Ãôb0¾€RÉbÌR¸\žž¤,ëåéŸü“ÿì7¿þÝç——ï¿ÿ> š[×ReÛï¥ÖßüÝoÜãz]‹ð¶ÝIØ]_>}y~6÷¥Öp9¢Ìlþæ±;ÞF¸3 3Î U«µžyW@ÄRŠö­µÆ½7æ}ß|]/—Ë%"–e-¥’jï­gÌ@ !EŒt˜ãØ8Ï™óIÕ½Åô9Éà‰‘€Ã Âɼ§YJIeTfH¥k¦™i·O¯Ÿ{o{Û0¼í{D aæBd±6ÓõzÙ{›õ"rfÅÇ'ïî¹h®ã|sZÒÎQÒ uäÓ®ˆP„!ÐÜ×u-eé]‘‹³¹wëêæÃ~uì`™K9YÆC\ sô5"ÓàÀmßî, fwEÙ ï ©|Ÿ_ËŒˆõž ò±‰ª”Ëz ¿\.÷¾óÌ'±®k]ÜŒÓ dไLîž¶ÛëÍfe®ëJ̦š…,éænî»v@H°?—Uä‰#}{`Æ:Œà0YŒ/Jí¨ò£á›sÅüÉĆgì0A€Ã¤†L⟠xfÃõôyO£÷·’ûs+}bÔœA‹3 ˆt2ýMFƒŒ(iäSßy’Èáyz,ÂYd¼gîÁ(_îH8FÀœ¶jC sl _v¾0àšøÑòúƒ";ŠÎZ—© 𬡳¨>DRç*ü#{Ôü.:lƒ¾¼ÝçßþåöðÅ«3‰¶ˆH‚ÄH죭ËT°"2øÔÉIÊ·0úAfq".)Ù‡1>áZ꺮µÖÛ}¤e½üÿŸÿ)Ï¿Ÿ>}Z–¥”"…DÀ¥©6ÀRöÖˆëRs4¦=ŸÀËr‰ÄrFNÞ›µH!aI\¨”jjëº"8˜z˜%K]DJ­Âèî<Ž:'4OæûþÿçëÏšeI’3AL3sˆsîš[efmªAAÕ`0Ý 4º‡i>p¤H¾p~â¼ð/pŽP„|i!¥)]]YUjɪ̼û9îf¦ª|P3ss³x$óÊ]Ήðp7SSýôÓï[Ó|<ŸÏÓ49gªM¨šOdyvf•™ªbR ÖTi ;öÒµ¥iPBl^»HàÒö)M~ªZ%ƒ¡›^zÃÁRr/o=>åb½SJ KiýÉ)¦Q ú€Òբ걠 ª‰Ûºê–§Nãð Ú–=éèF‚uòœ3Pû˜"RJÞúóê"ì»ETƒ§têÚ>¶.àåì쪳.RêÍöþúËîÀ¥ö9ýé£[<ªU‘BŒñp<2’‰¦)©êÝùžˆÜ'­ ¨N§Qø€šÖ>„y:œ=ÅdxÉYU/˹ւ·õ~¾S}™ 6Ýþí¨ Uz`mæÖžø‹6Lÿ Ñ€úâoѰVlj‘ÜNšÚ`hq* Z„¡NS2© hÞ½$F.U|ȼ“W±'¦›vX¿þ½ Å>à\-î~7¼P°nÖFŒÚYÔ4ƒ•:†-ßzã‹‘c×ùº*꙽™àŸiOHêP?U] 7VÉ>ŠÃ.a¶Žôy}çv*Üu‡˜ï¡Æ« ‚Q3tBl „«¿ƒ+±3Äý™4NÂý±±Šy3ym°·x(°›úæàμØý•˜R Ó4Í)ÍîÖ H†6§×"§Ó©ŠäµpH"†¤77·ëº–Rb ïÞ½Ž)Üß¿ÓZ 4ç5çÅÌnnOx¹,Ö^QÐÀdj1ÅR¥9³¸äV^))yÑ ÎM–*)¥\ ˜E·¾“ZrÍ¥ÖišJÉ¥–Z\|F¥V/u§tæÃñÖÛ䇔ó¼älæyvü·#Ä@(¥h_—Ôë^Øé-3s5ìvà4Gr ¹\Š:ìDÜÀË0±[*«Þžnj­ªx1kv¾Ø`ýˆÜ5ª¬¹”ã›Ä¬9ExÚîÔoÇUj­ÔUJ:ík`î¸æ,ªÔ¿Óa¥–dª;›ª¯­Ð¯« Òƒ„®·Zõ#>ßï|gÜ–îž¡»†ä¦ºDLÌ?f5'§V‘£ï´é0‹ÉažµÖËùìHìZ²˜úŒ5D§Óéñ£G‘¸ä\šû—Ûz¶Œ±æRJ°œsˆ.ND%Ƙk††­ûñ*„``lsš'´4hë:/k§ï3}Û§ 3symÝ[Röú¡„*¥úÀ; 2#WìÁ¡Bˆ@` ¢bRPbv ²ýZy0ü8‚ûȹ±7rFn¼CÉ[Ùs5䑤C`6Ü…£þY¹Ù¸YŸŠºú ·†*^ç¶m‚©«r#â!šq¿o¡GÌÞóÞèå¼#r¢c—[ß‘öTË«7êVÏÛGÜIØõ%á·LØâƒ‹‘eß‘ðqž}«môöé°g—)%VUpò) ò·çž§˜‹ºï¢À6ƒ=¥$CƒÆ[£=û}¦Õ²rî,áï;†¨Ø 7ðÛ ðQ7Ôv™þRJôhmÿæÖm9¤”RJ­Ê¯*UœŒ?ϳ+s-Ë"B&!¬ËET8´ìÃ5¢*R¬¨*˜HíÀyËhÏLJbæ\ÝÖG8Ð}:Èß8l×{¹ ºÂk3Nje7"¸Ç¬ˆ7:².ÞñÁ¶äÀTê¸cõN)©6|ÌûÞjBDdn× ­­a;¦ÇµÖ÷Ô¯ÊLÛÈÕf³çDô©Ò‡ÆÕ¿‚þ·ðÈØdzpçÙÔŽáßÇô! ýÐÑåuH6…íßÑê. ÜϽÀõÐnÌ>Ž;gfܯîáÕ¥n#ÝÛuî¾ß}®»cøHÚ?fè-b!ÂÀ Üò ˜ãáp<¹L˜]›Yó¨ÒÜy8:d!"âøÙgŸÍÓñÕ«7.š¡R‰­¦\‹ÇˆYªÖ"HÍåÙÙofZJe×îácma S .¢bâ.Ó”D$„ÙTÀ  ºf/1…È%›H­> ꃣªŠ‡S©âÍÒZ¤ä5vo&WöI¤Ž[ëÚˆX¤¶j©·Ú¿Ÿæãº."[cG€ª"C©• ±Ö*êÄœk‰1šÔ¶´}¸Ë›¹Ø¡Ë´"¢U%m›5% !Œ"úªÎC´ž}“«ëô-d4©¶)FyélgTLÄÌ)¥ÈÁw=÷ºӋ‹(ˆ ”œÉI¢ØRض\Q`¾\.àÝyÄ+âD»Œ]Íî+cükã,˜™‡Ð";¹# @Éåã?ZÎ'G眗e)RE5…è°=ªI©ïÞ½€²fcB&+*fS©)ƦƒíxSp. ¨ˆ¯K"Ü4ÑT™êËƲi aÓYôÎÖ ‘(^ŲýÙìÁk­{z·Üõ›eäsvÖ¦X‡3§4ÖdŒqŸËº:™Õ¡GèW5Z]#ì!yëØs£p¼ö‚MÄšu½¯ê‘nRsÄÖ^¨èxž{h<ÜÇöBXÌq‘ ú€j?IZm?¾wFnÛ_îþ8¾´ßk4´ÞwÅnŒØîo;.®Ñ¢.äÚRþ&ÝG.7`»7ò ŽìTk[lØ;ÙèônŒFh’êFÆØ›ì1ÆÚä=• fp:݈“þ)„C@#0Œ!"3 !QŠ‘C¨µ0‡\˲®išjÑ6lh`ªDÞyãRjJš¦Ll>îïïÌÐ?y"µœÏgB·Zeg7¿L1!ºX¼MÑ›"ÈL‰‰€Üs°dTd$¬ .äÍ!:9ÒÁ´ªuö!32CÂ’©%ápÆá &jõÑÍí<Í*"5+ •5c3"!5)¥4i86‘j 1DH!®Ë˜‰…Ä!©R@fõÁKÍR²›Õ›dÐJ h¢µ²;R±T5­.ÿh¢Øfµ­š;ïAdFçc8¸o^íµ¡¹yžEêét"ÀÃ| w$„lÚì ¬é6†¡GåÔGôò\Í\±+ ™(#1â–ôWDJ.¾®ýHÊ-DPµŠi?94v´’ -D&¦ªRU€\Ú°scÚˆ†í`ÌmKzôt8Â……™©V)¥Liòí’RR31½ÜßGŽhXE9¤Ó4MG±SÌÕUA «j–ʤ֘¦uYìÃgÏoæ£Y%»V3p+?üÂ& ¨ÆÌm‚דâÎV07ÔH,.~_„ŸSj5CðžMJi¤Z%ÆÔ\pzâhª”¢‹¤˜˜U!§z ùÜŸËð hE“Rò©:¡Ó±xawÌ æÄPÍüŽ™ïØ®€h4p2÷q <ž[uÕ'(›5Ã8´°3|áE$­ÂÁPæéP—ïì bñÆ~ öi‹}½f¤áÔ®Âú•òÃö#C·í*YÞò£<((öEÈîÝU·Âù*gÙeèû⮺ñ C"ÊìŠÔAL¢U[2k¥d"¬µôïÚáÈBJ‰™KqyqrsÛ”‡Ãa>Üóóž{:ÍÉßÀi6ìòÜ1F©ºæ\J‰)Eæe¹»¿{óøñ#ïA4•«)úëΗ˹ւ>«Ø{A¾ŸÁ|t¢·+]ŒLÍRšù“ï|§–c40â`è2+꪿ÄÙ‡ô•Ñç¡:‡„0ÄÐkinñ"µXÄÑb°»ô©™´ñœ…™çù˜ªëÉH€ã<—RœÅèlj¥4¥4¹vã¸ÿýi¢›¿övHË´© )ww´6Èí6 Ôî#¯ìI­µÔÒ8Ô<ñÜ#X¸…¦Hˆ¡çŽžóî×ý*õ¹ýê€6^ÙIUämæÈ³?Û]»xŽn×Þëu¿cSEG'b$äþCfn\óépÈ¥¬ëÊÌ1%U]×UDKÍÞ¹DhÑ`˜ÇS‘jU bJµV©µŽ×'p´nívëˆ3ÌìKÑ ˜6> áãû^cc§úÔ¡U"âºiCP¢Ó_8¡äÜ”ª'ˆ¾bÆ8ÙUÐh‘1–RJ)*šsV©jêé¨$<‚9ÝË38ƒ†á0²ÿ!„àÆ4M`$bó|^¯ƒve½PÛGÑqI5WŠ1pœǘb^W Ôª.§ê Mç¼Ò€1€l‹¯W‚ˆˆu‡ŠìƒiaX€ãnЮ¿Ü•Þ1P_¦ã-œïAœ‹»È»CB¯";xcj”»µo'>Âöv›÷ÕàŸÂºJQŒ †Ü~p-°èû1ÞF<ú> œ€» à²¬i"ÑÕÌÞ¾½ œÂ‘ïßÝ©ê4jQæH!„u-D'&¢>øÿð‡ß•œñý»»ÃñP<áRE0‘²^t…E¤gvÎ÷7­“Ç‘@!¦Ù/[¤ŠÃµ”h!ÄØî•¢)ˆ®"*µnªô cò¡„u½ô²É@]`jË7ÁÜ‹ÄÉHµ!™AÐ Œ—l¨•âa}sal ]­Ú‘2ó-ξ+ØP­ªŒQÒ}¾½*E³FˆÈØ5̃…WÇδÃàCo˜@?±º~lßßÇ6Â<.ëNÑÛ íŽê‚Ãñƒj)EADT7*è²´¶£Xì·Ûþé?Hb<Šù{Eb×WUŽÁS´qI޼»¿‹9EQ]òÚb‚Ô*д«¨ ¥@rçU3XÕÞÝß»½ë˜6r'h d`DôÖ: ê:ø©ÛÓ,E°[€íÙuŸ<ÝØ+|æEvž £ìÆX®Ö碰µú56·N¥”Tûë3‘!×Z ™ ©¶öL@"ÐÚX†ÌdȉAÇ^vûe÷I÷‘°Eã C^Ö|8Þ¨øZU«un_Ì*Æ=&"#…ýâ7k %Þ~žç}Î;At5Ï«/óú*ar¦¤>À÷þF“¡µ†¡3/õzqïÞüácÃËøcförý,W®$¦ËÕó  UÛ!NÓ”Ò„ˆì–êU¥+d¥?úh]sŠóº.1…óùž‰Üµ]ªŠhŒišf7Ã0kæoß¾-%˜J™¦”k>ŸÏ¹,ÌÄL¬ÖR«j{z»õ-¢ØEÏÛÜ8-C˜‰¸ˆq)eY3‹1V­è’Š)…œÜi`1²™8ˇµ}õ”R<;¬RÖ¼H)Ž>¦)`7ü%BàÎ$6 (°˜¨þ€´Jõ÷ÂÖv3BZóÃìB Ì89ÔAMÐ’#4}_BQ ×FeŠíÏû<ÌÌÔÕ3Œ™!0nq{Œ^z5ÆjFŸéÃØž]­âD²^–¹p5ó"²&+„µÖV:²ËöRäÄäc%äxå\cšÇÓ²d$G Ýafë8>Xµ[¸V…›G×µ˜ÙßüÍ¿ùê÷_•š=çë+ì,áü‹‘¨SE›NfZû–\"¡¸Q¡ùذ€5e4Ç× v!•ÆÄé5¼sMõÿ£cJÜÑÒ='úê<ÿ6áÜÇ;>8]ºå‡¼•Zʺ//Z‚†8ìôú+·Ì=¥DDj"¢ëºŠªÓ3ªhÎåtºùþ÷¿÷úõëõr1WnòÚ³V‰)˜šªÔê–7ÓŸüÉŸžN§¯¾ú:¯—ÃáPJÎ¥¸š:•Þ¯D:ïPvíóºÉy:ª9¶¦ù¼\B.)ìÍ"7ŠÚkuŵV•ʈηU·ƒ‰10k+fà“ýmÙ@ŸñFŠš…cL*¢ >L‹]݉¤…W«R§~H8´ $6ÀÀº,€õ‘:ã¶{[«ppWú@Ò•ò~c‹tò "‚m,û}Ò½á•Ý÷n[]fi/K®ÎˆbJˆ‘@ïO¤º^’íV P„g— ÅqàîAFå«qgŸv¥cÕ8H»O:\úZßÒú‰×PP Dñé°¦¯cô·œÒDÝ_)¥éæp4³ÂúK­b’ÇÜÄ)Á\³ êp–í,FAÓrö]ßí2XÚè"fÜÕGpGB×냎Y‰¨m—0»kã¸]í‚Nv|Ü·xbµÖ®e­¨êýx¥]£nP“D(¢@!FŽÌj-ÈÀ"B œ²Tè®PþVýÃm´Ú}#Ÿ#^sŽ1…nooß¼y™s7¡íŽ`­o¤C÷ÔŒ½S ×iï@nöËÈßLjSyã¦Xç{bß7[°þ#ÕG»1°É¯¿ŸøÁõ}ëaû#louu<4ƒž÷N "Šq¢ÆñHó|p ©ÖêV>®DBT€˜&oF{`›9¸/IJ\,¦hçó™™Ej)ë«×¯kÎk¾@LÜ)‘9Óùr6Sx¾¿¤iι¼½»_Öušæ“ª‰I!Å U #º^Ý|nÜR4†³|¦ ¡jmº¼jH4ϳCÞªà½eÏ©D¯ê’2.u[k•adêÜÓx¨ ‹do‡5zcg8ÁÙœófJ@€HØVe¥äS-Nlh ?{Ddš’ !ˆjãÍ6ùÜŽ4Ó E&hCgûC» w-™¢²žóuÁ^9htø7µ<­Cd€DÞMÓ±Îû‹]{op¢á¶ÏÚZÐÁ&»­á³´[ÛRЙÿHŒÑAö®‚"ÖRÅ4Ä(=ÓÇk©æ8ĉ©–Zs€)N€p¾\ü“®ëz¾Ü‹T'bh=¡NE „&€<²fìQ> ­Ú¨~í°4ï=Ćq€3bµ yrELˆc³Bl(`×$èJNÁÏè†ö À\ÍÇŽæ®[po%]Œ"6#3Þþ^')Ž Bˆ &m7E©ä qžªj.yž§*¹Á»@ýàzkÚÇ1"¦š‹³Ú¿üÝo Dœ¼Ëw{k7JÞ)_‡r to<ðÖ}ïžûˆù0.÷×l»¨µ Zã +!mÄćA}€ãVŽ¿|¬wBOW׳§F]:n媙Ú©@Îq;ŸÌŒcð‰ê.¢=6Rû\žÌzà&9¯ˆ@*u>Ì%ç”b ïÞ¾MS4ƒcJ±TqÁm •èžMªF„bSÂ6x9JB#Q«nÝà ³¸•ºš©6ÏO/; €1¶$Ôq“ÀÌÄA\Dƒ1—B„`F@LèM âк¶)%Uk¢gMã¡ýê7ºŠxñ«ªÆ ^,´[f½h·Š$ æ®6‚Ï?Óù[‰æ>¥ÐºoÖÍ= Agš;sÒÀÙÑj“=÷¬ÌC"b?n=Ðx”t~ˆi5ÐFúï˜í6£ÿ8\{ƒì‹?}œñÔG<¶*™ZgÙúq20(Ÿds"¦©Æ§”0çRJ^–¥ÖÚÐ0€ãé”R**~úš*RK¤VÝ7ÀZ”ò2‚üi<ÈÕFÊÅ>}¿ƒ¤˜Èãs;:Íg.RŒÉ£ƒ-~sZ„^åõöo;`º(wËãÉŸé°K‰Âáp !+bŒ­píèª"&®‹®jìúÑPJE‡Ý,ƈŒ€§(µôq¦Ñ­Gì”ÿqÏF,*9ƒégŸ~öêõ+U9NÓår'Rýó¸.zHSÜñ xÈïÑn¨Ç£î’îñ5ê__Êö^ǵç=³x ²;nåÆÅÞìwßC;áõ‡¯¿ûú–pßßàÁåGß Íè.çÒ»£¾;‚GïRêa>6ÎÍV‰=‡­5‹¨{aÕ:Mé{ßÿÞ¾ú2Ä—ó9…$"%¯ÏŸ?½¬‹_!Äe¹ÄènUªO§j€Ì/_¾ªUBLµÖÏ?ýÎÛ×oÞ½{´ÖêsFfÆ¿¯Wˆîu@Ä)ÎqžBHD¨ªµ–Rsˆͦ)…½è=Nhžjµê°ÍÀ×,âV¯žÓ—^ÀºAƒ§{œ…”’;§Y›G÷Ú¶NA$¢RJà€àý3戨ˆ01åž<~âoäv !x:_F·³H%LܲÓZ ™ù׊×6Æ‚]ޤÕàb[.<⚯ûž4®-é‘CxŒàÑÈo©-(„ÐVB›¼ï[ænvÕñµcœ¦I´JÓN3cŽÈAÕ®–ëàSK©Ø¥\úSk ÛƒÂÔWµ»zU qJ@¸äÕ;«ŽIˆ˜s!Ì!"sŒñp8„JÎReN³‘5UH‘R20q oß½óû椾*ZE8¤¦ÏÑMÖœWÚ¼Š'Ð-ʬqž­™-çZ¼Bó³ ›÷EbÎ¥ˆ)óÎ~szBê"Ìæ³åþ8@3ÜûöÁÝ ¯Ì±ŠåRz 6UŸÖ6"S$˜çY* 9]=¦èBÁ`nÈj¦ZçÃašRÎ+z‚à"ìN¸>¼GÜcS»?ßPx9ßû$º™¹ix[Ò@͹©gfÆ!úD☻ÃF"ëVÇû¼C7èƒ|=GðZžc â4uóYBt 4°MemWêîøjÖLôƽîéÙ˜o²¶,Ñ•½¬5]û÷9ŒÐ”\½ÕXÅ;‡Í"Z¹Ãd ªâ‘Ç›œ ×Z›"Cj.mhvw'R*˜J©L°\îˉÔ\J.¥NSrEIRµ¿úëµæŒ÷wwµ–§ŸÌsüá~ðåïþùíÛWEV$‹‰4/ 6bGû¸œbLËEJHI b˜J@P«Ê.øµÖb¨*k.!Æ@Á£ø|H¥”Rê£Û'%kA¥BÍÂè`z SLžõôZ™S2@U3%熆c )Æ¥.@ˆSšœ' Eňs­SšÖe™§ " -ë;˜XµªTÉë*V¦1€•j"€ÈL),„XÊê®K‡GJªR2"Dˆ­jDžc"fBô™¦…{3´J­ ˆØ=-DEUÔi€DcrÜ™Cª³:A\[Àý²Ç¬JtŠŽÞzÀ/¥¤0“ë¸0$S©Ãe~ 7}2·ùDôSÐ{<ƒ.¹PÏ©Uœï?¥TKés=Tk-¥PˆH ¤ÄXK½\.¥dIJ,0MS–RªªkÎÞðDŠÄ.öRÝ•¨‰€à™D½jÍ6l »Æ®ñ"O@«j5ö9U2pê ûœœÔJFΊU «ÆhD@h¦L˜šï Š‘ÐlÇ«ªûFølÁ*P«Dà–|fJhfÕ¬–Zý`S ¨€HA Ý*÷xsCT°R+1•ZÈA™´‚JÉ9`X–sv±?üè£ÞݽõáœÀ‰¨inxýäã]‚†ìþYÒ¨M­ÏÑæ±±Ip«’a@nÚKܱHÛ-³¶k€Û¹[·³Úçãˆ;‘»/õΖ'å£Í?`]2uµ”·F¾ÔÈ­ý÷Ôõc6ÀòÁñ;R§—êÿ0ò)¦Á†a±=:oÞy1õº/8SÛñ†)Íf jƒÞP‚ZŠ+LSB‚Ú3˜¶Í£“D²о~õú«?|E@ŒC¨yýͯÿùr·æÅ™î’‹H5õîYë<¶ 7³Z‹ˆVS Ì †TjÍ5{ÍÝA›9Äy:¤˜¤JŒˆ1&5ñ|-çŒè™ µÕã}glª0Øwt¡;DDâf2ênÑ êå€J3ðf1N).¥®y©ÃáZDL¥HJ±VŸ™UUç®Ä”\©›88RO¦iúø£O8bðæ÷a§UÔ¶‡ßÈ„Íiɽæ›ÖüìèÔ7ff$Õ‚Vã@Þ÷Ùèޝò@´Aä}ß¡]­Òkò˜¿~Œ‰J­j6ÏsŒqY–}i»m|êÂki-€Øåü„ "TõY3”aÏÒõÕ›¾`“v= >‘ìÊ\.iÝšgÅo[—Þu‰3óÆÄ¾Ðž‡išTµŠ8®gÚOÇ>ÝÓž’õžG›÷¡’Cky ¬+Âw«Ômø `.eÄîóç· ±q¥ô„Œ9¸¦ßÕŸ=Ua¦ÇGU½û6q¬µä|ùÉ_üžúêx˜ïÏK ±Ö¥–åbfëšE]»n0öæÏ¶$ú#¾ÊôÛÑî&<Æg¤àvÜ…ëAÞÙûZ#í7£ñžê jD@Ä.>jH@!E¿×¸»¸±Ä±ûÛLÖ²uÎ^„îÚ>ÖÊ8öaý½8ÞF]a´ùÛ[5ž²?¶QÚvyÎ…l!Þ ó¡ÃDDîç‹MÕ¹ Uçºj­M›©–œWCXò%¥èÂ'"Z«2>züøÝ›»ÇaŒAkYïïÞÅÀËzˆsЦZ]w›ˆ0ˆ¬"1„€y-OÑ\Ÿ90S)j­1¥5/UK)„C,%·?:: z¹\–åÜÈ#"¦ÕL|…8„ÁÄ)¢ÎëðL¹m4ÖLÔ[5bÒ;øÐaPorÚºfU‰)¢ÔêÆÍ‡›©4óEÄøñ£GÖ¢mˆÉõ|Š8¹Ì@Õ˜¹š\.gŸ kõ›ªäZ¼â³Nä ÌÄ¡i¬7ÕnWèqÁ=¸š ©Nóäaç]|ôþ‚ô¾Ñ©»A(´Æ]—Â-íahDoS¶n×`Ť”N§“DÙ%[W;k# Áþ5Å:yÑ4¤x<Þç9†»1 x3Óƒš‹b5,ÛoOAê6oÕèê>WÉ4nrOÓ¼:г±,Ì´GžZ«6—RÈÖZú=¸»,“|ˆˆú騛û.ŒšÆ¿Fÿãú15V·÷gcŠØ{lcf'P³c Ñ›ÀSœÞ½{k1Ä\Êù|~óæ•”B(ye0D»»{Gww÷Ì|<s¹„ÀÄ”›ìÒ0äÃþ¾¶å¡ãØÙ»w¡¾‰4ø«A ððäµeî» ùû©øß î<àZŸ³®?ÓN’gѧÝüqóàCr¤ÆÈÙn3íîùøˆ:²!óÿ¼v|È—×ìŸr|ÜÝç†6sŒ[?`xÔš "A³F‰çìNEˆ1ŠØ<bŠži1‰(L!"BΫc€ÈHŒ§ÀÄ!Šh)ÕådŸ?{FHµÖÓé(R¿úêÌý‹ýéÛwo}-š ‚Ř\Êü¦ÍEks§@až&4œGϪJ•LÌ¢âG–7õ§°šŽÇG½~ýÚLC fÎy1Pk“ºê(L˜ûT¼¯7êõ 3R¸"Œ‚V‡Pˆš {"Q3…iJ7·7˲¨ªnNÄ8:∢`6NÎKó@àÁBÄ0N““M,Å„À"še­R9¾\k-¹ô0ºMy¯I<™T…#vI[ž3º1¶*1•RFîé¡så@‡¾­dýjfj{VëÉÏ¢æi€RŠ_•Ë¿,ËB;zþ–î]¥wûkÇ‹‡&jÒ\/ã°Á¡XU¤Ôœ3p èº3‘ ¢:2ƒ–JõÔ°#Kí¶`Ë¢ ©ÇõvÍœ1UJÉ9ûiºÍ¡™:ùÄ·¯C7Häü`GPùi»lè™\Ýäm8Ô:¦à׀㡌ÈnfÞþí¹mÒx 7a‰hšRŒÑDײ”œçiòÇ-¹X-2MÉD—ua¢ÓÍͲ,€Ö}8pòƒ*¥ùŠN-Дóµ}äA[½Ãmµ01³Žƒ©·šãîíãõ×> ]…NçœãÂ5Й}_Kú÷^é œn§Þn 6]áM~úB÷˜šãRög|Ëw\]¹ÿFT©R†f {ÁáVýaØøÂ#ÁǰÄpÏŠ¡=ÒËM ‰"‡u]×e™ç¹Õ³cˆ›ràœ 3åœïïïjÍ÷÷ïÖu°ÛÛÛÿþ¿ÿ?üýßýݲžkÍ ]ÙÙ\€9NXÍ“èöùóZ YDÀ4×ÌÌVjeŽ)M̬Å,­À£¨ŠŠŠx¶´,ç)†nß`؉î{À^Þ…=goVàÑjÖ\[(՜ﵳ†VÑ”B)¥tB­´RŒS IÕjɦŠH®æ­¾ÛÕj­.:Ï1¢¨¥”À Æäon(ûk-µÖ)NiJ%¸¹}$ªþ¬Z“¦"«¶Ê~г”’‘¨–¢ 8 H©Â!0‘HâˆDH}ÈÅÑ¿6 é%ˆ¦4I¼jS™kgý·àÎmS€!!»®.öé*Dt"ì’k3qr*\áš}ƒh#cï“3‹}úÌ_Íæ!°ÿÎQCôÐfû±,Çš:ŠÞòu_èZ´Žƒ‰Ëuõæ–§|Þ†eæÏBÝÍÍúþn„z³­‘Jy$sûbÂqó†b«`·¢Õá©Ô錮5ïÁÝÀ>áA=¸[ÿ¼~7°OcŽÃÐh‡NP¶Phªœ8J±Ú´NÍ@r©*UÊápP«ž,;090š˜æRÊšó<ϹVUSR•išn5RÄž€0üÝ÷v“+À«€¹­ ÚÙävþ‹Ïƒ6Ì}|oÌw¦ý 5¸£!1@ˆ>“GÝjûfkUFòÁ £K¹Q8±SÌ®2}/+ºOßh¸ÃUdûq3é÷¢‡oïþBsáÎ"S†wwôëueûãÉ\*ï‘ÑÌ<ª*=çHU˜¦ùp84µÏˆ™Ìj-93S©ØÌm "Ôu]¦)ž†›†úU¢îëßl‹9ã÷m<ëG„)Ƙ׵ŠÔZÍÍæ±ûóÍét^–”Òt˜—eÁbJÍÌÈLÇò^˜¦æ˜ÔP£¶ºYÅ"7†ú¾VÛõ=ÉÑOþ½!¢ìÒí-so-ЫW÷[L> l»V»µ;­KJÐn¦ÎäÞ!G¸ëfo„ší#5v‰_}踴=Z§ñµ_ ´ÿJýÚ¼WÕ Å1¯lÚÈãþ¥ ãxˆÔ”bˆAU=³vÂÒáx’")N§ãÄ8Äœ ¶ÚH™©”ܽ&j­šRº¹9ÖZ;b@÷÷÷’óêG9“wq LTD Ä#RÕÃ<©UgF×R8¦\iÀrÎ¥äZKÎUít:•œUõõ«iŠÌžzSƒ28†B(’]©}6¤÷W]8“<×Ñž¬ÙàP8¦ì •ˆ©”œ]Ô¡äòòÅ‹·ïîr."uš&8ŸÏ¥$&nbå&!pJ‰‘á˜#Ç)& Ó”ž?^k)¥@)%2ö„7;š?0pŒÕ‰¥Ðsm$dæKn5™'imI©rŒÞcl UÐîž±9ÁÈ]º0(ü¹JP¶-@ýGì:j;C³JE£¨x6mÛ$ÚØ¿[íJcZUU³ÔÑâž§ùxa·§bí´&$²R‘Ta>„€J1@Q­MZϥќpÞ !¯–~€\¶xo¥×¨WÔŠ5ÿEd ` Ü«mwSk<}4ϳԂf.Ž„Hndj€F§˜æÃéxTÕ\–››C­k]rªEr3k¦tsóØ VB:5—òB|òô™ç‰k^E­Š‚¢ÝZõt<Þß¿MÓaž#ªV)¥¬¥¬‡iæÀ‚¹1^Íó<ŸN'?˜×u`U»»œ]3@ ArQb*RQDcйf@b4Ĝ᧣K)%¦ µ2hU0f2Sµj&µfb¼¹=¼yóÆÑX5¨½MC„Yõps“¦ƒTQ¹œ/(R €9Jk¹£JQ•fu ԫ¦$„äb¸~Ü©±W¨bɉÇÙU–DZÐçZ…X  ¨0aB§ŽÀ:@HÚMîÓíV¹öËöÖ=숕‚ • Ì0¦1ÑM‹}„'Äàƒ»HTJ%b2`âÀÁ­ìЍ"„§y 1\.CŽlD!%•êbsµ–ú.ªúöíÛêfäÙmB¸Ô‚o´FÁð”È™@¥šŠ›r ™RJ±Y‚´ú‰Ð L82Eëz­j0 ó1çŒÝÓ%²ŠBG« ¹óv`wpö¬ÜÍZ¡oGî½ÎŸ!†*•‡º'°)øX»™ ´+Cë¾î:0L0PTÈ+ăˆ¼rë0¾óH€º©y¯êG¥ví:B®ªqšK­!¦R*4±ž¾šÕQœbeúàÝý¤ìg0õ9§Q=ÙfÇÐpcõÖƒ&™öVO=öWqŒÏw`3iììŽ6à $pÁ÷*À±ŠxuÏÌ“7ÎÓt^.ÌlUiÍK)åíÛ·ˆmhП”Rí¶Ú¹TB×eÍ9›¾\.òÆ<‹a°µä?ù8çår¹73ix.Æ—Õg4nàŠfm´élOË;cŒˆ™Bš&¯.œ~çú~üè?üá×_ãËõ|ww8RJZëà’ M·Ž°Yï8l#6!ÎÚÜÙT½îqc¹ÐÖ*܃0ûÕ¶ÿ}g»lßC}Œ¸Sü£¨Í‡c)Â!rS`p8«+ÊSkdîºí}Æ-CO°ß¿˜ñ§öâ=¸»à\óÀ¼æÙ}F‚¾v«ªM²¨83$øÔFÎ9ç|¹œÝšƒ™"Ç*’Bòé:Us~È”f‡ÿTÝÞ:¯ëc©^Ûº.£šyj†@Ý€Hשä2M‰)"‡˜ Á_ʬºƒ3ö¸¯j¥”5/CõE¤bŸf5¯a]¢úD霦*u]—¼.8Å Z«ˆŠ‰W…ØŽ·À1ÆhÄ~S™ØLE•‘Xч9M"M(•¤öÃ5›h¡—\ < !ø½UgË{C¯ a[iÈnÁ@)öKD`*š;§Ûqò^æacŒŠ\~’3OiòúÓû…`JD!&_Ž$¶øÔ–SÓGrSÒVͺ7‰z‡©ñ¸ökmoEz‰ÃÌcôôAq½§Ìã{_"9 Ð9tÇ5uQ3ó €ö1iO'ï»ZÛ»» ÝÜܤ)ºVŒ¨ø•‘÷0[L¯MJï·ØÖ Þí½N׸Šùx­_6üú?Ñx” õjÃ[ÖO€ªšs>ŸÏîdÝÆêAÁ@¬š‰uF€vý–+îWWµ”íFi«B|(Á³´ºfU )æuíX–QÕúâÅ fÑZëÓ§O/ç3˜q›”§Ñj$¢ÄšÒ™ôauðÃÐw”ô ú<ð~ aÒ˜5~ "2nc»Óʇøw¶/þŸŠÂ(¹üÙ¼¤ÇÆ`ˆHˆ™c˜Æ- —i\Ù!î˜Ý_©;RîIeæîf t£“õxÇÃqR—v¶Ã¨Àö›Ê¥Äü öPë÷ ”¬ªµVD#”"™Bš¦@!Ĩ¥ºWªÕ*!°ªæãPà©Í}ÆeáJ©16´ÓçÈ \ÓÜ%2\Ñ¥^1—@´”e¹¸Â{)ÕG7[ËØåzQo€)%v?Z+r0ƒZZÓOU}Ö‹™noo»è›õ#Ó @JžIuÚ¼E8L‡£VAbd",Ö–˜÷àÝ>˜802§4µ¹’¤à裼þFLdHýŒaŽHìÆÌ‘»N¬ÔÀ\ó§5É ÌåÈÇ*¹ÒzÃ¥u¢‘¼튂Ái½„DÔeåAÁG‚å:ãÓ5“½fõ;ÙgŽÌçn´ñGƒGéþËÒTá:=§Rã.‹FRQS‹Ñ©¨fªL$UEÕA Ó7€óßwfôý€¼bI ¹á–Nª¦”nO7¹¬f¶®+0;Ë· dÇhª.Ü‚3߯Ãb'JlI%îyý#æÖX ãÚb˜ ´‹ ùAÙôû¬¥¯j‡àÝáÏ@[’ ­99ŽéˆtñöçÓ>}lQKMSŠ!²§CWÀˆðtsr=ï…ÎóîžàÓ‹Ó4ÅK)ëùÎT܃càyJó<•ºÍ:Œ ܸ%ïHÛ=¼ÊJ @ °Gd ¾íëŠøÝŸŠ™í(4†»"ËL™‚ÓëCˆµÊÍ£Gª µX•Zki£"-ìn#Ú#¥Úƒì.Ý™õúðÛw†ÝÂAtñÃcßnJ#‘tDgœ:ΑmïÛóié°†ˆñ€ˆ¤‚ˆ„Ì,†¤*h8ÌÓÄD!F‘ÊÌ€.3d‡yò/DŒ1?EÖu‹IÛ¼¾„T[²i½Ò÷â†Ñj)>›w<½mr{s3Š’Ðu_}«§–e‘ZJ^!¥éx:U5P7Ì>Ûç.$q>„LÝÔ[Ç'—SNse¥'©Ù yÍ%PdêmçÖ«ìäkht5üýyc€F#&“?wB¦À>ÛDÍ_ÅËWU«¥6}ëÁkرZuب5;y¢æ¼[¥Q½kÊD¤ÒÀ>Uu¥3‡ƒL{ìÆ!$€Úƒ»¯Ik‰ˆC¥ ôÙ è³HJŽ^Y!4Ï)9ö£‚]Ôˆ™™ÓÁ¶Dt8ۤȘ¯1ØÓ~P³ß”† µO ]ÓÉÜ ÎæyÄW¯^"bƒtä‡Ù‡BÛaÓÇJ­µóÜ{Êy8Z~x¥R5|§Â¡¡odÓ4{Œ“~î@£©´Ôs| ¿04sË‘æ{·) tvŸŸ*†¦Ý{vwI×Ño_Ü´³¶Ý¨¦üÝÅl]W"ò¤ÍKÏ⺮§Óér>«¨žïή¥xë×Zsÿ‚Öì”>£ÔÎ<ÄqöÃyrÁíú;† ×-œA¸‚ù@:nÖæ zò5Žhô~=vš- ´*¦5ƈŠnnΫՆ›Ò΄¶ñ3ßáãü—1Nr·>æ×9®V»íƒÙØÌè˜ûxxDÍ®w¿aÌy\Ìw®3‹A3èãÖîíPw ºœsSZ¿šÔL®ì…ÈE´Ôµæ…åê#×}iì¸B“QôãÕ­¸ëû`è«°” Ó4QÎ9¥ôôéÓw÷÷µV)%…‚6ï'zûöíñt’R íx<Þß_B5gÜ ŸhKE¹”²ó/Ù@ d6ü>äe½0F2XUÀ±_öÜóýSk¨<ë¸ÐzËLÞ´uù'˜çc^²±«\@ }à‚öBÃ;«£ý¢³ÿðDÝÒõ¤úxzGê¯!<ÿ&EØs¦ vƒKm$•û÷·OMìqmš€9ñ<ÏÇãišçs`¤Ä§KÉçË¥Ö8z¥|ÉK)lžcħGø¬)0Ñát˜"Öu©¥ô®•€ ‡t8cLïÞÝÝ¿»_ו¨ q`{ì¾µÈ06MSd7µÅ\J®’Ò0pˆ§ÓÉåZž>ûàÑÓB:”匎;¨(©a ‚¼.µ¬µ”À4O³˜ PHÓ<Ÿ¦iŠÓìBV‰˜bä@±u‘½dñ6æé)ËïÏR…¢—ç²{”غ…DØÏOm˜¨A ÐÆS|ɽÑ€Í —¬Ùaˆè)b !MIDF¸ !ÔRœ)Ip[3D€`‚~¡^ý9sQUk….È^JñáG5bó6Þ¬ª ׿†§›”Y»oRŠŠÒù²ÔZ=Í"nɯ™ùiätÏsßÔ±)Z”5· ¯*HXJ©*88Ôæ…Kcc ‰ÚþYv!·<«Ý<ÏI7=¯ñw"6Ú‰Ôöjˆ-Ó÷™Y÷hŠƒï}«ÞðÁ÷sÊuF˜ ¼€ð*âõù.²¹ÿ ÀqžUJéöövYWu¿¢RJq†Â4¥²,ŽîKcOP)yž¦Npre*mG²!€¢Ã5~Ë8Ääp?uƇËÓƒþ'ìý€iš,³Gåüã¥ÃÜè†LŽâ1; ®‡NÑ@Ñ!™˜JÎD¡ŠœÏ÷ÈXÊjeÄ0³VkÍÒ½æNóÌ/Ü×5 !†Õaûo×Ônýÿ9­Ã†ÊKšN²Ù÷ÖP+uKÁÐÉ\²Gä µÉ±‹•âLiþè“Öe)µ–R¦y23 òqž¹#"‡ÔÄÅJî3J”s³Ztš¦8¯k)™Ì´¬QonnÔ :q]ýd›çCJÉeìÌŒ9¤8OÓÃäŠ777*%çÜ4Ÿ>{>ŽHÈÌàtsûù÷ÿäé³kµW/¿’*ŠÃˆâ4rYL„EŠ™"Q©€k^T˜77!&´®‹Û9f—БR×’U*˜MóLÌ>ß!¦K^]2ˆOÓ!ÄHÌ!F5,U)Œ†ÿNœòŠl}T‡ph´²šª@Ÿ‹ör¼·`>€ c[ƒnèu â“Ç›F˜'¶€)%Sí‚,-9ñ9>0 Ppz? “äZ‡!\5¼#l#Ï´,‡{¶ÓØìA& €¥”¤¯–˜ ƒÛ'u@j­ž8;jáâõÃÜ wÍÖP5Ä)%©RJI):ï+Åä’þÊn¡ìÕÐmcË\edCóÊ7Áƒ3òSÚá¥.’cT™ €(4Öž‚ʦ»`fæJó"zfÛ‡xÜ!Øzÿ†|¼NÚ ToÆl™ë>g·­Å=p­6æE†kRÞßßçRüg¼ÎĘbárwG1±Tiœ9_ U·§¬>Ü Ô« Ê CœÌÀÒFXß´¡¢ž x2Ó¦—‡‡*À¶yˆ¨ÔúíÕ8–Šƒmª MʪWÊ.ØZÀ¤8ÏÜ÷À¸m‚>)·oø—ÅqÓÿ=¸Ûò`±€ Š”s0ÙG•µûx¶'æ3¨Ø51_fÜNGG“mÞä`¢•™B 3e #‚" $—K- ’^Î÷!ñ'Ÿ~üã¿øóßüæŸóz9Þj-oïÞz“‰LD<#6âM4„c039Ìɬªä\ëšWbŒ=¡#Â*RŠQ\J 1žnN%ç”R5¢€5%&$3&%UÃZ 2¨H5€y>Ni>nŸø!¥éÃO¿÷ìÃÏÖl?þæë/u½»¿ ª¥TQS¤0Ç¢"eÉu³u]§iò±•ÜHA$“˜‚‘˜Š©ˆAàjŠLKYÔ´Ô Jˆ%çZ !yŸ‰Ö’Ç“æ,!¤€1sSÂAUq­YUcNÄ T­Ô‰Ñ7¶)ú½rðÊ M(˜¢ˆ2×ïâÎ,9¯ëê–O›©nš!D¬ JLÕÀ€ Ú¸¾š˜‚£8f*Ým¸E ¡žˆÐ<´Éƒì³DŒR«7¥)T$TÒªÕ;C!sðq|FjÊ!r)UÙ RšnoÓÒä Á_EÁ§0‡IA]Õ«â.ïrº¹ño!×Ú“ÌŒ»Î0¶LôŠãçµ5XFb5pÅas¥äm‹n1¯ÄÉ&ÄŒT«pŒÄ,"777··7¥f04#0Ä® In›΋$pº>ˆc3z%S¶Ù=°–”˜*fï= f©BÍñX]à‘<µ –Fð5‘ ÄDÈÕÔþU‰Ä$)­xÓ-«)B䀈UÄb‚Óy±ÙÛÛ°-»†D…¸kñw&QË“Úmgè¶Ìvܯ°Ëƒ·BÜ_€Ý=ÛtbëŽ=Èña@]¤».DCưË TË¿cÓiÙµõˆ(ÆÄ]1¼&¶1Y2³eYÖe­µæ’óº,ËåW¿úÕÛ·ocŒËºæZ¼nU$T×D$âV60Kõ™=5"œ¦¹åVœRŠªæÒ ˆ(M²Š¸_×Õùõ¢êä&W œ«óm^½~•×%D–ꎀÈîîϧ›[â@¥”R^³‰Èo÷Ïõ| î¬–R:Ìó<Ï`RD”#§׵̇C­²®9ÅS˜G¢  hXk©¥N1&÷Çð¹vpY>$Ä¿ V"™2MÓì+¸¡ºÌF§Ü*“}à¶Tq®³JU•&BBCp;\¬‘Ù MaW' Ï­öÿùt[¯—uඈh†ªZÊz8›eòÍÍÍÓ'O^¿yÛ` •&yÓHÞ!ûšß ˆã5¶Þ·áS "·âsJ±·1­‰Nï'¤`p”]Ñn_d˜©C‚óeU%—µ–ŒŒÌ¤êæ‚6Oéx¸Û.ì?øûÛßsí¾m¤ØÖ5¬ÀŒ(8"Ó>&9‰¬+uw&F UŸ;ÚÆqsnôú]Xh¹%bs4SxÖ`±+LÌßd·bͱ ÿu³ÿˆ>ÅâëŠú5ãŽ•×ºØØf&DÄÔ!×\¥€Kw0—R¦iB¦ £ '73Þ!ŠDÄÁí]Â1ô¥ »—hjpûÅ7þ¸ƒcvÁ½¯®W‰½‹b›èxhúgÛíÛ=o£Æi0÷áDb_¿à¬ákà½o‰Ýl<ˆþ}]¸±ƒwûIñÁaØ‚û–zôÁ0_|:ìu VuhXÍÀ”™90€½~󚙀)çÕïuéì7WÝ Ì!t} ¢)M1§xvS²2…Ò¤*ZÕG7KÉ€:¥Ã<'O$77·sH“©iÉk^ÍlžÇãít˜‰QªØº,Çã)K͹œnoK®Ó4ßßÝ© ˆ¥)}øá³W/ÿóùåW¿GÄõr ̃¨ÔRÏç3-ëjb§ÓMAäép¬"¥d„ât:žˆX¤Çy>Ä8q D ¡%0°È…Nœië1ÞñA îò™ý–»ü»†{³„@ÄêÁ{gEâ;¹Š`ï o›'Ü÷«»Ç–+°ÀBÞÖ‚öû&Ûjh}zkZPÏíVÝJ–îq…Ãö¶oçM*òjž±=®%×éÁaø¡·+¿ÖB€6Iá‰33{Gû€•cc|ÁµØüÐÇÑ%Þ¹S‡ÎÔ,¥¹ªÎNšóÁi&b¢R+¤ý£Á®yÕ²–*äq´¾õì‰z?KUv¶ç½Øƒ·´ë›»½ZûqÚ–{/0IE7'm_IMWÌD÷ î>Mzæ‹olêçPÿ8}ÏØ~DÂKfFq‡>Ÿ?v™¨!†b ˆE‡ˆ¹”cõî§Hš&_>1Fâ%@HÄ~ïA¥q½Ýª‘B777k)І?ˆh¢ÕëºzJ²V‰1"ÇeÉ9×ãñp˜S­¢‡ÃÍ%gxþÁ30yùòå|8â|¼yòäùÓ§„”òeý_ÿûssü⋟ßßÝ¿~õòÍë—`µ®+µÑ4­µº'½,ËùööËš(Nó§Ÿ~þîÝ]ˆÑ™ÈfÆ”‡ZJ^n6P¥ŠˆüšTT•]#ËgsÀ÷&‚»n¢ªj“÷ ©÷”¼ÑÝHt]ð¨é3W¹ ‡8¶üpÎòG&âܾ«lÃ̘›çTëW™µ‰4æ("1&"6Ñ×oßüüç?S‘0È.¼ïr#ÿM³ý#ûkÄâq£ÚØeÍ9„Rlˆö|>¤&SOÌÞ"³« R!·ìkû±Þ kdüº})qKG×Ô'n`·mæ:î’¶½Qíµim9ãÕØzÃ{œòAÞÝëZfÕí¹êõ`; i 6kôÌí÷ël./0tû í×­]‚H6”`KûÇéñjcûõyƒ>dÔzÏìîq°í)x˽f P×e”G¶SxÄ^åìšÔ88ÓWE9Æi<•­Õî$åÝúÛGÃë碹8.z#-/CÜU½.¿×h§ƒÝs6À&Ÿo[Gþª>èoÝÅ#71Lì6¸ûÒXS»F5Ú+_Vj6!愇u@à㘘"f¢^Æ–Ü¥€DD®3á;ÛO)ؤ̻üˆG 5Ss¶¬'ëÐDõ|™MìÚˆòã^l®œ#âÚO«WdÌÒïì±1CZÂ'{ݲ:F_kV_ï¸„× [PR£èèscR¨»¼îø‘žæ÷™¦Qñؘ‡¸:±¨…—G£xÄð‡§E«ûTÕÌë>P£öüZt bëó†ÐǼÁ›«NÓÁÚ €äÕzÏy«“6È•õ´¹íâáx|üä ÇtØNýn6nÇûñýAp·m¦„ÔÐQó4y|ï~•ïúEMQuŸèø¿Šˆöæ¾]ñsÀP mØ "Ù^F§«êìGòÌ|rþ xT›¸Ã¦ŽkÚZùs{Ð'¦@è³ø>@ÑLV‘Ü3šÍ,¤èóÐ!°–‚†!rpö†øªæ’×¼”RSJD”RòA'5­UÑTõt:Íó´,g—R9M³Çƒy>¬—å|¾«RÅ9ªá4¥ûóÝS)òäÉó?ùìpóä‡òg€|óèñÓÇô/~ô‹_~ñöí»ËåÂ!¨¢ÐFZ<¶·qâ«Ü°m;·Áh-"3_½zu:Ý~òO^¿zussóãÿär9¯Ëy¿I|1ÔZ¯³ç–‘9s›}lèÛ*éóZ\þéþþÎÏÚ»»wLm€Èœç«¥qß·}„sçëäw¿Dûvãň¨ŠP` ÁªŠˆ;†sì ¹IG¥Úkêî7Q~lÌцDù jCD[¶´ýÀ{1-ßM‡ôllKÒ½ƒ2âÛ.Á…á&æ´qz)lŽB]°ÓeÝÆ¼Õ𦦆ÈíÊÇõ©ª?|O¹-!0¯Éœwçb—åoñFÌÙåþ/È“Gƒ4œÊrÅ·G¬:Kx»Ü&.榊‡ù¤1&Uúxp}ì¦A@~“™OišçùñãÇÏž=ã§]˜ÛühŒü\ÅGÛæƒ€Ó¥h {?²_5¾¹¿]J“—“ÔÉ‹ž8µmgèóìcÄNûš¦÷¡¤ñÎã^ï»c¿¹HsÂm­0oM`Uí 9„˜aèV+¥®ëâ‰6 ,ëê¥màä«(r‚æ4‰#÷ô©—åÀ‡ÃчÜ8`Î+ ™é4ÍÇùØ4{»„%"‰hŒñx8Päxœ‡iÄiŽÇÓÍÓgÎó|ûø6Fª¹à||ôÑw>GˆÏž} Ë%ùå杖ï}ÿû_üâ ¬?þÉO¾÷ýï]Îç_üê—*0Mó|8¾y÷n­ÙOÇC.¦ép8çé„>xþá²^îïÞæu§šɪ…ªT3u¯!"ÈC(Ñ»|#|t\ÑMM=êIƒÎÔ¬JV“¾ {2îË.ofÇãQDsÎ`°®ËÝÝݲ¬Õßšy›‚uîØ6£¡}¦›f“€TµRDU…ÉòIµJ-ئóÄUÍ}™Q#…ÛûëqŸ¦ìâÛžîf}—ð íªj• W mUS*TGœ°»óø†ò"•Ü)³[3¢!Ä¡[ñ¹mKïÄöØÞuÞñ½Öô~°¶m·‡£æƒtד?ññ.ÐlÿBKìTœ?¦&ÀÝšÕiìdàs–0Œôü:;ÿ’ú!M@›‰ÿ›¡ê@€ ¼N2ÿqk<ˆ!#…ÝÀEŒ}Ž2t¤Öºèro;‹T{ µÒ!‹1‰ˆyÿ©dµ–Wbº3ýöó`í)“³Hç*z¾,¯^¿ #êùÀVF]ç¶ûCï¶¶½ú{ØL|Û×n$lƒMñx¼y÷îMÎÙÑg'×ZÝ¥a?mUµÙ6uK·ž`l߉0Ì_Ì,İ'ÆôàÎÖ3žæmš L™ÉM*rΦFLÑXUW îVˈäJ¹Ë%;÷Nbd¯51 ÂÚ-ÍT+QpÁ?B˜Íì²®Dáp8<{ü¬”òòå7µæãñôæÍ›qÄ1GÓŒ—ûû 1#À²,~øáÏÿág€q®õÕË7OŸ}˜¦ù|Yh)ùî²|þùçÿ»ÿíÿ~Yò›»w‡Óü?ûù?~ñ³ûËzœŽwç …˜Çéæxw÷ÖGòÖe¹_îÇÓË£'O_¼xQj1"5‘b††JĹœÍŒC"S†PÌLԠͲ{YÖ›–f…W­"`äè ƒ„>­*ýHèÍû­e…àdDv| ÍïÍþF¤]^ÇGKQj®DJMxËÐÑñpœK‘5_˜b ÁT4Æs¸¢ˆô úáÚÿ;ô<æïaÇX맪jš’÷?;@¡+¨ì“ìSò®îíØ³Lä§‚SãUÅ7"”¼®9OÓD„1fRÕ”¦æë6C!ú vKeî÷­Ç6¦Ùû‡Àöñýo˜Ù DÄ@ÜÒYħ‡LE#ùšˆ¸ùš¨4Wqµ¦8ETkE çbµŠßšÕŸö¢m¼;mÙ÷€|»¿d¦od‡‹û`ÿÈÔŸ–¤»]Ú8ª÷Éqœ%š/P“ÂC ¡5ÞT•ÈûÜã’j×#‘`mv§QKÁv÷LD9ÆyŸó´¥éïC—#kŸ¸;M»·ª“nZçÔá­LÙˆ‘íäìègþbŒ 11)EÀÀ9-ªbj}2­#B~ã†O ’«A¹[Ðx$L„†.]=D6˜#R@bFÆæD ‚Kñ;M1;„P­”r:žÜÙGª0SnîÞÝßß_òòF¥þËÿæ_~ðüùÛ·oþ¯ÿçÿ“UùÍ?þÓ‹/“B óa¾yüü“OæÃé{Ÿ7ÆYK)ËZr™O1Âûû·÷woóùH&€Z ‚FPÕÚ„ÍÔÅ2C`$@¦PJ¹¹¹ñ¶¾W!0]æ(º›UжüÔÌ$—,RÕÉ1¦DRrFâ ª!¤æ«É©dW-0)p *ŵt¢÷ýÓÂ+ßiZT#‡iâY‹zËÖ ŠdLà–ET)Ps¤Q«Ui-ÔUÕ1¦@y-1˜!‹Ÿ‘)¶4bÇ›@ä“'|"¾ÙgÜvM„ ¹dåÖrwåe"BPõv‚íÈsÐxä ôn“óp½ kÖ%Kcœ}}ñ<‡# ­¹”*€ÖŒá˜¡ÑÝÝʼnI¯G“Ì ÐÜDËŠýa U¥J Óéxœçƒ®¥°«ž_uý3#¦æaêmÆÃÍtJÑG B`i†&J]Ê‚ˆÀ@DÝA‘ͽ¼8 BCä»sOòÆ„j»ûÌ µpmñ‘º ÐÈúÛglç7 …¦ 9„É‹2UM’dˆ"1õò qì´p02"2T­`&ÚØ2ïçÝûcÇZ¯ùúÛFÚÛ ÷&„¢wÂïÕ×ì3lñԠ΋¢¸é¹·znHy:68šÚý.¹Ä î. ú‰ìßæ‹•ˆQmOõAj«3„è~rþ´†J(²‹ùé¾FFD1÷–©>,*âÂ21òèñ¹Jâ”Òº\ˆ¨”ì\„öó|¨µ"ÀÓ4MHã”s)„˜jÉÎ ZóBDb1¸j.Qð•5Ïqú³?ûó?|õBD‡ã²žÏww)¦?ÿóÿþú«oÞÏ˺¼xñêÑãG|ô,¯ùoþæ¯×eùŸþÇÿñ믾úæÅWçó=‚‡µ ‡tûèÉ«—¯–ËåõË—Vs­Å¤õ±EDj©ZMÊØ®#‹ÁΰîyèÆÙ’*!ðñx¨µ bŒ¡aT½ds ­sˆÂ0_Å›;„]Ý¥ÕÙäaÅ%– Á]D$bw ¹ä¾Xy°G6Ä}BöP ¨šje¦iJžÓä¼ve齪O³î^Õ¸ßñè©û%7o53»Ž)ŠTQwïÚ ÿ ðvüÍžõ„ÚÄÐfõì.áW¿#ÝVÓñŽ}¦I1?•ÇÃðÒ›ª»»§½¶Y÷> eàS¬UºÂ–õØÕeèÕ°Uän]ÕŸ‹bÇ´úd~ëÊŠJ¿G ïeZ؃}ãyØ·4Ä÷ub›¶h›¹h[ïe,&i ÂVž˜u™ëóf;höb>=U÷çÁffÍ8ÞÒâEÄhSì·î¦OÔg¯MKÝ?žQ‰Ç\»µüdf1'´àÎRr¬òÎŽgÂ} `| ""ä¹MIΙ9ƽõæ•&3‡—e©UÍÞÖ.HÒ°û†àÜc­¾ÿYbH¶®€>ýô³ßÿþ«žp¼}´,çÃqºûîÕ«/^¾‰ót^ó¿ÿ÷ÿþãO>ýû¿ÿé<Ïögòêå7"òÍ7_ÿú7ÿ¤–­šjœŽ7î–ãôáóøþí›Ëe –¡Ík-«™¨‚š“úëÄ^ßäµV¿W£yÈlEªXë/¹öigguÙÁM¤€…œ]Œ]Ç®\ŠTÕ§áÉ,út>€7¥MD€ql{‡n@ª1³mˆ15Ĩ-ò– 5bÒŽF½‡V@º*$"«TÓ9à Œfc¬¦¨h}?v)\ ˆŒÀM&Û°÷¶l+l`  8tÙix­ì–ã±5ty¬ÍÎà&/`¦ntÛèX] ¬™˜ˆON§7oÞˆX“m1l†GD0M®=M>WfM̳¤4Ǩ”¸é†¦iBàZk5ÍËo¿<ý)%‘¢ªUЉ8ÒìÿDj=תÓÄ)¦'Ož(Ò«W¯ÞÝ¿ýío¾$ Ÿ~çsûøóïß/÷?}ñÓGOŸ]r)òéó>úè£Dʺš"½~óîÿòûŸ~ÿ›^×UÊÊÌhŠ!§0?º}òÁ“ÇÏTj!S­YUUÔêȃEèbåc!!²j ¾]N±”r^#4Àµ3›ãÌÎgƒ®Ñ¿ü`SèR—nIîn*ƒÛ7ÊD¨5«ÖZ³£Ã"b&E™@Ì‘)NÂÆÌ¥æ2ÌÀ…÷IËv¹Át¼O‡U<uÐÓ#Óœ/Ó4¥4ŸÏg©¾`(çµeåàÞ³ÈØz8áL©fuÍ#LˆÔª®Bœ¥mf†lH`ä;h OøëpXfÚnbÃ-[è÷`çéˆjõu¢÷Ž}¤ólzÌ1Œ]ï:…DT+!–¡ì+§WZEA ÉDš<àxeH°‘5 ¶ÃÏ“|¿0fL¡ý<'s˜¦fŸâ1–ˆTëˆfÜ]4‘»ƒáUpê ЈIWS>Ðæ';ÒÿŠ&"‘€(Š1xÊb&†=ÓÇÖ³)Öøù/h¢,ýÃ2ó·è¹ï÷~e£ü¸UíGpËð Ñóbj‚‘ÙÐô}:±·½\ŸÑ„ΗO¶üî2¢n}ïÆP'ÔÁ¯'>º¦Š9X•^[ÁîF{îä£P Zµš¹#MõÂVjõµc\–` (¥®Ž¼Qî#ˆ3ÕZs®D4MsŒÀ˽vlÅRJ9—ZUUcj„æÝ8Í_3çÕ{ñµVôâCUQæt<˜x:žqÍùææt9/Ó”.糈œNÇG7·iž–œ§ùðÝï~ïóÏ¿K„_|ñE)å£?øË¿üWðìéãøÿüTêz<Ì9g"š¦›4Ï7Ÿ=yúÜ þðåïÞ¼~ñöÍ+Ôªª¦Ò–¦¶Y;D§¼¢¨Ñ4IT‡™cÛV§¦Ð¥ÑKÓjŠàÔÚÐù¦TÞfJÁj­ŽÝ´ó£Ù *#¡* 1SWkra/1;Îf^Ê¥á*vf hÜ&=û§à€Ü†bƎ݆Œ(:S…cã{¤”10?~üäÉ“'Öd·mšRŒÉQ©±˜]O‘\Sa|´-š¨ öA]k.sh¶¿ {6S5‹}Ne¿‹Gp5Ö–6wö‘†û$”µV§rWkþì{p©‡…‘¨Ž à „qþw?;Û뀺(÷)R1€IDAT¦$Ó0hèNyDHaŠ3c¯¬Ç̺Zc—ú™·+\öî}¡ÁâÌ1FUp£›bÜò¹îýÙ“Òö[»ÎQDËoïqŒ õZ\–h—ííƒusÞ3÷´ÖÒ/ª•˜N«wÞs×oW…¤iÆî Úʱq&оí'4¯Ýù€GÚx!ô¦ìVYøÞ¯F¼Z2Æ÷>a´ÿ#É–Þh<å.*Bô6ºb«º˜ƒ[ü‚ù(¶gî½2£ŽXç¼×ê <÷…ñ{ „䯡Ò<ó|ªDt:ªJ•Jˆ!0,ËÅ/2D¯„C0Y×õp8N¥÷±Uææ#R(Eóñt:ÍÓ”s¹,—»»w¹æËåòÉ'¿~ýêÍë7µæ¯¿ù:ç²–|·\ž?{öï|ö“Ÿüø|¾üàûß›Rúóñ£ó¥¼øæÅ<Ç_ýâ‹ß|Å膧ÇÓtzüô9ßÝݽyýâry{¾{M ªÕ´H#ÂvÖ¯‚¡!Ìó|8Õ,缟 ñ¡y¥Ê(þöÌï¹Yh¿nàSòi¤ÃÍKoX(Jõr SLfº,«™ÕRÓ”D•‰TÅÀT´H‹v¿æ92c®Ì¡5mïº}ňHLGmÇÌRªªÔZ×\K©ªV¥šº9WOPšE7sH)©sð]=P$t ,Æ] m“tm¯µ’÷jsíØŸ>>ÝÂ+`§‘l<—_€Rj͹Ah¢níp×+”¶à½b³®/oòÞ£:í¨`êSø=ÏÓvÖ8§›Z fN`<ôö ``1¦Ñ è%{½Žlí®„©ÔZŠ1)h©µJ Ä»§Š[øG‚û>F UCèTôqB{^ï…È^‘ËkóSuÆ™ªŠUM! hk@¨V‘Zkñs²‰rli2öBp× Ø_ô¨/Æ¡´OX¾åCªt+“njê©63‘7åŠõ` òÕL“·›¿@Üo3ìBbmJF7vÐxqw–1—¨2a>×j®Ü퇤Ef"ÏÛðí-o¨UÌ2HT}݈4'f!9Kx\¡+ÄÚü¸‡©”R×¢HnD™RªDˆøøæöþR¦t¸¬†VCˆ†l†Lññã›Ã4ûv2‚u]J)Óaþä“?ÿü³gOžüüç?óöåw?ÿÁá8}ýòEÎ9„ðÉ'ŸÜÜ<ú—õ¯R /¾úúå×ß„éÉ/~þEYï‰øtº]òr8JfŠ)Nç5ŸÏ÷!R@ˆ‰´ ú ¶·;ÔõŽ›Üô²vpfÈ϶­>¢¡(×*Šªª‘˜Ú©¿UTÚë+DäÔ­ú—·js^:JÐ:«L^ô ˆ€ÑÍÍ£u]HBÓa^–sJipø–eQU—¾ñx× Ÿå j cD‡év[`¿ TÕ‡h¼ E…´fŠ¡dYÖw.÷6M“Ôª*ÌnFª­º50B`¼½½ÅÎDÄ”šbh1ÛÏcãu·l‰* ¥‡ûqÀžßòö¡À!ãR Ú6/;>~í iûW¼J÷ÝKÿbŠhÖÐ$ÇgüÄvÓTUÝèM"è}E#S…½Þ¦†HxBD)ù…ZµÖº7뀆®À¸WÎE‰Ýa-ç¼oŒ0ó–~¦ÞG­AÌÿµw}[( ¸3•kTK`k@–˜™×"ŒH‘œ&Z|¤cgjtEu¹>eÚWxA¿õþrÿýûй{œï7D$5¹>ÜÚ¯®ÑÚjà뻆֦F*6\Í~QŸOÝ^Ä©ªÍ¡¡½#d@èÒØjC%T3ãÐRÚõ+bpS®Ãá°.K) PõüÝ_Ù Í ”b†‘"J©ŒC0³årùàƒDä|¾ËÎLÎç»G§GFh9çyžcŒy]ß½»7ä"f45d6³\Ê<Ç››yûú €1sˆ¤@‡Ãôúõkf<ËzþàùS7U\×uŽéÙ³goÞ¼Ñ*?¾Ü½+¥üùŸÿùϾøµW —ËŽÇ›ãñøúÕ[1pÜÏÂûûû·ï^ÇÈEEXÉDÑ Šë• ˲\–ì}ŠÛ}ëöe£J‡Ã\Jq/l?¼û·0¹{µÏÚ¸ðS€5³¬ªMÌQ¡Í¿°ª¦i*Eæéæ“O¾óÍ7ß\.gf~öüÉñæôòåËÃ4ŸÏgõiL4ÁŸ©§»žM·|¢TQq¡!DÄj* °£í‡ÂEÔU}=#Vj¢’ažçª"`¹”)4)'¦ VÑšŒ»—†h´yÈá~èŸ\PÐ̘×ÄÛÅ :ùnÃî·þ€\Z\îå¶#]¾‘ÇùGDLxÍóÇdCê£!ïð-´œë"ÛŇ›ºú¶6<òµbbÆ‹ø;ªÏ®¸%:;Ãrk„ÀÓ4‰Øº–Öu -àìb+tîî/¾y<ôwÑ5E¶î[ãøþÆ^ï‚íØÉïc‘8–UD‰3òº,>X &äœM€B.‹gí5›—L°ž`×xˆÈæôð¦µÞ»7"̓´ !õâts_ÝHH 6âw;<·¦&3bŸ“b¢ˆÁ8Ä8M©ÅÔÉY_æÄÜDÉ‘R‹©‚ÚZ+ ë£yÚeÆFLsŒ‘Yj>¤©–BîPfVK`þe⥭1fÀt^Έ‘)n9;n9¤¨‰"t«(D Ä1DŸ‚ifÍ∶2®m2ú%€@LÔŸÔ>WU‘*ê+³‘âˆózwW̩æb´=Æùcn}ƒˆ1¦ö¡¤ÇÓŽd…®ÚŒˆMÕý¸—’]Þ™­Vê&nó`f"ÕL¬VÉ9›)€–²¨ùGk§T@Ä\22NÓá|¹0rà8  Š€{­ˆô~¾§­ÖrÔ1úÛ‰õ»dw“k`··~©‰ËÒú±ÉÝ‚G2©EÊ}ª#r˜ÒB4³œ³€ZSCmïMNZ EA­Í²;¶oPCwºgxo} óýý#k|¿iï p“vóĺ×qÔJïNw6©j6@ˆR%¥ä³0@LÍx›(="¹¼F«°Ùtí …÷Ë¥^‹X'/ÃÀÓ¡…8„ØcMUµ‘ß‘[U´‚œ ™“ÛÝÐáp±y> 5öóùr¹\ÔtžçyžTUUL܆¥wíçy&d©2OsšÒù|>ŸÏDôôéÓG—R^¿~µ® 3ÅÍl-Ås˜ç>þäoÿöoÿõ¿þ׿ùõoÏçó“§Ïÿâ/þâîþþþþÝÝ»ûãáæõ«ï~ö]fzòøñ˯þãü¿ÿýoïîÞ\–ûãq¤_ÿúׯ^¿þÞ` ç»·/^|}ÿQSä€x¹ç“#jàè÷°­ZŸÒÆàŠÕž1î°rYzbಹ"¡RFr&Isêz¾SU1Ad—ÏNqŠ!`mè°ˆ‹ qp=©5›©h©µÔZzŠÐɬօP Ä]ÓEÄ8l–x0¥DM1Ü“2W"l­&*µŠT©•ˆ‡1‹"MÓbôd+„HØÆKÎ!%555÷ŒsôpLˆ9H‘¡d°ÃG­tV©ê¶·ªUUáZ ˜7Bz‡†ÂCŽ?pSÚ5$ ÞƒÌl×ݾSUû áH‘™ [÷ ¯žæ5þ¼íÖy>̇Ã<ÏÞzT%“Îø4·´3³.Ñ>EBËÇ¥¶¹q L¦ÃñxsâDÔÀÜ£Å}ÒU "îÉZ£o´×äA¸B/þxvûÙeôWÙ=n!Wuϸ«ÞýN;Tp÷ʆ»9Œ-h3!c‚íM„ú -Ùƒ*û ?Þ¯ÍðRÔ<¯Ì{}²Ã= ½ÖÀB¢±ò€€k-)$©æp ÆÔÃní"l¦ö®´†MëÎZê”ï7ÔÞûí¤Ÿ…Zbµnbßó<—‰ZÅ@]Þ‹ˆÝ=#„øüù‡‡ùðäÉS©µÄZÆì»ær¹gf3]sv¤xžç¢6ÃNJiŠ!œŽ§çÏž‡Þ½{÷úÍ›5_¡æoß¾{öìùñxüoÿÝ¿ýÓ?ý³Ÿþô§¿ûÝ—âápøÁÿôrY.÷Ÿ~òéíÍí×øzž¦ÛÓÍ«—¯¾ùú›/þù¯_½²”¼¬ëz8Ìwwwó4—óýÝÛõr/eE-¨u=ß¿}û:l7v÷Å]ÌÚ™ûý‰èçeu^©™–ºŠˆçR.óàÉ .="‘¨Âç}p6#5ÉŽaMc UdJÉW# ˜:™Ô ½Q@¦i& Â݃¬TÈôèÑ#—¾ÒkáòRŠˆ"B )pôó‰9 ¡Uq=3UŸJûøãMì|¾äR\™ ÈMˆùéÓç v:ž(ˆS)ÛM3éDãÆ0CÞï7<ÌTE«'}6ÁÔ‰è©Yì¹î ò‘`ô¦G“+Ù¾=àö0îo§{CÏñu2»{Kû®"ûØ–%kUUµ’«b„RˆR…‘\DAµ˜ª—[Ú' ÒGæ‘‘\‰OÄìrY‰}šØlœýÜzE#ò®‡÷"ºÎqÇÂxoZ³¹úxÚß«!´C[;žØÚêšÌï(ÞûÚ’>Ü´ îHá:ŽW1û#™ûƒ¿l˜3PÛèè:Ú^¼ǘú*QD$PÓÄÓ8MÜ¡Ã4»+¹Ü.ºÈÑ5À‰§žá¸"„/À·K}fõAp'ÎPí4ÃÙuˆèÎîôµ—¥NÒðI¢Rª ±ˆ¦”bšJ)Ót0³Ze]ÖÛä7åuõÇ·,Ëù|§ª1Fçu2‡Þ‡ÃóçÐ<ÿí¿ýwçóÙ¯º¸Éjhšs&u)eJóñx‘¦un#‹T €ÀÕk-λ¯µŒ¿R-*šA›6ø8;1»¦y;ºˆ§;r ¦iš½s»”\jEBÔm`dzbQ͵¼zùú|>«Á<¬^#" 2r`@pZ€QÙGUñ¤™ ¹Ö dM|_«Ôjæ}]ÝUïsDö}ˆ|ÿ³_Et™?ÜïÄm,n¿<ÈŒ@?ú‹[Öü^bÝõõMƒjìƒ6co\ôëƒ^ lýî÷ÓöÆo®gDÎ}kÔÝ"û6kȈ4 Ù•™×u™nnʲ( ûARˆÓŽ:†£õimð¼W„Üu„:ÚŸ nG¬ß±ýå%¤óð©a—$ï?´j[KŠˆnn‡Z•™O‡˜çIªÏS°/ÕSTÕœKœs®U8DbægÏž§”ÖeuÉ»»û/¾¹»{·,Ëår¾\.bÍDaYs!NS.Œ‡ãG}̧ÛÛW/ß|óÍ ñöövšÌaY÷Júúëonoo¬Örww·®ëýåÕÝÝ›èñí£u]k­)MoÞ¼E4É‹jAP0)*E«AoT¥iˆôAQD´¦õVFX$jµÿ˜XÀÀ4Ô’kŸ'°æNî«ÚÉò>ºE#Öw¨×û¨­Þ×fqf ˜µ9XÕÒJÆ>C‡ˆµ³ÊM¢ÎF3Š˜«ˆØi1t–=ˆh5#ÂãÍÍͺ,CüOLbŠ”„”8$¢ËºäuÍET5q_Õãáp9ßÜÜäu ÔŽ.WF'`†@®3„ñÔs0€ ç t XÓe\µcë²sŽÞï÷}ÐÙå›[¬÷]³Y•]'›ÄÛ¶ºê9Ã(»aÿ¯v]aŒ¯”fNEDÑn` ݃©½ sÀ›@? œÍ‹¤4Íó4ǘ@ëJ„hµÖb*Á[Œ¢€Û1¹OgÇéúþ\lWY/`¿¯û¢sˆ}>Ööq|6ŠÌî{¢¥°}îvù}{q'†_+žaæý0žkûA·D$ vYœÙDE«šzŸÓ ˜Ð}Ö܉‰ñøøÉ÷ðà fN¼äR…8W"½2Rób¯i™º_¥7N¶Áq¸¾‰ úØ“RÇwz.à|TÑU¢öIGa u §4™A ñt<½}ûÎHkï˱ i©Æ˜ÜVtšçÃ|øàƒJ)_}õ•Ä–åRʪ*>¨*!„”f‡DnN¦txüøÙ§Ÿ}Cøë¿þ›)Åã|üîçßûå¯þIÕÖ¼>{þáü㯿þúéãÇŸ|üÉgŸ}fj7§ÓÿâÇõWùÓŸþÏDöòÕï Ì–å|8àþþ|:M ¡©Ö²\JÎF@jbs%í‡åõítp˜h »%³f?Bêmcµ{Àò4‡EY£N#î¤ ­¿7P]›Z{ö® GXKb$&SSW ¢¡´Üö$¡™:÷‚C[ÔÊÍ4¥¶Âª”R¼t‹!·ƒªqUó³'çU¤€Á˪µ¸|nˆÁŒ}ÖL̳ÄTs¾¹½…^šÄÞÝÝ!br:MKÇ€9„À¡gî¾}¶$¢ýë’µ½óqzYÛ³êH˜b7Û|0¢¸4Oßoÿñ—ã7[Ü ÄRÃc=.¸Ò!¹­Øny\éÝ×qÒ ¨Y­ýYûk{ÏŬö®ÇÒƒŸŒö,³‡@eâ™A­ÔšÑ=T¨ñ]ì*”ïã2tìýØýŽoïAFðÑä{@HÅÒuu«{澿Õèƒ]À¬—½oÚgèý˜þ­Á}Xí/‚ÂÄ^5(1xê*ªÖÈWD¡Gv¤80"+Àr^á|YÎÏ֧Ѩ™óô±[kr6Ôï8z^n„°†ßvüâî†bÏî¡wcÜD¯(øt §”†Æ s‘£ïáœK)%pŒ1:ilY–e]b ó|ðƒ¡Ö’KQµÃáHÄó<¥4Å47ïÞ½;ŸÏ1F\kq†C.ÙoWûD„|<ž=züÃþ釟|ç³O¿»\ÖÏ>ýìõïþíO~ò“¿ÿ»Xr¾,«[±þüóÏò_ýå×ß|óèñã>üðóï~öÅ/þËÏ¿øÙï¾üõåüf¹,.ì)U˜ØÔ˜ÈjEl]‡Ö,!Bb;„]Ñ—´WC½|k“# ø|ï„H§ÓéÆ ½ëYšF'c´´ÝÍ­èA,Þ| ຾­=D,¥J“QQ±6#`VJö.œª4?hSCpm`÷Ǧƥ¥–&ËCˆ1zØ]¥¬kñBLS²Zö¯ª0ܪ* rH~ àÎ3l$ú7ÿæoùË_‡yž_½z•b ÄŠjÐÜ‘ú S?Ô}û}¶6›“å>Hi#Ní"õž´÷àgÄšžÆÓU ÚÍr^m=#*R9$Ì¥"‡Pjå÷rÿñÃ1$ÄR ‚‰šßIë <8"u,5Uᵦ;ÌCêl#µZ´VS%4"×Zk‡ß>è™]5ì=Žé·zAÙ n8ƒÙùð]®ÔþEÛÁómÑØ„b'’td¢O¨z™0x#ï¿Çû¿ùÖÓ&pð´8P¾"0@®ìMU0 LÌÜ7ø|¦êi>”5k­*’bUV`îîì®DÜn¶tR”@]üz\ážd:î´²ãÊ–Ïõ}q0aW`Cº-}Ϧ‡ã²\BÎ}ta"*¥0‡išrÎ1D@ôaã”R­§izúôéår‰1©ÚeYKÎD´®kΙçyŠ1ˆÔ!B˜ç‰J)fðñÇßùΧŸ‹Àétû›ßüöûßûãï~óÛ/¿üúWÿôjöìƒçÏŸ?7³¿ýÛ¿á@ß|ó2„ð£ýÈLö³Ÿý?þŸÿ÷ûûw¯ß¼´¼f)Õ_¹ÉFƒÖZŠš»rÛš³*pˆÐÝ.½졊jèÂm£p´&Òí°1‡ZÔç¼E*´þ`Ûœ ë3éŠiD$j ¾%€˜2`1†ƒ¡s'ê§.Ð=ê' ƒO¢ù£LStLÖÜS—½KÑS•À첦ž?ú~PUdƒóù ”ŒØ¤Œ‘HDÒ¥BbSJ!˜ ªRð¢Ðbšþñÿñ?øÁÝÝÝÛ·oçyöœ€™w«z$Å&¥-ƒ28:DdCé¬ ù¹™Žƒp÷ö{ìp 2£ ê¸ÍÖêÜЕÑcÅ뾯¾?Æ”U[Ší\cò|ˆ™F%T{p¡sSBBÂZ«‚ŠJlZÄb¦-ÕiælDÄÞoª8™†Ôn’À¤–šk-™j-¦5"„ZEM˜ƒBuR¼O·„eWjl¿ÿ¶yÿä#ÎŒ_Ü:í­…Öë¾ßÝÝš¬Òׂ[«Ý5c̘܃԰J·ÜRcÃUµí1Ý?†M„ÇTjõ2ÒLÖå2¥(Z»¹‰|Ôȹ ®åmÀj‘ZJàP¥VÉÞqUU·ŠD4ck¸Î«UAB“f“Ýs\¾ºwµ¨T0%&KÓqš\¥ZFc¦0£×Ù˜£·RK)  Ó4!y®B©Å¥ß}šALÁƒœÏ÷Ó4«jˆ onn™9‡ãáþþÞG'–e6TD8ŽÓ4õ±i]×%Æp<œ-~YÖ¥Èq:<{öÁápúÇú§'ÏŸ•\~ó»ßýòW¿úò7ÿx¹Ü¯µÜ<~üÁ'}úÝOð'ß¿}rs8Lÿïÿ×üÑþä¿øùþÏ?ýõ?ÿ2—»u¹cÆÛÛ›œË“‰¢”rQ©~½jŒ1M11±A¨"†š©”ꮟfu¦*Åü &mqÕ¬”Õ;rj¬U‹¸-ÉæVî#‡î48gfÀ]ÛÌšn8"‘T@M04 ÉĦF÷.UйÅ‘YHisõÚ—šZ-U´BwšgD¶^h‚yLÅä8¥ªs0ÁÔš©"ä’ BLD‰ ¤z¹*‚¤È¹Š©ÜÜÜ”¼”²J-Uª¥y2S20v —• HÂâØÊÝžá6EYõ-ÑŠ+$jCè\ï:Z5È\»ìJ‰àCÄ¢ ˆÔK|—F`½>nJÛëQhµfk4ç-¨MÓ<¢[¯!ÄùTÐØ©k–6ÙNkuûPS¨Ãb¡]¶(˜¡YÛ§Ð?‚[9¸‚› pêîQ~Ji?€v®Ù­G¼: X~&ŽÛ»Ï5GßZõ€®]§¾ÕyæK¾‘;FÂí‚Zfà-q * ¦ÇõùJnŠ[£ÁØWÎuGeËËÆGÀÑ €î¿(h—üFÄ–oøÐ£kè"Rœt ÷9j8‘g›þBSUê+·©À;ÑÕ© ýÞqÏÇ›¸¨Öæ@+^Úi)½2²Ö‚ýÁ»+lÉl¤"nl}:U%Æàn‡Ë²zbb Çãq]ó<Ïžª¿|õ2ç•ÍlY7o2“œ×Z €º!§ËׄˆBÎj­ëºz®¢r:ÞüW?þË?ùäïÿ矞nn?yòñGéWøúÕ«Wøúë›GcšñæxŒ)|õå—¿ýõoÿîïþîç?ÿù_ü—¯¾þ}`F´ZE¥"âºdÇ7˜¹õß=ìêˆ8„Þ-0'†{™oº[ûÌe'DÕžâŽòàDru}_Oþñ=%/¨ªÔLµ‡]5­2<á`7­ªìNþªmû~û&4"2mf›®UͦK:nSµf­G#"1Df:g"”*ÖDZüá”f‡ïÝÖYšðhÿlÄDDÌ äÕE)ÀíÚD”µ_ELTA¶ùéþåéK Wn|£ê'@/Øy˯ÆÖTçûÇw…ÏàÕ¿Â&&Üžûþ›‰F|ÜX‰}!uö=ÄÆ‹w ÇܶFöÝ¿ß? \=ÄÁ·/Fb°A¡qØó¡°Àþ¥ð $ižÌtè=jIÿø›îûß¶BýAÔR¶½³KäEªênV¿cèîS›:›¿ ìöôK»tÙVh8 ìjDÆöŒÁ‹#P)Ùµ-E«Ó ½èˆÑvÒEŽF Ùý‡W7•"d$ âºÞH2j™ û*´«âÉ‹833²m=­ë‚Ã8ËPƒñ°ôôƒº ‘«ª¸–…ãw†Ëz6mš$9,b檺®+€Ýïçy¾¿¿oëAÁÖuU­~/TtYΪ:M"ªUýöpWõó;cŠqúàù‡§G·¿øÅ/¦Ã|¹\nE¾þúk0yw'fÃýýýÓ§ÏÿìO~øæÕ‹ÿãÿð?¤ätyùò›£V¹èÅÅ„SôÓwìÏ!èJD†Ûób<%4ÓRk›‘!CñÊkßVûP:àÛÕÀª’36|‚­¯ÚaLjW½ú{iµ¯ÁÌaâ" Wðw>3T`"Dú* H¸,Ë mäœÇ)íð v·_ç—ËEU—¼ºÛ#ˆX—ºhþÈÒ1sÉ…ˆLŒbŒäíÓA=í©ÖÍè[Ÿ+ V¡w„´•.;2 6ˆÿª`÷/b0Ï{˜œý%ò-£ó#茓ûM£Ý7"Ô` ûõ×ÚÌä†6f ®do74Ÿû â8A¡)øæï¥ ã µ<´§Ö³~Ù/œɸIí‹‚5¥XS}ßÛöý;³Çµþÿ|ý±…:^äÁa×ÙLãø†°ÇsÆçBd‡NÆ­hÁY‰XD‰ Ÿÿã½FæÞ'Ç´¡§#·¿:mÌ:´4 |„¦NÍ4 4&BPS%7idbŽD†n…ç4ÛaMð6™qbj2Um¥™óžtƒÆÑ#u 1»¶"“ëƒùw)bj£[„j‡;j×H‘Îòó®Ý.šŽ9çRЇÑR2a@Äé0ßÞÞ¼{÷ÖWx­ešæ”’HAD3Yk!fjvh†Ó”Bˆíí EŠk:‹ø8+3˹¾|ýêã>üÃ~ÿË_|q÷ûßÿþîî bŒ‡Ã1¥øåï~óåo÷æõ«ËÝ»˜R`^.÷¥øµãñc ¬;ï "1ønóPô}Ð?8â0©PŸ¥ô £¢]®m¦ú Û¤¾Ê¶­ÈÕ ‘®ˆä Þ©§>ØÆ!×ÿÚµAésÖ„Œ#ï‚ÎT[&Á°iq »._†ˆÈa ümF“&i™b43$6" ¬¢¥6K8$ !†MuÜè§J¢5Š:¨ªA#ä˜Ôªª€ÆÌM i«Ê7â„SNG ÞÝp$ÜÒpèò H»i¦8Bo}¸¼Ó,?u—¹³«¸ÈƒˆÓë®Í;ÛëQd>wÒïâ¶`ÆÅw¡Þm™÷N8~>×ìu5¡þÙ¯æw«QÙ]ô:®õ A¼ò4÷•<(ßÿúc/çðà(}ðyýu\Wn Z“Mþ>ýíºLü&“=—÷·ØZ -¸ûãäÌ‘Þ$#?6Úìmý´n°™æyšëÿµ?}²lIòÃ0ß"ι73«ê­Ý¯{3 p†¤@F“€/4£øçHfúGµ˜ AÑL$Á!Óý¶Z2óÞs"Ü]Ü#îɬ×=CiõžUeæÝΉððå·høÁÇuGfæÄÆ x*—ÒËœq¢£ÜFÆÁ\Ì ™Ï9æhÖMm FÌÏúÅ4ß¹-Çï 1#¸yˆÆX&uácÝÄŠŒÀ×Í3Ï|Iä[Öªª‚†ŠÄ]{­ÕÝ/—Kï]–jà… 3†=!ôÞó¸4«µ"Aô CôÀmÄ/ÀÖUD~üñ‡§§çÇOŸ~ü釶oŸ?þüÓû¾ýÕ_ýå?þÇÿèŸÿóÿÇï/—Ç÷?ýøøø¡]¯,äª×ËsÛ7XOõ|>‹pkÆe´¨”£9ÜÁéF;s1¿M)ÍáÆB:.Ü㆙I_,'5‰F.ø¸Û~`-ŽØúZ‘üØ |UçÍoŽú#1ÎÑl´Ô&Ëý`é @Pk–’D¸,˲,€("žó)÷r?aˆO,cõ‘šó€07ãIQDdWA„£½„(7 ™©îy~Î~ú$¹ƒ‚\ÜŽ+|\ýƒf$pl=Œ‚ëïÔkCŸW$¦ž±ê7­ùL ³J{É¡…—ŸåUðªP8~ÑPä½eÁ©_ôÇ‚ø òÇ!ˆÿ‘Côðu|3t#âa´Ff&3`6yÇãäC7Åèœæ3s åhèdŽNW›]k"¶ÛEÙY„âa\ënû¶Aк‚”Šˆq¤C˜«.e±‘àÌ𢄷9&úÃÈ2xš©·“GÃ6·Ãåƒóà„â©§(’GšF(;±.§€Õ@šÉÜІެˆlÛ5ê¢g¦?f°žÎ‘òüøþþþ®»><ܯë²o›»·ÖzdýéÛ±Õ™C0MÛ÷}Ç,“½›qkmo»êÎŒßÿûóºH¡ï¾ûÕº¬ÿò_þKwûWÿïÿ—0mÛ¥mWDCw)%ÐÛàv}~bD5«uƒ1 å™ –ÄÜ.!¶šâ2:Ox™4½Ü0cÄm%êšÇBs4µÑÏ™Kc†õx‰ÐM<ƸÁ% vŽ·JÈqàÀ™‰„Fº0HOóÔuþ—ã$t4wf^׳j75Àê€ð‹ˆº¹Å‚qsf60ðèRh‰ D”Cf"æ`€ºÆ½a¦©!Û Í“c™ÿâ;·ë?Œþ’M ¿pƒÜ=>þ«Û7ÑY¾ø@i¨ë@l!ÑnŠó|”1ÀVïÜ㟓¹v<f†>6uÇ_;$…/6»ß ¯³ì?‘kϵú¢cã jü»ƒûñ âíî—ëç?:†õ£ÔÏ`·ÎÊ2‚™GQh¨À—¿8T˜ )¬îƃÀfÞôútÂsÛÌÇ‚Ó[ëªÚ;KÍ*"º]9Á}¢º.!ÌüUb’RH³8Ä¡ËÞ#C ÇqubÄ`è½–Œõa4\V_Ôñó°‹MÄŒL,UJ Õ*f9OÛ¾K)Äð‚ÀÀ –Z¯êfˆ¨j""RÍ\DZWw¿\ž–ey¼<3óåri­¹ª»EÃ7è]îư¡\ke¦Öz€½L{d=±ŽÏw÷—Ëõ|>ýùï~»]/oΦ»ö˜¶ËöáýÏÿæßü7ÿýÿÿ{ÿþçµò‡÷?»÷Ói…p-·ÞµMߨޚŒ¥EÚ‰˜ªæ}¥Ã­$¢®]U5ÅNn1â˜}Ìã¸ô_í±P4=²¦CgÆÍ\ÕÓ‘¸xmËy ëø²’µá0úB¿ÐšêÄ„ÓÅe q}ª23š3RLqK]âÀ©¥~ó«ïâ*1eœY2vUÓ67r‘RJÅ1ùÊQ“šZ +¢€4DÒA¦ »8 rpDG"4P P!ò3rƒÊéójÛMO=¸^± Ü^ýòŒ†Ç4ïé‹tx<”òUHõ¡íüª‘asD¾‡ˆ ]mÔøÙA"IÁËÅ3»s¯"ÌöŽáõU)óê}~~¢í1Ÿ9î=~ñ…^!Ë_Ÿw‹ã0ë0Oô²„—‚t5ÊVfB>¢Àadî8[瘘÷:êÕ¥è;¼¶o‘½b9Τj@rÓÈ&ªµJn­ÏÊ.üär=Íj2&3fÈD d w7rÃ0 "mЦƒSФGmnê lG ȧtS$JEÐÄ݃ÚnnÝŒEc~í½k-öRʺž£6ÿöÛo»Úóós)ÂÌ—í*"ïÞ½!Âëó•™¹”¬FQ´[)ÕA§ ¤,uð2Üp¢·ûëßü懿?­ç7wûö즗çÇRÚ~mÚ[ëŸ>|hûõryÚ¶ë²DèÚC»Æ]÷¾­§¥÷^Òš"¾oÙ-Ñdf¥]bè5Fo:¬5)øö>Í^n°Ù6±× æ¶„â×r,§²fxòµ?E* à¡ÈêL\K¥‘àç¯M×Á®s?ÞfîýºXA<®µˆpð÷}ïš®ž‘Œ£¹‹j&ܸoM?!!îûÅœ,eÛZLPÀ½”_¤¨êÞZБbɉuõZk‘ÑPF€ ÁV€‘äº:ò‹j}z™„Ý¢ó­MØIÀ¥¹A _:;ã‹€>Kƒé&Ú0ôæ@õH¹<¬Ÿû:~j®Ç6‹†åÒÑ:&üvç1ÇÕ1“ ³Ù_J)FC§î·ÞÄÖÇÈŽ½cä—ùIw©ÏâçñpzqÞ@qÆ2˜€÷ä¾vÜPô¡ðƒˆ¥”¥.D¨=ré|' $!øÓ⎦ \µq‡Ró‘âc¥žºóèR‘øÖ¶®;  ‚†¨µiCStÓ¶wíLX‹¢©3 IUuRí`*ˆ nΦjÅ<@"å Þ0 Ú2™æôè bžHGò&È‚ÑeBB.……™X[&7uT‘x#bå²®«ªîm ¡ç"òðð°–úüôx¹^ºõO—µ¨5ÛöëýÝ™ ŸžŸŸŸŸ UJQu7úú«oþÁo·o×}» {oz^Ͻu)UµjÜvuUmK•·oþ§¿þ·R ñî?ýô€¾øò«OŸ>¹GâÛúvÑ~E0pëÖ‰h©§íÚ—õdQ6Ix˜Ì5Õ&% w¼µ}Òµ=•²ˆBŒ ZCóÞ67]jq÷ÞZjÇ”Eø%†÷Ö<H‰9OÅa·!]/äÑßK‰+÷È[‰……Q ‰X†ïc‘ÞÂXíÖº[…¥– /!ÄXÛäNA¬žé¡:tèŽÌT ² ³6³~ÝŠ3ï½Õu$Gl­Êæ"R-k­‹;:´ÞwoU–ðh]­_‘Ýví»ö€4@WtïV¥²›“T.•ØÔA1á7ÝiΙæiÞªà}ÄzLãÐr)Õ°o3‡ð3¦#bí3$÷þLhî„–¦\Yº|žO!š¸AÀÌ­µeY£c$RD âRJ©îè=ÔË5È1ß"² nà/Rcõñ såê:™ÛA½kuñ—¾üö[œuö—‰óköÖ1ˆïøAeoVx>Þ×k8?Í'Xd ¿uÇÔÐF‰yÎóIZo­·€Wͺƒc£q­5„œ"ÜjŠ_˜To¼ßžq¸àä†å\ Ð#irs@ $ ehÁ‰. …±Þ’‹X™)þnÓKœpø‘çåÖšyž§InªÔÆŸI[AFÊ)?R`ØÃÕ“ =àñt:Ùpˆ6𦽵ֵG˜“ÉP_@]ÀÓéÎzW"úþá_˜õ>¸Ûº.ûÞÎçóåz­µlÛ•ˆÎ§{hÛ•üá‡eYTM»í×½ÖÚZë½N+"~züˆˆÂúéPJ©eHðè4¬™ûPÇœ`Û‰[ðiŒƒ¶ænšX޲:¨[a)ðêk<êöO¼…0tzGŽð t ¼BÜ,L“èlrJ _³Z „°Ykan…9¶9²XoöÄé¯å‡ûÐôèH“|B$’Ù–)µZo"š³uƒ@pÍLÓÁ{ë½·Ö÷RŠHÙ¶mßâï²ï{‰ F4…@»ºšHÉ”-úQNUJ ß‚Q9¹=d}‰+®«™AÀ(_šxxËÍg3íU™u¼›3ÏË`„"Œbb$þSçëuÄDJuƒ`ýº£Ó­;?Œ2ð¶fn9þ¬á6xå?ï®üRB>ûÎ/^e߯só_š*áóŸš½ÐÓÿì!7AòxíÂ%|˜™ˆ‰™ 3q@r“kðòc~þ´/^‹‰JldÉ©’#™Ðû‡ƒÐùÔÊ f׿X$æ,ë S`A0P3Q*$æ½oà8•WKYˆ¹uUŸ ´@ûÆ<.o+ŽÊëÆ»KøWJÄÄc>ìÁ„ç*½­wOÍò¢Y­#xÂlÜL{ Ø1Ç>»Á­¼aít°¦‰ª3M’îÛvݶ«›@ë}רÖ:`ÄäüÐ,Æu]£Y „R„‘¾6"ÅLux–öÞYÀDéJdfó<"1b¨g½Ð{9ôséELAà9<::Íàu Fóö³ÚWÁ=Ð8±ýвŸŠ»3~åó#².{k±U£#ä§vœ”zŒ¼³‚ ÅíŽXt{ciQrƒ±ö‡r è0…¢_W¯çÿ¯‚øá |ymÇE»£ŸÇ'9^œÜÈ7Pqò©j¡ÛÁsüzÙ_ÕÇñ™ïÉÀY‰Ä%îw˜!;Ʋ=–›Oî‹rPÈÐÃgŽ#AÝo6êä,kw'¢w_¼5Õ¾·ø¦¸f±iÉmKdž&g8jœ¸D‰Ç8ŒRóG‚—?’ $Þ{So3{~~º"¹y´Öˆ%)©½Ï¦ª4D›h×ìûNDëéNõ)º:w>šÙº®Ì„HOOO„òÃ?tÝIëé´^.×óº>??/Ë Ì\¥|úô!Sˆx½^ECA…¸šckM­‰°»s-e©íÒpþâŒì~œáP†*E¦Fñ1£Aáà ÓÀ>:aw‹+`ê/º¡ŸM¥2`«*‘0“¡E4' óphÐqsì=ª„IȦZe=Uút <#„¤ÜnkÑ=›)~Á^Ô‘" (Œæ¨Bt3åwBìؘÑÕÑ<”s›™ÅÝãvD_ÈÌtïÈÈÌy|…ŠCw悈&Hñü1´dºM×Ñ<×dž^ÁhŠíîX‡cA‡hH¯Ø@J1¯òÂÑl~äôŠ˜ŒÊ¹ÍGY€póóÄ,z_¼ó^U˜Z Sî=röùATy‡_èEÄC^DOø»¾>Ð,|Ç×<ÿ^f0/0¿ô®^?á ýäcsæC4Ë"â_,2^}Ìù6ŽGq)Q èS¢”4œAðæ xµù_þ4OWËKƒ£ÃãfÚuçèrh¯{¨³"€›_/WwgÖÕ0oæ½$€ðAB Ï!Ñ<Ô8–J=ÀŽN¥Ö` _1v†¸©¦0!S_5t¨ybx‘"˜ðXS×DRbyÄ€»©³öv>Ÿzo—Ësï}]‹ª^¯×Þ÷pÑ]–‚\½µxˆ© Iá^Jù¯ÿëÿóö¿ÿÏÞüøã—Ë¥ÖB„­5DX–e]ϵÖмff`ªµ.˲oÛ+(ô1ÔN Iä DÄÈ1¸Ê$:‡f§d1„#@bq°oú‹êøE/ø¶4¹¢’ݺô_t·~ãéd±èî&RcÄÏúÞ·ËÅLq mŽà.·žr¿iæ0G}¯7äHý8SÆÍæÅ?þéªDG]~@¿õYüø~nÇ L5‘?Uïü—cîßÍ¿øz•tÓÈ ÿDYð*ì¿óÙ7oÁÝÆ™8£ùÜ­/߯ˆ«ñlÑ¥ÀŒ@Òwp€l "z†Nrâm@Ž®4qœE('Ðø¨Ù§ëÞÍo…ó«ë±Ø•£Z–(ð[SuoÂWQÕÎË™¹jïݬse$lÚ…Jž37v2ÄÞ¦ŒÑÿÀ¬qâ׺?wï}?”±±È̈1¾8i͉Æ+Gj@ Zo |m{)e]×Þ»¶nfŽ!éεÖmÛz»jßwfZ–»hã b)åò¼Îuß÷Þ;öÞ×u ÓTsªeÕî÷÷÷oÞ¼ùOþÓ¿¼8züð¯ÿõ¿þë¿þkwWmwww­µÇÇOwwwDÐÚàs„w³ßtÕ3O?$/vrºYY·¡œ<%á*µ~éÝ =†à—™9" ×µ¾ €?:”s÷>´{9sdªcç =Œ c¯,áȤª®ÃUÂU£ƒ‘Å;"C w3·È,YvXæÈ%"µÞ B½£#IYªì­Wyßš8Ï|T4NGô®M ç“»ŠÔëõZjÚ,€æ>|¸îºmWwd"&–Ë~áÿ¥÷Ý­×a@Kfî˲\¯×}w3=ŒUQF>¡ÐÑE|ÿþ½¿4Ù—W9`"©¦)üÍêÈÝÝ‹¸@9!â¶mckÓ¼ªîŽnŒÐµK‘Húc#OcëYmŒØ’’;a‘š#á?ÙÿtÌ=®½ã7ogÌøJdA"ë^ _uŽß<&õó;â…f€òQã$f S öhoÃÓ`FöÃûO6Dà‰‰¨ï:ÊÌ ¡ÝpãX Ñû ÷.&ü †¿.AfÇC$šEE^¬–!Î-Œ1H…˨"ºHD©ËrÝw ë^ˆ½ÛÍT%lºˆ 1„Æ4¸[Õãò Õðæ.\&ˆ«;.§u]jﻻƙ¬>Î ÇhŒh`ÔIH¤„ ’ÆìK­î½±°¹E¿§ï½HÑÞÛ¾;81ﺟÖ;f©ëŠDëé¼7©DE®[ëjç»»ë¾ß¿}x¼~øðßüþÍ÷ÿý7ÛõY»ЂÃèûz}ví…ÒŠÀƒýå½ aAUEf$’²Œ ï­cè³"‚šiïqP1s»>»¸EâÝ­ííä D æ½›R¨«1™)4;4èΈœ®‰ ³ds3p`±ì­×GïÚ ,пÑ.ï;1¤Â5-Ë¢€Ìµ€#‘¢Þ®4ƺÓE¤˜#"›º:p©È‚XhÛ6m½–B½õÔ‡ÄøÈl‡º¸2Yø@33‰ ÔsEá>(>•…·ësÓ‹Ùnd Þ¼;€ 1½¨÷ѹÄÕºöæˆÂÌR àÍÝ.ÛU{›»~tBÀC°ž‰º…x§¶¶Ò ÓòyÙGFw&ª¥L¦Ë¨ü‚§f–3›!16s‡ÄûÇEF þWL™y{²X„ѰW›ÂD-—Ì[ǰñRëó„òó/w‡¡ˆ)q•´8„Ûÿãs¼úNÝáñg’4j_>‚ô=N')…k­?ýø³HAÀÖ{l¿ëõú¯þÕ¿úþßÿúøøøøøÂñBÐZïæ«Ù¤g¢»¤œ¬E"$ŽÉ}ߨ÷ÊÆ"ÂÄ3ó g€0Ÿ3ý±¯FHá*DwnÖ§º§ë~Ø~8ùì†Áhu‡ÕÅ«höm á¶OæH<µZ˜u°^•ÏžÓÎÃÏ(º»ñ´R$ZÁ …Ñ‘%²HGäꔡºéë¨Ü®—¬J£]9êËÞ™ä lÿ§ÀÃlІÇKvëÆŒ :ðO7¡½£ïÌ)ðKtëPú^¯ÙgŸU,„«Žé¦êsH<_ÄЈ›Qûæ~á‹èÒèÄÿb–=oÖ1­þy.ü¯ø:Ö+‡åö–^}þHAp|{!tx\uy›ÆQ0{€· þr€£ {Ñ+ó±èïdô ÌC­Ã£ŸF£Æ­m ,ÄáT€Ç«ŒÃá%¦»Z‡›Zx @¤)f†‚ÅǬÇÀÜz#‡{1±š4/`ü’=/TàYáÖšSîã›´mb$IÙs@­Üý¦ß&cq¼fN„ذ)tp„Z× Xø(ãHÊÆ›·àq ›ioˆÉqO'?ˆ¨bÍB6ÐT 4õÂÇŒoº#u@¸§Zšçæj&LF s’*!ZÞÍúÅåJ`Ú÷Q«‚Ð…jæáw[Ùà€Þ®"a RJLŠÊR—¥@7Ý›öÞ…Ùk©®ZYÈakABÞ÷Ö¶Ö”™EJ¤SÌ|}z>NõTÝýãÇÛ¶]¯Ïà¾,år¹ˆpˆÀ¤Ü•+"´ýŠJf„¦ ]¦àÐzP"f Å; ¬DôRb¦hf!±`Ö ’‚À00%` pT@ŸÝ^ˆ”™C¿ž@;Z #ïû4 ³q"eWñŘ™# 0Nš;ucnÛ WfB¹#Aö—RÌYu±Qü"bÁó‹µU-¶¶¹»j7´ð!A&wg(>õ ñ˜]Úðü¢Xj]UÓ–ÝÒc=/²GFáaÐ {'33´´¾jºùžS23x àá`L„‰qê± ànœÆ43åÞ,³þXÿÂ|Ô#%ˆcÛÞ"oºë-°GXTø hˆ“L›^y‚æàÄ]xyYŒO:ð3"þbäýÎÙ?¯>/>>o‹Ï`8SÆ™õþâÛˆÞÃÈñÁ­g2Ƴpë—ÁMþ3 À8NØ,œŒÖ‡úf D°;t˜ø–H˜PÖð½K…[¤˜k€»Âm½Ž)æ}óLˆ¸H¢Ù a`•1à]ÄÌÒÚf”‡Hó‚¶ 4ë_’6b”À„É!†žràTH‘Ìt“ƤæŠ1äL¯t÷ðÍAD4ÅÑ;ïX]jàçÜX˜ˆLƒz¯6;Œ©«ãk]×e]ꢚ! éæÃ Ñ—eAA€Öw)Ì1xP}¾^"{Bœ˜3õeY¿øâËwïÞþøãÌü|yÔÞj-Û¶E« ¬ïDd¦aÌFHL ¡Ù‚~ôTñl43baqSBÖÞ™˜â6„ I´Ç#oŒPžÚ†tdöŠÈùi:‰¸7EâÃ'©Î™o#ú±D$"¢è ­§{ïû~m‰$é‡lGŸ#}˜B’¹q‡Òïè&ÇZãë'ó>vk}بf½÷¨ ˜8„Fã¡á~ÉE¦Ô­E_ ¹1ÇgÍ2)·<€¶®ˆ‡J-ѰÙJ Œ{‰¹@œ®ãtEÅiÍ5sËCéβßâ9MefB‘hóÀ@1Í q`c¿žºâ I8È–‰Ï>œ¯àã÷SG…™ŽÈÔÙ±™{öïl‰¼ ÍÏŒþ£ø5ýÕß_÷y=ÿȓϧÅÃw‹?BbŒkFn>hz¹bEÅÌr4Í=7ž~T«7¼ÍtŸÿt"â˜.0—õ¸ÉF‰”ÂÇÈž ‹8Ä]"sC"µÈ²oDÁ<8 TK0µ‡%ê@¬c8!08"PB=%íÑPĘ MÝ¢úCD' çm¿õ™90Èîî®ÚZQ ¢Y›jkcJs#\EÔ'¿©ó„ñCÌ)ˆ¼µÆ,L6Kw©îÚUMG7 H]j*Pš/µ¾}óÁ[ë1^¹»»»îšö»»ó¯ý|ùå—û¾xÿsÛ÷}»Dó·µ}Y–}ß#«Å ¸ïÍÔD¸ˆ¡ÇšÐÆ"¢GàŽéE‚i åCX×5S34B4„œ;äpÖqÿY—ZˆYB  F }èëÅ.OÇ¡AžÛŠòìðp–ŒçO¤À€ ¸*㛯£Ò cóßgsõ!¨­C¯ÍLoqv¸« ‹ü<¤Þ`Ú£˜ž¿›qà4Ë‹ÏpÕð’\`/“åchþß"¸ó„Û¾øƒ‘ÈD„Íúáñ´Œ@¼½ftOùÂ[Š~øåº0 £èûͳ$‹ƒçõË¢,'qÄnÖÕÔ“tø z¢šó˜ìéÍë+6·!“ Izi3òèW€‰Ì«H º@ŽØÜTµQú×9 #b  ³c&Žu?‰33¹]éçä"o"¿ ‚ó]Ë â›Ô¢ÈçÉ›†·¶ÌêŠ}vSÌ_s¨r’/~dé/‘bµI8ø þ™©Þ¾ÿO ]Mmpñ3 «¶Ù­ŽÊ‘D XwCB$öÑ‘sCæêˆH{ëÖU­ÏL.RÅÖR 'äûý¦ùŠæàŒ ‡ìühÅ=ãïè³'Pè&`¨ 1oôŒ†‰¢8 çIs³ZwˆlxéáK¬Ëßó ‡ûf°‰ÙÓ…mNÆD¢Aó$ó‰åñçë<œ~l3¶ Ž®ûJR’üsÉ©‚*€!JWw"^ÏwM»9(x]×õüК³,j~:­Ûóŵ§ê‰iø}‚y(±1Ð2 ¸|yZÁ8¯½x0³HI2< #1!S¦äà ®y49 jŸÆ`æŽ$,ÒÕ —€O‘ÈzZ뺴Þ×¥ô½íûæCñ+5¹LÑ,Ôè&í1@@ä)}Üí1¾ð˜bEémnnP˜£éì/n…kïf“d)“òlv…ü€ˆ¬ë R˘†µSŽÝ¿Böîæ¶ï qÊÌÜÕ¤æ€Pû¾m³ ë½³°AÀ®=r·à¯Îd!@ô–Šê寛„úàӂϼøÅ¢Œ¨¡¦]—efB„}ßÜÁãàðÜIDSö¿ýæßë•CTÃ;&: ·4‡rÙäæDÓ¦NšY²ŠÇ¦8æY¯vÔ«”GJ³r‘EŸ9"ª«©–š½ ¾±§“-Å•Oú%Þò2œÜËQdäp—Җh±ØDŒìcÕ@dâ)‚LÁLi4æä˜xóCßÙÝoN›³æTfBLS`"’è]&öYµK­_õåi]/—§¶_C~àó)"ŽÖÿ«oÎ;2'óG‡ðG0€Ô>ãbÁÕ³¥qËÅç(~¾ôá1GVÑù_Üqf'£”€1¬øùAòTË:cà8b03·Ï×á,2ŽßGÞQú1ÄR‰€Ý5ãwÕ:Ìö%€Óh—‰…ËW_óô| 08fš™ÐÕ»jò]Xˆß}ùkÌ¡¹·f¦éâ—1:ëÐÄäxzÔ¢›{²þ¢Ïæ6ä7c¸'h¿Ä÷¸!²,u Ù§8ù‘`ß6t»\ž­í|¤@æ $™šŸ` ‚V „„Œ”¸ì "€«:èÍäÃmò¦jdƒ6o.Ñc®UfO#ftqá÷}/µú !bïšâ`ˆX¸0q¼Vë-J"sC¢¶wwo¦]{ë½–’ê4fÑ6!¢6º“æÖö}.>wÞl®"ɽ4ÒvO9~Çôa“ @kmY¿\.ˆ¸®+íû†@Ñ·Ë#Ä 0ã0Œ-:+w".á 3spN¶ßË¢ÌÝuÔ’8T×ã tN~x¹k^}½t©ÏᘙŽKDŠa¬Ï ò<‡ž³©öGï²Ù¸MÇÜØL$ÌöDÁÈ‹ú— Œ0®Ûw‹»ô§ÏÌ”H™!‚»ªF–‚·N·O˜Æ°á>‘„àv30À\bB$@ ®}ß·çç§m»PŽ:!²ŸövlÇ÷ã^ ÅüCüb¢ ôЇ?s¶V^."¤Ù|é[3}¾‡8Íè`·2MbÿXpÇ_Z%ÇoFÇ1ŠçÛ Ó}þöŽ_¬³·ãuˆ?¶k^¾ú«^Mþ_Í1ÐVÙÓðâàåZ!àm„¸m[)e߻ȢºZï½÷Æ©I¨ØvGbÖî`Úy˜¿þöϘœJlI¦ÓüÏ>•ŠA¦°HLÌ´G‹/…vÝŒR”Q¸Ä7¼hæ1:'4÷u]‘ér½¨™jo×Ý­żXÕEàÐcûEJjæHRJ‘Z¢|ˆÌÑ

    Zk” ó I´õÖMrŒÈEÉÂòËÍgÙÆÀ n~4±†ê²˜ ×e50z“Äø«o¾Ã¦ÖÊ¥¨Ù¶ï½÷"’g B-%,_ù.Ž©Z¤Ææ}NØ"œÏöb6ˆB¤½ûÍ7Ûõz¾»ûíoóÃ?dîY˜™°­fFGþ ˆÙif(”Ú÷¯ý‘_½[Uu4æ­fd5‹Ò5®±™8¿`¾Ü‡<ÚÔ!† ±8Bk=ºU!uJÄKš{›ˆâL=Ò5cÒðHäJ¾®µP• ¦ê6oΈ£‘šª.¡²^+6|'n:EIî%j­õ¾ÝÒ4<À'ÆQOìó=gšówLïp@2íµpÛ®íM˜˜iÛ6ác To'è«ø5‚ûm‚á×ÿå¶š:£³-þ"jSö]aêA¾|¿EIO“\9/K_ îì;ˆHÉڻɠ^Ž÷KÒ?æ_ÌÓ?*ð;ôb<«é7tÈÔˆ´‹F9•Yô‘ÖÓéri÷wo·ë.RÌír¹¬k…˜”¸»;“8ÀZOhÚBùÊéºon©j €¡Ot;yè0”‹Õã`¡ê=àßÈLR’¦æ qûK­‘ò›¦@X vͼ«šÙ²žDІ@+@t0JwO­].7ŸxBŠÑP]Öóù+Îo²vIÍE7U »†#~鶉ÐKDÉ…¡„yäR覞|0šŽhˆ8e"¨)ÇD ’ñ— õ´†M]-5JïèûÑÓãÓår13˜`jáõt‚‘è¹; '¼ò°¤fdŸÄK 2)«ÍÆÐÝ}©•ˆ>|øÐÍñÓ§Oªw'0…æŠÄÑl‰–EW³4V½0ÒÙž =xµ¸èH„LS« ÀD¶ °vÔäCaöyücà¯&P#ê3DAdB^x9!òåra‘û‡‡ÞÛº®[ï„¶ø,PËÒÍ$ŒÔ™‘;ÈúèÇé#^«Ú=£‘èF#ŠóH»§ÿ*úoPX¡æÀÌ{PL‘½ÛÜzï’'6†c\]ÖR–h%†óiÎ@DJYjkMµ[·Äj¸šª›2:Q'm,S&’”„Ñ¡1ÑÓðœög2GF1ƒ¢Á‰^D‘"Ò´BèøÄK«)hï½i<œnº˜] X†;„·Ö®×+ ÀRvlDxÊ‹Çyƒ¢­6©ÜÅL/b bÛwf¢eYˆxï-Fº]{ö£1G<ëÐvB€°ë@°Ô0‰Ïr|f+™2W5ÏDŠKùe ÷¦¼EùW…íøÔLþsC¹£ˆ¼yûv]×}Ûzï¡Lü î†Ó, =>æ<ÒÆÙì îÍ Ð½¢›)Ù wF7ð;Ðo1";´]C;Q°DHÔû òxŒƒ¯Z óSƒûg4ùMéër`œâM`6)U@ÆýÍdËG w¬ð`íôª32 Ó¿gpçðp7Cy`BFµ#æŽÏKƒªKɦÍø É[Ü?¼èñG·,&5µXˆ@r´,_5ˆAùœù™ykβžïÞþæÏÿÓÓùþùù“{CríZj5 Av2S)ÀÈÌ»u:Àåô‡:ÇRê²,C\‡‘CÉÈ»{Œ_ÕÜ0òòÝPš ŸÎgæBÌj¶í­[s4$0íZ–¥‡2Â~ÝJ ÿ\”*µV$Ž³Â´í62"¥(X $ÇHÑ:¢IÐÍM1TÿGû ¬ùÁÂõ)º«éÀ­.¢Ð¨ÓmÂì½ëÐeY¢«˜RJ`TÍL–ÊDè°ocŒ1ÀÌ™ÙzšYGDgF"O hÛ®×Þ{)%‰ÊjÁ„Š>ˆÀË 3O_Uј†eùE3ѳ/‹wwwOOOËief )¥^.W ,2ÄÂ"ú°¸{Ûw`œ–䙨ެjˆa,¤èrÄ™9uŽpš@ª¤ ]D|3ëjÌ„“€)ä’ÛﳨÄs:Ñÿð^W)5„WBÈ…™{Û‰YD–¥Æûi­e(¼íØ0*ñc¹}¼ÔñVOëiÛ63‹¢ôv¤_ílL¤ÄŠŒÖÄè¡çÒÝÎçó²,1Ÿ%v‘2nè ²Oê§Þr¬ØŒdÞS·,&ÆÃÕDcdÃ$Ö ‰c ñ ²ý꓾ÊgÇ3|ÜÇ,$œŒ°Î¼†Ìm&ŒˆÂeh»ÝLVç Ût?º?fÀy1áXÌýéø>â/deéï³d¥†ôz¸È·Ä ŠHpó¼yõÒì}ø€ÙÍ¿Œþ¥€ã(û’,I,iKXˆÕМÖõáÝ»¯þÙ¿ø¯ž/OïŸ>üPÙÚ ¦˜æ-zŒÀR‚DO’*a¬opß;Kq$dÙZ7@GFfHWè©l¦‚¾·½”âèÑéj„d®¥Šš9¢;9𲬈–½÷¸*bÁ‘™A• Â6‰öÞwŽüa‰&>ŒÖ¹G5Ë"®:xWm®x't47´žÝF÷4ö ù@Œç.¨ÒÑ B¡LÁ¨T¤ÎÂ5Òèªëéxÿ ûФ€•À†ˆ\ß¼ûúÍ»¯žŸ·ç­I©EÊår!® <ÉH™‘¸¬ç}ÛIÚ¶™ÙR ÿ Ãeêx€™aa§Ümé{ÈyåTÓ\Õ‚óŠ›4“?ÑÄfæàÂõ|ºâÞ‘/E\-¼ÐÆDÌuYëõº;•©Tt°Þ×uuïû¶ ³ªªssár:­uè½¹{:Ö‰&ŠF¼£» 7UG2ÕPž.!§3ÍCÑ,tùA¤"Ië†("UÕL]Ó 9Dâ¼ÇyíîÖ ÜØ1Ô›{{¦¨_4sÏ £h»îÏŽæ AÂH¸ŒvADp @Q+¹/Rîד;gœ˜=øYÂÔ{3í1ºŒ“IŠªŠP´øÌEXØU#ûÖîÄÔl.!NofÞ•Y„Å ˜AU¥”®ª¦¥³ÀÎGH!‘‰MÃʆ<9 ©%΋£§—¥908Z7Dvƒ»»»¨‡ 0ŒZ!º4® ²áš9£ã,é4D?^ù ‘#Bþ=HL/“ëq~°$n ˆ‰oï«*-‘gÊ„ëRÐL‰ØÑ’~9^7ÕüœPjà)µv5`&‚¼¹B]ÕÜ™*Qqu ©T–©²¹–(–ÓÚµ¹÷Þ®nûO?þtùðÓOø[r®R8ݬ‡¤H1DbQ3¢¸GæîÀ¼<ÜßßQ­µµv:¢œ³ÒÞe¦™†¹ƒK)µ.«'ï@¸0 `púpk-jÆ8*ÑÑuN ü !˜ºÔ”ˆìÈiª¦»¤‹;3)GÆ9À øTbÙ€H¤”˜Áló€[â= c\Ê9xÓ•8K9ÕY¦6Ѳ¬–Î8¤ô6÷z:}ñî‹Ç§§Ózúú›ožŸŸYrâ fÆÂ€(œ=–’0vt4d"_«Fÿ3[zÙ4£Cõt˜¸Y4ºÿóÿ£ôsŠÌ|ß÷ Dü}U&ÇRfÉLÞlˆÉm B¢±H¹š1`Ž! ‘ÚZ©53¦›¯¸{©uæ˜Ùî™úqy»b®W ÓL÷ÉÒ'O¬XÜ£à÷Æs¸©Þš¯ íñÿl²§LJœU9Á1õÖbd¡¤Æš“œšsÊÝ‘ ˆ…áÌ7çÕ‡:,Ùù±ðÜýî|·m›ªŸN§eYZ×Öö"%úµÙ Ë%$‹çœ‡ ‹˜ù/ŸÅ5<®“AIHT~ž ž‘0Ú­Q‡WFà@pD‹5bÈà!ÅÆcâÈþTUHz×RJxqc­ K%f‡€ÜKkíq×7÷oÔúÇ/O—¦M ~õë__žŸ‰ÞÜ»:3uíàfðàjÆ£üÛÛ8fDdú§üãQŠA˜k4vòüµˆÇŒ†xE –ùSíÌ$–[àIû2Ù:¿D5à0a‚ÈØÕbn‚flÑQEUˆÁ–RU–š&Ì£pú;1GM?M‰ÙQ$„颎à4N±#ô„MBò‰½ÒÙ‡ÓÝY(̱(ÃÄH=Nt®nuÌñ.Ç£‰Ò'à¶/LáUfÎoÍËÑÈ18Qw‘‹GD"ÏØöíùz½^¶}ßU- ËÀ¦ ‘´+&3CU[8¬Š”Z×  î{ÏàN$E4” „ã¼Aæ‡w¿ê­ ËR—o¿ùF˜Ýìéñ‘ˆ´íªŠà”l‘Ì{L½.(‰°«ŠÔP^]Ö3‚‘GJAÓ5Y†/ W õàÃjË\,‹Jb$¤dÂé@ŸÞz 9ûÊYd´wˆˆX˜¹«rôíS8^‡*Iž©2OãvŽáG@Tµk`÷#`¹1©YS_–ºí;P)õtÝv5XêÒ»:.bÚãØ›7o¾ÿþðÀDÒ²®ÛvAGÕŽ€Ö-Y±àh~È ,¸ìÂB7Ý`&>Eã)â £d>r.¦¬tô© à¡b?ÇYñä‹£tpwí:4Oç…‰sÜÜü<Ù¦«K]£3Œ“ý?c·öÞZ“RfDSUšý™@p5s¢(f?Ï­&‡Hç´6 ¤±™–)n‹fâ6Çk‡öŒóï‰Xi{„(¦!%Íź,³ó¡éšð§ÃWLÀˆÈÂŽcðïÍ@ÕŠ3$âZ ›{ï»3s)r‹h‡’Ž9=d<áÑ*ñNæµ±3³„Œ4g˜4±=£½s«´j]¢A·ÉPPØ *ŒHê¼÷NŒ™Á¤:ì~|ÎÓÿCƒûwzŒtñÂ|˜úÌCÑÌœX9`ï±"Ô#Ä.dã—nÍLHjwA–Ìcɵ.®Ú»)„ýªgôKÕepg&Ï.Yt“‚ÕUJYˆkë¾ï¶®‹ÔRj)¥”ea."¥H1ofÉïaÅB„¡Døñã‡ÖöÖöH­´+º Ü:©*0­§s”!˲ƘNÏž4<J7“ @aaH§Wf)ËJ,HD´:wGTUS“9^ ²ÑûŽºØÝ @½až•9KÅÁ@õnfîJ‘‹x*¾Ðc6œÂ‚X„ æ£ucŽ€aJâHì©ý µ®T–õ|wÿðÖºz]—õ|ZЦ¾ÿòTpG¢Óéˆ]£%‹×ËÅ\Ý­'{q˜Äf+€R v°‹r6…]í€àf{k¶áí»¡ØœpZ;Î14µ.‘ÞN@˫͌‡¡-â‘ö¿&$'×um»ŠP”w!f´kDî¦aû‘ؤ‘ŒÏ‘gS8t$“6þNÄ%"ÃL5ûr76Q‘ t0Àp>½†ô™9¤c3šäº÷Ð%.Ë̲@Žøh˜¨Íç Þ€H‰8Nµ.ëz ]Us0óøˆ–bA™ŠŽit7åîtÇ"îÖuo½¹»0 dâÄð’I)ø ± ç}§ÅMx=–""¼]èTØ>àåFÇCDÂ9=’€8E¢ò‹ä4‚{0"1öu?äªa@úÜ_V–s¸p’ "R´^G¨÷þã@"³†Ø}àPáÅ:qwbÎã™ K‰„EÓ-N…ZÄ\] …˜™±0"¡ªª6)1"!"f!D!bsTU€ìëºï½[ ½«[ÓÖÚ¾ïmçåü&š¼îÆL벸Yo-''îà –F"w&føbFDJö&€û¶]C Lµ32"´mgf³ âRÊ H,•Hò¨„PqrC‡žði˜í 嚀qÅÏÜ㦘RMžR-@ˆM{kMÛ6ºeŽ=¥ºsú4ÈÙ@Hj’C¸. bë-„IT•E²íFØZ—ºrYHV’…¸áÖºk¿>?ýÙo#ˆ~þ9æb¿þõwR–®=æÉîV„E¸µF8¼ä3‚"˜ãˆï`)8Ž£ NýÐX‘fnQ7šÉd‘̬ÉAÈž;9Š”¨W˜y]O’’C7é%ùL?æ¢Î4YÄœ#„ ¿ýæ×OOO¡bNDn ª{Û1Ž[°1lOÅ‚x•Ï$nó=gö]ìÄ%Ž“Rjt„b˜Lhî0uÒˆÄu4ßBs‡fâsó|&©ý0pf¢v›âáï!å|ffÏkj5ײ¼{÷î‹/¾øðñã1s¿j!"= î–ѧ.KEÄ}oµ"Þ¶-Þ´.%Œ+£éIÌ|Ý®àPYÔHJ•eEæZOÂ<Ö¤"‚‚©öBŒH<%Œ#wží.ƒk,-4¢°sg7×H¿æpÌ-\¶ƒ:?²F&s fNuow/µd3Þl=Ý!åÈ}YÖëÖ¾øê›»‡wŸž/¿ûó?ÿ«¿üËǧOýzAðýr½¿;]¯—u©[ëïÞ¾5À§Ç§` z-ÂÈ—ëeJt…I\òXhŒº¸s1ňuô bwf‚y?Г£LÎè3Ý!²¡¬¢„Š~÷0©3+¥H1:gcz †2*±lm—"±‘è·ö»÷>hofÆTTu×næ±|ø¤ÖzÓ`ë–62•ÓétwwGÄ—çg@“Bªm»n.„B=ñV¹”»»ûÓé\JÅ1SÄ,6ø¸žàS»wÎKÁFnH¾ I´ì= -$®u]×õ믿VÕÖ3¿yóƤõ믿º¿¸^¯±%·íOžò˜+ö›1"¸J?ÜÇ,ô@áŽR‘<Q‘Œ&Ì1mww.ì)yÇÌ\ê-¸»{«³@1Ía¸AfhU%â"ÅŠ Ó‹lH+0¡Z?0ä—3µÂT¢5ï\ÕºÙ÷‰÷Øwð/c¤ëõJÈ"…ß|õݾ·Ö;!.Ë25Qݺ ã²,MM–“A!:5óZKo;9îÍj½7Y+oÛ&œcª®@€Ž®™GãÕµâ¶oæíº?»u ئî¥Ô\7íàv@€¦ª½:ÍÁ»+@ÚŽÄT0ü¦Ý(P`¦æ¦šæÄ–h"‡|à`À†d±‹[È¢9œO§~Ýà7ÿàÏ~üð‰e}8¿õå ³~üt:îÈìýè—GpTðßÿðÓ›/Þ==_ýçÿ ½A×}Û–Z½{ëû¾_E™Ã™ÊbœÒã#1°0!˜š1¦¿‚wSSCettbr§¤“`P½£ÏdžÖ¸=šH„¬Ø­=õV$×ÃUmxUK0lÁ½·¨dNlŸ£0`<³øþû¶ï"%œ7ÕQAÕù´œ‹Ô¾·uY/×+1 Ec6µ, µn]¥(&×hï¨vâÒÍîîV$X×ú»ßýÙþð{"ÜûŽ„Œ®A ˆ¥÷.ÂÞÝYÄTÉC¤,M Ù˜‹»Uc€™ÛLÁàЬ(!•ó™€TGý¹8L’ÀäCe(ú€®ÖÍzÀV×¥¶­1‘)üÅŸÿE‘²o8„ÒdPç°÷ÞÚõéééº][Û£¥ûõ׿r÷å¼’ÐÖ6)â‚ôîÍOŸžN몽_/W›ª5îFÚ¸3‘pí=õ6Ý\£+hfj-Ķq˜vI¢H]—õû¾1ÇóÝ}ÌaI¨uýøéSÈTìû5C³Ý‡¯pq1¼é³Æ˜×R•6µiÞ+; ,iy’ð[[æ‹DáÆ2´v>ìˆ.Âa#…õ¶ïÛB"‰%t]b¿0’«¹Zô#(‡ ·ÙC¡DÇDÔz·T¥5NÎ`tÏ̬×ZzWB¥žz×Ô¡bA<‹ºˆ€)ºÃåùùî|£÷Ý[oD´¬ Ëúý2ÌÚ-³‰ÞÚÝÝÝóåJÌîèÀ÷o¾ìjë²^/WÓ¦®ˆøæÍÛ7oÞÖZÚvÁä˜u󘚂›Aïîî 1Eöñ_Sp‹LG@µOÄÕ¨YÁ Rqñ0ÞJ¸K eÀ’@9DªèÐB€Qh!b•RôH·©‹™¹)Œó<‚û°.LèjüÓÓÓî°œÎ\jïm] ¡¿y÷Ö îîï>¾ÿðÓß›!×%úOácªƒ‡ÙÕ@˜«Óâ¯H4³à"ÌD$ÛûæèIP–cM;Qî~èG®22Sýiá˜ã~7ô„Íðg‰¸ €PtŠc^—J„www‘u÷ëõ”ˆiV0#àìÏš+¦ÄLsñáááùù9ÕÕKÙ÷m°jxÌ(5¼ˆ†µTbTˆ¤µ~½n×ë¶mq–óÔ ù j­³Èº¬}o…ùË/¿‘mß窰iX Ù¬³9ˆ;t¨Ý\ª™ò2áT*KWOKÒæwwÕ6ÑœÂÞ¼yPµ>.Ë*RB2ÌÜ¢'›î^J9Î˲œ×Ó·_C€? ‰™}øð^„Û¾íû¦Ã{2'½QƒZÔ¡\=syO/­„ÛŸÖÆt=vè¾·mÛXä|>ÿ'õWŒüðæÍW_}ùÃ?lÛ5Ø×Þ5z³60¾SSï0‰Ä)l7ÛGóp0H©‘—þxæÎ<Ѩù”/Û>ÃP܃ª2!ÿól@fî]}ðŒC]a66oÝ¹Ñ´Š’-ZˆÈ“ûÖöf)7tÓ}Sµ ”ÞÎ7÷qö'ð&DÞ´FÖ «“t¬@gom‹OHRJ­‘Œºã²®;ÀRïM5.BÀ"Ø`ˆ¨ôîw_týãÿåÿúûý~üñÇ]/e©]µHyüô‰(J¿Þ¶Ü ºZWL¬JŸxaw7S&D(r:•ròRÜ®ÞÌ£ÇÊ|ñçUÁt8e‡hë°¢GÆàFáÔ¹Q‘Üò¼´P²3ëaá0J óDàк½.Ý`i!/8ö ÉþL}À¡·½0ûÏà´ŒQ*ÌÁÄ ‰©OÂ#OÇ0b1@¦Ç`WCòhKv3årzÀƒöETdf&• –ÓÝãÓ•ëúîËoþÛÿö¿»^vGmíùîáîéçŸËzÖnÑ'Uí­!ši[†–Ô<·1ˆ…ÀÑpÏžI¤<‡™s­‘ÍEÃdØOŒ-­ç`äŽÖh,ÇEבLaø}XeBæ9OÊWáî„É`â¤B1—å|çHöÛßý»÷7?ÿð3Ý‘ør¹œÏ÷Ûå™ß}ù´ëåÓ§÷èFªeY )£ž›ö†àfJ §uuwÝ›ª G.«Rb,HÈgd‘fi¯™ÁþÀ§ ’ ‰Aê‰8g¶€æ`‘ÐSnøÌˆ']{Ôayƒª6“ÜÓéÔZ/¥¨ƒ¹Ã Yݤe m ˜Æ­'fQm³¥xݶ8Ëk­ÚÒņ·»‡°WªÒdf¾î{à/—Käž÷_}õÕ‡¤ÔÜN@˲„£K-Kï³mßTÈ{oH€u]qP\àDo@xÌØ17xê MÈäY&¥ñ Kz¬¢µØZŸá>¾Ý›©ê¶íf¶_OÏŸDpï{³±‹H_~ùå_0â_~`?ýüSˆÞ´¾'¼m6Ô‡$ý춦Å\ý|:i×X<¦Ña èªûÀù í?`æëõ\§u]®—ç" ¶m› éàOÌ 4¬À3"ŽK1gæÿ P1‡êæ’@¤WEX¾Ü@Ð!mgùì s*@„Óû`áøü ÷DÄ´‹ËI.߯ã´Ì DL"2!0œÓiv„RÓ4E–Ì4ì™Õº¹"ÉX‚öËn¨ª„ÄŒ"R–€S ’ëžm>„ÃFŽ–‹f&Dj¶œÏ[ëR–/¿úæñé¹µöøé“dÒËå©®çRêÝýyß·Þ÷(1,4P„ã:Ô¶DLEjD&Žw°t[ÃÃÆ¿8´ &éð}-»[gñ&;ë¾`JÈˈP@ÍF)ÊÄê¾9A¤LYp)Ûå*ȈØTïÞýðýŸÞ¿ß·g+"€øå×ß~û«ïj7mû®ûuß/}¿žª"˜öÖÊz‡vÝŠapÔÞ……êR½h J]ÌA³ŸAa­®Áf+°mãw^q>N0ü§ãÿQUÄëY£¡#›w%êøœ‡g,Á›œq$Oj‰M³\Ž~š©Y"ÖÇíƒq„¥b ³”ºÜß½SSw@7Pí©žB4ˆ—#ý±” !‡Øþ‘œŠˆùèv¤Õ]¤bVXp© ¢/U¶ë3¸‚*@ "0—ó˜¤ ’¤É¤  aë½.µihþ¡¶þ´·çu]Ì@xe–m¿¬'ñÔÔ$f¡(Ücà†ÌH”fN"L.–[D®êÁñFBž޲EÒ©–‰o=»ÐC¤lÛxÀä_‹îGS,Ô}žóf-mdGg"ÂØo‘„.ëºï­œÖ¯¾ývë}Ûv@hû¾žÖw_|¹›5µïøÑͶËåí_-˲m×ËÓ3K1G.Ë›·_l—ˆÀ]U÷¾kïH €ÚwU5Umˆ¦v>2Å /*7éî4(Xˆ}ôOnûaèjÑ-K¢l ˜9—88g7y&¢DÄ"E¤„ä)‡«Ñ¾ïµÖ@£¿yóîùùÂ,)K6:ë x&‰~+Õãáû¾G{´µÏ8Ÿy€òÐ9aWgDzxóvÛ[¬ðJÇDDœÕøóÖ²ªZ)åÍ›7ÿðÏw¹w”·¡ßÞ-šAHÔµ-U¬÷Ù°w%,@òŸÿ³úññçËõÙ5e(bÝ,ËRkU37`báRˆ%5Ì´«“LŸÙÌê |Jœ™Â=–n"8S)@l$‚ú õ’áa²ÂRû¨ŠTÕ{swpå² R‘©å »(5ûêÛïÞ}óͯ~û›OŸ>}ýõ×,²Ô凾ÿ‹ÿèýøóûÓùîòôüå—o>]va^×uÛ··_|qÝ÷»‡·_û«Ë§ÇÞÛ¶mÛv©µ ñ²,½w£ǹ§ÞK žk‰ÏŤ™f=–ÚE6º‡8&6¹Îq¶e²Í™ðwæ°™u/Ëꇘ›èI‡Óé.úWôŸfc½7‰:½÷ž|³ÿ‚š‘ýäf#]fV3S#")jˆDôOÿé?]OëÇ/—K)1{#³Á_¢fËz*uùò‹¯žŸ/A wa1óëu£uR‘áθ,ËÛwïBŽ\¤þïþÑ?ü÷ÿþßw³RJ´éK]­›Y‹!X­56è¾ïæ:¡xˆ2f6œÂnߌ‹ïh4¯ç:iS¼^ÁôHúÍŒê莫ªÄ¡ý ËºÄ°7IE ð7ÏubK][k[Û£ØÛÞµ‡Vª›a0ã,tü,Ï]ÂT Œ®}äì—ËeFÿC®`“v0uб”º®+ ‰”ï~û›÷>\¯×à6÷¾O—×X¢sß%ŒÄCöâ&î‹sà9ão®jžÜ‚#ËôU"øç`V'±<o KYnm÷ÛÝÅ™ª›O+CÖÐT DÆ8 ÃgíÖ†0w ¹5I¥B&Só0p3׈æ­5#ˆ¡hœBE¤°âÃÛ·­µ€*¨ª¥]6ÓÜÔÕÌUãMGv¯MMmß7m›µÔ!ÐJªÊu9cpšˆ¯½L¨Öµñ)…¸ë4VM=Efë?þ|}¾¶­ƒm„ ávF޽û¾5WtÝõú¬û.,ŒbÝ»¶¥VÕNÈîf}_APëjÚl]JêÚšªˆ”(|JY»!«jA‘Ó ˆÌRkD,ÔÜd=©#•t6133F¢ÚiŽˆË² x×EÔqYëi]™ùãÇ÷DÈLæº2XﯛÊýÝ»woþçÿé¯/ϬïBÈ`ÛósADÁÓÃýÃùþr¹\¯Ûé|ÿô|-eùÿã¿ü·ÿÿ½^~VÛ*x/‚­÷fvÝ•Ë !!Sär½ÊºÈr:¹e,g$žÞîsçf†¡„lèq³"†CÎ !fŽê @N‚îÐzwÔ$&Î8Ž„^Ê*•Õ[øJ:¸”ÚÔÀ´,µu=?Ü#³ª.ëjªÑÛQÓ}ßÝ´ so{­Kôpcví!n#Ìû¾¯ëúôôô|¹DGUÃY"u8åx”«`þã?F¡Í̈±®Òµ©÷Zkk»« 38hïû¶mÛu]—}¿þíï¿ßö¶m{ïZë€îzº;²q’_¿8juV„™£"†(‚[ïOFðeYqë2TIŽƒÈ辶aHÄLn@DU4æ‚ÀRdz€”ÚšžÏ÷×ë míM„ÝwS%bu—R°éÖ‡¦½õ–€tBBk½-ë²ï{Àçîïï/—k3ž‚0"à_~ùåårC/¥š)Sí­ƒ#s´æÔÁTûRVwÿù§ŸžM5D8›Ý6½P2ñ“ °A×¢L¥3×¶!&ŸÓŒ¹Ä ñÞ-‚ÁŒ ’¹ 'ž=œ›ø«{ú†Ô¾g÷?$ÿ‡Ûm¶ÌÁ1M$9HeiˆÆ…«uc 5Å…jÚ벎ÚÎ…ðÝÃýZËÖŸ]wm;ªr ÁI(Ê/WÃA|‹rûéòåcïA¢7a)UCpdš©üÐ È]uw3L¸ ³£ôÞ™¥›ÕR§ÉĥƧNbë; ßÝßµ}Wí×í’©Œé4ç17\–z>ß…£‘¹¹Ç¡ô $df b«£íÊÑS´Y |]N{oEÄÁOËÉzëà)þeªD°ZÖL †ò]Ц‰k”ði~Ô{⤄šHßvW V1!"•¦þ拯êùî¾m—¾ÿÃõé1 ¦½u5¾^ —eyÿó[–jÚU»«¶ëõ‡ïÿ¶V.DûÞDdß›Ô ŸÏgSýóßýƒŸþ±Ix-%’)r˜Ø†èƒB pæˆlথa:Yˆ³Žf33×Ùh¯0¥Û%v^\CspW5vŽD즿þÕ¯îï¯ÛÞöÖ[w÷óz*¥\·+"FFoæ©”L‘ýþþþÛo¿}zzª5±ÛŒ"ámß§¬UÓŽpC^F2Êíõh_®—ói]×åÇ÷µ 51pD©Ì¢= £íž¦»HRjE")ü5ë-,$!…æáÆŠ¾caî1°Ìè†æDdn<\1YJè:ÐÁñ ãF`&^)rˆ‹ÐÎåt÷00®µ¨i)åîÁe€Z{f¾ÔªÝ˜R}g03nÖ‘ê[tÌEäþîn»n­÷RJh=»ÏvF·¸S9‡™Zk€>[Ïã—ÀUU»F¦9ñT0¶sæÈ‡”yqœ‰ùœÒ¯PçÁ šc̾ŒÁŠ&}ð¢œ:äõ8´0 á€“èzSÒ‡\¡æ`9k-=ès>;¸ß€¦£ìpDj­ÓÐÍ’ýà¡©ËIÕïù>‘ÉÌ{ofÎL£ßr)Ç2>Á@S 9.ÑÈ73 zž8z­K4jUuTù9ÇÇAì-•Ý­wÕ®""Eˆaoz¶>J©5eæZ‹vmmïÚÉÐL-×@)ãRÒ˜ˆG3ï]MˆEJª*#2 ?<¼m]벪{–é(/q÷´›°°,F¨c5‡¿ƒß,ŠÃ?|[S3Ì3¹m{Ðf€åë_ÿf9ÝÿüñÓ¯õ]oûõù±ySŽ6‘°†Û¯v«"…¹õíry^„­·Ÿ~üC%bN ƒ;pY¥.+—ÓýùîüÙŸ}úðž\Ûn]Ó‚ù,|tf¦¶ûì¼ ‹ö‘…ˆÊ0#å€R 'ß(ØE†óEc<ïFÃïWU/ÏO—ËeÛ ´ÆÝù|¹\Sv"†¥Dá1–ÎõzÝ÷~¹\#ÝY‹¸M{oñÎC¶–rì¢2sžñŠ"™ËßßÝ-˲·…cT#")PnàŽ¥T.¥.kHq…êlªÐµ38´ÞX¸Ti½…áúŒ,fæˆÎ,ч‰áe !V <@47ÌXÀó”Ý sOéó¨Ç[߃s5³ÙQ°€Û#©vUuë)d(Lìæërª$¥.ëR㔽µ8l`AUÝ,GÌDwww—Ë¥·~ZOf `“xÑÄxOS¥™ÕÚ²,0F²>Ô,Bˆ&`ûdz»Û-"ßúé³Õ6».sPt쯼 îcÖ:šþC5o@q4Ði7«‚daöêN!PuhïÜf ž¾(ÂÄI„añˆCœÜMMaˆ6Î2(Tû£É6ÕÀ=ÊÐ)Ä$‹ˆ¨kvµ°UŠÔc²éð¦+B{kˆÎw-ðŒjÁšrw‘ZJ1÷Ö[4‰Û¾wm 8‘‹ázRÙT·Ââî(\—%Z~‘ËGt’‡7ï.×¥´­‹0…ÑA)à@Õ¾Ö¥†äd¸xyƒ‰¨¤H)¸'fˆÐÑ„‡©£ˆX¨KÙ;íê—Ëv¾øâ‹w?ýð=‚?=~b@â*4d²¡k¿îD¸]¯„жíééÓZ¹è¾µý ½»¿Wƒû‡·½›9§¹sU5‘BU;Ÿï–ei{¨C/½w`êj’€‹ÚZÏéaz6ÿiæ…K€|Îç“;tm˲RbÙÍ—e€åtúú«o.—-ê†X?ˆý=w?ß=áe»¢ãÝÝ™‰÷}CÄ*%wÑÀºÌ¦Á±’˜o ‡\{îpwu–0žf*9¶!”h²Îfþ›~ ðSabBqG3€a³ÔJD‰åp<¯o¾ýöÛßüú7§º2£›=Üßïû¾í×™ûNüåž#)¢¿0kמMç¿ø—™…c€—RJw'ÆP¼Še6{ƒ‡³ÿ˜1 ¾øÎ-ÏÎÖkTÌìfŠXÕ·Sd®|$ ÍÑ÷1‘0ºêdñ½åa91ÁÁW LÂ`ƒ‡Ìí_#±Äá _ì>æ2²m‚‰^CgaI~¶îÑ<)B;3ÁÛ~Sè´{rÝqx%íqB7ý¸Sf‹JÀJYÊÉ]EÄT…¹uCb7—Z„eßxR3Eg‘…yù/ÿËÿêzÝ?}úþßüúÛ½µÑ¯tÑÁÌh8O†i^º9… {˜édùƒˆPJE R*Å׌‰Ý¡µÞ[…¯Öú*QïÚ´ s0’Àít:»ƒZ'©”xËÞ © êm×ÞÜ4¸£Â®0œédYÖëÞÔLÍHêóÓÓÇKYññÓÇóyE„¶mµ”HpÝ´÷`ð’ˆìû¶]/¦½/RÜ]˜ˆ¥í-&K©}ßú~ukŒÞ÷ëºqx!©”9õ}HV:*s 3cŽþU¦ó¡†ãaJ³Íé»”£ Wsƒ xâšAXÜ“‚¯¦ˆ¸]·²TU QYB¼\/„ĤØ,;3";@©Ë¶7$Þö}Y×Ö;2y: §Øä¤ eVû²V'"fÙöà="¨ÚõºI)f!’.˲v3áúððp¹\ÒO’˜nciß·ð€Ü·mß·»Ó“˜£Ã· ²J«,Â,Äéxt«u|¢›h¨x3! ðˆ>Ì8…‡ƒÕd$zÖCy ‹æ·RCŒïŒ nXdùòÝ—oÞ¼€}»„B!`Ž£î9>ÕhÉÚ(|öd¦®F]Ö‰>˜'ͬ³ÌùÙyt§¢¦Á) 4¡9cpq±˜EÞ&ŒXKÙÚž&³›©S6HÓ=¼ÃG 榦>ä]=í3“ÄHŽˆ3³Fyˆ¶!ËIRݹ.w1Qt0"Žè4NÇ´1€¨ ÜIþöû—Ç?/çúøñ=Ií]‘°Ö*Ù:誦¿ÄpÔ«‡Ü‘ºe§2 tÿæáþá·mÛ¶ HXµ…9™”º,•Xöm0" Íd"$2UDrdŠæ”#ÀÖ°íÏîEx]jY„ä@Dr>ŸË²z*e¢SYˆ“}ÓzÓ¾?z¼¿¿×Pì²NèÖšjï½9ÚÃÃ×ëõîî¬îmÛ¿ûõ¯ÿüÏÿáÏ?¾Gí ›¶Â²oЮ}ÝŠpo×Xä½·®Kþ™ÃÆY O––îéæ¹ÕXÄÞá©™(¤c“»¦<ƒ‡ZäÜB9ü̧H(E"s?NOOOæ®]‰É-É8 '¢0€Þ»®ëiß3­ëZJyzúRÅ¡p¸—0,ÆÑ Áµg$Ȉˆ¥VBÇÓé~]Ϧ1Dꦭ5So-¥¸¢*2ëˆØ{ïº#ÂÞÔÌЀ  ïÍÍj­iM§/áÕè9…0£¾`Uj‘*”¦ç"¢fèÀ$3 вÁ´ã Äö©j{ëWs%BfŠa,„Ïê»w_VY–º¾}÷nß¶?ÿüóO?¤G±ºJ)A2˜Ç!͆[ R®'+¼­™øýèð²ªE£,é™Ô»ƒf¥’œ†Ñ™ùG~pšÁwjK¿Ä™ÿ/ çì:ŽóY§ÚP* xìmr›‹söÖ_3žnO.%ú½­žzœ$¹Œ³y8Q²|¦bÌÐ:Ê…|$æÛE¤.gw‹,*©i«Jȳ±if†c´ æœÈŽ:æËÜÜRB/˜¡>rš‰1àb!ɰ!€ëzà­ï…¸õN,jÀ,-\Öa|¥?e¸µ}ö…ˆ>ІcÂ7&É6»9©óE$ÓMÔ7§VŽ 6úrFcu&¨Q7h¸°÷S)¦1t ûæÐéÕ,E=+@¦‹ÅEÈщÏ@@àDþò¬®Ë[@$” Úi7`¤®îfwçsïÝ\ód ˜úýíÓÇÛö„èDlÀŽàänæh@Ýœ¸’ˆ†þ¨zo{ƒ×d©» ¸àÉÔk©½5p_–Ò÷‰œk•º4³§ËU»²n¼B"03JIû~Ý™€Ø+/„´®'uëÚúÞ‘X˲`ÛûˆJXër¹n ¬ÈÈåáþ#9–e]‰èñÓ{íííÃ;.§m·¾·¨_Ÿª`Y I1\–å!„ÎM÷ó²\ž>¢;š©ê¾ëù|Ò¾kW!é ¥.M÷!C HáXmP ^T¥ 3º{©«šoÚlfOìÔzffìí¬$[&ï’)÷#(‚IQ €sök÷maªu]NÈâŽV½•ZúÞ ‘~þñ§BÕN§õáÍ›íÓ,¬Þ X‚»éÕ@ïîî/ÏÏaÝ €K¦޵œj]£+ Ö‘ÝÚ¾]·‹jïæ…ëi½÷ŽNܺ׳)˜©¶~½\>}üÈBîvÝ7Bvæbˆ,år¹¬§uo×®=èÞ¡ îV˜ÍýrÝZëÈdèA ÐÐ ÜÜši‡ÓéôÍ7ß,ËéùùR¤¼}óб¶NH¥¬×ëUÕZoPO+qQ÷¥Ôu=·½‹”ßþö·oÎ÷Û֮׋„2  ³ö.Â!†aÉΖÝß?,e)"?˜5Â~½>›ÛùþžY¾ÿ᪠‚æ¢ÉåˆÊ˜ D»mûuYDØÛ~º?ïm?F[wèˆÎŒû¾ø¶_c@ ÝB}.´Åy´+œ¤ð*ºœP7µîñ$¥’ i¨LGÆŠD$\] ‡Ãp¾+5Lëmˆ‰åLÆ#"Ž¡¨3;’:q*ƒÝÚýùEï†àÑaë­ƒYaA7gf 63»uDØ÷­p1U–‚€dæÚ¶¨ä<õè±éަ-øNîÀRº%Ô \bdT’Oî–¦ ‘}"2ŠpäÇên,u̺=ÈQq’ä—®F ¨÷îæÃɲÞ%Kˆ8iÕHT—%.ß¶mqlFõ†vVûé ChS» À˜KðnKΠ,L>™ xòljÄ@Y(zO€ØzQA"–âBœH£*Ùí#¤ÓRssXJb³¦}w0LªXÚ+׺‚‘ÀÍHÌà|ÿ æÈ,¥0‹”²_¯ÏÏO¦»0Òåz½^®,u»>/µTf$ì»Ãùþ­”Uû Õ®cèm""…[ÛO§³Ž†1ö}›L¸Ð=,"i®"ìêÆ!„€‹(üB©˜ˆ G^sÛvÑYϪ8fÛ˜…<qðȈœ©›—²ì{ u[—soݱÈRJ1µÈ±´‡¸ªY|ZBbaY 3[ —5:ò{ÛóÝo>|ø jû¾¿}û¶÷Vª¸;S!×`ŒRj‚§ee"À€W·ççg@뺳Pë:¤Íº£›©°\."|÷î"îûžÞ¡àáRë n%r@ey43bʸ–¶m{||r÷Ð=¿\.fJLÈìîÏ—gUuðÓé’…XÕ ð‹/¾üꫯ˜ùûï¿ï½K‘Rë€RXNÄíÁ[?*0ÁáFˆÔÕÚ¾¿ÿðaÛwpeæ"Òuº<]Ÿ/˲ˆHÛ[ ÞBÀô@`­¥´ÖN§“¹]®×WªAu°i†•ÒŽ³#OtHÇP{ê‡oNeüx*šåɈñÏ8Âà^òº,Ûví¦˜` ’u]Ý'éú–à@©_ÎuS‘ô6ù¼åõˆ9)%b²¥!â(¦jrký#Ng³¼˜|:áuYN§“#nÛÖö=zâ½w/a_5†7È© SÅlž3"»G‡0q¨Ì4‡OÑ{Ûn$/¸MÚ0 ü–®Ð9J-1¼™¿Æe¹Ëg äeÊs{]ÖISŽ~«Yï½Ë²…‰3Lxú]L…ñÀ[›I&*¯bv]Ì~…–Ÿ=SÐ<ÍqRîܽ”bPDŠ9HYT•DBᾇ)(¤R™'¤•™¨J)ŒûõÝ6DWÝ )|`K©ÊÇà¨ÄQ'Ç5ºxà*¥Ô¾_Ì@]uÛ7p,¥ÜŸïÞ½iû~½^¤Ê·¿úî|~دªÔº›õÖÕ¬ï ‘Pëm=­ûÞk]¿Tøf 6ëMwç"læW¡w ­1õ>ovà poÓÐ~Š!9¸[JY# ¥Õ\°bÀ !&Ïh΄¥Ôµ«žÖÓåú\‹ Iqpæqgß›ö¾oI â´rpµ8fAFF™SÜëõvÉÛe3³ÓéªUfªÖ{ïAÁ%") )çó]-…®ÏϽµÓzÚ·«»5këim}—Âî¦Ý–Z1ä8Àdz@òÞ†)9˜X¢<öX¶‰1; U¸^¯×ë%nK¯"Òz¿l×½mÆj:n—+`ï=|qúñǽ]‘@DÔzkÍ!\RmÈšQ%ÑÆ¤T1è½í­uíÄÔÛs°CzëÛ¶9z‰T=ùmðâà.ÝÝÕY(8·ˆÐz÷ȉ_®ÃÚŇV|'úË ›96^ óHð[{ M-³é¨‡f&\œR[b6UPˆèþáAÕÌ4LJCðPƬåUdŸ/tl1’”‚C¤l¨ÁL!L‰1¯§ub~©“ £JÎ ö!Ü÷ÖUÏçsš€l­M%µ‰®\–Ú{߯[Ì*$èu¹ºÅ‚¡V Œ>‘ Ä/ϼЮ9Î'Ƥ÷&£ÍšBZtDŒ€×-5ø‰ëz3¤ "÷ÖZï SïI–)«]5„¸€wUí},}ÈsÆSŠË H8Z!*HÙRÈ@R FëM©ÖÕ=ÐróÜ$¦žÒZBp‰¥2˜ï׫ #¡k넉 3›C ƒÊ²Êzÿ›ßþ.PÆ×ëvæÿîßÿ;ÒŽîÂÔûnjRŠHq°_ýú»mÛ÷ë^Ö3ÕJ¥®ë݇õòI[Grë-H§¥TLnš5ìÝÖuaám»ž×eÞHΛþö‹¯X¤›q4â Í,¸pAÚš÷;º‰K©xAL„RŒc€0|j8Ïð`§qÀh°Nˆò—ùŸ™ù¶5x÷îmWe¤Ö›"n­{ké½!‘j7pâ05ŒDû ¹D²÷@dBè¶GGnÛ¶pzRÕd«¥n† HÑ®Þ÷7÷§õtݶççg$°ë~ýÿ·õ§M–$Wš&v6U5»¾Dd€P(Lµtqªª{–š‘þ ¿LÿÎoí/Ã&)B!Eš3ÓÕœU‰.dÆâî÷š©ž…Žš¹'†)(H$3"ü^3Õ³¼ïó"åbÀÎWºA‚pøê«¯Tõùù¹°0£›„…[æCgÌELTi*Ž•ušG×7ïXœú¼#&M³ôADseæV.,—Ëzïû¾oÛ¶,Õ’¹Ø·ü1Ì…8M÷Q¯O¬lR¥ÎŸÃÝR¡3xŒ1Rä#Ì\„å‡gRŠvE¤1:i6W•ÏknŽíÝÝ N(SŽ΃û˜zDD MjJøëYpø6QÕrÚ¹,‹Ú`Nb3œ 39íÉ_? ¤'e,ùòç'óv†žÏõÙLµ0Îuéñe½½ ÎIúÉçüä=D„H€°°“á™Ù`òááaž¹ 4Í “ÙTäf>E@óÃG"·ÁÎHœû ÈsOý`D¤HY’iù ¿ˆç$OýÏt½CfUÓ! 0ðµ#†›™2•v $Q,TŠŒÝ<ùäe{êÆ ^›gË?nH3äRk[–0˜•>Ì(¥|<…yµ Kžì–X`),¥ ’Õw³ü"Ó?6‡ÉS’xŒ´Ž‘ݵw³a6Qm3MÎçÕ‚j»Üß?‚Ô@0µwïÜõË—§>z!ˆ>¶0…8ˆ•HµÖï>}²¡jŽÌêñîÝ×ëº>?}ÛS‚"¢T9l=YÈŒü‰ÓzáÛö‰ÀžÅ5¤€—.€³ì2µ‹Ãt¾'t)u¥@8L½6æŠ3Ïõ`,!¤€Ì5%bö@@.,Ï/ÛÞǾïï·íVŠ µË²‡Vj-53K“9 ´£?Ì¡x2 ,XXDTGªîþøø.ßê§§/µ–u]Í,¦T –’‡¥Öõ¯þÕü“øÇdf)FD¤;lÛ•aúû2¼mÛ·RÄç¸cjRù/ÎKÉB%óqº‘ÞNêϹÁ{Õ81 ÀLïËâÝÃð@´âÔ æÓÈD4L‰)#vÃ-×ÑîŽo€_ow³©ÍìQ>ƶmqè>ßL$§üÂÁÏŠž^½ŠS¨5i¬FD©ÊA\ÖÕû¾ŸþêDUïûžf9U]ZËOÏâ¼Û –âÓLž €Yh§ÙÍðu­íó š½²¼¢_~0Šy{Éy–u”.Ï¢ÐÇ8ÅšLÒŽeö ³Õrª­–Z.—K‰N·ÀÛ=N¬ q¾;Ó‚5±s˜>å8®ÓÃ{ƒ­.ˆG\Fz‘Ì ˆfÂ03Q"×Ñ3N!"»Šü•–Z'=1ïÃãÒ¶~sKyûÔ±Ô–]8“X¸) I«ëÅAˆåþ²~þôil#ĶíëZTóL%–Rª´z½]óA$©ЖÒo·ëÓg°}^4éKV53»Ü­½ïfÊBEG}‹0{®s‰)…ÒAf‘CËÓ<è~&‹†MmÔDvLoœnë@D`$;ºÇ žîÑV‘ÈÓ€C4µº"L¥”²\Ö„I]ÖKïûvÛ×å.me)¯˜àº,Œo¼ˆìo:èZZäjDØÝ¤!Nyæ~dÉÖ{?جù òRkk-Ümèý»ÇÛ¶ûí·f¶]m "±Äñ<”R8ÙD´ß6U•’W•RÆžåPêp‚Õ0 Œ˜\‡˜#­Z‹©ŸÏyV»ªczí\b>¹æeÞ—Š3½k+·ýªª1…üyÏÝ£°H)ùVã‘M“Õwf­¡ÄPˆÃ4TÃcY–|“ îná4’rÐÊÜ9ŠkeIÞ§™Êù¬Z"Îp2æ†aÎâcš¨¹0¦X¾är†øyß™p½¬yC¹K)1ááI-Úûè~Æ+cSû¡„ç¼$Žw"‚…ÝAûXZ£s 02Ñ"Uû¨¥‚G-ÅKÌ• <SÍ‚"\î—‡¿ùë¿yúüÌÄáµU5…76‚CÀ—¥C0‹H®D<¼ÿÿqj´5YÙGõHÈG™ÉD´,K†LõÞ³¨t‹Sâ’„†¼ÃpŒ‘"ÚsÌ$šQD'x#wj€Ä’Ϫé8æàîvw癈Óå~2 ŽhìX–s?+¤óÏÈ¥Tf1ó\?€ÔRJQµ²ß®7~||Ìê>"ÆÞSD?éUiðA' ÂHËwÆÏ!f¸db(Á:‡åóÍ|éÜ!ÏÃ}Žn’Ÿ•Lj€Ÿ}óÍTx«2µ%á ³˜:j!q „nšG@·ÀIŽ_n>Ï)š„"µÖ „ñcö]J˜6ª˜+$@¢®>Ã1ÒdÌÜjk­©n™Ñn:v;‚'ÔÀM‡v‘f¥¶ÖÚýý}舤ªÆ„ôD„›B íàR«»ë°€@ R 1×¶ÜQiµ,ÿâ_þW"ò»ßüæîÒn×k©<º™@63Ò€ˆ)IX˜/ëe]/Ÿ?~6Öûvý Ú‘“%b̘C\À{ß9aÅ¥ª¥¾†µ@òfbê±Áï£s:­fRG øù"!ÍEôœâ±Æñé"¡´äFë+ ¤°™ÎvÍ=•3ˆÅÝ[kf¦á—uݶ-«ÔZ*Q¹]· ÂH¸õîLÈÈóvÏ;™ J­û¶Ï²—I¤ í‚´ï»H)¥ü⿈ð¡Ý̈9 ˜eikªá2žär¹€mÛ²ü€ÞwîD²TT4Í :Y†Ç†ú'_ýôü¿üÿöú¿>îïîºõÛv%þA¦RO0» *¥Yˆä-Ë趯Gœ\¦i‚¹-Äy^¡Ä8†ÖZÒ•}1ÇÖEê܈ráÂ2ú–ÄÉÔþûÛß:ÇMlfjZDj­¹€nÛ€ÃÆ—ççR—¡^i­¼¶wïÞ?=½<<><½B`:½Óµ.€Á "Œæ=C¨zé”Ô¶”Z<|»m ªpà³ð"^„ Is„0@ÌbB˜$-§,ìçlð€ ü`8ƒˆ”ScpSb¢p'ŒpCÆ Ô A)KŽšœ„Z»S wÈæ&ÜÂ-DêÛaÌ8´biëPÈXpœ337#" @b†ˆp¦ðQJqS÷A5þA‚›T¨Èp7Ï$?we¦R!¥©)߉”n1 ðÝý×Â%bn›éàhD©åØ‘B™jÈ(¥1˼<ÜÕ­›÷>€¥ ‚HŽŸfÎý[_b.”<@ ÕZ‘(1Ó¹Ê CùÌB2·ƒ™Aéûp5œó‰Tx0 ‚€If~-Ͻy1ˆ’´„å<üåé³`:ÒÍ¥´‡w_½ý! µq±‰ì·ëè[-l¦Â|Ê­²_šÄ’ˆ>FNÙ² 0Ïy ¿ñiY]$ˆ¤COFʱ§À,~rZz"'#[c¢ÖV"&œ&&÷ ’¡/TŠ´“¤î¢!sÄáH$R˜sŽlµ”|™¿þúëRëÓËÓ¯ÿÙ¯ú¶‡9"˜;!yñ²®ß|øp½^U- áç——Ú*õÛŽˆË²D®S#bY–R[º¥Zk///ˆP[Cœ@%f)¥ S¯µ<>>Þ¶=÷„Ù–Ý«ù¹ëswsM„r–ÎÙñd¦UŸÿH\ñª9sɃ“ˆ9刃Mˆ¹á<˜‹EQþ‹cŒ"e*•Óí~:ÝçÿMü‘»áøJ$ÉÍ“`EîÞ÷½–RDö½W–¥6U%ä¡¶Ü­s›Ê|ik‡Àô¦Ž€@sÓpžþO>‡éļ.wªv¹¬÷wÿ]|üô½]¯/¥¼R§€ý$LšWf^×5‡rqëÍôD£¸›d<î˜Vþ)˜îÜCç÷ǺøÌlc!Â"‰!] Iº~3JzÌàá y;³ÎAPŠës¢›œÑP#>AÔZafSã(·éõ)c¹p$‚C¹Üß=¼¼Ü˜‰Y"\»šfh5æ/"Îq®7pÊ,ÿ|éú˜Êļݦß3–¥—.Îg)oÙƒMÄëÝ×oÿ<:I/HªZJM(æâ9Ѱ˜9ë%p™ÅÙŒðë7*L8TÇÞm¨™ºf¤÷±!1wó—ìy6ÁL @*R×e Ëe"¤ê¹><~ÊÜÎ<³ÕýÅ/~±ÞÝÕ}Û“dàc‘uiO//www­¶}ßo·ÛýãB¼¼¼bZ2}=<€¯dÇ 48Uïœ/L“›§Àf®ûÎËõX¦¡!µzQŽ|(R3;!ɹ#’z€ÏðT©F0qºÄs¥@3!Ἠ_íB§¤Œˆ I¶ê D•Ë>Ìͳ\!&íc߯²´}ïÄÄ"®‘x} Ü÷­´FŒ}Œ\5$"”`âZøž£¼ëíZ¤|óÍÏþ›ÿú¿ýôéÓïÿmމj-G‘™Î‘3w˜¸º9cLy E`ª.ælrÚà@"E¸z$õ³O:Z“ßwÆÌ›S~ÂK&h\u†¾š)¾Ñƒ¼¹¬ÏÊýmØÞ|¿N£l’‘5:zf–òªI™%ÕÚZ«8¡i–>SBt:vS#$0õ1ÔÔ(S_Ž& ÐpÊ¥æ"Ç-Is ™{g$dz‹˜«‘¬rpj¦ó £“ÊþJd©÷s *¥yåZ²gÁAˆ<úÞ[mèéG:>wBä™+– "ˆpSwÚ7~J3ßJ8+Ëj-¥HkUÇPa>ùnÁMæÜÞ=Åì­.ëzyÙv.%cÎ7H¤ÖËe}~zÚ·mï7B^×Å#GÞÉÄám{ÛõúòTn//IÇÌPàZÊrÛF–‡"³4wD¹¨yz9*s¸ß_îÜÜâÜ¿œ¼ˆ”­·{8NU,¢ª&&"rtÇ¢üö`M°ˆ|õõW·Ûmè˜ñ¤fjVJÙnÛ¾ô\.—Ñ»ª!D[dvµ‘T™Ú–ûËÃДëá¤ÀÁôAðýÝÃ\ʸå€Þ¸Éç/O_}ý!·”wwwÿïÿ> “õr_ê²\Väé~'fA)UÜ}ÛöŸÿügßúß}÷=Š4"Jè.üò—¿Üûxyy飛ڶm:ú².ÏÏO@¤ª™}¡ªµ–ÛvÛGáäï»Ì.ij…Ÿ›ˆãTçÐŽ™V˜[ÓTÑ€0…'êc–ÿ©) ©×¢ˆ i¼˜„nÓ‘{£©Œ0Éò%§ç)-¥˜Fêé3/,ç¾ n¹C³äÉG)¯*x¤°‡‰™J]/w¹*¼»t(\Ö»£«"Œ¡Sà@àà­5sWë@8¿nÆð°ì¨žCg$Ü÷ñŸ~û»¿ÿû¿ï}wû»ûËÝ’Ï-Δ’ ƒ¯2Å AG!¹Ø<žÿ©àNxÉaÝu̹ÍÝá¼5N¼pÞ—éµx–’«™õÞÇfºï»ž·Nþ[gÇ{(È~ ñËÿ7GwOy¥w9„çh =R‚Kk­ÖüÝõL0v³1ö1”£ÓUÙy=Hæ)†OZ–䦪C!LÇ â£c¥‘:±Ð!šLìÛÙ1äÃvhRpREbþ¾áŽÌåîø@áÐÉç·fNç§™WjÎÓ SIH“‚GT¥´Z€âùt$™eWtrù¤Û§ÔY3% "0œ1` ÀüEth¾r)ˆ˜sÀ”pbJ0œ‚È9* ‡À“(ÛPDÐÞ…¥°ì{סDøøþë/ÏÏ¥Öm»¶Òj)àADéë&ÆmßòO’êÌãÖÝ#Òî–ÛKD¨u©¥~÷ý÷¹¯2ë,H„·ÛMuÏ$ ÊÔã?<<æk}ŠFNSRÌË#R«–aIO~›çÄŒYJ"2µ9k~ÅXfžZî3ôŸåÛ1ßô@sš1+à³Áúárx*rpî-‰pŒ1Æ $>¢3Ì4`¢ÆÓ‹4Ç 3*òÀÍcjMÆP™ÓìTý¥H‰2—ÜhB•§§O LÁ%ÓëÍtŽƒò@8gDGÁ‹Dä6?d.wyþÇCŠAÈRÄ-ˆ8e4iÃ=ZÊy²D@¤D0¥]éAw”‡¿;F$ñ:*€X–K­ÝÂ\û`DºÜÝõÛ²!Bç9frB‚´éÃìŸ"çAæT¤”àfŠH¥–R*"ÙöR…[ëÛ6ú‚᎘³#Ä"ºÜ­º÷ÚŠª1 1·ºT@:ÆÈaˆ .å›_ýóÿÓÿùÿøÛÿø^¾|è­‰é@bsˆ È,Áãa"ª­~ýáÃõv3ó} @,µÂ‘“ÍÓ9/$$S nzßãšÙª<_¡Ô9äN¬€×Û•™ŸžŸ³ ãRÈ,R[æž™€"å ‘Ð‘k@LéÖƒr¤ž2óýý=2ßÝÝÿì§?ÿòå "f1¼o±„ƒšg,Wm-ͨŒä6"âz½²ÐçOŸêÒ¾<}Ù÷[OR~žNNÐ1ÆÐ4ŒŒÞ|˜ö£A!¤1çw±÷ÝÍ&q"KGH³í¹PKµ/L¤0â”v¹¥‘*£ùìFd­â•¬Àf†Çûs¨Œ]4O;/’Þ;—ir™Ç(€©Â;Lu&Îu!ŠpÀý- ‘ñà± 1#‡[óûwïGïî^jEÆÇ÷?þõ¯~õí·¿/"K«­¶¾íK[rþ>´÷¾ƒ§8DuÄ¡?öó·«`*Éiê½KA¿^¯{RÌÇé:€›‡ƒˆüä'߸{ïšC¡„^ß ®uIiJúþÝÍÃj­‡;š’Ÿ/R˜)N×£ H6OVôy÷½1*ÿ`s¨…çæ2ÌbR&'Éfý¤G^vNÿ5Ü0ñ˯^³p'älygÎ-"Q¦\QŒ1Žò7Kf‡ì$=·AœÓ‹œÖš)½¶;I(”2¯žrE@È”ìƒÆ¡ÍyDVøsèÍ,Š(Äsà#"3>1j­ûPÚwsóÌ`˜ñY zºÈÂÝ´Rp.. õ±W—Y²†Ý¶î½xx˜nùô—D-GRfFD’ÿABï{„q8 ô¾·"cìŸ>·V1Û%ˆC»F›nîºÔ–©i:ÒCˆˆ¥UBÚ÷™OD¥4¦ `M¨ßžÂ·Záz}2@–‰F?3Ï`Fr„ë¾ý÷¿ï½·Ö.¥Xø>z›%Ã{ˆèÃÃâ¼¥sBåª>×tz+Ìg€}aFŒRJï'kÃ<‘¥–¥T4S€#k G"Ab&\ZCαN2ó°›mÛí÷ˆ˜GðýýýÝÝ]ï:Æ`)Æ,uY{ï"Ln¨øòòà…ʇþéûj­ªÂ¾ïcŒœrœnºRJï[ïÊÌm]®¶®µÖz½^Õ´”r¹¿ûòåsÊ qÒBŒg³p¬æÒG÷f0ãSN)NK¢†™‘G•ªjç5§1ÿûØå<¸'Þ‹ÞáðUlN)Ä6@?"ó¿‘‚ EÝ!€!c˜R»_<-"(€µ”Ò÷Ý̶Ñ1ÌÕ±­ËOþ'øÿú.mqWJ­”RÚ¾ßú¾S ˜)ޱwSdÊç ªO°]¡1zÄóÃý;æ d³4:œŸÉù7"ä>]`i>pOÇ™£çPëXs­‚L#GÞî.R""ÿ—ÜÜöÞ54e|‘£›·¥·„÷SžszS•ÿ Tÿã…Š‚××¼ÛÐ#äÜššÞ76£‰C0w<¦—‡- €J ;áh¥Ôz´Š&ÁlŒ0"ƒ³  T˜)ÈQñY, nÈ qlñˆç03Ó!ŽÏ‡0Ô`¶DáÎ(µT ð³ç#˜T³Ü\K)ww÷·m¯µDkË”fª9¯ç9$ ƒCnk«ÄÄx dÎÉf­ š©MÃa–™icô ˆ¬^…ŧzŠÊ‰Q‰Ãû¶iÉLa¤0Û¯{ïÏL`£çõª}degnuYö¾¯ËšÇîÃããzYÇmßG/¥¤+J­áàa̳b.àRê—/Oÿïÿûÿõùûß3 ×›,Œ .AÀ€S¢žwU-­¢'>“ÿˆž1Û.1UD,%•¼Éß G’}ßÕ”0€­5Ë$¬é‚±\Õ"¢È@jênª:L=!× ÉŽG*¥¶z©µ ð|y²¾† ÷ïÞ_Ÿ¯ëÝjfwww½÷1úããûÑ ‘ôpi^_žkm‘ÍxVµ{¿³ÇÜŸ©:)›É¸ S}¸0÷ÞûzYK­ÏÏÏnVk–­ïˆ˜A("r¾—x0ræèn3Ð2Æø•ÕžjRçÄÀ "Zk917U:¸+S®ÿ†ò‘U¦•0ÂÞNÉóv~;ᙇÑ „™‰ÁÉÜæ13ÎöøW“1Y„DËÒÞ?¾{úòe:ÎDnÛFŸ?^ÿ×ÿõ©µF¶Èˆèjïßß®/[ß–µe"‚ˆì½«›»wÕ¨­dⱪö¾·º¬ëHQUó~½¾H¡tPªªê,lsÈIÄÉZIGzDô>DÄLO¯&y¿Y%äQ>̼®KïÃ-`Y.D¸ïû=›uŸ9Vgèö4Ò%„#?ùÈß .Žá>p…ó’íàçè ™I„ŽLÙtxæ¸RÄŒE–ÒX/Ëmß™ÕAJ­­ UÀðpà4F̹'¬ëÅÌ™ØÍ+³äð4œ…±µ¦6!\‰–umÿì×úݧïP‡Ý]îFµšÆ]¨u5 7ðówAf$4DÇx¹>»›¹ßßß_¯ÛÃÃã¶í¶gi¥‚oÛ ƒéNDµd2· a.áxÛ^ˆ˜@ÝK«û¶•RîïŸJáZEÇ`âív–ZÛècØô4õi7Ö¨ðôç1 s˜ëðE DzB„'f˜K1u (IÆA€p* nî–^SOZÈHˆËÔØå=€T˜½ïK©©,aÎÀÄ Ì0“΂șÝ.LÂÄÀ‚R¤¦>`¤Ç5ƒbB1̽qe)› #Fcâ/_>2€`´µ=_¯ëãýó¶+^·ýF)ý4W×Ñ–òåó—áNEö½c¤ I< ©µfzå\³ÕRïîîµ÷1zþñr²ÕÇ6ÆV 'üöÍAŠÁ$K«)¼1Us­µD2 '€Œò28±‡t-÷ˆˆlæfžÖQ÷èûæ“~zÎÜñâ 8É™´ˆ˜NÙ~8 P‘JÄe¯©^3Š #éªÌ%‘î8u!’®ÔS éîûv+uɘÙÃqŠH¼¬«†¾Q©ì>Ü•ˆ˜ 9õn9•›ÕÈÜ PÌ«=bÖ¿ªn—»Ç¡Áàè®ÒjºàêÒtìL £‹ˆŸ0dT2akuWµðTò²Ô{:rOÞV‡ä–ñàfµ•Êeœ9òYk¢û‹fÅ1u ç_o‹µ8–#ùûÛëÈZïXBzLòœï£`Ê €‘à ^ôˆ¾í¹F ¢1ƾoß÷‡¤TŠ!"”äšžWzâ«gZBß#$µ«Âù˜¹H%7O ^oÏàæ¡1e¼Ó⟠è?ZÝdeZD,â׿þõ—çgBY.ë¶õº®}Û2Í92g;?9V„ôÞKÌæPJy~~N‡´ˆ„[ïH¸Hæ3·Üöðchw³´A…¥Ì–J«(Üû°ˆÖîŠÔÑGF‚\¢sžíÌâ„RŠš½{÷î׿þõoûŸR ÈRÔG„•ZJÊ1b-EÍÍ-ƒÐLÇP5kM±ˆ\o·u]¬÷Ûmk¥¶¥!â7ß|óøðîË—/YòdŸ.…×u½mW óeiª6Sb! \Žé&f”Ä”‡Ïyrd(Ñ9ÖŒˆ¬Îä9›ù®“Âgf”ë²ciFàQ˜—" ái#ÀãE£IÓA‹,K+"­VSe’|VGïæž"©…[¹A¤4L¸{†Ûƒºu½¬ ÔZn/W‘¹J! Z*¸‡9`x`JÚ 0†+‹¸@\–õxÿæy ˜>†jf®~€mﻪæeœ¾ŠIµ•ÉöšMätõÏ f©) ‹Ús¨ÞüËãA#ÈBÌœˆr00ÆHÀA%‹Œ:ͦæõˆÌÐ13›Ó7™F48½5½ˆ€H LªJ¦užt “€°ÔWSUNiÞDþ¾tç¸?•AÇIýº„Dôà ‡m ÜÕÕ‘RJ®Àœ¼ôÈ\"" 5=ánS9—óù,?ož9“x# À_|¹{:Æ"R—6ºªZ­uß»ˆ ‹¤d.±ìL‰´Df!bH‰‡P!¤TsðåáCž( º<§‡<ï„™gøêËÀ"É‹r3‘’aÂRÌž'T®ôìÀ`ž?g®ùøôßÞ™LŒos‡ç4—œùÞˆ„|èJRoLTkB–‡›×V¤ˆkÆDà”C!@~D¸÷žÍ ±ˆš3 @šÈ8H‡#€HË–íáþ>"ršÄŒç*#&â ˆ=Þ~.Df.òýwŸ.÷w"Õ ji9k.¥Dö¤Œè®‰[…HÌÐl‚"rªD·í¶´åv»ãÝåòòò2#¡Sß3iš^J½¬?„–}tvµZ›{¤÷·›2×R[áfÃJ)óeA!D©ë:Tîï^®/EćzؾïµVcAä9–ÅôL ”À6†ö}칃}||,HÆ0_o·¤õb&"]Ö•ˆ¶mûúë¯[kôáÃÂu¨šibÓ3°R©f™¸](›&‚C®‡Gž'% ½N÷ü„˜ã1©]e¿Î¼}Êထâ0V–Æåñᾑa¸g"V)E˜ÓYMDkkfæjÌmV6¨#§®‡é,«QÀa“€†ACx¿\À­–—õrÛö"¢îˆQ¸0†ç3Zð @ÆHƒk ¨û¾ïçÎpÖ¼9Öp[Û’íã¾ïû¾II4ò,ðͼ”z¹\ÖåÎ݇öZkN¥ÌÝ#%¼q02{ï§læíû~¬À'Í ‘k¢‘‘BÆdKÏS˜ˆ85pÒÅóï[k}Œ©|J W†U†Ÿ¹f‡š&;v°ŒgÊs€Î)`áVײ´ô柚™KÍ]’‚›©E¸¹eƧë€8þ¯²·sùÜ:´˜û˜>,×,ÔêÚÚŠ‡u<Â*â`ùM@•rö^NCæYG"q»ÿ*Yfæa©„ ÷ƒ´pÈ´Ïs*k[DTWJT’yÏ0”˜˜7Kö·Åì9~:3Žòm Wvaá¡)ÅÆ#<‘eš<0–eMrb`èÞ™¹Öfj†HTëbahæ"EjIE9C¤Ê3›¢ôÂInºÖec•…g– ๦Ǔ¶xN–Žöh*®Ì­ÖV[5s–r½^™™K‘”î e€EX–œ ‡ê#íÑ}ï"òçög/×çeY^žžK)ëºÂ×Ln>HEøzÛ¦$‰‘gÕÃûÇûûwì]#°Õ–åOB:ZId½\ÆØ÷> €Z©æ QZQ·SøLÇêòºmóÙ‡ð¡{šÑµŸþä›oÿûõ²><<Œ1Ì}YÖÛÖ/ww{ïLüôôœXöÿæ_þWÿßÿí?b2õp©’dÊÜN‰;ÌvÉV\–åßÿ÷ë­µ¦ªûmKZ@~¸TKËX¢”ä­S+¥º{k­.5th ×T©²@x­!ãÖ€X.—ûļܯ«»Ý®?ýÙ7¸ë.Ì}(-ëJÌ}t[Ö…„C­±› Ä™#ãêO×—‡‡‡¡úË_þòÓ§/î!¥~õþÃí¶­—ååùå›o¾c0à¿ÿ÷ÿ>1èÛÞ/—5Zk: ‘ªHe"DFdBˆÐ‘âTÄ1É'm¾0î“_‰y„É\Œð}Œ›ö®ÃÌ…À§ãX8æ"k»ub©­]·1K‘ûû{æÒÇž¯Ø))Éš±ÖJHsf fäPD˜%ç^[µ” "å˜Ôœä™NSت³rä"Ĭff6&Ú°¼v®Š1ûaCMýHÆ„ f^–õr¹ â¶íoÝ.燖ÏéÇ ;Lv71Б#JDÄs´r”37C„cŒÑê‚©½Ñ“—‚˜›ãðšgÔ<¿ÎÓóœJÿÑGmªˆ‘çàÔÀÌŠ’Ó©—Yë2‘Û0ª 1©×iCCD?2MNK€³rÇÃ¥õ¦l=KicŒjm)R¹ÔÖîñ‹_~üôQÝ‹"Nþ¹!šŽô±Ð[£ÓÜd°´û,EfOL˜“ùüoUÄsX6m¯“ÁœL2ó¯Óš‘ åtÑžS°,+€I„¦QmRmÀèíŸrê×€¸ G4 D P3@R·®µ,ˆ\*™»š!Ñårÿð®M;4!—">íZdnîÁ¥@ K¹F‘âó#ˆèûžx£V‹™ÏrÞèkqZcîãéPw¦}J­û¾`fyß].àÚ#<À 0"qèS›jßt` g劽wƒ‰Ìl]*`1±Im““ç•:@@Vµ}ßÂÆe½ì½3ÉÐQ„U÷„™@¸¹¹*禎5"Â"2Lû¾‹ˆ›1‘ˆ¸)”R=€ˆ×õ>ï˜Þ;!õnEäÇ?úp½^ó½’"‘*Wb)Í<8Óg܄͎Îiîïß}ÿý÷k[„ùúòŒj*­~ó³Ÿ~úô”ïÏ£ÎL1úî¦}¿…i€§c{¶Ïa—Ë]@ 5D^/÷îQ¤ ÏáÕv»=>¾{~ú‚‡ Õ, zïyz» g6%d9–{à„â" 0óá瞌'A:=PyØA…¤Œ¨8þi'¢‰LûœŸ 2Q»l:ÎINË}—½.óõ½,5ª,’q†û¾›™çÄ k2“ÕÒa•áJLÌD·ÞE8<Üuß6@ÜFÀˆ¤h¨›iD±©`0 ¤åÍ=,4Òñ;é¤H-â¦"Òê$É”ZÌ-÷î1†)ª~»m_¾|VÕR“œo>äWœý99ËùÏ}`ÆQÀÏDrðM=¶ ²È+ƒ–r‘›§Ÿ±<ÇüV5“žõbä‘ ç8á•ÌŽá˜ó×"RO9|èF„!’R'ÄZ$/¿®µ­x¨·Ñ-ß™æ'¦ñ¬kñö{3Çz¹²y"’¨‘,w¿úõŸë¾ÝöÍmìÛ•)!5¨#uñ4G“°‘¬éƒŠ Á"‹0!ØÝÂbx ÷°Lûs7#¦Àô`¡aQ«•"÷¢@˜“GˆP¶x¹´M’Ì $@v‡ ˜Ø{iˆ™Ÿ‹@L`€¤û^ÚŽy¯Š#¢TwubVƒ÷_}Ø5<´µVëbEj~ߪÊ¥TNß_m«›¡ HÌm]îß}…R†Q,ÿå¿ø»½kºŽTˆTd”Rêpw@sî*ŒÈ¬c ##™)0–R-¼’ØÐZŠG&êÒ1hªI®ØÎâÄ-¨-L6\N³’Èû÷ïÆ€&B:jSuƒÂ2·‚ÌáæDRZ )íoþÅ¿üýþ'µaÛ~­µòËËKN±³˜†¥]–Ú\Ñ€Šusä®ððøµY±¹Ý¶—üö?AÄÓËÓ¶¿F©BŒ}Û}ëæÝ­ Óv½V){ßYh˜³ð¶oµÕ­ïHÐJé}10Ñí¶·²–ýø'_¾|‰pÕ]©ÔÚ†iªÀ°ñ§çÏ‘âT" A¾ï8 –ëíÊ"æJ„è¡Ì æîÞÚjêÄXK$ *Ì2oM€ pÊÄ<ˆLò»õBD6öZK†%ŠH­e;0u·÷ïß `ÃÃF¿µZUõÒ.cX"TvU è:mzy01Q¸)˜™+º#‚ 7)qøv,…ˆ)Cµ2Û:— {߉ÜDøåå¥Ö ˆTHlèÏ~üÍ÷×§¶,E„‘£EÀû»‡¾m¦*Ì6F@AÆ ðøÓŸÿt\ZÛn×½oRëб.‹iG’'mŒÍ †+–ZÒ\˜4Ê´!a[Z@ì½g!LÄ3ׇΔ—ÚtX‚ÌàH¦L+Óq1ÌÁã$º„Š›U’¦RjnŒRhä¥6ð@âºwe/5% &Âû؉IJ¹ÝúÝÝã¶ïINËs!¦nᙢN¨ªÄhj³¦¬wUª¸'-ÃVKzÉ™™"g×ÎtpC0ËéBDAxÿî~ Ýû¾¬Ëèûµß\Uûí²”µ±ÛØ{aS ÷˜±w|ä zâl˜Ë%•©9€0ÏhQJ"[xXNB¨Hɵ’ í½«Yî¹HïÊÙý"‚»QL !ÇÔ«æmŽ ”z¶×áûìã܉¨­«e)fDlæËÒ\ê²”ZûP)5¯i½ɥЙ•R ³¦8gîÜ<„ÃÍ}æ— ¦ƒEÕºúóó¸ á¶o­.€è€DYb €©¥?9ð e–ûÇÇZkï*'8)r”væùFb³'–”Ø÷±ƒ{Žób:K"\5yžŸL ‰Ÿ£üœ6óº^¶½ÿþ?ÿþz}écƒHu™A€ê ¨;þâ®`êH\kËÆI„<»“wïÞÙ$üEï»jÿ³?ûõíåJ£¡ã«¯¾º]¯“ü(Ì©ÉÆºTJ ëåî¢jÃì²®_>v˜wsc–ß}'LáFÌj#ú>¤°´ö³Ÿü8‰Í:Fk )c¹îÖ‹©…›I)¹ãÍê;ÇŒs2‹î­ HÙbÎ7ßÌàðø;·¹ tËœ^$fd ("fjæáCußwíÃÉ Vq‡pÿó¿øËï?}€¡{[›Y69Æ 8È(sEoª­®EÄÜF!æJé·ªDÂÄ4à ùv0s¾`Y¯¥¶2k,s:6=A8y„ÀPÕ ËúWÍÁ½R 3fé}°ð0C&5{“¯0[+šõ V©BBD qKÕÊùç9ñùvŸÂŠ?S¤c¬Ô–I–©É87ÉF¾œz¶ó×®,…P<"#¦ó>ÀX¤ä¶v]×ÔÑ'*Â!ÈZ]X YZ[—eUíèɉWY‡™1c’fÊJ)5y¥îø !#Òô~ãÑ.îÖã8ÒÙ뤭˜¥§†Á̤ˆv}ÛöÍtsàÃÜ4õöù㥉oªE!27”Žß‚ÈÌ2p9#¦"9¨“|cÞ‘ÂÄtÿðÐ{Gbdä"Œc^–UU[[ÇV˜Ã†³™†y“=½¼b]Úz¹PÚÅÀqBsÃÁ-ÁXŸžž áöò…~þóŸm·­!¥F y¸Hf„.°Ùˆ0œ G¦p:äP˜ÏEp¨ð:žŸ\Zâ"Lˆ‘ÔÙÌÕ¬D”~Ôsá~ZòòÜ÷£W=2(HÍÌ´´ZkY—6úVª¤Æ?Ó9‰¨ÖÆyŸ~ô"RØ!,0Z-ÿÿþþþ?üýËËKîî®×§ËeýËþ矿ÿî~÷[se&7û“?ù“<˜ œÁ½Õ¶o[-îvÝ®©”x¹¾0óW_}õù㧇LJ7sB*RÓì&Lû¾Ñ!Rlmyx¸¯ËRks€çÏ_ž_P„›ÐÞ×uu}ŒÂÜÇ>ÆÈÑÊlUaŠ 32 ”ÉEÊå²¶ZÍl¨Æ‘r™gû©xx|߇¦`·ë’‡Çw"åz}Q35ˆ¨…S+qž#ß}ÿÝËíJ —‡ûÏŸ?‰TbŽ„ÛDc¨"áº,}W¶,Ë„Íc@@1Ä™ÈÁ<³Ká#‡3Æ]Dz®£÷"¥”õrÙöm¸¥:"Ï÷<Ü‘h·L.CP³ð`–Çû‡þgõòrãL?!áëíÖZ3ל•çó–ÑÇî¾´V¤äà×&‡À-üô*ú>FðxfÏó1ÿ—ÆÌ¤ÁRܦô_L`j^r‘ì¬HD2s‘Ì‚¹¸C­µ´Æ\ß©j­Õ–õ‚La‘V V "nuͬT€ù(Nô ¨ªYjkàÎ>†Õ¹šžÞãÏÁïÛY´»«§(1Ža3#p ¢ÌñõÞ÷¡£°ìû†ª]挈ˆ“Îr v â0OŸ#q¼YBxBŘ(µ¤çö9Ü,tßqs‘ˆH%S»Ü]&ƒe*FÓQ’|¹C%¢¤ Ï+zvaÄ€rˆîaµ÷Dµ´¡š#fÓ!$áÎÂ{¥@àR‡ê¯þÙ¯z1W"ëe]Öuì=K Èp;yxx¦õþÝw`Â/O_4"Jkšga@)•˜Ý5™xª¨d°"‰|æ·8ÎâdžøÊD,Œ:ö‘˜Ã4 ñ±ÓKÃEΩ–t“•û´˜"²ˆ» óãÃýõv½Þ^2÷‹Pˆâ•£õ„Î5lØp„Q„þÝÿüÿ1þ£_??}®µôýö¿û‚§{Pû|d¯×ëmÛŠLVªïûF<*2-:ð/þöoÿ·ßüÇZʇ}øôéck­–²m;"öÛµŠX)µ)¥Œ¡½t÷¼<®,ý¸Ýn„Ôû¸»»|øðaÛ®}ßïï/û¶Ó²,R+Ø\ë¥gBŽø-tÏèÂR[€Û‚ü›#_é”xÏ-wÚhTu uš1K&|M䱈 ¡dÚ ÎU5Oz 1NEµ#³$ÜT¤ÖZ±µ¶m=ã–e.}Äpèp"ç ·ÛõñáጄÍuQ¥<”騙!$\(bŒ‡,=ANùQä?–¼¶œžåEIˆóxF)Ŧ‹• ³j&7=‚ëgütž’DR„»&M(܆iï}¨þâúïþÝ¿+¥üÝÿßýíßþÍoûÛ}ïûÞ/—Õ,QÉB[ß1À™8n/×»e¡\Œ1j­àQK}¹>»ùݺ>?=ÿÝÿwÿøí·{ïf&,‡Î™¨ˆdzgºŠ "ÌUÇÖû>ºÅ«ƒZh ³§T‹Ãly%E2#RK):œ‰tô&…‰jmˆˆÌµµeY¶±¹[)eÛw‰ñ8FH$BXJ¹»\úPc”:«×ãÐyÕÌœ%ÈyîŸ"‹¼-T ‰jm„‚@"ÕM %ûNf®ÈL$™4‹D\ë"R”y DÂ¥^3›sCUmÛ®fš¾“ضçZË3ûÔL=ÔL‹Ôãgœƒ½ÜŲ”œÒLô8ò·¢õCy™SÙ|NfmAé-‡"LDÈ”’匈š‡»È¾ï­µûË"š ÕQ('9Óä©Ýd¢£l?ïÑÀ·ãöÍdafÈD˜éá$Àdê&³lªý‚1c±È!¸”¼W×eAÀ¡ú¾›iÚº! Tò·'Ê›#<ˆ€rúÍS©Šëºî£‹ˆª.ËEÝ-"ªfNÂÈ•¥©ƒº×Úò! B³X.«QWC¤1„K"b"2:KD(èüDr JDÄòþëoÿá—R®×—ýèGÛÞ‘KIQx`bûûþÂÈè¦îHé?,ÌùÊ@~µ9c­|Økq‹)RÈËD뺦4-Ÿ˜¡š¢üÔnYºã‰AuÐųèá¡–Ë:˜fKîCïÖ» -"œiX‘'ÿ|÷ )0Ó!ÌmÓWï¿|þ acÏlر_¯wwfº®—/OŸ/—•ˆ¿ÿþ»lŸ§Í€7ðкÔ}ï—»»ï¿ÿ>j)¿ùÍo¾ýö?~ü\KËÀÌMÍÁÌ ¼¬½ \k­R·ýÚûa3K.)&w—ÉÝ÷Þ—Öþð‡ïÆÓDGBbpbË&kÖæÖu¨[bÒy8ƒ qªn3ïri1C×"ÀLHBíñþ "qß7ó¸Ýnûè,´,ëív#–-ç ›ã}ß‘`]žu'÷Þƒ –R¥±`Ü®:4l¸Â›ÓÄÍÀAXÖeIå(uæV[3w™«>c¸U5f¾`¸‹HÁ@!ÝÜýr¿~þü9ÀöÞî"à¶m‚Hcô¤Í€T¹_lÛ­Ô2'õc‡ø!yü pþoÈÀ³øE$a®¥&ȼµÕ†fB^Ó)KÍE³\Ö{) ‘™‹`ŒÓà°“zJ³G‡§Ú{kÕ\3\hŒ]mÌõ’õláÜ 5ŽDŒRÀg\sà¡qN¥_v{s–/&Dâøs:u~kÌ5N~YblÓ0Q¥>ZiLœpù¼Y —Œ×)Rry7ÏX$ʵ*qÖŒ²`þÁ/ÄRÝcZ†±}þr­-YT^.« ÝÇÀÕ1¡pRë)ÎݦÃYr $Œ·rì „d3~0Ý/H‚}I©ëe x|‡„CˆÓFRÝD’¾PKþêff¡ƒXÜ7 Èj­uY³ !bñ )m¹ÜóÓo>~ú,ÌÝ”„K]z掠"mY³ãÆ„XÝ]XYmêˆ!!|ˆÄ\J)éT¡‰ÂHŠ!šù¶ß.—Kß73¿¬km Iþ‹ö«§//]ûñmNáE´ºdKqB r´bÛ¶…3…™™ ‰›·¶ @ßv@\––,Ÿýì§_ž^¤Š…AþMƒ˜k¡­÷aÖZ»\.ª:F¿\.a¾oýOÿ‹_~y~þêÇ1ÆÐaî}·®j­ÛõFŽ„¨]XXþ¼`ª­U„äç„><<„{¨ )âá,Õ-ò©¶0_— ¦ÏÈ,]¤€Lºé™Y: !lësžRê!Ì$EJª•eì}{¹^éåz{|÷8Æ0õ"ÕÂÌŒr©šDûÔ“-Ë’jnwËùU@ î¹É ‡„ÝÍ ¢–BBà9!—Ë…Mµ”R¥t½w@¼õÝ͹H^TÉúˆÜ»› ]–µ²¸º0¹=;¸{ܶm»Ý²â^ëŠ,È”ÏI©EDÔtŒAX"€…D$'Ÿîž odãÔ{ß¶¤pŽþ¹7Ì¡MD)%3–'°I¤Ô²æ.qâü0…^ˆD6ïs'â»û‡ëõáIJضm¦æ2 ËОø—Ô5ä­¾¬ËËËõÀOb-5ÈÀsñKEjæÈ›Yö¼’÷bn•Ž™¥Ö3Õ$;W!öd©BJþSK \§ThNçMÍTM5åÌr×µ›A~”ު¤× $R"NRfÞ€âµ-miR SYrë•U„ÔBŒjJX¤Ôd+G¡ ²ÇÑC„Âm»š)aC˜ªnwÍ­-1 ADi¥.ÅÃ"Í™ÈuLiBƒÁA‘À}`ùÍÒBf@,mY/$ÍÝ?~üH,e15£¶5ù…cìà;Ã@U°áæ†ä\êrXÌ^èŒOL‘S¸‡Eh„I‘rSU7íJæjÚ Ô³Œ]ãôÒÓ’u]‡*uÕwï¾&.Û¾“Ž‘ž*ÀäØQÕzw.-—e!!ï£×VSÂøøø@cìpHK-™PÝgo`‘5“ v¥”?ÿ³¿üÝ?þTu]×>zîÌ ¢AfébŠ‹“/  H­Ôp͈.`1vp§07펀_ž^ÂÌWãý׆¹›3‡²ÈŽ€PмÿáùiSRÊïÿOØ· À0 <Œ 9‹h$‹°Bµ” áòÕWðÇ?þðôü\k}ÿõ‡­ëu sÏ"Çl¸¹9s dÞ·½updõ½µ‚î«HÅòx¹¯¥8`-í6º ³RjkË—ëÕl“Ô"Rèåú¤1‚3ÈEÕ@ÇÀ4ú´¶zB0Ñ 0&k."¬UQ ÕB\¥˜{«UÝÈ3ŒÛŒ‰K©(—e]–…ˆ °õ~×\kËBÞÌþö¯ÿz»^}˜‡1 ";*u÷‚üx¹¯R ?m×*BÃ-w“…ÈÜ#·ëf#³‰¹¢pgS%ž.ÓPddj„†›j7à®ã5…5…†PKc–uiûfÂK-‹0×*´oc¸!ñz·"ÑPO2J9ÖÌ®®C-ûâý¶¡#.µb`X0ˆº§}­”vÛn¥Ô;Ù«Çv&ð±"¤¯†î9ÝeäÕH éþ5õÛ¶#±@x)eÒÄœYn·É™#­™ˆ)„Lª0ðp&f5»Ýn`6¯+pP@¡@áµÉ°6"JkÃÕ#P{' Wç¶ÞíÌÛ϶Âç¬î@Žük8,Uðž™2SV~îO8åh©ÉH/@¼srŠ„éb86@©T$@Jë 9„Ha@†‰£4øÞ—V.ËÝP)ºï/BHy@ q“£Û§*`J€³œŠA )¶Eç× J‹ö1`Ѭ€æØê aCÕ +¥ JkmÌ2›GÆ{Æ1pôpò‘zwÿ&½1´0!ຬ‘žFw`SOÍÆ·Mksâ¤ìªv wpÇÀÀBTPj-oYèæ“ŸO¹ôÔÅ5ß² "t¦}ß—ÚÂ2e7\ÍX™þê¿ü?\¯×ëíÖ{7"R×>z«•ˆ*qa9<Ð÷á1ñ[ÙD ‘Z·æh0eó¹3<¦ßŠFÞœ ‡÷2Ìv9¦ðTk-¥aw8†µ!R™D¤úD„ZÏ›™äôwzXJÜ"'Q,"µ@"ò2kèÀ|æ«/áá™òâlð„x§È˜™è(ç_רS4B”söWíòÔo gÎWêÒ¬6 f¦ôlVJ@Ž‹K”ïAã‘”£y)Ÿ+tlw¨ÖÊ4‘bîÎmy<Å`èá©=ò‰—›‡{:H§ êÿÏÉž?´§ìûüݤÜIdžácì¡–jÅ ’Új]„‹í/yÁ“pHÓ ³Henm),`fc.…<­q~ŽÆÂõðì%”'Ij>37¤Qkk)¥ÖåкԜÀ䜜d;ÄZ—õ²æ bf£oî¾,Cóe¸¿¿¿¾¼ä“z :…pCKDÔ°eY˜dßÇœ{¸Çº^´k„ÓLtšIdé¹ÃÉʼnMM¡ˆ3GF>$bG3˜eå°8ö±±Ð¾õpc —"uÛ;€AïÝ-˜IPÒ÷áfaà¬CS÷šÉ”{oµ ×pü×ÿú_ÿÅ?ÿËóoþÍõví}ÔR‰xôáfD,…uXªŒÓ»Ç$È숀àª.R²hiU<ÀÔ!’ÝŒ› SˆHWHºöôõ×:Æv½Í= ‚¹I‘ž*uœncîvÝç&už‰(È‚(,¹ç>-98`¢RJ¦`§P]=‘ñX¥Àa‹Ue Ïž1ù^€ nÿñ·¿ù§ï¿f®nC5¹†ù‹–Ô%äeO®SNNÑ‘<"oFBÈ’dˆ)4Å9ÅMbúYðÁ!ÏÍ!8ÎXäÉÌL=¥’„¹è£ëѾ`­­–ÖÚ  æ0)©Ì+&ù”€èˆÄRïÛ²’y"+|¨‰L–‹ª.kK¾<t—|ŠyÒ€xn¿0¢’;ƒ¹Ï_öغ¸‰¼ŸŽ1bŽ<œET()lY4o;$â’D~„I¹IM&þN† !³”ÚÜ‚…%0ÂýØÉU>6ÁR/A$(Daù"ÿÊB6•=oŠ÷×ñ õv÷ §iÊÞ_xri˜ÑchZúçáŽÇúq¢ý§Ü›’†”b:y¼f¹²}ß™0Âk)úË_Þ?ÜþþûŒab˜Y<H¨ÃÂ6wÇcí3Ž÷È( U]‡ Eøi*C˜d(ÊÌ4EÏà8‚¸Ö€è9n ŸÚ5·à¹IAÄ¡c:"J¡é\ȼ$€eYŽa¥.x¿Ýò!ƒ$4»"¨j̈½ofFÈ¥4wƒ˜™^ï޽߶[ò4<)Yë#¿*3=œ3“Þ=¤RNMæ—0Ì(àÝãÃЌ۾Cľí­-ˆE¤nûV›¬ër»^!ânYІ.­iâ±òâ`âd¹ÌeŒ^jÃÀV×Z–o¿ýÏ?}üøñ{wcìÛ£OXqƧ6 %Ì̉äD{Bk«G€ÇWªš–™´e:‹tëw÷÷Û¾# „y)á­Õ¾mÛv«EX,LЍ¹g^1€»ª«ºº©†[XÌO1Ÿ¶œãžÓgœü/&ªµ¾\_ÁÌHØÌܼÖúpwïêÃF"|ÁÕ“äÅ"j¶÷Þ]1“ÑÜ”Å!ZT!Nâ]ºê€ µ¤~7,ÐÜ‘°¶imã5™6§7ðE _|.Þh1¡Ä’L"wBâL³Ë1=±[„Ó²Þ¥Tf|œæy:¸;01•©LU»»»#:!‘|¬v˜%õ«¯Þïûžïl. ŽÊÕÞPõý\Æž`´ää“™,t‘’AQis™böY¹[Ìg0×ÕLĪ)³ï‡)¥Ôlèkmˆ”á/D˜y-L§q$+iªµ®—˾ÈþÝfÈLDH»Büÿ&wF¹Ò€u%tEXtdate:create2016-10-10T23:52:04-06:00Ä2¹„%tEXtdate:modify2016-10-10T23:51:48-06:00²ÞµtEXtexif:ColorSpace1›I!tEXtexif:DateTime2013:06:23 12:04:13 ¢vjtEXtexif:ExifImageLength1200€BV­tEXtexif:ExifImageWidth1200sf¸`tEXtexif:ExifOffset164Ì{++tEXtexif:SoftwareAdobe Photoshop CS6 (Windows)ç©Ç;8tEXticc:copyrightCopyright (c) 1998 Hewlett-Packard CompanyùWy7!tEXticc:descriptionsRGB IEC61966-2.1W­ÚG&tEXticc:manufacturerIEC http://www.iec.chL7tEXticc:modelIEC 61966-2.1 Default RGB colour space - sRGBDSH©IEND®B`‚fvwm-2.7.0/default-config/images/fvwm-logo-small.png0000644000175000017500000001335314147024700017311 00000000000000‰PNG  IHDRn&%P®úbKGDÿÿÿ ½§“ pHYs  d_‘tIMEà &]P òxIDATxÚÕ|yx]Õuïo­½ÏͲ$YäYfˆM0~L P¨ m ôå¥$ „ò2¾—W^^¿44MÓ$mI¾LM@·@¡ÌÆÆàÙÆž-y’dÙš¥;OgØûýqŽd Æìï»ß½ßÕ9û®a¯µ~ë·÷á䃽w…Þ O~v?À~O›"è1/å½ä†<ù·eLF,ªÍÁupò Ùó\0€‚“£Ý­æhP öÇA†¤5³mtD­€Ü©­Á.Øé,€ 룴:ßýehú>ŠÍ› {8¯KýèÜ¡ßAY;Î#ÙÀd ÔÏ&_嵚ƒŸ$_Õl Ôƒüõ€Q Q€% í)«• X h³ºØ ˜½9X‰õZ•^ÕÙ#ë¡ÍvƒEÇÉð©láç8Þ²˜|åPÉíY•ÚóKïø%€öó@îQxÊõžòi Ô^Báé àdK@+ Z»YpDÁQǨM @€ˆ¡­Tît¾#¯Ký/ªäîàäVèÿHEœ7¦ÁˆÝ%k¯ý–¬»T¦ vßÊ*±óÿX÷!É;•|åw‰Ú«oâðäY™È ÷E ‘€&rÕÓ ½’Ɔ«ðˆs•òî©ºØ •=bªôþÕÎÀ†'<òQsIî®ù™1ù6¡K°ºžï²ûÖ~À²s,ë—å„kî”Õ—]DáI ´í%M °m¦ ÒG ²P…n;Ÿ×NÞ€c lhö•)ø+¨EšÀÑ) 6eCk÷RUê‡NN–:Ÿz¥¡¿Ð(eΠlj3ü݆¶wë‰nÀ^"kBTÌŽ‹ëd«Àšs cœdðW™wUÖ]ÙÈщ a€Xƒ ?@Ôà›°:ž„u왬=°Þ •Óˆ³Ê¶—ÈKY³@r´‘Ùöð[UêÀ½*×¹ÓÞ‘pú×Gt±'ÎþD¤ b€ýQˆp}@V_2K;…›UöX޹í|‰81Žk(k·Êͱ/ô £bÉŠÙ>¬]ll›à™? |3D¬éÉÀœ{n’U->ö@L )@p`X‰â_$íÞ kTþįHÛ5‘+~1ÑW÷ßHÖ^ 'uX‰Èék¼QȲé$b“ÉÞÓ« ½ß‡“_ ;»B›É'uîø*»o=9É=Í"\+D´D$ìBV¶Ä)X}3¸c€—χBŒó:ílr†vGdlÒ¥":‘EY‹ŠÙ-vÿöÅPæ+ò¨\Ä×5¿œ÷噲¬ `€™@¤a'ÛPxëGi»gÝrX¹ŸC;úU’Áë‚3o› &°á‡Ý·Y³ ²¯z“4Ü{{7¤Uað'<™‡¡íÃPÖKºÐ÷”Õ³.ˆÒà,Y>E’/ì- »À _¬ÞÜ•]Ð*ÿ{ƒå,q@§Î´8ÄYL«¬´z·6Éê™se¤–E´FMË•î¼V‡·èùÄq¨æ._ÃeËBÝÁ8À $Py.SÅ}îÖVæ€ò€R‹dàÖàŒ[f+°4`õlvزQ3—IJ€Xݪ0ð4€¾wèf¹(R?ï¤Û7ØÛgˆxC­ U ’Äöо°*}J–O»Nåz>(}€‰}KÚ‹_"ÐTm¦_PÅÁÊÿåépñ5jö dù”g-} Ôòßý"œb5€Ø{£¼Î< º”º+·ëá!mgï 6ßFž}3ìäü|õóoPÙ¾MV²c§Õ»g¿¶ †½š"DÔËŠ)Ӫ湭»Ì(kª7j[Ü^L› ¿N¶¹=OÂêÛ£Bsná`ó¨b‚¼¨ŽH¾³¹qãEH¸Žƒ`hͿ߮ž¾ðs¾ügtvÓOÀ‘Ú‚WkŽÁÁ0"}Žd¼þϱ†}@ëøƒ€Å¾I ¿œzí'ü“A+Çm/Ý~„ÿPŽ€¬*$îËï{ªW‡þ&«Ë$bA2 #XFÂWÆÁrp¤$ @9 "€ƒ(ߊÜÍÞÝݱE÷N 6_€ÖЦ†q'‘܈#vözrƒA‚¡À8Ïie9FÕd[t/Ú^VÙ%ŒY7™,)í¦“ÐÌ?‚,›x{áÀ S‹ëÿ€ã˜úŽÐœ¥ÿ78ý“ÓdùT@™ fh‡ADãB¬ò}æçŒ*$~\h}é€8úá–?™˜´P8‡Œ”€­ê´²]– —ž))ÚµùCp²ÈlÿŠ›ö©Bâ1Q£²ñ–"­ Ó-Fb6@Â[ì¦J!€³Œ8"±‚Ä™·”u)Y©JY“ (gTþ@Ã\ñê…©|(¿÷¹ïøíiïÆ}é§\UÆ8`A)_qù%mÿËìÙ½Ãêoý¦¿qáݱKn—Fõ4he{i@0ïÀ° vª¹íϡк²W™Ù—´c¿ `5€%$H“A€&]žR_€%A„š A’@’ÀšABŒ¿®“v.Æ}ª˜f2P4Ʋ¬ñÿEƒDþ5ûÖ“ Ú±~À‘G¹!&‚åÿ[tç©—3yä·›5@ r`:gŽsû<åth]üzñ𚋇×|ÝW7çÓÁéWD/†Œ×¹«êmm½ ;Ñ…RÏ^Žl0ÍÞýíÚ±ÖxÀvâ8.9â¸S+ÆF @ÒÛŽcZ;Jðî“’>Æx×5‘[+…»½Gä½ ÈÍN¦"Rã^.‚ˆ/ú¼!Âe—Þòø UHÞ ­óŒÊÉÅÝyU`òhåŒâ*';­öî§ñÜæ8/ˆ´ `'±ü‚Ù³ï;fϾëRÀ徚éWU\û­&YÝ"FzË2¤6wPz›ýĈñÎà8¨Š„à@Û& í´Å$H’ @ °/È^ë1‰nQP›…w¥¸Q§Ãm/Í 6è}øªüꯨ@ÓB €¶]p+ŒÊIÿ#ñúÏæªBê[FUÓ#å×|u¢Q=Ú6A’¡m¹=/:ùCëxÂgMÊ,¸¿C†ãF‹ºíxó €GeYÃ5¬¯³pÁi[{uàq)oŸÏ<%[Àž±4Në8Ÿ0Í]µ §˜‡v¬¤6s’XH0 8\n(ÛG›þ†Œ€/·oÅ*Oî15޼H ¯fº ZƒACŸ|ñ»ÊáÆpËÇD0íœr)ŒÊI¥ß|bUÙ_û#ÐÊvf©õ—rûW¬L^ÐBŒj-Æžøa‘”&ñïf á)éEةД&‰:Kyª]…‰-b ’ UL@›Ù.•O¤Ç»W@–ÕúT“­·÷Å}6ÿøŸûˆøþw¡T/âÜhp_$¼Vƒ 8~\ÿÐ×Rë"#Põ΋´,5*êÜß!NªÛr²CNf`”i³qÕ!2ü3Üú%ÿ*zÉM ,,Ñ o¨bè‹#vþ`lÔI hej«·GáÛö5_/Ù|Çðë¿x:»ç°ß–…ä¦'0¼êçoYCÇþÀ¿Øã¯ŸYÕ8ÏR¥ *ø÷Ê’+œwÎip;û#ÅÞ²±îs?ùYhÆâ[ÌÞ¶0´íÝ/(4åc &Œ¹oI|á-õ$¼4™F©û@?€6šGK#éHÃlœ?ÀÕñæ_eƒ1~ŒªŽ-üô•.@2V&!@Li¨bÚ!)LcÒþ»íÜjöþRrÍCßZþt)çÿ^§6>¾ÒÉ%~пÔÀvŠ·Žzó1Èàä¤7ê4†×Íõ"ª‘@‹¿¾¹%Ð8¿:ØtqÀ?ajB²ÅQênSÅ®½¤Øï ÑKn¬Èµ­¿À^0*꿜z± @ˆàd‘;¸ñ€6ÅŽm¥È¬E1D$ÿÄYuùÃ[¾j¾t®ˆDG««0"M]0%³{åÍNª¿à¯ŸaCº©ÎR°“=¶QÑcæ˜&uºžrØÎ ÞŸÙõÊÞÜ5_w²Ã[´²_Ñ›Ð:ý¶zN`ìð‡Øœ±Æ¹h,2{1ùjê{dÙÈh%FÂplª Á6Îáôö•O±Œ– ˜8#hlYZìÜý €Ùe—ß6_„"D‚ m…öm9m·è̵nÜ_½äk5 ‚ŒÄa”MhŽÌ¹jz ¡YŒ Ä+&6#6ÿÚkk¯ \0§œýþQn½Ô}0é«iÊ‚T±pw ÿ©lXRÅ쓪˜}գ膠õÛ¶jHDRX2”ç¸ó+â¼CU,ÚQðOš‰À³Hâ1ܘҧmÚÎC„¢ Ù=++*'ü¥,`”U£ì²[.êíÜ}›,«n^ÐÀ> '—AjëóÝë’;Õ÷œ9Ð~¥¿~:AÁ¦yh˜-÷Ø ­5HÈx%Ìžj¾´EFÊÄÈbsÒ½¶*åŽ’à ´ 2 AÁhØ>uÉQzNœ¢o"ò«I¸¬Žã”59çGÄÔ7öx`4J)«],À)å KyUhßUÊì^ÉÙÞà‘Ƨn.¿üO®ñj""„¦´„CÍ ÿ&0q¦O–׌6Éùƒ›,;Õ¿ÄûÝC”€g³{^ûÇ`ã,C;õS"hÇûüÈì\UÌ"~Ù-ж…д‹Ø(«†Œ•»õMéݯ™Þ„²gh3ëB||uSË‹'ÚÊß‹YÌÞ£S"s¯4Ü“‚ UHAÙVúćq.ýëÖ Ø™aXC=ÐŽ m[Z• –•ì+Z¹Â±ýÉbWë1û=êk? Ù®­âºÁ×ZS÷g÷Uh¥à«™„Ê«n¯¡8d8æn‹˜y ¿ñ»AË¡ÕØÝéÎ̾µ­5Ÿúʰ?„ĺ§Pê=²D+“›žý§ªë?§˜s³, ¤·¾UÈl°3xG›Æ+Ðú±Ìî7ÖX©^°”`A`P ¯^–v#Šœ|zk©çÈN•O¸lŒ!Q»ôÞÉþ÷Ù˜DF*~Z³äî2ÀI k Å®.oKùq˜ôœtq£ 8»½˜ö€Ã ¸‡v†½ô`âôOŠ'Þ;øêCá(Fz3‘Üø¬¡îµ¶âä'Î:³­[v\/Ba$·¾ ³ïØ:@o„ÖÃv²ÿû©7_„…Üyý>äöo@©·}€€¶N¬æUs°Ëq©/ 4m>×Üt÷ŸX:N“Ü=áÖoÜà¯kôøP\ÛV;¸m«ÛâhóühÀGXán“0½¹gSöÀæßd[7ƒ€21øú)¯œ.]9¹ä²ÂÑà€Nf™]«“N!³ÀŽ9Ô½£Ø¹o¹9Ð 2$D0„¡Ui¯Ž×É¥~1üú²6må]}ü>”]z}Mx悯˜x šË/ýjìÂ+üîî¼€9p ÃkŸî„{fó8ÆñxŸ«GÂåø\jg\”×)ÁX±«íkŸ€¶!CA$Ö=;5¸À›§+ìì>Þ½2Az×jµn°Á«)0”?º÷7Ù=ë!C!äÛw¢Ðy`€-Þ.ÆÈèNmíÇ™]ks#%À_?•W愾p:ÖWÝp_Õµ·Ïá°»»`Xÿl¡Ô}äUO–ì8«Ï¹•Ä f—Z"¢÷;c{¡«í{©-Ë¡•ÄÆ3ª”_‰3ßûü=éÑÉ¢f•¢’•³î鹘´×§NÞçš©°_ ·yîÉg”IÄóû÷Í›–ë‹Ý|®íMÄQóý˜G='Âõ¤ª,•º­¯÷[æÓ'Ôë)²áH!Ú‹L«Œ7ˆÚ°ï–îFÌ´X·é“.fµ4õ”}&ØüýcP~í…Xg¸@O%øÄ”Ùhï½÷¿„`^Ž!…N%z[•H”(/æýÞB£U 'JL”w¦É‘åA8[C ïÞ;®ö‹°ëÜÂûÒ Õ÷‹a±°3mQF*z¦ª–8pµ÷“€±•mdD¾e–IrÀö{”•½¢7É ‚¼ÛN¦š+:évÌ}îQSä`!:t~: @ž=ï±øäQå^Ô³ úìçè^'M„ú@Jî4>ÑDúQM_ƒ[™úóTŸ.ÔŒLÁdø‡Tÿ“Ùpƒµÿ %tEXtdate:create2016-10-10T23:52:41-06:00@˜Ù%tEXtdate:modify2016-10-10T23:45:45-06:00´ÀÏIEND®B`‚fvwm-2.7.0/default-config/images/bgicons/bg2.png0000644000175000017500000000336614147024700016367 00000000000000‰PNG  IHDR üí£gAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ pHYs.#.#x¥?vtIMEà 'cfÝ6åIDATHÇÖËrãÖ…áµö9¸ƒ¤DQìNWRñÀU.{”—ð4ï?n¹RéH–H$€sÛ¤Øv*œpò×>øÏÿùZUóÀz¯Ç‚‰tò¢ÚL8­׎üð¾ü Uó õ^nzŵïÉí'šûdm—ÌZ„<&ô^¡–I0E¢¥5Œéwí#GdûdŒ!Ž }€Ô ¦ˆÑ#ZÃd‘^µwà¯yji3v¼¤U‹ä)xªäØ÷È’,ºO¸üÿz¯Ò«ùñoÖ]OÍô¡…Ö­Pœf^ïÈþ «{ n`UB˜š2÷é¡…ÑBŽs<èò½'j˜_¬Ù9jŽÊj¾ÓûJ…øCMY }§¨à‰ñ„×Âãy rTù÷¥òÛ—^݀ŨÖ7’F-r]y+o­¤ á‹0k¾µ\Df)×Ás¨@¹.=¬Å[Ëpîíšo­´Q³¨1ÇàKJH€ |©a :<űàXpxJ1`jÄwȺD—a„^§FbÀiîåô”b€kè{”>Ñüµ¶jQ‚+豦QßÊfºF¯4½r‰UÔIÄ“ê#`õ¶w­<®QWèq郎"Ž„‡€¨ “b7œÿHØMLŠÆ€‰ÚPϽÄíïÚ«¢6a>­­ :zHE!5CzI½ò4Àî’݈€Î sp µˆ8zHI‘›~„ÝéÜ ;¯ˆüõïE2ÊlÞo»@ôªÀ­eשýŸ÷¡ºW€²¤É´ëpíM¢ùÉÈFØíuµæàV%ͼwv=æû¸Ùû <îu¹¾½J !»žšá¡Ö†®WóãÙôݽ;<¸ì]ïK9ä ßÙ;ÆçžÈµ²šïq_ɾ]Ñü+N%Làs„À¬¦Ïx (+½ È”‡¥D¥{Ñp‚6KÖ…Àçðs/§ ç>Wì—TÓ«Jo8þSÀÔHìQ‘0ð‰.‘–é{uÄ€á)‡œãç”ÂB|P¯t 0ÌßéÔH Ÿ´7”í„;ñ¯)d¸«¹epˆYFqW"Ц5×øø@}}M1ǪR¥È&D‡Ì"K²(á2 ¯)Þsû€ »Q¢¢5H… àÛ(ªžo$ˆ€×AH´‚Dˆ µb7‘7÷dî`í^³ zÃÞcLË 8œ¼ÚŠ"™¦í!ý æ-e! wNÇcƒ×£ƒ©DHdL/zð4?ׯ¬isv=Nš X r¨-jìGõËŠRÜÔFÍ7³'MËÌÜãÜF Ë R£tgäÆƒ÷½ãö}÷«¦¡¼ßÇìÁG¡|ëž=Ðæ+;'š§ËÞyÝû®…¾ÃÍ}¤Òéóø­aAÿ•<{°ÕúƤQ‹+cùµòÖ¢šEÄ\GÏ¡zÂÅÙƒøEõâG˜EÜx € ¸Ùï¼÷‚ÃSŒ®ß¡ ˜=0(À¹žâPp,8žûV|§Å×°–¼¾ïæq¦Â4½â;ÜôÏßz€%î¢NWH4I±¿ì·"Tì'ª¢P@ÑúÚÏÌ&ðÒŸý¨EA˜O÷v:{PRä¼ß«šmDøîA2L‚)`ôRDˆ é%•Çv—²Ò Î$Kóóɬ5.û¥4KÈÎ{ïuP].`(c´¬q˜Î{ç¹·ÙÆØ ]º\À¥ÂüddcÙíf®ï»©iþ̃o¿.=ØõHYÚœïÃÐugTnö®ã‰ïèŸxð•A‹iîëË}ü·š Ü×îYÃh8],eûþr=/iÍÅ}%tEXtdate:create2016-10-10T23:52:46-06:00×ç¦W%tEXtdate:modify2016-10-10T23:45:45-06:00´ÀÏIEND®B`‚fvwm-2.7.0/default-config/images/bgicons/bg3.png0000644000175000017500000000463714147024700016372 00000000000000‰PNG  IHDR üí£gAMA± üa cHRMz&€„ú€èu0ê`:˜pœºQ<bKGDÿÿÿ ½§“ pHYs  ÒÝ~ütIMEà 'cfÝ6¿IDATHÇ5•KdÙm„#HžsofVuõôè­…$H†`À6¼òÿÿ1öBÓÐtwUuÞÇ9dh‘ã-Œø‚——?¨*ÆâÞ0ÇFÀ=Ì,ú¥õ›$Ð[Ͷ»{Ím’Z´¢›‡¼ÉV™mÇÛ±½[¿B¥÷Ë'I4~1Š(i¢²Æ­G[Ìœ•cï5ïgn^¨kôëzõe}Ýß–vùøô£E“…h—§ßî÷/cû*0<šÆôhNä<Ûzi}]Öçm{ßï_GM³h-”ÓÌ TÍ/cû+ÁÏ*VÐÜç8ÎýNßsìÑŸ øåúbÑÍÜÛ:Ç]ª?ÿûÿüæ¯ÿ}¿¯1 tco½y<ýð›¾Þöí=«ý²ÞŒVÀ1Îml#Ïe¹µ¶c¿ß_[¿˜¹‘ý eA$®>Aþúõç·/?©æœ»æ˜ÇýÜ¿·årûø«QYsÒŒf Gå×ó~Ž3ÜÍ<Ì’õÛßÿåú·e]¿}ù‡~¹ý9H«sw_ÌÃÂçyß¾}ÎcÇ4˜c¼¿Ý÷{¢@š™ežb‹µhUEr]ÖãÜ |ýúùˆ@UËÓ£Ñhš”2ãë—Ï÷ﯭ¯YE³Êñh÷ ™r ²*ç<çœY³ò|è,ÁÌÍ»÷«¯O¿²èxT’R•ýéÅ/ÏÇû·œ|4Bƒy*ÍÈš»+›™»Wͪô𜧣{[ènÞ,_®!•·®šÖ.’PÓÚ5Ï£*+§¦.­Ó»æX/ `ž.I`5/ ù|P:ìE, UžyÊ£ß(‡Ìb¥™ óþ€}}º=ÿ¾õçbæãlUÝ‚€ƒ7_$•ªt€B™‡yûÿ'(¤4k5>A7kÊAš¹EZ¦èÖ÷N–ê\å$´x?À<¬™UåƒÿÞo•ã_óqò’LÀé%tEXtdate:create2016-10-10T23:52:26-06:00ˆ¯Ð%tEXtdate:modify2016-10-10T23:52:26-06:00`ÕltEXtexif:ColorSpace1›I!tEXtexif:DateTime2013:06:23 12:04:13 ¢vjtEXtexif:ExifImageLength1200€BV­tEXtexif:ExifImageWidth1200sf¸`tEXtexif:ExifOffset164Ì{++tEXtexif:SoftwareAdobe Photoshop CS6 (Windows)ç©Ç;8tEXticc:copyrightCopyright (c) 1998 Hewlett-Packard CompanyùWy7!tEXticc:descriptionsRGB IEC61966-2.1W­ÚG&tEXticc:manufacturerIEC http://www.iec.chL7tEXticc:modelIEC 61966-2.1 Default RGB colour space - sRGBDSH©IEND®B`‚fvwm-2.7.0/config.h.in0000644000175000017500000004420414324315775011462 00000000000000/* config.h.in. Generated from configure.ac by autoheader. */ /* Define if building universal (internal helper macro) */ #undef AC_APPLE_UNIVERSAL_BUILD /* Old AIX systems (3.2.5) don't define some common keysyms. */ #undef COMPAT_OLD_KEYSYMDEF /* Old libstroke <= 0.4 does not use STROKE_ prefix for constants. */ #undef COMPAT_OLD_LIBSTROKE /* Support fribidi-0.10.4 and older with "CHARSET" spelling. */ #undef FRIBIDI_CHARSET_SPELLING /* Suffix for old (to be deprecated) config filenames */ #undef FVWM2RC /* Produces a log of all executed commands and their times on stderr. */ #undef FVWM_COMMAND_LOG /* Name of config filenames in FVWM_USERDIR and FVWM_DATADIR */ #undef FVWM_CONFIG /* if you would like to see lots of debug messages from fvwm, for debugging purposes, uncomment the next line */ #undef FVWM_DEBUG_MSGS /* Where to search for images. */ #undef FVWM_IMAGEPATH /* Define if gdk-imlib is used */ #undef GDK_IMLIB /* Define if fribidi library is used. */ #undef HAVE_BIDI /* Define to 1 if you have the `bindtextdomain' function. */ #undef HAVE_BINDTEXTDOMAIN /* Have nl_langinfo (CODESET) */ #undef HAVE_CODESET /* Define to 1 if you have the `dgettext' function. */ #undef HAVE_DGETTEXT /* Define to 1 if you have the `div' function. */ #undef HAVE_DIV /* Define to 1 if you have the header file. */ #undef HAVE_DMALLOC_H /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* Define to 1 if you have the header file. */ #undef HAVE_GETOPT_H /* Define to 1 if you have the `getpwuid' function. */ #undef HAVE_GETPWUID /* Define to 1 if you have the `gettext' function. */ #undef HAVE_GETTEXT /* Define to 1 if you have the `gettimeofday' function. */ #undef HAVE_GETTIMEOFDAY /* Define if readline has full GNU interface */ #undef HAVE_GNU_READLINE /* Define if iconv (in the libc) or libiconv is available */ #undef HAVE_ICONV /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `dmalloc' library (-ldmalloc). */ #undef HAVE_LIBDMALLOC /* Define to 1 if you have the `efence' library (-lefence). */ #undef HAVE_LIBEFENCE /* Define to 1 if you have the `intl' library (-lintl). */ #undef HAVE_LIBINTL /* Define to 1 if you have the header file. */ #undef HAVE_LIMITS_H /* Define to 1 if you have the `lstat' function. */ #undef HAVE_LSTAT /* Define to 1 if you have the header file. */ #undef HAVE_MALLOC_H /* Define to 1 if you have the `memcpy' function. */ #undef HAVE_MEMCPY /* Define to 1 if you have the `memmove' function. */ #undef HAVE_MEMMOVE /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the header file. */ #undef HAVE_MINIX_CONFIG_H /* Define to 1 if you have the `mkfifo' function. */ #undef HAVE_MKFIFO /* Define to 1 if you have the `mkstemp' function. */ #undef HAVE_MKSTEMP /* Define to 1 if translation of program messages to the user's native language is requested. */ #undef HAVE_NLS /* Define PNG */ #undef HAVE_PNG /* Define to 1 if you have the `putenv' function. */ #undef HAVE_PUTENV /* Define if readline is available. */ #undef HAVE_READLINE /* Define if rplay library is used. */ #undef HAVE_RPLAY /* Define if librsvg library is used. */ #undef HAVE_RSVG /* Enable the use of mkstemp */ #undef HAVE_SAFETY_MKSTEMP /* Define to 1 if you have the `select' function. */ #undef HAVE_SELECT /* Define to 1 if you have the `setpgid' function. */ #undef HAVE_SETPGID /* Define to 1 if you have the `setpgrp' function. */ #undef HAVE_SETPGRP /* Define to 1 if you have the `setvbuf' function. */ #undef HAVE_SETVBUF /* Define to 1 if you have the `sigaction' function. */ #undef HAVE_SIGACTION /* Define to 1 if you have the `siginterrupt' function. */ #undef HAVE_SIGINTERRUPT /* Define to 1 if you have the `siglongjmp' function. */ #undef HAVE_SIGLONGJMP /* Define to 1 if you have the `sigsetjmp' function. */ #undef HAVE_SIGSETJMP /* Define to 1 if you have the `socket' function. */ #undef HAVE_SOCKET /* Define if Solaris' Xinerama calls are being used. (Solaris 7 11/99 and later) */ #undef HAVE_SOLARIS_XINERAMA /* Define if Solaris' X11/extensions/xinerama.h header is provided. (Solaris 9 and later) */ #undef HAVE_SOLARIS_XINERAMA_H /* Define to 1 if you have the header file. */ #undef HAVE_STDARG_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDIO_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strchr' function. */ #undef HAVE_STRCHR /* Define to 1 if you have the `strdup' function. */ #undef HAVE_STRDUP /* Define to 1 if you have the `strftime' function. */ #undef HAVE_STRFTIME /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define if stroke library is used. */ #undef HAVE_STROKE /* Define to 1 if you have the `strstr' function. */ #undef HAVE_STRSTR /* Define to 1 if you have the `strtol' function. */ #undef HAVE_STRTOL /* Define to 1 if you have the `sysconf' function. */ #undef HAVE_SYSCONF /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SELECT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SOCKET_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SYSTEMINFO_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TIME_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have that is POSIX.1 compatible. */ #undef HAVE_SYS_WAIT_H /* Define to 1 if you have the `textdomain' function. */ #undef HAVE_TEXTDOMAIN /* Define to 1 if you have the `uname' function. */ #undef HAVE_UNAME /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if you have the `vfprintf' function. */ #undef HAVE_VFPRINTF /* Define to 1 if you have the `wait3' function. */ #undef HAVE_WAIT3 /* Define to 1 if you have the `wait4' function. */ #undef HAVE_WAIT4 /* Define to 1 if you have the `waitpid' function. */ #undef HAVE_WAITPID /* Define to 1 if you have the header file. */ #undef HAVE_WCHAR_H /* Define if Xkb extension is used. */ #undef HAVE_X11_XKBLIB_H /* Define if Xcursor library is used. */ #undef HAVE_XCURSOR /* Define if Xft library is used. */ #undef HAVE_XFT /* Define if Xft 2 library is used. */ #undef HAVE_XFT2 /* Define if Xft library can handle utf8 encoding */ #undef HAVE_XFT_UTF8 /* Define if Xinerama library is used. */ #undef HAVE_XINERAMA /* Enable X output method */ #undef HAVE_XOUTPUT_METHOD /* Define if Xrender library is used. */ #undef HAVE_XRENDER /* Define if MIT Shared Memory extension is used. */ #undef HAVE_XSHM /* define if second arg of iconv use const */ #undef ICONV_ARG_CONST /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define as the return type of signal handlers (`int' or `void'). */ #undef RETSIGTYPE /* Define a suitable cast for arguments 2-4 of `select'. On most systems, this will be the empty string, as select usually takes pointers to fd_set. */ #undef SELECT_FD_SET_CAST /* Enables session management functionality. */ #undef SESSION /* Define to 1 if the `setpgrp' function requires zero arguments. */ #undef SETPGRP_VOID /* Define if you want the Shaped window extensions. Shaped window extensions seem to increase the window managers RSS by about 60 Kbytes. They provide for leaving a title-bar on the window without a border. If you don't use shaped window extension, you can either make your shaped windows undecorated, or live with a border and backdrop around all your shaped windows (oclock, xeyes) If you normally use a shaped window (xeyes or oclock), you might as well compile this extension in, since the memory cost is minimal in this case (The shaped window shared libs will be loaded anyway). If you don't normally use a shaped window, you have to decide for yourself. Note: if it is compiled in, run time detection is used to make sure that the currently running X server supports it. */ #undef SHAPE /* The size of `int', as computed by sizeof. */ #undef SIZEOF_INT /* The size of `long', as computed by sizeof. */ #undef SIZEOF_LONG /* The size of `Pixel', as computed by sizeof. */ #undef SIZEOF_PIXEL /* The size of `void *', as computed by sizeof. */ #undef SIZEOF_VOID_P /* The size of `Window', as computed by sizeof. */ #undef SIZEOF_WINDOW /* Define to 1 if all of the C90 standard headers exist (not just the ones required in a freestanding environment). This macro is provided for backward compatibility; new code need not use it. */ #undef STDC_HEADERS /* Define to 1 if you can safely include both and . This macro is obsolete. */ #undef TIME_WITH_SYS_TIME /* define if we use libiconv (not needed in general: for example iconv is native with recent glibc) */ #undef USE_LIBICONV /* Enable extensions on AIX 3, Interix. */ #ifndef _ALL_SOURCE # undef _ALL_SOURCE #endif /* Enable general extensions on macOS. */ #ifndef _DARWIN_C_SOURCE # undef _DARWIN_C_SOURCE #endif /* Enable general extensions on Solaris. */ #ifndef __EXTENSIONS__ # undef __EXTENSIONS__ #endif /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # undef _GNU_SOURCE #endif /* Enable X/Open compliant socket functions that do not require linking with -lxnet on HP-UX 11.11. */ #ifndef _HPUX_ALT_XOPEN_SOCKET_API # undef _HPUX_ALT_XOPEN_SOCKET_API #endif /* Identify the host operating system as Minix. This macro does not affect the system headers' behavior. A future release of Autoconf may stop defining this macro. */ #ifndef _MINIX # undef _MINIX #endif /* Enable general extensions on NetBSD. Enable NetBSD compatibility extensions on Minix. */ #ifndef _NETBSD_SOURCE # undef _NETBSD_SOURCE #endif /* Enable OpenBSD compatibility extensions on NetBSD. Oddly enough, this does nothing on OpenBSD. */ #ifndef _OPENBSD_SOURCE # undef _OPENBSD_SOURCE #endif /* Define to 1 if needed for POSIX-compatible behavior. */ #ifndef _POSIX_SOURCE # undef _POSIX_SOURCE #endif /* Define to 2 if needed for POSIX-compatible behavior. */ #ifndef _POSIX_1_SOURCE # undef _POSIX_1_SOURCE #endif /* Enable POSIX-compatible threading on Solaris. */ #ifndef _POSIX_PTHREAD_SEMANTICS # undef _POSIX_PTHREAD_SEMANTICS #endif /* Enable extensions specified by ISO/IEC TS 18661-5:2014. */ #ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__ # undef __STDC_WANT_IEC_60559_ATTRIBS_EXT__ #endif /* Enable extensions specified by ISO/IEC TS 18661-1:2014. */ #ifndef __STDC_WANT_IEC_60559_BFP_EXT__ # undef __STDC_WANT_IEC_60559_BFP_EXT__ #endif /* Enable extensions specified by ISO/IEC TS 18661-2:2015. */ #ifndef __STDC_WANT_IEC_60559_DFP_EXT__ # undef __STDC_WANT_IEC_60559_DFP_EXT__ #endif /* Enable extensions specified by ISO/IEC TS 18661-4:2015. */ #ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__ # undef __STDC_WANT_IEC_60559_FUNCS_EXT__ #endif /* Enable extensions specified by ISO/IEC TS 18661-3:2015. */ #ifndef __STDC_WANT_IEC_60559_TYPES_EXT__ # undef __STDC_WANT_IEC_60559_TYPES_EXT__ #endif /* Enable extensions specified by ISO/IEC TR 24731-2:2010. */ #ifndef __STDC_WANT_LIB_EXT2__ # undef __STDC_WANT_LIB_EXT2__ #endif /* Enable extensions specified by ISO/IEC 24747:2009. */ #ifndef __STDC_WANT_MATH_SPEC_FUNCS__ # undef __STDC_WANT_MATH_SPEC_FUNCS__ #endif /* Enable extensions on HP NonStop. */ #ifndef _TANDEM_SOURCE # undef _TANDEM_SOURCE #endif /* Enable X/Open extensions. Define to 500 only if necessary to make mbstate_t available. */ #ifndef _XOPEN_SOURCE # undef _XOPEN_SOURCE #endif /* Define if Xinerama should be emulated on a single screen. */ #undef USE_XINERAMA_EMULATION /* Version number of package */ #undef VERSION /* Additional version information, like date */ #undef VERSIONINFO /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD # if defined __BIG_ENDIAN__ # define WORDS_BIGENDIAN 1 # endif #else # ifndef WORDS_BIGENDIAN # undef WORDS_BIGENDIAN # endif #endif /* Define if Xpm library is used. */ #undef XPM /* Define to 1 if the X Window System is missing or not being used. */ #undef X_DISPLAY_MISSING /* Enables to use setlocale() provided by X */ #undef X_LOCALE #ifdef COMPAT_OLD_KEYSYMDEF # define XK_Page_Up XK_Prior # define XK_Page_Down XK_Next #endif #ifdef COMPAT_OLD_LIBSTROKE /* currently we only use one constant */ # define STROKE_MAX_SEQUENCE MAX_SEQUENCE #endif #ifdef FRIBIDI_CHARSET_SPELLING # define FRIBIDI_CHAR_SET_NOT_FOUND FRIBIDI_CHARSET_NOT_FOUND #endif #ifdef FVWM_COMMAND_LOG # define FVWM_DEBUG_TIME 1 #endif #ifdef FVWM_DEBUG_MSGS # define DBUG(x,y) fvwm_msg(DBG,x,y) #else # define DBUG(x,y) /* no messages */ #endif #ifdef USE_LIBICONV /* define to use locale_charset in the place of nl_langinfog if libiconv * is used */ #undef HAVE_LIBCHARSET #endif #ifdef HAVE_STROKE # define STROKE_ARG(x) x, # define STROKE_CODE(x) x #else # define STROKE_ARG(x) # define STROKE_CODE(x) #endif /** * The next few defines are options that are only changed from their values * shown here on systems that _don't_ use the configure script. **/ /* Enable tests for missing too many XEvents. Usually you want this. */ #define WORRY_ABOUT_MISSED_XEVENTS 1 /* Define if the X11 ConnectionNumber is actually a file descriptor. */ #define HAVE_X11_FD 1 /* Define if fork() has unix semantics. On VMS, no child process is created until after a successful exec(). */ #define FORK_CREATES_CHILD 1 /* Suffix for executable filenames; NULL if no extension needed. */ #define EXECUTABLE_EXTENSION NULL /* Define to remove the extension from executable pathnames before calling exec(). */ #undef REMOVE_EXECUTABLE_EXTENSION /* Enables the "MiniIcon" Style option to specify a small pixmap which * can be used as one of the title-bar buttons, shown in window list, * utilized by modules, etc. Requires PIXMAP_BUTTONS to be defined * (see below). */ /* #undef MINI_ICONS */ /* NOTE: hard coded to 1 */ #if 1 #define FMiniIconsSupported 1 #else #define FMiniIconsSupported 0 #endif #if RETSIGTYPE != void #define SIGNAL_RETURN return 0 #else #define SIGNAL_RETURN return #endif /* Allow GCC extensions to work, if you have GCC. */ #ifndef __attribute__ /* This feature is available in gcc versions 2.5 and later. */ # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__ # define __attribute__(x) # endif /* The __-protected variants of `format' and `printf' attributes * are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) # define __format__ format # define __printf__ printf # endif #endif #ifdef HAVE_STRING_H # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_MEMORY_H # include #endif #ifdef HAVE_STDLIB_H # include #endif #if defined (HAVE_MALLOC_H) && !defined (__FreeBSD__) && !defined (__OpenBSD__) && !defined(__NetBSD__) # include #endif #ifdef HAVE_FCNTL_H # include #endif #ifndef HAVE_STRCHR # define strchr(_s,_c) index((_s),(_c)) # define strrchr(_s,_c) rindex((_s),(_c)) #endif #ifndef HAVE_MEMCPY # define memcpy(_d,_s,_l) bcopy((_s),(_d),(_l)) #endif #ifndef HAVE_MEMMOVE # define memmove(_d,_s,_l) bcopy((_s),(_d),(_l)) #endif #if HAVE_SYS_TYPES_H # include #endif #if HAVE_UNISTD_H # include #endif #ifndef min # define min(a,b) (((a)<(b)) ? (a) : (b)) #endif #ifndef max # define max(a,b) (((a)>(b)) ? (a) : (b)) #endif #ifndef abs # define abs(a) (((a)>=0)?(a):-(a)) #endif #include "libs/defaults.h" #ifndef FEVENT_C #include #include #include "libs/FEvent.h" #endif #ifndef O_NOFOLLOW #define O_NOFOLLOW 0 #endif #ifdef HAVE_LSTAT #define DO_USE_LSTAT 1 #define fvwm_lstat(x,y) lstat(x,y) #else #define DO_USE_LSTAT 0 #define fvwm_lstat(x,y) -1 #endif #ifdef HAVE_X11_XKBLIB_H #include #define fvwm_KeycodeToKeysym(d, k, l, g) \ (XkbKeycodeToKeysym((d), (k), (g), (l))) #else #define fvwm_KeycodeToKeysym(d, k, x, i) (XKeycodeToKeysym((d), (k), (i))) #endif /* A macro that touches a variable in a compiler independent way to suppress * warnings. */ #define SUPPRESS_UNUSED_VAR_WARNING(x) \ do { void *p; p = (void *)&x; (void)p; } while (0); /* Define to empty if `const' does not conform to ANSI C. */ #undef const /* Define to the type used in arguments 2-4 of `select', if not set by system headers. */ #undef fd_set /* Define to the type used in argument 1 `select'. Usually this is an `int'. */ #undef fd_set_size_t /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus #undef inline #endif /* Define to the type of a signed integer type of width exactly 16 bits if such a type exists and the standard includes do not define it. */ #undef int16_t /* Define to `long int' if does not define. */ #undef off_t /* Define as a signed integer type capable of holding a process identifier. */ #undef pid_t /* Specify a type for sig_atomic_t if it's not available. */ #undef sig_atomic_t /* Define to `unsigned int' if does not define. */ #undef size_t /* Define to the type of an unsigned integer type of width exactly 16 bits if such a type exists and the standard includes do not define it. */ #undef uint16_t fvwm-2.7.0/Makefile.in0000644000175000017500000007140214324315775011504 00000000000000# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 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 = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ $(am__configure_deps) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_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 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 \ cscope distdir distdir-am dist dist-all distcheck am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) \ config.h.in # 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)` DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \ $(top_srcdir)/etc/compile $(top_srcdir)/etc/config.guess \ $(top_srcdir)/etc/config.sub $(top_srcdir)/etc/install-sh \ $(top_srcdir)/etc/missing COPYING INSTALL.md NEWS README.md \ etc/compile etc/config.guess etc/config.sub etc/install-sh \ etc/missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) 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" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best DIST_TARGETS = dist-gzip # Exists only to be overridden by the user if desired. AM_DISTCHECK_DVI_TARGET = dvi distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ ALL_DOMAINS = @ALL_DOMAINS@ ALL_LINGUAS = @ALL_LINGUAS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR_FLAGS = @AR_FLAGS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ Bidi_CFLAGS = @Bidi_CFLAGS@ Bidi_LIBS = @Bidi_LIBS@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DOC_COMMANDS = @DOC_COMMANDS@ DOC_COMMANDS_HTML = @DOC_COMMANDS_HTML@ DOC_COMMANDS_XML = @DOC_COMMANDS_XML@ DOC_COMMANDS_XML_PATH = @DOC_COMMANDS_XML_PATH@ DOC_MODULES = @DOC_MODULES@ DOC_MODULES_HTML = @DOC_MODULES_HTML@ DOC_SECTIONS = @DOC_SECTIONS@ DOC_SECTIONS_XML = @DOC_SECTIONS_XML@ DOC_SECTIONS_XML_PATH = @DOC_SECTIONS_XML_PATH@ DUMMYPOFILES = @DUMMYPOFILES@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FC_CFLAGS = @FC_CFLAGS@ FC_CONFIG = @FC_CONFIG@ FC_LIBS = @FC_LIBS@ FRIBIDI_CONFIG = @FRIBIDI_CONFIG@ FVWMALTFTP = @FVWMALTFTP@ FVWMALTFTPDIR = @FVWMALTFTPDIR@ FVWMFTP = @FVWMFTP@ FVWMFTPDIR = @FVWMFTPDIR@ FVWMHOMEPAGE = @FVWMHOMEPAGE@ FVWMLIST = @FVWMLIST@ FVWMNAMELONG = @FVWMNAMELONG@ FVWMSCRIPT_DOMAIN = @FVWMSCRIPT_DOMAIN@ FVWMTASKBAR_DOMAIN = @FVWMTASKBAR_DOMAIN@ FVWMWORKERSLIST = @FVWMWORKERSLIST@ FVWMWORKERSLISTLONG = @FVWMWORKERSLISTLONG@ FVWM_CONFDIR = @FVWM_CONFDIR@ FVWM_CPP = @FVWM_CPP@ FVWM_DATADIR = @FVWM_DATADIR@ FVWM_DOCDIR = @FVWM_DOCDIR@ FVWM_DOMAIN = @FVWM_DOMAIN@ FVWM_IMAGEPATH = @FVWM_IMAGEPATH@ FVWM_MODULEDIR = @FVWM_MODULEDIR@ FVWM_PERLLIB = @FVWM_PERLLIB@ FVWM_PERLLIBDIR = @FVWM_PERLLIBDIR@ GDK_IMLIB_CFLAGS = @GDK_IMLIB_CFLAGS@ GDK_IMLIB_LIBS = @GDK_IMLIB_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ IMLIBCONF = @IMLIBCONF@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INST_LINGUAS = @INST_LINGUAS@ ISRELEASED = @ISRELEASED@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOCALEDIR = @LOCALEDIR@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANPAGE_PREAMBLE = @MANPAGE_PREAMBLE@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ MSGUNIQ = @MSGUNIQ@ OBJEXT = @OBJEXT@ 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@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PYTHON = @PYTHON@ RANLIB = @RANLIB@ RELDATELONG = @RELDATELONG@ RELDATENUM = @RELDATENUM@ RELDATESHORT = @RELDATESHORT@ REQUIRED_PERL_VERSION = @REQUIRED_PERL_VERSION@ REQUIRED_PYTHON_VERSION = @REQUIRED_PYTHON_VERSION@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ UPDATEPOFILES = @UPDATEPOFILES@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VERSIONINFO = @VERSIONINFO@ XFT_CFLAGS = @XFT_CFLAGS@ XFT_CONFIG = @XFT_CONFIG@ XFT_LIBS = @XFT_LIBS@ XGETTEXT = @XGETTEXT@ XMKMF = @XMKMF@ XSLTPROC = @XSLTPROC@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Xcursor_CFLAGS = @Xcursor_CFLAGS@ Xcursor_LIBS = @Xcursor_LIBS@ Xft_CFLAGS = @Xft_CFLAGS@ Xft_LIBS = @Xft_LIBS@ Xinerama_CFLAGS = @Xinerama_CFLAGS@ Xinerama_LIBS = @Xinerama_LIBS@ Xrender_CFLAGS = @Xrender_CFLAGS@ Xrender_LIBS = @Xrender_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ iconv_CFLAGS = @iconv_CFLAGS@ iconv_LIBS = @iconv_LIBS@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intl_CFLAGS = @intl_CFLAGS@ intl_LIBS = @intl_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ png_CFLAGS = @png_CFLAGS@ png_LIBS = @png_LIBS@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ readline_CFLAGS = @readline_CFLAGS@ readline_LIBS = @readline_LIBS@ rplay_CFLAGS = @rplay_CFLAGS@ rplay_LIBS = @rplay_LIBS@ rsvg_CFLAGS = @rsvg_CFLAGS@ rsvg_LIBS = @rsvg_LIBS@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ stroke_CFLAGS = @stroke_CFLAGS@ stroke_LIBS = @stroke_LIBS@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ with_bidi = @with_bidi@ with_gdkimlib = @with_gdkimlib@ with_gettext = @with_gettext@ with_iconv = @with_iconv@ with_perllib = @with_perllib@ with_png = @with_png@ with_readline = @with_readline@ with_rplay = @with_rplay@ with_rsvg = @with_rsvg@ with_shape = @with_shape@ with_shm = @with_shm@ with_sm = @with_sm@ with_stroke = @with_stroke@ with_xcursor = @with_xcursor@ with_xft = @with_xft@ with_xinerama = @with_xinerama@ with_xpm = @with_xpm@ with_xrender = @with_xrender@ xpm_CFLAGS = @xpm_CFLAGS@ xpm_LIBS = @xpm_LIBS@ AUTOMAKE_OPTIONS = 1.4 SUBDIRS = \ default-config \ libs \ fvwm \ modules \ bin \ utils \ $(FVWM_PERLLIB) \ doc \ docs \ $(POSUB) \ tests # Usage: # make dist2 # instead of make dist # make distcheck2 # instead of make distcheck # make distclean2 # instead of make distclean DISTCHECK_CONFIGURE_FLAGS = --enable-htmldoc all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: am--refresh: Makefile @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): config.h: stamp-h1 @test -f $@ || rm -f stamp-h1 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h $(srcdir)/config.h.in: $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (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" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist 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 -rm -f cscope.out cscope.in.out cscope.po.out cscope.files distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am distdir-am: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @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 -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-zstd: distdir tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst $(am__post_remove_distdir) dist-tarZ: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ *.tar.zst*) \ zstd -dc $(distdir).tar.zst | $(am__untar) ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build/sub \ && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ --srcdir=../.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile config.h installdirs: installdirs-recursive installdirs-am: 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 mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-hdr 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-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 $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) uninstall-hook .MAKE: $(am__recursive_targets) all install-am install-strip \ uninstall-am .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--refresh check check-am clean clean-cscope clean-generic \ cscope cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \ dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \ dist-zstd distcheck distclean distclean-generic distclean-hdr \ distclean-tags distcleancheck distdir distuninstallcheck dvi \ dvi-am html html-am info info-am install install-am \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-hook .PRECIOUS: Makefile distcheck2: distcheck @banner="$(distdir).tar.gz - ready for distribution"; \ dashes=`echo "$$banner" | sed s/./=/g`; \ echo "$$banner"; \ echo "$$dashes" @if test "x$(ISRELEASED)" != xyes; then \ echo 'Warning: ISRELEASED is not set to "yes".'; \ echo ' So these can not be the official tarballs.'; \ exit 1; \ fi distclean2: distclean uninstall-hook: -rmdir @FVWM_DATADIR@ # 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: fvwm-2.7.0/fvwm/0000755000175000017500000000000014324316054010461 500000000000000fvwm-2.7.0/fvwm/execcontext.c0000644000175000017500000001000414147024700013066 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #define FEVENT_PRIVILEGED_ACCESS #include "config.h" #undef FEVENT_PRIVILEGED_ACCESS #include #include "fvwm.h" #include "externs.h" #include "execcontext.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ #undef DEBUG_EXECCONTEXT #ifdef DEBUG_EXECCONTEXT static exec_context_t *x[256]; static int nx = 0; #endif /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ static void __exc_change_context( exec_context_t *exc, exec_context_changes_t *ecc, exec_context_change_mask_t mask) { if (mask & ECC_TYPE) { exc->type = ecc->type; } if (mask & ECC_ETRIGGER) { if (ecc->x.etrigger == NULL) { fev_copy_last_event(&exc->private_data.te); } else { exc->private_data.te = *ecc->x.etrigger; } exc->x.etrigger = &(exc->private_data.te); } if (mask & ECC_FW) { exc->w.fw = ecc->w.fw; } if (mask & ECC_W) { exc->w.w = ecc->w.w; } if (mask & ECC_WCONTEXT) { exc->w.wcontext = ecc->w.wcontext; } if (mask & ECC_MODULE) { exc->m.module = ecc->m.module; } return; } /* ---------------------------- interface functions ------------------------ */ const exec_context_t *exc_create_null_context(void) { exec_context_t *exc; #ifdef DEBUG_EXECCONTEXT int i; #endif exc = (exec_context_t *)safecalloc(1, sizeof(exec_context_t)); #ifdef DEBUG_EXECCONTEXT fprintf(stderr, "xxx+0 "); for(i=0;itype = EXCT_NULL; fev_make_null_event(&exc->private_data.te, dpy); exc->x.etrigger = &exc->private_data.te; exc->x.elast = fev_get_last_event_address(); exc->m.module = NULL; return exc; } const exec_context_t *exc_create_context( exec_context_changes_t *ecc, exec_context_change_mask_t mask) { exec_context_t *exc; #ifdef DEBUG_EXECCONTEXT if (!(mask & ECC_TYPE)) abort(); #endif exc = (exec_context_t *)exc_create_null_context(); __exc_change_context(exc, ecc, mask); return exc; } const exec_context_t *exc_clone_context( const exec_context_t *excin, exec_context_changes_t *ecc, exec_context_change_mask_t mask) { exec_context_t *exc; #ifdef DEBUG_EXECCONTEXT int i; #endif exc = (exec_context_t *)safemalloc(sizeof(exec_context_t)); #ifdef DEBUG_EXECCONTEXT fprintf(stderr, "xxx+= "); for(i=0;i */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include "libs/fvwmlib.h" #include "libs/FShape.h" #include "libs/Grab.h" #include "libs/charmap.h" #include "libs/wcontext.h" #include "fvwm.h" #include "externs.h" #include "execcontext.h" #include "events.h" #include "misc.h" #include "screen.h" #include "geometry.h" #include "module_interface.h" #include "focus.h" #include "borders.h" #include "frame.h" #include "ewmh.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ typedef struct { int decor_grav; int title_grav; int lbutton_grav; int rbutton_grav; int parent_grav; int client_grav; } frame_decor_gravities_type; typedef struct { /* filled when args are created */ frame_move_resize_mode mode; frame_decor_gravities_type grav; size_borders b_g; size_borders b_no_title_g; rectangle curr_sidebar_g; rectangle start_g; rectangle end_g; rectangle delta_g; rectangle current_g; rectangle client_g; int anim_steps; Window w_with_focus; int current_step; int curr_titlebar_compression; direction_t shade_dir; window_parts trans_parts; struct { unsigned do_force : 1; unsigned do_not_configure_client : 1; unsigned do_not_draw : 1; unsigned do_restore_gravity : 1; unsigned do_set_bit_gravity : 1; unsigned do_update_shape : 1; unsigned had_handles : 1; unsigned is_lazy_shading : 1; unsigned is_setup : 1; unsigned is_shading : 1; unsigned was_moved : 1; } flags; /* used during the animation */ int next_titlebar_compression; rectangle next_sidebar_g; rectangle next_g; rectangle dstep_g; size_rect parent_s; int minimal_w_offset; int minimal_h_offset; struct { /* cleared before each step */ unsigned do_hide_parent : 1; unsigned do_unhide_parent : 1; unsigned is_hidden : 1; unsigned was_hidden : 1; } step_flags; } mr_args_internal; /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* windows used to hide animation steps */ static struct { Window parent; Window w[4]; } hide_wins; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ #if 0 static void print_g(char *text, rectangle *g) { if (g == NULL) { fprintf(stderr, "%s: (null)", (text == NULL) ? "" : text); } else { fprintf(stderr, "%s: %4d %4d %4dx%4d (%4d - %4d %4d - %4d)\n", (text == NULL) ? "" : text, g->x, g->y, g->width, g->height, g->x, g->x + g->width - 1, g->y, g->y + g->height - 1); } } #endif static void combine_gravities( frame_decor_gravities_type *ret_grav, frame_decor_gravities_type *grav_x, frame_decor_gravities_type *grav_y) { ret_grav->decor_grav = gravity_combine_xy_grav( grav_x->decor_grav, grav_y->decor_grav); ret_grav->title_grav = gravity_combine_xy_grav( grav_x->title_grav, grav_y->title_grav); ret_grav->lbutton_grav = gravity_combine_xy_grav( grav_x->lbutton_grav, grav_y->lbutton_grav); ret_grav->rbutton_grav = gravity_combine_xy_grav( grav_x->rbutton_grav, grav_y->rbutton_grav); ret_grav->parent_grav = gravity_combine_xy_grav( grav_x->parent_grav, grav_y->parent_grav); ret_grav->client_grav = gravity_combine_xy_grav( grav_x->client_grav, grav_y->client_grav); return; } static void get_resize_decor_gravities_one_axis( frame_decor_gravities_type *ret_grav, direction_t title_dir, frame_move_resize_mode axis_mode, direction_t neg_dir, direction_t pos_dir, int is_moving) { int title_grav; int neg_grav; int pos_grav; title_grav = gravity_dir_to_grav(title_dir); neg_grav = gravity_dir_to_grav(neg_dir); pos_grav = gravity_dir_to_grav(pos_dir); if (title_dir != DIR_NONE) { ret_grav->decor_grav = title_grav; ret_grav->lbutton_grav = title_grav; ret_grav->title_grav = title_grav; ret_grav->rbutton_grav = title_grav; } else { ret_grav->decor_grav = neg_grav; ret_grav->lbutton_grav = neg_grav; ret_grav->title_grav = neg_grav; ret_grav->rbutton_grav = pos_grav; } switch (axis_mode) { case FRAME_MR_SCROLL: ret_grav->client_grav = (is_moving) ? neg_grav : pos_grav; break; case FRAME_MR_SHRINK: ret_grav->client_grav = (is_moving) ? pos_grav : neg_grav; break; case FRAME_MR_OPAQUE: case FRAME_MR_FORCE_SETUP: case FRAME_MR_FORCE_SETUP_NO_W: case FRAME_MR_SETUP: case FRAME_MR_SETUP_BY_APP: ret_grav->client_grav = neg_grav; break; case FRAME_MR_DONT_DRAW: default: /* can not happen, just a dummy to keep -Wall happy */ ret_grav->client_grav = pos_grav; break; } ret_grav->parent_grav = ret_grav->client_grav; return; } static void frame_get_titlebar_dimensions_only( FvwmWindow *fw, rectangle *frame_g, size_borders *bs, rectangle *ret_titlebar_g) { if (!HAS_TITLE(fw)) { return; } switch (GET_TITLE_DIR(fw)) { case DIR_W: case DIR_E: ret_titlebar_g->x = (GET_TITLE_DIR(fw) == DIR_W) ? bs->top_left.width : frame_g->width - bs->bottom_right.width - fw->title_thickness; ret_titlebar_g->y = bs->top_left.height; ret_titlebar_g->width = fw->title_thickness; ret_titlebar_g->height = frame_g->height - bs->total_size.height; break; case DIR_N: case DIR_S: default: /* default makes gcc4 happy */ ret_titlebar_g->y = (GET_TITLE_DIR(fw) == DIR_N) ? bs->top_left.height : frame_g->height - bs->bottom_right.height - fw->title_thickness; ret_titlebar_g->x = bs->top_left.width; ret_titlebar_g->width = frame_g->width - bs->total_size.width; ret_titlebar_g->height = fw->title_thickness; break; } return; } static void frame_setup_border( FvwmWindow *fw, rectangle *frame_g, window_parts setup_parts, rectangle *diff_g) { XWindowChanges xwc; Window w; window_parts part; rectangle sidebar_g; rectangle part_g; Bool dummy; if (HAS_NO_BORDER(fw)) { return; } frame_get_sidebar_geometry( fw, NULL, frame_g, &sidebar_g, &dummy, &dummy); for (part = PART_BORDER_N; (part & PART_FRAME); part <<= 1) { if ((part & PART_FRAME & setup_parts) == PART_NONE) { continue; } border_get_part_geometry(fw, part, &sidebar_g, &part_g, &w); if (part_g.width <= 0 || part_g.height <= 0) { xwc.x = -1; xwc.y = -1; xwc.width = 1; xwc.height = 1; } else { xwc.x = part_g.x; xwc.y = part_g.y; xwc.width = part_g.width; xwc.height = part_g.height; } if (diff_g != NULL) { if (part == PART_BORDER_NE || part == PART_BORDER_E || part == PART_BORDER_SE) { xwc.x -= diff_g->width; } if (part == PART_BORDER_SW || part == PART_BORDER_S || part == PART_BORDER_SE) { xwc.y -= diff_g->height; } } XConfigureWindow(dpy, w, CWWidth | CWHeight | CWX | CWY, &xwc); } return; } static void frame_setup_titlebar( FvwmWindow *fw, rectangle *frame_g, window_parts setup_parts, rectangle *diff_g) { frame_title_layout_t title_layout; int i; if (!HAS_TITLE(fw)) { return; } frame_get_titlebar_dimensions(fw, frame_g, diff_g, &title_layout); /* configure buttons */ for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; i++) { if (FW_W_BUTTON(fw, i) != None && (setup_parts & PART_BUTTONS)) { XMoveResizeWindow( dpy, FW_W_BUTTON(fw, i), title_layout.button_g[i].x, title_layout.button_g[i].y, title_layout.button_g[i].width, title_layout.button_g[i].height); } } /* configure title */ if (setup_parts & PART_TITLE) { XMoveResizeWindow( dpy, FW_W_TITLE(fw), title_layout.title_g.x, title_layout.title_g.y, title_layout.title_g.width, title_layout.title_g.height); } return; } static void __frame_setup_window( FvwmWindow *fw, rectangle *frame_g, Bool do_send_configure_notify, Bool do_force, Bool is_application_request) { frame_move_resize_args mr_args; Bool is_resized = False; Bool is_moved = False; rectangle new_g; new_g = *frame_g; /* sanity checks */ if (new_g.width < 1) { new_g.width = 1; } if (new_g.height < 1) { new_g.height = 1; } /* set some flags */ if (new_g.width != fw->g.frame.width || new_g.height != fw->g.frame.height) { is_resized = True; } if (new_g.x != fw->g.frame.x || new_g.y != fw->g.frame.y) { is_moved = True; } /* setup the window */ if (is_resized || do_force) { frame_move_resize_mode mode; if (is_application_request) { mode = FRAME_MR_SETUP_BY_APP; } else if (do_force) { mode = FRAME_MR_FORCE_SETUP; } else { mode = FRAME_MR_SETUP; } mr_args = frame_create_move_resize_args( fw, mode, NULL, &new_g, 0, DIR_NONE); frame_move_resize(fw, mr_args); ((mr_args_internal *)mr_args)->flags.was_moved = 0; frame_free_move_resize_args(fw, mr_args); fw->g.frame = *frame_g; } else if (is_moved) { unsigned int draw_parts = PART_NONE; /* inform the application of the change * * According to the July 27, 1988 ICCCM draft, we should send a * synthetic ConfigureNotify event to the client if the window * was moved but not resized. */ XMoveWindow(dpy, FW_W_FRAME(fw), frame_g->x, frame_g->y); fw->g.frame = *frame_g; if ((draw_parts = border_get_transparent_decorations_part(fw)) != PART_NONE) { border_draw_decorations( fw, draw_parts, ((fw == get_focus_window())) ? True : False, True, CLEAR_ALL, NULL, NULL); } fw->g.frame = *frame_g; do_send_configure_notify = True; } /* must not send events to shaded windows because this might cause them * to look at their current geometry */ if (do_send_configure_notify && !IS_SHADED(fw)) { SendConfigureNotify( fw, new_g.x, new_g.y, new_g.width, new_g.height, 0, True); } /* get things updated */ XFlush(dpy); if (is_moved || is_resized) { /* inform the modules of the change */ BroadcastConfig(M_CONFIGURE_WINDOW,fw); } return; } static void frame_reparent_hide_windows( Window w) { int i; hide_wins.parent = w; for (i = 0; i < 4 ; i++) { if (w == Scr.Root) { XUnmapWindow(dpy, hide_wins.w[i]); } XReparentWindow(dpy, hide_wins.w[i], w, -1, -1); } if (w != Scr.Root) { XRaiseWindow(dpy, hide_wins.w[0]); XRestackWindows(dpy, hide_wins.w, 4); } return; } /* Returns True if the frame is so small that the parent window would have a * width or height smaller than one pixel. */ static Bool frame_is_parent_hidden( FvwmWindow *fw, rectangle *frame_g) { size_borders b; get_window_borders(fw, &b); if (frame_g->width <= b.total_size.width || frame_g->height <= b.total_size.height) { return True; } return False; } /* Returns the number of pixels that the title bar is too short to accomodate * all the title buttons and a title window that has at least a length of one * pixel. */ static int frame_get_titlebar_compression( FvwmWindow *fw, rectangle *frame_g) { size_borders b; int space; int need_space; if (!HAS_TITLE(fw)) { return 0; } get_window_borders(fw, &b); if (HAS_VERTICAL_TITLE(fw)) { space = frame_g->height - b.total_size.height; } else { space = frame_g->width - b.total_size.width; } need_space = (fw->nr_left_buttons + fw->nr_right_buttons) * fw->title_thickness + MIN_WINDOW_TITLE_LENGTH; if (space < need_space) { return need_space - space; } return 0; } /* Calculates the gravities for the various parts of the decor through ret_grav. * This can be passed to frame_set_decor_gravities. * * title_dir * The direction of the title in the frame. * rmode * The mode for the resize operation */ static void frame_get_resize_decor_gravities( frame_decor_gravities_type *ret_grav, direction_t title_dir, frame_move_resize_mode rmode, rectangle *delta_g) { frame_decor_gravities_type grav_x; frame_decor_gravities_type grav_y; direction_t title_dir_x; direction_t title_dir_y; gravity_split_xy_dir(&title_dir_x, &title_dir_y, title_dir); get_resize_decor_gravities_one_axis( &grav_x, title_dir_x, rmode, DIR_W, DIR_E, (delta_g->x != 0)); get_resize_decor_gravities_one_axis( &grav_y, title_dir_y, rmode, DIR_N, DIR_S, (delta_g->y != 0)); combine_gravities(ret_grav, &grav_x, &grav_y); return; } /* sets the gravity for the various parts of the window */ static void frame_set_decor_gravities( FvwmWindow *fw, frame_decor_gravities_type *grav, int do_set1_restore2_bit_gravity) { int valuemask; XSetWindowAttributes xcwa; int i; Bool button_reverted = False; /* using bit gravity can reduce redrawing dramatically */ valuemask = CWWinGravity; xcwa.win_gravity = grav->client_grav; if (do_set1_restore2_bit_gravity == 1) { XWindowAttributes xwa; if (!fw->attr_backup.is_bit_gravity_stored && XGetWindowAttributes(dpy, FW_W(fw), &xwa)) { fw->attr_backup.bit_gravity = xwa.bit_gravity; } fw->attr_backup.is_bit_gravity_stored = 1; valuemask |= CWBitGravity; xcwa.bit_gravity = grav->client_grav; } else if (do_set1_restore2_bit_gravity == 2) { fw->attr_backup.is_bit_gravity_stored = 0; valuemask |= CWBitGravity; xcwa.bit_gravity = fw->attr_backup.bit_gravity; } XChangeWindowAttributes(dpy, FW_W(fw), valuemask, &xcwa); xcwa.win_gravity = grav->parent_grav; valuemask = CWWinGravity; XChangeWindowAttributes(dpy, FW_W_PARENT(fw), valuemask, &xcwa); if (!HAS_TITLE(fw)) { return; } xcwa.win_gravity = grav->title_grav; XChangeWindowAttributes(dpy, FW_W_TITLE(fw), valuemask, &xcwa); if (fw->title_text_rotation == ROTATION_270 || fw->title_text_rotation == ROTATION_180) { button_reverted = True; } if (button_reverted) { xcwa.win_gravity = grav->rbutton_grav; } else { xcwa.win_gravity = grav->lbutton_grav; } for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; i += 2) { if (FW_W_BUTTON(fw, i)) { XChangeWindowAttributes( dpy, FW_W_BUTTON(fw, i), valuemask, &xcwa); } } if (button_reverted) { xcwa.win_gravity = grav->lbutton_grav; } else { xcwa.win_gravity = grav->rbutton_grav; } for (i = 1; i < NUMBER_OF_TITLE_BUTTONS; i += 2) { if (FW_W_BUTTON(fw, i)) { XChangeWindowAttributes( dpy, FW_W_BUTTON(fw, i), valuemask, &xcwa); } } return; } /* Just restore the win and bit gravities on the client window. */ static void frame_restore_client_gravities(FvwmWindow *fw) { XSetWindowAttributes xcwa; long valuemask; valuemask = CWWinGravity; if (fw->attr_backup.is_bit_gravity_stored) { fw->attr_backup.is_bit_gravity_stored = 0; xcwa.bit_gravity = fw->attr_backup.bit_gravity; valuemask |= CWBitGravity; } xcwa.win_gravity = fw->hints.win_gravity; XChangeWindowAttributes(dpy, FW_W(fw), valuemask, &xcwa); return; } /* Prepares the structure for the next animation step. */ static void frame_next_move_resize_args( frame_move_resize_args mr_args) { mr_args_internal *mra; mra = (mr_args_internal *)mr_args; mra->curr_sidebar_g = mra->next_sidebar_g; mra->current_g = mra->next_g; mra->step_flags.was_hidden = mra->step_flags.is_hidden; mra->curr_titlebar_compression = mra->next_titlebar_compression; return; } static rectangle *frame_get_hidden_pos( FvwmWindow *fw, mr_args_internal *mra, Bool do_unhide, rectangle *ret_hidden_g) { rectangle *target_g; direction_t dir_x; direction_t dir_y; if (do_unhide == False) { gravity_split_xy_dir(&dir_x, &dir_y, mra->shade_dir); ret_hidden_g->x = (dir_x == DIR_E) ? -mra->client_g.width + mra->parent_s.width : 0; ret_hidden_g->y = (dir_y == DIR_S) ? -mra->client_g.height + mra->parent_s.height : 0; target_g = &mra->next_g; } else { gravity_split_xy_dir(&dir_x, &dir_y, SHADED_DIR(fw)); if (mra->mode == FRAME_MR_SCROLL) { ret_hidden_g->x = (dir_x == DIR_W) ? -mra->client_g.width + mra->parent_s.width : 0; ret_hidden_g->y = (dir_y == DIR_N) ? -mra->client_g.height + mra->parent_s.height : 0; } else { ret_hidden_g->x = (dir_x == DIR_E) ? -mra->client_g.width + mra->parent_s.width : 0; ret_hidden_g->y = (dir_y == DIR_S) ? -mra->client_g.height + mra->parent_s.height : 0; } target_g = &mra->next_g; } return target_g; } static void frame_update_hidden_window_pos( FvwmWindow *fw, mr_args_internal *mra, Bool do_unhide) { rectangle *target_g; rectangle hidden_g; target_g = frame_get_hidden_pos(fw, mra, do_unhide, &hidden_g); XMoveResizeWindow( dpy, FW_W_PARENT(fw), mra->b_g.top_left.width, mra->b_g.top_left.height, max(1, target_g->width - mra->b_g.total_size.width), max(1, target_g->height - mra->b_g.total_size.height)); XMoveResizeWindow( dpy, FW_W(fw), hidden_g.x, hidden_g.y, mra->client_g.width, mra->client_g.height); mra->flags.was_moved = 1; return; } static void frame_prepare_animation_shape( FvwmWindow *fw, mr_args_internal *mra, int parent_x, int parent_y) { rectangle parent_g; rectangle client_g; if (!FShapesSupported) { return; } parent_g.x = parent_x; parent_g.y = parent_y; parent_g.width = mra->parent_s.width; parent_g.height = mra->parent_s.height; gravity_move_resize_parent_child( mra->grav.parent_grav, &mra->dstep_g, &parent_g); client_g = mra->client_g; frame_get_hidden_pos(fw, mra, True, &client_g); client_g.x += parent_g.x; client_g.y += parent_g.y; FShapeCombineShape( dpy, Scr.NoFocusWin, FShapeBounding, client_g.x, client_g.y, FW_W(fw), FShapeBounding, FShapeSet); if (HAS_TITLE(fw)) { rectangle tb_g; XRectangle rect; SUPPRESS_UNUSED_VAR_WARNING(rect); frame_get_titlebar_dimensions_only( fw, &mra->next_g, &mra->b_no_title_g, &tb_g); /* windows w/ titles */ rect.x = tb_g.x; rect.y = tb_g.y; rect.width = tb_g.width; rect.height = tb_g.height; FShapeCombineRectangles( dpy, Scr.NoFocusWin, FShapeBounding, 0, 0, &rect, 1, FShapeUnion, Unsorted); } return; } static void frame_mrs_prepare_vars( FvwmWindow *fw, mr_args_internal *mra) { Bool dummy; int i; /* preparations */ i = mra->current_step; mra->next_g = mra->start_g; mra->next_g.x += (mra->delta_g.x * i) / mra->anim_steps; mra->next_g.y += (mra->delta_g.y * i) / mra->anim_steps; mra->next_g.width += (mra->delta_g.width * i) / mra->anim_steps; mra->next_g.height += (mra->delta_g.height * i) / mra->anim_steps; frame_get_sidebar_geometry( fw, NULL, &mra->next_g, &mra->next_sidebar_g, &dummy, &dummy); fvwmrect_subtract_rectangles( &mra->dstep_g, &mra->next_g, &mra->current_g); mra->next_titlebar_compression = frame_get_titlebar_compression(fw, &mra->next_g); mra->step_flags.is_hidden = (frame_is_parent_hidden(fw, &mra->next_g) == True); mra->step_flags.do_hide_parent = ((!mra->step_flags.was_hidden || mra->flags.do_force) && mra->step_flags.is_hidden); mra->step_flags.do_unhide_parent = ((mra->step_flags.was_hidden || mra->flags.do_force) && !mra->step_flags.is_hidden); /* get the parent's dimensions */ mra->parent_s.width = mra->next_g.width - mra->b_g.total_size.width; if (mra->parent_s.width < 1) { mra->minimal_w_offset = 1 - mra->parent_s.width; mra->parent_s.width = 1; } else { mra->minimal_w_offset = 0; } mra->parent_s.height = mra->next_g.height - mra->b_g.total_size.height; if (mra->parent_s.height < 1) { mra->minimal_h_offset = 1 - mra->parent_s.height; mra->parent_s.height = 1; } else { mra->minimal_h_offset = 0; } return; } static void frame_mrs_hide_changing_parts( mr_args_internal *mra) { int l_add; int t_add; int r_add; int b_add; int w; int h; t_add = 0; l_add = 0; b_add = 0; r_add = 0; if (mra->mode == FRAME_MR_SHRINK) { if (mra->dstep_g.x > 0) { l_add = mra->dstep_g.x; } if (mra->dstep_g.y > 0) { t_add = mra->dstep_g.y; } } else if (mra->mode == FRAME_MR_SCROLL) { if (mra->dstep_g.x == 0 && mra->dstep_g.width < 0) { l_add = -mra->dstep_g.width; } if (mra->dstep_g.y == 0 && mra->dstep_g.height < 0) { t_add = -mra->dstep_g.height; } } if (l_add > 0) { l_add -= mra->minimal_w_offset; } else { r_add = (mra->dstep_g.width < 0) ? -mra->dstep_g.width : 0; r_add -= mra->minimal_w_offset; } if (t_add > 0) { t_add -= mra->minimal_h_offset; } else { b_add = (mra->dstep_g.height < 0) ? -mra->dstep_g.height : 0; b_add -= mra->minimal_h_offset; } /* cover top border */ w = mra->current_g.width; h = mra->b_g.top_left.height + t_add; if (w > 0 && h > 0) { XMoveResizeWindow(dpy, hide_wins.w[0], 0, 0, w, h); XMapWindow(dpy, hide_wins.w[0]); } /* cover left border */ w = mra->b_g.top_left.width + l_add; h = mra->current_g.height; if (w > 0 && h > 0) { XMoveResizeWindow(dpy, hide_wins.w[1], 0, 0, w, h); XMapWindow(dpy, hide_wins.w[1]); } /* cover bottom border and possibly part of the client */ w = mra->current_g.width; h = mra->b_g.bottom_right.height + b_add; if (w > 0 && h > 0) { XMoveResizeWindow( dpy, hide_wins.w[2], 0, mra->current_g.height - mra->b_g.bottom_right.height - b_add, w, h); XMapWindow(dpy, hide_wins.w[2]); } /* cover right border and possibly part of the client */ w = mra->b_g.bottom_right.width + r_add; h = mra->current_g.height; if (w > 0 && h > 0) { XMoveResizeWindow( dpy, hide_wins.w[3], mra->current_g.width - mra->b_g.bottom_right.width - r_add, 0, w, h); XMapWindow(dpy, hide_wins.w[3]); } return; } static void frame_mrs_hide_unhide_parent( FvwmWindow *fw, mr_args_internal *mra) { XSetWindowAttributes xswa; if (mra->step_flags.do_unhide_parent) { Window w[2]; /* update the hidden position of the client */ frame_update_hidden_window_pos(fw, mra, True); w[0] = hide_wins.w[3]; w[1] = FW_W_PARENT(fw); XRestackWindows(dpy, w, 2); } else if (mra->step_flags.do_hide_parent) { /* When the parent gets hidden, unmap it automatically, lower * it while hidden, then remap it. Necessary to eliminate * flickering. */ xswa.win_gravity = UnmapGravity; XChangeWindowAttributes( dpy, FW_W_PARENT(fw), CWWinGravity, &xswa); } return; } static void frame_mrs_hide_unhide_parent2( FvwmWindow *fw, mr_args_internal *mra) { XSetWindowAttributes xswa; /* finish hiding the parent */ if (mra->step_flags.do_hide_parent) { xswa.win_gravity = mra->grav.parent_grav; XChangeWindowAttributes( dpy, FW_W_PARENT(fw), CWWinGravity, &xswa); /* update the hidden position of the client */ frame_update_hidden_window_pos(fw, mra, False); XLowerWindow(dpy, FW_W_PARENT(fw)); XMapWindow(dpy, FW_W_PARENT(fw)); } return; } static void frame_mrs_setup_draw_decorations( FvwmWindow *fw, mr_args_internal *mra) { window_parts setup_parts; /* setup the title bar and the border */ setup_parts = PART_TITLE; if (mra->curr_titlebar_compression != mra->next_titlebar_compression || mra->mode == FRAME_MR_FORCE_SETUP) { setup_parts |= PART_BUTTONS; } frame_setup_titlebar(fw, &mra->next_g, setup_parts, &mra->dstep_g); frame_setup_border(fw, &mra->next_g, PART_ALL, &mra->dstep_g); /* draw the border and the titlebar */ if (mra->flags.do_not_draw == 1) { /* nothing */ } else if (!mra->flags.is_shading || !mra->flags.is_lazy_shading) { /* draw as usual */ border_draw_decorations( fw, PART_ALL, (mra->w_with_focus != None) ? True : False, (mra->flags.do_force) ? True : False, CLEAR_ALL, &mra->current_g, &mra->next_g); } else /* lazy shading */ { /* Lazy shading relies on the proper window gravities and does * not redraw the decorations during the animation. Only draw * on the first step. */ if (mra->current_step == 1) { rectangle lazy_g; /* Use the larger width and height values from the * current and the final geometry to get proper * decorations. */ lazy_g.x = mra->current_g.x; lazy_g.y = mra->current_g.y; lazy_g.width = max( mra->current_g.width, mra->end_g.width); lazy_g.height = max( mra->current_g.height, mra->end_g.height); border_draw_decorations( fw, PART_ALL, (mra->w_with_focus != None) ? True : False, True, CLEAR_ALL, &mra->current_g, &lazy_g); } } return; } static void frame_mrs_resize_move_windows( FvwmWindow *fw, mr_args_internal *mra) { /* setup the parent, the frame and the client window */ if (!mra->flags.is_shading) { if (!mra->step_flags.is_hidden && !mra->flags.do_not_configure_client) { XMoveResizeWindow( dpy, FW_W(fw), 0, 0, mra->parent_s.width, mra->parent_s.height); mra->client_g.width = mra->parent_s.width; mra->client_g.height = mra->parent_s.height; } else { XMoveWindow(dpy, FW_W(fw), 0, 0); } mra->flags.was_moved = 1; #if 0 /* reduces flickering */ /* dv (11-Aug-2002): ... and slows down large scripts * dramatically. Rather let it flicker */ if (mra->flags.is_setup) { usleep(1000); } #endif XSync(dpy, 0); XMoveResizeWindow( dpy, FW_W_PARENT(fw), mra->b_g.top_left.width, mra->b_g.top_left.height, mra->parent_s.width, mra->parent_s.height); } else { int x; int y; x = mra->b_g.top_left.width; y = mra->b_g.top_left.height; if (mra->mode == FRAME_MR_SCROLL) { if (mra->dstep_g.x == 0) { x -= mra->dstep_g.width - mra->minimal_w_offset; } if (mra->dstep_g.y == 0) { y -= mra->dstep_g.height - mra->minimal_h_offset;; } } else if (mra->mode == FRAME_MR_SHRINK) { x += mra->dstep_g.x; y += mra->dstep_g.y; } if (x > 0) { x -= mra->minimal_w_offset; } else if (x < 0) { x += mra->minimal_w_offset; } if (y > 0) { y -= mra->minimal_h_offset; } else if (y < 0) { y += mra->minimal_h_offset; } XMoveResizeWindow( dpy, FW_W_PARENT(fw), x, y, mra->parent_s.width, mra->parent_s.height); if (mra->flags.do_update_shape) { /* Step 1: apply the union of the old and new shapes. * This way so that the client stays visible - rather * let the background show through than force an * Expose event. */ frame_prepare_animation_shape(fw, mra, x, y); FShapeCombineShape( dpy, FW_W_FRAME(fw), FShapeBounding, 0, 0, Scr.NoFocusWin, FShapeBounding, FShapeUnion); } } XMoveResizeWindow( dpy, FW_W_FRAME(fw), mra->next_g.x, mra->next_g.y, mra->next_g.width, mra->next_g.height); if (mra->flags.do_update_shape) { /* Step 2: clip the previous shape. */ FShapeCombineShape( dpy, FW_W_FRAME(fw), FShapeBounding, 0, 0, Scr.NoFocusWin, FShapeBounding, FShapeSet); } return; } static void frame_move_resize_step( FvwmWindow *fw, mr_args_internal *mra) { frame_mrs_prepare_vars(fw, mra); frame_mrs_hide_changing_parts(mra); frame_mrs_hide_unhide_parent(fw, mra); frame_mrs_setup_draw_decorations(fw, mra); frame_mrs_resize_move_windows(fw, mra); frame_mrs_hide_unhide_parent2(fw, mra); fw->g.frame = mra->next_g; return; } static void frame_has_handles_and_tiled_border( FvwmWindow *fw, int *ret_has_handles, int *ret_has_tiled_border) { DecorFace *df; *ret_has_handles = 1; if (!HAS_HANDLES(fw)) { *ret_has_handles = 0; } df = border_get_border_style(fw, (fw == Scr.Hilite) ? True : False); if (DFS_HAS_HIDDEN_HANDLES(df->style)) { *ret_has_handles = 0; } *ret_has_tiled_border = (DFS_FACE_TYPE(df->style) == TiledPixmapButton) || (DFS_FACE_TYPE(df->style) == ColorsetButton && !CSET_IS_TRANSPARENT_PR(df->u.acs.cs) && CSET_HAS_PIXMAP(df->u.acs.cs)); return; } static int frame_get_shading_laziness( FvwmWindow *fw, mr_args_internal *mra) { int has_handles; int has_tiled_pixmap_border; int using_border_style; if (!mra->flags.is_shading || mra->anim_steps <= 2) { return 0; } frame_has_handles_and_tiled_border( fw, &has_handles, &has_tiled_pixmap_border); if (HAS_TITLE(fw) && has_tiled_pixmap_border) { using_border_style = border_is_using_border_style( fw, (fw == Scr.Hilite) ? True : False); } else { using_border_style = 0; } switch (WINDOWSHADE_LAZINESS(fw)) { case WINDOWSHADE_ALWAYS_LAZY: return 1; case WINDOWSHADE_BUSY: if (has_handles) { return 0; } /* fall through */ case WINDOWSHADE_LAZY: default: if (has_tiled_pixmap_border && !HAS_NO_BORDER(fw)) { return 0; } else if (has_tiled_pixmap_border && HAS_TITLE(fw) && using_border_style) { return 0; } return 1; } } void frame_reshape_border(FvwmWindow *fw) { int grav; int off_x = 0; int off_y = 0; rectangle naked_g; rectangle *new_g; /* calculate the new offsets */ if (!IS_MAXIMIZED(fw)) { grav = fw->hints.win_gravity; new_g = &fw->g.normal; } else { /* maximized windows are always considered to have * NorthWestGravity */ grav = NorthWestGravity; new_g = &fw->g.max; off_x = fw->g.normal.x - fw->g.max.x; off_y = fw->g.normal.y - fw->g.max.y; } gravity_get_naked_geometry(grav, fw, &naked_g, new_g); gravity_translate_to_northwest_geometry_no_bw( grav, fw, &naked_g, &naked_g); set_window_border_size(fw, fw->unshaped_boundary_width); gravity_add_decoration(grav, fw, new_g, &naked_g); if (IS_MAXIMIZED(fw)) { /* prevent random paging when unmaximizing after the border * width has changed */ fw->g.max_offset.x += fw->g.normal.x - fw->g.max.x - off_x; fw->g.max_offset.y += fw->g.normal.y - fw->g.max.y - off_y; } if (IS_SHADED(fw)) { get_unshaded_geometry(fw, new_g); if (USED_TITLE_DIR_FOR_SHADING(fw)) { SET_SHADED_DIR(fw, GET_TITLE_DIR(fw)); } get_shaded_geometry(fw, &fw->g.frame, new_g); frame_force_setup_window( fw, fw->g.frame.x, fw->g.frame.y, fw->g.frame.width, fw->g.frame.height, False); } else { get_relative_geometry(new_g, new_g); frame_force_setup_window( fw, new_g->x, new_g->y, new_g->width, new_g->height, True); } return; } /* ---------------------------- interface functions ------------------------ */ /* Initialise structures local to frame.c */ void frame_init(void) { XSetWindowAttributes xswa; unsigned long valuemask; int i; xswa.override_redirect = True; xswa.backing_store = NotUseful; xswa.save_under = False; xswa.win_gravity = UnmapGravity; xswa.background_pixmap = None; valuemask = CWOverrideRedirect | CWSaveUnder | CWBackingStore | CWBackPixmap | CWWinGravity; hide_wins.parent = Scr.Root; for (i = 0; i < 4; i++) { hide_wins.w[i] = XCreateWindow( dpy, Scr.Root, -1, -1, 1, 1, 0, CopyFromParent, InputOutput, CopyFromParent, valuemask, &xswa); if (hide_wins.w[i] == None) { fvwm_msg(ERR, "frame_init", "Could not create internal windows. Exiting"); MyXUngrabServer(dpy); exit(1); } } return; } Bool is_frame_hide_window( Window w) { int i; if (w == None) { return False; } for (i = 0; i < 4; i++) { if (w == hide_wins.w[i]) { return True; } } return False; } void frame_destroyed_frame( Window frame_w) { if (hide_wins.parent == frame_w) { /* Oops, the window containing the hide windows was destroyed! * Let it die and create them from scratch. */ frame_init(); } return; } void frame_get_titlebar_dimensions( FvwmWindow *fw, rectangle *frame_g, rectangle *diff_g, frame_title_layout_t *title_layout) { size_borders b; int i; int tb_length; int tb_thick; int tb_x; int tb_y; int b_length; int b_w; int b_h; int t_length; int t_w; int t_h; int br_sub; int nbuttons; int nbuttons_big; int *padd_coord; int *b_l; Bool revert_button = False; if (!HAS_TITLE(fw)) { return; } get_window_borders_no_title(fw, &b); if (HAS_VERTICAL_TITLE(fw)) { tb_length = frame_g->height - b.total_size.height; } else { tb_length = frame_g->width - b.total_size.width; } /* find out the length of the title and the buttons */ tb_thick = fw->title_thickness; nbuttons = fw->nr_left_buttons + fw->nr_right_buttons; nbuttons_big = 0; b_length = tb_thick; t_length = tb_length - nbuttons * b_length; if (nbuttons > 0 && t_length < MIN_WINDOW_TITLE_LENGTH) { int diff = MIN_WINDOW_TITLE_LENGTH - t_length; int pixels = diff / nbuttons; b_length -= pixels; t_length += nbuttons * pixels; nbuttons_big = nbuttons - (MIN_WINDOW_TITLE_LENGTH - t_length); t_length = MIN_WINDOW_TITLE_LENGTH; } if (b_length < MIN_WINDOW_TITLEBUTTON_LENGTH) { /* don't draw the buttons */ nbuttons = 0; nbuttons_big = 0; b_length = 0; t_length = tb_length; } if (t_length < 0) { t_length = 0; } fw->title_length = t_length; /* prepare variables */ if (HAS_VERTICAL_TITLE(fw)) { tb_y = b.top_left.height; br_sub = (diff_g != NULL) ? diff_g->height : 0; if (GET_TITLE_DIR(fw) == DIR_W) { tb_x = b.top_left.width; } else { tb_x = frame_g->width - b.bottom_right.width - tb_thick; if (diff_g != NULL) { tb_x -= diff_g->width; } } padd_coord = &tb_y; b_w = tb_thick; b_h = b_length; t_w = tb_thick; t_h = t_length; b_l = &b_h; } else { tb_x = b.top_left.width; br_sub = (diff_g != NULL) ? diff_g->width : 0; if (GET_TITLE_DIR(fw) == DIR_N) { tb_y = b.top_left.height; } else { tb_y = frame_g->height - b.bottom_right.height - tb_thick; if (diff_g != NULL) { tb_y -= diff_g->height; } } padd_coord = &tb_x; b_w = b_length; b_h = tb_thick; t_w = t_length; t_h = tb_thick; b_l = &b_w; } if (fw->title_text_rotation == ROTATION_270 || fw->title_text_rotation == ROTATION_180) { revert_button = True; } /* configure left buttons */ for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; i++) { if ((revert_button && !(i & 1)) || (!revert_button && (i & 1)) || FW_W_BUTTON(fw, i) == None) { continue; } if (b_length <= 0) { title_layout->button_g[i].x = -1; title_layout->button_g[i].y = -1; title_layout->button_g[i].width = 1; title_layout->button_g[i].height = 1; } else { title_layout->button_g[i].x = tb_x; title_layout->button_g[i].y = tb_y; title_layout->button_g[i].width = b_w; title_layout->button_g[i].height = b_h; } *padd_coord += b_length; nbuttons_big--; if (nbuttons_big == 0) { b_length--; (*b_l)--; } } /* configure title */ if (t_length == 0) { title_layout->title_g.x = -1; title_layout->title_g.y = -1; title_layout->title_g.width = 1; title_layout->title_g.height = 1; } else { title_layout->title_g.x = tb_x; title_layout->title_g.y = tb_y; title_layout->title_g.width = t_w; title_layout->title_g.height = t_h; } *padd_coord += t_length; /* configure right buttons */ *padd_coord -= br_sub; for (i = NUMBER_OF_TITLE_BUTTONS-1; i > -1; i--) { if ((revert_button && (i & 1)) || (!revert_button && !(i & 1)) || FW_W_BUTTON(fw, i) == None) { continue; } if (b_length <= 0) { title_layout->button_g[i].x = -1; title_layout->button_g[i].y = -1; title_layout->button_g[i].width = 1; title_layout->button_g[i].height = 1; } else { title_layout->button_g[i].x = tb_x; title_layout->button_g[i].y = tb_y; title_layout->button_g[i].width = b_w; title_layout->button_g[i].height = b_h; } *padd_coord += b_length; nbuttons_big--; if (nbuttons_big == 0) { b_length--; (*b_l)--; } } return; } void frame_get_sidebar_geometry( FvwmWindow *fw, DecorFaceStyle *borderstyle, rectangle *frame_g, rectangle *ret_g, Bool *ret_has_x_marks, Bool *ret_has_y_marks) { int min_w; size_borders b; ret_g->x = 0; ret_g->y = 0; ret_g->width = 0; ret_g->height = 0; *ret_has_x_marks = False; *ret_has_y_marks = False; if (HAS_NO_BORDER(fw)) { return; } /* get the corner size */ if (!HAS_HANDLES(fw)) { *ret_has_x_marks = False; *ret_has_y_marks = False; } else if (borderstyle == NULL) { if (fw->decor_state.parts_drawn & PART_X_HANDLES) { *ret_has_x_marks = True; } if (fw->decor_state.parts_drawn & PART_Y_HANDLES) { *ret_has_y_marks = True; } } else if (!DFS_HAS_HIDDEN_HANDLES(*borderstyle)) { *ret_has_x_marks = True; *ret_has_y_marks = True; } ret_g->x = fw->corner_width; ret_g->y = fw->corner_width; min_w = 2 * fw->corner_width + 4; /* limit by available space, remove handle marks if necessary */ if (frame_g->width < min_w) { ret_g->x = frame_g->width / 3; *ret_has_y_marks = False; } if (frame_g->height < min_w) { ret_g->y = frame_g->height / 3; *ret_has_x_marks = False; } get_window_borders_no_title(fw, &b); if (ret_g->x < b.top_left.width) { ret_g->x = b.top_left.width; } if (ret_g->y < b.top_left.height) { ret_g->y = b.top_left.height; } /* length of the side bars */ ret_g->width = frame_g->width - 2 * ret_g->x; ret_g->height = frame_g->height - 2 * ret_g->y; return; } int frame_window_id_to_context( FvwmWindow *fw, Window w, int *ret_num) { int context = C_ROOT; *ret_num = -1; if (fw == NULL || w == None) { return C_ROOT; } if (w == FW_W_TITLE(fw)) { context = C_TITLE; } else if (Scr.EwmhDesktop && (w == FW_W(Scr.EwmhDesktop) || w == FW_W_PARENT(Scr.EwmhDesktop) || w == FW_W_FRAME(Scr.EwmhDesktop))) { context = C_EWMH_DESKTOP; } else if (w == FW_W(fw) || w == FW_W_PARENT(fw) || w == FW_W_FRAME(fw)) { context = C_WINDOW; } else if (w == FW_W_ICON_TITLE(fw) || w == FW_W_ICON_PIXMAP(fw)) { context = C_ICON; } else if (w == FW_W_CORNER(fw, 0)) { *ret_num = 0; context = C_F_TOPLEFT; } else if (w == FW_W_CORNER(fw, 1)) { *ret_num = 1; context = C_F_TOPRIGHT; } else if (w == FW_W_CORNER(fw, 2)) { *ret_num = 2; context = C_F_BOTTOMLEFT; } else if (w == FW_W_CORNER(fw, 3)) { *ret_num = 3; context = C_F_BOTTOMRIGHT; } else if (w == FW_W_SIDE(fw, 0)) { *ret_num = 0; context = C_SB_TOP; } else if (w == FW_W_SIDE(fw, 1)) { *ret_num = 1; context = C_SB_RIGHT; } else if (w == FW_W_SIDE(fw, 2)) { *ret_num = 2; context = C_SB_BOTTOM; } else if (w == FW_W_SIDE(fw, 3)) { *ret_num = 3; context = C_SB_LEFT; } else { int i; for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; i++) { if (w == FW_W_BUTTON(fw, i) && ((!(i & 1) && i / 2 < Scr.nr_left_buttons) || ( (i & 1) && i / 2 < Scr.nr_right_buttons))) { context = (1 << i) * C_L1; *ret_num = i; break; } } } if (!HAS_HANDLES(fw) && (context & (C_SIDEBAR | C_FRAME))) { context = C_SIDEBAR; } return context; } /* Creates a structure that must be passed to frame_move_resize(). The * structure *must* be deleted with frame_free_move_resize_args() as soon as the * move or resize operation is finished. Prepares the window for a move/resize * operation. * * Arguments: * fw * The window to move or resize. * mr_mode * The mode of operation: * FRAME_MR_SETUP: setup the frame * FRAME_MR_FORCE_SETUP: same, but forces all updates * FRAME_MR_OPAQUE: resize the frame in an opaque fashion * FRAME_MR_SHRINK: shrink the client window (useful for shading only) * FRAME_MR_SCROLL: scroll the client window (useful for shading only) * start_g * The initial geometry of the frame. If a NULL pointer is passed, the * frame_g member of the window is used instead. * end_g * The desired new geometry of the frame. * anim_steps * The number of animation steps in between * = 0: The operation is finished in a single step. * > 0: The given number of steps are drawn in between. * < 0: Each step resizes the window by the given number of pixels. * (the sign of the number is flipped first). * This argument is used only with FRAME_MR_SHRINK and FRAME_MR_SCROLL. */ frame_move_resize_args frame_create_move_resize_args( FvwmWindow *fw, frame_move_resize_mode mr_mode, rectangle *start_g, rectangle *end_g, int anim_steps, int shade_dir) { mr_args_internal *mra; Bool dummy; Bool rc; int whdiff; int xydiff; int diff; /* set some variables */ mra = (mr_args_internal *)safecalloc(1, sizeof(mr_args_internal)); memset(mra, 0, sizeof(*mra)); if (mr_mode & FRAME_MR_DONT_DRAW) { mr_mode &= ~FRAME_MR_DONT_DRAW; mra->flags.do_not_draw = 1; } else { mra->flags.do_not_draw = 0; } if (mr_mode == FRAME_MR_SETUP_BY_APP) { mr_mode = FRAME_MR_SETUP; mra->flags.do_set_bit_gravity = 0; } else { mra->flags.do_set_bit_gravity = 1; } if (mr_mode == FRAME_MR_FORCE_SETUP_NO_W) { mr_mode = FRAME_MR_FORCE_SETUP; mra->flags.do_not_configure_client = 1; } mra->mode = mr_mode; mra->shade_dir = (direction_t)shade_dir; mra->w_with_focus = (fw == get_focus_window()) ? FW_W(fw) : None; /* calculate various geometries */ if (!IS_SHADED(fw)) { rc = XGetGeometry( dpy, FW_W(fw), &JunkRoot, &mra->client_g.x, &mra->client_g.y, (unsigned int*)&mra->client_g.width, (unsigned int*)&mra->client_g.height, (unsigned int*)&JunkBW, (unsigned int*)&JunkDepth); if (rc == True) { rc = XTranslateCoordinates( dpy, FW_W_PARENT(fw), Scr.Root, mra->client_g.x, mra->client_g.y, &mra->client_g.x, &mra->client_g.y, &JunkChild); } if (rc == False) { /* Can only happen if the window died */ get_client_geometry(fw, &mra->client_g); } } else { /* If the window was reisez while shaded the client window * will not have been resized. Use the frame to get the * geometry */ get_client_geometry(fw, &mra->client_g); } get_window_borders(fw, &mra->b_g); get_window_borders_no_title(fw, &mra->b_no_title_g); mra->start_g = (start_g != NULL) ? *start_g : fw->g.frame; frame_get_sidebar_geometry( fw, NULL, &mra->start_g, &mra->curr_sidebar_g, &dummy, &dummy); mra->end_g = *end_g; mra->current_g = mra->start_g; mra->next_g = mra->end_g; mra->curr_titlebar_compression = frame_get_titlebar_compression(fw, &mra->start_g); fvwmrect_subtract_rectangles( &mra->delta_g, &mra->end_g, &mra->start_g); /* calcuate the number of animation steps */ switch (mra->mode) { case FRAME_MR_SHRINK: case FRAME_MR_SCROLL: whdiff = max(abs(mra->delta_g.width), abs(mra->delta_g.height)); xydiff = max(abs(mra->delta_g.x), abs(mra->delta_g.y)); diff = max(whdiff, xydiff); if (diff == 0) { mra->anim_steps = 0; } else if (anim_steps < 0) { mra->anim_steps = -(diff - 1) / anim_steps; } else if (anim_steps > 0 && anim_steps >= diff) { mra->anim_steps = diff - 1; } else { mra->anim_steps = anim_steps; } mra->anim_steps++; break; case FRAME_MR_FORCE_SETUP: case FRAME_MR_SETUP: case FRAME_MR_OPAQUE: default: mra->anim_steps = 1; break; } /* various flags */ mra->flags.was_moved = 0; mra->step_flags.was_hidden = (frame_is_parent_hidden(fw, &mra->start_g) == True); mra->flags.is_setup = (mra->mode == FRAME_MR_FORCE_SETUP || mra->mode == FRAME_MR_SETUP); mra->flags.do_force = (mra->mode == FRAME_MR_FORCE_SETUP); mra->flags.is_shading = !(mra->flags.is_setup || mra->mode == FRAME_MR_OPAQUE); mra->flags.do_update_shape = (FShapesSupported && mra->flags.is_shading && fw->wShaped); /* Lazy shading does not draw the hadle marks. Disable them in the * window flags if necessary. Restores the marks when mr_args are * freed. Lazy shading is considerably faster but causes funny looks * if either the border uses a tiled pixmap background. */ mra->flags.had_handles = HAS_HANDLES(fw); mra->flags.is_lazy_shading = frame_get_shading_laziness(fw, mra); mra->trans_parts = border_get_transparent_decorations_part(fw); if (mra->flags.is_lazy_shading) { SET_HAS_HANDLES(fw, 0); } /* Set gravities for the window parts. */ frame_get_resize_decor_gravities( &mra->grav, GET_TITLE_DIR(fw), mra->mode, &mra->delta_g); if (mra->flags.is_setup && mra->delta_g.x == 0 && mra->delta_g.y == 0 && mra->delta_g.width == 0 && mra->delta_g.height == 0) { frame_decor_gravities_type grav; /* The caller has already set the frame geometry. Use * StaticGravity so the sub windows are not moved to funny * places. */ grav.decor_grav = StaticGravity; grav.title_grav = StaticGravity; grav.lbutton_grav = StaticGravity; grav.rbutton_grav = StaticGravity; grav.parent_grav = StaticGravity; grav.client_grav = StaticGravity; frame_set_decor_gravities( fw, &grav, (mra->flags.do_set_bit_gravity) ? 1 : 0); mra->flags.do_restore_gravity = 1; mra->flags.do_force = 1; } else { frame_set_decor_gravities( fw, &mra->grav, (mra->flags.do_set_bit_gravity) ? 1 : 0); } frame_reparent_hide_windows(FW_W_FRAME(fw)); return (frame_move_resize_args)mra; } /* Changes the final_geometry in a frame_move_resize_args structure. This is * useful during opaque resize operations to avoid creating and destroying the * args for each animation step. * * If FRAME_MR_SHRINK or FRAME_MR_SCROLL was used to greate the mr_args, the * function does nothing. */ void frame_update_move_resize_args( frame_move_resize_args mr_args, rectangle *end_g) { mr_args_internal *mra; mra = (mr_args_internal *)mr_args; mra->end_g = *end_g; fvwmrect_subtract_rectangles( &mra->delta_g, &mra->end_g, &mra->start_g); return; } /* Destroys the structure allocated with frame_create_move_resize_args(). Does * some clean up operations on the modified window first. */ void frame_free_move_resize_args( FvwmWindow *fw, frame_move_resize_args mr_args) { mr_args_internal *mra; mra = (mr_args_internal *)mr_args; SET_HAS_HANDLES(fw, mra->flags.had_handles); fw->g.frame = mra->end_g; if (mra->flags.is_lazy_shading) { border_draw_decorations( fw, PART_ALL, (mra->w_with_focus != None) ? True : False, True, CLEAR_ALL, &mra->current_g, &mra->end_g); } else if (mra->trans_parts != PART_NONE) { border_draw_decorations( fw, mra->trans_parts, (mra->w_with_focus != None) ? True : False, True, CLEAR_ALL, &mra->current_g, &mra->end_g); } update_absolute_geometry(fw); frame_reparent_hide_windows(Scr.NoFocusWin); if (mra->w_with_focus != None && FP_IS_LENIENT(FW_FOCUS_POLICY(fw))) { /* domivogt (28-Dec-1999): For some reason the XMoveResize() on * the frame window removes the input focus from the client * window. I have no idea why, but if we explicitly restore * the focus here everything works fine. */ FOCUS_SET(mra->w_with_focus, fw); } if (mra->flags.do_update_shape) { /* unset shape */ FShapeCombineMask( dpy, FW_W_FRAME(fw), FShapeBounding, 0, 0, None, FShapeSet); } frame_setup_shape(fw, mra->end_g.width, mra->end_g.height, fw->wShaped); if (mra->flags.do_restore_gravity) { /* TA: 2011-09-04: There might be a chance some clients with * a gravity other than Static (such as non-NW gravity) * might not react well -- but setting the gravity to the * main window hint will break clients being remapped as * subwindows, c.f. XEmbed. * * Note that we should probably consider handling * GravityNotify events ourselves, since we already set * StructureNotify and SubstructureNotify events on * FW_W_PARENT for example. * * mra->grav.client_grav = fw->hints.win_gravity; */ frame_set_decor_gravities( fw, &mra->grav, (mra->flags.do_set_bit_gravity) ? 2 : 0); } else { frame_restore_client_gravities(fw); } if (!IS_SHADED(fw) && mra->flags.was_moved) { SendConfigureNotify( fw, fw->g.frame.x, fw->g.frame.y, fw->g.frame.width, fw->g.frame.height, 0, True); mra->flags.was_moved = 0; } focus_grab_buttons_on_layer(fw->layer); /* free the memory */ free(mr_args); return; } void frame_move_resize( FvwmWindow *fw, frame_move_resize_args mr_args) { mr_args_internal *mra; Bool is_grabbed = False; int i; mra = (mr_args_internal *)mr_args; /* freeze the cursor shape; otherwise it may flash to a different shape * during the animation */ if (mra->anim_steps > 1) { is_grabbed = GrabEm(None, GRAB_FREEZE_CURSOR); } /* animation */ for (i = 1; i <= mra->anim_steps; i++, frame_next_move_resize_args(mra)) { mra->current_step = i; frame_move_resize_step(fw, mra); } if (is_grabbed == True) { UngrabEm(GRAB_FREEZE_CURSOR); } return; } /*********************************************************************** * * Procedure: * frame_setup_window - set window sizes * * Inputs: * fw - the FvwmWindow pointer * x - the x coordinate of the upper-left outer corner of the frame * y - the y coordinate of the upper-left outer corner of the frame * w - the width of the frame window w/o border * h - the height of the frame window w/o border * * Special Considerations: * This routine will check to make sure the window is not completely * off the display, if it is, it'll bring some of it back on. * * The fw->frame_XXX variables should NOT be updated with the * values of x,y,w,h prior to calling this routine, since the new * values are compared against the old to see whether a synthetic * ConfigureNotify event should be sent. (It should be sent if the * window was moved but not resized.) * ************************************************************************/ void frame_setup_window( FvwmWindow *fw, int x, int y, int w, int h, Bool do_send_configure_notify) { rectangle g; g.x = x; g.y = y; g.width = w; g.height = h; __frame_setup_window(fw, &g, do_send_configure_notify, False, False); return; } void frame_setup_window_app_request( FvwmWindow *fw, int x, int y, int w, int h, Bool do_send_configure_notify) { rectangle g; g.x = x; g.y = y; g.width = w; g.height = h; __frame_setup_window(fw, &g, do_send_configure_notify, False, True); return; } void frame_force_setup_window( FvwmWindow *fw, int x, int y, int w, int h, Bool do_send_configure_notify) { rectangle g; g.x = x; g.y = y; g.width = w; g.height = h; __frame_setup_window(fw, &g, do_send_configure_notify, True, False); return; } /**************************************************************************** * * Sets up the shaped window borders * ****************************************************************************/ void frame_setup_shape(FvwmWindow *fw, int w, int h, int shape_mode) { rectangle r; size_borders b; if (!FShapesSupported) { return; } if (fw->wShaped != shape_mode) { fw->wShaped = shape_mode; frame_reshape_border(fw); } if (!shape_mode) { /* unset shape */ FShapeCombineMask( dpy, FW_W_FRAME(fw), FShapeBounding, 0, 0, None, FShapeSet); } else { /* shape the window */ get_window_borders(fw, &b); FShapeCombineShape( dpy, FW_W_FRAME(fw), FShapeBounding, b.top_left.width, b.top_left.height, FW_W(fw), FShapeBounding, FShapeSet); if (FW_W_TITLE(fw)) { XRectangle rect; /* windows w/ titles */ r.width = w; r.height = h; get_title_geometry(fw, &r); rect.x = r.x; rect.y = r.y; rect.width = r.width; rect.height = r.height; SUPPRESS_UNUSED_VAR_WARNING(rect); FShapeCombineRectangles( dpy, FW_W_FRAME(fw), FShapeBounding, 0, 0, &rect, 1, FShapeUnion, Unsorted); } } return; } /* ---------------------------- builtin commands --------------------------- */ fvwm-2.7.0/fvwm/focus.c0000644000175000017500000006532314147024700011672 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include "libs/fvwmlib.h" #include "libs/charmap.h" #include "libs/wcontext.h" #include "libs/ClientMsg.h" #include "libs/Grab.h" #include "libs/Parse.h" #include "libs/Strings.h" #include "fvwm.h" #include "externs.h" #include "execcontext.h" #include "eventhandler.h" #include "bindings.h" #include "misc.h" #include "screen.h" #include "focus.h" #include "borders.h" #include "frame.h" #include "virtual.h" #include "stack.h" #include "geometry.h" #include "colormaps.h" #include "add_window.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ typedef struct { unsigned do_allow_force_broadcast : 1; unsigned do_forbid_warp : 1; unsigned do_force : 1; unsigned is_focus_by_flip_focus_cmd : 1; unsigned client_entered : 1; fpol_set_focus_by_t set_by; } sftfwin_args_t; /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ static Bool lastFocusType; /* Last window which Fvwm gave the focus to NOT the window that really has the * focus */ static FvwmWindow *ScreenFocus = NULL; /* Window which had focus before the pointer moved to a different screen. */ static FvwmWindow *LastScreenFocus = NULL; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ void _focus_set(Window w, FvwmWindow *fw) { Scr.focus_in_requested_window = fw; XSetInputFocus(dpy, w, RevertToParent, CurrentTime); return; } void _focus_reset(void) { Scr.focus_in_requested_window = NULL; XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); return; } /* ---------------------------- local functions ---------------------------- */ static Bool focus_get_fpol_context_flag( fpol_context_t *fpol_context, int context) { int flag; switch (context) { case C_WINDOW: case C_EWMH_DESKTOP: flag = fpol_context->client; break; case C_ICON: flag = fpol_context->icon; break; default: flag = fpol_context->decor; break; } return (flag) ? True : False; } /* * Helper functions for setting the focus */ static void __try_program_focus(Window w, const FvwmWindow *fw) { if (fw && WM_TAKES_FOCUS(fw) && FP_DO_FOCUS_BY_PROGRAM(FW_FOCUS_POLICY(fw))) { send_clientmessage(dpy, w, _XA_WM_TAKE_FOCUS, fev_get_evtime()); } return; } static Bool __try_forbid_user_focus( Window w, FvwmWindow *fw) { if (fw == NULL || fpol_query_allow_user_focus(&FW_FOCUS_POLICY(fw)) == True) { return False; } if (WM_TAKES_FOCUS(fw)) { /* give it a chance to take the focus itself */ __try_program_focus(w, fw); XFlush(dpy); } else { /* make sure the window is not hilighted */ border_draw_decorations( fw, PART_ALL, False, False, CLEAR_ALL, NULL, NULL); } return True; } static Bool __check_allow_focus( Window w, FvwmWindow *fw, fpol_set_focus_by_t set_by) { FvwmWindow *sf; if (fw == NULL || set_by == FOCUS_SET_FORCE) { /* always allow to delete focus */ return True; } sf = get_focus_window(); if (!FP_IS_LENIENT(FW_FOCUS_POLICY(fw)) && !focus_does_accept_input_focus(fw) && sf != NULL && sf->Desk == Scr.CurrentDesk) { /* window does not want focus */ return False; } if (fpol_query_allow_set_focus(&FW_FOCUS_POLICY(fw), set_by)) { return True; } return False; } static void __update_windowlist( FvwmWindow *fw, fpol_set_focus_by_t set_by, int is_focus_by_flip_focus_cmd) { lastFocusType = (is_focus_by_flip_focus_cmd) ? True : False; if (fw == NULL || focus_is_focused(fw) || fw == &Scr.FvwmRoot || IS_SCHEDULED_FOR_DESTROY(fw)) { return; } /* Watch out: fw may not be on the windowlist and the windowlist may be * empty */ if (!is_focus_by_flip_focus_cmd && (FP_DO_SORT_WINDOWLIST_BY(FW_FOCUS_POLICY(fw)) == FPOL_SORT_WL_BY_OPEN || set_by == FOCUS_SET_BY_FUNCTION)) { /* move the windowlist around so that fw is at the top */ FvwmWindow *fw2; /* find the window on the windowlist */ for (fw2 = &Scr.FvwmRoot; fw2 && fw2 != fw; fw2 = fw2->next) { /* nothing */ } if (fw2) { /* the window is on the (non-zero length) windowlist */ /* make fw2 point to the last window on the list */ while (fw2->next) { fw2 = fw2->next; } /* close the ends of the windowlist */ fw2->next = Scr.FvwmRoot.next; Scr.FvwmRoot.next->prev = fw2; /* make fw the new start of the list */ Scr.FvwmRoot.next = fw; /* open the closed loop windowlist */ fw->prev->next = NULL; fw->prev = &Scr.FvwmRoot; } } else { /* pluck window from list and deposit at top */ /* remove fw from list */ if (fw->prev) { fw->prev->next = fw->next; } if (fw->next) { fw->next->prev = fw->prev; } /* insert fw at start */ fw->next = Scr.FvwmRoot.next; if (Scr.FvwmRoot.next) { Scr.FvwmRoot.next->prev = fw; } Scr.FvwmRoot.next = fw; fw->prev = &Scr.FvwmRoot; } return; } static Bool __try_other_screen_focus(const FvwmWindow *fw) { if (fw == NULL && !Scr.flags.is_pointer_on_this_screen) { FvwmWindow *sf; sf = get_focus_window(); set_focus_window(NULL); if (sf != NULL) { focus_grab_buttons(sf); } /* DV (25-Nov-2000): Don't give the Scr.NoFocusWin the focus * here. This would steal the focus from the other screen's * root window again. */ return True; } return False; } /* * Sets the input focus to the indicated window. */ static void __set_focus_to_fwin( Window w, FvwmWindow *fw, sftfwin_args_t *args) { FvwmWindow *sf; if (__try_forbid_user_focus(w, fw) == True) { return; } __try_program_focus(w, fw); if (__check_allow_focus(w, fw, args->set_by) == False) { return; } __update_windowlist(fw, args->set_by, args->is_focus_by_flip_focus_cmd); if (__try_other_screen_focus(fw) == True) { return; } if (fw && !args->do_forbid_warp) { if (IS_ICONIFIED(fw)) { rectangle r; Bool rc; rc = get_visible_icon_geometry(fw, &r); if (!rc || !IsRectangleOnThisPage(&r, fw->Desk)) { fw = NULL; w = Scr.NoFocusWin; } } else if (!IsRectangleOnThisPage(&(fw->g.frame), fw->Desk)) { fw = NULL; w = Scr.NoFocusWin; } } sf = get_focus_window(); if (fw == NULL) { FOCUS_SET(Scr.NoFocusWin, NULL); set_focus_window(NULL); Scr.UnknownWinFocused = None; XFlush(dpy); return; } /* RBW - allow focus to go to a NoIconTitle icon window so * auto-raise will work on it. */ if (IS_ICONIFIED(fw)) { Bool is_window_selected = False; if (FW_W_ICON_TITLE(fw)) { w = FW_W_ICON_TITLE(fw); is_window_selected = True; } if ((!is_window_selected || WAS_ICON_HINT_PROVIDED(fw)) && FW_W_ICON_PIXMAP(fw)) { w = FW_W_ICON_PIXMAP(fw); } } if (FP_IS_LENIENT(FW_FOCUS_POLICY(fw))) { FOCUS_SET(w, fw); set_focus_window(fw); if (args->do_allow_force_broadcast) { SET_FOCUS_CHANGE_BROADCAST_PENDING(fw, 1); } Scr.UnknownWinFocused = None; } else if (focus_does_accept_input_focus(fw)) { /* Window will accept input focus */ if (Scr.StolenFocusWin == w && Scr.UnknownWinFocused != None) { /* Without this FocusIn is not generated on the * window if it was focuesed when the unmanaged * window took focus. */ FOCUS_SET(Scr.NoFocusWin, NULL); } FOCUS_SET(w, fw); set_focus_window(fw); if (fw) { if (args->do_allow_force_broadcast) { SET_FOCUS_CHANGE_BROADCAST_PENDING(fw, 1); } } Scr.UnknownWinFocused = None; } else if (sf && sf->Desk == Scr.CurrentDesk) { /* Window doesn't want focus. Leave focus alone */ } else { FOCUS_SET(Scr.NoFocusWin, NULL); set_focus_window(NULL); } XFlush(dpy); return; } static void set_focus_to_fwin( Window w, FvwmWindow *fw, sftfwin_args_t *args) { FvwmWindow *sf; sf = get_focus_window(); if (!args->do_force && fw == sf) { focus_grab_buttons(sf); return; } __set_focus_to_fwin(w, fw, args); /* Make sure the button grabs on the new and the old focused windows * are up to date. */ if (args->client_entered) { focus_grab_buttons_client_entered(fw); } else { focus_grab_buttons(fw); } /* RBW -- don't call this twice for the same window! */ if (fw != get_focus_window()) { if (args->client_entered) { focus_grab_buttons_client_entered(get_focus_window()); } else { focus_grab_buttons(get_focus_window()); } } return; } /* * * Moves pointer to specified window * */ static void warp_to_fvwm_window( const exec_context_t *exc, int warp_x, int x_unit, int warp_y, int y_unit, int do_raise) { int dx,dy; int cx,cy; int x,y; FvwmWindow *t = exc->w.fw; if (t == (FvwmWindow *)0 || (IS_ICONIFIED(t) && FW_W_ICON_TITLE(t) == None)) { return; } if (t->Desk != Scr.CurrentDesk) { goto_desk(t->Desk); } if (IS_ICONIFIED(t)) { rectangle g; Bool rc; rc = get_visible_icon_title_geometry(t, &g); if (rc == False) { get_visible_icon_picture_geometry(t, &g); } cx = g.x + g.width / 2; cy = g.y + g.height / 2; } else { cx = t->g.frame.x + t->g.frame.width/2; cy = t->g.frame.y + t->g.frame.height/2; } dx = (cx + Scr.Vx) / Scr.MyDisplayWidth * Scr.MyDisplayWidth; dy = (cy + Scr.Vy) / Scr.MyDisplayHeight * Scr.MyDisplayHeight; if (dx != Scr.Vx || dy != Scr.Vy) { MoveViewport(dx, dy, True); } if (IS_ICONIFIED(t)) { rectangle g; Bool rc; rc = get_visible_icon_title_geometry(t, &g); if (rc == False) { get_visible_icon_picture_geometry(t, &g); } x = g.x + g.width / 2; y = g.y + g.height / 2; } else { if (x_unit != Scr.MyDisplayWidth && warp_x >= 0) { x = t->g.frame.x + warp_x; } else if (x_unit != Scr.MyDisplayWidth) { x = t->g.frame.x + t->g.frame.width + warp_x; } else if (warp_x >= 0) { x = t->g.frame.x + (t->g.frame.width - 1) * warp_x / 100; } else { x = t->g.frame.x + (t->g.frame.width - 1) * (100 + warp_x) / 100; } if (y_unit != Scr.MyDisplayHeight && warp_y >= 0) { y = t->g.frame.y + warp_y; } else if (y_unit != Scr.MyDisplayHeight) { y = t->g.frame.y + t->g.frame.height + warp_y; } else if (warp_y >= 0) { y = t->g.frame.y + (t->g.frame.height - 1) * warp_y / 100; } else { y = t->g.frame.y + (t->g.frame.height - 1) * (100 + warp_y) / 100; } } FWarpPointerUpdateEvpos( exc->x.elast, dpy, None, Scr.Root, 0, 0, 0, 0, x, y); if (do_raise) { RaiseWindow(t, False); } /* If the window is still not visible, make it visible! */ if (t->g.frame.x + t->g.frame.width < 0 || t->g.frame.y + t->g.frame.height < 0 || t->g.frame.x >= Scr.MyDisplayWidth || t->g.frame.y >= Scr.MyDisplayHeight) { frame_setup_window( t, 0, 0, t->g.frame.width, t->g.frame.height, False); FWarpPointerUpdateEvpos( exc->x.elast, dpy, None, Scr.Root, 0, 0, 0, 0, 2, 2); } return; } static Bool focus_query_grab_buttons(FvwmWindow *fw, Bool client_entered) { Bool flag; Bool is_focused; if (fw->Desk != Scr.CurrentDesk || IS_ICONIFIED(fw)) { return False; } is_focused = focus_is_focused(fw); if (!is_focused && FP_DO_FOCUS_CLICK_CLIENT(FW_FOCUS_POLICY(fw))) { return True; } if (is_on_top_of_layer_and_above_unmanaged(fw)) { return False; } if (is_focused) { flag = FP_DO_RAISE_FOCUSED_CLIENT_CLICK(FW_FOCUS_POLICY(fw)); } else { flag = FP_DO_RAISE_UNFOCUSED_CLIENT_CLICK(FW_FOCUS_POLICY(fw)); } return (flag) ? True : False; } static FvwmWindow *__restore_focus_after_unmap( const FvwmWindow *fw, Bool do_skip_marked_transients) { FvwmWindow *t = NULL; FvwmWindow *set_focus_to = NULL; t = get_transientfor_fvwmwindow(fw); if (t != NULL && FP_DO_RELEASE_FOCUS_TRANSIENT(FW_FOCUS_POLICY(fw)) && !FP_DO_OVERRIDE_RELEASE_FOCUS(FW_FOCUS_POLICY(t)) && t->Desk == fw->Desk && (!do_skip_marked_transients || !IS_IN_TRANSIENT_SUBTREE(t))) { set_focus_to = t; } else if (t == NULL && FP_DO_RELEASE_FOCUS(FW_FOCUS_POLICY(fw))) { for (t = fw->next; t != NULL && set_focus_to == NULL; t = t->next) { if (!FP_DO_OVERRIDE_RELEASE_FOCUS( FW_FOCUS_POLICY(t)) && t->Desk == fw->Desk && !DO_SKIP_CIRCULATE(t) && !(IS_ICONIFIED(t) && (DO_SKIP_ICON_CIRCULATE(t) || IS_ICON_SUPPRESSED(t))) && (!do_skip_marked_transients || !IS_IN_TRANSIENT_SUBTREE(t))) { /* If it is on a different desk we have to look * for another window */ set_focus_to = t; } } } if (set_focus_to && set_focus_to != fw && set_focus_to->Desk == fw->Desk) { /* Don't transfer focus to windows on other desks */ SetFocusWindow(set_focus_to, True, FOCUS_SET_FORCE); } if (focus_is_focused(fw)) { DeleteFocus(True); } return set_focus_to; } /* * * Moves focus to specified window; only to be called bay Focus and FlipFocus * */ static void __activate_window_by_command( F_CMD_ARGS, int is_focus_by_flip_focus_cmd) { int cx; int cy; Bool do_not_warp; sftfwin_args_t sf_args; FvwmWindow * const fw = exc->w.fw; memset(&sf_args, 0, sizeof(sf_args)); sf_args.do_allow_force_broadcast = 1; sf_args.is_focus_by_flip_focus_cmd = is_focus_by_flip_focus_cmd; sf_args.set_by = FOCUS_SET_BY_FUNCTION; sf_args.client_entered = 0; if (fw == NULL || !FP_DO_FOCUS_BY_FUNCTION(FW_FOCUS_POLICY(fw))) { UngrabEm(GRAB_NORMAL); if (fw) { /* give the window a chance to take the focus itself */ sf_args.do_forbid_warp = 1; sf_args.do_force = 0; set_focus_to_fwin(FW_W(fw), fw, &sf_args); } return; } do_not_warp = StrEquals(PeekToken(action, NULL), "NoWarp"); if (!do_not_warp) { if (fw->Desk != Scr.CurrentDesk) { goto_desk(fw->Desk); } if (IS_ICONIFIED(fw)) { rectangle g; Bool rc; rc = get_visible_icon_title_geometry(fw, &g); if (rc == False) { get_visible_icon_picture_geometry(fw, &g); } cx = g.x + g.width / 2; cy = g.y + g.height / 2; } else { cx = fw->g.frame.x + fw->g.frame.width/2; cy = fw->g.frame.y + fw->g.frame.height/2; } if ( cx < 0 || cx >= Scr.MyDisplayWidth || cy < 0 || cy >= Scr.MyDisplayHeight) { int dx; int dy; dx = ((cx + Scr.Vx) / Scr.MyDisplayWidth) * Scr.MyDisplayWidth; dy = ((cy + Scr.Vy) / Scr.MyDisplayHeight) * Scr.MyDisplayHeight; MoveViewport(dx, dy, True); } #if 0 /* can not happen */ /* If the window is still not visible, make it visible! */ if (fw->g.frame.x + fw->g.frame.width < 0 || fw->g.frame.y + fw->g.frame.height < 0 || fw->g.frame.x >= Scr.MyDisplayWidth || fw->g.frame.y >= Scr.MyDisplayHeight) { frame_setup_window( fw, 0, 0, fw->g.frame.width, fw->g.frame.height, False); if ( FP_DO_WARP_POINTER_ON_FOCUS_FUNC( FW_FOCUS_POLICY(fw))) { FWarpPointerUpdateEvpos( exc->x.elast, dpy, None, Scr.Root, 0, 0, 0, 0, 2, 2); } } #endif } UngrabEm(GRAB_NORMAL); if (fw->Desk == Scr.CurrentDesk) { FvwmWindow *sf; sf = get_focus_window(); sf_args.do_forbid_warp = !!do_not_warp; sf_args.do_force = 0; sf_args.client_entered = 0; set_focus_to_fwin(FW_W(fw), fw, &sf_args); if (sf != get_focus_window()) { /* Ignore EnterNotify event while we are waiting for * this window to be focused. */ Scr.focus_in_pending_window = sf; } } return; } static void __focus_grab_one_button( FvwmWindow *fw, int button, int grab_buttons) { Bool do_grab; do_grab = (grab_buttons & (1 << button)); if ((do_grab & (1 << button)) == (fw->grabbed_buttons & (1 << button))) { return; } if (do_grab) { XGrabButton( dpy, button + 1, AnyModifier, FW_W_PARENT(fw), True, ButtonPressMask, GrabModeSync, GrabModeAsync, None, None); /* Set window flags accordingly as we grab or ungrab. */ fw->grabbed_buttons |= (1 << button); } else { XUngrabButton(dpy, button + 1, AnyModifier, FW_W_PARENT(fw)); fw->grabbed_buttons &= ~(1 << button); } return; } /* ---------------------------- interface functions ------------------------ */ Bool focus_does_accept_input_focus(const FvwmWindow *fw) { return (!fw || !fw->wmhints || !(fw->wmhints->flags & InputHint) || fw->wmhints->input); } Bool focus_is_focused(const FvwmWindow *fw) { return (fw && fw == ScreenFocus); } Bool focus_query_click_to_raise( FvwmWindow *fw, Bool is_focused, int context) { fpol_context_t *c; if (is_focused) { c = &FP_DO_RAISE_FOCUSED_CLICK(FW_FOCUS_POLICY(fw)); } else { c = &FP_DO_RAISE_UNFOCUSED_CLICK(FW_FOCUS_POLICY(fw)); } return focus_get_fpol_context_flag(c, context); } Bool focus_query_click_to_focus( FvwmWindow *fw, int context) { fpol_context_t *c; c = &FP_DO_FOCUS_CLICK(FW_FOCUS_POLICY(fw)); return focus_get_fpol_context_flag(c, context); } /* Takes as input the window that wants the focus and the one that currently * has the focus and returns if the new window should get it. */ Bool focus_query_open_grab_focus(FvwmWindow *fw, FvwmWindow *focus_win) { if (fw == NULL) { return False; } focus_win = get_focus_window(); if (focus_win != NULL && FP_DO_OVERRIDE_GRAB_FOCUS(FW_FOCUS_POLICY(focus_win))) { /* Don't steal the focus from the current window */ return False; } validate_transientfor(fw); if (IS_TRANSIENT(fw) && FW_W_TRANSIENTFOR(fw) != Scr.Root) { if (focus_win != NULL && FP_DO_GRAB_FOCUS_TRANSIENT(FW_FOCUS_POLICY(fw)) && FW_W(focus_win) == FW_W_TRANSIENTFOR(fw)) { /* it's a transient and its transientfor currently has * focus. */ return True; } } else { if (FP_DO_GRAB_FOCUS(FW_FOCUS_POLICY(fw)) && (focus_win == NULL || !FP_DO_OVERRIDE_GRAB_FOCUS(FW_FOCUS_POLICY(focus_win)))) { return True; } } return False; } /* Returns true if the focus has to be restored to a different window after * unmapping. */ Bool focus_query_close_release_focus(const FvwmWindow *fw) { if (fw == NULL || fw != get_focus_window()) { return False; } if (!IS_TRANSIENT(fw) && (FW_W_TRANSIENTFOR(fw) == Scr.Root || FP_DO_GRAB_FOCUS(FW_FOCUS_POLICY(fw)))) { return True; } else if (IS_TRANSIENT(fw) && FP_DO_GRAB_FOCUS_TRANSIENT(FW_FOCUS_POLICY(fw))) { return True; } return False; } static void __focus_grab_buttons(FvwmWindow *fw, Bool client_entered) { int i; Bool do_grab_window = False; int grab_buttons; if (fw == NULL || IS_SCHEDULED_FOR_DESTROY(fw) || !IS_MAPPED(fw)) { /* It is pointless to grab buttons on dieing windows. Buttons * can not be grabbed when the window is unmapped. */ return; } grab_buttons = Scr.buttons2grab; do_grab_window = focus_query_grab_buttons(fw, client_entered); if (do_grab_window == True) { grab_buttons |= FP_USE_MOUSE_BUTTONS(FW_FOCUS_POLICY(fw)); } if (grab_buttons != fw->grabbed_buttons) { MyXGrabServer(dpy); for (i = 0; i < NUMBER_OF_EXTENDED_MOUSE_BUTTONS; i++) { __focus_grab_one_button(fw, i, grab_buttons); } MyXUngrabServer (dpy); } return; } void focus_grab_buttons(FvwmWindow *fw) { __focus_grab_buttons(fw, False); } void focus_grab_buttons_client_entered(FvwmWindow *fw) { __focus_grab_buttons(fw, True); } void focus_grab_buttons_on_layer(int layer) { FvwmWindow *fw; for ( fw = Scr.FvwmRoot.stack_next; fw != &Scr.FvwmRoot && fw->layer >= layer; fw = fw->stack_next) { if (fw->layer == layer) { focus_grab_buttons(fw); } } return; } void focus_grab_buttons_all(void) { FvwmWindow *fw; for (fw = Scr.FvwmRoot.next; fw != NULL; fw = fw->next) { focus_grab_buttons(fw); } return; } void _SetFocusWindow( FvwmWindow *fw, Bool do_allow_force_broadcast, fpol_set_focus_by_t set_by, Bool client_entered) { sftfwin_args_t sf_args; memset(&sf_args, 0, sizeof(sf_args)); sf_args.do_allow_force_broadcast = !!do_allow_force_broadcast; sf_args.is_focus_by_flip_focus_cmd = 0; sf_args.do_forbid_warp = 0; sf_args.do_force = 1; sf_args.set_by = set_by; if (client_entered) { sf_args.client_entered = 1; } else { sf_args.client_entered = 0; } set_focus_to_fwin(FW_W(fw), fw, &sf_args); return; } void _ReturnFocusWindow(FvwmWindow *fw) { sftfwin_args_t sf_args; memset(&sf_args, 0, sizeof(sf_args)); sf_args.do_allow_force_broadcast = 1; sf_args.is_focus_by_flip_focus_cmd = 0; sf_args.do_forbid_warp = 1; sf_args.client_entered = 0; sf_args.do_force = 0; sf_args.set_by = FOCUS_SET_FORCE; set_focus_to_fwin(FW_W(fw), fw, &sf_args); return; } void _DeleteFocus(Bool do_allow_force_broadcast) { sftfwin_args_t sf_args; memset(&sf_args, 0, sizeof(sf_args)); sf_args.do_allow_force_broadcast = !!do_allow_force_broadcast; sf_args.is_focus_by_flip_focus_cmd = 0; sf_args.do_forbid_warp = 0; sf_args.client_entered = 0; sf_args.do_force = 0; sf_args.set_by = FOCUS_SET_FORCE; set_focus_to_fwin(Scr.NoFocusWin, NULL, &sf_args); return; } void _ForceDeleteFocus(void) { sftfwin_args_t sf_args; memset(&sf_args, 0, sizeof(sf_args)); sf_args.do_allow_force_broadcast = 1; sf_args.is_focus_by_flip_focus_cmd = 0; sf_args.do_forbid_warp = 0; sf_args.client_entered = 0; sf_args.do_force = 1; sf_args.set_by = FOCUS_SET_FORCE; set_focus_to_fwin(Scr.NoFocusWin, NULL, &sf_args); return; } /* When a window is unmapped (or destroyed) this function takes care of * adjusting the focus window appropriately. */ void restore_focus_after_unmap( const FvwmWindow *fw, Bool do_skip_marked_transients) { extern FvwmWindow *colormap_win; FvwmWindow *set_focus_to = NULL; if (focus_is_focused(fw)) { set_focus_to = __restore_focus_after_unmap( fw, do_skip_marked_transients); } if (fw == Scr.pushed_window) { Scr.pushed_window = NULL; } if (fw == colormap_win) { InstallWindowColormaps(set_focus_to); } return; } Bool IsLastFocusSetByMouse(void) { return lastFocusType; } /* same as above, but forces to regrab buttons on the window under the pointer * if necessary */ void focus_grab_buttons_on_pointer_window(void) { Window w; FvwmWindow *fw; if (!FQueryPointer( dpy, Scr.Root, &JunkRoot, &w, &JunkX, &JunkY, &JunkX, &JunkY, &JunkMask)) { /* pointer is not on this screen */ return; } if (XFindContext(dpy, w, FvwmContext, (caddr_t *) &fw) == XCNOENT) { /* pointer is not over a window */ return; } focus_grab_buttons(fw); return; } /* functions to access ScreenFocus, LastScreenFocus and PreviousFocus */ FvwmWindow *get_focus_window(void) { return ScreenFocus; } void set_focus_window(FvwmWindow *fw) { ScreenFocus = fw; return; } FvwmWindow *get_last_screen_focus_window(void) { return LastScreenFocus; } void set_last_screen_focus_window(FvwmWindow *fw) { LastScreenFocus = fw; return; } void update_last_screen_focus_window(FvwmWindow *fw) { if (fw == LastScreenFocus) { LastScreenFocus = NULL; } return; } void set_focus_model(FvwmWindow *fw) { if (!focus_does_accept_input_focus(fw)) { if (WM_TAKES_FOCUS(fw)) { fw->focus_model = FM_GLOBALLY_ACTIVE; } else { fw->focus_model = FM_NO_INPUT; } } else { if (WM_TAKES_FOCUS(fw)) { fw->focus_model = FM_LOCALLY_ACTIVE; } else { fw->focus_model = FM_PASSIVE; } } return; } /* This function is part of a hack to make focus handling work better with * applications that use the passive focus model but manage focus in their own * sub windows and should thus use the locally active focus model instead. * There are many examples like netscape or ddd. */ void focus_force_refresh_focus(const FvwmWindow *fw) { XWindowAttributes winattrs; MyXGrabServer(dpy); if (XGetWindowAttributes(dpy, FW_W(fw), &winattrs)) { XSelectInput( dpy, FW_W(fw), winattrs.your_event_mask & ~FocusChangeMask); FOCUS_SET(FW_W(fw), NULL /* we don't expect an event */); XSelectInput(dpy, FW_W(fw), winattrs.your_event_mask); } MyXUngrabServer(dpy); return; } void refresh_focus(const FvwmWindow *fw) { Bool do_refresh = False; if (fw == NULL || !focus_is_focused(fw)) { /* only refresh the focus on the currently focused window */ return; } /* only refresh the focus for windows with the passive focus model so * that we don't disturb focus handling more than necessary */ switch (fw->focus_model) { case FM_PASSIVE: do_refresh = True; break; case FM_NO_INPUT: case FM_GLOBALLY_ACTIVE: case FM_LOCALLY_ACTIVE: default: do_refresh = False; break; } if (do_refresh) { focus_force_refresh_focus(fw); } return; } /* ---------------------------- builtin commands --------------------------- */ void CMD_FlipFocus(F_CMD_ARGS) { /* Reorder the window list */ __activate_window_by_command(F_PASS_ARGS, 1); return; } void CMD_Focus(F_CMD_ARGS) { __activate_window_by_command(F_PASS_ARGS, 0); return; } void CMD_WarpToWindow(F_CMD_ARGS) { int val1_unit, val2_unit, n; int val1, val2; int do_raise; char *next; char *token; next = GetNextToken(action, &token); if (StrEquals(token, "!raise")) { do_raise = 0; action = next; } else if (StrEquals(token, "raise")) { do_raise = 1; action = next; } else { do_raise = 1; } n = GetTwoArguments(action, &val1, &val2, &val1_unit, &val2_unit); if (exc->w.wcontext != C_UNMANAGED) { if (n == 2) { warp_to_fvwm_window( exc, val1, val1_unit, val2, val2_unit, do_raise); } else { warp_to_fvwm_window(exc, 0, 0, 0, 0, do_raise); } } else { int x = 0; int y = 0; if (n == 2) { int wx; int wy; int ww; int wh; if (!XGetGeometry( dpy, exc->w.w, &JunkRoot, &wx, &wy, (unsigned int*)&ww, (unsigned int*)&wh, (unsigned int*)&JunkBW, (unsigned int*)&JunkDepth)) { return; } if (val1_unit != Scr.MyDisplayWidth) { x = val1; } else { x = (ww - 1) * val1 / 100; } if (val2_unit != Scr.MyDisplayHeight) { y = val2; } else { y = (wh - 1) * val2 / 100; } if (x < 0) { x += ww; } if (y < 0) { y += wh; } } FWarpPointerUpdateEvpos( exc->x.elast, dpy, None, exc->w.w, 0, 0, 0, 0, x, y); } return; } fvwm-2.7.0/fvwm/schedule.c0000644000175000017500000001554514147024700012350 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ #include "config.h" #include #include "libs/fvwmlib.h" #include "libs/queue.h" #include "libs/charmap.h" #include "libs/wcontext.h" #include "libs/Parse.h" #include "fvwm.h" #include "externs.h" #include "colorset.h" #include "bindings.h" #include "misc.h" #include "cursor.h" #include "functions.h" #include "commands.h" #include "screen.h" typedef struct { int id; Time time_to_execute; Window window; char *command; int period; /* in milliseconds */ } sq_object_type; static int last_schedule_id = 0; static int next_schedule_id = -1; static fqueue sq = FQUEUE_INIT; static int cmp_times(Time t1, Time t2) { unsigned long ul1 = (unsigned long)t1; unsigned long ul2 = (unsigned long)t2; unsigned long diff; signed long udiff; diff = ul1 - ul2; udiff = *(signed long *)&diff; if (udiff > 0) { return 1; } else if (udiff < 0) { return -1; } else { return 0; } } static int cmp_object_time(void *object1, void *object2, void *args) { sq_object_type *so1 = (sq_object_type *)object1; sq_object_type *so2 = (sq_object_type *)object2; return cmp_times(so1->time_to_execute, so2->time_to_execute); } static int check_deschedule_obj_func(void *object, void *args) { sq_object_type *obj = object; return (obj->id == *(int *)args); } static void destroy_obj_func(void *object) { sq_object_type *obj = object; if (obj->command != NULL) { free(obj->command); } free(obj); return; } static void deschedule(int *pid) { int id; if (FQUEUE_IS_EMPTY(&sq)) { return; } /* get the job group id to deschedule */ if (pid != NULL) { id = *pid; } else { id = last_schedule_id; } /* deschedule matching jobs */ fqueue_remove_or_operate_all( &sq, check_deschedule_obj_func, NULL, destroy_obj_func, (void *)&id); return; } static void schedule( Window window, char *command, Time time_to_execute, int *pid, int period) { sq_object_type *new_obj; if (command == NULL || *command == 0) { return; } /* create the new object */ new_obj = (sq_object_type *)safemalloc(sizeof(sq_object_type)); memset(new_obj, 0, sizeof(sq_object_type)); new_obj->window = window; new_obj->command = safestrdup(command); new_obj->time_to_execute = time_to_execute; new_obj->period = period; /* 0 if this is not a periodic command */ /* set the job group id */ if (pid != NULL) { new_obj->id = *pid; } else { new_obj->id = next_schedule_id; next_schedule_id--; if (next_schedule_id >= 0) { /* wrapped around */ next_schedule_id = -1; } } last_schedule_id = new_obj->id; /* insert into schedule queue */ fqueue_add_inside(&sq, new_obj, cmp_object_time, NULL); return; } static int check_execute_obj_func(void *object, void *args) { sq_object_type *obj = object; Time *ptime = (Time *)args; return (cmp_times(*ptime, obj->time_to_execute) >= 0); } static void execute_obj_func(void *object, void *args) { sq_object_type *obj = object; if (obj->command != NULL) { /* execute the command */ const exec_context_t *exc; exec_context_changes_t ecc; exec_context_change_mask_t mask = ECC_TYPE | ECC_WCONTEXT; ecc.type = EXCT_SCHEDULE; ecc.w.wcontext = C_ROOT; if (XFindContext( dpy, obj->window, FvwmContext, (caddr_t *)&ecc.w.fw) != XCNOENT) { ecc.w.wcontext = C_WINDOW; mask |= ECC_FW; } exc = exc_create_context(&ecc, mask); execute_function(NULL, exc, obj->command, 0); exc_destroy_context(exc); } if (obj->period > 0) { /* This is a periodic function, so reschedule it. */ sq_object_type *new_obj = (sq_object_type *)safemalloc(sizeof(sq_object_type)); memcpy(new_obj, obj, sizeof(sq_object_type)); obj->command = NULL; /* new_obj->command now points to cmd. */ new_obj->time_to_execute = fev_get_evtime() + new_obj->period; /* insert into schedule queue */ fqueue_add_inside(&sq, new_obj, cmp_object_time, NULL); } XFlush(dpy); return; } /* executes all scheduled commands that are due for execution */ void squeue_execute(void) { Time current_time; if (FQUEUE_IS_EMPTY(&sq)) { return; } current_time = get_server_time(); fqueue_remove_or_operate_all( &sq, check_execute_obj_func, execute_obj_func, destroy_obj_func, ¤t_time); return; } /* returns the time in milliseconds to wait before next queue command must be * executed or -1 if none is queued */ int squeue_get_next_ms(void) { int ms; sq_object_type *obj; if (fqueue_get_first(&sq, (void **)&obj) == 0) { return -1; } if (cmp_times(fev_get_evtime(), obj->time_to_execute) >= 0) { /* jobs pending to be executed immediately */ ms = 0; } else { /* execute jobs later */ ms = obj->time_to_execute - fev_get_evtime(); } return ms; } int squeue_get_next_id(void) { return next_schedule_id; } int squeue_get_last_id(void) { return last_schedule_id; } void CMD_Schedule(F_CMD_ARGS) { Window xw; Time time; Time current_time; char *taction; char *token; char *next; int ms; int id; int *pid; int n; FvwmWindow * const fw = exc->w.fw; Bool is_periodic = False; token = PeekToken(action, &next); if (token && strcasecmp(token, "periodic") == 0) { is_periodic = True; action = next; } /* get the time to execute */ n = GetIntegerArguments(action, &action, &ms, 1); if (n <= 0) { fvwm_msg(ERR, "CMD_Schedule", "Requires time to schedule as argument"); return; } if (ms < 0) { ms = 0; } #if 0 /* eats up way too much cpu if schedule is used excessively */ current_time = get_server_time(); #else /* with this version, scheduled commands may be executed earlier than * intended. */ current_time = fev_get_evtime(); #endif time = current_time + (Time)ms; /* get the job group id to schedule */ n = GetIntegerArgumentsAnyBase(action, &taction, &id, 1); if (n >= 1) { pid = &id; action = taction; } else { pid = NULL; } /* get the window to operate on */ if (fw != NULL) { xw = FW_W(fw); } else { xw = None; } /* schedule the job */ schedule(xw, action, time, pid, (is_periodic == True ? ms : 0)); return; } void CMD_Deschedule(F_CMD_ARGS) { int id; int *pid; int n; /* get the job group id to deschedule */ n = GetIntegerArgumentsAnyBase(action, &action, &id, 1); if (n <= 0) { /* none, use default */ pid = NULL; } else { pid = &id; } /* deschedule matching jobs */ deschedule(pid); return; } fvwm-2.7.0/fvwm/repeat.c0000644000175000017500000001004014147024700012015 00000000000000/* -*-c-*- */ /* Copyright (C) 1999 Dominik Vogt */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ #include "config.h" #include #include "libs/fvwmlib.h" #include "fvwm.h" #include "externs.h" #include "cursor.h" #include "functions.h" #include "repeat.h" #include "libs/Parse.h" /* If non-zero we are already repeating a function, so don't record the * command again. */ static int repeat_depth = 0; #if 0 typedef struct { char *start; char *end; } double_ended_string; static struct { double_ended_string string; double_ended_string old; double_ended_string builtin; double_ended_string function; double_ended_string top_function; double_ended_string module; double_ended_string menu; double_ended_string popup; double_ended_string menu_or_popup; int page_x; int page_y; int desk; FvwmWindow *fvwm_window; } last; #endif static struct { char *command_line; char *menu_name; } last = { NULL, NULL }; #if 0 char *repeat_last_function = NULL; char *repeat_last_complex_function = NULL; char *repeat_last_builtin_function = NULL; char *repeat_last_module = NULL; char *repeat_last_top_function = NULL; char *repeat_last_menu = NULL; FvwmWindow *repeat_last_fvwm_window = NULL; #endif /* Stores the contents of the data pointer internally for the repeat command. * The type of data is determined by the 'type' parameter. If this function is * called to set a string value representing an fvwm builtin function the * 'builtin' can be set to the F_... value in the function table in * functions.c. If this value is set certain functions are not recorded. * The 'depth' parameter indicates the recursion depth of the current data * pointer (i.e. the first function call has a depth of one, functions called * from within this function have depth 2 and higher, this may be applicable * to future enhancements like menus). * * TODO: [finish and update description] */ Bool set_repeat_data(void *data, repeat_t type, const func_t *builtin) { /* No history recording during startup. */ if (fFvwmInStartup) { return True; } switch(type) { case REPEAT_COMMAND: if (last.command_line == (char *)data) { /* Already stored, no need to free the data pointer. */ return False; } if (data == NULL || repeat_depth != 0) { /* Ignoring the data, must free it outside of this * call. */ return True; } if (builtin && (builtin->flags & FUNC_DONT_REPEAT)) { /* Dont' record functions that have the * FUNC_DONT_REPEAT flag set. */ return True; } if (last.command_line) { free(last.command_line); } /* Store a backup. */ last.command_line = (char *)data; /* Since we stored the pointer the caller must not free it. */ return False; case REPEAT_MENU: case REPEAT_POPUP: if (last.menu_name) { free(last.menu_name); } last.menu_name = (char *)data; /* Since we stored the pointer the caller must not free it. */ return False; case REPEAT_PAGE: case REPEAT_DESK: case REPEAT_DESK_AND_PAGE: return True; case REPEAT_FVWM_WINDOW: return True; case REPEAT_NONE: default: return True; } } void CMD_Repeat(F_CMD_ARGS) { int index; char *optlist[] = { "command", NULL }; repeat_depth++; /* Replay the backup, we don't want the repeat command recorded. */ GetNextTokenIndex(action, optlist, 0, &index); switch (index) { case 0: /* command */ default: action = last.command_line; execute_function( cond_rc, exc, action, FUNC_DONT_EXPAND_COMMAND); break; } repeat_depth--; return; } fvwm-2.7.0/fvwm/modconf.h0000644000175000017500000000015614147024676012212 00000000000000/* -*-c-*- */ #ifndef MODCONF_H #define MODCONF_H void ModuleConfig(char *action); #endif /* MODCONF_H */ fvwm-2.7.0/fvwm/colorset.c0000644000175000017500000011737514147024700012412 00000000000000/* -*-c-*- */ /* Copyright (C) 2002 the late Joey Shutup. * * http://www.streetmap.co.uk/streetmap.dll?postcode2map?BS24+9TZ * * No guarantees or warranties or anything are provided or implied in any way * whatsoever. Use this program at your own risk. Permission to use this * program for any purpose is given, as long as the copyright is kept intact. */ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include "libs/fvwmlib.h" #include "libs/Parse.h" #include "libs/PictureBase.h" #include "libs/FShape.h" #include "libs/ColorUtils.h" #include "libs/Picture.h" #include "libs/PictureUtils.h" #include "libs/Graphics.h" #include "libs/PictureGraphics.h" #include "libs/FRenderInit.h" #include "libs/Strings.h" #include "libs/Grab.h" #include "colorset.h" #include "externs.h" #include "fvwm.h" #include "cursor.h" #include "functions.h" #include "commands.h" #include "misc.h" #include "screen.h" #include "module_interface.h" #include "execcontext.h" #include "builtins.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ extern int nColorsets; /* in libs/Colorset.c */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* When fvwm destroys pixmaps it puts them on a list and only destroys them * after some period of inactivity. This is necessary because changing colorset * options rapidly may result in a module redrawing itself due to the first * change while the second change is happening. If the module renders something * with the colorset affected by the second change there is a chance it may * reference pixmaps that FvwmTheme has destroyed, bad things would happen */ struct junklist { struct junklist *prev; Pixmap pixmap; }; struct root_pic { Pixmap pixmap; Pixmap old_pixmap; int width; int height; }; /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ static char *black = "black"; static char *white = "white"; static char *gray = "gray"; static struct junklist *junk = NULL; static Bool cleanup_scheduled = False; static struct root_pic root_pic = {None, None, 0, 0}; static char *csetopts[] = { "Foreground", "Fore", "fg", "Background", "Back", "bg", "Hilight", "Hilite", "hi", "Shadow", "Shade", "sh", "fgsh", "fg_alpha", "fgAlpha", /* these strings are used inside the cases in the switch below! */ "Pixmap", "TiledPixmap", "AspectPixmap", /* these strings are used inside the cases in the switch below! */ "Shape", "TiledShape", "AspectShape", /* switch off pixmaps and gradients */ "Plain", /* switch off shape */ "NoShape", /* Make the background transparent, copies the root window background */ "Transparent", "RootTransparent", /* tint for the Pixmap or the gradient */ "Tint", "PixmapTint", /* ~ Tint */ "ImageTint", /* ~ Tint */ "TintMask", /* ~ Tint (backward compatibility) */ "NoTint", /* ~ Tint without argument */ "fgTint", "bgTint", /* Dither the Pixmap or the gradient */ "Dither", "NoDither", /* alpha for the Pixmap or the gradient */ "Alpha", "PixmapAlpha", /* ~ Alpha */ "ImageAlpha", /* ~ Alpha */ /* Icon stuff */ "DitherIcon", "NoDitherIcon", "IconTint", "NoIconTint", "IconAlpha", NULL }; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ static Pixmap get_root_pixmap(Atom prop) { Atom type; int format; unsigned long length, after; unsigned char *reteval = NULL; int ret; Pixmap pix = None; ret = XGetWindowProperty( dpy, Scr.Root, prop, 0L, 1L, False, XA_PIXMAP, &type, &format, &length, &after, &reteval); if ( ret == Success && type == XA_PIXMAP && format == 32 && length == 1 && after == 0) { pix = (Pixmap)(*(long *)reteval); } if (reteval) { XFree(reteval); } return pix; } void update_root_pixmap(Atom prop) { static Atom a_rootpix = None; int w = 0; int h = 0; XID dummy; Pixmap pix; if (a_rootpix == None) { a_rootpix = XInternAtom(dpy,"_XROOTPMAP_ID", False); } XSync(dpy, False); if (prop != 0) { pix = get_root_pixmap(prop); if (pix && !XGetGeometry( dpy, pix, &dummy, (int *)&dummy, (int *)&dummy, (unsigned int *)&w, (unsigned int *)&h, (unsigned int *)&dummy, (unsigned int *)&dummy)) { pix = None; } } else { pix = get_root_pixmap(a_rootpix); if (pix && !XGetGeometry( dpy, pix, &dummy, (int *)&dummy, (int *)&dummy, (unsigned int *)&w, (unsigned int *)&h, (unsigned int *)&dummy, (unsigned int *)&dummy)) { pix = None; } } root_pic.pixmap = pix; root_pic.width = w; root_pic.height = h; #if 0 fprintf(stderr,"Get New Root Pixmap: 0x%lx %i,%i\n", root_pic.pixmap, w, h); #endif } static void add_to_junk(Pixmap pixmap) { struct junklist *oldjunk = junk; junk = (struct junklist *)safemalloc(sizeof(struct junklist)); junk->prev = oldjunk; junk->pixmap = pixmap; if (!cleanup_scheduled) { const exec_context_t *exc; exc = exc_create_null_context(); CMD_Schedule(NULL, exc, "3000 CleanupColorsets"); exc_destroy_context(exc); cleanup_scheduled = True; } return; } static char *get_simple_color( char *string, char **color, colorset_t *cs, int supplied_color, int special_flag, char *special_string) { char *rest; if (*color) { free(*color); *color = NULL; } rest = GetNextToken(string, color); if (*color) { if (special_string && StrEquals(*color, special_string)) { free(*color); *color = NULL; cs->color_flags |= special_flag; cs->color_flags &= ~supplied_color; } else { cs->color_flags |= supplied_color; cs->color_flags &= ~special_flag; } } else { cs->color_flags &= ~(supplied_color | special_flag); } return rest; } static void SafeDestroyPicture(Display *dpy, FvwmPicture *picture) { /* have to subvert destroy picture so that it doesn't free pixmaps, * these are added to the junk list to be cleaned up after a timeout */ if (picture->count < 2) { if (picture->picture) { add_to_junk(picture->picture); picture->picture = None; } if (picture->mask) { add_to_junk(picture->mask); picture->mask = None; } if (picture->alpha) { add_to_junk(picture->alpha); picture->alpha = None; } } /* all that this will now do is free the colors and the name */ PDestroyFvwmPicture(dpy, picture); return; } static void free_colorset_background(colorset_t *cs, Bool do_free_args) { if (cs->picture != NULL) { if (cs->picture->picture != cs->pixmap) { add_to_junk(cs->pixmap); } SafeDestroyPicture(dpy, cs->picture); cs->picture = NULL; cs->pixmap = None; cs->alpha_pixmap = None; /* alaways equal to picture->alpha */ } if (cs->pixmap && cs->pixmap != ParentRelative && cs->pixmap != root_pic.pixmap && cs->pixmap != root_pic.old_pixmap) { add_to_junk(cs->pixmap); } cs->pixmap = None; if (cs->mask) { add_to_junk(cs->mask); cs->mask = None; } if (cs->alpha_pixmap) { add_to_junk(cs->alpha_pixmap); cs->alpha_pixmap = None; } if (cs->pixels && cs->nalloc_pixels) { PictureFreeColors( dpy, Pcmap, cs->pixels, cs->nalloc_pixels, 0, False); free(cs->pixels); cs->pixels = NULL; cs->nalloc_pixels = 0; } if (do_free_args) { if (cs->pixmap_args != NULL) { free(cs->pixmap_args); cs->pixmap_args = NULL; } if (cs->gradient_args != NULL) { free(cs->gradient_args); cs->gradient_args = NULL; } cs->is_maybe_root_transparent = False; cs->pixmap_type = 0; } } static void reset_cs_pixmap(colorset_t *cs, GC gc) { if (Pdepth == cs->picture->depth) { XCopyArea(dpy, cs->picture->picture, cs->pixmap, gc, 0, 0, cs->width, cs->height, 0, 0); } else { XCopyPlane(dpy, cs->picture->picture, cs->pixmap, gc, 0, 0, cs->width, cs->height, 0, 0, 1); } return; } static void parse_pixmap( Window win, GC gc, colorset_t *cs, Bool *pixmap_is_a_bitmap) { static char *name = "parse_colorset(pixmap)"; FvwmPictureAttributes fpa; /* dither */ fpa.mask = 0; if (cs->dither) { fpa.mask = FPAM_DITHER; } /* read filename */ if (!cs->pixmap_args) { return; } /* load the file */ cs->picture = PCacheFvwmPicture(dpy, win, NULL, cs->pixmap_args, fpa); if (cs->picture == NULL) { fvwm_msg(ERR, name, "can't load picture %s", cs->pixmap_args); return; } if (cs->picture->depth != Pdepth) { *pixmap_is_a_bitmap = True; cs->pixmap = None; /* build cs->pixmap later */ } /* copy the picture pixmap into the public structure */ cs->width = cs->picture->width; cs->height = cs->picture->height; cs->alpha_pixmap = cs->picture->alpha; if (!*pixmap_is_a_bitmap) { cs->pixmap = XCreatePixmap(dpy, win, cs->width, cs->height, Pdepth); XSetClipMask(dpy, gc, cs->picture->mask); XCopyArea(dpy, cs->picture->picture, cs->pixmap, gc, 0, 0, cs->width, cs->height, 0, 0); XSetClipMask(dpy, gc, None); } if (cs->pixmap) { if (cs->picture->mask != None) { /* make an inverted copy of the mask */ cs->mask = XCreatePixmap(dpy, win, cs->width, cs->height, 1); if (cs->mask) { XCopyArea(dpy, cs->picture->mask, cs->mask, Scr.MonoGC, 0, 0, cs->width, cs->height, 0, 0); /* Invert the mask. We use it to draw the * background. */ XSetFunction(dpy, Scr.MonoGC, GXinvert); XFillRectangle(dpy, cs->mask, Scr.MonoGC, 0, 0, cs->width, cs->height); XSetFunction(dpy, Scr.MonoGC, GXcopy); } } } } static void parse_shape(Window win, colorset_t *cs, int i, char *args, int *has_shape_changed) { char *token; static char *name = "parse_colorset(shape)"; FvwmPicture *picture; FvwmPictureAttributes fpa; if (!FHaveShapeExtension) { cs->shape_mask = None; return; } /* read filename */ token = PeekToken(args, &args); *has_shape_changed = True; if (cs->shape_mask) { add_to_junk(cs->shape_mask); cs->shape_mask = None; } /* set the flags */ if (csetopts[i][0] == 'T') { cs->shape_type = SHAPE_TILED; } else if (csetopts[i][0] == 'A') { cs->shape_type = SHAPE_STRETCH_ASPECT; } else { cs->shape_type = SHAPE_STRETCH; } fpa.mask = FPAM_NO_ALPHA; /* try to load the shape mask */ if (!token) { return; } /* load the shape mask */ picture = PCacheFvwmPicture(dpy, win, NULL, token, fpa); if (!picture) { fvwm_msg(ERR, name, "can't load picture %s", token); } else if (picture->depth != 1 && picture->mask == None) { fvwm_msg(ERR, name, "shape pixmap must be of depth 1"); SafeDestroyPicture(dpy, picture); } else { Pixmap mask; /* okay, we have what we want */ if (picture->mask != None) { mask = picture->mask; } else { mask = picture->picture; } cs->shape_width = picture->width; cs->shape_height = picture->height; if (mask != None) { cs->shape_mask = XCreatePixmap( dpy, mask, picture->width, picture->height, 1); if (cs->shape_mask != None) { XCopyPlane(dpy, mask, cs->shape_mask, Scr.MonoGC, 0, 0, picture->width, picture->height, 0, 0, 1); } } } if (picture) { SafeDestroyPicture(dpy, picture); picture = None; } return; } static void parse_simple_tint( colorset_t *cs, char *args, char **tint, int supplied_color, int *changed, int *percent, char *cmd) { char *rest; static char *name = "parse_colorset (tint)"; *changed = False; rest = get_simple_color(args, tint, cs, supplied_color, 0, NULL); if (!(cs->color_flags & supplied_color)) { /* restore to default */ *percent = 0; *changed = True; cs->color_flags &= ~(supplied_color); } else if (!GetIntegerArguments(rest, NULL, percent, 1)) { fvwm_msg(WARN, name, "%s must have two arguments a color and an integer", cmd); return; } *changed = True; if (*percent > 100) { *percent = 100; } else if (*percent < 0) { *percent = 0; } } /* ---------------------------- interface functions ------------------------ */ void cleanup_colorsets(void) { struct junklist *oldjunk = junk; while (junk) { XFreePixmap(dpy, junk->pixmap); oldjunk = junk; junk = junk->prev; free(oldjunk); } cleanup_scheduled = False; } /* translate a colorset spec into a colorset structure */ void parse_colorset(int n, char *line) { int i; int w; int h; int tmp; int percent; colorset_t *cs; char *optstring; char *args; char *option; char *tmp_str; char *fg = NULL; char *bg = NULL; char *hi = NULL; char *sh = NULL; char *fgsh = NULL; char *tint = NULL; char *fg_tint = NULL; char *bg_tint = NULL; char *icon_tint = NULL; Bool have_pixels_changed = False; Bool has_icon_pixels_changed = False; Bool has_fg_changed = False; Bool has_bg_changed = False; Bool has_sh_changed = False; Bool has_hi_changed = False; Bool has_fgsh_changed = False; Bool has_fg_alpha_changed = False; Bool has_tint_changed = False; Bool has_fg_tint_changed = False; Bool has_bg_tint_changed = False; Bool has_icon_tint_changed = False; Bool has_pixmap_changed = False; Bool has_shape_changed = False; Bool has_image_alpha_changed = False; Bool pixmap_is_a_bitmap = False; Bool do_reload_pixmap = False; Bool is_server_grabbed = False; XColor color; XGCValues xgcv; static char *name = "parse_colorset"; Window win = Scr.NoFocusWin; static GC gc = None; /* initialize statics */ if (gc == None) { gc = fvwmlib_XCreateGC(dpy, win, 0, &xgcv); } /* make sure it exists and has sensible contents */ alloc_colorset(n); cs = &Colorset[n]; /*** Parse the options ***/ while (line && *line) { /* Read next option specification delimited by a comma or \0. */ line = GetQuotedString( line, &optstring, ",", NULL, NULL, NULL); if (!optstring) break; args = GetNextToken(optstring, &option); if (!option) { free(optstring); break; } switch((i = GetTokenIndex(option, csetopts, 0, NULL))) { case 0: /* Foreground */ case 1: /* Fore */ case 2: /* fg */ get_simple_color( args, &fg, cs, FG_SUPPLIED, FG_CONTRAST, "contrast"); has_fg_changed = True; break; case 3: /* Background */ case 4: /* Back */ case 5: /* bg */ get_simple_color( args, &bg, cs, BG_SUPPLIED, BG_AVERAGE, "average"); has_bg_changed = True; break; case 6: /* Hilight */ case 7: /* Hilite */ case 8: /* hi */ get_simple_color(args, &hi, cs, HI_SUPPLIED, 0, NULL); has_hi_changed = True; break; case 9: /* Shadow */ case 10: /* Shade */ case 11: /* sh */ get_simple_color(args, &sh, cs, SH_SUPPLIED, 0, NULL); has_sh_changed = True; break; case 12: /* fgsh */ get_simple_color( args, &fgsh, cs, FGSH_SUPPLIED, 0,NULL); has_fgsh_changed = True; break; case 13: /* fg_alpha */ case 14: /* fgAlpha */ if (GetIntegerArguments(args, NULL, &tmp, 1)) { if (tmp > 100) tmp = 100; else if (tmp < 0) tmp = 0; } else { tmp = 100; } if (tmp != cs->fg_alpha_percent) { cs->fg_alpha_percent = tmp; has_fg_alpha_changed = True; } break; case 15: /* TiledPixmap */ case 16: /* Pixmap */ case 17: /* AspectPixmap */ has_pixmap_changed = True; free_colorset_background(cs, True); tmp_str = PeekToken(args, &args); if (tmp_str) { CopyString(&cs->pixmap_args, tmp_str); do_reload_pixmap = True; cs->gradient_type = 0; /* set the flags */ if (csetopts[i][0] == 'T') { cs->pixmap_type = PIXMAP_TILED; } else if (csetopts[i][0] == 'A') { cs->pixmap_type = PIXMAP_STRETCH_ASPECT; } else { cs->pixmap_type = PIXMAP_STRETCH; } } /* the pixmap is build later */ break; case 18: /* Shape */ case 19: /* TiledShape */ case 20: /* AspectShape */ parse_shape(win, cs, i, args, &has_shape_changed); break; case 21: /* Plain */ has_pixmap_changed = True; free_colorset_background(cs, True); break; case 22: /* NoShape */ has_shape_changed = True; if (cs->shape_mask) { add_to_junk(cs->shape_mask); cs->shape_mask = None; } break; case 23: /* Transparent */ /* This is only allowable when the root depth == fvwm * visual depth otherwise bad match errors happen, * it may be even more restrictive but my tests (on * exceed 6.2) show that only == depth is necessary */ if (Pdepth != DefaultDepth(dpy, (DefaultScreen(dpy)))) { fvwm_msg( ERR, name, "can't do Transparent " "when root_depth!=fvwm_depth"); break; } has_pixmap_changed = True; free_colorset_background(cs, True); cs->pixmap = ParentRelative; cs->pixmap_type = PIXMAP_STRETCH; break; case 24: /* RootTransparent */ if (Pdepth != DefaultDepth(dpy, (DefaultScreen(dpy)))) { fvwm_msg( ERR, name, "can't do RootTransparent " "when root_depth!=fvwm_depth"); break; } free_colorset_background(cs, True); has_pixmap_changed = True; cs->pixmap_type = PIXMAP_ROOT_PIXMAP_PURE; do_reload_pixmap = True; tmp_str = PeekToken(args, &args); if (StrEquals(tmp_str, "buffer")) { cs->allows_buffered_transparency = True; } else { cs->allows_buffered_transparency = False; } cs->is_maybe_root_transparent = True; break; case 25: /* Tint */ case 26: /* PixmapTint */ case 27: /* ImageTint */ case 28: /* TintMask */ parse_simple_tint( cs, args, &tint, TINT_SUPPLIED, &has_tint_changed, &percent, "tint"); if (has_tint_changed) { cs->tint_percent = percent; } break; case 29: /* NoTint */ has_tint_changed = True; cs->tint_percent = 0; cs->color_flags &= ~TINT_SUPPLIED; break; case 30: /* fgTint */ parse_simple_tint( cs, args, &fg_tint, FG_TINT_SUPPLIED, &has_fg_tint_changed, &percent, "fgTint"); if (has_fg_tint_changed) { cs->fg_tint_percent = percent; } break; case 31: /* bgTint */ parse_simple_tint( cs, args, &bg_tint, BG_TINT_SUPPLIED, &has_bg_tint_changed, &percent, "bgTint"); if (has_bg_tint_changed) { cs->bg_tint_percent = percent; } break; case 32: /* dither */ if (cs->pixmap_args || cs->gradient_args) { has_pixmap_changed = True; do_reload_pixmap = True; } cs->dither = True; break; case 33: /* nodither */ if (cs->pixmap_args || cs->gradient_args) { has_pixmap_changed = True; do_reload_pixmap = True; } cs->dither = False; break; case 34: /* Alpha */ case 35: /* PixmapAlpha */ case 36: /* ImageAlpha */ if (GetIntegerArguments(args, NULL, &tmp, 1)) { if (tmp > 100) tmp = 100; else if (tmp < 0) tmp = 0; } else { tmp = 100; } if (tmp != cs->image_alpha_percent) { has_image_alpha_changed = True; cs->image_alpha_percent = tmp; } break; /* dither icon is not dynamic (yet) maybe a bad opt: default * to False ? */ case 37: /* ditherIcon */ cs->do_dither_icon = True; break; case 38: /* DoNotDitherIcon */ cs->do_dither_icon = False; break; case 39: /* IconTint */ parse_simple_tint( cs, args, &icon_tint, ICON_TINT_SUPPLIED, &has_icon_tint_changed, &percent, "IconTint"); if (has_icon_tint_changed) { cs->icon_tint_percent = percent; has_icon_pixels_changed = True; } break; case 40: /* NoIconTint */ has_icon_tint_changed = True; if (cs->icon_tint_percent != 0) { has_icon_pixels_changed = True; } cs->icon_tint_percent = 0; break; case 41: /* IconAlpha */ if (GetIntegerArguments(args, NULL, &tmp, 1)) { if (tmp > 100) tmp = 100; else if (tmp < 0) tmp = 0; } else { tmp = 100; } if (tmp != cs->icon_alpha_percent) { has_icon_pixels_changed = True; cs->icon_alpha_percent = tmp; } break; default: /* test for ?Gradient */ if (option[0] && StrEquals(&option[1], "Gradient")) { cs->gradient_type = toupper(option[0]); if (!IsGradientTypeSupported(cs->gradient_type)) break; has_pixmap_changed = True; free_colorset_background(cs, True); CopyString(&cs->gradient_args, args); do_reload_pixmap = True; if (cs->gradient_type == V_GRADIENT) { cs->pixmap_type = PIXMAP_STRETCH_Y; } else if (cs->gradient_type == H_GRADIENT) cs->pixmap_type = PIXMAP_STRETCH_X; else cs->pixmap_type = PIXMAP_STRETCH; } else { fvwm_msg( WARN, name, "bad colorset pixmap " "specifier %s %s", option, line); } break; } /* switch */ if (option) { free(option); option = NULL; } free(optstring); optstring = NULL; } /* while (line && *line) */ /* * ---------- change the "pixmap" tint colour ---------- */ if (has_tint_changed) { /* user specified colour */ if (tint != NULL) { Pixel old_tint = cs->tint; PictureFreeColors(dpy, Pcmap, &cs->tint, 1, 0, True); cs->tint = GetColor(tint); if (old_tint != cs->tint) { have_pixels_changed = True; } } else if (tint == NULL) { /* default */ Pixel old_tint = cs->tint; PictureFreeColors(dpy, Pcmap, &cs->tint, 1, 0, True); cs->tint = GetColor(black); if (old_tint != cs->tint) { have_pixels_changed = True; } } } /* * reload the gradient if the tint or the alpha have changed. * Do this too if we need to recompute the bg average and the * gradient is tinted (perforemence issue). */ if ((has_tint_changed || has_image_alpha_changed || (has_bg_changed && (cs->color_flags & BG_AVERAGE) && cs->tint_percent > 0)) && cs->gradient_args) { do_reload_pixmap = True; } /* * reset the pixmap if the tint or the alpha has changed */ if (!do_reload_pixmap && (has_tint_changed || has_image_alpha_changed || (has_bg_changed && cs->alpha_pixmap != None))) { if (cs->pixmap_type == PIXMAP_ROOT_PIXMAP_PURE || cs->pixmap_type == PIXMAP_ROOT_PIXMAP_TRAN) { do_reload_pixmap = True; } else if (cs->picture != NULL && cs->pixmap) { XSetClipMask(dpy, gc, cs->picture->mask); reset_cs_pixmap(cs, gc); XSetClipMask(dpy, gc, None); has_pixmap_changed = True; } } /* * (re)build the pixmap or the gradient */ if (do_reload_pixmap) { free_colorset_background(cs, False); has_pixmap_changed = True; if (cs->pixmap_type == PIXMAP_ROOT_PIXMAP_PURE || cs->pixmap_type == PIXMAP_ROOT_PIXMAP_TRAN) { cs->pixmap_type = 0; if (root_pic.pixmap) { cs->pixmap = root_pic.pixmap; cs->width = root_pic.width; cs->height = root_pic.height; cs->pixmap_type = PIXMAP_ROOT_PIXMAP_PURE; #if 0 fprintf(stderr,"Cset %i LoadRoot 0x%lx\n", n, cs->pixmap); #endif } } else if (cs->pixmap_args) { parse_pixmap(win, gc, cs, &pixmap_is_a_bitmap); } else if (cs->gradient_args) { cs->pixmap = CreateGradientPixmapFromString( dpy, win, gc, cs->gradient_type, cs->gradient_args, &w, &h, &cs->pixels, &cs->nalloc_pixels, cs->dither); cs->width = w; cs->height = h; } has_pixmap_changed = True; } if (cs->picture != NULL && cs->picture->depth != Pdepth) { pixmap_is_a_bitmap = True; } /* * ---------- change the background colour ---------- */ if (has_bg_changed || (has_pixmap_changed && (cs->color_flags & BG_AVERAGE) && cs->pixmap != None && cs->pixmap != ParentRelative && !pixmap_is_a_bitmap)) { Bool do_set_default_background = False; Pixmap average_pix = None; if (cs->color_flags & BG_AVERAGE) { if (cs->picture != NULL && cs->picture->picture != None) { average_pix = cs->picture->picture; } else if (cs->pixmap != ParentRelative) { average_pix = cs->pixmap; } if (average_pix == root_pic.pixmap) { int w; int h; XID dummy; MyXGrabServer(dpy); is_server_grabbed = True; if (!XGetGeometry( dpy, average_pix, &dummy, (int *)&dummy, (int *)&dummy, (unsigned int *)&w, (unsigned int *)&h, (unsigned int *)&dummy, (unsigned int *)&dummy)) { average_pix = None; } else { if (w != cs->width || h != cs->height) { average_pix = None; } } if (average_pix == None) { MyXUngrabServer(dpy); is_server_grabbed = False; } } } /* note: no average for bitmap */ if ((cs->color_flags & BG_AVERAGE) && average_pix) { /* calculate average background color */ XColor *colors; XImage *image; XImage *mask_image = None; unsigned int i, j, k = 0; unsigned long red = 0, blue = 0, green = 0; unsigned long tred, tblue, tgreen; double dred = 0.0, dblue = 0.0, dgreen = 0.0; has_bg_changed = True; /* create an array to store all the pixmap colors in */ /* Note: this may allocate a lot of memory: * cs->width * cs->height * 12 and then the rest of the * procedure can take a lot of times */ colors = (XColor *)safemalloc( cs->width * cs->height * sizeof(XColor)); /* get the pixmap and mask into an image */ image = XGetImage( dpy, average_pix, 0, 0, cs->width, cs->height, AllPlanes, ZPixmap); if (cs->mask != None) { mask_image = XGetImage( dpy, cs->mask, 0, 0, cs->width, cs->height, AllPlanes, ZPixmap); } if (is_server_grabbed == True) { MyXUngrabServer(dpy); } if (image != None && mask_image != None) { /* only fetch the pixels that are not masked * out */ for (i = 0; i < cs->width; i++) { for (j = 0; j < cs->height; j++) { if ( cs->mask == None || XGetPixel( mask_image, i, j) == 0) { colors[k++].pixel = XGetPixel( image, i, j); } } } } if (image != None) { XDestroyImage(image); } if (mask_image != None) { XDestroyImage(mask_image); } if (k == 0) { do_set_default_background = True; } else { /* look them all up, XQueryColors() can't * handle more than 256 */ for (i = 0; i < k; i += 256) { XQueryColors( dpy, Pcmap, &colors[i], min(k - i, 256)); } /* calculate average, add overflows in a double * .red is short, red is long */ for (i = 0; i < k; i++) { tred = red; red += colors[i].red; if (red < tred) { dred += (double)tred; red = colors[i].red; } tgreen = green; green += colors[i].green; if (green < tgreen) { dgreen += (double)tgreen; green = colors[i].green; } tblue = blue; blue += colors[i].blue; if (blue < tblue) { dblue += (double)tblue; blue = colors[i].blue; } } dred += red; dgreen += green; dblue += blue; /* get it */ color.red = dred / k; color.green = dgreen / k; color.blue = dblue / k; { Pixel old_bg = cs->bg; PictureFreeColors( dpy, Pcmap, &cs->bg, 1, 0, True); PictureAllocColor( dpy, Pcmap, &color, True); cs->bg = color.pixel; if (old_bg != cs->bg) { have_pixels_changed = True; } } } free(colors); } /* average */ else if ((cs->color_flags & BG_SUPPLIED) && bg != NULL) { /* user specified colour */ Pixel old_bg = cs->bg; PictureFreeColors(dpy, Pcmap, &cs->bg, 1, 0, True); cs->bg = GetColor(bg); if (old_bg != cs->bg) { have_pixels_changed = True; } } /* user specified */ else if (bg == NULL && has_bg_changed) { /* default */ do_set_default_background = True; } /* default */ if (do_set_default_background) { Pixel old_bg = cs->bg; PictureFreeColors(dpy, Pcmap, &cs->bg, 1, 0, True); cs->bg = GetColor(white); if (old_bg != cs->bg) { have_pixels_changed = True; } has_bg_changed = True; } if (has_bg_changed) { /* save the bg color for tinting */ cs->bg_saved = cs->bg; } } /* has_bg_changed */ /* * ---------- setup the bg tint colour ---------- */ if (has_bg_tint_changed && cs->bg_tint_percent > 0 && bg_tint != NULL) { PictureFreeColors(dpy, Pcmap, &cs->bg_tint, 1, 0, True); cs->bg_tint = GetColor(bg_tint); } /* * ---------- tint the bg colour ---------- */ if (has_bg_tint_changed || (has_bg_changed && cs->bg_tint_percent > 0)) { if (cs->bg_tint_percent == 0) { Pixel old_bg = cs->bg; PictureFreeColors(dpy, Pcmap, &cs->bg, 1, 0, True); cs->bg = cs->bg_saved; if (old_bg != cs->bg) { have_pixels_changed = True; has_bg_changed = True; } } else { Pixel old_bg = cs->bg; PictureFreeColors(dpy, Pcmap, &cs->bg, 1, 0, True); cs->bg = GetTintedPixel( cs->bg_saved, cs->bg_tint, cs->bg_tint_percent); if (old_bg != cs->bg) { have_pixels_changed = True; has_bg_changed = True; } } } /* * ---------- setup the fg tint colour ---------- */ if (has_fg_tint_changed && cs->fg_tint_percent > 0 && fg_tint != NULL) { PictureFreeColors(dpy, Pcmap, &cs->fg_tint, 1, 0, True); cs->fg_tint = GetColor(fg_tint); } /* * ---------- change the foreground colour ---------- */ if (has_fg_changed || (has_bg_changed && (cs->color_flags & FG_CONTRAST))) { if (cs->color_flags & FG_CONTRAST) { Pixel old_fg = cs->fg; /* calculate contrasting foreground color */ color.pixel = cs->bg; XQueryColor(dpy, Pcmap, &color); color.red = (color.red > 32767) ? 0 : 65535; color.green = (color.green > 32767) ? 0 : 65535; color.blue = (color.blue > 32767) ? 0 : 65535; PictureFreeColors(dpy, Pcmap, &cs->fg, 1, 0, True); PictureAllocColor(dpy, Pcmap, &color, True); cs->fg = color.pixel; if (old_fg != cs->fg) { have_pixels_changed = True; has_fg_changed = 1; } } /* contrast */ else if ((cs->color_flags & FG_SUPPLIED) && fg != NULL) { /* user specified colour */ Pixel old_fg = cs->fg; PictureFreeColors(dpy, Pcmap, &cs->fg, 1, 0, True); cs->fg = GetColor(fg); if (old_fg != cs->fg) { have_pixels_changed = True; has_fg_changed = 1; } } /* user specified */ else if (fg == NULL) { /* default */ Pixel old_fg = cs->fg; PictureFreeColors(dpy, Pcmap, &cs->fg, 1, 0, True); cs->fg = GetColor(black); if (old_fg != cs->fg) { have_pixels_changed = True; has_fg_changed = 1; } } /* save the fg color for tinting */ cs->fg_saved = cs->fg; } /* has_fg_changed */ /* * ---------- tint the foreground colour ---------- */ if (has_fg_tint_changed || (has_fg_changed && cs->fg_tint_percent > 0)) { if (cs->fg_tint_percent == 0) { Pixel old_fg = cs->fg; PictureFreeColors(dpy, Pcmap, &cs->fg, 1, 0, True); cs->fg = cs->fg_saved; if (old_fg != cs->fg) { have_pixels_changed = True; has_fg_changed = 1; } } else { Pixel old_fg = cs->fg; PictureFreeColors(dpy, Pcmap, &cs->fg, 1, 0, True); cs->fg = GetTintedPixel( cs->fg_saved, cs->fg_tint, cs->fg_tint_percent); if (old_fg != cs->fg) { have_pixels_changed = True; has_fg_changed = 1; } } } /* * ---------- change the hilight colour ---------- */ if (has_hi_changed || (has_bg_changed && !(cs->color_flags & HI_SUPPLIED))) { has_hi_changed = 1; if ((cs->color_flags & HI_SUPPLIED) && hi != NULL) { /* user specified colour */ Pixel old_hilite = cs->hilite; PictureFreeColors(dpy, Pcmap, &cs->hilite, 1, 0, True); cs->hilite = GetColor(hi); if (old_hilite != cs->hilite) { have_pixels_changed = True; } } /* user specified */ else if (hi == NULL) { Pixel old_hilite = cs->hilite; PictureFreeColors(dpy, Pcmap, &cs->hilite, 1, 0, True); cs->hilite = GetHilite(cs->bg); if (old_hilite != cs->hilite) { have_pixels_changed = True; } } } /* has_hi_changed */ /* * ---------- change the shadow colour ---------- */ if (has_sh_changed || (has_bg_changed && !(cs->color_flags & SH_SUPPLIED))) { has_sh_changed = 1; if ((cs->color_flags & SH_SUPPLIED) && sh != NULL) { /* user specified colour */ Pixel old_shadow = cs->shadow; PictureFreeColors(dpy, Pcmap, &cs->shadow, 1, 0, True); cs->shadow = GetColor(sh); if (old_shadow != cs->shadow) { have_pixels_changed = True; } } /* user specified */ else if (sh == NULL) { Pixel old_shadow = cs->shadow; PictureFreeColors(dpy, Pcmap, &cs->shadow, 1, 0, True); cs->shadow = GetShadow(cs->bg); if (old_shadow != cs->shadow) { have_pixels_changed = True; } } } /* has_sh_changed */ /* * ---------- change the shadow foreground colour ---------- */ if (has_fgsh_changed || ((has_fg_changed || has_bg_changed) && !(cs->color_flags & FGSH_SUPPLIED))) { has_fgsh_changed = 1; if ((cs->color_flags & FGSH_SUPPLIED) && fgsh != NULL) { /* user specified colour */ Pixel old_fgsh = cs->fgsh; PictureFreeColors(dpy, Pcmap, &cs->fgsh, 1, 0, True); cs->fgsh = GetColor(fgsh); if (old_fgsh != cs->fgsh) { have_pixels_changed = True; } } /* user specified */ else if (fgsh == NULL) { Pixel old_fgsh = cs->fgsh; PictureFreeColors(dpy, Pcmap, &cs->fgsh, 1, 0, True); cs->fgsh = GetForeShadow(cs->fg, cs->bg); if (old_fgsh != cs->fgsh) { have_pixels_changed = True; } } } /* has_fgsh_changed */ /* * ------- the pixmap is a bitmap: create here cs->pixmap ------- */ if (cs->picture != None && pixmap_is_a_bitmap && (has_pixmap_changed || has_bg_changed)) { cs->pixmap = XCreatePixmap( dpy, win, cs->width, cs->height, Pdepth); XSetBackground(dpy, gc, cs->bg); XSetForeground(dpy, gc, cs->fg); reset_cs_pixmap(cs, gc); } /* * ------- change the masked out parts of the background pixmap ------- */ if (cs->pixmap != None && cs->pixmap != ParentRelative && (!CSETS_IS_TRANSPARENT_ROOT(cs)|| cs->allows_buffered_transparency) && (cs->mask != None || cs->alpha_pixmap != None || cs->image_alpha_percent < 100 || cs->tint_percent > 0) && (has_pixmap_changed || has_bg_changed || has_image_alpha_changed || has_tint_changed)) { /* Now that we know the background colour we can update the * pixmap background. */ FvwmRenderAttributes fra; Pixmap temp, mask, alpha; memset(&fra, 0, sizeof(fra)); temp = XCreatePixmap(dpy, win, cs->width, cs->height, Pdepth); if (cs->picture != NULL) { mask = cs->picture->mask; alpha = cs->picture->alpha; } else { mask = None; alpha = None; } XSetForeground(dpy, gc, cs->bg); XFillRectangle( dpy, temp, gc, 0, 0, cs->width, cs->height); fra.mask = FRAM_HAVE_ADDED_ALPHA | FRAM_HAVE_TINT; fra.added_alpha_percent = cs->image_alpha_percent; fra.tint = cs->tint; fra.tint_percent = cs->tint_percent; PGraphicsRenderPixmaps( dpy, win, cs->pixmap, mask, alpha, Pdepth, &fra, temp, gc, Scr.MonoGC, Scr.AlphaGC, 0, 0, cs->width, cs->height, 0, 0, cs->width, cs->height, False); if (cs->pixmap != root_pic.pixmap) { add_to_junk(cs->pixmap); } cs->pixmap = temp; has_pixmap_changed = True; if (CSETS_IS_TRANSPARENT_ROOT(cs)) { cs->pixmap_type = PIXMAP_ROOT_PIXMAP_TRAN; } } /* has_pixmap_changed */ /* * ---------- change the icon tint colour ---------- */ if (has_icon_tint_changed) { /* user specified colour */ if (icon_tint != NULL) { Pixel old_tint = cs->icon_tint; PictureFreeColors( dpy, Pcmap, &cs->icon_tint, 1, 0, True); cs->icon_tint = GetColor(icon_tint); if (old_tint != cs->icon_tint) { has_icon_pixels_changed = True; } } else { /* default */ Pixel old_tint = cs->icon_tint; PictureFreeColors( dpy, Pcmap, &cs->icon_tint, 1, 0, True); cs->icon_tint = GetColor(black); if (old_tint != cs->icon_tint) { has_icon_pixels_changed = True; } } } /* * ---------- send new colorset to fvwm and clean up ---------- */ /* make sure the server has this to avoid races */ XSync(dpy, False); /* inform modules of the change */ if (have_pixels_changed || has_pixmap_changed || has_shape_changed || has_fg_alpha_changed || has_icon_pixels_changed) { BroadcastColorset(n); } if (fg) { free(fg); } if (bg) { free(bg); } if (hi) { free(hi); } if (sh) { free(sh); } if (fgsh) { free(fgsh); } if (tint) { free(tint); } if (fg_tint) { free(fg_tint); } if (bg_tint) { free(bg_tint); } if (icon_tint) { free(icon_tint); } return; } /* * alloc_colorset() grows the size of the Colorset array to include set n * colorset_t *Colorset will be altered * returns the address of the member */ void alloc_colorset(int n) { /* do nothing if it already exists */ if (n < nColorsets) { return; } else { Colorset = (colorset_t *)saferealloc( (char *)Colorset, (n + 1) * sizeof(colorset_t)); memset( &Colorset[nColorsets], 0, (n + 1 - nColorsets) * sizeof(colorset_t)); } if (n == 0) { update_root_pixmap(0); } /* initialize new colorsets to black on gray */ while (nColorsets <= n) { colorset_t *ncs = &Colorset[nColorsets]; if (PictureUseBWOnly()) { char g_bits[] = {0x0a, 0x05, 0x0a, 0x05, 0x08, 0x02, 0x08, 0x02, 0x01, 0x02, 0x04, 0x08}; /* monochrome monitors get black on white */ /* with a gray pixmap background */ ncs->fg = GetColor(black); ncs->bg = GetColor(white); ncs->hilite = GetColor(white); ncs->shadow = GetColor(black); ncs->fgsh = GetColor(white); ncs->tint = GetColor(black); ncs->icon_tint = GetColor(black); ncs->pixmap = XCreatePixmapFromBitmapData( dpy, Scr.NoFocusWin, &g_bits[4 * (nColorsets % 3)], 4, 4, PictureBlackPixel(), PictureWhitePixel(), Pdepth); ncs->width = 4; ncs->height = 4; } else { ncs->fg = GetColor(black); ncs->bg = GetColor(gray); ncs->hilite = GetHilite(ncs->bg); ncs->shadow = GetShadow(ncs->bg); ncs->fgsh = GetForeShadow(ncs->fg, ncs->bg); ncs->tint = GetColor(black); ncs->icon_tint = GetColor(black); } ncs->fg_tint = ncs->bg_tint = GetColor(black); /* set flags for fg contrast, bg average */ /* in case just a pixmap is given */ ncs->color_flags = FG_CONTRAST | BG_AVERAGE; ncs->fg_saved = ncs->fg; ncs->fg_alpha_percent = 100; ncs->image_alpha_percent = 100; ncs->icon_alpha_percent = 100; ncs->tint_percent = 0; ncs->icon_tint_percent = 0; ncs->fg_tint_percent = ncs->bg_tint_percent = 0; ncs->dither = (PictureDitherByDefault())? True:False; nColorsets++; } } void update_root_transparent_colorset(Atom prop) { int i; colorset_t *cs; root_pic.old_pixmap = root_pic.pixmap; update_root_pixmap(prop); #if 0 if (!root_pic.pixmap) { return; } #endif for (i=0; i < nColorsets; i++) { Bool root_trans = False; cs = &Colorset[i]; if (cs->is_maybe_root_transparent && cs->allows_buffered_transparency) { parse_colorset(i, "RootTransparent buffer"); root_trans = True; } else if (cs->is_maybe_root_transparent) { parse_colorset(i, "RootTransparent"); root_trans = True; } if (root_trans) { update_fvwm_colorset(i); } } } /* ---------------------------- builtin commands ---------------------------- */ void CMD_ReadWriteColors(F_CMD_ARGS) { fvwm_msg(WARN, "CMD_ReadWriteColors", "ReadWriteColors is obsolete"); return; } void CMD_Colorset(F_CMD_ARGS) { int n; char *token; if (GetIntegerArguments(action, &token, &n, 1) != 1) { return; } if (n < 0) { return; } if (token == NULL) { return; } parse_colorset(n, token); update_fvwm_colorset(n); return; } void CMD_CleanupColorsets(F_CMD_ARGS) { cleanup_colorsets(); } fvwm-2.7.0/fvwm/menubindings.c0000644000175000017500000005742314147024700013237 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include "libs/Parse.h" #include "libs/Bindings.h" #include "libs/charmap.h" #include "libs/Flocale.h" #include "libs/wcontext.h" #include "fvwm.h" #include "fvwm.h" #include "externs.h" #include "execcontext.h" #include "misc.h" #include "screen.h" #include "bindings.h" #include "move_resize.h" #include "menudim.h" #include "menustyle.h" #include "menuitem.h" #include "menuroot.h" #include "menuparameters.h" #include "menugeometry.h" #include "menubindings.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* menu bindings are kept in a local binding list separate from other * bindings*/ static Binding *menu_bindings_regular = NULL; static Binding *menu_bindings_fallback = NULL; static Binding **menu_bindings = NULL; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ /* * Returns the position of the item in the menu, but counts * only items that can be selected (i.e. nor separators or * titles). The count begins with 0. */ static int get_selectable_item_index( MenuRoot *mr, MenuItem *mi_target, int *ret_sections) { int i = 0; int s = 0; MenuItem *mi; int is_last_selectable = 0; for (mi = MR_FIRST_ITEM(mr); mi && mi != mi_target; mi = MI_NEXT_ITEM(mi)) { if (MI_IS_SELECTABLE(mi)) { i++; is_last_selectable = 1; } else if (is_last_selectable == 1) { s++; is_last_selectable = 0; } } if (ret_sections) { *ret_sections = s; } if (mi == mi_target) { return i; } return -1; } static MenuItem *get_selectable_item_from_index(MenuRoot *mr, int index) { int i = -1; MenuItem *mi; MenuItem *mi_last_ok = NULL; for (mi = MR_FIRST_ITEM(mr); mi && (i < index || mi_last_ok == NULL); mi=MI_NEXT_ITEM(mi)) { if (MI_IS_SELECTABLE(mi)) { mi_last_ok = mi; i++; } } return mi_last_ok; } static MenuItem *get_selectable_item_from_section(MenuRoot *mr, int section) { int i = 0; MenuItem *mi; MenuItem *mi_last_ok = NULL; int is_last_selectable = 0; for ( mi = MR_FIRST_ITEM(mr); mi && (i <= section || mi_last_ok == NULL); mi=MI_NEXT_ITEM(mi)) { if (MI_IS_SELECTABLE(mi)) { if (!is_last_selectable) { mi_last_ok = mi; is_last_selectable = 1; } } else if (is_last_selectable) { i++; is_last_selectable = 0; } } return mi_last_ok; } static int get_selectable_item_count(MenuRoot *mr, int *ret_sections) { int count; count = get_selectable_item_index(mr, MR_LAST_ITEM(mr), ret_sections); if (MR_LAST_ITEM(mr) && MI_IS_SELECTABLE(MR_LAST_ITEM(mr))) { count++; } return count; } static Binding *__menu_binding_is_mouse( Binding *blist, XEvent* event, int context) { Binding *b; int real_mod; real_mod = event->xbutton.state - (1 << (7 + event->xbutton.button)); for (b = blist; b != NULL; b = b->NextBinding) { if ( BIND_IS_MOUSE_BINDING(b->type) && (b->Button_Key == 0 || event->xbutton.button == b->Button_Key) && (b->Modifier == AnyModifier || MaskUsedModifiers(b->Modifier) == MaskUsedModifiers(real_mod)) && (b->Context == C_MENU || (b->Context & context) != C_MENU)) { break; } } return b; } static void parse_menu_action( struct MenuRoot *mr, const char *action, menu_shortcut_action *saction, int *items_to_move, int *do_skip_section, char **ret_cmd) { char *optlist[] = { "MenuClose", "MenuEnterContinuation", "MenuEnterSubmenu", "MenuLeaveSubmenu", "MenuMoveCursor", "MenuCursorLeft", "MenuCursorRight", "MenuSelectItem", "MenuScroll", "MenuTearOff", "MenuCloseAndExec", NULL }; int index; char *options; int num; int suffix[2]; int count[2]; *ret_cmd = NULL; options = GetNextTokenIndex((char *)action, optlist, 0, &index); switch (index) { case 0: /* MenuClose */ *saction = SA_ABORT; break; case 1: /* MenuEnterContinuation */ *saction = (MR_CONTINUATION_MENU(mr) != NULL) ? SA_CONTINUE : SA_ENTER; break; case 2: /* MenuEnterSubmenu */ *saction = SA_ENTER; break; case 3: /* MenuLeaveSubmenu */ *saction = SA_LEAVE; break; case 4: /* MenuMoveCursor */ num = GetSuffixedIntegerArguments(options, NULL, count, 2, "s", suffix); if (num == 2) { if (suffix[0] != 0 || count[0] != 0) { fvwm_msg(ERR, "parse_menu_action", "invalid MenuMoveCursor arguments " "'%s'", options); *saction = SA_NONE; break; } if (count[1] < 0) { *saction = SA_LAST; *items_to_move = 1 + count[1]; } else { *saction = SA_FIRST; *items_to_move = count[1]; } if (suffix[1] == 1) { *do_skip_section = 1; } } else if (num == 1) { *saction = SA_MOVE_ITEMS; *items_to_move = count[0]; if (suffix[0] == 1) { *do_skip_section = 1; } } else { fvwm_msg(ERR, "parse_menu_action", "invalid MenuMoveCursor arguments '%s'", options); *saction = SA_NONE; break; } break; case 5: /* MenuCursorLeft */ *saction = (MST_USE_LEFT_SUBMENUS(mr)) ? SA_ENTER : SA_LEAVE; break; case 6: /* MenuCursorRight */ *saction = (MST_USE_LEFT_SUBMENUS(mr)) ? SA_LEAVE : SA_ENTER; break; case 7: /* MenuSelectItem */ *saction = SA_SELECT; break; case 8: /* MenuScroll */ if (MST_MOUSE_WHEEL(mr) == MMW_OFF) { *saction = SA_SELECT; } else { num = GetSuffixedIntegerArguments(options, NULL, count, 1, "s", suffix); if (num == 1) { *saction = SA_SCROLL; *items_to_move = count[0]; if (suffix[0] == 1) { *do_skip_section = 1; } } else { fvwm_msg(ERR, "parse_menu_action", "invalid MenuScroll arguments '%s'", options); *saction = SA_NONE; break; } } break; case 9: /* MenuTearOff */ *saction = SA_TEAROFF; break; case 10: /* MenuCloseAndExecute */ *saction = SA_EXEC_CMD; *ret_cmd = options; break; default: fvwm_msg( ERR, "parse_menu_action", "unknown action '%s'", action); *saction = SA_NONE; } return; } static Binding *__menu_binding_is_key( Binding *blist, XEvent* event, int context) { Binding *b; for (b = blist; b != NULL; b = b->NextBinding) { if ( BIND_IS_KEY_BINDING(b->type) && event->xkey.keycode == b->Button_Key && (b->Modifier == AnyModifier || MaskUsedModifiers(b->Modifier) == MaskUsedModifiers(event->xkey.state)) && (b->Context == C_MENU || (b->Context & context) != C_MENU)) { break; } } return b; } /* ---------------------------- interface functions ------------------------ */ void menu_bindings_startup_complete(void) { menu_bindings = &menu_bindings_regular; return; } Binding *menu_binding_is_mouse(XEvent* event, int context) { Binding *b; b = __menu_binding_is_mouse(menu_bindings_regular, event, context); if (b == NULL) { b = __menu_binding_is_mouse( menu_bindings_fallback, event, context); } return b; } Binding *menu_binding_is_key(XEvent* event, int context) { Binding *b; b = __menu_binding_is_key(menu_bindings_regular, event, context); if (b == NULL) { b = __menu_binding_is_key( menu_bindings_fallback, event, context); } return b; } int menu_binding( Display *dpy, binding_t type, int button, KeySym keysym, int context, int modifier, char *action, char *menu_style) { Binding *rmlist; int rc; Bool dummy; if (menu_bindings == NULL) { menu_bindings = &menu_bindings_fallback; } rmlist = NULL; if (~(~context | C_MENU | C_TITLE | C_MENU_ITEM | C_SIDEBAR) != 0) { fvwm_msg( ERR, "menu_binding", "invalid context in combination with menu context."); return 1; } if (menu_style != NULL) { /*!!! fixme - make either match a menu style or a menu name */ fvwm_msg( ERR, "menu_binding", "a window name may not be" " specified without a menu context."); return 1; } /* * Remove the "old" bindings if any */ /* BEGIN remove */ CollectBindingList( dpy, menu_bindings, &rmlist, &dummy, type, STROKE_ARG(NULL) button, keysym, modifier, context, menu_style); if (rmlist != NULL) { FreeBindingList(rmlist); } else if ( keysym == 0 && button != 0 && modifier == 0 && strcmp(action,"-") == 0 && context == C_MENU) { /* Warn if Mouse n M N - occurs without removing any binding. The user most likely want Mouse n MT A - instead. */ fvwm_msg( WARN, "menu_binding", "The syntax for disabling the tear off button has " "changed."); } if (strcmp(action,"-") == 0) { return 0; } /* END remove */ if ((modifier & AnyModifier) && (modifier & (~AnyModifier))) { fvwm_msg( WARN, "menu_binding", "Binding specified AnyModifier" " and other modifiers too. Excess modifiers are" " ignored."); modifier = AnyModifier; } /* Warn about Mouse n M N TearOff. */ if ( keysym == 0 && button != 0 && modifier == 0 && strcasecmp(action,"tearoff") == 0 && context == C_MENU) { fvwm_msg(OLD, "menu_binding", "The syntax for disabling the tear off button has " "changed. The TearOff action is no longer possible " "in menu bindings."); } rc = AddBinding( dpy, menu_bindings, type, STROKE_ARG(NULL) button, keysym, NULL, modifier, context, (void *)action, NULL, menu_style); return rc; } void menu_shortcuts( struct MenuRoot *mr, struct MenuParameters *pmp, struct MenuReturn *pmret, XEvent *event, struct MenuItem **pmi_current, double_keypress *pdkp, int *ret_menu_x, int *ret_menu_y) { int with_control; int with_shift; int with_meta; KeySym keysym; char ckeychar; int ikeychar; MenuItem *new_item; MenuItem *mi_current; int index; int mx; int my; int menu_x; int menu_y; int menu_width; int menu_height; int items_to_move; int do_skip_section; menu_shortcut_action saction; Binding *binding; int context; int is_geometry_known; char *command; ckeychar = 0; new_item = NULL; mi_current = pmi_current ? *pmi_current : NULL; do_skip_section = 0; saction = SA_NONE; context = C_MENU; is_geometry_known = 0; context = C_MENU; command = 0; if (mi_current) { if (MI_IS_TITLE(mi_current)) { context |= C_TITLE; } else { /* menu item context, use I (icon) for it */ context |= C_MENU_ITEM; } } else { if ( menu_get_geometry( mr, &JunkRoot, &menu_x, &menu_y, &menu_width, &menu_height, &JunkBW, &JunkDepth)) { is_geometry_known = 1; if ( FQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, &mx, &my, &JunkX, &JunkY, &JunkMask) == 0) { /* pointer is on a different screen */ mx = 0; my = 0; } else if ( mx >= menu_x && mx < menu_x + menu_width && my >= menu_y && my < menu_y + menu_height) { /* pointer is on the meny somewhere not over * an item */ if (my < menu_y + MST_BORDER_WIDTH(mr)) { /* upper border context (-)*/ context |= C_SB_TOP; } else if ( my >= menu_y + menu_height - MST_BORDER_WIDTH(mr)) { /* lower border context (_) */ context |= C_SB_BOTTOM; } else if (mx < menu_x + MR_ITEM_X_OFFSET(mr)) { /* left border or left sidepic */ context |= C_SB_LEFT; } else if (mx < menu_x + MST_BORDER_WIDTH(mr)) { /* left border context ([)*/ context |= C_SB_LEFT; } else if ( mx >= menu_x + MR_ITEM_X_OFFSET(mr) + MR_ITEM_WIDTH(mr)) { /* right sidepic or right border */ context |= C_SB_RIGHT; } else if ( mx >= menu_x + menu_width - MST_BORDER_WIDTH(mr)) { /* right border context (])*/ context |= C_SB_RIGHT; } } } else { fvwm_msg( ERR, "menu_shortcuts", "can't get geometry of" " menu %s", MR_NAME(mr)); } } if (event->type == KeyRelease) { /* This function is only called with a KeyRelease event if the * user released the 'select' key (s)he configured. */ pmret->rc = MENU_SELECTED; return; } items_to_move = 0; pmret->rc = MENU_NOP; /*** handle mouse events ***/ if (event->type == ButtonRelease) { /*** Read the control keys stats ***/ with_control = event->xbutton.state & ControlMask ? 1 : 0; with_shift = event->xbutton.state & ShiftMask ? 1: 0; with_meta = event->xbutton.state & Mod1Mask ? 1: 0; /** handle menu bindings **/ binding = menu_binding_is_mouse(event, context); if (binding != NULL) { parse_menu_action( mr, binding->Action, &saction, &items_to_move, &do_skip_section, &command); } index = 0; ikeychar = 0; } else /* Should be KeyPressed */ { /*** Read the control keys stats ***/ with_control = event->xkey.state & ControlMask? 1 : 0; with_shift = event->xkey.state & ShiftMask? 1: 0; with_meta = event->xkey.state & Mod1Mask? 1: 0; /*** handle double-keypress ***/ if (pdkp->timestamp && fev_get_evtime() - pdkp->timestamp < MST_DOUBLE_CLICK_TIME(pmp->menu) && event->xkey.state == pdkp->keystate && event->xkey.keycode == pdkp->keycode) { *pmi_current = NULL; pmret->rc = MENU_DOUBLE_CLICKED; return; } pdkp->timestamp = 0; /*** find out the key ***/ /* Is it okay to treat keysym-s as Ascii? * No, because the keypad numbers don't work. * Use XlookupString */ index = XLookupString(&(event->xkey), &ckeychar, 1, &keysym, NULL); ikeychar = (int)ckeychar; } /*** Try to match hot keys ***/ /* Need isascii here - isgraph might coredump! */ if (index == 1 && isascii(ikeychar) && isgraph(ikeychar) && with_control == 0 && with_meta == 0) { /* allow any printable character to be a keysym, but be sure * control isn't pressed */ MenuItem *mi; MenuItem *mi1; int key; int countHotkey = 0; /* if this is a letter set it to lower case */ if (isupper(ikeychar)) { ikeychar = tolower(ikeychar) ; } /* MMH mikehan@best.com 2/7/99 * Multiple hotkeys per menu * Search menu for matching hotkey; * remember how many we found and where we found it */ mi = (mi_current == NULL || mi_current == MR_LAST_ITEM(mr)) ? MR_FIRST_ITEM(mr) : MI_NEXT_ITEM(mi_current); mi1 = mi; do { if (MI_HAS_HOTKEY(mi) && !MI_IS_TITLE(mi) && (!MI_IS_HOTKEY_AUTOMATIC(mi) || MST_USE_AUTOMATIC_HOTKEYS(mr))) { key = (MI_LABEL(mi)[(int)MI_HOTKEY_COLUMN(mi)]) [MI_HOTKEY_COFFSET(mi)]; key = tolower(key); if (ikeychar == key) { if (++countHotkey == 1) { new_item = mi; } } } mi = (mi == MR_LAST_ITEM(mr)) ? MR_FIRST_ITEM(mr) : MI_NEXT_ITEM(mi); } while (mi != mi1); /* For multiple instances of a single hotkey, just move the * selection */ /* TA: 2011-07-24: But if the user has turned off * "UniqueHotkeyActivatedImmediate", keep the menu open until * the user has asked for that entry to be enacted. This also * implies the style "TitleWarpOff" and we're not over a popup * item, in which case the pointer is warped to the submenu in * the usual way. */ if ((countHotkey > 1) || (countHotkey >=1 && ( (!MST_DO_WARP_TO_TITLE(mr) || !MI_IS_POPUP(new_item)) ) && !MST_HOTKEY_ACTIVATES_IMMEDIATE(mr))) { *pmi_current = new_item; pmret->rc = MENU_NEWITEM; return; } /* Do things the old way for unique hotkeys in the menu */ else if (countHotkey == 1) { *pmi_current = new_item; if (new_item && MI_IS_POPUP(new_item)) { pmret->rc = MENU_POPUP; } else { pmret->rc = MENU_SELECTED; } return; } /* MMH mikehan@best.com 2/7/99 */ } /*** now determine the action to take ***/ /** handle menu key bindings **/ if ( event->type == KeyPress && keysym == XK_Escape && with_control == 0 && with_shift == 0 && with_meta == 0) { /* Don't allow override of Escape with no modifiers */ saction = SA_ABORT; } else if (event->type == KeyPress) { binding = menu_binding_is_key(event, context); if (binding != NULL) { parse_menu_action( mr, binding->Action, &saction, &items_to_move, &do_skip_section, &command); } } if ( !mi_current && (saction == SA_ENTER || saction == SA_MOVE_ITEMS || saction == SA_SELECT || saction == SA_SCROLL)) { if (is_geometry_known) { if (my < menu_y + MST_BORDER_WIDTH(mr)) { saction = SA_FIRST; } else if (my > menu_y + menu_height - MST_BORDER_WIDTH(mr)) { saction = SA_LAST; } else { saction = SA_WARPBACK; } } else { saction = SA_FIRST; } } /*** execute the necessary actions ***/ switch (saction) { case SA_ENTER: if (mi_current && MI_IS_POPUP(mi_current)) { pmret->rc = MENU_POPUP; } else { pmret->rc = MENU_NOP; } break; case SA_LEAVE: pmret->rc = (MR_IS_TEAR_OFF_MENU(mr)) ? MENU_NOP : MENU_POPDOWN; break; case SA_FIRST: if (do_skip_section) { *pmi_current = get_selectable_item_from_section( mr, items_to_move); } else { *pmi_current = get_selectable_item_from_index( mr, items_to_move); } if (*pmi_current != NULL) { pmret->rc = MENU_NEWITEM; } else { pmret->rc = MENU_NOP; } break; case SA_LAST: if (do_skip_section) { get_selectable_item_count(mr, &index); index += items_to_move; if (index < 0) { index = 0; } *pmi_current = get_selectable_item_from_section( mr, index); if (*pmi_current != NULL) { pmret->rc = MENU_NEWITEM; } else { pmret->rc = MENU_NOP; } } else { index = get_selectable_item_count(mr, NULL); if (index > 0) { index += items_to_move; if (index < 0) { index = 0; } *pmi_current = get_selectable_item_from_index( mr, index); pmret->rc = (*pmi_current) ? MENU_NEWITEM : MENU_NOP; } else { pmret->rc = MENU_NOP; } } break; case SA_MOVE_ITEMS: if (do_skip_section) { int section; int count; get_selectable_item_count(mr, &count); get_selectable_item_index(mr, mi_current, §ion); section += items_to_move; if (section < 0) section = count; else if (section > count) section = 0; index = section; } else if (items_to_move < 0) { index = get_selectable_item_index( mr, mi_current, NULL); if (index == 0) /* wraparound */ index = get_selectable_item_count(mr, NULL); else { index += items_to_move; } } else { index = get_selectable_item_index( mr, mi_current, NULL) + items_to_move; /* correct for the case that we're between items */ if (!MI_IS_SELECTABLE(mi_current)) { index--; } } if (do_skip_section) { new_item = get_selectable_item_from_section(mr, index); } else { new_item = get_selectable_item_from_index(mr, index); if (items_to_move > 0 && new_item == mi_current) { new_item = get_selectable_item_from_index(mr, 0); } } if (new_item) { *pmi_current = new_item; pmret->rc = MENU_NEWITEM; } else { pmret->rc = MENU_NOP; } break; case SA_CONTINUE: *pmi_current = MR_LAST_ITEM(mr); if (*pmi_current && MI_IS_POPUP(*pmi_current)) { /* enter the submenu */ pmret->rc = MENU_POPUP; } else { /* do nothing */ *pmi_current = mi_current; pmret->rc = MENU_NOP; } break; case SA_WARPBACK: /* Warp the pointer back into the menu. */ FWarpPointer( dpy, 0, MR_WINDOW(mr), 0, 0, 0, 0, menudim_middle_x_offset(&MR_DIM(mr)), my - menu_y); pmret->rc = MENU_NEWITEM_FIND; break; case SA_SELECT: pmret->rc = MENU_SELECTED; return; case SA_ABORT: pmret->rc = (MR_IS_TEAR_OFF_MENU(mr)) ? MENU_KILL_TEAR_OFF_MENU : MENU_ABORTED; return; case SA_TEAROFF: pmret->rc = (MR_IS_TEAR_OFF_MENU(mr)) ? MENU_NOP : MENU_TEAR_OFF; return; case SA_SCROLL: if (MST_MOUSE_WHEEL(mr) == MMW_MENU) { items_to_move *= -1; } if ( !menu_get_outer_geometry( mr, pmp, &JunkRoot, &menu_x, &menu_y, &JunkWidth, &menu_height, &JunkBW, &JunkDepth)) { fvwm_msg( ERR, "menu_shortcuts", "can't get geometry of menu %s", MR_NAME(mr)); return; } if (do_skip_section) { int count; get_selectable_item_count(mr, &count); get_selectable_item_index(mr, mi_current, &index); index += items_to_move; if (index < 0) { index = 0; } else if (index > count) { index = count; } new_item = get_selectable_item_from_section(mr, index); } else { index = get_selectable_item_index( mr, mi_current, NULL); if (items_to_move > 0 && !MI_IS_SELECTABLE(mi_current)) { index--; } index += items_to_move; new_item = get_selectable_item_from_index(mr, index); } if ( new_item && ((items_to_move < 0 && MI_Y_OFFSET(new_item) > MI_Y_OFFSET(mi_current)) || (items_to_move > 0 && MI_Y_OFFSET(new_item) < MI_Y_OFFSET(mi_current)))) { /* never scroll in the "wrong" direction */ new_item = NULL; } if (new_item) { *pmi_current = new_item; pmret->rc = MENU_NEWITEM; /* Have to work with relative positions or tear off * menus will be hard to reposition */ if ( FQueryPointer( dpy, MR_WINDOW(mr), &JunkRoot, &JunkChild, &JunkX, &JunkY, &mx, &my, &JunkMask) == 0) { /* This should not happen */ mx = 0; my = 0; } if (MST_MOUSE_WHEEL(mr) == MMW_POINTER) { if (event->type == ButtonRelease) { FWarpPointer( dpy, 0, 0, 0, 0, 0, 0, 0, -my + menuitem_middle_y_offset( new_item, MR_STYLE(mr))); } /* pointer wrapped elsewhere for key events */ } else { int old_y = menu_y; menu_y += my - menuitem_middle_y_offset( new_item, MR_STYLE(mr)); if ( !MST_SCROLL_OFF_PAGE(mr) && menu_height < MR_SCREEN_HEIGHT(mr)) { if (menu_y < 0) { FWarpPointer(dpy, 0, 0, 0, 0, 0, 0, 0,-menu_y); menu_y=0; } if ( menu_y + menu_height > MR_SCREEN_HEIGHT(mr)) { FWarpPointer( dpy, 0, 0, 0, 0, 0, 0, 0, MR_SCREEN_HEIGHT(mr) - menu_y - menu_height); menu_y = MR_SCREEN_HEIGHT(mr) - menu_height; } } if (old_y != menu_y) { pmret->rc = MENU_NEWITEM_MOVEMENU; *ret_menu_x = menu_x; *ret_menu_y = menu_y; } else { pmret->rc = MENU_NEWITEM; } } } else { pmret->rc = MENU_NOP; } break; case SA_EXEC_CMD: pmret->rc = MENU_EXEC_CMD; *pmp->ret_paction = command; break; case SA_NONE: default: pmret->rc = MENU_NOP; break; } if (saction != SA_SCROLL && pmret->rc == MENU_NEWITEM) { if (!menu_get_outer_geometry( mr, pmp, &JunkRoot, &menu_x, &menu_y, &JunkWidth, &menu_height, &JunkBW, &JunkDepth)) { fvwm_msg( ERR, "menu_shortcuts", "can't get geometry of menu %s", MR_NAME(mr)); return; } if (menu_y < 0 || menu_y + menu_height > MR_SCREEN_HEIGHT(mr)) { menu_y = (menu_y < 0) ? 0 : MR_SCREEN_HEIGHT(mr) - menu_height; pmret->rc = MENU_NEWITEM_MOVEMENU; *ret_menu_x = menu_x; *ret_menu_y = menu_y; } } return; } fvwm-2.7.0/fvwm/decorations.h0000644000175000017500000000206014147024700013057 00000000000000/* -*-c-*- */ #ifndef DECORATIONS_H #define DECORATIONS_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ typedef enum { RQORIG_PROGRAM = False, RQORIG_PROGRAM_US = True, RQORIG_MODULE_INPUT, RQORIG_FVWM_USER, } request_origin_t; /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ void GetMwmHints(FvwmWindow *t); void GetOlHints(FvwmWindow *t); void SelectDecor(FvwmWindow *t, window_style *pstyle, short *buttons); Bool is_function_allowed( int function, char *action_string, const FvwmWindow *t, request_origin_t request_origin, Bool do_allow_override_mwm_hints); #endif /* DECORATIONS_H */ fvwm-2.7.0/fvwm/bindings.c0000644000175000017500000004010614147024700012340 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include "libs/fvwmlib.h" #include "libs/charmap.h" #include "libs/wcontext.h" #include "libs/modifiers.h" #include "libs/Parse.h" #include "libs/Strings.h" #include "libs/defaults.h" #include "fvwm.h" #include "externs.h" #include "cursor.h" #include "functions.h" #include "bindings.h" #include "module_interface.h" #include "misc.h" #include "screen.h" #include "focus.h" #include "menubindings.h" #include "move_resize.h" /* for placement_binding */ #ifdef HAVE_STROKE #include "stroke.h" #endif /* HAVE_STROKE */ /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ static int mods_unused = DEFAULT_MODS_UNUSED; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ static void update_nr_buttons( int contexts, int *nr_left_buttons, int *nr_right_buttons, Bool do_set) { int i; int l = *nr_left_buttons; int r = *nr_right_buttons; if (contexts == C_ALL) { return; } /* check for nr_left_buttons */ for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; i += 2) { if ((contexts & (C_L1 << i))) { if (do_set || *nr_left_buttons <= i / 2) { *nr_left_buttons = i / 2 + 1; } } } /* check for nr_right_buttons */ for (i = 1; i < NUMBER_OF_TITLE_BUTTONS; i += 2) { if ((contexts & (C_L1 << i))) { if (do_set || *nr_right_buttons <= i / 2) { *nr_right_buttons = i / 2 + 1; } } } if (*nr_left_buttons != l || *nr_right_buttons != r) { Scr.flags.do_need_window_update = 1; Scr.flags.has_nr_buttons_changed = 1; } return; } static int activate_binding(Binding *binding, binding_t type, Bool do_grab) { FvwmWindow *t; Bool rc = 0; if (binding == NULL) { return rc; } if (BIND_IS_PKEY_BINDING(type) || binding->Context == C_ALL) { /* necessary for key bindings that work over unfocused windows */ GrabWindowKeyOrButton( dpy, Scr.Root, binding, C_WINDOW | C_DECOR | C_ROOT | C_ICON | C_EWMH_DESKTOP, GetUnusedModifiers(), None, do_grab); if (do_grab == False) { rc = 1; } } if (do_grab == False && BIND_IS_KEY_BINDING(type) && (binding->Context & C_ROOT)) { rc = 1; } if (fFvwmInStartup == True) { return rc; } /* grab keys immediately */ for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) { if (!IS_EWMH_DESKTOP(FW_W(t)) && (binding->Context & (C_WINDOW | C_DECOR)) && BIND_IS_KEY_BINDING(type)) { GrabWindowKey( dpy, FW_W_FRAME(t), binding, C_WINDOW | C_DECOR, GetUnusedModifiers(), do_grab); } if (binding->Context & C_ICON) { if (FW_W_ICON_TITLE(t) != None) { GrabWindowKeyOrButton( dpy, FW_W_ICON_TITLE(t), binding, C_ICON, GetUnusedModifiers(), None, do_grab); } if (FW_W_ICON_PIXMAP(t) != None) { GrabWindowKeyOrButton( dpy, FW_W_ICON_PIXMAP(t), binding, C_ICON, GetUnusedModifiers(), None, do_grab); } } if (IS_EWMH_DESKTOP(FW_W(t)) && (binding->Context & C_EWMH_DESKTOP)) { GrabWindowKeyOrButton( dpy, FW_W_PARENT(t), binding, C_EWMH_DESKTOP, GetUnusedModifiers(), None, do_grab); } } return rc; } static int bind_get_bound_button_contexts( Binding **pblist, unsigned short *buttons_grabbed) { int bcontext = 0; Binding *b; if (buttons_grabbed) { *buttons_grabbed = 0; } for (b = *pblist; b != NULL; b = b->NextBinding) { if (!BIND_IS_MOUSE_BINDING(b->type) && !BIND_IS_STROKE_BINDING(b->type)) { continue; } if ((b->Context & (C_WINDOW | C_EWMH_DESKTOP)) && !(BIND_IS_STROKE_BINDING(b->type) && b->Button_Key == 0) && buttons_grabbed != NULL) { if (b->Button_Key == 0) { *buttons_grabbed |= ((1 << NUMBER_OF_EXTENDED_MOUSE_BUTTONS) - 1); } else { *buttons_grabbed |= (1 << (b->Button_Key - 1)); } } if (b->Context != C_ALL && (b->Context & (C_LALL | C_RALL))) { bcontext |= b->Context; } } return bcontext; } static void __rebind_global_key(Binding **pblist, int Button_Key) { Binding *b; for (b = *pblist; b != NULL; b = b->NextBinding) { if (b->Button_Key == Button_Key && (BIND_IS_PKEY_BINDING(b->type) || b->Context == C_ALL)) { activate_binding(b, b->type, True); return; } } return; } /* Parses a mouse or key binding */ static int ParseBinding( Display *dpy, Binding **pblist, char *tline, binding_t type, int *nr_left_buttons, int *nr_right_buttons, unsigned short *buttons_grabbed, Bool is_silent) { char *action; char context_string[20]; char modifier_string[20]; char *ptr; char *token; char key_string[201] = ""; char buffer[80]; char *window_name = NULL; char *p; int button = 0; int n1 = 0; int n2 = 0; int n3 = 0; int context; int modifier; int rc; KeySym keysym = NoSymbol; Bool is_unbind_request = False; Bool is_pass_through = False; Bool are_similar_bindings_left; Binding *b; Binding *rmlist = NULL; STROKE_CODE(char stroke[STROKE_MAX_SEQUENCE + 1] = ""); STROKE_CODE(int n4 = 0); STROKE_CODE(int i); /* tline points after the key word "Mouse" or "Key" */ token = p = PeekToken(tline, &ptr); /* check to see if a window name has been specified. */ if (p == NULL) { fvwm_msg( ERR, "ParseBinding", "empty %s binding, ignored\n", tline); return 0; } if (*p == '(') { /* A window name has been specified for the binding. */ sscanf(p + 1, "%79s", buffer); p = buffer; while (*p != ')') { if (*p == '\0') { if (!is_silent) { fvwm_msg( ERR, "ParseBinding", "Syntax error in line %s -" " missing ')'", tline); } return 0; } ++p; } *p++ = '\0'; window_name = buffer; if (*p != '\0') { if (!is_silent) { fvwm_msg( ERR, "ParseBinding", "Syntax error in line %s - trailing" " text after specified window", tline); } return 0; } token = PeekToken(ptr, &ptr); } if (token != NULL) { if (BIND_IS_KEY_BINDING(type)) { /* see len of key_string above */ n1 = sscanf(token,"%200s", key_string); } #ifdef HAVE_STROKE else if (BIND_IS_STROKE_BINDING(type)) { int num = 0; int j; n1 = 1; i = 0; if (token[0] == 'N' && token[1] != '\0') { num = 1; } j=i+num; while (n1 && token[j] != '\0' && i < STROKE_MAX_SEQUENCE) { if (!isdigit(token[j])) { n1 = 0; } if (num) { /* Numeric pad to Telephone */ if ('7' <= token[j] && token[j] <= '9') { token[j] -= 6; } else if ('1' <= token[j] && token[j] <= '3') { token[j] += 6; } } stroke[i] = token[j]; i++; j=i+num; } stroke[i] = '\0'; if (strlen(token) > STROKE_MAX_SEQUENCE + num) { if (!is_silent) { fvwm_msg( WARN, "ParseBinding", "Too long stroke sequence in" " line %s. Only %i elements" " will be taken into" " account.\n", tline, STROKE_MAX_SEQUENCE); } } } #endif /* HAVE_STROKE */ else { n1 = sscanf(token, "%d", &button); if (button < 0) { if (!is_silent) { fvwm_msg( ERR, "ParseBinding", "Illegal mouse button in line" " %s", tline); } return 0; } if (button > NUMBER_OF_MOUSE_BUTTONS) { if (!is_silent) { fvwm_msg( WARN, "ParseBinding", "Got mouse button %d when the" " maximum is %d.\n You can't" " bind complex functions to" " this button. To suppress" " this warning, use:\n" " Silent Mouse %s", button, NUMBER_OF_MOUSE_BUTTONS, tline); } } } } #ifdef HAVE_STROKE if (BIND_IS_STROKE_BINDING(type)) { token = PeekToken(ptr, &ptr); if (token != NULL) { n4 = sscanf(token,"%d", &button); } } #endif /* HAVE_STROKE */ token = PeekToken(ptr, &ptr); if (token != NULL) { n2 = sscanf(token, "%19s", context_string); } token = PeekToken(ptr, &action); if (token != NULL) { n3 = sscanf(token, "%19s", modifier_string); } if (n1 != 1 || n2 != 1 || n3 != 1 STROKE_CODE(|| (BIND_IS_STROKE_BINDING(type) && n4 != 1))) { if (!is_silent) { fvwm_msg( ERR, "ParseBinding", "Syntax error in line %s", tline); } return 0; } if (wcontext_string_to_wcontext( context_string, &context) && !is_silent) { fvwm_msg( WARN, "ParseBinding", "Illegal context in line %s", tline); } if (modifiers_string_to_modmask(modifier_string, &modifier) && !is_silent) { fvwm_msg( WARN, "ParseBinding", "Illegal modifier in line %s", tline); } if (BIND_IS_KEY_BINDING(type)) { keysym = FvwmStringToKeysym(dpy, key_string); /* Don't let a 0 keycode go through, since that means AnyKey * to the XGrabKey call. */ if (keysym == 0) { if (!is_silent) { fvwm_msg( ERR, "ParseBinding", "No such key: %s", key_string); } return 0; } } if (action != NULL) { action = SkipSpaces(action, NULL, 0); } if ( action == NULL || *action == 0 || (action[0] == '-' && !is_pass_through)) { is_unbind_request = True; } else { is_pass_through = is_pass_through_action(action); if (is_pass_through) { /* pass-through actions indicate that the event be * allowed to pass through to the underlying window. */ if (window_name == NULL) { /* It doesn't make sense to have a pass-through * action on global bindings. */ if (!is_silent) { fvwm_msg( ERR, "ParseBinding", "Invalid action for global " "binding: %s", tline); } return 0; } } } /* short circuit menu bindings for now. */ if ((context & C_MENU) == C_MENU) { menu_binding( dpy, type, button, keysym, context, modifier, action, window_name); /* ParseBinding returns the number of new bindings in pblist * menu bindings does not add to pblist, and should return 0 */ return 0; } /* short circuit placement bindings for now. */ if ((context & C_PLACEMENT) == C_PLACEMENT) { placement_binding(button,keysym,modifier,action); /* ParseBinding returns the number of new bindings in pblist * placement bindings does not add to pblist, and should * return 0 */ return 0; } /* ** Remove the "old" bindings if any */ /* BEGIN remove */ CollectBindingList( dpy, pblist, &rmlist, &are_similar_bindings_left, type, STROKE_ARG((void *)stroke) button, keysym, modifier, context, window_name); if (rmlist != NULL) { int bcontext; if (is_unbind_request && are_similar_bindings_left == False) { int rc = 0; for (b = rmlist; b != NULL; b = b->NextBinding) { /* release the grab */ rc |= activate_binding(b, type, False); } if (rc) { __rebind_global_key( pblist, rmlist->Button_Key); } } FreeBindingList(rmlist); bcontext = bind_get_bound_button_contexts( pblist, buttons_grabbed); update_nr_buttons( bcontext, nr_left_buttons, nr_right_buttons, True); } /* return if it is an unbind request */ if (is_unbind_request) { return 0; } /* END remove */ update_nr_buttons(context, nr_left_buttons, nr_right_buttons, False); if ((modifier & AnyModifier)&&(modifier&(~AnyModifier))) { fvwm_msg( WARN, "ParseBinding", "Binding specified AnyModifier" " and other modifiers too. Excess modifiers are" " ignored."); modifier = AnyModifier; } if ( (BIND_IS_MOUSE_BINDING(type) || (BIND_IS_STROKE_BINDING(type) && button != 0)) && (context & (C_WINDOW | C_EWMH_DESKTOP)) && buttons_grabbed != NULL) { if (button == 0) { *buttons_grabbed |= ((1 << NUMBER_OF_EXTENDED_MOUSE_BUTTONS) - 1); } else { *buttons_grabbed |= (1 << (button - 1)); } } rc = AddBinding( dpy, pblist, type, STROKE_ARG((void *)stroke) button, keysym, key_string, modifier, context, (void *)action, NULL, window_name); return rc; } static void binding_cmd(F_CMD_ARGS, binding_t type) { Binding *b; int count; unsigned short btg = Scr.buttons2grab; count = ParseBinding( dpy, &Scr.AllBindings, action, type, &Scr.nr_left_buttons, &Scr.nr_right_buttons, &btg, Scr.flags.are_functions_silent); if (btg != Scr.buttons2grab) { Scr.flags.do_need_window_update = 1; Scr.flags.has_mouse_binding_changed = 1; Scr.buttons2grab = btg; } for ( b = Scr.AllBindings; count > 0 && b != NULL; count--, b = b->NextBinding) { activate_binding(b, type, True); } return; } void print_bindings(void) { Binding *b; fprintf(stderr, "Current list of bindings:\n\n"); for (b = Scr.AllBindings; b != NULL; b = b->NextBinding) { switch (b->type) { case BIND_KEYPRESS: fprintf(stderr, "Key"); break; case BIND_PKEYPRESS: fprintf(stderr, "PointerKey"); break; case BIND_BUTTONPRESS: case BIND_BUTTONRELEASE: fprintf(stderr, "Mouse"); break; case BIND_STROKE: fprintf(stderr, "Stroke"); break; default: fvwm_msg( ERR, "print_bindings", "invalid binding type %d", b->type); continue; } if (b->windowName != NULL) { fprintf(stderr, " (%s)", b->windowName); } switch (b->type) { case BIND_KEYPRESS: case BIND_PKEYPRESS: fprintf(stderr, "\t%s", b->key_name); break; case BIND_BUTTONPRESS: case BIND_BUTTONRELEASE: fprintf(stderr, "\t%d", b->Button_Key); break; case BIND_STROKE: STROKE_CODE( fprintf( stderr, "\t%s\t%d", (char *)b->Stroke_Seq, b->Button_Key)); break; } { char *mod_string; char *context_string; mod_string = charmap_table_to_string( MaskUsedModifiers(b->Modifier),key_modifiers); context_string = charmap_table_to_string( b->Context, win_contexts); fprintf( stderr, "\t%s\t%s\t%s\n", context_string, mod_string, (char *)b->Action); free(mod_string); free(context_string); } } return; } /* ---------------------------- interface functions ------------------------ */ /* Removes all unused modifiers from in_modifiers */ unsigned int MaskUsedModifiers(unsigned int in_modifiers) { return in_modifiers & ~mods_unused; } unsigned int GetUnusedModifiers(void) { return mods_unused; } /* ---------------------------- builtin commands --------------------------- */ void CMD_Key(F_CMD_ARGS) { binding_cmd(F_PASS_ARGS, BIND_KEYPRESS); return; } void CMD_PointerKey(F_CMD_ARGS) { binding_cmd(F_PASS_ARGS, BIND_PKEYPRESS); return; } void CMD_Mouse(F_CMD_ARGS) { binding_cmd(F_PASS_ARGS, BIND_BUTTONPRESS); return; } #ifdef HAVE_STROKE void CMD_Stroke(F_CMD_ARGS) { binding_cmd(F_PASS_ARGS, BIND_STROKE); return; } #endif /* HAVE_STROKE */ /* Declares which X modifiers are actually locks and should be ignored when * testing mouse/key binding modifiers. */ void CMD_IgnoreModifiers(F_CMD_ARGS) { char *token; int mods_unused_old = mods_unused; token = PeekToken(action, &action); if (!token) { mods_unused = 0; } else if (StrEquals(token, "default")) { mods_unused = DEFAULT_MODS_UNUSED; } else if (modifiers_string_to_modmask(token, &mods_unused)) { fvwm_msg( ERR, "ignore_modifiers", "illegal modifier in line %s\n", action); } if (mods_unused != mods_unused_old) { /* broadcast config to modules */ broadcast_ignore_modifiers(); } return; } fvwm-2.7.0/fvwm/events.c0000644000175000017500000034611314147024700012056 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* This module is based on Twm, but has been siginificantly modified * by Rob Nation */ /* * Copyright 1988 by Evans & Sutherland Computer Corporation, * Salt Lake City, Utah * Portions Copyright 1989 by the Massachusetts Institute of Technology * Cambridge, Massachusetts * * All Rights Reserved * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice appear in all * copies and that both that copyright notice and this permis- * sion notice appear in supporting documentation, and that the * names of Evans & Sutherland and M.I.T. not be used in advertising * in publicity pertaining to distribution of the software without * specific, written prior permission. * * EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- * ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR * M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- * AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE * OR PERFORMANCE OF THIS SOFTWARE. */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #if HAVE_SYS_BSDTYPES_H #include #endif #include #include #include #include #include "libs/ftime.h" #include "libs/fvwmlib.h" #include "libs/System.h" #include "libs/Grab.h" #include "libs/Parse.h" #include "libs/ColorUtils.h" #include "libs/FShape.h" #include "libs/PictureBase.h" #include "libs/Colorset.h" #include "libs/charmap.h" #include "libs/wcontext.h" #include "fvwm.h" #include "externs.h" #include "cursor.h" #include "functions.h" #include "commands.h" #include "bindings.h" #include "misc.h" #include "screen.h" #include "events.h" #include "eventhandler.h" #include "eventmask.h" #include "libs/fvwmsignal.h" #include "module_list.h" #include "module_interface.h" #include "session.h" #include "borders.h" #include "frame.h" #include "add_window.h" #include "icccm2.h" #include "icons.h" #include "ewmh.h" #include "update.h" #include "style.h" #include "stack.h" #include "geometry.h" #include "focus.h" #include "virtual.h" #include "decorations.h" #include "schedule.h" #include "menus.h" #include "colormaps.h" #include "colorset.h" #ifdef HAVE_STROKE #include "stroke.h" #endif /* HAVE_STROKE */ /* ---------------------------- local definitions -------------------------- */ #ifndef XUrgencyHint #define XUrgencyHint (1L << 8) #endif #define CR_MOVERESIZE_MASK (CWX | CWY | CWWidth | CWHeight | CWBorderWidth) #define DEBUG_GLOBALLY_ACTIVE 1 #define MAX_NUM_WEED_EVENT_TYPES 40 /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ extern void StartupStuff(void); /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ typedef void (*PFEH)(const evh_args_t *ea); typedef struct { Window w; Bool do_return_true; Bool do_return_true_cr; unsigned long cr_value_mask; Bool ret_does_match; unsigned long ret_type; } check_if_event_args; typedef struct { unsigned do_forbid_function : 1; unsigned do_focus : 1; unsigned do_swallow_click : 1; unsigned do_raise : 1; } hfrc_ret_t; typedef struct event_group { int base; int count; PFEH *jump_table; struct event_group *next; } event_group_t; typedef struct { int num_event_types; int event_types[MAX_NUM_WEED_EVENT_TYPES]; } _weed_event_type_arg; typedef struct { long event_mask; } _weed_window_mask_events_arg; typedef struct { Window w; XEvent *last_cr_event; int count; } _merge_cr_args; /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ static int Button = 0; static const FvwmWindow *xcrossing_last_grab_window = NULL; STROKE_CODE(static int send_motion); STROKE_CODE(static char sequence[STROKE_MAX_SEQUENCE + 1]); static event_group_t *base_event_group = NULL; /* ---------------------------- exported variables (globals) --------------- */ int last_event_type = 0; Window PressedW = None; /* ---------------------------- local functions ---------------------------- */ static void fake_map_unmap_notify(const FvwmWindow *fw, int event_type) { XEvent client_event; XWindowAttributes winattrs = {0}; if (!XGetWindowAttributes(dpy, FW_W(fw), &winattrs)) { return; } XSelectInput( dpy, FW_W(fw), winattrs.your_event_mask & ~StructureNotifyMask); client_event.type = event_type; client_event.xmap.display = dpy; client_event.xmap.event = FW_W(fw); client_event.xmap.window = FW_W(fw); switch (event_type) { case MapNotify: client_event.xmap.override_redirect = False; break; case UnmapNotify: client_event.xunmap.from_configure = False; break; default: /* not possible if called correctly */ break; } FSendEvent( dpy, FW_W(fw), False, StructureNotifyMask, &client_event); XSelectInput(dpy, FW_W(fw), winattrs.your_event_mask); XFlush(dpy); return; } static int _pred_weed_accumulate_expose( Display *display, XEvent *ev, XPointer arg) { XEvent *em = (XEvent *)arg; if (ev->type != Expose) { return 0; } { int x0; int x1; x1 = max( ev->xexpose.x + ev->xexpose.width, em->xexpose.x + em->xexpose.width); x0 = min(em->xexpose.x, ev->xexpose.x); em->xexpose.x = x0; em->xexpose.width = x1 - x0; } { int y0; int y1; y1 = max( ev->xexpose.y + ev->xexpose.height, em->xexpose.y + em->xexpose.height); y0 = min(em->xexpose.y, ev->xexpose.y); em->xexpose.y = y0; em->xexpose.height = y1 - y0; } return 1; } static int _pred_weed_handle_expose( Display *display, XEvent *event, XPointer arg) { if (event->type == Expose) { dispatch_event(event); return 1; } else { return 0; } } static int _pred_weed_event_type( Display *display, XEvent *event, XPointer arg) { _weed_event_type_arg *args = (_weed_event_type_arg *)arg; int i; for (i = 0; i < args->num_event_types; i++) { if (event->type == args->event_types[i]) { /* invalidate event and continue weeding */ return 1; } } /* keep event and continue weeding */ return 0; } static int _pred_flush_property_notify_weed( Display *display, XEvent *event, XPointer arg) { flush_property_notify_args *args = (flush_property_notify_args *)arg; int does_match_window; does_match_window = ( FEV_HAS_EVENT_WINDOW(event->type) && event->xany.window == args->w) ? 1 : 0; if ( does_match_window && event->type == args->event_type && event->xproperty.atom == args->atom) { /* invalidate event and continue weeding */ return 1; } else if ( args->do_stop_at_event_type && event->type == args->stop_at_event_type && ( !FEV_HAS_EVENT_WINDOW(args->stop_at_event_type) || does_match_window)) { /* keep event and stop weeding */ return 2; } /* keep event and continue weeding */ return 0; } static Bool test_resizing_event( Display *display, XEvent *event, XPointer arg) { check_if_event_args *cie_args; Bool rc; cie_args = (check_if_event_args *)arg; cie_args->ret_does_match = False; if (event->xany.window != cie_args->w) { return False; } rc = False; switch (event->type) { case ConfigureRequest: if ((event->xconfigurerequest.value_mask & cie_args->cr_value_mask) != 0) { cie_args->ret_type = ConfigureRequest; cie_args->ret_does_match = True; rc = cie_args->do_return_true_cr; } break; case PropertyNotify: if (event->xproperty.atom == XA_WM_NORMAL_HINTS) { cie_args->ret_type = PropertyNotify; cie_args->ret_does_match = True; rc = cie_args->do_return_true; } default: break; } /* Yes, it is correct that this function may always returns False. */ return rc; } static inline void _handle_cr_on_unmanaged(XEvent *e) { XConfigureRequestEvent *cre = &e->xconfigurerequest; XWindowChanges xwc; unsigned long xwcm; xwcm = (cre->value_mask & CR_MOVERESIZE_MASK); xwc.x = cre->x; xwc.y = cre->y; xwc.width = cre->width; xwc.height = cre->height; xwc.border_width = cre->border_width; XConfigureWindow(dpy, cre->window, xwcm, &xwc); return; } static inline void _handle_cr_on_icon(XEvent *e, FvwmWindow *fw) { XConfigureRequestEvent *cre = &e->xconfigurerequest; XWindowChanges xwc; unsigned long xwcm; xwcm = (cre->value_mask & CR_MOVERESIZE_MASK); xwc.x = cre->x; xwc.y = cre->y; xwc.width = cre->width; xwc.height = cre->height; xwc.border_width = cre->border_width; if (FW_W_ICON_PIXMAP(fw) == cre->window) { int bw; if (cre->value_mask & CWBorderWidth) { fw->icon_border_width = cre->border_width; } bw = fw->icon_border_width; if ((cre->value_mask & (CWWidth | CWHeight)) == (CWWidth | CWHeight)) { set_icon_picture_size( fw, cre->width + 2 * bw, cre->height + 2 * bw); } } set_icon_position(fw, cre->x, cre->y); broadcast_icon_geometry(fw, False); XConfigureWindow(dpy, cre->window, xwcm, &xwc); if (cre->window != FW_W_ICON_PIXMAP(fw) && FW_W_ICON_PIXMAP(fw) != None) { rectangle g; get_icon_picture_geometry(fw, &g); xwc.x = g.x; xwc.y = g.y; xwcm = cre->value_mask & (CWX | CWY); XConfigureWindow( dpy, FW_W_ICON_PIXMAP(fw), xwcm, &xwc); } if (FW_W_ICON_TITLE(fw) != None) { rectangle g; get_icon_title_geometry(fw, &g); xwc.x = g.x; xwc.y = g.y; xwcm = cre->value_mask & (CWX | CWY); XConfigureWindow( dpy, FW_W_ICON_TITLE(fw), xwcm, &xwc); } return; } static inline void _handle_cr_on_shaped(FvwmWindow *fw) { /* suppress compiler warnings w/o shape extension */ int i; unsigned int u; Bool b; int boundingShaped; SUPPRESS_UNUSED_VAR_WARNING(i); SUPPRESS_UNUSED_VAR_WARNING(u); SUPPRESS_UNUSED_VAR_WARNING(b); if (FShapeQueryExtents( dpy, FW_W(fw), &boundingShaped, &i, &i, &u, &u, &b, &i, &i, &u, &u)) { fw->wShaped = boundingShaped; } else { fw->wShaped = 0; } return; } static inline void _handle_cr_restack( int *ret_do_send_event, XEvent *e, FvwmWindow *fw) { XConfigureRequestEvent *cre = &e->xconfigurerequest; XWindowChanges xwc; unsigned long xwcm; FvwmWindow *fw2 = NULL; if (cre->value_mask & CWSibling) { if (XFindContext( dpy, cre->above, FvwmContext, (caddr_t *)&fw2) == XCNOENT) { fw2 = NULL; } if (fw2 == fw) { fw2 = NULL; } } if (cre->detail != Above && cre->detail != Below) { HandleUnusualStackmodes( cre->detail, fw, cre->window, fw2, cre->above); } /* only allow clients to restack windows within their layer */ else if (fw2 == NULL || compare_window_layers(fw2, fw) != 0) { switch (cre->detail) { case Above: RaiseWindow(fw, True); break; case Below: LowerWindow(fw, True); break; } } else { xwc.sibling = FW_W_FRAME(fw2); xwc.stack_mode = cre->detail; xwcm = CWSibling | CWStackMode; XConfigureWindow(dpy, FW_W_FRAME(fw), xwcm, &xwc); /* Maintain the condition that icon windows are stacked * immediately below their frame * 1. for fw */ xwc.sibling = FW_W_FRAME(fw); xwc.stack_mode = Below; xwcm = CWSibling | CWStackMode; if (FW_W_ICON_TITLE(fw) != None) { XConfigureWindow( dpy, FW_W_ICON_TITLE(fw), xwcm, &xwc); } if (FW_W_ICON_PIXMAP(fw) != None) { XConfigureWindow( dpy, FW_W_ICON_PIXMAP(fw), xwcm, &xwc); } /* 2. for fw2 */ if (cre->detail == Below) { xwc.sibling = FW_W_FRAME(fw2); xwc.stack_mode = Below; xwcm = CWSibling | CWStackMode; if (FW_W_ICON_TITLE(fw2) != None) { XConfigureWindow( dpy, FW_W_ICON_TITLE(fw2), xwcm, &xwc); } if (FW_W_ICON_PIXMAP(fw2) != None) { XConfigureWindow( dpy, FW_W_ICON_PIXMAP(fw2), xwcm, &xwc); } } /* Maintain the stacking order ring */ if (cre->detail == Above) { remove_window_from_stack_ring(fw); add_window_to_stack_ring_after( fw, get_prev_window_in_stack_ring(fw2)); } else /* cre->detail == Below */ { remove_window_from_stack_ring(fw); add_window_to_stack_ring_after(fw, fw2); } BroadcastRestackThisWindow(fw); } /* srt (28-Apr-2001): Tk needs a ConfigureNotify event after a * raise, otherwise it would hang for two seconds */ *ret_do_send_event = 1; return; } static inline void _cr_get_static_position( rectangle *ret_g, FvwmWindow *fw, XEvent *e, size_borders *b) { XConfigureRequestEvent *cre = &e->xconfigurerequest; if (cre->value_mask & CWX) { ret_g->x = cre->x - b->top_left.width; } else { ret_g->x = fw->g.frame.x; } if (cre->value_mask & CWY) { ret_g->y = cre->y - b->top_left.height; } else { ret_g->y = fw->g.frame.y; } return; } static inline void _cr_get_grav_position( rectangle *ret_g, FvwmWindow *fw, XEvent *e, size_borders *b) { XConfigureRequestEvent *cre = &e->xconfigurerequest; int grav_x; int grav_y; gravity_get_offsets(fw->hints.win_gravity, &grav_x, &grav_y); if (cre->value_mask & CWX) { ret_g->x = cre->x - ((grav_x + 1) * b->total_size.width) / 2; } else { ret_g->x = fw->g.frame.x; } if (cre->value_mask & CWY) { ret_g->y = cre->y - ((grav_y + 1) * b->total_size.height) / 2; } else { ret_g->y = fw->g.frame.y; } return; } /* Try to detect whether the application uses the ICCCM way of moving its * window or the traditional way, always assuming StaticGravity. */ static inline void _cr_detect_icccm_move( FvwmWindow *fw, XEvent *e, size_borders *b) { XConfigureRequestEvent *cre = &e->xconfigurerequest; rectangle grav_g; rectangle static_g; rectangle dg_g; rectangle ds_g; int mx; int my; int m; int w; int h; int has_x; int has_y; if (CR_MOTION_METHOD(fw) != CR_MOTION_METHOD_AUTO) { if (Scr.bo.do_debug_cr_motion_method == 1) { fprintf( stderr, "_cdim: --- already detected (pid %d) %p" " '%s'\n", HAS_EWMH_WM_PID(fw), fw, fw->visible_name); } return; } if (HAS_EWMH_WM_PID(fw)) { if (Scr.bo.do_debug_cr_motion_method == 1) { fprintf( stderr,"_cdim: +++ has ewmh_wm_pid: icccm" " %p '%s'\n", fw, fw->visible_name); } SET_CR_MOTION_METHOD(fw, CR_MOTION_METHOD_USE_GRAV); SET_CR_MOTION_METHOD_DETECTED(fw, 1); return; } if (fw->ewmh_window_type != EWMH_WINDOW_TYPE_NONE_ID) { if (Scr.bo.do_debug_cr_motion_method == 1) { fprintf( stderr, "_cdim: +++ has ewmh_window_type:" " icccm %p '%s'\n", fw, fw->visible_name); } SET_CR_MOTION_METHOD(fw, CR_MOTION_METHOD_USE_GRAV); SET_CR_MOTION_METHOD_DETECTED(fw, 1); return; } if (FShapesSupported && fw->wShaped) { if (Scr.bo.do_debug_cr_motion_method == 1) { fprintf( stderr, "_cdim: --- shaped window %p " "'%s'\n", fw, fw->visible_name); } /* no detection for shaped windows */ return; } if (fw->hints.win_gravity == StaticGravity) { if (Scr.bo.do_debug_cr_motion_method == 1) { fprintf( stderr, "_cdim: --- using StaticGravity" " %p '%s'\n", fw, fw->visible_name); } return; } has_x = (cre->value_mask & CWX); has_y = (cre->value_mask & CWY); if (!has_x && !has_y) { if (Scr.bo.do_debug_cr_motion_method == 1) { fprintf( stderr, "_cdim: --- not moved %p '%s'\n", fw, fw->visible_name); } return; } _cr_get_grav_position(&grav_g, fw, e, b); _cr_get_static_position(&static_g, fw, e, b); if (static_g.x == grav_g.x) { /* both methods have the same result; ignore */ has_x = 0; } if (static_g.y == grav_g.y) { /* both methods have the same result; ignore */ has_y = 0; } if (!has_x && !has_y) { if (Scr.bo.do_debug_cr_motion_method == 1) { fprintf( stderr, "_cdim: --- not moved %p '%s'\n", fw, fw->visible_name); } return; } dg_g.x = grav_g.x - fw->g.frame.x; dg_g.y = grav_g.y - fw->g.frame.y; ds_g.x = static_g.x - fw->g.frame.x; ds_g.y = static_g.y - fw->g.frame.y; if (Scr.bo.do_debug_cr_motion_method == 1) { fprintf( stderr, "s %3d/%3d %2d/%2d, g %3d/%3d %2d/%2d: ", static_g.x, static_g.y, ds_g.x, ds_g.y, grav_g.x, grav_g.y, dg_g.x, dg_g.y); } /* check full screen */ if ((cre->value_mask & (CWX | CWY)) == (CWX | CWY) && (has_x || has_y) && cre->width == Scr.MyDisplayWidth && cre->height == Scr.MyDisplayHeight) { if (grav_g.x == -b->top_left.width && grav_g.y == -b->top_left.height) { /* Window is fullscreen using the ICCCM way. */ SET_CR_MOTION_METHOD(fw, CR_MOTION_METHOD_USE_GRAV); SET_CR_MOTION_METHOD_DETECTED(fw, 1); if (Scr.bo.do_debug_cr_motion_method == 1) { fprintf( stderr, "+++ fullscreen icccm %p" " '%s'\n", fw, fw->visible_name); } return; } else if (static_g.x == -b->top_left.width && static_g.y == -b->top_left.height) { /* Window is fullscreen using the traditional way. */ SET_CR_MOTION_METHOD(fw, CR_MOTION_METHOD_STATIC_GRAV); SET_CR_MOTION_METHOD_DETECTED(fw, 1); if (Scr.bo.do_debug_cr_motion_method == 1) { fprintf( stderr, "+++ fullscreen traditional" " %p '%s'\n", fw, fw->visible_name); } return; } } /* check travelling across the screen */ if (has_x && dg_g.x == 0 && ds_g.x != 0 && has_y && dg_g.y == 0 && ds_g.y != 0) { /* The traditional way causes a shift by the border width or * height. Use ICCCM way. */ SET_CR_MOTION_METHOD(fw, CR_MOTION_METHOD_USE_GRAV); SET_CR_MOTION_METHOD_DETECTED(fw, 1); if (Scr.bo.do_debug_cr_motion_method == 1) { fprintf( stderr, "+++ travelling icccm %p '%s'\n", fw, fw->visible_name); } return; } if (has_x && dg_g.x != 0 && ds_g.x == 0 && has_y && dg_g.y != 0 && ds_g.y == 0) { /* The ICCCM way causes a shift by the border width or height. * Use traditional way. */ SET_CR_MOTION_METHOD(fw, CR_MOTION_METHOD_STATIC_GRAV); SET_CR_MOTION_METHOD_DETECTED(fw, 1); if (Scr.bo.do_debug_cr_motion_method == 1) { fprintf( stderr, "+++ travelling traditional %p" " '%s'\n", fw, fw->visible_name); } return; } /* check placement near border */ w = (cre->value_mask & CWWidth) ? cre->width + b->total_size.width : fw->g.frame.width; h = (cre->value_mask & CWHeight) ? cre->height + b->total_size.height : fw->g.frame.height; if (!has_x) { mx = CR_MOTION_METHOD_AUTO; } else if (static_g.x == 0 || static_g.x + w == Scr.MyDisplayWidth) { mx = CR_MOTION_METHOD_STATIC_GRAV; } else if (grav_g.x == 0 || grav_g.x + w == Scr.MyDisplayWidth) { mx = CR_MOTION_METHOD_USE_GRAV; } else { mx = CR_MOTION_METHOD_AUTO; } if (!has_y) { my = CR_MOTION_METHOD_AUTO; } else if (static_g.y == 0 || static_g.y + h == Scr.MyDisplayHeight) { my = CR_MOTION_METHOD_STATIC_GRAV; } else if (grav_g.y == 0 || grav_g.y + h == Scr.MyDisplayHeight) { my = CR_MOTION_METHOD_USE_GRAV; } else { my = CR_MOTION_METHOD_AUTO; } m = (mx != CR_MOTION_METHOD_AUTO) ? mx : my; if (m != CR_MOTION_METHOD_AUTO) { /* Window was placed next to the display border. */ if (m == my || my == CR_MOTION_METHOD_AUTO) { SET_CR_MOTION_METHOD(fw, m); SET_CR_MOTION_METHOD_DETECTED(fw, 1); if (Scr.bo.do_debug_cr_motion_method == 1) { fprintf( stderr, "+++ near border %s %p " "'%s'\n", (m == CR_MOTION_METHOD_USE_GRAV) ? "icccm" : "traditional", fw, fw->visible_name); } return; } } if (Scr.bo.do_debug_cr_motion_method == 1) { fprintf( stderr, "--- not detected %p '%s'\n", fw, fw->visible_name); } return; } /* This is not a good idea because this interferes with changes in the size * hints of the window. However, it is impossible to be completely safe here. * For example, if the client changes the size inc, then resizes the size of * its window and then changes the size inc again - all in one batch - then * the WM will read the *second* size inc upon the *first* event and use the * wrong one in the ConfigureRequest calculations. */ /* dv (31 Mar 2002): The code now handles these situations, so enable it * again. */ static int _pred_merge_cr(Display *display, XEvent *event, XPointer arg) { _merge_cr_args *args = (_merge_cr_args *)arg; switch (event->type) { case ConfigureRequest: { XConfigureRequestEvent *ecr = &event->xconfigurerequest; XConfigureRequestEvent *lcr = &args->last_cr_event->xconfigurerequest; if (event->xconfigurerequest.window != args->w) { /* no match, keep looking */ return 0; } /* collect the size/position changes */ if (lcr->value_mask & CWX) { ecr->x = lcr->x; } if (lcr->value_mask & CWY) { ecr->y = lcr->y; } if (lcr->value_mask & CWWidth) { ecr->width = lcr->width; } if (lcr->value_mask & CWHeight) { ecr->height = lcr->height; } if (lcr->value_mask & CWBorderWidth) { ecr->border_width = lcr->border_width; } /* add to new event and remove from old event */ ecr->value_mask |= (lcr->value_mask & CR_MOVERESIZE_MASK); lcr->value_mask &= ~CR_MOVERESIZE_MASK; if (lcr->value_mask == 0) { /* The event has no useful contents anymore. */ FEV_INVALIDATE_EVENT(args->last_cr_event); } args->last_cr_event = event; args->count++; /* don't drop the current event and continue weeding */ return 0; } case PropertyNotify: if ( event->xproperty.window == args->w && event->xproperty.atom != XA_WM_NORMAL_HINTS) { /* ConfigureRequest events cannot be merged past * changes of the size hints. */ /* don't merge and stop weeding */ return 2; } else { /* PropertyNotify for another window, or the changed * property does not interfere with merging. */ /* keep looking */ return 0; } default: /* Other events do not interfer with merging. */ /* keep looking */ return 0; } } static inline int _merge_cr_moveresize( const evh_args_t *ea, XEvent *ev, FvwmWindow *fw, size_borders *b) { _merge_cr_args args; memset(&args, 0, sizeof(args)); args.w = ev->xconfigurerequest.window; args.last_cr_event = ev; FWeedIfEvents(dpy, _pred_merge_cr, (XPointer)&args); #if 1 /*!!!*/ if (args.count > 0) { fprintf(stderr, "%s: merged %d cr events\n", __func__, args.count); } #endif /* use the count from the structure, not the return value of * FWeedIfEvents() because the predicate has a different way of weeding * and the return value is always zero. */ return args.count; } static inline int _handle_cr_on_client( int *ret_do_send_event, XEvent *e, const evh_args_t *ea, FvwmWindow *fw, Bool force, int force_gravity) { XConfigureRequestEvent *cre = &e->xconfigurerequest; rectangle current_g; rectangle new_g; rectangle d_g; size_rect constr_dim; size_rect oldnew_dim; size_borders b; int gravity; if (ea) { cre = &ea->exc->x.etrigger->xconfigurerequest; } if (cre->value_mask & CWBorderWidth) { /* for restoring */ fw->attr_backup.border_width = cre->border_width; } if ((cre->value_mask & (CWWidth | CWHeight | CWX | CWY)) == 0) { return 0; } get_window_borders(fw, &b); /* Merge all pending ConfigureRequests for the window into a single * event. However, we can not do this if the window uses the motion * method autodetection because the merged event might confuse the * detection code. */ if (ea && CR_MOTION_METHOD(fw) != CR_MOTION_METHOD_AUTO) { int count; count = _merge_cr_moveresize(ea, e, fw, &b); if (count > 0) { /* the event has been merged into a later one, do * nothing */ return 0; } } #if 0 fprintf(stderr, "cre: %d(%d) %d(%d) %d(%d)x%d(%d) fw 0x%08x w 0x%08x " "ew 0x%08x '%s'\n", cre->x, (int)(cre->value_mask & CWX), cre->y, (int)(cre->value_mask & CWY), cre->width, (int)(cre->value_mask & CWWidth), cre->height, (int)(cre->value_mask & CWHeight), (int)FW_W_FRAME(fw), (int)FW_W(fw), (int)cre->window, (fw->name.name) ? fw->name.name : ""); #endif /* Don't modify frame_g fields before calling SetupWindow! */ memset(&d_g, 0, sizeof(d_g)); if (HAS_NEW_WM_NORMAL_HINTS(fw)) { /* get the latest size hints */ XSync(dpy, 0); GetWindowSizeHints(fw); SET_HAS_NEW_WM_NORMAL_HINTS(fw, 0); } if (!HAS_OVERRIDE_SIZE_HINTS(fw) && (fw->hints.flags & PMaxSize)) { /* Java workaround */ if (cre->height > fw->hints.max_height && fw->hints.max_height <= BROKEN_MAXSIZE_LIMIT) { fw->hints.max_height = DEFAULT_MAX_MAX_WINDOW_HEIGHT; cre->value_mask |= CWHeight; } if (cre->width > fw->hints.max_width && fw->hints.max_width <= BROKEN_MAXSIZE_LIMIT) { fw->hints.max_width = DEFAULT_MAX_MAX_WINDOW_WIDTH; cre->value_mask |= CWWidth; } } if (!HAS_OVERRIDE_SIZE_HINTS(fw) && (fw->hints.flags & PMinSize)) { if (cre->width < fw->hints.min_width && fw->hints.min_width >= BROKEN_MINSIZE_LIMIT) { fw->hints.min_width = 1; cre->value_mask |= CWWidth; } if (cre->height < fw->hints.min_height && fw->hints.min_height >= BROKEN_MINSIZE_LIMIT) { fw->hints.min_height = 1; cre->value_mask |= CWHeight; } } if (IS_SHADED(fw) || !is_function_allowed(F_MOVE, NULL, fw, RQORIG_PROGRAM, False)) { /* forbid shaded applications to move their windows */ cre->value_mask &= ~(CWX | CWY); /* resend the old geometry */ *ret_do_send_event = 1; } if (IS_MAXIMIZED(fw)) { /* dont allow clients to resize maximized windows */ cre->value_mask &= ~(CWWidth | CWHeight); /* resend the old geometry */ *ret_do_send_event = 1; d_g.width = 0; d_g.height = 0; } else if ( !is_function_allowed( F_RESIZE, NULL, fw, RQORIG_PROGRAM, False)) { cre->value_mask &= ~(CWWidth | CWHeight); *ret_do_send_event = 1; } if (!force && CR_MOTION_METHOD(fw) == CR_MOTION_METHOD_AUTO) { _cr_detect_icccm_move(fw, e, &b); } if (force_gravity > ForgetGravity && force_gravity <= StaticGravity) { gravity = force_gravity; } else { gravity = fw->hints.win_gravity; } if (IS_SHADED(fw)) { direction_t gravity_dir; get_unshaded_geometry(fw, ¤t_g); /* the shade direction overrides the window's gravity */ gravity_dir = gravity_grav_to_dir(gravity); gravity_dir = gravity_override_dir( gravity_dir, SHADED_DIR(fw)); gravity = gravity_dir_to_grav(gravity_dir); } else { current_g = fw->g.frame; } if (!(cre->value_mask & (CWX | CWY))) { /* nothing */ } else if ((force || CR_MOTION_METHOD(fw) == CR_MOTION_METHOD_USE_GRAV) && gravity != StaticGravity) { int ref_x; int ref_y; int grav_x; int grav_y; gravity_get_offsets(gravity, &grav_x, &grav_y); if (cre->value_mask & CWX) { ref_x = cre->x - ((grav_x + 1) * b.total_size.width) / 2; d_g.x = ref_x - current_g.x; } if (cre->value_mask & CWY) { ref_y = cre->y - ((grav_y + 1) * b.total_size.height) / 2; d_g.y = ref_y - current_g.y; } } else /* ..._USE_GRAV or ..._AUTO */ { /* default: traditional cr handling */ if (cre->value_mask & CWX) { d_g.x = cre->x - current_g.x - b.top_left.width; } if (cre->value_mask & CWY) { d_g.y = cre->y - current_g.y - b.top_left.height; } } if (cre->value_mask & CWHeight) { if (cre->height < (WINDOW_FREAKED_OUT_SIZE - b.total_size.height)) { d_g.height = cre->height - (current_g.height - b.total_size.height); } else { /* Ignore height changes to astronomically large * windows (needed for XEmacs 20.4); don't care if the * window is shaded here - we won't use 'height' in * this case anyway. * Inform the buggy app about the size that *we* want */ d_g.height = 0; *ret_do_send_event = 1; } } if (cre->value_mask & CWWidth) { if (cre->width < (WINDOW_FREAKED_OUT_SIZE - b.total_size.width)) { d_g.width = cre->width - (current_g.width - b.total_size.width); } else { d_g.width = 0; *ret_do_send_event = 1; } } /* SetupWindow (x,y) are the location of the upper-left outer corner * and are passed directly to XMoveResizeWindow (frame). The * (width,height) are the inner size of the frame. The inner width is * the same as the requested client window width; the inner height is * the same as the requested client window height plus any title bar * slop. */ new_g = current_g; oldnew_dim.width = new_g.width + d_g.width; oldnew_dim.height = new_g.height + d_g.height; constr_dim.width = oldnew_dim.width; constr_dim.height = oldnew_dim.height; constrain_size( fw, NULL, &constr_dim.width, &constr_dim.height, 0, 0, CS_UPDATE_MAX_DEFECT); d_g.width += (constr_dim.width - oldnew_dim.width); d_g.height += (constr_dim.height - oldnew_dim.height); if ((cre->value_mask & CWX) && d_g.width) { new_g.x = current_g.x + d_g.x; new_g.width = current_g.width + d_g.width; } else if ((cre->value_mask & CWX) && !d_g.width) { new_g.x = current_g.x + d_g.x; } else if (!(cre->value_mask & CWX) && d_g.width) { gravity_resize(gravity, &new_g, d_g.width, 0); } if ((cre->value_mask & CWY) && d_g.height) { new_g.y = current_g.y + d_g.y; new_g.height = current_g.height + d_g.height; } else if ((cre->value_mask & CWY) && !d_g.height) { new_g.y = current_g.y + d_g.y; } else if (!(cre->value_mask & CWY) && d_g.height) { gravity_resize(gravity, &new_g, 0, d_g.height); } if (new_g.x == current_g.x && new_g.y == current_g.y && new_g.width == current_g.width && new_g.height == current_g.height) { /* Window will not be moved or resized; send a synthetic * ConfigureNotify. */ *ret_do_send_event = 1; } else if ((cre->value_mask & CWX) || (cre->value_mask & CWY) || d_g.width || d_g.height) { if (IS_SHADED(fw)) { fw->g.normal = new_g; get_shaded_geometry(fw, &new_g, &new_g); } frame_setup_window_app_request( fw, new_g.x, new_g.y, new_g.width, new_g.height, False); /* make sure the window structure has the new position */ update_absolute_geometry(fw); maximize_adjust_offset(fw); } else if (DO_FORCE_NEXT_CR(fw)) { *ret_do_send_event = 1; } SET_FORCE_NEXT_CR(fw, 0); SET_FORCE_NEXT_PN(fw, 0); return 1; } void _handle_configure_request( XEvent *e, const evh_args_t *ea, FvwmWindow *fw, Bool force, int force_gravity) { XConfigureRequestEvent *cre = &e->xconfigurerequest; int do_send_event = 0; int cn_count = 0; fev_sanitise_configure_request(cre); /* According to the July 27, 1988 ICCCM draft, we should ignore size * and position fields in the WM_NORMAL_HINTS property when we map a * window. Instead, we'll read the current geometry. Therefore, we * should respond to configuration requests for windows which have * never been mapped. */ if (fw == NULL) { _handle_cr_on_unmanaged(e); return; } if (cre->window == FW_W_ICON_TITLE(fw) || cre->window == FW_W_ICON_PIXMAP(fw)) { _handle_cr_on_icon(e, fw); } if (FShapesSupported) { _handle_cr_on_shaped(fw); } if (fw != NULL && cre->window == FW_W(fw)) { cn_count = _handle_cr_on_client( &do_send_event, e, ea, fw, force, force_gravity); } /* Stacking order change requested. Handle this *after* geometry * changes, since we need the new geometry in occlusion calculations */ if ((cre->value_mask & CWStackMode) && (!DO_IGNORE_RESTACK(fw) || force)) { _handle_cr_restack(&do_send_event, e, fw); } #if 1 /* This causes some ddd windows not to be drawn properly. Reverted back * to the old method in frame_setup_window. */ /* domivogt (15-Oct-1999): enabled this to work around buggy apps that * ask for a nonsense height and expect that they really get it. */ if (cn_count == 0 && do_send_event) { cn_count = 1; } else if (cn_count > 0) { do_send_event = 1; } for ( ; cn_count > 0; cn_count--) { SendConfigureNotify( fw, fw->g.frame.x, fw->g.frame.y, fw->g.frame.width, fw->g.frame.height, 0, True); } if (do_send_event) { XFlush(dpy); } #endif return; } static Bool _pred_button_click( Display *display, XEvent *event, XPointer arg) { if (event->type == ButtonPress || event->type == ButtonRelease) { return True; } return False; } /* Helper function for __handle_focus_raise_click(). */ static Bool __test_for_motion(int x0, int y0) { int x; int y; unsigned int mask; XEvent e; /* Query the pointer to do this. We can't check for events here since * the events are still needed if the pointer moves. */ /* However, some special mouse (e.g., a touchpad with the * synaptic driver) may handle a double click in a special way * (for dragging through short touching and holding down the * finger on the touchpad). Bascially, when you execute a * double click the first button release is queued after the * second _physical_ mouse release happen. It seems that * FQueryPointer may not work as expected: it does not see * that the button is released on a double click. So, we need * to check for a button press in the future to avoid a fvwm * lockup! (olicha 2004-01-31) */ for (x = x0, y = y0; FQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, &JunkX, &JunkY, &x, &y, &mask) == True; usleep(20000)) { if ((mask & DEFAULT_ALL_BUTTONS_MASK) == 0) { /* all buttons are released */ return False; } else if (abs(x - x0) >= Scr.MoveThreshold || abs(y - y0) >= Scr.MoveThreshold) { /* the pointer has moved */ return True; } if (FCheckPeekIfEvent(dpy, &e, _pred_button_click, NULL)) { /* click in the future */ return False; } else { /* The predicate procedure finds no match, no event * has been removed from the queue and XFlush was * called. Nothing to do */ } } /* pointer has moved off screen */ return True; } /* Helper function for __handle_focus_raise_click(). */ static void __check_click_to_focus_or_raise( hfrc_ret_t *ret_args, const exec_context_t *exc) { FvwmWindow * const fw = exc->w.fw; const XEvent *te = exc->x.etrigger; struct { unsigned is_client_click : 1; unsigned is_focused : 1; } f; f.is_focused = !!focus_is_focused(fw); f.is_client_click = (exc->w.wcontext == C_WINDOW || exc->w.wcontext == C_EWMH_DESKTOP); /* check if we need to raise and/or focus the window */ ret_args->do_focus = focus_query_click_to_focus(fw, exc->w.wcontext); if (f.is_client_click && !ret_args->do_focus && !f.is_focused && FP_DO_FOCUS_BY_PROGRAM(FW_FOCUS_POLICY(fw)) && !fpol_query_allow_user_focus(&FW_FOCUS_POLICY(fw))) { /* Give the window a chance to to take focus itself */ ret_args->do_focus = 1; } if (ret_args->do_focus && focus_is_focused(fw)) { ret_args->do_focus = 0; } ret_args->do_raise = focus_query_click_to_raise(fw, f.is_focused, exc->w.wcontext); #define EXPERIMENTAL_ROU_HANDLING_V2 #ifdef EXPERIMENTAL_ROU_HANDLING_V2 /* RBW -- Dang! This works without the one in HandleEnterNotify! */ if (ret_args->do_raise && is_on_top_of_layer_and_above_unmanaged(fw)) #else if (ret_args->do_raise && is_on_top_of_layer(fw)) #endif { ret_args->do_raise = 0; } if ((ret_args->do_focus && FP_DO_IGNORE_FOCUS_CLICK_MOTION(FW_FOCUS_POLICY(fw))) || (ret_args->do_raise && FP_DO_IGNORE_RAISE_CLICK_MOTION(FW_FOCUS_POLICY(fw)))) { /* Pass further events to the application and check if a button * release or motion event occurs next. If we don't do this * here, the pointer will seem to be frozen in * __test_for_motion(). */ XAllowEvents(dpy, ReplayPointer, CurrentTime); if (__test_for_motion(te->xbutton.x_root, te->xbutton.y_root)) { /* the pointer was moved, process event normally */ ret_args->do_focus = 0; ret_args->do_raise = 0; } } if (ret_args->do_focus || ret_args->do_raise) { if (!((ret_args->do_focus && FP_DO_ALLOW_FUNC_FOCUS_CLICK(FW_FOCUS_POLICY(fw))) || (ret_args->do_raise && FP_DO_ALLOW_FUNC_RAISE_CLICK(FW_FOCUS_POLICY(fw))))) { ret_args->do_forbid_function = 1; } if (!((ret_args->do_focus && FP_DO_PASS_FOCUS_CLICK(FW_FOCUS_POLICY(fw))) || (ret_args->do_raise && FP_DO_PASS_RAISE_CLICK(FW_FOCUS_POLICY(fw))))) { ret_args->do_swallow_click = 1; } } return; } /* Finds out if the click on a window must be used to focus or raise it. */ static void __handle_focus_raise_click( hfrc_ret_t *ret_args, const exec_context_t *exc) { memset(ret_args, 0, sizeof(*ret_args)); if (exc->w.fw == NULL) { return; } /* check for proper click button and modifiers*/ if (FP_USE_MOUSE_BUTTONS(FW_FOCUS_POLICY(exc->w.fw)) != 0 && !(FP_USE_MOUSE_BUTTONS(FW_FOCUS_POLICY(exc->w.fw)) & (1 << (exc->x.etrigger->xbutton.button - 1)))) { /* wrong button, handle click normally */ return; } else if (FP_USE_MODIFIERS(FW_FOCUS_POLICY(exc->w.fw)) != FPOL_ANY_MODIFIER && MaskUsedModifiers( FP_USE_MODIFIERS(FW_FOCUS_POLICY(exc->w.fw))) != MaskUsedModifiers(exc->x.etrigger->xbutton.state)) { /* right button but wrong modifiers, handle click normally */ return; } else { __check_click_to_focus_or_raise(ret_args, exc); } return; } /* Helper function for HandleButtonPress */ static Bool __is_bpress_window_handled(const exec_context_t *exc) { Window eventw; const XEvent *te = exc->x.etrigger; if (exc->w.fw == NULL) { if ((te->xbutton.window != Scr.Root || te->xbutton.subwindow != None) && !is_pan_frame(te->xbutton.window)) { /* Ignore events in unmanaged windows or subwindows of * a client */ return False; } else { return True; } } eventw = (te->xbutton.subwindow != None && te->xany.window != FW_W(exc->w.fw)) ? te->xbutton.subwindow : te->xany.window; if (is_frame_hide_window(eventw) || eventw == FW_W_FRAME(exc->w.fw)) { return False; } if (!XGetGeometry( dpy, eventw, &JunkRoot, &JunkX, &JunkY, (unsigned int*)&JunkWidth, (unsigned int*)&JunkHeight, (unsigned int*)&JunkBW, (unsigned int*)&JunkDepth)) { /* The window has already died. */ return False; } return True; } /* Helper function for __handle_bpress_on_managed */ static Bool __handle_click_to_focus(const exec_context_t *exc) { fpol_set_focus_by_t set_by; switch (exc->w.wcontext) { case C_WINDOW: case C_EWMH_DESKTOP: set_by = FOCUS_SET_BY_CLICK_CLIENT; break; case C_ICON: set_by = FOCUS_SET_BY_CLICK_ICON; break; default: set_by = FOCUS_SET_BY_CLICK_DECOR; break; } SetFocusWindow(exc->w.fw, True, set_by); focus_grab_buttons(exc->w.fw); if (focus_is_focused(exc->w.fw) && !IS_ICONIFIED(exc->w.fw)) { border_draw_decorations( exc->w.fw, PART_ALL, True, True, CLEAR_ALL, NULL, NULL); } return focus_is_focused(exc->w.fw); } /* Helper function for __handle_bpress_on_managed */ static Bool __handle_click_to_raise(const exec_context_t *exc) { Bool rc = False; int is_focused; is_focused = focus_is_focused(exc->w.fw); if (focus_query_click_to_raise(exc->w.fw, is_focused, True)) { rc = True; } return rc; } /* Helper function for HandleButtonPress */ static void __handle_bpress_stroke(void) { STROKE_CODE(stroke_init()); STROKE_CODE(send_motion = True); return; } /* Helper function for __handle_bpress_on_managed */ static Bool __handle_bpress_action( const exec_context_t *exc, char *action) { window_parts part; Bool do_force; Bool rc = False; if (!action || *action == 0) { PressedW = None; return False; } /* draw pressed in decorations */ part = border_context_to_parts(exc->w.wcontext); do_force = (part & PART_TITLEBAR) ? True : False; border_draw_decorations( exc->w.fw, part, (Scr.Hilite == exc->w.fw), do_force, CLEAR_ALL, NULL, NULL); /* execute the action */ if (IS_ICONIFIED(exc->w.fw)) { /* release the pointer since it can't do harm over an icon */ XAllowEvents(dpy, AsyncPointer, CurrentTime); } execute_function(NULL, exc, action, 0); if (exc->w.wcontext != C_WINDOW && exc->w.wcontext != C_NO_CONTEXT) { WaitForButtonsUp(True); rc = True; } /* redraw decorations */ PressedW = None; if (check_if_fvwm_window_exists(exc->w.fw)) { part = border_context_to_parts(exc->w.wcontext); do_force = (part & PART_TITLEBAR) ? True : False; border_draw_decorations( exc->w.fw, part, (Scr.Hilite == exc->w.fw), do_force, CLEAR_ALL, NULL, NULL); } return rc; } /* Handles button presses on the root window. */ static void __handle_bpress_on_root(const exec_context_t *exc) { char *action; PressedW = None; __handle_bpress_stroke(); /* search for an appropriate mouse binding */ action = CheckBinding( Scr.AllBindings, STROKE_ARG(0) exc->x.etrigger->xbutton.button, exc->x.etrigger->xbutton.state, GetUnusedModifiers(), C_ROOT, BIND_BUTTONPRESS, NULL, NULL); if (action && *action) { const exec_context_t *exc2; exec_context_changes_t ecc; ecc.w.wcontext = C_ROOT; exc2 = exc_clone_context(exc, &ecc, ECC_WCONTEXT); execute_function(NULL, exc2, action, 0); exc_destroy_context(exc2); WaitForButtonsUp(True); } return; } /* Handles button presses on unmanaged windows */ static void __handle_bpress_on_unmanaged(const exec_context_t *exc) { /* Pass the event to the application. */ XAllowEvents(dpy, ReplayPointer, CurrentTime); XFlush(dpy); return; } /* Handles button presses on managed windows */ static void __handle_bpress_on_managed(const exec_context_t *exc) { char *action; hfrc_ret_t f; FvwmWindow * const fw = exc->w.fw; XEvent *e; e = exc->x.etrigger; /* Now handle click to focus and click to raise. */ __handle_focus_raise_click(&f, exc); PressedW = (f.do_forbid_function) ? None : exc->w.w; if (f.do_focus) { if (!__handle_click_to_focus(exc)) { /* Window didn't accept the focus; pass the click to * the application. */ f.do_swallow_click = 0; } } if (f.do_raise) { if (__handle_click_to_raise(exc) == True) { /* We can't raise the window immediately because the * action bound to the click might be "Lower" or * "RaiseLower". So mark the window as scheduled to be * raised after the binding is executed. Functions that * modify the stacking order will reset this flag. */ SET_SCHEDULED_FOR_RAISE(fw, 1); } } /* handle bindings */ if (!f.do_forbid_function) { /* stroke bindings */ __handle_bpress_stroke(); /* mouse bindings */ action = CheckBinding( Scr.AllBindings, STROKE_ARG(0) e->xbutton.button, e->xbutton.state, GetUnusedModifiers(), exc->w.wcontext, BIND_BUTTONPRESS, &fw->class, fw->name.name); if (__handle_bpress_action(exc, action)) { f.do_swallow_click = 1; } } /* raise the window */ if (IS_SCHEDULED_FOR_RAISE(fw)) { /* Now that we know the action did not restack the window we * can raise it. * dv (10-Aug-2002): We can safely raise the window after * redrawing it since all the decorations are drawn in the * window background and no Expose event is generated. */ RaiseWindow(fw, False); SET_SCHEDULED_FOR_RAISE(fw, 0); } /* clean up */ if (!f.do_swallow_click) { /* pass the click to the application */ XAllowEvents(dpy, ReplayPointer, CurrentTime); XFlush(dpy); } else if (f.do_focus || f.do_raise) { WaitForButtonsUp(True); } return; } /* restore focus stolen by unmanaged */ static void __refocus_stolen_focus_win(const evh_args_t *ea) { FOCUS_SET(Scr.StolenFocusWin, Scr.StolenFocusFvwmWin); ea->exc->x.etrigger->xfocus.window = Scr.StolenFocusWin; ea->exc->x.etrigger->type = FocusIn; Scr.UnknownWinFocused = None; Scr.StolenFocusWin = None; Scr.StolenFocusFvwmWin = NULL; dispatch_event(ea->exc->x.etrigger); return; } /* ---------------------------- event handlers ----------------------------- */ void HandleButtonPress(const evh_args_t *ea) { DBUG("HandleButtonPress", "Routine Entered"); GrabEm(CRS_NONE, GRAB_PASSIVE); if (__is_bpress_window_handled(ea->exc) == False) { __handle_bpress_on_unmanaged(ea->exc); } else if (ea->exc->w.fw != NULL) { __handle_bpress_on_managed(ea->exc); } else { __handle_bpress_on_root(ea->exc); } UngrabEm(GRAB_PASSIVE); return; } #ifdef HAVE_STROKE void HandleButtonRelease(const evh_args_t *ea) { char *action; char *name; int real_modifier; const XEvent *te = ea->exc->x.etrigger; XClassHint *class; DBUG("HandleButtonRelease", "Routine Entered"); send_motion = False; stroke_trans (sequence); DBUG("HandleButtonRelease",sequence); /* Allows modifier to work (Only R context works here). */ real_modifier = te->xbutton.state - (1 << (7 + te->xbutton.button)); if (ea->exc->w.fw == NULL) { class = NULL; name = NULL; } else { class = &ea->exc->w.fw->class; name = ea->exc->w.fw->name.name; } /* need to search for an appropriate stroke binding */ action = CheckBinding( Scr.AllBindings, sequence, te->xbutton.button, real_modifier, GetUnusedModifiers(), ea->exc->w.wcontext, BIND_STROKE, class, name); /* got a match, now process it */ if (action != NULL && (action[0] != 0)) { execute_function(NULL, ea->exc, action, 0); WaitForButtonsUp(True); } return; } #endif /* HAVE_STROKE */ void HandleClientMessage(const evh_args_t *ea) { const XEvent *te = ea->exc->x.etrigger; FvwmWindow * const fw = ea->exc->w.fw; DBUG("HandleClientMessage", "Routine Entered"); if (EWMH_ProcessClientMessage(ea->exc)) { return; } /* handle deletion of tear out menus */ if (fw && IS_TEAR_OFF_MENU(fw) && te->xclient.format == 32 && te->xclient.data.l[0] == _XA_WM_DELETE_WINDOW) { menu_close_tear_off_menu(fw); return; } if (te->xclient.message_type == _XA_WM_CHANGE_STATE && fw && te->xclient.data.l[0] == IconicState && !IS_ICONIFIED(fw)) { const exec_context_t *exc; exec_context_changes_t ecc; ecc.w.wcontext = C_WINDOW; exc = exc_clone_context(ea->exc, &ecc, ECC_WCONTEXT); execute_function(NULL, exc, "Iconify", 0); exc_destroy_context(exc); return; } /* FIXME: Is this safe enough ? I guess if clients behave * according to ICCCM and send these messages only if they * grabbed the pointer, it is OK */ { extern Atom _XA_WM_COLORMAP_NOTIFY; if (te->xclient.message_type == _XA_WM_COLORMAP_NOTIFY) { set_client_controls_colormaps(te->xclient.data.l[1]); return; } } /* CKH - if we get here, it was an unknown client message, so send * it to the client if it was in a window we know about. I'm not so * sure this should be done or not, since every other window manager * I've looked at doesn't. But it might be handy for a free drag and * drop setup being developed for Linux. */ /* TA: 20091231 - But this confuses QT Drag and Drop since it handles * processing XSendEvents in an odd order. For now, workaround this * by using a BugOpts option. */ if (fw) { if ((!Scr.bo.do_enable_qt_drag_n_drop_workaround) && (te->xclient.window != FW_W(fw))) { XEvent e; e = *te; e.xclient.window = FW_W(fw); FSendEvent(dpy, FW_W(fw), False, NoEventMask, &e); } } } void HandleColormapNotify(const evh_args_t *ea) { colormap_handle_colormap_notify(ea); return; } void HandleConfigureRequest(const evh_args_t *ea) { XEvent *te = ea->exc->x.etrigger; XConfigureRequestEvent *cre; FvwmWindow *fw = ea->exc->w.fw; DBUG("HandleConfigureRequest", "Routine Entered"); cre = &te->xconfigurerequest; /* te->xany.window is te->.xconfigurerequest.parent, so the context * window may be wrong. */ if (XFindContext(dpy, cre->window, FvwmContext, (caddr_t *)&fw) == XCNOENT) { fw = NULL; } _handle_configure_request(te, ea, fw, False, ForgetGravity); return; } void HandleDestroyNotify(const evh_args_t *ea) { DBUG("HandleDestroyNotify", "Routine Entered"); destroy_window(ea->exc->w.fw); EWMH_ManageKdeSysTray( ea->exc->x.etrigger->xdestroywindow.window, ea->exc->x.etrigger->type); EWMH_WindowDestroyed(); return; } #define DEBUG_ENTERNOTIFY 0 #if DEBUG_ENTERNOTIFY static int ecount=0; #define ENTER_DBG(x) fprintf x; #else #define ENTER_DBG(x) #endif void HandleEnterNotify(const evh_args_t *ea) { const XEnterWindowEvent *ewp; XEvent d; FvwmWindow *sf; static Bool is_initial_ungrab_pending = True; Bool is_tear_off_menu; const XEvent *te = ea->exc->x.etrigger; FvwmWindow * const fw = ea->exc->w.fw; DBUG("HandleEnterNotify", "Routine Entered"); ewp = &te->xcrossing; ENTER_DBG((stderr, "++++++++ en (%d): fw %p w 0x%08x sw 0x%08x mode 0x%x detail 0x%x '%s'\n", ++ecount, fw, (int)ewp->window, (int)ewp->subwindow, ewp->mode, ewp->detail, fw?fw->visible_name:"(none)")); if ( ewp->window == Scr.Root && ewp->detail == NotifyInferior && ewp->mode == NotifyNormal) { /* pointer left subwindow */ BroadcastPacket( MX_ENTER_WINDOW, 3, (long)Scr.Root, (long)NULL, (long)NULL); } else if ( ewp->window == Scr.Root && ewp->detail == NotifyNonlinearVirtual) { /* pointer entered screen */ BroadcastPacket( MX_ENTER_WINDOW, 3, (long)Scr.Root, (long)NULL, (long)NULL); } if (Scr.ColormapFocus == COLORMAP_FOLLOWS_MOUSE) { if (fw && !IS_ICONIFIED(fw) && ewp->window == FW_W(fw)) { InstallWindowColormaps(fw); } else { /* make sure its for one of our windows */ /* handle a subwindow cmap */ InstallWindowColormaps(NULL); } } else if (!fw) { EnterSubWindowColormap(ewp->window); } if (Scr.flags.is_wire_frame_displayed) { ENTER_DBG((stderr, "en: exit: iwfd\n")); /* Ignore EnterNotify events while a window is resized or moved * as a wire frame; otherwise the window list may be screwed * up. */ return; } if (fw) { if (ewp->window != FW_W_FRAME(fw) && ewp->window != FW_W_PARENT(fw) && ewp->window != FW_W(fw) && ewp->window != FW_W_ICON_TITLE(fw) && ewp->window != FW_W_ICON_PIXMAP(fw)) { /* Ignore EnterNotify that received by any of the sub * windows that don't handle this event. unclutter * triggers these events sometimes, re focusing an * unfocused window under the pointer */ ENTER_DBG((stderr, "en: exit: funny window\n")); return; } } if (Scr.focus_in_pending_window != NULL) { ENTER_DBG((stderr, "en: exit: fipw\n")); /* Ignore EnterNotify event while we are waiting for a window to * receive focus via Focus or FlipFocus commands. */ focus_grab_buttons(fw); return; } if (ewp->mode == NotifyGrab) { ENTER_DBG((stderr, "en: exit: NotifyGrab\n")); return; } else if (ewp->mode == NotifyNormal) { ENTER_DBG((stderr, "en: NotifyNormal\n")); if (ewp->detail == NotifyNonlinearVirtual && ewp->focus == False && ewp->subwindow != None) { /* This takes care of some buggy apps that forget that * one of their dialog subwindows has the focus after * popping up a selection list several times (ddd, * netscape). I'm not convinced that this does not * break something else. */ ENTER_DBG((stderr, "en: NN: refreshing focus\n")); refresh_focus(fw); } } else if (ewp->mode == NotifyUngrab) { ENTER_DBG((stderr, "en: NotifyUngrab\n")); /* Ignore events generated by grabbing or ungrabbing the * pointer. However, there is no way to prevent the client * application from handling this event and, for example, * grabbing the focus. This will interfere with functions that * transferred the focus to a different window. */ if (is_initial_ungrab_pending) { ENTER_DBG((stderr, "en: NU: initial ungrab pending (lgw = NULL)\n")); is_initial_ungrab_pending = False; xcrossing_last_grab_window = NULL; } else { if (ewp->detail == NotifyNonlinearVirtual && ewp->focus == False && ewp->subwindow != None) { /* see comment above */ ENTER_DBG((stderr, "en: NU: refreshing focus\n")); refresh_focus(fw); } if (fw && fw == xcrossing_last_grab_window) { ENTER_DBG((stderr, "en: exit: NU: is last grab window\n")); if (ewp->window == FW_W_FRAME(fw) || ewp->window == FW_W_ICON_TITLE(fw) || ewp->window == FW_W_ICON_PIXMAP(fw)) { ENTER_DBG((stderr, "en: exit: NU: last grab window = NULL\n")); xcrossing_last_grab_window = NULL; } focus_grab_buttons(fw); return; } else if (fw) { if (ewp->window != FW_W_FRAME(fw) && ewp->window != FW_W_ICON_TITLE(fw) && ewp->window != FW_W_ICON_PIXMAP(fw)) { ENTER_DBG((stderr, "en: exit: NU: not frame window\n")); focus_grab_buttons(fw); return; } } } } if (fw) { is_initial_ungrab_pending = False; } /* look for a matching leaveNotify which would nullify this EnterNotify */ /* * RBW - if we're in startup, this is a coerced focus, so we don't * want to save the event time, or exit prematurely. * * Ignore LeaveNotify events for tear out menus - handled by menu code */ is_tear_off_menu = (fw && IS_TEAR_OFF_MENU(fw) && ewp->window == FW_W(fw)); if (!fFvwmInStartup && !is_tear_off_menu && FCheckTypedWindowEvent(dpy, ewp->window, LeaveNotify, &d)) { if (d.xcrossing.mode == NotifyNormal && d.xcrossing.detail != NotifyInferior) { ENTER_DBG((stderr, "en: exit: found LeaveNotify\n")); return; } } if (ewp->window == Scr.Root) { FvwmWindow *lf = get_last_screen_focus_window(); if (!Scr.flags.is_pointer_on_this_screen) { Scr.flags.is_pointer_on_this_screen = 1; if (lf && lf != &Scr.FvwmRoot && !FP_DO_UNFOCUS_LEAVE(FW_FOCUS_POLICY(lf))) { SetFocusWindow(lf, True, FOCUS_SET_FORCE); } else if (lf != &Scr.FvwmRoot) { ForceDeleteFocus(); } else { /* This was the first EnterNotify event for the * root window - ignore */ } set_last_screen_focus_window(NULL); } else if (!(sf = get_focus_window()) || FP_DO_UNFOCUS_LEAVE(FW_FOCUS_POLICY(sf))) { DeleteFocus(True); } else if ( Scr.UnknownWinFocused != None && sf != NULL && sf == Scr.StolenFocusFvwmWin) { __refocus_stolen_focus_win(ea); } if (Scr.ColormapFocus == COLORMAP_FOLLOWS_MOUSE) { InstallWindowColormaps(NULL); } focus_grab_buttons(lf); return; } else { Scr.flags.is_pointer_on_this_screen = 1; } /* An EnterEvent in one of the PanFrameWindows activates the Paging or an EdgeCommand. */ if (is_pan_frame(ewp->window)) { char *edge_command = NULL; if ( Scr.UnknownWinFocused != None && (sf = get_focus_window()) != NULL && sf == Scr.StolenFocusFvwmWin) { __refocus_stolen_focus_win(ea); } /* check for edge commands */ if (ewp->window == Scr.PanFrameTop.win) { edge_command = Scr.PanFrameTop.command; } else if (ewp->window == Scr.PanFrameBottom.win) { edge_command = Scr.PanFrameBottom.command; } else if (ewp->window == Scr.PanFrameLeft.win) { edge_command = Scr.PanFrameLeft.command; } else if (ewp->window == Scr.PanFrameRight.win) { edge_command = Scr.PanFrameRight.command; } if (edge_command && ewp->mode == NotifyUngrab && ewp->detail == NotifyAncestor) { /* nothing */ } else if (edge_command) { execute_function(NULL, ea->exc, edge_command, 0); } else { /* no edge command for this pan frame - so we do * HandlePaging */ int delta_x = 0; int delta_y = 0; XEvent e; /* this was in the HandleMotionNotify before, HEDU */ Scr.flags.is_pointer_on_this_screen = 1; e = *te; HandlePaging( &e, Scr.EdgeScrollX, Scr.EdgeScrollY, &JunkX, &JunkY, &delta_x, &delta_y, True, True, False, Scr.ScrollDelay); return; } } if (!fw) { return; } if (IS_EWMH_DESKTOP(FW_W(fw))) { BroadcastPacket( MX_ENTER_WINDOW, 3, (long)Scr.Root, (long)NULL, (long)NULL); return; } if (ewp->window == FW_W_FRAME(fw) || ewp->window == FW_W_ICON_TITLE(fw) || ewp->window == FW_W_ICON_PIXMAP(fw)) { BroadcastPacket( MX_ENTER_WINDOW, 3, (long)FW_W(fw), (long)FW_W_FRAME(fw), (unsigned long)fw); } sf = get_focus_window(); if (sf && fw != sf && FP_DO_UNFOCUS_LEAVE(FW_FOCUS_POLICY(sf))) { ENTER_DBG((stderr, "en: delete focus\n")); DeleteFocus(True); } focus_grab_buttons(fw); if (FP_DO_FOCUS_ENTER(FW_FOCUS_POLICY(fw))) { ENTER_DBG((stderr, "en: set mousey focus\n")); if (ewp->window == FW_W(fw)) { /* Event is for the client window...*/ #ifndef EXPERIMENTAL_ROU_HANDLING_V2 /* RBW -- This may still be needed at times, I'm not *sure yet. */ SetFocusWindowClientEntered( fw, True, FOCUS_SET_BY_ENTER); #else SetFocusWindow(fw, True, FOCUS_SET_BY_ENTER); #endif } else { /* Event is for the frame...*/ SetFocusWindow(fw, True, FOCUS_SET_BY_ENTER); } } else if (focus_is_focused(fw) && focus_does_accept_input_focus(fw)) { /* We have to refresh the focus window here in case we left the * focused fvwm window. Motif apps may lose the input focus * otherwise. But do not try to refresh the focus of * applications that want to handle it themselves. */ focus_force_refresh_focus(fw); } else if (sf != fw) { /* Give the window a chance to grab the buttons needed for * raise-on-click */ focus_grab_buttons(sf); } if ( Scr.UnknownWinFocused != None && sf != NULL && sf == Scr.StolenFocusFvwmWin) { __refocus_stolen_focus_win(ea); } /* We get an EnterNotify with mode == UnGrab when fvwm releases the * grab held during iconification. We have to ignore this, or icon * title will be initially raised. */ if (IS_ICONIFIED(fw) && (ewp->mode == NotifyNormal) && (ewp->window == FW_W_ICON_PIXMAP(fw) || ewp->window == FW_W_ICON_TITLE(fw)) && FW_W_ICON_PIXMAP(fw) != None) { SET_ICON_ENTERED(fw, 1); DrawIconWindow(fw, True, False, False, False, NULL); } /* Check for tear off menus */ if (is_tear_off_menu) { menu_enter_tear_off_menu(ea->exc); } return; } void HandleExpose(const evh_args_t *ea) { XEvent e; FvwmWindow * const fw = ea->exc->w.fw; e = *ea->exc->x.etrigger; #if 0 /* This doesn't work well. Sometimes, the expose count is zero although * dozens of expose events are pending. This happens all the time * during a shading animation. Simply flush expose events * unconditionally. */ if (e.xexpose.count != 0) { flush_accumulate_expose(e.xexpose.window, &e); } #else flush_accumulate_expose(e.xexpose.window, &e); #endif if (fw == NULL) { return; } if (e.xany.window == FW_W_ICON_TITLE(fw) || e.xany.window == FW_W_ICON_PIXMAP(fw)) { DrawIconWindow(fw, True, True, False, False, &e); return; } else if (IS_TEAR_OFF_MENU(fw) && e.xany.window == FW_W(fw)) { /* refresh the contents of the torn out menu */ menu_expose(&e, NULL); } return; } void HandleFocusIn(const evh_args_t *ea) { XEvent d; Window w = None; Window focus_w = None; Window focus_fw = None; Pixel fc = 0; Pixel bc = 0; FvwmWindow *ffw_old = get_focus_window(); FvwmWindow *sf; Bool do_force_broadcast = False; Bool is_unmanaged_focused = False; static Window last_focus_w = None; static Window last_focus_fw = None; static Bool was_nothing_ever_focused = True; FvwmWindow *fw = ea->exc->w.fw; DBUG("HandleFocusIn", "Routine Entered"); Scr.focus_in_pending_window = NULL; /* This is a hack to make the PointerKey command work */ if (ea->exc->x.etrigger->xfocus.detail != NotifyPointer) { /**/ w = ea->exc->x.etrigger->xany.window; } while (FCheckTypedEvent(dpy, FocusIn, &d)) { /* dito */ if (d.xfocus.detail != NotifyPointer) { /**/ w = d.xany.window; } } /* dito */ if (w == None) { return; } /**/ if (XFindContext(dpy, w, FvwmContext, (caddr_t *) &fw) == XCNOENT) { fw = NULL; } Scr.UnknownWinFocused = None; if ( fw && Scr.focus_in_requested_window != fw && !FP_DO_FOCUS_BY_PROGRAM(FW_FOCUS_POLICY(fw)) && fw->focus_model == FM_GLOBALLY_ACTIVE) { if (DEBUG_GLOBALLY_ACTIVE) { fprintf( stderr, "prevented globally active fw %p (%s)" " from stealing the focus\n", fw, fw->name.name); fprintf( stderr, "window was %p (%s)\n", Scr.focus_in_pending_window, Scr.focus_in_pending_window ? Scr.focus_in_pending_window->name.name : ""); } Scr.focus_in_requested_window = NULL; __refocus_stolen_focus_win(ea); return; } Scr.focus_in_pending_window = NULL; if (!fw) { if (w != Scr.NoFocusWin) { Scr.UnknownWinFocused = w; Scr.StolenFocusWin = (ffw_old != NULL) ? FW_W(ffw_old) : None; Scr.StolenFocusFvwmWin = ffw_old; focus_w = w; is_unmanaged_focused = True; } /* Only show a non-focused window as focused, * if the focus is on unmanaged and flickering qt dialogs * workaround is on. */ if (!Scr.bo.do_enable_flickering_qt_dialogs_workaround || !is_unmanaged_focused) { border_draw_decorations( Scr.Hilite, PART_ALL, False, True, CLEAR_ALL, NULL, NULL); if (Scr.ColormapFocus == COLORMAP_FOLLOWS_FOCUS) { if ((Scr.Hilite)&&(!IS_ICONIFIED(Scr.Hilite))) { InstallWindowColormaps(Scr.Hilite); } else { InstallWindowColormaps(NULL); } } } /* Not very useful if no window that fvwm and its modules know * about has the focus. */ fc = GetColor(DEFAULT_FORE_COLOR); bc = GetColor(DEFAULT_BACK_COLOR); } else if (fw != Scr.Hilite || /* domivogt (16-May-2000): This check is necessary to force * sending a M_FOCUS_CHANGE packet after an unmanaged window * was focused. Otherwise fvwm would believe that Scr.Hilite * was still focused and not send any info to the modules. */ last_focus_fw == None || IS_FOCUS_CHANGE_BROADCAST_PENDING(fw) || fpol_query_allow_user_focus(&FW_FOCUS_POLICY(fw))) { if (w != Scr.NoFocusWin) { Scr.StolenFocusWin = (ffw_old != NULL) ? FW_W(ffw_old) : None; Scr.StolenFocusFvwmWin = ffw_old; } do_force_broadcast = IS_FOCUS_CHANGE_BROADCAST_PENDING(fw); SET_FOCUS_CHANGE_BROADCAST_PENDING(fw, 0); if (fw != Scr.Hilite && fpol_query_allow_user_focus(&FW_FOCUS_POLICY(fw))) { border_draw_decorations( fw, PART_ALL, True, True, CLEAR_ALL, NULL, NULL); } focus_w = FW_W(fw); focus_fw = FW_W_FRAME(fw); fc = fw->hicolors.fore; bc = fw->hicolors.back; set_focus_window(fw); if (Scr.ColormapFocus == COLORMAP_FOLLOWS_FOCUS) { if ((Scr.Hilite)&&(!IS_ICONIFIED(Scr.Hilite))) { InstallWindowColormaps(Scr.Hilite); } else { InstallWindowColormaps(NULL); } } } else { return; } if (was_nothing_ever_focused || last_focus_fw == None || focus_w != last_focus_w || focus_fw != last_focus_fw || do_force_broadcast) { if (!Scr.bo.do_enable_flickering_qt_dialogs_workaround || !is_unmanaged_focused) { BroadcastPacket( M_FOCUS_CHANGE, 5, (long)focus_w, (long)focus_fw, (unsigned long)IsLastFocusSetByMouse(), (long)fc, (long)bc); EWMH_SetActiveWindow(focus_w); } last_focus_w = focus_w; last_focus_fw = focus_fw; was_nothing_ever_focused = False; } if ((sf = get_focus_window()) != ffw_old) { focus_grab_buttons(sf); focus_grab_buttons(ffw_old); } return; } void HandleFocusOut(const evh_args_t *ea) { if (Scr.UnknownWinFocused != None && Scr.StolenFocusWin != None && ea->exc->x.etrigger->xfocus.window == Scr.UnknownWinFocused) { __refocus_stolen_focus_win(ea); } return; } void __handle_key(const evh_args_t *ea, Bool is_press) { char *action; FvwmWindow *sf; KeyCode kc; int kcontext; const XEvent *te = ea->exc->x.etrigger; const FvwmWindow * const fw = ea->exc->w.fw; Bool is_second_binding; const XClassHint *winClass1, *winClass2; XClassHint tmp; char *name1, *name2; const exec_context_t *exc; exec_context_changes_t ecc; PressedW = None; /* Here's a real hack - some systems have two keys with the * same keysym and different keycodes. This converts all * the cases to one keycode. */ kc = XKeysymToKeycode(dpy, fvwm_KeycodeToKeysym(dpy, te->xkey.keycode, 0, 0)); /* Check if there is something bound to the key */ sf = get_focus_window(); if (sf == NULL) { tmp.res_name = tmp.res_class = name1 = "root"; winClass1 = &tmp; kcontext = C_ROOT; } else { winClass1 = &sf->class; name1 = sf->name.name; kcontext = (sf == fw ? ea->exc->w.wcontext : C_WINDOW); } if (fw == NULL) { tmp.res_name = tmp.res_class = name2 = "root"; winClass2 = &tmp; } else { winClass2 = &fw->class; name2 = fw->name.name; } /* Searching the binding list with a different 'type' value * (ie. BIND_KEYPRESS vs BIND_PKEYPRESS) doesn't make a difference. * The different context value does though. */ action = CheckTwoBindings( &is_second_binding, Scr.AllBindings, STROKE_ARG(0) kc, te->xkey.state, GetUnusedModifiers(), kcontext, BIND_KEYPRESS, winClass1, name1, ea->exc->w.wcontext, BIND_PKEYPRESS, winClass2, name2); if (action != NULL) { if (!is_press) { XAllowEvents(dpy, AsyncKeyboard, CurrentTime); return; } exc = ea->exc; if (is_second_binding == False) { ecc.w.fw = sf; ecc.w.wcontext = kcontext; exc = exc_clone_context( ea->exc, &ecc, ECC_FW | ECC_WCONTEXT); } execute_function(NULL, exc, action, 0); if (is_second_binding == False) { exc_destroy_context(exc); } XAllowEvents(dpy, AsyncKeyboard, CurrentTime); return; } /* if we get here, no function key was bound to the key. Send it * to the client if it was in a window we know about. */ sf = get_focus_window(); if (sf && te->xkey.window != FW_W(sf)) { XEvent e; e = *te; e.xkey.window = FW_W(sf); FSendEvent( dpy, e.xkey.window, False, (is_press)? KeyPressMask:KeyReleaseMask, &e); } else if (fw && te->xkey.window != FW_W(fw)) { XEvent e; e = *te; e.xkey.window = FW_W(fw); FSendEvent( dpy, e.xkey.window, False, (is_press)? KeyPressMask:KeyReleaseMask, &e); } XAllowEvents(dpy, AsyncKeyboard, CurrentTime); return; } void HandleKeyPress(const evh_args_t *ea) { __handle_key(ea, True); } void HandleKeyRelease(const evh_args_t *ea) { __handle_key(ea, False); } void HandleLeaveNotify(const evh_args_t *ea) { const XLeaveWindowEvent *lwp; const XEvent *te = ea->exc->x.etrigger; FvwmWindow * const fw = ea->exc->w.fw; DBUG("HandleLeaveNotify", "Routine Entered"); ENTER_DBG((stderr, "-------- ln (%d): fw %p w 0x%08x sw 0x%08x mode 0x%x detail 0x%x '%s'\n", ++ecount, fw, (int)te->xcrossing.window, (int)te->xcrossing.subwindow, te->xcrossing.mode, te->xcrossing.detail, fw?fw->visible_name:"(none)")); lwp = &te->xcrossing; if ( lwp->window == Scr.Root && lwp->detail == NotifyInferior && lwp->mode == NotifyNormal) { /* pointer entered subwindow */ BroadcastPacket( MX_LEAVE_WINDOW, 3, (long)Scr.Root, (long)NULL, (long)NULL); } else if ( lwp->window == Scr.Root && lwp->detail == NotifyNonlinearVirtual) { /* pointer left screen */ BroadcastPacket( MX_LEAVE_WINDOW, 3, (long)Scr.Root, (long)NULL, (long)NULL); } /* Ignore LeaveNotify events while a window is resized or moved as a * wire frame; otherwise the window list may be screwed up. */ if (Scr.flags.is_wire_frame_displayed) { return; } if (lwp->mode != NotifyNormal) { /* Ignore events generated by grabbing or ungrabbing the * pointer. However, there is no way to prevent the client * application from handling this event and, for example, * grabbing the focus. This will interfere with functions that * transferred the focus to a different window. It is * necessary to check for LeaveNotify events on the client * window too in case buttons are not grabbed on it. */ if (lwp->mode == NotifyGrab && fw && (lwp->window == FW_W_FRAME(fw) || lwp->window == FW_W(fw) || lwp->window == FW_W_ICON_TITLE(fw) || lwp->window == FW_W_ICON_PIXMAP(fw))) { ENTER_DBG((stderr, "ln: *** lgw = %p\n", fw)); xcrossing_last_grab_window = fw; } #ifdef FOCUS_EXPANDS_TITLE if (fw && IS_ICONIFIED(fw)) { SET_ICON_ENTERED(fw, 0); DrawIconWindow( fw, True, False, False, False, NULL); } #endif return; } /* CDE-like behaviour of raising the icon title if the icon gets the focus (in particular if the cursor is over the icon) */ if (fw && IS_ICONIFIED(fw)) { SET_ICON_ENTERED(fw,0); DrawIconWindow(fw, True, False, False, False, NULL); } /* An LeaveEvent in one of the PanFrameWindows activates an EdgeLeaveCommand. */ if (is_pan_frame(lwp->window)) { char *edge_command_leave = NULL; /* check for edge commands */ if (lwp->window == Scr.PanFrameTop.win) { edge_command_leave = Scr.PanFrameTop.command_leave; } else if (lwp->window == Scr.PanFrameBottom.win) { edge_command_leave = Scr.PanFrameBottom.command_leave; } else if (lwp->window == Scr.PanFrameLeft.win) { edge_command_leave = Scr.PanFrameLeft.command_leave; } else if (lwp->window == Scr.PanFrameRight.win) { edge_command_leave = Scr.PanFrameRight.command_leave; } if (edge_command_leave && lwp->mode == NotifyUngrab && lwp->detail == NotifyAncestor) { /* nothing */ } else if (edge_command_leave) { execute_function(NULL, ea->exc, edge_command_leave, 0); } } /* If we leave the root window, then we're really moving * another screen on a multiple screen display, and we * need to de-focus and unhighlight to make sure that we * don't end up with more than one highlighted window at a time */ if (lwp->window == Scr.Root && /* domivogt (16-May-2000): added this test because somehow fvwm * sometimes gets a LeaveNotify on the root window although it is * single screen. */ Scr.NumberOfScreens > 1) { if (lwp->mode == NotifyNormal) { if (lwp->detail != NotifyInferior) { FvwmWindow *sf = get_focus_window(); Scr.flags.is_pointer_on_this_screen = 0; set_last_screen_focus_window(sf); if (sf != NULL) { DeleteFocus(True); } if (Scr.Hilite != NULL) { border_draw_decorations( Scr.Hilite, PART_ALL, False, True, CLEAR_ALL, NULL, NULL); } } } } else { /* handle a subwindow cmap */ LeaveSubWindowColormap(te->xany.window); } if (fw != NULL && (lwp->window == FW_W_FRAME(fw) || lwp->window == FW_W_ICON_TITLE(fw) || lwp->window == FW_W_ICON_PIXMAP(fw))) { BroadcastPacket( MX_LEAVE_WINDOW, 3, (long)FW_W(fw), (long)FW_W_FRAME(fw), (unsigned long)fw); } return; } void HandleMapNotify(const evh_args_t *ea) { Bool is_on_this_page = False; const XEvent *te = ea->exc->x.etrigger; FvwmWindow * const fw = ea->exc->w.fw; DBUG("HandleMapNotify", "Routine Entered"); if (!fw) { if (te->xmap.override_redirect == True && te->xmap.window != Scr.NoFocusWin) { XSelectInput(dpy, te->xmap.window, XEVMASK_ORW); XFlush(dpy); Scr.UnknownWinFocused = te->xmap.window; } return; } if (te->xmap.window == FW_W_FRAME(fw)) { /* Now that we know the frame is mapped after capturing the * window we do not need StructureNotifyMask events anymore. */ XSelectInput(dpy, FW_W_FRAME(fw), XEVMASK_FRAMEW); XFlush(dpy); } /* Except for identifying over-ride redirect window mappings, we * don't need or want windows associated with the * SubstructureNotifyMask */ if (te->xmap.event != te->xmap.window) { return; } SET_MAP_PENDING(fw, 0); /* don't map if the event was caused by a de-iconify */ if (IS_ICONIFY_PENDING(fw)) { return; } /* Make sure at least part of window is on this page before giving it * focus... */ is_on_this_page = IsRectangleOnThisPage(&(fw->g.frame), fw->Desk); /* * Need to do the grab to avoid race condition of having server send * MapNotify to client before the frame gets mapped; this is bad because * the client would think that the window has a chance of being viewable * when it really isn't. */ MyXGrabServer (dpy); if (FW_W_ICON_TITLE(fw)) { XUnmapWindow(dpy, FW_W_ICON_TITLE(fw)); } if (FW_W_ICON_PIXMAP(fw) != None) { XUnmapWindow(dpy, FW_W_ICON_PIXMAP(fw)); } XMapSubwindows(dpy, FW_W_FRAME(fw)); if (fw->Desk == Scr.CurrentDesk) { XMapWindow(dpy, FW_W_FRAME(fw)); } if (IS_ICONIFIED(fw)) { BroadcastPacket( M_DEICONIFY, 3, (long)FW_W(fw), (long)FW_W_FRAME(fw), (unsigned long)fw); } else { BroadcastPacket( M_MAP, 3, (long)FW_W(fw), (long)FW_W_FRAME(fw), (unsigned long)fw); } if (is_on_this_page && focus_query_open_grab_focus(fw, get_focus_window()) == True) { SetFocusWindow(fw, True, FOCUS_SET_FORCE); } border_draw_decorations( fw, PART_ALL, (fw == get_focus_window()) ? True : False, True, CLEAR_ALL, NULL, NULL); MyXUngrabServer (dpy); SET_MAPPED(fw, 1); SET_ICONIFIED(fw, 0); SET_ICON_UNMAPPED(fw, 0); if (DO_ICONIFY_AFTER_MAP(fw)) { initial_window_options_t win_opts; /* finally, if iconification was requested before the window * was mapped, request it now. */ memset(&win_opts, 0, sizeof(win_opts)); Iconify(fw, &win_opts); SET_ICONIFY_AFTER_MAP(fw, 0); } focus_grab_buttons_on_layer(fw->layer); return; } void HandleMappingNotify(const evh_args_t *ea) { XRefreshKeyboardMapping(&ea->exc->x.etrigger->xmapping); return; } void HandleMapRequest(const evh_args_t *ea) { DBUG("HandleMapRequest", "Routine Entered"); if (fFvwmInStartup) { /* Just map the damn thing, decorations are added later * in CaptureAllWindows. */ XMapWindow(dpy, ea->exc->x.etrigger->xmaprequest.window); return; } HandleMapRequestKeepRaised(ea, None, NULL, NULL); return; } void HandleMapRequestKeepRaised( const evh_args_t *ea, Window KeepRaised, FvwmWindow *ReuseWin, initial_window_options_t *win_opts) { Bool is_on_this_page = False; Bool is_new_window = False; FvwmWindow *tmp; FvwmWindow *sf; initial_window_options_t win_opts_bak; Window ew; FvwmWindow *fw; extern Bool Restarting; const char *initial_map_command; initial_map_command = NULL; if (win_opts == NULL) { memset(&win_opts_bak, 0, sizeof(win_opts_bak)); win_opts = &win_opts_bak; } ew = ea->exc->w.w; if (ReuseWin == NULL) { if (XFindContext(dpy, ew, FvwmContext, (caddr_t *)&fw) == XCNOENT) { fw = NULL; } if (fw != NULL && IS_MAP_PENDING(fw)) { /* The window is already going to be mapped, no need to * do that twice */ return; } } else { fw = ReuseWin; } if (fw == NULL && EWMH_IsKdeSysTrayWindow(ew)) { /* This means that the window is swallowed by kicker and that * kicker restart or exit. As we should assume that kicker * restart we should return here, if not we go into trouble * ... */ return; } if (!win_opts->flags.do_override_ppos) { XFlush(dpy); } /* If the window has never been mapped before ... */ if (!fw || (fw && DO_REUSE_DESTROYED(fw))) { /* Add decorations. */ fw = AddWindow( &initial_map_command, ea->exc, ReuseWin, win_opts); if (fw == AW_NO_WINDOW) { return; } else if (fw == AW_UNMANAGED) { XMapWindow(dpy, ew); return; } is_new_window = True; } /* * Make sure at least part of window is on this page * before giving it focus... */ is_on_this_page = IsRectangleOnThisPage(&(fw->g.frame), fw->Desk); if (KeepRaised != None) { XRaiseWindow(dpy, KeepRaised); } /* If it's not merely iconified, and we have hints, use them. */ if (IS_ICONIFIED(fw)) { /* If no hints, or currently an icon, just "deiconify" */ DeIconify(fw); } else if (IS_MAPPED(fw)) { /* the window is already mapped - fake a MapNotify event */ fake_map_unmap_notify(fw, MapNotify); } else { int state; if (fw->wmhints && (fw->wmhints->flags & StateHint)) { state = fw->wmhints->initial_state; } else { state = NormalState; } if (win_opts->initial_state != DontCareState) { state = win_opts->initial_state; } switch (state) { case DontCareState: case NormalState: case InactiveState: default: MyXGrabServer(dpy); if (fw->Desk == Scr.CurrentDesk) { Bool do_grab_focus; SET_MAP_PENDING(fw, 1); XMapWindow(dpy, FW_W_FRAME(fw)); XMapWindow(dpy, FW_W(fw)); SetMapStateProp(fw, NormalState); if (Scr.flags.is_map_desk_in_progress) { do_grab_focus = False; } else if (!is_on_this_page) { do_grab_focus = False; } else if (focus_query_open_grab_focus( fw, get_focus_window()) == True) { do_grab_focus = True; } else { do_grab_focus = False; } if (do_grab_focus) { SetFocusWindow( fw, True, FOCUS_SET_FORCE); } else { /* make sure the old focused window * still has grabbed all necessary * buttons. */ focus_grab_buttons( get_focus_window()); } } else { #ifndef ICCCM2_UNMAP_WINDOW_PATCH /* nope, this is forbidden by the ICCCM2 */ XMapWindow(dpy, FW_W(fw)); SetMapStateProp(fw, NormalState); #else /* Since we will not get a MapNotify, set the * IS_MAPPED flag manually. */ SET_MAPPED(fw, 1); SetMapStateProp(fw, IconicState); /* fake that the window was mapped to allow * modules to swallow it */ BroadcastPacket( M_MAP, 3, (long)FW_W(fw), (long)FW_W_FRAME(fw), (unsigned long)fw); #endif } /* TA: 20090125: We *have* to handle * InitialMapCommand here and not in AddWindow() to * allow for correct timings when the window is truly * mapped. (c.f. things like Iconify.) */ /* TA: 20091212: But only do this when we're *not* * restarting -- the window is still mapped, but gets * recaptured -- we don't want to trigger this event * again. Otherwise we end up toggling the state of * the window in situations where the * InitialMapCommand is Iconify or Maximize, for * instance. */ if ((initial_map_command != NULL) && (!Restarting && Scr.flags.are_windows_captured)) { execute_function_override_window( NULL, ea->exc, (char *)initial_map_command, 0, fw); } MyXUngrabServer(dpy); break; case IconicState: if (is_new_window) { /* the window will not be mapped - fake a * MapNotify and an UnmapNotify event. Can't * remember exactly why this is necessary, but * probably something w/ (de)iconify state * confusion. */ fake_map_unmap_notify(fw, MapNotify); fake_map_unmap_notify(fw, UnmapNotify); } if (win_opts->flags.is_iconified_by_parent || ((tmp = get_transientfor_fvwmwindow(fw)) && IS_ICONIFIED(tmp))) { win_opts->flags.is_iconified_by_parent = 0; SET_ICONIFIED_BY_PARENT(fw, 1); } if (USE_ICON_POSITION_HINT(fw) && fw->wmhints && (fw->wmhints->flags & IconPositionHint)) { win_opts->default_icon_x = fw->wmhints->icon_x; win_opts->default_icon_y = fw->wmhints->icon_y; } Iconify(fw, win_opts); break; } } if (IS_SHADED(fw)) { BroadcastPacket( M_WINDOWSHADE, 3, (long)FW_W(fw), (long)FW_W_FRAME(fw), (unsigned long)fw); } /* If the newly mapped window overlaps the focused window, make sure * ClickToFocusRaises and MouseFocusClickRaises work again. */ sf = get_focus_window(); if (sf != NULL) { focus_grab_buttons(sf); } if (win_opts->flags.is_menu) { SET_MAPPED(fw, 1); SET_MAP_PENDING(fw, 0); } EWMH_SetClientList(); EWMH_SetClientListStacking(); return; } #ifdef HAVE_STROKE void HandleMotionNotify(const evh_args_t *ea) { DBUG("HandleMotionNotify", "Routine Entered"); if (send_motion == True) { stroke_record( ea->exc->x.etrigger->xmotion.x, ea->exc->x.etrigger->xmotion.y); } return; } #endif /* HAVE_STROKE */ void HandlePropertyNotify(const evh_args_t *ea) { Bool has_icon_changed = False; Bool has_icon_pixmap_hint_changed = False; Bool has_icon_window_hint_changed = False; /* NoName is an extern pointer to a constant "Untitled". See lib/Flocale.c FlocaleFreeNameProperty to see how this initialization causes a problem: */ FlocaleNameString new_name = { NoName, NULL }; int old_wmhints_flags; const XEvent *te = ea->exc->x.etrigger; char *urgency_action = NULL; FvwmWindow * const fw = ea->exc->w.fw; DBUG("HandlePropertyNotify", "Routine Entered"); if (te->xproperty.window == Scr.Root && te->xproperty.state == PropertyNewValue && (te->xproperty.atom == _XA_XSETROOT_ID || te->xproperty.atom == _XA_XROOTPMAP_ID)) { /* background change */ /* _XA_XSETROOT_ID is used by fvwm-root, xli and more (xv sends * no property notify?). _XA_XROOTPMAP_ID is used by Esetroot * compatible program: the problem here is that with some * Esetroot compatible program we get the message _before_ the * background change. This is fixed with Esetroot 9.2 (not yet * released, 2002-01-14) */ /* update icon window with some alpha and tear-off menu */ FvwmWindow *t; for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) { int cs; int t_cs = -1; int b_cs = t->icon_background_cs; Bool draw_picture = False; Bool draw_title = False; /* redraw ParentRelative tear-off menu */ menu_redraw_transparent_tear_off_menu(t, True); if (!IS_ICONIFIED(t) || IS_ICON_SUPPRESSED(t)) { continue; } if (Scr.Hilite == t) { if (t->icon_title_cs_hi >= 0) { t_cs = cs = t->icon_title_cs_hi; } else { cs = t->cs_hi; } } else { if (t->icon_title_cs >= 0) { t_cs = cs = t->icon_title_cs; } else { cs = t->cs; } } if (t->icon_alphaPixmap != None || (cs >= 0 && Colorset[cs].icon_alpha_percent < 100) || CSET_IS_TRANSPARENT_PR(b_cs) || (!IS_ICON_SHAPED(t) && t->icon_background_padding > 0)) { draw_picture = True; } if (CSET_IS_TRANSPARENT_PR(t_cs)) { draw_title = True; } if (draw_title || draw_picture) { DrawIconWindow( t, draw_title, draw_picture, False, draw_picture, NULL); } } if (te->xproperty.atom == _XA_XROOTPMAP_ID) { update_root_transparent_colorset(te->xproperty.atom); } BroadcastPropertyChange( MX_PROPERTY_CHANGE_BACKGROUND, 0, 0, ""); return; } if (!fw) { return; } switch (te->xproperty.atom) { case XA_WM_TRANSIENT_FOR: { if (setup_transientfor(fw) == True) { RaiseWindow(fw, False); } break; } case XA_WM_NAME: { int changed_names; flush_property_notify_stop_at_event_type( te->xproperty.atom, FW_W(fw), 0, 0); if (XGetGeometry( dpy, FW_W(fw), &JunkRoot, &JunkX, &JunkY, (unsigned int*)&JunkWidth, (unsigned int*)&JunkHeight, (unsigned int*)&JunkBW, (unsigned int*)&JunkDepth) == 0) { /* Window does not exist anymore. */ return; } if (HAS_EWMH_WM_NAME(fw)) { return; } FlocaleGetNameProperty(XGetWMName, dpy, FW_W(fw), &new_name); if (new_name.name == NULL) { FlocaleFreeNameProperty(&new_name); return; } if (strlen(new_name.name) > MAX_WINDOW_NAME_LEN) { /* limit to prevent hanging X server */ (new_name.name)[MAX_WINDOW_NAME_LEN] = 0; } if (fw->name.name && strcmp(new_name.name, fw->name.name) == 0) { /* migo: some apps update their names every second */ /* griph: make sure we don't free the property if it is THE same name */ if (new_name.name != fw->name.name) { FlocaleFreeNameProperty(&new_name); } return; } free_window_names(fw, True, False); fw->name = new_name; SET_NAME_CHANGED(fw, 1); if (fw->name.name == NULL) { fw->name.name = NoName; /* must not happen */ } changed_names = 1; /* * if the icon name is NoName, set the name of the icon to be * the same as the window */ if (!WAS_ICON_NAME_PROVIDED(fw) #if 0 /* dje, reported as causing various dumps. I tried to debug, but so far haven't even figured out how to exercise this logic. Mov 9, 2013. */ || (fw->icon_name.name && (fw->icon_name.name != fw->name.name)) #endif ) { fw->icon_name = fw->name; changed_names |= 2; } update_window_names(fw, changed_names); break; } case XA_WM_ICON_NAME: { flush_property_notify_stop_at_event_type( te->xproperty.atom, FW_W(fw), 0, 0); if (XGetGeometry( dpy, FW_W(fw), &JunkRoot, &JunkX, &JunkY, (unsigned int*)&JunkWidth, (unsigned int*)&JunkHeight, (unsigned int*)&JunkBW, (unsigned int*)&JunkDepth) == 0) { /* Window does not exist anymore. */ return; } if (HAS_EWMH_WM_ICON_NAME(fw)) { return; } FlocaleGetNameProperty( XGetWMIconName, dpy, FW_W(fw), &new_name); if (new_name.name == NULL) { FlocaleFreeNameProperty(&new_name); return; } if (new_name.name && strlen(new_name.name) > MAX_ICON_NAME_LEN) { /* limit to prevent hanging X server */ (new_name.name)[MAX_ICON_NAME_LEN] = 0; } if (fw->icon_name.name && strcmp(new_name.name, fw->icon_name.name) == 0) { /* migo: some apps update their names every second */ /* griph: make sure we don't free the property if it is THE same name */ if (new_name.name != fw->icon_name.name) { FlocaleFreeNameProperty(&new_name); } return; } free_window_names(fw, False, True); fw->icon_name = new_name; SET_WAS_ICON_NAME_PROVIDED(fw, 1); if (fw->icon_name.name == NULL) { /* currently never happens */ fw->icon_name.name = fw->name.name; SET_WAS_ICON_NAME_PROVIDED(fw, 0); } update_window_names(fw, 2); break; } case XA_WM_HINTS: { flush_property_notify_stop_at_event_type( te->xproperty.atom, FW_W(fw), 0, 0); if (XGetGeometry( dpy, FW_W(fw), &JunkRoot, &JunkX, &JunkY, (unsigned int*)&JunkWidth, (unsigned int*)&JunkHeight, (unsigned int*)&JunkBW, (unsigned int*)&JunkDepth) == 0) { /* Window does not exist anymore. */ return; } /* clasen@mathematik.uni-freiburg.de - 02/01/1998 - new - * the urgency flag is an ICCCM 2.0 addition to the WM_HINTS. */ old_wmhints_flags = 0; if (fw->wmhints) { old_wmhints_flags = fw->wmhints->flags; XFree ((char *) fw->wmhints); } setup_wm_hints(fw); if (fw->wmhints == NULL) { return; } /* * rebuild icon if the client either provides an icon * pixmap or window or has reset the hints to `no icon'. */ if ((fw->wmhints->flags & IconPixmapHint) || (old_wmhints_flags & IconPixmapHint)) { ICON_DBG((stderr, "hpn: iph changed (%d) '%s'\n", !!(int)(fw->wmhints->flags & IconPixmapHint), fw->name.name)); has_icon_pixmap_hint_changed = True; } if ((fw->wmhints->flags & IconWindowHint) || (old_wmhints_flags & IconWindowHint)) { ICON_DBG((stderr, "hpn: iwh changed (%d) '%s'\n", !!(int)(fw->wmhints->flags & IconWindowHint), fw->name.name)); has_icon_window_hint_changed = True; SET_USE_EWMH_ICON(fw, False); } increase_icon_hint_count(fw); if (has_icon_window_hint_changed || has_icon_pixmap_hint_changed) { if (ICON_OVERRIDE_MODE(fw) == ICON_OVERRIDE) { ICON_DBG((stderr, "hpn: icon override '%s'\n", fw->name.name)); has_icon_changed = False; } else if (ICON_OVERRIDE_MODE(fw) == NO_ACTIVE_ICON_OVERRIDE) { if (has_icon_pixmap_hint_changed) { if (WAS_ICON_HINT_PROVIDED(fw) == ICON_HINT_MULTIPLE) { ICON_DBG((stderr, "hpn: using further iph '%s'\n", fw->name.name)); has_icon_changed = True; } else if (fw->icon_bitmap_file == NULL || fw->icon_bitmap_file == Scr.DefaultIcon) { ICON_DBG((stderr, "hpn: using first iph '%s'\n", fw->name.name)); has_icon_changed = True; } else { /* ignore the first icon pixmap * hint if the application did * not provide it from the * start */ ICON_DBG((stderr, "hpn: first iph ignored '%s'\n", fw->name.name)); has_icon_changed = False; } } else if (has_icon_window_hint_changed) { ICON_DBG((stderr, "hpn: using iwh '%s'\n", fw->name.name)); has_icon_changed = True; } else { ICON_DBG((stderr, "hpn: iwh not changed, hint ignored '%s'\n", fw->name.name)); has_icon_changed = False; } } else /* NO_ICON_OVERRIDE */ { ICON_DBG((stderr, "hpn: using hint '%s'\n", fw->name.name)); has_icon_changed = True; } if (USE_EWMH_ICON(fw)) { has_icon_changed = False; } if (has_icon_changed) { ICON_DBG((stderr, "hpn: icon changed '%s'\n", fw->name.name)); /* Okay, the icon hint has changed and style * options tell us to honour this change. Now * let's see if we have to use the application * provided pixmap or window (if any), the icon * file provided by the window's style or the * default style's icon. */ if (fw->icon_bitmap_file == Scr.DefaultIcon) { fw->icon_bitmap_file = NULL; } if (!fw->icon_bitmap_file && !(fw->wmhints->flags & (IconPixmapHint|IconWindowHint))) { fw->icon_bitmap_file = (Scr.DefaultIcon) ? Scr.DefaultIcon : NULL; } fw->iconPixmap = (Window)NULL; ChangeIconPixmap(fw); } } /* clasen@mathematik.uni-freiburg.de - 02/01/1998 - new - * the urgency flag is an ICCCM 2.0 addition to the WM_HINTS. * Treat urgency changes by calling user-settable functions. * These could e.g. deiconify and raise the window or * temporarily change the decor. */ if (!(old_wmhints_flags & XUrgencyHint) && (fw->wmhints->flags & XUrgencyHint)) { urgency_action = "Function UrgencyFunc"; } if ((old_wmhints_flags & XUrgencyHint) && !(fw->wmhints->flags & XUrgencyHint)) { urgency_action = "Function UrgencyDoneFunc"; } if (urgency_action) { const exec_context_t *exc; exec_context_changes_t ecc; ecc.w.fw = fw; ecc.w.wcontext = C_WINDOW; exc = exc_clone_context( ea->exc, &ecc, ECC_FW | ECC_WCONTEXT); execute_function(NULL, exc, urgency_action, 0); exc_destroy_context(exc); } break; } case XA_WM_NORMAL_HINTS: /* just mark wm normal hints as changed and look them up when * the next ConfigureRequest w/ x, y, width or height set * arrives. */ SET_HAS_NEW_WM_NORMAL_HINTS(fw, 1); /* TA: 20120317: Always set the size hints here, regardless * of them possibly being modified by a ConfigureNotify * request, due to XSizeHints disallowing resize -- FVWM would * always use old values if the application decided to toggle * such things, and FVWM would then never resize the window. * * Note that SET_HAS_NEW_WM_NORMAL_HINTS being set here to * true is still valid. */ GetWindowSizeHintsWithCheck(fw, 1); break; default: if (te->xproperty.atom == _XA_WM_PROTOCOLS) { FetchWmProtocols (fw); } else if (te->xproperty.atom == _XA_WM_COLORMAP_WINDOWS) { FetchWmColormapWindows (fw); /* frees old data */ ReInstallActiveColormap(); } else if (te->xproperty.atom == _XA_WM_STATE) { /* * Make sure at least part of window is on this page * before giving it focus... */ Bool is_on_this_page; is_on_this_page = IsRectangleOnThisPage( &(fw->g.frame), fw->Desk); if (fw && is_on_this_page == True && focus_is_focused(fw) && FP_DO_FOCUS_ENTER(FW_FOCUS_POLICY(fw))) { /* refresh the focus - why? */ focus_force_refresh_focus(fw); } } else { EWMH_ProcessPropertyNotify(ea->exc); } break; } } void HandleReparentNotify(const evh_args_t *ea) { const XEvent *te = ea->exc->x.etrigger; FvwmWindow * const fw = ea->exc->w.fw; if (!fw) { return; } if (te->xreparent.parent == Scr.Root) { /* Ignore reparenting to the root window. In some cases these * events are selected although the window is no longer * managed. */ return; } if (te->xreparent.parent != FW_W_FRAME(fw)) { /* window was reparented by someone else, destroy the frame */ SetMapStateProp(fw, WithdrawnState); EWMH_RestoreInitialStates(fw, te->type); if (!IS_TEAR_OFF_MENU(fw)) { XRemoveFromSaveSet(dpy, te->xreparent.window); XSelectInput(dpy, te->xreparent.window, NoEventMask); } else { XSelectInput(dpy, te->xreparent.window, XEVMASK_MENUW); } XSync(dpy, 0); FWeedIfWindowEvents(dpy, FW_W_FRAME(fw), NULL, NULL); destroy_window(fw); EWMH_ManageKdeSysTray(te->xreparent.window, te->type); EWMH_WindowDestroyed(); } return; } void HandleSelectionRequest(const evh_args_t *ea) { icccm2_handle_selection_request(ea->exc->x.etrigger); return; } void HandleSelectionClear(const evh_args_t *ea) { icccm2_handle_selection_clear(); return; } void HandleShapeNotify(const evh_args_t *ea) { FvwmWindow * const fw = ea->exc->w.fw; DBUG("HandleShapeNotify", "Routine Entered"); if (FShapesSupported) { const FShapeEvent *sev = (const FShapeEvent *)(ea->exc->x.etrigger); if (!fw) { return; } if (sev->kind != FShapeBounding) { return; } frame_setup_shape( fw, fw->g.frame.width, fw->g.frame.height, sev->shaped); EWMH_SetFrameStrut(fw); if (!IS_ICONIFIED(fw)) { border_redraw_decorations(fw); } } return; } void HandleUnmapNotify(const evh_args_t *ea) { int dstx, dsty; Window dumwin; XEvent dummy; XEvent map_event; const XEvent *te = ea->exc->x.etrigger; Bool focus_grabbed; Bool must_return = False; Bool do_map = False; FvwmWindow * const fw = ea->exc->w.fw; Window pw; Window cw; DBUG("HandleUnmapNotify", "Routine Entered"); if (te->xunmap.event != te->xunmap.window && (te->xunmap.event != Scr.Root || !te->xunmap.send_event)) { /* Nothing to do except updating some states. */ must_return = True; } /* * The July 27, 1988 ICCCM spec states that a client wishing to switch * to WithdrawnState should send a synthetic UnmapNotify with the * event field set to (pseudo-)root, in case the window is already * unmapped (which is the case for fvwm for IconicState). * Unfortunately, we looked for the FvwmContext using that field, so * try the window field also. */ if (!fw) { if (XFindContext( dpy, te->xunmap.window, FvwmContext, (caddr_t *)&fw) == XCNOENT) { return; } } cw = FW_W(fw); pw = FW_W_PARENT(fw); if (te->xunmap.window == FW_W_FRAME(fw)) { SET_ICONIFY_PENDING(fw , 0); return; } if (must_return) { return; } if (fw == Scr.Hilite) { Scr.Hilite = NULL; } focus_grabbed = focus_query_close_release_focus(fw); restore_focus_after_unmap(fw, False); if (!IS_MAPPED(fw) && !IS_ICONIFIED(fw)) { return; } /* * The program may have unmapped the client window, from either * NormalState or IconicState. Handle the transition to WithdrawnState. * * We need to reparent the window back to the root (so that fvwm exiting * won't cause it to get mapped) and then throw away all state (pretend * that we've received a DestroyNotify). */ if (!FCheckTypedWindowEvent( dpy, te->xunmap.window, DestroyNotify, &dummy) && XTranslateCoordinates( dpy, te->xunmap.window, Scr.Root, 0, 0, &dstx, &dsty, &dumwin)) { MyXGrabServer(dpy); SetMapStateProp(fw, WithdrawnState); EWMH_RestoreInitialStates(fw, te->type); if (FCheckTypedWindowEvent( dpy, te->xunmap.window, ReparentNotify, &dummy)) { if (fw->attr_backup.border_width) { XSetWindowBorderWidth( dpy, te->xunmap.window, fw->attr_backup.border_width); } if ((!IS_ICON_SUPPRESSED(fw))&& (fw->wmhints && (fw->wmhints->flags & IconWindowHint))) { XUnmapWindow(dpy, fw->wmhints->icon_window); } } else { RestoreWithdrawnLocation(fw, False, Scr.Root); } if (!IS_TEAR_OFF_MENU(fw)) { XRemoveFromSaveSet(dpy, te->xunmap.window); XSelectInput(dpy, te->xunmap.window, NoEventMask); } XSync(dpy, 0); MyXUngrabServer(dpy); if (FCheckTypedWindowEvent(dpy, pw, MapRequest, &map_event)) { /* the client tried to map the window again while it * was still inside the decoration windows */ do_map = True; } } destroy_window(fw); if (focus_grabbed == True) { CoerceEnterNotifyOnCurrentWindow(); } EWMH_ManageKdeSysTray(te->xunmap.window, te->type); EWMH_WindowDestroyed(); if (do_map == True) { map_event.xmaprequest.window = cw; map_event.xmaprequest.parent = Scr.Root; dispatch_event(&map_event); /* note: we really should handle all map and unmap notify * events for that window in a loop here */ } return; } void HandleVisibilityNotify(const evh_args_t *ea) { FvwmWindow * const fw = ea->exc->w.fw; DBUG("HandleVisibilityNotify", "Routine Entered"); if (fw && ea->exc->x.etrigger->xvisibility.window == FW_W_FRAME(fw)) { switch (ea->exc->x.etrigger->xvisibility.state) { case VisibilityUnobscured: SET_FULLY_VISIBLE(fw, 1); SET_PARTIALLY_VISIBLE(fw, 1); break; case VisibilityPartiallyObscured: SET_FULLY_VISIBLE(fw, 0); SET_PARTIALLY_VISIBLE(fw, 1); break; default: SET_FULLY_VISIBLE(fw, 0); SET_PARTIALLY_VISIBLE(fw, 0); break; } /* Make sure the button grabs are up to date */ focus_grab_buttons(fw); } return; } /* ---------------------------- interface functions ------------------------ */ /* Inform a client window of its geometry. * * The input (frame) geometry will be translated to client geometry * before sending. */ void SendConfigureNotify( FvwmWindow *fw, int x, int y, int w, int h, int bw, Bool send_for_frame_too) { XEvent client_event; size_borders b; if (!fw || IS_SHADED(fw)) { return; } client_event.type = ConfigureNotify; client_event.xconfigure.display = dpy; client_event.xconfigure.event = FW_W(fw); client_event.xconfigure.window = FW_W(fw); get_window_borders(fw, &b); client_event.xconfigure.x = x + b.top_left.width; client_event.xconfigure.y = y + b.top_left.height; client_event.xconfigure.width = w - b.total_size.width; client_event.xconfigure.height = h - b.total_size.height; client_event.xconfigure.border_width = bw; client_event.xconfigure.above = FW_W_FRAME(fw); client_event.xconfigure.override_redirect = False; #if 0 fprintf(stderr, "send cn: %d %d %dx%d fw 0x%08x w 0x%08x ew 0x%08x '%s'\n", client_event.xconfigure.x, client_event.xconfigure.y, client_event.xconfigure.width, client_event.xconfigure.height, (int)FW_W_FRAME(fw), (int)FW_W(fw), (int)client_event.xconfigure.window, (fw->name.name) ? fw->name.name : ""); #endif fev_sanitise_configure_notify(&client_event.xconfigure); FSendEvent( dpy, FW_W(fw), False, StructureNotifyMask, &client_event); if (send_for_frame_too) { /* This is for buggy tk, which waits for the real * ConfigureNotify on frame instead of the synthetic one on w. * The geometry data in the event will not be correct for the * frame, but tk doesn't look at that data anyway. */ client_event.xconfigure.event = FW_W_FRAME(fw); client_event.xconfigure.window = FW_W_FRAME(fw); FSendEvent( dpy, FW_W_FRAME(fw), False, StructureNotifyMask, &client_event); } return; } /* Add an event group to the event handler */ int register_event_group(int event_base, int event_count, PFEH *jump_table) { /* insert into the list */ event_group_t *group; event_group_t *position = base_event_group; event_group_t *prev_position = NULL; while ( position != NULL && position->base + position->count < event_base) { prev_position = position; position = position->next; } if ((position != NULL && position->base < event_base + event_count)) { /* there is already an event group registered at the specified * event range, or the base is before the base X events */ return 1; } /* create the group structure (these are not freed until fvwm exits) */ group = (event_group_t*)safemalloc(sizeof(event_group_t)); group->base = event_base; group->count = event_count; group->jump_table = jump_table; group->next = position; if (prev_position != NULL) { prev_position->next = group; } else { base_event_group = group; } return 0; } /* ** Procedure: ** InitEventHandlerJumpTable */ void InitEventHandlerJumpTable(void) { static PFEH EventHandlerJumpTable[LASTEvent]; int i; for (i=0; ixany.window; FvwmWindow *fw; event_group_t *event_group; DBUG("dispatch_event", "Routine Entered"); XFlush(dpy); if (w == Scr.Root) { switch (e->type) { case ButtonPress: case ButtonRelease: if (e->xbutton.subwindow != None) { w = e->xbutton.subwindow; } case MapRequest: w = e->xmaprequest.window; break; default: break; } } if (w == Scr.Root || XFindContext(dpy, w, FvwmContext, (caddr_t *)&fw) == XCNOENT) { fw = NULL; } if ( fw != NULL && IS_SCHEDULED_FOR_DESTROY(fw) && e->type != DestroyNotify) { return; } last_event_type = e->type; event_group = base_event_group; while ( event_group != NULL && event_group->base + event_group->count < e->type) { event_group = event_group->next; } if ( event_group != NULL && e->type - event_group->base < event_group->count && event_group->jump_table[e->type - event_group->base] != NULL) { evh_args_t ea; exec_context_changes_t ecc; Window dummyw; ecc.type = EXCT_EVENT; ecc.x.etrigger = e; ecc.w.wcontext = GetContext(&fw, fw, e, &dummyw); ecc.w.w = w; ecc.w.fw = fw; ea.exc = exc_create_context( &ecc, ECC_TYPE | ECC_ETRIGGER | ECC_FW | ECC_W | ECC_WCONTEXT); (*event_group->jump_table[e->type - event_group->base])(&ea); exc_destroy_context(ea.exc); } #ifdef C_ALLOCA /* If we're using the C version of alloca, see if anything needs to be * freed up. */ alloca(0); #endif DBUG("dispatch_event", "Leaving Routine"); return; } /* ewmh configure request */ void events_handle_configure_request( XEvent *cre, FvwmWindow *fw, Bool force, int force_gravity) { _handle_configure_request(cre, NULL, fw, force, force_gravity); return; } void HandleEvents(void) { XEvent ev; DBUG("HandleEvents", "Routine Entered"); STROKE_CODE(send_motion = False); while (!isTerminated) { last_event_type = 0; if (Scr.flags.is_window_scheduled_for_destroy) { destroy_scheduled_windows(); } if (Scr.flags.do_need_window_update) { flush_window_updates(); } if (My_XNextEvent(dpy, &ev)) { /* DV (19-Sep-2014): We mark events as invalid by * setting the send_event field to a bogus value in a * predicate procedure. It's unsure whether this works * reliably. */ if (FEV_IS_EVENT_INVALID(ev)) { continue; } dispatch_event(&ev); } if (Scr.flags.do_need_style_list_update) { simplify_style_list(); } } return; } /* * * Waits for next X or module event, fires off startup routines when startup * modules have finished or after a timeout if the user has specified a * command line module that doesn't quit or gets stuck. * */ int My_XNextEvent(Display *dpy, XEvent *event) { fd_set in_fdset, out_fdset; int num_fd; fmodule_list_itr moditr; fmodule *module; fmodule_input *input; static struct timeval timeout; static struct timeval *timeoutP = &timeout; DBUG("My_XNextEvent", "Routine Entered"); /* check for any X events already queued up. * Side effect: this does an XFlush if no events are queued * Make sure nothing between here and the select causes further * X requests to be sent or the select may block even though * there are events in the queue */ if (FPending(dpy)) { DBUG( "My_XNextEvent", "taking care of queued up events" " & returning (1)"); FNextEvent(dpy, event); return 1; } /* check for termination of all startup modules */ if (fFvwmInStartup) { module_list_itr_init(&moditr); module = module_list_itr_next(&moditr); for (; module != NULL; module = module_list_itr_next(&moditr)) { if (MOD_IS_CMDLINE(module) == 1) { break; } } module_cleanup(); if (module == NULL) { /* last module */ DBUG( "My_XNextEvent", "Starting up after command lines modules"); /* set an infinite timeout to stop ticking */ timeoutP = NULL; /* This may cause X requests to be sent */ StartupStuff(); return 0; /* so return without select()ing */ } } /* Some signals can interrupt us while we wait for any action * on our descriptors. While some of these signals may be asking * fvwm to die, some might be harmless. Harmless interruptions * mean we have to start waiting all over again ... */ do { int ms; Bool is_waiting_for_scheduled_command = False; static struct timeval *old_timeoutP = NULL; /* The timeouts become undefined whenever the select returns, * and so we have to reinitialise them */ ms = squeue_get_next_ms(); if (ms == 0) { /* run scheduled commands */ squeue_execute(); ms = squeue_get_next_ms(); /* should not happen anyway. * get_next_schedule_queue_ms() can't return 0 after a * call to execute_schedule_queue(). */ if (ms == 0) { ms = 1; } } if (ms < 0) { timeout.tv_sec = 42; timeout.tv_usec = 0; } else { /* scheduled commands are pending - don't wait too * long */ timeout.tv_sec = ms / 1000; timeout.tv_usec = 1000 * (ms % 1000); old_timeoutP = timeoutP; timeoutP = &timeout; is_waiting_for_scheduled_command = True; } FD_ZERO(&in_fdset); FD_ZERO(&out_fdset); FD_SET(x_fd, &in_fdset); /* nothing is done here if fvwm was compiled without session * support */ if (sm_fd >= 0) { FD_SET(sm_fd, &in_fdset); } module_list_itr_init(&moditr); while ( (module = module_list_itr_next(&moditr)) != NULL) { FD_SET(MOD_READFD(module), &in_fdset); if (!FQUEUE_IS_EMPTY(&MOD_PIPEQUEUE(module))) { FD_SET(MOD_WRITEFD(module), &out_fdset); } } DBUG("My_XNextEvent", "waiting for module input/output"); num_fd = fvwmSelect( fvwmlib_max_fd, &in_fdset, &out_fdset, 0, timeoutP); if (is_waiting_for_scheduled_command) { timeoutP = old_timeoutP; } /* Express route out of fvwm ... */ if (isTerminated) { return 0; } } while (num_fd < 0); if (num_fd > 0) { /* Check for module input. */ module_list_itr_init(&moditr); while ( (module = module_list_itr_next(&moditr)) != NULL) { if (FD_ISSET(MOD_READFD(module), &in_fdset)) { input = module_receive(module); /* enqueue the received command */ module_input_enqueue(input); } if ( MOD_WRITEFD(module) >= 0 && FD_ISSET(MOD_WRITEFD(module), &out_fdset)) { DBUG("My_XNextEvent", "calling FlushMessageQueue"); FlushMessageQueue(module); } } /* execute any commands queued up */ DBUG("My_XNextEvent", "executing module comand queue"); ExecuteCommandQueue(); /* cleanup dead modules */ module_cleanup(); /* nothing is done here if fvwm was compiled without session * support */ if ((sm_fd >= 0) && (FD_ISSET(sm_fd, &in_fdset))) { ProcessICEMsgs(); } } else { /* select has timed out, things must have calmed down so let's * decorate */ if (fFvwmInStartup) { fvwm_msg(ERR, "My_XNextEvent", "Some command line modules have not quit, " "Starting up after timeout.\n"); StartupStuff(); timeoutP = NULL; /* set an infinite timeout to stop * ticking */ reset_style_changes(); Scr.flags.do_need_window_update = 0; } /* run scheduled commands if necessary */ squeue_execute(); } /* check for X events again, rather than return 0 and get called again */ if (FPending(dpy)) { DBUG("My_XNextEvent", "taking care of queued up events & returning (2)"); FNextEvent(dpy,event); return 1; } DBUG("My_XNextEvent", "leaving My_XNextEvent"); return 0; } /* * * Procedure: * Find the Fvwm context for the event. * */ int GetContext(FvwmWindow **ret_fw, FvwmWindow *t, const XEvent *e, Window *w) { int context; Window win; Window subw = None; int x = 0; int y = 0; Bool is_key_event = False; win = e->xany.window; context = C_NO_CONTEXT; switch (e->type) { case KeyPress: case KeyRelease: x = e->xkey.x; y = e->xkey.y; subw = e->xkey.subwindow; if (win == Scr.Root && subw != None) { /* Translate root coordinates into subwindow * coordinates. Necessary for key bindings that work * over unfocused windows. */ win = subw; XTranslateCoordinates( dpy, Scr.Root, subw, x, y, &x, &y, &subw); XFindContext(dpy, win, FvwmContext, (caddr_t *) &t); } is_key_event = True; /* fall through */ case ButtonPress: case ButtonRelease: if (!is_key_event) { x = e->xbutton.x; y = e->xbutton.y; subw = e->xbutton.subwindow; } if (t && win == FW_W_FRAME(t) && subw != None) { /* Translate frame coordinates into subwindow * coordinates. */ win = subw; XTranslateCoordinates( dpy, FW_W_FRAME(t), subw, x, y, &x, &y, &subw); if (win == FW_W_PARENT(t)) { win = subw; XTranslateCoordinates( dpy, FW_W_PARENT(t), subw, x, y, &x, &y, &subw); } } break; default: XFindContext(dpy, win, FvwmContext, (caddr_t *)&t); break; } if (ret_fw != NULL) { *ret_fw = t; } if (!t) { return C_ROOT; } *w = win; if (*w == Scr.NoFocusWin) { return C_ROOT; } if (subw != None) { if (win == FW_W_PARENT(t)) { *w = subw; } } if (*w == Scr.Root) { return C_ROOT; } context = frame_window_id_to_context(t, *w, &Button); return context; } /* Drops all expose events for the given window from the input queue and merges * the expose rectangles into a single big one (*e). */ void flush_accumulate_expose(Window w, XEvent *e) { FWeedIfWindowEvents(dpy, w, _pred_weed_accumulate_expose, (XPointer)e); return; } /* * * Removes all expose events from the queue and does the necessary redraws * */ void handle_all_expose(void) { void *saved_event; saved_event = fev_save_event(); FPending(dpy); FWeedIfEvents(dpy, _pred_weed_handle_expose, NULL); fev_restore_event(saved_event); return; } /* CoerceEnterNotifyOnCurrentWindow() * Pretends to get a HandleEnterNotify on the window that the pointer * currently is in so that the focus gets set correctly from the beginning. * Note that this presently only works if the current window is not * click_to_focus; I think that that behaviour is correct and desirable. * --11/08/97 gjb */ void CoerceEnterNotifyOnCurrentWindow(void) { Window child; Window root; Bool f; evh_args_t ea; exec_context_changes_t ecc; XEvent e; FvwmWindow *fw; f = FQueryPointer( dpy, Scr.Root, &root, &child, &e.xcrossing.x_root, &e.xcrossing.y_root, &e.xcrossing.x, &e.xcrossing.y, &JunkMask); if (f == False || child == None) { return; } e.xcrossing.type = EnterNotify; e.xcrossing.window = child; e.xcrossing.subwindow = None; e.xcrossing.mode = NotifyNormal; e.xcrossing.detail = NotifyAncestor; e.xcrossing.same_screen = True; if (XFindContext(dpy, child, FvwmContext, (caddr_t *)&fw) == XCNOENT) { fw = NULL; } else { XTranslateCoordinates( dpy, Scr.Root, child, e.xcrossing.x_root, e.xcrossing.y_root, &JunkX, &JunkY, &child); if (child == FW_W_PARENT(fw)) { child = FW_W(fw); } if (child != None) { e.xany.window = child; } } e.xcrossing.focus = (fw == get_focus_window()) ? True : False; ecc.type = EXCT_NULL; ecc.x.etrigger = &e; ea.exc = exc_create_context(&ecc, ECC_TYPE | ECC_ETRIGGER); HandleEnterNotify(&ea); exc_destroy_context(ea.exc); return; } /* This function discards all queued up events selected by the mask. */ int discard_typed_events(int num_event_types, int *event_types) { _weed_event_type_arg args; int count; int i; XSync(dpy, 0); assert(num_event_types <= MAX_NUM_WEED_EVENT_TYPES); args.num_event_types = num_event_types; for (i = 0; i < num_event_types; i++) { args.event_types[i] = event_types[i]; } count = FWeedIfEvents(dpy, _pred_weed_event_type, (XPointer)&args); return count; } /* Similar function for certain types of PropertyNotify. */ int flush_property_notify_stop_at_event_type( Atom atom, Window w, char do_stop_at_event_type, int stop_at_event_type) { flush_property_notify_args args; XSync(dpy, 0); args.w = w; args.atom = atom; args.event_type = PropertyNotify; args.stop_at_event_type = stop_at_event_type; args.do_stop_at_event_type = do_stop_at_event_type; FWeedIfEvents( dpy, _pred_flush_property_notify_weed, (XPointer)&args); return 0; } /* Wait for all mouse buttons to be released * This can ease some confusion on the part of the user sometimes * * Discard superflous button events during this wait period. */ void WaitForButtonsUp(Bool do_handle_expose) { unsigned int mask; unsigned int bmask; long evmask = ButtonPressMask|ButtonReleaseMask|ButtonMotionMask| KeyPressMask|KeyReleaseMask; int count; int use_wait_cursor; XEvent e; if (FQueryPointer(dpy, Scr.Root, &JunkRoot, &JunkChild, &JunkX, &JunkY, &JunkX, &JunkY, &mask) == False) { /* pointer is on a different screen - that's okay here */ } mask &= DEFAULT_ALL_BUTTONS_MASK; if (mask == 0) { return; } if (do_handle_expose) { evmask |= ExposureMask; } GrabEm(None, GRAB_NORMAL); for (count = 0, use_wait_cursor = 0; mask != 0; count++) { /* handle expose events */ XAllowEvents(dpy, SyncPointer, CurrentTime); if (FCheckMaskEvent(dpy, evmask, &e)) { switch (e.type) { case ButtonRelease: if (e.xbutton.button <= NUMBER_OF_MOUSE_BUTTONS) { bmask = (Button1Mask << (e.xbutton.button - 1)); mask = e.xbutton.state & ~bmask; } break; case Expose: dispatch_event(&e); break; default: break; } } else { if (FQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, &JunkX, &JunkY, &JunkX, &JunkY, &mask) == False) { /* pointer is on a different screen - that's * okay here */ } mask &= DEFAULT_ALL_BUTTONS_MASK; usleep(1); } if (use_wait_cursor == 0 && count == 20) { GrabEm(CRS_WAIT, GRAB_NORMAL); use_wait_cursor = 1; } } UngrabEm(GRAB_NORMAL); if (use_wait_cursor) { UngrabEm(GRAB_NORMAL); XFlush(dpy); } return; } void sync_server(int toggle) { static Bool synced = False; if (toggle == -1) { toggle = (synced == False); } if (toggle == 1) { synced = True; } else { synced = False; } XSynchronize(dpy, synced); XFlush(dpy); return; } Bool is_resizing_event_pending(FvwmWindow *fw) { XEvent e; check_if_event_args args; args.w = FW_W(fw); args.do_return_true = False; args.do_return_true_cr = False; args.cr_value_mask = 0; args.ret_does_match = False; args.ret_type = 0; FCheckIfEvent(dpy, &e, test_resizing_event, (XPointer)&args); return args.ret_does_match; } /* ---------------------------- builtin commands --------------------------- */ void CMD_XSynchronize(F_CMD_ARGS) { int toggle; toggle = ParseToggleArgument(action, NULL, -1, 0); sync_server(toggle); return; } void CMD_XSync(F_CMD_ARGS) { XSync(dpy, 0); return; } fvwm-2.7.0/fvwm/session.h0000644000175000017500000000357714147024700012246 00000000000000/* -*-c-*- */ /* Description: * exports from session.c shall go into this file * * Created: * 4 April 1999 - Steve Robbins */ #ifndef SESSION_H #define SESSION_H /* ** Load and save the 'global', ie not window-related, state of fvwm ** into a file. */ void LoadGlobalState(char *filename); /* ** Turn off SM for new windows */ void DisableRestoringState(void); /* ** Load and save window states. */ void LoadWindowStates (char *filename); /* ** Save state to the named file, and if running under SM, ** make the SM properly restart fvwm. */ void RestartInSession (char *filename, Bool isNative, Bool doPreserveState); /* ** Fill in the FvwmWindow struct with information saved from ** the last session. This expects the fields ** t->w ** t->name ** t->class ** t->tmpflags.NameChanged ** to have meaningful values. The shade and maximize flags are set ** if the window should start out as shaded or maximized, respecively. ** The dimensions returned in x, y, w, h should be used when the ** window is to be maximized. */ typedef struct { int shade_dir; unsigned do_shade : 1; unsigned used_title_dir_for_shading : 1; unsigned do_max : 1; } mwtsm_state_args; Bool MatchWinToSM( FvwmWindow *ewin, mwtsm_state_args *ret_state_args, initial_window_options_t *win_opts); void SetClientID(char *client_id); /* ** Try to open a connection to the session manager. If non-NULL, ** reuse the client_id. */ void SessionInit(void); /* ** The file number of the session manager connection or -1 ** if no session manager was found. */ extern int sm_fd; /* ** Process messages received from the session manager. Call this ** from the main event loop when there is input waiting sm_fd. */ void ProcessICEMsgs(void); /* * Fvwm Function implementation */ Bool quitSession(void); Bool saveSession(void); Bool saveQuitSession(void); #endif fvwm-2.7.0/fvwm/conditional.h0000644000175000017500000000173014147024676013067 00000000000000/* -*-c-*- */ #ifndef CONDITIONAL_H #define CONDITIONAL_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ /* Condition matching routines */ char *CreateFlagString(char *string, char **restptr); void DefaultConditionMask(WindowConditionMask *mask); void CreateConditionMask(char *flags, WindowConditionMask *mask); void FreeConditionMask(WindowConditionMask *mask); Bool MatchesConditionMask(FvwmWindow *fw, WindowConditionMask *mask); #endif /* CONDITIONAL_H */ fvwm-2.7.0/fvwm/icccm2.h0000644000175000017500000000040114147024676011716 00000000000000/* -*-c-*- */ #ifndef ICCCM2_h #define ICCCM2_h extern void SetupICCCM2(Bool replace_wm); extern void CloseICCCM2(void); extern void icccm2_handle_selection_request(const XEvent *e); extern void icccm2_handle_selection_clear(void); #endif /* ICCCM2_H */ fvwm-2.7.0/fvwm/misc.c0000644000175000017500000003207014147024700011477 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include #include "libs/ftime.h" #ifdef FVWM_DEBUG_TIME #include #endif #include "libs/Parse.h" #include "libs/Target.h" #include "fvwm.h" #include "externs.h" #include "execcontext.h" #include "cursor.h" #include "misc.h" #include "screen.h" #include "module_interface.h" #include "events.h" #include "eventmask.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ #define GRAB_EVMASK (ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | \ PointerMotionMask | EnterWindowMask | LeaveWindowMask) /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ static int grab_count[GRAB_MAXVAL] = { 1, 1, 0, 0, 0, 0, 0 }; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ /* * Change the appearance of the grabbed cursor. */ static void change_grab_cursor(int cursor) { if (cursor != None) { XChangeActivePointerGrab( dpy, GRAB_EVMASK, Scr.FvwmCursors[cursor], CurrentTime); } return; } /* ---------------------------- interface functions ------------------------ */ int GetTwoArguments( char *action, int *val1, int *val2, int *val1_unit, int *val2_unit) { *val1_unit = Scr.MyDisplayWidth; *val2_unit = Scr.MyDisplayHeight; return GetTwoPercentArguments(action, val1, val2, val1_unit, val2_unit); } /* * Grab the pointer. * grab_context: GRAB_NORMAL, GRAB_BUSY, GRAB_MENU, GRAB_BUSYMENU, * GRAB_PASSIVE. * GRAB_STARTUP and GRAB_NONE are used at startup but are not made * to be grab_context. * GRAB_PASSIVE does not actually grab, but only delays the following ungrab * until the GRAB_PASSIVE is released too. */ #define DEBUG_GRAB 0 #if DEBUG_GRAB void print_grab_stats(char *text) { int i; fprintf(stderr,"grab_stats (%s):", text); for (i = 0; i < GRAB_MAXVAL; i++) { fprintf(stderr," %d", grab_count[i]); } fprintf(stderr," \n"); return; } #endif Bool GrabEm(int cursor, int grab_context) { int i = 0; int val = 0; int rep; Window grab_win; extern Window PressedW; if (grab_context <= GRAB_STARTUP || grab_context >= GRAB_MAXVAL) { fvwm_msg( ERR, "GrabEm", "Bug: Called with illegal context %d", grab_context); return False; } if (grab_context == GRAB_PASSIVE) { grab_count[grab_context]++; grab_count[GRAB_ALL]++; return True; } if (grab_count[GRAB_ALL] > grab_count[GRAB_PASSIVE]) { /* already grabbed, just change the grab cursor */ if (grab_context == GRAB_FREEZE_CURSOR) { if (XGrabPointer( dpy, (PressedW != None) ? PressedW : Scr.NoFocusWin, True, GRAB_EVMASK, GrabModeAsync, GrabModeAsync, None, Scr.FvwmCursors[CRS_DEFAULT], CurrentTime) != GrabSuccess) { return False; } return True; } grab_count[grab_context]++; grab_count[GRAB_ALL]++; if (grab_context != GRAB_BUSY || grab_count[GRAB_STARTUP] == 0) { change_grab_cursor(cursor); } return True; } /* move the keyboard focus prior to grabbing the pointer to * eliminate the enterNotify and exitNotify events that go * to the windows. But GRAB_BUSY. */ switch (grab_context) { case GRAB_BUSY: if ( Scr.Hilite != NULL ) { grab_win = FW_W(Scr.Hilite); } else { grab_win = Scr.Root; } /* retry to grab the busy cursor only once */ rep = 2; break; case GRAB_PASSIVE: /* cannot happen */ return False; case GRAB_FREEZE_CURSOR: grab_win = (PressedW != None) ? PressedW : Scr.NoFocusWin; rep = 2; break; default: grab_win = Scr.Root; rep = NUMBER_OF_GRAB_ATTEMPTS; break; } XFlush(dpy); while (i < rep && (val = XGrabPointer( dpy, grab_win, True, GRAB_EVMASK, GrabModeAsync, GrabModeAsync, None, (grab_context == GRAB_FREEZE_CURSOR) ? None : Scr.FvwmCursors[cursor], CurrentTime) != GrabSuccess)) { switch (val) { case GrabInvalidTime: case GrabNotViewable: /* give up */ i += rep; break; case GrabSuccess: break; case AlreadyGrabbed: case GrabFrozen: default: /* If you go too fast, other windows may not get a * chance to release any grab that they have. */ i++; if (grab_context == GRAB_FREEZE_CURSOR) { break; } if (i < rep) { usleep(1000 * TIME_BETWEEN_GRAB_ATTEMPTS); } break; } } XFlush(dpy); /* If we fall out of the loop without grabbing the pointer, its * time to give up */ if (val != GrabSuccess) { return False; } grab_count[grab_context]++; grab_count[GRAB_ALL]++; #if DEBUG_GRAB print_grab_stats("grabbed"); #endif return True; } /* * * UnGrab the pointer * */ Bool UngrabEm(int ungrab_context) { if (ungrab_context <= GRAB_ALL || ungrab_context >= GRAB_MAXVAL) { fvwm_msg( ERR, "UngrabEm", "Bug: Called with illegal context %d", ungrab_context); return False; } if (grab_count[ungrab_context] == 0 || grab_count[GRAB_ALL] == 0) { /* context is not grabbed */ return False; } XFlush(dpy); grab_count[ungrab_context]--; grab_count[GRAB_ALL]--; if (grab_count[GRAB_ALL] > 0) { int new_cursor = None; /* there are still grabs left - switch grab cursor */ switch (ungrab_context) { case GRAB_NORMAL: case GRAB_BUSY: case GRAB_MENU: if (grab_count[GRAB_BUSYMENU] > 0) { new_cursor = CRS_WAIT; } else if (grab_count[GRAB_BUSY] > 0) { new_cursor = CRS_WAIT; } else if (grab_count[GRAB_MENU] > 0) { new_cursor = CRS_MENU; } else { new_cursor = None; } break; case GRAB_BUSYMENU: /* switch back from busymenu cursor to normal menu * cursor */ new_cursor = CRS_MENU; break; default: new_cursor = None; break; } if (grab_count[GRAB_ALL] > grab_count[GRAB_PASSIVE]) { #if DEBUG_GRAB print_grab_stats("-restore"); #endif change_grab_cursor(new_cursor); } } else { #if DEBUG_GRAB print_grab_stats("-ungrab"); #endif XUngrabPointer(dpy, CurrentTime); } XFlush(dpy); return True; } #ifndef fvwm_msg /* Some ports (i.e. VMS) define their own version */ /* ** fvwm_msg: used to send output from fvwm to files and or stderr/stdout ** ** type -> DBG == Debug, ERR == Error, INFO == Information, WARN == Warning, ** OLD == Command or option deprecated ** id -> name of function, or other identifier */ static char *fvwm_msg_strings[] = { "<> ", "", "", "<> ", "<> ", "<> " }; void fvwm_msg(fvwm_msg_t type, char *id, char *msg, ...) { va_list args; char *mfmt; char fvwm_id[20]; char time_str[40] = "\0"; #ifdef FVWM_DEBUG_TIME clock_t time_val, time_taken; static clock_t start_time = 0; static clock_t prev_time = 0; struct tms not_used_tms; time_t mytime; struct tm *t_ptr; #endif #ifdef FVWM_DEBUG_TIME time(&mytime); t_ptr = localtime(&mytime); if (start_time == 0) { /* get clock ticks */ prev_time = start_time = (unsigned int)times(¬_used_tms); } time_val = (unsigned int)times(¬_used_tms); /* get clock ticks */ time_taken = time_val - prev_time; prev_time = time_val; sprintf(time_str, "%.2d:%.2d:%.2d%7ld ", t_ptr->tm_hour, t_ptr->tm_min, t_ptr->tm_sec, time_taken); #endif strcpy(fvwm_id, "fvwm"); if (Scr.NumberOfScreens > 1) { sprintf(&fvwm_id[strlen(fvwm_id)], ".%d", (int)Scr.screen); } if (type == ERR) { /* I hate to use a fixed length but this will do for now */ char tmp[2 * MAX_TOKEN_LENGTH]; sprintf(tmp, "[%s][%s]: %s", fvwm_id, id, fvwm_msg_strings[(int)type]); va_start(args, msg); vsprintf(tmp + strlen(tmp), msg, args); va_end(args); tmp[strlen(tmp) + 1] = '\0'; tmp[strlen(tmp)] = '\n'; if (strlen(tmp) >= MAX_MODULE_INPUT_TEXT_LEN) { sprintf(tmp + MAX_MODULE_INPUT_TEXT_LEN - 5, "...\n"); } fprintf(stderr, "%s", tmp); BroadcastName(M_ERROR, 0, 0, 0, tmp); } else { fprintf(stderr, "%s[%s][%s]: %s", time_str, fvwm_id, id, fvwm_msg_strings[(int)type]); va_start(args, msg); { int n; n = asprintf(&mfmt, "%s\n", msg); (void)n; } vfprintf(stderr, mfmt, args); va_end(args); free(mfmt); } } /* fvwm_msg */ #endif void fvwm_msg_report_app(void) { fprintf( stderr, " If you are having a problem with the application, send a" " bug report\n" " with this message included to the application owner.\n" " There is no need to notify fvwm-workers@fvwm.org.\n"); return; } void fvwm_msg_report_app_and_workers(void) { fprintf( stderr, " If you are having a problem with the application, send" " a bug report with\n" " this message included to the application owner and" " notify\n" " fvwm-workers@fvwm.org.\n"); return; } /* Store the last item that was added with '+' */ void set_last_added_item(last_added_item_t type, void *item) { Scr.last_added_item.type = type; Scr.last_added_item.item = item; return; } /* some fancy font handling stuff */ void NewFontAndColor(FlocaleFont *flf, Pixel color, Pixel backcolor) { Globalgcm = GCForeground | GCBackground; if (flf->font) { Globalgcm |= GCFont; Globalgcv.font = flf->font->fid; } Globalgcv.foreground = color; Globalgcv.background = backcolor; XChangeGC(dpy,Scr.TitleGC,Globalgcm,&Globalgcv); return; } /* * * For menus, move, and resize operations, we can effect keyboard * shortcuts by warping the pointer. * */ void Keyboard_shortcuts( XEvent *ev, FvwmWindow *fw, int *x_defect, int *y_defect, int ReturnEvent) { int x_move_size = 0; int y_move_size = 0; if (fw) { x_move_size = fw->hints.width_inc; y_move_size = fw->hints.height_inc; } fvwmlib_keyboard_shortcuts( dpy, Scr.screen, ev, x_move_size, y_move_size, x_defect, y_defect, ReturnEvent); return; } /* * * Check if the given FvwmWindow structure still points to a valid window. * */ Bool check_if_fvwm_window_exists(FvwmWindow *fw) { FvwmWindow *t; for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) { if (t == fw) return True; } return False; } /* rounds x down to the next multiple of m */ int truncate_to_multiple (int x, int m) { return (x < 0) ? (m * (((x + 1) / m) - 1)) : (m * (x / m)); } Bool IsRectangleOnThisPage(const rectangle *rec, int desk) { return (desk == Scr.CurrentDesk && rec->x + (signed int)rec->width > 0 && (rec->x < 0 || rec->x < Scr.MyDisplayWidth) && rec->y + (signed int)rec->height > 0 && (rec->y < 0 || rec->y < Scr.MyDisplayHeight)) ? True : False; } /* returns the FvwmWindow that contains the pointer or NULL if none */ FvwmWindow *get_pointer_fvwm_window(void) { int x,y; Window win; Window ancestor; FvwmWindow *t; if (FQueryPointer( dpy, Scr.Root, &JunkRoot, &win, &JunkX, &JunkY, &x, &y, &JunkMask) == False) { /* pointer is on a different screen */ return NULL; } for (t = NULL ; win != Scr.Root && win != None; win = ancestor) { Window root = None; Window *children; unsigned int nchildren; if (XFindContext(dpy, win, FvwmContext, (caddr_t *) &t) != XCNOENT) { /* found a matching window context */ return t; } /* get next higher ancestor window */ children = NULL; if (!XQueryTree( dpy, win, &root, &ancestor, &children, &nchildren)) { return NULL; } if (children) { XFree(children); } } return t; } /* Returns the current X server time */ Time get_server_time(void) { XEvent xev; XSetWindowAttributes attr; /* add PropChange to NoFocusWin events */ attr.event_mask = PropertyChangeMask; XChangeWindowAttributes (dpy, Scr.NoFocusWin, CWEventMask, &attr); /* provoke an event */ XChangeProperty( dpy, Scr.NoFocusWin, XA_WM_CLASS, XA_STRING, 8, PropModeAppend, NULL, 0); FWindowEvent(dpy, Scr.NoFocusWin, PropertyChangeMask, &xev); attr.event_mask = XEVMASK_NOFOCUSW; XChangeWindowAttributes(dpy, Scr.NoFocusWin, CWEventMask, &attr); return xev.xproperty.time; } void print_g(char *text, rectangle *g) { fprintf(stderr,"%s: ", (text != NULL) ? text : ""); if (g == NULL) { fprintf(stderr, "(null)\n"); return; } fprintf(stderr,"%4d %4d %4dx%4d (%4d - %4d, %4d - %4d)\n", g->x, g->y, g->width, g->height, g->x, g->x + g->width, g->y, g->y + g->height); return; } fvwm-2.7.0/fvwm/update.c0000644000175000017500000004451514147024700012035 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include "libs/fvwmlib.h" #include "libs/charmap.h" #include "libs/wcontext.h" #include "libs/Grab.h" #include "fvwm.h" #include "externs.h" #include "execcontext.h" #include "cursor.h" #include "bindings.h" #include "misc.h" #include "screen.h" #include "update.h" #include "style.h" #include "builtins.h" #include "borders.h" #include "frame.h" #include "ewmh.h" #include "icons.h" #include "geometry.h" #include "move_resize.h" #include "add_window.h" #include "module_interface.h" #include "focus.h" #include "stack.h" #include "icons.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ /* ---------------------------- interface functions ------------------------ */ static void init_style( FvwmWindow *old_t, FvwmWindow *t, window_style *pstyle, short *pbuttons) { /* copy the window structure because we still need some old values. */ memcpy(old_t, t, sizeof(FvwmWindow)); /* determine level of decoration */ setup_style_and_decor(t, pstyle, pbuttons); /* restore some old values */ IS_STICKY_ACROSS_PAGES(t) = IS_STICKY_ACROSS_PAGES(old_t); IS_STICKY_ACROSS_DESKS(t) = IS_STICKY_ACROSS_DESKS(old_t); GET_USER_STATES(t) = GET_USER_STATES(old_t); return; } static void apply_window_updates( FvwmWindow *t, update_win *flags, window_style *pstyle, FvwmWindow *focus_w) { FvwmWindow old_t; short buttons; Bool is_style_initialised = False; rectangle frame_g; const exec_context_t *exc; exec_context_changes_t ecc; frame_g.x = t->g.frame.x; frame_g.y = t->g.frame.y; frame_g.width = t->g.frame.width; frame_g.height = t->g.frame.height; /* TA: 2010-07-28: Conditionally update window states if they're * present -- i.e., we're preserving states set via Windowstyle. */ CLEAR_USER_STATES(t, S_USER_STATES(SCM(*pstyle))); SET_USER_STATES(t, S_USER_STATES(SCF(*pstyle))); if (flags->do_setup_focus_policy) { setup_focus_policy(t); if (t == focus_w && !fpol_query_allow_user_focus(&FW_FOCUS_POLICY(t))) { focus_w = NULL; if (Scr.Hilite == t) { Scr.Hilite = NULL; } flags->do_redraw_decoration = True; } } if (flags->do_update_window_grabs) { focus_grab_buttons(t); } if (IS_TRANSIENT(t) && flags->do_redecorate_transient) { flags->do_redecorate = True; flags->do_update_window_font = True; } /* * is_sticky * is_icon_sticky * * These are a bit complicated because they can move windows to a * different page or desk. */ ecc.type = EXCT_NULL; ecc.w.fw = t; ecc.w.w = FW_W_FRAME(t); ecc.w.wcontext = C_FRAME; exc = exc_create_context( &ecc, ECC_TYPE | ECC_FW | ECC_W | ECC_WCONTEXT); if (flags->do_update_stick_icon && IS_ICONIFIED(t) && !(IS_STICKY_ACROSS_PAGES(t) || IS_STICKY_ACROSS_DESKS(t))) { if (IS_ICON_STICKY_ACROSS_PAGES(pstyle) || IS_ICON_STICKY_ACROSS_DESKS(pstyle)) { /* stick and unstick the window to force the icon on * the current page */ handle_stick( NULL, exc, "", S_IS_STICKY_ACROSS_PAGES(SCF(*pstyle)), S_IS_STICKY_ACROSS_DESKS(SCF(*pstyle)), 1, 1); handle_stick(NULL, exc, "", 0, 0, 1, 0); } flags->do_update_icon_title = True; } else if (flags->do_update_stick) { handle_stick( NULL, exc, "", S_IS_STICKY_ACROSS_PAGES(SCF(*pstyle)), S_IS_STICKY_ACROSS_DESKS(SCF(*pstyle)), 0, 0); } exc_destroy_context(exc); if (FMiniIconsSupported && flags->do_update_mini_icon) { if (!HAS_EWMH_MINI_ICON(t) || DO_EWMH_MINI_ICON_OVERRIDE(t)) { change_mini_icon(t, pstyle); } else { if (EWMH_SetIconFromWMIcon(t, NULL, 0, True)) { SET_HAS_EWMH_MINI_ICON(t, True); } else { /* "should" not happen */ SET_HAS_EWMH_MINI_ICON(t, False); change_mini_icon(t, pstyle); } } } if (flags->do_update_visible_window_name) { setup_visible_names(t, 4); BroadcastName(M_VISIBLE_NAME,FW_W(t),FW_W_FRAME(t), (unsigned long)t,t->visible_name); EWMH_SetVisibleName(t, False); } if (flags->do_update_visible_icon_name) { setup_visible_names(t, 8); BroadcastName(MX_VISIBLE_ICON_NAME,FW_W(t),FW_W_FRAME(t), (unsigned long)t,t->visible_icon_name); EWMH_SetVisibleName(t, True); } if (flags->do_update_window_font || flags->do_update_window_font_height) { if (!is_style_initialised) { init_style(&old_t, t, pstyle, &buttons); is_style_initialised = True; } setup_window_font(t, pstyle, flags->do_update_window_font); flags->do_redecorate = True; } if (flags->do_update_title_text_dir) { flags->do_redecorate = True; } if (flags->do_redecorate || flags->do_update_title_dir) { size_borders b_old; size_borders b_new; int dw = 0; int dh = 0; rectangle naked_g; rectangle *new_g; if (flags->do_redecorate) { if (!is_style_initialised) { init_style(&old_t, t, pstyle, &buttons); is_style_initialised = True; } /* redecorate */ change_auxiliary_windows(t, buttons); /* calculate the new offsets */ /* naked_g: geometry without decor */ gravity_get_naked_geometry( old_t.hints.win_gravity, &old_t, &naked_g, &t->g.normal); /* gravity without decor */ gravity_translate_to_northwest_geometry_no_bw( old_t.hints.win_gravity, &old_t, &naked_g, &naked_g); /* set g.normal with the decor */ gravity_add_decoration( old_t.hints.win_gravity, t, &t->g.normal, &naked_g); } if (flags->do_update_title_dir) { /* new border sizes */ get_window_borders(t, &b_old); SET_TITLE_DIR(t, S_TITLE_DIR(SCF(*pstyle))); setup_title_geometry(t, pstyle); get_window_borders(t, &b_new); /* resizing */ dw = b_new.total_size.width - b_old.total_size.width; dh = b_new.total_size.height - b_old.total_size.height; gravity_resize( t->hints.win_gravity, &t->g.normal, dw, dh); gravity_constrain_size( t->hints.win_gravity, t, &t->g.normal, 0); } if (IS_MAXIMIZED(t)) { if (flags->do_redecorate) { int off_x = old_t.g.normal.x - old_t.g.max.x; int off_y = old_t.g.normal.y - old_t.g.max.y; int new_off_x; int new_off_y; /* maximized windows are always considered to * have NorthWestGravity */ gravity_get_naked_geometry( NorthWestGravity, &old_t, &naked_g, &t->g.max); gravity_translate_to_northwest_geometry_no_bw( NorthWestGravity, &old_t, &naked_g, &naked_g); gravity_add_decoration( NorthWestGravity, t, &t->g.max, &naked_g); /* prevent random paging when unmaximizing * after e.g. the border width has changed */ new_off_x = t->g.normal.x - t->g.max.x; new_off_y = t->g.normal.y - t->g.max.y; t->g.max_offset.x += new_off_x - off_x; t->g.max_offset.y += new_off_y - off_y; } if (flags->do_update_title_dir) { frame_g = t->g.max; gravity_resize( t->hints.win_gravity, &t->g.max, dw, dh); gravity_constrain_size( t->hints.win_gravity, t, &t->g.max, CS_UPDATE_MAX_DEFECT); } new_g = &t->g.max; } else { new_g = &t->g.normal; } if (IS_SHADED(t)) { get_unshaded_geometry(t, new_g); if (USED_TITLE_DIR_FOR_SHADING(t)) { SET_SHADED_DIR(t, GET_TITLE_DIR(t)); } get_shaded_geometry(t, &frame_g, new_g); } else { get_relative_geometry(&frame_g, new_g); } flags->do_setup_frame = True; flags->do_redraw_decoration = True; } if (flags->do_update_rotated_title) { if (t->title_text_rotation != ROTATION_0) { flags->do_setup_frame = True; flags->do_redraw_decoration = True; } } if (flags->do_resize_window) { rectangle old_g; setup_frame_size_limits(t, pstyle); old_g = frame_g; frame_g = t->g.normal; gravity_constrain_size(t->hints.win_gravity, t, &frame_g, 0); t->g.normal = frame_g; if (IS_MAXIMIZED(t)) { frame_g = t->g.max; gravity_constrain_size( t->hints.win_gravity, t, &frame_g, CS_UPDATE_MAX_DEFECT); t->g.max = frame_g; } frame_g = old_g; gravity_constrain_size( t->hints.win_gravity, t, &frame_g, 0); flags->do_setup_frame = True; flags->do_redraw_decoration = True; } if (flags->do_setup_frame) { FvwmWindow *tmp; setup_title_geometry(t, pstyle); /* frame_force_setup_window needs to know if the window is * hilighted */ tmp = get_focus_window(); set_focus_window(focus_w); frame_force_setup_window( t, frame_g.x, frame_g.y, frame_g.width, frame_g.height, True); set_focus_window(tmp); EWMH_SetFrameStrut(t); } if (flags->do_update_window_color) { if (t != focus_w) { flags->do_redraw_decoration = True; } update_window_color_style(t, pstyle); if (t != Scr.Hilite) { flags->do_broadcast_focus = True; } } if (flags->do_update_window_color_hi) { if (t == focus_w) { flags->do_redraw_decoration = True; } update_window_color_hi_style(t, pstyle); flags->do_broadcast_focus = True; if (t == Scr.Hilite) { flags->do_broadcast_focus = True; } } if (flags->do_update_icon_title_cs_hi) { if (t == focus_w && IS_ICONIFIED(t)) { flags->do_redraw_icon = True; } update_icon_title_cs_hi_style(t, pstyle); } if (flags->do_update_icon_title_cs) { if (t != focus_w && IS_ICONIFIED(t)) { flags->do_redraw_icon = True; } update_icon_title_cs_style(t, pstyle); } if (flags->do_update_icon_background_cs) { int old_cs = t->icon_background_cs; update_icon_background_cs_style(t, pstyle); if ((old_cs < 0 && t->icon_background_cs >= 0) || (old_cs >= 0 && t->icon_background_cs < 0)) { flags->do_update_icon = True; } else { flags->do_redraw_icon = True; } } if (flags->do_update_icon_size_limits) { setup_icon_size_limits(t, pstyle); flags->do_update_icon = True; } if (flags->do_update_icon_font) { if (!is_style_initialised) { init_style(&old_t, t, pstyle, &buttons); is_style_initialised = True; } setup_icon_font(t, pstyle, flags->do_update_icon_font); flags->do_update_icon_title = True; } if (flags->do_update_icon_boxes) { change_icon_boxes(t, pstyle); } if (flags->do_update_icon) { setup_icon_background_parameters(t, pstyle); setup_icon_title_parameters(t, pstyle); change_icon(t, pstyle); flags->do_update_icon_placement = True; flags->do_update_icon_title = False; flags->do_redraw_icon = False; flags->do_update_ewmh_icon = True; } if (flags->do_redraw_icon) { /* should not test if the window is iconified */ DrawIconWindow(t, True, True, False, True, NULL);; flags->do_redraw_decoration = False; flags->do_update_icon_title = False; } if (flags->do_update_icon_title) { RedoIconName(t); } if (flags->do_update_icon_placement) { if (IS_ICONIFIED(t)) { initial_window_options_t win_opts; memset(&win_opts, 0, sizeof(win_opts)); SET_ICONIFIED(t, 0); Iconify(t, &win_opts); flags->do_redraw_decoration = False; } } if (flags->do_redraw_decoration) { FvwmWindow *tmp; /* frame_redraw_decorations needs to know if the window is * hilighted */ tmp = get_focus_window(); set_focus_window(focus_w); if (IS_ICONIFIED(t)) { DrawIconWindow(t, True, True, False, False, NULL); } else { border_redraw_decorations(t); } set_focus_window(tmp); } if (flags->do_update_frame_attributes) { setup_frame_attributes(t, pstyle); } if (flags->do_update_ewmh_state_hints) { EWMH_SetWMState(t, False); } if (flags->do_update_modules_flags) { BroadcastConfig(M_CONFIGURE_WINDOW,t); } if (flags->do_update_ewmh_mini_icon || flags->do_update_ewmh_icon) { EWMH_DoUpdateWmIcon( t, flags->do_update_ewmh_mini_icon, flags->do_update_ewmh_icon); } if (flags->do_update_placement_penalty) { setup_placement_penalty(t, pstyle); } if (flags->do_update_working_area) { EWMH_UpdateWorkArea(); } if (flags->do_update_ewmh_stacking_hints) { if (DO_EWMH_USE_STACKING_HINTS(t)) { if (t->ewmh_hint_layer > 0 && t->layer != t->ewmh_hint_layer) { t->ewmh_normal_layer = t->layer; new_layer(t, t->ewmh_hint_layer); } } else { if (t->ewmh_hint_layer > 0 && t->ewmh_normal_layer) { if (t->ewmh_normal_layer) { new_layer(t, t->ewmh_normal_layer); } else { new_layer(t, Scr.DefaultLayer); } } } } if (flags->do_update_ewmh_allowed_actions) { EWMH_SetAllowedActions(t); } if (flags->do_broadcast_focus) { if (Scr.Hilite != NULL && t == Scr.Hilite) { BroadcastPacket( M_FOCUS_CHANGE, 5, (long)FW_W(Scr.Hilite), (long)FW_W_FRAME(Scr.Hilite), (long)0, (long)Scr.Hilite->hicolors.fore, (long)Scr.Hilite->hicolors.back); } } if (flags->do_refresh) { if (!IS_ICONIFIED(t)) { refresh_window(FW_W_FRAME(t), False); } } setup_numeric_vals(t, pstyle); if (flags->do_update_cr_motion_method) { switch (SCR_MOTION_METHOD(&pstyle->flags)) { case WS_CR_MOTION_METHOD_AUTO: if (WAS_CR_MOTION_METHOD_DETECTED(t)) { /* method was already detected, keep it */ break; } /* fall through */ case WS_CR_MOTION_METHOD_USE_GRAV: case WS_CR_MOTION_METHOD_STATIC_GRAV: SET_CR_MOTION_METHOD( t, SCR_MOTION_METHOD(&pstyle->flags)); SET_CR_MOTION_METHOD_DETECTED(t, 0); break; } } if (flags->do_update_layer) { int layer = get_layer(t); if (SUSE_LAYER(&pstyle->flags)) { /* use layer from style */ layer = SGET_LAYER(*pstyle); } /* Set the layer, and modify the stack ring. */ new_layer(t, layer); } return; } /* ---------------------------- builtin commands --------------------------- */ /* takes only care of destroying windows that have to go away. */ void destroy_scheduled_windows(void) { flist *t; Bool do_need_ungrab = False; if (Scr.flags.is_executing_complex_function || Scr.flags.is_executing_menu_function || !Scr.flags.is_window_scheduled_for_destroy) { return; } /* Grab the server during the style update! */ if (GrabEm(CRS_WAIT, GRAB_BUSY)) { do_need_ungrab = True; } MyXGrabServer(dpy); Scr.flags.is_window_scheduled_for_destroy = 0; /* need to destroy one or more windows before looking at the window * list */ for (t = Scr.FWScheduledForDestroy; t != NULL; t = t->next) { destroy_window(t->object); } Scr.FWScheduledForDestroy = flist_free_list(Scr.FWScheduledForDestroy); MyXUngrabServer(dpy); if (do_need_ungrab) { UngrabEm(GRAB_BUSY); } return; } /* similar to the flush_window_updates() function, but does only the updates * for a single window whose decor has been changed. */ void apply_decor_change(FvwmWindow *fw) { window_style style; update_win flags; lookup_style(fw, &style); memset(&flags, 0, sizeof(flags)); flags.do_redecorate = True; flags.do_update_window_font_height = True; apply_window_updates(fw, &flags, &style, get_focus_window()); return; } /* Check and apply new style to each window if the style has changed. */ void flush_window_updates(void) { FvwmWindow *t; window_style style; FvwmWindow *focus_fw; Bool do_need_ungrab = False; update_win flags; /* Grab the server during the style update! */ if (GrabEm(CRS_WAIT, GRAB_BUSY)) { do_need_ungrab = True; } MyXGrabServer(dpy); /* This is necessary in case the focus policy changes. With * ClickToFocus some buttons have to be grabbed/ungrabbed. */ focus_fw = get_focus_window(); DeleteFocus(False); /* Apply the new default font and colours first */ if (Scr.flags.has_default_color_changed || Scr.flags.has_default_font_changed) { ApplyDefaultFontAndColors(); } /* update styles for all windows */ for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) { memset(&flags, 0, sizeof(update_win)); check_window_style_change(t, &flags, &style); if (Scr.flags.has_xinerama_state_changed) { flags.do_update_icon_boxes = True; flags.do_update_icon_placement = True; } if (Scr.flags.has_nr_buttons_changed) { flags.do_redecorate = True; } /* TODO: this is not optimised for minimal redrawing yet*/ if (t->decor->flags.has_changed) { flags.do_redecorate = True; flags.do_update_window_font_height = True; } if (Scr.flags.has_default_font_changed && !HAS_ICON_FONT(t)) { flags.do_update_icon_font = True; } if (Scr.flags.has_default_font_changed && !HAS_WINDOW_FONT(t)) { flags.do_update_window_font = True; } if (t->decor->flags.has_title_height_changed) { flags.do_update_window_font_height = True; } if (Scr.flags.has_mouse_binding_changed) { flags.do_update_window_grabs = True; } /* now apply the changes */ apply_window_updates(t, &flags, &style, focus_fw); } /* restore the focus; also handles the case that the previously focused * window is now NeverFocus */ if (focus_fw) { SetFocusWindow(focus_fw, False, FOCUS_SET_FORCE); if (Scr.flags.has_mouse_binding_changed) { focus_grab_buttons(focus_fw); } } else { DeleteFocus(True); } /* finally clean up the change flags */ reset_style_changes(); reset_decor_changes(); Scr.flags.do_need_window_update = 0; Scr.flags.has_default_font_changed = 0; Scr.flags.has_default_color_changed = 0; Scr.flags.has_mouse_binding_changed = 0; Scr.flags.has_nr_buttons_changed = 0; Scr.flags.has_xinerama_state_changed = 0; MyXUngrabServer(dpy); if (do_need_ungrab) { UngrabEm(GRAB_BUSY); } return; } void CMD_UpdateStyles(F_CMD_ARGS) { if (Scr.flags.do_need_window_update) { flush_window_updates(); } return; } fvwm-2.7.0/fvwm/menugeometry.c0000644000175000017500000000626614147024700013274 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include "fvwm.h" #include "externs.h" #include "execcontext.h" #include "misc.h" #include "screen.h" #include "menudim.h" #include "menuroot.h" #include "menuparameters.h" #include "menugeometry.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ /* ---------------------------- interface functions ------------------------ */ Bool menu_get_geometry( struct MenuRoot *mr, Window *root_return, int *x_return, int *y_return, int *width_return, int *height_return, int *border_width_return, int *depth_return) { Status rc; Bool brc; int root_x; int root_y; rc = XGetGeometry( dpy, MR_WINDOW(mr), root_return, x_return, y_return, (unsigned int*)width_return, (unsigned int*)height_return, (unsigned int*)border_width_return, (unsigned int*)depth_return); if (rc == 0) { return False; } if (!MR_IS_TEAR_OFF_MENU(mr)) { return True; } brc = XTranslateCoordinates( dpy, MR_WINDOW(mr), Scr.Root, *x_return, *y_return, &root_x, &root_y, &JunkChild); if (brc == True) { *x_return = root_x; *y_return = root_y; } else { *x_return = 0; *y_return = 0; } return brc; } Bool menu_get_outer_geometry( struct MenuRoot *mr, struct MenuParameters *pmp, Window *root_return, int *x_return, int *y_return, int *width_return, int *height_return, int *border_width_return, int *depth_return) { if (MR_IS_TEAR_OFF_MENU(mr)) { return XGetGeometry( dpy, FW_W_FRAME(pmp->tear_off_root_menu_window), root_return,x_return,y_return, (unsigned int*)width_return, (unsigned int*)height_return, (unsigned int*)border_width_return, (unsigned int*)depth_return); } else { return menu_get_geometry( mr,root_return,x_return,y_return, width_return, height_return, border_width_return, depth_return); } } fvwm-2.7.0/fvwm/Makefile.in0000644000175000017500000010630414324315775012463 00000000000000# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 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@ bin_PROGRAMS = fvwm$(EXEEXT) subdir = fvwm ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.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)$(bindir)" "$(DESTDIR)$(configdir)" PROGRAMS = $(bin_PROGRAMS) am_fvwm_OBJECTS = menus.$(OBJEXT) style.$(OBJEXT) borders.$(OBJEXT) \ events.$(OBJEXT) move_resize.$(OBJEXT) builtins.$(OBJEXT) \ add_window.$(OBJEXT) icons.$(OBJEXT) fvwm.$(OBJEXT) \ frame.$(OBJEXT) placement.$(OBJEXT) virtual.$(OBJEXT) \ menustyle.$(OBJEXT) conditional.$(OBJEXT) ewmh.$(OBJEXT) \ stack.$(OBJEXT) session.$(OBJEXT) colorset.$(OBJEXT) \ functions.$(OBJEXT) ewmh_events.$(OBJEXT) geometry.$(OBJEXT) \ module_list.$(OBJEXT) focus.$(OBJEXT) windowlist.$(OBJEXT) \ functable.$(OBJEXT) menuitem.$(OBJEXT) expand.$(OBJEXT) \ module_interface.$(OBJEXT) menubindings.$(OBJEXT) \ decorations.$(OBJEXT) ewmh_icons.$(OBJEXT) update.$(OBJEXT) \ bindings.$(OBJEXT) misc.$(OBJEXT) cursor.$(OBJEXT) \ colormaps.$(OBJEXT) modconf.$(OBJEXT) ewmh_conf.$(OBJEXT) \ read.$(OBJEXT) schedule.$(OBJEXT) menucmd.$(OBJEXT) \ ewmh_names.$(OBJEXT) icccm2.$(OBJEXT) windowshade.$(OBJEXT) \ focus_policy.$(OBJEXT) repeat.$(OBJEXT) execcontext.$(OBJEXT) \ menugeometry.$(OBJEXT) menudim.$(OBJEXT) condrc.$(OBJEXT) \ infostore.$(OBJEXT) fvwm_OBJECTS = $(am_fvwm_OBJECTS) fvwm_LDADD = $(LDADD) am__DEPENDENCIES_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)/etc/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/add_window.Po \ ./$(DEPDIR)/bindings.Po ./$(DEPDIR)/borders.Po \ ./$(DEPDIR)/builtins.Po ./$(DEPDIR)/colormaps.Po \ ./$(DEPDIR)/colorset.Po ./$(DEPDIR)/conditional.Po \ ./$(DEPDIR)/condrc.Po ./$(DEPDIR)/cursor.Po \ ./$(DEPDIR)/decorations.Po ./$(DEPDIR)/events.Po \ ./$(DEPDIR)/ewmh.Po ./$(DEPDIR)/ewmh_conf.Po \ ./$(DEPDIR)/ewmh_events.Po ./$(DEPDIR)/ewmh_icons.Po \ ./$(DEPDIR)/ewmh_names.Po ./$(DEPDIR)/execcontext.Po \ ./$(DEPDIR)/expand.Po ./$(DEPDIR)/focus.Po \ ./$(DEPDIR)/focus_policy.Po ./$(DEPDIR)/frame.Po \ ./$(DEPDIR)/functable.Po ./$(DEPDIR)/functions.Po \ ./$(DEPDIR)/fvwm.Po ./$(DEPDIR)/geometry.Po \ ./$(DEPDIR)/icccm2.Po ./$(DEPDIR)/icons.Po \ ./$(DEPDIR)/infostore.Po ./$(DEPDIR)/menubindings.Po \ ./$(DEPDIR)/menucmd.Po ./$(DEPDIR)/menudim.Po \ ./$(DEPDIR)/menugeometry.Po ./$(DEPDIR)/menuitem.Po \ ./$(DEPDIR)/menus.Po ./$(DEPDIR)/menustyle.Po \ ./$(DEPDIR)/misc.Po ./$(DEPDIR)/modconf.Po \ ./$(DEPDIR)/module_interface.Po ./$(DEPDIR)/module_list.Po \ ./$(DEPDIR)/move_resize.Po ./$(DEPDIR)/placement.Po \ ./$(DEPDIR)/read.Po ./$(DEPDIR)/repeat.Po \ ./$(DEPDIR)/schedule.Po ./$(DEPDIR)/session.Po \ ./$(DEPDIR)/stack.Po ./$(DEPDIR)/style.Po \ ./$(DEPDIR)/update.Po ./$(DEPDIR)/virtual.Po \ ./$(DEPDIR)/windowlist.Po ./$(DEPDIR)/windowshade.Po am__mv = mv -f 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 = $(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 = $(fvwm_SOURCES) DIST_SOURCES = $(fvwm_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; }; \ } DATA = $(config_DATA) 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)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/etc/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALL_DOMAINS = @ALL_DOMAINS@ ALL_LINGUAS = @ALL_LINGUAS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR_FLAGS = @AR_FLAGS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ Bidi_CFLAGS = @Bidi_CFLAGS@ Bidi_LIBS = @Bidi_LIBS@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DOC_COMMANDS = @DOC_COMMANDS@ DOC_COMMANDS_HTML = @DOC_COMMANDS_HTML@ DOC_COMMANDS_XML = @DOC_COMMANDS_XML@ DOC_COMMANDS_XML_PATH = @DOC_COMMANDS_XML_PATH@ DOC_MODULES = @DOC_MODULES@ DOC_MODULES_HTML = @DOC_MODULES_HTML@ DOC_SECTIONS = @DOC_SECTIONS@ DOC_SECTIONS_XML = @DOC_SECTIONS_XML@ DOC_SECTIONS_XML_PATH = @DOC_SECTIONS_XML_PATH@ DUMMYPOFILES = @DUMMYPOFILES@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FC_CFLAGS = @FC_CFLAGS@ FC_CONFIG = @FC_CONFIG@ FC_LIBS = @FC_LIBS@ FRIBIDI_CONFIG = @FRIBIDI_CONFIG@ FVWMALTFTP = @FVWMALTFTP@ FVWMALTFTPDIR = @FVWMALTFTPDIR@ FVWMFTP = @FVWMFTP@ FVWMFTPDIR = @FVWMFTPDIR@ FVWMHOMEPAGE = @FVWMHOMEPAGE@ FVWMLIST = @FVWMLIST@ FVWMNAMELONG = @FVWMNAMELONG@ FVWMSCRIPT_DOMAIN = @FVWMSCRIPT_DOMAIN@ FVWMTASKBAR_DOMAIN = @FVWMTASKBAR_DOMAIN@ FVWMWORKERSLIST = @FVWMWORKERSLIST@ FVWMWORKERSLISTLONG = @FVWMWORKERSLISTLONG@ FVWM_CONFDIR = @FVWM_CONFDIR@ FVWM_CPP = @FVWM_CPP@ FVWM_DATADIR = @FVWM_DATADIR@ FVWM_DOCDIR = @FVWM_DOCDIR@ FVWM_DOMAIN = @FVWM_DOMAIN@ FVWM_IMAGEPATH = @FVWM_IMAGEPATH@ FVWM_MODULEDIR = @FVWM_MODULEDIR@ FVWM_PERLLIB = @FVWM_PERLLIB@ FVWM_PERLLIBDIR = @FVWM_PERLLIBDIR@ GDK_IMLIB_CFLAGS = @GDK_IMLIB_CFLAGS@ GDK_IMLIB_LIBS = @GDK_IMLIB_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ IMLIBCONF = @IMLIBCONF@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INST_LINGUAS = @INST_LINGUAS@ ISRELEASED = @ISRELEASED@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOCALEDIR = @LOCALEDIR@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANPAGE_PREAMBLE = @MANPAGE_PREAMBLE@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ MSGUNIQ = @MSGUNIQ@ OBJEXT = @OBJEXT@ 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@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PYTHON = @PYTHON@ RANLIB = @RANLIB@ RELDATELONG = @RELDATELONG@ RELDATENUM = @RELDATENUM@ RELDATESHORT = @RELDATESHORT@ REQUIRED_PERL_VERSION = @REQUIRED_PERL_VERSION@ REQUIRED_PYTHON_VERSION = @REQUIRED_PYTHON_VERSION@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ UPDATEPOFILES = @UPDATEPOFILES@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VERSIONINFO = @VERSIONINFO@ XFT_CFLAGS = @XFT_CFLAGS@ XFT_CONFIG = @XFT_CONFIG@ XFT_LIBS = @XFT_LIBS@ XGETTEXT = @XGETTEXT@ XMKMF = @XMKMF@ XSLTPROC = @XSLTPROC@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Xcursor_CFLAGS = @Xcursor_CFLAGS@ Xcursor_LIBS = @Xcursor_LIBS@ Xft_CFLAGS = @Xft_CFLAGS@ Xft_LIBS = @Xft_LIBS@ Xinerama_CFLAGS = @Xinerama_CFLAGS@ Xinerama_LIBS = @Xinerama_LIBS@ Xrender_CFLAGS = @Xrender_CFLAGS@ Xrender_LIBS = @Xrender_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ iconv_CFLAGS = @iconv_CFLAGS@ iconv_LIBS = @iconv_LIBS@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intl_CFLAGS = @intl_CFLAGS@ intl_LIBS = @intl_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ png_CFLAGS = @png_CFLAGS@ png_LIBS = @png_LIBS@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ readline_CFLAGS = @readline_CFLAGS@ readline_LIBS = @readline_LIBS@ rplay_CFLAGS = @rplay_CFLAGS@ rplay_LIBS = @rplay_LIBS@ rsvg_CFLAGS = @rsvg_CFLAGS@ rsvg_LIBS = @rsvg_LIBS@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ stroke_CFLAGS = @stroke_CFLAGS@ stroke_LIBS = @stroke_LIBS@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ with_bidi = @with_bidi@ with_gdkimlib = @with_gdkimlib@ with_gettext = @with_gettext@ with_iconv = @with_iconv@ with_perllib = @with_perllib@ with_png = @with_png@ with_readline = @with_readline@ with_rplay = @with_rplay@ with_rsvg = @with_rsvg@ with_shape = @with_shape@ with_shm = @with_shm@ with_sm = @with_sm@ with_stroke = @with_stroke@ with_xcursor = @with_xcursor@ with_xft = @with_xft@ with_xinerama = @with_xinerama@ with_xpm = @with_xpm@ with_xrender = @with_xrender@ xpm_CFLAGS = @xpm_CFLAGS@ xpm_LIBS = @xpm_LIBS@ configdir = @FVWM_DATADIR@ EXTRA_DIST = $(config_DATA) config_DATA = ConfigFvwmDefaults fvwm_SOURCES = \ add_window.h bindings.h borders.h builtins.h colormaps.h colorset.h \ commands.h conditional.h condrc.h cursor.h decorations.h events.h \ eventhandler.h eventmask.h ewmh.h ewmh_intern.h expand.h externs.h \ focus.h functable.h functions.h fvwm.h geometry.h focus_policy.h \ icccm2.h icons.h menubindings.h menudim.h menugeometry.h \ menuitem.h menuroot.h menuparameters.h menus.h menustyle.h misc.h \ modconf.h module_interface.h module_list.h move_resize.h \ placement.h read.h repeat.h execcontext.h schedule.h screen.h \ session.h stack.h style.h update.h virtual.h window_flags.h frame.h \ infostore.h \ \ menus.c style.c borders.c events.c move_resize.c builtins.c \ add_window.c icons.c fvwm.c frame.c placement.c virtual.c \ menustyle.c conditional.c ewmh.c stack.c session.c colorset.c \ functions.c ewmh_events.c geometry.c module_list.c focus.c \ windowlist.c functable.c menuitem.c expand.c module_interface.c \ menubindings.c decorations.c ewmh_icons.c update.c bindings.c misc.c \ cursor.c colormaps.c modconf.c ewmh_conf.c read.c schedule.c \ menucmd.c ewmh_names.c icccm2.c windowshade.c focus_policy.c repeat.c \ execcontext.c menugeometry.c menudim.c condrc.c infostore.c fvwm_DEPENDENCIES = $(top_builddir)/libs/libfvwm.a LDADD = \ -L$(top_builddir)/libs -lfvwm $(Xft_LIBS) $(X_LIBS) $(xpm_LIBS) \ $(stroke_LIBS) $(X_PRE_LIBS) $(Xinerama_LIBS) -lXext -lX11 \ $(X_EXTRA_LIBS) -lm $(iconv_LIBS) $(Xrender_LIBS) $(Xcursor_LIBS) \ $(Bidi_LIBS) $(png_LIBS) $(rsvg_LIBS) $(intl_LIBS) AM_CPPFLAGS = \ -I$(top_srcdir) $(stroke_CFLAGS) $(Xft_CFLAGS) \ $(xpm_CFLAGS) $(X_CFLAGS) $(iconv_CFLAGS) $(Xrender_CFLAGS) \ $(Bidi_CFLAGS) $(png_CFLAGS) $(rsvg_CFLAGS) $(intl_CFLAGS) AM_CFLAGS = \ -DFVWM_MODULEDIR=\"$(FVWM_MODULEDIR)\" \ -DFVWM_DATADIR=\"$(FVWM_DATADIR)\" \ -DFVWM_CONFDIR=\"$(FVWM_CONFDIR)\" \ -DFVWM_COLORSET_PRIVATE=1 \ -DLOCALEDIR=\"$(LOCALEDIR)\" fvwm_name = `echo "fvwm" | "$(SED)" -e "${transform}"` fvwm2_name = `echo "fvwm2" | "$(SED)" -e "${transform}"` all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: $(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) --foreign fvwm/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign fvwm/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: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ ; 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) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || 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)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) fvwm$(EXEEXT): $(fvwm_OBJECTS) $(fvwm_DEPENDENCIES) $(EXTRA_fvwm_DEPENDENCIES) @rm -f fvwm$(EXEEXT) $(AM_V_CCLD)$(LINK) $(fvwm_OBJECTS) $(fvwm_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/add_window.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bindings.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/borders.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/builtins.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/colormaps.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/colorset.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conditional.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/condrc.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cursor.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decorations.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/events.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ewmh.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ewmh_conf.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ewmh_events.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ewmh_icons.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ewmh_names.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/execcontext.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/expand.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/focus.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/focus_policy.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/frame.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/functable.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/functions.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fvwm.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/geometry.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icccm2.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icons.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/infostore.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/menubindings.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/menucmd.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/menudim.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/menugeometry.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/menuitem.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/menus.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/menustyle.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/modconf.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/module_interface.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/module_list.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/move_resize.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/placement.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/read.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/repeat.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/schedule.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/session.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stack.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/style.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/update.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/virtual.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/windowlist.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/windowshade.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)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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) '$<'` install-configDATA: $(config_DATA) @$(NORMAL_INSTALL) @list='$(config_DATA)'; test -n "$(configdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(configdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(configdir)" || 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)$(configdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(configdir)" || exit $$?; \ done uninstall-configDATA: @$(NORMAL_UNINSTALL) @list='$(config_DATA)'; test -n "$(configdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(configdir)'; $(am__uninstall_files_from_dir) 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 $(PROGRAMS) $(DATA) installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(configdir)"; 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-binPROGRAMS clean-generic mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/add_window.Po -rm -f ./$(DEPDIR)/bindings.Po -rm -f ./$(DEPDIR)/borders.Po -rm -f ./$(DEPDIR)/builtins.Po -rm -f ./$(DEPDIR)/colormaps.Po -rm -f ./$(DEPDIR)/colorset.Po -rm -f ./$(DEPDIR)/conditional.Po -rm -f ./$(DEPDIR)/condrc.Po -rm -f ./$(DEPDIR)/cursor.Po -rm -f ./$(DEPDIR)/decorations.Po -rm -f ./$(DEPDIR)/events.Po -rm -f ./$(DEPDIR)/ewmh.Po -rm -f ./$(DEPDIR)/ewmh_conf.Po -rm -f ./$(DEPDIR)/ewmh_events.Po -rm -f ./$(DEPDIR)/ewmh_icons.Po -rm -f ./$(DEPDIR)/ewmh_names.Po -rm -f ./$(DEPDIR)/execcontext.Po -rm -f ./$(DEPDIR)/expand.Po -rm -f ./$(DEPDIR)/focus.Po -rm -f ./$(DEPDIR)/focus_policy.Po -rm -f ./$(DEPDIR)/frame.Po -rm -f ./$(DEPDIR)/functable.Po -rm -f ./$(DEPDIR)/functions.Po -rm -f ./$(DEPDIR)/fvwm.Po -rm -f ./$(DEPDIR)/geometry.Po -rm -f ./$(DEPDIR)/icccm2.Po -rm -f ./$(DEPDIR)/icons.Po -rm -f ./$(DEPDIR)/infostore.Po -rm -f ./$(DEPDIR)/menubindings.Po -rm -f ./$(DEPDIR)/menucmd.Po -rm -f ./$(DEPDIR)/menudim.Po -rm -f ./$(DEPDIR)/menugeometry.Po -rm -f ./$(DEPDIR)/menuitem.Po -rm -f ./$(DEPDIR)/menus.Po -rm -f ./$(DEPDIR)/menustyle.Po -rm -f ./$(DEPDIR)/misc.Po -rm -f ./$(DEPDIR)/modconf.Po -rm -f ./$(DEPDIR)/module_interface.Po -rm -f ./$(DEPDIR)/module_list.Po -rm -f ./$(DEPDIR)/move_resize.Po -rm -f ./$(DEPDIR)/placement.Po -rm -f ./$(DEPDIR)/read.Po -rm -f ./$(DEPDIR)/repeat.Po -rm -f ./$(DEPDIR)/schedule.Po -rm -f ./$(DEPDIR)/session.Po -rm -f ./$(DEPDIR)/stack.Po -rm -f ./$(DEPDIR)/style.Po -rm -f ./$(DEPDIR)/update.Po -rm -f ./$(DEPDIR)/virtual.Po -rm -f ./$(DEPDIR)/windowlist.Po -rm -f ./$(DEPDIR)/windowshade.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-configDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-exec-local 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)/add_window.Po -rm -f ./$(DEPDIR)/bindings.Po -rm -f ./$(DEPDIR)/borders.Po -rm -f ./$(DEPDIR)/builtins.Po -rm -f ./$(DEPDIR)/colormaps.Po -rm -f ./$(DEPDIR)/colorset.Po -rm -f ./$(DEPDIR)/conditional.Po -rm -f ./$(DEPDIR)/condrc.Po -rm -f ./$(DEPDIR)/cursor.Po -rm -f ./$(DEPDIR)/decorations.Po -rm -f ./$(DEPDIR)/events.Po -rm -f ./$(DEPDIR)/ewmh.Po -rm -f ./$(DEPDIR)/ewmh_conf.Po -rm -f ./$(DEPDIR)/ewmh_events.Po -rm -f ./$(DEPDIR)/ewmh_icons.Po -rm -f ./$(DEPDIR)/ewmh_names.Po -rm -f ./$(DEPDIR)/execcontext.Po -rm -f ./$(DEPDIR)/expand.Po -rm -f ./$(DEPDIR)/focus.Po -rm -f ./$(DEPDIR)/focus_policy.Po -rm -f ./$(DEPDIR)/frame.Po -rm -f ./$(DEPDIR)/functable.Po -rm -f ./$(DEPDIR)/functions.Po -rm -f ./$(DEPDIR)/fvwm.Po -rm -f ./$(DEPDIR)/geometry.Po -rm -f ./$(DEPDIR)/icccm2.Po -rm -f ./$(DEPDIR)/icons.Po -rm -f ./$(DEPDIR)/infostore.Po -rm -f ./$(DEPDIR)/menubindings.Po -rm -f ./$(DEPDIR)/menucmd.Po -rm -f ./$(DEPDIR)/menudim.Po -rm -f ./$(DEPDIR)/menugeometry.Po -rm -f ./$(DEPDIR)/menuitem.Po -rm -f ./$(DEPDIR)/menus.Po -rm -f ./$(DEPDIR)/menustyle.Po -rm -f ./$(DEPDIR)/misc.Po -rm -f ./$(DEPDIR)/modconf.Po -rm -f ./$(DEPDIR)/module_interface.Po -rm -f ./$(DEPDIR)/module_list.Po -rm -f ./$(DEPDIR)/move_resize.Po -rm -f ./$(DEPDIR)/placement.Po -rm -f ./$(DEPDIR)/read.Po -rm -f ./$(DEPDIR)/repeat.Po -rm -f ./$(DEPDIR)/schedule.Po -rm -f ./$(DEPDIR)/session.Po -rm -f ./$(DEPDIR)/stack.Po -rm -f ./$(DEPDIR)/style.Po -rm -f ./$(DEPDIR)/update.Po -rm -f ./$(DEPDIR)/virtual.Po -rm -f ./$(DEPDIR)/windowlist.Po -rm -f ./$(DEPDIR)/windowshade.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-configDATA \ uninstall-local .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-binPROGRAMS clean-generic cscopelist-am ctags ctags-am \ distclean distclean-compile distclean-generic distclean-tags \ distdir dvi dvi-am html html-am info info-am install \ install-am install-binPROGRAMS install-configDATA install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-exec-local 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 pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-configDATA uninstall-local .PRECIOUS: Makefile install-exec-local: @rm -f $(DESTDIR)$(bindir)/$(fvwm2_name)$(EXEEXT) @$(LN_S) $(fvwm_name)$(EXEEXT) \ $(DESTDIR)$(bindir)/$(fvwm2_name)$(EXEEXT) || \ echo "Minor warning: $(bindir)/fvwm2 symlink was not created" uninstall-local: @rm -f $(DESTDIR)$(bindir)/$(fvwm2_name)$(EXEEXT) # 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: fvwm-2.7.0/fvwm/colormaps.h0000644000175000017500000000701314147024700012547 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ #ifndef COLORMAP_H #define COLORMAP_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ /* colormap notify event handler * * This procedure handles both a client changing its own colormap, and * a client explicitly installing its colormap itself (only the window * manager should do that, so we must set it correctly). */ void colormap_handle_colormap_notify(const evh_args_t *ea); /* Re-Install the active colormap */ void ReInstallActiveColormap(void); /* install the colormaps for one fvwm window * * Inputs: * type - type of event that caused the installation * tmp - for a subset of event types, the address of the * window structure, whose colormaps are to be installed. */ void InstallWindowColormaps(const FvwmWindow *tmp); /* Force (un)loads root colormap(s) * * These matching routines provide a mechanism to insure that * the root colormap(s) is installed during operations like * rubber banding that require colors from * that colormap. Calls may be nested arbitrarily deeply, * as long as there is one UninstallRootColormap call per * InstallRootColormap call. * * The final UninstallRootColormap will cause the colormap list * which would otherwise have be loaded to be loaded, unless * Enter or Leave Notify events are queued, indicating some * other colormap list would potentially be loaded anyway. */ void InstallRootColormap(void); /* Unstacks one layer of root colormap pushing * If we peel off the last layer, re-install the application colormap */ void UninstallRootColormap(void); /* Force (un)loads fvwm colormap(s) * * This is used to ensure the fvwm colormap is installed during * menu operations */ void InstallFvwmColormap(void); void UninstallFvwmColormap(void); /* Gets the WM_COLORMAP_WINDOWS property from the window * * This property typically doesn't exist, but a few applications * use it. These seem to occur mostly on SGI machines. */ void FetchWmColormapWindows (FvwmWindow *tmp); /* clasen@mathematik.uni-freiburg.de - 03/01/1999 - new * boolean for handling of client-side InstallColormap * as described in the ICCCM 2.0 */ void set_client_controls_colormaps(Bool flag); /* Looks through the window list for any matching COLORMAP_WINDOWS * windows and installs the colormap if one exists. */ void EnterSubWindowColormap(Window win); void LeaveSubWindowColormap(Window win); #endif /* COLORMAP_H */ fvwm-2.7.0/fvwm/icons.h0000644000175000017500000000157714147024676011710 00000000000000/* -*-c-*- */ #ifndef _ICONS_ #define _ICONS_ #ifdef NO_ICONS #define ICON_HEIGHT(t) 1 #else #define ICON_HEIGHT(t) \ ((t)->icon_font->height + 2*abs((t)->icon_title_relief)) #endif int get_visible_icon_window_count(FvwmWindow *fw); void clear_icon(FvwmWindow *fw); void setup_icon_title_size(FvwmWindow *fw); void GetIconPicture(FvwmWindow *fw, Bool no_icon_window); void AutoPlaceIcon( FvwmWindow *t, initial_window_options_t *win_opts, Bool do_move_immediately); void ChangeIconPixmap(FvwmWindow *fw); void RedoIconName(FvwmWindow *fw); void DrawIconWindow( FvwmWindow *fw, Bool draw_title, Bool draw_pixmap, Bool focus_change, Bool reset_bg, XEvent *pev); void CreateIconWindow(FvwmWindow *fw, int def_x, int def_y); void Iconify(FvwmWindow *fw, initial_window_options_t *win_opts); void DeIconify(FvwmWindow *); void SetMapStateProp(const FvwmWindow *, int); #endif /* _ICONS_ */ fvwm-2.7.0/fvwm/session.c0000644000175000017500000012431214147024700012230 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* This file is strongly based on the corresponding files from twm and enlightenment. */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #ifdef HAVE_GETPWUID #include #endif #include #include #include #include "libs/fvwmlib.h" #include "libs/FSMlib.h" #include "libs/Strings.h" #include "libs/System.h" #include "fvwm.h" #include "externs.h" #include "execcontext.h" #include "add_window.h" #include "misc.h" #include "screen.h" #include "session.h" #include "module_list.h" #include "module_interface.h" #include "stack.h" #include "icccm2.h" #include "virtual.h" #include "geometry.h" #include "move_resize.h" #include "infostore.h" /* ---------------------------- local definitions -------------------------- */ /*#define FVWM_SM_DEBUG_PROTO*/ /*#define FVWM_SM_DEBUG_WINMATCH*/ #define FVWM_SM_DEBUG_FILES /* ---------------------------- local macros ------------------------------- */ #define xstreq(a,b) ((!a && !b) || (a && b && (strcmp(a,b)==0))) /* ---------------------------- imports ------------------------------------ */ extern Bool Restarting; extern int master_pid; extern char **g_argv; extern int g_argc; /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ typedef struct _match { unsigned long win; char *client_id; char *res_name; char *res_class; char *window_role; char *wm_name; int wm_command_count; char **wm_command; int x, y, w, h, icon_x, icon_y; int x_max, y_max, w_max, h_max; int width_defect_max, height_defect_max; int max_x_offset, max_y_offset; int desktop; int layer; int default_layer; int placed_by_button; int used; int gravity; unsigned long ewmh_hint_desktop; window_flags flags; } Match; /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ static char *previous_sm_client_id = NULL; static char *sm_client_id = NULL; static Bool sent_save_done = 0; static char *real_state_filename = NULL; static Bool going_to_restart = False; static FIceIOErrorHandler prev_handler; static FSmcConn sm_conn = NULL; static int num_match = 0; static Match *matches = NULL; static Bool does_file_version_match = False; static Bool do_preserve_state = True; /* ---------------------------- exported variables (globals) --------------- */ int sm_fd = -1; /* ---------------------------- local functions ---------------------------- */ static char *duplicate(const char *s) { int l; char *r; if (!s) return NULL; l = strlen(s); r = (char *) safemalloc (sizeof(char)*(l+1)); strncpy(r, s, l+1); return r; } static char *get_version_string(void) { /* migo (14-Mar-2001): it is better to manually update a version string * in the stable branch, otherwise saving sessions becomes useless */ return CatString3(VERSION, ", ", __DATE__); /* return "2.6-0"; */ } static char *unspace_string(const char *str) { static const char *spaces = " \t\n"; char *tr_str = CatString2(str, NULL); int i; if (!tr_str) { return NULL; } for (i = 0; i < strlen(spaces); i++) { char *ptr = tr_str; while ((ptr = strchr(ptr, spaces[i])) != NULL) { *(ptr++) = '_'; } } return tr_str; } /* * It is a bit ugly to have a separate file format for * config files and session save files. The proper way * to do this may be to extend the config file format * to allow the specification of everything we need * to save here. Then the option "-restore xyz" could * be replaced by "-f xyz". */ static int SaveGlobalState(FILE *f) { fprintf(f, "[GLOBAL]\n"); fprintf(f, " [DESKTOP] %i\n", Scr.CurrentDesk); fprintf(f, " [VIEWPORT] %i %i %i %i\n", Scr.Vx, Scr.Vy, Scr.VxMax, Scr.VyMax); fprintf(f, " [SCROLL] %i %i %i %i %i\n", Scr.EdgeScrollX, Scr.EdgeScrollY, Scr.ScrollDelay, !!(Scr.flags.do_edge_wrap_x), !!(Scr.flags.do_edge_wrap_y)); fprintf(f, " [MISC] %i %i %i\n", Scr.ClickTime, Scr.ColormapFocus, Scr.ColorLimit); fprintf( f, " [STYLE] %i %i\n", Scr.gs.do_emulate_mwm, Scr.gs.do_emulate_win); if (get_metainfo_length() > 0) { MetaInfo *mi = get_metainfo(), *mi_i; fprintf(f, " [INFOSTORE]\n"); for (mi_i = mi; mi_i; mi_i = mi_i->next) { fprintf(f, " [KEY] %s\n", mi_i->key); fprintf(f, " [VALUE] %s\n", mi_i->value); } } return 1; } static void set_real_state_filename(char *filename) { if (!SessionSupport) { return; } if (real_state_filename) { free(real_state_filename); } real_state_filename = safestrdup(filename); return; } static char *get_unique_state_filename(void) { const char *path = getenv("SM_SAVE_DIR"); char *filename; int fd; if (!SessionSupport) { return NULL; } if (!path) { path = getenv ("HOME"); } #ifdef HAVE_GETPWUID if (!path) { struct passwd *pwd; pwd = getpwuid(getuid()); if (pwd) { path = pwd->pw_dir; } } #endif if (!path) { return NULL; } filename = safestrdup(CatString2(path, "/.fs-XXXXXX")); fd = fvwm_mkstemp(filename); if (fd == -1) { free (filename); filename = NULL; } else { close (fd); } return filename; } static char * GetWindowRole(Window window) { XTextProperty tp; if (XGetTextProperty (dpy, window, &tp, _XA_WM_WINDOW_ROLE)) { if (tp.encoding == XA_STRING && tp.format == 8 && tp.nitems != 0) { return ((char *) tp.value); } } if (XGetTextProperty (dpy, window, &tp, _XA_WINDOW_ROLE)) { if (tp.encoding == XA_STRING && tp.format == 8 && tp.nitems != 0) { return ((char *) tp.value); } } return NULL; } static char * GetClientID(FvwmWindow *fw) { char *client_id = NULL; Window client_leader = None; Window window; XTextProperty tp; Atom actual_type; int actual_format; unsigned long nitems; unsigned long bytes_after; unsigned char *prop = NULL; window = FW_W(fw); if (XGetWindowProperty( dpy, window, _XA_WM_CLIENT_LEADER, 0L, 1L, False, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &prop) == Success) { if (actual_type == XA_WINDOW && actual_format == 32 && nitems == 1 && bytes_after == 0) { client_leader = (Window)(*(long *)prop); } } if (!client_leader && fw->wmhints && (fw->wmhints->flags & WindowGroupHint)) { client_leader = fw->wmhints->window_group; } if (client_leader) { if ( XGetTextProperty( dpy, client_leader, &tp, _XA_SM_CLIENT_ID)) { if (tp.encoding == XA_STRING && tp.format == 8 && tp.nitems != 0) { client_id = (char *) tp.value; } } } if (prop) { XFree (prop); } return client_id; } /* ** Verify the current fvwm version with the version that stroed the state file. ** No state will be restored if versions don't match. */ static Bool VerifyVersionInfo(char *filename) { FILE *f; char s[4096], s1[4096]; if (!filename || !*filename) { return False; } if ((f = fopen(filename, "r")) == NULL) { return False; } while (fgets(s, sizeof(s), f)) { sscanf(s, "%4000s", s1); if (!strcmp(s1, "[FVWM_VERSION]")) { char *current_v = get_version_string(); sscanf(s, "%*s %[^\n]", s1); if (strcmp(s1, current_v) == 0) { does_file_version_match = True; } else { fvwm_msg( ERR, "VerifyVersionInfo", "State file version (%s) does not" " match the current version (%s), " "state file is ignored.", s1, current_v); break; } } } fclose(f); return does_file_version_match; } static int SaveVersionInfo(FILE *f) { fprintf(f, "[FVWM_VERSION] %s\n", get_version_string()); return 1; } static int SaveWindowStates(FILE *f) { char *client_id; char *window_role; char **wm_command; int wm_command_count; FvwmWindow *ewin; rectangle save_g; rectangle ig; int i; int layer; for (ewin = get_next_window_in_stack_ring(&Scr.FvwmRoot); ewin != &Scr.FvwmRoot; ewin = get_next_window_in_stack_ring(ewin)) { Bool is_icon_sticky_across_pages; if (!XGetGeometry( dpy, FW_W(ewin), &JunkRoot, &JunkX, &JunkY, (unsigned int*)&JunkWidth, (unsigned int*)&JunkHeight, (unsigned int*)&JunkBW, (unsigned int*)&JunkDepth)) { /* Don't save the state of windows that already died * (i.e. modules)! */ continue; } is_icon_sticky_across_pages = is_window_sticky_across_pages(ewin); wm_command = NULL; wm_command_count = 0; client_id = GetClientID(ewin); if (!client_id) { /* no client id, some session manager do not manage * such client ... this can cause problem */ if (XGetCommand( dpy, FW_W(ewin), &wm_command, &wm_command_count) && wm_command && wm_command_count > 0) { /* ok */ } else { /* No client id and no WM_COMMAND, the client * cannot be managed by the sessiom manager * skip it! */ /* TA: 20110611 - But actually, this breaks * those applications which don't set the * WM_COMMAND XAtom anymore. The ICCCM * deprecated this at version 2.0 -- and its * lack of existence here shouldn't be a * problem. Let newer session managers handle * the error if it even matters. */ if (!Restarting) { if (wm_command) { XFreeStringList(wm_command); wm_command = NULL; } /* TA: 20110611 - But see above. We * no longer skip clients who don't * set this legacy field. */ /* continue; */ } } } fprintf(f, "[CLIENT] %lx\n", FW_W(ewin)); if (client_id) { fprintf(f, " [CLIENT_ID] %s\n", client_id); XFree(client_id); } window_role = GetWindowRole(FW_W(ewin)); if (window_role) { fprintf(f, " [WINDOW_ROLE] %s\n", window_role); XFree(window_role); } if (client_id && window_role) { /* we have enough information */ } else { if (ewin->class.res_class) { fprintf(f, " [RES_NAME] %s\n", ewin->class.res_name); } if (ewin->class.res_name) { fprintf(f, " [RES_CLASS] %s\n", ewin->class.res_class); } if (ewin->name.name) { fprintf(f, " [WM_NAME] %s\n", ewin->name.name); } if (wm_command && wm_command_count > 0) { fprintf(f, " [WM_COMMAND] %i", wm_command_count); for (i = 0; i < wm_command_count; i++) { fprintf(f, " %s", unspace_string(wm_command[i])); } fprintf(f, "\n"); } } /* !window_role */ if (wm_command) { XFreeStringList(wm_command); wm_command = NULL; } gravity_get_naked_geometry( ewin->hints.win_gravity, ewin, &save_g, &ewin->g.normal); if (IS_STICKY_ACROSS_PAGES(ewin)) { save_g.x -= Scr.Vx; save_g.y -= Scr.Vy; } get_visible_icon_geometry(ewin, &ig); fprintf( f, " [GEOMETRY] %i %i %i %i %i %i %i %i %i %i %i %i" " %i %i %i\n", save_g.x, save_g.y, save_g.width, save_g.height, ewin->g.max.x, ewin->g.max.y, ewin->g.max.width, ewin->g.max.height, ewin->g.max_defect.width, ewin->g.max_defect.height, ig.x + ((!is_icon_sticky_across_pages) ? Scr.Vx : 0), ig.y + ((!is_icon_sticky_across_pages) ? Scr.Vy : 0), ewin->hints.win_gravity, ewin->g.max_offset.x, ewin->g.max_offset.y); fprintf(f, " [DESK] %i\n", ewin->Desk); /* set the layer to the default layer if the layer has been * set by an ewmh hint */ layer = get_layer(ewin); if (layer == ewin->ewmh_hint_layer && layer > 0) { layer = Scr.DefaultLayer; } fprintf(f, " [LAYER] %i %i\n", layer, ewin->default_layer); fprintf(f, " [PLACED_BY_BUTTON] %i\n", ewin->placed_by_button); fprintf(f, " [EWMH_DESKTOP] %lu\n", ewin->ewmh_hint_desktop); fprintf(f, " [FLAGS] "); for (i = 0; i < sizeof(window_flags); i++) { fprintf(f, "%02x ", (int)(((unsigned char *)&(ewin->flags))[i])); } fprintf(f, "\n"); } return 1; } /* This complicated logic is from twm, where it is explained */ static Bool matchWin(FvwmWindow *w, Match *m) { char *client_id = NULL; char *window_role = NULL; char **wm_command = NULL; int wm_command_count = 0, i; int found; found = 0; client_id = GetClientID(w); if (Restarting) { if (FW_W(w) == m->win) { found = 1; } } else if (xstreq(client_id, m->client_id)) { /* client_id's match */ window_role = GetWindowRole(FW_W(w)); if (client_id && (window_role || m->window_role)) { /* We have or had a window role, base decision on it */ found = xstreq(window_role, m->window_role); } else if (xstreq(w->class.res_name, m->res_name) && xstreq(w->class.res_class, m->res_class) && (IS_NAME_CHANGED(w) || IS_NAME_CHANGED(m) || xstreq(w->name.name, m->wm_name))) { if (client_id) { /* If we have a client_id, we don't * compare WM_COMMAND, since it will be * different. */ found = 1; } else { /* for non-SM-aware clients we also * compare WM_COMMAND */ if (!XGetCommand( dpy, FW_W(w), &wm_command, &wm_command_count)) { wm_command = NULL; wm_command_count = 0; } if (wm_command_count == m->wm_command_count) { for (i = 0; i < wm_command_count; i++) { if (strcmp(unspace_string( wm_command[i]), m->wm_command[i])!=0) { break; } } if (i == wm_command_count) { /* migo (21/Oct/1999): * on restarts compare * window ids too */ /* But if we restart we only need * to compare window ids * olicha (2005-01-06) */ found = 1; } } /* if (wm_command_count ==... */ } /* else if res_class, res_name and wm_name agree */ } /* else no window roles */ } /* if client_id's agree */ #ifdef FVWM_SM_DEBUG_WINMATCH fprintf(stderr, "\twin(%s, %s, %s, %s, %s,", w->class.res_name, w->class.res_class, w->name.name, (client_id)? client_id:"(null)", (window_role)? window_role:"(null)"); if (wm_command) { for (i = 0; i < wm_command_count; i++) { fprintf(stderr," %s", wm_command[i]); } fprintf(stderr,","); } else { fprintf(stderr," no_wmc,"); } fprintf(stderr," %d)", IS_NAME_CHANGED(w)); fprintf(stderr,"\n[%d]", found); fprintf(stderr, "\tmat(%s, %s, %s, %s, %s,", m->res_name, m->res_class, m->wm_name, (m->client_id)?m->client_id:"(null)", (m->window_role)?m->window_role:"(null)"); if (m->wm_command) { for (i = 0; i < m->wm_command_count; i++) { fprintf(stderr," %s", m->wm_command[i]); } fprintf(stderr,","); } else { fprintf(stderr," no_wmc,"); } fprintf(stderr," %d)\n\n", IS_NAME_CHANGED(m)); #endif if (client_id) { XFree(client_id); } if (window_role) { XFree(window_role); } if (wm_command) { XFreeStringList (wm_command); } return found; } static int save_state_file(char *filename) { FILE *f; int success; if (!filename || !*filename) { return 0; } if ((f = fopen(filename, "w")) == NULL) { return 0; } fprintf(f, "# This file is generated by fvwm." " It stores global and window states.\n"); fprintf(f, "# Normally, you must never delete this file," " it will be auto-deleted.\n\n"); if (SessionSupport && going_to_restart) { fprintf(f, "[REAL_STATE_FILENAME] %s\n", real_state_filename); going_to_restart = False; /* not needed */ } success = do_preserve_state ? SaveVersionInfo(f) && SaveWindowStates(f) && SaveGlobalState(f) : 1; do_preserve_state = True; if (fclose(f) != 0) return 0; #ifdef FVWM_SM_DEBUG_FILES system(CatString3( "mkdir -p /tmp/fs-save; cp ", filename, " /tmp/fs-save")); #endif #if defined(FVWM_SM_DEBUG_PROTO) || defined(FVWM_SM_DEBUG_FILES) fprintf(stderr, "[FVWM_SMDEBUG] Saving %s\n", filename); #endif return success; } static void set_sm_properties(FSmcConn sm_conn, char *filename, char hint) { FSmProp prop1, prop2, prop3, prop4, prop5, prop6, prop7, *props[7]; FSmPropValue prop1val, prop2val, prop3val, prop4val, prop7val; struct passwd *pwd; char *user_id; char screen_num[32]; int numVals, i, priority = 30; Bool is_xsm_detected = False; if (!SessionSupport) { return; } #ifdef FVWM_SM_DEBUG_PROTO fprintf(stderr, "[FVWM_SMDEBUG][set_sm_properties] state filename: %s%s\n", filename ? filename : "(null)", sm_conn ? "" : " - not connected"); #endif if (!sm_conn) { return; } pwd = getpwuid (getuid()); user_id = pwd->pw_name; prop1.name = FSmProgram; prop1.type = FSmARRAY8; prop1.num_vals = 1; prop1.vals = &prop1val; prop1val.value = g_argv[0]; prop1val.length = strlen (g_argv[0]); prop2.name = FSmUserID; prop2.type = FSmARRAY8; prop2.num_vals = 1; prop2.vals = &prop2val; prop2val.value = (FSmPointer) user_id; prop2val.length = strlen (user_id); prop3.name = FSmRestartStyleHint; prop3.type = FSmCARD8; prop3.num_vals = 1; prop3.vals = &prop3val; prop3val.value = (FSmPointer) &hint; prop3val.length = 1; prop4.name = "_GSM_Priority"; prop4.type = FSmCARD8; prop4.num_vals = 1; prop4.vals = &prop4val; prop4val.value = (FSmPointer) &priority; prop4val.length = 1; sprintf(screen_num, "%d", (int)Scr.screen); prop5.name = FSmCloneCommand; prop5.type = FSmLISTofARRAY8; prop5.vals = (FSmPropValue *)malloc((g_argc + 2) * sizeof (FSmPropValue)); numVals = 0; for (i = 0; i < g_argc; i++) { if (strcmp (g_argv[i], "-clientId") == 0 || strcmp (g_argv[i], "-restore") == 0 || strcmp (g_argv[i], "-d") == 0 || (strcmp (g_argv[i], "-s") == 0 && i+1 < g_argc && g_argv[i+1][0] != '-')) { i++; } else if (strcmp (g_argv[i], "-s") != 0) { prop5.vals[numVals].value = (FSmPointer) g_argv[i]; prop5.vals[numVals++].length = strlen (g_argv[i]); } } prop5.vals[numVals].value = (FSmPointer) "-s"; prop5.vals[numVals++].length = 2; prop5.vals[numVals].value = (FSmPointer) screen_num; prop5.vals[numVals++].length = strlen (screen_num); prop5.num_vals = numVals; if (filename) { prop6.name = FSmRestartCommand; prop6.type = FSmLISTofARRAY8; prop6.vals = (FSmPropValue *)malloc( (g_argc + 6) * sizeof (FSmPropValue)); numVals = 0; for (i = 0; i < g_argc; i++) { if (strcmp (g_argv[i], "-clientId") == 0 || strcmp (g_argv[i], "-restore") == 0 || strcmp (g_argv[i], "-d") == 0 || (strcmp (g_argv[i], "-s") == 0 && i+1 < g_argc && g_argv[i+1][0] != '-')) { i++; } else if (strcmp (g_argv[i], "-s") != 0) { prop6.vals[numVals].value = (FSmPointer) g_argv[i]; prop6.vals[numVals++].length = strlen (g_argv[i]); } } prop6.vals[numVals].value = (FSmPointer) "-s"; prop6.vals[numVals++].length = 2; prop6.vals[numVals].value = (FSmPointer) screen_num; prop6.vals[numVals++].length = strlen (screen_num); prop6.vals[numVals].value = (FSmPointer) "-clientId"; prop6.vals[numVals++].length = 9; prop6.vals[numVals].value = (FSmPointer) sm_client_id; prop6.vals[numVals++].length = strlen (sm_client_id); prop6.vals[numVals].value = (FSmPointer) "-restore"; prop6.vals[numVals++].length = 8; prop6.vals[numVals].value = (FSmPointer) filename; prop6.vals[numVals++].length = strlen (filename); prop6.num_vals = numVals; prop7.name = FSmDiscardCommand; is_xsm_detected = StrEquals(getenv("SESSION_MANAGER_NAME"), "xsm"); if (is_xsm_detected) { /* the protocol spec says that the discard command should be LISTofARRAY8 on posix systems, but xsm demands that it be ARRAY8. */ char *discardCommand = alloca( (10 + strlen(filename)) * sizeof(char)); sprintf (discardCommand, "rm -f '%s'", filename); prop7.type = FSmARRAY8; prop7.num_vals = 1; prop7.vals = &prop7val; prop7val.value = (FSmPointer) discardCommand; prop7val.length = strlen (discardCommand); } else { prop7.type = FSmLISTofARRAY8; prop7.num_vals = 3; prop7.vals = (FSmPropValue *) malloc ( 3 * sizeof (FSmPropValue)); prop7.vals[0].value = "rm"; prop7.vals[0].length = 2; prop7.vals[1].value = "-f"; prop7.vals[1].length = 2; prop7.vals[2].value = filename; prop7.vals[2].length = strlen (filename); } } props[0] = &prop1; props[1] = &prop2; props[2] = &prop3; props[3] = &prop4; props[4] = &prop5; SUPPRESS_UNUSED_VAR_WARNING(props); if (filename) { props[5] = &prop6; props[6] = &prop7; FSmcSetProperties (sm_conn, 7, props); free ((char *) prop6.vals); if (!is_xsm_detected) { free ((char *) prop7.vals); } } else { FSmcSetProperties (sm_conn, 5, props); } free ((char *) prop5.vals); } static void callback_save_yourself2(FSmcConn sm_conn, FSmPointer client_data) { Bool success = 0; char *filename; if (!SessionSupport) { return; } filename = get_unique_state_filename(); #ifdef FVWM_SM_DEBUG_PROTO fprintf(stderr, "[FVWM_SMDEBUG][callback_save_yourself2]\n"); #endif success = save_state_file(filename); if (success) { set_sm_properties(sm_conn, filename, FSmRestartIfRunning); set_real_state_filename(filename); } free(filename); FSmcSaveYourselfDone (sm_conn, success); sent_save_done = 1; } static void callback_save_yourself(FSmcConn sm_conn, FSmPointer client_data, int save_style, Bool shutdown, int interact_style, Bool fast) { if (!SessionSupport) { return; } #ifdef FVWM_SM_DEBUG_PROTO fprintf(stderr, "[FVWM_SMDEBUG][callback_save_yourself] " "(save=%d, shut=%d, intr=%d, fast=%d)\n", save_style, shutdown, interact_style, fast); #endif if (save_style == FSmSaveGlobal) { /* nothing to do */ #ifdef FVWM_SM_DEBUG_PROTO fprintf(stderr, "[FVWM_SMDEBUG][callback_save_yourself] " "Global Save type ... do nothing\n"); #endif FSmcSaveYourselfDone (sm_conn, True); sent_save_done = 1; return; } #ifdef FVWM_SM_DEBUG_PROTO fprintf(stderr, "[FVWM_SMDEBUG][callback_save_yourself] " "Both or Local save type, going to phase 2 ..."); #endif if (!FSmcRequestSaveYourselfPhase2( sm_conn, callback_save_yourself2, NULL)) { FSmcSaveYourselfDone (sm_conn, False); sent_save_done = 1; #ifdef FVWM_SM_DEBUG_PROTO fprintf(stderr, " failed!\n"); #endif } else { #ifdef FVWM_SM_DEBUG_PROTO fprintf(stderr, " OK\n"); #endif sent_save_done = 0; } return; } static void callback_die(FSmcConn sm_conn, FSmPointer client_data) { if (!SessionSupport) { return; } #ifdef FVWM_SM_DEBUG_PROTO fprintf(stderr, "[FVWM_SMDEBUG][callback_die]\n"); #endif if (FSmcCloseConnection(sm_conn, 0, NULL) != FSmcClosedNow) { /* go a head any way ? */ } sm_fd = -1; if (master_pid != getpid()) { kill(master_pid, SIGTERM); } Done(0, NULL); } static void callback_save_complete(FSmcConn sm_conn, FSmPointer client_data) { if (!SessionSupport) { return; } #ifdef FVWM_SM_DEBUG_PROTO fprintf(stderr, "[FVWM_SMDEBUG][callback_save_complete]\n"); #endif return; } static void callback_shutdown_cancelled(FSmcConn sm_conn, FSmPointer client_data) { if (!SessionSupport) { return; } #ifdef FVWM_SM_DEBUG_PROTO fprintf(stderr, "[FVWM_SMDEBUG][callback_shutdown_cancelled]\n"); #endif if (!sent_save_done) { FSmcSaveYourselfDone(sm_conn, False); sent_save_done = 1; } return; } /* the following is taken from xsm */ static void MyIoErrorHandler(FIceConn ice_conn) { if (!SessionSupport) { return; } if (prev_handler) { (*prev_handler) (ice_conn); } return; } static void InstallIOErrorHandler(void) { FIceIOErrorHandler default_handler; if (!SessionSupport) { return; } prev_handler = FIceSetIOErrorHandler (NULL); default_handler = FIceSetIOErrorHandler (MyIoErrorHandler); if (prev_handler == default_handler) { prev_handler = NULL; } return; } /* ---------------------------- interface functions ------------------------ */ void LoadGlobalState(char *filename) { FILE *f; char s[4096], s1[4096]; /* char s2[256]; */ char *is_key = NULL, *is_value = NULL; int n, i1, i2, i3, i4; if (!does_file_version_match) { return; } if (!filename || !*filename) { return; } if ((f = fopen(filename, "r")) == NULL) { return; } while (fgets(s, sizeof(s), f)) { n = 0; i1 = 0; i2 = 0; i3 = 0; i4 = 0; sscanf(s, "%4000s%n", s1, &n); /* If we are restarting, [REAL_STATE_FILENAME] points * to the file containing the true session state. */ if (SessionSupport && !strcmp(s1, "[REAL_STATE_FILENAME]")) { /* migo: temporarily (?) moved to LoadWindowStates (trick for gnome-session) sscanf(s, "%*s %s", s2); set_sm_properties(sm_conn, s2, FSmRestartIfRunning); set_real_state_filename(s2); */ } else if (!strcmp(s1, "[DESKTOP]")) { sscanf(s, "%*s %i", &i1); goto_desk(i1); } else if (!strcmp(s1, "[VIEWPORT]")) { sscanf(s, "%*s %i %i %i %i", &i1, &i2, &i3, &i4); /* migo: we don't want to lose DeskTopSize in * configurations, and it does not work well * anyways - Gnome is not updated Scr.VxMax = i3; Scr.VyMax = i4; */ MoveViewport(i1, i2, True); } else if (!strcmp(s1, "[KEY]")) { char *s2; s2 = s + n; if (*s2 != 0) { s2++; } sscanf(s2, "%[^\n]", s1); is_key = safestrdup(s1); } else if (!strcmp(s1, "[VALUE]")) { char *s2; s2 = s + n; if (*s2 != 0) { s2++; } sscanf(s2, "%[^\n]", s1); is_value = safestrdup(s1); fprintf(stderr, "GOT: %s -> %s\n", is_key, is_value); if (is_key != NULL && is_value != NULL) { fprintf(stderr, "INSERTING: %s -> %s\n", is_key, is_value); insert_metainfo(is_key, is_value); } free(is_key); free(is_value); is_key = is_value = NULL; } #if 0 /* migo (08-Dec-1999): we don't want to eliminate config yet */ else if (/*!Restarting*/ 0) { /* Matthias: We don't want to restore too much * state if we are restarting, since that * would make restarting useless for rereading * changed rc files. */ if (!strcmp(s1, "[SCROLL]")) { sscanf(s, "%*s %i %i %i %i ", &i1, &i2, &i3, &i4); Scr.EdgeScrollX = i1; Scr.EdgeScrollY = i2; Scr.ScrollDelay = i3; if (i4) { Scr.flags.edge_wrap_x = 1; } else { Scr.flags.edge_wrap_x = 0; } if (i3) { Scr.flags.edge_wrap_y = 1; } else { Scr.flags.edge_wrap_y = 0; } } else if (!strcmp(s1, "[MISC]")) { sscanf(s, "%*s %i %i %i", &i1, &i2, &i3); Scr.ClickTime = i1; Scr.ColormapFocus = i2; Scr.ColorLimit = i3; } else if (!strcmp(s1, "[STYLE]")) { sscanf(s, "%*s %i %i", &i1, &i2); Scr.gs.EmulateMWM = i1; Scr.gs.EmulateWIN = i2; } } #endif } fclose(f); return; } void DisableRestoringState(void) { num_match = 0; return; } void LoadWindowStates(char *filename) { FILE *f; char s[4096], s1[4096]; char *s2; int i, pos, pos1; unsigned long w; int n; if (!VerifyVersionInfo(filename)) { return; } if (!filename || !*filename) { return; } set_real_state_filename(filename); if ((f = fopen(filename, "r")) == NULL) { return; } #if defined(FVWM_SM_DEBUG_PROTO) || defined(FVWM_SM_DEBUG_FILES) fprintf(stderr, "[FVWM_SMDEBUG] Loading %s\n", filename); #endif #ifdef FVWM_SM_DEBUG_FILES system(CatString3( "mkdir -p /tmp/fs-load; cp ", filename, " /tmp/fs-load")); #endif while (fgets(s, sizeof(s), f)) { n = 0; sscanf(s, "%4000s%n", s1, &n); if (!SessionSupport /* migo: temporarily */ && !strcmp(s1, "[REAL_STATE_FILENAME]")) { sscanf(s, "%*s %s", s1); set_sm_properties(sm_conn, s1, FSmRestartIfRunning); set_real_state_filename(s1); } else if (!strcmp(s1, "[CLIENT]")) { sscanf(s, "%*s %lx", &w); num_match++; matches = (Match *)saferealloc( (void *)matches, sizeof(Match) * num_match); matches[num_match - 1].win = w; matches[num_match - 1].client_id = NULL; matches[num_match - 1].res_name = NULL; matches[num_match - 1].res_class = NULL; matches[num_match - 1].window_role = NULL; matches[num_match - 1].wm_name = NULL; matches[num_match - 1].wm_command_count = 0; matches[num_match - 1].wm_command = NULL; matches[num_match - 1].x = 0; matches[num_match - 1].y = 0; matches[num_match - 1].w = 100; matches[num_match - 1].h = 100; matches[num_match - 1].x_max = 0; matches[num_match - 1].y_max = 0; matches[num_match - 1].w_max = Scr.MyDisplayWidth; matches[num_match - 1].h_max = Scr.MyDisplayHeight; matches[num_match - 1].width_defect_max = 0; matches[num_match - 1].height_defect_max = 0; matches[num_match - 1].icon_x = 0; matches[num_match - 1].icon_y = 0; matches[num_match - 1].desktop = 0; matches[num_match - 1].layer = 0; matches[num_match - 1].default_layer = 0; memset(&(matches[num_match - 1].flags), 0, sizeof(window_flags)); matches[num_match - 1].used = 0; } else if (!strcmp(s1, "[GEOMETRY]")) { sscanf(s, "%*s %i %i %i %i %i %i %i %i %i %i %i %i" " %i %i %i", &(matches[num_match - 1].x), &(matches[num_match - 1].y), &(matches[num_match - 1].w), &(matches[num_match - 1].h), &(matches[num_match - 1].x_max), &(matches[num_match - 1].y_max), &(matches[num_match - 1].w_max), &(matches[num_match - 1].h_max), &(matches[num_match - 1].width_defect_max), &(matches[num_match - 1].height_defect_max), &(matches[num_match - 1].icon_x), &(matches[num_match - 1].icon_y), &(matches[num_match - 1].gravity), &(matches[num_match - 1].max_x_offset), &(matches[num_match - 1].max_y_offset)); } else if (!strcmp(s1, "[DESK]")) { sscanf(s, "%*s %i", &(matches[num_match - 1].desktop)); } else if (!strcmp(s1, "[LAYER]")) { sscanf(s, "%*s %i %i", &(matches[num_match - 1].layer), &(matches[num_match - 1].default_layer)); } else if (!strcmp(s1, "[PLACED_BY_BUTTON]")) { sscanf(s, "%*s %i", &(matches[num_match - 1].placed_by_button)); } else if (!strcmp(s1, "[EWMH_DESKTOP]")) { sscanf(s, "%*s %lu", &(matches[num_match - 1].ewmh_hint_desktop)); } else if (!strcmp(s1, "[FLAGS]")) { char *ts = s; /* skip [FLAGS] */ while (*ts != ']') { ts++; } ts++; for (i = 0; i < sizeof(window_flags); i++) { unsigned int f; sscanf(ts, "%02x ", &f); ((unsigned char *)& (matches[num_match-1].flags))[i] = f; ts += 3; } } else if (!strcmp(s1, "[CLIENT_ID]")) { s2 = s + n; if (*s2 != 0) { s2++; } sscanf(s2, "%[^\n]", s1); matches[num_match - 1].client_id = duplicate(s1); } else if (!strcmp(s1, "[WINDOW_ROLE]")) { s2 = s + n; if (*s2 != 0) { s2++; } sscanf(s2, "%[^\n]", s1); matches[num_match - 1].window_role = duplicate(s1); } else if (!strcmp(s1, "[RES_NAME]")) { s2 = s + n; if (*s2 != 0) { s2++; } sscanf(s2, "%[^\n]", s1); matches[num_match - 1].res_name = duplicate(s1); } else if (!strcmp(s1, "[RES_CLASS]")) { s2 = s + n; if (*s2 != 0) { s2++; } sscanf(s2, "%[^\n]", s1); matches[num_match - 1].res_class = duplicate(s1); } else if (!strcmp(s1, "[WM_NAME]")) { s2 = s + n; if (*s2 != 0) { s2++; } sscanf(s2, "%[^\n]", s1); matches[num_match - 1].wm_name = duplicate(s1); } else if (!strcmp(s1, "[WM_COMMAND]")) { sscanf(s, "%*s %i%n", &matches[num_match - 1].wm_command_count, &pos); matches[num_match - 1].wm_command = (char **) safemalloc( matches[num_match - 1]. wm_command_count * sizeof (char *)); for (i = 0; i < matches[num_match - 1].wm_command_count; i++) { sscanf (s+pos, "%s%n", s1, &pos1); pos += pos1; matches[num_match - 1].wm_command[i] = duplicate (s1); } } } fclose(f); return; } /* This routine (potentially) changes the flags STARTICONIC, MAXIMIZED, WSHADE and STICKY and the Desk and attr.x, .y, .width, .height entries. It also changes the stack_before pointer to return information about the desired stacking order. It expects the stacking order to be set up correctly beforehand! */ Bool MatchWinToSM( FvwmWindow *ewin, mwtsm_state_args *ret_state_args, initial_window_options_t *win_opts) { int i; if (!does_file_version_match) { return False; } for (i = 0; i < num_match; i++) { if (!matches[i].used && matchWin(ewin, &matches[i])) { matches[i].used = 1; if (!Restarting) { /* We don't want to restore too much state if we are restarting, since that would make * restarting useless for rereading changed * rc files. */ SET_DO_SKIP_WINDOW_LIST( ewin, DO_SKIP_WINDOW_LIST(&(matches[i]))); SET_ICON_SUPPRESSED( ewin, IS_ICON_SUPPRESSED(&(matches[i]))); SET_HAS_NO_ICON_TITLE( ewin, HAS_NO_ICON_TITLE(&(matches[i]))); FPS_LENIENT( FW_FOCUS_POLICY(ewin), FP_IS_LENIENT(FW_FOCUS_POLICY( &(matches[i])))); SET_ICON_STICKY_ACROSS_PAGES( ewin, IS_ICON_STICKY_ACROSS_PAGES( &(matches[i]))); SET_ICON_STICKY_ACROSS_DESKS( ewin, IS_ICON_STICKY_ACROSS_DESKS( &(matches[i]))); SET_DO_SKIP_ICON_CIRCULATE( ewin, DO_SKIP_ICON_CIRCULATE( &(matches[i]))); SET_DO_SKIP_SHADED_CIRCULATE( ewin, DO_SKIP_SHADED_CIRCULATE( &(matches[i]))); SET_DO_SKIP_CIRCULATE( ewin, DO_SKIP_CIRCULATE(&(matches[i]))); memcpy( &FW_FOCUS_POLICY(ewin), &FW_FOCUS_POLICY(&matches[i]), sizeof(focus_policy_t)); if (matches[i].wm_name) { free_window_names(ewin, True, False); ewin->name.name = matches[i].wm_name; setup_visible_names(ewin, 1); } } SET_NAME_CHANGED(ewin,IS_NAME_CHANGED(&(matches[i]))); SET_PLACED_BY_FVWM( ewin, IS_PLACED_BY_FVWM(&(matches[i]))); ret_state_args->do_shade = IS_SHADED(&(matches[i])); ret_state_args->used_title_dir_for_shading = USED_TITLE_DIR_FOR_SHADING(&(matches[i])); ret_state_args->shade_dir = SHADED_DIR(&(matches[i])); ret_state_args->do_max = IS_MAXIMIZED(&(matches[i])); SET_USER_STATES(ewin, GET_USER_STATES(&(matches[i]))); SET_ICON_MOVED(ewin, IS_ICON_MOVED(&(matches[i]))); if (IS_ICONIFIED(&(matches[i]))) { /* ICON_MOVED is necessary to make fvwm use icon_[xy]_loc for icon placement */ win_opts->initial_state = IconicState; win_opts->flags.use_initial_icon_xy = 1; win_opts->initial_icon_x = matches[i].icon_x; win_opts->initial_icon_y = matches[i].icon_y; if (!IS_STICKY_ACROSS_PAGES(&(matches[i])) && !(IS_ICONIFIED(&(matches[i])) && IS_ICON_STICKY_ACROSS_PAGES( &(matches[i])))) { win_opts->initial_icon_x -= Scr.Vx; win_opts->initial_icon_y -= Scr.Vy; } } ewin->g.normal.x = matches[i].x; ewin->g.normal.y = matches[i].y; ewin->g.normal.width = matches[i].w; ewin->g.normal.height = matches[i].h; ewin->g.max.x = matches[i].x_max; ewin->g.max.y = matches[i].y_max; ewin->g.max.width = matches[i].w_max; ewin->g.max.height = matches[i].h_max; ewin->g.max_defect.width = matches[i].width_defect_max; ewin->g.max_defect.height = matches[i].height_defect_max; ewin->g.max_offset.x = matches[i].max_x_offset; ewin->g.max_offset.y = matches[i].max_y_offset; SET_STICKY_ACROSS_PAGES( ewin, IS_STICKY_ACROSS_PAGES(&(matches[i]))); SET_STICKY_ACROSS_DESKS( ewin, IS_STICKY_ACROSS_DESKS(&(matches[i]))); ewin->Desk = (IS_STICKY_ACROSS_DESKS(ewin)) ? Scr.CurrentDesk : matches[i].desktop; set_layer(ewin, matches[i].layer); set_default_layer(ewin, matches[i].default_layer); ewin->placed_by_button = matches[i].placed_by_button; /* Note: the Modal, skip pager, skip taskbar and * "stacking order" state are not restored here: there * are restored in EWMH_ExitStuff */ ewin->ewmh_hint_desktop = matches[i].ewmh_hint_desktop; SET_HAS_EWMH_INIT_WM_DESKTOP( ewin, HAS_EWMH_INIT_WM_DESKTOP(&(matches[i]))); SET_HAS_EWMH_INIT_HIDDEN_STATE( ewin, HAS_EWMH_INIT_HIDDEN_STATE( &(matches[i]))); SET_HAS_EWMH_INIT_MAXHORIZ_STATE( ewin, HAS_EWMH_INIT_MAXHORIZ_STATE( &(matches[i]))); SET_HAS_EWMH_INIT_MAXVERT_STATE( ewin, HAS_EWMH_INIT_MAXVERT_STATE( &(matches[i]))); SET_HAS_EWMH_INIT_SHADED_STATE( ewin, HAS_EWMH_INIT_SHADED_STATE( &(matches[i]))); SET_HAS_EWMH_INIT_STICKY_STATE( ewin, HAS_EWMH_INIT_STICKY_STATE( &(matches[i]))); return True; } } return False; } void RestartInSession (char *filename, Bool is_native, Bool _do_preserve_state) { do_preserve_state = _do_preserve_state; if (SessionSupport && sm_conn && is_native) { going_to_restart = True; save_state_file(filename); set_sm_properties(sm_conn, filename, FSmRestartImmediately); MoveViewport(0, 0, False); Reborder(); CloseICCCM2(); XCloseDisplay(dpy); if ((!FSmcCloseConnection(sm_conn, 0, NULL)) != FSmcClosedNow) { /* go a head any way ? */ } #ifdef FVWM_SM_DEBUG_PROTO fprintf(stderr, "[FVWM_SMDEBUG]: Exiting, now SM must " "restart us.\n"); #endif /* Close all my pipes */ module_kill_all(); exit(0); /* let the SM restart us */ } save_state_file(filename); /* return and let Done restart us */ return; } void SetClientID(char *client_id) { if (!SessionSupport) { return; } previous_sm_client_id = client_id; return; } void SessionInit(void) { char error_string_ret[4096] = ""; FSmPointer context; FSmcCallbacks callbacks; if (!SessionSupport) { /* -Wall fixes */ MyIoErrorHandler(NULL); callback_save_yourself2(NULL, NULL); return; } InstallIOErrorHandler(); callbacks.save_yourself.callback = callback_save_yourself; callbacks.die.callback = callback_die; callbacks.save_complete.callback = callback_save_complete; callbacks.shutdown_cancelled.callback = callback_shutdown_cancelled; callbacks.save_yourself.client_data = callbacks.die.client_data = callbacks.save_complete.client_data = callbacks.shutdown_cancelled.client_data = (FSmPointer) NULL; SUPPRESS_UNUSED_VAR_WARNING(context); sm_conn = FSmcOpenConnection( NULL, &context, FSmProtoMajor, FSmProtoMinor, FSmcSaveYourselfProcMask | FSmcDieProcMask | FSmcSaveCompleteProcMask | FSmcShutdownCancelledProcMask, &callbacks, previous_sm_client_id, &sm_client_id, 4096, error_string_ret); if (!sm_conn) { /* Don't annoy users which don't use a session manager */ if (previous_sm_client_id) { fvwm_msg( ERR, "SessionInit", "While connecting to session manager:\n%s.", error_string_ret); } sm_fd = -1; #ifdef FVWM_SM_DEBUG_PROTO fprintf(stderr,"[FVWM_SMDEBUG] No SM connection\n"); #endif } else { sm_fd = FIceConnectionNumber(FSmcGetIceConnection(sm_conn)); #ifdef FVWM_SM_DEBUG_PROTO fprintf(stderr,"[FVWM_SMDEBUG] Connectecd to a SM\n"); #endif set_init_function_name(0, "SessionInitFunction"); set_init_function_name(1, "SessionRestartFunction"); set_init_function_name(2, "SessionExitFunction"); /* basically to restet our restart style hint after a * restart */ set_sm_properties(sm_conn, NULL, FSmRestartIfRunning); } return; } void ProcessICEMsgs(void) { FIceProcessMessagesStatus status; if (!SessionSupport) { return; } #ifdef FVWM_SM_DEBUG_PROTO fprintf(stderr,"[FVWM_SMDEBUG][ProcessICEMsgs] %i\n", (int)sm_fd); #endif if (sm_fd < 0) { return; } status = FIceProcessMessages(FSmcGetIceConnection(sm_conn), NULL, NULL); if (status == FIceProcessMessagesIOError) { fvwm_msg(ERR, "ProcessICEMSGS", "Connection to session manager lost\n"); sm_conn = NULL; sm_fd = -1; } return; } /* * Fvwm Function implementation: QuitSession, SaveSession, SaveQuitSession. * migo (15-Jun-1999): I am not sure this is right. * The session mabager must implement SmsSaveYourselfRequest (xsm doesn't?). * Alternative implementation may use unix signals, but this does not work * with all session managers (also must suppose that SM runs locally). */ int get_sm_pid(void) { const char *session_manager_var = getenv("SESSION_MANAGER"); const char *sm_pid_str_ptr; int sm_pid = 0; if (!SessionSupport) { return 0; } if (!session_manager_var) { return 0; } sm_pid_str_ptr = strchr(session_manager_var, ','); if (!sm_pid_str_ptr) { return 0; } while (sm_pid_str_ptr > session_manager_var && isdigit(*(--sm_pid_str_ptr))) { /* nothing */ } while (isdigit(*(++sm_pid_str_ptr))) { sm_pid = sm_pid * 10 + *sm_pid_str_ptr - '0'; } return sm_pid; } /* * quit_session - hopefully shutdowns the session */ Bool quit_session(void) { if (!SessionSupport) { return False; } if (!sm_conn) { return False; } FSmcRequestSaveYourself( sm_conn, FSmSaveLocal, True /* shutdown */, FSmInteractStyleAny, False /* fast */, True /* global */); return True; /* migo: xsm does not support RequestSaveYourself, but supports * signals: */ /* int sm_pid = get_sm_pid(); if (!sm_pid) return False; return kill(sm_pid, SIGTERM) == 0 ? True : False; */ } /* * save_session - hopefully saves the session */ Bool save_session(void) { if (!SessionSupport) { return False; } if (!sm_conn) { return False; } FSmcRequestSaveYourself( sm_conn, FSmSaveBoth, False /* shutdown */, FSmInteractStyleAny, False /* fast */, True /* global */); return True; /* migo: xsm does not support RequestSaveYourself, but supports * signals: */ /* int sm_pid = get_sm_pid(); if (!sm_pid) return False; return kill(sm_pid, SIGUSR1) == 0 ? True : False; */ } /* * save_quit_session - hopefully saves and shutdowns the session */ Bool save_quit_session(void) { if (!SessionSupport) { return False; } if (!sm_conn) { return False; } FSmcRequestSaveYourself( sm_conn, FSmSaveBoth, True /* shutdown */, FSmInteractStyleAny, False /* fast */, True /* global */); return True; /* migo: xsm does not support RequestSaveYourself, but supports * signals: */ /* if (save_session() == False) return False; sleep(3); / * doesn't work anyway * / if (quit_session() == False) return False; return True; */ } /* ---------------------------- builtin commands --------------------------- */ void CMD_QuitSession(F_CMD_ARGS) { quit_session(); return; } void CMD_SaveSession(F_CMD_ARGS) { save_session(); return; } void CMD_SaveQuitSession(F_CMD_ARGS) { save_quit_session(); return; } fvwm-2.7.0/fvwm/virtual.h0000644000175000017500000000111014147024700012226 00000000000000/* -*-c-*- */ #ifndef _VIRTUAL_ #define _VIRTUAL_ int HandlePaging( XEvent *pev, int HorWarpSize, int VertWarpSize, int *xl, int *yt, int *delta_x, int *delta_y, Bool Grab, Bool fLoop, Bool do_continue_previous, int delay); void checkPanFrames(void); void raisePanFrames(void); void initPanFrames(void); Bool is_pan_frame(Window w); void MoveViewport(int newx, int newy,Bool); void goto_desk(int desk); void do_move_window_to_desk(FvwmWindow *fw, int desk); Bool get_page_arguments(char *action, int *page_x, int *page_y); char *GetDesktopName(int desk); #endif /* _VIRTUAL_ */ fvwm-2.7.0/fvwm/frame.h0000644000175000017500000000451014147024700011641 00000000000000/* -*-c-*- */ #ifndef FRAME_H #define FRAME_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ typedef enum { FRAME_MR_SETUP, FRAME_MR_SETUP_BY_APP, FRAME_MR_OPAQUE, FRAME_MR_SHRINK, FRAME_MR_SCROLL, /* used internally only, do not set these in any calls */ FRAME_MR_FORCE_SETUP, FRAME_MR_FORCE_SETUP_NO_W, /* used by AddWindow() to suppress drawing during window setup */ FRAME_MR_DONT_DRAW = 0x80 } frame_move_resize_mode; typedef struct { rectangle title_g; rectangle button_g[NUMBER_OF_TITLE_BUTTONS]; } frame_title_layout_t; /* details are hidden in frame.c */ typedef void *frame_move_resize_args; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ void frame_init(void); Bool is_frame_hide_window( Window w); void frame_destroyed_frame( Window frame_w); frame_move_resize_args frame_create_move_resize_args( FvwmWindow *fw, frame_move_resize_mode mr_mode, rectangle *start_g, rectangle *end_g, int anim_steps, int shade_dir); void frame_update_move_resize_args( frame_move_resize_args mr_args, rectangle *end_g); void frame_free_move_resize_args( FvwmWindow *fw, frame_move_resize_args mr_args); void frame_get_titlebar_dimensions( FvwmWindow *fw, rectangle *frame_g, rectangle *diff_g, frame_title_layout_t *title_layout); void frame_get_sidebar_geometry( FvwmWindow *fw, DecorFaceStyle *borderstyle, rectangle *frame_g, rectangle *ret_g, Bool *ret_has_x_marks, Bool *ret_has_y_marks); int frame_window_id_to_context( FvwmWindow *fw, Window w, int *ret_num); void frame_move_resize( FvwmWindow *fw, frame_move_resize_args mr_args); void frame_setup_window( FvwmWindow *fw, int x, int y, int w, int h, Bool do_send_configure_notify); void frame_setup_window_app_request( FvwmWindow *fw, int x, int y, int w, int h, Bool do_send_configure_notify); void frame_force_setup_window( FvwmWindow *fw, int x, int y, int w, int h, Bool do_send_configure_notify); void frame_setup_shape( FvwmWindow *fw, int w, int h, int shape_mode); #endif /* FRAME_H */ fvwm-2.7.0/fvwm/icccm2.c0000644000175000017500000001476214147024700011714 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ #include "config.h" #include #ifdef HAVE_FCNTL_H #include #endif #include #include "fvwm.h" #include "externs.h" #include "execcontext.h" #include "misc.h" #include "screen.h" #include "eventmask.h" Time managing_since; Atom _XA_WM_SX; Atom _XA_MANAGER; Atom _XA_ATOM_PAIR; Atom _XA_WM_COLORMAP_NOTIFY; #define _XA_TARGETS conversion_targets[0] #define _XA_MULTIPLE conversion_targets[1] #define _XA_TIMESTAMP conversion_targets[2] #define _XA_VERSION conversion_targets[3] #define MAX_TARGETS 4 long conversion_targets[MAX_TARGETS]; long icccm_version[] = { 2, 0 }; void SetupICCCM2(Bool replace_wm) { Window running_wm_win; XSetWindowAttributes attr; XEvent xev; XClientMessageEvent ev; char wm_sx[20]; sprintf(wm_sx, "WM_S%lu", Scr.screen); _XA_WM_SX = XInternAtom(dpy, wm_sx, False); _XA_MANAGER = XInternAtom(dpy, "MANAGER", False); _XA_ATOM_PAIR = XInternAtom(dpy, "ATOM_PAIR", False); _XA_TARGETS = XInternAtom(dpy, "TARGETS", False); _XA_MULTIPLE = XInternAtom(dpy, "MULTIPLE", False); _XA_TIMESTAMP = XInternAtom(dpy, "TIMESTAMP", False); _XA_VERSION = XInternAtom(dpy, "VERSION", False); _XA_WM_COLORMAP_NOTIFY = XInternAtom(dpy, "WM_COLORMAP_NOTIFY", False); /* Check for a running ICCCM 2.0 compliant WM */ running_wm_win = XGetSelectionOwner(dpy, _XA_WM_SX); if (running_wm_win != None) { DBUG( "SetupICCCM2", "another ICCCM 2.0 compliant WM is running"); if (!replace_wm) { fvwm_msg( ERR, "SetupICCCM2", "another ICCCM 2.0 compliant WM is running," " try -replace"); exit(1); } /* We need to know when the old manager is gone. Thus we wait until it destroys running_wm_win. */ attr.event_mask = StructureNotifyMask; XChangeWindowAttributes( dpy, running_wm_win, CWEventMask, &attr); } /* We are not yet in the event loop, thus fev_get_evtime() will not * be ready. Have to get a timestamp manually by provoking a * PropertyNotify. */ managing_since = get_server_time(); XSetSelectionOwner(dpy, _XA_WM_SX, Scr.NoFocusWin, managing_since); if (XGetSelectionOwner(dpy, _XA_WM_SX) != Scr.NoFocusWin) { fvwm_msg( ERR, "SetupICCCM2", "failed to acquire selection ownership"); exit(1); } /* Announce ourself as the new wm */ ev.type = ClientMessage; ev.window = Scr.Root; ev.message_type = _XA_MANAGER; ev.format = 32; ev.data.l[0] = managing_since; ev.data.l[1] = _XA_WM_SX; FSendEvent(dpy, Scr.Root, False, StructureNotifyMask,(XEvent*)&ev); if (running_wm_win != None) { /* Wait for the old wm to finish. */ /* FIXME: need a timeout here. */ DBUG("SetupICCCM2", "waiting for WM to give up"); do { FWindowEvent( dpy, running_wm_win, StructureNotifyMask, &xev); } while (xev.type != DestroyNotify); } /* restore NoFocusWin event mask */ attr.event_mask = XEVMASK_NOFOCUSW; XChangeWindowAttributes(dpy, Scr.NoFocusWin, CWEventMask, &attr); return; } /* We must make sure that we have released SubstructureRedirect before we destroy manager_win, so that another wm can start successfully. */ void CloseICCCM2(void) { DBUG("CloseICCCM2", "good luck, new wm"); XSelectInput(dpy, Scr.Root, NoEventMask); XFlush(dpy); return; } /* FIXME: property change actually succeeded */ static Bool convertProperty(Window w, Atom target, Atom property) { if (target == _XA_TARGETS) { XChangeProperty( dpy, w, property, XA_ATOM, 32, PropModeReplace, (unsigned char *)conversion_targets, MAX_TARGETS); } else if (target == _XA_TIMESTAMP) { long local_managing_since; local_managing_since = managing_since; XChangeProperty( dpy, w, property, XA_INTEGER, 32, PropModeReplace, (unsigned char *)&local_managing_since, 1); } else if (target == _XA_VERSION) { XChangeProperty( dpy, w, property, XA_INTEGER, 32, PropModeReplace, (unsigned char *)icccm_version, 2); } else { return False; } /* FIXME: This is ugly. We should rather select for PropertyNotify on the window, return to the main loop, and send the SelectionNotify once we are sure the property has arrived. Problem: this needs a list of pending SelectionNotifys. */ XFlush(dpy); return True; } void icccm2_handle_selection_request(const XEvent *e) { Atom type; unsigned long *adata; int i, format; unsigned long num, rest; unsigned char *data; XSelectionRequestEvent ev = e->xselectionrequest; XSelectionEvent reply; reply.type = SelectionNotify; reply.display = dpy; reply.requestor = ev.requestor; reply.selection = ev.selection; reply.target = ev.target; reply.property = None; reply.time = ev.time; if (ev.target == _XA_MULTIPLE) { if (ev.property != None) { XGetWindowProperty( dpy, ev.requestor, ev.property, 0L, 256L, False, _XA_ATOM_PAIR, &type, &format, &num, &rest, &data); /* FIXME: to be 100% correct, should deal with * rest > 0, but since we have 4 possible targets, we * will hardly ever meet multiple requests with a * length > 8 */ adata = (unsigned long *)data; for(i = 0; i < num; i += 2) { if (!convertProperty( ev.requestor, adata[i], adata[i+1])) { adata[i+1] = None; } } XChangeProperty( dpy, ev.requestor, ev.property, _XA_ATOM_PAIR, 32, PropModeReplace, data, num); XFree(data); } } else { if (ev.property == None) { ev.property = ev.target; } if (convertProperty(ev.requestor, ev.target, ev.property)) { reply.property = ev.property; } } FSendEvent(dpy, ev.requestor, False, 0L,(XEvent*)&reply); XFlush(dpy); return; } /* If another wm is requesting ownership of the selection, we receive a SelectionClear event. In that case, we have to release all resources and destroy manager_win. Done() calls CloseICCCM2() after undecorating all windows. */ void icccm2_handle_selection_clear(void) { DBUG("HandleSelectionClear", "I lost my selection!"); Done(0, NULL); return; } fvwm-2.7.0/fvwm/fvwm.h0000644000175000017500000007371614147024700011544 00000000000000/* -*-c-*- */ /* This module is based on Twm, but has been siginificantly modified * by Rob Nation */ /* * Copyright 1988 by Evans & Sutherland Computer Corporation, * Salt Lake City, Utah * Portions Copyright 1989 by the Massachusetts Institute of Technology * Cambridge, Massachusetts * * All Rights Reserved * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice appear in all * copies and that both that copyright notice and this permis- * sion notice appear in supporting documentation, and that the * names of Evans & Sutherland and M.I.T. not be used in advertising * in publicity pertaining to distribution of the software without * specific, written prior permission. * * EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- * ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR * M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- * AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE * OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef FVWM_H #define FVWM_H /* ---------------------------- included header files ---------------------- */ #include #include #include #include #include "libs/PictureBase.h" #include "libs/Flocale.h" #include "libs/fvwmrect.h" #include "window_flags.h" #include "condrc.h" /* ---------------------------- global definitions ------------------------- */ #ifndef WithdrawnState #define WithdrawnState 0 #endif /* ---------------------------- global macros ------------------------------ */ /* * Fvwm trivia: There were 97 commands in the fvwm command table * when the F_CMD_ARGS macro was written. * dje 12/19/98. */ /* Macro for args passed to fvwm commands... */ #define F_CMD_ARGS \ cond_rc_t *cond_rc, const exec_context_t *exc, char *action #define F_PASS_ARGS cond_rc, exc, action #define FUNC_FLAGS_TYPE unsigned char /* access macros */ #define FW_W_FRAME(fw) ((fw)->wins.frame) #define FW_W_PARENT(fw) ((fw)->wins.parent) #define FW_W_CLIENT(fw) ((fw)->wins.client) #define FW_W(fw) FW_W_CLIENT(fw) #define FW_W_TITLE(fw) ((fw)->wins.title) #define FW_W_BUTTON(fw,i) ((fw)->wins.button_w[(i)]) #define FW_W_SIDE(fw,i) ((fw)->wins.sides[(i)]) #define FW_W_CORNER(fw,i) ((fw)->wins.corners[(i)]) #define FW_W_ICON_TITLE(fw) ((fw)->wins.icon_title_w) #define FW_W_ICON_PIXMAP(fw) ((fw)->wins.icon_pixmap_w) #define FW_W_TRANSIENTFOR(fw) ((fw)->wins.transientfor) /* ---------------------------- forward declarations ----------------------- */ struct size_borders; struct exec_context_t; /* definition in screen.h */ struct FvwmDecor; /* ---------------------------- type definitions --------------------------- */ /* This structure carries information about the initial window state and * placement. This information is gathered at various places: the (re)capture * code, AddToWindow(), HandleMapRequestRaised(), ewmh_events.c and others. * * initial_state * The initial window state. By default it carries the value DontCareState. * Other states can be set if * - an icon is recaptured or restarted with session management * - the StartIconic style is set * - GNOME, EWMH, foobar hints demand that the icon starts iconic * The final value is calculated in HandleMapRequestRaised(). * * do_override_ppos * This flag is used in PlaceWindow(). If it is set, the position requested * by the program is ignored unconditionally. This is used during the * initial capture and later recapture operations. * * is_iconified_by_parent * Preserves the information if the window is a transient window that was * iconified along with its transientfor window. Set when the window is * recaptured and used in HandleMapRequestRaised() to set the according * window state flag. Deleted afterwards. * * is_menu * Set in menus.c or in the recapture code if the new window is a tear off * menu. Such windows get special treatment in AddWindow() and events.c. * * is_recapture * Set for the initial capture and later recaptures. * * default_icon_x/y * The icon position that was requested by the application in the icon * position hint. May be overridden by a style (0/0 then). Set in * HandleMapRequestRaised() and used in the icon placement code. * * initial_icon_x/y * The icon position that is forced during a restart with SM. If set it * overrides all other methods of icon placement. Set by session.c and used * in the icon placement code. * * use_initial_icon_xy * If set, the initial_icon_x/y values are used. Other wise they are * ignored. */ typedef struct { long initial_state; struct { unsigned do_override_ppos : 1; unsigned is_iconified_by_parent : 1; unsigned is_menu : 1; unsigned is_recapture : 1; unsigned use_initial_icon_xy : 1; } flags; int initial_icon_x; int initial_icon_y; int default_icon_x; int default_icon_y; } initial_window_options_t; /* For 1 style statement, there can be any number of IconBoxes. The name list points at the first one in the chain. */ typedef struct icon_boxes_struct { struct icon_boxes_struct *next; /* next icon_boxes or zero */ unsigned int use_count; int IconBox[4]; /* x/y x/y for iconbox */ int IconScreen; /* Xinerama screen */ short IconGrid[2]; /* x incr, y incr */ char IconSign[4]; /* because of -0, need to save */ unsigned is_orphan : 1; unsigned IconFlags : 3; /* some bits */ /* IconFill only takes 3 bits. Defaults are top, left, vert co-ord * first eg: t l = 0,0,0; l t = 0,0,1; b r = 1,1,0 */ #define ICONFILLBOT (1<<0) #define ICONFILLRGT (1<<1) #define ICONFILLHRZ (1<<2) } icon_boxes; typedef struct { Pixel fore; Pixel back; } ColorPair; typedef struct { Pixel fore; Pixel back; Pixel hilight; Pixel shadow; } color_quad; typedef struct { int left; int right; int top; int bottom; } ewmh_strut; typedef struct { /* common flags (former flags in bits 0-12) */ unsigned is_sticky_across_pages : 1; unsigned is_sticky_across_desks : 1; unsigned has_icon_font : 1; unsigned has_no_border : 1; unsigned has_window_font : 1; unsigned title_dir : 2; unsigned user_states : 32; /* static flags that do not change dynamically after the window has * been created */ struct { unsigned do_circulate_skip : 1; unsigned do_circulate_skip_icon : 1; unsigned do_circulate_skip_shaded : 1; unsigned do_ewmh_donate_icon : 1; unsigned do_ewmh_donate_mini_icon : 1; unsigned do_ewmh_ignore_state_hints : 1; unsigned do_ewmh_ignore_strut_hints : 1; unsigned do_ewmh_mini_icon_override : 1; unsigned do_ewmh_use_stacking_hints : 1; unsigned do_ewmh_ignore_window_type : 1; unsigned do_iconify_window_groups : 1; unsigned do_ignore_icon_boxes : 1; unsigned do_ignore_restack : 1; unsigned do_use_window_group_hint : 1; unsigned do_lower_transient : 1; unsigned do_not_show_on_map : 1; unsigned do_raise_transient : 1; unsigned do_resize_opaque : 1; unsigned do_shrink_windowshade : 1; unsigned do_stack_transient_parent : 1; unsigned do_window_list_skip : 1; unsigned ewmh_maximize_mode : 2; /* see ewmh.h */ unsigned has_depressable_border : 1; unsigned has_mwm_border : 1; unsigned has_mwm_buttons : 1; unsigned has_mwm_override : 1; unsigned has_no_icon_title : 1; unsigned has_override_size : 1; unsigned has_stippled_title : 1; unsigned has_stippled_icon_title : 1; /* default has to be 0, therefore no_, not in macros */ unsigned has_no_sticky_stippled_title : 1; unsigned has_no_sticky_stippled_icon_title : 1; unsigned icon_override : 2; #define NO_ACTIVE_ICON_OVERRIDE 0 #define ICON_OVERRIDE 1 #define NO_ICON_OVERRIDE 2 #define ICON_OVERRIDE_MASK 0x3 unsigned is_bottom_title_rotated : 1; unsigned is_fixed : 1; unsigned is_fixed_ppos : 1; unsigned is_uniconifiable : 1; unsigned is_unmaximizable : 1; unsigned is_unclosable : 1; unsigned is_maximize_fixed_size_disallowed : 1; unsigned is_icon_sticky_across_pages : 1; unsigned is_icon_sticky_across_desks : 1; unsigned is_icon_suppressed : 1; unsigned is_left_title_rotated_cw : 1; /* cw = clock wise */ unsigned is_lenient : 1; unsigned is_size_fixed : 1; unsigned is_psize_fixed : 1; unsigned is_right_title_rotated_cw : 1; unsigned is_top_title_rotated : 1; unsigned use_icon_position_hint : 1; unsigned use_indexed_window_name : 1; unsigned use_indexed_icon_name : 1; #define WINDOWSHADE_LAZY 0 #define WINDOWSHADE_ALWAYS_LAZY 1 #define WINDOWSHADE_BUSY 2 #define WINDOWSHADE_LAZY_MASK 0x3 unsigned windowshade_laziness : 2; unsigned use_title_decor_rotation : 1; focus_policy_t focus_policy; } s; } common_flags_t; typedef struct { common_flags_t common; #define CR_MOTION_METHOD_AUTO 0 #define CR_MOTION_METHOD_USE_GRAV 1 #define CR_MOTION_METHOD_STATIC_GRAV 2 #define CR_MOTION_METHOD_MASK 0x3 unsigned cr_motion_method : 2; unsigned was_cr_motion_method_detected : 1; unsigned does_wm_delete_window : 1; unsigned does_wm_take_focus : 1; unsigned do_force_next_cr : 1; unsigned do_force_next_pn : 1; unsigned do_iconify_after_map : 1; unsigned do_disable_constrain_size_fullscreen : 1; /* Reuse this struct, don't free it, when destroying/recapturing * window. */ unsigned do_reuse_destroyed : 1; /* Does it have resize handles? */ unsigned has_handles : 1; /* Icon change is pending */ unsigned has_icon_changed : 1; /* Is this decorated with title */ unsigned has_title : 1; /* wm_normal_hints update is pending? */ unsigned has_new_wm_normal_hints : 1; /* ChangeDecor was used for window */ unsigned is_decor_changed : 1; /* Sent an XUnmapWindow for iconifying, but didn't receive an * UnmapNotify yet.*/ unsigned is_iconify_pending : 1; /* window had the focus when the desk was switched. set if the window * was mapped and got focused but the focus change was not announced * to the modules yet. */ unsigned is_focused_on_other_desk : 1; unsigned is_focus_change_broadcast_pending : 1; /* is the window fully visible */ unsigned is_fully_visible : 1; /* is it an icon now? */ unsigned is_iconified : 1; /* To prevent iconified transients in a parent icon from counting for * Next */ unsigned is_iconified_by_parent : 1; /* is the pointer over the icon? */ unsigned is_icon_entered : 1; unsigned is_icon_font_loaded : 1; /* has the icon been moved by the user? */ unsigned is_icon_moved : 1; /* is the icon window supplied by the app? */ unsigned is_icon_ours : 1; /* is the icon shaped? */ unsigned is_icon_shaped : 1; /* was the icon unmapped, even though the window is still iconified * (Transients) */ unsigned is_icon_unmapped : 1; /* temporary flag used in stack.c */ unsigned is_in_transient_subtree : 1; /* is it mapped? */ unsigned is_mapped : 1; /* Sent an XMapWindow, but didn't receive a MapNotify yet.*/ unsigned is_map_pending : 1; /* is the window maximized? */ unsigned is_maximized : 1; /* Set if the client changes its WM_NAME. The source of twm contains * an explanation why we need this information. */ unsigned is_name_changed : 1; /* is the window partially visible */ unsigned is_partially_visible : 1; /* is the icon pixmap ours to free? */ unsigned is_pixmap_ours : 1; /* fvwm places the window itself */ unsigned is_placed_by_fvwm : 1; /* mark window to be destroyed after last complex func has finished. */ unsigned is_scheduled_for_destroy : 1; /* mark window to be raised after function execution. */ unsigned is_scheduled_for_raise : 1; unsigned is_size_inc_set : 1; unsigned is_style_deleted : 1; /* the window is a torn out fvwm menu */ unsigned is_tear_off_menu : 1; /* is it a transient window? */ unsigned is_transient : 1; unsigned is_window_drawn_once : 1; /* To prevent double move in MoveViewport.*/ unsigned is_viewport_moved : 1; unsigned is_window_being_moved_opaque : 1; unsigned is_window_font_loaded : 1; unsigned is_window_shaded : 1; unsigned used_title_dir_for_shading : 1; unsigned shaded_dir : 3; unsigned using_default_icon_font : 1; unsigned using_default_window_font : 1; #define ICON_HINT_NEVER 0 #define ICON_HINT_ONCE 1 #define ICON_HINT_MULTIPLE 2 unsigned was_icon_hint_provided : 2; unsigned was_icon_name_provided : 1; unsigned was_never_drawn : 1; unsigned has_ewmh_wm_name : 1; unsigned has_ewmh_wm_icon_name : 1; #define EWMH_NO_ICON 0 /* the application does not provide an ewmh icon */ #define EWMH_TRUE_ICON 1 /* the application does provide an ewmh icon */ #define EWMH_FVWM_ICON 2 /* the ewmh icon has been set by fvwm */ unsigned has_ewmh_wm_icon_hint : 2; /* says if the app have an ewmh icon of acceptable size for a mini * icon in its list of icons */ unsigned has_ewmh_mini_icon : 1; unsigned has_ewmh_wm_pid : 1; /* the ewmh icon is used as icon pixmap */ unsigned use_ewmh_icon : 1; unsigned is_ewmh_modal : 1; unsigned is_ewmh_fullscreen : 1; #define EWMH_STATE_UNDEFINED_HINT 0 #define EWMH_STATE_NO_HINT 1 #define EWMH_STATE_HAS_HINT 2 unsigned has_ewmh_init_fullscreen_state : 2; unsigned has_ewmh_init_hidden_state : 2; unsigned has_ewmh_init_maxhoriz_state : 2; unsigned has_ewmh_init_maxvert_state : 2; unsigned has_ewmh_init_modal_state : 2; unsigned has_ewmh_init_shaded_state : 2; unsigned has_ewmh_init_skip_pager_state : 2; unsigned has_ewmh_init_skip_taskbar_state : 2; unsigned has_ewmh_init_sticky_state : 2; unsigned has_ewmh_init_wm_desktop : 2; } window_flags; /* Actions allowed by modules. */ typedef struct action_flags { unsigned is_movable : 1; unsigned is_deletable : 1; unsigned is_destroyable : 1; unsigned is_closable : 1; unsigned is_maximizable : 1; unsigned is_resizable : 1; unsigned is_iconifiable : 1; } action_flags; /* Window name data structure for window conditions: a list of lists of names to match, the boolean operation on the matches being an AND of ORs. */ struct namelist /* matches to names in this list are ORed */ { char *name; struct namelist *next; }; struct name_condition /* matches to namelists in this list are ANDed, after possibly inverting each */ { Bool invert; struct namelist *namelist; struct name_condition *next; }; /* Window mask for Circulate and Direction functions */ typedef struct WindowConditionMask { struct { unsigned do_accept_focus : 1; unsigned do_check_desk : 1; unsigned do_check_screen : 1; unsigned do_check_cond_desk : 1; unsigned do_check_desk_and_global_page : 1; unsigned do_check_desk_and_page : 1; unsigned do_check_global_page : 1; unsigned do_check_overlapped : 1; unsigned do_check_page : 1; unsigned do_check_fullscreen : 1; unsigned do_not_check_screen : 1; unsigned needs_current_desk : 1; unsigned needs_current_desk_and_global_page : 1; unsigned needs_current_desk_and_page : 1; unsigned needs_current_global_page : 1; unsigned needs_current_page : 1; #define NEEDS_ANY 0 #define NEEDS_TRUE 1 #define NEEDS_FALSE 2 unsigned needs_focus : 2; unsigned needs_overlapped : 2; unsigned needs_pointer : 2; unsigned needs_same_layer : 1; unsigned use_circulate_hit : 1; unsigned use_circulate_hit_icon : 1; unsigned use_circulate_hit_shaded : 1; unsigned use_do_accept_focus : 1; } my_flags; window_flags flags; window_flags flag_mask; struct name_condition *name_condition; int layer; int desk; int screen; int placed_by_button_mask; int placed_by_button_set_mask; } WindowConditionMask; typedef struct pl_penalty_struct { float normal; float ontop; float icon; float sticky; float below; float strut; } pl_penalty_struct; typedef struct pl_percent_penalty_struct { int p99; int p95; int p85; int p75; } pl_percent_penalty_struct; /* only style.c and add_window.c are allowed to access this struct! */ typedef struct style_flags { common_flags_t common; unsigned do_decorate_transient : 1; /* old placement flags */ #define PLACE_DUMB 0x0 #define PLACE_SMART 0x1 #define PLACE_CLEVER 0x2 #define PLACE_CLEVERNESS_MASK 0x3 #define PLACE_RANDOM 0x4 /* new placements value, try to get a minimal backward compatibility * with the old flags: * Dumb+Active = Manual, * Dumb+Random = Cascade, * Smart+Random = TileCascade, * Smart+Active = TileManual, * Random+Smart+Clever = MINOVERLAP which is the original Clever * placement code, * Active+Smart+Clever = MINOVERLAPPERCENT which is the "new" Clever * placement code and was the original Clever placement code. Now the * original placement code said: * Active/Random+Dumb+Clever = Active/Random+Dumb (with Dumb Clever is * ignored); These represent the not use value: 0x2=Active+Dumb+Clever, * 0x6=Random+Dumb+Clever */ #define PLACE_MANUAL 0x0 #define PLACE_TILEMANUAL 0x1 #define PLACE_MANUAL_B 0x2 #define PLACE_MINOVERLAPPERCENT 0x3 #define PLACE_CASCADE 0x4 #define PLACE_TILECASCADE 0x5 #define PLACE_CASCADE_B 0x6 #define PLACE_MINOVERLAP 0x7 #define PLACE_POSITION 0x8 #define PLACE_MASK 0xF unsigned placement_mode : 4; unsigned ewmh_placement_mode : 2; /* see ewmh.h */ #define WS_CR_MOTION_METHOD_AUTO CR_MOTION_METHOD_AUTO #define WS_CR_MOTION_METHOD_USE_GRAV CR_MOTION_METHOD_USE_GRAV #define WS_CR_MOTION_METHOD_STATIC_GRAV CR_MOTION_METHOD_STATIC_GRAV #define WS_CR_MOTION_METHOD_MASK CR_MOTION_METHOD_MASK unsigned ws_cr_motion_method : 2; unsigned do_save_under : 1; unsigned do_start_iconic : 1; unsigned do_start_lowered : 1; unsigned do_start_shaded : 1; unsigned start_shaded_dir : 3; unsigned has_border_width : 1; unsigned has_color_back : 1; unsigned has_color_fore : 1; unsigned has_color_back_hi : 1; unsigned has_color_fore_hi : 1; unsigned has_decor : 1; unsigned has_edge_delay_ms_move : 1; unsigned has_edge_delay_ms_resize : 1; unsigned has_edge_resistance_move : 1; unsigned has_edge_resistance_xinerama_move : 1; unsigned has_handle_width : 1; unsigned has_icon : 1; unsigned has_icon_boxes : 1; unsigned has_icon_size_limits : 1; unsigned has_min_window_size : 1; unsigned has_max_window_size : 1; unsigned has_icon_background_padding : 1; unsigned has_icon_background_relief : 1; unsigned has_icon_title_relief : 1; unsigned has_window_shade_steps : 1; unsigned has_mini_icon : 1; unsigned has_mwm_decor : 1; unsigned has_mwm_functions : 1; unsigned has_no_handles : 1; unsigned has_no_title : 1; unsigned has_ol_decor : 1; unsigned has_snap_grid : 1; unsigned has_snap_attraction : 1; #if 0 unsigned has_condition_mask : 1; #endif unsigned is_button_disabled : NUMBER_OF_TITLE_BUTTONS; unsigned is_unmanaged : 1; #define BACKINGSTORE_DEFAULT 0 #define BACKINGSTORE_ON 1 #define BACKINGSTORE_OFF 2 #define BACKINGSTORE_MASK 0x3 unsigned use_backing_store : 2; unsigned use_parent_relative : 1; unsigned use_colorset : 1; unsigned use_colorset_hi : 1; unsigned use_border_colorset : 1; unsigned use_border_colorset_hi : 1; unsigned use_icon_title_colorset : 1; unsigned use_icon_title_colorset_hi : 1; unsigned use_icon_background_colorset : 1; unsigned use_layer : 1; unsigned use_no_pposition : 1; unsigned use_no_usposition : 1; unsigned use_no_transient_pposition : 1; unsigned use_no_transient_usposition : 1; unsigned use_start_on_desk : 1; unsigned use_start_on_page_for_transient : 1; unsigned use_start_on_screen : 1; unsigned manual_placement_honors_starts_on_page : 1; unsigned um_placement_honors_starts_on_page : 1; unsigned capture_honors_starts_on_page : 1; unsigned recapture_honors_starts_on_page : 1; unsigned has_placement_penalty : 1; unsigned has_placement_percentage_penalty : 1; unsigned has_placement_position_string : 1; unsigned has_initial_map_command_string : 1; unsigned has_title_format_string : 1; unsigned has_icon_title_format_string : 1; } style_flags; typedef struct style_id_t { char *name; XID window_id; struct { unsigned has_name:1; unsigned has_window_id:1; } flags; } style_id_t; typedef struct snap_attraction_t { /* attractiveness of window edges */ int proximity; /* mode of snap attraction */ int mode; /* mode flags to do bit manipulation */ enum { SNAP_NONE = 0x00, SNAP_WINDOWS = 0x01, SNAP_ICONS = 0x02, SNAP_SAME = 0x04, SNAP_SCREEN = 0x08, SNAP_SCREEN_WINDOWS = 0x10, SNAP_SCREEN_ICONS = 0x20, SNAP_SCREEN_ALL = 0x40, } types; } snap_attraction_t; /* only style.c and add_window.c are allowed to access this struct! */ typedef struct window_style { struct window_style *next; struct window_style *prev; style_id_t id; #if 0 WindowConditionMask *condition_mask; #endif char *icon_name; char *mini_icon_name; char *decor_name; unsigned char min_icon_width; unsigned char max_icon_width; unsigned char min_icon_height; unsigned char max_icon_height; #define ICON_RESIZE_TYPE_NONE 0x0 #define ICON_RESIZE_TYPE_STRETCHED 0x1 #define ICON_RESIZE_TYPE_ADJUSTED 0x2 #define ICON_RESIZE_TYPE_SHRUNK 0x3 #define ICON_RESIZE_TYPE_MASK 0x3 unsigned icon_resize_type : 2; unsigned char icon_background_padding; signed char icon_background_relief; signed char icon_title_relief; char *icon_font; char *window_font; char *fore_color_name; char *back_color_name; char *fore_color_name_hi; char *back_color_name_hi; int colorset; int colorset_hi; int border_colorset; int border_colorset_hi; int icon_title_colorset; int icon_title_colorset_hi; int icon_background_colorset; short border_width; /* resize handle width */ short handle_width; int layer; int start_desk; int start_page_x; int start_page_y; int start_screen; int min_window_width; int min_window_height; int max_window_width; int max_window_height; int shade_anim_steps; #if 1 /*!!!*/ snap_attraction_t snap_attraction; /* snap grid size */ int snap_grid_x; int snap_grid_y; int edge_delay_ms_move; int edge_delay_ms_resize; int edge_resistance_move; int edge_resistance_xinerama_move; #endif icon_boxes *icon_boxes; float norm_placement_penalty; pl_penalty_struct pl_penalty; pl_percent_penalty_struct pl_percent_penalty; char *pl_position_string; char *initial_map_command_string; char *title_format_string; char *icon_title_format_string; style_flags flags; style_flags flag_default; style_flags flag_mask; style_flags change_mask; unsigned has_style_changed : 1; unsigned has_title_format_string : 1; unsigned has_icon_title_format_string : 1; } window_style; typedef struct window_g { rectangle frame; /* absolute geometry when not maximized */ rectangle normal; /* maximized window geometry */ rectangle max; /* defect between maximized geometry before and after * constraining size. */ size_rect max_defect; /* original delta between normalized and maximized window, * used to keep unmaximized window at same screen position */ position max_offset; } window_g; /* for each window that is on the display, one of these structures * is allocated and linked into a list */ typedef struct FvwmWindow { /* name of the window */ FlocaleNameString name; /* name of the icon */ FlocaleNameString icon_name; char *visible_name; char *visible_icon_name; /* if non-null: Use this instead of any other names for matching styles */ char *style_name; int name_count; int icon_name_count; /* next fvwm window */ struct FvwmWindow *next; /* prev fvwm window */ struct FvwmWindow *prev; /* next (lower) fvwm window in stacking order*/ struct FvwmWindow *stack_next; /* prev (higher) fvwm window in stacking order */ struct FvwmWindow *stack_prev; /* border width before reparenting */ struct { /* the frame window */ Window frame; /* It looks like you HAVE to reparent the app window into a * window whose size = app window, or else you can't keep xv * and matlab happy at the same time! */ Window parent; /* the child window */ Window client; /* the title bar window and button windows */ Window title; Window button_w[NUMBER_OF_TITLE_BUTTONS]; /* sides of the border */ Window sides[4]; /* corner pieces */ Window corners[4]; /* icon title window */ Window icon_title_w; /* icon picture window */ Window icon_pixmap_w; Window transientfor; } wins; window_flags flags; struct { unsigned buttons_drawn : NUMBER_OF_TITLE_BUTTONS; unsigned buttons_lit : NUMBER_OF_TITLE_BUTTONS; unsigned buttons_inverted : NUMBER_OF_TITLE_BUTTONS; unsigned buttons_toggled : NUMBER_OF_TITLE_BUTTONS; unsigned parts_drawn : 12; unsigned parts_lit : 12; unsigned parts_inverted : 12; } decor_state; int nr_left_buttons; int nr_right_buttons; #define BUTTON_INDEX(b) \ (((b) == 0) ? (NUMBER_OF_TITLE_BUTTONS - 1) : ((b) - 1)) struct FvwmDecor *decor; /* is this a shaped window */ int wShaped; Pixmap title_background_pixmap; /* Note: if the type of this variable is changed, do update the * CONFIGARGSNEW macro in module_interface.c, libs/vpacket.h too! */ short boundary_width; short unshaped_boundary_width; short corner_width; short visual_corner_width; /* title font */ FlocaleFont *title_font; /* /Y coordinate to draw the title name */ short title_text_offset; short title_length; /* Note: if the type of this variable is changed, do update the * CONFIGARGSNEW macro in module_interface.c, libs/vpacket.h and too! */ short title_thickness; rotation_t title_text_rotation; struct { /* geometry of the icon picture window */ rectangle picture_w_g; /* geometry of the icon title window */ rectangle title_w_g; /* width of the text in the icon title */ int title_text_width; } icon_g; short icon_border_width; /* Drawable depth for the icon */ int iconDepth; /* pixmap for the icon */ Pixmap iconPixmap; /* pixmap for the icon mask */ Pixmap icon_maskPixmap; Pixmap icon_alphaPixmap; int icon_nalloc_pixels; Pixel *icon_alloc_pixels; int icon_no_limit; FlocaleFont *icon_font; /* some parts of the window attributes */ struct { int backing_store; int border_width; int depth; int bit_gravity; unsigned is_bit_gravity_stored : 1; Visual *visual; Colormap colormap; } attr_backup; /* normal hints */ XSizeHints hints; struct { int width_inc; int height_inc; } orig_hints; /* WM hints */ XWMHints *wmhints; XClassHint class; /* Tells which desktop this window is on */ /* Note: if the type of this variable is changed, do update the * CONFIGARGSNEW macro in module_interface.c, libs/vpacket.h and too! */ int Desk; /* Where (if at all) was it focused */ int FocusDesk; /* Desk to deiconify to, for StubbornIcons */ int DeIconifyDesk; char *mini_pixmap_file; FvwmPicture *mini_icon; char *icon_bitmap_file; struct window_g g; long *mwm_hints; int ol_hints; int functions; /* Colormap windows property */ Window *cmap_windows; /* Should generally be 0 */ int number_cmap_windows; color_quad colors; color_quad hicolors; color_quad border_colors; color_quad border_hicolors; int cs; int cs_hi; int border_cs; int border_cs_hi; int icon_title_cs; int icon_title_cs_hi; int icon_background_cs; unsigned long buttons; /* zero or more iconboxes */ icon_boxes *IconBoxes; int default_layer; /* Note: if the type of this variable is changed, do update the * CONFIGARGSNEW macro in module_interface.c, libs/vpacket.h and too! */ int layer; unsigned char min_icon_width; unsigned char max_icon_width; unsigned char min_icon_height; unsigned char max_icon_height; unsigned short icon_resize_type; unsigned char icon_background_padding; char icon_background_relief; char icon_title_relief; int min_window_width; int min_window_height; int max_window_width; int max_window_height; int shade_anim_steps; unsigned char grabbed_buttons; #if 1 /*!!!*/ snap_attraction_t snap_attraction; /* snap grid size */ int snap_grid_x; int snap_grid_y; int edge_delay_ms_move; int edge_delay_ms_resize; int edge_resistance_move; int edge_resistance_xinerama_move; #endif #define FM_NO_INPUT 0 #define FM_PASSIVE 1 #define FM_LOCALLY_ACTIVE 2 #define FM_GLOBALLY_ACTIVE 3 unsigned char focus_model; pl_penalty_struct pl_penalty; pl_percent_penalty_struct pl_percent_penalty; unsigned char placed_by_button; #define EWMH_WINDOW_TYPE_NONE_ID 0 #define EWMH_WINDOW_TYPE_DESKTOP_ID 1 #define EWMH_WINDOW_TYPE_DIALOG_ID 2 #define EWMH_WINDOW_TYPE_DOCK_ID 3 #define EWMH_WINDOW_TYPE_MENU_ID 4 #define EWMH_WINDOW_TYPE_NORMAL_ID 5 #define EWMH_WINDOW_TYPE_TOOLBAR_ID 6 #define EWMH_WINDOW_TYPE_NOTIFICATION_ID 7 /* Note: if the type of this variable is changed, do update the * CONFIGARGSNEW macro in module_interface.c, libs/vpacket.h and too! */ int ewmh_window_type; /* icon geometry */ rectangle ewmh_icon_geometry; /* for computing the working area */ ewmh_strut strut; /* for the dynamic working area */ ewmh_strut dyn_strut; /* memories for the icons we set on the */ int ewmh_icon_height; /* _NET_WM_ICON */ int ewmh_icon_width; int ewmh_mini_icon_height; int ewmh_mini_icon_width; /* memory for the initial _NET_WM_STATE */ /* Note: if the type of this variable is changed, do update the * CONFIGARGSNEW macro in module_interface.c, libs/vpacket.h and too! */ int ewmh_hint_layer; int ewmh_normal_layer; /* for restoring non ewmh layer */ /* memory for the initial _NET_WM_STATE */ unsigned long ewmh_hint_desktop; /* For the purposes of restoring attributes before/after a window goes * into fullscreen. */ struct { struct window_g g; int is_iconified; int is_shaded; int was_maximized; } fullscreen; /* multi purpose scratch structure */ struct { void *p; int i; } scratch; } FvwmWindow; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ void SetMWM_INFO(Window window); void fvmm_deinstall_signals(void); #endif /* FVWM_H */ fvwm-2.7.0/fvwm/module_list.c0000644000175000017500000006701414147024700013072 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ #include "config.h" #include #ifdef HAVE_FCNTL_H #include #endif /* for F_CMD_ARGS */ #include "fvwm/fvwm.h" #include "execcontext.h" /* end of for CMD_ARGS */ /*for debug message*/ #include "fvwm.h" #include "misc.h" /* end of for debug message */ /* for get_current_read_file */ #include "read.h" /* for busy cursor */ #include "cursor.h" /* for Scr global */ #include "screen.h" #include "externs.h" /* for module syncronous */ #include "libs/ftime.h" #include "libs/System.c" #include "libs/envvar.h" #include "libs/Parse.h" #include "libs/Strings.h" #include "libs/wild.h" #include "libs/fvwmsignal.h" #include "events.h" #include "bindings.h" /* for positive write */ #include "module_list.h" #include "module_interface.h" /* * Use POSIX behaviour if we can, otherwise use SysV instead * should this be here? */ #ifndef O_NONBLOCK # define O_NONBLOCK O_NDELAY #endif #define MOD_NOGRABMASK(m) ((m)->xNoGrabMask) #define MOD_SYNCMASK(m) ((m)->xSyncMask) typedef struct { unsigned long *data; int size; int done; } mqueue_object_type; /* the linked list pointers to the first and last modules */ static fmodule_list module_list = NULL; /* keep to-be-deleted modules in a deathrow until they are deleted safely. */ static fmodule_list death_row = NULL; /* * static functions */ static fmodule *module_alloc(void); static void module_free(fmodule *module); /* * list handling functions */ static inline void module_list_insert(fmodule *module, fmodule_list *list); static inline fmodule *module_list_remove(fmodule *module, fmodule_list *list); static inline void module_list_destroy(fmodule_list *list); static void KillModuleByName(char *name, char *alias); static char *get_pipe_name(fmodule *module); static void DeleteMessageQueueBuff(fmodule *module); static inline void msg_mask_set( msg_masks_t *msg_mask, unsigned long m1, unsigned long m2); static void set_message_mask(msg_masks_t *mask, unsigned long msg); void module_kill_all(void) { module_list_destroy(&module_list); return; } static fmodule *module_alloc(void) { fmodule *module; module = (fmodule *)safemalloc(sizeof(fmodule)); MOD_SET_CMDLINE(module, 0); MOD_READFD(module) = -1; MOD_WRITEFD(module) = -1; fqueue_init(&MOD_PIPEQUEUE(module)); msg_mask_set(&MOD_PIPEMASK(module), DEFAULT_MASK, DEFAULT_MASK); msg_mask_set(&MOD_NOGRABMASK(module), 0, 0); msg_mask_set(&MOD_SYNCMASK(module), 0, 0); MOD_NAME(module) = NULL; MOD_ALIAS(module) = NULL; return module; } /* closes the pipes and frees every data associated with a module record */ static void module_free(fmodule *module) { if (module == NULL) { return; } close(MOD_WRITEFD(module)); close(MOD_READFD(module)); if (MOD_NAME(module) != NULL) { free(MOD_NAME(module)); } if (MOD_ALIAS(module) != NULL) { free(MOD_ALIAS(module)); } while (!FQUEUE_IS_EMPTY(&(MOD_PIPEQUEUE(module)))) { DeleteMessageQueueBuff(module); } free(module); return; } static inline void module_list_insert(fmodule *module, fmodule_list *list) { fmodule_store *new_store; DBUG("module_list_insert", "inserting module"); if (module == NULL) { return; } new_store = (fmodule_store*)safemalloc(sizeof(fmodule_store)); new_store->module = module; new_store->next = *list; *list = new_store; return; } static inline fmodule *module_list_remove(fmodule *module, fmodule_list *list) { fmodule_store **position; if (module == NULL) { return NULL; } for ( position = list; *position != NULL; position = &((*position)->next)) { if ((*position)->module == module) { /* found it */ fmodule_store *current; DBUG("module_list_remove", "Removing from module list"); current = *position; *position = (*position)->next; free(current); return module; } } /* module not found */ DBUG("module_list_remove", "Tried to remove a not listed module!"); return NULL; } static inline void module_list_destroy(fmodule_list *list) { fmodule_store *current; fmodule_store *next; for (current = *list; current != NULL; current = next) { next = current->next; module_free(current->module); free(current); } *list = NULL; return; } static fmodule *do_execute_module( F_CMD_ARGS, Bool desperate, Bool do_listen_only) { int fvwm_to_app[2], app_to_fvwm[2]; int i, val, nargs = 0; char *cptr = NULL; char **args = NULL; char *arg1 = NULL; char arg2[20]; char arg3[20]; char arg5[20]; char arg6[20]; char *token; extern char *ModulePath; Window win; FvwmWindow * const fw = exc->w.fw; fmodule *module; fvwm_to_app[0] = -1; fvwm_to_app[1] = -1; app_to_fvwm[1] = -1; app_to_fvwm[0] = -1; args = (char **)safemalloc(7 * sizeof(char *)); /* Olivier: Why ? */ /* if (eventp->type != KeyPress) */ /* UngrabEm(); */ if (action == NULL) { goto err_exit; } if (fw) { win = FW_W(fw); } else { win = None; } action = GetNextToken(action, &cptr); if (!cptr) { goto err_exit; } arg1 = searchPath(ModulePath, cptr, EXECUTABLE_EXTENSION, X_OK); if (arg1 == NULL) { /* If this function is called in 'desparate' mode this means * fvwm is trying a module name as a last resort. In this case * the error message is inappropriate because it was most * likely a typo in a command, not a module name. */ if (!desperate) { fvwm_msg( ERR, "executeModule", "No such module '%s' in ModulePath '%s'", cptr, ModulePath); } goto err_exit; } #ifdef REMOVE_EXECUTABLE_EXTENSION { char *p; p = arg1 + strlen(arg1) - strlen(EXECUTABLE_EXTENSION); if (strcmp(p, EXECUTABLE_EXTENSION) == 0) { *p = 0; } } #endif /* I want one-ended pipes, so I open two two-ended pipes, * and close one end of each. I need one ended pipes so that * I can detect when the module crashes/malfunctions */ if (do_listen_only == True) { fvwm_to_app[0] = -1; fvwm_to_app[1] = -1; } else if (pipe(fvwm_to_app) != 0) { fvwm_msg(ERR, "executeModule", "Failed to open pipe"); goto err_exit; } if (pipe(app_to_fvwm) != 0) { fvwm_msg(ERR, "executeModule", "Failed to open pipe2"); goto err_exit; } if ( fvwm_to_app[0] >= fvwmlib_max_fd || fvwm_to_app[1] >= fvwmlib_max_fd || app_to_fvwm[0] >= fvwmlib_max_fd || app_to_fvwm[1] >= fvwmlib_max_fd) { fvwm_msg(ERR, "executeModule", "too many open fds"); goto err_exit; } /* all ok, create the space and fill up */ module = module_alloc(); MOD_NAME(module) = stripcpy(cptr); free(cptr); sprintf(arg2, "%d", app_to_fvwm[1]); sprintf(arg3, "%d", fvwm_to_app[0]); sprintf(arg5, "%lx", (unsigned long)win); sprintf(arg6, "%lx", (unsigned long)exc->w.wcontext); args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = (char *)get_current_read_file(); if (!args[3]) { args[3] = "none"; } args[4] = arg5; args[5] = arg6; for (nargs = 6; action = GetNextToken(action, &token), token; nargs++) { args = (char **)saferealloc( (void *)args, (nargs + 2) * sizeof(char *)); args[nargs] = token; if (MOD_ALIAS(module) == NULL) { const char *ptr = skipModuleAliasToken(args[nargs]); if (ptr && *ptr == '\0') { MOD_ALIAS(module) = stripcpy(args[nargs]); } } } args[nargs] = NULL; /* Try vfork instead of fork. The man page says that vfork is better! */ /* Also, had to change exit to _exit() */ /* Not everyone has vfork! */ val = fork(); if (val > 0) { /* This fork remains running fvwm */ /* close appropriate descriptors from each pipe so * that fvwm will be able to tell when the app dies */ close(app_to_fvwm[1]); /* dont't care that this may be -1 */ close(fvwm_to_app[0]); /* add these pipes to fvwm's active pipe list */ MOD_WRITEFD(module) = fvwm_to_app[1]; MOD_READFD(module) = app_to_fvwm[0]; msg_mask_set( &MOD_PIPEMASK(module), DEFAULT_MASK, DEFAULT_MASK); free(arg1); if (DoingCommandLine) { /* add to the list of command line modules */ DBUG("executeModule", "starting commandline module\n"); MOD_SET_CMDLINE(module, 1); } /* make the PositiveWrite pipe non-blocking. Don't want to jam * up fvwm because of an uncooperative module */ if (MOD_WRITEFD(module) >= 0) { fcntl(MOD_WRITEFD(module), F_SETFL, O_NONBLOCK); } /* Mark the pipes close-on exec so other programs * won`t inherit them */ if (fcntl(MOD_READFD(module), F_SETFD, 1) == -1) { fvwm_msg( ERR, "executeModule", "module close-on-exec failed"); } if ( MOD_WRITEFD(module) >= 0 && fcntl(MOD_WRITEFD(module), F_SETFD, 1) == -1) { fvwm_msg( ERR, "executeModule", "module close-on-exec failed"); } /* module struct is completed, insert into the list */ module_list_insert(module, &module_list); for (i = 6; i < nargs; i++) { if (args[i] != 0) { free(args[i]); } } } else if (val ==0) { /* this is the child */ /* this fork execs the module */ #ifdef FORK_CREATES_CHILD /* dont't care that this may be -1 */ close(fvwm_to_app[1]); close(app_to_fvwm[0]); #endif fvmm_deinstall_signals(); if (!Pdefault) { char visualid[32]; char colormap[32]; sprintf( visualid, "FVWM_VISUALID=%lx", XVisualIDFromVisual(Pvisual)); flib_putenv("FVWM_VISUALID", visualid); sprintf(colormap, "FVWM_COLORMAP=%lx", Pcmap); flib_putenv("FVWM_COLORMAP", colormap); } else { flib_unsetenv("FVWM_VISUALID"); flib_unsetenv("FVWM_COLORMAP"); } /* Why is this execvp?? We've already searched the module * path! */ execvp(arg1,args); fvwm_msg( ERR, "executeModule", "Execution of module failed: %s", arg1); perror(""); close(app_to_fvwm[1]); /* dont't care that this may be -1 */ close(fvwm_to_app[0]); #ifdef FORK_CREATES_CHILD exit(1); #endif } else { fvwm_msg(ERR, "executeModule", "Fork failed"); free(arg1); for (i = 6; i < nargs; i++) { if (args[i] != 0) { free(args[i]); } } free(args); module_free(module); return NULL; } free(args); return module; err_exit: if (arg1 != NULL) { free(arg1); } if (cptr != NULL) { free(cptr); } if (args != NULL) { free(args); } /* dont't care that these may be -1 */ close(fvwm_to_app[0]); close(fvwm_to_app[1]); close(app_to_fvwm[0]); close(app_to_fvwm[1]); return NULL; } fmodule *executeModuleDesperate(F_CMD_ARGS) { fmodule *m; m = do_execute_module(F_PASS_ARGS, True, False); return m; } void module_kill(fmodule *module) { module_list_insert( module_list_remove(module, &module_list), &death_row); return; } /* free modules in the deathrow */ void module_cleanup(void) { module_list_destroy(&death_row); return; } /* void module_send(fmodule *module, unsigned long *ptr, int size) */ /* This used to be marked "fvwm_inline". I removed this when I added the lockonsend logic. The routine seems too big to want to inline. dje 9/4/98 */ extern int myxgrabcount; /* defined in libs/Grab.c */ extern char *ModuleUnlock; /* defined in libs/Module.c */ void PositiveWrite(fmodule *module, unsigned long *ptr, int size) { extern int moduleTimeout; msg_masks_t mask; if (ptr == NULL) { return; } if (MOD_WRITEFD(module) == -1) { return; } if (!IS_MESSAGE_IN_MASK(&(MOD_PIPEMASK(module)), ptr[1])) { return; } /* a dirty hack to prevent FvwmAnimate triggering during Recapture */ /* would be better to send RecaptureStart and RecaptureEnd messages. */ /* If module is lock on send for iconify message and it's an * iconify event and server grabbed, then return */ mask.m1 = (MOD_NOGRABMASK(module).m1 & MOD_SYNCMASK(module).m1); mask.m2 = (MOD_NOGRABMASK(module).m2 & MOD_SYNCMASK(module).m2); if (IS_MESSAGE_IN_MASK(&mask, ptr[1]) && myxgrabcount != 0) { return; } /* DV: This was once the AddToMessageQueue function. Since it was only * called once, put it in here for better performance. */ { mqueue_object_type *c; c = (mqueue_object_type *)malloc( sizeof(mqueue_object_type) + size); if (c == NULL) { fvwm_msg(ERR, "PositiveWrite", "malloc failed\n"); exit(1); } c->size = size; c->done = 0; c->data = (unsigned long *)(c + 1); memcpy((void*)c->data, (const void*)ptr, size); fqueue_add_at_end(&(MOD_PIPEQUEUE(module)), c); } /* dje, from afterstep, for FvwmAnimate, allows modules to sync with * fvwm. this is disabled when the server is grabbed, otherwise * deadlocks happen. M_LOCKONSEND has been replaced by a separated * mask which defines on which messages the fvwm-to-module * communication need to be lock on send. olicha Nov 13, 1999 */ /* migo (19-Aug-2000): removed !myxgrabcount to sync M_DESTROY_WINDOW */ /* dv (06-Jul-2002): added the !myxgrabcount again. Deadlocks *do* * happen without it. There must be another way to fix * M_DESTROY_WINDOW handling in FvwmEvent. */ /*if (IS_MESSAGE_IN_MASK(&(MOD_SYNCMASK(module)), ptr[1]))*/ if ( IS_MESSAGE_IN_MASK( &(MOD_SYNCMASK(module)), ptr[1]) && !myxgrabcount) { fd_set readSet; int channel = MOD_READFD(module); struct timeval timeout; Bool done = False; fmodule_input *input; FlushMessageQueue(module); while (!done) { int rc = 0; /* * We give the read a long timeout; if the module * fails to respond within this time then it deserves * to be KILLED! * * NOTE: rather than impose an arbitrary timeout on the * user, we will make this a configuration parameter. */ do { timeout.tv_sec = moduleTimeout; timeout.tv_usec = 0; FD_ZERO(&readSet); FD_SET(channel, &readSet); /* Wait for input to arrive on just one * descriptor, with a timeout (fvwmSelect <= 0) * or read() returning wrong size is bad news */ rc = fvwmSelect( channel + 1, &readSet, NULL, NULL, &timeout); /* retry if select() failed with EINTR */ } while (rc < 0 && !isTerminated && (errno == EINTR)); if ( isTerminated ) { break; } if (rc > 0) { input = module_receive(module); if ( input == NULL || module_input_expect(input, ModuleUnlockResponse)) { module_input_discard(input); done = True; } else { module_input_execute(input); } } else { char *name; name = get_pipe_name(module); /* Doh! Something has gone wrong - get rid of * the offender! */ fvwm_msg(ERR, "PositiveWrite", "Failed to read descriptor from" " '%s':\n" "- data available=%c\n" "- terminate signal=%c\n", name, (FD_ISSET(channel, &readSet) ? 'Y' : 'N'), isTerminated ? 'Y' : 'N'); module_kill(module); break; } /* Execute all messages from the module until UNLOCK is * received N.B. This may cause recursion if a command * results in a sync message to another module, which * in turn may send a command that results in another * sync message to this module. * Hippo: I don't think this will cause deadlocks, but * the third time we get here the first times UNLOCK * will be read and then on returning up the third * level UNLOCK will be read at the first level. This * could be difficult to fix without turning queueing * on. Turning queueing on may be bad because it can * be useful for modules to be able to inject commands * from modules in a synchronous manner. e.g. * FvwmIconMan can tell FvwmAnimate to do an animation * when a window is de-iconified from the IconMan, * queueing make s this happen too late. */ } } return; } fmodule_input *module_receive(fmodule *module) { unsigned long size; unsigned long cont; Window win; int n; fmodule_input *input = NULL; n = read(MOD_READFD(module), &win, sizeof(Window)); if (n < sizeof(Window)) { /* exit silently, module should have died.. */ goto err; } n = read(MOD_READFD(module), &size, sizeof(size)); if (n < sizeof(size)) { fvwm_msg( ERR, "module_receive", "Fail to read command size (Module: %p, read: %i, " "size: %i)", module, n, (int)sizeof(size)); goto err; } if (size > MAX_MODULE_INPUT_TEXT_LEN) { fvwm_msg(ERR, "module_receive", "Module(%p) command is too big (%ld), limit is %d", module, size, MAX_MODULE_INPUT_TEXT_LEN); /* The rest of the output from this module is going to be * scrambled so let's kill it rather than risk interpreting * garbage */ goto err; } /* allocate all storage at once */ /* also save space for the '\0' termination character */ input = (fmodule_input *)safemalloc( sizeof(fmodule_input) + sizeof(char)*(size + 1)); input->module = module; input->window = win; input->command = (char*)input + sizeof(fmodule_input); n = read(MOD_READFD(module), input->command, size); if (n < size) { fvwm_msg( ERR, "module_receive", "Fail to read command (Module: %p, read: %i, size:" " %ld)", module, n, size); goto err; } input->command[n] = '\0'; n = read(MOD_READFD(module), &cont, sizeof(cont)); if (n < sizeof(cont)) { fvwm_msg(ERR, "module_receive", "Module %p, Size Problems (read: %d, size: %d)", module, n, (int)sizeof(cont)); goto err; } if (cont == 0) { /* this is documented as a valid way for a module to quit * so let's not complain */ module_kill(module); } return input; err: module_kill(module); module_input_discard(input); return NULL; } /* frees the module input data struct */ void module_input_discard(fmodule_input *input) { if (input==NULL) { return; } free(input); } /* returns true if the module command matches "expect", false otherwise */ Bool module_input_expect(fmodule_input *input, char *expect) { if (input == NULL || input->command == NULL || expect == NULL) { return False; } if (strncasecmp(input->command, expect, strlen(expect)) == 0) { /* the module sent the expected string */ return True; } return False; } void module_list_itr_init(fmodule_list_itr *itr) { *itr = module_list; return; } fmodule *module_list_itr_next(fmodule_list_itr *itr) { fmodule *module; if (*itr == NULL) { return NULL; } module = (*itr)->module; *itr = (*itr)->next; return module; } static void KillModuleByName(char *name, char *alias) { fmodule_list_itr moditr; fmodule *module; if (name == NULL) { return; } module_list_itr_init(&moditr); while ( (module = module_list_itr_next(&moditr)) != NULL) { if ( MOD_NAME(module) != NULL && matchWildcards(name, MOD_NAME(module)) && (!alias || ( MOD_ALIAS(module) && matchWildcards(alias, MOD_ALIAS(module))))) { module_kill(module); } } return; } static char *get_pipe_name(fmodule *module) { char *name=""; if (MOD_NAME(module) != NULL) { if (MOD_ALIAS(module) != NULL) { name = CatString3( MOD_NAME(module), " ", MOD_ALIAS(module)); } else { name = MOD_NAME(module); } } else { name = CatString3("(null)", "", ""); } return name; } /* * returns a pointer inside a string (just after the alias) if ok or NULL */ char *skipModuleAliasToken(const char *string) { #define is_valid_first_alias_char(ch) (isalpha(ch) || (ch) == '/') #define is_valid_alias_char(ch) (is_valid_first_alias_char(ch) \ || isalnum(ch) || (ch) == '-' || \ (ch) == '.' || (ch) == '/') if (is_valid_first_alias_char(*string)) { int len = 1; string++; while (*string && is_valid_alias_char(*string)) { if (++len > MAX_MODULE_ALIAS_LEN) { return NULL; } string++; } return (char *)string; } return NULL; #undef is_valid_first_alias_char #undef is_valid_alias_char } /* message mask handling - does this belong here? */ static inline void msg_mask_set( msg_masks_t *msg_mask, unsigned long m1, unsigned long m2) { msg_mask->m1 = m1; msg_mask->m2 = m2; return; } /* * Sets the mask to the specific value. If M_EXTENDED_MSG is set in mask, the * function operates only on the extended messages, otherwise it operates only * on normal messages. */ static void set_message_mask(msg_masks_t *mask, unsigned long msg) { if (msg & M_EXTENDED_MSG) { mask->m2 = (msg & ~M_EXTENDED_MSG); } else { mask->m1 = msg; } return; } /* message queues */ static void DeleteMessageQueueBuff(fmodule *module) { mqueue_object_type *obj; if (fqueue_get_first(&(MOD_PIPEQUEUE(module)), (void **)&obj) == 1) { /* remove from queue */ fqueue_remove_or_operate_from_front( &(MOD_PIPEQUEUE(module)), NULL, NULL, NULL, NULL); /* we don't need to free the obj->data here because it's in the * same malloced block as the obj itself. */ free(obj); } return; } void FlushMessageQueue(fmodule *module) { extern int moduleTimeout; mqueue_object_type *obj; char *dptr; int a; if (module == NULL) { return; } while (fqueue_get_first(&(MOD_PIPEQUEUE(module)), (void **)&obj) == 1) { dptr = (char *)obj->data; while (obj->done < obj->size) { a = write(MOD_WRITEFD(module), &dptr[obj->done], obj->size - obj->done); if (a >=0) { obj->done += a; } /* the write returns EWOULDBLOCK or EAGAIN if the pipe * is full. (This is non-blocking I/O). SunOS returns * EWOULDBLOCK, OSF/1 returns EAGAIN under these * conditions. Hopefully other OSes return one of these * values too. Solaris 2 doesn't seem to have a man * page for write(2) (!) */ else if (errno == EWOULDBLOCK || errno == EAGAIN) { fd_set writeSet; struct timeval timeout; int channel = MOD_WRITEFD(module); int rc = 0; do { /* Wait until the pipe accepts further * input */ timeout.tv_sec = moduleTimeout; timeout.tv_usec = 0; FD_ZERO(&writeSet); FD_SET(channel, &writeSet); rc = fvwmSelect( channel + 1, NULL, &writeSet, NULL, &timeout); /* retry if select() failed with EINTR */ } while ((rc < 0) && !isTerminated && (errno == EINTR)); if ( isTerminated ) { return; } if (!FD_ISSET(channel, &writeSet)) { char *name; name = get_pipe_name(module); /* Doh! Something has gone wrong - get * rid of the offender! */ fvwm_msg( ERR, "FlushMessageQueue", "Failed to write descriptor to" " '%s':\n" "- select rc=%d\n" "- terminate signal=%c\n", name, rc, isTerminated ? 'Y' : 'N'); module_kill(module); return; } /* pipe accepts further input; continue */ continue; } else if (errno != EINTR) { module_kill(module); return; } } DeleteMessageQueueBuff(module); } return; } void FlushAllMessageQueues(void) { fmodule_list_itr moditr; fmodule *module; module_list_itr_init(&moditr); while ( (module = module_list_itr_next(&moditr)) != NULL) { FlushMessageQueue(module); } return; } /* empty, only here so that the signal handling initialization code is the * same for modules and fvwm */ RETSIGTYPE DeadPipe(int sig) { SIGNAL_RETURN; } void CMD_Module(F_CMD_ARGS) { do_execute_module(F_PASS_ARGS, False, False); return; } void CMD_ModuleListenOnly(F_CMD_ARGS) { do_execute_module(F_PASS_ARGS, False, True); return; } void CMD_KillModule(F_CMD_ARGS) { char *name; char *alias = NULL; action = GetNextToken(action,&name); if (!name) { return; } GetNextToken(action, &alias); KillModuleByName(name, alias); free(name); if (alias) { free(alias); } return; } void CMD_ModuleSynchronous(F_CMD_ARGS) { int sec = 0; char *next; char *token; char *expect = ModuleFinishedStartupResponse; fmodule *module; fd_set in_fdset; fd_set out_fdset; time_t start_time; Bool done = False; Bool need_ungrab = False; char *escape = NULL; XEvent tmpevent; if (!action) { return; } token = PeekToken(action, &next); if (StrEquals(token, "expect")) { token = PeekToken(next, &next); if (token) { expect = alloca(strlen(token) + 1); strcpy(expect, token); } action = next; token = PeekToken(action, &next); } if (token && StrEquals(token, "timeout")) { if (GetIntegerArguments(next, &next, &sec, 1) > 0 && sec > 0) { /* we have a delay, skip the number */ action = next; } else { fvwm_msg(ERR, "executeModuleSync", "illegal timeout"); return; } } if (!action) { /* no module name */ return; } module = do_execute_module(F_PASS_ARGS, False, False); if (module == NULL) { /* executing the module failed, just return */ return; } /* Busy cursor stuff */ if (Scr.BusyCursor & BUSY_MODULESYNCHRONOUS) { if (GrabEm(CRS_WAIT, GRAB_BUSY)) need_ungrab = True; } /* wait for module input */ start_time = time(NULL); while (!done) { struct timeval timeout; int num_fd; /* A signal here could interrupt the select call. We would * then need to restart our select, unless the signal was * a "terminate" signal. Note that we need to reinitialise * all of select's parameters after it has returned. */ do { FD_ZERO(&in_fdset); FD_ZERO(&out_fdset); FD_SET(MOD_READFD(module), &in_fdset); if (!FQUEUE_IS_EMPTY(&MOD_PIPEQUEUE(module))) { FD_SET(MOD_WRITEFD(module), &out_fdset); } timeout.tv_sec = 0; timeout.tv_usec = 1; num_fd = fvwmSelect( fvwmlib_max_fd, &in_fdset, &out_fdset, 0, &timeout); } while (num_fd < 0 && !isTerminated); /* Exit if we have received a "terminate" signal */ if (isTerminated) { break; } if (num_fd > 0) { if (FD_ISSET(MOD_READFD(module), &in_fdset)) { fmodule_input * input; /* Check for module input. */ input = module_receive(module); if ( input == NULL || module_input_expect(input,expect)) { module_input_discard(input); done = True; } else { module_input_execute(input); } } if ((MOD_WRITEFD(module) >= 0) && FD_ISSET(MOD_WRITEFD(module), &out_fdset)) { FlushMessageQueue(module); } } usleep(1000); if (difftime(time(NULL), start_time) >= sec && sec) { /* timeout */ done = True; } /* Check for "escape function" */ if (FPending(dpy) && FCheckMaskEvent(dpy, KeyPressMask, &tmpevent)) { int context; XClassHint *class; char *name; Window w; context = GetContext( NULL, exc->w.fw, &tmpevent, &w); if (exc->w.fw != NULL) { class = &(exc->w.fw->class); name = exc->w.fw->name.name; } else { class = NULL; name = NULL; } escape = CheckBinding( Scr.AllBindings, STROKE_ARG(0) tmpevent.xkey.keycode, tmpevent.xkey.state, GetUnusedModifiers(), context, BIND_KEYPRESS, class, name); if (escape != NULL) { if (!strcasecmp(escape,"escapefunc")) { done = True; } } } } /* while */ if (need_ungrab) { UngrabEm(GRAB_BUSY); } return; } /* mask handling - does this belong here? */ void CMD_set_mask(F_CMD_ARGS) { unsigned long val; if (exc->m.module == NULL) { return; } if (!action || sscanf(action, "%lu", &val) != 1) { val = 0; } set_message_mask(&(MOD_PIPEMASK(exc->m.module)), (unsigned long)val); return; } void CMD_set_sync_mask(F_CMD_ARGS) { unsigned long val; if (exc->m.module == NULL) { return; } if (!action || sscanf(action,"%lu",&val) != 1) { val = 0; } set_message_mask(&(MOD_SYNCMASK(exc->m.module)), (unsigned long)val); return; } void CMD_set_nograb_mask(F_CMD_ARGS) { unsigned long val; if (exc->m.module == NULL) { return; } if (!action || sscanf(action,"%lu",&val) != 1) { val = 0; } set_message_mask(&(MOD_NOGRABMASK(exc->m.module)), (unsigned long)val); return; } fvwm-2.7.0/fvwm/eventhandler.h0000644000175000017500000000356514147024700013237 00000000000000/* -*-c-*- */ #ifndef EVENTHANDLER_H #define EVENTHANDLER_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ typedef struct { const exec_context_t *exc; } evh_args_t; /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ /* ---------------------------- event handlers ----------------------------- */ void HandleEvents(void); void HandleExpose(const evh_args_t *ea); void HandleFocusIn(const evh_args_t *ea); void HandleFocusOut(const evh_args_t *ea); void HandleDestroyNotify(const evh_args_t *ea); void HandleMapRequest(const evh_args_t *ea); void HandleMapRequestKeepRaised( const evh_args_t *ea, Window KeepRaised, FvwmWindow *ReuseWin, initial_window_options_t *win_opts); void HandleMapNotify(const evh_args_t *ea); void HandleUnmapNotify(const evh_args_t *ea); void HandleMotionNotify(const evh_args_t *ea); void HandleButtonRelease(const evh_args_t *ea); void HandleButtonPress(const evh_args_t *ea); void HandleEnterNotify(const evh_args_t *ea); void HandleLeaveNotify(const evh_args_t *ea); void HandleConfigureRequest(const evh_args_t *ea); void HandleClientMessage(const evh_args_t *ea); void HandlePropertyNotify(const evh_args_t *ea); void HandleKeyPress(const evh_args_t *ea); void HandleKeyRelease(const evh_args_t *ea); void HandleVisibilityNotify(const evh_args_t *ea); STROKE_CODE(void HandleButtonRelease(const evh_args_t *ea)); STROKE_CODE(void HandleMotionNotify(const evh_args_t *ea)); #endif /* EVENTHANDLER_H */ fvwm-2.7.0/fvwm/update.h0000644000175000017500000000364214147024700012036 00000000000000/* -*-c-*- */ #ifndef _UPDATE_ #define _UPDATE_ /* Ipmortant not: All the flags below must have a positive syntax. If a flag * is set, this indicates that something has to happen with the window. */ typedef struct { unsigned do_broadcast_focus : 1; unsigned do_redecorate : 1; unsigned do_redecorate_transient : 1; unsigned do_redraw_decoration : 1; unsigned do_redraw_icon : 1; unsigned do_refresh : 1; unsigned do_resize_window : 1; unsigned do_setup_focus_policy : 1; unsigned do_setup_frame : 1; unsigned do_update_cr_motion_method : 1; unsigned do_update_ewmh_allowed_actions : 1; unsigned do_update_ewmh_icon : 1; unsigned do_update_ewmh_mini_icon : 1; unsigned do_update_ewmh_stacking_hints : 1; unsigned do_update_ewmh_state_hints : 1; unsigned do_update_frame_attributes : 1; unsigned do_update_icon : 1; unsigned do_update_icon_background_cs : 1; unsigned do_update_icon_boxes : 1; unsigned do_update_icon_font : 1; unsigned do_update_icon_placement : 1; unsigned do_update_icon_size_limits : 1; unsigned do_update_icon_title : 1; unsigned do_update_icon_title_cs : 1; unsigned do_update_icon_title_cs_hi : 1; unsigned do_update_mini_icon : 1; unsigned do_update_layer : 1; unsigned do_update_modules_flags : 1; unsigned do_update_placement_penalty : 1; unsigned do_update_rotated_title : 1; unsigned do_update_stick : 1; unsigned do_update_stick_icon : 1; unsigned do_update_title_dir : 1; unsigned do_update_title_text_dir : 1; unsigned do_update_visible_icon_name : 1; unsigned do_update_visible_window_name : 1; unsigned do_update_window_color : 1; unsigned do_update_window_color_hi : 1; unsigned do_update_window_font : 1; unsigned do_update_window_font_height : 1; unsigned do_update_window_grabs : 1; unsigned do_update_working_area : 1; } update_win; void destroy_scheduled_windows(void); void apply_decor_change(FvwmWindow *fw); void flush_window_updates(void); #endif /* _UPDATE_ */ fvwm-2.7.0/fvwm/builtins.h0000644000175000017500000000061114147024676012412 00000000000000/* -*-c-*- */ #ifndef BUILTINS_H #define BUILTINS_H void refresh_window(Window w, Bool window_update); void ApplyDefaultFontAndColors(void); void InitFvwmDecor(FvwmDecor *decor); void reset_decor_changes(void); Bool ReadDecorFace(char *s, DecorFace *df, int button, int verbose); void FreeDecorFace(Display *dpy, DecorFace *df); void update_fvwm_colorset(int cset); #endif /* BUILTINS_H */ fvwm-2.7.0/fvwm/module_interface.h0000644000175000017500000000273214147024700014060 00000000000000/* -*-c-*- */ #ifndef FVWM_MODULE_INTERFACE_H #define FVWM_MODULE_INTERFACE_H #include "libs/Module.h" struct fmodule; struct fmodule_input; /* Packet sending functions */ void BroadcastPacket(unsigned long event_type, unsigned long num_datum, ...); void BroadcastConfig(unsigned long event_type, const FvwmWindow *t); void BroadcastName( unsigned long event_type, unsigned long data1, unsigned long data2, unsigned long data3, const char *name); void BroadcastWindowIconNames(FvwmWindow *t, Bool window, Bool icon); void BroadcastFvwmPicture( unsigned long event_type, unsigned long data1, unsigned long data2, unsigned long data3, FvwmPicture *picture, char *name); void BroadcastPropertyChange( unsigned long argument, unsigned long data1, unsigned long data2, char *string); void BroadcastColorset(int n); void BroadcastConfigInfoString(char *string); void broadcast_xinerama_state(void); void broadcast_ignore_modifiers(void); void SendPacket( struct fmodule *module, unsigned long event_type, unsigned long num_datum, ...); void SendConfig( struct fmodule *module, unsigned long event_type, const FvwmWindow *t); void SendName( struct fmodule *module, unsigned long event_type, unsigned long data1, unsigned long data2, unsigned long data3, const char *name); /* command queue - module input */ void module_input_enqueue(struct fmodule_input *input); void module_input_execute(struct fmodule_input *input); void ExecuteCommandQueue(void); #endif /* MODULE_INTERFACE_H */ fvwm-2.7.0/fvwm/windowshade.c0000644000175000017500000001332614147024700013063 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include "libs/fvwmlib.h" #include "libs/Parse.h" #include "libs/Strings.h" #include "fvwm.h" #include "externs.h" #include "execcontext.h" #include "misc.h" #include "commands.h" #include "screen.h" #include "module_list.h" #include "module_interface.h" #include "geometry.h" #include "ewmh.h" #include "borders.h" #include "frame.h" #include "focus.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ /* ---------------------------- interface functions ------------------------ */ /* ---------------------------- builtin commands --------------------------- */ /* * * WindowShade -- shades or unshades a window (veliaa@rpi.edu) * * Args: 1 -- shade, 2 -- unshade No Arg: toggle * */ void CMD_WindowShade(F_CMD_ARGS) { direction_t shade_dir; int toggle; frame_move_resize_mode resize_mode; rectangle start_g; rectangle end_g; frame_move_resize_args mr_args; char *token; char *naction; Bool do_force_shading; Bool has_dir; FvwmWindow * const fw = exc->w.fw; if (IS_ICONIFIED(fw) || IS_EWMH_FULLSCREEN(fw)) { return; } token = PeekToken(action, &naction); if (StrEquals("shadeagain", token)) { do_force_shading = True; action = naction; token = PeekToken(action, &naction); } else { do_force_shading = False; } /* parse arguments */ if (StrEquals("Last", token)) { /* last given instead of a direction will make * fvwm to reuse the last used shading direction. * A new, nevershaded window will have * USED_TITLE_DIR_FOR_SHADING set (in add_window.c: * setup_window_structure) */ action = naction; if (!USED_TITLE_DIR_FOR_SHADING(fw)) { shade_dir = SHADED_DIR(fw); } else { shade_dir = DIR_NONE; } } else { /* parse normal direction if last was not given */ shade_dir = gravity_parse_dir_argument(action, NULL, -1); } if (shade_dir >= 0 && shade_dir <= DIR_MASK) { has_dir = True; toggle = (!IS_SHADED(fw) || SHADED_DIR(fw) != shade_dir); } else { has_dir = False; toggle = ParseToggleArgument(action, NULL, -1, 0); if (toggle == -1 && GetIntegerArguments(action, NULL, &toggle, 1) > 0) { if (toggle == 1) { toggle = 1; } else if (toggle == 2) { toggle = 0; } else { toggle = -1; } } if (toggle == -1) { toggle = !(IS_SHADED(fw)); } if (!IS_SHADED(fw) && toggle == 1) { shade_dir = GET_TITLE_DIR(fw); } else if (IS_SHADED(fw) && toggle == 0) { shade_dir = SHADED_DIR(fw); } else { shade_dir = -1; } } if (!IS_SHADED(fw) && toggle == 0) { /* nothing to do */ return; } if (IS_SHADED(fw) && toggle == 1) { if (has_dir == False) { /* nothing to do */ return; } else if (do_force_shading == False) { toggle = 0; } else if (shade_dir == SHADED_DIR(fw)) { return; } } if (toggle == 1) { SET_USED_TITLE_DIR_FOR_SHADING(fw, !has_dir); } /* draw the animation */ start_g = fw->g.frame; get_unshaded_geometry(fw, &end_g); if (toggle == 1) { get_shaded_geometry_with_dir(fw, &end_g, &end_g, shade_dir); } resize_mode = (DO_SHRINK_WINDOWSHADE(fw)) ? FRAME_MR_SHRINK : FRAME_MR_SCROLL; mr_args = frame_create_move_resize_args( fw, resize_mode, &start_g, &end_g, fw->shade_anim_steps, shade_dir); frame_move_resize(fw, mr_args); /* Set the new shade value before destroying the args but after the * animation. */ SET_SHADED(fw, toggle); if (toggle == 1) { SET_SHADED_DIR(fw, shade_dir); } frame_free_move_resize_args(fw, mr_args); border_draw_decorations( fw, PART_TITLEBAR, (fw == get_focus_window()) ? True : False, 0, CLEAR_BUTTONS, NULL, NULL); /* update hints and inform modules */ BroadcastConfig(M_CONFIGURE_WINDOW, fw); BroadcastPacket( (toggle == 1) ? M_WINDOWSHADE : M_DEWINDOWSHADE, 3, (long)FW_W(fw), (long)FW_W_FRAME(fw), (unsigned long)fw); FlushAllMessageQueues(); XFlush(dpy); EWMH_SetWMState(fw, False); return; } /* set the number or size of shade animation steps, N => steps, Np => pixels */ void CMD_WindowShadeAnimate(F_CMD_ARGS) { char *buf; if (!action) { action = ""; } fvwm_msg( ERR, "CMD_WindowShadeAnimate", "The WindowShadeAnimate command is obsolete. " "Please use 'Style * WindowShadeSteps %s' instead.", action); buf = safemalloc(strlen(action) + 32); sprintf(buf, "* WindowShadeSteps %s", action); action = buf; CMD_Style(F_PASS_ARGS); free(buf); return; } fvwm-2.7.0/fvwm/stack.c0000644000175000017500000013564514147024700011665 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include #include #include "libs/ftime.h" #include "libs/fvwmlib.h" #include "libs/gravity.h" #include "libs/Grab.h" #include "libs/Parse.h" #include "libs/defaults.h" #include "fvwm.h" #include "externs.h" #include "cursor.h" #include "functions.h" #include "bindings.h" #include "misc.h" #include "screen.h" #include "module_list.h" #include "module_interface.h" #include "focus.h" #include "stack.h" #include "events.h" #include "borders.h" #include "virtual.h" #include "geometry.h" #include "icons.h" #include "ewmh.h" #include "frame.h" /* ---------------------------- local definitions -------------------------- */ /* If more than this many transients are in a single branch of a transient * tree, they will end up in more or less random stacking order. */ #define MAX_TRANSIENTS_IN_BRANCH 200000 /* Same for total levels of transients. */ #define MAX_TRANSIENT_LEVELS 10000 /* This number must fit in a signed int! */ #define LOWER_PENALTY (MAX_TRANSIENTS_IN_BRANCH * MAX_TRANSIENT_LEVELS) /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ typedef enum { SM_RAISE = MARK_RAISE, SM_LOWER = MARK_LOWER, SM_RESTACK = MARK_RESTACK } stack_mode_t; /* ---------------------------- forward declarations ----------------------- */ static void __raise_or_lower_window( FvwmWindow *t, stack_mode_t mode, Bool allow_recursion, Bool is_new_window, Bool is_client_request); static void raise_or_lower_window( FvwmWindow *t, stack_mode_t mode, Bool allow_recursion, Bool is_new_window, Bool is_client_request); #if 0 static void ResyncFvwmStackRing(void); #endif static void ResyncXStackingOrder(void); static void BroadcastRestack(FvwmWindow *s1, FvwmWindow *s2); static Bool is_above_unmanaged(FvwmWindow *fw, Window *umtop); static int collect_transients_recursive( FvwmWindow *t, FvwmWindow *list_head, int layer, stack_mode_t mode, Bool do_include_target_window); /* ---------------------------- local variables ---------------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ #define DEBUG_STACK_RING 1 #ifdef DEBUG_STACK_RING /* debugging function */ static void dump_stack_ring(void) { FvwmWindow *t1; if (!debugging_stack_ring) { return; } XBell(dpy, 0); fprintf(stderr,"dumping stack ring:\n"); for ( t1 = Scr.FvwmRoot.stack_next; t1 != &Scr.FvwmRoot; t1 = t1->stack_next) { fprintf(stderr," l=%d fw=%p f=0x%08x '%s'\n", t1->layer, t1, (int)FW_W_FRAME(t1), t1->name.name); } return; } /* debugging function */ void verify_stack_ring_consistency(void) { Window root, parent, *children; unsigned int nchildren; int i; FvwmWindow *t1, *t2; int last_layer; int last_index; if (!debugging_stack_ring) { return; } XFlush(dpy); t2 = Scr.FvwmRoot.stack_next; if (t2 == &Scr.FvwmRoot) { return; } last_layer = t2->layer; for ( t1 = t2->stack_next; t1 != &Scr.FvwmRoot; t2 = t1, t1 = t1->stack_next) { if (t1->layer > last_layer) { fprintf( stderr, "vsrc: stack ring is corrupt! '%s' (layer %d)" " is above '%s' (layer %d/%d)\n", t1->name.name, t1->layer, t2->name.name, t2->layer, last_layer); dump_stack_ring(); return; } last_layer = t1->layer; } t2 = &Scr.FvwmRoot; for ( t1 = t2->stack_next; t1 != &Scr.FvwmRoot; t2 = t1, t1 = t1->stack_next) { if (t1->stack_prev != t2) { break; } } if (t1 != &Scr.FvwmRoot || t1->stack_prev != t2) { fprintf( stderr, "vsrc: stack ring is corrupt -" " fvwm will probably crash! %p -> %p but %p <- %p", t2, t1, t1->stack_prev, t1); dump_stack_ring(); return; } MyXGrabServer(dpy); if (!XQueryTree(dpy, Scr.Root, &root, &parent, &children, &nchildren)) { MyXUngrabServer(dpy); return; } last_index = nchildren; for ( t1 = Scr.FvwmRoot.stack_next; t1 != &Scr.FvwmRoot; t1 = t1->stack_next) { /* find window in window list */ for ( i = 0; i < nchildren && FW_W_FRAME(t1) != children[i]; i++) { /* nothing to do here */ } if (i == nchildren) { fprintf( stderr,"vsrc: window already died:" " fw=%p w=0x%08x '%s'\n", t1, (int)FW_W_FRAME(t1), t1->name.name); } else if (i >= last_index) { fprintf( stderr, "vsrc: window is at wrong position" " in stack ring: fw=%p f=0x%08x '%s'\n", t1, (int)FW_W_FRAME(t1), t1->name.name); dump_stack_ring(); fprintf(stderr,"dumping X stacking order:\n"); for (i = nchildren; i-- > 0; ) { for ( t1 = Scr.FvwmRoot.stack_next; t1 != &Scr.FvwmRoot; t1 = t1->stack_next) { /* only dump frame windows */ if (FW_W_FRAME(t1) == children[i]) { fprintf( stderr, " f=0x%08x\n", (int)children[i]); break; } } } MyXUngrabServer(dpy); XFree(children); return; } last_index = i; } MyXUngrabServer(dpy); XFree(children); return; } #endif /* Add a whole ring of windows. The list_head itself will not be added. */ static void add_windowlist_to_stack_ring_after( FvwmWindow *list_head, FvwmWindow *add_after_win) { add_after_win->stack_next->stack_prev = list_head->stack_prev; list_head->stack_prev->stack_next = add_after_win->stack_next; add_after_win->stack_next = list_head->stack_next; list_head->stack_next->stack_prev = add_after_win; return; } static FvwmWindow *get_transientfor_top_fvwmwindow(FvwmWindow *t) { FvwmWindow *s; s = t; while (s && IS_TRANSIENT(s) && DO_STACK_TRANSIENT_PARENT(s)) { s = get_transientfor_fvwmwindow(s); if (s) { t = s; } } return t; } /* * Raise a target and all higher fvwm-managed windows above any * override_redirects: * - locate the highest override_redirect above our target * - put all the FvwmWindows from the target to the highest FvwmWindow * below the highest override_redirect in the restack list * - configure our target window above the override_redirect sibling, * and restack. */ static void raise_over_unmanaged(FvwmWindow *t) { int i; Window OR_Above = None; Window *wins; int count = 0; FvwmWindow *t2 = NULL; unsigned int flags; XWindowChanges changes; /* * Locate the highest override_redirect window above our target, and * the highest of our windows below it. * * Count the windows we need to restack, then build the stack list. */ if (!is_above_unmanaged(t, &OR_Above)) { for ( count = 0, t2 = Scr.FvwmRoot.stack_next; t2 != &Scr.FvwmRoot; t2 = t2->stack_next) { count++; count += get_visible_icon_window_count(t2); if (t2 == t) { break; } } if (count > 0) { wins = (Window*) safemalloc (count * sizeof (Window)); for ( i = 0, t2 = Scr.FvwmRoot.stack_next; t2 != &Scr.FvwmRoot; t2 = t2->stack_next) { wins[i++] = FW_W_FRAME(t2); if (IS_ICONIFIED(t2) && ! IS_ICON_SUPPRESSED(t2)) { if (FW_W_ICON_TITLE(t2) != None) { wins[i++] = FW_W_ICON_TITLE(t2); } if (FW_W_ICON_PIXMAP(t2) != None) { wins[i++] = FW_W_ICON_PIXMAP(t2); } } if (t2 == t) { break; } } memset(&changes, '\0', sizeof(changes)); changes.sibling = OR_Above; changes.stack_mode = Above; flags = CWSibling|CWStackMode; XConfigureWindow( dpy, FW_W_FRAME(t)/*topwin*/, flags, &changes); if (i > 1) { XRestackWindows(dpy, wins, i); } free (wins); } }/* end - we found an OR above our target */ return; } static Bool __is_restack_transients_needed( FvwmWindow *t, stack_mode_t mode) { if (DO_RAISE_TRANSIENT(t)) { if (mode == SM_RAISE || mode == SM_RESTACK) { return True; } } if (DO_LOWER_TRANSIENT(t)) { if (mode == SM_LOWER || mode == SM_RESTACK) { return True; } } return False; } static Bool __must_move_transients( FvwmWindow *t, stack_mode_t mode) { if (IS_ICONIFIED(t)) { return False; } /* raise */ if (__is_restack_transients_needed(t, mode) == True) { Bool scanning_above_window = True; FvwmWindow *q; for ( q = Scr.FvwmRoot.stack_next; q != &Scr.FvwmRoot && t->layer <= q->layer; q = q->stack_next) { if (t->layer < q->layer) { /* We're not interested in higher layers. */ continue; } else if (mode == SM_RESTACK && IS_TRANSIENT(q) && FW_W_TRANSIENTFOR(q) == FW_W(t)) { return True; } else if (t == q) { /* We found our window. All further transients * are below it. */ scanning_above_window = False; } else if (IS_TRANSIENT(q) && FW_W_TRANSIENTFOR(q) == FW_W(t)) { return True; } else if (scanning_above_window && mode == SM_RAISE) { /* raise: The window is not raised, so itself * and all transients will be raised. */ return True; } } } return False; } static Window __get_stacking_sibling(FvwmWindow *fw, Bool do_stack_below) { Window w; /* default to frame window */ w = FW_W_FRAME(fw); if (IS_ICONIFIED(fw) && do_stack_below == True) { /* override with icon windows when stacking below */ if (FW_W_ICON_PIXMAP(fw) != None) { w = FW_W_ICON_PIXMAP(fw); } else if (FW_W_ICON_TITLE(fw) != None) { w = FW_W_ICON_TITLE(fw); } } return w; } static void __sort_transient_ring(FvwmWindow *ring) { FvwmWindow *s; FvwmWindow *t; FvwmWindow *u; FvwmWindow *prev; if (ring->stack_next->stack_next == ring) { /* only one or zero windows */ return; } /* Implementation note: this sorting algorithm is about the most * inefficient possible. It just swaps the position of two adjacent * windows in the ring if they are in the wrong order. Since * transient windows are rare, this should not cause any notable * performance hit. Because it is important that the order of windows * with the same key is not changed, we can not just use qsort() here. */ for ( t = ring->stack_next, prev = ring; t->stack_next != ring; prev = t->stack_prev) { s = t->stack_next; if (t->scratch.i < s->scratch.i) { /* swap windows */ u = s->stack_next; s->stack_next = t; t->stack_next = u; u = t->stack_prev; t->stack_prev = s; s->stack_prev = u; s->stack_prev->stack_next = s; t->stack_next->stack_prev = t; if (prev != ring) { /* move further up the ring? */ t = prev; } else { /* hit start of ring */ } } else { /* correct order, advance one window */ t = t->stack_next; } } return; } static void __restack_window_list( FvwmWindow *r, FvwmWindow *s, int count, Bool do_broadcast_all, Bool do_lower) { FvwmWindow *t; unsigned int flags; int i; XWindowChanges changes; Window *wins; int do_stack_above; int is_reversed; if (count <= 0) { for (count = 0, t = r->stack_next; t != s; t = t->stack_next) { count++; count += get_visible_icon_window_count(t); } } /* restack the windows between r and s */ wins = (Window *)safemalloc((count + 3) * sizeof(Window)); for (t = r->stack_next, i = 0; t != s; t = t->stack_next) { if (i > count) { fvwm_msg( ERR, "__restack_window_list", "more transients than expected"); break; } wins[i++] = FW_W_FRAME(t); if (IS_ICONIFIED(t) && !IS_ICON_SUPPRESSED(t)) { if (FW_W_ICON_TITLE(t) != None) { wins[i++] = FW_W_ICON_TITLE(t); } if (FW_W_ICON_PIXMAP(t) != None) { wins[i++] = FW_W_ICON_PIXMAP(t); } } } changes.sibling = __get_stacking_sibling(r, True); if (changes.sibling == None) { changes.sibling = __get_stacking_sibling(s, False); is_reversed = 1; } else { is_reversed = 0; } if (changes.sibling == None) { do_stack_above = !do_lower; flags = CWStackMode; } else { do_stack_above = 0; flags = CWStackMode | CWSibling; } changes.stack_mode = (do_stack_above ^ is_reversed) ? Above : Below; XConfigureWindow(dpy, FW_W_FRAME(r->stack_next), flags, &changes); if (count > 1) { XRestackWindows(dpy, wins, count); } free(wins); EWMH_SetClientListStacking(); if (do_broadcast_all) { /* send out M_RESTACK for all windows, to make sure we don't * forget anything. */ BroadcastRestackAllWindows(); } else { /* send out (one or more) M_RESTACK packets for windows * between r and s */ BroadcastRestack(r, s); } return; } FvwmWindow *__get_window_to_insert_after(FvwmWindow *fw, stack_mode_t mode) { int test_layer; FvwmWindow *s; switch (mode) { case SM_LOWER: test_layer = fw->layer - 1; break; default: case SM_RAISE: case SM_RESTACK: test_layer = fw->layer; break; } for ( s = Scr.FvwmRoot.stack_next; s != &Scr.FvwmRoot; s = s->stack_next) { if (s == fw) { continue; } if (test_layer >= s->layer) { break; } } return s; } static void __mark_group_member( FvwmWindow *fw, FvwmWindow *start, FvwmWindow *end) { FvwmWindow *t; for (t = start; t != end; t = t->stack_next) { if (FW_W(t) == fw->wmhints->window_group || (t->wmhints && (t->wmhints->flags & WindowGroupHint) && t->wmhints->window_group == fw->wmhints->window_group)) { if (IS_IN_TRANSIENT_SUBTREE(t)) { /* have to move this one too */ SET_IN_TRANSIENT_SUBTREE(fw, 1); } } } return; } static Bool __mark_transient_subtree_test( FvwmWindow *s, FvwmWindow *start, FvwmWindow *end, int mark_mode, Bool do_ignore_icons, Bool use_window_group_hint) { Bool use_group_hint = False; FvwmWindow *r; if (IS_IN_TRANSIENT_SUBTREE(s)) { return False; } if (use_window_group_hint && DO_ICONIFY_WINDOW_GROUPS(s) && s->wmhints && (s->wmhints->flags & WindowGroupHint) && (s->wmhints->window_group != None) && (s->wmhints->window_group != FW_W(s)) && (s->wmhints->window_group != Scr.Root)) { use_group_hint = True; } if (!IS_TRANSIENT(s) && !use_group_hint) { return False; } if (do_ignore_icons && IS_ICONIFIED(s)) { return False; } r = (FvwmWindow *)s->scratch.p; if (IS_TRANSIENT(s)) { if (r && IS_IN_TRANSIENT_SUBTREE(r) && ((mark_mode == MARK_ALL) || __is_restack_transients_needed( r, (stack_mode_t)mark_mode) == True)) { /* have to move this one too */ SET_IN_TRANSIENT_SUBTREE(s, 1); /* used for stacking transients */ s->scratch.i += r->scratch.i + 1; return True; } } if (use_group_hint && !IS_IN_TRANSIENT_SUBTREE(s)) { __mark_group_member(s, start, end); if (IS_IN_TRANSIENT_SUBTREE(s)) { /* need another scan through the list */ return True; } } return False; } /* heavaly borrowed from mark_transient_subtree. This will mark a subtree as * long as it is straight, and return true if the operation is succussful. It * will abort and return False as soon as some inconsitance is hit. */ static Bool is_transient_subtree_straight( FvwmWindow *t, int layer, stack_mode_t mode, Bool do_ignore_icons, Bool use_window_group_hint) { FvwmWindow *s; FvwmWindow *start; FvwmWindow *end; int min_i; Bool is_in_gap; int mark_mode; switch (mode) { case SM_RAISE: mark_mode = MARK_RAISE; break; case SM_LOWER: mark_mode = MARK_LOWER; break; default: return False; } if (layer >= 0 && t->layer != layer) { return True; } if (t->stack_prev == NULL || t->stack_next == NULL) { /* the window is not placed correctly in the stack ring * (probably about to be destroyed) */ return False; } /* find out on which windows to operate */ /* iteration are done reverse (bottom up, since that's the way the * transients wil be stacked if all is well */ if (layer >= 0) { /* only work on the given layer */ start = &Scr.FvwmRoot; end = &Scr.FvwmRoot; for ( s = Scr.FvwmRoot.stack_prev; s != &Scr.FvwmRoot && s->layer <= layer; s = s->stack_prev) { if (s->layer == layer) { if (start == &Scr.FvwmRoot) { start = s; } end = s->stack_prev; } } } else { /* work on complete window list */ start = Scr.FvwmRoot.stack_prev; end = &Scr.FvwmRoot; } /* clean the temporary flag in all windows and precalculate the * transient frame windows */ for ( s = Scr.FvwmRoot.stack_next; s != &Scr.FvwmRoot; s = s->stack_next) { SET_IN_TRANSIENT_SUBTREE(s, 0); if (IS_TRANSIENT(s) && (layer < 0 || layer == s->layer)) { s->scratch.p = get_transientfor_fvwmwindow(s); } else { s->scratch.p = NULL; } } /* Indicate that no cleening is needed */ Scr.FvwmRoot.scratch.i = 1; /* now loop over the windows and mark the ones we need to move */ SET_IN_TRANSIENT_SUBTREE(t, 1); min_i = INT_MIN; is_in_gap = False; if (mode == SM_LOWER && t != start) { return False; } /* check that all transients above the window are in a sorted line * with no other windows between them */ for (s = t->stack_prev; s != end && !(is_in_gap && mode == SM_RAISE); s = s->stack_prev) { if ( __mark_transient_subtree_test( s, start, end, mark_mode, do_ignore_icons, use_window_group_hint)) { if (is_in_gap) { return False; } else if (s->scratch.i < min_i) { return False; } min_i = s->scratch.i; } else { is_in_gap = True; } } /* for */ if (is_in_gap && mode == SM_RAISE) { return False; } /* check that there are no transients left beneth the window */ for (s = start; s != t; s = s->stack_prev) { if ( __mark_transient_subtree_test( s, start, end, mark_mode, do_ignore_icons, use_window_group_hint)) { return False; } } return True; } /* function to test if all windows are at correct place from start. */ static Bool __is_restack_needed( FvwmWindow *t, stack_mode_t mode, Bool do_restack_transients, Bool is_new_window) { if (is_new_window) { return True; } else if (t->stack_prev == NULL || t->stack_next == NULL) { /* the window is about to be destroyed, and has been removed * from the stack ring. No need to restack. */ return False; } if (mode == SM_RESTACK) { return True; } if (do_restack_transients) { return !is_transient_subtree_straight( t, t->layer, mode, True, False); } else if (mode == SM_LOWER) { return (t->stack_next != &Scr.FvwmRoot && t->stack_next->layer == t->layer); } else if (mode == SM_RAISE) { return (t->stack_prev != &Scr.FvwmRoot && t->stack_prev->layer == t->layer); } return True; } static Bool __restack_window( FvwmWindow *t, stack_mode_t mode, Bool do_restack_transients, Bool is_new_window, Bool is_client_request) { FvwmWindow *s = NULL; FvwmWindow *r = NULL; FvwmWindow tmp_r; int count; if (!__is_restack_needed( t, mode, do_restack_transients, is_new_window)) { /* need to cancel out the effect of any M_RAISE/M_LOWER that * might already be send out. This is ugly. Better would be to * not send the messages in the first place. */ if (do_restack_transients) { s = t->stack_next; if (s == NULL) { return True; } while (IS_IN_TRANSIENT_SUBTREE(s)) { s = s->stack_next; } BroadcastRestack(t->stack_prev, s); } /* native/unmanaged windows might have raised. However some * buggy clients will keep issuing requests if the raise hacks * are done after processing their requests. */ return is_client_request; } count = 0; if (do_restack_transients) { /* collect the transients in a temp list */ tmp_r.stack_prev = &tmp_r; tmp_r.stack_next = &tmp_r; count = collect_transients_recursive( t, &tmp_r, t->layer, mode, False); if (count == 0) { do_restack_transients = False; } } count += 1 + get_visible_icon_window_count(t); /* now find the place to reinsert t and friends */ if (mode == SM_RESTACK) { s = t->stack_next; } else { s = __get_window_to_insert_after(t, mode); } remove_window_from_stack_ring(t); r = s->stack_prev; if (do_restack_transients) { /* re-sort the transient windows according to their scratch.i * register */ __sort_transient_ring(&tmp_r); /* insert all transients between r and s. */ add_windowlist_to_stack_ring_after(&tmp_r, r); } /* ** Re-insert t - below transients */ add_window_to_stack_ring_after(t, s->stack_prev); if (is_new_window && IS_TRANSIENT(t) && DO_STACK_TRANSIENT_PARENT(t) && !IS_ICONIFIED(t)) { /* now that the new transient is properly positioned in the * stack ring, raise/lower it again so that its parent is * raised/lowered too */ raise_or_lower_window(t, mode, True, False, is_client_request); /* make sure the stacking order is correct - may be the * sledge-hammer method, but the recursion ist too hard to * understand. */ ResyncXStackingOrder(); /* if the transient is on the top of the top layer pan frames * will have ended up under all windows after this. */ return (t->stack_prev != &Scr.FvwmRoot); } else { /* restack the windows between r and s */ __restack_window_list( r, s, count, do_restack_transients, mode == (SM_LOWER) ? True : False); } return False; } static Bool __raise_lower_recursion( FvwmWindow *t, stack_mode_t mode, Bool is_client_request) { FvwmWindow *t2; for ( t2 = Scr.FvwmRoot.stack_next; t2 != &Scr.FvwmRoot; t2 = t2->stack_next) { if (FW_W(t2) == FW_W_TRANSIENTFOR(t)) { if (t2 == t) { return False; } if (IS_ICONIFIED(t2) || t->layer != t2->layer) { break; } if (mode == SM_LOWER && (!IS_TRANSIENT(t2) || !DO_STACK_TRANSIENT_PARENT(t2))) { /* hit the highest level transient; lower this * subtree below all other subtrees of the * same window */ t->scratch.i = -LOWER_PENALTY; } else { /* Add a bonus to the stack ring position for * this branch of the transient tree over all * other branches. */ t->scratch.i = MAX_TRANSIENTS_IN_BRANCH; } __raise_or_lower_window( t2, mode, True, False, is_client_request); if (__is_restack_transients_needed(t2, mode)) { /* moving the parent moves our window already */ return True; } } } return False; } static void __raise_or_lower_window( FvwmWindow *t, stack_mode_t mode, Bool allow_recursion, Bool is_new_window, Bool is_client_request) { FvwmWindow *t2; Bool do_move_transients; /* Do not raise this window after command execution (see * HandleButtonPress()). */ SET_SCHEDULED_FOR_RAISE(t, 0); /* New windows are simply raised/lowered without touching the * transientfor at first. Then, further down in the code, * __raise_or_lower_window() is called again to raise/lower the * transientfor if necessary. We can not do the recursion stuff for * new windows because the __must_move_transients() call needs a * properly ordered stack ring - but the new window is still at the * front of the stack ring. */ if (allow_recursion && !is_new_window && !IS_ICONIFIED(t)) { /* This part makes Raise/Lower on a Transient act on its Main * and sibling Transients. * * The recursion is limited to one level - which caters for * most cases. This code does not handle the case where there * are trees of Main + Transient (i.e. where a * Main_window_with_Transients is itself Transient for another * window). */ if (IS_TRANSIENT(t) && DO_STACK_TRANSIENT_PARENT(t)) { if (__raise_lower_recursion( t, mode, is_client_request) == True) { return; } } } if (is_new_window) { do_move_transients = False; } else { do_move_transients = __must_move_transients(t, mode); } if (__restack_window( t, mode, do_move_transients, is_new_window, is_client_request) == True) { return; } if (mode == SM_RAISE) { /* This hack raises the target and all higher fvwm windows over * any style grabfocusoff override_redirect windows that may be * above it. This is used to cope with ill-behaved applications * that insist on using long-lived override_redirects. */ if (Scr.bo.do_raise_over_unmanaged) { raise_over_unmanaged(t); } /* * The following is a hack to raise X windows over native * windows which is needed for some (all ?) X servers running * under Windows or Windows NT. */ if (Scr.bo.is_raise_hack_needed) { /* RBW - 09/20/1999. I find that trying to raise * unmanaged windows causes problems with some apps. If * this seems to work well for everyone, I'll remove * the #if 0. */ #if 0 /* get *all* toplevels (even including * override_redirects) */ XQueryTree(dpy, Scr.Root, &junk, &junk, &tops, &num); /* raise from fw upwards to get them above NT windows */ for (i = 0; i < num; i++) { if (tops[i] == FW_W_FRAME(t)) { found = True; } if (found) { XRaiseWindow (dpy, tops[i]); } } XFree (tops); #endif for (t2 = t; t2 != &Scr.FvwmRoot; t2 = t2->stack_prev) { XRaiseWindow(dpy, FW_W_FRAME(t2)); } } /* This needs to be done after all the raise hacks. */ raisePanFrames(); /* If the window has been raised, make sure the decorations are * updated immediately in case we are in a complex function * (e.g. raise, unshade). */ XFlush(dpy); handle_all_expose(); } return; } static void raise_or_lower_window( FvwmWindow *t, stack_mode_t mode, Bool allow_recursion, Bool is_new_window, Bool is_client_request) { FvwmWindow *fw; /* clean the auxiliary registers used in stacking transients */ for (fw = Scr.FvwmRoot.next; fw != NULL; fw = fw->next) { fw->scratch.i = 0; } __raise_or_lower_window( t, mode, allow_recursion, is_new_window, is_client_request); return; } static Bool intersect( int x0, int y0, int w0, int h0, int x1, int y1, int w1, int h1) { return !((x0 >= x1 + w1) || (x0 + w0 <= x1) || (y0 >= y1 + h1) || (y0 + h0 <= y1)); } static Bool overlap(FvwmWindow *r, FvwmWindow *s) { rectangle g1; rectangle g2; Bool rc; if (r->Desk != s->Desk) { return False; } rc = get_visible_window_or_icon_geometry(r, &g1); if (rc == False) { return False; } rc = get_visible_window_or_icon_geometry(s, &g2); if (rc == False) { return False; } rc = intersect( g1.x, g1.y, g1.width, g1.height, g2.x, g2.y, g2.width, g2.height); return rc; } #if 0 /* ResyncFvwmStackRing - Rebuilds the stacking order ring of fvwm-managed windows. For use in cases where apps raise/lower their own windows in a way that makes it difficult to determine exactly where they ended up in the stacking order. - Based on code from Matthias Clasen. */ static void ResyncFvwmStackRing (void) { Window root, parent, *children; unsigned int nchildren; int i; FvwmWindow *t1, *t2; MyXGrabServer (dpy); if (!XQueryTree (dpy, Scr.Root, &root, &parent, &children, &nchildren)) { MyXUngrabServer (dpy); return; } t2 = &Scr.FvwmRoot; for (i = 0; i < nchildren; i++) { for (t1 = Scr.FvwmRoot.next; t1 != NULL; t1 = t1->next) { if (IS_ICONIFIED(t1) && !IS_ICON_SUPPRESSED(t1)) { if (FW_W_ICON_TITLE(t1) == children[i] || FW_W_ICON_PIXMAP(t1) == children[i]) { break; } } else { if (FW_W_FRAME(t1) == children[i]) { break; } } } if (t1 != NULL && t1 != t2) { /* Move the window to its new position, working from * the bottom up (that's the way XQueryTree presents * the list). */ /* Pluck from chain. */ remove_window_from_stack_ring(t1); add_window_to_stack_ring_after(t1, t2->stack_prev); if (t2 != &Scr.FvwmRoot && t2->layer > t1->layer) { /* oops, now our stack ring is out of order! */ /* emergency fix */ t1->layer = t2->layer; } t2 = t1; } } MyXUngrabServer (dpy); XFree (children); } #endif /* same as above but synchronizes the stacking order in X from the stack ring. */ static void ResyncXStackingOrder(void) { Window *wins; FvwmWindow *t; int count; int i; for (count = 0, t = Scr.FvwmRoot.next; t != NULL; count++, t = t->next) { /* nothing to do here */ } if (count > 0) { wins = (Window *)safemalloc(3 * count * sizeof (Window)); for ( i = 0, t = Scr.FvwmRoot.stack_next; count--; t = t->stack_next) { wins[i++] = FW_W_FRAME(t); if (IS_ICONIFIED(t) && !IS_ICON_SUPPRESSED(t)) { if (FW_W_ICON_TITLE(t) != None) { wins[i++] = FW_W_ICON_TITLE(t); } if (FW_W_ICON_PIXMAP(t) != None) { wins[i++] = FW_W_ICON_PIXMAP(t); } } } XRestackWindows(dpy, wins, i); free(wins); /* send out M_RESTACK for all windows, to make sure we don't * forget anything. */ BroadcastRestackAllWindows(); } return; } /* send RESTACK packets for all windows between s1 and s2 */ static void BroadcastRestack(FvwmWindow *s1, FvwmWindow *s2) { FvwmWindow *fw; int num; int i; int n; fmodule_list_itr moditr; fmodule *module; unsigned long *body, *bp, length; unsigned long max_wins_per_packet; if (s2 == &Scr.FvwmRoot) { s2 = s2->stack_prev; if (s2 == &Scr.FvwmRoot) { return; } } if (s1 == &Scr.FvwmRoot) { s1 = s1->stack_next; if (s1 == &Scr.FvwmRoot) { return; } /* s1 has been moved to the top of stack */ BroadcastPacket( M_RAISE_WINDOW, 3, (long)FW_W(s1), (long)FW_W_FRAME(s1), (unsigned long)s1); if (s1->stack_next == s2) { /* avoid sending empty RESTACK packet */ return; } } if (s1 == s2) { /* A useful M_RESTACK packet must contain at least two windows. */ return; } for ( fw = s1, num = 1; fw != s2 && fw != &Scr.FvwmRoot; fw = fw->stack_next, num++) { /* nothing */ } max_wins_per_packet = (FvwmPacketMaxSize - FvwmPacketHeaderSize) / 3; /* split packet if it is too long */ for ( ; num > 1; s1 = fw, num -= n) { n = min(num, max_wins_per_packet) - 1; length = FvwmPacketHeaderSize + 3 * (n + 1); body = (unsigned long *)safemalloc( length * sizeof(unsigned long)); bp = body; *(bp++) = START_FLAG; *(bp++) = M_RESTACK; *(bp++) = length; *(bp++) = fev_get_evtime(); for (fw = s1, i = 0; i <= n; i++, fw = fw->stack_next) { *(bp++) = FW_W(fw); *(bp++) = FW_W_FRAME(fw); *(bp++) = (unsigned long)fw; } /* The last window has to be in the header of the next part */ fw = fw->stack_prev; module_list_itr_init(&moditr); while ( (module = module_list_itr_next(&moditr)) != NULL) { PositiveWrite( module,body,length*sizeof(unsigned long)); } free(body); } #ifdef DEBUG_STACK_RING verify_stack_ring_consistency(); #endif return; } static int collect_transients_recursive( FvwmWindow *t, FvwmWindow *list_head, int layer, stack_mode_t mode, Bool do_include_target_window) { FvwmWindow *s; int count = 0; int m; switch (mode) { case SM_LOWER: m = MARK_LOWER; break; case SM_RAISE: m = MARK_RAISE; break; case SM_RESTACK: m = MARK_RESTACK; break; default: /* can not happen */ m = MARK_RAISE; break; } mark_transient_subtree(t, layer, m, True, False); /* now collect the marked windows in a separate list */ for (s = Scr.FvwmRoot.stack_next; s != &Scr.FvwmRoot; ) { FvwmWindow *tmp; if (s == t && do_include_target_window == False) { /* ignore the target window */ s = s->stack_next; continue; } tmp = s->stack_next; if (IS_IN_TRANSIENT_SUBTREE(s)) { remove_window_from_stack_ring(s); add_window_to_stack_ring_after( s, list_head->stack_prev); count++; count += get_visible_icon_window_count(t); } s = tmp; } return count; } static Bool is_above_unmanaged(FvwmWindow *fw, Window *umtop) { /* Chase through the entire stack of the server's windows looking for any unmanaged window that's higher than the target. Called from raise_over_unmanaged and is_on_top_of_layer. */ Bool ontop = True; Window junk; Window *tops; int i; unsigned int num; Window OR_Above = None; XWindowAttributes wa; if (fw->Desk != Scr.CurrentDesk) { return True; } if (!XQueryTree(dpy, Scr.Root, &junk, &junk, &tops, &num)) { return ontop; } /* * Locate the highest override_redirect window above our target, and * the highest of our windows below it. */ for (i = 0; i < num && tops[i] != FW_W_FRAME(fw); i++) { /* look for target window in list */ } for (; i < num; i++) { /* It might be just as well (and quicker) just to check for the * absence of an FvwmContext instead of for * override_redirect... */ if (!XGetWindowAttributes(dpy, tops[i], &wa)) { continue; } /* Don't forget to ignore the hidden frame resizing windows... */ if (wa.override_redirect == True && wa.class != InputOnly && tops[i] != Scr.NoFocusWin && (!is_frame_hide_window(tops[i]))) { OR_Above = tops[i]; } } /* end for */ if (OR_Above) { *umtop = OR_Above; ontop = False; } XFree (tops); return ontop; } static Bool is_on_top_of_layer_ignore_rom(FvwmWindow *fw) { FvwmWindow *t; Bool ontop = True; if (IS_SCHEDULED_FOR_DESTROY(fw)) { /* stack ring members are no longer valid */ return False; } if (DO_RAISE_TRANSIENT(fw)) { mark_transient_subtree(fw, fw->layer, MARK_RAISE, True, False); } for (t = fw->stack_prev; t != &Scr.FvwmRoot; t = t->stack_prev) { if (t->layer > fw->layer) { break; } if (t->Desk != fw->Desk) { continue; } /* For RaiseOverUnmanaged we can not determine if the window is * on top by checking if the window overlaps another one. If * it was below unmanaged windows, but on top of its layer, it * would be considered on top. */ if (Scr.bo.do_raise_over_unmanaged || overlap(fw, t)) { if (!DO_RAISE_TRANSIENT(fw) || (!IS_IN_TRANSIENT_SUBTREE(t) && t != fw)) { ontop = False; break; } } } return ontop; } static Bool __is_on_top_of_layer(FvwmWindow *fw, Bool client_entered) { Window junk; Bool ontop = False; if (Scr.bo.do_raise_over_unmanaged) { #define EXPERIMENTAL_ROU_HANDLING #ifdef EXPERIMENTAL_ROU_HANDLING /* RBW - 2002/08/15 - RaiseOverUnmanaged adds some overhead. The only way to let our caller know for sure whether we need to grab the mouse buttons because we may need to raise this window is to query the server's tree and look for any override_redirect windows above this one. But this function is called far too often to do this every time. Only if the window is at the top of the FvwmWindow stack do we need more information from the server; and then only at the last moment in HandleEnterNotify when we really need to know whether a raise will be needed if the user clicks in the client window. is_on_top_of_layer_and_above_unmanaged is called in that case. */ if (is_on_top_of_layer_ignore_rom(fw)) { if (client_entered) /* FIXME! - perhaps we should only do if MFCR */ { #ifdef ROUDEBUG printf("RBW-iotol - %8.8lx is on top," " checking server tree. ***\n", FW_W_CLIENT(fw)); #endif ontop = is_above_unmanaged(fw, &junk); #ifdef ROUDEBUG printf(" returning %d\n", (int) ontop); #endif } else { #ifdef ROUDEBUG printf("RBW-iotol - %8.8lx is on top," " *** NOT checking server tree.\n", FW_W_CLIENT(fw)); #endif ontop = True; } return ontop; } else { return False; } #else return False; /* Old pre-2002/08/22 handling. */ #endif } else { return is_on_top_of_layer_ignore_rom(fw); } } /* ---------------------------- interface functions ------------------------ */ /* Remove a window from the stack ring */ void remove_window_from_stack_ring(FvwmWindow *t) { if (IS_SCHEDULED_FOR_DESTROY(t)) { return; } t->stack_prev->stack_next = t->stack_next; t->stack_next->stack_prev = t->stack_prev; /* not really necessary, but gives a little more saftey */ t->stack_prev = NULL; t->stack_next = NULL; return; } /* Add window t to the stack ring after window t */ void add_window_to_stack_ring_after(FvwmWindow *t, FvwmWindow *add_after_win) { if (IS_SCHEDULED_FOR_DESTROY(t)) { return; } if (t == add_after_win || t == add_after_win->stack_next) { /* tried to add the window before or after itself */ fvwm_msg( ERR, "add_window_to_stack_ring_after", "BUG: tried to add window '%s' %s itself in stack" " ring\n", t->name.name, (t == add_after_win) ? "after" : "before"); return; } t->stack_next = add_after_win->stack_next; add_after_win->stack_next->stack_prev = t; t->stack_prev = add_after_win; add_after_win->stack_next = t; return; } FvwmWindow *get_next_window_in_stack_ring(const FvwmWindow *t) { return t->stack_next; } FvwmWindow *get_prev_window_in_stack_ring(const FvwmWindow *t) { return t->stack_prev; } FvwmWindow *get_transientfor_fvwmwindow(const FvwmWindow *t) { FvwmWindow *s; if (!t || !IS_TRANSIENT(t) || FW_W_TRANSIENTFOR(t) == Scr.Root || FW_W_TRANSIENTFOR(t) == None) { return NULL; } for (s = Scr.FvwmRoot.next; s != NULL; s = s->next) { if (FW_W(s) == FW_W_TRANSIENTFOR(t)) { return (s == t) ? NULL : s; } } return NULL; } /* Takes a window from the top of the stack ring and puts it at the appropriate * place. Called when new windows are created. */ Bool position_new_window_in_stack_ring(FvwmWindow *t, Bool do_lower) { if (t->stack_prev != &Scr.FvwmRoot) { /* Not at top of stack ring, so it is already in place. * add_window.c relies on this. */ return False; } /* RaiseWindow/LowerWindow will put the window in its layer */ raise_or_lower_window( t, (do_lower) ? SM_LOWER : SM_RAISE, False, True, False); return True; } /* Raise t and its transients to the top of its layer. For the pager to work * properly it is necessary that RaiseWindow *always* sends a proper M_RESTACK * packet, even if the stacking order didn't change. */ void RaiseWindow(FvwmWindow *t, Bool is_client_request) { BroadcastPacket( M_RAISE_WINDOW, 3, (long)FW_W(t), (long)FW_W_FRAME(t), (unsigned long)t); raise_or_lower_window(t, SM_RAISE, True, False, is_client_request); focus_grab_buttons_on_layer(t->layer); #ifdef DEBUG_STACK_RING verify_stack_ring_consistency(); #endif return; } void LowerWindow(FvwmWindow *t, Bool is_client_request) { BroadcastPacket( M_LOWER_WINDOW, 3, (long)FW_W(t), (long)FW_W_FRAME(t), (unsigned long)t); raise_or_lower_window(t, SM_LOWER, True, False, is_client_request); focus_grab_buttons_on_layer(t->layer); #ifdef DEBUG_STACK_RING verify_stack_ring_consistency(); #endif return; } void RestackWindow(FvwmWindow *t, Bool is_client_request) { raise_or_lower_window(t, SM_RESTACK, True, False, is_client_request); focus_grab_buttons_on_layer(t->layer); #ifdef DEBUG_STACK_RING verify_stack_ring_consistency(); #endif return; } /* return true if stacking order changed */ Bool HandleUnusualStackmodes( unsigned int stack_mode, FvwmWindow *r, Window rw, FvwmWindow *s, Window sw) { int do_restack = 0; FvwmWindow *t; /* DBUG("HandleUnusualStackmodes", "called with %d, %lx\n", stack_mode, s);*/ if ( ((rw != FW_W(r)) ^ IS_ICONIFIED(r)) || (s && (((sw != FW_W(s)) ^ IS_ICONIFIED(s)) || (r->Desk != s->Desk)))) { /* one of the relevant windows is unmapped */ return 0; } switch (stack_mode) { case TopIf: for ( t = r->stack_prev; t != &Scr.FvwmRoot && !do_restack; t = t->stack_prev) { do_restack = ((s == NULL || s == t) && overlap(t, r)); } if (do_restack) { RaiseWindow (r, True); } break; case BottomIf: for ( t = r->stack_next; t != &Scr.FvwmRoot && !do_restack; t = t->stack_next) { do_restack = ((s == NULL || s == t) && overlap(t, r)); } if (do_restack) { LowerWindow (r, True); } break; case Opposite: do_restack = ( HandleUnusualStackmodes(TopIf, r, rw, s, sw) || HandleUnusualStackmodes(BottomIf, r, rw, s, sw)); break; } /* DBUG("HandleUnusualStackmodes", "\t---> %d\n", do_restack);*/ #ifdef DEBUG_STACK_RING verify_stack_ring_consistency(); #endif return do_restack; } /* RBW - 01/07/1998 - this is here temporarily - I mean to move it to libfvwm eventually, along with some other chain manipulation functions. */ void BroadcastRestackAllWindows(void) { BroadcastRestack(Scr.FvwmRoot.stack_next, Scr.FvwmRoot.stack_prev); return; } /* send RESTACK packets for t, t->stack_prev and t->stack_next */ void BroadcastRestackThisWindow(FvwmWindow *t) { BroadcastRestack(t->stack_prev, t->stack_next); return; } /* returns 0 if s and t are on the same layer, <1 if t is on a lower layer and * >1 if t is on a higher layer. */ int compare_window_layers(FvwmWindow *t, FvwmWindow *s) { return t->layer - s->layer; } void set_default_layer(FvwmWindow *t, int layer) { t->default_layer = layer; return; } void set_layer(FvwmWindow *t, int layer) { t->layer = layer; return; } int get_layer(FvwmWindow *t) { return t->layer; } /* This function recursively finds the transients of the window t and sets their * is_in_transient_subtree flag. If a layer is given, only windows in this * layer are checked. If the layer is < 0, all windows are considered. */ void mark_transient_subtree( FvwmWindow *t, int layer, int mark_mode, Bool do_ignore_icons, Bool use_window_group_hint) { FvwmWindow *s; FvwmWindow *start; FvwmWindow *end; Bool is_finished; if (layer >= 0 && t->layer != layer) { return; } /* find out on which windows to operate */ if (layer >= 0) { /* only work on the given layer */ start = &Scr.FvwmRoot; end = &Scr.FvwmRoot; for ( s = Scr.FvwmRoot.stack_next; s != &Scr.FvwmRoot && s->layer >= layer; s = s->stack_next) { if (s == t) { /* ignore the target window */ continue; } if (s->layer == layer) { if (start == &Scr.FvwmRoot) { start = s; } end = s->stack_next; } } } else { /* work on complete window list */ start = Scr.FvwmRoot.stack_next; end = &Scr.FvwmRoot; } /* clean the temporary flag in all windows and precalculate the * transient frame windows */ if (Scr.FvwmRoot.scratch.i == 0) { for ( s = Scr.FvwmRoot.stack_next; s != &Scr.FvwmRoot; s = s->stack_next) { SET_IN_TRANSIENT_SUBTREE(s, 0); if ( IS_TRANSIENT(s) && (layer < 0 || layer == s->layer)) { s->scratch.p = get_transientfor_fvwmwindow(s); } else { s->scratch.p = NULL; } } } Scr.FvwmRoot.scratch.i = 0; /* now loop over the windows and mark the ones we need to move */ SET_IN_TRANSIENT_SUBTREE(t, 1); is_finished = False; while (!is_finished) { /* recursively search for all transient windows */ is_finished = True; for (s = start; s != end; s = s->stack_next) { if ( __mark_transient_subtree_test( s, start, end, mark_mode, do_ignore_icons, use_window_group_hint)) { is_finished = False; } } /* for */ } /* while */ return; } void new_layer(FvwmWindow *fw, int layer) { FvwmWindow *s; FvwmWindow *target; FvwmWindow *prev; FvwmWindow list_head; int add_after_layer; int count; int old_layer; Bool do_lower; if (layer < 0) { layer = 0; } fw = get_transientfor_top_fvwmwindow(fw); if (layer == fw->layer) { return; } old_layer = fw->layer; list_head.stack_next = &list_head; list_head.stack_prev = &list_head; count = collect_transients_recursive( fw, &list_head, fw->layer, (layer < fw->layer) ? SM_LOWER : SM_RAISE, True); if (count == 0) { /* no windows to move */ return; } add_after_layer = layer; if (layer < fw->layer) { /* lower below the windows in the new (lower) layer */ add_after_layer = layer; do_lower = True; } else { /* raise above the windows in the new (higher) layer */ add_after_layer = layer + 1; do_lower = False; } /* find the place to insert the windows */ for ( target = Scr.FvwmRoot.stack_next; target != &Scr.FvwmRoot; target = target->stack_next) { if (target->layer < add_after_layer) { /* add all windows before the current window */ break; } } /* insert windows at new position */ add_windowlist_to_stack_ring_after(&list_head, target->stack_prev); prev = NULL; for ( s = list_head.stack_next; prev != list_head.stack_prev; prev = s, s = s->stack_next) { s->layer = layer; /* redraw title and buttons to update layer buttons */ border_draw_decorations( s, PART_TITLEBAR, (Scr.Hilite == fw), True, CLEAR_NONE, NULL, NULL); EWMH_SetWMState(fw, False); } /* move the windows without modifying their stacking order */ __restack_window_list( list_head.stack_next->stack_prev, target, count, (count > 1), do_lower); focus_grab_buttons_on_layer(layer); focus_grab_buttons_on_layer(old_layer); return; } /* RBW - 11/13/1998 - 2 new fields to init - stacking order chain. */ void init_stack_and_layers(void) { Scr.BottomLayer = DEFAULT_BOTTOM_LAYER; Scr.DefaultLayer = DEFAULT_DEFAULT_LAYER; Scr.TopLayer = DEFAULT_TOP_LAYER; Scr.FvwmRoot.stack_next = &Scr.FvwmRoot; Scr.FvwmRoot.stack_prev = &Scr.FvwmRoot; set_layer(&Scr.FvwmRoot, DEFAULT_ROOT_WINDOW_LAYER); return; } Bool is_on_top_of_layer(FvwmWindow *fw) { return __is_on_top_of_layer(fw, False); } Bool is_on_top_of_layer_and_above_unmanaged(FvwmWindow *fw) { return __is_on_top_of_layer(fw, True); } /* ----------------------------- built in functions ----------------------- */ void CMD_Raise(F_CMD_ARGS) { RaiseWindow(exc->w.fw, False); return; } void CMD_Lower(F_CMD_ARGS) { LowerWindow(exc->w.fw, False); return; } void CMD_RestackTransients(F_CMD_ARGS) { RestackWindow(exc->w.fw, False); return; } void CMD_RaiseLower(F_CMD_ARGS) { Bool ontop; FvwmWindow * const fw = exc->w.fw; ontop = is_on_top_of_layer_ignore_rom(fw); if (ontop) { LowerWindow(fw, False); } else { RaiseWindow(fw, False); } return; } void CMD_Layer(F_CMD_ARGS) { int n, layer, val[2]; char *token; FvwmWindow * const fw = exc->w.fw; if (fw == NULL) { return; } token = PeekToken(action, NULL); if (StrEquals("default", token)) { layer = fw->default_layer; } else { n = GetIntegerArguments(action, NULL, val, 2); layer = fw->layer; if ((n == 1) || ((n == 2) && (val[0] != 0))) { layer += val[0]; } else if ((n == 2) && (val[1] >= 0)) { layer = val[1]; } else { layer = fw->default_layer; } } if (layer < 0) { layer = 0; } new_layer(fw, layer); #ifdef DEBUG_STACK_RING verify_stack_ring_consistency(); #endif return; } void CMD_DefaultLayers(F_CMD_ARGS) { char *bot = NULL; char *def = NULL; char *top = NULL; int i; bot = PeekToken(action, &action); if (bot) { i = atoi (bot); if (i < 0) { fvwm_msg( ERR, "DefaultLayers", "Layer must be non-negative." ); } else { Scr.BottomLayer = i; } } def = PeekToken(action, &action); if (def) { i = atoi (def); if (i < 0) { fvwm_msg( ERR, "DefaultLayers", "Layer must be non-negative." ); } else { Scr.DefaultLayer = i; } } top = PeekToken(action, &action); if (top) { i = atoi (top); if (i < 0) { fvwm_msg( ERR, "DefaultLayers", "Layer must be non-negative." ); } else { Scr.TopLayer = i; } } #ifdef DEBUG_STACK_RING verify_stack_ring_consistency(); #endif return; } fvwm-2.7.0/fvwm/menuitem.c0000644000175000017500000005520414147024700012373 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include "libs/fvwmlib.h" #include "libs/Picture.h" #include "libs/Graphics.h" #include "libs/PictureGraphics.h" #include "libs/Rectangles.h" #include "fvwm.h" #include "externs.h" #include "execcontext.h" #include "misc.h" #include "screen.h" #include "menudim.h" #include "menustyle.h" #include "menuitem.h" #include "decorations.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ static void clear_menu_item_background( MenuPaintItemParameters *mpip, int x, int y, int w, int h) { MenuStyle *ms = mpip->ms; if (!ST_HAS_MENU_CSET(ms) && ST_FACE(ms).type == GradientMenu && (ST_FACE(ms).gradient_type == D_GRADIENT || ST_FACE(ms).gradient_type == B_GRADIENT)) { XEvent e; e.xexpose.x = x; e.xexpose.y = y; e.xexpose.width = w; e.xexpose.height = h; mpip->cb_reset_bg(mpip->cb_mr, &e); } else { XClearArea(dpy, mpip->w, x, y, w, h, False); } } /* * * Draws two horizontal lines to form a separator * */ static void draw_separator( Window w, GC TopGC, GC BottomGC, int x1, int y, int x2) { XDrawLine(dpy, w, TopGC , x1, y, x2, y); XDrawLine(dpy, w, BottomGC, x1-1, y+1, x2+1, y+1); return; } /* * * Draws a tear off bar. Similar to a separator, but with a dashed line. * */ static void draw_tear_off_bar( Window w, GC TopGC, GC BottomGC, int x1, int y, int x2) { XGCValues xgcv; int width; int offset; xgcv.line_style = LineOnOffDash; xgcv.dashes = MENU_TEAR_OFF_BAR_DASH_WIDTH; XChangeGC(dpy, TopGC, GCLineStyle | GCDashList, &xgcv); XChangeGC(dpy, BottomGC, GCLineStyle | GCDashList, &xgcv); width = (x2 - x1 + 1); offset = (width / MENU_TEAR_OFF_BAR_DASH_WIDTH) * MENU_TEAR_OFF_BAR_DASH_WIDTH; offset = (width - offset) / 2; x1 += offset; x2 += offset; XDrawLine(dpy, w, TopGC, x1, y, x2, y); XDrawLine(dpy, w, BottomGC, x1, y + 1, x2, y + 1); xgcv.line_style = LineSolid; XChangeGC(dpy, TopGC, GCLineStyle, &xgcv); XChangeGC(dpy, BottomGC, GCLineStyle, &xgcv); return; } static void draw_highlight_background( struct MenuPaintItemParameters *mpip, int x, int y, int width, int height, colorset_t *cs, GC gc) { if (cs != NULL && cs->pixmap && cs->pixmap_type != PIXMAP_TILED) { Pixmap p; p = CreateOffsetBackgroundPixmap( dpy, mpip->w, 0, 0, width, height, cs, Pdepth, gc, False); switch (cs->pixmap_type) { case PIXMAP_STRETCH_X: /* todo: optimize to only create one pixmap and gc per * mr. */ case PIXMAP_STRETCH_Y: { XGCValues gcv; int gcm; GC bgc; gcv.tile = p; gcv.fill_style = FillTiled; gcm = GCFillStyle | GCTile; /* vertcal gradients has to be aligned properly */ if (cs->pixmap_type == PIXMAP_STRETCH_Y) { gcv.ts_y_origin = y; gcm|=GCTileStipYOrigin; } else if (cs->pixmap_type == PIXMAP_STRETCH_X) { gcv.ts_x_origin = x; gcm|=GCTileStipXOrigin; } bgc = fvwmlib_XCreateGC(dpy, mpip->w, gcm, &gcv); XFillRectangle(dpy, mpip->w, bgc, x, y, width, height); XFreeGC(dpy, bgc); break; } default: XCopyArea(dpy, p, mpip->w, gc, 0, 0, width, height, x, y); break; } XFreePixmap(dpy, p); } else { XFillRectangle(dpy, mpip->w, gc, x, y, width, height); } } /* ---------------------------- interface functions ------------------------ */ /* Allocates a new, empty menu item */ struct MenuItem *menuitem_create(void) { MenuItem *mi; mi = (MenuItem *)safemalloc(sizeof(MenuItem)); memset(mi, 0, sizeof(MenuItem)); return mi; } /* Frees a menu item and all of its allocated resources. */ void menuitem_free(struct MenuItem *mi) { int i; if (!mi) { return; } for (i = 0; i < MAX_MENU_ITEM_LABELS; i++) { if (MI_LABEL(mi)[i] != NULL) { free(MI_LABEL(mi)[i]); } } if (MI_ACTION(mi) != NULL) { free(MI_ACTION(mi)); } if (MI_PICTURE(mi)) { PDestroyFvwmPicture(dpy, MI_PICTURE(mi)); } for (i = 0; i < MAX_MENU_ITEM_MINI_ICONS; i++) { if (MI_MINI_ICON(mi)[i]) { PDestroyFvwmPicture(dpy, MI_MINI_ICON(mi)[i]); } } free(mi); return; } /* Duplicate a menu item into newly allocated memory. The new item is * completely independent of the old one. */ struct MenuItem *menuitem_clone(struct MenuItem *mi) { MenuItem *new_mi; int i; /* copy everything */ new_mi = (MenuItem *)safemalloc(sizeof(MenuItem)); memcpy(new_mi, mi, sizeof(MenuItem)); /* special treatment for a few parts */ MI_NEXT_ITEM(new_mi) = NULL; MI_PREV_ITEM(new_mi) = NULL; MI_WAS_DESELECTED(new_mi) = 0; if (MI_ACTION(mi) != NULL) { MI_ACTION(new_mi) = safestrdup(MI_ACTION(mi)); } for (i = 0; i < MAX_MENU_ITEM_LABELS; i++) { if (MI_LABEL(mi)[i] != NULL) { MI_LABEL(new_mi)[i] = strdup(MI_LABEL(mi)[i]); } } if (MI_PICTURE(mi) != NULL) { MI_PICTURE(new_mi) = PCloneFvwmPicture(MI_PICTURE(mi)); } for (i = 0; i < MAX_MENU_ITEM_MINI_ICONS; i++) { if (MI_MINI_ICON(mi)[i] != NULL) { MI_MINI_ICON(new_mi)[i] = PCloneFvwmPicture(MI_MINI_ICON(mi)[i]); } } return new_mi; } /* Calculate the size of the various parts of the item. The sizes are returned * through mipst. */ void menuitem_get_size( struct MenuItem *mi, struct MenuItemPartSizesT *mipst, FlocaleFont *font, Bool do_reverse_icon_order) { int i; int j; int w; memset(mipst, 0, sizeof(MenuItemPartSizesT)); if (MI_IS_POPUP(mi)) { mipst->triangle_width = MENU_TRIANGLE_WIDTH; } else if (MI_IS_TITLE(mi) && !MI_HAS_PICTURE(mi)) { Bool is_formatted = False; /* titles stretch over the whole menu width, so count the * maximum separately if the title is unformatted. */ for (j = 1; j < MAX_MENU_ITEM_LABELS; j++) { if (MI_LABEL(mi)[j] != NULL) { is_formatted = True; break; } else { MI_LABEL_OFFSET(mi)[j] = 0; } } if (!is_formatted && MI_LABEL(mi)[0] != NULL) { MI_LABEL_STRLEN(mi)[0] = strlen(MI_LABEL(mi)[0]); w = FlocaleTextWidth( font, MI_LABEL(mi)[0], MI_LABEL_STRLEN(mi)[0]); MI_LABEL_OFFSET(mi)[0] = w; MI_IS_TITLE_CENTERED(mi) = True; if (mipst->title_width < w) { mipst->title_width = w; } return; } } /* regular item or formatted title */ for (i = 0; i < MAX_MENU_ITEM_LABELS; i++) { if (MI_LABEL(mi)[i]) { MI_LABEL_STRLEN(mi)[i] = strlen(MI_LABEL(mi)[i]); w = FlocaleTextWidth( font, MI_LABEL(mi)[i], MI_LABEL_STRLEN(mi)[i]); MI_LABEL_OFFSET(mi)[i] = w; if (mipst->label_width[i] < w) { mipst->label_width[i] = w; } } } if (MI_PICTURE(mi) && mipst->picture_width < MI_PICTURE(mi)->width) { mipst->picture_width = MI_PICTURE(mi)->width; } for (i = 0; i < MAX_MENU_ITEM_MINI_ICONS; i++) { if (MI_MINI_ICON(mi)[i]) { int k; /* Reverse mini icon order for left submenu style. */ k = (do_reverse_icon_order == True) ? MAX_MENU_ITEM_MINI_ICONS - 1 - i : i; mipst->icon_width[k] = MI_MINI_ICON(mi)[i]->width; } } return; } /* * * Procedure: * menuitem_paint - draws a single entry in a popped up menu * * mr - the menu instance that holds the menu item * mi - the menu item to redraw * fw - the FvwmWindow structure to check against allowed functions * */ void menuitem_paint( struct MenuItem *mi, struct MenuPaintItemParameters *mpip) { struct MenuStyle *ms = mpip->ms; struct MenuDimensions *dim = mpip->dim; static FlocaleWinString *fws = NULL; int y_offset; int text_y; int y_height; int x; int y; int lit_x_start; int lit_x_end; gc_quad_t gcs; gc_quad_t off_gcs; int cs = -1; int off_cs; FvwmRenderAttributes fra; /*Pixel fg, fgsh;*/ int relief_thickness = ST_RELIEF_THICKNESS(ms); Bool is_item_selected; Bool item_cleared = False; Bool xft_clear = False; Bool empty_inter = False; XRectangle b; Region region = None; int i; int sx1; int sx2; FlocaleFont* font; if (!mi) { return; } is_item_selected = (mi == mpip->selected_item); if (MI_IS_TITLE(mi)) { font = ST_PTITLEFONT(ms); } else { font = ST_PSTDFONT(ms); } y_offset = MI_Y_OFFSET(mi); y_height = MI_HEIGHT(mi); if (MI_IS_SELECTABLE(mi)) { text_y = y_offset + MDIM_ITEM_TEXT_Y_OFFSET(*dim); } else { text_y = y_offset + font->ascent + ST_TITLE_GAP_ABOVE(ms); } /* center text vertically if the pixmap is taller */ if (MI_PICTURE(mi)) { text_y += MI_PICTURE(mi)->height; } for (i = 0; i < mpip->used_mini_icons; i++) { y = 0; if (MI_MINI_ICON(mi)[i]) { if (MI_MINI_ICON(mi)[i]->height > y) { y = MI_MINI_ICON(mi)[i]->height; } } y -= font->height; if (y > 1) { text_y += y / 2; } } off_cs = ST_HAS_MENU_CSET(ms) ? ST_CSET_MENU(ms) : -1; /* Note: it's ok to pass a NULL label to is_function_allowed. */ if ( !IS_EWMH_DESKTOP_FW(mpip->fw) && !is_function_allowed( MI_FUNC_TYPE(mi), MI_LABEL(mi)[0], mpip->fw, RQORIG_PROGRAM_US, False)) { gcs = ST_MENU_STIPPLE_GCS(ms); off_gcs = gcs; off_cs = ST_HAS_GREYED_CSET(ms) ? ST_CSET_GREYED(ms) : -1; } else if (is_item_selected) { gcs = ST_MENU_ACTIVE_GCS(ms); off_gcs = ST_MENU_INACTIVE_GCS(ms); } else if (MI_IS_TITLE(mi)) { gcs = ST_MENU_TITLE_GCS(ms); off_gcs = ST_MENU_INACTIVE_GCS(ms); } else { gcs = ST_MENU_INACTIVE_GCS(ms); off_gcs = ST_MENU_INACTIVE_GCS(ms); } if (is_item_selected) { cs = (ST_HAS_ACTIVE_CSET(ms)) ? ST_CSET_ACTIVE(ms) : -1; } else if (MI_IS_TITLE(mi)) { cs = (ST_HAS_TITLE_CSET(ms)) ? ST_CSET_TITLE(ms) : off_cs; } else { cs = off_cs; } /* * Hilight the item. */ if (FftSupport && ST_PSTDFONT(ms)->fftf.fftfont != NULL) { xft_clear = True; } /* Hilight or clear the background. */ lit_x_start = -1; lit_x_end = -1; if (is_item_selected && (ST_DO_HILIGHT_BACK(ms) || ST_DO_HILIGHT_FORE(ms))) { /* Hilight the background. */ if (MDIM_HILIGHT_WIDTH(*dim) - 2 * relief_thickness > 0) { lit_x_start = MDIM_HILIGHT_X_OFFSET(*dim) + relief_thickness; lit_x_end = lit_x_start + MDIM_HILIGHT_WIDTH(*dim) - 2 * relief_thickness; if (ST_DO_HILIGHT_BACK(ms)) { draw_highlight_background( mpip, lit_x_start, y_offset + relief_thickness, lit_x_end - lit_x_start, y_height - relief_thickness, (cs >= 0 ? &Colorset[cs] : NULL), gcs.back_gc); item_cleared = True; } } } else if ((MI_WAS_DESELECTED(mi) && (relief_thickness > 0 || ST_DO_HILIGHT_BACK(ms) || ST_DO_HILIGHT_FORE(ms)) && (ST_FACE(ms).type != GradientMenu || ST_HAS_MENU_CSET(ms)))) { int x1; int x2; /* we clear if xft_clear and !ST_HAS_MENU_CSET(ms) as the * non colorset code is too complicate ... olicha */ int d = 0; if (MI_PREV_ITEM(mi) && mpip->selected_item == MI_PREV_ITEM(mi)) { /* Don't paint over the hilight relief. */ d = relief_thickness; } /* Undo the hilighting. */ x1 = min( MDIM_HILIGHT_X_OFFSET(*dim), MDIM_ITEM_X_OFFSET(*dim)); x2 = max( MDIM_HILIGHT_X_OFFSET(*dim) + MDIM_HILIGHT_WIDTH(*dim), MDIM_ITEM_X_OFFSET(*dim) + MDIM_ITEM_WIDTH(*dim)); clear_menu_item_background( mpip, x1, y_offset + d, x2 - x1, y_height + relief_thickness - d); item_cleared = True; } else if (MI_IS_TITLE(mi)) { lit_x_start = MDIM_ITEM_X_OFFSET(*dim); lit_x_end = lit_x_start + MDIM_ITEM_WIDTH(*dim); /* Hilight the background. */ if ( MDIM_HILIGHT_WIDTH(*dim) > 0 && ST_DO_HILIGHT_TITLE_BACK(ms)) { draw_highlight_background( mpip, lit_x_start, y_offset + relief_thickness, lit_x_end - lit_x_start, y_height - relief_thickness, (cs >= 0 ? &Colorset[cs] : NULL), gcs.back_gc); item_cleared = True; } } MI_WAS_DESELECTED(mi) = False; memset(&fra, 0, sizeof(fra)); fra.mask = 0; /* Hilight 3D */ if (is_item_selected && relief_thickness > 0) { GC rgc; GC sgc; rgc = gcs.hilight_gc; sgc = gcs.shadow_gc; if (ST_IS_ITEM_RELIEF_REVERSED(ms)) { GC tgc = rgc; /* swap gcs for reversed relief */ rgc = sgc; sgc = tgc; } if (MDIM_HILIGHT_WIDTH(*dim) - 2 * relief_thickness > 0) { /* The relief reaches down into the next item, hence * the value for the second y coordinate: * MI_HEIGHT(mi) + 1 */ RelieveRectangle( dpy, mpip->w, MDIM_HILIGHT_X_OFFSET(*dim), y_offset, MDIM_HILIGHT_WIDTH(*dim) - 1, MI_HEIGHT(mi) - 1 + relief_thickness, rgc, sgc, relief_thickness); } } /* * Draw the item itself. */ /* Calculate the separator offsets. */ if (ST_HAS_LONG_SEPARATORS(ms)) { sx1 = MDIM_ITEM_X_OFFSET(*dim) + relief_thickness; sx2 = MDIM_ITEM_X_OFFSET(*dim) + MDIM_ITEM_WIDTH(*dim) - 1 - relief_thickness; } else { sx1 = MDIM_ITEM_X_OFFSET(*dim) + relief_thickness + MENU_SEPARATOR_SHORT_X_OFFSET; sx2 = MDIM_ITEM_X_OFFSET(*dim) + MDIM_ITEM_WIDTH(*dim) - 1 - relief_thickness - MENU_SEPARATOR_SHORT_X_OFFSET; } if (MI_IS_SEPARATOR(mi)) { if (sx1 < sx2) { /* It's a separator. */ draw_separator( mpip->w, gcs.shadow_gc, gcs.hilight_gc, sx1, y_offset + y_height - MENU_SEPARATOR_HEIGHT, sx2); /* Nothing else to do. */ } return; } else if (MI_IS_TEAR_OFF_BAR(mi)) { int tx1; int tx2; tx1 = MDIM_ITEM_X_OFFSET(*dim) + relief_thickness + MENU_TEAR_OFF_BAR_X_OFFSET; tx2 = MDIM_ITEM_X_OFFSET(*dim) + MDIM_ITEM_WIDTH(*dim) - 1 - relief_thickness - MENU_TEAR_OFF_BAR_X_OFFSET; if (tx1 < tx2) { /* It's a tear off bar. */ draw_tear_off_bar( mpip->w, gcs.shadow_gc, gcs.hilight_gc, tx1, y_offset + relief_thickness + MENU_TEAR_OFF_BAR_Y_OFFSET, tx2); } /* Nothing else to do. */ return; } else if (MI_IS_TITLE(mi)) { /* Separate the title. */ if (ST_TITLE_UNDERLINES(ms) > 0 && !mpip->flags.is_first_item) { int add = (MI_IS_SELECTABLE(MI_PREV_ITEM(mi))) ? relief_thickness : 0; text_y += MENU_SEPARATOR_HEIGHT + add; y = y_offset + add; if (sx1 < sx2) { draw_separator( mpip->w, gcs.shadow_gc, gcs.hilight_gc, sx1, y, sx2); } } /* Underline the title. */ switch (ST_TITLE_UNDERLINES(ms)) { case 0: break; case 1: if (MI_NEXT_ITEM(mi) != NULL) { y = y_offset + y_height - MENU_SEPARATOR_HEIGHT; draw_separator( mpip->w, gcs.shadow_gc, gcs.hilight_gc, sx1, y, sx2); } break; default: for (i = ST_TITLE_UNDERLINES(ms); i-- > 0; ) { y = y_offset + y_height - 1 - i * MENU_UNDERLINE_HEIGHT; XDrawLine( dpy, mpip->w, gcs.shadow_gc, sx1, y, sx2, y); } break; } } /* * Draw the labels. */ if (fws == NULL) { FlocaleAllocateWinString(&fws); } fws->win = mpip->w; fws->y = text_y; fws->flags.has_colorset = 0; b.y = text_y - font->ascent; b.height = font->height + 1; /* ? */ if (!item_cleared && mpip->ev) { int u,v; if (!frect_get_seg_intersection( mpip->ev->xexpose.y, mpip->ev->xexpose.height, b.y, b.height, &u, &v)) { /* empty intersection */ empty_inter = True; } b.y = u; b.height = v; } for (i = MAX_MENU_ITEM_LABELS; i-- > 0; ) { if (!empty_inter && MI_LABEL(mi)[i] && *(MI_LABEL(mi)[i])) { Bool draw_string = True; int text_width; int tmp_cs; if (MI_LABEL_OFFSET(mi)[i] >= lit_x_start && MI_LABEL_OFFSET(mi)[i] < lit_x_end) { /* label is in hilighted area */ fws->gc = gcs.fore_gc; tmp_cs = cs; } else { /* label is in unhilighted area */ fws->gc = off_gcs.fore_gc; tmp_cs = off_cs; } if (tmp_cs >= 0) { fws->colorset = &Colorset[tmp_cs]; fws->flags.has_colorset = 1; } fws->str = MI_LABEL(mi)[i]; b.x = fws->x = MI_LABEL_OFFSET(mi)[i]; b.width = text_width = FlocaleTextWidth( font, fws->str, strlen(fws->str)); if (!item_cleared && mpip->ev) { int s_x,s_w; if (frect_get_seg_intersection( mpip->ev->xexpose.x, mpip->ev->xexpose.width, fws->x, text_width, &s_x, &s_w)) { b.x = s_x; b.width = s_w; region = XCreateRegion(); XUnionRectWithRegion( &b, region, region); fws->flags.has_clip_region = True; fws->clip_region = region; draw_string = True; XSetRegion(dpy, fws->gc, region); } else { /* empty intersection */ draw_string = False; } } if (draw_string) { if (!item_cleared && xft_clear) { clear_menu_item_background( mpip, b.x, b.y, b.width, b.height); } FlocaleDrawString(dpy, font, fws, 0); /* hot key */ if (MI_HAS_HOTKEY(mi) && !MI_IS_TITLE(mi) && (!MI_IS_HOTKEY_AUTOMATIC(mi) || ST_USE_AUTOMATIC_HOTKEYS(ms)) && MI_HOTKEY_COLUMN(mi) == i) { FlocaleDrawUnderline( dpy, ST_PSTDFONT(ms), fws, MI_HOTKEY_COFFSET(mi)); } } } if (region) { XDestroyRegion(region); region = None; fws->flags.has_clip_region = False; fws->clip_region = None; XSetClipMask(dpy, fws->gc, None); } } /* * Draw the submenu triangle. */ if (MI_IS_POPUP(mi)) { GC tmp_gc; if (MDIM_TRIANGLE_X_OFFSET(*dim) >= lit_x_start && MDIM_TRIANGLE_X_OFFSET(*dim) < lit_x_end && is_item_selected) { /* triangle is in hilighted area */ if (ST_TRIANGLES_USE_FORE(ms)) { tmp_gc = gcs.fore_gc; } else { tmp_gc = gcs.hilight_gc; } } else { /* triangle is in unhilighted area */ if (ST_TRIANGLES_USE_FORE(ms)) { tmp_gc = off_gcs.fore_gc; } else { tmp_gc = off_gcs.hilight_gc; } } y = y_offset + (y_height - MENU_TRIANGLE_HEIGHT + relief_thickness) / 2; if (ST_TRIANGLES_USE_FORE(ms)) { DrawTrianglePattern( dpy, mpip->w, tmp_gc, tmp_gc, tmp_gc, MDIM_TRIANGLE_X_OFFSET(*dim), y, MENU_TRIANGLE_WIDTH, MENU_TRIANGLE_HEIGHT, 0, (mpip->flags.is_left_triangle) ? 'l' : 'r', ST_HAS_TRIANGLE_RELIEF(ms), !ST_HAS_TRIANGLE_RELIEF(ms), is_item_selected); } else { DrawTrianglePattern( dpy, mpip->w, gcs.hilight_gc, gcs.shadow_gc, tmp_gc, MDIM_TRIANGLE_X_OFFSET(*dim), y, MENU_TRIANGLE_WIDTH, MENU_TRIANGLE_HEIGHT, 0, (mpip->flags.is_left_triangle) ? 'l' : 'r', ST_HAS_TRIANGLE_RELIEF(ms), !ST_HAS_TRIANGLE_RELIEF(ms), is_item_selected); } } /* * Draw the item picture. */ if (MI_PICTURE(mi)) { GC tmp_gc; int tmp_cs; Bool draw_picture = True; x = menudim_middle_x_offset(mpip->dim) - MI_PICTURE(mi)->width / 2; y = y_offset + ((MI_IS_SELECTABLE(mi)) ? relief_thickness : 0); if (x >= lit_x_start && x < lit_x_end) { tmp_gc = gcs.fore_gc; tmp_cs = cs; } else { tmp_gc = off_gcs.fore_gc; tmp_cs = off_cs; } fra.mask = FRAM_DEST_IS_A_WINDOW; if (tmp_cs >= 0) { fra.mask |= FRAM_HAVE_ICON_CSET; fra.colorset = &Colorset[tmp_cs]; } b.x = x; b.y = y; b.width = MI_PICTURE(mi)->width; b.height = MI_PICTURE(mi)->height; if (!item_cleared && mpip->ev) { if (!frect_get_intersection( mpip->ev->xexpose.x, mpip->ev->xexpose.y, mpip->ev->xexpose.width, mpip->ev->xexpose.height, b.x, b.y, b.width, b.height, &b)) { draw_picture = False; } } if (draw_picture) { if ( !item_cleared && (MI_PICTURE(mi)->alpha != None || (tmp_cs >=0 && Colorset[tmp_cs].icon_alpha_percent < 100))) { clear_menu_item_background( mpip, b.x, b.y, b.width, b.height); } PGraphicsRenderPicture( dpy, mpip->w, MI_PICTURE(mi), &fra, mpip->w, tmp_gc, Scr.MonoGC, Scr.AlphaGC, b.x - x, b.y - y, b.width, b.height, b.x, b.y, b.width, b.height, False); } } /* * Draw the mini icons. */ for (i = 0; i < mpip->used_mini_icons; i++) { int k; Bool draw_picture = True; /* We need to reverse the mini icon order for left submenu * style. */ k = (ST_USE_LEFT_SUBMENUS(ms)) ? mpip->used_mini_icons - 1 - i : i; if (MI_MINI_ICON(mi)[i]) { GC tmp_gc; int tmp_cs; if (MI_PICTURE(mi)) { y = y_offset + MI_HEIGHT(mi) - MI_MINI_ICON(mi)[i]->height; } else { y = y_offset + (MI_HEIGHT(mi) + ((MI_IS_SELECTABLE(mi)) ? relief_thickness : 0) - MI_MINI_ICON(mi)[i]->height) / 2; } if (MDIM_ICON_X_OFFSET(*dim)[k] >= lit_x_start && MDIM_ICON_X_OFFSET(*dim)[k] < lit_x_end) { /* icon is in hilighted area */ tmp_gc = gcs.fore_gc; tmp_cs = cs; } else { /* icon is in unhilighted area */ tmp_gc = off_gcs.fore_gc; tmp_cs = off_cs; } fra.mask = FRAM_DEST_IS_A_WINDOW; if (tmp_cs >= 0) { fra.mask |= FRAM_HAVE_ICON_CSET; fra.colorset = &Colorset[tmp_cs]; } b.x = MDIM_ICON_X_OFFSET(*dim)[k]; b.y = y; b.width = MI_MINI_ICON(mi)[i]->width; b.height = MI_MINI_ICON(mi)[i]->height; if (!item_cleared && mpip->ev) { if (!frect_get_intersection( mpip->ev->xexpose.x, mpip->ev->xexpose.y, mpip->ev->xexpose.width, mpip->ev->xexpose.height, b.x, b.y, b.width, b.height, &b)) { draw_picture = False; } } if (draw_picture) { if (!item_cleared && (MI_MINI_ICON(mi)[i]->alpha != None || (tmp_cs >=0 && Colorset[tmp_cs].icon_alpha_percent < 100))) { clear_menu_item_background( mpip, b.x, b.y, b.width, b.height); } PGraphicsRenderPicture( dpy, mpip->w, MI_MINI_ICON(mi)[i], &fra, mpip->w, tmp_gc, Scr.MonoGC, Scr.AlphaGC, b.x - MDIM_ICON_X_OFFSET(*dim)[k], b.y - y, b.width, b.height, b.x, b.y, b.width, b.height, False); } } } return; } /* returns the center y coordinate of the menu item */ int menuitem_middle_y_offset(struct MenuItem *mi, struct MenuStyle *ms) { int r; if (!mi) { return ST_BORDER_WIDTH(ms); } r = (MI_IS_SELECTABLE(mi)) ? ST_RELIEF_THICKNESS(ms) : 0; return MI_Y_OFFSET(mi) + (MI_HEIGHT(mi) + r) / 2; } fvwm-2.7.0/fvwm/move_resize.c0000644000175000017500000032572214147024700013104 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* * * code for moving and resizing windows * */ #include "config.h" #include #include #include #include "libs/fvwmlib.h" #include "libs/FScreen.h" #include "libs/Picture.h" #include "libs/Grab.h" #include "libs/Parse.h" #include "libs/Graphics.h" #include "fvwm.h" #include "externs.h" #include "cursor.h" #include "execcontext.h" #include "commands.h" #include "misc.h" #include "screen.h" #include "menus.h" #include "menuparameters.h" #include "module_list.h" #include "module_interface.h" #include "focus.h" #include "borders.h" #include "frame.h" #include "geometry.h" #include "ewmh.h" #include "virtual.h" #include "decorations.h" #include "events.h" #include "eventhandler.h" #include "eventmask.h" #include "colormaps.h" #include "update.h" #include "stack.h" #include "move_resize.h" #include "functions.h" #include "style.h" /* ----- move globals ----- */ #define MOVE_NORMAL 0x00 #define MOVE_PAGE 0x01 #define MOVE_SCREEN 0x02 /* Animated move stuff added by Greg J. Badros, gjb@cs.washington.edu */ float rgpctMovementDefault[32] = { -.01, 0, .01, .03,.08,.18,.3,.45,.60,.75,.85,.90,.94,.97,.99,1.0 /* must end in 1.0 */ }; int cmsDelayDefault = 10; /* milliseconds */ /* current geometry of size window */ static rectangle sizew_g = { -1, -1, -1, -1 }; static int move_interactive_finish_button_mask = ((1<<(NUMBER_OF_EXTENDED_MOUSE_BUTTONS))-1) & ~0x2; static int move_drag_finish_button_mask = ((1<<(NUMBER_OF_EXTENDED_MOUSE_BUTTONS))-1) & ~0x3; /* ----- end of move globals ----- */ /* ----- resize globals ----- */ /* DO NOT USE (STATIC) GLOBALS IN THIS MODULE! * Since some functions are called from other modules unwanted side effects * (i.e. bugs.) would be created */ extern Window PressedW; static void draw_move_resize_grid(int x, int y, int width, int height); /* ----- end of resize globals ----- */ /* * * Procedure: * draw_move_resize_grid - move a window outline * * Inputs: * root - the window we are outlining * x - upper left x coordinate * y - upper left y coordinate * width - the width of the rectangle * height - the height of the rectangle * */ static int get_outline_rects( XRectangle *rects, int x, int y, int width, int height) { int i; int n; int m; n = 3; m = (width - 5) / 2; if (m < n) { n = m; } m = (height - 5) / 2; if (m < n) { n = m; } if (n < 1) { n = 1; } for (i = 0; i < n; i++) { rects[i].x = x + i; rects[i].y = y + i; rects[i].width = width - (i << 1); rects[i].height = height - (i << 1); } if (width - (n << 1) >= 5 && height - (n << 1) >= 5) { if (width - (n << 1) >= 10) { int off = (width - (n << 1)) / 3 + n; rects[i].x = x + off; rects[i].y = y + n; rects[i].width = width - (off << 1); rects[i].height = height - (n << 1); i++; } if (height - (n << 1) >= 10) { int off = (height - (n << 1)) / 3 + n; rects[i].x = x + n; rects[i].y = y + off; rects[i].width = width - (n << 1); rects[i].height = height - (off << 1); i++; } } return i; } struct { rectangle geom; struct { unsigned is_enabled : 1; } flags; } move_resize_grid = { { 0, 0, 0, 0 }, { 0 } }; static void draw_move_resize_grid(int x, int y, int width, int height) { int nrects = 0; XRectangle rects[10]; if (move_resize_grid.flags.is_enabled && x == move_resize_grid.geom.x && y == move_resize_grid.geom.y && width == move_resize_grid.geom.width && height == move_resize_grid.geom.height) { return; } memset(rects, 0, 10 * sizeof(XRectangle)); /* place the resize rectangle into the array of rectangles */ /* interleave them for best visual look */ /* draw the new one, if any */ if (move_resize_grid.flags.is_enabled /*move_resize_grid.geom.width && move_resize_grid.geom.height*/) { move_resize_grid.flags.is_enabled = 0; nrects += get_outline_rects( &(rects[0]), move_resize_grid.geom.x, move_resize_grid.geom.y, move_resize_grid.geom.width, move_resize_grid.geom.height); } if (width && height) { move_resize_grid.flags.is_enabled = 1; move_resize_grid.geom.x = x; move_resize_grid.geom.y = y; move_resize_grid.geom.width = width; move_resize_grid.geom.height = height; nrects += get_outline_rects( &(rects[nrects]), x, y, width, height); } if (nrects > 0) { XDrawRectangles(dpy, Scr.Root, Scr.XorGC, rects, nrects); XFlush(dpy); } return; } void switch_move_resize_grid(Bool state) { if (state == False) { if (move_resize_grid.flags.is_enabled) { draw_move_resize_grid(0, 0, 0, 0); } else { move_resize_grid.geom.x = 0; move_resize_grid.geom.y = 0; move_resize_grid.geom.width = 0; move_resize_grid.geom.height = 0; } } else if (!move_resize_grid.flags.is_enabled) { if (move_resize_grid.geom.width && move_resize_grid.geom.height) { draw_move_resize_grid( move_resize_grid.geom.x, move_resize_grid.geom.y, move_resize_grid.geom.width, move_resize_grid.geom.height); } } return; } static int ParsePositionArgumentSuffix( float *ret_factor, char *suffix, float wfactor, float sfactor) { int n; switch (*suffix) { case 'p': case 'P': *ret_factor = 1.0; n = 1; break; case 'w': case 'W': *ret_factor = wfactor; n = 1; break; default: *ret_factor = sfactor; n = 0; break; } return n; } static int __get_shift(int val, float factor) { int shift; if (val >= 0) { shift = (int)(val * factor + 0.5); } else { shift = (int)(val * factor - 0.5); } return shift; } /* The vars are named for the x-direction, but this is used for both x and y */ static int GetOnePositionArgument( char *s1, int window_pos, int window_size, int *pFinalPos, float sfactor, int screen_size, int screen_pos, Bool is_x) { int final_pos; float wfactor; if (s1 == 0 || *s1 == 0) { return 0; } wfactor = (float)window_size / 100; /* get start position */ switch (*s1) { case 'w': case 'W': final_pos = window_pos; s1++; break; case 'm': case 'M': { int x; int y; if ( FQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, &JunkX, &JunkY, &x, &y, &JunkMask) == False) { /* pointer is on a different screen - that's okay here */ final_pos = 0; } else { final_pos = (is_x) ? x : y; } s1++; break; } default: final_pos = screen_pos; if (*s1 != 0) { int val; int n; float f; /* parse value */ if (sscanf(s1, "-%d%n", &val, &n) >= 1) { /* i.e. -1, -+1 or --1 */ final_pos += (screen_size - window_size); val = -val; } else if ( sscanf(s1, "+%d%n", &val, &n) >= 1 || sscanf(s1, "%d%n", &val, &n) >= 1) { /* i.e. 1, +1, ++1 or +-1 */ } else { /* syntax error, ignore rest of string */ break; } s1 += n; /* parse suffix */ n = ParsePositionArgumentSuffix( &f, s1, wfactor, sfactor); s1 += n; final_pos += __get_shift(val, f); } break; } /* loop over shift arguments */ while (*s1 != 0) { int val; int n; float f; /* parse value */ if (sscanf(s1, "-%d%n", &val, &n) >= 1) { /* i.e. -1, -+1 or --1 */ val = -val; } else if ( sscanf(s1, "+%d%n", &val, &n) >= 1 || sscanf(s1, "%d%n", &val, &n) >= 1) { /* i.e. 1, +1, ++1 or +-1 */ } else { /* syntax error, ignore rest of string */ break; } s1 += n; /* parse suffix */ n = ParsePositionArgumentSuffix(&f, s1, wfactor, sfactor); s1 += n; final_pos += __get_shift(val, f); } *pFinalPos = final_pos; return 1; } /* GetMoveArguments is used for Move & AnimatedMove * It lets you specify in all the following ways * 20 30 Absolute percent position, from left edge and top * -50 50 Absolute percent position, from right edge and top * 10p 5p Absolute pixel position * 10p -0p Absolute pixel position, from bottom * w+5 w-10p Relative position, right 5%, up ten pixels * m+5 m-10p Pointer relative position, right 5%, up ten pixels * Returns 2 when x & y have parsed without error, 0 otherwise */ int GetMoveArguments( char **paction, int w, int h, int *pFinalX, int *pFinalY, Bool *fWarp, Bool *fPointer, Bool fKeep) { char *s1 = NULL; char *s2 = NULL; char *token = NULL; char *action; char *naction; int scr_x = 0; int scr_y = 0; int scr_w = Scr.MyDisplayWidth; int scr_h = Scr.MyDisplayHeight; Bool use_working_area = True; Bool global_flag_parsed = False; int retval = 0; if (!paction) { return 0; } action = *paction; action = GetNextToken(action, &s1); if (s1 && fPointer && StrEquals(s1, "pointer")) { *fPointer = True; *paction = action; free(s1); return 0; } if (s1 && StrEquals(s1, "screen")) { char *token; int scr; fscreen_scr_arg arg; fscreen_scr_arg* parg; free(s1); token = PeekToken(action, &action); scr = FScreenGetScreenArgument(token, FSCREEN_SPEC_PRIMARY); if (scr == FSCREEN_XYPOS) { arg.xypos.x = *pFinalX; arg.xypos.y = *pFinalY; parg = &arg; } else { parg = NULL; } FScreenGetScrRect(parg, scr, &scr_x, &scr_y, &scr_w, &scr_h); action = GetNextToken(action, &s1); } action = GetNextToken(action, &s2); while (!global_flag_parsed) { token = PeekToken(action, &naction); if (!token) { global_flag_parsed = True; break; } if (StrEquals(token, "Warp")) { action = naction; if (fWarp) { *fWarp = True; } } else if (StrEquals(token, "ewmhiwa")) { use_working_area = False; action = naction; } else { global_flag_parsed = True; } } if (use_working_area) { EWMH_GetWorkAreaIntersection( NULL, &scr_x, &scr_y, &scr_w, &scr_h, EWMH_USE_WORKING_AREA); } if (s1 != NULL && s2 != NULL) { retval = 0; if (fKeep == True && StrEquals(s1, "keep")) { retval++; } else if ( GetOnePositionArgument( s1, *pFinalX, w, pFinalX, (float)scr_w / 100, scr_w, scr_x, True)) { retval++; } if (fKeep == True && StrEquals(s2, "keep")) { retval++; } else if ( GetOnePositionArgument( s2, *pFinalY, h, pFinalY, (float)scr_h / 100, scr_h, scr_y, False)) { retval++; } if (retval == 0) { /* make sure warping is off for interactive moves */ *fWarp = False; } } else { /* not enough arguments, switch to current page. */ while (*pFinalX < 0) { *pFinalX = Scr.MyDisplayWidth + *pFinalX; } while (*pFinalY < 0) { *pFinalY = Scr.MyDisplayHeight + *pFinalY; } } if (s1) { free(s1); } if (s2) { free(s2); } *paction = action; return retval; } static int ParseOneResizeArgument( char *arg, int scr_size, int wa_size, int dwa_size, int base_size, int size_inc, int add_size, int *ret_size) { float factor; int val; int add_base_size = 0; int cch = strlen(arg); int tmp_size; if (cch == 0) { return 0; } if (StrEquals(arg, "keep")) { /* do not change size */ return 1; } if (cch > 1 && arg[cch-2] == 'w' && arg[cch-1] == 'a') { /* ewmh working area */ factor = (float)wa_size / 100.0; arg[cch-1] = '\0'; } else if (cch > 1 && arg[cch-2] == 'd' && arg[cch-1] == 'a') { /* ewmh dynamic working area */ factor = (float)dwa_size / 100.0; arg[cch-1] = '\0'; } else if (arg[cch-1] == 'p') { factor = 1; arg[cch-1] = '\0'; } else if (arg[cch-1] == 'c') { factor = size_inc; add_base_size = base_size; arg[cch-1] = '\0'; } else { factor = (float)scr_size / 100.0; } if (strcmp(arg,"w") == 0) { /* do not change size */ } else if (sscanf(arg,"w-%d",&val) == 1) { tmp_size = (int)(val * factor + 0.5); if (tmp_size < *ret_size) { *ret_size -= tmp_size; } else { *ret_size = 0; } } else if (sscanf(arg,"w+%d",&val) == 1 || sscanf(arg,"w%d",&val) == 1) { tmp_size = (int)(val * factor + 0.5); if (-tmp_size < *ret_size) { *ret_size += tmp_size; } else { *ret_size = 0; } } else if (sscanf(arg,"-%d",&val) == 1) { tmp_size = (int)(val * factor + 0.5); if (tmp_size < scr_size + add_size) { *ret_size = scr_size - tmp_size + add_size; } else { *ret_size = 0; } } else if (sscanf(arg,"+%d",&val) == 1 || sscanf(arg,"%d",&val) == 1) { tmp_size = (int)(val * factor + 0.5); if (-tmp_size < add_size + add_base_size) { *ret_size = tmp_size + add_size + add_base_size; } else { *ret_size = 0; } } else { return 0; } return 1; } static int GetResizeArguments( char **paction, int x, int y, int w_base, int h_base, int w_inc, int h_inc, size_borders *sb, int *pFinalW, int *pFinalH, direction_t *ret_dir, Bool *is_direction_fixed, Bool *do_warp_to_border, Bool *automatic_border_direction, Bool *detect_automatic_direction) { int n; char *naction; char *token; char *tmp_token; char *s1; char *s2; int w_add; int h_add; int has_frame_option; *ret_dir = DIR_NONE; *is_direction_fixed = False; *do_warp_to_border = False; *automatic_border_direction = False; *detect_automatic_direction = False; if (!paction) { return 0; } token = PeekToken(*paction, &naction); if (!token) { return 0; } if (StrEquals(token, "bottomright") || StrEquals(token, "br")) { int nx = x + *pFinalW - 1; int ny = y + *pFinalH - 1; n = GetMoveArguments( &naction, 0, 0, &nx, &ny, NULL, NULL, True); if (n < 2) { return 0; } *pFinalW = nx - x + 1; *pFinalH = ny - y + 1; *paction = naction; return n; } has_frame_option = 0; for ( ; ; token = PeekToken(naction, &naction)) { if (StrEquals(token, "frame")) { has_frame_option = 1; } else if (StrEquals(token, "direction")) { *ret_dir = gravity_parse_dir_argument( naction, &naction, DIR_NONE); if (*ret_dir != DIR_NONE) { *is_direction_fixed = True; } else if (*ret_dir == DIR_NONE) { tmp_token = PeekToken(naction, &naction); if (tmp_token != NULL && StrEquals(tmp_token, "automatic")) { *detect_automatic_direction = True; *is_direction_fixed = True; } } } else if (StrEquals(token, "fixeddirection")) { *is_direction_fixed = True; } else if (StrEquals(token, "warptoborder")) { tmp_token = PeekToken(naction, &naction); if (tmp_token != NULL && StrEquals(tmp_token, "automatic")) { *automatic_border_direction = True; } *do_warp_to_border = True; } else { break; } } if (has_frame_option) { w_add = 0; h_add = 0; } else { w_add = sb->total_size.width; h_add = sb->total_size.height; } s1 = NULL; if (token != NULL) { s1 = safestrdup(token); } naction = GetNextToken(naction, &s2); if (!s2) { free(s1); return 0; } *paction = naction; n = 0; n += ParseOneResizeArgument( s1, Scr.MyDisplayWidth, Scr.Desktops->ewmh_working_area.width, Scr.Desktops->ewmh_dyn_working_area.width, w_base, w_inc, w_add, pFinalW); n += ParseOneResizeArgument( s2, Scr.MyDisplayHeight, Scr.Desktops->ewmh_working_area.height, Scr.Desktops->ewmh_dyn_working_area.height, h_base, h_inc, h_add, pFinalH); free(s1); free(s2); if (n < 2) { n = 0; } return n; } static int GetResizeMoveArguments( char **paction, int w_base, int h_base, int w_inc, int h_inc, size_borders *sb, int *pFinalX, int *pFinalY, int *pFinalW, int *pFinalH, Bool *fWarp, Bool *fPointer) { char *action = *paction; direction_t dir; Bool dummy; if (!paction) { return 0; } if (GetResizeArguments( &action, *pFinalX, *pFinalY, w_base, h_base, w_inc, h_inc, sb, pFinalW, pFinalH, &dir, &dummy, &dummy, &dummy, &dummy) < 2) { return 0; } if (GetMoveArguments( &action, *pFinalW, *pFinalH, pFinalX, pFinalY, fWarp, NULL, True) < 2) { return 0; } *paction = action; return 4; } /* Positions the SizeWindow on the current ("moused") xinerama-screen */ static void position_geometry_window(const XEvent *eventp) { int x; int y; fscreen_scr_arg fscr; fscr.mouse_ev = (XEvent *)eventp; /* Probably should remove this positioning code from {builtins,fvwm}.c? */ if (Scr.gs.do_emulate_mwm) { FScreenCenterOnScreen( &fscr, FSCREEN_CURRENT, &x, &y, sizew_g.width, sizew_g.height); } else { FScreenGetScrRect(&fscr, FSCREEN_CURRENT, &x, &y, NULL, NULL); } if (x != sizew_g.x || y != sizew_g.y) { switch_move_resize_grid(False); XMoveWindow(dpy, Scr.SizeWindow, x, y); switch_move_resize_grid(True); sizew_g.x = x; sizew_g.y = y; } return; } void resize_geometry_window(void) { int w; int h; int cset = Scr.DefaultColorset; Scr.SizeStringWidth = FlocaleTextWidth(Scr.DefaultFont, GEOMETRY_WINDOW_STRING, sizeof(GEOMETRY_WINDOW_STRING) - 1); w = Scr.SizeStringWidth + 2 * GEOMETRY_WINDOW_BW; h = Scr.DefaultFont->height + 2 * GEOMETRY_WINDOW_BW; if (w != sizew_g.width || h != sizew_g.height) { XResizeWindow(dpy, Scr.SizeWindow, w, h); sizew_g.width = w; sizew_g.height = h; } if (cset >= 0) { SetWindowBackground( dpy, Scr.SizeWindow, w, h, &Colorset[cset], Pdepth, Scr.StdGC, False); } else { XSetWindowBackground(dpy, Scr.SizeWindow, Scr.StdBack); } return; } /* * * Procedure: * DisplayPosition - display the position in the dimensions window * * Inputs: * tmp_win - the current fvwm window * x, y - position of the window * */ static void DisplayPosition( const FvwmWindow *tmp_win, const XEvent *eventp, int x, int y,int Init) { char str[100]; int offset; fscreen_scr_arg fscr; FlocaleWinString fstr; if (Scr.gs.do_hide_position_window) { return; } position_geometry_window(eventp); /* Translate x,y into local screen coordinates, * in case Xinerama is used. */ fscr.xypos.x = x; fscr.xypos.y = y; FScreenTranslateCoordinates( NULL, FSCREEN_GLOBAL, &fscr, FSCREEN_XYPOS, &x, &y); (void)sprintf(str, GEOMETRY_WINDOW_POS_STRING, x, y); if (Init) { XClearWindow(dpy, Scr.SizeWindow); } else { /* just clear indside the relief lines to reduce flicker */ XClearArea(dpy, Scr.SizeWindow, GEOMETRY_WINDOW_BW, GEOMETRY_WINDOW_BW, Scr.SizeStringWidth, Scr.DefaultFont->height, False); } if (Pdepth >= 2) { RelieveRectangle( dpy, Scr.SizeWindow, 0, 0, Scr.SizeStringWidth + GEOMETRY_WINDOW_BW * 2 - 1, Scr.DefaultFont->height + GEOMETRY_WINDOW_BW * 2 - 1, Scr.StdReliefGC, Scr.StdShadowGC, GEOMETRY_WINDOW_BW); } offset = (Scr.SizeStringWidth - FlocaleTextWidth(Scr.DefaultFont, str, strlen(str))) / 2; offset += GEOMETRY_WINDOW_BW; memset(&fstr, 0, sizeof(fstr)); if (Scr.DefaultColorset >= 0) { fstr.colorset = &Colorset[Scr.DefaultColorset]; fstr.flags.has_colorset = True; } fstr.str = str; fstr.win = Scr.SizeWindow; fstr.gc = Scr.StdGC; fstr.x = offset; fstr.y = Scr.DefaultFont->ascent + GEOMETRY_WINDOW_BW; FlocaleDrawString(dpy, Scr.DefaultFont, &fstr, 0); return; } /* * * Procedure: * DisplaySize - display the size in the dimensions window * * Inputs: * tmp_win - the current fvwm window * width - the width of the rubber band * height - the height of the rubber band * */ static void DisplaySize( const FvwmWindow *tmp_win, const XEvent *eventp, int width, int height, Bool Init, Bool resetLast) { char str[100]; int dwidth,dheight,offset; size_borders b; static int last_width = 0; static int last_height = 0; FlocaleWinString fstr; if (Scr.gs.do_hide_resize_window) { return; } position_geometry_window(eventp); if (resetLast) { last_width = 0; last_height = 0; } if (last_width == width && last_height == height) { return; } last_width = width; last_height = height; get_window_borders(tmp_win, &b); dheight = height - b.total_size.height; dwidth = width - b.total_size.width; dwidth -= tmp_win->hints.base_width; dheight -= tmp_win->hints.base_height; dwidth /= tmp_win->hints.width_inc; dheight /= tmp_win->hints.height_inc; (void)sprintf(str, GEOMETRY_WINDOW_SIZE_STRING, dwidth, dheight); if (Init) { XClearWindow(dpy,Scr.SizeWindow); } else { /* just clear indside the relief lines to reduce flicker */ XClearArea( dpy, Scr.SizeWindow, GEOMETRY_WINDOW_BW, GEOMETRY_WINDOW_BW, Scr.SizeStringWidth, Scr.DefaultFont->height, False); } if (Pdepth >= 2) { RelieveRectangle( dpy, Scr.SizeWindow, 0, 0, Scr.SizeStringWidth + GEOMETRY_WINDOW_BW * 2 - 1, Scr.DefaultFont->height + GEOMETRY_WINDOW_BW*2 - 1, Scr.StdReliefGC, Scr.StdShadowGC, GEOMETRY_WINDOW_BW); } offset = (Scr.SizeStringWidth - FlocaleTextWidth(Scr.DefaultFont, str, strlen(str))) / 2; offset += GEOMETRY_WINDOW_BW; memset(&fstr, 0, sizeof(fstr)); if (Scr.DefaultColorset >= 0) { fstr.colorset = &Colorset[Scr.DefaultColorset]; fstr.flags.has_colorset = True; } fstr.str = str; fstr.win = Scr.SizeWindow; fstr.gc = Scr.StdGC; fstr.x = offset; fstr.y = Scr.DefaultFont->ascent + GEOMETRY_WINDOW_BW; FlocaleDrawString(dpy, Scr.DefaultFont, &fstr, 0); return; } static Bool resize_move_window(F_CMD_ARGS) { int FinalX = 0; int FinalY = 0; int FinalW = 0; int FinalH = 0; int n; int x,y; Bool fWarp = False; Bool fPointer = False; int dx; int dy; size_borders b; FvwmWindow *fw = exc->w.fw; Window w = exc->w.w; if (!is_function_allowed(F_MOVE, NULL, fw, RQORIG_PROGRAM_US, False)) { return False; } if (!is_function_allowed(F_RESIZE, NULL, fw, RQORIG_PROGRAM_US, True)) { return False; } /* gotta have a window */ w = FW_W_FRAME(fw); if (!XGetGeometry( dpy, w, &JunkRoot, &x, &y, (unsigned int*)&FinalW, (unsigned int*)&FinalH, (unsigned int*)&JunkBW, (unsigned int*)&JunkDepth)) { XBell(dpy, 0); return False; } FinalX = x; FinalY = y; get_window_borders(fw, &b); n = GetResizeMoveArguments( &action, fw->hints.base_width, fw->hints.base_height, fw->hints.width_inc, fw->hints.height_inc, &b, &FinalX, &FinalY, &FinalW, &FinalH, &fWarp, &fPointer); if (n < 4) { return False; } if (IS_MAXIMIZED(fw)) { /* must redraw the buttons now so that the 'maximize' button * does not stay depressed. */ SET_MAXIMIZED(fw, 0); border_draw_decorations( fw, PART_BUTTONS, (fw == Scr.Hilite), True, CLEAR_ALL, NULL, NULL); } dx = FinalX - fw->g.frame.x; dy = FinalY - fw->g.frame.y; /* size will be less or equal to requested */ constrain_size(fw, NULL, &FinalW, &FinalH, 0, 0, 0); if (IS_SHADED(fw)) { frame_setup_window( fw, FinalX, FinalY, FinalW, fw->g.frame.height, False); } else { frame_setup_window(fw, FinalX, FinalY, FinalW, FinalH, True); } if (fWarp) { FWarpPointer( dpy, None, None, 0, 0, 0, 0, FinalX - x, FinalY - y); } if (IS_MAXIMIZED(fw)) { fw->g.max.x += dx; fw->g.max.y += dy; } else { fw->g.normal.x += dx; fw->g.normal.y += dy; } update_absolute_geometry(fw); maximize_adjust_offset(fw); XFlush(dpy); return True; } void CMD_ResizeMove(F_CMD_ARGS) { FvwmWindow *fw = exc->w.fw; if (IS_EWMH_FULLSCREEN(fw)) { /* do not unmaximize ! */ CMD_ResizeMoveMaximize(F_PASS_ARGS); return; } resize_move_window(F_PASS_ARGS); return; } static void InteractiveMove( Window *win, const exec_context_t *exc, int *FinalX, int *FinalY, Bool do_start_at_pointer) { int origDragX,origDragY,DragX, DragY, DragWidth, DragHeight; int XOffset, YOffset; Window w; Bool do_move_opaque = False; w = *win; if (Scr.bo.do_install_root_cmap) { InstallRootColormap(); } else { InstallFvwmColormap(); } /* warp the pointer to the cursor position from before menu appeared */ /* domivogt (17-May-1999): an XFlush should not hurt anyway, so do it * unconditionally to remove the external */ XFlush(dpy); if (do_start_at_pointer) { if (FQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, &DragX, &DragY, &JunkX, &JunkY, &JunkMask) == False) { /* pointer is on a different screen */ DragX = 0; DragY = 0; } } else { /* Although a move is usually done with a button depressed we * have to check for ButtonRelease too since the event may be * faked. */ fev_get_evpos_or_query( dpy, Scr.Root, exc->x.elast, &DragX, &DragY); } MyXGrabServer(dpy); if (!XGetGeometry( dpy, w, &JunkRoot, &origDragX, &origDragY, (unsigned int*)&DragWidth, (unsigned int*)&DragHeight, (unsigned int*)&JunkBW, (unsigned int*)&JunkDepth)) { MyXUngrabServer(dpy); return; } MyXGrabKeyboard(dpy); if (do_start_at_pointer) { origDragX = DragX; origDragY = DragY; } if (IS_ICONIFIED(exc->w.fw)) { do_move_opaque = True; } else if (IS_MAPPED(exc->w.fw)) { float areapct; areapct = 100.0; areapct *= ((float)DragWidth / (float)Scr.MyDisplayWidth); areapct *= ((float)DragHeight / (float)Scr.MyDisplayHeight); /* round up */ areapct += 0.1; if (Scr.OpaqueSize < 0 || (float)areapct <= (float)Scr.OpaqueSize) { do_move_opaque = True; } } if (do_move_opaque) { MyXUngrabServer(dpy); } else { Scr.flags.is_wire_frame_displayed = True; } if (!do_move_opaque && IS_ICONIFIED(exc->w.fw)) { XUnmapWindow(dpy,w); } XOffset = origDragX - DragX; YOffset = origDragY - DragY; if (!Scr.gs.do_hide_position_window) { position_geometry_window(NULL); XMapRaised(dpy,Scr.SizeWindow); } __move_loop( exc, XOffset, YOffset, DragWidth, DragHeight, FinalX, FinalY, do_move_opaque, CRS_MOVE); if (!Scr.gs.do_hide_position_window) { XUnmapWindow(dpy,Scr.SizeWindow); } if (Scr.bo.do_install_root_cmap) { UninstallRootColormap(); } else { UninstallFvwmColormap(); } if (!do_move_opaque) { int event_types[2] = { EnterNotify, LeaveNotify }; /* Throw away some events that dont interest us right now. */ discard_typed_events(2, event_types); Scr.flags.is_wire_frame_displayed = False; MyXUngrabServer(dpy); } MyXUngrabKeyboard(dpy); return; } /* Perform the movement of the window. ppctMovement *must* have a 1.0 entry * somewhere in ins list of floats, and movement will stop when it hits a 1.0 * entry */ static void AnimatedMoveAnyWindow( FvwmWindow *fw, Window w, int startX, int startY, int endX, int endY, Bool fWarpPointerToo, int cmsDelay, float *ppctMovement, MenuRepaintTransparentParameters *pmrtp) { int pointerX, pointerY; int currentX, currentY; int lastX, lastY; int deltaX, deltaY; Bool first = True; XEvent evdummy; unsigned int draw_parts = PART_NONE; if (!is_function_allowed(F_MOVE, NULL, fw, RQORIG_PROGRAM_US, False)) { return; } /* set our defaults */ if (ppctMovement == NULL) { ppctMovement = rgpctMovementDefault; } if (cmsDelay < 0) { cmsDelay = cmsDelayDefault; } if (startX < 0 || startY < 0) { if ( !XGetGeometry( dpy, w, &JunkRoot, ¤tX, ¤tY, (unsigned int*)&JunkWidth, (unsigned int*)&JunkHeight, (unsigned int*)&JunkBW, (unsigned int*)&JunkDepth)) { XBell(dpy, 0); return; } if (startX < 0) { startX = currentX; } if (startY < 0) { startY = currentY; } } deltaX = endX - startX; deltaY = endY - startY; lastX = startX; lastY = startY; if (deltaX == 0 && deltaY == 0) { /* go nowhere fast */ return; } if (fw && w == FW_W_FRAME(fw)) { draw_parts = border_get_transparent_decorations_part(fw); } /* Needed for aborting */ MyXGrabKeyboard(dpy); do { currentX = startX + deltaX * (*ppctMovement); currentY = startY + deltaY * (*ppctMovement); if (lastX == currentX && lastY == currentY) { /* don't waste time in the same spot */ continue; } if (pmrtp != NULL) { update_transparent_menu_bg( pmrtp, lastX, lastY, currentX, currentY, endX, endY); } XMoveWindow(dpy,w,currentX,currentY); if (pmrtp != NULL) { repaint_transparent_menu( pmrtp, first, currentX, currentY, endX, endY, True); } else if (draw_parts != PART_NONE) { border_draw_decorations( fw, draw_parts, ((fw == get_focus_window())) ? True : False, True, CLEAR_ALL, NULL, NULL); } if (fw && pmrtp == NULL && IS_TEAR_OFF_MENU(fw)) { menu_redraw_transparent_tear_off_menu(fw, False); } if (fWarpPointerToo == True) { if (FQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, &JunkX, &JunkY, &pointerX, &pointerY, &JunkMask) == False) { /* pointer is on a different screen */ pointerX = currentX; pointerY = currentY; } else { pointerX += currentX - lastX; pointerY += currentY - lastY; } FWarpPointer( dpy, None, Scr.Root, 0, 0, 0, 0, pointerX, pointerY); } if (fw && !IS_SHADED(fw) && !Scr.bo.do_disable_configure_notify) { /* send configure notify event for windows that care * about their location */ SendConfigureNotify( fw, currentX, currentY, fw->g.frame.width, fw->g.frame.height, 0, False); #ifdef FVWM_DEBUG_MSGS fvwm_msg(DBG,"AnimatedMoveAnyWindow", "Sent ConfigureNotify (w == %d, h == %d)", fw->g.frame.width, fw->g.frame.height); #endif } XFlush(dpy); if (fw) { fw->g.frame.x = currentX; fw->g.frame.y = currentY; update_absolute_geometry(fw); maximize_adjust_offset(fw); BroadcastConfig(M_CONFIGURE_WINDOW, fw); FlushAllMessageQueues(); } usleep(cmsDelay * 1000); /* usleep takes microseconds */ /* this didn't work for me -- maybe no longer necessary since * we warn the user when they use > .5 seconds as a * between-frame delay time. * * domivogt (28-apr-1999): That is because the keyboard was not * grabbed. works nicely now. */ if (FCheckMaskEvent( dpy, ButtonPressMask|ButtonReleaseMask|KeyPressMask, &evdummy)) { /* finish the move immediately */ if (pmrtp != NULL) { update_transparent_menu_bg( pmrtp, lastX, lastY, currentX, currentY, endX, endY); } XMoveWindow(dpy,w,endX,endY); if (pmrtp != NULL) { repaint_transparent_menu( pmrtp, first, endX, endY, endX, endY, True); } break; } lastX = currentX; lastY = currentY; first = False; } while (*ppctMovement != 1.0 && ppctMovement++); MyXUngrabKeyboard(dpy); XFlush(dpy); return; } /* used for moving menus, not a client window */ void AnimatedMoveOfWindow( Window w, int startX, int startY, int endX, int endY, Bool fWarpPointerToo, int cmsDelay, float *ppctMovement, MenuRepaintTransparentParameters *pmrtp) { AnimatedMoveAnyWindow( NULL, w, startX, startY, endX, endY, fWarpPointerToo, cmsDelay, ppctMovement, pmrtp); return; } /* used for moving client windows */ void AnimatedMoveFvwmWindow( FvwmWindow *fw, Window w, int startX, int startY, int endX, int endY, Bool fWarpPointerToo, int cmsDelay, float *ppctMovement) { AnimatedMoveAnyWindow( fw, w, startX, startY, endX, endY, fWarpPointerToo, cmsDelay, ppctMovement, NULL); return; } int placement_binding(int button, KeySym keysym, int modifier, char *action) { if (keysym != 0) { /* fixme */ fvwm_msg( ERR, "placement_binding", "sorry, placement keybindings not allowed. yet."); return 1; } if (modifier != 0) { /* fixme */ fvwm_msg( ERR, "placement_binding", "sorry, placement binding modifiers not allowed. yet."); return 1; } if (strcmp(action,"-") == 0 || strcasecmp(action,"CancelPlacement") == 0) { if (keysym == 0) /* must be button binding */ { if (button == 0) { move_drag_finish_button_mask = 0; move_interactive_finish_button_mask = 0; } else if (button > 0 && button <= NUMBER_OF_EXTENDED_MOUSE_BUTTONS) { move_drag_finish_button_mask &= ~(1<<(button-1)); move_interactive_finish_button_mask &= ~(1<<(button-1)); } } } else if (strcasecmp(action,"CancelPlacementDrag") == 0) { if (keysym == 0) /* must be button binding */ { if (button == 0) { move_drag_finish_button_mask = 0; } else if (button > 0 && button <= NUMBER_OF_EXTENDED_MOUSE_BUTTONS) { move_drag_finish_button_mask &= ~(1<<(button-1)); } } } else if (strcasecmp(action,"CancelPlacementInteractive") == 0) { if (keysym == 0) /* must be button binding */ { if (button == 0) { move_interactive_finish_button_mask = 0; } else if (button > 0 && button <= NUMBER_OF_EXTENDED_MOUSE_BUTTONS) { move_interactive_finish_button_mask &= ~(1<<(button-1)); } } } else if (strcasecmp(action,"PlaceWindow") == 0) { if (keysym == 0) /* must be button binding */ { if (button == 0) { move_interactive_finish_button_mask = move_drag_finish_button_mask = (1< 0 && button <= NUMBER_OF_EXTENDED_MOUSE_BUTTONS) { move_drag_finish_button_mask |= (1<<(button-1)); move_interactive_finish_button_mask |= (1<<(button-1)); } } } else if (strcasecmp(action,"PlaceWindowDrag") == 0) { if (keysym == 0) /* must be button binding */ { if (button == 0) { move_drag_finish_button_mask = (1< 0 && button <= NUMBER_OF_EXTENDED_MOUSE_BUTTONS) { move_drag_finish_button_mask |= (1<<(button-1)); } } } else if (strcasecmp(action,"PlaceWindowInteractive") == 0) { if (keysym == 0) /* must be button binding */ { if (button == 0) { move_interactive_finish_button_mask = (1< 0 && button <= NUMBER_OF_EXTENDED_MOUSE_BUTTONS) { move_interactive_finish_button_mask |= (1<<(button-1)); } } } else { fvwm_msg( ERR, "placement_binding", "invalid action %s", action); } return 0; } /* * * Start a window move operation * */ void __move_icon( FvwmWindow *fw, int x, int y, int old_x, int old_y, Bool do_move_animated, Bool do_warp_pointer) { rectangle gt; rectangle gp; Bool has_icon_title; Bool has_icon_picture; Window tw; int tx; int ty; set_icon_position(fw, x, y); broadcast_icon_geometry(fw, False); has_icon_title = get_visible_icon_title_geometry(fw, >); has_icon_picture = get_visible_icon_picture_geometry(fw, &gp); if (has_icon_picture) { tw = FW_W_ICON_PIXMAP(fw); tx = gp.x; ty = gp.y; } else if (has_icon_title) { tw = FW_W_ICON_TITLE(fw); tx = gt.x; ty = gt.y; } else { return; } if (do_move_animated) { AnimatedMoveOfWindow( tw, -1, -1, tx, ty, do_warp_pointer, -1, NULL, NULL); do_warp_pointer = 0; } if (has_icon_title) { XMoveWindow(dpy, FW_W_ICON_TITLE(fw), gt.x, gt.y); } if (has_icon_picture) { XMoveWindow(dpy, FW_W_ICON_PIXMAP(fw), gp.x, gp.y); if (fw->Desk == Scr.CurrentDesk) { XMapWindow(dpy, FW_W_ICON_PIXMAP(fw)); if (has_icon_title) { XMapWindow(dpy, FW_W_ICON_TITLE(fw)); } } } if (do_warp_pointer) { FWarpPointer(dpy, None, None, 0, 0, 0, 0, x - old_x, y - old_y); } return; } static void __move_window(F_CMD_ARGS, Bool do_animate, int mode) { int FinalX = 0; int FinalY = 0; int n; int x; int y; int width, height; int page_x, page_y; Bool fWarp = False; Bool fPointer = False; int dx; int dy; FvwmWindow *fw = exc->w.fw; Window w; if (!is_function_allowed(F_MOVE, NULL, fw, RQORIG_PROGRAM_US, False)) { return; } /* gotta have a window */ w = FW_W_FRAME(fw); if (IS_ICONIFIED(fw)) { if (FW_W_ICON_PIXMAP(fw) != None) { w = FW_W_ICON_PIXMAP(fw); XUnmapWindow(dpy,FW_W_ICON_TITLE(fw)); } else { w = FW_W_ICON_TITLE(fw); } if (w == None && (mode == MOVE_PAGE || mode == MOVE_SCREEN)) { w = FW_W_FRAME(fw); } } if ( !XGetGeometry( dpy, w, &JunkRoot, &x, &y, (unsigned int*)&width, (unsigned int*)&height, (unsigned int*)&JunkBW, (unsigned int*)&JunkDepth)) { return; } if (mode == MOVE_PAGE && IS_STICKY_ACROSS_PAGES(fw)) { return; } if (mode == MOVE_PAGE) { rectangle r; rectangle s; rectangle t; do_animate = False; r.x = x; r.y = y; r.width = width; r.height = height; get_absolute_geometry(&t, &r); get_page_offset_rectangle(&page_x, &page_y, &t); if (!get_page_arguments(action, &page_x, &page_y)) { page_x = Scr.Vx; page_y = Scr.Vy; } s.x = page_x - Scr.Vx; s.y = page_y - Scr.Vy; s.width = Scr.MyDisplayWidth; s.height = Scr.MyDisplayHeight; fvwmrect_move_into_rectangle(&r, &s); FinalX = r.x; FinalY = r.y; } else if (mode == MOVE_SCREEN) { rectangle r; rectangle s; rectangle p; int fscreen; do_animate = False; fscreen = FScreenGetScreenArgument( action, FSCREEN_SPEC_CURRENT); FScreenGetScrRect( NULL, fscreen, &s.x, &s.y, &s.width, &s.height); page_x = Scr.Vx; page_y = Scr.Vy; r.x = x; r.y = y; r.width = width; r.height = height; p.x = page_x - Scr.Vx; p.y = page_y - Scr.Vy; p.width = Scr.MyDisplayWidth; p.height = Scr.MyDisplayHeight; /* move to page first */ fvwmrect_move_into_rectangle(&r, &p); /* then move to screen */ fvwmrect_move_into_rectangle(&r, &s); FinalX = r.x; FinalY = r.y; } else { FinalX = x; FinalY = y; n = GetMoveArguments( &action, width, height, &FinalX, &FinalY, &fWarp, &fPointer, True); if (n != 2 || fPointer) { InteractiveMove(&w, exc, &FinalX, &FinalY, fPointer); } else if (IS_ICONIFIED(fw)) { SET_ICON_MOVED(fw, 1); } } if (w == FW_W_FRAME(fw)) { dx = FinalX - fw->g.frame.x; dy = FinalY - fw->g.frame.y; if (do_animate) { AnimatedMoveFvwmWindow( fw, w, -1, -1, FinalX, FinalY, fWarp, -1, NULL); } frame_setup_window( fw, FinalX, FinalY, fw->g.frame.width, fw->g.frame.height, True); if (fWarp & !do_animate) { FWarpPointer( dpy, None, None, 0, 0, 0, 0, FinalX - x, FinalY - y); } if (IS_MAXIMIZED(fw)) { fw->g.max.x += dx; fw->g.max.y += dy; } else { fw->g.normal.x += dx; fw->g.normal.y += dy; } update_absolute_geometry(fw); maximize_adjust_offset(fw); XFlush(dpy); } else /* icon window */ { __move_icon(fw, FinalX, FinalY, x, y, do_animate, fWarp); XFlush(dpy); } focus_grab_buttons_on_layer(fw->layer); return; } void CMD_Move(F_CMD_ARGS) { __move_window(F_PASS_ARGS, False, MOVE_NORMAL); return; } void CMD_AnimatedMove(F_CMD_ARGS) { __move_window(F_PASS_ARGS, True, MOVE_NORMAL); return; } void CMD_MoveToPage(F_CMD_ARGS) { __move_window(F_PASS_ARGS, False, MOVE_PAGE); return; } void CMD_MoveToScreen(F_CMD_ARGS) { __move_window(F_PASS_ARGS, False, MOVE_SCREEN); return; } static void update_pos( int *dest_score, int *dest_pos, int current_pos, int requested_pos) { int requested_score; requested_score = abs(current_pos - requested_pos); if (requested_score < *dest_score) { *dest_pos = requested_pos; *dest_score = requested_score; } return; } /* This function does the SnapAttraction stuff. It takes x and y coordinates * (*px and *py) and returns the snapped values. */ static void DoSnapAttract( FvwmWindow *fw, int Width, int Height, int *px, int *py) { int nyt,nxl; rectangle self; int score_x; int score_y; nxl = -99999; nyt = -99999; score_x = 99999999; score_y = 99999999; self.x = *px; self.y = *py; self.width = Width; self.height = Height; { rectangle g; Bool rc; rc = get_visible_icon_title_geometry(fw, &g); if (rc == True) { self.height += g.height; } } /* * Snap grid handling */ if (fw->snap_grid_x > 1 && nxl == -99999) { if (*px != *px / fw->snap_grid_x * fw->snap_grid_x) { nxl = (*px + ((*px >= 0) ? fw->snap_grid_x : -fw->snap_grid_x) / 2) / fw->snap_grid_x * fw->snap_grid_x; } } if (fw->snap_grid_y > 1 && nyt == -99999) { if (*py != *py / fw->snap_grid_y * fw->snap_grid_y) { nyt = (*py + ((*py >= 0) ? fw->snap_grid_y : -fw->snap_grid_y) / 2) / fw->snap_grid_y * fw->snap_grid_y; } } /* * snap attraction */ /* snap to other windows or icons*/ if (fw->snap_attraction.proximity > 0 && (fw->snap_attraction.mode & (SNAP_ICONS | SNAP_WINDOWS | SNAP_SAME))) { FvwmWindow *tmp; int maskout = (SNAP_SCREEN | SNAP_SCREEN_WINDOWS | SNAP_SCREEN_ICONS | SNAP_SCREEN_ALL); for (tmp = Scr.FvwmRoot.next; tmp; tmp = tmp->next) { rectangle other; if (fw->Desk != tmp->Desk || fw == tmp) { continue; } /* check snapping type */ switch (fw->snap_attraction.mode & ~(maskout)) { case SNAP_WINDOWS: /* we only snap windows */ if (IS_ICONIFIED(tmp) || IS_ICONIFIED(fw)) { continue; } break; case SNAP_ICONS: /* we only snap icons */ if (!IS_ICONIFIED(tmp) || !IS_ICONIFIED(fw)) { continue; } break; case SNAP_SAME: /* we don't snap unequal */ if (IS_ICONIFIED(tmp) != IS_ICONIFIED(fw)) { continue; } break; default: /* All */ /* NOOP */ break; } /* get other window dimensions */ get_visible_window_or_icon_geometry(tmp, &other); if (other.x >= Scr.MyDisplayWidth || other.x + other.width <= 0 || other.y >= Scr.MyDisplayHeight || other.y + other.height <= 0) { /* do not snap to windows that are not currently * visible */ continue; } /* snap horizontally */ if ( other.y + other.height > *py && other.y < *py + self.height) { if (*px + self.width >= other.x && *px + self.width < other.x + fw->snap_attraction.proximity) { update_pos( &score_x, &nxl, *px, other.x - self.width); } if (*px + self.width >= other.x - fw->snap_attraction.proximity && *px + self.width < other.x) { update_pos( &score_x, &nxl, *px, other.x - self.width); } if (*px <= other.x + other.width && *px > other.x + other.width - fw->snap_attraction.proximity) { update_pos( &score_x, &nxl, *px, other.x + other.width); } if (*px <= other.x + other.width + fw->snap_attraction.proximity && *px > other.x + other.width) { update_pos( &score_x, &nxl, *px, other.x + other.width); } } /* snap vertically */ if ( other.x + other.width > *px && other.x < *px + self.width) { if (*py + self.height >= other.y && *py + self.height < other.y + fw->snap_attraction.proximity) { update_pos( &score_y, &nyt, *py, other.y - self.height); } if (*py + self.height >= other.y - fw->snap_attraction.proximity && *py + self.height < other.y) { update_pos( &score_y, &nyt, *py, other.y - self.height); } if (*py <= other.y + other.height && *py > other.y + other.height - fw->snap_attraction.proximity) { update_pos( &score_y, &nyt, *py, other.y + other.height); } if (*py <= other.y + other.height + fw->snap_attraction.proximity && *py > other.y + other.height) { update_pos( &score_y, &nyt, *py, other.y + other.height); } } } /* for */ } /* snap to other windows */ /* snap to screen egdes */ if (fw->snap_attraction.proximity > 0 && ( ( fw->snap_attraction.mode & SNAP_SCREEN && ( fw->snap_attraction.mode & SNAP_SAME || ( IS_ICONIFIED(fw) && fw->snap_attraction.mode & SNAP_ICONS ) || ( !IS_ICONIFIED(fw) && fw->snap_attraction.mode & SNAP_WINDOWS ))) || ( !IS_ICONIFIED(fw) && fw->snap_attraction.mode & SNAP_SCREEN_WINDOWS ) || ( IS_ICONIFIED(fw) && fw->snap_attraction.mode & SNAP_SCREEN_ICONS ) || fw->snap_attraction.mode & SNAP_SCREEN_ALL )) { /* vertically */ if (!(Scr.MyDisplayWidth < (*px) || (*px + self.width) < 0)) { if (*py + self.height >= Scr.MyDisplayHeight && *py + self.height < Scr.MyDisplayHeight + fw->snap_attraction.proximity) { update_pos( &score_y, &nyt, *py, Scr.MyDisplayHeight - self.height); } if (*py + self.height >= Scr.MyDisplayHeight - fw->snap_attraction.proximity && *py + self.height < Scr.MyDisplayHeight) { update_pos( &score_y, &nyt, *py, Scr.MyDisplayHeight - self.height); } if ((*py <= 0)&&(*py > - fw->snap_attraction.proximity)) { update_pos(&score_y, &nyt, *py, 0); } if ((*py <= fw->snap_attraction.proximity)&&(*py > 0)) { update_pos(&score_y, &nyt, *py, 0); } } /* vertically */ /* horizontally */ if (!(Scr.MyDisplayHeight < (*py) || (*py + self.height) < 0)) { if (*px + self.width >= Scr.MyDisplayWidth && *px + self.width < Scr.MyDisplayWidth + fw->snap_attraction.proximity) { update_pos( &score_x, &nxl, *px, Scr.MyDisplayWidth - self.width); } if (*px + self.width >= Scr.MyDisplayWidth - fw->snap_attraction.proximity && *px + self.width < Scr.MyDisplayWidth) { update_pos( &score_x, &nxl, *px, Scr.MyDisplayWidth - self.width); } if ((*px <= 0) && (*px > - fw->snap_attraction.proximity)) { update_pos(&score_x, &nxl, *px, 0); } if ((*px <= fw->snap_attraction.proximity) && (*px > 0)) { update_pos(&score_x, &nxl, *px, 0); } } /* horizontally */ } /* snap to screen edges */ if (nxl != -99999) { *px = nxl; } if (nyt != -99999) { *py = nyt; } /* * Resist moving windows beyond the edge of the screen */ if (fw->edge_resistance_move > 0) { /* snap to right edge */ if ( *px + Width > Scr.MyDisplayWidth && *px + Width < Scr.MyDisplayWidth + fw->edge_resistance_move) { *px = Scr.MyDisplayWidth - Width; } /* snap to left edge */ else if ((*px < 0) && (*px > -fw->edge_resistance_move)) { *px = 0; } /* snap to bottom edge */ if ( *py + Height > Scr.MyDisplayHeight && *py + Height < Scr.MyDisplayHeight + fw->edge_resistance_move) { *py = Scr.MyDisplayHeight - Height; } /* snap to top edge */ else if (*py < 0 && *py > -fw->edge_resistance_move) { *py = 0; } } /* Resist moving windows between xineramascreens */ if (fw->edge_resistance_xinerama_move > 0 && FScreenIsEnabled()) { int scr_x0, scr_y0; int scr_x1, scr_y1; Bool do_recalc_rectangle = False; FScreenGetResistanceRect( *px, *py, Width, Height, &scr_x0, &scr_y0, &scr_x1, &scr_y1); /* snap to right edge */ if (scr_x1 < Scr.MyDisplayWidth && *px + Width >= scr_x1 && *px + Width < scr_x1 + fw->edge_resistance_xinerama_move) { *px = scr_x1 - Width; do_recalc_rectangle = True; } /* snap to left edge */ else if ( scr_x0 > 0 && *px <= scr_x0 && scr_x0 - *px < fw->edge_resistance_xinerama_move) { *px = scr_x0; do_recalc_rectangle = True; } if (do_recalc_rectangle) { /* Snapping in X direction can move the window off a * screen. Thus, it may no longer be necessary to snap * in Y direction. */ FScreenGetResistanceRect( *px, *py, Width, Height, &scr_x0, &scr_y0, &scr_x1, &scr_y1); } /* snap to bottom edge */ if (scr_y1 < Scr.MyDisplayHeight && *py + Height >= scr_y1 && *py + Height < scr_y1 + fw->edge_resistance_xinerama_move) { *py = scr_y1 - Height; } /* snap to top edge */ else if ( scr_y0 > 0 && *py <= scr_y0 && scr_y0 - *py < fw->edge_resistance_xinerama_move) { *py = scr_y0; } } return; } /* * * Move the rubberband around, return with the new window location * * Returns True if the window has to be resized after the move. * */ Bool __move_loop( const exec_context_t *exc, int XOffset, int YOffset, int Width, int Height, int *FinalX, int *FinalY, Bool do_move_opaque, int cursor) { extern Window bad_window; Bool is_finished = False; Bool is_aborted = False; int xl,xl2,yt,yt2,delta_x,delta_y,paged; unsigned int button_mask = 0; FvwmWindow fw_copy; int dx = Scr.EdgeScrollX ? Scr.EdgeScrollX : Scr.MyDisplayWidth; int dy = Scr.EdgeScrollY ? Scr.EdgeScrollY : Scr.MyDisplayHeight; const int vx = Scr.Vx; const int vy = Scr.Vy; int xl_orig = 0; int yt_orig = 0; int cnx = 0; int cny = 0; int x_virtual_offset = 0; int y_virtual_offset = 0; Bool sent_cn = False; Bool do_resize_too = False; int x_bak; int y_bak; Window move_w = None; int orig_icon_x = 0; int orig_icon_y = 0; Bool do_snap = True; Bool was_snapped = False; /* if Alt is initially pressed don't enable no-snap until Alt is * released */ Bool nosnap_enabled = False; /* Must not set placed by button if the event is a modified KeyEvent */ Bool is_fake_event; FvwmWindow *fw = exc->w.fw; unsigned int draw_parts = PART_NONE; XEvent e; if (!GrabEm(cursor, GRAB_NORMAL)) { XBell(dpy, 0); return False; } if (!IS_MAPPED(fw) && !IS_ICONIFIED(fw)) { do_move_opaque = False; } bad_window = None; if (IS_ICONIFIED(fw)) { if (FW_W_ICON_PIXMAP(fw) != None) { move_w = FW_W_ICON_PIXMAP(fw); } else if (FW_W_ICON_TITLE(fw) != None) { move_w = FW_W_ICON_TITLE(fw); } } else { move_w = FW_W_FRAME(fw); } if ( !XGetGeometry( dpy, move_w, &JunkRoot, &x_bak, &y_bak, (unsigned int*)&JunkWidth, (unsigned int*)&JunkHeight, (unsigned int*)&JunkBW, (unsigned int*)&JunkDepth)) { /* This is allright here since the window may not be mapped * yet. */ } if (IS_ICONIFIED(fw)) { rectangle g; get_visible_icon_geometry(fw, &g); orig_icon_x = g.x; orig_icon_y = g.y; } /* make a copy of the fw structure for sending to the pager */ memcpy(&fw_copy, fw, sizeof(FvwmWindow)); /* prevent flicker when paging */ SET_WINDOW_BEING_MOVED_OPAQUE(fw, do_move_opaque); if (FQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, &xl, &yt, &JunkX, &JunkY, &button_mask) == False) { /* pointer is on a different screen */ xl = 0; yt = 0; } else { xl += XOffset; yt += YOffset; } button_mask &= DEFAULT_ALL_BUTTONS_MASK; xl_orig = xl; yt_orig = yt; /* draw initial outline */ if (!IS_ICONIFIED(fw) && ((!do_move_opaque && !Scr.gs.do_emulate_mwm) || !IS_MAPPED(fw))) { draw_move_resize_grid(xl, yt, Width - 1, Height - 1); } if (move_w == FW_W_FRAME(fw) && do_move_opaque) { draw_parts = border_get_transparent_decorations_part(fw); } DisplayPosition(fw, exc->x.elast, xl, yt, True); memset(&e, 0, sizeof(e)); /* Unset the placed by button mask. * If the move is canceled this will remain as zero. */ fw->placed_by_button = 0; while (!is_finished && bad_window != FW_W(fw)) { int rc = 0; int old_xl; int old_yt; old_xl = xl; old_yt = yt; /* wait until there is an interesting event */ while (rc != -1 && (!FPending(dpy) || !FCheckMaskEvent( dpy, ButtonPressMask | ButtonReleaseMask | KeyPressMask | PointerMotionMask | ButtonMotionMask | ExposureMask, &e))) { XEvent le; int x; int y; fev_get_last_event(&le); xl -= XOffset; yt -= YOffset; rc = HandlePaging( &le, dx, dy, &xl, &yt, &delta_x, &delta_y, False, False, True, fw->edge_delay_ms_move); /* Fake an event to force window reposition */ if (delta_x) { x_virtual_offset = 0; } xl += XOffset; if (delta_y) { y_virtual_offset = 0; } yt += YOffset; if (do_snap) { DoSnapAttract(fw, Width, Height, &xl, &yt); was_snapped = True; } fev_make_null_event(&e, dpy); e.type = MotionNotify; e.xmotion.time = fev_get_evtime(); if (FQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, &x, &y, &JunkX, &JunkY, &JunkMask) == True) { e.xmotion.x_root = x; e.xmotion.y_root = y; } else { /* pointer is on a different screen */ e.xmotion.x_root = 0; e.xmotion.y_root = 0; } e.xmotion.state = JunkMask; e.xmotion.same_screen = True; break; } if (rc == -1) { /* block until an event arrives */ /* dv (2004-07-01): With XFree 4.1.0.1, some Mouse * events are not reported to fvwm when the pointer * moves very fast and suddenly stops in the corner of * the screen. Handle EnterNotify/LeaveNotify events * too to get an idea where the pointer might be. */ FMaskEvent( dpy, ButtonPressMask | ButtonReleaseMask | KeyPressMask | PointerMotionMask | ButtonMotionMask | ExposureMask | EnterWindowMask | LeaveWindowMask, &e); } /* discard extra events before a logical release */ if (e.type == MotionNotify || e.type == EnterNotify || e.type == LeaveNotify) { while (FPending(dpy) > 0 && FCheckMaskEvent( dpy, ButtonMotionMask | PointerMotionMask | ButtonPressMask | ButtonRelease | KeyPressMask | EnterWindowMask | LeaveWindowMask, &e)) { if (e.type == ButtonPress || e.type == ButtonRelease || e.type == KeyPress) { break; } } } if (e.type == EnterNotify || e.type == LeaveNotify) { XEvent e2; int x; int y; /* Query the pointer to catch the latest information. * This *is* necessary. */ if (FQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, &x, &y, &JunkX, &JunkY, &JunkMask) == True) { fev_make_null_event(&e2, dpy); e2.type = MotionNotify; e2.xmotion.time = fev_get_evtime(); e2.xmotion.x_root = x; e2.xmotion.y_root = y; e2.xmotion.state = JunkMask; e2.xmotion.same_screen = True; e = e2; fev_fake_event(&e); } else { /* pointer is on a different screen, * ignore event */ } } is_fake_event = False; /* Handle a limited number of key press events to allow * mouseless operation */ if (e.type == KeyPress) { Keyboard_shortcuts( &e, fw, &x_virtual_offset, &y_virtual_offset, ButtonRelease); is_fake_event = (e.type != KeyPress); } switch (e.type) { case KeyPress: if (!(e.xkey.state & Mod1Mask)) { nosnap_enabled = True; } do_snap = nosnap_enabled && (e.xkey.state & Mod1Mask) ? False : True; /* simple code to bag out of move - CKH */ if (XLookupKeysym(&(e.xkey), 0) == XK_Escape) { if (!do_move_opaque) { switch_move_resize_grid(False); } if (!IS_ICONIFIED(fw)) { if (do_move_opaque) { *FinalX = fw->g.frame.x; *FinalY = fw->g.frame.y; } } else { *FinalX = orig_icon_x; *FinalY = orig_icon_y; } is_aborted = True; is_finished = True; } break; case ButtonPress: if (e.xbutton.button <= NUMBER_OF_MOUSE_BUTTONS && ((Button1Mask << (e.xbutton.button - 1)) & button_mask)) { /* No new button was pressed, just a delayed * event */ break; } if (!IS_MAPPED(fw) && ((e.xbutton.button == 2 && !Scr.gs.do_emulate_mwm) || (e.xbutton.button == 1 && Scr.gs.do_emulate_mwm && (e.xbutton.state & ShiftMask)))) { do_resize_too = True; /* Fallthrough to button-release */ } else if (!button_mask && e.xbutton.button <= NUMBER_OF_EXTENDED_MOUSE_BUTTONS && e.xbutton.button > 0 && (move_interactive_finish_button_mask & (1<<(e.xbutton.button-1)))) { do_resize_too = False; break; } else if (button_mask && e.xbutton.button <= NUMBER_OF_EXTENDED_MOUSE_BUTTONS && e.xbutton.button > 0 && (move_drag_finish_button_mask & (1<<(e.xbutton.button-1)))) { do_resize_too = False; /* Fallthrough to button-release */ } else { /* Abort the move if * - the move started with a pressed button * and another button was pressed during the * operation * - Any button not in the * move_finish_button_mask is pressed */ /* if (button_mask) */ /* - button_mask will always be set here. * only add an if if we want to be able to * place windows dragged by other means * than releasing the initial button. */ { if (!do_move_opaque) { switch_move_resize_grid(False); } if (!IS_ICONIFIED(fw)) { *FinalX = fw->g.frame.x; *FinalY = fw->g.frame.y; } else { *FinalX = orig_icon_x; *FinalY = orig_icon_y; } is_aborted = True; is_finished = True; } break; } case ButtonRelease: if (!is_fake_event) { fw->placed_by_button = e.xbutton.button; } if (!do_move_opaque) { switch_move_resize_grid(False); } xl2 = e.xbutton.x_root + XOffset + x_virtual_offset; yt2 = e.xbutton.y_root + YOffset + y_virtual_offset; /* ignore the position of the button release if it was * on a different page. */ if (!(((xl < 0 && xl2 >= 0) || (xl >= 0 && xl2 < 0) || (yt < 0 && yt2 >= 0) || (yt >= 0 && yt2 < 0)) && (abs(xl - xl2) > Scr.MyDisplayWidth / 2 || abs(yt - yt2) > Scr.MyDisplayHeight / 2))) { xl = xl2; yt = yt2; } if (xl != xl_orig || yt != yt_orig || vx != Scr.Vx || vy != Scr.Vy || was_snapped) { /* only snap if the window actually moved! */ if (do_snap) { DoSnapAttract( fw, Width, Height, &xl, &yt); was_snapped = True; } } *FinalX = xl; *FinalY = yt; is_finished = True; break; case MotionNotify: if (e.xmotion.same_screen == False) { continue; } if (!(e.xmotion.state & Mod1Mask)) { nosnap_enabled = True; } do_snap = nosnap_enabled && (e.xmotion.state & Mod1Mask) ? False : True; xl = e.xmotion.x_root; yt = e.xmotion.y_root; if (xl > 0 && xl < Scr.MyDisplayWidth - 1) { /* pointer was moved away from the left/right * border with the mouse, reset the virtual x * offset */ x_virtual_offset = 0; } if (yt > 0 && yt < Scr.MyDisplayHeight - 1) { /* pointer was moved away from the top/bottom * border with the mouse, reset the virtual y * offset */ y_virtual_offset = 0; } xl += XOffset + x_virtual_offset; yt += YOffset + y_virtual_offset; if (do_snap) { DoSnapAttract(fw, Width, Height, &xl, &yt); was_snapped = True; } /* check Paging request once and only once after * outline redrawn redraw after paging if needed * - mab */ for (paged = 0; paged <= 1; paged++) { if (!do_move_opaque) { draw_move_resize_grid( xl, yt, Width - 1, Height - 1); } else { if (IS_ICONIFIED(fw)) { set_icon_position(fw, xl, yt); move_icon_to_position(fw); broadcast_icon_geometry( fw, False); } else { XMoveWindow( dpy, FW_W_FRAME(fw), xl, yt); } } DisplayPosition(fw, &e, xl, yt, False); /* prevent window from lagging behind mouse * when paging - mab */ if (paged == 0) { XEvent le; xl = e.xmotion.x_root; yt = e.xmotion.y_root; fev_get_last_event(&le); HandlePaging( &le, dx, dy, &xl, &yt, &delta_x, &delta_y, False, False, False, fw->edge_delay_ms_move); if (delta_x) { x_virtual_offset = 0; } xl += XOffset; if (delta_y) { y_virtual_offset = 0; } yt += YOffset; if (do_snap) { DoSnapAttract( fw, Width, Height, &xl, &yt); was_snapped = True; } if (!delta_x && !delta_y) { /* break from while * (paged <= 1) */ break; } } } /* dv (13-Jan-2014): Without this XFlush the modules * (and probably other windows too) sometimes get their * expose only after the next motion step. */ XFlush(dpy); break; case Expose: if (!do_move_opaque) { /* must undraw the rubber band in case the * event causes some drawing */ switch_move_resize_grid(False); } dispatch_event(&e); if (!do_move_opaque) { draw_move_resize_grid( xl, yt, Width - 1, Height - 1); } break; default: /* cannot happen */ break; } /* switch */ xl += x_virtual_offset; yt += y_virtual_offset; if (do_move_opaque && !IS_ICONIFIED(fw) && !IS_SHADED(fw) && !Scr.bo.do_disable_configure_notify) { /* send configure notify event for windows that care * about their location; don't send anything if * position didn't change */ if (!sent_cn || cnx != xl || cny != yt) { cnx = xl; cny = yt; sent_cn = True; SendConfigureNotify( fw, xl, yt, Width, Height, 0, False); #ifdef FVWM_DEBUG_MSGS fvwm_msg( DBG, "frame_setup_window", "Sent ConfigureNotify (w %d, h %d)", Width, Height); #endif } } if (do_move_opaque) { if (!IS_ICONIFIED(fw)) { fw_copy.g.frame.x = xl; fw_copy.g.frame.y = yt; } if (xl != old_xl || yt != old_yt) { /* only do this with opaque moves, (i.e. the * server is not grabbed) */ if (draw_parts != PART_NONE) { border_draw_decorations( fw, draw_parts, ((fw == get_focus_window())) ? True : False, True, CLEAR_ALL, NULL, NULL); } if (IS_TEAR_OFF_MENU(fw)) { menu_redraw_transparent_tear_off_menu( fw, False); } BroadcastConfig(M_CONFIGURE_WINDOW, &fw_copy); FlushAllMessageQueues(); } } } /* while (!is_finished) */ if (!Scr.gs.do_hide_position_window) { XUnmapWindow(dpy,Scr.SizeWindow); } if (is_aborted || bad_window == FW_W(fw)) { if (vx != Scr.Vx || vy != Scr.Vy) { MoveViewport(vx, vy, False); } if (is_aborted && do_move_opaque) { XMoveWindow(dpy, move_w, x_bak, y_bak); if (draw_parts != PART_NONE) { border_draw_decorations( fw, draw_parts, ((fw == get_focus_window())) ? True : False, True, CLEAR_ALL, NULL, NULL); } menu_redraw_transparent_tear_off_menu(fw, False); } if (bad_window == FW_W(fw)) { XUnmapWindow(dpy, move_w); border_undraw_decorations(fw); XBell(dpy, 0); } } if (!is_aborted && bad_window != FW_W(fw) && IS_ICONIFIED(fw)) { SET_ICON_MOVED(fw, 1); } UngrabEm(GRAB_NORMAL); if (!do_resize_too) { /* Don't wait for buttons to come up when user is placing a new * window and wants to resize it. */ WaitForButtonsUp(True); } SET_WINDOW_BEING_MOVED_OPAQUE(fw, 0); bad_window = None; return do_resize_too; } void CMD_MoveThreshold(F_CMD_ARGS) { int val = 0; if (GetIntegerArguments(action, NULL, &val, 1) < 1 || val < 0) { Scr.MoveThreshold = DEFAULT_MOVE_THRESHOLD; } else { Scr.MoveThreshold = val; } return; } void CMD_OpaqueMoveSize(F_CMD_ARGS) { int val; if (GetIntegerArguments(action, NULL, &val, 1) < 1) { if (strncasecmp(action, "unlimited", 9) == 0) { Scr.OpaqueSize = -1; } else { Scr.OpaqueSize = DEFAULT_OPAQUE_MOVE_SIZE; } } else { Scr.OpaqueSize = val; } return; } static char *hide_options[] = { "never", "move", "resize", NULL }; void CMD_HideGeometryWindow(F_CMD_ARGS) { char *token = PeekToken(action, NULL); Scr.gs.do_hide_position_window = 0; Scr.gs.do_hide_resize_window = 0; switch(GetTokenIndex(token, hide_options, 0, NULL)) { case 0: break; case 1: Scr.gs.do_hide_position_window = 1; break; case 2: Scr.gs.do_hide_resize_window = 1; break; default: Scr.gs.do_hide_position_window = 1; Scr.gs.do_hide_resize_window = 1; break; } return; } void CMD_SnapAttraction(F_CMD_ARGS) { char *cmd; size_t len; len = strlen(action); len += 99; cmd = safemalloc(len); sprintf(cmd, "Style * SnapAttraction %s", action); fvwm_msg( OLD, "CMD_SnapAttraction", "The command SnapAttraction is obsolete. Please use the" " following command instead:\n\n%s", cmd); execute_function( cond_rc, exc, cmd, FUNC_DONT_REPEAT | FUNC_DONT_EXPAND_COMMAND); free(cmd); return; } void CMD_SnapGrid(F_CMD_ARGS) { char *cmd; size_t len; len = strlen(action); len += 99; cmd = safemalloc(len); sprintf(cmd, "Style * SnapGrid %s", action); fvwm_msg( OLD, "CMD_SnapGrid", "The command SnapGrid is obsolete. Please use the following" " command instead:\n\n%s", cmd); execute_function( cond_rc, exc, cmd, FUNC_DONT_REPEAT | FUNC_DONT_EXPAND_COMMAND); free(cmd); return; } static Pixmap XorPixmap = None; void CMD_XorValue(F_CMD_ARGS) { int val; XGCValues gcv; unsigned long gcm; if (GetIntegerArguments(action, NULL, &val, 1) != 1) { val = 0; } PictureUseDefaultVisual(); gcm = GCFunction|GCLineWidth|GCForeground|GCFillStyle|GCSubwindowMode; gcv.subwindow_mode = IncludeInferiors; gcv.function = GXxor; gcv.line_width = 1; /* use passed in value, or try to calculate appropriate value if 0 */ /* ctwm method: */ /* gcv.foreground = (val1)?(val1):((((unsigned long) 1) << Scr.d_depth) - 1); */ /* Xlib programming manual suggestion: */ gcv.foreground = (val)? (val):(PictureBlackPixel() ^ PictureWhitePixel()); gcv.fill_style = FillSolid; gcv.subwindow_mode = IncludeInferiors; /* modify XorGC, only create once */ if (Scr.XorGC) { XChangeGC(dpy, Scr.XorGC, gcm, &gcv); } else { Scr.XorGC = fvwmlib_XCreateGC(dpy, Scr.Root, gcm, &gcv); } /* free up XorPixmap if neccesary */ if (XorPixmap != None) { XFreePixmap(dpy, XorPixmap); XorPixmap = None; } PictureUseFvwmVisual(); return; } void CMD_XorPixmap(F_CMD_ARGS) { char *PixmapName; FvwmPicture *xp; XGCValues gcv; unsigned long gcm; FvwmPictureAttributes fpa; action = GetNextToken(action, &PixmapName); if (PixmapName == NULL) { /* return to default value. */ action = "0"; CMD_XorValue(F_PASS_ARGS); return; } /* get the picture in the root visual, colorlimit is ignored because the * pixels will be freed */ fpa.mask = FPAM_NO_COLOR_LIMIT | FPAM_NO_ALPHA; PictureUseDefaultVisual(); xp = PGetFvwmPicture(dpy, Scr.Root, NULL, PixmapName, fpa); if (xp == NULL) { fvwm_msg(ERR,"SetXORPixmap","Can't find pixmap %s", PixmapName); free(PixmapName); PictureUseFvwmVisual(); return; } free(PixmapName); /* free up old pixmap */ if (XorPixmap != None) { XFreePixmap(dpy, XorPixmap); } /* make a copy of the picture pixmap */ XorPixmap = XCreatePixmap(dpy, Scr.Root, xp->width, xp->height, Pdepth); XCopyArea(dpy, xp->picture, XorPixmap, DefaultGC(dpy, Scr.screen), 0, 0, xp->width, xp->height, 0, 0); /* destroy picture and free colors */ PDestroyFvwmPicture(dpy, xp); PictureUseFvwmVisual(); /* create Graphics context */ gcm = GCFunction|GCLineWidth|GCTile|GCFillStyle|GCSubwindowMode; gcv.subwindow_mode = IncludeInferiors; gcv.function = GXxor; /* line width of 1 is necessary for Exceed servers */ gcv.line_width = 1; gcv.tile = XorPixmap; gcv.fill_style = FillTiled; gcv.subwindow_mode = IncludeInferiors; /* modify XorGC, only create once */ if (Scr.XorGC) { XChangeGC(dpy, Scr.XorGC, gcm, &gcv); } else { Scr.XorGC = fvwmlib_XCreateGC(dpy, Scr.Root, gcm, &gcv); } return; } /* ----------------------------- resizing code ----------------------------- */ /* Given a mouse location within a window context, return the direction the * window could be resized in, based on the window quadrant. This is the same * as the quadrants drawn by the rubber-band, if "ResizeOpaque" has not been * set. */ static direction_t __resize_get_dir_from_resize_quadrant( int x_off, int y_off, int px, int py) { direction_t dir = DIR_NONE; int tx; int ty; int dx; int dy; if (px < 0 || x_off < 0 || py < 0 || y_off < 0) { return dir; } /* Rough quadrants per window. 3x3. */ tx = (x_off / 3) - 1; ty = (y_off / 3) - 1; dx = x_off - px; dy = y_off - py; if (px < tx) { /* Far left of window. Quadrants of NW, W, SW. */ if (py < ty) { /* North-West direction. */ dir = DIR_NW; } else if (dy < ty) { /* South-West direction. */ dir = DIR_SW; } else { /* West direction. */ dir = DIR_W; } } else if (dx < tx) { /* Far right of window. Quadrants NE, E, SE. */ if (py < ty) { /* North-East direction. */ dir = DIR_NE; } else if (dy < ty) { /* South-East direction */ dir = DIR_SE; } else { /* East direction. */ dir = DIR_E; } } else { if (py < ty) { /* North direction. */ dir = DIR_N; } else if (dy < ty) { /* South direction. */ dir = DIR_S; } } return dir; } static void __resize_get_dir_from_window( int *ret_xmotion, int *ret_ymotion, FvwmWindow *fw, Window context_w) { if (context_w != Scr.Root && context_w != None) { if (context_w == FW_W_SIDE(fw, 0)) /* top */ { *ret_ymotion = 1; } else if (context_w == FW_W_SIDE(fw, 1)) /* right */ { *ret_xmotion = -1; } else if (context_w == FW_W_SIDE(fw, 2)) /* bottom */ { *ret_ymotion = -1; } else if (context_w == FW_W_SIDE(fw, 3)) /* left */ { *ret_xmotion = 1; } else if (context_w == FW_W_CORNER(fw, 0)) /* upper-left */ { *ret_xmotion = 1; *ret_ymotion = 1; } else if (context_w == FW_W_CORNER(fw, 1)) /* upper-right */ { *ret_xmotion = -1; *ret_ymotion = 1; } else if (context_w == FW_W_CORNER(fw, 2)) /* lower left */ { *ret_xmotion = 1; *ret_ymotion = -1; } else if (context_w == FW_W_CORNER(fw, 3)) /* lower right */ { *ret_xmotion = -1; *ret_ymotion = -1; } } return; } static void __resize_get_dir_proximity( int *ret_xmotion, int *ret_ymotion, FvwmWindow *fw, int x_off, int y_off, int px, int py, int *warp_x, int *warp_y, Bool find_nearest_border) { int tx; int ty; direction_t dir; *warp_x = *warp_y = -1; if (px < 0 || x_off < 0 || py < 0 || y_off < 0) { return; } if (find_nearest_border == False) { tx = 0; ty = 0; tx = max(fw->boundary_width, tx); ty = max(fw->boundary_width, ty); if (px < tx) { *ret_xmotion = 1; } else if (x_off < tx) { *ret_xmotion = -1; } if (py < ty) { *ret_ymotion = 1; } else if (y_off < ty) { *ret_ymotion = -1; } return; } /* Get the direction from the quadrant the pointer is in. */ dir = __resize_get_dir_from_resize_quadrant( x_off, y_off, px, py); switch (dir) { case DIR_NW: *ret_xmotion = 1; *ret_ymotion = 1; *warp_x = 0; *warp_y = 0; break; case DIR_SW: *ret_xmotion = 1; *ret_ymotion = -1; *warp_x = 0; *warp_y = (y_off - 1); break; case DIR_W: *ret_xmotion = 1; *warp_x = 0; *warp_y = (y_off / 2); break; case DIR_NE: *ret_xmotion = -1; *ret_ymotion = 1; *warp_x = (x_off - 1); *warp_y = 0; break; case DIR_SE: *ret_xmotion = -1; *ret_ymotion = -1; *warp_x = (x_off - 1); *warp_y = (y_off - 1); break; case DIR_E: *ret_xmotion = -1; *warp_x = (x_off - 1); *warp_y = (y_off / 2); break; case DIR_N: *ret_ymotion = 1; *warp_x = (x_off / 2); *warp_y = 0; break; case DIR_S: *ret_ymotion = -1; *warp_x = (x_off / 2); *warp_y = (y_off - 1); break; default: break; } return; } static void __resize_get_refpos( int *ret_x, int *ret_y, int xmotion, int ymotion, int w, int h, FvwmWindow *fw) { if (xmotion > 0) { *ret_x = 0; } else if (xmotion < 0) { *ret_x = w - 1; } else { *ret_x = w / 2; } if (ymotion > 0) { *ret_y = 0; } else if (ymotion < 0) { *ret_y = h - 1; } else { *ret_y = h / 2; } return; } /* Procedure: * __resize_step - move the rubberband around. This is called for * each motion event when we are resizing * * Inputs: * x_root - the X corrdinate in the root window * y_root - the Y corrdinate in the root window * x_off - x offset of pointer from border (input/output) * y_off - y offset of pointer from border (input/output) * drag - resize internal structure * orig - resize internal structure * xmotionp - pointer to xmotion in resize_window * ymotionp - pointer to ymotion in resize_window * */ static void __resize_step( const exec_context_t *exc, int x_root, int y_root, int *x_off, int *y_off, rectangle *drag, const rectangle *orig, int *xmotionp, int *ymotionp, Bool do_resize_opaque, Bool is_direction_fixed) { int action = 0; int x2; int y2; int xdir; int ydir; x2 = x_root - *x_off; x_root += *x_off; if (is_direction_fixed == True && (*xmotionp != 0 || *ymotionp != 0)) { xdir = *xmotionp; } else if (x2 <= orig->x || (*xmotionp == 1 && x2 < orig->x + orig->width - 1)) { xdir = 1; } else if (x2 >= orig->x + orig->width - 1 || (*xmotionp == -1 && x2 > orig->x)) { xdir = -1; } else { xdir = 0; } switch (xdir) { case 1: if (*xmotionp != 1) { *x_off = -*x_off; x_root = x2; *xmotionp = 1; } drag->x = x_root; drag->width = orig->x + orig->width - x_root; action = 1; break; case -1: if (*xmotionp != -1) { *x_off = -*x_off; x_root = x2; *xmotionp = -1; } drag->x = orig->x; drag->width = 1 + x_root - drag->x; action = 1; break; default: break; } y2 = y_root - *y_off; y_root += *y_off; if (is_direction_fixed == True && (*xmotionp != 0 || *ymotionp != 0)) { ydir = *ymotionp; } else if (y2 <= orig->y || (*ymotionp == 1 && y2 < orig->y + orig->height - 1)) { ydir = 1; } else if (y2 >= orig->y + orig->height - 1 || (*ymotionp == -1 && y2 > orig->y)) { ydir = -1; } else { ydir = 0; } switch (ydir) { case 1: if (*ymotionp != 1) { *y_off = -*y_off; y_root = y2; *ymotionp = 1; } drag->y = y_root; drag->height = orig->y + orig->height - y_root; action = 1; break; case -1: if (*ymotionp != -1) { *y_off = -*y_off; y_root = y2; *ymotionp = -1; } drag->y = orig->y; drag->height = 1 + y_root - drag->y; action = 1; break; default: break; } if (action) { /* round up to nearest OK size to keep pointer inside * rubberband */ constrain_size( exc->w.fw, exc->x.elast, &drag->width, &drag->height, *xmotionp, *ymotionp, CS_ROUND_UP); if (*xmotionp == 1) { drag->x = orig->x + orig->width - drag->width; } if (*ymotionp == 1) { drag->y = orig->y + orig->height - drag->height; } if (!do_resize_opaque) { draw_move_resize_grid( drag->x, drag->y, drag->width - 1, drag->height - 1); } else { frame_setup_window( exc->w.fw, drag->x, drag->y, drag->width, drag->height, False); } } DisplaySize(exc->w.fw, exc->x.elast, drag->width, drag->height, False, False); return; } /* Starts a window resize operation */ static Bool __resize_window(F_CMD_ARGS) { extern Window bad_window; FvwmWindow *fw = exc->w.fw; Bool is_finished = False, is_done = False, is_aborted = False; Bool do_send_cn = False; Bool do_resize_opaque; Bool do_warp_to_border; Bool is_direction_fixed; Bool automatic_border_direction; Bool detect_automatic_direction; Bool fButtonAbort = False; Bool fForceRedraw = False; Bool called_from_title = False; int x,y,delta_x,delta_y,stashed_x,stashed_y; Window ResizeWindow; int dx = Scr.EdgeScrollX ? Scr.EdgeScrollX : Scr.MyDisplayWidth; int dy = Scr.EdgeScrollY ? Scr.EdgeScrollY : Scr.MyDisplayHeight; const int vx = Scr.Vx; const int vy = Scr.Vy; int n; unsigned int button_mask = 0; rectangle sdrag; rectangle sorig; rectangle *drag = &sdrag; const rectangle *orig = &sorig; const window_g g_backup = fw->g; int ymotion = 0; int xmotion = 0; int was_maximized; unsigned edge_wrap_x; unsigned edge_wrap_y; int px; int py; int i; size_borders b; frame_move_resize_args mr_args = NULL; long evmask; XEvent ev; int ref_x; int ref_y; int x_off; int y_off; direction_t dir; int warp_x = 0; int warp_y = 0; bad_window = False; ResizeWindow = FW_W_FRAME(fw); if (fev_get_evpos_or_query(dpy, Scr.Root, exc->x.etrigger, &px, &py) == False || XTranslateCoordinates( dpy, Scr.Root, ResizeWindow, px, py, &px, &py, &JunkChild) == False) { /* pointer is on a different screen - that's okay here */ px = 0; py = 0; } button_mask &= DEFAULT_ALL_BUTTONS_MASK; if (!is_function_allowed(F_RESIZE, NULL, fw, RQORIG_PROGRAM_US, True)) { XBell(dpy, 0); return False; } if (IS_SHADED(fw) || !IS_MAPPED(fw)) { do_resize_opaque = False; evmask = XEVMASK_RESIZE; } else { do_resize_opaque = DO_RESIZE_OPAQUE(fw); evmask = XEVMASK_RESIZE_OPAQUE; } /* no suffix = % of screen, 'p' = pixels, 'c' = increment units */ if (IS_SHADED(fw)) { get_unshaded_geometry(fw, drag); } else { drag->width = fw->g.frame.width; drag->height = fw->g.frame.height; } get_window_borders(fw, &b); n = GetResizeArguments( &action, fw->g.frame.x, fw->g.frame.y, fw->hints.base_width, fw->hints.base_height, fw->hints.width_inc, fw->hints.height_inc, &b, &(drag->width), &(drag->height), &dir, &is_direction_fixed, &do_warp_to_border, &automatic_border_direction, &detect_automatic_direction); if (n == 2) { rectangle new_g; /* size will be less or equal to requested */ if (IS_SHADED(fw)) { rectangle shaded_g; get_unshaded_geometry(fw, &new_g); SET_MAXIMIZED(fw, 0); constrain_size( fw, NULL, &drag->width, &drag->height, xmotion, ymotion, 0); gravity_resize( fw->hints.win_gravity, &new_g, drag->width - new_g.width, drag->height - new_g.height); fw->g.normal = new_g; get_shaded_geometry(fw, &shaded_g, &new_g); frame_setup_window( fw, shaded_g.x, shaded_g.y, shaded_g.width, shaded_g.height, False); } else { new_g = fw->g.frame; SET_MAXIMIZED(fw, 0); constrain_size( fw, NULL, &drag->width, &drag->height, xmotion, ymotion, 0); gravity_resize( fw->hints.win_gravity, &new_g, drag->width - new_g.width, drag->height - new_g.height); frame_setup_window( fw, new_g.x, new_g.y, drag->width, drag->height, False); } update_absolute_geometry(fw); maximize_adjust_offset(fw); ResizeWindow = None; return True; } was_maximized = IS_MAXIMIZED(fw); SET_MAXIMIZED(fw, 0); if (was_maximized) { /* must redraw the buttons now so that the 'maximize' button * does not stay depressed. */ border_draw_decorations( fw, PART_BUTTONS, (fw == Scr.Hilite), True, CLEAR_ALL, NULL, NULL); } if (Scr.bo.do_install_root_cmap) { InstallRootColormap(); } else { InstallFvwmColormap(); } if (!GrabEm(CRS_RESIZE, GRAB_NORMAL)) { XBell(dpy, 0); return False; } /* handle problems with edge-wrapping while resizing */ edge_wrap_x = Scr.flags.do_edge_wrap_x; edge_wrap_y = Scr.flags.do_edge_wrap_y; Scr.flags.do_edge_wrap_x = 0; Scr.flags.do_edge_wrap_y = 0; if (!do_resize_opaque) { MyXGrabServer(dpy); } if (!XGetGeometry( dpy, (Drawable)ResizeWindow, &JunkRoot, &drag->x, &drag->y, (unsigned int*)&drag->width, (unsigned int*)&drag->height, (unsigned int*)&JunkBW, (unsigned int*)&JunkDepth)) { UngrabEm(GRAB_NORMAL); if (!do_resize_opaque) { MyXUngrabServer(dpy); } return False; } if (IS_SHADED(fw)) { SET_MAXIMIZED(fw, was_maximized); get_unshaded_geometry(fw, drag); SET_MAXIMIZED(fw, 0); } if (do_resize_opaque) { mr_args = frame_create_move_resize_args( fw, FRAME_MR_OPAQUE, &fw->g.frame, &fw->g.frame, 0, DIR_NONE); } else { Scr.flags.is_wire_frame_displayed = True; } MyXGrabKeyboard(dpy); sorig = *drag; ymotion = 0; xmotion = 0; /* pop up a resize dimensions window */ if (!Scr.gs.do_hide_resize_window) { position_geometry_window(NULL); XMapRaised(dpy, Scr.SizeWindow); } DisplaySize(fw, exc->x.elast, orig->width, orig->height, True, True); if (dir == DIR_NONE && detect_automatic_direction == True) { dir = __resize_get_dir_from_resize_quadrant( orig->width, orig->height, px, py); } if (dir != DIR_NONE) { int grav; grav = gravity_dir_to_grav(dir); gravity_get_offsets(grav, &xmotion, &ymotion); xmotion = -xmotion; ymotion = -ymotion; } if (xmotion == 0 && ymotion == 0) { __resize_get_dir_from_window(&xmotion, &ymotion, fw, PressedW); } if (FW_W_TITLE(fw) != None && PressedW == FW_W_TITLE(fw)) { /* title was pressed to start the resize */ called_from_title = True; } else { for (i = NUMBER_OF_TITLE_BUTTONS; i--; ) { /* see if the title button was pressed to that the * resize */ if (FW_W_BUTTON(fw, i) != None && FW_W_BUTTON(fw, i) == PressedW) { /* yes */ called_from_title = True; } } } /* don't warp if the resize was triggered by a press somwhere on the * title bar */ if (PressedW != Scr.Root && xmotion == 0 && ymotion == 0 && !called_from_title) { __resize_get_dir_proximity( &xmotion, &ymotion, fw, orig->width, orig->height, px, py, &warp_x, &warp_y, automatic_border_direction); if (xmotion != 0 || ymotion != 0) { do_warp_to_border = True; } } if (!IS_SHADED(fw)) { __resize_get_refpos( &ref_x, &ref_y, xmotion, ymotion, orig->width, orig->height, fw); } else { switch (SHADED_DIR(fw)) { case DIR_N: case DIR_NW: case DIR_NE: if (ymotion == -1) { ymotion = 0; } break; case DIR_S: case DIR_SW: case DIR_SE: if (ymotion == 1) { ymotion = 0; } break; default: break; } switch (SHADED_DIR(fw)) { case DIR_E: case DIR_NE: case DIR_SE: if (xmotion == 1) { xmotion = 0; } break; case DIR_W: case DIR_NW: case DIR_SW: if (xmotion == -1) { xmotion = 0; } break; default: break; } __resize_get_refpos( &ref_x, &ref_y, xmotion, ymotion, fw->g.frame.width, fw->g.frame.height, fw); } x_off = 0; y_off = 0; if (do_warp_to_border == True) { int dx; int dy; dx = (xmotion == 0) ? px : ref_x; dy = (ymotion == 0) ? py : ref_y; /* Warp the pointer to the closest border automatically? */ if (automatic_border_direction == True && (warp_x >=0 && warp_y >=0) && !IS_SHADED(fw)) { dx = warp_x; dy = warp_y; } /* warp the pointer to the border */ FWarpPointer( dpy, None, ResizeWindow, 0, 0, 1, 1, dx, dy); XFlush(dpy); } else if (xmotion != 0 || ymotion != 0) { /* keep the distance between pointer and border */ x_off = (xmotion == 0) ? 0 : ref_x - px; y_off = (ymotion == 0) ? 0 : ref_y - py; } else { /* wait until the pointer hits a border before making a * decision about the resize direction */ } /* draw the rubber-band window */ if (!do_resize_opaque) { draw_move_resize_grid( drag->x, drag->y, drag->width - 1, drag->height - 1); } /* kick off resizing without requiring any motion if invoked with a key * press */ if (exc->x.elast->type == KeyPress) { int xo; int yo; if (FQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, &stashed_x, &stashed_y, &JunkX, &JunkY, &JunkMask) == False) { /* pointer is on a different screen */ stashed_x = 0; stashed_y = 0; } xo = 0; yo = 0; __resize_step( exc, stashed_x, stashed_y, &xo, &yo, drag, orig, &xmotion, &ymotion, do_resize_opaque, True); } else { stashed_x = stashed_y = -1; } /* loop to resize */ memset(&ev, 0, sizeof(ev)); while (!is_finished && bad_window != FW_W(fw)) { int rc = 0; int is_resized = False; /* block until there is an interesting event */ while (rc != -1 && (!FPending(dpy) || !FCheckMaskEvent(dpy, evmask, &ev))) { rc = HandlePaging( &ev, dx, dy, &x, &y, &delta_x, &delta_y, False, False, True, fw->edge_delay_ms_resize); if (rc == 1) { /* Fake an event to force window reposition */ ev.type = MotionNotify; ev.xmotion.time = fev_get_evtime(); fForceRedraw = True; break; } } if (rc == -1) { FMaskEvent( dpy, evmask | EnterWindowMask | LeaveWindowMask, &ev); } if (ev.type == MotionNotify || ev.type == EnterNotify || ev.type == LeaveNotify) { /* discard any extra motion events before a release */ /* dv (2004-07-01): With XFree 4.1.0.1, some Mouse * events are not reported to fvwm when the pointer * moves very fast and suddenly stops in the corner of * the screen. Handle EnterNotify/LeaveNotify events * too to get an idea where the pointer might be. */ while ( FCheckMaskEvent( dpy, ButtonMotionMask | PointerMotionMask | ButtonReleaseMask | ButtonPressMask | EnterWindowMask | LeaveWindowMask, &ev) == True) { if (ev.type == ButtonRelease || ev.type == ButtonPress || ev.type == KeyPress) { break; } } } if (ev.type == EnterNotify || ev.type == LeaveNotify) { XEvent e2; int x; int y; /* Query the pointer to catch the latest information. * This *is* necessary. */ if (FQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, &x, &y, &JunkX, &JunkY, &JunkMask) == True) { /* Must NOT use button_mask here, or resize * will not work with num lock */ fev_make_null_event(&e2, dpy); e2.type = MotionNotify; e2.xmotion.time = fev_get_evtime(); e2.xmotion.x_root = x; e2.xmotion.y_root = y; e2.xmotion.state = JunkMask; e2.xmotion.same_screen = True; ev = e2; fev_fake_event(&ev); } else { /* pointer is on a different screen, * ignore event */ } } is_done = False; /* Handle a limited number of key press events to allow * mouseless operation */ if (ev.type == KeyPress) { Keyboard_shortcuts(&ev, fw, NULL, NULL, ButtonRelease); if (ev.type == ButtonRelease) { do_send_cn = True; } } switch (ev.type) { case ButtonPress: is_done = True; if (ev.xbutton.button <= NUMBER_OF_MOUSE_BUTTONS && ((Button1Mask << (ev.xbutton.button - 1)) & button_mask)) { /* No new button was pressed, just a delayed * event */ break; } /* Abort the resize if * - the move started with a pressed button and * another button was pressed during the operation * - no button was started at the beginning and any * button except button 1 was pressed. */ if (button_mask || (ev.xbutton.button != 1)) { fButtonAbort = True; /* fall through */ } else { is_finished = True; do_send_cn = True; break; } case KeyPress: /* simple code to bag out of move - CKH */ if (fButtonAbort || XLookupKeysym(&ev.xkey, 0) == XK_Escape) { is_aborted = True; do_send_cn = True; is_finished = True; } is_done = True; break; case ButtonRelease: is_finished = True; is_done = True; break; case MotionNotify: if (ev.xmotion.same_screen == False) { continue; } if (!fForceRedraw) { x = ev.xmotion.x_root; y = ev.xmotion.y_root; /* resize before paging request to prevent * resize from lagging * mouse - mab */ __resize_step( exc, x, y, &x_off, &y_off, drag, orig, &xmotion, &ymotion, do_resize_opaque, is_direction_fixed); is_resized = True; /* need to move the viewport */ HandlePaging( &ev, dx, dy, &x, &y, &delta_x, &delta_y, False, False, False, fw->edge_delay_ms_resize); } /* redraw outline if we paged - mab */ if (delta_x != 0 || delta_y != 0) { sorig.x -= delta_x; sorig.y -= delta_y; drag->x -= delta_x; drag->y -= delta_y; __resize_step( exc, x, y, &x_off, &y_off, drag, orig, &xmotion, &ymotion, do_resize_opaque, is_direction_fixed); is_resized = True; } fForceRedraw = False; is_done = True; break; case PropertyNotify: { evh_args_t ea; exec_context_changes_t ecc; ecc.x.etrigger = &ev; ea.exc = exc_clone_context(exc, &ecc, ECC_ETRIGGER); HandlePropertyNotify(&ea); exc_destroy_context(ea.exc); is_done = True; break; } default: break; } if (!is_done) { if (!do_resize_opaque) { /* must undraw the rubber band in case the * event causes some drawing */ switch_move_resize_grid(False); } dispatch_event(&ev); if (!do_resize_opaque) { draw_move_resize_grid( drag->x, drag->y, drag->width - 1, drag->height - 1); } } else { if (do_resize_opaque) { /* only do this with opaque resizes, (i.e. the * server is not grabbed) */ if (is_resized == False) { BroadcastConfig( M_CONFIGURE_WINDOW, fw); } else { /* event already broadcast */ } FlushAllMessageQueues(); } } } /* erase the rubber-band */ if (!do_resize_opaque) { switch_move_resize_grid(False); } /* pop down the size window */ if (!Scr.gs.do_hide_resize_window) { XUnmapWindow(dpy, Scr.SizeWindow); } if (is_aborted || bad_window == FW_W(fw)) { /* return pointer if aborted resize was invoked with key */ if (stashed_x >= 0) { FWarpPointer( dpy, None, Scr.Root, 0, 0, 0, 0, stashed_x, stashed_y); } if (was_maximized) { /* since we aborted the resize, the window is still * maximized */ SET_MAXIMIZED(fw, 1); } if (do_resize_opaque) { int xo; int yo; rectangle g; xo = 0; yo = 0; xmotion = 1; ymotion = 1; g = sorig; __resize_step( exc, sorig.x, sorig.y, &xo, &yo, &g, orig, &xmotion, &ymotion, do_resize_opaque, True); } if (vx != Scr.Vx || vy != Scr.Vy) { MoveViewport(vx, vy, False); } /* restore all geometry-related info */ fw->g = g_backup; if (bad_window == FW_W(fw)) { XUnmapWindow(dpy, FW_W_FRAME(fw)); border_undraw_decorations(fw); XBell(dpy, 0); } } else if (!is_aborted && bad_window != FW_W(fw)) { rectangle new_g; /* size will be >= to requested */ constrain_size( fw, exc->x.elast, &drag->width, &drag->height, xmotion, ymotion, CS_ROUND_UP); if (IS_SHADED(fw)) { get_shaded_geometry(fw, &new_g, drag); } else { new_g = *drag; } if (do_resize_opaque) { frame_update_move_resize_args(mr_args, &new_g); } else { frame_setup_window( fw, new_g.x, new_g.y, new_g.width, new_g.height, False); } if (IS_SHADED(fw)) { fw->g.normal.width = drag->width; fw->g.normal.height = drag->height; } } if (is_aborted && was_maximized) { /* force redraw */ border_draw_decorations( fw, PART_BUTTONS, (fw == Scr.Hilite), True, CLEAR_ALL, NULL, NULL); } if (Scr.bo.do_install_root_cmap) { UninstallRootColormap(); } else { UninstallFvwmColormap(); } ResizeWindow = None; if (!do_resize_opaque) { int event_types[2] = { EnterNotify, LeaveNotify }; /* Throw away some events that dont interest us right now. */ discard_typed_events(2, event_types); Scr.flags.is_wire_frame_displayed = False; MyXUngrabServer(dpy); } if (mr_args != NULL) { frame_free_move_resize_args(fw, mr_args); } if (do_send_cn == True) { rectangle g; if (is_aborted) { g = sorig; } else { g = *drag; } SendConfigureNotify(fw, g.x, g.y, g.width, g.height, 0, True); } MyXUngrabKeyboard(dpy); WaitForButtonsUp(True); UngrabEm(GRAB_NORMAL); Scr.flags.do_edge_wrap_x = edge_wrap_x; Scr.flags.do_edge_wrap_y = edge_wrap_y; update_absolute_geometry(fw); maximize_adjust_offset(fw); if (is_aborted) { return False; } return True; } void CMD_Resize(F_CMD_ARGS) { FvwmWindow *fw = exc->w.fw; if (IS_EWMH_FULLSCREEN(fw)) { /* do not unmaximize ! */ CMD_ResizeMaximize(F_PASS_ARGS); return; } __resize_window(F_PASS_ARGS); return; } /* ----------------------------- maximizing code --------------------------- */ Bool is_window_sticky_across_pages(FvwmWindow *fw) { if (IS_STICKY_ACROSS_PAGES(fw) || (IS_ICONIFIED(fw) && IS_ICON_STICKY_ACROSS_PAGES(fw))) { return True; } else { return False; } } Bool is_window_sticky_across_desks(FvwmWindow *fw) { if (IS_STICKY_ACROSS_DESKS(fw) || (IS_ICONIFIED(fw) && IS_ICON_STICKY_ACROSS_DESKS(fw))) { return True; } else { return False; } } static void move_sticky_window_to_same_page( int *x11, int *x12, int *y11, int *y12, int x21, int x22, int y21, int y22) { /* make sure the x coordinate is on the same page as the reference * window */ if (*x11 >= x22) { while (*x11 >= x22) { *x11 -= Scr.MyDisplayWidth; *x12 -= Scr.MyDisplayWidth; } } else if (*x12 <= x21) { while (*x12 <= x21) { *x11 += Scr.MyDisplayWidth; *x12 += Scr.MyDisplayWidth; } } /* make sure the y coordinate is on the same page as the reference * window */ if (*y11 >= y22) { while (*y11 >= y22) { *y11 -= Scr.MyDisplayHeight; *y12 -= Scr.MyDisplayHeight; } } else if (*y12 <= y21) { while (*y12 <= y21) { *y11 += Scr.MyDisplayHeight; *y12 += Scr.MyDisplayHeight; } } return; } static void MaximizeHeight( FvwmWindow *win, int win_width, int win_x, int *win_height, int *win_y, Bool grow_up, Bool grow_down, int top_border, int bottom_border, int *layers) { FvwmWindow *cwin; int x11, x12, x21, x22; int y11, y12, y21, y22; int new_y1, new_y2; rectangle g; Bool rc; x11 = win_x; /* Start x */ y11 = *win_y; /* Start y */ x12 = x11 + win_width; /* End x */ y12 = y11 + *win_height; /* End y */ new_y1 = top_border; new_y2 = bottom_border; for (cwin = Scr.FvwmRoot.next; cwin; cwin = cwin->next) { if (cwin == win || (cwin->Desk != win->Desk && !is_window_sticky_across_desks(cwin))) { continue; } if ((layers[0] >= 0 && cwin->layer < layers[0]) || (layers[1] >= 0 && cwin->layer > layers[1])) { continue; } rc = get_visible_window_or_icon_geometry(cwin, &g); if (rc == False) { continue; } x21 = g.x; y21 = g.y; x22 = x21 + g.width; y22 = y21 + g.height; if (is_window_sticky_across_pages(cwin)) { move_sticky_window_to_same_page( &x21, &x22, &new_y1, &new_y2, x11, x12, y11, y12); } /* Are they in the same X space? */ if (!((x22 <= x11) || (x21 >= x12))) { if ((y22 <= y11) && (y22 >= new_y1)) { new_y1 = y22; } else if ((y12 <= y21) && (new_y2 >= y21)) { new_y2 = y21; } } } if (!grow_up) { new_y1 = y11; } if (!grow_down) { new_y2 = y12; } *win_height = new_y2 - new_y1; *win_y = new_y1; return; } static void MaximizeWidth( FvwmWindow *win, int *win_width, int *win_x, int win_height, int win_y, Bool grow_left, Bool grow_right, int left_border, int right_border, int *layers) { FvwmWindow *cwin; int x11, x12, x21, x22; int y11, y12, y21, y22; int new_x1, new_x2; rectangle g; Bool rc; x11 = *win_x; /* Start x */ y11 = win_y; /* Start y */ x12 = x11 + *win_width; /* End x */ y12 = y11 + win_height; /* End y */ new_x1 = left_border; new_x2 = right_border; for (cwin = Scr.FvwmRoot.next; cwin; cwin = cwin->next) { if (cwin == win || (cwin->Desk != win->Desk && !is_window_sticky_across_desks(cwin))) { continue; } if ((layers[0] >= 0 && cwin->layer < layers[0]) || (layers[1] >= 0 && cwin->layer > layers[1])) { continue; } rc = get_visible_window_or_icon_geometry(cwin, &g); if (rc == False) { continue; } x21 = g.x; y21 = g.y; x22 = x21 + g.width; y22 = y21 + g.height; if (is_window_sticky_across_pages(cwin)) { move_sticky_window_to_same_page( &new_x1, &new_x2, &y21, &y22, x11, x12, y11, y12); } /* Are they in the same Y space? */ if (!((y22 <= y11) || (y21 >= y12))) { if ((x22 <= x11) && (x22 >= new_x1)) { new_x1 = x22; } else if ((x12 <= x21) && (new_x2 >= x21)) { new_x2 = x21; } } } if (!grow_left) { new_x1 = x11; } if (!grow_right) { new_x2 = x12; } *win_width = new_x2 - new_x1; *win_x = new_x1; return; } static void unmaximize_fvwm_window( FvwmWindow *fw) { rectangle new_g; SET_MAXIMIZED(fw, 0); if (IS_SHADED(fw)) { get_shaded_geometry(fw, &new_g, &new_g); } /* We might be restoring a window's geometry coming out of fullscreen, * which might be a maximized window, so ensure we use the correct * geometry reference. * * If the window was not maximized, then we use the window's normal * geometry. */ get_relative_geometry(&new_g, fw->fullscreen.was_maximized ? &fw->fullscreen.g.max : &fw->g.normal); if (fw->fullscreen.was_maximized) { /* If MWMButtons is in use, set the style of the button as * marked as maximized. */ SET_MAXIMIZED(fw, 1); } if (IS_EWMH_FULLSCREEN(fw)) { SET_EWMH_FULLSCREEN(fw, False); if (DO_EWMH_USE_STACKING_HINTS(fw)) { new_layer(fw, fw->ewmh_normal_layer); } } /* TA: Apply the decor change now, if the window we've just restored * was maximized; the client frame and geometry will be updated as a * result of this, so we correctly restore the window at this point. */ if (fw->fullscreen.was_maximized) { fw->fullscreen.was_maximized = 0; apply_decor_change(fw); } frame_setup_window( fw, new_g.x, new_g.y, new_g.width, new_g.height, True); border_draw_decorations( fw, PART_ALL, (Scr.Hilite == fw), True, CLEAR_ALL, NULL, NULL); if (fw->fullscreen.is_shaded) { execute_function_override_window( NULL, NULL, "WindowShade on", 0, fw); fw->fullscreen.is_shaded = 0; } if (fw->fullscreen.is_iconified) { execute_function_override_window( NULL, NULL, "Iconify on", 0, fw); fw->fullscreen.is_iconified = 0; } /* Since the window's geometry will have been constrained already when * coming out of fullscreen, we can always call this; either it's a * noop or the window will be correctly decorated in the case of the * window being restored from fullscreen to a non-maximized state. */ apply_decor_change(fw); return; } static void maximize_fvwm_window( FvwmWindow *fw, rectangle *geometry) { SET_MAXIMIZED(fw, 1); fw->g.max_defect.width = 0; fw->g.max_defect.height = 0; constrain_size( fw, NULL, &geometry->width, &geometry->height, 0, 0, CS_UPDATE_MAX_DEFECT); fw->g.max = *geometry; if (IS_SHADED(fw)) { get_shaded_geometry(fw, geometry, &fw->g.max); } frame_setup_window( fw, geometry->x, geometry->y, geometry->width, geometry->height, True); border_draw_decorations( fw, PART_ALL, (Scr.Hilite == fw), True, CLEAR_ALL, NULL, NULL); update_absolute_geometry(fw); /* remember the offset between old and new position in case the * maximized window is moved more than the screen width/height. */ fw->g.max_offset.x = fw->g.normal.x - fw->g.max.x; fw->g.max_offset.y = fw->g.normal.y - fw->g.max.y; #if 0 fprintf(stderr,"%d %d %d %d, g.max_offset.x = %d, g.max_offset.y = %d, %d %d %d %d\n", fw->g.max.x, fw->g.max.y, fw->g.max.width, fw->g.max.height, fw->g.max_offset.x, fw->g.max_offset.y, fw->g.normal.x, fw->g.normal.y, fw->g.normal.width, fw->g.normal.height); #endif return; } /* * * Procedure: * (Un)Maximize a window. * */ void CMD_Maximize(F_CMD_ARGS) { int page_x, page_y; int val1, val2, val1_unit, val2_unit; int toggle; char *token; char *taction; Bool grow_up = False; Bool grow_down = False; Bool grow_left = False; Bool grow_right = False; Bool do_force_maximize = False; Bool do_forget = False; Bool is_screen_given = False; Bool ignore_working_area = False; Bool do_fullscreen = False; int layers[2] = { -1, -1 }; Bool global_flag_parsed = False; int scr_x, scr_y; int scr_w, scr_h; rectangle new_g; FvwmWindow *fw = exc->w.fw; if ( !is_function_allowed( F_MAXIMIZE, NULL, fw, RQORIG_PROGRAM_US, False)) { XBell(dpy, 0); return; } /* Check for "global" flag ("absolute" is for compatibility with E) */ while (!global_flag_parsed) { token = PeekToken(action, &taction); if (!token) { global_flag_parsed = True; } else { if (StrEquals(token, "screen")) { int scr; is_screen_given = True; token = PeekToken(taction, &action); scr = FScreenGetScreenArgument( token, FSCREEN_SPEC_PRIMARY); FScreenGetScrRect( NULL, scr, &scr_x, &scr_y, &scr_w, &scr_h); } else if (StrEquals(token, "ewmhiwa")) { ignore_working_area = True; action = taction; } else if (StrEquals(token, "growonwindowlayer")) { layers[0] = fw->layer; layers[1] = fw->layer; action = taction; } else if (StrEquals(token, "growonlayers")) { int n; n = GetIntegerArguments( taction, &action, layers, 2); if (n != 2) { layers[0] = -1; layers[1] = -1; } } else if (StrEquals(token, "fullscreen")) { do_fullscreen = True; action = taction; } else { global_flag_parsed = True; } } } toggle = ParseToggleArgument(action, &action, -1, 0); if (do_fullscreen) { if (toggle == -1) { /* Flip-flop between fullscreen or not, if no toggle * argument is given. */ toggle = (IS_EWMH_FULLSCREEN(fw) ? 0 : 1); } if (toggle == 1 && !IS_EWMH_FULLSCREEN(fw)) { EWMH_fullscreen(fw); return; } if (toggle == 0 && IS_EWMH_FULLSCREEN(fw)) { unmaximize_fvwm_window(fw); return; } return; } else { if (toggle == 0 && !IS_MAXIMIZED(fw)) { return; } if (toggle == 1 && IS_MAXIMIZED(fw)) { /* Fake that the window is not maximized. */ do_force_maximize = True; } } /* find the new page and geometry */ new_g.x = fw->g.frame.x; new_g.y = fw->g.frame.y; new_g.width = fw->g.frame.width; new_g.height = fw->g.frame.height; get_page_offset_check_visible(&page_x, &page_y, fw); /* Check if we should constrain rectangle to some Xinerama screen */ if (!is_screen_given) { fscreen_scr_arg fscr; fscr.xypos.x = fw->g.frame.x + fw->g.frame.width / 2 - page_x; fscr.xypos.y = fw->g.frame.y + fw->g.frame.height / 2 - page_y; FScreenGetScrRect( &fscr, FSCREEN_XYPOS, &scr_x, &scr_y, &scr_w, &scr_h); } if (!ignore_working_area) { EWMH_GetWorkAreaIntersection( fw, &scr_x, &scr_y, &scr_w, &scr_h, EWMH_MAXIMIZE_MODE(fw)); } #if 0 fprintf(stderr, "%s: page=(%d,%d), scr=(%d,%d, %dx%d)\n", __FUNCTION__, page_x, page_y, scr_x, scr_y, scr_w, scr_h); #endif /* parse first parameter */ val1_unit = scr_w; token = PeekToken(action, &taction); if (token && StrEquals(token, "forget")) { if (!IS_MAXIMIZED(fw)) { return; } do_forget = True; do_force_maximize = True; } else if (token && StrEquals(token, "grow")) { grow_left = True; grow_right = True; val1 = 100; val1_unit = scr_w; } else if (token && StrEquals(token, "growleft")) { grow_left = True; val1 = 100; val1_unit = scr_w; } else if (token && StrEquals(token, "growright")) { grow_right = True; val1 = 100; val1_unit = scr_w; } else { if (GetOnePercentArgument(token, &val1, &val1_unit) == 0) { val1 = 100; val1_unit = scr_w; } else if (val1 < 0) { /* handle negative offsets */ if (val1_unit == scr_w) { val1 = 100 + val1; } else { val1 = scr_w + val1; } } } /* parse second parameter */ val2_unit = scr_h; token = PeekToken(taction, NULL); if (do_forget == True) { /* nop */ } else if (token && StrEquals(token, "grow")) { grow_up = True; grow_down = True; val2 = 100; val2_unit = scr_h; } else if (token && StrEquals(token, "growup")) { grow_up = True; val2 = 100; val2_unit = scr_h; } else if (token && StrEquals(token, "growdown")) { grow_down = True; val2 = 100; val2_unit = scr_h; } else { if (GetOnePercentArgument(token, &val2, &val2_unit) == 0) { val2 = 100; val2_unit = scr_h; } else if (val2 < 0) { /* handle negative offsets */ if (val2_unit == scr_h) { val2 = 100 + val2; } else { val2 = scr_h + val2; } } } #if 0 fprintf(stderr, "%s: page=(%d,%d), scr=(%d,%d, %dx%d)\n", __FUNCTION__, page_x, page_y, scr_x, scr_y, scr_w, scr_h); #endif if (do_forget == True) { fw->g.normal = fw->g.max; unmaximize_fvwm_window(fw); } else if (IS_MAXIMIZED(fw) && !do_force_maximize) { unmaximize_fvwm_window(fw); } else /* maximize */ { /* handle command line arguments */ if (grow_up || grow_down) { MaximizeHeight( fw, new_g.width, new_g.x, &new_g.height, &new_g.y, grow_up, grow_down, page_y + scr_y, page_y + scr_y + scr_h, layers); } else if (val2 > 0) { new_g.height = val2 * val2_unit / 100; new_g.y = page_y + scr_y; } if (grow_left || grow_right) { MaximizeWidth( fw, &new_g.width, &new_g.x, new_g.height, new_g.y, grow_left, grow_right, page_x + scr_x, page_x + scr_x + scr_w, layers); } else if (val1 >0) { new_g.width = val1 * val1_unit / 100; new_g.x = page_x + scr_x; } if (val1 == 0 && val2 == 0) { new_g.x = page_x + scr_x; new_g.y = page_y + scr_y; new_g.height = scr_h; new_g.width = scr_w; } /* now maximize it */ maximize_fvwm_window(fw, &new_g); } EWMH_SetWMState(fw, False); return; } /* * * Same as CMD_Resize and CMD_ResizeMove, but the window ends up maximized * without touching the normal geometry. * */ void CMD_ResizeMaximize(F_CMD_ARGS) { rectangle normal_g; rectangle max_g; Bool was_resized; FvwmWindow *fw = exc->w.fw; /* keep a copy of the old geometry */ normal_g = fw->g.normal; /* resize the window normally */ was_resized = __resize_window(F_PASS_ARGS); if (was_resized == True) { /* set the new geometry as the maximized geometry and restore * the old normal geometry */ max_g = fw->g.normal; max_g.x -= Scr.Vx; max_g.y -= Scr.Vy; fw->g.normal = normal_g; /* and mark it as maximized */ maximize_fvwm_window(fw, &max_g); } EWMH_SetWMState(fw, False); return; } void CMD_ResizeMoveMaximize(F_CMD_ARGS) { rectangle normal_g; rectangle max_g; Bool was_resized; FvwmWindow *fw = exc->w.fw; /* keep a copy of the old geometry */ normal_g = fw->g.normal; /* resize the window normally */ was_resized = resize_move_window(F_PASS_ARGS); if (was_resized == True) { /* set the new geometry as the maximized geometry and restore * the old normal geometry */ max_g = fw->g.normal; max_g.x -= Scr.Vx; max_g.y -= Scr.Vy; fw->g.normal = normal_g; /* and mark it as maximized */ maximize_fvwm_window(fw, &max_g); } EWMH_SetWMState(fw, False); return; } /* ----------------------------- stick code -------------------------------- */ int stick_across_pages(F_CMD_ARGS, int toggle) { FvwmWindow *fw = exc->w.fw; if ((toggle == 1 && IS_STICKY_ACROSS_PAGES(fw)) || (toggle == 0 && !IS_STICKY_ACROSS_PAGES(fw))) { return 0; } if (IS_STICKY_ACROSS_PAGES(fw)) { SET_STICKY_ACROSS_PAGES(fw, 0); } else { if (!IsRectangleOnThisPage(&fw->g.frame, Scr.CurrentDesk)) { action = ""; __move_window(F_PASS_ARGS, False, MOVE_PAGE); } SET_STICKY_ACROSS_PAGES(fw, 1); } return 1; } int stick_across_desks(F_CMD_ARGS, int toggle) { FvwmWindow *fw = exc->w.fw; if ((toggle == 1 && IS_STICKY_ACROSS_DESKS(fw)) || (toggle == 0 && !IS_STICKY_ACROSS_DESKS(fw))) { return 0; } if (IS_STICKY_ACROSS_DESKS(fw)) { SET_STICKY_ACROSS_DESKS(fw, 0); fw->Desk = Scr.CurrentDesk; } else { if (fw->Desk != Scr.CurrentDesk) { do_move_window_to_desk(fw, Scr.CurrentDesk); } SET_STICKY_ACROSS_DESKS(fw, 1); } return 1; } static void __handle_stick_exit( FvwmWindow *fw, int do_not_draw, int do_silently) { if (do_not_draw == 0) { border_draw_decorations( fw, PART_TITLE | PART_BUTTONS, (Scr.Hilite==fw), True, CLEAR_ALL, NULL, NULL); } if (!do_silently) { BroadcastConfig(M_CONFIGURE_WINDOW,fw); EWMH_SetWMState(fw, False); EWMH_SetWMDesktop(fw); } return; } void handle_stick_across_pages( F_CMD_ARGS, int toggle, int do_not_draw, int do_silently) { FvwmWindow *fw = exc->w.fw; int did_change; did_change = stick_across_pages(F_PASS_ARGS, toggle); if (did_change) { __handle_stick_exit(fw, do_not_draw, do_silently); } return; } void handle_stick_across_desks( F_CMD_ARGS, int toggle, int do_not_draw, int do_silently) { FvwmWindow *fw = exc->w.fw; int did_change; did_change = stick_across_desks(F_PASS_ARGS, toggle); if (did_change) { __handle_stick_exit(fw, do_not_draw, do_silently); } return; } void handle_stick( F_CMD_ARGS, int toggle_page, int toggle_desk, int do_not_draw, int do_silently) { FvwmWindow *fw = exc->w.fw; int did_change; did_change = 0; did_change |= stick_across_desks(F_PASS_ARGS, toggle_desk); did_change |= stick_across_pages(F_PASS_ARGS, toggle_page); if (did_change) { __handle_stick_exit(fw, do_not_draw, do_silently); } return; } void CMD_Stick(F_CMD_ARGS) { int toggle; toggle = ParseToggleArgument(action, &action, -1, 0); if (toggle == -1 && IS_STICKY_ACROSS_DESKS(exc->w.fw) != IS_STICKY_ACROSS_PAGES(exc->w.fw)) { /* don't switch between only stickypage and only stickydesk. * rather switch it off completely */ toggle = 0; } handle_stick(F_PASS_ARGS, toggle, toggle, 0, 0); return; } void CMD_StickAcrossPages(F_CMD_ARGS) { int toggle; toggle = ParseToggleArgument(action, &action, -1, 0); handle_stick_across_pages(F_PASS_ARGS, toggle, 0, 0); return; } void CMD_StickAcrossDesks(F_CMD_ARGS) { int toggle; toggle = ParseToggleArgument(action, &action, -1, 0); handle_stick_across_desks(F_PASS_ARGS, toggle, 0, 0); return; } fvwm-2.7.0/fvwm/ewmh.c0000644000175000017500000013311514147024700011506 00000000000000/* -*-c-*- */ /* Copyright (C) 2001 Olivier Chapuis */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* * An implementation of the Extended Window Manager Hints specification * http://freedesktop.org/Standards/wm-spec/ * * Not Implemented (draft 1.3 - 2004-05-01): * * _NET_DESKTOP_LAYOUT (not useful for us) * _NET_VIRTUAL_ROOTS (not useful at all for us) * _NET_SHOWING_DESKTOP should be implemented * _NET_REQUEST_FRAME_EXTENTS may be implemented * * Some _NET_WINDOW_TYPE are simply ignored: * _NET_WM_WINDOW_TYPE_SPLASH * _NET_WM_WINDOW_TYPE_UTILITIES * _KDE_NET_WM_WINDOW_TYPE_OVERRIDE (deprecated) * * _NET_WM_STATE_DEMANDS_ATTENTION state * * _NET_WM_STRUT_PARTIAL should be implemented * * _NET_WM_USER_TIME can be used to decide if we give the focus to a newly * mapped window * * The kill huge process protocol: _NET_WM_PID and _NET_WM_PING * * _NET_WM_HANDLED_ICONS (what to do? Nothing?) * * "Source indication in requests" is not used but can be useful with some * "ignore styles" * * Problems: * - _NET_WM_WINDOW_TYPE_TOOLBAR is interpreted in a different way * in GNOME (the spec) and in KDE 2/3.0 (~ simple dock?). * */ #include "config.h" #include #include #include "libs/fvwmlib.h" #include "libs/FScreen.h" #include "fvwm.h" #include "execcontext.h" #include "functions.h" #include "commands.h" #include "misc.h" #include "screen.h" #include "update.h" #include "stack.h" #include "style.h" #include "externs.h" #include "decorations.h" #include "ewmh.h" #include "ewmh_intern.h" #include "geometry.h" #include "window_flags.h" typedef struct kst_item { Window w; struct kst_item *next; } KstItem; Atom XA_UTF8_STRING = None; KstItem *ewmh_KstWinList = NULL; /* * Default */ ewmhInfo ewmhc = { 4, /* NumberOfDesktops */ 0, /* MaxDesktops limit the number of desktops*/ 0, /* CurrentNumberOfDesktops */ False, /* NeedsToCheckDesk */ {0, 0, 0, 0}, /* BaseStrut */ }; /* * The ewmh atoms lists */ #define ENTRY(name, type, func) {name, None, type, func} /* WARNING: lists must be in "name" alphabetic order! */ /* EWMH_ATOM_LIST_CLIENT_ROOT * net atoms that can be send (Client Message) by a client and do not * need a window to operate */ ewmh_atom ewmh_atom_client_root[] = { ENTRY("_NET_CURRENT_DESKTOP", XA_CARDINAL, ewmh_CurrentDesktop), ENTRY("_NET_DESKTOP_GEOMETRY", XA_CARDINAL, ewmh_DesktopGeometry), ENTRY("_NET_DESKTOP_NAMES", None, None), ENTRY("_NET_DESKTOP_VIEWPORT", XA_CARDINAL, ewmh_DesktopViewPort), ENTRY("_NET_NUMBER_OF_DESKTOPS", XA_CARDINAL, ewmh_NumberOfDesktops), {NULL,0,0,0} }; /* EWMH_ATOM_LIST_CLIENT_WIN * net atoms that can be send (Client Message) by a client and do need * window to operate */ ewmh_atom ewmh_atom_client_win[] = { ENTRY("_NET_ACTIVE_WINDOW", XA_WINDOW, ewmh_ActiveWindow), ENTRY("_NET_CLOSE_WINDOW", XA_WINDOW, ewmh_CloseWindow), ENTRY("_NET_MOVERESIZE_WINDOW", XA_WINDOW, ewmh_MoveResizeWindow), ENTRY("_NET_RESTACK_WINDOW", XA_WINDOW, ewmh_RestackWindow), ENTRY("_NET_WM_DESKTOP", XA_CARDINAL, ewmh_WMDesktop), ENTRY("_NET_WM_MOVERESIZE", XA_WINDOW, ewmh_MoveResize), ENTRY("_NET_WM_STATE", XA_ATOM, ewmh_WMState), {NULL,0,0,0} }; /* EWMH_ATOM_LIST_WM_STATE * the different wm state, a client can ask to add, remove or toggle * via a _NET_WM_STATE Client message. fvwm must maintain these states * too */ ewmh_atom ewmh_atom_wm_state[] = { ENTRY( "_NET_WM_STATE_ABOVE", XA_ATOM, ewmh_WMStateStaysOnTop), ENTRY( "_NET_WM_STATE_BELOW", XA_ATOM, ewmh_WMStateStaysOnBottom), ENTRY( "_NET_WM_STATE_FULLSCREEN", XA_ATOM, ewmh_WMStateFullScreen), ENTRY("_NET_WM_STATE_HIDDEN", XA_ATOM, ewmh_WMStateHidden), ENTRY( "_NET_WM_STATE_MAXIMIZED_HORIZ", XA_ATOM, ewmh_WMStateMaxHoriz), ENTRY( "_NET_WM_STATE_MAXIMIZED_HORZ", XA_ATOM, ewmh_WMStateMaxHoriz), ENTRY("_NET_WM_STATE_MAXIMIZED_VERT", XA_ATOM, ewmh_WMStateMaxVert), ENTRY("_NET_WM_STATE_MODAL", XA_ATOM, ewmh_WMStateModal), ENTRY("_NET_WM_STATE_SHADED", XA_ATOM, ewmh_WMStateShaded), ENTRY( "_NET_WM_STATE_SKIP_PAGER", XA_ATOM, ewmh_WMStateSkipPager), ENTRY( "_NET_WM_STATE_SKIP_TASKBAR", XA_ATOM, ewmh_WMStateSkipTaskBar), ENTRY( "_NET_WM_STATE_STAYS_ON_TOP", XA_ATOM, ewmh_WMStateStaysOnTop), ENTRY("_NET_WM_STATE_STICKY", XA_ATOM, ewmh_WMStateSticky), {NULL,0,0,0} }; #define EWMH_NUMBER_OF_STATE sizeof(ewmh_atom_wm_state)/sizeof(ewmh_atom) - 1 /* EWMH ATOM_LIST_ALLOWED_ACTIONS: atom for _NET_WM_ALLOWED_ACTIONS */ ewmh_atom ewmh_atom_allowed_actions[] = { ENTRY("_NET_WM_ACTION_CHANGE_DESKTOP", XA_ATOM, ewmh_AllowsYes), ENTRY("_NET_WM_ACTION_CLOSE", XA_ATOM, ewmh_AllowsClose), ENTRY("_NET_WM_ACTION_FULLSCREEN", XA_ATOM, ewmh_AllowsFullScreen), ENTRY("_NET_WM_ACTION_MAXIMIZE_HORZ", XA_ATOM, ewmh_AllowsMaximize), ENTRY("_NET_WM_ACTION_MAXIMIZE_VERT", XA_ATOM, ewmh_AllowsMaximize), ENTRY("_NET_WM_ACTION_MINIMIZE", XA_ATOM, ewmh_AllowsMinimize), ENTRY("_NET_WM_ACTION_MOVE", XA_ATOM, ewmh_AllowsMove), ENTRY("_NET_WM_ACTION_RESIZE", XA_ATOM, ewmh_AllowsResize), ENTRY("_NET_WM_ACTION_SHADE", XA_ATOM, ewmh_AllowsYes), ENTRY("_NET_WM_ACTION_STICK", XA_ATOM, ewmh_AllowsYes), {NULL,0,0,0} }; #define EWMH_NUMBER_OF_ALLOWED_ACTIONS \ sizeof(ewmh_atom_allowed_actions)/sizeof(ewmh_atom) - 1 /* EWMH ATOM_LIST_WINDOW_TYPE: the various window type */ ewmh_atom ewmh_atom_window_type[] = { ENTRY("_NET_WM_WINDOW_TYPE_DESKTOP", XA_ATOM, ewmh_HandleDesktop), ENTRY("_NET_WM_WINDOW_TYPE_DIALOG", XA_ATOM, ewmh_HandleDialog), ENTRY("_NET_WM_WINDOW_TYPE_DOCK", XA_ATOM, ewmh_HandleDock), ENTRY("_NET_WM_WINDOW_TYPE_MENU", XA_ATOM, ewmh_HandleMenu), ENTRY("_NET_WM_WINDOW_TYPE_NORMAL", XA_ATOM, ewmh_HandleNormal), ENTRY("_NET_WM_WINDOW_TYPE_TOOLBAR", XA_ATOM, ewmh_HandleToolBar), ENTRY("_NET_WM_WINDOW_TYPE_NOTIFICATION", XA_ATOM, ewmh_HandleNotification), {NULL,0,0,0} }; /* EWMH ATOM_LIST_FIXED_PROPERTY * property that have a window at startup and which should not change */ ewmh_atom ewmh_atom_fixed_property[] = { ENTRY("_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", XA_WINDOW, None), ENTRY("_NET_WM_HANDLED_ICON", XA_ATOM, None), ENTRY("_NET_WM_PID", XA_ATOM, None), ENTRY("_NET_WM_WINDOW_TYPE", XA_ATOM, None), {NULL,0,0,0} }; /* EWMH ATOM_LIST_PROPERTY_NOTIFY * properties of a window which is updated by the window via a PropertyNotify * event */ ewmh_atom ewmh_atom_property_notify[] = { ENTRY("_NET_WM_ICON", XA_CARDINAL, ewmh_WMIcon), ENTRY("_NET_WM_ICON_GEOMETRY", XA_CARDINAL, ewmh_WMIconGeometry), ENTRY("_NET_WM_ICON_NAME", None, EWMH_WMIconName), ENTRY("_NET_WM_NAME", None, EWMH_WMName), ENTRY("_NET_WM_STRUT", XA_CARDINAL, ewmh_WMStrut), {NULL,0,0,0} }; /* EWMH_ATOM_LIST_FVWM_ROOT: root atom that should be maintained by fvwm only */ ewmh_atom ewmh_atom_fvwm_root[] = { ENTRY("_KDE_NET_SYSTEM_TRAY_WINDOWS", XA_WINDOW, None), ENTRY("_NET_CLIENT_LIST", XA_WINDOW, None), ENTRY("_NET_CLIENT_LIST_STACKING", XA_WINDOW, None), ENTRY("_NET_SUPPORTED", XA_ATOM, None), ENTRY("_NET_SUPPORTING_WM_CHECK", XA_WINDOW, None), ENTRY("_NET_VIRTUAL_ROOTS", XA_WINDOW, None), ENTRY("_NET_WORKAREA", XA_CARDINAL, None), {NULL,0,0,0} }; /* EWMH_ATOM_LIST_FVWM_WIN: window atom that should be maintained by fvwm * only */ ewmh_atom ewmh_atom_fvwm_win[] = { ENTRY("_KDE_NET_WM_FRAME_STRUT", XA_CARDINAL, None), ENTRY("_NET_FRAME_EXTENTS", XA_CARDINAL, None), ENTRY("_NET_WM_ALLOWED_ACTIONS", XA_ATOM, None), ENTRY("_NET_WM_ICON_VISIBLE_NAME", None, None), ENTRY("_NET_WM_VISIBLE_NAME", None, None), {NULL,0,0,0} }; #define NUMBER_OF_ATOM_LISTS 9 #define L_ENTRY(x,y) {x,y,sizeof(y)/sizeof(ewmh_atom)} ewmh_atom_list atom_list[] = { L_ENTRY(EWMH_ATOM_LIST_CLIENT_ROOT, ewmh_atom_client_root), L_ENTRY(EWMH_ATOM_LIST_CLIENT_WIN, ewmh_atom_client_win), L_ENTRY(EWMH_ATOM_LIST_WM_STATE, ewmh_atom_wm_state), L_ENTRY(EWMH_ATOM_LIST_ALLOWED_ACTIONS, ewmh_atom_allowed_actions), L_ENTRY(EWMH_ATOM_LIST_WINDOW_TYPE, ewmh_atom_window_type), L_ENTRY(EWMH_ATOM_LIST_FIXED_PROPERTY, ewmh_atom_fixed_property), L_ENTRY(EWMH_ATOM_LIST_PROPERTY_NOTIFY, ewmh_atom_property_notify), L_ENTRY(EWMH_ATOM_LIST_FVWM_ROOT, ewmh_atom_fvwm_root), L_ENTRY(EWMH_ATOM_LIST_FVWM_WIN, ewmh_atom_fvwm_win), L_ENTRY(EWMH_ATOM_LIST_END, NULL) }; /* * Atoms utilities */ static int compare(const void *a, const void *b) { return (strcmp((char *)a, ((ewmh_atom *)b)->name)); } static ewmh_atom *get_ewmh_atom_by_name( const char *atom_name, ewmh_atom_list_name list_name) { ewmh_atom *a = NULL; Bool done = 0; int i = 0; while(!done && atom_list[i].name != EWMH_ATOM_LIST_END) { if (atom_list[i].name == list_name || list_name == EWMH_ATOM_LIST_ALL) { a = (ewmh_atom *)bsearch( atom_name, atom_list[i].list, atom_list[i].size - 1, sizeof(ewmh_atom), compare); if (a != NULL || list_name != EWMH_ATOM_LIST_ALL) { done = 1; } } i++; } return a; } ewmh_atom *ewmh_GetEwmhAtomByAtom(Atom atom, ewmh_atom_list_name list_name) { int i = 0; for (i = 0; atom_list[i].name != EWMH_ATOM_LIST_END; i++) { ewmh_atom *item; if (list_name != atom_list[i].name && list_name != EWMH_ATOM_LIST_ALL) { continue; } for (item = atom_list[i].list; item->name != NULL; item++) { if (atom == item->atom) { return item; } } if (list_name == atom_list[i].name) { return NULL; } } return NULL; } static int atom_size(int format) { if (format == 32) { return sizeof(long); } else { return (format >> 3); } } void ewmh_ChangeProperty( Window w, const char *atom_name, ewmh_atom_list_name list, unsigned char *data, int length) { ewmh_atom *a; int format = 32; if ((a = get_ewmh_atom_by_name(atom_name, list)) != NULL) { int asize; int free_data = 0; if (a->atom_type == XA_UTF8_STRING) { format = 8; } asize = atom_size(format); if ( format == 32 && asize * 8 != format && strcmp(atom_name, "_NET_WM_ICON") == 0) { long *datacopy = (long*)safemalloc(asize * length); int i; for (i = 0; i < length; i++) { datacopy[i] = ((CARD32 *)data)[i]; } data = (unsigned char*)datacopy; free_data = 1; } XChangeProperty( dpy, w, a->atom, a->atom_type , format, PropModeReplace, data, length); if (free_data) { free(data); } } return; } void ewmh_DeleteProperty( Window w, const char *atom_name, ewmh_atom_list_name list) { ewmh_atom *a; if ((a = get_ewmh_atom_by_name(atom_name, list)) != NULL) { XDeleteProperty(dpy, w, a->atom); } return; } static void *atom_get(Window win, Atom to_get, Atom type, int *size) { unsigned char *retval; Atom type_ret; unsigned long bytes_after, num_ret; long length; int format_ret; void *data; int ok; retval = NULL; length = 0x7fffffff; ok = XGetWindowProperty( dpy, win, to_get, 0L, length, False, type, &type_ret, &format_ret, &num_ret, &bytes_after, &retval); if ((ok == Success) && (retval) && (num_ret > 0) && (format_ret > 0)) { int asize; asize = atom_size(format_ret); data = safemalloc(num_ret * asize); if (format_ret == 32 && asize * 8 != format_ret) { int i; for (i = 0; i < num_ret; i++) { ((CARD32 *)data)[i] = ((long *)retval)[i]; } } else { if (data) { memcpy(data, retval, num_ret * asize); } } XFree(retval); *size = num_ret * (format_ret >> 3); return data; } if (retval) { XFree(retval); } return NULL; } void *ewmh_AtomGetByName( Window win, const char *atom_name, ewmh_atom_list_name list, int *size) { ewmh_atom *a; void *data = NULL; if ((a = get_ewmh_atom_by_name(atom_name, list)) != NULL) { data = atom_get(win, a->atom, a->atom_type, size); } return data; } /* * client_root: here the client is fvwm */ static int check_desk(void) { int d = -1; FvwmWindow *fw; for (fw = Scr.FvwmRoot.next; fw != NULL; fw = fw->next) { if (!IS_STICKY_ACROSS_DESKS(fw)) { d = max(d, fw->Desk); } } return d; } void EWMH_SetCurrentDesktop(void) { long val; val = Scr.CurrentDesk; if (val < 0 || (val >= ewmhc.MaxDesktops && ewmhc.MaxDesktops != 0)) { return; } if (val >= ewmhc.CurrentNumberOfDesktops || (ewmhc.NumberOfDesktops != ewmhc.CurrentNumberOfDesktops && val < ewmhc.CurrentNumberOfDesktops)) { EWMH_SetNumberOfDesktops(); } ewmh_ChangeProperty(Scr.Root,"_NET_CURRENT_DESKTOP", EWMH_ATOM_LIST_CLIENT_ROOT, (unsigned char *)&val, 1); return; } void EWMH_SetNumberOfDesktops(void) { long val; if (ewmhc.CurrentNumberOfDesktops < ewmhc.NumberOfDesktops) { ewmhc.CurrentNumberOfDesktops = ewmhc.NumberOfDesktops; } if (ewmhc.CurrentNumberOfDesktops > ewmhc.NumberOfDesktops || ewmhc.NeedsToCheckDesk) { int d = check_desk(); ewmhc.NeedsToCheckDesk = False; if (d >= ewmhc.MaxDesktops && ewmhc.MaxDesktops != 0) d = 0; ewmhc.CurrentNumberOfDesktops = max(ewmhc.NumberOfDesktops, d+1); } if (Scr.CurrentDesk >= ewmhc.CurrentNumberOfDesktops && (Scr.CurrentDesk < ewmhc.MaxDesktops || ewmhc.MaxDesktops == 0)) { ewmhc.CurrentNumberOfDesktops = Scr.CurrentDesk + 1; } val = (long)ewmhc.CurrentNumberOfDesktops; ewmh_ChangeProperty(Scr.Root, "_NET_NUMBER_OF_DESKTOPS", EWMH_ATOM_LIST_CLIENT_ROOT, (unsigned char *)&val, 1); ewmh_SetWorkArea(); return; } void EWMH_SetDesktopViewPort(void) { long val[256][2]; /* no more than 256 desktops */ int i = 0; while(i < ewmhc.NumberOfDesktops && i < 256) { val[i][0] = Scr.Vx; val[i][1] = Scr.Vy; i++; } ewmh_ChangeProperty( Scr.Root, "_NET_DESKTOP_VIEWPORT", EWMH_ATOM_LIST_CLIENT_ROOT, (unsigned char *)&val, i*2); return; } void EWMH_SetDesktopGeometry(void) { long val[2]; val[0] = Scr.VxMax + Scr.MyDisplayWidth; val[1] = Scr.VyMax + Scr.MyDisplayHeight; ewmh_ChangeProperty( Scr.Root,"_NET_DESKTOP_GEOMETRY", EWMH_ATOM_LIST_CLIENT_ROOT, (unsigned char *)&val, 2); return; } /* * client_win: here the client is fvwm */ void EWMH_SetActiveWindow(Window w) { ewmh_ChangeProperty( Scr.Root, "_NET_ACTIVE_WINDOW", EWMH_ATOM_LIST_CLIENT_WIN, (unsigned char *)&w, 1); return; } void EWMH_SetWMDesktop(FvwmWindow *fw) { long desk = fw->Desk; if (IS_STICKY_ACROSS_DESKS(fw)) { desk = (unsigned long)-1; } else if (desk >= ewmhc.CurrentNumberOfDesktops) { ewmhc.NeedsToCheckDesk = True; EWMH_SetNumberOfDesktops(); } ewmh_ChangeProperty( FW_W(fw), "_NET_WM_DESKTOP", EWMH_ATOM_LIST_CLIENT_WIN, (unsigned char *)&desk, 1); return; } /* * fvwm must maintain the _NET_WM_STATE */ void EWMH_SetWMState(FvwmWindow *fw, Bool do_restore) { Atom wm_state[EWMH_NUMBER_OF_STATE]; int i = 0; ewmh_atom *list = ewmh_atom_wm_state; while(list->name != NULL) { if (list->action(fw, NULL, NULL, do_restore)) { wm_state[i++] = list->atom; } list++; } if (i > 0) { ewmh_ChangeProperty( FW_W(fw), "_NET_WM_STATE", EWMH_ATOM_LIST_CLIENT_WIN, (unsigned char *)wm_state, i); } else { ewmh_DeleteProperty( FW_W(fw), "_NET_WM_STATE", EWMH_ATOM_LIST_CLIENT_WIN); } return; } /* * fvwm_root */ /*** kde system tray ***/ /* #define DEBUG_KST */ static void add_kst_item(Window w) { KstItem *t,**prev; t = ewmh_KstWinList; prev = &ewmh_KstWinList; while(t != NULL) { prev = &(t->next); t = t->next; } *prev = (KstItem *)safemalloc(sizeof(KstItem)); (*prev)->w = w; (*prev)->next = NULL; return; } static void delete_kst_item(Window w) { KstItem *t,**prev; t = ewmh_KstWinList; prev = &ewmh_KstWinList; while((t!= NULL)&&(t->w != w)) { prev = &(t->next); t = t->next; } if (t == NULL) { return; } if(prev != NULL) { *prev = t->next; } free(t); return; } static void set_kde_sys_tray(void) { Window *wins = NULL; KstItem *t; int i = 0, nbr = 0; t = ewmh_KstWinList; while(t != NULL) { nbr++; t = t->next; } if (nbr > 0) { wins = (Window *)safemalloc(sizeof(Window) * nbr); } t = ewmh_KstWinList; #ifdef DEBUG_KST fprintf(stderr,"ADD_TO_KST: "); #endif while (t != NULL) { #ifdef DEBUG_KST fprintf(stderr,"0x%lx ",t->w); #endif wins[i++] = t->w; t = t->next; } #ifdef DEBUG_KST fprintf(stderr,"\n"); #endif ewmh_ChangeProperty(Scr.Root,"_KDE_NET_SYSTEM_TRAY_WINDOWS", EWMH_ATOM_LIST_FVWM_ROOT, (unsigned char *)wins,i); if (wins != NULL) { free(wins); } return; } void ewmh_AddToKdeSysTray(FvwmWindow *fw) { int size = 0; CARD32 *val; KstItem *t; val = ewmh_AtomGetByName( FW_W(fw), "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", EWMH_ATOM_LIST_FIXED_PROPERTY, &size); if (val == NULL) { return; } free(val); t = ewmh_KstWinList; while(t != NULL && t->w != FW_W(fw)) t = t->next; if (t != NULL) { return; /* already in the list */ } add_kst_item(FW_W(fw)); set_kde_sys_tray(); return; } #if 0 /* not used at present time */ void ewmh_FreeKdeSysTray(void) { KstItem *t; t = ewmh_KstWinList; while(t != NULL) { XSelectInput(dpy, t->w, NoEventMask); delete_kst_item(t->w); t = ewmh_KstWinList; } set_kde_sys_tray(); return; } #endif int EWMH_IsKdeSysTrayWindow(Window w) { KstItem *t; t = ewmh_KstWinList; while(t != NULL && t->w != w) { t = t->next; } if (t == NULL) { return 0; } #ifdef DEBUG_KST fprintf(stderr,"IsKdeSysTrayWindow: 0x%lx\n", w); #endif return 1; } void EWMH_ManageKdeSysTray(Window w, int type) { KstItem *t; t = ewmh_KstWinList; while(t != NULL && t->w != w) { t = t->next; } if (t == NULL) { return; } switch(type) { case UnmapNotify: #ifdef DEBUG_KST fprintf(stderr,"KST_UNMAP: 0x%lx\n", w); #endif XSelectInput(dpy, w, StructureNotifyMask); XFlush(dpy); break; case DestroyNotify: #ifdef DEBUG_KST fprintf(stderr,"KST_DESTROY: 0x%lx\n", w); #endif XSelectInput(dpy, t->w, NoEventMask); XFlush(dpy); delete_kst_item(w); set_kde_sys_tray(); break; case ReparentNotify: #ifdef DEBUG_KST fprintf(stderr,"KST_Reparent: 0x%lx\n", w); #endif XSelectInput(dpy, w, StructureNotifyMask); XFlush(dpy); break; default: #ifdef DEBUG_KST fprintf(stderr,"KST_NO: 0x%lx\n", w); #endif break; } return; } /**** Client lists ****/ void EWMH_SetClientList(void) { Window *wl = NULL; FvwmWindow *fw; int nbr = 0; int i = 0; for (fw = Scr.FvwmRoot.next; fw != NULL; fw = fw->next) { nbr++; } if (nbr != 0) { wl = (Window *)safemalloc(sizeof(Window) * nbr); for (fw = Scr.FvwmRoot.next; fw != NULL; fw = fw->next) { wl[i++] = FW_W(fw); } } ewmh_ChangeProperty( Scr.Root,"_NET_CLIENT_LIST", EWMH_ATOM_LIST_FVWM_ROOT, (unsigned char *)wl, nbr); if (wl != NULL) { free (wl); } return; } void EWMH_SetClientListStacking(void) { Window *wl = NULL; FvwmWindow *fw; int nbr = 0; int i = 0; for ( fw = Scr.FvwmRoot.stack_next; fw != &Scr.FvwmRoot; fw = fw->stack_next) { nbr++; } i = nbr-1; if (nbr != 0) { wl = (Window *)safemalloc(sizeof(Window) * nbr); for ( fw = Scr.FvwmRoot.stack_next; fw != &Scr.FvwmRoot; fw = fw->stack_next) { wl[i--] = FW_W(fw); } } ewmh_ChangeProperty( Scr.Root,"_NET_CLIENT_LIST_STACKING", EWMH_ATOM_LIST_FVWM_ROOT, (unsigned char *)wl, nbr); if (wl != NULL) { free (wl); } return; } /**** Working Area stuff ****/ /**** At present time we support only sticky windows with strut ****/ void ewmh_SetWorkArea(void) { long val[256][4]; /* no more than 256 desktops */ int i = 0; while(i < ewmhc.NumberOfDesktops && i < 256) { val[i][0] = Scr.Desktops->ewmh_working_area.x; val[i][1] = Scr.Desktops->ewmh_working_area.y; val[i][2] = Scr.Desktops->ewmh_working_area.width; val[i][3] = Scr.Desktops->ewmh_working_area.height; i++; } ewmh_ChangeProperty( Scr.Root, "_NET_WORKAREA", EWMH_ATOM_LIST_FVWM_ROOT, (unsigned char *)&val, i*4); return; } void ewmh_ComputeAndSetWorkArea(void) { int left = ewmhc.BaseStrut.left; int right = ewmhc.BaseStrut.right; int top = ewmhc.BaseStrut.top; int bottom = ewmhc.BaseStrut.bottom; int x,y,width,height; FvwmWindow *fw; for (fw = Scr.FvwmRoot.next; fw != NULL; fw = fw->next) { if ( DO_EWMH_IGNORE_STRUT_HINTS(fw) || !IS_STICKY_ACROSS_PAGES(fw)) { continue; } left = max(left, fw->strut.left); right = max(right, fw->strut.right); top = max(top, fw->strut.top); bottom = max(bottom, fw->strut.bottom); } x = left; y = top; width = Scr.MyDisplayWidth - (left + right); height = Scr.MyDisplayHeight - (top + bottom); if ( Scr.Desktops->ewmh_working_area.x != x || Scr.Desktops->ewmh_working_area.y != y || Scr.Desktops->ewmh_working_area.width != width || Scr.Desktops->ewmh_working_area.height != height) { Scr.Desktops->ewmh_working_area.x = x; Scr.Desktops->ewmh_working_area.y = y; Scr.Desktops->ewmh_working_area.width = width; Scr.Desktops->ewmh_working_area.height = height; ewmh_SetWorkArea(); } return; } void ewmh_HandleDynamicWorkArea(void) { int dyn_left = ewmhc.BaseStrut.left; int dyn_right = ewmhc.BaseStrut.right; int dyn_top = ewmhc.BaseStrut.top; int dyn_bottom = ewmhc.BaseStrut.bottom; int x,y,width,height; FvwmWindow *fw; for (fw = Scr.FvwmRoot.next; fw != NULL; fw = fw->next) { if ( DO_EWMH_IGNORE_STRUT_HINTS(fw) || !IS_STICKY_ACROSS_PAGES(fw)) { continue; } dyn_left = max(dyn_left, fw->dyn_strut.left); dyn_right = max(dyn_right, fw->dyn_strut.right); dyn_top = max(dyn_top, fw->dyn_strut.top); dyn_bottom = max(dyn_bottom, fw->dyn_strut.bottom); } x = dyn_left; y = dyn_top; width = Scr.MyDisplayWidth - (dyn_left + dyn_right); height = Scr.MyDisplayHeight - (dyn_top + dyn_bottom); if ( Scr.Desktops->ewmh_dyn_working_area.x != x || Scr.Desktops->ewmh_dyn_working_area.y != y || Scr.Desktops->ewmh_dyn_working_area.width != width || Scr.Desktops->ewmh_dyn_working_area.height != height) { Scr.Desktops->ewmh_dyn_working_area.x = x; Scr.Desktops->ewmh_dyn_working_area.y = y; Scr.Desktops->ewmh_dyn_working_area.width = width; Scr.Desktops->ewmh_dyn_working_area.height = height; /* here we may update the maximized window ...etc */ } return; } void EWMH_UpdateWorkArea(void) { ewmh_ComputeAndSetWorkArea(); ewmh_HandleDynamicWorkArea(); return; } void EWMH_GetWorkAreaIntersection( FvwmWindow *fw, int *x, int *y, int *w, int *h, int type) { int nx,ny,nw,nh; int area_x = Scr.Desktops->ewmh_working_area.x; int area_y = Scr.Desktops->ewmh_working_area.y; int area_w = Scr.Desktops->ewmh_working_area.width; int area_h = Scr.Desktops->ewmh_working_area.height; Bool is_dynamic = False; switch(type) { case EWMH_IGNORE_WORKING_AREA: return; case EWMH_USE_WORKING_AREA: break; case EWMH_USE_DYNAMIC_WORKING_AREA: is_dynamic = True; break; default: break; } if (is_dynamic) { area_x = Scr.Desktops->ewmh_dyn_working_area.x; area_y = Scr.Desktops->ewmh_dyn_working_area.y; area_w = Scr.Desktops->ewmh_dyn_working_area.width; area_h = Scr.Desktops->ewmh_dyn_working_area.height; } nx = max(*x, area_x); ny = max(*y, area_y); nw = min(*x + *w, area_x + area_w) - nx; nh = min(*y + *h, area_y + area_h) - ny; *x = nx; *y = ny; *w = nw; *h = nh; return; } static float get_intersection( int x11, int y11, int x12, int y12, int x21, int y21, int x22, int y22, Bool use_percent) { float ret = 0; int xl, xr, yt, yb; if (x11 < x22 && x12 > x21 && y11 < y22 && y12 > y21) { xl = max(x11, x21); xr = min(x12, x22); yt = max(y11, y21); yb = min(y12, y22); ret = (xr - xl) * (yb - yt); } if (use_percent && (x22 - x21) * (y22 - y21) != 0 && (x12 - x11) * (y12 - y11) != 0) { ret = 100 * max(ret / ((x22 - x21) * (y22 - y21)), ret / ((x12 - x11) * (y12 - y11))); } return ret; } static float ewmh_GetStrutIntersection( int x11, int y11, int x12, int y12, int left, int right, int top, int bottom, Bool use_percent) { float ret = 0; int x21, y21, x22, y22; /* left */ x21 = 0; y21 = 0; x22 = left; y22 = Scr.MyDisplayHeight; ret += get_intersection( x11, y11, x12, y12, x21, y21, x22, y22, use_percent); /* right */ x21 = Scr.MyDisplayWidth - right; y21 = 0; x22 = Scr.MyDisplayWidth; y22 = Scr.MyDisplayHeight; ret += get_intersection( x11, y11, x12, y12, x21, y21, x22, y22, use_percent); /* top */ x21 = 0; y21 = 0; x22 = Scr.MyDisplayWidth; y22 = top; ret += get_intersection( x11, y11, x12, y12, x21, y21, x22, y22, use_percent); /* bottom */ x21 = 0; y21 = Scr.MyDisplayHeight - bottom; x22 = Scr.MyDisplayWidth; y22 = Scr.MyDisplayHeight; ret += get_intersection( x11, y11, x12, y12, x21, y21, x22, y22, use_percent); return ret; } float EWMH_GetBaseStrutIntersection( int x11, int y11, int x12, int y12, Bool use_percent) { return ewmh_GetStrutIntersection( x11, y11, x12, y12, ewmhc.BaseStrut.left, ewmhc.BaseStrut.right, ewmhc.BaseStrut.top, ewmhc.BaseStrut.bottom, use_percent); } float EWMH_GetStrutIntersection( int x11, int y11, int x12, int y12, Bool use_percent) { int left, right, top, bottom; left = Scr.Desktops->ewmh_working_area.x; right = Scr.MyDisplayWidth - (Scr.Desktops->ewmh_working_area.x + Scr.Desktops->ewmh_working_area.width); top = Scr.Desktops->ewmh_working_area.y; bottom = Scr.MyDisplayHeight - (Scr.Desktops->ewmh_working_area.y + Scr.Desktops->ewmh_working_area.height); return ewmh_GetStrutIntersection( x11, y11, x12, y12, left, right, top, bottom, use_percent); } /* * fvwm_win */ void EWMH_SetFrameStrut(FvwmWindow *fw) { long val[4]; size_borders b; if (EWMH_IsKdeSysTrayWindow(FW_W(fw))) { /* Fixed position of tray window in kicker */ return; } get_window_borders(fw, &b); /* left */ val[0] = b.top_left.width; /* right */ val[1] = b.bottom_right.width; /* top */ val[2] = b.top_left.height; /* bottom */ val[3] = b.bottom_right.height; ewmh_ChangeProperty( FW_W(fw), "_KDE_NET_WM_FRAME_STRUT", EWMH_ATOM_LIST_FVWM_WIN, (unsigned char *)&val, 4); ewmh_ChangeProperty( FW_W(fw), "_NET_FRAME_EXTENTS", EWMH_ATOM_LIST_FVWM_WIN, (unsigned char *)&val, 4); return; } /* * allowed actions */ Bool ewmh_AllowsYes( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { return True; } Bool ewmh_AllowsClose( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { return is_function_allowed( F_CLOSE, NULL, fw, RQORIG_PROGRAM_US, False); } Bool ewmh_AllowsFullScreen( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { if ( !is_function_allowed( F_MAXIMIZE, NULL, fw, RQORIG_PROGRAM_US, False) || !is_function_allowed( F_MOVE, NULL, fw, RQORIG_PROGRAM_US, False) || !is_function_allowed( F_RESIZE, NULL, fw, RQORIG_PROGRAM_US, True)) { return False; } return True; } Bool ewmh_AllowsMinimize( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { return is_function_allowed(F_ICONIFY, NULL, fw, RQORIG_PROGRAM_US, False); } Bool ewmh_AllowsMaximize( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { return is_function_allowed(F_MAXIMIZE, NULL, fw, RQORIG_PROGRAM_US, False); } Bool ewmh_AllowsMove( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { return is_function_allowed(F_MOVE, NULL, fw, RQORIG_PROGRAM_US, False); } Bool ewmh_AllowsResize( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { return is_function_allowed(F_RESIZE, NULL, fw, RQORIG_PROGRAM_US, False); } void EWMH_SetAllowedActions(FvwmWindow *fw) { Atom wm_actions[EWMH_NUMBER_OF_ALLOWED_ACTIONS]; int i = 0; ewmh_atom *list = ewmh_atom_allowed_actions; while(list->name != NULL) { if (list->action(fw, NULL, NULL, 0)) wm_actions[i++] = list->atom; list++; } if (i > 0) { ewmh_ChangeProperty( FW_W(fw), "_NET_WM_ALLOWED_ACTIONS", EWMH_ATOM_LIST_FVWM_WIN, (unsigned char *)wm_actions, i); } else { ewmh_DeleteProperty( FW_W(fw), "_NET_WM_ALLOWED_ACTIONS", EWMH_ATOM_LIST_FVWM_WIN); } return; } /* * Window types */ int ewmh_HandleDesktop( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { if (Scr.EwmhDesktop != NULL && FW_W(Scr.EwmhDesktop) != FW_W(fw)) { fvwm_msg( WARN,"ewmh_HandleDesktop", "A Desktop application (0x%lx) already runs! This" " can cause problems\n", FW_W(Scr.EwmhDesktop)); /* what to do ? */ } fw->ewmh_window_type = EWMH_WINDOW_TYPE_DESKTOP_ID; Scr.EwmhDesktop = fw; SSET_LAYER(*style, 0); style->flags.use_layer = 1; style->flag_mask.use_layer = 1; style->change_mask.use_layer = 1; S_SET_IS_STICKY_ACROSS_PAGES(SCF(*style), 1); S_SET_IS_STICKY_ACROSS_PAGES(SCM(*style), 1); S_SET_IS_STICKY_ACROSS_PAGES(SCC(*style), 1); S_SET_IS_STICKY_ACROSS_DESKS(SCF(*style), 1); S_SET_IS_STICKY_ACROSS_DESKS(SCM(*style), 1); S_SET_IS_STICKY_ACROSS_DESKS(SCC(*style), 1); S_SET_IS_FIXED(SCF(*style), 1); S_SET_IS_FIXED(SCM(*style), 1); S_SET_IS_FIXED(SCC(*style), 1); S_SET_DO_WINDOW_LIST_SKIP(SCF(*style), 1); S_SET_DO_WINDOW_LIST_SKIP(SCM(*style), 1); S_SET_DO_WINDOW_LIST_SKIP(SCC(*style), 1); S_SET_DO_CIRCULATE_SKIP(SCF(*style), 1); S_SET_DO_CIRCULATE_SKIP(SCM(*style), 1); S_SET_DO_CIRCULATE_SKIP(SCC(*style), 1); S_SET_IS_UNICONIFIABLE(SCF(*style), 1); S_SET_IS_UNICONIFIABLE(SCM(*style), 1); S_SET_IS_UNICONIFIABLE(SCC(*style), 1); S_SET_IS_UNMAXIMIZABLE(SCF(*style), 1); S_SET_IS_UNMAXIMIZABLE(SCM(*style), 1); S_SET_IS_UNMAXIMIZABLE(SCC(*style), 1); /* No border */ SSET_BORDER_WIDTH(*style, 0); style->flags.has_border_width = 1; style->flag_mask.has_border_width = 1; style->change_mask.has_border_width = 1; SSET_HANDLE_WIDTH(*style, 0); style->flags.has_handle_width = 1; style->flag_mask.has_handle_width = 1; style->change_mask.has_handle_width = 1; /* no title */ style->flags.has_no_title = 1; style->flag_mask.has_no_title = 1; style->change_mask.has_no_title = 1; /* ClickToFocus, I do not think we should use NeverFocus */ FPS_FOCUS_CLICK_CLIENT(S_FOCUS_POLICY(SCF(*style)), 1); FPS_FOCUS_CLICK_CLIENT(S_FOCUS_POLICY(SCM(*style)), 1); FPS_FOCUS_CLICK_CLIENT(S_FOCUS_POLICY(SCC(*style)), 1); FPS_GRAB_FOCUS(S_FOCUS_POLICY(SCF(*style)), 1); FPS_GRAB_FOCUS(S_FOCUS_POLICY(SCM(*style)), 1); FPS_GRAB_FOCUS(S_FOCUS_POLICY(SCC(*style)), 1); /* ClickToFocusPassesClick */ FPS_PASS_FOCUS_CLICK(S_FOCUS_POLICY(SCF(*style)), 1); FPS_PASS_FOCUS_CLICK(S_FOCUS_POLICY(SCM(*style)), 1); FPS_PASS_FOCUS_CLICK(S_FOCUS_POLICY(SCC(*style)), 1); FPS_PASS_RAISE_CLICK(S_FOCUS_POLICY(SCF(*style)), 1); FPS_PASS_RAISE_CLICK(S_FOCUS_POLICY(SCM(*style)), 1); FPS_PASS_RAISE_CLICK(S_FOCUS_POLICY(SCC(*style)), 1); /* not useful */ FPS_RAISE_FOCUSED_CLIENT_CLICK(S_FOCUS_POLICY(SCF(*style)), 0); FPS_RAISE_FOCUSED_CLIENT_CLICK(S_FOCUS_POLICY(SCM(*style)), 1); FPS_RAISE_FOCUSED_CLIENT_CLICK(S_FOCUS_POLICY(SCC(*style)), 1); FPS_RAISE_UNFOCUSED_CLIENT_CLICK(S_FOCUS_POLICY(SCF(*style)), 0); FPS_RAISE_UNFOCUSED_CLIENT_CLICK(S_FOCUS_POLICY(SCM(*style)), 1); FPS_RAISE_UNFOCUSED_CLIENT_CLICK(S_FOCUS_POLICY(SCC(*style)), 1); FPS_RAISE_FOCUSED_DECOR_CLICK(S_FOCUS_POLICY(SCF(*style)), 0); FPS_RAISE_FOCUSED_DECOR_CLICK(S_FOCUS_POLICY(SCM(*style)), 1); FPS_RAISE_FOCUSED_DECOR_CLICK(S_FOCUS_POLICY(SCC(*style)), 1); FPS_RAISE_UNFOCUSED_DECOR_CLICK(S_FOCUS_POLICY(SCF(*style)), 0); FPS_RAISE_UNFOCUSED_DECOR_CLICK(S_FOCUS_POLICY(SCM(*style)), 1); FPS_RAISE_UNFOCUSED_DECOR_CLICK(S_FOCUS_POLICY(SCC(*style)), 1); return 1; } int ewmh_HandleDialog( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { fw->ewmh_window_type = EWMH_WINDOW_TYPE_DIALOG_ID; return 0; } int ewmh_HandleDock( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { fw->ewmh_window_type = EWMH_WINDOW_TYPE_DOCK_ID; S_SET_IS_STICKY_ACROSS_PAGES(SCF(*style), 1); S_SET_IS_STICKY_ACROSS_PAGES(SCM(*style), 1); S_SET_IS_STICKY_ACROSS_PAGES(SCC(*style), 1); S_SET_IS_STICKY_ACROSS_DESKS(SCF(*style), 1); S_SET_IS_STICKY_ACROSS_DESKS(SCM(*style), 1); S_SET_IS_STICKY_ACROSS_DESKS(SCC(*style), 1); S_SET_DO_WINDOW_LIST_SKIP(SCF(*style), 1); S_SET_DO_WINDOW_LIST_SKIP(SCM(*style), 1); S_SET_DO_WINDOW_LIST_SKIP(SCC(*style), 1); S_SET_DO_CIRCULATE_SKIP(SCF(*style), 1); S_SET_DO_CIRCULATE_SKIP(SCM(*style), 1); S_SET_DO_CIRCULATE_SKIP(SCC(*style), 1); S_SET_IS_UNICONIFIABLE(SCF(*style), 1); S_SET_IS_UNICONIFIABLE(SCM(*style), 1); S_SET_IS_UNICONIFIABLE(SCC(*style), 1); S_SET_IS_UNMAXIMIZABLE(SCF(*style), 1); S_SET_IS_UNMAXIMIZABLE(SCM(*style), 1); S_SET_IS_UNMAXIMIZABLE(SCC(*style), 1); if (fw->ewmh_hint_layer == -1) { fw->ewmh_hint_layer = Scr.TopLayer; if (DO_EWMH_USE_STACKING_HINTS(style)) { SSET_LAYER(*style, Scr.TopLayer); style->flags.use_layer = 1; style->flag_mask.use_layer = 1; style->change_mask.use_layer = 1; } else if (!style->change_mask.use_layer) { SSET_LAYER(*style, Scr.DefaultLayer); style->flags.use_layer = 1; style->flag_mask.use_layer = 1; style->change_mask.use_layer = 1; } } /* no title ? MWM hints should be used by the app but ... */ return 1; } int ewmh_HandleMenu( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { fw->ewmh_window_type = EWMH_WINDOW_TYPE_MENU_ID; /* tear off menu */ S_SET_DO_WINDOW_LIST_SKIP(SCF(*style), 1); S_SET_DO_WINDOW_LIST_SKIP(SCM(*style), 1); S_SET_DO_WINDOW_LIST_SKIP(SCC(*style), 1); S_SET_DO_CIRCULATE_SKIP(SCF(*style), 1); S_SET_DO_CIRCULATE_SKIP(SCM(*style), 1); S_SET_DO_CIRCULATE_SKIP(SCC(*style), 1); /* NeverFocus */ FPS_LENIENT(S_FOCUS_POLICY(SCF(*style)), 0); FPS_LENIENT(S_FOCUS_POLICY(SCM(*style)), 1); FPS_LENIENT(S_FOCUS_POLICY(SCC(*style)), 1); FPS_FOCUS_ENTER(S_FOCUS_POLICY(SCF(*style)), 0); FPS_UNFOCUS_LEAVE(S_FOCUS_POLICY(SCF(*style)), 0); FPS_FOCUS_CLICK_CLIENT(S_FOCUS_POLICY(SCF(*style)), 0); FPS_FOCUS_CLICK_DECOR(S_FOCUS_POLICY(SCF(*style)), 0); FPS_FOCUS_CLICK_ICON(S_FOCUS_POLICY(SCF(*style)), 0); FPS_FOCUS_BY_FUNCTION(S_FOCUS_POLICY(SCF(*style)), 0); FPS_FOCUS_ENTER(S_FOCUS_POLICY(SCM(*style)), 1); FPS_FOCUS_ENTER(S_FOCUS_POLICY(SCC(*style)), 1); FPS_UNFOCUS_LEAVE(S_FOCUS_POLICY(SCM(*style)), 1); FPS_UNFOCUS_LEAVE(S_FOCUS_POLICY(SCC(*style)), 1); FPS_FOCUS_CLICK_CLIENT(S_FOCUS_POLICY(SCM(*style)), 1); FPS_FOCUS_CLICK_CLIENT(S_FOCUS_POLICY(SCC(*style)), 1); FPS_FOCUS_CLICK_DECOR(S_FOCUS_POLICY(SCM(*style)), 1); FPS_FOCUS_CLICK_DECOR(S_FOCUS_POLICY(SCC(*style)), 1); FPS_FOCUS_CLICK_ICON(S_FOCUS_POLICY(SCM(*style)), 1); FPS_FOCUS_CLICK_ICON(S_FOCUS_POLICY(SCC(*style)), 1); FPS_FOCUS_BY_FUNCTION(S_FOCUS_POLICY(SCM(*style)), 1); FPS_FOCUS_BY_FUNCTION(S_FOCUS_POLICY(SCC(*style)), 1); return 1; } int ewmh_HandleNormal( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { fw->ewmh_window_type = EWMH_WINDOW_TYPE_NORMAL_ID; return 0; } int ewmh_HandleToolBar( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { fw->ewmh_window_type = EWMH_WINDOW_TYPE_TOOLBAR_ID; /* this ok for KDE 2 (and 3??) but I do not think that a toolbar should be sticky */ S_SET_IS_STICKY_ACROSS_PAGES(SCF(*style), 1); S_SET_IS_STICKY_ACROSS_PAGES(SCM(*style), 1); S_SET_IS_STICKY_ACROSS_PAGES(SCC(*style), 1); S_SET_IS_STICKY_ACROSS_DESKS(SCF(*style), 1); S_SET_IS_STICKY_ACROSS_DESKS(SCM(*style), 1); S_SET_IS_STICKY_ACROSS_DESKS(SCC(*style), 1); S_SET_DO_WINDOW_LIST_SKIP(SCF(*style), 1); S_SET_DO_WINDOW_LIST_SKIP(SCM(*style), 1); S_SET_DO_WINDOW_LIST_SKIP(SCC(*style), 1); S_SET_DO_CIRCULATE_SKIP(SCF(*style), 1); S_SET_DO_CIRCULATE_SKIP(SCM(*style), 1); S_SET_DO_CIRCULATE_SKIP(SCC(*style), 1); /* no title ? MWM hints should be used by the app but ... */ return 1; } int ewmh_HandleNotification( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { /* fw->ewmh_window_type is generally used by FvwmIdent, but for this * EWMH type it is not used. Reporting on unmanaged windows with * FvwmIdent won't work anyway as the click to the window is eaten. * So although setting this is a NOP, it might be useful for things in * the future. */ fw->ewmh_window_type = EWMH_WINDOW_TYPE_NOTIFICATION_ID; style->flags.is_unmanaged = 1; style->flag_mask.is_unmanaged = 1; style->change_mask.is_unmanaged = 1; return 1; } void ewmh_HandleWindowType(FvwmWindow *fw, window_style *style) { CARD32 *val; unsigned int nitems; ewmh_atom *list = ewmh_atom_window_type; int size = 0; int i = 0; Bool found = False; fw->ewmh_window_type = 0; if (DO_EWMH_IGNORE_WINDOW_TYPE(style)) { return; } val = ewmh_AtomGetByName( FW_W(fw), "_NET_WM_WINDOW_TYPE", EWMH_ATOM_LIST_FIXED_PROPERTY, &size); if (val == NULL) { return; } /* we support only one window type: the first that we support */ nitems = size / sizeof(CARD32); while(i < nitems && !found) { list = ewmh_atom_window_type; while(list->name != NULL && !found) { if (list->atom == val[i]) { list->action(fw, NULL, style, 0); found = True; } list++; } i++; } free(val); return; } /* * a workaround for ksmserver exit windows */ static int ksmserver_workarround(FvwmWindow *fw) { if (fw->name.name != NULL && fw->class.res_name != NULL && fw->icon_name.name != NULL && fw->class.res_class != NULL && strcmp(fw->name.name, "ksmserver") == 0 && strcmp(fw->class.res_class, "ksmserver") == 0 && strcmp(fw->icon_name.name, "ksmserver") == 0 && strcmp(fw->class.res_name, "unnamed") == 0) { int layer = 0; if (IS_TRANSIENT(fw)) { layer = Scr.TopLayer + 2; } else { layer = Scr.TopLayer + 1; } new_layer(fw, layer); return 1; } return 0; } /* * Window Initialisation / Destroy */ void EWMH_GetStyle(FvwmWindow *fw, window_style *style) { if (style->change_mask.use_layer) { fw->ewmh_normal_layer = SGET_LAYER(*style); } else if (fw->ewmh_normal_layer == 0) { fw->ewmh_normal_layer = Scr.DefaultLayer; } ewmh_WMState(fw, NULL, style, 0); ewmh_WMDesktop(fw, NULL, style, 0); /* the window type override the state hint */ ewmh_HandleWindowType(fw, style); return; } static void ewmh_check_wm_pid(FvwmWindow *fw) { int size = 0; CARD32 *val; fw->ewmh_window_type = 0; val = ewmh_AtomGetByName( FW_W(fw), "_NET_WM_PID", EWMH_ATOM_LIST_FIXED_PROPERTY, &size); if (val != NULL) { free(val); SET_HAS_EWMH_WM_PID(fw, 1); if (CR_MOTION_METHOD(fw) == CR_MOTION_METHOD_AUTO) { SET_CR_MOTION_METHOD(fw, CR_MOTION_METHOD_USE_GRAV); SET_CR_MOTION_METHOD_DETECTED(fw, 1); } } return; } /* see also EWMH_WMName and EWMH_WMIconName in add_window */ void EWMH_WindowInit(FvwmWindow *fw) { /*EWMH_DLOG("Init window 0x%lx",FW_W(fw));*/ EWMH_SetWMState(fw, False); EWMH_SetWMDesktop(fw); EWMH_SetAllowedActions(fw); ewmh_WMStrut(fw, NULL, NULL, 0); ewmh_WMIconGeometry(fw, NULL, NULL, 0); ewmh_AddToKdeSysTray(fw); EWMH_SetFrameStrut(fw); if (IS_EWMH_DESKTOP(FW_W(fw))) { return; } if (ksmserver_workarround(fw)) { return; } ewmh_WMIcon(fw, NULL, NULL, 0); ewmh_check_wm_pid(fw); /*EWMH_DLOG("window 0x%lx initialised",FW_W(fw));*/ return; } /* unmap or reparent: restore state */ void EWMH_RestoreInitialStates(FvwmWindow *fw, int event_type) { EWMH_SetWMState(fw, True); if (HAS_EWMH_INIT_WM_DESKTOP(fw) == EWMH_STATE_HAS_HINT) { ewmh_ChangeProperty( FW_W(fw), "_NET_WM_DESKTOP", EWMH_ATOM_LIST_CLIENT_WIN, (unsigned char *)&(fw->ewmh_hint_desktop), 1); } else { ewmh_DeleteProperty( FW_W(fw), "_NET_WM_DESKTOP", EWMH_ATOM_LIST_CLIENT_WIN); } if (HAS_EWMH_WM_ICON_HINT(fw) == EWMH_FVWM_ICON) { EWMH_DeleteWmIcon(fw, True, True); } return; } /* a window are going to be destroyed (in the add_window.c destroy_window * sens) */ void EWMH_DestroyWindow(FvwmWindow *fw) { if (IS_EWMH_DESKTOP(FW_W(fw))) { Scr.EwmhDesktop = NULL; } if (fw->Desk >= ewmhc.NumberOfDesktops) { ewmhc.NeedsToCheckDesk = True; } return; } /* a window has been destroyed (unmap/reparent/destroy) */ void EWMH_WindowDestroyed(void) { EWMH_SetClientList(); EWMH_SetClientListStacking(); if (ewmhc.NeedsToCheckDesk) { EWMH_SetNumberOfDesktops(); } ewmh_ComputeAndSetWorkArea(); ewmh_HandleDynamicWorkArea(); return; } /* * Init Stuff */ static int set_all_atom_in_list(ewmh_atom *list) { int l = 0; while(list->name != NULL) { list->atom = XInternAtom(dpy,list->name,False); if (list->atom_type == None) { list->atom_type = XA_UTF8_STRING; } l++; list++; } return l; } static void set_net_supported(int l) { Atom *supported; int i, k = 0; supported = (Atom *)safemalloc(l*sizeof(Atom)); for(i=0; i < NUMBER_OF_ATOM_LISTS; i++) { ewmh_atom *list = atom_list[i].list; while(list->name != NULL) { supported[k++] = list->atom; list++; } } ewmh_ChangeProperty( Scr.Root, "_NET_SUPPORTED", EWMH_ATOM_LIST_FVWM_ROOT, (unsigned char *)supported, k); free(supported); return; } static void clean_up(void) { ewmh_ChangeProperty( Scr.Root,"_KDE_NET_SYSTEM_TRAY_WINDOWS", EWMH_ATOM_LIST_FVWM_ROOT, NULL, 0); return; } void EWMH_Init(void) { int i; int supported_count = 0; long val; XTextProperty text; unsigned char utf_name[4]; char *names[1]; XClassHint classhints; /* initialisation of all the atoms */ XA_UTF8_STRING = XInternAtom(dpy,"UTF8_STRING",False); for(i=0; i < NUMBER_OF_ATOM_LISTS; i++) { supported_count += set_all_atom_in_list(atom_list[i].list); } /* the laws that we respect */ set_net_supported(supported_count); /* use the Scr.NoFocusWin as the WM_CHECK window */ val = Scr.NoFocusWin; ewmh_ChangeProperty( Scr.Root, "_NET_SUPPORTING_WM_CHECK", EWMH_ATOM_LIST_FVWM_ROOT, (unsigned char *)&val, 1); ewmh_ChangeProperty( Scr.NoFocusWin, "_NET_SUPPORTING_WM_CHECK", EWMH_ATOM_LIST_FVWM_ROOT, (unsigned char *)&val, 1); names[0] = "fvwm"; classhints.res_name= "fvwm"; classhints.res_class= "FVWM"; XSetClassHint(dpy, Scr.NoFocusWin, &classhints); if (XStringListToTextProperty(names, 1, &text)) { XSetWMName(dpy, Scr.NoFocusWin, &text); XFree(text.value); } /* FVWM in UTF8 */ utf_name[0] = 0x46; utf_name[1] = 0x56; utf_name[2] = 0x57; utf_name[3] = 0x4D; ewmh_ChangeProperty( Scr.NoFocusWin, "_NET_WM_NAME", EWMH_ATOM_LIST_PROPERTY_NOTIFY, (unsigned char *)&utf_name, 4); clean_up(); EWMH_SetDesktopNames(); EWMH_SetCurrentDesktop(); EWMH_SetNumberOfDesktops(); EWMH_SetDesktopViewPort(); EWMH_SetDesktopGeometry(); EWMH_SetClientList(); EWMH_SetClientListStacking(); ewmh_ComputeAndSetWorkArea(); return; } /* * Exit Stuff */ void EWMH_ExitStuff(void) { FvwmWindow *fw; for (fw = Scr.FvwmRoot.next; fw != NULL; fw = fw->next) { EWMH_RestoreInitialStates(fw, 0); } return; } #ifdef EWMH_DEBUG void EWMH_DLOG(char *msg, ...) { va_list args; clock_t time_val, time_taken; static clock_t start_time = 0; static clock_t prev_time = 0; struct tms not_used_tms; char buffer[200]; /* oversized */ time_t mytime; struct tm *t_ptr; time(&mytime); t_ptr = localtime(&mytime); if (start_time == 0) { /* get clock ticks */ prev_time = start_time = (unsigned int)times(¬_used_tms); } /* get clock ticks */ time_val = (unsigned int)times(¬_used_tms); time_taken = time_val - prev_time; prev_time = time_val; sprintf( buffer, "%.2d:%.2d:%.2d %6ld", t_ptr->tm_hour, t_ptr->tm_min, t_ptr->tm_sec, time_taken); fprintf(stderr, "EWMH DEBUG: "); va_start(args,msg); vfprintf(stderr, msg, args); va_end(args); fprintf(stderr, "\n"); fprintf(stderr, " [time]: %s\n",buffer); return; } #endif void EWMH_fullscreen(FvwmWindow *fw) { fscreen_scr_arg fscr; rectangle scr_g; size_borders b; int page_x; int page_y; char cmd[128] = "\0"; /* maximize with ResizeMoveMaximize */ if ( !is_function_allowed( F_MAXIMIZE, NULL, fw, RQORIG_PROGRAM_US, False) || !is_function_allowed( F_MOVE, NULL, fw, RQORIG_PROGRAM_US, False) || !is_function_allowed( F_RESIZE, NULL, fw, RQORIG_PROGRAM_US, True)) { return; } fw->fullscreen.was_maximized = 0; fw->fullscreen.is_shaded = 0; /* Keep the old geometry when restoring from fullscreen. */ memcpy(&fw->fullscreen.g, &fw->g, sizeof(struct window_g)); if (IS_MAXIMIZED(fw)) fw->fullscreen.was_maximized = 1; if (IS_ICONIFIED(fw)) { fw->fullscreen.is_iconified = 1; execute_function_override_window( NULL, NULL, "Iconify off", 0, fw); } if (IS_SHADED(fw)) { int sas = fw->shade_anim_steps; fw->fullscreen.is_shaded = 1; fw->shade_anim_steps = 0; execute_function_override_window( NULL, NULL, "WindowShade off", 0, fw); fw->shade_anim_steps = sas; } SET_EWMH_FULLSCREEN(fw,True); apply_decor_change(fw); fscr.xypos.x = fw->g.frame.x + fw->g.frame.width / 2; fscr.xypos.y = fw->g.frame.y + fw->g.frame.height / 2; FScreenGetScrRect( &fscr, FSCREEN_XYPOS, &scr_g.x, &scr_g.y, &scr_g.width, &scr_g.height); get_window_borders(fw, &b); get_page_offset_check_visible(&page_x, &page_y, fw); sprintf( cmd, "ResizeMoveMaximize %dp %dp +%dp +%dp ewmhiwa", scr_g.width, scr_g.height, scr_g.x - b.top_left.width + page_x, scr_g.y - b.top_left.height + page_y); if (DO_EWMH_USE_STACKING_HINTS(fw)) { int sl = fw->ewmh_normal_layer; new_layer(fw, Scr.TopLayer); if (sl == 0) { fw->ewmh_normal_layer = Scr.DefaultLayer; } else { fw->ewmh_normal_layer = sl; } } if (cmd[0] != 0) { SET_DISABLE_CONSTRAIN_SIZE_FULLSCREEN(fw, 1); execute_function_override_window(NULL, NULL, cmd, 0, fw); SET_DISABLE_CONSTRAIN_SIZE_FULLSCREEN(fw, 0); } return; } fvwm-2.7.0/fvwm/functable.h0000644000175000017500000000130114147024676012521 00000000000000/* -*-c-*- */ #ifndef FUNCTABLE_H #define FUNCTABLE_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ #define PRE_KEEPRC "keeprc" #define PRE_REPEAT "repeat" #define PRE_SILENT "silent" /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ /* ---------------------------- exported variables (globals) --------------- */ extern const func_t func_table[]; /* ---------------------------- interface functions ------------------------ */ #endif /* FUNCTABLE_H */ fvwm-2.7.0/fvwm/functions.c0000644000175000017500000010065014147024700012554 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* * fvwm built-in functions and complex functions */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include "libs/fvwmlib.h" #include "libs/charmap.h" #include "libs/wcontext.h" #include "libs/Grab.h" #include "libs/Parse.h" #include "libs/Strings.h" #include "libs/Event.h" #include "fvwm.h" #include "externs.h" #include "cursor.h" #include "execcontext.h" #include "functions.h" #include "commands.h" #include "functable.h" #include "events.h" #include "modconf.h" #include "module_list.h" #include "misc.h" #include "screen.h" #include "repeat.h" #include "expand.h" #include "menus.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ typedef struct FunctionItem { struct FvwmFunction *func; /* the function this item is in */ struct FunctionItem *next_item; /* next function item */ char condition; /* the character string displayed on * left*/ char *action; /* action to be performed */ short type; /* type of built in function */ FUNC_FLAGS_TYPE flags; } FunctionItem; typedef struct FvwmFunction { struct FvwmFunction *next_func; /* next in list of root menus */ FunctionItem *first_item; /* first item in function */ FunctionItem *last_item; /* last item in function */ char *name; /* function name */ int use_depth; } FvwmFunction; /* Types of events for the FUNCTION builtin */ typedef enum { CF_IMMEDIATE = 'i', CF_LATE_IMMEDIATE = 'j', CF_MOTION = 'm', CF_HOLD = 'h', CF_CLICK = 'c', CF_DOUBLE_CLICK = 'd', CF_TIMEOUT = '-' } cfunc_action_t; /* ---------------------------- forward declarations ----------------------- */ static void execute_complex_function( cond_rc_t *cond_rc, const exec_context_t *exc, char *action, Bool *desperate, Bool has_ref_window_moved); /* ---------------------------- local variables ---------------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ static int __context_has_window( const exec_context_t *exc, execute_flags_t flags) { if (exc->w.fw != NULL) { return 1; } else if ((flags & FUNC_ALLOW_UNMANAGED) && exc->w.w != None) { return 1; } return 0; } /* * Defer the execution of a function to the next button press if the context is * C_ROOT * * Inputs: * cursor - the cursor to display while waiting */ static Bool DeferExecution( exec_context_changes_t *ret_ecc, exec_context_change_mask_t *ret_mask, cursor_t cursor, int trigger_evtype, int do_allow_unmanaged) { int done; int finished = 0; int just_waiting_for_finish = 0; Window dummy; Window original_w; static XEvent e; Window w; int wcontext; FvwmWindow *fw; int FinishEvent; fw = ret_ecc->w.fw; w = ret_ecc->w.w; original_w = w; wcontext = ret_ecc->w.wcontext; FinishEvent = ((fw != NULL) ? ButtonRelease : ButtonPress); if (wcontext == C_UNMANAGED && do_allow_unmanaged) { return False; } if (wcontext != C_ROOT && wcontext != C_NO_CONTEXT && fw != NULL && wcontext != C_EWMH_DESKTOP) { if (FinishEvent == ButtonPress || (FinishEvent == ButtonRelease && trigger_evtype != ButtonPress)) { return False; } else if (FinishEvent == ButtonRelease) { /* We are only waiting until the user releases the * button. Do not change the cursor. */ cursor = CRS_NONE; just_waiting_for_finish = 1; } } if (Scr.flags.are_functions_silent) { return True; } if (!GrabEm(cursor, GRAB_NORMAL)) { XBell(dpy, 0); return True; } MyXGrabKeyboard(dpy); while (!finished) { done = 0; /* block until there is an event */ FMaskEvent( dpy, ButtonPressMask | ButtonReleaseMask | ExposureMask | KeyPressMask | VisibilityChangeMask | ButtonMotionMask | PointerMotionMask /* | EnterWindowMask | LeaveWindowMask*/, &e); if (e.type == KeyPress) { KeySym keysym = XLookupKeysym(&e.xkey, 0); if (keysym == XK_Escape) { ret_ecc->x.etrigger = &e; *ret_mask |= ECC_ETRIGGER; UngrabEm(GRAB_NORMAL); MyXUngrabKeyboard(dpy); return True; } Keyboard_shortcuts(&e, NULL, NULL, NULL, FinishEvent); } if (e.type == FinishEvent) { finished = 1; } switch (e.type) { case KeyPress: case ButtonPress: if (e.type != FinishEvent) { original_w = e.xany.window; } done = 1; break; case ButtonRelease: done = 1; break; default: break; } if (!done) { dispatch_event(&e); } } MyXUngrabKeyboard(dpy); UngrabEm(GRAB_NORMAL); if (just_waiting_for_finish) { return False; } w = e.xany.window; ret_ecc->x.etrigger = &e; *ret_mask |= ECC_ETRIGGER | ECC_W | ECC_WCONTEXT; if ((w == Scr.Root || w == Scr.NoFocusWin) && e.xbutton.subwindow != None) { w = e.xbutton.subwindow; e.xany.window = w; } if (w == Scr.Root || IS_EWMH_DESKTOP(w)) { ret_ecc->w.w = w; ret_ecc->w.wcontext = C_ROOT; XBell(dpy, 0); return True; } *ret_mask |= ECC_FW; if (XFindContext(dpy, w, FvwmContext, (caddr_t *)&fw) == XCNOENT) { ret_ecc->w.fw = NULL; ret_ecc->w.w = w; ret_ecc->w.wcontext = C_ROOT; XBell(dpy, 0); return (True); } if (w == FW_W_PARENT(fw)) { w = FW_W(fw); } if (original_w == FW_W_PARENT(fw)) { original_w = FW_W(fw); } /* this ugly mess attempts to ensure that the release and press * are in the same window. */ if (w != original_w && original_w != Scr.Root && original_w != None && original_w != Scr.NoFocusWin && !IS_EWMH_DESKTOP(original_w)) { if (w != FW_W_FRAME(fw) || original_w != FW_W(fw)) { ret_ecc->w.fw = fw; ret_ecc->w.w = w; ret_ecc->w.wcontext = C_ROOT; XBell(dpy, 0); return True; } } if (IS_EWMH_DESKTOP(FW_W(fw))) { ret_ecc->w.fw = fw; ret_ecc->w.w = w; ret_ecc->w.wcontext = C_ROOT; XBell(dpy, 0); return True; } wcontext = GetContext(NULL, fw, &e, &dummy); ret_ecc->w.fw = fw; ret_ecc->w.w = w; ret_ecc->w.wcontext = C_ROOT; return False; } /* ** do binary search on func list */ static int func_comp(const void *a, const void *b) { return (strcmp((char *)a, ((func_t *)b)->keyword)); } static const func_t *find_builtin_function(char *func) { static int nfuncs = 0; func_t *ret_func; char *temp; char *s; if (!func || func[0] == 0) { return NULL; } /* since a lot of lines in a typical rc are probably menu/func * continues: */ if (func[0]=='+' || (func[0] == ' ' && func[1] == '+')) { return &(func_table[0]); } temp = safestrdup(func); for (s = temp; *s != 0; s++) { if (isupper(*s)) { *s = tolower(*s); } } if (nfuncs == 0) { for ( ; (func_table[nfuncs]).action != NULL; nfuncs++) { /* nothing to do here */ } } ret_func = (func_t *)bsearch( temp, func_table, nfuncs, sizeof(func_t), func_comp); free(temp); return ret_func; } static void __execute_function( cond_rc_t *cond_rc, const exec_context_t *exc, char *action, FUNC_FLAGS_TYPE exec_flags, char *args[], Bool has_ref_window_moved) { static int func_depth = 0; cond_rc_t *func_rc = NULL; cond_rc_t dummy_rc; Window w; int j; char *function; char *taction; char *trash; char *trash2; char *expaction = NULL; char *arguments[11]; const func_t *bif; Bool set_silent; Bool must_free_string = False; Bool must_free_function = False; Bool do_keep_rc = False; /* needed to be able to avoid resize to use moved windows for base */ extern Window PressedW; Window dummy_w; if (!action) { return; } /* ignore whitespace at the beginning of all config lines */ action = SkipSpaces(action, NULL, 0); if (!action || action[0] == 0) { /* impossibly short command */ return; } if (action[0] == '#') { /* a comment */ return; } func_depth++; if (func_depth > MAX_FUNCTION_DEPTH) { fvwm_msg( ERR, "__execute_function", "Function '%s' called with a depth of %i, " "stopping function execution!", action, func_depth); func_depth--; return; } if (args) { for (j = 0; j < 11; j++) { arguments[j] = args[j]; } } else { for (j = 0; j < 11; j++) { arguments[j] = NULL; } } if (exc->w.fw == NULL || IS_EWMH_DESKTOP(FW_W(exc->w.fw))) { if (exec_flags & FUNC_IS_UNMANAGED) { w = exc->w.w; } else { w = Scr.Root; } } else { FvwmWindow *tw; w = GetSubwindowFromEvent(dpy, exc->x.elast); if (w == None) { w = exc->x.elast->xany.window; } tw = NULL; if (w != None) { if (XFindContext( dpy, w, FvwmContext, (caddr_t *)&tw) == XCNOENT) { tw = NULL; } } if (w == None || tw != exc->w.fw) { w = FW_W(exc->w.fw); } } set_silent = False; if (action[0] == '-') { exec_flags |= FUNC_DONT_EXPAND_COMMAND; action++; } taction = action; /* parse prefixes */ trash = PeekToken(taction, &trash2); while (trash) { if (StrEquals(trash, PRE_SILENT)) { if (Scr.flags.are_functions_silent == 0) { set_silent = 1; Scr.flags.are_functions_silent = 1; } taction = trash2; trash = PeekToken(taction, &trash2); } else if (StrEquals(trash, PRE_KEEPRC)) { do_keep_rc = True; taction = trash2; trash = PeekToken(taction, &trash2); } else { break; } } if (taction == NULL) { if (set_silent) { Scr.flags.are_functions_silent = 0; } func_depth--; return; } if (cond_rc == NULL || do_keep_rc == True) { condrc_init(&dummy_rc); func_rc = &dummy_rc; } else { func_rc = cond_rc; } GetNextToken(taction, &function); if (function) { char *tmp = function; function = expand_vars( function, arguments, False, False, func_rc, exc); free(tmp); } if (function && function[0] != '*') { #if 1 /* DV: with this piece of code it is impossible to have a * complex function with embedded whitespace that begins with a * builtin function name, e.g. a function "echo hello". */ /* DV: ... and without it some of the complex functions will * fail */ char *tmp = function; while (*tmp && !isspace(*tmp)) { tmp++; } *tmp = 0; #endif bif = find_builtin_function(function); must_free_function = True; } else { bif = NULL; if (function) { free(function); } function = ""; } if (Scr.cur_decor && Scr.cur_decor != &Scr.DefaultDecor && (!bif || !(bif->flags & FUNC_DECOR))) { fvwm_msg( ERR, "__execute_function", "Command can not be added to a decor; executing" " command now: '%s'", action); } if (!(exec_flags & FUNC_DONT_EXPAND_COMMAND)) { expaction = expand_vars( taction, arguments, (bif) ? !!(bif->flags & FUNC_ADD_TO) : False, (taction[0] == '*'), func_rc, exc); if (func_depth <= 1) { must_free_string = set_repeat_data( expaction, REPEAT_COMMAND, bif); } else { must_free_string = True; } } else { expaction = taction; } #ifdef FVWM_COMMAND_LOG fvwm_msg(INFO, "LOG", "%c: %s", (char)exc->type, expaction); #endif /* Note: the module config command, "*" can not be handled by the * regular command table because there is no required white space after * the asterisk. */ if (expaction[0] == '*') { if (Scr.cur_decor && Scr.cur_decor != &Scr.DefaultDecor) { fvwm_msg( WARN, "__execute_function", "Command can not be added to a decor;" " executing command now: '%s'", expaction); } /* process a module config command */ ModuleConfig(expaction); } else { const exec_context_t *exc2; exec_context_changes_t ecc; exec_context_change_mask_t mask; mask = (w != exc->w.w) ? ECC_W : 0; ecc.w.fw = exc->w.fw; ecc.w.w = w; ecc.w.wcontext = exc->w.wcontext; if (bif && bif->func_t != F_FUNCTION) { char *runaction; Bool rc = False; runaction = SkipNTokens(expaction, 1); if ((bif->flags & FUNC_NEEDS_WINDOW) && !(exec_flags & FUNC_DONT_DEFER)) { rc = DeferExecution( &ecc, &mask, bif->cursor, exc->x.elast->type, (bif->flags & FUNC_ALLOW_UNMANAGED)); } else if ((bif->flags & FUNC_NEEDS_WINDOW) && !__context_has_window( exc, bif->flags & FUNC_ALLOW_UNMANAGED)) { /* no context window and not allowed to defer, * skip command */ rc = True; } if (rc == False) { exc2 = exc_clone_context(exc, &ecc, mask); if (has_ref_window_moved && (bif->func_t == F_ANIMATED_MOVE || bif->func_t == F_MOVE || bif->func_t == F_RESIZE || bif->func_t == F_RESIZEMOVE || bif->func_t == F_RESIZE_MAXIMIZE || bif->func_t == F_RESIZEMOVE_MAXIMIZE)) { dummy_w = PressedW; PressedW = None; bif->action(func_rc, exc2, runaction); PressedW = dummy_w; } else { bif->action(func_rc, exc2, runaction); } exc_destroy_context(exc2); } } else { Bool desperate = 1; char *runaction; if (bif) { /* strip "function" command */ runaction = SkipNTokens(expaction, 1); } else { runaction = expaction; } exc2 = exc_clone_context(exc, &ecc, mask); execute_complex_function( func_rc, exc2, runaction, &desperate, has_ref_window_moved); if (!bif && desperate) { if (executeModuleDesperate( func_rc, exc, runaction) == NULL && *function != 0 && !set_silent) { fvwm_msg( ERR, "__execute_function", "No such command '%s'", function); } } exc_destroy_context(exc2); } } if (set_silent) { Scr.flags.are_functions_silent = 0; } if (cond_rc != NULL) { cond_rc->break_levels = func_rc->break_levels; } if (must_free_string) { free(expaction); } if (must_free_function) { free(function); } func_depth--; return; } /* find_complex_function expects a token as the input. Make sure you have used * GetNextToken before passing a function name to remove quotes */ static FvwmFunction *find_complex_function(const char *function_name) { FvwmFunction *func; if (function_name == NULL || *function_name == 0) { return NULL; } func = Scr.functions; while (func != NULL) { if (func->name != NULL) { if (strcasecmp(function_name, func->name) == 0) { return func; } } func = func->next_func; } return NULL; } /* * Builtin which determines if the button press was a click or double click... * Waits Scr.ClickTime, or until it is evident that the user is not * clicking, but is moving the cursor */ static cfunc_action_t CheckActionType( int x, int y, XEvent *d, Bool may_time_out, Bool is_button_pressed, int *ret_button) { int xcurrent,ycurrent,total = 0; Time t0; int dist; Bool do_sleep = False; xcurrent = x; ycurrent = y; t0 = fev_get_evtime(); dist = Scr.MoveThreshold; while ((total < Scr.ClickTime && fev_get_evtime() - t0 < Scr.ClickTime) || !may_time_out) { if (!(x - xcurrent <= dist && xcurrent - x <= dist && y - ycurrent <= dist && ycurrent - y <= dist)) { return (is_button_pressed) ? CF_MOTION : CF_TIMEOUT; } if (do_sleep) { usleep(20000); } else { usleep(1); do_sleep = 1; } total += 20; if (FCheckMaskEvent( dpy, ButtonReleaseMask|ButtonMotionMask| PointerMotionMask|ButtonPressMask|ExposureMask, d)) { do_sleep = 0; switch (d->xany.type) { case ButtonRelease: *ret_button = d->xbutton.button; return CF_CLICK; case MotionNotify: if (d->xmotion.same_screen == False) { break; } if ((d->xmotion.state & DEFAULT_ALL_BUTTONS_MASK) || !is_button_pressed) { xcurrent = d->xmotion.x_root; ycurrent = d->xmotion.y_root; } else { return CF_CLICK; } break; case ButtonPress: *ret_button = d->xbutton.button; if (may_time_out) { is_button_pressed = True; } break; case Expose: /* must handle expose here so that raising a * window with "I" works */ dispatch_event(d); break; default: /* can't happen */ break; } } } return (is_button_pressed) ? CF_HOLD : CF_TIMEOUT; } static void __run_complex_function_items( cond_rc_t *cond_rc, char cond, FvwmFunction *func, const exec_context_t *exc, char *args[], Bool has_ref_window_moved) { char c; FunctionItem *fi; int x0, y0, x, y; extern Window PressedW; if (!(!has_ref_window_moved && PressedW && XTranslateCoordinates( dpy, PressedW , Scr.Root, 0, 0, &x0, &y0, &JunkChild))) { x0 = y0 = 0; } for (fi = func->first_item; fi != NULL && cond_rc->break_levels == 0; ) { /* make lower case */ c = fi->condition; if (isupper(c)) { c = tolower(c); } if (c == cond) { __execute_function( cond_rc, exc, fi->action, FUNC_DONT_DEFER, args, has_ref_window_moved); if (!has_ref_window_moved && PressedW && XTranslateCoordinates( dpy, PressedW , Scr.Root, 0, 0, &x, &y, &JunkChild)) { has_ref_window_moved =(x != x0 || y != y0); } } fi = fi->next_item; } return; } static void __cf_cleanup( int *depth, char **arguments, cond_rc_t *cond_rc) { int i; (*depth)--; if (!(*depth)) { Scr.flags.is_executing_complex_function = 0; } for (i = 0; i < 11; i++) { if (arguments[i] != NULL) { free(arguments[i]); } } if (cond_rc->break_levels > 0) { cond_rc->break_levels--; } return; } static void execute_complex_function( cond_rc_t *cond_rc, const exec_context_t *exc, char *action, Bool *desperate, Bool has_ref_window_moved) { cond_rc_t tmp_rc; cfunc_action_t type = CF_MOTION; char c; FunctionItem *fi; Bool Persist = False; Bool HaveDoubleClick = False; Bool HaveHold = False; Bool NeedsTarget = False; Bool ImmediateNeedsTarget = False; int has_immediate = 0; int do_run_late_immediate = 0; int do_allow_unmanaged = FUNC_ALLOW_UNMANAGED; int do_allow_unmanaged_immediate = FUNC_ALLOW_UNMANAGED; char *arguments[11], *taction; char *func_name; int x, y ,i; XEvent d; FvwmFunction *func; static int depth = 0; const exec_context_t *exc2; exec_context_changes_t ecc; exec_context_change_mask_t mask; int trigger_evtype; int button; XEvent *te; if (cond_rc == NULL) { condrc_init(&tmp_rc); cond_rc = &tmp_rc; } cond_rc->rc = COND_RC_OK; mask = 0; d.type = 0; ecc.w.fw = exc->w.fw; ecc.w.w = exc->w.w; ecc.w.wcontext = exc->w.wcontext; /* find_complex_function expects a token, not just a quoted string */ func_name = PeekToken(action, &taction); if (!func_name) { return; } func = find_complex_function(func_name); if (func == NULL) { if (*desperate == 0) { fvwm_msg( ERR, "ComplexFunction", "No such function %s", action); } return; } if (!depth) { Scr.flags.is_executing_complex_function = 1; } depth++; *desperate = 0; /* duplicate the whole argument list for use as '$*' */ if (taction) { arguments[0] = safestrdup(taction); /* strip trailing newline */ if (arguments[0][0]) { int l= strlen(arguments[0]); if (arguments[0][l - 1] == '\n') { arguments[0][l - 1] = 0; } } /* Get the argument list */ for (i = 1; i < 11; i++) { taction = GetNextToken(taction, &arguments[i]); } } else { for (i = 0; i < 11; i++) { arguments[i] = NULL; } } /* In case we want to perform an action on a button press, we * need to fool other routines */ te = exc->x.elast; if (te->type == ButtonPress) { trigger_evtype = ButtonRelease; } else { trigger_evtype = te->type; } func->use_depth++; for (fi = func->first_item; fi != NULL; fi = fi->next_item) { if (fi->condition == CF_IMMEDIATE) { has_immediate = 1; } if (fi->flags & FUNC_NEEDS_WINDOW) { NeedsTarget = True; do_allow_unmanaged &= fi->flags; if (fi->condition == CF_IMMEDIATE) { do_allow_unmanaged_immediate &= fi->flags; ImmediateNeedsTarget = True; } } } if (ImmediateNeedsTarget) { if (DeferExecution( &ecc, &mask, CRS_SELECT, trigger_evtype, do_allow_unmanaged_immediate)) { func->use_depth--; __cf_cleanup(&depth, arguments, cond_rc); return; } NeedsTarget = False; } else { ecc.w.w = (ecc.w.fw) ? FW_W_FRAME(ecc.w.fw) : None; mask |= ECC_W; } /* we have to grab buttons before executing immediate actions because * these actions can move the window away from the pointer so that a * button release would go to the application below. */ if (!GrabEm(CRS_NONE, GRAB_NORMAL)) { func->use_depth--; fvwm_msg( ERR, "ComplexFunction", "Grab failed in function %s," " unable to execute immediate action", action); __cf_cleanup(&depth, arguments, cond_rc); return; } if (has_immediate) { exc2 = exc_clone_context(exc, &ecc, mask); __run_complex_function_items( cond_rc, CF_IMMEDIATE, func, exc2, arguments, has_ref_window_moved); exc_destroy_context(exc2); } for (fi = func->first_item; fi != NULL && cond_rc->break_levels == 0; fi = fi->next_item) { /* c is already lowercase here */ c = fi->condition; switch (c) { case CF_IMMEDIATE: break; case CF_LATE_IMMEDIATE: do_run_late_immediate = 1; break; case CF_DOUBLE_CLICK: HaveDoubleClick = True; Persist = True; break; case CF_HOLD: HaveHold = True; Persist = True; break; default: Persist = True; break; } } if (!Persist || cond_rc->break_levels != 0) { func->use_depth--; __cf_cleanup(&depth, arguments, cond_rc); UngrabEm(GRAB_NORMAL); return; } /* Only defer execution if there is a possibility of needing * a window to operate on */ if (NeedsTarget) { if (DeferExecution( &ecc, &mask, CRS_SELECT, trigger_evtype, do_allow_unmanaged)) { func->use_depth--; __cf_cleanup(&depth, arguments, cond_rc); UngrabEm(GRAB_NORMAL); return; } } te = (mask & ECC_ETRIGGER) ? ecc.x.etrigger : exc->x.elast; switch (te->xany.type) { case ButtonPress: case ButtonRelease: x = te->xbutton.x_root; y = te->xbutton.y_root; button = te->xbutton.button; /* Take the click which started this fuction off the * Event queue. -DDN- Dan D Niles dniles@iname.com */ FCheckMaskEvent(dpy, ButtonPressMask, &d); break; default: if (FQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, &x, &y, &JunkX, &JunkY, &JunkMask) == False) { /* pointer is on a different screen */ x = 0; y = 0; } button = 0; break; } /* Wait and see if we have a click, or a move */ /* wait forever, see if the user releases the button */ type = CheckActionType(x, y, &d, HaveHold, True, &button); if (do_run_late_immediate) { exc2 = exc_clone_context(exc, &ecc, mask); __run_complex_function_items( cond_rc, CF_LATE_IMMEDIATE, func, exc2, arguments, has_ref_window_moved); exc_destroy_context(exc2); do_run_late_immediate = 0; } if (type == CF_CLICK) { int button2; /* If it was a click, wait to see if its a double click */ if (HaveDoubleClick) { type = CheckActionType( x, y, &d, True, False, &button2); switch (type) { case CF_HOLD: case CF_MOTION: case CF_CLICK: if (button == button2) { type = CF_DOUBLE_CLICK; } else { type = CF_CLICK; } break; case CF_TIMEOUT: type = CF_CLICK; break; default: /* can't happen */ break; } } } else if (type == CF_TIMEOUT) { type = CF_HOLD; } /* some functions operate on button release instead of presses. These * gets really weird for complex functions ... */ if (d.type == ButtonPress) { d.type = ButtonRelease; if (d.xbutton.button > 0 && d.xbutton.button <= NUMBER_OF_MOUSE_BUTTONS) { d.xbutton.state &= (~(Button1Mask >> (d.xbutton.button - 1))); } } #ifdef BUGGY_CODE /* domivogt (11-Apr-2000): The pointer ***must not*** be ungrabbed * here. If it is, any window that the mouse enters during the * function will receive MotionNotify events with a button held down! * The results are unpredictable. E.g. rxvt interprets the * ButtonMotion as user input to select text. */ UngrabEm(GRAB_NORMAL); #endif fev_set_evpos(&d, x, y); fev_fake_event(&d); ecc.x.etrigger = &d; ecc.w.w = (ecc.w.fw) ? FW_W_FRAME(ecc.w.fw) : None; mask |= ECC_ETRIGGER | ECC_W; exc2 = exc_clone_context(exc, &ecc, mask); if (do_run_late_immediate) { __run_complex_function_items( cond_rc, CF_LATE_IMMEDIATE, func, exc2, arguments, has_ref_window_moved); } __run_complex_function_items( cond_rc, type, func, exc2, arguments, has_ref_window_moved); exc_destroy_context(exc2); /* This is the right place to ungrab the pointer (see comment above). */ func->use_depth--; __cf_cleanup(&depth, arguments, cond_rc); UngrabEm(GRAB_NORMAL); return; } /* * create a new FvwmFunction */ static FvwmFunction *NewFvwmFunction(const char *name) { FvwmFunction *tmp; tmp = (FvwmFunction *)safemalloc(sizeof(FvwmFunction)); tmp->next_func = Scr.functions; tmp->first_item = NULL; tmp->last_item = NULL; tmp->name = stripcpy(name); tmp->use_depth = 0; Scr.functions = tmp; return tmp; } static void DestroyFunction(FvwmFunction *func) { FunctionItem *fi,*tmp2; FvwmFunction *tmp, *prev; if (func == NULL) { return; } tmp = Scr.functions; prev = NULL; while (tmp && tmp != func) { prev = tmp; tmp = tmp->next_func; } if (tmp != func) { return; } if (func->use_depth != 0) { fvwm_msg( ERR,"DestroyFunction", "Function %s is in use (depth %d)", func->name, func->use_depth); return; } if (prev == NULL) { Scr.functions = func->next_func; } else { prev->next_func = func->next_func; } free(func->name); fi = func->first_item; while (fi != NULL) { tmp2 = fi->next_item; if (fi->action != NULL) { free(fi->action); } free(fi); fi = tmp2; } free(func); return; } /* ---------------------------- interface functions ------------------------ */ Bool functions_is_complex_function(const char *function_name) { if (find_complex_function(function_name) != NULL) { return True; } return False; } void execute_function( cond_rc_t *cond_rc, const exec_context_t *exc, char *action, FUNC_FLAGS_TYPE exec_flags) { __execute_function(cond_rc, exc, action, exec_flags, NULL, False); return; } void execute_function_override_wcontext( cond_rc_t *cond_rc, const exec_context_t *exc, char *action, FUNC_FLAGS_TYPE exec_flags, int wcontext) { const exec_context_t *exc2; exec_context_changes_t ecc; ecc.w.wcontext = wcontext; exc2 = exc_clone_context(exc, &ecc, ECC_WCONTEXT); execute_function(cond_rc, exc2, action, exec_flags); exc_destroy_context(exc2); return; } void execute_function_override_window( cond_rc_t *cond_rc, const exec_context_t *exc, char *action, FUNC_FLAGS_TYPE exec_flags, FvwmWindow *fw) { const exec_context_t *exc2; exec_context_changes_t ecc; ecc.w.fw = fw; if (fw != NULL) { ecc.w.w = FW_W(fw); ecc.w.wcontext = C_WINDOW; exec_flags |= FUNC_DONT_DEFER; } else { ecc.w.w = None; ecc.w.wcontext = C_ROOT; } if (exc != NULL) { exc2 = exc_clone_context( exc, &ecc, ECC_FW | ECC_W | ECC_WCONTEXT); } else { ecc.type = EXCT_NULL; exc2 = exc_create_context( &ecc, ECC_TYPE | ECC_FW | ECC_W | ECC_WCONTEXT); } execute_function(cond_rc, exc2, action, exec_flags); exc_destroy_context(exc2); return; } void find_func_t(char *action, short *func_t, unsigned char *flags) { int j, len = 0; char *endtok = action; Bool matched; int mlen; if (action) { while (*endtok && !isspace((unsigned char)*endtok)) { ++endtok; } len = endtok - action; j=0; matched = False; while (!matched && (mlen = strlen(func_table[j].keyword)) > 0) { if (mlen == len && strncasecmp(action,func_table[j].keyword,mlen) == 0) { matched=True; /* found key word */ if (func_t) { *func_t = func_table[j].func_t; } if (flags) { *flags = func_table[j].flags; } return; } else { j++; } } /* No clue what the function is. Just return "BEEP" */ } if (func_t) { *func_t = F_BEEP; } if (flags) { *flags = 0; } return; } /* * add an item to a FvwmFunction * * Inputs: * func - pointer to the FvwmFunction to add the item * action - the definition string from the config line */ void AddToFunction(FvwmFunction *func, char *action) { FunctionItem *tmp; char *token = NULL; char condition; token = PeekToken(action, &action); if (!token) return; condition = token[0]; if (isupper(condition)) condition = tolower(condition); if (condition != CF_IMMEDIATE && condition != CF_LATE_IMMEDIATE && condition != CF_MOTION && condition != CF_HOLD && condition != CF_CLICK && condition != CF_DOUBLE_CLICK) { fvwm_msg( ERR, "AddToFunction", "Got '%s' instead of a valid function specifier", token); return; } if (token[0] != 0 && token[1] != 0 && (find_builtin_function(token) || find_complex_function(token))) { fvwm_msg( WARN, "AddToFunction", "Got the command or function name '%s' instead of a" " function specifier. This may indicate a syntax" " error in the configuration file. Using %c as the" " specifier.", token, token[0]); } if (!action) { return; } while (isspace(*action)) { action++; } if (*action == 0) { return; } tmp = (FunctionItem *)safemalloc(sizeof(FunctionItem)); tmp->next_item = NULL; tmp->func = func; if (func->first_item == NULL) { func->first_item = tmp; func->last_item = tmp; } else { func->last_item->next_item = tmp; func->last_item = tmp; } tmp->condition = condition; tmp->action = stripcpy(action); find_func_t(tmp->action, NULL, &(tmp->flags)); return; } /* ---------------------------- builtin commands --------------------------- */ void CMD_DestroyFunc(F_CMD_ARGS) { FvwmFunction *func; char *token; token = PeekToken(action, NULL); if (!token) { return; } func = find_complex_function(token); if (!func) { return; } if (Scr.last_added_item.type == ADDED_FUNCTION) { set_last_added_item(ADDED_NONE, NULL); } DestroyFunction(func); return; } void CMD_AddToFunc(F_CMD_ARGS) { FvwmFunction *func; char *token; action = GetNextToken(action,&token); if (!token) { return; } func = find_complex_function(token); if (func == NULL) { func = NewFvwmFunction(token); } /* Set + state to last function */ set_last_added_item(ADDED_FUNCTION, func); free(token); AddToFunction(func, action); return; } void CMD_Plus(F_CMD_ARGS) { if (Scr.last_added_item.type == ADDED_MENU) { add_another_menu_item(action); } else if (Scr.last_added_item.type == ADDED_FUNCTION) { AddToFunction(Scr.last_added_item.item, action); } else if (Scr.last_added_item.type == ADDED_DECOR) { FvwmDecor *tmp = &Scr.DefaultDecor; for ( ; tmp && tmp != Scr.last_added_item.item; tmp = tmp->next) { /* nothing to do here */ } if (!tmp) { return; } AddToDecor(F_PASS_ARGS, tmp); } return; } void CMD_EchoFuncDefinition(F_CMD_ARGS) { FvwmFunction *func; const func_t *bif; FunctionItem *fi; char *token; GetNextToken(action, &token); if (!token) { fvwm_msg(ERR, "EchoFuncDefinition", "Missing argument"); return; } bif = find_builtin_function(token); if (bif != NULL) { fvwm_msg( INFO, "EchoFuncDefinition", "function '%s' is a built in command", token); free(token); return; } func = find_complex_function(token); if (!func) { fvwm_msg( INFO, "EchoFuncDefinition", "function '%s' not defined", token); free(token); return; } fvwm_msg( INFO, "EchoFuncDefinition", "definition of function '%s':", token); for (fi = func->first_item; fi != NULL; fi = fi->next_item) { fvwm_msg( INFO, "EchoFuncDefinition", " %c %s", fi->condition, (fi->action == 0) ? "(null)" : fi->action); } fvwm_msg(INFO, "EchoFuncDefinition", "end of definition"); free(token); return; } /* dummy commands */ void CMD_Title(F_CMD_ARGS) { } void CMD_TearMenuOff(F_CMD_ARGS) { } void CMD_KeepRc(F_CMD_ARGS) { } void CMD_Silent(F_CMD_ARGS) { } void CMD_Function(F_CMD_ARGS) { } fvwm-2.7.0/fvwm/ewmh_conf.c0000644000175000017500000002036314147024700012513 00000000000000/* -*-c-*- */ /* Copyright (C) 2001 Olivier Chapuis */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ #include "config.h" #include #include #include #include "libs/fvwmlib.h" #include "libs/Parse.h" #include "libs/Strings.h" #include "fvwm.h" #include "cursor.h" #include "functions.h" #include "misc.h" #include "screen.h" #include "update.h" #include "stack.h" #include "style.h" #include "externs.h" #include "icons.h" #include "ewmh.h" #include "ewmh_intern.h" #include "move_resize.h" /* * CMDS */ static void set_state_workaround(void) { FvwmWindow *t; for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) { if ((t->Desk != Scr.CurrentDesk) && (!is_window_sticky_across_desks(t) && !IS_ICON_UNMAPPED(t))) { if (Scr.bo.do_enable_ewmh_iconic_state_workaround) { SetMapStateProp(t, NormalState); } else { SetMapStateProp(t, IconicState); } } } } Bool EWMH_BugOpts(char *opt, Bool toggle) { Bool save_isw = Scr.bo.do_enable_ewmh_iconic_state_workaround; if (StrEquals(opt,"EWMHIconicStateWorkaround")) { switch (toggle) { case -1: Scr.bo.do_enable_ewmh_iconic_state_workaround ^= 1; break; case 0: case 1: Scr.bo.do_enable_ewmh_iconic_state_workaround = toggle; break; default: Scr.bo.do_enable_ewmh_iconic_state_workaround = 0; break; } if (save_isw != Scr.bo.do_enable_ewmh_iconic_state_workaround) { set_state_workaround(); } return True; } return False; } void CMD_EwmhNumberOfDesktops(F_CMD_ARGS) { int val[2]; int num; num = GetIntegerArguments(action, NULL, val, 2); if ((num != 1 && num != 2) || val[0] < 1 || (num == 2 && val[1] < val[0] && val[1] != 0)) { fvwm_msg(ERR,"EwmhNumberOfDesktops", "Bad arguments to EwmhNumberOfDesktops"); return; } if (num == 2 && ewmhc.MaxDesktops != val[1]) { ewmhc.MaxDesktops = val[1]; num = 3; } else if (num == 1 && ewmhc.MaxDesktops != 0) { ewmhc.MaxDesktops = 0; num = 3; } if (ewmhc.NumberOfDesktops != val[0]) { ewmhc.NumberOfDesktops = val[0]; num = 3; } if (num == 3) { ewmhc.NeedsToCheckDesk = True; EWMH_SetNumberOfDesktops(); } } void CMD_EwmhBaseStruts(F_CMD_ARGS) { int val[4]; if (GetIntegerArguments(action, NULL, val, 4) != 4 || val[0] < 0 || val[1] < 0 || val[2] < 0 || val[3] < 0) { fvwm_msg(ERR,"CMD_EwmhBaseStruts", "EwmhBaseStruts needs four positive arguments"); return; } if (ewmhc.BaseStrut.left != val[0] || ewmhc.BaseStrut.right != val[1] || ewmhc.BaseStrut.top != val[2] || ewmhc.BaseStrut.bottom != val[3]) { ewmhc.BaseStrut.left = val[0]; ewmhc.BaseStrut.right = val[1]; ewmhc.BaseStrut.top = val[2]; ewmhc.BaseStrut.bottom = val[3]; EWMH_UpdateWorkArea(); } } /* * Styles */ Bool EWMH_CMD_Style(char *token, window_style *ptmpstyle, int on) { int found = False; if (StrEquals(token, "EWMHDonateIcon")) { found = True; S_SET_DO_EWMH_DONATE_ICON(SCF(*ptmpstyle), on); S_SET_DO_EWMH_DONATE_ICON(SCM(*ptmpstyle), 1); S_SET_DO_EWMH_DONATE_ICON(SCC(*ptmpstyle), 1); } else if (StrEquals(token, "EWMHDonateMiniIcon")) { found = True; S_SET_DO_EWMH_DONATE_MINI_ICON(SCF(*ptmpstyle), on); S_SET_DO_EWMH_DONATE_MINI_ICON(SCM(*ptmpstyle), 1); S_SET_DO_EWMH_DONATE_MINI_ICON(SCC(*ptmpstyle), 1); } else if (StrEquals(token, "EWMHDontDonateIcon")) { found = True; S_SET_DO_EWMH_DONATE_ICON(SCF(*ptmpstyle), !on); S_SET_DO_EWMH_DONATE_ICON(SCM(*ptmpstyle), 1); S_SET_DO_EWMH_DONATE_ICON(SCC(*ptmpstyle), 1); } else if (StrEquals(token, "EWMHDontDonateMiniIcon")) { found = True; S_SET_DO_EWMH_DONATE_MINI_ICON(SCF(*ptmpstyle), !on); S_SET_DO_EWMH_DONATE_MINI_ICON(SCM(*ptmpstyle), 1); S_SET_DO_EWMH_DONATE_MINI_ICON(SCC(*ptmpstyle), 1); } else if (StrEquals(token, "EWMHMaximizeIgnoreWorkingArea")) { found = True; S_SET_EWMH_MAXIMIZE_MODE( SCF(*ptmpstyle), EWMH_IGNORE_WORKING_AREA); S_SET_EWMH_MAXIMIZE_MODE( SCM(*ptmpstyle), EWMH_WORKING_AREA_MASK); S_SET_EWMH_MAXIMIZE_MODE( SCC(*ptmpstyle), EWMH_WORKING_AREA_MASK); } else if (StrEquals(token, "EWMHMaximizeUseWorkingArea")) { found = True; S_SET_EWMH_MAXIMIZE_MODE( SCF(*ptmpstyle), EWMH_USE_WORKING_AREA); S_SET_EWMH_MAXIMIZE_MODE( SCM(*ptmpstyle), EWMH_WORKING_AREA_MASK); S_SET_EWMH_MAXIMIZE_MODE( SCC(*ptmpstyle), EWMH_WORKING_AREA_MASK); } else if (StrEquals(token, "EWMHMaximizeUseDynamicWorkingArea")) { found = True; S_SET_EWMH_MAXIMIZE_MODE( SCF(*ptmpstyle), EWMH_USE_DYNAMIC_WORKING_AREA); S_SET_EWMH_MAXIMIZE_MODE( SCM(*ptmpstyle), EWMH_WORKING_AREA_MASK); S_SET_EWMH_MAXIMIZE_MODE( SCC(*ptmpstyle), EWMH_WORKING_AREA_MASK); } else if (StrEquals(token, "EWMHMiniIconOverride")) { found = True; S_SET_DO_EWMH_MINI_ICON_OVERRIDE(SCF(*ptmpstyle), on); S_SET_DO_EWMH_MINI_ICON_OVERRIDE(SCM(*ptmpstyle), 1); S_SET_DO_EWMH_MINI_ICON_OVERRIDE(SCC(*ptmpstyle), 1); } else if (StrEquals(token, "EWMHNoMiniIconOverride")) { found = True; S_SET_DO_EWMH_MINI_ICON_OVERRIDE(SCF(*ptmpstyle), !on); S_SET_DO_EWMH_MINI_ICON_OVERRIDE(SCM(*ptmpstyle), 1); S_SET_DO_EWMH_MINI_ICON_OVERRIDE(SCC(*ptmpstyle), 1); } else if (StrEquals(token, "EWMHPlacementIgnoreWorkingArea")) { found = True; ptmpstyle->flags.ewmh_placement_mode = EWMH_IGNORE_WORKING_AREA; ptmpstyle->flag_mask.ewmh_placement_mode = EWMH_WORKING_AREA_MASK; ptmpstyle->change_mask.ewmh_placement_mode = EWMH_WORKING_AREA_MASK; } else if (StrEquals(token, "EWMHPlacementUseWorkingArea")) { found = True; ptmpstyle->flags.ewmh_placement_mode = EWMH_USE_WORKING_AREA; ptmpstyle->flag_mask.ewmh_placement_mode = EWMH_WORKING_AREA_MASK; ptmpstyle->change_mask.ewmh_placement_mode = EWMH_WORKING_AREA_MASK; } else if (StrEquals(token, "EWMHPlacementUseDynamicWorkingArea")) { found = True; ptmpstyle->flags.ewmh_placement_mode = EWMH_USE_DYNAMIC_WORKING_AREA; ptmpstyle->flag_mask.ewmh_placement_mode = EWMH_WORKING_AREA_MASK; ptmpstyle->change_mask.ewmh_placement_mode = EWMH_WORKING_AREA_MASK; } else if (StrEquals(token, "EWMHUseStackingOrderHints")) { found = True; S_SET_DO_EWMH_USE_STACKING_HINTS(SCF(*ptmpstyle), on); S_SET_DO_EWMH_USE_STACKING_HINTS(SCM(*ptmpstyle), 1); S_SET_DO_EWMH_USE_STACKING_HINTS(SCC(*ptmpstyle), 1); } else if (StrEquals(token, "EWMHIgnoreStackingOrderHints")) { found = True; S_SET_DO_EWMH_USE_STACKING_HINTS(SCF(*ptmpstyle), !on); S_SET_DO_EWMH_USE_STACKING_HINTS(SCM(*ptmpstyle), 1); S_SET_DO_EWMH_USE_STACKING_HINTS(SCC(*ptmpstyle), 1); } else if (StrEquals(token, "EWMHUseStateHints")) { found = True; S_SET_DO_EWMH_IGNORE_STATE_HINTS(SCF(*ptmpstyle), !on); S_SET_DO_EWMH_IGNORE_STATE_HINTS(SCM(*ptmpstyle), 1); S_SET_DO_EWMH_IGNORE_STATE_HINTS(SCC(*ptmpstyle), 1); } else if (StrEquals(token, "EWMHIgnoreStateHints")) { found = True; S_SET_DO_EWMH_IGNORE_STATE_HINTS(SCF(*ptmpstyle), on); S_SET_DO_EWMH_IGNORE_STATE_HINTS(SCM(*ptmpstyle), 1); S_SET_DO_EWMH_IGNORE_STATE_HINTS(SCC(*ptmpstyle), 1); } else if (StrEquals(token, "EWMHUseStrutHints")) { found = True; S_SET_DO_EWMH_IGNORE_STRUT_HINTS(SCF(*ptmpstyle), !on); S_SET_DO_EWMH_IGNORE_STRUT_HINTS(SCM(*ptmpstyle), 1); S_SET_DO_EWMH_IGNORE_STRUT_HINTS(SCC(*ptmpstyle), 1); } else if (StrEquals(token, "EWMHIgnoreStrutHints")) { found = True; S_SET_DO_EWMH_IGNORE_STRUT_HINTS(SCF(*ptmpstyle), on); S_SET_DO_EWMH_IGNORE_STRUT_HINTS(SCM(*ptmpstyle), 1); S_SET_DO_EWMH_IGNORE_STRUT_HINTS(SCC(*ptmpstyle), 1); } else if (StrEquals(token, "EWMHIgnoreWindowType")) { found = True; S_SET_DO_EWMH_IGNORE_WINDOW_TYPE(SCF(*ptmpstyle), on); S_SET_DO_EWMH_IGNORE_WINDOW_TYPE(SCM(*ptmpstyle), 1); S_SET_DO_EWMH_IGNORE_WINDOW_TYPE(SCC(*ptmpstyle), 1); } return found; } fvwm-2.7.0/fvwm/events.h0000644000175000017500000000331714147024700012057 00000000000000/* -*-c-*- */ #ifndef EVENTS_H #define EVENTS_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ typedef struct { Window w; Atom atom; int event_type; int stop_at_event_type; char do_stop_at_event_type; } flush_property_notify_args; /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ void dispatch_event(XEvent *e); int GetContext(FvwmWindow **ret_fw, FvwmWindow *t, const XEvent *e, Window *w); int My_XNextEvent(Display *dpy, XEvent *event); void flush_accumulate_expose(Window w, XEvent *e); void handle_all_expose(void); Bool StashEventTime(const XEvent *ev); void CoerceEnterNotifyOnCurrentWindow(void); void InitEventHandlerJumpTable(void); void SendConfigureNotify( FvwmWindow *fw, int x, int y, int w, int h, int bw, Bool send_for_frame_too); void WaitForButtonsUp(Bool do_handle_expose); int discard_typed_events(int num_event_types, int *event_types); int flush_property_notify_stop_at_event_type( Atom atom, Window w, char do_stop_at_event_type, int stop_at_event_type); void sync_server(int toggle); Bool is_resizing_event_pending(FvwmWindow *fw); void events_handle_configure_request( XEvent *e, FvwmWindow *fw, Bool force_use_grav, int force_gravity); Bool test_typed_window_event(Display *display, XEvent *event, char *arg); #endif /* EVENTS_H */ fvwm-2.7.0/fvwm/geometry.c0000644000175000017500000007267414147024700012415 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include "libs/fvwmlib.h" #include "libs/charmap.h" #include "libs/wcontext.h" #include "fvwm.h" #include "externs.h" #include "execcontext.h" #include "misc.h" #include "screen.h" #include "geometry.h" #include "module_interface.h" #include "borders.h" #include "icons.h" #include "add_window.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ /* ---------------------------- interface functions ------------------------ */ /* Removes decorations from the source rectangle and moves it according to the * gravity specification. */ void gravity_get_naked_geometry( int gravity, FvwmWindow *t, rectangle *dest_g, rectangle *orig_g) { int xoff; int yoff; size_borders b; get_window_borders(t, &b); gravity_get_offsets(gravity, &xoff, &yoff); dest_g->x = orig_g->x + ((xoff + 1) * (orig_g->width - 1)) / 2; dest_g->y = orig_g->y + ((yoff + 1) * (orig_g->height - 1)) / 2; dest_g->width = orig_g->width - b.total_size.width; dest_g->height = orig_g->height - b.total_size.height; return; } /* Decorate the rectangle. Resize and shift it according to gravity. */ void gravity_add_decoration( int gravity, FvwmWindow *t, rectangle *dest_g, rectangle *orig_g) { size_borders b; get_window_borders(t, &b); *dest_g = *orig_g; gravity_resize( gravity, dest_g, b.total_size.width, b.total_size.height); return; } void get_relative_geometry(rectangle *rel_g, rectangle *abs_g) { rel_g->x = abs_g->x - Scr.Vx; rel_g->y = abs_g->y - Scr.Vy; rel_g->width = abs_g->width; rel_g->height = abs_g->height; return; } void get_absolute_geometry(rectangle *abs_g, rectangle *rel_g) { abs_g->x = rel_g->x + Scr.Vx; abs_g->y = rel_g->y + Scr.Vy; abs_g->width = rel_g->width; abs_g->height = rel_g->height; return; } void gravity_translate_to_northwest_geometry( int gravity, FvwmWindow *t, rectangle *dest_g, rectangle *orig_g) { int xoff; int yoff; gravity_get_offsets(gravity, &xoff, &yoff); dest_g->x = orig_g->x - ((xoff + 1) * (orig_g->width - 1 + 2 * t->attr_backup.border_width)) / 2; dest_g->y = orig_g->y - ((yoff + 1) * (orig_g->height - 1 + 2 * t->attr_backup.border_width)) / 2; dest_g->width = orig_g->width; dest_g->height = orig_g->height; return; } void gravity_translate_to_northwest_geometry_no_bw( int gravity, FvwmWindow *t, rectangle *dest_g, rectangle *orig_g) { int bw = t->attr_backup.border_width; t->attr_backup.border_width = 0; gravity_translate_to_northwest_geometry(gravity, t, dest_g, orig_g); t->attr_backup.border_width = bw; return; } void get_title_geometry( FvwmWindow *fw, rectangle *ret_g) { size_borders b; size_borders nt; int w; int h; get_window_borders(fw, &b); get_window_borders_no_title(fw, &nt); w = (ret_g->width > 0) ? ret_g->width : fw->g.frame.width; h = (ret_g->height > 0) ? ret_g->height : fw->g.frame.height; ret_g->x = nt.top_left.width; ret_g->y = nt.top_left.height; switch (GET_TITLE_DIR(fw)) { case DIR_S: ret_g->y = h - b.bottom_right.height; /* fall through */ case DIR_N: ret_g->width = w - b.total_size.width; ret_g->height = fw->title_thickness; break; case DIR_E: ret_g->x = w - b.bottom_right.width; /* fall through */ case DIR_W: ret_g->width = fw->title_thickness; ret_g->height = h - b.total_size.height; break; default: break; } return; } void get_title_gravity_factors( FvwmWindow *fw, int *ret_fx, int *ret_fy) { switch (GET_TITLE_DIR(fw)) { case DIR_N: *ret_fx = 0; *ret_fy = 1; break; case DIR_S: *ret_fx = 0; *ret_fy = -1; break; case DIR_W: *ret_fx = 1; *ret_fy = 0; break; case DIR_E: *ret_fx = -1; *ret_fy = 0; break; } return; } Bool get_title_button_geometry( FvwmWindow *fw, rectangle *ret_g, int context) { int bnum; if (context & C_TITLE) { ret_g->width = 0; ret_g->height = 0; get_title_geometry(fw, ret_g); ret_g->x += fw->g.frame.x; ret_g->y += fw->g.frame.y; return True; } bnum = get_button_number(context); if (bnum < 0 || FW_W_BUTTON(fw, bnum) == None) { return False; } if (XGetGeometry( dpy, FW_W_BUTTON(fw, bnum), &JunkRoot, &ret_g->x, &ret_g->y, (unsigned int*)&ret_g->width, (unsigned int*)&ret_g->height, (unsigned int*)&JunkBW, (unsigned int*)&JunkDepth) == 0) { return False; } XTranslateCoordinates( dpy, FW_W_FRAME(fw), Scr.Root, ret_g->x, ret_g->y, &ret_g->x, &ret_g->y, &JunkChild); return True; } void get_title_font_size_and_offset( FvwmWindow *fw, direction_t title_dir, Bool is_left_title_rotated_cw, Bool is_right_title_rotated_cw, Bool is_top_title_rotated, Bool is_bottom_title_rotated, int *size, int *offset) { int decor_size; int extra_size; int font_size; int min_offset; Bool is_rotated_cw, is_rotated; rotation_t draw_rotation; /* adjust font offset according to height specified in title style */ decor_size = fw->decor->title_height; font_size = fw->title_font->height + EXTRA_TITLE_FONT_HEIGHT; switch (title_dir) { case DIR_W: case DIR_E: is_rotated_cw = (title_dir == DIR_W) ? is_left_title_rotated_cw : is_right_title_rotated_cw; if (is_rotated_cw) { fw->title_text_rotation = ROTATION_90; } else { fw->title_text_rotation = ROTATION_270; } break; case DIR_N: case DIR_S: default: is_rotated = (title_dir == DIR_N) ? is_top_title_rotated : is_bottom_title_rotated; if (is_rotated) { fw->title_text_rotation = ROTATION_180; } else { fw->title_text_rotation = ROTATION_0; } break; } if (USE_TITLE_DECOR_ROTATION(fw)) { draw_rotation = ROTATION_0; } else { draw_rotation = fw->title_text_rotation; } min_offset = FlocaleGetMinOffset( fw->title_font, draw_rotation); extra_size = (decor_size > 0) ? decor_size - font_size : 0; *offset = min_offset; if (fw->decor->min_title_height > 0 && font_size + extra_size < fw->decor->min_title_height) { extra_size = fw->decor->min_title_height - font_size; } if (extra_size > 0) { *offset += extra_size / 2; } *size = font_size + extra_size; return; } void get_icon_corner( FvwmWindow *fw, rectangle *ret_g) { switch (GET_TITLE_DIR(fw)) { case DIR_N: case DIR_W: ret_g->x = fw->g.frame.x; ret_g->y = fw->g.frame.y; break; case DIR_S: ret_g->x = fw->g.frame.x; ret_g->y = fw->g.frame.y + fw->g.frame.height - ret_g->height; break; case DIR_E: ret_g->x = fw->g.frame.x + fw->g.frame.width - ret_g->width; ret_g->y = fw->g.frame.y; break; } return; } void get_shaded_geometry( FvwmWindow *fw, rectangle *small_g, rectangle *big_g) { size_borders b; /* this variable is necessary so the function can be called with * small_g == big_g */ int big_width = big_g->width; int big_height = big_g->height; int d; switch (SHADED_DIR(fw)) { case DIR_SW: case DIR_SE: case DIR_NW: case DIR_NE: get_window_borders_no_title(fw, &b); break; default: get_window_borders(fw, &b); break; } *small_g = *big_g; d = 0; switch (SHADED_DIR(fw)) { case DIR_S: case DIR_SW: case DIR_SE: small_g->y = big_g->y + big_height - b.total_size.height; d = 1; /* fall through */ case DIR_N: case DIR_NW: case DIR_NE: small_g->height = b.total_size.height; if (small_g->height == 0) { small_g->height = 1; small_g->y -= d; } break; default: break; } d = 0; switch (SHADED_DIR(fw)) { case DIR_E: case DIR_NE: case DIR_SE: small_g->x = big_g->x + big_width - b.total_size.width; d = 1; /* fall through */ case DIR_W: case DIR_NW: case DIR_SW: small_g->width = b.total_size.width; if (small_g->width == 0) { small_g->width = 1; small_g->x -= d; } break; default: break; } return; } void get_shaded_geometry_with_dir( FvwmWindow *fw, rectangle *small_g, rectangle *big_g, direction_t shade_dir) { direction_t old_shade_dir; old_shade_dir = SHADED_DIR(fw); SET_SHADED_DIR(fw, shade_dir); get_shaded_geometry(fw, small_g, big_g); SET_SHADED_DIR(fw, old_shade_dir); return; } void get_unshaded_geometry( FvwmWindow *fw, rectangle *ret_g) { if (IS_SHADED(fw)) { if (IS_MAXIMIZED(fw)) { *ret_g = fw->g.max; } else { *ret_g = fw->g.normal; } get_relative_geometry(ret_g, ret_g); } else { *ret_g = fw->g.frame; } return; } void get_shaded_client_window_pos( FvwmWindow *fw, rectangle *ret_g) { rectangle big_g; size_borders b; get_window_borders(fw, &b); big_g = (IS_MAXIMIZED(fw)) ? fw->g.max : fw->g.normal; get_relative_geometry(&big_g, &big_g); switch (SHADED_DIR(fw)) { case DIR_S: case DIR_SW: case DIR_SE: ret_g->y = 1 - big_g.height + b.total_size.height; break; default: ret_g->y = 0; break; } switch (SHADED_DIR(fw)) { case DIR_E: case DIR_NE: case DIR_SE: ret_g->x = 1 - big_g.width + b.total_size.width; break; default: ret_g->x = 0; break; } return; } /* returns the dimensions of the borders */ void get_window_borders( const FvwmWindow *fw, size_borders *borders) { borders->top_left.width = fw->boundary_width; borders->bottom_right.width = fw->boundary_width; borders->top_left.height = fw->boundary_width; borders->bottom_right.height = fw->boundary_width; switch (GET_TITLE_DIR(fw)) { case DIR_N: borders->top_left.height += fw->title_thickness; break; case DIR_S: borders->bottom_right.height += fw->title_thickness; break; case DIR_W: borders->top_left.width += fw->title_thickness; break; case DIR_E: borders->bottom_right.width += fw->title_thickness; break; } borders->total_size.width = borders->top_left.width + borders->bottom_right.width; borders->total_size.height = borders->top_left.height + borders->bottom_right.height; return; } /* returns the dimensions of the borders without the title */ void get_window_borders_no_title( const FvwmWindow *fw, size_borders *borders) { borders->top_left.width = fw->boundary_width; borders->bottom_right.width = fw->boundary_width; borders->top_left.height = fw->boundary_width; borders->bottom_right.height = fw->boundary_width; borders->total_size.width = borders->top_left.width + borders->bottom_right.width; borders->total_size.height = borders->top_left.height + borders->bottom_right.height; return; } void set_window_border_size( FvwmWindow *fw, int used_width) { if (used_width <= 0) { fw->boundary_width = 0; fw->unshaped_boundary_width = 0; } else { fw->unshaped_boundary_width = used_width; fw->boundary_width = (fw->wShaped) ? 0 : used_width; } return; } /* Returns True if all window borders are only 1 pixel thick (or less). */ Bool is_window_border_minimal( FvwmWindow *fw) { size_borders nt; get_window_borders_no_title(fw, &nt); if (nt.top_left.width > 1 || nt.top_left.height > 1 || nt.bottom_right.width > 1 || nt.bottom_right.height > 1) { return False; } return True; } /* This function returns the geometry of the client window. If the window is * shaded, the unshaded geometry is used instead. */ void get_client_geometry( FvwmWindow *fw, rectangle *ret_g) { size_borders borders; get_unshaded_geometry(fw, ret_g); get_window_borders(fw, &borders); ret_g->x += borders.top_left.width; ret_g->y += borders.top_left.height; ret_g->width -= borders.total_size.width; ret_g->height -= borders.total_size.height; return; } /* update the frame_g according to the window's g.normal or g.max and shaded * state */ void update_relative_geometry(FvwmWindow *fw) { get_relative_geometry( &fw->g.frame, (IS_MAXIMIZED(fw)) ? &fw->g.max : &fw->g.normal); if (IS_SHADED(fw)) { get_shaded_geometry( fw, &fw->g.frame, &fw->g.frame); } return; } /* update the g.normal or g.max according to the window's current position */ void update_absolute_geometry(FvwmWindow *fw) { rectangle *dest_g; rectangle frame_g; /* store orig values in absolute coords */ dest_g = (IS_MAXIMIZED(fw)) ? &fw->g.max : &fw->g.normal; frame_g = *dest_g; dest_g->x = fw->g.frame.x + Scr.Vx; dest_g->y = fw->g.frame.y + Scr.Vy; dest_g->width = fw->g.frame.width; dest_g->height = fw->g.frame.height; if (IS_SHADED(fw)) { switch (SHADED_DIR(fw)) { case DIR_SW: case DIR_S: case DIR_SE: dest_g->y += fw->g.frame.height - frame_g.height; /* fall through */ case DIR_NW: case DIR_N: case DIR_NE: dest_g->height = frame_g.height; break; } switch (SHADED_DIR(fw)) { case DIR_NE: case DIR_E: case DIR_SE: dest_g->x += fw->g.frame.width - frame_g.width; /* fall through */ case DIR_NW: case DIR_W: case DIR_SW: dest_g->width = frame_g.width; break; } } return; } /* make sure a maximized window and it's normal version are never a page or * more apart. */ void maximize_adjust_offset(FvwmWindow *fw) { int off_x; int off_y; int dh; int dw; if (!IS_MAXIMIZED(fw)) { /* otherwise we might corrupt the g.normal */ return; } off_x = fw->g.normal.x - fw->g.max.x - fw->g.max_offset.x; off_y = fw->g.normal.y - fw->g.max.y - fw->g.max_offset.y; dw = Scr.MyDisplayWidth; dh = Scr.MyDisplayHeight; if (off_x >= dw) { fw->g.normal.x -= (off_x / dw) * dw; } else if (off_x <= -dw) { fw->g.normal.x += (-off_x / dw) * dw; } if (off_y >= dh) { fw->g.normal.y -= (off_y / dh) * dh; } else if (off_y <= -dh) { fw->g.normal.y += (-off_y / dh) * dh; } return; } #define MAKEMULT(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) ) static void __cs_handle_aspect_ratio( size_rect *ret_s, FvwmWindow *fw, size_rect s, const size_rect base, const size_rect inc, size_rect min, size_rect max, int xmotion, int ymotion, int flags) { volatile double odefect; volatile double defect; volatile double rmax; volatile double rmin; volatile int delta; volatile int ow; volatile int oh; if (fw->hints.flags & PBaseSize) { /* * ICCCM 2 demands that aspect ratio should apply to width - * base_width. To prevent funny results, we reset PBaseSize in * GetWindowSizeHints, if base is not smaller than min. */ s.width -= base.width; max.width -= base.width; min.width -= base.width; s.height -= base.height; max.height -= base.height; min.height -= base.height; } rmin = (double)fw->hints.min_aspect.x / (double)fw->hints.min_aspect.y; rmax = (double)fw->hints.max_aspect.x / (double)fw->hints.max_aspect.y; do { double r; r = (double)s.width / (double)s.height; ow = s.width; oh = s.height; odefect = 0; if (r < rmin) { odefect = rmin - r; } else if (r > rmax) { odefect = r - rmax; } if (r < rmin && (flags & CS_ROUND_UP) && xmotion == 0) { /* change width to match */ delta = MAKEMULT(s.height * rmin - s.width, inc.width); if (s.width + delta <= max.width) { s.width += delta; } r = (double)s.width / (double)s.height; } if (r < rmin) { /* change height to match */ delta = MAKEMULT( s.height - s.width / rmin, inc.height); if (s.height - delta >= min.height) { s.height -= delta; } else { delta = MAKEMULT( s.height * rmin - s.width, inc.width); if (s.width + delta <= max.width) { s.width += delta; } } r = (double)s.width / (double)s.height; } if (r > rmax && (flags & CS_ROUND_UP) && ymotion == 0) { /* change height to match */ delta = MAKEMULT(s.width /rmax - s.height, inc.height); if (s.height + delta <= max.height) { s.height += delta; } r = (double)s.width / (double)s.height; } if (r > rmax) { /* change width to match */ delta = MAKEMULT(s.width - s.height * rmax, inc.width); if (s.width - delta >= min.width) { s.width -= delta; } else { delta = MAKEMULT( s.width / rmax - s.height, inc.height); if (s.height + delta <= max.height) { s.height += delta; } } r = (double)s.width / (double)s.height; } defect = 0; if (r < rmin) { defect = rmin - r; } else if (r > rmax) { defect = r - rmax; } } while (odefect > defect); if (fw->hints.flags & PBaseSize) { ow += base.width; oh += base.height; } ret_s->width = ow; ret_s->height = oh; return; } /* * * Procedure: * constrain_size - adjust the given width and height to account for the * constraints imposed by size hints */ void constrain_size( FvwmWindow *fw, const XEvent *e, int *widthp, int *heightp, int xmotion, int ymotion, int flags) { size_rect min; size_rect max; size_rect inc; size_rect base; size_rect round_up; size_rect d; size_rect old; size_borders b; if (DO_DISABLE_CONSTRAIN_SIZE_FULLSCREEN(fw) == 1) { return; } if (HAS_NEW_WM_NORMAL_HINTS(fw)) { /* get the latest size hints */ XSync(dpy, 0); GetWindowSizeHints(fw); SET_HAS_NEW_WM_NORMAL_HINTS(fw, 0); } if (IS_MAXIMIZED(fw) && (flags & CS_UPDATE_MAX_DEFECT)) { *widthp += fw->g.max_defect.width; *heightp += fw->g.max_defect.height; } /* gcc 4.1.1 warns about these not being initialized at the end, * but the conditions for the use are the same...*/ old.width = *widthp; old.height = *heightp; d.width = *widthp; d.height = *heightp; get_window_borders(fw, &b); d.width -= b.total_size.width; d.height -= b.total_size.height; min.width = fw->hints.min_width; min.height = fw->hints.min_height; if (min.width < fw->min_window_width - b.total_size.width) { min.width = fw->min_window_width - b.total_size.width; } if (min.height < fw->min_window_height - b.total_size.height) { min.height = fw->min_window_height - b.total_size.height; } max.width = fw->hints.max_width; max.height = fw->hints.max_height; if (max.width > fw->max_window_width - b.total_size.width) { max.width = fw->max_window_width - b.total_size.width; } if (max.height > fw->max_window_height - b.total_size.height) { max.height = fw->max_window_height - b.total_size.height; } if (min.width > max.width) { min.width = max.width; } if (min.height > max.height) { min.height = max.height; } base.width = fw->hints.base_width; base.height = fw->hints.base_height; inc.width = fw->hints.width_inc; inc.height = fw->hints.height_inc; /* * First, clamp to min and max values */ if (d.width < min.width) { d.width = min.width; } if (d.height < min.height) { d.height = min.height; } if (d.width > max.width) { d.width = max.width; } if (d.height > max.height) { d.height = max.height; } /* * Second, round to base + N * inc (up or down depending on resize * type) if rounding up store amount */ if (!(flags & CS_ROUND_UP)) { d.width = ((d.width - base.width) / inc.width) * inc.width + base.width; d.height = ((d.height - base.height) / inc.height) * inc.height + base.height; } else { round_up.width = d.width; round_up.height = d.height; d.width = ((d.width - base.width + inc.width - 1) / inc.width) * inc.width + base.width; d.height = ((d.height - base.height + inc.height - 1) / inc.height) * inc.height + base.height; round_up.width = d.width - round_up.width; round_up.height = d.height - round_up.height; } /* * Step 2a: check we didn't move the edge off screen in interactive * moves */ if ((flags & CS_ROUND_UP) && e != NULL && e->type == MotionNotify) { if (xmotion > 0 && e->xmotion.x_root < round_up.width) { d.width -= inc.width; } else if ( xmotion < 0 && e->xmotion.x_root >= Scr.MyDisplayWidth - round_up.width) { d.width -= inc.width; } if (ymotion > 0 && e->xmotion.y_root < round_up.height) { d.height -= inc.height; } else if ( ymotion < 0 && e->xmotion.y_root >= Scr.MyDisplayHeight - round_up.height) { d.height -= inc.height; } } /* * Step 2b: Check that we didn't violate min and max. */ if (d.width < min.width) { d.width += inc.width; } if (d.height < min.height) { d.height += inc.height; } if (d.width > max.width) { d.width -= inc.width; } if (d.height > max.height) { d.height -= inc.height; } /* * Third, adjust for aspect ratio */ if (fw->hints.flags & PAspect) { __cs_handle_aspect_ratio( &d, fw, d, base, inc, min, max, xmotion, ymotion, flags); } /* * Fourth, account for border width and title height */ *widthp = d.width + b.total_size.width; *heightp = d.height + b.total_size.height; if (IS_MAXIMIZED(fw) && (flags & CS_UPDATE_MAX_DEFECT)) { /* update size defect for maximized window */ fw->g.max_defect.width = old.width - *widthp; fw->g.max_defect.height = old.height - *heightp; } return; } /* This function does roughly the same as constrain_size, but takes into account * that the window shifts according to gravity if constrain_size actually * changes the width or height. The frame_g of the window is not changed. The * target geometry is expected to be in *rect and will be retured through rect. */ void gravity_constrain_size( int gravity, FvwmWindow *t, rectangle *rect, int flags) { int new_width = rect->width; int new_height = rect->height; if (IS_MAXIMIZED(t) && (flags & CS_UPDATE_MAX_DEFECT)) { gravity_resize( gravity, rect, t->g.max_defect.width, t->g.max_defect.height); t->g.max_defect.width = 0; t->g.max_defect.height = 0; new_width = rect->width; new_height = rect->height; } constrain_size( t, NULL, &new_width, &new_height, 0, 0, flags); if (rect->width != new_width || rect->height != new_height) { gravity_resize( gravity, rect, new_width - rect->width, new_height - rect->height); } return; } /* returns the icon title geometry if it is visible */ Bool get_visible_icon_title_geometry( FvwmWindow *fw, rectangle *ret_g) { if (HAS_NO_ICON_TITLE(fw) || IS_ICON_UNMAPPED(fw) || !IS_ICONIFIED(fw)) { memset(ret_g, 0, sizeof(*ret_g)); return False; } *ret_g = fw->icon_g.title_w_g; return True; } /* returns the icon title geometry if it the icon title window exists */ Bool get_icon_title_geometry( FvwmWindow *fw, rectangle *ret_g) { if (HAS_NO_ICON_TITLE(fw)) { memset(ret_g, 0, sizeof(*ret_g)); return False; } *ret_g = fw->icon_g.title_w_g; return True; } /* returns the icon picture geometry if it is visible */ Bool get_visible_icon_picture_geometry( FvwmWindow *fw, rectangle *ret_g) { if (fw->icon_g.picture_w_g.width == 0 || IS_ICON_UNMAPPED(fw) || !IS_ICONIFIED(fw)) { memset(ret_g, 0, sizeof(*ret_g)); return False; } *ret_g = fw->icon_g.picture_w_g; return True; } /* returns the icon picture geometry if it is exists */ Bool get_icon_picture_geometry( FvwmWindow *fw, rectangle *ret_g) { if (fw->icon_g.picture_w_g.width == 0) { memset(ret_g, 0, sizeof(*ret_g)); return False; } *ret_g = fw->icon_g.picture_w_g; return True; } /* returns the icon geometry (unexpanded title plus pixmap) if it is visible */ Bool get_visible_icon_geometry( FvwmWindow *fw, rectangle *ret_g) { if (IS_ICON_UNMAPPED(fw) || !IS_ICONIFIED(fw)) { memset(ret_g, 0, sizeof(*ret_g)); return False; } if (fw->icon_g.picture_w_g.width > 0) { *ret_g = fw->icon_g.picture_w_g; if (!HAS_NO_ICON_TITLE(fw)) { ret_g->height += fw->icon_g.title_w_g.height; } } else if (!HAS_NO_ICON_TITLE(fw)) { *ret_g = fw->icon_g.title_w_g; } else { memset(ret_g, 0, sizeof(*ret_g)); return False; } return True; } /* returns the icon geometry (unexpanded title plus pixmap) if it exists */ void get_icon_geometry( FvwmWindow *fw, rectangle *ret_g) { /* valid geometry? */ if (fw->icon_g.picture_w_g.width > 0) { *ret_g = fw->icon_g.picture_w_g; if (!HAS_NO_ICON_TITLE(fw)) { ret_g->height += fw->icon_g.title_w_g.height; } } else if (fw->icon_g.title_w_g.width > 0) { *ret_g = fw->icon_g.title_w_g; } /* valid position? */ else if (fw->icon_g.picture_w_g.x != 0 || fw->icon_g.picture_w_g.y != 0) { *ret_g = fw->icon_g.picture_w_g; } else if (fw->icon_g.title_w_g.x != 0 || fw->icon_g.title_w_g.y != 0) { *ret_g = fw->icon_g.title_w_g; } else { memset(ret_g, 0, sizeof(*ret_g)); } return; } /* Returns the visible geometry of a window or icon. This can be used to test * if this region overlaps other windows. */ Bool get_visible_window_or_icon_geometry( FvwmWindow *fw, rectangle *ret_g) { if (IS_ICONIFIED(fw)) { return get_visible_icon_geometry(fw, ret_g); } *ret_g = fw->g.frame; return True; } void move_icon_to_position( FvwmWindow *fw) { Bool draw_picture_w = False; Bool draw_title_w = False; if (fw->icon_g.picture_w_g.width > 0) { int cs; if (Scr.Hilite == fw) { cs = fw->cs_hi; } else { cs = fw->cs; } XMoveWindow( dpy, FW_W_ICON_PIXMAP(fw), fw->icon_g.picture_w_g.x, fw->icon_g.picture_w_g.y); if (fw->icon_alphaPixmap || (cs >= 0 && Colorset[cs].icon_alpha_percent < 100) || CSET_IS_TRANSPARENT(fw->icon_background_cs) || (!IS_ICON_SHAPED(fw) && fw->icon_background_padding > 0)) { draw_picture_w = True; } } if (!HAS_NO_ICON_TITLE(fw)) { int cs; rectangle dummy; if (Scr.Hilite == fw) { cs = fw->icon_title_cs_hi; } else { cs = fw->icon_title_cs; } XMoveWindow( dpy, FW_W_ICON_TITLE(fw), fw->icon_g.title_w_g.x, fw->icon_g.title_w_g.y); if (CSET_IS_TRANSPARENT(cs) && !get_visible_icon_picture_geometry(fw, &dummy) && get_visible_icon_title_geometry(fw, &dummy)) { draw_title_w = True; } } if (draw_title_w || draw_picture_w) { DrawIconWindow( fw, draw_title_w, draw_picture_w, False, draw_picture_w, NULL); } return; } void broadcast_icon_geometry( FvwmWindow *fw, Bool do_force) { rectangle g; Bool rc; rc = get_visible_icon_geometry(fw, &g); if (rc == True && (!IS_ICON_UNMAPPED(fw) || do_force == True)) { BroadcastPacket( M_ICON_LOCATION, 7, (long)FW_W(fw), (long)FW_W_FRAME(fw), (unsigned long)fw, (long)g.x, (long)g.y, (long)g.width, (long)g.height); } return; } void modify_icon_position( FvwmWindow *fw, int dx, int dy) { if (fw->icon_g.picture_w_g.width > 0 || HAS_NO_ICON_TITLE(fw)) { /* picture position is also valid if there is neither a picture * nor a title */ fw->icon_g.picture_w_g.x += dx; fw->icon_g.picture_w_g.y += dy; } if (!HAS_NO_ICON_TITLE(fw)) { fw->icon_g.title_w_g.x += dx; fw->icon_g.title_w_g.y += dy; } return; } /* set the icon position to the specified value. take care of the actual icon * layout */ void set_icon_position( FvwmWindow *fw, int x, int y) { if (fw->icon_g.picture_w_g.width > 0) { fw->icon_g.picture_w_g.x = x; fw->icon_g.picture_w_g.y = y; } else { fw->icon_g.picture_w_g.x = 0; fw->icon_g.picture_w_g.y = 0; } if (!HAS_NO_ICON_TITLE(fw)) { fw->icon_g.title_w_g.x = x; fw->icon_g.title_w_g.y = y; } else { fw->icon_g.title_w_g.x = 0; fw->icon_g.title_w_g.y = 0; } if (fw->icon_g.picture_w_g.width > 0 && !HAS_NO_ICON_TITLE(fw)) { fw->icon_g.title_w_g.x -= (fw->icon_g.title_w_g.width - fw->icon_g.picture_w_g.width) / 2; fw->icon_g.title_w_g.y += fw->icon_g.picture_w_g.height; } else if (fw->icon_g.picture_w_g.width <= 0 && HAS_NO_ICON_TITLE(fw)) { /* In case there is no icon, fake the icon position so the * modules know where its window was iconified. */ fw->icon_g.picture_w_g.x = x; fw->icon_g.picture_w_g.y = y; } return; } void set_icon_picture_size( FvwmWindow *fw, int w, int h) { if (fw->icon_g.picture_w_g.width > 0) { fw->icon_g.picture_w_g.width = w; fw->icon_g.picture_w_g.height = h; } else { fw->icon_g.picture_w_g.width = 0; fw->icon_g.picture_w_g.height = 0; } return; } void resize_icon_title_height(FvwmWindow *fw, int dh) { if (!HAS_NO_ICON_TITLE(fw)) { fw->icon_g.title_w_g.height += dh; } return; } void get_page_offset_rectangle( int *ret_page_x, int *ret_page_y, rectangle *r) { int xoff = Scr.Vx % Scr.MyDisplayWidth; int yoff = Scr.Vy % Scr.MyDisplayHeight; /* maximize on the page where the center of the window is */ *ret_page_x = truncate_to_multiple( r->x + r->width / 2 + xoff, Scr.MyDisplayWidth) - xoff; *ret_page_y = truncate_to_multiple( r->y + r->height / 2 + yoff, Scr.MyDisplayHeight) - yoff; return; } void get_page_offset( int *ret_page_x, int *ret_page_y, FvwmWindow *fw) { rectangle r; r.x = fw->g.frame.x; r.y = fw->g.frame.y; r.width = fw->g.frame.width; r.height = fw->g.frame.height; get_page_offset_rectangle(ret_page_x, ret_page_y, &r); return; } void get_page_offset_check_visible( int *ret_page_x, int *ret_page_y, FvwmWindow *fw) { if (IsRectangleOnThisPage(&fw->g.frame, fw->Desk)) { /* maximize on visible page if any part of the window is * visible */ *ret_page_x = 0; *ret_page_y = 0; } else { get_page_offset(ret_page_x, ret_page_y, fw); } return; } /* ---------------------------- builtin commands --------------------------- */ fvwm-2.7.0/fvwm/colormaps.c0000644000175000017500000002415714147024700012552 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include "libs/fvwmlib.h" #include "fvwm.h" #include "externs.h" #include "cursor.h" #include "execcontext.h" #include "eventhandler.h" #include "functions.h" #include "bindings.h" #include "misc.h" #include "screen.h" #include "colormaps.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ static Bool client_controls_colormaps = False; static Colormap last_cmap = None; /* ---------------------------- exported variables (globals) --------------- */ const FvwmWindow *colormap_win; /* ---------------------------- local functions ---------------------------- */ /* ---------------------------- interface functions ------------------------ */ void set_client_controls_colormaps(Bool flag) { client_controls_colormaps = flag; return; } /* HandleColormapNotify - colormap notify event handler * * This procedure handles both a client changing its own colormap, and * a client explicitly installing its colormap itself (only the window * manager should do that, so we must set it correctly). */ void colormap_handle_colormap_notify(const evh_args_t *ea) { XEvent evdummy; XColormapEvent *cevent = (XColormapEvent *)ea->exc->x.etrigger; Bool ReInstall = False; XWindowAttributes attr; FvwmWindow *fw = ea->exc->w.fw; if (!fw) { return; } if (cevent->new) { if (XGetWindowAttributes(dpy, FW_W(fw), &attr) != 0) { fw->attr_backup.colormap = attr.colormap; if (fw == colormap_win && fw->number_cmap_windows == 0) { last_cmap = attr.colormap; } ReInstall = True; } } else if ((cevent->state == ColormapUninstalled)&& (last_cmap == cevent->colormap)) { /* Some window installed its colormap, change it back */ ReInstall = True; } while (FCheckTypedEvent(dpy, ColormapNotify, &evdummy)) { if (XFindContext( dpy, cevent->window, FvwmContext, (caddr_t *) &fw) == XCNOENT) { fw = NULL; } if ((fw)&&(cevent->new)) { if (XGetWindowAttributes(dpy, FW_W(fw), &attr) != 0) { fw->attr_backup.colormap = attr.colormap; if (fw == colormap_win && fw->number_cmap_windows == 0) { last_cmap = attr.colormap; } ReInstall = True; } } else if ((fw)&& (cevent->state == ColormapUninstalled)&& (last_cmap == cevent->colormap)) { /* Some window installed its colormap, change it back */ ReInstall = True; } else if ((fw)&& (cevent->state == ColormapInstalled)&& (last_cmap == cevent->colormap)) { /* The last color map installed was the correct one. * Do not change anything */ ReInstall = False; } } /* Reinstall the colormap that we think should be installed, * UNLESS and unrecognized window has the focus - it might be * an override-redirect window that has its own colormap. */ if (ReInstall && Scr.UnknownWinFocused == None && !client_controls_colormaps) { XInstallColormap(dpy,last_cmap); } return; } /* Re-Install the active colormap */ void ReInstallActiveColormap(void) { InstallWindowColormaps(colormap_win); return; } /* Procedure: * InstallWindowColormaps - install the colormaps for one fvwm window * * Inputs: * type - type of event that caused the installation * tmp - for a subset of event types, the address of the * window structure, whose colormaps are to be installed. */ void InstallWindowColormaps(const FvwmWindow *fw) { int i; XWindowAttributes attributes; Window w; Bool ThisWinInstalled = False; /* If no window, then install fvwm colormap */ if (!fw) { fw = &Scr.FvwmRoot; } colormap_win = fw; /* Save the colormap to be loaded for when force loading of * root colormap(s) ends. */ Scr.pushed_window = fw; /* Don't load any new colormap if root/fvwm colormap(s) has been * force loaded. */ if (Scr.root_pushes || Scr.fvwm_pushes || client_controls_colormaps) { return; } if (fw->number_cmap_windows > 0) { for (i=fw->number_cmap_windows -1; i>=0;i--) { w = fw->cmap_windows[i]; if (w == FW_W(fw)) { ThisWinInstalled = True; } if (!XGetWindowAttributes(dpy,w,&attributes)) { attributes.colormap = last_cmap; } /* * On Sun X servers, don't install 24 bit TrueColor * colourmaps. Despite what the server says, these * colourmaps are always installed. */ if (last_cmap != attributes.colormap #if defined(sun) && defined(TRUECOLOR_ALWAYS_INSTALLED) && !(attributes.depth == 24 && attributes.visual->class == TrueColor) #endif ) { last_cmap = attributes.colormap; XInstallColormap(dpy, last_cmap); } } } if (!ThisWinInstalled) { if (last_cmap != fw->attr_backup.colormap #if defined(sun) && defined(TRUECOLOR_ALWAYS_INSTALLED) && !(fw->attr_backup.depth == 24 && fw->attr_backup.visual->class == TrueColor) #endif ) { last_cmap = fw->attr_backup.colormap; XInstallColormap(dpy, last_cmap); } } return; } /* Force (un)loads root colormap(s) * * These matching routines provide a mechanism to insure that * the root colormap(s) is installed during operations like * rubber banding that require colors from * that colormap. Calls may be nested arbitrarily deeply, * as long as there is one UninstallRootColormap call per * InstallRootColormap call. * * {Uni,I}nstall{Root,Fvwm}Colormap calls may be freely intermixed */ void InstallRootColormap(void) { if (last_cmap != DefaultColormap(dpy, Scr.screen)) { last_cmap = DefaultColormap(dpy, Scr.screen); XInstallColormap(dpy, last_cmap); } Scr.root_pushes++; return; } /* Unstacks one layer of root colormap pushing * If we peel off the last layer, re-install the application colormap * or the fvwm colormap if fvwm has a menu posted */ void UninstallRootColormap(void) { if (Scr.root_pushes) { Scr.root_pushes--; } if (!Scr.root_pushes) { if (!Scr.fvwm_pushes) { InstallWindowColormaps(Scr.pushed_window); } else if (last_cmap != Pcmap) { last_cmap = Pcmap; XInstallColormap(dpy, last_cmap); } } return; } /* Procedures: * {Uni/I}nstallFvwmColormap - Force (un)loads fvwm colormap(s) * This is used to ensure the fvwm colormap is installed during * menu operations */ void InstallFvwmColormap(void) { if (last_cmap != Pcmap) { last_cmap = Pcmap; XInstallColormap(dpy, last_cmap); } Scr.fvwm_pushes++; return; } void UninstallFvwmColormap(void) { if (Scr.fvwm_pushes) { Scr.fvwm_pushes--; } if (!Scr.fvwm_pushes) { if (!Scr.root_pushes) { InstallWindowColormaps(Scr.pushed_window); } else if (last_cmap != DefaultColormap(dpy, Scr.screen)) { last_cmap = DefaultColormap(dpy, Scr.screen); XInstallColormap(dpy, last_cmap); } } return; } /* Gets the WM_COLORMAP_WINDOWS property from the window * * This property typically doesn't exist, but a few applications * use it. These seem to occur mostly on SGI machines. */ void FetchWmColormapWindows (FvwmWindow *fw) { XWindowAttributes getattribs; XSetWindowAttributes setattribs; long i; unsigned long valuemask; if (fw->cmap_windows != (Window *)NULL) { XFree((void *)fw->cmap_windows); } if (!XGetWMColormapWindows (dpy, FW_W(fw), &(fw->cmap_windows), &(fw->number_cmap_windows))) { fw->number_cmap_windows = 0; fw->cmap_windows = NULL; } /* we need to be notified of Enter events into these subwindows * so we can set their colormaps */ if (fw->number_cmap_windows != 0) { for (i = 0; i < fw->number_cmap_windows; i++) { if (XGetWindowAttributes( dpy, fw->cmap_windows[i], &getattribs)) { valuemask = CWEventMask; setattribs.event_mask = getattribs.your_event_mask | EnterWindowMask | LeaveWindowMask; XChangeWindowAttributes( dpy, fw->cmap_windows[i], valuemask, &setattribs); } } } return; } /* Looks through the window list for any matching COLORMAP_WINDOWS * windows and installs the colormap if one exists. */ void EnterSubWindowColormap(Window win) { FvwmWindow *t; long i; XWindowAttributes attribs; for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) { if (t->number_cmap_windows != 0) { for (i = 0; i < t->number_cmap_windows; i++) { if (t->cmap_windows[i] == win) { if (XGetWindowAttributes( dpy,win,&attribs)) { last_cmap = attribs.colormap; XInstallColormap( dpy, last_cmap); } return; } } } } return; } void LeaveSubWindowColormap(Window win) { FvwmWindow *t; long i; int bWinInList, bParentInList; for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) { if (t->number_cmap_windows != 0) { bWinInList = 0; bParentInList = 0; for (i=0;inumber_cmap_windows;i++) { if (t->cmap_windows[i] == win) { bWinInList = 1; } if (t->cmap_windows[i] == FW_W(t)) { bParentInList = 1; } } if (bWinInList) { if (bParentInList) { InstallWindowColormaps(t); } else { InstallWindowColormaps(NULL); } return; } } } return; } fvwm-2.7.0/fvwm/menustyle.h0000644000175000017500000003347714147024700012612 00000000000000/* -*-c-*- */ #ifndef MENUSTYLE_H #define MENUSTYLE_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ #define ST_NAME(s) ((s)->name) #define MST_NAME(m) ((m)->s->ms->name) #define ST_NEXT_STYLE(s) ((s)->next_style) #define MST_NEXT_STYLE(m) ((m)->s->ms->next_style) #define ST_USAGE_COUNT(s) ((s)->usage_count) #define MST_USAGE_COUNT(m) ((m)->s->ms->usage_count) /* flags */ #define ST_IS_UPDATED(s) ((s)->flags.is_updated) #define MST_IS_UPDATED(m) ((m)->s->ms->flags.is_updated) /* look */ #define ST_FACE(s) ((s)->look.face) #define MST_FACE(m) ((m)->s->ms->look.face) #define ST_DO_HILIGHT_BACK(s) ((s)->look.flags.do_hilight_back) #define MST_DO_HILIGHT_BACK(m) ((m)->s->ms->look.flags.do_hilight_back) #define ST_DO_HILIGHT_FORE(s) ((s)->look.flags.do_hilight_fore) #define MST_DO_HILIGHT_FORE(m) ((m)->s->ms->look.flags.do_hilight_fore) #define ST_DO_HILIGHT_TITLE_BACK(s) ((s)->look.flags.do_hilight_title_back) #define MST_DO_HILIGHT_TITLE_BACK(m) \ ((m)->s->ms->look.flags.do_hilight_title_back) #define ST_HAS_ACTIVE_FORE(s) ((s)->look.flags.has_active_fore) #define MST_HAS_ACTIVE_FORE(m) ((m)->s->ms->look.flags.has_active_fore) #define ST_HAS_ACTIVE_BACK(s) ((s)->look.flags.has_active_back) #define MST_HAS_ACTIVE_BACK(m) ((m)->s->ms->look.flags.has_active_back) #define ST_HAS_STIPPLE_FORE(s) ((s)->look.flags.has_stipple_fore) #define MST_HAS_STIPPLE_FORE(m) ((m)->s->ms->look.flags.has_stipple_fore) #define ST_HAS_LONG_SEPARATORS(s) ((s)->look.flags.has_long_separators) #define MST_HAS_LONG_SEPARATORS(m) \ ((m)->s->ms->look.flags.has_long_separators) #define ST_HAS_TRIANGLE_RELIEF(s) ((s)->look.flags.has_triangle_relief) #define MST_HAS_TRIANGLE_RELIEF(m) \ ((m)->s->ms->look.flags.has_triangle_relief) #define ST_HAS_SIDE_COLOR(s) ((s)->look.flags.has_side_color) #define MST_HAS_SIDE_COLOR(m) ((m)->s->ms->look.flags.has_side_color) #define ST_HAS_MENU_CSET(s) ((s)->look.flags.has_menu_cset) #define MST_HAS_MENU_CSET(m) ((m)->s->ms->look.flags.has_menu_cset) #define ST_HAS_ACTIVE_CSET(s) ((s)->look.flags.has_active_cset) #define MST_HAS_ACTIVE_CSET(m) ((m)->s->ms->look.flags.has_active_cset) #define ST_HAS_GREYED_CSET(s) ((s)->look.flags.has_greyed_cset) #define MST_HAS_GREYED_CSET(m) ((m)->s->ms->look.flags.has_greyed_cset) #define ST_HAS_TITLE_CSET(s) ((s)->look.flags.has_title_cset) #define MST_HAS_TITLE_CSET(m) ((m)->s->ms->look.flags.has_title_cset) #define ST_IS_ITEM_RELIEF_REVERSED(s) ((s)->look.flags.is_item_relief_reversed) #define MST_IS_ITEM_RELIEF_REVERSED(m) \ ((m)->s->ms->look.flags.is_item_relief_reversed) #define ST_USING_DEFAULT_FONT(s) ((s)->look.flags.using_default_font) #define MST_USING_DEFAULT_FONT(m) \ ((m)->s->ms->look.flags.using_default_font) #define ST_USING_DEFAULT_TITLEFONT(s) ((s)->look.flags.using_default_titlefont) #define MST_USING_DEFAULT_TITLEFONT(m) \ ((m)->s->ms->look.flags.using_default_titlefont) #define ST_TRIANGLES_USE_FORE(s) ((s)->look.flags.triangles_use_fore) #define MST_TRIANGLES_USE_FORE(m) \ ((m)->s->ms->look.flags.triangles_use_fore) #define ST_RELIEF_THICKNESS(s) ((s)->look.ReliefThickness) #define MST_RELIEF_THICKNESS(m) ((m)->s->ms->look.ReliefThickness) #define ST_TITLE_UNDERLINES(s) ((s)->look.TitleUnderlines) #define MST_TITLE_UNDERLINES(m) ((m)->s->ms->look.TitleUnderlines) #define ST_BORDER_WIDTH(s) ((s)->look.BorderWidth) #define MST_BORDER_WIDTH(m) ((m)->s->ms->look.BorderWidth) #define ST_ITEM_GAP_ABOVE(s) ((s)->look.vertical_spacing.item_above) #define MST_ITEM_GAP_ABOVE(m) \ ((m)->s->ms->look.vertical_spacing.item_above) #define ST_ITEM_GAP_BELOW(s) ((s)->look.vertical_spacing.item_below) #define MST_ITEM_GAP_BELOW(m) \ ((m)->s->ms->look.vertical_spacing.item_below) #define ST_TITLE_GAP_ABOVE(s) ((s)->look.vertical_spacing.title_above) #define MST_TITLE_GAP_ABOVE(m) \ ((m)->s->ms->look.vertical_spacing.title_above) #define ST_TITLE_GAP_BELOW(s) ((s)->look.vertical_spacing.title_below) #define MST_TITLE_GAP_BELOW(m) \ ((m)->s->ms->look.vertical_spacing.title_below) #define ST_SEPARATOR_GAP_ABOVE(s) \ ((s)->look.vertical_spacing.separator_above) #define MST_SEPARATOR_GAP_ABOVE(m) \ ((m)->s->ms->look.vertical_spacing.separator_above) #define ST_SEPARATOR_GAP_BELOW(s) \ ((s)->look.vertical_spacing.separator_below) #define MST_SEPARATOR_GAP_BELOW(m) \ ((m)->s->ms->look.vertical_spacing.separator_below) #define ST_CSET_MENU(s) ((s)->look.cset.menu) #define MST_CSET_MENU(m) ((m)->s->ms->look.cset.menu) #define ST_CSET_ACTIVE(s) ((s)->look.cset.active) #define MST_CSET_ACTIVE(m) ((m)->s->ms->look.cset.active) #define ST_CSET_TITLE(s) ((s)->look.cset.title) #define MST_CSET_TITLE(m) ((m)->s->ms->look.cset.title) #define ST_CSET_GREYED(s) ((s)->look.cset.greyed) #define MST_CSET_GREYED(m) ((m)->s->ms->look.cset.greyed) #define ST_SIDEPIC(s) ((s)->look.side_picture) #define MST_SIDEPIC(m) ((m)->s->ms->look.side_picture) #define ST_SIDE_COLOR(s) ((s)->look.side_color) #define MST_SIDE_COLOR(m) ((m)->s->ms->look.side_color) #define ST_MENU_ACTIVE_GCS(s) ((s)->look.active_gcs) #define MST_MENU_ACTIVE_GCS(m) ((m)->s->ms->look.active_gcs) #define ST_MENU_INACTIVE_GCS(s) ((s)->look.inactive_gcs) #define MST_MENU_INACTIVE_GCS(m) ((m)->s->ms->look.inactive_gcs) #define ST_MENU_STIPPLE_GCS(s) ((s)->look.stipple_gcs) #define MST_MENU_STIPPLE_GCS(m) ((m)->s->ms->look.stipple_gcs) #define ST_MENU_TITLE_GCS(s) ((s)->look.title_gcs) #define MST_MENU_TITLE_GCS(m) ((m)->s->ms->look.title_gcs) #define FORE_GC(g) ((g).fore_gc) #define BACK_GC(g) ((g).back_gc) #define HILIGHT_GC(g) ((g).hilight_gc) #define SHADOW_GC(g) ((g).shadow_gc) #define ST_MENU_STIPPLE_GC(s) ((s)->look.MenuStippleGC) #define MST_MENU_STIPPLE_GC(m) ((m)->s->ms->look.MenuStippleGC) #define ST_MENU_COLORS(s) ((s)->look.MenuColors) #define MST_MENU_COLORS(m) ((m)->s->ms->look.MenuColors) #define ST_MENU_ACTIVE_COLORS(s) ((s)->look.MenuActiveColors) #define MST_MENU_ACTIVE_COLORS(m) ((m)->s->ms->look.MenuActiveColors) #define ST_MENU_STIPPLE_COLORS(s) ((s)->look.MenuStippleColors) #define MST_MENU_STIPPLE_COLORS(m) ((m)->s->ms->look.MenuStippleColors) #define ST_PSTDFONT(s) ((s)->look.pStdFont) #define MST_PSTDFONT(m) ((m)->s->ms->look.pStdFont) #define ST_PTITLEFONT(s) ((s)->look.pTitleFont) #define MST_PTITLEFONT(m) ((m)->s->ms->look.pTitleFont) #define ST_FONT_HEIGHT(s) ((s)->look.FontHeight) #define MST_FONT_HEIGHT(m) ((m)->s->ms->look.FontHeight) /* feel */ #define ST_IS_ANIMATED(s) ((s)->feel.flags.is_animated) #define MST_IS_ANIMATED(m) ((m)->s->ms->feel.flags.is_animated) #define ST_DO_POPUP_IMMEDIATELY(s) ((s)->feel.flags.do_popup_immediately) #define MST_DO_POPUP_IMMEDIATELY(m) \ ((m)->s->ms->feel.flags.do_popup_immediately) #define ST_DO_POPDOWN_IMMEDIATELY(s) ((s)->feel.flags.do_popdown_immediately) #define MST_DO_POPDOWN_IMMEDIATELY(m) \ ((m)->s->ms->feel.flags.do_popdown_immediately) #define ST_DO_WARP_TO_TITLE(s) ((s)->feel.flags.do_warp_to_title) #define MST_DO_WARP_TO_TITLE(m) ((m)->s->ms->feel.flags.do_warp_to_title) #define ST_DO_POPUP_AS(s) ((s)->feel.flags.do_popup_as) #define MST_DO_POPUP_AS(m) ((m)->s->ms->feel.flags.do_popup_as) #define ST_DO_UNMAP_SUBMENU_ON_POPDOWN(s) \ ((s)->feel.flags.do_unmap_submenu_on_popdown) #define MST_DO_UNMAP_SUBMENU_ON_POPDOWN(m) \ ((m)->s->ms->feel.flags.do_unmap_submenu_on_popdown) #define ST_USE_LEFT_SUBMENUS(s) ((s)->feel.flags.use_left_submenus) #define MST_USE_LEFT_SUBMENUS(m) \ ((m)->s->ms->feel.flags.use_left_submenus) #define ST_USE_AUTOMATIC_HOTKEYS(s) ((s)->feel.flags.use_automatic_hotkeys) #define MST_USE_AUTOMATIC_HOTKEYS(m) \ ((m)->s->ms->feel.flags.use_automatic_hotkeys) #define ST_MOUSE_WHEEL(s) ((s)->feel.flags.mouse_wheel) #define MST_MOUSE_WHEEL(m) ((m)->s->ms->feel.flags.mouse_wheel) #define ST_SCROLL_OFF_PAGE(s) ((s)->feel.flags.scroll_off_page) #define MST_SCROLL_OFF_PAGE(m) ((m)->s->ms->feel.flags.scroll_off_page) #define ST_FLAGS(s) ((s)->feel.flags) #define MST_FLAGS(m) ((m)->s->ms->feel.flags) #define ST_POPUP_OFFSET_PERCENT(s) ((s)->feel.PopupOffsetPercent) #define MST_POPUP_OFFSET_PERCENT(m) ((m)->s->ms->feel.PopupOffsetPercent) #define ST_POPUP_OFFSET_ADD(s) ((s)->feel.PopupOffsetAdd) #define MST_POPUP_OFFSET_ADD(m) ((m)->s->ms->feel.PopupOffsetAdd) #define ST_ACTIVE_AREA_PERCENT(s) \ ((s)->feel.ActiveAreaPercent) #define MST_ACTIVE_AREA_PERCENT(m) \ ((m)->s->ms->feel.ActiveAreaPercent) #define ST_POPDOWN_DELAY(s) ((s)->feel.PopdownDelay10ms) #define MST_POPDOWN_DELAY(m) ((m)->s->ms->feel.PopdownDelay10ms) #define ST_POPUP_DELAY(s) ((s)->feel.PopupDelay10ms) #define MST_POPUP_DELAY(m) ((m)->s->ms->feel.PopupDelay10ms) #define ST_DOUBLE_CLICK_TIME(s) ((s)->feel.DoubleClickTime) #define MST_DOUBLE_CLICK_TIME(m) ((m)->s->ms->feel.DoubleClickTime) #define ST_ITEM_FORMAT(s) ((s)->feel.item_format) #define MST_ITEM_FORMAT(m) ((m)->s->ms->feel.item_format) #define ST_SELECT_ON_RELEASE_KEY(s) ((s)->feel.select_on_release_key) #define MST_SELECT_ON_RELEASE_KEY(m) ((m)->s->ms->feel.select_on_release_key) #define ST_VERTICAL_MARGIN_TOP(s) ((s)->look.vertical_margins.top) #define MST_VERTICAL_MARGIN_TOP(m) ((m)->s->ms->look.vertical_margins.top) #define ST_VERTICAL_MARGIN_BOTTOM(s) ((s)->look.vertical_margins.bottom) #define MST_VERTICAL_MARGIN_BOTTOM(m) ((m)->s->ms->look.vertical_margins.bottom) #define ST_HOTKEY_ACTIVATES_IMMEDIATE(s) ((s)->feel.flags.hotkey_activates_immediate) #define MST_HOTKEY_ACTIVATES_IMMEDIATE(m) ((m)->s->ms->feel.flags.hotkey_activates_immediate) /* ---------------------------- type definitions --------------------------- */ typedef enum { /* menu types */ SimpleMenu = 0, GradientMenu, PixmapMenu, TiledPixmapMenu, SolidMenu /* max button is 8 (0x8) */ } MenuFaceType; typedef enum { MDP_POST_MENU = 0, MDP_ROOT_MENU = 1, MDP_IGNORE = 2, MDP_CLOSE = 3 } ms_do_popup_as_t; typedef enum { MMW_OFF = 0, MMW_MENU_BACKWARDS = 1, MMW_MENU = 2, MMW_POINTER = 3 } ms_mouse_wheel_t; typedef struct MenuFeel { struct { unsigned is_animated : 1; unsigned do_popdown_immediately : 1; unsigned do_popup_immediately : 1; unsigned do_popup_as : 2; unsigned do_warp_to_title : 1; unsigned do_unmap_submenu_on_popdown : 1; unsigned use_left_submenus : 1; unsigned use_automatic_hotkeys : 1; unsigned mouse_wheel : 2; unsigned scroll_off_page : 1; unsigned hotkey_activates_immediate : 1; } flags; int PopdownDelay10ms; int PopupOffsetPercent; int ActiveAreaPercent; int PopupOffsetAdd; int PopupDelay10ms; int DoubleClickTime; char *item_format; KeyCode select_on_release_key; } MenuFeel; typedef struct MenuFace { union { FvwmPicture *p; Pixel back; struct { int npixels; XColor *xcs; Bool do_dither; } grad; } u; MenuFaceType type; char gradient_type; } MenuFace; typedef struct { GC fore_gc; GC back_gc; GC hilight_gc; GC shadow_gc; } gc_quad_t; typedef struct MenuLook { MenuFace face; struct { unsigned do_hilight_back : 1; unsigned do_hilight_fore : 1; unsigned has_active_fore : 1; unsigned has_active_back : 1; unsigned has_stipple_fore : 1; unsigned has_long_separators : 1; unsigned has_triangle_relief : 1; unsigned has_side_color : 1; unsigned has_menu_cset : 1; unsigned has_active_cset : 1; unsigned has_greyed_cset : 1; unsigned is_item_relief_reversed : 1; unsigned using_default_font : 1; unsigned triangles_use_fore : 1; unsigned has_title_cset : 1; unsigned do_hilight_title_back : 1; unsigned using_default_titlefont : 1; } flags; unsigned char ReliefThickness; unsigned char TitleUnderlines; unsigned char BorderWidth; struct { signed char item_above; signed char item_below; signed char title_above; signed char title_below; signed char separator_above; signed char separator_below; } vertical_spacing; struct { unsigned char top; unsigned char bottom; } vertical_margins; struct { int menu; int active; int greyed; int title; } cset; FvwmPicture *side_picture; Pixel side_color; gc_quad_t inactive_gcs; gc_quad_t active_gcs; gc_quad_t stipple_gcs; gc_quad_t title_gcs; ColorPair MenuColors; ColorPair MenuActiveColors; ColorPair MenuStippleColors; FlocaleFont *pStdFont; FlocaleFont *pTitleFont; int FontHeight; } MenuLook; typedef struct MenuStyle { char *name; struct MenuStyle *next_style; int usage_count; MenuLook look; MenuFeel feel; struct { unsigned is_updated : 1; } flags; } MenuStyle; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ void menustyle_free(MenuStyle *ms); MenuStyle *menustyle_find(char *name); void menustyle_update(MenuStyle *ms); MenuStyle *menustyle_parse_style(F_CMD_ARGS); MenuStyle *menustyle_get_default_style(void); void menustyle_copy(MenuStyle *origms, MenuStyle *destms); #endif /* MENUSTYLE_H */ fvwm-2.7.0/fvwm/move_resize.h0000644000175000017500000000231514147024700013077 00000000000000/* -*-c-*- */ #ifndef _MOVE_RESIZE_ #define _MOVE_RESIZE_ struct MenuRepaintTransparentParameters; void switch_move_resize_grid(Bool state); void AnimatedMoveOfWindow( Window w,int startX,int startY,int endX, int endY,Bool fWarpPointerToo, int cusDelay, float *ppctMovement, struct MenuRepaintTransparentParameters *pmrtp); void AnimatedMoveFvwmWindow( FvwmWindow *fw, Window w, int startX, int startY, int endX, int endY, Bool fWarpPointerToo, int cmsDelay, float *ppctMovement); Bool __move_loop( const exec_context_t *exc, int XOffset, int YOffset, int Width, int Height, int *FinalX, int *FinalY, Bool do_move_opaque, int cursor); int is_window_sticky_across_pages(FvwmWindow *fw); int is_window_sticky_across_desks(FvwmWindow *fw); void handle_stick( F_CMD_ARGS, int toggle_page, int toggle_desk, int do_not_draw, int do_silently); void resize_geometry_window(void); void __move_icon( FvwmWindow *fw, int x, int y, int old_x, int old_y, Bool do_move_animated, Bool do_warp_pointer); int placement_binding(int button,KeySym keysym,int modifier,char *action); int GetMoveArguments( char **paction, int w, int h, int *pFinalX, int *pFinalY, Bool *fWarp, Bool *fPointer, Bool fKeep); #endif /* _MOVE_RESIZE_ */ fvwm-2.7.0/fvwm/ewmh_names.c0000644000175000017500000001432014147024700012665 00000000000000/* -*-c-*- */ /* Copyright (C) 2001 Olivier Chapuis */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ #include "config.h" #include #include #include #include "libs/fvwmlib.h" #include "libs/Flocale.h" #include "libs/FlocaleCharset.h" #include "libs/Ficonv.h" #include "fvwm.h" #include "window_flags.h" #include "cursor.h" #include "functions.h" #include "misc.h" #include "screen.h" #include "module_interface.h" #include "borders.h" #include "add_window.h" #include "icons.h" #include "ewmh.h" #include "ewmh_intern.h" #include "externs.h" /* * set the visibale window name and icon name */ void EWMH_SetVisibleName(FvwmWindow *fw, Bool is_icon_name) { unsigned char *val; char *tmp_str; FlocaleCharset *fc = NULL; if (!FiconvSupport) { return; } /* set the ewmh visible name only if it is != wm name */ if (is_icon_name) { if ((fw->icon_name_count == 0 || !USE_INDEXED_ICON_NAME(fw)) && !HAS_EWMH_WM_ICON_NAME(fw) && !HAS_EWMH_WM_NAME(fw)) { ewmh_DeleteProperty( FW_W(fw), "_NET_WM_ICON_VISIBLE_NAME", EWMH_ATOM_LIST_FVWM_WIN); return; } if (IS_ICON_FONT_LOADED(fw) && fw->icon_font != NULL) { fc = fw->icon_font->str_fc; } tmp_str = fw->visible_icon_name; } else { if ((fw->name_count == 0 || !USE_INDEXED_WINDOW_NAME(fw)) && !HAS_EWMH_WM_NAME(fw) && !HAS_EWMH_WM_ICON_NAME(fw)) { ewmh_DeleteProperty( FW_W(fw), "_NET_WM_VISIBLE_NAME", EWMH_ATOM_LIST_FVWM_WIN); return; } if (IS_WINDOW_FONT_LOADED(fw) && fw->title_font != NULL) { fc = fw->title_font->str_fc; } tmp_str = fw->visible_name; } if (tmp_str == NULL) { return; /* should never happen */ } val = (unsigned char *)FiconvCharsetToUtf8( dpy, fc, tmp_str, strlen(tmp_str)); if (val == NULL) { return; } if (is_icon_name) { ewmh_ChangeProperty( FW_W(fw), "_NET_WM_ICON_VISIBLE_NAME", EWMH_ATOM_LIST_FVWM_WIN, (unsigned char *)val, strlen((char *)val)); } else { ewmh_ChangeProperty( FW_W(fw), "_NET_WM_VISIBLE_NAME", EWMH_ATOM_LIST_FVWM_WIN, (unsigned char *)val, strlen((char *)val)); } free(val); } /* * setup and property notify */ int EWMH_WMIconName( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { int size = 0; char *val; char *tmp_str; FlocaleCharset *fc = NULL; if (!FiconvSupport) { return 0; } val = ewmh_AtomGetByName( FW_W(fw), "_NET_WM_ICON_NAME", EWMH_ATOM_LIST_PROPERTY_NOTIFY, &size); if (val == NULL) { SET_HAS_EWMH_WM_ICON_NAME(fw,0); return 0; } if (IS_ICON_FONT_LOADED(fw) && fw->icon_font != NULL) { fc = fw->icon_font->str_fc; } tmp_str = (char *)FiconvUtf8ToCharset( dpy, fc, (const char *) val, size); free(val); if (tmp_str == NULL) { SET_HAS_EWMH_WM_ICON_NAME(fw, 0); return 0; } if (strlen(tmp_str) > MAX_ICON_NAME_LEN) { tmp_str[MAX_ICON_NAME_LEN] = 0; } SET_HAS_EWMH_WM_ICON_NAME(fw, 1); if (fw->icon_name.name && strcmp(tmp_str, fw->icon_name.name) == 0) { /* migo: some apps update their names every second */ free(tmp_str); return 0; } if (ev != NULL) { /* client message */ free_window_names(fw, False, True); } fw->icon_name.name = tmp_str; SET_WAS_ICON_NAME_PROVIDED(fw, 1); if (ev == NULL) { /* return now for setup */ return 1; } update_window_names(fw, 2); return 1; } int EWMH_WMName( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { int size = 0; char *val; char *tmp_str; FlocaleCharset *fc = NULL; int what_changed; if (!FiconvSupport) return 0; val = ewmh_AtomGetByName( FW_W(fw), "_NET_WM_NAME", EWMH_ATOM_LIST_PROPERTY_NOTIFY, &size); if (val == NULL) { SET_HAS_EWMH_WM_NAME(fw,0); return 0; } if (IS_WINDOW_FONT_LOADED(fw) && fw->title_font != NULL) { fc = fw->title_font->str_fc; } tmp_str = (char *)FiconvUtf8ToCharset( dpy, fc, (const char *) val, size); free(val); if (tmp_str == NULL) { SET_HAS_EWMH_WM_NAME(fw,0); return 0; } if (strlen(tmp_str) > MAX_WINDOW_NAME_LEN) { tmp_str[MAX_WINDOW_NAME_LEN] = 0; } SET_HAS_EWMH_WM_NAME(fw, 1); if (fw->name.name && strcmp(tmp_str, fw->name.name) == 0) { /* migo: some apps update their names every second */ free(tmp_str); return 0; } if (ev != NULL) { /* client message */ free_window_names(fw, True, False); } fw->name.name = tmp_str; if (ev == NULL) { return 1; } SET_NAME_CHANGED(fw, 1); what_changed = 1; if (!WAS_ICON_NAME_PROVIDED(fw)) { fw->icon_name = fw->name; what_changed |= 2; } update_window_names(fw, what_changed); return 0; } #define MAX(A,B) ((A)>(B)? (A):(B)) /* * set the desktop name */ void EWMH_SetDesktopNames(void) { int nbr = 0; int len = 0; int i; int j = 0; DesktopsInfo *d,*s; unsigned char **names; unsigned char *val; if (!FiconvSupport) { return; } d = Scr.Desktops->next; /* skip negative desk */ while (d != NULL && d->desk < 0) { d = d->next; } s = d; while (d != NULL && d->name != NULL && d->desk == nbr) { nbr++; d = d->next; } if (nbr == 0) { return; } names = (void *)safemalloc(sizeof(*names)*nbr); for (i = 0; i < nbr; i++) { names[i] = (unsigned char *)FiconvCharsetToUtf8( dpy, NULL, s->name, strlen(s->name)); if (names[i]) { len += strlen((char *)names[i]) + 1; } else { len++; } s = s->next; } val = (unsigned char *)safemalloc(len); for (i = 0; i < nbr; i++) { if (names[i] != NULL) { memcpy(&val[j], names[i], strlen((char *)names[i])); j += strlen((char *)names[i]); free(names[i]); } val[j++] = '\0'; } ewmh_ChangeProperty( Scr.Root, "_NET_DESKTOP_NAMES", EWMH_ATOM_LIST_CLIENT_ROOT, (unsigned char *)val, len); free(names); free(val); } fvwm-2.7.0/fvwm/builtins.c0000644000175000017500000025231114147024700012377 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include #include #include #include #include #include "libs/fvwmlib.h" #include "libs/fvwmsignal.h" #include "libs/setpgrp.h" #include "libs/Grab.h" #include "libs/Parse.h" #include "libs/ColorUtils.h" #include "libs/Graphics.h" #include "libs/wild.h" #include "libs/envvar.h" #include "libs/ClientMsg.h" #include "libs/Picture.h" #include "libs/PictureUtils.h" #include "libs/FGettext.h" #include "libs/charmap.h" #include "libs/wcontext.h" #include "libs/Flocale.h" #include "libs/Ficonv.h" #include "fvwm.h" #include "externs.h" #include "colorset.h" #include "bindings.h" #include "misc.h" #include "cursor.h" #include "functions.h" #include "commands.h" #include "screen.h" #include "builtins.h" #include "module_interface.h" #include "borders.h" #include "frame.h" #include "events.h" #include "ewmh.h" #include "virtual.h" #include "decorations.h" #include "add_window.h" #include "update.h" #include "style.h" #include "move_resize.h" #include "menus.h" #include "infostore.h" #ifdef HAVE_STROKE #include "stroke.h" #endif /* HAVE_STROKE */ /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ extern float rgpctMovementDefault[32]; extern int cpctMovementDefault; extern int cmsDelayDefault; /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ typedef enum {FakeMouseEvent, FakeKeyEvent} FakeEventType; /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ static char *exec_shell_name="/bin/sh"; /* button state strings must match the enumerated states */ static char *button_states[BS_MaxButtonStateName + 1] = { "ActiveUp", "ActiveDown", "InactiveUp", "InactiveDown", "ToggledActiveUp", "ToggledActiveDown", "ToggledInactiveUp", "ToggledInactiveDown", "Active", "Inactive", "ToggledActive", "ToggledInactive", "AllNormal", "AllToggled", "AllActive", "AllInactive", "AllUp", "AllDown", "AllActiveUp", "AllActiveDown", "AllInactiveUp", "AllInactiveDown", NULL }; /* ---------------------------- exported variables (globals) --------------- */ char *ModulePath = FVWM_MODULEDIR; int moduleTimeout = DEFAULT_MODULE_TIMEOUT; /* ---------------------------- local functions ---------------------------- */ /** Prepend rather than replace the image path. Used for obsolete PixmapPath and IconPath **/ static void obsolete_imagepaths( const char* pre_path ) { char* tmp = stripcpy( pre_path ); char* path = alloca(strlen( tmp ) + strlen(PictureGetImagePath()) + 2 ); strcpy( path, tmp ); free( tmp ); strcat( path, ":" ); strcat( path, PictureGetImagePath() ); PictureSetImagePath( path ); return; } /* * * Reads a title button description (veliaa@rpi.edu) * */ static char *ReadTitleButton( char *s, TitleButton *tb, Boolean append, int button) { char *end = NULL; char *spec; char *t; int i; int bs; int bs_start, bs_end; int pstyle = 0; DecorFace tmpdf; Bool multiple; int use_mask = 0; int set_mask = 0; s = SkipSpaces(s, NULL, 0); t = GetNextTokenIndex(s, button_states, 0, &bs); if (bs != BS_All) { s = SkipSpaces(t, NULL, 0); } if (bs == BS_All) { use_mask = 0; set_mask = 0; } else if (bs == BS_Active) { use_mask = BS_MASK_INACTIVE | BS_MASK_TOGGLED; set_mask = 0; } else if (bs == BS_Inactive) { use_mask = BS_MASK_INACTIVE | BS_MASK_TOGGLED; set_mask = BS_MASK_INACTIVE; } else if (bs == BS_ToggledActive) { use_mask = BS_MASK_INACTIVE | BS_MASK_TOGGLED; set_mask = BS_MASK_TOGGLED; } else if (bs == BS_ToggledInactive) { use_mask = BS_MASK_INACTIVE | BS_MASK_TOGGLED; set_mask = BS_MASK_INACTIVE | BS_MASK_TOGGLED; } else if (bs == BS_AllNormal) { use_mask = BS_MASK_TOGGLED; set_mask = 0; } else if (bs == BS_AllToggled) { use_mask = BS_MASK_TOGGLED; set_mask = BS_MASK_TOGGLED; } else if (bs == BS_AllActive) { use_mask = BS_MASK_INACTIVE; set_mask = 0; } else if (bs == BS_AllInactive) { use_mask = BS_MASK_INACTIVE; set_mask = BS_MASK_INACTIVE; } else if (bs == BS_AllUp) { use_mask = BS_MASK_DOWN; set_mask = 0; } else if (bs == BS_AllDown) { use_mask = BS_MASK_DOWN; set_mask = BS_MASK_DOWN; } else if (bs == BS_AllActiveUp) { use_mask = BS_MASK_INACTIVE | BS_MASK_DOWN; set_mask = 0; } else if (bs == BS_AllActiveDown) { use_mask = BS_MASK_INACTIVE | BS_MASK_DOWN; set_mask = BS_MASK_DOWN; } else if (bs == BS_AllInactiveUp) { use_mask = BS_MASK_INACTIVE | BS_MASK_DOWN; set_mask = BS_MASK_INACTIVE; } else if (bs == BS_AllInactiveDown) { use_mask = BS_MASK_INACTIVE | BS_MASK_DOWN; set_mask = BS_MASK_INACTIVE | BS_MASK_DOWN; } if ((bs & BS_MaxButtonStateMask) == bs) { multiple = False; bs_start = bs; bs_end = bs; } else { multiple = True; bs_start = 0; bs_end = BS_MaxButtonState - 1; for (i = bs_start; (i & use_mask) != set_mask && i <= bs_end; i++) { bs_start++; } } if (*s == '(') { int len; pstyle = 1; if (!(end = strchr(++s, ')'))) { fvwm_msg( ERR, "ReadTitleButton", "missing parenthesis: %s", s); return NULL; } s = SkipSpaces(s, NULL, 0); len = end - s + 1; spec = safemalloc(len); strncpy(spec, s, len - 1); spec[len - 1] = 0; } else { spec = s; } spec = SkipSpaces(spec, NULL, 0); /* setup temporary in case button read fails */ memset(&tmpdf, 0, sizeof(DecorFace)); DFS_FACE_TYPE(tmpdf.style) = SimpleButton; if (strncmp(spec, "--", 2) == 0) { /* only change flags */ Bool verbose = True; for (i = bs_start; i <= bs_end; ++i) { if (multiple && (i & use_mask) != set_mask) { continue; } ReadDecorFace(spec, &TB_STATE(*tb)[i], button, verbose); verbose = False; } } else if (ReadDecorFace(spec, &tmpdf, button, True)) { if (append) { DecorFace *head = &TB_STATE(*tb)[bs_start]; DecorFace *tail = head; DecorFace *next; while (tail->next) { tail = tail->next; } tail->next = (DecorFace *)safemalloc(sizeof(DecorFace)); memcpy(tail->next, &tmpdf, sizeof(DecorFace)); if (DFS_FACE_TYPE(tail->next->style) == VectorButton && DFS_FACE_TYPE((&TB_STATE(*tb)[bs_start])->style) == DefaultVectorButton) { /* override the default vector style */ memcpy( &tail->next->style, &head->style, sizeof(DecorFaceStyle)); DFS_FACE_TYPE(tail->next->style) = VectorButton; next = head->next; head->next = NULL; FreeDecorFace(dpy, head); memcpy(head, next, sizeof(DecorFace)); free(next); } for (i = bs_start + 1; i <= bs_end; ++i) { if (multiple && (i & use_mask) != set_mask) { continue; } head = &TB_STATE(*tb)[i]; tail = head; while (tail->next) { tail = tail->next; } tail->next = (DecorFace *)safemalloc( sizeof(DecorFace)); memset( &DFS_FLAGS(tail->next->style), 0, sizeof(DFS_FLAGS(tail->next->style))); DFS_FACE_TYPE(tail->next->style) = SimpleButton; tail->next->next = NULL; ReadDecorFace(spec, tail->next, button, False); if (DFS_FACE_TYPE(tail->next->style) == VectorButton && DFS_FACE_TYPE((&TB_STATE(*tb)[i])->style) == DefaultVectorButton) { /* override the default vector style */ memcpy( &tail->next->style, &head->style, sizeof(DecorFaceStyle)); DFS_FACE_TYPE(tail->next->style) = VectorButton; next = head->next; head->next = NULL; FreeDecorFace(dpy, head); memcpy(head, next, sizeof(DecorFace)); free(next); } } } else { FreeDecorFace(dpy, &TB_STATE(*tb)[bs_start]); memcpy( &(TB_STATE(*tb)[bs_start]), &tmpdf, sizeof(DecorFace)); for (i = bs_start + 1; i <= bs_end; ++i) { if (multiple && (i & use_mask) != set_mask) { continue; } ReadDecorFace( spec, &TB_STATE(*tb)[i], button, False); } } } if (pstyle) { free(spec); end++; end = SkipSpaces(end, NULL, 0); } return end; } /* Remove the given decor from all windows */ static void __remove_window_decors(F_CMD_ARGS, FvwmDecor *d) { const exec_context_t *exc2; exec_context_changes_t ecc; FvwmWindow *t; for (t = Scr.FvwmRoot.next; t; t = t->next) { if (t->decor == d) { /* remove the extra title height now because we delete * the current decor before calling ChangeDecor(). */ t->g.frame.height -= t->decor->title_height; t->decor = NULL; ecc.w.fw = t; ecc.w.wcontext = C_WINDOW; exc2 = exc_clone_context( exc, &ecc, ECC_FW | ECC_WCONTEXT); execute_function( cond_rc, exc2, "ChangeDecor Default", 0); exc_destroy_context(exc2); } } return; } static void do_title_style(F_CMD_ARGS, Bool do_add) { char *parm; char *prev; FvwmDecor *decor = Scr.cur_decor ? Scr.cur_decor : &Scr.DefaultDecor; Scr.flags.do_need_window_update = 1; decor->flags.has_changed = 1; decor->titlebar.flags.has_changed = 1; for (prev = action ; (parm = PeekToken(action, &action)); prev = action) { if (!do_add && StrEquals(parm,"centered")) { TB_JUSTIFICATION(decor->titlebar) = JUST_CENTER; } else if (!do_add && StrEquals(parm,"leftjustified")) { TB_JUSTIFICATION(decor->titlebar) = JUST_LEFT; } else if (!do_add && StrEquals(parm,"rightjustified")) { TB_JUSTIFICATION(decor->titlebar) = JUST_RIGHT; } else if (!do_add && StrEquals(parm,"height")) { int height = 0; int next = 0; if (!action || sscanf(action, "%d%n", &height, &next) <= 0 || height < MIN_FONT_HEIGHT || height > MAX_FONT_HEIGHT) { if (height != 0) { fvwm_msg(ERR, "do_title_style", "bad height argument (height" " must be from 5 to 256)"); height = 0; } } if (decor->title_height != height || decor->min_title_height != 0) { decor->title_height = height; decor->min_title_height = 0; decor->flags.has_title_height_changed = 1; } if (action) action += next; } else if (!do_add && StrEquals(parm,"MinHeight")) { int height = 0; int next = 0; if (!action || sscanf(action, "%d%n", &height, &next) <= 0 || height < MIN_FONT_HEIGHT || height > MAX_FONT_HEIGHT) { if (height < MIN_FONT_HEIGHT) height = MIN_FONT_HEIGHT; else if (height > MAX_FONT_HEIGHT) height = 0; } if (decor->min_title_height != height) { decor->title_height = 0; decor->min_title_height = height; decor->flags.has_title_height_changed = 1; } if (action) action += next; } else { action = ReadTitleButton( prev, &decor->titlebar, do_add, -1); } } return; } /* * * Reads a multi-pixmap titlebar config. (tril@igs.net) * */ static char *ReadMultiPixmapDecor(char *s, DecorFace *df) { static char *pm_names[TBMP_NUM_PIXMAPS+1] = { "Main", "LeftMain", "RightMain", "LeftButtons", "RightButtons", "UnderText", "LeftOfText", "RightOfText", "LeftEnd", "RightEnd", "Buttons", NULL }; FvwmPicture **pm; FvwmAcs *acs; Pixel *pixels; char *token; Bool stretched; Bool load_pixmap = False; int pm_id, i = 0; FvwmPictureAttributes fpa; df->style.face_type = MultiPixmap; df->u.mp.pixmaps = pm = (FvwmPicture**)safecalloc( TBMP_NUM_PIXMAPS, sizeof(FvwmPicture*)); df->u.mp.acs = acs = (FvwmAcs *)safemalloc(TBMP_NUM_PIXMAPS * sizeof(FvwmAcs)); df->u.mp.pixels = pixels = (Pixel *)safemalloc(TBMP_NUM_PIXMAPS * sizeof(Pixel)); for(i=0; i < TBMP_NUM_PIXMAPS; i++) { acs[i].cs = -1; acs[i].alpha_percent = 100; } s = GetNextTokenIndex(s, pm_names, 0, &pm_id); while (pm_id >= 0) { stretched = False; load_pixmap = False; s = DoPeekToken(s, &token, ",()", NULL, NULL); if (StrEquals(token, "stretched")) { stretched = True; s = DoPeekToken(s, &token, ",", NULL, NULL); } else if (StrEquals(token, "tiled")) { s = DoPeekToken(s, &token, ",", NULL, NULL); } if (!token) { break; } if (pm[pm_id] || acs[pm_id].cs >= 0 || (df->u.mp.solid_flags & (1 << pm_id))) { fvwm_msg(WARN, "ReadMultiPixmapDecor", "Ignoring: already-specified %s", pm_names[i]); continue; } if (stretched) { df->u.mp.stretch_flags |= (1 << pm_id); } if (strncasecmp (token, "Colorset", 8) == 0) { int val; char *tmp; tmp = DoPeekToken(s, &token, ",", NULL, NULL); if (!GetIntegerArguments(token, NULL, &val, 1) || val < 0) { fvwm_msg( ERR, "ReadMultiPixmapDecor", "Colorset should take one or two " "positive integers as argument"); } else { acs[pm_id].cs = val; alloc_colorset(val); s = tmp; tmp = DoPeekToken(s, &token, ",", NULL, NULL); if (GetIntegerArguments(token, NULL, &val, 1)) { acs[pm_id].alpha_percent = max(0, min(100,val)); s = tmp; } } } else if (strncasecmp(token, "TiledPixmap", 11) == 0) { s = DoPeekToken(s, &token, ",", NULL, NULL); load_pixmap = True; } else if (strncasecmp(token, "AdjustedPixmap", 14) == 0) { s = DoPeekToken(s, &token, ",", NULL, NULL); load_pixmap = True; df->u.mp.stretch_flags |= (1 << pm_id); } else if (strncasecmp(token, "Solid", 5) == 0) { s = DoPeekToken(s, &token, ",", NULL, NULL); if (token) { df->u.mp.pixels[pm_id] = GetColor(token); df->u.mp.solid_flags |= (1 << pm_id); } } else { load_pixmap = True; } if (load_pixmap && token) { fpa.mask = (Pdepth <= 8)? FPAM_DITHER:0; /* ? */ pm[pm_id] = PCacheFvwmPicture( dpy, Scr.NoFocusWin, NULL, token, fpa); if (!pm[pm_id]) { fvwm_msg(ERR, "ReadMultiPixmapDecor", "Pixmap '%s' could not be loaded", token); } } if (pm_id == TBMP_BUTTONS) { if (pm[TBMP_LEFT_BUTTONS]) { PDestroyFvwmPicture(dpy, pm[TBMP_LEFT_BUTTONS]); } if (pm[TBMP_RIGHT_BUTTONS]) { PDestroyFvwmPicture(dpy, pm[TBMP_RIGHT_BUTTONS]); } df->u.mp.stretch_flags &= ~(1 << TBMP_LEFT_BUTTONS); df->u.mp.stretch_flags &= ~(1 << TBMP_RIGHT_BUTTONS); df->u.mp.solid_flags &= ~(1 << TBMP_LEFT_BUTTONS); df->u.mp.solid_flags &= ~(1 << TBMP_RIGHT_BUTTONS); if (pm[TBMP_BUTTONS]) { pm[TBMP_LEFT_BUTTONS] = PCloneFvwmPicture(pm[TBMP_BUTTONS]); acs[TBMP_LEFT_BUTTONS].cs = -1; pm[TBMP_RIGHT_BUTTONS] = PCloneFvwmPicture(pm[TBMP_BUTTONS]); acs[TBMP_RIGHT_BUTTONS].cs = -1; } else { pm[TBMP_RIGHT_BUTTONS] = pm[TBMP_LEFT_BUTTONS] = NULL; acs[TBMP_RIGHT_BUTTONS].cs = acs[TBMP_LEFT_BUTTONS].cs = acs[TBMP_BUTTONS].cs; acs[TBMP_RIGHT_BUTTONS].alpha_percent = acs[TBMP_LEFT_BUTTONS].alpha_percent = acs[TBMP_BUTTONS].alpha_percent; pixels[TBMP_LEFT_BUTTONS] = pixels[TBMP_RIGHT_BUTTONS] = pixels[TBMP_BUTTONS]; } if (stretched) { df->u.mp.stretch_flags |= (1 << TBMP_LEFT_BUTTONS) | (1 << TBMP_RIGHT_BUTTONS); } if (df->u.mp.solid_flags & (1 << TBMP_BUTTONS)) { df->u.mp.solid_flags |= (1 << TBMP_LEFT_BUTTONS); df->u.mp.solid_flags |= (1 << TBMP_RIGHT_BUTTONS); } if (pm[TBMP_BUTTONS]) { PDestroyFvwmPicture(dpy, pm[TBMP_BUTTONS]); pm[TBMP_BUTTONS] = NULL; } acs[TBMP_BUTTONS].cs = -1; df->u.mp.solid_flags &= ~(1 << TBMP_BUTTONS); } s = SkipSpaces(s, NULL, 0); s = GetNextTokenIndex(s, pm_names, 0, &pm_id); } if (!(pm[TBMP_MAIN] || acs[TBMP_MAIN].cs >= 0 || (df->u.mp.solid_flags & TBMP_MAIN)) && !(pm[TBMP_LEFT_MAIN] || acs[TBMP_LEFT_MAIN].cs >= 0 || (df->u.mp.solid_flags & TBMP_LEFT_MAIN)) && !(pm[TBMP_RIGHT_MAIN] || acs[TBMP_RIGHT_MAIN].cs >= 0 || (df->u.mp.solid_flags & TBMP_RIGHT_MAIN))) { fvwm_msg(ERR, "ReadMultiPixmapDecor", "No Main pixmap/colorset/solid found for TitleStyle " "MultiPixmap (you must specify either Main, " "or both LeftMain and RightMain)"); for (i=0; i < TBMP_NUM_PIXMAPS; i++) { if (pm[i]) { PDestroyFvwmPicture(dpy, pm[i]); } else if (!!(df->u.mp.solid_flags & i)) { PictureFreeColors( dpy, Pcmap, &df->u.mp.pixels[i], 1, 0, False); } } free(pm); free(acs); free(pixels); return NULL; } return s; } /* * * DestroyFvwmDecor -- frees all memory assocated with an FvwmDecor * structure, but does not free the FvwmDecor itself * */ static void DestroyFvwmDecor(FvwmDecor *decor) { int i; /* reset to default button set (frees allocated mem) */ DestroyAllButtons(decor); for (i = 0; i < BS_MaxButtonState; ++i) { FreeDecorFace(dpy, &TB_STATE(decor->titlebar)[i]); } FreeDecorFace(dpy, &decor->BorderStyle.active); FreeDecorFace(dpy, &decor->BorderStyle.inactive); if (decor->tag) { free(decor->tag); decor->tag = NULL; } return; } static void SetLayerButtonFlag( int layer, int multi, int set, FvwmDecor *decor, TitleButton *tb) { int i; int start = 0; int add = 2; if (multi) { if (multi == 2) { start = 1; } else if (multi == 3) { add = 1; } for (i = start; i < NUMBER_OF_TITLE_BUTTONS; i += add) { if (set) { TB_FLAGS(decor->buttons[i]).has_layer = 1; TB_LAYER(decor->buttons[i]) = layer; } else { TB_FLAGS(decor->buttons[i]).has_layer = 0; } } } else { if (set) { TB_FLAGS(*tb).has_layer = 1; TB_LAYER(*tb) = layer; } else { TB_FLAGS(*tb).has_layer = 0; } } return; } /* * * Changes a button decoration style (changes by veliaa@rpi.edu) * */ static void SetMWMButtonFlag( mwm_flags flag, int multi, int set, FvwmDecor *decor, TitleButton *tb) { int i; int start = 0; int add = 2; if (multi) { if (multi == 2) { start = 1; } else if (multi == 3) { add = 1; } for (i = start; i < NUMBER_OF_TITLE_BUTTONS; i += add) { if (set) { TB_MWM_DECOR_FLAGS(decor->buttons[i]) |= flag; } else { TB_MWM_DECOR_FLAGS(decor->buttons[i]) &= ~flag; } } } else { if (set) { TB_MWM_DECOR_FLAGS(*tb) |= flag; } else { TB_MWM_DECOR_FLAGS(*tb) &= ~flag; } } return; } static void do_button_style(F_CMD_ARGS, Bool do_add) { int i; int multi = 0; int button = 0; int do_return; char *text = NULL; char *prev = NULL; char *parm = NULL; TitleButton *tb = NULL; FvwmDecor *decor = Scr.cur_decor ? Scr.cur_decor : &Scr.DefaultDecor; parm = PeekToken(action, &text); if (parm && isdigit(*parm)) { button = atoi(parm); button = BUTTON_INDEX(button); } if (parm == NULL || button >= NUMBER_OF_TITLE_BUTTONS || button < 0) { fvwm_msg( ERR, "ButtonStyle", "Bad button style (1) in line %s", action); return; } Scr.flags.do_need_window_update = 1; do_return = 0; if (!isdigit(*parm)) { if (StrEquals(parm,"left")) { multi = 1; /* affect all left buttons */ } else if (StrEquals(parm,"right")) { multi = 2; /* affect all right buttons */ } else if (StrEquals(parm,"all")) { multi = 3; /* affect all buttons */ } else { /* we're either resetting buttons or an invalid button * set was specified */ if (StrEquals(parm,"reset")) { ResetAllButtons(decor); } else { fvwm_msg( ERR, "ButtonStyle", "Bad button style (2) in line %s", action); } multi = 3; do_return = 1; } } /* mark button style and decor as changed */ decor->flags.has_changed = 1; if (multi == 0) { /* a single button was specified */ tb = &decor->buttons[button]; TB_FLAGS(*tb).has_changed = 1; } else { for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; ++i) { if (((multi & 1) && !(i & 1)) || ((multi & 2) && (i & 1))) { TB_FLAGS(decor->buttons[i]).has_changed = 1; } } } if (do_return == 1) { return; } for (prev = text; (parm = PeekToken(text, &text)); prev = text) { if (!do_add && strcmp(parm,"-") == 0) { char *tok; text = GetNextToken(text, &tok); while (tok) { int set = 1; char *old_tok = NULL; if (*tok == '!') { /* flag negate */ set = 0; old_tok = tok; tok++; } if (StrEquals(tok,"Clear")) { if (multi) { for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; ++i) { if (((multi & 1) && !(i & 1)) || ((multi & 2) && (i & 1))) { TB_JUSTIFICATION(decor->buttons[i]) = (set) ? JUST_CENTER : JUST_RIGHT; memset(&TB_FLAGS(decor->buttons[i]), (set) ? 0 : 0xff, sizeof(TB_FLAGS(decor->buttons[i]))); /* ? not very useful if set == 0 ? */ } } } else { TB_JUSTIFICATION(*tb) = (set) ? JUST_CENTER : JUST_RIGHT; memset(&TB_FLAGS(*tb), (set) ? 0 : 0xff, sizeof(TB_FLAGS(*tb))); /* ? not very useful if * set == 0 ? */ } } else if (StrEquals(tok, "MWMDecorMenu")) { SetMWMButtonFlag( MWM_DECOR_MENU, multi, set, decor, tb); } else if (StrEquals(tok, "MWMDecorMin")) { SetMWMButtonFlag( MWM_DECOR_MINIMIZE, multi, set, decor, tb); } else if (StrEquals(tok, "MWMDecorMax")) { SetMWMButtonFlag( MWM_DECOR_MAXIMIZE, multi, set, decor, tb); } else if (StrEquals(tok, "MWMDecorShade")) { SetMWMButtonFlag( MWM_DECOR_SHADE, multi, set, decor, tb); } else if (StrEquals(tok, "MWMDecorStick")) { SetMWMButtonFlag( MWM_DECOR_STICK, multi, set, decor, tb); } else if (StrEquals(tok, "MwmDecorLayer")) { int layer, got_number; char *ltok; text = GetNextToken(text, <ok); if (ltok) { got_number = (sscanf(ltok, "%d", &layer) == 1); free (ltok); } else { got_number = 0; } if (!ltok || !got_number) { fvwm_msg(ERR, "ButtonStyle", "could not read" " integer value for" " layer -- line: %s", text); } else { SetLayerButtonFlag( layer, multi, set, decor, tb); } } else { fvwm_msg(ERR, "ButtonStyle", "unknown title button flag" " %s -- line: %s", tok, text); } if (set) { free(tok); } else { free(old_tok); } text = GetNextToken(text, &tok); } break; } else { if (multi) { for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; ++i) { if (((multi & 1) && !(i & 1)) || ((multi & 2) && (i & 1))) { text = ReadTitleButton( prev, &decor->buttons[i], do_add, i); } } } else if (!(text = ReadTitleButton( prev, tb, do_add, button))) { break; } } } return; } static int update_decorface_colorset(DecorFace *df, int cset) { DecorFace *tdf; int has_changed = 0; for(tdf = df; tdf != NULL; tdf = tdf->next) { if (DFS_FACE_TYPE(tdf->style) == ColorsetButton && tdf->u.acs.cs == cset) { tdf->flags.has_changed = 1; has_changed = 1; } else if (DFS_FACE_TYPE(tdf->style) == MultiPixmap) { int i; for (i = 0; i < TBMP_NUM_PIXMAPS; i++) { if (tdf->u.mp.acs[i].cs == cset) { tdf->flags.has_changed = 1; has_changed = 1; } } } } return has_changed; } static int update_titlebutton_colorset(TitleButton *tb, int cset) { int i; int has_changed = 0; for(i = 0; i < BS_MaxButtonState; i++) { tb->state[i].flags.has_changed = update_decorface_colorset(&(tb->state[i]), cset); has_changed |= tb->state[i].flags.has_changed; } return has_changed; } static void update_decors_colorset(int cset) { int i; FvwmDecor *decor = &Scr.DefaultDecor; for(decor = &Scr.DefaultDecor; decor != NULL; decor = decor->next) { for(i = 0; i < NUMBER_OF_TITLE_BUTTONS; i++) { decor->flags.has_changed |= update_titlebutton_colorset( &(decor->buttons[i]), cset); } decor->flags.has_changed |= update_titlebutton_colorset( &(decor->titlebar), cset); decor->flags.has_changed |= update_decorface_colorset( &(decor->BorderStyle.active), cset); decor->flags.has_changed |= update_decorface_colorset( &(decor->BorderStyle.inactive), cset); if (decor->flags.has_changed) { Scr.flags.do_need_window_update = 1; } } } static Bool __parse_vector_line_one_coord( char **ret_action, int *pcoord, int *poff, char *action) { int offset; int n; *ret_action = action; n = sscanf(action, "%d%n", pcoord, &offset); if (n < 1) { return False; } action += offset; /* check for offest */ if (*action == '+' || *action == '-') { n = sscanf(action, "%dp%n", poff, &offset); if (n < 1) { return False; } if (*poff < -128) { *poff = -128; } else if (*poff > 127) { *poff = 127; } action += offset; } else { *poff = 0; } *ret_action = action; return True; } static Bool __parse_vector_line( char **ret_action, int *px, int *py, int *pxoff, int *pyoff, int *pc, char *action) { Bool is_valid = True; int offset; int n; *ret_action = action; if (__parse_vector_line_one_coord(&action, px, pxoff, action) == False) { return False; } if (*action != 'x') { return False; } action++; if (__parse_vector_line_one_coord(&action, py, pyoff, action) == False) { return False; } if (*action != '@') { return False; } action++; /* read the line style */ n = sscanf(action, "%d%n", pc, &offset); if (n < 1) { return False; } action += offset; *ret_action = action; return is_valid; } /* ---------------------------- interface functions ------------------------ */ void refresh_window(Window w, Bool window_update) { XSetWindowAttributes attributes; unsigned long valuemask; valuemask = CWOverrideRedirect | CWBackingStore | CWSaveUnder | CWBackPixmap; attributes.override_redirect = True; attributes.save_under = False; attributes.background_pixmap = None; attributes.backing_store = NotUseful; w = XCreateWindow( dpy, w, 0, 0, Scr.MyDisplayWidth, Scr.MyDisplayHeight, 0, CopyFromParent, CopyFromParent, CopyFromParent, valuemask, &attributes); XMapWindow(dpy, w); if (Scr.flags.do_need_window_update && window_update) { flush_window_updates(); } XDestroyWindow(dpy, w); XSync(dpy, 0); handle_all_expose(); return; } void ApplyDefaultFontAndColors(void) { XGCValues gcv; unsigned long gcm; int cset = Scr.DefaultColorset; /* make GC's */ gcm = GCFunction|GCLineWidth|GCForeground|GCBackground; gcv.function = GXcopy; if (Scr.DefaultFont->font) { gcm |= GCFont; gcv.font = Scr.DefaultFont->font->fid; } gcv.line_width = 0; if (cset >= 0) { gcv.foreground = Colorset[cset].fg; gcv.background = Colorset[cset].bg; } else { gcv.foreground = Scr.StdFore; gcv.background = Scr.StdBack; } if (Scr.StdGC) { XChangeGC(dpy, Scr.StdGC, gcm, &gcv); } else { Scr.StdGC = fvwmlib_XCreateGC(dpy, Scr.NoFocusWin, gcm, &gcv); } gcm = GCFunction|GCLineWidth|GCForeground; if (cset >= 0) { gcv.foreground = Colorset[cset].hilite; } else { gcv.foreground = Scr.StdHilite; } if (Scr.StdReliefGC) { XChangeGC(dpy, Scr.StdReliefGC, gcm, &gcv); } else { Scr.StdReliefGC = fvwmlib_XCreateGC( dpy, Scr.NoFocusWin, gcm, &gcv); } if (cset >= 0) { gcv.foreground = Colorset[cset].shadow; } else { gcv.foreground = Scr.StdShadow; } if (Scr.StdShadowGC) { XChangeGC(dpy, Scr.StdShadowGC, gcm, &gcv); } else { Scr.StdShadowGC = fvwmlib_XCreateGC( dpy, Scr.NoFocusWin, gcm, &gcv); } /* update the geometry window for move/resize */ if (Scr.SizeWindow != None) { resize_geometry_window(); } UpdateAllMenuStyles(); return; } void FreeDecorFace(Display *dpy, DecorFace *df) { int i; switch (DFS_FACE_TYPE(df->style)) { case GradientButton: if (df->u.grad.d_pixels != NULL && df->u.grad.d_npixels) { PictureFreeColors( dpy, Pcmap, df->u.grad.d_pixels, df->u.grad.d_npixels, 0, False); free(df->u.grad.d_pixels); } else if (Pdepth <= 8 && df->u.grad.xcs != NULL && df->u.grad.npixels > 0 && !df->u.grad.do_dither) { Pixel *p; int i; p = (Pixel *)safemalloc( df->u.grad.npixels * sizeof(Pixel)); for(i=0; i < df->u.grad.npixels; i++) { p[i] = df->u.grad.xcs[i].pixel; } PictureFreeColors( dpy, Pcmap, p, df->u.grad.npixels, 0, False); free(p); } if (df->u.grad.xcs != NULL) { free(df->u.grad.xcs); } break; case PixmapButton: case TiledPixmapButton: case StretchedPixmapButton: case AdjustedPixmapButton: case ShrunkPixmapButton: if (df->u.p) { PDestroyFvwmPicture(dpy, df->u.p); } break; case MultiPixmap: if (df->u.mp.pixmaps) { for (i = 0; i < TBMP_NUM_PIXMAPS; i++) { if (df->u.mp.pixmaps[i]) { PDestroyFvwmPicture( dpy, df->u.mp.pixmaps[i]); } else if (!!(df->u.mp.solid_flags & i)) { PictureFreeColors( dpy, Pcmap, &df->u.mp.pixels[i], 1, 0, False); } } free(df->u.mp.pixmaps); } if (df->u.mp.acs) { free(df->u.mp.acs); } if (df->u.mp.pixels) { free(df->u.mp.pixels); } break; case VectorButton: case DefaultVectorButton: if (df->u.vector.x) { free (df->u.vector.x); } if (df->u.vector.y) { free (df->u.vector.y); } /* free offsets for coord */ if (df->u.vector.xoff) { free(df->u.vector.xoff); } if (df->u.vector.yoff) { free(df->u.vector.yoff); } if (df->u.vector.c) { free (df->u.vector.c); } break; default: /* see below */ break; } /* delete any compound styles */ if (df->next) { FreeDecorFace(dpy, df->next); free(df->next); } df->next = NULL; memset(&df->style, 0, sizeof(df->style)); memset(&df->u, 0, sizeof(df->u)); DFS_FACE_TYPE(df->style) = SimpleButton; return; } /* * * Reads a button face line into a structure (veliaa@rpi.edu) * */ Bool ReadDecorFace(char *s, DecorFace *df, int button, int verbose) { int offset; char style[256], *file; char *action = s; /* some variants of scanf do not increase the assign count when %n is * used, so a return value of 1 is no error. */ if (sscanf(s, "%255s%n", style, &offset) < 1) { if (verbose) { fvwm_msg(ERR, "ReadDecorFace", "error in face `%s'", s); } return False; } style[255] = 0; if (strncasecmp(style, "--", 2) != 0) { s += offset; FreeDecorFace(dpy, df); /* determine button style */ if (strncasecmp(style,"Simple",6)==0) { memset(&df->style, 0, sizeof(df->style)); DFS_FACE_TYPE(df->style) = SimpleButton; } else if (strncasecmp(style,"Default",7)==0) { int b = -1, n = sscanf(s, "%d%n", &b, &offset); if (n < 1) { if (button == -1) { if (verbose) { fvwm_msg( ERR,"ReadDecorFace", "need default button" " number to load"); } return False; } b = button; } else { b = BUTTON_INDEX(b); s += offset; } if (b >= 0 && b < NUMBER_OF_TITLE_BUTTONS) { LoadDefaultButton(df, b); } else { if (verbose) { fvwm_msg( ERR, "ReadDecorFace", "button number out of range:" " %d", b); } return False; } } else if (strncasecmp(style,"Vector",6)==0 || (strlen(style)<=2 && isdigit(*style))) { /* normal coordinate list button style */ int i, num_coords, num; struct vector_coords *vc = &df->u.vector; /* get number of points */ if (strncasecmp(style,"Vector",6)==0) { num = sscanf(s,"%d%n",&num_coords,&offset); s += offset; } else { num = sscanf(style,"%d",&num_coords); } if (num < 1 || num_coords<2 || num_coords > MAX_TITLE_BUTTON_VECTOR_LINES) { if (verbose) { fvwm_msg( ERR, "ReadDecorFace", "Bad button style (2) in line:" " %s",action); } return False; } vc->num = num_coords; vc->use_fgbg = 0; vc->x = (signed char*)safemalloc(sizeof(char) * num_coords); vc->y = (signed char*)safemalloc(sizeof(char) * num_coords); vc->xoff = (signed char*)safemalloc(sizeof(char) * num_coords); vc->yoff = (signed char*)safemalloc(sizeof(char) * num_coords); vc->c = (signed char*)safemalloc(sizeof(char) * num_coords); /* get the points */ for (i = 0; i < vc->num; ++i) { int x; int y; int xoff = 0; int yoff = 0; int c; if (__parse_vector_line( &s, &x, &y, &xoff, &yoff, &c, s) == False) { break; } if (x < 0) { x = 0; } if (x > 100) { x = 100; } if (y < 0) { y = 0; } if (y > 100) { y = 100; } if (c < 0 || c > 4) { c = 4; } vc->x[i] = x; vc->y[i] = y; vc->c[i] = c; vc->xoff[i] = xoff; vc->yoff[i] = yoff; if (c == 2 || c == 3) { vc->use_fgbg = 1; } } if (i < vc->num) { if (verbose) { fvwm_msg( ERR, "ReadDecorFace", "Bad button style (3) in line" " %s", action); } free(vc->x); free(vc->y); free(vc->c); free(vc->xoff); free(vc->yoff); vc->x = NULL; vc->y = NULL; vc->c = NULL; vc->xoff = NULL; vc->yoff = NULL; return False; } memset(&df->style, 0, sizeof(df->style)); DFS_FACE_TYPE(df->style) = VectorButton; } else if (strncasecmp(style,"Solid",5)==0) { s = GetNextToken(s, &file); if (file) { memset(&df->style, 0, sizeof(df->style)); DFS_FACE_TYPE(df->style) = SolidButton; df->u.back = GetColor(file); free(file); } else { if (verbose) { fvwm_msg( ERR, "ReadDecorFace", "no color given for Solid" " face type: %s", action); } return False; } } else if (strncasecmp(style+1, "Gradient", 8)==0) { char **s_colors; int npixels, nsegs, *perc; XColor *xcs; Bool do_dither = False; if (!IsGradientTypeSupported(style[0])) { return False; } /* translate the gradient string into an array of * colors etc */ npixels = ParseGradient( s, &s, &s_colors, &perc, &nsegs); while (*s && isspace(*s)) { s++; } if (npixels <= 0) { return False; } /* grab the colors */ if (Pdepth <= 16) { do_dither = True; } xcs = AllocAllGradientColors( s_colors, perc, nsegs, npixels, do_dither); if (xcs == None) return False; df->u.grad.xcs = xcs; df->u.grad.npixels = npixels; df->u.grad.do_dither = do_dither; df->u.grad.d_pixels = NULL; memset(&df->style, 0, sizeof(df->style)); DFS_FACE_TYPE(df->style) = GradientButton; df->u.grad.gradient_type = toupper(style[0]); } else if (strncasecmp(style,"Pixmap",6)==0 || strncasecmp(style,"TiledPixmap",11)==0 || strncasecmp(style,"StretchedPixmap",15)==0 || strncasecmp(style,"AdjustedPixmap",14)==0 || strncasecmp(style,"ShrunkPixmap",12)==0) { FvwmPictureAttributes fpa; s = GetNextToken(s, &file); fpa.mask = (Pdepth <= 8)? FPAM_DITHER:0; /* ? */ df->u.p = PCacheFvwmPicture( dpy, Scr.NoFocusWin, NULL, file, fpa); if (df->u.p == NULL) { if (file) { if (verbose) { fvwm_msg( ERR, "ReadDecorFace", "couldn't load pixmap" " %s", file); } free(file); } return False; } if (file) { free(file); file = NULL; } memset(&df->style, 0, sizeof(df->style)); if (strncasecmp(style,"Tiled",5)==0) { DFS_FACE_TYPE(df->style) = TiledPixmapButton; } else if (strncasecmp(style,"Stretched",9)==0) { DFS_FACE_TYPE(df->style) = StretchedPixmapButton; } else if (strncasecmp(style,"Adjusted",8)==0) { DFS_FACE_TYPE(df->style) = AdjustedPixmapButton; } else if (strncasecmp(style,"Shrunk",6)==0) { DFS_FACE_TYPE(df->style) = ShrunkPixmapButton; } else { DFS_FACE_TYPE(df->style) = PixmapButton; } } else if (strncasecmp(style,"MultiPixmap",11)==0) { if (button != -1) { if (verbose) { fvwm_msg( ERR, "ReadDecorFace", "MultiPixmap is only valid" " for TitleStyle"); } return False; } s = ReadMultiPixmapDecor(s, df); if (!s) { return False; } } else if (FMiniIconsSupported && strncasecmp (style, "MiniIcon", 8) == 0) { memset(&df->style, 0, sizeof(df->style)); DFS_FACE_TYPE(df->style) = MiniIconButton; /* pixmap read in when the window is created */ df->u.p = NULL; } else if (strncasecmp (style, "Colorset", 8) == 0) { int val[2]; int n; n = GetIntegerArguments(s, NULL, val, 2); if (n == 0) { } memset(&df->style, 0, sizeof(df->style)); if (n > 0 && val[0] >= 0) { df->u.acs.cs = val[0]; alloc_colorset(val[0]); DFS_FACE_TYPE(df->style) = ColorsetButton; } df->u.acs.alpha_percent = 100; if (n > 1) { df->u.acs.alpha_percent = max(0, min(100,val[1])); } s = SkipNTokens(s, n); } else { if (verbose) { fvwm_msg( ERR, "ReadDecorFace", "unknown style %s: %s", style, action); } return False; } } /* Process button flags ("--" signals start of flags, it is also checked for above) */ s = GetNextToken(s, &file); if (file && (strcmp(file,"--")==0)) { char *tok; s = GetNextToken(s, &tok); while (tok && *tok) { int set = 1; char *old_tok = NULL; if (*tok == '!') { /* flag negate */ set = 0; old_tok = tok; tok++; } if (StrEquals(tok,"Clear")) { memset(&DFS_FLAGS(df->style), (set) ? 0 : 0xff, sizeof(DFS_FLAGS(df->style))); /* ? what is set == 0 good for ? */ } else if (StrEquals(tok,"Left")) { if (set) { DFS_H_JUSTIFICATION(df->style) = JUST_LEFT; } else { DFS_H_JUSTIFICATION(df->style) = JUST_RIGHT; } } else if (StrEquals(tok,"Right")) { if (set) { DFS_H_JUSTIFICATION(df->style) = JUST_RIGHT; } else { DFS_H_JUSTIFICATION(df->style) = JUST_LEFT; } } else if (StrEquals(tok,"Centered")) { DFS_H_JUSTIFICATION(df->style) = JUST_CENTER; DFS_V_JUSTIFICATION(df->style) = JUST_CENTER; } else if (StrEquals(tok,"Top")) { if (set) { DFS_V_JUSTIFICATION(df->style) = JUST_TOP; } else { DFS_V_JUSTIFICATION(df->style) = JUST_BOTTOM; } } else if (StrEquals(tok,"Bottom")) { if (set) { DFS_V_JUSTIFICATION(df->style) = JUST_BOTTOM; } else { DFS_V_JUSTIFICATION(df->style) = JUST_TOP; } } else if (StrEquals(tok,"Flat")) { if (set) { DFS_BUTTON_RELIEF(df->style) = DFS_BUTTON_IS_FLAT; } else if (DFS_BUTTON_RELIEF(df->style) == DFS_BUTTON_IS_FLAT) { DFS_BUTTON_RELIEF(df->style) = DFS_BUTTON_IS_UP; } } else if (StrEquals(tok,"Sunk")) { if (set) { DFS_BUTTON_RELIEF(df->style) = DFS_BUTTON_IS_SUNK; } else if (DFS_BUTTON_RELIEF(df->style) == DFS_BUTTON_IS_SUNK) { DFS_BUTTON_RELIEF(df->style) = DFS_BUTTON_IS_UP; } } else if (StrEquals(tok,"Raised")) { if (set) { DFS_BUTTON_RELIEF(df->style) = DFS_BUTTON_IS_UP; } else { DFS_BUTTON_RELIEF(df->style) = DFS_BUTTON_IS_SUNK; } } else if (StrEquals(tok,"UseTitleStyle")) { if (set) { DFS_USE_TITLE_STYLE(df->style) = 1; DFS_USE_BORDER_STYLE(df->style) = 0; } else DFS_USE_TITLE_STYLE(df->style) = 0; } else if (StrEquals(tok,"HiddenHandles")) { DFS_HAS_HIDDEN_HANDLES(df->style) = !!set; } else if (StrEquals(tok,"NoInset")) { DFS_HAS_NO_INSET(df->style) = !!set; } else if (StrEquals(tok,"UseBorderStyle")) { if (set) { DFS_USE_BORDER_STYLE(df->style) = 1; DFS_USE_TITLE_STYLE(df->style) = 0; } else { DFS_USE_BORDER_STYLE(df->style) = 0; } } else if (verbose) { fvwm_msg( ERR, "ReadDecorFace", "unknown button face flag '%s'" " -- line: %s", tok, action); } if (set) { free(tok); } else { free(old_tok); } s = GetNextToken(s, &tok); } } if (file) { free(file); } return True; } /* * * Diverts a style definition to an FvwmDecor structure (veliaa@rpi.edu) * */ void AddToDecor(F_CMD_ARGS, FvwmDecor *decor) { if (!action) { return; } while (*action && isspace((unsigned char)*action)) { ++action; } if (!*action) { return; } Scr.cur_decor = decor; execute_function(cond_rc, exc, action, 0); Scr.cur_decor = NULL; return; } /* * * InitFvwmDecor -- initializes an FvwmDecor structure to defaults * */ void InitFvwmDecor(FvwmDecor *decor) { int i; DecorFace tmpdf; /* zero out the structures */ memset(decor, 0, sizeof (FvwmDecor)); memset(&tmpdf, 0, sizeof(DecorFace)); /* initialize title-bar button styles */ DFS_FACE_TYPE(tmpdf.style) = SimpleButton; for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; ++i) { int j = 0; for (; j < BS_MaxButtonState; ++j) { TB_STATE(decor->buttons[i])[j] = tmpdf; } } /* reset to default button set */ ResetAllButtons(decor); /* initialize title-bar styles */ for (i = 0; i < BS_MaxButtonState; ++i) { DFS_FACE_TYPE( TB_STATE(decor->titlebar)[i].style) = SimpleButton; } /* initialize border texture styles */ DFS_FACE_TYPE(decor->BorderStyle.active.style) = SimpleButton; DFS_FACE_TYPE(decor->BorderStyle.inactive.style) = SimpleButton; return; } void reset_decor_changes(void) { FvwmDecor *decor; for (decor = &Scr.DefaultDecor; decor; decor = decor->next) { decor->flags.has_changed = 0; decor->flags.has_title_height_changed = 0; } /* todo: must reset individual change flags too */ return; } void update_fvwm_colorset(int cset) { if (cset == Scr.DefaultColorset) { Scr.flags.do_need_window_update = 1; Scr.flags.has_default_color_changed = 1; } UpdateMenuColorset(cset); update_style_colorset(cset); update_decors_colorset(cset); return; } /* ---------------------------- builtin commands --------------------------- */ void CMD_Beep(F_CMD_ARGS) { XBell(dpy, 0); return; } void CMD_Nop(F_CMD_ARGS) { return; } void CMD_EscapeFunc(F_CMD_ARGS) { return; } void CMD_CursorMove(F_CMD_ARGS) { int x = 0, y = 0; int val1, val2, val1_unit, val2_unit; int x_unit, y_unit; int virtual_x, virtual_y; int x_pages, y_pages; if (GetTwoArguments(action, &val1, &val2, &val1_unit, &val2_unit) != 2) { fvwm_msg(ERR, "movecursor", "CursorMove needs 2 arguments"); return; } if (FQueryPointer(dpy, Scr.Root, &JunkRoot, &JunkChild, &x, &y, &JunkX, &JunkY, &JunkMask) == False) { /* pointer is on a different screen */ return; } x_unit = val1 * val1_unit / 100; y_unit = val2 * val2_unit / 100; x += x_unit; y += y_unit; virtual_x = Scr.Vx; virtual_y = Scr.Vy; if (x >= 0) { x_pages = x / Scr.MyDisplayWidth; } else { x_pages = ((x + 1) / Scr.MyDisplayWidth) - 1; } virtual_x += x_pages * Scr.MyDisplayWidth; x -= x_pages * Scr.MyDisplayWidth; if (virtual_x < 0) { x += virtual_x; virtual_x = 0; } else if (virtual_x > Scr.VxMax) { x += virtual_x - Scr.VxMax; virtual_x = Scr.VxMax; } if (y >= 0) { y_pages = y / Scr.MyDisplayHeight; } else { y_pages = ((y + 1) / Scr.MyDisplayHeight) - 1; } virtual_y += y_pages * Scr.MyDisplayHeight; y -= y_pages * Scr.MyDisplayHeight; if (virtual_y < 0) { y += virtual_y; virtual_y = 0; } else if (virtual_y > Scr.VyMax) { y += virtual_y - Scr.VyMax; virtual_y = Scr.VyMax; } /* TA: (2010/12/19): Only move to the new page if scrolling is * enabled and the viewport is able to change based on where the * pointer is. */ if ((virtual_x != Scr.Vx && Scr.EdgeScrollX != 0) || (virtual_y != Scr.Vy && Scr.EdgeScrollY != 0)) { MoveViewport(virtual_x, virtual_y, True); } /* TA: (2010/12/19): If the cursor is about to enter a pan-window, or * is one, or the cursor's next step is to go beyond the page * boundary, stop the cursor from moving in that direction, *if* we've * disallowed edge scrolling. * * Whilst this stops the cursor short of the edge of the screen in a * given direction, this is the desired behaviour. */ if (Scr.EdgeScrollX == 0 && (x >= Scr.MyDisplayWidth || x + x_unit >= Scr.MyDisplayWidth)) return; if (Scr.EdgeScrollY == 0 && (y >= Scr.MyDisplayHeight || y + y_unit >= Scr.MyDisplayHeight)) return; FWarpPointerUpdateEvpos( exc->x.elast, dpy, None, Scr.Root, 0, 0, Scr.MyDisplayWidth, Scr.MyDisplayHeight, x, y); return; } void CMD_Delete(F_CMD_ARGS) { FvwmWindow * const fw = exc->w.fw; if (!is_function_allowed(F_DELETE, NULL, fw, RQORIG_PROGRAM_US, True)) { XBell(dpy, 0); return; } if (IS_TEAR_OFF_MENU(fw)) { /* 'soft' delete tear off menus. Note: we can't send the * message to the menu window directly because it was created * using a different display. The client message would never * be read from there. */ send_clientmessage( dpy, FW_W_PARENT(fw), _XA_WM_DELETE_WINDOW, CurrentTime); return; } if (WM_DELETES_WINDOW(fw)) { send_clientmessage( dpy, FW_W(fw), _XA_WM_DELETE_WINDOW, CurrentTime); return; } else { XBell(dpy, 0); } XFlush(dpy); return; } void CMD_Destroy(F_CMD_ARGS) { FvwmWindow * const fw = exc->w.fw; if (IS_TEAR_OFF_MENU(fw)) { CMD_Delete(F_PASS_ARGS); return; } if (!is_function_allowed(F_DESTROY, NULL, fw, True, True)) { XBell(dpy, 0); return; } if ( XGetGeometry( dpy, FW_W(fw), &JunkRoot, &JunkX, &JunkY, (unsigned int*)&JunkWidth, (unsigned int*)&JunkHeight, (unsigned int*)&JunkBW, (unsigned int*)&JunkDepth) != 0) { XKillClient(dpy, FW_W(fw)); } destroy_window(fw); XFlush(dpy); return; } void CMD_Close(F_CMD_ARGS) { FvwmWindow * const fw = exc->w.fw; if (IS_TEAR_OFF_MENU(fw)) { CMD_Delete(F_PASS_ARGS); return; } if (!is_function_allowed(F_CLOSE, NULL, fw, True, True)) { XBell(dpy, 0); return; } if (WM_DELETES_WINDOW(fw)) { send_clientmessage( dpy, FW_W(fw), _XA_WM_DELETE_WINDOW, CurrentTime); return; } if ( XGetGeometry( dpy, FW_W(fw), &JunkRoot, &JunkX, &JunkY, (unsigned int*)&JunkWidth, (unsigned int*)&JunkHeight, (unsigned int*)&JunkBW, (unsigned int*)&JunkDepth) != 0) { XKillClient(dpy, FW_W(fw)); } destroy_window(fw); XFlush(dpy); return; } void CMD_Restart(F_CMD_ARGS) { Done(1, action); return; } void CMD_ExecUseShell(F_CMD_ARGS) { char *arg=NULL; static char shell_set = 0; if (shell_set) { free(exec_shell_name); } shell_set = 1; action = GetNextToken(action,&arg); if (arg) /* specific shell was specified */ { exec_shell_name = arg; } else /* no arg, so use $SHELL -- not working??? */ { if (getenv("SHELL")) { exec_shell_name = safestrdup(getenv("SHELL")); } else { /* if $SHELL not set, use default */ exec_shell_name = safestrdup("/bin/sh"); } } } void CMD_Exec(F_CMD_ARGS) { char *cmd=NULL; /* if it doesn't already have an 'exec' as the first word, add that * to keep down number of procs started */ /* need to parse string better to do this right though, so not doing * this for now... */ #if 0 if (strncasecmp(action,"exec",4)!=0) { cmd = (char *)safemalloc(strlen(action)+6); strcpy(cmd,"exec "); strcat(cmd,action); } else #endif { cmd = safestrdup(action); } if (!cmd) { return; } /* Use to grab the pointer here, but the fork guarantees that * we wont be held up waiting for the function to finish, * so the pointer-gram just caused needless delay and flashing * on the screen */ /* Thought I'd try vfork and _exit() instead of regular fork(). * The man page says that its better. */ /* Not everyone has vfork! */ /* According to the man page, vfork should never be used at all. */ if (!(fork())) /* child process */ { /* This is for fixing a problem with rox filer */ int fd; fvmm_deinstall_signals(); fd = open("/dev/null", O_RDONLY, 0); dup2(fd,STDIN_FILENO); if (fd != STDIN_FILENO) close(fd); if (fvwm_setpgrp() == -1) { fvwm_msg(ERR, "exec_function", "setpgrp failed (%s)", strerror(errno)); exit(100); } if (execl(exec_shell_name, exec_shell_name, "-c", cmd, NULL) == -1) { fvwm_msg(ERR, "exec_function", "execl failed (%s)", strerror(errno)); exit(100); } } free(cmd); return; } void CMD_Refresh(F_CMD_ARGS) { refresh_window(Scr.Root, True); return; } void CMD_RefreshWindow(F_CMD_ARGS) { FvwmWindow * const fw = exc->w.fw; refresh_window( (exc->w.wcontext == C_ICON) ? FW_W_ICON_TITLE(fw) : FW_W_FRAME(fw), True); return; } void CMD_Wait(F_CMD_ARGS) { Bool done = False; Bool redefine_cursor = False; Bool is_ungrabbed; char *escape; Window nonewin = None; char *wait_string, *rest; FvwmWindow *t; /* try to get a single token */ rest = GetNextToken(action, &wait_string); if (wait_string) { while (*rest && isspace((unsigned char)*rest)) { rest++; } if (*rest) { int i; char *temp; /* nope, multiple tokens - try old syntax */ /* strip leading and trailing whitespace */ temp = action; while (*temp && isspace((unsigned char)*temp)) { temp++; } free(wait_string); wait_string = safestrdup(temp); for (i = strlen(wait_string) - 1; i >= 0 && isspace(wait_string[i]); i--) { wait_string[i] = 0; } } } else { wait_string = safestrdup(""); } is_ungrabbed = UngrabEm(GRAB_NORMAL); while (!done && !isTerminated) { XEvent e; if (BUSY_WAIT & Scr.BusyCursor) { XDefineCursor(dpy, Scr.Root, Scr.FvwmCursors[CRS_WAIT]); redefine_cursor = True; } if (My_XNextEvent(dpy, &e)) { dispatch_event(&e); if (XFindContext( dpy, e.xmap.window, FvwmContext, (caddr_t *)&t) == XCNOENT) { t = NULL; } if (e.type == MapNotify && e.xmap.event == Scr.Root) { if (!*wait_string) { done = True; } if (t && matchWildcards( wait_string, t->name.name) == True) { done = True; } else if (t && t->class.res_class && matchWildcards( wait_string, t->class.res_class) == True) { done = True; } else if (t && t->class.res_name && matchWildcards( wait_string, t->class.res_name) == True) { done = True; } } else if (e.type == KeyPress) { /* should I be using or w.fw>? * DV: t */ int context; XClassHint *class; char *name; context = GetContext(&t, t, &e, &nonewin); if (t != NULL) { class = &(t->class); name = t->name.name; } else { class = NULL; name = NULL; } escape = CheckBinding( Scr.AllBindings, STROKE_ARG(0) e.xkey.keycode, e.xkey.state, GetUnusedModifiers(), context, BIND_KEYPRESS, class, name); if (escape != NULL) { if (!strcasecmp(escape,"escapefunc")) { done = True; } } } } } if (redefine_cursor) { XDefineCursor(dpy, Scr.Root, Scr.FvwmCursors[CRS_ROOT]); } if (is_ungrabbed) { GrabEm(CRS_NONE, GRAB_NORMAL); } free(wait_string); return; } void CMD_Quit(F_CMD_ARGS) { if (master_pid != getpid()) { kill(master_pid, SIGTERM); } Done(0,NULL); return; } void CMD_QuitScreen(F_CMD_ARGS) { Done(0,NULL); return; } void CMD_Echo(F_CMD_ARGS) { int len; if (!action) { action = ""; } len = strlen(action); if (len != 0) { if (action[len-1]=='\n') { action[len-1]='\0'; } } fvwm_msg(ECHO, "Echo", "%s", action); return; } void CMD_PrintInfo(F_CMD_ARGS) { int verbose; char *rest, *subject = NULL; rest = GetNextToken(action, &subject); if (!rest || GetIntegerArguments(rest, NULL, &verbose, 1) != 1) { verbose = 0; } if (StrEquals(subject, "Colors")) { PicturePrintColorInfo(verbose); } else if (StrEquals(subject, "Locale")) { FlocalePrintLocaleInfo(dpy, verbose); } else if (StrEquals(subject, "NLS")) { FGettextPrintLocalePath(verbose); } else if (StrEquals(subject, "style")) { print_styles(verbose); } else if (StrEquals(subject, "ImageCache")) { PicturePrintImageCache(verbose); } else if (StrEquals(subject, "Bindings")) { print_bindings(); } else if (StrEquals(subject, "InfoStore")) { print_infostore(); } else { fvwm_msg(ERR, "PrintInfo", "Unknown subject '%s'", action); } if (subject) { free(subject); } return; } void CMD_ColormapFocus(F_CMD_ARGS) { if (MatchToken(action,"FollowsFocus")) { Scr.ColormapFocus = COLORMAP_FOLLOWS_FOCUS; } else if (MatchToken(action,"FollowsMouse")) { Scr.ColormapFocus = COLORMAP_FOLLOWS_MOUSE; } else { fvwm_msg(ERR, "SetColormapFocus", "ColormapFocus requires 1 arg: FollowsFocus or" " FollowsMouse"); return; } return; } void CMD_ClickTime(F_CMD_ARGS) { int val; if (GetIntegerArguments(action, NULL, &val, 1) != 1) { Scr.ClickTime = DEFAULT_CLICKTIME; } else { Scr.ClickTime = (val < 0)? 0 : val; } /* Use a negative value during startup and change sign afterwards. This * speeds things up quite a bit. */ if (fFvwmInStartup) { Scr.ClickTime = -Scr.ClickTime; } return; } void CMD_ImagePath(F_CMD_ARGS) { PictureSetImagePath( action ); return; } void CMD_IconPath(F_CMD_ARGS) { fvwm_msg(ERR, "iconPath_function", "IconPath is deprecated since 2.3.0; use ImagePath instead."); obsolete_imagepaths( action ); return; } void CMD_PixmapPath(F_CMD_ARGS) { fvwm_msg(ERR, "pixmapPath_function", "PixmapPath is deprecated since 2.3.0; use ImagePath" " instead." ); obsolete_imagepaths( action ); return; } void CMD_LocalePath(F_CMD_ARGS) { FGettextSetLocalePath( action ); return; } void CMD_ModulePath(F_CMD_ARGS) { static int need_to_free = 0; setPath( &ModulePath, action, need_to_free ); need_to_free = 1; return; } void CMD_ModuleTimeout(F_CMD_ARGS) { int timeout; moduleTimeout = DEFAULT_MODULE_TIMEOUT; if (GetIntegerArguments(action, NULL, &timeout, 1) == 1 && timeout > 0) { moduleTimeout = timeout; } return; } void CMD_HilightColor(F_CMD_ARGS) { char *fore; char *back; if (Scr.cur_decor && Scr.cur_decor != &Scr.DefaultDecor) { fvwm_msg( ERR, "SetHiColor", "Decors do not support the HilightColor command" " anymore. Please use" " 'Style HilightFore ' and" " 'Style HilightBack ' instead." " Sorry for the inconvenience."); return; } action = GetNextToken(action, &fore); GetNextToken(action, &back); if (fore && back) { action = safemalloc(strlen(fore) + strlen(back) + 29); sprintf(action, "* HilightFore %s, HilightBack %s", fore, back); CMD_Style(F_PASS_ARGS); } if (fore) { free(fore); } if (back) { free(back); } return; } void CMD_HilightColorset(F_CMD_ARGS) { char *newaction; if (Scr.cur_decor && Scr.cur_decor != &Scr.DefaultDecor) { fvwm_msg( ERR, "SetHiColorset", "Decors do not support the HilightColorset command " "anymore. Please use " "'Style HilightColorset '" " instead. Sorry for the inconvenience."); return; } if (action) { newaction = safemalloc(strlen(action) + 32); sprintf(newaction, "* HilightColorset %s", action); action = newaction; CMD_Style(F_PASS_ARGS); free(newaction); } return; } void CMD_TitleStyle(F_CMD_ARGS) { do_title_style(F_PASS_ARGS, False); return; } /* SetTitleStyle */ /* * * Appends a titlestyle (veliaa@rpi.edu) * */ void CMD_AddTitleStyle(F_CMD_ARGS) { do_title_style(F_PASS_ARGS, True); return; } void CMD_PropertyChange(F_CMD_ARGS) { char string[256]; char *token; char *rest; int ret; unsigned long argument; unsigned long data1; unsigned long data2; /* argument */ token = PeekToken(action, &rest); if (token == NULL) { return; } ret = sscanf(token, "%lu", &argument); if (ret < 1) { return; } /* data1 */ data1 = 0; token = PeekToken(rest, &rest); if (token != NULL) { ret = sscanf(token, "%lu", &data1); if (ret < 1) { rest = NULL; } } /* data2 */ data2 = 0; token = PeekToken(rest, &rest); if (token != NULL) { ret = sscanf(token, "%lu", &data2); if (ret < 1) { rest = NULL; } } /* string */ memset(string, 0, 256); if (rest != NULL) { ret = sscanf(rest, "%255c", &(string[0])); } BroadcastPropertyChange(argument, data1, data2, string); return; } void CMD_DefaultIcon(F_CMD_ARGS) { if (Scr.DefaultIcon) { free(Scr.DefaultIcon); } GetNextToken(action, &Scr.DefaultIcon); return; } void CMD_DefaultColorset(F_CMD_ARGS) { int cset; if (GetIntegerArguments(action, NULL, &cset, 1) != 1) { return; } Scr.DefaultColorset = cset; if (Scr.DefaultColorset < 0) { Scr.DefaultColorset = -1; } alloc_colorset(Scr.DefaultColorset); Scr.flags.do_need_window_update = 1; Scr.flags.has_default_color_changed = 1; return; } void CMD_DefaultColors(F_CMD_ARGS) { char *fore = NULL; char *back = NULL; action = GetNextToken(action, &fore); if (action) { action = GetNextToken(action, &back); } if (!back) { back = safestrdup(DEFAULT_BACK_COLOR); } if (!fore) { fore = safestrdup(DEFAULT_FORE_COLOR); } if (!StrEquals(fore, "-")) { PictureFreeColors(dpy, Pcmap, &Scr.StdFore, 1, 0, True); Scr.StdFore = GetColor(fore); } if (!StrEquals(back, "-")) { PictureFreeColors(dpy, Pcmap, &Scr.StdBack, 3, 0, True); Scr.StdBack = GetColor(back); Scr.StdHilite = GetHilite(Scr.StdBack); Scr.StdShadow = GetShadow(Scr.StdBack); } free(fore); free(back); Scr.DefaultColorset = -1; Scr.flags.do_need_window_update = 1; Scr.flags.has_default_color_changed = 1; return; } void CMD_DefaultFont(F_CMD_ARGS) { char *font; FlocaleFont *new_font; FvwmWindow *t; font = PeekToken(action, &action); if (!font) { /* Try 'fixed', pass NULL font name */ } if (!(new_font = FlocaleLoadFont(dpy, font, "fvwm"))) { if (Scr.DefaultFont == NULL) { exit(1); } else { return; } } FlocaleUnloadFont(dpy, Scr.DefaultFont); Scr.DefaultFont = new_font; /* we should do that here because a redraw can happen before flush_window_updates is called ... */ for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) { if (USING_DEFAULT_ICON_FONT(t)) { t->icon_font = Scr.DefaultFont; } if (USING_DEFAULT_WINDOW_FONT(t)) { t->title_font = Scr.DefaultFont; } } /* set flags to indicate that the font has changed */ Scr.flags.do_need_window_update = 1; Scr.flags.has_default_font_changed = 1; return; } void CMD_IconFont(F_CMD_ARGS) { char *newaction; if (Scr.cur_decor && Scr.cur_decor != &Scr.DefaultDecor) { fvwm_msg( ERR, "LoadIconFont", "Decors do not support the IconFont command anymore." " Please use 'Style IconFont '" " instead. Sorry for the inconvenience."); return; } if (action) { newaction = safemalloc(strlen(action) + 16); sprintf(newaction, "* IconFont %s", action); action = newaction; CMD_Style(F_PASS_ARGS); free(newaction); } return; } void CMD_WindowFont(F_CMD_ARGS) { char *newaction; if (Scr.cur_decor && Scr.cur_decor != &Scr.DefaultDecor) { fvwm_msg( ERR, "LoadWindowFont", "Decors do not support the WindowFont command anymore." " Please use 'Style Font '" " instead. Sorry for the inconvenience."); return; } if (action) { newaction = safemalloc(strlen(action) + 16); sprintf(newaction, "* Font %s", action); action = newaction; CMD_Style(F_PASS_ARGS); free(newaction); } return; } /* * * Changes the window's FvwmDecor pointer (veliaa@rpi.edu) * */ void CMD_ChangeDecor(F_CMD_ARGS) { char *item; FvwmDecor *decor = &Scr.DefaultDecor; FvwmDecor *found = NULL; FvwmWindow * const fw = exc->w.fw; item = PeekToken(action, &action); if (!action || !item) { return; } /* search for tag */ for (; decor; decor = decor->next) { if (decor->tag && StrEquals(item, decor->tag)) { found = decor; break; } } if (!found) { XBell(dpy, 0); return; } SET_DECOR_CHANGED(fw, 1); fw->decor = found; apply_decor_change(fw); return; } /* * * Destroys an FvwmDecor (veliaa@rpi.edu) * */ void CMD_DestroyDecor(F_CMD_ARGS) { char *item; FvwmDecor *decor = Scr.DefaultDecor.next; FvwmDecor *prev = &Scr.DefaultDecor, *found = NULL; Bool do_recreate = False; item = PeekToken(action, &action); if (!item) { return; } if (StrEquals(item, "recreate")) { do_recreate = True; item = PeekToken(action, NULL); } if (!item) { return; } /* search for tag */ for (; decor; decor = decor->next) { if (decor->tag && StrEquals(item, decor->tag)) { found = decor; break; } prev = decor; } if (found && (found != &Scr.DefaultDecor || do_recreate)) { if (!do_recreate) { __remove_window_decors(F_PASS_ARGS, found); } DestroyFvwmDecor(found); if (do_recreate) { int i; InitFvwmDecor(found); found->tag = safestrdup(item); Scr.flags.do_need_window_update = 1; found->flags.has_changed = 1; found->flags.has_title_height_changed = 0; found->titlebar.flags.has_changed = 1; for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; ++i) { TB_FLAGS(found->buttons[i]).has_changed = 1; } } else { prev->next = found->next; free(found); } } return; } /* * * Initiates an AddToDecor (veliaa@rpi.edu) * */ void CMD_AddToDecor(F_CMD_ARGS) { FvwmDecor *decor; FvwmDecor *found = NULL; char *item = NULL; action = GetNextToken(action, &item); if (!item) { return; } if (!action) { free(item); return; } /* search for tag */ for (decor = &Scr.DefaultDecor; decor; decor = decor->next) { if (decor->tag && StrEquals(item, decor->tag)) { found = decor; break; } } if (!found) { /* then make a new one */ found = (FvwmDecor *)safemalloc(sizeof( FvwmDecor )); InitFvwmDecor(found); found->tag = item; /* tag it */ /* add it to list */ for (decor = &Scr.DefaultDecor; decor->next; decor = decor->next) { /* nop */ } decor->next = found; } else { free(item); } if (found) { AddToDecor(F_PASS_ARGS, found); /* Set + state to last decor */ set_last_added_item(ADDED_DECOR, found); } return; } /* * * Updates window decoration styles (veliaa@rpi.edu) * */ void CMD_UpdateDecor(F_CMD_ARGS) { FvwmWindow *fw2; FvwmDecor *decor, *found = NULL; FvwmWindow *hilight = Scr.Hilite; char *item = NULL; action = GetNextToken(action, &item); if (item) { /* search for tag */ for (decor = &Scr.DefaultDecor; decor; decor = decor->next) { if (decor->tag && StrEquals(item, decor->tag)) { found = decor; break; } } free(item); } for (fw2 = Scr.FvwmRoot.next; fw2; fw2 = fw2->next) { /* update specific decor, or all */ if (found) { if (fw2->decor == found) { border_draw_decorations( fw2, PART_ALL, True, True, CLEAR_ALL, NULL, NULL); border_draw_decorations( fw2, PART_ALL, False, True, CLEAR_ALL, NULL, NULL); } } else { border_draw_decorations( fw2, PART_ALL, True, True, CLEAR_ALL, NULL, NULL); border_draw_decorations( fw2, PART_ALL, False, True, CLEAR_ALL, NULL, NULL); } } border_draw_decorations( hilight, PART_ALL, True, True, CLEAR_ALL, NULL, NULL); } void CMD_ButtonStyle(F_CMD_ARGS) { do_button_style(F_PASS_ARGS, False); return; } /* * * Appends a button decoration style (veliaa@rpi.edu) * */ void CMD_AddButtonStyle(F_CMD_ARGS) { do_button_style(F_PASS_ARGS, True); return; } void CMD_SetEnv(F_CMD_ARGS) { char *szVar = NULL; char *szValue = NULL; char *szPutenv = NULL; action = GetNextToken(action, &szVar); if (!szVar) { return; } action = GetNextToken(action, &szValue); if (!szValue) { szValue = safestrdup(""); } szPutenv = safemalloc(strlen(szVar) + strlen(szValue) + 2); sprintf(szPutenv,"%s=%s", szVar, szValue); flib_putenv(szVar, szPutenv); free(szVar); free(szPutenv); free(szValue); return; } void CMD_UnsetEnv(F_CMD_ARGS) { char *szVar = NULL; szVar = PeekToken(action, &action); if (!szVar) { return; } flib_unsetenv(szVar); return; } void CMD_GlobalOpts(F_CMD_ARGS) { char *opt; char *replace; char buf[64]; int i; Bool is_bugopt; char *optlist[] = { "WindowShadeShrinks", "WindowShadeScrolls", "SmartPlacementIsReallySmart", "SmartPlacementIsNormal", "ClickToFocusDoesntPassClick", "ClickToFocusPassesClick", "ClickToFocusDoesntRaise", "ClickToFocusRaises", "MouseFocusClickDoesntRaise", "MouseFocusClickRaises", "NoStipledTitles", "StipledTitles", "CaptureHonorsStartsOnPage", "CaptureIgnoresStartsOnPage", "RecaptureHonorsStartsOnPage", "RecaptureIgnoresStartsOnPage", "ActivePlacementHonorsStartsOnPage", "ActivePlacementIgnoresStartsOnPage", "RaiseOverNativeWindows", "IgnoreNativeWindows", NULL }; char *replacelist[] = { /* These options are mapped to the Style * command */ NULL, /* NULL means to use "Style * " */ NULL, "* MinOverlapPlacement", "* TileCascadePlacement", "* ClickToFocusPassesClickOff", "* ClickToFocusPassesClick", "* ClickToFocusRaisesOff", "* ClickToFocusRaises", "* MouseFocusClickRaisesOff", "* MouseFocusClickRaises", "* StippledTitleOff", "* StippledTitle", NULL, NULL, NULL, NULL, "* ManualPlacementHonorsStartsOnPage", "* ManualPlacementIgnoresStartsOnPage", /* These options are mapped to the BugOpts command */ "RaiseOverNativeWindows on", "RaiseOverNativeWindows off" }; fvwm_msg(ERR, "SetGlobalOptions", "The GlobalOpts command is obsolete."); for (action = GetNextSimpleOption(action, &opt); opt; action = GetNextSimpleOption(action, &opt)) { replace = NULL; is_bugopt = False; i = GetTokenIndex(opt, optlist, 0, NULL); if (i > -1) { char *cmd; char *tmp; replace = replacelist[i]; if (replace == NULL) { replace = &(buf[0]); sprintf(buf, "* %s", opt); } else if (*replace != '*') { is_bugopt = True; } tmp = action; action = replace; if (!is_bugopt) { CMD_Style(F_PASS_ARGS); cmd = "Style"; } else { CMD_BugOpts(F_PASS_ARGS); cmd = "BugOpts"; } action = tmp; fvwm_msg( ERR, "SetGlobalOptions", "Please replace 'GlobalOpts %s' with '%s %s'.", opt, cmd, replace); } else { fvwm_msg(ERR, "SetGlobalOptions", "Unknown Global Option '%s'", opt); } /* should never be null, but checking anyways... */ if (opt) { free(opt); } } if (opt) { free(opt); } return; } void CMD_BugOpts(F_CMD_ARGS) { char *opt; int toggle; char *optstring; /* fvwm_msg(DBG,"SetGlobalOptions","init action == '%s'\n",action); */ while (action && *action && *action != '\n') { action = GetNextFullOption(action, &optstring); if (!optstring) { /* no more options */ return; } toggle = ParseToggleArgument( SkipNTokens(optstring,1), NULL, 2, False); opt = PeekToken(optstring, NULL); free(optstring); if (!opt) { return; } /* toggle = ParseToggleArgument(rest, &rest, 2, False);*/ if (StrEquals(opt, "FlickeringMoveWorkaround")) { switch (toggle) { case -1: Scr.bo.do_disable_configure_notify ^= 1; break; case 0: case 1: Scr.bo.do_disable_configure_notify = toggle; break; default: Scr.bo.do_disable_configure_notify = 0; break; } } else if (StrEquals(opt, "MixedVisualWorkaround")) { switch (toggle) { case -1: Scr.bo.do_install_root_cmap ^= 1; break; case 0: case 1: Scr.bo.do_install_root_cmap = toggle; break; default: Scr.bo.do_install_root_cmap = 0; break; } } else if (StrEquals(opt, "ModalityIsEvil")) { switch (toggle) { case -1: Scr.bo.is_modality_evil ^= 1; break; case 0: case 1: Scr.bo.is_modality_evil = toggle; break; default: Scr.bo.is_modality_evil = 0; break; } if (Scr.bo.is_modality_evil) { SetMWM_INFO(Scr.NoFocusWin); } } else if (StrEquals(opt, "RaiseOverNativeWindows")) { switch (toggle) { case -1: Scr.bo.is_raise_hack_needed ^= 1; break; case 0: case 1: Scr.bo.is_raise_hack_needed = toggle; break; default: Scr.bo.is_raise_hack_needed = 0; break; } } else if (StrEquals(opt, "RaiseOverUnmanaged")) { switch (toggle) { case -1: Scr.bo.do_raise_over_unmanaged ^= 1; break; case 0: case 1: Scr.bo.do_raise_over_unmanaged = toggle; break; default: Scr.bo.do_raise_over_unmanaged = 0; break; } } else if (StrEquals(opt, "FlickeringQtDialogsWorkaround")) { switch (toggle) { case -1: Scr.bo.do_enable_flickering_qt_dialogs_workaround ^= 1; break; case 0: case 1: Scr.bo.do_enable_flickering_qt_dialogs_workaround = toggle; break; default: Scr.bo.do_enable_flickering_qt_dialogs_workaround = 0; break; } } else if (StrEquals(opt, "QtDragnDropWorkaround") ) { switch (toggle) { case -1: Scr.bo.do_enable_qt_drag_n_drop_workaround ^= 1; break; case 0: case 1: Scr.bo.do_enable_qt_drag_n_drop_workaround = toggle; break; default: Scr.bo.do_enable_qt_drag_n_drop_workaround = 0; break; } } else if (EWMH_BugOpts(opt, toggle)) { /* work is done in EWMH_BugOpts */ } else if (StrEquals(opt, "DisplayNewWindowNames")) { switch (toggle) { case -1: Scr.bo.do_display_new_window_names ^= 1; break; case 0: case 1: Scr.bo.do_display_new_window_names = toggle; break; default: Scr.bo.do_display_new_window_names = 0; break; } } else if (StrEquals(opt, "ExplainWindowPlacement")) { switch (toggle) { case -1: Scr.bo.do_explain_window_placement ^= 1; break; case 0: case 1: Scr.bo.do_explain_window_placement = toggle; break; default: Scr.bo.do_explain_window_placement = 0; break; } } else if (StrEquals(opt, "DebugCRMotionMethod")) { switch (toggle) { case -1: Scr.bo.do_debug_cr_motion_method ^= 1; break; case 0: case 1: Scr.bo.do_debug_cr_motion_method = toggle; break; default: Scr.bo.do_debug_cr_motion_method = 0; break; } } else if (StrEquals(opt, "TransliterateUtf8")) { FiconvSetTransliterateUtf8(toggle); } else { fvwm_msg(ERR, "SetBugOptions", "Unknown Bug Option '%s'", opt); } } return; } void CMD_Emulate(F_CMD_ARGS) { char *style; style = PeekToken(action, NULL); if (!style || StrEquals(style, "fvwm")) { Scr.gs.do_emulate_mwm = False; Scr.gs.do_emulate_win = False; } else if (StrEquals(style, "mwm")) { Scr.gs.do_emulate_mwm = True; Scr.gs.do_emulate_win = False; } else if (StrEquals(style, "win")) { Scr.gs.do_emulate_mwm = False; Scr.gs.do_emulate_win = True; } else { fvwm_msg(ERR, "Emulate", "Unknown style '%s'", style); return; } Scr.flags.do_need_window_update = 1; Scr.flags.has_default_font_changed = 1; Scr.flags.has_default_color_changed = 1; return; } void CMD_ColorLimit(F_CMD_ARGS) { fvwm_msg( WARN, "ColorLimit", "ColorLimit is obsolete,\n\tuse the " "fvwm -color-limit option"); return; } /* set animation parameters */ void CMD_SetAnimation(F_CMD_ARGS) { char *opt; int delay; float pct; int i = 0; opt = PeekToken(action, &action); if (!opt || sscanf(opt,"%d",&delay) != 1) { fvwm_msg(ERR,"SetAnimation", "Improper milli-second delay as first argument"); return; } if (delay > 500) { fvwm_msg(WARN,"SetAnimation", "Using longer than .5 seconds as between frame" " animation delay"); } cmsDelayDefault = delay; for (opt = PeekToken(action, &action); opt; opt = PeekToken(action, &action)) { if (sscanf(opt,"%f",&pct) != 1) { fvwm_msg(ERR,"SetAnimation", "Use fractional values ending in 1.0 as args" " 2 and on"); return; } rgpctMovementDefault[i++] = pct; } /* No pct entries means don't change them at all */ if (i > 0 && rgpctMovementDefault[i-1] != 1.0) { rgpctMovementDefault[i++] = 1.0; } return; } /* Determine which modifiers are required with a keycode to make . */ static Bool FKeysymToKeycode (Display *dpy, KeySym keysym, unsigned int *keycode, unsigned int *modifiers) { int m; *keycode = XKeysymToKeycode(dpy, keysym); *modifiers = 0; for (m = 0; m <= 8; ++m) { KeySym ks = fvwm_KeycodeToKeysym(dpy, *keycode, m, 0); if (ks == keysym) { switch (m) { case 0: /* No modifiers */ break; case 1: /* Shift modifier */ *modifiers |= ShiftMask; break; default: fvwm_msg(ERR, "FKeysymToKeycode", "Unhandled modifier %d", m); break; } return True; } } return False; } static void __fake_event(F_CMD_ARGS, FakeEventType type) { char *token; char *optlist[] = { "press", "p", "release", "r", "wait", "w", "modifiers", "m", "depth", "d", NULL }; unsigned int mask = 0; Window root = Scr.Root; int maxdepth = 0; static char args[128]; strncpy(args, action, sizeof(args) - 1); /* get the mask of pressed/released buttons/keys */ FQueryPointer( dpy, Scr.Root, &root, &JunkRoot, &JunkX, &JunkY, &JunkX, &JunkY, &mask); token = PeekToken(action, &action); while (token && action) { int index = GetTokenIndex(token, optlist, 0, NULL); int val, depth; XEvent e; Window w; Window child_w; int x = 0; int y = 0; int rx = 0; int ry = 0; Bool do_unset; long add_mask = 0; KeySym keysym = NoSymbol; XFlush(dpy); do_unset = True; switch (index) { case 0: case 1: do_unset = False; /* fall through */ case 2: case 3: /* key/button press or release */ if (type == FakeMouseEvent) { if ((GetIntegerArguments( action, &action, &val, 1) != 1) || val < 1 || val > NUMBER_OF_EXTENDED_MOUSE_BUTTONS) { fvwm_msg( ERR, "__fake_event", "Invalid button specifier in" " \"%s\" for FakeClick.", args); return; /* error */ } } else /* type == FakeKeyEvent */ { char *key = PeekToken(action, &action); if (key == NULL) { fvwm_msg( ERR, "__fake_event", "No keysym specifier in \"%s\"" " for FakeKeypress.", args); return; } /* Do *NOT* use FvwmStringToKeysym() as it is * case insensitive. */ keysym = XStringToKeysym(key); if (keysym == NoSymbol) { fvwm_msg( ERR, "__fake_event", "Invalid keysym specifier (%s)" " in \"%s\" for FakeKeypress.", key, args); return; } } w = None; child_w = root; for (depth = 1; depth != maxdepth && w != child_w && child_w != None; depth++) { w = child_w; if (FQueryPointer( dpy, w, &root, &child_w, &rx, &ry, &x, &y, &JunkMask) == False) { /* pointer is on a different * screen - that's okay here */ } } if (type == FakeMouseEvent) { e.type = (do_unset) ? ButtonRelease : ButtonPress; e.xbutton.display = dpy; e.xbutton.window = w; e.xbutton.subwindow = None; e.xbutton.root = root; e.xbutton.time = fev_get_evtime(); e.xbutton.x = x; e.xbutton.y = y; e.xbutton.x_root = rx; e.xbutton.y_root = ry; e.xbutton.button = val; e.xbutton.state = mask; e.xbutton.same_screen = (Scr.Root == root); /* SS: I think this mask handling code is * buggy. * The value of is overridden during a * "wait" operation. Also why are we only using * Button1Mask? What if the user has requested * a FakeClick using some other button? */ /* DV: Button1Mask is actually a bit. Shifting * it by (val -1) bits to the left gives * Button2Mask, Button3Mask etc. */ if (do_unset) { mask &= ~(Button1Mask << (val - 1)); } else { mask |= (Button1Mask << (val - 1)); } add_mask = (do_unset) ? ButtonPressMask : ButtonReleaseMask; } else { /* type == FakeKeyEvent */ e.type = (do_unset ? KeyRelease : KeyPress); e.xkey.display = dpy; e.xkey.subwindow = None; e.xkey.root = root; e.xkey.time = fev_get_evtime(); e.xkey.x = x; e.xkey.y = y; e.xkey.x_root = rx; e.xkey.y_root = ry; e.xkey.same_screen = (Scr.Root == root); w = e.xkey.window = exc->w.w; if (FKeysymToKeycode( dpy, keysym, &(e.xkey.keycode), &(e.xkey.state)) != True) { fvwm_msg(DBG, "__fake_event", "FKeysymToKeycode failed"); return; } e.xkey.state |= mask; add_mask = (do_unset) ? KeyReleaseMask : KeyPressMask; } FSendEvent(dpy, w, True, SubstructureNotifyMask | add_mask, &e); XFlush(dpy); break; case 4: case 5: /* wait */ if ((GetIntegerArguments( action, &action, &val, 1) != 1) || val <= 0 || val > 1000000) { fvwm_msg(ERR, "__fake_event", "Invalid wait value in \"%s\"", args); return; } usleep(1000 * val); if (FQueryPointer( dpy, Scr.Root, &root, &JunkRoot, &JunkX, &JunkY, &JunkX, &JunkY, &mask) == False) { /* pointer is on a different screen - * that's okay here */ } break; case 6: case 7: /* set modifier */ if (GetIntegerArguments(action, &action, &val, 1) != 1) { fvwm_msg( ERR, "__fake_event", "Invalid modifier value in \"%s\"", args); return; } do_unset = False; if (val < 0) { do_unset = True; val = -val; } if (val == 6) { val = ShiftMask; } else if (val == 7) { val = LockMask; } else if (val == 8) { val = ControlMask; } else if (val >=1 && val <= 5) { val = (Mod1Mask << (val - 1)); } else { /* error */ return; } /* SS: Could be buggy if a "modifier" operation * preceeds a "wait" operation. */ if (do_unset) { mask &= ~val; } else { mask |= val; } break; case 8: case 9: /* new max depth */ if (GetIntegerArguments(action, &action, &val, 1) != 1) { fvwm_msg(ERR, "__fake_event", "Invalid depth value in \"%s\"", args); return; } maxdepth = val; break; default: fvwm_msg(ERR, "__fake_event", "Invalid command (%s) in \"%s\"", token, args); return; } if (action) { token = PeekToken(action, &action); } } return; } void CMD_FakeClick(F_CMD_ARGS) { __fake_event(F_PASS_ARGS, FakeMouseEvent); return; } void CMD_FakeKeypress(F_CMD_ARGS) { __fake_event(F_PASS_ARGS, FakeKeyEvent); return; } /* A function to handle stroke (olicha Nov 11, 1999) */ #ifdef HAVE_STROKE void CMD_StrokeFunc(F_CMD_ARGS) { int finished = 0; int abort = 0; int modifiers = exc->x.etrigger->xbutton.state; int start_event_type = exc->x.etrigger->type; char sequence[STROKE_MAX_SEQUENCE + 1]; char *stroke_action, *name; char *opt = NULL; Bool finish_on_release = True; KeySym keysym; Bool restore_repeat = False; Bool echo_sequence = False; Bool draw_motion = False; int i = 0; int *x = NULL; int *y = NULL; const int STROKE_CHUNK_SIZE = 0xff; int coords_size = STROKE_CHUNK_SIZE; Window JunkRoot, JunkChild; int JunkX, JunkY; int tmpx, tmpy; unsigned int JunkMask; Bool feed_back = False; int stroke_width = 1; XEvent e; XClassHint *class; if (!GrabEm(CRS_STROKE, GRAB_NORMAL)) { XBell(dpy, 0); return; } x = (int*)safemalloc(coords_size * sizeof(int)); y = (int*)safemalloc(coords_size * sizeof(int)); e = *exc->x.etrigger; /* set the default option */ if (e.type == KeyPress || e.type == ButtonPress) { finish_on_release = True; } else { finish_on_release = False; } /* parse the option */ for (action = GetNextSimpleOption(action, &opt); opt; action = GetNextSimpleOption(action, &opt)) { if (StrEquals("NotStayPressed",opt)) { finish_on_release = False; } else if (StrEquals("EchoSequence",opt)) { echo_sequence = True; } else if (StrEquals("DrawMotion",opt)) { draw_motion = True; } else if (StrEquals("FeedBack",opt)) { feed_back = True; } else if (StrEquals("StrokeWidth",opt)) { /* stroke width takes a positive integer argument */ if (opt) { free(opt); } action = GetNextToken(action, &opt); if (!opt) { fvwm_msg( WARN, "StrokeWidth", "needs an integer argument"); } /* we allow stroke_width == 0 which means drawing a * `fast' line of width 1; the upper level of 100 is * arbitrary */ else if (!sscanf(opt, "%d", &stroke_width) || stroke_width < 0 || stroke_width > 100) { fvwm_msg( WARN, "StrokeWidth", "Bad integer argument %d", stroke_width); stroke_width = 1; } } else { fvwm_msg(WARN,"StrokeFunc","Unknown option %s", opt); } if (opt) { free(opt); } } if (opt) { free(opt); } /* Force auto repeat off and grab the Keyboard to get proper * KeyRelease events if we need it. * Some computers do not support KeyRelease events, can we * check this here ? No ? */ if (start_event_type == KeyPress && finish_on_release) { XKeyboardState kstate; XGetKeyboardControl(dpy, &kstate); if (kstate.global_auto_repeat == AutoRepeatModeOn) { XAutoRepeatOff(dpy); restore_repeat = True; } MyXGrabKeyboard(dpy); } /* be ready to get a stroke sequence */ stroke_init(); if (draw_motion) { MyXGrabServer(dpy); if (FQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, &x[0], &y[0], &JunkX, &JunkY, &JunkMask) == False) { /* pointer is on a different screen */ x[0] = 0; y[0] = 0; } XSetLineAttributes( dpy,Scr.XorGC,stroke_width,LineSolid,CapButt,JoinMiter); } while (!finished && !abort) { /* block until there is an event */ FMaskEvent( dpy, ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | ButtonMotionMask | PointerMotionMask, &e); switch (e.type) { case MotionNotify: if (e.xmotion.same_screen == False) { continue; } if (e.xany.window != Scr.Root) { if (FQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, &tmpx, &tmpy, &JunkX, &JunkY, &JunkMask) == False) { /* pointer is on a different screen */ tmpx = 0; tmpy = 0; } } else { tmpx = e.xmotion.x; tmpy = e.xmotion.y; } stroke_record(tmpx,tmpy); if (draw_motion && (x[i] != tmpx || y[i] != tmpy)) { i++; if (i >= coords_size) { coords_size += STROKE_CHUNK_SIZE; x = (int*)saferealloc( (void *)x, coords_size * sizeof(int)); y = (int*)saferealloc( (void *)y, coords_size * sizeof(int)); } x[i] = tmpx; y[i] = tmpy; XDrawLine( dpy, Scr.Root, Scr.XorGC, x[i-1], y[i-1], x[i], y[i]); } break; case ButtonRelease: if (finish_on_release && start_event_type == ButtonPress) { finished = 1; } break; case KeyRelease: if (finish_on_release && start_event_type == KeyPress) { finished = 1; } break; case KeyPress: keysym = XLookupKeysym(&e.xkey, 0); /* abort if Escape or Delete is pressed (as in menus.c) */ if (keysym == XK_Escape || keysym == XK_Delete || keysym == XK_KP_Separator) { abort = 1; } /* finish on enter or space (as in menus.c) */ if (keysym == XK_Return || keysym == XK_KP_Enter || keysym == XK_space) { finished = 1; } break; case ButtonPress: if (!finish_on_release) { finished = 1; } break; default: break; } } if (draw_motion) { while (i > 0) { XDrawLine( dpy, Scr.Root, Scr.XorGC, x[i-1], y[i-1], x[i], y[i]); i--; } XSetLineAttributes(dpy,Scr.XorGC,0,LineSolid,CapButt,JoinMiter); MyXUngrabServer(dpy); } if (x != NULL) { free(x); free(y); } if (start_event_type == KeyPress && finish_on_release) { MyXUngrabKeyboard(dpy); } UngrabEm(GRAB_NORMAL); if (restore_repeat) { XAutoRepeatOn(dpy); } /* get the stroke sequence */ stroke_trans(sequence); if (echo_sequence) { char num_seq[STROKE_MAX_SEQUENCE + 1]; for (i = 0; sequence[i] != '\0';i++) { /* Telephone to numeric pad */ if ('7' <= sequence[i] && sequence[i] <= '9') { num_seq[i] = sequence[i]-6; } else if ('1' <= sequence[i] && sequence[i] <= '3') { num_seq[i] = sequence[i]+6; } else { num_seq[i] = sequence[i]; } } num_seq[i++] = '\0'; fvwm_msg(INFO, "StrokeFunc", "stroke sequence: %s (N%s)", sequence, num_seq); } if (abort) { return; } if (exc->w.fw == NULL) { class = NULL; name = NULL; } else { class = &exc->w.fw->class; name = exc->w.fw->name.name; } /* check for a binding */ stroke_action = CheckBinding( Scr.AllBindings, sequence, 0, modifiers, GetUnusedModifiers(), exc->w.wcontext, BIND_STROKE, class, name); /* execute the action */ if (stroke_action != NULL) { const exec_context_t *exc2; exec_context_changes_t ecc; if (feed_back && atoi(sequence) != 0) { GrabEm(CRS_WAIT, GRAB_BUSY); usleep(200000); UngrabEm(GRAB_BUSY); } ecc.x.etrigger = &e; exc2 = exc_clone_context(exc, &ecc, ECC_ETRIGGER); execute_function(cond_rc, exc2, stroke_action, 0); exc_destroy_context(exc2); } return; } #endif /* HAVE_STROKE */ void CMD_State(F_CMD_ARGS) { unsigned int state; int toggle; int n; FvwmWindow * const fw = exc->w.fw; n = GetIntegerArguments(action, &action, (int *)&state, 1); if (n <= 0) { return; } if (state > 31) { fvwm_msg(ERR, "CMD_State", "Illegal state %d\n", state); return; } toggle = ParseToggleArgument(action, NULL, -1, 0); state = (1 << state); switch (toggle) { case -1: TOGGLE_USER_STATES(fw, state); break; case 0: CLEAR_USER_STATES(fw, state); break; case 1: default: SET_USER_STATES(fw, state); break; } return; } fvwm-2.7.0/fvwm/focus_policy.c0000644000175000017500000001232114147024700013237 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* Note: focus_policy.[ch] is meant to manage structures of type focus_policy_t * only. No code dealing with *any* external data types belongs in here! Put * it in focus.[ch] instead. */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include "focus_policy.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ /* ---------------------------- interface functions ------------------------ */ /* Initialise focus policy to the system defaults */ void fpol_init_default_fp(focus_policy_t *fp) { memset(fp, 0, sizeof(focus_policy_t)); FPS_FOCUS_ENTER(*fp, DEF_FP_FOCUS_ENTER); FPS_UNFOCUS_LEAVE(*fp, DEF_FP_UNFOCUS_LEAVE); FPS_FOCUS_CLICK_CLIENT(*fp, DEF_FP_FOCUS_CLICK_CLIENT); FPS_FOCUS_CLICK_DECOR(*fp, DEF_FP_FOCUS_CLICK_DECOR); FPS_FOCUS_BY_PROGRAM(*fp, DEF_FP_FOCUS_BY_PROGRAM); FPS_FOCUS_BY_FUNCTION(*fp, DEF_FP_FOCUS_BY_FUNCTION); FPS_WARP_POINTER_ON_FOCUS_FUNC(*fp, DEF_FP_WARP_POINTER_ON_FOCUS_FUNC); FPS_LENIENT(*fp, DEF_FP_LENIENT); FPS_RAISE_FOCUSED_CLIENT_CLICK(*fp, DEF_FP_RAISE_FOCUSED_CLIENT_CLICK); FPS_RAISE_UNFOCUSED_CLIENT_CLICK( *fp, DEF_FP_RAISE_UNFOCUSED_CLIENT_CLICK); FPS_RAISE_FOCUSED_DECOR_CLICK( *fp, DEF_FP_RAISE_FOCUSED_DECOR_CLICK); FPS_RAISE_UNFOCUSED_DECOR_CLICK( *fp, DEF_FP_RAISE_UNFOCUSED_DECOR_CLICK); FPS_RAISE_FOCUSED_ICON_CLICK( *fp, DEF_FP_RAISE_FOCUSED_ICON_CLICK); FPS_RAISE_UNFOCUSED_ICON_CLICK( *fp, DEF_FP_RAISE_UNFOCUSED_ICON_CLICK); FPS_MOUSE_BUTTONS(*fp, DEF_FP_MOUSE_BUTTONS); FPS_MODIFIERS(*fp, DEF_FP_MODIFIERS); FPS_PASS_FOCUS_CLICK(*fp, DEF_FP_PASS_FOCUS_CLICK); FPS_PASS_RAISE_CLICK(*fp, DEF_FP_PASS_RAISE_CLICK); FPS_IGNORE_FOCUS_CLICK_MOTION(*fp, DEF_FP_IGNORE_FOCUS_CLICK_MOTION); FPS_IGNORE_RAISE_CLICK_MOTION(*fp, DEF_FP_IGNORE_RAISE_CLICK_MOTION); FPS_ALLOW_FUNC_FOCUS_CLICK(*fp, DEF_FP_ALLOW_FUNC_FOCUS_CLICK); FPS_ALLOW_FUNC_RAISE_CLICK(*fp, DEF_FP_ALLOW_FUNC_RAISE_CLICK); FPS_GRAB_FOCUS(*fp, DEF_FP_GRAB_FOCUS); FPS_GRAB_FOCUS_TRANSIENT(*fp, DEF_FP_GRAB_FOCUS_TRANSIENT); FPS_OVERRIDE_GRAB_FOCUS(*fp, DEF_FP_OVERRIDE_GRAB_FOCUS); FPS_RELEASE_FOCUS(*fp, DEF_FP_RELEASE_FOCUS); FPS_RELEASE_FOCUS_TRANSIENT(*fp, DEF_FP_RELEASE_FOCUS_TRANSIENT); FPS_OVERRIDE_RELEASE_FOCUS(*fp, DEF_FP_OVERRIDE_RELEASE_FOCUS); FPS_SORT_WINDOWLIST_BY(*fp, DEF_FP_SORT_WINDOWLIST_BY); return; } int fpol_query_allow_set_focus( focus_policy_t *fpol, fpol_set_focus_by_t set_by_mode) { switch (set_by_mode) { case FOCUS_SET_BY_ENTER: return FP_DO_FOCUS_ENTER(*fpol); case FOCUS_SET_BY_CLICK_CLIENT: return FP_DO_FOCUS_CLICK_CLIENT(*fpol); case FOCUS_SET_BY_CLICK_DECOR: return FP_DO_FOCUS_CLICK_DECOR(*fpol); case FOCUS_SET_BY_CLICK_ICON: return FP_DO_FOCUS_CLICK_ICON(*fpol); case FOCUS_SET_BY_PROGRAM: return FP_DO_FOCUS_BY_PROGRAM(*fpol); case FOCUS_SET_BY_FUNCTION: return FP_DO_FOCUS_BY_FUNCTION(*fpol); case FOCUS_SET_FORCE: return 1; } return 0; } int fpol_query_allow_user_focus( focus_policy_t *fpol) { int flag = 0; flag |= FP_DO_FOCUS_ENTER(*fpol); flag |= FP_DO_FOCUS_CLICK_CLIENT(*fpol); flag |= FP_DO_FOCUS_CLICK_DECOR(*fpol); flag |= FP_DO_FOCUS_BY_FUNCTION(*fpol); return !!flag; } int fpol_is_policy_changed( focus_policy_t *fpol) { if (FP_DO_FOCUS_ENTER(*fpol)) { return 1; } if (FP_DO_UNFOCUS_LEAVE(*fpol)) { return 1; } if (FP_DO_FOCUS_CLICK_CLIENT(*fpol)) { return 1; } if (FP_DO_FOCUS_CLICK_DECOR(*fpol)) { return 1; } if (FP_DO_FOCUS_BY_PROGRAM(*fpol)) { return 1; } if (FP_DO_FOCUS_BY_FUNCTION(*fpol)) { return 1; } if (FP_IS_LENIENT(*fpol)) { return 1; } if (FP_DO_RAISE_FOCUSED_CLIENT_CLICK(*fpol)) { return 1; } if (FP_DO_RAISE_UNFOCUSED_CLIENT_CLICK(*fpol)) { return 1; } if (FP_DO_RAISE_FOCUSED_DECOR_CLICK(*fpol)) { return 1; } if (FP_DO_RAISE_UNFOCUSED_DECOR_CLICK(*fpol)) { return 1; } if (FP_USE_MOUSE_BUTTONS(*fpol)) { return 1; } if (FP_USE_MODIFIERS(*fpol)) { return 1; } return 0; } fvwm-2.7.0/fvwm/placement.c0000644000175000017500000016367114147024700012530 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include "libs/fvwmlib.h" #include "libs/FScreen.h" #include "libs/Grab.h" #include "libs/Parse.h" #include "libs/XResource.h" #include "fvwm.h" #include "externs.h" #include "execcontext.h" #include "cursor.h" #include "bindings.h" #include "misc.h" #include "screen.h" #include "placement.h" #include "geometry.h" #include "update.h" #include "style.h" #include "move_resize.h" #include "virtual.h" #include "stack.h" #include "ewmh.h" #include "icons.h" #include "add_window.h" /* ---------------------------- local definitions -------------------------- */ #define MAX_NUM_PLACEMENT_ALGOS 31 #define CP_GET_NEXT_STEP 5 /* ---------------------------- local macros ------------------------------- */ #ifndef MIN #define MIN(A,B) ((A)<(B)? (A):(B)) #endif #ifndef MAX #define MAX(A,B) ((A)>(B)? (A):(B)) #endif #define NORMAL_PLACEMENT_PENALTY(p) (p->normal) #define ONTOP_PLACEMENT_PENALTY(p) (p->ontop) #define ICON_PLACEMENT_PENALTY(p) (p->icon) #define STICKY_PLACEMENT_PENALTY(p) (p->sticky) #define BELOW_PLACEMENT_PENALTY(p) (p->below) #define EWMH_STRUT_PLACEMENT_PENALTY(p) (p->strut) #define PERCENTAGE_99_PENALTY(p) (p->p99) #define PERCENTAGE_95_PENALTY(p) (p->p95) #define PERCENTAGE_85_PENALTY(p) (p->p85) #define PERCENTAGE_75_PENALTY(p) (p->p75) /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ typedef enum { PR_POS_NORMAL = 0, PR_POS_IGNORE_PPOS, PR_POS_USE_PPOS, PR_POS_IGNORE_USPOS, PR_POS_USE_USPOS, PR_POS_PLACE_AGAIN, PR_POS_CAPTURE, PR_POS_USPOS_OVERRIDE_SOS } preason_pos_t; typedef enum { PR_SCREEN_CURRENT = 0, PR_SCREEN_STYLE, PR_SCREEN_X_RESOURCE_FVWMSCREEN, PR_SCREEN_IGNORE_CAPTURE } preason_screen_t; typedef enum { PR_PAGE_CURRENT = 0, PR_PAGE_STYLE, PR_PAGE_X_RESOURCE_PAGE, PR_PAGE_IGNORE_CAPTURE, PR_PAGE_IGNORE_INVALID, PR_PAGE_STICKY } preason_page_t; typedef enum { PR_DESK_CURRENT = 0, PR_DESK_STYLE, PR_DESK_X_RESOURCE_DESK, PR_DESK_X_RESOURCE_PAGE, PR_DESK_CAPTURE, PR_DESK_STICKY, PR_DESK_WINDOW_GROUP_LEADER, PR_DESK_WINDOW_GROUP_MEMBER, PR_DESK_TRANSIENT, PR_DESK_XPROP_XA_WM_DESKTOP } preason_desk_t; typedef struct { struct { preason_pos_t reason; int x; int y; int algo; char *pl_position_string; unsigned do_not_manual_icon_placement : 1; unsigned do_adjust_off_screen : 1; unsigned do_adjust_off_page : 1; unsigned is_pl_position_string_invalid : 1; unsigned has_tile_failed : 1; unsigned has_manual_failed : 1; unsigned has_placement_failed : 1; } pos; struct { preason_screen_t reason; int screen; rectangle g; unsigned was_modified_by_ewmh_workingarea : 1; } screen; struct { preason_page_t reason; int px; int py; unsigned do_switch_page : 1; unsigned do_honor_starts_on_page : 1; unsigned do_ignore_starts_on_page : 1; } page; struct { preason_desk_t reason; preason_desk_t sod_reason; int desk; unsigned do_switch_desk : 1; } desk; } pl_reason_t; typedef struct { int desk; int page_x; int page_y; int screen; } pl_start_style_t; typedef struct { unsigned do_forbid_manual_placement : 1; unsigned do_honor_starts_on_page : 1; unsigned do_honor_starts_on_screen : 1; unsigned do_not_use_wm_placement : 1; } pl_flags_t; typedef float pl_penalty_t; typedef enum { PL_LOOP_END, PL_LOOP_CONT } pl_loop_rc_t; struct pl_arg_t; struct pl_ret_t; typedef struct { /* If this funtion pointer is not NULL, use this function to return * the desired position in a single call */ pl_penalty_t (*get_pos_simple)( position *ret_p, struct pl_ret_t *ret, const struct pl_arg_t *arg); /* otherwise use these three in a loop */ pl_loop_rc_t (*get_first_pos)( position *ret_p, struct pl_ret_t *ret, const struct pl_arg_t *arg); pl_loop_rc_t (*get_next_pos)( position *ret_p, struct pl_ret_t *ret, const struct pl_arg_t *arg, position hint_p); pl_penalty_t (*get_pos_penalty)( position *ret_hint_p, struct pl_ret_t *ret, const struct pl_arg_t *arg); } pl_algo_t; typedef struct pl_scratch_t { const pl_penalty_struct *pp; const pl_percent_penalty_struct *ppp; } pl_scratch_t; typedef struct pl_arg_t { const pl_algo_t *algo; const exec_context_t *exc; const window_style *style; pl_reason_t *reason; FvwmWindow *place_fw; pl_scratch_t *scratch; rectangle place_g; position place_p2; rectangle screen_g; position page_p1; position page_p2; position pdelta_p; struct { unsigned use_percent : 1; unsigned use_ewmh_dynamic_working_areapercent : 1; unsigned do_honor_starts_on_page : 1; } flags; } pl_arg_t; typedef struct pl_ret_t { position best_p; pl_penalty_t best_penalty; struct { unsigned do_resize_too : 1; } flags; } pl_ret_t; /* ---------------------------- forward declarations ----------------------- */ static pl_loop_rc_t __pl_minoverlap_get_first_pos( position *ret_p, struct pl_ret_t *ret, const struct pl_arg_t *arg); static pl_loop_rc_t __pl_minoverlap_get_next_pos( position *ret_p, struct pl_ret_t *ret, const struct pl_arg_t *arg, position hint_p); static pl_penalty_t __pl_minoverlap_get_pos_penalty( position *ret_hint_p, struct pl_ret_t *ret, const pl_arg_t *arg); static pl_penalty_t __pl_smart_get_pos_penalty( position *ret_hint_p, struct pl_ret_t *ret, const pl_arg_t *arg); static pl_penalty_t __pl_position_get_pos_simple( position *ret_p, struct pl_ret_t *ret, const struct pl_arg_t *arg); static pl_penalty_t __pl_cascade_get_pos_simple( position *ret_p, struct pl_ret_t *ret, const struct pl_arg_t *arg); static pl_penalty_t __pl_manual_get_pos_simple( position *ret_p, struct pl_ret_t *ret, const struct pl_arg_t *arg); /* ---------------------------- local variables ---------------------------- */ const pl_algo_t minoverlap_placement_algo = { NULL, __pl_minoverlap_get_first_pos, __pl_minoverlap_get_next_pos, __pl_minoverlap_get_pos_penalty }; const pl_algo_t smart_placement_algo = { NULL, __pl_minoverlap_get_first_pos, __pl_minoverlap_get_next_pos, __pl_smart_get_pos_penalty }; const pl_algo_t position_placement_algo = { __pl_position_get_pos_simple }; const pl_algo_t cascade_placement_algo = { __pl_cascade_get_pos_simple }; const pl_algo_t manual_placement_algo = { __pl_manual_get_pos_simple }; /* ---------------------------- exported variables (globals) --------------- */ const pl_penalty_struct default_pl_penalty = { 1, PLACEMENT_AVOID_ONTOP, PLACEMENT_AVOID_ICON, PLACEMENT_AVOID_STICKY, PLACEMENT_AVOID_BELOW, PLACEMENT_AVOID_EWMH_STRUT }; const pl_percent_penalty_struct default_pl_percent_penalty = { PLACEMENT_AVOID_COVER_99, PLACEMENT_AVOID_COVER_95, PLACEMENT_AVOID_COVER_85, PLACEMENT_AVOID_COVER_75 }; /* ---------------------------- local functions (PositionPlacement) -------- */ static pl_penalty_t __pl_position_get_pos_simple( position *ret_p, struct pl_ret_t *ret, const struct pl_arg_t *arg) { char *spos; Bool fPointer; int n; int i; Bool is_under_mouse; is_under_mouse = False; spos = SGET_PLACEMENT_POSITION_STRING(*arg->style); if (spos == NULL || *spos == 0) { spos = DEFAULT_PLACEMENT_POSITION_STRING; i = 1; } else if (StrEquals(spos, "Center")) { spos = DEFAULT_PLACEMENT_POS_CENTER_STRING; i = 1; } else if (StrEquals(spos, "UnderMouse")) { spos = DEFAULT_PLACEMENT_POS_MOUSE_STRING; i = 1; is_under_mouse = True; } else { i = 0; } arg->reason->pos.pl_position_string = spos; for (n = -1; i < 2 && n < 2; i++) { fPointer = False; ret_p->x = 0; ret_p->y = 0; n = GetMoveArguments( &spos, arg->place_g.width, arg->place_g.height, &ret_p->x, &ret_p->y, NULL, &fPointer, False); spos = DEFAULT_PLACEMENT_POSITION_STRING; if (n < 2) { arg->reason->pos.is_pl_position_string_invalid = 1; } } if (n < 2) { /* bug */ abort(); } if (is_under_mouse) { /* TA: 20090218: Try and keep the window on-screen if we * can. */ /* TA: 20120316: Imply the working-area when under the mouse -- this * brings it in-line with making the EWMH working area the default. * Note that "UnderMouse" is a special case, deliberately. All other * PositionPlacement commands are deliberately NOT subject to ewmhiwa * options. */ EWMH_GetWorkAreaIntersection( arg->place_fw, (int *)&arg->screen_g.x, (int *)&arg->screen_g.y, (int *)&arg->screen_g.width, (int *)&arg->screen_g.height, EWMH_USE_WORKING_AREA); if (ret_p->x + arg->place_fw->g.frame.width > arg->screen_g.x + arg->screen_g.width) { ret_p->x = (arg->screen_g.x + arg->screen_g.width) - arg->place_fw->g.frame.width; } if (ret_p->y + arg->place_fw->g.frame.height > arg->screen_g.y + arg->screen_g.height) { ret_p->y = (arg->screen_g.y + arg->screen_g.height) - arg->place_fw->g.frame.height; } } /* Don't let the upper left corner be offscreen. */ if (ret_p->x < arg->screen_g.x) { ret_p->x = arg->screen_g.x; } if (ret_p->y < arg->screen_g.y) { ret_p->y = arg->screen_g.y; } if (arg->flags.do_honor_starts_on_page) { ret_p->x -= arg->pdelta_p.x; ret_p->y -= arg->pdelta_p.y; } return 0; } /* ---------------------------- local functions (CascadePlacement)---------- */ static pl_penalty_t __pl_cascade_get_pos_simple( position *ret_p, struct pl_ret_t *ret, const struct pl_arg_t *arg) { size_borders b; int w; FvwmWindow *t; t = (Scr.cascade_window != NULL) ? Scr.cascade_window : arg->place_fw; w = t->title_thickness; if (w == 0) { w = t->boundary_width; } if (w == 0) { w = PLACEMENT_FALLBACK_CASCADE_STEP; } if (Scr.cascade_window != NULL) { Scr.cascade_x += w; Scr.cascade_y += w; switch (GET_TITLE_DIR(t)) { case DIR_S: case DIR_N: Scr.cascade_y += w; break; case DIR_E: case DIR_W: Scr.cascade_x += w; break; default: break; } } Scr.cascade_window = arg->place_fw; if (Scr.cascade_x > arg->screen_g.width / 2) { Scr.cascade_x = arg->place_fw->title_thickness; } if (Scr.cascade_y > arg->screen_g.height / 2) { Scr.cascade_y = 2 * arg->place_fw->title_thickness; } ret_p->x = Scr.cascade_x + arg->page_p1.x; ret_p->y = Scr.cascade_y + arg->page_p1.y; /* try to keep the window on the screen */ get_window_borders(arg->place_fw, &b); if (ret_p->x + arg->place_g.width >= arg->page_p2.x) { ret_p->x = arg->page_p2.x - arg->place_g.width - b.total_size.width; Scr.cascade_x = arg->place_fw->title_thickness; switch (GET_TITLE_DIR(t)) { case DIR_E: case DIR_W: Scr.cascade_x += arg->place_fw->title_thickness; default: break; } } if (ret_p->y + arg->place_g.height >= arg->page_p2.y) { ret_p->y = arg->page_p2.y - arg->place_g.height - b.total_size.height; Scr.cascade_y = arg->place_fw->title_thickness; switch (GET_TITLE_DIR(t)) { case DIR_N: case DIR_S: Scr.cascade_y += arg->place_fw->title_thickness; default: break; } } /* the left and top sides are more important in huge windows */ if (ret_p->x < arg->page_p1.x) { ret_p->x = arg->page_p1.x; } if (ret_p->y < arg->page_p1.y) { ret_p->y = arg->page_p1.y; } return 0; } /* ---------------------------- local functions (ManualPlacement)----------- */ static pl_penalty_t __pl_manual_get_pos_simple( position *ret_p, struct pl_ret_t *ret, const struct pl_arg_t *arg) { ret_p->x = 0; ret_p->y = 0; if (GrabEm(CRS_POSITION, GRAB_NORMAL)) { int DragWidth; int DragHeight; int mx; int my; /* Grabbed the pointer - continue */ MyXGrabServer(dpy); if ( XGetGeometry( dpy, FW_W(arg->place_fw), &JunkRoot, &JunkX, &JunkY, (unsigned int*)&DragWidth, (unsigned int*)&DragHeight, (unsigned int*)&JunkBW, (unsigned int*)&JunkDepth) == 0) { MyXUngrabServer(dpy); UngrabEm(GRAB_NORMAL); return -1; } SET_PLACED_BY_FVWM(arg->place_fw, 0); MyXGrabKeyboard(dpy); DragWidth = arg->place_g.width; DragHeight = arg->place_g.height; if (Scr.SizeWindow != None) { XMapRaised(dpy, Scr.SizeWindow); } FScreenGetScrRect( NULL, FSCREEN_GLOBAL, &mx, &my, NULL, NULL); if (__move_loop( arg->exc, mx, my, DragWidth, DragHeight, &ret_p->x, &ret_p->y, False, CRS_POSITION)) { ret->flags.do_resize_too = 1; } if (Scr.SizeWindow != None) { XUnmapWindow(dpy, Scr.SizeWindow); } MyXUngrabKeyboard(dpy); MyXUngrabServer(dpy); UngrabEm(GRAB_NORMAL); } else { /* couldn't grab the pointer - better do something */ XBell(dpy, 0); ret_p->x = 0; ret_p->y = 0; arg->reason->pos.has_manual_failed = 1; } if (arg->flags.do_honor_starts_on_page) { ret_p->x -= arg->pdelta_p.x; ret_p->y -= arg->pdelta_p.y; } return 0; } /* ---------------------------- local functions (MinoverlapPlacement) ------ */ /* MinoverlapPlacement by Anthony Martin * This algorithm places a new window such that there is a minimum amount of * interference with other windows. If it can place a window without any * interference, fine. Otherwise, it places it so that the area of of * interference between the new window and the other windows is minimized */ static int __pl_minoverlap_get_next_x(const pl_arg_t *arg) { FvwmWindow *other_fw; int xnew; int xtest; int stickyx; int stickyy; int start,i; int win_left; rectangle g; Bool rc; int x; int y; x = arg->place_g.x; y = arg->place_g.y; if (arg->flags.use_percent == 1) { start = 0; } else { start = CP_GET_NEXT_STEP; } /* Test window at far right of screen */ xnew = arg->page_p2.x; xtest = arg->page_p2.x - arg->place_g.width; if (xtest > x) { xnew = xtest; } /* test the borders of the working area */ xtest = arg->page_p1.x + Scr.Desktops->ewmh_working_area.x; if (xtest > x) { xnew = MIN(xnew, xtest); } xtest = arg->page_p1.x + (Scr.Desktops->ewmh_working_area.x + Scr.Desktops->ewmh_working_area.width) - arg->place_g.width; if (xtest > x) { xnew = MIN(xnew, xtest); } /* Test the values of the right edges of every window */ for ( other_fw = Scr.FvwmRoot.next; other_fw != NULL; other_fw = other_fw->next) { if ( other_fw == arg->place_fw || (other_fw->Desk != arg->place_fw->Desk && !IS_STICKY_ACROSS_DESKS(other_fw)) || IS_EWMH_DESKTOP(FW_W(other_fw))) { continue; } if (IS_STICKY_ACROSS_PAGES(other_fw)) { stickyx = arg->pdelta_p.x; stickyy = arg->pdelta_p.y; } else { stickyx = 0; stickyy = 0; } if (IS_ICONIFIED(other_fw)) { rc = get_visible_icon_geometry(other_fw, &g); if (rc == True && y < g.y + g.height - stickyy && g.y - stickyy < arg->place_g.height + y) { win_left = arg->page_p1.x + g.x - stickyx - arg->place_g.width; for (i = start; i <= CP_GET_NEXT_STEP; i++) { xtest = win_left + g.width * (CP_GET_NEXT_STEP - i) / CP_GET_NEXT_STEP; if (xtest > x) { xnew = MIN(xnew, xtest); } } win_left = arg->page_p1.x + g.x - stickyx; for (i = start; i <= CP_GET_NEXT_STEP; i++) { xtest = (win_left) + g.width * i / CP_GET_NEXT_STEP; if (xtest > x) { xnew = MIN(xnew, xtest); } } } } else if ( y < other_fw->g.frame.height + other_fw->g.frame.y - stickyy && other_fw->g.frame.y - stickyy < arg->place_g.height + y && arg->page_p1.x < other_fw->g.frame.width + other_fw->g.frame.x - stickyx && other_fw->g.frame.x - stickyx < arg->page_p2.x) { win_left = other_fw->g.frame.x - stickyx - arg->place_g.width; for (i = start; i <= CP_GET_NEXT_STEP; i++) { xtest = win_left + other_fw->g.frame.width * (CP_GET_NEXT_STEP - i) / CP_GET_NEXT_STEP; if (xtest > x) { xnew = MIN(xnew, xtest); } } win_left = other_fw->g.frame.x - stickyx; for (i = start; i <= CP_GET_NEXT_STEP; i++) { xtest = win_left + other_fw->g.frame.width * i / CP_GET_NEXT_STEP; if (xtest > x) { xnew = MIN(xnew, xtest); } } } } return xnew; } static int __pl_minoverlap_get_next_y(const pl_arg_t *arg) { FvwmWindow *other_fw; int ynew; int ytest; int stickyy; int win_top; int start; int i; rectangle g; int y; y = arg->place_g.y; if (arg->flags.use_percent == 1) { start = 0; } else { start = CP_GET_NEXT_STEP; } /* Test window at far bottom of screen */ ynew = arg->page_p2.y; ytest = arg->page_p2.y - arg->place_g.height; if (ytest > y) { ynew = ytest; } /* test the borders of the working area */ ytest = arg->page_p1.y + Scr.Desktops->ewmh_working_area.y; if (ytest > y) { ynew = MIN(ynew, ytest); } ytest = arg->screen_g.y + (Scr.Desktops->ewmh_working_area.y + Scr.Desktops->ewmh_working_area.height) - arg->place_g.height; if (ytest > y) { ynew = MIN(ynew, ytest); } /* Test the values of the bottom edge of every window */ for ( other_fw = Scr.FvwmRoot.next; other_fw != NULL; other_fw = other_fw->next) { if ( other_fw == arg->place_fw || ( other_fw->Desk != arg->place_fw->Desk && !IS_STICKY_ACROSS_DESKS(other_fw)) || IS_EWMH_DESKTOP(FW_W(other_fw))) { continue; } if (IS_STICKY_ACROSS_PAGES(other_fw)) { stickyy = arg->pdelta_p.y; } else { stickyy = 0; } if (IS_ICONIFIED(other_fw)) { get_visible_icon_geometry(other_fw, &g); win_top = g.y - stickyy; for (i = start; i <= CP_GET_NEXT_STEP; i++) { ytest = win_top + g.height * i / CP_GET_NEXT_STEP; if (ytest > y) { ynew = MIN(ynew, ytest); } } win_top = g.y - stickyy - arg->place_g.height; for (i = start; i <= CP_GET_NEXT_STEP; i++) { ytest = win_top + g.height * (CP_GET_NEXT_STEP - i) / CP_GET_NEXT_STEP; if (ytest > y) { ynew = MIN(ynew, ytest); } } } else { win_top = other_fw->g.frame.y - stickyy; for (i = start; i <= CP_GET_NEXT_STEP; i++) { ytest = win_top + other_fw->g.frame.height * i / CP_GET_NEXT_STEP; if (ytest > y) { ynew = MIN(ynew, ytest); } } win_top = other_fw->g.frame.y - stickyy - arg->place_g.height; for (i = start; i <= CP_GET_NEXT_STEP; i++) { ytest = win_top + other_fw->g.frame.height * (CP_GET_NEXT_STEP - i) / CP_GET_NEXT_STEP; if (ytest > y) { ynew = MIN(ynew, ytest); } } } } return ynew; } static pl_loop_rc_t __pl_minoverlap_get_first_pos( position *ret_p, struct pl_ret_t *ret, const pl_arg_t *arg) { /* top left corner of page */ ret_p->x = arg->page_p1.x; ret_p->y = arg->page_p1.y; return PL_LOOP_CONT; } static pl_loop_rc_t __pl_minoverlap_get_next_pos( position *ret_p, struct pl_ret_t *ret, const struct pl_arg_t *arg, position hint_p) { ret_p->x = arg->place_g.x; ret_p->y = arg->place_g.y; if (ret_p->x + arg->place_g.width <= arg->page_p2.x) { /* try next x */ ret_p->x = __pl_minoverlap_get_next_x(arg); ret_p->y = arg->place_g.y; } if (ret_p->x + arg->place_g.width > arg->page_p2.x) { /* out of room in x direction. Try next y. Reset x.*/ ret_p->x = arg->page_p1.x; ret_p->y = __pl_minoverlap_get_next_y(arg); } if (ret_p->y + arg->place_g.height > arg->page_p2.y) { /* PageBottom */ return PL_LOOP_END; } return PL_LOOP_CONT; } static pl_penalty_t __pl_minoverlap_get_avoidance_penalty( const pl_arg_t *arg, FvwmWindow *other_fw, const rectangle *other_g) { pl_penalty_t anew; pl_penalty_t avoidance_factor; position other_p2; const pl_penalty_struct *opp; const pl_percent_penalty_struct *oppp; opp = (arg->scratch->pp != 0 && 0) ? arg->scratch->pp : &other_fw->pl_penalty; oppp = (arg->scratch->ppp != 0 && 0) ? arg->scratch->ppp : &other_fw->pl_percent_penalty; other_p2.x = other_g->x + other_g->width; other_p2.y = other_g->y + other_g->height; { long x1 = MAX(arg->place_g.x, other_g->x); long x2 = MIN(arg->place_p2.x, other_p2.x); long y1 = MAX(arg->place_g.y, other_g->y); long y2 = MIN(arg->place_p2.y, other_p2.y); /* overlapping area in pixels (windows are guaranteed to * overlap when this function is called) */ anew = (x2 - x1) * (y2 - y1); } if (IS_ICONIFIED(other_fw)) { avoidance_factor = ICON_PLACEMENT_PENALTY(opp); } else if (compare_window_layers(other_fw, arg->place_fw) > 0) { avoidance_factor = ONTOP_PLACEMENT_PENALTY(opp); } else if (compare_window_layers(other_fw, arg->place_fw) < 0) { avoidance_factor = BELOW_PLACEMENT_PENALTY(opp); } else if ( IS_STICKY_ACROSS_PAGES(other_fw) || IS_STICKY_ACROSS_DESKS(other_fw)) { avoidance_factor = STICKY_PLACEMENT_PENALTY(opp); } else { avoidance_factor = NORMAL_PLACEMENT_PENALTY(opp); } if (arg->flags.use_percent == 1) { pl_penalty_t cover_factor; long other_area; long place_area; other_area = other_g->width * other_g->height; place_area = arg->place_g.width * arg->place_g.height; cover_factor = 0; if (other_area != 0 && place_area != 0) { anew = 100 * MAX(anew / other_area, anew / place_area); if (anew >= 99) { cover_factor = PERCENTAGE_99_PENALTY(oppp); } else if (anew > 94) { cover_factor = PERCENTAGE_95_PENALTY(oppp); } else if (anew > 84) { cover_factor = PERCENTAGE_85_PENALTY(oppp); } else if (anew > 74) { cover_factor = PERCENTAGE_75_PENALTY(oppp); } } if (avoidance_factor >= 1) { avoidance_factor += cover_factor; } } if ( arg->flags.use_ewmh_dynamic_working_areapercent == 1 && DO_EWMH_IGNORE_STRUT_HINTS(other_fw) == 0 && ( other_fw->dyn_strut.left > 0 || other_fw->dyn_strut.right > 0 || other_fw->dyn_strut.top > 0 || other_fw->dyn_strut.bottom > 0)) { const pl_penalty_struct *mypp; mypp = (arg->scratch->pp != 0 && 0) ? arg->scratch->pp : &arg->place_fw->pl_penalty; /* if we intersect a window which reserves space */ avoidance_factor += (avoidance_factor >= 1) ? EWMH_STRUT_PLACEMENT_PENALTY(mypp) : 0; } anew *= avoidance_factor; return anew; } static pl_penalty_t __pl_minoverlap_get_pos_penalty( position *ret_hint_p, struct pl_ret_t *ret, const struct pl_arg_t *arg) { FvwmWindow *other_fw; pl_penalty_t penalty; size_borders b; penalty = 0; for ( other_fw = Scr.FvwmRoot.next; other_fw != NULL; other_fw = other_fw->next) { rectangle other_g; get_window_borders(other_fw, &b); if ( arg->place_fw == other_fw || IS_EWMH_DESKTOP(FW_W(other_fw))) { continue; } /* RBW - account for sticky windows... */ if ( other_fw->Desk != arg->place_fw->Desk && IS_STICKY_ACROSS_DESKS(other_fw) == 0) { continue; } (void)get_visible_window_or_icon_geometry(other_fw, &other_g); if (IS_STICKY_ACROSS_PAGES(other_fw)) { other_g.x -= arg->pdelta_p.x; other_g.y -= arg->pdelta_p.y; } if ( arg->place_g.x < other_g.x + other_g.width && arg->place_p2.x > other_g.x && arg->place_g.y < other_g.y + other_g.height && arg->place_p2.y > other_g.y) { pl_penalty_t anew; anew = __pl_minoverlap_get_avoidance_penalty( arg, other_fw, &other_g); penalty += anew; if ( penalty > ret->best_penalty && ret->best_penalty != -1) { /* TA: 20091230: Fix over-zealous penalties * by explicitly forcing the window on-screen * here. The y-axis is only affected here, * due to how the xoffset calculations happen * prior to setting the x-axis. When we get * penalties which are "over-zealous" -- and * by not taking into account the size of the * window borders, the window was being placed * off screen. */ if (ret->best_p.y + arg->place_g.height > arg->page_p2.y) { ret->best_p.y = (arg->page_p2.y - arg->place_g.height - b.total_size.height); ret->best_penalty = 0; penalty = 0; } /* stop looking; the penalty is too high */ return penalty; } } } /* now handle the working area */ { const pl_penalty_struct *mypp; mypp = (arg->scratch->pp != 0 && 0) ? arg->scratch->pp : &arg->place_fw->pl_penalty; if (arg->flags.use_ewmh_dynamic_working_areapercent == 1) { penalty += EWMH_STRUT_PLACEMENT_PENALTY(mypp) * EWMH_GetStrutIntersection( arg->place_g.x, arg->place_g.y, arg->place_p2.x, arg->place_p2.y, arg->flags.use_percent); } else { /* EWMH_USE_DYNAMIC_WORKING_AREA, count the base strut */ penalty += EWMH_STRUT_PLACEMENT_PENALTY(mypp) * EWMH_GetBaseStrutIntersection( arg->place_g.x, arg->place_g.y, arg->place_p2.x, arg->place_p2.y, arg->flags.use_percent); } } return penalty; } /* ---------------------------- local functions (SmartPlacement) ----------- */ static pl_penalty_t __pl_smart_get_pos_penalty( position *ret_hint_p, struct pl_ret_t *ret, const struct pl_arg_t *arg) { pl_penalty_t p; arg->scratch->pp = &default_pl_penalty; arg->scratch->ppp = &default_pl_percent_penalty; p = __pl_minoverlap_get_pos_penalty(ret_hint_p, ret, arg); if (p != 0) { p = -1; } return p; } /* ---------------------------- local functions ---------------------------- */ static int placement_loop(pl_ret_t *ret, pl_arg_t *arg) { position next_p; pl_penalty_t penalty; pl_loop_rc_t loop_rc; if (arg->algo->get_pos_simple != NULL) { position pos; penalty = arg->algo->get_pos_simple(&pos, ret, arg); arg->place_g.x = pos.x; arg->place_g.y = pos.y; ret->best_penalty = penalty; ret->best_p.x = pos.x; ret->best_p.y = pos.y; loop_rc = PL_LOOP_END; } else { loop_rc = arg->algo->get_first_pos(&next_p, ret, arg); arg->place_g.x = next_p.x; arg->place_g.y = next_p.y; ret->best_p.x = next_p.x; ret->best_p.y = next_p.y; } while (loop_rc != PL_LOOP_END) { position hint_p; pl_scratch_t scratch; memset(&scratch, 0, sizeof(scratch)); arg->scratch = &scratch; arg->place_p2.x = arg->place_g.x + arg->place_g.width; arg->place_p2.y = arg->place_g.y + arg->place_g.height; hint_p.x = arg->place_g.x; hint_p.y = arg->place_g.y; penalty = arg->algo->get_pos_penalty(&hint_p, ret, arg); /* I've added +0.0001 because with my machine the < test fail * with certain *equal* float numbers! */ if ( penalty >= 0 && ( ret->best_penalty < 0 || penalty + 0.0001 < ret->best_penalty)) { ret->best_p.x = arg->place_g.x; ret->best_p.y = arg->place_g.y; ret->best_penalty = penalty; } if (penalty == 0) { break; } loop_rc = arg->algo->get_next_pos(&next_p, ret, arg, hint_p); arg->place_g.x = next_p.x; arg->place_g.y = next_p.y; } if (ret->best_penalty < 0) { ret->best_penalty = -1; } return (ret->best_penalty == -1) ? -1 : 0; } static void __place_get_placement_flags( pl_flags_t *ret_flags, FvwmWindow *fw, window_style *pstyle, initial_window_options_t *win_opts, int mode, pl_reason_t *reason) { Bool override_ppos; Bool override_uspos; Bool has_ppos = False; Bool has_uspos = False; /* Windows use the position hint if these conditions are met: * * The program specified a USPosition hint and it is not overridden * with the No(Transient)USPosition style. * * OR * * The program specified a PPosition hint and it is not overridden * with the No(Transient)PPosition style. * * Windows without a position hint are placed using wm placement. */ if (IS_TRANSIENT(fw)) { override_ppos = SUSE_NO_TRANSIENT_PPOSITION(&pstyle->flags); override_uspos = SUSE_NO_TRANSIENT_USPOSITION(&pstyle->flags); } else { override_ppos = SUSE_NO_PPOSITION(&pstyle->flags); override_uspos = SUSE_NO_USPOSITION(&pstyle->flags); } if (fw->hints.flags & PPosition) { if (!override_ppos) { has_ppos = True; reason->pos.reason = PR_POS_USE_PPOS; } else { reason->pos.reason = PR_POS_IGNORE_PPOS; } } if (fw->hints.flags & USPosition) { if (!override_uspos) { has_uspos = True; reason->pos.reason = PR_POS_USE_USPOS; } else if (reason->pos.reason != PR_POS_USE_PPOS) { reason->pos.reason = PR_POS_IGNORE_USPOS; } } if (mode == PLACE_AGAIN) { ret_flags->do_not_use_wm_placement = 0; reason->pos.reason = PR_POS_PLACE_AGAIN; } else if (has_ppos || has_uspos) { ret_flags->do_not_use_wm_placement = 1; } else if (win_opts->flags.do_override_ppos) { ret_flags->do_not_use_wm_placement = 1; reason->pos.reason = PR_POS_CAPTURE; } else if (!ret_flags->do_honor_starts_on_page && fw->wmhints && (fw->wmhints->flags & StateHint) && fw->wmhints->initial_state == IconicState) { ret_flags->do_forbid_manual_placement = 1; reason->pos.do_not_manual_icon_placement = 1; } return; } static int __add_algo( const pl_algo_t **algos, int num_algos, const pl_algo_t *new_algo) { if (num_algos >= MAX_NUM_PLACEMENT_ALGOS) { return MAX_NUM_PLACEMENT_ALGOS; } algos[num_algos] = new_algo; num_algos++; return num_algos; } static int __place_get_wm_pos( const exec_context_t *exc, window_style *pstyle, rectangle *attr_g, pl_flags_t flags, rectangle screen_g, pl_start_style_t start_style, int mode, initial_window_options_t *win_opts, pl_reason_t *reason, int pdeltax, int pdeltay) { const pl_algo_t *algos[MAX_NUM_PLACEMENT_ALGOS + 1]; int num_algos; unsigned int placement_mode = SPLACEMENT_MODE(&pstyle->flags); pl_arg_t arg; pl_ret_t ret; int i; /* BEGIN init placement agrs and ret */ memset(&arg, 0, sizeof(arg)); arg.exc = exc; arg.style = pstyle; arg.reason = reason; arg.place_fw = exc->w.fw; arg.place_g = arg.place_fw->g.frame; arg.screen_g = screen_g; arg.page_p1.x = arg.screen_g.x - pdeltax; arg.page_p1.y = arg.screen_g.y - pdeltay; arg.page_p2.x = arg.page_p1.x + screen_g.width; arg.page_p2.y = arg.page_p1.y + screen_g.height; arg.pdelta_p.x = pdeltax; arg.pdelta_p.y = pdeltay; arg.flags.use_percent = 0; arg.flags.do_honor_starts_on_page = flags.do_honor_starts_on_page; if (SEWMH_PLACEMENT_MODE(&pstyle->flags) == EWMH_USE_WORKING_AREA) { arg.flags.use_ewmh_dynamic_working_areapercent = 1; } memset(&ret, 0, sizeof(ret)); ret.best_penalty = -1.0; /* END init placement agrs and ret */ /* override if manual placement happens */ SET_PLACED_BY_FVWM(arg.place_fw, 1); if (flags.do_forbid_manual_placement) { switch (placement_mode) { case PLACE_MANUAL: case PLACE_MANUAL_B: placement_mode = PLACE_CASCADE; break; case PLACE_TILEMANUAL: placement_mode = PLACE_TILECASCADE; break; default: break; } } reason->pos.algo = placement_mode; /* first, try various "smart" placement */ num_algos = 0; switch (placement_mode) { case PLACE_POSITION: num_algos = __add_algo( algos, num_algos, &position_placement_algo); break; case PLACE_TILEMANUAL: num_algos = __add_algo( algos, num_algos, &smart_placement_algo); num_algos = __add_algo( algos, num_algos, &manual_placement_algo); break; case PLACE_MINOVERLAPPERCENT: arg.flags.use_percent = 1; /* fall through */ case PLACE_MINOVERLAP: num_algos = __add_algo( algos, num_algos, &minoverlap_placement_algo); break; case PLACE_TILECASCADE: num_algos = __add_algo( algos, num_algos, &smart_placement_algo); num_algos = __add_algo( algos, num_algos, &cascade_placement_algo); break; case PLACE_MANUAL: case PLACE_MANUAL_B: num_algos = __add_algo( algos, num_algos, &manual_placement_algo); break; case PLACE_CASCADE: case PLACE_CASCADE_B: num_algos = __add_algo( algos, num_algos, &cascade_placement_algo); break; default: /* can't happen */ break; } /* try all the placement algorithms */ for (i = 0 ; ret.best_penalty < 0 && i < num_algos; i++) { arg.algo = algos[i]; placement_loop(&ret, &arg); } if (ret.best_penalty >= 0) { /* placement succed */ attr_g->x = ret.best_p.x; attr_g->y = ret.best_p.y; } else { /* fall back to default position */ attr_g->x = 0; attr_g->y = 0; reason->pos.has_placement_failed = 1; } return ret.flags.do_resize_too; } static int __place_get_nowm_pos( const exec_context_t *exc, window_style *pstyle, rectangle *attr_g, pl_flags_t flags, rectangle screen_g, pl_start_style_t start_style, int mode, initial_window_options_t *win_opts, pl_reason_t *reason, int pdeltax, int pdeltay) { FvwmWindow *fw = exc->w.fw; size_borders b; if (!win_opts->flags.do_override_ppos) { SET_PLACED_BY_FVWM(fw, False); } /* the USPosition was specified, or the window is a transient, or it * starts iconic so place it automatically */ if ( SUSE_START_ON_SCREEN(&pstyle->flags) && flags.do_honor_starts_on_screen) { fscreen_scr_t mangle_screen; /* If StartsOnScreen has been given for a window, translate its * USPosition so that it is relative to that particular screen. * If we don't do this, then a geometry would completely * cancel the effect of the StartsOnScreen style. However, some * applications try to remember their position. This would * break if these were translated to screen coordinates. There * is no reliable way to do it. Currently, if the desired * place does not intersect the target screen, we assume the * window position must be adjusted to the screen origin. So * there are two ways to get a window to pop up on a particular * Xinerama screen. 1: The intuitive way giving a geometry * hint relative to the desired screen's 0,0 along with the * appropriate StartsOnScreen style (or *wmscreen resource), or * 2: Do NOT specify a Xinerama screen (or specify it to be * 'g') and give the geometry hint in terms of the global * screen. */ mangle_screen = FScreenFetchMangledScreenFromUSPosHints( &(fw->hints)); if (mangle_screen != FSCREEN_GLOBAL) { /* whoever set this hint knew exactly what he was * doing; so ignore the StartsOnScreen style */ flags.do_honor_starts_on_screen = 0; reason->pos.reason = PR_POS_USPOS_OVERRIDE_SOS; } else if (attr_g->x + attr_g->width < screen_g.x || attr_g->x >= screen_g.x + screen_g.width || attr_g->y + attr_g->height < screen_g.y || attr_g->y >= screen_g.y + screen_g.height) { /* desired coordinates do not intersect the target * screen. Let's assume the application specified * global coordinates and translate them to the screen. */ FScreenTranslateCoordinates( NULL, start_style.screen, NULL, FSCREEN_GLOBAL, &attr_g->x, &attr_g->y); reason->pos.do_adjust_off_screen = 1; } } /* If SkipMapping, and other legalities are observed, adjust for * StartsOnPage. */ if (DO_NOT_SHOW_ON_MAP(fw) && flags.do_honor_starts_on_page && (!IS_TRANSIENT(fw) || SUSE_START_ON_PAGE_FOR_TRANSIENT(&pstyle->flags)) #if 0 /* dv 08-Jul-2003: Do not use this. Instead, force the window on * the requested page even if the application requested a different * position. */ && (SUSE_NO_PPOSITION(&pstyle->flags) || !(fw->hints.flags & PPosition)) /* dv 08-Jul-2003: This condition is always true because we * already checked for flags.do_honor_starts_on_page above. */ /* RBW - allow StartsOnPage to go through, even if iconic. */ && ((!(fw->wmhints && (fw->wmhints->flags & StateHint) && fw->wmhints->initial_state == IconicState)) || flags.do_honor_starts_on_page) #endif ) { int old_x; int old_y; old_x = attr_g->x; old_y = attr_g->y; /* We're placing a SkipMapping window - either capturing one * that's previously been mapped, or overriding USPosition - so * what we have here is its actual untouched coordinates. In * case it was a StartsOnPage window, we have to 1) convert the * existing x,y offsets relative to the requested page (i.e., * as though there were only one page, no virtual desktop), * then 2) readjust relative to the current page. */ if (attr_g->x < 0) { attr_g->x += Scr.MyDisplayWidth; } attr_g->x %= Scr.MyDisplayWidth; attr_g->x -= pdeltax; /* Noticed a quirk here. With some apps (e.g., xman), we find * the placement has moved 1 pixel away from where we * originally put it when we come through here. Why is this * happening? Probably attr_backup.border_width, try xclock * -borderwidth 100 */ if (attr_g->y < 0) { attr_g->y += Scr.MyDisplayHeight; } attr_g->y %= Scr.MyDisplayHeight; attr_g->y -= pdeltay; if (attr_g->x != old_x || attr_g->y != old_y) { reason->pos.do_adjust_off_page = 1; } } /* put it where asked, mod title bar */ /* if the gravity is towards the top, move it by the title height */ { rectangle final_g; int gravx; int gravy; gravity_get_offsets(fw->hints.win_gravity, &gravx, &gravy); final_g.x = attr_g->x + gravx * fw->attr_backup.border_width; final_g.y = attr_g->y + gravy * fw->attr_backup.border_width; /* Virtually all applications seem to share a common bug: they * request the top left pixel of their *border* as their origin * instead of the top left pixel of their client window, e.g. * 'xterm -g +0+0' creates an xterm that tries to map at (0 0) * although its border (width 1) would not be visible if it ran * under plain X. It should have tried to map at (1 1) * instead. This clearly violates the ICCCM, but trying to * change this is like tilting at windmills. So we have to add * the border width here. */ final_g.x += fw->attr_backup.border_width; final_g.y += fw->attr_backup.border_width; final_g.width = 0; final_g.height = 0; if (mode == PLACE_INITIAL) { get_window_borders(fw, &b); gravity_resize( fw->hints.win_gravity, &final_g, b.total_size.width, b.total_size.height); } attr_g->x = final_g.x; attr_g->y = final_g.y; } return 0; } /* Handles initial placement and sizing of a new window * * Return value: * * 0 = window lost * 1 = OK * 2 = OK, window must be resized too */ static int __place_window( const exec_context_t *exc, window_style *pstyle, rectangle *attr_g, pl_start_style_t start_style, int mode, initial_window_options_t *win_opts, pl_reason_t *reason) { FvwmWindow *t; int is_skipmapping_forbidden; int px = 0; int py = 0; int pdeltax = 0; int pdeltay = 0; rectangle screen_g; int rc = 0; pl_flags_t flags; extern Bool Restarting; FvwmWindow *fw = exc->w.fw; memset(&flags, 0, sizeof(flags)); /* Select a desk to put the window on (in list of priority): * 1. Sticky Windows stay on the current desk. * 2. Windows specified with StartsOnDesk go where specified * 3. Put it on the desk it was on before the restart. * 4. Transients go on the same desk as their parents. * 5. Window groups stay together (if the KeepWindowGroupsOnDesk style * is used). */ /* Let's get the StartsOnDesk/Page tests out of the way first. */ if ( SUSE_START_ON_DESK(&pstyle->flags) || SUSE_START_ON_SCREEN(&pstyle->flags)) { flags.do_honor_starts_on_page = 1; flags.do_honor_starts_on_screen = 1; /* * Honor the flag unless... * it's a restart or recapture, and that option's disallowed... */ if (win_opts->flags.do_override_ppos && (Restarting || (Scr.flags.are_windows_captured)) && !SRECAPTURE_HONORS_STARTS_ON_PAGE(&pstyle->flags)) { flags.do_honor_starts_on_page = 0; flags.do_honor_starts_on_screen = 0; reason->page.reason = (preason_page_t)PR_PAGE_IGNORE_CAPTURE; reason->page.do_ignore_starts_on_page = 1; reason->screen.reason = (preason_screen_t)PR_PAGE_IGNORE_CAPTURE; } /* * it's a cold start window capture, and that's disallowed... */ if (win_opts->flags.do_override_ppos && (!Restarting && !(Scr.flags.are_windows_captured)) && !SCAPTURE_HONORS_STARTS_ON_PAGE(&pstyle->flags)) { flags.do_honor_starts_on_page = 0; flags.do_honor_starts_on_screen = 0; reason->page.reason = PR_PAGE_IGNORE_CAPTURE; reason->page.do_ignore_starts_on_page = 1; reason->screen.reason = (preason_screen_t)PR_PAGE_IGNORE_CAPTURE; } /* * it's ActivePlacement and SkipMapping, and that's disallowed. */ switch (SPLACEMENT_MODE(&pstyle->flags)) { case PLACE_MANUAL: case PLACE_MANUAL_B: case PLACE_TILEMANUAL: is_skipmapping_forbidden = !SMANUAL_PLACEMENT_HONORS_STARTS_ON_PAGE( &pstyle->flags); break; default: is_skipmapping_forbidden = 0; break; } if (win_opts->flags.do_override_ppos || !DO_NOT_SHOW_ON_MAP(fw)) { is_skipmapping_forbidden = 0; } if (is_skipmapping_forbidden == 1) { flags.do_honor_starts_on_page = 0; reason->page.reason = PR_PAGE_IGNORE_INVALID; reason->page.do_ignore_starts_on_page = 1; fvwm_msg( WARN, "__place_window", "invalid style combination used: StartsOnPage" "/StartsOnDesk and SkipMapping don't work with" " ManualPlacement and TileManualPlacement." " Putting window on current page, please use" " another placement style or" " ActivePlacementHonorsStartsOnPage."); } } /* get the screen coordinates to place window on */ if (SUSE_START_ON_SCREEN(&pstyle->flags)) { if (flags.do_honor_starts_on_screen) { /* use screen from style */ FScreenGetScrRect( NULL, start_style.screen, &screen_g.x, &screen_g.y, &screen_g.width, &screen_g.height); reason->screen.screen = start_style.screen; } else { /* use global screen */ FScreenGetScrRect( NULL, FSCREEN_GLOBAL, &screen_g.x, &screen_g.y, &screen_g.width, &screen_g.height); reason->screen.screen = FSCREEN_GLOBAL; } } else { /* use current screen */ FScreenGetScrRect( NULL, FSCREEN_CURRENT, &screen_g.x, &screen_g.y, &screen_g.width, &screen_g.height); reason->screen.screen = FSCREEN_CURRENT; } if (SPLACEMENT_MODE(&pstyle->flags) != PLACE_MINOVERLAPPERCENT && SPLACEMENT_MODE(&pstyle->flags) != PLACE_MINOVERLAP && SPLACEMENT_MODE(&pstyle->flags) != PLACE_POSITION) { /* TA: In the case of PositionPlacement, the "ewmhiwa" option * will have already modified this for us -- so don't do it * for this placement policy. */ EWMH_GetWorkAreaIntersection( fw, &screen_g.x, &screen_g.y, &screen_g.width, &screen_g.height, SEWMH_PLACEMENT_MODE(&pstyle->flags)); reason->screen.was_modified_by_ewmh_workingarea = 1; } reason->screen.g = screen_g; /* Don't alter the existing desk location during Capture/Recapture. */ if (!win_opts->flags.do_override_ppos) { fw->Desk = Scr.CurrentDesk; reason->desk.reason = PR_DESK_CURRENT; } else { reason->desk.reason = PR_DESK_CAPTURE; } if (S_IS_STICKY_ACROSS_DESKS(SFC(pstyle->flags))) { fw->Desk = Scr.CurrentDesk; reason->desk.reason = PR_DESK_STICKY; } else if (SUSE_START_ON_DESK(&pstyle->flags) && start_style.desk && flags.do_honor_starts_on_page) { fw->Desk = (start_style.desk > -1) ? start_style.desk - 1 : start_style.desk; reason->desk.reason = reason->desk.sod_reason; } else { if ((DO_USE_WINDOW_GROUP_HINT(fw)) && (fw->wmhints) && (fw->wmhints->flags & WindowGroupHint)&& (fw->wmhints->window_group != None) && (fw->wmhints->window_group != Scr.Root)) { /* Try to find the group leader or another window in * the group */ for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) { if (FW_W(t) == fw->wmhints->window_group) { /* found the group leader, break out */ fw->Desk = t->Desk; reason->desk.reason = PR_DESK_WINDOW_GROUP_LEADER; break; } else if (t->wmhints && (t->wmhints->flags & WindowGroupHint) && (t->wmhints->window_group == fw->wmhints->window_group)) { /* found a window from the same group, * but keep looking for the group * leader */ fw->Desk = t->Desk; reason->desk.reason = PR_DESK_WINDOW_GROUP_MEMBER; } } } if ((IS_TRANSIENT(fw))&&(FW_W_TRANSIENTFOR(fw)!=None)&& (FW_W_TRANSIENTFOR(fw) != Scr.Root)) { /* Try to find the parent's desktop */ for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) { if (FW_W(t) == FW_W_TRANSIENTFOR(fw)) { fw->Desk = t->Desk; reason->desk.reason = PR_DESK_TRANSIENT; break; } } } { /* migo - I am not sure this block is ever needed */ Atom atype; int aformat; unsigned long nitems, bytes_remain; unsigned char *prop; if ( XGetWindowProperty( dpy, FW_W(fw), _XA_WM_DESKTOP, 0L, 1L, True, _XA_WM_DESKTOP, &atype, &aformat, &nitems, &bytes_remain, &prop) == Success) { if (prop != NULL) { fw->Desk = *(unsigned long *)prop; XFree(prop); reason->desk.reason = PR_DESK_XPROP_XA_WM_DESKTOP; } } } } reason->desk.desk = fw->Desk; /* I think it would be good to switch to the selected desk * whenever a new window pops up, except during initialization */ /* RBW - 11/02/1998 -- I dont. */ if (!win_opts->flags.do_override_ppos && !DO_NOT_SHOW_ON_MAP(fw)) { if (Scr.CurrentDesk != fw->Desk) { reason->desk.do_switch_desk = 1; } goto_desk(fw->Desk); } /* Don't move viewport if SkipMapping, or if recapturing the window, * adjust the coordinates later. Otherwise, just switch to the target * page - it's ever so much simpler. */ if (S_IS_STICKY_ACROSS_PAGES(SFC(pstyle->flags))) { reason->page.reason = PR_PAGE_STICKY; } else if (SUSE_START_ON_DESK(&pstyle->flags)) { if (start_style.page_x != 0 && start_style.page_y != 0) { px = start_style.page_x - 1; py = start_style.page_y - 1; reason->page.reason = PR_PAGE_STYLE; px *= Scr.MyDisplayWidth; py *= Scr.MyDisplayHeight; if (!win_opts->flags.do_override_ppos && !DO_NOT_SHOW_ON_MAP(fw)) { MoveViewport(px,py,True); reason->page.do_switch_page = 1; } else if (flags.do_honor_starts_on_page) { /* Save the delta from current page */ pdeltax = Scr.Vx - px; pdeltay = Scr.Vy - py; reason->page.do_honor_starts_on_page = 1; } } } /* pick a location for the window. */ __place_get_placement_flags( &flags, fw, pstyle, win_opts, mode, reason); if (flags.do_not_use_wm_placement) { rc = __place_get_nowm_pos( exc, pstyle, attr_g, flags, screen_g, start_style, mode, win_opts, reason, pdeltax, pdeltay); } else { rc = __place_get_wm_pos( exc, pstyle, attr_g, flags, screen_g, start_style, mode, win_opts, reason, pdeltax, pdeltay); } reason->pos.x = attr_g->x; reason->pos.y = attr_g->y; return rc; } static void __place_handle_x_resources( FvwmWindow *fw, window_style *pstyle, pl_reason_t *reason) { int client_argc = 0; char **client_argv = NULL; XrmValue rm_value; /* Used to parse command line of clients for specific desk requests. */ /* Todo: check for multiple desks. */ XrmDatabase db = NULL; static XrmOptionDescRec table [] = { /* Want to accept "-workspace N" or -xrm "fvwm*desk:N" as * options to specify the desktop. I have to include dummy * options that are meaningless since Xrm seems to allow -w to * match -workspace if there would be no ambiguity. */ {"-workspacf", "*junk", XrmoptionSepArg, (caddr_t) NULL}, {"-workspace", "*desk", XrmoptionSepArg, (caddr_t) NULL}, {"-xrn", NULL, XrmoptionResArg, (caddr_t) NULL}, {"-xrm", NULL, XrmoptionResArg, (caddr_t) NULL}, }; int t1 = -1, t2 = -1, t3 = -1, spargs = 0; /* Find out if the client requested a specific desk on the command * line. * RBW - 11/20/1998 - allow a desk of -1 to work. */ if (XGetCommand(dpy, FW_W(fw), &client_argv, &client_argc) == 0) { return; } if (client_argc <= 0 || client_argv == NULL) { return; } /* Get global X resources */ MergeXResources(dpy, &db, False); /* command line takes precedence over all */ MergeCmdLineResources( &db, table, 4, client_argv[0], &client_argc, client_argv, True); /* parse the database values */ if (GetResourceString(db, "desk", client_argv[0], &rm_value) && rm_value.size != 0) { SGET_START_DESK(*pstyle) = atoi(rm_value.addr); /* RBW - 11/20/1998 */ if (SGET_START_DESK(*pstyle) > -1) { SSET_START_DESK( *pstyle, SGET_START_DESK(*pstyle) + 1); } reason->desk.sod_reason = PR_DESK_X_RESOURCE_DESK; pstyle->flags.use_start_on_desk = 1; } if (GetResourceString(db, "fvwmscreen", client_argv[0], &rm_value) && rm_value.size != 0) { SSET_START_SCREEN( *pstyle, FScreenGetScreenArgument(rm_value.addr, 'c')); reason->screen.reason = PR_SCREEN_X_RESOURCE_FVWMSCREEN; reason->screen.screen = SGET_START_SCREEN(*pstyle); pstyle->flags.use_start_on_screen = 1; } if (GetResourceString(db, "page", client_argv[0], &rm_value) && rm_value.size != 0) { spargs = sscanf( rm_value.addr, "%d %d %d", &t1, &t2, &t3); switch (spargs) { case 1: pstyle->flags.use_start_on_desk = 1; SSET_START_DESK(*pstyle, (t1 > -1) ? t1 + 1 : t1); reason->desk.sod_reason = PR_DESK_X_RESOURCE_PAGE; break; case 2: pstyle->flags.use_start_on_desk = 1; SSET_START_PAGE_X(*pstyle, (t1 > -1) ? t1 + 1 : t1); SSET_START_PAGE_Y(*pstyle, (t2 > -1) ? t2 + 1 : t2); reason->page.reason = PR_PAGE_X_RESOURCE_PAGE; reason->page.px = SGET_START_PAGE_X(*pstyle); reason->page.py = SGET_START_PAGE_Y(*pstyle); break; case 3: pstyle->flags.use_start_on_desk = 1; SSET_START_DESK(*pstyle, (t1 > -1) ? t1 + 1 : t1); reason->desk.sod_reason = PR_DESK_X_RESOURCE_PAGE; SSET_START_PAGE_X(*pstyle, (t2 > -1) ? t2 + 1 : t2); SSET_START_PAGE_Y(*pstyle, (t3 > -1) ? t3 + 1 : t3); reason->page.reason = PR_PAGE_X_RESOURCE_PAGE; reason->page.px = SGET_START_PAGE_X(*pstyle); reason->page.py = SGET_START_PAGE_Y(*pstyle); break; default: break; } } XFreeStringList(client_argv); XrmDestroyDatabase(db); return; } static void __explain_placement(FvwmWindow *fw, pl_reason_t *reason) { char explanation[2048]; char *r; char *s; char t[32]; int do_show_page; int is_placed_by_algo; *explanation = 0; s = explanation; strcat(s, "placed new window 0x%x '%s':\n"); s += strlen(s); sprintf( s, " initial size %dx%d\n", fw->g.frame.width, fw->g.frame.height); s += strlen(s); switch (reason->desk.reason) { case PR_DESK_CURRENT: r = "current desk"; break; case PR_DESK_STYLE: r = "specified by style"; break; case PR_DESK_X_RESOURCE_DESK: r = "specified by 'desk' X resource"; break; case PR_DESK_X_RESOURCE_PAGE: r = "specified by 'page' X resource"; break; case PR_DESK_CAPTURE: r = "window was (re)captured"; break; case PR_DESK_STICKY: r = "window is sticky"; break; case PR_DESK_WINDOW_GROUP_LEADER: r = "same desk as window group leader"; break; case PR_DESK_WINDOW_GROUP_MEMBER: r = "same desk as window group member"; break; case PR_DESK_TRANSIENT: r = "transient window placed on same desk as parent"; break; case PR_DESK_XPROP_XA_WM_DESKTOP: r = "specified by _XA_WM_DESKTOP property"; break; default: r = "bug"; break; } sprintf(s, " desk %d (%s)\n", reason->desk.desk, r); s += strlen(s); if (reason->desk.do_switch_desk == 1) { sprintf(s, " (switched to desk)\n"); s += strlen(s); } /* page */ do_show_page = 1; switch (reason->page.reason) { case PR_PAGE_CURRENT: do_show_page = 0; r = "current page"; break; case PR_PAGE_STYLE: r = "specified by style"; break; case PR_PAGE_X_RESOURCE_PAGE: r = "specified by 'page' X resource"; break; case PR_PAGE_IGNORE_CAPTURE: r = "window was (re)captured"; break; case PR_PAGE_IGNORE_INVALID: r = "requested page ignored because of invalid style" " combination"; break; case PR_PAGE_STICKY: do_show_page = 0; r = "current page (window is sticky)"; break; default: r = "bug"; break; } if (do_show_page == 0) { sprintf(s, " %s\n", r); } else { sprintf( s, " page %d %d (%s)\n", reason->page.px - 1, reason->page.py - 1, r); } s += strlen(s); if (reason->page.do_switch_page == 1) { sprintf(s, " (switched to page)\n"); s += strlen(s); } if (reason->page.do_ignore_starts_on_page == 1) { sprintf(s, " (possibly ignored StartsOnPage)\n"); s += strlen(s); } /* screen */ if (FScreenIsEnabled() == True || FScreenIsSLSEnabled() == True) { switch (reason->screen.reason) { case PR_SCREEN_CURRENT: r = "current screen"; break; case PR_SCREEN_STYLE: r = "specified by style"; break; case PR_SCREEN_X_RESOURCE_FVWMSCREEN: r = "specified by 'fvwmscreen' X resource"; break; case PR_SCREEN_IGNORE_CAPTURE: r = "window was (re)captured"; break; default: r = "bug"; break; } FScreenSpecToString(t, 32, reason->screen.screen); sprintf( s, " screen: %s: %d %d %dx%d (%s)\n", t, reason->screen.g.x, reason->screen.g.y, reason->screen.g.width, reason->screen.g.height, r); s += strlen(s); if (reason->screen.was_modified_by_ewmh_workingarea == 1) { sprintf( s, " (screen area modified by EWMH working" " area)\n"); s += strlen(s); } } /* position */ is_placed_by_algo = 0; switch (reason->pos.reason) { case PR_POS_NORMAL: is_placed_by_algo = 1; r = "normal placement"; break; case PR_POS_IGNORE_PPOS: is_placed_by_algo = 1; r = "ignored program specified position"; break; case PR_POS_USE_PPOS: r = "used program specified position"; break; case PR_POS_IGNORE_USPOS: is_placed_by_algo = 1; r = "ignored user specified position"; break; case PR_POS_USE_USPOS: r = "used user specified position"; break; case PR_POS_PLACE_AGAIN: is_placed_by_algo = 1; r = "by PlaceAgain command"; break; case PR_POS_CAPTURE: r = "window was (re)captured"; break; case PR_POS_USPOS_OVERRIDE_SOS: r = "StartsOnPage style overridden by application via USPos"; break; default: r = "bug"; break; } sprintf(s, " position %d %d", reason->pos.x, reason->pos.y); s += strlen(s); if (is_placed_by_algo == 1) { char *a; char *b; b = ""; switch (reason->pos.algo) { case PLACE_POSITION: a = "Position args: "; b = reason->pos.pl_position_string; break; case PLACE_TILEMANUAL: a = "TileManual"; break; case PLACE_MANUAL: case PLACE_MANUAL_B: a = "Manual"; break; case PLACE_MINOVERLAPPERCENT: a = "MinOverlapPercent"; break; case PLACE_TILECASCADE: a = "TileCascade"; break; case PLACE_CASCADE: case PLACE_CASCADE_B: a = "Cascade"; break; case PLACE_MINOVERLAP: a = "MinOverlap"; break; default: a = "bug"; break; } sprintf(s, ", placed by fvwm (%s)\n", r); s += strlen(s); sprintf(s, " placement method: %s%s\n", a, b); s += strlen(s); if (reason->pos.do_not_manual_icon_placement == 1) { sprintf(s, " (icon not placed manually)\n"); s += strlen(s); } if (reason->pos.is_pl_position_string_invalid == 1) { sprintf(s, " (invalid position string)\n"); s += strlen(s); } if (reason->pos.has_tile_failed == 1) { sprintf(s, " (tile placement failed)\n"); s += strlen(s); } if (reason->pos.has_manual_failed == 1) { sprintf(s, " (manual placement failed)\n"); s += strlen(s); } if (reason->pos.has_placement_failed == 1) { sprintf(s, " (placement failed default pos 0 0)\n"); s += strlen(s); } } else { sprintf(s, " (%s)\n", r); s += strlen(s); } if (reason->pos.do_adjust_off_screen == 1) { sprintf(s, " (adjusted to force window on screen)\n"); s += strlen(s); } if (reason->pos.do_adjust_off_page == 1) { sprintf(s, " (adjusted to force window on page)\n"); s += strlen(s); } fvwm_msg( INFO, "__explain_placement", explanation, (int)FW_W(fw), fw->name.name); return; } /* ---------------------------- interface functions ------------------------ */ Bool setup_window_placement( FvwmWindow *fw, window_style *pstyle, rectangle *attr_g, initial_window_options_t *win_opts, placement_mode_t mode) { int rc; const exec_context_t *exc; exec_context_changes_t ecc; pl_reason_t reason; pl_start_style_t start_style; memset(&reason, 0, sizeof(reason)); if (pstyle->flags.use_start_on_desk) { reason.desk.sod_reason = PR_DESK_STYLE; reason.page.px = SGET_START_PAGE_X(*pstyle); reason.page.py = SGET_START_PAGE_Y(*pstyle); } if (pstyle->flags.use_start_on_screen) { reason.screen.reason = PR_SCREEN_STYLE; reason.screen.screen = SGET_START_SCREEN(*pstyle); } __place_handle_x_resources(fw, pstyle, &reason); if (pstyle->flags.do_start_iconic) { win_opts->initial_state = IconicState; } ecc.type = EXCT_NULL; ecc.w.fw = fw; exc = exc_create_context(&ecc, ECC_TYPE | ECC_FW); start_style.desk = SGET_START_DESK(*pstyle); start_style.page_x = SGET_START_PAGE_X(*pstyle); start_style.page_y = SGET_START_PAGE_Y(*pstyle); start_style.screen = SGET_START_SCREEN(*pstyle); rc = __place_window( exc, pstyle, attr_g, start_style, mode, win_opts, &reason); exc_destroy_context(exc); if (Scr.bo.do_explain_window_placement == 1) { __explain_placement(fw, &reason); } return (rc == 0) ? False : True; } /* ---------------------------- builtin commands --------------------------- */ void CMD_PlaceAgain(F_CMD_ARGS) { int old_desk; char *token; float noMovement[1] = {1.0}; float *ppctMovement = noMovement; rectangle attr_g; XWindowAttributes attr; Bool do_move_animated = False; Bool do_place_icon = False; FvwmWindow * const fw = exc->w.fw; if (!XGetWindowAttributes(dpy, FW_W(fw), &attr)) { return; } while ((token = PeekToken(action, &action)) != NULL) { if (StrEquals("Anim", token)) { ppctMovement = NULL; do_move_animated = True; } else if (StrEquals("icon", token)) { do_place_icon = True; } } old_desk = fw->Desk; if (IS_ICONIFIED(fw) && !do_place_icon) { return; } if (IS_ICONIFIED(fw) && do_place_icon) { rectangle new_g; rectangle old_g; if (IS_ICON_SUPPRESSED(fw)) { return; } fw->Desk = Scr.CurrentDesk; get_icon_geometry(fw, &old_g); SET_ICON_MOVED(fw, 0); AutoPlaceIcon(fw, NULL, False); get_icon_geometry(fw, &new_g); __move_icon( fw, new_g.x, new_g.y, old_g.x, old_g.y, do_move_animated, False); } else { window_style style; initial_window_options_t win_opts; memset(&win_opts, 0, sizeof(win_opts)); lookup_style(fw, &style); attr_g.x = attr.x; attr_g.y = attr.y; attr_g.width = attr.width; attr_g.height = attr.height; setup_window_placement( exc->w.fw, &style, &attr_g, &win_opts, PLACE_AGAIN); AnimatedMoveFvwmWindow( fw, FW_W_FRAME(fw), -1, -1, attr_g.x, attr_g.y, False, -1, ppctMovement); } if (fw->Desk != old_desk) { int new_desk = fw->Desk; fw->Desk = old_desk; do_move_window_to_desk(fw, new_desk); } return; } fvwm-2.7.0/fvwm/schedule.h0000644000175000017500000000030414147024676012354 00000000000000/* -*-c-*- */ #ifndef SCHEDULE_H #define SCHEDULE_H void squeue_execute(void); int squeue_get_next_ms(void); int squeue_get_next_id(void); int squeue_get_last_id(void); #endif /* SCHEDULE_H */ fvwm-2.7.0/fvwm/bindings.h0000644000175000017500000000144414147024700012347 00000000000000/* -*-c-*- */ #ifndef BINDINGS_H #define BINDINGS_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ void update_key_bindings(void); unsigned int MaskUsedModifiers(unsigned int in_modifiers); unsigned int GetUnusedModifiers(void); void print_bindings(void); #endif /* BINDINGS_H */ fvwm-2.7.0/fvwm/expand.c0000644000175000017500000006255314147024700012034 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include "libs/fvwmlib.h" #include "libs/Parse.h" #include "libs/Strings.h" #include "libs/ColorUtils.h" #include "libs/FScreen.h" #include "fvwm.h" #include "externs.h" #include "cursor.h" #include "functions.h" #include "misc.h" #include "move_resize.h" #include "screen.h" #include "geometry.h" #include "read.h" #include "virtual.h" #include "colorset.h" #include "schedule.h" #include "infostore.h" #include "libs/FGettext.h" #include "libs/charmap.h" #include "libs/wcontext.h" #include "libs/Fsvg.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ extern char const * const Fvwm_VersionInfo; /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ static char *partial_function_vars[] = { "bg.cs", "desk.name", "fg.cs", "fgsh.cs", "gt.", "hilight.cs", "infostore.", "shadow.cs", NULL }; static char *function_vars[] = { "cond.rc", "cw.height", "cw.width", "cw.x", "cw.y", "desk.height", "desk.n", "desk.pagesx", "desk.pagesy", "desk.width", "func.context", "i.height", "i.width", "i.x", "i.y", "ip.height", "ip.width", "ip.x", "ip.y", "it.height", "it.width", "it.x", "it.y", "page.nx", "page.ny", "pointer.cx", "pointer.cy", "pointer.wx", "pointer.wy", "pointer.x", "pointer.y", "pointer.screen", "schedule.last", "schedule.next", "screen", "version.info", "version.line", "version.num", "vp.height", "vp.width", "vp.x", "vp.y", "w.class", "w.height", "w.iconname", "w.iconfile", "w.miniiconfile", "w.iconfile.svgopts", "w.miniiconfile.svgopts", "w.id", "w.name", "w.resource", "w.visiblename", "w.width", "w.x", "w.y", "w.desk", "w.layer", "w.screen", /* ewmh working area */ "wa.height", "wa.width", "wa.x", "wa.y", /* ewmh dynamic working area */ "dwa.height", "dwa.width", "dwa.x", "dwa.y", NULL }; enum { VAR_BG_CS, VAR_DESK_NAME, VAR_FG_CS, VAR_FGSH_CS, VAR_GT_, VAR_HILIGHT_CS, VAR_INFOSTORE_, VAR_SHADOW_CS } partial_extended_vars; enum { VAR_COND_RC, VAR_CW_HEIGHT, VAR_CW_WIDTH, VAR_CW_X, VAR_CW_Y, VAR_DESK_HEIGHT, VAR_DESK_N, VAR_DESK_PAGESX, VAR_DESK_PAGESY, VAR_DESK_WIDTH, VAR_FUNC_CONTEXT, VAR_I_HEIGHT, VAR_I_WIDTH, VAR_I_X, VAR_I_Y, VAR_IP_HEIGHT, VAR_IP_WIDTH, VAR_IP_X, VAR_IP_Y, VAR_IT_HEIGHT, VAR_IT_WIDTH, VAR_IT_X, VAR_IT_Y, VAR_PAGE_NX, VAR_PAGE_NY, VAR_POINTER_CX, VAR_POINTER_CY, VAR_POINTER_WX, VAR_POINTER_WY, VAR_POINTER_X, VAR_POINTER_Y, VAR_POINTER_SCREEN, VAR_SCHEDULE_LAST, VAR_SCHEDULE_NEXT, VAR_SCREEN, VAR_VERSION_INFO, VAR_VERSION_LINE, VAR_VERSION_NUM, VAR_VP_HEIGHT, VAR_VP_WIDTH, VAR_VP_X, VAR_VP_Y, VAR_W_CLASS, VAR_W_HEIGHT, VAR_W_ICONNAME, VAR_W_ICONFILE, VAR_W_MINIICONFILE, VAR_W_ICONFILE_SVGOPTS, VAR_W_MINIICONFILE_SVGOPTS, VAR_W_ID, VAR_W_NAME, VAR_W_RESOURCE, VAR_W_VISIBLE_NAME, VAR_W_WIDTH, VAR_W_X, VAR_W_Y, VAR_W_DESK, VAR_W_LAYER, VAR_W_SCREEN, /* ewmh working area */ VAR_WA_HEIGHT, VAR_WA_WIDTH, VAR_WA_X, VAR_WA_Y, /* ewmh dynamic working area */ VAR_DWA_HEIGHT, VAR_DWA_WIDTH, VAR_DWA_X, VAR_DWA_Y } extended_vars; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ int __eae_parse_range(char *input, int *lower, int *upper) { int rc; int n; *lower = 0; *upper = INT_MAX; if (*input == '*') { return 0; } if (!isdigit(*input)) { return -1; } rc = sscanf(input, "%d-%d%n", lower, upper, &n); if (rc < 2) { rc = sscanf(input, "%d%n", lower, &n); if (rc < 1) { /* not a positional argument */ return -1; } if (input[n] == '-') { /* $[n- */ n++; } else { /* $[n */ *upper = *lower; } } input += n; if (*input != 0) { /* trailing characters - not good */ return -1; } if (*upper < *lower) { /* the range is reverse - not good */ return -1; } return 0; } static signed int expand_args_extended( char *input, char *argument_string, char *output) { int rc; int lower; int upper; int i; size_t len; rc = __eae_parse_range(input, &lower, &upper); if (rc == -1) { return -1; } /* Skip to the start of the requested argument range */ if (lower > 0) { argument_string = SkipNTokens(argument_string, lower); } if (!argument_string) { /* replace with empty string */ return 0; } /* TODO: optimise handling of $[0] to $[9] which have already been * parsed */ for (i = lower, len = 0; i <= upper; i++) { char *token; size_t tlen; token = PeekToken(argument_string, &argument_string); if (token == NULL) { break; } /* copy the token */ if (i > lower) { if (output != NULL) { *output = ' '; output++; } len++; } tlen = strlen(token); if (output != NULL && tlen > 0) { memcpy(output, token, tlen); output += tlen; } len += tlen; } return (int)len; } static signed int expand_vars_extended( char *var_name, char *output, cond_rc_t *cond_rc, const exec_context_t *exc) { char *rest; char dummy[64] = "\0"; char *target = (output) ? output : dummy; int cs = -1; int n; int i; int l; int x; int y; Pixel pixel = 0; int val = -12345678; const char *string = NULL; char *allocated_string = NULL; char *quoted_string = NULL; Bool should_quote = False; Bool is_numeric = False; Bool is_target = False; Bool is_x; Window context_w = Scr.Root; FvwmWindow *fw = exc->w.fw; signed int len = -1; /* allow partial matches for *.cs, gt, ... etc. variables */ switch ((i = GetTokenIndex(var_name, partial_function_vars, -1, &rest))) { case VAR_FG_CS: case VAR_BG_CS: case VAR_HILIGHT_CS: case VAR_SHADOW_CS: case VAR_FGSH_CS: if (!isdigit(*rest) || (*rest == '0' && *(rest + 1) != 0)) { /* not a non-negative integer without leading zeros */ return -1; } if (sscanf(rest, "%d%n", &cs, &n) < 1) { return -1; } if (*(rest + n) != 0) { /* trailing characters */ return -1; } if (cs < 0) { return -1; } alloc_colorset(cs); switch (i) { case VAR_FG_CS: pixel = Colorset[cs].fg; break; case VAR_BG_CS: pixel = Colorset[cs].bg; break; case VAR_HILIGHT_CS: pixel = Colorset[cs].hilite; break; case VAR_SHADOW_CS: pixel = Colorset[cs].shadow; break; case VAR_FGSH_CS: pixel = Colorset[cs].fgsh; break; } is_target = True; len = pixel_to_color_string(dpy, Pcmap, pixel, target, False); goto GOT_STRING; case VAR_GT_: if (rest == NULL) { return -1; } string = _(rest); goto GOT_STRING; case VAR_INFOSTORE_: if (rest == NULL) return -1; if ((string = get_metainfo_value(rest)) == NULL) return -1; goto GOT_STRING; case VAR_DESK_NAME: if (sscanf(rest, "%d%n", &cs, &n) < 1) { return -1; } if (*(rest + n) != 0) { /* trailing characters */ return -1; } string = GetDesktopName(cs); if (string == NULL) { const char *ddn = _("Desk"); allocated_string = (char *)safemalloc(19 + strlen(ddn)); sprintf(allocated_string, "%s %i", ddn, cs); string = allocated_string; } goto GOT_STRING; default: break; } /* only exact matches for all other variables */ switch ((i = GetTokenIndex(var_name, function_vars, 0, &rest))) { case VAR_DESK_N: is_numeric = True; val = Scr.CurrentDesk; break; case VAR_DESK_WIDTH: is_numeric = True; val = Scr.VxMax + Scr.MyDisplayWidth; break; case VAR_DESK_HEIGHT: is_numeric = True; val = Scr.VyMax + Scr.MyDisplayHeight; break; case VAR_DESK_PAGESX: is_numeric = True; val = (int)(Scr.VxMax / Scr.MyDisplayWidth) + 1; break; case VAR_DESK_PAGESY: is_numeric = True; val = (int)(Scr.VyMax / Scr.MyDisplayHeight) + 1; break; case VAR_VP_X: is_numeric = True; val = Scr.Vx; break; case VAR_VP_Y: is_numeric = True; val = Scr.Vy; break; case VAR_VP_WIDTH: is_numeric = True; val = Scr.MyDisplayWidth; break; case VAR_VP_HEIGHT: is_numeric = True; val = Scr.MyDisplayHeight; break; case VAR_WA_HEIGHT: is_numeric = True; val = Scr.Desktops->ewmh_working_area.height; break; case VAR_WA_WIDTH: is_numeric = True; val = Scr.Desktops->ewmh_working_area.width; break; case VAR_WA_X: is_numeric = True; val = Scr.Desktops->ewmh_working_area.x; break; case VAR_WA_Y: is_numeric = True; val = Scr.Desktops->ewmh_working_area.y; break; case VAR_DWA_HEIGHT: is_numeric = True; val = Scr.Desktops->ewmh_dyn_working_area.height; break; case VAR_DWA_WIDTH: is_numeric = True; val = Scr.Desktops->ewmh_dyn_working_area.width; break; case VAR_DWA_X: is_numeric = True; val = Scr.Desktops->ewmh_dyn_working_area.x; break; case VAR_DWA_Y: is_numeric = True; val = Scr.Desktops->ewmh_dyn_working_area.y; break; case VAR_PAGE_NX: is_numeric = True; val = (int)(Scr.Vx / Scr.MyDisplayWidth); break; case VAR_PAGE_NY: is_numeric = True; val = (int)(Scr.Vy / Scr.MyDisplayHeight); break; case VAR_W_ID: if (fw && !IS_EWMH_DESKTOP(FW_W(fw))) { is_target = True; sprintf(target, "0x%x", (int)FW_W(fw)); } break; case VAR_W_NAME: if (fw && !IS_EWMH_DESKTOP(FW_W(fw))) { string = fw->name.name; should_quote = True; } break; case VAR_W_ICONNAME: if (fw && !IS_EWMH_DESKTOP(FW_W(fw))) { string = fw->icon_name.name; should_quote = True; } break; case VAR_W_ICONFILE: case VAR_W_MINIICONFILE: if (fw && !IS_EWMH_DESKTOP(FW_W(fw))) { char *t; t = (i == VAR_W_ICONFILE) ? fw->icon_bitmap_file : fw->mini_pixmap_file; /* expand the path if possible */ allocated_string = PictureFindImageFile(t, NULL, R_OK); if (allocated_string == NULL) { string = t; } else if (USE_SVG && *allocated_string == ':' && (string = strchr(allocated_string + 1, ':'))) { string++; } else { string = allocated_string; } } break; case VAR_W_ICONFILE_SVGOPTS: case VAR_W_MINIICONFILE_SVGOPTS: if (fw && !IS_EWMH_DESKTOP(FW_W(fw))) { char *t; if (!USE_SVG) { return -1; } t = (i == VAR_W_ICONFILE_SVGOPTS) ? fw->icon_bitmap_file : fw->mini_pixmap_file; /* expand the path if possible */ allocated_string = PictureFindImageFile(t, NULL, R_OK); string = allocated_string; if (string && *string == ':' && (t = strchr(string + 1, ':'))) { *t = 0; } else { string = ""; } } break; case VAR_W_CLASS: if (fw && !IS_EWMH_DESKTOP(FW_W(fw))) { string = fw->class.res_class; should_quote = True; } break; case VAR_W_RESOURCE: if (fw && !IS_EWMH_DESKTOP(FW_W(fw))) { string = fw->class.res_name; should_quote = True; } break; case VAR_W_VISIBLE_NAME: if (fw && !IS_EWMH_DESKTOP(FW_W(fw))) { string = fw->visible_name; should_quote = True; } break; case VAR_W_X: case VAR_W_Y: case VAR_W_WIDTH: case VAR_W_HEIGHT: if (!fw || IS_ICONIFIED(fw) || IS_EWMH_DESKTOP(FW_W(fw))) { return -1; } else { rectangle g; is_numeric = True; get_unshaded_geometry(fw, &g); switch (i) { case VAR_W_X: val = g.x; break; case VAR_W_Y: val = g.y; break; case VAR_W_WIDTH: val = g.width; break; case VAR_W_HEIGHT: val = g.height; break; default: return -1; } } break; case VAR_CW_X: case VAR_CW_Y: case VAR_CW_WIDTH: case VAR_CW_HEIGHT: if (!fw || IS_ICONIFIED(fw) || IS_EWMH_DESKTOP(FW_W(fw))) { return -1; } else { rectangle g; is_numeric = True; get_client_geometry(fw, &g); switch (i) { case VAR_CW_X: val = g.x; break; case VAR_CW_Y: val = g.y; break; case VAR_CW_WIDTH: val = g.width; break; case VAR_CW_HEIGHT: val = g.height; break; default: return -1; } } break; case VAR_IT_X: case VAR_IT_Y: case VAR_IT_WIDTH: case VAR_IT_HEIGHT: if (!fw || IS_EWMH_DESKTOP(FW_W(fw))) { return -1; } else { rectangle g; if (get_visible_icon_title_geometry(fw, &g) == False) { return -1; } is_numeric = True; switch (i) { case VAR_IT_X: val = g.x; break; case VAR_IT_Y: val = g.y; break; case VAR_IT_WIDTH: val = g.width; break; case VAR_IT_HEIGHT: val = g.height; break; default: return -1; } } break; case VAR_IP_X: case VAR_IP_Y: case VAR_IP_WIDTH: case VAR_IP_HEIGHT: if (!fw || IS_EWMH_DESKTOP(FW_W(fw))) { return -1; } else { rectangle g; if (get_visible_icon_picture_geometry(fw, &g) == False) { return -1; } is_numeric = True; switch (i) { case VAR_IP_X: val = g.x; break; case VAR_IP_Y: val = g.y; break; case VAR_IP_WIDTH: val = g.width; break; case VAR_IP_HEIGHT: val = g.height; break; default: return -1; } } break; case VAR_I_X: case VAR_I_Y: case VAR_I_WIDTH: case VAR_I_HEIGHT: if (!fw || IS_EWMH_DESKTOP(FW_W(fw))) { return -1; } else { rectangle g; if (get_visible_icon_geometry(fw, &g) == False) { return -1; } is_numeric = True; switch (i) { case VAR_I_X: val = g.x; break; case VAR_I_Y: val = g.y; break; case VAR_I_WIDTH: val = g.width; break; case VAR_I_HEIGHT: val = g.height; break; default: return -1; } } break; case VAR_W_DESK: if (!fw || IS_EWMH_DESKTOP(FW_W(fw))) { return -1; } is_numeric = True; if (is_window_sticky_across_desks(fw)) { val = Scr.CurrentDesk; } else { val = fw->Desk; } break; case VAR_W_LAYER: if (!fw || IS_EWMH_DESKTOP(FW_W(fw))) { return -1; } is_numeric = True; val = fw->layer; break; case VAR_W_SCREEN: if (!fw || IS_EWMH_DESKTOP(FW_W(fw))) { return -1; } else { is_numeric = True; rectangle g; get_unshaded_geometry(fw, &g); val = FScreenOfPointerXY(g.x, g.y); } break; case VAR_SCREEN: is_numeric = True; val = Scr.screen; break; case VAR_SCHEDULE_LAST: is_numeric = True; val = squeue_get_last_id(); break; case VAR_SCHEDULE_NEXT: is_numeric = True; val = squeue_get_next_id(); break; case VAR_COND_RC: if (cond_rc == NULL) { return -1; } switch (cond_rc->rc) { case COND_RC_OK: case COND_RC_NO_MATCH: case COND_RC_ERROR: case COND_RC_BREAK: val = (int)(cond_rc->rc); break; default: return -1; } is_numeric = True; break; case VAR_POINTER_X: case VAR_POINTER_Y: if (is_numeric == False) { is_numeric = True; context_w = Scr.Root; } /* fall through */ case VAR_POINTER_WX: case VAR_POINTER_WY: if (is_numeric == False) { if (!fw || IS_ICONIFIED(fw) || IS_EWMH_DESKTOP(FW_W(fw))) { return -1; } is_numeric = True; context_w = FW_W_FRAME(fw); } /* fall through */ case VAR_POINTER_CX: case VAR_POINTER_CY: if (is_numeric == False) { if (!fw || IS_ICONIFIED(fw) || IS_SHADED(fw) || IS_EWMH_DESKTOP(FW_W(fw))) { return -1; } is_numeric = True; context_w = FW_W(fw); } is_x = False; switch (i) { case VAR_POINTER_X: case VAR_POINTER_WX: case VAR_POINTER_CX: is_x = True; } if (FQueryPointer(dpy, context_w, &JunkRoot, &JunkChild, &JunkX, &JunkY, &x, &y, &JunkMask) == False) { /* pointer is on a different screen, don't expand */ return -1; } val = (is_x) ? x : y; break; case VAR_POINTER_SCREEN: is_numeric = True; FQueryPointer(dpy, context_w, &JunkRoot, &JunkChild, &JunkX, &JunkY, &x, &y, &JunkMask); val = FScreenOfPointerXY(x, y); break; case VAR_VERSION_NUM: string = VERSION; break; case VAR_VERSION_INFO: string = VERSIONINFO; break; case VAR_VERSION_LINE: string = Fvwm_VersionInfo; break; case VAR_FUNC_CONTEXT: is_target = True; target[0] = wcontext_wcontext_to_char(exc->w.wcontext); target[1] = '\0'; break; default: /* unknown variable - try to find it in the environment */ string = getenv(var_name); if (!string) { /* Replace it with unexpanded variable. This is needed * since var_name might have been expanded */ l = strlen(var_name) + 3; if (output) { strcpy(output, "$["); strcpy(output + 2, var_name); output[l - 1] = ']'; output[l] = 0; } return l; } } GOT_STRING: if (is_numeric) { is_target = True; sprintf(target, "%d", val); } if (is_target) { string = target; } else { if (!string) { return -1; } if (output) { strcpy(output, string); } } if (len < 0) { len = strlen(string); } if (should_quote) { quoted_string = (char *)safemalloc(len * 2 + 3); len = QuoteString(quoted_string, string) - quoted_string; if (output) { strcpy(output, quoted_string); } free(quoted_string); } if (allocated_string) { free(allocated_string); } return len; } /* ---------------------------- interface functions ------------------------ */ char *expand_vars( char *input, char *arguments[], Bool addto, Bool ismod, cond_rc_t *cond_rc, const exec_context_t *exc) { int l, i, l2, n, k, j, m; int xlen, xlevel; Bool name_has_dollar; char *out; char *var; const char *string = NULL; Bool is_string = False; FvwmWindow *fw = exc->w.fw; l = strlen(input); l2 = l; if (input[0] == '+' && Scr.last_added_item.type == ADDED_FUNCTION) { addto = 1; } /* Calculate best guess at length of expanded string */ i = 0; while (i < l) { if (input[i] == '$' && (!ismod || !isalpha(input[i + 1]))) { switch (input[i + 1]) { case '$': /* skip the second $, it is not a part of * variable */ i++; break; case '[': /* extended variables */ m = i + 2; var = &input[m]; xlevel = 1; name_has_dollar = False; while (m < l && xlevel && input[m]) { /* handle nested variables */ if (input[m] == ']') { xlevel--; } else if (input[m] == '[') { xlevel++; } else if (input[m] == '$') { name_has_dollar = True; } if (xlevel) { m++; } } if (input[m] == ']') { input[m] = 0; /* handle variable name */ k = strlen(var); if (addto) { i += k + 2; input[m] = ']'; break; } if (name_has_dollar) { var = expand_vars( var, arguments, addto, ismod, cond_rc, exc); } xlen = expand_args_extended( var, arguments ? arguments[0] : NULL, NULL); if (xlen < 0) { xlen = expand_vars_extended( var, NULL, cond_rc, exc); } if (name_has_dollar) { free(var); } if (xlen >= 0) { l2 += xlen - (k + 2); } i += k + 2; input[m] = ']'; } break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '*': if (input[i + 1] == '*') { n = 0; } else { n = input[i + 1] - '0' + 1; } if (arguments[n] != NULL) { l2 += strlen(arguments[n]) - 2; i++; } break; case '.': string = get_current_read_dir(); break; case 'w': case 'd': case 'x': case 'y': l2 += 16; i++; break; case 'c': case 'r': case 'n': if (fw && !IS_EWMH_DESKTOP(FW_W(fw))) { switch(input[i + 1]) { case 'c': if (fw->class.res_class && fw->class.res_class[0]) { string = fw->class. res_class; } break; case 'r': if (fw->class.res_name && fw->class.res_name[0]) { string = fw->class. res_name; } break; case 'n': if (fw->name.name && fw->name.name[0]) { string = fw->name.name; } break; } } break; case 'v': if (fw && !IS_EWMH_DESKTOP(FW_W(fw))) { switch(input[i + 1]) { case 'v': if(fw->visible_name) { string = fw->visible_name; } break; } } if (Fvwm_VersionInfo) { l2 += strlen(Fvwm_VersionInfo) + 2; } break; } if (string) { for (k = 0; string[k] != 0; k++, l2++) { if (string[k] == '\'') { l2++; } } string = NULL; } } i++; } /* Actually create expanded string */ i = 0; out = safemalloc(l2 + 1); j = 0; while (i < l) { if (input[i] == '$' && (!ismod || !isalpha(input[i + 1]))) { switch (input[i + 1]) { case '[': /* extended variables */ if (addto) { /* Don't expand these in an 'AddToFunc' * command */ out[j++] = input[i]; break; } m = i + 2; var = &input[m]; xlevel = 1; name_has_dollar = False; while (m < l && xlevel && input[m]) { /* handle nested variables */ if (input[m] == ']') { xlevel--; } else if (input[m] == '[') { xlevel++; } else if (input[m] == '$') { name_has_dollar = True; } if (xlevel) { m++; } } if (input[m] == ']') { input[m] = 0; /* handle variable name */ k = strlen(var); if (name_has_dollar) { var = expand_vars( var, arguments, addto, ismod, cond_rc, exc); } xlen = expand_args_extended( var, arguments ? arguments[0] : NULL, &out[j]); if (xlen < 0) { xlen = expand_vars_extended( var, &out[j], cond_rc, exc); } if (name_has_dollar) { free(var); } input[m] = ']'; if (xlen >= 0) { j += xlen; i += k + 2; } else { /* copy the whole string in * square brackets */ for ( ; i <= m; i++, j++) { out[j] = input[i]; } i--; } } else { out[j++] = input[i]; } break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '*': if (input[i + 1] == '*') { n = 0; } else { n = input[i + 1] - '0' + 1; } if (arguments[n] != NULL) { for (k = 0; arguments[n][k]; k++) { out[j++] = arguments[n][k]; } i++; } else if (addto == 1) { out[j++] = '$'; } else { i++; } break; case '.': string = get_current_read_dir(); is_string = True; break; case 'w': if (fw && !IS_EWMH_DESKTOP(FW_W(fw))) { fvwm_msg(OLD, "expand_vars", "Use $[w.id] instead of $w"); sprintf(&out[j], "0x%x", (int)FW_W(fw)); } else { sprintf(&out[j], "$w"); } j += strlen(&out[j]); i++; break; case 'd': fvwm_msg(OLD, "expand_vars", "Use $[desk.n] instead of $d"); sprintf(&out[j], "%d", Scr.CurrentDesk); j += strlen(&out[j]); i++; break; case 'x': fvwm_msg(OLD, "expand_vars", "Use $[vp.x] instead of $x"); sprintf(&out[j], "%d", Scr.Vx); j += strlen(&out[j]); i++; break; case 'y': fvwm_msg(OLD, "expand_vars", "Use $[vp.y] instead of $y"); sprintf(&out[j], "%d", Scr.Vy); j += strlen(&out[j]); i++; break; case 'c': case 'r': case 'n': if (fw && !IS_EWMH_DESKTOP(FW_W(fw))) { switch(input[i + 1]) { case 'c': fvwm_msg(OLD, "expand_vars", "Use $[w.class] " "instead of $c"); if (fw->class.res_class && fw->class.res_class[0]) { string = fw->class. res_class; } break; case 'r': fvwm_msg(OLD, "expand_vars", "Use $[w.resource] " "instead of $r"); if (fw->class.res_name && fw->class.res_name[0]) { string = fw->class. res_name; } break; case 'n': fvwm_msg(OLD, "expand_vars", "Use $[w.name] " "instead of $n"); if (fw->name.name && fw->name.name[0]) { string = fw->name.name; } break; } } is_string = True; break; case 'v': fvwm_msg(OLD, "expand_vars", "Use $[version.line] instead of $v"); sprintf(&out[j], "%s", (Fvwm_VersionInfo) ? Fvwm_VersionInfo : ""); j += strlen(&out[j]); i++; break; case '$': out[j++] = '$'; i++; break; default: out[j++] = input[i]; break; } /* switch */ if (is_string && string) { j = QuoteString(&out[j], string) - out; string = NULL; is_string = False; i++; } else if (is_string) { out[j++] = '$'; is_string = False; } } /* if '$' */ else { out[j++] = input[i]; } i++; } out[j] = 0; return out; } fvwm-2.7.0/fvwm/ewmh_intern.h0000644000175000017500000001425114147024700013071 00000000000000/* -*-c-*- */ /* Copyright (C) 2001 Olivier Chapuis */ #ifndef _EWMH_INTERN_ #define _EWMH_INTERN_ /* Extended window manager hints support */ /* #define EWMH_DEBUG */ #ifdef EWMH_DEBUG #include #include #include "ftime.h" #endif typedef struct ewmh_atom { char *name; Atom atom; Atom atom_type; #ifdef __STDC__ int (*action)(FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); #else int (*action)(); #endif } ewmh_atom; typedef enum { EWMH_ATOM_LIST_ALL, EWMH_ATOM_LIST_CLIENT_ROOT, EWMH_ATOM_LIST_CLIENT_WIN, EWMH_ATOM_LIST_WM_STATE, EWMH_ATOM_LIST_ALLOWED_ACTIONS, EWMH_ATOM_LIST_WINDOW_TYPE, EWMH_ATOM_LIST_FIXED_PROPERTY, EWMH_ATOM_LIST_PROPERTY_NOTIFY, EWMH_ATOM_LIST_FVWM_ROOT, EWMH_ATOM_LIST_FVWM_WIN, EWMH_ATOM_LIST_END } ewmh_atom_list_name; typedef struct { ewmh_atom_list_name name; ewmh_atom *list; int size; } ewmh_atom_list; #define NET_WM_STATE_ADD 1 #define NET_WM_STATE_REMOVE 0 #define NET_WM_STATE_TOGGLE 2 #define EWMH_MAXIMIZE_HORIZ 0x1 #define EWMH_MAXIMIZE_VERT 0x2 #define EWMH_MAXIMIZE_FULL 0x3 #define EWMH_MAXIMIZE_REMOVE 0x4 #define EWMH_MAXIMIZE_FULLSCREEN 0x8 typedef enum { _NET_WM_MOVERESIZE_SIZE_TOPLEFT, _NET_WM_MOVERESIZE_SIZE_TOP, _NET_WM_MOVERESIZE_SIZE_TOPRIGHT, _NET_WM_MOVERESIZE_SIZE_RIGHT, _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT, _NET_WM_MOVERESIZE_SIZE_BOTTOM, _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT, _NET_WM_MOVERESIZE_SIZE_LEFT, _NET_WM_MOVERESIZE_MOVE, _NET_WM_MOVERESIZE_SIZE_KEYBOARD, _NET_WM_MOVERESIZE_MOVE_KEYBOARD } ewmh_move_resize; typedef struct ewmh_info { unsigned NumberOfDesktops; unsigned MaxDesktops; unsigned CurrentNumberOfDesktops; Bool NeedsToCheckDesk; ewmh_strut BaseStrut; } ewmhInfo; extern ewmhInfo ewmhc; ewmh_atom *ewmh_GetEwmhAtomByAtom(Atom atom, ewmh_atom_list_name list_name); void ewmh_ChangeProperty( Window w, const char *atom_name, ewmh_atom_list_name list, unsigned char *data, int length); void ewmh_DeleteProperty( Window w, const char *atom_name, ewmh_atom_list_name list); void *ewmh_AtomGetByName( Window win, const char *atom_name, ewmh_atom_list_name list, int *size); int ewmh_HandleDesktop( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_HandleDialog( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_HandleDock( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_HandleMenu( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_HandleNormal( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_HandleToolBar( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_HandleNotification( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); void ewmh_AddToKdeSysTray(FvwmWindow *fw); void ewmh_SetWorkArea(void); void ewmh_ComputeAndSetWorkArea(void); void ewmh_HandleDynamicWorkArea(void); void ewmh_HandleWindowType(FvwmWindow *fw, window_style *style); int ewmh_CurrentDesktop( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_DesktopGeometry( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_DesktopViewPort( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_NumberOfDesktops( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_ActiveWindow( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_CloseWindow( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_MoveResizeWindow( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_RestackWindow( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_WMDesktop( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_MoveResize( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_WMState( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_WMStateFullScreen( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_WMStateHidden( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_WMStateMaxHoriz( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_WMStateMaxVert( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_WMStateModal( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_WMStateShaded( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_WMStateSkipPager( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_WMStateSkipTaskBar( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_WMStateStaysOnTop( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_WMStateStaysOnBottom( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_WMStateSticky( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_WMIconGeometry( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int ewmh_WMStrut( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); Bool ewmh_AllowsYes( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); Bool ewmh_AllowsClose( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); Bool ewmh_AllowsFullScreen( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); Bool ewmh_AllowsMinimize( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); Bool ewmh_AllowsMaximize( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); Bool ewmh_AllowsMove( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); Bool ewmh_AllowsResize( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); /* ewmh_icon */ int ewmh_WMIcon( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); CARD32 *ewmh_SetWmIconFromPixmap( FvwmWindow *fw, CARD32 *orig_icon, int *orig_size, Bool is_mini_icon); /* debugging */ #ifdef EWMH_DEBUG void EWMH_DLOG(char *msg, ...); #else #endif #endif /* _EWMH_INTERN_ */ fvwm-2.7.0/fvwm/menucmd.c0000644000175000017500000001517214147024700012200 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* IMPORTANT NOTE: Do *not* use any constant numbers in this file. All values * have to be #defined in the section below or defaults.h to ensure full * control over the menus. */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include "libs/Parse.h" #include "libs/Strings.h" #include "fvwm.h" #include "functions.h" #include "repeat.h" #include "misc.h" #include "move_resize.h" #include "screen.h" #include "menus.h" #include "menudim.h" #include "menuroot.h" #include "menustyle.h" #include "menuparameters.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ static void menu_func(F_CMD_ARGS, Bool fStaysUp) { struct MenuRoot *menu; char *ret_action = NULL; struct MenuOptions mops; char *menu_name = NULL; struct MenuParameters mp; struct MenuReturn mret; FvwmWindow * const fw = exc->w.fw; const Window w = exc->w.w; const exec_context_t *exc2; memset(&mops, 0, sizeof(mops)); memset(&mret, 0, sizeof(MenuReturn)); action = GetNextToken(action,&menu_name); action = get_menu_options( action, w, fw, NULL, NULL, NULL, &mops); while (action && *action && isspace((unsigned char)*action)) { action++; } if (action && *action == 0) { action = NULL; } menu = menus_find_menu(menu_name); if (menu == NULL) { if (menu_name) { fvwm_msg(ERR,"menu_func","No such menu %s",menu_name); free(menu_name); } return; } if (menu_name && set_repeat_data( menu_name, (fStaysUp) ? REPEAT_MENU : REPEAT_POPUP,NULL)) { free(menu_name); } memset(&mp, 0, sizeof(mp)); mp.menu = menu; exc2 = exc_clone_context(exc, NULL, 0); mp.pexc = &exc2; MR_IS_TEAR_OFF_MENU(menu) = 0; mp.flags.has_default_action = (action != NULL); mp.flags.is_sticky = fStaysUp; mp.flags.is_submenu = False; mp.flags.is_already_mapped = False; mp.flags.is_triggered_by_keypress = (exc->x.etrigger->type == KeyPress); mp.pops = &mops; mp.ret_paction = &ret_action; do_menu(&mp, &mret); if (mret.rc == MENU_DOUBLE_CLICKED && action) { execute_function(cond_rc, exc2, action, 0); } if (ret_action != NULL) { free(ret_action); } exc_destroy_context(exc2); return; } /* ---------------------------- interface functions ------------------------ */ /* ---------------------------- builtin commands --------------------------- */ /* the function for the "Popup" command */ void CMD_Popup(F_CMD_ARGS) { menu_func(F_PASS_ARGS, False); return; } /* the function for the "Menu" command */ void CMD_Menu(F_CMD_ARGS) { menu_func(F_PASS_ARGS, True); return; } void CMD_AddToMenu(F_CMD_ARGS) { MenuRoot *mr; MenuRoot *mrPrior; char *token, *rest,*item; token = PeekToken(action, &rest); if (!token) { return; } mr = menus_find_menu(token); if (mr && MR_MAPPED_COPIES(mr) != 0) { fvwm_msg(ERR,"add_item_to_menu", "menu %s is in use", token); return; } mr = FollowMenuContinuations(menus_find_menu(token), &mrPrior); if (mr == NULL) { mr = NewMenuRoot(token); } /* Set + state to last menu */ set_last_added_item(ADDED_MENU, mr); rest = GetNextToken(rest, &item); AddToMenu(mr, item, rest, True /* pixmap scan */, True, False); if (item) { free(item); } return; } void CMD_DestroyMenu(F_CMD_ARGS) { MenuRoot *mr; MenuRoot *mrContinuation; Bool do_recreate = False; char *token; token = PeekToken(action, &action); if (!token) { return; } if (StrEquals(token, "recreate")) { do_recreate = True; token = PeekToken(action, NULL); } mr = menus_find_menu(token); if (Scr.last_added_item.type == ADDED_MENU) { set_last_added_item(ADDED_NONE, NULL); } while (mr) { /* save continuation before destroy */ mrContinuation = MR_CONTINUATION_MENU(mr); if (!DestroyMenu(mr, do_recreate, True)) { return; } /* Don't recreate the continuations */ do_recreate = False; mr = mrContinuation; } return; } void CMD_DestroyMenuStyle(F_CMD_ARGS) { MenuStyle *ms = NULL; char *name = NULL; name = PeekToken(action, NULL); if (name == NULL) { fvwm_msg(ERR,"DestroyMenuStyle", "needs one parameter"); return; } ms = menustyle_find(name); if (ms == NULL) { return; } else if (ms == menustyle_get_default_style()) { fvwm_msg(ERR,"DestroyMenuStyle", "cannot destroy default menu style. " "To reset the default menu style use\n %s", DEFAULT_MENU_STYLE); return; } else if (ST_USAGE_COUNT(ms) != 0) { fvwm_msg(ERR, "DestroyMenuStyle", "menu style %s is in use", name); return; } else { menustyle_free(ms); } menus_remove_style_from_menus(ms); return; } void CMD_ChangeMenuStyle(F_CMD_ARGS) { char *name = NULL; char *menuname = NULL; MenuStyle *ms = NULL; MenuRoot *mr = NULL; name = PeekToken(action, &action); if (name == NULL) { fvwm_msg(ERR,"ChangeMenuStyle", "needs at least two parameters"); return; } ms = menustyle_find(name); if (ms == NULL) { fvwm_msg(ERR,"ChangeMenuStyle", "cannot find style %s", name); return; } menuname = PeekToken(action, &action); while (menuname && *menuname) { mr = menus_find_menu(menuname); if (mr == NULL) { fvwm_msg(ERR, "ChangeMenuStyle", "cannot find menu %s", menuname); break; } if (MR_MAPPED_COPIES(mr) != 0) { fvwm_msg(ERR, "ChangeMenuStyle", "menu %s is in use", menuname); } else { MR_STYLE(mr) = ms; MR_IS_UPDATED(mr) = 1; } menuname = PeekToken(action, &action); } return; } fvwm-2.7.0/fvwm/menustyle.c0000644000175000017500000013316214147024700012575 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include #include "libs/fvwmlib.h" #include "libs/Parse.h" #include "libs/ColorUtils.h" #include "libs/Picture.h" #include "libs/PictureUtils.h" #include "libs/Graphics.h" #include "fvwm.h" #include "externs.h" #include "execcontext.h" #include "functions.h" #include "misc.h" #include "screen.h" #include "colorset.h" #include "menustyle.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ static MenuStyle *default_menu_style; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ static void menustyle_free_face(MenuFace *mf) { switch (mf->type) { case GradientMenu: if (Pdepth <= 8 && mf->u.grad.npixels > 0 && !mf->u.grad.do_dither) { Pixel *p; int i; p = (Pixel *)safemalloc( mf->u.grad.npixels * sizeof(Pixel)); for(i=0; i < mf->u.grad.npixels; i++) { p[i] = mf->u.grad.xcs[i].pixel; } PictureFreeColors( dpy, Pcmap, p, mf->u.grad.npixels, 0, False); free(p); } free(mf->u.grad.xcs); mf->u.grad.xcs = NULL; break; case PixmapMenu: case TiledPixmapMenu: if (mf->u.p) { PDestroyFvwmPicture(dpy, mf->u.p); } mf->u.p = NULL; break; case SolidMenu: fvwmlib_free_colors(dpy, &mf->u.back, 1, True); default: break; } mf->type = SimpleMenu; return; } static void menustyle_copy_face(MenuFace *destmf, MenuFace *origmf) { FvwmPictureAttributes fpa; int i; menustyle_free_face(destmf); destmf->type = SimpleMenu; switch (origmf->type) { case SolidMenu: fvwmlib_copy_color( dpy, &destmf->u.back, &origmf->u.back, False, True); destmf->type = SolidMenu; break; case GradientMenu: destmf->u.grad.xcs = (XColor *)safemalloc(sizeof(XColor) * origmf->u.grad.npixels); memcpy(destmf->u.grad.xcs, origmf->u.grad.xcs, sizeof(XColor) * origmf->u.grad.npixels); for (i = 0; iu.grad.npixels;i++) { fvwmlib_clone_color(origmf->u.grad.xcs[i].pixel); } destmf->u.grad.npixels = origmf->u.grad.npixels; destmf->u.grad.do_dither = origmf->u.grad.do_dither; destmf->type = GradientMenu; destmf->gradient_type = origmf->gradient_type; break; case PixmapMenu: case TiledPixmapMenu: fpa.mask = (Pdepth <= 8)? FPAM_DITHER:0; if (destmf->u.p) destmf->u.p = NULL; if (origmf->u.p) destmf->u.p = PCacheFvwmPicture( dpy, Scr.NoFocusWin, NULL, origmf->u.p->name, fpa); destmf->type = origmf->type; break; default: break; } } /* * * Reads a menu face line into a structure (veliaa@rpi.edu) * */ static Boolean menustyle_parse_face(char *s, MenuFace *mf, int verbose) { char *style; char *token; char *action = s; FvwmPictureAttributes fpa; s = GetNextToken(s, &style); if (style && strncasecmp(style, "--", 2) == 0) { free(style); return True; } menustyle_free_face(mf); mf->type = SimpleMenu; /* determine menu style */ if (!style) { return True; } else if (StrEquals(style,"Solid")) { s = GetNextToken(s, &token); if (token) { mf->type = SolidMenu; mf->u.back = GetColor(token); free(token); } else { if (verbose) { fvwm_msg(ERR, "menustyle_parse_face", "no color given for Solid face type:" " %s", action); } free(style); return False; } } else if (StrEquals(style+1, "Gradient")) { char **s_colors; int npixels, nsegs, *perc; XColor *xcs; if (!IsGradientTypeSupported(style[0])) { return False; } /* translate the gradient string into an array of colors etc */ npixels = ParseGradient(s, NULL, &s_colors, &perc, &nsegs); if (npixels <= 0) { return False; } /* dither ? */ mf->u.grad.do_dither = False; if (Pdepth <= 8) { mf->u.grad.do_dither = True; } /* grab the colors */ xcs = AllocAllGradientColors( s_colors, perc, nsegs, npixels, mf->u.grad.do_dither); if (xcs == None) { return False; } mf->u.grad.xcs = xcs; mf->u.grad.npixels = npixels; mf->type = GradientMenu; mf->gradient_type = toupper(style[0]); } else if (StrEquals(style,"Pixmap") || StrEquals(style,"TiledPixmap")) { s = GetNextToken(s, &token); fpa.mask = (Pdepth <= 8)? FPAM_DITHER:0; if (token) { mf->u.p = PCacheFvwmPicture( dpy, Scr.NoFocusWin, NULL, token, fpa); if (mf->u.p == NULL) { if (verbose) { fvwm_msg(ERR, "menustyle_parse_face", "couldn't load pixmap %s", token); } free(token); free(style); return False; } free(token); mf->type = (StrEquals(style,"TiledPixmap")) ? TiledPixmapMenu : PixmapMenu; } else { if (verbose) { fvwm_msg(ERR, "menustyle_parse_face", "missing pixmap name for style %s", style); } free(style); return False; } } else { if (verbose) { fvwm_msg( ERR, "menustyle_parse_face", "unknown style %s: %s", style, action); } free(style); return False; } free(style); return True; } static void parse_vertical_spacing_line( char *args, signed char *above, signed char *below, signed char above_default, signed char below_default) { int val[2]; if (GetIntegerArguments(args, NULL, val, 2) != 2 || val[0] < MIN_VERTICAL_SPACING || val[0] > MAX_VERTICAL_SPACING || val[1] < MIN_VERTICAL_SPACING || val[1] > MAX_VERTICAL_SPACING) { /* illegal or missing parameters, return to default */ *above = above_default; *below = below_default; return; } *above = val[0]; *below = val[1]; return; } static void parse_vertical_margins_line( char *args, unsigned char *top, unsigned char *bottom, signed char top_default, signed char bottom_default) { int val[2]; if (GetIntegerArguments(args, NULL, val, 2) != 2 || val[0] < 0 || val[0] > MAX_MENU_MARGIN || val[1] < 0 || val[1] > MAX_MENU_MARGIN) { /* invalid or missing parameters, return to default */ *top = top_default; *bottom = bottom_default; return; } *top = val[0]; *bottom = val[1]; return; } static MenuStyle *menustyle_parse_old_style(F_CMD_ARGS) { char *buffer, *rest; char *fore, *back, *stipple, *font, *style, *animated; MenuStyle *ms = NULL; rest = GetNextToken(action,&fore); rest = GetNextToken(rest,&back); rest = GetNextToken(rest,&stipple); rest = GetNextToken(rest,&font); rest = GetNextToken(rest,&style); rest = GetNextToken(rest,&animated); if (!fore || !back || !stipple || !font || !style) { fvwm_msg(ERR, "menustyle_parse_old_style", "error in %s style specification", action); } else { buffer = (char *)alloca(strlen(action) + 100); sprintf(buffer, "* \"%s\", Foreground \"%s\", Background \"%s\", " "Greyed \"%s\", Font \"%s\", \"%s\"", style, fore, back, stipple, font, (animated && StrEquals(animated, "anim")) ? "Animation" : "AnimationOff"); fvwm_msg(OLD, "menustyle_parse_old_style", "The old MenuStyle snytax has been deprecated. " "Use 'MenuStyle %s' instead of 'MenuStyle %s'\n", buffer, action); action = buffer; ms = menustyle_parse_style(F_PASS_ARGS); } if (fore) { free(fore); } if (back) { free(back); } if (stipple) { free(stipple); } if (font) { free(font); } if (style) { free(style); } if (animated) { free(animated); } return ms; } static int menustyle_get_styleopt_index(char *option) { char *optlist[] = { "fvwm", "mwm", "win", "Foreground", "Background", "Greyed", "HilightBack", "HilightBackOff", "ActiveFore", "ActiveForeOff", "Hilight3DThick", "Hilight3DThin", "Hilight3DOff", "Animation", "AnimationOff", "Font", "MenuFace", "PopupDelay", "PopupOffset", "TitleWarp", "TitleWarpOff", "TitleUnderlines0", "TitleUnderlines1", "TitleUnderlines2", "SeparatorsLong", "SeparatorsShort", "TrianglesSolid", "TrianglesRelief", "PopupImmediately", "PopupDelayed", "DoubleClickTime", "SidePic", "SideColor", "PopupAsRootmenu", "PopupAsSubmenu", "RemoveSubmenus", "HoldSubmenus", "SubmenusRight", "SubmenusLeft", "BorderWidth", "Hilight3DThickness", "ItemFormat", "AutomaticHotkeys", "AutomaticHotkeysOff", "VerticalItemSpacing", "VerticalTitleSpacing", "MenuColorset", "ActiveColorset", "GreyedColorset", "SelectOnRelease", "PopdownImmediately", "PopdownDelayed", "PopdownDelay", "PopupActiveArea", "PopupIgnore", "PopupClose", "MouseWheel", "ScrollOffPage", "TrianglesUseFore", "TitleColorset", "HilightTitleBack", "TitleFont", "VerticalMargins", "UniqueHotkeyActivatesImmediate", NULL }; return GetTokenIndex(option, optlist, 0, NULL); } static void change_or_make_gc(GC *gc, unsigned long gcm, XGCValues *gcv) { if (*gc != None) { XChangeGC(dpy, *gc, gcm, gcv); } else { *gc = fvwmlib_XCreateGC(dpy, Scr.NoFocusWin, gcm, gcv); } return; } /* ---------------------------- interface functions ------------------------ */ MenuStyle *menustyle_get_default_style(void) { return default_menu_style; } void menustyle_free(MenuStyle *ms) { MenuStyle *before = default_menu_style; if (!ms) { return; } menustyle_free_face(&ST_FACE(ms)); if (FORE_GC(ST_MENU_INACTIVE_GCS(ms))) { XFreeGC(dpy, FORE_GC(ST_MENU_INACTIVE_GCS(ms))); } if (FORE_GC(ST_MENU_ACTIVE_GCS(ms))) { XFreeGC(dpy, FORE_GC(ST_MENU_ACTIVE_GCS(ms))); } if (BACK_GC(ST_MENU_ACTIVE_GCS(ms))) { XFreeGC(dpy, BACK_GC(ST_MENU_ACTIVE_GCS(ms))); } if (HILIGHT_GC(ST_MENU_ACTIVE_GCS(ms))) { XFreeGC(dpy, HILIGHT_GC(ST_MENU_ACTIVE_GCS(ms))); } if (SHADOW_GC(ST_MENU_ACTIVE_GCS(ms))) { XFreeGC(dpy, SHADOW_GC(ST_MENU_ACTIVE_GCS(ms))); } if (HILIGHT_GC(ST_MENU_INACTIVE_GCS(ms))) { XFreeGC(dpy, HILIGHT_GC(ST_MENU_INACTIVE_GCS(ms))); } if (SHADOW_GC(ST_MENU_INACTIVE_GCS(ms))) { XFreeGC(dpy, SHADOW_GC(ST_MENU_INACTIVE_GCS(ms))); } if (FORE_GC(ST_MENU_STIPPLE_GCS(ms))) { XFreeGC(dpy, FORE_GC(ST_MENU_STIPPLE_GCS(ms))); } if (FORE_GC(ST_MENU_TITLE_GCS(ms))) { XFreeGC(dpy, FORE_GC(ST_MENU_TITLE_GCS(ms))); } if (BACK_GC(ST_MENU_TITLE_GCS(ms))) { XFreeGC(dpy, BACK_GC(ST_MENU_TITLE_GCS(ms))); } if (HILIGHT_GC(ST_MENU_TITLE_GCS(ms))) { XFreeGC(dpy, HILIGHT_GC(ST_MENU_TITLE_GCS(ms))); } if (SHADOW_GC(ST_MENU_TITLE_GCS(ms))) { XFreeGC(dpy, SHADOW_GC(ST_MENU_TITLE_GCS(ms))); } if (ST_SIDEPIC(ms)) { PDestroyFvwmPicture(dpy, ST_SIDEPIC(ms)); } if (ST_HAS_SIDE_COLOR(ms) == 1) { fvwmlib_free_colors(dpy, &ST_SIDE_COLOR(ms), 1, True); } if (ST_PSTDFONT(ms) && !ST_USING_DEFAULT_FONT(ms)) { FlocaleUnloadFont(dpy, ST_PSTDFONT(ms)); } if (ST_PTITLEFONT(ms) && !ST_USING_DEFAULT_TITLEFONT(ms)) { FlocaleUnloadFont(dpy, ST_PTITLEFONT(ms)); } if (ST_ITEM_FORMAT(ms)) { free(ST_ITEM_FORMAT(ms)); } fvwmlib_free_colors(dpy, &ST_MENU_COLORS(ms).back,1,True); fvwmlib_free_colors(dpy, &ST_MENU_COLORS(ms).fore,1,True); if (ST_HAS_STIPPLE_FORE(ms)) { fvwmlib_free_colors( dpy, &ST_MENU_STIPPLE_COLORS(ms).fore,1,True); } if (ST_HAS_ACTIVE_BACK(ms)) { fvwmlib_free_colors( dpy, &ST_MENU_ACTIVE_COLORS(ms).back,1,True); } if (ST_HAS_ACTIVE_FORE(ms)) { fvwmlib_free_colors( dpy, &ST_MENU_ACTIVE_COLORS(ms).fore,1,True); } while (ST_NEXT_STYLE(before) != ms) { /* Not too many checks, may segfault in race conditions */ before = ST_NEXT_STYLE(before); } ST_NEXT_STYLE(before) = ST_NEXT_STYLE(ms); free(ST_NAME(ms)); free(ms); return; } MenuStyle *menustyle_find(char *name) { MenuStyle *ms = default_menu_style; while (ms) { if (strcasecmp(ST_NAME(ms),name)==0) { return ms; } ms = ST_NEXT_STYLE(ms); } return NULL; } void menustyle_update(MenuStyle *ms) { XGCValues gcv; unsigned long gcm; color_quad c_inactive; color_quad c_active; color_quad c_stipple; color_quad c_title; colorset_t *menu_cs = &Colorset[ST_CSET_MENU(ms)]; colorset_t *active_cs = &Colorset[ST_CSET_ACTIVE(ms)]; colorset_t *greyed_cs = &Colorset[ST_CSET_GREYED(ms)]; colorset_t *title_cs = &Colorset[ST_CSET_TITLE(ms)]; if (ST_USAGE_COUNT(ms) != 0) { fvwm_msg(ERR,"menustyle_update", "menu style %s is in use", ST_NAME(ms)); return; } ST_IS_UPDATED(ms) = 1; if (ST_USING_DEFAULT_FONT(ms)) { ST_PSTDFONT(ms) = Scr.DefaultFont; } if (ST_USING_DEFAULT_TITLEFONT(ms)) { ST_PTITLEFONT(ms) = ST_PSTDFONT(ms); } /* calculate colors based on foreground */ if (!ST_HAS_ACTIVE_FORE(ms)) { ST_MENU_ACTIVE_COLORS(ms).fore = ST_MENU_COLORS(ms).fore; } /* calculate colors based on background */ if (!ST_HAS_ACTIVE_BACK(ms)) { ST_MENU_ACTIVE_COLORS(ms).back = ST_MENU_COLORS(ms).back; } if (!ST_HAS_STIPPLE_FORE(ms)) { ST_MENU_STIPPLE_COLORS(ms).fore = ST_MENU_COLORS(ms).back; } ST_MENU_STIPPLE_COLORS(ms).back = ST_MENU_COLORS(ms).back; /* prepare colours for changing the gcs */ if (ST_HAS_MENU_CSET(ms)) { c_inactive.fore = menu_cs->fg; c_inactive.back = menu_cs->bg; c_inactive.hilight = menu_cs->hilite; c_inactive.shadow = menu_cs->shadow; } else { c_inactive.fore = ST_MENU_COLORS(ms).fore; c_inactive.back = ST_MENU_COLORS(ms).back; if (Pdepth > 2) { c_inactive.hilight = GetHilite(ST_MENU_COLORS(ms).back); c_inactive.shadow = GetShadow(ST_MENU_COLORS(ms).back); } else { c_inactive.hilight = GetColor(DEFAULT_HILIGHT_COLOR); c_inactive.shadow = GetColor(DEFAULT_SHADOW_COLOR); } } if (ST_HAS_ACTIVE_CSET(ms)) { c_active.fore = active_cs->fg; c_active.back = active_cs->bg; c_active.hilight = active_cs->hilite; c_active.shadow = active_cs->shadow; } else { c_active.fore = ST_MENU_ACTIVE_COLORS(ms).fore; c_active.back = ST_MENU_ACTIVE_COLORS(ms).back; if (Pdepth > 2) { c_active.hilight = GetHilite(ST_MENU_ACTIVE_COLORS(ms).back); c_active.shadow = GetShadow(ST_MENU_ACTIVE_COLORS(ms).back); } else { c_active.hilight = GetColor(DEFAULT_HILIGHT_COLOR); c_active.shadow = GetColor(DEFAULT_SHADOW_COLOR); } } if (ST_HAS_GREYED_CSET(ms)) { c_stipple.fore = greyed_cs->fg; c_stipple.back = greyed_cs->fg; } else { c_stipple.fore = ST_MENU_STIPPLE_COLORS(ms).fore; c_stipple.back = ST_MENU_STIPPLE_COLORS(ms).back; } if (ST_HAS_TITLE_CSET(ms)) { c_title.fore = title_cs->fg; c_title.back = title_cs->bg; c_title.hilight = title_cs->hilite; c_title.shadow = title_cs->shadow; } else { c_title.fore = c_inactive.fore; c_title.back = c_inactive.back; c_title.hilight = c_inactive.hilight; c_title.shadow = c_inactive.shadow; } /* override hilighting colours if necessary */ if (!ST_DO_HILIGHT_FORE(ms)) { c_active.fore = c_inactive.fore; } if (!ST_DO_HILIGHT_BACK(ms)) { c_active.back = c_inactive.back; c_active.hilight = c_inactive.hilight; c_active.shadow = c_inactive.shadow; } if (!ST_DO_HILIGHT_TITLE_BACK(ms)) { c_title.fore = c_inactive.fore; c_title.back = c_inactive.back; c_title.hilight = c_inactive.hilight; c_title.shadow = c_inactive.shadow; } /* make GC's */ gcm = GCFunction|GCLineWidth|GCForeground|GCBackground; if (ST_PSTDFONT(ms)->font != NULL) { gcm |= GCFont; gcv.font = ST_PSTDFONT(ms)->font->fid; } gcv.function = GXcopy; gcv.line_width = 0; /* update inactive menu gcs */ gcv.foreground = c_inactive.fore; gcv.background = c_inactive.back; change_or_make_gc(&FORE_GC(ST_MENU_INACTIVE_GCS(ms)), gcm, &gcv); BACK_GC(ST_MENU_INACTIVE_GCS(ms)) = FORE_GC(ST_MENU_INACTIVE_GCS(ms)); gcv.foreground = c_inactive.hilight; gcv.background = c_inactive.shadow; change_or_make_gc(&HILIGHT_GC(ST_MENU_INACTIVE_GCS(ms)), gcm, &gcv); gcv.foreground = c_inactive.shadow; gcv.background = c_inactive.hilight; change_or_make_gc(&SHADOW_GC(ST_MENU_INACTIVE_GCS(ms)), gcm, &gcv); /* update active menu gcs */ gcv.foreground = c_active.fore; gcv.background = c_active.back; change_or_make_gc(&FORE_GC(ST_MENU_ACTIVE_GCS(ms)), gcm, &gcv); gcv.foreground = c_active.back; gcv.background = c_active.fore; if (ST_HAS_ACTIVE_CSET(ms) && active_cs->pixmap && active_cs->pixmap_type == PIXMAP_TILED) { gcv.tile = active_cs->pixmap; gcv.fill_style = FillTiled; change_or_make_gc(&BACK_GC(ST_MENU_ACTIVE_GCS(ms)), gcm | GCFillStyle | GCTile , &gcv); } else { gcv.fill_style = FillSolid; change_or_make_gc(&BACK_GC(ST_MENU_ACTIVE_GCS(ms)), gcm | GCFillStyle , &gcv); } gcv.foreground = c_active.hilight; gcv.background = c_active.shadow; change_or_make_gc(&HILIGHT_GC(ST_MENU_ACTIVE_GCS(ms)), gcm, &gcv); gcv.foreground = c_active.shadow; gcv.background = c_active.hilight; change_or_make_gc(&SHADOW_GC(ST_MENU_ACTIVE_GCS(ms)), gcm, &gcv); /* update title gcs */ if (ST_PTITLEFONT(ms)->font != NULL && ST_PSTDFONT(ms)->font == NULL) { if (ST_PSTDFONT(ms)->font == NULL) { gcm |= GCFont; } gcv.font = ST_PTITLEFONT(ms)->font->fid; } gcv.foreground = c_title.fore; gcv.background = c_title.back; change_or_make_gc(&FORE_GC(ST_MENU_TITLE_GCS(ms)), gcm, &gcv); gcv.foreground = c_title.back; gcv.background = c_title.fore; if (ST_HAS_TITLE_CSET(ms) && title_cs->pixmap && title_cs->pixmap_type == PIXMAP_TILED) { gcv.tile = title_cs->pixmap; gcv.fill_style = FillTiled; change_or_make_gc(&BACK_GC(ST_MENU_TITLE_GCS(ms)), gcm | GCFillStyle | GCTile , &gcv); } else { gcv.fill_style = FillSolid; change_or_make_gc(&BACK_GC(ST_MENU_TITLE_GCS(ms)), gcm | GCFillStyle , &gcv); } gcv.foreground = c_title.hilight; gcv.background = c_title.shadow; change_or_make_gc(&HILIGHT_GC(ST_MENU_TITLE_GCS(ms)), gcm, &gcv); gcv.foreground = c_title.shadow; gcv.background = c_title.hilight; change_or_make_gc(&SHADOW_GC(ST_MENU_TITLE_GCS(ms)), gcm, &gcv); /* update stipple menu gcs */ SHADOW_GC(ST_MENU_STIPPLE_GCS(ms)) = SHADOW_GC(ST_MENU_INACTIVE_GCS(ms)); if (Pdepth < 2) { gcv.fill_style = FillStippled; gcv.stipple = Scr.gray_bitmap; /* no need to reset fg/bg, FillStipple wins */ gcm |= GCStipple | GCFillStyle; HILIGHT_GC(ST_MENU_STIPPLE_GCS(ms)) = SHADOW_GC(ST_MENU_INACTIVE_GCS(ms)); } else { gcv.foreground = c_stipple.fore; gcv.background = c_stipple.back; HILIGHT_GC(ST_MENU_STIPPLE_GCS(ms)) = HILIGHT_GC(ST_MENU_INACTIVE_GCS(ms)); } change_or_make_gc(&FORE_GC(ST_MENU_STIPPLE_GCS(ms)), gcm, &gcv); BACK_GC(ST_MENU_STIPPLE_GCS(ms)) = BACK_GC(ST_MENU_INACTIVE_GCS(ms)); return; } MenuStyle *menustyle_parse_style(F_CMD_ARGS) { char *name; char *option = NULL; char *poption = NULL; char *optstring = NULL; char *args = NULL; char *arg1; int on; MenuStyle *ms; MenuStyle *tmpms; Bool is_initialised = True; Bool has_gc_changed = False; int val[2]; int n; FlocaleFont *new_font = NULL; int i; KeyCode keycode; FvwmPictureAttributes fpa; action = GetNextToken(action, &name); if (!name) { fvwm_msg(ERR, "NewMenuStyle", "error in %s style specification",action); return NULL; } ms = menustyle_find(name); if (ms && ST_USAGE_COUNT(ms) != 0) { fvwm_msg(ERR,"NewMenuStyle", "menu style %s is in use", name); return ms; } tmpms = (MenuStyle *)safemalloc(sizeof(MenuStyle)); if (ms) { /* copy the structure over our temporary menu face. */ memcpy(tmpms, ms, sizeof(MenuStyle)); free(name); } else { memset(tmpms, 0, sizeof(MenuStyle)); ST_NAME(tmpms) = name; is_initialised = False; } ST_IS_UPDATED(tmpms) = 1; /* Parse the options. */ while (!is_initialised || (action && *action)) { on = 1; if (!is_initialised) { /* some default configuration goes here for the new * menu style */ ST_MENU_COLORS(tmpms).back = GetColor(DEFAULT_BACK_COLOR); ST_MENU_COLORS(tmpms).fore = GetColor(DEFAULT_FORE_COLOR); ST_PSTDFONT(tmpms) = Scr.DefaultFont; ST_USING_DEFAULT_FONT(tmpms) = True; ST_FACE(tmpms).type = SimpleMenu; ST_HAS_ACTIVE_FORE(tmpms) = 0; ST_HAS_ACTIVE_BACK(tmpms) = 0; ST_DO_POPUP_AS(tmpms) = MDP_POST_MENU; ST_DOUBLE_CLICK_TIME(tmpms) = DEFAULT_MENU_CLICKTIME; ST_POPUP_DELAY(tmpms) = DEFAULT_POPUP_DELAY; ST_POPDOWN_DELAY(tmpms) = DEFAULT_POPDOWN_DELAY; ST_MOUSE_WHEEL(tmpms) = MMW_POINTER; ST_SCROLL_OFF_PAGE(tmpms) = 1; ST_DO_HILIGHT_TITLE_BACK(tmpms) = 0; ST_USING_DEFAULT_TITLEFONT(tmpms) = True; has_gc_changed = True; option = "fvwm"; } else { /* Read next option specification (delimited by a comma * or \0). */ args = action; action = GetQuotedString( action, &optstring, ",", NULL, NULL, NULL); if (!optstring) { break; } args = GetNextToken(optstring, &option); if (!option) { free(optstring); break; } (void)GetNextToken(args, &arg1); } poption = option; while (poption[0] == '!') { on ^= 1; poption++; } switch((i = menustyle_get_styleopt_index(poption))) { case 0: /* fvwm */ case 1: /* mwm */ case 2: /* win */ if (i == 0) { ST_POPUP_OFFSET_PERCENT(tmpms) = 67; ST_POPUP_OFFSET_ADD(tmpms) = 0; ST_DO_POPUP_IMMEDIATELY(tmpms) = 0; ST_DO_WARP_TO_TITLE(tmpms) = 1; ST_DO_UNMAP_SUBMENU_ON_POPDOWN(tmpms) = 0; ST_RELIEF_THICKNESS(tmpms) = 1; ST_TITLE_UNDERLINES(tmpms) = 1; ST_HAS_LONG_SEPARATORS(tmpms) = 0; ST_HAS_TRIANGLE_RELIEF(tmpms) = 1; ST_DO_HILIGHT_BACK(tmpms) = 0; ST_DO_HILIGHT_FORE(tmpms) = 0; } else if (i == 1) { ST_POPUP_OFFSET_PERCENT(tmpms) = 100; ST_POPUP_OFFSET_ADD(tmpms) = -DEFAULT_MENU_BORDER_WIDTH - 1; ST_DO_POPUP_IMMEDIATELY(tmpms) = 1; ST_DO_WARP_TO_TITLE(tmpms) = 0; ST_DO_UNMAP_SUBMENU_ON_POPDOWN(tmpms) = 0; ST_RELIEF_THICKNESS(tmpms) = 2; ST_TITLE_UNDERLINES(tmpms) = 2; ST_HAS_LONG_SEPARATORS(tmpms) = 1; ST_HAS_TRIANGLE_RELIEF(tmpms) = 1; ST_DO_HILIGHT_BACK(tmpms) = 0; ST_DO_HILIGHT_FORE(tmpms) = 0; } else /* i == 2 */ { ST_POPUP_OFFSET_PERCENT(tmpms) = 100; ST_POPUP_OFFSET_ADD(tmpms) = -DEFAULT_MENU_BORDER_WIDTH - 3; ST_DO_POPUP_IMMEDIATELY(tmpms) = 1; ST_DO_WARP_TO_TITLE(tmpms) = 0; ST_DO_UNMAP_SUBMENU_ON_POPDOWN(tmpms) = 1; ST_RELIEF_THICKNESS(tmpms) = 0; ST_TITLE_UNDERLINES(tmpms) = 1; ST_HAS_LONG_SEPARATORS(tmpms) = 0; ST_HAS_TRIANGLE_RELIEF(tmpms) = 0; ST_DO_HILIGHT_BACK(tmpms) = 1; ST_DO_HILIGHT_FORE(tmpms) = 1; } /* common settings */ ST_VERTICAL_MARGIN_TOP(tmpms) = 0; ST_VERTICAL_MARGIN_BOTTOM(tmpms) = 0; ST_CSET_MENU(tmpms) = 0; ST_HAS_MENU_CSET(tmpms) = 0; ST_CSET_ACTIVE(tmpms) = 0; ST_HAS_ACTIVE_CSET(tmpms) = 0; ST_CSET_GREYED(tmpms) = 0; ST_HAS_GREYED_CSET(tmpms) = 0; ST_BORDER_WIDTH(tmpms) = DEFAULT_MENU_BORDER_WIDTH; ST_ACTIVE_AREA_PERCENT(tmpms) = DEFAULT_MENU_POPUP_NOW_RATIO; ST_ITEM_GAP_ABOVE(tmpms) = DEFAULT_MENU_ITEM_TEXT_Y_OFFSET; ST_ITEM_GAP_BELOW(tmpms) = DEFAULT_MENU_ITEM_TEXT_Y_OFFSET2; ST_TITLE_GAP_ABOVE(tmpms) = DEFAULT_MENU_TITLE_TEXT_Y_OFFSET; ST_TITLE_GAP_BELOW(tmpms) = DEFAULT_MENU_TITLE_TEXT_Y_OFFSET2; ST_USE_LEFT_SUBMENUS(tmpms) = 0; ST_IS_ANIMATED(tmpms) = 0; ST_USE_AUTOMATIC_HOTKEYS(tmpms) = 0; /* Pressing a hotkey on an item which only has a * single entry will activate that action; turning * those off will make the menu persist until enter or * space is pressed; the default behaviour is to * always close the menu and run the action. */ ST_HOTKEY_ACTIVATES_IMMEDIATE(tmpms) = 1; menustyle_free_face(&ST_FACE(tmpms)); ST_FACE(tmpms).type = SimpleMenu; if (ST_PSTDFONT(tmpms) && !ST_USING_DEFAULT_FONT(tmpms)) { FlocaleUnloadFont(dpy, ST_PSTDFONT(tmpms)); } ST_PSTDFONT(tmpms) = Scr.DefaultFont; ST_USING_DEFAULT_FONT(tmpms) = True; has_gc_changed = True; if (ST_HAS_SIDE_COLOR(tmpms) == 1) { fvwmlib_free_colors( dpy, &ST_SIDE_COLOR(tmpms), 1, True); ST_HAS_SIDE_COLOR(tmpms) = 0; } ST_HAS_SIDE_COLOR(tmpms) = 0; if (ST_SIDEPIC(tmpms)) { PDestroyFvwmPicture(dpy, ST_SIDEPIC(tmpms)); ST_SIDEPIC(tmpms) = NULL; } if (is_initialised == False) { /* now begin the real work */ is_initialised = True; continue; } break; case 3: /* Foreground */ fvwmlib_free_colors( dpy, &ST_MENU_COLORS(tmpms).fore, 1, True); if (arg1) { ST_MENU_COLORS(tmpms).fore = GetColor(arg1); } else { ST_MENU_COLORS(tmpms).fore = GetColor(DEFAULT_FORE_COLOR); } has_gc_changed = True; break; case 4: /* Background */ fvwmlib_free_colors( dpy, &ST_MENU_COLORS(tmpms).back, 1, True); if (arg1) { ST_MENU_COLORS(tmpms).back = GetColor(arg1); } else { ST_MENU_COLORS(tmpms).back = GetColor(DEFAULT_BACK_COLOR); } has_gc_changed = True; break; case 5: /* Greyed */ if (ST_HAS_STIPPLE_FORE(tmpms)) { fvwmlib_free_colors( dpy, &ST_MENU_STIPPLE_COLORS(tmpms).fore, 1, True); } if (arg1 == NULL) { ST_HAS_STIPPLE_FORE(tmpms) = 0; } else { ST_MENU_STIPPLE_COLORS(tmpms).fore = GetColor(arg1); ST_HAS_STIPPLE_FORE(tmpms) = 1; } has_gc_changed = True; break; case 7: /* HilightBackOff */ on ^= 1; /* fall throw */ case 6: /* HilightBack */ if (ST_HAS_ACTIVE_BACK(tmpms)) { fvwmlib_free_colors( dpy, &ST_MENU_ACTIVE_COLORS(tmpms).back, 1, True); } if (arg1 == NULL || !on) { ST_HAS_ACTIVE_BACK(tmpms) = 0; } else { ST_MENU_ACTIVE_COLORS(tmpms).back = GetColor(arg1); ST_HAS_ACTIVE_BACK(tmpms) = 1; } ST_DO_HILIGHT_BACK(tmpms) = on; has_gc_changed = True; break; case 9: /* ActiveForeOff */ on ^= 1; /* fall throw */ case 8: /* ActiveFore */ if (ST_HAS_ACTIVE_FORE(tmpms)) { fvwmlib_free_colors( dpy, &ST_MENU_ACTIVE_COLORS(tmpms).fore, 1, True); } if (arg1 == NULL || !on) { ST_HAS_ACTIVE_FORE(tmpms) = 0; } else { ST_MENU_ACTIVE_COLORS(tmpms).fore = GetColor(arg1); ST_HAS_ACTIVE_FORE(tmpms) = 1; } ST_DO_HILIGHT_FORE(tmpms) = on; has_gc_changed = True; break; case 10: /* Hilight3DThick */ ST_RELIEF_THICKNESS(tmpms) = 2; break; case 11: /* Hilight3DThin */ ST_RELIEF_THICKNESS(tmpms) = 1; break; case 12: /* Hilight3DOff */ ST_RELIEF_THICKNESS(tmpms) = 0; break; case 13: /* Animation */ ST_IS_ANIMATED(tmpms) = on; break; case 14: /* AnimationOff */ ST_IS_ANIMATED(tmpms) = !on; break; case 15: /* Font */ if (arg1 != NULL && !(new_font = FlocaleLoadFont(dpy, arg1, "fvwm"))) { fvwm_msg(ERR, "NewMenuStyle", "Couldn't load font '%s'\n", arg1); break; } if (ST_PSTDFONT(tmpms) && !ST_USING_DEFAULT_FONT(tmpms)) { FlocaleUnloadFont(dpy, ST_PSTDFONT(tmpms)); } if (arg1 == NULL) { /* reset to screen font */ ST_PSTDFONT(tmpms) = Scr.DefaultFont; ST_USING_DEFAULT_FONT(tmpms) = True; } else { ST_PSTDFONT(tmpms) = new_font; ST_USING_DEFAULT_FONT(tmpms) = False; } has_gc_changed = True; break; case 16: /* MenuFace */ while (args && *args != '\0' && isspace((unsigned char)*args)) { args++; } menustyle_parse_face(args, &ST_FACE(tmpms), True); break; case 17: /* PopupDelay */ if (GetIntegerArguments(args, NULL, val, 1) == 0 || *val < 0) { ST_POPUP_DELAY(tmpms) = DEFAULT_POPUP_DELAY; } else { ST_POPUP_DELAY(tmpms) = (*val+9)/10; } break; case 18: /* PopupOffset */ if ((n = GetIntegerArguments(args, NULL, val, 2)) == 0) { fvwm_msg(ERR,"NewMenuStyle", "PopupOffset requires one or two" " arguments"); } else { ST_POPUP_OFFSET_ADD(tmpms) = val[0]; if (n == 2 && val[1] <= 100 && val[1] >= 0) { ST_POPUP_OFFSET_PERCENT(tmpms) = val[1]; } else { ST_POPUP_OFFSET_PERCENT(tmpms) = 100; } } break; case 19: /* TitleWarp */ ST_DO_WARP_TO_TITLE(tmpms) = on; break; case 20: /* TitleWarpOff */ ST_DO_WARP_TO_TITLE(tmpms) = !on; break; case 21: /* TitleUnderlines0 */ ST_TITLE_UNDERLINES(tmpms) = 0; break; case 22: /* TitleUnderlines1 */ ST_TITLE_UNDERLINES(tmpms) = 1; break; case 23: /* TitleUnderlines2 */ ST_TITLE_UNDERLINES(tmpms) = 2; break; case 24: /* SeparatorsLong */ ST_HAS_LONG_SEPARATORS(tmpms) = on; break; case 25: /* SeparatorsShort */ ST_HAS_LONG_SEPARATORS(tmpms) = !on; break; case 26: /* TrianglesSolid */ ST_HAS_TRIANGLE_RELIEF(tmpms) = !on; break; case 27: /* TrianglesRelief */ ST_HAS_TRIANGLE_RELIEF(tmpms) = on; break; case 28: /* PopupImmediately */ ST_DO_POPUP_IMMEDIATELY(tmpms) = on; break; case 29: /* PopupDelayed */ ST_DO_POPUP_IMMEDIATELY(tmpms) = !on; break; case 30: /* DoubleClickTime */ if (GetIntegerArguments(args, NULL, val, 1) == 0 || *val < 0) { ST_DOUBLE_CLICK_TIME(tmpms) = DEFAULT_MENU_CLICKTIME; } else { ST_DOUBLE_CLICK_TIME(tmpms) = *val; } break; case 31: /* SidePic */ if (ST_SIDEPIC(tmpms)) { PDestroyFvwmPicture(dpy, ST_SIDEPIC(tmpms)); ST_SIDEPIC(tmpms) = NULL; } if (arg1) { fpa.mask = (Pdepth <= 8)? FPAM_DITHER:0; ST_SIDEPIC(tmpms) = PCacheFvwmPicture( dpy, Scr.NoFocusWin, NULL, arg1, fpa); if (!ST_SIDEPIC(tmpms)) { fvwm_msg(WARN, "NewMenuStyle", "Couldn't find pixmap %s", arg1); } } break; case 32: /* SideColor */ if (ST_HAS_SIDE_COLOR(tmpms) == 1) { fvwmlib_free_colors( dpy, &ST_SIDE_COLOR(tmpms), 1, True); ST_HAS_SIDE_COLOR(tmpms) = 0; } if (arg1) { ST_SIDE_COLOR(tmpms) = GetColor(arg1); ST_HAS_SIDE_COLOR(tmpms) = 1; } break; case 33: /* PopupAsRootmenu */ ST_DO_POPUP_AS(tmpms) = MDP_ROOT_MENU; break; case 34: /* PopupAsSubmenu */ ST_DO_POPUP_AS(tmpms) = MDP_POST_MENU; break; case 35: /* RemoveSubmenus */ ST_DO_UNMAP_SUBMENU_ON_POPDOWN(tmpms) = on; break; case 36: /* HoldSubmenus */ ST_DO_UNMAP_SUBMENU_ON_POPDOWN(tmpms) = !on; break; case 37: /* SubmenusRight */ ST_USE_LEFT_SUBMENUS(tmpms) = !on; break; case 38: /* SubmenusLeft */ ST_USE_LEFT_SUBMENUS(tmpms) = on; break; case 39: /* BorderWidth */ if (GetIntegerArguments(args, NULL, val, 1) == 0 || *val < 0 || *val > MAX_MENU_BORDER_WIDTH) { ST_BORDER_WIDTH(tmpms) = DEFAULT_MENU_BORDER_WIDTH; } else { ST_BORDER_WIDTH(tmpms) = *val; } break; case 40: /* Hilight3DThickness */ if (GetIntegerArguments(args, NULL, val, 1) > 0) { if (*val < 0) { *val = -*val; ST_IS_ITEM_RELIEF_REVERSED(tmpms) = 1; } else { ST_IS_ITEM_RELIEF_REVERSED(tmpms) = 0; } if (*val > MAX_MENU_ITEM_RELIEF_THICKNESS) *val = MAX_MENU_ITEM_RELIEF_THICKNESS; ST_RELIEF_THICKNESS(tmpms) = *val; } break; case 41: /* ItemFormat */ if (ST_ITEM_FORMAT(tmpms)) { free(ST_ITEM_FORMAT(tmpms)); ST_ITEM_FORMAT(tmpms) = NULL; } if (arg1) { ST_ITEM_FORMAT(tmpms) = safestrdup(arg1); } break; case 42: /* AutomaticHotkeys */ ST_USE_AUTOMATIC_HOTKEYS(tmpms) = on; break; case 43: /* AutomaticHotkeysOff */ ST_USE_AUTOMATIC_HOTKEYS(tmpms) = !on; break; case 44: /* VerticalItemSpacing */ parse_vertical_spacing_line( args, &ST_ITEM_GAP_ABOVE(tmpms), &ST_ITEM_GAP_BELOW(tmpms), DEFAULT_MENU_ITEM_TEXT_Y_OFFSET, DEFAULT_MENU_ITEM_TEXT_Y_OFFSET2); break; case 45: /* VerticalTitleSpacing */ parse_vertical_spacing_line( args, &ST_TITLE_GAP_ABOVE(tmpms), &ST_TITLE_GAP_BELOW(tmpms), DEFAULT_MENU_TITLE_TEXT_Y_OFFSET, DEFAULT_MENU_TITLE_TEXT_Y_OFFSET2); break; case 46: /* MenuColorset */ if (GetIntegerArguments(args, NULL, val, 1) == 0 || *val < 0) { ST_HAS_MENU_CSET(tmpms) = 0; ST_CSET_MENU(tmpms) = 0; } else { ST_HAS_MENU_CSET(tmpms) = 1; ST_CSET_MENU(tmpms) = *val; alloc_colorset(*val); } has_gc_changed = True; break; case 47: /* ActiveColorset */ if (GetIntegerArguments(args, NULL, val, 1) == 0 || *val < 0) { ST_HAS_ACTIVE_CSET(tmpms) = 0; ST_CSET_ACTIVE(tmpms) = 0; } else { ST_HAS_ACTIVE_CSET(tmpms) = 1; ST_CSET_ACTIVE(tmpms) = *val; alloc_colorset(*val); } has_gc_changed = True; break; case 48: /* GreyedColorset */ if (GetIntegerArguments(args, NULL, val, 1) == 0 || *val < 0) { ST_HAS_GREYED_CSET(tmpms) = 0; ST_CSET_GREYED(tmpms) = 0; } else { ST_HAS_GREYED_CSET(tmpms) = 1; ST_CSET_GREYED(tmpms) = *val; alloc_colorset(*val); } has_gc_changed = True; break; case 49: /* SelectOnRelease */ keycode = 0; if (arg1) { keycode = XKeysymToKeycode( dpy, FvwmStringToKeysym(dpy, arg1)); } ST_SELECT_ON_RELEASE_KEY(tmpms) = keycode; break; case 50: /* PopdownImmediately */ ST_DO_POPDOWN_IMMEDIATELY(tmpms) = 1; break; case 51: /* PopdownDelayed */ ST_DO_POPDOWN_IMMEDIATELY(tmpms) = 0; break; case 52: /* PopdownDelay */ if (GetIntegerArguments(args, NULL, val, 1) == 0 || *val < 0) { ST_POPDOWN_DELAY(tmpms) = DEFAULT_POPDOWN_DELAY; } else { ST_POPDOWN_DELAY(tmpms) = (*val+9)/10; } break; case 53: /* PopupActiveArea */ if (GetIntegerArguments(args, NULL, val, 1) == 0 || *val <= 50 || *val > 100) { ST_ACTIVE_AREA_PERCENT(tmpms) = DEFAULT_MENU_POPUP_NOW_RATIO; } else { ST_ACTIVE_AREA_PERCENT(tmpms) = *val; } break; case 54: /* PopupIgnore */ ST_DO_POPUP_AS(tmpms) = MDP_IGNORE; break; case 55: /* PopupClose */ ST_DO_POPUP_AS(tmpms) = MDP_CLOSE; break; case 56: /* MouseWheel */ if (arg1) { if (StrEquals(arg1, "ActivatesItem")) { ST_MOUSE_WHEEL(tmpms) = MMW_OFF; } else if (StrEquals(arg1, "ScrollsMenuBackwards")) { ST_MOUSE_WHEEL(tmpms) = MMW_MENU_BACKWARDS; } else if (StrEquals(arg1, "ScrollsMenu")) { ST_MOUSE_WHEEL(tmpms) = MMW_MENU; } else if (StrEquals(arg1, "ScrollsPointer")) { ST_MOUSE_WHEEL(tmpms) = MMW_POINTER; } else { fvwm_msg( ERR, "NewMenuStyle", "unknown argument to" " MouseWheel '%s'", arg1); ST_MOUSE_WHEEL(tmpms) = MMW_POINTER; } } else { ST_MOUSE_WHEEL(tmpms) = (on) ? MMW_POINTER : MMW_OFF; } break; case 57: /* ScrollOffPage */ ST_SCROLL_OFF_PAGE(tmpms) = on; break; case 58: /* TrianglesUseFore */ ST_TRIANGLES_USE_FORE(tmpms) = on; break; case 59: /* TitleColorset */ if (GetIntegerArguments(args, NULL, val, 1) == 0 || *val < 0) { ST_HAS_TITLE_CSET(tmpms) = 0; ST_CSET_TITLE(tmpms) = 0; } else { ST_HAS_TITLE_CSET(tmpms) = 1; ST_CSET_TITLE(tmpms) = *val; alloc_colorset(*val); } has_gc_changed = True; break; case 60: /* TitleHilightBack */ ST_DO_HILIGHT_TITLE_BACK(tmpms) = on; has_gc_changed = True; break; case 61: /* TitleFont */ if (arg1 != NULL && !(new_font = FlocaleLoadFont(dpy, arg1, "fvwm"))) { fvwm_msg(ERR, "NewMenuStyle", "Couldn't load font '%s'\n", arg1); break; } if ( ST_PTITLEFONT(tmpms) && !ST_USING_DEFAULT_TITLEFONT(tmpms)) { FlocaleUnloadFont(dpy, ST_PTITLEFONT(tmpms)); } if (arg1 == NULL) { /* reset to screen font */ ST_PTITLEFONT(tmpms) = Scr.DefaultFont; ST_USING_DEFAULT_TITLEFONT(tmpms) = True; } else { ST_PTITLEFONT(tmpms) = new_font; ST_USING_DEFAULT_TITLEFONT(tmpms) = False; } has_gc_changed = True; break; case 62: /* VerticalMargins */ parse_vertical_margins_line( args, &ST_VERTICAL_MARGIN_TOP(tmpms), &ST_VERTICAL_MARGIN_BOTTOM(tmpms), 0, 0); break; case 63: /* UniqueHotKeyActivatesImmediate */ ST_HOTKEY_ACTIVATES_IMMEDIATE(tmpms) = on; break; #if 0 case 99: /* PositionHints */ /* to be implemented */ break; #endif default: fvwm_msg(ERR, "NewMenuStyle", "unknown option '%s'", poption); break; } /* switch */ if (option) { free(option); option = NULL; } free(optstring); optstring = NULL; if (arg1) { free(arg1); arg1 = NULL; } } /* while */ if (has_gc_changed) { menustyle_update(tmpms); } if (default_menu_style == NULL) { /* First MenuStyle MUST be the default style */ default_menu_style = tmpms; ST_NEXT_STYLE(tmpms) = NULL; } else if (ms) { /* copy our new menu face over the old one */ memcpy(ms, tmpms, sizeof(MenuStyle)); free(tmpms); return ms; } else { MenuStyle *before = default_menu_style; /* add a new menu face to list */ ST_NEXT_STYLE(tmpms) = NULL; while (ST_NEXT_STYLE(before)) before = ST_NEXT_STYLE(before); ST_NEXT_STYLE(before) = tmpms; } return tmpms; } void menustyle_copy(MenuStyle *origms, MenuStyle *destms) { FvwmPictureAttributes fpa; /* Copy origms to destms, be aware of all pointers in the MenuStyle strcture. Use the same order as in menustyle_parse_style */ /* menu colors */ fvwmlib_copy_color( dpy, &ST_MENU_COLORS(destms).fore, &ST_MENU_COLORS(origms).fore, True, True); fvwmlib_copy_color( dpy, &ST_MENU_COLORS(destms).back, &ST_MENU_COLORS(origms).back, True, True); /* Greyed */ fvwmlib_copy_color( dpy, &ST_MENU_STIPPLE_COLORS(destms).fore, &ST_MENU_STIPPLE_COLORS(origms).fore, ST_HAS_STIPPLE_FORE(destms), ST_HAS_STIPPLE_FORE(origms)); ST_MENU_STIPPLE_COLORS(destms).back = ST_MENU_STIPPLE_COLORS(origms).back; ST_HAS_STIPPLE_FORE(destms) = ST_HAS_STIPPLE_FORE(origms); /* HilightBack */ fvwmlib_copy_color( dpy, &ST_MENU_ACTIVE_COLORS(destms).back, &ST_MENU_ACTIVE_COLORS(origms).back, ST_HAS_ACTIVE_BACK(destms), ST_HAS_ACTIVE_BACK(origms)); ST_HAS_ACTIVE_BACK(destms) = ST_HAS_ACTIVE_BACK(origms); ST_DO_HILIGHT_BACK(destms) = ST_DO_HILIGHT_BACK(origms); /* ActiveFore */ fvwmlib_copy_color( dpy, &ST_MENU_ACTIVE_COLORS(destms).fore, &ST_MENU_ACTIVE_COLORS(origms).fore, ST_HAS_ACTIVE_FORE(destms), ST_HAS_ACTIVE_FORE(origms)); ST_HAS_ACTIVE_FORE(destms) = ST_HAS_ACTIVE_FORE(origms); ST_DO_HILIGHT_FORE(destms) = ST_DO_HILIGHT_FORE(origms); /* Hilight3D */ ST_RELIEF_THICKNESS(destms) = ST_RELIEF_THICKNESS(origms); /* Animation */ ST_IS_ANIMATED(destms) = ST_IS_ANIMATED(origms); /* font */ if (ST_PSTDFONT(destms) && !ST_USING_DEFAULT_FONT(destms)) { FlocaleUnloadFont(dpy, ST_PSTDFONT(destms)); } if (ST_PSTDFONT(origms) && !ST_USING_DEFAULT_FONT(origms)) { if (!(ST_PSTDFONT(destms) = FlocaleLoadFont(dpy, ST_PSTDFONT(origms)->name, "fvwm"))) { ST_PSTDFONT(destms) = Scr.DefaultFont; ST_USING_DEFAULT_FONT(destms) = True; fvwm_msg(ERR, "CopyMenuStyle", "Couldn't load font '%s' use Default Font\n", ST_PSTDFONT(origms)->name); } else { ST_USING_DEFAULT_FONT(destms) = False; } } else { ST_USING_DEFAULT_FONT(destms) = True; ST_PSTDFONT(destms) = Scr.DefaultFont; } /* TitleFont */ if (ST_PTITLEFONT(destms) && !ST_USING_DEFAULT_TITLEFONT(destms)) { FlocaleUnloadFont(dpy, ST_PTITLEFONT(destms)); } if (ST_PTITLEFONT(origms) && !ST_USING_DEFAULT_TITLEFONT(origms)) { if ( !(ST_PTITLEFONT(destms) = FlocaleLoadFont( dpy, ST_PTITLEFONT(origms)->name, "fvwm"))) { ST_PTITLEFONT(destms) = Scr.DefaultFont; ST_USING_DEFAULT_TITLEFONT(destms) = True; fvwm_msg(ERR, "CopyMenuStyle", "Couldn't load font '%s' use Default Font\n", ST_PTITLEFONT(origms)->name); } else { ST_USING_DEFAULT_TITLEFONT(destms) = False; } } else { ST_USING_DEFAULT_TITLEFONT(destms) = True; ST_PTITLEFONT(destms) = Scr.DefaultFont; } /* MenuFace */ menustyle_copy_face(&ST_FACE(destms), &ST_FACE(origms)); /* PopupDelay */ ST_POPUP_DELAY(destms) = ST_POPUP_DELAY(origms); /* PopupOffset */ ST_POPUP_OFFSET_PERCENT(destms) = ST_POPUP_OFFSET_PERCENT(origms); ST_POPUP_OFFSET_ADD(destms) = ST_POPUP_OFFSET_ADD(origms); /* TitleWarp */ ST_DO_WARP_TO_TITLE(destms) = ST_DO_WARP_TO_TITLE(origms); /* TitleUnderlines */ ST_TITLE_UNDERLINES(destms) = ST_TITLE_UNDERLINES(origms); /* Separators */ ST_HAS_LONG_SEPARATORS(destms) = ST_HAS_LONG_SEPARATORS(origms); /* Triangles */ ST_HAS_TRIANGLE_RELIEF(destms) = ST_HAS_TRIANGLE_RELIEF(origms); /* PopupDelayed */ ST_DO_POPUP_IMMEDIATELY(destms) = ST_DO_POPUP_IMMEDIATELY(origms); /* DoubleClickTime */ ST_DOUBLE_CLICK_TIME(destms) = ST_DOUBLE_CLICK_TIME(origms); /* VerticalMargins */ ST_VERTICAL_MARGIN_TOP(destms) = ST_VERTICAL_MARGIN_TOP(origms); ST_VERTICAL_MARGIN_BOTTOM(destms) = ST_VERTICAL_MARGIN_BOTTOM(origms); /* SidePic */ if (ST_SIDEPIC(destms)) { PDestroyFvwmPicture(dpy, ST_SIDEPIC(destms)); ST_SIDEPIC(destms) = NULL; } if (ST_SIDEPIC(origms)) { fpa.mask = (Pdepth <= 8)? FPAM_DITHER:0; ST_SIDEPIC(destms) = PCacheFvwmPicture( dpy, Scr.NoFocusWin, NULL, ST_SIDEPIC(origms)->name, fpa); } /* side color */ fvwmlib_copy_color( dpy, &ST_SIDE_COLOR(destms), &ST_SIDE_COLOR(origms), ST_HAS_SIDE_COLOR(destms), ST_HAS_SIDE_COLOR(origms)); ST_HAS_SIDE_COLOR(destms) = ST_HAS_SIDE_COLOR(origms); /* PopupAsRootmenu */ ST_DO_POPUP_AS(destms) = ST_DO_POPUP_AS(origms); /* RemoveSubmenus */ ST_DO_UNMAP_SUBMENU_ON_POPDOWN(destms) = ST_DO_UNMAP_SUBMENU_ON_POPDOWN(origms); /* SubmenusRight */ ST_USE_LEFT_SUBMENUS(destms) = ST_USE_LEFT_SUBMENUS(origms); /* BorderWidth */ ST_BORDER_WIDTH(destms) = ST_BORDER_WIDTH(origms); /* Hilight3DThickness */ ST_IS_ITEM_RELIEF_REVERSED(destms) = ST_IS_ITEM_RELIEF_REVERSED(origms); /* ItemFormat */ if (ST_ITEM_FORMAT(destms)) { free(ST_ITEM_FORMAT(destms)); ST_ITEM_FORMAT(destms) = NULL; } if (ST_ITEM_FORMAT(origms)) { ST_ITEM_FORMAT(destms) = safestrdup(ST_ITEM_FORMAT(origms)); } /* AutomaticHotkeys */ ST_USE_AUTOMATIC_HOTKEYS(destms) = ST_USE_AUTOMATIC_HOTKEYS(origms); ST_HOTKEY_ACTIVATES_IMMEDIATE(destms) = ST_HOTKEY_ACTIVATES_IMMEDIATE(origms); /* Item and Title Spacing */ ST_ITEM_GAP_ABOVE(destms) = ST_ITEM_GAP_ABOVE(origms); ST_ITEM_GAP_BELOW(destms) = ST_ITEM_GAP_BELOW(origms); ST_TITLE_GAP_ABOVE(destms) = ST_TITLE_GAP_ABOVE(origms); ST_TITLE_GAP_BELOW(destms) = ST_TITLE_GAP_BELOW(origms); /* MenuColorset */ ST_HAS_MENU_CSET(destms) = ST_HAS_MENU_CSET(origms); ST_CSET_MENU(destms) = ST_CSET_MENU(origms); /* ActiveColorset */ ST_HAS_ACTIVE_CSET(destms) = ST_HAS_ACTIVE_CSET(origms); ST_CSET_ACTIVE(destms) = ST_CSET_ACTIVE(origms); /* MenuColorset */ ST_HAS_GREYED_CSET(destms) = ST_HAS_GREYED_CSET(origms); ST_CSET_GREYED(destms) = ST_CSET_GREYED(origms); /* TitleColorset */ ST_HAS_TITLE_CSET(destms) = ST_HAS_TITLE_CSET(origms); ST_CSET_TITLE(destms) = ST_CSET_TITLE(origms); /* SelectOnRelease */ ST_SELECT_ON_RELEASE_KEY(destms) = ST_SELECT_ON_RELEASE_KEY(origms); /* PopdownImmediately */ ST_DO_POPDOWN_IMMEDIATELY(destms) = ST_DO_POPDOWN_IMMEDIATELY(origms); /* PopdownDelay */ ST_POPDOWN_DELAY(destms) = ST_POPDOWN_DELAY(origms); /* Scroll */ ST_MOUSE_WHEEL(destms) = ST_MOUSE_WHEEL(origms); /* ScrollOffPage */ ST_SCROLL_OFF_PAGE(destms) = ST_SCROLL_OFF_PAGE(origms); /* TrianglesUseFore */ ST_TRIANGLES_USE_FORE(destms) = ST_TRIANGLES_USE_FORE(origms); /* Title */ ST_DO_HILIGHT_TITLE_BACK(destms) = ST_DO_HILIGHT_TITLE_BACK(origms); menustyle_update(destms); return; } /* ---------------------------- builtin commands --------------------------- */ void CMD_CopyMenuStyle(F_CMD_ARGS) { char *origname = NULL; char *destname = NULL; char *buffer; MenuStyle *origms; MenuStyle *destms; origname = PeekToken(action, &action); if (origname == NULL) { fvwm_msg(ERR,"CopyMenuStyle", "need two arguments"); return; } origms = menustyle_find(origname); if (!origms) { fvwm_msg(ERR, "CopyMenuStyle", "%s: no such menu style", origname); return; } destname = PeekToken(action, &action); if (destname == NULL) { fvwm_msg(ERR,"CopyMenuStyle", "need two arguments"); return; } if (action && *action) { fvwm_msg(ERR,"CopyMenuStyle", "too many arguments"); return; } destms = menustyle_find(destname); if (!destms) { /* create destms menu style */ buffer = (char *)safemalloc(strlen(destname) + 3); sprintf(buffer,"\"%s\"",destname); action = buffer; destms = menustyle_parse_style(F_PASS_ARGS); free(buffer); if (!destms) { /* this must never happen */ fvwm_msg(ERR, "CopyMenuStyle", "impossible to create %s menu style", destname); return; } } if (strcasecmp("*",destname) == 0) { fvwm_msg(ERR, "CopyMenuStyle", "You cannot copy on the default menu style"); return; } if (strcasecmp(ST_NAME(origms),destname) == 0) { fvwm_msg(ERR, "CopyMenuStyle", "%s and %s identify the same menu style", ST_NAME(origms),destname); return; } if (ST_USAGE_COUNT(destms) != 0) { fvwm_msg(ERR, "CopyMenuStyle", "menu style %s is in use", destname); return; } menustyle_copy(origms, destms); return; } void CMD_MenuStyle(F_CMD_ARGS) { char *option; char *poption; GetNextSimpleOption(SkipNTokens(action, 1), &option); poption = option; while (poption && poption[0] == '!') { poption++; } if (option == NULL || menustyle_get_styleopt_index(poption) != -1) { (void)menustyle_parse_style(F_PASS_ARGS); } else { (void)menustyle_parse_old_style(F_PASS_ARGS); } if (option) { free(option); } return; } fvwm-2.7.0/fvwm/repeat.h0000644000175000017500000000131214147024676012040 00000000000000/* -*-c-*- */ #ifndef _REPEAT_ #define _REPEAT_ typedef enum { REPEAT_NONE = 0, REPEAT_COMMAND, /* I think we don't need all these REPEAT_BUILTIN, REPEAT_FUNCTION, REPEAT_TOP_FUNCTION, REPEAT_MODULE, */ REPEAT_MENU, REPEAT_POPUP, REPEAT_PAGE, REPEAT_DESK, REPEAT_DESK_AND_PAGE, REPEAT_FVWM_WINDOW } repeat_t; extern char *repeat_last_function; extern char *repeat_last_complex_function; extern char *repeat_last_builtin_function; extern char *repeat_last_module; /* extern char *repeat_last_top_function; extern char *repeat_last_menu; extern FvwmWindow *repeat_last_fvwm_window; */ Bool set_repeat_data(void *data, repeat_t type, const func_t *builtin); #endif /* _REPEAT_ */ fvwm-2.7.0/fvwm/ewmh_events.c0000644000175000017500000010463014147024700013072 00000000000000/* -*-c-*- */ /* Copyright (C) 2001 Olivier Chapuis */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ #include "config.h" #include #include #include #include "libs/fvwmlib.h" #include "libs/FScreen.h" #include "libs/Strings.h" #include "fvwm.h" #include "externs.h" #include "execcontext.h" #include "functions.h" #include "misc.h" #include "screen.h" #include "virtual.h" #include "commands.h" #include "update.h" #include "style.h" #include "stack.h" #include "events.h" #include "ewmh.h" #include "ewmh_intern.h" #include "decorations.h" #include "geometry.h" #include "borders.h" extern ewmh_atom ewmh_atom_wm_state[]; #define DEBUG_EWMH_INIT_STATE 0 /* * root */ int ewmh_CurrentDesktop( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { if (ev->xclient.data.l[0] < 0 || ev->xclient.data.l[0] > 0x7fffffff) { fvwm_msg( WARN, "ewmh_CurrentDesktop", "The application window (id %#lx)\n" " \"%s\" tried to switch to an invalid desktop (%ld)\n" " using an EWMH client message.\n" " fvwm is ignoring this request.\n", fw ? FW_W(fw) : 0, fw ? fw->name.name : "(none)", ev->xclient.data.l[0]); fvwm_msg_report_app_and_workers(); return -1; } goto_desk(ev->xclient.data.l[0]); return -1; } int ewmh_DesktopGeometry( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { char action[256]; long width = ev->xclient.data.l[0]; long height = ev->xclient.data.l[1]; width = width / Scr.MyDisplayWidth; height = height / Scr.MyDisplayHeight; if (width <= 0 || height <= 0) { fvwm_msg( WARN, "ewmh_DesktopGeometry", "The application window (id %#lx)\n" " \"%s\" tried to set an invalid desktop geometry" " (%ldx%ld)\n" " using an EWMH client message.\n" " fvwm is ignoring this request.\n", fw ? FW_W(fw) : 0, fw ? fw->name.name : "(none)", ev->xclient.data.l[0], ev->xclient.data.l[1]); fvwm_msg_report_app_and_workers(); return -1; } sprintf(action, "DesktopSize %ld %ld", width, height); execute_function_override_window(NULL, NULL, action, 0, NULL); return -1; } int ewmh_DesktopViewPort( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { if ( ev->xclient.data.l[0] < 0 || ev->xclient.data.l[0] > 0x7fffffff || ev->xclient.data.l[1] < 0 || ev->xclient.data.l[1] > 0x7fffffff) { fvwm_msg( WARN, "ewmh_DesktopViewPort", "The application window (id %#lx)\n" " \"%s\" tried to switch to an invalid page" " (%ldx%ld)\n" " using an EWMH client message.\n" " fvwm is ignoring this request.\n", fw ? FW_W(fw) : 0, fw ? fw->name.name : "(none)", ev->xclient.data.l[0], ev->xclient.data.l[1]); fvwm_msg_report_app_and_workers(); return -1; } MoveViewport(ev->xclient.data.l[0], ev->xclient.data.l[1], 1); return -1; } int ewmh_NumberOfDesktops( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { int d = ev->xclient.data.l[0]; /* not a lot of sinification for fvwm */ if (d > 0 && (d <= ewmhc.MaxDesktops || ewmhc.MaxDesktops == 0)) { ewmhc.NumberOfDesktops = d; EWMH_SetNumberOfDesktops(); } else { fvwm_msg( WARN, "ewmh_NumberOfDesktops", "The application window (id %#lx)\n" " \"%s\" tried to set an invalid number of desktops" " (%ld)\n" " using an EWMH client message.\n" " fvwm is ignoring this request.\n", fw ? FW_W(fw) : 0, fw ? fw->name.name : "(none)", ev->xclient.data.l[0]); fvwm_msg_report_app_and_workers(); } return -1; } /* * window */ int ewmh_ActiveWindow( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { if (ev == NULL) { return 0; } execute_function_override_window( NULL, NULL, "EWMHActivateWindowFunc", 0, fw); return 0; } int ewmh_CloseWindow( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { if (ev == NULL) { return 0; } if (!is_function_allowed(F_CLOSE, NULL, fw, RQORIG_PROGRAM_US, False)) { return 0; } execute_function_override_window(NULL, NULL, "Close", 0, fw); return 0; } int ewmh_MoveResizeWindow( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { int do_reconfigure; int win_gravity; int value_mask; if (ev == NULL) { return 0; } win_gravity = ev->xclient.data.l[0] & 0xff; value_mask = (ev->xclient.data.l[0] >> 8) & 0xf; if (fw == NULL) { /* unmanaged window */ do_reconfigure = 1; } else { int func; if ( ((value_mask & CWWidth) == 0 || ev->xclient.data.l[3] == fw->g.normal.width) && ((value_mask & CWHeight) == 0 || ev->xclient.data.l[4] == fw->g.normal.height)) { func = F_MOVE; } else { func = F_RESIZE; } do_reconfigure = !!is_function_allowed( func, NULL, fw, RQORIG_PROGRAM, False); } if (do_reconfigure == 1) { XEvent e; XConfigureRequestEvent *cre = &e.xconfigurerequest; cre->value_mask = value_mask; cre->x = ev->xclient.data.l[1]; cre->y = ev->xclient.data.l[2]; cre->width = ev->xclient.data.l[3]; cre->height = ev->xclient.data.l[4]; cre->window = ev->xclient.window; events_handle_configure_request(&e, fw, True, win_gravity); } return 0; } int ewmh_RestackWindow( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { int do_restack; if (ev == NULL) { return 0; } if (fw == NULL) { /* unmanaged window */ do_restack = 1; } else { do_restack = !!DO_EWMH_USE_STACKING_HINTS(fw); } if (do_restack == 1) { XEvent e; XConfigureRequestEvent *cre = &e.xconfigurerequest; cre->value_mask = CWSibling | CWStackMode; cre->above = ev->xclient.data.l[1]; cre->detail = ev->xclient.data.l[2]; cre->window = ev->xclient.window; events_handle_configure_request(&e, fw, True, ForgetGravity); } return 0; } int ewmh_WMDesktop( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { if (ev != NULL && style == NULL) { /* client message */ unsigned long d = (unsigned long)ev->xclient.data.l[0]; /* the spec says that if d = 0xFFFFFFFF then we have to Stick * the window however KDE use 0xFFFFFFFE :o) */ if (d == (unsigned long)-2 || d == (unsigned long)-1) { execute_function_override_window( NULL, NULL, "Stick on", 0, fw); } else if (d > 0) { if (IS_STICKY_ACROSS_PAGES(fw) || IS_STICKY_ACROSS_DESKS(fw)) { execute_function_override_window( NULL, NULL, "Stick off", 0, fw); } if (fw->Desk != d) { do_move_window_to_desk(fw, (int)d); } } else { fvwm_msg( WARN, "ewmh_WMDesktop", "The application window (id %#lx)\n" " \"%s\" tried to move to an invalid desk" " (%ld)\n" " using an EWMH client message.\n" " fvwm is ignoring this request.\n", fw ? FW_W(fw) : 0, fw ? fw->name.name : "(none)", ev->xclient.data.l[0]); fvwm_msg_report_app_and_workers(); } return 0; } if (style != NULL && ev == NULL) { /* start on desk */ CARD32 *val; int size = 0; if (DO_EWMH_IGNORE_STATE_HINTS(style)) { SET_HAS_EWMH_INIT_WM_DESKTOP( fw, EWMH_STATE_UNDEFINED_HINT); return 0; } if (HAS_EWMH_INIT_WM_DESKTOP(fw) != EWMH_STATE_UNDEFINED_HINT) { return 0; } val = ewmh_AtomGetByName( FW_W(fw), "_NET_WM_DESKTOP", EWMH_ATOM_LIST_CLIENT_WIN, &size); if (val == NULL) { SET_HAS_EWMH_INIT_WM_DESKTOP(fw, EWMH_STATE_NO_HINT); return 0; } #if DEBUG_EWMH_INIT_STATE fprintf( stderr, "ewmh WM_DESKTOP hint for window 0x%lx " "(%i,%lu,%u)\n", FW_W(fw), HAS_EWMH_INIT_WM_DESKTOP(fw), fw->ewmh_hint_desktop, val[0]); #endif if (val[0] == (CARD32)-2 || val[0] == (CARD32)-1) { S_SET_IS_STICKY_ACROSS_PAGES(SCF(*style), 1); S_SET_IS_STICKY_ACROSS_PAGES(SCM(*style), 1); S_SET_IS_STICKY_ACROSS_PAGES(SCC(*style), 1); S_SET_IS_STICKY_ACROSS_DESKS(SCF(*style), 1); S_SET_IS_STICKY_ACROSS_DESKS(SCM(*style), 1); S_SET_IS_STICKY_ACROSS_DESKS(SCC(*style), 1); } else if (val[0] < 256) { /* prevent crazy hints ?? */ style->flags.use_start_on_desk = 1; style->flag_mask.use_start_on_desk = 1; style->change_mask.use_start_on_desk = 1; SSET_START_DESK(*style, val[0]); } SET_HAS_EWMH_INIT_WM_DESKTOP(fw, EWMH_STATE_HAS_HINT); fw->ewmh_hint_desktop = val[0]; free(val); } return 0; } int ewmh_MoveResize( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { int dir = -1; int x_warp = 0; int y_warp = 0; Bool move = False; char cmd[256]; if (ev == NULL) { return 0; } dir = ev->xclient.data.l[2]; switch(dir) { case _NET_WM_MOVERESIZE_SIZE_TOPLEFT: break; case _NET_WM_MOVERESIZE_SIZE_TOP: x_warp = 50; break; case _NET_WM_MOVERESIZE_SIZE_TOPRIGHT: x_warp = 100; break; case _NET_WM_MOVERESIZE_SIZE_RIGHT: x_warp = 100; y_warp = 50; break; case _NET_WM_MOVERESIZE_SIZE_KEYBOARD: case _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT: x_warp = 100; y_warp = 100; break; case _NET_WM_MOVERESIZE_SIZE_BOTTOM: x_warp = 50; y_warp = 100; break; case _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT: y_warp = 100; break; case _NET_WM_MOVERESIZE_SIZE_LEFT: y_warp = 50; break; case _NET_WM_MOVERESIZE_MOVE_KEYBOARD: case _NET_WM_MOVERESIZE_MOVE: move = True; break; default: return 0; } if (move) { if ( !is_function_allowed( F_MOVE, NULL, fw, RQORIG_PROGRAM_US, False)) { return 0; } } else { if ( !is_function_allowed( F_RESIZE, NULL, fw, RQORIG_PROGRAM_US, False)) { return 0; } } if (!move) { sprintf(cmd, "WarpToWindow %i %i",x_warp,y_warp); execute_function_override_window(NULL, NULL, cmd, 0, fw); } if (move) { execute_function_override_window( NULL, NULL, "Move", 0, fw); } else { execute_function_override_window( NULL, NULL, "Resize", 0, fw); } return 0; } /* * WM_STATE* */ int ewmh_WMState( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { unsigned long maximize = 0; if (ev != NULL) { ewmh_atom *a1,*a2; a1 = ewmh_GetEwmhAtomByAtom( ev->xclient.data.l[1], EWMH_ATOM_LIST_WM_STATE); a2 = ewmh_GetEwmhAtomByAtom( ev->xclient.data.l[2], EWMH_ATOM_LIST_WM_STATE); if (a1 != NULL) { maximize |= a1->action(fw, ev, NULL, 0); } if (a2 != NULL) { maximize |= a2->action(fw, ev, NULL, 0); } } else if (style != NULL) { CARD32 *val; unsigned int nitems; int size = 0; int i; ewmh_atom *list = ewmh_atom_wm_state; int has_hint = 0; val = ewmh_AtomGetByName( FW_W(fw), "_NET_WM_STATE", EWMH_ATOM_LIST_CLIENT_WIN, &size); if (val == NULL) { size = 0; } #if DEBUG_EWMH_INIT_STATE if (size != 0) { fprintf( stderr, "Window 0x%lx has an init" " _NET_WM_STATE hint\n",FW_W(fw)); } #endif nitems = size / sizeof(CARD32); while(list->name != NULL) { has_hint = 0; for(i = 0; i < nitems; i++) { if (list->atom == val[i]) { has_hint = 1; } } list->action(fw, NULL, style, has_hint); list++; } if (val != NULL) { free(val); } return 0; } if (maximize != 0) { int max_vert = (maximize & EWMH_MAXIMIZE_VERT)? 100:0; int max_horiz = (maximize & EWMH_MAXIMIZE_HORIZ)? 100:0; char cmd[256]; if (maximize & EWMH_MAXIMIZE_REMOVE) { sprintf(cmd,"Maximize off"); } else { if (!is_function_allowed( F_MAXIMIZE, NULL, fw, RQORIG_PROGRAM_US, False)) { return 0; } sprintf(cmd,"Maximize on %i %i", max_horiz, max_vert); } execute_function_override_window(NULL, NULL, cmd, 0, fw); } return 0; } int ewmh_WMStateFullScreen( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { if (ev == NULL && style == NULL) { return (IS_EWMH_FULLSCREEN(fw)); } if (ev == NULL && style != NULL) { /* start full screen */ unsigned long has_hint = any; #if DEBUG_EWMH_INIT_STATE if (has_hint) { fprintf(stderr,"\tFullscreen\n"); } #endif if (DO_EWMH_IGNORE_STATE_HINTS(style)) { SET_HAS_EWMH_INIT_FULLSCREEN_STATE( fw, EWMH_STATE_UNDEFINED_HINT); return 0; } if (HAS_EWMH_INIT_FULLSCREEN_STATE(fw) != EWMH_STATE_UNDEFINED_HINT) { return 0; } if (!has_hint) { SET_HAS_EWMH_INIT_FULLSCREEN_STATE( fw, EWMH_STATE_NO_HINT); return 0; } SET_EWMH_FULLSCREEN(fw,True); SET_HAS_EWMH_INIT_FULLSCREEN_STATE(fw, EWMH_STATE_HAS_HINT); return 0; } if (ev != NULL) { /* client message */ int bool_arg = ev->xclient.data.l[0]; int is_full_screen; is_full_screen = IS_EWMH_FULLSCREEN(fw); if ((bool_arg == NET_WM_STATE_TOGGLE && !is_full_screen) || bool_arg == NET_WM_STATE_ADD) { EWMH_fullscreen(fw); } else { if (HAS_EWMH_INIT_FULLSCREEN_STATE(fw) == EWMH_STATE_HAS_HINT) { /* the application started fullscreen */ SET_HAS_EWMH_INIT_FULLSCREEN_STATE( fw, EWMH_STATE_NO_HINT); } /* unmaximize will restore is_ewmh_fullscreen, * layer and apply_decor_change */ execute_function_override_window( NULL, NULL, "Maximize off", 0, fw); } if ((IS_EWMH_FULLSCREEN(fw) && !DO_EWMH_USE_STACKING_HINTS(fw)) || (!IS_EWMH_FULLSCREEN(fw) && DO_EWMH_USE_STACKING_HINTS(fw))) { /* On: if not raised by a layer cmd raise * Off: if lowered by a layer cmd raise */ execute_function_override_window( NULL, NULL, "Raise", 0, fw); } } return 0; } int ewmh_WMStateHidden( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { if (ev == NULL && style == NULL) { unsigned long do_restore = any; if (do_restore) { if (HAS_EWMH_INIT_HIDDEN_STATE(fw) == EWMH_STATE_HAS_HINT) { return True; } return False; } return IS_ICONIFIED(fw); } if (ev == NULL && style != NULL) { /* start iconified */ unsigned long has_hint = any; #if DEBUG_EWMH_INIT_STATE if (has_hint) fprintf(stderr,"\tHidden\n"); #endif if (DO_EWMH_IGNORE_STATE_HINTS(style)) { SET_HAS_EWMH_INIT_HIDDEN_STATE( fw, EWMH_STATE_UNDEFINED_HINT); return 0; } if (HAS_EWMH_INIT_HIDDEN_STATE(fw) != EWMH_STATE_UNDEFINED_HINT) { return 0; } if (!has_hint) { SET_HAS_EWMH_INIT_HIDDEN_STATE(fw, EWMH_STATE_NO_HINT); return 0; } style->flags.do_start_iconic = 1; style->flag_mask.do_start_iconic = 1; style->change_mask.do_start_iconic = 1; SET_HAS_EWMH_INIT_HIDDEN_STATE(fw, EWMH_STATE_HAS_HINT); return 0; } if (ev != NULL) { /* client message */ char cmd[16]; int bool_arg = ev->xclient.data.l[0]; if ((bool_arg == NET_WM_STATE_TOGGLE && !IS_ICONIFIED(fw)) || bool_arg == NET_WM_STATE_ADD) { /* iconify */ if ( !is_function_allowed( F_ICONIFY, NULL, fw, RQORIG_PROGRAM_US, False)) { return 0; } sprintf(cmd, "Iconify on"); } else { /* deiconify */ sprintf(cmd, "Iconify off"); } execute_function_override_window(NULL, NULL, cmd, 0, fw); } return 0; } int ewmh_WMStateMaxHoriz( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { if (ev == NULL && style == NULL) { #if 0 return (IS_MAXIMIZED(fw) && !IS_EWMH_FULLSCREEN(fw)); #else /* DV: the notion of vertical/horizontal maximization does not * make any sense in fvwm, so just claim we're never maximized */ return 0; #endif } if (ev == NULL && style != NULL) { unsigned long has_hint = any; #if DEBUG_EWMH_INIT_STATE if (has_hint) { fprintf( stderr, "\t Maxhoriz %i\n", HAS_EWMH_INIT_MAXHORIZ_STATE(fw)); } #endif if (DO_EWMH_IGNORE_STATE_HINTS(style)) { SET_HAS_EWMH_INIT_MAXHORIZ_STATE( fw, EWMH_STATE_UNDEFINED_HINT); return 0; } /* If the initial state is STATE_NO_HINT we still want to * override it, since having just one of MAXIMIZED_HORIZ or * MAXIMIZED_HORZ is enough to make the window maximized. */ if (HAS_EWMH_INIT_MAXHORIZ_STATE(fw) == EWMH_STATE_HAS_HINT) { return 0; } if (!has_hint) { SET_HAS_EWMH_INIT_MAXHORIZ_STATE( fw, EWMH_STATE_NO_HINT); return 0; } SET_HAS_EWMH_INIT_MAXHORIZ_STATE(fw, EWMH_STATE_HAS_HINT); return 0; } if (ev != NULL) { /* client message */ int cmd_arg = ev->xclient.data.l[0]; if ( !IS_MAXIMIZED(fw) && (cmd_arg == NET_WM_STATE_TOGGLE || cmd_arg == NET_WM_STATE_ADD)) { return EWMH_MAXIMIZE_HORIZ; } else if ( IS_MAXIMIZED(fw) && (cmd_arg == NET_WM_STATE_TOGGLE || cmd_arg == NET_WM_STATE_REMOVE)) { return EWMH_MAXIMIZE_REMOVE; } } return 0; } int ewmh_WMStateMaxVert( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { if (ev == NULL && style == NULL) { #if 0 return (IS_MAXIMIZED(fw) && !IS_EWMH_FULLSCREEN(fw)); #else /* DV: the notion of vertical/horizontal maximization does not * make any sense in fvwm, so just claim we're never maximized */ return 0; #endif } if (ev == NULL && style != NULL) { unsigned long has_hint = any; #if DEBUG_EWMH_INIT_STATE if (has_hint) { fprintf( stderr, "\t Maxvert %i\n", HAS_EWMH_INIT_MAXVERT_STATE(fw)); } #endif if (DO_EWMH_IGNORE_STATE_HINTS(style)) { SET_HAS_EWMH_INIT_MAXVERT_STATE( fw, EWMH_STATE_UNDEFINED_HINT); return 0; } if (HAS_EWMH_INIT_MAXVERT_STATE(fw) != EWMH_STATE_UNDEFINED_HINT) { return 0; } if (!has_hint) { SET_HAS_EWMH_INIT_MAXVERT_STATE( fw, EWMH_STATE_NO_HINT); return 0; } SET_HAS_EWMH_INIT_MAXVERT_STATE(fw, EWMH_STATE_HAS_HINT); return 0; } if (ev != NULL) { /* client message */ int cmd_arg = ev->xclient.data.l[0]; if ( !IS_MAXIMIZED(fw) && (cmd_arg == NET_WM_STATE_TOGGLE || cmd_arg == NET_WM_STATE_ADD)) { return EWMH_MAXIMIZE_VERT; } else if ( IS_MAXIMIZED(fw) && (cmd_arg == NET_WM_STATE_TOGGLE || cmd_arg == NET_WM_STATE_REMOVE)) { return EWMH_MAXIMIZE_REMOVE; } } return 0; } int ewmh_WMStateModal( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { if (ev == NULL && style == NULL) { unsigned long do_restore = any; if (do_restore) { if (HAS_EWMH_INIT_MODAL_STATE(fw) == EWMH_STATE_HAS_HINT) { return True; } return False; } return IS_EWMH_MODAL(fw); } if (ev == NULL && style != NULL) { unsigned long has_hint = any; #if DEBUG_EWMH_INIT_STATE if (has_hint) { fprintf( stderr, "\t Modal %i\n", HAS_EWMH_INIT_MODAL_STATE(fw)); } #endif if (DO_EWMH_IGNORE_STATE_HINTS(style)) { SET_HAS_EWMH_INIT_MODAL_STATE( fw, EWMH_STATE_UNDEFINED_HINT); return 0; } if (HAS_EWMH_INIT_MODAL_STATE(fw) != EWMH_STATE_UNDEFINED_HINT) { return 0; } if (!has_hint) { SET_HAS_EWMH_INIT_MODAL_STATE(fw, EWMH_STATE_NO_HINT); return 0; } /* the window map or had mapped with a modal hint */ if (IS_TRANSIENT(fw)) { SET_EWMH_MODAL(fw, True); /* the window is a modal transient window so we grab * the focus it will be good to raise it but ... */ FPS_GRAB_FOCUS_TRANSIENT( S_FOCUS_POLICY(SCF(*style)), 1); FPS_GRAB_FOCUS_TRANSIENT( S_FOCUS_POLICY(SCM(*style)), 1); FPS_GRAB_FOCUS_TRANSIENT( S_FOCUS_POLICY(SCC(*style)), 1); SET_HAS_EWMH_INIT_MODAL_STATE( fw, EWMH_STATE_HAS_HINT); } else { SET_EWMH_MODAL(fw, False); if (!FP_DO_GRAB_FOCUS_TRANSIENT( S_FOCUS_POLICY(SCF(*style)))) { FPS_GRAB_FOCUS_TRANSIENT( S_FOCUS_POLICY(SCF(*style)), 0); FPS_GRAB_FOCUS_TRANSIENT( S_FOCUS_POLICY(SCM(*style)), 1); FPS_GRAB_FOCUS_TRANSIENT( S_FOCUS_POLICY(SCC(*style)), 1); } } return 0; } if (ev != NULL && fw != NULL) { /* client message: I do not think we can get such message */ /* java sends this message */ int cmd_arg = ev->xclient.data.l[0]; if ( !IS_EWMH_MODAL(fw) && (cmd_arg == NET_WM_STATE_TOGGLE || cmd_arg == NET_WM_STATE_ADD)) { /* ON */ } else if ( IS_EWMH_MODAL(fw) && (cmd_arg == NET_WM_STATE_TOGGLE || cmd_arg == NET_WM_STATE_REMOVE)) { /* OFF */ } /* !MODAL MODAL * CMD * STATE_ADD ON do nothing * STATE_TOGGLE ON OFF * STATE_REMOVE do nothing OFF */ } return 0; } int ewmh_WMStateShaded( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { if (ev == NULL && style == NULL) { unsigned long do_restore = any; if (do_restore) { if (HAS_EWMH_INIT_SHADED_STATE(fw) == EWMH_STATE_HAS_HINT) { return True; } return False; } return IS_SHADED(fw); } if (ev == NULL && style != NULL) { /* start shaded */ unsigned long has_hint = any; #if DEBUG_EWMH_INIT_STATE if (has_hint) { fprintf( stderr, "\t Shaded %i\n", HAS_EWMH_INIT_SHADED_STATE(fw)); } #endif if (DO_EWMH_IGNORE_STATE_HINTS(style)) { SET_HAS_EWMH_INIT_SHADED_STATE( fw, EWMH_STATE_UNDEFINED_HINT); return 0; } if (HAS_EWMH_INIT_SHADED_STATE(fw) != EWMH_STATE_UNDEFINED_HINT) { return 0; } if (!has_hint) { SET_HAS_EWMH_INIT_SHADED_STATE( fw, EWMH_STATE_NO_HINT); return 0; } SET_SHADED(fw, 1); SET_SHADED_DIR(fw, GET_TITLE_DIR(fw)); SET_HAS_EWMH_INIT_SHADED_STATE(fw, EWMH_STATE_HAS_HINT); return 0; } if (ev != NULL) { /* client message */ int cmd_arg = ev->xclient.data.l[0]; if ( !IS_SHADED(fw) && (cmd_arg == NET_WM_STATE_TOGGLE || cmd_arg == NET_WM_STATE_ADD)) { execute_function_override_window( NULL, NULL, "Windowshade on", 0, fw); } else if ( IS_SHADED(fw) && (cmd_arg == NET_WM_STATE_TOGGLE || cmd_arg == NET_WM_STATE_REMOVE)) { execute_function_override_window( NULL, NULL, "Windowshade off", 0, fw); } } return 0; } int ewmh_WMStateSkipPager( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { if (ev == NULL && style == NULL) { unsigned long do_restore = any; if (do_restore) { if (HAS_EWMH_INIT_SKIP_PAGER_STATE(fw) == EWMH_STATE_HAS_HINT) { return True; } return False; } return DO_SKIP_WINDOW_LIST(fw); } if (ev == NULL && style != NULL) { unsigned long has_hint = any; #if DEBUG_EWMH_INIT_STATE /*if (has_hint)*/ fprintf( stderr, "\t Skip_Pager %lu, %i, %i\n", has_hint, HAS_EWMH_INIT_SKIP_PAGER_STATE(fw), DO_EWMH_IGNORE_STATE_HINTS(style)); #endif if (DO_EWMH_IGNORE_STATE_HINTS(style)) { SET_HAS_EWMH_INIT_SKIP_PAGER_STATE( fw, EWMH_STATE_UNDEFINED_HINT); return 0; } if (HAS_EWMH_INIT_SKIP_PAGER_STATE(fw) != EWMH_STATE_UNDEFINED_HINT) { return 0; } if (!has_hint) { SET_HAS_EWMH_INIT_SKIP_PAGER_STATE( fw, EWMH_STATE_NO_HINT); return 0; } S_SET_DO_WINDOW_LIST_SKIP(SCF(*style), 1); S_SET_DO_WINDOW_LIST_SKIP(SCM(*style), 1); S_SET_DO_WINDOW_LIST_SKIP(SCC(*style), 1); SET_HAS_EWMH_INIT_SKIP_PAGER_STATE(fw, EWMH_STATE_HAS_HINT); return 0; } if (ev != NULL) { /* I do not think we can get such client message */ int bool_arg = ev->xclient.data.l[0]; if ((bool_arg == NET_WM_STATE_TOGGLE && !DO_SKIP_WINDOW_LIST(fw)) || bool_arg == NET_WM_STATE_ADD) { } else { } } return 0; } int ewmh_WMStateSkipTaskBar( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { if (ev == NULL && style == NULL) { unsigned long do_restore = any; if (do_restore) { if (HAS_EWMH_INIT_SKIP_TASKBAR_STATE(fw) == EWMH_STATE_HAS_HINT) { return True; } return False; } return DO_SKIP_WINDOW_LIST(fw); } if (ev == NULL && style != NULL) { unsigned long has_hint = any; #if DEBUG_EWMH_INIT_STATE /*if (has_hint)*/ fprintf(stderr,"\t Skip_Taskbar %lu, %i, %i\n", has_hint, HAS_EWMH_INIT_SKIP_TASKBAR_STATE(fw), DO_EWMH_IGNORE_STATE_HINTS(style)); #endif if (DO_EWMH_IGNORE_STATE_HINTS(style)) { SET_HAS_EWMH_INIT_SKIP_TASKBAR_STATE( fw, EWMH_STATE_UNDEFINED_HINT); return 0; } if (HAS_EWMH_INIT_SKIP_TASKBAR_STATE(fw) != EWMH_STATE_UNDEFINED_HINT) { return 0; } if (!has_hint) { SET_HAS_EWMH_INIT_SKIP_TASKBAR_STATE( fw, EWMH_STATE_NO_HINT); return 0; } S_SET_DO_WINDOW_LIST_SKIP(SCF(*style), 1); S_SET_DO_WINDOW_LIST_SKIP(SCM(*style), 1); S_SET_DO_WINDOW_LIST_SKIP(SCC(*style), 1); SET_HAS_EWMH_INIT_SKIP_TASKBAR_STATE( fw, EWMH_STATE_HAS_HINT); return 0; } if (ev != NULL) { /* I do not think we can get such client message */ int bool_arg = ev->xclient.data.l[0]; if ((bool_arg == NET_WM_STATE_TOGGLE && !DO_SKIP_WINDOW_LIST(fw)) || bool_arg == NET_WM_STATE_ADD) { } else { } } return 0; } int ewmh_WMStateStaysOnTop( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { if (ev == NULL && style == NULL) { unsigned long do_restore = any; if (do_restore) { if (fw->ewmh_hint_layer == Scr.TopLayer) { return True; } return False; } if (fw->layer >= Scr.TopLayer) { return True; } return False; } if (ev == NULL && style != NULL) { unsigned long has_hint = any; #if DEBUG_EWMH_INIT_STATE if (has_hint) { fprintf(stderr,"\tStaysOnTop\n"); } #endif if (!DO_EWMH_USE_STACKING_HINTS(style)) { return 0; } if (!has_hint && fw->ewmh_hint_layer == 0) { fw->ewmh_hint_layer = -1; return 0; } if (fw->ewmh_hint_layer == -1) { return 0; } fw->ewmh_hint_layer = Scr.TopLayer; SSET_LAYER(*style, Scr.TopLayer); style->flags.use_layer = 1; style->flag_mask.use_layer = 1; style->change_mask.use_layer = 1; return 0; } if (ev != NULL) { /* client message */ int cmd_arg = ev->xclient.data.l[0]; if (!DO_EWMH_USE_STACKING_HINTS(fw)) { /* if we don't pay attention to the hints, * I don't think we should honor this request also */ return 0; } if (fw->layer < Scr.TopLayer && (cmd_arg == NET_WM_STATE_TOGGLE || cmd_arg == NET_WM_STATE_ADD)) { new_layer(fw, Scr.TopLayer); } else if ( fw->layer == Scr.TopLayer && (cmd_arg == NET_WM_STATE_TOGGLE || cmd_arg == NET_WM_STATE_REMOVE)) { new_layer(fw, Scr.DefaultLayer); } /* layer < TopLayer layer == TopLayer * CMD * STATE_ADD new_layer(TOP) do nothing * STATE_TOGGLE new_layer(TOP) new_layer(DEFAULT) * STATE_REMOVE do nothing new_layer(DEFAULT) */ } return 0; } int ewmh_WMStateStaysOnBottom( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { if (ev == NULL && style == NULL) { unsigned long do_restore = any; if (do_restore) { if (fw->ewmh_hint_layer == Scr.BottomLayer) { return True; } return False; } if (fw->layer <= Scr.BottomLayer) { return True; } return False; } if (ev == NULL && style != NULL) { unsigned long has_hint = any; #if DEBUG_EWMH_INIT_STATE if (has_hint) fprintf(stderr,"\tStaysOnBottom\n"); #endif if (!DO_EWMH_USE_STACKING_HINTS(style)) { return 0; } if (!has_hint && fw->ewmh_hint_layer == 0) { fw->ewmh_hint_layer = -1; return 0; } if (fw->ewmh_hint_layer == -1) { return 0; } fw->ewmh_hint_layer = Scr.BottomLayer; SSET_LAYER(*style, Scr.BottomLayer); style->flags.use_layer = 1; style->flag_mask.use_layer = 1; style->change_mask.use_layer = 1; return 0; } if (ev != NULL) { /* client message */ int cmd_arg = ev->xclient.data.l[0]; if (!DO_EWMH_USE_STACKING_HINTS(fw)) { /* if we don't pay attention to the hints, * I don't think we should honor this request also */ return 0; } if ( fw->layer > Scr.BottomLayer && (cmd_arg == NET_WM_STATE_TOGGLE || cmd_arg == NET_WM_STATE_ADD)) { new_layer(fw, Scr.BottomLayer); } else if ( fw->layer == Scr.BottomLayer && (cmd_arg == NET_WM_STATE_TOGGLE || cmd_arg == NET_WM_STATE_REMOVE)) { new_layer(fw, Scr.DefaultLayer); } /* layer > BottomLayer layer == BottomLayer * CMD * STATE_ADD new_layer(BOTTOM) do nothing * STATE_TOGGLE new_layer(BOTTOM) new_layer(DEFAULT) * STATE_REMOVE do nothing new_layer(DEFAULT) */ } return 0; } int ewmh_WMStateSticky( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { if (ev == NULL && style == NULL) { unsigned long do_restore = any; if (do_restore) { if (HAS_EWMH_INIT_STICKY_STATE(fw) == EWMH_STATE_HAS_HINT) { return True; } return False; } return (IS_STICKY_ACROSS_PAGES(fw) && IS_STICKY_ACROSS_DESKS(fw)); } if (ev == NULL && style != NULL) { /* start sticky */ unsigned long has_hint = any; #if DEBUG_EWMH_INIT_STATE if (has_hint) { fprintf(stderr,"\t Sticky\n"); } #endif if (DO_EWMH_IGNORE_STATE_HINTS(style)) { SET_HAS_EWMH_INIT_STICKY_STATE( fw, EWMH_STATE_UNDEFINED_HINT); return 0; } if (HAS_EWMH_INIT_STICKY_STATE(fw) != EWMH_STATE_UNDEFINED_HINT) { return 0; } if (!has_hint) { SET_HAS_EWMH_INIT_STICKY_STATE( fw, EWMH_STATE_NO_HINT); return 0; } S_SET_IS_STICKY_ACROSS_PAGES(SCF(*style), 1); S_SET_IS_STICKY_ACROSS_PAGES(SCM(*style), 1); S_SET_IS_STICKY_ACROSS_PAGES(SCC(*style), 1); S_SET_IS_STICKY_ACROSS_DESKS(SCF(*style), 1); S_SET_IS_STICKY_ACROSS_DESKS(SCM(*style), 1); S_SET_IS_STICKY_ACROSS_DESKS(SCC(*style), 1); SET_HAS_EWMH_INIT_STICKY_STATE(fw, EWMH_STATE_HAS_HINT); return 0; } if (ev != NULL) { /* client message */ int bool_arg = ev->xclient.data.l[0]; if ((bool_arg == NET_WM_STATE_TOGGLE && (!IS_STICKY_ACROSS_PAGES(fw) || !IS_STICKY_ACROSS_DESKS(fw))) || bool_arg == NET_WM_STATE_ADD) { execute_function_override_window( NULL, NULL, "Stick on", 0, fw); } else if ((IS_STICKY_ACROSS_PAGES(fw) || IS_STICKY_ACROSS_DESKS(fw)) && (bool_arg == NET_WM_STATE_TOGGLE || bool_arg == NET_WM_STATE_REMOVE)) { execute_function_override_window( NULL, NULL, "Stick off", 1, fw); } } return 0; } /* * Property Notify (_NET_WM_ICON is in ewmh_icon.c, _NET_WM_*NAME are in * ewmh_name) * */ int ewmh_WMIconGeometry( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { int size; CARD32 *val; /* FIXME: After a (un)slide of kicker the geometry are wrong (not * because we set the geometry just after the property notify). This * does not happen with kwin */ val = ewmh_AtomGetByName( FW_W(fw), "_NET_WM_ICON_GEOMETRY", EWMH_ATOM_LIST_PROPERTY_NOTIFY, &size); if (val != NULL && size < 4 * sizeof(CARD32)) { fvwm_msg( WARN, "ewmh_WMIconGeometry", "The application window (id %#lx)\n" " \"%s\" tried to set to an icon geometry via EWMH\n" " but provided only %d of the 4 values required.\n" " fvwm is ignoring this request.\n", fw ? FW_W(fw) : 0, fw ? fw->name.name : "(none)", (int)(size / sizeof(CARD32))); fvwm_msg_report_app_and_workers(); free(val); val = NULL; } if (val == NULL) { fw->ewmh_icon_geometry.x = 0; fw->ewmh_icon_geometry.y = 0; fw->ewmh_icon_geometry.width = 0; fw->ewmh_icon_geometry.height = 0; return 0; } fw->ewmh_icon_geometry.x = val[0]; fw->ewmh_icon_geometry.y = val[1]; fw->ewmh_icon_geometry.width = val[2]; fw->ewmh_icon_geometry.height = val[3]; free(val); return 0; } /**** for animation ****/ void EWMH_GetIconGeometry(FvwmWindow *fw, rectangle *icon_rect) { if (!IS_ICON_SUPPRESSED(fw) || (fw->ewmh_icon_geometry.x == 0 && fw->ewmh_icon_geometry.y == 0 && fw->ewmh_icon_geometry.width == 0 && fw->ewmh_icon_geometry.height == 0)) { return; } icon_rect->x = fw->ewmh_icon_geometry.x; icon_rect->y = fw->ewmh_icon_geometry.y; icon_rect->width = fw->ewmh_icon_geometry.width; icon_rect->height = fw->ewmh_icon_geometry.height; return; } int ewmh_WMStrut( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { int size = 0; CARD32 *val; if (ev == NULL) { fw->dyn_strut.left = fw->strut.left = 0; fw->dyn_strut.right = fw->strut.right = 0; fw->dyn_strut.top = fw->strut.top = 0; fw->dyn_strut.bottom = fw->strut.bottom = 0; } val = ewmh_AtomGetByName( FW_W(fw), "_NET_WM_STRUT", EWMH_ATOM_LIST_PROPERTY_NOTIFY, &size); if (val == NULL) { return 0; } if ((val[0] > 0 || val[1] > 0 || val[2] > 0 || val[3] > 0) && (val[0] != fw->strut.left || val[1] != fw->strut.right || val[2] != fw->strut.top || val[3] != fw->strut.bottom)) { fw->strut.left = val[0]; fw->strut.right = val[1]; fw->strut.top = val[2]; fw->strut.bottom = val[3]; ewmh_ComputeAndSetWorkArea(); } if (val[0] != fw->dyn_strut.left || val[1] != fw->dyn_strut.right || val[2] != fw->dyn_strut.top || val[3] != fw->dyn_strut.bottom) { fw->dyn_strut.left = val[0]; fw->dyn_strut.right = val[1]; fw->dyn_strut.top = val[2]; fw->dyn_strut.bottom = val[3]; ewmh_HandleDynamicWorkArea(); } free(val); return 0; } Bool EWMH_ProcessClientMessage(const exec_context_t *exc) { ewmh_atom *ewmh_a = NULL; FvwmWindow *fw = exc->w.fw; XEvent *ev = exc->x.elast; if ((ewmh_a = (ewmh_atom *)ewmh_GetEwmhAtomByAtom( ev->xclient.message_type, EWMH_ATOM_LIST_CLIENT_ROOT)) != NULL) { if (ewmh_a->action != None) { ewmh_a->action(fw, ev, NULL, 0); } return True; } if ((ewmh_a = (ewmh_atom *)ewmh_GetEwmhAtomByAtom( ev->xclient.message_type, EWMH_ATOM_LIST_CLIENT_WIN)) == NULL) { return False; } if (ev->xclient.window == None) { return False; } /* these one are special: we can get it on an unamaged window */ if (StrEquals(ewmh_a->name, "_NET_MOVERESIZE_WINDOW") || StrEquals(ewmh_a->name, "_NET_RESTACK_WINDOW")) { ewmh_a->action(fw, ev, NULL, 0); return True; } if (fw == NULL) { return False; } if ((ewmh_a = (ewmh_atom *)ewmh_GetEwmhAtomByAtom( ev->xclient.message_type, EWMH_ATOM_LIST_CLIENT_WIN)) != NULL) { if (ewmh_a->action != None) { ewmh_a->action(fw, ev, NULL, 0); } return True; } return False; } void EWMH_ProcessPropertyNotify(const exec_context_t *exc) { ewmh_atom *ewmh_a = NULL; FvwmWindow *fw = exc->w.fw; XEvent *ev = exc->x.elast; if ((ewmh_a = (ewmh_atom *)ewmh_GetEwmhAtomByAtom( ev->xproperty.atom, EWMH_ATOM_LIST_PROPERTY_NOTIFY)) != NULL) { if (ewmh_a->action != None) { flush_property_notify_stop_at_event_type( ev->xproperty.atom, FW_W(fw), 0, 0); if (XGetGeometry( dpy, FW_W(fw), &JunkRoot, &JunkX, &JunkY, (unsigned int*)&JunkWidth, (unsigned int*)&JunkHeight, (unsigned int*)&JunkBW, (unsigned int*)&JunkDepth) == 0) { /* Window does not exist anymore. */ return; } ewmh_a->action(fw, ev, NULL, 0); } } } fvwm-2.7.0/fvwm/geometry.h0000644000175000017500000000635014147024700012406 00000000000000/* -*-c-*- */ #ifndef GEOMETRY_H #define GEOMETRY_H #define CS_ROUND_UP 0x01 #define CS_UPDATE_MAX_DEFECT 0x02 void gravity_get_naked_geometry( int gravity, FvwmWindow *t, rectangle *dest_g, rectangle *orig_g); void gravity_add_decoration( int gravity, FvwmWindow *t, rectangle *dest_g, rectangle *orig_g); void get_relative_geometry(rectangle *rel_g, rectangle *abs_g); void get_absolute_geometry(rectangle *abs_g, rectangle *rel_g); void gravity_translate_to_northwest_geometry( int gravity, FvwmWindow *t, rectangle *dest_g, rectangle *orig_g); void gravity_translate_to_northwest_geometry_no_bw( int gravity, FvwmWindow *t, rectangle *dest_g, rectangle *orig_g); void get_title_geometry( FvwmWindow *fw, rectangle *ret_g); int get_title_gravity( FvwmWindow *fw); void get_title_gravity_factors( FvwmWindow *fw, int *ret_fx, int *ret_fy); Bool get_title_button_geometry( FvwmWindow *fw, rectangle *ret_g, int context); void get_title_font_size_and_offset( FvwmWindow *fw, direction_t title_dir, Bool is_left_title_rotated_cw, Bool is_right_title_rotated_cw, Bool is_top_title_rotated, Bool is_bottom_title_rotated, int *size, int *offset); void get_icon_corner( FvwmWindow *fw, rectangle *ret_g); void get_shaded_geometry( FvwmWindow *fw, rectangle *small_g, rectangle *big_g); void get_shaded_geometry_with_dir( FvwmWindow *fw, rectangle *small_g, rectangle *big_g, direction_t shade_dir); void get_unshaded_geometry( FvwmWindow *fw, rectangle *ret_g); void get_shaded_client_window_pos( FvwmWindow *fw, rectangle *ret_g); void get_client_geometry( FvwmWindow *fw, rectangle *ret_g); void get_window_borders( const FvwmWindow *fw, size_borders *borders); void get_window_borders_no_title( const FvwmWindow *fw, size_borders *borders); void set_window_border_size( FvwmWindow *fw, int used_width); Bool is_window_border_minimal( FvwmWindow *fw); void update_relative_geometry(FvwmWindow *fw); void update_absolute_geometry(FvwmWindow *fw); void maximize_adjust_offset(FvwmWindow *fw); void constrain_size( FvwmWindow *fw, const XEvent *e, int *widthp, int *heightp, int xmotion, int ymotion, int flags); void gravity_constrain_size( int gravity, FvwmWindow *t, rectangle *rect, int flags); Bool get_visible_window_or_icon_geometry( FvwmWindow *fw, rectangle *ret_g); Bool get_visible_icon_geometry( FvwmWindow *fw, rectangle *ret_g); void get_icon_geometry( FvwmWindow *fw, rectangle *ret_g); Bool get_visible_icon_title_geometry( FvwmWindow *fw, rectangle *ret_g); Bool get_icon_title_geometry( FvwmWindow *fw, rectangle *ret_g); Bool get_visible_icon_picture_geometry( FvwmWindow *fw, rectangle *ret_g); Bool get_icon_picture_geometry( FvwmWindow *fw, rectangle *ret_g); void broadcast_icon_geometry(FvwmWindow *fw, Bool do_force); void move_icon_to_position(FvwmWindow *fw); void modify_icon_position(FvwmWindow *fw, int dx, int dy); void set_icon_position(FvwmWindow *fw, int x, int y); void set_icon_picture_size(FvwmWindow *fw, int w, int h); void resize_icon_title_height(FvwmWindow *fw, int dh); void get_page_offset_rectangle( int *ret_page_x, int *ret_page_y, rectangle *r); void get_page_offset( int *ret_page_x, int *ret_page_y, FvwmWindow *fw); void get_page_offset_check_visible( int *ret_page_x, int *ret_page_y, FvwmWindow *fw); #endif fvwm-2.7.0/fvwm/module_list.h0000644000175000017500000000766314147024700013103 00000000000000/* -*-c-*- */ #ifndef FVWM_MODULE_LIST_H #define FVWM_MODULE_LIST_H #include "libs/Module.h" #include "libs/queue.h" /* for F_CMD_ARGS */ #include "fvwm/fvwm.h" /* please don't use msg_masks_t and PipeMask outside of module_interface.c. * They are only global to allow to access the IS_MESSAGE_SELECTED macro without * having to call a function. */ typedef struct msg_masks_t { unsigned long m1; unsigned long m2; } msg_masks_t; /* module linked list record, only to be accessed by using the access macros * below */ typedef struct fmodule { struct { unsigned is_cmdline_module : 1; } xflags; int xreadPipe; int xwritePipe; fqueue xpipeQueue; msg_masks_t xPipeMask; msg_masks_t xNoGrabMask; msg_masks_t xSyncMask; char *xname; char *xalias; } fmodule; #define MOD_IS_CMDLINE(m) ((m)->xflags.is_cmdline_module) #define MOD_SET_CMDLINE(m,on) ((m)->xflags.is_cmdline_module = !!(on)) typedef struct fmodule_store { fmodule *module; struct fmodule_store *next; } fmodule_store; /* This defines the module list object */ typedef fmodule_store* fmodule_list; /* this objects allows safe iteration over a module list */ typedef fmodule_store* fmodule_list_itr; #define MOD_READFD(m) ((m)->xreadPipe) #define MOD_WRITEFD(m) ((m)->xwritePipe) #define MOD_PIPEQUEUE(m) ((m)->xpipeQueue) #define MOD_PIPEMASK(m) ((m)->xPipeMask) #define MOD_NAME(m) ((m)->xname) #define MOD_ALIAS(m) ((m)->xalias) /* this is a bit long winded to allow MAX_MESSAGE to be 32 and not get an * integer overflow with (1 << MAX_MESSAGES) and even with * (1<<(MAX_MESSAGES-1)) - 1 */ #define DEFAULT_MASK (MAX_MSG_MASK & ~(M_SENDCONFIG)) #define DEFAULT_XMASK (DEFAULT_XMSG_MASK) /* * Returns zero if the msg is not selected by the mask. Takes care of normal * and extended messages. */ #define IS_MESSAGE_IN_MASK(mask, msg) \ (((msg)&M_EXTENDED_MSG) ? ((mask)->m2 & (msg)) : ((mask)->m1 & (msg))) /* * Returns non zero if one of the specified messages is selected for the module */ #define IS_MESSAGE_SELECTED(module, msg_mask) \ IS_MESSAGE_IN_MASK(&(MOD_PIPEMASK(module)), (msg_mask)) /* * M_SENDCONFIG for modules to tell fvwm that they want to see each * module configuration command as it is entered. Causes modconf.c to * look at each active module, find the ones that sent M_SENDCONFIG, and * send a copy of the command in an M_CONFIG_INFO command. */ /* struct to store module input data */ typedef struct fmodule_input { Window window; fmodule *module; char *command; } fmodule_input; /* * Basic Module Handling Functions */ /* kill all modules */ void module_kill_all(void); /* kill a module */ void module_kill(fmodule *module); /* execute module wraper, desperate mode */ fmodule *executeModuleDesperate(F_CMD_ARGS); /* * Basic Module Communication Functions */ /* send "raw" data to the module */ /* module_send(fmodule *module, unsigned long *ptr, int size); */ void PositiveWrite(fmodule *module, unsigned long *ptr, int size); /* returns a dynamicaly allocated struct with the received data * or NULL on error */ fmodule_input *module_receive(fmodule *module); /* frees an input data struct */ void module_input_discard(fmodule_input *input); /* returns true if received the "expect" string, false otherwise */ Bool module_input_expect(fmodule_input *input, char *expect); /* * Utility Functions */ /* initializes the given iterator */ void module_list_itr_init(fmodule_list_itr *itr); /* gets the next module on the list */ fmodule *module_list_itr_next(fmodule_list_itr *itr); /* free modules in the deathrow */ void module_cleanup(void); /* * Message Queue Handling Functions */ /* message queues */ void FlushAllMessageQueues(void); void FlushMessageQueue(fmodule *module); /* * Misc Functions (should they be here?) */ /* * exposed to be used by modconf.c */ char *skipModuleAliasToken(const char *string); /* dead pipe signal handler - empty */ RETSIGTYPE DeadPipe(int nonsense); #endif /* MODULE_LIST_H */ fvwm-2.7.0/fvwm/add_window.c0000644000175000017500000026137614147024700012700 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* This module is based on Twm, but has been siginificantly modified * by Rob Nation */ /* * Copyright 1988 by Evans & Sutherland Computer Corporation, * Salt Lake City, Utah * Portions Copyright 1989 by the Massachusetts Institute of Technology * Cambridge, Massachusetts * * All Rights Reserved * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice appear in all * copies and that both that copyright notice and this permis- * sion notice appear in supporting documentation, and that the * names of Evans & Sutherland and M.I.T. not be used in advertising * in publicity pertaining to distribution of the software without * specific, written prior permission. * * EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- * ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR * M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- * AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE * OR PERFORMANCE OF THIS SOFTWARE. */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include "libs/fvwmlib.h" #include "libs/FShape.h" #include "libs/FScreen.h" #include "libs/Picture.h" #include "libs/PictureUtils.h" #include "libs/charmap.h" #include "libs/wcontext.h" #include "libs/Grab.h" #include "libs/Strings.h" #include "libs/XResource.h" #include "fvwm.h" #include "externs.h" #include "cursor.h" #include "execcontext.h" #include "commands.h" #include "bindings.h" #include "misc.h" #include "screen.h" #include "add_window.h" #include "events.h" #include "eventhandler.h" #include "eventmask.h" #include "module_interface.h" #include "stack.h" #include "update.h" #include "style.h" #include "icons.h" #include "ewmh.h" #include "focus.h" #include "placement.h" #include "geometry.h" #include "session.h" #include "move_resize.h" #include "borders.h" #include "frame.h" #include "colormaps.h" #include "decorations.h" #include "functions.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* ---------------------------- exported variables (globals) --------------- */ char NoName[] = "Untitled"; /* name if no name in XA_WM_NAME */ char NoClass[] = "NoClass"; /* Class if no res_class in class hints */ char NoResource[] = "NoResource"; /* Class if no res_name in class hints */ /* ---------------------------- local functions ---------------------------- */ static void delete_client_context(FvwmWindow *fw) { FvwmWindow *cw; /* We can not simply delete the context. X might have reused the * window structure so we would delete the context that was established * by another FvwmWindow structure in the mean time. */ if (XFindContext( dpy, FW_W(fw), FvwmContext, (caddr_t *)&cw) != XCNOENT && cw == fw) { XDeleteContext(dpy, FW_W(fw), FvwmContext); } return; } /* * * Procedure: * CaptureOneWindow * CaptureAllWindows * * Decorates windows at start-up and during recaptures * */ static void CaptureOneWindow( const exec_context_t *exc, FvwmWindow *fw, Window window, Window keep_on_top_win, Window parent_win, Bool is_recapture) { Window w; unsigned long data[1]; initial_window_options_t win_opts; evh_args_t ea; exec_context_changes_t ecc; XEvent e; if (fw == NULL) { return; } if (IS_SCHEDULED_FOR_DESTROY(fw)) { /* Fvwm might crash in complex functions if we really try to * the dying window here because AddWindow() may fail and leave * a destroyed window in some structures. By the way, it is * pretty useless to recapture a window that will vanish in a * moment. */ return; } /* Grab the server to make sure the window does not die during the * recapture. */ MyXGrabServer(dpy); if ( !XGetGeometry( dpy, FW_W(fw), &JunkRoot, &JunkX, &JunkY, (unsigned int*)&JunkWidth, (unsigned int*)&JunkHeight, (unsigned int*)&JunkBW, (unsigned int*)&JunkDepth)) { /* The window has already died, do not recapture it! */ MyXUngrabServer(dpy); return; } if (XFindContext(dpy, window, FvwmContext, (caddr_t *)&fw) != XCNOENT) { Bool is_mapped = IS_MAPPED(fw); memset(&win_opts, 0, sizeof(win_opts)); win_opts.initial_state = DontCareState; win_opts.flags.do_override_ppos = 1; win_opts.flags.is_recapture = 1; if (IS_ICONIFIED(fw)) { win_opts.initial_state = IconicState; win_opts.flags.is_iconified_by_parent = IS_ICONIFIED_BY_PARENT(fw); } else { win_opts.initial_state = NormalState; win_opts.flags.is_iconified_by_parent = 0; if (Scr.CurrentDesk != fw->Desk) { SetMapStateProp(fw, NormalState); } } data[0] = (unsigned long) fw->Desk; XChangeProperty( dpy, FW_W(fw), _XA_WM_DESKTOP, _XA_WM_DESKTOP, 32, PropModeReplace, (unsigned char *) data, 1); XSelectInput(dpy, FW_W(fw), NoEventMask); w = FW_W(fw); XUnmapWindow(dpy, FW_W_FRAME(fw)); border_undraw_decorations(fw); RestoreWithdrawnLocation(fw, is_recapture, parent_win); SET_DO_REUSE_DESTROYED(fw, 1); /* RBW - 1999/03/20 */ destroy_window(fw); win_opts.flags.is_menu = (is_recapture && fw != NULL && IS_TEAR_OFF_MENU(fw)); fev_make_null_event(&e, dpy); e.xmaprequest.window = w; e.xmaprequest.parent = Scr.Root; ecc.x.etrigger = &e; ecc.w.fw = NULL; ecc.w.w = w; ecc.w.wcontext = C_ROOT; ea.exc = exc_clone_context( exc, &ecc, ECC_ETRIGGER | ECC_FW | ECC_W | ECC_WCONTEXT); HandleMapRequestKeepRaised(&ea, keep_on_top_win, fw, &win_opts); exc_destroy_context(ea.exc); /* HandleMapRequestKeepRaised may have destroyed the fw if the * window vanished while in AddWindow(), so don't access fw * anymore before checking if it is a valid window. */ if (check_if_fvwm_window_exists(fw)) { if (!fFvwmInStartup) { SET_MAP_PENDING(fw, 0); SET_MAPPED(fw, is_mapped); } } } MyXUngrabServer(dpy); return; } /* Put a transparent window all over the screen to hide what happens below. */ static void hide_screen( Bool do_hide, Window *ret_hide_win, Window *ret_parent_win) { static Bool is_hidden = False; static Window hide_win = None; static Window parent_win = None; XSetWindowAttributes xswa; unsigned long valuemask; if (do_hide == is_hidden) { /* nothing to do */ if (ret_hide_win) { *ret_hide_win = hide_win; } if (ret_parent_win) { *ret_parent_win = parent_win; } return; } is_hidden = do_hide; if (do_hide) { xswa.override_redirect = True; xswa.cursor = Scr.FvwmCursors[CRS_WAIT]; xswa.backing_store = NotUseful; xswa.save_under = False; xswa.background_pixmap = None; valuemask = CWOverrideRedirect | CWCursor | CWSaveUnder | CWBackingStore | CWBackPixmap; hide_win = XCreateWindow( dpy, Scr.Root, 0, 0, Scr.MyDisplayWidth, Scr.MyDisplayHeight, 0, Pdepth, InputOutput, Pvisual, valuemask, &xswa); if (hide_win) { /* When recapturing, all windows are reparented to this * window. If they are reparented to the root window, * they will flash over the hide_win with XFree. So * reparent them to an unmapped window that looks like * the root window. */ parent_win = XCreateWindow( dpy, Scr.Root, 0, 0, Scr.MyDisplayWidth, Scr.MyDisplayHeight, 0, CopyFromParent, InputOutput, CopyFromParent, valuemask, &xswa); if (!parent_win) { XDestroyWindow(dpy, hide_win); hide_win = None; } else { XMapWindow(dpy, hide_win); XFlush(dpy); } } } else { if (hide_win != None) { XDestroyWindow(dpy, hide_win); } if (parent_win != None) { XDestroyWindow(dpy, parent_win); } XFlush(dpy); hide_win = None; parent_win = None; } if (ret_hide_win) { *ret_hide_win = hide_win; } if (ret_parent_win) { *ret_parent_win = parent_win; } return; } /* * * Procedure: * MappedNotOverride - checks to see if we should really * put a fvwm frame on the window * * Returned Value: * 1 - go ahead and frame the window * 0 - don't frame the window * * Inputs: * w - the window to check * */ static int MappedNotOverride( Window w, initial_window_options_t *win_opts) { XWindowAttributes wa; Atom atype; int aformat; unsigned long nitems, bytes_remain; unsigned char *prop; win_opts->initial_state = DontCareState; if ((w==Scr.NoFocusWin)||(!XGetWindowAttributes(dpy, w, &wa))) { return 0; } if (XGetWindowProperty( dpy,w,_XA_WM_STATE,0L,3L,False,_XA_WM_STATE, &atype,&aformat,&nitems,&bytes_remain,&prop)==Success) { if (prop != NULL) { win_opts->initial_state = *(long *)prop; XFree(prop); } } if (wa.override_redirect == True) { XSelectInput(dpy, w, XEVMASK_ORW); XFlush(dpy); } return (((win_opts->initial_state == IconicState) || (wa.map_state != IsUnmapped)) && (wa.override_redirect != True)); } static void do_recapture(F_CMD_ARGS, Bool fSingle) { FvwmWindow *fw = exc->w.fw; int event_types[5] = { ButtonPress, ButtonRelease, MotionNotify, KeyPress, KeyRelease }; MyXGrabServer(dpy); if (fSingle) { CaptureOneWindow( exc, fw, FW_W(fw), None, None, True); } else { CaptureAllWindows(exc, True); } /* Throw away queued up events. We don't want user input during a * recapture. The window the user clicks in might disapper at the very * same moment and the click goes through to the root window. Not good */ XAllowEvents(dpy, AsyncPointer, CurrentTime); discard_typed_events(5, event_types); #ifdef DEBUG_STACK_RING verify_stack_ring_consistency(); #endif MyXUngrabServer(dpy); return; } static void setup_window_structure( FvwmWindow **pfw, Window w, FvwmWindow *ReuseWin) { FvwmWindow save_state; FvwmWindow *savewin = NULL; /* Allocate space for the FvwmWindow struct, or reuse an old one (on Recapture). */ if (ReuseWin == NULL) { *pfw = (FvwmWindow *)safemalloc(sizeof(FvwmWindow)); } else { *pfw = ReuseWin; savewin = &save_state; memcpy(savewin, ReuseWin, sizeof(FvwmWindow)); } /* RBW - 1999/05/28 - modify this when we implement the preserving of various states across a Recapture. The Destroy function in misc.c may also need tweaking, depending on what you want to preserve. For now, just zap any old information, except the desk. */ memset(*pfw, '\0', sizeof(FvwmWindow)); FW_W(*pfw) = w; if (savewin != NULL) { (*pfw)->Desk = savewin->Desk; SET_SHADED(*pfw, IS_SHADED(savewin)); SET_USED_TITLE_DIR_FOR_SHADING( *pfw, USED_TITLE_DIR_FOR_SHADING(savewin)); SET_SHADED_DIR(*pfw, SHADED_DIR(savewin)); SET_NAME_CHANGED(*pfw,IS_NAME_CHANGED(savewin)); (*pfw)->placed_by_button = savewin->placed_by_button; SET_PLACED_BY_FVWM(*pfw, IS_PLACED_BY_FVWM(savewin)); SET_HAS_EWMH_WM_ICON_HINT(*pfw, HAS_EWMH_WM_ICON_HINT(savewin)); (*pfw)->ewmh_mini_icon_width = savewin->ewmh_mini_icon_width; (*pfw)->ewmh_mini_icon_height = savewin->ewmh_mini_icon_height; (*pfw)->ewmh_icon_width = savewin->ewmh_icon_width; (*pfw)->ewmh_icon_height = savewin->ewmh_icon_height; (*pfw)->ewmh_hint_desktop = savewin->ewmh_hint_desktop; /* restore ewmh state */ EWMH_SetWMState(savewin, True); SET_HAS_EWMH_INIT_WM_DESKTOP( *pfw, HAS_EWMH_INIT_WM_DESKTOP(savewin)); SET_HAS_EWMH_INIT_FULLSCREEN_STATE( *pfw, HAS_EWMH_INIT_FULLSCREEN_STATE(savewin)); SET_HAS_EWMH_INIT_HIDDEN_STATE( *pfw, HAS_EWMH_INIT_HIDDEN_STATE(savewin)); SET_HAS_EWMH_INIT_MAXHORIZ_STATE( *pfw, HAS_EWMH_INIT_MAXHORIZ_STATE(savewin)); SET_HAS_EWMH_INIT_MAXVERT_STATE( *pfw, HAS_EWMH_INIT_MAXVERT_STATE(savewin)); SET_HAS_EWMH_INIT_SHADED_STATE( *pfw, HAS_EWMH_INIT_SHADED_STATE(savewin)); SET_HAS_EWMH_INIT_STICKY_STATE( *pfw, HAS_EWMH_INIT_STICKY_STATE(savewin)); CLEAR_USER_STATES(*pfw, ~0); SET_USER_STATES(*pfw, GET_USER_STATES(savewin)); } else { /* make sure that new windows *remember* being shaded with * title dir last */ SET_USED_TITLE_DIR_FOR_SHADING(*pfw,1); } (*pfw)->cmap_windows = (Window *)NULL; if (FMiniIconsSupported) { (*pfw)->mini_pixmap_file = NULL; (*pfw)->mini_icon = NULL; } return; } static void setup_name_count(FvwmWindow *fw, Bool is_icon) { FvwmWindow *t; int count = 0; int win_count; int win_count_counterpart; Bool done = False; FlocaleNameString *titlename, *title_counterpart; FlocaleNameString *t_titlename, *t_title_counterpart; titlename = (is_icon) ? &(fw->icon_name) : &(fw->name); title_counterpart = (is_icon) ? &(fw->name) : &(fw->icon_name); if (!titlename->name) { done = True; } if (titlename->name && title_counterpart->name && strcmp(titlename->name, title_counterpart->name) == 0) { count = is_icon ? fw->icon_name_count : fw->name_count; } while (!done) { done = True; for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) { if (t == fw) { continue; } win_count = is_icon ? t->icon_name_count : t->name_count; win_count_counterpart = is_icon ? t->name_count : t->icon_name_count; t_titlename = is_icon ? &(t->icon_name) : &(t->name); t_title_counterpart = is_icon ? &(t->name) : &(t->icon_name); if ((t_titlename->name && strcmp(titlename->name, t_titlename->name) == 0 && win_count == count) || (t_title_counterpart->name && strcmp(t_title_counterpart->name, titlename->name) == 0 && win_count_counterpart == count)) { count++; done = False; } } } if (is_icon) { fw->icon_name_count = count; } else { fw->name_count = count; } return; } static char *interpolate_titleformat_name( int *ret_bits, FvwmWindow *fw, window_style *style, Bool is_icon) { char stringbuf[MAX_VISIBLE_NAME_LEN] = ""; /* Get the title format string. This check should be redundant thanks * to the checking done in style.c */ const char *format; int count; /* MAX_WINDOW_NAME_NUMBER is defined as "999" -- that's three * characters maximum. win_name_len must be 1 larger for null. */ char win_name_len[MAX_WINDOW_NAME_NUMBER_DIGITS+1]; char w_id[12]; *ret_bits = 0; if (is_icon) { format = (style->flags.has_icon_title_format_string) ? SGET_ICON_TITLE_FORMAT_STRING(*style) : DEFAULT_ICON_TITLE_FORMAT; } else { format = (style->flags.has_title_format_string) ? SGET_TITLE_FORMAT_STRING(*style) : DEFAULT_TITLE_FORMAT; } while (*format) { int pos; for (pos = 0; format[pos] && format[pos] != '%'; pos++) { /* nothing */ } strncat(stringbuf, format, pos); format += pos; if (*format != '%') continue; format++; switch (*format) { case 'n': /* format contains the window name */ *ret_bits |= 1; if (strlen(stringbuf) + strlen(fw->name.name) > MAX_VISIBLE_NAME_LEN) { fvwm_msg(WARN, "interpolate_titleformat_name", "Visible name is too long based on " "TitleFormat. Not expanding further."); break; } strcat(stringbuf, fw->name.name); break; case 'c': if (strlen(stringbuf) + strlen(fw->class.res_class) > MAX_VISIBLE_NAME_LEN) { fvwm_msg(WARN, "interpolate_titleformat_name", "Visible name is too long based on " "TitleFormat. Not expanding further."); break; } strcat(stringbuf, fw->class.res_class); break; case 'i': /* format contains icon name */ *ret_bits |= 2; /* Not every application will have an icon * name set; don't crash trying to dereference * this if the name doesn't exist. */ if (fw->icon_name.name == NULL) break; if (strlen(stringbuf) + strlen(fw->icon_name.name) > MAX_VISIBLE_NAME_LEN) { fvwm_msg(WARN, "interpolate_titleformat_name", "Visible name is too long based on " "TitleFormat. Not expanding further."); break; } strcat(stringbuf, fw->icon_name.name); break; case 'r': if (strlen(stringbuf) + strlen(fw->class.res_name) > MAX_VISIBLE_NAME_LEN) { fvwm_msg(WARN, "interpolate_titleformat_name", "Visible name is too long based on " "TitleFormat. Not expanding further."); break; } strcat(stringbuf, fw->class.res_name); break; case 't': setup_name_count(fw, is_icon); count = is_icon ? fw->icon_name_count : fw->name_count; if (count > (MAX_WINDOW_NAME_NUMBER - 1)) count = MAX_WINDOW_NAME_NUMBER - 1; sprintf(win_name_len, "%d", ++count); strcat(stringbuf, win_name_len); break; case 'I': sprintf(w_id, "0x%x", (int)FW_W(fw)); strcat(stringbuf, w_id); break; case '%': strcat(stringbuf, "%"); break; default: break; } if (*format) format++; } /* Now allocate our string. */ return strdup(stringbuf); } static void setup_class_and_resource(FvwmWindow *fw) { /* removing NoClass change for now... */ fw->class.res_name = NoResource; fw->class.res_class = NoClass; XGetClassHint(dpy, FW_W(fw), &fw->class); if (fw->class.res_name == NULL) { fw->class.res_name = NoResource; } if (fw->class.res_class == NULL) { fw->class.res_class = NoClass; } FetchWmProtocols (fw); FetchWmColormapWindows (fw); return; } static void setup_window_attr( FvwmWindow *fw, XWindowAttributes *ret_attr) { if (XGetWindowAttributes(dpy, FW_W(fw), ret_attr) == 0) { /* can't happen because fvwm has grabbed the server and does * not destroy the window itself */ } fw->attr_backup.backing_store = ret_attr->backing_store; fw->attr_backup.border_width = ret_attr->border_width; fw->attr_backup.depth = ret_attr->depth; fw->attr_backup.bit_gravity = ret_attr->bit_gravity; fw->attr_backup.is_bit_gravity_stored = 0; fw->attr_backup.visual = ret_attr->visual; fw->attr_backup.colormap = ret_attr->colormap; return; } static void destroy_window_font(FvwmWindow *fw) { if (IS_WINDOW_FONT_LOADED(fw) && !USING_DEFAULT_WINDOW_FONT(fw) && fw->title_font != Scr.DefaultFont) { FlocaleUnloadFont(dpy, fw->title_font); } SET_WINDOW_FONT_LOADED(fw, 0); /* Fall back to default font. There are some race conditions when a * window is destroyed and recaptured where an invalid font might be * accessed otherwise. */ fw->title_font = Scr.DefaultFont; SET_USING_DEFAULT_WINDOW_FONT(fw, 1); return; } static void destroy_icon_font(FvwmWindow *fw) { if (IS_ICON_FONT_LOADED(fw) && !USING_DEFAULT_ICON_FONT(fw) && fw->icon_font != Scr.DefaultFont) { FlocaleUnloadFont(dpy, fw->icon_font); } SET_ICON_FONT_LOADED(fw, 0); /* Fall back to default font (see comment above). */ fw->icon_font = Scr.DefaultFont; SET_USING_DEFAULT_ICON_FONT(fw, 1); return; } static void adjust_fvwm_internal_windows(FvwmWindow *fw) { if (fw == Scr.Hilite) { Scr.Hilite = NULL; } update_last_screen_focus_window(fw); restore_focus_after_unmap(fw, False); frame_destroyed_frame(FW_W(fw)); if (fw == Scr.StolenFocusFvwmWin) { Scr.StolenFocusWin = None; Scr.StolenFocusFvwmWin = NULL; } if (Scr.focus_in_pending_window == fw) { Scr.focus_in_pending_window = NULL; } if (Scr.focus_in_requested_window == fw) { Scr.focus_in_requested_window = NULL; } if (Scr.cascade_window == fw) { Scr.cascade_window = NULL; } return; } static void broadcast_mini_icon(FvwmWindow *fw) { if (!FMiniIconsSupported) { return; } if (fw->mini_pixmap_file && fw->mini_icon) { BroadcastFvwmPicture( M_MINI_ICON, FW_W(fw), FW_W_FRAME(fw), (unsigned long)fw, fw->mini_icon, fw->mini_pixmap_file); } return; } static void setup_mini_icon(FvwmWindow *fw, window_style *pstyle) { FvwmPictureAttributes fpa; if (!FMiniIconsSupported) { return; } if (SHAS_MINI_ICON(&pstyle->flags)) { fw->mini_pixmap_file = SGET_MINI_ICON_NAME(*pstyle); } else { fw->mini_pixmap_file = NULL; } if (fw->mini_pixmap_file) { fpa.mask = 0; fw->mini_icon = PCacheFvwmPicture( dpy, Scr.NoFocusWin, NULL, fw->mini_pixmap_file, fpa); } else { fw->mini_icon = NULL; } return; } /* * Copy icon size limits from window_style structure to FvwmWindow * structure. */ void setup_icon_size_limits(FvwmWindow *fw, window_style *pstyle) { if (SHAS_ICON_SIZE_LIMITS(&pstyle->flags)) { fw->min_icon_width = SGET_MIN_ICON_WIDTH(*pstyle); fw->min_icon_height = SGET_MIN_ICON_HEIGHT(*pstyle); fw->max_icon_width = SGET_MAX_ICON_WIDTH(*pstyle); fw->max_icon_height = SGET_MAX_ICON_HEIGHT(*pstyle); fw->icon_resize_type = SGET_ICON_RESIZE_TYPE(*pstyle); } else { fw->min_icon_width = MIN_ALLOWABLE_ICON_DIMENSION; fw->min_icon_height = MIN_ALLOWABLE_ICON_DIMENSION; fw->max_icon_width = MAX_ALLOWABLE_ICON_DIMENSION; fw->max_icon_height = MAX_ALLOWABLE_ICON_DIMENSION; fw->icon_resize_type = ICON_RESIZE_TYPE_NONE; } return; } void setup_icon_background_parameters(FvwmWindow *fw, window_style *pstyle) { if (SHAS_ICON_BACKGROUND_PADDING(&pstyle->flags)) { fw->icon_background_padding = SGET_ICON_BACKGROUND_PADDING(*pstyle); } else { fw->icon_background_padding = ICON_BACKGROUND_PADDING; } if (SHAS_ICON_BACKGROUND_RELIEF(&pstyle->flags)) { fw->icon_background_relief = SGET_ICON_BACKGROUND_RELIEF(*pstyle); } else { fw->icon_background_relief = ICON_RELIEF_WIDTH; } return; } void setup_icon_title_parameters(FvwmWindow *fw, window_style *pstyle) { if (SHAS_ICON_TITLE_RELIEF(&pstyle->flags)) { fw->icon_title_relief = SGET_ICON_TITLE_RELIEF(*pstyle); } else { fw->icon_title_relief = ICON_RELIEF_WIDTH; } return; } void setup_numeric_vals(FvwmWindow *fw, window_style *pstyle) { /****** window shading ******/ fw->shade_anim_steps = pstyle->shade_anim_steps; /****** snapattraction, snapgrid, paging ******/ fw->snap_attraction.proximity = pstyle->snap_attraction.proximity; fw->snap_attraction.mode = pstyle->snap_attraction.mode; fw->snap_grid_x = pstyle->snap_grid_x; fw->snap_grid_y = pstyle->snap_grid_y; if (pstyle->flags.has_edge_delay_ms_move) { fw->edge_delay_ms_move = pstyle->edge_delay_ms_move; } else { fw->edge_delay_ms_move = DEFAULT_MOVE_DELAY; } if (pstyle->flags.has_edge_delay_ms_resize) { fw->edge_delay_ms_resize = pstyle->edge_delay_ms_resize; } else { fw->edge_delay_ms_resize = DEFAULT_RESIZE_DELAY; } fw->edge_resistance_move = pstyle->edge_resistance_move; fw->edge_resistance_xinerama_move = pstyle->edge_resistance_xinerama_move; return; } static void setup_frame_window( FvwmWindow *fw) { XSetWindowAttributes attributes; int valuemask; int depth; Visual *visual; FRenderPictFormat *format; valuemask = CWBackingStore | CWBackPixmap | CWEventMask | CWSaveUnder | CWCursor; /* This adds preliminary support for ARGB windows in fvwm. It should evolve to proper ARGB support in frames, menus and modules */ format=FRenderFindVisualFormat(dpy, fw->attr_backup.visual); if (format != NULL && format->type == FRenderPictTypeDirect && format->direct.alphaMask > 0) { depth = fw->attr_backup.depth; visual = fw->attr_backup.visual; attributes.colormap = fw->attr_backup.colormap; attributes.background_pixel = -1; attributes.border_pixel = -1; valuemask |= CWColormap | CWBackPixel | CWBorderPixel; } else { depth = CopyFromParent; visual = CopyFromParent; } attributes.backing_store = NotUseful; attributes.background_pixmap = None; attributes.cursor = Scr.FvwmCursors[CRS_DEFAULT]; attributes.event_mask = XEVMASK_FRAMEW_CAPTURE; attributes.save_under = False; /* create the frame window, child of root, grandparent of client */ FW_W_FRAME(fw) = XCreateWindow( dpy, Scr.Root, fw->g.frame.x, fw->g.frame.y, fw->g.frame.width, fw->g.frame.height, 0, depth, InputOutput, visual, valuemask, &attributes); XSaveContext(dpy, FW_W(fw), FvwmContext, (caddr_t) fw); XSaveContext(dpy, FW_W_FRAME(fw), FvwmContext, (caddr_t) fw); return; } static void setup_title_window( FvwmWindow *fw, int valuemask, XSetWindowAttributes *pattributes) { valuemask |= CWCursor | CWEventMask; pattributes->cursor = Scr.FvwmCursors[CRS_TITLE]; pattributes->event_mask = XEVMASK_TITLEW; FW_W_TITLE(fw) = XCreateWindow( dpy, FW_W_FRAME(fw), 0, 0, 1, 1, 0, Pdepth, InputOutput, Pvisual, valuemask, pattributes); XSaveContext(dpy, FW_W_TITLE(fw), FvwmContext, (caddr_t) fw); return; } static void destroy_title_window(FvwmWindow *fw, Bool do_only_delete_context) { if (!do_only_delete_context) { XDestroyWindow(dpy, FW_W_TITLE(fw)); FW_W_TITLE(fw) = None; } XDeleteContext(dpy, FW_W_TITLE(fw), FvwmContext); XFlush(dpy); FW_W_TITLE(fw) = None; return; } static void change_title_window( FvwmWindow *fw, int valuemask, XSetWindowAttributes *pattributes) { if (HAS_TITLE(fw) && FW_W_TITLE(fw) == None) { setup_title_window(fw, valuemask, pattributes); } else if (!HAS_TITLE(fw) && FW_W_TITLE(fw) != None) { destroy_title_window(fw, False); } return; } static void setup_button_windows( FvwmWindow *fw, int valuemask, XSetWindowAttributes *pattributes, short buttons) { int i; Bool has_button; Bool is_deleted = False; valuemask |= CWCursor | CWEventMask; pattributes->cursor = Scr.FvwmCursors[CRS_SYS]; pattributes->event_mask = XEVMASK_BUTTONW; for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; i++) { has_button = (((!(i & 1) && i / 2 < Scr.nr_left_buttons) || ( (i & 1) && i / 2 < Scr.nr_right_buttons)) && (buttons & (1 << i))); if (FW_W_BUTTON(fw, i) == None && has_button) { FW_W_BUTTON(fw, i) = XCreateWindow( dpy, FW_W_FRAME(fw), 0, 0, 1, 1, 0, Pdepth, InputOutput, Pvisual, valuemask, pattributes); XSaveContext( dpy, FW_W_BUTTON(fw, i), FvwmContext, (caddr_t)fw); } else if (FW_W_BUTTON(fw, i) != None && !has_button) { /* destroy the current button window */ XDestroyWindow(dpy, FW_W_BUTTON(fw, i)); XDeleteContext(dpy, FW_W_BUTTON(fw, i), FvwmContext); is_deleted = True; FW_W_BUTTON(fw, i) = None; } } if (is_deleted == True) { XFlush(dpy); } return; } static void destroy_button_windows(FvwmWindow *fw, Bool do_only_delete_context) { int i; Bool is_deleted = False; for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; i++) { if (FW_W_BUTTON(fw, i) != None) { if (!do_only_delete_context) { XDestroyWindow(dpy, FW_W_BUTTON(fw, i)); FW_W_BUTTON(fw, i) = None; } XDeleteContext(dpy, FW_W_BUTTON(fw, i), FvwmContext); is_deleted = True; FW_W_BUTTON(fw, i) = None; } } if (is_deleted == True) { XFlush(dpy); } return; } static void change_button_windows( FvwmWindow *fw, int valuemask, XSetWindowAttributes *pattributes, short buttons) { if (HAS_TITLE(fw)) { setup_button_windows( fw, valuemask, pattributes, buttons); } else { destroy_button_windows(fw, False); } return; } static void setup_parent_window(FvwmWindow *fw) { size_borders b; XSetWindowAttributes attributes; int valuemask; valuemask = CWBackingStore | CWBackPixmap | CWCursor | CWEventMask | CWSaveUnder; attributes.backing_store = NotUseful; attributes.background_pixmap = None; attributes.cursor = Scr.FvwmCursors[CRS_DEFAULT]; attributes.event_mask = XEVMASK_PARENTW; attributes.save_under = False; /* This window is exactly the same size as the client for the benefit * of some clients */ get_window_borders(fw, &b); FW_W_PARENT(fw) = XCreateWindow( dpy, FW_W_FRAME(fw), b.top_left.width, b.top_left.height, fw->g.frame.width - b.total_size.width, fw->g.frame.height - b.total_size.height, 0, CopyFromParent, InputOutput, CopyFromParent, valuemask, &attributes); XSaveContext(dpy, FW_W_PARENT(fw), FvwmContext, (caddr_t) fw); return; } static void setup_resize_handle_cursors(FvwmWindow *fw) { unsigned long valuemask; XSetWindowAttributes attributes; int i; if (HAS_NO_BORDER(fw)) { return; } valuemask = CWCursor; attributes.cursor = Scr.FvwmCursors[CRS_DEFAULT]; for (i = 0; i < 4; i++) { if (HAS_HANDLES(fw)) { attributes.cursor = Scr.FvwmCursors[CRS_TOP_LEFT + i]; } XChangeWindowAttributes( dpy, FW_W_CORNER(fw, i), valuemask, &attributes); if (HAS_HANDLES(fw)) { attributes.cursor = Scr.FvwmCursors[CRS_TOP + i]; } XChangeWindowAttributes( dpy, FW_W_SIDE(fw, i), valuemask, &attributes); } return; } static void setup_resize_handle_windows(FvwmWindow *fw) { unsigned long valuemask; XSetWindowAttributes attributes; int i; int c_grav[4] = { NorthWestGravity, NorthEastGravity, SouthWestGravity, SouthEastGravity }; int s_grav[4] = { NorthWestGravity, NorthEastGravity, SouthWestGravity, NorthWestGravity }; if (HAS_NO_BORDER(fw)) { return; } valuemask = CWEventMask | CWBackingStore | CWSaveUnder | CWWinGravity | CWBorderPixel | CWColormap; attributes.event_mask = XEVMASK_BORDERW; attributes.backing_store = NotUseful; attributes.save_under = False; attributes.border_pixel = 0; attributes.colormap = Pcmap; /* Just dump the windows any old place and let frame_setup_window take * care of the mess */ for (i = 0; i < 4; i++) { attributes.win_gravity = c_grav[i]; FW_W_CORNER(fw, i) = XCreateWindow( dpy, FW_W_FRAME(fw), -1, -1, 1, 1, 0, Pdepth, InputOutput, Pvisual, valuemask, &attributes); XSaveContext( dpy, FW_W_CORNER(fw, i), FvwmContext, (caddr_t)fw); attributes.win_gravity = s_grav[i]; FW_W_SIDE(fw, i) = XCreateWindow( dpy, FW_W_FRAME(fw), -1, -1, 1, 1, 0, Pdepth, InputOutput, Pvisual, valuemask, &attributes); XSaveContext(dpy, FW_W_SIDE(fw, i), FvwmContext, (caddr_t)fw); } setup_resize_handle_cursors(fw); return; } static void destroy_resize_handle_windows( FvwmWindow *fw, Bool do_only_delete_context) { int i; for (i = 0; i < 4 ; i++) { XDeleteContext(dpy, FW_W_SIDE(fw, i), FvwmContext); XDeleteContext(dpy, FW_W_CORNER(fw, i), FvwmContext); if (!do_only_delete_context) { XDestroyWindow(dpy, FW_W_SIDE(fw, i)); XDestroyWindow(dpy, FW_W_CORNER(fw, i)); FW_W_SIDE(fw, i) = None; FW_W_CORNER(fw, i) = None; } } XFlush(dpy); return; } static void change_resize_handle_windows(FvwmWindow *fw) { if (!HAS_NO_BORDER(fw) && FW_W_SIDE(fw, 0) == None) { setup_resize_handle_windows(fw); } else if (HAS_NO_BORDER(fw) && FW_W_SIDE(fw, 0) != None) { destroy_resize_handle_windows(fw, False); } else { setup_resize_handle_cursors(fw); } return; } static void setup_frame_stacking(FvwmWindow *fw) { int i; int n; Window w[10 + NUMBER_OF_TITLE_BUTTONS]; /* Stacking order (top to bottom): * - Parent window * - Title and buttons * - Corner handles * - Side handles */ n = 0; if (!IS_SHADED(fw)) { w[n] = FW_W_PARENT(fw); n++; } if (HAS_TITLE(fw)) { for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; i += 2) { if (FW_W_BUTTON(fw, i) != None) { w[n] = FW_W_BUTTON(fw, i); n++; } } for (i = 2 * NR_RIGHT_BUTTONS - 1; i > 0; i -= 2) { if (FW_W_BUTTON(fw, i) != None) { w[n] = FW_W_BUTTON(fw, i); n++; } } if (FW_W_TITLE(fw) != None) { w[n] = FW_W_TITLE(fw); n++; } } for (i = 0; i < 4; i++) { if (FW_W_CORNER(fw, i) != None) { w[n] = FW_W_CORNER(fw, i); n++; } } for (i = 0; i < 4; i++) { if (FW_W_SIDE(fw, i) != None) { w[n] = FW_W_SIDE(fw, i); n++; } } if (IS_SHADED(fw)) { w[n] = FW_W_PARENT(fw); n++; } XRestackWindows(dpy, w, n); return; } static void get_default_window_attributes( FvwmWindow *fw, unsigned long *pvaluemask, XSetWindowAttributes *pattributes) { *pvaluemask |= CWBackingStore | CWCursor | CWSaveUnder | CWBorderPixel | CWColormap | CWBackPixmap; pattributes->background_pixel = 0; pattributes->background_pixmap = None; pattributes->backing_store = NotUseful; pattributes->cursor = Scr.FvwmCursors[CRS_DEFAULT]; pattributes->save_under = False; pattributes->border_pixel = 0; pattributes->colormap = Pcmap; return; } static void setup_auxiliary_windows( FvwmWindow *fw, Bool setup_frame_and_parent, short buttons) { unsigned long valuemask_save = 0; XSetWindowAttributes attributes; get_default_window_attributes(fw, &valuemask_save, &attributes); if (setup_frame_and_parent) { setup_frame_window(fw); setup_parent_window(fw); } setup_resize_handle_windows(fw); if (HAS_TITLE(fw)) { setup_title_window(fw, valuemask_save, &attributes); setup_button_windows(fw, valuemask_save, &attributes, buttons); } setup_frame_stacking(fw); XMapSubwindows (dpy, FW_W_FRAME(fw)); return; } static void destroy_auxiliary_windows( FvwmWindow *fw, Bool destroy_frame_and_parent) { if (destroy_frame_and_parent) { XDeleteContext(dpy, FW_W_FRAME(fw), FvwmContext); XDeleteContext(dpy, FW_W_PARENT(fw), FvwmContext); delete_client_context(fw); XDestroyWindow(dpy, FW_W_FRAME(fw)); } if (HAS_TITLE(fw)) { destroy_title_window(fw, True); } if (HAS_TITLE(fw)) { destroy_button_windows(fw, True); } if (!HAS_NO_BORDER(fw)) { destroy_resize_handle_windows(fw, True); } XFlush(dpy); return; } static void broadcast_window_names(FvwmWindow *fw, int changed_names) { if (changed_names & 1) { EWMH_SetVisibleName(fw, False); BroadcastWindowIconNames(fw, True, False); } if (changed_names & 2) { EWMH_SetVisibleName(fw, True); BroadcastWindowIconNames(fw, False, True); } } static void setup_icon(FvwmWindow *fw, window_style *pstyle) { int affected_titles; increase_icon_hint_count(fw); /* find a suitable icon pixmap */ if ((fw->wmhints) && (fw->wmhints->flags & IconWindowHint)) { if (SHAS_ICON(&pstyle->flags) && S_ICON_OVERRIDE(SCF(*pstyle)) == ICON_OVERRIDE) { ICON_DBG((stderr,"si: iwh ignored '%s'\n", fw->name.name)); fw->icon_bitmap_file = SGET_ICON_NAME(*pstyle); } else { ICON_DBG((stderr,"si: using iwh '%s'\n", fw->name.name)); fw->icon_bitmap_file = NULL; } } else if ((fw->wmhints) && (fw->wmhints->flags & IconPixmapHint)) { if (SHAS_ICON(&pstyle->flags) && S_ICON_OVERRIDE(SCF(*pstyle)) != NO_ICON_OVERRIDE) { ICON_DBG((stderr,"si: iph ignored '%s'\n", fw->name.name)); fw->icon_bitmap_file = SGET_ICON_NAME(*pstyle); } else { ICON_DBG((stderr,"si: using iph '%s'\n", fw->name.name)); fw->icon_bitmap_file = NULL; } } else if (SHAS_ICON(&pstyle->flags)) { /* an icon was specified */ ICON_DBG((stderr,"si: using style '%s'\n", fw->name.name)); fw->icon_bitmap_file = SGET_ICON_NAME(*pstyle); } else { /* use default icon */ ICON_DBG((stderr,"si: using default '%s'\n", fw->name.name)); fw->icon_bitmap_file = Scr.DefaultIcon; } /* icon name */ if (!EWMH_WMIconName(fw, NULL, NULL, 0)) { fw->icon_name.name = NoName; fw->icon_name.name_list = NULL; FlocaleGetNameProperty( XGetWMIconName, dpy, FW_W(fw), &(fw->icon_name)); } if (fw->icon_name.name == NoName) { fw->icon_name.name = fw->name.name; SET_WAS_ICON_NAME_PROVIDED(fw, 0); } affected_titles = setup_visible_names(fw, 2); /* wait until the window is iconified and the icon window is mapped * before creating the icon window */ FW_W_ICON_TITLE(fw) = None; broadcast_window_names(fw, affected_titles); if (fw->icon_bitmap_file != NULL && fw->icon_bitmap_file != Scr.DefaultIcon) { BroadcastName(M_ICON_FILE,FW_W(fw),FW_W_FRAME(fw), (unsigned long)fw,fw->icon_bitmap_file); } return; } static void destroy_icon(FvwmWindow *fw) { free_window_names(fw, False, True); if (IS_PIXMAP_OURS(fw)) { XFreePixmap(dpy, fw->iconPixmap); fw->iconPixmap = None; if (fw->icon_maskPixmap != None) { XFreePixmap(dpy, fw->icon_maskPixmap); fw->icon_maskPixmap = None; } if (fw->icon_alphaPixmap != None) { XFreePixmap(dpy, fw->icon_alphaPixmap); fw->icon_alphaPixmap = None; } if (fw->icon_alloc_pixels != NULL) { if (fw->icon_nalloc_pixels != 0) { PictureFreeColors( dpy, Pcmap, fw->icon_alloc_pixels, fw->icon_nalloc_pixels, 0, fw->icon_no_limit); } free(fw->icon_alloc_pixels); fw->icon_alloc_pixels = NULL; fw->icon_nalloc_pixels = 0; fw->icon_no_limit = 0; } } if (FW_W_ICON_TITLE(fw)) { XDestroyWindow(dpy, FW_W_ICON_TITLE(fw)); XDeleteContext(dpy, FW_W_ICON_TITLE(fw), FvwmContext); XFlush(dpy); } if (FW_W_ICON_PIXMAP(fw) != None) { if (IS_ICON_OURS(fw)) { XDestroyWindow(dpy, FW_W_ICON_PIXMAP(fw)); } else { XUnmapWindow(dpy, FW_W_ICON_PIXMAP(fw)); } XDeleteContext(dpy, FW_W_ICON_PIXMAP(fw), FvwmContext); } clear_icon(fw); XFlush(dpy); return; } static void setup_icon_boxes(FvwmWindow *fw, window_style *pstyle) { icon_boxes *ib; /* copy iconboxes ptr (if any) */ if (SHAS_ICON_BOXES(&pstyle->flags)) { fw->IconBoxes = SGET_ICON_BOXES(*pstyle); for (ib = fw->IconBoxes; ib; ib = ib->next) { ib->use_count++; } } else { fw->IconBoxes = NULL; } return; } static void destroy_icon_boxes(FvwmWindow *fw) { if (fw->IconBoxes) { fw->IconBoxes->use_count--; if (fw->IconBoxes->use_count == 0 && fw->IconBoxes->is_orphan) { /* finally destroy the icon box */ free_icon_boxes(fw->IconBoxes); fw->IconBoxes = NULL; } } return; } static void setup_layer(FvwmWindow *fw, window_style *pstyle) { FvwmWindow *tf; int layer; if (SUSE_LAYER(&pstyle->flags)) { /* use layer from style */ layer = SGET_LAYER(*pstyle); } else if ((tf = get_transientfor_fvwmwindow(fw)) != NULL) { /* inherit layer from transientfor window */ layer = get_layer(tf); } else { /* use default layer */ layer = Scr.DefaultLayer; } set_default_layer(fw, layer); set_layer(fw, layer); return; } static void destroy_mini_icon(FvwmWindow *fw) { if (fw->mini_icon) { PDestroyFvwmPicture(dpy, fw->mini_icon); fw->mini_icon = 0; } return; } static void setup_key_and_button_grabs(FvwmWindow *fw) { #ifdef BUGS_ARE_COOL /* dv (29-May-2001): If keys are grabbed separately for C_WINDOW and * the other contexts, new windows have problems when bindings are * removed. Therefore, grab all keys in a single pass through the * list. */ GrabAllWindowKeys( dpy, FW_W_FRAME(fw), Scr.AllBindings, C_WINDOW|C_TITLE|C_RALL|C_LALL|C_SIDEBAR, GetUnusedModifiers(), True); #endif GrabAllWindowKeys( dpy, FW_W_FRAME(fw), Scr.AllBindings, C_TITLE|C_RALL|C_LALL|C_SIDEBAR|C_WINDOW, GetUnusedModifiers(), True); setup_focus_policy(fw); return; } static void __add_window_handle_x_resources(FvwmWindow *fw) { int client_argc = 0; char **client_argv = NULL; XrmValue rm_value; XrmDatabase db = NULL; static XrmOptionDescRec table [] = { {"-xrn", NULL, XrmoptionResArg, (caddr_t) NULL}, {"-xrm", NULL, XrmoptionResArg, (caddr_t) NULL}, }; /* Get global X resources */ MergeXResources(dpy, &db, False); /* Find out if the client requested a specific style on the command * line. */ if (XGetCommand(dpy, FW_W(fw), &client_argv, &client_argc)) { if (client_argc > 0 && client_argv != NULL) { /* command line takes precedence over all */ MergeCmdLineResources( &db, table, 2, fw->class.res_name, &client_argc, client_argv, True); } } /* parse the database values */ if (GetResourceString(db, "fvwmstyle", fw->class.res_name, &rm_value) && rm_value.size != 0) { char *style_name; int name_len; style_name = rm_value.addr; name_len = rm_value.size-1; /* Trim spaces at the start of the name */ while (name_len>0 && isspace(*style_name)) { style_name++; name_len--; } /* Trim spaces at the end of the name */ while (name_len>0 && isspace(*(style_name+name_len-1))) { name_len--; } if (name_len>0) { fw->style_name = (char*)safemalloc(sizeof(char)* (name_len+1)); memcpy(fw->style_name,style_name,name_len); fw->style_name[name_len] = 0; } } XFreeStringList(client_argv); XrmDestroyDatabase(db); return; } static int is_geometry_invalid_with_hints( const rectangle *g, const XSizeHints *hints) { if (hints->min_width > g->width) { return 1; } else if (hints->min_height > g->height) { return 2; } else if (hints->max_width < g->width) { return 3; } else if (hints->max_height < g->height) { return 4; } if (hints->width_inc > 0) { int remainder; remainder = (g->width - hints->base_width) % hints->width_inc; if (remainder != 0) { return 5; } } if (hints->height_inc > 0) { int remainder; remainder = (g->height - hints->base_height) % hints->height_inc; if (remainder != 0) { return 6; } } if (hints->flags & PAspect) { if ( (long)g->width * (long)hints->min_aspect.y < (long)hints->min_aspect.x * (long)g->height) { /* aspect smaller than minimum aspect */ return 7; } if ( (long)g->width * (long)hints->max_aspect.y > (long)hints->max_aspect.x * (long)g->height) { /* aspect larger than maximum aspect */ return 8; } } return 0; } /* ---------------------------- interface functions ------------------------ */ /* what_changed: * 1 = title name * 2 = icon name * 3 = both * 4 = title format style * 8 = icon title format style * * Returns which titles need to be updated (like what_changed). The return * value can be used as the 'which' argument of update_window_names. */ int setup_visible_names(FvwmWindow *fw, int what_changed) { char *ext_name; window_style style; int affected_titles; int changed_names; int changed_styles; int force_update; int bits; if (fw == NULL) { /* should never happen */ return 0; } changed_names = (what_changed & 3); changed_styles = ((what_changed >> 2) & 3); force_update = changed_styles; if (fw->visible_name == NULL) { force_update |= 1; } if (fw->visible_icon_name == NULL) { force_update |= 2; } affected_titles = 0; affected_titles |= changed_styles; /* TA: Get the window style. */ lookup_style(fw, &style); if (changed_names != 0 || (force_update & 1)) { ext_name = interpolate_titleformat_name( &bits, fw, &style, False); if ((changed_names & bits) || (force_update & 1)) { fw->visible_name = ext_name; affected_titles |= 1; } else { free(ext_name); } } if (changed_names != 0 || (force_update & 2)) { ext_name = interpolate_titleformat_name( &bits, fw, &style, True); if ((changed_names & bits) || (force_update & 2)) { fw->visible_icon_name = ext_name; affected_titles |= 2; } else { free(ext_name); } } return (changed_styles) ? changed_styles : affected_titles; } /* changed_names: * 1 = title * 2 = icon * 3 = both */ void update_window_names(FvwmWindow *fw, int changed_names) { int affected_titles; affected_titles = setup_visible_names(fw, changed_names); affected_titles |= changed_names; /* fix the name in the title bar */ if (!IS_ICONIFIED(fw)) { border_draw_decorations( fw, PART_TITLE, (Scr.Hilite == fw), True, CLEAR_ALL, NULL, NULL); } broadcast_window_names(fw, affected_titles); if (affected_titles & 2) { RedoIconName(fw); } return; } void setup_window_name(FvwmWindow *fw) { if (!EWMH_WMName(fw, NULL, NULL, 0)) { fw->name.name = NoName; fw->name.name_list = NULL; FlocaleGetNameProperty(XGetWMName, dpy, FW_W(fw), &(fw->name)); } return; } void setup_wm_hints(FvwmWindow *fw) { fw->wmhints = XGetWMHints(dpy, FW_W(fw)); set_focus_model(fw); return; } void setup_title_geometry( FvwmWindow *fw, window_style *pstyle) { int width; int offset; get_title_font_size_and_offset( fw, S_TITLE_DIR(SCF(*pstyle)), S_IS_LEFT_TITLE_ROTATED_CW(SCF(*pstyle)), S_IS_RIGHT_TITLE_ROTATED_CW(SCF(*pstyle)), S_IS_TOP_TITLE_ROTATED(SCF(*pstyle)), S_IS_BOTTOM_TITLE_ROTATED(SCF(*pstyle)), &width, &offset); fw->title_thickness = width; fw->title_text_offset = offset; fw->corner_width = fw->title_thickness + fw->boundary_width; if (!HAS_TITLE(fw)) { fw->title_thickness = 0; } return; } void setup_window_font( FvwmWindow *fw, window_style *pstyle, Bool do_destroy) { /* get rid of old font */ if (do_destroy) { destroy_window_font(fw); /* destroy_window_font resets the IS_WINDOW_FONT_LOADED flag */ } /* load new font */ if (!IS_WINDOW_FONT_LOADED(fw)) { if (S_HAS_WINDOW_FONT(SCF(*pstyle)) && SGET_WINDOW_FONT(*pstyle) && (fw->title_font = FlocaleLoadFont(dpy, SGET_WINDOW_FONT(*pstyle), "fvwm"))) { SET_USING_DEFAULT_WINDOW_FONT(fw, 0); } else { /* no explicit font or failed to load, use default font * instead */ fw->title_font = Scr.DefaultFont; SET_USING_DEFAULT_WINDOW_FONT(fw, 1); } SET_WINDOW_FONT_LOADED(fw, 1); } setup_title_geometry(fw, pstyle); return; } void setup_icon_font( FvwmWindow *fw, window_style *pstyle, Bool do_destroy) { int height = 0; if (IS_ICON_SUPPRESSED(fw) || HAS_NO_ICON_TITLE(fw)) { if (IS_ICON_FONT_LOADED(fw)) { destroy_icon_font(fw); /* destroy_icon_font resets the IS_ICON_FONT_LOADED * flag */ } return; } /* get rid of old font */ if (do_destroy && IS_ICON_FONT_LOADED(fw)) { destroy_icon_font(fw); /* destroy_icon_font resets the IS_ICON_FONT_LOADED flag */ } /* load new font */ if (!IS_ICON_FONT_LOADED(fw)) { if (S_HAS_ICON_FONT(SCF(*pstyle)) && SGET_ICON_FONT(*pstyle) && (fw->icon_font = FlocaleLoadFont(dpy, SGET_ICON_FONT(*pstyle), "fvwm"))) { SET_USING_DEFAULT_ICON_FONT(fw, 0); } else { /* no explicit font or failed to load, use default font * instead */ fw->icon_font = Scr.DefaultFont; SET_USING_DEFAULT_ICON_FONT(fw, 1); } SET_ICON_FONT_LOADED(fw, 1); } /* adjust y position of existing icons */ height = (IS_ICON_FONT_LOADED(fw)) ? fw->icon_font->height : 0; if (height) { resize_icon_title_height(fw, height - fw->icon_font->height); /* this repositions the icon even if the window is not * iconified */ DrawIconWindow(fw, True, True, False, False, NULL); } return; } void setup_style_and_decor( FvwmWindow *fw, window_style *pstyle, short *buttons) { /* first copy the static styles into the window struct */ memcpy(&(FW_COMMON_FLAGS(fw)), &(SCF(*pstyle)), sizeof(common_flags_t)); fw->wShaped = None; if (FShapesSupported) { int i; unsigned int u; Bool b; int boundingShaped; SUPPRESS_UNUSED_VAR_WARNING(i); SUPPRESS_UNUSED_VAR_WARNING(u); SUPPRESS_UNUSED_VAR_WARNING(b); FShapeSelectInput(dpy, FW_W(fw), FShapeNotifyMask); if (FShapeQueryExtents( dpy, FW_W(fw), &boundingShaped, &i, &i, &u, &u, &b, &i, &i, &u, &u)) { fw->wShaped = boundingShaped; } } /* search for a UseDecor tag in the style */ if (!IS_DECOR_CHANGED(fw)) { FvwmDecor *decor = &Scr.DefaultDecor; for (; decor; decor = decor->next) { if (StrEquals(SGET_DECOR_NAME(*pstyle), decor->tag)) { fw->decor = decor; break; } } } if (fw->decor == NULL) { fw->decor = &Scr.DefaultDecor; } GetMwmHints(fw); GetOlHints(fw); fw->buttons = SIS_BUTTON_DISABLED(&pstyle->flags); SelectDecor(fw, pstyle, buttons); if (IS_TRANSIENT(fw) && !pstyle->flags.do_decorate_transient) { SET_HAS_HANDLES(fw, 0); SET_HAS_TITLE(fw, 0); } /* set boundary width to zero for shaped windows */ if (FHaveShapeExtension) { if (fw->wShaped) { set_window_border_size(fw, fw->unshaped_boundary_width); SET_HAS_NO_BORDER(fw, 1); SET_HAS_HANDLES(fw, 0); } } /****** window colors ******/ update_window_color_style(fw, pstyle); update_window_color_hi_style(fw, pstyle); /***** icons colorsets *****/ update_icon_title_cs_style(fw, pstyle); update_icon_title_cs_hi_style(fw, pstyle); update_icon_background_cs_style(fw, pstyle); /***** icons title/background parameters ****/ setup_icon_background_parameters(fw, pstyle); setup_icon_title_parameters(fw, pstyle); /****** some numeric values ******/ setup_numeric_vals(fw, pstyle); /* ConfigureNotify motion method */ if (SCR_MOTION_METHOD(&pstyle->flag_mask)) { CR_MOTION_METHOD(fw) = SCR_MOTION_METHOD(&pstyle->flags); } return; } void change_icon_boxes(FvwmWindow *fw, window_style *pstyle) { destroy_icon_boxes(fw); setup_icon_boxes(fw, pstyle); return; } void setup_frame_size_limits(FvwmWindow *fw, window_style *pstyle) { if (SHAS_MIN_WINDOW_SIZE(&pstyle->flags)) { fw->min_window_width = SGET_MIN_WINDOW_WIDTH(*pstyle); fw->min_window_height = SGET_MIN_WINDOW_HEIGHT(*pstyle); } else { fw->min_window_width = 0; fw->min_window_height = 0; } if (SHAS_MAX_WINDOW_SIZE(&pstyle->flags)) { fw->max_window_width = SGET_MAX_WINDOW_WIDTH(*pstyle); fw->max_window_height = SGET_MAX_WINDOW_HEIGHT(*pstyle); } else { fw->max_window_width = DEFAULT_MAX_MAX_WINDOW_WIDTH; fw->max_window_height = DEFAULT_MAX_MAX_WINDOW_HEIGHT; } return; } void setup_placement_penalty(FvwmWindow *fw, window_style *pstyle) { if (!SHAS_PLACEMENT_PENALTY(&pstyle->flags)) { pl_penalty_struct *p; p = SGET_PLACEMENT_PENALTY_PTR(*pstyle); *p = default_pl_penalty; } if (!SHAS_PLACEMENT_PERCENTAGE_PENALTY(&pstyle->flags)) { pl_percent_penalty_struct *p; p = SGET_PLACEMENT_PERCENTAGE_PENALTY_PTR(*pstyle); *p = default_pl_percent_penalty; } fw->pl_penalty = (*pstyle).pl_penalty; fw->pl_percent_penalty = (*pstyle).pl_percent_penalty; return; } void setup_frame_attributes( FvwmWindow *fw, window_style *pstyle) { XSetWindowAttributes xswa; /* Backing_store is controlled on the client, borders, title & buttons */ switch (pstyle->flags.use_backing_store) { case BACKINGSTORE_DEFAULT: xswa.backing_store = fw->attr_backup.backing_store; break; case BACKINGSTORE_ON: xswa.backing_store = Scr.use_backing_store; break; case BACKINGSTORE_OFF: default: xswa.backing_store = NotUseful; break; } /* parent_relative is applied to the frame and the parent */ xswa.background_pixmap = pstyle->flags.use_parent_relative ? ParentRelative : None; /* Save_under is only useful on the frame */ xswa.save_under = pstyle->flags.do_save_under ? Scr.flags.do_save_under : NotUseful; XChangeWindowAttributes(dpy, FW_W(fw), CWBackingStore, &xswa); XChangeWindowAttributes( dpy, FW_W_PARENT(fw), CWBackPixmap | CWBackingStore, &xswa); XChangeWindowAttributes( dpy, FW_W_FRAME(fw), CWBackPixmap | CWBackingStore | CWSaveUnder, &xswa); return; } void change_auxiliary_windows(FvwmWindow *fw, short buttons) { unsigned long valuemask_save = 0; XSetWindowAttributes attributes; get_default_window_attributes(fw, &valuemask_save, &attributes); change_title_window(fw, valuemask_save, &attributes); change_button_windows(fw, valuemask_save, &attributes, buttons); change_resize_handle_windows(fw); setup_frame_stacking(fw); XMapSubwindows (dpy, FW_W_FRAME(fw)); return; } void increase_icon_hint_count(FvwmWindow *fw) { if (fw->wmhints && (fw->wmhints->flags & (IconWindowHint | IconPixmapHint))) { switch (WAS_ICON_HINT_PROVIDED(fw)) { case ICON_HINT_NEVER: SET_WAS_ICON_HINT_PROVIDED(fw, ICON_HINT_ONCE); break; case ICON_HINT_ONCE: SET_WAS_ICON_HINT_PROVIDED(fw, ICON_HINT_MULTIPLE); break; case ICON_HINT_MULTIPLE: default: break; } ICON_DBG((stderr,"icon hint count++ (%d) '%s'\n", (int)WAS_ICON_HINT_PROVIDED(fw), fw->name.name)); } return; } void change_icon(FvwmWindow *fw, window_style *pstyle) { destroy_icon(fw); setup_icon(fw, pstyle); return; } void change_mini_icon(FvwmWindow *fw, window_style *pstyle) { FvwmPicture *old_mi = fw->mini_icon; destroy_mini_icon(fw); setup_mini_icon(fw, pstyle); broadcast_mini_icon(fw); if (old_mi != NULL && fw->mini_icon == 0) { /* this case is not handled in setup_mini_icon, so we must * broadcast here explicitly */ BroadcastFvwmPicture( M_MINI_ICON, FW_W(fw), FW_W_FRAME(fw), (unsigned long)fw, NULL, ""); } return; } void setup_focus_policy(FvwmWindow *fw) { focus_grab_buttons(fw); return; } Bool validate_transientfor(FvwmWindow *fw) { XWindowAttributes wa; FvwmWindow *cw; Window w; w = FW_W_TRANSIENTFOR(fw); if (w == None || w == FW_W(fw) || w == IS_EWMH_DESKTOP(w)) { FW_W_TRANSIENTFOR(fw) = Scr.Root; return False; } else if (XFindContext(dpy, w, FvwmContext, (caddr_t *)&cw) != XCNOENT) { if (cw == fw) { /* It's a transient of itself, ignore the hint */ FW_W_TRANSIENTFOR(fw) = Scr.Root; return False; } /* Check for transient loops */ while (XFindContext( dpy, FW_W_TRANSIENTFOR(cw), FvwmContext, (caddr_t *)&cw) != XCNOENT && IS_TRANSIENT(cw)) { if (FW_W_TRANSIENTFOR(cw) == FW_W(fw) || cw == fw) { /* loop detected, ignore the hint */ FW_W_TRANSIENTFOR(fw) = Scr.Root; return False; } } } else if (!XGetWindowAttributes(dpy, w, &wa) || wa.map_state != IsViewable) { /* transientfor does not exist or is not viewable or unmapped */ FW_W_TRANSIENTFOR(fw) = Scr.Root; return False; } return True; } Bool setup_transientfor(FvwmWindow *fw) { Bool rc; rc = XGetTransientForHint(dpy, FW_W(fw), &FW_W_TRANSIENTFOR(fw)); SET_TRANSIENT(fw, rc); if (rc == False) { FW_W_TRANSIENTFOR(fw) = Scr.Root; } validate_transientfor(fw); return rc; } /* * * Procedure: * AddWindow - add a new window to the fvwm list * */ FvwmWindow *AddWindow( const char **ret_initial_map_command, const exec_context_t *exc, FvwmWindow *ReuseWin, initial_window_options_t * win_opts) { /* new fvwm window structure */ register FvwmWindow *fw; FvwmWindow *tmp; /* mask for create windows */ unsigned long valuemask; /* attributes for create windows */ XSetWindowAttributes attributes; XWindowAttributes wattr; /* area for merged styles */ window_style style; /* used for faster access */ style_flags *sflags; short buttons; Bool used_sm = False; Bool do_resize_too = False; size_borders b; frame_move_resize_args mr_args; mwtsm_state_args state_args; Window w = exc->w.w; const exec_context_t *exc2; exec_context_changes_t ecc; /****** init window structure ******/ setup_window_structure(&tmp, w, ReuseWin); fw = tmp; /****** Make sure the client window still exists. We don't want to * leave an orphan frame window if it doesn't. Since we now have the * server grabbed, the window can't disappear later without having been * reparented, so we'll get a DestroyNotify for it. We won't have * gotten one for anything up to here, however. ******/ MyXGrabServer(dpy); if (XGetGeometry( dpy, w, &JunkRoot, &JunkX, &JunkY, (unsigned int*)&JunkWidth, (unsigned int*)&JunkHeight, (unsigned int*)&JunkBW, (unsigned int*)&JunkDepth) == 0) { if (Scr.bo.do_display_new_window_names) { fvwm_msg(INFO, "AddWindow", "new window disappeared"); } free(fw); MyXUngrabServer(dpy); return NULL; } /****** window name ******/ setup_window_name(fw); setup_class_and_resource(fw); /****** style setup ******/ __add_window_handle_x_resources(fw); /* get merged styles */ lookup_style(fw, &style); sflags = SGET_FLAGS_POINTER(style); if (SIS_UNMANAGED(sflags)) { if (Scr.bo.do_display_new_window_names) { fvwm_msg( INFO, "AddWindow", "new window is unmanaged:\n" " name: %s\n" " icon name: (unknown)\n" " resource: %s\n" " class: %s", fw->name.name, fw->class.res_name, fw->class.res_class); } free_window_names(fw, True, True); if (fw->style_name) { free(fw->style_name); } free(fw); MyXUngrabServer(dpy); return AW_UNMANAGED; } /****** window attributes and hints ******/ setup_window_attr(fw, &wattr); setup_wm_hints(fw); /****** basic style and decor ******/ /* If the window is in the NoTitle list, or is a transient, dont * decorate it. If its a transient, and DecorateTransients was * specified, decorate anyway. */ setup_transientfor(fw); if (win_opts->flags.is_menu) { SET_TEAR_OFF_MENU(fw, 1); } fw->decor = NULL; setup_style_and_decor(fw, &style, &buttons); /****** fonts ******/ setup_window_font(fw, &style, False); setup_icon_font(fw, &style, False); /***** visible window name ****/ setup_visible_names(fw, 1); EWMH_SetVisibleName(fw, False); if (Scr.bo.do_display_new_window_names) { fvwm_msg( INFO, "AddWindow", "new window:\n" " name: %s\n" " icon name: %s\n" " resource: %s\n" " class: %s", fw->name.name, (fw->icon_name.name == NULL) ? "(unknown)" : fw->icon_name.name, fw->class.res_name, fw->class.res_class); } /****** InitialMapCommand ******/ *ret_initial_map_command = (style.flags.has_initial_map_command_string) ? SGET_INITIAL_MAP_COMMAND_STRING(style) : NULL; /****** state setup ******/ setup_icon_boxes(fw, &style); SET_ICONIFIED(fw, 0); SET_ICON_UNMAPPED(fw, 0); SET_MAXIMIZED(fw, 0); /* * Reparenting generates an UnmapNotify event, followed by a MapNotify. * Set the map state to 0 to prevent a transition back to * WithdrawnState in HandleUnmapNotify. Map state gets set corrected * again in HandleMapNotify. */ SET_MAPPED(fw, 0); /****** window list and stack ring ******/ /* add the window to the end of the fvwm list */ fw->next = Scr.FvwmRoot.next; fw->prev = &Scr.FvwmRoot; while (fw->next != NULL) { fw->prev = fw->next; fw->next = fw->next->next; } /* fw->prev points to the last window in the list, fw->next is * NULL. Now fix the last window to point to fw */ fw->prev->next = fw; /* * RBW - 11/13/1998 - add it into the stacking order chain also. * This chain is anchored at both ends on Scr.FvwmRoot, there are * no null pointers. */ add_window_to_stack_ring_after(fw, &Scr.FvwmRoot); /****** calculate frame size ******/ fw->hints.win_gravity = NorthWestGravity; GetWindowSizeHints(fw); /****** border width ******/ XSetWindowBorderWidth(dpy, FW_W(fw), 0); /****** icon size limits ******/ setup_icon_size_limits(fw, &style); /***** placement penalities *****/ setup_placement_penalty(fw, &style); /* * MatchWinToSM changes fw->attr and the stacking order. * Thus it is important have this call *after* PlaceWindow and the * stacking order initialization. */ get_window_borders(fw, &b); memset(&state_args, 0, sizeof(state_args)); used_sm = MatchWinToSM(fw, &state_args, win_opts); if (used_sm) { /* read the requested absolute geometry */ gravity_translate_to_northwest_geometry_no_bw( fw->hints.win_gravity, fw, &fw->g.normal, &fw->g.normal); gravity_resize( fw->hints.win_gravity, &fw->g.normal, b.total_size.width, b.total_size.height); fw->g.frame = fw->g.normal; fw->g.frame.x -= Scr.Vx; fw->g.frame.y -= Scr.Vy; /****** calculate frame size ******/ setup_frame_size_limits(fw, &style); constrain_size( fw, NULL, &fw->g.frame.width, &fw->g.frame.height, 0, 0, 0); /****** maximize ******/ if (state_args.do_max) { SET_MAXIMIZED(fw, 1); constrain_size( fw, NULL, &fw->g.max.width, &fw->g.max.height, 0, 0, CS_UPDATE_MAX_DEFECT); get_relative_geometry(&fw->g.frame, &fw->g.max); } else { get_relative_geometry(&fw->g.frame, &fw->g.normal); } } else { rectangle attr_g; if (IS_SHADED(fw)) { state_args.do_shade = 1; state_args.used_title_dir_for_shading = USED_TITLE_DIR_FOR_SHADING(fw); state_args.shade_dir = SHADED_DIR(fw); SET_SHADED(fw, 0); } /* Tentative size estimate */ fw->g.frame.width = wattr.width + b.total_size.width; fw->g.frame.height = wattr.height + b.total_size.height; /****** calculate frame size ******/ setup_frame_size_limits(fw, &style); /****** layer ******/ setup_layer(fw, &style); /****** window placement ******/ attr_g.x = wattr.x; attr_g.y = wattr.y; attr_g.width = wattr.width; attr_g.height = wattr.height; do_resize_too = setup_window_placement( fw, &style, &attr_g, win_opts, PLACE_INITIAL); wattr.x = attr_g.x; wattr.y = attr_g.y; /* set up geometry */ fw->g.frame.x = wattr.x; fw->g.frame.y = wattr.y; fw->g.frame.width = wattr.width + b.total_size.width; fw->g.frame.height = wattr.height + b.total_size.height; gravity_constrain_size( fw->hints.win_gravity, fw, &fw->g.frame, 0); update_absolute_geometry(fw); } /****** auxiliary window setup ******/ setup_auxiliary_windows(fw, True, buttons); /****** 'backing store' and 'save under' window setup ******/ setup_frame_attributes(fw, &style); /****** reparent the window ******/ XReparentWindow(dpy, FW_W(fw), FW_W_PARENT(fw), 0, 0); /****** select events ******/ valuemask = CWEventMask | CWDontPropagate; if (IS_TEAR_OFF_MENU(fw)) { attributes.event_mask = XEVMASK_TEAR_OFF_MENUW; } else { attributes.event_mask = XEVMASK_CLIENTW; } attributes.do_not_propagate_mask = ButtonPressMask | ButtonReleaseMask; XChangeWindowAttributes(dpy, FW_W(fw), valuemask, &attributes); /****** make sure the window is not destroyed when fvwm dies ******/ if (!IS_TEAR_OFF_MENU(fw)) { /* menus were created by fvwm itself, don't add them to the * save set */ XAddToSaveSet(dpy, FW_W(fw)); } /****** now we can sefely ungrab the server ******/ MyXUngrabServer(dpy); /* need to set up the mini icon before drawing */ if (FMiniIconsSupported) { setup_mini_icon(fw, &style); } /****** arrange the frame ******/ if (is_resizing_event_pending(fw) == True) { SET_FORCE_NEXT_CR(fw, 1); SET_FORCE_NEXT_PN(fw, 1); mr_args = frame_create_move_resize_args( fw, FRAME_MR_FORCE_SETUP_NO_W | FRAME_MR_DONT_DRAW, NULL, &fw->g.frame, 0, DIR_NONE); } else { mr_args = frame_create_move_resize_args( fw, FRAME_MR_FORCE_SETUP | FRAME_MR_DONT_DRAW, NULL, &fw->g.frame, 0, DIR_NONE); } frame_move_resize(fw, mr_args); frame_free_move_resize_args(fw, mr_args); /* draw later */ SET_WAS_NEVER_DRAWN(fw, 1); /****** grab keys and buttons ******/ setup_key_and_button_grabs(fw); /****** inform modules of new window ******/ BroadcastConfig(M_ADD_WINDOW,fw); BroadcastWindowIconNames(fw, True, False); /****** place the window in the stack ring ******/ if (!position_new_window_in_stack_ring(fw, SDO_START_LOWERED(sflags))) { XWindowChanges xwc; xwc.sibling = FW_W_FRAME(get_next_window_in_stack_ring(fw)); xwc.stack_mode = Above; XConfigureWindow( dpy, FW_W_FRAME(fw), CWSibling|CWStackMode, &xwc); } /* these are sent and broadcast before res_{class,name} for the benefit * of FvwmIconBox which can't handle M_ICON_FILE after M_RES_NAME */ /****** icon and mini icon ******/ /* migo (20-Jan-2000): the logic is to unset this flag on NULL values */ SET_WAS_ICON_NAME_PROVIDED(fw, 1); setup_icon(fw, &style); if (FMiniIconsSupported) { broadcast_mini_icon(fw); } BroadcastName(M_RES_CLASS,FW_W(fw),FW_W_FRAME(fw), (unsigned long)fw,fw->class.res_class); BroadcastName(M_RES_NAME,FW_W(fw),FW_W_FRAME(fw), (unsigned long)fw,fw->class.res_name); /****** stick window ******/ if (!(fw->hints.flags & USPosition) || used_sm) { int stick_page; int stick_desk; stick_page = is_window_sticky_across_pages(fw); stick_desk = is_window_sticky_across_desks(fw); if ((stick_page && !IsRectangleOnThisPage(&fw->g.frame, Scr.CurrentDesk)) || (stick_desk && fw->Desk != Scr.CurrentDesk)) { /* If it's sticky and the user didn't ask for an * explicit position, force it on screen now. Don't do * that with USPosition because we have to assume the * user knows what (s)he is doing. This is necessary * e.g. if we want a sticky 'panel' in FvwmButtons but * don't want to see when it's mapped in the void. */ ecc.w.fw = fw; ecc.w.w = FW_W_FRAME(fw); ecc.w.wcontext = C_FRAME; exc2 = exc_clone_context( exc, &ecc, ECC_FW | ECC_W | ECC_WCONTEXT); SET_STICKY_ACROSS_PAGES(fw, 0); SET_STICKY_ACROSS_DESKS(fw, 0); handle_stick( NULL, exc2, "", stick_page, stick_desk, 1, 0); exc_destroy_context(exc2); } } /****** resize window ******/ if (do_resize_too) { XEvent e; memset(&e, 0, sizeof(e)); FWarpPointer( dpy, Scr.Root, Scr.Root, 0, 0, Scr.MyDisplayWidth, Scr.MyDisplayHeight, fw->g.frame.x + (fw->g.frame.width>>1), fw->g.frame.y + (fw->g.frame.height>>1)); e.xany.type = ButtonPress; e.xbutton.button = 1; e.xbutton.state = Button1Mask; e.xbutton.x_root = fw->g.frame.x + (fw->g.frame.width>>1); e.xbutton.y_root = fw->g.frame.y + (fw->g.frame.height>>1); e.xbutton.x = (fw->g.frame.width>>1); e.xbutton.y = (fw->g.frame.height>>1); e.xbutton.subwindow = None; e.xany.window = FW_W(fw); fev_fake_event(&e); ecc.x.etrigger = &e; ecc.w.fw = fw; ecc.w.wcontext = C_WINDOW; exc2 = exc_clone_context( exc, &ecc, ECC_ETRIGGER | ECC_FW | ECC_WCONTEXT); CMD_Resize(NULL, exc2, ""); exc_destroy_context(exc2); } /****** window colormap ******/ ReInstallActiveColormap(); /****** ewmh setup *******/ EWMH_WindowInit(fw); /****** windowshade ******/ if (state_args.do_shade || SDO_START_SHADED(sflags)) { rectangle big_g; rectangle new_g; frame_move_resize_args mr_args; if (state_args.used_title_dir_for_shading) { state_args.shade_dir = GET_TITLE_DIR(fw); } /* If we've set a style for StartShaded, ensure we override * the state for it here. -- TA. */ if (SDO_START_SHADED(sflags) && !state_args.do_shade) { state_args.shade_dir = SGET_STARTS_SHADED_DIR(style); } big_g = (IS_MAXIMIZED(fw)) ? fw->g.max : fw->g.frame; new_g = big_g; get_shaded_geometry_with_dir( fw, &new_g, &new_g, state_args.shade_dir); mr_args = frame_create_move_resize_args( fw, FRAME_MR_SHRINK | FRAME_MR_DONT_DRAW, &big_g, &new_g, 0, state_args.shade_dir); frame_move_resize(fw, mr_args); SET_SHADED(fw, 1); SET_SHADED_DIR(fw, state_args.shade_dir); frame_free_move_resize_args(fw, mr_args); } if (!IS_SHADED(fw) && !IS_ICONIFIED(fw)) { /* TK always wants some special treatment: If the window is * simply mapped, the tk menus come up at funny Y coordinates. * Tell it it's geometry *again* to work around this problem. */ SendConfigureNotify( fw, fw->g.frame.x, fw->g.frame.y, fw->g.frame.width, fw->g.frame.height, 0, False); } if ( HAS_EWMH_INIT_MAXVERT_STATE(fw) == EWMH_STATE_HAS_HINT || HAS_EWMH_INIT_MAXHORIZ_STATE(fw) == EWMH_STATE_HAS_HINT) { int h; int v; char cmd[256]; if ( is_function_allowed( F_MAXIMIZE, NULL, fw, RQORIG_PROGRAM_US, False)) { h = (HAS_EWMH_INIT_MAXHORIZ_STATE(fw) == EWMH_STATE_HAS_HINT) ? 100 : 0; v = (HAS_EWMH_INIT_MAXVERT_STATE(fw) == EWMH_STATE_HAS_HINT) ? 100 : 0; sprintf(cmd,"Maximize on %i %i", h, v); execute_function_override_window( NULL, NULL, cmd, 0, fw); } } if (HAS_EWMH_INIT_FULLSCREEN_STATE(fw) == EWMH_STATE_HAS_HINT) { EWMH_fullscreen(fw); } if (!XGetGeometry( dpy, FW_W(fw), &JunkRoot, &JunkX, &JunkY, (unsigned int*)&JunkWidth, (unsigned int*)&JunkHeight, (unsigned int*)&JunkBW, (unsigned int*)&JunkDepth)) { /* The window has disappeared somehow. For some reason we do * not always get a DestroyNotify on the window, so make sure * it is destroyed. */ destroy_window(fw); fw = NULL; } return fw; } /* * * Procedure: * FetchWMProtocols - finds out which protocols the window supports * * Inputs: * tmp - the fvwm window structure to use * */ void FetchWmProtocols(FvwmWindow *tmp) { Atom *protocols = NULL, *ap; unsigned long *l_protocols; int i, n; Atom atype; int aformat; unsigned long bytes_remain,nitems; if (tmp == NULL) { return; } /* First, try the Xlib function to read the protocols. * This is what Twm uses. */ if (XGetWMProtocols (dpy, FW_W(tmp), &protocols, &n)) { for (i = 0, ap = protocols; i < n; i++, ap++) { if (*ap == (Atom)_XA_WM_TAKE_FOCUS) { SET_WM_TAKES_FOCUS(tmp, 1); set_focus_model(tmp); } if (*ap == (Atom)_XA_WM_DELETE_WINDOW) { SET_WM_DELETES_WINDOW(tmp, 1); } } if (protocols) { XFree((char *)protocols); } } else { /* Next, read it the hard way. mosaic from Coreldraw needs to * be read in this way. */ if ((XGetWindowProperty( dpy, FW_W(tmp), _XA_WM_PROTOCOLS, 0L, 10L, False, _XA_WM_PROTOCOLS, &atype, &aformat, &nitems, &bytes_remain, (unsigned char **)&l_protocols)) == Success) { for (i = 0; i < nitems; i++) { ap = &(l_protocols[i]); if (*ap == (Atom)_XA_WM_TAKE_FOCUS) { SET_WM_TAKES_FOCUS(tmp, 1); set_focus_model(tmp); } if (*ap == (Atom)_XA_WM_DELETE_WINDOW) { SET_WM_DELETES_WINDOW(tmp, 1); } } if (protocols) { XFree((char *)protocols); } } } return; } void GetWindowSizeHintsWithCheck( FvwmWindow *fw, int do_reject_invalid_size_constraints_on_existing_window) { long supplied = 0; char *broken_cause = 0; XSizeHints orig_hints; XSizeHints new_hints; Status rc; new_hints = fw->hints; rc = FGetWMNormalHints(dpy, FW_W(fw), &orig_hints, &supplied); if (rc == 0) { new_hints.flags = 0; memset(&orig_hints, 0, sizeof(orig_hints)); } else { new_hints = orig_hints; if (HAS_OVERRIDE_SIZE_HINTS(fw)) { /* ignore the WMNormal hints */ new_hints.flags &= ~(PMinSize | PMaxSize | PResizeInc); new_hints.min_width = 0; new_hints.min_height = 0; new_hints.max_width = 0; new_hints.max_height = 0; new_hints.width_inc = 1; new_hints.height_inc = 1; } } /* Beat up our copy of the hints, so that all important field are * filled in! */ if (new_hints.flags & PResizeInc) { SET_SIZE_INC_SET(fw, 1); if (new_hints.width_inc <= 0) { if (new_hints.width_inc < 0 || (new_hints.width_inc == 0 && (new_hints.flags & PMinSize) && (new_hints.flags & PMaxSize) && new_hints.min_width != new_hints.max_width)) { broken_cause = "width_inc"; } new_hints.width_inc = 1; SET_SIZE_INC_SET(fw, 0); } if (new_hints.height_inc <= 0) { if (new_hints.height_inc < 0 || (new_hints.height_inc == 0 && (new_hints.flags & PMinSize) && (new_hints.flags & PMaxSize) && new_hints.min_height != new_hints.max_height)) { if (!broken_cause) { broken_cause = "height_inc"; } } new_hints.height_inc = 1; SET_SIZE_INC_SET(fw, 0); } } else { SET_SIZE_INC_SET(fw, 0); new_hints.width_inc = 1; new_hints.height_inc = 1; } if (new_hints.flags & PMinSize) { if (new_hints.min_width < 0 && !broken_cause) { broken_cause = "min_width"; } if (new_hints.min_height < 0 && !broken_cause) { broken_cause = "min_height"; } } else { if (new_hints.flags & PBaseSize) { new_hints.min_width = new_hints.base_width; new_hints.min_height = new_hints.base_height; } else { new_hints.min_width = 1; new_hints.min_height = 1; } } if (new_hints.min_width <= 0) { new_hints.min_width = 1; } if (new_hints.min_height <= 0) { new_hints.min_height = 1; } if (new_hints.flags & PMaxSize) { if (new_hints.max_width < new_hints.min_width) { new_hints.max_width = DEFAULT_MAX_MAX_WINDOW_WIDTH; if (!broken_cause) { broken_cause = "max_width"; } } if (new_hints.max_height < new_hints.min_height) { new_hints.max_height = DEFAULT_MAX_MAX_WINDOW_HEIGHT; if (!broken_cause) { broken_cause = "max_height"; } } } else { new_hints.max_width = DEFAULT_MAX_MAX_WINDOW_WIDTH; new_hints.max_height = DEFAULT_MAX_MAX_WINDOW_HEIGHT; } /* * ICCCM says that PMinSize is the default if no PBaseSize is given, * and vice-versa. */ if (new_hints.flags & PBaseSize) { if (new_hints.base_width < 0) { new_hints.base_width = 0; if (!broken_cause) { broken_cause = "base_width"; } } if (new_hints.base_height < 0) { new_hints.base_height = 0; if (!broken_cause) { broken_cause = "base_height"; } } if ((new_hints.base_width > new_hints.min_width) || (new_hints.base_height > new_hints.min_height)) { /* In this case, doing the aspect ratio calculation for window_size - base_size as prescribed by the ICCCM is going to fail. Resetting the flag disables the use of base_size in aspect ratio calculation while it is still used for grid sizing. */ new_hints.flags &= ~PBaseSize; #if 0 /* Keep silent about this, since the Xlib manual * actually recommends making min <= base <= max ! */ broken_cause = 0; #endif } } else { if (new_hints.flags & PMinSize) { new_hints.base_width = new_hints.min_width; new_hints.base_height = new_hints.min_height; } else { new_hints.base_width = 0; new_hints.base_height = 0; } } if (!(new_hints.flags & PWinGravity)) { new_hints.win_gravity = NorthWestGravity; } if ((new_hints.flags & PMaxSize) && ((new_hints.flags & PMinSize) || (new_hints.flags & PBaseSize))) { if (new_hints.max_width < new_hints.base_width) { new_hints.max_width = DEFAULT_MAX_MAX_WINDOW_WIDTH; if (!broken_cause) { broken_cause = "max_width"; } } if (new_hints.max_height < new_hints.base_height) { new_hints.max_height = DEFAULT_MAX_MAX_WINDOW_HEIGHT; if (!broken_cause) { broken_cause = "max_height"; } } } if (new_hints.flags & PAspect) { /* ** check to make sure min/max aspect ratios look valid */ #define maxAspectX new_hints.max_aspect.x #define maxAspectY new_hints.max_aspect.y #define minAspectX new_hints.min_aspect.x #define minAspectY new_hints.min_aspect.y /* ** The math looks like this: ** ** minAspectX maxAspectX ** ---------- <= ---------- ** minAspectY maxAspectY ** ** If that is multiplied out, this must be satisfied: ** ** minAspectX * maxAspectY <= maxAspectX * minAspectY ** ** So, what to do if this isn't met? Ignoring it entirely ** seems safest. ** */ /* We also ignore people who put negative entries into * their aspect ratios. They deserve it. * * We cast to double here, since the values may be large. */ if ((maxAspectX < 0) || (maxAspectY < 0) || (minAspectX < 0) || (minAspectY < 0) || (((double)minAspectX * (double)maxAspectY) > ((double)maxAspectX * (double)minAspectY))) { if (!broken_cause) { broken_cause = "aspect ratio"; } new_hints.flags &= ~PAspect; fvwm_msg( WARN, "GetWindowSizeHints", "The applicaton window (window id %#lx)\n" " \"%s\" has broken aspect ratio: " "%d/%d - %d/%d\n" " fvwm is ignoring this aspect ratio. ", FW_W(fw), fw->name.name, minAspectX, minAspectY, maxAspectX, maxAspectY); fvwm_msg_report_app(); } else { /* protect against overflow */ if ((maxAspectX > 65536) || (maxAspectY > 65536)) { double ratio = (double) maxAspectX / (double) maxAspectY; if (ratio > 1.0) { maxAspectX = 65536; maxAspectY = 65536 / ratio; } else { maxAspectX = 65536 * ratio; maxAspectY = 65536; } } if ((minAspectX > 65536) || (minAspectY > 65536)) { double ratio = (double) minAspectX / (double) minAspectY; if (ratio > 1.0) { minAspectX = 65536; minAspectY = 65536 / ratio; } else { minAspectX = 65536 * ratio; minAspectY = 65536; } } } #undef maxAspectX #undef maxAspectY #undef minAspectX #undef minAspectY } if (do_reject_invalid_size_constraints_on_existing_window) { int is_invalid; rectangle g; gravity_get_naked_geometry( fw->hints.win_gravity, fw, &g, &fw->g.normal); is_invalid = is_geometry_invalid_with_hints(&g, &new_hints); if (!is_invalid && IS_MAXIMIZED(fw)) { gravity_get_naked_geometry( fw->hints.win_gravity, fw, &g, &fw->g.max); is_invalid = is_geometry_invalid_with_hints( &g, &new_hints); } if (is_invalid) { fvwm_msg( WARN, "GetWindowSizeHints", "reason: %d:" " The hints have been ignored because the" " window's current size would have become" " invalid. The new hints will become active" " when the window generates the next" " ConfigureRequest.\n", is_invalid); broken_cause = "inconsistent with current size"; } } else { fw->hints = new_hints; fw->orig_hints.width_inc = orig_hints.width_inc; fw->orig_hints.height_inc = orig_hints.height_inc; } if (broken_cause != 0) { fvwm_msg( WARN, "GetWindowSizeHints", "The application window (id %#lx)\n" " \"%s\" has broken size hints (%s).\n" " fvwm is ignoring those hints. " " hint override = %d, flags = %lx\n" " min_width = %d, min_height = %d, " "max_width = %d, max_height = %d\n" " width_inc = %d, height_inc = %d\n" " min_aspect = %d/%d, max_aspect = %d/%d\n" " base_width = %d, base_height = %d\n" " win_gravity = %d\n", FW_W(fw), fw->name.name, broken_cause, HAS_OVERRIDE_SIZE_HINTS(fw), orig_hints.flags, orig_hints.min_width, orig_hints.min_height, orig_hints.max_width, orig_hints.max_height, orig_hints.width_inc, orig_hints.height_inc, orig_hints.min_aspect.x, orig_hints.min_aspect.y, orig_hints.max_aspect.x, orig_hints.max_aspect.y, orig_hints.base_width, orig_hints.base_height, orig_hints.win_gravity); fvwm_msg_report_app(); } /* final safety net */ if (fw->orig_hints.width_inc <= 0) { fw->orig_hints.width_inc = 1; } if (fw->orig_hints.height_inc <= 0) { fw->orig_hints.height_inc = 1; } return; } void GetWindowSizeHints(FvwmWindow *fw) { GetWindowSizeHintsWithCheck(fw, 0); } /* * * Releases dynamically allocated space used to store window/icon names * */ void free_window_names(FvwmWindow *fw, Bool nukename, Bool nukeicon) { if (!fw) { return; } if (nukename) { if (fw->visible_name && fw->visible_name != fw->name.name && fw->visible_name != NoName) { free(fw->visible_name); } fw->visible_name = NoName; if (fw->name.name) { if (fw->icon_name.name == fw->name.name) { fw->icon_name.name = NoName; } if (fw->visible_icon_name == fw->name.name) { fw->visible_icon_name = fw->icon_name.name; } if (fw->name.name != NoName) { FlocaleFreeNameProperty(&(fw->name)); fw->visible_name = NULL; } } } if (nukeicon) { if (fw->visible_icon_name && fw->visible_icon_name != fw->name.name && fw->visible_icon_name != fw->icon_name.name && fw->visible_icon_name != NoName) { free(fw->visible_icon_name); } fw->visible_icon_name = NoName; if (fw->icon_name.name) { if ((fw->icon_name.name != fw->name.name) && fw->icon_name.name != NoName) { FlocaleFreeNameProperty(&(fw->icon_name)); fw->visible_icon_name = NULL; } } } return; } /* * * Handles destruction of a window * */ void destroy_window(FvwmWindow *fw) { /* Warning, this is also called by HandleUnmapNotify; if it ever needs * to look at the event, HandleUnmapNotify will have to mash the * UnmapNotify into a DestroyNotify. */ if (!fw) { return; } /* remove window style */ if (!IS_SCHEDULED_FOR_DESTROY(fw) && !DO_REUSE_DESTROYED(fw)) { style_id_t s_id; memset(&s_id, 0, sizeof(style_id_t)); SID_SET_WINDOW_ID(s_id, (XID)FW_W(fw)); SID_SET_HAS_WINDOW_ID(s_id, True); style_destroy_style(s_id); } /****** remove from window list ******/ /* if the window is sheduled fro destroy the window has been already * removed from list */ if (!IS_SCHEDULED_FOR_DESTROY(fw)) { /* first, remove the window from the list of all windows! */ if (fw->prev != NULL) { fw->prev->next = fw->next; } if (fw->next != NULL) { fw->next->prev = fw->prev; } fw->next = NULL; fw->prev = NULL; /****** also remove it from the stack ring ******/ /* * RBW - 11/13/1998 - new: have to unhook the stacking order chain also. There's always a prev and next, since this is a ring anchored on Scr.FvwmRoot */ remove_window_from_stack_ring(fw); } /****** check if we have to delay window destruction ******/ if ((Scr.flags.is_executing_complex_function || Scr.flags.is_executing_menu_function) && !DO_REUSE_DESTROYED(fw)) { if (IS_SCHEDULED_FOR_DESTROY(fw)) { return; } /* mark window for destruction */ SET_SCHEDULED_FOR_DESTROY(fw, 1); Scr.flags.is_window_scheduled_for_destroy = 1; /* this is necessary in case the application destroys the * client window and a new window is created with the same * window id */ delete_client_context(fw); XFlush(dpy); /* unmap the the window to fake that it was already removed */ if (IS_ICONIFIED(fw)) { if (FW_W_ICON_TITLE(fw)) { XUnmapWindow(dpy, FW_W_ICON_TITLE(fw)); } if (FW_W_ICON_PIXMAP(fw) != None) { XUnmapWindow(dpy, FW_W_ICON_PIXMAP(fw)); } } else { XUnmapWindow(dpy, FW_W_FRAME(fw)); } adjust_fvwm_internal_windows(fw); BroadcastPacket( M_DESTROY_WINDOW, 3, (long)FW_W(fw), (long)FW_W_FRAME(fw), (unsigned long)fw); EWMH_DestroyWindow(fw); focus_grab_buttons_on_layer(fw->layer); Scr.FWScheduledForDestroy = flist_append_obj( Scr.FWScheduledForDestroy, fw); return; } /****** unmap the frame ******/ XUnmapWindow(dpy, FW_W_FRAME(fw)); XFlush(dpy); /* already done above? */ if (!IS_SCHEDULED_FOR_DESTROY(fw)) { SET_SCHEDULED_FOR_DESTROY(fw, 1); adjust_fvwm_internal_windows(fw); BroadcastPacket( M_DESTROY_WINDOW, 3, (long)FW_W(fw), (long)FW_W_FRAME(fw), (unsigned long)fw); EWMH_DestroyWindow(fw); } focus_grab_buttons_on_layer(fw->layer); /****** destroy auxiliary windows ******/ destroy_auxiliary_windows(fw, True); /****** destroy icon ******/ destroy_icon_boxes(fw); destroy_icon(fw); /****** destroy mini icon ******/ #ifdef MINI_ICON destroy_mini_icon(fw); #endif /****** free strings ******/ free_window_names(fw, True, True); if (fw->style_name) { free(fw->style_name); fw->style_name = NULL; } if (fw->class.res_name && fw->class.res_name != NoResource) { XFree ((char *)fw->class.res_name); fw->class.res_name = NoResource; } if (fw->class.res_class && fw->class.res_class != NoClass) { XFree ((char *)fw->class.res_class); fw->class.res_class = NoClass; } if (fw->mwm_hints) { XFree((char *)fw->mwm_hints); fw->mwm_hints = NULL; } /****** free fonts ******/ destroy_window_font(fw); destroy_icon_font(fw); /****** free wmhints ******/ if (fw->wmhints) { XFree ((char *)fw->wmhints); fw->wmhints = NULL; } /****** free colormap windows ******/ if (fw->cmap_windows != (Window *)NULL) { XFree((void *)fw->cmap_windows); fw->cmap_windows = NULL; } /****** throw away the structure ******/ /* Recapture reuses this struct, so don't free it. */ if (!DO_REUSE_DESTROYED(fw)) { free((char *)fw); } /****** cleanup ******/ XFlush(dpy); return; } /* * * Procedure: * RestoreWithdrawnLocation * * Puts windows back where they were before fvwm took over * */ void RestoreWithdrawnLocation( FvwmWindow *fw, Bool is_restart_or_recapture, Window parent) { int w2,h2; unsigned int mask; XWindowChanges xwc; rectangle naked_g; rectangle unshaded_g; XSetWindowAttributes xswa; if (!fw) { return; } /* always get the latest size hints in case the application changed * the gravity and we do not yet know about it */ XSync(dpy, 0); GetWindowSizeHints(fw); SET_HAS_NEW_WM_NORMAL_HINTS(fw, 0); get_unshaded_geometry(fw, &unshaded_g); gravity_get_naked_geometry( fw->hints.win_gravity, fw, &naked_g, &unshaded_g); gravity_translate_to_northwest_geometry( fw->hints.win_gravity, fw, &naked_g, &naked_g); xwc.x = naked_g.x; xwc.y = naked_g.y; xwc.width = naked_g.width; xwc.height = naked_g.height; xwc.border_width = fw->attr_backup.border_width; mask = (CWX | CWY | CWWidth | CWHeight | CWBorderWidth); /* We can not assume that the window is currently on the screen. * Although this is normally the case, it is not always true. The * most common example is when the user does something in an * application which will, after some amount of computational delay, * cause the window to be unmapped, but then switches screens before * this happens. The XTranslateCoordinates call above will set the * window coordinates to either be larger than the screen, or negative. * This will result in the window being placed in odd, or even * unviewable locations when the window is remapped. The following * code forces the "relative" location to be within the bounds of the * display. * * gpw -- 11/11/93 * * Unfortunately, this does horrendous things during re-starts, * hence the "if (restart)" clause (RN) * * Also, fixed so that it only does this stuff if a window is more than * half off the screen. (RN) */ if (!is_restart_or_recapture) { /* Don't mess with it if its partially on the screen now */ if (unshaded_g.x < 0 || unshaded_g.y < 0 || unshaded_g.x >= Scr.MyDisplayWidth || unshaded_g.y >= Scr.MyDisplayHeight) { w2 = (unshaded_g.width >> 1); h2 = (unshaded_g.height >> 1); if ( xwc.x < -w2 || xwc.x > Scr.MyDisplayWidth - w2) { xwc.x = xwc.x % Scr.MyDisplayWidth; if (xwc.x < -w2) { xwc.x += Scr.MyDisplayWidth; } } if (xwc.y < -h2 || xwc.y > Scr.MyDisplayHeight - h2) { xwc.y = xwc.y % Scr.MyDisplayHeight; if (xwc.y < -h2) { xwc.y += Scr.MyDisplayHeight; } } } } /* restore initial backing store setting on window */ xswa.backing_store = fw->attr_backup.backing_store; XChangeWindowAttributes(dpy, FW_W(fw), CWBackingStore, &xswa); /* reparent to root window */ XReparentWindow( dpy, FW_W(fw), (parent == None) ? Scr.Root : parent, xwc.x, xwc.y); if (IS_ICONIFIED(fw) && !IS_ICON_SUPPRESSED(fw)) { if (FW_W_ICON_TITLE(fw)) { XUnmapWindow(dpy, FW_W_ICON_TITLE(fw)); } if (FW_W_ICON_PIXMAP(fw)) { XUnmapWindow(dpy, FW_W_ICON_PIXMAP(fw)); } } XConfigureWindow(dpy, FW_W(fw), mask, &xwc); if (!is_restart_or_recapture) { /* must be initial capture */ XFlush(dpy); } return; } /* * * Procedure: * Reborder - Removes fvwm border windows * */ void Reborder(void) { FvwmWindow *fw; /* put a border back around all windows */ MyXGrabServer (dpy); /* force reinstall */ InstallWindowColormaps (&Scr.FvwmRoot); /* RBW - 05/15/1998 * Grab the last window and work backwards: preserve stacking order on * restart. */ for (fw = get_prev_window_in_stack_ring(&Scr.FvwmRoot); fw != &Scr.FvwmRoot; fw = get_prev_window_in_stack_ring(fw)) { if (!IS_ICONIFIED(fw) && Scr.CurrentDesk != fw->Desk) { XMapWindow(dpy, FW_W(fw)); SetMapStateProp(fw, NormalState); } RestoreWithdrawnLocation (fw, True, Scr.Root); XUnmapWindow(dpy,FW_W_FRAME(fw)); XDestroyWindow(dpy,FW_W_FRAME(fw)); } MyXUngrabServer (dpy); FOCUS_RESET(); XFlush(dpy); return; } void CaptureAllWindows(const exec_context_t *exc, Bool is_recapture) { int i,j; unsigned int nchildren; Window root, parent, *children; initial_window_options_t win_opts; FvwmWindow *fw; MyXGrabServer(dpy); if (!XQueryTree(dpy, Scr.Root, &root, &parent, &children, &nchildren)) { MyXUngrabServer(dpy); return; } memset(&win_opts, 0, sizeof(win_opts)); win_opts.flags.do_override_ppos = 1; win_opts.flags.is_recapture = 1; if (!(Scr.flags.are_windows_captured)) /* initial capture? */ { evh_args_t ea; exec_context_changes_t ecc; XEvent e; /* weed out icon windows */ for (i = 0; i < nchildren; i++) { if (children[i]) { XWMHints *wmhintsp = XGetWMHints( dpy, children[i]); if (wmhintsp && wmhintsp->flags & IconWindowHint) { for (j = 0; j < nchildren; j++) { if (children[j] == wmhintsp->icon_window) { children[j] = None; break; } } } if (wmhintsp) { XFree ((char *) wmhintsp); } } } /* map all of the non-override, non-icon windows */ e.type = MapRequest; ecc.x.etrigger = &e; for (i = 0; i < nchildren; i++) { if (children[i] && MappedNotOverride(children[i], &win_opts)) { XUnmapWindow(dpy, children[i]); e.xmaprequest.window = children[i]; e.xmaprequest.parent = Scr.Root; ecc.w.fw = NULL; ecc.w.w = children[i]; ecc.w.wcontext = C_ROOT; ea.exc = exc_clone_context( exc, &ecc, ECC_ETRIGGER | ECC_FW | ECC_W | ECC_WCONTEXT); HandleMapRequestKeepRaised( &ea, None, NULL, &win_opts); exc_destroy_context(ea.exc); } } Scr.flags.are_windows_captured = 1; } else /* must be recapture */ { Window keep_on_top_win; Window parent_win; Window focus_w; FvwmWindow *t; t = get_focus_window(); focus_w = (t) ? FW_W(t) : None; hide_screen(True, &keep_on_top_win, &parent_win); /* reborder all windows */ for (i=0;inext) { ; } if (t) { SetFocusWindow(t, True, FOCUS_SET_FORCE); } } } if (nchildren > 0) { XFree((char *)children); } MyXUngrabServer(dpy); return; } /* ---------------------------- builtin commands --------------------------- */ void CMD_Recapture(F_CMD_ARGS) { do_recapture(F_PASS_ARGS, False); return; } void CMD_RecaptureWindow(F_CMD_ARGS) { do_recapture(F_PASS_ARGS, True); return; } fvwm-2.7.0/fvwm/borders.c0000644000175000017500000035475114147024700012221 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* IMPORTANT NOTE: * * The functions in this module *must not* assume that the geometries in the * FvwmWindow structure reflect the desired geometry of the window or its * parts. While the window is resized or shaded, they may hold the old * geometry instead of the new one (but you can not rely on this). Therefore, * these geometries must not be accessed directly or indirectly (by the * functions from geometry,c). Use the geometries that are passed in via * structure pointers, e.d. "td". */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include "libs/fvwmlib.h" #include "libs/Parse.h" #include "libs/Graphics.h" #include "libs/Picture.h" #include "libs/PictureGraphics.h" #include "libs/FRenderInit.h" #include "libs/charmap.h" #include "libs/wcontext.h" #include "fvwm.h" #include "execcontext.h" #include "externs.h" #include "misc.h" #include "screen.h" #include "geometry.h" #include "borders.h" #include "builtins.h" #include "icons.h" #include "frame.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ #define SWAP_ARGS(f,a1,a2) (f)?(a2):(a1),(f)?(a1):(a2) /* ---------------------------- imports ------------------------------------ */ extern Window PressedW; /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ typedef struct { struct { unsigned use_pixmap : 1; } flags; Pixel pixel; struct { Pixmap p; Pixmap shape; Pixmap alpha; int depth; FvwmRenderAttributes fra; rectangle g; int stretch_w; int stretch_h; struct { unsigned is_tiled : 1; unsigned is_stretched : 1; } flags; } pixmap; } pixmap_background_type; typedef struct { Pixmap p; FvwmPicture *mp_created_pic; int cs; FvwmPicture *mp_pic; int mp_part; Bool created; } bar_pixmap; typedef struct { int count; bar_pixmap *bps; } bar_bs_pixmaps; /* for UseTitleStyle & Colorset */ typedef struct { Pixmap frame_pixmap; bar_bs_pixmaps bar_pixmaps[BS_MaxButtonState]; } dynamic_common_decorations; typedef struct { int relief_width; GC relief_gc; GC shadow_gc; Pixel fore_color; Pixel back_color; int cs; int border_cs; /* for UseBorderStyle */ int bg_border_cs; /* for UseBorderStyle */ Pixmap back_pixmap; XSetWindowAttributes attributes; unsigned long valuemask; Pixmap texture_pixmap; int texture_pixmap_width; int texture_pixmap_height; XSetWindowAttributes notex_attributes; unsigned long notex_valuemask; dynamic_common_decorations dynamic_cd; } common_decorations_type; typedef struct { GC relief; GC shadow; GC transparent; } draw_border_gcs; typedef struct { int offset_tl; int offset_br; int thickness; int length; unsigned has_x_marks : 1; unsigned has_y_marks : 1; } border_marks_descr; typedef struct { int w_dout; int w_hiout; int w_trout; int w_c; int w_trin; int w_shin; int w_din; int sum; int trim; unsigned is_flat : 1; } border_relief_size_descr; typedef struct { rectangle sidebar_g; border_relief_size_descr relief; border_marks_descr marks; draw_border_gcs gcs; } border_relief_descr; typedef struct { unsigned pressed_bmask : NUMBER_OF_TITLE_BUTTONS; unsigned lit_bmask : NUMBER_OF_TITLE_BUTTONS; unsigned toggled_bmask : NUMBER_OF_TITLE_BUTTONS; unsigned clear_bmask : NUMBER_OF_TITLE_BUTTONS; unsigned draw_bmask : NUMBER_OF_TITLE_BUTTONS; unsigned max_bmask : NUMBER_OF_TITLE_BUTTONS; ButtonState bstate[NUMBER_OF_TITLE_BUTTONS]; unsigned is_title_pressed : 1; unsigned is_title_lit : 1; unsigned do_clear_title : 1; ButtonState tstate; } border_titlebar_state; typedef struct { GC rgc; GC sgc; FlocaleWinString fstr; DecorFaceStyle *tstyle; DecorFace *df; unsigned is_toggled : 1; } title_draw_descr; typedef struct { common_decorations_type *cd; rectangle frame_g; rectangle bar_g; /* titlebar geo vs the frame */ rectangle left_buttons_g; /* vs the frame */ rectangle right_buttons_g; /* vs the frame */ frame_title_layout_t layout; frame_title_layout_t old_layout; border_titlebar_state tbstate; int length; /* text */ int offset; /* text offset */ /* MultiPixmap Geometries */ rectangle under_text_g; /* vs the titlebar */ rectangle left_main_g; /* vs the titlebar */ rectangle right_main_g; /* vs the titlebar */ rectangle full_left_main_g; /* vs the frame */ rectangle full_right_main_g; /* vs the frame */ int left_end_length; int left_of_text_length; int right_end_length; int right_of_text_length; rotation_t draw_rotation; rotation_t restore_rotation; unsigned td_is_rotated : 1; unsigned has_been_saved : 1; unsigned has_vt : 1; /* vertical title ? */ unsigned has_an_upsidedown_rotation : 1; /* 270 || 180 */ } titlebar_descr; /* ---------------------------- forward declarations ----------------------- */ /* forward declarations are not so good */ /* for grouping titlebar_descr computation */ static void border_rotate_titlebar_descr(FvwmWindow *fw, titlebar_descr *td); /* for grouping the MultiPixmap stuff */ static Bool border_mp_get_use_title_style_parts_and_geometry( titlebar_descr *td, FvwmPicture **pm, FvwmAcs *acs, unsigned short sf, int is_left, rectangle *g, int *part); /* ---------------------------- local variables ---------------------------- */ static const char ulgc[] = { 1, 0, 0, 0x7f, 2, 1, 1 }; static const char brgc[] = { 1, 1, 2, 0x7f, 0, 0, 3 }; /* ---------------------------- exported variables (globals) --------------- */ XGCValues Globalgcv; unsigned long Globalgcm; /* ---------------------------- local functions ---------------------------- */ static Bool is_button_toggled( FvwmWindow *fw, int button) { mwm_flags mf; if (!HAS_MWM_BUTTONS(fw)) { return False; } mf = TB_MWM_DECOR_FLAGS(GetDecor(fw, buttons[button])); if ((mf & MWM_DECOR_MAXIMIZE) && IS_MAXIMIZED(fw)) { return True; } if ((mf & MWM_DECOR_SHADE) && IS_SHADED(fw)) { return True; } if ((mf & MWM_DECOR_STICK) && (IS_STICKY_ACROSS_PAGES(fw) || IS_STICKY_ACROSS_DESKS(fw))) { return True; } if (TB_FLAGS(fw->decor->buttons[button]).has_layer && fw->layer == TB_LAYER(fw->decor->buttons[button])) { return True; } return False; } /* rules to get button state */ static ButtonState border_flags_to_button_state( int is_pressed, int is_lit, int is_toggled) { if (!is_lit && Scr.gs.use_inactive_buttons) { if (is_pressed && Scr.gs.use_inactive_down_buttons) { return (is_toggled) ? BS_ToggledInactiveDown : BS_InactiveDown; } else { return (is_toggled) ? BS_ToggledInactiveUp : BS_InactiveUp; } } else { if (is_pressed && Scr.gs.use_active_down_buttons) { return (is_toggled) ? BS_ToggledActiveDown : BS_ActiveDown; } else { return (is_toggled) ? BS_ToggledActiveUp : BS_ActiveUp; } } } static void get_common_decorations( common_decorations_type *cd, FvwmWindow *t, window_parts draw_parts, Bool has_focus, Bool is_border, Bool do_change_gcs) { DecorFace *df; color_quad *draw_colors; df = border_get_border_style(t, has_focus); cd->bg_border_cs = -1; cd->cs = -1; if (has_focus) { /* are we using textured borders? */ if (DFS_FACE_TYPE(df->style) == TiledPixmapButton && GetDecor(t, BorderStyle.active.u.p->depth) == Pdepth) { cd->texture_pixmap = GetDecor( t, BorderStyle.active.u.p->picture); cd->texture_pixmap_width = GetDecor( t, BorderStyle.active.u.p->width); cd->texture_pixmap_height = GetDecor( t, BorderStyle.active.u.p->height); } else if (DFS_FACE_TYPE(df->style) == ColorsetButton) { cd->bg_border_cs = GetDecor( t, BorderStyle.active.u.acs.cs); } cd->back_pixmap = Scr.gray_pixmap; if (is_border) { draw_colors = &(t->border_hicolors); cd->cs = t->border_cs_hi; } else { draw_colors = &(t->hicolors); cd->cs = t->cs_hi; } } else { if (DFS_FACE_TYPE(df->style) == TiledPixmapButton && GetDecor(t, BorderStyle.inactive.u.p->depth) == Pdepth) { cd->texture_pixmap = GetDecor( t, BorderStyle.inactive.u.p->picture); cd->texture_pixmap_width = GetDecor( t, BorderStyle.inactive.u.p->width); cd->texture_pixmap_height = GetDecor( t, BorderStyle.inactive.u.p->height); } else if (DFS_FACE_TYPE(df->style) == ColorsetButton) { cd->bg_border_cs = GetDecor( t, BorderStyle.inactive.u.acs.cs); } if (IS_STICKY_ACROSS_PAGES(t) || IS_STICKY_ACROSS_DESKS(t)) { cd->back_pixmap = Scr.sticky_gray_pixmap; } else { cd->back_pixmap = Scr.light_gray_pixmap; } if (is_border) { draw_colors = &(t->border_colors); cd->cs = t->border_cs; } else { draw_colors = &(t->colors); cd->cs = t->cs; } } cd->fore_color = draw_colors->fore; cd->back_color = draw_colors->back; if (do_change_gcs) { Globalgcv.foreground = draw_colors->hilight; Globalgcm = GCForeground; XChangeGC(dpy, Scr.ScratchGC1, Globalgcm, &Globalgcv); Globalgcv.foreground = draw_colors->shadow; XChangeGC(dpy, Scr.ScratchGC2, Globalgcm, &Globalgcv); cd->relief_gc = Scr.ScratchGC1; cd->shadow_gc = Scr.ScratchGC2; } /* MWMBorder style means thin 3d effects */ cd->relief_width = (HAS_MWM_BORDER(t) ? 1 : 2); if (cd->texture_pixmap) { cd->attributes.background_pixmap = cd->texture_pixmap; cd->valuemask = CWBackPixmap; } else { if (Pdepth < 2) { cd->attributes.background_pixmap = cd->back_pixmap; cd->valuemask = CWBackPixmap; } else { cd->attributes.background_pixel = cd->back_color; cd->valuemask = CWBackPixel; } } if (Pdepth < 2) { cd->notex_attributes.background_pixmap = cd->back_pixmap; cd->notex_valuemask = CWBackPixmap; } else { cd->notex_attributes.background_pixel = cd->back_color; cd->notex_valuemask = CWBackPixel; } return; } static window_parts border_get_changed_border_parts( FvwmWindow *fw, rectangle *old_sidebar_g, rectangle *new_sidebar_g, int cs) { window_parts changed_parts; changed_parts = PART_NONE; if (!CSET_IS_TRANSPARENT_PR(cs) && CSET_HAS_PIXMAP(cs) && (old_sidebar_g->x != new_sidebar_g->x || old_sidebar_g->y != new_sidebar_g->y || old_sidebar_g->width != new_sidebar_g->width || old_sidebar_g->height != new_sidebar_g->height)) { /* optimizable? */ changed_parts |= PART_FRAME; return changed_parts; } if (old_sidebar_g->x != new_sidebar_g->x) { changed_parts |= (PART_FRAME & (~PART_BORDER_W)); } if (old_sidebar_g->y != new_sidebar_g->y) { changed_parts |= (PART_FRAME & (~PART_BORDER_N)); } if (old_sidebar_g->width != new_sidebar_g->width) { changed_parts |= PART_BORDER_N | PART_BORDER_S; if (DFS_FACE_TYPE(GetDecor(fw, BorderStyle.active.style)) == TiledPixmapButton) { changed_parts |= PART_BORDER_NE | PART_BORDER_E | PART_BORDER_SE; } } if (old_sidebar_g->height != new_sidebar_g->height) { changed_parts |= PART_BORDER_W | PART_BORDER_E; if (DFS_FACE_TYPE(GetDecor(fw, BorderStyle.active.style)) == TiledPixmapButton) { changed_parts |= PART_BORDER_SW | PART_BORDER_S | PART_BORDER_SE; } } return changed_parts; } static int border_get_parts_and_pos_to_draw( common_decorations_type *cd, FvwmWindow *fw, window_parts pressed_parts, window_parts force_draw_parts, rectangle *old_g, rectangle *new_g, Bool do_hilight, border_relief_descr *br) { window_parts draw_parts; window_parts parts_to_light; rectangle sidebar_g_old; DecorFaceStyle *borderstyle; Bool has_x_marks; Bool has_x_marks_old; Bool has_y_marks; Bool has_y_marks_old; int cs = cd->bg_border_cs; draw_parts = 0; borderstyle = (do_hilight) ? &GetDecor(fw, BorderStyle.active.style) : &GetDecor(fw, BorderStyle.inactive.style); frame_get_sidebar_geometry( fw, borderstyle, new_g, &br->sidebar_g, &has_x_marks, &has_y_marks); if (has_x_marks == True) { draw_parts |= PART_X_HANDLES; br->marks.has_x_marks = 1; } else { br->marks.has_x_marks = 0; } if (has_y_marks == True) { draw_parts |= PART_Y_HANDLES; br->marks.has_y_marks = 1; } else { br->marks.has_y_marks = 0; } draw_parts |= (pressed_parts ^ fw->decor_state.parts_inverted); parts_to_light = (do_hilight == True) ? PART_FRAME : PART_NONE; draw_parts |= (parts_to_light ^ fw->decor_state.parts_lit); draw_parts |= (~(fw->decor_state.parts_drawn) & PART_FRAME); draw_parts |= force_draw_parts; if (old_g == NULL) { old_g = &fw->g.frame; } if ((draw_parts & PART_FRAME) == PART_FRAME) { draw_parts |= PART_FRAME; return draw_parts; } frame_get_sidebar_geometry( fw, borderstyle, old_g, &sidebar_g_old, &has_x_marks_old, &has_y_marks_old); if (has_x_marks_old != has_x_marks) { draw_parts |= (PART_FRAME & (~(PART_BORDER_N | PART_BORDER_S))); } if (has_y_marks_old != has_y_marks) { draw_parts |= (PART_FRAME & (~(PART_BORDER_W | PART_BORDER_E))); } draw_parts |= border_get_changed_border_parts( fw, &sidebar_g_old, &br->sidebar_g, cs); draw_parts &= (PART_FRAME | PART_HANDLES); return draw_parts; } static window_parts border_get_tb_parts_to_draw( FvwmWindow *fw, titlebar_descr *td, rectangle *old_g, rectangle *new_g, window_parts force_draw_parts) { window_parts draw_parts; ButtonState old_state; int i; DecorFace *df,*tdf; td->tbstate.draw_bmask = 0; draw_parts = PART_NONE; /* first time? */ draw_parts |= (~(fw->decor_state.parts_drawn) & PART_TITLE); td->tbstate.draw_bmask |= (~(fw->decor_state.buttons_drawn)); /* forced? */ draw_parts |= force_draw_parts; td->tbstate.draw_bmask |= (force_draw_parts & PART_BUTTONS) ? ~0 : 0; /* check if state changed */ old_state = border_flags_to_button_state( (fw->decor_state.parts_inverted & PART_TITLE), (fw->decor_state.parts_lit & PART_TITLE), 0); if (old_state != td->tbstate.tstate) { draw_parts |= PART_TITLE; } /* size changed? */ if ((td->old_layout.title_g.width != td->layout.title_g.width || td->old_layout.title_g.height != td->layout.title_g.height) && td->layout.title_g.x >= 0 && td->layout.title_g.y >= 0) { draw_parts |= PART_TITLE; } /* same for buttons */ for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; i++) { unsigned int mask = (1 << i); if (FW_W_BUTTON(fw, i) == None) { continue; } old_state = border_flags_to_button_state( (fw->decor_state.buttons_inverted & mask), (fw->decor_state.buttons_lit & mask), (fw->decor_state.buttons_toggled & mask)); if (old_state != td->tbstate.bstate[i]) { draw_parts |= PART_BUTTONS; td->tbstate.draw_bmask |= mask; } if ((td->old_layout.button_g[i].width != td->layout.button_g[i].width || td->old_layout.button_g[i].height != td->layout.button_g[i].height) && td->layout.button_g[i].x >= 0 && td->layout.button_g[i].y >= 0) { draw_parts |= PART_BUTTONS; td->tbstate.draw_bmask |= mask; } } /* position changed and background is tiled or a cset? */ if ((draw_parts & PART_TITLE) == PART_NONE && td->layout.title_g.x >= 0 && td->layout.title_g.y >= 0) { df = &TB_STATE(GetDecor(fw, titlebar))[td->tbstate.tstate]; if (DFS_USE_BORDER_STYLE(df->style) && (((td->old_layout.title_g.x != td->layout.title_g.x || td->old_layout.title_g.y != td->layout.title_g.y) && ((td->cd->valuemask & CWBackPixmap) || CSET_PIXMAP_IS_TILED(td->cd->bg_border_cs))) || (old_g->width != new_g->width && CSET_PIXMAP_IS_X_STRETCHED(td->cd->bg_border_cs)) || (old_g->height != new_g->height && CSET_PIXMAP_IS_Y_STRETCHED(td->cd->bg_border_cs)) || ((old_g->x != new_g->x || old_g->y != new_g->y) && CSET_IS_TRANSPARENT_ROOT(td->cd->bg_border_cs)))) { draw_parts |= PART_TITLE; } if ((draw_parts & PART_TITLE) == PART_NONE && (old_g->x != new_g->x || old_g->y != new_g->y)) { for (tdf = df; tdf != NULL; tdf = tdf->next) { if (DFS_FACE_TYPE(tdf->style) == ColorsetButton && CSET_IS_TRANSPARENT_ROOT(tdf->u.acs.cs)) { draw_parts |= PART_TITLE; break; } } } } for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; i++) { unsigned int mask; DecorFaceStyle *bs; mask = (1 << i); bs = &TB_STATE( GetDecor(fw, buttons[i]))[td->tbstate.bstate[i]].style; if ((td->tbstate.draw_bmask & mask) || td->layout.button_g[i].x < 0 || td->layout.button_g[i].y < 0) { continue; } if (DFS_USE_BORDER_STYLE(*bs) && (((td->old_layout.button_g[i].x != td->layout.button_g[i].x|| td->old_layout.button_g[i].y != td->layout.button_g[i].y) && ((td->cd->valuemask & CWBackPixmap) || CSET_PIXMAP_IS_TILED(td->cd->bg_border_cs))) || (old_g->width != new_g->width && CSET_PIXMAP_IS_X_STRETCHED(td->cd->bg_border_cs)) || (old_g->height != new_g->height && CSET_PIXMAP_IS_Y_STRETCHED(td->cd->bg_border_cs)) || ((old_g->x != new_g->x || old_g->y != new_g->y) && CSET_IS_TRANSPARENT_ROOT(td->cd->bg_border_cs)))) { td->tbstate.draw_bmask |= mask; } else if (DFS_USE_TITLE_STYLE(*bs)) { df = &TB_STATE(GetDecor( fw, titlebar))[td->tbstate.bstate[i]]; for(tdf = df; tdf != NULL; tdf = tdf->next) { int cs; if (DFS_FACE_TYPE(tdf->style) == MultiPixmap) { /* can be improved */ td->tbstate.draw_bmask |= mask; break; } if (DFS_FACE_TYPE(tdf->style) != ColorsetButton || !CSET_HAS_PIXMAP(tdf->u.acs.cs)) { continue; } cs = tdf->u.acs.cs; if(((td->old_layout.button_g[i].x != td->layout.button_g[i].x || td->old_layout.button_g[i].y != td->layout.button_g[i].y) || CSET_PIXMAP_IS_TILED(cs)) || (old_g->width != new_g->width && CSET_PIXMAP_IS_X_STRETCHED(cs)) || (old_g->height != new_g->height && CSET_PIXMAP_IS_Y_STRETCHED(cs)) || ((old_g->x != new_g->x || old_g->y != new_g->y) && CSET_IS_TRANSPARENT_ROOT(cs))) { td->tbstate.draw_bmask |= mask; break; } } } if (td->tbstate.draw_bmask & mask) { continue; } if (old_g->x != new_g->x || old_g->y != new_g->y) { df = &TB_STATE(GetDecor( fw, buttons[i]))[td->tbstate.bstate[i]]; for(tdf = df; tdf != NULL; tdf = tdf->next) { if (DFS_FACE_TYPE(tdf->style) == ColorsetButton && CSET_IS_TRANSPARENT_ROOT(tdf->u.acs.cs)) { td->tbstate.draw_bmask |= mask; break; } } } } td->tbstate.max_bmask = 0; for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; i++) { if (FW_W_BUTTON(fw, i) == None) { continue; } if ((i & 1) == 1 && i / 2 < Scr.nr_right_buttons) { td->tbstate.max_bmask |= (1 << i); } else if ((i & 1) == 0 && i / 2 < Scr.nr_left_buttons) { td->tbstate.max_bmask |= (1 << i); } } td->tbstate.draw_bmask &= td->tbstate.max_bmask; td->tbstate.pressed_bmask &= td->tbstate.max_bmask; td->tbstate.lit_bmask &= td->tbstate.max_bmask; td->tbstate.toggled_bmask &= td->tbstate.max_bmask; td->tbstate.clear_bmask &= td->tbstate.max_bmask; if (td->tbstate.draw_bmask == 0) { draw_parts &= ~PART_BUTTONS; } else { draw_parts |= PART_BUTTONS; } draw_parts &= PART_TITLEBAR; return draw_parts; } static void border_get_border_gcs( draw_border_gcs *ret_gcs, common_decorations_type *cd, FvwmWindow *fw, Bool do_hilight) { static GC transparent_gc = None; DecorFaceStyle *borderstyle; Bool is_reversed = False; if (transparent_gc == None && !HAS_NO_BORDER(fw) && !HAS_MWM_BORDER(fw)) { XGCValues xgcv; xgcv.function = GXnoop; xgcv.plane_mask = 0; transparent_gc = fvwmlib_XCreateGC( dpy, Scr.NoFocusWin, GCFunction | GCPlaneMask, &xgcv); } ret_gcs->transparent = transparent_gc; /* get the border style bits */ borderstyle = (do_hilight) ? &GetDecor(fw, BorderStyle.active.style) : &GetDecor(fw, BorderStyle.inactive.style); if (borderstyle->flags.button_relief == DFS_BUTTON_IS_SUNK) { is_reversed = True; } if (is_reversed) { ret_gcs->shadow = cd->relief_gc; ret_gcs->relief = cd->shadow_gc; } else { ret_gcs->relief = cd->relief_gc; ret_gcs->shadow = cd->shadow_gc; } return; } static void trim_border_layout( FvwmWindow *fw, DecorFaceStyle *borderstyle, border_relief_size_descr *ret_size_descr) { /* If the border is too thin to accomodate the standard look, we remove * parts of the border so that at least one pixel of the original * colour is visible. We make an exception for windows with a border * width of 2, though. */ if ((!IS_SHADED(fw) || HAS_TITLE(fw)) && fw->boundary_width == 2) { ret_size_descr->trim--; } if (ret_size_descr->trim < 0) { ret_size_descr->trim = 0; } for ( ; ret_size_descr->trim > 0; ret_size_descr->trim--) { if (ret_size_descr->w_hiout > 1) { ret_size_descr->w_hiout--; } else if (ret_size_descr->w_shin > 0) { ret_size_descr->w_shin--; } else if (ret_size_descr->w_hiout > 0) { ret_size_descr->w_hiout--; } else if (ret_size_descr->w_trout > 0) { ret_size_descr->w_trout = 0; ret_size_descr->w_trin = 0; ret_size_descr->w_din = 0; ret_size_descr->w_hiout = 1; } ret_size_descr->sum--; } ret_size_descr->w_c = fw->boundary_width - ret_size_descr->sum; return; } static void check_remove_inset( DecorFaceStyle *borderstyle, border_relief_size_descr *ret_size_descr) { if (!DFS_HAS_NO_INSET(*borderstyle)) { return; } ret_size_descr->w_shin = 0; ret_size_descr->sum--; ret_size_descr->trim--; if (ret_size_descr->w_trin) { ret_size_descr->w_trout = 0; ret_size_descr->w_trin = 0; ret_size_descr->w_din = 0; ret_size_descr->w_hiout = 1; ret_size_descr->sum -= 2; ret_size_descr->trim -= 2; } return; } static void border_fetch_mwm_layout( FvwmWindow *fw, DecorFaceStyle *borderstyle, border_relief_size_descr *ret_size_descr) { /* MWM borders look like this: * * HHCCCCS from outside to inside on the left and top border * SSCCCCH from outside to inside on the bottom and right border * ||||||| * |||||||__ w_shin (inner shadow area) * ||||||___ w_c (transparent area) * |||||____ w_c (transparent area) * ||||_____ w_c (transparent area) * |||______ w_c (transparent area) * ||_______ w_hiout (outer hilight area) * |________ w_hiout (outer hilight area) * * * C = original colour * H = hilight * S = shadow */ ret_size_descr->w_dout = 0; ret_size_descr->w_hiout = 2; ret_size_descr->w_trout = 0; ret_size_descr->w_trin = 0; ret_size_descr->w_shin = 1; ret_size_descr->w_din = 0; ret_size_descr->sum = 3; ret_size_descr->trim = ret_size_descr->sum - fw->boundary_width + 1; check_remove_inset(borderstyle, ret_size_descr); trim_border_layout(fw, borderstyle, ret_size_descr); return; } static void border_fetch_fvwm_layout( FvwmWindow *fw, DecorFaceStyle *borderstyle, border_relief_size_descr *ret_size_descr) { /* Fvwm borders look like this: * * SHHCCSS from outside to inside on the left and top border * SSCCHHS from outside to inside on the bottom and right border * ||||||| * |||||||__ w_din (inner dark area) * ||||||___ w_shin (inner shadow area) * |||||____ w_trin (inner transparent/shadow area) * ||||_____ w_c (transparent area) * |||______ w_trout (outer transparent/hilight area) * ||_______ w_hiout (outer hilight area) * |________ w_dout (outer dark area) * * C = original colour * H = hilight * S = shadow * * reduced to 5 pixels it looks like this: * * SHHCS * SSCHS * ||||| * |||||__ w_din (inner dark area) * ||||___ w_trin (inner transparent/shadow area) * |||____ w_trout (outer transparent/hilight area) * ||_____ w_hiout (outer hilight area) * |______ w_dout (outer dark area) */ ret_size_descr->w_dout = 1; ret_size_descr->w_hiout = 1; ret_size_descr->w_trout = 1; ret_size_descr->w_trin = 1; ret_size_descr->w_shin = 1; ret_size_descr->w_din = 1; /* w_trout + w_trin counts only as one pixel of border because * they let one pixel of the original colour shine through. */ ret_size_descr->sum = 6; ret_size_descr->trim = ret_size_descr->sum - fw->boundary_width; check_remove_inset(borderstyle, ret_size_descr); trim_border_layout(fw, borderstyle, ret_size_descr); return; } static void border_get_border_relief_size_descr( border_relief_size_descr *ret_size_descr, FvwmWindow *fw, Bool do_hilight) { DecorFaceStyle *borderstyle; if (is_window_border_minimal(fw)) { /* the border is too small, only a background but no relief */ ret_size_descr->is_flat = 1; return; } borderstyle = (do_hilight) ? &GetDecor(fw, BorderStyle.active.style) : &GetDecor(fw, BorderStyle.inactive.style); if (borderstyle->flags.button_relief == DFS_BUTTON_IS_FLAT) { ret_size_descr->is_flat = 1; return; } ret_size_descr->is_flat = 0; /* get the relief layout */ if (HAS_MWM_BORDER(fw)) { border_fetch_mwm_layout(fw, borderstyle, ret_size_descr); } else { border_fetch_fvwm_layout(fw, borderstyle, ret_size_descr); } return; } static void border_get_border_marks_descr( common_decorations_type *cd, border_relief_descr *br, FvwmWindow *fw) { int inset; /* get mark's length and thickness */ inset = (br->relief.w_shin != 0 || br->relief.w_din != 0); br->marks.length = fw->boundary_width - br->relief.w_dout - inset; if (br->marks.length <= 0) { br->marks.has_x_marks = 0; br->marks.has_y_marks = 0; return; } br->marks.thickness = cd->relief_width; if (br->marks.thickness > br->marks.length) { br->marks.thickness = br->marks.length; } /* get offsets from outer side of window */ br->marks.offset_tl = br->relief.w_dout; br->marks.offset_br = -br->relief.w_dout - br->marks.length - br->marks.offset_tl; return; } static Pixmap border_create_decor_pixmap( common_decorations_type *cd, rectangle *decor_g) { Pixmap p; p = XCreatePixmap( dpy, Scr.Root, decor_g->width, decor_g->height, Pdepth); return p; } static void border_draw_part_relief( border_relief_descr *br, rectangle *frame_g, rectangle *part_g, Pixmap dest_pix, Bool is_inverted) { int i; int off_x = 0; int off_y = 0; int width = frame_g->width - 1; int height = frame_g->height - 1; int w[7]; GC gc[4]; w[0] = br->relief.w_dout; w[1] = br->relief.w_hiout; w[2] = br->relief.w_trout; w[3] = br->relief.w_c; w[4] = br->relief.w_trin; w[5] = br->relief.w_shin; w[6] = br->relief.w_din; gc[(is_inverted == True)] = br->gcs.relief; gc[!(is_inverted == True)] = br->gcs.shadow; gc[2] = br->gcs.transparent; gc[3] = br->gcs.shadow; off_x = -part_g->x; off_y = -part_g->y; width = frame_g->width - 1; height = frame_g->height - 1; for (i = 0; i < 7; i++) { if (ulgc[i] != 0x7f && w[i] > 0) { do_relieve_rectangle( dpy, dest_pix, off_x, off_y, width, height, gc[(int)ulgc[i]], gc[(int)brgc[i]], w[i], False); } off_x += w[i]; off_y += w[i]; width -= 2 * w[i]; height -= 2 * w[i]; } return; } static void border_draw_x_mark( border_relief_descr *br, int x, int y, Pixmap dest_pix, Bool do_draw_shadow) { int k; int length; GC gc; if (br->marks.has_x_marks == 0) { return; } x += br->marks.offset_tl; gc = (do_draw_shadow) ? br->gcs.shadow : br->gcs.relief; /* draw it */ for (k = 0, length = br->marks.length - 1; k < br->marks.thickness; k++, length--) { int x1; int x2; int y1; int y2; if (length < 0) { break; } if (do_draw_shadow) { x1 = x + k; y1 = y - 1 - k; } else { x1 = x; y1 = y + k; } x2 = x1 + length; y2 = y1; XDrawLine(dpy, dest_pix, gc, x1, y1, x2, y2); } return; } static void border_draw_y_mark( border_relief_descr *br, int x, int y, Pixmap dest_pix, Bool do_draw_shadow) { int k; int length; GC gc; if (br->marks.has_y_marks == 0) { return; } y += br->marks.offset_tl; gc = (do_draw_shadow) ? br->gcs.shadow : br->gcs.relief; /* draw it */ for (k = 0, length = br->marks.length; k < br->marks.thickness; k++, length--) { int x1; int x2; int y1; int y2; if (length <= 0) { break; } if (do_draw_shadow) { x1 = x - 1 - k; y1 = y + k; } else { x1 = x + k; y1 = y; } x2 = x1; y2 = y1 + length - 1; XDrawLine(dpy, dest_pix, gc, x1, y1, x2, y2); } return; } static void border_draw_part_marks( border_relief_descr *br, rectangle *part_g, window_parts part, Pixmap dest_pix) { int l; int t; int w; int h; int o; l = br->sidebar_g.x; t = br->sidebar_g.y; w = part_g->width; h = part_g->height; o = br->marks.offset_br; switch (part) { case PART_BORDER_N: border_draw_y_mark(br, 0, 0, dest_pix, False); border_draw_y_mark(br, w, 0, dest_pix, True); break; case PART_BORDER_S: border_draw_y_mark(br, 0, h + o, dest_pix, False); border_draw_y_mark(br, w, h + o, dest_pix, True); break; case PART_BORDER_E: border_draw_x_mark(br, w + o, 0, dest_pix, False); border_draw_x_mark(br, w + o, h, dest_pix, True); break; case PART_BORDER_W: border_draw_x_mark(br, 0, 0, dest_pix, False); border_draw_x_mark(br, 0, h, dest_pix, True); break; case PART_BORDER_NW: border_draw_x_mark(br, 0, t, dest_pix, True); border_draw_y_mark(br, l, 0, dest_pix, True); break; case PART_BORDER_NE: border_draw_x_mark(br, l + o, t, dest_pix, True); border_draw_y_mark(br, 0, 0, dest_pix, False); break; case PART_BORDER_SW: border_draw_x_mark(br, 0, 0, dest_pix, False); border_draw_y_mark(br, l, t + o, dest_pix, True); break; case PART_BORDER_SE: border_draw_x_mark(br, l + o, 0, dest_pix, False); border_draw_y_mark(br, 0, t + o, dest_pix, False); break; default: return; } return; } inline static void border_set_part_background( Window w, Pixmap pix) { XSetWindowAttributes xswa; xswa.background_pixmap = pix; XChangeWindowAttributes(dpy, w, CWBackPixmap, &xswa); return; } /* render the an image into the pixmap */ static void border_fill_pixmap_background( Pixmap dest_pix, rectangle *dest_g, pixmap_background_type *bg, common_decorations_type *cd) { Bool do_tile; Bool do_stretch; XGCValues xgcv; unsigned long valuemask; Pixmap p = None, shape = None, alpha = None; int src_width, src_height; do_tile = (bg->flags.use_pixmap && bg->pixmap.flags.is_tiled) ? True : False; do_stretch = (bg->flags.use_pixmap && bg->pixmap.flags.is_stretched) ? True : False; xgcv.fill_style = FillSolid; valuemask = GCFillStyle; if (!bg->flags.use_pixmap) { /* solid pixel */ xgcv.foreground = bg->pixel; xgcv.clip_x_origin = 0; xgcv.clip_y_origin = 0; xgcv.clip_mask = None; valuemask |= GCForeground | GCClipMask | GCClipXOrigin | GCClipYOrigin; XChangeGC(dpy, Scr.BordersGC, valuemask, &xgcv); XFillRectangle( dpy, dest_pix, Scr.BordersGC, dest_g->x, dest_g->y, dest_g->width - dest_g->x, dest_g->height - dest_g->y); return; } if (do_stretch) { if (bg->pixmap.p) { p = CreateStretchPixmap( dpy, bg->pixmap.p, bg->pixmap.g.width, bg->pixmap.g.height, bg->pixmap.depth, bg->pixmap.stretch_w, bg->pixmap.stretch_h, (bg->pixmap.depth == 1)? Scr.MonoGC:Scr.BordersGC); } if (bg->pixmap.shape) { shape = CreateStretchPixmap( dpy, bg->pixmap.shape, bg->pixmap.g.width, bg->pixmap.g.height, 1, bg->pixmap.stretch_w, bg->pixmap.stretch_h, Scr.MonoGC); } if (bg->pixmap.alpha) { alpha = CreateStretchPixmap( dpy, bg->pixmap.alpha, bg->pixmap.g.width, bg->pixmap.g.height, FRenderGetAlphaDepth(), bg->pixmap.stretch_w, bg->pixmap.stretch_h, Scr.AlphaGC); } src_width = bg->pixmap.stretch_w; src_height = bg->pixmap.stretch_h; } else { p = bg->pixmap.p; shape = bg->pixmap.shape; alpha = bg->pixmap.alpha; src_width = bg->pixmap.g.width; src_height = bg->pixmap.g.height; } if (do_tile == False) { /* pixmap, offset stored in dest_g->x/y */ xgcv.foreground = cd->fore_color; xgcv.background = cd->back_color; valuemask |= GCForeground|GCBackground; XChangeGC(dpy, Scr.BordersGC, valuemask, &xgcv); PGraphicsRenderPixmaps( dpy, Scr.NoFocusWin, p, shape, alpha, bg->pixmap.depth, &(bg->pixmap.fra), dest_pix, Scr.BordersGC, Scr.MonoGC, Scr.AlphaGC, bg->pixmap.g.x, bg->pixmap.g.y, src_width, src_height, dest_g->x, dest_g->y, dest_g->width - dest_g->x, dest_g->height - dest_g->y, False); } else { /* tiled pixmap */ xgcv.foreground = cd->fore_color; xgcv.background = cd->back_color; valuemask |= GCForeground|GCBackground; XChangeGC(dpy, Scr.BordersGC, valuemask, &xgcv); PGraphicsRenderPixmaps( dpy, Scr.NoFocusWin, p, shape, alpha, bg->pixmap.depth, &(bg->pixmap.fra), dest_pix, Scr.BordersGC, Scr.MonoGC, Scr.AlphaGC, bg->pixmap.g.x, bg->pixmap.g.y, src_width, src_height, dest_g->x, dest_g->y, dest_g->width - dest_g->x, dest_g->height - dest_g->y, True); } if (p && p != bg->pixmap.p) { XFreePixmap(dpy, p); } if (shape && shape != bg->pixmap.shape) { XFreePixmap(dpy, shape); } if (alpha && alpha != bg->pixmap.alpha) { XFreePixmap(dpy, alpha); } return; } /* create a root transparent colorset bg, we take in account a possible * drawing rotation */ static Pixmap border_create_root_transparent_pixmap( titlebar_descr *td, Window w, int width, int height, int cs) { int my_w, my_h; Pixmap p; if (!CSET_IS_TRANSPARENT_ROOT(cs)) { return None; } if (td->td_is_rotated && (td->draw_rotation == ROTATION_90 || td->draw_rotation == ROTATION_270)) { my_h = width; my_w = height; } else { my_w = width; my_h = height; } p = CreateBackgroundPixmap( dpy, w, my_w, my_h, &Colorset[cs], Pdepth, Scr.BordersGC, False); if (p && td->td_is_rotated) { Pixmap tmp; tmp = CreateRotatedPixmap( dpy, p, my_w, my_h, Pdepth, Scr.BordersGC, td->restore_rotation); XFreePixmap(dpy, p); p = tmp; } return p; } static void border_get_frame_pixmap( common_decorations_type *cd, rectangle *frame_g) { dynamic_common_decorations *dcd = &(cd->dynamic_cd); if (dcd->frame_pixmap != None) { /* should not happen */ fprintf(stderr, "Bad use of border_get_frame_pixmap!!\n"); dcd->frame_pixmap = None; } if (cd->bg_border_cs < 0 || CSET_IS_TRANSPARENT(cd->bg_border_cs)) { /* should not happen */ } else { dcd->frame_pixmap = CreateBackgroundPixmap( dpy, Scr.NoFocusWin, frame_g->width, frame_g->height, &Colorset[cd->bg_border_cs], Pdepth, Scr.BordersGC, False); } return; } static void border_get_border_background( pixmap_background_type *bg, common_decorations_type *cd, rectangle *part_g, rectangle *relative_g, int *free_bg_pixmap, Window w) { *free_bg_pixmap = False; if (cd->texture_pixmap) { bg->flags.use_pixmap = 1; bg->pixmap.p = cd->texture_pixmap; bg->pixmap.g.width = cd->texture_pixmap_width; bg->pixmap.g.height = cd->texture_pixmap_height; bg->pixmap.shape = None; bg->pixmap.alpha = None; bg->pixmap.depth = Pdepth; bg->pixmap.flags.is_tiled = 1; bg->pixmap.flags.is_stretched = 0; bg->pixmap.fra.mask = 0; } else if (cd->bg_border_cs >= 0 && !CSET_IS_TRANSPARENT_PR(cd->bg_border_cs)) { colorset_t *cs_t = &Colorset[cd->bg_border_cs]; XGCValues xgcv; if (CSET_IS_TRANSPARENT_ROOT(cd->bg_border_cs)) { bg->pixmap.p = CreateBackgroundPixmap( dpy, w, part_g->width, part_g->height, cs_t, Pdepth, Scr.BordersGC, False); } else { /* FIXME */ if (cd->dynamic_cd.frame_pixmap == None) { border_get_frame_pixmap(cd, relative_g); } bg->pixmap.p = XCreatePixmap( dpy, cd->dynamic_cd.frame_pixmap, part_g->width, part_g->height, Pdepth); xgcv.fill_style = FillTiled; xgcv.tile = cd->dynamic_cd.frame_pixmap; xgcv.ts_x_origin = - relative_g->x; xgcv.ts_y_origin = - relative_g->y; XChangeGC( dpy, Scr.BordersGC, GCTile | GCTileStipXOrigin | GCTileStipYOrigin | GCFillStyle, &xgcv); XFillRectangle( dpy, bg->pixmap.p, Scr.BordersGC, 0, 0, part_g->width, part_g->height); xgcv.fill_style = FillSolid; XChangeGC(dpy, Scr.BordersGC, GCFillStyle, &xgcv); } bg->pixmap.g.width = part_g->width; bg->pixmap.g.height = part_g->height; bg->flags.use_pixmap = 1; bg->pixmap.shape = None; bg->pixmap.alpha = None; bg->pixmap.depth = Pdepth; bg->pixmap.flags.is_tiled = 1; bg->pixmap.flags.is_stretched = 0; bg->pixmap.fra.mask = 0; *free_bg_pixmap = True; } else { bg->flags.use_pixmap = 0; bg->pixel = cd->attributes.background_pixel; } return; } static void border_draw_one_border_part( common_decorations_type *cd, FvwmWindow *fw, rectangle *sidebar_g, rectangle *frame_g, border_relief_descr *br, window_parts part, window_parts draw_handles, Bool is_inverted, Bool do_clear) { pixmap_background_type bg; rectangle part_g; rectangle pix_g; rectangle relative_g; Pixmap p; Window w; Bool free_bg_pixmap = False; /* make a pixmap */ border_get_part_geometry(fw, part, sidebar_g, &part_g, &w); if (part_g.width <= 0 || part_g.height <= 0) { return; } p = border_create_decor_pixmap(cd, &part_g); /* set the background tile */ relative_g.width = fw->g.frame.width; relative_g.height = fw->g.frame.height; relative_g.x = part_g.x; relative_g.y = part_g.y; border_get_border_background( &bg, cd, &part_g, &relative_g, &free_bg_pixmap, w); if (cd->texture_pixmap) { switch (part) { case PART_BORDER_E: bg.pixmap.g.x = frame_g->width - fw->boundary_width; break; case PART_BORDER_NE: case PART_BORDER_SE: bg.pixmap.g.x = frame_g->width - fw->corner_width; break; case PART_BORDER_N: case PART_BORDER_S: bg.pixmap.g.x = fw->corner_width; break; default: bg.pixmap.g.x = 0; break; } switch (part) { case PART_BORDER_S: bg.pixmap.g.y = frame_g->height - fw->boundary_width; break; case PART_BORDER_SW: case PART_BORDER_SE: bg.pixmap.g.y = frame_g->height - fw->corner_width; break; case PART_BORDER_W: case PART_BORDER_E: bg.pixmap.g.y = fw->corner_width; break; default: bg.pixmap.g.y = 0; break; } } else { bg.pixmap.g.x = 0; bg.pixmap.g.y = 0; } /* set the geometry for drawing the Tiled pixmap; maybe add the relief * as offset? */ pix_g.x = 0; pix_g.y = 0; pix_g.width = part_g.width; pix_g.height = part_g.height; border_fill_pixmap_background(p, &pix_g, &bg, cd); if (free_bg_pixmap && bg.pixmap.p) { XFreePixmap(dpy, bg.pixmap.p); } /* draw the relief over the background */ if (!br->relief.is_flat) { border_draw_part_relief(br, frame_g, &part_g, p, is_inverted); /* draw the handle marks */ if (br->marks.has_x_marks || br->marks.has_y_marks) { border_draw_part_marks(br, &part_g, part, p); } } /* apply the pixmap and destroy it */ border_set_part_background(w, p); if (do_clear == True) { XClearWindow(dpy,w); } XFreePixmap(dpy, p); return; } static void border_draw_all_border_parts( common_decorations_type *cd, FvwmWindow *fw, border_relief_descr *br, rectangle *frame_g, window_parts draw_parts, window_parts pressed_parts, Bool do_hilight, Bool do_clear) { window_parts part; window_parts draw_handles; /* get the description of the drawing directives */ border_get_border_relief_size_descr(&br->relief, fw, do_hilight); border_get_border_marks_descr(cd, br, fw); /* fetch the gcs used to draw the border */ border_get_border_gcs(&br->gcs, cd, fw, do_hilight); /* draw everything in a big loop */ draw_parts &= (PART_FRAME | PART_HANDLES); draw_handles = (draw_parts & PART_HANDLES); for (part = PART_BORDER_N; (part & PART_FRAME); part <<= 1) { if (part & draw_parts) { border_draw_one_border_part( cd, fw, &br->sidebar_g, frame_g, br, part, draw_handles, (pressed_parts & part) ? True : False, do_clear); } } return; } /* * * Draws a little pattern within a window (more complex) * */ static void border_draw_vector_to_pixmap( Pixmap dest_pix, common_decorations_type *cd, int is_toggled, struct vector_coords *coords, rectangle *pixmap_g) { GC gcs[4]; int i; if (coords->use_fgbg == 1) { Globalgcv.foreground = cd->fore_color; Globalgcm = GCForeground; XChangeGC(dpy, Scr.ScratchGC3, Globalgcm, &Globalgcv); Globalgcv.foreground = cd->back_color; XChangeGC(dpy, Scr.ScratchGC4, Globalgcm, &Globalgcv); gcs[3] = Scr.ScratchGC3; /* @3 is fg */ gcs[2] = Scr.ScratchGC4; /* @2 is bg */ } if (is_toggled) { gcs[0] = cd->relief_gc; gcs[1] = cd->shadow_gc; } else { gcs[0] = cd->shadow_gc; gcs[1] = cd->relief_gc; } for (i = 1; i < coords->num; i++) { if (coords->c[i] < 0 || coords->c[i] >= 4) { /* don't draw a line */ continue; } XDrawLine( dpy, dest_pix, gcs[coords->c[i]], pixmap_g->width * coords->x[i-1] / 100 + coords->xoff[i-1], pixmap_g->height * coords->y[i-1] / 100 + coords->yoff[i-1], pixmap_g->width * coords->x[i] / 100 + coords->xoff[i], pixmap_g->height * coords->y[i] / 100 + coords->yoff[i]); } return; } /* * * Handle Title pixmaps used for UseTitleStyle * */ static void border_setup_bar_pixmaps( titlebar_descr *td, dynamic_common_decorations *dcd, DecorFace *df, ButtonState bs) { int count = dcd->bar_pixmaps[bs].count; DecorFace *tsdf; int i, j, mp_part_left, mp_part_right; if (count != 0) { /* ok */ return; } for (tsdf = df; tsdf != NULL; tsdf = tsdf->next) { if (DFS_FACE_TYPE(tsdf->style) == ColorsetButton) { count++; } else if (DFS_FACE_TYPE(tsdf->style) == MultiPixmap) { border_mp_get_use_title_style_parts_and_geometry( td, tsdf->u.mp.pixmaps, tsdf->u.mp.acs, tsdf->u.mp.solid_flags, True, NULL, &mp_part_left); border_mp_get_use_title_style_parts_and_geometry( td, tsdf->u.mp.pixmaps, tsdf->u.mp.acs, tsdf->u.mp.solid_flags, False, NULL, &mp_part_right); for (j = 0; j < UTS_TBMP_NUM_PIXMAPS; j++) { if (j != mp_part_left && j != mp_part_right) { continue; } if (tsdf->u.mp.acs[j].cs >= 0 || tsdf->u.mp.pixmaps[j]) { count++; } } } } if (count == 0) { dcd->bar_pixmaps[bs].count = -1; return; } else { dcd->bar_pixmaps[bs].bps = (bar_pixmap *)safemalloc(count*sizeof(bar_pixmap)); } dcd->bar_pixmaps[bs].count = count; i = 0; for (tsdf = df; tsdf != NULL; tsdf = tsdf->next) { if (DFS_FACE_TYPE(tsdf->style) == ColorsetButton) { dcd->bar_pixmaps[bs].bps[i].p = None; dcd->bar_pixmaps[bs].bps[i].mp_created_pic = NULL; dcd->bar_pixmaps[bs].bps[i].cs = tsdf->u.acs.cs; dcd->bar_pixmaps[bs].bps[i].mp_pic = NULL; dcd->bar_pixmaps[bs].bps[i].created = 0; dcd->bar_pixmaps[bs].bps[i].mp_part = TBMP_NONE; i++; } else if (DFS_FACE_TYPE(tsdf->style) == MultiPixmap) { border_mp_get_use_title_style_parts_and_geometry( td, tsdf->u.mp.pixmaps, tsdf->u.mp.acs, tsdf->u.mp.solid_flags, True, NULL, &mp_part_left); border_mp_get_use_title_style_parts_and_geometry( td, tsdf->u.mp.pixmaps, tsdf->u.mp.acs, tsdf->u.mp.solid_flags, False, NULL, &mp_part_right); for (j = 0; j < UTS_TBMP_NUM_PIXMAPS; j++) { if (j != mp_part_left && j != mp_part_right) { continue; } if (tsdf->u.mp.acs[j].cs >= 0 || tsdf->u.mp.pixmaps[j]) { dcd->bar_pixmaps[bs].bps[i].p = None; dcd->bar_pixmaps[bs].bps[i]. mp_created_pic = NULL; dcd->bar_pixmaps[bs].bps[i].cs = tsdf->u.mp.acs[j].cs; dcd->bar_pixmaps[bs].bps[i].mp_pic = tsdf->u.mp.pixmaps[j]; dcd->bar_pixmaps[bs].bps[i].created = 0; dcd->bar_pixmaps[bs].bps[i].mp_part = j; i++; } } } } } static Pixmap border_get_bar_pixmaps( dynamic_common_decorations *dcd, rectangle *bar_g, ButtonState bs, int cset, FvwmPicture *mp_pic, int mp_part, int stretch, FvwmPicture **mp_ret_pic) { ButtonState b; int i,j; int count = dcd->bar_pixmaps[bs].count; if (count <= 0) { return None; } i = 0; while(i < count && (dcd->bar_pixmaps[bs].bps[i].cs != cset || dcd->bar_pixmaps[bs].bps[i].mp_part != mp_part || dcd->bar_pixmaps[bs].bps[i].mp_pic != mp_pic)) { i++; } if (i == count) { return None; } if (mp_ret_pic) { *mp_ret_pic = dcd->bar_pixmaps[bs].bps[i].mp_created_pic; } if (dcd->bar_pixmaps[bs].bps[i].p == None) { /* see if we have it */ b = 0; while (b < BS_MaxButtonState) { int c = dcd->bar_pixmaps[b].count; j = 0; while(j < c && (dcd->bar_pixmaps[b].bps[j].cs != cset || dcd->bar_pixmaps[b].bps[j].mp_part != mp_part || dcd->bar_pixmaps[b].bps[j].mp_pic != mp_pic)) { j++; } if (j < c && dcd->bar_pixmaps[b].bps[j].p) { dcd->bar_pixmaps[bs].bps[i].p = dcd->bar_pixmaps[b].bps[j].p; if (mp_pic && mp_ret_pic) { *mp_ret_pic = dcd->bar_pixmaps[bs].bps[i]. mp_created_pic = dcd->bar_pixmaps[b].bps[j]. mp_created_pic; } break; } b++; } } if (dcd->bar_pixmaps[bs].bps[i].p == None) { if (cset >= 0) { dcd->bar_pixmaps[bs].bps[i].p = CreateBackgroundPixmap( dpy, Scr.NoFocusWin, bar_g->width, bar_g->height, &Colorset[cset], Pdepth, Scr.BordersGC, False); dcd->bar_pixmaps[bs].bps[i].created = True; } else if (mp_pic && mp_ret_pic) { if (stretch) { dcd->bar_pixmaps[bs].bps[i].mp_created_pic = PGraphicsCreateStretchPicture( dpy, Scr.NoFocusWin, mp_pic, bar_g->width, bar_g->height, Scr.BordersGC, Scr.MonoGC, Scr.AlphaGC); } else { dcd->bar_pixmaps[bs].bps[i].mp_created_pic = PGraphicsCreateTiledPicture( dpy, Scr.NoFocusWin, mp_pic, bar_g->width, bar_g->height, Scr.BordersGC, Scr.MonoGC, Scr.AlphaGC); } if (dcd->bar_pixmaps[bs].bps[i].mp_created_pic) { dcd->bar_pixmaps[bs].bps[i].created = True; *mp_ret_pic = dcd->bar_pixmaps[bs].bps[i]. mp_created_pic; dcd->bar_pixmaps[bs].bps[i].p = dcd->bar_pixmaps[bs].bps[i]. mp_created_pic->picture; } } } return dcd->bar_pixmaps[bs].bps[i].p; } static void border_free_bar_pixmaps( dynamic_common_decorations *dcd) { ButtonState bs; int i; for (bs = 0; bs < BS_MaxButtonState; bs++) { if (dcd->bar_pixmaps[bs].count < 1) { continue; } for (i = 0; i < dcd->bar_pixmaps[bs].count; i++) { if (dcd->bar_pixmaps[bs].bps[i].mp_created_pic && dcd->bar_pixmaps[bs].bps[i].created) { PDestroyFvwmPicture( dpy, dcd->bar_pixmaps[bs].bps[i]. mp_created_pic); } else if (dcd->bar_pixmaps[bs].bps[i].p != None && dcd->bar_pixmaps[bs].bps[i].created) { XFreePixmap( dpy, dcd->bar_pixmaps[bs].bps[i].p); } } free(dcd->bar_pixmaps[bs].bps); } } /* * * MultiPixmap (aka, fancy title bar) (tril@igs.net) * */ #define TBMP_HAS_PART(p, pm, acs, sf) \ (pm[p] || acs[p].cs >= 0 || (sf & (1 << p))) /* Tile or stretch src into dest, starting at the given location and * continuing for the given width and height. This is a utility function used * by border_mp_draw_mp_titlebar. (tril@igs.net) */ static void border_mp_render_into_pixmap( titlebar_descr *td, common_decorations_type *cd, FvwmPicture **src, FvwmAcs *acs, Pixel *pixels, unsigned short solid_flags, unsigned short stretch_flags, int part, Pixmap dest, Window w, rectangle *full_g, rectangle *title_g, ButtonState bs, rectangle *g) { int x = 0; int y = 0; pixmap_background_type bg; rectangle dest_g; dynamic_common_decorations *dcd; dcd = &cd->dynamic_cd; /* setup some default */ bg.pixmap.fra.mask = 0; bg.pixmap.flags.is_stretched = 0; bg.pixmap.flags.is_tiled = 0; bg.flags.use_pixmap = 1; bg.pixmap.p = bg.pixmap.alpha = bg.pixmap.shape = None; bg.pixmap.g.x = 0; bg.pixmap.g.y = 0; dest_g.width = g->width + g->x; dest_g.height = g->height + g->y; dest_g.x = g->x; dest_g.y = g->y; if (solid_flags & (1 << part)) { bg.flags.use_pixmap = 0; bg.pixel = pixels[part]; border_fill_pixmap_background(dest, &dest_g, &bg, cd); return; } else if (acs[part].cs >= 0) { Pixmap p = None; bg.pixmap.fra.mask = FRAM_HAVE_ADDED_ALPHA; bg.pixmap.fra.added_alpha_percent = acs[part].alpha_percent; if (CSET_IS_TRANSPARENT_PR(acs[part].cs)) { return; } if (CSET_IS_TRANSPARENT_ROOT(acs[part].cs)) { p = border_create_root_transparent_pixmap( td, w, g->width + g->x, g->height + g->y, acs[part].cs); bg.pixmap.p = p; bg.pixmap.depth = Pdepth; bg.pixmap.g.width = g->width; bg.pixmap.g.height = g->height; bg.pixmap.g.x = g->x; bg.pixmap.g.y = g->y; } else if (full_g != NULL) { bg.pixmap.p = border_get_bar_pixmaps( dcd, full_g, bs, acs[part].cs, NULL, part, (stretch_flags & (1 << part)), NULL); if (bg.pixmap.p) { if (part != TBMP_RIGHT_MAIN) { /* left buttons offset */ x = title_g->x - full_g->x; y = title_g->y - full_g->y; } bg.pixmap.g.width = full_g->width; bg.pixmap.g.height = full_g->height; bg.pixmap.flags.is_tiled = 1; bg.pixmap.g.x = x; bg.pixmap.g.y = y; bg.pixmap.depth = Pdepth; } } if (!bg.pixmap.p) { int bg_w, bg_h; p = CreateBackgroundPixmap( dpy, w, g->width, g->height, &Colorset[acs[part].cs], Pdepth, Scr.BordersGC, False); bg.pixmap.p = p; GetWindowBackgroundPixmapSize( &Colorset[acs[part].cs], g->width, g->height, &bg_w, &bg_h); bg.pixmap.g.width = bg_w; bg.pixmap.g.height = bg_h; bg.pixmap.depth = Pdepth; bg.pixmap.flags.is_tiled = 1; } if (bg.pixmap.p) { border_fill_pixmap_background(dest, &dest_g, &bg, cd); } if (p) { XFreePixmap(dpy, p); } } else if (src[part]) { FvwmPicture *full_pic = NULL; Pixmap p; if (full_g != NULL) { p = border_get_bar_pixmaps( dcd, full_g, bs, -1, src[part], part, (stretch_flags & (1 << part)), &full_pic); if (p && full_pic) { if (part != TBMP_RIGHT_MAIN) { /* left buttons offset */ x = title_g->x - full_g->x; y = title_g->y - full_g->y; } bg.pixmap.p = full_pic->picture; bg.pixmap.shape = full_pic->mask; bg.pixmap.alpha = full_pic->alpha; bg.pixmap.depth = full_pic->depth; bg.pixmap.g.width = full_pic->width; bg.pixmap.g.height = full_pic->height; bg.pixmap.g.x = x; bg.pixmap.g.y = y; } } if (!bg.pixmap.p) { if (stretch_flags & (1 << part)) { bg.pixmap.flags.is_stretched = 1; } else { bg.pixmap.flags.is_tiled = 1; } bg.pixmap.p = src[part]->picture; bg.pixmap.shape = src[part]->mask; bg.pixmap.alpha = src[part]->alpha; bg.pixmap.depth = src[part]->depth; bg.pixmap.g.width = src[part]->width; bg.pixmap.g.height = src[part]->height; bg.pixmap.stretch_w = dest_g.width - dest_g.x; bg.pixmap.stretch_h = dest_g.height - dest_g.y; } if (bg.pixmap.p) { border_fill_pixmap_background(dest, &dest_g, &bg, cd); } } return; } static int border_mp_get_length( titlebar_descr *td, FvwmPicture **pm, FvwmAcs *acs, unsigned int solid_flags, int part) { if (acs[part].cs >= 0 || (solid_flags & (1 << part))) { /* arbitrary */ if (td->has_vt) { return td->bar_g.width/2; } else { return td->bar_g.height/2; } } if (pm[part] == NULL) { return 0; } else if (td->has_vt) { return pm[part]->height; } else { return pm[part]->width; } } /* geometries relatively to the frame */ static void border_mp_get_titlebar_descr( FvwmWindow *fw, titlebar_descr *td, DecorFace *df) { DecorFace *tsdf; FvwmPicture **pm; FvwmAcs *acs; int add,tmpi; int left_of_text = 0; int right_of_text = 0; int left_end = 0; int right_end = 0; int before_space, after_space, under_offset, under_width; Bool has_mp = False; JustificationType just; unsigned short sf; int is_start = 0; just = TB_JUSTIFICATION(GetDecor(fw, titlebar)); /* first compute under text width */ if (td->length > 0) { under_width = td->length + 2*TBMP_TITLE_PADDING; } else { under_width = 0; } if (under_width > fw->title_length) { under_width = fw->title_length; td->offset = (fw->title_length - td->length) / 2; just = JUST_CENTER; } for (tsdf = df; tsdf != NULL; tsdf = tsdf->next) { if (tsdf->style.face_type != MultiPixmap) { continue; } has_mp = True; acs = tsdf->u.mp.acs; pm = tsdf->u.mp.pixmaps; sf = tsdf->u.mp.solid_flags; add = border_mp_get_length( td, pm, acs, sf, TBMP_LEFT_OF_TEXT); if (add > left_of_text && add + left_end + right_of_text + right_end + under_width + 2*TBMP_MIN_RL_TITLE_LENGTH <= fw->title_length) { left_of_text = add; } add = border_mp_get_length( td, pm, acs, sf, TBMP_RIGHT_OF_TEXT); if (add > right_of_text && add + left_end + left_of_text + right_end + under_width + 2*TBMP_MIN_RL_TITLE_LENGTH <= fw->title_length) { right_of_text = add; } add = border_mp_get_length( td, pm, acs, sf, TBMP_LEFT_END); if (add > left_end && add + right_of_text + left_of_text + right_end + under_width + 2*TBMP_MIN_RL_TITLE_LENGTH <= fw->title_length) { left_end = add; } add = border_mp_get_length( td, pm, acs, sf, TBMP_RIGHT_END); if (add > right_end && add + right_of_text + left_of_text + left_end + under_width + 2*TBMP_MIN_RL_TITLE_LENGTH <= fw->title_length) { right_end = add; } } if (!has_mp) { return; } switch (just) { case JUST_LEFT: is_start = 1; /* fall through */ case JUST_RIGHT: if (td->has_an_upsidedown_rotation) { is_start = !is_start; } if (is_start) { if (td->has_an_upsidedown_rotation) { td->offset = max( td->offset, right_of_text + right_end + TBMP_MIN_RL_TITLE_LENGTH + TBMP_TITLE_PADDING); } else { td->offset = max( td->offset, left_of_text + left_end + TBMP_MIN_RL_TITLE_LENGTH + TBMP_TITLE_PADDING); } } else { if (td->has_an_upsidedown_rotation) { td->offset = min( td->offset, fw->title_length - (td->length + left_of_text + left_end + TBMP_MIN_RL_TITLE_LENGTH + TBMP_TITLE_PADDING)); } else { td->offset = min( td->offset, fw->title_length - (td->length + right_of_text + right_end + TBMP_MIN_RL_TITLE_LENGTH + TBMP_TITLE_PADDING)); } } break; case JUST_CENTER: default: break; } under_offset = td->offset - (under_width - td->length)/2; before_space = under_offset; if (td->has_vt) { after_space = td->layout.title_g.height - before_space - under_width; } else { after_space = td->layout.title_g.width - before_space - under_width; } if (td->has_an_upsidedown_rotation) { td->left_end_length = right_end; td->left_of_text_length = right_of_text; td->right_of_text_length = left_of_text; td->right_end_length = left_end; tmpi = before_space; before_space = after_space; after_space = tmpi; } else { td->left_end_length = left_end; td->left_of_text_length = left_of_text; td->right_of_text_length = right_of_text; td->right_end_length = right_end; } if (td->has_vt) { td->under_text_g.width = td->bar_g.width; td->under_text_g.height = under_width; td->under_text_g.x = 0; td->under_text_g.y = under_offset; } else { td->under_text_g.height = td->bar_g.height; td->under_text_g.width = under_width; td->under_text_g.x = under_offset; td->under_text_g.y = 0; } /* width & height */ if (td->has_vt) { /* left */ td->full_left_main_g.width = td->bar_g.width; td->full_left_main_g.height = before_space + td->left_buttons_g.height; td->left_main_g.width = td->bar_g.width; td->left_main_g.height = before_space; /* right */ td->full_right_main_g.width = td->bar_g.width; td->full_right_main_g.height = after_space + td->right_buttons_g.height; td->right_main_g.width = td->bar_g.width; td->right_main_g.height = after_space; } else { /* left */ td->full_left_main_g.height = td->bar_g.height; td->full_left_main_g.width = before_space + td->left_buttons_g.width; td->left_main_g.height = td->bar_g.height; td->left_main_g.width = before_space; /* right */ td->full_right_main_g.height = td->bar_g.height; td->full_right_main_g.width = after_space + td->right_buttons_g.width; td->right_main_g.height = td->bar_g.height; td->right_main_g.width = after_space; } /* position */ if (td->has_an_upsidedown_rotation) { td->full_right_main_g.x = td->bar_g.x; td->full_right_main_g.y = td->bar_g.y; td->right_main_g.x = 0; td->right_main_g.y = 0; } else { td->full_left_main_g.x = td->bar_g.x; td->full_left_main_g.y = td->bar_g.y; td->left_main_g.x = 0; td->left_main_g.y = 0; } if (td->has_vt) { if (td->has_an_upsidedown_rotation) { td->full_left_main_g.x = td->bar_g.x; td->full_left_main_g.y = td->full_right_main_g.height + td->bar_g.y + td->under_text_g.height; td->left_main_g.y = td->under_text_g.y + td->under_text_g.height; td->left_main_g.x = 0; } else { td->full_right_main_g.x = td->bar_g.x; td->full_right_main_g.y = td->full_left_main_g.height + td->bar_g.y + td->under_text_g.height; td->right_main_g.y = td->under_text_g.y + td->under_text_g.height; td->right_main_g.x = 0; } } else { if (td->has_an_upsidedown_rotation) { td->full_left_main_g.x = td->full_right_main_g.width + td->bar_g.x + td->under_text_g.width; td->full_left_main_g.y = td->bar_g.y; td->left_main_g.x = td->under_text_g.x + td->under_text_g.width; td->left_main_g.y = 0; } else { td->full_right_main_g.x = td->full_left_main_g.width + td->bar_g.x + td->under_text_g.width; td->full_right_main_g.y = td->bar_g.y; td->right_main_g.x = td->under_text_g.x + td->under_text_g.width; td->right_main_g.y = 0; } } } /* the returned geometries are relative to the titlebar (not the frame) */ static void border_mp_get_extreme_geometry( titlebar_descr *td, FvwmPicture **pm, FvwmAcs *acs, unsigned short sf, rectangle *left_of_text_g, rectangle *right_of_text_g, rectangle *left_end_g, rectangle *right_end_g) { int left_of_text = 0; int right_of_text = 0; int left_end = 0; int right_end = 0; left_of_text = border_mp_get_length( td, pm, acs, sf, TBMP_LEFT_OF_TEXT); left_end = border_mp_get_length( td, pm, acs, sf, TBMP_LEFT_END); right_of_text = border_mp_get_length( td, pm, acs, sf, TBMP_RIGHT_OF_TEXT); right_end = border_mp_get_length( td, pm, acs, sf, TBMP_RIGHT_END); if (left_of_text > 0 && left_of_text <= td->left_of_text_length) { if (td->has_vt) { left_of_text_g->y = td->under_text_g.y - left_of_text; left_of_text_g->x = 0; left_of_text_g->height = left_of_text; left_of_text_g->width = td->bar_g.width; } else { left_of_text_g->x = td->under_text_g.x - left_of_text; left_of_text_g->y = 0; left_of_text_g->width = left_of_text; left_of_text_g->height = td->bar_g.height; } } else { left_of_text_g->x = 0; left_of_text_g->y = 0; left_of_text_g->width = 0; left_of_text_g->height = 0; } if (right_of_text > 0 && right_of_text <= td->right_of_text_length) { if (td->has_vt) { right_of_text_g->y = td->under_text_g.y + td->under_text_g.height; right_of_text_g->x = 0; right_of_text_g->height = right_of_text; right_of_text_g->width = td->bar_g.width; } else { right_of_text_g->x = td->under_text_g.x + td->under_text_g.width; right_of_text_g->y = 0; right_of_text_g->width = right_of_text; right_of_text_g->height = td->bar_g.height; } } else { right_of_text_g->x = 0; right_of_text_g->y = 0; right_of_text_g->width = 0; right_of_text_g->height = 0; } if (left_end > 0 && left_end <= td->left_end_length) { if (td->has_vt) { left_end_g->y = 0; left_end_g->x = 0; left_end_g->height = left_end; left_end_g->width = td->bar_g.width; } else { left_end_g->x = 0; left_end_g->y = 0; left_end_g->width = left_end; left_end_g->height = td->bar_g.height; } } else { left_end_g->x = 0; left_end_g->y = 0; left_end_g->width = 0; left_end_g->height = 0; } if (right_end > 0 && right_end <= td->right_end_length) { if (td->has_vt) { right_end_g->y = td->layout.title_g.height - right_end; right_end_g->x = 0; right_end_g->height = right_end; right_end_g->width = td->bar_g.width; } else { right_end_g->x = td->layout.title_g.width - right_end; right_end_g->y = 0; right_end_g->width = right_end; right_end_g->height = td->bar_g.height; } } else { right_end_g->x = 0; right_end_g->y = 0; right_end_g->width = 0; right_end_g->height = 0; } return; } static Bool border_mp_get_use_title_style_parts_and_geometry( titlebar_descr *td, FvwmPicture **pm, FvwmAcs *acs, unsigned short sf, int is_left, rectangle *g, int *part) { rectangle *tmp_g = NULL; Bool g_ok = True; if (is_left && TBMP_HAS_PART(TBMP_LEFT_BUTTONS, pm, acs, sf)) { *part = TBMP_LEFT_BUTTONS; tmp_g = &td->left_buttons_g; } else if (!is_left && TBMP_HAS_PART(TBMP_RIGHT_BUTTONS, pm, acs, sf)) { *part = TBMP_RIGHT_BUTTONS; tmp_g = &td->right_buttons_g; } else if (is_left && TBMP_HAS_PART(TBMP_LEFT_MAIN, pm, acs, sf)) { *part = TBMP_LEFT_MAIN; tmp_g = &td->full_left_main_g; } else if (!is_left && TBMP_HAS_PART(TBMP_RIGHT_MAIN, pm, acs, sf)) { *part = TBMP_RIGHT_MAIN; tmp_g = &td->full_right_main_g; } else if (TBMP_HAS_PART(TBMP_MAIN, pm, acs, sf)) { *part = TBMP_MAIN; tmp_g = &(td->bar_g); } else { *part = TBMP_NONE; } if (g && tmp_g) { g->x = tmp_g->x; g->y = tmp_g->y; g->width = tmp_g->width; g->height = tmp_g->height; g_ok = True; } return g_ok; } /* Redraws multi-pixmap titlebar (tril@igs.net) */ static void border_mp_draw_mp_titlebar( FvwmWindow *fw, titlebar_descr *td, DecorFace *df, Pixmap dest_pix, Window w) { FvwmPicture **pm; FvwmAcs *acs; Pixel *pixels; unsigned short solid_flags; unsigned short stretch_flags; rectangle tmp_g, left_of_text_g,left_end_g,right_of_text_g,right_end_g; ButtonState bs; bs = td->tbstate.tstate; pm = df->u.mp.pixmaps; acs = df->u.mp.acs; pixels = df->u.mp.pixels; stretch_flags = df->u.mp.stretch_flags; solid_flags = df->u.mp.solid_flags; tmp_g.x = 0; tmp_g.y = 0; tmp_g.width = td->layout.title_g.width; tmp_g.height = td->layout.title_g.height; if (TBMP_HAS_PART(TBMP_MAIN, pm, acs, solid_flags)) { border_mp_render_into_pixmap( td, td->cd, pm, acs, pixels, solid_flags, stretch_flags, TBMP_MAIN, dest_pix, w, &td->bar_g, &td->layout.title_g, bs, &tmp_g); } else if (td->length <= 0) { border_mp_render_into_pixmap( td, td->cd, pm, acs, pixels, solid_flags, stretch_flags, TBMP_LEFT_MAIN, dest_pix, w, NULL, &td->layout.title_g, bs, &tmp_g); } border_mp_get_extreme_geometry( td, pm, acs, solid_flags, &left_of_text_g, &right_of_text_g, &left_end_g, &right_end_g); if (td->length > 0) { if (TBMP_HAS_PART(TBMP_LEFT_MAIN, pm, acs, solid_flags) && td->left_main_g.width > 0 && td->left_main_g.height > 0) { border_mp_render_into_pixmap( td, td->cd, pm, acs, pixels, solid_flags, stretch_flags, TBMP_LEFT_MAIN, dest_pix, w, &td->full_left_main_g, &td->layout.title_g, bs, &td->left_main_g); } if (TBMP_HAS_PART(TBMP_RIGHT_MAIN, pm, acs, solid_flags) && td->right_main_g.width > 0 && td->right_main_g.height > 0) { border_mp_render_into_pixmap( td, td->cd, pm, acs, pixels, solid_flags, stretch_flags, TBMP_RIGHT_MAIN, dest_pix, w, &td->full_right_main_g, &td->layout.title_g, bs, &td->right_main_g); } if (TBMP_HAS_PART(TBMP_UNDER_TEXT, pm, acs, solid_flags) && td->under_text_g.width > 0 && td->under_text_g.height > 0) { border_mp_render_into_pixmap( td, td->cd, pm, acs, pixels, solid_flags, stretch_flags, TBMP_UNDER_TEXT, dest_pix, w, NULL, &td->layout.title_g, bs, &td->under_text_g); } if (left_of_text_g.width > 0 && left_of_text_g.height > 0) { border_mp_render_into_pixmap( td, td->cd, pm, acs, pixels, solid_flags, stretch_flags, TBMP_LEFT_OF_TEXT, dest_pix, w, NULL, &td->layout.title_g, bs, &left_of_text_g); } if (right_of_text_g.width > 0 && right_of_text_g.height > 0) { border_mp_render_into_pixmap( td, td->cd, pm, acs, pixels, solid_flags, stretch_flags, TBMP_RIGHT_OF_TEXT, dest_pix, w, NULL, &td->layout.title_g, bs, &right_of_text_g); } } if (left_end_g.width > 0 && left_end_g.height > 0) { border_mp_render_into_pixmap( td, td->cd, pm, acs, pixels, solid_flags, stretch_flags, TBMP_LEFT_END, dest_pix, w, NULL, &td->layout.title_g, bs, &left_end_g); } if (right_end_g.width > 0 && right_end_g.height > 0) { border_mp_render_into_pixmap( td, td->cd, pm, acs, pixels, solid_flags, stretch_flags, TBMP_RIGHT_END, dest_pix, w, NULL, &td->layout.title_g, bs, &right_end_g); } return; } /* * * draw title bar and buttons * */ static void border_draw_decor_to_pixmap( FvwmWindow *fw, Pixmap dest_pix, Window w, pixmap_background_type *solid_bg, rectangle *w_g, DecorFace *df, titlebar_descr *td, ButtonState bs, int use_title_style, int is_toggled, int left1right0) { register DecorFaceType type = DFS_FACE_TYPE(df->style); pixmap_background_type bg; rectangle dest_g; FvwmPicture *p; int width,height; int border; int lr_just, tb_just; common_decorations_type *cd; cd = td->cd; /* setup some default */ bg.pixmap.fra.mask = 0; bg.pixmap.flags.is_stretched = 0; bg.pixmap.flags.is_tiled = 0; bg.flags.use_pixmap = 0; bg.pixmap.g.x = 0; bg.pixmap.g.y = 0; if (DFS_BUTTON_RELIEF(df->style) == DFS_BUTTON_IS_FLAT) { border = 0; } else { border = HAS_MWM_BORDER(fw) ? 1 : 2; } dest_g.width = w_g->width; dest_g.height = w_g->height; dest_g.x = border; dest_g.y = border; switch (type) { case SimpleButton: /* do nothing */ break; case SolidButton: /* overwrite with the default background */ dest_g.x = 0; dest_g.y = 0; border_fill_pixmap_background(dest_pix, &dest_g, solid_bg, cd); break; case VectorButton: case DefaultVectorButton: border_draw_vector_to_pixmap( dest_pix, cd, is_toggled, &df->u.vector, w_g); break; case MiniIconButton: case PixmapButton: case ShrunkPixmapButton: case StretchedPixmapButton: if (w_g->width - 2*border <= 0 || w_g->height - 2*border <= 0) { break; } if (FMiniIconsSupported && type == MiniIconButton) { if (!fw->mini_icon) { break; } p = fw->mini_icon; if (cd->cs >= 0) { bg.pixmap.fra.mask |= FRAM_HAVE_ICON_CSET; bg.pixmap.fra.colorset = &Colorset[cd->cs]; } } else { p = df->u.p; } width = p->width; height = p->height; if ((type == ShrunkPixmapButton || type == MiniIconButton) && (p->width > w_g->width - 2*border || p->height > w_g->height - 2*border)) { /* do so that the picture fit into the destination */ bg.pixmap.stretch_w = width = min(w_g->width - 2*border, p->width); bg.pixmap.stretch_h = height = min(w_g->height - 2*border, p->height); bg.pixmap.flags.is_stretched = 1; } else if (type == StretchedPixmapButton && (p->width < w_g->width - 2*border || p->height < w_g->height - 2*border)) { /* do so that the picture fit into the destination */ bg.pixmap.stretch_w = width = max(w_g->width - 2*border, p->width); bg.pixmap.stretch_h = height = max(w_g->height - 2*border, p->height); bg.pixmap.flags.is_stretched = 1; } lr_just = DFS_H_JUSTIFICATION(df->style); tb_just = DFS_V_JUSTIFICATION(df->style); if (!td->td_is_rotated && fw->title_text_rotation != ROTATION_0) { if (fw->title_text_rotation == ROTATION_180) { switch (lr_just) { case JUST_LEFT: lr_just = JUST_RIGHT; break; case JUST_RIGHT: lr_just = JUST_LEFT; break; case JUST_CENTER: default: break; } switch (tb_just) { case JUST_TOP: tb_just = JUST_BOTTOM; break; case JUST_BOTTOM: tb_just = JUST_TOP; break; case JUST_CENTER: default: break; } } else if (fw->title_text_rotation == ROTATION_90) { switch (lr_just) { case JUST_LEFT: tb_just = JUST_TOP; break; case JUST_RIGHT: tb_just = JUST_BOTTOM; break; case JUST_CENTER: default: tb_just = JUST_CENTER; break; } switch (DFS_V_JUSTIFICATION(df->style)) { case JUST_TOP: lr_just = JUST_RIGHT; break; case JUST_BOTTOM: lr_just = JUST_LEFT; break; case JUST_CENTER: default: lr_just = JUST_CENTER; break; } } else if (fw->title_text_rotation == ROTATION_270) { switch (lr_just) { case JUST_LEFT: tb_just = JUST_BOTTOM; break; case JUST_RIGHT: tb_just = JUST_TOP; break; case JUST_CENTER: default: tb_just = JUST_CENTER; break; } switch (DFS_V_JUSTIFICATION(df->style)) { case JUST_TOP: lr_just = JUST_LEFT; break; case JUST_BOTTOM: lr_just = JUST_RIGHT; break; case JUST_CENTER: default: lr_just = JUST_CENTER; break; } } } switch (lr_just) { case JUST_LEFT: dest_g.x = border; break; case JUST_RIGHT: dest_g.x = (int)(w_g->width - width - border); break; case JUST_CENTER: default: /* round down */ dest_g.x = (int)(w_g->width - width) / 2; break; } switch (tb_just) { case JUST_TOP: dest_g.y = border; break; case JUST_BOTTOM: dest_g.y = (int)(w_g->height - height - border); break; case JUST_CENTER: default: /* round down */ dest_g.y = (int)(w_g->height - height) / 2; break; } if (dest_g.x < border) { dest_g.x = border; } if (dest_g.y < border) { dest_g.y = border; } bg.flags.use_pixmap = 1; bg.pixmap.p = p->picture; bg.pixmap.shape = p->mask; bg.pixmap.alpha = p->alpha; bg.pixmap.depth = p->depth; bg.pixmap.g.width = p->width; bg.pixmap.g.height = p->height; border_fill_pixmap_background(dest_pix, &dest_g, &bg, cd); break; case TiledPixmapButton: case AdjustedPixmapButton: if (w_g->width - 2*border <= 0 || w_g->height - 2*border <= 0) { break; } p = df->u.p; if (type == TiledPixmapButton) { bg.pixmap.flags.is_tiled = 1; } else { bg.pixmap.stretch_w = width = w_g->width - 2*dest_g.x; bg.pixmap.stretch_h = height = w_g->height - 2*dest_g.y; bg.pixmap.flags.is_stretched = 1; } bg.flags.use_pixmap = 1; bg.pixmap.p = p->picture; bg.pixmap.shape = p->mask; bg.pixmap.alpha = p->alpha; bg.pixmap.depth = p->depth; bg.pixmap.g.width = p->width; bg.pixmap.g.height = p->height; border_fill_pixmap_background(dest_pix, &dest_g, &bg, cd); break; case MultiPixmap: /* for UseTitleStyle only */ { int is_left = left1right0; int part = TBMP_NONE; int ap, cs; unsigned int stretch; Pixmap tmp = None; FvwmPicture *full_pic = NULL; rectangle g; dynamic_common_decorations *dcd = &(cd->dynamic_cd); FvwmPicture **pm; FvwmAcs *acs; Pixel *pixels; unsigned short sf; pm = df->u.mp.pixmaps; acs = df->u.mp.acs; pixels = df->u.mp.pixels; sf = df->u.mp.solid_flags; if (!border_mp_get_use_title_style_parts_and_geometry( td, pm, acs, sf, is_left, &g, &part)) { g.width = 0; g.height = 0; g.x = 0; g.y = 0; } if (part == TBMP_NONE) { break; } if (sf & (1 << part)) { bg.flags.use_pixmap = 0; bg.pixel = pixels[part]; border_fill_pixmap_background( dest_pix, &dest_g, &bg, cd); break; } cs = acs[part].cs; ap = acs[part].alpha_percent; if (CSET_IS_TRANSPARENT_PR(cs)) { break; } if (cs >= 0) { bg.pixmap.fra.mask = FRAM_HAVE_ADDED_ALPHA; bg.pixmap.fra.added_alpha_percent = ap; } stretch = !!(df->u.mp.stretch_flags & (1 << part)); bg.flags.use_pixmap = 1; dest_g.x = 0; dest_g.y = 0; if (cs >= 0 && use_title_style && g.width > 0 && g.height > 0 && !CSET_IS_TRANSPARENT_ROOT(cs) && (bg.pixmap.p = border_get_bar_pixmaps( dcd, &g, bs, cs, NULL, part, stretch, NULL)) != None) { bg.pixmap.g.width = g.width; bg.pixmap.g.height = g.height; bg.pixmap.flags.is_tiled = 1; bg.pixmap.g.x = w_g->x - g.x; bg.pixmap.g.y = w_g->y - g.y; bg.pixmap.shape = None; bg.pixmap.alpha = None; bg.pixmap.depth = Pdepth; } else if (CSET_IS_TRANSPARENT_ROOT(cs)) { tmp = border_create_root_transparent_pixmap( td, w, w_g->width, w_g->height, cs); bg.pixmap.p = tmp; bg.pixmap.g.width = w_g->width; bg.pixmap.g.height = w_g->height; bg.pixmap.shape = None; bg.pixmap.alpha = None; bg.pixmap.depth = Pdepth; } else if (cs >= 0) { int bg_w, bg_h; tmp = CreateBackgroundPixmap( dpy, w, w_g->width, w_g->height, &Colorset[cs], Pdepth, Scr.BordersGC, False); bg.pixmap.p = tmp; GetWindowBackgroundPixmapSize( &Colorset[cs], w_g->width, w_g->height, &bg_w, &bg_h); bg.pixmap.g.width = bg_w; bg.pixmap.g.height = bg_h; bg.pixmap.shape = None; bg.pixmap.alpha = None; bg.pixmap.depth = Pdepth; bg.pixmap.flags.is_tiled = 1; } else if (pm[part] && g.width > 0 && g.height > 0 && border_get_bar_pixmaps( dcd, &g, bs, -1, pm[part], part, stretch, &full_pic) != None && full_pic) { bg.pixmap.p = full_pic->picture; bg.pixmap.shape = full_pic->mask; bg.pixmap.alpha = full_pic->alpha; bg.pixmap.depth = full_pic->depth; bg.pixmap.g.width = full_pic->width; bg.pixmap.g.height = full_pic->height; bg.pixmap.g.x = w_g->x - g.x; bg.pixmap.g.y = w_g->y - g.y; } else if (pm[part]) { p = pm[part]; if (df->u.mp.stretch_flags & (1 << part)) { bg.pixmap.flags.is_stretched = 1; } else { bg.pixmap.flags.is_tiled = 1; } bg.pixmap.p = p->picture; bg.pixmap.shape = p->mask; bg.pixmap.alpha = p->alpha; bg.pixmap.depth = p->depth; bg.pixmap.g.width = p->width; bg.pixmap.g.height = p->height; bg.pixmap.stretch_w = dest_g.width - dest_g.x; bg.pixmap.stretch_h = dest_g.height - dest_g.y; } else { /* should not happen */ return; } if (bg.pixmap.p != None) { border_fill_pixmap_background( dest_pix, &dest_g, &bg, cd); } if (tmp != None) { XFreePixmap(dpy, tmp); } break; } case ColorsetButton: { colorset_t *cs_t = &Colorset[df->u.acs.cs]; int cs = df->u.acs.cs; Pixmap tmp = None; int bg_w, bg_h; if (CSET_IS_TRANSPARENT_PR(cs)) { break; } dest_g.x = 0; dest_g.y = 0; if (use_title_style && !CSET_IS_TRANSPARENT_ROOT(cs) && (bg.pixmap.p = border_get_bar_pixmaps( &(cd->dynamic_cd), &(td->bar_g), bs, cs, NULL, TBMP_NONE, 0, NULL)) != None) { bg.pixmap.g.width = td->bar_g.width; bg.pixmap.g.height = td->bar_g.height; bg.pixmap.g.x = w_g->x - td->bar_g.x; bg.pixmap.g.y = w_g->y - td->bar_g.y; } else if (CSET_IS_TRANSPARENT_ROOT(cs)) { tmp = border_create_root_transparent_pixmap( td, w, w_g->width, w_g->height, cs); if (tmp == None) { break; } bg.pixmap.p = tmp; bg.pixmap.g.width = w_g->width; bg.pixmap.g.height = w_g->height; bg.pixmap.shape = None; bg.pixmap.alpha = None; bg.pixmap.depth = Pdepth; } else { tmp = CreateBackgroundPixmap( dpy, w, w_g->width, w_g->height, cs_t, Pdepth, Scr.BordersGC, False); if (tmp == None) { break; } bg.pixmap.p = tmp; GetWindowBackgroundPixmapSize( cs_t, w_g->width, w_g->height, &bg_w, &bg_h); bg.pixmap.g.width = bg_w; bg.pixmap.g.height = bg_h; bg.pixmap.g.x = 0; bg.pixmap.g.y = 0; } bg.flags.use_pixmap = 1; bg.pixmap.shape = None; bg.pixmap.alpha = None; bg.pixmap.depth = Pdepth; bg.pixmap.flags.is_tiled = 1; bg.pixmap.fra.mask = FRAM_HAVE_ADDED_ALPHA; bg.pixmap.fra.added_alpha_percent = df->u.acs.alpha_percent; border_fill_pixmap_background(dest_pix, &dest_g, &bg, cd); if (tmp) { XFreePixmap(dpy, tmp); } break; } case GradientButton: /* draw the gradient into the pixmap */ CreateGradientPixmap( dpy, dest_pix, Scr.TransMaskGC, df->u.grad.gradient_type, 0, 0, df->u.grad.npixels, df->u.grad.xcs, df->u.grad.do_dither, &df->u.grad.d_pixels, &df->u.grad.d_npixels, dest_pix, 0, 0, w_g->width, w_g->height, NULL); break; default: fvwm_msg(ERR, "DrawButton", "unknown button type: %i", type); break; } return; } static void border_set_button_pixmap( FvwmWindow *fw, titlebar_descr *td, int button, Pixmap *dest_pix, Window w) { pixmap_background_type bg; unsigned int mask; int is_left_button; int do_reverse_relief; ButtonState bs; DecorFace *df; rectangle *button_g; GC rgc; GC sgc; Bool free_bg_pixmap = False; rectangle pix_g; /* prepare variables */ mask = (1 << button); if (td->has_an_upsidedown_rotation) { is_left_button = (button & 1); } else { is_left_button = !(button & 1); } button_g = &td->layout.button_g[button]; bs = td->tbstate.bstate[button]; df = &TB_STATE(GetDecor(fw, buttons[button]))[bs]; rgc = td->cd->relief_gc; sgc = td->cd->shadow_gc; /* prepare background, either from the window colour or from the * border style */ if (!DFS_USE_BORDER_STYLE(df->style)) { /* fill with the button background colour */ bg.flags.use_pixmap = 0; bg.pixel = td->cd->back_color; pix_g.x = 0; pix_g.y = 0; pix_g.width = button_g->width; pix_g.height = button_g->height; border_fill_pixmap_background(*dest_pix, &pix_g, &bg, td->cd); } else { /* draw pixmap background inherited from border style */ rectangle relative_g; relative_g.width = td->frame_g.width; relative_g.height = td->frame_g.height; relative_g.x = button_g->x; relative_g.y = button_g->y; border_get_border_background( &bg, td->cd, button_g, &relative_g, &free_bg_pixmap, w); bg.pixmap.g.x = 0; bg.pixmap.g.y = 0; /* set the geometry for drawing the Tiled pixmap; * FIXME: maybe add the relief as offset? */ pix_g.x = 0; pix_g.y = 0; pix_g.width = button_g->width; pix_g.height = button_g->height; border_fill_pixmap_background(*dest_pix, &pix_g, &bg, td->cd); if (free_bg_pixmap && bg.pixmap.p) { XFreePixmap(dpy, bg.pixmap.p); } } /* handle title style */ if (DFS_USE_TITLE_STYLE(df->style)) { /* draw background inherited from title style */ DecorFace *tsdf; Pixmap tmp; if (td->draw_rotation != ROTATION_0) { tmp = CreateRotatedPixmap( dpy, *dest_pix, td->layout.button_g[button].width, td->layout.button_g[button].height, Pdepth, Scr.BordersGC, td->restore_rotation); XFreePixmap(dpy, *dest_pix); *dest_pix = tmp; border_rotate_titlebar_descr(fw, td); button_g = &td->layout.button_g[button]; is_left_button = !(button & 1); } for (tsdf = &TB_STATE(GetDecor(fw, titlebar))[bs]; tsdf != NULL; tsdf = tsdf->next) { bg.pixel = tsdf->u.back; border_draw_decor_to_pixmap( fw, *dest_pix, w, &bg, button_g, tsdf, td, bs, True, (td->tbstate.toggled_bmask & mask), is_left_button); } if (td->draw_rotation != ROTATION_0) { tmp = CreateRotatedPixmap( dpy, *dest_pix, td->layout.button_g[button].width, td->layout.button_g[button].height, Pdepth, Scr.BordersGC, td->draw_rotation); XFreePixmap(dpy, *dest_pix); *dest_pix = tmp; border_rotate_titlebar_descr(fw, td); button_g = &td->layout.button_g[button]; if (td->has_an_upsidedown_rotation) { is_left_button = (button & 1); } else { is_left_button = !(button & 1); } } } /* handle button style */ for ( ; df; df = df->next) { /* draw background from button style */ bg.pixel = df->u.back; border_draw_decor_to_pixmap( fw, *dest_pix, w, &bg, button_g, df, td, bs, False, (td->tbstate.toggled_bmask & mask), is_left_button); } /* draw the button relief */ do_reverse_relief = !!(td->tbstate.pressed_bmask & mask); switch (DFS_BUTTON_RELIEF( TB_STATE(GetDecor(fw, buttons[button]))[bs].style)) { case DFS_BUTTON_IS_SUNK: do_reverse_relief ^= 1; /* fall through*/ case DFS_BUTTON_IS_UP: do_relieve_rectangle( dpy, *dest_pix, 0, 0, button_g->width - 1, button_g->height - 1, (do_reverse_relief) ? sgc : rgc, (do_reverse_relief) ? rgc : sgc, td->cd->relief_width, True); break; default: /* flat */ break; } return; } static void border_draw_one_button( FvwmWindow *fw, titlebar_descr *td, int button) { Pixmap p; /* make a pixmap */ if (td->layout.button_g[button].x < 0 || td->layout.button_g[button].y < 0) { return; } p = border_create_decor_pixmap(td->cd, &(td->layout.button_g[button])); /* set the background tile */ border_set_button_pixmap(fw, td, button, &p, FW_W_BUTTON(fw, button)); /* apply the pixmap and destroy it */ border_set_part_background(FW_W_BUTTON(fw, button), p); XFreePixmap(dpy, p); if ((td->tbstate.clear_bmask & (1 << button)) != 0) { XClearWindow(dpy, FW_W_BUTTON(fw, button)); } return; } static void border_draw_title_stick_lines( FvwmWindow *fw, titlebar_descr *td, title_draw_descr *tdd, Pixmap dest_pix) { int i; int num; int min; int max; int left_x; int left_w; int right_x; int right_w; int under_text_length = 0; int under_text_offset = 0; int right_length = 0; int left_length = 0; rotation_t rotation; if (!( (HAS_STICKY_STIPPLED_TITLE(fw) && (IS_STICKY_ACROSS_PAGES(fw) || IS_STICKY_ACROSS_DESKS(fw))) || HAS_STIPPLED_TITLE(fw))) { return; } if (td->td_is_rotated) { rotation = td->restore_rotation; } else { rotation = ROTATION_0; } if (td->has_vt && td->under_text_g.height > 0) { under_text_length = td->under_text_g.height; under_text_offset = td->under_text_g.y; left_length = td->left_main_g.height - td->left_of_text_length - td->left_end_length; right_length = td->right_main_g.height - td->right_of_text_length - td->right_end_length; } else if (!td->has_vt && td->under_text_g.width > 0) { under_text_length = td->under_text_g.width; under_text_offset = td->under_text_g.x; left_length = td->left_main_g.width - td->left_of_text_length - td->left_end_length; right_length = td->right_main_g.width - td->right_of_text_length - td->right_end_length; } /* If the window is sticky either across pages or * desks and it has a stippled title, but nothing for * sticky_stippled_title, then don't bother drawing them, just * return immediately. -- Thomas Adam */ if ( (IS_STICKY_ACROSS_PAGES(fw) || IS_STICKY_ACROSS_DESKS(fw)) && (!HAS_STICKY_STIPPLED_TITLE(fw) && HAS_STIPPLED_TITLE(fw)) ) { return; } num = (int)(fw->title_thickness / WINDOW_TITLE_STICK_VERT_DIST / 2) * 2 - 1; min = fw->title_thickness / 2 - num * 2 + 1; max = fw->title_thickness / 2 + num * 2 - WINDOW_TITLE_STICK_VERT_DIST + 1; left_x = WINDOW_TITLE_STICK_OFFSET + td->left_end_length; left_w = ((under_text_length == 0)? td->offset:under_text_offset) - left_x - WINDOW_TITLE_TO_STICK_GAP - td->left_of_text_length; right_x = ((under_text_length == 0)? td->offset + td->length : under_text_offset + under_text_length) + td->right_of_text_length + WINDOW_TITLE_TO_STICK_GAP - 1; right_w = fw->title_length - right_x - WINDOW_TITLE_STICK_OFFSET - td->right_end_length; /* an odd number of lines every WINDOW_TITLE_STICK_VERT_DIST pixels */ if (left_w < WINDOW_TITLE_STICK_MIN_WIDTH) { left_x = td->left_end_length + ((left_length > WINDOW_TITLE_STICK_MIN_WIDTH)? (left_length - WINDOW_TITLE_STICK_MIN_WIDTH)/2 : 0); left_w = WINDOW_TITLE_STICK_MIN_WIDTH; } if (right_w < WINDOW_TITLE_STICK_MIN_WIDTH) { right_w = WINDOW_TITLE_STICK_MIN_WIDTH; right_x = fw->title_length - WINDOW_TITLE_STICK_MIN_WIDTH - 1 - td->right_end_length - ((right_length > WINDOW_TITLE_STICK_MIN_WIDTH)? (right_length - WINDOW_TITLE_STICK_MIN_WIDTH)/2 : 0); } for (i = min; i <= max; i += WINDOW_TITLE_STICK_VERT_DIST) { if (left_w > 0) { do_relieve_rectangle_with_rotation( dpy, dest_pix, SWAP_ARGS(td->has_vt, left_x, i), SWAP_ARGS(td->has_vt, left_w, 1), tdd->sgc, tdd->rgc, 1, False, rotation); } if (right_w > 0) { do_relieve_rectangle_with_rotation( dpy, dest_pix, SWAP_ARGS(td->has_vt, right_x, i), SWAP_ARGS(td->has_vt, right_w, 1), tdd->sgc, tdd->rgc, 1, False, rotation); } } return; } static void border_draw_title_mono( FvwmWindow *fw, titlebar_descr *td, title_draw_descr *tdd, FlocaleWinString *fstr, Pixmap dest_pix) { int has_vt; has_vt = HAS_VERTICAL_TITLE(fw); XFillRectangle( dpy, dest_pix, td->cd->relief_gc, td->offset - 2, 0, td->length+4, fw->title_thickness); if (fw->visible_name != (char *)NULL) { FlocaleDrawString(dpy, fw->title_font, fstr, 0); } /* for mono, we clear an area in the title bar where the window * title goes, so that its more legible. For color, no need */ do_relieve_rectangle( dpy, dest_pix, 0, 0, SWAP_ARGS(has_vt, td->offset - 3, fw->title_thickness - 1), tdd->rgc, tdd->sgc, td->cd->relief_width, False); do_relieve_rectangle( dpy, dest_pix, SWAP_ARGS(has_vt, td->offset + td->length + 2, 0), SWAP_ARGS(has_vt, fw->title_length - td->length - td->offset - 3, fw->title_thickness - 1), tdd->rgc, tdd->sgc, td->cd->relief_width, False); XDrawLine( dpy, dest_pix, tdd->sgc, SWAP_ARGS(has_vt, 0, td->offset + td->length + 1), SWAP_ARGS(has_vt, td->offset + td->length + 1, fw->title_thickness)); return; } static void border_draw_title_relief( FvwmWindow *fw, titlebar_descr *td, title_draw_descr *tdd, Pixmap dest_pix) { int reverse = 0; rotation_t rotation; if (td->td_is_rotated) { rotation = td->restore_rotation; } else { rotation = ROTATION_0; } /* draw title relief */ switch (DFS_BUTTON_RELIEF(*tdd->tstyle)) { case DFS_BUTTON_IS_SUNK: reverse = 1; case DFS_BUTTON_IS_UP: do_relieve_rectangle_with_rotation( dpy, dest_pix, 0, 0, SWAP_ARGS( td->has_vt, fw->title_length - 1, fw->title_thickness - 1), (reverse) ? tdd->sgc : tdd->rgc, (reverse) ? tdd->rgc : tdd->sgc, td->cd->relief_width, True, rotation); break; default: /* flat */ break; } return; } static void border_draw_title_deep( FvwmWindow *fw, titlebar_descr *td, title_draw_descr *tdd, FlocaleWinString *fstr, Pixmap dest_pix, Window w) { DecorFace *df; pixmap_background_type bg; bg.flags.use_pixmap = 0; for (df = tdd->df; df != NULL; df = df->next) { if (df->style.face_type == MultiPixmap) { border_mp_draw_mp_titlebar( fw, td, df, dest_pix, w); } else { bg.pixel = df->u.back; border_draw_decor_to_pixmap( fw, dest_pix, w, &bg, &td->layout.title_g, df, td, td->tbstate.tstate, True, tdd->is_toggled, 1); } } FlocaleDrawString(dpy, fw->title_font, &tdd->fstr, 0); return; } static void border_get_titlebar_draw_descr( FvwmWindow *fw, titlebar_descr *td, title_draw_descr *tdd, Pixmap dest_pix) { memset(tdd, 0, sizeof(*tdd)); /* prepare the gcs and variables */ if (td->tbstate.is_title_pressed) { tdd->rgc = td->cd->shadow_gc; tdd->sgc = td->cd->relief_gc; } else { tdd->rgc = td->cd->relief_gc; tdd->sgc = td->cd->shadow_gc; } NewFontAndColor(fw->title_font, td->cd->fore_color, td->cd->back_color); tdd->tstyle = &TB_STATE( GetDecor(fw, titlebar))[td->tbstate.tstate].style; tdd->df = &TB_STATE(GetDecor(fw, titlebar))[td->tbstate.tstate]; /* fetch the title string */ tdd->fstr.str = fw->visible_name; tdd->fstr.win = dest_pix; if (td->td_is_rotated) { tdd->fstr.flags.text_rotation = ROTATION_0; } else { tdd->fstr.flags.text_rotation = fw->title_text_rotation; } if (td->has_vt) { tdd->fstr.y = td->offset; tdd->fstr.x = fw->title_text_offset + 1; } else { tdd->fstr.x = td->offset; tdd->fstr.y = fw->title_text_offset + 1; } if (td->cd->cs >= 0) { tdd->fstr.colorset = &Colorset[td->cd->cs]; tdd->fstr.flags.has_colorset = 1; } tdd->fstr.gc = Scr.TitleGC; return; } static void border_set_title_pixmap( FvwmWindow *fw, titlebar_descr *td, Pixmap *dest_pix, Window w) { pixmap_background_type bg; title_draw_descr tdd; FlocaleWinString fstr; Bool free_bg_pixmap = False; rectangle pix_g; border_get_titlebar_draw_descr(fw, td, &tdd, *dest_pix); /* prepare background, either from the window colour or from the * border style */ if (!DFS_USE_BORDER_STYLE(*tdd.tstyle)) { /* fill with the button background colour */ bg.flags.use_pixmap = 0; bg.pixel = td->cd->back_color; pix_g.x = 0; pix_g.y = 0; pix_g.width = td->layout.title_g.width; pix_g.height = td->layout.title_g.height; border_fill_pixmap_background( *dest_pix, &pix_g, &bg, td->cd); } else { /* draw pixmap background inherited from border style */ rectangle relative_g; Pixmap tmp; if (td->draw_rotation != ROTATION_0) { tmp = CreateRotatedPixmap( dpy, *dest_pix, td->layout.title_g.width, td->layout.title_g.height, Pdepth, Scr.BordersGC, td->restore_rotation); XFreePixmap(dpy, *dest_pix); *dest_pix = tmp; border_rotate_titlebar_descr(fw, td); } relative_g.width = td->frame_g.width; relative_g.height = td->frame_g.height; relative_g.x = td->layout.title_g.x; relative_g.y = td->layout.title_g.y; border_get_border_background( &bg, td->cd, &td->layout.title_g, &relative_g, &free_bg_pixmap, w); bg.pixmap.g.x = 0; bg.pixmap.g.y = 0; /* set the geometry for drawing the Tiled pixmap; * FIXME: maybe add the relief as offset? */ pix_g.x = 0; pix_g.y = 0; pix_g.width = td->layout.title_g.width; pix_g.height = td->layout.title_g.height; border_fill_pixmap_background( *dest_pix, &pix_g, &bg, td->cd); if (free_bg_pixmap && bg.pixmap.p) { XFreePixmap(dpy, bg.pixmap.p); } if (td->draw_rotation != ROTATION_0) { tmp = CreateRotatedPixmap( dpy, *dest_pix, td->layout.title_g.width, td->layout.title_g.height, Pdepth, Scr.BordersGC, td->draw_rotation); XFreePixmap(dpy, *dest_pix); *dest_pix = tmp; border_rotate_titlebar_descr(fw, td); } } if (Pdepth < 2) { border_draw_title_mono(fw, td, &tdd, &fstr, *dest_pix); } else { border_draw_title_deep(fw, td, &tdd, &fstr, *dest_pix, w); } border_draw_title_relief(fw, td, &tdd, *dest_pix); border_draw_title_stick_lines(fw, td, &tdd, *dest_pix); return; } static void border_draw_title( FvwmWindow *fw, titlebar_descr *td) { Pixmap p; if (td->layout.title_g.x < 0 || td->layout.title_g.y < 0) { return; } if (td->draw_rotation != ROTATION_0) { border_rotate_titlebar_descr(fw, td); } /* make a pixmap */ p = border_create_decor_pixmap(td->cd, &(td->layout.title_g)); /* set the background tile */ #if 0 fprintf(stderr,"drawing title\n"); #endif border_set_title_pixmap(fw, td, &p, FW_W_TITLE(fw)); if (td->draw_rotation != ROTATION_0) { Pixmap tmp; tmp = CreateRotatedPixmap( dpy, p, td->layout.title_g.width, td->layout.title_g.height, Pdepth, Scr.BordersGC, td->draw_rotation); XFreePixmap(dpy, p); p = tmp; border_rotate_titlebar_descr(fw, td); } /* apply the pixmap and destroy it */ border_set_part_background(FW_W_TITLE(fw), p); XFreePixmap(dpy, p); if (td->tbstate.do_clear_title) { XClearWindow(dpy, FW_W_TITLE(fw)); } return; } static void border_draw_buttons( FvwmWindow *fw, titlebar_descr *td) { int i; /* draw everything in a big loop */ #if 0 fprintf(stderr, "drawing buttons 0x%04x\n", td->tbstate.draw_bmask); #endif for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; i++) { unsigned int mask = (1 << i); if ((td->tbstate.draw_bmask & mask) != 0) { border_draw_one_button(fw, td, i); } } /* update the button states */ fw->decor_state.buttons_drawn |= td->tbstate.draw_bmask; fw->decor_state.buttons_inverted = td->tbstate.pressed_bmask; fw->decor_state.buttons_lit = td->tbstate.lit_bmask; fw->decor_state.buttons_toggled = td->tbstate.toggled_bmask; return; } static void border_setup_use_title_style( FvwmWindow *fw, titlebar_descr *td) { int i; DecorFace *df, *tsdf; ButtonState bs, tsbs; /* use a full bar pixmap (for Colorset) or non window size pixmaps * (for MultiPixmap) under certain condition: * - for the buttons which use title style * - for title which have a button with UseTitle style */ tsbs = td->tbstate.tstate; for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; i++) { bs = td->tbstate.bstate[i]; df = &TB_STATE(GetDecor(fw, buttons[i]))[bs]; tsdf = &TB_STATE(GetDecor(fw, buttons[i]))[tsbs]; if (FW_W_BUTTON(fw, i) != None) { if (DFS_USE_TITLE_STYLE(df->style)) { border_setup_bar_pixmaps( td, &(td->cd->dynamic_cd), &TB_STATE(GetDecor(fw, titlebar))[bs], bs); } if (DFS_USE_TITLE_STYLE(tsdf->style)) { border_setup_bar_pixmaps( td, &(td->cd->dynamic_cd), &TB_STATE(GetDecor(fw, titlebar))[tsbs], tsbs); } } } return; } static void border_rotate_titlebar_descr( FvwmWindow *fw, titlebar_descr *td) { rotation_t rotation; int i, tmpi; static titlebar_descr saved_td; if (td->draw_rotation == ROTATION_0) { return; } if (!td->has_been_saved) { td->has_been_saved = True; memcpy(&saved_td, td, sizeof(titlebar_descr)); } if (!td->td_is_rotated) { /* make the bar horizontal */ switch(td->draw_rotation) { case ROTATION_90: /* cw */ rotation = ROTATION_270; break; case ROTATION_270: /* ccw */ rotation = ROTATION_90; break; case ROTATION_180: rotation = ROTATION_180; break; default: return; } td->has_vt = 0; td->has_an_upsidedown_rotation = 0; td->td_is_rotated = 1; } else { /* restore */ memcpy(td, &saved_td, sizeof(titlebar_descr)); td->td_is_rotated = 0; return; } #define ROTATE_RECTANGLE(rot, r, vs_frame, vs_titlebar, vs_title) \ { \ rectangle tr; \ tr.x = r->x; \ tr.y = r->y; \ tr.width = r->width; \ tr.height = r->height; \ switch(rot) \ { \ case ROTATION_270: /* ccw */ \ tr.x = r->y; \ if (vs_frame) \ { \ tr.y = td->frame_g.width - (r->x+r->width); \ } \ else if (vs_titlebar) \ { \ tr.y = td->bar_g.width - \ (r->x+r->width); \ } \ else if (vs_title) \ { \ tr.y = td->layout.title_g.width - \ (r->x+r->width); \ } \ else \ { \ tr.y = r->x; \ } \ tr.width = r->height; \ tr.height = r->width; \ break; \ case ROTATION_90: /* cw */ \ if (vs_frame) \ { \ tr.x = td->frame_g.height - (r->y+r->height); \ } \ else if (vs_titlebar) \ { \ tr.x = td->bar_g.height - \ (r->y+r->height); \ } \ else if (vs_title) \ { \ tr.x = td->layout.title_g.height - \ (r->y+r->height); \ } \ else \ { \ tr.x = r->y; \ } \ tr.y = r->x; \ tr.width = r->height; \ tr.height = r->width; \ break; \ case ROTATION_180: \ if (vs_frame) \ { \ tr.x = td->frame_g.width - (r->x+r->width); \ } \ else if (vs_titlebar) \ { \ tr.x = td->bar_g.width - \ (r->x + r->width); \ } \ else if (vs_title) \ { \ tr.x = td->layout.title_g.width - \ (r->x + r->width); \ } \ else \ { \ tr.x = r->x; \ } \ break; \ case ROTATION_0: \ break; \ } \ r->x = tr.x; \ r->y = tr.y; \ r->width = tr.width; \ r->height = tr.height; \ } switch(rotation) { case ROTATION_90: td->offset = td->layout.title_g.height - td->offset - td->length; tmpi = td->left_end_length; td->left_end_length = td->right_end_length; td->right_end_length = tmpi; tmpi = td->left_of_text_length; td->left_of_text_length = td->right_of_text_length; td->right_of_text_length = tmpi; break; case ROTATION_270: break; case ROTATION_180: td->offset = td->layout.title_g.width - td->offset - td->length; tmpi = td->left_end_length; td->left_end_length = td->right_end_length; td->right_end_length = tmpi; tmpi = td->left_of_text_length; td->left_of_text_length = td->right_of_text_length; td->right_of_text_length = tmpi; break; case ROTATION_0: break; } ROTATE_RECTANGLE(rotation, (&td->left_buttons_g), True, False, False) ROTATE_RECTANGLE(rotation, (&td->right_buttons_g), True, False, False) for (i=0; i < NUMBER_OF_TITLE_BUTTONS; i++) { ROTATE_RECTANGLE( rotation, (&td->layout.button_g[i]), True, False, False) } ROTATE_RECTANGLE(rotation, (&td->under_text_g), False, False, True) ROTATE_RECTANGLE(rotation, (&td->left_main_g), False, False, True) ROTATE_RECTANGLE(rotation, (&td->right_main_g), False, False, True) ROTATE_RECTANGLE(rotation, (&td->full_left_main_g), True, False, False) ROTATE_RECTANGLE(rotation, (&td->full_right_main_g), True, False, False) ROTATE_RECTANGLE(rotation, (&td->layout.title_g), True, False, False) ROTATE_RECTANGLE(rotation, (&td->bar_g), True, False, False) ROTATE_RECTANGLE(rotation, (&td->frame_g), False, False, False); #undef ROTATE_RECTANGLE } static void border_get_titlebar_descr_state( FvwmWindow *fw, window_parts pressed_parts, int pressed_button, clear_window_parts clear_parts, Bool do_hilight, border_titlebar_state *tbstate) { int i; if ((pressed_parts & PART_BUTTONS) != PART_NONE && pressed_button >= 0) { tbstate->pressed_bmask = (1 << pressed_button); } else { tbstate->pressed_bmask = 0; } if ((clear_parts & CLEAR_BUTTONS) != CLEAR_NONE) { tbstate->clear_bmask = 0x3FF; } else { tbstate->clear_bmask = 0; } tbstate->lit_bmask = (do_hilight == True) ? ~0 : 0; if ((pressed_parts & PART_TITLE) != PART_NONE) { tbstate->is_title_pressed = 1; } else { tbstate->is_title_pressed = 0; } if ((clear_parts & CLEAR_TITLE) != CLEAR_NONE) { tbstate->do_clear_title = 1; } else { tbstate->do_clear_title = 0; } tbstate->is_title_lit = (do_hilight == True) ? 1 : 0; tbstate->toggled_bmask = 0; for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; i++) { unsigned int mask = (1 << i); if (is_button_toggled(fw, i)) { tbstate->toggled_bmask |= mask; } tbstate->bstate[i] = border_flags_to_button_state( tbstate->pressed_bmask & mask, tbstate->lit_bmask & mask, tbstate->toggled_bmask & mask); } tbstate->tstate = border_flags_to_button_state( tbstate->is_title_pressed, tbstate->is_title_lit, 0); } static window_parts border_get_titlebar_descr( common_decorations_type *cd, FvwmWindow *fw, window_parts pressed_parts, int pressed_button, window_parts force_draw_parts, clear_window_parts clear_parts, rectangle *old_g, rectangle *new_g, Bool do_hilight, titlebar_descr *ret_td) { window_parts draw_parts; int i; DecorFace *df; int is_start = 0; JustificationType just; int lbl = 0; int rbl = 0; ret_td->cd = cd; ret_td->frame_g = *new_g; if (old_g == NULL) { old_g = &fw->g.frame; } frame_get_titlebar_dimensions(fw, old_g, NULL, &ret_td->old_layout); frame_get_titlebar_dimensions(fw, new_g, NULL, &ret_td->layout); ret_td->has_vt = HAS_VERTICAL_TITLE(fw); if (USE_TITLE_DECOR_ROTATION(fw)) { ret_td->draw_rotation = fw->title_text_rotation; switch(ret_td->draw_rotation) { case ROTATION_90: ret_td->restore_rotation = ROTATION_270; break; case ROTATION_270: /* ccw */ ret_td->restore_rotation = ROTATION_90; break; case ROTATION_180: ret_td->restore_rotation = ROTATION_180; break; default: break; } } if (fw->title_text_rotation == ROTATION_270 || fw->title_text_rotation == ROTATION_180) { ret_td->has_an_upsidedown_rotation = True; } /* geometry of the title bar title + buttons */ if (!ret_td->has_vt) { ret_td->bar_g.width = new_g->width - 2 * fw->boundary_width; ret_td->bar_g.height = ret_td->layout.title_g.height; ret_td->bar_g.x = fw->boundary_width; ret_td->bar_g.y = ret_td->layout.title_g.y; } else { ret_td->bar_g.width = ret_td->layout.title_g.width; ret_td->bar_g.height = new_g->height - 2 * fw->boundary_width; ret_td->bar_g.y = fw->boundary_width; ret_td->bar_g.x = ret_td->layout.title_g.x; } /* buttons geometries */ if (ret_td->has_vt) { ret_td->left_buttons_g.width = ret_td->bar_g.width; ret_td->right_buttons_g.width = ret_td->bar_g.width; } else { ret_td->left_buttons_g.height = ret_td->bar_g.height; ret_td->right_buttons_g.height = ret_td->bar_g.width; } for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; i++) { if (FW_W_BUTTON(fw, i) == None) { continue; } if (ret_td->has_vt) { if (i & 1) { rbl += ret_td->layout.button_g[i].height; } else { lbl += ret_td->layout.button_g[i].height; } } else { if (i & 1) { rbl += ret_td->layout.button_g[i].width; } else { lbl += ret_td->layout.button_g[i].width; } } } if (ret_td->has_an_upsidedown_rotation) { if (ret_td->has_vt) { ret_td->left_buttons_g.height = rbl; ret_td->right_buttons_g.height = lbl; ret_td->right_buttons_g.y = fw->boundary_width; ret_td->right_buttons_g.x = ret_td->bar_g.x; ret_td->left_buttons_g.y = ret_td->layout.title_g.y + ret_td->layout.title_g.height; ret_td->left_buttons_g.x = ret_td->bar_g.x; } else { ret_td->left_buttons_g.width = rbl; ret_td->right_buttons_g.width = lbl; ret_td->right_buttons_g.x = fw->boundary_width; ret_td->right_buttons_g.y = ret_td->bar_g.y; ret_td->left_buttons_g.x = ret_td->layout.title_g.x + ret_td->layout.title_g.width; ret_td->left_buttons_g.y = ret_td->bar_g.y; } } else { if (ret_td->has_vt) { ret_td->left_buttons_g.height = lbl; ret_td->right_buttons_g.height = rbl; ret_td->left_buttons_g.y = fw->boundary_width; ret_td->left_buttons_g.x = ret_td->bar_g.x; ret_td->right_buttons_g.y = ret_td->layout.title_g.y + ret_td->layout.title_g.height; ret_td->right_buttons_g.x = ret_td->bar_g.x; } else { ret_td->left_buttons_g.width = lbl; ret_td->right_buttons_g.width = rbl; ret_td->left_buttons_g.x = fw->boundary_width; ret_td->left_buttons_g.y = ret_td->bar_g.y; ret_td->right_buttons_g.x = ret_td->layout.title_g.x + ret_td->layout.title_g.width; ret_td->right_buttons_g.y = ret_td->bar_g.y; } } /* initialise flags */ border_get_titlebar_descr_state( fw, pressed_parts, pressed_button, clear_parts, do_hilight, &(ret_td->tbstate)); /* get the title string length and position * This is not in "tdd" (titlebar_draw_descr), because these are needed * to draw the buttons with UseTitleStyle */ just = TB_JUSTIFICATION(GetDecor(fw, titlebar)); if (fw->visible_name != (char *)NULL) { ret_td->length = FlocaleTextWidth( fw->title_font, fw->visible_name, (ret_td->has_vt) ? -strlen(fw->visible_name) : strlen(fw->visible_name)); if (ret_td->length > fw->title_length - 2*MIN_WINDOW_TITLE_TEXT_OFFSET) { ret_td->length = fw->title_length - 2*MIN_WINDOW_TITLE_TEXT_OFFSET; just = JUST_CENTER; } if (ret_td->length < 0) { ret_td->length = 0; } } else { ret_td->length = 0; } if (ret_td->length == 0) { just = JUST_CENTER; } df = &TB_STATE(GetDecor(fw, titlebar))[ret_td->tbstate.tstate]; switch (just) { case JUST_LEFT: is_start = 1; /* fall through */ case JUST_RIGHT: if (ret_td->has_an_upsidedown_rotation) { is_start = !is_start; } if (is_start) { if (WINDOW_TITLE_TEXT_OFFSET + ret_td->length <= fw->title_length) { ret_td->offset = WINDOW_TITLE_TEXT_OFFSET; } else { ret_td->offset = fw->title_length - ret_td->length; } } else { ret_td->offset = fw->title_length - ret_td->length - WINDOW_TITLE_TEXT_OFFSET; } break; case JUST_CENTER: default: ret_td->offset = (fw->title_length - ret_td->length) / 2; break; } if (ret_td->offset < MIN_WINDOW_TITLE_TEXT_OFFSET) { ret_td->offset = MIN_WINDOW_TITLE_TEXT_OFFSET; } /* setup MultiPixmap */ border_mp_get_titlebar_descr(fw, ret_td, df); /* determine the parts to draw */ draw_parts = border_get_tb_parts_to_draw( fw, ret_td, old_g, new_g, force_draw_parts); return draw_parts; } static void border_draw_titlebar( common_decorations_type *cd, FvwmWindow *fw, window_parts pressed_parts, int pressed_button, window_parts force_draw_parts, clear_window_parts clear_parts, rectangle *old_g, rectangle *new_g, Bool do_hilight) { window_parts draw_parts; titlebar_descr td; if (!HAS_TITLE(fw)) { /* just reset border states */ fw->decor_state.parts_drawn &= ~(PART_TITLE); fw->decor_state.parts_lit &= ~(PART_TITLE); fw->decor_state.parts_inverted &= ~(PART_TITLE); fw->decor_state.buttons_drawn = 0; fw->decor_state.buttons_lit = 0; fw->decor_state.buttons_inverted = 0; fw->decor_state.buttons_toggled = 0; return; } memset(&td, 0, sizeof(td)); draw_parts = border_get_titlebar_descr( cd, fw, pressed_parts, pressed_button, force_draw_parts, clear_parts, old_g, new_g, do_hilight, &td); if ((draw_parts & PART_TITLE) != PART_NONE || (draw_parts & PART_BUTTONS) != PART_NONE) { /* set up UseTitleStyle Colorset */ border_setup_use_title_style(fw, &td); } if ((draw_parts & PART_TITLE) != PART_NONE) { border_draw_title(fw, &td); } if ((draw_parts & PART_BUTTONS) != PART_NONE) { border_draw_buttons(fw, &td); } border_free_bar_pixmaps(&(td.cd->dynamic_cd)); /* update the decor states */ fw->decor_state.parts_drawn |= draw_parts; if (do_hilight) { fw->decor_state.parts_lit |= draw_parts; } else { fw->decor_state.parts_lit &= ~draw_parts; } fw->decor_state.parts_inverted &= ~draw_parts; fw->decor_state.parts_inverted |= (draw_parts & pressed_parts); if (draw_parts & PART_BUTTONS) { fw->decor_state.buttons_drawn |= td.tbstate.draw_bmask; fw->decor_state.parts_lit = (do_hilight) ? ~0 : 0; if (td.tbstate.pressed_bmask) { fw->decor_state.buttons_inverted = td.tbstate.pressed_bmask; } else { fw->decor_state.buttons_inverted &= ~td.tbstate.draw_bmask; } fw->decor_state.buttons_toggled = (fw->decor_state.buttons_toggled & ~td.tbstate.max_bmask) | td.tbstate.toggled_bmask; } return; } /* * * Redraws the windows borders * */ static void border_draw_border_parts( common_decorations_type *cd, FvwmWindow *fw, window_parts pressed_parts, window_parts force_draw_parts, clear_window_parts clear_parts, rectangle *old_g, rectangle *new_g, Bool do_hilight) { border_relief_descr br; window_parts draw_parts; Bool do_clear; if (HAS_NO_BORDER(fw)) { /* just reset border states */ fw->decor_state.parts_drawn &= ~(PART_FRAME | PART_HANDLES); fw->decor_state.parts_lit &= ~(PART_FRAME | PART_HANDLES); fw->decor_state.parts_inverted &= ~(PART_FRAME | PART_HANDLES); return; } do_clear = (clear_parts & CLEAR_FRAME) ? True : False; /* determine the parts to draw and the position to place them */ if (HAS_DEPRESSABLE_BORDER(fw)) { pressed_parts &= PART_FRAME; } else { pressed_parts = PART_NONE; } force_draw_parts &= PART_FRAME; memset(&br, 0, sizeof(br)); draw_parts = border_get_parts_and_pos_to_draw( cd, fw, pressed_parts, force_draw_parts, old_g, new_g, do_hilight, &br); if ((draw_parts & PART_FRAME) != PART_NONE) { border_draw_all_border_parts( cd, fw, &br, new_g, draw_parts, pressed_parts, do_hilight, do_clear); } /* update the decor states */ fw->decor_state.parts_drawn |= draw_parts; if (do_hilight) { fw->decor_state.parts_lit |= draw_parts; } else { fw->decor_state.parts_lit &= ~draw_parts; } fw->decor_state.parts_inverted &= ~draw_parts; fw->decor_state.parts_inverted |= (draw_parts & pressed_parts); return; } /* ---------------------------- interface functions ------------------------ */ DecorFace *border_get_border_style( FvwmWindow *fw, Bool has_focus) { DecorFace *df; if (has_focus == True) { df = &(GetDecor(fw, BorderStyle.active)); } else { df = &(GetDecor(fw, BorderStyle.inactive)); } return df; } int border_is_using_border_style( FvwmWindow *fw, Bool has_focus) { ButtonState bs; int is_pressed; int is_toggled; int i; /* title */ is_pressed = (FW_W_TITLE(fw) == PressedW); bs = border_flags_to_button_state(is_pressed, has_focus, 0); if (DFS_USE_BORDER_STYLE(TB_STATE(GetDecor(fw, titlebar))[bs].style)) { return 1; } for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; i++) { if (FW_W_BUTTON(fw, i) == None) { continue; } is_pressed = (FW_W_BUTTON(fw, i) == PressedW); is_toggled = (is_button_toggled(fw, i) == True); bs = border_flags_to_button_state( is_pressed, (has_focus == True), is_toggled); if (DFS_USE_BORDER_STYLE( TB_STATE(GetDecor(fw, buttons[i]))[bs].style)) { return 1; } } return 0; } int border_context_to_parts( int context) { if (context == C_FRAME || context == C_SIDEBAR || context == (C_FRAME | C_SIDEBAR)) { return PART_FRAME; } else if (context == C_F_TOPLEFT) { return PART_BORDER_NW; } else if (context == C_F_TOPRIGHT) { return PART_BORDER_NE; } else if (context == C_F_BOTTOMLEFT) { return PART_BORDER_SW; } else if (context == C_F_BOTTOMRIGHT) { return PART_BORDER_SE; } else if (context == C_SB_LEFT) { return PART_BORDER_W; } else if (context == C_SB_RIGHT) { return PART_BORDER_E; } else if (context == C_SB_TOP) { return PART_BORDER_N; } else if (context == C_SB_BOTTOM) { return PART_BORDER_S; } else if (context == C_TITLE) { return PART_TITLE; } else if (context & (C_LALL | C_RALL)) { return PART_BUTTONS; } return PART_NONE; } void border_get_part_geometry( FvwmWindow *fw, window_parts part, rectangle *sidebar_g, rectangle *ret_g, Window *ret_w) { int bw; bw = fw->boundary_width; /* ret_g->x and ret->y is just an offset relatively to the w, * maybe we can take the relief in account? */ switch (part) { case PART_BORDER_N: ret_g->x = sidebar_g->x; ret_g->y = 0; *ret_w = FW_W_SIDE(fw, 0); break; case PART_BORDER_E: ret_g->x = 2 * sidebar_g->x + sidebar_g->width - bw; ret_g->y = sidebar_g->y; *ret_w = FW_W_SIDE(fw, 1); break; case PART_BORDER_S: ret_g->x = sidebar_g->x; ret_g->y = 2 * sidebar_g->y + sidebar_g->height - bw; *ret_w = FW_W_SIDE(fw, 2); break; case PART_BORDER_W: ret_g->x = 0; ret_g->y = sidebar_g->y; *ret_w = FW_W_SIDE(fw, 3); break; case PART_BORDER_NW: ret_g->x = 0; ret_g->y = 0; *ret_w = FW_W_CORNER(fw, 0); break; case PART_BORDER_NE: ret_g->x = sidebar_g->x + sidebar_g->width; ret_g->y = 0; *ret_w = FW_W_CORNER(fw, 1); break; case PART_BORDER_SW: ret_g->x = 0; ret_g->y = sidebar_g->y + sidebar_g->height; *ret_w = FW_W_CORNER(fw, 2); break; case PART_BORDER_SE: ret_g->x = sidebar_g->x + sidebar_g->width; ret_g->y = sidebar_g->y + sidebar_g->height; *ret_w = FW_W_CORNER(fw, 3); break; default: break; } switch (part) { case PART_BORDER_N: case PART_BORDER_S: ret_g->width = sidebar_g->width; ret_g->height = bw; break; case PART_BORDER_E: case PART_BORDER_W: ret_g->width = bw; ret_g->height = sidebar_g->height; break; case PART_BORDER_NW: case PART_BORDER_NE: case PART_BORDER_SW: case PART_BORDER_SE: ret_g->width = sidebar_g->x; ret_g->height = sidebar_g->y; break; default: return; } return; } int get_button_number(int context) { int i; for (i = 0; (C_L1 << i) & (C_LALL | C_RALL); i++) { if (context & (C_L1 << i)) { return i; } } return -1; } void border_draw_decorations( FvwmWindow *fw, window_parts draw_parts, Bool has_focus, Bool do_force, clear_window_parts clear_parts, rectangle *old_g, rectangle *new_g) { common_decorations_type cd; Bool do_redraw_titlebar = False; window_parts pressed_parts; window_parts force_parts; int context; int item; if (fw == NULL) { return; } if (WAS_NEVER_DRAWN(fw)) { /* force drawing everything */ do_force = True; draw_parts = PART_ALL; SET_WAS_NEVER_DRAWN(fw, 0); } memset(&cd, 0, sizeof(cd)); /* can't compare with True here, old code calls this with value "2" */ if (do_force != False) { force_parts = draw_parts; } else { force_parts = PART_NONE; } if (has_focus) { /* don't re-draw just for kicks */ if (Scr.Hilite != fw && Scr.Hilite != NULL) { FvwmWindow *t = Scr.Hilite; Scr.Hilite = NULL; /* make sure that the previously highlighted * window got unhighlighted */ border_draw_decorations( t, PART_ALL, False, True, CLEAR_ALL, NULL, NULL); } Scr.Hilite = fw; } else if (fw == Scr.Hilite) { Scr.Hilite = NULL; } if (fw->Desk != Scr.CurrentDesk) { return; } if (IS_ICONIFIED(fw)) { DrawIconWindow(fw, True, True, True, False, NULL); return; } /* calculate some values and flags */ if ((draw_parts & PART_TITLEBAR) && HAS_TITLE(fw)) { do_redraw_titlebar = True; } get_common_decorations( &cd, fw, draw_parts, has_focus, False, do_redraw_titlebar); /* redraw */ context = frame_window_id_to_context(fw, PressedW, &item); if ((context & (C_LALL | C_RALL)) == 0) { item = -1; } pressed_parts = border_context_to_parts(context); if (new_g == NULL) { new_g = &fw->g.frame; } if (do_redraw_titlebar) { border_draw_titlebar( &cd, fw, pressed_parts & PART_TITLEBAR, item, force_parts & PART_TITLEBAR, clear_parts, old_g, new_g, has_focus); } if (draw_parts & PART_FRAME) { Pixmap save_pix = cd.dynamic_cd.frame_pixmap; memset(&cd, 0, sizeof(cd)); get_common_decorations( &cd, fw, draw_parts, has_focus, True, True); cd.dynamic_cd.frame_pixmap = save_pix; border_draw_border_parts( &cd, fw, (pressed_parts & (PART_FRAME | PART_HANDLES)), (force_parts & (PART_FRAME | PART_HANDLES)), clear_parts, old_g, new_g, has_focus); } if (cd.dynamic_cd.frame_pixmap != None) { XFreePixmap(dpy, cd.dynamic_cd.frame_pixmap); } return; } void border_undraw_decorations( FvwmWindow *fw) { memset(&fw->decor_state, 0, sizeof(fw->decor_state)); return; } /* * * redraw the decoration when style change * */ void border_redraw_decorations( FvwmWindow *fw) { FvwmWindow *u = Scr.Hilite; /* domivogt (6-Jun-2000): Don't check if the window is visible here. * If we do, some updates are not applied and when the window becomes * visible again, the X Server may not redraw the window. */ border_draw_decorations( fw, PART_ALL, (Scr.Hilite == fw), True, CLEAR_ALL, NULL, NULL); Scr.Hilite = u; return; } /* * * get the the root transparent parts of the decoration * */ unsigned int border_get_transparent_decorations_part(FvwmWindow *fw) { DecorFace *df,*tdf; unsigned int draw_parts = PART_NONE; int i; window_parts pressed_parts; int context; int item; border_titlebar_state tbstate; Bool title_use_borderstyle = False; Bool buttons_use_borderstyle = False; Bool buttons_use_titlestyle = False; context = frame_window_id_to_context(fw, PressedW, &item); if ((context & (C_LALL | C_RALL)) == 0) { item = -1; } pressed_parts = border_context_to_parts(context); memset(&tbstate, 0, sizeof(tbstate)); border_get_titlebar_descr_state( fw, pressed_parts & PART_TITLEBAR, item, CLEAR_ALL, (Scr.Hilite == fw), &tbstate); for(i = 0; i < NUMBER_OF_TITLE_BUTTONS; i++) { df = &TB_STATE(GetDecor(fw, buttons[i]))[tbstate.bstate[i]]; if (DFS_USE_TITLE_STYLE(df->style)) { buttons_use_titlestyle = True; } if (DFS_USE_BORDER_STYLE(df->style)) { buttons_use_borderstyle = True; } for(tdf = df; tdf != NULL; tdf = tdf->next) { if (DFS_FACE_TYPE(tdf->style) == ColorsetButton && CSET_IS_TRANSPARENT_ROOT(tdf->u.acs.cs)) { draw_parts |= PART_BUTTONS; break; } } } df = &TB_STATE(GetDecor(fw, titlebar))[tbstate.tstate]; if (DFS_USE_BORDER_STYLE(df->style)) { title_use_borderstyle = True; } for(tdf = df; tdf != NULL; tdf = tdf->next) { if (DFS_FACE_TYPE(tdf->style) == ColorsetButton && CSET_IS_TRANSPARENT_ROOT(tdf->u.acs.cs)) { draw_parts |= PART_TITLE; break; } else if (DFS_FACE_TYPE(tdf->style) == MultiPixmap) { int i; for (i = 0; i < TBMP_NUM_PIXMAPS; i++) { if (CSET_IS_TRANSPARENT_ROOT( tdf->u.mp.acs[i].cs)) { draw_parts |= PART_TITLE; break; } } } } df = border_get_border_style(fw, (Scr.Hilite == fw)); if (DFS_FACE_TYPE(df->style) == ColorsetButton && CSET_IS_TRANSPARENT_ROOT(df->u.acs.cs)) { draw_parts |= PART_FRAME|PART_HANDLES; } if (draw_parts & PART_FRAME) { if (title_use_borderstyle) { draw_parts |= PART_TITLE; } if (buttons_use_borderstyle) { draw_parts |= PART_BUTTONS; } } if ((draw_parts & PART_TITLE) && buttons_use_titlestyle) { draw_parts |= PART_BUTTONS; } #if 0 fprintf(stderr,"Transparant Part: %u\n", draw_parts); #endif return draw_parts; } /* ---------------------------- builtin commands --------------------------- */ /* * * Sets the allowed button states * */ void CMD_ButtonState(F_CMD_ARGS) { char *token; while ((token = PeekToken(action, &action))) { static char first = True; if (!token && first) { Scr.gs.use_active_down_buttons = DEFAULT_USE_ACTIVE_DOWN_BUTTONS; Scr.gs.use_inactive_buttons = DEFAULT_USE_INACTIVE_BUTTONS; Scr.gs.use_inactive_down_buttons = DEFAULT_USE_INACTIVE_DOWN_BUTTONS; return; } first = False; if (StrEquals("activedown", token)) { Scr.gs.use_active_down_buttons = ParseToggleArgument( action, &action, DEFAULT_USE_ACTIVE_DOWN_BUTTONS, True); } else if (StrEquals("inactive", token)) { Scr.gs.use_inactive_buttons = ParseToggleArgument( action, &action, DEFAULT_USE_INACTIVE_BUTTONS, True); } else if (StrEquals("inactivedown", token)) { Scr.gs.use_inactive_down_buttons = ParseToggleArgument( action, &action, DEFAULT_USE_INACTIVE_DOWN_BUTTONS, True); } else { Scr.gs.use_active_down_buttons = DEFAULT_USE_ACTIVE_DOWN_BUTTONS; Scr.gs.use_inactive_buttons = DEFAULT_USE_INACTIVE_BUTTONS; Scr.gs.use_inactive_down_buttons = DEFAULT_USE_INACTIVE_DOWN_BUTTONS; fvwm_msg(ERR, "cmd_button_state", "Unknown button state %s", token); return; } } return; } /* * * Sets the border style (veliaa@rpi.edu) * */ void CMD_BorderStyle(F_CMD_ARGS) { char *parm; char *prev; FvwmDecor *decor = Scr.cur_decor ? Scr.cur_decor : &Scr.DefaultDecor; Scr.flags.do_need_window_update = 1; decor->flags.has_changed = 1; for (prev = action; (parm = PeekToken(action, &action)); prev = action) { if (StrEquals(parm, "active") || StrEquals(parm, "inactive")) { int len; char *end, *tmp; DecorFace tmpdf, *df; memset(&tmpdf.style, 0, sizeof(tmpdf.style)); DFS_FACE_TYPE(tmpdf.style) = SimpleButton; tmpdf.next = NULL; if (FMiniIconsSupported) { tmpdf.u.p = NULL; } if (StrEquals(parm,"active")) { df = &decor->BorderStyle.active; } else { df = &decor->BorderStyle.inactive; } df->flags.has_changed = 1; while (isspace(*action)) { ++action; } if (*action != '(') { if (!*action) { fvwm_msg( ERR, "SetBorderStyle", "error in %s border" " specification", parm); return; } while (isspace(*action)) { ++action; } if (ReadDecorFace(action, &tmpdf,-1,True)) { FreeDecorFace(dpy, df); *df = tmpdf; } break; } end = strchr(++action, ')'); if (!end) { fvwm_msg( ERR, "SetBorderStyle", "error in %s border specification", parm); return; } len = end - action + 1; tmp = safemalloc(len); strncpy(tmp, action, len - 1); tmp[len - 1] = 0; ReadDecorFace(tmp, df,-1,True); free(tmp); action = end + 1; } else if (strcmp(parm,"--")==0) { if (ReadDecorFace( prev, &decor->BorderStyle.active,-1,True)) { ReadDecorFace( prev, &decor->BorderStyle.inactive, -1, False); } decor->BorderStyle.active.flags.has_changed = 1; decor->BorderStyle.inactive.flags.has_changed = 1; break; } else { DecorFace tmpdf; memset(&tmpdf.style, 0, sizeof(tmpdf.style)); DFS_FACE_TYPE(tmpdf.style) = SimpleButton; tmpdf.next = NULL; if (FMiniIconsSupported) { tmpdf.u.p = NULL; } if (ReadDecorFace(prev, &tmpdf,-1,True)) { FreeDecorFace(dpy,&decor->BorderStyle.active); decor->BorderStyle.active = tmpdf; ReadDecorFace( prev, &decor->BorderStyle.inactive, -1, False); decor->BorderStyle.active.flags.has_changed = 1; decor->BorderStyle.inactive.flags.has_changed = 1; } break; } } return; } fvwm-2.7.0/fvwm/conditional.c0000644000175000017500000013324214147024700013052 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include "libs/fvwmlib.h" #include "libs/Parse.h" #include "libs/wild.h" #include "libs/FScreen.h" #include "libs/charmap.h" #include "libs/wcontext.h" #include "fvwm.h" #include "externs.h" #include "execcontext.h" #include "functions.h" #include "conditional.h" #include "misc.h" #include "screen.h" #include "update.h" #include "style.h" #include "focus.h" #include "geometry.h" #include "stack.h" #include "commands.h" #include "decorations.h" #include "virtual.h" #include "infostore.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ /* * * Direction = 1 ==> "Next" operation * Direction = -1 ==> "Previous" operation * Direction = 0 ==> operation on current window (returns pass or fail) * */ static FvwmWindow *Circulate( FvwmWindow *sf, char *action, int Direction, char **restofline) { int pass = 0; FvwmWindow *fw, *found = NULL; WindowConditionMask mask; char *flags; /* Create window mask */ flags = CreateFlagString(action, restofline); DefaultConditionMask(&mask); if (Direction == 0) { /* override for Current [] */ mask.my_flags.use_circulate_hit = 1; mask.my_flags.use_circulate_hit_icon = 1; mask.my_flags.use_circulate_hit_shaded = 1; } CreateConditionMask(flags, &mask); if (flags) { free(flags); } if (sf == NULL || Direction == 0) { sf = get_focus_window(); } if (sf != NULL) { if (Direction > 0) { fw = sf->prev; } else if (Direction < 0) { fw = sf->next; } else { fw = sf; } } else { fw = NULL; if (Direction == 0) { FreeConditionMask(&mask); return NULL; } } for (pass = 0; pass < 3 && !found; pass++) { while (fw && !found && fw != &Scr.FvwmRoot) { /* Make CirculateUp and CirculateDown take args. by * Y.NOMURA */ if (MatchesConditionMask(fw, &mask)) { found = fw; } else { if (Direction > 0) { fw = fw->prev; } else { fw = fw->next; } } if (Direction == 0) { FreeConditionMask(&mask); return found; } } if (fw == NULL || fw == &Scr.FvwmRoot) { if (Direction > 0) { /* Go to end of list */ for (fw = Scr.FvwmRoot.next; fw && fw->next; fw = fw->next) { /* nop */ } } else { /* Go to top of list */ fw = Scr.FvwmRoot.next; } } } FreeConditionMask(&mask); return found; } static void circulate_cmd( F_CMD_ARGS, int new_context, int circ_dir, Bool do_use_found, Bool do_exec_on_match) { FvwmWindow *found; char *restofline; found = Circulate(exc->w.fw, action, circ_dir, &restofline); if (cond_rc != NULL) { cond_rc->rc = (found == NULL) ? COND_RC_NO_MATCH : COND_RC_OK; } if ((!found == !do_exec_on_match) && restofline) { const exec_context_t *exc2; exec_context_changes_t ecc; int flags; ecc.w.fw = (do_use_found == True) ? found : NULL; if (found != NULL) { ecc.w.w = FW_W(found); flags = FUNC_DONT_DEFER; } else { ecc.w.w = None; flags = 0; } ecc.w.wcontext = new_context; exc2 = exc_clone_context( exc, &ecc, ECC_FW | ECC_W | ECC_WCONTEXT); execute_function(cond_rc, exc2, restofline, flags); exc_destroy_context(exc2); } return; } static void select_cmd(F_CMD_ARGS) { char *restofline; char *flags; WindowConditionMask mask; FvwmWindow * const fw = exc->w.fw; if (!fw || IS_EWMH_DESKTOP(FW_W(fw))) { if (cond_rc != NULL) { cond_rc->rc = COND_RC_ERROR; } return; } flags = CreateFlagString(action, &restofline); DefaultConditionMask(&mask); mask.my_flags.use_circulate_hit = 1; mask.my_flags.use_circulate_hit_icon = 1; mask.my_flags.use_circulate_hit_shaded = 1; CreateConditionMask(flags, &mask); if (flags) { free(flags); } if (MatchesConditionMask(fw, &mask) && restofline) { if (cond_rc != NULL) { cond_rc->rc = COND_RC_OK; } execute_function_override_wcontext( cond_rc, exc, restofline, 0, C_WINDOW); } else if (cond_rc != NULL) { cond_rc->rc = COND_RC_NO_MATCH; } FreeConditionMask(&mask); return; } static Bool cond_check_access(char *file, int type, Bool im) { char *full_file; char *path = NULL; if (!file || *file == 0) { return False; } if (file[0] == '/') { if (access(file, type) == 0) { return True; } else { return False; } } if (type != X_OK && im == False) { return False; } if (im == False) { path = getenv("PATH"); } else { path = PictureGetImagePath(); } if (path == NULL || *path == 0) { return False; } full_file = searchPath(path, file, NULL, type); if (full_file) { free(full_file); return True; } return False; } /* ---------------------------- interface functions ------------------------ */ /* * Parses the flag string and returns the text between [ ] or ( ) * characters. The start of the rest of the line is put in restptr. * Note that the returned string is allocated here and it must be * freed when it is not needed anymore. * NOTE - exported via .h */ char *CreateFlagString(char *string, char **restptr) { char *retval; char *c; char *start; char closeopt; int length; c = string; while (isspace((unsigned char)*c) && (*c != 0)) { c++; } if (*c == '[' || *c == '(') { char *d; /* Get the text between [ ] or ( ) */ if (*c == '[') { closeopt = ']'; } else { closeopt = ')'; } c++; start = c; length = 0; while (*c != closeopt) { if (*c == 0) { fvwm_msg(ERR, "CreateFlagString", "Conditionals require closing " "parenthesis"); *restptr = NULL; return NULL; } /* skip quoted string */ d = SkipQuote(c, NULL, NULL, NULL); length += d - c; c = d; } /* We must allocate a new string because we null terminate the * string between the [ ] or ( ) characters. */ retval = safemalloc(length + 1); strncpy(retval, start, length); retval[length] = 0; *restptr = c + 1; } else { retval = NULL; *restptr = c; } return retval; } /* * The name_condition field of the mask is allocated in CreateConditionMask. * It must be freed. * NOTE - exported via .h */ void FreeConditionMask(WindowConditionMask *mask) { struct name_condition *pp,*pp2; struct namelist *p,*p2; for (pp=mask->name_condition; pp; ) { /* One malloc() is done for all the name strings. The string is tokenised & the name fields point to different parts of the one string. The start of the string is the first name in the string which is actually the last node in the linked list. */ for (p=pp->namelist; p; ) { p2=p->next; if(!p2) { free(p->name); } free(p); p=p2; } pp2=pp->next; free(pp); pp=pp2; } } /* Assign the default values for the window mask * NOTE - exported via .h */ void DefaultConditionMask(WindowConditionMask *mask) { memset(mask, 0, sizeof(WindowConditionMask)); /* -2 means no layer condition, -1 means current */ mask->layer = -2; return; } /* * Note that this function allocates the name field of the mask struct. * FreeConditionMask must be called for the mask when the mask is discarded. * NOTE - exported via .h */ void CreateConditionMask(char *flags, WindowConditionMask *mask) { char *allocated_condition; char *next_condition; char *condition; char *tmp; unsigned int state; if (flags == NULL) { return; } /* Next parse the flags in the string. */ next_condition = GetNextFullOption(flags, &allocated_condition); condition = PeekToken(allocated_condition, &tmp); while (condition) { char *cond; int on; cond = condition; on = 1; if (*cond == '!') { on = 0; cond++; } if (StrEquals(cond,"AcceptsFocus")) { mask->my_flags.do_accept_focus = on; mask->my_flags.use_do_accept_focus = 1; } else if (StrEquals(cond,"Focused")) { mask->my_flags.needs_focus = (on) ? NEEDS_TRUE : NEEDS_FALSE; } else if (StrEquals(cond,"HasPointer")) { mask->my_flags.needs_pointer = (on) ? NEEDS_TRUE : NEEDS_FALSE; } else if (StrEquals(cond,"Iconic")) { SET_ICONIFIED(mask, on); SETM_ICONIFIED(mask, 1); } else if (StrEquals(cond,"Visible")) { SET_PARTIALLY_VISIBLE(mask, on); SETM_PARTIALLY_VISIBLE(mask, 1); } else if (StrEquals(cond,"Overlapped")) { mask->my_flags.needs_overlapped = on; mask->my_flags.do_check_overlapped = 1; } else if (StrEquals(cond,"PlacedByButton")) { int button; int button_mask; if (sscanf(tmp, "%d", &button) && (button >= 1 && button <= NUMBER_OF_EXTENDED_MOUSE_BUTTONS)) { tmp = SkipNTokens(tmp, 1); button_mask = (1<<(button-1)); } else { button_mask = (1<placed_by_button_mask & mask->placed_by_button_set_mask & ~button_mask) { fvwm_msg(WARN, "PlacedByButton", "Condition always False."); } mask->placed_by_button_mask |= button_mask; } else { mask->placed_by_button_mask &= ~button_mask; } mask->placed_by_button_set_mask |= button_mask; } else if (StrEquals(cond,"PlacedByButton3")) { if (on) { if (mask->placed_by_button_mask & mask->placed_by_button_set_mask & ~(1<<2)) { fvwm_msg(WARN, "PlacedByButton3", "Condition always False."); } mask->placed_by_button_mask |= (1<<2); } else { mask->placed_by_button_mask &= ~(1<<2); } mask->placed_by_button_set_mask |= (1<<2); } else if (StrEquals(cond,"Raised")) { SET_FULLY_VISIBLE(mask, on); SETM_FULLY_VISIBLE(mask, 1); } else if (StrEquals(cond,"Sticky")) { SET_STICKY_ACROSS_PAGES(mask, on); SET_STICKY_ACROSS_DESKS(mask, on); SETM_STICKY_ACROSS_PAGES(mask, 1); SETM_STICKY_ACROSS_DESKS(mask, 1); } else if (StrEquals(cond,"StickyAcrossPages")) { SET_STICKY_ACROSS_PAGES(mask, on); SETM_STICKY_ACROSS_PAGES(mask, 1); } else if (StrEquals(cond,"StickyAcrossDesks")) { SET_STICKY_ACROSS_DESKS(mask, on); SETM_STICKY_ACROSS_DESKS(mask, 1); } else if (StrEquals(cond,"StickyIcon")) { SET_ICON_STICKY_ACROSS_PAGES(mask, on); SET_ICON_STICKY_ACROSS_DESKS(mask, on); SETM_ICON_STICKY_ACROSS_PAGES(mask, 1); SETM_ICON_STICKY_ACROSS_DESKS(mask, 1); } else if (StrEquals(cond,"StickyAcrossPagesIcon")) { SET_ICON_STICKY_ACROSS_PAGES(mask, on); SETM_ICON_STICKY_ACROSS_PAGES(mask, 1); } else if (StrEquals(cond,"StickyAcrossDesksIcon")) { SET_ICON_STICKY_ACROSS_DESKS(mask, on); SETM_ICON_STICKY_ACROSS_DESKS(mask, 1); } else if (StrEquals(cond,"Maximized")) { SET_MAXIMIZED(mask, on); SETM_MAXIMIZED(mask, 1); } else if (StrEquals(cond, "Fullscreen")) { mask->my_flags.do_check_fullscreen = on; } else if (StrEquals(cond,"FixedSize")) { /* don't set mask here, because we make the test here (and don't compare against window's mask) by checking allowed function */ SET_SIZE_FIXED(mask, on); SETM_SIZE_FIXED(mask, 1); } else if (StrEquals(cond, "FixedPosition")) { SET_FIXED(mask, on); SETM_FIXED(mask, 1); } else if (StrEquals(cond,"HasHandles")) { SET_HAS_HANDLES(mask, on); SETM_HAS_HANDLES(mask, 1); } else if (StrEquals(cond,"Iconifiable")) { SET_IS_UNICONIFIABLE(mask, !on); SETM_IS_UNICONIFIABLE(mask, 1); } else if (StrEquals(cond,"Maximizable")) { SET_IS_UNMAXIMIZABLE(mask, !on); SETM_IS_UNMAXIMIZABLE(mask, 1); } else if (StrEquals(cond,"Closable")) { SET_IS_UNCLOSABLE(mask, !on); SETM_IS_UNCLOSABLE(mask, 1); } else if (StrEquals(cond,"Shaded")) { SET_SHADED(mask, on); SETM_SHADED(mask, 1); } else if (StrEquals(cond,"Transient")) { SET_TRANSIENT(mask, on); SETM_TRANSIENT(mask, 1); } else if (StrEquals(cond,"PlacedByFvwm")) { SET_PLACED_BY_FVWM(mask, on); SETM_PLACED_BY_FVWM(mask, 1); } else if (StrEquals(cond,"CurrentDesk")) { mask->my_flags.needs_current_desk = on; mask->my_flags.do_check_desk = 1; } else if (StrEquals(cond,"CurrentPage")) { mask->my_flags.needs_current_desk_and_page = on; mask->my_flags.do_check_desk_and_page = 1; } else if (StrEquals(cond,"CurrentGlobalPage")) { mask->my_flags.needs_current_desk_and_global_page = on; mask->my_flags.do_check_desk_and_global_page = 1; } else if (StrEquals(cond,"CurrentPageAnyDesk") || StrEquals(cond,"CurrentScreen")) { mask->my_flags.needs_current_page = on; mask->my_flags.do_check_page = 1; } else if (StrEquals(cond,"AnyScreen")) { mask->my_flags.do_not_check_screen = on; } else if (StrEquals(cond,"CurrentGlobalPageAnyDesk")) { mask->my_flags.needs_current_global_page = on; mask->my_flags.do_check_global_page = 1; } else if (StrEquals(cond,"CirculateHit")) { mask->my_flags.use_circulate_hit = on; } else if (StrEquals(cond,"CirculateHitIcon")) { mask->my_flags.use_circulate_hit_icon = on; } else if (StrEquals(cond,"CirculateHitShaded")) { mask->my_flags.use_circulate_hit_shaded = on; } else if (StrEquals(cond,"State")) { if (sscanf(tmp, "%u", &state) && state <= 31) { state = (1 << state); if (on) { SET_USER_STATES(mask, state); } else { CLEAR_USER_STATES(mask, state); } SETM_USER_STATES(mask, state); tmp = SkipNTokens(tmp, 1); } } else if (StrEquals(cond, "Layer")) { if (sscanf(tmp, "%d", &mask->layer)) { tmp = SkipNTokens(tmp, 1); if (mask->layer < 0) { /* silently ignore invalid layers */ mask->layer = -2; } } else { /* needs current layer */ mask->layer = -1; } mask->my_flags.needs_same_layer = on; } else if (StrEquals(cond, "Desk")) { if (sscanf(tmp, "%d", &mask->desk)) { tmp = SkipNTokens(tmp, 1); } mask->my_flags.do_check_cond_desk = on; } else if (StrEquals(cond, "Screen")) { if (sscanf(tmp, "%d", &mask->screen)) { tmp = SkipNTokens(tmp, 1); } mask->my_flags.do_check_screen = 1; if (!on) mask->my_flags.do_not_check_screen = 1; } else { struct name_condition *pp; struct namelist *p; char *condp = safestrdup(cond); pp = (struct name_condition *) safemalloc(sizeof(struct name_condition)); pp->invert = (!on ? True : False); pp->namelist = NULL; pp->next = mask->name_condition; mask->name_condition = pp; for (;;) { p = (struct namelist *) safemalloc(sizeof(struct namelist)); p->name=condp; p->next=pp->namelist; pp->namelist=p; while(*condp && *condp != '|') { condp++; } if(!*condp) { break; } *condp++='\0'; } } if (tmp && *tmp) { fvwm_msg(OLD, "CreateConditionMask", "Use comma instead of whitespace to " "separate conditions"); } else { if (allocated_condition != NULL) { free(allocated_condition); allocated_condition = NULL; } if (next_condition && *next_condition) { next_condition = GetNextFullOption( next_condition, &allocated_condition); } tmp = allocated_condition; } condition = PeekToken(tmp, &tmp); } return; } /* * Checks whether the given window matches the mask created with * CreateConditionMask. * NOTE - exported via .h */ Bool MatchesConditionMask(FvwmWindow *fw, WindowConditionMask *mask) { int does_match; int is_on_desk; int is_on_page; int is_on_global_page; FvwmWindow *sf = get_focus_window(); struct name_condition *pp; struct namelist *p; char *name; /* match FixedSize conditional */ /* special treatment for FixedSize, because more than just the is_size_fixed flag makes a window unresizable (width and height hints etc.) */ if (IS_SIZE_FIXED(mask) && mask->flag_mask.common.s.is_size_fixed && is_function_allowed(F_RESIZE, NULL, fw, RQORIG_PROGRAM_US, False)) { return False; } if (!IS_SIZE_FIXED(mask) && mask->flag_mask.common.s.is_size_fixed && !is_function_allowed(F_RESIZE, NULL, fw, RQORIG_PROGRAM_US, False)) { return False; } if (IS_FIXED(mask) && mask->flag_mask.common.s.is_fixed && is_function_allowed(F_MOVE, NULL, fw, RQORIG_PROGRAM_US, False)) { return False; } if (!IS_FIXED(mask) && mask->flag_mask.common.s.is_fixed && !is_function_allowed(F_MOVE, NULL, fw, RQORIG_PROGRAM_US, False)) { return False; } if (IS_UNICONIFIABLE(mask) && mask->flag_mask.common.s.is_uniconifiable && is_function_allowed(F_ICONIFY, NULL, fw, RQORIG_PROGRAM_US, False)) { return False; } if ( !IS_UNICONIFIABLE(mask) && mask->flag_mask.common.s.is_uniconifiable && !is_function_allowed( F_ICONIFY, NULL, fw, RQORIG_PROGRAM_US, False)) { return False; } if ( IS_UNMAXIMIZABLE(mask) && mask->flag_mask.common.s.is_unmaximizable && is_function_allowed( F_MAXIMIZE, NULL, fw, RQORIG_PROGRAM_US, False)) { return False; } if ( !IS_UNMAXIMIZABLE(mask) && mask->flag_mask.common.s.is_unmaximizable && !is_function_allowed( F_MAXIMIZE, NULL, fw, RQORIG_PROGRAM_US, False)) { return False; } if ( IS_UNCLOSABLE(mask) && mask->flag_mask.common.s.is_unclosable && (is_function_allowed( F_CLOSE, NULL, fw, RQORIG_PROGRAM_US,False) || is_function_allowed( F_DELETE, NULL, fw, RQORIG_PROGRAM_US,False) || is_function_allowed( F_DESTROY, NULL, fw, RQORIG_PROGRAM_US, False))) { return False; } if ( !IS_UNCLOSABLE(mask) && mask->flag_mask.common.s.is_unclosable && (!is_function_allowed( F_CLOSE, NULL, fw, RQORIG_PROGRAM_US,False) && !is_function_allowed( F_DELETE, NULL, fw, RQORIG_PROGRAM_US,False) && !is_function_allowed( F_DESTROY, NULL, fw, RQORIG_PROGRAM_US,False))) { return False; } if (!blockcmpmask((char *)&(fw->flags), (char *)&(mask->flags), (char *)&(mask->flag_mask), sizeof(fw->flags))) { return False; } if (!mask->my_flags.use_circulate_hit && DO_SKIP_CIRCULATE(fw)) { return False; } if (!mask->my_flags.use_circulate_hit_icon && IS_ICONIFIED(fw) && DO_SKIP_ICON_CIRCULATE(fw)) { return False; } if (!mask->my_flags.use_circulate_hit_shaded && IS_SHADED(fw) && DO_SKIP_SHADED_CIRCULATE(fw)) { return False; } if (IS_ICONIFIED(fw) && IS_TRANSIENT(fw) && IS_ICONIFIED_BY_PARENT(fw)) { return False; } /* desk and page matching */ is_on_desk = 1; if (mask->my_flags.do_check_desk || mask->my_flags.do_check_desk_and_page || mask->my_flags.do_check_desk_and_global_page) { is_on_desk = (fw->Desk == Scr.CurrentDesk); } is_on_page = 1; if (mask->my_flags.do_check_page || mask->my_flags.do_check_desk_and_page) { if (FScreenIsEnabled() && !mask->my_flags.do_not_check_screen) { is_on_page = !!FScreenIsRectangleOnScreen( NULL, FSCREEN_CURRENT, &(fw->g.frame)); } else { is_on_page = !!IsRectangleOnThisPage( &(fw->g.frame), Scr.CurrentDesk); } } is_on_global_page = 1; if (mask->my_flags.do_check_global_page || mask->my_flags.do_check_desk_and_global_page) { is_on_global_page = !!IsRectangleOnThisPage( &(fw->g.frame), Scr.CurrentDesk); } if (mask->my_flags.do_check_desk_and_page) { int is_on_desk_and_page; is_on_desk_and_page = (is_on_desk && is_on_page); if (mask->my_flags.needs_current_desk_and_page != is_on_desk_and_page) { return False; } } else if (mask->my_flags.do_check_desk_and_global_page) { int is_on_desk_and_global_page; is_on_desk_and_global_page = (is_on_desk && is_on_global_page); if (mask->my_flags.needs_current_desk_and_global_page != is_on_desk_and_global_page) { return False; } } if (mask->my_flags.do_check_desk && mask->my_flags.needs_current_desk != is_on_desk) { return False; } if (mask->my_flags.do_check_page) { if (mask->my_flags.needs_current_page != is_on_page) { return False; } } else if (mask->my_flags.do_check_global_page) { if (mask->my_flags.needs_current_global_page != is_on_global_page) { return False; } } for (pp = mask->name_condition; pp; pp = pp->next) { does_match = 0; for (p = pp->namelist; p; p = p->next) { name=p->name; does_match |= matchWildcards(name, fw->name.name); does_match |= matchWildcards(name, fw->icon_name.name); if(fw->class.res_class) does_match |= matchWildcards(name, fw->class.res_class); if(fw->class.res_name) does_match |= matchWildcards(name, fw->class.res_name); } if(( pp->invert && does_match) || (!pp->invert && !does_match)) { return False; } } if (mask->my_flags.do_check_fullscreen) { return IS_EWMH_FULLSCREEN(fw); } if (mask->layer == -1 && sf) { int is_same_layer; is_same_layer = (fw->layer == sf->layer); if (mask->my_flags.needs_same_layer != is_same_layer) { return False; } } if (mask->layer >= 0) { int is_same_layer; is_same_layer = (fw->layer == mask->layer); if (mask->my_flags.needs_same_layer != is_same_layer) { return False; } } if (mask->placed_by_button_set_mask) { if (!((mask->placed_by_button_set_mask & (1<<(fw->placed_by_button - 1))) == (mask->placed_by_button_set_mask & mask->placed_by_button_mask))) { return False; } } if (GET_USER_STATES(mask) != (mask->flag_mask.common.user_states & GET_USER_STATES(fw))) { return False; } if (mask->my_flags.use_do_accept_focus) { Bool f; f = focus_does_accept_input_focus(fw); if (fw && !FP_DO_FOCUS_BY_FUNCTION(FW_FOCUS_POLICY(fw))) { f = False; } else if (fw && FP_IS_LENIENT(FW_FOCUS_POLICY(fw))) { f = True; } if (!f != !mask->my_flags.do_accept_focus) { return False; } } if (mask->my_flags.needs_focus != NEEDS_ANY) { int is_focused; is_focused = (fw == get_focus_window()); if (!is_focused && mask->my_flags.needs_focus == NEEDS_TRUE) { return False; } else if (is_focused && mask->my_flags.needs_focus == NEEDS_FALSE) { return False; } } if (mask->my_flags.needs_pointer != NEEDS_ANY) { int has_pointer; FvwmWindow *t; t = get_pointer_fvwm_window(); if (t != NULL && t == fw) { has_pointer = 1; } else { has_pointer = 0; } if (!has_pointer && mask->my_flags.needs_pointer == NEEDS_TRUE) { return False; } else if (has_pointer && mask->my_flags.needs_pointer == NEEDS_FALSE) { return False; } } if (mask->my_flags.do_check_overlapped) { int is_o; is_o = (is_on_top_of_layer(fw) == False); if (is_o != mask->my_flags.needs_overlapped) { return False; } } if (mask->my_flags.do_check_cond_desk) { if (fw->Desk == mask->desk) return True; else return False; if (fw->Desk != mask->desk) return True; else return False; } if (mask->my_flags.do_check_screen) { rectangle g; int scr; get_unshaded_geometry(fw, &g); scr = FScreenOfPointerXY(g.x, g.y); if (mask->my_flags.do_not_check_screen) { /* Negation of (!screen n) specified. */ return (scr != mask->screen); } else return (scr == mask->screen); } return True; } static void direction_cmd(F_CMD_ARGS, Bool is_scan) { rectangle my_g; rectangle his_g; int my_cx; int my_cy; int his_cx; int his_cy; int cross = 0; int offset = 0; int distance = 0; int cycle = False; int forward = False; int score; int best_cross = 0; int best_score; int worst_score = -1; FvwmWindow *tfw; FvwmWindow *fw_best; int dir; int dir2; Bool right_handed=False; char *flags; char *restofline; char *tmp; float tx; float ty; WindowConditionMask mask; Bool is_pointer_relative; FvwmWindow * const fw = exc->w.fw; /* Parse the direction. */ tmp = PeekToken(action, &action); if (StrEquals(tmp, "FromPointer")) { is_pointer_relative = True; tmp = PeekToken(action, &action); } else { is_pointer_relative = False; } dir = gravity_parse_dir_argument(tmp, NULL, -1); if (dir == -1 || dir > DIR_ALL_MASK) { fvwm_msg(ERR, "Direction", "Invalid direction %s", (tmp) ? tmp : ""); if (cond_rc != NULL) { cond_rc->rc = COND_RC_ERROR; } return; } if (is_scan) { cycle = True; tmp = PeekToken(action, &action); if ( ! tmp ) { fvwm_msg( ERR, "Direction", "Missing minor direction %s", (tmp) ? tmp : ""); if (cond_rc != NULL) { cond_rc->rc = COND_RC_ERROR; } return; } dir2 = gravity_parse_dir_argument(tmp, NULL, -1); /* if enum direction_t changes, this is trashed. */ if (dir2 == -1 || dir2 > DIR_NW || (dir < 4) != (dir2 < 4) || (abs(dir - dir2) & 1) != 1) { fvwm_msg( ERR, "Direction", "Invalid minor direction %s", (tmp) ? tmp : ""); if (cond_rc != NULL) { cond_rc->rc = COND_RC_ERROR; } return; } else if (dir2 - dir == 1 || dir2 - dir == -3) { right_handed=True; } } /* Create the mask for flags */ flags = CreateFlagString(action, &restofline); if (!restofline) { if (flags) { free(flags); } if (cond_rc != NULL) { cond_rc->rc = COND_RC_NO_MATCH; } return; } DefaultConditionMask(&mask); CreateConditionMask(flags, &mask); if (flags) { free(flags); } /* If there is a focused window, use that as a starting point. * Otherwise we use the pointer as a starting point. */ if (fw && is_pointer_relative == False) { get_visible_window_or_icon_geometry(fw, &my_g); my_cx = my_g.x + my_g.width / 2; my_cy = my_g.y + my_g.height / 2; } else { if (FQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, &my_g.x, &my_g.y, &JunkX, &JunkY, &JunkMask) == False) { /* pointer is on a different screen */ my_g.x = 0; my_g.y = 0; } my_g.width = 1; my_g.height = 1; my_cx = my_g.x; my_cy = my_g.y; } /* Next we iterate through all windows and choose the closest one in * the wanted direction. */ fw_best = NULL; best_score = -1; for (tfw = Scr.FvwmRoot.next; tfw != NULL; tfw = tfw->next) { /* Skip every window that does not match conditionals. Also * skip the currently focused window. That would be too * close. :) */ if (tfw == fw || !MatchesConditionMask(tfw, &mask)) { continue; } /* Calculate relative location of the window. */ get_visible_window_or_icon_geometry(tfw, &his_g); his_g.x -= my_cx; his_g.y -= my_cy; his_cx = his_g.x + his_g.width / 2; his_cy = his_g.y + his_g.height / 2; if (dir > DIR_MAJOR_MASK && dir <= DIR_MINOR_MASK) { int tx; /* Rotate the diagonals 45 degrees counterclockwise. To * do this, multiply the matrix /+h +h\ with the vector * (x y). \-h +h/ * h = sqrt(0.5). We can set h := 1 since absolute * distance doesn't * matter here. */ tx = his_cx + his_cy; his_cy = -his_cx + his_cy; his_cx = tx; } /* Arrange so that distance and offset are positive in desired * direction. */ switch (dir) { case DIR_S: case DIR_SW: forward = True; case DIR_N: case DIR_NE: cross = -his_cx; offset = (his_cx < 0) ? -his_cx : his_cx; distance = (dir == DIR_N || dir == DIR_NE) ? -his_cy : his_cy; break; case DIR_E: /* E */ case DIR_SE: /* SE */ forward = True; case DIR_W: /* W */ case DIR_NW: /* NW */ cross = his_cy; offset = (his_cy < 0) ? -his_cy : his_cy; distance = (dir == DIR_W || dir == DIR_NW) ? -his_cx : his_cx; break; case DIR_C: offset = 0; tx = (float)his_cx; ty = (float)his_cy; distance = (int)sqrt(tx * tx + ty * ty); break; } if (cycle) { offset=0; } else if (distance < 0) { /* Target must be in given direction. */ continue; } else if (distance == 0 && dir != DIR_C) { continue; } /* Calculate score for this window. The smaller the better. */ score = distance + offset; if (!right_handed) { cross= -cross; } if (cycle) { int ordered = (forward == (cross < best_cross)); if (distance < 0 && best_score == -1 && (score < worst_score || (score == worst_score && ordered))) { fw_best = tfw; worst_score = score; best_cross = cross; } if (score == 0 && forward == (cross < 0) && dir != DIR_C) { continue; } if (distance >= 0 && (best_score == -1 || score < best_score || (score == best_score && ordered))) { fw_best = tfw; best_score = score; best_cross = cross; } } else { /* windows more than 45 degrees off the direction are * heavily penalized and will only be chosen if nothing * else within a million pixels */ if (offset > distance) { score += 1000000; } if (best_score == -1 || score < best_score || (score == best_score && dir == DIR_C)) { fw_best = tfw; best_score = score; } } } /* for */ if (fw_best) { if (cond_rc != NULL) { cond_rc->rc = COND_RC_OK; } execute_function_override_window( cond_rc, exc, restofline, 0, fw_best); } else if (cond_rc != NULL) { cond_rc->rc = COND_RC_NO_MATCH; } FreeConditionMask(&mask); return; } static int __rc_matches_rcstring_consume( char **ret_rest, cond_rc_t *cond_rc, char *action) { cond_rc_enum match_rc; char *orig_flags; char *flags; int is_not_reversed = 1; int ret; /* Create window mask */ orig_flags = CreateFlagString(action, ret_rest); flags = orig_flags; if (flags == NULL) { match_rc = COND_RC_NO_MATCH; } else { if (*flags == '!') { is_not_reversed = 0; flags++; } if (StrEquals(flags, "1") || StrEquals(flags, "match")) { match_rc = COND_RC_OK; } else if (StrEquals(flags, "0") || StrEquals(flags, "nomatch")) { match_rc = COND_RC_NO_MATCH; } else if (StrEquals(flags, "-1") || StrEquals(flags, "error")) { match_rc = COND_RC_ERROR; } else if (StrEquals(flags, "-2") || StrEquals(flags, "break")) { match_rc = COND_RC_BREAK; } else { match_rc = COND_RC_NO_MATCH; /* Does anyone check for other numerical returncode * values? If so, this might have to be changed. */ fprintf( stderr, "Unrecognised condition \"%s\" in" " TestRc command.\n", flags); } } if (orig_flags != NULL) { free(orig_flags); } ret = ((cond_rc->rc == match_rc) == is_not_reversed); return ret; } /* ---------------------------- builtin commands --------------------------- */ void CMD_Prev(F_CMD_ARGS) { circulate_cmd(F_PASS_ARGS, C_WINDOW, -1, True, True); return; } void CMD_Next(F_CMD_ARGS) { circulate_cmd(F_PASS_ARGS, C_WINDOW, 1, True, True); return; } void CMD_None(F_CMD_ARGS) { circulate_cmd(F_PASS_ARGS, C_ROOT, 1, False, False); /* invert return code */ switch (cond_rc->rc) { case COND_RC_OK: cond_rc->rc = COND_RC_NO_MATCH; break; case COND_RC_NO_MATCH: cond_rc->rc = COND_RC_OK; break; default: break; } return; } void CMD_Any(F_CMD_ARGS) { circulate_cmd(F_PASS_ARGS, exc->w.wcontext, 1, False, True); return; } void CMD_Current(F_CMD_ARGS) { circulate_cmd(F_PASS_ARGS, C_WINDOW, 0, True, True); return; } void CMD_PointerWindow(F_CMD_ARGS) { exec_context_changes_t ecc; ecc.w.fw = get_pointer_fvwm_window(); exc = exc_clone_context(exc, &ecc, ECC_FW); select_cmd(F_PASS_ARGS); exc_destroy_context(exc); return; } void CMD_ThisWindow(F_CMD_ARGS) { select_cmd(F_PASS_ARGS); return; } void CMD_Pick(F_CMD_ARGS) { select_cmd(F_PASS_ARGS); return; } void CMD_All(F_CMD_ARGS) { FvwmWindow *t, **g; char *restofline; WindowConditionMask mask; char *flags; int num, i; Bool does_any_window_match = False; char *token; Bool do_reverse = False; Bool use_stack = False; while (True) /* break when a non-option is found */ { token = PeekToken(action, &restofline); if (StrEquals(token, "Reverse")) { if (!*restofline) { /* if not any more actions, then Reverse * probably is some user function, so ignore * it and do the old behaviour */ break; } else { do_reverse = True; action = restofline; } } else if (StrEquals(token, "UseStack")) { if (!*restofline) { /* if not any more actions, then UseStack * probably is some user function, so ignore * it and do the old behaviour */ break; } else { use_stack = True; action = restofline; } } else { /* No more options -- continue with flags and * commands */ break; } } flags = CreateFlagString(action, &restofline); DefaultConditionMask(&mask); mask.my_flags.use_circulate_hit = 1; mask.my_flags.use_circulate_hit_icon = 1; mask.my_flags.use_circulate_hit_shaded = 1; CreateConditionMask(flags, &mask); if (flags) { free(flags); } num = 0; for (t = Scr.FvwmRoot.next; t; t = t->next) { num++; } g = (FvwmWindow **)safemalloc(num * sizeof(FvwmWindow *)); num = 0; if (!use_stack) { for (t = Scr.FvwmRoot.next; t; t = t->next) { if (MatchesConditionMask(t, &mask)) { g[num++] = t; does_any_window_match = True; } } } else { for (t = Scr.FvwmRoot.stack_next; t && t != &Scr.FvwmRoot; t = t->stack_next) { if (MatchesConditionMask(t, &mask)) { g[num++] = t; does_any_window_match = True; } } } if (do_reverse) { for (i = num-1; i >= 0; i--) { execute_function_override_window( cond_rc, exc, restofline, 0, g[i]); } } else { for (i = 0; i < num; i++) { execute_function_override_window( cond_rc, exc, restofline, 0, g[i]); } } if (cond_rc != NULL && cond_rc->rc != COND_RC_BREAK) { cond_rc->rc = (does_any_window_match == False) ? COND_RC_NO_MATCH : COND_RC_OK; } free(g); FreeConditionMask(&mask); return; } /* * Execute a function to the closest window in the given * direction. */ void CMD_Direction(F_CMD_ARGS) { direction_cmd(F_PASS_ARGS,False); } void CMD_ScanForWindow(F_CMD_ARGS) { direction_cmd(F_PASS_ARGS,True); } void CMD_WindowId(F_CMD_ARGS) { FvwmWindow *t; char *token; char *naction; unsigned long win; Bool use_condition = False; Bool use_screenroot = False; WindowConditionMask mask; char *flags, *restofline; /* Get window ID */ action = GetNextToken(action, &token); if (token && StrEquals(token, "root")) { int screen = Scr.screen; free(token); token = PeekToken(action, &naction); if (!token || GetIntegerArguments(token, NULL, &screen, 1) != 1) { screen = Scr.screen; } else { action = naction; } use_screenroot = True; if (screen < 0 || screen >= Scr.NumberOfScreens) { screen = 0; } win = XRootWindow(dpy, screen); if (win == None) { if (cond_rc != NULL) { cond_rc->rc = COND_RC_ERROR; } return; } } else if (token) { /* SunOS doesn't have strtoul */ win = (unsigned long)strtol(token, NULL, 0); free(token); } else { win = 0; } /* Look for condition - CreateFlagString returns NULL if no '(' or '[' */ if (!use_screenroot) { flags = CreateFlagString(action, &restofline); if (flags) { /* Create window mask */ use_condition = True; DefaultConditionMask(&mask); /* override for Current [] */ mask.my_flags.use_circulate_hit = 1; mask.my_flags.use_circulate_hit_icon = 1; mask.my_flags.use_circulate_hit_icon = 1; CreateConditionMask(flags, &mask); free(flags); /* Relocate action */ action = restofline; } } /* Search windows */ for (t = Scr.FvwmRoot.next; t; t = t->next) { if (FW_W(t) == win) { /* do it if no conditions or the conditions match */ if (action && (!use_condition || MatchesConditionMask(t, &mask))) { if (cond_rc != NULL) { cond_rc->rc = COND_RC_OK; } execute_function_override_window( cond_rc, exc, action, 0, t); } else if (cond_rc != NULL) { cond_rc->rc = COND_RC_NO_MATCH; } break; } } if (!t) { /* The window is not managed by fvwm. Still some functions may * work on it. */ if (use_condition) { if (cond_rc != NULL) { cond_rc->rc = COND_RC_ERROR; } } else if (XGetGeometry( dpy, win, &JunkRoot, &JunkX, &JunkY, (unsigned int*)&JunkWidth, (unsigned int*)&JunkHeight, (unsigned int*)&JunkBW, (unsigned int*)&JunkDepth) != 0) { if (cond_rc != NULL) { cond_rc->rc = COND_RC_OK; } if (action != NULL) { const exec_context_t *exc2; exec_context_changes_t ecc; ecc.w.fw = NULL; ecc.w.w = win; ecc.w.wcontext = C_UNMANAGED; exc2 = exc_clone_context( exc, &ecc, ECC_FW | ECC_W | ECC_WCONTEXT); execute_function( cond_rc, exc2, action, FUNC_IS_UNMANAGED); exc_destroy_context(exc2); } } else { /* window id does not exist */ if (cond_rc != NULL) { cond_rc->rc = COND_RC_ERROR; } } } /* Tidy up */ if (use_condition) { FreeConditionMask(&mask); } return; } void CMD_TestRc(F_CMD_ARGS) { char *rest; if (cond_rc == NULL) { /* useless if no return code to compare to is given */ return; } if (__rc_matches_rcstring_consume(&rest, cond_rc, action) && rest != NULL) { /* execute the command in root window context; overwrite the * return code with the return code of the command */ execute_function(cond_rc, exc, rest, 0); } return; } void CMD_Break(F_CMD_ARGS) { int rc; if (cond_rc == NULL) { return; } rc = GetIntegerArguments(action, &action, &cond_rc->break_levels, 1); if (rc != 1 || cond_rc->break_levels <= 0) { cond_rc->break_levels = -1; } cond_rc->rc = COND_RC_BREAK; return; } void CMD_NoWindow(F_CMD_ARGS) { execute_function_override_window(cond_rc, exc, action, 0, NULL); return; } /* ver() - convert a version string to a floating-point number that * can be used to compare different versions. * ie. converts "2.5.11" to 2005011 */ static int ver (char *str) { char *n; int v; str = DoPeekToken(str, &n, NULL, ".", NULL); if (!n) { return -1.0; } v = atoi(n) * 1000000; str = DoPeekToken(str, &n, NULL, ".", NULL); if (!n) { return -1.0; } v += atoi(n) * 1000; str = DoPeekToken(str, &n, NULL, ".", NULL); if (!n) { return -1.0; } v += atoi(n); return v; } /* match_version() - compare $version against this version of fvwm * using the operator specified by $operator. */ static Bool match_version(char *version, char *operator) { static int fvwm_version = -1; const int v = ver(version); if (fvwm_version < 0) { char *tmp = safestrdup(VERSION); fvwm_version = ver(tmp); free(tmp); } if (v < 0) { fprintf( stderr, "match_version: Invalid version: %s\n", version); return False; } if (strcmp(operator, ">=") == 0) { return fvwm_version >= v; } else if (strcmp(operator, ">") == 0) { return fvwm_version > v; } else if (strcmp(operator, "<=") == 0) { return fvwm_version <= v; } else if (strcmp(operator, "<") == 0) { return fvwm_version < v; } else if (strcmp(operator, "==") == 0) { return (v == fvwm_version); } else if (strcmp(operator, "!=") == 0) { return (v != fvwm_version); } else { fprintf( stderr, "match_version: Invalid operator: %s\n", operator); } return False; } void CMD_Test(F_CMD_ARGS) { char *restofline; char *flags; char *condition; char *flags_ptr; int match; int error; flags = CreateFlagString(action, &restofline); /* Next parse the flags in the string. */ flags_ptr = flags; flags_ptr = GetNextSimpleOption(flags_ptr, &condition); match = 1; error = 0; while (condition) { char *cond; int reverse; cond = condition; reverse = 0; if (*cond == '!') { reverse = 1; cond++; } if (StrEquals(cond, "True")) { match = 1; } else if (StrEquals(cond, "False")) { match = 0; } else if (StrEquals(cond, "Version")) { char *pattern; flags_ptr = GetNextSimpleOption(flags_ptr, &pattern); if (pattern) { char *ver; flags_ptr = GetNextSimpleOption( flags_ptr, &ver); if (ver == NULL) { match = matchWildcards( pattern, VERSION); } else { match = match_version(ver, pattern); free(ver); } free(pattern); } else { error = 1; } } else if (StrEquals(cond, "Start")) { match = exc->type == EXCT_INIT || exc->type == EXCT_RESTART; } else if (StrEquals(cond, "Init")) { match = exc->type == EXCT_INIT; } else if (StrEquals(cond, "Restart")) { match = exc->type == EXCT_RESTART; } else if (StrEquals(cond, "Exit")) { match = exc->type == EXCT_QUIT || exc->type == EXCT_TORESTART; } else if (StrEquals(cond, "Quit")) { match = exc->type == EXCT_QUIT; } else if (StrEquals(cond, "ToRestart")) { match = exc->type == EXCT_TORESTART; } else if (StrEquals(cond, "x") || StrEquals(cond, "r") || StrEquals(cond, "w") || StrEquals(cond, "f") || StrEquals(cond, "i")) { char *pattern; int type = X_OK; Bool im = 0; switch(cond[0]) { case 'X': case 'x': type = X_OK; break; case 'R': case 'r': type = R_OK; break; case 'W': case 'w': type = W_OK; break; case 'f': case 'F': type = F_OK; break; case 'i': case 'I': im = True; type = R_OK; break; default: /* cannot happen */ break; } flags_ptr = GetNextSimpleOption(flags_ptr, &pattern); if (pattern) { match = cond_check_access(pattern, type, im); free(pattern); } else { error = 1; } } else if (StrEquals(cond, "EnvIsSet")) { char *var_name; flags_ptr = GetNextSimpleOption(flags_ptr, &var_name); if (var_name) { const char *value = getenv(var_name); match = (value != NULL) ? 1 : 0; } else { error = 1; } } else if (StrEquals(cond, "EnvMatch")) { char *var_name; flags_ptr = GetNextSimpleOption(flags_ptr, &var_name); if (var_name) { const char *value; if ( (strlen(var_name) > 10) && (memcmp(var_name,"infostore.",10) == 0) ) { value = get_metainfo_value(var_name+10); } else { value = getenv(var_name); } char *pattern; /* unfortunately, GetNextSimpleOption is * broken, does not accept quoted empty "" * * DV (2-Sep-2014): It is *not* broken. The * parsing functions never return empty tokens * by design. */ flags_ptr = GetNextSimpleOption( flags_ptr, &pattern); if (!value) { value = ""; } if (pattern) { match = /* include empty string case */ (!pattern[0] && !value[0]) || matchWildcards(pattern, value); } else { error = 1; } } else { error = 1; } } else if (StrEquals(cond, "EdgeIsActive")) { direction_t dir= DIR_NONE; char *dirname; char *next; next = GetNextSimpleOption(flags_ptr, &dirname); if (dirname) { dir = gravity_parse_dir_argument( dirname, NULL, DIR_NONE); if (dir == DIR_NONE) { if (!StrEquals(dirname, "Any")) { next = flags_ptr; } } else if (dir > DIR_MAJOR_MASK) { error = 1; } free(dirname); } if (!error) { if (((dir == DIR_W || dir == DIR_NONE) && Scr.PanFrameLeft.isMapped) || ((dir == DIR_N || dir == DIR_NONE) && Scr.PanFrameTop.isMapped) || ((dir == DIR_S || dir == DIR_NONE) && Scr.PanFrameBottom.isMapped) || ((dir == DIR_E || dir == DIR_NONE) && Scr.PanFrameRight.isMapped)) { match = 1; } else { match = 0; } } flags_ptr = next; } else if (StrEquals(cond, "EdgeHasPointer")) { int x,y; Window win; direction_t dir = DIR_NONE; char *dirname; char *next; next = GetNextSimpleOption(flags_ptr, &dirname); if (dirname) { dir = gravity_parse_dir_argument( dirname, NULL, DIR_NONE); if (dir == DIR_NONE) { if (!StrEquals(dirname, "Any")) { next = flags_ptr; } } else if (dir > DIR_MAJOR_MASK) { error = 1; } free(dirname); } if (!error) { if (FQueryPointer( dpy, Scr.Root, &JunkRoot, &win, &JunkX, &JunkY, &x, &y, &JunkMask) == False) { /* pointer is on a different screen */ match = 0; } else if (is_pan_frame(win)) { if (dir == DIR_NONE || (dir == DIR_N && win == Scr.PanFrameTop.win) || (dir == DIR_S && win == Scr.PanFrameBottom.win) || (dir == DIR_E && win == Scr.PanFrameRight.win) || (dir == DIR_W && win == Scr.PanFrameLeft.win)) { match = 1; } else { match = 0; } } else { match = 0; } } flags_ptr = next; } else { /* unrecognized condition */ error = 1; fprintf( stderr, "Unrecognised condition \"%s\" in" " Test command.\n", cond); } if (reverse) { match = !match; } free(condition); if (error || !match) { break; } flags_ptr = GetNextSimpleOption(flags_ptr, &condition); } if (flags != NULL) { free(flags); } if (!error && match) { execute_function(cond_rc, exc, restofline, 0); } if (cond_rc != NULL) { if (error) { cond_rc->rc = COND_RC_ERROR; } else if (match) { cond_rc->rc = COND_RC_OK; } else { cond_rc->rc = COND_RC_NO_MATCH; } } return; } fvwm-2.7.0/fvwm/condrc.c0000644000175000017500000000330514147024700012013 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include "condrc.h" /* --------------------------- local definitions --------------------------- */ /* --------------------------- local macros -------------------------------- */ /* --------------------------- imports ------------------------------------- */ /* --------------------------- included code files ------------------------- */ /* --------------------------- local types --------------------------------- */ /* --------------------------- forward declarations ------------------------ */ /* --------------------------- local variables ----------------------------- */ /* --------------------------- exported variables (globals) ---------------- */ /* --------------------------- local functions ----------------------------- */ /* --------------------------- interface functions ------------------------- */ void condrc_init(cond_rc_t *cond_rc) { memset(cond_rc, 0, sizeof(*cond_rc)); cond_rc->rc = COND_RC_OK; return; } fvwm-2.7.0/fvwm/modconf.c0000644000175000017500000002114614147024700012173 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* * * code for processing module configuration commands * * Modification History * * Created 09/23/98 by Dan Espen: * * - Some of this logic used to reside in "read.c", preceeded by a * comment about whether it belonged there. Time tells. * * - Added logic to execute module config commands by passing to the * modules that want "active command pipes". * * ******************************************************************** */ #include "config.h" #include #include "libs/fvwmlib.h" #include "libs/Parse.h" #include "libs/Strings.h" #include "libs/wild.h" #include "fvwm.h" #include "externs.h" #include "cursor.h" #include "functions.h" #include "bindings.h" #include "misc.h" #include "screen.h" #include "module_list.h" #include "module_interface.h" #include "colorset.h" #include "libs/FScreen.h" extern int nColorsets; /* in libs/Colorset.c */ /* do not send ColorLimit, it is not used anymore but maybe by non * "official" modules */ #define DISABLE_COLORLIMIT_CONFIG_INFO #define MODULE_CONFIG_DELIM ':' struct moduleInfoList { char *data; unsigned char alias_len; struct moduleInfoList *next; }; struct moduleInfoList *modlistroot = NULL; static struct moduleInfoList *AddToModList(char *tline); static void SendConfigToModule( fmodule *module, const struct moduleInfoList *entry, char *match, int match_len); /* * ModuleConfig handles commands starting with "*". * * Each command is added to a list from which modules request playback * thru "sendconfig". * * Some modules request that module config commands be sent to them * as the commands are entered. Send to modules that want it. */ void ModuleConfig(char *action) { int end; fmodule_list_itr moditr; fmodule *module; struct moduleInfoList *new_entry; end = strlen(action) - 1; if (action[end] == '\n') action[end] = '\0'; /* save for config request */ new_entry = AddToModList(action); /* look at all possible pipes */ module_list_itr_init(&moditr); while ( (module = module_list_itr_next(&moditr)) != NULL) { if (IS_MESSAGE_SELECTED(module, M_SENDCONFIG)) { /* module wants config cmds */ char *name = MOD_NAME(module); if (MOD_ALIAS(module)) { name = MOD_ALIAS(module); } SendConfigToModule( module, new_entry, CatString2("*", name), 0); } } return; } static struct moduleInfoList *AddToModList(char *tline) { struct moduleInfoList *t, *prev, *this; char *rline = tline; char *alias_end = skipModuleAliasToken(tline + 1); /* Find end of list */ t = modlistroot; prev = NULL; while(t != NULL) { prev = t; t = t->next; } this = (struct moduleInfoList *)safemalloc( sizeof(struct moduleInfoList)); this->alias_len = 0; if (alias_end && alias_end[0] == MODULE_CONFIG_DELIM) { /* migo (01-Sep-2000): construct an old-style config line */ char *conf_start = alias_end + 1; while (isspace(*conf_start)) conf_start++; *alias_end = '\0'; rline = CatString2(tline, conf_start); *alias_end = MODULE_CONFIG_DELIM; this->alias_len = alias_end - tline; } this->data = (char *)safemalloc(strlen(rline)+1); strcpy(this->data, rline); this->next = NULL; if(prev == NULL) { modlistroot = this; } else { prev->next = this; } return this; } /* * delete from module configuration */ void CMD_DestroyModuleConfig(F_CMD_ARGS) { struct moduleInfoList *current, *next, *prev; char *info; /* info to be deleted - may contain wildcards */ char *mi; char *alias_end; int alias_len = 0; while (isspace(*action)) { action++; } alias_end = skipModuleAliasToken(action); if (alias_end && alias_end[0] == MODULE_CONFIG_DELIM) { /* migo: construct an old-style config line */ char *conf_start = alias_end + 1; while (isspace(*conf_start)) conf_start++; *alias_end = '\0'; GetNextToken(conf_start, &conf_start); if (conf_start == NULL) { return; } info = stripcpy(CatString2(action, conf_start)); *alias_end = MODULE_CONFIG_DELIM; /* +1 for a leading '*' */ alias_len = alias_end - action + 1; free(conf_start); } else { GetNextToken(action, &info); if (info == NULL) { return; } } current = modlistroot; prev = NULL; while (current != NULL) { GetNextToken(current->data, &mi); next = current->next; if ((!alias_len || !current->alias_len || alias_len == current->alias_len) && matchWildcards(info, mi+1)) { free(current->data); free(current); if( prev ) { prev->next = next; } else { modlistroot = next; } } else { prev = current; } current = next; if (mi) { free(mi); } } free(info); return; } static void send_xinerama_state(fmodule *module) { SendName(module, M_CONFIG_INFO, 0, 0, 0, FScreenGetConfiguration()); return; } static void send_desktop_names(fmodule *module) { DesktopsInfo *d; char *name; for (d = Scr.Desktops->next; d != NULL; d = d->next) { if (d->name != NULL) { name = (char *)safemalloc(strlen(d->name) + 44); sprintf(name,"DesktopName %d %s", d->desk, d->name); SendName(module, M_CONFIG_INFO, 0, 0, 0, name); free(name); } } return; } static void send_desktop_geometry(fmodule *module) { char msg[64]; sprintf(msg, "DesktopSize %d %d\n", Scr.VxMax / Scr.MyDisplayWidth + 1, Scr.VyMax / Scr.MyDisplayHeight + 1); SendName(module, M_CONFIG_INFO, 0, 0, 0, msg); return; } static void send_image_path(fmodule *module) { char *msg; char *ImagePath = PictureGetImagePath(); if (ImagePath && *ImagePath != 0) { msg = safemalloc(strlen(ImagePath) + 12); sprintf(msg, "ImagePath %s\n", ImagePath); SendName(module, M_CONFIG_INFO, 0, 0, 0, msg); free(msg); } return; } static void send_color_limit(fmodule *module) { #ifndef DISABLE_COLORLIMIT_CONFIG_INFO char msg[64]; sprintf(msg, "ColorLimit %d\n", Scr.ColorLimit); SendName(module, M_CONFIG_INFO, 0, 0, 0, msg); #endif return; } static void send_colorsets(fmodule *module) { int n; /* dump the colorsets (0 first as others copy it) */ for (n = 0; n < nColorsets; n++) { SendName( module, M_CONFIG_INFO, 0, 0, 0, DumpColorset(n, &Colorset[n])); } return; } static void send_click_time(fmodule *module) { char msg[64]; /* Dominik Vogt (8-Nov-1998): Scr.ClickTime patch to set ClickTime to * 'not at all' during InitFunction and RestartFunction. */ sprintf(msg,"ClickTime %d\n", (Scr.ClickTime < 0) ? -Scr.ClickTime : Scr.ClickTime); SendName(module, M_CONFIG_INFO, 0, 0, 0, msg); return; } static void send_move_threshold(fmodule *module) { char msg[64]; sprintf(msg, "MoveThreshold %d\n", Scr.MoveThreshold); SendName(module, M_CONFIG_INFO, 0, 0, 0, msg); return; } void send_ignore_modifiers(fmodule *module) { char msg[64]; sprintf(msg, "IgnoreModifiers %d\n", GetUnusedModifiers()); SendName(module, M_CONFIG_INFO, 0, 0, 0, msg); return; } void CMD_Send_ConfigInfo(F_CMD_ARGS) { struct moduleInfoList *t; /* matching criteria for module cmds */ char *match; /* get length once for efficiency */ int match_len = 0; fmodule *mod = exc->m.module; send_desktop_geometry(mod); /* send ImagePath and ColorLimit first */ send_image_path(mod); send_color_limit(mod); send_xinerama_state(mod); send_colorsets(mod); send_click_time(mod); send_move_threshold(mod); match = PeekToken(action, &action); if (match) { match_len = strlen(match); } for (t = modlistroot; t != NULL; t = t->next) { SendConfigToModule(mod, t, match, match_len); } send_desktop_names(mod); send_ignore_modifiers(mod); SendPacket( mod, M_END_CONFIG_INFO, (long)0, (long)0, (long)0, (long)0, (long)0, (long)0, (long)0, (long)0); return; } static void SendConfigToModule( fmodule *module, const struct moduleInfoList *entry, char *match, int match_len) { if (match) { if (match_len == 0) { match_len = strlen(match); } if (entry->alias_len > 0 && entry->alias_len != match_len) { return; } /* migo: this should be strncmp not strncasecmp probably. */ if (strncasecmp(entry->data, match, match_len) != 0) { return; } } SendName(module, M_CONFIG_INFO, 0, 0, 0, entry->data); return; } fvwm-2.7.0/fvwm/style.h0000644000175000017500000005403214147024700011713 00000000000000/* -*-c-*- */ #ifndef _STYLE_ #define _STYLE_ /* access to the special flags of a style */ /* call these with a pointer to a style_flags struct */ #define SDO_DECORATE_TRANSIENT(sf) \ ((sf)->do_decorate_transient) #define SDO_SAVE_UNDER(sf) \ ((sf)->do_save_under) #define SDO_START_LOWERED(sf) \ ((sf)->do_start_lowered) #define SDO_START_SHADED(sf) \ ((sf)->do_start_shaded) #define SHAS_BORDER_WIDTH(sf) \ ((sf)->has_border_width) #define SHAS_COLOR_BACK(sf) \ ((sf)->has_color_back) #define SHAS_COLOR_FORE(sf) \ ((sf)->has_color_fore) #define SHAS_HANDLE_WIDTH(sf) \ ((sf)->has_handle_width) #define SHAS_ICON(sf) \ ((sf)->has_icon) #define SHAS_ICON_BOXES(sf) \ ((sf)->has_icon_boxes) #define SHAS_ICON_SIZE_LIMITS(sf) \ ((sf)->has_icon_size_limits) #define SHAS_ICON_BACKGROUND_PADDING(sf) \ ((sf)->has_icon_background_padding) #define SHAS_ICON_BACKGROUND_RELIEF(sf) \ ((sf)->has_icon_background_relief) #define SHAS_ICON_TITLE_RELIEF(sf) \ ((sf)->has_icon_title_relief) #define SHAS_MIN_WINDOW_SIZE(sf) \ ((sf)->has_min_window_size) #define SHAS_MAX_WINDOW_SIZE(sf) \ ((sf)->has_max_window_size) #define SHAS_WINDOW_SHADE_STEPS(sf) \ ((sf)->has_window_shade_steps) #define SHAS_MINI_ICON(sf) \ ((sf)->has_mini_icon) #define SHAS_MWM_DECOR(sf) \ ((sf)->has_mwm_decor) #define SHAS_MWM_FUNCTIONS(sf) \ ((sf)->has_mwm_functions) #define SHAS_NO_HANDLES(sf) \ ((sf)->has_no_handles) #define SHAS_NO_TITLE(sf) \ ((sf)->has_no_title) #define SHAS_OL_DECOR(sf) \ ((sf)->has_ol_decor) #define SIS_BUTTON_DISABLED(sf) \ ((sf)->is_button_disabled) #define SIS_UNMANAGED(sf) \ ((sf)->is_unmanaged) #define SPLACEMENT_MODE(sf) \ ((sf)->placement_mode) #define SEWMH_PLACEMENT_MODE(sf) \ ((sf)->ewmh_placement_mode) #define SUSE_BACKING_STORE(sf) \ ((sf)->use_backing_store) #define SUSE_PARENT_RELATIVE(sf) \ ((sf)->use_parent_relative) #define SUSE_COLORSET(sf) \ ((sf)->use_colorset) #define SUSE_COLORSET_HI(sf) \ ((sf)->use_colorset_hi) #define SUSE_BORDER_COLORSET(sf) \ ((sf)->use_border_colorset) #define SUSE_BORDER_COLORSET_HI(sf) \ ((sf)->use_border_colorset_hi) #define SUSE_ICON_TITLE_COLORSET(sf) \ ((sf)->use_icon_title_colorset) #define SUSE_ICON_TITLE_COLORSET_HI(sf) \ ((sf)->use_icon_title_colorset_hi) #define SUSE_ICON_BACKGROUND_COLORSET(sf) \ ((sf)->use_icon_background_colorset) #define SUSE_LAYER(sf) \ ((sf)->use_layer) #define SUSE_NO_PPOSITION(sf) \ ((sf)->use_no_pposition) #define SUSE_NO_USPOSITION(sf) \ ((sf)->use_no_usposition) #define SUSE_NO_TRANSIENT_PPOSITION(sf) \ ((sf)->use_no_transient_pposition) #define SUSE_NO_TRANSIENT_USPOSITION(sf) \ ((sf)->use_no_transient_usposition) #define SUSE_START_ON_DESK(sf) \ ((sf)->use_start_on_desk) #define SUSE_START_ON_PAGE_FOR_TRANSIENT(sf) \ ((sf)->use_start_on_page_for_transient) #define SUSE_START_ON_SCREEN(sf) \ ((sf)->use_start_on_screen) #define SMANUAL_PLACEMENT_HONORS_STARTS_ON_PAGE(sf) \ ((sf)->manual_placement_honors_starts_on_page) #define SCAPTURE_HONORS_STARTS_ON_PAGE(sf) \ ((sf)->capture_honors_starts_on_page) #define SRECAPTURE_HONORS_STARTS_ON_PAGE(sf) \ ((sf)->recapture_honors_starts_on_page) #define SHAS_PLACEMENT_PENALTY(sf) \ ((sf)->has_placement_penalty) #define SHAS_PLACEMENT_PERCENTAGE_PENALTY(sf) \ ((sf)->has_placement_percentage_penalty) #define SHAS_PLACEMENT_POSITION_STRING(sf) \ ((sf)->has_placement_position_string #define SCR_MOTION_METHOD(sf) \ ((sf)->ws_cr_motion_method) /* access the various copies of the common flags structure. */ #define SCF(st) \ ((st).flags.common) #define SCFS(st) \ ((st).flags.common.s) #define SCM(st) \ ((st).flag_mask.common) #define SCMS(st) \ ((st).flag_mask.common.s) #define SCD(st) \ ((st).flag_default.common) #define SCDS(st) \ ((st).flag_default.common.s) #define SCC(st) \ ((st).change_mask.common) #define SCCS(st) \ ((st).change_mask.common.s) #define SFC(sf) \ ((sf).common) /* access to common flags */ #define S_FOCUS_POLICY(c) \ ((c).s.focus_policy) #define S_TITLE_DIR(c) \ ((c).title_dir) #define S_SET_TITLE_DIR(c,x) \ ((c).title_dir = (x)) #define S_USER_STATES(c) \ ((c).user_states) #define S_SET_USER_STATES(c,x) \ ((c).user_states = (x)) #define S_ADD_USER_STATES(c,x) \ ((c).user_states = ((c).user_states | (x))) #define S_IS_STICKY_ACROSS_PAGES(c) \ ((c).is_sticky_across_pages) #define S_SET_IS_STICKY_ACROSS_PAGES(c,x) \ ((c).is_sticky_across_pages = !!(x)) #define S_IS_STICKY_ACROSS_DESKS(c) \ ((c).is_sticky_across_desks) #define S_SET_IS_STICKY_ACROSS_DESKS(c,x) \ ((c).is_sticky_across_desks = !!(x)) #define S_DO_CIRCULATE_SKIP(c) \ ((c).s.do_circulate_skip) #define S_SET_DO_CIRCULATE_SKIP(c,x) \ ((c).s.do_circulate_skip = !!(x)) #define S_DO_CIRCULATE_SKIP_ICON(c) \ ((c).s.do_circulate_skip_icon) #define S_SET_DO_CIRCULATE_SKIP_ICON(c,x) \ ((c).s.do_circulate_skip_icon = !!(x)) #define S_DO_CIRCULATE_SKIP_SHADED(c) \ ((c).s.do_circulate_skip_shaded) #define S_SET_DO_CIRCULATE_SKIP_SHADED(c,x) \ ((c).s.do_circulate_skip_shaded = !!(x)) #define S_DO_ICONIFY_WINDOW_GROUPS(c) \ ((c).s.do_iconify_window_groups) #define S_SET_DO_ICONIFY_WINDOW_GROUPS(c,x) \ ((c).s.do_iconify_window_groups = !!(x)) #define S_DO_IGNORE_ICON_BOXES(c) \ ((c).s.do_ignore_icon_boxes) #define S_SET_DO_IGNORE_ICON_BOXES(c,x) \ ((c).s.do_ignore_icon_boxes = !!(x)) #define S_DO_IGNORE_RESTACK(c) \ ((c).s.do_ignore_restack) #define S_SET_DO_IGNORE_RESTACK(c,x) \ ((c).s.do_ignore_restack = !!(x)) #define S_DO_USE_WINDOW_GROUP_HINT(c) \ ((c).s.do_use_window_group_hint) #define S_SET_DO_USE_WINDOW_GROUP_HINT(c,x) \ ((c).s.do_use_window_group_hint = !!(x)) #define S_DO_LOWER_TRANSIENT(c) \ ((c).s.do_lower_transient) #define S_SET_DO_LOWER_TRANSIENT(c,x) \ ((c).s.do_lower_transient = !!(x)) #define S_DO_NOT_SHOW_ON_MAP(c) \ ((c).s.do_not_show_on_map) #define S_SET_DO_NOT_SHOW_ON_MAP(c,x) \ ((c).s.do_not_show_on_map = !!(x)) #define S_DO_RAISE_TRANSIENT(c) \ ((c).s.do_raise_transient) #define S_SET_DO_RAISE_TRANSIENT(c,x) \ ((c).s.do_raise_transient = !!(x)) #define S_DO_RESIZE_OPAQUE(c) \ ((c).s.do_resize_opaque) #define S_SET_DO_RESIZE_OPAQUE(c,x) \ ((c).s.do_resize_opaque = !!(x)) #define S_DO_SHRINK_WINDOWSHADE(c) \ ((c).s.do_shrink_windowshade) #define S_SET_DO_SHRINK_WINDOWSHADE(c,x) \ ((c).s.do_shrink_windowshade = !!(x)) #define S_DO_STACK_TRANSIENT_PARENT(c) \ ((c).s.do_stack_transient_parent) #define S_SET_DO_STACK_TRANSIENT_PARENT(c,x) \ ((c).s.do_stack_transient_parent = !!(x)) #define S_DO_WINDOW_LIST_SKIP(c) \ ((c).s.do_window_list_skip) #define S_SET_DO_WINDOW_LIST_SKIP(c,x) \ ((c).s.do_window_list_skip = !!(x)) #define S_HAS_NO_BORDER(c) \ ((c).has_no_border) #define S_SET_HAS_NO_BORDER(c,x) \ ((c).has_no_border = !!(x)) #define S_HAS_DEPRESSABLE_BORDER(c) \ ((c).s.has_depressable_border) #define S_SET_HAS_DEPRESSABLE_BORDER(c,x) \ ((c).s.has_depressable_border = !!(x)) #define S_HAS_ICON_FONT(c) \ ((c).has_icon_font) #define S_SET_HAS_ICON_FONT(c,x) \ ((c).has_icon_font = !!(x)) #define S_HAS_MWM_BORDER(c) \ ((c).s.has_mwm_border) #define S_SET_HAS_MWM_BORDER(c,x) \ ((c).s.has_mwm_border = !!(x)) #define S_HAS_MWM_BUTTONS(c) \ ((c).s.has_mwm_buttons) #define S_SET_HAS_MWM_BUTTONS(c,x) \ ((c).s.has_mwm_buttons = !!(x)) #define S_HAS_MWM_OVERRIDE(c) \ ((c).s.has_mwm_override) #define S_SET_HAS_MWM_OVERRIDE(c,x) \ ((c).s.has_mwm_override = !!(x)) #define S_HAS_NO_STICKY_STIPPLED_ICON_TITLE(c) \ ((c).s.has_no_sticky_stippled_icon_title) #define S_SET_HAS_NO_STICKY_STIPPLED_ICON_TITLE(c,x) \ ((c).s.has_no_sticky_stippled_icon_title = !!(x)) #define S_HAS_NO_ICON_TITLE(c) \ ((c).s.has_no_icon_title) #define S_SET_HAS_NO_ICON_TITLE(c,x) \ ((c).s.has_no_icon_title = !!(x)) #define S_HAS_OVERRIDE_SIZE(c) \ ((c).s.has_override_size) #define S_SET_HAS_OVERRIDE_SIZE(c,x) \ ((c).s.has_override_size = !!(x)) #define S_HAS_STIPPLED_TITLE(c) \ ((c).s.has_stippled_title) #define S_SET_HAS_STIPPLED_TITLE(c,x) \ ((c).s.has_stippled_title = !!(x)) #define S_HAS_NO_STICKY_STIPPLED_TITLE(c) \ ((c).s.has_no_sticky_stippled_title) #define S_SET_HAS_NO_STICKY_STIPPLED_TITLE(c,x) \ ((c).s.has_no_sticky_stippled_title = !!(x)) #define S_HAS_STIPPLED_ICON_TITLE(c) \ ((c).s.has_stippled_icon_title) #define S_SET_HAS_STIPPLED_ICON_TITLE(c,x) \ ((c).s.has_stippled_icon_title = !!(x)) #define S_HAS_WINDOW_FONT(c) \ ((c).has_window_font) #define S_SET_HAS_WINDOW_FONT(c,x) \ ((c).has_window_font = !!(x)) #define S_ICON_OVERRIDE(c) \ ((c).s.icon_override) #define S_SET_ICON_OVERRIDE(c,x) \ ((c).s.icon_override = (x)) #define S_IS_BOTTOM_TITLE_ROTATED(c) \ ((c).s.is_bottom_title_rotated) #define S_SET_IS_BOTTOM_TITLE_ROTATED(c,x) \ ((c).s.is_bottom_title_rotated = !!(x)) #define S_IS_FIXED(c) \ ((c).s.is_fixed) #define S_SET_IS_FIXED(c,x) \ ((c).s.is_fixed = !!(x)) #define S_IS_FIXED_PPOS(c) \ ((c).s.is_fixed_ppos) #define S_SET_IS_FIXED_PPOS(c,x) \ ((c).s.is_fixed_ppos = !!(x)) #define S_SET_IS_UNICONIFIABLE(c,x) \ ((c).s.is_uniconifiable = !!(x)) #define S_SET_IS_UNMAXIMIZABLE(c,x) \ ((c).s.is_unmaximizable = !!(x)) #define S_SET_IS_UNCLOSABLE(c,x) \ ((c).s.is_unclosable = !!(x)) #define S_SET_MAXIMIZE_FIXED_SIZE_DISALLOWED(c,x) \ ((c).s.is_maximize_fixed_size_disallowed = !!(x)) #define S_IS_ICON_STICKY_ACROSS_PAGES(c) \ ((c).s.is_icon_sticky_across_pages) #define S_SET_IS_ICON_STICKY_ACROSS_PAGES(c,x) \ ((c).s.is_icon_sticky_across_pages = !!(x)) #define S_IS_ICON_STICKY_ACROSS_DESKS(c) \ ((c).s.is_icon_sticky_across_desks) #define S_SET_IS_ICON_STICKY_ACROSS_DESKS(c,x) \ ((c).s.is_icon_sticky_across_desks = !!(x)) #define S_IS_ICON_SUPPRESSED(c) \ ((c).s.is_icon_suppressed) #define S_SET_IS_ICON_SUPPRESSED(c,x) \ ((c).s.is_icon_suppressed = !!(x)) #define S_IS_LEFT_TITLE_ROTATED_CW(c) \ ((c).s.is_left_title_rotated_cw) #define S_SET_IS_LEFT_TITLE_ROTATED_CW(c,x) \ ((c).s.is_left_title_rotated_cw = !!(x)) #define S_IS_SIZE_FIXED(c) \ ((c).s.is_size_fixed) #define S_SET_IS_SIZE_FIXED(c,x) \ ((c).s.is_size_fixed = !!(x)) #define S_IS_PSIZE_FIXED(c) \ ((c).s.is_psize_fixed) #define S_SET_IS_PSIZE_FIXED(c,x) \ ((c).s.is_psize_fixed = !!(x)) #define S_IS_RIGHT_TITLE_ROTATED_CW(c) \ ((c).s.is_right_title_rotated_cw) #define S_SET_IS_RIGHT_TITLE_ROTATED_CW(c,x) \ ((c).s.is_right_title_rotated_cw = !!(x)) #define S_IS_TOP_TITLE_ROTATED(c) \ ((c).s.is_top_title_rotated) #define S_SET_IS_TOP_TITLE_ROTATED(c,x) \ ((c).s.is_top_title_rotated = !!(x)) #define S_USE_ICON_POSITION_HINT(c) \ ((c).s.use_icon_position_hint) #define S_SET_USE_ICON_POSITION_HINT(c,x) \ ((c).s.use_icon_position_hint = !!(x)) #define S_USE_INDEXED_WINDOW_NAME(c) \ ((c).s.use_indexed_window_name) #define S_SET_USE_INDEXED_WINDOW_NAME(c,x) \ ((c).s.use_indexed_window_name = !!(x)) #define S_USE_INDEXED_ICON_NAME(c) \ ((c).s.use_indexed_icon_name) #define S_SET_USE_INDEXED_ICON_NAME(c,x) \ ((c).s.use_indexed_icon_name = !!(x)) #define S_WINDOWSHADE_LAZINESS(c) \ ((c).s.windowshade_laziness) #define S_SET_WINDOWSHADE_LAZINESS(c,x) \ ((c).s.windowshade_laziness = (x)) #define S_USE_TITLE_DECOR_ROTATION(c) \ ((c).s.use_title_decor_rotation) #define S_SET_USE_TITLE_DECOR_ROTATION(c,x) \ ((c).s.use_title_decor_rotation = !!(x)) #define S_DO_EWMH_MINI_ICON_OVERRIDE(c) \ ((c).s.do_ewmh_mini_icon_override) #define S_SET_DO_EWMH_MINI_ICON_OVERRIDE(c,x) \ ((c).s.do_ewmh_mini_icon_override = !!(x)) #define S_DO_EWMH_DONATE_ICON(c) \ ((c).s.do_ewmh_donate_icon) #define S_SET_DO_EWMH_DONATE_ICON(c,x) \ ((c).s.do_ewmh_donate_icon = !!(x)) #define S_DO_EWMH_DONATE_MINI_ICON(c) \ ((c).s.do_ewmh_donate_mini_icon) #define S_SET_DO_EWMH_DONATE_MINI_ICON(c,x) \ ((c).s.do_ewmh_donate_mini_icon = !!(x)) #define S_DO_EWMH_USE_STACKING_HINTS(c) \ ((c).s.do_ewmh_use_stacking_hints) #define S_SET_DO_EWMH_USE_STACKING_HINTS(c,x) \ ((c).s.do_ewmh_use_stacking_hints = !!(x)) #define S_DO_EWMH_IGNORE_STRUT_HINTS(c) \ ((c).s.do_ewmh_ignore_strut_hints) #define S_SET_DO_EWMH_IGNORE_STRUT_HINTS(c,x) \ ((c).s.do_ewmh_ignore_strut_hints = !!(x)) #define S_DO_EWMH_IGNORE_STATE_HINTS(c) \ ((c).s.do_ewmh_ignore_state_hints) #define S_SET_DO_EWMH_IGNORE_STATE_HINTS(c,x) \ ((c).s.do_ewmh_ignore_state_hints = !!(x)) #define S_DO_EWMH_IGNORE_WINDOW_TYPE(c) \ ((c).s.do_ewmh_ignore_window_type) #define S_SET_DO_EWMH_IGNORE_WINDOW_TYPE(c,x) \ ((c).s.do_ewmh_ignore_window_type = !!(x)) #define S_EWMH_MAXIMIZE_MODE(c) \ ((c).s.ewmh_maximize_mode) #define S_SET_EWMH_MAXIMIZE_MODE(c,x) \ ((c).s.ewmh_maximize_mode = (x)) /* access to style_id */ #define SID_GET_NAME(id) \ ((id).name) #define SID_SET_NAME(id,x) \ ((id).name = (x)) #define SID_GET_WINDOW_ID(id) \ ((id).window_id) #define SID_SET_WINDOW_ID(id,x) \ ((id).window_id = (x)) #define SID_SET_HAS_NAME(id,x) \ ((id).flags.has_name = !!(x)) #define SID_GET_HAS_NAME(id) \ ((id).flags.has_name) #define SID_SET_HAS_WINDOW_ID(id,x) \ ((id).flags.has_window_id = !!(x)) #define SID_GET_HAS_WINDOW_ID(id) \ ((id).flags.has_window_id) /* access to other parts of a style (call with the style itself) */ #define SGET_NEXT_STYLE(s) \ ((s).next) #define SSET_NEXT_STYLE(s,x) \ ((s).next = (x)) #define SGET_PREV_STYLE(s) \ ((s).prev) #define SSET_PREV_STYLE(s,x) \ ((s).prev = (x)) #define SGET_ID(s) \ ((s).id) #define SGET_NAME(s) \ SID_GET_NAME(SGET_ID(s)) #define SSET_NAME(s,x) \ SID_SET_NAME(SGET_ID(s),x) #define SGET_WINDOW_ID(s) \ SID_GET_WINDOW_ID(SGET_ID(s)) #define SSET_WINDOW_ID(s,x) \ SID_SET_WINDOW_ID(SGET_ID(s),x) #define SSET_ID_HAS_NAME(s,x) \ SID_SET_HAS_NAME(SGET_ID(s), x) #define SGET_ID_HAS_NAME(s) \ SID_GET_HAS_NAME(SGET_ID(s)) #define SSET_ID_HAS_WINDOW_ID(s,x) \ SID_SET_HAS_WINDOW_ID(SGET_ID(s),x) #define SGET_ID_HAS_WINDOW_ID(s) \ SID_GET_HAS_WINDOW_ID(SGET_ID(s)) #define SGET_ICON_NAME(s) \ ((s).icon_name) #define SSET_ICON_NAME(s,x) \ ((s).icon_name = (x)) #define SGET_MINI_ICON_NAME(s) \ ((s).mini_icon_name) #define SSET_MINI_ICON_NAME(s,x) \ ((s).mini_icon_name = (x)) #define SGET_DECOR_NAME(s) \ ((s).decor_name) #define SSET_DECOR_NAME(s,x) \ ((s).decor_name = (x)) #define SGET_FORE_COLOR_NAME(s) \ ((s).fore_color_name) #define SSET_FORE_COLOR_NAME(s,x) \ ((s).fore_color_name = (x)) #define SGET_BACK_COLOR_NAME(s) \ ((s).back_color_name) #define SSET_BACK_COLOR_NAME(s,x) \ ((s).back_color_name = (x)) #define SGET_FORE_COLOR_NAME_HI(s) \ ((s).fore_color_name_hi) #define SSET_FORE_COLOR_NAME_HI(s,x) \ ((s).fore_color_name_hi = (x)) #define SGET_BACK_COLOR_NAME_HI(s) \ ((s).back_color_name_hi) #define SSET_BACK_COLOR_NAME_HI(s,x) \ ((s).back_color_name_hi = (x)) #define SGET_ICON_FONT(s) \ ((s).icon_font) #define SSET_ICON_FONT(s,x) \ ((s).icon_font = (x)) #define SGET_WINDOW_FONT(s) \ ((s).window_font) #define SSET_WINDOW_FONT(s,x) \ ((s).window_font = (x)) #define SGET_COLORSET(s) \ ((s).colorset) #define SSET_COLORSET(s,x) \ ((s).colorset = (x)) #define SSET_BORDER_COLORSET(s,x) \ ((s).border_colorset = (x)) #define SGET_BORDER_COLORSET(s) \ ((s).border_colorset) #define SGET_COLORSET_HI(s) \ ((s).colorset_hi) #define SSET_COLORSET_HI(s,x) \ ((s).colorset_hi = (x)) #define SGET_BORDER_COLORSET_HI(s) \ ((s).border_colorset_hi) #define SSET_BORDER_COLORSET_HI(s,x) \ ((s).border_colorset_hi = (x)) #define SSET_ICON_TITLE_COLORSET(s,x) \ ((s).icon_title_colorset = (x)) #define SGET_ICON_TITLE_COLORSET(s) \ ((s).icon_title_colorset) #define SSET_ICON_TITLE_COLORSET_HI(s,x) \ ((s).icon_title_colorset_hi = (x)) #define SGET_ICON_TITLE_COLORSET_HI(s) \ ((s).icon_title_colorset_hi) #define SSET_ICON_BACKGROUND_COLORSET(s,x) \ ((s).icon_background_colorset = (x)) #define SGET_ICON_BACKGROUND_COLORSET(s) \ ((s).icon_background_colorset) #define SGET_FLAGS_POINTER(s) \ (&((s).flags)) #define SGET_BORDER_WIDTH(s) \ ((s).border_width) #define SSET_BORDER_WIDTH(s,x) \ ((s).border_width = (x)) #define SGET_HANDLE_WIDTH(s) \ ((s).handle_width) #define SSET_HANDLE_WIDTH(s,x) \ ((s).handle_width = (x)) #define SGET_LAYER(s) \ ((s).layer) #define SSET_LAYER(s,x) \ ((s).layer = (x)) #define SGET_START_DESK(s) \ ((s).start_desk) #define SSET_START_DESK(s,x) \ ((s).start_desk = (x)) #define SGET_START_PAGE_X(s) \ ((s).start_page_x) #define SSET_START_PAGE_X(s,x) \ ((s).start_page_x = (x)) #define SGET_START_PAGE_Y(s) \ ((s).start_page_y) #define SSET_START_PAGE_Y(s,x) \ ((s).start_page_y = (x)) #define SGET_START_SCREEN(s) \ ((s).start_screen) #define SSET_START_SCREEN(s,x) \ ((s).start_screen = (x)) #define SSET_STARTS_SHADED_DIR(s,x) \ ((s).flags.start_shaded_dir = (x)) #define SGET_STARTS_SHADED_DIR(s) \ ((s).flags.start_shaded_dir) #define SGET_MIN_ICON_WIDTH(s) \ ((s).min_icon_width) #define SSET_MIN_ICON_WIDTH(s,x) \ ((s).min_icon_width = (x)) #define SGET_MIN_ICON_HEIGHT(s) \ ((s).min_icon_height) #define SSET_MIN_ICON_HEIGHT(s,x) \ ((s).min_icon_height = (x)) #define SGET_MAX_ICON_WIDTH(s) \ ((s).max_icon_width) #define SSET_MAX_ICON_WIDTH(s,x) \ ((s).max_icon_width = (x)) #define SGET_MAX_ICON_HEIGHT(s) \ ((s).max_icon_height) #define SSET_MAX_ICON_HEIGHT(s,x) \ ((s).max_icon_height = (x)) #define SGET_ICON_RESIZE_TYPE(s) \ ((s).icon_resize_type) #define SSET_ICON_RESIZE_TYPE(s,x) \ ((s).icon_resize_type = (x)) #define SGET_ICON_BACKGROUND_RELIEF(s) \ ((s).icon_background_relief) #define SSET_ICON_BACKGROUND_RELIEF(s,x) \ ((s).icon_background_relief = (x)) #define SGET_ICON_BACKGROUND_PADDING(s) \ ((s).icon_background_padding) #define SSET_ICON_BACKGROUND_PADDING(s,x) \ ((s).icon_background_padding = (x)) #define SGET_ICON_TITLE_RELIEF(s) \ ((s).icon_title_relief) #define SSET_ICON_TITLE_RELIEF(s,x) \ ((s).icon_title_relief = (x)) #define SGET_MIN_WINDOW_WIDTH(s) \ ((s).min_window_width) #define SSET_MIN_WINDOW_WIDTH(s,x) \ ((s).min_window_width = (x)) #define SGET_MAX_WINDOW_WIDTH(s) \ ((s).max_window_width) #define SSET_MAX_WINDOW_WIDTH(s,x) \ ((s).max_window_width = (x)) #define SGET_MIN_WINDOW_HEIGHT(s) \ ((s).min_window_height) #define SSET_MIN_WINDOW_HEIGHT(s,x) \ ((s).min_window_height = (x)) #define SGET_MAX_WINDOW_HEIGHT(s) \ ((s).max_window_height) #define SSET_MAX_WINDOW_HEIGHT(s,x) \ ((s).max_window_height = (x)) #define SGET_WINDOW_SHADE_STEPS(s) \ ((s).shade_anim_steps) #define SSET_WINDOW_SHADE_STEPS(s,x) \ ((s).shade_anim_steps = (x)) #define SGET_SNAP_PROXIMITY(s) \ ((s).snap_attraction.proximity) #define SSET_SNAP_PROXIMITY(s,x) \ ((s).snap_attraction.proximity = (x)) #define SGET_SNAP_MODE(s) \ ((s).snap_attraction.mode) #define SSET_SNAP_MODE(s,x) \ ((s).snap_attraction.mode = (x)) #define SGET_SNAP_GRID_X(s) \ ((s).snap_grid_x) #define SSET_SNAP_GRID_X(s,x) \ ((s).snap_grid_x = (x)) #define SGET_SNAP_GRID_Y(s) \ ((s).snap_grid_y) #define SSET_SNAP_GRID_Y(s,x) \ ((s).snap_grid_y = (x)) #define SGET_EDGE_DELAY_MS_MOVE(s) \ ((s).edge_delay_ms_move) #define SSET_EDGE_DELAY_MS_MOVE(s,x) \ ((s).edge_delay_ms_move = (x)) #define SGET_EDGE_DELAY_MS_RESIZE(s) \ ((s).edge_delay_ms_resize) #define SSET_EDGE_DELAY_MS_RESIZE(s,x) \ ((s).edge_delay_ms_resize = (x)) #define SGET_EDGE_RESISTANCE_MOVE(s) \ ((s).edge_resistance_move) #define SSET_EDGE_RESISTANCE_MOVE(s,x) \ ((s).edge_resistance_move = (x)) #define SGET_EDGE_RESISTANCE_XINERAMA_MOVE(s) \ ((s).edge_resistance_xinerama_move) #define SSET_EDGE_RESISTANCE_XINERAMA_MOVE(s,x) \ ((s).edge_resistance_xinerama_move = (x)) #define SGET_ICON_BOXES(s) \ ((s).icon_boxes) #define SSET_ICON_BOXES(s,x) \ ((s).icon_boxes = (x)) #define SGET_PLACEMENT_PENALTY_PTR(s) \ (&(s).pl_penalty) #define SGET_NORMAL_PLACEMENT_PENALTY(s) \ ((s).pl_penalty.normal) #define SGET_ONTOP_PLACEMENT_PENALTY(s) \ ((s).pl_penalty.ontop) #define SGET_ICON_PLACEMENT_PENALTY(s) \ ((s).pl_penalty.icon) #define SGET_STICKY_PLACEMENT_PENALTY(s) \ ((s).pl_penalty.sticky) #define SGET_BELOW_PLACEMENT_PENALTY(s) \ ((s).pl_penalty.below) #define SGET_EWMH_STRUT_PLACEMENT_PENALTY(s) \ ((s).pl_penalty.strut) #define SSET_NORMAL_PLACEMENT_PENALTY(s,x) \ ((s).pl_penalty.normal = (x)) #define SSET_ONTOP_PLACEMENT_PENALTY(s,x) \ ((s).pl_penalty.ontop = (x)) #define SSET_ICON_PLACEMENT_PENALTY(s,x) \ ((s).pl_penalty.icon = (x)) #define SSET_STICKY_PLACEMENT_PENALTY(s,x) \ ((s).pl_penalty.sticky = (x)) #define SSET_BELOW_PLACEMENT_PENALTY(s,x) \ ((s).pl_penalty.below = (x)) #define SSET_EWMH_STRUT_PLACEMENT_PENALTY(s,x) \ ((s).pl_penalty.strut = (x)) #define SGET_PLACEMENT_PERCENTAGE_PENALTY_PTR(s) \ (&(s).pl_percent_penalty) #define SGET_99_PLACEMENT_PERCENTAGE_PENALTY(s) \ ((s).pl_percent_penalty.p99) #define SGET_95_PLACEMENT_PERCENTAGE_PENALTY(s) \ ((s).pl_percent_penalty.p95) #define SGET_85_PLACEMENT_PERCENTAGE_PENALTY(s) \ ((s).pl_percent_penalty.p85) #define SGET_75_PLACEMENT_PERCENTAGE_PENALTY(s) \ ((s).pl_percent_penalty.p75) #define SSET_99_PLACEMENT_PERCENTAGE_PENALTY(s,x) \ ((s).pl_percent_penalty.p99 = (x)) #define SSET_95_PLACEMENT_PERCENTAGE_PENALTY(s,x) \ ((s).pl_percent_penalty.p95 = (x)) #define SSET_85_PLACEMENT_PERCENTAGE_PENALTY(s,x) \ ((s).pl_percent_penalty.p85 = (x)) #define SSET_75_PLACEMENT_PERCENTAGE_PENALTY(s,x) \ ((s).pl_percent_penalty.p75 = (x)) #define SGET_PLACEMENT_POSITION_STRING(s) \ ((s).pl_position_string) #define SSET_PLACEMENT_POSITION_STRING(s,x) \ ((s).pl_position_string = (x)) #define SGET_INITIAL_MAP_COMMAND_STRING(s) \ ((s).initial_map_command_string) #define SSET_INITIAL_MAP_COMMAND_STRING(s,x) \ ((s).initial_map_command_string = (x)) #define SGET_TITLE_FORMAT_STRING(s) \ ((s).title_format_string) #define SSET_TITLE_FORMAT_STRING(s,x) \ ((s).title_format_string = (x)) #define SGET_ICON_TITLE_FORMAT_STRING(s) \ ((s).icon_title_format_string) #define SSET_ICON_TITLE_FORMAT_STRING(s,x) \ ((s).icon_title_format_string = (x)) /* function prototypes */ void lookup_style(FvwmWindow *fw, window_style *styles); Bool blockcmpmask(char *blk1, char *blk2, char *mask, int length); void check_window_style_change( FvwmWindow *t, update_win *flags, window_style *ret_style); void reset_style_changes(void); void update_style_colorset(int colorset); void update_window_color_style(FvwmWindow *fw, window_style *style); void update_window_color_hi_style(FvwmWindow *fw, window_style *style); void update_icon_title_cs_style(FvwmWindow *fw, window_style *pstyle); void update_icon_title_cs_hi_style(FvwmWindow *fw, window_style *pstyle); void update_icon_background_cs_style(FvwmWindow *fw, window_style *pstyle); void free_icon_boxes(icon_boxes *ib); void style_destroy_style(style_id_t s_id); void print_styles(int verbose); #endif /* _STYLE_ */ fvwm-2.7.0/fvwm/menugeometry.h0000644000175000017500000000244514147024700013274 00000000000000/* -*-c-*- */ #ifndef MENU_GEOMETRY_H #define MENU_GEOMETRY_H /* ---------------------------- included header files ---------------------- */ /* Do not #include any files - the file including this file has to take care of * it. */ /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- forward declarations ----------------------- */ struct MenuRoot; struct MenuParameters; /* ---------------------------- type definitions --------------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* Do not use global variable. Full stop. */ /* ---------------------------- interface functions ------------------------ */ /* * All functions in this file are to be used from menu*.c *only* */ Bool menu_get_geometry( struct MenuRoot *mr, Window *root_return, int *x_return, int *y_return, int *width_return, int *height_return, int *border_width_return, int *depth_return); Bool menu_get_outer_geometry( struct MenuRoot *mr, struct MenuParameters *pmp, Window *root_return, int *x_return, int *y_return, int *width_return, int *height_return, int *border_width_return, int *depth_return); #endif /* MENU_GEOMETRY_H */ fvwm-2.7.0/fvwm/infostore.c0000644000175000017500000001102514147024700012551 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include "fvwm.h" #include "externs.h" #include "libs/FGettext.h" #include "libs/Parse.h" #include "libs/Strings.h" #include "infostore.h" #include "misc.h" #include "functions.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ static MetaInfo *mi_store; /* ---------------------------- forward declarations ----------------------- */ static void delete_metainfo(const char *); /* ---------------------------- local variables ---------------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ MetaInfo *new_metainfo(void) { MetaInfo *mi; mi = (MetaInfo *)safemalloc(sizeof(MetaInfo)); memset(mi, '\0', sizeof(MetaInfo)); return mi; } void insert_metainfo(char *key, char *value) { MetaInfo *mi; MetaInfo *mi_new; for (mi = mi_store; mi; mi = mi->next) { if (StrEquals(mi->key, key)) { /* We already have an entry in the list with that key, so * update the value of it only. */ free (mi->value); CopyString(&mi->value, value); return; } } /* It's a new item, add it to the list. */ mi_new = new_metainfo(); mi_new->key = key; CopyString(&mi_new->value, value); mi_new->next = mi_store; mi_store = mi_new; return; } static void delete_metainfo(const char *key) { MetaInfo *mi_current, *mi_prev; mi_prev = NULL; for(mi_current = mi_store; mi_current != NULL; mi_prev = mi_current, mi_current = mi_current->next) { if (StrEquals(mi_current->key, key)) { if (mi_prev == NULL) mi_store = mi_current->next; else mi_prev->next = mi_current->next; free(mi_current->key); free(mi_current->value); free(mi_current); break; } } return; } inline char *get_metainfo_value(const char *key) { MetaInfo *mi_current; for(mi_current = mi_store; mi_current; mi_current = mi_current->next) { if (StrEquals(mi_current->key, key)) return mi_current->value; } return NULL; } int get_metainfo_length(void) { MetaInfo *mi; int count; count = 0; for(mi = mi_store; mi; mi = mi->next) count++; return count; } MetaInfo * get_metainfo(void) { return mi_store; } void print_infostore(void) { MetaInfo *mi; fprintf(stderr, "Current items in infostore (key, value):\n\n"); if (get_metainfo_length() == 0) { fprintf(stderr, "No items are currently stored in the infostore.\n"); return; } for(mi = mi_store; mi; mi = mi->next) { fprintf(stderr, "%s\t%s\n", mi->key, mi->value); } return; } /* ---------------------------- interface functions ------------------------ */ /* ---------------------------- builtin commands --------------------------- */ void CMD_InfoStoreAdd(F_CMD_ARGS) { char *key, *value; char *token; token = PeekToken(action, &action); key = value = NULL; if (token) key = strdup(token); token = PeekToken(action, &action); if (token) value = strdup(token); if (!key || !value) { fvwm_msg(ERR, "CMD_InfoStore", "Bad arguments given."); return; } insert_metainfo(key, value); free(value); return; } void CMD_InfoStoreRemove(F_CMD_ARGS) { char *token; token = PeekToken(action, &action); if (!token) { fvwm_msg(ERR, "CMD_InfoStoreRemove", "No key given to remove item."); return; } delete_metainfo(token); return; } void CMD_InfoStoreClear(F_CMD_ARGS) { MetaInfo *mi; if (get_metainfo_length() == 0) return; for (mi = mi_store; mi; mi = mi->next) delete_metainfo(mi->key); } fvwm-2.7.0/fvwm/style.c0000644000175000017500000042305214147024700011710 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* code for parsing the fvwm style command */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include "libs/fvwmlib.h" #include "libs/FScreen.h" #include "libs/charmap.h" #include "libs/modifiers.h" #include "libs/ColorUtils.h" #include "libs/Parse.h" #include "libs/wild.h" #include "fvwm.h" #include "execcontext.h" #include "misc.h" #include "screen.h" #include "update.h" #include "style.h" #include "colorset.h" #include "ewmh.h" #include "placement.h" /* ---------------------------- local definitions -------------------------- */ #define SAFEFREE( p ) {if (p) {free(p);(p)=NULL;}} /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* list of window names with attributes */ static window_style *all_styles = NULL; static window_style *last_style_in_list = NULL; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ static Bool __validate_titleformat_string(const char *formatstr) { const char *fmt; /* Setting this to "True" here ensures we don't erroneously report on * an invalid TitleFormat string which contains no placeholders * whatsoever. */ Bool ret_condition = True; for (fmt = formatstr; *fmt; fmt++) { if (*fmt != '%') continue; switch (*++fmt) { case 'c': case 'n': case 'r': case 't': case 'i': case 'I': ret_condition = True; break; default: ret_condition = False; break; } } return ret_condition; } static int blockor(char *dest, char *blk1, char *blk2, int length) { int i; char result = 0; for (i = 0; i < length; i++) { dest[i] = (blk1[i] | blk2[i]); result |= dest[i]; } return (result) ? 1 : 0; } static int blockand(char *dest, char *blk1, char *blk2, int length) { int i; char result = 0; for (i = 0; i < length; i++) { dest[i] = (blk1[i] & blk2[i]); result |= dest[i]; } return (result) ? 1 : 0; } static int blockunmask(char *dest, char *blk1, char *blk2, int length) { int i; char result = (char)0xff; for (i = 0; i < length; i++) { dest[i] = (blk1[i] & ~blk2[i]); result |= dest[i]; } return (result) ? 1 : 0; } static int blockissubset(char *sub, char *super, int length) { int i; for (i = 0; i < length; i++) { if ((sub[i] & super[i]) != sub[i]) { return 0; } } return 1; } static int blocksintersect(char *blk1, char *blk2, int length) { int i; for (i = 0; i < length; i++) { if (blk1[i] & blk2[i]) { return 1; } } return 0; } static int style_ids_are_equal(style_id_t *a, style_id_t *b) { if ( SID_GET_HAS_NAME(*a) && SID_GET_HAS_NAME(*b) && !strcmp(SID_GET_NAME(*a), SID_GET_NAME(*b))) { return 1; } if ( SID_GET_HAS_WINDOW_ID(*a) && SID_GET_HAS_WINDOW_ID(*b) && SID_GET_WINDOW_ID(*a) == SID_GET_WINDOW_ID(*b)) { return 1; } return 0; } static int style_id_equals_id(window_style *s, style_id_t* id) { return style_ids_are_equal(&SGET_ID(*s), id); } static int styles_have_same_id(window_style* s, window_style* t) { return style_ids_are_equal(&SGET_ID(*s), &SGET_ID(*t)); } static int fw_match_style_id(FvwmWindow *fw, style_id_t s_id) { if (SID_GET_HAS_NAME(s_id)) { if (matchWildcards(SID_GET_NAME(s_id), fw->class.res_class) == 1) { return 1; } if (matchWildcards(SID_GET_NAME(s_id), fw->class.res_name) == 1) { return 1; } if (matchWildcards(SID_GET_NAME(s_id), fw->visible_name) == 1) { return 1; } if (matchWildcards(SID_GET_NAME(s_id), fw->name.name) == 1) { return 1; } if (fw->style_name != NULL && matchWildcards(SID_GET_NAME(s_id), fw->style_name) == 1) { return 1; } } if (SID_GET_HAS_WINDOW_ID(s_id) && SID_GET_WINDOW_ID(s_id) == (XID)FW_W(fw)) { return 1; } return 0; } static int one_fw_can_match_both_ids(window_style *s, window_style *t) { if (SGET_ID_HAS_WINDOW_ID(*s) && SGET_ID_HAS_WINDOW_ID(*t) && SGET_WINDOW_ID(*s) != SGET_WINDOW_ID(*t)) { return 0; } return 1; } static void remove_icon_boxes_from_style(window_style *pstyle) { if (SHAS_ICON_BOXES(&pstyle->flags)) { free_icon_boxes(SGET_ICON_BOXES(*pstyle)); pstyle->flags.has_icon_boxes = 0; SSET_ICON_BOXES(*pstyle, NULL); } return; } static void copy_icon_boxes(icon_boxes **pdest, icon_boxes *src) { icon_boxes *last = NULL; icon_boxes *temp; *pdest = NULL; /* copy the icon boxes */ for ( ; src != NULL; src = src->next) { temp = (icon_boxes *)safemalloc(sizeof(icon_boxes)); memcpy(temp, src, sizeof(icon_boxes)); temp->next = NULL; if (last != NULL) last->next = temp; else *pdest = temp; last = temp; } } /* Check word after IconFill to see if its "Top,Bottom,Left,Right" */ static int Get_TBLR(char *token, unsigned char *IconFill) { /* init */ if (StrEquals(token, "B") || StrEquals(token, "BOT")|| StrEquals(token, "BOTTOM")) { /* turn on bottom and verical */ *IconFill = ICONFILLBOT | ICONFILLHRZ; } else if (StrEquals(token, "T") || StrEquals(token, "TOP")) { /* turn on vertical */ *IconFill = ICONFILLHRZ; } else if (StrEquals(token, "R") || StrEquals(token, "RGT") || StrEquals(token, "RIGHT")) { /* turn on right bit */ *IconFill = ICONFILLRGT; } else if (StrEquals(token, "L") || StrEquals(token, "LFT") || StrEquals(token, "LEFT")) { *IconFill = 0; } else { /* anything else is bad */ return 0; } /* return OK */ return 1; } static void cleanup_style_defaults(window_style *style) { int i; char *dflt; char *mask; mask = (char *)&(style->flag_mask); dflt = (char *)&(style->flag_default); for (i = 0; i < sizeof(style_flags); i++) { dflt[i] &= ~mask[i]; } return; } /* merge_styles - For a matching style, merge window_style to window_style * * Returned Value: * merged matching styles in callers window_style. * * Inputs: * merged_style - style resulting from the merge * add_style - the style to be added into the merge_style * do_free_src_and_alloc_copy * - free allocated parts of merge_style that are replaced * from add_style. Create a copy of of the replaced * styles in allocated memory. * * Note: * The only trick here is that on and off flags/buttons are * combined into the on flag/button. */ static void merge_styles( window_style *merged_style, window_style *add_style, Bool do_free_src_and_alloc_copy) { int i; char *merge_flags; char *add_flags; char *merge_mask; char *add_mask; char *merge_dflt; char *add_dflt; char *merge_change_mask; char *add_change_mask; if (add_style->flag_mask.has_icon) { if (do_free_src_and_alloc_copy) { SAFEFREE(SGET_ICON_NAME(*merged_style)); SSET_ICON_NAME( *merged_style, (SGET_ICON_NAME(*add_style)) ? safestrdup(SGET_ICON_NAME(*add_style)) : NULL); } else { SSET_ICON_NAME( *merged_style, SGET_ICON_NAME(*add_style)); } } if (FMiniIconsSupported && add_style->flag_mask.has_mini_icon) { if (do_free_src_and_alloc_copy) { SAFEFREE(SGET_MINI_ICON_NAME(*merged_style)); SSET_MINI_ICON_NAME( *merged_style, (SGET_MINI_ICON_NAME(*add_style)) ? safestrdup(SGET_MINI_ICON_NAME(*add_style)) : NULL); } else { SSET_MINI_ICON_NAME( *merged_style, SGET_MINI_ICON_NAME(*add_style)); } } if (add_style->flag_mask.has_decor) { if (do_free_src_and_alloc_copy) { SAFEFREE(SGET_DECOR_NAME(*merged_style)); SSET_DECOR_NAME( *merged_style, (SGET_DECOR_NAME(*add_style)) ? safestrdup(SGET_DECOR_NAME(*add_style)) : NULL); } else { SSET_DECOR_NAME( *merged_style, SGET_DECOR_NAME(*add_style)); } } if (S_HAS_ICON_FONT(SCF(*add_style))) { if (do_free_src_and_alloc_copy) { SAFEFREE(SGET_ICON_FONT(*merged_style)); SSET_ICON_FONT( *merged_style, (SGET_ICON_FONT(*add_style)) ? safestrdup(SGET_ICON_FONT(*add_style)) : NULL); } else { SSET_ICON_FONT( *merged_style, SGET_ICON_FONT(*add_style)); } } if (S_HAS_WINDOW_FONT(SCF(*add_style))) { if (do_free_src_and_alloc_copy) { SAFEFREE(SGET_WINDOW_FONT(*merged_style)); SSET_WINDOW_FONT( *merged_style, (SGET_WINDOW_FONT(*add_style)) ? safestrdup(SGET_WINDOW_FONT(*add_style)) : NULL); } else { SSET_WINDOW_FONT( *merged_style, SGET_WINDOW_FONT(*add_style)); } } if (add_style->flags.use_start_on_desk) { SSET_START_DESK(*merged_style, SGET_START_DESK(*add_style)); SSET_START_PAGE_X( *merged_style, SGET_START_PAGE_X(*add_style)); SSET_START_PAGE_Y( *merged_style, SGET_START_PAGE_Y(*add_style)); } if (add_style->flags.use_start_on_screen) { SSET_START_SCREEN (*merged_style, SGET_START_SCREEN(*add_style)); } if (add_style->flag_mask.has_color_fore) { if (do_free_src_and_alloc_copy) { SAFEFREE(SGET_FORE_COLOR_NAME(*merged_style)); SSET_FORE_COLOR_NAME( *merged_style, (SGET_FORE_COLOR_NAME(*add_style)) ? safestrdup(SGET_FORE_COLOR_NAME(*add_style)) : NULL); } else { SSET_FORE_COLOR_NAME( *merged_style, SGET_FORE_COLOR_NAME(*add_style)); } } if (add_style->flag_mask.has_color_back) { if (do_free_src_and_alloc_copy) { SAFEFREE(SGET_BACK_COLOR_NAME(*merged_style)); SSET_BACK_COLOR_NAME( *merged_style, (SGET_BACK_COLOR_NAME(*add_style)) ? safestrdup(SGET_BACK_COLOR_NAME(*add_style)) : NULL); } else { SSET_BACK_COLOR_NAME( *merged_style, SGET_BACK_COLOR_NAME(*add_style)); } } if (add_style->flag_mask.has_color_fore_hi) { if (do_free_src_and_alloc_copy) { SAFEFREE(SGET_FORE_COLOR_NAME_HI(*merged_style)); SSET_FORE_COLOR_NAME_HI( *merged_style, (SGET_FORE_COLOR_NAME_HI(*add_style)) ? safestrdup( SGET_FORE_COLOR_NAME_HI(*add_style)) : NULL); } else { SSET_FORE_COLOR_NAME_HI( *merged_style, SGET_FORE_COLOR_NAME_HI(*add_style)); } } if (add_style->flag_mask.has_color_back_hi) { if (do_free_src_and_alloc_copy) { SAFEFREE(SGET_BACK_COLOR_NAME_HI(*merged_style)); SSET_BACK_COLOR_NAME_HI( *merged_style, (SGET_BACK_COLOR_NAME_HI(*add_style)) ? safestrdup( SGET_BACK_COLOR_NAME_HI(*add_style)) : NULL); } else { SSET_BACK_COLOR_NAME_HI( *merged_style, SGET_BACK_COLOR_NAME_HI(*add_style)); } } if (add_style->flags.has_border_width) { SSET_BORDER_WIDTH( *merged_style, SGET_BORDER_WIDTH(*add_style)); } if (add_style->flags.has_handle_width) { SSET_HANDLE_WIDTH( *merged_style, SGET_HANDLE_WIDTH(*add_style)); } if (add_style->flags.has_icon_size_limits) { SSET_MIN_ICON_WIDTH( *merged_style, SGET_MIN_ICON_WIDTH(*add_style)); SSET_MIN_ICON_HEIGHT( *merged_style, SGET_MIN_ICON_HEIGHT(*add_style)); SSET_MAX_ICON_WIDTH( *merged_style, SGET_MAX_ICON_WIDTH(*add_style)); SSET_MAX_ICON_HEIGHT( *merged_style, SGET_MAX_ICON_HEIGHT(*add_style)); SSET_ICON_RESIZE_TYPE( *merged_style, SGET_ICON_RESIZE_TYPE(*add_style)); } if (add_style->flags.has_min_window_size) { SSET_MIN_WINDOW_WIDTH( *merged_style, SGET_MIN_WINDOW_WIDTH(*add_style)); SSET_MIN_WINDOW_HEIGHT( *merged_style, SGET_MIN_WINDOW_HEIGHT(*add_style)); } if (add_style->flags.has_max_window_size) { SSET_MAX_WINDOW_WIDTH( *merged_style, SGET_MAX_WINDOW_WIDTH(*add_style)); SSET_MAX_WINDOW_HEIGHT( *merged_style, SGET_MAX_WINDOW_HEIGHT(*add_style)); } if (add_style->flags.has_icon_background_relief) { SSET_ICON_BACKGROUND_RELIEF( *merged_style, SGET_ICON_BACKGROUND_RELIEF(*add_style)); } if (add_style->flags.has_icon_background_padding) { SSET_ICON_BACKGROUND_PADDING( *merged_style, SGET_ICON_BACKGROUND_PADDING(*add_style)); } if (add_style->flags.has_icon_title_relief) { SSET_ICON_TITLE_RELIEF( *merged_style, SGET_ICON_TITLE_RELIEF(*add_style)); } if (add_style->flags.has_window_shade_steps) { SSET_WINDOW_SHADE_STEPS( *merged_style, SGET_WINDOW_SHADE_STEPS(*add_style)); } if (add_style->flags.has_snap_attraction) { SSET_SNAP_PROXIMITY( *merged_style, SGET_SNAP_PROXIMITY(*add_style)); SSET_SNAP_MODE( *merged_style, SGET_SNAP_MODE(*add_style)); } if (add_style->flags.has_snap_grid) { SSET_SNAP_GRID_X( *merged_style, SGET_SNAP_GRID_X(*add_style)); SSET_SNAP_GRID_Y( *merged_style, SGET_SNAP_GRID_Y(*add_style)); } if (add_style->flags.has_edge_delay_ms_move) { SSET_EDGE_DELAY_MS_MOVE( *merged_style, SGET_EDGE_DELAY_MS_MOVE(*add_style)); } if (add_style->flags.has_edge_delay_ms_resize) { SSET_EDGE_DELAY_MS_RESIZE( *merged_style, SGET_EDGE_DELAY_MS_RESIZE(*add_style)); } if (add_style->flags.has_edge_resistance_move) { SSET_EDGE_RESISTANCE_MOVE( *merged_style, SGET_EDGE_RESISTANCE_MOVE(*add_style)); } if (add_style->flags.has_edge_resistance_xinerama_move) { SSET_EDGE_RESISTANCE_XINERAMA_MOVE( *merged_style, SGET_EDGE_RESISTANCE_XINERAMA_MOVE(*add_style)); } /* Note: Only one style cmd can define a window's iconboxes, the last * one encountered. */ if (SHAS_ICON_BOXES(&add_style->flag_mask)) { /* If style has iconboxes */ /* copy it */ if (do_free_src_and_alloc_copy) { remove_icon_boxes_from_style(merged_style); copy_icon_boxes( &SGET_ICON_BOXES(*merged_style), SGET_ICON_BOXES(*add_style)); } else { SSET_ICON_BOXES( *merged_style, SGET_ICON_BOXES(*add_style)); } } if (add_style->flags.use_layer) { SSET_LAYER(*merged_style, SGET_LAYER(*add_style)); } if (add_style->flags.do_start_shaded) { SSET_STARTS_SHADED_DIR( *merged_style, SGET_STARTS_SHADED_DIR(*add_style)); } if (add_style->flags.use_colorset) { SSET_COLORSET(*merged_style, SGET_COLORSET(*add_style)); } if (add_style->flags.use_colorset_hi) { SSET_COLORSET_HI(*merged_style, SGET_COLORSET_HI(*add_style)); } if (add_style->flags.use_border_colorset) { SSET_BORDER_COLORSET( *merged_style, SGET_BORDER_COLORSET(*add_style)); } if (add_style->flags.use_border_colorset_hi) { SSET_BORDER_COLORSET_HI( *merged_style,SGET_BORDER_COLORSET_HI(*add_style)); } if (add_style->flags.use_icon_title_colorset) { SSET_ICON_TITLE_COLORSET( *merged_style,SGET_ICON_TITLE_COLORSET(*add_style)); } if (add_style->flags.use_icon_title_colorset_hi) { SSET_ICON_TITLE_COLORSET_HI( *merged_style,SGET_ICON_TITLE_COLORSET_HI(*add_style)); } if (add_style->flags.use_icon_background_colorset) { SSET_ICON_BACKGROUND_COLORSET( *merged_style,SGET_ICON_BACKGROUND_COLORSET( *add_style)); } if (add_style->flags.has_placement_penalty) { SSET_NORMAL_PLACEMENT_PENALTY( *merged_style, SGET_NORMAL_PLACEMENT_PENALTY(*add_style)); SSET_ONTOP_PLACEMENT_PENALTY( *merged_style, SGET_ONTOP_PLACEMENT_PENALTY(*add_style)); SSET_ICON_PLACEMENT_PENALTY( *merged_style, SGET_ICON_PLACEMENT_PENALTY( *add_style)); SSET_STICKY_PLACEMENT_PENALTY( *merged_style, SGET_STICKY_PLACEMENT_PENALTY(*add_style)); SSET_BELOW_PLACEMENT_PENALTY( *merged_style, SGET_BELOW_PLACEMENT_PENALTY(*add_style)); SSET_EWMH_STRUT_PLACEMENT_PENALTY( *merged_style, SGET_EWMH_STRUT_PLACEMENT_PENALTY(*add_style)); } if (add_style->flags.has_placement_percentage_penalty) { SSET_99_PLACEMENT_PERCENTAGE_PENALTY( *merged_style, SGET_99_PLACEMENT_PERCENTAGE_PENALTY(*add_style)); SSET_95_PLACEMENT_PERCENTAGE_PENALTY( *merged_style, SGET_95_PLACEMENT_PERCENTAGE_PENALTY(*add_style)); SSET_85_PLACEMENT_PERCENTAGE_PENALTY( *merged_style, SGET_85_PLACEMENT_PERCENTAGE_PENALTY(*add_style)); SSET_75_PLACEMENT_PERCENTAGE_PENALTY( *merged_style, SGET_75_PLACEMENT_PERCENTAGE_PENALTY(*add_style)); } if (add_style->flags.has_placement_position_string) { SAFEFREE(SGET_PLACEMENT_POSITION_STRING(*merged_style)); SSET_PLACEMENT_POSITION_STRING( *merged_style, strdup(SGET_PLACEMENT_POSITION_STRING(*add_style))); } if (add_style->flags.has_initial_map_command_string) { SAFEFREE(SGET_INITIAL_MAP_COMMAND_STRING(*merged_style)); SSET_INITIAL_MAP_COMMAND_STRING( *merged_style, strdup(SGET_INITIAL_MAP_COMMAND_STRING(*add_style))); } if (add_style->flags.has_title_format_string) { SAFEFREE(SGET_TITLE_FORMAT_STRING(*merged_style)); SSET_TITLE_FORMAT_STRING(*merged_style, strdup(SGET_TITLE_FORMAT_STRING(*add_style))); } if (add_style->flags.has_icon_title_format_string) { SAFEFREE(SGET_ICON_TITLE_FORMAT_STRING(*merged_style)); SSET_ICON_TITLE_FORMAT_STRING(*merged_style, strdup(SGET_ICON_TITLE_FORMAT_STRING(*add_style))); } /* merge the style flags */ /*** ATTENTION: *** This must be the last thing that is done in this function! */ merge_flags = (char *)&(merged_style->flags); add_flags = (char *)&(add_style->flags); merge_mask = (char *)&(merged_style->flag_mask); add_mask = (char *)&(add_style->flag_mask); merge_dflt = (char *)&(merged_style->flag_default); add_dflt = (char *)&(add_style->flag_default); merge_change_mask = (char *)&(merged_style->change_mask); add_change_mask = (char *)&(add_style->change_mask); for (i = 0; i < sizeof(style_flags); i++) { char m; /* overwrite set styles */ merge_flags[i] |= (add_flags[i] & add_mask[i]); merge_flags[i] &= (add_flags[i] | ~add_mask[i]); /* overwrite default values */ m = add_dflt[i] & ~add_mask[i] & ~merge_mask[i]; merge_flags[i] |= (add_flags[i] & m); merge_flags[i] &= (add_flags[i] | ~m); /* overwrite even weaker default values */ m = ~add_dflt[i] & ~add_mask[i] & ~merge_dflt[i] & ~merge_mask[i]; merge_flags[i] |= (add_flags[i] & m); merge_flags[i] &= (add_flags[i] | ~m); /* other flags */ merge_change_mask[i] &= ~(add_mask[i]); merge_change_mask[i] |= add_change_mask[i]; merge_mask[i] |= add_mask[i]; merge_dflt[i] |= add_dflt[i]; merge_dflt[i] &= ~merge_mask[i]; } merged_style->has_style_changed |= add_style->has_style_changed; return; } static void free_style(window_style *style) { /* Free contents of style */ SAFEFREE(SGET_NAME(*style)); SAFEFREE(SGET_BACK_COLOR_NAME(*style)); SAFEFREE(SGET_FORE_COLOR_NAME(*style)); SAFEFREE(SGET_BACK_COLOR_NAME_HI(*style)); SAFEFREE(SGET_FORE_COLOR_NAME_HI(*style)); SAFEFREE(SGET_DECOR_NAME(*style)); SAFEFREE(SGET_ICON_FONT(*style)); SAFEFREE(SGET_WINDOW_FONT(*style)); SAFEFREE(SGET_ICON_NAME(*style)); SAFEFREE(SGET_MINI_ICON_NAME(*style)); remove_icon_boxes_from_style(style); SAFEFREE(SGET_PLACEMENT_POSITION_STRING(*style)); SAFEFREE(SGET_INITIAL_MAP_COMMAND_STRING(*style)); SAFEFREE(SGET_TITLE_FORMAT_STRING(*style)); SAFEFREE(SGET_ICON_TITLE_FORMAT_STRING(*style)); return; } /* Frees only selected members of a style; adjusts the flag_mask and * change_mask appropriately. */ static void free_style_mask(window_style *style, style_flags *mask) { style_flags local_mask; style_flags *pmask; /* mask out all bits that are not set in the target style */ pmask =&local_mask; blockand((char *)pmask, (char *)&style->flag_mask, (char *)mask, sizeof(style_flags)); /* Free contents of style */ if (pmask->has_color_back) { SAFEFREE(SGET_BACK_COLOR_NAME(*style)); } if (pmask->has_color_fore) { SAFEFREE(SGET_FORE_COLOR_NAME(*style)); } if (pmask->has_color_back_hi) { SAFEFREE(SGET_BACK_COLOR_NAME_HI(*style)); } if (pmask->has_color_fore_hi) { SAFEFREE(SGET_FORE_COLOR_NAME_HI(*style)); } if (pmask->has_decor) { SAFEFREE(SGET_DECOR_NAME(*style)); } if (pmask->common.has_icon_font) { SAFEFREE(SGET_ICON_FONT(*style)); } if (pmask->common.has_window_font) { SAFEFREE(SGET_WINDOW_FONT(*style)); } if (pmask->has_icon) { SAFEFREE(SGET_ICON_NAME(*style)); } if (pmask->has_mini_icon) { SAFEFREE(SGET_MINI_ICON_NAME(*style)); } if (pmask->has_icon_boxes) { remove_icon_boxes_from_style(style); } /* remove styles from definitiion */ blockunmask((char *)&style->flag_mask, (char *)&style->flag_mask, (char *)pmask, sizeof(style_flags)); blockunmask((char *)&style->flag_default, (char *)&style->flag_default, (char *)pmask, sizeof(style_flags)); blockunmask((char *)&style->change_mask, (char *)&style->change_mask, (char *)pmask, sizeof(style_flags)); return; } static void add_style_to_list(window_style *new_style) { /* This used to contain logic that returned if the style didn't contain * anything. I don't see why we should bother. dje. * * used to merge duplicate entries, but that is no longer * appropriate since conflicting styles are possible, and the * last match should win! */ if (last_style_in_list != NULL) { /* not first entry in list chain this entry to the list */ SSET_NEXT_STYLE(*last_style_in_list, new_style); } else { /* first entry in list set the list root pointer. */ all_styles = new_style; } SSET_PREV_STYLE(*new_style, last_style_in_list); SSET_NEXT_STYLE(*new_style, NULL); last_style_in_list = new_style; Scr.flags.do_need_style_list_update = 1; return; } /* end function */ static void remove_style_from_list(window_style *style, Bool do_free_style) { window_style *prev; window_style *next; prev = SGET_PREV_STYLE(*style); next = SGET_NEXT_STYLE(*style); if (!prev) { /* first style in list */ all_styles = next; } else { /* not first style in list */ SSET_NEXT_STYLE(*prev, next); } if (!next) { /* last style in list */ last_style_in_list = prev; } else { SSET_PREV_STYLE(*next, prev); } if (do_free_style) { free_style(style); free(style); } } static int remove_all_of_style_from_list(style_id_t style_id) { window_style *nptr = all_styles; window_style *next; int is_changed = 0; /* loop though styles */ while (nptr) { next = SGET_NEXT_STYLE(*nptr); /* Check if it's to be wiped */ if (style_id_equals_id(nptr, &style_id)) { remove_style_from_list(nptr, True); is_changed = 1; } /* move on */ nptr = next; } return is_changed; } static int __simplify_style_list(void) { window_style *cur; int has_modified; /* Step 1: * Remove styles that are completely overridden by later * style definitions. At the same time... * Step 2: * Merge styles with the same name if there are no * conflicting styles with other names set in between. */ for ( cur = last_style_in_list, has_modified = 0; cur; cur = SGET_PREV_STYLE(*cur)) { style_flags dummyflags; /* incremental flags set in styles with the same name */ style_flags sumflags; style_flags sumdflags; /* incremental flags set in styles with other names */ style_flags interflags; window_style *cmp; memset(&interflags, 0, sizeof(style_flags)); memcpy(&sumflags, &cur->flag_mask, sizeof(style_flags)); memcpy(&sumdflags, &cur->flag_default, sizeof(style_flags)); cmp = SGET_PREV_STYLE(*cur); while (cmp) { if (!styles_have_same_id(cur, cmp)) { if (one_fw_can_match_both_ids(cur, cmp)) { blockor((char *)&interflags, (char *)&interflags, (char *)&cmp->flag_mask, sizeof(style_flags)); blockor((char *)&interflags, (char *)&interflags, (char *)&cmp->flag_default, sizeof(style_flags)); } cmp = SGET_PREV_STYLE(*cmp); continue; } if (blockissubset( (char *)&cmp->flag_mask, (char *)&sumflags, sizeof(style_flags)) && blockissubset( (char *)&cmp->flag_default, (char *)&sumdflags, sizeof(style_flags))) { /* The style is a subset of later style * definitions; nuke it */ window_style *tmp = SGET_PREV_STYLE(*cmp); remove_style_from_list(cmp, True); cmp = tmp; has_modified = 1; continue; } /* remove all styles that are overridden later from the * style */ blockor((char *)&dummyflags, (char *)&sumdflags, (char *)&sumflags, sizeof(style_flags)); free_style_mask(cmp, &dummyflags); if ( !blocksintersect( (char *)&cmp->flag_mask, (char *)&interflags, sizeof(style_flags)) && !blocksintersect( (char *)&cmp->flag_default, (char *)&interflags, sizeof(style_flags))) { /* merge old style into new style */ window_style *tmp = SGET_PREV_STYLE(*cmp); window_style *prev = SGET_PREV_STYLE(*cur); window_style *next = SGET_NEXT_STYLE(*cur); /* Add the style to the set */ blockor((char *)&sumflags, (char *)&sumflags, (char *)&cmp->flag_mask, sizeof(style_flags)); blockor((char *)&sumdflags, (char *)&sumflags, (char *)&cmp->flag_default, sizeof(style_flags)); /* merge cmp into cur and delete it * afterwards */ merge_styles(cmp, cur, True); free_style(cur); memcpy(cur, cmp, sizeof(window_style)); /* restore fields overwritten by memcpy */ SSET_PREV_STYLE(*cur, prev); SSET_NEXT_STYLE(*cur, next); /* remove the style without freeing the * memory */ remove_style_from_list(cmp, False); /* release the style structure */ free(cmp); cmp = tmp; has_modified = 1; } else if ( !blocksintersect( (char *)&cur->flag_mask, (char *)&interflags, sizeof(style_flags)) && !blocksintersect( (char *)&cur->flag_default, (char *)&interflags, sizeof(style_flags))) { /* merge new style into old style */ window_style *tmp = SGET_PREV_STYLE(*cmp); /* Add the style to the set */ blockor((char *)&sumflags, (char *)&sumflags, (char *)&cur->flag_mask, sizeof(style_flags)); blockor((char *)&sumdflags, (char *)&sumflags, (char *)&cur->flag_default, sizeof(style_flags)); /* merge cur into cmp and delete it * afterwards */ merge_styles(cmp, cur, True); remove_style_from_list(cur, True); cur = cmp; cmp = tmp; has_modified = 1; memset(&interflags, 0, sizeof(style_flags)); continue; } else { /* Add it to the set of interfering styles. */ blockor((char *)&interflags, (char *)&interflags, (char *)&cmp->flag_mask, sizeof(style_flags)); blockor((char *)&interflags, (char *)&interflags, (char *)&cmp->flag_default, sizeof(style_flags)); cmp = SGET_PREV_STYLE(*cmp); } } } return has_modified; } static void style_set_old_focus_policy(window_style *ps, int policy) { focus_policy_t fp; switch (policy) { case 0: /* ClickToFocus */ FPS_FOCUS_ENTER(S_FOCUS_POLICY(SCF(*ps)), 0); FPS_UNFOCUS_LEAVE(S_FOCUS_POLICY(SCF(*ps)), 0); FPS_FOCUS_CLICK_CLIENT(S_FOCUS_POLICY(SCF(*ps)), 1); FPS_FOCUS_CLICK_DECOR(S_FOCUS_POLICY(SCF(*ps)), 1); FPS_FOCUS_CLICK_ICON(S_FOCUS_POLICY(SCF(*ps)), 1); FPS_FOCUS_BY_FUNCTION(S_FOCUS_POLICY(SCF(*ps)), 1); FPS_FOCUS_BY_PROGRAM(fp, 1); FPS_GRAB_FOCUS(fp, 1); FPS_RELEASE_FOCUS(fp, 1); FPS_RAISE_FOCUSED_CLIENT_CLICK(fp, 1); FPS_RAISE_UNFOCUSED_CLIENT_CLICK(fp, 1); FPS_RAISE_FOCUSED_DECOR_CLICK(fp, 1); FPS_RAISE_UNFOCUSED_DECOR_CLICK(fp, 1); FPS_PASS_FOCUS_CLICK(fp, 1); FPS_PASS_RAISE_CLICK(fp, 1); FPS_ALLOW_FUNC_FOCUS_CLICK(fp, 1); FPS_ALLOW_FUNC_RAISE_CLICK(fp, 1); FPS_WARP_POINTER_ON_FOCUS_FUNC(fp, 0); break; case 1: /* MouseFocus */ FPS_FOCUS_ENTER(S_FOCUS_POLICY(SCF(*ps)), 1); FPS_UNFOCUS_LEAVE(S_FOCUS_POLICY(SCF(*ps)), 1); FPS_FOCUS_CLICK_CLIENT(S_FOCUS_POLICY(SCF(*ps)), 0); FPS_FOCUS_CLICK_DECOR(S_FOCUS_POLICY(SCF(*ps)), 0); FPS_FOCUS_CLICK_ICON(S_FOCUS_POLICY(SCF(*ps)), 0); FPS_FOCUS_BY_FUNCTION(S_FOCUS_POLICY(SCF(*ps)), 1); FPS_FOCUS_BY_PROGRAM(fp, 1); FPS_GRAB_FOCUS(fp, 0); FPS_RELEASE_FOCUS(fp, 0); FPS_RAISE_FOCUSED_CLIENT_CLICK(fp, 0); FPS_RAISE_UNFOCUSED_CLIENT_CLICK(fp, 0); FPS_RAISE_FOCUSED_DECOR_CLICK(fp, 0); FPS_RAISE_UNFOCUSED_DECOR_CLICK(fp, 0); FPS_PASS_FOCUS_CLICK(fp, 1); FPS_PASS_RAISE_CLICK(fp, 1); FPS_ALLOW_FUNC_FOCUS_CLICK(fp, 0); FPS_ALLOW_FUNC_RAISE_CLICK(fp, 0); FPS_WARP_POINTER_ON_FOCUS_FUNC(fp, 1); break; case 2: /* SloppyFocus */ FPS_FOCUS_ENTER(S_FOCUS_POLICY(SCF(*ps)), 1); FPS_UNFOCUS_LEAVE(S_FOCUS_POLICY(SCF(*ps)), 0); FPS_FOCUS_CLICK_CLIENT(S_FOCUS_POLICY(SCF(*ps)), 0); FPS_FOCUS_CLICK_DECOR(S_FOCUS_POLICY(SCF(*ps)), 0); FPS_FOCUS_CLICK_ICON(S_FOCUS_POLICY(SCF(*ps)), 0); FPS_FOCUS_BY_FUNCTION(S_FOCUS_POLICY(SCF(*ps)), 1); FPS_FOCUS_BY_PROGRAM(fp, 1); FPS_GRAB_FOCUS(fp, 0); FPS_RELEASE_FOCUS(fp, 1); FPS_RAISE_FOCUSED_CLIENT_CLICK(fp, 0); FPS_RAISE_UNFOCUSED_CLIENT_CLICK(fp, 0); FPS_RAISE_FOCUSED_DECOR_CLICK(fp, 0); FPS_RAISE_UNFOCUSED_DECOR_CLICK(fp, 0); FPS_PASS_FOCUS_CLICK(fp, 1); FPS_PASS_RAISE_CLICK(fp, 1); FPS_ALLOW_FUNC_FOCUS_CLICK(fp, 0); FPS_ALLOW_FUNC_RAISE_CLICK(fp, 0); FPS_WARP_POINTER_ON_FOCUS_FUNC(fp, 1); break; case 3: /* NeverFocus */ FPS_FOCUS_ENTER(S_FOCUS_POLICY(SCF(*ps)), 0); FPS_UNFOCUS_LEAVE(S_FOCUS_POLICY(SCF(*ps)), 0); FPS_FOCUS_CLICK_CLIENT(S_FOCUS_POLICY(SCF(*ps)), 0); FPS_FOCUS_CLICK_DECOR(S_FOCUS_POLICY(SCF(*ps)), 0); FPS_FOCUS_CLICK_ICON(S_FOCUS_POLICY(SCF(*ps)), 0); FPS_FOCUS_BY_FUNCTION(S_FOCUS_POLICY(SCF(*ps)), 0); FPS_FOCUS_BY_PROGRAM(fp, 1); FPS_GRAB_FOCUS(fp, 0); FPS_RELEASE_FOCUS(fp, 0); FPS_RAISE_FOCUSED_CLIENT_CLICK(fp, 0); FPS_RAISE_UNFOCUSED_CLIENT_CLICK(fp, 0); FPS_RAISE_FOCUSED_DECOR_CLICK(fp, 0); FPS_RAISE_UNFOCUSED_DECOR_CLICK(fp, 0); FPS_PASS_FOCUS_CLICK(fp, 1); FPS_PASS_RAISE_CLICK(fp, 1); FPS_ALLOW_FUNC_FOCUS_CLICK(fp, 1); FPS_ALLOW_FUNC_RAISE_CLICK(fp, 1); FPS_WARP_POINTER_ON_FOCUS_FUNC(fp, 0); break; } FPS_FOCUS_ENTER(S_FOCUS_POLICY(SCM(*ps)), 1); FPS_FOCUS_ENTER(S_FOCUS_POLICY(SCC(*ps)), 1); FPS_UNFOCUS_LEAVE(S_FOCUS_POLICY(SCM(*ps)), 1); FPS_UNFOCUS_LEAVE(S_FOCUS_POLICY(SCC(*ps)), 1); FPS_FOCUS_CLICK_CLIENT(S_FOCUS_POLICY(SCM(*ps)), 1); FPS_FOCUS_CLICK_CLIENT(S_FOCUS_POLICY(SCC(*ps)), 1); FPS_FOCUS_CLICK_DECOR(S_FOCUS_POLICY(SCM(*ps)), 1); FPS_FOCUS_CLICK_DECOR(S_FOCUS_POLICY(SCC(*ps)), 1); FPS_FOCUS_CLICK_ICON(S_FOCUS_POLICY(SCM(*ps)), 1); FPS_FOCUS_CLICK_ICON(S_FOCUS_POLICY(SCC(*ps)), 1); FPS_FOCUS_BY_FUNCTION(S_FOCUS_POLICY(SCM(*ps)), 1); FPS_FOCUS_BY_FUNCTION(S_FOCUS_POLICY(SCC(*ps)), 1); if (!FP_DO_FOCUS_BY_PROGRAM(S_FOCUS_POLICY(SCM(*ps)))) { FPS_FOCUS_BY_PROGRAM( S_FOCUS_POLICY(SCF(*ps)), FP_DO_FOCUS_BY_PROGRAM(fp)); FPS_FOCUS_BY_PROGRAM(S_FOCUS_POLICY(SCD(*ps)), 1); FPS_FOCUS_BY_PROGRAM(S_FOCUS_POLICY(SCC(*ps)), 1); } if (!FP_DO_GRAB_FOCUS(S_FOCUS_POLICY(SCM(*ps)))) { FPS_GRAB_FOCUS(S_FOCUS_POLICY(SCF(*ps)), FP_DO_GRAB_FOCUS(fp)); FPS_GRAB_FOCUS(S_FOCUS_POLICY(SCD(*ps)), 1); FPS_GRAB_FOCUS(S_FOCUS_POLICY(SCC(*ps)), 1); } if (!FP_DO_RELEASE_FOCUS(S_FOCUS_POLICY(SCM(*ps)))) { FPS_RELEASE_FOCUS( S_FOCUS_POLICY(SCF(*ps)), FP_DO_RELEASE_FOCUS(fp)); FPS_RELEASE_FOCUS(S_FOCUS_POLICY(SCD(*ps)), 1); FPS_RELEASE_FOCUS(S_FOCUS_POLICY(SCC(*ps)), 1); } if (!FP_DO_RAISE_FOCUSED_CLIENT_CLICK(S_FOCUS_POLICY(SCM(*ps)))) { FPS_RAISE_FOCUSED_CLIENT_CLICK( S_FOCUS_POLICY(SCF(*ps)), FP_DO_RAISE_FOCUSED_CLIENT_CLICK(fp)); FPS_RAISE_FOCUSED_CLIENT_CLICK(S_FOCUS_POLICY(SCD(*ps)), 1); FPS_RAISE_FOCUSED_CLIENT_CLICK(S_FOCUS_POLICY(SCC(*ps)), 1); } if (!FP_DO_RAISE_UNFOCUSED_CLIENT_CLICK(S_FOCUS_POLICY(SCM(*ps)))) { FPS_RAISE_UNFOCUSED_CLIENT_CLICK( S_FOCUS_POLICY(SCF(*ps)), FP_DO_RAISE_UNFOCUSED_CLIENT_CLICK(fp)); FPS_RAISE_UNFOCUSED_CLIENT_CLICK(S_FOCUS_POLICY(SCD(*ps)), 1); FPS_RAISE_UNFOCUSED_CLIENT_CLICK(S_FOCUS_POLICY(SCC(*ps)), 1); } if (!FP_DO_RAISE_FOCUSED_DECOR_CLICK(S_FOCUS_POLICY(SCM(*ps)))) { FPS_RAISE_FOCUSED_DECOR_CLICK( S_FOCUS_POLICY(SCF(*ps)), FP_DO_RAISE_FOCUSED_DECOR_CLICK(fp)); FPS_RAISE_FOCUSED_DECOR_CLICK(S_FOCUS_POLICY(SCD(*ps)), 1); FPS_RAISE_FOCUSED_DECOR_CLICK(S_FOCUS_POLICY(SCC(*ps)), 1); } if (!FP_DO_RAISE_UNFOCUSED_DECOR_CLICK(S_FOCUS_POLICY(SCM(*ps)))) { FPS_RAISE_UNFOCUSED_DECOR_CLICK( S_FOCUS_POLICY(SCF(*ps)), FP_DO_RAISE_UNFOCUSED_DECOR_CLICK(fp)); FPS_RAISE_UNFOCUSED_DECOR_CLICK(S_FOCUS_POLICY(SCD(*ps)), 1); FPS_RAISE_UNFOCUSED_DECOR_CLICK(S_FOCUS_POLICY(SCC(*ps)), 1); } if (!FP_DO_PASS_FOCUS_CLICK(S_FOCUS_POLICY(SCM(*ps)))) { FPS_PASS_FOCUS_CLICK( S_FOCUS_POLICY(SCF(*ps)), FP_DO_PASS_FOCUS_CLICK(fp)); FPS_PASS_FOCUS_CLICK(S_FOCUS_POLICY(SCD(*ps)), 1); FPS_PASS_FOCUS_CLICK(S_FOCUS_POLICY(SCC(*ps)), 1); } if (!FP_DO_PASS_RAISE_CLICK(S_FOCUS_POLICY(SCM(*ps)))) { FPS_PASS_RAISE_CLICK( S_FOCUS_POLICY(SCF(*ps)), FP_DO_PASS_RAISE_CLICK(fp)); FPS_PASS_RAISE_CLICK(S_FOCUS_POLICY(SCD(*ps)), 1); FPS_PASS_RAISE_CLICK(S_FOCUS_POLICY(SCC(*ps)), 1); } if (!FP_DO_ALLOW_FUNC_FOCUS_CLICK(S_FOCUS_POLICY(SCM(*ps)))) { FPS_ALLOW_FUNC_FOCUS_CLICK( S_FOCUS_POLICY(SCF(*ps)), FP_DO_ALLOW_FUNC_FOCUS_CLICK(fp)); FPS_ALLOW_FUNC_FOCUS_CLICK(S_FOCUS_POLICY(SCD(*ps)), 1); FPS_ALLOW_FUNC_FOCUS_CLICK(S_FOCUS_POLICY(SCC(*ps)), 1); } if (!FP_DO_ALLOW_FUNC_RAISE_CLICK(S_FOCUS_POLICY(SCM(*ps)))) { FPS_ALLOW_FUNC_RAISE_CLICK( S_FOCUS_POLICY(SCF(*ps)), FP_DO_ALLOW_FUNC_RAISE_CLICK(fp)); FPS_ALLOW_FUNC_RAISE_CLICK(S_FOCUS_POLICY(SCD(*ps)), 1); FPS_ALLOW_FUNC_RAISE_CLICK(S_FOCUS_POLICY(SCC(*ps)), 1); } if (!FP_DO_WARP_POINTER_ON_FOCUS_FUNC( S_FOCUS_POLICY(SCM(*ps)))) { FPS_WARP_POINTER_ON_FOCUS_FUNC( S_FOCUS_POLICY(SCF(*ps)), FP_DO_WARP_POINTER_ON_FOCUS_FUNC(fp)); FPS_WARP_POINTER_ON_FOCUS_FUNC(S_FOCUS_POLICY(SCD(*ps)), 1); FPS_WARP_POINTER_ON_FOCUS_FUNC(S_FOCUS_POLICY(SCC(*ps)), 1); } if (!FP_DO_SORT_WINDOWLIST_BY(S_FOCUS_POLICY(SCM(*ps)))) { FPS_SORT_WINDOWLIST_BY( S_FOCUS_POLICY(SCF(*ps)), FP_DO_SORT_WINDOWLIST_BY(fp)); FPS_SORT_WINDOWLIST_BY(S_FOCUS_POLICY(SCD(*ps)), 1); FPS_SORT_WINDOWLIST_BY(S_FOCUS_POLICY(SCC(*ps)), 1); } return; } static char *style_parse_button_style( window_style *ps, char *button_string, int on) { int button; char *rest; button = -1; GetIntegerArguments(button_string, &rest, &button, 1); button = BUTTON_INDEX(button); if (button < 0 || button >= NUMBER_OF_TITLE_BUTTONS) { fvwm_msg( ERR, "CMD_Style", "Button and NoButton styles require an argument"); } else { if (on) { ps->flags.is_button_disabled &= ~(1 << button); ps->flag_mask.is_button_disabled |= (1 << button); ps->change_mask.is_button_disabled |= (1 << button); } else { ps->flags.is_button_disabled |= (1 << button); ps->flag_mask.is_button_disabled |= (1 << button); ps->change_mask.is_button_disabled |= (1 << button); } } return rest; } static Bool style_parse_focus_policy_style( char *option, char *rest, char **ret_rest, Bool is_reversed, focus_policy_t *f, focus_policy_t *m, focus_policy_t *c) { char *optlist[] = { "SortWindowlistByFocus", "FocusClickButtons", "FocusClickModifiers", "ClickRaisesFocused", "ClickDecorRaisesFocused", "ClickIconRaisesFocused", "ClickRaisesUnfocused", "ClickDecorRaisesUnfocused", "ClickIconRaisesUnfocused", "ClickToFocus", "ClickDecorToFocus", "ClickIconToFocus", "EnterToFocus", "LeaveToUnfocus", "FocusByProgram", "FocusByFunction", "FocusByFunctionWarpPointer", "Lenient", "PassFocusClick", "PassRaiseClick", "IgnoreFocusClickMotion", "IgnoreRaiseClickMotion", "AllowFocusClickFunction", "AllowRaiseClickFunction", "GrabFocus", "GrabFocusTransient", "OverrideGrabFocus", "ReleaseFocus", "ReleaseFocusTransient", "OverrideReleaseFocus", NULL }; Bool found; int val; int index; char *token; if (ret_rest) { *ret_rest = rest; } found = True; val = !is_reversed; GetNextTokenIndex(option, optlist, 0, &index); switch (index) { case 0: /* SortWindowlistByFocus */ FPS_SORT_WINDOWLIST_BY( *f, (val) ? FPOL_SORT_WL_BY_FOCUS : FPOL_SORT_WL_BY_OPEN); FPS_SORT_WINDOWLIST_BY(*m, 1); FPS_SORT_WINDOWLIST_BY(*c, 1); break; case 1: /* FocusClickButtons */ if (is_reversed) { found = False; break; } token = PeekToken(rest, ret_rest); val = 0; for ( ; token != NULL && isdigit(*token); token++) { int button; char s[2]; s[0] = *token; s[1] = 0; button = atoi(s); if (button == 0) { val = ~0; } else if (button > NUMBER_OF_EXTENDED_MOUSE_BUTTONS) { break; } else { val |= (1 << (button - 1)); } } if (token != NULL && *token != 0) { fvwm_msg( ERR, "style_parse_focus_policy_style", "illegal mouse button '%c'", *token); val = DEF_FP_MOUSE_BUTTONS; } if (token == NULL) { val = DEF_FP_MOUSE_BUTTONS; } FPS_MOUSE_BUTTONS(*f, val); FPS_MOUSE_BUTTONS(*m, 0x1FF); FPS_MOUSE_BUTTONS(*c, 0x1FF); break; case 2: /* FocusClickModifiers */ if (is_reversed) { found = False; break; } token = PeekToken(rest, ret_rest); if (token == NULL || modifiers_string_to_modmask(token, &val) == 1) { val = DEF_FP_MODIFIERS; } if (val & AnyModifier) { val = FPOL_ANY_MODIFIER; } FPS_MODIFIERS(*f, val); FPS_MODIFIERS(*m, 0xFF); FPS_MODIFIERS(*c, 0xFF); break; case 3: /* ClickRaisesFocused */ FPS_RAISE_FOCUSED_CLIENT_CLICK(*f, val); FPS_RAISE_FOCUSED_CLIENT_CLICK(*m, 1); FPS_RAISE_FOCUSED_CLIENT_CLICK(*c, 1); break; case 4: /* ClickDecorRaisesFocused */ FPS_RAISE_FOCUSED_DECOR_CLICK(*f, val); FPS_RAISE_FOCUSED_DECOR_CLICK(*m, 1); FPS_RAISE_FOCUSED_DECOR_CLICK(*c, 1); break; case 5: /* ClickIconRaisesFocused */ FPS_RAISE_FOCUSED_ICON_CLICK(*f, val); FPS_RAISE_FOCUSED_ICON_CLICK(*m, 1); FPS_RAISE_FOCUSED_ICON_CLICK(*c, 1); break; case 6: /* ClickRaisesUnfocused */ FPS_RAISE_UNFOCUSED_CLIENT_CLICK(*f, val); FPS_RAISE_UNFOCUSED_CLIENT_CLICK(*m, 1); FPS_RAISE_UNFOCUSED_CLIENT_CLICK(*c, 1); break; case 7: /* ClickDecorRaisesUnfocused */ FPS_RAISE_UNFOCUSED_DECOR_CLICK(*f, val); FPS_RAISE_UNFOCUSED_DECOR_CLICK(*m, 1); FPS_RAISE_UNFOCUSED_DECOR_CLICK(*c, 1); break; case 8: /* ClickIconRaisesUnfocused */ FPS_RAISE_UNFOCUSED_ICON_CLICK(*f, val); FPS_RAISE_UNFOCUSED_ICON_CLICK(*m, 1); FPS_RAISE_UNFOCUSED_ICON_CLICK(*c, 1); break; case 9: /* ClickToFocus */ FPS_FOCUS_CLICK_CLIENT(*f, val); FPS_FOCUS_CLICK_CLIENT(*m, 1); FPS_FOCUS_CLICK_CLIENT(*c, 1); break; case 10: /* ClickDecorToFocus */ FPS_FOCUS_CLICK_DECOR(*f, val); FPS_FOCUS_CLICK_DECOR(*m, 1); FPS_FOCUS_CLICK_DECOR(*c, 1); break; case 11: /* ClickIconToFocus */ FPS_FOCUS_CLICK_ICON(*f, val); FPS_FOCUS_CLICK_ICON(*m, 1); FPS_FOCUS_CLICK_ICON(*c, 1); break; case 12: /* EnterToFocus */ FPS_FOCUS_ENTER(*f, val); FPS_FOCUS_ENTER(*m, 1); FPS_FOCUS_ENTER(*c, 1); break; case 13: /* LeaveToUnfocus */ FPS_UNFOCUS_LEAVE(*f, val); FPS_UNFOCUS_LEAVE(*m, 1); FPS_UNFOCUS_LEAVE(*c, 1); break; case 14: /* FocusByProgram */ FPS_FOCUS_BY_PROGRAM(*f, val); FPS_FOCUS_BY_PROGRAM(*m, 1); FPS_FOCUS_BY_PROGRAM(*c, 1); break; case 15: /* FocusByFunction */ FPS_FOCUS_BY_FUNCTION(*f, val); FPS_FOCUS_BY_FUNCTION(*m, 1); FPS_FOCUS_BY_FUNCTION(*c, 1); break; case 16: /* FocusByFunctionWarpPointer */ FPS_WARP_POINTER_ON_FOCUS_FUNC(*f, val); FPS_WARP_POINTER_ON_FOCUS_FUNC(*m, 1); FPS_WARP_POINTER_ON_FOCUS_FUNC(*c, 1); break; case 17: /* Lenient */ FPS_LENIENT(*f, val); FPS_LENIENT(*m, 1); FPS_LENIENT(*c, 1); break; case 18: /* PassFocusClick */ FPS_PASS_FOCUS_CLICK(*f, val); FPS_PASS_FOCUS_CLICK(*m, 1); FPS_PASS_FOCUS_CLICK(*c, 1); break; case 19: /* PassRaiseClick */ FPS_PASS_RAISE_CLICK(*f, val); FPS_PASS_RAISE_CLICK(*m, 1); FPS_PASS_RAISE_CLICK(*c, 1); break; case 20: /* IgnoreFocusClickMotion */ FPS_IGNORE_FOCUS_CLICK_MOTION(*f, val); FPS_IGNORE_FOCUS_CLICK_MOTION(*m, 1); FPS_IGNORE_FOCUS_CLICK_MOTION(*c, 1); break; case 21: /* IgnoreRaiseClickMotion */ FPS_IGNORE_RAISE_CLICK_MOTION(*f, val); FPS_IGNORE_RAISE_CLICK_MOTION(*m, 1); FPS_IGNORE_RAISE_CLICK_MOTION(*c, 1); break; case 22: /* AllowFocusClickFunction */ FPS_ALLOW_FUNC_FOCUS_CLICK(*f, val); FPS_ALLOW_FUNC_FOCUS_CLICK(*m, 1); FPS_ALLOW_FUNC_FOCUS_CLICK(*c, 1); break; case 23: /* AllowRaiseClickFunction */ FPS_ALLOW_FUNC_RAISE_CLICK(*f, val); FPS_ALLOW_FUNC_RAISE_CLICK(*m, 1); FPS_ALLOW_FUNC_RAISE_CLICK(*c, 1); break; case 24: /* GrabFocus */ FPS_GRAB_FOCUS(*f, val); FPS_GRAB_FOCUS(*m, 1); FPS_GRAB_FOCUS(*c, 1); break; case 25: /* GrabFocusTransient */ FPS_GRAB_FOCUS_TRANSIENT(*f, val); FPS_GRAB_FOCUS_TRANSIENT(*m, 1); FPS_GRAB_FOCUS_TRANSIENT(*c, 1); break; case 26: /* OverrideGrabFocus */ FPS_OVERRIDE_GRAB_FOCUS(*f, val); FPS_OVERRIDE_GRAB_FOCUS(*m, 1); FPS_OVERRIDE_GRAB_FOCUS(*c, 1); break; case 27: /* ReleaseFocus */ FPS_RELEASE_FOCUS(*f, val); FPS_RELEASE_FOCUS(*m, 1); FPS_RELEASE_FOCUS(*c, 1); break; case 28: /* ReleaseFocusTransient */ FPS_RELEASE_FOCUS_TRANSIENT(*f, val); FPS_RELEASE_FOCUS_TRANSIENT(*m, 1); FPS_RELEASE_FOCUS_TRANSIENT(*c, 1); break; case 29: /* OverrideReleaseFocus */ FPS_OVERRIDE_RELEASE_FOCUS(*f, val); FPS_OVERRIDE_RELEASE_FOCUS(*m, 1); FPS_OVERRIDE_RELEASE_FOCUS(*c, 1); break; default: found = False; break; } return found; } static char *style_parse_icon_size_style( char *option, char *rest, window_style *ps) { int vals[4]; int i; option = PeekToken(rest, NULL); if (StrEquals(option, "Stretched")) { SSET_ICON_RESIZE_TYPE(*ps, ICON_RESIZE_TYPE_STRETCHED); option = PeekToken(rest, &rest); } else if (StrEquals(option, "Adjusted")) { SSET_ICON_RESIZE_TYPE(*ps, ICON_RESIZE_TYPE_ADJUSTED); option = PeekToken(rest, &rest); } else if (StrEquals(option, "Shrunk")) { SSET_ICON_RESIZE_TYPE(*ps, ICON_RESIZE_TYPE_SHRUNK); option = PeekToken(rest, &rest); } else { SSET_ICON_RESIZE_TYPE(*ps, ICON_RESIZE_TYPE_NONE); } switch (GetIntegerArguments(rest, &rest, vals, 4)) { case 0: /* No arguments results in default values */ vals[0] = vals[1] = UNSPECIFIED_ICON_DIMENSION; /* fall through */ case 2: /* Max and min values are the same */ vals[2] = vals[0]; vals[3] = vals[1]; /* fall through */ case 4: /* Validate values */ for (i = 0; i < 4; i++) { int use_default = 0; if (vals[i] != UNSPECIFIED_ICON_DIMENSION && (vals[i] < MIN_ALLOWABLE_ICON_DIMENSION || vals[i] > MAX_ALLOWABLE_ICON_DIMENSION)) { fvwm_msg( ERR, "CMD_Style", "IconSize dimension (%d) not in valid" " range (%d-%d)", vals[i], MIN_ALLOWABLE_ICON_DIMENSION, MAX_ALLOWABLE_ICON_DIMENSION); use_default = 1; } /* User requests default value for this dimension */ else if (vals[i] == UNSPECIFIED_ICON_DIMENSION) { use_default = 1; } if (use_default) { /* Set default value for this dimension. The * first two indexes refer to min values, the * latter two to max values. */ vals[i] = i < 2 ? MIN_ALLOWABLE_ICON_DIMENSION : MAX_ALLOWABLE_ICON_DIMENSION; } } SSET_MIN_ICON_WIDTH(*ps, vals[0]); SSET_MIN_ICON_HEIGHT(*ps, vals[1]); SSET_MAX_ICON_WIDTH(*ps, vals[2]); SSET_MAX_ICON_HEIGHT(*ps, vals[3]); ps->flags.has_icon_size_limits = 1; ps->flag_mask.has_icon_size_limits = 1; ps->change_mask.has_icon_size_limits = 1; break; default: fvwm_msg( ERR, "CMD_Style", "IconSize requires exactly 0, 2 or 4" " numerical arguments"); break; } return rest; } static char *style_parse_icon_box_style( icon_boxes **ret_ib, char *option, char *rest, window_style *ps) { icon_boxes *IconBoxes = NULL; Bool is_screen_given = False; int val[4]; int num; int i; option = PeekToken(rest, NULL); if (!option || StrEquals(option, "none")) { option = PeekToken(rest, &rest); /* delete icon boxes from style */ if (SGET_ICON_BOXES(*ps)) { remove_icon_boxes_from_style(ps); } (*ret_ib) = NULL; if (option) { /* disable default icon box */ S_SET_DO_IGNORE_ICON_BOXES(SCF(*ps), 1); } else { /* use default icon box */ S_SET_DO_IGNORE_ICON_BOXES(SCF(*ps), 0); } S_SET_DO_IGNORE_ICON_BOXES(SCM(*ps), 1); S_SET_DO_IGNORE_ICON_BOXES(SCC(*ps), 1); ps->flags.has_icon_boxes = 0; ps->flag_mask.has_icon_boxes = 1; ps->change_mask.has_icon_boxes = 1; return rest; } /* otherwise try to parse the icon box */ IconBoxes = (icon_boxes *)safemalloc(sizeof(icon_boxes)); /* clear it */ memset(IconBoxes, 0, sizeof(icon_boxes)); IconBoxes->IconScreen = FSCREEN_GLOBAL; /* init grid x */ IconBoxes->IconGrid[0] = 3; /* init grid y */ IconBoxes->IconGrid[1] = 3; /* check for screen (for 4 numbers) */ if (StrEquals(option, "screen")) { is_screen_given = True; option = PeekToken(rest, &rest); /* skip screen */ option = PeekToken(rest, &rest); /* get the screen spec */ IconBoxes->IconScreen = FScreenGetScreenArgument(option, FSCREEN_SPEC_PRIMARY); } /* try for 4 numbers x y x y */ num = GetIntegerArguments(rest, NULL, val, 4); /* if 4 numbers */ if (num == 4) { for (i = 0; i < 4; i++) { /* make sure the value fits into a short */ if (val[i] < -32768) { val[i] = -32768; } if (val[i] > 32767) { val[i] = 32767; } IconBoxes->IconBox[i] = val[i]; /* If leading minus sign */ option = PeekToken(rest, &rest); if (option[0] == '-') { IconBoxes->IconSign[i]='-'; } /* end leading minus sign */ } /* Note: here there is no test for valid co-ords, use geom */ } else if (is_screen_given) { /* screen-spec is given but not 4 numbers */ fvwm_msg( ERR,"CMD_Style", "IconBox requires 4 numbers if screen is given!" " Invalid: <%s>.", option); /* Drop the box */ free(IconBoxes); /* forget about it */ IconBoxes = 0; } else { /* Not 4 numeric args dje */ /* bigger than =32767x32767+32767+32767 */ int geom_flags; int l; int width; int height; /* read in 1 word w/o advancing */ option = PeekToken(rest, NULL); if (!option) { return rest; } l = strlen(option); if (l > 0 && l < 24) { /* advance */ option = PeekToken(rest, &rest); /* if word found, not too long */ geom_flags = FScreenParseGeometryWithScreen( option, &IconBoxes->IconBox[0], &IconBoxes->IconBox[1], (unsigned int*)&width, (unsigned int*)&height, &IconBoxes->IconScreen); if (width == 0 || !(geom_flags & WidthValue)) { /* zero width is invalid */ fvwm_msg( ERR,"CMD_Style", "IconBox requires 4 numbers or" " geometry! Invalid string <%s>.", option); /* Drop the box */ free(IconBoxes); /* forget about it */ IconBoxes = 0; } else { /* got valid iconbox geom */ if (geom_flags & XNegative) { IconBoxes->IconBox[0] = /* neg x coord */ IconBoxes->IconBox[0] - width - 2; /* save for later */ IconBoxes->IconSign[0]='-'; IconBoxes->IconSign[2]='-'; } if (geom_flags & YNegative) { IconBoxes->IconBox[1] = /* neg y coord */ IconBoxes->IconBox[1] - height -2; /* save for later */ IconBoxes->IconSign[1]='-'; IconBoxes->IconSign[3]='-'; } /* x + wid = right x */ IconBoxes->IconBox[2] = width + IconBoxes->IconBox[0]; /* y + height = bottom y */ IconBoxes->IconBox[3] = height + IconBoxes->IconBox[1]; } /* end icon geom worked */ } else { /* no word or too long; drop the box */ free(IconBoxes); /* forget about it */ IconBoxes = 0; } /* end word found, not too long */ } /* end not 4 args */ /* If we created an IconBox, put it in the chain. */ if (IconBoxes != 0) { /* no error */ if (SGET_ICON_BOXES(*ps) == 0) { /* first one, chain to root */ SSET_ICON_BOXES(*ps, IconBoxes); } else { /* else not first one, add to end of chain */ (*ret_ib)->next = IconBoxes; } /* end not first one */ /* new current box. save for grid */ (*ret_ib) = IconBoxes; } /* end no error */ S_SET_DO_IGNORE_ICON_BOXES(SCF(*ps), 0); S_SET_DO_IGNORE_ICON_BOXES(SCM(*ps), 1); S_SET_DO_IGNORE_ICON_BOXES(SCC(*ps), 1); ps->flags.has_icon_boxes = !!(SGET_ICON_BOXES(*ps)); ps->flag_mask.has_icon_boxes = 1; ps->change_mask.has_icon_boxes = 1; return rest; } static char *style_parse_icon_grid_style( char *option, char *rest, window_style *ps, icon_boxes *ib) { int val[4]; int num; int i; /* The grid always affects the prior iconbox */ if (ib == 0) { /* If no current box */ fvwm_msg( ERR,"CMD_Style", "IconGrid must follow an IconBox in same Style" " command"); return rest; } /* have a place to grid */ /* 2 ints */ num = GetIntegerArguments(rest, &rest, val, 2); if (num != 2 || val[0] < 1 || val[1] < 1) { fvwm_msg( ERR,"CMD_Style", "IconGrid needs 2 numbers > 0. Got %d numbers." " x=%d y=%d!", num, val[0], val[1]); /* reset grid */ ib->IconGrid[0] = 3; ib->IconGrid[1] = 3; } else { for (i = 0; i < 2; i++) { ib->IconGrid[i] = val[i]; } } /* end bad grid */ return rest; } static char *style_parse_icon_fill_style( char *option, char *rest, window_style *ps, icon_boxes *ib) { /* first type direction parsed */ unsigned char IconFill_1; /* second type direction parsed */ unsigned char IconFill_2; /* direction to fill iconbox */ /* The fill always affects the prior iconbox */ if (ib == 0) { /* If no current box */ fvwm_msg( ERR,"CMD_Style", "IconFill must follow an IconBox in same Style" " command"); return rest; } /* have a place to fill */ option = PeekToken(rest, &rest); /* top/bot/lft/rgt */ if (!option || Get_TBLR(option, &IconFill_1) == 0) { /* its wrong */ if (!option) { option = "(none)"; } fvwm_msg( ERR,"CMD_Style", "IconFill must be followed by T|B|R|L, found" " %s.", option); return rest; } /* first word valid */ /* read in second word */ option = PeekToken(rest, &rest); /* top/bot/lft/rgt */ if (!option || Get_TBLR(option, &IconFill_2) == 0) { /* its wrong */ if (!option) { option = "(none)"; } fvwm_msg( ERR,"CMD_Style", "IconFill must be followed by T|B|R|L," " found %s.", option); return rest; } if ((IconFill_1 & ICONFILLHRZ) == (IconFill_2 & ICONFILLHRZ)) { fvwm_msg( ERR, "CMD_Style", "IconFill must specify a horizontal" " and vertical direction."); return rest; } /* Its valid! */ /* merge in flags */ ib->IconFlags |= IconFill_1; /* ignore horiz in 2nd arg */ IconFill_2 &= ~ICONFILLHRZ; /* merge in flags */ ib->IconFlags |= IconFill_2; return rest; } static Bool style_parse_one_style_option( char *token, char *rest, char **ret_rest, char *prefix, window_style *ps, icon_boxes **cur_ib) { window_style *add_style; /* work area for button number */ int num; int i; int tmpno[3] = { -1, -1, -1 }; int val[4]; int spargs = 0; Bool found; int on; char *token_l = NULL; found = True; on = 1; while (token[0] == '!') { on ^= 1; token++; } if (prefix != NULL && *prefix != 0) { int l; l = strlen(prefix); if (strncasecmp(token, prefix, l) != 0) { /* add missing prefix */ token_l = (char *)safemalloc(l + strlen(token) + 1); strcpy(token_l, prefix); strcat(token_l, token); token = token_l; } } switch (tolower(token[0])) { case 'a': if (StrEquals(token, "ACTIVEPLACEMENT")) { ps->flags.placement_mode &= (~PLACE_RANDOM); ps->flag_mask.placement_mode |= PLACE_RANDOM; ps->change_mask.placement_mode |= PLACE_RANDOM; } else if (StrEquals(token, "ACTIVEPLACEMENTHONORSSTARTSONPAGE")) { ps->flags.manual_placement_honors_starts_on_page = on; ps->flag_mask.manual_placement_honors_starts_on_page = 1; ps->change_mask.manual_placement_honors_starts_on_page = 1; } else if (StrEquals( token, "ACTIVEPLACEMENTIGNORESSTARTSONPAGE")) { ps->flags.manual_placement_honors_starts_on_page = !on; ps->flag_mask.manual_placement_honors_starts_on_page = 1; ps->change_mask.manual_placement_honors_starts_on_page = 1; } else if (StrEquals(token, "AllowRestack")) { S_SET_DO_IGNORE_RESTACK(SCF(*ps), !on); S_SET_DO_IGNORE_RESTACK(SCM(*ps), 1); S_SET_DO_IGNORE_RESTACK(SCC(*ps), 1); } else if (StrEquals(token, "AllowMaximizeFixedSize")) { S_SET_MAXIMIZE_FIXED_SIZE_DISALLOWED(SCF(*ps), !on); S_SET_MAXIMIZE_FIXED_SIZE_DISALLOWED(SCM(*ps), 1); S_SET_MAXIMIZE_FIXED_SIZE_DISALLOWED(SCC(*ps), 1); } else { found = False; } break; case 'b': if (StrEquals(token, "BackColor")) { rest = GetNextToken(rest, &token); if (token) { SAFEFREE(SGET_BACK_COLOR_NAME(*ps)); SSET_BACK_COLOR_NAME(*ps, token); ps->flags.has_color_back = 1; ps->flag_mask.has_color_back = 1; ps->change_mask.has_color_back = 1; ps->flags.use_colorset = 0; ps->flag_mask.use_colorset = 1; ps->change_mask.use_colorset = 1; } else { fvwm_msg( ERR, "style_parse_on_estyle_option", "Style BackColor requires color" " argument"); } } else if (StrEquals(token, "Button")) { rest = style_parse_button_style(ps, rest, on); } else if (StrEquals(token, "BorderWidth")) { if (GetIntegerArguments(rest, &rest, val, 1)) { SSET_BORDER_WIDTH(*ps, (short)*val); ps->flags.has_border_width = 1; ps->flag_mask.has_border_width = 1; ps->change_mask.has_border_width = 1; } else { ps->flags.has_border_width = 0; ps->flag_mask.has_border_width = 1; ps->change_mask.has_border_width = 1; } } else if (StrEquals(token, "BackingStore")) { ps->flags.use_backing_store = BACKINGSTORE_ON; ps->flag_mask.use_backing_store = BACKINGSTORE_MASK; ps->change_mask.use_backing_store = BACKINGSTORE_MASK; } else if (StrEquals(token, "BackingStoreOff")) { ps->flags.use_backing_store = BACKINGSTORE_OFF; ps->flag_mask.use_backing_store = BACKINGSTORE_MASK; ps->change_mask.use_backing_store = BACKINGSTORE_MASK; } else if (StrEquals(token, "BackingStoreWindowDefault")) { ps->flags.use_backing_store = BACKINGSTORE_DEFAULT; ps->flag_mask.use_backing_store = BACKINGSTORE_MASK; ps->change_mask.use_backing_store = BACKINGSTORE_MASK; } else if (StrEquals(token, "BorderColorset")) { *val = -1; GetIntegerArguments(rest, &rest, val, 1); SSET_BORDER_COLORSET(*ps, *val); alloc_colorset(*val); ps->flags.use_border_colorset = (*val >= 0); ps->flag_mask.use_border_colorset = 1; ps->change_mask.use_border_colorset = 1; } else if (StrEquals(token, "BottomTitleRotated")) { S_SET_IS_BOTTOM_TITLE_ROTATED(SCF(*ps), on); S_SET_IS_BOTTOM_TITLE_ROTATED(SCM(*ps), 1); S_SET_IS_BOTTOM_TITLE_ROTATED(SCC(*ps), 1); } else if (StrEquals(token, "BottomTitleNotRotated")) { S_SET_IS_BOTTOM_TITLE_ROTATED(SCF(*ps), !on); S_SET_IS_BOTTOM_TITLE_ROTATED(SCM(*ps), 1); S_SET_IS_BOTTOM_TITLE_ROTATED(SCC(*ps), 1); } else if (StrEquals(token, "Borders")) { S_SET_HAS_NO_BORDER(SCF(*ps), !on); S_SET_HAS_NO_BORDER(SCM(*ps), 1); S_SET_HAS_NO_BORDER(SCC(*ps), 1); } else { found = False; } break; case 'c': if (StrEquals(token, "CascadePlacement")) { ps->flags.placement_mode = PLACE_CASCADE; ps->flag_mask.placement_mode = PLACE_MASK; ps->change_mask.placement_mode = PLACE_MASK; } else if (StrEquals(token, "CLEVERPLACEMENT")) { ps->flags.placement_mode |= PLACE_CLEVER; ps->flag_mask.placement_mode |= PLACE_CLEVER; ps->change_mask.placement_mode |= PLACE_CLEVER; } else if (StrEquals(token, "CleverPlacementOff")) { ps->flags.placement_mode &= (~PLACE_CLEVER); ps->flag_mask.placement_mode |= PLACE_CLEVER; ps->change_mask.placement_mode |= PLACE_CLEVER; } else if (StrEquals(token, "CaptureHonorsStartsOnPage")) { ps->flags.capture_honors_starts_on_page = on; ps->flag_mask.capture_honors_starts_on_page = 1; ps->change_mask.capture_honors_starts_on_page = 1; } else if (StrEquals(token, "CaptureIgnoresStartsonPage")) { ps->flags.capture_honors_starts_on_page = !on; ps->flag_mask.capture_honors_starts_on_page = 1; ps->change_mask.capture_honors_starts_on_page = 1; } else if (StrEquals(token, "ColorSet")) { *val = -1; GetIntegerArguments(rest, &rest, val, 1); if (*val < 0) { *val = -1; } SSET_COLORSET(*ps, *val); alloc_colorset(*val); ps->flags.use_colorset = (*val >= 0); ps->flag_mask.use_colorset = 1; ps->change_mask.use_colorset = 1; } else if (StrEquals(token, "Color")) { char c = 0; char *next; next = GetNextToken(rest, &token); if (token == NULL) { fvwm_msg( ERR, "style_parse_one_style_option", "Color Style requires a color" " argument"); break; } if (strncasecmp(token, "rgb:", 4) == 0) { char *s; int i; /* spool to third '/' */ for (i = 0, s = token + 4; *s && i < 3; s++) { if (*s == '/') { i++; } } s--; if (i == 3) { *s = 0; /* spool to third '/' in original * string too */ for (i = 0, s = rest; *s && i < 3; s++) { if (*s == '/') { i++; } } next = s - 1; } } else { free(token); next = DoGetNextToken( rest, &token, NULL, ",/", &c); } rest = next; SAFEFREE(SGET_FORE_COLOR_NAME(*ps)); SSET_FORE_COLOR_NAME(*ps, token); ps->flags.has_color_fore = 1; ps->flag_mask.has_color_fore = 1; ps->change_mask.has_color_fore = 1; ps->flags.use_colorset = 0; ps->flag_mask.use_colorset = 1; ps->change_mask.use_colorset = 1; /* skip over '/' */ if (c != '/') { while (rest && *rest && isspace((unsigned char)*rest) && *rest != ',' && *rest != '/') { rest++; } if (*rest == '/') { rest++; } } rest=GetNextToken(rest, &token); if (!token) { fvwm_msg( ERR, "style_parse_one_style_option", "Color Style called with incomplete" " color argument."); break; } SAFEFREE(SGET_BACK_COLOR_NAME(*ps)); SSET_BACK_COLOR_NAME(*ps, token); ps->flags.has_color_back = 1; ps->flag_mask.has_color_back = 1; ps->change_mask.has_color_back = 1; break; } else if (StrEquals(token, "CirculateSkipIcon")) { S_SET_DO_CIRCULATE_SKIP_ICON(SCF(*ps), on); S_SET_DO_CIRCULATE_SKIP_ICON(SCM(*ps), 1); S_SET_DO_CIRCULATE_SKIP_ICON(SCC(*ps), 1); } else if (StrEquals(token, "CirculateSkipShaded")) { S_SET_DO_CIRCULATE_SKIP_SHADED(SCF(*ps), on); S_SET_DO_CIRCULATE_SKIP_SHADED(SCM(*ps), 1); S_SET_DO_CIRCULATE_SKIP_SHADED(SCC(*ps), 1); } else if (StrEquals(token, "CirculateHitShaded")) { S_SET_DO_CIRCULATE_SKIP_SHADED(SCF(*ps), !on); S_SET_DO_CIRCULATE_SKIP_SHADED(SCM(*ps), 1); S_SET_DO_CIRCULATE_SKIP_SHADED(SCC(*ps), 1); } else if (StrEquals(token, "CirculateHitIcon")) { S_SET_DO_CIRCULATE_SKIP_ICON(SCF(*ps), !on); S_SET_DO_CIRCULATE_SKIP_ICON(SCM(*ps), 1); S_SET_DO_CIRCULATE_SKIP_ICON(SCC(*ps), 1); } else if (StrEquals(token, "ClickToFocus")) { style_set_old_focus_policy(ps, 0); } else if (StrEquals(token, "ClickToFocusPassesClick")) { FPS_PASS_FOCUS_CLICK(S_FOCUS_POLICY(SCF(*ps)), on); FPS_PASS_FOCUS_CLICK(S_FOCUS_POLICY(SCM(*ps)), 1); FPS_PASS_FOCUS_CLICK(S_FOCUS_POLICY(SCC(*ps)), 1); FPS_PASS_RAISE_CLICK(S_FOCUS_POLICY(SCF(*ps)), on); FPS_PASS_RAISE_CLICK(S_FOCUS_POLICY(SCM(*ps)), 1); FPS_PASS_RAISE_CLICK(S_FOCUS_POLICY(SCC(*ps)), 1); } else if (StrEquals(token, "ClickToFocusPassesClickOff")) { FPS_PASS_FOCUS_CLICK(S_FOCUS_POLICY(SCF(*ps)), !on); FPS_PASS_FOCUS_CLICK(S_FOCUS_POLICY(SCM(*ps)), 1); FPS_PASS_FOCUS_CLICK(S_FOCUS_POLICY(SCC(*ps)), 1); FPS_PASS_RAISE_CLICK(S_FOCUS_POLICY(SCF(*ps)), !on); FPS_PASS_RAISE_CLICK(S_FOCUS_POLICY(SCM(*ps)), 1); FPS_PASS_RAISE_CLICK(S_FOCUS_POLICY(SCC(*ps)), 1); } else if (StrEquals(token, "ClickToFocusRaises")) { FPS_RAISE_FOCUSED_CLIENT_CLICK( S_FOCUS_POLICY(SCF(*ps)), on); FPS_RAISE_FOCUSED_CLIENT_CLICK( S_FOCUS_POLICY(SCM(*ps)), 1); FPS_RAISE_FOCUSED_CLIENT_CLICK( S_FOCUS_POLICY(SCC(*ps)), 1); FPS_RAISE_UNFOCUSED_CLIENT_CLICK( S_FOCUS_POLICY(SCF(*ps)), on); FPS_RAISE_UNFOCUSED_CLIENT_CLICK( S_FOCUS_POLICY(SCM(*ps)), 1); FPS_RAISE_UNFOCUSED_CLIENT_CLICK( S_FOCUS_POLICY(SCC(*ps)), 1); } else if (StrEquals(token, "ClickToFocusRaisesOff")) { FPS_RAISE_FOCUSED_CLIENT_CLICK( S_FOCUS_POLICY(SCF(*ps)), !on); FPS_RAISE_FOCUSED_CLIENT_CLICK( S_FOCUS_POLICY(SCM(*ps)), 1); FPS_RAISE_FOCUSED_CLIENT_CLICK( S_FOCUS_POLICY(SCC(*ps)), 1); FPS_RAISE_UNFOCUSED_CLIENT_CLICK( S_FOCUS_POLICY(SCF(*ps)), !on); FPS_RAISE_UNFOCUSED_CLIENT_CLICK( S_FOCUS_POLICY(SCM(*ps)), 1); FPS_RAISE_UNFOCUSED_CLIENT_CLICK( S_FOCUS_POLICY(SCC(*ps)), 1); } else if (StrEquals(token, "CirculateSkip")) { S_SET_DO_CIRCULATE_SKIP(SCF(*ps), on); S_SET_DO_CIRCULATE_SKIP(SCM(*ps), 1); S_SET_DO_CIRCULATE_SKIP(SCC(*ps), 1); } else if (StrEquals(token, "CirculateHit")) { S_SET_DO_CIRCULATE_SKIP(SCF(*ps), !on); S_SET_DO_CIRCULATE_SKIP(SCM(*ps), 1); S_SET_DO_CIRCULATE_SKIP(SCC(*ps), 1); } else if (StrEquals(token, "Closable")) { S_SET_IS_UNCLOSABLE(SCF(*ps), !on); S_SET_IS_UNCLOSABLE(SCM(*ps), 1); S_SET_IS_UNCLOSABLE(SCC(*ps), 1); } else { found = False; } break; case 'd': if (StrEquals(token, "DepressableBorder")) { S_SET_HAS_DEPRESSABLE_BORDER(SCF(*ps), on); S_SET_HAS_DEPRESSABLE_BORDER(SCM(*ps), 1); S_SET_HAS_DEPRESSABLE_BORDER(SCC(*ps), 1); } else if (StrEquals(token, "DecorateTransient")) { ps->flags.do_decorate_transient = on; ps->flag_mask.do_decorate_transient = 1; ps->change_mask.do_decorate_transient = 1; } else if (StrEquals(token, "DumbPlacement")) { ps->flags.placement_mode &= (~PLACE_SMART); ps->flag_mask.placement_mode |= PLACE_SMART; ps->change_mask.placement_mode |= PLACE_SMART; } else if (StrEquals(token, "DONTRAISETRANSIENT")) { S_SET_DO_RAISE_TRANSIENT(SCF(*ps), !on); S_SET_DO_RAISE_TRANSIENT(SCM(*ps), 1); S_SET_DO_RAISE_TRANSIENT(SCC(*ps), 1); } else if (StrEquals(token, "DONTLOWERTRANSIENT")) { S_SET_DO_LOWER_TRANSIENT(SCF(*ps), !on); S_SET_DO_LOWER_TRANSIENT(SCM(*ps), 1); S_SET_DO_LOWER_TRANSIENT(SCC(*ps), 1); } else if (StrEquals(token, "DontStackTransientParent")) { S_SET_DO_STACK_TRANSIENT_PARENT(SCF(*ps), !on); S_SET_DO_STACK_TRANSIENT_PARENT(SCM(*ps), 1); S_SET_DO_STACK_TRANSIENT_PARENT(SCC(*ps), 1); } else { found = False; } break; case 'e': if (StrEquals(token, "ExactWindowName")) { char *format; /* TA: This is being deprecated in favour of the more * generic: * * TitleFormat %n */ fvwm_msg(WARN, "style_parse_one_style_option", "ExactWindowName is deprecated -- using" " TitleFormat %%n"); format = strdup(DEFAULT_TITLE_FORMAT); SSET_TITLE_FORMAT_STRING(*ps, format); ps->flags.has_title_format_string = 1; ps->flag_mask.has_title_format_string = 1; ps->change_mask.has_title_format_string = 1; } else if (StrEquals(token, "ExactIconName")) { char *format; /* TA: This is being deprecated in favour of the more * generic: * * IconTitleFormat %n */ fvwm_msg(WARN, "style_parse_one_style_option", "ExactIconName is deprecated -- using" " IconTitleFormat %%n"); format = strdup(DEFAULT_TITLE_FORMAT); SSET_ICON_TITLE_FORMAT_STRING(*ps, format); ps->flags.has_icon_title_format_string = 1; ps->flag_mask.has_icon_title_format_string = 1; ps->change_mask.has_icon_title_format_string = 1; } else if (StrEquals(token, "EdgeMoveResistance")) { int num; unsigned has_move; unsigned has_xinerama_move; num = GetIntegerArguments(rest, &rest, val, 2); if (num == 1) { has_move = 1; has_xinerama_move = 0; } else if (num == 2) { has_move = 1; has_xinerama_move = 1; } else { val[0] = 0; val[1] = 0; has_move = 0; has_xinerama_move = 0; } if (val[0] < 0) { val[0] = 0; } if (val[1] < 0) { val[1] = 0; } ps->flags.has_edge_resistance_move = has_move; ps->flag_mask.has_edge_resistance_move = 1; ps->change_mask.has_edge_resistance_move = 1; SSET_EDGE_RESISTANCE_MOVE(*ps, val[0]); ps->flags.has_edge_resistance_xinerama_move = has_xinerama_move; ps->flag_mask.has_edge_resistance_xinerama_move = 1; ps->change_mask.has_edge_resistance_xinerama_move = 1; SSET_EDGE_RESISTANCE_XINERAMA_MOVE(*ps, val[1]); } else if (StrEquals(token, "EdgeMoveDelay")) { if (GetIntegerArguments(rest, &rest, val, 1)) { SSET_EDGE_DELAY_MS_MOVE(*ps, (short)*val); ps->flags.has_edge_delay_ms_move = 1; ps->flag_mask.has_edge_delay_ms_move = 1; ps->change_mask.has_edge_delay_ms_move = 1; } else { ps->flags.has_edge_delay_ms_move = 0; ps->flag_mask.has_edge_delay_ms_move = 1; ps->change_mask.has_edge_delay_ms_move = 1; } } else if (StrEquals(token, "EdgeResizeDelay")) { if (GetIntegerArguments(rest, &rest, val, 1)) { SSET_EDGE_DELAY_MS_RESIZE(*ps, (short)*val); ps->flags.has_edge_delay_ms_resize = 1; ps->flag_mask.has_edge_delay_ms_resize = 1; ps->change_mask.has_edge_delay_ms_resize = 1; } else { ps->flags.has_edge_delay_ms_resize = 0; ps->flag_mask.has_edge_delay_ms_resize = 1; ps->change_mask.has_edge_delay_ms_resize = 1; } } else { found = EWMH_CMD_Style(token, ps, on); } break; case 'f': if (strncasecmp(token, "fp", 2) == 0) { /* parse focus policy options */ found = style_parse_focus_policy_style( token + 2, rest, &rest, (on) ? False : True, &S_FOCUS_POLICY(SCF(*ps)), &S_FOCUS_POLICY(SCM(*ps)), &S_FOCUS_POLICY(SCC(*ps))); } else if (StrEquals(token, "Font")) { SAFEFREE(SGET_WINDOW_FONT(*ps)); rest = GetNextToken(rest, &token); SSET_WINDOW_FONT(*ps, token); S_SET_HAS_WINDOW_FONT(SCF(*ps), (token != NULL)); S_SET_HAS_WINDOW_FONT(SCM(*ps), 1); S_SET_HAS_WINDOW_FONT(SCC(*ps), 1); } else if (StrEquals(token, "ForeColor")) { rest = GetNextToken(rest, &token); if (token) { SAFEFREE(SGET_FORE_COLOR_NAME(*ps)); SSET_FORE_COLOR_NAME(*ps, token); ps->flags.has_color_fore = 1; ps->flag_mask.has_color_fore = 1; ps->change_mask.has_color_fore = 1; ps->flags.use_colorset = 0; ps->flag_mask.use_colorset = 1; ps->change_mask.use_colorset = 1; } else { fvwm_msg( ERR, "style_parse_one_style_option", "ForeColor Style needs color argument" ); } } else if (StrEquals(token, "FVWMBUTTONS")) { S_SET_HAS_MWM_BUTTONS(SCF(*ps), !on); S_SET_HAS_MWM_BUTTONS(SCM(*ps), 1); S_SET_HAS_MWM_BUTTONS(SCC(*ps), 1); } else if (StrEquals(token, "FVWMBORDER")) { S_SET_HAS_MWM_BORDER(SCF(*ps), !on); S_SET_HAS_MWM_BORDER(SCM(*ps), 1); S_SET_HAS_MWM_BORDER(SCC(*ps), 1); } else if (StrEquals(token, "FocusFollowsMouse")) { style_set_old_focus_policy(ps, 1); } else if (StrEquals(token, "FirmBorder")) { S_SET_HAS_DEPRESSABLE_BORDER(SCF(*ps), !on); S_SET_HAS_DEPRESSABLE_BORDER(SCM(*ps), 1); S_SET_HAS_DEPRESSABLE_BORDER(SCC(*ps), 1); } else if (StrEquals(token, "FixedPosition") || StrEquals(token, "FixedUSPosition")) { S_SET_IS_FIXED(SCF(*ps), on); S_SET_IS_FIXED(SCM(*ps), 1); S_SET_IS_FIXED(SCC(*ps), 1); } else if (StrEquals(token, "FixedPPosition")) { S_SET_IS_FIXED_PPOS(SCF(*ps), on); S_SET_IS_FIXED_PPOS(SCM(*ps), 1); S_SET_IS_FIXED_PPOS(SCC(*ps), 1); } else if (StrEquals(token, "FixedSize") || StrEquals(token, "FixedUSSize")) { S_SET_IS_SIZE_FIXED(SCF(*ps), on); S_SET_IS_SIZE_FIXED(SCM(*ps), 1); S_SET_IS_SIZE_FIXED(SCC(*ps), 1); } else if (StrEquals(token, "FixedPSize")) { S_SET_IS_PSIZE_FIXED(SCF(*ps), on); S_SET_IS_PSIZE_FIXED(SCM(*ps), 1); S_SET_IS_PSIZE_FIXED(SCC(*ps), 1); } else { found = False; } break; case 'g': if (StrEquals(token, "GrabFocusOff")) { FPS_GRAB_FOCUS(S_FOCUS_POLICY(SCF(*ps)), !on); FPS_GRAB_FOCUS(S_FOCUS_POLICY(SCM(*ps)), 1); FPS_GRAB_FOCUS(S_FOCUS_POLICY(SCC(*ps)), 1); } else if (StrEquals(token, "GrabFocus")) { FPS_GRAB_FOCUS(S_FOCUS_POLICY(SCF(*ps)), on); FPS_GRAB_FOCUS(S_FOCUS_POLICY(SCM(*ps)), 1); FPS_GRAB_FOCUS(S_FOCUS_POLICY(SCC(*ps)), 1); } else if (StrEquals(token, "GrabFocusTransientOff")) { FPS_GRAB_FOCUS_TRANSIENT( S_FOCUS_POLICY(SCF(*ps)), !on); FPS_GRAB_FOCUS_TRANSIENT(S_FOCUS_POLICY(SCM(*ps)), 1); FPS_GRAB_FOCUS_TRANSIENT(S_FOCUS_POLICY(SCC(*ps)), 1); } else if (StrEquals(token, "GrabFocusTransient")) { FPS_GRAB_FOCUS_TRANSIENT(S_FOCUS_POLICY(SCF(*ps)), on); FPS_GRAB_FOCUS_TRANSIENT(S_FOCUS_POLICY(SCM(*ps)), 1); FPS_GRAB_FOCUS_TRANSIENT(S_FOCUS_POLICY(SCC(*ps)), 1); } else { found = False; } break; case 'h': if (StrEquals(token, "HintOverride")) { S_SET_HAS_MWM_OVERRIDE(SCF(*ps), on); S_SET_HAS_MWM_OVERRIDE(SCM(*ps), 1); S_SET_HAS_MWM_OVERRIDE(SCC(*ps), 1); } else if (StrEquals(token, "Handles")) { ps->flags.has_no_handles = !on; ps->flag_mask.has_no_handles = 1; ps->change_mask.has_no_handles = 1; } else if (StrEquals(token, "HandleWidth")) { if (GetIntegerArguments(rest, &rest, val, 1)) { SSET_HANDLE_WIDTH(*ps, (short)*val); ps->flags.has_handle_width = 1; ps->flag_mask.has_handle_width = 1; ps->change_mask.has_handle_width = 1; } else { ps->flags.has_handle_width = 0; ps->flag_mask.has_handle_width = 1; ps->change_mask.has_handle_width = 1; } } else if (StrEquals(token, "HilightFore")) { rest = GetNextToken(rest, &token); if (token) { SAFEFREE(SGET_FORE_COLOR_NAME_HI(*ps)); SSET_FORE_COLOR_NAME_HI(*ps, token); ps->flags.has_color_fore_hi = 1; ps->flag_mask.has_color_fore_hi = 1; ps->change_mask.has_color_fore_hi = 1; ps->flags.use_colorset_hi = 0; ps->flag_mask.use_colorset_hi = 1; ps->change_mask.use_colorset_hi = 1; } else { fvwm_msg( ERR, "style_parse_one_style_option", "HilightFore Style needs color" " argument"); } } else if (StrEquals(token, "HilightBack")) { rest = GetNextToken(rest, &token); if (token) { SAFEFREE(SGET_BACK_COLOR_NAME_HI(*ps)); SSET_BACK_COLOR_NAME_HI(*ps, token); ps->flags.has_color_back_hi = 1; ps->flag_mask.has_color_back_hi = 1; ps->change_mask.has_color_back_hi = 1; ps->flags.use_colorset_hi = 0; ps->flag_mask.use_colorset_hi = 1; ps->change_mask.use_colorset_hi = 1; } else { fvwm_msg( ERR, "style_parse_one_style_option", "HilightBack Style needs color" " argument"); } } else if (StrEquals(token, "HilightColorset")) { *val = -1; GetIntegerArguments(rest, &rest, val, 1); SSET_COLORSET_HI(*ps, *val); alloc_colorset(*val); ps->flags.use_colorset_hi = (*val >= 0); ps->flag_mask.use_colorset_hi = 1; ps->change_mask.use_colorset_hi = 1; } else if (StrEquals(token, "HilightBorderColorset")) { *val = -1; GetIntegerArguments(rest, &rest, val, 1); SSET_BORDER_COLORSET_HI(*ps, *val); alloc_colorset(*val); ps->flags.use_border_colorset_hi = (*val >= 0); ps->flag_mask.use_border_colorset_hi = 1; ps->change_mask.use_border_colorset_hi = 1; } else if (StrEquals(token, "HilightIconTitleColorset")) { *val = -1; GetIntegerArguments(rest, &rest, val, 1); SSET_ICON_TITLE_COLORSET_HI(*ps, *val); alloc_colorset(*val); ps->flags.use_icon_title_colorset_hi = (*val >= 0); ps->flag_mask.use_icon_title_colorset_hi = 1; ps->change_mask.use_icon_title_colorset_hi = 1; } else { found = False; } break; case 'i': if (StrEquals(token, "Icon")) { if (on == 1) { rest = GetNextToken(rest, &token); SAFEFREE(SGET_ICON_NAME(*ps)); SSET_ICON_NAME(*ps,token); ps->flags.has_icon = (token != NULL); ps->flag_mask.has_icon = 1; ps->change_mask.has_icon = 1; S_SET_IS_ICON_SUPPRESSED(SCF(*ps), 0); S_SET_IS_ICON_SUPPRESSED(SCM(*ps), 1); S_SET_IS_ICON_SUPPRESSED(SCC(*ps), 1); } else { S_SET_IS_ICON_SUPPRESSED(SCF(*ps), 1); S_SET_IS_ICON_SUPPRESSED(SCM(*ps), 1); S_SET_IS_ICON_SUPPRESSED(SCC(*ps), 1); } } else if (StrEquals(token, "IconBackgroundColorset")) { *val = -1; GetIntegerArguments(rest, &rest, val, 1); SSET_ICON_BACKGROUND_COLORSET(*ps, *val); alloc_colorset(*val); ps->flags.use_icon_background_colorset = (*val >= 0); ps->flag_mask.use_icon_background_colorset = 1; ps->change_mask.use_icon_background_colorset = 1; } else if (StrEquals(token, "IconBackgroundPadding")) { *val = ICON_BACKGROUND_PADDING; GetIntegerArguments(rest, &rest, val, 1); if (*val < 0) { *val = 0; } else if (*val > 50) { *val = 50; } SSET_ICON_BACKGROUND_PADDING(*ps, (unsigned char)*val); ps->flags.has_icon_background_padding = 1; ps->flag_mask.has_icon_background_padding = 1; ps->change_mask.has_icon_background_padding = 1; } else if (StrEquals(token, "IconBackgroundRelief")) { *val = ICON_RELIEF_WIDTH; GetIntegerArguments(rest, &rest, val, 1); if (*val < -50) { *val = -50; } else if (*val > 50) { *val = 50; } SSET_ICON_BACKGROUND_RELIEF(*ps, (signed char)*val); ps->flags.has_icon_background_relief = 1; ps->flag_mask.has_icon_background_relief = 1; ps->change_mask.has_icon_background_relief = 1; } else if (StrEquals(token, "IconFont")) { SAFEFREE(SGET_ICON_FONT(*ps)); rest = GetNextToken(rest, &token); SSET_ICON_FONT(*ps, token); S_SET_HAS_ICON_FONT(SCF(*ps), (token != NULL)); S_SET_HAS_ICON_FONT(SCM(*ps), 1); S_SET_HAS_ICON_FONT(SCC(*ps), 1); } else if (StrEquals(token, "IconOverride")) { S_SET_ICON_OVERRIDE(SCF(*ps), ICON_OVERRIDE); S_SET_ICON_OVERRIDE(SCM(*ps), ICON_OVERRIDE_MASK); S_SET_ICON_OVERRIDE(SCC(*ps), ICON_OVERRIDE_MASK); } else if (StrEquals(token, "IgnoreRestack")) { S_SET_DO_IGNORE_RESTACK(SCF(*ps), on); S_SET_DO_IGNORE_RESTACK(SCM(*ps), 1); S_SET_DO_IGNORE_RESTACK(SCC(*ps), 1); } else if (StrEquals(token, "IconTitle")) { S_SET_HAS_NO_ICON_TITLE(SCF(*ps), !on); S_SET_HAS_NO_ICON_TITLE(SCM(*ps), 1); S_SET_HAS_NO_ICON_TITLE(SCC(*ps), 1); } else if (StrEquals(token, "IconTitleFormat")) { char *fmt_string = NULL; (rest != NULL) ? fmt_string = strdup(rest) : NULL; rest = NULL; /* Consume the string. */ if (fmt_string == NULL) { fmt_string = DEFAULT_TITLE_FORMAT; } if (!__validate_titleformat_string(fmt_string)) { fvwm_msg(ERR, "style_parse_one_style_option", "TitleFormat string invalid: %s", fmt_string); } SSET_ICON_TITLE_FORMAT_STRING(*ps, fmt_string); ps->flags.has_icon_title_format_string = 1; ps->flag_mask.has_icon_title_format_string = 1; ps->change_mask.has_icon_title_format_string = 1; } else if (StrEquals(token, "IconTitleColorset")) { *val = -1; GetIntegerArguments(rest,&rest, val, 1); SSET_ICON_TITLE_COLORSET(*ps, *val); alloc_colorset(*val); ps->flags.use_icon_title_colorset = (*val >= 0); ps->flag_mask.use_icon_title_colorset = 1; ps->change_mask.use_icon_title_colorset = 1; } else if (StrEquals(token, "IconTitleRelief")) { *val = ICON_RELIEF_WIDTH; GetIntegerArguments(rest, &rest, val, 1); if (*val < -50) { *val = -50; } else if (*val > 50) { *val = 50; } SSET_ICON_TITLE_RELIEF(*ps, (signed char)*val); ps->flags.has_icon_title_relief = 1; ps->flag_mask.has_icon_title_relief = 1; ps->change_mask.has_icon_title_relief = 1; } else if (StrEquals(token, "IconSize")) { rest = style_parse_icon_size_style(token, rest, ps); } else if (StrEquals(token, "IconBox")) { rest = style_parse_icon_box_style(cur_ib, token, rest, ps); } /* end iconbox parameter */ else if (StrEquals(token, "ICONGRID")) { rest = style_parse_icon_grid_style(token, rest, ps, *cur_ib); } else if (StrEquals(token, "ICONFILL")) { rest = style_parse_icon_fill_style(token, rest, ps, *cur_ib); } /* end iconfill */ else if (StrEquals(token, "IconifyWindowGroups")) { S_SET_DO_ICONIFY_WINDOW_GROUPS(SCF(*ps), on); S_SET_DO_ICONIFY_WINDOW_GROUPS(SCM(*ps), 1); S_SET_DO_ICONIFY_WINDOW_GROUPS(SCC(*ps), 1); } else if (StrEquals(token, "IconifyWindowGroupsOff")) { S_SET_DO_ICONIFY_WINDOW_GROUPS(SCF(*ps), !on); S_SET_DO_ICONIFY_WINDOW_GROUPS(SCM(*ps), 1); S_SET_DO_ICONIFY_WINDOW_GROUPS(SCC(*ps), 1); } else if (StrEquals(token, "Iconifiable")) { S_SET_IS_UNICONIFIABLE(SCF(*ps), !on); S_SET_IS_UNICONIFIABLE(SCM(*ps), 1); S_SET_IS_UNICONIFIABLE(SCC(*ps), 1); } else if (StrEquals(token, "IndexedWindowName")) { char *format; /* TA: This is being deprecated in favour of the more * generic: * * TitleFormat %n */ fvwm_msg(WARN, "style_parse_one_style_option", "IndexedWindowName is deprecated. " "Converting to use: TitleFormat %%n (%%t)"); format = strdup( "%n (%t)" ); SSET_TITLE_FORMAT_STRING(*ps, format); ps->flags.has_title_format_string = 1; ps->flag_mask.has_title_format_string = 1; ps->change_mask.has_title_format_string = 1; } else if (StrEquals(token, "IndexedIconName")) { char *format; /* TA: This is being deprecated in favour of the more * generic: * * TitleFormat %n */ fvwm_msg(WARN, "style_parse_one_style_option", "IndexedIconName is deprecated. " "Converting to use: IconTitleFormat %%n (%%t)"); format = strdup( "%n (%t)" ); SSET_ICON_TITLE_FORMAT_STRING(*ps, format); ps->flags.has_icon_title_format_string = 1; ps->flag_mask.has_icon_title_format_string = 1; ps->change_mask.has_icon_title_format_string = 1; } else if (StrEquals(token, "InitialMapCommand")) { char *s; s = (rest != NULL) ? strdup(rest) : NULL; SSET_INITIAL_MAP_COMMAND_STRING(*ps, s); ps->flags.has_initial_map_command_string = on; ps->flag_mask.has_initial_map_command_string = on; ps->change_mask.has_initial_map_command_string = 1; rest = NULL; /* consume the entire string */ } else { found = False; } break; case 'j': if (0) { } else { found = False; } break; case 'k': if (StrEquals(token, "KeepWindowGroupsOnDesk")) { S_SET_DO_USE_WINDOW_GROUP_HINT(SCF(*ps), on); S_SET_DO_USE_WINDOW_GROUP_HINT(SCM(*ps), 1); S_SET_DO_USE_WINDOW_GROUP_HINT(SCC(*ps), 1); } else { found = False; } break; case 'l': if (StrEquals(token, "LeftTitleRotatedCW")) { S_SET_IS_LEFT_TITLE_ROTATED_CW(SCF(*ps), on); S_SET_IS_LEFT_TITLE_ROTATED_CW(SCM(*ps), 1); S_SET_IS_LEFT_TITLE_ROTATED_CW(SCC(*ps), 1); } else if (StrEquals(token, "LeftTitleRotatedCCW")) { S_SET_IS_LEFT_TITLE_ROTATED_CW(SCF(*ps), !on); S_SET_IS_LEFT_TITLE_ROTATED_CW(SCM(*ps), 1); S_SET_IS_LEFT_TITLE_ROTATED_CW(SCC(*ps), 1); } else if (StrEquals(token, "Lenience")) { FPS_LENIENT(S_FOCUS_POLICY(SCF(*ps)), on); FPS_LENIENT(S_FOCUS_POLICY(SCM(*ps)), 1); FPS_LENIENT(S_FOCUS_POLICY(SCC(*ps)), 1); } else if (StrEquals(token, "Layer")) { *val = -1; if (GetIntegerArguments(rest, &rest, val, 1) && *val < 0) { fvwm_msg(ERR, "style_parse_one_style_option", "Layer must be positive or zero."); } if (*val < 0) { SSET_LAYER(*ps, -9); /* mark layer unset */ ps->flags.use_layer = 0; ps->flag_mask.use_layer = 1; ps->change_mask.use_layer = 1; } else { SSET_LAYER(*ps, *val); ps->flags.use_layer = 1; ps->flag_mask.use_layer = 1; ps->change_mask.use_layer = 1; } } else if (StrEquals(token, "LOWERTRANSIENT")) { S_SET_DO_LOWER_TRANSIENT(SCF(*ps), on); S_SET_DO_LOWER_TRANSIENT(SCM(*ps), 1); S_SET_DO_LOWER_TRANSIENT(SCC(*ps), 1); } else { found = False; } break; case 'm': if (StrEquals(token, "ManualPlacement")) { ps->flags.placement_mode = PLACE_MANUAL; ps->flag_mask.placement_mode = PLACE_MASK; ps->change_mask.placement_mode = PLACE_MASK; } else if (StrEquals(token, "ManualPlacementHonorsStartsOnPage")) { ps->flags.manual_placement_honors_starts_on_page = on; ps->flag_mask.manual_placement_honors_starts_on_page = 1; ps->change_mask.manual_placement_honors_starts_on_page = 1; } else if (StrEquals( token, "ManualPlacementIgnoresStartsOnPage")) { ps->flags.manual_placement_honors_starts_on_page = !on; ps->flag_mask.manual_placement_honors_starts_on_page = 1; ps->change_mask.manual_placement_honors_starts_on_page = 1; } else if (StrEquals(token, "Maximizable")) { S_SET_IS_UNMAXIMIZABLE(SCF(*ps), !on); S_SET_IS_UNMAXIMIZABLE(SCM(*ps), 1); S_SET_IS_UNMAXIMIZABLE(SCC(*ps), 1); } else if (StrEquals(token, "MinOverlapPlacement")) { ps->flags.placement_mode = PLACE_MINOVERLAP; ps->flag_mask.placement_mode = PLACE_MASK; ps->change_mask.placement_mode = PLACE_MASK; } else if (StrEquals(token, "MinOverlapPercentPlacement")) { ps->flags.placement_mode = PLACE_MINOVERLAPPERCENT; ps->flag_mask.placement_mode = PLACE_MASK; ps->change_mask.placement_mode = PLACE_MASK; } else if (StrEquals(token, "MinOverlapPlacementPenalties")) { float f[6] = {-1, -1, -1, -1, -1, -1}; Bool bad = False; num = 0; if (on != 0 && rest != NULL) { num = sscanf( rest, "%f %f %f %f %f %f", &f[0], &f[1], &f[2], &f[3], &f[4], &f[5]); for (i=0; i < num; i++) { PeekToken(rest,&rest); if (f[i] < 0) { bad = True; } } } if (bad) { fvwm_msg( ERR, "style_parse_one_style_option", "Bad argument to MinOverlap" "PlacementPenalties: %s", rest); break; } { pl_penalty_struct *p; p = SGET_PLACEMENT_PENALTY_PTR(*ps); *p = default_pl_penalty; } if (num > 0) { (*ps).pl_penalty.normal = f[0]; } if (num > 1) { (*ps).pl_penalty.ontop = f[1]; } if (num > 2) { (*ps).pl_penalty.icon = f[2]; } if (num > 3) { (*ps).pl_penalty.sticky = f[3]; } if (num > 4) { (*ps).pl_penalty.below = f[4]; } if (num > 5) { (*ps).pl_penalty.strut = f[5]; } ps->flags.has_placement_penalty = 1; ps->flag_mask.has_placement_penalty = 1; ps->change_mask.has_placement_penalty = 1; } else if (StrEquals( token, "MinOverlapPercentPlacementPenalties")) { Bool bad = False; num = 0; if (on != 0) { num = GetIntegerArguments(rest, &rest, val, 4); for (i=0; i < num; i++) { if (val[i] < 0) bad = True; } } if (bad) { fvwm_msg( ERR, "style_parse_one_style_option", "Bad argument to MinOverlapPercent" "PlacementPenalties: %s", rest); break; } { pl_percent_penalty_struct *p; p = SGET_PLACEMENT_PERCENTAGE_PENALTY_PTR(*ps); *p = default_pl_percent_penalty; } if (num > 0) { (*ps).pl_percent_penalty.p99 = val[0]; } if (num > 1) { (*ps).pl_percent_penalty.p95 = val[1]; } if (num > 2) { (*ps).pl_percent_penalty.p85 = val[2]; } if (num > 3) { (*ps).pl_percent_penalty.p75 = val[3]; } ps->flags.has_placement_percentage_penalty = 1; ps->flag_mask.has_placement_percentage_penalty = 1; ps->change_mask.has_placement_percentage_penalty = 1; } else if (StrEquals(token, "MwmButtons")) { S_SET_HAS_MWM_BUTTONS(SCF(*ps), on); S_SET_HAS_MWM_BUTTONS(SCM(*ps), 1); S_SET_HAS_MWM_BUTTONS(SCC(*ps), 1); } else if (StrEquals(token, "MiniIcon")) { if (!FMiniIconsSupported) { break; } rest = GetNextToken(rest, &token); if (token) { SAFEFREE(SGET_MINI_ICON_NAME(*ps)); SSET_MINI_ICON_NAME(*ps, token); ps->flags.has_mini_icon = 1; ps->flag_mask.has_mini_icon = 1; ps->change_mask.has_mini_icon = 1; } else { fvwm_msg( ERR, "style_parse_one_style_option", "MiniIcon Style requires an Argument"); } } else if (StrEquals(token, "MwmBorder")) { S_SET_HAS_MWM_BORDER(SCF(*ps), on); S_SET_HAS_MWM_BORDER(SCM(*ps), 1); S_SET_HAS_MWM_BORDER(SCC(*ps), 1); } else if (StrEquals(token, "MwmDecor")) { ps->flags.has_mwm_decor = on; ps->flag_mask.has_mwm_decor = 1; ps->change_mask.has_mwm_decor = 1; } else if (StrEquals(token, "MwmFunctions")) { ps->flags.has_mwm_functions = on; ps->flag_mask.has_mwm_functions = 1; ps->change_mask.has_mwm_functions = 1; } else if (StrEquals(token, "MouseFocus")) { style_set_old_focus_policy(ps, 1); } else if (StrEquals(token, "MouseFocusClickRaises")) { FPS_RAISE_FOCUSED_CLIENT_CLICK( S_FOCUS_POLICY(SCF(*ps)), on); FPS_RAISE_FOCUSED_CLIENT_CLICK( S_FOCUS_POLICY(SCM(*ps)), 1); FPS_RAISE_FOCUSED_CLIENT_CLICK( S_FOCUS_POLICY(SCC(*ps)), 1); FPS_RAISE_UNFOCUSED_CLIENT_CLICK( S_FOCUS_POLICY(SCF(*ps)), on); FPS_RAISE_UNFOCUSED_CLIENT_CLICK( S_FOCUS_POLICY(SCM(*ps)), 1); FPS_RAISE_UNFOCUSED_CLIENT_CLICK( S_FOCUS_POLICY(SCC(*ps)), 1); } else if (StrEquals(token, "MouseFocusClickRaisesOff")) { FPS_RAISE_FOCUSED_CLIENT_CLICK( S_FOCUS_POLICY(SCF(*ps)), !on); FPS_RAISE_FOCUSED_CLIENT_CLICK( S_FOCUS_POLICY(SCM(*ps)), 1); FPS_RAISE_FOCUSED_CLIENT_CLICK( S_FOCUS_POLICY(SCC(*ps)), 1); FPS_RAISE_UNFOCUSED_CLIENT_CLICK( S_FOCUS_POLICY(SCF(*ps)), !on); FPS_RAISE_UNFOCUSED_CLIENT_CLICK( S_FOCUS_POLICY(SCM(*ps)), 1); FPS_RAISE_UNFOCUSED_CLIENT_CLICK( S_FOCUS_POLICY(SCC(*ps)), 1); } else if (StrEquals(token, "MinWindowSize")) { int val1; int val2; int val1_unit; int val2_unit; num = GetTwoArguments( rest, &val1, &val2, &val1_unit, &val2_unit); rest = SkipNTokens(rest, num); if (num != 2) { val1 = 0; val2 = 0; } else { val1 = val1 * val1_unit / 100; val2 = val2 * val2_unit / 100; } if (val1 < 0) { val1 = 0; } if (val2 < 0) { val2 = 0; } SSET_MIN_WINDOW_WIDTH(*ps, val1); SSET_MIN_WINDOW_HEIGHT(*ps, val2); ps->flags.has_min_window_size = 1; ps->flag_mask.has_min_window_size = 1; ps->change_mask.has_min_window_size = 1; } else if (StrEquals(token, "MaxWindowSize")) { int val1; int val2; int val1_unit; int val2_unit; num = GetTwoArguments( rest, &val1, &val2, &val1_unit, &val2_unit); rest = SkipNTokens(rest, num); if (num != 2) { val1 = DEFAULT_MAX_MAX_WINDOW_WIDTH; val2 = DEFAULT_MAX_MAX_WINDOW_HEIGHT; } else { val1 = val1 * val1_unit / 100; val2 = val2 * val2_unit / 100; } if (val1 < DEFAULT_MIN_MAX_WINDOW_WIDTH) { val1 = DEFAULT_MIN_MAX_WINDOW_WIDTH; } if (val1 > DEFAULT_MAX_MAX_WINDOW_WIDTH || val1 <= 0) { val1 = DEFAULT_MAX_MAX_WINDOW_WIDTH; } if (val2 < DEFAULT_MIN_MAX_WINDOW_HEIGHT) { val2 = DEFAULT_MIN_MAX_WINDOW_HEIGHT; } if (val2 > DEFAULT_MAX_MAX_WINDOW_HEIGHT || val2 <= 0) { val2 = DEFAULT_MAX_MAX_WINDOW_HEIGHT; } SSET_MAX_WINDOW_WIDTH(*ps, val1); SSET_MAX_WINDOW_HEIGHT(*ps, val2); ps->flags.has_max_window_size = 1; ps->flag_mask.has_max_window_size = 1; ps->change_mask.has_max_window_size = 1; } else if (StrEquals(token, "MoveByProgramMethod")) { int i; char *methodlist[] = { "AutoDetect", "UseGravity", "IgnoreGravity", NULL }; i = GetTokenIndex(rest, methodlist, 0, &rest); if (i == -1) { i = WS_CR_MOTION_METHOD_AUTO; } SCR_MOTION_METHOD(&ps->flags) = i; SCR_MOTION_METHOD(&ps->flag_mask) = WS_CR_MOTION_METHOD_MASK; SCR_MOTION_METHOD(&ps->change_mask) = WS_CR_MOTION_METHOD_MASK; } else { found = False; } break; case 'n': if (StrEquals(token, "NoActiveIconOverride")) { S_SET_ICON_OVERRIDE(SCF(*ps), NO_ACTIVE_ICON_OVERRIDE); S_SET_ICON_OVERRIDE(SCM(*ps), ICON_OVERRIDE_MASK); S_SET_ICON_OVERRIDE(SCC(*ps), ICON_OVERRIDE_MASK); } else if (StrEquals(token, "NoIconOverride")) { S_SET_ICON_OVERRIDE(SCF(*ps), NO_ICON_OVERRIDE); S_SET_ICON_OVERRIDE(SCM(*ps), ICON_OVERRIDE_MASK); S_SET_ICON_OVERRIDE(SCC(*ps), ICON_OVERRIDE_MASK); } else if (StrEquals(token, "NoIconTitle")) { S_SET_HAS_NO_ICON_TITLE(SCF(*ps), on); S_SET_HAS_NO_ICON_TITLE(SCM(*ps), 1); S_SET_HAS_NO_ICON_TITLE(SCC(*ps), 1); } else if (StrEquals(token, "NOICON")) { S_SET_IS_ICON_SUPPRESSED(SCF(*ps), on); S_SET_IS_ICON_SUPPRESSED(SCM(*ps), 1); S_SET_IS_ICON_SUPPRESSED(SCC(*ps), 1); } else if (StrEquals(token, "NOTITLE")) { ps->flags.has_no_title = on; ps->flag_mask.has_no_title = 1; ps->change_mask.has_no_title = 1; } else if (StrEquals(token, "NoPPosition")) { ps->flags.use_no_pposition = on; ps->flag_mask.use_no_pposition = 1; ps->change_mask.use_no_pposition = 1; } else if (StrEquals(token, "NoUSPosition")) { ps->flags.use_no_usposition = on; ps->flag_mask.use_no_usposition = 1; ps->change_mask.use_no_usposition = 1; } else if (StrEquals(token, "NoTransientPPosition")) { ps->flags.use_no_transient_pposition = on; ps->flag_mask.use_no_transient_pposition = 1; ps->change_mask.use_no_transient_pposition = 1; } else if (StrEquals(token, "NoTransientUSPosition")) { ps->flags.use_no_transient_usposition = on; ps->flag_mask.use_no_transient_usposition = 1; ps->change_mask.use_no_transient_usposition = 1; } else if (StrEquals(token, "NoIconPosition")) { S_SET_USE_ICON_POSITION_HINT(SCF(*ps), !on); S_SET_USE_ICON_POSITION_HINT(SCM(*ps), 1); S_SET_USE_ICON_POSITION_HINT(SCC(*ps), 1); } else if (StrEquals(token, "NakedTransient")) { ps->flags.do_decorate_transient = !on; ps->flag_mask.do_decorate_transient = 1; ps->change_mask.do_decorate_transient = 1; } else if (StrEquals(token, "NODECORHINT")) { ps->flags.has_mwm_decor = !on; ps->flag_mask.has_mwm_decor = 1; ps->change_mask.has_mwm_decor = 1; } else if (StrEquals(token, "NOFUNCHINT")) { ps->flags.has_mwm_functions = !on; ps->flag_mask.has_mwm_functions = 1; ps->change_mask.has_mwm_functions = 1; } else if (StrEquals(token, "NOOVERRIDE")) { S_SET_HAS_MWM_OVERRIDE(SCF(*ps), !on); S_SET_HAS_MWM_OVERRIDE(SCM(*ps), 1); S_SET_HAS_MWM_OVERRIDE(SCC(*ps), 1); } else if (StrEquals(token, "NORESIZEOVERRIDE") || StrEquals(token, "NORESIZEHINTOVERRIDE")) { S_SET_HAS_OVERRIDE_SIZE(SCF(*ps), !on); S_SET_HAS_OVERRIDE_SIZE(SCM(*ps), 1); S_SET_HAS_OVERRIDE_SIZE(SCC(*ps), 1); } else if (StrEquals(token, "NOHANDLES")) { ps->flags.has_no_handles = on; ps->flag_mask.has_no_handles = 1; ps->change_mask.has_no_handles = 1; } else if (StrEquals(token, "NOLENIENCE")) { FPS_LENIENT(S_FOCUS_POLICY(SCF(*ps)), !on); FPS_LENIENT(S_FOCUS_POLICY(SCM(*ps)), 1); FPS_LENIENT(S_FOCUS_POLICY(SCC(*ps)), 1); } else if (StrEquals(token, "NoButton")) { rest = style_parse_button_style(ps, rest, !on); } else if (StrEquals(token, "NOOLDECOR")) { ps->flags.has_ol_decor = !on; ps->flag_mask.has_ol_decor = 1; ps->change_mask.has_ol_decor = 1; } else if (StrEquals(token, "NeverFocus")) { style_set_old_focus_policy(ps, 3); } else { found = False; } break; case 'o': if (StrEquals(token, "OLDECOR")) { ps->flags.has_ol_decor = on; ps->flag_mask.has_ol_decor = 1; ps->change_mask.has_ol_decor = 1; } else if (StrEquals(token, "Opacity")) { ps->flags.use_parent_relative = !on; ps->flag_mask.use_parent_relative = 1; ps->change_mask.use_parent_relative = 1; } else { found = False; } break; case 'p': if (StrEquals(token, "PositionPlacement")) { char *s; ps->flags.placement_mode = PLACE_POSITION; ps->flag_mask.placement_mode = PLACE_MASK; ps->change_mask.placement_mode = PLACE_MASK; s = (rest != NULL) ? strdup(rest) : NULL; rest = NULL; /* consume the entire string */ SSET_PLACEMENT_POSITION_STRING(*ps, s); ps->flags.has_placement_position_string = 1; ps->flag_mask.has_placement_position_string = 1; ps->change_mask.has_placement_position_string = 1; } else if (StrEquals(token, "ParentalRelativity")) { ps->flags.use_parent_relative = on; ps->flag_mask.use_parent_relative = 1; ps->change_mask.use_parent_relative = 1; } else { found = False; } break; case 'q': if (0) { } else { found = False; } break; case 'r': if (StrEquals(token, "RAISETRANSIENT")) { S_SET_DO_RAISE_TRANSIENT(SCF(*ps), on); S_SET_DO_RAISE_TRANSIENT(SCM(*ps), 1); S_SET_DO_RAISE_TRANSIENT(SCC(*ps), 1); } else if (StrEquals(token, "RANDOMPLACEMENT")) { ps->flags.placement_mode |= PLACE_RANDOM; ps->flag_mask.placement_mode |= PLACE_RANDOM; ps->change_mask.placement_mode |= PLACE_RANDOM; } else if (StrEquals(token, "RECAPTUREHONORSSTARTSONPAGE")) { ps->flags.recapture_honors_starts_on_page = on; ps->flag_mask.recapture_honors_starts_on_page = 1; ps->change_mask.recapture_honors_starts_on_page = 1; } else if (StrEquals(token, "RECAPTUREIGNORESSTARTSONPAGE")) { ps->flags.recapture_honors_starts_on_page = !on; ps->flag_mask.recapture_honors_starts_on_page = 1; ps->change_mask.recapture_honors_starts_on_page = 1; } else if (StrEquals(token, "RESIZEHINTOVERRIDE")) { S_SET_HAS_OVERRIDE_SIZE(SCF(*ps), on); S_SET_HAS_OVERRIDE_SIZE(SCM(*ps), 1); S_SET_HAS_OVERRIDE_SIZE(SCC(*ps), 1); } else if (StrEquals(token, "ResizeOpaque")) { S_SET_DO_RESIZE_OPAQUE(SCF(*ps), on); S_SET_DO_RESIZE_OPAQUE(SCM(*ps), 1); S_SET_DO_RESIZE_OPAQUE(SCC(*ps), 1); } else if (StrEquals(token, "ResizeOutline")) { S_SET_DO_RESIZE_OPAQUE(SCF(*ps), !on); S_SET_DO_RESIZE_OPAQUE(SCM(*ps), 1); S_SET_DO_RESIZE_OPAQUE(SCC(*ps), 1); } else if (StrEquals(token, "RightTitleRotatedCW")) { S_SET_IS_RIGHT_TITLE_ROTATED_CW(SCF(*ps), on); S_SET_IS_RIGHT_TITLE_ROTATED_CW(SCM(*ps), 1); S_SET_IS_RIGHT_TITLE_ROTATED_CW(SCC(*ps), 1); } else if (StrEquals(token, "RightTitleRotatedCCW")) { S_SET_IS_RIGHT_TITLE_ROTATED_CW(SCF(*ps), !on); S_SET_IS_RIGHT_TITLE_ROTATED_CW(SCM(*ps), 1); S_SET_IS_RIGHT_TITLE_ROTATED_CW(SCC(*ps), 1); } else { found = False; } break; case 's': if (StrEquals(token, "SMARTPLACEMENT")) { ps->flags.placement_mode |= PLACE_SMART; ps->flag_mask.placement_mode |= PLACE_SMART; ps->change_mask.placement_mode |= PLACE_SMART; } else if (StrEquals(token, "SkipMapping")) { S_SET_DO_NOT_SHOW_ON_MAP(SCF(*ps), on); S_SET_DO_NOT_SHOW_ON_MAP(SCM(*ps), 1); S_SET_DO_NOT_SHOW_ON_MAP(SCC(*ps), 1); } else if (StrEquals(token, "ShowMapping")) { S_SET_DO_NOT_SHOW_ON_MAP(SCF(*ps), !on); S_SET_DO_NOT_SHOW_ON_MAP(SCM(*ps), 1); S_SET_DO_NOT_SHOW_ON_MAP(SCC(*ps), 1); } else if (StrEquals(token, "StackTransientParent")) { S_SET_DO_STACK_TRANSIENT_PARENT(SCF(*ps), on); S_SET_DO_STACK_TRANSIENT_PARENT(SCM(*ps), 1); S_SET_DO_STACK_TRANSIENT_PARENT(SCC(*ps), 1); } else if (StrEquals(token, "StickyIcon")) { S_SET_IS_ICON_STICKY_ACROSS_PAGES(SCF(*ps), on); S_SET_IS_ICON_STICKY_ACROSS_PAGES(SCM(*ps), 1); S_SET_IS_ICON_STICKY_ACROSS_PAGES(SCC(*ps), 1); S_SET_IS_ICON_STICKY_ACROSS_DESKS(SCF(*ps), on); S_SET_IS_ICON_STICKY_ACROSS_DESKS(SCM(*ps), 1); S_SET_IS_ICON_STICKY_ACROSS_DESKS(SCC(*ps), 1); } else if (StrEquals(token, "StickyAcrossPagesIcon")) { S_SET_IS_ICON_STICKY_ACROSS_PAGES(SCF(*ps), on); S_SET_IS_ICON_STICKY_ACROSS_PAGES(SCM(*ps), 1); S_SET_IS_ICON_STICKY_ACROSS_PAGES(SCC(*ps), 1); } else if (StrEquals(token, "StickyAcrossDesksIcon")) { S_SET_IS_ICON_STICKY_ACROSS_DESKS(SCF(*ps), on); S_SET_IS_ICON_STICKY_ACROSS_DESKS(SCM(*ps), 1); S_SET_IS_ICON_STICKY_ACROSS_DESKS(SCC(*ps), 1); } else if (StrEquals(token, "SlipperyIcon")) { S_SET_IS_ICON_STICKY_ACROSS_PAGES(SCF(*ps), !on); S_SET_IS_ICON_STICKY_ACROSS_PAGES(SCM(*ps), 1); S_SET_IS_ICON_STICKY_ACROSS_PAGES(SCC(*ps), 1); S_SET_IS_ICON_STICKY_ACROSS_DESKS(SCF(*ps), !on); S_SET_IS_ICON_STICKY_ACROSS_DESKS(SCM(*ps), 1); S_SET_IS_ICON_STICKY_ACROSS_DESKS(SCC(*ps), 1); } else if (StrEquals(token, "SloppyFocus")) { style_set_old_focus_policy(ps, 2); } else if (StrEquals(token, "StartIconic")) { ps->flags.do_start_iconic = on; ps->flag_mask.do_start_iconic = 1; ps->change_mask.do_start_iconic = 1; } else if (StrEquals(token, "StartNormal")) { ps->flags.do_start_iconic = !on; ps->flag_mask.do_start_iconic = 1; ps->change_mask.do_start_iconic = 1; } else if (StrEquals(token, "StaysOnBottom")) { SSET_LAYER( *ps, (on) ? Scr.BottomLayer : Scr.DefaultLayer); ps->flags.use_layer = 1; ps->flag_mask.use_layer = 1; ps->change_mask.use_layer = 1; } else if (StrEquals(token, "StaysOnTop")) { SSET_LAYER( *ps, (on) ? Scr.BottomLayer : Scr.DefaultLayer); SSET_LAYER(*ps, Scr.TopLayer); ps->flags.use_layer = 1; ps->flag_mask.use_layer = 1; ps->change_mask.use_layer = 1; } else if (StrEquals(token, "StaysPut")) { SSET_LAYER(*ps, Scr.DefaultLayer); ps->flags.use_layer = 1; ps->flag_mask.use_layer = 1; ps->change_mask.use_layer = 1; } else if (StrEquals(token, "Sticky")) { S_SET_IS_STICKY_ACROSS_PAGES(SCF(*ps), on); S_SET_IS_STICKY_ACROSS_PAGES(SCM(*ps), 1); S_SET_IS_STICKY_ACROSS_PAGES(SCC(*ps), 1); S_SET_IS_STICKY_ACROSS_DESKS(SCF(*ps), on); S_SET_IS_STICKY_ACROSS_DESKS(SCM(*ps), 1); S_SET_IS_STICKY_ACROSS_DESKS(SCC(*ps), 1); } else if (StrEquals(token, "StickyAcrossPages")) { S_SET_IS_STICKY_ACROSS_PAGES(SCF(*ps), on); S_SET_IS_STICKY_ACROSS_PAGES(SCM(*ps), 1); S_SET_IS_STICKY_ACROSS_PAGES(SCC(*ps), 1); } else if (StrEquals(token, "StickyAcrossDesks")) { S_SET_IS_STICKY_ACROSS_DESKS(SCF(*ps), on); S_SET_IS_STICKY_ACROSS_DESKS(SCM(*ps), 1); S_SET_IS_STICKY_ACROSS_DESKS(SCC(*ps), 1); } else if (StrEquals(token, "StickyStippledTitle")) { S_SET_HAS_NO_STICKY_STIPPLED_TITLE(SCF(*ps), !on); S_SET_HAS_NO_STICKY_STIPPLED_TITLE(SCM(*ps), 1); S_SET_HAS_NO_STICKY_STIPPLED_TITLE(SCC(*ps), 1); } else if (StrEquals(token, "StickyStippledIconTitle")) { S_SET_HAS_NO_STICKY_STIPPLED_ICON_TITLE(SCF(*ps), !on); S_SET_HAS_NO_STICKY_STIPPLED_ICON_TITLE(SCM(*ps), 1); S_SET_HAS_NO_STICKY_STIPPLED_ICON_TITLE(SCC(*ps), 1); } else if (StrEquals(token, "Slippery")) { S_SET_IS_STICKY_ACROSS_PAGES(SCF(*ps), !on); S_SET_IS_STICKY_ACROSS_PAGES(SCM(*ps), 1); S_SET_IS_STICKY_ACROSS_PAGES(SCC(*ps), 1); S_SET_IS_STICKY_ACROSS_DESKS(SCF(*ps), !on); S_SET_IS_STICKY_ACROSS_DESKS(SCM(*ps), 1); S_SET_IS_STICKY_ACROSS_DESKS(SCC(*ps), 1); } else if (StrEquals(token, "STARTSONDESK")) { spargs = GetIntegerArguments(rest, NULL, tmpno, 1); if (spargs == 1) { PeekToken(rest,&rest); ps->flags.use_start_on_desk = 1; ps->flag_mask.use_start_on_desk = 1; ps->change_mask.use_start_on_desk = 1; /* RBW - 11/20/1998 - allow for the special * case of -1 */ SSET_START_DESK( *ps, (tmpno[0] > -1) ? tmpno[0] + 1 : tmpno[0]); } else { fvwm_msg(ERR,"style_parse_one_style_option", "bad StartsOnDesk arg: %s", rest); } } /* StartsOnPage is like StartsOnDesk-Plus */ else if (StrEquals(token, "STARTSONPAGE")) { char *ret_rest; spargs = GetIntegerArguments(rest, &ret_rest, tmpno, 3); if (spargs == 1 || spargs == 3) { /* We have a desk no., with or without page. */ /* RBW - 11/20/1998 - allow for the special * case of -1 */ /* Desk is now actual + 1 */ SSET_START_DESK( *ps, (tmpno[0] > -1) ? tmpno[0] + 1 : tmpno[0]); } if (spargs == 2 || spargs == 3) { if (spargs == 3) { /* RBW - 11/20/1998 - allow for the * special case of -1 */ SSET_START_PAGE_X( *ps, (tmpno[1] > -1) ? tmpno[1] + 1 : tmpno[1]); SSET_START_PAGE_Y( *ps, (tmpno[2] > -1) ? tmpno[2] + 1 : tmpno[2]); } else { SSET_START_PAGE_X( *ps, (tmpno[0] > -1) ? tmpno[0] + 1 : tmpno[0]); SSET_START_PAGE_Y( *ps, (tmpno[1] > -1) ? tmpno[1] + 1 : tmpno[1]); } } if (spargs < 1 || spargs > 3) { fvwm_msg(ERR, "style_parse_one_style_option", "bad StartsOnPage args: %s", rest); } else { ps->flags.use_start_on_desk = 1; ps->flag_mask.use_start_on_desk = 1; ps->change_mask.use_start_on_desk = 1; } rest = ret_rest; } else if (StrEquals(token, "STARTSONPAGEINCLUDESTRANSIENTS")) { ps->flags.use_start_on_page_for_transient = on; ps->flag_mask.use_start_on_page_for_transient = 1; ps->change_mask.use_start_on_page_for_transient = 1; } else if (StrEquals(token, "STARTSONPAGEIGNORESTRANSIENTS")) { ps->flags.use_start_on_page_for_transient = !on; ps->flag_mask.use_start_on_page_for_transient = 1; ps->change_mask.use_start_on_page_for_transient = 1; } else if (StrEquals(token, "StartsOnScreen")) { if (rest) { tmpno[0] = FScreenGetScreenArgument(rest, 'c'); PeekToken(rest,&rest); ps->flags.use_start_on_screen = 1; ps->flag_mask.use_start_on_screen = 1; ps->change_mask.use_start_on_screen = 1; SSET_START_SCREEN(*ps, tmpno[0]); } else { ps->flags.use_start_on_screen = 0; ps->flag_mask.use_start_on_screen = 1; ps->change_mask.use_start_on_screen = 1; } } else if (StrEquals(token, "STARTSANYWHERE")) { ps->flags.use_start_on_desk = 0; ps->flag_mask.use_start_on_desk = 1; ps->change_mask.use_start_on_desk = 1; } else if (StrEquals(token, "STARTSLOWERED")) { ps->flags.do_start_lowered = on; ps->flag_mask.do_start_lowered = 1; ps->change_mask.do_start_lowered = 1; } else if (StrEquals(token, "STARTSRAISED")) { ps->flags.do_start_lowered = !on; ps->flag_mask.do_start_lowered = 1; ps->change_mask.do_start_lowered = 1; } else if (StrEquals(token, "StartShaded")) { token = PeekToken(rest, &rest); if (token) { direction_t direction; direction = gravity_parse_dir_argument( token, &token, DIR_NONE); if (direction >= 0 && direction <= DIR_MASK) { SSET_STARTS_SHADED_DIR(*ps, direction); } else { fvwm_msg( ERR, "style_parse_one_style_option", "Option: %s is not valid with" " StartShaded", token); } } else { SSET_STARTS_SHADED_DIR(*ps, DIR_N); } ps->flags.do_start_shaded = on; ps->flag_mask.do_start_shaded = 1; ps->change_mask.do_start_shaded = 1; } else if (StrEquals(token, "SaveUnder")) { ps->flags.do_save_under = on; ps->flag_mask.do_save_under = 1; ps->change_mask.do_save_under = 1; } else if (StrEquals(token, "SaveUnderOff")) { ps->flags.do_save_under = !on; ps->flag_mask.do_save_under = 1; ps->change_mask.do_save_under = 1; } else if (StrEquals(token, "StippledTitle")) { S_SET_HAS_STIPPLED_TITLE(SCF(*ps), on); S_SET_HAS_STIPPLED_TITLE(SCM(*ps), 1); S_SET_HAS_STIPPLED_TITLE(SCC(*ps), 1); } else if (StrEquals(token, "StippledTitleOff")) { S_SET_HAS_STIPPLED_TITLE(SCF(*ps), !on); S_SET_HAS_STIPPLED_TITLE(SCM(*ps), 1); S_SET_HAS_STIPPLED_TITLE(SCC(*ps), 1); } else if (StrEquals(token, "StippledIconTitle")) { S_SET_HAS_STIPPLED_ICON_TITLE(SCF(*ps), on); S_SET_HAS_STIPPLED_ICON_TITLE(SCM(*ps), 1); S_SET_HAS_STIPPLED_ICON_TITLE(SCC(*ps), 1); } else if (StrEquals(token, "ScatterWindowGroups")) { S_SET_DO_USE_WINDOW_GROUP_HINT(SCF(*ps), !on); S_SET_DO_USE_WINDOW_GROUP_HINT(SCM(*ps), 1); S_SET_DO_USE_WINDOW_GROUP_HINT(SCC(*ps), 1); } else if (StrEquals(token, "State")) { unsigned int mask; unsigned int states; spargs = GetIntegerArguments(rest, NULL, tmpno, 1); if (spargs == 1 && tmpno[0] >= 0 && tmpno[0] <= 31) { PeekToken(rest,&rest); states = S_USER_STATES(SCF(*ps)); mask = (1 << tmpno[0]); if (on) { states |= mask; } else { states &= ~mask; } S_SET_USER_STATES(SCF(*ps), states); S_ADD_USER_STATES(SCM(*ps), mask); S_ADD_USER_STATES(SCC(*ps), mask); } else { fvwm_msg( ERR,"style_parse_one_style_option", "bad State arg: %s", rest); } } else if (StrEquals(token, "SnapAttraction")) { int val; char *token; int snap_proximity; int snap_mode; do { snap_proximity = DEFAULT_SNAP_ATTRACTION; snap_mode = DEFAULT_SNAP_ATTRACTION_MODE; if ( GetIntegerArguments( rest, &rest, &val, 1) != 1) { break; } if (val >= 0) { snap_proximity = val; } if (val == 0) { break; } token = PeekToken(rest, &rest); if (token == NULL) { break; } if (StrEquals(token, "All")) { snap_mode = SNAP_ICONS | SNAP_WINDOWS; token = PeekToken(rest, &rest); } else if (StrEquals(token, "None")) { snap_mode = SNAP_NONE; token = PeekToken(rest, &rest); } else if (StrEquals(token, "SameType")) { snap_mode = SNAP_SAME; token = PeekToken(rest, &rest); } else if (StrEquals(token, "Icons")) { snap_mode = SNAP_ICONS; token = PeekToken(rest, &rest); } else if (StrEquals(token, "Windows")) { snap_mode = SNAP_WINDOWS; token = PeekToken(rest, &rest); } if (token == NULL) { break; } if (StrEquals(token, "Screen")) { snap_mode |= SNAP_SCREEN; } else if (StrEquals(token, "ScreenWindows")) { snap_mode |= SNAP_SCREEN_WINDOWS; } else if (StrEquals(token, "ScreenIcons")) { snap_mode |= SNAP_SCREEN_ICONS; } else if (StrEquals(token, "ScreenAll")) { snap_mode |= SNAP_SCREEN_ALL; } } while (0); ps->flags.has_snap_attraction = 1; ps->flag_mask.has_snap_attraction = 1; ps->change_mask.has_snap_attraction = 1; SSET_SNAP_PROXIMITY(*ps, snap_proximity); SSET_SNAP_MODE(*ps, snap_mode); } else if (StrEquals(token, "SnapGrid")) { int num; num = GetIntegerArguments(rest, &rest, val, 2); if (num != 2) { val[0] = DEFAULT_SNAP_GRID_X; val[1] = DEFAULT_SNAP_GRID_Y; } if (val[0] < 0) { val[0] = DEFAULT_SNAP_GRID_X; } if (val[1] < 0) { val[1] = DEFAULT_SNAP_GRID_Y; } ps->flags.has_snap_grid = 1; ps->flag_mask.has_snap_grid = 1; ps->change_mask.has_snap_grid = 1; SSET_SNAP_GRID_X(*ps, val[0]); SSET_SNAP_GRID_Y(*ps, val[1]); } else { found = False; } break; case 't': if (StrEquals(token, "TileCascadePlacement")) { ps->flags.placement_mode = PLACE_TILECASCADE; ps->flag_mask.placement_mode = PLACE_MASK; ps->change_mask.placement_mode = PLACE_MASK; } else if (StrEquals(token, "TileManualPlacement")) { ps->flags.placement_mode = PLACE_TILEMANUAL; ps->flag_mask.placement_mode = PLACE_MASK; ps->change_mask.placement_mode = PLACE_MASK; } else if (StrEquals(token, "Title")) { ps->flags.has_no_title = !on; ps->flag_mask.has_no_title = 1; ps->change_mask.has_no_title = 1; } else if (StrEquals(token, "TitleAtBottom")) { S_SET_TITLE_DIR(SCF(*ps), DIR_S); S_SET_TITLE_DIR(SCM(*ps), DIR_MAJOR_MASK); S_SET_TITLE_DIR(SCC(*ps), DIR_MAJOR_MASK); } else if (StrEquals(token, "TitleAtTop")) { S_SET_TITLE_DIR(SCF(*ps), DIR_N); S_SET_TITLE_DIR(SCM(*ps), DIR_MAJOR_MASK); S_SET_TITLE_DIR(SCC(*ps), DIR_MAJOR_MASK); } else if (StrEquals(token, "TitleAtLeft")) { S_SET_TITLE_DIR(SCF(*ps), DIR_W); S_SET_TITLE_DIR(SCM(*ps), DIR_MAJOR_MASK); S_SET_TITLE_DIR(SCC(*ps), DIR_MAJOR_MASK); } else if (StrEquals(token, "TitleAtRight")) { S_SET_TITLE_DIR(SCF(*ps), DIR_E); S_SET_TITLE_DIR(SCM(*ps), DIR_MAJOR_MASK); S_SET_TITLE_DIR(SCC(*ps), DIR_MAJOR_MASK); } else if (StrEquals(token, "TitleFormat")) { char *fmt_string = NULL; (rest != NULL) ? fmt_string = strdup(rest) : NULL; rest = NULL; /* Consume the string. */ if (fmt_string == NULL) { fmt_string = DEFAULT_TITLE_FORMAT; } if (!__validate_titleformat_string(fmt_string)) { fvwm_msg(ERR, "style_parse_one_style_option", "TitleFormat string invalid: %s", fmt_string); } SSET_TITLE_FORMAT_STRING(*ps, fmt_string); ps->flags.has_title_format_string = 1; ps->flag_mask.has_title_format_string = 1; ps->change_mask.has_title_format_string = 1; } else if (StrEquals(token, "TopTitleRotated")) { S_SET_IS_TOP_TITLE_ROTATED(SCF(*ps), on); S_SET_IS_TOP_TITLE_ROTATED(SCM(*ps), 1); S_SET_IS_TOP_TITLE_ROTATED(SCC(*ps), 1); } else if (StrEquals(token, "TopTitleNotRotated")) { S_SET_IS_TOP_TITLE_ROTATED(SCF(*ps), !on); S_SET_IS_TOP_TITLE_ROTATED(SCM(*ps), 1); S_SET_IS_TOP_TITLE_ROTATED(SCC(*ps), 1); } else { found = False; } break; case 'u': if (StrEquals(token, "UsePPosition")) { ps->flags.use_no_pposition = !on; ps->flag_mask.use_no_pposition = 1; ps->change_mask.use_no_pposition = 1; } else if (StrEquals(token, "UseUSPosition")) { ps->flags.use_no_usposition = !on; ps->flag_mask.use_no_usposition = 1; ps->change_mask.use_no_usposition = 1; } else if (StrEquals(token, "UseTransientPPosition")) { ps->flags.use_no_transient_pposition = !on; ps->flag_mask.use_no_transient_pposition = 1; ps->change_mask.use_no_transient_pposition = 1; } else if (StrEquals(token, "UseTransientUSPosition")) { ps->flags.use_no_transient_usposition = !on; ps->flag_mask.use_no_transient_usposition = 1; ps->change_mask.use_no_transient_usposition = 1; } else if (StrEquals(token, "UseIconPosition")) { S_SET_USE_ICON_POSITION_HINT(SCF(*ps), on); S_SET_USE_ICON_POSITION_HINT(SCM(*ps), 1); S_SET_USE_ICON_POSITION_HINT(SCC(*ps), 1); } else if (StrEquals(token, "UseTitleDecorRotation")) { S_SET_USE_TITLE_DECOR_ROTATION(SCF(*ps), on); S_SET_USE_TITLE_DECOR_ROTATION(SCM(*ps), 1); S_SET_USE_TITLE_DECOR_ROTATION(SCC(*ps), 1); } else if (StrEquals(token, "UseDecor")) { SAFEFREE(SGET_DECOR_NAME(*ps)); rest = GetNextToken(rest, &token); SSET_DECOR_NAME(*ps, token); ps->flags.has_decor = (token != NULL); ps->flag_mask.has_decor = 1; ps->change_mask.has_decor = 1; } else if (StrEquals(token, "UseStyle")) { int hit; token = PeekToken(rest, &rest); if (!token) { fvwm_msg(ERR, "style_parse_one_style_option", "UseStyle needs an argument"); break; } hit = 0; /* changed to accum multiple Style definitions * (veliaa@rpi.edu) */ for (add_style = all_styles; add_style; add_style = SGET_NEXT_STYLE(*add_style)) { if (SGET_ID_HAS_NAME(*add_style) && StrEquals(token, SGET_NAME(*add_style))) { /* match style */ hit = 1; merge_styles(ps, add_style, True); } /* end found matching style */ } /* end looking at all styles */ /* move forward one word */ if (!hit) { fvwm_msg( ERR, "style_parse_one_style_option", "UseStyle: %s style not found", token); } } else if (StrEquals(token, "Unmanaged")) { ps->flags.is_unmanaged = on; ps->flag_mask.is_unmanaged = 1; ps->change_mask.is_unmanaged = 1; } else { found = False; } break; case 'v': if (StrEquals(token, "VariablePosition") || StrEquals(token, "VariableUSPosition")) { S_SET_IS_FIXED(SCF(*ps), !on); S_SET_IS_FIXED(SCM(*ps), 1); S_SET_IS_FIXED(SCC(*ps), 1); } else if (StrEquals(token, "VariablePPosition")) { S_SET_IS_FIXED_PPOS(SCF(*ps), !on); S_SET_IS_FIXED_PPOS(SCM(*ps), 1); S_SET_IS_FIXED_PPOS(SCC(*ps), 1); } else if (StrEquals(token, "VariableSize") || StrEquals(token, "VariableUSSize")) { S_SET_IS_SIZE_FIXED(SCF(*ps), !on); S_SET_IS_SIZE_FIXED(SCM(*ps), 1); S_SET_IS_SIZE_FIXED(SCC(*ps), 1); } else if (StrEquals(token, "VariablePSize")) { S_SET_IS_PSIZE_FIXED(SCF(*ps), !on); S_SET_IS_PSIZE_FIXED(SCM(*ps), 1); S_SET_IS_PSIZE_FIXED(SCC(*ps), 1); } else { found = False; } break; case 'w': if (StrEquals(token, "WindowListSkip")) { S_SET_DO_WINDOW_LIST_SKIP(SCF(*ps), on); S_SET_DO_WINDOW_LIST_SKIP(SCM(*ps), 1); S_SET_DO_WINDOW_LIST_SKIP(SCC(*ps), 1); } else if (StrEquals(token, "WindowListHit")) { S_SET_DO_WINDOW_LIST_SKIP(SCF(*ps), !on); S_SET_DO_WINDOW_LIST_SKIP(SCM(*ps), 1); S_SET_DO_WINDOW_LIST_SKIP(SCC(*ps), 1); } else if (StrEquals(token, "WindowShadeSteps")) { int n = 0; int val = 0; int unit = 0; n = GetOnePercentArgument(rest, &val, &unit); if (n != 1) { val = 0; } else { PeekToken(rest,&rest); } /* we have a 'pixel' suffix if unit != 0; negative * values mean pixels */ val = (unit != 0) ? -val : val; ps->flags.has_window_shade_steps = 1; ps->flag_mask.has_window_shade_steps = 1; ps->change_mask.has_window_shade_steps = 1; SSET_WINDOW_SHADE_STEPS(*ps, val); } else if (StrEquals(token, "WindowShadeScrolls")) { S_SET_DO_SHRINK_WINDOWSHADE(SCF(*ps), !on); S_SET_DO_SHRINK_WINDOWSHADE(SCM(*ps), 1); S_SET_DO_SHRINK_WINDOWSHADE(SCC(*ps), 1); } else if (StrEquals(token, "WindowShadeShrinks")) { S_SET_DO_SHRINK_WINDOWSHADE(SCF(*ps), on); S_SET_DO_SHRINK_WINDOWSHADE(SCM(*ps), 1); S_SET_DO_SHRINK_WINDOWSHADE(SCC(*ps), 1); } else if (StrEquals(token, "WindowShadeLazy")) { S_SET_WINDOWSHADE_LAZINESS(SCF(*ps), WINDOWSHADE_LAZY); S_SET_WINDOWSHADE_LAZINESS( SCM(*ps), WINDOWSHADE_LAZY_MASK); S_SET_WINDOWSHADE_LAZINESS( SCC(*ps), WINDOWSHADE_LAZY_MASK); } else if (StrEquals(token, "WindowShadeAlwaysLazy")) { S_SET_WINDOWSHADE_LAZINESS( SCF(*ps), WINDOWSHADE_ALWAYS_LAZY); S_SET_WINDOWSHADE_LAZINESS( SCM(*ps), WINDOWSHADE_LAZY_MASK); S_SET_WINDOWSHADE_LAZINESS( SCC(*ps), WINDOWSHADE_LAZY_MASK); } else if (StrEquals(token, "WindowShadeBusy")) { S_SET_WINDOWSHADE_LAZINESS(SCF(*ps), WINDOWSHADE_BUSY); S_SET_WINDOWSHADE_LAZINESS( SCM(*ps), WINDOWSHADE_LAZY_MASK); S_SET_WINDOWSHADE_LAZINESS( SCC(*ps), WINDOWSHADE_LAZY_MASK); } else { found = False; } break; case 'x': case 'y': case 'z': if (0) { } else { found = False; } break; default: found = False; break; } if (ret_rest) { *ret_rest = rest; } if (token_l != NULL) { free(token_l); } return found; } static void parse_and_set_window_style(char *action, char *prefix, window_style *ps) { char *option; char *token; char *rest; Bool found; /* which current boxes to chain to */ icon_boxes *cur_ib = NULL; while (isspace((unsigned char)*action)) { action++; } while (action && *action && *action != '\n') { action = GetNextFullOption(action, &option); if (!option) { break; } token = PeekToken(option, &rest); if (!token) { free(option); break; } /* It might make more sense to capture the whole word, fix its * case, and use strcmp, but there aren't many caseless compares * because of this "switch" on the first letter. */ found = style_parse_one_style_option( token, rest, &rest, prefix, ps, &cur_ib); if (found == False) { fvwm_msg( ERR, "style_parse_and_set_window_style", "Bad style option: %s", option); /* Can't return here since all malloced memory will be * lost. Ignore rest of line instead. */ /* No, I think we /can/ return here. In fact, /not/ * bombing out leaves a half-done style in the list! * N.Bird 07-Sep-1999 */ /* domivogt (01-Oct-1999): Which is exactly what we * want! Why should all the styles be thrown away if a * single one is mis-spelled? Let's just continue * parsing styles. */ } else if (rest != NULL) { rest = SkipSpaces(rest,NULL,0); if (*rest) { fvwm_msg(WARN, "style_parse_and_set_window_style", "Unconsumed argument in %s: %s", option, rest); } } free(option); } /* end while still stuff on command */ return; } /* Process a style command. First built up in a temp area. * If valid, added to the list in a malloced area. * * *** Important note *** * * Remember that *all* styles need a flag, flag_mask and change_mask. * It is not enough to add the code for new styles in this function. * There *must* be corresponding code in handle_new_window_style() * and merge_styles() too. And don't forget that allocated memory * must be freed in ProcessDestroyStyle(). */ static void __style_command(F_CMD_ARGS, char *prefix, Bool is_window_style) { /* temp area to build name list */ window_style *ps; ps = (window_style *)safemalloc(sizeof(window_style)); /* init temp window_style area */ memset(ps, 0, sizeof(window_style)); /* init default focus policy */ fpol_init_default_fp(&S_FOCUS_POLICY(SCF(*ps))); /* mark style as changed */ ps->has_style_changed = 1; /* set global flag */ Scr.flags.do_need_window_update = 1; /* default StartsOnPage behavior for initial capture */ ps->flags.capture_honors_starts_on_page = 1; if (!is_window_style) { /* parse style name */ action = GetNextToken(action, &SGET_NAME(*ps)); /* in case there was no argument! */ if (SGET_NAME(*ps) == NULL) { free(ps); return; } SSET_ID_HAS_NAME(*ps, True); } else { SSET_WINDOW_ID(*ps, (XID)FW_W(exc->w.fw)); SSET_ID_HAS_WINDOW_ID(*ps, True); CopyString(&SGET_NAME(*ps), ""); /* safe */ } if (action == NULL) { free(SGET_NAME(*ps)); free(ps); return; } parse_and_set_window_style(action, prefix, ps); /* capture default icons */ if (SGET_ID_HAS_NAME(*ps) && StrEquals(SGET_NAME(*ps), "*")) { if (ps->flags.has_icon == 1) { if (Scr.DefaultIcon) { free(Scr.DefaultIcon); } Scr.DefaultIcon = SGET_ICON_NAME(*ps); ps->flags.has_icon = 0; ps->flag_mask.has_icon = 0; ps->change_mask.has_icon = 1; SSET_ICON_NAME(*ps, NULL); } } if (last_style_in_list && styles_have_same_id(ps, last_style_in_list)) { /* merge with previous style */ merge_styles(last_style_in_list, ps, True); free_style(ps); free(ps); } else { /* add temp name list to list */ add_style_to_list(ps); cleanup_style_defaults(ps); } return; } /* ---------------------------- interface functions ------------------------ */ /* Compare two flag structures passed as byte arrays. Only compare bits set in * the mask. * * Returned Value: * zero if the flags are the same * non-zero otherwise * * Inputs: * flags1 - first byte array of flags to compare * flags2 - second byte array of flags to compare * mask - byte array of flags to be considered for the comparison * len - number of bytes to compare */ Bool blockcmpmask(char *blk1, char *blk2, char *mask, int length) { int i; for (i = 0; i < length; i++) { if ((blk1[i] & mask[i]) != (blk2[i] & mask[i])) { /* flags are not the same, return 1 */ return False; } } return True; } void free_icon_boxes(icon_boxes *ib) { icon_boxes *temp; for ( ; ib != NULL; ib = temp) { temp = ib->next; if (ib->use_count == 0) { free(ib); } else { /* we can't delete the icon box yet, it is still in use */ ib->is_orphan = True; } } return; } void simplify_style_list(void) { /* one pass through the style list, then process other events first */ Scr.flags.do_need_style_list_update = __simplify_style_list(); return; } /* lookup_style - look through a list for a window name, or class * * Returned Value: * merged matching styles in callers window_style. * * Inputs: * fw - FvwmWindow structure to match against * styles - callers return area */ void lookup_style(FvwmWindow *fw, window_style *styles) { window_style *nptr; /* clear callers return area */ memset(styles, 0, sizeof(window_style)); /* look thru all styles in order defined. */ for (nptr = all_styles; nptr != NULL; nptr = SGET_NEXT_STYLE(*nptr)) { if (fw_match_style_id(fw, SGET_ID(*nptr))) { merge_styles(styles, nptr, False); } } EWMH_GetStyle(fw, styles); return; } /* This function sets the style update flags as necessary */ void check_window_style_change( FvwmWindow *t, update_win *flags, window_style *ret_style) { int i; char *wf; char *sf; char *sc; lookup_style(t, ret_style); if (!ret_style->has_style_changed && !IS_STYLE_DELETED(t)) { /* nothing to do */ return; } /*** common style flags ***/ wf = (char *)(&FW_COMMON_STATIC_FLAGS(t)); sf = (char *)(&SCFS(*ret_style)); if (IS_STYLE_DELETED(t)) { /* update all styles */ memset(flags, 0xff, sizeof(*flags)); SET_STYLE_DELETED(t, 0); /* copy the static common window flags */ for (i = 0; i < sizeof(SCFS(*ret_style)); i++) { wf[i] = sf[i]; } return; } /* All static common styles can simply be copied. For some there is * additional work to be done below. */ sc = (char *)(&SCCS(*ret_style)); for (i = 0; i < sizeof(SCFS(*ret_style)); i++) { wf[i] = (wf[i] & ~sc[i]) | (sf[i] & sc[i]); sf[i] = wf[i]; } /* is_sticky * is_icon_sticky */ if (S_IS_STICKY_ACROSS_PAGES(SCC(*ret_style)) || S_IS_STICKY_ACROSS_DESKS(SCC(*ret_style))) { flags->do_update_stick = 1; } else if (S_IS_ICON_STICKY_ACROSS_PAGES(SCC(*ret_style)) && IS_ICONIFIED(t) && !IS_STICKY_ACROSS_PAGES(t)) { flags->do_update_stick_icon = 1; } else if (S_IS_ICON_STICKY_ACROSS_DESKS(SCC(*ret_style)) && IS_ICONIFIED(t) && !IS_STICKY_ACROSS_DESKS(t)) { flags->do_update_stick_icon = 1; } /* focus policy */ if (fpol_is_policy_changed(&S_FOCUS_POLICY(SCC(*ret_style)))) { flags->do_setup_focus_policy = 1; } /* is_left_title_rotated_cw * is_right_title_rotated_cw * is_top_title_rotated * is_bottom_title_rotated */ if (S_IS_LEFT_TITLE_ROTATED_CW(SCC(*ret_style)) || S_IS_RIGHT_TITLE_ROTATED_CW(SCC(*ret_style)) || S_IS_TOP_TITLE_ROTATED(SCC(*ret_style)) || S_IS_BOTTOM_TITLE_ROTATED(SCC(*ret_style))) { flags->do_update_title_text_dir = 1; } /* title_dir */ if (S_TITLE_DIR(SCC(*ret_style))) { flags->do_update_title_dir = 1; } /* use_title_decor_rotation */ if (S_USE_TITLE_DECOR_ROTATION(SCC(*ret_style))) { flags->do_update_rotated_title = 1; } /* has_mwm_border * has_mwm_buttons */ if (S_HAS_MWM_BORDER(SCC(*ret_style)) || S_HAS_MWM_BUTTONS(SCC(*ret_style))) { flags->do_redecorate = 1; } /* has_icon_font */ if (S_HAS_ICON_FONT(SCC(*ret_style))) { flags->do_update_icon_font = 1; } /* has_window_font */ if (S_HAS_WINDOW_FONT(SCC(*ret_style))) { flags->do_update_window_font = 1; } /* has_stippled_title */ if (S_HAS_STIPPLED_TITLE(SCC(*ret_style)) || S_HAS_NO_STICKY_STIPPLED_TITLE(SCC(*ret_style)) || S_HAS_STIPPLED_ICON_TITLE(SCC(*ret_style)) || S_HAS_NO_STICKY_STIPPLED_ICON_TITLE(SCC(*ret_style))) { flags->do_redraw_decoration = 1; } /* has_no_icon_title * is_icon_suppressed * * handled below */ /*** private style flags ***/ /* nothing to do for these flags (only used when mapping new windows): * * do_place_random * do_place_smart * do_start_lowered * use_no_pposition * use_no_usposition * use_no_transient_pposition * use_no_transient_usposition * use_start_on_desk * use_start_on_page_for_transient * use_start_on_screen * manual_placement_honors_starts_on_page * capture_honors_starts_on_page * recapture_honors_starts_on_page * ewmh_placement_mode */ /* not implemented yet: * * handling the 'usestyle' style */ /* do_window_list_skip */ if (S_DO_WINDOW_LIST_SKIP(SCC(*ret_style))) { flags->do_update_modules_flags = 1; flags->do_update_ewmh_state_hints = 1; } /* has_icon * icon_override */ if (ret_style->change_mask.has_icon || S_ICON_OVERRIDE(SCC(*ret_style))) { flags->do_update_icon_font = 1; flags->do_update_icon = 1; } /* has_icon_background_padding * has_icon_background_relief * has_icon_title_relief */ if (ret_style->change_mask.has_icon_background_padding || ret_style->change_mask.has_icon_background_relief || ret_style->change_mask.has_icon_title_relief) { flags->do_update_icon = 1; } /* has_no_icon_title * is_icon_suppressed */ if (S_HAS_NO_ICON_TITLE(SCC(*ret_style)) || S_IS_ICON_SUPPRESSED(SCC(*ret_style))) { flags->do_update_icon_font = 1; flags->do_update_icon_title = 1; flags->do_update_icon = 1; flags->do_update_modules_flags = 1; } /* has_icon_size_limits */ if (ret_style->change_mask.has_icon_size_limits) { flags->do_update_icon_size_limits = 1; flags->do_update_icon = 1; } /* has_icon_boxes */ if (ret_style->change_mask.has_icon_boxes) { flags->do_update_icon_boxes = 1; flags->do_update_icon = 1; } /* do_ewmh_donate_icon */ if (S_DO_EWMH_DONATE_ICON(SCC(*ret_style))) { flags->do_update_ewmh_icon = 1; } /* has_mini_icon * do_ewmh_mini_icon_override */ if ( FMiniIconsSupported && ( ret_style->change_mask.has_mini_icon || S_DO_EWMH_MINI_ICON_OVERRIDE(SCC(*ret_style)))) { flags->do_update_mini_icon = 1; flags->do_update_ewmh_mini_icon = 1; flags->do_redecorate = 1; } /* do_ewmh_donate_mini_icon */ if (FMiniIconsSupported && S_DO_EWMH_DONATE_MINI_ICON(SCC(*ret_style))) { flags->do_update_ewmh_mini_icon = 1; } /* has_min_window_size */ /* has_max_window_size */ if (ret_style->change_mask.has_min_window_size) { flags->do_resize_window = 1; flags->do_update_ewmh_allowed_actions = 1; flags->do_update_modules_flags = 1; } if (ret_style->change_mask.has_max_window_size) { flags->do_resize_window = 1; flags->do_update_ewmh_allowed_actions = 1; flags->do_update_modules_flags = 1; } /* has_color_back * has_color_fore * use_colorset * use_border_colorset */ if (ret_style->change_mask.has_color_fore || ret_style->change_mask.has_color_back || ret_style->change_mask.use_colorset || ret_style->change_mask.use_border_colorset) { flags->do_update_window_color = 1; } /* has_color_back_hi * has_color_fore_hi * use_colorset_hi * use_border_colorset_hi */ if (ret_style->change_mask.has_color_fore_hi || ret_style->change_mask.has_color_back_hi || ret_style->change_mask.use_colorset_hi || ret_style->change_mask.use_border_colorset_hi) { flags->do_update_window_color_hi = 1; } /* use_icon_title_colorset */ if (ret_style->change_mask.use_icon_title_colorset) { flags->do_update_icon_title_cs = 1; } /* use_icon_title_colorset_hi */ if (ret_style->change_mask.use_icon_title_colorset_hi) { flags->do_update_icon_title_cs_hi = 1; } /* use_icon_title_colorset */ if (ret_style->change_mask.use_icon_title_colorset) { flags->do_update_icon_title_cs = 1; } /* use_icon_background_colorset */ if (ret_style->change_mask.use_icon_background_colorset) { flags->do_update_icon_background_cs = 1; } /* has_decor */ if (ret_style->change_mask.has_decor) { flags->do_redecorate = 1; flags->do_update_window_font_height = 1; } /* has_no_title */ if (ret_style->change_mask.has_no_title) { flags->do_redecorate = 1; flags->do_update_window_font = 1; } /* do_decorate_transient */ if (ret_style->change_mask.do_decorate_transient) { flags->do_redecorate_transient = 1; } /* has_ol_decor */ if (ret_style->change_mask.has_ol_decor) { /* old decor overrides 'has_no_icon_title'! */ flags->do_update_icon_font = 1; flags->do_update_icon_title = 1; flags->do_update_icon = 1; flags->do_redecorate = 1; } /* Changing layer. */ if (ret_style->change_mask.use_layer) { flags->do_update_layer = 1; } /* has_no_border * has_border_width * has_handle_width * has_mwm_decor * has_mwm_functions * has_no_handles * is_button_disabled */ if (S_HAS_NO_BORDER(SCC(*ret_style)) || ret_style->change_mask.has_border_width || ret_style->change_mask.has_handle_width || ret_style->change_mask.has_mwm_decor || ret_style->change_mask.has_mwm_functions || ret_style->change_mask.has_no_handles || ret_style->change_mask.is_button_disabled) { flags->do_redecorate = 1; flags->do_update_ewmh_allowed_actions = 1; flags->do_update_modules_flags = 1; } if (ret_style->change_mask.do_save_under || ret_style->change_mask.use_backing_store || ret_style->change_mask.use_parent_relative) { flags->do_update_frame_attributes = 1; } if (ret_style->change_mask.use_parent_relative && ret_style->flags.use_parent_relative) { /* needed only for Opacity -> ParentalRelativity */ flags->do_refresh = 1; } /* has_placement_penalty * has_placement_percentage_penalty */ if (ret_style->change_mask.has_placement_penalty || ret_style->change_mask.has_placement_percentage_penalty) { flags->do_update_placement_penalty = 1; } /* do_ewmh_ignore_strut_hints */ if (S_DO_EWMH_IGNORE_STRUT_HINTS(SCC(*ret_style))) { flags->do_update_working_area = 1; } /* do_ewmh_ignore_state_hints */ if (S_DO_EWMH_IGNORE_STATE_HINTS(SCC(*ret_style))) { flags->do_update_ewmh_state_hints = 1; flags->do_update_modules_flags = 1; } /* do_ewmh_use_staking_hints */ if (S_DO_EWMH_USE_STACKING_HINTS(SCC(*ret_style))) { flags->do_update_ewmh_stacking_hints = 1; } /* has_title_format_string */ if (ret_style->change_mask.has_title_format_string) { flags->do_update_visible_window_name = 1; flags->do_redecorate = 1; } /* has_icon_title_format_string */ if (ret_style->change_mask.has_icon_title_format_string) { flags->do_update_visible_icon_name = 1; flags->do_update_icon_title = 1; } /* is_fixed */ if (S_IS_FIXED(SCC(*ret_style)) || S_IS_FIXED_PPOS(SCC(*ret_style)) || S_IS_SIZE_FIXED(SCC(*ret_style)) || S_IS_PSIZE_FIXED(SCC(*ret_style)) || S_HAS_OVERRIDE_SIZE(SCC(*ret_style))) { flags->do_update_ewmh_allowed_actions = 1; flags->do_update_modules_flags = 1; } /* cr_motion_method */ if (SCR_MOTION_METHOD(&ret_style->change_mask)) { flags->do_update_cr_motion_method = 1; } return; } /* Mark all styles as unchanged. */ void reset_style_changes(void) { window_style *temp; for (temp = all_styles; temp != NULL; temp = SGET_NEXT_STYLE(*temp)) { temp->has_style_changed = 0; memset(&SCCS(*temp), 0, sizeof(SCCS(*temp))); memset(&(temp->change_mask), 0, sizeof(temp->change_mask)); } return; } /* Mark styles as updated if their colorset changed. */ void update_style_colorset(int colorset) { window_style *temp; for (temp = all_styles; temp != NULL; temp = SGET_NEXT_STYLE(*temp)) { if (SUSE_COLORSET(&temp->flags) && SGET_COLORSET(*temp) == colorset) { temp->has_style_changed = 1; temp->change_mask.use_colorset = 1; Scr.flags.do_need_window_update = 1; } if (SUSE_COLORSET_HI(&temp->flags) && SGET_COLORSET_HI(*temp) == colorset) { temp->has_style_changed = 1; temp->change_mask.use_colorset_hi = 1; Scr.flags.do_need_window_update = 1; } if (SUSE_BORDER_COLORSET(&temp->flags) && SGET_BORDER_COLORSET(*temp) == colorset) { temp->has_style_changed = 1; temp->change_mask.use_border_colorset = 1; Scr.flags.do_need_window_update = 1; } if (SUSE_BORDER_COLORSET_HI(&temp->flags) && SGET_BORDER_COLORSET_HI(*temp) == colorset) { temp->has_style_changed = 1; temp->change_mask.use_border_colorset_hi = 1; Scr.flags.do_need_window_update = 1; } if (SUSE_ICON_TITLE_COLORSET(&temp->flags) && SGET_ICON_TITLE_COLORSET(*temp) == colorset) { temp->has_style_changed = 1; temp->change_mask.use_icon_title_colorset = 1; Scr.flags.do_need_window_update = 1; } if (SUSE_ICON_TITLE_COLORSET_HI(&temp->flags) && SGET_ICON_TITLE_COLORSET_HI(*temp) == colorset) { temp->has_style_changed = 1; temp->change_mask.use_icon_title_colorset_hi = 1; Scr.flags.do_need_window_update = 1; } if (SUSE_ICON_BACKGROUND_COLORSET(&temp->flags) && SGET_ICON_BACKGROUND_COLORSET(*temp) == colorset) { temp->has_style_changed = 1; temp->change_mask.use_icon_background_colorset = 1; Scr.flags.do_need_window_update = 1; } } return; } /* Update fore and back colours for a specific window */ void update_window_color_style(FvwmWindow *fw, window_style *pstyle) { int cs = Scr.DefaultColorset; if (SUSE_COLORSET(&pstyle->flags)) { cs = SGET_COLORSET(*pstyle); fw->cs = cs; } else { fw->cs = -1; } if (SGET_FORE_COLOR_NAME(*pstyle) != NULL && !SUSE_COLORSET(&pstyle->flags)) { fw->colors.fore = GetColor(SGET_FORE_COLOR_NAME(*pstyle)); } else { fw->colors.fore = Colorset[cs].fg; } if (SGET_BACK_COLOR_NAME(*pstyle) != NULL && !SUSE_COLORSET(&pstyle->flags)) { fw->colors.back = GetColor(SGET_BACK_COLOR_NAME(*pstyle)); fw->colors.shadow = GetShadow(fw->colors.back); fw->colors.hilight = GetHilite(fw->colors.back); } else { fw->colors.hilight = Colorset[cs].hilite; fw->colors.shadow = Colorset[cs].shadow; fw->colors.back = Colorset[cs].bg; } if (SUSE_BORDER_COLORSET(&pstyle->flags)) { cs = SGET_BORDER_COLORSET(*pstyle); fw->border_cs = cs; fw->border_colors.hilight = Colorset[cs].hilite; fw->border_colors.shadow = Colorset[cs].shadow; fw->border_colors.back = Colorset[cs].bg; } else { fw->border_cs = -1; fw->border_colors.hilight = fw->colors.hilight; fw->border_colors.shadow = fw->colors.shadow; fw->border_colors.back = fw->colors.back; } } void update_window_color_hi_style(FvwmWindow *fw, window_style *pstyle) { int cs = Scr.DefaultColorset; if (SUSE_COLORSET_HI(&pstyle->flags)) { cs = SGET_COLORSET_HI(*pstyle); fw->cs_hi = cs; } else { fw->cs_hi = -1; } if ( SGET_FORE_COLOR_NAME_HI(*pstyle) != NULL && !SUSE_COLORSET_HI(&pstyle->flags)) { fw->hicolors.fore = GetColor(SGET_FORE_COLOR_NAME_HI(*pstyle)); } else { fw->hicolors.fore = Colorset[cs].fg; } if ( SGET_BACK_COLOR_NAME_HI(*pstyle) != NULL && !SUSE_COLORSET_HI(&pstyle->flags)) { fw->hicolors.back = GetColor(SGET_BACK_COLOR_NAME_HI(*pstyle)); fw->hicolors.shadow = GetShadow(fw->hicolors.back); fw->hicolors.hilight = GetHilite(fw->hicolors.back); } else { fw->hicolors.hilight = Colorset[cs].hilite; fw->hicolors.shadow = Colorset[cs].shadow; fw->hicolors.back = Colorset[cs].bg; } if (SUSE_BORDER_COLORSET_HI(&pstyle->flags)) { cs = SGET_BORDER_COLORSET_HI(*pstyle); fw->border_cs_hi = cs; fw->border_hicolors.hilight = Colorset[cs].hilite; fw->border_hicolors.shadow = Colorset[cs].shadow; fw->border_hicolors.back = Colorset[cs].bg; } else { fw->border_cs_hi = -1; fw->border_hicolors.hilight = fw->hicolors.hilight; fw->border_hicolors.shadow = fw->hicolors.shadow; fw->border_hicolors.back = fw->hicolors.back; } } void update_icon_title_cs_style(FvwmWindow *fw, window_style *pstyle) { if (SUSE_ICON_TITLE_COLORSET(&pstyle->flags)) { fw->icon_title_cs = SGET_ICON_TITLE_COLORSET(*pstyle); } else { fw->icon_title_cs = -1; } } void update_icon_title_cs_hi_style(FvwmWindow *fw, window_style *pstyle) { if (SUSE_ICON_TITLE_COLORSET_HI(&pstyle->flags)) { fw->icon_title_cs_hi = SGET_ICON_TITLE_COLORSET_HI(*pstyle); } else { fw->icon_title_cs_hi = -1; } } void update_icon_background_cs_style(FvwmWindow *fw, window_style *pstyle) { if (SUSE_ICON_BACKGROUND_COLORSET(&pstyle->flags)) { fw->icon_background_cs = SGET_ICON_BACKGROUND_COLORSET(*pstyle); } else { fw->icon_background_cs = -1; } } void style_destroy_style(style_id_t s_id) { FvwmWindow *t; if (remove_all_of_style_from_list(s_id)) { /* compact the current list of styles */ Scr.flags.do_need_style_list_update = 1; } else { return; } /* mark windows for update */ for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) { if (fw_match_style_id(t, s_id)) { SET_STYLE_DELETED(t, 1); Scr.flags.do_need_window_update = 1; } } return; } void print_styles(int verbose) { window_style *nptr; int count = 0; int mem = 0; fprintf(stderr,"Info on fvwm Styles:\n"); if (verbose) { fprintf(stderr," List of Styles Names:\n"); } for (nptr = all_styles; nptr != NULL; nptr = SGET_NEXT_STYLE(*nptr)) { count++; if (SGET_ID_HAS_NAME(*nptr)) { mem += strlen(SGET_NAME(*nptr)); if (verbose) { fprintf(stderr," * %s\n", SGET_NAME(*nptr)); } } else { mem++; if (verbose) { fprintf(stderr," * 0x%lx\n", (unsigned long)SGET_WINDOW_ID(*nptr)); } } if (SGET_BACK_COLOR_NAME(*nptr)) { mem += strlen(SGET_BACK_COLOR_NAME(*nptr)); if (verbose > 1) { fprintf( stderr," Back Color: %s\n", SGET_BACK_COLOR_NAME(*nptr)); } } if (SGET_FORE_COLOR_NAME(*nptr)) { mem += strlen(SGET_FORE_COLOR_NAME(*nptr)); if (verbose > 1) { fprintf( stderr," Fore Color: %s\n", SGET_FORE_COLOR_NAME(*nptr)); } } if (SGET_BACK_COLOR_NAME_HI(*nptr)) { mem += strlen(SGET_BACK_COLOR_NAME_HI(*nptr)); if (verbose > 1) { fprintf( stderr," Back Color hi: %s\n", SGET_BACK_COLOR_NAME_HI(*nptr)); } } if (SGET_FORE_COLOR_NAME_HI(*nptr)) { mem += strlen(SGET_FORE_COLOR_NAME_HI(*nptr)); if (verbose > 1) { fprintf( stderr," Fore Color hi: %s\n", SGET_FORE_COLOR_NAME_HI(*nptr)); } } if (SGET_DECOR_NAME(*nptr)) { mem += strlen(SGET_DECOR_NAME(*nptr)); if (verbose > 1) { fprintf( stderr," Decor: %s\n", SGET_DECOR_NAME(*nptr)); } } if (SGET_WINDOW_FONT(*nptr)) { mem += strlen(SGET_WINDOW_FONT(*nptr)); if (verbose > 1) { fprintf( stderr," Window Font: %s\n", SGET_WINDOW_FONT(*nptr)); } } if (SGET_ICON_FONT(*nptr)) { mem += strlen(SGET_ICON_FONT(*nptr)); if (verbose > 1) { fprintf( stderr," Icon Font: %s\n", SGET_ICON_FONT(*nptr)); } } if (SGET_ICON_NAME(*nptr)) { mem += strlen(SGET_ICON_NAME(*nptr)); if (verbose > 1) { fprintf( stderr," Icon Name: %s\n", SGET_ICON_NAME(*nptr)); } } if (SGET_MINI_ICON_NAME(*nptr)) { mem += strlen(SGET_MINI_ICON_NAME(*nptr)); if (verbose > 1) { fprintf( stderr," MiniIcon Name: %s\n", SGET_MINI_ICON_NAME(*nptr)); } } if (SGET_ICON_BOXES(*nptr)) { mem += sizeof(icon_boxes); } } fprintf(stderr," Number of styles: %d, Memory Used: %d bits\n", count, (int)(count*sizeof(window_style) + mem)); return; } /* ---------------------------- builtin commands --------------------------- */ void CMD_Style(F_CMD_ARGS) { __style_command(F_PASS_ARGS, NULL, False); return; } void CMD_WindowStyle(F_CMD_ARGS) { __style_command(F_PASS_ARGS, NULL, True); return; } void CMD_FocusStyle(F_CMD_ARGS) { __style_command(F_PASS_ARGS, "FP", False); return; } void CMD_DestroyStyle(F_CMD_ARGS) { char *name; style_id_t s_id; /* parse style name */ name = PeekToken(action, &action); /* in case there was no argument! */ if (name == NULL) return; memset(&s_id, 0, sizeof(style_id_t)); SID_SET_NAME(s_id, name); SID_SET_HAS_NAME(s_id, True); /* Do it */ style_destroy_style(s_id); return; } void CMD_DestroyWindowStyle(F_CMD_ARGS) { style_id_t s_id; memset(&s_id, 0, sizeof(style_id_t)); SID_SET_WINDOW_ID(s_id, (XID)FW_W(exc->w.fw)); SID_SET_HAS_WINDOW_ID(s_id, True); /* Do it */ style_destroy_style(s_id); return; } fvwm-2.7.0/fvwm/menuitem.h0000644000175000017500000001060314147024700012372 00000000000000/* -*-c-*- */ #ifndef MENUITEM_H #define MENUITEM_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ #define MI_NEXT_ITEM(i) ((i)->next) #define MI_PREV_ITEM(i) ((i)->prev) #define MI_LABEL(i) ((i)->label) #define MI_LABEL_OFFSET(i) ((i)->label_offset) #define MI_LABEL_STRLEN(i) ((i)->label_strlen) #define MI_PICTURE(i) ((i)->picture) #define MI_MINI_ICON(i) ((i)->lpicture) #define MI_Y_OFFSET(i) ((i)->y_offset) #define MI_HEIGHT(i) ((i)->height) #define MI_ACTION(i) ((i)->action) #define MI_FUNC_TYPE(i) ((i)->func_type) #define MI_HOTKEY_COFFSET(i) ((i)->hotkey_coffset) #define MI_HOTKEY_COLUMN(i) ((i)->hotkey_column) /* flags */ #define MI_IS_SEPARATOR(i) ((i)->flags.is_separator) #define MI_IS_TEAR_OFF_BAR(i) ((i)->flags.is_tear_off_bar) #define MI_IS_TITLE(i) ((i)->flags.is_title) #define MI_IS_TITLE_CENTERED(i) ((i)->flags.is_title_centered) #define MI_IS_POPUP(i) ((i)->flags.is_popup) #define MI_IS_MENU(i) ((i)->flags.is_menu) #define MI_IS_CONTINUATION(i) ((i)->flags.is_continuation) #define MI_HAS_TEXT(i) ((i)->flags.has_text) #define MI_HAS_PICTURE(i) ((i)->flags.has_picture) #define MI_HAS_HOTKEY(i) ((i)->flags.has_hotkey) #define MI_IS_HOTKEY_AUTOMATIC(i) ((i)->flags.is_hotkey_automatic) #define MI_IS_SELECTABLE(i) ((i)->flags.is_selectable) /* temporary flags */ #define MI_WAS_DESELECTED(i) ((i)->flags.was_deselected) /* ---------------------------- forward declarations ----------------------- */ struct MenuStyle; /* ---------------------------- type definitions --------------------------- */ /* IMPORTANT NOTE: Don't put members into this struct that can change while the * menu is visible! This will wreak havoc on recursive menus. */ typedef struct MenuItem { /* next and prev menu items */ struct MenuItem *next; struct MenuItem *prev; /* the strings displayed in the item */ char *label[MAX_MENU_ITEM_LABELS]; /* witdh of label[i] */ int label_offset[MAX_MENU_ITEM_LABELS]; /* strlen(label[i]) */ int label_strlen[MAX_MENU_ITEM_LABELS]; /* Pixmap to show above label*/ FvwmPicture *picture; /* Pics to show left/right of label */ FvwmPicture *lpicture[MAX_MENU_ITEM_MINI_ICONS]; /* y offset and height for item */ int y_offset; int height; /* action to be performed */ char *action; /* type of built in function */ short func_type; /* Hot key offset (pete@tecc.co.uk). */ int hotkey_coffset; /* The column number the hotkey is defined in*/ char hotkey_column; struct { unsigned is_continuation : 1; unsigned is_separator : 1; unsigned is_tear_off_bar : 1; unsigned is_title : 1; unsigned is_title_centered : 1; unsigned is_popup : 1; unsigned is_menu : 1; unsigned has_text : 1; unsigned has_picture : 1; unsigned has_hotkey : 1; unsigned is_hotkey_automatic : 1; unsigned is_selectable : 1; /* temporary flags */ unsigned was_deselected : 1; } flags; } MenuItem; typedef struct MenuItemPartSizesT { int label_width[MAX_MENU_ITEM_LABELS]; int icon_width[MAX_MENU_ITEM_MINI_ICONS]; int picture_width; int triangle_width; int title_width; } MenuItemPartSizesT; typedef struct MenuPaintItemParameters { struct MenuStyle *ms; Window w; struct MenuItem *selected_item; struct MenuDimensions *dim; FvwmWindow *fw; XEvent *ev; int used_mini_icons; struct MenuRoot *cb_mr; /* number of item labels present in the item format */ Bool (*cb_reset_bg)(struct MenuRoot *mr, XEvent *pevent); struct { unsigned is_first_item : 1; unsigned is_left_triangle : 1; } flags; } MenuPaintItemParameters; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ struct MenuItem *menuitem_clone(struct MenuItem *mi); struct MenuItem *menuitem_create(void); void menuitem_free(struct MenuItem *mi); void menuitem_get_size( struct MenuItem *mi, struct MenuItemPartSizesT *mipst, FlocaleFont *font, Bool do_reverse_icon_order); void menuitem_paint( struct MenuItem *mi, struct MenuPaintItemParameters *mpip); int menuitem_middle_y_offset(struct MenuItem *mi, struct MenuStyle *ms); #endif /* MENUITEM_H */ fvwm-2.7.0/fvwm/focus_policy.h0000644000175000017500000001652314147024700013254 00000000000000/* -*-c-*- */ #ifndef FOCUS_POLICY_H #define FOCUS_POLICY_H /* Note: focus_policy.[ch] is meant to manage structures of type focus_policy_t * only. No code dealing with *any* external data types belongs in here! Put * it in focus.[ch] instead. */ /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ #define FPOL_ANY_MODIFIER 0xff /* ---------------------------- access macros ------------------------------ */ #define FP_DO_RAISE_FOCUSED_CLICK(fp) \ ((fp).do_raise_focused_click) #define FP_DO_RAISE_UNFOCUSED_CLICK(fp) \ ((fp).do_raise_unfocused_click) #define FP_DO_FOCUS_CLICK(fp) \ ((fp).do_focus_click) #define FP_DO_RAISE_FOCUSED_CLIENT_CLICK(fp) \ ((fp).do_raise_focused_click.client) #define FPS_RAISE_FOCUSED_CLIENT_CLICK(fp,x) \ ((fp).do_raise_focused_click.client = !!(x)) #define FP_DO_RAISE_UNFOCUSED_CLIENT_CLICK(fp) \ ((fp).do_raise_unfocused_click.client) #define FPS_RAISE_UNFOCUSED_CLIENT_CLICK(fp,x) \ ((fp).do_raise_unfocused_click.client = !!(x)) #define FP_DO_RAISE_FOCUSED_DECOR_CLICK(fp) \ ((fp).do_raise_focused_click.decor) #define FPS_RAISE_FOCUSED_DECOR_CLICK(fp,x) \ ((fp).do_raise_focused_click.decor = !!(x)) #define FP_DO_RAISE_UNFOCUSED_DECOR_CLICK(fp) \ ((fp).do_raise_unfocused_click.decor) #define FPS_RAISE_UNFOCUSED_DECOR_CLICK(fp,x) \ ((fp).do_raise_unfocused_click.decor = !!(x)) #define FP_DO_RAISE_FOCUSED_ICON_CLICK(fp) \ ((fp).do_raise_focused_click.icon) #define FPS_RAISE_FOCUSED_ICON_CLICK(fp,x) \ ((fp).do_raise_focused_click.icon = !!(x)) #define FP_DO_RAISE_UNFOCUSED_ICON_CLICK(fp) \ ((fp).do_raise_unfocused_click.icon) #define FPS_RAISE_UNFOCUSED_ICON_CLICK(fp,x) \ ((fp).do_raise_unfocused_click.icon = !!(x)) #define FP_DO_FOCUS_ENTER(fp) \ ((fp).do_focus_enter) #define FPS_FOCUS_ENTER(fp,x) \ ((fp).do_focus_enter = !!(x)) #define FP_DO_UNFOCUS_LEAVE(fp) \ ((fp).do_unfocus_leave) #define FPS_UNFOCUS_LEAVE(fp,x) \ ((fp).do_unfocus_leave = !!(x)) #define FP_DO_FOCUS_CLICK_CLIENT(fp) \ ((fp).do_focus_click.client) #define FPS_FOCUS_CLICK_CLIENT(fp,x) \ ((fp).do_focus_click.client = !!(x)) #define FP_DO_FOCUS_CLICK_DECOR(fp) \ ((fp).do_focus_click.decor) #define FPS_FOCUS_CLICK_DECOR(fp,x) \ ((fp).do_focus_click.decor = !!(x)) #define FP_DO_FOCUS_CLICK_ICON(fp) \ ((fp).do_focus_click.icon) #define FPS_FOCUS_CLICK_ICON(fp,x) \ ((fp).do_focus_click.icon = !!(x)) #define FP_DO_FOCUS_BY_PROGRAM(fp) \ ((fp).do_focus_by_program) #define FPS_FOCUS_BY_PROGRAM(fp,x) \ ((fp).do_focus_by_program = !!(x)) #define FP_DO_FOCUS_BY_FUNCTION(fp) \ ((fp).do_focus_by_function) #define FPS_FOCUS_BY_FUNCTION(fp,x) \ ((fp).do_focus_by_function = !!(x)) #define FP_DO_WARP_POINTER_ON_FOCUS_FUNC(fp) \ ((fp).do_warp_pointer_on_focus_func) #define FPS_WARP_POINTER_ON_FOCUS_FUNC(fp,x) \ ((fp).do_warp_pointer_on_focus_func = !!(x)) #define FP_IS_LENIENT(fp) \ ((fp).is_lenient) #define FPS_LENIENT(fp,x) \ ((fp).is_lenient = !!(x)) #define FP_USE_MOUSE_BUTTONS(fp) \ ((fp).use_mouse_buttons) #define FPS_MOUSE_BUTTONS(fp,x) \ ((fp).use_mouse_buttons = (x)) #define FP_USE_MODIFIERS(fp) \ ((fp).use_modifiers) #define FPS_MODIFIERS(fp,x) \ ((fp).use_modifiers = (x)) #define FP_DO_PASS_FOCUS_CLICK(fp) \ ((fp).do_pass_focus_click) #define FPS_PASS_FOCUS_CLICK(fp,x) \ ((fp).do_pass_focus_click = !!(x)) #define FP_DO_PASS_RAISE_CLICK(fp) \ ((fp).do_pass_raise_click) #define FPS_PASS_RAISE_CLICK(fp,x) \ ((fp).do_pass_raise_click = !!(x)) #define FP_DO_IGNORE_FOCUS_CLICK_MOTION(fp) \ ((fp).do_ignore_focus_click_motion) #define FPS_IGNORE_FOCUS_CLICK_MOTION(fp,x) \ ((fp).do_ignore_focus_click_motion = !!(x)) #define FP_DO_IGNORE_RAISE_CLICK_MOTION(fp) \ ((fp).do_ignore_raise_click_motion) #define FPS_IGNORE_RAISE_CLICK_MOTION(fp,x) \ ((fp).do_ignore_raise_click_motion = !!(x)) #define FP_DO_ALLOW_FUNC_FOCUS_CLICK(fp) \ ((fp).do_allow_func_focus_click) #define FPS_ALLOW_FUNC_FOCUS_CLICK(fp,x) \ ((fp).do_allow_func_focus_click = !!(x)) #define FP_DO_ALLOW_FUNC_RAISE_CLICK(fp) \ ((fp).do_allow_func_raise_click) #define FPS_ALLOW_FUNC_RAISE_CLICK(fp,x) \ ((fp).do_allow_func_raise_click = !!(x)) #define FP_DO_GRAB_FOCUS(fp) \ ((fp).do_open_grabs_focus) #define FPS_GRAB_FOCUS(fp,x) \ ((fp).do_open_grabs_focus = !!(x)) #define FP_DO_GRAB_FOCUS_TRANSIENT(fp) \ ((fp).do_open_grabs_focus_transient) #define FPS_GRAB_FOCUS_TRANSIENT(fp,x) \ ((fp).do_open_grabs_focus_transient = !!(x)) #define FP_DO_OVERRIDE_GRAB_FOCUS(fp) \ ((fp).do_override_grab_focus) #define FPS_OVERRIDE_GRAB_FOCUS(fp,x) \ ((fp).do_override_grab_focus = !!(x)) #define FP_DO_RELEASE_FOCUS(fp) \ ((fp).do_close_releases_focus) #define FPS_RELEASE_FOCUS(fp,x) \ ((fp).do_close_releases_focus = !!(x)) #define FP_DO_RELEASE_FOCUS_TRANSIENT(fp) \ ((fp).do_close_releases_focus_transient) #define FPS_RELEASE_FOCUS_TRANSIENT(fp,x) \ ((fp).do_close_releases_focus_transient = !!(x)) #define FP_DO_OVERRIDE_RELEASE_FOCUS(fp) \ ((fp).do_override_release_focus) #define FPS_OVERRIDE_RELEASE_FOCUS(fp,x) \ ((fp).do_override_release_focus = !!(x)) #define FP_DO_SORT_WINDOWLIST_BY(fp) \ ((fp).do_sort_windowlist_by) #define FPS_SORT_WINDOWLIST_BY(fp,x) \ ((fp).do_sort_windowlist_by = !!(x)) /* ---------------------------- type definitions --------------------------- */ typedef enum { FPOL_SORT_WL_BY_FOCUS = 0, FPOL_SORT_WL_BY_OPEN = 1 } fpol_sort_windowlist_t; typedef enum { FOCUS_SET_BY_CLICK_CLIENT, FOCUS_SET_BY_CLICK_DECOR, FOCUS_SET_BY_CLICK_ICON, FOCUS_SET_BY_ENTER, FOCUS_SET_BY_PROGRAM, FOCUS_SET_BY_FUNCTION, /* used internally to restore the focus after certain actions */ FOCUS_SET_FORCE } fpol_set_focus_by_t; typedef struct { unsigned client : 1; unsigned decor : 1; unsigned icon : 1; } fpol_context_t; typedef struct { /* raising the window */ fpol_context_t do_raise_focused_click; fpol_context_t do_raise_unfocused_click; /* focus transition */ fpol_context_t do_focus_click; unsigned do_focus_enter : 1; unsigned do_unfocus_leave : 1; unsigned do_focus_by_program : 1; unsigned do_focus_by_function : 1; unsigned do_warp_pointer_on_focus_func : 1; /* application focus model */ unsigned is_lenient : 1; /* click configuration */ unsigned use_mouse_buttons : NUMBER_OF_EXTENDED_MOUSE_BUTTONS; unsigned use_modifiers : 8; /* recycling of focus and raise clicks */ unsigned do_pass_focus_click : 1; unsigned do_pass_raise_click : 1; unsigned do_ignore_focus_click_motion : 1; unsigned do_ignore_raise_click_motion : 1; unsigned do_allow_func_focus_click : 1; unsigned do_allow_func_raise_click : 1; /* keeping track of the focus */ unsigned do_open_grabs_focus : 1; unsigned do_open_grabs_focus_transient : 1; unsigned do_override_grab_focus : 1; unsigned do_close_releases_focus : 1; unsigned do_close_releases_focus_transient : 1; unsigned do_override_release_focus : 1; unsigned do_sort_windowlist_by : 1; } focus_policy_t; /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ void fpol_init_default_fp( focus_policy_t *fp); int fpol_query_allow_set_focus( focus_policy_t *fpol, fpol_set_focus_by_t set_by_mode); int fpol_query_allow_user_focus( focus_policy_t *fpol); int fpol_is_policy_changed( focus_policy_t *fpol); #endif /* FOCUS_POLICY_H */ fvwm-2.7.0/fvwm/eventmask.h0000644000175000017500000000466314147024676012571 00000000000000/* -*-c-*- */ #ifndef EVENTMASK_H #define EVENTMASK_H /* ---------------------------- global definitions ------------------------- */ #define XEVMASK_FRAMEW \ (SubstructureRedirectMask | VisibilityChangeMask | \ EnterWindowMask | LeaveWindowMask) #define XEVMASK_FRAMEW_CAPTURE (XEVMASK_FRAMEW | StructureNotifyMask) #define XEVMASK_TITLEW \ (ButtonPressMask | ButtonReleaseMask | \ OwnerGrabButtonMask | /*ButtonMotionMask | PointerMotionMask | */\ EnterWindowMask | LeaveWindowMask) #define XEVMASK_BUTTONW \ XEVMASK_TITLEW #define XEVMASK_PARENTW \ (SubstructureRedirectMask) #define XEVMASK_BORDERW \ (ButtonPressMask | ButtonReleaseMask | \ EnterWindowMask | LeaveWindowMask) #define XEVMASK_CLIENTW \ (StructureNotifyMask | PropertyChangeMask | \ EnterWindowMask | LeaveWindowMask | \ ColormapChangeMask | FocusChangeMask) #define XEVMASK_ICONW \ (ButtonPressMask | ButtonReleaseMask | \ VisibilityChangeMask | ExposureMask | KeyPressMask | KeyReleaseMask | \ EnterWindowMask | LeaveWindowMask | FocusChangeMask) #define XEVMASK_ICONPW \ XEVMASK_ICONW #define XEVMASK_MENU \ (ButtonPressMask | ButtonReleaseMask | ExposureMask | KeyReleaseMask | \ KeyPressMask | VisibilityChangeMask | ButtonMotionMask | \ PointerMotionMask) #define XEVMASK_TEAR_OFF_MENU \ (XEVMASK_MENU | LeaveWindowMask | EnterWindowMask) #define XEVMASK_MENUW \ (ExposureMask | KeyPressMask | KeyReleaseMask) #define XEVMASK_TEAR_OFF_MENUW \ (XEVMASK_MENUW | EnterWindowMask | LeaveWindowMask | \ StructureNotifyMask) #define XEVMASK_TEAR_OFF_SUBMENUW \ (XEVMASK_MENUW | LeaveWindowMask) #define XEVMASK_PANFW \ (ButtonPressMask | ButtonReleaseMask | KeyReleaseMask | KeyPressMask | \ EnterWindowMask | LeaveWindowMask | VisibilityChangeMask) #define XEVMASK_NOFOCUSW \ (KeyPressMask | KeyReleaseMask | FocusChangeMask) #define XEVMASK_MENUNFW \ (KeyPressMask | KeyReleaseMask | FocusChangeMask) #define XEVMASK_ORW \ (FocusChangeMask) #define XEVMASK_ROOTW \ (LeaveWindowMask| EnterWindowMask | \ PropertyChangeMask | SubstructureRedirectMask | KeyPressMask | \ KeyReleaseMask | \ SubstructureNotifyMask | ColormapChangeMask | \ STROKE_CODE(ButtonMotionMask | DEFAULT_ALL_BUTTONS_MOTION_MASK |) \ ButtonPressMask | ButtonReleaseMask) #define XEVMASK_RESIZE \ (ButtonPressMask | ButtonReleaseMask | KeyPressMask | \ PointerMotionMask | ButtonMotionMask | ExposureMask) #define XEVMASK_RESIZE_OPAQUE \ (XEVMASK_RESIZE | PropertyChangeMask) #endif /* EVENTMASK_H */ fvwm-2.7.0/fvwm/functions.h0000644000175000017500000000473214147024700012565 00000000000000/* -*-c-*- */ #ifndef FUNCTIONS_H #define FUNCTIONS_H /* ---------------------------- included header files ---------------------- */ #include "execcontext.h" /* ---------------------------- global definitions ------------------------- */ /* Bits for the function flag byte. */ typedef enum { FUNC_NEEDS_WINDOW = 0x01, FUNC_DONT_REPEAT = 0x02, FUNC_ADD_TO = 0x04, FUNC_DECOR = 0x08, FUNC_ALLOW_UNMANAGED = 0x10, /* only to be passed to execute_function() */ FUNC_IS_UNMANAGED = 0x20, FUNC_DONT_EXPAND_COMMAND = 0x40, FUNC_DONT_DEFER = 0x80, /* The values are not used internally but by external scripts parsing * functable. Hence all the values below are 0 */ /* tagging used only for building the documentation */ FUNC_OBSOLETE = 0, FUNC_DEPRECATED = 0, /* command grouping (used only for building the documentation) */ /*!!!*/ FG_BINDING = 0, FG_MODULE = 0, FG_MENU = 0, FG_SESSION = 0, FG_STYLE = 0, FG_MOVE = 0, FG_STATE = 0, FG_COND = 0, FG_USER = 0, FG_COLOR = 0, FG_EWMH_GNOME = 0, FG_VIRTUAL = 0, FG_FOCUS = 0, FG_MISC = 0, FG_OLD = 0 } execute_flags_t; /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ /* used for parsing commands*/ typedef struct { char *keyword; #ifdef __STDC__ void (*action)(F_CMD_ARGS); #else void (*action)(); #endif short func_t; FUNC_FLAGS_TYPE flags; int cursor; } func_t; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ void find_func_t( char *action, short *func_t, FUNC_FLAGS_TYPE *flags); Bool functions_is_complex_function( const char *function_name); void execute_function( cond_rc_t *cond_rc, const exec_context_t *exc, char *action, FUNC_FLAGS_TYPE exec_flags); void execute_function_override_wcontext( cond_rc_t *cond_rc, const exec_context_t *exc, char *action, FUNC_FLAGS_TYPE exec_flags, int wcontext); void execute_function_override_window( cond_rc_t *cond_rc, const exec_context_t *exc, char *action, FUNC_FLAGS_TYPE exec_flags, FvwmWindow *fw); #endif /* FUNCTIONS_H */ fvwm-2.7.0/fvwm/menudim.h0000644000175000017500000000406014147024700012205 00000000000000/* -*-c-*- */ #ifndef MENUDIM_H #define MENUDIM_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ #define MDIM_WIDTH(d) ((d).width) #define MDIM_HEIGHT(d) ((d).height) #define MDIM_ITEM_WIDTH(d) ((d).item_width) #define MDIM_SIDEPIC_X_OFFSET(d) ((d).sidepic_x_offset) #define MDIM_ICON_X_OFFSET(d) ((d).icon_x_offset) #define MDIM_TRIANGLE_X_OFFSET(d) ((d).triangle_x_offset) #define MDIM_ITEM_X_OFFSET(d) ((d).item_text_x_offset) #define MDIM_ITEM_TEXT_Y_OFFSET(d) ((d).item_text_y_offset) #define MDIM_HILIGHT_X_OFFSET(d) ((d).hilight_x_offset) #define MDIM_HILIGHT_WIDTH(d) ((d).hilight_width) #define MDIM_SCREEN_WIDTH(d) ((d).screen_width) #define MDIM_SCREEN_HEIGHT(d) ((d).screen_height) /* ---------------------------- type definitions --------------------------- */ struct MenuDimensions { /* width/height of the menu */ int width; int height; /* width of the actual menu item */ int item_width; /* offset of the sidepic */ int sidepic_x_offset; /* offsets of the mini icons */ int icon_x_offset[MAX_MENU_ITEM_MINI_ICONS]; /* offset of the submenu triangle col */ int triangle_x_offset; /* offset of the actual menu item */ int item_text_x_offset; /* y offset for item text. */ int item_text_y_offset; /* start of the area to be hilighted */ int hilight_x_offset; /* width of the area to be hilighted */ int hilight_width; /* y coordinate for item */ int y_offset; /* width and height of the last screen * the menu was mapped on */ int screen_width; int screen_height; }; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ int menudim_middle_x_offset(struct MenuDimensions *mdim); /* ---------------------------- builtin commands --------------------------- */ #endif /* MENUDIM_H */ fvwm-2.7.0/fvwm/functable.c0000644000175000017500000005716114147024700012517 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include "fvwm.h" #include "execcontext.h" #include "commands.h" #include "cursor.h" #include "functions.h" #include "misc.h" #include "functable.h" /* ---------------------------- local definitions -------------------------- */ /* The function names in the first field *must* be in lowercase or else the * function cannot be called. The func parameter of the macro is also used * for parsing by modules that rely on the old case of the commands. */ #define CMD_ENT(cmd, func, cmd_id, flags, cursor) \ { cmd, func, cmd_id, flags, cursor } /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* IMPORTANT: command description should not be longer than 53 characters. */ /* If you change func_table format, change also perllib/FVWM/create-commands */ /* The next line must be blank for modules to properly parse this file. */ const func_t func_table[] = { /* CMD_ENT("#", CMD_Comment, 0, 0, 0), */ /* # - Comment line (ignored) */ /* CMD_ENT("*", CMD_Asterisk, 0, 0, 0), */ /* * - Module configuration line (no space after asterisk) */ CMD_ENT("+", CMD_Plus, F_ADDMENU2, 0, 0), /* + - Continue the last AddToFunc, AddToMenu or AddToDecor */ CMD_ENT("addbuttonstyle", CMD_AddButtonStyle, F_ADD_BUTTON_STYLE, FUNC_DECOR, 0), /* - Add to a button style (see ButtonStyle) */ CMD_ENT("addtitlestyle", CMD_AddTitleStyle, F_ADD_TITLE_STYLE, FUNC_DECOR, 0), /* - Add to a title style (see TitleStyle) */ CMD_ENT("addtodecor", CMD_AddToDecor, F_ADD_DECOR, 0, 0), /* - Add a decor definition (will be obsolete) */ CMD_ENT("addtofunc", CMD_AddToFunc, F_ADDFUNC, FUNC_ADD_TO, 0), /* - Add a function definition */ CMD_ENT("addtomenu", CMD_AddToMenu, F_ADDMENU, 0, 0), /* - Add a menu definition */ CMD_ENT("all", CMD_All, F_ALL, 0, 0), /* - Operate on all windows matching the given condition */ CMD_ENT("animatedmove", CMD_AnimatedMove, F_ANIMATED_MOVE, FUNC_NEEDS_WINDOW, CRS_MOVE), /* - Like Move, but uses animation to move windows */ CMD_ENT("any", CMD_Any, F_ANY, 0, 0), /* - Operate if there is any window matching the condition */ CMD_ENT("beep", CMD_Beep, F_BEEP, 0, 0), /* - Produce a bell */ CMD_ENT("borderstyle", CMD_BorderStyle, F_BORDERSTYLE, FUNC_DECOR, 0), /* - Define a window border look (will be reworked) */ CMD_ENT("break", CMD_Break, F_BREAK, 0, 0), /* - Stop executing the current (but not parent) function */ CMD_ENT("bugopts", CMD_BugOpts, F_BUG_OPTS, 0, 0), /* - Set some application bug workarounds */ CMD_ENT("busycursor", CMD_BusyCursor, F_BUSY_CURSOR, 0, 0), /* - Show/don't show the wait cursor in certain operations */ CMD_ENT("buttonstate", CMD_ButtonState, F_BUTTON_STATE, 0, 0), /* - Disable some titlebar button states (not recommended) */ CMD_ENT("buttonstyle", CMD_ButtonStyle, F_BUTTON_STYLE, FUNC_DECOR, 0), /* - Define a window button look (will be reworked) */ CMD_ENT("changedecor", CMD_ChangeDecor, F_CHANGE_DECOR, FUNC_NEEDS_WINDOW, CRS_SELECT), /* - Attach decor to a window (will be obsolete) */ CMD_ENT("changemenustyle", CMD_ChangeMenuStyle, F_CHANGE_MENUSTYLE, 0, 0), /* - Attach menu style to a menu (see MenuStyle) */ CMD_ENT("cleanupcolorsets", CMD_CleanupColorsets, F_NOP, 0, 0), /* - Reset all used colorsets with the default gray colors */ CMD_ENT("clicktime", CMD_ClickTime, F_CLICK, 0, 0), /* - Set a time in milliseconds for click and double click */ CMD_ENT("close", CMD_Close, F_CLOSE, FUNC_NEEDS_WINDOW, CRS_DESTROY), /* - Try to Delete a window, if this fails, Destroy it */ CMD_ENT("colorlimit", CMD_ColorLimit, F_COLOR_LIMIT, 0, 0), /* - Set limit on colors used (obsolete) */ CMD_ENT("colormapfocus", CMD_ColormapFocus, F_COLORMAP_FOCUS, 0, 0), /* - Change the colormap behaviour for low-depth X servers */ CMD_ENT("colorset", CMD_Colorset, F_NOP, 0, 0), /* - Manage colors used like fg, bg, image bg, gradient bg */ CMD_ENT("copymenustyle", CMD_CopyMenuStyle, F_COPY_MENU_STYLE, 0, 0), /* - Copy the existing menu style to new or existing one */ CMD_ENT("current", CMD_Current, F_CURRENT, 0, 0), /* - Operate on the currently focused window */ CMD_ENT("cursormove", CMD_CursorMove, F_MOVECURSOR, 0, 0), /* - Move the cursor pointer non interactively */ CMD_ENT("cursorstyle", CMD_CursorStyle, F_CURSOR_STYLE, 0, 0), /* - Define different cursor pointer shapes and colors */ CMD_ENT("defaultcolors", CMD_DefaultColors, F_DFLT_COLORS, 0, 0), /* - Set colors for the feedback window (will be obsolete) */ CMD_ENT("defaultcolorset", CMD_DefaultColorset, F_DFLT_COLORSET, 0, 0), /* - Set colors for the Move/Resize feedback window */ CMD_ENT("defaultfont", CMD_DefaultFont, F_DFLT_FONT, 0, 0), /* - The default font to use (mainly for feedback window) */ CMD_ENT("defaulticon", CMD_DefaultIcon, F_DFLT_ICON, 0, 0), /* - The default icon to use for iconified windows */ CMD_ENT("defaultlayers", CMD_DefaultLayers, F_DFLT_LAYERS, 0, 0), /* - Set StaysOnBottom, StaysPut, StaysOnTop layer numbers */ CMD_ENT("delete", CMD_Delete, F_DELETE, FUNC_NEEDS_WINDOW, CRS_DESTROY), /* - Try to delete a window using the X delete protocol */ CMD_ENT("deschedule", CMD_Deschedule, F_DESCHEDULE, 0, 0), /* - Remove commands sheduled earlier using Schedule */ CMD_ENT("desk", CMD_Desk, F_GOTO_DESK, 0, 0), /* - (obsolete, use GotoDesk instead) */ CMD_ENT("desktopname", CMD_DesktopName, F_DESKTOP_NAME, 0, 0), /* - Define the desktop names used in WindowList, modules */ CMD_ENT("desktopsize", CMD_DesktopSize, F_SETDESK, 0, 0), /* - Set virtual desktop size in units of physical pages */ CMD_ENT("destroy", CMD_Destroy, F_DESTROY, FUNC_NEEDS_WINDOW, CRS_DESTROY), /* - Kill a window without any warning to an application */ CMD_ENT("destroydecor", CMD_DestroyDecor, F_DESTROY_DECOR, 0, 0), /* - Delete decor defined by AddToDecor (will be obsolete) */ CMD_ENT("destroyfunc", CMD_DestroyFunc, F_DESTROY_FUNCTION, 0, 0), /* - Delete function defined using AddToFunc */ CMD_ENT("destroymenu", CMD_DestroyMenu, F_DESTROY_MENU, 0, 0), /* - Delete menu defined using AddToMenu */ CMD_ENT("destroymenustyle", CMD_DestroyMenuStyle, F_DESTROY_MENUSTYLE, 0, 0), /* - Delete menu style defined using MenuStyle */ CMD_ENT("destroymoduleconfig", CMD_DestroyModuleConfig, F_DESTROY_MOD, 0, 0), /* - Delete matching module config lines defined using "*" */ CMD_ENT("destroystyle", CMD_DestroyStyle, F_DESTROY_STYLE, 0, 0), /* - Delete style defined using Style */ CMD_ENT("destroywindowstyle", CMD_DestroyWindowStyle, F_DESTROY_WINDOW_STYLE, FUNC_NEEDS_WINDOW, CRS_SELECT), /* - Delete style defined using WindowStyle */ CMD_ENT("direction", CMD_Direction, F_DIRECTION, 0, 0), /* - Operate on the next window in the specified direction */ CMD_ENT("echo", CMD_Echo, F_ECHO, 0, 0), /* - Print message to stderr, mainly for debugging */ CMD_ENT("echofuncdefinition", CMD_EchoFuncDefinition, F_ECHO_FUNC_DEFINITION, 0, 0), /* - Print the definion of a function */ CMD_ENT("edgecommand", CMD_EdgeCommand, F_EDGE_COMMAND, 0, 0), /* - Bind one or another screen edge to an fvwm action */ CMD_ENT("edgeleavecommand", CMD_EdgeLeaveCommand, F_EDGE_LEAVE_COMMAND, 0, 0), /* - Bind one or another screen edge to an fvwm action */ CMD_ENT("edgeresistance", CMD_EdgeResistance, F_EDGE_RES, 0, 0), /* - Control viewport scrolling and window move over edge */ CMD_ENT("edgescroll", CMD_EdgeScroll, F_EDGE_SCROLL, 0, 0), /* - Control how much of the viewport is scrolled if any */ CMD_ENT("edgethickness", CMD_EdgeThickness, F_NOP, 0, 0), /* - Control how closely to edge to run command/scrolling */ CMD_ENT("emulate", CMD_Emulate, F_EMULATE, 0, 0), /* - Only used to position the position/size window */ CMD_ENT("escapefunc", CMD_EscapeFunc, F_ESCAPE_FUNC, 0, 0), /* - Abort a wait or ModuleSynchonous command */ CMD_ENT("ewmhbasestruts", CMD_EwmhBaseStruts, F_EWMH_BASE_STRUTS, 0, 0), /* - Define restricted areas of the screen */ CMD_ENT("ewmhnumberofdesktops", CMD_EwmhNumberOfDesktops, F_EWMH_NUMBER_OF_DESKTOPS, 0, 0), /* - For ewmh pager, define number of desktops */ CMD_ENT("exec", CMD_Exec, F_EXEC, 0, 0), /* - Execute an external command */ CMD_ENT("execuseshell", CMD_ExecUseShell, F_EXEC_SETUP, 0, 0), /* - The shell to use to execute an external command */ CMD_ENT("fakeclick", CMD_FakeClick, F_FAKE_CLICK, 0, 0), /* - Generate a mouse click */ CMD_ENT("fakekeypress", CMD_FakeKeypress, F_FAKE_KEYPRESS, 0, 0), /* - Send a keyboard event to a window */ CMD_ENT("flipfocus", CMD_FlipFocus, F_FLIP_FOCUS, FUNC_NEEDS_WINDOW, CRS_SELECT), /* - Focus a window without rotating windowlist order */ CMD_ENT("focus", CMD_Focus, F_FOCUS, FUNC_NEEDS_WINDOW, CRS_SELECT), /* - Give focus to a window */ CMD_ENT("focusstyle", CMD_FocusStyle, F_FOCUSSTYLE, 0, 0), /* - Configure focus and raise policy for windows */ CMD_ENT("function", CMD_Function, F_FUNCTION, 0, 0), /* Function - Execute a user defined function, see AddToFunc */ CMD_ENT("globalopts", CMD_GlobalOpts, F_GLOBAL_OPTS, 0, 0), /* - (obsolete, use corresponding Style * instead) */ CMD_ENT("gotodesk", CMD_GotoDesk, F_GOTO_DESK, 0, 0), /* - Switch viewport to another desk same page */ CMD_ENT("gotodeskandpage", CMD_GotoDeskAndPage, F_GOTO_DESK, 0, 0), /* - Switch viewport to another desk and page */ CMD_ENT("gotopage", CMD_GotoPage, F_GOTO_PAGE, 0, 0), /* - Switch viewport to another page same desk */ CMD_ENT("hidegeometrywindow", CMD_HideGeometryWindow, F_HIDEGEOMWINDOW, 0, 0), /* - Hide/show the position/size window */ CMD_ENT("hilightcolor", CMD_HilightColor, F_HICOLOR, 0, 0), /* - (obsolete, use Style * HighlightFore/Back) */ CMD_ENT("hilightcolorset", CMD_HilightColorset, F_HICOLORSET, 0, 0), /* - (obsolete, use Style * HighlightColorset) */ CMD_ENT("iconfont", CMD_IconFont, F_ICONFONT, 0, 0), /* - (obsolete, use Style * IconFont) */ CMD_ENT("iconify", CMD_Iconify, F_ICONIFY, FUNC_NEEDS_WINDOW, CRS_SELECT), /* - Change iconification status of a window (minimize) */ CMD_ENT("iconpath", CMD_IconPath, F_ICON_PATH, 0, 0), /* - (obsolete, use ImagePath instead) */ CMD_ENT("ignoremodifiers", CMD_IgnoreModifiers, F_IGNORE_MODIFIERS, 0, 0), /* - Modifiers to ignore on mouse and key bindings */ CMD_ENT("imagepath", CMD_ImagePath, F_IMAGE_PATH, 0, 0), /* - Directories to search for images */ CMD_ENT("infostoreadd", CMD_InfoStoreAdd, F_INFOSTOREADD, 0, 0), /* - Adds an entry (key/value pairs) to the infostore */ CMD_ENT("infostoreclear", CMD_InfoStoreClear, F_INFOSTORECLEAR, 0, 0), /* - Clears all entries from the infostore */ CMD_ENT("infostoreremove", CMD_InfoStoreRemove, F_INFOSTOREREMOVE, 0, 0), /* - Removes an entry from the infostore */ CMD_ENT(PRE_KEEPRC, CMD_KeepRc, F_KEEPRC, 0, 0), /* KeepRc - Do not modify the previous command return code */ CMD_ENT("key", CMD_Key, F_KEY, 0, 0), /* - Bind or unbind a key to an fvwm action */ CMD_ENT("killmodule", CMD_KillModule, F_KILL_MODULE, 0, 0), /* - Stops an fvwm module */ CMD_ENT("layer", CMD_Layer, F_LAYER, FUNC_NEEDS_WINDOW, CRS_SELECT), /* - Change the layer of a window */ CMD_ENT("localepath", CMD_LocalePath, F_LOCALE_PATH, 0, 0), /* - Directories/domains to search for locale data */ CMD_ENT("lower", CMD_Lower, F_LOWER, FUNC_NEEDS_WINDOW, CRS_SELECT), /* - Lower a window within a layer */ CMD_ENT("maximize", CMD_Maximize, F_MAXIMIZE, FUNC_NEEDS_WINDOW, CRS_SELECT), /* - Toggle maximal-size status of a window */ CMD_ENT("menu", CMD_Menu, F_STAYSUP, 0, 0), /* - Display (post) a menu */ CMD_ENT("menustyle", CMD_MenuStyle, F_MENUSTYLE, 0, 0), /* - Control appearance and behavior of a menu */ CMD_ENT("module", CMD_Module, F_MODULE, 0, 0), /* - Invoke an fvwm module */ CMD_ENT("modulelistenonly", CMD_ModuleListenOnly, F_MODULE_LISTEN_ONLY, 0, 0), /* - Invoke an fvwm module */ CMD_ENT("modulepath", CMD_ModulePath, F_MODULE_PATH, 0, 0), /* - Modify the directories to search for an fvwm module */ CMD_ENT("modulesynchronous", CMD_ModuleSynchronous, F_MODULE_SYNC, 0, 0), /* - Invoke an fvwm module synchronously */ CMD_ENT("moduletimeout", CMD_ModuleTimeout, F_NOP, 0, 0), /* - Set timeout value for response from module */ CMD_ENT("mouse", CMD_Mouse, F_MOUSE, 0, 0), /* - Bind or unbind a mouse button press to an fvwm action */ CMD_ENT("move", CMD_Move, F_MOVE, FUNC_NEEDS_WINDOW, CRS_MOVE), /* - Move a window */ CMD_ENT("movethreshold", CMD_MoveThreshold, F_MOVE_THRESHOLD, 0, 0), /* - Set number of pixels in a click and a hold vs. a drag */ CMD_ENT("movetodesk", CMD_MoveToDesk, F_MOVE_TO_DESK, FUNC_NEEDS_WINDOW, CRS_SELECT), /* - Move a window to another desk same page */ CMD_ENT("movetopage", CMD_MoveToPage, F_MOVE_TO_PAGE, FUNC_NEEDS_WINDOW, CRS_SELECT), /* - Move a window to another page same desk */ CMD_ENT("movetoscreen", CMD_MoveToScreen, F_MOVE_TO_SCREEN, FUNC_NEEDS_WINDOW, CRS_SELECT), /* - Move a window to another Xinerama screen */ CMD_ENT("next", CMD_Next, F_NEXT, 0, 0), /* - Operate on the next window matching conditions */ CMD_ENT("none", CMD_None, F_NONE, 0, 0), /* - Perform command if no window matches conditions */ CMD_ENT("nop", CMD_Nop, F_NOP, FUNC_DONT_REPEAT, 0), /* - Do nothing (used internally) */ CMD_ENT("nowindow", CMD_NoWindow, F_NOP, 0, 0), /* - Prefix that runs a command without a window context */ CMD_ENT("opaquemovesize", CMD_OpaqueMoveSize, F_OPAQUE, 0, 0), /* - Set maximum size window fvwm should move opaquely */ CMD_ENT("pick", CMD_Pick, F_PICK, FUNC_NEEDS_WINDOW, CRS_SELECT), /* - Prefix to force a window context, prompted if needed */ CMD_ENT("piperead", CMD_PipeRead, F_READ, 0, 0), /* - Exec system command interpret output as fvwm commands */ CMD_ENT("pixmappath", CMD_PixmapPath, F_PIXMAP_PATH, 0, 0), /* - (obsolete, use ImagePath instead) */ CMD_ENT("placeagain", CMD_PlaceAgain, F_PLACEAGAIN, FUNC_NEEDS_WINDOW, CRS_SELECT), /* - Replace a window using initial window placement logic */ CMD_ENT("pointerkey", CMD_PointerKey, F_POINTERKEY, 0, 0), /* - Bind an action to a key based on pointer not focus */ CMD_ENT("pointerwindow", CMD_PointerWindow, F_POINTERWINDOW, 0, 0), /* - Operate on window under pointer if it meets conditions */ CMD_ENT("popup", CMD_Popup, F_POPUP, 0, 0), /* - Display (pop-up) a menu, see also Menu */ CMD_ENT("prev", CMD_Prev, F_PREV, 0, 0), /* - Operate on the precious window matching conditions */ CMD_ENT("printinfo", CMD_PrintInfo, F_PRINTINFO, 0, 0), /* - Print information about the state of fvwm */ CMD_ENT("propertychange", CMD_PropertyChange, F_NOP, 0, 0), /* - Internal, used for inter-module communication */ CMD_ENT("quit", CMD_Quit, F_QUIT, 0, 0), /* - Exit fvwm */ CMD_ENT("quitscreen", CMD_QuitScreen, F_QUIT_SCREEN, 0, 0), /* - Stop managing the specified screen */ CMD_ENT("quitsession", CMD_QuitSession, F_QUIT_SESSION, 0, 0), /* - Ask session manager to shut down itself and fvwm */ CMD_ENT("raise", CMD_Raise, F_RAISE, FUNC_NEEDS_WINDOW, CRS_SELECT), /* - Raise a window in a layer */ CMD_ENT("raiselower", CMD_RaiseLower, F_RAISELOWER, FUNC_NEEDS_WINDOW, CRS_SELECT), /* - Alternately raise or lower a window in a layer */ CMD_ENT("read", CMD_Read, F_READ, 0, 0), /* - Read fvwm commands from a file */ CMD_ENT("readwritecolors", CMD_ReadWriteColors, F_NOP, 0, 0), /* - Used for colorset speed hacks (will be removed?) */ CMD_ENT("recapture", CMD_Recapture, F_RECAPTURE, 0, 0), /* - Reapply styles to all windows (will be obsolete) */ CMD_ENT("recapturewindow", CMD_RecaptureWindow, F_RECAPTURE_WINDOW, FUNC_NEEDS_WINDOW, CRS_SELECT), /* - Reapply styles to one window (will be obsolete) */ CMD_ENT("refresh", CMD_Refresh, F_REFRESH, 0, 0), /* - Cause all windows to redraw themselves */ CMD_ENT("refreshwindow", CMD_RefreshWindow, F_REFRESH, FUNC_NEEDS_WINDOW, CRS_SELECT), /* - Cause one window to redraw itself */ CMD_ENT(PRE_REPEAT, CMD_Repeat, F_REPEAT, FUNC_DONT_REPEAT, 0), /* - Repeat (very unreliably) the last command, don't use */ CMD_ENT("resize", CMD_Resize, F_RESIZE, FUNC_NEEDS_WINDOW, CRS_RESIZE), /* - Cause a window to be resized */ CMD_ENT("resizemaximize", CMD_ResizeMaximize, F_RESIZE_MAXIMIZE, FUNC_NEEDS_WINDOW, CRS_RESIZE), /* - Resize a window and mark window as maximized */ CMD_ENT("resizemove", CMD_ResizeMove, F_RESIZEMOVE, FUNC_NEEDS_WINDOW, CRS_RESIZE), /* - Resize and move in one operation */ CMD_ENT("resizemovemaximize", CMD_ResizeMoveMaximize, F_RESIZEMOVE_MAXIMIZE, FUNC_NEEDS_WINDOW, CRS_RESIZE), /* - Resize and move in one operation and mark maximized */ CMD_ENT("restacktransients", CMD_RestackTransients, F_RESTACKTRANSIENTS, FUNC_NEEDS_WINDOW, CRS_SELECT), /* - Regroup the window transients in the stack */ CMD_ENT("restart", CMD_Restart, F_RESTART, 0, 0), /* - Restart itself or replace with another window manager */ CMD_ENT("savequitsession", CMD_SaveQuitSession, F_SAVE_QUIT_SESSION, 0, 0), /* - Cause session manager to save and shutdown fvwm */ CMD_ENT("savesession", CMD_SaveSession, F_SAVE_SESSION, 0, 0), /* - Cause session manager to save the session */ CMD_ENT("scanforwindow", CMD_ScanForWindow, F_SCANFORWINDOW, 0, 0), /* - Operate on the matching window in the given direction */ CMD_ENT("schedule", CMD_Schedule, F_SCHEDULE, 0, 0), /* - Run an fvwm command after a delay */ CMD_ENT("scroll", CMD_Scroll, F_SCROLL, 0, 0), /* - Scroll the desktop viewport */ CMD_ENT("send_configinfo", CMD_Send_ConfigInfo, F_CONFIG_LIST, FUNC_DONT_REPEAT, 0), /* - Internal, used for module communication */ CMD_ENT("send_reply", CMD_Send_Reply, F_SEND_REPLY, FUNC_DONT_REPEAT, 0), /* - Internal, used for module communication */ CMD_ENT("send_windowlist", CMD_Send_WindowList, F_SEND_WINDOW_LIST, FUNC_DONT_REPEAT, 0), /* - Internal, used for module communication */ CMD_ENT("sendtomodule", CMD_SendToModule, F_SEND_STRING, FUNC_DONT_REPEAT, 0), /* - Send a string (action) to a module */ CMD_ENT("set_mask", CMD_set_mask, F_SET_MASK, FUNC_DONT_REPEAT, 0), /* - Internal, used for module communication */ CMD_ENT("set_nograb_mask", CMD_set_nograb_mask, F_SET_NOGRAB_MASK, FUNC_DONT_REPEAT, 0), /* - Internal, used for module communication */ CMD_ENT("set_sync_mask", CMD_set_sync_mask, F_SET_SYNC_MASK, FUNC_DONT_REPEAT, 0), /* - Internal, used for module communication */ CMD_ENT("setanimation", CMD_SetAnimation, F_SET_ANIMATION, 0, 0), /* - Control animated moves and menus */ CMD_ENT("setenv", CMD_SetEnv, F_SETENV, 0, 0), /* - Set an environment variable */ CMD_ENT(PRE_SILENT, CMD_Silent, F_SILENT, 0, 0), /* Silent - Suppress errors on command, avoid window selection */ CMD_ENT("snapattraction", CMD_SnapAttraction, F_SNAP_ATT, 0, 0), /* - Control attraction of windows during move */ CMD_ENT("snapgrid", CMD_SnapGrid, F_SNAP_GRID, 0, 0), /* - Control grid used with SnapAttraction */ CMD_ENT("state", CMD_State, F_STATE, FUNC_NEEDS_WINDOW, CRS_SELECT), /* - Control user defined window states */ CMD_ENT("stick", CMD_Stick, F_STICK, FUNC_NEEDS_WINDOW, CRS_SELECT), /* - Change window stickyness */ CMD_ENT("stickacrossdesks", CMD_StickAcrossDesks, F_STICKACROSSDESKS, FUNC_NEEDS_WINDOW, CRS_SELECT), /* - Change window stickyness on a desk basis */ CMD_ENT("stickacrosspages", CMD_StickAcrossPages, F_STICKACROSSPAGES, FUNC_NEEDS_WINDOW, CRS_SELECT), /* - Change window stickyness on a page basis */ #ifdef HAVE_STROKE CMD_ENT("stroke", CMD_Stroke, F_STROKE, 0, 0), /* - Bind a stroke to an fvwm action */ CMD_ENT("strokefunc", CMD_StrokeFunc, F_STROKE_FUNC, 0, 0), /* - Record stroke and execute corresponding stroke action */ #endif /* HAVE_STROKE */ CMD_ENT("style", CMD_Style, F_STYLE, 0, 0), /* - Set attributes of windows that match a pattern */ CMD_ENT("tearmenuoff", CMD_TearMenuOff, F_TEARMENUOFF, 0, 0), /* TearMenuOff - Convert a menu to a window, for use in menu items */ CMD_ENT("test", CMD_Test, F_TEST_, 0, 0), /* - Execute command if conditions are met */ CMD_ENT("testrc", CMD_TestRc, F_TESTRC, 0, 0), /* - Conditional switch (may be changed) */ CMD_ENT("thiswindow", CMD_ThisWindow, F_THISWINDOW, 0, 0), /* - Operate on the context window if it meets conditions */ CMD_ENT("title", CMD_Title, F_TITLE, 0, 0), /* Title - Insert title into a menu */ CMD_ENT("titlestyle", CMD_TitleStyle, F_TITLESTYLE, FUNC_DECOR, 0), /* - Control window title */ CMD_ENT("unsetenv", CMD_UnsetEnv, F_SETENV, 0, 0), /* - Remove an environment variable */ CMD_ENT("updatedecor", CMD_UpdateDecor, F_UPDATE_DECOR, 0, 0), /* - Update window decor (obsolete and not needed anymore) */ CMD_ENT("updatestyles", CMD_UpdateStyles, F_UPDATE_STYLES, 0, 0), /* - Cause styles to update while still in a function */ CMD_ENT("wait", CMD_Wait, F_WAIT, 0, 0), /* - Pause until a matching window appears */ CMD_ENT("warptowindow", CMD_WarpToWindow, F_WARP, FUNC_NEEDS_WINDOW | FUNC_ALLOW_UNMANAGED, CRS_SELECT), /* - Warp the pointer to a window */ CMD_ENT("windowfont", CMD_WindowFont, F_WINDOWFONT, 0, 0), /* - (obsolete, use Style * Font) */ CMD_ENT("windowid", CMD_WindowId, F_WINDOWID, 0, 0), /* - Execute command for window matching the windowid */ CMD_ENT("windowlist", CMD_WindowList, F_WINDOWLIST, 0, 0), /* - Display the window list as a menu to select a window */ CMD_ENT("windowshade", CMD_WindowShade, F_WINDOW_SHADE, FUNC_NEEDS_WINDOW, CRS_SELECT), /* - Shade/unshade a window */ CMD_ENT("windowshadeanimate", CMD_WindowShadeAnimate, F_SHADE_ANIMATE, 0, 0), /* - (obsolete, use Style * WindowShadeSteps) */ CMD_ENT("windowstyle", CMD_WindowStyle, F_WINDOW_STYLE, FUNC_NEEDS_WINDOW, CRS_SELECT), /* - Set styles on the selected window */ CMD_ENT("xinerama", CMD_Xinerama, F_XINERAMA, 0, 0), /* - Control Xinerama support */ CMD_ENT("xineramaprimaryscreen", CMD_XineramaPrimaryScreen, F_XINERAMAPRIMARYSCREEN, 0, 0), /* - Identify Xinerama primary screen */ CMD_ENT("xineramasls", CMD_XineramaSls, F_XINERAMASLS, 0, 0), /* - Control single logical screen support */ CMD_ENT("xineramaslsscreens", CMD_XineramaSlsScreens, F_XINERAMASLSSCREENS, 0, 0), /* - Configure layout for single logical screen */ CMD_ENT("xineramaslssize", CMD_XineramaSlsSize, F_XINERAMASLSSIZE, 0, 0), /* - Configure layout for single logical screen sizes */ CMD_ENT("xorpixmap", CMD_XorPixmap, F_XOR, 0, 0), /* - Use a pixmap for move/resize rubber-band */ CMD_ENT("xorvalue", CMD_XorValue, F_XOR, 0, 0), /* - Change bits used for move/resize rubber-band */ CMD_ENT("xsync", CMD_XSync, F_XSYNC, 0, 0), /* - For debugging, send all pending requests to X server */ CMD_ENT("xsynchronize", CMD_XSynchronize, F_XSYNCHRONIZE, 0, 0), /* - For debugging, cause all X requests to be synchronous */ { "", 0, 0, 0, 0 } }; fvwm-2.7.0/fvwm/menus.h0000644000175000017500000000372414147024700011704 00000000000000/* -*-c-*- */ #ifndef _MENUS_ #define _MENUS_ #define MENU_IS_LEFT 0x01 #define MENU_IS_RIGHT 0x02 #define MENU_IS_UP 0x04 #define MENU_IS_DOWN 0x08 /* * MISCELLANEOUS MENU STUFF */ #define IS_MENU_RETURN(x) \ ((x)==MENU_DONE || (x)==MENU_ABORTED || (x)==MENU_SUBMENU_TORN_OFF) struct MenuRoot; struct MenuStyle; struct MenuReturn; struct MenuParameters; struct MenuOptions; struct MenuItem; struct MenuRepaintTransparentParameters; /* * EXPORTED FUNCTIONS */ void menus_init(void); struct MenuRoot *menus_find_menu(char *name); void menus_remove_style_from_menus(struct MenuStyle *ms); struct MenuRoot *FollowMenuContinuations( struct MenuRoot *mr, struct MenuRoot **pmrPrior); struct MenuRoot *NewMenuRoot(char *name); void AddToMenu(struct MenuRoot *, char *, char *, Bool, Bool, Bool); void menu_enter_tear_off_menu(const exec_context_t *exc); void menu_close_tear_off_menu(FvwmWindow *fw); Bool menu_redraw_transparent_tear_off_menu(FvwmWindow *fw, Bool pr_only); void do_menu(struct MenuParameters *pmp, struct MenuReturn *pret); char *get_menu_options( char *action, Window w, FvwmWindow *fw, XEvent *e, struct MenuRoot *mr, struct MenuItem *mi, struct MenuOptions *pops); Bool DestroyMenu( struct MenuRoot *mr, Bool do_recreate, Bool is_command_request); void add_another_menu_item(char *action); void change_mr_menu_style(struct MenuRoot *mr, char *stylename); void UpdateAllMenuStyles(void); void UpdateMenuColorset(int cset); void SetMenuCursor(Cursor cursor); void update_transparent_menu_bg( struct MenuRepaintTransparentParameters *prtm, int current_x, int current_y, int step_x, int step_y, int end_x, int end_y); void repaint_transparent_menu( struct MenuRepaintTransparentParameters *prtmp, Bool first, int x, int y, int end_x, int end_y, Bool is_bg_set); Bool menu_expose(XEvent *event, FvwmWindow *fw); int menu_binding(Display *dpy, binding_t type, int button, KeySym keysym, int context, int modifier, char *action, char *menuStyle); #endif /* _MENUS_ */ fvwm-2.7.0/fvwm/ewmh_icons.c0000644000175000017500000004271714147024700012710 00000000000000/* -*-c-*- */ /* Copyright (C) 2001 Olivier Chapuis */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ #include "config.h" #include #include "libs/fvwmlib.h" #include "libs/FShape.h" #include "libs/PictureBase.h" #include "libs/Picture.h" #include "libs/PictureUtils.h" #include "libs/PictureImageLoader.h" #include "libs/FRenderInit.h" #include "libs/Graphics.h" #include "libs/Strings.h" #include "fvwm.h" #include "externs.h" #include "window_flags.h" #include "cursor.h" #include "functions.h" #include "misc.h" #include "screen.h" #include "module_interface.h" #include "borders.h" #include "icons.h" #include "ewmh.h" #include "ewmh_intern.h" /* * net icon handler */ int ewmh_WMIcon( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any) { CARD32 *list = NULL; CARD32 *new_list = NULL; CARD32 *dummy = NULL; int size = 0; if (ev != NULL && HAS_EWMH_WM_ICON_HINT(fw) == EWMH_FVWM_ICON) { /* this event has been produced by fvwm itself */ return 0; } list = ewmh_AtomGetByName(FW_W(fw),"_NET_WM_ICON", EWMH_ATOM_LIST_PROPERTY_NOTIFY, &size); if (list != NULL && HAS_EWMH_WM_ICON_HINT(fw) == EWMH_NO_ICON) { /* the application have a true _NET_WM_ICON */ SET_HAS_EWMH_WM_ICON_HINT(fw, EWMH_TRUE_ICON); } if (list == NULL || HAS_EWMH_WM_ICON_HINT(fw) != EWMH_TRUE_ICON) { /* No net icon or we have set the net icon */ if (DO_EWMH_DONATE_ICON(fw) && (new_list = ewmh_SetWmIconFromPixmap( fw, list, &size, False)) != NULL) { SET_HAS_EWMH_WM_ICON_HINT(fw, EWMH_FVWM_ICON); } } else if (ev != NULL && USE_EWMH_ICON(fw)) { /* client message. the application change its net icon */ ChangeIconPixmap(fw); } if (FMiniIconsSupported) { if (list == NULL || HAS_EWMH_WM_ICON_HINT(fw) != EWMH_TRUE_ICON) { /* No net icon or we have set the net icon */ if (DO_EWMH_DONATE_MINI_ICON(fw) && (dummy = ewmh_SetWmIconFromPixmap( fw, (new_list != NULL)? new_list : list, &size, True)) != NULL) { SET_HAS_EWMH_WM_ICON_HINT( fw, EWMH_FVWM_ICON); free(dummy); } } else { /* the application has a true ewmh icon */ if (EWMH_SetIconFromWMIcon(fw, list, size, True)) { SET_HAS_EWMH_MINI_ICON(fw, True); } } } if (list != NULL) { free(list); } if (new_list != NULL) { free(new_list); } return 0; } /* * update */ void EWMH_DoUpdateWmIcon(FvwmWindow *fw, Bool mini_icon, Bool icon) { CARD32 *list = NULL; CARD32 *new_list = NULL; CARD32 *dummy = NULL; int size = 0; Bool icon_too = False; if (HAS_EWMH_WM_ICON_HINT(fw) == EWMH_TRUE_ICON) { return; } /* first see if we have to delete */ if (FMiniIconsSupported && mini_icon && !DO_EWMH_DONATE_MINI_ICON(fw)) { if (icon && !DO_EWMH_DONATE_ICON(fw)) { icon_too = True; } EWMH_DeleteWmIcon(fw, True, icon_too); } if (!icon_too && icon && !DO_EWMH_DONATE_ICON(fw)) { EWMH_DeleteWmIcon(fw, False, True); } /* now set if needed */ if ((mini_icon && DO_EWMH_DONATE_MINI_ICON(fw)) || (icon && DO_EWMH_DONATE_ICON(fw))) { list = ewmh_AtomGetByName( FW_W(fw),"_NET_WM_ICON", EWMH_ATOM_LIST_PROPERTY_NOTIFY, &size); } else { return; } /* we have to reset */ if (icon && DO_EWMH_DONATE_ICON(fw)) { if ((new_list = ewmh_SetWmIconFromPixmap( fw, list, &size, False)) != NULL) { SET_HAS_EWMH_WM_ICON_HINT(fw, EWMH_FVWM_ICON); } } if (FMiniIconsSupported && mini_icon && DO_EWMH_DONATE_MINI_ICON(fw)) { if ((dummy = ewmh_SetWmIconFromPixmap( fw, (new_list != NULL)? new_list : list, &size, True)) != NULL) { SET_HAS_EWMH_WM_ICON_HINT(fw, EWMH_FVWM_ICON); free(dummy); } } if (list != NULL) { free(list); } if (new_list != NULL) { free(new_list); } } /* * build and set a net icon from a pixmap */ CARD32 *ewmh_SetWmIconFromPixmap( FvwmWindow *fw, CARD32 *orig_icon, int *orig_size, Bool is_mini_icon) { CARD32 *new_icon = NULL; int keep_start = 0, keep_length = 0; int width = 0, height = 0; int i,j,k,l,m; int s; Pixmap pixmap = None; Pixmap mask = None; Pixmap alpha = None; XImage *image; XImage *m_image = NULL; XImage *a_image = NULL; int save_picture_w_g_width = 0; int save_picture_w_g_height = 0; int save_icon_depth = 0; Pixmap save_icon_pixmap = None; Pixmap save_icon_mask = None; Pixmap save_icon_alpha = None; int save_icon_nalloc_pixels = 0; Pixel *save_icon_alloc_pixels = NULL; int save_icon_no_limit = 0; Window save_icon_pixmap_w = None; Bool is_pixmap_ours = False; Bool is_icon_ours = False; Bool is_icon_shaped = False; Bool destroy_icon_pix = False; s = *orig_size / sizeof(CARD32); *orig_size = 0; if (is_mini_icon) { if (FMiniIconsSupported && fw->mini_icon != NULL) { pixmap = fw->mini_icon->picture; mask = fw->mini_icon->mask; alpha = fw->mini_icon->alpha; width = fw->mini_icon->width; height = fw->mini_icon->height; } } else { /* should save and restore any iformation modified by * a call to GetIconPicture */ save_picture_w_g_width = fw->icon_g.picture_w_g.width; save_picture_w_g_height = fw->icon_g.picture_w_g.height; save_icon_depth = fw->iconDepth; save_icon_pixmap = fw->iconPixmap; save_icon_mask = fw->icon_maskPixmap; save_icon_alpha = fw->icon_alphaPixmap; save_icon_nalloc_pixels = fw->icon_nalloc_pixels; save_icon_alloc_pixels = fw->icon_alloc_pixels; save_icon_no_limit = fw->icon_no_limit; save_icon_pixmap_w = FW_W_ICON_PIXMAP(fw); is_pixmap_ours = IS_PIXMAP_OURS(fw); is_icon_ours = IS_ICON_OURS(fw); is_icon_shaped = IS_ICON_SHAPED(fw); GetIconPicture(fw, True); if (IS_PIXMAP_OURS(fw)) { destroy_icon_pix = True; } pixmap = fw->iconPixmap; mask = fw->icon_maskPixmap; alpha = fw->icon_alphaPixmap; width = fw->icon_g.picture_w_g.width; height = fw->icon_g.picture_w_g.height; if (fw->icon_alloc_pixels != NULL) { if (fw->icon_nalloc_pixels != 0) { PictureFreeColors( dpy, Pcmap, fw->icon_alloc_pixels, fw->icon_nalloc_pixels, 0, fw->icon_no_limit); } free(fw->icon_alloc_pixels); } fw->icon_g.picture_w_g.width = save_picture_w_g_width; fw->icon_g.picture_w_g.height = save_picture_w_g_height; fw->iconDepth = save_icon_depth; fw->iconPixmap = save_icon_pixmap; fw->icon_maskPixmap = save_icon_mask; fw->icon_alphaPixmap = save_icon_alpha; fw->icon_nalloc_pixels = save_icon_nalloc_pixels; fw->icon_alloc_pixels = save_icon_alloc_pixels; fw->icon_no_limit = save_icon_no_limit; FW_W_ICON_PIXMAP(fw) = save_icon_pixmap_w; SET_ICON_OURS(fw, is_icon_ours); SET_PIXMAP_OURS(fw, is_pixmap_ours); SET_ICON_SHAPED(fw, is_icon_shaped); } if (pixmap == None) { return NULL; } if (FMiniIconsSupported && orig_icon != NULL) { int k_width = (is_mini_icon)? fw->ewmh_icon_width : fw->ewmh_mini_icon_width; int k_height = (is_mini_icon)? fw->ewmh_icon_height : fw->ewmh_mini_icon_height; for (i = 0; i < s - 1 && i >= 0; ) { if (i + 1 + orig_icon[i]*orig_icon[i+1] < s) { if (orig_icon[i] == k_width && orig_icon[i+1] == k_height) { keep_start = i; keep_length = 2 + orig_icon[i] * orig_icon[i+1]; i = s; } } if (i != s && orig_icon[i]*orig_icon[i+1] > 0) { i = i + 2 + orig_icon[i]*orig_icon[i+1]; } else { i = s; } } } image = XGetImage( dpy, pixmap, 0, 0, width, height, AllPlanes, ZPixmap); if (image == NULL) { fvwm_msg( ERR, "EWMH_SetWmIconFromPixmap", "cannot create XImage\n"); if (destroy_icon_pix) { XFreePixmap(dpy, pixmap); if (mask != None) { XFreePixmap(dpy, mask); } if (alpha != None) { XFreePixmap(dpy, alpha); } } return NULL; } if (mask != None) { m_image = XGetImage(dpy, mask, 0, 0, width, height, AllPlanes, ZPixmap); } if (alpha != None) { a_image = XGetImage(dpy, alpha, 0, 0, width, height, AllPlanes, ZPixmap); } *orig_size = (height*width + 2 + keep_length) * sizeof(CARD32); new_icon = (CARD32 *)safemalloc(*orig_size); if (keep_length > 0) { memcpy(new_icon, &orig_icon[keep_start], keep_length * sizeof(CARD32)); } new_icon[keep_length] = width; new_icon[1+keep_length] = height; k = 0; l = (2 + keep_length); m = 0; switch(image->depth) { case 1: { XColor colors[2]; CARD32 fg, bg; colors[0].pixel = fw->colors.fore; colors[1].pixel = fw->colors.back; XQueryColors(dpy, Pcmap, colors, 2); fg = 0xff000000 + (((colors[0].red >> 8) & 0xff) << 16) + (((colors[0].green >> 8) & 0xff) << 8) + ((colors[0].blue >> 8) & 0xff); bg = 0xff000000 + (((colors[1].red >> 8) & 0xff) << 16) + (((colors[1].green >> 8) & 0xff) << 8) + ((colors[1].blue >> 8) & 0xff); for (j = 0; j < height; j++) { for (i = 0; i < width; i++) { if (m_image != NULL && (XGetPixel(m_image, i, j) == 0)) { new_icon[l++] = 0; } else if (XGetPixel(image, i, j) == 0) { new_icon[l++] = bg; } else { new_icon[l++] = fg; } } } break; } default: /* depth = Pdepth */ { unsigned char *cm; XColor *colors; colors = (XColor *)safemalloc(width * height * sizeof(XColor)); cm = (unsigned char *)safemalloc( width * height * sizeof(char)); for (j = 0; j < height; j++) { for (i = 0; i < width; i++) { if (m_image != NULL && (XGetPixel(m_image, i, j) == 0)) { cm[m++] = 0; } else if (a_image != NULL) { cm[m++] = (unsigned char)XGetPixel( a_image, i, j); colors[k++].pixel = XGetPixel( image, i, j); } else { cm[m++] = 255; colors[k++].pixel = XGetPixel( image, i, j); } } } for (i = 0; i < k; i += 256) XQueryColors(dpy, Pcmap, &colors[i], min(k - i, 256)); k = 0;m = 0; for (j = 0; j < height; j++) { for (i = 0; i < width; i++) { if (cm[m] > 0) { new_icon[l++] = ((cm[m] & 0xff) << 24) + (((colors[k].red >> 8) & 0xff) << 16) + (((colors[k].green >> 8) & 0xff) << 8) + ((colors[k].blue >> 8) & 0xff); k++; } else { new_icon[l++] = 0; } m++; } } free(colors); free(cm); break; } } /* switch */ if (is_mini_icon) { fw->ewmh_mini_icon_width = width; fw->ewmh_mini_icon_height = height; } else { fw->ewmh_icon_width = width; fw->ewmh_icon_height = height; } ewmh_ChangeProperty( FW_W(fw), "_NET_WM_ICON", EWMH_ATOM_LIST_PROPERTY_NOTIFY, (unsigned char *)new_icon, height*width + 2 + keep_length); if (destroy_icon_pix) { XFreePixmap(dpy, pixmap); if (mask != None) { XFreePixmap(dpy, mask); } if (alpha != None) { XFreePixmap(dpy, alpha); } } XDestroyImage(image); if (m_image != None) { XDestroyImage(m_image); } if (a_image != None) { XDestroyImage(a_image); } return new_icon; } /* * delete the mini icon and/or the icon from a ewmh icon */ void EWMH_DeleteWmIcon(FvwmWindow *fw, Bool mini_icon, Bool icon) { CARD32 *list; CARD32 *new_list = NULL; int keep_start = 0, keep_length = 0; int s; int i; if (mini_icon && icon) { ewmh_DeleteProperty( FW_W(fw), "_NET_WM_ICON", EWMH_ATOM_LIST_PROPERTY_NOTIFY); fw->ewmh_mini_icon_width = 0; fw->ewmh_mini_icon_height = 0; fw->ewmh_icon_width = 0; fw->ewmh_icon_height = 0; /*SET_HAS_EWMH_WM_ICON_HINT(fw, EWMH_NO_ICON);*/ return; } list = ewmh_AtomGetByName( FW_W(fw),"_NET_WM_ICON", EWMH_ATOM_LIST_PROPERTY_NOTIFY, &s); if (list == NULL) { return; } s = s / sizeof(CARD32); if (FMiniIconsSupported && list != NULL) { int k_width = (mini_icon) ? fw->ewmh_icon_width : fw->ewmh_mini_icon_width; int k_height = (mini_icon) ? fw->ewmh_icon_height : fw->ewmh_mini_icon_height; for (i = 0; i < s - 1; ) { if (i + 1 + list[i]*list[i+1] < s) { if (list[i] == k_width && list[i+1] == k_height) { keep_start = i; keep_length = 2 + list[i]*list[i+1]; i = s; } } if (i != s && list[i]*list[i+1] > 0) { i = i + 2 + list[i]*list[i+1]; } else { i = s; } } } if (keep_length > 0) { new_list = (CARD32 *)safemalloc(keep_length * sizeof(CARD32)); memcpy( new_list, &list[keep_start], keep_length * sizeof(CARD32)); } if (new_list != NULL) { ewmh_ChangeProperty( FW_W(fw),"_NET_WM_ICON", EWMH_ATOM_LIST_PROPERTY_NOTIFY, (unsigned char *)new_list, keep_length); } else { /*SET_HAS_EWMH_WM_ICON_HINT(fw, EWMH_NO_ICON);*/ ewmh_DeleteProperty( FW_W(fw), "_NET_WM_ICON", EWMH_ATOM_LIST_PROPERTY_NOTIFY); } if (mini_icon) { fw->ewmh_mini_icon_width = 0; fw->ewmh_mini_icon_height = 0; } if (icon) { fw->ewmh_icon_width = 0; fw->ewmh_icon_height = 0; } if (new_list != NULL) { free(new_list); } free(list); } /* * Create an x image from a NET icon */ #define SQUARE(X) ((X)*(X)) static void extract_wm_icon( CARD32 *list, int size, int wanted_w, int wanted_h, int *start_best, int *best_w, int *best_h) { int i; int dist = 0; *start_best = 0; *best_w = 0; *best_h = 0; size = size / (sizeof(CARD32)); for (i = 0; i < size - 1; ) { if (i + 1 + list[i]*list[i+1] < size) { if (*best_w == 0 && *best_h == 0) { *start_best = i+2; *best_w = list[i]; *best_h = list[i+1]; dist = SQUARE( list[i]-wanted_w) + SQUARE(list[i+1]-wanted_h); } else if (SQUARE(list[i]-wanted_w) + SQUARE(list[i+1]-wanted_h) < dist) { *start_best = i+2; *best_w = list[i]; *best_h = list[i+1]; dist = SQUARE( list[i]-wanted_w) + SQUARE(list[i+1]-wanted_h); } } if (list[i]*list[i+1] > 0) { i = i + 2 + list[i]*list[i+1]; } else { i = size; } } return; } #define MINI_ICON_WANTED_WIDTH 16 #define MINI_ICON_WANTED_HEIGHT 16 #define MINI_ICON_MAX_WIDTH 22 #define MINI_ICON_MAX_HEIGHT 22 #define ICON_WANTED_WIDTH 56 #define ICON_WANTED_HEIGHT 56 #define ICON_MAX_WIDTH 100 #define ICON_MAX_HEIGHT 100 int EWMH_SetIconFromWMIcon( FvwmWindow *fw, CARD32 *list, int size, Bool is_mini_icon) { int start, width, height; int wanted_w, wanted_h; int max_w, max_h; Pixmap pixmap = None; Pixmap mask = None; Pixmap alpha = None; Bool free_list = False; int nalloc_pixels; Pixel *alloc_pixels; int no_limit; FvwmPictureAttributes fpa; if (list == NULL) { /* we are called from icons.c or update.c */ list = ewmh_AtomGetByName( FW_W(fw),"_NET_WM_ICON", EWMH_ATOM_LIST_PROPERTY_NOTIFY, &size); free_list = True; if (list == NULL) { return 0; } } if (is_mini_icon) { wanted_w = MINI_ICON_WANTED_WIDTH; wanted_h = MINI_ICON_WANTED_HEIGHT; max_w = MINI_ICON_MAX_WIDTH; max_h = ICON_MAX_HEIGHT; fpa.mask = 0; } else { wanted_w = ICON_WANTED_WIDTH; wanted_h = ICON_WANTED_HEIGHT; max_w = ICON_MAX_WIDTH; max_h = ICON_MAX_HEIGHT; if (fw->cs >= 0 && Colorset[fw->cs].do_dither_icon) { fpa.mask = FPAM_DITHER; } else { fpa.mask = 0; } } extract_wm_icon( list, size, wanted_w, wanted_h, &start, &width, &height); if (width == 0 || height == 0) { if (free_list) { free(list); } return 0; } if (!PImageCreatePixmapFromArgbData( dpy, Scr.NoFocusWin, list, start, width, height, &pixmap, &mask, &alpha, &nalloc_pixels, &alloc_pixels, &no_limit, fpa)) { fvwm_msg(ERR, "EWMH_SetIconFromWMIcon", "fail to create a pixmap\n"); if (free_list) { free(list); } return 0; } if (width > max_w || height > max_h) { Pixmap np = None,nm =None, na = None; if (pixmap) { np = CreateStretchPixmap( dpy, pixmap, width, height, Pdepth, wanted_w, wanted_h, Scr.TitleGC); XFreePixmap(dpy, pixmap); pixmap = np; } if (mask) { nm = CreateStretchPixmap( dpy, mask, width, height, 1, wanted_w, wanted_h, Scr.MonoGC); XFreePixmap(dpy, mask); mask = nm; } if (alpha) { na = CreateStretchPixmap( dpy, alpha, width, height, FRenderGetAlphaDepth(), wanted_w, wanted_h, Scr.AlphaGC); XFreePixmap(dpy, alpha); alpha = na; } width = wanted_w; height = wanted_h; } if (FMiniIconsSupported && is_mini_icon && !DO_EWMH_MINI_ICON_OVERRIDE(fw)) { char *name = NULL; CopyString(&name,"ewmh_mini_icon"); if (fw->mini_icon) { PDestroyFvwmPicture(dpy,fw->mini_icon); fw->mini_icon = 0; } fw->mini_icon = PCacheFvwmPictureFromPixmap( dpy, Scr.NoFocusWin, name, pixmap,mask,alpha, width, height, nalloc_pixels, alloc_pixels, no_limit); if (fw->mini_icon != NULL) { fw->mini_pixmap_file = name; BroadcastFvwmPicture( M_MINI_ICON, FW_W(fw), FW_W_FRAME(fw), (unsigned long)fw, fw->mini_icon, fw->mini_pixmap_file); border_redraw_decorations(fw); } } if (!is_mini_icon) { fw->iconPixmap = pixmap; fw->icon_maskPixmap = mask; fw->icon_alphaPixmap = alpha; fw->icon_nalloc_pixels = nalloc_pixels; fw->icon_alloc_pixels = alloc_pixels; fw->icon_no_limit = no_limit; fw->icon_g.picture_w_g.width = width; fw->icon_g.picture_w_g.height = height; fw->iconDepth = Pdepth; SET_PIXMAP_OURS(fw, 1); if (FShapesSupported && mask) { SET_ICON_SHAPED(fw, 1); } } if (free_list) { free(list); } return 1; } fvwm-2.7.0/fvwm/menuroot.h0000644000175000017500000001435214147024700012424 00000000000000/* -*-c-*- */ #ifndef MENU_ROOT_H #define MENU_ROOT_H /* ---------------------------- included header files ---------------------- */ /* Do not #include any files - the file including this file has to take care of * it. */ /* ---------------------------- forward declarations ----------------------- */ struct MenuItem; struct MenuStyle; /* ---------------------------- type definitions --------------------------- */ /* * MENU ROOT STRUCTURES */ /* This struct contains the parts of a root menu that are shared among all * copies of the menu */ typedef struct MenuRootStatic { /* first item in menu */ struct MenuItem *first; /* last item in menu */ struct MenuItem *last; /* # of copies, 0 if none except this one */ int copies; /* # of mapped instances */ int usage_count; /* name of root */ char *name; struct MenuDimensions dim; int items; FvwmPicture *sidePic; Pixel sideColor; int used_mini_icons; /* Menu Face */ struct MenuStyle *ms; /* permanent flags */ struct { unsigned has_side_color : 1; unsigned is_left_triangle : 1; unsigned is_updated : 1; } flags; struct { char *popup_action; char *popdown_action; char *missing_submenu_func; } dynamic; } MenuRootStatic; /* access macros to static menu members */ #define MR_FIRST_ITEM(m) ((m)->s->first) #define MR_LAST_ITEM(m) ((m)->s->last) #define MR_COPIES(m) ((m)->s->copies) #define MR_MAPPED_COPIES(m) ((m)->s->usage_count) #define MR_NAME(m) ((m)->s->name) #define MR_DIM(m) ((m)->s->dim) #define MR_WIDTH(m) MDIM_WIDTH((m)->s->dim) #define MR_HEIGHT(m) MDIM_HEIGHT((m)->s->dim) #define MR_ITEM_WIDTH(m) MDIM_ITEM_WIDTH((m)->s->dim) #define MR_SIDEPIC_X_OFFSET(m) MDIM_SIDEPIC_X_OFFSET((m)->s->dim) #define MR_ICON_X_OFFSET(m) MDIM_ICON_X_OFFSET((m)->s->dim) #define MR_TRIANGLE_X_OFFSET(m) MDIM_TRIANGLE_X_OFFSET((m)->s->dim) #define MR_ITEM_X_OFFSET(m) MDIM_ITEM_X_OFFSET((m)->s->dim) #define MR_ITEM_TEXT_Y_OFFSET(m) MDIM_ITEM_TEXT_Y_OFFSET((m)->s->dim) #define MR_HILIGHT_X_OFFSET(m) MDIM_HILIGHT_X_OFFSET((m)->s->dim) #define MR_HILIGHT_WIDTH(m) MDIM_HILIGHT_WIDTH((m)->s->dim) #define MR_SCREEN_WIDTH(m) MDIM_SCREEN_WIDTH((m)->s->dim) #define MR_SCREEN_HEIGHT(m) MDIM_SCREEN_HEIGHT((m)->s->dim) #define MR_ITEMS(m) ((m)->s->items) #define MR_SIDEPIC(m) ((m)->s->sidePic) #define MR_SIDECOLOR(m) ((m)->s->sideColor) #define MR_USED_MINI_ICONS(m) ((m)->s->used_mini_icons) #define MR_STYLE(m) ((m)->s->ms) /* flags */ #define MR_FLAGS(m) ((m)->s->flags) #define MR_POPUP_ACTION(m) ((m)->s->dynamic.popup_action) #define MR_POPDOWN_ACTION(m) ((m)->s->dynamic.popdown_action) #define MR_MISSING_SUBMENU_FUNC(m) ((m)->s->dynamic.missing_submenu_func) #define MR_HAS_SIDECOLOR(m) ((m)->s->flags.has_side_color) #define MR_IS_LEFT_TRIANGLE(m) ((m)->s->flags.is_left_triangle) #define MR_IS_UPDATED(m) ((m)->s->flags.is_updated) /* This struct contains the parts of a root menu that differ in all copies of * the menu */ typedef struct MenuRootDynamic { /* the first copy of the current menu */ struct MenuRoot *original_menu; /* next in list of root menus */ struct MenuRoot *next_menu; /* continuation of this menu (too tall for screen) */ struct MenuRoot *continuation_menu; /* can get the menu that this popped up through selected_item->mr when * selected is a popup menu item */ /* the menu that popped this up, if any */ struct MenuRoot *parent_menu; /* the menu item that popped this up, if any */ struct MenuItem *parent_item; /* the display used to create the menu. Can't use the normal display * because 'xkill' would kill the window manager if used on a tear off * menu. */ Display *create_dpy; /* the window of the menu */ Window window; /* the selected item in menu */ struct MenuItem *selected_item; /* item that has it's submenu mapped */ struct MenuItem *submenu_item; /* x distance window was moved by animation */ int xanimation; /* dynamic temp flags */ struct { /* is win background set? */ unsigned is_background_set : 1; unsigned is_destroyed : 1; /* menu direction relative to parent menu */ unsigned is_left : 1; unsigned is_right : 1; unsigned is_up : 1; unsigned is_down : 1; unsigned is_painted : 1; unsigned is_tear_off_menu : 1; unsigned has_popped_up_left : 1; unsigned has_popped_up_right : 1; } dflags; struct { Pixmap stored; int width; int height; int y; } stored_item; struct { Pixel *d_pixels; int d_npixels; } stored_pixels; /* alloc pixels when dithering is used for gradients */ } MenuRootDynamic; /* access macros to dynamic menu members */ #define MR_ORIGINAL_MENU(m) ((m)->d->original_menu) #define MR_NEXT_MENU(m) ((m)->d->next_menu) #define MR_CONTINUATION_MENU(m) ((m)->d->continuation_menu) #define MR_PARENT_MENU(m) ((m)->d->parent_menu) #define MR_PARENT_ITEM(m) ((m)->d->parent_item) #define MR_CREATE_DPY(m) ((m)->d->create_dpy) #define MR_WINDOW(m) ((m)->d->window) #define MR_SELECTED_ITEM(m) ((m)->d->selected_item) #define MR_SUBMENU_ITEM(m) ((m)->d->submenu_item) #define MR_XANIMATION(m) ((m)->d->xanimation) #define MR_STORED_ITEM(m) ((m)->d->stored_item) #define MR_STORED_PIXELS(m) ((m)->d->stored_pixels) /* flags */ #define MR_DYNAMIC_FLAGS(m) ((m)->d->dflags) #define MR_IS_BACKGROUND_SET(m) ((m)->d->dflags.is_background_set) #define MR_IS_DESTROYED(m) ((m)->d->dflags.is_destroyed) #define MR_IS_LEFT(m) ((m)->d->dflags.is_left) #define MR_IS_RIGHT(m) ((m)->d->dflags.is_right) #define MR_IS_UP(m) ((m)->d->dflags.is_up) #define MR_IS_DOWN(m) ((m)->d->dflags.is_down) #define MR_IS_PAINTED(m) ((m)->d->dflags.is_painted) #define MR_IS_TEAR_OFF_MENU(m) ((m)->d->dflags.is_tear_off_menu) #define MR_HAS_POPPED_UP_LEFT(m) ((m)->d->dflags.has_popped_up_left) #define MR_HAS_POPPED_UP_RIGHT(m) ((m)->d->dflags.has_popped_up_right) typedef struct MenuRoot { MenuRootStatic *s; MenuRootDynamic *d; } MenuRoot; /* don't forget to initialise new members in NewMenuRoot()! */ #endif /* MENU_ROOT_H */ fvwm-2.7.0/fvwm/ConfigFvwmDefaults0000644000175000017500000001355614147024700014070 00000000000000# This file gets installed in the "datadir" during fvwm # installation. Do not remove or change this file. # # Created on 21/Mar/1999 by DanEspen (dje): # - FvwmDefaults file. Contains fvwm defaults, and enough to help out # the new user with no configuration file. # This picks up from where the builtin table in fvwm.c SetRCDefaults ends. # TA: 2012-01-02: Set the default cursor style to a dot, if FVWM is busy # in a PipeRead or Read operation. ImagePath +:$[FVWM_USERDIR] BusyCursor Read True CursorStyle Wait Dot # Set at least 2 root keys to bring up the builtin menu: Silent Key Help R A Popup MenuFvwmRoot Key F1 R A Popup MenuFvwmRoot # Ctrl-Alt-Escape for aborting Wait pause and ModuleSynchronous command Key Escape A MC EscapeFunc # Needed by the builtin WindowList command, this should match the manpage AddToFunc WindowListFunc + I Iconify off + I FlipFocus + I Raise + I WarpToWindow !raise 5p 5p # Needed by the ewmh support AddToFunc EWMHActivateWindowFunc + I Iconify off + I Focus + I Raise # Also in the fvwm man page AddToFunc UrgencyFunc + I Iconify off + I FlipFocus + I Raise + I WarpToWindow 5p 5p AddToFunc UrgencyDoneFunc I Nop # Needed by modules which use session management # FSMExecFuncWithSessionManagment "module_sm_env" "action" "orig_sm_env" AddToFunc FSMExecFuncWithSessionManagment + I Setenv SESSION_MANAGER $0 + I $1 + I Setenv SESSION_MANAGER $2 # Default styles Style * LowerTransient, RaiseTransient, StackTransientParent Style * TileCascadePlacement, Title, MouseFocus Style * UseIconPosition, RightTitleRotatedCW, UseTitleDecorRotation Style * EWMHPlacementUseDynamicWorkingArea, EWMHMaximizeUseDynamicWorkingArea # Default styles for tear off menus Style fvwm_menu NoPPosition, NeverFocus, NoLenience, \ WindowListSkip, CirculateSkip # Alt-Tab: Key Tab A M WindowList Root c c NoDeskSort # Basic Mouse controls: Mouse 1 T A FuncFvwmRaiseLowerX Move Mouse 1 FS A FuncFvwmRaiseLowerX Resize Mouse 2 FST A FuncFvwmRaiseLowerX Move AddToFunc FuncFvwmRaiseLowerX + I Raise + M $0 + D Lower ###################### # BEGIN MENU BINDINGS # # # hard coded defaults that can not be deleted #Key Escape M A MenuClose #Key Return M A MenuSelectItem #Key Left M A MenuCursorLeft #Key Right M A MenuCursorRight #Key Up M A MenuMoveCursor -1 #Key Down M A MenuMoveCursor 1 #Mouse 1 M A MenuSelectItem # Normal bindings Silent Key Delete M A MenuClose Silent Key KP_Separator M A MenuClose Silent Key KP_Decimal M A MenuClose Silent Key Space M A MenuSelectItem Silent Key KP_Enter M A MenuSelectItem # move to last entry of menu ('More...' if this exists) and # try to enter the menu. Otherwise try to enter the current # submenu Silent Key Insert M A MenuEnterContinuation Silent Key KP_Insert M A MenuEnterContinuation Silent Key KP_0 M A MenuEnterContinuation Silent Key KP_Left M A MenuCursorLeft Silent Key KP_4 M A MenuCursorLeft Silent Key KP_Right M A MenuCursorRight Silent Key KP_6 M A MenuCursorRight #back Silent Key b M A MenuLeaveSubmenu #forward Silent Key f M A MenuEnterSubmenu Silent Key Page_Up M A MenuMoveCursor -5 Silent Key KP_Prior M A MenuMoveCursor -5 Silent Key KP_9 M A MenuMoveCursor -5 Silent Key Page_Down M A MenuMoveCursor +5 Silent Key KP_Next M A MenuMoveCursor +5 Silent Key KP_3 M A MenuMoveCursor +5 # Up Silent Key KP_Up M A MenuMoveCursor -1 Silent Key KP_8 M A MenuMoveCursor -1 #prior Silent Key p M A MenuMoveCursor -1 Silent Key Up M S MenuMoveCursor 0 0 Silent Key KP_Up M S MenuMoveCursor 0 0 Silent Key KP_8 M S MenuMoveCursor 0 0 #prior Silent Key p M S MenuMoveCursor 0 0 Silent Key Up M C MenuMoveCursor -5 Silent Key KP_Up M C MenuMoveCursor -5 Silent Key KP_8 M C MenuMoveCursor -5 #prior Silent Key p M C MenuMoveCursor -5 Silent Key Up M M MenuMoveCursor -1s Silent Key KP_Up M M MenuMoveCursor -1s Silent Key KP_8 M M MenuMoveCursor -1s #prior Silent Key p M M MenuMoveCursor -1s # Down Silent Key KP_Down M A MenuMoveCursor 1 Silent Key KP_2 M A MenuMoveCursor 1 #next Silent Key n M A MenuMoveCursor 1 Silent Key Down M S MenuMoveCursor 0 -1 Silent Key KP_Down M S MenuMoveCursor 0 -1 Silent Key KP_2 M S MenuMoveCursor 0 -1 #next Silent Key n M S MenuMoveCursor 0 -1 Silent Key Down M C MenuMoveCursor +5 Silent Key KP_Down M C MenuMoveCursor +5 Silent Key KP_2 M C MenuMoveCursor +5 #next Silent Key n M C MenuMoveCursor +5 Silent Key Down M M MenuMoveCursor +1s Silent Key KP_Down M M MenuMoveCursor +1s Silent Key KP_2 M M MenuMoveCursor +1s #next Silent Key n M M MenuMoveCursor +1s Silent Key Tab M A MenuMoveCursor +1 Silent Key Tab M C MenuMoveCursor +1s Silent Key Tab M MC MenuMoveCursor +5 Silent Key Tab M S MenuMoveCursor -1 Silent Key Tab M SM MenuMoveCursor -1 Silent Key Tab M SC MenuMoveCursor -1s Silent Key Tab M SMC MenuMoveCursor -5 Silent Key Home M A MenuMoveCursor 0 0 Silent Key KP_Home M A MenuMoveCursor 0 0 Silent Key KP_7 M A MenuMoveCursor 0 0 Silent Key End M A MenuMoveCursor 0 -1 Silent Key KP_End M A MenuMoveCursor 0 -1 Silent Key KP_1 M A MenuMoveCursor 0 -1 Silent Key BackSpace M A MenuTearOff Silent Key KP_Add M A MenuScroll 1 Silent Key KP_Subtract M A MenuScroll -1 # vi bindings Silent Key h M A MenuCursorLeft Silent Key l M A MenuCursorRight Silent Key k M A MenuMoveCursor -1 Silent Key k M C MenuMoveCursor -5 Silent Key j M A MenuMoveCursor 1 Silent Key j M C MenuMoveCursor 5 # emacs bindings Silent Key a M C MenuMoveCursor 0 0 Silent Key e M C MenuMoveCursor 0 -1 Silent Key b M C MenuMoveCursor -1 Silent Key f M C MenuMoveCursor +1 Silent Key Left M C MenuMoveCursor -1s Silent Key Right M C MenuMoveCursor +1s Silent Key g M C MenuClose # Mouse bindings Mouse 0 MI A MenuSelectItem Mouse 0 MTS A MenuLeaveSubmenu Silent Mouse 4 MIT A MenuScroll -1 Silent Mouse 5 MIT A MenuScroll +1 # NB: Only on title -- changes syntax for remapping the TearOff functionality Mouse 2 MT A MenuTearOff # # # END MENU BINDINGS #################### fvwm-2.7.0/fvwm/externs.h0000644000175000017500000000607714147024700012251 00000000000000/* -*-c-*- */ /* * Copyright 1988 by Evans & Sutherland Computer Corporation, * Salt Lake City, Utah * Portions Copyright 1989 by the Massachusetts Institute of Technology * Cambridge, Massachusetts * * All Rights Reserved * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice appear in all * copies and that both that copyright notice and this permis- * sion notice appear in supporting documentation, and that the * names of Evans & Sutherland and M.I.T. not be used in advertising * in publicity pertaining to distribution of the software without * specific, written prior permission. * * EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- * ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR * M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- * AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE * OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef EXTERNS_H #define EXTERNS_H void Done(int, char *) __attribute__((__noreturn__)); void set_init_function_name(int n, const char *name); const char *get_init_function_name(int n); extern char NoName[]; extern char NoClass[]; extern char NoResource[]; extern XGCValues Globalgcv; extern unsigned long Globalgcm; extern int master_pid; extern Display *dpy; extern int x_fd; extern XContext FvwmContext; extern Bool fFvwmInStartup; extern Bool DoingCommandLine; extern Bool debugging; extern Bool debugging_stack_ring; extern int GrabPointerState; extern Window JunkRoot, JunkChild; extern int JunkX, JunkY; extern int JunkWidth, JunkHeight, JunkBW, JunkDepth; extern unsigned int JunkMask; extern char *fvwm_userdir; extern char *display_name; extern Atom _XA_MIT_PRIORITY_COLORS; extern Atom _XA_WM_CHANGE_STATE; extern Atom _XA_WM_STATE; extern Atom _XA_WM_COLORMAP_WINDOWS; extern Atom _XA_WM_PROTOCOLS; extern Atom _XA_WM_TAKE_FOCUS; extern Atom _XA_WM_SAVE_YOURSELF; extern Atom _XA_WM_DELETE_WINDOW; extern Atom _XA_WM_DESKTOP; extern Atom _XA_OL_WIN_ATTR; extern Atom _XA_OL_WT_BASE; extern Atom _XA_OL_WT_CMD; extern Atom _XA_OL_WT_HELP; extern Atom _XA_OL_WT_NOTICE; extern Atom _XA_OL_WT_OTHER; extern Atom _XA_OL_DECOR_ADD; extern Atom _XA_OL_DECOR_DEL; extern Atom _XA_OL_DECOR_CLOSE; extern Atom _XA_OL_DECOR_RESIZE; extern Atom _XA_OL_DECOR_HEADER; extern Atom _XA_OL_DECOR_ICON_NAME; extern Atom _XA_WM_WINDOW_ROLE; extern Atom _XA_WINDOW_ROLE; extern Atom _XA_WM_CLIENT_LEADER; extern Atom _XA_SM_CLIENT_ID; extern Atom _XA_WIN_SX; extern Atom _XA_MANAGER; extern Atom _XA_ATOM_PAIR; extern Atom _XA_WM_COLORMAP_NOTIFY; extern Atom _XA_XROOTPMAP_ID; extern Atom _XA_XSETROOT_ID; #endif /* _EXTERNS_ */ fvwm-2.7.0/fvwm/borders.h0000644000175000017500000000403214147024676012222 00000000000000/* -*-c-*- */ #ifndef _BORDERS_H #define _BORDERS_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ #define NPARTS_KEEP_STATE 12 /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ typedef enum { PART_NONE = 0x0, /* the border drawing code relies on the fact that the border bits * occupy the lowest ten bits in this order! */ PART_BORDER_N = 0x1, PART_BORDER_S = 0x2, PART_BORDER_E = 0x4, PART_BORDER_W = 0x8, PART_BORDER_NW = 0x10, PART_BORDER_NE = 0x20, PART_BORDER_SW = 0x40, PART_BORDER_SE = 0x80, PART_TITLE = 0x100, PART_BUTTONS = 0x200, PART_X_HANDLES = 0x400, PART_Y_HANDLES = 0x800, /* combinations of the above values */ PART_SIDES = 0x0f, PART_CORNERS = 0xf0, PART_FRAME = 0xff, PART_TITLEBAR = 0x300, PART_HANDLES = 0xc00, PART_ALL = 0xfff } window_parts; typedef enum { CLEAR_NONE = 0x0, CLEAR_FRAME = 0x1, CLEAR_TITLE = 0x2, CLEAR_BUTTONS = 0x4, CLEAR_ALL = 0x7 } clear_window_parts; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ DecorFace *border_get_border_style( FvwmWindow *fw, Bool has_focus); int border_is_using_border_style( FvwmWindow *fw, Bool has_focus); int border_context_to_parts( int context); void border_get_part_geometry( FvwmWindow *fw, window_parts part, rectangle *sidebar_g, rectangle *ret_g, Window *ret_w); int get_button_number(int context); void border_draw_decorations( FvwmWindow *t, window_parts draw_parts, Bool has_focus, int force, clear_window_parts clear_parts, rectangle *old_g, rectangle *new_g); void border_undraw_decorations( FvwmWindow *fw); void border_redraw_decorations( FvwmWindow *fw); unsigned int border_get_transparent_decorations_part( FvwmWindow *fw); #endif /* _BORDERS_H */ fvwm-2.7.0/fvwm/menubindings.h0000644000175000017500000000525414147024700013237 00000000000000/* -*-c-*- */ #ifndef MENU_BINDINGS_H #define MENU_BINDINGS_H /* ---------------------------- included header files ---------------------- */ /* Do not #include any files - the file including this file has to take care of * it. */ /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- forward declarations ----------------------- */ struct MenuRoot; struct MenuParameters; struct MenuReturn; struct MenuItem; /* ---------------------------- type definitions --------------------------- */ typedef struct { unsigned int keystate; unsigned int keycode; Time timestamp; } double_keypress; typedef enum { SA_NONE = 0, SA_ENTER, SA_LEAVE, SA_MOVE_ITEMS, SA_FIRST, SA_LAST, SA_CONTINUE, SA_WARPBACK, SA_SELECT, SA_TEAROFF, SA_ABORT, SA_SCROLL, SA_EXEC_CMD } menu_shortcut_action; /* ---------------------------- exported variables (globals) --------------- */ /* Do not use global variable. Full stop. */ /* ---------------------------- interface functions ------------------------ */ /* Before this function is called, all menu bindings created through * menu_binding() are permanent i.e. they can not be deleted (although * overridden). After calling it, new bindings are stored in the regular list * and can be deleted by the user as usual. * * To be called by SetRCDefaults *only*. */ void menu_bindings_startup_complete(void); /* Parse a menu binding and store it. * * To be called from bindings.c *only*. */ int menu_binding( Display *dpy, binding_t type, int button, KeySym keysym, int context, int modifier, char *action, char *menu_style); /* Checks if the given mouse or keyboard event in the given context * corresponds to a menu binding. If so, the binding is returned. Otherwise * NULL is returned. * * To be called from menus.c *only*. */ Binding *menu_binding_is_mouse(XEvent* event, int context); Binding *menu_binding_is_key(XEvent* event, int context); /* Menu keyboard processing * * Function called instead of Keyboard_Shortcuts() * when a KeyPress event is received. If the key is alphanumeric, * then the menu is scanned for a matching hot key. Otherwise if * it was the escape key then the menu processing is aborted. * If none of these conditions are true, then the default processing * routine is called. * TKP - uses XLookupString so that keypad numbers work with windowlist */ void menu_shortcuts( struct MenuRoot *mr, struct MenuParameters *pmp, struct MenuReturn *pmret, XEvent *event, struct MenuItem **pmi_current, double_keypress *pdkp, int *ret_menu_x, int *ret_menu_y); #endif /* MENU_BINDINGS_H */ fvwm-2.7.0/fvwm/focus.h0000644000175000017500000000535614147024700011677 00000000000000/* -*-c-*- */ #ifndef FOCUS_H #define FOCUS_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ #define FOCUS_SET(w, fw) _focus_set(w, fw) #define FOCUS_RESET() _focus_reset() #define SetFocusWindow(a, b, c) _SetFocusWindow(a, b, c, False); #define SetFocusWindowClientEntered(a, b, c) _SetFocusWindow(a, b, c, True); #define ReturnFocusWindow(a) _ReturnFocusWindow(a); #define DeleteFocus(a) _DeleteFocus(a); #define ForceDeleteFocus() _ForceDeleteFocus(); /* ---------------------------- type definitions --------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ /* * Triggers X protocol actions to set the focus to the given window. It also * stores the FvwmWindow pointer to indicate that fvwm requested focus for that * FvwmWindow, not the application itself or someone else. */ void _focus_set(Window w, FvwmWindow *fw); void _focus_reset(void); /* * * Sets/deletes the input focus to the indicated window. * */ void _SetFocusWindow( FvwmWindow *fw, Bool do_allow_force_broadcast, fpol_set_focus_by_t set_by, Bool client_entered); void _ReturnFocusWindow(FvwmWindow *fw); void _DeleteFocus(Bool do_allow_force_broadcast); void _ForceDeleteFocus(void); void restore_focus_after_unmap( const FvwmWindow *fw, Bool do_skip_marked_transients); /* * These need documentation */ Bool IsLastFocusSetByMouse(void); void focus_grab_buttons(FvwmWindow *fw); void focus_grab_buttons_client_entered(FvwmWindow *fw); void focus_grab_buttons_on_layer(int layer); void focus_grab_buttons_all(void); void focus_grab_buttons_on_pointer_window(void); Bool focus_does_accept_input_focus(const FvwmWindow *fw); Bool focus_is_focused(const FvwmWindow *fw); Bool focus_query_click_to_raise( FvwmWindow *fw, Bool is_focused, int context); Bool focus_query_click_to_focus( FvwmWindow *fw, int context); Bool focus_query_open_grab_focus(FvwmWindow *fw, FvwmWindow *focus_win); Bool focus_query_close_release_focus(const FvwmWindow *fw); FvwmWindow *focus_get_transientfor_fwin(const FvwmWindow *fw); FvwmWindow *get_focus_window(void); void set_focus_window(FvwmWindow *fw); FvwmWindow *get_last_screen_focus_window(void); void set_last_screen_focus_window(FvwmWindow *fw); void update_last_screen_focus_window(FvwmWindow *fw); void set_focus_model(FvwmWindow *fw); void focus_force_refresh_focus(const FvwmWindow *fw); void refresh_focus(const FvwmWindow *fw); #endif /* FOCUS_H */ fvwm-2.7.0/fvwm/fvwm.c0000644000175000017500000020063314147024700011525 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include #include #ifdef HAVE_FCNTL_H #include #endif #ifdef HAVE_GETPWUID # include #endif #if HAVE_SYS_SYSTEMINFO_H /* Solaris has sysinfo instead of gethostname. */ #include #endif #include #include #include "libs/fvwmlib.h" #include "libs/envvar.h" #include "libs/Strings.h" #include "libs/System.h" #include "libs/Grab.h" #include "libs/ColorUtils.h" #include "libs/Graphics.h" #include "libs/FScreen.h" #include "libs/FShape.h" #include "libs/PictureBase.h" #include "libs/PictureUtils.h" #include "libs/Fsvg.h" #include "libs/FRenderInit.h" #include "libs/charmap.h" #include "libs/wcontext.h" #include "fvwm.h" #include "externs.h" #include "cursor.h" #include "functions.h" #include "misc.h" #include "screen.h" #include "builtins.h" #include "module_list.h" #include "colorset.h" #include "events.h" #include "eventhandler.h" #include "eventmask.h" #include "icccm2.h" #include "ewmh.h" #include "add_window.h" #include "libs/fvwmsignal.h" #include "stack.h" #include "virtual.h" #include "session.h" #include "read.h" #include "focus.h" #include "update.h" #include "move_resize.h" #include "frame.h" #include "menus.h" #include "menubindings.h" #include "libs/FGettext.h" /* ---------------------------- local definitions -------------------------- */ #define MAXHOSTNAME 255 #define MAX_CFG_CMDS 10 #define MAX_ARG_SIZE 25 #define g_width 2 #define g_height 2 #define l_g_width 4 #define l_g_height 2 #define s_g_width 4 #define s_g_height 4 /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ extern int last_event_type; /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ typedef enum { FVWM_RUNNING = 0, FVWM_DONE, FVWM_RESTART } fvwm_run_state_t; /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ static char *config_commands[MAX_CFG_CMDS]; static int num_config_commands=0; /* assorted gray bitmaps for decorative borders */ static char g_bits[] = {0x02, 0x01}; static char l_g_bits[] = {0x08, 0x02}; static char s_g_bits[] = {0x01, 0x02, 0x04, 0x08}; static char *home_dir; static volatile sig_atomic_t fvwmRunState = FVWM_RUNNING; static const char *init_function_names[4] = { "InitFunction", "RestartFunction", "ExitFunction", "Nop" }; /* ---------------------------- exported variables (globals) --------------- */ int master_pid; /* process number of 1st fvwm process */ ScreenInfo Scr; /* structures for the screen */ Display *dpy = NULL; /* which display are we talking to */ Bool fFvwmInStartup = True; /* Set to False when startup has finished */ Bool DoingCommandLine = False; /* Set True before each cmd line arg */ XContext FvwmContext; /* context for fvwm windows */ XContext MenuContext; /* context for fvwm menus */ int JunkX = 0, JunkY = 0; Window JunkRoot, JunkChild; /* junk window */ int JunkWidth, JunkHeight, JunkBW, JunkDepth; unsigned int JunkMask; Bool debugging = False; Bool debugging_stack_ring = False; Window bad_window = None; char **g_argv; int g_argc; char *state_filename = NULL; char *restart_state_filename = NULL; /* $HOME/.fs-restart */ Bool Restarting = False; int x_fd; char *display_name = NULL; char *fvwm_userdir; char const *Fvwm_VersionInfo; char const *Fvwm_LicenseInfo; char const *Fvwm_SupportInfo; Atom _XA_MIT_PRIORITY_COLORS; Atom _XA_WM_CHANGE_STATE; Atom _XA_WM_STATE; Atom _XA_WM_COLORMAP_WINDOWS; Atom _XA_WM_TAKE_FOCUS; Atom _XA_WM_DELETE_WINDOW; Atom _XA_WM_DESKTOP; Atom _XA_MwmAtom; Atom _XA_MOTIF_WM; Atom _XA_OL_WIN_ATTR; Atom _XA_OL_WT_BASE; Atom _XA_OL_WT_CMD; Atom _XA_OL_WT_HELP; Atom _XA_OL_WT_NOTICE; Atom _XA_OL_WT_OTHER; Atom _XA_OL_DECOR_ADD; Atom _XA_OL_DECOR_DEL; Atom _XA_OL_DECOR_CLOSE; Atom _XA_OL_DECOR_RESIZE; Atom _XA_OL_DECOR_HEADER; Atom _XA_OL_DECOR_ICON_NAME; Atom _XA_WM_WINDOW_ROLE; Atom _XA_WINDOW_ROLE; Atom _XA_WM_CLIENT_LEADER; Atom _XA_SM_CLIENT_ID; Atom _XA_XROOTPMAP_ID; Atom _XA_XSETROOT_ID; /* ---------------------------- local functions ---------------------------- */ static void SaveDesktopState(void) { FvwmWindow *t; unsigned long data[1]; for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) { data[0] = (unsigned long) t->Desk; XChangeProperty( dpy, FW_W(t), _XA_WM_DESKTOP, _XA_WM_DESKTOP, 32, PropModeReplace, (unsigned char *)data, 1); } data[0] = (unsigned long) Scr.CurrentDesk; XChangeProperty( dpy, Scr.Root, _XA_WM_DESKTOP, _XA_WM_DESKTOP, 32, PropModeReplace, (unsigned char *) data, 1); XFlush(dpy); return; } static void InternUsefulAtoms (void) { /* Create priority colors if necessary. */ _XA_MIT_PRIORITY_COLORS = XInternAtom( dpy, "_MIT_PRIORITY_COLORS", False); _XA_WM_CHANGE_STATE = XInternAtom(dpy, "WM_CHANGE_STATE", False); _XA_WM_STATE = XInternAtom(dpy, "WM_STATE", False); _XA_WM_COLORMAP_WINDOWS = XInternAtom( dpy, "WM_COLORMAP_WINDOWS", False); _XA_WM_PROTOCOLS = XInternAtom(dpy, "WM_PROTOCOLS", False); _XA_WM_TAKE_FOCUS = XInternAtom(dpy, "WM_TAKE_FOCUS", False); _XA_WM_DELETE_WINDOW = XInternAtom(dpy, "WM_DELETE_WINDOW", False); _XA_WM_DESKTOP = XInternAtom(dpy, "WM_DESKTOP", False); _XA_MwmAtom=XInternAtom(dpy, "_MOTIF_WM_HINTS",False); _XA_MOTIF_WM=XInternAtom(dpy, "_MOTIF_WM_INFO",False); _XA_OL_WIN_ATTR=XInternAtom(dpy, "_OL_WIN_ATTR",False); _XA_OL_WT_BASE=XInternAtom(dpy, "_OL_WT_BASE",False); _XA_OL_WT_CMD=XInternAtom(dpy, "_OL_WT_CMD",False); _XA_OL_WT_HELP=XInternAtom(dpy, "_OL_WT_HELP",False); _XA_OL_WT_NOTICE=XInternAtom(dpy, "_OL_WT_NOTICE",False); _XA_OL_WT_OTHER=XInternAtom(dpy, "_OL_WT_OTHER",False); _XA_OL_DECOR_ADD=XInternAtom(dpy, "_OL_DECOR_ADD",False); _XA_OL_DECOR_DEL=XInternAtom(dpy, "_OL_DECOR_DEL",False); _XA_OL_DECOR_CLOSE=XInternAtom(dpy, "_OL_DECOR_CLOSE",False); _XA_OL_DECOR_RESIZE=XInternAtom(dpy, "_OL_DECOR_RESIZE",False); _XA_OL_DECOR_HEADER=XInternAtom(dpy, "_OL_DECOR_HEADER",False); _XA_OL_DECOR_ICON_NAME=XInternAtom(dpy, "_OL_DECOR_ICON_NAME",False); _XA_WM_WINDOW_ROLE=XInternAtom(dpy, "WM_WINDOW_ROLE",False); _XA_WINDOW_ROLE=XInternAtom(dpy, "WINDOW_ROLE",False); _XA_WM_CLIENT_LEADER=XInternAtom(dpy, "WM_CLIENT_LEADER",False); _XA_SM_CLIENT_ID=XInternAtom(dpy, "SM_CLIENT_ID",False); _XA_XROOTPMAP_ID=XInternAtom(dpy, "_XROOTPMAP_ID",False); _XA_XSETROOT_ID=XInternAtom(dpy, "_XSETROOT_ID",False); return; } /* exit handler that will try to release any grabs */ static void catch_exit(void) { if (dpy != NULL) { /* Don't care if this is called from an X error handler. We * *have* to try this, whatever happens. XFree 4.0 may freeze * if we don't do this. */ XUngrabServer(dpy); XUngrabPointer(dpy, CurrentTime); XUngrabKeyboard(dpy, CurrentTime); } return; } /* * Restart on a signal */ static RETSIGTYPE Restart(int sig) { fvwmRunState = FVWM_RESTART; /* This function might not return - it could "long-jump" * right out, so we need to do everything we need to do * BEFORE we call it ... */ fvwmSetTerminate(sig); SIGNAL_RETURN; } static RETSIGTYPE SigDone(int sig) { fvwmRunState = FVWM_DONE; /* This function might not return - it could "long-jump" * right out, so we need to do everything we need to do * BEFORE we call it ... */ fvwmSetTerminate(sig); SIGNAL_RETURN; } /* * parse_command_args - parses a given command string into a given limited * argument array suitable for execv*. The parsing is similar to shell's. * Returns: * positive number of parsed arguments - on success, * 0 - on empty command (only spaces), * negative - on no command or parsing error. * * Any character can be quoted with a backslash (even inside single quotes). * Every command argument is separated by a space/tab/new-line from both sizes * or is at the start/end of the command. Sequential spaces are ignored. * An argument can be enclosed into single quotes (no further expanding) * or double quotes (expending environmental variables $VAR or ${VAR}). * The character '~' is expanded into user home directory (if not in quotes). * * In the current implementation, parsed arguments are stored in one * large static string pointed by returned argv[0], so they will be lost * on the next function call. This can be changed using dynamic allocation, * in this case the caller must free the string pointed by argv[0]. */ static int parse_command_args( const char *command, char **argv, int max_argc, const char **error_msg) { /* It is impossible to guess the exact length because of expanding */ #define MAX_TOTAL_ARG_LEN 256 /* char *arg_string = safemalloc(MAX_TOTAL_ARG_LEN); */ static char arg_string[MAX_TOTAL_ARG_LEN]; int total_arg_len = 0; int error_code = 0; int argc; char *aptr = arg_string; const char *cptr = command; #define the_char (*cptr) #define adv_char (cptr++) #define top_char (*cptr == '\\' ? *(cptr + 1) : *cptr) #define pop_char (*(cptr++) == '\\' ? *(cptr++) : *(cptr - 1)) #define can_add_arg_char (total_arg_len < MAX_TOTAL_ARG_LEN-1) #define add_arg_char(ch) (++total_arg_len, *(aptr++) = ch) #define can_add_arg_str(str) (total_arg_len < MAX_TOTAL_ARG_LEN - strlen(str)) #define add_arg_str(str) \ {\ const char *tmp = str;\ while (*tmp)\ {\ add_arg_char(*(tmp++));\ }\ } *error_msg = ""; if (!command) { *error_msg = "No command"; return -1; } for (argc = 0; argc < max_argc - 1; argc++) { int s_quote = 0; argv[argc] = aptr; while (isspace(the_char)) { adv_char; } if (the_char == '\0') { break; } while ((s_quote || !isspace(the_char)) && the_char != '\0' && can_add_arg_char) { if (the_char == '"') { if (s_quote) { s_quote = 0; } else { s_quote = 1; } adv_char; } else if (!s_quote && the_char == '\'') { adv_char; while (the_char != '\'' && the_char != '\0' && can_add_arg_char) { add_arg_char(pop_char); } if (the_char == '\'') { adv_char; } else if (!can_add_arg_char) { break; } else { *error_msg = "No closing single quote"; error_code = -3; break; } } else if (!s_quote && the_char == '~') { if (!can_add_arg_str(home_dir)) { break; } add_arg_str(home_dir); adv_char; } else if (the_char == '$') { int beg, len; const char *str = getFirstEnv(cptr, &beg, &len); if (!str || beg) { add_arg_char(the_char); adv_char; continue; } if (!can_add_arg_str(str)) { break; } add_arg_str(str); cptr += len; } else { if (add_arg_char(pop_char) == '\0') { break; } } } if (*(aptr-1) == '\0') { *error_msg = "Unexpected last backslash"; error_code = -2; break; } if (error_code) { break; } if (the_char == '~' || the_char == '$' || !can_add_arg_char) { *error_msg = "The command is too long"; error_code = -argc - 100; break; } if (s_quote) { *error_msg = "No closing double quote"; error_code = -4; break; } add_arg_char('\0'); } #undef the_char #undef adv_char #undef top_char #undef pop_char #undef can_add_arg_char #undef add_arg_char #undef can_add_arg_str #undef add_arg_str argv[argc] = NULL; if (argc == 0 && !error_code) { *error_msg = "Void command"; } return error_code ? error_code : argc; } /* * */ static char *get_display_name(char *display_name, int screen_num) { char *msg; char *new_dn; char *cp; char string_screen_num[32]; CopyString(&msg, display_name); cp = strchr(msg, ':'); if (cp != NULL) { cp = strchr(cp, '.'); if (cp != NULL) { /* truncate at display part */ *cp = '\0'; } } sprintf(string_screen_num, ".%d", screen_num); new_dn = safemalloc( strlen(msg) + strlen(string_screen_num) + 1); new_dn[0] = '\0'; strcat(new_dn, msg); strcat(new_dn, string_screen_num); free(msg); return new_dn; } /* * * Procedure: * Done - tells fvwm to clean up and exit * */ /* if restart is true, command must not be NULL... */ void Done(int restart, char *command) { const char *exit_func_name; if (!restart) { MoveViewport(0,0,False); } /* migo (03/Jul/1999): execute [Session]ExitFunction */ exit_func_name = get_init_function_name(2); if (functions_is_complex_function(exit_func_name)) { const exec_context_t *exc; exec_context_changes_t ecc; char *action = safestrdup( CatString2("Function ", exit_func_name)); ecc.type = restart ? EXCT_TORESTART : EXCT_QUIT; ecc.w.wcontext = C_ROOT; exc = exc_create_context(&ecc, ECC_TYPE | ECC_WCONTEXT); execute_function(NULL, exc, action, 0); exc_destroy_context(exc); free(action); } /* XFree freeze hack */ XUngrabPointer(dpy, CurrentTime); XUngrabKeyboard(dpy, CurrentTime); XUngrabServer(dpy); if (!restart) { Reborder(); } EWMH_ExitStuff(); if (restart) { Bool do_preserve_state = True; SaveDesktopState(); if (command) { while (isspace(command[0])) { command++; } if (strncmp(command, "--dont-preserve-state", 21) == 0) { do_preserve_state = False; command += 21; while (isspace(command[0])) command++; } } if (command[0] == '\0') { command = NULL; /* native restart */ } /* won't return under SM on Restart without parameters */ RestartInSession( restart_state_filename, command == NULL, do_preserve_state); /* RBW - 06/08/1999 - without this, windows will wander to * other pages on a Restart/Recapture because Restart gets the * window position information out of sync. There may be a * better way to do this (i.e., adjust the Restart code), but * this works for now. */ MoveViewport(0,0,False); Reborder(); /* Really make sure that the connection is closed and cleared! */ CloseICCCM2(); catch_exit(); XCloseDisplay(dpy); dpy = NULL; /* really need to destroy all windows, explicitly, not sleep, * but this is adequate for now */ sleep(1); if (command) { char *my_argv[MAX_ARG_SIZE]; const char *error_msg; int n = parse_command_args( command, my_argv, MAX_ARG_SIZE, &error_msg); if (n <= 0) { fvwm_msg( ERR, "Done", "Restart command parsing error in" " (%s): [%s]", command, error_msg); } else if (strcmp(my_argv[0], "--pass-args") == 0) { if (n != 2) { fvwm_msg( ERR, "Done", "Restart --pass-args: single" " name expected. (restarting" " '%s' instead)", g_argv[0]); } else { int i; my_argv[0] = my_argv[1]; for (i = 1; i < g_argc && i < MAX_ARG_SIZE - 1; i++) { my_argv[i] = g_argv[i]; } my_argv[i] = NULL; execvp(my_argv[0], my_argv); fvwm_msg( ERR, "Done", "Call of '%s' failed!" " (restarting '%s' instead)", my_argv[0], g_argv[0]); perror(" system error description"); } } else { char *str = NULL; /* Warn against an old 'Restart fvwm2' usage */ if (n == 1 && strcmp(my_argv[0], "fvwm2") == 0) { str = "fvwm2"; } /* If we are at it, warn against a 'Restart * fvwm' usage as well */ else if (n == 1 && strcmp(my_argv[0], "fvwm") == 0) { str = "fvwm"; } if (str) { fvwm_msg( WARN, "Done", "`Restart %s' might not do" " what you want, see the man" " page.\n\tUse Restart without" " parameters if you mean to" " restart the same WM.", str); } execvp(my_argv[0], my_argv); fvwm_msg( ERR, "Done", "Call of '%s' failed!" " (restarting '%s' instead)", my_argv[0], g_argv[0]); perror(" system error description"); } } execvp(g_argv[0], g_argv); /* that _should_ work */ fvwm_msg(ERR, "Done", "Call of '%s' failed!", g_argv[0]); perror(" system error description"); } else { CloseICCCM2(); catch_exit(); XCloseDisplay(dpy); dpy = NULL; } /* dv (15-Jan-2000): This must be done after calling CloseICCCM2()! * Otherwise fvwm ignores map requests while it still has * SubstructureRedirect selected on the root window ==> windows end up * in nirvana. This explicitly happened with windows unswallowed by * FvwmButtons. */ module_kill_all(); exit(0); } /*********************************************************************** * * Procedure: * InstallSignals: install the signal handlers, using whatever * means we have at our disposal. The more POSIXy, the better * ************************************************************************/ static void InstallSignals(void) { #ifdef HAVE_SIGACTION struct sigaction sigact; /* * All signals whose handlers call fvwmSetTerminate() * must be mutually exclusive - we mustn't receive one * while processing any of the others ... */ sigemptyset(&sigact.sa_mask); sigaddset(&sigact.sa_mask, SIGINT); sigaddset(&sigact.sa_mask, SIGHUP); sigaddset(&sigact.sa_mask, SIGQUIT); sigaddset(&sigact.sa_mask, SIGTERM); sigaddset(&sigact.sa_mask, SIGUSR1); #ifdef SA_RESTART sigact.sa_flags = SA_RESTART; #else sigact.sa_flags = 0; #endif sigact.sa_handler = DeadPipe; sigaction(SIGPIPE, &sigact, NULL); sigact.sa_handler = Restart; sigaction(SIGUSR1, &sigact, NULL); sigact.sa_handler = SigDone; sigaction(SIGINT, &sigact, NULL); sigaction(SIGHUP, &sigact, NULL); sigaction(SIGQUIT, &sigact, NULL); sigaction(SIGTERM, &sigact, NULL); /* Unblock these signals so that we can process them again. */ sigprocmask(SIG_UNBLOCK, &sigact.sa_mask, NULL); /* Reap all zombies automatically! This signal handler will only be * called if a child process dies, not if someone sends a child a STOP * signal. Note that none of our "terminate" signals can be delivered * until the SIGCHLD handler completes, and this is a Good Thing * because the terminate handlers might exit abruptly via "siglongjmp". * This could potentially leave SIGCHLD handler with unfinished * business ... * * NOTE: We could still receive SIGPIPE signals within the SIGCHLD * handler, but the SIGPIPE handler has the SA_RESTART flag set and so * should not affect our "wait" system call. */ sigact.sa_flags |= SA_NOCLDSTOP; sigact.sa_handler = fvwmReapChildren; sigaction(SIGCHLD, &sigact, NULL); #else #ifdef USE_BSD_SIGNALS fvwmSetSignalMask( sigmask(SIGUSR1) | sigmask(SIGINT) | sigmask(SIGHUP) | sigmask(SIGQUIT) | sigmask(SIGTERM) ); #endif /* * We don't have sigaction(), so fall back on * less reliable methods ... */ signal(SIGPIPE, DeadPipe); signal(SIGUSR1, Restart); #ifdef HAVE_SIGINTERRUPT siginterrupt(SIGUSR1, 0); #endif signal(SIGINT, SigDone); #ifdef HAVE_SIGINTERRUPT siginterrupt(SIGINT, 0); #endif signal(SIGHUP, SigDone); #ifdef HAVE_SIGINTERRUPT siginterrupt(SIGHUP, 0); #endif signal(SIGQUIT, SigDone); #ifdef HAVE_SIGINTERRUPT siginterrupt(SIGQUIT, 0); #endif signal(SIGTERM, SigDone); #ifdef HAVE_SIGINTERRUPT siginterrupt(SIGTERM, 0); #endif signal(SIGCHLD, fvwmReapChildren); #ifdef HAVE_SIGINTERRUPT siginterrupt(SIGCHLD, 0); #endif #endif /* When fvwm restarts, the SIGCHLD handler is automatically reset * to the default handler. This means that Zombies left over from * the previous instance of fvwm could still be roaming the process * table if they exited while the default handler was in place. * We fix this by invoking the SIGCHLD handler NOW, so that they * may finally rest in peace. */ fvwmReapChildren(0); return; } void fvmm_deinstall_signals(void) { signal(SIGCHLD, SIG_DFL); signal(SIGHUP, SIG_DFL); signal(SIGINT, SIG_DFL); signal(SIGPIPE, SIG_DFL); signal(SIGQUIT, SIG_DFL); signal(SIGTERM, SIG_DFL); signal(SIGUSR1, SIG_DFL); return; } /*********************************************************************** * * LoadDefaultLeftButton -- loads default left button # into * assumes associated button memory is already free * ************************************************************************/ static void LoadDefaultLeftButton(DecorFace *df, int i) { struct vector_coords *v = &df->u.vector; int j = 0; memset(&df->style, 0, sizeof(df->style)); DFS_FACE_TYPE(df->style) = DefaultVectorButton; switch (i % 5) { case 0: case 4: v->num = 5; v->x = (signed char*)safemalloc(sizeof(char) * v->num); v->y = (signed char*)safemalloc(sizeof(char) * v->num); v->xoff = (signed char*)safemalloc(sizeof(char) * v->num); v->yoff = (signed char*)safemalloc(sizeof(char) * v->num); v->c = (signed char*)safecalloc(v->num, sizeof(char)); v->x[0] = 22; v->y[0] = 39; v->c[0] = 1; v->x[1] = 78; v->y[1] = 39; v->c[1] = 1; v->x[2] = 78; v->y[2] = 61; v->x[3] = 22; v->y[3] = 61; v->x[4] = 22; v->y[4] = 39; v->c[4] = 1; break; case 1: v->num = 5; v->x = (signed char*)safemalloc(sizeof(char) * v->num); v->y = (signed char*)safemalloc(sizeof(char) * v->num); v->xoff = (signed char*)safemalloc(sizeof(char) * v->num); v->yoff = (signed char*)safemalloc(sizeof(char) * v->num); v->c = (signed char*)safecalloc(v->num, sizeof(char)); v->x[0] = 32; v->y[0] = 45; v->x[1] = 68; v->y[1] = 45; v->x[2] = 68; v->y[2] = 55; v->c[2] = 1; v->x[3] = 32; v->y[3] = 55; v->c[3] = 1; v->x[4] = 32; v->y[4] = 45; break; case 2: v->num = 5; v->x = (signed char*)safemalloc(sizeof(char) * v->num); v->y = (signed char*)safemalloc(sizeof(char) * v->num); v->xoff = (signed char*)safemalloc(sizeof(char) * v->num); v->yoff = (signed char*)safemalloc(sizeof(char) * v->num); v->c = (signed char*)safecalloc(v->num, sizeof(char)); v->x[0] = 49; v->y[0] = 49; v->c[0] = 1; v->x[1] = 51; v->y[1] = 49; v->c[1] = 1; v->x[2] = 51; v->y[2] = 51; v->x[3] = 49; v->y[3] = 51; v->x[4] = 49; v->y[4] = 49; v->c[4] = 1; break; case 3: v->num = 5; v->x = (signed char*)safemalloc(sizeof(char) * v->num); v->y = (signed char*)safemalloc(sizeof(char) * v->num); v->xoff = (signed char*)safemalloc(sizeof(char) * v->num); v->yoff = (signed char*)safemalloc(sizeof(char) * v->num); v->c = (signed char*)safecalloc(v->num, sizeof(char)); v->x[0] = 32; v->y[0] = 45; v->c[0] = 1; v->x[1] = 68; v->y[1] = 45; v->c[1] = 1; v->x[2] = 68; v->y[2] = 55; v->x[3] = 32; v->y[3] = 55; v->x[4] = 32; v->y[4] = 45; v->c[4] = 1; break; } /* set offsets to 0, for all buttons */ for(j = 0 ; j < v->num ; j++) { v->xoff[j] = 0; v->yoff[j] = 0; } return; } /*********************************************************************** * * LoadDefaultRightButton -- loads default left button # into * assumes associated button memory is already free * ************************************************************************/ static void LoadDefaultRightButton(DecorFace *df, int i) { struct vector_coords *v = &df->u.vector; int j = 0; memset(&df->style, 0, sizeof(df->style)); DFS_FACE_TYPE(df->style) = DefaultVectorButton; switch (i % 5) { case 0: case 3: v->num = 5; v->x = (signed char*)safemalloc(sizeof(char) * v->num); v->y = (signed char*)safemalloc(sizeof(char) * v->num); v->xoff = (signed char*)safemalloc(sizeof(char) * v->num); v->yoff = (signed char*)safemalloc(sizeof(char) * v->num); v->c = (signed char*)safecalloc(v->num, sizeof(char)); v->x[0] = 25; v->y[0] = 25; v->c[0] = 1; v->x[1] = 75; v->y[1] = 25; v->c[1] = 1; v->x[2] = 75; v->y[2] = 75; v->x[3] = 25; v->y[3] = 75; v->x[4] = 25; v->y[4] = 25; v->c[4] = 1; break; case 1: v->num = 5; v->x = (signed char*)safemalloc(sizeof(char) * v->num); v->y = (signed char*)safemalloc(sizeof(char) * v->num); v->xoff = (signed char*)safemalloc(sizeof(char) * v->num); v->yoff = (signed char*)safemalloc(sizeof(char) * v->num); v->c = (signed char*)safecalloc(v->num, sizeof(char)); v->x[0] = 39; v->y[0] = 39; v->c[0] = 1; v->x[1] = 61; v->y[1] = 39; v->c[1] = 1; v->x[2] = 61; v->y[2] = 61; v->x[3] = 39; v->y[3] = 61; v->x[4] = 39; v->y[4] = 39; v->c[4] = 1; break; case 2: v->num = 5; v->x = (signed char*)safemalloc(sizeof(char) * v->num); v->y = (signed char*)safemalloc(sizeof(char) * v->num); v->xoff = (signed char*)safemalloc(sizeof(char) * v->num); v->yoff = (signed char*)safemalloc(sizeof(char) * v->num); v->c = (signed char*)safecalloc(v->num, sizeof(char)); v->x[0] = 49; v->y[0] = 49; v->c[0] = 1; v->x[1] = 51; v->y[1] = 49; v->c[1] = 1; v->x[2] = 51; v->y[2] = 51; v->x[3] = 49; v->y[3] = 51; v->x[4] = 49; v->y[4] = 49; v->c[4] = 1; break; case 4: v->num = 5; v->x = (signed char*)safemalloc(sizeof(char) * v->num); v->y = (signed char*)safemalloc(sizeof(char) * v->num); v->xoff = (signed char*)safemalloc(sizeof(char) * v->num); v->yoff = (signed char*)safemalloc(sizeof(char) * v->num); v->c = (signed char*)safecalloc(v->num, sizeof(char)); v->x[0] = 36; v->y[0] = 36; v->c[0] = 1; v->x[1] = 64; v->y[1] = 36; v->c[1] = 1; v->x[2] = 64; v->y[2] = 64; v->x[3] = 36; v->y[3] = 64; v->x[4] = 36; v->y[4] = 36; v->c[4] = 1; break; } /* set offsets to 0, for all buttons */ for(j = 0 ; j < v->num ; j++) { v->xoff[j] = 0; v->yoff[j] = 0; } return; } /*********************************************************************** * * Procedure: * CreateGCs - open fonts and create all the needed GC's. I only * want to do this once, hence the first_time flag. * ***********************************************************************/ static void CreateGCs(void) { XGCValues gcv; unsigned long gcm; /* create scratch GC's */ gcm = GCFunction|GCLineWidth; gcv.function = GXcopy; gcv.line_width = 0; Scr.ScratchGC1 = fvwmlib_XCreateGC(dpy, Scr.NoFocusWin, gcm, &gcv); Scr.ScratchGC2 = fvwmlib_XCreateGC(dpy, Scr.NoFocusWin, gcm, &gcv); Scr.ScratchGC3 = fvwmlib_XCreateGC(dpy, Scr.NoFocusWin, gcm, &gcv); Scr.ScratchGC4 = fvwmlib_XCreateGC(dpy, Scr.NoFocusWin, gcm, &gcv); Scr.TitleGC = fvwmlib_XCreateGC(dpy, Scr.NoFocusWin, gcm, &gcv); Scr.BordersGC = fvwmlib_XCreateGC(dpy, Scr.NoFocusWin, gcm, &gcv); Scr.TransMaskGC = fvwmlib_XCreateGC(dpy, Scr.NoFocusWin, gcm, &gcv); Scr.ScratchMonoPixmap = XCreatePixmap(dpy, Scr.Root, 1, 1, 1); Scr.MonoGC = fvwmlib_XCreateGC(dpy, Scr.ScratchMonoPixmap, gcm, &gcv); Scr.ScratchAlphaPixmap = XCreatePixmap( dpy, Scr.Root, 1, 1, FRenderGetAlphaDepth()); Scr.AlphaGC = fvwmlib_XCreateGC(dpy, Scr.ScratchAlphaPixmap, gcm, &gcv); return; } /*********************************************************************** * * Procedure: * InitVariables - initialize fvwm variables * ************************************************************************/ static void InitVariables(void) { FvwmContext = XUniqueContext(); MenuContext = XUniqueContext(); /* initialize some lists */ Scr.AllBindings = NULL; Scr.functions = NULL; menus_init(); Scr.last_added_item.type = ADDED_NONE; Scr.DefaultIcon = NULL; Scr.DefaultColorset = -1; Scr.StdGC = 0; Scr.StdReliefGC = 0; Scr.StdShadowGC = 0; Scr.XorGC = 0; /* zero all flags */ memset(&Scr.flags, 0, sizeof(Scr.flags)); /* create graphics contexts */ CreateGCs(); FW_W(&Scr.FvwmRoot) = Scr.Root; Scr.FvwmRoot.next = 0; init_stack_and_layers(); Scr.root_pushes = 0; Scr.fvwm_pushes = 0; Scr.pushed_window = &Scr.FvwmRoot; Scr.FvwmRoot.number_cmap_windows = 0; Scr.FvwmRoot.attr_backup.colormap = Pcmap; Scr.MyDisplayWidth = DisplayWidth(dpy, Scr.screen); Scr.MyDisplayHeight = DisplayHeight(dpy, Scr.screen); Scr.BusyCursor = BUSY_NONE; Scr.Hilite = NULL; Scr.DefaultFont = NULL; Scr.VxMax = 2*Scr.MyDisplayWidth; Scr.VyMax = 2*Scr.MyDisplayHeight; Scr.Vx = 0; Scr.Vy = 0; Scr.SizeWindow = None; /* Sets the current desktop number to zero */ /* Multiple desks are available even in non-virtual * compilations */ Scr.CurrentDesk = 0; Scr.EdgeScrollX = DEFAULT_EDGE_SCROLL * Scr.MyDisplayWidth / 100; Scr.EdgeScrollY = DEFAULT_EDGE_SCROLL * Scr.MyDisplayHeight / 100; Scr.ScrollDelay = DEFAULT_SCROLL_DELAY; Scr.OpaqueSize = DEFAULT_OPAQUE_MOVE_SIZE; Scr.MoveThreshold = DEFAULT_MOVE_THRESHOLD; /* ClickTime is set to the positive value upon entering the * event loop. */ Scr.ClickTime = -DEFAULT_CLICKTIME; Scr.ColormapFocus = COLORMAP_FOLLOWS_MOUSE; /* set major operating modes */ Scr.NumBoxes = 0; Scr.cascade_x = 0; Scr.cascade_y = 0; /* the last Cascade placed window or NULL, we don't want NULL * initially */ Scr.cascade_window = &Scr.FvwmRoot; Scr.buttons2grab = 0; /* initialisation of the head of the desktops info */ Scr.Desktops = (DesktopsInfo *)safemalloc(sizeof(DesktopsInfo)); Scr.Desktops->name = NULL; Scr.Desktops->desk = 0; /* not desk 0 */ Scr.Desktops->ewmh_dyn_working_area.x = Scr.Desktops->ewmh_working_area.x = 0; Scr.Desktops->ewmh_dyn_working_area.y = Scr.Desktops->ewmh_working_area.y = 0; Scr.Desktops->ewmh_dyn_working_area.width = Scr.Desktops->ewmh_working_area.width = Scr.MyDisplayWidth; Scr.Desktops->ewmh_dyn_working_area.height = Scr.Desktops->ewmh_working_area.height = Scr.MyDisplayHeight; Scr.Desktops->next = NULL; /* ewmh desktop */ Scr.EwmhDesktop = NULL; InitFvwmDecor(&Scr.DefaultDecor); Scr.DefaultDecor.tag = "Default"; /* Initialize RaiseHackNeeded by identifying X servers possibly running under NT. This is probably not an ideal solution, since eg NCD also produces X servers which do not run under NT. "Hummingbird Communications Ltd." is the ServerVendor string of the Exceed X server under NT, "Network Computing Devices Inc." is the ServerVendor string of the PCXware X server under Windows. "WRQ, Inc." is the ServerVendor string of the Reflection X server under Windows. */ Scr.bo.is_raise_hack_needed = (strcmp ( ServerVendor (dpy), "Hummingbird Communications Ltd.") == 0) || (strcmp ( ServerVendor (dpy), "Network Computing Devices Inc.") == 0) || (strcmp (ServerVendor (dpy), "WRQ, Inc.") == 0); Scr.bo.is_modality_evil = 0; Scr.bo.do_disable_configure_notify = 0; Scr.bo.do_install_root_cmap = 0; Scr.bo.do_enable_flickering_qt_dialogs_workaround = 1; Scr.bo.do_enable_qt_drag_n_drop_workaround = 0; Scr.bo.do_enable_ewmh_iconic_state_workaround = 0; Scr.gs.do_emulate_mwm = DEFAULT_EMULATE_MWM; Scr.gs.do_emulate_win = DEFAULT_EMULATE_WIN; Scr.gs.use_active_down_buttons = DEFAULT_USE_ACTIVE_DOWN_BUTTONS; Scr.gs.use_inactive_buttons = DEFAULT_USE_INACTIVE_BUTTONS; Scr.gs.use_inactive_down_buttons = DEFAULT_USE_INACTIVE_DOWN_BUTTONS; /* Not the right place for this, should only be called once * somewhere .. */ /* EdgeCommands - no edge commands by default */ Scr.PanFrameTop.command = NULL; Scr.PanFrameBottom.command = NULL; Scr.PanFrameRight.command = NULL; Scr.PanFrameLeft.command = NULL; /* EdgeLeaveCommands - no edge leave commands by default */ Scr.PanFrameTop.command_leave = NULL; Scr.PanFrameBottom.command_leave = NULL; Scr.PanFrameRight.command_leave = NULL; Scr.PanFrameLeft.command_leave = NULL; Scr.flags.is_pointer_on_this_screen = !!FQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, &JunkX, &JunkY, &JunkX, &JunkY, &JunkMask); /* make sure colorset 0 exists */ alloc_colorset(0); return; } static void usage(int is_verbose) { fprintf(stderr, "usage: %s", g_argv[0]); fprintf(stderr, " [-d display]" " [-f cfgfile]" " [-c cmd]" " [-s [screen_num]]" " [-I vis-id | -C vis-class]" " [-l colors" " [-L|A|S|P] ...]" " [-r]" " [OTHER OPTIONS] ..." "\n"); if (!is_verbose) { fprintf( stderr, "Try '%s --help' for more information.\n", g_argv[0]); return; } fprintf(stderr, " -A: allocate palette\n" " -c cmd: preprocess configuration file with \n" " -C vis-class: use visual class \n" " -d display: run fvwm on \n" " -D: enable debug oputput\n" " -f cfgfile: read configuration from \n" " -F file: used internally for session management\n" " -h, -?: print this help message\n" " -i client-id: used internally for session management\n" " -I vis-id: use visual \n" " -l colors: try to use no more than colors\n" " -L: strict color limit\n" " -P: visual palette\n" " -r: replace running window manager\n" " -s [screen]: manage a single screen\n" " -S: static palette\n" " -V: print version information\n" ); fprintf( stderr, "Try 'man %s' for more information.\n", PACKAGE); return; } static void setVersionInfo(void) { char version_str[256]; char license_str[512]; char support_str[512] = ""; int support_len; /* Set version information string */ sprintf(version_str, "fvwm %s%s compiled on %s at %s", VERSION, VERSIONINFO, __DATE__, __TIME__); Fvwm_VersionInfo = safestrdup(version_str); sprintf(license_str, "fvwm comes with NO WARRANTY, to the extent permitted by law. " "You may\nredistribute copies of fvwm under " "the terms of the GNU General Public License.\n" "For more information about these matters, see the file " "named COPYING."); Fvwm_LicenseInfo = safestrdup(license_str); #ifdef HAVE_READLINE strcat(support_str, " ReadLine,"); #endif #ifdef HAVE_RPLAY strcat(support_str, " RPlay,"); #endif #ifdef HAVE_STROKE strcat(support_str, " Stroke,"); #endif #ifdef XPM strcat(support_str, " XPM,"); #endif #ifdef HAVE_RSVG strcat(support_str, " SVG,"); #endif if (FHaveShapeExtension) strcat(support_str, " Shape,"); #ifdef HAVE_XSHM strcat(support_str, " XShm,"); #endif #ifdef SESSION strcat(support_str, " SM,"); #endif #ifdef HAVE_BIDI strcat(support_str, " Bidi text,"); #endif #ifdef HAVE_XINERAMA strcat(support_str, " Xinerama,"); #endif #ifdef HAVE_XRENDER strcat(support_str, " XRender,"); #endif #ifdef HAVE_XCURSOR strcat(support_str, " XCursor,"); #endif #ifdef HAVE_XFT strcat(support_str, " XFT,"); #endif #ifdef HAVE_NLS strcat(support_str, " NLS,"); #endif support_len = strlen(support_str); if (support_len > 0) { /* strip last comma */ support_str[support_len - 1] = '\0'; Fvwm_SupportInfo = safestrdup( CatString2("with support for:", support_str)); } else { Fvwm_SupportInfo = "with no optional feature support"; } return; } /* Sets some initial style values & such */ static void SetRCDefaults(void) { #define RC_DEFAULTS_COMPLETE ((char *)-1) int i; /* set up default colors, fonts, etc */ const char *defaults[][3] = { { "XORValue 0", "", "" }, { "ImagePath "FVWM_DATADIR"/default-config/images", "", "" }, { "SetEnv FVWM_DATADIR "FVWM_DATADIR"", "", "" }, /* The below is historical -- before we had a default * configuration which defines these and more. */ { "DefaultFont", "", "" }, { "DefaultColors black grey", "", "" }, { DEFAULT_MENU_STYLE, "", "" }, { "TitleStyle Centered -- Raised", "", "" }, { "Style * Color lightgrey/dimgrey", "", "" }, { "Style * HilightFore black, HilightBack grey", "", "" }, { "DestroyFunc FvwmMakeMissingDesktopMenu", "", "" }, { "AddToFunc FvwmMakeMissingDesktopMenu I PipeRead 'fvwm-menu-desktop --enable-mini-icons --fvwm-icons'", "", "" }, { "AddToMenu MenuFvwmRoot \"", _("Builtin Menu"), "\" Title" }, { "+ MissingSubmenuFunction FvwmMakeMissingDesktopMenu","",""}, { "+ \"&1. XTerm\" Exec xterm", "", ""}, { "+ \"&2. ", _("Issue fvwm commands"), "\" Module FvwmConsole" }, { "+ \"&D. ", _("Desktop Menu"), "\" Popup FvwmMenu" }, { "+ \"&R. ", _("Restart fvwm"), "\" Restart" }, { "+ \"&X. ", _("Exit fvwm"), "\" Quit" }, { "Mouse 1 R A Menu MenuFvwmRoot", "", "" }, /* default menu navigation */ { "Key Escape M A MenuClose", "", "" }, { "Key Return M A MenuSelectItem", "", "" }, { "Key Left M A MenuCursorLeft", "", "" }, { "Key Right M A MenuCursorRight", "", "" }, { "Key Up M A MenuMoveCursor -1", "", "" }, { "Key Down M A MenuMoveCursor 1", "", "" }, { "Mouse 1 MI A MenuSelectItem", "", "" }, /* don't add anything below */ { RC_DEFAULTS_COMPLETE, "", "" }, { "Read "FVWM_DATADIR"/ConfigFvwmDefaults", "", "" }, { NULL, NULL, NULL } }; for (i = 0; defaults[i][0] != NULL; i++) { const exec_context_t *exc; exec_context_changes_t ecc; char *cmd; if (defaults[i][0] == RC_DEFAULTS_COMPLETE) { menu_bindings_startup_complete(); continue; } ecc.type = Restarting ? EXCT_RESTART : EXCT_INIT; ecc.w.wcontext = C_ROOT; exc = exc_create_context(&ecc, ECC_TYPE | ECC_WCONTEXT); cmd = CatString3( defaults[i][0], defaults[i][1], defaults[i][2]); execute_function(NULL, exc, cmd, 0); exc_destroy_context(exc); } #undef RC_DEFAULTS_COMPLETE return; } static int CatchRedirectError(Display *dpy, XErrorEvent *event) { fvwm_msg(ERR, "CatchRedirectError", "another WM is running"); exit(1); /* to make insure happy */ return 0; } /* CatchFatal - Shuts down if the server connection is lost */ static int CatchFatal(Display *dpy) { /* No action is taken because usually this action is caused by someone using "xlogout" to be able to switch between multiple window managers */ module_kill_all(); exit(1); /* to make insure happy */ return 0; } /* FvwmErrorHandler - displays info on internal errors */ static int FvwmErrorHandler(Display *dpy, XErrorEvent *event) { if (event->error_code == BadWindow) { bad_window = event->resourceid; return 0; } /* some errors are acceptable, mostly they're caused by * trying to update a lost window or free'ing another modules colors */ if (event->error_code == BadWindow || event->request_code == X_GetGeometry || event->error_code == BadDrawable || event->request_code == X_ConfigureWindow || event->request_code == X_SetInputFocus|| event->request_code == X_GrabButton || event->request_code == X_ChangeWindowAttributes || event->request_code == X_InstallColormap || event->request_code == X_FreePixmap || event->request_code == X_FreeColors) { return 0; } fvwm_msg(ERR, "FvwmErrorHandler", "*** internal error ***"); fvwm_msg(ERR, "FvwmErrorHandler", "Request %d, Error %d, EventType: %d", event->request_code, event->error_code, last_event_type); return 0; } /* ---------------------------- interface functions ------------------------ */ /* Does initial window captures and runs init/restart function */ void StartupStuff(void) { #define start_func_name "StartFunction" const char *init_func_name; const exec_context_t *exc; exec_context_changes_t ecc; ecc.type = Restarting ? EXCT_RESTART : EXCT_INIT; ecc.w.wcontext = C_ROOT; exc = exc_create_context(&ecc, ECC_TYPE | ECC_WCONTEXT); CaptureAllWindows(exc, False); /* Turn off the SM stuff after the initial capture so that new windows * will not be matched by accident. */ if (Restarting) { DisableRestoringState(); } /* Have to do this here too because preprocessor modules have not run * to the end when HandleEvents is entered from the main loop. */ checkPanFrames(); fFvwmInStartup = False; /* Make sure the geometry window uses the current font */ resize_geometry_window(); /* Make sure we have the correct click time now. */ if (Scr.ClickTime < 0) { Scr.ClickTime = -Scr.ClickTime; } # if 0 /* It is safe to ungrab here: if not, and one of the init functions * does not finish, we've got a complete freeze! */ /* DV (15-Jul-2004): No, it is not safe to ungrab. If another * application grabs the pointer before execute_function gets it, the * start functions are not executed. And the pointer is grabbed * during function execution anyway, so releasing it here buys us * nothing. */ UngrabEm(GRAB_STARTUP); XUngrabPointer(dpy, CurrentTime); #endif /* migo (04-Sep-1999): execute StartFunction */ if (functions_is_complex_function(start_func_name)) { char *action = "Function " start_func_name; execute_function(NULL, exc, action, 0); } /* migo (03-Jul-1999): execute [Session]{Init|Restart}Function */ init_func_name = get_init_function_name(Restarting == True); if (functions_is_complex_function(init_func_name)) { char *action = safestrdup( CatString2("Function ", init_func_name)); execute_function(NULL, exc, action, 0); free(action); } /* see comment above */ UngrabEm(GRAB_STARTUP); XUngrabPointer(dpy, CurrentTime); /* This should be done after the initialization is finished, since * it directly changes the global state. */ LoadGlobalState(state_filename); /* ** migo (20-Jun-1999): Remove state file after usage. ** migo (09-Jul-1999): but only on restart, otherwise it can be reused. */ if (Restarting) { unlink(state_filename); } exc_destroy_context(exc); /* TA: 20091212: If we get here, we're done restarting, so reset the * flag back to False! */ Restarting = False; return; } /*********************************************************************** * * LoadDefaultButton -- loads default button # into button structure * assumes associated button memory is already free * ************************************************************************/ void LoadDefaultButton(DecorFace *df, int i) { if (i & 1) { LoadDefaultRightButton(df, i / 2); } else { LoadDefaultLeftButton(df, i / 2); } return; } /*********************************************************************** * * ResetOrDestroyAllButtons -- resets all buttons to defaults * destroys existing buttons * ************************************************************************/ void DestroyAllButtons(FvwmDecor *decor) { TitleButton *tbp; DecorFace *face; int i; int j; for (tbp = decor->buttons, i = 0; i < NUMBER_OF_TITLE_BUTTONS; i++, tbp++) { for (j = 0, face = TB_STATE(*tbp); j < BS_MaxButtonState; j++, face++) { FreeDecorFace(dpy, face); } } return; } void ResetAllButtons(FvwmDecor *decor) { TitleButton *tbp; DecorFace *face; int i; int j; DestroyAllButtons(decor); for (tbp = decor->buttons, i = 0; i < NUMBER_OF_TITLE_BUTTONS; i++, tbp++) { memset(&TB_FLAGS(*tbp), 0, sizeof(TB_FLAGS(*tbp))); TB_JUSTIFICATION(*tbp) = JUST_CENTER; for (face = TB_STATE(*tbp), j = 0; j < BS_MaxButtonState; j++, face++) { LoadDefaultButton(face, i); } } /* standard MWM decoration hint assignments (veliaa@rpi.edu) [Menu] - Title Bar - [Minimize] [Maximize] */ TB_MWM_DECOR_FLAGS(decor->buttons[0]) |= MWM_DECOR_MENU; TB_MWM_DECOR_FLAGS(decor->buttons[1]) |= MWM_DECOR_MAXIMIZE; TB_MWM_DECOR_FLAGS(decor->buttons[3]) |= MWM_DECOR_MINIMIZE; return; } void SetMWM_INFO(Window window) { struct mwminfo { long props[2]; /* prop[0]: flags */ /* prop[1]: win */ } motif_wm_info; static char set_yorn='n'; if (set_yorn=='y') { return; } if (Scr.bo.is_modality_evil) { /* Set Motif WM_INFO atom to make motif relinquish * broken handling of modal dialogs */ motif_wm_info.props[0] = 2; motif_wm_info.props[1] = window; XChangeProperty( dpy,Scr.Root, _XA_MOTIF_WM, _XA_MOTIF_WM,32, PropModeReplace, (unsigned char *)&motif_wm_info, 2); set_yorn='y'; } return; } /* * set_init_function_name - sets one of the init, restart or exit function names * get_init_function_name - gets one of the init, restart or exit function names * * First parameter defines a function type: 0 - init, 1 - restart, 2 - exit. */ void set_init_function_name(int n, const char *name) { init_function_names[n >= 0 && n < 3? n: 3] = name; return; } const char *get_init_function_name(int n) { return init_function_names[n >= 0 && n < 3? n: 3]; } #ifndef _PATH_DEVNULL # define _PATH_DEVNULL "/dev/null" #endif static void reopen_fd(int fd, char* mode, FILE *of) { struct stat sbuf; FILE *f; int rc; errno = 0; rc = fstat(fd, &sbuf); if (rc == 0) { return; } else if (errno != EBADF) { exit(77); } f = freopen(_PATH_DEVNULL, mode, of); if (f == 0 || fileno(f) != fd) { exit(88); } return; } /*********************************************************************** * * Procedure: * main - start of fvwm * ***********************************************************************/ int main(int argc, char **argv) { unsigned long valuemask; XSetWindowAttributes attributes; int i; int len; char *display_string; Bool do_force_single_screen = False; int single_screen_num = -1; Bool replace_wm = False; int visualClass = -1; int visualId = -1; PictureColorLimitOption colorLimitop = {-1, -1, -1, -1, -1}; const exec_context_t *exc; exec_context_changes_t ecc; DBUG("main", "Entered, about to parse args"); fvwmlib_init_max_fd(); /* Tell the FEvent module an event type that is not used by fvwm. */ fev_init_invalid_event_type(KeymapNotify); /* close open fds */ for (i = 3; i < fvwmlib_max_fd; i++) { close(i); } /* reopen stdin, stdout and stderr if necessary */ reopen_fd(0, "rb", stdin); reopen_fd(1, "wb", stdout); reopen_fd(2, "wb", stderr); memset(&Scr, 0, sizeof(Scr)); /* for use on restart */ g_argv = (char **)safemalloc((argc + 4) * sizeof(char *)); g_argc = argc; for (i = 0; i < argc; i++) { g_argv[i] = argv[i]; } g_argv[g_argc] = NULL; FlocaleInit(LC_CTYPE, "", "", "fvwm"); FGettextInit("fvwm", LOCALEDIR, "fvwm"); setVersionInfo(); /* Put the default module directory into the environment so it can be * used later by the config file, etc. */ flib_putenv("FVWM_MODULEDIR", "FVWM_MODULEDIR=" FVWM_MODULEDIR); /* Figure out user's home directory */ home_dir = getenv("HOME"); #ifdef HAVE_GETPWUID if (home_dir == NULL) { struct passwd* pw = getpwuid(getuid()); if (pw != NULL) { home_dir = safestrdup(pw->pw_dir); } } #endif if (home_dir == NULL) { home_dir = "/"; /* give up and use root dir */ } /* Figure out where to read and write user's data files. */ fvwm_userdir = getenv("FVWM_USERDIR"); if (fvwm_userdir == NULL) { char *s; fvwm_userdir = safestrdup(CatString2(home_dir, "/.fvwm")); /* Put the user directory into the environment so it can be used * later everywhere. */ s = safestrdup(CatString2("FVWM_USERDIR=", fvwm_userdir)); flib_putenv("FVWM_USERDIR", s); free(s); } /* Create FVWM_USERDIR directory if needed */ if (access(fvwm_userdir, F_OK) != 0) { mkdir(fvwm_userdir, 0777); } if (access(fvwm_userdir, W_OK) != 0) { fvwm_msg( ERR, "main", "No write permissions in `%s/'.\n", fvwm_userdir); } for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-debug_stack_ring") == 0 || strcmp(argv[i], "--debug-stack-ring") == 0) { debugging_stack_ring = True; } else if (strcmp(argv[i], "-D") == 0 || strcmp(argv[i], "-debug") == 0 || strcmp(argv[i], "--debug") == 0) { debugging = True; } else if (strcmp(argv[i], "-i") == 0 || strcmp(argv[i], "-clientid") == 0 || strcmp(argv[i], "--clientid") == 0 || strcmp(argv[i], "-clientId") == 0 || strcmp(argv[i], "--clientId") == 0) { if (++i >= argc) { usage(0); exit(1); } SetClientID(argv[i]); } else if (strcmp(argv[i], "-F") == 0 || strcmp(argv[i], "-restore") == 0 || strcmp(argv[i], "--restore") == 0) { if (++i >= argc) { usage(0); exit(1); } state_filename = argv[i]; } else if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "-single-screen") == 0 || strcmp(argv[i], "--single-screen") == 0) { do_force_single_screen = True; if (i+1 < argc && argv[i+1][0] != '-') { i++; if (sscanf(argv[i], "%d", &single_screen_num) == 0) { usage(0); exit(1); } } } else if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "-display") == 0 || strcmp(argv[i], "--display") == 0) { if (++i >= argc) { usage(0); exit(1); } display_name = argv[i]; } else if (strcmp(argv[i], "-f") == 0) { if (++i >= argc) { usage(0); exit(1); } if (num_config_commands < MAX_CFG_CMDS) { config_commands[num_config_commands] = (char *)malloc(6+strlen(argv[i])); strcpy(config_commands[num_config_commands], "Read "); strcat(config_commands[num_config_commands], argv[i]); /* Check to see if the file requested exists. * If it doesn't, use the default config * instead. */ if (access(argv[i], F_OK) != 0) { free(config_commands[num_config_commands]); config_commands[num_config_commands] = safestrdup("Read " FVWM_DATADIR "/default-config/config"); } num_config_commands++; } else { fvwm_msg( ERR, "main", "only %d -f and -cmd parms allowed!", MAX_CFG_CMDS); } } else if (strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "-cmd") == 0 || strcmp(argv[i], "--cmd") == 0) { if (++i >= argc) { usage(0); exit(1); } if (num_config_commands < MAX_CFG_CMDS) { config_commands[num_config_commands] = safestrdup(argv[i]); num_config_commands++; } else { fvwm_msg( ERR, "main", "only %d -f and -cmd parms allowed!", MAX_CFG_CMDS); } } else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-?") == 0 || strcmp(argv[i], "--help") == 0) { usage(1); exit(0); } else if (strcmp(argv[i], "-blackout") == 0) { /* obsolete option */ fvwm_msg( WARN, "main", "The -blackout option is obsolete, it will be " "removed in 3.0."); } else if (strcmp(argv[i], "-r") == 0 || strcmp(argv[i], "-replace") == 0 || strcmp(argv[i], "--replace") == 0) { replace_wm = True; } /* check for visualId before visual to remove ambiguity */ else if (strcmp(argv[i], "-I") == 0 || strcmp(argv[i], "-visualid") == 0 || strcmp(argv[i], "--visualid") == 0 || strcmp(argv[i], "-visualId") == 0 || strcmp(argv[i], "--visualId") == 0) { visualClass = -1; if (++i >= argc) { usage(0); exit(1); } if (sscanf(argv[i], "0x%x", &visualId) == 0) { if (sscanf(argv[i], "%d", &visualId) == 0) { usage(0); exit(1); } } } else if (strcmp(argv[i], "-C") == 0 || strcmp(argv[i], "-visual") == 0 || strcmp(argv[i], "--visual") == 0) { visualId = None; if (++i >= argc) { usage(0); exit(1); } if (strncasecmp(argv[i], "staticg", 7) == 0) { visualClass = StaticGray; } else if (strncasecmp(argv[i], "g", 1) == 0) { visualClass = GrayScale; } else if (strncasecmp(argv[i], "staticc", 7) == 0) { visualClass = StaticColor; } else if (strncasecmp(argv[i], "p", 1) == 0) { visualClass = PseudoColor; } else if (strncasecmp(argv[i], "t", 1) == 0) { visualClass = TrueColor; } else if (strncasecmp(argv[i], "d", 1) == 0) { visualClass = DirectColor; } else { usage(0); exit(1); } } else if (strcmp(argv[i], "-l") == 0 || strcmp(argv[i], "-color-limit") == 0 || strcmp(argv[i], "--color-limit") == 0) { if (++i >= argc) { usage(0); exit(1); } colorLimitop.color_limit = atoi(argv[i]); } else if (strcmp(argv[i], "-L") == 0 || strcmp(argv[i], "-strict-color-limit") == 0 || strcmp(argv[i], "--strict-color-limit") == 0) { colorLimitop.strict = True; } else if (strcmp(argv[i], "-A") == 0 || strcmp(argv[i], "-allocate-palette") == 0 || strcmp(argv[i], "--allocate-palette") == 0) { colorLimitop.allocate = True; } else if (strcmp(argv[i], "-S") == 0 || strcmp(argv[i], "-static-palette") == 0 || strcmp(argv[i], "--static-palette") == 0) { colorLimitop.not_dynamic = True; } else if (strcmp(argv[i], "-P") == 0 || strcmp(argv[i], "-visual-palette") == 0 || strcmp(argv[i], "--visual-palette") == 0) { colorLimitop.use_named_table = True; } else if (strcmp(argv[i], "-V") == 0 || strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "--version") == 0) { printf("%s\n%s\n\n%s\n", Fvwm_VersionInfo, Fvwm_SupportInfo, Fvwm_LicenseInfo); exit(0); } else { usage(0); fprintf(stderr, "invalid option -- %s\n", argv[i]); exit(1); } } DBUG("main", "Done parsing args"); DBUG("main", "Installing signal handlers"); InstallSignals(); if (single_screen_num >= 0) { char *dn = NULL; if (display_name) { dn = display_name; } if (!dn) { dn = getenv("DISPLAY"); } if (!dn) { /* should never happen ? */ if (!(dpy = XOpenDisplay(dn))) { fvwm_msg( ERR, "main", "can't open display %s" "to get the default display", XDisplayName(dn)); } else { dn = XDisplayString(dpy); } } if (dn == NULL) { fvwm_msg( ERR, "main", "couldn't find default display (%s)", XDisplayName(dn)); } else { char *new_dn; new_dn = get_display_name(dn, single_screen_num); if (dpy && strcmp(new_dn, dn) == 0) { /* allready opened */ Pdpy = dpy; } else if (dpy) { XCloseDisplay(dpy); dpy = NULL; } if (!dpy && !(Pdpy = dpy = XOpenDisplay(new_dn))) { fvwm_msg( ERR, "main", "can't open display %s, single screen " "number %d maybe not correct", new_dn, single_screen_num); } Scr.screen = single_screen_num; Scr.NumberOfScreens = ScreenCount(dpy); free(new_dn); } } if (!dpy) { if(!(Pdpy = dpy = XOpenDisplay(display_name))) { fvwm_msg( ERR, "main", "can't open display %s", XDisplayName(display_name)); exit (1); } Scr.screen= DefaultScreen(dpy); Scr.NumberOfScreens = ScreenCount(dpy); } atexit(catch_exit); master_pid = getpid(); if (!do_force_single_screen) { int myscreen = 0; char *new_dn; char *dn; dn = XDisplayString(dpy); for (i=0;i Pdepth) { Pvisual = vinfo[i].visual; Pdepth = vinfo[i].depth; } } if (vinfo) { XFree(vinfo); } /* Detection of a card with 2 hardware colormaps (8+24) which * use depth 8 for the default. We can use our own depth 24 * cmap without affecting other applications. */ if (Pdepth == 0 && DefaultDepth(dpy, Scr.screen) <= 8) { template.class = TrueColor; vinfo = XGetVisualInfo( dpy, VisualScreenMask|VisualClassMask, &template, &total); for(i = 0; i 8) { Pvisual = vinfo[i].visual; Pdepth = vinfo[i].depth; } } if (vinfo) { XFree(vinfo); } } /* have to have a colormap for non-default visual windows */ if (Pdepth > 0) { if (Pvisual->class == DirectColor) { Pcmap = XCreateColormap( dpy, Scr.Root, Pvisual, AllocAll); } else { Pcmap = XCreateColormap( dpy, Scr.Root, Pvisual, AllocNone); } } /* use default visuals if none found so far */ else { Pvisual = DefaultVisual(dpy, Scr.screen); Pdepth = DefaultDepth(dpy, Scr.screen); Pcmap = DefaultColormap(dpy, Scr.screen); Pdefault = True; } } PictureSetupWhiteAndBlack(); /* make a copy of the visual stuff so that XorPixmap can swap with root */ PictureSaveFvwmVisual(); Scr.ColorLimit = 0; PUseDynamicColors = 0; Scr.ColorLimit = PictureInitColors( PICTURE_CALLED_BY_FVWM, True, &colorLimitop, True, True); #ifdef Frsvg_init Frsvg_init(); #endif FShapeInit(dpy); FRenderInit(dpy); Scr.pscreen = XScreenOfDisplay(dpy, Scr.screen); Scr.use_backing_store = DoesBackingStore(Scr.pscreen); Scr.flags.do_save_under = DoesSaveUnders(Scr.pscreen); InternUsefulAtoms(); /* Make sure property priority colors is empty */ XChangeProperty(dpy, Scr.Root, _XA_MIT_PRIORITY_COLORS, XA_CARDINAL, 32, PropModeReplace, NULL, 0); Scr.FvwmCursors = CreateCursors(dpy); XDefineCursor(dpy, Scr.Root, Scr.FvwmCursors[CRS_ROOT]); /* create a window which will accept the keyboard focus when no other * windows have it */ /* do this before any RC parsing as some GC's are created from this * window rather than the root window */ attributes.event_mask = XEVMASK_NOFOCUSW; attributes.override_redirect = True; attributes.colormap = Pcmap; attributes.cursor = Scr.FvwmCursors[CRS_DEFAULT]; attributes.background_pixmap = None; attributes.border_pixel = 0; Scr.NoFocusWin=XCreateWindow( dpy, Scr.Root, -10, -10, 10, 10, 0, Pdepth, InputOutput, Pvisual, CWEventMask | CWOverrideRedirect | CWColormap | CWBackPixmap | CWBorderPixel | CWCursor, &attributes); XMapWindow(dpy, Scr.NoFocusWin); SetMWM_INFO(Scr.NoFocusWin); FOCUS_SET(Scr.NoFocusWin, NULL); frame_init(); XFlush(dpy); if (debugging) { sync_server(1); } SetupICCCM2(replace_wm); XSetIOErrorHandler(CatchFatal); { /* We need to catch any errors of XSelectInput on the root * window here. The event mask contains * SubstructureRedirectMask which can be acquired by exactly * one client (window manager). Synchronizing is necessary * here because Neither XSetErrorHandler nor XSelectInput * generate any protocol requests. */ XSync(dpy, 0); XSetErrorHandler(CatchRedirectError); XSelectInput(dpy, Scr.Root, XEVMASK_ROOTW); XSync(dpy, 0); XSetErrorHandler(FvwmErrorHandler); } { /* do not grab the pointer earlier because if fvwm exits with * the pointer grabbed while a different display is visible, * XFree 4.0 freezes. */ Cursor cursor = XCreateFontCursor(dpy, XC_watch); XGrabPointer( dpy, Scr.Root, 0, 0, GrabModeAsync, GrabModeAsync, None, cursor, CurrentTime); } { Atom atype; int aformat; unsigned long nitems, bytes_remain; unsigned char *prop; if (XGetWindowProperty( dpy, Scr.Root, _XA_WM_DESKTOP, 0L, 1L, True, _XA_WM_DESKTOP, &atype, &aformat, &nitems, &bytes_remain, &prop) == Success) { if (prop != NULL) { Restarting = True; /* do_force_single_screen = True; */ } } } restart_state_filename = safestrdup( CatString3(fvwm_userdir, "/.fs-restart-", getenv("HOSTDISPLAY"))); if (!state_filename && Restarting) { state_filename = restart_state_filename; } /* This should be done early enough to have the window states loaded * before the first call to AddWindow. */ LoadWindowStates(state_filename); InitVariables(); if (visualClass != -1 || visualId != -1) { /* this is so that menus use the (non-default) fvwm colormap */ FW_W(&Scr.FvwmRoot) = Scr.NoFocusWin; Scr.FvwmRoot.number_cmap_windows = 1; Scr.FvwmRoot.cmap_windows = &Scr.NoFocusWin; } InitEventHandlerJumpTable(); Scr.gray_bitmap = XCreateBitmapFromData(dpy,Scr.Root,g_bits, g_width,g_height); EWMH_Init(); DBUG("main", "Setting up rc file defaults..."); SetRCDefaults(); flush_window_updates(); simplify_style_list(); DBUG("main", "Running config_commands..."); ecc.type = Restarting ? EXCT_RESTART : EXCT_INIT; ecc.w.wcontext = C_ROOT; exc = exc_create_context(&ecc, ECC_TYPE | ECC_WCONTEXT); if (num_config_commands > 0) { int i; for (i = 0; i < num_config_commands; i++) { DoingCommandLine = True; execute_function(NULL, exc, config_commands[i], 0); free(config_commands[i]); } DoingCommandLine = False; } else { /* Run startup command file in these places (default prefix): * ~/.fvwm/config * /usr/local/share/fvwm/config * and for compatibility: * ~/.fvwm/.fvwm2rc * /usr/local/share/fvwm/system.fvwm2rc * and for compatibility to be discontinued: * ~/.fvwm2rc, * /usr/local/share/fvwm/.fvwm2rc * /usr/local/etc/system.fvwm2rc */ if ( !run_command_file(CatString3( fvwm_userdir, "/", FVWM_CONFIG), exc) && !run_command_file(CatString3( FVWM_DATADIR, "/", FVWM_CONFIG), exc) && !run_command_file(CatString3( fvwm_userdir, "/", FVWM2RC), exc) && !run_command_file(CatString3( home_dir, "/", FVWM2RC), exc) && !run_command_file(CatString3( FVWM_DATADIR, "/", FVWM2RC), exc) && !run_command_file(CatString3( FVWM_DATADIR, "/system", FVWM2RC), exc) && !run_command_file(CatString3( FVWM_CONFDIR, "/system", FVWM2RC), exc) && !run_command_file(CatString3( FVWM_DATADIR, "/default-config/", "config"), exc)) { fvwm_msg( ERR, "main", "Cannot read startup config file," " tried: \n\t%s/%s\n\t%s/%s\n\t%s/%s\n\t" "%s/%s\n\t%s/%s\n\t%s/system%s\n\t%s/system%s", fvwm_userdir, FVWM_CONFIG, FVWM_DATADIR, FVWM_CONFIG, fvwm_userdir, FVWM2RC, home_dir, FVWM2RC, FVWM_DATADIR, FVWM2RC, FVWM_DATADIR, FVWM2RC, FVWM_CONFDIR, FVWM2RC); } } exc_destroy_context(exc); DBUG("main", "Done running config_commands"); if (Pdepth<2) { Scr.gray_pixmap = XCreatePixmapFromBitmapData( dpy, Scr.NoFocusWin, g_bits, g_width, g_height, PictureBlackPixel(), PictureWhitePixel(), Pdepth); Scr.light_gray_pixmap = XCreatePixmapFromBitmapData( dpy, Scr.NoFocusWin, l_g_bits, l_g_width, l_g_height, PictureBlackPixel(), PictureWhitePixel(), Pdepth); Scr.sticky_gray_pixmap = XCreatePixmapFromBitmapData( dpy, Scr.NoFocusWin, s_g_bits, s_g_width, s_g_height, PictureBlackPixel(), PictureWhitePixel(), Pdepth); } attributes.background_pixel = Scr.StdBack; attributes.colormap = Pcmap; attributes.border_pixel = 0; valuemask = CWBackPixel | CWColormap | CWBorderPixel; Scr.SizeWindow = XCreateWindow( dpy, Scr.Root, 0, 0, 1, 1, 0, Pdepth, InputOutput, Pvisual, valuemask, &attributes); resize_geometry_window(); initPanFrames(); MyXGrabServer(dpy); checkPanFrames(); MyXUngrabServer(dpy); CoerceEnterNotifyOnCurrentWindow(); SessionInit(); DBUG("main", "Entering HandleEvents loop..."); HandleEvents(); switch (fvwmRunState) { case FVWM_DONE: Done(0, NULL); /* does not return */ case FVWM_RESTART: Done(1, ""); /* does not return */ default: DBUG("main", "Unknown fvwm run-state"); } exit(0); } fvwm-2.7.0/fvwm/menuparameters.h0000644000175000017500000000616514147024700013607 00000000000000/* -*-c-*- */ #ifndef MENU_PARAMETERS_H #define MENU_PARAMETERS_H /* ---------------------------- included header files ---------------------- */ /* Do not #include any files - the file including this file has to take care of * it. */ /* ---------------------------- forward declarations ----------------------- */ struct MenuRoot; struct MenuParameters; struct MenuReturn; struct MenuItem; struct FvwmWindow; /* ---------------------------- type definitions --------------------------- */ /* Return values for UpdateMenu, do_menu, menuShortcuts. This is a lame * hack, in that "_BUTTON" is added to mean a button-release caused the * return-- the macros below help deal with the ugliness. */ typedef enum MenuRC { MENU_ERROR = -1, MENU_NOP = 0, MENU_DONE, MENU_ABORTED, MENU_SUBMENU_DONE, MENU_DOUBLE_CLICKED, MENU_POPUP, MENU_POPDOWN, MENU_SELECTED, MENU_NEWITEM, MENU_NEWITEM_MOVEMENU, MENU_NEWITEM_FIND, MENU_POST, MENU_UNPOST, MENU_TEAR_OFF, MENU_SUBMENU_TORN_OFF, MENU_KILL_TEAR_OFF_MENU, MENU_EXEC_CMD, /* propagate the event to a different menu */ MENU_PROPAGATE_EVENT } MenuRC; typedef struct MenuReturn { MenuRC rc; struct MenuRoot *target_menu; struct { unsigned do_unpost_submenu : 1; unsigned is_first_item_selected : 1; unsigned is_key_press : 1; unsigned is_menu_posted : 1; } flags; } MenuReturn; typedef struct MenuPosHints { /* suggested x/y position */ int x; int y; /* additional offset to x */ int x_offset; /* width of the parent menu or item */ int menu_width; /* to take menu width into account (0, -1 or -0.5) */ float x_factor; /* additional offset factor to x */ float context_x_factor; /* same with height */ float y_factor; int screen_origin_x; int screen_origin_y; /* False if referring to absolute screen position */ Bool is_relative; /* True if referring to a part of a menu */ Bool is_menu_relative; Bool has_screen_origin; } MenuPosHints; typedef struct MenuOptions { struct MenuPosHints pos_hints; /* A position on the Xinerama screen on which the menu should be * started. */ struct { unsigned do_not_warp : 1; unsigned do_warp_on_select : 1; unsigned do_warp_title : 1; unsigned do_select_in_place : 1; unsigned do_tear_off_immediately : 1; unsigned has_poshints : 1; unsigned is_fixed : 1; } flags; } MenuOptions; typedef struct MenuParameters { struct MenuRoot *menu; struct MenuRoot *parent_menu; struct MenuItem *parent_item; const exec_context_t **pexc; struct FvwmWindow *tear_off_root_menu_window; char **ret_paction; XEvent *event_propagate_to_submenu; struct MenuOptions *pops; /* A position on the Xinerama screen on which the menu should be * started. */ int screen_origin_x; int screen_origin_y; struct { unsigned has_default_action : 1; unsigned is_already_mapped : 1; unsigned is_first_root_menu : 1; unsigned is_invoked_by_key_press : 1; unsigned is_sticky : 1; unsigned is_submenu : 1; unsigned is_triggered_by_keypress : 1; } flags; } MenuParameters; typedef struct MenuRepaintTransparentParameters { struct MenuRoot *mr; struct FvwmWindow *fw; } MenuRepaintTransparentParameters; #endif /* MENU_PARAMETERS_H */ fvwm-2.7.0/fvwm/read.c0000644000175000017500000001665414147024700011471 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* Changed 09/24/98 by Dan Espen: * - remove logic that processed and saved module configuration commands. * Its now in "modconf.c". */ #include "config.h" #include #ifdef HAVE_FCNTL_H #include #endif #include "libs/Parse.h" #include "libs/Strings.h" #include "fvwm.h" #include "externs.h" #include "cursor.h" #include "functions.h" #include "events.h" #include "misc.h" #include "screen.h" #define MAX_READ_DEPTH 40 static char *curr_read_file = NULL; static char *curr_read_dir = NULL; static int curr_read_depth = 0; static char *prev_read_files[MAX_READ_DEPTH]; static int push_read_file(const char *file) { if (curr_read_depth >= MAX_READ_DEPTH) { fvwm_msg( ERR, "Read", "Nested Read limit %d is reached", MAX_READ_DEPTH); return 0; } prev_read_files[curr_read_depth++] = curr_read_file; curr_read_file = safestrdup(file); if (curr_read_dir) { free(curr_read_dir); } curr_read_dir = NULL; return 1; } static void pop_read_file(void) { if (curr_read_depth == 0) { return; } if (curr_read_file) { free(curr_read_file); } curr_read_file = prev_read_files[--curr_read_depth]; if (curr_read_dir) { free(curr_read_dir); } curr_read_dir = NULL; return; } const char *get_current_read_file(void) { return curr_read_file; } const char *get_current_read_dir(void) { if (!curr_read_dir) { char *dir_end; if (!curr_read_file) { return "."; } /* it should be a library function parse_file_dir() */ dir_end = strrchr(curr_read_file, '/'); if (!dir_end) { dir_end = curr_read_file; } curr_read_dir = safemalloc(dir_end - curr_read_file + 1); strncpy(curr_read_dir, curr_read_file, dir_end - curr_read_file); curr_read_dir[dir_end - curr_read_file] = '\0'; } return curr_read_dir; } /* * Read and execute each line from stream. */ void run_command_stream( cond_rc_t *cond_rc, FILE *f, const exec_context_t *exc) { char *tline; char line[1024]; /* Set close-on-exec flag */ fcntl(fileno(f), F_SETFD, 1); /* Update window decorations in case we were called from a menu that * has now popped down. */ handle_all_expose(); tline = fgets(line, (sizeof line) - 1, f); while (tline) { int l; while (tline && (l = strlen(line)) < sizeof(line) && l >= 2 && line[l-2]=='\\' && line[l-1]=='\n') { tline = fgets(line+l-2,sizeof(line)-l+1,f); } tline=line; while (isspace((unsigned char)*tline)) { tline++; } l = strlen(tline); if (l > 0 && tline[l - 1] == '\n') { tline[l - 1] = '\0'; } execute_function(cond_rc, exc, tline, 0); tline = fgets(line, (sizeof line) - 1, f); } return; } /** * Parse the action string. We expect a filename, and optionally, * the keyword "Quiet". The parameter `cmdname' is used for diagnostic * messages only. * * Returns true if the parse succeeded. * The filename and the presence of the quiet flag are returned * using the pointer arguments. **/ static int parse_filename( char *cmdname, char *action, char **filename, int *quiet_flag) { char *rest; char *option; /* fvwm_msg(INFO,cmdname,"action == '%s'",action); */ /* read file name arg */ rest = GetNextToken(action,filename); if (*filename == NULL) { fvwm_msg(ERR, cmdname, "missing filename parameter"); return 0; } /* optional "Quiet" argument -- flag defaults to `off' (noisy) */ *quiet_flag = 0; rest = GetNextToken(rest,&option); if (option != NULL) { *quiet_flag = strncasecmp(option, "Quiet", 5) == 0; free(option); } return 1; } /** * Returns 0 if file not found **/ int run_command_file( char *filename, const exec_context_t *exc) { char *full_filename; FILE* f = NULL; /* We attempt to open the filename by doing the following: * * - If the file does start with a "/" then it's treated as an * absolute path. * * - Otherwise, it's assumed to be in FVWM_USERDIR OR FVWM_DATADIR, * whichever comes first. * * - If the file starts with "./" or "../" then try and * open the file exactly as specified which means * things like: * * ../.././foo is catered for. At this point, we just try and open * the specified file regardless. * * - *Hidden* files in the CWD would have to be specified as: * * ./.foo */ full_filename = filename; if (full_filename[0] == '/') { /* It's an absolute path */ f = fopen(full_filename,"r"); } else { /* It's a relative path. Check in either FVWM_USERDIR or * FVWM_DATADIR. * */ full_filename = CatString3(fvwm_userdir, "/", filename); if((f = fopen(full_filename, "r")) == NULL) { full_filename = CatString3( FVWM_DATADIR, "/", filename); f = fopen(full_filename, "r"); } } if ((f == NULL) && (f = fopen(filename, "r")) == NULL) { /* We really couldn't open the file. */ return 0; } if (push_read_file(full_filename) == 0) { return 0; } run_command_stream(NULL, f, exc); fclose(f); pop_read_file(); return 1; } /** * Busy Cursor Stuff for Read **/ static void cursor_control(Bool grab) { static int read_depth = 0; static Bool need_ungrab = False; if (!(Scr.BusyCursor & BUSY_READ) && !need_ungrab) { return; } if (grab) { if (!read_depth && GrabEm(CRS_WAIT, GRAB_BUSY)) { need_ungrab = True; } if (need_ungrab) { read_depth++; } } else if (need_ungrab) { read_depth--; if (!read_depth || !(Scr.BusyCursor & BUSY_READ)) { UngrabEm(GRAB_BUSY); need_ungrab = False; read_depth = 0; } } return; } void CMD_Read(F_CMD_ARGS) { char* filename; int read_quietly; DoingCommandLine = False; if (cond_rc != NULL) { cond_rc->rc = COND_RC_OK; } if (!parse_filename("Read", action, &filename, &read_quietly)) { if (cond_rc != NULL) { cond_rc->rc = COND_RC_ERROR; } return; } cursor_control(True); if (!run_command_file(filename, exc)) { if (!read_quietly) { if (filename[0] == '/') { fvwm_msg( ERR, "Read", "file '%s' not found", filename); } else { fvwm_msg( ERR, "Read", "file '%s' not found in %s or " FVWM_DATADIR, filename, fvwm_userdir); } } if (cond_rc != NULL) { cond_rc->rc = COND_RC_ERROR; } } free(filename); cursor_control(False); return; } void CMD_PipeRead(F_CMD_ARGS) { char* command; int read_quietly; FILE* f; DoingCommandLine = False; if (cond_rc != NULL) { cond_rc->rc = COND_RC_OK; } if (!parse_filename("PipeRead", action, &command, &read_quietly)) { if (cond_rc != NULL) { cond_rc->rc = COND_RC_ERROR; } return; } cursor_control(True); f = popen(command, "r"); if (f == NULL) { if (cond_rc != NULL) { cond_rc->rc = COND_RC_ERROR; } if (!read_quietly) { fvwm_msg( ERR, "PipeRead", "command '%s' not run", command); } free(command); cursor_control(False); return; } free(command); run_command_stream(cond_rc,f, exc); pclose(f); cursor_control(False); return; } fvwm-2.7.0/fvwm/cursor.h0000644000175000017500000000326714147024676012110 00000000000000/* -*-c-*- */ #ifndef CURSOR_H #define CURSOR_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ /* Cursor types */ typedef enum { CRS_NONE = 0, CRS_POSITION, /* upper Left corner cursor */ CRS_TITLE, /* title-bar cursor */ CRS_DEFAULT, /* cursor for apps to inherit */ CRS_SYS, /* sys-menu and iconify boxes cursor */ CRS_MOVE, /* move cursor */ CRS_RESIZE, /* resize cursor */ CRS_WAIT, /* wait a while cursor */ CRS_MENU, /* menu cursor */ CRS_SELECT, /* dot cursor for selecting windows */ CRS_DESTROY, /* skull and cross bones */ CRS_TOP, CRS_RIGHT, CRS_BOTTOM, CRS_LEFT, CRS_TOP_LEFT, CRS_TOP_RIGHT, CRS_BOTTOM_LEFT, CRS_BOTTOM_RIGHT, CRS_TOP_EDGE, CRS_RIGHT_EDGE, CRS_BOTTOM_EDGE, CRS_LEFT_EDGE, CRS_ROOT, CRS_STROKE, CRS_MAX } cursor_t; typedef enum { /* busy cursor bits */ BUSY_NONE = 0, BUSY_READ = (1<<0), BUSY_WAIT = (1<<1), BUSY_MODULESYNCHRONOUS = (1<<2), BUSY_DYNAMICMENU = (1<<3), BUSY_ALL = (BUSY_READ|BUSY_WAIT|BUSY_MODULESYNCHRONOUS|BUSY_DYNAMICMENU) } busy_cursor_t; /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ Cursor *CreateCursors(Display *dpy); #endif /* CURSOR_H */ fvwm-2.7.0/fvwm/module_interface.c0000644000175000017500000005307114147024700014055 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* * * code for talking with fvwm modules. * */ #include "config.h" #include #include #include #include "libs/ftime.h" #include "libs/fvwmlib.h" #include "libs/FScreen.h" #include "libs/ColorUtils.h" #include "libs/Parse.h" #include "libs/Strings.h" #include "libs/wild.h" #include "fvwm.h" #include "externs.h" #include "functions.h" #include "bindings.h" #include "misc.h" #include "screen.h" #include "module_interface.h" #include "module_list.h" #include "events.h" #include "geometry.h" #include "libs/fvwmsignal.h" #include "decorations.h" #include "commands.h" /* A queue of commands from the modules */ static fqueue cqueue = FQUEUE_INIT; static const unsigned long dummy = 0; static unsigned long * make_vpacket(unsigned long *body, unsigned long event_type, unsigned long num, va_list ap) { unsigned long *bp = body; /* truncate long packets */ if (num > FvwmPacketMaxSize) { num = FvwmPacketMaxSize; } *(bp++) = START_FLAG; *(bp++) = event_type; *(bp++) = num+FvwmPacketHeaderSize; *(bp++) = fev_get_evtime(); for (; num > 0; --num) { *(bp++) = va_arg(ap, unsigned long); } return body; } /* RBW - 04/16/1999 - new packet builder for GSFR -- Arguments are pairs of lengths and argument data pointers. RBW - 05/01/2000 - A length of zero means that an int is being passed which must be stored in the packet as an unsigned long. This is a special hack to accommodate the old CONFIGARGS technique of sending the args for the M_CONFIGURE_WINDOW packet. */ static unsigned long make_new_vpacket(unsigned char *body, unsigned long event_type, unsigned long num, va_list ap) { long arglen; unsigned long addlen; unsigned long bodylen = 0; unsigned long *bp = (unsigned long *)body; unsigned long *bp1 = bp; unsigned long plen = 0; *(bp++) = START_FLAG; *(bp++) = event_type; /* Skip length field, we don't know it yet. */ bp++; *(bp++) = fev_get_evtime(); for (; num > 0; --num) { arglen = va_arg(ap, long); if (arglen <= 0) { if (arglen == 0) { arglen = -sizeof(int); } addlen = sizeof(unsigned long); } else { addlen = arglen; } bodylen += addlen; if (bodylen >= FvwmPacketMaxSize_byte) { fvwm_msg( ERR, "make_new_vpacket", "packet too long %ld %ld", (long)bodylen, (long)FvwmPacketMaxSize_byte); break; } if (arglen > 0) { register char *tmp = (char *)bp; memcpy(tmp, va_arg(ap, char *), arglen); tmp += arglen; bp = (unsigned long *)tmp; } else if (arglen == 0 || arglen == -sizeof(int)) { int *tmp; tmp = va_arg(ap, int *); *bp = (unsigned long) *tmp; bp++; } else if (arglen == -sizeof(long)) { unsigned long *tmp; tmp = va_arg(ap, unsigned long *); *bp = (unsigned long) *tmp; bp++; } else if (arglen == -sizeof(short)) { short *tmp; tmp = va_arg(ap, short *); *bp = (unsigned long) *tmp; bp++; } else { fvwm_msg( ERR, "make_new_vpacket", "can not handle arglen %ld, please contact" " fvwm-workers@fvwm.org. aborting...", arglen); abort(); } } /* Round up to a long word boundary. Most of the module interface still thinks in terms of an array of longss, so let's humor it. */ plen = (unsigned long) ((char *)bp - (char *)bp1); plen = ((plen + (sizeof(long) - 1)) / sizeof(long)) * sizeof(long); *(((unsigned long*)bp1)+2) = (plen / (sizeof(unsigned long))); return plen; } void SendPacket( fmodule *module, unsigned long event_type, unsigned long num_datum, ...) { unsigned long body[FvwmPacketMaxSize]; va_list ap; va_start(ap, num_datum); make_vpacket(body, event_type, num_datum, ap); va_end(ap); PositiveWrite( module, body, (num_datum+FvwmPacketHeaderSize)*sizeof(body[0])); return; } void BroadcastPacket(unsigned long event_type, unsigned long num_datum, ...) { unsigned long body[FvwmPacketMaxSize]; va_list ap; fmodule_list_itr moditr; fmodule *module; va_start(ap,num_datum); make_vpacket(body, event_type, num_datum, ap); va_end(ap); module_list_itr_init(&moditr); while ( (module = module_list_itr_next(&moditr)) != NULL) { PositiveWrite( module, body, (num_datum+FvwmPacketHeaderSize)*sizeof(body[0])); } return; } /* RBW - 04/16/1999 - new style packet senders for GSFR -- */ static void SendNewPacket( fmodule *module, unsigned long event_type, unsigned long num_datum, ...) { unsigned char body[FvwmPacketMaxSize_byte]; va_list ap; unsigned long plen; va_start(ap,num_datum); plen = make_new_vpacket(body, event_type, num_datum, ap); va_end(ap); PositiveWrite(module, (void *) &body, plen); return; } static void BroadcastNewPacket(unsigned long event_type, unsigned long num_datum, ...) { unsigned char body[FvwmPacketMaxSize_byte]; va_list ap; fmodule_list_itr moditr; fmodule *module; unsigned long plen; va_start(ap,num_datum); plen = make_new_vpacket(body, event_type, num_datum, ap); va_end(ap); module_list_itr_init(&moditr); while ( (module = module_list_itr_next(&moditr)) != NULL) { PositiveWrite(module, (void *) &body, plen); } return; } action_flags *__get_allowed_actions(const FvwmWindow *fw) { static action_flags act; act.is_movable = is_function_allowed( F_MOVE, NULL, fw, RQORIG_PROGRAM_US, False); act.is_deletable = is_function_allowed( F_DELETE, NULL, fw, RQORIG_PROGRAM_US, False); act.is_destroyable = is_function_allowed( F_DESTROY, NULL, fw, RQORIG_PROGRAM_US, False); act.is_closable = is_function_allowed( F_CLOSE, NULL, fw, RQORIG_PROGRAM_US, False); act.is_maximizable = is_function_allowed( F_MAXIMIZE, NULL, fw, RQORIG_PROGRAM_US, False); act.is_resizable = is_function_allowed( F_RESIZE, NULL, fw, RQORIG_PROGRAM_US, False); act.is_iconifiable = is_function_allowed( F_ICONIFY, NULL, fw, RQORIG_PROGRAM_US, False); return &act; } /* RBW - 04/16/1999 - new version for GSFR -- - args are now pairs: - length of arg data - pointer to arg data - number of arguments is the number of length/pointer pairs. - the 9th field, where flags used to be, is temporarily left as a dummy to preserve alignment of the other fields in the old packet: we should drop this before the next release. */ #define CONFIGARGS(_fw) 33, \ (unsigned long)(-sizeof(Window)), \ &FW_W(*(_fw)), \ (unsigned long)(-sizeof(Window)), \ &FW_W_FRAME(*(_fw)), \ (unsigned long)(-sizeof(void *)), \ &(_fw), \ (unsigned long)(0), \ &(*(_fw))->g.frame.x, \ (unsigned long)(0), \ &(*(_fw))->g.frame.y, \ (unsigned long)(0), \ &(*(_fw))->g.frame.width, \ (unsigned long)(0), \ &(*(_fw))->g.frame.height, \ (unsigned long)(0), \ &(*(_fw))->Desk, \ (unsigned long)(0), \ &(*(_fw))->layer, \ (unsigned long)(0), \ &(*(_fw))->hints.base_width, \ (unsigned long)(0), \ &(*(_fw))->hints.base_height, \ (unsigned long)(0), \ &(*(_fw))->hints.width_inc, \ (unsigned long)(0), \ &(*(_fw))->hints.height_inc, \ (unsigned long)(0), \ &(*(_fw))->orig_hints.width_inc, \ (unsigned long)(0), \ &(*(_fw))->orig_hints.height_inc, \ (unsigned long)(0), \ &(*(_fw))->hints.min_width, \ (unsigned long)(0), \ &(*(_fw))->hints.min_height, \ (unsigned long)(0), \ &(*(_fw))->hints.max_width, \ (unsigned long)(0), \ &(*(_fw))->hints.max_height, \ (unsigned long)(-sizeof(Window)), \ &FW_W_ICON_TITLE(*(_fw)), \ (unsigned long)(-sizeof(Window)), \ &FW_W_ICON_PIXMAP(*(_fw)), \ (unsigned long)(0), \ &(*(_fw))->hints.win_gravity, \ (unsigned long)(-sizeof(Pixel)), \ &(*(_fw))->colors.fore, \ (unsigned long)(-sizeof(Pixel)), \ &(*(_fw))->colors.back, \ (unsigned long)(0), \ &(*(_fw))->ewmh_hint_layer, \ (unsigned long)(sizeof(unsigned long)), \ &(*(_fw))->ewmh_hint_desktop, \ (unsigned long)(0), \ &(*(_fw))->ewmh_window_type, \ (unsigned long)(sizeof(short)), \ &(*(_fw))->title_thickness, \ (unsigned long)(sizeof(short)), \ &(*(_fw))->boundary_width, \ (unsigned long)(sizeof(short)), \ &dummy, \ (unsigned long)(sizeof(short)), \ &dummy, \ (unsigned long)(sizeof((*(_fw))->flags)), \ &(*(_fw))->flags, \ (unsigned long)(sizeof(action_flags)), \ __get_allowed_actions((*(_fw))) void SendConfig(fmodule *module, unsigned long event_type, const FvwmWindow *t) { const FvwmWindow **t1 = &t; /* RBW- SendPacket(module, event_type, CONFIGARGS(t)); */ SendNewPacket(module, event_type, CONFIGARGS(t1)); return; } void BroadcastConfig(unsigned long event_type, const FvwmWindow *t) { const FvwmWindow **t1 = &t; /* RBW- BroadcastPacket(event_type, CONFIGARGS(t)); */ BroadcastNewPacket(event_type, CONFIGARGS(t1)); return; } static unsigned long *make_named_packet( int *len, unsigned long event_type, const char *name, int num, ...) { unsigned long *body; va_list ap; /* Packet is the header plus the items plus enough items to hold the * name string. */ *len = FvwmPacketHeaderSize + num + (strlen(name) / sizeof(unsigned long)) + 1; /* truncate long packets */ if (*len > FvwmPacketMaxSize) { *len = FvwmPacketMaxSize; } body = (unsigned long *)safemalloc(*len * sizeof(unsigned long)); /* Zero out end of memory to avoid uninit memory access. */ body[*len-1] = 0; va_start(ap, num); make_vpacket(body, event_type, num, ap); va_end(ap); strncpy((char *)&body[FvwmPacketHeaderSize+num], name, (*len - FvwmPacketHeaderSize - num)*sizeof(unsigned long) - 1); body[2] = *len; return (body); } void SendName( fmodule *module, unsigned long event_type, unsigned long data1,unsigned long data2, unsigned long data3, const char *name) { unsigned long *body; int l; if (name == NULL) { return; } body = make_named_packet(&l, event_type, name, 3, data1, data2, data3); PositiveWrite(module, body, l*sizeof(unsigned long)); free(body); return; } void BroadcastName( unsigned long event_type, unsigned long data1, unsigned long data2, unsigned long data3, const char *name) { unsigned long *body; int l; fmodule_list_itr moditr; fmodule *module; if (name == NULL) { return; } body = make_named_packet(&l, event_type, name, 3, data1, data2, data3); module_list_itr_init(&moditr); while ( (module = module_list_itr_next(&moditr)) != NULL) { PositiveWrite(module, body, l*sizeof(unsigned long)); } free(body); return; } void BroadcastWindowIconNames(FvwmWindow *fw, Bool window, Bool icon) { if (window) { BroadcastName( M_WINDOW_NAME, FW_W(fw), FW_W_FRAME(fw), (unsigned long)fw, fw->name.name); BroadcastName( M_VISIBLE_NAME, FW_W(fw), FW_W_FRAME(fw), (unsigned long)fw, fw->visible_name); } if (icon) { BroadcastName( M_ICON_NAME, FW_W(fw), FW_W_FRAME(fw), (unsigned long)fw, fw->icon_name.name); BroadcastName( MX_VISIBLE_ICON_NAME, FW_W(fw), FW_W_FRAME(fw), (unsigned long)fw, fw->visible_icon_name); } return; } void SendFvwmPicture( fmodule *module, unsigned long event_type, unsigned long data1, unsigned long data2, unsigned long data3, FvwmPicture *picture, char *name) { unsigned long *body; unsigned long data4 = 0, data5 = 0, data6 = 0, data7 = 0, data8 = 0, data9 = 0; int l; if (!FMiniIconsSupported) { return; } if ((name == NULL) || (event_type != M_MINI_ICON)) { return; } if (picture != NULL) { data4 = picture->width; data5 = picture->height; data6 = picture->depth; data7 = picture->picture; data8 = picture->mask; data9 = picture->alpha; } body = make_named_packet( &l, event_type, name, 9, data1, data2, data3, data4, data5, data6, data7, data8, data9); PositiveWrite(module, body, l*sizeof(unsigned long)); free(body); return; } void BroadcastFvwmPicture( unsigned long event_type, unsigned long data1, unsigned long data2, unsigned long data3, FvwmPicture *picture, char *name) { unsigned long *body; unsigned long data4, data5, data6, data7, data8, data9; int l; fmodule_list_itr moditr; fmodule *module; if (!FMiniIconsSupported) { return; } if (picture != NULL) { data4 = picture->width; data5 = picture->height; data6 = picture->depth; data7 = picture->picture; data8 = picture->mask; data9 = picture->alpha; } else { data4 = 0; data5 = 0; data6 = 0; data7 = 0; data8 = 0; data9 = 0; } body = make_named_packet( &l, event_type, name, 9, data1, data2, data3, data4, data5, data6, data7, data8, data9); module_list_itr_init(&moditr); while ( (module = module_list_itr_next(&moditr)) != NULL) { PositiveWrite(module, body, l*sizeof(unsigned long)); } free(body); return; } /* * Reads a colorset command from a module and broadcasts it back out */ void BroadcastColorset(int n) { fmodule_list_itr moditr; fmodule *module; char *buf; buf = DumpColorset(n, &Colorset[n]); module_list_itr_init(&moditr); while ( (module = module_list_itr_next(&moditr)) != NULL) { SendName(module, M_CONFIG_INFO, 0, 0, 0, buf); } return; } /* * Broadcasts a string to all modules as M_CONFIG_INFO. */ void BroadcastPropertyChange( unsigned long argument, unsigned long data1, unsigned long data2, char *string) { fmodule_list_itr moditr; fmodule *module; module_list_itr_init(&moditr); while ( (module = module_list_itr_next(&moditr)) != NULL) { SendName(module, MX_PROPERTY_CHANGE, argument, data1, data2, string); } return; } /* * Broadcasts a string to all modules as M_CONFIG_INFO. */ void BroadcastConfigInfoString(char *string) { fmodule_list_itr moditr; fmodule *module; module_list_itr_init(&moditr); while ( (module = module_list_itr_next(&moditr)) != NULL) { SendName(module, M_CONFIG_INFO, 0, 0, 0, string); } return; } /* * Broadcasts the state of Xinerama support to all modules as M_CONFIG_INFO. */ void broadcast_xinerama_state(void) { BroadcastConfigInfoString((char *)FScreenGetConfiguration()); return; } /* * Broadcasts the ignored modifiers to all modules as M_CONFIG_INFO. */ void broadcast_ignore_modifiers(void) { char msg[32]; sprintf(msg, "IgnoreModifiers %d", GetUnusedModifiers()); BroadcastConfigInfoString(msg); return; } /* run the input command as if it cames from a button press or release */ void module_input_execute(struct fmodule_input *input) { XEvent e; const exec_context_t *exc; exec_context_changes_t ecc; int flags; memset(&e, 0, sizeof(e)); if (XFindContext(dpy, input->window, FvwmContext, (caddr_t *)&ecc.w.fw) == XCNOENT) { ecc.w.fw = NULL; input->window = None; } /* Query the pointer, the pager-drag-out feature doesn't work properly. * This is OK now that the Pager uses "Move pointer" * A real fix would be for the modules to pass the button press coords */ if (FQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, &JunkX,&JunkY, &e.xbutton.x_root, &e.xbutton.y_root, &e.xbutton.state) == False) { /* pointer is not on this screen */ /* If a module does XUngrabPointer(), it can now get proper * Popups */ e.xbutton.window = Scr.Root; ecc.w.fw = NULL; } else { e.xbutton.window = input->window; } e.xbutton.subwindow = None; e.xbutton.button = 1; /* If a module does XUngrabPointer(), it can now get proper Popups */ if (StrEquals(input->command, "popup")) { e.xbutton.type = ButtonPress; e.xbutton.state |= Button1Mask; } else { e.xbutton.type = ButtonRelease; e.xbutton.state &= (~(Button1Mask)); } e.xbutton.x = 0; e.xbutton.y = 0; fev_fake_event(&e); ecc.type = EXCT_MODULE; ecc.w.w = input->window; flags = (input->window == None) ? 0 : FUNC_DONT_DEFER; ecc.w.wcontext = GetContext(NULL, ecc.w.fw, &e, &(input->window)); ecc.x.etrigger = &e; ecc.m.module = input->module; exc = exc_create_context( &ecc, ECC_TYPE | ECC_ETRIGGER | ECC_FW | ECC_W | ECC_WCONTEXT | ECC_MODULE); execute_function(NULL, exc, input->command, flags); exc_destroy_context(exc); module_input_discard(input); return; } /* enqueue a module command on the command queue to be executed later */ void module_input_enqueue(struct fmodule_input *input) { if (input == NULL) { return; } DBUG("module_input_enqueue", input->command); fqueue_add_at_end(&cqueue, (void*)input); } /* * * Procedure: * ExecuteCommandQueue - runs command from the module command queue * This may be called recursively if a module command runs a function * that does a Wait, so it must be re-entrant * */ void ExecuteCommandQueue(void) { fmodule_input *input; while (fqueue_get_first(&cqueue, (void **)&input) == 1) { /* remove from queue */ fqueue_remove_or_operate_from_front( &cqueue, NULL, NULL, NULL, NULL); /* execute and destroy */ if (input->command) { DBUG("ExecuteCommandQueue", input->command); module_input_execute(input); } else { module_input_discard(input); } } return; } /* ** send an arbitrary string to all instances of a module */ void CMD_SendToModule(F_CMD_ARGS) { char *name,*str; unsigned long data0, data1, data2; fmodule_list_itr moditr; fmodule *module; FvwmWindow * const fw = exc->w.fw; /* FIXME: Without this, popup menus can't be implemented properly in * modules. Olivier: Why ? */ /* UngrabEm(); */ if (!action) { return; } str = GetNextToken(action, &name); if (!name) { return; } if (fw) { /* Modules may need to know which window this applies to */ data0 = FW_W(fw); data1 = FW_W_FRAME(fw); data2 = (unsigned long)fw; } else { data0 = 0; data1 = 0; data2 = 0; } module_list_itr_init(&moditr); while ( (module = module_list_itr_next(&moditr)) != NULL) { if ( (MOD_NAME(module) != NULL && matchWildcards(name,MOD_NAME(module))) || (MOD_ALIAS(module) && matchWildcards(name, MOD_ALIAS(module)))) { SendName(module,M_STRING,data0,data1,data2,str); FlushMessageQueue(module); } } free(name); return; } /* ** send an arbitrary string back to the calling module */ void CMD_Send_Reply(F_CMD_ARGS) { unsigned long data0, data1, data2; fmodule *module = exc->m.module; FvwmWindow * const fw = exc->w.fw; if (module == NULL) { return; } if (!action) { return; } if (fw) { /* Modules may need to know which window this applies to */ data0 = FW_W(fw); data1 = FW_W_FRAME(fw); data2 = (unsigned long)fw; } else { data0 = 0; data1 = 0; data2 = 0; } SendName(module, MX_REPLY, data0, data1, data2, action); FlushMessageQueue(module); return; } void CMD_Send_WindowList(F_CMD_ARGS) { FvwmWindow *t; fmodule *mod = exc->m.module; if (mod == NULL) { return; } SendPacket(mod, M_NEW_DESK, 1, (long)Scr.CurrentDesk); SendPacket( mod, M_NEW_PAGE, 7, (long)Scr.Vx, (long)Scr.Vy, (long)Scr.CurrentDesk, (long)Scr.MyDisplayWidth, (long)Scr.MyDisplayHeight, (long)((Scr.VxMax / Scr.MyDisplayWidth) + 1), (long)((Scr.VyMax / Scr.MyDisplayHeight) + 1)); if (Scr.Hilite != NULL) { SendPacket( mod, M_FOCUS_CHANGE, 5, (long)FW_W(Scr.Hilite), (long)FW_W_FRAME(Scr.Hilite), (unsigned long)True, (long)Scr.Hilite->hicolors.fore, (long)Scr.Hilite->hicolors.back); } else { SendPacket( mod, M_FOCUS_CHANGE, 5, 0, 0, (unsigned long)True, (long)GetColor(DEFAULT_FORE_COLOR), (long)GetColor(DEFAULT_BACK_COLOR)); } if (Scr.DefaultIcon != NULL) { SendName(mod, M_DEFAULTICON, 0, 0, 0, Scr.DefaultIcon); } for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) { SendConfig(mod,M_CONFIGURE_WINDOW,t); SendName( mod, M_WINDOW_NAME, FW_W(t), FW_W_FRAME(t), (unsigned long)t, t->name.name); SendName( mod, M_ICON_NAME, FW_W(t), FW_W_FRAME(t), (unsigned long)t, t->icon_name.name); SendName( mod, M_VISIBLE_NAME, FW_W(t), FW_W_FRAME(t), (unsigned long)t, t->visible_name); SendName( mod, MX_VISIBLE_ICON_NAME, FW_W(t), FW_W_FRAME(t), (unsigned long)t,t->visible_icon_name); if (t->icon_bitmap_file != NULL && t->icon_bitmap_file != Scr.DefaultIcon) { SendName( mod, M_ICON_FILE, FW_W(t), FW_W_FRAME(t), (unsigned long)t, t->icon_bitmap_file); } SendName( mod, M_RES_CLASS, FW_W(t), FW_W_FRAME(t), (unsigned long)t, t->class.res_class); SendName( mod, M_RES_NAME, FW_W(t), FW_W_FRAME(t), (unsigned long)t, t->class.res_name); if (IS_ICONIFIED(t) && !IS_ICON_UNMAPPED(t)) { rectangle r; Bool rc; rc = get_visible_icon_geometry(t, &r); if (rc == True) { SendPacket( mod, M_ICONIFY, 7, (long)FW_W(t), (long)FW_W_FRAME(t), (unsigned long)t, (long)r.x, (long)r.y, (long)r.width, (long)r.height); } } if ((IS_ICONIFIED(t))&&(IS_ICON_UNMAPPED(t))) { SendPacket( mod, M_ICONIFY, 7, (long)FW_W(t), (long)FW_W_FRAME(t), (unsigned long)t, (long)0, (long)0, (long)0, (long)0); } if (FMiniIconsSupported && t->mini_icon != NULL) { SendFvwmPicture( mod, M_MINI_ICON, FW_W(t), FW_W_FRAME(t), (unsigned long)t, t->mini_icon, t->mini_pixmap_file); } } if (Scr.Hilite == NULL) { BroadcastPacket( M_FOCUS_CHANGE, 5, (long)0, (long)0, (unsigned long)True, (long)GetColor(DEFAULT_FORE_COLOR), (long)GetColor(DEFAULT_BACK_COLOR)); } else { BroadcastPacket( M_FOCUS_CHANGE, 5, (long)FW_W(Scr.Hilite), (long)FW_W(Scr.Hilite), (unsigned long)True, (long)Scr.Hilite->hicolors.fore, (long)Scr.Hilite->hicolors.back); } SendPacket(mod, M_END_WINDOWLIST, 0); return; } fvwm-2.7.0/fvwm/ewmh.h0000644000175000017500000000476214147024700011520 00000000000000/* -*-c-*- */ /* Copyright (C) 2001 Olivier Chapuis */ #ifndef _EWMH_ #define _EWMH_ /* Extended window manager hints support */ /* ewmh_conf.c */ Bool EWMH_BugOpts(char *opt, Bool toggle); void CMD_EwmhNumberOfDesktops(F_CMD_ARGS); void CMD_EwmhBaseStrut(F_CMD_ARGS); Bool EWMH_CMD_Style(char *token, window_style *ptmpstyle, int on); /* for maximize and placement ewmh style */ #define EWMH_IGNORE_WORKING_AREA 0 #define EWMH_USE_WORKING_AREA 1 #define EWMH_USE_DYNAMIC_WORKING_AREA 2 #define EWMH_WORKING_AREA_MASK 3 /* Extended window manager hints support */ #include void EWMH_SetCurrentDesktop(void); void EWMH_SetNumberOfDesktops(void); void EWMH_SetDesktopViewPort(void); void EWMH_SetDesktopGeometry(void); void EWMH_SetActiveWindow(Window w); void EWMH_SetWMDesktop(FvwmWindow *fw); void EWMH_SetWMState(FvwmWindow *fw, Bool do_restore); int EWMH_IsKdeSysTrayWindow(Window w); void EWMH_ManageKdeSysTray(Window w, int type); void EWMH_SetClientList(void); void EWMH_SetClientListStacking(void); void EWMH_UpdateWorkArea(void); void EWMH_GetWorkAreaIntersection( FvwmWindow *fw, int *x, int *y, int *w, int *h, int type); float EWMH_GetBaseStrutIntersection( int x11, int y11, int x12, int y12, Bool use_percent); float EWMH_GetStrutIntersection( int x11, int y11, int x12, int y12, Bool use_percent); void EWMH_SetFrameStrut(FvwmWindow *fw); void EWMH_SetAllowedActions(FvwmWindow *fw); void EWMH_GetIconGeometry(FvwmWindow *fw, rectangle *icon_rect); void EWMH_GetStyle(FvwmWindow *fw, window_style *style); void EWMH_WindowInit(FvwmWindow *fw); void EWMH_RestoreInitialStates(FvwmWindow *fw, int event_type); void EWMH_DestroyWindow(FvwmWindow *fw); void EWMH_WindowDestroyed(void); void EWMH_Init(void); void EWMH_ExitStuff(void); /* ewmh_conf.c */ /* ewmh_events.c */ Bool EWMH_ProcessClientMessage(const exec_context_t *exc); void EWMH_ProcessPropertyNotify(const exec_context_t *exc); /* ewmh_icon.c */ void EWMH_DeleteWmIcon(FvwmWindow *fw, Bool mini_icon, Bool icon); int EWMH_SetIconFromWMIcon( FvwmWindow *fw, CARD32 *list, int size, Bool is_mini_icon); void EWMH_DoUpdateWmIcon(FvwmWindow *fw, Bool mini_icon, Bool icon); /* ewmh_name.c */ void EWMH_SetVisibleName(FvwmWindow *fw, Bool is_icon_name); int EWMH_WMName( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); int EWMH_WMIconName( FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any); void EWMH_SetDesktopNames(void); void EWMH_fullscreen(FvwmWindow *fw); #endif /* _EWMH_ */ fvwm-2.7.0/fvwm/screen.h0000644000175000017500000003361214147024700012033 00000000000000/* -*-c-*- */ /* This module is based on Twm, but has been siginificantly modified * by Rob Nation */ /* Copyright 1989 Massachusetts Institute of Technology * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of M.I.T. not be used in advertising * or publicity pertaining to distribution of the software without specific, * written prior permission. M.I.T. makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T. * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * * fvwm per-screen data include file * */ #ifndef _SCREEN_ #define _SCREEN_ #include "libs/flist.h" #include "libs/Bindings.h" #define SIZE_HINDENT 5 #define SIZE_VINDENT 3 /* colormap focus styes */ #define COLORMAP_FOLLOWS_MOUSE 1 /* default */ #define COLORMAP_FOLLOWS_FOCUS 2 /* title bar multi pixmap parts */ /* those which can be used as UseTitleStyle should be enum first */ typedef enum { TBMP_NONE = -1, TBMP_MAIN, TBMP_LEFT_MAIN, TBMP_RIGHT_MAIN, TBMP_LEFT_BUTTONS, TBMP_RIGHT_BUTTONS, TBMP_UNDER_TEXT, TBMP_LEFT_OF_TEXT, TBMP_RIGHT_OF_TEXT, TBMP_LEFT_END, TBMP_RIGHT_END, TBMP_BUTTONS, TBMP_NUM_PIXMAPS } TbmpParts; /* title bar multi pixmap parts which can be use for UseTitleStyle */ typedef enum { UTS_TBMP_NONE = -1, UTS_TBMP_MAIN, UTS_TBMP_LEFT_MAIN, UTS_TBMP_RIGHT_MAIN, UTS_TBMP_LEFT_BUTTONS, UTS_TBMP_RIGHT_BUTTONS, UTS_TBMP_NUM_PIXMAPS } UtsTbmpParts; typedef struct { int cs; int alpha_percent; } FvwmAcs; typedef struct { Window win; int isMapped; /* command which is executed when the pan frame is entered */ char *command; /* command which is executed when the pan frame is left*/ char *command_leave; } PanFrame; typedef enum { /* button types */ DefaultVectorButton, VectorButton, SimpleButton, GradientButton, PixmapButton, TiledPixmapButton, StretchedPixmapButton, AdjustedPixmapButton, ShrunkPixmapButton, MultiPixmap, MiniIconButton, SolidButton, ColorsetButton } DecorFaceType; typedef enum { JUST_CENTER = 0, JUST_LEFT = 1, JUST_TOP = 1, JUST_RIGHT = 2, JUST_BOTTOM = 2, JUST_MASK = 3 } JustificationType; typedef struct { unsigned face_type : 4; struct { unsigned h_justification : 2; unsigned v_justification : 2; #define DFS_BUTTON_IS_UP 0 #define DFS_BUTTON_IS_FLAT 1 #define DFS_BUTTON_IS_SUNK 2 #define DFS_BUTTON_MASK 3 unsigned int button_relief : 2; /* not used in border styles */ unsigned int use_title_style : 1; unsigned int use_border_style : 1; /* only used in border styles */ unsigned int has_hidden_handles : 1; unsigned int has_no_inset : 1; } flags; } DecorFaceStyle; #define DFS_FACE_TYPE(dfs) ((dfs).face_type) #define DFS_FLAGS(dfs) ((dfs).flags) #define DFS_H_JUSTIFICATION(dfs) ((dfs).flags.h_justification) #define DFS_V_JUSTIFICATION(dfs) ((dfs).flags.v_justification) #define DFS_BUTTON_RELIEF(dfs) ((dfs).flags.button_relief) #define DFS_USE_TITLE_STYLE(dfs) ((dfs).flags.use_title_style) #define DFS_USE_BORDER_STYLE(dfs) ((dfs).flags.use_border_style) #define DFS_HAS_HIDDEN_HANDLES(dfs) ((dfs).flags.has_hidden_handles) #define DFS_HAS_NO_INSET(dfs) ((dfs).flags.has_no_inset) typedef struct DecorFace { DecorFaceStyle style; struct { FvwmPicture *p; struct { FvwmPicture **pixmaps; unsigned short stretch_flags; FvwmAcs *acs; Pixel *pixels; unsigned short solid_flags; } mp; struct { int cs; int alpha_percent; } acs; Pixel back; struct { int npixels; XColor *xcs; int do_dither; Pixel *d_pixels; int d_npixels; char gradient_type; } grad; struct vector_coords { int num; signed char *x; signed char *y; signed char *xoff; signed char *yoff; signed char *c; unsigned use_fgbg : 1; } vector; } u; struct DecorFace *next; struct { unsigned has_changed : 1; } flags; } DecorFace; typedef enum { BS_All = -1, BS_ActiveUp, BS_ActiveDown, BS_InactiveUp, BS_InactiveDown, BS_ToggledActiveUp, BS_ToggledActiveDown, BS_ToggledInactiveUp, BS_ToggledInactiveDown, BS_MaxButtonState, BS_MaxButtonStateMask = BS_MaxButtonState - 1, BS_Active, BS_Inactive, BS_ToggledActive, BS_ToggledInactive, BS_AllNormal, BS_AllToggled, BS_AllActive, BS_AllInactive, BS_AllUp, BS_AllDown, BS_AllActiveUp, BS_AllActiveDown, BS_AllInactiveUp, BS_AllInactiveDown, BS_MaxButtonStateName } ButtonState; #define BS_MASK_DOWN (1 << 0) #define BS_MASK_INACTIVE (1 << 1) #define BS_MASK_TOGGLED (1 << 2) typedef enum { /* The first five are used in title buttons. These can't be * renumbered without extending the mwm_decor_flags member below and * adapting the style structure. */ MWM_DECOR_MENU = 0x1, MWM_DECOR_MINIMIZE = 0x2, MWM_DECOR_MAXIMIZE = 0x4, MWM_DECOR_SHADE = 0x8, MWM_DECOR_STICK = 0x10, /* --- */ MWM_DECOR_BORDER = 0x20, MWM_DECOR_RESIZEH = 0x40, MWM_DECOR_TITLE = 0x80, MWM_DECOR_ALL = 0x100, MWM_DECOR_EVERYTHING = 0xff } mwm_flags; typedef struct { unsigned just : 2; /* was JustificationType : 2 */ int layer; struct { unsigned has_changed : 1; mwm_flags mwm_decor_flags : 9; /* Support {ButtonStyle - Layer 4} construction, so * button can be rendered 'pressed in' when the window is * assigned to a particular layer. */ unsigned has_layer : 1; } flags; DecorFace state[BS_MaxButtonState]; } TitleButton; #define TB_FLAGS(tb) ((tb).flags) #define TB_STATE(tb) ((tb).state) #define TB_JUSTIFICATION(tb) ((tb).just) #define TB_LAYER(tb) ((tb).layer) #define TB_MWM_DECOR_FLAGS(tb) ((tb).flags.mwm_decor_flags) #define TB_HAS_CHANGED(tb) \ (!!((tb).flags.has_changed)) #define TB_HAS_MWM_DECOR_MENU(tb) \ (!!((tb).flags.mwm_decor_flags & MWM_DECOR_MENU)) #define TB_HAS_MWM_DECOR_MINIMIZE(tb) \ (!!((tb).flags.mwm_decor_flags & MWM_DECOR_MINIMIZE)) #define TB_HAS_MWM_DECOR_MAXIMIZE(tb) \ (!!((tb).flags.mwm_decor_flags & MWM_DECOR_MAXIMIZE)) #define TB_HAS_MWM_DECOR_SHADE(tb) \ (!!((tb).flags.mwm_decor_flags & MWM_DECOR_SHADE)) #define TB_HAS_MWM_DECOR_STICK(tb) \ (!!((tb).flags.mwm_decor_flags & MWM_DECOR_STICK)) typedef struct FvwmDecor { char *tag; /* general style tag */ int title_height; /* explicitly specified title bar height */ int min_title_height; /* titlebar buttons */ TitleButton buttons[NUMBER_OF_TITLE_BUTTONS]; TitleButton titlebar; struct BorderStyle { DecorFace active, inactive; } BorderStyle; struct FvwmDecor *next; /* additional user-defined styles */ struct { unsigned has_changed : 1; unsigned has_title_height_changed : 1; } flags; } FvwmDecor; typedef struct DesktopsInfo { int desk; char *name; struct { int x; int y; int width; int height; } ewmh_working_area; struct { int x; int y; int width; int height; } ewmh_dyn_working_area; struct DesktopsInfo *next; } DesktopsInfo; typedef struct ScreenInfo { unsigned long screen; Screen *pscreen; /* number of screens on display */ int NumberOfScreens; /* my copy of DisplayWidth(dpy, screen) */ int MyDisplayWidth; /* my copy of DisplayHeight(dpy, screen) */ int MyDisplayHeight; /* the head of the fvwm window list */ FvwmWindow FvwmRoot; /* the root window */ Window Root; /* the resize dimensions window */ Window SizeWindow; /* Window which will own focus when no other windows have it */ Window NoFocusWin; flist *FWScheduledForDestroy; PanFrame PanFrameTop; PanFrame PanFrameLeft; PanFrame PanFrameRight; PanFrame PanFrameBottom; /*dark gray pattern for shaded out menu items*/ Pixmap gray_bitmap; /* dark gray pattern for inactive borders */ Pixmap gray_pixmap; /* light gray pattern for inactive borders */ Pixmap light_gray_pixmap; /* light gray pattern for sticky borders */ Pixmap sticky_gray_pixmap; Binding *AllBindings; /* current push level to install root colormap windows */ int root_pushes; /* current push level to install fvwm colormap windows */ int fvwm_pushes; /* saved window to install when pushes drops to zero */ const FvwmWindow *pushed_window; Cursor *FvwmCursors; /* context where we display the busy cursor */ int BusyCursor; /* Icon to use when no other icons are found */ char *DefaultIcon; int TopLayer; int DefaultLayer; int BottomLayer; struct FvwmFunction *functions; /* font structure */ FlocaleFont *DefaultFont; /* GC for transparency masks */ GC TransMaskGC; /* don't change the order */ Pixel StdFore, StdBack, StdHilite, StdShadow; GC StdGC; GC StdReliefGC; GC StdShadowGC; /* A scratch 1x1x1 pixmap */ Pixmap ScratchMonoPixmap; /* GC for drawing into depth 1 drawables */ GC MonoGC; /* A scratch 1x1xalpha_depth pixmap */ Pixmap ScratchAlphaPixmap; /* GC for drawing into depth alpha_depth drawables */ GC AlphaGC; /* GC to draw lines for move and resize */ GC XorGC; GC ScratchGC1; GC ScratchGC2; GC ScratchGC3; GC ScratchGC4; GC TitleGC; GC BordersGC; /* minimum width of size window */ int SizeStringWidth; /* decoration style(s) */ FvwmDecor DefaultDecor; FvwmDecor *cur_decor; /* number of left-side title-bar buttons */ int nr_left_buttons; /* number of right-side title-bar buttons */ int nr_right_buttons; /* the fvwm window that is highlighted except for networking delays, * this is the window which REALLY has the focus */ FvwmWindow *Hilite; /* None, if the focus is nowhere or on an fvwm managed window. Set to * id of otherwindow with focus otherwise */ Window UnknownWinFocused; /* The window that the UnknownWinFocused window stole the focus from. */ Window StolenFocusWin; FvwmWindow *StolenFocusFvwmWin; FvwmWindow *focus_in_pending_window; FvwmWindow *focus_in_requested_window; /* #pixels to scroll on screen edge */ int EdgeScrollX; /* #pixels to scroll on screen edge */ int EdgeScrollY; /* buttons to grab in click to focus mode */ unsigned short buttons2grab; int NumBoxes; /* values used for CascadePlacement */ int cascade_x; int cascade_y; FvwmWindow *cascade_window; /* Max location for top left of virt desk*/ int VxMax; int VyMax; /* Current loc for top left of virt desk */ int Vx; int Vy; /*Max button-click delay for Function built-in*/ int ClickTime; /* resistance to scrolling in desktop */ int ScrollDelay; int MoveThreshold; int OpaqueSize; /* The current desktop number */ int CurrentDesk; /* colormap focus style */ int ColormapFocus; /* Limit on colors used in pixmaps */ int ColorLimit; /* Default Colorset used by feedback window */ int DefaultColorset; int use_backing_store; /* some additional global options which will probably become window * specific options later on: */ struct { unsigned do_debug_cr_motion_method : 1; unsigned do_disable_configure_notify : 1; unsigned do_display_new_window_names : 1; unsigned do_enable_ewmh_iconic_state_workaround : 1; unsigned do_enable_flickering_qt_dialogs_workaround : 1; unsigned do_enable_qt_drag_n_drop_workaround : 1; unsigned do_explain_window_placement : 1; unsigned do_install_root_cmap : 1; unsigned do_raise_over_unmanaged : 1; unsigned is_modality_evil : 1; unsigned is_raise_hack_needed : 1; } bo; /* bug workaround control options */ struct { unsigned do_emulate_mwm : 1; unsigned do_emulate_win : 1; unsigned do_hide_position_window : 1; unsigned do_hide_resize_window : 1; unsigned use_active_down_buttons : 1; unsigned use_inactive_buttons : 1; unsigned use_inactive_down_buttons : 1; } gs; /* global style structure */ struct { unsigned are_functions_silent : 1; unsigned are_windows_captured : 1; unsigned do_edge_wrap_x : 1; unsigned do_edge_wrap_y : 1; unsigned do_need_style_list_update : 1; unsigned do_need_window_update : 1; unsigned do_save_under : 1; unsigned has_default_color_changed : 1; unsigned has_default_font_changed : 1; unsigned has_mouse_binding_changed : 1; unsigned has_nr_buttons_changed : 1; unsigned has_xinerama_state_changed : 1; unsigned is_executing_complex_function : 1; unsigned is_executing_menu_function : 1; unsigned is_map_desk_in_progress : 1; unsigned is_pointer_on_this_screen : 1; unsigned is_single_screen : 1; unsigned is_window_scheduled_for_destroy : 1; unsigned is_wire_frame_displayed : 1; } flags; /* info for some desktops; the first entries should be generic info * correct for any desktop not in the list */ DesktopsInfo *Desktops; /* the window of desktop type if any */ FvwmWindow *EwmhDesktop; struct { last_added_item_t type; void *item; } last_added_item; } ScreenInfo; /* A macro to to simplify he "ewmh desktop code" */ #define IS_EWMH_DESKTOP(win) \ (Scr.EwmhDesktop && win == Scr.EwmhDesktop->wins.client) #define IS_EWMH_DESKTOP_FW(fwin) \ (fwin && Scr.EwmhDesktop && Scr.EwmhDesktop == fwin) /* Macro which gets specific decor or default decor. * This saves an indirection in case you don't want * the UseDecor mechanism. */ #define GetDecor(window,part) ((window)->decor->part) /* some protos for the decoration structures */ void LoadDefaultButton(DecorFace *bf, int i); void ResetAllButtons(FvwmDecor *decor); void DestroyAllButtons(FvwmDecor *decor); void simplify_style_list(void); /* * Diverts a style definition to an FvwmDecor structure (veliaa@rpi.edu) */ void AddToDecor(F_CMD_ARGS, FvwmDecor *decor); extern ScreenInfo Scr; #endif /* _SCREEN_ */ fvwm-2.7.0/fvwm/menus.c0000644000175000017500000053135714147024700011707 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* IMPORTANT NOTE: Do *not* use any constant numbers in this file. All values * have to be #defined in the section below or in defaults.h to ensure full * control over the menus. */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include #include "libs/ftime.h" #include "libs/fvwmlib.h" #include "libs/FScreen.h" #include "libs/Grab.h" #include "libs/Parse.h" #include "libs/ColorUtils.h" #include "libs/Picture.h" #include "libs/PictureUtils.h" #include "libs/Graphics.h" #include "libs/PictureGraphics.h" #include "libs/charmap.h" #include "libs/wcontext.h" #include "fvwm.h" #include "externs.h" #include "execcontext.h" #include "events.h" #include "eventhandler.h" #include "eventmask.h" #include "cursor.h" #include "functions.h" #include "commands.h" #include "misc.h" #include "screen.h" #include "colormaps.h" #include "geometry.h" #include "move_resize.h" #include "menudim.h" #include "menuitem.h" #include "menuroot.h" #include "menustyle.h" #include "bindings.h" #include "menubindings.h" #include "menugeometry.h" #include "menuparameters.h" #include "menus.h" #include "libs/FGettext.h" /* ---------------------------- local definitions -------------------------- */ /* used in float to int arithmetic */ #define ROUNDING_ERROR_TOLERANCE 0.005 /* ---------------------------- local macros ------------------------------- */ #define SCTX_SET_MI(ctx,item) ((ctx).type = SCTX_MENU_ITEM, \ (ctx).menu_item.menu_item = (item)) #define SCTX_GET_MI(ctx) ((ctx).type == SCTX_MENU_ITEM ? \ (ctx).menu_item.menu_item : NULL) #define SCTX_SET_MR(ctx,root) ((ctx).type = SCTX_MENU_ROOT, \ (ctx).menu_root.menu_root = (root)) #define SCTX_GET_MR(ctx) ((ctx).type == SCTX_MENU_ROOT ? \ (ctx).menu_root.menu_root : NULL) /* ---------------------------- imports ------------------------------------ */ /* This external is safe. It's written only during startup. */ extern XContext MenuContext; /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* patch to pass the last popups position hints to popup_func */ typedef struct { struct { unsigned is_last_menu_pos_hints_valid : 1; unsigned do_ignore_pos_hints : 1; unsigned do_warp_title : 1; } flags; struct MenuPosHints pos_hints; } saved_pos_hints; typedef struct MenuInfo { MenuRoot *all; int n_destroyed_menus; } MenuInfo; typedef struct MenuSizingParameters { MenuRoot *menu; /* number of item labels present in the item format */ int used_item_labels; /* same for mini icons */ int used_mini_icons; struct { int sidepic_width; MenuItemPartSizesT i; } max; struct { unsigned is_popup_indicator_used : 1; } flags; } MenuSizingParameters; typedef enum { SCTX_MENU_ROOT, SCTX_MENU_ITEM } string_context_type_t; typedef union { string_context_type_t type; struct { string_context_type_t type; MenuRoot *menu_root; } menu_root; struct { string_context_type_t type; MenuItem *menu_item; } menu_item; } string_context_t; typedef struct { char delimiter; Bool (*string_handler)( char *string, char delimiter, string_context_t *user_data); } string_def_t; /* ---------------------------- menu loop types ---------------------------- */ typedef enum { MENU_MLOOP_RET_NORMAL, MENU_MLOOP_RET_LOOP, MENU_MLOOP_RET_END } mloop_ret_code_t; typedef struct { unsigned do_popup_immediately : 1; /* used for delay popups, to just popup the menu */ unsigned do_popup_now : 1; unsigned do_popdown_now : 1; /* used for keystrokes, to popup and move to that menu */ unsigned do_popup_and_warp : 1; unsigned do_force_reposition : 1; unsigned do_force_popup : 1; unsigned do_popdown : 1; unsigned do_popup : 1; unsigned do_menu : 1; unsigned do_recycle_event : 1; unsigned do_propagate_event_into_submenu : 1; unsigned has_mouse_moved : 1; unsigned is_off_menu_allowed : 1; unsigned is_key_press : 1; unsigned is_item_entered_by_key_press : 1; unsigned is_motion_faked : 1; unsigned is_popped_up_by_timeout : 1; unsigned is_pointer_in_active_item_area : 1; unsigned is_motion_first : 1; unsigned is_release_first : 1; unsigned is_submenu_mapped : 1; unsigned was_item_unposted : 1; unsigned is_button_release : 1; } mloop_flags_t; typedef struct { MenuItem *mi; MenuRoot *mrMi; int x_offset; int popdown_delay_10ms; int popup_delay_10ms; } mloop_evh_data_t; typedef struct { MenuRoot *mrPopup; MenuRoot *mrPopdown; mloop_flags_t mif; /* used to reduce network traffic with delayed popup/popdown */ MenuItem *mi_with_popup; MenuItem *mi_wants_popup; MenuItem *miRemovedSubmenu; } mloop_evh_input_t; /* values that are set once when the menu loop is entered */ typedef struct mloop_static_info_t { int x_init; int y_init; Time t0; unsigned int event_mask; } mloop_static_info_t; /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* This global is saved and restored every time a function is called that * might modify them, so we can safely let it live outside a function. */ static saved_pos_hints last_saved_pos_hints; /* structures for menus */ static MenuInfo Menus; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ static void __menu_execute_function(const exec_context_t **pexc, char *action) { const exec_context_t *exc; exec_context_changes_t ecc; int old_emf; ecc.w.w = ((*pexc)->w.fw) ? FW_W((*pexc)->w.fw) : None; exc = exc_clone_context(*pexc, &ecc, ECC_W); old_emf = Scr.flags.is_executing_menu_function; Scr.flags.is_executing_menu_function = 1; execute_function(NULL, exc, action, FUNC_DONT_EXPAND_COMMAND); Scr.flags.is_executing_menu_function = old_emf; exc_destroy_context(exc); /* See if the window has been deleted */ if (!check_if_fvwm_window_exists((*pexc)->w.fw)) { ecc.w.fw = NULL; ecc.w.w = None; ecc.w.wcontext = 0; exc = exc_clone_context( *pexc, &ecc, ECC_FW | ECC_W | ECC_WCONTEXT); exc_destroy_context(*pexc); *pexc = exc; } return; } static Bool pointer_in_active_item_area(int x_offset, MenuRoot *mr) { float ratio = (float)MST_ACTIVE_AREA_PERCENT(mr) / 100.0; if (MST_ACTIVE_AREA_PERCENT(mr) >= 100) { return False; } if (MST_USE_LEFT_SUBMENUS(mr)) { return (x_offset <= MR_ITEM_X_OFFSET(mr) + MR_ITEM_WIDTH(mr) - MR_ITEM_WIDTH(mr) * ratio); } else { return (x_offset >= MR_ITEM_X_OFFSET(mr) + MR_ITEM_WIDTH(mr) * ratio); } } static Bool pointer_in_passive_item_area(int x_offset, MenuRoot *mr) { float ratio = (float)MST_ACTIVE_AREA_PERCENT(mr) / 100.0; if (MST_ACTIVE_AREA_PERCENT(mr) >= 100) { return False; } if (MST_USE_LEFT_SUBMENUS(mr)) { return (x_offset >= MR_ITEM_X_OFFSET(mr) + MR_ITEM_WIDTH(mr) * ratio); } else { return (x_offset <= MR_ITEM_X_OFFSET(mr) + MR_ITEM_WIDTH(mr) - MR_ITEM_WIDTH(mr) * ratio); } } /* * warping functions */ static void warp_pointer_to_title(MenuRoot *mr) { FWarpPointer( dpy, 0, MR_WINDOW(mr), 0, 0, 0, 0, menudim_middle_x_offset(&MR_DIM(mr)), menuitem_middle_y_offset(MR_FIRST_ITEM(mr), MR_STYLE(mr))); } static MenuItem *warp_pointer_to_item( MenuRoot *mr, MenuItem *mi, Bool do_skip_title) { if (do_skip_title) { while (MI_NEXT_ITEM(mi) != NULL && (!MI_IS_SELECTABLE(mi) || MI_IS_TEAR_OFF_BAR(mi))) { /* skip separators, titles and tear off bars until the * first 'real' item is found */ mi = MI_NEXT_ITEM(mi); } } if (mi == NULL) { mi = MR_LAST_ITEM(mr); } if (mi == NULL) { return mi; } FWarpPointer( dpy, 0, MR_WINDOW(mr), 0, 0, 0, 0, menudim_middle_x_offset(&MR_DIM(mr)), menuitem_middle_y_offset(mi, MR_STYLE(mr))); return mi; } /* * menu animation functions */ /* prepares the parameters to be passed to AnimatedMoveOfWindow * mr - the menu instance that holds the menu item * fw - the FvwmWindow structure to check against allowed functions */ static void get_menu_repaint_transparent_parameters( MenuRepaintTransparentParameters *pmrtp, MenuRoot *mr, FvwmWindow *fw) { pmrtp->mr = mr; pmrtp->fw = fw; return; } /* Undo the animation of a menu */ static void animated_move_back( MenuRoot *mr, Bool do_warp_pointer, FvwmWindow *fw) { MenuRepaintTransparentParameters mrtp; int act_x; int act_y; if (MR_XANIMATION(mr) == 0) { return; } if (menu_get_geometry( mr, &JunkRoot, &act_x, &act_y, &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth)) { Bool transparent_bg = False; /* move it back */ if (ST_HAS_MENU_CSET(MR_STYLE(mr)) && CSET_IS_TRANSPARENT(ST_CSET_MENU(MR_STYLE(mr)))) { transparent_bg = True; get_menu_repaint_transparent_parameters( &mrtp, mr, fw); } AnimatedMoveOfWindow( MR_WINDOW(mr), act_x, act_y, act_x - MR_XANIMATION(mr), act_y, do_warp_pointer, -1, NULL, (transparent_bg)? &mrtp:NULL); MR_XANIMATION(mr) = 0; } return; } /* move a menu or a tear-off menu preserving transparency. * tear-off menus are moved with their frame coordinates. */ static void move_any_menu( MenuRoot *mr, MenuParameters *pmp, int endX, int endY) { if (MR_IS_TEAR_OFF_MENU(mr)) { float fFull = 1.0; /* this moves the tearoff menu, updating of transparency * will not be as good as if menu repaint parameters * are used. */ AnimatedMoveFvwmWindow( pmp->tear_off_root_menu_window, FW_W_FRAME(pmp->tear_off_root_menu_window), -1, -1, endX, endY, False, 0, &fFull); } else { int x; int y; int JunkDept; menu_get_geometry(mr, &JunkRoot, &x, &y, &JunkWidth, &JunkHeight, &JunkBW, &JunkDept); if (x == endX && y == endY) { return; } if (ST_HAS_MENU_CSET(MR_STYLE(mr)) && CSET_IS_TRANSPARENT(ST_CSET_MENU(MR_STYLE(mr)))) { MenuRepaintTransparentParameters mrtp; get_menu_repaint_transparent_parameters( &mrtp, mr, (*pmp->pexc)->w.fw); update_transparent_menu_bg( &mrtp, x, y, endX, endY, endX, endY); XMoveWindow(dpy, MR_WINDOW(mr), endX, endY); repaint_transparent_menu( &mrtp, False, endX,endY, endX, endY, True); } else { XMoveWindow(dpy, MR_WINDOW(mr), endX, endY); } } } /* ---------------------------- submenu function --------------------------- */ /* Search for a submenu that was popped up by the given item in the given * instance of the menu. */ static MenuRoot *seek_submenu_instance( MenuRoot *parent_menu, MenuItem *parent_item) { MenuRoot *mr; for (mr = Menus.all; mr != NULL; mr = MR_NEXT_MENU(mr)) { if (MR_PARENT_MENU(mr) == parent_menu && MR_PARENT_ITEM(mr) == parent_item) { /* here it is */ break; } } return mr; } static Bool is_submenu_mapped(MenuRoot *parent_menu, MenuItem *parent_item) { XWindowAttributes win_attribs; MenuRoot *mr; mr = seek_submenu_instance(parent_menu, parent_item); if (mr == NULL) { return False; } if (MR_WINDOW(mr) == None) { return False; } if (!XGetWindowAttributes(dpy, MR_WINDOW(mr), &win_attribs)) { return False; } return (win_attribs.map_state == IsViewable); } /* Returns the menu root that a given menu item pops up */ static MenuRoot *mr_popup_for_mi(MenuRoot *mr, MenuItem *mi) { char *menu_name; MenuRoot *menu = NULL; /* This checks if mi is != NULL too */ if (!mi || !MI_IS_POPUP(mi)) { return NULL; } /* first look for a menu that is aleady mapped */ menu = seek_submenu_instance(mr, mi); if (menu) { return menu; } /* just look past "Popup " in the action, and find that menu root */ menu_name = PeekToken(SkipNTokens(MI_ACTION(mi), 1), NULL); menu = menus_find_menu(menu_name); return menu; } /* ---------------------------- item handling ------------------------------ */ /* * find_entry() * * Returns the menu item the pointer is over and optionally the offset * from the left side of the menu entry (if px_offset is != NULL) and * the MenuRoot the pointer is over (if pmr is != NULL). */ static MenuItem *find_entry( MenuParameters *pmp, int *px_offset /*NULL means don't return this value */, MenuRoot **pmr /*NULL means don't return this value */, /* values passed in from caller it FQueryPointer was already called * there */ Window p_child, int p_rx, int p_ry) { MenuItem *mi; MenuRoot *mr; int root_x, root_y; int x, y; Window Child; int r; /* x_offset returns the x offset of the pointer in the found menu item */ if (px_offset) { *px_offset = 0; } if (pmr) { *pmr = NULL; } /* get the pointer position */ if (p_rx < 0) { if (!FQueryPointer( dpy, Scr.Root, &JunkRoot, &Child, &root_x, &root_y, &JunkX, &JunkY, &JunkMask)) { /* pointer is on a different screen */ return NULL; } } else { root_x = p_rx; root_y = p_ry; Child = p_child; } /* find out the menu the pointer is in */ if (pmp->tear_off_root_menu_window != NULL && Child == FW_W_FRAME(pmp->tear_off_root_menu_window)) { /* we're in the top level torn off menu */ Child = FW_W(pmp->tear_off_root_menu_window); } if (XFindContext(dpy, Child, MenuContext, (caddr_t *)&mr) == XCNOENT) { return NULL; } /* get position in that child window */ if (!XTranslateCoordinates( dpy, Scr.Root, MR_WINDOW(mr), root_x, root_y, &x, &y, &JunkChild)) { return NULL; } if (x < 0 || y < 0 || x >= MR_WIDTH(mr) || y >= MR_HEIGHT(mr)) { return NULL; } if (pmr) { *pmr = mr; } r = MST_RELIEF_THICKNESS(mr); /* look for the entry that the mouse is in */ for (mi = MR_FIRST_ITEM(mr); mi; mi = MI_NEXT_ITEM(mi)) { int a; int b; a = (MI_PREV_ITEM(mi) && MI_IS_SELECTABLE(MI_PREV_ITEM(mi))) ? r / 2 : 0; if (!MI_IS_SELECTABLE(mi)) { b = 0; } else if (MI_NEXT_ITEM(mi) && MI_IS_SELECTABLE(MI_NEXT_ITEM(mi))) { b = r / 2; } else { b = r; } if (y >= MI_Y_OFFSET(mi) - a && y < MI_Y_OFFSET(mi) + MI_HEIGHT(mi) + b) { break; } } if (x < MR_ITEM_X_OFFSET(mr) || x >= MR_ITEM_X_OFFSET(mr) + MR_ITEM_WIDTH(mr) - 1) { mi = NULL; } if (mi && px_offset) { *px_offset = x; } return mi; } /* ---------------------------- keyboard shortcuts ------------------------- */ static Bool is_double_click( Time t0, MenuItem *mi, MenuParameters *pmp, MenuReturn *pmret, double_keypress *pdkp, Bool has_mouse_moved) { if ((*pmp->pexc)->x.elast->type == KeyPress) { return False; } if (fev_get_evtime() - t0 >= MST_DOUBLE_CLICK_TIME(pmp->menu)) { return False; } if (has_mouse_moved) { return False; } if (!pmp->flags.has_default_action && (mi && mi == MR_FIRST_ITEM(pmp->menu) && MI_IS_SELECTABLE(mi))) { return False; } if (pmp->flags.is_submenu) { return False; } if (pmp->flags.is_invoked_by_key_press && pdkp->timestamp == 0) { return False; } return True; } /* ---------------------------- item label parsing ------------------------- */ /* * Procedure: * scanForHotkeys - Look for hotkey markers in a MenuItem * (pete@tecc.co.uk) * * Inputs: * it - MenuItem to scan * column - The column number in which to look for a hotkey. * */ static void scanForHotkeys( MenuItem *it, int column) { char *start; char *s; char *t; /* Get start of string */ start = MI_LABEL(it)[column]; /* Scan whole string */ for (s = start; *s != '\0'; s++) { if (*s != '&') { continue; } if (s[1] != '&') { /* found a hotkey - only one hotkey per item */ break; } /* Just an escaped '&'; copy the string down over it */ for (t = s; *t != '\0'; t++) { t[0] = t[1]; } } if (*s != 0) { /* It's a hot key marker - work out the offset value */ MI_HOTKEY_COFFSET(it) = s - start; MI_HOTKEY_COLUMN(it) = column; MI_HAS_HOTKEY(it) = (s[1] != '\0'); MI_IS_HOTKEY_AUTOMATIC(it) = 0; for ( ; *s != '\0'; s++) { /* Copy down.. */ s[0] = s[1]; } } return; } static void __copy_down(char *remove_from, char *remove_to) { char *t1; char *t2; for (t1 = remove_from, t2 = remove_to; *t2 != '\0'; t2++, t1++) { *t1 = *t2; } *t1 = '\0'; return; } static int __check_for_delimiter(char *s, const string_def_t *string_defs) { int type; for (type = 0; string_defs[type].delimiter != '\0'; type++) { if (s[0] == string_defs[type].delimiter) { if (s[1] != string_defs[type].delimiter) { return type; } else { /* escaped delimiter, copy the * string down over it */ __copy_down(s, s+1); return -1; } } } return -1; } /* This scans for strings within delimiters and calls a callback based * on the delimiter found for each found string */ static void scanForStrings( char *instring, const string_def_t *string_defs, string_context_t *context) { char *s; int type; char *string; type = -1; /* string is set whenever type >= 0, and unused otherwise * set to NULL to supress compiler warning */ string = NULL; for (s = instring; *s != '\0'; s++) { if (type < 0) { /* look for starting delimiters */ type = __check_for_delimiter(s, string_defs); if (type >= 0) { /* start of a string */ string = s + 1; } } else if ( s[0] == string_defs[type].delimiter && s[1] != string_defs[type].delimiter) { /* found ending delimiter */ Bool is_valid; /* terminate the string pointer */ s[0] = '\0'; is_valid = string_defs[type].string_handler( string, string_defs[type].delimiter, context); /* restore the string */ s[0] = string_defs[type].delimiter; if (is_valid) { /* the string was OK, remove it from * instring */ __copy_down(string - 1, s + 1); /* continue next iteration at the * first character after the string */ s = string - 2; } type = -1; } else if (s[0] == string_defs[type].delimiter) { /* escaped delimiter, copy the string down over * it */ __copy_down(s, s + 1); } } } /* Side picture support: this scans for a color int the menu name for colorization */ static Bool __scan_for_color( char *name, char type, string_context_t *context) { if (type != '^' || SCTX_GET_MR(*context) == NULL) { abort(); } if (MR_HAS_SIDECOLOR(SCTX_GET_MR(*context))) { return False; } MR_SIDECOLOR(SCTX_GET_MR(*context)) = GetColor(name); MR_HAS_SIDECOLOR(SCTX_GET_MR(*context)) = True; return True; } static Bool __scan_for_pixmap( char *name, char type, string_context_t *context) { FvwmPicture *p; FvwmPictureAttributes fpa; int current_mini_icon; /* check that more pictures are allowed before trying to load the * picture */ current_mini_icon = -999999999; switch (type) { case '@': if (SCTX_GET_MR(*context) == NULL) { abort(); } if (MR_SIDEPIC(SCTX_GET_MR(*context))) { return False; } break; case '*': /* menu item picture, requires menu item */ if (SCTX_GET_MI(*context) == NULL) { abort(); } if (MI_PICTURE(SCTX_GET_MI(*context))) { return False; } break; case '%': /* mini icon - look for next free spot */ if (SCTX_GET_MI(*context) == NULL) { abort(); } current_mini_icon = 0; while (current_mini_icon < MAX_MENU_ITEM_MINI_ICONS) { if ( MI_MINI_ICON(SCTX_GET_MI(*context)) [current_mini_icon]) { current_mini_icon++; } else { break; } } if (current_mini_icon == MAX_MENU_ITEM_MINI_ICONS) { return False; } break; default: abort(); } fpa.mask = 0; p = PCacheFvwmPicture( dpy, Scr.NoFocusWin, NULL, name, fpa); if (!p) { fvwm_msg(WARN, "scanForPixmap", "Couldn't load image from %s", name); fvwm_msg(WARN, "scanForPixmap", "Check that FVWM has support for the filetype it's " "being asked to load."); /* return true to make missing pictures not appear in the * label/name */ return True; } switch (type) { case '@': MR_SIDEPIC(SCTX_GET_MR(*context)) = p; break; case '*': MI_PICTURE(SCTX_GET_MI(*context)) = p; MI_HAS_PICTURE(SCTX_GET_MI(*context)) = True; break; case '%': MI_MINI_ICON(SCTX_GET_MI(*context))[current_mini_icon] = p; MI_HAS_PICTURE(SCTX_GET_MI(*context)) = True; break; } return True; } /* ---------------------------- item list handling ------------------------- */ static void unlink_item_from_menu( MenuRoot *mr, MenuItem *mi) { MenuItem *next; MenuItem *prev; next = MI_NEXT_ITEM(mi); prev = MI_PREV_ITEM(mi); if (next != NULL) { MI_PREV_ITEM(next) = prev; } else { MR_LAST_ITEM(mr) = prev; } if (prev != NULL) { MI_NEXT_ITEM(prev) = next; } else { MR_FIRST_ITEM(mr) = next; } MI_NEXT_ITEM(mi) = NULL; MI_PREV_ITEM(mi) = NULL; MR_ITEMS(mr)--; return; } /* Add the given menu item to the menu. If the first item of the menu is a * title, and the do_replace_title flag is True, the old title is deleted and * replaced by the new item. Otherwise the item is appended at the end of the * menu. */ static void append_item_to_menu( MenuRoot *mr, MenuItem *mi, Bool do_replace_title) { if (MR_FIRST_ITEM(mr) == NULL) { MR_FIRST_ITEM(mr) = mi; MR_LAST_ITEM(mr) = mi; MI_NEXT_ITEM(mi) = NULL; MI_PREV_ITEM(mi) = NULL; } else if (do_replace_title) { if (MI_IS_TITLE(MR_FIRST_ITEM(mr))) { if (MR_FIRST_ITEM(mr) == MR_LAST_ITEM(mr)) { MR_LAST_ITEM(mr) = mi; } if (MI_NEXT_ITEM(MR_FIRST_ITEM(mr)) != NULL) { MI_PREV_ITEM(MI_NEXT_ITEM( MR_FIRST_ITEM(mr))) = mi; } MI_NEXT_ITEM(mi) = MI_NEXT_ITEM(MR_FIRST_ITEM(mr)); menuitem_free(MR_FIRST_ITEM(mr)); } else { MI_PREV_ITEM(MR_FIRST_ITEM(mr)) = mi; MI_NEXT_ITEM(mi) = MR_FIRST_ITEM(mr); } MI_PREV_ITEM(mi) = NULL; MR_FIRST_ITEM(mr) = mi; } else { MI_NEXT_ITEM(MR_LAST_ITEM(mr)) = mi; MI_PREV_ITEM(mi) = MR_LAST_ITEM(mr); MR_LAST_ITEM(mr) = mi; } return; } static void clone_menu_item_list( MenuRoot *dest_mr, MenuRoot *src_mr) { MenuItem *mi; MenuItem *cloned_mi; MenuRoot *mr; MR_FIRST_ITEM(dest_mr) = NULL; MR_LAST_ITEM(dest_mr) = NULL; /* traverse the menu and all its continuations */ for (mr = src_mr; mr != NULL; mr = MR_CONTINUATION_MENU(mr)) { /* duplicate all items in the current menu */ for (mi = MR_FIRST_ITEM(mr); mi != NULL; mi = MI_NEXT_ITEM(mi)) { if (MI_IS_CONTINUATION(mi)) { /* skip this item */ continue; } cloned_mi = menuitem_clone(mi); append_item_to_menu(dest_mr, cloned_mi, False); } } return; } /* ---------------------------- MenuRoot maintenance functions ------------- */ /* Extract interesting values from the item format string that are needed by * the size_menu_... functions. */ static void calculate_item_sizes(MenuSizingParameters *msp) { MenuItem *mi; MenuItemPartSizesT mipst; int i; Bool do_reverse_icon_order = (MST_USE_LEFT_SUBMENUS(msp->menu)) ? True : False; memset(&(msp->max), 0, sizeof(msp->max)); /* Calculate the widths for all columns of all items. */ for (mi = MR_FIRST_ITEM(msp->menu); mi != NULL; mi = MI_NEXT_ITEM(mi)) { if (MI_IS_TITLE(mi)) { menuitem_get_size( mi, &mipst, MST_PTITLEFONT(msp->menu), do_reverse_icon_order); } else { menuitem_get_size( mi, &mipst, MST_PSTDFONT(msp->menu), do_reverse_icon_order); } /* adjust maximums */ if (msp->max.i.triangle_width < mipst.triangle_width) { msp->max.i.triangle_width = mipst.triangle_width; } if (msp->max.i.title_width < mipst.title_width) { msp->max.i.title_width = mipst.title_width; } for (i = 0; i < MAX_MENU_ITEM_LABELS; i++) { if (msp->max.i.label_width[i] < mipst.label_width[i]) { msp->max.i.label_width[i] = mipst.label_width[i]; } } if (msp->max.i.picture_width < mipst.picture_width) { msp->max.i.picture_width = mipst.picture_width; } for (i = 0; i < MAX_MENU_ITEM_MINI_ICONS; i++) { if (msp->max.i.icon_width[i] < mipst.icon_width[i]) { msp->max.i.icon_width[i] = mipst.icon_width[i]; } } } if (MR_SIDEPIC(msp->menu)) { msp->max.sidepic_width = MR_SIDEPIC(msp->menu)->width; } else if (MST_SIDEPIC(msp->menu)) { msp->max.sidepic_width = MST_SIDEPIC(msp->menu)->width; } return; } /* * * Calculate the positions of the columns in the menu. * Called by make_menu(). * */ static void size_menu_horizontally(MenuSizingParameters *msp) { MenuItem *mi; Bool sidepic_is_left = True; int total_width; int sidepic_space = 0; int label_offset[MAX_MENU_ITEM_LABELS]; char lcr_column[MAX_MENU_ITEM_LABELS]; int i; int d; int relief_thickness = MST_RELIEF_THICKNESS(msp->menu); int *item_order[ MAX_MENU_ITEM_LABELS + MAX_MENU_ITEM_MINI_ICONS + 1 /* triangle */ + 2 /* relief markers */]; int used_objects = 0; int left_objects = 0; int right_objects = 0; int x; unsigned char icons_placed = 0; Bool sidepic_placed = False; Bool triangle_placed = False; Bool relief_begin_placed = False; Bool relief_end_placed = False; char *format; Bool first = True; Bool done = False; Bool is_last_object_left = True; unsigned char columns_placed = 0; int relief_gap = 0; int gap_left; int gap_right; int chars; memset(item_order, 0, sizeof(item_order)); for (i = 0; i < MAX_MENU_ITEM_LABELS; i++) { lcr_column[i] = 'l'; } /* Now calculate the offsets for the columns. */ format = MST_ITEM_FORMAT(msp->menu); if (!format) { format = (MST_USE_LEFT_SUBMENUS(msp->menu)) ? DEFAULT_LEFT_MENU_ITEM_FORMAT : DEFAULT_MENU_ITEM_FORMAT; } /* Place the individual items off the menu in case they are not * set in the format string. */ for (i = 0; i < MAX_MENU_ITEM_LABELS; i++) { label_offset[i] = 2 * Scr.MyDisplayWidth; } x = MST_BORDER_WIDTH(msp->menu); while (*format && !done) { switch (*format) { case '%': format++; chars = 0; gap_left = 0; gap_right = 0; /* Insert a gap of %d pixels. */ if (sscanf(format, "%d.%d%n", &gap_left, &gap_right, &chars) >= 2 || (sscanf(format, "%d.%n", &gap_left, &chars) >= 1 && chars > 0) || sscanf(format, "%d%n", &gap_left, &chars) >= 1 || sscanf(format, ".%d%n", &gap_right, &chars) >= 1) { if (gap_left > MR_SCREEN_WIDTH(msp->menu) || gap_left < -MR_SCREEN_WIDTH(msp->menu)) { gap_left = 0; } if (gap_right > MR_SCREEN_HEIGHT(msp->menu) || gap_right < -MR_SCREEN_HEIGHT(msp->menu)) { gap_right = 0; } /* Skip the number. */ format += chars; } else if (*format == '.') { /* Skip a dot without values */ format++; } if (!*format) { break; } switch (*format) { case 'l': case 'c': case 'r': /* A left, center or right aligned column. */ if (columns_placed >= MAX_MENU_ITEM_LABELS) { break; } if ( msp->max.i.label_width[columns_placed] <= 0) { columns_placed++; break; } lcr_column[columns_placed] = *format; x += gap_left; label_offset[columns_placed] = x; x += msp->max.i.label_width[columns_placed] + gap_right; item_order[used_objects++] = &(label_offset[columns_placed]); if (is_last_object_left && (*format == 'l')) { left_objects++; } else { is_last_object_left = False; if (*format == 'r') { right_objects++; } else { right_objects = 0; } } columns_placed++; break; case 's': /* the sidepic */ if (sidepic_placed) { break; } sidepic_placed = True; if (msp->max.sidepic_width <= 0) { break; } x += gap_left; MR_SIDEPIC_X_OFFSET(msp->menu) = x; sidepic_is_left = first; sidepic_space = msp->max.sidepic_width + ((sidepic_is_left) ? gap_left : gap_right); x += msp->max.sidepic_width + gap_right; break; case 'i': /* a mini icon */ if (icons_placed >= MAX_MENU_ITEM_MINI_ICONS) { break; } if (msp->max.i.icon_width[icons_placed] > 0) { x += gap_left; MR_ICON_X_OFFSET(msp->menu) [icons_placed] = x; x += msp->max.i.icon_width [icons_placed] + gap_right; item_order[used_objects++] = &(MR_ICON_X_OFFSET(msp->menu) [icons_placed]); if (is_last_object_left) { left_objects++; } else { right_objects++; } } icons_placed++; break; case '|': if (!relief_begin_placed) { relief_begin_placed = True; x += gap_left; MR_HILIGHT_X_OFFSET(msp->menu) = x; x += relief_thickness + gap_right; relief_gap += gap_right; item_order[used_objects++] = &(MR_HILIGHT_X_OFFSET( msp->menu)); if (is_last_object_left) { left_objects++; } else { right_objects = 0; } } else if (!relief_end_placed) { relief_end_placed = True; x += relief_thickness + gap_left; /* This is a hack: for now we record * the x coordinate of the end of the * hilight area, but later we'll place * the width in here. */ MR_HILIGHT_WIDTH(msp->menu) = x; x += gap_right; relief_gap += gap_left; item_order[used_objects++] = &(MR_HILIGHT_WIDTH(msp->menu)); right_objects++; } break; case '>': case '<': /* the triangle for popup menus */ if (triangle_placed) { break; } triangle_placed = True; if (msp->max.i.triangle_width > 0) { x += gap_left; MR_TRIANGLE_X_OFFSET( msp->menu) = x; MR_IS_LEFT_TRIANGLE(msp->menu) = (*format == '<'); x += msp->max.i.triangle_width + gap_right; item_order[used_objects++] = &(MR_TRIANGLE_X_OFFSET( msp->menu)); if (is_last_object_left && *format == '<') { left_objects++; } else { is_last_object_left = False; right_objects++; } } break; case 'p': /* Simply add a gap. */ x += gap_right + gap_left; break; case '\t': x += MENU_TAB_WIDTH * FlocaleTextWidth( MST_PSTDFONT( msp->menu), " ", 1); break; case ' ': /* Advance the x position. */ x += FlocaleTextWidth( MST_PSTDFONT(msp->menu), format, 1); break; default: /* Ignore unknown characters. */ break; } /* switch (*format) */ break; case '\t': x += MENU_TAB_WIDTH * FlocaleTextWidth( MST_PSTDFONT(msp->menu), " ", 1); break; case ' ': /* Advance the x position. */ x += FlocaleTextWidth( MST_PSTDFONT(msp->menu), format, 1); break; default: /* Ignore unknown characters. */ break; } /* switch (*format) */ format++; first = False; } /* while (*format) */ /* stored for vertical sizing */ msp->used_item_labels = columns_placed; msp->used_mini_icons = icons_placed; /* Hide unplaced parts of the menu. */ if (!sidepic_placed) { MR_SIDEPIC_X_OFFSET(msp->menu) = 2 * MR_SCREEN_WIDTH(msp->menu); } for (i = icons_placed; i < MAX_MENU_ITEM_MINI_ICONS; i++) { MR_ICON_X_OFFSET(msp->menu)[i] = 2 * MR_SCREEN_WIDTH(msp->menu); } if (!triangle_placed) { MR_TRIANGLE_X_OFFSET(msp->menu) = 2 * MR_SCREEN_WIDTH(msp->menu); } msp->flags.is_popup_indicator_used = triangle_placed; total_width = x - MST_BORDER_WIDTH(msp->menu); d = (sidepic_space + 2 * relief_thickness + max(msp->max.i.title_width, msp->max.i.picture_width)) - total_width; if (d > 0) { int m = 1 - left_objects; int n = 1 + used_objects - left_objects - right_objects; /* The title is larger than all menu items. Stretch the * gaps between the items up to the total width of the * title. */ for (i = 0; i < used_objects; i++) { if (i < left_objects) { continue; } if (i >= used_objects - right_objects) { /* Right aligned item. */ *(item_order[i]) += d; } else { /* Neither left nor right aligned item. * Divide the overhead gap evenly * between the items. */ *(item_order[i]) += d * (m + i) / n; } } total_width += d; if (!sidepic_is_left) { MR_SIDEPIC_X_OFFSET(msp->menu) += d; } } /* if (d > 0) */ MR_WIDTH(msp->menu) = total_width + 2 * MST_BORDER_WIDTH(msp->menu); MR_ITEM_WIDTH(msp->menu) = total_width - sidepic_space; MR_ITEM_X_OFFSET(msp->menu) = MST_BORDER_WIDTH(msp->menu); if (sidepic_is_left) { MR_ITEM_X_OFFSET(msp->menu) += sidepic_space; } if (!relief_begin_placed) { MR_HILIGHT_X_OFFSET(msp->menu) = MR_ITEM_X_OFFSET(msp->menu); } if (relief_end_placed) { MR_HILIGHT_WIDTH(msp->menu) = MR_HILIGHT_WIDTH(msp->menu) - MR_HILIGHT_X_OFFSET(msp->menu); } else { MR_HILIGHT_WIDTH(msp->menu) = MR_ITEM_WIDTH(msp->menu) + MR_ITEM_X_OFFSET(msp->menu) - MR_HILIGHT_X_OFFSET(msp->menu); } /* Now calculate the offsets for the individual labels. */ for (mi = MR_FIRST_ITEM(msp->menu); mi != NULL; mi = MI_NEXT_ITEM(mi)) { for (i = 0; i < MAX_MENU_ITEM_LABELS; i++) { if (MI_LABEL(mi)[i] == NULL) { continue; } if (!MI_IS_TITLE(mi) || !MI_IS_TITLE_CENTERED(mi)) { switch (lcr_column[i]) { case 'l': MI_LABEL_OFFSET(mi)[i] = label_offset[i]; break; case 'c': MI_LABEL_OFFSET(mi)[i] = label_offset[i] + (msp->max.i.label_width[i] - MI_LABEL_OFFSET(mi)[i]) / 2; break; case 'r': MI_LABEL_OFFSET(mi)[i] = label_offset[i] + msp->max.i.label_width[i] - MI_LABEL_OFFSET(mi)[i]; break; } } else { /* This is a centered title item (indicated by * negative width). */ MI_LABEL_OFFSET(mi)[i] = menudim_middle_x_offset( &MR_DIM(msp->menu)) - MI_LABEL_OFFSET(mi)[i] / 2; } } /* for */ } /* for */ return; } static int calc_more_item_height(MenuSizingParameters *msp) { int height; height = MST_PSTDFONT(msp->menu)->height + MST_ITEM_GAP_ABOVE(msp->menu) + MST_ITEM_GAP_BELOW(msp->menu) + MST_RELIEF_THICKNESS(msp->menu); return height; } static int calc_normal_item_height(MenuSizingParameters *msp, MenuItem *mi) { int height; height = MST_ITEM_GAP_ABOVE(msp->menu) + MST_ITEM_GAP_BELOW(msp->menu) + MST_RELIEF_THICKNESS(msp->menu); /* Normal text entry or an entry with a sub menu triangle */ if ( (MI_HAS_TEXT(mi) && msp->used_item_labels) || (MI_IS_POPUP(mi) && msp->flags.is_popup_indicator_used)) { height += MST_PSTDFONT(msp->menu)->height; } return height; } /* * * Calculate the positions of the columns in the menu. * Called by make_menu(). * */ static Bool size_menu_vertically(MenuSizingParameters *msp) { MenuItem *mi; int y; int cItems; int relief_thickness = MST_RELIEF_THICKNESS(msp->menu); int i; Bool has_continuation_menu = False; MR_ITEM_TEXT_Y_OFFSET(msp->menu) = MST_PSTDFONT(msp->menu)->ascent + relief_thickness + MST_ITEM_GAP_ABOVE(msp->menu); /* mi_prev trails one behind mi, since we need to move that into a newly-made menu if we run out of space */ y = MST_BORDER_WIDTH(msp->menu) + MST_VERTICAL_MARGIN_TOP(msp->menu); for ( cItems = 0, mi = MR_FIRST_ITEM(msp->menu); mi != NULL; mi = MI_NEXT_ITEM(mi), cItems++) { Bool last_item_has_relief = (MI_PREV_ITEM(mi)) ? MI_IS_SELECTABLE(MI_PREV_ITEM(mi)) : False; Bool has_mini_icon = False; int separator_height; int menu_height; separator_height = (last_item_has_relief) ? MENU_SEPARATOR_HEIGHT + relief_thickness : MENU_SEPARATOR_TOTAL_HEIGHT; MI_Y_OFFSET(mi) = y; if (MI_IS_TITLE(mi)) { MI_HEIGHT(mi) = MST_PTITLEFONT(msp->menu)->height + MST_TITLE_GAP_ABOVE(msp->menu) + MST_TITLE_GAP_BELOW(msp->menu); } else if (MI_IS_SEPARATOR(mi)) { /* Separator */ MI_HEIGHT(mi) = separator_height; } else if (MI_IS_TEAR_OFF_BAR(mi)) { /* Tear off bar */ MI_HEIGHT(mi) = relief_thickness + MENU_TEAR_OFF_BAR_HEIGHT; } else { MI_HEIGHT(mi) = calc_normal_item_height(msp, mi); } if (MI_IS_TITLE(mi)) { /* add space for the underlines */ switch (MST_TITLE_UNDERLINES(msp->menu)) { case 0: if (last_item_has_relief) MI_HEIGHT(mi) += relief_thickness; break; case 1: if (mi != MR_FIRST_ITEM(msp->menu)) { /* Space to draw the separator plus a * gap above */ MI_HEIGHT(mi) += separator_height; } if (MI_NEXT_ITEM(mi) != NULL) { /* Space to draw the separator */ MI_HEIGHT(mi) += MENU_SEPARATOR_HEIGHT; } break; default: /* Space to draw n underlines. */ MI_HEIGHT(mi) += MENU_UNDERLINE_HEIGHT * MST_TITLE_UNDERLINES(msp->menu); if (last_item_has_relief) MI_HEIGHT(mi) += relief_thickness; break; } } for (i = 0; i < msp->used_mini_icons; i++) { if (MI_MINI_ICON(mi)[i]) { has_mini_icon = True; } if (MI_MINI_ICON(mi)[i] && MI_HEIGHT(mi) < MI_MINI_ICON(mi)[i]->height + relief_thickness) { MI_HEIGHT(mi) = MI_MINI_ICON(mi)[i]->height + relief_thickness; } } if (MI_PICTURE(mi)) { if ((MI_HAS_TEXT(mi) && msp->used_item_labels) || has_mini_icon) { MI_HEIGHT(mi) += MI_PICTURE(mi)->height; } else { MI_HEIGHT(mi) = MI_PICTURE(mi)->height + relief_thickness; } } y += MI_HEIGHT(mi); /* this item would have to be the last item, or else * we need to add a "More..." entry pointing to a new menu */ menu_height = y + MST_BORDER_WIDTH(msp->menu) + MST_VERTICAL_MARGIN_BOTTOM(msp->menu) + ((MI_IS_SELECTABLE(mi)) ? relief_thickness : 0); if (menu_height > MR_SCREEN_HEIGHT(msp->menu)) { /* Item does not fit on screen anymore. */ char *t; char *tempname; const char *gt_name; char *name; MenuRoot *menuContinuation; int more_item_height; more_item_height = calc_more_item_height(msp); /* Remove items form the menu until it fits (plus a * 'More' entry). */ while ( MI_PREV_ITEM(mi) != NULL && menu_height > MR_SCREEN_HEIGHT(msp->menu)) { /* Remove current item. */ y -= MI_HEIGHT(mi); mi = MI_PREV_ITEM(mi); cItems--; menu_height = y + MST_BORDER_WIDTH(msp->menu) + more_item_height + relief_thickness + MST_VERTICAL_MARGIN_BOTTOM(msp->menu); } if ( MI_PREV_ITEM(mi) == NULL || menu_height > MR_SCREEN_HEIGHT(msp->menu)) { fvwm_msg(ERR, "size_menu_vertically", "Menu entry does not fit on screen"); /* leave a coredump */ abort(); exit(1); } t = EscapeString(MR_NAME(msp->menu), "\"", '\\'); tempname = (char *)safemalloc( (10 + strlen(t)) * sizeof(char)); strcpy(tempname, "Popup \""); strcat(tempname, t); strcat(tempname, "$\""); free(t); /* NewMenuRoot inserts at the head of the list of menus but, we need it at the end. (Give it just the name, * which is 6 chars past the action since * strlen("Popup ")==6 ) */ t = (char *)safemalloc(strlen(MR_NAME(msp->menu)) + 2); strcpy(t, MR_NAME(msp->menu)); strcat(t, "$"); menuContinuation = NewMenuRoot(t); free(t); MR_CONTINUATION_MENU(msp->menu) = menuContinuation; /* Now move this item and the remaining items into the * new menu */ MR_FIRST_ITEM(menuContinuation) = MI_NEXT_ITEM(mi); MR_LAST_ITEM(menuContinuation) = MR_LAST_ITEM(msp->menu); MR_ITEMS(menuContinuation) = MR_ITEMS(msp->menu) - cItems; MI_PREV_ITEM(MI_NEXT_ITEM(mi)) = NULL; /* mi_prev is now the last item in the parent menu */ MR_LAST_ITEM(msp->menu) = mi; MR_ITEMS(msp->menu) = cItems; MI_NEXT_ITEM(mi) = NULL; /* use the same style for the submenu */ MR_STYLE(menuContinuation) = MR_STYLE(msp->menu); MR_IS_LEFT_TRIANGLE(menuContinuation) = MR_IS_LEFT_TRIANGLE(msp->menu); /* migo: propagate missing_submenu_func */ if (MR_MISSING_SUBMENU_FUNC(msp->menu)) { MR_MISSING_SUBMENU_FUNC(menuContinuation) = safestrdup(MR_MISSING_SUBMENU_FUNC( msp->menu)); } /* don't propagate sidepic, sidecolor, popup and * popdown actions */ /* And add the entry pointing to the new menu */ gt_name = gettext("More&..."); name = safestrdup(gt_name); AddToMenu( msp->menu, name, tempname, False /* no pixmap scan */, False, True); free(name); free(tempname); has_continuation_menu = True; } } /* for */ /* The menu may be empty here! */ if (MR_LAST_ITEM(msp->menu) != NULL && MI_IS_SELECTABLE(MR_LAST_ITEM(msp->menu))) { y += relief_thickness; } MR_HEIGHT(msp->menu) = y + MST_BORDER_WIDTH(msp->menu) + MST_VERTICAL_MARGIN_BOTTOM(msp->menu); return has_continuation_menu; } /* * * Merge menu continuations back into the original menu. * Called by make_menu(). * */ static void merge_continuation_menus(MenuRoot *mr) { /* merge menu continuations into one menu again - needed when changing * the font size of a long menu. */ while (MR_CONTINUATION_MENU(mr) != NULL) { MenuRoot *cont = MR_CONTINUATION_MENU(mr); /* link first item of continuation to item before 'more...' */ MI_NEXT_ITEM(MI_PREV_ITEM(MR_LAST_ITEM(mr))) = MR_FIRST_ITEM(cont); MI_PREV_ITEM(MR_FIRST_ITEM(cont)) = MI_PREV_ITEM(MR_LAST_ITEM(mr)); menuitem_free(MR_LAST_ITEM(mr)); MR_LAST_ITEM(mr) = MR_LAST_ITEM(cont); MR_CONTINUATION_MENU(mr) = MR_CONTINUATION_MENU(cont); /* fake an empty menu so that DestroyMenu does not destroy the * items. */ MR_FIRST_ITEM(cont) = NULL; DestroyMenu(cont, False, False); } return; } /* * * Creates the window for the menu. * */ static void make_menu_window(MenuRoot *mr, Bool is_tear_off) { unsigned long valuemask; XSetWindowAttributes attributes; int w; int h; unsigned int evmask; w = MR_WIDTH(mr); if (w == 0) { w = 1; } h = MR_HEIGHT(mr); if (h == 0) { h = 1; } attributes.background_pixel = (MST_HAS_MENU_CSET(mr)) ? Colorset[MST_CSET_MENU(mr)].bg : MST_MENU_COLORS(mr).back; if (MR_WINDOW(mr) != None) { /* just resize the existing window */ XResizeWindow(dpy, MR_WINDOW(mr), w, h); /* and change the background color */ valuemask = CWBackPixel | CWCursor; XChangeWindowAttributes( dpy, MR_WINDOW(mr), valuemask, &attributes); } else { /* create a new window */ valuemask = CWBackPixel | CWEventMask | CWCursor | CWColormap | CWBorderPixel | CWSaveUnder; attributes.border_pixel = 0; attributes.colormap = Pcmap; evmask = XEVMASK_MENUW; attributes.event_mask = 0; attributes.cursor = Scr.FvwmCursors[CRS_MENU]; attributes.save_under = True; /* Create a display used to create the window. Can't use the * normal display because 'xkill' would kill the window * manager if used on a tear off menu. The display can't be * deleted right now because that would either destroy the new * window or leave it as an orphan if fvwm dies or is * restarted. */ if (is_tear_off) { MR_CREATE_DPY(mr) = XOpenDisplay(display_name); if (MR_CREATE_DPY(mr) == NULL) { /* Doh. Use the standard display instead. */ MR_CREATE_DPY(mr) = dpy; } } else { MR_CREATE_DPY(mr) = dpy; } MR_WINDOW(mr) = XCreateWindow( MR_CREATE_DPY(mr), Scr.Root, 0, 0, w, h, 0, Pdepth, InputOutput, Pvisual, valuemask, &attributes); if (MR_CREATE_DPY(mr) != dpy) { /* We *must* synchronize the display here. Otherwise * the request will never be processed. */ XSync(MR_CREATE_DPY(mr), 1); } if (MR_WINDOW(mr) != None) { /* select events for the window from the standard * display */ XSelectInput(dpy, MR_WINDOW(mr), evmask); } XSaveContext(dpy, MR_WINDOW(mr), MenuContext,(caddr_t)mr); } return; } /* * * Generates the window for a menu * */ static void make_menu(MenuRoot *mr, Bool is_tear_off) { MenuSizingParameters msp; Bool has_continuation_menu = False; if (MR_MAPPED_COPIES(mr) > 0) { return; } merge_continuation_menus(mr); do { memset(&msp, 0, sizeof(MenuSizingParameters)); msp.menu = mr; calculate_item_sizes(&msp); /* Call size_menu_horizontally first because it calculated * some values used by size_menu_vertically. */ size_menu_horizontally(&msp); has_continuation_menu = size_menu_vertically(&msp); /* repeat this step if the menu was split */ } while (has_continuation_menu); MR_USED_MINI_ICONS(mr) = msp.used_mini_icons; MR_XANIMATION(mr) = 0; memset(&(MR_DYNAMIC_FLAGS(mr)), 0, sizeof(MR_DYNAMIC_FLAGS(mr))); /* create a new window for the menu */ make_menu_window(mr, is_tear_off); MR_IS_UPDATED(mr) = 0; return; } /* Make sure the menu is properly rebuilt when the style or the menu has * changed. */ static void update_menu(MenuRoot *mr, MenuParameters *pmp) { int sw; int sh; Bool has_screen_size_changed = False; fscreen_scr_arg fscr; if (MST_IS_UPDATED(mr)) { /* The menu style has changed. */ MenuRoot *menu; for (menu = Menus.all; menu; menu = MR_NEXT_MENU(menu)) { if (MR_STYLE(menu) == MR_STYLE(mr)) { /* Mark all other menus with the same style as * changed. */ MR_IS_UPDATED(menu) = 1; } } MST_IS_UPDATED(mr) = 0; } fscr.xypos.x = pmp->screen_origin_x; fscr.xypos.y = pmp->screen_origin_y; FScreenGetScrRect(&fscr, FSCREEN_XYPOS, &JunkX, &JunkY, &sw, &sh); if (sw != MR_SCREEN_WIDTH(mr) || sh != MR_SCREEN_HEIGHT(mr)) { has_screen_size_changed = True; MR_SCREEN_WIDTH(mr) = sw; MR_SCREEN_HEIGHT(mr) = sh; } if (MR_IS_UPDATED(mr) || has_screen_size_changed) { /* The menu or the screen dimensions have changed. We have to * re-make it. */ make_menu(mr, False); } return; } /* * * Procedure: * copy_menu_root - creates a new instance of an existing menu * * Returned Value: * (MenuRoot *) * * Inputs: * mr - the MenuRoot structure of the existing menu * */ static MenuRoot *copy_menu_root(MenuRoot *mr) { MenuRoot *tmp; if (!mr || MR_COPIES(mr) >= MAX_MENU_COPIES) { return NULL; } tmp = (MenuRoot *)safemalloc(sizeof(MenuRoot)); tmp->d = (MenuRootDynamic *)safemalloc(sizeof(MenuRootDynamic)); memset(tmp->d, 0, sizeof(MenuRootDynamic)); tmp->s = mr->s; MR_COPIES(mr)++; MR_ORIGINAL_MENU(tmp) = MR_ORIGINAL_MENU(mr); MR_CONTINUATION_MENU(tmp) = MR_CONTINUATION_MENU(mr); MR_NEXT_MENU(tmp) = MR_NEXT_MENU(mr); MR_NEXT_MENU(mr) = tmp; MR_WINDOW(tmp) = None; memset(&(MR_DYNAMIC_FLAGS(tmp)), 0, sizeof(MR_DYNAMIC_FLAGS(tmp))); return tmp; } /* * * Procedure: * clone_menu - duplicates an existing menu in newly allocated memory. The new menu is independent of the original. * * Returned Value: * (MenuRoot *) * * Inputs: * mr - the MenuRoot structure of the existing menu * */ static void clone_menu_root_static( MenuRoot *dest_mr, MenuRoot *src_mr) { dest_mr->s = (MenuRootStatic *)safemalloc(sizeof(MenuRootStatic)); /* copy everything */ memcpy(dest_mr->s, src_mr->s, sizeof(MenuRootStatic)); /* special treatment for a few parts */ if (MR_NAME(src_mr) != NULL) { MR_NAME(dest_mr) = safestrdup(MR_NAME(src_mr)); } MR_COPIES(dest_mr) = 1; MR_MAPPED_COPIES(dest_mr) = 0; MR_POPUP_ACTION(dest_mr) = NULL; MR_POPDOWN_ACTION(dest_mr) = NULL; if (MR_MISSING_SUBMENU_FUNC(src_mr)) { MR_MISSING_SUBMENU_FUNC(dest_mr) = safestrdup(MR_MISSING_SUBMENU_FUNC(src_mr)); } if (MR_HAS_SIDECOLOR(src_mr)) { MR_SIDECOLOR(dest_mr) = fvwmlib_clone_color(MR_SIDECOLOR(src_mr)); } MR_SIDEPIC(dest_mr) = PCloneFvwmPicture(MR_SIDEPIC(src_mr)); clone_menu_item_list(dest_mr, src_mr); return; } static MenuRoot *clone_menu(MenuRoot *mr) { MenuRoot *new_mr; new_mr = (MenuRoot *)safemalloc(sizeof(MenuRoot)); new_mr->d = (MenuRootDynamic *)safemalloc(sizeof(MenuRootDynamic)); memset(new_mr->d, 0, sizeof(MenuRootDynamic)); clone_menu_root_static(new_mr, mr); return new_mr; } /* ---------------------------- position hints ----------------------------- */ static int float_to_int_with_tolerance(float f) { int low; if (f < 0) { low = (int)(f - ROUNDING_ERROR_TOLERANCE); } else { low = (int)(f + ROUNDING_ERROR_TOLERANCE); } if ((int)f != low) { return low; } else { return (int)(f); } } static void get_xy_from_position_hints( struct MenuPosHints *ph, int width, int height, int context_width, Bool do_reverse_x, int *ret_x, int *ret_y) { float x_add; float y_add; *ret_x = ph->x; *ret_y = ph->y; if (ph->is_menu_relative) { if (do_reverse_x) { *ret_x -= ph->x_offset; x_add = width * (-1.0 - ph->x_factor) + ph->menu_width * (1.0 - ph->context_x_factor); } else { *ret_x += ph->x_offset; x_add = width * ph->x_factor + ph->menu_width * ph->context_x_factor; } y_add = height * ph->y_factor; } else { x_add = width * ph->x_factor; y_add = height * ph->y_factor; } *ret_x += float_to_int_with_tolerance(x_add); *ret_y += float_to_int_with_tolerance(y_add); return; } /* * Used by get_menu_options * * The vars are named for the x-direction, but this is used for both x and y */ static char *get_one_menu_position_argument( char *action, int x, int w, int *pFinalX, int *x_offset, float *width_factor, float *context_width_factor, Bool *is_menu_relative) { char *token, *orgtoken, *naction; char c; int val; int chars; float fval; float factor = (float)w/100; float x_add = 0; naction = GetNextToken(action, &token); if (token == NULL) { return action; } orgtoken = token; *pFinalX = x; *x_offset = 0; *width_factor = 0.0; *context_width_factor = 0.0; if (sscanf(token,"o%d%n", &val, &chars) >= 1) { fval = val; token += chars; x_add += fval*factor; *width_factor -= fval / 100.0; *context_width_factor += fval / 100.0; } else if (token[0] == 'c') { token++; x_add += ((float)w) / 2.0; *width_factor -= 0.5; *context_width_factor += 0.5; } while (*token != 0) { if (sscanf(token,"%d%n", &val, &chars) < 1) { naction = action; break; } fval = (float)val; token += chars; if (sscanf(token,"%c", &c) == 1) { switch (c) { case 'm': token++; *width_factor += fval / 100.0; *is_menu_relative = True; break; case 'p': token++; x_add += val; *x_offset += val; break; default: x_add += fval * factor; *context_width_factor += fval / 100.0; break; } } else { x_add += fval * factor; *context_width_factor += fval / 100.0; } } *pFinalX += float_to_int_with_tolerance(x_add); free(orgtoken); return naction; } /* Returns the menu options for the menu that a given menu item pops up */ static void get_popup_options( MenuParameters *pmp, MenuItem *mi, MenuOptions *pops) { if (!mi) { return; } pops->flags.has_poshints = 0; pops->pos_hints.has_screen_origin = True; pops->pos_hints.screen_origin_x = pmp->screen_origin_x; pops->pos_hints.screen_origin_y = pmp->screen_origin_y; /* just look past "Popup " in the action */ get_menu_options( SkipNTokens(MI_ACTION(mi), 2), MR_WINDOW(pmp->menu), NULL, NULL, pmp->menu, mi, pops); return; } /* ---------------------------- menu painting functions --------------------- */ static void clear_expose_menu_area(Window win, XEvent *e) { if (e == NULL) { XClearWindow(dpy, win); } else { XClearArea( dpy, win, e->xexpose.x, e->xexpose.y, e->xexpose.width, e->xexpose.height, False); } return; } /* * * Draws a picture on the left side of the menu * What about a SidePic Colorset ? (olicha 2002-08-21) * */ static void paint_side_pic(MenuRoot *mr, XEvent *pevent) { GC gc; FvwmPicture *sidePic; int ys; int yt; int h; int bw = MST_BORDER_WIDTH(mr); if (MR_SIDEPIC(mr)) { sidePic = MR_SIDEPIC(mr); } else if (MST_SIDEPIC(mr)) { sidePic = MST_SIDEPIC(mr); } else { return; } if (Pdepth < 2) { /* ? */ gc = SHADOW_GC(MST_MENU_INACTIVE_GCS(mr)); } else { gc = FORE_GC(MST_MENU_INACTIVE_GCS(mr)); } if (sidePic->height > MR_HEIGHT(mr) - 2 * bw) { h = MR_HEIGHT(mr) - 2 * bw; ys = sidePic->height - h; yt = bw; } else { h = sidePic->height; ys = 0; yt = MR_HEIGHT(mr) - bw - sidePic->height; } if (pevent != NULL && pevent->type == Expose) { if ( pevent->xexpose.x + pevent->xexpose.width < MR_SIDEPIC_X_OFFSET(mr) || pevent->xexpose.x >= MR_SIDEPIC_X_OFFSET(mr) + sidePic->width) { /* out of x-range for side bar */ return; } if ( pevent->xexpose.y + pevent->xexpose.height < bw || pevent->xexpose.y >= bw + MR_HEIGHT(mr)) { /* in the border */ return; } if ( !(MR_HAS_SIDECOLOR(mr) || MST_HAS_SIDE_COLOR(mr)) && pevent->xexpose.y + pevent->xexpose.height < yt) { /* outside picture and no background */ return; } } if (MR_HAS_SIDECOLOR(mr)) { Globalgcv.foreground = MR_SIDECOLOR(mr); } else if (MST_HAS_SIDE_COLOR(mr)) { Globalgcv.foreground = MST_SIDE_COLOR(mr); } if (MR_HAS_SIDECOLOR(mr) || MST_HAS_SIDE_COLOR(mr)) { Globalgcm = GCForeground; XChangeGC(dpy, Scr.ScratchGC1, Globalgcm, &Globalgcv); XFillRectangle( dpy, MR_WINDOW(mr), Scr.ScratchGC1, MR_SIDEPIC_X_OFFSET(mr), bw, sidePic->width, MR_HEIGHT(mr) - 2 * bw); } else if (sidePic->alpha != None) { XClearArea( dpy, MR_WINDOW(mr), MR_SIDEPIC_X_OFFSET(mr), yt, sidePic->width, h, False); } PGraphicsRenderPicture( dpy, MR_WINDOW(mr), sidePic, 0, MR_WINDOW(mr), gc, Scr.MonoGC, Scr.AlphaGC, 0, ys, sidePic->width, h, MR_SIDEPIC_X_OFFSET(mr), yt, sidePic->width, h, False); return; } static Bool paint_menu_gradient_background( MenuRoot *mr, XEvent *pevent) { MenuStyle *ms = MR_STYLE(mr); int bw = MST_BORDER_WIDTH(mr); XRectangle bounds; Pixmap pmap; GC pmapgc; XGCValues gcv; unsigned long gcm = GCLineWidth; int switcher = -1; Bool do_clear = False; gcv.line_width = 1; bounds.x = bw; bounds.y = bw; bounds.width = MR_WIDTH(mr) - bw; bounds.height = MR_HEIGHT(mr) - bw; /* H, V, D and B gradients are optimized and have * their own code here. (if no dither) */ if (!ST_FACE(ms).u.grad.do_dither) { switcher = ST_FACE(ms).gradient_type; } switch (switcher) { case H_GRADIENT: if (MR_IS_BACKGROUND_SET(mr) == False) { register int i; register int dw; pmap = XCreatePixmap( dpy, MR_WINDOW(mr), MR_WIDTH(mr), DEFAULT_MENU_GRADIENT_PIXMAP_THICKNESS, Pdepth); pmapgc = fvwmlib_XCreateGC(dpy, pmap, gcm, &gcv); dw = (float) (bounds.width / ST_FACE(ms).u.grad.npixels) + 1; for (i = 0; i < ST_FACE(ms).u.grad.npixels; i++) { int x; x = i * bounds.width / ST_FACE(ms).u.grad.npixels; XSetForeground( dpy, pmapgc, ST_FACE(ms).u.grad.xcs[i].pixel); XFillRectangle( dpy, pmap, pmapgc, x, 0, dw, DEFAULT_MENU_GRADIENT_PIXMAP_THICKNESS); } XSetWindowBackgroundPixmap(dpy, MR_WINDOW(mr), pmap); XFreeGC(dpy,pmapgc); XFreePixmap(dpy,pmap); MR_IS_BACKGROUND_SET(mr) = True; } do_clear = True; break; case V_GRADIENT: if (MR_IS_BACKGROUND_SET(mr) == False) { register int i; register int dh; static int best_tile_width = 0; int junk; if (best_tile_width == 0) { int tw = DEFAULT_MENU_GRADIENT_PIXMAP_THICKNESS; if (!XQueryBestTile( dpy, Scr.screen, tw, tw, (unsigned int*)&best_tile_width, (unsigned int*)&junk)) { /* call failed, use default and risk a * screwed up tile */ best_tile_width = tw; } } pmap = XCreatePixmap( dpy, MR_WINDOW(mr), best_tile_width, MR_HEIGHT(mr), Pdepth); pmapgc = fvwmlib_XCreateGC(dpy, pmap, gcm, &gcv); dh = (float) (bounds.height / ST_FACE(ms).u.grad.npixels) + 1; for (i = 0; i < ST_FACE(ms).u.grad.npixels; i++) { int y; y = i * bounds.height / ST_FACE(ms).u.grad.npixels; XSetForeground( dpy, pmapgc, ST_FACE(ms).u.grad.xcs[i].pixel); XFillRectangle( dpy, pmap, pmapgc, 0, y, best_tile_width, dh); } XSetWindowBackgroundPixmap(dpy, MR_WINDOW(mr), pmap); XFreeGC(dpy,pmapgc); XFreePixmap(dpy,pmap); MR_IS_BACKGROUND_SET(mr) = True; } do_clear = True; break; case D_GRADIENT: case B_GRADIENT: { register int i = 0, numLines; int cindex = -1; XRectangle r; if (pevent) { r.x = pevent->xexpose.x; r.y = pevent->xexpose.y; r.width = pevent->xexpose.width; r.height = pevent->xexpose.height; } else { r.x = bw; r.y = bw; r.width = MR_WIDTH(mr) - 2 * bw; r.height = MR_HEIGHT(mr) - 2 * bw; } XSetClipRectangles( dpy, Scr.TransMaskGC, 0, 0, &r, 1, Unsorted); numLines = MR_WIDTH(mr) + MR_HEIGHT(mr) - 2 * bw; for (i = 0; i < numLines; i++) { if ((int)(i * ST_FACE(ms).u.grad.npixels / numLines) > cindex) { /* pick the next colour (skip if necc.) */ cindex = i * ST_FACE(ms).u.grad.npixels / numLines; XSetForeground( dpy, Scr.TransMaskGC, ST_FACE(ms).u.grad.xcs[cindex].pixel); } if (ST_FACE(ms).gradient_type == D_GRADIENT) { XDrawLine(dpy, MR_WINDOW(mr), Scr.TransMaskGC, 0, i, i, 0); } else /* B_GRADIENT */ { XDrawLine(dpy, MR_WINDOW(mr), Scr.TransMaskGC, 0, MR_HEIGHT(mr) - 1 - i, i, MR_HEIGHT(mr) - 1); } } } XSetClipMask(dpy, Scr.TransMaskGC, None); break; default: if (MR_IS_BACKGROUND_SET(mr) == False) { int g_width; int g_height; /* let library take care of all other gradients */ pmap = XCreatePixmap( dpy, MR_WINDOW(mr), MR_WIDTH(mr), MR_HEIGHT(mr), Pdepth); pmapgc = fvwmlib_XCreateGC(dpy, pmap, gcm, &gcv); /* find out the size the pixmap should be */ CalculateGradientDimensions( dpy, MR_WINDOW(mr), ST_FACE(ms).u.grad.npixels, ST_FACE(ms).gradient_type, ST_FACE(ms).u.grad.do_dither, &g_width, &g_height); /* draw the gradient directly into the window */ CreateGradientPixmap( dpy, MR_WINDOW(mr), pmapgc, ST_FACE(ms).gradient_type, g_width, g_height, ST_FACE(ms).u.grad.npixels, ST_FACE(ms).u.grad.xcs, ST_FACE(ms).u.grad.do_dither, &(MR_STORED_PIXELS(mr).d_pixels), &(MR_STORED_PIXELS(mr).d_npixels), pmap, bw, bw, MR_WIDTH(mr) - bw, MR_HEIGHT(mr) - bw, NULL); XSetWindowBackgroundPixmap(dpy, MR_WINDOW(mr), pmap); XFreeGC(dpy, pmapgc); XFreePixmap(dpy, pmap); MR_IS_BACKGROUND_SET(mr) = True; } do_clear = True; break; } return do_clear; } static Bool paint_menu_pixmap_background( MenuRoot *mr, XEvent *pevent) { MenuStyle *ms = MR_STYLE(mr); int width, height, x, y; int bw = MST_BORDER_WIDTH(mr); FvwmPicture *p; p = ST_FACE(ms).u.p; width = MR_WIDTH(mr) - 2 * bw; height = MR_HEIGHT(mr) - 2 * bw; y = (int)(height - p->height) / 2; x = (int)(width - p->width) / 2; if (x < bw) { x = bw; } if (y < bw) { y = bw; } if (width > p->width) { width = p->width; } if (height > p->height) { height = p->height; } if (width > MR_WIDTH(mr) - x - bw) { width = MR_WIDTH(mr) - x - bw; } if (height > MR_HEIGHT(mr) - y - bw) { height = MR_HEIGHT(mr) - y - bw; } XSetClipMask(dpy, Scr.TransMaskGC, p->mask); XSetClipOrigin(dpy, Scr.TransMaskGC, x, y); XCopyArea( dpy, p->picture, MR_WINDOW(mr), Scr.TransMaskGC, bw, bw, width, height, x, y); return False; } /* * * Procedure: * get_menu_paint_item_parameters - prepares the parameters to be * passed to menuitem_paint(). * * mr - the menu instance that holds the menu item * mi - the menu item to redraw * fw - the FvwmWindow structure to check against allowed functions * */ static void get_menu_paint_item_parameters( MenuPaintItemParameters *mpip, MenuRoot *mr, MenuItem *mi, FvwmWindow *fw, XEvent *pevent, Bool do_redraw_menu_border) { mpip->ms = MR_STYLE(mr); mpip->w = MR_WINDOW(mr); mpip->selected_item = MR_SELECTED_ITEM(mr); mpip->dim = &MR_DIM(mr); mpip->fw = fw; mpip->used_mini_icons = MR_USED_MINI_ICONS(mr); mpip->cb_mr = mr; mpip->cb_reset_bg = paint_menu_gradient_background; mpip->flags.is_first_item = (MR_FIRST_ITEM(mr) == mi); mpip->flags.is_left_triangle = MR_IS_LEFT_TRIANGLE(mr); mpip->ev = pevent; return; } /* * * Procedure: * paint_menu - draws the entire menu * */ static void paint_menu( MenuRoot *mr, XEvent *pevent, FvwmWindow *fw) { MenuItem *mi; MenuStyle *ms = MR_STYLE(mr); int bw = MST_BORDER_WIDTH(mr); int relief_thickness = ST_RELIEF_THICKNESS(MR_STYLE(mr)); if (fw && !check_if_fvwm_window_exists(fw)) { fw = NULL; } if (MR_IS_PAINTED(mr) && pevent && (pevent->xexpose.x >= MR_WIDTH(mr) - bw || pevent->xexpose.x + pevent->xexpose.width <= bw || pevent->xexpose.y >= MR_HEIGHT(mr) - bw || pevent->xexpose.y + pevent->xexpose.height <= bw)) { /* Only the border was obscured. Redraw it centrally instead of * redrawing several menu items. */ RelieveRectangle( dpy, MR_WINDOW(mr), 0, 0, MR_WIDTH(mr) - 1, MR_HEIGHT(mr) - 1, (Pdepth < 2) ? SHADOW_GC(MST_MENU_INACTIVE_GCS(mr)) : HILIGHT_GC(MST_MENU_INACTIVE_GCS(mr)), SHADOW_GC(MST_MENU_INACTIVE_GCS(mr)), bw); { return; } } MR_IS_PAINTED(mr) = 1; /* paint the menu background */ if (ms && ST_HAS_MENU_CSET(ms)) { if (MR_IS_BACKGROUND_SET(mr) == False) { SetWindowBackground( dpy, MR_WINDOW(mr), MR_WIDTH(mr), MR_HEIGHT(mr), &Colorset[ST_CSET_MENU(ms)], Pdepth, FORE_GC(ST_MENU_INACTIVE_GCS(ms)), True); MR_IS_BACKGROUND_SET(mr) = True; } } else if (ms) { int type; Bool do_clear = False; type = ST_FACE(ms).type; switch(type) { case SolidMenu: XSetWindowBackground( dpy, MR_WINDOW(mr), MST_FACE(mr).u.back); do_clear = True; break; case GradientMenu: do_clear = paint_menu_gradient_background(mr, pevent); break; case PixmapMenu: do_clear = paint_menu_pixmap_background(mr, pevent); break; case TiledPixmapMenu: XSetWindowBackgroundPixmap( dpy, MR_WINDOW(mr), ST_FACE(ms).u.p->picture); do_clear = True; break; } /* switch(type) */ if (do_clear == True) { clear_expose_menu_area(MR_WINDOW(mr), pevent); } } /* if (ms) */ /* draw the relief */ RelieveRectangle(dpy, MR_WINDOW(mr), 0, 0, MR_WIDTH(mr) - 1, MR_HEIGHT(mr) - 1, (Pdepth < 2) ? SHADOW_GC(MST_MENU_INACTIVE_GCS(mr)) : HILIGHT_GC(MST_MENU_INACTIVE_GCS(mr)), SHADOW_GC(MST_MENU_INACTIVE_GCS(mr)), bw); /* paint the menu items */ for (mi = MR_FIRST_ITEM(mr); mi != NULL; mi = MI_NEXT_ITEM(mi)) { int do_draw = 0; /* be smart about handling the expose, redraw only the entries * that we need to */ if (pevent == NULL) { do_draw = True; } else { register int b_offset; b_offset = MI_Y_OFFSET(mi) + MI_HEIGHT(mi); if (MR_SELECTED_ITEM(mr) == mi) { b_offset += relief_thickness; } if (pevent->xexpose.y < b_offset && (pevent->xexpose.y + pevent->xexpose.height) > MI_Y_OFFSET(mi)) { do_draw = True; } } if (do_draw) { MenuPaintItemParameters mpip; get_menu_paint_item_parameters( &mpip, mr, NULL, fw, pevent, True); mpip.flags.is_first_item = (MR_FIRST_ITEM(mr) == mi); menuitem_paint(mi, &mpip); } } paint_side_pic(mr, pevent); XFlush(dpy); return; } /* Set the selected-ness state of the menuitem passed in */ static void select_menu_item( MenuRoot *mr, MenuItem *mi, Bool select, FvwmWindow *fw) { if (select == True && MR_SELECTED_ITEM(mr) != NULL && MR_SELECTED_ITEM(mr) != mi) { select_menu_item(mr, MR_SELECTED_ITEM(mr), False, fw); } else if (select == False && MR_SELECTED_ITEM(mr) == NULL) { return; } else if (select == True && MR_SELECTED_ITEM(mr) == mi) { return; } if (!MI_IS_SELECTABLE(mi)) { return; } if (select == False) { MI_WAS_DESELECTED(mi) = True; } if (!MST_HAS_MENU_CSET(mr)) { switch (MST_FACE(mr).type) { case GradientMenu: if (select == True) { int iy; int ih; int mw; XEvent e; if (!MR_IS_PAINTED(mr)) { FCheckWeedTypedWindowEvents( dpy, MR_WINDOW(mr), Expose, NULL); paint_menu(mr, NULL, fw); } iy = MI_Y_OFFSET(mi); ih = MI_HEIGHT(mi) + (MI_IS_SELECTABLE(mi) ? MST_RELIEF_THICKNESS(mr) : 0); if (iy < 0) { ih += iy; iy = 0; } mw = MR_WIDTH(mr) - 2 * MST_BORDER_WIDTH(mr); if (iy + ih > MR_HEIGHT(mr)) ih = MR_HEIGHT(mr) - iy; /* grab image */ MR_STORED_ITEM(mr).stored = XCreatePixmap( dpy, Scr.NoFocusWin, mw, ih, Pdepth); XSetGraphicsExposures( dpy, FORE_GC(MST_MENU_INACTIVE_GCS(mr)), True); XSync(dpy, 0); while (FCheckTypedEvent(dpy, NoExpose, &e)) { /* nothing to do here */ } XCopyArea( dpy, MR_WINDOW(mr), MR_STORED_ITEM(mr).stored, FORE_GC(MST_MENU_INACTIVE_GCS(mr)), MST_BORDER_WIDTH(mr), iy, mw, ih, 0, 0); XSync(dpy, 0); if (FCheckTypedEvent(dpy, NoExpose, &e)) { MR_STORED_ITEM(mr).y = iy; MR_STORED_ITEM(mr).width = mw; MR_STORED_ITEM(mr).height = ih; } else { XFreePixmap( dpy, MR_STORED_ITEM(mr).stored); MR_STORED_ITEM(mr).stored = None; MR_STORED_ITEM(mr).width = 0; MR_STORED_ITEM(mr).height = 0; MR_STORED_ITEM(mr).y = 0; } XSetGraphicsExposures( dpy, FORE_GC(MST_MENU_INACTIVE_GCS(mr)), False); } else if (select == False && MR_STORED_ITEM(mr).width != 0) { /* ungrab image */ XCopyArea( dpy, MR_STORED_ITEM(mr).stored, MR_WINDOW(mr), FORE_GC(MST_MENU_INACTIVE_GCS(mr)), 0, 0, MR_STORED_ITEM(mr).width, MR_STORED_ITEM(mr).height, MST_BORDER_WIDTH(mr), MR_STORED_ITEM(mr).y); if (MR_STORED_ITEM(mr).stored != None) { XFreePixmap( dpy, MR_STORED_ITEM(mr).stored); } MR_STORED_ITEM(mr).stored = None; MR_STORED_ITEM(mr).width = 0; MR_STORED_ITEM(mr).height = 0; MR_STORED_ITEM(mr).y = 0; } else if (select == False) { XEvent e; FvwmPicture *sidePic = NULL; e.type = Expose; e.xexpose.x = MST_BORDER_WIDTH(mr); e.xexpose.y = MI_Y_OFFSET(mi); e.xexpose.width = MR_WIDTH(mr) - 2 * MST_BORDER_WIDTH(mr); e.xexpose.height = MI_HEIGHT(mi) + (MI_IS_SELECTABLE(mi) ? MST_RELIEF_THICKNESS(mr) : 0); if (MR_SIDEPIC(mr)) { sidePic = MR_SIDEPIC(mr); } else if (MST_SIDEPIC(mr)) { sidePic = MST_SIDEPIC(mr); } if (sidePic) { e.xexpose.width -= sidePic->width; if (MR_SIDEPIC_X_OFFSET(mr) == MST_BORDER_WIDTH(mr)) { e.xexpose.x += sidePic->width; } } MR_SELECTED_ITEM(mr) = (select) ? mi : NULL; paint_menu(mr, &e, fw); } break; default: if (MR_STORED_ITEM(mr).width != 0) { if (MR_STORED_ITEM(mr).stored != None) { XFreePixmap( dpy, MR_STORED_ITEM(mr).stored); } MR_STORED_ITEM(mr).stored = None; MR_STORED_ITEM(mr).width = 0; MR_STORED_ITEM(mr).height = 0; MR_STORED_ITEM(mr).y = 0; } break; } /* switch */ } /* if */ if (fw && !check_if_fvwm_window_exists(fw)) { fw = NULL; } MR_SELECTED_ITEM(mr) = (select) ? mi : NULL; if (MR_IS_PAINTED(mr)) { MenuPaintItemParameters mpip; get_menu_paint_item_parameters(&mpip, mr, mi, fw, NULL, False); menuitem_paint(mi, &mpip); } return; } /* ---------------------------- popping menu up or down -------------------- */ static int get_left_popup_x_position(MenuRoot *mr, MenuRoot *submenu, int x) { if (MST_USE_LEFT_SUBMENUS(mr)) { return (x - MST_POPUP_OFFSET_ADD(mr) - MR_WIDTH(submenu) + MR_WIDTH(mr) * (100 - MST_POPUP_OFFSET_PERCENT(mr)) / 100); } else { return (x - MR_WIDTH(submenu) + MST_BORDER_WIDTH(mr)); } } static int get_right_popup_x_position(MenuRoot *mr, MenuRoot *submenu, int x) { if (MST_USE_LEFT_SUBMENUS(mr)) { return (x + MR_WIDTH(mr) - MST_BORDER_WIDTH(mr)); } else { return (x + MR_WIDTH(mr) * MST_POPUP_OFFSET_PERCENT(mr) / 100 + MST_POPUP_OFFSET_ADD(mr)); } } static void get_prefered_popup_position( MenuRoot *mr, MenuRoot *submenu, int *px, int *py, Bool *pprefer_left_submenus) { int menu_x, menu_y; MenuItem *mi = NULL; if (!menu_get_geometry( mr, &JunkRoot, &menu_x, &menu_y, &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth)) { *px = 0; *py = 0; *pprefer_left_submenus = False; fvwm_msg(ERR, "get_prefered_popup_position", "can't get geometry of menu %s", MR_NAME(mr)); return; } /* set the direction flag */ *pprefer_left_submenus = (MR_HAS_POPPED_UP_LEFT(mr) || (MST_USE_LEFT_SUBMENUS(mr) && !MR_HAS_POPPED_UP_RIGHT(mr))); /* get the x position */ if (*pprefer_left_submenus) { *px = get_left_popup_x_position(mr, submenu, menu_x); } else { *px = get_right_popup_x_position(mr, submenu, menu_x); } /* get the y position */ if (MR_SELECTED_ITEM(mr)) { mi = MR_SELECTED_ITEM(mr); } if (mi) { *py = menu_y + MI_Y_OFFSET(mi) - MST_BORDER_WIDTH(mr) + MST_RELIEF_THICKNESS(mr); } else { *py = menu_y; } } static int do_menus_overlap( MenuRoot *mr, int x, int y, int width, int height, int h_tolerance, int v_tolerance, int s_tolerance, Bool allow_popup_offset_tolerance) { int prior_x, prior_y, x_overlap; int prior_width, prior_height; if (mr == NULL) { return 0; } if (!menu_get_geometry( mr, &JunkRoot,&prior_x,&prior_y, &prior_width, &prior_height, &JunkBW, &JunkDepth)) { return 0; } x_overlap = 0; if (allow_popup_offset_tolerance) { if (MST_POPUP_OFFSET_ADD(mr) < 0) { s_tolerance = -MST_POPUP_OFFSET_ADD(mr); } if (MST_USE_LEFT_SUBMENUS(mr)) { prior_x += (100 - MST_POPUP_OFFSET_PERCENT(mr)) / 100; } else { prior_width *= (float)(MST_POPUP_OFFSET_PERCENT(mr)) / 100.0; } } if (MST_USE_LEFT_SUBMENUS(mr)) { int t = s_tolerance; s_tolerance = h_tolerance; h_tolerance = t; } if (y < prior_y + prior_height - v_tolerance && prior_y < y + height - v_tolerance && x < prior_x + prior_width - s_tolerance && prior_x < x + width - h_tolerance) { x_overlap = x - prior_x; if (x <= prior_x) { x_overlap--; } } return x_overlap; } /* * * Procedure: * pop_menu_up - pop up a pull down menu * * Inputs: * x, y - location of upper left of menu * do_warp_to_item - warp pointer to the first item after title * pops - pointer to the menu options for new menu * */ static int pop_menu_up( MenuRoot **pmenu, MenuParameters *pmp, MenuRoot *parent_menu, MenuItem *parent_item, const exec_context_t **pexc, int x, int y, Bool prefer_left_submenu, Bool do_warp_to_item, MenuOptions *pops, Bool *ret_overlap, Window popdown_window) { Bool do_warp_to_title = False; int x_overlap = 0; int x_clipped_overlap; MenuRoot *mrMi; MenuRoot *mr; FvwmWindow *fw; int context; int bw = 0; int bwp = 0; int prev_x; int prev_y; int prev_width; int prev_height; unsigned int event_mask; int scr_x, scr_y; int scr_w, scr_h; mr = *pmenu; if (!mr || (MR_MAPPED_COPIES(mr) > 0 && MR_COPIES(mr) >= MAX_MENU_COPIES)) { return False; } /* * handle dynamic menu actions */ /* First of all, execute the popup action (if defined). */ if (MR_POPUP_ACTION(mr)) { char *menu_name; saved_pos_hints pos_hints; Bool is_busy_grabbed = False; int mapped_copies = MR_MAPPED_COPIES(mr); /* save variables that we still need but that may be * overwritten */ menu_name = safestrdup(MR_NAME(mr)); pos_hints = last_saved_pos_hints; if (Scr.BusyCursor & BUSY_DYNAMICMENU) { is_busy_grabbed = GrabEm(CRS_WAIT, GRAB_BUSYMENU); } /* Execute the action */ __menu_execute_function(pmp->pexc, MR_POPUP_ACTION(mr)); if (is_busy_grabbed) { UngrabEm(GRAB_BUSYMENU); } /* restore the stuff we saved */ last_saved_pos_hints = pos_hints; if (mapped_copies == 0) { /* Now let's see if the menu still exists. It may have * been destroyed and recreated, so we have to look for * a menu with the saved name. menus_find_menu() always * returns the original menu, not one of its copies, so * below logic would fail miserably if used with a menu * copy. On the other hand, menu copies can't be * deleted within a dynamic popup action, so just * ignore this case. */ *pmenu = menus_find_menu(menu_name); if (menu_name) { free(menu_name); } mr = *pmenu; } } if (mr) { update_menu(mr, pmp); } if (mr == NULL || MR_FIRST_ITEM(mr) == NULL || MR_ITEMS(mr) == 0) { /* The menu deleted itself or all its items or it has been * empty from the start. */ return False; } fw = (*pexc)->w.fw; if (fw && !check_if_fvwm_window_exists(fw)) { fw = NULL; } context = (*pexc)->w.wcontext; /* * Create a new menu instance (if necessary) */ if (MR_MAPPED_COPIES(mr) > 0) { /* create a new instance of the menu */ *pmenu = copy_menu_root(*pmenu); if (!*pmenu) { return False; } make_menu_window(*pmenu, False); mr = *pmenu; } /* * Evaluate position hints */ /* calculate position from position hints if available */ if (pops->flags.has_poshints && !last_saved_pos_hints.flags.do_ignore_pos_hints) { get_xy_from_position_hints( &(pops->pos_hints), MR_WIDTH(mr), MR_HEIGHT(mr), (parent_menu) ? MR_WIDTH(parent_menu) : 0, prefer_left_submenu, &x, &y); } /* * Initialise new menu */ MR_PARENT_MENU(mr) = parent_menu; MR_PARENT_ITEM(mr) = parent_item; MR_IS_PAINTED(mr) = 0; MR_IS_LEFT(mr) = 0; MR_IS_RIGHT(mr) = 0; MR_IS_UP(mr) = 0; MR_IS_DOWN(mr) = 0; MR_XANIMATION(mr) = 0; InstallFvwmColormap(); /* * Handle popups from button clicks on buttons in the title bar, * or the title bar itself. Position hints override this. */ if (!pops->flags.has_poshints && fw && parent_menu == NULL && pmp->flags.is_first_root_menu) { int cx; int cy; int gx; int gy; Bool has_context; rectangle button_g; has_context = get_title_button_geometry( fw, &button_g, context); if (has_context) { fscreen_scr_arg fscr; get_title_gravity_factors(fw, &gx, &gy); cx = button_g.x + button_g.width / 2; cy = button_g.y + button_g.height / 2; if (gx != 0) { x = button_g.x + (gx == 1) * button_g.width - (gx == -1) * MR_WIDTH(mr); } if (gy != 0) { y = button_g.y + (gy == 1) * button_g.height - (gy == -1) * MR_HEIGHT(mr); } if (gx == 0 && x < button_g.x) { x = button_g.x; } else if (gx == 0 && x + MR_WIDTH(mr) >= button_g.x + button_g.width) { x = button_g.x + button_g.width - MR_WIDTH(mr); } if (gy == 0 && y < button_g.y) { y = button_g.y; } else if (gy == 0 && y + MR_HEIGHT(mr) >= button_g.y + button_g.height) { y = button_g.y + button_g.height - MR_HEIGHT(mr); } pops->pos_hints.has_screen_origin = True; fscr.xypos.x = cx; fscr.xypos.y = cy; if (FScreenGetScrRect( &fscr, FSCREEN_XYPOS, &JunkX, &JunkY, &JunkWidth, &JunkHeight)) { /* use current cx/cy */ } else if (FQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, &cx, &cy, &JunkX, &JunkY, &JunkMask)) { /* use pointer's position */ } else { cx = -1; cy = -1; } pops->pos_hints.screen_origin_x = cx; pops->pos_hints.screen_origin_y = cy; } } /* if (pops->flags.has_poshints) */ /* * Clip to screen */ { fscreen_scr_arg fscr; fscr.xypos.x = pops->pos_hints.screen_origin_x; fscr.xypos.y = pops->pos_hints.screen_origin_y; /* clip to screen */ FScreenClipToScreen( &fscr, FSCREEN_XYPOS, &x, &y, MR_WIDTH(mr), MR_HEIGHT(mr)); /* "this" screen is defined -- so get its coords for future * reference */ FScreenGetScrRect( &fscr, FSCREEN_XYPOS, &scr_x, &scr_y, &scr_w, &scr_h); } if (parent_menu) { bw = MST_BORDER_WIDTH(mr); bwp = MST_BORDER_WIDTH(parent_menu); x_overlap = do_menus_overlap( parent_menu, x, y, MR_WIDTH(mr), MR_HEIGHT(mr), bwp, bwp, bwp, True); } /* * Calculate position and animate menus */ if (parent_menu == NULL || !menu_get_geometry( parent_menu, &JunkRoot, &prev_x, &prev_y, &prev_width, &prev_height, &JunkBW, &JunkDepth)) { MR_HAS_POPPED_UP_LEFT(mr) = 0; MR_HAS_POPPED_UP_RIGHT(mr) = 0; } else { int left_x; int right_x; Bool use_left_submenus = MST_USE_LEFT_SUBMENUS(mr); MenuRepaintTransparentParameters mrtp; Bool transparent_bg = False; /* check if menus overlap */ x_clipped_overlap = do_menus_overlap( parent_menu, x, y, MR_WIDTH(mr), MR_HEIGHT(mr), bwp, bwp, bwp, True); if (x_clipped_overlap && (!pops->flags.has_poshints || pops->pos_hints.is_relative == False || x_overlap == 0)) { /* menus do overlap, but do not reposition if overlap * was caused by relative positioning hints */ left_x = get_left_popup_x_position( parent_menu, mr, prev_x); right_x = get_right_popup_x_position( parent_menu, mr, prev_x); if (use_left_submenus) { if (left_x + MR_WIDTH(mr) < prev_x + bwp) { left_x = prev_x + bwp - MR_WIDTH(mr); } } else { if (right_x > prev_x + prev_width - bwp) { right_x = prev_x + prev_width - bwp; } } /* * Animate parent menu */ if (MST_IS_ANIMATED(mr)) { /* animate previous out of the way */ int a_left_x; int a_right_x; int end_x; Window w; if (use_left_submenus) { if (prev_x - left_x < MR_WIDTH(mr)) { a_right_x = x + (prev_x - left_x); } else { a_right_x = x + MR_WIDTH(mr) - bw; } a_left_x = x - MR_WIDTH(parent_menu); } else { if (right_x - prev_x < prev_width) { a_left_x = x + (prev_x - right_x); } else { a_left_x = x - prev_width + bw; } a_right_x = x + MR_WIDTH(mr); } if (prefer_left_submenu) { /* popup menu is left of old menu, try * to move prior menu right */ if (a_right_x + prev_width <= scr_x + scr_w) { end_x = a_right_x; } else if (a_left_x >= scr_x) { end_x = a_left_x; } else { end_x = scr_x + scr_w - prev_width; } } else { /* popup menu is right of old menu, try * to move prior menu left */ if (a_left_x >= scr_x) { end_x = a_left_x; } else if (a_right_x + prev_width <= scr_x + scr_w) { end_x = a_right_x; } else { end_x = scr_x; } } if (end_x == a_left_x || end_x == 0) { MR_HAS_POPPED_UP_LEFT(mr) = 0; MR_HAS_POPPED_UP_RIGHT(mr) = 1; } else { MR_HAS_POPPED_UP_LEFT(mr) = 1; MR_HAS_POPPED_UP_RIGHT(mr) = 0; } MR_XANIMATION(parent_menu) += end_x - prev_x; if (ST_HAS_MENU_CSET(MR_STYLE(parent_menu)) && CSET_IS_TRANSPARENT( ST_CSET_MENU( MR_STYLE(parent_menu)))) { transparent_bg = True; get_menu_repaint_transparent_parameters( &mrtp, parent_menu, fw); } if (MR_IS_TEAR_OFF_MENU(parent_menu)) { int cx; int cy; w = FW_W_FRAME( pmp->tear_off_root_menu_window ); if (XGetGeometry( dpy, w, &JunkRoot, &cx, &cy, (unsigned int*)&JunkWidth, (unsigned int*)&JunkHeight, (unsigned int*)&JunkBW, (unsigned int*)&JunkDepth)) { end_x += (cx - prev_x ); prev_x = cx; prev_y = cy; } } else { w = MR_WINDOW(parent_menu); } AnimatedMoveOfWindow( w, prev_x, prev_y, end_x, prev_y, True, -1, NULL, (transparent_bg)? &mrtp:NULL); } /* if (MST_IS_ANIMATED(mr)) */ /* * Try the other side of the parent menu */ else if (!pops->flags.is_fixed) { Bool may_use_left; Bool may_use_right; Bool do_use_left; Bool use_left_as_last_resort; use_left_as_last_resort = (left_x > scr_x + scr_w - right_x - MR_WIDTH(mr)); may_use_left = (left_x >= scr_x); may_use_right = (right_x + MR_WIDTH(mr) <= scr_x + scr_w); if (!may_use_left && !may_use_right) { /* If everything goes wrong, put the * submenu on the side with more free * space. */ do_use_left = use_left_as_last_resort; } else if (may_use_left && (prefer_left_submenu || !may_use_right)) { do_use_left = True; } else { do_use_left = False; } x = (do_use_left) ? left_x : right_x; MR_HAS_POPPED_UP_LEFT(mr) = do_use_left; MR_HAS_POPPED_UP_RIGHT(mr) = !do_use_left; /* Force the menu onto the screen, but leave at * least PARENT_MENU_FORCE_VISIBLE_WIDTH pixels * of the parent menu visible */ if (x + MR_WIDTH(mr) > scr_x + scr_w) { int d = x + MR_WIDTH(mr) - (scr_x + scr_w); int c; if (prev_width >= PARENT_MENU_FORCE_VISIBLE_WIDTH) { c = PARENT_MENU_FORCE_VISIBLE_WIDTH + prev_x; } else { c = prev_x + prev_width; } if (x - c >= d || x <= prev_x) { x -= d; } else if (x > c) { x = c; } } if (x < scr_x) { int c = prev_width - PARENT_MENU_FORCE_VISIBLE_WIDTH; if (c < 0) { c = 0; } if (scr_x - x > c) { x += c; } else { x = scr_x; } } } /* else if (non-overlapping menu style) */ } /* if (x_clipped_overlap && ...) */ else { MR_HAS_POPPED_UP_LEFT(mr) = prefer_left_submenu; MR_HAS_POPPED_UP_RIGHT(mr) = !prefer_left_submenu; } if (x < prev_x) { MR_IS_LEFT(mr) = 1; } if (x + MR_WIDTH(mr) > prev_x + prev_width) { MR_IS_RIGHT(mr) = 1; } if (y < prev_y) { MR_IS_UP(mr) = 1; } if (y + MR_HEIGHT(mr) > prev_y + prev_height) { MR_IS_DOWN(mr) = 1; } if (!MR_IS_LEFT(mr) && !MR_IS_RIGHT(mr)) { MR_IS_LEFT(mr) = 1; MR_IS_RIGHT(mr) = 1; } } /* if (parent_menu) */ /* * Make sure we have the correct events selected */ if (pmp->tear_off_root_menu_window == NULL) { /* normal menus and sub menus */ event_mask = XEVMASK_MENUW; } else if (parent_menu == NULL) { /* tear off menu needs more events */ event_mask = XEVMASK_TEAR_OFF_MENUW; } else { /* sub menus of tear off menus need LeaveNotify */ event_mask = XEVMASK_TEAR_OFF_SUBMENUW; } /* * Pop up the menu */ XMoveWindow(dpy, MR_WINDOW(mr), x, y); XSelectInput(dpy, MR_WINDOW(mr), event_mask); XMapRaised(dpy, MR_WINDOW(mr)); if (popdown_window) XUnmapWindow(dpy, popdown_window); XFlush(dpy); MR_MAPPED_COPIES(mr)++; MST_USAGE_COUNT(mr)++; if (ret_overlap) { *ret_overlap = do_menus_overlap( parent_menu, x, y, MR_WIDTH(mr), MR_HEIGHT(mr), 0, 0, 0, False) ? True : False; } /* * Warp the pointer */ if (!do_warp_to_item && parent_menu != NULL) { MenuItem *mi; mi = find_entry(pmp, NULL, &mrMi, None, -1, -1); if (mi && mrMi == mr && mi != MR_FIRST_ITEM(mrMi)) { /* pointer is on an item of the popup */ if (MST_DO_WARP_TO_TITLE(mr)) { /* warp pointer if not on a root menu */ do_warp_to_title = True; } } } /* if (!do_warp_to_item) */ if (pops->flags.do_not_warp) { do_warp_to_title = False; } else if (pops->flags.do_warp_title) { do_warp_to_title = True; } if (pops->flags.has_poshints && !last_saved_pos_hints.flags.do_ignore_pos_hints && pops->flags.do_warp_title) { do_warp_to_title = True; } if (do_warp_to_item) { /* also warp */ MR_SELECTED_ITEM(mr) = NULL; warp_pointer_to_item( mr, MR_FIRST_ITEM(mr), True /* skip Title */); select_menu_item(mr, MR_SELECTED_ITEM(mr), True, fw); } else if (do_warp_to_title) { /* Warp pointer to middle of top line, since we don't * want the user to come up directly on an option */ warp_pointer_to_title(mr); } return True; } /* * * Procedure: * pop_menu_down - unhighlight the current menu selection and * take down the menus * * mr - menu to pop down; this pointer is invalid after the function * returns. Don't use it anymore! * parent - the menu that has spawned mr (may be NULL). this is * used to see if mr was spawned by itself on some level. * this is a hack to allow specifying 'Popup foo' within * menu foo. You must use the MenuRoot that is currently * being processed here. DO NOT USE MR_PARENT_MENU(mr) here! * */ static void pop_menu_down(MenuRoot **pmr, MenuParameters *pmp) { MenuItem *mi; assert(*pmr); memset(&(MR_DYNAMIC_FLAGS(*pmr)), 0, sizeof(MR_DYNAMIC_FLAGS(*pmr))); XUnmapWindow(dpy, MR_WINDOW(*pmr)); MR_MAPPED_COPIES(*pmr)--; MST_USAGE_COUNT(*pmr)--; UninstallFvwmColormap(); XFlush(dpy); if ((mi = MR_SELECTED_ITEM(*pmr)) != NULL) { select_menu_item(*pmr, mi, False, (*pmp->pexc)->w.fw); } if (MR_STORED_PIXELS(*pmr).d_pixels != NULL) { PictureFreeColors( dpy, Pcmap, MR_STORED_PIXELS(*pmr).d_pixels, MR_STORED_PIXELS(*pmr).d_npixels, 0, False); free(MR_STORED_PIXELS(*pmr).d_pixels); MR_STORED_PIXELS(*pmr).d_pixels = NULL; } if (MR_COPIES(*pmr) > 1) { /* delete this instance of the menu */ DestroyMenu(*pmr, False, False); } else if (MR_POPDOWN_ACTION(*pmr)) { /* Finally execute the popdown action (if defined). */ saved_pos_hints pos_hints; /* save variables that we still need but that may be * overwritten */ pos_hints = last_saved_pos_hints; /* Execute the action */ __menu_execute_function(pmp->pexc, MR_POPDOWN_ACTION(*pmr)); /* restore the stuff we saved */ last_saved_pos_hints = pos_hints; } return; } /* * * Procedure: * pop_menu_down_and_repaint_parent - Pops down a menu and repaints the * overlapped portions of the parent menu. This is done only if * *fSubmenuOverlaps is True. *fSubmenuOverlaps is set to False * afterwards. * */ static void pop_menu_down_and_repaint_parent( MenuRoot **pmr, Bool *fSubmenuOverlaps, MenuParameters *pmp) { MenuRoot *parent = MR_PARENT_MENU(*pmr); XEvent event; int mr_x; int mr_y; int mr_width; int mr_height; int parent_x; int parent_y; int parent_width; int parent_height; if (*fSubmenuOverlaps && parent) { /* popping down the menu may destroy the menu via the dynamic * popdown action! Thus we must not access *pmr afterwards. */ /* Create a fake event to pass into paint_menu */ event.type = Expose; if (!menu_get_geometry( *pmr, &JunkRoot, &mr_x, &mr_y, &mr_width, &mr_height, &JunkBW, &JunkDepth) || !menu_get_geometry( parent, &JunkRoot, &parent_x, &parent_y, &parent_width, &parent_height, &JunkBW, &JunkDepth)) { pop_menu_down(pmr, pmp); paint_menu(parent, NULL, (*pmp->pexc)->w.fw); } else { pop_menu_down(pmr, pmp); event.xexpose.x = mr_x - parent_x; event.xexpose.width = mr_width; if (event.xexpose.x < 0) { event.xexpose.width += event.xexpose.x; event.xexpose.x = 0; } if (event.xexpose.x + event.xexpose.width > parent_width) { event.xexpose.width = parent_width - event.xexpose.x; } event.xexpose.y = mr_y - parent_y; event.xexpose.height = mr_height; if (event.xexpose.y < 0) { event.xexpose.height += event.xexpose.y; event.xexpose.y = 0; } if (event.xexpose.y + event.xexpose.height > parent_height) { event.xexpose.height = parent_height - event.xexpose.y; } flush_accumulate_expose(MR_WINDOW(parent), &event); paint_menu(parent, &event, (*pmp->pexc)->w.fw); } } else { /* popping down the menu may destroy the menu via the dynamic * popdown action! Thus we must not access *pmr afterwards. */ pop_menu_down(pmr, pmp); } *fSubmenuOverlaps = False; return; } /* ---------------------------- menu main loop ------------------------------ */ static void __mloop_init( MenuParameters *pmp, MenuReturn *pmret, mloop_evh_input_t *in, mloop_evh_data_t *med, mloop_static_info_t *msi, MenuOptions *pops) { memset(in, 0, sizeof(*in)); in->mif.do_force_reposition = 1; memset(med, 0, sizeof(*med)); msi->t0 = fev_get_evtime(); pmret->rc = MENU_NOP; memset(pops, 0, sizeof(*pops)); /* remember where the pointer was so we can tell if it has moved */ if (FQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, &(msi->x_init), &(msi->y_init), &JunkX, &JunkY, &JunkMask) == False) { /* pointer is on a different screen */ msi->x_init = 0; msi->y_init = 0; } /* get the event mask right */ msi->event_mask = (pmp->tear_off_root_menu_window == NULL) ? XEVMASK_MENU : XEVMASK_TEAR_OFF_MENU; return; } static void __mloop_get_event_timeout_loop( MenuParameters *pmp, mloop_evh_input_t *in, mloop_evh_data_t *med, mloop_static_info_t *msi) { XEvent e = *(*pmp->pexc)->x.elast; while (!FPending(dpy) || !FCheckMaskEvent(dpy, msi->event_mask, &e)) { Bool is_popup_timed_out = (MST_POPUP_DELAY(pmp->menu) > 0 && med->popup_delay_10ms++ >= MST_POPUP_DELAY(pmp->menu) + 1); Bool is_popdown_timed_out = (MST_POPDOWN_DELAY(pmp->menu) > 0 && in->mrPopdown && med->popdown_delay_10ms++ >= MST_POPDOWN_DELAY(pmp->menu) + 1); Bool do_fake_motion = False; if (is_popup_timed_out) { med->popup_delay_10ms = MST_POPUP_DELAY(pmp->menu); } if (is_popdown_timed_out) { med->popdown_delay_10ms = MST_POPDOWN_DELAY(pmp->menu); } if ( in->mif.do_force_popup || (is_popup_timed_out && (is_popdown_timed_out || in->mif.is_item_entered_by_key_press || !in->mrPopdown || MST_DO_POPDOWN_IMMEDIATELY(pmp->menu)))) { in->mif.do_popup_now = True; in->mif.do_force_popup = False; do_fake_motion = True; in->mif.is_popped_up_by_timeout = True; is_popdown_timed_out = True; } if ((in->mrPopdown || in->mrPopup) && (is_popdown_timed_out || MST_DO_POPDOWN_IMMEDIATELY(pmp->menu))) { MenuRoot *m = (in->mrPopdown) ? in->mrPopdown : in->mrPopup; if (!m || med->mi != MR_PARENT_ITEM(m)) { in->mif.do_popdown_now = True; do_fake_motion = True; if (MST_DO_POPUP_IMMEDIATELY(pmp->menu)) { in->mif.do_popup_now = True; in->mif.is_popped_up_by_timeout = True; } else if ( !MST_DO_POPUP_IMMEDIATELY(pmp->menu) && in->mif.is_pointer_in_active_item_area) { in->mif.do_popup_now = True; in->mif.is_popped_up_by_timeout = True; } else if ( !MST_DO_POPUP_IMMEDIATELY(pmp->menu) && !MST_DO_POPDOWN_IMMEDIATELY(pmp->menu) && MST_POPUP_DELAY(pmp->menu) <= MST_POPDOWN_DELAY(pmp->menu) && med->popup_delay_10ms == med->popdown_delay_10ms) { in->mif.do_popup_now = True; in->mif.is_popped_up_by_timeout = True; } } } if (in->mif.do_popup_now && med->mi == in->miRemovedSubmenu && !in->mif.is_key_press) { /* prevent popping up the menu again with * RemoveSubemenus */ in->mif.do_popup_now = False; in->mif.do_force_popup = False; do_fake_motion = in->mif.do_popdown_now; in->mif.is_popped_up_by_timeout = False; } if (do_fake_motion) { /* fake a motion event, and set in->mif.do_popup_now */ e.type = MotionNotify; e.xmotion.time = fev_get_evtime(); fev_fake_event(&e); in->mif.is_motion_faked = True; break; } usleep(10000 /* 10 ms*/); } return; } static mloop_ret_code_t __mloop_get_event( MenuParameters *pmp, MenuReturn *pmret, mloop_evh_input_t *in, mloop_evh_data_t *med, mloop_static_info_t *msi) { XEvent e = *(*pmp->pexc)->x.elast; in->mif.do_popup_and_warp = False; in->mif.do_popup_now = False; in->mif.do_popdown_now = False; in->mif.do_propagate_event_into_submenu = False; in->mif.is_key_press = False; in->mif.is_button_release = 0; if (pmp->event_propagate_to_submenu) { /* handle an event that was passed in from the parent menu */ fev_fake_event(pmp->event_propagate_to_submenu); pmp->event_propagate_to_submenu = NULL; } else if (in->mif.do_recycle_event) { in->mif.is_popped_up_by_timeout = False; in->mif.do_recycle_event = 0; if (pmp->menu != pmret->target_menu) { /* the event is for a previous menu, just close this * one */ pmret->rc = MENU_PROPAGATE_EVENT; return MENU_MLOOP_RET_END; } if ((*pmp->pexc)->x.elast->type == KeyPress) { /* since the pointer has been warped since the key was * pressed, fake a different key press position */ if (FQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, &e.xkey.x_root, &e.xkey.y_root, &JunkX, &JunkY, &e.xkey.state) == False) { /* pointer is on a different screen */ e.xkey.x_root = 0; e.xkey.y_root = 0; } fev_fake_event(&e); med->mi = MR_SELECTED_ITEM(pmp->menu); } } else if (pmp->tear_off_root_menu_window != NULL && FCheckTypedWindowEvent( dpy, FW_W_PARENT(pmp->tear_off_root_menu_window), ClientMessage, &e)) { /* Got a ClientMessage for the tear out menu */ } else { if (in->mif.do_force_reposition) { e.type = MotionNotify; e.xmotion.time = fev_get_evtime(); in->mif.is_motion_faked = True; in->mif.do_force_reposition = False; in->mif.is_popped_up_by_timeout = False; fev_fake_event(&e); } else if (!FCheckMaskEvent(dpy, ExposureMask, &e)) { Bool is_popdown_timer_active = False; Bool is_popup_timer_active = False; if (MST_POPDOWN_DELAY(pmp->menu) > 0 && in->mi_with_popup != NULL && in->mi_with_popup != MR_SELECTED_ITEM(pmp->menu)) { is_popdown_timer_active = True; } if (MST_POPUP_DELAY(pmp->menu) > 0 && !in->mif.is_popped_up_by_timeout && in->mi_wants_popup != NULL) { is_popup_timer_active = True; } /* handle exposure events first */ if (in->mif.do_force_popup || in->mif.is_pointer_in_active_item_area || is_popdown_timer_active || is_popup_timer_active) { __mloop_get_event_timeout_loop( pmp, in, med, msi); } else { /* block until there is an event */ FMaskEvent(dpy, msi->event_mask, &e); in->mif.is_popped_up_by_timeout = False; } } else { in->mif.is_popped_up_by_timeout = False; } } in->mif.is_pointer_in_active_item_area = False; if (e.type == MotionNotify) { /* discard any extra motion events before a release */ while (FCheckMaskEvent( dpy, ButtonMotionMask | ButtonReleaseMask, &e) && (e.type != ButtonRelease)) { /* nothing */ } } return MENU_MLOOP_RET_NORMAL; } static mloop_ret_code_t __mloop_handle_event( MenuParameters *pmp, MenuReturn *pmret, double_keypress *pdkp, mloop_evh_input_t *in, mloop_evh_data_t *med, mloop_static_info_t *msi) { MenuRoot *tmrMi; Bool rc; pmret->rc = MENU_NOP; switch ((*pmp->pexc)->x.elast->type) { case ButtonRelease: in->mif.is_button_release = 1; med->mi = find_entry( pmp, &med->x_offset, &med->mrMi, (*pmp->pexc)->x.elast->xbutton.subwindow, (*pmp->pexc)->x.elast->xbutton.x_root, (*pmp->pexc)->x.elast->xbutton.y_root); /* hold the menu up when the button is released * for the first time if released OFF of the menu */ if (pmp->flags.is_sticky && !in->mif.is_motion_first) { in->mif.is_release_first = True; pmp->flags.is_sticky = False; return MENU_MLOOP_RET_LOOP; } if (med->mrMi != NULL) { int menu_x; int menu_y; menu_shortcuts( med->mrMi, pmp, pmret, (*pmp->pexc)->x.elast, &med->mi, pdkp, &menu_x, &menu_y); if (pmret->rc == MENU_NEWITEM_MOVEMENU) { move_any_menu(med->mrMi, pmp, menu_x, menu_y); pmret->rc = MENU_NEWITEM; } else if (pmret->rc == MENU_NEWITEM_FIND) { med->mi = find_entry( pmp, NULL, NULL, None, -1, -1); pmret->rc = MENU_NEWITEM; } } else { pmret->rc = MENU_SELECTED; } switch (pmret->rc) { case MENU_NOP: return MENU_MLOOP_RET_LOOP; case MENU_POPDOWN: case MENU_ABORTED: case MENU_DOUBLE_CLICKED: case MENU_TEAR_OFF: case MENU_KILL_TEAR_OFF_MENU: case MENU_EXEC_CMD: return MENU_MLOOP_RET_END; case MENU_POPUP: /* Allow for MoveLeft/MoveRight action to work with * Mouse */ in->mif.do_popup_and_warp = True; case MENU_NEWITEM: /* unpost the menu if posted */ pmret->flags.is_menu_posted = 0; return MENU_MLOOP_RET_NORMAL; case MENU_SELECTED: in->mif.was_item_unposted = 0; if (pmret->flags.is_menu_posted && med->mrMi != NULL) { if (pmret->flags.do_unpost_submenu) { pmret->flags.do_unpost_submenu = 0; pmret->flags.is_menu_posted = 0; /* just ignore the event */ return MENU_MLOOP_RET_LOOP; } else if (med->mi && MI_IS_POPUP(med->mi) && med->mrMi == pmp->menu) { /* post menu - done below */ } else if (MR_PARENT_ITEM(pmp->menu) && med->mi == MR_PARENT_ITEM(pmp->menu)) { /* propagate back to parent menu * and unpost current menu */ pmret->flags.do_unpost_submenu = 1; pmret->rc = MENU_PROPAGATE_EVENT; pmret->target_menu = med->mrMi; return MENU_MLOOP_RET_END; } else if (med->mrMi != pmp->menu && med->mrMi != in->mrPopup) { /* unpost and propagate back to * ancestor */ pmret->flags.is_menu_posted = 0; pmret->rc = MENU_PROPAGATE_EVENT; pmret->target_menu = med->mrMi; return MENU_MLOOP_RET_END; } else if (in->mrPopup && med->mrMi == in->mrPopup) { /* unpost and propagate into * submenu */ in->mif.was_item_unposted = 1; in->mif.do_propagate_event_into_submenu = True; break; } else { /* simply unpost the menu */ pmret->flags.is_menu_posted = 0; } } if (is_double_click( msi->t0, med->mi, pmp, pmret, pdkp, in->mif.has_mouse_moved)) { pmret->rc = MENU_DOUBLE_CLICKED; return MENU_MLOOP_RET_END; } if (med->mi == NULL) { pmret->rc = MENU_ABORTED; } else if (MI_IS_POPUP(med->mi)) { switch (MST_DO_POPUP_AS(pmp->menu)) { case MDP_POST_MENU: if (in->mif.was_item_unposted) { pmret->flags.is_menu_posted = 0; pmret->rc = MENU_UNPOST; pmret->target_menu = NULL; in->mif.do_popup_now = False; } else { pmret->flags.is_menu_posted = 1; pmret->rc = MENU_POST; pmret->target_menu = NULL; in->mif.do_popup_now = True; if ((in->mrPopup || in->mrPopdown) && med->mi != MR_SELECTED_ITEM( pmp->menu)) { in->mif.do_popdown_now = True; } } return MENU_MLOOP_RET_NORMAL; case MDP_IGNORE: pmret->rc = MENU_NOP; return MENU_MLOOP_RET_NORMAL; case MDP_CLOSE: pmret->rc = MENU_ABORTED; break; case MDP_ROOT_MENU: default: break; } } break; default: break; } pdkp->timestamp = 0; return MENU_MLOOP_RET_END; case ButtonPress: /* if the first event is a button press allow the release to * select something */ pmp->flags.is_sticky = False; return MENU_MLOOP_RET_LOOP; case VisibilityNotify: return MENU_MLOOP_RET_LOOP; case KeyRelease: if ((*pmp->pexc)->x.elast->xkey.keycode != MST_SELECT_ON_RELEASE_KEY(pmp->menu)) { return MENU_MLOOP_RET_LOOP; } /* fall through to KeyPress */ case KeyPress: /* Handle a key press events to allow mouseless operation */ in->mif.is_key_press = True; med->x_offset = menudim_middle_x_offset(&MR_DIM(pmp->menu)); /* if there is a posted menu we may have to move back into a * previous menu or possibly ignore the mouse position */ if (pmret->flags.is_menu_posted) { MenuRoot *l_mrMi; int l_x_offset; XEvent e; pmret->flags.is_menu_posted = 0; (void)find_entry( pmp, &l_x_offset, &l_mrMi, None, -1, -1); if (l_mrMi != NULL) { if (pmp->menu != l_mrMi) { /* unpost the menu and propagate the * event to the correct menu */ pmret->rc = MENU_PROPAGATE_EVENT; pmret->target_menu = l_mrMi; return MENU_MLOOP_RET_END; } } med->mi = MR_SELECTED_ITEM(pmp->menu); e = *(*pmp->pexc)->x.elast; e.xkey.x_root = med->x_offset; e.xkey.y_root = menuitem_middle_y_offset( med->mi, MR_STYLE(pmp->menu)); fev_fake_event(&e); } /* now handle the actual key press */ { int menu_x; int menu_y; menu_shortcuts( pmp->menu, pmp, pmret, (*pmp->pexc)->x.elast, &med->mi, pdkp, &menu_x, &menu_y); if (pmret->rc == MENU_NEWITEM_MOVEMENU) { move_any_menu(pmp->menu, pmp, menu_x, menu_y); pmret->rc = MENU_NEWITEM; } else if (pmret->rc == MENU_NEWITEM_FIND) { med->mi = find_entry( pmp, NULL, NULL, None, -1, -1); pmret->rc = MENU_NEWITEM; } } if (pmret->rc != MENU_NOP) { /* using a key 'unposts' the posted menu */ pmret->flags.is_menu_posted = 0; } switch (pmret->rc) { case MENU_SELECTED: if (med->mi && MI_IS_POPUP(med->mi)) { switch (MST_DO_POPUP_AS(pmp->menu)) { case MDP_POST_MENU: pmret->rc = MENU_POPUP; break; case MDP_IGNORE: pmret->rc = MENU_NOP; return MENU_MLOOP_RET_NORMAL; case MDP_CLOSE: pmret->rc = MENU_ABORTED; return MENU_MLOOP_RET_END; case MDP_ROOT_MENU: default: return MENU_MLOOP_RET_END; } break; } return MENU_MLOOP_RET_END; case MENU_POPDOWN: case MENU_ABORTED: case MENU_DOUBLE_CLICKED: case MENU_TEAR_OFF: case MENU_KILL_TEAR_OFF_MENU: case MENU_EXEC_CMD: return MENU_MLOOP_RET_END; case MENU_NEWITEM: case MENU_POPUP: if (med->mrMi == NULL) { /* Set the MenuRoot of the current item in case * we have just warped to the menu from the * void or unposted a popup menu. */ med->mrMi = pmp->menu; } /*tmrMi = med->mrMi;*/ break; default: break; } /* now warp to the new menu item, if any */ if (pmret->rc == MENU_NEWITEM && med->mi) { warp_pointer_to_item(med->mrMi, med->mi, False); } if (pmret->rc == MENU_POPUP && med->mi && MI_IS_POPUP(med->mi)) { in->mif.do_popup_and_warp = True; break; } break; case MotionNotify: { int p_rx = -1; int p_ry = -1; Window p_child = None; if (in->mif.has_mouse_moved == False) { if (FQueryPointer( dpy, Scr.Root, &JunkRoot, &p_child, &p_rx, &p_ry, &JunkX, &JunkY, &JunkMask) == False) { /* pointer is on a different screen */ p_rx = 0; p_ry = 0; } if (p_rx - msi->x_init > Scr.MoveThreshold || msi->x_init - p_rx > Scr.MoveThreshold || p_ry - msi->y_init > Scr.MoveThreshold || msi->y_init - p_ry > Scr.MoveThreshold) { /* remember that this isn't just a click any * more since the pointer moved */ in->mif.has_mouse_moved = True; } } med->mi = find_entry( pmp, &med->x_offset, &med->mrMi, p_child, p_rx, p_ry); if (pmret->flags.is_menu_posted && med->mrMi != pmret->target_menu) { /* ignore mouse movement outside a posted menu */ med->mrMi = NULL; med->mi = NULL; } if (!in->mif.is_release_first && !in->mif.is_motion_faked && in->mif.has_mouse_moved) { in->mif.is_motion_first = True; } in->mif.is_motion_faked = False; break; } case Expose: /* grab our expose events, let the rest go through */ XFlush(dpy); rc = menu_expose((*pmp->pexc)->x.elast, (*pmp->pexc)->w.fw); /* we want to dispatch this too so that icons and maybe tear * off get redrawn after being obscured by menus. */ if (rc == False) { dispatch_event((*pmp->pexc)->x.elast); } return MENU_MLOOP_RET_LOOP; case ClientMessage: if ((*pmp->pexc)->x.elast->xclient.format == 32 && (*pmp->pexc)->x.elast->xclient.data.l[0] == _XA_WM_DELETE_WINDOW && pmp->tear_off_root_menu_window != NULL && (*pmp->pexc)->x.elast->xclient.window == FW_W_PARENT( pmp->tear_off_root_menu_window)) { /* handle deletion of tear out menus */ pmret->rc = MENU_KILL_TEAR_OFF_MENU; return MENU_MLOOP_RET_END; } break; case EnterNotify: /* ignore EnterNotify events */ break; case LeaveNotify: if (pmp->tear_off_root_menu_window != NULL && find_entry(pmp, NULL, &tmrMi, None, -1, -1) == NULL && tmrMi == NULL) { /* handle deletion of tear out menus */ pmret->rc = MENU_ABORTED; return MENU_MLOOP_RET_END; } /* ignore it */ return MENU_MLOOP_RET_LOOP; case UnmapNotify: /* should never happen, but does not hurt */ if (pmp->tear_off_root_menu_window != NULL && (*pmp->pexc)->x.elast->xunmap.window == FW_W(pmp->tear_off_root_menu_window)) { /* handle deletion of tear out menus */ pmret->rc = MENU_KILL_TEAR_OFF_MENU; /* extra safety: pass event back to main event loop to * make sure the window is destroyed */ FPutBackEvent(dpy, (*pmp->pexc)->x.elast); return MENU_MLOOP_RET_END; } break; default: /* We must not dispatch events here. There is no guarantee * that dispatch_event doesn't destroy a window stored in the * menu structures. Anyway, no events should ever get here * except to tear off menus and these must be handled * individually. */ #if 0 dispatch_event((*pmp->pexc)->x.elast); #endif break; } return MENU_MLOOP_RET_NORMAL; } static void __mloop_select_item( MenuParameters *pmp, mloop_evh_input_t *in, mloop_evh_data_t *med, Bool does_submenu_overlap, Bool *pdoes_popdown_submenu_overlap) { in->mif.is_item_entered_by_key_press = in->mif.is_key_press; med->popup_delay_10ms = 0; /* we're on the same menu, but a different item, so we need to unselect * the old item */ if (MR_SELECTED_ITEM(pmp->menu)) { /* something else was already selected on this menu. We have * to pop down the menu before unselecting the item in case we * are using gradient menus. The recalled image would paint * over the submenu. */ if (in->mrPopup && in->mrPopup != in->mrPopdown) { in->mrPopdown = in->mrPopup; med->popdown_delay_10ms = 0; *pdoes_popdown_submenu_overlap = does_submenu_overlap; in->mrPopup = NULL; } select_menu_item( pmp->menu, MR_SELECTED_ITEM(pmp->menu), False, (*pmp->pexc)->w.fw); } /* highlight the new item; sets MR_SELECTED_ITEM(pmp->menu) too */ select_menu_item(pmp->menu, med->mi, True, (*pmp->pexc)->w.fw); return; } static void __mloop_wants_popup( MenuParameters *pmp, mloop_evh_input_t *in, mloop_evh_data_t *med, MenuRoot *mrMiPopup) { Bool do_it_now = False; in->mi_wants_popup = med->mi; if (in->mif.do_popup_now) { do_it_now = True; } else if (MST_DO_POPUP_IMMEDIATELY(pmp->menu) && med->mi != in->miRemovedSubmenu) { if (in->mif.is_key_press || MST_DO_POPDOWN_IMMEDIATELY(pmp->menu) || !in->mrPopdown) { do_it_now = True; } } else if (pointer_in_active_item_area(med->x_offset, med->mrMi)) { if (in->mif.is_key_press || med->mi == in->miRemovedSubmenu || MST_DO_POPDOWN_IMMEDIATELY(pmp->menu) || !in->mrPopdown) { do_it_now = True; } else { in->mif.is_pointer_in_active_item_area = 1; } } if (do_it_now) { in->miRemovedSubmenu = NULL; /* must create a new menu or popup */ if (in->mrPopup == NULL || in->mrPopup != mrMiPopup) { if (in->mif.do_popup_now) { in->mif.do_popup = True; } else { /* pop up in next pass through loop */ in->mif.do_force_popup = True; } } else if (in->mif.do_popup_and_warp) { warp_pointer_to_item( in->mrPopup, MR_FIRST_ITEM(in->mrPopup), True); } } return; } static mloop_ret_code_t __mloop_make_popup( MenuParameters *pmp, MenuReturn *pmret, mloop_evh_input_t *in, mloop_evh_data_t *med, MenuOptions *pops, Bool *pdoes_submenu_overlap) { /* create a popup menu */ if (!is_submenu_mapped(pmp->menu, med->mi)) { /* We want to pop prepop menus so it doesn't *have* to be unpopped; do_menu pops down any menus it pops up, but we want to be able to popdown w/o actually removing the menu */ int x; int y; Bool prefer_left_submenus; /* Make sure we are using the latest style and menu layout. */ update_menu(in->mrPopup, pmp); get_prefered_popup_position( pmp->menu, in->mrPopup, &x, &y, &prefer_left_submenus); /* Note that we don't care if popping up the menu works. If it * doesn't we'll catch it below. */ pop_menu_up( &in->mrPopup, pmp, pmp->menu, med->mi, pmp->pexc, x, y, prefer_left_submenus, in->mif.do_popup_and_warp, pops, pdoes_submenu_overlap, (in->mrPopdown) ? MR_WINDOW(in->mrPopdown) : None); in->mi_with_popup = med->mi; in->mi_wants_popup = NULL; if (in->mrPopup == NULL) { /* the menu deleted itself when execution the dynamic * popup * action */ pmret->rc = MENU_ERROR; return MENU_MLOOP_RET_END; } MR_SUBMENU_ITEM(pmp->menu) = med->mi; } return MENU_MLOOP_RET_NORMAL; } static mloop_ret_code_t __mloop_get_mi_actions( MenuParameters *pmp, MenuReturn *pmret, double_keypress *pdkp, mloop_evh_input_t *in, mloop_evh_data_t *med, mloop_static_info_t *msi, MenuRoot *mrMiPopup, Bool *pdoes_submenu_overlap, Bool *pdoes_popdown_submenu_overlap) { in->mif.do_popdown = False; in->mif.do_popup = False; in->mif.do_menu = False; in->mif.is_submenu_mapped = False; if (!in->mrPopup && in->mrPopdown && med->mi == MR_PARENT_ITEM(in->mrPopdown)) { /* We're again on the item that we left before. * Deschedule popping it down. */ in->mrPopup = in->mrPopdown; in->mrPopdown = NULL; } if (med->mrMi == in->mrPopup) { /* must make current popup menu a real menu */ in->mif.do_menu = True; in->mif.is_submenu_mapped = True; } else if (pmret->rc == MENU_POST) { /* must create a real menu and warp into it */ if (in->mrPopup == NULL || in->mrPopup != mrMiPopup) { in->mif.do_popup = True; } in->mif.do_menu = True; in->mif.is_submenu_mapped = True; } else if (in->mif.do_popup_and_warp) { /* must create a real menu and warp into it */ if (in->mrPopup == NULL || in->mrPopup != mrMiPopup) { in->mif.do_popup = True; } else { XRaiseWindow(dpy, MR_WINDOW(in->mrPopup)); warp_pointer_to_item( in->mrPopup, MR_FIRST_ITEM(in->mrPopup), True); in->mif.do_menu = True; in->mif.is_submenu_mapped = True; } } else if (med->mi && MI_IS_POPUP(med->mi)) { if ((*pmp->pexc)->x.elast->type == ButtonPress && is_double_click( msi->t0, med->mi, pmp, pmret, pdkp, in->mif.has_mouse_moved)) { pmret->rc = MENU_DOUBLE_CLICKED; return MENU_MLOOP_RET_END; } else if (!in->mrPopup || in->mrPopup != mrMiPopup || in->mif.do_popup_and_warp) { __mloop_wants_popup(pmp, in, med, mrMiPopup); } } if (in->mif.do_popdown_now) { in->mif.do_popdown = True; in->mif.do_popdown_now = False; } else if (in->mif.do_popup) { if (in->mrPopup && in->mrPopup != mrMiPopup) { in->mif.do_popdown = True; in->mrPopdown = in->mrPopup; med->popdown_delay_10ms = 0; *pdoes_popdown_submenu_overlap = *pdoes_submenu_overlap; } else if (in->mrPopdown && in->mrPopdown != mrMiPopup) { in->mif.do_popdown = True; } else if (in->mrPopdown && in->mrPopdown == mrMiPopup) { in->mrPopup = in->mrPopdown; *pdoes_submenu_overlap = *pdoes_popdown_submenu_overlap; in->mrPopdown = NULL; in->mif.do_popup = False; in->mif.do_popdown = False; } } return MENU_MLOOP_RET_NORMAL; } static void __mloop_do_popdown( MenuParameters *pmp, mloop_evh_input_t *in, Bool *pdoes_popdown_submenu_overlap) { if (in->mrPopdown) { pop_menu_down_and_repaint_parent( &in->mrPopdown, pdoes_popdown_submenu_overlap, pmp); in->mi_with_popup = NULL; MR_SUBMENU_ITEM(pmp->menu) = NULL; if (in->mrPopup == in->mrPopdown) { in->mrPopup = NULL; } in->mrPopdown = NULL; } in->mif.do_popdown = False; return; } static mloop_ret_code_t __mloop_do_popup( MenuParameters *pmp, MenuReturn *pmret, mloop_evh_input_t *in, mloop_evh_data_t *med, MenuOptions *pops, MenuRoot *mrMiPopup, Bool *pdoes_submenu_overlap, Bool *pdoes_popdown_submenu_overlap) { if (!MR_IS_PAINTED(pmp->menu)) { /* draw the parent menu if it is not already drawn */ FCheckWeedTypedWindowEvents( dpy, MR_WINDOW(pmp->menu), Expose, NULL); paint_menu(pmp->menu, NULL, (*pmp->pexc)->w.fw); } /* get pos hints for item's action */ get_popup_options(pmp, med->mi, pops); if (med->mrMi == pmp->menu && mrMiPopup == NULL && MI_IS_POPUP(med->mi) && MR_MISSING_SUBMENU_FUNC(pmp->menu)) { /* We're on a submenu item, but the submenu does not exist. * The user defined missing_submenu_action may create it. */ Bool is_complex_function; Bool is_busy_grabbed = False; char *menu_name; char *action; char *missing_action = MR_MISSING_SUBMENU_FUNC(pmp->menu); menu_name = PeekToken( SkipNTokens(MI_ACTION(med->mi), 1), NULL); if (!menu_name) { menu_name = ""; } is_complex_function = functions_is_complex_function(missing_action); if (is_complex_function) { char *action_ptr; action = safemalloc( strlen("Function") + 3 + strlen(missing_action) * 2 + 3 + strlen(menu_name) * 2 + 1); strcpy(action, "Function "); action_ptr = action + strlen(action); action_ptr = QuoteString(action_ptr, missing_action); *action_ptr++ = ' '; action_ptr = QuoteString(action_ptr, menu_name); } else { action = MR_MISSING_SUBMENU_FUNC(pmp->menu); } if (Scr.BusyCursor & BUSY_DYNAMICMENU) { is_busy_grabbed = GrabEm(CRS_WAIT, GRAB_BUSYMENU); } /* Execute the action */ __menu_execute_function(pmp->pexc, action); if (is_complex_function) { free(action); } if (is_busy_grabbed) { UngrabEm(GRAB_BUSYMENU); } /* Let's see if the menu exists now. */ mrMiPopup = mr_popup_for_mi(pmp->menu, med->mi); } /* run MISSING_SUBMENU_FUNCTION */ in->mrPopup = mrMiPopup; if (!in->mrPopup) { in->mif.do_menu = False; pmret->flags.is_menu_posted = 0; } else { if (__mloop_make_popup( pmp, pmret, in, med, pops, pdoes_submenu_overlap) == MENU_MLOOP_RET_END) { return MENU_MLOOP_RET_END; } } /* else (in->mrPopup) */ if (in->mif.do_popdown) { if (in->mrPopdown) { if (in->mrPopdown != in->mrPopup) { if (in->mi_with_popup == MR_PARENT_ITEM(in->mrPopdown)) { in->mi_with_popup = NULL; } pop_menu_down_and_repaint_parent( &in->mrPopdown, pdoes_popdown_submenu_overlap, pmp); } in->mrPopdown = NULL; } in->mif.do_popdown = False; } if (in->mrPopup) { if (MR_PARENT_MENU(in->mrPopup) == pmp->menu) { med->mi = find_entry( pmp, NULL, &med->mrMi, None, -1, -1); if (med->mi && med->mrMi == in->mrPopup) { in->mif.do_menu = True; in->mif.is_submenu_mapped = True; } } else { /* This menu must be already mapped somewhere else, so * ignore it completely. This can only happen if we * have reached the maximum allowed number of menu * copies. */ in->mif.do_menu = False; in->mif.do_popdown = False; in->mrPopup = NULL; } } return MENU_MLOOP_RET_NORMAL; } static mloop_ret_code_t __mloop_do_menu( MenuParameters *pmp, MenuReturn *pmret, double_keypress *pdkp, mloop_evh_input_t *in, mloop_evh_data_t *med, MenuOptions *pops, Bool *pdoes_submenu_overlap) { MenuParameters mp; XEvent e; memset(&mp, 0, sizeof(mp)); mp.menu = in->mrPopup; mp.pexc = pmp->pexc; mp.parent_menu = pmp->menu; mp.parent_item = med->mi; mp.tear_off_root_menu_window = pmp->tear_off_root_menu_window; MR_IS_TEAR_OFF_MENU(in->mrPopup) = 0; mp.flags.has_default_action = False; mp.flags.is_already_mapped = in->mif.is_submenu_mapped; mp.flags.is_sticky = False; mp.flags.is_submenu = True; mp.flags.is_triggered_by_keypress = !!in->mif.do_popup_and_warp; mp.pops = pops; mp.ret_paction = pmp->ret_paction; mp.screen_origin_x = pmp->screen_origin_x; mp.screen_origin_y = pmp->screen_origin_y; if (in->mif.do_propagate_event_into_submenu) { e = *(*pmp->pexc)->x.elast; mp.event_propagate_to_submenu = &e; } else { mp.event_propagate_to_submenu = NULL; } /* recursively do the new menu we've moved into */ do_menu(&mp, pmret); in->mif.do_propagate_event_into_submenu = False; if (pmret->rc == MENU_PROPAGATE_EVENT) { in->mif.do_recycle_event = 1; return MENU_MLOOP_RET_LOOP; } if (IS_MENU_RETURN(pmret->rc)) { pdkp->timestamp = 0; return MENU_MLOOP_RET_END; } if (MST_DO_UNMAP_SUBMENU_ON_POPDOWN(pmp->menu) && pmret->flags.is_key_press) { in->miRemovedSubmenu = MR_PARENT_ITEM(in->mrPopup); pop_menu_down_and_repaint_parent( &in->mrPopup, pdoes_submenu_overlap, pmp); in->mi_with_popup = NULL; MR_SUBMENU_ITEM(pmp->menu) = NULL; if (in->mrPopup == in->mrPopdown) { in->mrPopdown = NULL; } in->mrPopup = NULL; } if (pmret->rc == MENU_POPDOWN) { med->popup_delay_10ms = 0; in->mif.do_force_reposition = True; } return MENU_MLOOP_RET_NORMAL; } static mloop_ret_code_t __mloop_handle_action_with_mi( MenuParameters *pmp, MenuReturn *pmret, double_keypress *pdkp, mloop_evh_input_t *in, mloop_evh_data_t *med, mloop_static_info_t *msi, MenuOptions *pops, Bool *pdoes_submenu_overlap, Bool *pdoes_popdown_submenu_overlap) { MenuItem *tmi; MenuRoot *tmrMi; MenuRoot *mrMiPopup = NULL; pmret->flags.do_unpost_submenu = 0; /* we're on a menu item */ in->mif.is_off_menu_allowed = False; if (med->mrMi == pmp->menu && med->mi != in->miRemovedSubmenu) { in->miRemovedSubmenu = NULL; } if (med->mrMi != pmp->menu && med->mrMi != in->mrPopup && med->mrMi != in->mrPopdown) { /* we're on an item from a prior menu */ if (med->mrMi != MR_PARENT_MENU(pmp->menu)) { /* the event is for a previous menu, just close * this one */ pmret->rc = MENU_PROPAGATE_EVENT; pmret->target_menu = med->mrMi; } else { pmret->rc = MENU_POPDOWN; } pdkp->timestamp = 0; return MENU_MLOOP_RET_END; } if (med->mi != MR_SELECTED_ITEM(pmp->menu) && med->mrMi == pmp->menu) { /* new item of the same menu */ __mloop_select_item( pmp, in, med, *pdoes_submenu_overlap, pdoes_popdown_submenu_overlap); } else if (med->mi != MR_SELECTED_ITEM(pmp->menu) && med->mrMi && med->mrMi == in->mrPopdown) { /* we're on the popup menu of a different menu item of this * menu */ med->mi = MR_PARENT_ITEM(in->mrPopdown); in->mrPopup = in->mrPopdown; in->mrPopdown = NULL; *pdoes_submenu_overlap = *pdoes_popdown_submenu_overlap; select_menu_item(pmp->menu, med->mi, True, (*pmp->pexc)->w.fw); } mrMiPopup = mr_popup_for_mi(pmp->menu, med->mi); /* check what has to be done with the item */ if (__mloop_get_mi_actions( pmp, pmret, pdkp, in, med, msi, mrMiPopup, pdoes_submenu_overlap, pdoes_popdown_submenu_overlap) == MENU_MLOOP_RET_END) { return MENU_MLOOP_RET_END; } /* do what needs to be done */ if (in->mif.do_popdown && !in->mif.do_popup) { /* popdown previous popup */ __mloop_do_popdown(pmp, in, pdoes_popdown_submenu_overlap); } if (in->mif.do_popup) { if (__mloop_do_popup( pmp, pmret, in, med, pops, mrMiPopup, pdoes_submenu_overlap, pdoes_popdown_submenu_overlap) == MENU_MLOOP_RET_END) { return MENU_MLOOP_RET_END; } } /* remember the 'posted' menu */ if (pmret->flags.is_menu_posted && in->mrPopup != NULL && pmret->target_menu == NULL) { pmret->target_menu = in->mrPopup; } else if (pmret->flags.is_menu_posted && in->mrPopup == NULL) { pmret->flags.is_menu_posted = 0; } if (in->mif.do_menu) { mloop_ret_code_t rc; rc = __mloop_do_menu( pmp, pmret, pdkp, in, med, pops, pdoes_submenu_overlap); if (rc != MENU_MLOOP_RET_NORMAL) { return rc; } } /* Now check whether we can animate the current popup menu back to the * original place to unobscure the current menu; this happens only * when using animation */ if (in->mrPopup && MR_XANIMATION(in->mrPopup) && (tmi = find_entry(pmp, NULL, &tmrMi, None, -1, -1)) && (tmi == MR_SELECTED_ITEM(pmp->menu) || tmrMi != pmp->menu)) { animated_move_back(in->mrPopup, False, (*pmp->pexc)->w.fw); } /* now check whether we should animate the current real menu * over to the right to unobscure the prior menu; only a very * limited case where this might be helpful and not too disruptive */ /* but this cause terrible back-and-forth under certain circonstance, * I think we should disable this ... 2002-09-17 olicha */ if (in->mrPopup == NULL && pmp->parent_menu != NULL && MR_XANIMATION(pmp->menu) != 0 && pointer_in_passive_item_area(med->x_offset, med->mrMi)) { /* we have to see if we need menu to be moved */ animated_move_back(pmp->menu, True, (*pmp->pexc)->w.fw); if (in->mrPopdown) { if (in->mrPopdown != in->mrPopup) { pop_menu_down_and_repaint_parent( &in->mrPopdown, pdoes_popdown_submenu_overlap, pmp); in->mi_with_popup = NULL; } in->mrPopdown = NULL; } in->mif.do_popdown = False; } return MENU_MLOOP_RET_NORMAL; } static mloop_ret_code_t __mloop_handle_action_without_mi( MenuParameters *pmp, MenuReturn *pmret, double_keypress *pdkp, mloop_evh_input_t *in, mloop_evh_data_t *med, mloop_static_info_t *msi, MenuOptions *pops, Bool *pdoes_submenu_overlap, Bool *pdoes_popdown_submenu_overlap) { pmret->flags.do_unpost_submenu = 0; /* moved off menu, deselect selected item... */ if (!MR_SELECTED_ITEM(pmp->menu) || in->mif.is_off_menu_allowed == True || pmret->flags.is_menu_posted) { /* nothing to do */ return MENU_MLOOP_RET_NORMAL; } if (in->mrPopup) { int x, y, mx, my; int mw, mh; if (FQueryPointer(dpy, Scr.Root, &JunkRoot, &JunkChild, &x, &y, &JunkX, &JunkY, &JunkMask) == False) { /* pointer is on a different screen */ x = 0; y = 0; } if (menu_get_geometry( pmp->menu, &JunkRoot, &mx, &my, &mw, &mh, &JunkBW, &JunkDepth) && ((!MR_IS_LEFT(in->mrPopup) && x < mx) || (!MR_IS_RIGHT(in->mrPopup) && x > mx + mw) || (!MR_IS_UP(in->mrPopup) && y < my) || (!MR_IS_DOWN(in->mrPopup) && y > my + mh))) { select_menu_item( pmp->menu, MR_SELECTED_ITEM(pmp->menu), False, (*pmp->pexc)->w.fw); pop_menu_down_and_repaint_parent( &in->mrPopup, pdoes_submenu_overlap, pmp); in->mi_with_popup = NULL; MR_SUBMENU_ITEM(pmp->menu) = NULL; if (in->mrPopup == in->mrPopdown) { in->mrPopdown = NULL; } in->mrPopup = NULL; } else if (x < mx || x >= mx + mw || y < my || y >= my + mh) { /* pointer is outside the menu but do not pop down */ in->mif.is_off_menu_allowed = True; } else { /* Pointer is still in the menu. Postpone the decision * if we have to pop down. */ } } /* if (in->mrPopup) */ else { select_menu_item( pmp->menu, MR_SELECTED_ITEM(pmp->menu), False, (*pmp->pexc)->w.fw); } return MENU_MLOOP_RET_NORMAL; } static void __mloop_exit_warp_back(MenuParameters *pmp) { MenuRoot *tmrMi; if (pmp->parent_menu && MR_SELECTED_ITEM(pmp->parent_menu)) { warp_pointer_to_item( pmp->parent_menu, MR_SELECTED_ITEM(pmp->parent_menu), False); (void)find_entry(pmp, NULL, &tmrMi, None, -1, -1); if (pmp->parent_menu != tmrMi && MR_XANIMATION(pmp->menu) == 0) { /* Warping didn't take us to the correct menu, i.e. the * spot we want to warp to is obscured. So raise our * window first. */ XRaiseWindow(dpy, MR_WINDOW(pmp->parent_menu)); } } return; } static void __mloop_exit_select_in_place( MenuParameters *pmp, mloop_evh_data_t *med, MenuOptions *pops) { MenuRoot *submenu; XWindowAttributes win_attribs; last_saved_pos_hints.flags.is_last_menu_pos_hints_valid = True; last_saved_pos_hints.pos_hints.x_offset = 0; last_saved_pos_hints.pos_hints.x_factor = 0; last_saved_pos_hints.pos_hints.context_x_factor = 0; last_saved_pos_hints.pos_hints.y_factor = 0; last_saved_pos_hints.pos_hints.is_relative = False; last_saved_pos_hints.pos_hints.is_menu_relative = False; submenu = mr_popup_for_mi(pmp->menu, med->mi); if (submenu && MR_WINDOW(submenu) != None && XGetWindowAttributes(dpy, MR_WINDOW(submenu), &win_attribs) && win_attribs.map_state == IsViewable && menu_get_geometry( submenu, &JunkRoot, &last_saved_pos_hints.pos_hints.x, &last_saved_pos_hints.pos_hints.y, &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth)) { /* The submenu is mapped, just take its position and put it in * the position hints. */ } else if (pops->flags.has_poshints) { last_saved_pos_hints.pos_hints = pops->pos_hints; } else { Bool dummy; get_prefered_popup_position( pmp->menu, submenu, &last_saved_pos_hints. pos_hints.x, &last_saved_pos_hints. pos_hints.y, &dummy); } if (pops->flags.do_warp_on_select) { last_saved_pos_hints.flags.do_warp_title = 1; } return; } static void __mloop_exit_selected( MenuParameters *pmp, MenuReturn *pmret, mloop_evh_data_t *med, MenuOptions *pops) { /* save action to execute so that the menu may be destroyed now */ if (pmp->ret_paction) { if (pmret->rc == MENU_EXEC_CMD) { *pmp->ret_paction = safestrdup(*pmp->ret_paction); } else { if (*pmp->ret_paction) { free(*pmp->ret_paction); } *pmp->ret_paction = (med->mi) ? safestrdup(MI_ACTION(med->mi)) : NULL; } } if ( pmp->ret_paction && *pmp->ret_paction && med->mi && MI_IS_POPUP(med->mi)) { get_popup_options(pmp, med->mi, pops); if (pops->flags.do_select_in_place) { __mloop_exit_select_in_place(pmp, med, pops); } else { last_saved_pos_hints.flags.do_ignore_pos_hints = True; } /* pops->flags.do_select_in_place */ last_saved_pos_hints.pos_hints.screen_origin_x = pmp->screen_origin_x; last_saved_pos_hints.pos_hints.screen_origin_y = pmp->screen_origin_y; } return; } static void __mloop_exit( MenuParameters *pmp, MenuReturn *pmret, double_keypress *pdkp, mloop_evh_input_t *in, mloop_evh_data_t *med, mloop_static_info_t *msi, MenuOptions *pops) { Bool no = False; Bool do_deselect = False; if (in->mrPopdown) { pop_menu_down_and_repaint_parent(&in->mrPopdown, &no, pmp); MR_SUBMENU_ITEM(pmp->menu) = NULL; } if ( pmret->rc == MENU_SELECTED && is_double_click( msi->t0, med->mi, pmp, pmret, pdkp, in->mif.has_mouse_moved)) { pmret->rc = MENU_DOUBLE_CLICKED; } if ( pmret->rc == MENU_SELECTED && med->mi && MI_FUNC_TYPE(med->mi) == F_TEARMENUOFF) { pmret->rc = (MR_IS_TEAR_OFF_MENU(pmp->menu)) ? MENU_KILL_TEAR_OFF_MENU : MENU_TEAR_OFF; } switch (pmret->rc) { case MENU_POPDOWN: case MENU_PROPAGATE_EVENT: case MENU_DOUBLE_CLICKED: do_deselect = True; /* Allow popdown to warp back pointer to main menu with mouse button control. (MoveLeft/MoveRight on a mouse binding) */ if (((pmret->rc == MENU_POPDOWN && in->mif.is_button_release) || in->mif.is_key_press) && pmret->rc != MENU_DOUBLE_CLICKED) { if (!pmp->flags.is_submenu) { /* abort a root menu rather than pop it down */ pmret->rc = MENU_ABORTED; } __mloop_exit_warp_back(pmp); } break; case MENU_ABORTED: case MENU_TEAR_OFF: case MENU_KILL_TEAR_OFF_MENU: do_deselect = True; break; case MENU_SELECTED: case MENU_EXEC_CMD: __mloop_exit_selected(pmp, pmret, med, pops); pmret->rc = MENU_DONE; break; default: break; } if (do_deselect && MR_SELECTED_ITEM(pmp->menu)) { select_menu_item( pmp->menu, MR_SELECTED_ITEM(pmp->menu), False, (*pmp->pexc)->w.fw); } if (pmret->rc == MENU_SUBMENU_TORN_OFF) { in->mrPopup = NULL; MR_SUBMENU_ITEM(pmp->menu) = NULL; } if (in->mrPopup) { pop_menu_down_and_repaint_parent(&in->mrPopup, &no, pmp); MR_SUBMENU_ITEM(pmp->menu) = NULL; } pmret->flags.is_key_press = in->mif.is_key_press; return; } static void __menu_loop( MenuParameters *pmp, MenuReturn *pmret, double_keypress *pdkp) { mloop_evh_input_t mei; mloop_ret_code_t mloop_ret; mloop_evh_data_t med; mloop_static_info_t msi; MenuOptions mops; Bool is_finished; Bool does_submenu_overlap = False; Bool does_popdown_submenu_overlap = False; __mloop_init(pmp, pmret, &mei, &med, &msi, &mops); for (is_finished = False; !is_finished; ) { mloop_ret = __mloop_get_event(pmp, pmret, &mei, &med, &msi); switch (mloop_ret) { case MENU_MLOOP_RET_END: is_finished = True; case MENU_MLOOP_RET_LOOP: continue; default: break; } mloop_ret = __mloop_handle_event( pmp, pmret, pdkp, &mei, &med, &msi); switch (mloop_ret) { case MENU_MLOOP_RET_END: is_finished = True; continue; case MENU_MLOOP_RET_LOOP: continue; default: break; } /* Now handle new menu items, whether it is from a keypress or * a pointer motion event. */ if (med.mi != NULL) { mloop_ret = __mloop_handle_action_with_mi( pmp, pmret, pdkp, &mei, &med, &msi, &mops, &does_submenu_overlap, &does_popdown_submenu_overlap); } else { mloop_ret = __mloop_handle_action_without_mi( pmp, pmret, pdkp, &mei, &med, &msi, &mops, &does_submenu_overlap, &does_popdown_submenu_overlap); } if (mloop_ret == MENU_MLOOP_RET_END) { is_finished = True; } XFlush(dpy); } __mloop_exit(pmp, pmret, pdkp, &mei, &med, &msi, &mops); return; } /* * Functions dealing with tear off menus */ static char *menu_strip_tear_off_title(MenuRoot *mr) { MenuItem *mi; int i; int len; char *name; for (mi = MR_FIRST_ITEM(mr); mi != NULL; mi = MI_NEXT_ITEM(mi)) { if (MI_IS_TITLE(mi)) { break; } else if (!MI_IS_SEPARATOR(mi) && !MI_IS_TEAR_OFF_BAR(mi)) { /* a normal item, no title found */ return NULL; } /* skip separators and tear off bars */ } if (mi == NULL || !MI_HAS_TEXT(mi) || MI_NEXT_ITEM(mi) == NULL) { return NULL; } /* extract the window title from the labels */ for (i = 0, len = 0; i < MAX_MENU_ITEM_LABELS; i++) { if (MI_LABEL(mi)[i] != 0) { len += strlen(MI_LABEL(mi)[i]) + 1; } } if (len == 0) { return NULL; } name = safemalloc(len + 1); *name = 0; for (i = 0; i < MAX_MENU_ITEM_LABELS; i++) { if (MI_LABEL(mi)[i] != 0) { strcat(name, MI_LABEL(mi)[i]); strcat(name, " "); } } /* strip the last space */ name[len - 1] = 0; /* unlink and destroy the item */ unlink_item_from_menu(mr, mi); menuitem_free(mi); return name; } static int _pred_menu_window_weed_events( Display *display, XEvent *event, XPointer arg) { switch (event->type) { case CirculateNotify: case ConfigureNotify: case CreateNotify: case DestroyNotify: case GravityNotify: case MapNotify: case ReparentNotify: case UnmapNotify: /* events in SubstructureNotifyMask */ return 1; default: return 0; } } static void menu_tear_off(MenuRoot *mr_to_copy) { MenuRoot *mr; MenuStyle *ms; XEvent ev; XSizeHints menusizehints; XClassHint menuclasshints; XTextProperty menunametext; XWMHints menuwmhints; char *list[] ={ NULL, NULL }; char *t; char *name = NULL; Atom protocols[1]; int x = 0; int y = 0; unsigned int add_mask = 0; initial_window_options_t win_opts; evh_args_t ea; exec_context_changes_t ecc; char *buffer; char *action; cond_rc_t *cond_rc = NULL; const exec_context_t *exc = NULL; /* keep the menu open */ if (MR_WINDOW(mr_to_copy) != None) { XSync(dpy, 0); FWeedIfWindowEvents( dpy, MR_WINDOW(mr_to_copy), _pred_menu_window_weed_events, NULL); } mr = clone_menu(mr_to_copy); /* also dump the menu style */ buffer = (char *)safemalloc(23); sprintf(buffer,"%lu",(unsigned long)mr); action = buffer; ms = menustyle_parse_style(F_PASS_ARGS); if (!ms) { /* this must never happen */ fvwm_msg( ERR, "menu_tear_off", "impossible to create %s menu style", buffer); free(buffer); DestroyMenu(mr, False, False); return; } free(buffer); menustyle_copy(MR_STYLE(mr_to_copy),ms); MR_STYLE(mr) = ms; MST_USAGE_COUNT(mr) = 0; name = menu_strip_tear_off_title(mr); /* create the menu window and size the menu */ make_menu(mr, True); /* set position */ if (menu_get_geometry( mr_to_copy, &JunkRoot, &x, &y, &JunkWidth, &JunkHeight, &JunkBW, &JunkDepth)) { add_mask = PPosition; XMoveWindow(dpy, MR_WINDOW(mr), x, y); } else { add_mask = 0; } /* focus policy */ menuwmhints.flags = InputHint; menuwmhints.input = False; /* size hints */ menusizehints.flags = PBaseSize | PMinSize | PMaxSize | add_mask; menusizehints.base_width = 0; menusizehints.base_height = 0; menusizehints.min_width = MR_WIDTH(mr); menusizehints.min_height = MR_HEIGHT(mr); menusizehints.max_width = MR_WIDTH(mr); menusizehints.max_height = MR_HEIGHT(mr); /* class, resource and names */ menuclasshints.res_name = (name != NULL) ? name : safestrdup(MR_NAME(mr)); menuclasshints.res_class = safestrdup("fvwm_menu"); for (t = menuclasshints.res_name; t != NULL && *t != 0; t++) { /* replace tabs in the title with spaces */ if (*t == '\t') { *t = ' '; } } list[0] = menuclasshints.res_name; menunametext.value = NULL; XStringListToTextProperty(list, 1, &menunametext); /* set all properties and hints */ XSetWMProperties( dpy, MR_WINDOW(mr), &menunametext, &menunametext, NULL, 0, &menusizehints, NULL, &menuclasshints); XSetWMHints(dpy, MR_WINDOW(mr), &menuwmhints); protocols[0] = _XA_WM_DELETE_WINDOW; XSetWMProtocols(dpy, MR_WINDOW(mr), &(protocols[0]), 1); /* free memory */ if (menunametext.value != NULL) { XFree(menunametext.value); } free(menuclasshints.res_class); free(menuclasshints.res_name); /* manage the window */ memset(&win_opts, 0, sizeof(win_opts)); win_opts.flags.is_menu = True; ev.type = MapRequest; ev.xmaprequest.send_event = True; ev.xmaprequest.display = dpy; ev.xmaprequest.parent = Scr.Root; ev.xmaprequest.window = MR_WINDOW(mr); fev_fake_event(&ev); ecc.type = EXCT_NULL; ecc.x.etrigger = &ev; ecc.w.w = MR_WINDOW(mr); ecc.w.wcontext = C_ROOT; ea.exc = exc_create_context( &ecc, ECC_TYPE | ECC_ETRIGGER | ECC_W | ECC_WCONTEXT); HandleMapRequestKeepRaised(&ea, None, NULL, &win_opts); exc_destroy_context(ea.exc); return; } static void do_menu_close_tear_off_menu(MenuRoot *mr, MenuParameters mp) { pop_menu_down(&mr, &mp); menustyle_free(MR_STYLE(mr)); DestroyMenu(mr, False, False); } /* ---------------------------- interface functions ------------------------- */ void menus_init(void) { memset((&Menus), 0, sizeof(MenuInfo)); return; } /* menus_find_menu expects a token as the input. Make sure you have used * GetNextToken before passing a menu name to remove quotes (if necessary) */ MenuRoot *menus_find_menu(char *name) { MenuRoot *mr; if (name == NULL) { return NULL; } for (mr = Menus.all; mr != NULL; mr = MR_NEXT_MENU(mr)) { if (!MR_IS_DESTROYED(mr) && mr == MR_ORIGINAL_MENU(mr) && MR_NAME(mr) != NULL && StrEquals(name, MR_NAME(mr))) { break; } } return mr; } void menus_remove_style_from_menus(MenuStyle *ms) { MenuRoot *mr; for (mr = Menus.all; mr; mr = MR_NEXT_MENU(mr)) { if (MR_STYLE(mr) == ms) { MR_STYLE(mr) = menustyle_get_default_style(); MR_IS_UPDATED(mr) = 1; } } return; } /* * Functions dealing with tear off menus */ void menu_enter_tear_off_menu(const exec_context_t *exc) { MenuRoot *mr; char *ret_action = NULL; MenuOptions mops; MenuParameters mp; MenuReturn mret; const exec_context_t *exc2; exec_context_changes_t ecc; if (XFindContext( dpy, FW_W(exc->w.fw), MenuContext, (caddr_t *)&mr) == XCNOENT) { return; } ecc.w.fw = NULL; ecc.w.w = None; ecc.w.wcontext = C_ROOT; exc2 = exc_clone_context(exc, &ecc, ECC_FW | ECC_W | ECC_WCONTEXT); memset(&mops, 0, sizeof(mops)); memset(&mret, 0, sizeof(MenuReturn)); memset(&mp, 0, sizeof(mp)); mp.menu = mr; mp.pexc = &exc2; mp.tear_off_root_menu_window = exc->w.fw; MR_IS_TEAR_OFF_MENU(mr) = 1; mp.flags.has_default_action = 0; mp.flags.is_already_mapped = True; mp.flags.is_sticky = False; mp.flags.is_submenu = False; mp.pops = &mops; mp.ret_paction = &ret_action; do_menu(&mp, &mret); exc_destroy_context(exc2); return; } void menu_close_tear_off_menu(FvwmWindow *fw) { MenuRoot *mr; MenuParameters mp; const exec_context_t *exc; exec_context_changes_t ecc; if (XFindContext( dpy, FW_W(fw), MenuContext, (caddr_t *)&mr) == XCNOENT) { return; } memset(&mp, 0, sizeof(mp)); mp.menu = mr; ecc.w.fw = NULL; ecc.w.w = None; ecc.w.wcontext = C_ROOT; exc = exc_create_context(&ecc, ECC_FW | ECC_W | ECC_WCONTEXT); mp.pexc = &exc; do_menu_close_tear_off_menu(mr, mp); exc_destroy_context(exc); return; } Bool menu_redraw_transparent_tear_off_menu(FvwmWindow *fw, Bool pr_only) { MenuRoot *mr; MenuStyle *ms = NULL; int cs; if (!(IS_TEAR_OFF_MENU(fw) && XFindContext(dpy, FW_W(fw), MenuContext,(caddr_t *)&mr) != XCNOENT && (ms = MR_STYLE(mr)) && ST_HAS_MENU_CSET(ms))) { return False; } cs = ST_CSET_MENU(ms); if (!CSET_IS_TRANSPARENT(cs) || (pr_only && !CSET_IS_TRANSPARENT_PR(cs))) { return False; } return UpdateBackgroundTransparency( dpy, MR_WINDOW(mr), MR_WIDTH(mr), MR_HEIGHT(mr), &Colorset[ST_CSET_MENU(ms)], Pdepth, FORE_GC(MST_MENU_INACTIVE_GCS(mr)), True); } /* * * Initiates a menu pop-up * * fStick = True = sticky menu, stays up on initial button release. * fStick = False = transient menu, drops on initial release. * * eventp = 0: menu opened by mouse, do not warp * eventp > 1: root menu opened by keypress with 'Menu', warp pointer and * allow 'double-keypress'. * eventp = 1: menu opened by keypress, warp but forbid 'double-keypress' * this should always be used except in the call in 'staysup_func' * in builtin.c * * Returns one of MENU_NOP, MENU_ERROR, MENU_ABORTED, MENU_DONE * do_menu() may destroy the *pmp->pexec member and replace it with a new * copy. Be sure not to rely on the original structure being kept intact * when calling do_menu(). */ void do_menu(MenuParameters *pmp, MenuReturn *pmret) { int x; int y; Bool fWasAlreadyPopped = False; Bool key_press; Bool is_pointer_grabbed = False; Bool is_pointer_ungrabbed = False; Bool do_menu_interaction; Bool do_check_pop_down; Bool do_warp; Time t0 = fev_get_evtime(); XEvent tmpevent; double_keypress dkp; /* don't save these ones, we want them to work even within recursive * menus popped up by dynamic actions. */ static int indirect_depth = 0; static int x_start; static int y_start; int scr_x, scr_y; int scr_w, scr_h; pmret->rc = MENU_NOP; if (pmp->flags.is_sticky && !pmp->flags.is_submenu) { FCheckTypedEvent(dpy, ButtonPressMask, &tmpevent); } if (pmp->menu == NULL) { pmret->rc = MENU_ERROR; return; } key_press = pmp->flags.is_triggered_by_keypress; /* Try to pick a root-relative optimal x,y to * put the mouse right on the title w/o warping */ if (FQueryPointer(dpy, Scr.Root, &JunkRoot, &JunkChild, &x, &y, &JunkX, &JunkY, &JunkMask) == False) { /* pointer is on a different screen */ x = 0; y = 0; } /* Save these - we want to warp back here if this is a top level * menu brought up by a keystroke */ if (!pmp->flags.is_submenu) { pmp->flags.is_invoked_by_key_press = key_press; pmp->flags.is_first_root_menu = !indirect_depth; } else { pmp->flags.is_first_root_menu = 0; } if (!pmp->flags.is_submenu && indirect_depth == 0) { if (key_press) { x_start = x; y_start = y; } else { x_start = -1; y_start = -1; } pmp->screen_origin_x = pmp->pops->pos_hints.screen_origin_x; pmp->screen_origin_y = pmp->pops->pos_hints.screen_origin_y; } if (pmp->pops->flags.do_warp_title) { do_warp = True; } else if (pmp->pops->flags.do_not_warp) { do_warp = False; } else if (key_press) { do_warp = True; } else { do_warp = False; } /* Figure out where we should popup, if possible */ if (!pmp->flags.is_already_mapped) { Bool prefer_left_submenus = False; /* Make sure we are using the latest style and menu layout. */ update_menu(pmp->menu, pmp); if (pmp->flags.is_submenu) { /* this is a submenu popup */ get_prefered_popup_position( pmp->parent_menu, pmp->menu, &x, &y, &prefer_left_submenus); } else { fscreen_scr_arg fscr; /* we're a top level menu */ if (!GrabEm(CRS_MENU, GRAB_MENU)) { /* GrabEm specifies the cursor to use */ XBell(dpy, 0); pmret->rc = MENU_ABORTED; return; } is_pointer_grabbed = True; /* Make the menu appear under the pointer rather than * warping */ fscr.xypos.x = x; fscr.xypos.y = y; FScreenGetScrRect( &fscr, FSCREEN_XYPOS, &scr_x, &scr_y, &scr_w, &scr_h); x -= menudim_middle_x_offset(&MR_DIM(pmp->menu)); y -= menuitem_middle_y_offset( MR_FIRST_ITEM(pmp->menu), MR_STYLE(pmp->menu)); if (x < scr_x) { x = scr_x; } if (y < scr_y) { y = scr_y; } } /* pop_menu_up may move the x,y to make it fit on screen more * nicely. It might also move parent_menu out of the way. */ if (!pop_menu_up( &(pmp->menu), pmp, pmp->parent_menu, NULL, pmp->pexc, x, y, prefer_left_submenus, do_warp, pmp->pops, NULL, None)) { XBell(dpy, 0); UngrabEm(GRAB_MENU); pmret->rc = MENU_ERROR; return; } } else { fWasAlreadyPopped = True; if (pmp->tear_off_root_menu_window != NULL) { if (!GrabEm(CRS_MENU, GRAB_MENU)) { /* GrabEm specifies the cursor to use */ XBell(dpy, 0); pmret->rc = MENU_ABORTED; return; } is_pointer_grabbed = True; } if (key_press) { warp_pointer_to_item( pmp->menu, MR_FIRST_ITEM(pmp->menu), True /* skip Title */); } } /* Remember the key that popped up the root menu. */ if (pmp->flags.is_submenu) { dkp.timestamp = 0; } else { if (pmp->flags.is_triggered_by_keypress) { /* we have a real key event */ dkp.keystate = (*pmp->pexc)->x.etrigger->xkey.state; dkp.keycode = (*pmp->pexc)->x.etrigger->xkey.keycode; } dkp.timestamp = (key_press && pmp->flags.has_default_action) ? t0 : 0; } if (!pmp->flags.is_submenu && indirect_depth == 0) { /* we need to grab the keyboard so we are sure no key presses * are lost */ MyXGrabKeyboard(dpy); } /* This may loop for tear off menus */ for (do_menu_interaction = True; do_menu_interaction == True; ) { if (is_pointer_ungrabbed && !GrabEm(CRS_MENU, GRAB_MENU)) { /* re-grab the pointer in this cycle */ XBell(dpy, 0); pmret->rc = MENU_ABORTED; break; } do_menu_interaction = False; if (pmp->pops->flags.do_tear_off_immediately == 1) { pmret->rc = MENU_TEAR_OFF; } else { if (!pmp->flags.is_submenu) { XSelectInput( dpy, Scr.NoFocusWin, XEVMASK_MENUNFW); XFlush(dpy); } __menu_loop(pmp, pmret, &dkp); if (!pmp->flags.is_submenu) { XSelectInput( dpy, Scr.NoFocusWin, XEVMASK_NOFOCUSW); XFlush(dpy); } } do_check_pop_down = False; switch (pmret->rc) { case MENU_TEAR_OFF: menu_tear_off(pmp->menu); pop_menu_down(&pmp->menu, pmp); break; case MENU_KILL_TEAR_OFF_MENU: if (MR_IS_TEAR_OFF_MENU(pmp->menu)) { /* kill the menu */ do_menu_close_tear_off_menu(pmp->menu, *pmp); pmret->rc = MENU_ABORTED; } else { /* pass return code up to the torn off menu */ } break; case MENU_DOUBLE_CLICKED: case MENU_DONE: if (MR_IS_TEAR_OFF_MENU(pmp->menu)) { do_menu_interaction = True; } else { do_check_pop_down = True; } break; case MENU_SUBMENU_TORN_OFF: pmret->rc = MENU_ABORTED; do_check_pop_down = True; break; default: do_check_pop_down = True; break; } if (do_check_pop_down == True) { /* popping down may destroy the menu via the dynamic * popdown action! */ if (!MR_IS_TEAR_OFF_MENU(pmp->menu) && fWasAlreadyPopped == False) { pop_menu_down(&pmp->menu, pmp); } } XFlush(dpy); if (!pmp->flags.is_submenu && x_start >= 0 && y_start >= 0 && pmret->flags.is_key_press && pmret->rc != MENU_TEAR_OFF) { /* warp pointer back to where invoked if this was * brought up with a keypress and we're returning from * a top level menu, and a button release event didn't * end it */ FWarpPointer( dpy, 0, Scr.Root, 0, 0, Scr.MyDisplayWidth, Scr.MyDisplayHeight, x_start, y_start); if ((*pmp->pexc)->x.elast->type == KeyPress) { XEvent e = *(*pmp->pexc)->x.elast; e.xkey.x_root = x_start; e.xkey.y_root = y_start; fev_fake_event(&e); } } if (pmret->rc == MENU_TEAR_OFF) { pmret->rc = MENU_SUBMENU_TORN_OFF; } dkp.timestamp = 0; if (is_pointer_grabbed) { UngrabEm(GRAB_MENU); WaitForButtonsUp(True); is_pointer_ungrabbed = True; } if (!pmp->flags.is_submenu) { if (pmret->rc == MENU_DONE) { if (pmp->ret_paction && *pmp->ret_paction) { indirect_depth++; /* Execute the action */ __menu_execute_function( pmp->pexc, *pmp->ret_paction); indirect_depth--; free(*pmp->ret_paction); *pmp->ret_paction = NULL; } last_saved_pos_hints.flags. do_ignore_pos_hints = False; last_saved_pos_hints.flags. is_last_menu_pos_hints_valid = False; } if (indirect_depth == 0) { last_saved_pos_hints.flags. do_ignore_pos_hints = False; last_saved_pos_hints.flags. is_last_menu_pos_hints_valid = False; } } } if (!pmp->flags.is_submenu && indirect_depth == 0) { /* release the keyboard when the last menu closes */ MyXUngrabKeyboard(dpy); } return; } Bool menu_expose(XEvent *event, FvwmWindow *fw) { MenuRoot *mr = NULL; if ((XFindContext( dpy, event->xany.window, MenuContext, (caddr_t *)&mr) != XCNOENT)) { flush_accumulate_expose(event->xany.window, event); paint_menu(mr, event, fw); return True; } else { return False; } } /* * * Procedure: * update_transparent_menu_bg - set the background of the menu to * match a forseen move of a menu. If the background is updated * for the target position before the move is done, and repainted * after the move, the move will look more seamless. * * This method should be folleowd by a call to repaint_transparent_menu * with the same step_x, stey_y, end_x and any_y, with is_bg_set True */ void update_transparent_menu_bg( MenuRepaintTransparentParameters *prtm, int current_x, int current_y, int step_x, int step_y, int end_x, int end_y) { MenuRoot *mr; MenuStyle *ms; Bool last = False; mr = prtm->mr; ms = MR_STYLE(mr); if (step_x == end_x && step_y == end_y) { last = True; } if (!last && CSET_IS_TRANSPARENT_PR_TINT(ST_CSET_MENU(ms))) { /* too slow ... */ return; } SetWindowBackgroundWithOffset( dpy, MR_WINDOW(mr), step_x - current_x, step_y - current_y, MR_WIDTH(mr), MR_HEIGHT(mr), &Colorset[ST_CSET_MENU(ms)], Pdepth, FORE_GC(MST_MENU_INACTIVE_GCS(mr)), False); } /* * * Procedure: * repaint_transparent_menu - repaint the menu background if it is * tranparent during an animated move. Called in move_resize.c * (AnimatedMoveAnyWindow). Performance improvement Welcome! * ideas: - write the foreground into a pixmap and a mask the first time * this function is called. Then use these pixmaps to draw * the items * - Use a Buffer if !IS_TRANSPARENT_PR_PURE and if we do not have one * already */ void repaint_transparent_menu( MenuRepaintTransparentParameters *prtm, Bool first, int x, int y, int end_x, int end_y, Bool is_bg_set) { MenuItem *mi; MenuRoot *mr; MenuStyle *ms; int h = 0; int s_h = 0; int e_h = 0; Bool last = False; mr = prtm->mr; ms = MR_STYLE(mr); if (x == end_x && y == end_y) { last = True; } if (!last && CSET_IS_TRANSPARENT_PR_TINT(ST_CSET_MENU(ms))) { /* too slow ... */ return; } if (!is_bg_set) { SetWindowBackground( dpy, MR_WINDOW(mr), MR_WIDTH(mr), MR_HEIGHT(mr), &Colorset[ST_CSET_MENU(ms)], Pdepth, FORE_GC(MST_MENU_INACTIVE_GCS(mr)), False); } /* redraw the background of non active item */ for (mi = MR_FIRST_ITEM(mr); mi != NULL; mi = MI_NEXT_ITEM(mi)) { if (mi == MR_SELECTED_ITEM(mr) && MST_DO_HILIGHT_BACK(mr)) { int left; left = MR_HILIGHT_X_OFFSET(mr) - MR_ITEM_X_OFFSET(mr); if (left > 0) { XClearArea( dpy, MR_WINDOW(mr), MR_ITEM_X_OFFSET(mr), MI_Y_OFFSET(mi), left, MI_HEIGHT(mi) + MST_RELIEF_THICKNESS(mr), 0); } h = MI_HEIGHT(mi); continue; } if (h == 0) { s_h += MI_HEIGHT(mi); } else { e_h += MI_HEIGHT(mi); } } XClearArea( dpy, MR_WINDOW(mr), MR_ITEM_X_OFFSET(mr), MST_BORDER_WIDTH(mr), MR_ITEM_WIDTH(mr), s_h, 0); if (e_h != 0) { XClearArea( dpy, MR_WINDOW(mr), MR_ITEM_X_OFFSET(mr), s_h + h + MST_RELIEF_THICKNESS(mr) + MST_BORDER_WIDTH(mr), MR_ITEM_WIDTH(mr), e_h, 0); } /* now redraw the items */ for (mi = MR_FIRST_ITEM(mr); mi != NULL; mi = MI_NEXT_ITEM(mi)) { MenuPaintItemParameters mpip; if (mi == MR_SELECTED_ITEM(mr) && MST_DO_HILIGHT_BACK(mr) && !CSET_IS_TRANSPARENT_PR_TINT(ST_CSET_MENU(ms))) { continue; } get_menu_paint_item_parameters( &mpip, mr, NULL, prtm->fw, NULL, True); mpip.flags.is_first_item = (MR_FIRST_ITEM(mr) == mi); menuitem_paint(mi, &mpip); } /* if we have a side pic and no side colors we shound repaint the side * pic */ if ((MR_SIDEPIC(mr) || MST_SIDEPIC(mr)) && !MR_HAS_SIDECOLOR(mr) && !MST_HAS_SIDE_COLOR(mr)) { FvwmPicture *sidePic; if (MR_SIDEPIC(mr)) { sidePic = MR_SIDEPIC(mr); } else if (MST_SIDEPIC(mr)) { sidePic = MST_SIDEPIC(mr); } else { return; } XClearArea( dpy, MR_WINDOW(mr), MR_SIDEPIC_X_OFFSET(mr), MST_BORDER_WIDTH(mr), sidePic->width, MR_HEIGHT(mr) - 2 * MST_BORDER_WIDTH(mr), 0); paint_side_pic(mr, NULL); } } Bool DestroyMenu(MenuRoot *mr, Bool do_recreate, Bool is_command_request) { MenuItem *mi,*tmp2; MenuRoot *tmp, *prev; Bool in_list = True; if (mr == NULL) { return False; } /* seek menu in master list */ tmp = Menus.all; prev = NULL; while (tmp && tmp != mr) { prev = tmp; tmp = MR_NEXT_MENU(tmp); } if (tmp != mr) { /* no such menu */ in_list = False; } if (MR_MAPPED_COPIES(mr) > 0 && (is_command_request || MR_COPIES(mr) == 1)) { /* can't destroy a menu while in use */ fvwm_msg(ERR, "DestroyMenu", "Menu %s is in use", MR_NAME(mr)); return False; } if (in_list && MR_COPIES(mr) > 1 && MR_ORIGINAL_MENU(mr) == mr) { MenuRoot *m; MenuRoot *new_orig; /* find a new 'original' menu */ for (m = Menus.all, new_orig = NULL; m; m = MR_NEXT_MENU(m)) { if (m != mr && MR_ORIGINAL_MENU(m) == mr) { if (new_orig == NULL) { new_orig = m; } MR_ORIGINAL_MENU(m) = new_orig; } } MR_ORIGINAL_MENU(mr) = new_orig; /* now dump old original menu */ } MR_COPIES(mr)--; if (MR_STORED_ITEM(mr).stored) { XFreePixmap(dpy, MR_STORED_ITEM(mr).stored); } if (MR_COPIES(mr) > 0) { do_recreate = False; } else { /* free all items */ mi = MR_FIRST_ITEM(mr); while (mi != NULL) { tmp2 = MI_NEXT_ITEM(mi); menuitem_free(mi); mi = tmp2; } if (do_recreate) { /* just dump the menu items but keep the menu itself */ MR_COPIES(mr)++; MR_FIRST_ITEM(mr) = NULL; MR_LAST_ITEM(mr) = NULL; MR_SELECTED_ITEM(mr) = NULL; MR_CONTINUATION_MENU(mr) = NULL; MR_PARENT_MENU(mr) = NULL; MR_ITEMS(mr) = 0; memset(&(MR_STORED_ITEM(mr)), 0 , sizeof(MR_STORED_ITEM(mr))); MR_IS_UPDATED(mr) = 1; return True; } } /* unlink menu from list */ if (in_list) { if (prev == NULL) { Menus.all = MR_NEXT_MENU(mr); } else { MR_NEXT_MENU(prev) = MR_NEXT_MENU(mr); } } /* destroy the window and the display */ if (MR_WINDOW(mr) != None) { XDeleteContext(dpy, MR_WINDOW(mr), MenuContext); XFlush(dpy); XDestroyWindow(MR_CREATE_DPY(mr), MR_WINDOW(mr)); MR_WINDOW(mr) = None; XFlush(MR_CREATE_DPY(mr)); } if (MR_CREATE_DPY(mr) != NULL && MR_CREATE_DPY(mr) != dpy) { XCloseDisplay(MR_CREATE_DPY(mr)); MR_CREATE_DPY(mr) = NULL; } if (MR_COPIES(mr) == 0) { if (MR_POPUP_ACTION(mr)) { free(MR_POPUP_ACTION(mr)); } if (MR_POPDOWN_ACTION(mr)) { free(MR_POPDOWN_ACTION(mr)); } if (MR_MISSING_SUBMENU_FUNC(mr)) { free(MR_MISSING_SUBMENU_FUNC(mr)); } free(MR_NAME(mr)); if (MR_SIDEPIC(mr)) { PDestroyFvwmPicture(dpy, MR_SIDEPIC(mr)); } memset(mr->s, 0, sizeof(*(mr->s))); free(mr->s); } memset(mr->d, 0, sizeof(*(mr->d))); free(mr->d); memset(mr, 0, sizeof(*mr)); free(mr); return True; } /* FollowMenuContinuations * Given an menu root, return the menu root to add to by * following continuation links until there are no more */ MenuRoot *FollowMenuContinuations(MenuRoot *mr, MenuRoot **pmrPrior ) { *pmrPrior = NULL; while ((mr != NULL) && (MR_CONTINUATION_MENU(mr) != NULL)) { *pmrPrior = mr; mr = MR_CONTINUATION_MENU(mr); } return mr; } /* * * Procedure: * AddToMenu - add an item to a root menu * * Returned Value: * (MenuItem *) * * Inputs: * menu - pointer to the root menu to add the item * item - the text to appear in the menu * action - the string to possibly execute * * ckh - need to add boolean to say whether or not to expand for pixmaps, * so built in window list can handle windows w/ * and % in title. * */ void AddToMenu( MenuRoot *mr, char *item, char *action, Bool fPixmapsOk, Bool fNoPlus, Bool is_continuation_item) { MenuItem *tmp; char *start; char *end; char *token = NULL; char *option = NULL; int i; int is_empty; Bool do_replace_title; if (MR_MAPPED_COPIES(mr) > 0) { /* whoa, we can't handle *everything* */ return; } if ((item == NULL || *item == 0) && (action == NULL || *action == 0) && fNoPlus) { return; } /* empty items screw up our menu when painted, so we replace them with * a separator */ if (item == NULL) item = ""; /* * Handle dynamic actions */ if (StrEquals(item, "DynamicPopupAction")) { if (MR_POPUP_ACTION(mr)) { free(MR_POPUP_ACTION(mr)); } if (!action || *action == 0) { MR_POPUP_ACTION(mr) = NULL; } else { MR_POPUP_ACTION(mr) = stripcpy(action); } return; } else if (StrEquals(item, "DynamicPopdownAction")) { if (MR_POPDOWN_ACTION(mr)) { free(MR_POPDOWN_ACTION(mr)); } if (!action || *action == 0) { MR_POPDOWN_ACTION(mr) = NULL; } else { MR_POPDOWN_ACTION(mr) = stripcpy(action); } return; } else if (StrEquals(item, "MissingSubmenuFunction")) { if (MR_MISSING_SUBMENU_FUNC(mr)) { free(MR_MISSING_SUBMENU_FUNC(mr)); } if (!action || *action == 0) { MR_MISSING_SUBMENU_FUNC(mr) = NULL; } else { MR_MISSING_SUBMENU_FUNC(mr) = stripcpy(action); } return; } /* * Parse the action */ if (action == NULL || *action == 0) { action = "Nop"; } GetNextToken(GetNextToken(action, &token), &option); tmp = menuitem_create(); if (MR_FIRST_ITEM(mr) != NULL && StrEquals(token, "title") && option != NULL && StrEquals(option, "top")) { do_replace_title = True; } else { do_replace_title = False; } append_item_to_menu(mr, tmp, do_replace_title); if (token) { free(token); } if (option) { free(option); } MI_ACTION(tmp) = stripcpy(action); /* * Parse the labels */ start = item; end = item; for (i = 0; i < MAX_MENU_ITEM_LABELS; i++, start = end) { /* Read label up to next tab. */ if (*end) { if (i < MAX_MENU_ITEM_LABELS - 1) { while (*end && *end != '\t') { /* seek next tab or end of string */ end++; } } else { /* remove all tabs in last label */ while (*end) { if (*end == '\t') { *end = ' '; } end++; } } /* Copy the label. */ MI_LABEL(tmp)[i] = safemalloc(end - start + 1); strncpy(MI_LABEL(tmp)[i], start, end - start); (MI_LABEL(tmp)[i])[end - start] = 0; if (*end == '\t') { /* skip the tab */ end++; } } else { MI_LABEL(tmp)[i] = NULL; } /* Parse the label. */ if (MI_LABEL(tmp)[i] != NULL) { if (fPixmapsOk) { string_def_t item_pixmaps[] = { {'*', __scan_for_pixmap}, {'%', __scan_for_pixmap}, {'\0', NULL}}; string_context_t ctx; SCTX_SET_MI(ctx,tmp); scanForStrings( MI_LABEL(tmp)[i], item_pixmaps, &ctx); } if (!MI_HAS_HOTKEY(tmp)) { /* pete@tecc.co.uk */ scanForHotkeys(tmp, i); if (!MI_HAS_HOTKEY(tmp) && *MI_LABEL(tmp)[i] != 0) { MI_HOTKEY_COFFSET(tmp) = 0; MI_HOTKEY_COLUMN(tmp) = i; MI_HAS_HOTKEY(tmp) = 1; MI_IS_HOTKEY_AUTOMATIC(tmp) = 1; } } if (*(MI_LABEL(tmp)[i])) { MI_HAS_TEXT(tmp) = True; } else { free(MI_LABEL(tmp)[i]); MI_LABEL(tmp)[i] = NULL; } } MI_LABEL_STRLEN(tmp)[i] = (MI_LABEL(tmp)[i]) ? strlen(MI_LABEL(tmp)[i]) : 0; } /* for */ /* * Set the type flags */ if (is_continuation_item) { MI_IS_CONTINUATION(tmp) = True; } find_func_t(MI_ACTION(tmp), &(MI_FUNC_TYPE(tmp)), NULL); switch (MI_FUNC_TYPE(tmp)) { case F_POPUP: MI_IS_POPUP(tmp) = True; case F_WINDOWLIST: case F_STAYSUP: MI_IS_MENU(tmp) = True; break; case F_TITLE: MI_IS_TITLE(tmp) = True; break; default: break; } is_empty = (!MI_HAS_TEXT(tmp) && !MI_HAS_PICTURE(tmp)); if (is_empty) { if (MI_FUNC_TYPE(tmp) == F_TEARMENUOFF) { MI_IS_TEAR_OFF_BAR(tmp) = 1; MI_IS_SEPARATOR(tmp) = 0; } else { MI_IS_TEAR_OFF_BAR(tmp) = 0; MI_IS_SEPARATOR(tmp) = 1; } } if (MI_IS_SEPARATOR(tmp)) { /* An empty title is handled like a separator. */ MI_IS_TITLE(tmp) = False; } MI_IS_SELECTABLE(tmp) = ((MI_HAS_TEXT(tmp) || MI_HAS_PICTURE(tmp) || MI_IS_TEAR_OFF_BAR(tmp)) && !MI_IS_TITLE(tmp)); /* * misc stuff */ MR_ITEMS(mr)++; MR_IS_UPDATED(mr) = 1; return; } /* * * Procedure: * NewMenuRoot - create a new menu root * * Returned Value: * (MenuRoot *) * * Inputs: * name - the name of the menu root * */ MenuRoot *NewMenuRoot(char *name) { MenuRoot *mr; string_def_t root_strings[] = { {'@', __scan_for_pixmap}, {'^', __scan_for_color}, {'\0', NULL}}; string_context_t ctx; mr = (MenuRoot *)safemalloc(sizeof(MenuRoot)); mr->s = (MenuRootStatic *)safemalloc(sizeof(MenuRootStatic)); mr->d = (MenuRootDynamic *)safemalloc(sizeof(MenuRootDynamic)); memset(mr->s, 0, sizeof(MenuRootStatic)); memset(mr->d, 0, sizeof(MenuRootDynamic)); MR_NEXT_MENU(mr) = Menus.all; MR_NAME(mr) = safestrdup(name); MR_WINDOW(mr) = None; SCTX_SET_MR(ctx,mr); MR_HAS_SIDECOLOR(mr) = False; scanForStrings( MR_NAME(mr), root_strings, &ctx); MR_STYLE(mr) = menustyle_get_default_style(); MR_ORIGINAL_MENU(mr) = mr; MR_COPIES(mr) = 1; MR_IS_UPDATED(mr) = 1; Menus.all = mr; return mr; } void SetMenuCursor(Cursor cursor) { MenuRoot *mr; mr = Menus.all; for (mr = Menus.all; mr; mr = MR_NEXT_MENU(mr)) { if (MR_WINDOW(mr)) { XDefineCursor(dpy, MR_WINDOW(mr), cursor); } } return; } void UpdateAllMenuStyles(void) { MenuStyle *ms; for (ms = menustyle_get_default_style(); ms; ms = ST_NEXT_STYLE(ms)) { menustyle_update(ms); } return; } void UpdateMenuColorset(int cset) { MenuStyle *ms; FvwmWindow *t; for (ms = menustyle_get_default_style(); ms; ms = ST_NEXT_STYLE(ms)) { if ((ST_HAS_MENU_CSET(ms) && ST_CSET_MENU(ms) == cset) || (ST_HAS_ACTIVE_CSET(ms) && ST_CSET_ACTIVE(ms) == cset) || (ST_HAS_GREYED_CSET(ms) && ST_CSET_GREYED(ms) == cset) || (ST_HAS_TITLE_CSET(ms) && ST_CSET_TITLE(ms) == cset)) { menustyle_update(ms); } } for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) { MenuRoot *mr = NULL; MenuStyle *ms = NULL; if (IS_TEAR_OFF_MENU(t) && XFindContext(dpy, FW_W(t), MenuContext, (caddr_t *)&mr) != XCNOENT && (ms = MR_STYLE(mr))) { if (ST_HAS_MENU_CSET(ms) && ST_CSET_MENU(ms) == cset) { SetWindowBackground( dpy, MR_WINDOW(mr), MR_WIDTH(mr), MR_HEIGHT(mr), &Colorset[ST_CSET_MENU(ms)], Pdepth, FORE_GC(MST_MENU_INACTIVE_GCS(mr)), True); } else if ((ST_HAS_ACTIVE_CSET(ms) && ST_CSET_ACTIVE(ms) == cset) || (ST_HAS_GREYED_CSET(ms) && ST_CSET_GREYED(ms) == cset)) { paint_menu(mr, NULL, NULL); } } } return; } /* This is called by the window list function */ void change_mr_menu_style(MenuRoot *mr, char *stylename) { MenuStyle *ms = NULL; ms = menustyle_find(stylename); if (ms == NULL) { return; } if (MR_MAPPED_COPIES(mr) != 0) { fvwm_msg(ERR,"ChangeMenuStyle", "menu %s is in use", MR_NAME(mr)); } else { MR_STYLE(mr) = ms; MR_IS_UPDATED(mr) = 1; } return; } void add_another_menu_item(char *action) { MenuRoot *mr; MenuRoot *mrPrior; char *rest,*item; mr = FollowMenuContinuations(Scr.last_added_item.item, &mrPrior); if (mr == NULL) { return; } if (MR_MAPPED_COPIES(mr) != 0) { fvwm_msg(ERR,"add_another_menu_item", "menu is in use"); return; } rest = GetNextToken(action,&item); AddToMenu(mr, item, rest, True /* pixmap scan */, False, False); if (item) { free(item); } return; } /* * get_menu_options is used for Menu, Popup and WindowList * It parses strings matching * * [ [context-rectangle] x y ] [special-options] [other arguments] * * and returns a pointer to the first part of the input string that doesn't * match this syntax. * * See documentation for a detailed description. */ char *get_menu_options( char *action, Window w, FvwmWindow *fw, XEvent *e, MenuRoot *mr, MenuItem *mi, MenuOptions *pops) { char *tok = NULL; char *naction = action; char *taction; int x; int y; int button; int width; int height; int dummy_int; float dummy_float; Bool dummy_flag; Window context_window = None; Bool fHasContext, fUseItemOffset, fRectangleContext, fXineramaRoot; Bool fValidPosHints = last_saved_pos_hints.flags.is_last_menu_pos_hints_valid; Bool is_action_empty = False; Bool once_more = True; Bool is_icon_context; rectangle icon_g; /* If this is set we may want to reverse the position hints, so don't * sum up the totals right now. This is useful for the SubmenusLeft * style. */ fXineramaRoot = False; last_saved_pos_hints.flags.is_last_menu_pos_hints_valid = False; if (pops == NULL) { fvwm_msg(ERR, "get_menu_options","no MenuOptions pointer passed"); return action; } taction = action; memset(&(pops->flags), 0, sizeof(pops->flags)); pops->flags.has_poshints = 0; if (!action || *action == 0) { is_action_empty = True; } while (action != NULL && *action != 0 && once_more) { /* ^ just to be able to jump to end of loop without 'goto' */ pops->pos_hints.is_relative = False; pops->pos_hints.menu_width = 0; pops->pos_hints.is_menu_relative = False; /* parse context argument (if present) */ naction = GetNextToken(taction, &tok); if (!tok) { /* no context string */ fHasContext = False; is_action_empty = True; break; } /* set to False for absolute hints! */ pops->pos_hints.is_relative = True; fUseItemOffset = False; fHasContext = True; fRectangleContext = False; is_icon_context = False; if (StrEquals(tok, "context")) { if (mi && mr) { context_window = MR_WINDOW(mr); } else if (fw) { if (IS_ICONIFIED(fw)) { is_icon_context = True; get_icon_geometry(fw, &icon_g); context_window = None; } else { context_window = FW_W_FRAME(fw); } } else { context_window = w; } } else if (StrEquals(tok,"menu")) { if (mr) { context_window = MR_WINDOW(mr); pops->pos_hints.is_menu_relative = True; pops->pos_hints.menu_width = MR_WIDTH(mr); } } else if (StrEquals(tok,"item")) { if (mi && mr) { context_window = MR_WINDOW(mr); fUseItemOffset = True; pops->pos_hints.is_menu_relative = True; pops->pos_hints.menu_width = MR_WIDTH(mr); } } else if (StrEquals(tok,"icon")) { if (fw && IS_ICONIFIED(fw)) { is_icon_context = True; get_icon_geometry(fw, &icon_g); context_window = None; } } else if (StrEquals(tok,"window")) { if (fw && !IS_ICONIFIED(fw)) { context_window = FW_W_FRAME(fw); } } else if (StrEquals(tok,"interior")) { if (fw && !IS_ICONIFIED(fw)) { context_window = FW_W(fw); } } else if (StrEquals(tok,"title")) { if (fw) { if (IS_ICONIFIED(fw)) { context_window = FW_W_ICON_TITLE(fw); } else { context_window = FW_W_TITLE(fw); } } } else if (strncasecmp(tok,"button",6) == 0) { if (sscanf(&(tok[6]),"%d",&button) != 1 || tok[6] == '+' || tok[6] == '-' || button < 0 || button > 9) { fHasContext = False; } else if (fw && !IS_ICONIFIED(fw)) { button = BUTTON_INDEX(button); context_window = FW_W_BUTTON(fw, button); } } else if (StrEquals(tok,"root")) { context_window = Scr.Root; pops->pos_hints.is_relative = False; } else if (StrEquals(tok,"xineramaroot")) { context_window = Scr.Root; pops->pos_hints.is_relative = False; fXineramaRoot = True; } else if (StrEquals(tok,"mouse")) { context_window = None; } else if (StrEquals(tok,"rectangle")) { int flags; int screen; int sx; int sy; int sw; int sh; /* parse the rectangle */ free(tok); naction = GetNextToken(naction, &tok); if (tok == NULL) { fvwm_msg(ERR, "get_menu_options", "missing rectangle geometry"); if (!pops->pos_hints.has_screen_origin) { /* xinerama: emergency fallback */ pops->pos_hints.has_screen_origin = 1; pops->pos_hints.screen_origin_x = 0; pops->pos_hints.screen_origin_y = 0; } return action; } flags = FScreenParseGeometryWithScreen( tok, &x, &y, (unsigned int*)&width, (unsigned int*)&height, &screen); if ((flags & (XValue | YValue)) != (XValue | YValue)) { free(tok); fvwm_msg(ERR, "get_menu_options", "invalid rectangle geometry"); if (!pops->pos_hints.has_screen_origin) { /* xinerama: emergency fallback */ pops->pos_hints.has_screen_origin = 1; pops->pos_hints.screen_origin_x = 0; pops->pos_hints.screen_origin_y = 0; } return action; } pops->pos_hints.has_screen_origin = 1; FScreenGetScrRect(NULL, screen, &sx, &sy, &sw, &sh); pops->pos_hints.screen_origin_x = sx; pops->pos_hints.screen_origin_y = sy; if (!(flags & WidthValue)) { width = 1; } if (!(flags & HeightValue)) { height = 1; } x += sx; y += sy; if (flags & XNegative) { /* x is negative */ x = sx + sw + x; } if (flags & YNegative) { /* y is negative */ y = sy + sh + y; } pops->pos_hints.is_relative = False; fRectangleContext = True; } else if (StrEquals(tok,"this")) { MenuRoot *dummy_mr; context_window = w; if (XFindContext( dpy, w, MenuContext, (caddr_t *)&dummy_mr) != XCNOENT) { if (mr) { /* the parent menu */ pops->pos_hints.is_menu_relative = True; pops->pos_hints.menu_width = MR_WIDTH(mr); } } } else { /* no context string */ fHasContext = False; } if (tok) { free(tok); } if (fHasContext) { taction = naction; } else { naction = action; } if (fRectangleContext) { if (!pops->pos_hints.has_screen_origin) { /* xinerama: use global screen as reference */ pops->pos_hints.has_screen_origin = 1; pops->pos_hints.screen_origin_x = -1; pops->pos_hints.screen_origin_y = -1; } /* nothing else to do */ } else if (!is_icon_context && (!fHasContext || !context_window || !XGetGeometry( dpy, context_window, &JunkRoot, &JunkX, &JunkY, (unsigned int*)&width, (unsigned int*)&height, (unsigned int*)&JunkBW, (unsigned int*)&JunkDepth) || !XTranslateCoordinates( dpy, context_window, Scr.Root, 0, 0, &x, &y, &JunkChild))) { /* no window or could not get geometry */ if (FQueryPointer( dpy,Scr.Root, &JunkRoot, &JunkChild, &x, &y, &JunkX, &JunkY, &JunkMask) == False) { /* pointer is on a different screen - that's * okay here */ x = 0; y = 0; } width = height = 1; if (!pops->pos_hints.has_screen_origin) { /* xinerama: use screen with pinter as * reference */ pops->pos_hints.has_screen_origin = 1; pops->pos_hints.screen_origin_x = x; pops->pos_hints.screen_origin_y = y; } } else { if (is_icon_context) { x = icon_g.x; y = icon_g.y; width = icon_g.width; height = icon_g.height; } /* we have a context window */ if (fUseItemOffset) { y += MI_Y_OFFSET(mi); height = MI_HEIGHT(mi); } if (!pops->pos_hints.has_screen_origin) { pops->pos_hints.has_screen_origin = 1; if (fXineramaRoot) { /* use whole screen */ pops->pos_hints.screen_origin_x = -1; pops->pos_hints.screen_origin_y = -1; } else if (context_window == Scr.Root) { /* xinerama: use screen that contains * the window center as reference */ if (!fev_get_evpos_or_query( dpy, context_window, e, &pops->pos_hints. screen_origin_x, &pops->pos_hints. screen_origin_y)) { pops->pos_hints. screen_origin_x = 0; pops->pos_hints. screen_origin_y = 0; } else { fscreen_scr_arg fscr; fscr.xypos.x = pops->pos_hints. screen_origin_x; fscr.xypos.y = pops->pos_hints. screen_origin_y; FScreenGetScrRect( &fscr, FSCREEN_XYPOS, &x, &y, &width, &height); } } else { /* xinerama: use screen that contains * the window center as reference */ pops->pos_hints.screen_origin_x = JunkX + width / 2; pops->pos_hints.screen_origin_y = JunkY + height / 2; } } } /* parse position arguments */ taction = get_one_menu_position_argument( naction, x, width, &(pops->pos_hints.x), &(pops->pos_hints.x_offset), &(pops->pos_hints.x_factor), &(pops->pos_hints.context_x_factor), &pops->pos_hints.is_menu_relative); if (pops->pos_hints.is_menu_relative) { pops->pos_hints.x = x; if (pops->pos_hints.menu_width == 0 && mr) { pops->pos_hints.menu_width = MR_WIDTH(mr); } } naction = get_one_menu_position_argument( taction, y, height, &(pops->pos_hints.y), &dummy_int, &(pops->pos_hints.y_factor), &dummy_float, &dummy_flag); if (naction == taction) { /* argument is missing or invalid */ if (fHasContext) { fvwm_msg(ERR, "get_menu_options", "invalid position arguments"); } naction = action; taction = action; break; } taction = naction; pops->flags.has_poshints = 1; if (fValidPosHints == True && pops->pos_hints.is_relative == True) { pops->pos_hints = last_saved_pos_hints.pos_hints; } /* we want to do this only once */ once_more = False; } /* while */ if (is_action_empty) { if (!pops->pos_hints.has_screen_origin) { pops->pos_hints.has_screen_origin = 1; if (!fev_get_evpos_or_query( dpy, Scr.Root, e, &pops->pos_hints.screen_origin_x, &pops->pos_hints.screen_origin_y)) { pops->pos_hints.screen_origin_x = 0; pops->pos_hints.screen_origin_y = 0; } } } if (!pops->flags.has_poshints && fValidPosHints) { pops->flags.has_poshints = 1; pops->pos_hints = last_saved_pos_hints.pos_hints; pops->pos_hints.is_relative = False; } action = naction; /* to keep Purify silent */ pops->flags.do_select_in_place = 0; /* parse additional options */ while (naction && *naction) { naction = GetNextToken(action, &tok); if (!tok) { break; } if (StrEquals(tok, "WarpTitle")) { pops->flags.do_warp_title = 1; pops->flags.do_not_warp = 0; } else if (StrEquals(tok, "NoWarp")) { pops->flags.do_warp_title = 0; pops->flags.do_not_warp = 1; } else if (StrEquals(tok, "Fixed")) { pops->flags.is_fixed = 1; } else if (StrEquals(tok, "SelectInPlace")) { pops->flags.do_select_in_place = 1; } else if (StrEquals(tok, "SelectWarp")) { pops->flags.do_warp_on_select = 1; } else if (StrEquals(tok, "TearOffImmediately")) { pops->flags.do_tear_off_immediately = 1; } else { free (tok); break; } action = naction; free (tok); } if (!pops->flags.do_select_in_place) { pops->flags.do_warp_on_select = 0; } return action; } /* ---------------------------- new menu loop code ------------------------- */ #if 0 /*!!!*/ typedef enum { MTR_XEVENT = 0x1, MTR_FAKE_ENTER_ITEM = 0x2, MTR_PROPAGATE_XEVENT_UP = 0x4, MTR_PROPAGATE_XEVENT_DOWN = 0x8, MTR_POPUP_TIMEOUT = 0x10, MTR_POPDOWN_TIMEOUT = 0x20 } mloop_trigger_type_t; typedef_struct { mloop_trigger_type_t type; XEvent trigger_ev; int ticks_passed; } mloop_trigger_t; typedef_struct { int popup_10ms; int popdown_10ms; } mloop_timeouts_t; typedef struct { MenuRoot *current_menu; XEvent *in_ev; struct { unsigned do_fake_enter_item : 1; unsigned do_propagete_event_up : 1; unsigned do_propagete_event_down : 1; } flags; } mloop_get_trigger_input_t; /*!!!static*/ mloop_trigger_type_t __mloop_get_trigger( mloop_trigger_t *ret_trigger, mloop_timeouts_t *io_timeouts, const mloop_get_trigger_input_t * const in, { if (in_out->in_flags->do_propagate_event_down) { return MTR_PROPAGATE_XEVENT_DOWN; } else if (in_out->in_flags->do_propagate_event_up) { if (a != b) { return MTR_PROPAGATE_XEVENT_UP; } else { } /*!!!return propagate up*/ /*!!!*/ } /*!!!read event or wait for timeout*/ while (0/*!!!not finished*/) { /*!!!rc = 0*/ if (0/*!!!wait for tiomeout*/) { /*!!!check for event*/ } else { /*!!!block for event*/ } if (0/*got event*/) { /*!!!rc = MTR_XEVENT*/ } if (0/*!!!popup timed out;break*/) { /*!!!rc = MTR_POPUP;break*/ } if (0/*!!!popdown timed out;break*/) { /*!!!rc = MTR_POPDOWN;break*/ } /*!!!sleep*/ } if (0/*!!!rc == MTR_XEVENT && evtype == MotionNotify*/) { /*!!!eat up further MotionNotify events*/ } return 0/*!!!rc*/; } /*!!!static*/ void __menu_loop_new( MenuParameters *pmp, MenuReturn *pmret, double_keypress *pdkp) { mloop_evh_input_t mei; #if 0 mloop_ret_code_t mloop_ret; #endif mloop_evh_data_t med; mloop_static_info_t msi; MenuOptions mops; Bool is_finished; /*!!!init menu loop*/ __mloop_init(pmp, pmret, &mei, &med, &msi, &mops); for (is_finished = False; !is_finished; ) { mloop_trigger_type_t mtr; mtr = __mloop_get_trigger( pmp, pmret, &mei, &med, &msi); switch (mtr) { case MTR_XEVENT: /*!!!handle event*/ break; case MTR_FAKE_ENTER_ITEM: /*!!!fake enter item*/ break; case MTR_PROPAGATE_XEVENT_UP: /*!!!handle propagation*/ break; case MTR_PROPAGATE_XEVENT_DOWN: /*!!!handle propagation*/ break; case MTR_POPUP_TIMEOUT: /*!!!handle popup*/ break; case MTR_POPDOWN_TIMEOUT: /*!!!handle popdown*/ break; } #if 0 mloop_ret = __mloop_handle_event( pmp, pmret, pdkp, &mei, &med, &msi); switch (mloop_ret) { case MENU_MLOOP_RET_LOOP: continue; case MENU_MLOOP_RET_END: is_finished = True; break; default: break; } /* Now handle new menu items, whether it is from a * keypress or a pointer motion event. */ if (med.mi != NULL) { mloop_ret = __mloop_handle_action_with_mi( pmp, pmret, pdkp, &mei, &med, &msi, &mops); } else { mloop_ret = __mloop_handle_action_without_mi( pmp, pmret, pdkp, &mei, &med, &msi, &mops); } if (mloop_ret == MENU_MLOOP_RET_END) { is_finished = True; } XFlush(dpy); #endif } __mloop_exit(pmp, pmret, pdkp, &mei, &med, &msi, &mops); return; } #endif fvwm-2.7.0/fvwm/virtual.c0000644000175000017500000014765514147024700012252 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include "libs/fvwmlib.h" #include "libs/FScreen.h" #include "libs/FGettext.h" #include "libs/Grab.h" #include "libs/Parse.h" #include "fvwm.h" #include "externs.h" #include "execcontext.h" #include "cursor.h" #include "events.h" #include "eventmask.h" #include "misc.h" #include "screen.h" #include "virtual.h" #include "module_interface.h" #include "module_list.h" #include "focus.h" #include "ewmh.h" #include "move_resize.h" #include "borders.h" #include "frame.h" #include "geometry.h" #include "icons.h" #include "stack.h" #include "functions.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* * dje 12/19/98 * * Testing with edge_thickness of 1 showed that some XServers don't * care for 1 pixel windows, causing EdgeScrolling not to work with some * servers. One bug report was for SUNOS 4.1.3_U1. We didn't find out * the exact cause of the problem. Perhaps no enter/leave events were * generated. * * Allowed: 0,1,or 2 pixel pan frames. * * 0 completely disables mouse edge scrolling, even while dragging a * window. * * 1 gives the smallest pan frames, which seem to work best except on * some servers. * * 2 is the default. */ static int edge_thickness = 2; static int last_edge_thickness = 2; static int prev_page_x = 0; static int prev_page_y = 0; static int prev_desk = 0; static int prev_desk_and_page_desk = 0; static int prev_desk_and_page_page_x = 0; static int prev_desk_and_page_page_y = 0; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ static Bool _pred_button_event(Display *display, XEvent *event, XPointer arg) { return (event->type == ButtonPress || event->type == ButtonRelease) ? True : False; } static void __drag_viewport(const exec_context_t *exc, int scroll_speed) { XEvent e; int x; int y; unsigned int button_mask = 0; Bool is_finished = False; if (!GrabEm(CRS_MOVE, GRAB_NORMAL)) { XBell(dpy, 0); return; } if (FQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, &x, &y, &JunkX, &JunkY, &button_mask) == False) { /* pointer is on a different screen */ /* Is this the best thing to do? */ UngrabEm(GRAB_NORMAL); return; } MyXGrabKeyboard(dpy); button_mask &= DEFAULT_ALL_BUTTONS_MASK; memset(&e, 0, sizeof(e)); while (!is_finished) { int old_x; int old_y; old_x = x; old_y = y; FMaskEvent( dpy, ButtonPressMask | ButtonReleaseMask | KeyPressMask | PointerMotionMask | ButtonMotionMask | ExposureMask | EnterWindowMask | LeaveWindowMask, &e); /* discard extra events before a logical release */ if (e.type == MotionNotify || e.type == EnterNotify || e.type == LeaveNotify) { while (FPending(dpy) > 0 && FCheckMaskEvent( dpy, ButtonMotionMask | PointerMotionMask | ButtonPressMask | ButtonRelease | KeyPressMask | EnterWindowMask | LeaveWindowMask, &e)) { if (e.type == ButtonPress || e.type == ButtonRelease || e.type == KeyPress) { break; } } } if (e.type == EnterNotify || e.type == LeaveNotify) { XEvent e2; int px; int py; /* Query the pointer to catch the latest information. * This *is* necessary. */ if (FQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, &px, &py, &JunkX, &JunkY, &JunkMask) == True) { fev_make_null_event(&e2, dpy); e2.type = MotionNotify; e2.xmotion.time = fev_get_evtime(); e2.xmotion.x_root = px; e2.xmotion.y_root = py; e2.xmotion.state = JunkMask; e2.xmotion.same_screen = True; e = e2; fev_fake_event(&e); } else { /* pointer is on a different screen, * ignore event */ } } /* Handle a limited number of key press events to allow * mouseless operation */ if (e.type == KeyPress) { Keyboard_shortcuts( &e, NULL, NULL, NULL, ButtonRelease); } switch (e.type) { case KeyPress: /* simple code to bag out of move - CKH */ if (XLookupKeysym(&(e.xkey), 0) == XK_Escape) { is_finished = True; } break; case ButtonPress: if (e.xbutton.button <= NUMBER_OF_MOUSE_BUTTONS && ((Button1Mask << (e.xbutton.button - 1)) & button_mask)) { /* No new button was pressed, just a delayed * event */ break; } /* fall through */ case ButtonRelease: x = e.xbutton.x_root; y = e.xbutton.y_root; is_finished = True; break; case MotionNotify: if (e.xmotion.same_screen == False) { continue; } x = e.xmotion.x_root; y = e.xmotion.y_root; break; case Expose: dispatch_event(&e); break; default: /* cannot happen */ break; } /* switch */ if (x != old_x || y != old_y) { MoveViewport( Scr.Vx + scroll_speed * (x - old_x), Scr.Vy + scroll_speed * (y - old_y), False); FlushAllMessageQueues(); } } /* while*/ UngrabEm(GRAB_NORMAL); MyXUngrabKeyboard(dpy); WaitForButtonsUp(True); } /* * * Parse arguments for "Desk" and "MoveToDesk" (formerly "WindowsDesk"): * * (nil) : desk number = current desk * n : desk number = current desk + n * 0 n : desk number = n * n x : desk number = current desk + n * 0 n min max : desk number = n, but limit to min/max * n min max : desk number = current desk + n, but wrap around at desk #min * or desk #max * n x min max : desk number = current desk + n, but wrap around at desk #min * or desk #max * * The current desk number is returned if not enough parameters could be * read (or if action is empty). * */ static int GetDeskNumber(char *action, int current_desk) { int n; int m; int is_relative; int desk; int val[4]; int min, max; if (MatchToken(action, "prev")) { return prev_desk; } n = GetIntegerArguments(action, NULL, &(val[0]), 4); if (n <= 0) { return Scr.CurrentDesk; } if (n == 1) { return current_desk + val[0]; } desk = current_desk; m = 0; if (val[0] == 0) { /* absolute desk number */ desk = val[1]; is_relative = 0; } else { /* relative desk number */ desk += val[0]; is_relative = 1; } if (n == 3) { m = 1; } if (n == 4) { m = 2; } if (n > 2) { /* handle limits */ if (val[m] <= val[m+1]) { min = val[m]; max = val[m+1]; } else { /* min > max is nonsense, so swap 'em. */ min = val[m+1]; max = val[m]; } if (is_relative) { /* Relative moves wrap around. */ if (desk < min) { desk += (max - min + 1); } else if (desk > max) { desk -= (max - min + 1); } } else if (desk < min) { /* Relative move outside of range, wrap around. */ if (val[0] < 0) { desk = max; } else { desk = min; } } else if (desk > max) { /* Move outside of range, truncate. */ if (val[0] > 0) { desk = min; } else { desk = max; } } } return desk; } /* * * Unmaps a window on transition to a new desktop * */ static void unmap_window(FvwmWindow *t) { XWindowAttributes winattrs; unsigned long eventMask = 0; Status ret; /* * Prevent the receipt of an UnmapNotify, since that would * cause a transition to the Withdrawn state. */ ret = XGetWindowAttributes(dpy, FW_W(t), &winattrs); if (ret) { eventMask = winattrs.your_event_mask; /* suppress UnmapRequest event */ XSelectInput(dpy, FW_W(t), eventMask & ~StructureNotifyMask); } if (IS_ICONIFIED(t)) { if (FW_W_ICON_PIXMAP(t) != None) { XUnmapWindow(dpy,FW_W_ICON_PIXMAP(t)); } if (FW_W_ICON_TITLE(t) != None) { XUnmapWindow(dpy,FW_W_ICON_TITLE(t)); } } else { XUnmapWindow(dpy,FW_W_FRAME(t)); border_undraw_decorations(t); #ifdef ICCCM2_UNMAP_WINDOW_PATCH /* this is required by the ICCCM2 */ XUnmapWindow(dpy, FW_W(t)); #endif if (!Scr.bo.do_enable_ewmh_iconic_state_workaround) { SetMapStateProp(t, IconicState); } } if (ret) { XSelectInput(dpy, FW_W(t), eventMask); XFlush(dpy); } return; } /* * * Maps a window on transition to a new desktop * */ static void map_window(FvwmWindow *t) { XWindowAttributes winattrs; unsigned long eventMask = 0; Status ret; if (IS_SCHEDULED_FOR_DESTROY(t)) { return; } /* * Prevent the receipt of an UnmapNotify, since that would * cause a transition to the Withdrawn state. */ ret = XGetWindowAttributes(dpy, FW_W(t), &winattrs); if (ret) { eventMask = winattrs.your_event_mask; /* suppress MapRequest event */ XSelectInput(dpy, FW_W(t), eventMask & ~StructureNotifyMask); } if (IS_ICONIFIED(t)) { if (FW_W_ICON_PIXMAP(t) != None) { XMapWindow(dpy,FW_W_ICON_PIXMAP(t)); } if (FW_W_ICON_TITLE(t) != None) { XMapWindow(dpy,FW_W_ICON_TITLE(t)); } } else if (IS_MAPPED(t)) { border_draw_decorations( t, PART_ALL, (t == get_focus_window()) ? True : False, False, CLEAR_ALL, NULL, NULL); XMapWindow(dpy, FW_W_FRAME(t)); XMapWindow(dpy, FW_W_PARENT(t)); XMapSubwindows(dpy, FW_W_FRAME(t)); #ifdef ICCCM2_UNMAP_WINDOW_PATCH /* this is required by the ICCCM2 */ XMapWindow(dpy, FW_W(t)); #endif if (!Scr.bo.do_enable_ewmh_iconic_state_workaround) { SetMapStateProp(t, NormalState); } } if (ret) { XSelectInput(dpy, FW_W(t), eventMask); XFlush(dpy); } return; } /* * * Unmap all windows on a desk - * - Part 1 of a desktop switch * - must eventually be followed by a call to MapDesk * - unmaps from the bottom of the stack up * */ static void UnmapDesk(int desk, Bool grab) { FvwmWindow *t; FvwmWindow *sf = get_focus_window(); if (grab) { MyXGrabServer(dpy); } for (t = get_prev_window_in_stack_ring(&Scr.FvwmRoot); t != &Scr.FvwmRoot; t = get_prev_window_in_stack_ring(t)) { /* Only change mapping for non-sticky windows */ if (!is_window_sticky_across_desks(t) && !IS_ICON_UNMAPPED(t)) { if (t->Desk == desk) { if (sf == t) { t->flags.is_focused_on_other_desk = 1; t->FocusDesk = desk; DeleteFocus(True); } else { t->flags.is_focused_on_other_desk = 0; } unmap_window(t); SET_FULLY_VISIBLE(t, 0); SET_PARTIALLY_VISIBLE(t, 0); } } else { t->flags.is_focused_on_other_desk = 0; } } if (grab) { MyXUngrabServer(dpy); } return; } /* * * Map all windows on a desk - * - Part 2 of a desktop switch * - only use if UnmapDesk has previously been called * - maps from the top of the stack down * */ static void MapDesk(int desk, Bool grab) { FvwmWindow *t; FvwmWindow *FocusWin = NULL; FvwmWindow *StickyWin = NULL; FvwmWindow *sf = get_focus_window(); Scr.flags.is_map_desk_in_progress = 1; if (grab) { MyXGrabServer(dpy); } for (t = get_next_window_in_stack_ring(&Scr.FvwmRoot); t != &Scr.FvwmRoot; t = get_next_window_in_stack_ring(t)) { /* Only change mapping for non-sticky windows */ if (!is_window_sticky_across_desks(t) && !IS_ICON_UNMAPPED(t)) { if (t->Desk == desk) { map_window(t); } } else { /* If window is sticky, just update its desk (it's * still mapped). */ t->Desk = desk; if (sf == t) { StickyWin = t; } } } if (grab) { MyXUngrabServer(dpy); } for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) { /* Autoplace any sticky icons, so that sticky icons from the old desk don't land on top of stationary ones on the new desk. */ if (is_window_sticky_across_desks(t) && IS_ICONIFIED(t) && !IS_ICON_MOVED(t) && !IS_ICON_UNMAPPED(t)) { AutoPlaceIcon(t, NULL, True); } /* Keep track of the last-focused window on the new desk. */ if (t->flags.is_focused_on_other_desk && t->FocusDesk == desk) { t->flags.is_focused_on_other_desk = 0; FocusWin = t; } } /* If a sticky window has focus, don't disturb it. */ if (!StickyWin && FocusWin) { /* Otherwise, handle remembering the last-focused clicky * window. */ if (!FP_DO_UNFOCUS_LEAVE(FW_FOCUS_POLICY(FocusWin))) { ReturnFocusWindow(FocusWin); } else { DeleteFocus(True); } } Scr.flags.is_map_desk_in_progress = 0; return; } /* ---------------------------- interface functions ------------------------ */ /* * * Check to see if the pointer is on the edge of the screen, and scroll/page * if needed * * Returns * 0: no paging * 1: paging occured * -1: no need to call the function again before a new event arrives */ int HandlePaging( XEvent *pev, int HorWarpSize, int VertWarpSize, int *xl, int *yt, int *delta_x, int *delta_y, Bool Grab, Bool fLoop, Bool do_continue_previous, int delay) { static int add_time = 0; int x,y; XEvent e; static Time my_timestamp = 0; static Time my_last_timestamp = 0; static Bool is_timestamp_valid = False; static int last_x = 0; static int last_y = 0; static Bool is_last_position_valid = False; *delta_x = 0; *delta_y = 0; if (!is_timestamp_valid && do_continue_previous) { /* don't call me again until something has happened */ return -1; } if (!is_timestamp_valid && pev->type == MotionNotify) { x = pev->xmotion.x_root; y = pev->xmotion.y_root; if ((Scr.VxMax == 0 || (x >= edge_thickness && x < Scr.MyDisplayWidth - edge_thickness)) && (Scr.VyMax == 0 || (y >= edge_thickness && y < Scr.MyDisplayHeight - edge_thickness))) { return -1; } } if (delay < 0 || (HorWarpSize == 0 && VertWarpSize==0)) { is_timestamp_valid = False; add_time = 0; return 0; } if (Scr.VxMax == 0 && Scr.VyMax == 0) { is_timestamp_valid = False; add_time = 0; return 0; } if (!is_timestamp_valid) { is_timestamp_valid = True; my_timestamp = fev_get_evtime(); is_last_position_valid = False; add_time = 0; last_x = -1; last_y = -1; } else if (my_last_timestamp != fev_get_evtime()) { add_time = 0; } my_last_timestamp = fev_get_evtime(); do { int rc; Window JunkW; int JunkC; unsigned int JunkM; if (FCheckPeekIfEvent(dpy, &e, _pred_button_event, NULL)) { is_timestamp_valid = False; add_time = 0; return 0; } /* get pointer location */ rc = FQueryPointer( dpy, Scr.Root, &JunkW, &JunkW, &x, &y, &JunkC, &JunkC, &JunkM); if (rc == False) { /* pointer is on a different screen */ x = 0; y = 0; } /* check actual pointer location since PanFrames can get buried * under window being moved or resized - mab */ if (x >= edge_thickness && x < Scr.MyDisplayWidth-edge_thickness && y >= edge_thickness && y < Scr.MyDisplayHeight-edge_thickness) { is_timestamp_valid = False; add_time = 0; return 0; } if (!fLoop && is_last_position_valid && (x - last_x > MAX_PAGING_MOVE_DISTANCE || x - last_x < -MAX_PAGING_MOVE_DISTANCE || y - last_y > MAX_PAGING_MOVE_DISTANCE || y - last_y < -MAX_PAGING_MOVE_DISTANCE)) { /* The pointer is moving too fast, prevent paging until * it slows down. Don't prevent paging when fLoop is * set since we can't be sure that HandlePaging will be * called again. */ is_timestamp_valid = True; my_timestamp = fev_get_evtime(); add_time = 0; last_x = x; last_y = y; return 0; } last_x = x; last_y = y; is_last_position_valid = True; usleep(10000); add_time += 10; } while (fLoop && fev_get_evtime() - my_timestamp + add_time < delay); if (fev_get_evtime() - my_timestamp + add_time < delay) { return 0; } /* Get the latest pointer position. This is necessary as XFree 4.1.0.1 * sometimes does not report mouse movement when it should. */ if (FQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, &x, &y, &JunkX, &JunkY, &JunkMask) == False) { /* pointer is on a different screen - ignore */ } /* Move the viewport */ /* and/or move the cursor back to the approximate correct location */ /* that is, the same place on the virtual desktop that it */ /* started at */ if (x < edge_thickness) { *delta_x = -HorWarpSize; } else if (x >= Scr.MyDisplayWidth-edge_thickness) { *delta_x = HorWarpSize; } else { *delta_x = 0; } if (Scr.VxMax == 0) { *delta_x = 0; } if (y < edge_thickness) { *delta_y = -VertWarpSize; } else if (y >= Scr.MyDisplayHeight-edge_thickness) { *delta_y = VertWarpSize; } else { *delta_y = 0; } if (Scr.VyMax == 0) { *delta_y = 0; } /* Ouch! lots of bounds checking */ if (Scr.Vx + *delta_x < 0) { if (!(Scr.flags.do_edge_wrap_x)) { *delta_x = -Scr.Vx; *xl = x - *delta_x; } else { *delta_x += Scr.VxMax + Scr.MyDisplayWidth; *xl = x + *delta_x % Scr.MyDisplayWidth + HorWarpSize; } } else if (Scr.Vx + *delta_x > Scr.VxMax) { if (!(Scr.flags.do_edge_wrap_x)) { *delta_x = Scr.VxMax - Scr.Vx; *xl = x - *delta_x; } else { *delta_x -= Scr.VxMax +Scr.MyDisplayWidth; *xl = x + *delta_x % Scr.MyDisplayWidth - HorWarpSize; } } else { *xl = x - *delta_x; } if (Scr.Vy + *delta_y < 0) { if (!(Scr.flags.do_edge_wrap_y)) { *delta_y = -Scr.Vy; *yt = y - *delta_y; } else { *delta_y += Scr.VyMax + Scr.MyDisplayHeight; *yt = y + *delta_y % Scr.MyDisplayHeight + VertWarpSize; } } else if (Scr.Vy + *delta_y > Scr.VyMax) { if (!(Scr.flags.do_edge_wrap_y)) { *delta_y = Scr.VyMax - Scr.Vy; *yt = y - *delta_y; } else { *delta_y -= Scr.VyMax + Scr.MyDisplayHeight; *yt = y + *delta_y % Scr.MyDisplayHeight - VertWarpSize; } } else { *yt = y - *delta_y; } /* Check for paging -- and don't warp the pointer. */ is_timestamp_valid = False; add_time = 0; if (*delta_x == 0 && *delta_y == 0) { return 0; } /* make sure the pointer isn't warped into the panframes */ if (*xl < edge_thickness) { *xl = edge_thickness; } if (*yt < edge_thickness) { *yt = edge_thickness; } if (*xl >= Scr.MyDisplayWidth - edge_thickness) { *xl = Scr.MyDisplayWidth - edge_thickness -1; } if (*yt >= Scr.MyDisplayHeight - edge_thickness) { *yt = Scr.MyDisplayHeight - edge_thickness -1; } if (Grab) { MyXGrabServer(dpy); } /* Turn off the rubberband if its on */ switch_move_resize_grid(False); FWarpPointer(dpy,None,Scr.Root,0,0,0,0,*xl,*yt); MoveViewport(Scr.Vx + *delta_x,Scr.Vy + *delta_y,False); if (FQueryPointer( dpy, Scr.Root, &JunkRoot, &JunkChild, xl, yt, &JunkX, &JunkY, &JunkMask) == False) { /* pointer is on a different screen */ *xl = 0; *yt = 0; } if (Grab) { MyXUngrabServer(dpy); } return 1; } /* the root window is surrounded by four window slices, which are InputOnly. * So you can see 'through' them, but they eat the input. An EnterEvent in * one of these windows causes a Paging. The windows have the according cursor * pointing in the pan direction or are hidden if there is no more panning * in that direction. This is mostly intended to get a panning even atop * of Motif applictions, which does not work yet. It seems Motif windows * eat all mouse events. * * Hermann Dunkel, HEDU, dunkel@cul-ipn.uni-kiel.de 1/94 */ /* * checkPanFrames hides PanFrames if they are on the very border of the * VIRTUAL screen and EdgeWrap for that direction is off. * (A special cursor for the EdgeWrap border could be nice) HEDU */ void checkPanFrames(void) { Bool do_unmap_l = False; Bool do_unmap_r = False; Bool do_unmap_t = False; Bool do_unmap_b = False; if (!Scr.flags.are_windows_captured) return; /* thickness of 0 means remove the pan frames */ if (edge_thickness == 0) { do_unmap_l = True; do_unmap_r = True; do_unmap_t = True; do_unmap_b = True; } /* Remove Pan frames if paging by edge-scroll is permanently or * temporarily disabled */ if (Scr.EdgeScrollX == 0 || Scr.VxMax == 0) { do_unmap_l = True; do_unmap_r = True; } if (Scr.EdgeScrollY == 0 || Scr.VyMax == 0) { do_unmap_t = True; do_unmap_b = True; } if (Scr.Vx == 0 && !Scr.flags.do_edge_wrap_x) { do_unmap_l = True; } if (Scr.Vx == Scr.VxMax && !Scr.flags.do_edge_wrap_x) { do_unmap_r = True; } if (Scr.Vy == 0 && !Scr.flags.do_edge_wrap_y) { do_unmap_t = True; } if (Scr.Vy == Scr.VyMax && !Scr.flags.do_edge_wrap_y) { do_unmap_b = True; } /* correct the unmap variables if pan frame commands are set */ if (edge_thickness != 0) { if (Scr.PanFrameLeft.command != NULL || Scr.PanFrameLeft.command_leave != NULL) { do_unmap_l = False; } if (Scr.PanFrameRight.command != NULL || Scr.PanFrameRight.command_leave != NULL) { do_unmap_r = False; } if (Scr.PanFrameBottom.command != NULL || Scr.PanFrameBottom.command_leave != NULL) { do_unmap_b = False; } if (Scr.PanFrameTop.command != NULL || Scr.PanFrameTop.command_leave != NULL) { do_unmap_t = False; } } /* * hide or show the windows */ /* left */ if (do_unmap_l) { if (Scr.PanFrameLeft.isMapped) { XUnmapWindow(dpy, Scr.PanFrameLeft.win); Scr.PanFrameLeft.isMapped = False; } } else { if (edge_thickness != last_edge_thickness) { XResizeWindow( dpy, Scr.PanFrameLeft.win, edge_thickness, Scr.MyDisplayHeight); } if (!Scr.PanFrameLeft.isMapped) { XMapRaised(dpy, Scr.PanFrameLeft.win); Scr.PanFrameLeft.isMapped = True; } } /* right */ if (do_unmap_r) { if (Scr.PanFrameRight.isMapped) { XUnmapWindow(dpy, Scr.PanFrameRight.win); Scr.PanFrameRight.isMapped = False; } } else { if (edge_thickness != last_edge_thickness) { XMoveResizeWindow( dpy, Scr.PanFrameRight.win, Scr.MyDisplayWidth - edge_thickness, 0, edge_thickness, Scr.MyDisplayHeight); } if (!Scr.PanFrameRight.isMapped) { XMapRaised(dpy, Scr.PanFrameRight.win); Scr.PanFrameRight.isMapped = True; } } /* top */ if (do_unmap_t) { if (Scr.PanFrameTop.isMapped) { XUnmapWindow(dpy, Scr.PanFrameTop.win); Scr.PanFrameTop.isMapped = False; } } else { if (edge_thickness != last_edge_thickness) { XResizeWindow( dpy, Scr.PanFrameTop.win, Scr.MyDisplayWidth, edge_thickness); } if (!Scr.PanFrameTop.isMapped) { XMapRaised(dpy, Scr.PanFrameTop.win); Scr.PanFrameTop.isMapped = True; } } /* bottom */ if (do_unmap_b) { if (Scr.PanFrameBottom.isMapped) { XUnmapWindow(dpy, Scr.PanFrameBottom.win); Scr.PanFrameBottom.isMapped = False; } } else { if (edge_thickness != last_edge_thickness) { XMoveResizeWindow( dpy, Scr.PanFrameBottom.win, 0, Scr.MyDisplayHeight - edge_thickness, Scr.MyDisplayWidth, edge_thickness); } if (!Scr.PanFrameBottom.isMapped) { XMapRaised(dpy, Scr.PanFrameBottom.win); Scr.PanFrameBottom.isMapped = True; } } last_edge_thickness = edge_thickness; return; } /* * * Gotta make sure these things are on top of everything else, or they * don't work! * * For some reason, this seems to be unneeded. * */ void raisePanFrames(void) { Window windows[4]; int n; /* Note: make sure the stacking order of the pan frames is not changed * every time they are raised by using XRestackWindows. */ n = 0; if (Scr.PanFrameTop.isMapped) { windows[n++] = Scr.PanFrameTop.win; } if (Scr.PanFrameLeft.isMapped) { windows[n++] = Scr.PanFrameLeft.win; } if (Scr.PanFrameRight.isMapped) { windows[n++] = Scr.PanFrameRight.win; } if (Scr.PanFrameBottom.isMapped) { windows[n++] = Scr.PanFrameBottom.win; } if (n > 0) { XRaiseWindow(dpy, windows[0]); if (n > 1) { XRestackWindows(dpy, windows, n); } } return; } /* * * Creates the windows for edge-scrolling * */ void initPanFrames(void) { XSetWindowAttributes attributes; unsigned long valuemask; int saved_thickness; /* Not creating the frames disables all subsequent behavior */ /* TKP. This is bad, it will cause an XMap request on a null window * later*/ /* if (edge_thickness == 0) return; */ saved_thickness = edge_thickness; if (edge_thickness == 0) { edge_thickness = 2; } attributes.event_mask = XEVMASK_PANFW; valuemask= (CWEventMask | CWCursor); attributes.cursor = Scr.FvwmCursors[CRS_TOP_EDGE]; /* I know these overlap, it's useful when at (0,0) and the top one is * unmapped */ Scr.PanFrameTop.win = XCreateWindow( dpy, Scr.Root, 0, 0, Scr.MyDisplayWidth, edge_thickness, 0, CopyFromParent, InputOnly, CopyFromParent, valuemask, &attributes); attributes.cursor = Scr.FvwmCursors[CRS_LEFT_EDGE]; Scr.PanFrameLeft.win = XCreateWindow( dpy, Scr.Root, 0, 0, edge_thickness, Scr.MyDisplayHeight, 0, CopyFromParent, InputOnly, CopyFromParent, valuemask, &attributes); attributes.cursor = Scr.FvwmCursors[CRS_RIGHT_EDGE]; Scr.PanFrameRight.win = XCreateWindow( dpy, Scr.Root, Scr.MyDisplayWidth - edge_thickness, 0, edge_thickness, Scr.MyDisplayHeight, 0, CopyFromParent, InputOnly, CopyFromParent, valuemask, &attributes); attributes.cursor = Scr.FvwmCursors[CRS_BOTTOM_EDGE]; Scr.PanFrameBottom.win = XCreateWindow( dpy, Scr.Root, 0, Scr.MyDisplayHeight - edge_thickness, Scr.MyDisplayWidth, edge_thickness, 0, CopyFromParent, InputOnly, CopyFromParent, valuemask, &attributes); Scr.PanFrameTop.isMapped=Scr.PanFrameLeft.isMapped= Scr.PanFrameRight.isMapped= Scr.PanFrameBottom.isMapped=False; edge_thickness = saved_thickness; return; } Bool is_pan_frame(Window w) { if (w == Scr.PanFrameTop.win || w == Scr.PanFrameBottom.win || w == Scr.PanFrameLeft.win || w == Scr.PanFrameRight.win) { return True; } else { return False; } } /* * * Moves the viewport within the virtual desktop * */ void MoveViewport(int newx, int newy, Bool grab) { FvwmWindow *t, *t1; int deltax,deltay; int PageTop, PageLeft; int PageBottom, PageRight; int txl, txr, tyt, tyb; if (grab) { MyXGrabServer(dpy); } if (newx > Scr.VxMax) { newx = Scr.VxMax; } if (newy > Scr.VyMax) { newy = Scr.VyMax; } if (newx < 0) { newx = 0; } if (newy < 0) { newy = 0; } deltay = Scr.Vy - newy; deltax = Scr.Vx - newx; /* Identify the bounding rectangle that will be moved into the viewport. */ PageBottom = Scr.MyDisplayHeight - deltay - 1; PageRight = Scr.MyDisplayWidth - deltax - 1; PageTop = 0 - deltay; PageLeft = 0 - deltax; if (deltax || deltay) { prev_page_x = Scr.Vx; prev_page_y = Scr.Vy; prev_desk_and_page_page_x = Scr.Vx; prev_desk_and_page_page_y = Scr.Vy; prev_desk_and_page_desk = Scr.CurrentDesk; } Scr.Vx = newx; Scr.Vy = newy; if (deltax || deltay) { BroadcastPacket( M_NEW_PAGE, 7, (long)Scr.Vx, (long)Scr.Vy, (long)Scr.CurrentDesk, (long)Scr.MyDisplayWidth, (long)Scr.MyDisplayHeight, (long)((Scr.VxMax / Scr.MyDisplayWidth) + 1), (long)((Scr.VyMax / Scr.MyDisplayHeight) + 1)); /* * RBW - 11/13/1998 - new: chase the chain * bidirectionally, all at once! The idea is to move the * windows that are moving out of the viewport from the bottom * of the stacking order up, to minimize the expose-redraw * overhead. Windows that will be moving into view will be * moved top down, for the same reason. Use the new * stacking-order chain, rather than the old last-focused * chain. * * domivogt (29-Nov-1999): It's faster to first map windows * top to bottom and then unmap windows bottom up. */ t = get_next_window_in_stack_ring(&Scr.FvwmRoot); while (t != &Scr.FvwmRoot) { /* * If the window is moving into the viewport... */ txl = t->g.frame.x; tyt = t->g.frame.y; txr = t->g.frame.x + t->g.frame.width - 1; tyb = t->g.frame.y + t->g.frame.height - 1; if (is_window_sticky_across_pages(t) && !IS_VIEWPORT_MOVED(t)) { /* the absolute position has changed */ t->g.normal.x -= deltax; t->g.normal.y -= deltay; t->g.max.x -= deltax; t->g.max.y -= deltay; /* Block double move. */ SET_VIEWPORT_MOVED(t, 1); } if ((txr >= PageLeft && txl <= PageRight && tyb >= PageTop && tyt <= PageBottom) && !IS_VIEWPORT_MOVED(t) && !IS_WINDOW_BEING_MOVED_OPAQUE(t)) { /* Block double move. */ SET_VIEWPORT_MOVED(t, 1); /* If the window is iconified, and sticky * Icons is set, then the window should * essentially be sticky */ if (!is_window_sticky_across_pages(t)) { if (IS_ICONIFIED(t)) { modify_icon_position( t, deltax, deltay); move_icon_to_position(t); broadcast_icon_geometry( t, False); } frame_setup_window( t, t->g.frame.x + deltax, t->g.frame.y + deltay, t->g.frame.width, t->g.frame.height, False); } } /* Bump to next win... */ t = get_next_window_in_stack_ring(t); } t1 = get_prev_window_in_stack_ring(&Scr.FvwmRoot); while (t1 != &Scr.FvwmRoot) { /* *If the window is not moving into the viewport... */ SET_VIEWPORT_MOVED(t, 1); txl = t1->g.frame.x; tyt = t1->g.frame.y; txr = t1->g.frame.x + t1->g.frame.width - 1; tyb = t1->g.frame.y + t1->g.frame.height - 1; if (! (txr >= PageLeft && txl <= PageRight && tyb >= PageTop && tyt <= PageBottom) && !IS_VIEWPORT_MOVED(t1) && !IS_WINDOW_BEING_MOVED_OPAQUE(t1)) { /* If the window is iconified, and sticky * Icons is set, then the window should * essentially be sticky */ if (!is_window_sticky_across_pages(t1)) { if (IS_ICONIFIED(t1)) { modify_icon_position( t1, deltax, deltay); move_icon_to_position(t1); broadcast_icon_geometry( t1, False); } frame_setup_window( t1, t1->g.frame.x + deltax, t1->g.frame.y + deltay, t1->g.frame.width, t1->g.frame.height, False); } } /* Bump to next win... */ t1 = get_prev_window_in_stack_ring(t1); } for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) { if (IS_VIEWPORT_MOVED(t)) { /* Clear double move blocker. */ SET_VIEWPORT_MOVED(t, 0); } /* If its an icon, and its sticking, autoplace it so * that it doesn't wind up on top a a stationary * icon */ if (is_window_sticky_across_pages(t) && IS_ICONIFIED(t) && !IS_ICON_MOVED(t) && !IS_ICON_UNMAPPED(t)) { AutoPlaceIcon(t, NULL, True); } } } checkPanFrames(); /* regrab buttons in case something got obscured or unobscured */ focus_grab_buttons_all(); #if 0 /* dv (2004-07-01): I don't think that's a good idea. We could eat too * many events. */ /* do this with PanFrames too ??? HEDU */ { XEvent e; while (FCheckTypedEvent(dpy, MotionNotify, &e)) { /* nothing */ } } #endif if (grab) { MyXUngrabServer(dpy); } EWMH_SetDesktopViewPort(); return; } void goto_desk(int desk) { /* RBW - the unmapping operations are now removed to their own * functions so they can also be used by the new GoToDeskAndPage * command. */ if (Scr.CurrentDesk != desk) { prev_desk = Scr.CurrentDesk; prev_desk_and_page_desk = Scr.CurrentDesk; prev_desk_and_page_page_x = Scr.Vx; prev_desk_and_page_page_y = Scr.Vy; UnmapDesk(Scr.CurrentDesk, True); Scr.CurrentDesk = desk; MapDesk(desk, True); focus_grab_buttons_all(); BroadcastPacket(M_NEW_DESK, 1, (long)Scr.CurrentDesk); /* FIXME: domivogt (22-Apr-2000): Fake a 'restack' for sticky * window upon desk change. This is a workaround for a * problem in FvwmPager: The pager has a separate 'root' * window for each desk. If the active desk changes, the * pager destroys sticky mini windows and creates new ones in * the other desktop 'root'. But the pager can't know where to * stack them. So we have to tell it explicitly where they * go :-( This should be fixed in the pager, but right now the * pager doesn't maintain the stacking order. */ BroadcastRestackAllWindows(); EWMH_SetCurrentDesktop(); } return; } /* * * Move a window to a new desktop * */ void do_move_window_to_desk(FvwmWindow *fw, int desk) { if (fw == NULL) { return; } /* * Set the window's desktop, and map or unmap it as needed. */ /* Only change mapping for non-sticky windows */ if (!is_window_sticky_across_desks(fw) /*&& !IS_ICON_UNMAPPED(fw)*/) { if (fw->Desk == Scr.CurrentDesk) { fw->Desk = desk; if (fw == get_focus_window()) { DeleteFocus(True); } unmap_window(fw); SET_FULLY_VISIBLE(fw, 0); SET_PARTIALLY_VISIBLE(fw, 0); } else if (desk == Scr.CurrentDesk) { fw->Desk = desk; /* If its an icon, auto-place it */ if (IS_ICONIFIED(fw)) { AutoPlaceIcon(fw, NULL, True); } map_window(fw); } else { fw->Desk = desk; } BroadcastConfig(M_CONFIGURE_WINDOW,fw); } focus_grab_buttons_on_layer(fw->layer); EWMH_SetWMDesktop(fw); return; } Bool get_page_arguments(char *action, int *page_x, int *page_y) { int val[2]; int suffix[2]; char *token; char *taction; int wrapx; int wrapy; int limitdeskx; int limitdesky; wrapx = 0; wrapy = 0; limitdeskx = 1; limitdesky = 1; for (; ; action = taction) { int do_reverse; token = PeekToken(action, &taction); if (token == NULL) { *page_x = Scr.Vx; *page_y = Scr.Vy; return True; } if (StrEquals(token, "prev")) { /* last page selected */ *page_x = prev_page_x; *page_y = prev_page_y; return True; } do_reverse = 0; for ( ; *token == '!'; token++) { do_reverse = !do_reverse; } if (StrEquals(token, "wrapx")) { wrapx = (1 ^ do_reverse); } else if (StrEquals(token, "wrapy")) { wrapy = (1 ^ do_reverse); } else if (StrEquals(token, "nodesklimitx")) { limitdeskx = (0 ^ do_reverse); } else if (StrEquals(token, "nodesklimity")) { limitdesky = (0 ^ do_reverse); } else { /* no more options */ break; } } if (GetSuffixedIntegerArguments(action, NULL, val, 2, "pw", suffix) != 2) { return 0; } if (suffix[0] == 1) { *page_x = val[0] * Scr.MyDisplayWidth + Scr.Vx; } else if (suffix[0] == 2) { *page_x += val[0] * Scr.MyDisplayWidth; } else if (val[0] >= 0) { *page_x = val[0] * Scr.MyDisplayWidth; } else { *page_x = (val[0] + 1) * Scr.MyDisplayWidth + Scr.VxMax; } if (suffix[1] == 1) { *page_y = val[1] * Scr.MyDisplayHeight + Scr.Vy; } else if (suffix[1] == 2) { *page_y += val[1] * Scr.MyDisplayHeight; } else if (val[1] >= 0) { *page_y = val[1] * Scr.MyDisplayHeight; } else { *page_y = (val[1] + 1) * Scr.MyDisplayHeight + Scr.VyMax; } /* limit to desktop size */ if (limitdeskx && !wrapx) { if (*page_x < 0) { *page_x = 0; } else if (*page_x > Scr.VxMax) { *page_x = Scr.VxMax; } } else if (limitdeskx && wrapx) { while (*page_x < 0) { *page_x += Scr.VxMax + Scr.MyDisplayWidth; } while (*page_x > Scr.VxMax) { *page_x -= Scr.VxMax + Scr.MyDisplayWidth; } } if (limitdesky && !wrapy) { if (*page_y < 0) { *page_y = 0; } else if (*page_y > Scr.VyMax) { *page_y = Scr.VyMax; } } else if (limitdesky && wrapy) { while (*page_y < 0) { *page_y += Scr.VyMax + Scr.MyDisplayHeight; } while (*page_y > Scr.VyMax) { *page_y -= Scr.VyMax + Scr.MyDisplayHeight; } } return True; } char *GetDesktopName(int desk) { DesktopsInfo *d; d = Scr.Desktops->next; while (d != NULL && d->desk != desk) { d = d->next; } if (d != NULL) { return d->name; } return NULL; } /* ---------------------------- builtin commands --------------------------- */ /* EdgeCommand - binds a function to a pan frame enter event */ void CMD_EdgeCommand(F_CMD_ARGS) { direction_t direction; char * command; /* get the direction */ direction = gravity_parse_dir_argument(action, &action, DIR_NONE); if (direction >= 0 && direction <= DIR_MAJOR_MASK) { /* check if the command does contain at least one token */ command = safestrdup(action); if (PeekToken(action , &action) == NULL) { /* the command does not contain a token so the command of this edge is removed */ free(command); command = NULL; } /* assign command to the edge(s) */ if (direction == DIR_N) { if (Scr.PanFrameTop.command != NULL) { free(Scr.PanFrameTop.command); } Scr.PanFrameTop.command = command; } else if (direction == DIR_S) { if (Scr.PanFrameBottom.command != NULL) { free(Scr.PanFrameBottom.command); } Scr.PanFrameBottom.command = command; } else if (direction == DIR_W) { if (Scr.PanFrameLeft.command != NULL) { free(Scr.PanFrameLeft.command); } Scr.PanFrameLeft.command = command; } else if (direction == DIR_E) { if (Scr.PanFrameRight.command != NULL) { free(Scr.PanFrameRight.command); } Scr.PanFrameRight.command = command; } else { /* this should never happen */ fvwm_msg(ERR, "EdgeCommand", "Internal error in CMD_EdgeCommand"); } } else { /* check if the argument does contain at least one token */ if (PeekToken(action , &action) == NULL) { /* Just plain EdgeCommand, so all edge commands are * removed */ if (Scr.PanFrameTop.command != NULL) { free(Scr.PanFrameTop.command); Scr.PanFrameTop.command = NULL; } if (Scr.PanFrameBottom.command != NULL) { free(Scr.PanFrameBottom.command); Scr.PanFrameBottom.command = NULL; } if (Scr.PanFrameLeft.command != NULL) { free(Scr.PanFrameLeft.command); Scr.PanFrameLeft.command = NULL; } if (Scr.PanFrameRight.command != NULL) { free(Scr.PanFrameRight.command); Scr.PanFrameRight.command = NULL; } } else { /* not a proper direction */ fvwm_msg(ERR, "EdgeCommand", "EdgeCommand [direction [function]]"); } } /* maybe something has changed so we adapt the pan frames */ checkPanFrames(); return; } /* EdgeLeaveCommand - binds a function to a pan frame Leave event */ void CMD_EdgeLeaveCommand(F_CMD_ARGS) { direction_t direction; char * command; /* get the direction */ direction = gravity_parse_dir_argument(action, &action, DIR_NONE); if (direction >= 0 && direction <= DIR_MAJOR_MASK) { /* check if the command does contain at least one token */ command = safestrdup(action); if (PeekToken(action , &action) == NULL) { /* the command does not contain a token so the command of this edge is removed */ free(command); command = NULL; } /* assign command to the edge(s) */ if (direction == DIR_N) { if (Scr.PanFrameTop.command_leave != NULL) { free(Scr.PanFrameTop.command_leave); } Scr.PanFrameTop.command_leave = command; } else if (direction == DIR_S) { if (Scr.PanFrameBottom.command_leave != NULL) { free(Scr.PanFrameBottom.command_leave); } Scr.PanFrameBottom.command_leave = command; } else if (direction == DIR_W) { if (Scr.PanFrameLeft.command_leave != NULL) { free(Scr.PanFrameLeft.command_leave); } Scr.PanFrameLeft.command_leave = command; } else if (direction == DIR_E) { if (Scr.PanFrameRight.command_leave != NULL) { free(Scr.PanFrameRight.command_leave); } Scr.PanFrameRight.command_leave = command; } else { /* this should never happen */ fvwm_msg(ERR, "EdgeLeaveCommand", "Internal error in CMD_EdgeLeaveCommand"); } } else { /* check if the argument does contain at least one token */ if (PeekToken(action , &action) == NULL) { /* Just plain EdgeLeaveCommand, so all edge commands are * removed */ if (Scr.PanFrameTop.command_leave != NULL) { free(Scr.PanFrameTop.command_leave); Scr.PanFrameTop.command_leave = NULL; } if (Scr.PanFrameBottom.command_leave != NULL) { free(Scr.PanFrameBottom.command_leave); Scr.PanFrameBottom.command_leave = NULL; } if (Scr.PanFrameLeft.command_leave != NULL) { free(Scr.PanFrameLeft.command_leave); Scr.PanFrameLeft.command_leave = NULL; } if (Scr.PanFrameRight.command_leave != NULL) { free(Scr.PanFrameRight.command_leave); Scr.PanFrameRight.command_leave = NULL; } } else { /* not a proper direction */ fvwm_msg(ERR, "EdgeLeaveCommand", "EdgeLeaveCommand [direction [function]]"); } } /* maybe something has changed so we adapt the pan frames */ checkPanFrames(); return; } void CMD_EdgeThickness(F_CMD_ARGS) { int val, n; n = GetIntegerArguments(action, NULL, &val, 1); if (n != 1) { fvwm_msg(ERR,"setEdgeThickness", "EdgeThickness requires 1 numeric argument," " found %d args",n); return; } /* check range */ if (val < 0 || val > 2) { fvwm_msg(ERR,"setEdgeThickness", "EdgeThickness arg must be between 0 and 2," " found %d",val); return; } edge_thickness = val; checkPanFrames(); return; } void CMD_EdgeScroll(F_CMD_ARGS) { int val1, val2, val1_unit, val2_unit, n; char *token; n = GetTwoArguments(action, &val1, &val2, &val1_unit, &val2_unit); if (n != 2) { fvwm_msg( ERR, "SetEdgeScroll", "EdgeScroll requires two arguments"); return; } /* * if edgescroll >1000 and <100000 * wrap at edges of desktop (a "spherical" desktop) */ if (val1 >= 1000 && val1_unit != 100) { val1 /= 1000; Scr.flags.do_edge_wrap_x = 1; } else { Scr.flags.do_edge_wrap_x = 0; } if (val2 >= 1000 && val2_unit != 100) { val2 /= 1000; Scr.flags.do_edge_wrap_y = 1; } else { Scr.flags.do_edge_wrap_y = 0; } action=SkipNTokens(action,2); token = PeekToken(action, NULL); if (token) { if (StrEquals(token, "wrap")) { Scr.flags.do_edge_wrap_x = 1; Scr.flags.do_edge_wrap_y = 1; } else if (StrEquals(token, "wrapx")) { Scr.flags.do_edge_wrap_x = 1; } else if (StrEquals(token, "wrapy")) { Scr.flags.do_edge_wrap_y = 1; } } Scr.EdgeScrollX = val1 * val1_unit / 100; Scr.EdgeScrollY = val2 * val2_unit / 100; checkPanFrames(); return; } void CMD_EdgeResistance(F_CMD_ARGS) { int val[3]; int n; val[0] = 0; n = GetIntegerArguments(action, NULL, val, 3); if (n > 1 && val[0] >= 10000) { /* map val[0] >= 10000 in old syntax to -1 in new syntax */ val[0] = -1; } if (n == 1) { Scr.ScrollDelay = val[0]; } else if (n >= 2 && n <= 3) { char cmd[99]; char stylecmd[99]; char stylecmd2[99]; Scr.ScrollDelay = val[0]; sprintf(cmd, "EdgeResistance %d", val[0]); sprintf(stylecmd, "Style * EdgeMoveDelay %d", val[0]); if (n == 2) { sprintf( stylecmd2, "Style * EdgeMoveResistance %d", val[1]); } else { sprintf( stylecmd2, "Style * EdgeMoveResistance %d %d", val[1], val[2]); } fvwm_msg( OLD, "CMD_EdgeResistance", "The command EdgeResistance with three arguments is" " obsolete. Please use the following commands" " instead:\n%s\n%s\n%s\n", cmd, stylecmd, stylecmd2); execute_function( cond_rc, exc, cmd, FUNC_DONT_REPEAT | FUNC_DONT_EXPAND_COMMAND); execute_function( cond_rc, exc, stylecmd, FUNC_DONT_REPEAT | FUNC_DONT_EXPAND_COMMAND); execute_function( cond_rc, exc, stylecmd2, FUNC_DONT_REPEAT | FUNC_DONT_EXPAND_COMMAND); } else { fvwm_msg( ERR, "CMD_EdgeResistance", "EdgeResistance requires two or three arguments"); return; } return; } void CMD_Xinerama(F_CMD_ARGS) { int toggle; toggle = ParseToggleArgument(action, NULL, -1, 0); if (toggle == -1) { toggle = !FScreenIsEnabled(); } if (!toggle != !FScreenIsEnabled()) { Scr.flags.do_need_window_update = True; Scr.flags.has_xinerama_state_changed = True; FScreenOnOff(toggle); broadcast_xinerama_state(); } return; } void CMD_XineramaPrimaryScreen(F_CMD_ARGS) { int val; val = FScreenGetScreenArgument(action, 0); FScreenSetPrimaryScreen(val); if (FScreenIsEnabled()) { Scr.flags.do_need_window_update = True; Scr.flags.has_xinerama_state_changed = True; } broadcast_xinerama_state(); return; } void CMD_XineramaSls(F_CMD_ARGS) { int toggle; toggle = ParseToggleArgument(action, NULL, -1, 0); if (toggle == -1) { toggle = !FScreenIsSLSEnabled(); } if (!toggle != !FScreenIsSLSEnabled()) { if (FScreenIsEnabled()) { Scr.flags.do_need_window_update = True; Scr.flags.has_xinerama_state_changed = True; } FScreenSLSOnOff(toggle); broadcast_xinerama_state(); } return; } void CMD_XineramaSlsSize(F_CMD_ARGS) { int val[2]; if (GetIntegerArguments(action, NULL, val, 2) != 2 && GetRectangleArguments(action, &val[0], &val[1]) != 2) { val[0] = 1; val[1] = 1; } if (FScreenConfigureSLSSize(val[0], val[1])) { broadcast_xinerama_state(); } return; } void CMD_XineramaSlsScreens(F_CMD_ARGS) { int nscreens; char *args; if (GetIntegerArguments(action, &args, &nscreens, 1) != 1) { nscreens = 0; args = NULL; } else if (args == NULL) { nscreens = 0; } if (FScreenConfigureSLSScreens(nscreens, args)) { broadcast_xinerama_state(); } return; } void CMD_DesktopSize(F_CMD_ARGS) { int val[2]; if (GetIntegerArguments(action, NULL, val, 2) != 2 && GetRectangleArguments(action, &val[0], &val[1]) != 2) { fvwm_msg(ERR, "CMD_DesktopSize", "DesktopSize requires two arguments"); return; } Scr.VxMax = (val[0] <= 0) ? 0: val[0]*Scr.MyDisplayWidth-Scr.MyDisplayWidth; Scr.VyMax = (val[1] <= 0) ? 0: val[1]*Scr.MyDisplayHeight-Scr.MyDisplayHeight; BroadcastPacket( M_NEW_PAGE, 7, (long)Scr.Vx, (long)Scr.Vy, (long)Scr.CurrentDesk, (long)Scr.MyDisplayWidth, (long)Scr.MyDisplayHeight, (long)((Scr.VxMax / Scr.MyDisplayWidth) + 1), (long)((Scr.VyMax / Scr.MyDisplayHeight) + 1)); checkPanFrames(); EWMH_SetDesktopGeometry(); return; } /* * * Move to a new desktop * */ void CMD_GotoDesk(F_CMD_ARGS) { goto_desk(GetDeskNumber(action, Scr.CurrentDesk)); return; } void CMD_Desk(F_CMD_ARGS) { CMD_GotoDesk(F_PASS_ARGS); return; } /* * * Move to a new desktop and page at the same time. * This function is designed for use by the Pager, and replaces the old * GoToDesk 0 10000 hack. * - unmap all windows on the current desk so they don't flash when the * viewport is moved, then switch the viewport, then the desk. * */ void CMD_GotoDeskAndPage(F_CMD_ARGS) { int val[3]; Bool is_new_desk; if (MatchToken(action, "prev")) { val[0] = prev_desk_and_page_desk; val[1] = prev_desk_and_page_page_x; val[2] = prev_desk_and_page_page_y; } else if (GetIntegerArguments(action, NULL, val, 3) == 3) { val[1] *= Scr.MyDisplayWidth; val[2] *= Scr.MyDisplayHeight; } else { return; } is_new_desk = (Scr.CurrentDesk != val[0]); if (is_new_desk) { UnmapDesk(Scr.CurrentDesk, True); } prev_desk_and_page_page_x = Scr.Vx; prev_desk_and_page_page_y = Scr.Vy; MoveViewport(val[1], val[2], True); if (is_new_desk) { prev_desk = Scr.CurrentDesk; prev_desk_and_page_desk = Scr.CurrentDesk; Scr.CurrentDesk = val[0]; MapDesk(val[0], True); focus_grab_buttons_all(); BroadcastPacket(M_NEW_DESK, 1, (long)Scr.CurrentDesk); /* FIXME: domivogt (22-Apr-2000): Fake a 'restack' for sticky * window upon desk change. This is a workaround for a * problem in FvwmPager: The pager has a separate 'root' * window for each desk. If the active desk changes, the * pager destroys sticky mini windows and creates new ones in * the other desktop 'root'. But the pager can't know where to * stack them. So we have to tell it ecplicitly where they * go :-( This should be fixed in the pager, but right now the * pager doesn't the stacking order. */ BroadcastRestackAllWindows(); } else { BroadcastPacket(M_NEW_DESK, 1, (long)Scr.CurrentDesk); } EWMH_SetCurrentDesktop(); return; } void CMD_GotoPage(F_CMD_ARGS) { int x; int y; x = Scr.Vx; y = Scr.Vy; if (!get_page_arguments(action, &x, &y)) { fvwm_msg( ERR, "goto_page_func", "GotoPage: invalid arguments: %s", action); return; } if (x < 0) { x = 0; } if (x > Scr.VxMax) { x = Scr.VxMax; } if (y < 0) { y = 0; } if (y > Scr.VyMax) { y = Scr.VyMax; } MoveViewport(x,y,True); return; } /* function with parsing of command line */ void CMD_MoveToDesk(F_CMD_ARGS) { int desk; FvwmWindow * const fw = exc->w.fw; desk = GetDeskNumber(action, fw->Desk); if (desk == fw->Desk) { return; } do_move_window_to_desk(fw, desk); return; } void CMD_Scroll(F_CMD_ARGS) { int x,y; int val1, val2, val1_unit, val2_unit; if (GetTwoArguments(action, &val1, &val2, &val1_unit, &val2_unit) != 2) { /* less then two integer parameters implies interactive * scroll check if we are scrolling in reverse direction */ char *option; int scroll_speed = 1; option = PeekToken(action, NULL); if (option != NULL) { if (StrEquals(option, "Reverse")) { scroll_speed *= -1; } } __drag_viewport(exc, scroll_speed); return; } if ((val1 > -100000)&&(val1 < 100000)) { x = Scr.Vx + val1*val1_unit/100; } else { x = Scr.Vx + (val1/1000)*val1_unit/100; } if ((val2 > -100000)&&(val2 < 100000)) { y=Scr.Vy + val2*val2_unit/100; } else { y = Scr.Vy + (val2/1000)*val2_unit/100; } if (((val1 <= -100000)||(val1 >= 100000))&&(x>Scr.VxMax)) { int xpixels; xpixels = (Scr.VxMax / Scr.MyDisplayWidth + 1) * Scr.MyDisplayWidth; x %= xpixels; y += Scr.MyDisplayHeight * (1+((x-Scr.VxMax-1)/xpixels)); if (y > Scr.VyMax) { y %= (Scr.VyMax / Scr.MyDisplayHeight + 1) * Scr.MyDisplayHeight; } } if (((val1 <= -100000)||(val1 >= 100000))&&(x<0)) { x = Scr.VxMax; y -= Scr.MyDisplayHeight; if (y < 0) { y=Scr.VyMax; } } if (((val2 <= -100000)||(val2>= 100000))&&(y>Scr.VyMax)) { int ypixels = (Scr.VyMax / Scr.MyDisplayHeight + 1) * Scr.MyDisplayHeight; y %= ypixels; x += Scr.MyDisplayWidth * (1+((y-Scr.VyMax-1)/ypixels)); if (x > Scr.VxMax) { x %= (Scr.VxMax / Scr.MyDisplayWidth + 1) * Scr.MyDisplayWidth; } } if (((val2 <= -100000)||(val2>= 100000))&&(y<0)) { y = Scr.VyMax; x -= Scr.MyDisplayWidth; if (x < 0) { x=Scr.VxMax; } } MoveViewport(x,y,True); return; } /* * * Defines the name of a desktop * */ void CMD_DesktopName(F_CMD_ARGS) { int desk; DesktopsInfo *t, *d, *new, **prev; if (GetIntegerArguments(action, &action, &desk, 1) != 1) { fvwm_msg( ERR,"CMD_DesktopName", "First argument to DesktopName must be an integer: %s", action); return; } d = Scr.Desktops->next; while (d != NULL && d->desk != desk) { d = d->next; } if (d != NULL) { if (d->name != NULL) { free(d->name); d->name = NULL; } if (action != NULL && *action && *action != '\n') { CopyString(&d->name, action); } } else { /* new deskops entries: add it in order */ d = Scr.Desktops->next; t = Scr.Desktops; prev = &(Scr.Desktops->next); while (d != NULL && d->desk < desk) { t = t->next; prev = &(d->next); d = d->next; } if (d == NULL) { /* add it at the end */ *prev = (DesktopsInfo *)safemalloc( sizeof(DesktopsInfo)); memset(*prev, 0, sizeof(DesktopsInfo)); (*prev)->desk = desk; if (action != NULL && *action && *action != '\n') { CopyString(&((*prev)->name), action); } } else { /* instert it */ new = (DesktopsInfo *)safemalloc(sizeof(DesktopsInfo)); memset(new, 0, sizeof(DesktopsInfo)); new->desk = desk; if (action != NULL && *action && *action != '\n') { CopyString(&(new->name), action); } t->next = new; new->next = d; } /* should check/set the working areas */ } if (!fFvwmInStartup) { char *msg; const char *default_desk_name = _("Desk"); /* should send the info to the FvwmPager and set the EWMH * desktop names */ if (action != NULL && *action && *action != '\n') { msg = (char *)safemalloc(strlen(action) + 44); sprintf(msg, "DesktopName %d %s", desk, action); } else { msg = (char *)safemalloc(strlen(default_desk_name)+44); sprintf( msg, "DesktopName %d %s %d", desk, default_desk_name, desk); } BroadcastConfigInfoString(msg); free(msg); } EWMH_SetDesktopNames(); return; } fvwm-2.7.0/fvwm/Makefile.am0000644000175000017500000000506314147024700012436 00000000000000## Process this file with automake to create Makefile.in configdir = @FVWM_DATADIR@ bin_PROGRAMS = fvwm EXTRA_DIST = $(config_DATA) config_DATA = ConfigFvwmDefaults ## please keep .c file in largest first order to speed up parallel makes fvwm_SOURCES = \ add_window.h bindings.h borders.h builtins.h colormaps.h colorset.h \ commands.h conditional.h condrc.h cursor.h decorations.h events.h \ eventhandler.h eventmask.h ewmh.h ewmh_intern.h expand.h externs.h \ focus.h functable.h functions.h fvwm.h geometry.h focus_policy.h \ icccm2.h icons.h menubindings.h menudim.h menugeometry.h \ menuitem.h menuroot.h menuparameters.h menus.h menustyle.h misc.h \ modconf.h module_interface.h module_list.h move_resize.h \ placement.h read.h repeat.h execcontext.h schedule.h screen.h \ session.h stack.h style.h update.h virtual.h window_flags.h frame.h \ infostore.h \ \ menus.c style.c borders.c events.c move_resize.c builtins.c \ add_window.c icons.c fvwm.c frame.c placement.c virtual.c \ menustyle.c conditional.c ewmh.c stack.c session.c colorset.c \ functions.c ewmh_events.c geometry.c module_list.c focus.c \ windowlist.c functable.c menuitem.c expand.c module_interface.c \ menubindings.c decorations.c ewmh_icons.c update.c bindings.c misc.c \ cursor.c colormaps.c modconf.c ewmh_conf.c read.c schedule.c \ menucmd.c ewmh_names.c icccm2.c windowshade.c focus_policy.c repeat.c \ execcontext.c menugeometry.c menudim.c condrc.c infostore.c fvwm_DEPENDENCIES = $(top_builddir)/libs/libfvwm.a LDADD = \ -L$(top_builddir)/libs -lfvwm $(Xft_LIBS) $(X_LIBS) $(xpm_LIBS) \ $(stroke_LIBS) $(X_PRE_LIBS) $(Xinerama_LIBS) -lXext -lX11 \ $(X_EXTRA_LIBS) -lm $(iconv_LIBS) $(Xrender_LIBS) $(Xcursor_LIBS) \ $(Bidi_LIBS) $(png_LIBS) $(rsvg_LIBS) $(intl_LIBS) AM_CPPFLAGS = \ -I$(top_srcdir) $(stroke_CFLAGS) $(Xft_CFLAGS) \ $(xpm_CFLAGS) $(X_CFLAGS) $(iconv_CFLAGS) $(Xrender_CFLAGS) \ $(Bidi_CFLAGS) $(png_CFLAGS) $(rsvg_CFLAGS) $(intl_CFLAGS) AM_CFLAGS = \ -DFVWM_MODULEDIR=\"$(FVWM_MODULEDIR)\" \ -DFVWM_DATADIR=\"$(FVWM_DATADIR)\" \ -DFVWM_CONFDIR=\"$(FVWM_CONFDIR)\" \ -DFVWM_COLORSET_PRIVATE=1 \ -DLOCALEDIR=\"$(LOCALEDIR)\" ## Create compatibility symlinks if available fvwm_name =`echo "fvwm" | "$(SED)" -e "${transform}"` fvwm2_name =`echo "fvwm2" | "$(SED)" -e "${transform}"` install-exec-local: @rm -f $(DESTDIR)$(bindir)/$(fvwm2_name)$(EXEEXT) @$(LN_S) $(fvwm_name)$(EXEEXT) \ $(DESTDIR)$(bindir)/$(fvwm2_name)$(EXEEXT) || \ echo "Minor warning: $(bindir)/fvwm2 symlink was not created" uninstall-local: @rm -f $(DESTDIR)$(bindir)/$(fvwm2_name)$(EXEEXT) fvwm-2.7.0/fvwm/decorations.c0000644000175000017500000004561114147024700013063 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include #include "libs/fvwmlib.h" #include "libs/FShape.h" #include "libs/Parse.h" #include "libs/lang-strings.h" #include "fvwm.h" #include "externs.h" #include "execcontext.h" #include "commands.h" #include "misc.h" #include "screen.h" #include "update.h" #include "style.h" #include "geometry.h" #include "decorations.h" /* ---------------------------- local definitions -------------------------- */ /* Motif window hints */ #define MWM_HINTS_FUNCTIONS (1L << 0) #define MWM_HINTS_DECORATIONS (1L << 1) /* bit definitions for MwmHints.functions */ #define MWM_FUNC_ALL (1L << 0) #define MWM_FUNC_RESIZE (1L << 1) #define MWM_FUNC_MOVE (1L << 2) #define MWM_FUNC_MINIMIZE (1L << 3) #define MWM_FUNC_MAXIMIZE (1L << 4) #define MWM_FUNC_CLOSE (1L << 5) /* bit definitions for MwmHints.decorations */ #if 0 #define MWM_DECOR_ALL (1L << 0) #define MWM_DECOR_BORDER (1L << 1) #define MWM_DECOR_RESIZEH (1L << 2) #define MWM_DECOR_TITLE (1L << 3) #define MWM_DECOR_MENU (1L << 4) #define MWM_DECOR_MINIMIZE (1L << 5) #define MWM_DECOR_MAXIMIZE (1L << 6) #endif #define PROP_MOTIF_WM_HINTS_ELEMENTS 4 #define PROP_MWM_HINTS_ELEMENTS PROP_MOTIF_WM_HINTS_ELEMENTS /* bit definitions for OL hints; I just * made these up, OL stores hints as atoms */ #define OL_DECOR_CLOSE (1L << 0) #define OL_DECOR_RESIZEH (1L << 1) #define OL_DECOR_HEADER (1L << 2) #define OL_DECOR_ICON_NAME (1L << 3) #define OL_DECOR_ALL \ (OL_DECOR_CLOSE | OL_DECOR_RESIZEH | OL_DECOR_HEADER | OL_DECOR_ICON_NAME) /* indicates if there are any OL hints */ #define OL_ANY_HINTS (1L << 7) /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ extern Atom _XA_MwmAtom; /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* Motif window hints */ typedef struct { long flags; long functions; long decorations; long inputMode; } PropMotifWmHints; typedef PropMotifWmHints PropMwmHints; /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ /* ---------------------------- interface functions ------------------------ */ /* * * Reads the property MOTIF_WM_HINTS * */ void GetMwmHints(FvwmWindow *t) { int actual_format; Atom actual_type; unsigned long nitems, bytesafter; if (t->mwm_hints) { XFree((char *)t->mwm_hints); t->mwm_hints = NULL; } if (XGetWindowProperty( dpy, FW_W(t), _XA_MwmAtom, 0L, 32L, False, _XA_MwmAtom, &actual_type, &actual_format, &nitems, &bytesafter,(unsigned char **)&t->mwm_hints)==Success) { if (nitems >= PROP_MOTIF_WM_HINTS_ELEMENTS) { return; } } t->mwm_hints = NULL; return; } /* * * Reads the openlook properties _OL_WIN_ATTR, _OL_DECOR_ADD, _OL_DECOR_DEL * * _OL_WIN_ATTR - the win_type field is the either the first atom if the * property has length three or the second atom if the property has * length five. It can be any of: * _OL_WT_BASE (no changes) * _OL_WT_CMD (no minimize decoration) * _OL_WT_HELP (no minimize, maximize or resize handle decorations) * _OL_WT_NOTICE (no minimize, maximize, system menu, resize handle * or titlebar decorations) * _OL_WT_OTHER (no minimize, maximize, system menu, resize handle * or titlebar decorations) * In addition, if the _OL_WIN_ATTR property is in the three atom format * or if the type is _OL_WT_OTHER, then the icon name is not displayed * (same behavior as olvwm). * * _OL_DECOR_ADD or _OL_DECOR_DEL - indivdually add or remove minimize * button (_OL_DECOR_CLOSE), resize handles (_OL_DECOR_RESIZE), title bar * (_OL_DECOR_HEADER), or icon name (_OL_DECOR_ICON_NAME). * * The documentation for the Open Look hints was taken from "Advanced X * Window Application Programming", Eric F. Johnson and Kevin Reichard * (M&T Books), and the olvwm source code (available at ftp.x.org in * /R5contrib). */ void GetOlHints(FvwmWindow *t) { int actual_format; Atom actual_type; unsigned long nitems, bytesafter; Atom *hints; int i; Atom win_type; t->ol_hints = OL_DECOR_ALL; if (XGetWindowProperty( dpy, FW_W(t), _XA_OL_WIN_ATTR, 0L, 32L, False, _XA_OL_WIN_ATTR, &actual_type, &actual_format, &nitems, &bytesafter, (unsigned char **)&hints) == Success) { if (nitems > 0) { t->ol_hints |= OL_ANY_HINTS; if (nitems == 3) { win_type = hints[0]; } else { win_type = hints[1]; } /* got this from olvwm and sort of mapped it to * fvwm/MWM hints */ if (win_type == _XA_OL_WT_BASE) { t->ol_hints = OL_DECOR_ALL; } else if (win_type == _XA_OL_WT_CMD) { t->ol_hints = OL_DECOR_ALL & ~OL_DECOR_CLOSE; } else if (win_type == _XA_OL_WT_HELP) { t->ol_hints = OL_DECOR_ALL & ~(OL_DECOR_CLOSE | OL_DECOR_RESIZEH); } else if (win_type == _XA_OL_WT_NOTICE) { t->ol_hints = OL_DECOR_ALL & ~(OL_DECOR_CLOSE | OL_DECOR_RESIZEH | OL_DECOR_HEADER | OL_DECOR_ICON_NAME); } else if (win_type == _XA_OL_WT_OTHER) { t->ol_hints = 0; } else { t->ol_hints = OL_DECOR_ALL; } if (nitems == 3) { t->ol_hints &= ~OL_DECOR_ICON_NAME; } } if (hints) { XFree (hints); } } if (XGetWindowProperty( dpy, FW_W(t), _XA_OL_DECOR_ADD, 0L, 32L, False, XA_ATOM, &actual_type, &actual_format, &nitems, &bytesafter,(unsigned char **)&hints)==Success) { for (i = 0; i < nitems; i++) { t->ol_hints |= OL_ANY_HINTS; if (hints[i] == _XA_OL_DECOR_CLOSE) { t->ol_hints |= OL_DECOR_CLOSE; } else if (hints[i] == _XA_OL_DECOR_RESIZE) { t->ol_hints |= OL_DECOR_RESIZEH; } else if (hints[i] == _XA_OL_DECOR_HEADER) { t->ol_hints |= OL_DECOR_HEADER; } else if (hints[i] == _XA_OL_DECOR_ICON_NAME) { t->ol_hints |= OL_DECOR_ICON_NAME; } } if (hints) { XFree (hints); } } if (XGetWindowProperty( dpy, FW_W(t), _XA_OL_DECOR_DEL, 0L, 32L, False, XA_ATOM, &actual_type, &actual_format, &nitems, &bytesafter,(unsigned char **)&hints)==Success) { for (i = 0; i < nitems; i++) { t->ol_hints |= OL_ANY_HINTS; if (hints[i] == _XA_OL_DECOR_CLOSE) { t->ol_hints &= ~OL_DECOR_CLOSE; } else if (hints[i] == _XA_OL_DECOR_RESIZE) { t->ol_hints &= ~OL_DECOR_RESIZEH; } else if (hints[i] == _XA_OL_DECOR_HEADER) { t->ol_hints &= ~OL_DECOR_HEADER; } else if (hints[i] == _XA_OL_DECOR_ICON_NAME) { t->ol_hints &= ~OL_DECOR_ICON_NAME; } } if (hints) { XFree (hints); } } return; } /* * * Interprets the property MOTIF_WM_HINTS, sets decoration and functions * accordingly * */ void SelectDecor(FvwmWindow *t, window_style *pstyle, short *buttons) { int decor; int i; int border_width; int handle_width; int used_width; PropMwmHints *prop; style_flags *sflags = &(pstyle->flags); border_width = (SHAS_BORDER_WIDTH(sflags)) ? SGET_BORDER_WIDTH(*pstyle) : DEFAULT_BORDER_WIDTH; if (border_width > MAX_BORDER_WIDTH) { border_width = MAX_BORDER_WIDTH; } handle_width = (SHAS_HANDLE_WIDTH(sflags)) ? SGET_HANDLE_WIDTH(*pstyle) : DEFAULT_HANDLE_WIDTH; if (handle_width > MAX_HANDLE_WIDTH) { handle_width = MAX_HANDLE_WIDTH; } *buttons = (1 << NUMBER_OF_TITLE_BUTTONS) - 1; decor = MWM_DECOR_ALL; t->functions = MWM_FUNC_ALL; if (t->mwm_hints) { prop = (PropMwmHints *)t->mwm_hints; if (SHAS_MWM_DECOR(sflags)) { if (prop->flags & MWM_HINTS_DECORATIONS) { decor = 0; if (prop->decorations & 0x1) { decor |= MWM_DECOR_ALL; } if (prop->decorations & 0x2) { decor |= MWM_DECOR_BORDER; } if (prop->decorations & 0x4) { decor |= MWM_DECOR_RESIZEH; } if (prop->decorations & 0x8) { decor |= MWM_DECOR_TITLE; } if (prop->decorations & 0x10) { decor |= MWM_DECOR_MENU; } if (prop->decorations & 0x20) { decor |= MWM_DECOR_MINIMIZE; } if (prop->decorations & 0x40) { decor |= MWM_DECOR_MAXIMIZE; } } } if (SHAS_MWM_FUNCTIONS(sflags)) { if (prop->flags & MWM_HINTS_FUNCTIONS) { t->functions = prop->functions; } } } /* functions affect the decorations! if the user says * no iconify function, then the iconify button doesn't show * up. */ if (t->functions & MWM_FUNC_ALL) { /* If we get ALL + some other things, that means to use * ALL except the other things... */ t->functions &= ~MWM_FUNC_ALL; t->functions = (MWM_FUNC_RESIZE | MWM_FUNC_MOVE | MWM_FUNC_MINIMIZE | MWM_FUNC_MAXIMIZE | MWM_FUNC_CLOSE) & (~(t->functions)); } if (SHAS_MWM_FUNCTIONS(sflags) && IS_TRANSIENT(t)) { t->functions &= ~(MWM_FUNC_MAXIMIZE|MWM_FUNC_MINIMIZE); } if (decor & MWM_DECOR_ALL) { /* If we get ALL + some other things, that means to use * ALL except the other things... */ decor &= ~MWM_DECOR_ALL; decor = MWM_DECOR_EVERYTHING & (~decor); } /* now add/remove any functions specified in the OL hints */ if (SHAS_OL_DECOR(sflags) && (t->ol_hints & OL_ANY_HINTS)) { if (t->ol_hints & OL_DECOR_CLOSE) { t->functions |= MWM_FUNC_MINIMIZE; decor |= MWM_FUNC_MINIMIZE; } else { t->functions &= ~MWM_FUNC_MINIMIZE; decor &= ~MWM_FUNC_MINIMIZE; } if (t->ol_hints & OL_DECOR_RESIZEH) { t->functions |= (MWM_FUNC_RESIZE | MWM_FUNC_MAXIMIZE); decor |= (MWM_FUNC_RESIZE | MWM_FUNC_MAXIMIZE); } else { t->functions &= ~(MWM_FUNC_RESIZE | MWM_FUNC_MAXIMIZE); decor &= ~(MWM_FUNC_RESIZE | MWM_FUNC_MAXIMIZE); } if (t->ol_hints & OL_DECOR_HEADER) { t->functions |= (MWM_DECOR_MENU | MWM_FUNC_MINIMIZE | MWM_FUNC_MAXIMIZE | MWM_DECOR_TITLE); decor |= (MWM_DECOR_MENU | MWM_FUNC_MINIMIZE | MWM_FUNC_MAXIMIZE | MWM_DECOR_TITLE); } else { t->functions &= ~(MWM_DECOR_MENU | MWM_FUNC_MINIMIZE | MWM_FUNC_MAXIMIZE | MWM_DECOR_TITLE); decor &= ~(MWM_DECOR_MENU | MWM_FUNC_MINIMIZE | MWM_FUNC_MAXIMIZE | MWM_DECOR_TITLE); } if (t->ol_hints & OL_DECOR_ICON_NAME) { SET_HAS_NO_ICON_TITLE(t, 0); } else { SET_HAS_NO_ICON_TITLE(t, 1); } } /* Now I have the un-altered decor and functions, but with the * ALL attribute cleared and interpreted. I need to modify the * decorations that are affected by the functions */ if (!(t->functions & MWM_FUNC_RESIZE)) { decor &= ~MWM_DECOR_RESIZEH; } /* MWM_FUNC_MOVE has no impact on decorations. */ if (!(t->functions & MWM_FUNC_MINIMIZE)) { decor &= ~MWM_DECOR_MINIMIZE; } if (!(t->functions & MWM_FUNC_MAXIMIZE)) { decor &= ~MWM_DECOR_MAXIMIZE; } /* MWM_FUNC_CLOSE has no impact on decorations. */ /* This rule is implicit, but its easier to deal with if * I take care of it now */ if (decor & (MWM_DECOR_MENU| MWM_DECOR_MINIMIZE | MWM_DECOR_MAXIMIZE)) { decor |= MWM_DECOR_TITLE; } /* Selected the mwm-decor field, now trim down, based on * .fvwmrc entries */ if (SHAS_NO_TITLE(sflags) || (!SDO_DECORATE_TRANSIENT(sflags) && IS_TRANSIENT(t))) { decor &= ~MWM_DECOR_TITLE; } if (SHAS_NO_HANDLES(sflags) || (!SDO_DECORATE_TRANSIENT(sflags) && IS_TRANSIENT(t))) { decor &= ~MWM_DECOR_RESIZEH; } if (SHAS_MWM_DECOR(sflags) && IS_TRANSIENT(t)) { decor &= ~(MWM_DECOR_MAXIMIZE|MWM_DECOR_MINIMIZE); } if (FShapesSupported) { if (t->wShaped) { decor &= ~(MWM_DECOR_BORDER|MWM_DECOR_RESIZEH); } } if (IS_EWMH_FULLSCREEN(t)) { decor &=~(MWM_DECOR_BORDER|MWM_DECOR_RESIZEH|MWM_DECOR_TITLE); } /* Assume no decorations, and build up */ SET_HAS_TITLE(t, 0); SET_HAS_HANDLES(t, 0); used_width = 0; if (decor & MWM_DECOR_BORDER) { /* A narrow border is displayed (5 pixels - 2 relief, 1 top, * (2 shadow) */ used_width = border_width; } if (decor & MWM_DECOR_TITLE) { /* A title bar with no buttons in it * window gets a 1 pixel wide black border. */ SET_HAS_TITLE(t, 1); } if (decor & MWM_DECOR_RESIZEH) { /* A wide border, with corner tiles is desplayed * (10 pixels - 2 relief, 2 shadow) */ SET_HAS_HANDLES(t, 1); used_width = handle_width; } SET_HAS_NO_BORDER(t, S_HAS_NO_BORDER(SFC(*sflags)) || used_width <= 0); if (HAS_NO_BORDER(t)) { used_width = 0; } SET_HAS_HANDLES(t, (!HAS_NO_BORDER(t) && HAS_HANDLES(t))); set_window_border_size(t, used_width); if (!(decor & MWM_DECOR_MENU)) { /* title-bar menu button omitted * window gets 1 pixel wide black border */ /* disable any buttons with the MWMDecorMenu flag */ int i; for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; ++i) { if (TB_HAS_MWM_DECOR_MENU(GetDecor(t, buttons[i]))) { *buttons &= ~(1 << i); } } } if (!(decor & MWM_DECOR_MINIMIZE)) { /* title-bar + iconify button, no menu button. * window gets 1 pixel wide black border */ /* disable any buttons with the MWMDecorMinimize/MWMDecorShaded * flag */ int i; for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; ++i) { if (TB_HAS_MWM_DECOR_MINIMIZE(GetDecor(t, buttons[i]))) { *buttons &= ~(1 << i); } } } if (!(decor & MWM_DECOR_MAXIMIZE)) { /* title-bar + maximize button, no menu button, no iconify. * window has 1 pixel wide black border */ /* disable any buttons with the MWMDecorMaximize flag */ int i; for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; ++i) { if (TB_HAS_MWM_DECOR_MAXIMIZE(GetDecor(t, buttons[i]))) { *buttons &= ~(1 << i); } } } for (i = (1 << (NUMBER_OF_TITLE_BUTTONS - 1)); i; i >>= 1) { if (t->buttons & i) *buttons &= ~i; } t->nr_left_buttons = Scr.nr_left_buttons; t->nr_right_buttons = Scr.nr_right_buttons; for (i = 0; i / 2 < Scr.nr_left_buttons; i += 2) { if ((*buttons & (1 << i)) == 0) t->nr_left_buttons--; } for (i = 1; i / 2 < Scr.nr_right_buttons; i += 2) { if ((*buttons & (1 << i)) == 0) t->nr_right_buttons--; } return; } static Bool __is_resize_allowed( const FvwmWindow *t, int functions, request_origin_t request_origin) { if (!HAS_OVERRIDE_SIZE_HINTS(t) && t->hints.min_width == t->hints.max_width && t->hints.min_height == t->hints.max_height) { return False; } if (request_origin && IS_SIZE_FIXED(t)) { return False; } else if (!request_origin && IS_PSIZE_FIXED(t)) { return False; } if (request_origin && !(functions & MWM_FUNC_RESIZE)) { return False; } return True; } /* ** seemed kind of silly to have check_allowed_function and ** check_allowed_function2 partially overlapping in their checks, so I ** combined them here and made them wrapper functions instead. */ Bool is_function_allowed( int function, char *action_string, const FvwmWindow *t, request_origin_t request_origin, Bool do_allow_override_mwm_hints) { unsigned int functions; char *functionlist[] = { MOVE_STRING, RESIZE_STRING1, RESIZE_STRING2, MINIMIZE_STRING, MINIMIZE_STRING2, MAXIMIZE_STRING, CLOSE_STRING1, CLOSE_STRING2, CLOSE_STRING3, CLOSE_STRING4, NULL }; if (t == NULL) { return True; /* this logic come from animated menu */ } if (do_allow_override_mwm_hints && HAS_MWM_OVERRIDE_HINTS(t)) { /* allow everything */ functions = ~0; } else { /* restrict by mwm hints */ functions = t->functions; } /* Hate to do it, but for lack of a better idea, check based on the * menu entry name */ /* Complex functions are a little tricky, ignore them if no menu item*/ if (function == F_FUNCTION && action_string != NULL) { int i; /* remap to regular actions */ i = GetTokenIndex(action_string, functionlist, -1, NULL); switch (i) { case 0: function = F_MOVE; break; case 1: function = F_RESIZE; break; case 2: function = F_RESIZE; break; case 3: function = F_ICONIFY; break; case 4: function = F_ICONIFY; break; case 5: function = F_MAXIMIZE; break; case 6: function = F_CLOSE; break; case 7: function = F_DELETE; break; case 8: function = F_DESTROY; break; case 9: function = F_QUIT; break; default: break; } } /* now do the real checks */ switch(function) { case F_DELETE: if (IS_UNCLOSABLE(t)) { return False; } if (IS_TEAR_OFF_MENU(t)) { /* always allow this on tear off menus */ break; } if (!WM_DELETES_WINDOW(t)) { return False; } /* fall through to close clause */ case F_CLOSE: if (IS_UNCLOSABLE(t)) { return False; } if (IS_TEAR_OFF_MENU(t)) { /* always allow this on tear off menus */ break; } if (!(functions & MWM_FUNC_CLOSE)) { return False; } break; case F_DESTROY: /* shouldn't destroy always be allowed??? */ if (IS_UNCLOSABLE(t)) { return False; } if (IS_TEAR_OFF_MENU(t)) { /* always allow this on tear off menus */ break; } if (!(functions & MWM_FUNC_CLOSE)) { return False; } break; case F_RESIZE: if(!__is_resize_allowed(t, functions, request_origin)) { return False; } break; case F_ICONIFY: if ((!IS_ICONIFIED(t) && !(functions & MWM_FUNC_MINIMIZE)) || IS_UNICONIFIABLE(t)) { return False; } break; case F_MAXIMIZE: if (IS_MAXIMIZE_FIXED_SIZE_DISALLOWED(t) && !__is_resize_allowed(t, functions, request_origin)) { return False; } if ((request_origin && !(functions & MWM_FUNC_MAXIMIZE)) || IS_UNMAXIMIZABLE(t)) { return False; } break; case F_MOVE: /* Move is a funny hint. Keeps it out of the menu, but you're * still allowed to move. */ if (request_origin && IS_FIXED(t)) { return False; } else if (!request_origin && IS_FIXED_PPOS(t)) { return False; } if (request_origin && !(functions & MWM_FUNC_MOVE)) { return False; } break; case F_FUNCTION: default: break; } /* end of switch */ /* if we fell through, just return True */ return True; } fvwm-2.7.0/fvwm/expand.h0000644000175000017500000000125414147024676012044 00000000000000/* -*-c-*- */ #ifndef EXPAND_H #define EXPAND_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ char *expand_vars( char *input, char *arguments[], Bool addto, Bool ismod, cond_rc_t *cond_rc, const exec_context_t *exc); #endif /* EXPAND_H */ fvwm-2.7.0/fvwm/misc.h0000644000175000017500000000450614147024700011507 00000000000000/* -*-c-*- */ #ifndef MISC_H #define MISC_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ enum { GRAB_ALL = 0, /* sum of all grabs */ GRAB_STARTUP = 1, /* Startup busy cursor */ GRAB_NORMAL = 2, /* DeferExecution, Move, Resize, ... */ GRAB_MENU = 3, /* a menus.c grabing */ GRAB_BUSY = 4, /* BusyCursor stuff */ GRAB_BUSYMENU = 5, /* Allows menus.c to regrab the cursor */ GRAB_PASSIVE = 6, /* Override of passive grab, only prevents grab * to be released too early */ GRAB_FREEZE_CURSOR = 7, /* Freeze the cursor shape if a window is * pressed. */ GRAB_MAXVAL /* last GRAB macro + 1 */ }; /* ---------------------------- global macros ------------------------------ */ #ifdef ICON_DEBUG #define ICON_DBG(X) fprintf X; #else #define ICON_DBG(X) #endif /* ---------------------------- type definitions --------------------------- */ /* message levels for fvwm_msg */ typedef enum { DBG = 0, ECHO, INFO, WARN, OLD, ERR } fvwm_msg_t; typedef enum { ADDED_NONE = 0, ADDED_MENU, ADDED_DECOR, ADDED_FUNCTION } last_added_item_t; /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ Bool GrabEm( int cursor, int grab_context); Bool UngrabEm( int ungrab_context); int GetTwoArguments( char *action, int *val1, int *val2, int *val1_unit, int *val2_unit); void NewFontAndColor( FlocaleFont *flf, Pixel color, Pixel backcolor); void Keyboard_shortcuts( XEvent *ev, FvwmWindow *fw, int *x_defect, int *y_defect, int ReturnEvent); Bool check_if_fvwm_window_exists( FvwmWindow *fw); int truncate_to_multiple( int x, int m); Bool IsRectangleOnThisPage( const rectangle *rec, int desk); FvwmWindow *get_pointer_fvwm_window(void); Time get_server_time(void); void fvwm_msg(fvwm_msg_t type, char *id, char *msg, ...) __attribute__ ((format (printf, 3, 4))); void fvwm_msg_report_app(void); void fvwm_msg_report_app_and_workers(void); void set_last_added_item(last_added_item_t type, void *item); void print_g(char *text, rectangle *g); #endif /* MISC_H */ fvwm-2.7.0/fvwm/read.h0000644000175000017500000000154614147024700011470 00000000000000/* -*-c-*- */ #ifndef FVWM_READ_H #define FVWM_READ_H #include /* for FILE below */ /** * Full pathname of file read in progress, or NULL. **/ extern const char *get_current_read_file(void); extern const char *get_current_read_dir(void); /** * Read and execute each line from stream. * * Parameters eventp, fw, context, and Module supply the context * for executing the commands. * cond_rc_t is passed thru incase piperead is running in a function. **/ void run_command_stream( cond_rc_t *cond_rc, FILE *f, const exec_context_t *exc); /** * Given a filename, open it and execute the commands therein. * * If the filename is not an absolute path, search for it in * fvwm_userdir (set in main()) or in FVWM_DATADIR. Return 1 * if the file was found and executed. **/ int run_command_file(char *filename, const exec_context_t *exc); #endif fvwm-2.7.0/fvwm/execcontext.h0000644000175000017500000000525614147024700013110 00000000000000/* -*-c-*- */ #ifndef EXECCONTEXT_H #define EXECCONTEXT_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ /* Inernal types */ typedef struct { XEvent te; } exec_context_privileged_t; /* Interface types */ typedef enum { EXCT_NULL = '-', EXCT_INIT = 'I', EXCT_RESTART = 'R', EXCT_QUIT = 'Q', EXCT_TORESTART = 'r', EXCT_EVENT ='E', EXCT_MODULE ='M', EXCT_MENULOOP ='m', EXCT_PAGING = 'P', EXCT_SCHEDULE = 'S' } exec_context_type_t; typedef struct { XEvent *etrigger; XEvent *elast; } x_context_t; typedef struct { FvwmWindow *fw; Window w; unsigned long wcontext; } window_context_t; struct fmodule; typedef struct { struct fmodule *module; } module_context_t; typedef struct { exec_context_type_t type; x_context_t x; window_context_t w; module_context_t m; /* for internal use *only*. *Never* acces this from outside! */ exec_context_privileged_t private_data; } exec_context_t; typedef enum { ECC_TYPE = 0x1, ECC_ETRIGGER = 0x2, ECC_FW = 0x4, ECC_W = 0x8, ECC_WCONTEXT = 0x10, ECC_MODULE = 0x20 } exec_context_change_mask_t; typedef struct { exec_context_type_t type; x_context_t x; window_context_t w; module_context_t m; } exec_context_changes_t; /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ /* Creates a new exec_context from the passed in arguments in malloc'ed memory. * The context must later be destroyed with exc_destroy_context(). * * Args: * ecc * Pointer to a structure which specifies the initial values of the struct * members. * mask * The mask of members in ecc to use. */ const exec_context_t *exc_create_context( exec_context_changes_t *ecc, exec_context_change_mask_t mask); /* Similar to exc_create_context(), but the created context contains only dummy * information. */ const exec_context_t *exc_create_null_context(void); /* Works like exc_create_context(), but initialises all values with the data * from excin. The ecc/mask pair overrides these values. */ const exec_context_t *exc_clone_context( const exec_context_t *excin, exec_context_changes_t *ecc, exec_context_change_mask_t mask); /* Destroys an exec_context structure that was created with * exc_create_context(). */ void exc_destroy_context(const exec_context_t *exc); #endif /* EXECCONTEXT_H */ fvwm-2.7.0/fvwm/icons.c0000644000175000017500000020617014147024700011663 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* * * fvwm icon code * */ #include "config.h" #include #ifdef HAVE_FCNTL_H #include #endif #include "libs/fvwmlib.h" #include "libs/FScreen.h" #include "libs/FShape.h" #include "libs/Parse.h" #include "libs/Picture.h" #include "libs/Graphics.h" #include "libs/PictureGraphics.h" #include "libs/FRenderInit.h" #include "libs/Rectangles.c" #include "libs/charmap.h" #include "libs/wcontext.h" #include "fvwm.h" #include "externs.h" #include "cursor.h" #include "execcontext.h" #include "commands.h" #include "bindings.h" #include "events.h" #include "eventmask.h" #include "eventhandler.h" #include "misc.h" #include "screen.h" #include "icons.h" #include "borders.h" #include "frame.h" #include "focus.h" #include "colormaps.h" #include "stack.h" #include "virtual.h" #include "decorations.h" #include "module_interface.h" #include "ewmh.h" #include "geometry.h" static int do_all_iconboxes(FvwmWindow *t, icon_boxes **icon_boxes_ptr); static void GetIconFromFile(FvwmWindow *fw); static void GetIconWindow(FvwmWindow *fw); static void GetIconBitmap(FvwmWindow *fw); static void clear_icon_dimensions(FvwmWindow *fw) { int px; int py; int tx; int ty; px = fw->icon_g.picture_w_g.x; py = fw->icon_g.picture_w_g.y; tx = fw->icon_g.title_w_g.x; ty = fw->icon_g.title_w_g.y; memset(&fw->icon_g, 0, sizeof(fw->icon_g)); fw->icon_g.picture_w_g.x = px; fw->icon_g.picture_w_g.y = py; fw->icon_g.title_w_g.x = tx; fw->icon_g.title_w_g.y = ty; return; } /* erase all traces of the last used icon in the window structure */ void clear_icon(FvwmWindow *fw) { FW_W_ICON_PIXMAP(fw) = None; fw->iconPixmap = None; fw->icon_maskPixmap = None; fw->icon_alphaPixmap = None; fw->icon_nalloc_pixels = 0; fw->icon_alloc_pixels = NULL; fw->icon_no_limit = 0; if (IS_ICON_MOVED(fw)) { clear_icon_dimensions(fw); } else { memset(&fw->icon_g, 0, sizeof(fw->icon_g)); } return; } int get_visible_icon_window_count(FvwmWindow *fw) { int count = 0; if (fw == NULL || !IS_ICONIFIED(fw) || IS_ICON_SUPPRESSED(fw)) { return 0; } if (FW_W_ICON_PIXMAP(fw) != None) { count++; } if (FW_W_ICON_TITLE(fw) != None) { count++; } return count; } void setup_icon_title_size(FvwmWindow *fw) { if (HAS_NO_ICON_TITLE(fw)) { fw->icon_g.title_text_width = 0; fw->icon_g.title_w_g.width = 0; fw->icon_g.title_w_g.height = 0; } else { fw->icon_g.title_text_width = FlocaleTextWidth( fw->icon_font, fw->visible_icon_name, strlen(fw->visible_icon_name)); fw->icon_g.title_w_g.height = ICON_HEIGHT(fw); if (fw->icon_g.picture_w_g.width == 0) { fw->icon_g.title_w_g.width = fw->icon_g.title_text_width + 2 * (ICON_TITLE_TEXT_GAP_COLLAPSED + abs(fw->icon_title_relief)); if (IS_STICKY_ACROSS_PAGES(fw) || IS_ICON_STICKY_ACROSS_PAGES(fw) || IS_STICKY_ACROSS_DESKS(fw) || IS_ICON_STICKY_ACROSS_DESKS(fw)) { fw->icon_g.title_w_g.width += 2 * (ICON_TITLE_TO_STICK_EXTRA_GAP + ICON_TITLE_STICK_MIN_WIDTH); } } else { fw->icon_g.title_w_g.width = fw->icon_g.picture_w_g.width; } } return; } /* * * Resizes the given icon Pixmap. * */ static void SetIconPixmapSize( Pixmap *icon, int width, int height, int depth, int newWidth, int newHeight, Bool force_centering, int resize_type, int *nrx, int *nry, int freeOldPixmap) { Pixmap oldPixmap; Pixmap resizedPixmap = None; int r_w,r_h; GC gc; XGCValues gc_init; *nrx = 0; *nry = 0; /* Check for invalid dimensions */ if (newWidth == 0 || newHeight == 0) { return; } /* Save the existing Pixmap */ oldPixmap = *icon; gc = XCreateGC(dpy, oldPixmap, 0, &gc_init); switch(resize_type) { case ICON_RESIZE_TYPE_ADJUSTED: if (newWidth != width || newHeight != height) { *icon = CreateStretchPixmap( dpy, oldPixmap, width, height, depth, newWidth, newHeight, gc); } break; case ICON_RESIZE_TYPE_STRETCHED: if (width < newWidth || height < newHeight) { r_w = max(newWidth, width); r_h = max(newHeight, height); resizedPixmap = CreateStretchPixmap( dpy, oldPixmap, width, height, depth, r_w, r_h, gc); width = r_w; height = r_h; } break; case ICON_RESIZE_TYPE_SHRUNK: if (width > newWidth || height > newHeight) { r_w = min(newWidth, width); r_h = min(newHeight, height); resizedPixmap = CreateStretchPixmap( dpy, oldPixmap, width, height, depth, r_w, r_h, gc); width = r_w; height = r_h; } break; default: break; } if (resize_type != ICON_RESIZE_TYPE_ADJUSTED) { *icon = XCreatePixmap( dpy, oldPixmap, newWidth, newHeight, depth); XSetForeground(dpy, gc, 0); XFillRectangle(dpy, *icon, gc, 0, 0, newWidth, newHeight); /* * Copy old Pixmap onto new. Center horizontally. Center * vertically if the new height is smaller than the old. * Otherwise, place the icon on the bottom, along the title bar. */ *nrx = (newWidth - width) / 2; *nry = (newHeight > height && !force_centering) ? newHeight - height : (newHeight - height) / 2; XCopyArea( dpy, (resizedPixmap)? resizedPixmap:oldPixmap, *icon, gc, 0, 0, width, height, *nrx, *nry); } XFreeGC(dpy, gc); if (freeOldPixmap) { XFreePixmap(dpy, oldPixmap); } } /* Move the icon of a window by dx/dy pixels */ /* * * Get the Icon for the icon window (also used by ewmh_icon) * */ void GetIconPicture(FvwmWindow *fw, Bool no_icon_window) { char icon_order[4]; int i; /* First, see if it was specified in the .fvwmrc */ if (ICON_OVERRIDE_MODE(fw) == ICON_OVERRIDE) { /* try fvwm provided icons before application provided icons */ icon_order[0] = 0; icon_order[1] = 1; icon_order[2] = 2; icon_order[3] = 3; ICON_DBG((stderr,"ciw: hint order: file iwh iph '%s'\n", fw->name.name)); } else if (ICON_OVERRIDE_MODE(fw) == NO_ACTIVE_ICON_OVERRIDE) { if (fw->wmhints && (fw->wmhints->flags & IconPixmapHint) && WAS_ICON_HINT_PROVIDED(fw) == ICON_HINT_MULTIPLE) { /* use application provided icon window or pixmap * first, then fvwm provided icons. */ icon_order[0] = 1; icon_order[1] = 2; icon_order[2] = 3; icon_order[3] = 0; ICON_DBG((stderr,"ciw: hint order: iwh iph file '%s'\n", fw->name.name)); } else if (Scr.DefaultIcon && fw->icon_bitmap_file == Scr.DefaultIcon) { /* use application provided icon window/pixmap first, * then fvwm provided default icon */ icon_order[0] = 1; icon_order[1] = 2; icon_order[2] = 3; icon_order[3] = 0; ICON_DBG((stderr,"ciw: hint order: iwh iph file '%s'\n", fw->name.name)); } else { /* use application provided icon window or ewmh icon * first, then fvwm provided icons and then application * provided icon pixmap */ icon_order[0] = 1; icon_order[1] = 2; icon_order[2] = 0; icon_order[3] = 3; ICON_DBG((stderr,"ciw: hint order: iwh file iph '%s'\n", fw->name.name)); } } else { /* use application provided icon rather than fvwm provided * icon */ icon_order[0] = 1; icon_order[1] = 2; icon_order[2] = 3; icon_order[3] = 0; ICON_DBG((stderr,"ciw: hint order: iwh iph file '%s'\n", fw->name.name)); } fw->icon_g.picture_w_g.width = 0; fw->icon_g.picture_w_g.height = 0; fw->iconPixmap = None; fw->icon_maskPixmap = None; fw->icon_alphaPixmap= None; FW_W_ICON_PIXMAP(fw) = None; for (i = 0; i < 4 && fw->icon_g.picture_w_g.width == 0 && fw->icon_g.picture_w_g.height == 0; i++) { switch (icon_order[i]) { case 0: /* Next, check for a color pixmap */ if (fw->icon_bitmap_file) { GetIconFromFile(fw); } ICON_DBG((stderr,"ciw: file%s used '%s'\n", (fw->icon_g.picture_w_g.height)?"":" not", fw->name.name)); break; case 1: /* Next, See if the app supplies its own icon window */ if (no_icon_window) { break; } if (fw->wmhints && (fw->wmhints->flags & IconWindowHint)) { GetIconWindow(fw); } ICON_DBG((stderr,"ciw: iwh%s used '%s'\n", (fw->icon_g.picture_w_g.height)?"":" not",fw->name.name)); break; case 2: /* try an ewmh icon */ if (HAS_EWMH_WM_ICON_HINT(fw) == EWMH_TRUE_ICON) { if (EWMH_SetIconFromWMIcon(fw, NULL, 0, False)) { SET_USE_EWMH_ICON(fw, True); } } ICON_DBG((stderr,"ciw: inh%s used '%s'\n", (fw->icon_g.picture_w_g.height)?"":" not",fw->name.name)); break; case 3: /* Finally, try to get icon bitmap from the * application */ if (fw->wmhints && (fw->wmhints->flags & IconPixmapHint)) { GetIconBitmap(fw); } ICON_DBG((stderr,"ciw: iph%s used '%s'\n", (fw->icon_g.picture_w_g.height)?"":" not",fw->name.name)); break; default: /* can't happen */ break; } } /* Resize icon if necessary */ if ((IS_ICON_OURS(fw)) && fw->icon_g.picture_w_g.height > 0 && fw->icon_g.picture_w_g.height > 0) { int newWidth = fw->icon_g.picture_w_g.width; int newHeight = fw->icon_g.picture_w_g.height; Boolean resize = False; if (newWidth < fw->min_icon_width) { newWidth = fw->min_icon_width; resize = True; } else { if (newWidth > fw->max_icon_width) { newWidth = fw->max_icon_width; resize = True; } } if (newHeight < fw->min_icon_height) { newHeight = fw->min_icon_height; resize = True; } else { if (newHeight > fw->max_icon_height) { newHeight = fw->max_icon_height; resize = True; } } if (resize) { /* Resize the icon Pixmap */ int force_centering = False; int nrx, nry; ICON_DBG((stderr, "ciw: Changing icon (%s) from %dx%d to" " %dx%d\n", fw->name.name, fw->icon_g.picture_w_g.width, fw->icon_g.picture_w_g.height, newWidth, newHeight)); /* Resize the icon Pixmap */ /* force to center if the icon has a bg */ if (fw->icon_background_cs >= 0 || fw->icon_maskPixmap == None) { force_centering = True; } SetIconPixmapSize( &(fw->iconPixmap), fw->icon_g.picture_w_g.width, fw->icon_g.picture_w_g.height, fw->iconDepth, newWidth, newHeight, force_centering, fw->icon_resize_type, &nrx, &nry, IS_PIXMAP_OURS(fw)); /* Resize the icon mask Pixmap if one was defined */ if (fw->icon_maskPixmap) { SetIconPixmapSize( &(fw->icon_maskPixmap), fw->icon_g.picture_w_g.width, fw->icon_g.picture_w_g.height, 1, newWidth, newHeight, force_centering, fw->icon_resize_type, &nrx, &nry, IS_PIXMAP_OURS(fw)); } else if ((nrx > 0 || nry > 0) && fw->iconDepth > 1) { fw->icon_maskPixmap = XCreatePixmap( dpy, fw->iconPixmap, newWidth, newHeight, 1); XSetForeground(dpy, Scr.MonoGC, 0); XFillRectangle( dpy, fw->icon_maskPixmap, Scr.MonoGC, 0, 0, newWidth, newHeight); XSetForeground(dpy, Scr.MonoGC, 1); XFillRectangle( dpy, fw->icon_maskPixmap, Scr.MonoGC, nrx, nry, fw->icon_g.picture_w_g.width, fw->icon_g.picture_w_g.height); XSetForeground(dpy, Scr.MonoGC, 0); /* set it shaped ? YES */ SET_ICON_SHAPED(fw, 1); } /* Resize the icon alpha Pixmap if one was defined */ if (fw->icon_alphaPixmap) { SetIconPixmapSize( &(fw->icon_alphaPixmap), fw->icon_g.picture_w_g.width, fw->icon_g.picture_w_g.height, FRenderGetAlphaDepth(), newWidth, newHeight, force_centering, fw->icon_resize_type, &nrx, &nry, IS_PIXMAP_OURS(fw)); } /* Set the new dimensions of the icon window */ fw->icon_g.picture_w_g.width = newWidth; fw->icon_g.picture_w_g.height = newHeight; } } return; } /* * * set the icon pixmap window background * */ static void set_icon_pixmap_background(FvwmWindow *fw) { if (fw->iconPixmap != None && (Pdefault || fw->iconDepth == 1 || fw->iconDepth == Pdepth || IS_PIXMAP_OURS(fw))) { if (fw->icon_background_cs >= 0) { SetWindowBackground( dpy, FW_W_ICON_PIXMAP(fw), fw->icon_g.picture_w_g.width, fw->icon_g.picture_w_g.height, &Colorset[fw->icon_background_cs], Pdepth, Scr.StdGC, False); } else if (FShapesSupported && Pdepth == DefaultDepth(dpy, (DefaultScreen(dpy)))) { XSetWindowBackgroundPixmap( dpy, FW_W_ICON_PIXMAP(fw), ParentRelative); } else if (Scr.DefaultColorset >= 0) { SetWindowBackground( dpy, FW_W_ICON_PIXMAP(fw), fw->icon_g.picture_w_g.width, fw->icon_g.picture_w_g.height, &Colorset[Scr.DefaultColorset], Pdepth, Scr.StdGC, False); } } } /* * * Creates an icon window as needed * */ void CreateIconWindow(FvwmWindow *fw, int def_x, int def_y) { /* mask for create windows */ unsigned long valuemask; /* attributes for create windows */ XSetWindowAttributes attributes; XWindowChanges xwc; Window old_icon_pixmap_w; Window old_icon_w; Bool is_old_icon_shaped = IS_ICON_SHAPED(fw); old_icon_w = FW_W_ICON_TITLE(fw); old_icon_pixmap_w = (IS_ICON_OURS(fw)) ? FW_W_ICON_PIXMAP(fw) : None; if (!IS_ICON_OURS(fw) && FW_W_ICON_PIXMAP(fw)) { XUnmapWindow(dpy, FW_W_ICON_PIXMAP(fw)); } SET_ICON_OURS(fw, 1); SET_PIXMAP_OURS(fw, 0); SET_ICON_SHAPED(fw, 0); FW_W_ICON_PIXMAP(fw) = None; fw->iconPixmap = None; fw->iconDepth = 0; if (IS_ICON_SUPPRESSED(fw)) { return; } /* * set up the icon picture */ GetIconPicture(fw, False); /* make space for relief to be drawn outside the icon */ /* this does not happen if fvwm is using a non-default visual (with * private colormap) and the client has supplied a pixmap (not a * bitmap) */ if ((IS_ICON_OURS(fw)) && (fw->icon_g.picture_w_g.height > 0) && (Pdefault || fw->iconDepth == 1 || fw->iconDepth == Pdepth || IS_PIXMAP_OURS(fw))) { fw->icon_g.picture_w_g.width += 2 * abs(fw->icon_background_relief) + 2 * fw->icon_background_padding; fw->icon_g.picture_w_g.height += 2 * abs(fw->icon_background_relief) + 2 * fw->icon_background_padding; } /* * set up the icon title geometry */ setup_icon_title_size(fw); /* * set up icon position */ set_icon_position(fw, def_x, def_y); /* * create the icon title window */ valuemask = CWColormap | CWBorderPixel | CWBackPixel | CWCursor | CWEventMask; attributes.colormap = Pcmap; attributes.background_pixel = Scr.StdBack; attributes.cursor = Scr.FvwmCursors[CRS_DEFAULT]; attributes.border_pixel = 0; attributes.event_mask = XEVMASK_ICONW; if (HAS_NO_ICON_TITLE(fw)) { if (FW_W_ICON_TITLE(fw)) { XDeleteContext(dpy, FW_W_ICON_TITLE(fw), FvwmContext); XDestroyWindow(dpy, FW_W_ICON_TITLE(fw)); XFlush(dpy); FW_W_ICON_TITLE(fw) = None; } } else { if (FW_W_ICON_TITLE(fw) == None) { FW_W_ICON_TITLE(fw) = XCreateWindow( dpy, Scr.Root, fw->icon_g.title_w_g.x, fw->icon_g.title_w_g.y, fw->icon_g.title_w_g.width, fw->icon_g.title_w_g.height, 0, Pdepth, InputOutput, Pvisual, valuemask, &attributes); } else { XMoveResizeWindow( dpy, FW_W_ICON_TITLE(fw), fw->icon_g.title_w_g.x, fw->icon_g.title_w_g.y, fw->icon_g.title_w_g.width, fw->icon_g.title_w_g.height); } } if (Scr.DefaultColorset >= 0) { SetWindowBackground( dpy, FW_W_ICON_TITLE(fw), fw->icon_g.title_w_g.width, fw->icon_g.title_w_g.height, &Colorset[Scr.DefaultColorset], Pdepth, Scr.StdGC, False); } /* * create the icon picture window */ if (IS_ICON_OURS(fw) && fw->icon_g.picture_w_g.width > 0 && fw->icon_g.picture_w_g.height > 0) { /* use fvwm's visuals in these cases */ if (Pdefault || fw->iconDepth == 1 || fw->iconDepth == Pdepth || IS_PIXMAP_OURS(fw)) { if (!old_icon_pixmap_w) { FW_W_ICON_PIXMAP(fw) = XCreateWindow( dpy, Scr.Root, fw->icon_g.picture_w_g.x, fw->icon_g.picture_w_g.y, fw->icon_g.picture_w_g.width, fw->icon_g.picture_w_g.height, 0, Pdepth, InputOutput, Pvisual, valuemask, &attributes); } else { FW_W_ICON_PIXMAP(fw) = old_icon_pixmap_w; XMoveResizeWindow( dpy, FW_W_ICON_PIXMAP(fw), fw->icon_g.picture_w_g.x, fw->icon_g.picture_w_g.y, fw->icon_g.picture_w_g.width, fw->icon_g.picture_w_g.height); } set_icon_pixmap_background(fw); } else { /* client supplied icon pixmap and fvwm is using * another visual. * use it as the background pixmap, don't try to put * relief on it because fvwm will not have the correct * colors the Exceed server has problems maintaining * the icon window, it usually fails to refresh the * icon leaving it black so ask for expose events */ attributes.background_pixmap = fw->iconPixmap; attributes.colormap = DefaultColormap(dpy, Scr.screen); valuemask &= ~CWBackPixel; valuemask |= CWBackPixmap; FW_W_ICON_PIXMAP(fw) = XCreateWindow( dpy, Scr.Root, fw->icon_g.picture_w_g.x, fw->icon_g.picture_w_g.y, fw->icon_g.picture_w_g.width, fw->icon_g.picture_w_g.height, 0, DefaultDepth(dpy, Scr.screen), InputOutput, DefaultVisual(dpy, Scr.screen), valuemask, &attributes); } } else if (FW_W_ICON_PIXMAP(fw) != None) { /* client supplied icon window: select events on it */ attributes.event_mask = XEVMASK_ICONPW; valuemask = CWEventMask; XChangeWindowAttributes( dpy, FW_W_ICON_PIXMAP(fw), valuemask,&attributes); if (!IS_ICON_OURS(fw)) { XMoveWindow( dpy, FW_W_ICON_PIXMAP(fw), fw->icon_g.picture_w_g.x, fw->icon_g.picture_w_g.y); } } if (old_icon_pixmap_w != None && old_icon_pixmap_w != FW_W_ICON_PIXMAP(fw)) { /* destroy the old window */ XDestroyWindow(dpy, old_icon_pixmap_w); XDeleteContext(dpy, old_icon_pixmap_w, FvwmContext); XFlush(dpy); is_old_icon_shaped = False; } if (FShapesSupported) { if (IS_ICON_SHAPED(fw) && fw->icon_background_cs < 0) { /* when fvwm is using the non-default visual client * supplied icon pixmaps are drawn in a window with no * relief */ int off = 0; if (Pdefault || fw->iconDepth == 1 || fw->iconDepth == Pdepth || IS_PIXMAP_OURS(fw)) { off = abs(fw->icon_background_relief) + fw->icon_background_padding; } SUPPRESS_UNUSED_VAR_WARNING(off); FShapeCombineMask( dpy, FW_W_ICON_PIXMAP(fw), FShapeBounding, off, off, fw->icon_maskPixmap, FShapeSet); } else if (is_old_icon_shaped && FW_W_ICON_PIXMAP(fw) == old_icon_pixmap_w) { /* remove the shape */ XRectangle r; r.x = 0; r.y = 0; r.width = fw->icon_g.picture_w_g.width; r.height = fw->icon_g.picture_w_g.height; SUPPRESS_UNUSED_VAR_WARNING(r); FShapeCombineRectangles( dpy, FW_W_ICON_PIXMAP(fw), FShapeBounding, 0, 0, &r, 1, FShapeSet, 0); } } if (FW_W_ICON_TITLE(fw) != None && FW_W_ICON_TITLE(fw) != old_icon_w) { XSaveContext( dpy, FW_W_ICON_TITLE(fw), FvwmContext, (caddr_t)fw); XDefineCursor( dpy, FW_W_ICON_TITLE(fw), Scr.FvwmCursors[CRS_DEFAULT]); GrabAllWindowKeysAndButtons( dpy, FW_W_ICON_TITLE(fw), Scr.AllBindings, C_ICON, GetUnusedModifiers(), Scr.FvwmCursors[CRS_DEFAULT], True); xwc.sibling = FW_W_FRAME(fw); xwc.stack_mode = Below; XConfigureWindow( dpy, FW_W_ICON_TITLE(fw), CWSibling|CWStackMode, &xwc); } if (FW_W_ICON_PIXMAP(fw) != None && FW_W_ICON_PIXMAP(fw) != old_icon_pixmap_w) { XSaveContext( dpy, FW_W_ICON_PIXMAP(fw), FvwmContext, (caddr_t)fw); XDefineCursor( dpy, FW_W_ICON_PIXMAP(fw), Scr.FvwmCursors[CRS_DEFAULT]); GrabAllWindowKeysAndButtons( dpy, FW_W_ICON_PIXMAP(fw), Scr.AllBindings, C_ICON, GetUnusedModifiers(), Scr.FvwmCursors[CRS_DEFAULT], True); xwc.sibling = FW_W_FRAME(fw); xwc.stack_mode = Below; XConfigureWindow( dpy,FW_W_ICON_PIXMAP(fw),CWSibling|CWStackMode,&xwc); } return; } /* * * Draws the icon window * */ static void DrawIconTitleWindow( FvwmWindow *fw, XEvent *pev, Pixel BackColor, GC Shadow, GC Relief, int cs, int title_cs) { int is_expanded = IS_ICON_ENTERED(fw); FlocaleWinString fstr; Region region = None; XRectangle clip, r; int relief = abs(fw->icon_title_relief); int x_title; int x_title_min = 0; int w_title = fw->icon_g.title_text_width; int x_title_w = fw->icon_g.picture_w_g.x; int w_title_w = fw->icon_g.picture_w_g.width; int x_stipple = relief; int w_title_text_gap = 0; int w_stipple = 0; int is_sticky; int is_stippled; int use_unexpanded_size = 1; Bool draw_string = True; is_sticky = (IS_STICKY_ACROSS_PAGES(fw) || IS_ICON_STICKY_ACROSS_PAGES(fw)); is_sticky |= (IS_STICKY_ACROSS_DESKS(fw) || IS_ICON_STICKY_ACROSS_DESKS(fw)); is_stippled = ((is_sticky && HAS_STICKY_STIPPLED_ICON_TITLE(fw)) || HAS_STIPPLED_ICON_TITLE(fw)); if (is_expanded && FW_W_ICON_PIXMAP(fw) != None) { int sx; int sy; int sw; int sh; use_unexpanded_size = 0; w_title_text_gap = ICON_TITLE_TEXT_GAP_EXPANDED; x_title_min = w_title_text_gap + relief; if (is_stippled) { w_stipple = ICON_TITLE_STICK_MIN_WIDTH; x_title_min += w_stipple + ICON_TITLE_TO_STICK_EXTRA_GAP; } /* resize the icon name window */ w_title_w = w_title + 2 * x_title_min; if (w_title_w <= fw->icon_g.picture_w_g.width) { /* the expanded title is smaller, so do not * expand at all */ is_expanded = 1; w_stipple = 0; use_unexpanded_size = 1; } else { x_title_w = fw->icon_g.picture_w_g.x - (w_title_w - fw->icon_g.picture_w_g.width) / 2; FScreenGetScrRect( NULL, FSCREEN_CURRENT, &sx, &sy, &sw, &sh); /* start keep label on screen. dje 8/7/97 */ if (x_title_w < sx) { /* if new loc neg (off left edge) */ x_title_w = sx; /* move to edge */ } else { /* if not on left edge */ /* if (new loc + width) > screen width * (off edge on right) */ if ((x_title_w + w_title_w) >sx + sw) { /* off right */ /* position up against right * edge */ x_title_w = sx + sw - w_title_w; } /* end keep label on screen. dje * 8/7/97 */ } } } if (use_unexpanded_size) { w_title_text_gap = ICON_TITLE_TEXT_GAP_COLLAPSED; x_title_min = w_title_text_gap + relief; /* resize the icon name window */ if (FW_W_ICON_PIXMAP(fw) != None) { w_title_w = fw->icon_g.picture_w_g.width; x_title_w = fw->icon_g.picture_w_g.x; } else { w_title_w = fw->icon_g.title_w_g.width; x_title_w = fw->icon_g.title_w_g.x; } } if (fw->icon_g.title_w_g.width != w_title_w || fw->icon_g.title_w_g.x != x_title_w || fw->icon_g.title_w_g.height != ICON_HEIGHT(fw)) { fw->icon_g.title_w_g.width = w_title_w; fw->icon_g.title_w_g.x = x_title_w; fw->icon_g.title_w_g.height = ICON_HEIGHT(fw); pev = NULL; /* resize && redraw all */ } if (!pev) { XMoveResizeWindow( dpy, FW_W_ICON_TITLE(fw), fw->icon_g.title_w_g.x, fw->icon_g.title_w_g.y, w_title_w, ICON_HEIGHT(fw)); } if (title_cs >= 0) { SetWindowBackground( dpy, FW_W_ICON_TITLE(fw), w_title_w, ICON_HEIGHT(fw), &Colorset[title_cs], Pdepth, Scr.TitleGC, False); } else { XSetWindowBackground( dpy, FW_W_ICON_TITLE(fw), BackColor); } /* text position */ x_title = (w_title_w - w_title) / 2; if (x_title < x_title_min) x_title = x_title_min; /* text rectangle */ r.x = x_title; r.y = relief; r.width = w_title_w - x_title - relief; r.height = ICON_HEIGHT(fw) - 2*relief; if (is_stippled) { if (w_stipple == 0) { w_stipple = ((w_title_w - 2 * (x_stipple + w_title_text_gap) - w_title) + 1) / 2; } if (w_stipple < ICON_TITLE_STICK_MIN_WIDTH) { w_stipple = ICON_TITLE_STICK_MIN_WIDTH; } if (x_title < x_stipple + w_stipple + w_title_text_gap) { x_title = x_stipple + w_stipple + w_title_text_gap; } r.x = x_title; r.width = w_title_w - 2 * x_title; if (r.width < 1) r.width = 1; } memset(&fstr, 0, sizeof(fstr)); if (pev || is_stippled) { if (pev) { if (!frect_get_intersection( pev->xexpose.x, pev->xexpose.y, pev->xexpose.width, pev->xexpose.height, r.x, r.y, r.width, r.height, &clip)) { draw_string = False; } } else { clip.x = r.x; clip.y = r.y; clip.width = r.width; clip.height = r.height; } if (draw_string) { XSetClipRectangles( dpy, Scr.TitleGC, 0, 0, &clip, 1, Unsorted); region = XCreateRegion(); XUnionRectWithRegion (&clip, region, region); fstr.flags.has_clip_region = True; fstr.clip_region = region; } } if (!pev) { clip.x = relief; clip.y = relief; clip.width = w_title_w - 2*relief; clip.height = ICON_HEIGHT(fw) - 2*relief; XClearWindow(dpy, FW_W_ICON_TITLE(fw)); } else { /* needed for first drawing */ if (x_title - relief >= 1) { /* clear before the text */ XClearArea( dpy, FW_W_ICON_TITLE(fw), relief, relief, x_title - relief, ICON_HEIGHT(fw) - 2*relief, False); } if (is_stippled) { /* clear the stippled area after the text */ XClearArea( dpy, FW_W_ICON_TITLE(fw), w_title_w - x_stipple - w_stipple -1, relief, w_stipple + 2, ICON_HEIGHT(fw) - 2*relief, False); } } if (draw_string) { if (pev) { /* needed by xft font and at first drawing */ XClearArea( dpy, FW_W_ICON_TITLE(fw), clip.x, clip.y, clip.width, clip.height, False); } fstr.str = fw->visible_icon_name; fstr.win = FW_W_ICON_TITLE(fw); fstr.gc = Scr.TitleGC; if (title_cs >= 0) { fstr.colorset = &Colorset[title_cs]; fstr.flags.has_colorset = 1; } else if (cs >= 0) { fstr.colorset = &Colorset[cs]; fstr.flags.has_colorset = 1; } fstr.x = x_title; fstr.y = fw->icon_g.title_w_g.height - relief - fw->icon_font->height + fw->icon_font->ascent; FlocaleDrawString(dpy, fw->icon_font, &fstr, 0); if (pev || is_stippled) { XSetClipMask(dpy, Scr.TitleGC, None); if (region) { XDestroyRegion(region); } } } RelieveRectangle( dpy, FW_W_ICON_TITLE(fw), 0, 0, w_title_w - 1, ICON_HEIGHT(fw) - 1, (fw->icon_title_relief > 0)? Relief:Shadow, (fw->icon_title_relief > 0)? Shadow:Relief, relief); if (is_stippled) { /* an odd number of lines every 4 pixels */ int pseudo_height = ICON_HEIGHT(fw)- 2*relief + 2; int num = (pseudo_height / ICON_TITLE_STICK_VERT_DIST / 2) * 2 - 1; int min = ICON_HEIGHT(fw) / 2 - num * 2 + 1; int max = ICON_HEIGHT(fw) / 2 + num * 2 - ICON_TITLE_STICK_VERT_DIST + 1; int i; for(i = min; w_stipple > 0 && i <= max; i += ICON_TITLE_STICK_VERT_DIST) { RelieveRectangle( dpy, FW_W_ICON_TITLE(fw), x_stipple, i, w_stipple - 1, 1, Shadow, Relief, ICON_TITLE_STICK_HEIGHT); RelieveRectangle( dpy, FW_W_ICON_TITLE(fw), w_title_w - x_stipple - w_stipple, i, w_stipple - 1, 1, Shadow, Relief, ICON_TITLE_STICK_HEIGHT); } } return; } static void DrawIconPixmapWindow( FvwmWindow *fw, Bool reset_bg, XEvent *pev, GC Shadow, GC Relief, int cs) { XRectangle r,clip; Bool cleared = False; if (!pev) { XMoveWindow( dpy, FW_W_ICON_PIXMAP(fw), fw->icon_g.picture_w_g.x, fw->icon_g.picture_w_g.y); if (reset_bg && (fw->iconDepth == 1 || fw->iconDepth == Pdepth || Pdefault || IS_PIXMAP_OURS(fw))) { set_icon_pixmap_background(fw); XClearArea(dpy, FW_W_ICON_PIXMAP(fw), 0, 0, 0, 0, False); cleared = True; } } /* need to locate the icon pixmap */ if (fw->iconPixmap != None) { if (fw->iconDepth == 1 || fw->iconDepth == Pdepth || Pdefault || IS_PIXMAP_OURS(fw)) { FvwmRenderAttributes fra; Bool draw_icon = True; memset(&fra, 0, sizeof(fra)); fra.mask = FRAM_DEST_IS_A_WINDOW; if (cs >= 0) { fra.mask |= FRAM_HAVE_ICON_CSET; fra.colorset = &Colorset[cs]; } r.x = r.y = abs(fw->icon_background_relief) + fw->icon_background_padding; r.width = fw->icon_g.picture_w_g.width - 2 * (abs(fw->icon_background_relief) + fw->icon_background_padding); r.height = fw->icon_g.picture_w_g.height - 2 * (abs(fw->icon_background_relief) + fw->icon_background_padding); if (pev) { if (!frect_get_intersection( pev->xexpose.x, pev->xexpose.y, pev->xexpose.width, pev->xexpose.height, r.x, r.y, r.width, r.height, &clip)) { draw_icon = False; } } else { clip.x = r.x; clip.y = r.y; clip.width = r.width; clip.height = r.height; } if (draw_icon) { if (!cleared && (fw->icon_alphaPixmap || (cs >= 0 && Colorset[cs].icon_alpha_percent < 100))) { XClearArea( dpy, FW_W_ICON_PIXMAP(fw), clip.x, clip.y, clip.width, clip.height, False); } PGraphicsRenderPixmaps( dpy, FW_W_ICON_PIXMAP(fw), fw->iconPixmap, fw->icon_maskPixmap, fw->icon_alphaPixmap, fw->iconDepth, &fra, FW_W_ICON_PIXMAP(fw), Scr.TitleGC, Scr.MonoGC, Scr.AlphaGC, clip.x - r.x, clip.y - r.y, clip.width, clip.height, clip.x, clip.y, clip.width, clip.height, False); } } else { /* it's a client pixmap and fvwm is not using * the root visual The icon window has no 3d * border so copy to (0,0) install the root * colormap temporarily to help the Exceed * server */ if (Scr.bo.do_install_root_cmap) InstallRootColormap(); XCopyArea( dpy, fw->iconPixmap, FW_W_ICON_PIXMAP(fw), DefaultGC(dpy, Scr.screen), 0, 0, fw->icon_g.picture_w_g.width, fw->icon_g.picture_w_g.height, 0, 0); if (Scr.bo.do_install_root_cmap) UninstallRootColormap(); } } /* only relieve unshaped icons or icons with a bg that share fvwm's * visual */ if ((fw->iconPixmap != None) && (!IS_ICON_SHAPED(fw) || fw->icon_background_cs >= 0) && (Pdefault || fw->iconDepth == 1 || fw->iconDepth == Pdepth || IS_PIXMAP_OURS(fw))) { RelieveRectangle( dpy, FW_W_ICON_PIXMAP(fw), 0, 0, fw->icon_g.picture_w_g.width - 1, fw->icon_g.picture_w_g.height - 1, (fw->icon_background_relief > 0)? Relief:Shadow, (fw->icon_background_relief > 0)? Shadow:Relief, abs(fw->icon_background_relief)); } } void DrawIconWindow( FvwmWindow *fw, Bool draw_title, Bool draw_pixmap, Bool focus_change, Bool reset_bg, XEvent *pev) { GC Shadow; GC Relief; Pixel TextColor; Pixel BackColor; color_quad draw_colors; color_quad co_draw_colors; int cs, co_cs; int title_cs = -1; int co_title_cs = -1; int is_expanded = IS_ICON_ENTERED(fw); if (IS_ICON_SUPPRESSED(fw) || (pev && fw->Desk != Scr.CurrentDesk)) { return; } if (Scr.Hilite == fw) { if (fw->icon_title_cs_hi >= 0) { title_cs = fw->icon_title_cs_hi; draw_colors.hilight = Colorset[title_cs].hilite; draw_colors.shadow = Colorset[title_cs].shadow; draw_colors.back = Colorset[title_cs].bg; draw_colors.fore = Colorset[title_cs].fg; } else { draw_colors.hilight = fw->hicolors.hilight; draw_colors.shadow = fw->hicolors.shadow; draw_colors.back = fw->hicolors.back; draw_colors.fore = fw->hicolors.fore; } if (fw->icon_title_cs >= 0) { co_title_cs = fw->icon_title_cs; co_draw_colors.hilight = Colorset[co_title_cs].hilite; co_draw_colors.shadow = Colorset[co_title_cs].shadow; co_draw_colors.back = Colorset[co_title_cs].bg; co_draw_colors.fore = Colorset[co_title_cs].fg; } else { co_draw_colors.hilight = fw->colors.hilight; co_draw_colors.shadow = fw->colors.shadow; co_draw_colors.back = fw->colors.back; co_draw_colors.fore = fw->colors.fore; } cs = fw->cs_hi; co_cs = fw->cs; } else { if (fw->icon_title_cs >= 0) { title_cs = fw->icon_title_cs; draw_colors.hilight = Colorset[title_cs].hilite; draw_colors.shadow = Colorset[title_cs].shadow; draw_colors.back = Colorset[title_cs].bg; draw_colors.fore = Colorset[title_cs].fg; } else { draw_colors.hilight = fw->colors.hilight; draw_colors.shadow = fw->colors.shadow; draw_colors.back = fw->colors.back; draw_colors.fore = fw->colors.fore; } if (fw->icon_title_cs_hi >= 0) { co_title_cs = fw->icon_title_cs_hi; co_draw_colors.hilight = Colorset[co_title_cs].hilite; co_draw_colors.shadow = Colorset[co_title_cs].shadow; co_draw_colors.back = Colorset[co_title_cs].bg; co_draw_colors.fore = Colorset[co_title_cs].fg; } else { co_draw_colors.hilight = fw->hicolors.hilight; co_draw_colors.shadow = fw->hicolors.shadow; co_draw_colors.back = fw->hicolors.back; co_draw_colors.fore = fw->hicolors.fore; } cs = fw->cs; co_cs = fw->cs_hi; } if (Pdepth < 2 && Scr.Hilite != fw) { Relief = Scr.StdReliefGC; Shadow = Scr.StdShadowGC; } else { if (Pdepth < 2 && Scr.Hilite == fw) { Relief = Scr.ScratchGC2; } else { Globalgcv.foreground = draw_colors.hilight; Globalgcm = GCForeground; XChangeGC(dpy,Scr.ScratchGC1,Globalgcm,&Globalgcv); Relief = Scr.ScratchGC1; } Globalgcv.foreground = draw_colors.shadow; XChangeGC(dpy,Scr.ScratchGC2, Globalgcm, &Globalgcv); Shadow = Scr.ScratchGC2; } TextColor = draw_colors.fore; BackColor = draw_colors.back; /* set up TitleGC for drawing the icon label */ if (fw->icon_font != NULL) { NewFontAndColor(fw->icon_font, TextColor, BackColor); } if (draw_title && FW_W_ICON_TITLE(fw) != None) { if (pev && pev->xexpose.window != FW_W_ICON_TITLE(fw)) { XEvent e; if (FCheckTypedWindowEvent( dpy, FW_W_ICON_TITLE(fw), Expose, &e)) { flush_accumulate_expose( FW_W_ICON_TITLE(fw), &e); DrawIconTitleWindow( fw, &e, BackColor, Shadow, Relief, cs, title_cs); } } else { if (!pev) { FCheckWeedTypedWindowEvents( dpy, FW_W_ICON_TITLE(fw), Expose, NULL); } DrawIconTitleWindow( fw, pev, BackColor, Shadow, Relief, cs, title_cs); } } if (draw_pixmap) { int bg_cs = fw->icon_background_cs; if (bg_cs >= 0 && (fw->iconDepth != 1 || fw->icon_background_padding > 0 || fw->icon_maskPixmap != None || fw->icon_alphaPixmap != None)) { if (Pdepth < 2 && Scr.Hilite == fw) { Relief = Scr.ScratchGC2; } else { Globalgcv.foreground = Colorset[bg_cs].hilite; Globalgcm = GCForeground; XChangeGC( dpy,Scr.ScratchGC1,Globalgcm,&Globalgcv); Relief = Scr.ScratchGC1; } Globalgcv.foreground = Colorset[bg_cs].shadow; XChangeGC(dpy,Scr.ScratchGC2, Globalgcm, &Globalgcv); Shadow = Scr.ScratchGC2; } } if (focus_change && draw_pixmap) { Bool alpha_change = False; Bool tint_change = False; Bool relief_change = False; Bool color_change = False; draw_pixmap = False; /* check if we have to draw the icons */ if (Pdepth < 2) { relief_change = True; } else if (fw->iconDepth == 1) { color_change = (draw_colors.fore != co_draw_colors.back) || (draw_colors.fore != co_draw_colors.back); } if (!relief_change && (fw->iconPixmap != None) && !IS_ICON_SHAPED(fw) && (Pdefault || fw->iconDepth == Pdepth || fw->iconDepth == 1 || IS_PIXMAP_OURS(fw))) { relief_change = (draw_colors.hilight != co_draw_colors.hilight) || (draw_colors.shadow != co_draw_colors.shadow); } if (cs >= 0 && co_cs >= 0) { alpha_change = (Colorset[cs].icon_alpha_percent != Colorset[co_cs].icon_alpha_percent); tint_change = (Colorset[cs].icon_tint_percent != Colorset[co_cs].icon_tint_percent) || (Colorset[cs].icon_tint_percent > 0 && Colorset[cs].icon_tint != Colorset[co_cs].icon_tint); } else if (cs >= 0 && co_cs < 0) { alpha_change = (Colorset[cs].icon_alpha_percent < 100); tint_change = (Colorset[cs].icon_tint_percent > 0); } else if (cs < 0 && co_cs >= 0) { alpha_change = (Colorset[co_cs].icon_alpha_percent < 100); tint_change = (Colorset[co_cs].icon_tint_percent > 0); } if (alpha_change || tint_change || relief_change || color_change) { draw_pixmap = True; } } if (draw_pixmap && FW_W_ICON_PIXMAP(fw) != None) { if (pev && pev->xexpose.window != FW_W_ICON_PIXMAP(fw)) { XEvent e; if (FCheckTypedWindowEvent( dpy, FW_W_ICON_PIXMAP(fw), Expose, &e)) { flush_accumulate_expose( FW_W_ICON_PIXMAP(fw), &e); DrawIconPixmapWindow( fw, reset_bg, &e, Shadow, Relief, cs); } } else { if (!pev) { FCheckWeedTypedWindowEvents( dpy, FW_W_ICON_PIXMAP(fw), Expose, NULL); } DrawIconPixmapWindow( fw, reset_bg, pev, Shadow, Relief, cs); } } if (is_expanded) { if (FW_W_ICON_TITLE(fw) != None) { XRaiseWindow(dpy, FW_W_ICON_TITLE(fw)); raisePanFrames(); } } else { XWindowChanges xwc; int mask; xwc.sibling = FW_W_FRAME(fw); xwc.stack_mode = Below; mask = CWSibling|CWStackMode; if (FW_W_ICON_TITLE(fw) != None) { XConfigureWindow(dpy, FW_W_ICON_TITLE(fw), mask, &xwc); } if (FW_W_ICON_PIXMAP(fw) != None) { XConfigureWindow(dpy, FW_W_ICON_PIXMAP(fw), mask, &xwc); } } /* wait for pending EnterNotify/LeaveNotify events to suppress race * condition w/ expanding/collapsing icon titles */ XFlush(dpy); } /* * * Procedure: * ChangeIconPixmap - procedure change the icon pixmap or "pixmap" * window. Called in events.c and ewmh_events.c * */ void ChangeIconPixmap(FvwmWindow *fw) { rectangle g; if (!IS_ICONIFIED(fw)) { ICON_DBG((stderr,"hpn: postpone icon change '%s'\n", fw->name.name)); /* update the icon later when application is iconified */ SET_HAS_ICON_CHANGED(fw, 1); } else if (IS_ICONIFIED(fw)) { ICON_DBG((stderr,"hpn: applying new icon '%s'\n", fw->name.name)); SET_ICONIFIED(fw, 0); SET_ICON_UNMAPPED(fw, 0); get_icon_geometry(fw, &g); CreateIconWindow(fw, g.x, g.y); broadcast_icon_geometry(fw, False); /* domivogt (15-Sep-1999): BroadcastConfig informs modules of * the configuration change including the iconified flag. So * this flag must be set here. I'm not sure if the two calls of * the SET_ICONIFIED macro after BroadcastConfig are necessary, * but since it's only minimal overhead I prefer to be on the * safe side. */ SET_ICONIFIED(fw, 1); BroadcastConfig(M_CONFIGURE_WINDOW, fw); SET_ICONIFIED(fw, 0); if (!IS_ICON_SUPPRESSED(fw)) { LowerWindow(fw, False); AutoPlaceIcon(fw, NULL, True); if (fw->Desk == Scr.CurrentDesk) { if (FW_W_ICON_TITLE(fw)) { XMapWindow(dpy, FW_W_ICON_TITLE(fw)); } if (FW_W_ICON_PIXMAP(fw) != None) { XMapWindow(dpy, FW_W_ICON_PIXMAP(fw)); } } } SET_ICONIFIED(fw, 1); DrawIconWindow(fw, False, True, False, False, NULL); } return; } /* * * Procedure: * RedoIconName - procedure to re-position the icon window and name * */ void RedoIconName(FvwmWindow *fw) { if (IS_ICON_SUPPRESSED(fw)) { return; } if (FW_W_ICON_TITLE(fw) == None) { return; } setup_icon_title_size(fw); /* clear the icon window, and trigger a re-draw via an expose event */ if (IS_ICONIFIED(fw)) { DrawIconWindow(fw, True, False, False, False, NULL); XClearArea(dpy, FW_W_ICON_TITLE(fw), 0, 0, 0, 0, True); } return; } /* * * Procedure: * AutoPlace - Find a home for an icon * */ void AutoPlaceIcon( FvwmWindow *t, initial_window_options_t *win_opts, Bool do_move_immediately) { int base_x, base_y; int width,height; FvwmWindow *test_fw; Bool loc_ok; Bool loc_ok_wrong_screen; Bool loc_ok_wrong_screen2; int real_x=10, real_y=10; int new_x, new_y; Bool do_move_icon = False; #if 0 /* dv (16-Mar-2003): We need to place the icon even if there is no icon so * the 'position' can be communicated to the modules to decide whether to show * the icon or not. */ if (FW_W_ICON_PIXMAP(t) == None && FW_W_ICON_TITLE(t) == None) { return; } #endif /* New! Put icon in same page as the center of the window */ /* Not a good idea for StickyIcons. Neither for icons of windows that are * visible on the current page. */ if (IS_ICON_STICKY_ACROSS_DESKS(t) || IS_STICKY_ACROSS_DESKS(t)) { t->Desk = Scr.CurrentDesk; } if (IS_ICON_STICKY_ACROSS_PAGES(t) || IS_STICKY_ACROSS_PAGES(t)) { base_x = 0; base_y = 0; /*Also, if its a stickyWindow, put it on the current page! */ new_x = t->g.frame.x % Scr.MyDisplayWidth; new_y = t->g.frame.y % Scr.MyDisplayHeight; if (new_x + t->g.frame.width <= 0) new_x += Scr.MyDisplayWidth; if (new_y + t->g.frame.height <= 0) new_y += Scr.MyDisplayHeight; frame_setup_window( t, new_x, new_y, t->g.frame.width, t->g.frame.height, False); } else if (IsRectangleOnThisPage(&(t->g.frame), t->Desk)) { base_x = 0; base_y = 0; } else { base_x = ((t->g.frame.x + Scr.Vx + (t->g.frame.width >> 1)) / Scr.MyDisplayWidth) * Scr.MyDisplayWidth; base_y= ((t->g.frame.y + Scr.Vy + (t->g.frame.height >> 1)) / Scr.MyDisplayHeight) * Scr.MyDisplayHeight; /* limit icon position to desktop */ if (base_x > Scr.VxMax) base_x = Scr.VxMax; if (base_x < 0) base_x = 0; if (base_y > Scr.VyMax) base_y = Scr.VyMax; if (base_y < 0) base_y = 0; base_x -= Scr.Vx; base_y -= Scr.Vy; } if (IS_ICON_MOVED(t) || (win_opts != NULL && win_opts->flags.use_initial_icon_xy)) { rectangle g; int dx; int dy; get_icon_geometry(t, &g); if (win_opts != NULL && win_opts->flags.use_initial_icon_xy) { g.x = win_opts->initial_icon_x; g.y = win_opts->initial_icon_y; } dx = g.x; dy = g.y; /* just make sure the icon is on this page */ g.x = g.x % Scr.MyDisplayWidth + base_x; g.y = g.y % Scr.MyDisplayHeight + base_y; if (g.x < 0) { g.x += Scr.MyDisplayWidth; } if (g.y < 0) { g.y += Scr.MyDisplayHeight; } dx = g.x - dx; dy = g.y - dy; modify_icon_position(t, dx, dy); do_move_icon = True; } else if (USE_ICON_POSITION_HINT(t) && t->wmhints && t->wmhints->flags & IconPositionHint) { set_icon_position(t, t->wmhints->icon_x, t->wmhints->icon_y); do_move_icon = True; } /* dje 10/12/97: Look thru chain of icon boxes assigned to window. Add logic for grids and fill direction. */ else if (DO_IGNORE_ICON_BOXES(t)) { int sx; int sy; int sw; int sh; fscreen_scr_arg fscr; rectangle g; get_icon_geometry(t, &g); get_icon_corner(t, &g); fscr.xypos.x = g.x + g.width / 2; fscr.xypos.y = g.y + g.height / 2; FScreenGetScrRect(&fscr, FSCREEN_XYPOS, &sx, &sy, &sw, &sh); if (g.x < sx) g.x = sx; else if (g.x + g.width > sx + sw) g.x = sx + sw - g.width; if (g.y < sy) g.y = sy; else if (g.y + g.height > sy + sh) g.y = sy + sh - g.height; set_icon_position(t, g.x, g.y); do_move_icon = True; } else { /* A place to hold inner and outer loop variables. */ typedef struct dimension_struct { int step; /* grid size (may be negative) */ int start_at; /* starting edge */ int real_start; /* on screen starting edge */ int end_at; /* ending edge */ int base; /* base for screen */ int icon_dimension; /* height or width */ int nom_dimension; /* nonminal height or width */ int screen_dimension; /* screen height or width */ int screen_offset; /* screen offset */ } dimension; dimension dim[3]; /* space for work, 1st, 2nd dimen */ icon_boxes *icon_boxes_ptr; /* current icon box */ int i; /* index for inner/outer loop data */ fscreen_scr_arg fscr; rectangle ref; rectangle g; /* Hopefully this makes the following more readable. */ #define ICONBOX_LFT icon_boxes_ptr->IconBox[0] #define ICONBOX_TOP icon_boxes_ptr->IconBox[1] #define ICONBOX_RGT icon_boxes_ptr->IconBox[2] #define ICONBOX_BOT icon_boxes_ptr->IconBox[3] #define BOT_FILL icon_boxes_ptr->IconFlags & ICONFILLBOT #define RGT_FILL icon_boxes_ptr->IconFlags & ICONFILLRGT #define HRZ_FILL icon_boxes_ptr->IconFlags & ICONFILLHRZ /* needed later */ fscr.xypos.x = t->g.frame.x + (t->g.frame.width / 2) - base_x; fscr.xypos.y = t->g.frame.y + (t->g.frame.height / 2) - base_y; get_icon_geometry(t, &g); /* unnecessary copy of width */ width = g.width; /* total height */ height = g.height; /* no slot found yet */ loc_ok = False; loc_ok_wrong_screen = False; /* check all boxes in order */ icon_boxes_ptr = NULL; /* init */ while(do_all_iconboxes(t, &icon_boxes_ptr)) { if (loc_ok == True) { /* leave for loop */ break; } /* get the screen dimensions for the icon box */ if (icon_boxes_ptr->IconScreen == FSCREEN_CURRENT) fscr.mouse_ev = NULL; FScreenGetScrRect( &fscr, icon_boxes_ptr->IconScreen, &ref.x, &ref.y, &ref.width, &ref.height); dim[1].screen_offset = ref.y; dim[1].screen_dimension = ref.height; dim[2].screen_offset = ref.x; dim[2].screen_dimension = ref.width; /* y amount */ dim[1].step = icon_boxes_ptr->IconGrid[1]; /* init start from */ dim[1].start_at = ICONBOX_TOP + dim[1].screen_offset; if (icon_boxes_ptr->IconSign[1] == '-') { dim[1].start_at += dim[1].screen_dimension; } /* init end at */ dim[1].end_at = ICONBOX_BOT + dim[1].screen_offset; if (icon_boxes_ptr->IconSign[3] == '-') { dim[1].end_at += dim[1].screen_dimension; } /* save base */ dim[1].base = base_y; /* save dimension */ dim[1].icon_dimension = height; if (BOT_FILL) { /* fill from bottom */ /* reverse step */ dim[1].step = 0 - dim[1].step; } /* end fill from bottom */ /* x amount */ dim[2].step = icon_boxes_ptr->IconGrid[0]; /* init start from */ dim[2].start_at = ICONBOX_LFT + dim[2].screen_offset; if (icon_boxes_ptr->IconSign[0] == '-') { dim[2].start_at += dim[2].screen_dimension; } /* init end at */ dim[2].end_at = ICONBOX_RGT + dim[2].screen_offset; if (icon_boxes_ptr->IconSign[2] == '-') { dim[2].end_at += dim[2].screen_dimension; } /* save base */ dim[2].base = base_x; /* save dimension */ dim[2].icon_dimension = width; if (RGT_FILL) { /* fill from right */ /* reverse step */ dim[2].step = 0 - dim[2].step; } /* end fill from right */ for (i=1;i<=2;i++) { /* for dimensions 1 and 2 */ /* If the window is taller than the icon box, ignore the icon height * when figuring where to put it. Same goes for the width * This should permit reasonably graceful handling of big icons. */ dim[i].nom_dimension = dim[i].icon_dimension; if (dim[i].icon_dimension >= dim[i].end_at - dim[i].start_at) { dim[i].nom_dimension = dim[i].end_at - dim[i].start_at - 1; } if (dim[i].step < 0) { /* if moving backwards */ /* save */ dim[0].start_at = dim[i].start_at; /* swap one */ dim[i].start_at = dim[i].end_at; /* swap the other */ dim[i].end_at = dim[0].start_at; dim[i].start_at -= dim[i].icon_dimension; } /* end moving backwards */ /* adjust both to base */ dim[i].start_at += dim[i].base; dim[i].end_at += dim[i].base; } /* end 2 dimensions */ if (HRZ_FILL) { /* if hrz first */ /* save */ memcpy(&dim[0],&dim[1],sizeof(dimension)); /* switch one */ memcpy(&dim[1],&dim[2],sizeof(dimension)); /* switch the other */ memcpy(&dim[2],&dim[0],sizeof(dimension)); } /* end horizontal dimension first */ /* save for reseting inner loop */ dim[0].start_at = dim[2].start_at; loc_ok_wrong_screen2 = False; while((dim[1].step < 0 /* filling reversed */ ? (dim[1].start_at + dim[1].icon_dimension - dim[1].nom_dimension > dim[1].end_at) /* check back edge */ : (dim[1].start_at + dim[1].nom_dimension < dim[1].end_at)) /* check front edge */ && (!loc_ok) && (!loc_ok_wrong_screen2)) { /* nothing found yet */ dim[1].real_start = dim[1].start_at; /* init */ if (dim[1].start_at + dim[1].icon_dimension > dim[1].screen_offset + dim[1].screen_dimension - 2 + dim[1].base) { /* off screen, move on screen */ dim[1].real_start = dim[1].screen_offset + dim[1].screen_dimension - dim[1].icon_dimension + dim[1].base; } /* end off screen */ if (dim[1].start_at < dim[1].screen_offset + dim[1].base) { /* if off other edge, move on screen */ dim[1].real_start = dim[1].screen_offset + dim[1].base; } /* end off other edge */ /* reset inner loop */ dim[2].start_at = dim[0].start_at; while((dim[2].step < 0 /* filling reversed */ ? (dim[2].start_at + dim[2].icon_dimension-dim[2].nom_dimension > dim[2].end_at) /* check back edge */ : (dim[2].start_at + dim[2].nom_dimension < dim[2].end_at)) /* check front edge */ && (!loc_ok) && (!loc_ok_wrong_screen2)) { /* nothing found yet */ dim[2].real_start = dim[2].start_at; /* init */ if (dim[2].start_at + dim[2].icon_dimension > dim[2].screen_offset + dim[2].screen_dimension - 2 + dim[2].base) { /* if off screen, move on screen */ dim[2].real_start = dim[2].screen_offset + dim[2].screen_dimension - dim[2].icon_dimension + dim[2].base; } /* end off screen */ if (dim[2].start_at < dim[2].screen_offset + dim[2].base) { /* if off other edge, move on screen */ dim[2].real_start = dim[2].screen_offset + dim[2].base; } /* end off other edge */ if (HRZ_FILL) { /* hrz first */ /* unreverse them */ real_x = dim[1].real_start; real_y = dim[2].real_start; } else { /* reverse them */ real_x = dim[2].real_start; real_y = dim[1].real_start; } /* this may be a good location */ if (FScreenIsRectangleOnScreen(&fscr, FSCREEN_XYPOS, &ref)) { loc_ok = True; } else { loc_ok_wrong_screen2 = True; } test_fw = Scr.FvwmRoot.next; while((test_fw != (FvwmWindow *)0) &&(loc_ok == True || loc_ok_wrong_screen2)) { /* test overlap */ if (test_fw->Desk == t->Desk) { rectangle g; if ((IS_ICONIFIED(test_fw)) && (!IS_TRANSIENT(test_fw) || !IS_ICONIFIED_BY_PARENT(test_fw)) && (FW_W_ICON_TITLE(test_fw)||FW_W_ICON_PIXMAP(test_fw)) && (test_fw != t)) { get_icon_geometry(test_fw, &g); if ((g.x<(real_x+width+MIN_ICON_BOX_DIST))&& ((g.x+g.width+MIN_ICON_BOX_DIST) > real_x)&& (g.y<(real_y+height+MIN_ICON_BOX_DIST))&& ((g.y+g.height + MIN_ICON_BOX_DIST)>real_y)) { /* don't accept this location */ loc_ok = False; loc_ok_wrong_screen2 = False; } /* end if icons overlap */ } /* end if its an icon */ } /* end if same desk */ test_fw = test_fw->next; } /* end while icons that may overlap */ if (loc_ok_wrong_screen2) { loc_ok_wrong_screen = True; } /* Grid inner value & direction */ dim[2].start_at += dim[2].step; } /* end while room inner dimension */ /* Grid outer value & direction */ dim[1].start_at += dim[1].step; } /* end while room outer dimension */ } /* end for all icon boxes, or found space */ if (!loc_ok && !loc_ok_wrong_screen) /* If icon never found a home just leave it */ return; set_icon_position(t, real_x, real_y); broadcast_icon_geometry(t, True); do_move_icon = True; } if (do_move_icon && do_move_immediately) { move_icon_to_position(t); } return; } static icon_boxes *global_icon_box_ptr; /* Find next icon box to try to place icon in. Goes thru chain that the window got thru style matching, then the global icon box. Create the global icon box on first call. Return code indicates when the boxes are used up. The boxes could only get completely used up when you fill the screen with them. */ static int do_all_iconboxes(FvwmWindow *t, icon_boxes **icon_boxes_ptr) { if (global_icon_box_ptr == 0) { /* if first time */ int sx; int sy; int sw; int sh; /* Right now, the global box is hard-coded, fills the primary * screen, uses an 80x80 grid, and fills top-bottom, * left-right */ FScreenGetScrRect(NULL, FSCREEN_PRIMARY, &sx, &sy, &sw, &sh); global_icon_box_ptr = calloc(1, sizeof(icon_boxes)); global_icon_box_ptr->IconBox[0] = sx; global_icon_box_ptr->IconBox[1] = sy; global_icon_box_ptr->IconBox[2] = sx + sw; global_icon_box_ptr->IconBox[3] = sy + sh; global_icon_box_ptr->IconGrid[0] = 80; global_icon_box_ptr->IconGrid[1] = 80; global_icon_box_ptr->IconFlags = ICONFILLHRZ; } if (*icon_boxes_ptr == NULL) { /* first time? */ /* start at windows box */ *icon_boxes_ptr = t->IconBoxes; if (!*icon_boxes_ptr) { /* if window has no box */ /* use global box */ *icon_boxes_ptr = global_icon_box_ptr; } /* use box */ return (1); } /* Here its not the first call, we are either on the chain or at * the global box */ if (*icon_boxes_ptr == global_icon_box_ptr) { /* if the global box */ /* completely out of boxes (unlikely) */ return (0); } /* move to next one on chain */ *icon_boxes_ptr = (*icon_boxes_ptr)->next; if (*icon_boxes_ptr) { /* if there is a next one */ /* return it */ return (1); } /* global box */ *icon_boxes_ptr = global_icon_box_ptr; /* use it */ return (1); } /* * * Looks for icon from a file * */ static void GetIconFromFile(FvwmWindow *fw) { char *path = NULL; FvwmPictureAttributes fpa; fpa.mask = 0; if (fw->cs >= 0 && Colorset[fw->cs].do_dither_icon) { fpa.mask |= FPAM_DITHER; } fw->icon_g.picture_w_g.width = 0; fw->icon_g.picture_w_g.height = 0; path = PictureFindImageFile(fw->icon_bitmap_file, NULL, R_OK); if (path == NULL) { return; } if (!PImageLoadPixmapFromFile( dpy, Scr.NoFocusWin, path, &fw->iconPixmap, &fw->icon_maskPixmap, &fw->icon_alphaPixmap, &fw->icon_g.picture_w_g.width, &fw->icon_g.picture_w_g.height, &fw->iconDepth, &fw->icon_nalloc_pixels, &fw->icon_alloc_pixels, &fw->icon_no_limit, fpa)) { fvwm_msg(ERR, "GetIconFromFile", "Failed to load %s", path); free(path); return; } SET_PIXMAP_OURS(fw, 1); free(path); if (FShapesSupported && fw->icon_maskPixmap) { SET_ICON_SHAPED(fw, 1); } return; } /* * * Looks for an application supplied icon window * */ static void GetIconWindow(FvwmWindow *fw) { int w; int h; int bw; fw->icon_g.picture_w_g.width = 0; fw->icon_g.picture_w_g.height = 0; /* We are guaranteed that wmhints is non-null when calling this * routine */ if (XGetGeometry( dpy, fw->wmhints->icon_window, &JunkRoot, &JunkX, &JunkY, (unsigned int*)&w, (unsigned int*)&h,(unsigned int*)&bw, (unsigned int*)&JunkDepth) == 0) { fvwm_msg( ERR,"GetIconWindow", "Window '%s' has a bad icon window! Ignoring icon" " window.", fw->name.name); /* disable the icon window hint */ fw->wmhints->icon_window = None; fw->wmhints->flags &= ~IconWindowHint; return; } fw->icon_border_width = bw; fw->icon_g.picture_w_g.width = w + 2 * bw; fw->icon_g.picture_w_g.height = h + 2 * bw; /* * Now make the new window the icon window for this window, * and set it up to work as such (select for key presses * and button presses/releases, set up the contexts for it, * and define the cursor for it). */ FW_W_ICON_PIXMAP(fw) = fw->wmhints->icon_window; if (FShapesSupported) { if (fw->wmhints->flags & IconMaskHint) { SET_ICON_SHAPED(fw, 1); fw->icon_maskPixmap = fw->wmhints->icon_mask; } } /* Make sure that the window is a child of the root window ! */ /* Olwais screws this up, maybe others do too! */ XReparentWindow(dpy, FW_W_ICON_PIXMAP(fw), Scr.Root, 0,0); SET_ICON_OURS(fw, 0); return; } /* * * Looks for an application supplied bitmap or pixmap * */ static void GetIconBitmap(FvwmWindow *fw) { int width, height, depth; fw->icon_g.picture_w_g.width = 0; fw->icon_g.picture_w_g.height = 0; /* We are guaranteed that wmhints is non-null when calling this routine */ if (!XGetGeometry( dpy, fw->wmhints->icon_pixmap, &JunkRoot, &JunkX, &JunkY, (unsigned int*)&width, (unsigned int*)&height, (unsigned int*)&JunkBW, (unsigned int*)&depth)) { fvwm_msg( ERR,"GetIconBitmap", "Window '%s' has a bad icon pixmap! Ignoring icon.", fw->name.name); /* disable icon pixmap hint */ fw->wmhints->icon_pixmap = None; fw->wmhints->flags &= ~IconPixmapHint; return; } /* sanity check the pixmap depth, it must be the same as the root or 1 */ if (depth != 1 && depth != Pdepth && depth != DefaultDepth(dpy,Scr.screen)) { fvwm_msg( ERR, "GetIconBitmap", "Window '%s' has a bad icon bitmap depth %d (should" " be 1, %d or %d)! Ignoring icon bitmap.", fw->name.name, depth, Pdepth, DefaultDepth(dpy,Scr.screen)); /* disable icon pixmap hint */ fw->wmhints->icon_pixmap = None; fw->wmhints->flags &= ~IconPixmapHint; return; } fw->iconPixmap = fw->wmhints->icon_pixmap; fw->icon_g.picture_w_g.width = width; fw->icon_g.picture_w_g.height = height; fw->iconDepth = depth; if (FShapesSupported) { if (fw->wmhints->flags & IconMaskHint) { SET_ICON_SHAPED(fw, 1); fw->icon_maskPixmap = fw->wmhints->icon_mask; } } SET_PIXMAP_OURS(fw, 0); return; } /* * * Procedure: * DeIconify a window * */ void DeIconify(FvwmWindow *fw) { FvwmWindow *t, *tmp, *ofw; FvwmWindow *sf = get_focus_window(); rectangle icon_rect; XWindowAttributes winattrs = {0}; if (!fw) { return; } if (!XGetWindowAttributes(dpy, FW_W(fw), &winattrs)) { return; } /* make sure fw->flags.is_map_pending is OK */ if (winattrs.map_state == IsViewable && IS_MAP_PENDING(fw)) { SET_MAP_PENDING(fw, 0); } else if (IS_MAP_PENDING(fw)) { /* final state: de-iconified */ SET_ICONIFY_AFTER_MAP(fw, 0); return; } for (ofw = NULL; fw != ofw && IS_ICONIFIED_BY_PARENT(fw); ) { t = get_transientfor_fvwmwindow(fw); if (t == NULL) { break; } ofw = fw; fw = t; } if (IS_ICONIFIED_BY_PARENT(fw)) { SET_ICONIFIED_BY_PARENT(fw, 0); } /* AS dje RaiseWindow(fw); */ if (fw == sf) { /* take away the focus before mapping */ DeleteFocus(True); } /* Note: DeleteFocus may delete the flags set by * mark_transient_subtree(), so do it later. */ mark_transient_subtree(fw, MARK_ALL_LAYERS, MARK_ALL, False, True); /* now de-iconify transients */ for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) { if (t == fw || IS_IN_TRANSIENT_SUBTREE(t)) { SET_IN_TRANSIENT_SUBTREE(t, 0); SET_MAPPED(t, 1); SET_ICONIFIED_BY_PARENT(t, 0); if (Scr.Hilite == t) { border_draw_decorations( t, PART_ALL, False, True, CLEAR_ALL, NULL, NULL); } /* AS stuff starts here dje */ if (FW_W_ICON_PIXMAP(t)) { XUnmapWindow(dpy, FW_W_ICON_PIXMAP(t)); } if (FW_W_ICON_TITLE(t)) { XUnmapWindow(dpy, FW_W_ICON_TITLE(t)); } XFlush(dpy); /* End AS */ XMapWindow(dpy, FW_W(t)); if (t->Desk == Scr.CurrentDesk) { rectangle r; get_icon_geometry(t, &r); /* update absoluthe geometry in case the icon * was moved over a page boundary; the move * code already takes care of keeping the frame * geometry up to date */ update_absolute_geometry(t); if (IsRectangleOnThisPage(&r, t->Desk) && !IsRectangleOnThisPage( &(t->g.frame), t->Desk)) { /* Make sure we keep it on screen when * de-iconifying. */ t->g.frame.x -= truncate_to_multiple( t->g.frame.x, Scr.MyDisplayWidth); t->g.frame.y -= truncate_to_multiple( t->g.frame.y, Scr.MyDisplayHeight); XMoveWindow( dpy, FW_W_FRAME(t), t->g.frame.x, t->g.frame.y); update_absolute_geometry(t); maximize_adjust_offset(t); } } /* domivogt (1-Mar-2000): The next block is a hack to * prevent animation if the window has an icon, but * neither a pixmap nor a title. */ if (HAS_NO_ICON_TITLE(t) && FW_W_ICON_PIXMAP(t) == None) { memset(&fw->icon_g, 0, sizeof(fw->icon_g)); } get_icon_geometry(t, &icon_rect); /* if this fails it does not overwrite icon_rect */ EWMH_GetIconGeometry(t, &icon_rect); if (t == fw) { BroadcastPacket( M_DEICONIFY, 11, (long)FW_W(t), (long)FW_W_FRAME(t), (unsigned long)t, (long)icon_rect.x, (long)icon_rect.y, (long)icon_rect.width, (long)icon_rect.height, (long)t->g.frame.x, (long)t->g.frame.y, (long)t->g.frame.width, (long)t->g.frame.height); } else { BroadcastPacket( M_DEICONIFY, 7, (long)FW_W(t), (long)FW_W_FRAME(t), (unsigned long)t, (long)icon_rect.x, (long)icon_rect.y, (long)icon_rect.width, (long)icon_rect.height); } XMapWindow(dpy, FW_W_PARENT(t)); if (t->Desk == Scr.CurrentDesk) { XMapWindow(dpy, FW_W_FRAME(t)); SET_MAP_PENDING(t, 1); } SetMapStateProp(t, NormalState); SET_ICONIFIED(t, 0); SET_ICON_UNMAPPED(t, 0); SET_ICON_ENTERED(t, 0); /* Need to make sure the border is colored correctly, * in case it was stuck or unstuck while iconified. */ tmp = Scr.Hilite; Scr.Hilite = t; border_draw_decorations( t, PART_ALL, (sf == t) ? True : False, True, CLEAR_ALL, NULL, NULL); Scr.Hilite = tmp; } } #if 1 RaiseWindow(fw, False); /* moved dje */ #endif if (sf == fw) { /* update the focus to make sure the application knows its * state */ if (!FP_DO_UNFOCUS_LEAVE(FW_FOCUS_POLICY(fw))) { SetFocusWindow(fw, True, FOCUS_SET_FORCE); } } else if (FP_DO_SORT_WINDOWLIST_BY(FW_FOCUS_POLICY(fw)) == FPOL_SORT_WL_BY_OPEN) { SetFocusWindow(fw, True, FOCUS_SET_FORCE); } focus_grab_buttons_on_layer(fw->layer); return; } /* * * Iconifies the selected window * */ void Iconify(FvwmWindow *fw, initial_window_options_t *win_opts) { FvwmWindow *t; FvwmWindow *sf; XWindowAttributes winattrs = {0}; unsigned long eventMask; rectangle icon_rect; if (!fw) { return; } if (!XGetWindowAttributes(dpy, FW_W(fw), &winattrs)) { return; } /* make sure fw->flags.is_map_pending is OK */ if ((winattrs.map_state == IsViewable) && IS_MAP_PENDING(fw)) { SET_MAP_PENDING(fw, 0); } if (IS_MAP_PENDING(fw)) { /* final state: iconified */ SET_ICONIFY_AFTER_MAP(fw, 1); return; } eventMask = winattrs.your_event_mask; mark_transient_subtree(fw, MARK_ALL_LAYERS, MARK_ALL, False, True); sf = get_focus_window(); if (sf && IS_IN_TRANSIENT_SUBTREE(sf)) { restore_focus_after_unmap(sf, True); /* restore_focus_after_unmap() destorys the flags set by * mark_transient_subtree(), so we have to unfortunately call * it again. */ mark_transient_subtree( fw, MARK_ALL_LAYERS, MARK_ALL, False, True); } /* iconify transients first */ for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) { if (t == fw || IS_IN_TRANSIENT_SUBTREE(t)) { SET_IN_TRANSIENT_SUBTREE(t, 0); SET_ICON_ENTERED(t, 0); /* Prevent the receipt of an UnmapNotify, since that * would cause a transition to the Withdrawn state. */ SET_MAPPED(t, 0); XSelectInput( dpy, FW_W(t), eventMask & ~StructureNotifyMask); XUnmapWindow(dpy, FW_W(t)); XSelectInput(dpy, FW_W(t), eventMask); XUnmapWindow(dpy, FW_W_FRAME(t)); border_undraw_decorations(t); t->DeIconifyDesk = t->Desk; if (FW_W_ICON_TITLE(t)) { XUnmapWindow(dpy, FW_W_ICON_TITLE(t)); } if (FW_W_ICON_PIXMAP(t)) { XUnmapWindow(dpy, FW_W_ICON_PIXMAP(t)); } SetMapStateProp(t, IconicState); border_draw_decorations( t, PART_ALL, False, False, CLEAR_ALL, NULL, NULL); if (t == fw && !IS_ICONIFIED_BY_PARENT(fw)) { SET_ICONIFY_PENDING(t, 1); } else { rectangle g; SET_ICONIFIED(t, 1); SET_ICON_UNMAPPED(t, 1); SET_ICONIFIED_BY_PARENT(t, 1); get_icon_geometry(t, &g); BroadcastPacket( M_ICONIFY, 7, (long)FW_W(t), (long)FW_W_FRAME(t), (unsigned long)t, (long)-32768, (long)-32768, (long)g.width, (long)g.height); BroadcastConfig(M_CONFIGURE_WINDOW,t); } } /* if */ } /* for */ /* necessary during a recapture */ if (IS_ICONIFIED_BY_PARENT(fw)) { return; } if (FW_W_ICON_TITLE(fw) == None || HAS_ICON_CHANGED(fw)) { if (IS_ICON_MOVED(fw) || win_opts->flags.use_initial_icon_xy) { rectangle g; get_icon_geometry(fw, &g); if (win_opts->flags.use_initial_icon_xy) { g.x = win_opts->initial_icon_x; g.y = win_opts->initial_icon_y; } CreateIconWindow(fw, g.x, g.y); } else { CreateIconWindow( fw, win_opts->default_icon_x, win_opts->default_icon_y); } SET_HAS_ICON_CHANGED(fw, 0); } else if (FW_W_ICON_TITLE(fw) && !FW_W_ICON_PIXMAP(fw)) { /* if no pixmap we want icon width to change to text width * every iconify; not necessary if the icon was created above */ setup_icon_title_size(fw); } /* this condition will be true unless we restore a window to * iconified state from a saved session. */ if (win_opts->initial_state != IconicState || (!IS_ICON_MOVED(fw) && !win_opts->flags.use_initial_icon_xy)) { AutoPlaceIcon(fw, win_opts, True); } /* domivogt (12-Mar-2003): Clean out the icon geometry if there is no * icon. Necessary to initialise the values and to suppress animation * if there is no icon. */ if (HAS_NO_ICON_TITLE(fw) && FW_W_ICON_PIXMAP(fw) == None) { clear_icon_dimensions(fw); } SET_ICONIFIED(fw, 1); SET_ICON_UNMAPPED(fw, 0); get_icon_geometry(fw, &icon_rect); /* if this fails it does not overwrite icon_rect */ EWMH_GetIconGeometry(fw, &icon_rect); BroadcastPacket( M_ICONIFY, 11, (long)FW_W(fw), (long)FW_W_FRAME(fw), (unsigned long)fw, (long)icon_rect.x, (long)icon_rect.y, (long)icon_rect.width, (long)icon_rect.height, /* next 4 added for Animate module */ (long)fw->g.frame.x, (long)fw->g.frame.y, (long)fw->g.frame.width, (long)fw->g.frame.height); BroadcastConfig(M_CONFIGURE_WINDOW,fw); if (win_opts->initial_state != IconicState || (!IS_ICON_MOVED(fw) && !win_opts->flags.use_initial_icon_xy)) { LowerWindow(fw, False); } if (IS_ICON_STICKY_ACROSS_DESKS(fw) || IS_STICKY_ACROSS_DESKS(fw)) { fw->Desk = Scr.CurrentDesk; } if (fw->Desk == Scr.CurrentDesk) { if (FW_W_ICON_TITLE(fw) != None) { XMapWindow(dpy, FW_W_ICON_TITLE(fw)); } if (FW_W_ICON_PIXMAP(fw) != None) { XMapWindow(dpy, FW_W_ICON_PIXMAP(fw)); } } focus_grab_buttons_on_layer(fw->layer); return; } /* * * This is used to tell applications which windows on the screen are * top level appication windows, and which windows are the icon windows * that go with them. * */ void SetMapStateProp(const FvwmWindow *fw, int state) { /* "suggested" by ICCCM version 1 */ unsigned long data[2]; data[0] = (unsigned long) state; data[1] = (unsigned long) FW_W_ICON_TITLE(fw); /* data[2] = (unsigned long) FW_W_ICON_PIXMAP(fw);*/ XChangeProperty( dpy, FW_W(fw), _XA_WM_STATE, _XA_WM_STATE, 32, PropModeReplace, (unsigned char *) data, 2); return; } void CMD_Iconify(F_CMD_ARGS) { int toggle; FvwmWindow * const fw = exc->w.fw; toggle = ParseToggleArgument(action, NULL, -1, 0); if (toggle == -1) { if (GetIntegerArguments(action, NULL, &toggle, 1) > 0) { if (toggle > 0) { toggle = 1; } else if (toggle < 0) { toggle = 0; } else { toggle = -1; } } } if (toggle == -1) { toggle = (IS_ICONIFIED(fw)) ? 0 : 1; } if (IS_ICONIFIED(fw)) { if (toggle == 0) { DeIconify(fw); EWMH_SetWMState(fw, False); } } else { if (toggle == 1) { initial_window_options_t win_opts; if ( !is_function_allowed( F_ICONIFY, NULL, fw, RQORIG_PROGRAM, True)) { XBell(dpy, 0); return; } memset(&win_opts, 0, sizeof(win_opts)); fev_get_evpos_or_query( dpy, Scr.Root, NULL, &win_opts.default_icon_x, &win_opts.default_icon_y); Iconify(fw, &win_opts); EWMH_SetWMState(fw, False); } } return; } fvwm-2.7.0/fvwm/menudim.c0000644000175000017500000000341214147024700012200 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include "menudim.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ /* ---------------------------- interface functions ------------------------ */ /* * functions dealing with coordinates */ int menudim_middle_x_offset(struct MenuDimensions *mdim) { return MDIM_ITEM_X_OFFSET(*mdim) + MDIM_ITEM_WIDTH(*mdim) / 2; } /* hallo */ fvwm-2.7.0/fvwm/colorset.h0000644000175000017500000000143214147024700012401 00000000000000/* -*-c-*- */ #ifndef COLORSET_H #define COLORSET_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ void parse_colorset(int n, char *line); void cleanup_colorsets(void); void alloc_colorset(int n); void update_root_transparent_colorset(Atom prop); #endif /* COLORSET_H */ fvwm-2.7.0/fvwm/condrc.h0000644000175000017500000000153314147024676012035 00000000000000/* -*-c-*- */ #ifndef CONDRC_H #define CONDRC_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ typedef enum { COND_RC_BREAK = -2, COND_RC_ERROR = -1, COND_RC_NO_MATCH = 0, COND_RC_OK = 1 } cond_rc_enum; typedef struct { cond_rc_enum rc; int break_levels; } cond_rc_t; /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ void condrc_init(cond_rc_t *cond_rc); #endif /* CONDRC_H */ fvwm-2.7.0/fvwm/cursor.c0000644000175000017500000002612314147024700012063 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include "libs/fvwmlib.h" #include "libs/ColorUtils.h" #include "libs/Cursor.h" #include "libs/Parse.h" #include "libs/Strings.h" #include "fvwm.h" #include "libs/PictureImageLoader.h" #include "externs.h" #include "cursor.h" #include "functions.h" #include "bindings.h" #include "misc.h" #include "screen.h" #include "cursor.h" #include "menus.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ static Cursor cursors[CRS_MAX]; static const unsigned int default_cursors[CRS_MAX] = { None, XC_top_left_corner, /* CRS_POSITION */ XC_top_left_arrow, /* CRS_TITLE */ XC_top_left_arrow, /* CRS_DEFAULT */ XC_hand2, /* CRS_SYS */ XC_fleur, /* CRS_MOVE */ XC_sizing, /* CRS_RESIZE */ XC_watch, /* CRS_WAIT */ XC_top_left_arrow, /* CRS_MENU */ XC_crosshair, /* CRS_SELECT */ XC_pirate, /* CRS_DESTROY */ XC_top_side, /* CRS_TOP */ XC_right_side, /* CRS_RIGHT */ XC_bottom_side, /* CRS_BOTTOM */ XC_left_side, /* CRS_LEFT */ XC_top_left_corner, /* CRS_TOP_LEFT */ XC_top_right_corner, /* CRS_TOP_RIGHT */ XC_bottom_left_corner, /* CRS_BOTTOM_LEFT */ XC_bottom_right_corner, /* CRS_BOTTOM_RIGHT */ XC_top_side, /* CRS_TOP_EDGE */ XC_right_side, /* CRS_RIGHT_EDGE */ XC_bottom_side, /* CRS_BOTTOM_EDGE */ XC_left_side, /* CRS_LEFT_EDGE */ XC_left_ptr, /* CRS_ROOT */ XC_plus /* CRS_STROKE */ }; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ static void SafeDefineCursor(Window w, Cursor cursor) { if (w) { XDefineCursor(dpy,w,cursor); } return; } /* ---------------------------- interface functions ------------------------ */ /* CreateCursors - Loads fvwm cursors */ Cursor *CreateCursors(Display *dpy) { int i; /* define cursors */ cursors[0] = None; for (i = 1; i < CRS_MAX; i++) { cursors[i] = XCreateFontCursor(dpy, default_cursors[i]); } return cursors; } /* ---------------------------- builtin commands --------------------------- */ void CMD_CursorStyle(F_CMD_ARGS) { char *cname=NULL; char *newcursor=NULL; char *errpos = NULL; char *fore = NULL; char *back = NULL; XColor colors[2]; int index; int nc; int i; int my_nc; FvwmWindow *fw2; Cursor cursor; cursor = 0; cname = PeekToken(action, &action); if (!cname) { fvwm_msg(ERR, "CursorStyle", "Bad cursor style"); return; } if (StrEquals("POSITION", cname)) { index = CRS_POSITION; } else if (StrEquals("DEFAULT", cname)) { index = CRS_DEFAULT; } else if (StrEquals("SYS", cname)) { index = CRS_SYS; } else if (StrEquals("TITLE", cname)) { index = CRS_TITLE; } else if (StrEquals("MOVE", cname)) { index = CRS_MOVE; } else if (StrEquals("RESIZE", cname)) { index = CRS_RESIZE; } else if (StrEquals("MENU", cname)) { index = CRS_MENU; } else if (StrEquals("WAIT", cname)) { index = CRS_WAIT; } else if (StrEquals("SELECT", cname)) { index = CRS_SELECT; } else if (StrEquals("DESTROY", cname)) { index = CRS_DESTROY; } else if (StrEquals("LEFT", cname)) { index = CRS_LEFT; } else if (StrEquals("RIGHT", cname)) { index = CRS_RIGHT; } else if (StrEquals("TOP", cname)) { index = CRS_TOP; } else if (StrEquals("BOTTOM", cname)) { index = CRS_BOTTOM; } else if (StrEquals("TOP_LEFT", cname)) { index = CRS_TOP_LEFT; } else if (StrEquals("TOP_RIGHT", cname)) { index = CRS_TOP_RIGHT; } else if (StrEquals("BOTTOM_LEFT", cname)) { index = CRS_BOTTOM_LEFT; } else if (StrEquals("BOTTOM_RIGHT", cname)) { index = CRS_BOTTOM_RIGHT; } else if (StrEquals("LEFT_EDGE", cname)) { index = CRS_LEFT_EDGE; } else if (StrEquals("RIGHT_EDGE", cname)) { index = CRS_RIGHT_EDGE; } else if (StrEquals("TOP_EDGE", cname)) { index = CRS_TOP_EDGE; } else if (StrEquals("BOTTOM_EDGE", cname)) { index = CRS_BOTTOM_EDGE; } else if (StrEquals("ROOT", cname)) { index = CRS_ROOT; } else if (StrEquals("STROKE", cname)) { index = CRS_STROKE; } else { fvwm_msg(ERR, "CursorStyle", "Unknown cursor name %s", cname); return; } cname = 0; /* check if the cursor is given by X11 name */ action = GetNextToken(action, &newcursor); if (newcursor) { my_nc = fvwmCursorNameToIndex(newcursor); } else { my_nc = default_cursors[index]; } if (my_nc == -1) { nc = strtol(newcursor, &errpos, 10); if (errpos && *errpos == '\0') { my_nc = 0; } } else { nc = my_nc; } if (my_nc > -1) { /* newcursor was a number or the name of a X11 cursor */ if ((nc < 0) || (nc >= XC_num_glyphs) || ((nc % 2) != 0)) { fvwm_msg( ERR, "CursorStyle", "Bad cursor number %s", newcursor); free(newcursor); return; } cursor = XCreateFontCursor(dpy, nc); } else { /* newcursor was not a number neither a X11 cursor name */ if ( StrEquals("none", newcursor) || StrEquals("tiny", newcursor)) { XColor nccol; XSetForeground( dpy, Scr.MonoGC, (tolower(*newcursor) == 'n') ? 0 : 1); XFillRectangle( dpy, Scr.ScratchMonoPixmap, Scr.MonoGC, 0, 0, 1, 1); cursor = XCreatePixmapCursor( dpy, Scr.ScratchMonoPixmap, Scr.ScratchMonoPixmap, &nccol, &nccol, 0, 0); } else { char *path; char *tmp; int hotspot[2]; hotspot[0] = -1; hotspot[1] = -1; path = PictureFindImageFile(newcursor, NULL, R_OK); if (!path) { fvwm_msg( ERR, "CursorStyle", "Cursor %s not found", newcursor); free(newcursor); return; } if (GetIntegerArguments(action, &tmp, hotspot, 2) == 2) { action = tmp; } cursor = PImageLoadCursorFromFile( dpy, Scr.Root, path, hotspot[0], hotspot[1]); free(path); } } if (!cursor) { fvwm_msg( ERR, "CursorStyle", "Cannot load cursor: %s", newcursor); free(newcursor); return; } free(newcursor); newcursor = 0; /* replace the cursor defn */ if (Scr.FvwmCursors[index]) { XFreeCursor(dpy, Scr.FvwmCursors[index]); } Scr.FvwmCursors[index] = cursor; /* look for optional color arguments */ action = GetNextToken(action, &fore); action = GetNextToken(action, &back); if (fore && back) { colors[0].pixel = GetColor(fore); colors[1].pixel = GetColor(back); XQueryColors (dpy, Pcmap, colors, 2); XRecolorCursor( dpy, Scr.FvwmCursors[index], &(colors[0]), &(colors[1])); } if (fore) { free(fore); } if (back) { free(back); } /* redefine all the windows using cursors */ for (fw2 = Scr.FvwmRoot.next; fw2; fw2 = fw2->next) { if (!HAS_HANDLES(fw2)) { /* Ignore windows without handles */ continue; } for (i = 0; i < 4; i++) { SafeDefineCursor( FW_W_CORNER(fw2, i), Scr.FvwmCursors[CRS_TOP_LEFT + i]); SafeDefineCursor( FW_W_SIDE(fw2, i), Scr.FvwmCursors[CRS_TOP + i]); } for (i = 0; i / 2 < Scr.nr_left_buttons; i += 2) { SafeDefineCursor( FW_W_BUTTON(fw2, i), Scr.FvwmCursors[CRS_SYS]); } for (i = 1; i / 2 < Scr.nr_right_buttons; i += 2) { SafeDefineCursor( FW_W_BUTTON(fw2, i), Scr.FvwmCursors[CRS_SYS]); } SafeDefineCursor(FW_W_TITLE(fw2), Scr.FvwmCursors[CRS_TITLE]); if (index == CRS_DEFAULT) { SafeDefineCursor( FW_W_FRAME(fw2), Scr.FvwmCursors[CRS_DEFAULT]); SafeDefineCursor( FW_W_PARENT(fw2), Scr.FvwmCursors[CRS_DEFAULT]); if (IS_ICONIFIED(fw2)) { if (!HAS_NO_ICON_TITLE(fw2)) { SafeDefineCursor( FW_W_ICON_TITLE(fw2), Scr.FvwmCursors[CRS_DEFAULT]); } if (FW_W_ICON_PIXMAP(fw2) != None) { SafeDefineCursor( FW_W_ICON_PIXMAP(fw2), Scr.FvwmCursors[CRS_DEFAULT]); } } } } /* Do the menus for good measure */ SetMenuCursor(Scr.FvwmCursors[CRS_MENU]); SafeDefineCursor(Scr.PanFrameTop.win, Scr.FvwmCursors[CRS_TOP_EDGE]); SafeDefineCursor( Scr.PanFrameBottom.win, Scr.FvwmCursors[CRS_BOTTOM_EDGE]); SafeDefineCursor(Scr.PanFrameLeft.win, Scr.FvwmCursors[CRS_LEFT_EDGE]); SafeDefineCursor( Scr.PanFrameRight.win, Scr.FvwmCursors[CRS_RIGHT_EDGE]); /* migo (04/Nov/1999): don't annoy users which use xsetroot */ if (index == CRS_ROOT) { SafeDefineCursor(Scr.Root, Scr.FvwmCursors[CRS_ROOT]); } return; } /* Defines in which cases fvwm "grab" the cursor during execution of certain * functions. */ void CMD_BusyCursor(F_CMD_ARGS) { char *option = NULL; char *optstring = NULL; char *args = NULL; int flag = -1; char *optlist[] = { "read", "wait", "modulesynchronous", "dynamicmenu", "*", NULL }; while (action && *action != '\0') { action = GetQuotedString( action, &optstring, ",", NULL, NULL, NULL); if (!optstring) { break; } args = GetNextToken(optstring, &option); if (!option) { free(optstring); break; } flag = ParseToggleArgument(args, NULL, -1, True); free(optstring); if (flag == -1) { fvwm_msg(ERR, "BusyCursor", "error in boolean specification"); free(option); break; } switch (GetTokenIndex(option, optlist, 0, NULL)) { case 0: /* read */ if (flag) { Scr.BusyCursor |= BUSY_READ; } else { Scr.BusyCursor &= ~BUSY_READ; } break; case 1: /* wait */ if (flag) { Scr.BusyCursor |= BUSY_WAIT; } else { Scr.BusyCursor &= ~BUSY_WAIT; } break; case 2: /* modulesynchronous */ if (flag) { Scr.BusyCursor |= BUSY_MODULESYNCHRONOUS; } else { Scr.BusyCursor &= ~BUSY_MODULESYNCHRONOUS; } break; case 3: /* dynamicmenu */ if (flag) { Scr.BusyCursor |= BUSY_DYNAMICMENU; } else { Scr.BusyCursor &= ~BUSY_DYNAMICMENU; } break; case 4: /* "*" */ if (flag) { Scr.BusyCursor |= BUSY_ALL; } else { Scr.BusyCursor &= ~(BUSY_ALL); } break; default: fvwm_msg(ERR, "BusyCursor", "unknown context '%s'", option); break; } free(option); } return; } fvwm-2.7.0/fvwm/commands.h0000644000175000017500000002267214147024700012361 00000000000000/* -*-c-*- */ #ifndef COMMANDS_H #define COMMANDS_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ enum { F_UNDEFINED = -1, /* functions that need no window */ F_NOP = 0, F_ADDFUNC, F_ADDMENU, F_ADDMENU2, F_ALL, F_ANY, F_BEEP, F_BREAK, F_BUG_OPTS, F_BUSY_CURSOR, F_BUTTON_STATE, F_BUTTON_STYLE, F_CHANGE_MENUSTYLE, F_CIRCULATE_DOWN, F_CIRCULATE_UP, F_CLICK, F_CLOSE, F_COLORMAP_FOCUS, F_COND, F_CONDCASE, F_CONFIG_LIST, F_COPY_MENU_STYLE, F_CURRENT, F_CURSOR_STYLE, F_DESCHEDULE, F_DESKTOP_NAME, F_DESTROY_FUNCTION, F_DESTROY_MENU, F_DESTROY_MENUSTYLE, F_DESTROY_STYLE, F_DFLT_COLORS, F_DFLT_COLORSET, F_DFLT_FONT, F_DFLT_ICON, F_DFLT_LAYERS, F_DIRECTION, F_EDGE_COMMAND, F_EDGE_LEAVE_COMMAND, F_EDGE_RES, F_EDGE_SCROLL, F_EMULATE, F_ESCAPE_FUNC, F_EWMH_BASE_STRUTS, F_EWMH_NUMBER_OF_DESKTOPS, F_EXEC, F_EXEC_SETUP, F_FAKE_CLICK, F_FAKE_KEYPRESS, F_FOCUSSTYLE, F_FUNCTION, F_GLOBAL_OPTS, F_GOTO_DESK, F_GOTO_PAGE, F_HICOLOR, F_HICOLORSET, F_HIDEGEOMWINDOW, F_ICONFONT, F_ICON_PATH, F_IGNORE_MODIFIERS, F_IMAGE_PATH, F_INFOSTOREADD, F_INFOSTOREREMOVE, F_INFOSTORECLEAR, F_KEEPRC, F_KEY, F_KILL_MODULE, F_LAYER, F_LOCALE_PATH, F_MENUSTYLE, F_MODULE, F_MODULE_LISTEN_ONLY, F_MODULE_PATH, F_MODULE_SYNC, F_MOUSE, F_MOVECURSOR, F_MOVE_TO_DESK, F_NEXT, F_NONE, F_OPAQUE, F_PICK, F_PIXMAP_PATH, F_POINTERKEY, F_POINTERWINDOW, F_POPUP, F_PREV, F_PRINTINFO, F_QUIT, F_QUIT_SESSION, F_QUIT_SCREEN, F_READ, F_RECAPTURE, F_RECAPTURE_WINDOW, F_REFRESH, F_REPEAT, F_RESTART, F_SAVE_SESSION, F_SAVE_QUIT_SESSION, F_SCANFORWINDOW, F_SCHEDULE, F_SCROLL, F_SETDESK, F_SETENV, F_SET_ANIMATION, F_SET_MASK, F_SET_NOGRAB_MASK, F_SET_SYNC_MASK, F_SHADE_ANIMATE, F_SILENT, F_SNAP_ATT, F_SNAP_GRID, F_STAYSUP, STROKE_ARG(F_STROKE) STROKE_ARG(F_STROKE_FUNC) F_STYLE, F_TEARMENUOFF, F_TEST_, F_TESTRC, F_THISWINDOW, F_TITLE, F_TITLESTYLE, F_TOGGLE_PAGE, F_UPDATE_STYLES, F_WAIT, F_WINDOWFONT, F_WINDOWLIST, F_XINERAMA, F_XINERAMAPRIMARYSCREEN, F_XINERAMASLS, F_XINERAMASLSSCREENS, F_XINERAMASLSSIZE, F_XOR, F_XSYNC, F_XSYNCHRONIZE, /* functions that need a window to operate on */ F_ADD_BUTTON_STYLE, F_ADD_DECOR, F_ADD_TITLE_STYLE, F_ANIMATED_MOVE, F_BORDERSTYLE, F_CHANGE_DECOR, F_COLOR_LIMIT, F_DELETE, F_DESTROY, F_DESTROY_DECOR, F_DESTROY_MOD, F_DESTROY_WINDOW_STYLE, F_ECHO, F_ECHO_FUNC_DEFINITION, F_FLIP_FOCUS, F_FOCUS, F_ICONIFY, F_LOWER, F_MAXIMIZE, F_MOVE, F_MOVE_THRESHOLD, F_MOVE_TO_PAGE, F_MOVE_TO_SCREEN, F_PLACEAGAIN, F_RAISE, F_RAISELOWER, F_RESIZE, F_RESIZE_MAXIMIZE, F_RESIZEMOVE, F_RESIZEMOVE_MAXIMIZE, F_RESTACKTRANSIENTS, F_SEND_STRING, F_STATE, F_STICK, F_STICKACROSSDESKS, F_STICKACROSSPAGES, F_UPDATE_DECOR, F_WARP, F_WINDOWID, F_WINDOW_SHADE, F_WINDOW_STYLE, F_END_OF_LIST = 999, /* Functions for use by modules only! */ F_SEND_WINDOW_LIST = 1000, F_SEND_REPLY }; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ /* This file contains all command prototypes. */ void CMD_Plus(F_CMD_ARGS); void CMD_AddButtonStyle(F_CMD_ARGS); void CMD_AddTitleStyle(F_CMD_ARGS); void CMD_AddToDecor(F_CMD_ARGS); void CMD_AddToFunc(F_CMD_ARGS); void CMD_AddToMenu(F_CMD_ARGS); void CMD_Alias(F_CMD_ARGS); void CMD_All(F_CMD_ARGS); void CMD_AnimatedMove(F_CMD_ARGS); void CMD_Any(F_CMD_ARGS); void CMD_Beep(F_CMD_ARGS); void CMD_Break(F_CMD_ARGS); void CMD_BorderStyle(F_CMD_ARGS); void CMD_BugOpts(F_CMD_ARGS); void CMD_BusyCursor(F_CMD_ARGS); void CMD_ButtonState(F_CMD_ARGS); void CMD_ButtonStyle(F_CMD_ARGS); void CMD_ChangeDecor(F_CMD_ARGS); void CMD_ChangeMenuStyle(F_CMD_ARGS); void CMD_CleanupColorsets(F_CMD_ARGS); void CMD_ClickTime(F_CMD_ARGS); void CMD_Close(F_CMD_ARGS); void CMD_ColorLimit(F_CMD_ARGS); void CMD_ColormapFocus(F_CMD_ARGS); void CMD_Colorset(F_CMD_ARGS); void CMD_CopyMenuStyle(F_CMD_ARGS); void CMD_Current(F_CMD_ARGS); void CMD_CursorMove(F_CMD_ARGS); void CMD_CursorStyle(F_CMD_ARGS); void CMD_DefaultColors(F_CMD_ARGS); void CMD_DefaultColorset(F_CMD_ARGS); void CMD_DefaultFont(F_CMD_ARGS); void CMD_DefaultIcon(F_CMD_ARGS); void CMD_DefaultLayers(F_CMD_ARGS); void CMD_Delete(F_CMD_ARGS); void CMD_Deschedule(F_CMD_ARGS); void CMD_Desk(F_CMD_ARGS); void CMD_DesktopName(F_CMD_ARGS); void CMD_DesktopSize(F_CMD_ARGS); void CMD_Destroy(F_CMD_ARGS); void CMD_DestroyDecor(F_CMD_ARGS); void CMD_DestroyFunc(F_CMD_ARGS); void CMD_DestroyMenu(F_CMD_ARGS); void CMD_DestroyMenuStyle(F_CMD_ARGS); void CMD_DestroyModuleConfig(F_CMD_ARGS); void CMD_DestroyStyle(F_CMD_ARGS); void CMD_DestroyWindowStyle(F_CMD_ARGS); void CMD_Direction(F_CMD_ARGS); void CMD_Echo(F_CMD_ARGS); void CMD_EchoFuncDefinition(F_CMD_ARGS); void CMD_EdgeCommand(F_CMD_ARGS); void CMD_EdgeLeaveCommand(F_CMD_ARGS); void CMD_EdgeResistance(F_CMD_ARGS); void CMD_EdgeScroll(F_CMD_ARGS); void CMD_EdgeThickness(F_CMD_ARGS); void CMD_Emulate(F_CMD_ARGS); void CMD_EscapeFunc(F_CMD_ARGS); void CMD_EwmhBaseStruts(F_CMD_ARGS); void CMD_EwmhNumberOfDesktops(F_CMD_ARGS); void CMD_Exec(F_CMD_ARGS); void CMD_ExecUseShell(F_CMD_ARGS); void CMD_FakeClick(F_CMD_ARGS); void CMD_FakeKeypress(F_CMD_ARGS); void CMD_FlipFocus(F_CMD_ARGS); void CMD_Focus(F_CMD_ARGS); void CMD_FocusStyle(F_CMD_ARGS); void CMD_Function(F_CMD_ARGS); void CMD_GlobalOpts(F_CMD_ARGS); void CMD_GotoDesk(F_CMD_ARGS); void CMD_GotoDeskAndPage(F_CMD_ARGS); void CMD_GotoPage(F_CMD_ARGS); void CMD_HideGeometryWindow(F_CMD_ARGS); void CMD_HilightColor(F_CMD_ARGS); void CMD_HilightColorset(F_CMD_ARGS); void CMD_IconFont(F_CMD_ARGS); void CMD_Iconify(F_CMD_ARGS); void CMD_IconPath(F_CMD_ARGS); void CMD_IgnoreModifiers(F_CMD_ARGS); void CMD_ImagePath(F_CMD_ARGS); void CMD_InfoStoreAdd(F_CMD_ARGS); void CMD_InfoStoreClear(F_CMD_ARGS); void CMD_InfoStoreRemove(F_CMD_ARGS); void CMD_KeepRc(F_CMD_ARGS); void CMD_Key(F_CMD_ARGS); void CMD_KillModule(F_CMD_ARGS); void CMD_Layer(F_CMD_ARGS); void CMD_LocalePath(F_CMD_ARGS); void CMD_Lower(F_CMD_ARGS); void CMD_Maximize(F_CMD_ARGS); void CMD_Menu(F_CMD_ARGS); void CMD_MenuStyle(F_CMD_ARGS); void CMD_Module(F_CMD_ARGS); void CMD_ModuleListenOnly(F_CMD_ARGS); void CMD_ModulePath(F_CMD_ARGS); void CMD_ModuleSynchronous(F_CMD_ARGS); void CMD_ModuleTimeout(F_CMD_ARGS); void CMD_Mouse(F_CMD_ARGS); void CMD_Move(F_CMD_ARGS); void CMD_MoveThreshold(F_CMD_ARGS); void CMD_MoveToDesk(F_CMD_ARGS); void CMD_MoveToPage(F_CMD_ARGS); void CMD_MoveToScreen(F_CMD_ARGS); void CMD_Next(F_CMD_ARGS); void CMD_None(F_CMD_ARGS); void CMD_Nop(F_CMD_ARGS); void CMD_NoWindow(F_CMD_ARGS); void CMD_OpaqueMoveSize(F_CMD_ARGS); void CMD_Pick(F_CMD_ARGS); void CMD_PipeRead(F_CMD_ARGS); void CMD_PixmapPath(F_CMD_ARGS); void CMD_PlaceAgain(F_CMD_ARGS); void CMD_PointerKey(F_CMD_ARGS); void CMD_PointerWindow(F_CMD_ARGS); void CMD_Popup(F_CMD_ARGS); void CMD_Prev(F_CMD_ARGS); void CMD_PrintInfo(F_CMD_ARGS); void CMD_PropertyChange(F_CMD_ARGS); void CMD_Quit(F_CMD_ARGS); void CMD_QuitScreen(F_CMD_ARGS); void CMD_QuitSession(F_CMD_ARGS); void CMD_Raise(F_CMD_ARGS); void CMD_RaiseLower(F_CMD_ARGS); void CMD_Read(F_CMD_ARGS); void CMD_ReadWriteColors(F_CMD_ARGS); void CMD_Recapture(F_CMD_ARGS); void CMD_RecaptureWindow(F_CMD_ARGS); void CMD_Refresh(F_CMD_ARGS); void CMD_RefreshWindow(F_CMD_ARGS); void CMD_Repeat(F_CMD_ARGS); void CMD_Resize(F_CMD_ARGS); void CMD_ResizeMaximize(F_CMD_ARGS); void CMD_ResizeMove(F_CMD_ARGS); void CMD_ResizeMoveMaximize(F_CMD_ARGS); void CMD_RestackTransients(F_CMD_ARGS); void CMD_Restart(F_CMD_ARGS); void CMD_SaveQuitSession(F_CMD_ARGS); void CMD_SaveSession(F_CMD_ARGS); void CMD_ScanForWindow(F_CMD_ARGS); void CMD_Schedule(F_CMD_ARGS); void CMD_Scroll(F_CMD_ARGS); void CMD_Send_ConfigInfo(F_CMD_ARGS); void CMD_Send_Reply(F_CMD_ARGS); void CMD_Send_WindowList(F_CMD_ARGS); void CMD_SendToModule(F_CMD_ARGS); void CMD_set_mask(F_CMD_ARGS); void CMD_set_nograb_mask(F_CMD_ARGS); void CMD_set_sync_mask(F_CMD_ARGS); void CMD_SetAnimation(F_CMD_ARGS); void CMD_SetEnv(F_CMD_ARGS); void CMD_Silent(F_CMD_ARGS); void CMD_SnapAttraction(F_CMD_ARGS); void CMD_SnapGrid(F_CMD_ARGS); void CMD_State(F_CMD_ARGS); void CMD_Stick(F_CMD_ARGS); void CMD_StickAcrossDesks(F_CMD_ARGS); void CMD_StickAcrossPages(F_CMD_ARGS); #ifdef HAVE_STROKE void CMD_Stroke(F_CMD_ARGS); void CMD_StrokeFunc(F_CMD_ARGS); #endif /* HAVE_STROKE */ void CMD_Style(F_CMD_ARGS); void CMD_TearMenuOff(F_CMD_ARGS); void CMD_Test(F_CMD_ARGS); void CMD_TestRc(F_CMD_ARGS); void CMD_ThisWindow(F_CMD_ARGS); void CMD_Title(F_CMD_ARGS); void CMD_TitleStyle(F_CMD_ARGS); void CMD_Unalias(F_CMD_ARGS); void CMD_UnsetEnv(F_CMD_ARGS); void CMD_UpdateDecor(F_CMD_ARGS); void CMD_UpdateStyles(F_CMD_ARGS); void CMD_Wait(F_CMD_ARGS); void CMD_WarpToWindow(F_CMD_ARGS); void CMD_WindowFont(F_CMD_ARGS); void CMD_WindowId(F_CMD_ARGS); void CMD_WindowList(F_CMD_ARGS); void CMD_WindowShade(F_CMD_ARGS); void CMD_WindowShadeAnimate(F_CMD_ARGS); void CMD_WindowStyle(F_CMD_ARGS); void CMD_Xinerama(F_CMD_ARGS); void CMD_XineramaPrimaryScreen(F_CMD_ARGS); void CMD_XineramaSls(F_CMD_ARGS); void CMD_XineramaSlsScreens(F_CMD_ARGS); void CMD_XineramaSlsSize(F_CMD_ARGS); void CMD_XorPixmap(F_CMD_ARGS); void CMD_XorValue(F_CMD_ARGS); void CMD_XSync(F_CMD_ARGS); void CMD_XSynchronize(F_CMD_ARGS); #endif /* COMMANDS_H */ fvwm-2.7.0/fvwm/add_window.h0000644000175000017500000000541114147024700012667 00000000000000/* -*-c-*- */ #ifndef ADD_WINDOW_H #define ADD_WINDOW_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ #define AW_NO_WINDOW NULL #define AW_UNMANAGED ((void *)1) /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ int setup_visible_names(FvwmWindow *fw, int what_changed); void update_window_names(FvwmWindow *fw, int which); void setup_wm_hints(FvwmWindow *fw); void setup_snapping(FvwmWindow *fw, window_style *pstyle); void setup_placement_penalty(FvwmWindow *fw, window_style *pstyle); void setup_focus_policy(FvwmWindow *fw); Bool setup_transientfor(FvwmWindow *fw); void setup_icon_size_limits(FvwmWindow *fw, window_style *pstyle); void setup_icon_background_parameters(FvwmWindow *fw, window_style *pstyle); void setup_icon_title_parameters(FvwmWindow *fw, window_style *pstyle); void setup_numeric_vals(FvwmWindow *fw, window_style *pstyle); Bool validate_transientfor(FvwmWindow *fw); void setup_title_geometry( FvwmWindow *fw, window_style *pstyle); void setup_window_font( FvwmWindow *fw, window_style *pstyle, Bool do_destroy); void setup_icon_font( FvwmWindow *fw, window_style *pstyle, Bool do_destroy); void setup_style_and_decor( FvwmWindow *fw, window_style *pstyle, short *buttons); void setup_frame_attributes( FvwmWindow *fw, window_style *pstyle); void change_auxiliary_windows( FvwmWindow *fw, short buttons); void setup_frame_geometry( FvwmWindow *fw); void setup_frame_size_limits( FvwmWindow *fw, window_style *pstyle); void increase_icon_hint_count( FvwmWindow *fw); void change_icon( FvwmWindow *fw, window_style *pstyle); void change_mini_icon( FvwmWindow *fw, window_style *pstyle); void change_icon_boxes( FvwmWindow *fw, window_style *pstyle); void FetchWmProtocols( FvwmWindow *); FvwmWindow *AddWindow( const char **ret_initial_map_command, const exec_context_t *exc, FvwmWindow *ReuseWin, initial_window_options_t * win_opts); void GetWindowSizeHints( FvwmWindow *fw); void GetWindowSizeHintsWithCheck( FvwmWindow *fw, int do_reject_invalid_size_constrains_on_existing_window); void free_window_names( FvwmWindow *tmp, Bool nukename, Bool nukeicon); void destroy_window( FvwmWindow *); void RestoreWithdrawnLocation( FvwmWindow *tmp, Bool is_restart_or_recapture, Window parent); void Reborder(void); void CaptureAllWindows(const exec_context_t *exc, Bool is_recapture); #endif /* ADD_WINDOW_H */ fvwm-2.7.0/fvwm/infostore.h0000644000175000017500000000166114147024700012563 00000000000000/* -*-c-*- */ #ifndef INFOSTORE_H #define INFOSTORE_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ typedef struct MetaInfo { char *key; char *value; struct MetaInfo *next; } MetaInfo; /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ MetaInfo *new_metainfo(void); void insert_metainfo(char *, char *); char *get_metainfo_value(const char *); int get_metainfo_length(void); MetaInfo *get_metainfo(void); void print_infostore(void); #endif /* INFOSTORE_H */ fvwm-2.7.0/fvwm/window_flags.h0000644000175000017500000007344214147024700013244 00000000000000/* -*-c-*- */ #ifndef _WINDOW_FLAGS_ #define _WINDOW_FLAGS_ #include "focus_policy.h" /* access to the common flags of a window */ #define FW_COMMON_FLAGS(fw) \ ((fw)->flags.common) #define FW_COMMON_STATIC_FLAGS(fw) \ ((fw)->flags.common.s) #define FW_FOCUS_POLICY(fw) \ ((fw)->flags.common.s.focus_policy) #define DO_LOWER_TRANSIENT(fw) \ ((fw)->flags.common.s.do_lower_transient) #define DO_NOT_SHOW_ON_MAP(fw) \ ((fw)->flags.common.s.do_not_show_on_map) #define DO_RAISE_TRANSIENT(fw) \ ((fw)->flags.common.s.do_raise_transient) #define DO_RESIZE_OPAQUE(fw) \ ((fw)->flags.common.s.do_resize_opaque) #define DO_SHRINK_WINDOWSHADE(fw) \ ((fw)->flags.common.s.do_shrink_windowshade) #define SET_DO_SHRINK_WINDOWSHADE(fw,x) \ (fw)->flags.common.s.do_shrink_windowshade = !!(x) #define SETM_DO_SHRINK_WINDOWSHADE(fw,x) \ (fw)->flag_mask.common.s.do_shrink_windowshade = !!(x) #define DO_SKIP_CIRCULATE(fw) \ ((fw)->flags.common.s.do_circulate_skip) #define SET_DO_SKIP_CIRCULATE(fw,x) \ (fw)->flags.common.s.do_circulate_skip = !!(x) #define SETM_DO_SKIP_CIRCULATE(fw,x) \ (fw)->flag_mask.common.s.do_circulate_skip = !!(x) #define DO_SKIP_ICON_CIRCULATE(fw) \ ((fw)->flags.common.s.do_circulate_skip_icon) #define SET_DO_SKIP_ICON_CIRCULATE(fw,x) \ (fw)->flags.common.s.do_circulate_skip_icon = !!(x) #define SETM_DO_SKIP_ICON_CIRCULATE(fw,x) \ (fw)->flag_mask.common.s.do_circulate_skip_icon = !!(x) #define DO_SKIP_SHADED_CIRCULATE(fw) \ ((fw)->flags.common.s.do_circulate_skip_shaded) #define SET_DO_SKIP_SHADED_CIRCULATE(fw,x) \ (fw)->flags.common.s.do_circulate_skip_shaded = !!(x) #define SETM_DO_SKIP_SHADED_CIRCULATE(fw,x) \ (fw)->flag_mask.common.s.do_circulate_skip_shaded = !!(x) #define DO_SKIP_WINDOW_LIST(fw) \ ((fw)->flags.common.s.do_window_list_skip) #define SET_DO_SKIP_WINDOW_LIST(fw,x) \ (fw)->flags.common.s.do_window_list_skip = !!(x) #define SETM_DO_SKIP_WINDOW_LIST(fw,x) \ (fw)->flag_mask.common.s.do_window_list_skip = !!(x) #define DO_STACK_TRANSIENT_PARENT(fw) \ ((fw)->flags.common.s.do_stack_transient_parent) #define GET_TITLE_DIR(fw) \ ((fw)->flags.common.title_dir) #define HAS_TITLE_DIR(fw,x) \ ((fw)->flags.common.title_dir == x) #define SET_TITLE_DIR(fw,x) \ ((fw)->flags.common.title_dir = x) #define SETM_TITLE_DIR(fw,x) \ ((fw)->flag_mask.common.title_dir = ((x) ? DIR_MAJOR_MASK : 0)) #define SET_USER_STATES(fw, mask) \ ((fw)->flags.common.user_states |= (mask)) #define CLEAR_USER_STATES(fw, mask) \ ((fw)->flags.common.user_states &= ~(mask)) #define TOGGLE_USER_STATES(fw, mask) \ ((fw)->flags.common.user_states ^= (mask)) #define SETM_USER_STATES(fw, mask) \ ((fw)->flag_mask.common.user_states |= (mask)) #define GET_USER_STATES(fw) \ ((fw)->flags.common.user_states) #define GETM_USER_STATES(fw) \ ((fw)->flag_mask.common.user_states) #define HAS_VERTICAL_TITLE(fw) \ ((HAS_TITLE_DIR(fw,DIR_W) || HAS_TITLE_DIR(fw,DIR_E))) #define HAS_STIPPLED_TITLE(fw) \ ((fw)->flags.common.s.has_stippled_title) #define SET_HAS_STIPPLED_TITLE(fw,x) \ (fw)->flags.common.s.has_stippled_title = !!(x) #define SETM_HAS_STIPPLED_TITLE(fw,x) \ (fw)->flag_mask.common.s.has_stippled_title = !!(x) #define HAS_STICKY_STIPPLED_TITLE(fw) \ !((fw)->flags.common.s.has_no_sticky_stippled_title) #define SET_HAS_STICKY_STIPPLED_TITLE(fw,x) \ (fw)->flags.common.s.has_no_sticky_stippled_title = !(x) #define SETM_HAS_STICKY_STIPPLED_TITLE(fw,x) \ (fw)->flag_mask.common.s.has_no_sticky_stippled_title = !!(x) #define HAS_STICKY_STIPPLED_ICON_TITLE(fw) \ !((fw)->flags.common.s.has_no_sticky_stippled_icon_title) #define SET_HAS_STICKY_STIPPLED_ICON_TITLE(fw,x) \ (fw)->flags.common.s.has_no_sticky_stippled_icon_title = !(x) #define SETM_HAS_STICKY_STIPPLED_ICON_TITLE(fw,x) \ (fw)->flag_mask.common.s.has_no_sticky_stippled_icon_title = !!(x) #define HAS_STIPPLED_ICON_TITLE(fw) \ ((fw)->flags.common.s.has_stippled_icon_title) #define SET_HAS_STIPPLED_ICON_TITLE(fw,x) \ (fw)->flags.common.s.has_stippled_icon_title = !!(x) #define SETM_HAS_STIPPLED_ICON_TITLE(fw,x) \ (fw)->flag_mask.common.s.has_stippled_icon_title = !!(x) #define ICON_OVERRIDE_MODE(fw) \ ((fw)->flags.common.s.icon_override) #define SET_ICON_OVERRIDE_MODE(fw,x) \ (fw)->flags.common.s.icon_override = ((x) & ICON_OVERRIDE_MASK) #define SETM_ICON_OVERRIDE_MODE(fw,x) \ (fw)->flag_mask.common.s.icon_override = ((x) ? ICON_OVERRIDE_MASK : 0) #define IS_ICON_STICKY_ACROSS_PAGES(fw) \ ((fw)->flags.common.s.is_icon_sticky_across_pages) #define SET_ICON_STICKY_ACROSS_PAGES(fw,x) \ (fw)->flags.common.s.is_icon_sticky_across_pages = !!(x) #define SETM_ICON_STICKY_ACROSS_PAGES(fw,x) \ (fw)->flag_mask.common.s.is_icon_sticky_across_pages = !!(x) #define IS_ICON_STICKY_ACROSS_DESKS(fw) \ ((fw)->flags.common.s.is_icon_sticky_across_desks) #define SET_ICON_STICKY_ACROSS_DESKS(fw,x) \ (fw)->flags.common.s.is_icon_sticky_across_desks = !!(x) #define SETM_ICON_STICKY_ACROSS_DESKS(fw,x) \ (fw)->flag_mask.common.s.is_icon_sticky_across_desks = !!(x) #define USE_ICON_POSITION_HINT(fw) \ ((fw)->flags.common.s.use_icon_position_hint) #define SET_USE_ICON_POSITION_HINT(fw,x) \ (fw)->flags.common.s.use_icon_position_hint = !!(x) #define SETM_USE_ICON_POSITION_HINT(fw,x) \ (fw)->flag_mask.common.s.use_icon_position_hint = !!(x) #define USE_INDEXED_WINDOW_NAME(fw) \ ((fw)->flags.common.s.use_indexed_window_name) #define SET_USE_INDEXED_WINDOW_NAME(fw,x) \ (fw)->flags.common.s.use_indexed_window_name = !!(x) #define SETM_USE_INDEXED_WINDOW_NAME(fw,x) \ (fw)->flag_mask.common.s.use_indexed_window_name = !!(x) #define USE_INDEXED_ICON_NAME(fw) \ ((fw)->flags.common.s.use_indexed_icon_name) #define SET_USE_INDEXED_ICON_NAME(fw,x) \ (fw)->flags.common.s.use_indexed_icon_name = !!(x) #define SETM_USE_INDEXED_ICON_NAME(fw,x) \ (fw)->flag_mask.common.s.use_indexed_icon_name = !!(x) #define WINDOWSHADE_LAZINESS(fw) \ ((fw)->flags.common.s.windowshade_laziness) #define SET_WINDOWSHADE_LAZINESS(fw,x) \ (fw)->flags.common.s.windowshade_laziness = \ ((x) & WINDOWSHADE_LAZY_MASK) #define SETM_WINDOWSHADE_LAZINESS(fw,x) \ (fw)->flag_mask.common.s.windowshade_laziness = \ ((x) ? WINDOWSHADE_LAZY_MASK : 0) #define DO_EWMH_MINI_ICON_OVERRIDE(fw) \ ((fw)->flags.common.s.do_ewmh_mini_icon_override) #define SET_DO_EWMH_MINI_ICON_OVERRIDE(fw,x) \ (fw)->flags.common.s.do_ewmh_mini_icon_override = !!(x) #define SETM_DO_EWMH_MINI_ICON_OVERRIDE(fw,x) \ (fw)->flag_mask.common.s.do_ewmh_mini_icon_override = !!(x) #define DO_EWMH_DONATE_ICON(fw) \ ((fw)->flags.common.s.do_ewmh_donate_icon) #define SET_DO_EWMH_DONATE_ICON(fw,x) \ (fw)->flags.common.s.do_ewmh_donate_icon = !!(x) #define SETM_DO_EWMH_DONATE_ICON(fw,x) \ (fw)->flag_mask.common.s.do_ewmh_donate_icon = !!(x) #define DO_EWMH_DONATE_MINI_ICON(fw) \ ((fw)->flags.common.s.do_ewmh_donate_mini_icon) #define SET_DO_EWMH_DONATE_MINI_ICON(fw,x) \ (fw)->flags.common.s.do_ewmh_donate_mini_icon = !!(x) #define SETM_DO_EWMH_DONATE_MINI_ICON(fw,x) \ (fw)->flag_mask.common.s.do_ewmh_donate_mini_icon = !!(x) #define DO_EWMH_USE_STACKING_HINTS(fw) \ ((fw)->flags.common.s.do_ewmh_use_stacking_hints) #define SET_DO_EWMH_USE_STACKING_HINTS(fw,x) \ (fw)->flags.common.s.do_ewmh_use_stacking_hints = !!(x) #define SETM_DO_EWMH_USE_STACKING_HINTS(fw,x) \ (fw)->flag_mask.common.s.do_ewmh_use_stacking_hints = !!(x) #define DO_EWMH_IGNORE_STRUT_HINTS(fw) \ ((fw)->flags.common.s.do_ewmh_ignore_strut_hints) #define SET_DO_EWMH_IGNORE_STRUT_HINTS(fw,x) \ (fw)->flags.common.s.do_ewmh_ignore_strut_hints = !!(x) #define SETM_DO_EWMH_IGNORE_STRUT_HINTS(fw,x) \ (fw)->flag_mask.common.s.do_ewmh_ignore_strut_hints = !!(x) #define DO_EWMH_IGNORE_STATE_HINTS(fw) \ ((fw)->flags.common.s.do_ewmh_ignore_state_hints) #define SET_DO_EWMH_IGNORE_STATE_HINTS(fw,x) \ (fw)->flags.common.s.do_ewmh_ignore_state_hints = !!(x) #define SETM_DO_EWMH_IGNORE_STATE_HINTS(fw,x) \ (fw)->flag_mask.common.s.do_ewmh_ignore_state_hints = !!(x) #define DO_EWMH_IGNORE_WINDOW_TYPE(fw) \ ((fw)->flags.common.s.do_ewmh_ignore_window_type) #define SET_DO_EWMH_IGNORE_WINDOW_TYPE(fw,x) \ (fw)->flags.common.s.do_ewmh_ignore_window_type = !!(x) #define SETM_DO_EWMH_IGNORE_WINDOW_TYPE(fw,x) \ (fw)->flag_mask.common.s.do_ewmh_ignore_window_type = !!(x) #define EWMH_MAXIMIZE_MODE(fw) \ ((fw)->flags.common.s.ewmh_maximize_mode) #define SET_EWMH_MAXIMIZE_MODE(fw,x) \ (fw)->flags.common.s.ewmh_maximize_mode = (x) #define SETM_EWMH_MAXIMIZE_MODE(fw,x) \ (fw)->flag_mask.common.s.ewmh_maximize_mode = (x) #define IS_ICON_SUPPRESSED(fw) \ ((fw)->flags.common.s.is_icon_suppressed) #define SET_ICON_SUPPRESSED(fw,x) \ (fw)->flags.common.s.is_icon_suppressed = !!(x) #define SETM_ICON_SUPPRESSED(fw,x) \ (fw)->flag_mask.common.s.is_icon_suppressed = !!(x) #define IS_STICKY_ACROSS_PAGES(fw) \ ((fw)->flags.common.is_sticky_across_pages) #define SET_STICKY_ACROSS_PAGES(fw,x) \ (fw)->flags.common.is_sticky_across_pages = !!(x) #define SETM_STICKY_ACROSS_PAGES(fw,x) \ (fw)->flag_mask.common.is_sticky_across_pages = !!(x) #define IS_STICKY_ACROSS_DESKS(fw) \ ((fw)->flags.common.is_sticky_across_desks) #define SET_STICKY_ACROSS_DESKS(fw,x) \ (fw)->flags.common.is_sticky_across_desks = !!(x) #define SETM_STICKY_ACROSS_DESKS(fw,x) \ (fw)->flag_mask.common.is_sticky_across_desks = !!(x) #define HAS_ICON_FONT(fw) \ ((fw)->flags.common.has_icon_font) #define SET_HAS_ICON_FONT(fw,x) \ (fw)->flags.common.has_icon_font = !!(x) #define SETM_HAS_ICON_FONT(fw,x) \ (fw)->flag_mask.common.has_icon_font = !!(x) #define HAS_NO_ICON_TITLE(fw) \ ((fw)->flags.common.s.has_no_icon_title) #define SET_HAS_NO_ICON_TITLE(fw,x) \ (fw)->flags.common.s.has_no_icon_title = !!(x) #define SETM_HAS_NO_ICON_TITLE(fw,x) \ (fw)->flag_mask.common.s.has_no_icon_title = !!(x) #define HAS_WINDOW_FONT(fw) \ ((fw)->flags.common.has_window_font) #define SET_HAS_WINDOW_FONT(fw,x) \ (fw)->flags.common.has_window_font = !!(x) #define SETM_HAS_WINDOW_FONT(fw,x) \ (fw)->flag_mask.common.has_window_font = !!(x) #define HAS_MWM_BORDER(fw) \ ((fw)->flags.common.s.has_mwm_border) #define HAS_MWM_BUTTONS(fw) \ ((fw)->flags.common.s.has_mwm_buttons) #define HAS_MWM_OVERRIDE_HINTS(fw) \ ((fw)->flags.common.s.has_mwm_override) #define HAS_OVERRIDE_SIZE_HINTS(fw) \ ((fw)->flags.common.s.has_override_size) #define DO_ICONIFY_WINDOW_GROUPS(fw) \ ((fw)->flags.common.s.do_iconify_window_groups) #define DO_IGNORE_GNOME_HINTS(fw) \ ((fw)->flags.common.s.do_ignore_gnome_hints) #define DO_IGNORE_RESTACK(fw) \ ((fw)->flags.common.s.do_ignore_restack) #define DO_IGNORE_ICON_BOXES(fw) \ ((fw)->flags.common.s.do_ignore_icon_boxes) #define DO_USE_WINDOW_GROUP_HINT(fw) \ ((fw)->flags.common.s.do_use_window_group_hint) #define IS_FIXED(fw) \ ((fw)->flags.common.s.is_fixed) #define SET_FIXED(fw,x) \ (fw)->flags.common.s.is_fixed = !!(x) #define SETM_FIXED(fw,x) \ (fw)->flag_mask.common.s.is_fixed = !!(x) #define IS_FIXED_PPOS(fw) \ ((fw)->flags.common.s.is_fixed_ppos) #define SET_FIXED_PPOS(fw,x) \ (fw)->flags.common.s.is_fixed_ppos = !!(x) #define SETM_FIXED_PPOS(fw,x) \ (fw)->flag_mask.common.s.is_fixed_ppos = !!(x) #define IS_SIZE_FIXED(fw) \ ((fw)->flags.common.s.is_size_fixed) #define SET_SIZE_FIXED(fw,x) \ (fw)->flags.common.s.is_size_fixed = !!(x) #define SETM_SIZE_FIXED(fw,x) \ (fw)->flag_mask.common.s.is_size_fixed = !!(x) #define IS_PSIZE_FIXED(fw) \ ((fw)->flags.common.s.is_psize_fixed) #define SET_PSIZE_FIXED(fw,x) \ (fw)->flags.common.s.is_psize_fixed = !!(x) #define SETM_PSIZE_FIXED(fw,x) \ (fw)->flag_mask.common.s.is_psize_fixed = !!(x) #define IS_UNICONIFIABLE(fw) \ ((fw)->flags.common.s.is_uniconifiable) #define SET_IS_UNICONIFIABLE(fw,x) \ (fw)->flags.common.s.is_uniconifiable = !!(x) #define SETM_IS_UNICONIFIABLE(fw,x) \ (fw)->flag_mask.common.s.is_uniconifiable = !!(x) #define IS_UNMAXIMIZABLE(fw) \ ((fw)->flags.common.s.is_unmaximizable) #define SET_IS_UNMAXIMIZABLE(fw,x) \ (fw)->flags.common.s.is_unmaximizable = !!(x) #define SETM_IS_UNMAXIMIZABLE(fw,x) \ (fw)->flag_mask.common.s.is_unmaximizable = !!(x) #define IS_UNCLOSABLE(fw) \ ((fw)->flags.common.s.is_unclosable) #define SET_IS_UNCLOSABLE(fw,x) \ (fw)->flags.common.s.is_unclosable = !!(x) #define SETM_IS_UNCLOSABLE(fw,x) \ (fw)->flag_mask.common.s.is_unclosable = !!(x) #define IS_MAXIMIZE_FIXED_SIZE_DISALLOWED(fw) \ ((fw)->flags.common.s.is_maximize_fixed_size_disallowed) #define SET_MAXIMIZE_FIXED_SIZE_DISALLOWED(fw,x) \ (fw)->flags.common.s.is_maximize_fixed_size_disallowed = !!(x) #define SETM_MAXIMIZE_FIXED_SIZE_DISALLOWED(fw,x) \ (fw)->flag_mask.common.s.is_maximize_fixed_size_disallowed = !!(x) #define HAS_DEPRESSABLE_BORDER(fw) \ ((fw)->flags.common.s.has_depressable_border) #define IS_LEFT_TITLE_ROTATED_CW(fw) \ ((fw)->flags.common.s.is_left_title_rotated_cw) #define SET_IS_LEFT_TITLE_ROTATED_CW(fw,x) \ (fw)->flags.common.s.is_left_title_rotated_cw = !!(x) #define SETM_IS_LEFT_TITLE_ROTATED_CW(fw,x) \ (fw)->flag_mask.common.s.is_left_title_rotated_cw = !!(x) #define IS_RIGHT_TITLE_ROTATED_CW(fw) \ ((fw)->flags.common.s.is_right_title_rotated_cw) #define SET_IS_RIGHT_TITLE_ROTATED_CW(fw,x) \ (fw)->flags.common.s.is_right_title_rotated_cw = !!(x) #define SETM_IS_RIGHT_TITLE_ROTATED_CW(fw,x) \ (fw)->flag_mask.common.s.is_right_title_rotated_cw = !!(x) #define IS_BOTTOM_TITLE_ROTATED(fw) \ ((fw)->flags.common.s.is_bottom_title_rotated) #define SET_IS_BOTTOM_TITLE_ROTATED(fw,x) \ (fw)->flags.common.s.is_bottom_title_rotated = !!(x) #define SETM_IS_BOTTOM_TITLE_ROTATED(fw,x) \ (fw)->flag_mask.common.s.is_bottom_title_rotated = !!(x) #define IS_BOTTOM_TITLE_ROTATED(fw) \ ((fw)->flags.common.s.is_bottom_title_rotated) #define SET_IS_BOTTOM_TITLE_ROTATED(fw,x) \ (fw)->flags.common.s.is_bottom_title_rotated = !!(x) #define SETM_IS_BOTTOM_TITLE_ROTATED(fw,x) \ (fw)->flag_mask.common.s.is_bottom_title_rotated = !!(x) #define USE_TITLE_DECOR_ROTATION(fw) \ ((fw)->flags.common.s.use_title_decor_rotation) #define SET_USE_TITLE_DECOR_ROTATION(fw,x) \ (fw)->flags.common.s.use_title_decor_rotation = !!(x) #define SETM_USE_TITLE_DECOR_ROTATION(fw,x) \ (fw)->flag_mask.common.s.use_title_decor_rotation = !!(x) /* access to the special flags of a window */ #define DO_REUSE_DESTROYED(fw) \ ((fw)->flags.do_reuse_destroyed) #define SET_DO_REUSE_DESTROYED(fw,x) \ (fw)->flags.do_reuse_destroyed = !!(x) #define SETM_DO_REUSE_DESTROYED(fw,x) \ (fw)->flag_mask.do_reuse_destroyed = !!(x) #define HAS_NO_BORDER(fw) \ ((fw)->flags.common.has_no_border) #define SET_HAS_NO_BORDER(fw,x) \ (fw)->flags.common.has_no_border = !!(x) #define SETM_HAS_NO_BORDER(fw,x) \ (fw)->flag_mask.common.has_no_border = !!(x) #define HAS_HANDLES(fw) \ ((fw)->flags.has_handles) #define SET_HAS_HANDLES(fw,x) \ (fw)->flags.has_handles = !!(x) #define SETM_HAS_HANDLES(fw,x) \ (fw)->flag_mask.has_handles = !!(x) #define HAS_ICON_CHANGED(fw) \ ((fw)->flags.has_icon_changed) #define SET_HAS_ICON_CHANGED(fw,x) \ (fw)->flags.has_icon_changed = !!(x) #define SETM_HAS_ICON_CHANGED(fw,x) \ (fw)->flag_mask.has_icon_changed = !!(x) #define HAS_TITLE(fw) \ ((fw)->flags.has_title) #define SET_HAS_TITLE(fw,x) \ (fw)->flags.has_title = !!(x) #define SETM_HAS_TITLE(fw,x) \ (fw)->flag_mask.has_title = !!(x) #define HAS_NEW_WM_NORMAL_HINTS(fw) \ ((fw)->flags.has_new_wm_normal_hints) #define SET_HAS_NEW_WM_NORMAL_HINTS(fw,x) \ (fw)->flags.has_new_wm_normal_hints = !!(x) #define SETM_HAS_NEW_WM_NORMAL_HINTS(fw,x) \ (fw)->flag_mask.has_new_wm_normal_hints = !!(x) #define IS_MAPPED(fw) \ ((fw)->flags.is_mapped) #define SET_MAPPED(fw,x) \ (fw)->flags.is_mapped = !!(x) #define SETM_MAPPED(fw,x) \ (fw)->flag_mask.is_mapped = !!(x) #define IS_DECOR_CHANGED(fw) \ ((fw)->flags.is_decor_changed) #define SET_DECOR_CHANGED(fw,x) \ (fw)->flags.is_decor_changed = !!(x) #define SETM_DECOR_CHANGED(fw,x) \ (fw)->flag_mask.is_decor_changed = !!(x) #define IS_ICON_FONT_LOADED(fw) \ ((fw)->flags.is_icon_font_loaded) #define SET_ICON_FONT_LOADED(fw,x) \ (fw)->flags.is_icon_font_loaded = !!(x) #define SETM_ICON_FONT_LOADED(fw,x) \ (fw)->flag_mask.is_icon_font_loaded = !!(x) #define IS_ICONIFIED(fw) \ ((fw)->flags.is_iconified) #define SET_ICONIFIED(fw,x) \ (fw)->flags.is_iconified = !!(x) #define SETM_ICONIFIED(fw,x) \ (fw)->flag_mask.is_iconified = !!(x) #define IS_ICONIFIED_BY_PARENT(fw) \ ((fw)->flags.is_iconified_by_parent) #define SET_ICONIFIED_BY_PARENT(fw,x) \ (fw)->flags.is_iconified_by_parent = !!(x) #define SETM_ICONIFIED_BY_PARENT(fw,x) \ (fw)->flag_mask.is_iconified_by_parent = !!(x) #define IS_ICON_ENTERED(fw) \ ((fw)->flags.is_icon_entered) #define SET_ICON_ENTERED(fw,x) \ (fw)->flags.is_icon_entered = !!(x) #define SETM_ICON_ENTERED(fw,x) \ (fw)->flag_mask.is_icon_entered = !!(x) #define IS_ICON_OURS(fw) \ ((fw)->flags.is_icon_ours) #define SET_ICON_OURS(fw,x) \ (fw)->flags.is_icon_ours = !!(x) #define SETM_ICON_OURS(fw,x) \ (fw)->flag_mask.is_icon_ours = !!(x) #define IS_ICON_SHAPED(fw) \ ((fw)->flags.is_icon_shaped) #define SET_ICON_SHAPED(fw,x) \ (fw)->flags.is_icon_shaped = !!(x) #define SETM_ICON_SHAPED(fw,x) \ (fw)->flag_mask.is_icon_shaped = !!(x) #define IS_ICON_MOVED(fw) \ ((fw)->flags.is_icon_moved) #define SET_ICON_MOVED(fw,x) \ (fw)->flags.is_icon_moved = !!(x) #define SETM_ICON_MOVED(fw,x) \ (fw)->flag_mask.is_icon_moved = !!(x) #define IS_ICON_UNMAPPED(fw) \ ((fw)->flags.is_icon_unmapped) #define SET_ICON_UNMAPPED(fw,x) \ (fw)->flags.is_icon_unmapped = !!(x) #define SETM_ICON_UNMAPPED(fw,x) \ (fw)->flag_mask.is_icon_unmapped = !!(x) #define IS_IN_TRANSIENT_SUBTREE(fw) \ ((fw)->flags.is_in_transient_subtree) #define SET_IN_TRANSIENT_SUBTREE(fw,x) \ (fw)->flags.is_in_transient_subtree = !!(x) #define IS_MAP_PENDING(fw) \ ((fw)->flags.is_map_pending) #define SET_MAP_PENDING(fw,x) \ (fw)->flags.is_map_pending = !!(x) #define SETM_MAP_PENDING(fw,x) \ (fw)->flag_mask.is_map_pending = !!(x) #define IS_MAXIMIZED(fw) \ ((fw)->flags.is_maximized) #define SET_MAXIMIZED(fw,x) \ (fw)->flags.is_maximized = !!(x) #define SETM_MAXIMIZED(fw,x) \ (fw)->flag_mask.is_maximized = !!(x) #define IS_NAME_CHANGED(fw) \ ((fw)->flags.is_name_changed) #define SET_NAME_CHANGED(fw,x) \ (fw)->flags.is_name_changed = !!(x) #define SETM_NAME_CHANGED(fw,x) \ (fw)->flag_mask.is_name_changed = !!(x) #define IS_PIXMAP_OURS(fw) \ ((fw)->flags.is_pixmap_ours) #define SET_PIXMAP_OURS(fw,x) \ (fw)->flags.is_pixmap_ours = !!(x) #define SETM_PIXMAP_OURS(fw,x) \ (fw)->flag_mask.is_pixmap_ours = !!(x) #define IS_PLACED_BY_FVWM(fw) \ ((fw)->flags.is_placed_by_fvwm) #define SET_PLACED_BY_FVWM(fw,x) \ (fw)->flags.is_placed_by_fvwm = (x) #define SETM_PLACED_BY_FVWM(fw,x) \ (fw)->flag_mask.is_placed_by_fvwm = (x) #define IS_SCHEDULED_FOR_DESTROY(fw) \ ((fw)->flags.is_scheduled_for_destroy) #define SET_SCHEDULED_FOR_DESTROY(fw,x) \ (fw)->flags.is_scheduled_for_destroy = !!(x) #define IS_SCHEDULED_FOR_RAISE(fw) \ ((fw)->flags.is_scheduled_for_raise) #define SET_SCHEDULED_FOR_RAISE(fw,x) \ (fw)->flags.is_scheduled_for_raise = !!(x) #define IS_SHADED(fw) \ ((fw)->flags.is_window_shaded) #define USED_TITLE_DIR_FOR_SHADING(fw) \ ((fw)->flags.used_title_dir_for_shading) #define SET_USED_TITLE_DIR_FOR_SHADING(fw,x) \ ((fw)->flags.used_title_dir_for_shading = !!(x)) #define SHADED_DIR(fw) \ ((fw)->flags.shaded_dir) #define SET_SHADED(fw,x) \ (fw)->flags.is_window_shaded = !!(x) #define SET_SHADED_DIR(fw,x) \ (fw)->flags.shaded_dir = (x) #define SETM_SHADED(fw,x) \ (fw)->flag_mask.is_window_shaded = !!(x) #define IS_TEAR_OFF_MENU(fw) \ ((fw)->flags.is_tear_off_menu) #define SET_TEAR_OFF_MENU(fw,x) \ (fw)->flags.is_tear_off_menu = !!(x) #define SETM_TEAR_OFF_MENU(fw,x) \ (fw)->flag_mask.is_tear_off_menu = !!(x) #define IS_TRANSIENT(fw) \ ((fw)->flags.is_transient) #define SET_TRANSIENT(fw,x) \ (fw)->flags.is_transient = !!(x) #define SETM_TRANSIENT(fw,x) \ (fw)->flag_mask.is_transient = !!(x) #define IS_ICONIFY_PENDING(fw) \ ((fw)->flags.is_iconify_pending) #define SET_ICONIFY_PENDING(fw,x) \ (fw)->flags.is_iconify_pending = !!(x) #define SETM_ICONIFY_PENDING(fw,x) \ (fw)->flag_mask.is_iconify_pending = !!(x) #define DO_ICONIFY_AFTER_MAP(fw) \ ((fw)->flags.do_iconify_after_map) #define SET_ICONIFY_AFTER_MAP(fw,x) \ (fw)->flags.do_iconify_after_map = !!(x) #define SETM_ICONIFY_AFTER_MAP(fw,x) \ (fw)->flag_mask.do_iconify_after_map = !!(x) #define DO_DISABLE_CONSTRAIN_SIZE_FULLSCREEN(fw) \ ((fw)->flags.do_disable_constrain_size_fullscreen) #define SET_DISABLE_CONSTRAIN_SIZE_FULLSCREEN(fw,x) \ (fw)->flags.do_disable_constrain_size_fullscreen = !!(x) #define SETM_DISABLE_CONSTRAIN_SIZE_FULLSCREEN(fw,x) \ (fw)->flag_mask.do_disable_constrain_size_fullscreen = !!(x) #define IS_SIZE_INC_SET(fw) \ ((fw)->flags.is_size_inc_set) #define SET_SIZE_INC_SET(fw,x) \ (fw)->flags.is_size_inc_set = !!(x) #define SETM_SIZE_INC_SET(fw,x) \ (fw)->flag_mask.is_size_inc_set = !!(x) #define IS_STYLE_DELETED(fw) \ ((fw)->flags.is_style_deleted) #define SET_STYLE_DELETED(fw,x) \ (fw)->flags.is_style_deleted = !!(x) #define SETM_STYLE_DELETED(fw,x) \ (fw)->flag_mask.is_style_deleted = !!(x) #define IS_VIEWPORT_MOVED(fw) \ ((fw)->flags.is_viewport_moved) #define SET_VIEWPORT_MOVED(fw,x) \ (fw)->flags.is_viewport_moved = !!(x) #define SETM_VIEWPORT_MOVED(fw,x) \ (fw)->flag_mask.is_viewport_moved = !!(x) #define IS_VIEWPORT_MOVED(fw) \ ((fw)->flags.is_viewport_moved) #define IS_FOCUS_CHANGE_BROADCAST_PENDING(fw) \ ((fw)->flags.is_focus_change_broadcast_pending) #define SET_FOCUS_CHANGE_BROADCAST_PENDING(fw,x) \ (fw)->flags.is_focus_change_broadcast_pending = !!(x) #define SETM_FOCUS_CHANGE_BROADCAST_PENDING(fw,x) \ (fw)->flag_mask.is_focus_change_broadcast_pending = !!(x) #define IS_FULLY_VISIBLE(fw) \ ((fw)->flags.is_fully_visible) #define SET_FULLY_VISIBLE(fw,x) \ (fw)->flags.is_fully_visible = !!(x) #define SETM_FULLY_VISIBLE(fw,x) \ (fw)->flag_mask.is_fully_visible = !!(x) #define IS_PARTIALLY_VISIBLE(fw) \ ((fw)->flags.is_partially_visible) #define SET_PARTIALLY_VISIBLE(fw,x) \ (fw)->flags.is_partially_visible = !!(x) #define SETM_PARTIALLY_VISIBLE(fw,x) \ (fw)->flag_mask.is_partially_visible = !!(x) #define IS_WINDOW_DRAWN_ONCE(fw) \ ((fw)->flags.is_window_drawn_once) #define SET_WINDOW_DRAWN_ONCE(fw,x) \ (fw)->flags.is_window_drawn_once = !!(x) #define SETM_WINDOW_DRAWN_ONCE(fw,x) \ (fw)->flag_mask.is_window_drawn_once = !!(x) #define IS_WINDOW_BEING_MOVED_OPAQUE(fw) \ ((fw)->flags.is_window_being_moved_opaque) #define SET_WINDOW_BEING_MOVED_OPAQUE(fw,x) \ (fw)->flags.is_window_being_moved_opaque = !!(x) #define SETM_WINDOW_BEING_MOVED_OPAQUE(fw,x) \ (fw)->flag_mask.is_window_being_moved_opaque = !!(x) #define IS_WINDOW_BORDER_DRAWN(fw) \ ((fw)->flags.is_window_border_drawn) #define SET_WINDOW_BORDER_DRAWN(fw,x) \ (fw)->flags.is_window_border_drawn = !!(x) #define SETM_WINDOW_BORDER_DRAWN(fw,x) \ (fw)->flag_mask.is_window_border_drawn = !!(x) #define IS_WINDOW_FONT_LOADED(fw) \ ((fw)->flags.is_window_font_loaded) #define SET_WINDOW_FONT_LOADED(fw,x) \ (fw)->flags.is_window_font_loaded = !!(x) #define SETM_WINDOW_FONT_LOADED(fw,x) \ (fw)->flag_mask.is_window_font_loaded = !!(x) #define CR_MOTION_METHOD(fw) \ ((fw)->flags.cr_motion_method) #define SET_CR_MOTION_METHOD(fw,x) \ (fw)->flags.cr_motion_method = ((x) & CR_MOTION_METHOD_MASK) #define SETM_CR_MOTION_METHOD(fw,x) \ (fw)->flag_mask.cr_motion_method = ((x) ? CR_MOTION_METHOD_MASK : 0) #define WAS_CR_MOTION_METHOD_DETECTED(fw) \ ((fw)->flags.was_cr_motion_method_detected) #define SET_CR_MOTION_METHOD_DETECTED(fw,x) \ (fw)->flags.was_cr_motion_method_detected = !!(x) #define SETM_CR_MOTION_METHOD_DETECTED(fw,x) \ (fw)->flag_mask.was_cr_motion_method_detected = !!(x) #define WM_DELETES_WINDOW(fw) \ ((fw)->flags.does_wm_delete_window) #define SET_WM_DELETES_WINDOW(fw,x) \ (fw)->flags.does_wm_delete_window = !!(x) #define SETM_WM_DELETES_WINDOW(fw,x) \ (fw)->flag_mask.does_wm_delete_window = !!(x) #define WM_TAKES_FOCUS(fw) \ ((fw)->flags.does_wm_take_focus) #define SET_WM_TAKES_FOCUS(fw,x) \ (fw)->flags.does_wm_take_focus = !!(x) #define SETM_WM_TAKES_FOCUS(fw,x) \ (fw)->flag_mask.does_wm_take_focus = !!(x) #define DO_FORCE_NEXT_CR(fw) \ ((fw)->flags.do_force_next_cr) #define SET_FORCE_NEXT_CR(fw,x) \ (fw)->flags.do_force_next_cr = !!(x) #define SETM_FORCE_NEXT_CR(fw,x) \ (fw)->flag_mask.do_force_next_cr = !!(x) #define DO_FORCE_NEXT_PN(fw) \ ((fw)->flags.do_force_next_pn) #define SET_FORCE_NEXT_PN(fw,x) \ (fw)->flags.do_force_next_pn = !!(x) #define SETM_FORCE_NEXT_PN(fw,x) \ (fw)->flag_mask.do_force_next_pn = !!(x) #define USING_DEFAULT_WINDOW_FONT(fw) \ ((fw)->flags.using_default_window_font) #define SET_USING_DEFAULT_WINDOW_FONT(fw,x) \ (fw)->flags.using_default_window_font = !!(x) #define SETM_USING_DEFAULT_WINDOW_FONT(fw,x) \ (fw)->flag_mask.using_default_window_font = !!(x) #define USING_DEFAULT_ICON_FONT(fw) \ ((fw)->flags.using_default_icon_font) #define SET_USING_DEFAULT_ICON_FONT(fw,x) \ (fw)->flags.using_default_icon_font = !!(x) #define SETM_USING_DEFAULT_ICON_FONT(fw,x) \ (fw)->flag_mask.using_default_icon_font = !!(x) #define WAS_ICON_HINT_PROVIDED(fw) \ ((fw)->flags.was_icon_hint_provided) #define SET_WAS_ICON_HINT_PROVIDED(fw,x) \ (fw)->flags.was_icon_hint_provided = (x) #define SETM_WAS_ICON_HINT_PROVIDED(fw,x) \ (fw)->flag_mask.was_icon_hint_provided = (x) #define WAS_ICON_NAME_PROVIDED(fw) \ ((fw)->flags.was_icon_name_provided) #define SET_WAS_ICON_NAME_PROVIDED(fw,x) \ (fw)->flags.was_icon_name_provided = (x) #define SETM_WAS_ICON_NAME_PROVIDED(fw,x) \ (fw)->flag_mask.was_icon_name_provided = (x) #define WAS_NEVER_DRAWN(fw) \ ((fw)->flags.was_never_drawn) #define SET_WAS_NEVER_DRAWN(fw,x) \ (fw)->flags.was_never_drawn = (x) #define SETM_WAS_NEVER_DRAWN(fw,x) \ (fw)->flag_mask.was_never_drawn = (x) #define HAS_EWMH_WM_NAME(fw) \ ((fw)->flags.has_ewmh_wm_name) #define SET_HAS_EWMH_WM_NAME(fw,x) \ (fw)->flags.has_ewmh_wm_name = !!(x) #define SETM_HAS_EWMH_WM_NAME(fw,x) \ (fw)->flag_mask.has_ewmh_wm_name = !!(x) #define HAS_EWMH_WM_ICON_NAME(fw) \ ((fw)->flags.has_ewmh_wm_icon_name) #define SET_HAS_EWMH_WM_ICON_NAME(fw,x) \ (fw)->flags.has_ewmh_wm_icon_name = !!(x) #define SETM_HAS_EWMH_WM_ICON_NAME(fw,x) \ (fw)->flag_mask.has_ewmh_wm_icon_name = !!(x) #define HAS_EWMH_WM_ICON_HINT(fw) \ ((fw)->flags.has_ewmh_wm_icon_hint) #define SET_HAS_EWMH_WM_ICON_HINT(fw,x) \ (fw)->flags.has_ewmh_wm_icon_hint = (x) #define SETM_HAS_EWMH_WM_ICON_HINT(fw,x) \ (fw)->flag_mask.has_ewmh_wm_icon_hint = (x) #define USE_EWMH_ICON(fw) \ ((fw)->flags.use_ewmh_icon) #define SET_USE_EWMH_ICON(fw,x) \ (fw)->flags.use_ewmh_icon = !!(x) #define SETM_USE_EWMH_ICON(fw,x) \ (fw)->flag_mask.use_ewmh_icon = !!(x) #define HAS_EWMH_MINI_ICON(fw) \ ((fw)->flags.has_ewmh_mini_icon) #define SET_HAS_EWMH_MINI_ICON(fw,x) \ (fw)->flags.has_ewmh_mini_icon = !!(x) #define SETM_HAS_EWMH_MINI_ICON(fw,x) \ (fw)->flag_mask.has_ewmh_mini_icon = !!(x) #define HAS_EWMH_WM_PID(fw) \ ((fw)->flags.has_ewmh_wm_pid) #define SET_HAS_EWMH_WM_PID(fw,x) \ (fw)->flags.has_ewmh_wm_pid = !!(x) #define SETM_HAS_EWMH_WM_PID(fw,x) \ (fw)->flag_mask.has_ewmh_wm_pid = !!(x) #define IS_EWMH_MODAL(fw) \ ((fw)->flags.is_ewmh_modal) #define SET_EWMH_MODAL(fw,x) \ (fw)->flags.is_ewmh_modal = !!(x) #define SETM_EWMH_MODAL(fw,x) \ (fw)->flag_mask.is_ewmh_modal = !!(x) #define IS_EWMH_FULLSCREEN(fw) \ ((fw)->flags.is_ewmh_fullscreen) #define SET_EWMH_FULLSCREEN(fw,x) \ (fw)->flags.is_ewmh_fullscreen = !!(x) #define SETM_EWMH_FULLSCREEN(fw,x) \ (fw)->flag_mask.is_ewmh_fullscreen = !!(x) #define SET_HAS_EWMH_INIT_FULLSCREEN_STATE(fw,x) \ (fw)->flags.has_ewmh_init_fullscreen_state = (x) #define SETM_HAS_EWMH_INIT_FULLSCREEN_STATE(fw,x) \ (fw)->flag_mask.has_ewmh_init_fullscreen_state = (x) #define HAS_EWMH_INIT_FULLSCREEN_STATE(fw) \ ((fw)->flags.has_ewmh_init_fullscreen_state) #define SET_HAS_EWMH_INIT_HIDDEN_STATE(fw,x) \ (fw)->flags.has_ewmh_init_hidden_state = (x) #define SETM_HAS_EWMH_INIT_HIDDEN_STATE(fw,x) \ (fw)->flag_mask.has_ewmh_init_hidden_state = (x) #define HAS_EWMH_INIT_HIDDEN_STATE(fw) \ ((fw)->flags.has_ewmh_init_hidden_state) #define SET_HAS_EWMH_INIT_MAXHORIZ_STATE(fw,x) \ (fw)->flags.has_ewmh_init_maxhoriz_state = (x) #define SETM_HAS_EWMH_INIT_MAXHORIZ_STATE(fw,x) \ (fw)->flag_mask.has_ewmh_init_maxhoriz_state = (x) #define HAS_EWMH_INIT_MAXHORIZ_STATE(fw) \ ((fw)->flags.has_ewmh_init_maxhoriz_state) #define SET_HAS_EWMH_INIT_MAXVERT_STATE(fw,x) \ (fw)->flags.has_ewmh_init_maxvert_state = (x) #define SETM_HAS_EWMH_INIT_MAXVERT_STATE(fw,x) \ (fw)->flag_mask.has_ewmh_init_maxvert_state = (x) #define HAS_EWMH_INIT_MAXVERT_STATE(fw) \ ((fw)->flags.has_ewmh_init_maxvert_state) #define SET_HAS_EWMH_INIT_MODAL_STATE(fw,x) \ (fw)->flags.has_ewmh_init_modal_state = (x) #define SETM_HAS_EWMH_INIT_MODAL_STATE(fw,x) \ (fw)->flag_mask.has_ewmh_init_modal_state = (x) #define HAS_EWMH_INIT_MODAL_STATE(fw) \ ((fw)->flags.has_ewmh_init_modal_state) #define SET_HAS_EWMH_INIT_SHADED_STATE(fw,x) \ (fw)->flags.has_ewmh_init_shaded_state = (x) #define SETM_HAS_EWMH_INIT_SHADED_STATE(fw,x) \ (fw)->flag_mask.has_ewmh_init_shaded_state = (x) #define HAS_EWMH_INIT_SHADED_STATE(fw) \ ((fw)->flags.has_ewmh_init_shaded_state) #define SET_HAS_EWMH_INIT_SKIP_PAGER_STATE(fw,x) \ (fw)->flags.has_ewmh_init_skip_pager_state = (x) #define SETM_HAS_EWMH_INIT_SKIP_PAGER_STATE(fw,x) \ (fw)->flag_mask.has_ewmh_init_skip_pager_state = (x) #define HAS_EWMH_INIT_SKIP_PAGER_STATE(fw) \ ((fw)->flags.has_ewmh_init_skip_pager_state) #define SET_HAS_EWMH_INIT_SKIP_TASKBAR_STATE(fw,x) \ (fw)->flags.has_ewmh_init_skip_taskbar_state = (x) #define SETM_HAS_EWMH_INIT_SKIP_TASKBAR_STATE(fw,x) \ (fw)->flag_mask.has_ewmh_init_skip_taskbar_state = (x) #define HAS_EWMH_INIT_SKIP_TASKBAR_STATE(fw) \ ((fw)->flags.has_ewmh_init_skip_taskbar_state) #define SET_HAS_EWMH_INIT_STICKY_STATE(fw,x) \ (fw)->flags.has_ewmh_init_sticky_state = (x) #define SETM_HAS_EWMH_INIT_STICKY_STATE(fw,x) \ (fw)->flag_mask.has_ewmh_init_sticky_state = (x) #define HAS_EWMH_INIT_STICKY_STATE(fw) \ ((fw)->flags.has_ewmh_init_sticky_state) #define SET_HAS_EWMH_INIT_WM_DESKTOP(fw,x) \ (fw)->flags.has_ewmh_init_wm_desktop = (x) #define SETM_HAS_EWMH_INIT_WM_DESKTOP(fw,x) \ (fw)->flag_mask.has_ewmh_init_wm_desktop = (x) #define HAS_EWMH_INIT_WM_DESKTOP(fw) \ ((fw)->flags.has_ewmh_init_wm_desktop) #endif /* _WINDOW_FLAGS_ */ fvwm-2.7.0/fvwm/windowlist.c0000644000175000017500000006006314147024700012752 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* * * fvwm window-list popup code * */ #include "config.h" #include #include #include "libs/fvwmlib.h" #include "libs/FScreen.h" #include "libs/FGettext.h" #include "libs/Parse.h" #include "libs/Strings.h" #include "fvwm.h" #include "externs.h" #include "functions.h" #include "misc.h" #include "screen.h" #include "menudim.h" #include "menuitem.h" #include "menuroot.h" #include "menustyle.h" #include "menus.h" #include "menuparameters.h" #include "conditional.h" #include "stack.h" #include "focus.h" #include "virtual.h" #include "geometry.h" #define SHOW_GEOMETRY (1<<0) #define SHOW_ALLDESKS (1<<1) #define SHOW_NORMAL (1<<2) #define SHOW_ICONIC (1<<3) #define SHOW_STICKY_ACROSS_PAGES (1<<4) #define SHOW_STICKY_ACROSS_DESKS (1<<5) #define NO_DESK_SORT (1<<6) #define SHOW_ICONNAME (1<<7) #define SHOW_ALPHABETIC (1<<8) #define SORT_BYCLASS (1<<9) #define SORT_BYRESOURCE (1<<10) #define SORT_REVERSE (1<<11) #define SHOW_INFONOTGEO (1<<12) #define NO_DESK_NUM (1<<13) #define NO_CURRENT_DESK_TITLE (1<<14) #define TITLE_FOR_ALL_DESKS (1<<15) #define NO_NUM_IN_DESK_TITLE (1<<16) #define SHOW_PAGE_X (1<<17) #define SHOW_PAGE_Y (1<<18) #define NO_LAYER (1<<19) #define SHOW_SCREEN (1<<20) #define SHOW_DEFAULT (SHOW_GEOMETRY | SHOW_ALLDESKS | SHOW_NORMAL | \ SHOW_ICONIC | SHOW_STICKY_ACROSS_PAGES | SHOW_STICKY_ACROSS_DESKS) static char *get_desk_title(int desk, unsigned long flags, Bool is_top_title) { char *desk_name; char *tlabel; desk_name = GetDesktopName(desk); if (desk_name != NULL) { tlabel = (char *)safemalloc(strlen(desk_name)+50); } else { tlabel = (char *)safemalloc(50); } if (desk_name != NULL) { if (flags & NO_NUM_IN_DESK_TITLE) { sprintf(tlabel, "%s%s", desk_name, (is_top_title && (flags & SHOW_GEOMETRY)) ? _("\tGeometry") : ""); } else { sprintf(tlabel,"%d: %s%s", desk, desk_name, (is_top_title && (flags & SHOW_GEOMETRY)) ? _("\tGeometry") : ""); } } else { sprintf(tlabel,_("Desk: %d%s"),desk, (is_top_title && (flags & SHOW_GEOMETRY)) ? _("\tGeometry") : ""); } return tlabel; } /* Function to compare window title names */ static int visibleCompare(const FvwmWindow **a, const FvwmWindow **b) { return strcasecmp((*a)->visible_name, (*b)->visible_name); } static int iconCompare(const FvwmWindow **a, const FvwmWindow **b) { return strcasecmp((*a)->visible_icon_name, (*b)->visible_icon_name); } /* Which of the compare functions to sort on. */ static int (*compare)(const FvwmWindow **a, const FvwmWindow **b); static int classCompare(const FvwmWindow **a, const FvwmWindow **b) { int result = strcasecmp((*a)->class.res_class, (*b)->class.res_class); if (result) { return result; } return strcasecmp((*a)->visible_name, (*b)->visible_name); } static int resourceCompare(const FvwmWindow **a, const FvwmWindow **b) { int result = strcasecmp((*a)->class.res_class, (*b)->class.res_class); if (result) { return result; } result = strcasecmp((*a)->class.res_name, (*b)->class.res_name); if (result) { return result; } return strcasecmp((*a)->visible_name, (*b)->visible_name); } static int classIconCompare(const FvwmWindow **a, const FvwmWindow **b) { int result = strcasecmp((*a)->class.res_class, (*b)->class.res_class); if (result) { return result; } return strcasecmp((*a)->visible_icon_name, (*b)->visible_icon_name); } static int resourceIconCompare(const FvwmWindow **a, const FvwmWindow **b) { int result = strcasecmp((*a)->class.res_class, (*b)->class.res_class); if (result) { return result; } result = strcasecmp((*a)->class.res_name, (*b)->class.res_name); if (result) { return result; } return strcasecmp((*a)->visible_icon_name, (*b)->visible_icon_name); } static int compareReverse(const FvwmWindow **a, const FvwmWindow **b) { return -compare(a, b); } /* * Change by PRB (pete@tecc.co.uk), 31/10/93. Prepend a hot key * specifier to each item in the list. This means allocating the * memory for each item (& freeing it) rather than just using the window * title directly. */ void CMD_WindowList(F_CMD_ARGS) { struct MenuRoot *mr; struct MenuParameters mp; char* ret_action = NULL; FvwmWindow *t; FvwmWindow **windowList; FvwmWindow **iconifiedList = NULL; int numWindows; int ii; char tname[128]; char loc[64]; char *name=NULL; Bool free_name = False; int dwidth; int dheight; char *tlabel; int last_desk_done = INT_MIN; int last_desk_displayed = INT_MIN; int next_desk = 0; char *t_hot=NULL; /* Menu label with hotkey added */ char scut = '0'; /* Current short cut key */ char *opts=NULL; char *tok=NULL; int desk = Scr.CurrentDesk; unsigned long flags = SHOW_DEFAULT; char *func = NULL; char *ffunc = NULL; char *tfunc = NULL; char *default_action = NULL; MenuReturn mret; MenuOptions mops; int low_layer = 0; /* show all layers by default */ int high_layer = INT_MAX; int max_label_width = 0; int skiplist_mode = 0; /* do not show skiplist by default */ Bool use_hotkey = True; KeyCode old_sor_keycode; char sor_default_keyname[8] = { 'M', 'e', 't', 'a', '_', 'L' }; char *sor_keyname = sor_default_keyname; /* Condition vars. */ Bool use_condition = False; Bool current_at_end = False; Bool iconified_at_end = False; int ic = 0; int ij; WindowConditionMask mask; char *cond_flags; Bool first_desk = True; Bool empty_menu = True; Bool was_get_menu_opts_called = False; FvwmWindow * const fw = exc->w.fw; const Window w = exc->w.w; const exec_context_t *exc2; memset(&mops, 0, sizeof(mops)); memset(&mret, 0, sizeof(MenuReturn)); /* parse postitioning args - must call this even if no action is given * because it sets the xinerama screen origin */ if (action && *action) { /* Look for condition - CreateFlagString returns NULL if no '(' * or '[' */ cond_flags = CreateFlagString(action, &action); if (cond_flags) { /* Create window mask */ use_condition = True; DefaultConditionMask(&mask); /* override for Current [] */ mask.my_flags.use_circulate_hit = 1; mask.my_flags.use_circulate_hit_icon = 1; CreateConditionMask(cond_flags, &mask); free(cond_flags); } opts = get_menu_options( action, w, fw, NULL, NULL, NULL, &mops); was_get_menu_opts_called = True; /* parse options */ while (opts && *opts) { opts = GetNextSimpleOption(opts, &tok); if (!tok) { break; } if (StrEquals(tok,"NoHotkeys")) { use_hotkey = False; } else if (StrEquals(tok,"Function")) { opts = GetNextSimpleOption(opts, &func); } else if (StrEquals(tok,"Desk")) { free(tok); opts = GetNextSimpleOption(opts, &tok); if (tok) { desk = atoi(tok); flags &= ~SHOW_ALLDESKS; } } else if (StrEquals(tok,"CurrentDesk")) { desk = Scr.CurrentDesk; flags &= ~SHOW_ALLDESKS; } else if (StrEquals(tok,"NotAlphabetic")) { flags &= ~SHOW_ALPHABETIC; } else if (StrEquals(tok,"Alphabetic")) { flags |= SHOW_ALPHABETIC; } else if (StrEquals(tok,"SortByClass")) { flags |= SORT_BYCLASS; } else if (StrEquals(tok,"SortByResource")) { flags |= SORT_BYRESOURCE; } else if (StrEquals(tok,"ReverseOrder")) { flags |= SORT_REVERSE; } else if (StrEquals(tok,"CurrentAtEnd")) { current_at_end = True; } else if (StrEquals(tok,"IconifiedAtEnd")) { iconified_at_end = True; } else if (StrEquals(tok,"NoDeskSort")) { flags |= NO_DESK_SORT; } else if (StrEquals(tok,"ShowPage")) { flags |= SHOW_PAGE_X | SHOW_PAGE_Y; } else if (StrEquals(tok,"ShowPageX")) { flags |= SHOW_PAGE_X; } else if (StrEquals(tok,"ShowPageY")) { flags |= SHOW_PAGE_Y; } else if (StrEquals(tok,"ShowScreen")) { flags |= SHOW_SCREEN; } else if (StrEquals(tok,"UseIconName")) { flags |= SHOW_ICONNAME; } else if (StrEquals(tok,"NoGeometry")) { flags &= ~SHOW_GEOMETRY; flags &= ~SHOW_INFONOTGEO; } else if (StrEquals(tok,"NoGeometryWithInfo")) { flags &= ~SHOW_GEOMETRY; flags |= SHOW_INFONOTGEO; } else if (StrEquals(tok,"Geometry")) { flags |= SHOW_GEOMETRY; flags &= ~SHOW_INFONOTGEO; } else if (StrEquals(tok,"NoIcons")) { flags &= ~SHOW_ICONIC; } else if (StrEquals(tok,"Icons")) { flags |= SHOW_ICONIC; } else if (StrEquals(tok,"OnlyIcons")) { flags = SHOW_ICONIC; } else if (StrEquals(tok,"NoNormal")) { flags &= ~SHOW_NORMAL; } else if (StrEquals(tok,"Normal")) { flags |= SHOW_NORMAL; } else if (StrEquals(tok,"OnlyNormal")) { flags = SHOW_NORMAL; } else if (StrEquals(tok,"NoSticky")) { flags &= ~(SHOW_STICKY_ACROSS_PAGES); flags &= ~(SHOW_STICKY_ACROSS_DESKS); } else if (StrEquals(tok,"NoStickyPage")) { flags &= ~(SHOW_STICKY_ACROSS_PAGES); } else if (StrEquals(tok,"NoStickyDesk")) { flags &= ~(SHOW_STICKY_ACROSS_DESKS); } else if (StrEquals(tok,"Sticky")) { flags |= SHOW_STICKY_ACROSS_PAGES; flags |= SHOW_STICKY_ACROSS_DESKS; } else if (StrEquals(tok,"StickyPage")) { flags |= SHOW_STICKY_ACROSS_PAGES; } else if (StrEquals(tok,"StickyDesk")) { flags |= SHOW_STICKY_ACROSS_DESKS; } else if (StrEquals(tok,"OnlySticky")) { flags = SHOW_STICKY_ACROSS_PAGES; flags = SHOW_STICKY_ACROSS_DESKS; } else if (StrEquals(tok,"OnlyStickyPage")) { flags = SHOW_STICKY_ACROSS_PAGES; } else if (StrEquals(tok,"OnlyStickyDesk")) { flags = SHOW_STICKY_ACROSS_DESKS; } else if (StrEquals(tok,"UseListSkip")) { /* deprecated as of 02-May-2007 (SS) */ fprintf(stderr, "UseListSkip is deprecated. Please use \"UseSkipList\".\n"); skiplist_mode = 1; } else if (StrEquals(tok,"UseSkipList")) { skiplist_mode = 1; } else if (StrEquals(tok,"OnlyListSkip")) { /* deprecated as of 02-May-2007 (SS) */ fprintf(stderr, "OnlyListSkip is deprecated. Please use \"OnlySkipList\".\n"); skiplist_mode = 2; } else if (StrEquals(tok,"OnlySkipList")) { skiplist_mode = 2; } else if (StrEquals(tok,"NoDeskNum")) { flags |= NO_DESK_NUM; } else if (StrEquals(tok,"NoLayer")) { flags |= NO_LAYER; } else if (StrEquals(tok,"NoCurrentDeskTitle")) { flags |= NO_CURRENT_DESK_TITLE; } else if (StrEquals(tok,"TitleForAllDesks")) { flags |= TITLE_FOR_ALL_DESKS; } else if (StrEquals(tok,"NoNumInDeskTitle")) { flags |= NO_NUM_IN_DESK_TITLE; } /* these are a bit dubious, but we should keep the * OnTop options for compatibility */ else if (StrEquals(tok, "NoOnTop")) { if (high_layer >= Scr.TopLayer) { high_layer = Scr.TopLayer - 1; } } else if (StrEquals(tok, "OnTop")) { if (high_layer < Scr.TopLayer) { high_layer = Scr.TopLayer; } } else if (StrEquals(tok, "OnlyOnTop")) { high_layer = low_layer = Scr.TopLayer; } else if (StrEquals(tok, "NoOnBottom")) { if (low_layer <= Scr.BottomLayer) { low_layer = Scr.BottomLayer - 1; } } else if (StrEquals(tok, "OnBottom")) { if (low_layer > Scr.BottomLayer) { low_layer = Scr.BottomLayer; } } else if (StrEquals(tok, "OnlyOnBottom")) { high_layer = low_layer = Scr.BottomLayer; } else if (StrEquals(tok, "Layer")) { free(tok); opts = GetNextSimpleOption(opts, &tok); if (tok) { low_layer = high_layer = atoi(tok); free(tok); opts = GetNextSimpleOption(opts, &tok); if (tok) { high_layer = atoi(tok); } } } else if (StrEquals(tok, "SelectOnRelease")) { if (sor_keyname != sor_default_keyname) { free(sor_keyname); } sor_keyname = NULL; opts = GetNextSimpleOption(opts, &sor_keyname); } else if (StrEquals(tok, "MaxLabelWidth")) { char *wid; opts = GetNextSimpleOption(opts, &wid); if (wid) { max_label_width = atoi(wid); if (max_label_width < 1) { max_label_width = 1; } free(wid); } } else if (!opts || !*opts) { default_action = safestrdup(tok); } else { fvwm_msg( ERR, "WindowList","Unknown option '%s'", tok); } if (tok) { free(tok); } } } if (was_get_menu_opts_called == False) { opts = get_menu_options( action, w, fw, NULL, NULL, NULL, &mops); } tlabel = get_desk_title(desk, flags, True); mr = NewMenuRoot(tlabel); if (!(flags & NO_CURRENT_DESK_TITLE)) { AddToMenu(mr, tlabel, "TITLE", False, False, False); empty_menu = False; } free(tlabel); numWindows = 0; for (t = Scr.FvwmRoot.next; t != NULL; t = t->next) { numWindows++; } windowList = malloc(numWindows*sizeof(t)); if (windowList == NULL) { return; } if (iconified_at_end) { iconifiedList = malloc(numWindows*sizeof(t)); if (iconifiedList == NULL) { free(windowList); return; } } /* get the windowlist starting from the current window (if any)*/ t = get_focus_window(); if (t == NULL) { t = Scr.FvwmRoot.next; } else if (current_at_end) { if (t->next) { t = t->next; } else { t = Scr.FvwmRoot.next; } } for (ii = 0; ii < numWindows; ii++) { if (flags & SORT_REVERSE) { windowList[numWindows - ii - 1] = t; } else if (iconified_at_end && IS_ICONIFIED(t)) { iconifiedList[ic++] = t; } else { windowList[ii - ic] = t; } if (t->next) { t = t->next; } else { t = Scr.FvwmRoot.next; } } if (iconified_at_end && ic > 0) { if (current_at_end && ii > ic) { windowList[numWindows - 1] = windowList[--ii - ic]; } for (ij = 0; ij < ic; ij++) { windowList[ij + (ii - ic)] = iconifiedList[ij]; } } /* Do alphabetic sort */ if (flags & (SHOW_ALPHABETIC | SORT_BYCLASS | SORT_BYRESOURCE)) { /* This will be compare or compareReverse if a reverse order * is selected. */ int (*sort)(const FvwmWindow **a, const FvwmWindow **b); switch (flags & (SHOW_ALPHABETIC | SHOW_ICONNAME | \ SORT_BYCLASS | SORT_BYRESOURCE)) { case SHOW_ALPHABETIC: compare = visibleCompare; break; case SHOW_ALPHABETIC | SHOW_ICONNAME: compare = iconCompare; break; /* Sorting based on class name produces an alphabetic * order so the keyword alphabetic is redundant. */ case SORT_BYCLASS: case SORT_BYCLASS | SHOW_ALPHABETIC: compare = classCompare; break; case SORT_BYCLASS | SHOW_ICONNAME: case SORT_BYCLASS | SHOW_ICONNAME | SHOW_ALPHABETIC: compare = classIconCompare; break; case SORT_BYRESOURCE: case SORT_BYRESOURCE | SORT_BYCLASS: case SORT_BYRESOURCE | SORT_BYCLASS | SHOW_ALPHABETIC: compare = resourceCompare; break; case SORT_BYRESOURCE | SHOW_ICONNAME: case SORT_BYRESOURCE | SHOW_ICONNAME | SORT_BYCLASS: case SORT_BYRESOURCE | SHOW_ICONNAME | SORT_BYCLASS | \ SHOW_ALPHABETIC: compare = resourceIconCompare; break; /* All current cases are covered, but if something * changes in the future we leave compare valid even if * it isn't what is expected. */ default: compare = visibleCompare; break; } if ( flags & SORT_REVERSE ) { sort = compareReverse; } else { sort = compare; } qsort(windowList, numWindows, sizeof(t), (int(*)(const void*, const void*))sort); } while(next_desk != INT_MAX) { /* Sort window list by desktop number */ if ((flags & SHOW_ALLDESKS) && !(flags & NO_DESK_SORT)) { /* run through the windowlist finding the first desk * not already processed */ next_desk = INT_MAX; for (ii = 0; ii < numWindows; ii++) { t = windowList[ii]; if (t->Desk >last_desk_done && t->Desk < next_desk) { next_desk = t->Desk; } } } if (!(flags & SHOW_ALLDESKS)) { /* if only doing one desk and it hasn't been done */ if (last_desk_done == INT_MIN) next_desk = desk; /* select the desk */ else next_desk = INT_MAX; /* flag completion */ } if (flags & NO_DESK_SORT) next_desk = INT_MAX; /* only go through loop once */ last_desk_done = next_desk; for (ii = 0; ii < numWindows; ii++) { t = windowList[ii]; if (t->Desk != next_desk && !(flags & NO_DESK_SORT)) { continue; } if (skiplist_mode == 0 && DO_SKIP_WINDOW_LIST(t)) { /* don't want skiplist windows - skip */ continue; } if (skiplist_mode == 2 && !DO_SKIP_WINDOW_LIST(t)) { /* don't want no skiplist one - skip */ continue; } if (use_condition && !MatchesConditionMask(t, &mask)) { /* doesn't match specified condition */ continue; } if (!(flags & SHOW_ICONIC) && (IS_ICONIFIED(t))) { /* don't want icons - skip */ continue; } if (!(flags & SHOW_STICKY_ACROSS_PAGES) && (IS_STICKY_ACROSS_PAGES(t))) { /* don't want sticky ones - skip */ continue; } if (!(flags & SHOW_STICKY_ACROSS_DESKS) && (IS_STICKY_ACROSS_DESKS(t))) { /* don't want sticky ones - skip */ continue; } if (!(flags & SHOW_NORMAL) && !(IS_ICONIFIED(t) || IS_STICKY_ACROSS_PAGES(t) || IS_STICKY_ACROSS_DESKS(t))) { /* don't want "normal" ones - skip */ continue; } if (get_layer(t) < low_layer || get_layer(t) > high_layer) { /* don't want this layer */ continue; } empty_menu = False; /* add separator between desks when geometry * shown but not at the top*/ if (t->Desk != last_desk_displayed) { if (last_desk_displayed != INT_MIN) { if (((flags & SHOW_GEOMETRY) || (flags & SHOW_INFONOTGEO)) && !(flags & TITLE_FOR_ALL_DESKS)) { AddToMenu( mr, NULL, NULL, False, False, False); } if (flags & TITLE_FOR_ALL_DESKS) { tlabel = get_desk_title( t->Desk, flags, False); AddToMenu( mr, tlabel, "TITLE", False, False, False); free(tlabel); } } last_desk_displayed = t->Desk; } if (first_desk && flags & TITLE_FOR_ALL_DESKS) { tlabel = get_desk_title(t->Desk, flags, False); AddToMenu( mr, tlabel, "TITLE", False, False, False); free(tlabel); } first_desk = False; if (flags & SHOW_ICONNAME) { name = t->visible_icon_name; } else { name = t->visible_name; } free_name = False; if (!name) { name = "NULL_NAME"; } else if (max_label_width > 0 && strlen(name) > max_label_width) { name = strdup(name); name[max_label_width] = '\0'; free_name = True; } t_hot = safemalloc(strlen(name) + 80); if (use_hotkey) { /* Generate label */ sprintf(t_hot, "&%c. ", scut); } else { *t_hot = 0; } if (!(flags & SHOW_INFONOTGEO)) { strcat(t_hot, name); } if (*t_hot == 0) { strcpy(t_hot, " "); } /* Next shortcut key */ if (scut == '9') { scut = 'A'; } else if (scut == 'Z') { scut = '0'; } else { scut++; } if (flags & SHOW_INFONOTGEO) { tname[0]=0; if (!IS_ICONIFIED(t) && !(flags & NO_DESK_NUM)) { sprintf(loc,"%d:", t->Desk); strcat(tname,loc); } if (IS_ICONIFIED(t)) { strcat(tname, "("); } strcat(t_hot,"\t"); strcat(t_hot,tname); strcat(t_hot, name); if (IS_ICONIFIED(t)) { strcat(t_hot, ")"); } } else if (flags & SHOW_GEOMETRY) { size_borders b; tname[0]=0; if (IS_ICONIFIED(t)) { strcpy(tname, "("); } if (!(flags & NO_DESK_NUM)) { sprintf(loc, "%d", t->Desk); strcat(tname, loc); } if (flags & SHOW_SCREEN) { fscreen_scr_arg fscr; int scr; fscr.xypos.x = Scr.Vx + t->g.frame.x + t->g.frame.width / 2; fscr.xypos.y = Scr.Vy + t->g.frame.y + t->g.frame.height / 2; scr = FScreenGetScrId( &fscr, FSCREEN_XYPOS); sprintf(loc, "@%d", scr); strcat(tname, loc); } if (flags & SHOW_PAGE_X) { sprintf(loc, "+%d", (Scr.Vx + t->g.frame.x + t->g.frame.width / 2) / Scr.MyDisplayWidth); strcat(tname, loc); } if (flags & SHOW_PAGE_Y) { sprintf(loc, "+%d", (Scr.Vy + t->g.frame.y + t->g.frame.height/2) / Scr.MyDisplayHeight); strcat(tname, loc); } if (!(flags & NO_LAYER)) { sprintf(loc, "(%d)", (get_layer(t))); strcat(tname, loc); } strcat(tname, ":"); get_window_borders(t, &b); dheight = t->g.frame.height - b.total_size.height; dwidth = t->g.frame.width - b.total_size.width; dwidth = (dwidth - t->hints.base_width) /t->orig_hints.width_inc; dheight = (dheight - t->hints.base_height) /t->orig_hints.height_inc; sprintf(loc,"%d",dwidth); strcat(tname, loc); sprintf(loc,"x%d",dheight); strcat(tname, loc); if (t->g.frame.x >=0) { sprintf(loc,"+%d",t->g.frame.x); } else { sprintf(loc,"%d",t->g.frame.x); } strcat(tname, loc); if (t->g.frame.y >=0) { sprintf(loc,"+%d",t->g.frame.y); } else { sprintf(loc,"%d",t->g.frame.y); } strcat(tname, loc); if (IS_STICKY_ACROSS_PAGES(t) || IS_STICKY_ACROSS_DESKS(t)) { strcat(tname, " S"); } if (IS_ICONIFIED(t)) { strcat(tname, ")"); } strcat(t_hot,"\t"); strcat(t_hot,tname); } ffunc = func ? func : "WindowListFunc"; tfunc = safemalloc(strlen(ffunc) + 36); /* support two ways for now: window context * (new) and window id param (old) */ sprintf(tfunc, "WindowId %lu %s %lu", FW_W(t), ffunc, FW_W(t)); AddToMenu( mr, t_hot, tfunc, False, False, False); free(tfunc); /* Add the title pixmap */ if (FMiniIconsSupported && t->mini_icon) { MI_MINI_ICON(MR_LAST_ITEM(mr))[0] = t->mini_icon; /* increase the cache count. Otherwise the * pixmap will be eventually removed from the * cache by DestroyMenu */ t->mini_icon->count++; } if (t_hot) { free(t_hot); } if (free_name) { free(name); } } } if (empty_menu) { /* force current desk title */ tlabel = get_desk_title(desk, flags, True); AddToMenu(mr, tlabel, "TITLE", False, False, False); free(tlabel); } if (func) { free(func); } free(windowList); if (iconified_at_end) { free(iconifiedList); } /* Use the WindowList menu style if there is one */ change_mr_menu_style(mr, "WindowList"); /* Activate select_on_release style */ old_sor_keycode = MST_SELECT_ON_RELEASE_KEY(mr); if (sor_keyname && (!MST_SELECT_ON_RELEASE_KEY(mr) || sor_keyname != sor_default_keyname)) { MST_SELECT_ON_RELEASE_KEY(mr) = XKeysymToKeycode( dpy, FvwmStringToKeysym(dpy, sor_keyname)); } memset(&mp, 0, sizeof(mp)); mp.menu = mr; exc2 = exc_clone_context(exc, NULL, 0); mp.pexc = &exc2; mp.flags.has_default_action = (default_action && *default_action != 0); mp.flags.is_sticky = 1; mp.flags.is_submenu = 0; mp.flags.is_already_mapped = 0; mp.flags.is_triggered_by_keypress = (!default_action && exc->x.etrigger->type == KeyPress); mp.pops = &mops; mp.ret_paction = &ret_action; do_menu(&mp, &mret); /* Restore old menu style */ MST_SELECT_ON_RELEASE_KEY(mr) = old_sor_keycode; if (ret_action) { free(ret_action); } DestroyMenu(mr, False, False); if (mret.rc == MENU_DOUBLE_CLICKED && default_action && *default_action) { execute_function(cond_rc, exc2, default_action, 0); } if (default_action != NULL) { free(default_action); } if (use_condition) { FreeConditionMask(&mask); } if (sor_keyname && sor_keyname != sor_default_keyname) { free(sor_keyname); } exc_destroy_context(exc2); return; } fvwm-2.7.0/aclocal.m40000644000175000017500000021006614324315774011277 00000000000000# generated automatically by aclocal 1.16.5 -*- Autoconf -*- # Copyright (C) 1996-2021 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # 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. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.71],, [m4_warning([this file was generated for autoconf 2.71. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # serial 11 (pkg-config-0.29.1) dnl Copyright © 2004 Scott James Remnant . dnl Copyright © 2012-2015 Dan Nicholson dnl dnl This program is free software; you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by dnl the Free Software Foundation; either version 2 of the License, or dnl (at your option) any later version. dnl dnl This program is distributed in the hope that it will be useful, but dnl WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU dnl General Public License for more details. dnl dnl You should have received a copy of the GNU General Public License dnl along with this program; if not, write to the Free Software dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA dnl 02111-1307, USA. dnl dnl As a special exception to the GNU General Public License, if you dnl distribute this file as part of a program that contains a dnl configuration script generated by Autoconf, you may include it under dnl the same distribution terms that you use for the rest of that dnl program. dnl PKG_PREREQ(MIN-VERSION) dnl ----------------------- dnl Since: 0.29 dnl dnl Verify that the version of the pkg-config macros are at least dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's dnl installed version of pkg-config, this checks the developer's version dnl of pkg.m4 when generating configure. dnl dnl To ensure that this macro is defined, also add: dnl m4_ifndef([PKG_PREREQ], dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) dnl dnl See the "Since" comment for each macro you use to see what version dnl of the macros you require. m4_defun([PKG_PREREQ], [m4_define([PKG_MACROS_VERSION], [0.29.1]) m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) ])dnl PKG_PREREQ dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) dnl ---------------------------------- dnl Since: 0.16 dnl dnl Search for the pkg-config tool and set the PKG_CONFIG variable to dnl first found in the path. Checks that the version of pkg-config found dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is dnl used since that's the first version where most current features of dnl pkg-config existed. AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])dnl PKG_PROG_PKG_CONFIG dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------------------------------- dnl Since: 0.18 dnl dnl Check to see whether a particular set of modules exists. Similar to dnl PKG_CHECK_MODULES(), but does not set variables or print errors. dnl dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) dnl only at the first occurence in configure.ac, so if the first place dnl it's called might be skipped (such as if it is within an "if", you dnl have to call PKG_CHECK_EXISTS manually AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_default([$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) dnl --------------------------------------------- dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting dnl pkg_failed based on the result. m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes ], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl ])dnl _PKG_CONFIG dnl _PKG_SHORT_ERRORS_SUPPORTED dnl --------------------------- dnl Internal check to see if pkg-config supports short errors. AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])dnl _PKG_SHORT_ERRORS_SUPPORTED dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl -------------------------------------------------------------- dnl Since: 0.4.0 dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES might not happen, you should be sure to include an dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])[]dnl ]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) $3 fi[]dnl ])dnl PKG_CHECK_MODULES dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl --------------------------------------------------------------------- dnl Since: 0.29 dnl dnl Checks for existence of MODULES and gathers its build flags with dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags dnl and VARIABLE-PREFIX_LIBS from --libs. dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to dnl include an explicit call to PKG_PROG_PKG_CONFIG in your dnl configure.ac. AC_DEFUN([PKG_CHECK_MODULES_STATIC], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl _save_PKG_CONFIG=$PKG_CONFIG PKG_CONFIG="$PKG_CONFIG --static" PKG_CHECK_MODULES($@) PKG_CONFIG=$_save_PKG_CONFIG[]dnl ])dnl PKG_CHECK_MODULES_STATIC dnl PKG_INSTALLDIR([DIRECTORY]) dnl ------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable pkgconfigdir as the location where a module dnl should install pkg-config .pc files. By default the directory is dnl $libdir/pkgconfig, but the default can be changed by passing dnl DIRECTORY. The user can override through the --with-pkgconfigdir dnl parameter. AC_DEFUN([PKG_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([pkgconfigdir], [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, [with_pkgconfigdir=]pkg_default) AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_INSTALLDIR dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) dnl -------------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable noarch_pkgconfigdir as the location where a dnl module should install arch-independent pkg-config .pc files. By dnl default the directory is $datadir/pkgconfig, but the default can be dnl changed by passing DIRECTORY. The user can override through the dnl --with-noarch-pkgconfigdir parameter. AC_DEFUN([PKG_NOARCH_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([noarch-pkgconfigdir], [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, [with_noarch_pkgconfigdir=]pkg_default) AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_NOARCH_INSTALLDIR dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------- dnl Since: 0.28 dnl dnl Retrieves the value of the pkg-config variable for the given module. AC_DEFUN([PKG_CHECK_VAR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl _PKG_CONFIG([$1], [variable="][$3]["], [$2]) AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl ])dnl PKG_CHECK_VAR dnl PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES, dnl [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND], dnl [DESCRIPTION], [DEFAULT]) dnl ------------------------------------------ dnl dnl Prepare a "--with-" configure option using the lowercase dnl [VARIABLE-PREFIX] name, merging the behaviour of AC_ARG_WITH and dnl PKG_CHECK_MODULES in a single macro. AC_DEFUN([PKG_WITH_MODULES], [ m4_pushdef([with_arg], m4_tolower([$1])) m4_pushdef([description], [m4_default([$5], [build with ]with_arg[ support])]) m4_pushdef([def_arg], [m4_default([$6], [auto])]) m4_pushdef([def_action_if_found], [AS_TR_SH([with_]with_arg)=yes]) m4_pushdef([def_action_if_not_found], [AS_TR_SH([with_]with_arg)=no]) m4_case(def_arg, [yes],[m4_pushdef([with_without], [--without-]with_arg)], [m4_pushdef([with_without],[--with-]with_arg)]) AC_ARG_WITH(with_arg, AS_HELP_STRING(with_without, description[ @<:@default=]def_arg[@:>@]),, [AS_TR_SH([with_]with_arg)=def_arg]) AS_CASE([$AS_TR_SH([with_]with_arg)], [yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)], [auto],[PKG_CHECK_MODULES([$1],[$2], [m4_n([def_action_if_found]) $3], [m4_n([def_action_if_not_found]) $4])]) m4_popdef([with_arg]) m4_popdef([description]) m4_popdef([def_arg]) ])dnl PKG_WITH_MODULES dnl PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES, dnl [DESCRIPTION], [DEFAULT]) dnl ----------------------------------------------- dnl dnl Convenience macro to trigger AM_CONDITIONAL after PKG_WITH_MODULES dnl check._[VARIABLE-PREFIX] is exported as make variable. AC_DEFUN([PKG_HAVE_WITH_MODULES], [ PKG_WITH_MODULES([$1],[$2],,,[$3],[$4]) AM_CONDITIONAL([HAVE_][$1], [test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"]) ])dnl PKG_HAVE_WITH_MODULES dnl PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES, dnl [DESCRIPTION], [DEFAULT]) dnl ------------------------------------------------------ dnl dnl Convenience macro to run AM_CONDITIONAL and AC_DEFINE after dnl PKG_WITH_MODULES check. HAVE_[VARIABLE-PREFIX] is exported as make dnl and preprocessor variable. AC_DEFUN([PKG_HAVE_DEFINE_WITH_MODULES], [ PKG_HAVE_WITH_MODULES([$1],[$2],[$3],[$4]) AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"], [AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])]) ])dnl PKG_HAVE_DEFINE_WITH_MODULES # Copyright (C) 2002-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.16' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.16.5], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.16.5])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. # TODO: see whether this extra hack can be removed once we start # requiring Autoconf 2.70 or later. AS_CASE([$CONFIG_FILES], [*\'*], [eval set x "$CONFIG_FILES"], [*], [set x $CONFIG_FILES]) shift # Used to flag and report bootstrapping failures. am_rc=0 for am_mf do # Strip MF so we end up with the name of the file. am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile which includes # dependency-tracking related rules and includes. # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ || continue am_dirpart=`AS_DIRNAME(["$am_mf"])` am_filepart=`AS_BASENAME(["$am_mf"])` AM_RUN_LOG([cd "$am_dirpart" \ && sed -e '/# am--include-marker/d' "$am_filepart" \ | $MAKE -f - am--depfiles]) || am_rc=$? done if test $am_rc -ne 0; then AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments for automatic dependency tracking. If GNU make was not used, consider re-running the configure script with MAKE="gmake" (or whatever is necessary). You can also try re-running configure with the '--disable-dependency-tracking' option to at least be able to build the package (albeit without support for automatic dependency tracking).]) fi AS_UNSET([am_dirpart]) AS_UNSET([am_filepart]) AS_UNSET([am_mf]) AS_UNSET([am_rc]) rm -f conftest-deps.mk } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking is enabled. # This creates each '.Po' and '.Plo' makefile fragment that we'll need in # order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC]) [_AM_PROG_CC_C_O ]) # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.65])dnl m4_ifdef([_$0_ALREADY_INIT], [m4_fatal([$0 expanded multiple times ]m4_defn([_$0_ALREADY_INIT]))], [m4_define([_$0_ALREADY_INIT], m4_expansion_stack)])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifset([AC_PACKAGE_NAME], [ok]):m4_ifset([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) # Variables for tags utilities; see am/tags.am if test -z "$CTAGS"; then CTAGS=ctags fi AC_SUBST([CTAGS]) if test -z "$ETAGS"; then ETAGS=etags fi AC_SUBST([ETAGS]) if test -z "$CSCOPE"; then CSCOPE=cscope fi AC_SUBST([CSCOPE]) AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi fi dnl The trailing newline in this macro's definition is deliberate, for dnl backward compatibility and to allow trailing 'dnl'-style comments dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MAKE_INCLUDE() # ----------------- # Check whether make has an 'include' directive that can support all # the idioms we need for our automatic dependency tracking code. AC_DEFUN([AM_MAKE_INCLUDE], [AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive]) cat > confinc.mk << 'END' am__doit: @echo this is the am__doit target >confinc.out .PHONY: am__doit END am__include="#" am__quote= # BSD make does it like this. echo '.include "confinc.mk" # ignored' > confmf.BSD # Other make implementations (GNU, Solaris 10, AIX) do it like this. echo 'include confinc.mk # ignored' > confmf.GNU _am_result=no for s in GNU BSD; do AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out]) AS_CASE([$?:`cat confinc.out 2>/dev/null`], ['0:this is the am__doit target'], [AS_CASE([$s], [BSD], [am__include='.include' am__quote='"'], [am__include='include' am__quote=''])]) if test "$am__include" != "#"; then _am_result="yes ($s style)" break fi done rm -f confinc.* confmf.* AC_MSG_RESULT([${_am_result}]) AC_SUBST([am__include])]) AC_SUBST([am__quote])]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it is modern enough. # If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then MISSING="\${SHELL} '$am_aux_dir/missing'" fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # -*- Autoconf -*- # Obsolete and "removed" macros, that must however still report explicit # error messages when used, to smooth transition. # # Copyright (C) 1996-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. AC_DEFUN([AM_CONFIG_HEADER], [AC_DIAGNOSE([obsolete], ['$0': this macro is obsolete. You should use the 'AC][_CONFIG_HEADERS' macro instead.])dnl AC_CONFIG_HEADERS($@)]) AC_DEFUN([AM_PROG_CC_STDC], [AC_PROG_CC am_cv_prog_cc_stdc=$ac_cv_prog_cc_stdc AC_DIAGNOSE([obsolete], ['$0': this macro is obsolete. You should simply use the 'AC][_PROG_CC' macro instead. Also, your code should no longer depend upon 'am_cv_prog_cc_stdc', but upon 'ac_cv_prog_cc_stdc'.])]) AC_DEFUN([AM_C_PROTOTYPES], [AC_FATAL([automatic de-ANSI-fication support has been removed])]) AU_DEFUN([fp_C_PROTOTYPES], [AM_C_PROTOTYPES]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Copyright (C) 1999-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_CC_C_O # --------------- # Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC # to automatically call this. AC_DEFUN([_AM_PROG_CC_C_O], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl AC_LANG_PUSH([C])dnl AC_CACHE_CHECK( [whether $CC understands -c and -o together], [am_cv_prog_cc_c_o], [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i]) if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) # Copyright (C) 1999-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PATH_PYTHON([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # --------------------------------------------------------------------------- # Adds support for distributing Python modules and packages. To # install modules, copy them to $(pythondir), using the python_PYTHON # automake variable. To install a package with the same name as the # automake package, install to $(pkgpythondir), or use the # pkgpython_PYTHON automake variable. # # The variables $(pyexecdir) and $(pkgpyexecdir) are provided as # locations to install python extension modules (shared libraries). # Another macro is required to find the appropriate flags to compile # extension modules. # # If your package is configured with a different prefix to python, # users will have to add the install directory to the PYTHONPATH # environment variable, or create a .pth file (see the python # documentation for details). # # If the MINIMUM-VERSION argument is passed, AM_PATH_PYTHON will # cause an error if the version of python installed on the system # doesn't meet the requirement. MINIMUM-VERSION should consist of # numbers and dots only. AC_DEFUN([AM_PATH_PYTHON], [ dnl Find a Python interpreter. Python versions prior to 2.0 are not dnl supported. (2.0 was released on October 16, 2000). m4_define_default([_AM_PYTHON_INTERPRETER_LIST], [python python2 python3 dnl python3.9 python3.8 python3.7 python3.6 python3.5 python3.4 python3.3 dnl python3.2 python3.1 python3.0 dnl python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 dnl python2.0]) AC_ARG_VAR([PYTHON], [the Python interpreter]) m4_if([$1],[],[ dnl No version check is needed. # Find any Python interpreter. if test -z "$PYTHON"; then AC_PATH_PROGS([PYTHON], _AM_PYTHON_INTERPRETER_LIST, :) fi am_display_PYTHON=python ], [ dnl A version check is needed. if test -n "$PYTHON"; then # If the user set $PYTHON, use it and don't search something else. AC_MSG_CHECKING([whether $PYTHON version is >= $1]) AM_PYTHON_CHECK_VERSION([$PYTHON], [$1], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) AC_MSG_ERROR([Python interpreter is too old])]) am_display_PYTHON=$PYTHON else # Otherwise, try each interpreter until we find one that satisfies # VERSION. AC_CACHE_CHECK([for a Python interpreter with version >= $1], [am_cv_pathless_PYTHON],[ for am_cv_pathless_PYTHON in _AM_PYTHON_INTERPRETER_LIST none; do test "$am_cv_pathless_PYTHON" = none && break AM_PYTHON_CHECK_VERSION([$am_cv_pathless_PYTHON], [$1], [break]) done]) # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON. if test "$am_cv_pathless_PYTHON" = none; then PYTHON=: else AC_PATH_PROG([PYTHON], [$am_cv_pathless_PYTHON]) fi am_display_PYTHON=$am_cv_pathless_PYTHON fi ]) if test "$PYTHON" = :; then dnl Run any user-specified action, or abort. m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])]) else dnl Query Python for its version number. Although site.py simply uses dnl sys.version[:3], printing that failed with Python 3.10, since the dnl trailing zero was eliminated. So now we output just the major dnl and minor version numbers, as numbers. Apparently the tertiary dnl version is not of interest. dnl AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version], [am_cv_python_version=`$PYTHON -c "import sys; print ('%u.%u' % sys.version_info[[:2]])"`]) AC_SUBST([PYTHON_VERSION], [$am_cv_python_version]) dnl At times, e.g., when building shared libraries, you may want dnl to know which OS platform Python thinks this is. dnl AC_CACHE_CHECK([for $am_display_PYTHON platform], [am_cv_python_platform], [am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`]) AC_SUBST([PYTHON_PLATFORM], [$am_cv_python_platform]) dnl emacs-page dnl If --with-python-sys-prefix is given, use the values of sys.prefix dnl and sys.exec_prefix for the corresponding values of PYTHON_PREFIX dnl and PYTHON_EXEC_PREFIX. Otherwise, use the GNU ${prefix} and dnl ${exec_prefix} variables. dnl dnl The two are made distinct variables so they can be overridden if dnl need be, although general consensus is that you shouldn't need dnl this separation. dnl dnl Also allow directly setting the prefixes via configure options, dnl overriding any default. dnl if test "x$prefix" = xNONE; then am__usable_prefix=$ac_default_prefix else am__usable_prefix=$prefix fi # Allow user to request using sys.* values from Python, # instead of the GNU $prefix values. AC_ARG_WITH([python-sys-prefix], [AS_HELP_STRING([--with-python-sys-prefix], [use Python's sys.prefix and sys.exec_prefix values])], [am_use_python_sys=:], [am_use_python_sys=false]) # Allow user to override whatever the default Python prefix is. AC_ARG_WITH([python_prefix], [AS_HELP_STRING([--with-python_prefix], [override the default PYTHON_PREFIX])], [am_python_prefix_subst=$withval am_cv_python_prefix=$withval AC_MSG_CHECKING([for explicit $am_display_PYTHON prefix]) AC_MSG_RESULT([$am_cv_python_prefix])], [ if $am_use_python_sys; then # using python sys.prefix value, not GNU AC_CACHE_CHECK([for python default $am_display_PYTHON prefix], [am_cv_python_prefix], [am_cv_python_prefix=`$PYTHON -c "import sys; sys.stdout.write(sys.prefix)"`]) dnl If sys.prefix is a subdir of $prefix, replace the literal value of dnl $prefix with a variable reference so it can be overridden. case $am_cv_python_prefix in $am__usable_prefix*) am__strip_prefix=`echo "$am__usable_prefix" | sed 's|.|.|g'` am_python_prefix_subst=`echo "$am_cv_python_prefix" | sed "s,^$am__strip_prefix,\\${prefix},"` ;; *) am_python_prefix_subst=$am_cv_python_prefix ;; esac else # using GNU prefix value, not python sys.prefix am_python_prefix_subst='${prefix}' am_python_prefix=$am_python_prefix_subst AC_MSG_CHECKING([for GNU default $am_display_PYTHON prefix]) AC_MSG_RESULT([$am_python_prefix]) fi]) # Substituting python_prefix_subst value. AC_SUBST([PYTHON_PREFIX], [$am_python_prefix_subst]) # emacs-page Now do it all over again for Python exec_prefix, but with yet # another conditional: fall back to regular prefix if that was specified. AC_ARG_WITH([python_exec_prefix], [AS_HELP_STRING([--with-python_exec_prefix], [override the default PYTHON_EXEC_PREFIX])], [am_python_exec_prefix_subst=$withval am_cv_python_exec_prefix=$withval AC_MSG_CHECKING([for explicit $am_display_PYTHON exec_prefix]) AC_MSG_RESULT([$am_cv_python_exec_prefix])], [ # no explicit --with-python_exec_prefix, but if # --with-python_prefix was given, use its value for python_exec_prefix too. AS_IF([test -n "$with_python_prefix"], [am_python_exec_prefix_subst=$with_python_prefix am_cv_python_exec_prefix=$with_python_prefix AC_MSG_CHECKING([for python_prefix-given $am_display_PYTHON exec_prefix]) AC_MSG_RESULT([$am_cv_python_exec_prefix])], [ # Set am__usable_exec_prefix whether using GNU or Python values, # since we use that variable for pyexecdir. if test "x$exec_prefix" = xNONE; then am__usable_exec_prefix=$am__usable_prefix else am__usable_exec_prefix=$exec_prefix fi # if $am_use_python_sys; then # using python sys.exec_prefix, not GNU AC_CACHE_CHECK([for python default $am_display_PYTHON exec_prefix], [am_cv_python_exec_prefix], [am_cv_python_exec_prefix=`$PYTHON -c "import sys; sys.stdout.write(sys.exec_prefix)"`]) dnl If sys.exec_prefix is a subdir of $exec_prefix, replace the dnl literal value of $exec_prefix with a variable reference so it can dnl be overridden. case $am_cv_python_exec_prefix in $am__usable_exec_prefix*) am__strip_prefix=`echo "$am__usable_exec_prefix" | sed 's|.|.|g'` am_python_exec_prefix_subst=`echo "$am_cv_python_exec_prefix" | sed "s,^$am__strip_prefix,\\${exec_prefix},"` ;; *) am_python_exec_prefix_subst=$am_cv_python_exec_prefix ;; esac else # using GNU $exec_prefix, not python sys.exec_prefix am_python_exec_prefix_subst='${exec_prefix}' am_python_exec_prefix=$am_python_exec_prefix_subst AC_MSG_CHECKING([for GNU default $am_display_PYTHON exec_prefix]) AC_MSG_RESULT([$am_python_exec_prefix]) fi])]) # Substituting python_exec_prefix_subst. AC_SUBST([PYTHON_EXEC_PREFIX], [$am_python_exec_prefix_subst]) # Factor out some code duplication into this shell variable. am_python_setup_sysconfig="\ import sys # Prefer sysconfig over distutils.sysconfig, for better compatibility # with python 3.x. See automake bug#10227. try: import sysconfig except ImportError: can_use_sysconfig = 0 else: can_use_sysconfig = 1 # Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs: # try: from platform import python_implementation if python_implementation() == 'CPython' and sys.version[[:3]] == '2.7': can_use_sysconfig = 0 except ImportError: pass" dnl emacs-page Set up 4 directories: dnl 1. pythondir: where to install python scripts. This is the dnl site-packages directory, not the python standard library dnl directory like in previous automake betas. This behavior dnl is more consistent with lispdir.m4 for example. dnl Query distutils for this directory. dnl AC_CACHE_CHECK([for $am_display_PYTHON script directory (pythondir)], [am_cv_python_pythondir], [if test "x$am_cv_python_prefix" = x; then am_py_prefix=$am__usable_prefix else am_py_prefix=$am_cv_python_prefix fi am_cv_python_pythondir=`$PYTHON -c " $am_python_setup_sysconfig if can_use_sysconfig: sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'}) else: from distutils import sysconfig sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix') sys.stdout.write(sitedir)"` # case $am_cv_python_pythondir in $am_py_prefix*) am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'` am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,\\${PYTHON_PREFIX},"` ;; *) case $am_py_prefix in /usr|/System*) ;; *) am_cv_python_pythondir="\${PYTHON_PREFIX}/lib/python$PYTHON_VERSION/site-packages" ;; esac ;; esac ]) AC_SUBST([pythondir], [$am_cv_python_pythondir]) dnl 2. pkgpythondir: $PACKAGE directory under pythondir. Was dnl PYTHON_SITE_PACKAGE in previous betas, but this naming is dnl more consistent with the rest of automake. dnl AC_SUBST([pkgpythondir], [\${pythondir}/$PACKAGE]) dnl 3. pyexecdir: directory for installing python extension modules dnl (shared libraries). dnl Query distutils for this directory. dnl AC_CACHE_CHECK([for $am_display_PYTHON extension module directory (pyexecdir)], [am_cv_python_pyexecdir], [if test "x$am_cv_python_exec_prefix" = x; then am_py_exec_prefix=$am__usable_exec_prefix else am_py_exec_prefix=$am_cv_python_exec_prefix fi am_cv_python_pyexecdir=`$PYTHON -c " $am_python_setup_sysconfig if can_use_sysconfig: sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_exec_prefix'}) else: from distutils import sysconfig sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_exec_prefix') sys.stdout.write(sitedir)"` # case $am_cv_python_pyexecdir in $am_py_exec_prefix*) am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'` am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,\\${PYTHON_EXEC_PREFIX},"` ;; *) case $am_py_exec_prefix in /usr|/System*) ;; *) am_cv_python_pyexecdir="\${PYTHON_EXEC_PREFIX}/lib/python$PYTHON_VERSION/site-packages" ;; esac ;; esac ]) AC_SUBST([pyexecdir], [$am_cv_python_pyexecdir]) dnl 4. pkgpyexecdir: $(pyexecdir)/$(PACKAGE) dnl AC_SUBST([pkgpyexecdir], [\${pyexecdir}/$PACKAGE]) dnl Run any user-specified action. $2 fi ]) # AM_PYTHON_CHECK_VERSION(PROG, VERSION, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) # --------------------------------------------------------------------------- # Run ACTION-IF-TRUE if the Python interpreter PROG has version >= VERSION. # Run ACTION-IF-FALSE otherwise. # This test uses sys.hexversion instead of the string equivalent (first # word of sys.version), in order to cope with versions such as 2.2c1. # This supports Python 2.0 or higher. (2.0 was released on October 16, 2000). AC_DEFUN([AM_PYTHON_CHECK_VERSION], [prog="import sys # split strings by '.' and convert to numeric. Append some zeros # because we need at least 4 digits for the hex conversion. # map returns an iterator in Python 3.0 and a list in 2.x minver = list(map(int, '$2'.split('.'))) + [[0, 0, 0]] minverhex = 0 # xrange is not present in Python 3.0 and range returns an iterator for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]] sys.exit(sys.hexversion < minverhex)" AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])]) # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2021 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar # AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([acinclude.m4]) fvwm-2.7.0/COPYING0000644000175000017500000004331714147024700010462 00000000000000The entire fvwm distribution is subject to the GNU GENERAL PUBLIC LICENSE (see below). ------------------------------------------------------------------------------- Additional copyrights of the fvwm main module: fvwm is copyright 1988 by Evans and Sutherland Computer Corporation, Salt Lake City, Utah, and 1989 by the Massachusetts Institute of Technology, Cambridge, Massachusetts, all rights reserved. It is also copyright 1993 and 1994 by Robert Nation, Nobutaka Suzuki, Mike Finger. Copyright 1996 by Romano Giannetti. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the names of Evans & Sutherland and M.I.T. not be used in advertising in publicity pertaining to distribution of the software without specific, written prior permission. ROBERT NATION, CHARLES HINES, EVANS & SUTHERLAND, AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ------------------------------------------------------------------------------- GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA fvwm-2.7.0/libs/0000755000175000017500000000000014324316054010433 500000000000000fvwm-2.7.0/libs/vpacket.h0000644000175000017500000000452314147024700012162 00000000000000/* -*-c-*- */ #ifndef _VPACKET_ #define _VPACKET_ #include "fvwm/window_flags.h" /* All new-style module packets (i.e., those that are not simply arrays of longs, as used by the older modules) should have a structure definition in this file. */ /* The M_CONFIGURE_WINDOW packet. This is the same packet as the M_ADD_WINDOW packet, the only difference being the type. */ /* RBW- typedef struct config_win_packet */ typedef struct ConfigWinPacket { /*** Alignment notes ***/ /*** Note that this packet format will break on future 128 bit *** platforms. ***/ /*** Put long, Window, and pointers here ***/ unsigned long w; /* Window */ unsigned long frame; /* Window */ unsigned long *fvwmwin; signed long frame_x; signed long frame_y; unsigned long frame_width; unsigned long frame_height; unsigned long desk; /* Temp word for alignment - old flags used to be here. - remove before next release. RBW - 05/01/2000 - layer has usurped this slot. unsigned long dummy; */ unsigned long layer; unsigned long hints_base_width; unsigned long hints_base_height; unsigned long hints_width_inc; unsigned long hints_height_inc; unsigned long orig_hints_width_inc; unsigned long orig_hints_height_inc; unsigned long hints_min_width; unsigned long hints_min_height; unsigned long hints_max_width; unsigned long hints_max_height; unsigned long icon_w; /* Window */ unsigned long icon_pixmap_w; /* Window */ unsigned long hints_win_gravity; unsigned long TextPixel; unsigned long BackPixel; /* Everything below this is post-GSFR */ unsigned long ewmh_hint_layer; unsigned long ewmh_hint_desktop; unsigned long ewmh_window_type; /*** Put int here, fill with dummies to a multiple of 2 ***/ /*** Put short here, fill with dummies to a multiple of 4 ***/ unsigned short title_height; unsigned short border_width; unsigned short short_dummy_3; unsigned short short_dummy_4; /*** Put structures here ***/ window_flags flags; action_flags allowed_actions; } ConfigWinPacket; typedef struct MiniIconPacket { Window w; Window frame; FvwmWindow *fvwmwin; unsigned long width; unsigned long height; unsigned long depth; Pixmap picture; Pixmap mask; Pixmap alpha; char name[1]; } MiniIconPacket; #endif /* _VPACKET_ */ fvwm-2.7.0/libs/envvar.c0000644000175000017500000003001114147024700012010 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* * MODULE OF fvwm * * DESCRIPTION Routines to expand environment-variables into strings. * Will understand both $ENV and ${ENV} -type variables. * * WRITTEN BY Sverre H. Huseby * sverrehu@ifi.uio.no * * CREATED 1995/10/3 * * UPDATED migo - 21/Jun/1999 - added getFirstEnv, some changes * */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include "fvwmlib.h" #include "envvar.h" /* ---------------------------- local definitions -------------------------- */ #ifdef HAVE_UNSETENV #define FHaveUnsetenv 1 #else #define unsetenv(x) do { } while (0) #define FHaveUnsetenv 0 #endif /* ---------------------------- local macros ------------------------------- */ #define ENV_LIST_INC 10 #ifndef NULL #define NULL 0 #endif /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ typedef struct { char *var; char *env; } env_list_item; /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ /*------------------------------------------------------------------------- * * NAME strDel * * FUNCTION Delete characters from a string. * * INPUT s the string to delete characters from. * idx index of first character to delete. * n number of characters to delete. * * OUTPUT s string with characters deleted. * * DESCRIPTION Deletes characters from a string by moving following * characters back. * */ static void strDel(char *s, int idx, int n) { int l; char *p; if (idx >= (l = strlen(s))) return; if (idx + n > l) n = l - idx; s += idx; p = s + n; do { *s++ = *p; } while (*p++); } /*------------------------------------------------------------------------- * * NAME strIns * * FUNCTION Insert a string into a string. * * INPUT s the string to insert into. * ins the string to insert. * idx index of where to insert the string. * maxstrlen max length of s, including '\0'. * * OUTPUT s string with characters inserted. * * DESCRIPTION The insertion will be done even if the string gets to * long, but characters will be sacrificed at the end of s. * The string is always '\0'-terminated. * */ static void strIns(char *s, const char *ins, int idx, int maxstrlen) { int l, li, move; char *p1, *p2; if (idx > (l = strlen(s))) { idx = l; } li = strlen(ins); move = l - idx + 1; /* include '\0' in move */ p1 = s + l; p2 = p1 + li; while (p2 >= s + maxstrlen) { --p1; --p2; --move; } while (move-- > 0) *p2-- = *p1--; p1 = s + idx; if (idx + li >= maxstrlen) { li = maxstrlen - idx - 1; } while (li-- > 0) *p1++ = *ins++; s[maxstrlen - 1] = '\0'; } /*------------------------------------------------------------------------- * * NAME findEnvVar * * FUNCTION Find first environment variable in a string. * * INPUT s the string to scan. * * OUTPUT len length of variable, including $ and { }. * * RETURNS Pointer to the $ that introduces the variable, or NULL * if no variable is found. * * DESCRIPTION Searches for matches like $NAME and ${NAME}, where NAME is * a sequence of characters, digits and underscores, of which * the first can not be a digit. * * NOTE This function will only return `legal' variables. There * may be $'s in the string that are not followed by what * is considered a legal variable name introducer. Such * occurrences are skipped. * */ static char *findEnvVar(const char *s, int *len) { int brace = 0; char *ret = NULL; const char *next; if (!s) return NULL; while (*s) { next = s + 1; if (*s == '$' && (isalpha(*next) || *next == '_' || *next == '{')) { ret = (char *) s++; if (*s == '{') { brace = 1; ++s; } while (*s && (isalnum(*s) || *s == '_')) ++s; *len = s - ret; if (brace) { if (*s == '}') { ++*len; break; } ret = NULL; } else break; } ++s; } return ret; } /*------------------------------------------------------------------------- * * FUNCTION Look up environment variable. * * INPUT name name of environment variable to look up. This * may include $ and { }. * len length for environment variable name (0 - ignore). * * RETURNS The variable contents, or "" if not found. * */ static const char *getEnv(const char *name, int len) { static char *empty = ""; char *ret = NULL, *tmp, *p, *p2; if ((tmp = safestrdup(name)) == NULL) return empty; /* better than no test at all. */ p = tmp; if (*p == '$') ++p; if (*p == '{') { ++p; if ((p2 = strchr(p, '}')) != NULL) *p2 = '\0'; } if (len > 0 && len < strlen(tmp)) tmp[len] = '\0'; if ((ret = getenv(p)) == NULL) ret = empty; free(tmp); return ret; } /* ---------------------------- interface functions ------------------------ */ /* * FUNCTION Expand environment variables in a string. * * SYNOPSIS #include "envvar.h" * int envExpand(char *s, int maxstrlen); * * INPUT s string to expand environment variables in. * maxstrlen max length of string, including '\0'. * * OUTPUT s the string with environment variables expanded. * * RETURNS Number of changes done. * * NOTES A non-existing variable is substituted with the empty * string. * */ int envExpand(char *s, int maxstrlen) { char *var, *s2; const char *env; int len, ret = 0; s2 = s; while ((var = findEnvVar(s2, &len)) != NULL) { ++ret; env = getEnv(var, len); strDel(s, var - s, len); strIns(s, env, var - s, maxstrlen); s2 = var + strlen(env); } return ret; } /* * FUNCTION Expand environment variables into a new string. * * SYNOPSIS #include "envvar.h" * char *envDupExpand(const char *s, int extra); * * INPUT s string to expand environment variables in. * extra number of extra bytes to allocate in the * string, in addition to the string contents * and the terminating '\0'. * * RETURNS A dynamically allocated string with environment * variables expanded. * Use free() to deallocate the buffer when it is no * longer needed. * NULL is returned if there is not enough memory. * * NOTES A non-existing variable is substituted with the empty * string. * */ char *envDupExpand(const char *s, int extra) { char *var, *ret; const char *env, *s2; int len, slen, elen, bufflen; /* * calculate length needed. */ s2 = s; slen = strlen(s); bufflen = slen + 1 + extra; while ((var = findEnvVar(s2, &len)) != NULL) { env = getEnv(var, len); elen = strlen(env); /* need to make a buffer the maximum possible size, else we * may get trouble while expanding. */ bufflen += len > elen ? len : elen; s2 = var + len; } if (bufflen < slen + 1) bufflen = slen + 1; ret = safemalloc(bufflen); /* * now do the real expansion. */ strcpy(ret, s); envExpand(ret, bufflen - extra); return ret; } /* * FUNCTION Search for the first environment variable and return * its contents and coordinates in the given string. * * INPUT s the string to scan. * may include $ and { } that introduce variable. * * OUTPUT beg index in the string of matching $. * end index in the string, first after matching var. * * RETURNS The variable contents; "" if env variable has legal name, * but does not exist; or NULL if no env variables found. * Returned constant string must not be deallocated. * * NOTE This function will only return `legal' variables. There * may be $'s in the string that are not followed by what * is considered a legal variable name introducer. Such * occurrences are skipped. * If nothing is found returns NULL and sets beg and end to 0. * * EXAMPLE getFirstEnv("echo $HOME/.fvwm/config", &beg, &end) * returns "/home/username" and beg=5, end=10. * */ const char* getFirstEnv(const char *s, int *beg, int *end) { char *var; const char *env; int len; *beg = *end = 0; if ((var = findEnvVar(s, &len)) == NULL) return NULL; env = getEnv(var, len); *beg = var - s; *end = *beg + len; return env; } /* If env is NULL, var is removed from the environment list */ static void add_to_envlist(char *var, char *env) { static env_list_item *env_list = NULL; static unsigned int env_len = 0; static unsigned int env_len_allocated = 0; unsigned int i; /* find string in list */ if (env_list && env_len) { for (i = 0; i < env_len; i++) { if (strcmp(var, env_list[i].var) != 0) { continue; } /* found it - replace old string */ free(env_list[i].var); free(env_list[i].env); if (env == NULL) { /* delete */ env_len--; env_list[i].var = env_list[env_len].var; env_list[i].env = env_list[env_len].env; } else { /* replace */ env_list[i].var = var; env_list[i].env = env; } return; } } if (env == NULL) { return; } /* not found */ if (env_list == NULL) { /* list is still empty */ env_len_allocated = ENV_LIST_INC; env_list = (env_list_item *)safecalloc( sizeof(env_list_item), env_len_allocated); } else if (env_len >= env_len_allocated && env != NULL) { /* need more memory */ env_len_allocated = env_len + ENV_LIST_INC; env_list = (env_list_item *)saferealloc( (void *)env_list, (env_len_allocated) * sizeof(env_list_item)); } env_list[env_len].var = var; env_list[env_len].env = env; env_len++; return; } /* This function keeps a list of all strings that were set in the environment. * If a variable is written again, the old memory is freed. This function * should be called instead of putenv(). * * var - environement variable name * env - environment string ("variable=value") * * Both arguments are copied internally and should be freed after calling this * function. */ void flib_putenv(char *var, char *env) { char *s; s = safestrdup(var); var = s; s = safestrdup(env); env = s; putenv(env); add_to_envlist(var, env); return; } void flib_unsetenv(const char *name) { if (FHaveUnsetenv) { unsetenv(name); } else { int rc; /* try putenv without '=' */ rc = putenv((char *)name); if (rc == 0 || getenv(name) != NULL) { /* failed, write empty string */ flib_putenv((char *)name, ""); return; } } add_to_envlist((char *)name, NULL); return; } fvwm-2.7.0/libs/FBidi.h0000644000175000017500000000534614147024700011506 00000000000000/* -*-c-*- */ /* Copyright (C) 2002 Mikhael Goikhman */ /* * FBidi.h - interface to Bidi (bidirectionality for some asian languages). */ /*** * The main function is * char *FBidiConvert( * const char *logical_str, const char *charset, int str_len, Bool *is_rtl, * int *out_len); * * input: * logical string - the original string * string charset - examples: "iso8859-15", "iso8859-8", "iso8859-6", "utf-8" * * output: * visual string is returned (should be free'd), or NULL if not applicable * the last argument is set to True if the string has the base RTL direction * * The is_rtl aggument may be used for 2 purposes. The first is to change the * string alignment if there is a free space (but it probably worth not to * override the user specified string aligment). The second is to determine * where to put ellipses if the string is longer than the available space. * * There are several possible ways to solve the ellipses problem. * This is not automated, the caller should choose one or another way. * * 1) For a logical string evaluate a visual string (and a base direction) * only once. If needed, cut the visual string and add ellipses at the * correct string side. * * 2) Cut logical string to the size that will be drawn, add allipses to the * end and call FBidiConvert on the resulting string. * * 3) Cut logical string to the size that will be drawn, call FBidiConvert * and add ellipses at the correct string side. * * Probably 2) is the best, but there is one nuance, the ellipses may be at * the middle of the string. With 1) and 3) the ellipses are always on the * edge of the string. The 1) is good when speed is more important than memory * and the string is usually either pure LTR or RTL. * * Example 1: * * input: she said "SHALOM" and then "BOKER TOV". * output: she said "MOLAHS" and then "VOT REKOB". * is_rtl: False * * 1) she said "MO... * 2) she said ...HS" * 3) she said HS"... * * Example 2: * * input: SHALOM, world! * output: !world ,MOLAHS * is_rtl: True * * 1) ...ld ,MOLAHS * 2) wo... ,MOLAHS * 3) ...wo ,MOLAHS * **/ #ifndef FBIDI_H #define FBIDI_H #include "config.h" #include #include "CombineChars.h" #if HAVE_BIDI /* * Checks whether the string in the given charset should be BidiConvert'd. */ Bool FBidiIsApplicable(const char *charset); /* * Converts the given logical string to visual string for the given charset. */ char *FBidiConvert( const char *logical_str, const char *charset, int str_len, Bool *is_rtl, int *out_len, superimpose_char_t *comb_chars, int *pos_l_to_v); #else /* !HAVE_BIDI */ #define FBidiIsApplicable(c) False #define FBidiConvert(s, c, l, r, o, cc, lv) NULL #endif /* HAVE_BIDI */ #endif /* FBIDI_H */ fvwm-2.7.0/libs/Strings.h0000644000175000017500000000421514147024700012154 00000000000000/* -*-c-*- */ #ifndef FVWMLIB_STRINGS_H #define FVWMLIB_STRINGS_H /** * Concatenate three strings. * * Parameters may be NULL to signify the empty string. * * Returns pointer to static storage, overwritten on the next call. **/ char *CatString3(const char *a, const char *b, const char *c); #define CatString2(a,b) CatString3(a,b,NULL) /** * Copy string into newly-malloced memory, stripping leading and * trailing spaces. The string is terminated by either a NUL or * a newline character. **/ void CopyString(char **dest, const char *source); /** * Like CopyString, but strips leading and trailing (double) quotes if any. **/ void CopyStringWithQuotes(char **dest, const char *src); /** * Copy string into newly-malloced memory, stripping leading and * trailing spaces. The difference between this and CopyString() * is that newlines are treated as whitespace by stripcpy(), whereas * CopyString() treats a newline as a string terminator (like the NUL * character. **/ char *stripcpy( const char *source ); /** * Return 1 if the two strings are equal. Case is ignored. **/ int StrEquals( const char *s1, const char *s2 ); /** * Return 1 if the string has the given prefix. Case is ignored. **/ int StrHasPrefix( const char* string, const char* prefix ); /** * Adds single quotes arround the string and escapes single quotes with * backslashes. The result is placed in the given dest, not allocated. * The end of destination, i.e. pointer to '\0' is returned. * You should allocate dest yourself, at least strlen(source) * 2 + 3. **/ char *QuoteString(char *dest, const char *source); /** * Adds delim around the source and escapes all characters in escape with * the corresponding escaper. The dest string must be preallocated. * delim should be included in escape with a proper escaper. * Returns a pointer to the end of dest. **/ char *QuoteEscapeString(char *dest, const char *source, char delim, const char *escape, const char *escaper); /** * Calculates the lenght needed by a escaped by QuoteEscapeString * the corresponding escaper. **/ unsigned int QuoteEscapeStringLength(const char *source, const char *escape); #endif fvwm-2.7.0/libs/fio.c0000644000175000017500000000274414147024700011300 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include #include "fio.h" /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- interface functions ------------------------ */ ssize_t fvwm_send(int s, const void *buf, size_t len, int flags) { int rc; size_t offset; const char *data; data = buf; offset = 0; do { rc = send(s, (char *)data + offset, len - offset, flags); if (rc > 0) { offset += rc; } } while ((rc > 0 && (offset < len)) || (rc == -1 && errno == EINTR)); return rc; } ssize_t fvwm_recv(int s, void *buf, size_t len, int flags) { int rc; do { rc = recv(s, buf, len, flags); } while (rc == -1 && errno == EINTR); return rc; } fvwm-2.7.0/libs/CombineChars.h0000644000175000017500000000073014147024676013072 00000000000000/* -*-c-*- */ /* Copyright (C) 2003 Marcus Lundblad */ /* * FCombineChars.h * * Interface to character combining */ #ifndef FCOMBINECHARS_H #define FCOMBINECHARS_H #include "config.h" #include typedef struct { int position; /* position in the string */ XChar2b c; /* UCS-2 character */ } superimpose_char_t; int CombineChars( unsigned char *str_visual, int len, superimpose_char_t **comb_chars, int **l_to_v); #endif /* FCOMBINECHARS_H */ fvwm-2.7.0/libs/Flocale.c0000644000175000017500000016031514147024700012067 00000000000000/* -*-c-*- */ /* Copyright (C) 2002 Olivier Chapuis */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* FlocaleRotateDrawString is strongly inspired by some part of xvertext * taken from wmx */ /* Here the copyright for this function: */ /* xvertext, Copyright (c) 1992 Alan Richardson (mppa3@uk.ac.sussex.syma) * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notice appear in all copies and that both the * copyright notice and this permission notice appear in supporting * documentation. All work developed as a consequence of the use of * this program should duly acknowledge such use. No representations are * made about the suitability of this software for any purpose. It is * provided "as is" without express or implied warranty. * * Minor modifications by Chris Cannam for wm2/wmx * Major modifications by Kazushi (Jam) Marukawa for wm2/wmx i18n patch * Simplification and complications by olicha for use with fvwm */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include #include #include #include "defaults.h" #include "fvwmlib.h" #include "Graphics.h" #include "ColorUtils.h" #include "Strings.h" #include "Parse.h" #include "PictureBase.h" #include "Flocale.h" #include "FlocaleCharset.h" #include "FBidi.h" #include "FftInterface.h" #include "Colorset.h" #include "Ficonv.h" #include "CombineChars.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ #define FSwitchDrawString(use_16, dpy, d, gc, x, y, s8, s16, l) \ (use_16) ? \ XDrawString16(dpy, d, gc, x, y, s16, l) : \ XDrawString(dpy, d, gc, x, y, s8, l) #define FSwitchDrawImageString(use_16, dpy, d, gc, x, y, s8, s16, l) \ (use_16) ? \ XDrawImageString16(dpy, d, gc, x, y, s16, l) : \ XDrawImageString(dpy, d, gc, x, y, s8, l) /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ static FlocaleFont *FlocaleFontList = NULL; static char *Flocale = NULL; static char *Fmodifiers = NULL; /* TODO: make these (static const char *) */ static char *fft_fallback_font = FLOCALE_FFT_FALLBACK_FONT; static char *mb_fallback_font = FLOCALE_MB_FALLBACK_FONT; static char *fallback_font = FLOCALE_FALLBACK_FONT; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ /* * shadow local functions */ static void FlocaleParseShadow(char *str, int *shadow_size, int *shadow_offset, int *direction, char * fontname, char *module) { char *dir_str; char *token; multi_direction_t dir; *direction = MULTI_DIR_NONE; token = PeekToken(str, &dir_str); if (token == NULL || *token == 0 || (GetIntegerArguments(token, NULL, shadow_size, 1) != 1) || *shadow_size < 0) { *shadow_size = 0; fprintf(stderr,"[%s][FlocaleParseShadow]: WARNING -- bad " "shadow size in font name:\n\t'%s'\n", (module)? module: "fvwm", fontname); return; } if (*shadow_size == 0) { return; } /* some offset ? */ if (dir_str && *dir_str && (GetIntegerArguments(dir_str, NULL, shadow_offset, 1) == 1)) { if (*shadow_offset < 0) { *shadow_offset = 0; fprintf(stderr,"[%s][FlocaleParseShadow]: WARNING -- " "bad shadow offset in font name:\n\t'%s'\n", (module)? module: "fvwmlibs", fontname); } PeekToken(dir_str, &dir_str); } while (dir_str && *dir_str && *dir_str != '\n') { dir = gravity_parse_multi_dir_argument(dir_str, &dir_str); if (dir == MULTI_DIR_NONE) { fprintf(stderr,"[%s][FlocaleParseShadow]: WARNING -- " "bad shadow direction in font description:\n" "\t%s\n", (module)? module: "fvwmlibs", fontname); PeekToken(dir_str, &dir_str); /* skip it */ } else { *direction |= dir; } } if (*direction == MULTI_DIR_NONE) *direction = MULTI_DIR_SE; } /* * some simple converters */ static int FlocaleChar2bOneCharToUtf8(XChar2b c, char *buf) { int len; char byte1 = c.byte1; char byte2 = c.byte2; unsigned short ucs2 = ((unsigned short)byte1 << 8) + byte2; if(ucs2 <= 0x7f) { len = 1; buf[0] = (char)ucs2; buf[1] = 0; } else if(ucs2 <= 0x7ff) { len = 2; buf[0] = (ucs2 >> 6) | 0xc0; buf[1] = (ucs2 & 0x3f) | 0x80; buf[2] = 0; } else { len = 3; buf[0] = (ucs2 >> 12) | 0xe0; buf[1] = ((ucs2 & 0xfff) >> 6) | 0x80; buf[2] = (ucs2 & 0x3f) | 0x80; buf[3] = 0; } return len; } /* return number of bytes of character at current position (pointed to by str) */ int FlocaleStringNumberOfBytes(FlocaleFont *flf, const char *str) { int bytes = 0; if(FLC_ENCODING_TYPE_IS_UTF_8(flf->fc)) { /* handle UTF-8 */ if ((str[0] & 0x80) == 0) { bytes = 1; } else if((str[0] & ~0xdf) == 0) { bytes = 2; } else { /* this handles only 16-bit Unicode */ bytes = 3; } } else if(flf->flags.is_mb) { /* non-UTF-8 multibyte encoding */ if ((str[0] & 0x80) == 0) { bytes = 1; } else { bytes = 2; } } else { /* we must be using an "ordinary" 8-bit encoding */ bytes = 1; } return bytes; } /* given a string, font specifying its locale and a byte offset gives character offset */ int FlocaleStringByteToCharOffset(FlocaleFont *flf, const char *str, int offset) { const char *curr_ptr = str; int i = 0; int len = strlen(str); int coffset = 0; int curr_len; for(i = 0 ; i < offset && i < len ; i += curr_len, curr_ptr += curr_len, coffset++) { curr_len = FlocaleStringNumberOfBytes(flf, curr_ptr); } return coffset; } /* like above but reversed, ie. return byte offset corresponding to given charater offset */ int FlocaleStringCharToByteOffset(FlocaleFont *flf, const char *str, int coffset) { const char *curr_ptr = str; int i; int len = strlen(str); int offset = 0; int curr_len; for(i = 0 ; i < coffset && i < len ; offset += curr_len, curr_ptr += curr_len, i++) { curr_len = FlocaleStringNumberOfBytes(flf, curr_ptr); } return offset; } /* return length of string in characters */ int FlocaleStringCharLength(FlocaleFont *flf, const char *str) { int i, len; int str_len = strlen(str); for(i = 0, len = 0 ; i < str_len ; i += FlocaleStringNumberOfBytes(flf, str+i), len++); return len; } static XChar2b *FlocaleUtf8ToUnicodeStr2b(char *str, int len, int *nl) { XChar2b *str2b = NULL; int i = 0, j = 0, t; str2b = (XChar2b *)safemalloc((len+1)*sizeof(XChar2b)); while (i < len && str[i] != 0) { if ((str[i] & 0x80) == 0) { str2b[j].byte2 = str[i]; str2b[j].byte1 = 0; } else if ((str[i] & ~0xdf) == 0 && i+1 < len) { t = ((str[i] & 0x1f) << 6) + (str[i+1] & 0x3f); str2b[j].byte2 = (unsigned char)(t & 0xff); str2b[j].byte1 = (unsigned char)(t >> 8); i++; } else if (i+2 > 8); i += 2; } i++; j++; } *nl = j; return str2b; } /* Note: this function is not expected to work; good mb rendering * should be (and is) done using Xmb functions and not XDrawString16 * (or with iso10646-1 fonts and setting the encoding). * This function is used when the locale does not correspond to the font. * It works with "EUC fonts": ksc5601.1987-0, gb2312 and maybe also * cns11643-*. It works patially with jisx* and big5-0. Should try gbk-0, * big5hkscs-0, and cns-11643- */ static XChar2b *FlocaleStringToString2b( Display *dpy, FlocaleFont *flf, char *str, int len, int *nl) { XChar2b *str2b = NULL; char *tmp = NULL; Bool free_str = False; int i = 0, j = 0; Bool euc = True; /* KSC5601 (EUC-KR), GB2312 (EUC-CN), CNS11643-1986-1 * (EUC-TW) and converted jisx (EUC-JP) */ if (flf->fc && StrEquals(flf->fc->x,"jisx0208.1983-0")) { tmp = FiconvCharsetToCharset( dpy, flf->fc, FlocaleCharsetGetEUCJPCharset(), str, len); if (tmp != NULL) { free_str = True; str = tmp; len = strlen(tmp); } } else if (flf->fc && StrEquals(flf->fc->x,"big5-0")) { euc = False; } str2b = (XChar2b *)safemalloc((len+1)*sizeof(XChar2b)); if (euc) { while (i < len && str[i] != 0) { if ((str[i] & 0x80) == 0) { /* seems ok with KSC5601 and GB2312 as we get * almost the ascii. I do no try * CNS11643-1986-1. Should convert to ascii * with jisx */ str2b[j].byte1 = 0x23; /* magic number! */ str2b[j].byte2 = str[i++]; } else if (i+1 < len) { /* mb gl (for gr replace & 0x7f by | 0x80 ...) */ str2b[j].byte1 = str[i++] & 0x7f; str2b[j].byte2 = str[i++] & 0x7f; } else { str2b[j].byte1 = 0; str2b[j].byte2 = 0; i++; } j++; } } else /* big5 and others not yet tested */ { while (i < len && str[i] != 0) { if ((str[i] & 0x80) == 0) { /* we should convert to ascii */ #if 0 str2b[j].byte1 = 0xa2; /* magic number! */ str2b[j].byte2 = str[i++]; #endif /* a blanck char ... */ str2b[j].byte1 = 0x21; str2b[j].byte2 = 0x21; } else if (i+1 < len) { str2b[j].byte1 = str[i++]; str2b[j].byte2 = str[i++]; } else { str2b[j].byte1 = 0; str2b[j].byte2 = 0; i++; } j++; } } *nl = j; if (free_str) free(str); return str2b; } static char *FlocaleEncodeString( Display *dpy, FlocaleFont *flf, char *str, int *do_free, int len, int *nl, int *is_rtl, superimpose_char_t **comb_chars, int **l_to_v) { char *str1, *str2, *str3; int len1; int len2; int i; Bool do_iconv = True; const char *bidi_charset; len1 = len; len2 = 0; if (is_rtl != NULL) *is_rtl = False; *do_free = False; *nl = len; if (flf->str_fc == NULL || flf->fc == NULL || flf->fc == flf->str_fc) { do_iconv = False; } str1 = str; if (FiconvSupport) { char *tmp_str; /* first process combining characters */ tmp_str = FiconvCharsetToUtf8( dpy, flf->str_fc, (const char *)str,len); /* if conversion to UTF-8 failed str1 will be NULL */ if(tmp_str != NULL) { /* do combining */ len = CombineChars((unsigned char *)tmp_str, strlen(tmp_str), comb_chars, l_to_v); /* returns the length of the resulting UTF-8 string */ /* convert back to current charset */ str1 = FiconvUtf8ToCharset( dpy, flf->str_fc, (const char *)tmp_str,len); if (tmp_str != str1) { free(tmp_str); } if (str1) { *nl = len = strlen(str1); *do_free = True; } else { /* convert back to current charset fail */ len = strlen(str); str1 = str; } } } if (FiconvSupport && do_iconv) { str2 = FiconvCharsetToCharset( dpy, flf->str_fc, flf->fc, (const char *)str1, len); if (str2 == NULL) { /* fail to convert */ return str1; } if (str2 != str1) { if (*do_free && str1) { free(str1); str1 = str2; } *do_free = True; len1 = strlen(str2); } } else { str2 = str1; len1 = len; /* initialise array with composing characters (empty) */ if(comb_chars != NULL && *comb_chars == NULL) { *comb_chars = (superimpose_char_t *) safemalloc(sizeof(superimpose_char_t)); (*comb_chars)[0].position = -1; (*comb_chars)[0].c.byte1 = 0; (*comb_chars)[0].c.byte2 = 0; } /* initialise logic to visual mapping here if that is demanded (this is default when no combining has been done (1-to-1)) */ if(l_to_v != NULL && *l_to_v == NULL) { *l_to_v = (int*)safemalloc((len + 1) * sizeof(int)); for(i = 0 ; i < len ; i++) (*l_to_v)[i] = i; (*l_to_v)[len] = -1; } } if (FlocaleGetBidiCharset(dpy, flf->str_fc) != NULL && (bidi_charset = FlocaleGetBidiCharset(dpy, flf->fc)) != NULL) { str3 = FBidiConvert(str2, bidi_charset, len1, is_rtl, &len2, comb_chars != NULL ? *comb_chars : NULL, l_to_v != NULL ? *l_to_v : NULL); if (str3 != NULL && str3 != str2) { if (*do_free) { free(str2); } *do_free = True; len1 = len2; str1 = str3; } /* if we failed to do BIDI convert, return string string from combining phase */ else { str1 = str2; /* we already have the logical to visual mapping from combining phase */ } } *nl = len1; return str1; } static void FlocaleEncodeWinString( Display *dpy, FlocaleFont *flf, FlocaleWinString *fws, int *do_free, int *len, superimpose_char_t **comb_chars, int **l_to_v) { int len2b; fws->e_str = FlocaleEncodeString( dpy, flf, fws->str, do_free, *len, len, NULL, comb_chars, l_to_v); fws->str2b = NULL; if (flf->font != None) { if (FLC_ENCODING_TYPE_IS_UTF_8(flf->fc)) { fws->str2b = FlocaleUtf8ToUnicodeStr2b( fws->e_str, *len, &len2b); } else if (flf->flags.is_mb) { fws->str2b = FlocaleStringToString2b( dpy, flf, fws->e_str, *len, &len2b); } } } /* * Text Drawing with a FontStruct */ static void FlocaleFontStructDrawString( Display *dpy, FlocaleFont *flf, Drawable d, GC gc, int x, int y, Pixel fg, Pixel fgsh, Bool has_fg_pixels, FlocaleWinString *fws, int len, Bool image) { int xt = x; int yt = y; int is_string16; flocale_gstp_args gstp_args; is_string16 = (FLC_ENCODING_TYPE_IS_UTF_8(flf->fc) || flf->flags.is_mb); if (is_string16 && fws->str2b == NULL) { return; } if (image) { /* for rotated drawing */ FSwitchDrawImageString( is_string16, dpy, d, gc, x, y, fws->e_str, fws->str2b, len); } else { FlocaleInitGstpArgs(&gstp_args, flf, fws, x, y); /* normal drawing */ if (flf->shadow_size != 0 && has_fg_pixels == True) { XSetForeground(dpy, fws->gc, fgsh); while (FlocaleGetShadowTextPosition( &xt, &yt, &gstp_args)) { FSwitchDrawString( is_string16, dpy, d, gc, xt, yt, fws->e_str, fws->str2b, len); } } if (has_fg_pixels == True) { XSetForeground(dpy, gc, fg); } xt = gstp_args.orig_x; yt = gstp_args.orig_y; FSwitchDrawString( is_string16, dpy, d, gc, xt,yt, fws->e_str, fws->str2b, len); } return; } /* * Rotated Text Drawing with a FontStruct or a FontSet */ static void FlocaleRotateDrawString( Display *dpy, FlocaleFont *flf, FlocaleWinString *fws, Pixel fg, Pixel fgsh, Bool has_fg_pixels, int len, superimpose_char_t *comb_chars, int *pixel_pos) { static GC my_gc = None; static GC font_gc = None; int j, i, xpfg, ypfg, xpsh, ypsh; unsigned char *normal_data, *rotated_data; unsigned int normal_w, normal_h, normal_len; unsigned int rotated_w, rotated_h, rotated_len; char val; int width, height, descent, min_offset; XImage *image, *rotated_image; Pixmap canvas_pix, rotated_pix; flocale_gstp_args gstp_args; char buf[4]; if (fws->str == NULL || len < 1) { return; } if (fws->flags.text_rotation == ROTATION_0) { return; /* should not happen */ } if (my_gc == None) { my_gc = fvwmlib_XCreateGC(dpy, fws->win, 0, NULL); } XCopyGC(dpy, fws->gc, GCForeground|GCBackground, my_gc); /* width and height (no shadow!) */ width = FlocaleTextWidth(flf, fws->str, len) - FLF_SHADOW_WIDTH(flf); height = flf->height - FLF_SHADOW_HEIGHT(flf); descent = flf->descent - FLF_SHADOW_DESCENT(flf);; if (width < 1) width = 1; if (height < 1) height = 1; /* glyph width and height of the normal text */ normal_w = width; normal_h = height; /* width in bytes */ normal_len = (normal_w - 1) / 8 + 1; /* create and clear the canvas */ canvas_pix = XCreatePixmap(dpy, fws->win, width, height, 1); if (font_gc == None) { font_gc = fvwmlib_XCreateGC(dpy, canvas_pix, 0, NULL); } XSetBackground(dpy, font_gc, 0); XSetForeground(dpy, font_gc, 0); XFillRectangle(dpy, canvas_pix, font_gc, 0, 0, width, height); /* draw the character center top right on canvas */ XSetForeground(dpy, font_gc, 1); if (flf->font != NULL) { XSetFont(dpy, font_gc, flf->font->fid); FlocaleFontStructDrawString(dpy, flf, canvas_pix, font_gc, 0, height - descent, fg, fgsh, has_fg_pixels, fws, len, True); } else if (flf->fontset != None) { XmbDrawString( dpy, canvas_pix, flf->fontset, font_gc, 0, height - descent, fws->e_str, len); } /* here take care of superimposing chars */ i = 0; if(comb_chars != NULL) { while(comb_chars[i].c.byte1 != 0 && comb_chars[i].c.byte2 != 0) { /* draw composing character on top of corresponding "real" character */ FlocaleWinString tmp_fws = *fws; int offset = pixel_pos[comb_chars[i].position]; int curr_len = FlocaleChar2bOneCharToUtf8( comb_chars[i].c, buf); int out_len; char *buf2 = FiconvUtf8ToCharset( dpy, flf->str_fc, (const char *)buf,curr_len); if(buf2 == NULL) { /* if conversion failed, combinational char is not representable in current charset */ /* just replace with empty string */ buf2 = (char *)safemalloc(sizeof(char)); buf2[0] = 0; } tmp_fws.e_str = buf2; tmp_fws.str2b = NULL; if(flf->fontset != None) { XmbDrawString(dpy, canvas_pix, flf->fontset, fws->gc, offset, height - descent, buf2, strlen(buf2)); } else if(flf->font != None) { if (FLC_ENCODING_TYPE_IS_UTF_8(flf->fc)) { tmp_fws.str2b = (XChar2b *) safemalloc(2 * sizeof(XChar2b)); tmp_fws.str2b[0] = comb_chars[i].c; tmp_fws.str2b[1].byte1 = 0; tmp_fws.str2b[1].byte2 = 0; out_len = 1; } else if (flf->flags.is_mb) { tmp_fws.str2b = FlocaleStringToString2b( dpy, flf, tmp_fws.e_str, curr_len, &out_len); } else { out_len = strlen(buf2); } XSetFont(dpy, font_gc, flf->font->fid); FlocaleFontStructDrawString( dpy, flf, canvas_pix, font_gc, offset, height - descent, fg, fgsh, has_fg_pixels, &tmp_fws, out_len, True); } free(buf2); if(tmp_fws.str2b != NULL) { free(tmp_fws.str2b); } i++; } } /* reserve memory for the first XImage */ normal_data = (unsigned char *)safemalloc(normal_len * normal_h); /* create depth 1 XImage */ if ((image = XCreateImage( dpy, Pvisual, 1, XYBitmap, 0, (char *)normal_data, normal_w, normal_h, 8, 0)) == NULL) { return; } image->byte_order = image->bitmap_bit_order = MSBFirst; /* extract character from canvas */ XGetSubImage( dpy, canvas_pix, 0, 0, normal_w, normal_h, 1, XYPixmap, image, 0, 0); image->format = XYBitmap; /* width, height of the rotated text */ if (fws->flags.text_rotation == ROTATION_180) { rotated_w = normal_w; rotated_h = normal_h; } else /* vertical text */ { rotated_w = normal_h; rotated_h = normal_w; } /* width in bytes */ rotated_len = (rotated_w - 1) / 8 + 1; /* reserve memory for the rotated image */ rotated_data = (unsigned char *)safecalloc(rotated_h * rotated_len, 1); /* create the rotated X image */ if ((rotated_image = XCreateImage( dpy, Pvisual, 1, XYBitmap, 0, (char *)rotated_data, rotated_w, rotated_h, 8, 0)) == NULL) { return; } rotated_image->byte_order = rotated_image->bitmap_bit_order = MSBFirst; /* map normal text data to rotated text data */ for (j = 0; j < rotated_h; j++) { for (i = 0; i < rotated_w; i++) { /* map bits ... */ if (fws->flags.text_rotation == ROTATION_270) val = normal_data[ i * normal_len + (normal_w - j - 1) / 8 ] & (128 >> ((normal_w - j - 1) % 8)); else if (fws->flags.text_rotation == ROTATION_180) val = normal_data[ (normal_h - j - 1) * normal_len + (normal_w - i - 1) / 8 ] & (128 >> ((normal_w - i - 1) % 8)); else /* ROTATION_90 */ val = normal_data[ (normal_h - i - 1) * normal_len + j / 8] & (128 >> (j % 8)); if (val) rotated_data[j * rotated_len + i / 8] |= (128 >> (i % 8)); } } /* create the character's bitmap and put the image on it */ rotated_pix = XCreatePixmap(dpy, fws->win, rotated_w, rotated_h, 1); XPutImage( dpy, rotated_pix, font_gc, rotated_image, 0, 0, 0, 0, rotated_w, rotated_h); /* free the image and data */ XDestroyImage(image); XDestroyImage(rotated_image); /* free pixmap and GC */ XFreePixmap(dpy, canvas_pix); /* x and y corrections: we fill a rectangle! */ min_offset = FlocaleGetMinOffset(flf, fws->flags.text_rotation); switch (fws->flags.text_rotation) { case ROTATION_90: /* CW */ xpfg = fws->x - min_offset; ypfg = fws->y; break; case ROTATION_180: xpfg = fws->x; ypfg = fws->y - min_offset + FLF_SHADOW_BOTTOM_SIZE(flf); break; case ROTATION_270: /* CCW */ xpfg = fws->x - min_offset; ypfg = fws->y; break; case ROTATION_0: default: xpfg = fws->x; ypfg = fws->y - min_offset; break; } xpsh = xpfg; ypsh = ypfg; /* write the image on the window */ XSetFillStyle(dpy, my_gc, FillStippled); XSetStipple(dpy, my_gc, rotated_pix); FlocaleInitGstpArgs(&gstp_args, flf, fws, xpfg, ypfg); if (flf->shadow_size != 0 && has_fg_pixels == True) { XSetForeground(dpy, my_gc, fgsh); while (FlocaleGetShadowTextPosition(&xpsh, &ypsh, &gstp_args)) { XSetTSOrigin(dpy, my_gc, xpsh, ypsh); XFillRectangle( dpy, fws->win, my_gc, xpsh, ypsh, rotated_w, rotated_h); } } xpsh = gstp_args.orig_x; ypsh = gstp_args.orig_y; XSetTSOrigin(dpy, my_gc, xpsh, ypsh); XFillRectangle(dpy, fws->win, my_gc, xpsh, ypsh, rotated_w, rotated_h); XFreePixmap(dpy, rotated_pix); return; } /* * Fonts info and checking */ static char *FlocaleGetFullNameOfFontStruct(Display *dpy, XFontStruct *font) { char *full_name = NULL; unsigned long value; if (XGetFontProperty(font, XA_FONT, &value)) { full_name = XGetAtomName(dpy, value); } return full_name; } static char *FlocaleGetCharsetOfFontStruct(Display *dpy, XFontStruct *font) { int i = 0; int count = 0; char *charset = NULL; char *full_name; full_name = FlocaleGetFullNameOfFontStruct(dpy, font); if (full_name == NULL) { return NULL; } while(full_name[i] != '\0' && count < 13) { if (full_name[i] == '-') { count++; } i++; } if (count != 13) { return NULL; } CopyString(&charset, full_name+i); XFree(full_name); return charset; } static char *FlocaleGetCharsetFromName(char *name) { int l,i,e; char *charset; l = strlen(name); i = l-1; while(i >= 0 && name[i] != '-') { i--; } if (i == 0 || i == l-1) { return NULL; } i--; e = i; while(i >= 0 && name[i] != '-') { i--; } if (i <= 0 || e == i) { return NULL; } CopyString(&charset, name + i + 1); return charset; } /* return NULL if it is not reasonable to load a FontSet. * Currently return name if it is reasonable to load a FontSet, but in the * future we may want to transform name for faster FontSet loading */ static char *FlocaleFixNameForFontSet(Display *dpy, char *name, char *module) { char *new_name; char *charset; XFontStruct *test_font = NULL; if (!name) { return NULL; } new_name = name; if (strchr(name, ',')) { /* tmp, do not handle "," separated list */ return name; } charset = FlocaleGetCharsetFromName(name); if (charset == NULL && !strchr(name, '*') && !strchr(name, '?')) { /* probably a font alias! */ if ((test_font = XLoadQueryFont(dpy, name))) { charset = FlocaleGetCharsetOfFontStruct(dpy, test_font); XFreeFont(dpy, test_font); } } if (charset != NULL) { if (!strchr(charset, '*') && !strchr(charset, '?') && !FlocaleCharsetIsCharsetXLocale(dpy, charset, module)) { /* if the charset is fully specified and do not match * one of the X locale charset */ new_name = NULL; #if 0 fprintf(stderr,"[%s][FlocaleGetFontSet]: WARNING -- " "Use of a non X locale charset '%s' when " "loading font: %s\n", (module)? module:"fvwmlibs", charset, name); #endif } free(charset); } return new_name; } /* * Fonts loading */ static FlocaleFont *FlocaleGetFftFont( Display *dpy, char *fontname, char *encoding, char *module) { FftFontType *fftf = NULL; FlocaleFont *flf = NULL; char *fn, *hints = NULL; hints = GetQuotedString(fontname, &fn, "/", NULL, NULL, NULL); if (fn == NULL) { fn = fft_fallback_font; } else if (*fn == '\0') { free(fn); fn = fft_fallback_font; } fftf = FftGetFont(dpy, fn, module); if (fftf == NULL) { if (fn != NULL && fn != fft_fallback_font) { free(fn); } return NULL; } flf = (FlocaleFont *)safemalloc(sizeof(FlocaleFont)); memset(flf, '\0', sizeof(FlocaleFont)); flf->count = 1; flf->fftf = *fftf; FlocaleCharsetSetFlocaleCharset(dpy, flf, hints, encoding, module); FftGetFontHeights( &flf->fftf, &flf->height, &flf->ascent, &flf->descent); FftGetFontWidths(flf, &flf->max_char_width); free(fftf); if (fn != NULL && fn != fft_fallback_font) { free(fn); } return flf; } static FlocaleFont *FlocaleGetFontSet( Display *dpy, char *fontname, char *encoding, char *module) { static int mc_errors = 0; FlocaleFont *flf = NULL; XFontSet fontset = NULL; char **ml; int mc,i; char *ds; XFontSetExtents *fset_extents; char *fn, *hints = NULL, *fn_fixed = NULL; hints = GetQuotedString(fontname, &fn, "/", NULL, NULL, NULL); if (*fn == '\0') { free(fn); fn = fn_fixed = mb_fallback_font; } else if (!(fn_fixed = FlocaleFixNameForFontSet(dpy, fn, module))) { if (fn != NULL && fn != mb_fallback_font) { free(fn); } return NULL; } if (!(fontset = XCreateFontSet(dpy, fn_fixed, &ml, &mc, &ds))) { if (fn_fixed && fn_fixed != fn) { free(fn_fixed); } if (fn != NULL && fn != mb_fallback_font) { free(fn); } return NULL; } if (mc > 0) { if (mc_errors <= FLOCALE_NUMBER_MISS_CSET_ERR_MSG) { mc_errors++; fprintf(stderr, "[%s][FlocaleGetFontSet]: (%s)" " Missing font charsets:\n", (module)? module: "fvwmlibs", fontname); for (i = 0; i < mc; i++) { fprintf(stderr, "%s", ml[i]); if (i < mc - 1) fprintf(stderr, ", "); } fprintf(stderr, "\n"); if (mc_errors == FLOCALE_NUMBER_MISS_CSET_ERR_MSG) { fprintf(stderr, "[%s][FlocaleGetFontSet]: No more" " missing charset reportings\n", (module)? module: "fvwmlibs"); } } XFreeStringList(ml); } flf = (FlocaleFont *)safemalloc(sizeof(FlocaleFont)); memset(flf, '\0', sizeof(FlocaleFont)); flf->count = 1; flf->fontset = fontset; FlocaleCharsetSetFlocaleCharset(dpy, flf, hints, encoding, module); fset_extents = XExtentsOfFontSet(fontset); flf->height = fset_extents->max_ink_extent.height; flf->ascent = - fset_extents->max_ink_extent.y; flf->descent = fset_extents->max_ink_extent.height + fset_extents->max_ink_extent.y; flf->max_char_width = fset_extents->max_ink_extent.width; if (fn_fixed && fn_fixed != fn) { free(fn_fixed); } if (fn != NULL && fn != mb_fallback_font) { free(fn); } return flf; } static FlocaleFont *FlocaleGetFont( Display *dpy, char *fontname, char *encoding, char *module) { XFontStruct *font = NULL; FlocaleFont *flf; char *str,*fn,*tmp; char *hints = NULL; hints = GetQuotedString(fontname, &tmp, "/", NULL, NULL, NULL); str = GetQuotedString(tmp, &fn, ",", NULL, NULL, NULL); while (!font && fn) { if (*fn == '\0') { free(fn); fn = fallback_font; } font = XLoadQueryFont(dpy, fn); if (fn != NULL && fn != fallback_font) { free(fn); fn = NULL; } if (!font && str && *str) { str = GetQuotedString(str, &fn, ",", NULL, NULL, NULL); } } if (font == NULL) { if (fn != NULL && fn != fallback_font) { free(fn); } if (tmp != NULL) { free(tmp); } return NULL; } flf = (FlocaleFont *)safemalloc(sizeof(FlocaleFont)); memset(flf, '\0', sizeof(FlocaleFont)); flf->count = 1; flf->fontset = None; flf->fftf.fftfont = NULL; flf->font = font; FlocaleCharsetSetFlocaleCharset(dpy, flf, hints, encoding, module); flf->height = font->max_bounds.ascent + font->max_bounds.descent; flf->ascent = font->max_bounds.ascent; flf->descent = font->max_bounds.descent; flf->max_char_width = font->max_bounds.width; if (flf->font->max_byte1 > 0) flf->flags.is_mb = True; if (fn != NULL && fn != fallback_font) { free(fn); } if (tmp != NULL) { free(tmp); } return flf; } static FlocaleFont *FlocaleGetFontOrFontSet( Display *dpy, char *fontname, char *encoding, char *fullname, char *module) { FlocaleFont *flf = NULL; if (fontname && strlen(fontname) > 3 && strncasecmp("xft:", fontname, 4) == 0) { if (FftSupport) { flf = FlocaleGetFftFont( dpy, fontname+4, encoding, module); } if (flf) { CopyString(&flf->name, fullname); } return flf; } if (flf == NULL && Flocale != NULL && fontname) { flf = FlocaleGetFontSet(dpy, fontname, encoding, module); } if (flf == NULL && fontname) { flf = FlocaleGetFont(dpy, fontname, encoding, module); } if (flf && fontname) { if (StrEquals(fullname, mb_fallback_font)) { flf->name = mb_fallback_font; } else if (StrEquals(fullname, fallback_font)) { flf->name = fallback_font; } else { CopyString(&flf->name, fullname); } return flf; } return NULL; } /* * locale local functions */ static void FlocaleSetlocaleForX( int category, const char *locale, const char *module) { if ((Flocale = setlocale(category, locale)) == NULL) { fprintf(stderr, "[%s][%s]: ERROR -- Cannot set locale. Please check" " your $LC_CTYPE or $LANG.\n", (module == NULL)? "" : module, "FlocaleSetlocaleForX"); return; } if (!XSupportsLocale()) { fprintf(stderr, "[%s][%s]: WARNING -- X does not support locale %s\n", (module == NULL)? "": module, "FlocaleSetlocaleForX", Flocale); Flocale = NULL; } } /* ---------------------------- interface functions ------------------------ */ /* * locale initialisation */ void FlocaleInit( int category, const char *locale, const char *modifiers, const char *module) { FlocaleSetlocaleForX(category, locale, module); if (Flocale == NULL) return; if (modifiers != NULL && (Fmodifiers = XSetLocaleModifiers(modifiers)) == NULL) { fprintf(stderr, "[%s][%s]: WARNING -- Cannot set locale modifiers\n", (module == NULL)? "": module, "FlocaleInit"); } #if FLOCALE_DEBUG_SETLOCALE fprintf(stderr,"[%s][FlocaleInit] locale: %s, modifier: %s\n", module, Flocale, Fmodifiers); #endif } /* * fonts loading */ char *prefix_list[] = { "Shadow=", "StringEncoding=", NULL }; FlocaleFont *FlocaleLoadFont(Display *dpy, char *fontname, char *module) { FlocaleFont *flf = FlocaleFontList; Bool ask_default = False; char *t; char *str, *opt_str, *encoding= NULL, *fn = NULL; int shadow_size = 0; int shadow_offset = 0; int shadow_dir = MULTI_DIR_SE; int i; /* removing quoting for modules */ if (fontname && (t = strchr("\"'`", *fontname))) { char c = *t; fontname++; if (fontname[strlen(fontname)-1] == c) fontname[strlen(fontname)-1] = 0; } if (fontname == NULL || *fontname == 0) { ask_default = True; fontname = mb_fallback_font; } while (flf) { char *c1, *c2; for (c1 = fontname, c2 = flf->name; *c1 && *c2; ++c1, ++c2) { if (*c1 != *c2) { break; } } if (!*c1 && !*c2) { flf->count++; return flf; } flf = flf->next; } /* not cached load the font as a ";" separated list */ /* But first see if we have a shadow relief and/or an encoding */ str = fontname; while ((i = GetTokenIndex(str, prefix_list, -1, &str)) > -1) { str = GetQuotedString(str, &opt_str, ":", NULL, NULL, NULL); switch(i) { case 0: /* shadow= */ FlocaleParseShadow( opt_str, &shadow_size, &shadow_offset, &shadow_dir, fontname, module); break; case 1: /* encoding= */ if (encoding != NULL) { free(encoding); encoding = NULL; } if (opt_str && *opt_str) { CopyString(&encoding, opt_str); } break; default: break; } if (opt_str != NULL) free(opt_str); } if (str && *str) { str = GetQuotedString(str, &fn, ";", NULL, NULL, NULL); } else { fn = mb_fallback_font; } while (!flf && (fn && *fn)) { flf = FlocaleGetFontOrFontSet( dpy, fn, encoding, fontname, module); if (fn != NULL && fn != mb_fallback_font && fn != fallback_font) { free(fn); fn = NULL; } if (!flf && str && *str) { str = GetQuotedString(str, &fn, ";", NULL, NULL, NULL); } } if (fn != NULL && fn != mb_fallback_font && fn != fallback_font) { free(fn); } if (flf == NULL) { /* loading failed, try default font */ if (!ask_default) { fprintf(stderr,"[%s][FlocaleLoadFont]: " "WARNING -- can't load font '%s'," " trying default:\n", (module)? module: "fvwmlibs", fontname); } else { /* we already tried default fonts: try again? yes */ } if (Flocale != NULL) { if (!ask_default) { fprintf(stderr, "\t%s\n", mb_fallback_font); } if ((flf = FlocaleGetFontSet( dpy, mb_fallback_font, NULL, module)) != NULL) { flf->name = mb_fallback_font; } } if (flf == NULL) { if (!ask_default) { fprintf(stderr,"\t%s\n", fallback_font); } if ((flf = FlocaleGetFont( dpy, fallback_font, NULL, module)) != NULL) { flf->name = fallback_font; } else if (!ask_default) { fprintf(stderr, "[%s][FlocaleLoadFont]:" " ERROR -- can't load font.\n", (module)? module: "fvwmlibs"); } else { fprintf(stderr, "[%s][FlocaleLoadFont]: ERROR" " -- can't load default font:\n", (module)? module: "fvwmlibs"); fprintf(stderr, "\t%s\n", mb_fallback_font); fprintf(stderr, "\t%s\n", fallback_font); } } } if (flf != NULL) { if (shadow_size > 0) { flf->shadow_size = shadow_size; flf->flags.shadow_dir = shadow_dir; flf->shadow_offset = shadow_offset; flf->descent += FLF_SHADOW_DESCENT(flf); flf->ascent += FLF_SHADOW_ASCENT(flf); flf->height += FLF_SHADOW_HEIGHT(flf); flf->max_char_width += FLF_SHADOW_WIDTH(flf); } if (flf->fc == FlocaleCharsetGetUnknownCharset()) { fprintf(stderr,"[%s][FlocaleLoadFont]: " "WARNING -- Unknown charset for font\n\t'%s'\n", (module)? module: "fvwmlibs", flf->name); flf->fc = FlocaleCharsetGetDefaultCharset(dpy, module); } else if (flf->str_fc == FlocaleCharsetGetUnknownCharset() && (encoding != NULL || (FftSupport && flf->fftf.fftfont != NULL && flf->fftf.str_encoding != NULL))) { fprintf(stderr,"[%s][FlocaleLoadFont]: " "WARNING -- Unknown string encoding for font\n" "\t'%s'\n", (module)? module: "fvwmlibs", flf->name); } if (flf->str_fc == FlocaleCharsetGetUnknownCharset()) { flf->str_fc = FlocaleCharsetGetDefaultCharset(dpy, module); } flf->next = FlocaleFontList; FlocaleFontList = flf; } if (encoding != NULL) { free(encoding); } return flf; } void FlocaleUnloadFont(Display *dpy, FlocaleFont *flf) { FlocaleFont *list = FlocaleFontList; int i = 0; if (!flf) { return; } /* Remove a weight, still too heavy? */ if (--(flf->count) > 0) { return; } if (flf->name != NULL && !StrEquals(flf->name, mb_fallback_font) && !StrEquals(flf->name, fallback_font)) { free(flf->name); } if (FftSupport && flf->fftf.fftfont != NULL) { FftFontClose(dpy, flf->fftf.fftfont); if (flf->fftf.fftfont_rotated_90 != NULL) FftFontClose(dpy, flf->fftf.fftfont_rotated_90); if (flf->fftf.fftfont_rotated_180 != NULL) FftFontClose(dpy, flf->fftf.fftfont_rotated_180); if (flf->fftf.fftfont_rotated_270 != NULL) FftFontClose(dpy, flf->fftf.fftfont_rotated_270); } if (flf->fontset != NULL) { XFreeFontSet(dpy, flf->fontset); } if (flf->font != NULL) { XFreeFont(dpy, flf->font); } if (flf->flags.must_free_fc) { if (flf->fc->x) free(flf->fc->x); if (flf->fc->bidi) free(flf->fc->bidi); if (flf->fc->locale != NULL) { while (FLC_GET_LOCALE_CHARSET(flf->fc,i) != NULL) { free(FLC_GET_LOCALE_CHARSET(flf->fc,i)); i++; } free(flf->fc->locale); } free(flf->fc); } /* Link it out of the list (it might not be there) */ if (flf == list) /* in head? simple */ { FlocaleFontList = flf->next; } else { while (list && list->next != flf) { /* fast forward until end or found */ list = list->next; } /* not end? means we found it in there, possibly at end */ if (list) { /* link around it */ list->next = flf->next; } } free(flf); } /* * Width and Drawing Text */ void FlocaleInitGstpArgs( flocale_gstp_args *args, FlocaleFont *flf, FlocaleWinString *fws, int start_x, int start_y) { args->step = 0; args->offset = flf->shadow_offset + 1; args->outer_offset = flf->shadow_offset + flf->shadow_size; args->size = flf->shadow_size; args->sdir = flf->flags.shadow_dir; switch (fws->flags.text_rotation) { case ROTATION_270: /* CCW */ args->orig_x = start_x + FLF_SHADOW_UPPER_SIZE(flf); args->orig_y = start_y + FLF_SHADOW_RIGHT_SIZE(flf); break; case ROTATION_180: args->orig_x = start_x + FLF_SHADOW_RIGHT_SIZE(flf); args->orig_y = start_y; break; case ROTATION_90: /* CW */ args->orig_x = start_x + FLF_SHADOW_BOTTOM_SIZE(flf); args->orig_y = start_y + FLF_SHADOW_LEFT_SIZE(flf); break; case ROTATION_0: default: args->orig_x = start_x + FLF_SHADOW_LEFT_SIZE(flf); args->orig_y = start_y; break; } args->rot = fws->flags.text_rotation; return; } Bool FlocaleGetShadowTextPosition( int *x, int *y, flocale_gstp_args *args) { if (args->step == 0) { args->direction = MULTI_DIR_NONE; args->inter_step = 0; } if ((args->step == 0 || args->inter_step >= args->num_inter_steps) && args->size != 0) { /* setup a new direction */ args->inter_step = 0; gravity_get_next_multi_dir(args->sdir, &args->direction); if (args->direction == MULTI_DIR_C) { int size; size = 2 * (args->outer_offset) + 1; args->num_inter_steps = size * size; } else { args->num_inter_steps = args->size; } } if (args->direction == MULTI_DIR_NONE || args->size == 0) { *x = args->orig_x; *y = args->orig_y; return False; } if (args->direction == MULTI_DIR_C) { int tx; int ty; int size; int is_finished; size = 2 * (args->outer_offset) + 1; tx = args->inter_step % size - args->outer_offset; ty = args->inter_step / size - args->outer_offset; for (is_finished = 0; ty <= args->outer_offset; ty++, tx = -args->outer_offset) { for (; tx <= args->outer_offset; tx++) { if (tx <= -args->offset || tx >= args->offset || ty <= -args->offset || ty >= args->offset) { is_finished = 1; break; } } if (is_finished) { break; } } args->inter_step = (tx + args->outer_offset) + (ty + args->outer_offset) * size; if (!is_finished) { tx = 0; ty = 0; } *x = args->orig_x + tx; *y = args->orig_y + ty; } else if (args->inter_step > 0) { /* into a directional drawing */ (*x) += args->x_sign; (*y) += args->y_sign; } else { direction_t dir; direction_t dir_x; direction_t dir_y; dir = gravity_multi_dir_to_dir(args->direction); gravity_split_xy_dir(&dir_x, &dir_y, dir); args->x_sign = gravity_dir_to_sign_one_axis(dir_x); args->y_sign = gravity_dir_to_sign_one_axis(dir_y); gravity_rotate_xy( args->rot, args->x_sign, args->y_sign, &args->x_sign, &args->y_sign); *x = args->orig_x + args->x_sign * args->offset; *y = args->orig_y + args->y_sign * args->offset; } args->inter_step++; args->step++; return True; } void FlocaleDrawString( Display *dpy, FlocaleFont *flf, FlocaleWinString *fws, unsigned long flags) { int len; Bool do_free = False; Pixel fg = 0, fgsh = 0; Bool has_fg_pixels = False; flocale_gstp_args gstp_args; superimpose_char_t *comb_chars = NULL; char *curr_str; int char_len; /* length in number of chars */ int *pixel_pos = NULL; int i; int j; char buf[4]; int curr_pixel_pos; int curr_len; if (!fws || !fws->str) { return; } if (flags & FWS_HAVE_LENGTH) { len = fws->len; } else { len = strlen(fws->str); } /* encode the string */ FlocaleEncodeWinString( dpy, flf, fws, &do_free, &len, &comb_chars, NULL); curr_str = fws->e_str; for(char_len = 0, i = 0 ; i < len && curr_str[i] != 0 ; char_len++, i += curr_len) { curr_len = FlocaleStringNumberOfBytes(flf, curr_str + i); } /* for superimposition calculate the character positions in pixels */ if (comb_chars != NULL && ( comb_chars[0].c.byte1 != 0 || comb_chars[0].c.byte2 != 0)) { /* the second condition is actually redundant, but there for clarity, ending at 0 is what's expected in a correct string */ pixel_pos = (int *)safemalloc( (char_len != 0 ? char_len : 1) * sizeof(int)); /* if there is 0 bytes in the encoded string, there might still be combining character to draw (at position 0) */ if(char_len == 0) { pixel_pos[0] = 0; } for( i = 0, curr_pixel_pos = 0 ; i < char_len ; i++, curr_str += curr_len) { curr_len = FlocaleStringNumberOfBytes(flf, curr_str); for (j = 0 ; j < curr_len ; j++) { buf[j] = curr_str[j]; } buf[j] = 0; pixel_pos[i] = curr_pixel_pos; /* need to compensate for shadow width (if any) */ curr_pixel_pos += FlocaleTextWidth(flf, buf, curr_len) - FLF_SHADOW_WIDTH(flf); } } /* get the pixels */ if (fws->flags.has_colorset) { fg = fws->colorset->fg; fgsh = fws->colorset->fgsh; has_fg_pixels = True; } else if (flf->shadow_size != 0) { XGCValues xgcv; if (XGetGCValues(dpy, fws->gc, GCForeground, &xgcv) != 0) { fg = xgcv.foreground; } else { fg = PictureBlackPixel(); } fgsh = GetShadow(fg); has_fg_pixels = True; } if(flf->font != None && (FLC_ENCODING_TYPE_IS_UTF_8(flf->fc) || flf->flags.is_mb)) { /* in this case, length is number of 2-byte chars */ len = char_len; } if (fws->flags.text_rotation != ROTATION_0 && flf->fftf.fftfont == NULL) { /* pass in information to perform superimposition */ FlocaleRotateDrawString( dpy, flf, fws, fg, fgsh, has_fg_pixels, len, comb_chars, pixel_pos); } else if (FftSupport && flf->fftf.fftfont != NULL) { FftDrawString( dpy, flf, fws, fg, fgsh, has_fg_pixels, len, flags); } else if (flf->fontset != None) { int xt = fws->x; int yt = fws->y; FlocaleInitGstpArgs(&gstp_args, flf, fws, fws->x, fws->y); if (flf->shadow_size != 0) { XSetForeground(dpy, fws->gc, fgsh); while (FlocaleGetShadowTextPosition( &xt, &yt, &gstp_args)) { XmbDrawString( dpy, fws->win, flf->fontset, fws->gc, xt, yt, fws->e_str, len); } } if (has_fg_pixels == True) { XSetForeground(dpy, fws->gc, fg); } xt = gstp_args.orig_x; yt = gstp_args.orig_y; XmbDrawString( dpy, fws->win, flf->fontset, fws->gc, xt, yt, fws->e_str, len); } else if (flf->font != None) { FlocaleFontStructDrawString( dpy, flf, fws->win, fws->gc, fws->x, fws->y, fg, fgsh, has_fg_pixels, fws, len, False); } /* here take care of superimposing chars */ i = 0; if (comb_chars != NULL) { while(comb_chars[i].c.byte1 != 0 && comb_chars[i].c.byte2 != 0) { /* draw composing character on top of corresponding "real" character */ FlocaleWinString tmp_fws = *fws; int offset = pixel_pos[comb_chars[i].position]; char *buf2; int out_len; curr_len = FlocaleChar2bOneCharToUtf8(comb_chars[i].c, buf); buf2 = FiconvUtf8ToCharset( dpy, flf->str_fc, (const char *)buf, curr_len); if(buf2 == NULL) { /* if conversion failed, combinational char is not representable in current charset */ /* just replace with empty string */ buf2 = (char *)safemalloc(sizeof(char)); buf2[0] = 0; } tmp_fws.e_str = buf2; tmp_fws.str2b = NULL; if(FftSupport && flf->fftf.fftfont != NULL) { tmp_fws.x = fws->x + offset; FftDrawString( dpy, flf, &tmp_fws, fg, fgsh, has_fg_pixels, strlen(buf2), flags); } else if(flf->fontset != None) { int xt = fws->x; int yt = fws->y; FlocaleInitGstpArgs( &gstp_args, flf, fws, fws->x, fws->y); if (flf->shadow_size != 0) { XSetForeground(dpy, fws->gc, fgsh); while (FlocaleGetShadowTextPosition( &xt, &yt, &gstp_args)) { XmbDrawString( dpy, fws->win, flf->fontset, fws->gc, xt, yt, buf2, strlen(buf2)); } } XSetForeground(dpy, fws->gc, fg); xt = gstp_args.orig_x; yt = gstp_args.orig_y; XmbDrawString( dpy, fws->win, flf->fontset, fws->gc, xt + offset, yt, buf2, strlen(buf2)); } else if (flf->font != None) { if (FLC_ENCODING_TYPE_IS_UTF_8(flf->fc)) { tmp_fws.str2b = (XChar2b *) safemalloc(2 * sizeof(XChar2b)); tmp_fws.str2b[0] = comb_chars[i].c; tmp_fws.str2b[1].byte1 = 0; tmp_fws.str2b[1].byte2 = 0; out_len = 1; /*tmp_fws.str2b = FlocaleUtf8ToUnicodeStr2b( tmp_fws.e_str, curr_len, &out_len);*/ } else if (flf->flags.is_mb) { tmp_fws.str2b = FlocaleStringToString2b( dpy, flf, tmp_fws.e_str, curr_len, &out_len); } else { out_len = strlen(buf2); } FlocaleFontStructDrawString( dpy, flf, fws->win, fws->gc, fws->x + offset, fws->y, fg, fgsh, has_fg_pixels, &tmp_fws, out_len, False); } free(buf2); if(tmp_fws.str2b != NULL) { free(tmp_fws.str2b); } i++; } } if (do_free) { if (fws->e_str != NULL) { free(fws->e_str); fws->e_str = NULL; } } if (fws->str2b != NULL) { free(fws->str2b); fws->str2b = NULL; } if(comb_chars != NULL) { free(comb_chars); if(pixel_pos) free(pixel_pos); } return; } void FlocaleDrawUnderline( Display *dpy, FlocaleFont *flf, FlocaleWinString *fws, int offset) { int off1, off2, y, x_s, x_e; superimpose_char_t *comb_chars = NULL; int *l_to_v = NULL; Bool do_free = True; int len = strlen(fws->str); int l_coffset; int v_coffset; int voffset; if (fws == NULL || fws->str == NULL) { return; } /* need to encode the string first to get BIDI and combining chars */ FlocaleEncodeWinString(dpy, flf, fws, &do_free, &len, &comb_chars, &l_to_v); /* we don't need this, only interested in char mapping */ free(comb_chars); /* now calculate char offset (in bytes) in visual string corresponding to coffset */ /* calculate absolute position in string (in characters) */ l_coffset = FlocaleStringByteToCharOffset(flf, fws->str, offset); /* map to an offset in the visual string */ v_coffset = l_to_v[l_coffset]; /* calculate byte offset into visual string */ voffset = FlocaleStringCharToByteOffset(flf, fws->e_str, v_coffset); off1 = FlocaleTextWidth(flf, fws->e_str, voffset) + ((voffset == 0)? FLF_SHADOW_LEFT_SIZE(flf) : - FLF_SHADOW_RIGHT_SIZE(flf) ); off2 = FlocaleTextWidth(flf, fws->e_str + voffset, FlocaleStringNumberOfBytes(flf, fws->e_str + voffset)) - FLF_SHADOW_WIDTH(flf) - 1 + off1; y = fws->y + 2; x_s = fws->x + off1; x_e = fws->x + off2; /* No shadow */ XDrawLine(dpy, fws->win, fws->gc, x_s, y, x_e, y); /* free encoded string if it isn't the same as input string */ if(fws->e_str != fws->str) { free(fws->e_str); fws->e_str = NULL; } if(fws->str2b != NULL) { free(fws->str2b); fws->str2b = NULL; } free(l_to_v); return; } int FlocaleTextWidth(FlocaleFont *flf, char *str, int sl) { int result = 0; char *tmp_str; int new_l,do_free; superimpose_char_t *comb_chars = NULL; if (!str || sl == 0) return 0; if (sl < 0) { /* a vertical string: nothing to do! */ sl = -sl; } /* FIXME */ /* to avoid eccesive calls iconv (slow in Solaris 8) don't bother to encode if string is one byte when drawing a string this function is used to calculate position of each character (for superimposition) */ if(sl == 1) { tmp_str = str; new_l = sl; do_free = False; } else { tmp_str = FlocaleEncodeString( Pdpy, flf, str, &do_free, sl, &new_l, NULL, &comb_chars, NULL); } /* if we get zero-length, check to to see if there if there's any combining chars, if so use an imagninary space as a "base character" */ if (strlen(tmp_str) == 0 && comb_chars && (comb_chars[0].c.byte1 != 0 || comb_chars[0].c.byte2 != 0)) { if(do_free) { free(tmp_str); } if(comb_chars) { free(comb_chars); } return FlocaleTextWidth(flf, " ", 1); } else if (FftSupport && flf->fftf.fftfont != NULL) { result = FftTextWidth(flf, tmp_str, new_l); } else if (flf->fontset != None) { result = XmbTextEscapement(flf->fontset, tmp_str, new_l); } else if (flf->font != None) { if (FLC_ENCODING_TYPE_IS_UTF_8(flf->fc) || flf->flags.is_mb) { XChar2b *str2b; int nl; if (FLC_ENCODING_TYPE_IS_UTF_8(flf->fc)) str2b = FlocaleUtf8ToUnicodeStr2b( tmp_str, new_l, &nl); else str2b = FlocaleStringToString2b( Pdpy, flf, tmp_str, new_l, &nl); if (str2b != NULL) { result = XTextWidth16(flf->font, str2b, nl); free(str2b); } } else { result = XTextWidth(flf->font, tmp_str, new_l); } } if (do_free) { free(tmp_str); } if (comb_chars) { free(comb_chars); } return result + ((result != 0)? FLF_SHADOW_WIDTH(flf):0); } int FlocaleGetMinOffset( FlocaleFont *flf, rotation_t rotation) { int min_offset; #ifdef FFT_BUGGY_FREETYPE switch(rotation) { case ROTATION_270: case ROTATION_180: /* better than descent */ min_offset = (flf->descent + flf->height - flf->ascent)/2; break; case ROTATION_0: case ROTATION_90: default: /* better than ascent */ min_offset = (flf->ascent + flf->height - flf->descent)/2; break; } #else switch(rotation) { case ROTATION_180: case ROTATION_90: /* better than descent */ min_offset = (flf->descent + flf->height - flf->ascent)/2; break; case ROTATION_270: case ROTATION_0: default: /* better than ascent */ min_offset = (flf->ascent + flf->height - flf->descent)/2; break; } #endif return min_offset; } void FlocaleAllocateWinString(FlocaleWinString **pfws) { *pfws = (FlocaleWinString *)safemalloc(sizeof(FlocaleWinString)); memset(*pfws, '\0', sizeof(FlocaleWinString)); } /* * Text properties */ void FlocaleGetNameProperty( Status (func)(Display *, Window, XTextProperty *), Display *dpy, Window w, FlocaleNameString *ret_name) { char **list; int num; XTextProperty text_prop; list = NULL; if (func(dpy, w, &text_prop) == 0) { return; } if (text_prop.encoding == XA_STRING) { /* STRING encoding, use this as it is */ ret_name->name = (char *)text_prop.value; ret_name->name_list = NULL; return; } /* not STRING encoding, try to convert XA_COMPOUND_TEXT */ if (XmbTextPropertyToTextList(dpy, &text_prop, &list, &num) >= Success && num > 0 && *list) { /* Does not consider the conversion is REALLY succeeded: * XmbTextPropertyToTextList return 0 (== Success) on success, * a negative int if it fails (and in this case we are not * here), the number of unconvertible char on "partial" * success*/ XFree(text_prop.value); /* return of XGetWM(Icon)Name() */ ret_name->name = *list; ret_name->name_list = list; } else { if (list) { XFreeStringList(list); } ret_name->name = (char *)text_prop.value; ret_name->name_list = NULL; } } void FlocaleFreeNameProperty(FlocaleNameString *ptext) { if (ptext->name_list != NULL) { if (ptext->name != NULL && ptext->name != *ptext->name_list) XFree(ptext->name); XFreeStringList(ptext->name_list); ptext->name_list = NULL; } else if (ptext->name != NULL /* Sorry, this is pretty ugly. in fvwm/events.c we have: FlocaleNameString new_name = { NoName, NULL }; NoName is a global extern I don't want to add to to this libary module. So, this check comes close enough: */ && strcmp("Untitled",ptext->name) != 0) { XFree(ptext->name); } ptext->name = NULL; return; } Bool FlocaleTextListToTextProperty( Display *dpy, char **list, int count, XICCEncodingStyle style, XTextProperty *text_prop_return) { int ret = False; if (Flocale != NULL) { ret = XmbTextListToTextProperty( dpy, list, count, style, text_prop_return); if (ret == XNoMemory) { ret = False; } else { /* ret == Success or the number of unconvertible * characters. ret should be != XLocaleNotSupported * because in this case Flocale == NULL */ ret = True; } } if (!ret) { if (XStringListToTextProperty( list, count, text_prop_return) == 0) { ret = False; } else { ret = True; } } return ret; } /* * Info */ void FlocalePrintLocaleInfo(Display *dpy, int verbose) { FlocaleFont *flf = FlocaleFontList; int count = 0; FlocaleCharset *cs; fflush(stderr); fflush(stdout); fprintf(stderr,"fvwm info on locale:\n"); fprintf(stderr," locale: %s, Modifier: %s\n", (Flocale)? Flocale:"", (Fmodifiers)? Fmodifiers:""); cs = FlocaleCharsetGetDefaultCharset(dpy, NULL); fprintf(stderr," Default Charset: X: %s, Iconv: %s, Bidi: %s\n", cs->x, (cs->iconv_index >= 0)? cs->locale[cs->iconv_index]:"Not defined", (cs->bidi)? "Yes":"No"); FlocaleCharsetPrintXOMInfo(); while (flf) { count++; flf = flf->next; } fprintf(stderr," Number of loaded font: %i\n", count); if (verbose) { count = 0; flf = FlocaleFontList; while(flf) { cs = flf->fc; fprintf(stderr," * Font number %i\n", count); fprintf(stderr," fvwm info:\n"); fprintf(stderr," Name: %s\n", (flf->name)? flf->name:""); fprintf(stderr," Cache count: %i\n", flf->count); fprintf(stderr," Type: "); if (flf->font) { fprintf(stderr,"FontStruct\n"); } else if (flf->fontset) { fprintf(stderr,"FontSet\n"); } else { fprintf(stderr,"XftFont\n"); } fprintf(stderr, " Charset: X: %s, Iconv: %s, " "Bidi: %s\n", cs->x, (cs->iconv_index >= 0)? cs->locale[cs->iconv_index]:"Not defined", (cs->bidi)? "Yes":"No"); fprintf(stderr," height: %i, ascent: %i, " "descent: %i\n", flf->height, flf->ascent, flf->descent); fprintf(stderr," shadow size: %i, " "shadow offset: %i, shadow direction:%i\n", flf->shadow_size, flf->shadow_offset, flf->flags.shadow_dir); if (verbose >= 2) { if (flf->fftf.fftfont != NULL) { FftFontType *fftf; fftf = &flf->fftf; fprintf(stderr, " Xft info:\n" " - Vertical font:"); FftPrintPatternInfo( fftf->fftfont, False); fprintf(stderr, " " "- Rotated font 90:"); if (fftf->fftfont_rotated_90) FftPrintPatternInfo( fftf-> fftfont_rotated_90, True); else fprintf(stderr, " None\n"); fprintf(stderr, " " "- Rotated font 270:"); if (fftf->fftfont_rotated_270) FftPrintPatternInfo( fftf-> fftfont_rotated_270, True); else fprintf(stderr, " None\n"); fprintf(stderr, " " "- Rotated font 180:"); if (fftf->fftfont_rotated_180) FftPrintPatternInfo( fftf-> fftfont_rotated_180, True); else fprintf(stderr, " None\n"); } else if (flf->font != NULL) { char *full_name; full_name = FlocaleGetFullNameOfFontStruct( dpy, flf->font); fprintf(stderr, " X info:\n" " %s\n", (full_name)? full_name:"?"); if (full_name != NULL) { XFree(full_name); } } else if (flf->fontset != NULL) { int n,i; XFontStruct **font_struct_list; char **font_name_list; fprintf(stderr, " X info:\n"); n = XFontsOfFontSet( flf->fontset, &font_struct_list, &font_name_list); for(i = 0; i < n; i++) { fprintf(stderr, " %s\n", font_name_list[i]); } } } count++; flf = flf->next; } } } fvwm-2.7.0/libs/Module.c0000644000175000017500000002601414147024700011744 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ** Module.c: code for modules to communicate with fvwm */ #include "config.h" #include #include #include "libs/defaults.h" #include "Module.h" #include "Parse.h" /* * Loop until count bytes are read, unless an error or end-of-file * condition occurs. */ inline static int positive_read(int fd, char *buf, int count) { while (count > 0) { int n_read = read(fd, buf, count); if (n_read <= 0) { return -1; } buf += n_read; count -= n_read; } return 0; } /* * Reads a single packet of info from fvwm. * The packet is stored in static memory that is reused during * the next call. */ FvwmPacket *ReadFvwmPacket(int fd) { static unsigned long buffer[FvwmPacketMaxSize]; FvwmPacket *packet = (FvwmPacket *)buffer; unsigned long length; /* The `start flag' value supposedly exists to synchronize the * fvwm -> module communication. However, the communication goes * through a pipe. I don't see how any data could ever get lost, * so how would fvwm & the module become unsynchronized? */ do { if (positive_read(fd, (char *)buffer, sizeof(unsigned long)) < 0) { return NULL; } } while (packet->start_pattern != START_FLAG); /* Now read the rest of the header */ if (positive_read(fd, (char *)(&buffer[1]), 3 * sizeof(unsigned long)) < 0) { return NULL; } length = FvwmPacketBodySize_byte(*packet); if (length > FvwmPacketMaxSize_byte - FvwmPacketHeaderSize_byte) { /* packet too long */ return NULL; } /* Finally, read the body, and we're done */ if (positive_read(fd, (char *)(&buffer[4]), length) < 0) { return NULL; } return packet; } /* * * SendFinishedStartupNotification - informs fvwm that the module has * finished its startup procedures and is fully operational now. * */ void SendFinishedStartupNotification(int *fd) { SendText(fd, ModuleFinishedStartupResponse, 0); } /* * * SendUnlockNotification - informs fvwm that the module has * finished it's procedures and fvwm may proceed. * */ void SendUnlockNotification(int *fd) { SendText(fd, ModuleUnlockResponse, 0); } /* * * SendQuitNotification - informs fvwm that the module has * finished and may be killed. * */ static unsigned long ModuleContinue = 1; void SendQuitNotification(int *fd) { ModuleContinue = 0; SendText(fd, ModuleUnlockResponse, 0); /* unlock just in case */ } /* * * SendText - Sends arbitrary text/command back to fvwm * */ void SendText(int *fd, const char *message, unsigned long window) { char *p, *buf; unsigned int len; if (!message) { return; } /* Get enough memory to store the entire message. */ len = strlen(message); p = buf = alloca(sizeof(long) * (3 + 1 + (len / sizeof(long)))); /* Put the message in the buffer, and... */ *((unsigned long *)p) = window; p += sizeof(unsigned long); *((unsigned long *)p) = len; p += sizeof(unsigned long); strcpy(p, message); p += len; memcpy(p, &ModuleContinue, sizeof(unsigned long)); p += sizeof(unsigned long); /* Send it! */ { int n; n = write(fd[0], buf, p - buf); (void)n; } } /* * * SendFvwmPipe - Sends message to fvwm: The message is a comma-delimited * string separated into its component sections and sent one by one to fvwm. * It is discouraged to use this function with a "synchronous" module. * (Form FvwmIconMan) * */ void SendFvwmPipe(int *fd, const char *message, unsigned long window) { const char *hold = message; const char *temp; while ((temp = strchr(hold, ',')) != NULL) { char *temp_msg = (char*)alloca(temp - hold + 1); strncpy(temp_msg, hold, (temp - hold)); temp_msg[(temp - hold)] = '\0'; hold = temp + 1; SendText(fd, temp_msg, window); } /* * Send the last part of the string : * we don't need to copy this into separate * storage because we don't need to modify it ... * * NOTE: this makes this second call to SendText() * distinct from the first call. Two calls is * cleaner than hacking the loop to make only * one call. */ SendText(fd, hold, window); } void SetMessageMask(int *fd, unsigned long mask) { char set_mask_mesg[50]; sprintf(set_mask_mesg, "SET_MASK %lu", mask); SendText(fd, set_mask_mesg, 0); } void SetSyncMask(int *fd, unsigned long mask) { char set_syncmask_mesg[50]; sprintf(set_syncmask_mesg, "SET_SYNC_MASK %lu", mask); SendText(fd, set_syncmask_mesg, 0); } void SetNoGrabMask(int *fd, unsigned long mask) { char set_nograbmask_mesg[50]; sprintf(set_nograbmask_mesg, "SET_NOGRAB_MASK %lu", mask); SendText(fd, set_nograbmask_mesg, 0); } /* * Optional routine that sets the matching criteria for config lines * that should be sent to a module by way of the GetConfigLine function. * * If this routine is not called, all module config lines are sent. */ static int first_pass = 1; void InitGetConfigLine(int *fd, char *match) { char *buffer = (char *)alloca(strlen(match) + 32); first_pass = 0; /* make sure get wont do this */ sprintf(buffer, "Send_ConfigInfo %s", match); SendText(fd, buffer, 0); } /* * Gets a module configuration line from fvwm. Returns NULL if there are * no more lines to be had. "line" is a pointer to a char *. * * Changed 10/19/98 by Dan Espen: * * - The "isspace" call was referring to memory beyond the end of the * input area. This could have led to the creation of a core file. Added * "body_size" to keep it in bounds. */ void GetConfigLine(int *fd, char **tline) { FvwmPacket *packet; int body_count; if (first_pass) { SendText(fd, "Send_ConfigInfo", 0); first_pass = 0; } do { packet = ReadFvwmPacket(fd[1]); if (packet == NULL || packet->type == M_END_CONFIG_INFO) { *tline = NULL; return; } } while (packet->type != M_CONFIG_INFO); /* For whatever reason CONFIG_INFO packets start with three * (unsigned long) zeros. Skip the zeros and any whitespace that * follows */ *tline = (char *)&(packet->body[3]); body_count = FvwmPacketBodySize(*packet) * sizeof(unsigned long); while (body_count > 0 && isspace((unsigned char)**tline)) { (*tline)++; --body_count; } } ModuleArgs *ParseModuleArgs(int argc, char *argv[], int use_arg6_as_alias) { static ModuleArgs ma; /* Need at least six arguments: [0] name of executable [1] file descriptor of module->fvwm pipe (write end) [2] file descriptor of fvwm->module pipe (read end) [3] pathname of last config file read (ignored, use Send_ConfigInfo) [4] application window context [5] window decoration context Optionally (left column used if use_arg6_as_alias is true): [6] alias or user argument 0 [7] user arg 0 or user arg 1 ... */ if (argc < 6) { return NULL; } /* Module name is (last component of) argv[0] or possibly an alias passed on the command line. */ if (use_arg6_as_alias && argc >= 7) { ma.name = argv[6]; ma.user_argc = argc - 7; ma.user_argv = &(argv[7]); } else { char *p = strrchr(argv[0], '/'); if (p == NULL) { ma.name = argv[0]; } else { ma.name = ++p; } ma.user_argc = argc - 6; ma.user_argv = &(argv[6]); } ma.namelen=strlen(ma.name); if (ma.user_argc == 0) { ma.user_argv = NULL; } /* File descriptors for the pipes */ ma.to_fvwm = atoi(argv[1]); ma.from_fvwm = atoi(argv[2]); /* Ignore argv[3] */ /* These two are generated as long hex strings */ ma.window = strtoul(argv[4], NULL, 16); ma.decoration = strtoul(argv[5], NULL, 16); return &ma; } /* expands certain variables in a command to be sent by a module */ char *module_expand_action( Display *dpy, int screen , char *in_action, rectangle *r, char *forecolor, char *backcolor) { char *variables[] = { "$", "fg", "bg", "left", "-left", "right", "-right", "top", "-top", "bottom", "-bottom", "width", "height", NULL }; char *action = NULL; char *src; char *dest; char *string = NULL; char *rest; int val = 0; int offset; int i; char *dest_org; Bool is_string; Bool is_value; Bool has_geom; Bool has_fg; Bool has_bg; rectangle tmpr = { 0, 0, 0, 0 }; has_geom = (r == NULL) ? False : True; has_fg = (forecolor == NULL) ? False : True; has_bg = (backcolor == NULL) ? False : True; if (r == NULL) { r = &tmpr; } /* create a temporary storage for expanding */ action = (char *)safemalloc(MAX_MODULE_INPUT_TEXT_LEN); for (src = in_action, dest = action; *src != 0; src++) { if (*src != '$') { *(dest++) = *src; continue; } /* it's a variable */ dest_org = dest; is_string = False; is_value = False; *(dest++) = *(src++); i = GetTokenIndex(src, variables, -1, &rest); if (i == -1) { src--; continue; } switch (i) { case 0: /* $ */ continue; case 1: /* fg */ string = forecolor; is_string = has_fg; break; case 2: /* bg */ if (backcolor == NULL) { continue; } string = backcolor; is_string = has_bg; break; case 3: /* left */ val = r->x; is_value = has_geom; break; case 4: /* -left */ val = DisplayWidth(dpy, screen) - r->x - 1; is_value = has_geom; break; case 5: /* right */ val = r->x + r->width; is_value = has_geom; break; case 6: /* -right */ val = DisplayWidth(dpy, screen) - r->x - r->width - 1; is_value = has_geom; break; case 7: /* top */ val = r->y; is_value = has_geom; break; case 8: /* -top */ val = DisplayHeight(dpy, screen) - r->y - 1; is_value = has_geom; break; case 9: /* bottom */ val = r->y + r->height; is_value = has_geom; break; case 10: /* -bottom */ val = DisplayHeight(dpy, screen) - r->y - r->height - 1; is_value = has_geom; break; case 11: /* width */ val = r->width; is_value = has_geom; break; case 12: /* height */ val = r->height; is_value = has_geom; break; default: /* unknown */ src--; continue; } /* switch */ if (is_value == False && is_string == False) { src--; continue; } dest = dest_org; src = --rest; if (is_value) { if (MAX_MODULE_INPUT_TEXT_LEN - (dest - action) <= 16) { /* out of space */ free(action); return NULL; } /* print the number into the string */ sprintf(dest, "%d%n", val, &offset); dest += offset; } else if (is_string) { if (MAX_MODULE_INPUT_TEXT_LEN - (dest - action) <= strlen(string)) { /* out of space */ free(action); return NULL; } /* print the colour name into the string */ if (string) { sprintf(dest, "%s%n", string, &offset); dest += offset; } } } /* for */ *dest = 0; return action; } fvwm-2.7.0/libs/wcontext.h0000644000175000017500000000366414147024700012405 00000000000000/* -*-c-*- */ #ifndef WCONTEXT_H #define WCONTEXT_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ typedef enum { /* contexts for button presses */ C_NO_CONTEXT = 0x00, C_WINDOW = 0x01, C_TITLE = 0x02, C_ICON = 0x04, C_ROOT = 0x08, C_MENU = 0x10, C_PLACEMENT = 0x20, C_L1 = 0x40, C_R1 = 0x80, C_L2 = 0x100, C_R2 = 0x200, C_L3 = 0x400, C_R3 = 0x800, C_L4 = 0x1000, C_R4 = 0x2000, C_L5 = 0x4000, C_R5 = 0x8000, C_UNMANAGED = 0x10000, C_EWMH_DESKTOP = 0x20000, C_F_TOPLEFT = 0x100000, C_F_TOPRIGHT = 0x200000, C_F_BOTTOMLEFT = 0x400000, C_F_BOTTOMRIGHT = 0x800000, C_SB_LEFT = 0x1000000, C_SB_RIGHT = 0x2000000, C_SB_TOP = 0x4000000, C_SB_BOTTOM = 0x8000000, /* C_ = 0x10000000, */ /* C_ = 0x20000000, */ /* C_ = 0x40000000, */ C_IGNORE_ALL = (int)0x80000000, C_FRAME = (C_F_TOPLEFT|C_F_TOPRIGHT|C_F_BOTTOMLEFT|C_F_BOTTOMRIGHT), C_SIDEBAR = (C_SB_LEFT|C_SB_RIGHT|C_SB_TOP|C_SB_BOTTOM), C_RALL = (C_R1|C_R2|C_R3|C_R4|C_R5), C_LALL = (C_L1|C_L2|C_L3|C_L4|C_L5), C_DECOR = (C_LALL|C_RALL|C_TITLE|C_FRAME|C_SIDEBAR), C_ALL = (C_WINDOW|C_TITLE|C_ICON|C_ROOT|C_FRAME|C_SIDEBAR|\ C_LALL|C_RALL|C_EWMH_DESKTOP), C_MENU_ITEM = (C_ICON|C_MENU) } win_context_t; /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- exported variables (globals) --------------- */ extern charmap_t win_contexts[]; /* ---------------------------- interface functions ------------------------ */ int wcontext_string_to_wcontext(char *in_context, int *out_context_mask); char wcontext_wcontext_to_char(win_context_t wcontext); win_context_t wcontext_merge_border_wcontext(win_context_t wcontext); #endif /* WCONTEXT_H */ fvwm-2.7.0/libs/Graphics.c0000644000175000017500000010065214147024700012260 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* Graphics.c: misc convenience functions for drawing stuff */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include #include "defaults.h" #include "libs/fvwmlib.h" #include "libs/Parse.h" #include "libs/PictureBase.h" #include "libs/PictureUtils.h" #include "libs/PictureGraphics.h" #include "libs/gravity.h" #include "libs/FImage.h" #include "libs/Graphics.h" /* ---------------------------- local definitions -------------------------- */ /* Define some standard constants that are not included in the C89 standard */ #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #ifndef M_PI_2 #define M_PI_2 1.57079632679489661923 #endif #ifndef M_1_PI #define M_1_PI 0.31830988618379067154 #endif /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ /* ---------------------------- interface functions ------------------------ */ /* Draws the relief pattern around a window * Draws a line_width wide rectangle from (x,y) to (x+w,y+h) i.e w+1 wide, * h+1 high * Draws end points assuming CAP_NOT_LAST style in GC * Draws anti-clockwise in case CAP_BUTT is the style and the end points overlap * Top and bottom lines come out full length, the sides come out 1 pixel less * This is so FvwmBorder windows have a correct bottom edge and the sticky lines * look like just lines * rotation rotate the relief and shadow part */ void do_relieve_rectangle_with_rotation( Display *dpy, Drawable d, int x, int y, int w, int h, GC ReliefGC, GC ShadowGC, int line_width, Bool use_alternate_shading, int rotation) { XSegment* seg; GC shadow_gc, relief_gc; int i,i2; int a; int l; int max_w; int max_h; a = (use_alternate_shading) ? 1 : 0; l = 1 - a; if (w <= 0 || h <= 0) { return; } /* If line_width is negative, reverse the rotation, which will */ /* have the effect of inverting the relief. */ if (line_width < 0) { line_width = -line_width; rotation = gravity_add_rotations(rotation, ROTATION_180); } switch (rotation) { case ROTATION_180: case ROTATION_270: rotation = gravity_add_rotations(rotation, ROTATION_180); shadow_gc = ReliefGC; relief_gc = ShadowGC; break; default: shadow_gc = ShadowGC; relief_gc = ReliefGC; break; } max_w = min((w + 1) / 2, line_width); max_h = min((h + 1) / 2, line_width); seg = (XSegment*)alloca((sizeof(XSegment) * line_width) * 2); /* from 0 to the lesser of line_width & just over half w */ for (i = 0; i < max_w; i++) { if (rotation == ROTATION_0) { /* left */ seg[i].x1 = x+i; seg[i].y1 = y+i+a; seg[i].x2 = x+i; seg[i].y2 = y+h-i+a; } else /* ROTATION_90 */ { /* right */ seg[i].x1 = x+w-i; seg[i].y1 = y+h-i-a; seg[i].x2 = x+w-i; seg[i].y2 = y+i+1-a; } } i2 = i; /* draw top segments */ for (i = 0; i < max_h; i++,i2++) { seg[i2].x1 = x+w-i-a; seg[i2].y1 = y+i; seg[i2].x2 = x+i+1-a; seg[i2].y2 = y+i; } XDrawSegments(dpy, d, relief_gc, seg, i2); /* bottom */ for (i = 0; i < max_h; i++) { seg[i].x1 = x+i+a+l; seg[i].y1 = y+h-i; seg[i].x2 = x+w-i-1+a; seg[i].y2 = y+h-i; } i2 = i; for (i = 0; i < max_w; i++,i2++) { if (rotation == ROTATION_0) { /* right */ seg[i2].x1 = x+w-i; seg[i2].y1 = y+h-i-a; seg[i2].x2 = x+w-i; seg[i2].y2 = y+i+1-a; } else /* ROTATION_90 */ { /* left */ seg[i2].x1 = x+i; seg[i2].y1 = y+i+a; seg[i2].x2 = x+i; seg[i2].y2 = y+h-i+a; } } XDrawSegments(dpy, d, shadow_gc, seg, i2); return; } void do_relieve_rectangle( Display *dpy, Drawable d, int x, int y, int w, int h, GC ReliefGC, GC ShadowGC, int line_width, Bool use_alternate_shading) { do_relieve_rectangle_with_rotation( dpy, d, x, y, w, h, ReliefGC, ShadowGC, line_width, use_alternate_shading, ROTATION_0); return; } /* Creates a pixmap that is a horizontally stretched version of the input * pixmap */ Pixmap CreateStretchXPixmap( Display *dpy, Pixmap src, int src_width, int src_height, int src_depth, int dest_width, GC gc) { int i; Pixmap pixmap; GC my_gc = None; if (src_width < 0 || src_height < 0 || dest_width < 0) { return None; } pixmap = XCreatePixmap(dpy, src, dest_width, src_height, src_depth); if (pixmap == None) { return None; } if (gc == None) { my_gc = fvwmlib_XCreateGC(dpy, pixmap, 0, 0); } for (i = 0; i < dest_width; i++) { XCopyArea( dpy, src, pixmap, (gc == None)? my_gc:gc, (i * src_width) / dest_width, 0, 1, src_height, i, 0); } if (my_gc) { XFreeGC(dpy, my_gc); } return pixmap; } /* Creates a pixmap that is a vertically stretched version of the input * pixmap */ Pixmap CreateStretchYPixmap( Display *dpy, Pixmap src, int src_width, int src_height, int src_depth, int dest_height, GC gc) { int i; Pixmap pixmap; GC my_gc = None; if (src_height < 0 || src_depth < 0 || dest_height < 0) { return None; } pixmap = XCreatePixmap(dpy, src, src_width, dest_height, src_depth); if (pixmap == None) { return None; } if (gc == None) { my_gc = fvwmlib_XCreateGC(dpy, pixmap, 0, 0); } for (i = 0; i < dest_height; i++) { XCopyArea( dpy, src, pixmap, (gc == None)? my_gc:gc, 0, (i * src_height) / dest_height, src_width, 1, 0, i); } if (my_gc) { XFreeGC(dpy, my_gc); } return pixmap; } /* Creates a pixmap that is a stretched version of the input * pixmap */ Pixmap CreateStretchPixmap( Display *dpy, Pixmap src, int src_width, int src_height, int src_depth, int dest_width, int dest_height, GC gc) { Pixmap pixmap = None; Pixmap temp_pixmap; GC my_gc = None; if (src_width < 0 || src_height < 0 || src_depth < 0 || dest_width < 0) { return None; } if (gc == None) { my_gc = fvwmlib_XCreateGC(dpy, src, 0, 0); } temp_pixmap = CreateStretchXPixmap( dpy, src, src_width, src_height, src_depth, dest_width, (gc == None)? my_gc:gc); if (temp_pixmap == None) { if (my_gc) { XFreeGC(dpy, my_gc); } return None; } pixmap = CreateStretchYPixmap( dpy, temp_pixmap, dest_width, src_height, src_depth, dest_height, (gc == None)? my_gc:gc); XFreePixmap(dpy, temp_pixmap); if (my_gc) { XFreeGC(dpy, my_gc); } return pixmap; } /* Creates a pixmap that is a tiled version of the input pixmap. Modifies the * sets the fill_style of the GC to FillSolid and the tile to None. */ Pixmap CreateTiledPixmap( Display *dpy, Pixmap src, int src_width, int src_height, int dest_width, int dest_height, int depth, GC gc) { XGCValues xgcv; Pixmap pixmap; if (src_width < 0 || src_height < 0 || dest_width < 0 || dest_height < 0) { return None; } pixmap = XCreatePixmap(dpy, src, dest_width, dest_height, depth); if (pixmap == None) { return None; } xgcv.fill_style = FillTiled; xgcv.tile = src; xgcv.ts_x_origin = 0; xgcv.ts_y_origin = 0; XChangeGC( dpy, gc, GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin, &xgcv); XFillRectangle(dpy, pixmap, gc, 0, 0, dest_width, dest_height); xgcv.fill_style = FillSolid; XChangeGC(dpy, gc, GCFillStyle, &xgcv); return pixmap; } Pixmap CreateRotatedPixmap( Display *dpy, Pixmap src, int src_width, int src_height, int depth, GC gc, int rotation) { GC my_gc = None; Pixmap pixmap = None; int dest_width, dest_height, i, j; Bool error = False; FImage *fim = NULL; FImage *src_fim = NULL; if (src_width <= 0 || src_height <= 0) { return None; } switch(rotation) { case ROTATION_90: case ROTATION_270: dest_width = src_height; dest_height = src_width; break; case ROTATION_0: case ROTATION_180: dest_width = src_width; dest_height = src_height; break; default: return None; break; } pixmap = XCreatePixmap(dpy, src, dest_width, dest_height, depth); if (pixmap == None) { return None; } if (gc == None) { my_gc = fvwmlib_XCreateGC(dpy, src, 0, 0); } if (rotation == ROTATION_0) { XCopyArea( dpy, src, pixmap, (gc == None)? my_gc:gc, 0, 0, src_width, src_height, 0, 0); goto bail; } if (!(src_fim = FGetFImage( dpy, src, Pvisual, depth, 0, 0, src_width, src_height, AllPlanes, ZPixmap))) { error = True; goto bail; } if (!(fim = FCreateFImage( dpy, Pvisual, depth, ZPixmap, dest_width, dest_height))) { error = True; goto bail; } for (j = 0; j < src_height; j++) { for (i = 0; i < src_width; i++) { switch(rotation) { case ROTATION_270: XPutPixel( fim->im, j, src_width - i - 1, XGetPixel(src_fim->im, i, j)); break; case ROTATION_90: XPutPixel( fim->im, src_height - j - 1, i, XGetPixel(src_fim->im, i, j)); break; case ROTATION_180: XPutPixel( fim->im, src_width - i - 1, src_height - j - 1, XGetPixel(src_fim->im, i, j)); break; default: break; } } } FPutFImage(dpy, pixmap, gc, fim, 0, 0, 0, 0, dest_width, dest_height); bail: if (error && pixmap) { XFreePixmap(dpy,pixmap); pixmap = None; } if (fim) { FDestroyFImage(dpy, fim); } if (src_fim) { FDestroyFImage(dpy, src_fim); } if (my_gc) { XFreeGC(dpy, my_gc); } return pixmap; } /* * * Returns True if the given type of gradient is supported. * */ Bool IsGradientTypeSupported(char type) { switch (toupper(type)) { case V_GRADIENT: case H_GRADIENT: case B_GRADIENT: case D_GRADIENT: case R_GRADIENT: case Y_GRADIENT: case S_GRADIENT: case C_GRADIENT: return True; default: fprintf(stderr, "%cGradient type is not supported\n", toupper(type)); return False; } } /* * * Allocates a linear color gradient (veliaa@rpi.edu) * */ static XColor *AllocLinearGradient( char *s_from, char *s_to, int npixels, int skip_first_color, int dither) { XColor *xcs; XColor from, to, c; float r; float dr; float g; float dg; float b; float db; int i; int got_all = 1; int div; if (npixels < 1) { fprintf(stderr, "AllocLinearGradient: Invalid number of pixels: %d\n", npixels); return NULL; } if (!s_from || !XParseColor(Pdpy, Pcmap, s_from, &from)) { fprintf(stderr, "Cannot parse color \"%s\"\n", s_from ? s_from : ""); return NULL; } if (!s_to || !XParseColor(Pdpy, Pcmap, s_to, &to)) { fprintf(stderr, "Cannot parse color \"%s\"\n", s_to ? s_to : ""); return NULL; } /* divisor must not be zero, hence this calculation */ div = (npixels == 1) ? 1 : npixels - 1; c = from; /* red part and step width */ r = from.red; dr = (float)(to.red - from.red); /* green part and step width */ g = from.green; dg = (float)(to.green - from.green); /* blue part and step width */ b = from.blue; db = (float)(to.blue - from.blue); xcs = (XColor *)safemalloc(sizeof(XColor) * npixels); memset(xcs, 0, sizeof(XColor) * npixels); c.flags = DoRed | DoGreen | DoBlue; for (i = (skip_first_color) ? 1 : 0; i < npixels && div > 0; ++i) { c.red = (unsigned short) ((int)(r + dr / (float)div * (float)i + 0.5)); c.green = (unsigned short) ((int)(g + dg / (float)div * (float)i + 0.5)); c.blue = (unsigned short) ((int)(b + db / (float)div * (float)i + 0.5)); if (dither == 0 && !PictureAllocColor(Pdpy, Pcmap, &c, False)) { got_all = 0; } xcs[i] = c; } if (!got_all && dither == 0) { fprintf(stderr, "Cannot alloc color gradient %s to %s\n", s_from, s_to); } return xcs; } /* * * Allocates a nonlinear color gradient (veliaa@rpi.edu) * */ static XColor *AllocNonlinearGradient( char *s_colors[], int clen[], int nsegs, int npixels, int dither) { XColor *xcs = (XColor *)safemalloc(sizeof(XColor) * npixels); int i; int curpixel = 0; int *seg_end_colors; int seg_sum = 0; float color_sum = 0.0; if (nsegs < 1 || npixels < 2) { fprintf(stderr, "Gradients must specify at least one segment and" " two colors\n"); free(xcs); return NULL; } for (i = 0; i < npixels; i++) { xcs[i].pixel = 0; } /* get total length of all segments */ for (i = 0; i < nsegs; i++) { seg_sum += clen[i]; } /* calculate the index of a segment's las color */ seg_end_colors = alloca(nsegs * sizeof(int)); if (nsegs == 1) { seg_end_colors[0] = npixels - 1; } else { for (i = 0; i < nsegs; i++) { color_sum += (float)(clen[i] * (npixels - 1)) / (float)(seg_sum); seg_end_colors[i] = (int)(color_sum + 0.5); } if (seg_end_colors[nsegs - 1] > npixels - 1) { fprintf(stderr, "BUG: (AllocNonlinearGradient): " "seg_end_colors[nsegs - 1] (%d)" " > npixels - 1 (%d)." " Gradient drawing aborted\n", seg_end_colors[nsegs - 1], npixels - 1); return NULL; } /* take care of rounding errors */ seg_end_colors[nsegs - 1] = npixels - 1; } for (i = 0; i < nsegs; ++i) { XColor *c = NULL; int j; int n; int skip_first_color = (curpixel != 0); if (i == 0) { n = seg_end_colors[0] + 1; } else { n = seg_end_colors[i] - seg_end_colors[i - 1] + 1; } if (n > 1) { c = AllocLinearGradient( s_colors[i], s_colors[i + 1], n, skip_first_color, dither); if (!c && (n - skip_first_color) != 0) { free(xcs); return NULL; } for (j = skip_first_color; j < n; ++j) { xcs[curpixel + j] = c[j]; } curpixel += n - 1; } if (c) { free(c); c = NULL; } if (curpixel != seg_end_colors[i]) { fprintf(stderr, "BUG: (AllocNonlinearGradient): " "nsegs %d, i %d, curpixel %d," " seg_end_colors[i] = %d," " npixels %d, n %d\n", nsegs, i, curpixel, seg_end_colors[i],npixels,n); return NULL; } } return xcs; } /* Convenience function. Calls AllocNonLinearGradient to fetch all colors and * then frees the color names and the perc and color_name arrays. */ XColor *AllocAllGradientColors( char *color_names[], int perc[], int nsegs, int ncolors, int dither) { XColor *xcs = NULL; int i; /* grab the colors */ xcs = AllocNonlinearGradient( color_names, perc, nsegs, ncolors, dither); for (i = 0; i <= nsegs; i++) { if (color_names[i]) { free(color_names[i]); } } free(color_names); free(perc); if (!xcs) { fprintf(stderr, "couldn't create gradient\n"); return NULL; } return xcs; } /* groks a gradient string and creates arrays of colors and percentages * returns the number of colors asked for (No. allocated may be less due * to the ColorLimit command). A return of 0 indicates an error */ int ParseGradient( char *gradient, char **rest, char ***colors_return, int **perc_return, int *nsegs_return) { char *item; char *orig; int npixels; char **s_colors; int *perc; int nsegs, i, sum; Bool is_syntax_error = False; /* get the number of colors specified */ if (rest) { *rest = gradient; } orig = gradient; if (GetIntegerArguments(gradient, &gradient, (int *)&npixels, 1) != 1 || npixels < 2) { fprintf( stderr, "ParseGradient: illegal number of colors in" " gradient: '%s'\n", orig); return 0; } /* get the starting color or number of segments */ gradient = GetNextToken(gradient, &item); if (gradient) { gradient = SkipSpaces(gradient, NULL, 0); } if (!gradient || !*gradient || !item) { fprintf(stderr, "Incomplete gradient style: '%s'\n", orig); if (item) { free(item); } if (rest) { *rest = gradient; } return 0; } if (GetIntegerArguments(item, NULL, &nsegs, 1) != 1) { /* get the end color of a simple gradient */ s_colors = (char **)safemalloc(sizeof(char *) * 2); perc = (int *)safemalloc(sizeof(int)); nsegs = 1; s_colors[0] = item; gradient = GetNextToken(gradient, &item); s_colors[1] = item; perc[0] = 100; } else { free(item); /* get a list of colors and percentages */ if (nsegs < 1) nsegs = 1; if (nsegs > MAX_GRADIENT_SEGMENTS) nsegs = MAX_GRADIENT_SEGMENTS; s_colors = (char **)safemalloc(sizeof(char *) * (nsegs + 1)); perc = (int *)safemalloc(sizeof(int) * nsegs); for (i = 0; !is_syntax_error && i <= nsegs; i++) { s_colors[i] = 0; gradient = GetNextToken(gradient, &s_colors[i]); if (i < nsegs) { if (GetIntegerArguments( gradient, &gradient, &perc[i], 1) != 1 || perc[i] <= 0) { /* illegal size */ perc[i] = 0; } } } if (s_colors[nsegs] == NULL) { fprintf( stderr, "ParseGradient: too few gradient" " segments: '%s'\n", orig); is_syntax_error = True; } } /* sanity check */ for (i = 0, sum = 0; !is_syntax_error && i < nsegs; ++i) { int old_sum = sum; sum += perc[i]; if (sum < old_sum) { /* integer overflow */ fprintf( stderr, "ParseGradient: multi gradient" " overflow: '%s'", orig); is_syntax_error = 1; break; } } if (is_syntax_error) { for (i = 0; i <= nsegs; ++i) { if (s_colors[i]) { free(s_colors[i]); } } free(s_colors); free(perc); if (rest) { *rest = gradient; } return 0; } /* sensible limits */ if (npixels < 2) npixels = 2; if (npixels > MAX_GRADIENT_COLORS) npixels = MAX_GRADIENT_COLORS; /* send data back */ *colors_return = s_colors; *perc_return = perc; *nsegs_return = nsegs; if (rest) *rest = gradient; return npixels; } /* Calculate the prefered dimensions of a gradient, based on the number of * colors and the gradient type. Returns False if the gradient type is not * supported. */ Bool CalculateGradientDimensions( Display *dpy, Drawable d, int ncolors, char type, int dither, int *width_ret, int *height_ret) { static int best_width = 0, best_height = 0; int dither_factor = (dither > 0)? 128:1; /* get the best tile size (once) */ if (!best_width) { if (!XQueryBestTile( dpy, d, 1, 1, (unsigned int*)&best_width, (unsigned int*)&best_height)) { best_width = 0; best_height = 0; } /* this is needed for buggy X servers like XFree 3.3.3.1 */ if (!best_width) best_width = 1; if (!best_height) best_height = 1; } switch (type) { case H_GRADIENT: *width_ret = ncolors; *height_ret = best_height * dither_factor; break; case V_GRADIENT: *width_ret = best_width * dither_factor; *height_ret = ncolors; break; case D_GRADIENT: case B_GRADIENT: /* diagonal gradients are rendered into a rectangle for which * the width plus the height is equal to ncolors + 1. The * rectangle is square when ncolors is odd and one pixel * taller than wide with even numbers */ *width_ret = (ncolors + 1) / 2; *height_ret = ncolors + 1 - *width_ret; break; case S_GRADIENT: /* square gradients have the last color as a single pixel in * the centre */ *width_ret = *height_ret = 2 * ncolors - 1; break; case C_GRADIENT: /* circular gradients have the first color as a pixel in each * corner */ *width_ret = *height_ret = 2 * ncolors - 1; break; case R_GRADIENT: case Y_GRADIENT: /* swept types need each color to occupy at least one pixel at * the edge. Get the smallest odd number that will provide * enough */ for (*width_ret = 1; (double)(*width_ret - 1) * M_PI < (double)ncolors; *width_ret += 2) { /* nothing to do here */ } *height_ret = *width_ret; break; default: fprintf(stderr, "%cGradient not supported\n", type); return False; } return True; } /* Does the actual drawing of the pixmap. If the in_drawable argument is None, * a new pixmap of the given depth, width and height is created. If it is not * None the gradient is drawn into it. The d_width, d_height, d_x and d_y * describe the traget rectangle within the drawable. */ Drawable CreateGradientPixmap( Display *dpy, Drawable d, GC gc, int type, int g_width, int g_height, int ncolors, XColor *xcs, int dither, Pixel **d_pixels, int *d_npixels, Drawable in_drawable, int d_x, int d_y, int d_width, int d_height, XRectangle *rclip) { Pixmap pixmap = None; PictureImageColorAllocator *pica = NULL; XColor c; FImage *fim; register int i, j; XGCValues xgcv; Drawable target; int t_x; int t_y; int t_width; int t_height; if (d_pixels != NULL && *d_pixels != NULL) { if (d_npixels != NULL && *d_npixels > 0) { PictureFreeColors( dpy, Pcmap, *d_pixels, *d_npixels, 0, False); } free(*d_pixels); *d_pixels = NULL; } if (d_npixels != NULL) { *d_npixels = 0; } if (g_height < 0 || g_width < 0 || d_width < 0 || d_height < 0) return None; if (in_drawable == None) { /* create a pixmap to use */ pixmap = XCreatePixmap(dpy, d, g_width, g_height, Pdepth); if (pixmap == None) return None; target = pixmap; t_x = 0; t_y = 0; t_width = g_width; t_height = g_height; } else { target = in_drawable; t_x = d_x; t_y = d_y; t_width = d_width; t_height = d_height; } fim = FCreateFImage( dpy, Pvisual, Pdepth, ZPixmap, t_width, t_height); if (!fim) { fprintf(stderr, "%cGradient couldn't get image\n", type); if (pixmap != None) XFreePixmap(dpy, pixmap); return None; } if (dither) { pica = PictureOpenImageColorAllocator( dpy, Pcmap, t_width, t_height, False, False, dither, False); } /* now do the fancy drawing */ switch (type) { case H_GRADIENT: { for (i = 0; i < t_width; i++) { int d = i * ncolors / t_width; c = xcs[d]; for (j = 0; j < t_height; j++) { if (dither) { c = xcs[d]; PictureAllocColorImage( dpy, pica, &c, i, j); } XPutPixel(fim->im, i, j, c.pixel); } } } break; case V_GRADIENT: { for (j = 0; j < t_height; j++) { int d = j * ncolors / t_height; c = xcs[d]; for (i = 0; i < t_width; i++) { if (dither) { c = xcs[d]; PictureAllocColorImage( dpy, pica, &c, i, j); } XPutPixel(fim->im, i, j, c.pixel); } } break; } case D_GRADIENT: { register int t_scale = t_width + t_height - 1; for (i = 0; i < t_width; i++) { for (j = 0; j < t_height; j++) { c = xcs[(i+j) * ncolors / t_scale]; if (dither) { PictureAllocColorImage( dpy, pica, &c, i, j); } XPutPixel(fim->im, i, j, c.pixel); } } break; } case B_GRADIENT: { register int t_scale = t_width + t_height - 1; for (i = 0; i < t_width; i++) { for (j = 0; j < t_height; j++) { c = xcs[(i + (t_height - j - 1)) * ncolors / t_scale]; if (dither) { PictureAllocColorImage( dpy, pica, &c, i, j); } XPutPixel(fim->im, i, j, c.pixel); } } break; } case S_GRADIENT: { register int t_scale = t_width * t_height; register int myncolors = ncolors * 2; for (i = 0; i < t_width; i++) { register int pi = min(i, t_width - 1 - i) * t_height; for (j = 0; j < t_height; j++) { register int pj = min(j, t_height - 1 - j) * t_width; c = xcs[(min(pi, pj) * myncolors - 1) / t_scale]; if (dither) { PictureAllocColorImage( dpy, pica, &c, i, j); } XPutPixel(fim->im, i, j, c.pixel); } } } break; case C_GRADIENT: { register double t_scale = (double)(t_width * t_height) / sqrt(8); for (i = 0; i < t_width; i++) { for (j = 0; j < t_height; j++) { register double x = (double)((2 * i - t_width) * t_height) / 4.0; register double y = (double)((t_height - 2 * j) * t_width) / 4.0; register double rad = sqrt(x * x + y * y); c = xcs[(int)((rad * ncolors - 0.5) / t_scale)]; if (dither) { PictureAllocColorImage( dpy, pica, &c, i, j); } XPutPixel(fim->im, i, j, c.pixel); } } break; } case R_GRADIENT: { register int w = t_width - 1; register int h = t_height - 1; /* g_width == g_height, both are odd, therefore x can be 0.0 */ for (i = 0; i <= w; i++) { for (j = 0; j <= h; j++) { register double x = (double)((2 * i - w) * h) / 4.0; register double y = (double)((h - 2 * j) * w) / 4.0; /* angle ranges from -pi/2 to +pi/2 */ register double angle; if (x != 0.0) { angle = atan(y / x); } else { angle = (y < 0) ? - M_PI_2 : M_PI_2; } /* extend to -pi/2 to 3pi/2 */ if (x < 0) angle += M_PI; /* move range from -pi/2:3*pi/2 to 0:2*pi */ if (angle < 0.0) angle += M_PI * 2.0; /* normalize to gradient */ c = xcs[(int)(angle * M_1_PI * 0.5 * ncolors)]; if (dither) { PictureAllocColorImage( dpy, pica, &c, i, j); } XPutPixel(fim->im, i, j, c.pixel); } } } break; /* * The Yin Yang gradient style and the following code are: * Copyright 1999 Sir Boris. (email to sir_boris@bigfoot.com may be * read by his groom but is not guaranteed to elicit a response) * No restrictions are placed on this code, as long as the copyright * notice is preserved. */ case Y_GRADIENT: { register int r = t_width * t_height / 4; for (i = 0; i < t_width; i++) { for (j = 0; j < t_height; j++) { register double x = (double)((2 * i - t_width) * t_height) / 4.0; register double y = (double)((t_height - 2 * j) * t_width) / 4.0; register double rad = sqrt(x * x + y * y); /* angle ranges from -pi/2 to +pi/2 */ register double angle; if (x != 0.0) { angle = atan(y / x); } else { angle = (y < 0) ? - M_PI_2 : M_PI_2; } /* extend to -pi/2 to 3pi/2 */ if (x < 0) angle += M_PI; /* warp the angle within the yinyang circle */ if (rad <= r) { angle -= acos(rad / r); } /* move range from -pi/2:3*pi/2 to 0:2*pi */ if (angle < 0.0) angle += M_PI * 2.0; /* normalize to gradient */ c = xcs[(int)(angle * M_1_PI * 0.5 * ncolors)]; if (dither) { PictureAllocColorImage( dpy, pica, &c, i, j); } XPutPixel(fim->im, i, j, c.pixel); } } } break; default: /* placeholder function, just fills the pixmap with the first * color */ memset(fim->im->data, 0, fim->im->bytes_per_line * t_height); XAddPixel(fim->im, xcs[0].pixel); break; } if (dither) { if (d_pixels != NULL && d_npixels != NULL) { PictureCloseImageColorAllocator( dpy, pica, d_npixels, d_pixels, 0); } else { /* possible color leak */ } } /* set the gc style */ xgcv.function = GXcopy; xgcv.plane_mask = AllPlanes; xgcv.fill_style = FillSolid; xgcv.clip_mask = None; XChangeGC(dpy, gc, GCFunction|GCPlaneMask|GCFillStyle|GCClipMask, &xgcv); if (rclip) { XSetClipRectangles(dpy, gc, 0, 0, rclip, 1, Unsorted); } /* copy the image to the server */ FPutFImage(dpy, target, gc, fim, 0, 0, t_x, t_y, t_width, t_height); if (rclip) { XSetClipMask(dpy, gc, None); } FDestroyFImage(dpy, fim); return target; } /* Create a pixmap from a gradient specifier, width and height are hints * that are only used for gradients that can be tiled e.g. H or V types * types are HVDBSCRY for Horizontal, Vertical, Diagonal, Back-diagonal, Square, * Circular, Radar and Yin/Yang respectively (in order of bloatiness) */ Pixmap CreateGradientPixmapFromString( Display *dpy, Drawable d, GC gc, int type, char *action, int *width_return, int *height_return, Pixel **pixels_return, int *nalloc_pixels, int dither) { Pixel *d_pixels = NULL; int d_npixels = 0; XColor *xcs = NULL; int ncolors = 0; char **colors; int *perc, nsegs; Pixmap pixmap = None; /* set return pixels to NULL in case of premature return */ if (pixels_return) *pixels_return = NULL; if (nalloc_pixels) *nalloc_pixels = 0; /* translate the gradient string into an array of colors etc */ if (!(ncolors = ParseGradient(action, NULL, &colors, &perc, &nsegs))) { fprintf(stderr, "Can't parse gradient: '%s'\n", action); return None; } /* grab the colors */ xcs = AllocAllGradientColors( colors, perc, nsegs, ncolors, dither); if (xcs == NULL) { return None; } /* grok the size to create from the type */ type = toupper(type); if (CalculateGradientDimensions( dpy, d, ncolors, type, dither, width_return, height_return)) { pixmap = CreateGradientPixmap( dpy, d, gc, type, *width_return, *height_return, ncolors, xcs, dither, &d_pixels, &d_npixels, None, 0, 0, 0, 0, NULL); } /* if the caller has not asked for the pixels there is probably a leak */ if (PUseDynamicColors) { if (!(pixels_return && nalloc_pixels)) { /* if the caller has not asked for the pixels there is * probably a leak */ fprintf(stderr, "CreateGradient: potential color leak, losing track" " of pixels\n"); if (d_pixels != NULL) { free(d_pixels); } } else { if (!dither) { Pixel *pixels; int i; pixels = (Pixel *)safemalloc( ncolors * sizeof(Pixel)); for(i=0; igraphics_exposures; if (!(valuemask & GCGraphicsExposures)) { valuemask |= GCGraphicsExposures; values->graphics_exposures = 0; } gc = XCreateGC(display, drawable, valuemask, values); values->graphics_exposures = f; return gc; } fvwm-2.7.0/libs/WinMagic.c0000644000175000017500000001712614147024700012221 00000000000000/* -*-c-*- */ /* Copyright (C) 1999 Dominik Vogt */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ** WinMagic.c: ** This file supplies routines for moving and resizing windows in an animated ** fashion. */ #include "config.h" #include #include #include #include "WinMagic.h" /* Continuously moves and resized window win from start geometry (s_?) to end * geometry (e_?). Waits for delay_ms milliseconds after each step except the * last (max. 10 seconds per step). The number of steps is determined by the * steps argument (min. 1 and max. 10000). If the pointer ppctMovement is NULL * the steps are all the same width, if it is given it is interpreted as a * pointer to an array of float percent values. These are used to determine the * distance of each step counted from the start position, i.e. 0.0 means the * start position itself, 50.0 is halfway between start and end position and * 100.0 is the end position. Values smaller than 0.0 or bigger than 100.0 are * allowed too. The do_flush flag determines of all requests are sent to the * X server immediately (True) or not (False). The use_hints detrmines if the * min size and resize hints are used */ void SlideWindow( Display *dpy, Window win, int s_x, int s_y, int s_w, int s_h, int e_x, int e_y, int e_w, int e_h, int steps, int delay_ms, float *ppctMovement, Bool do_sync, Bool use_hints) { int x = 0; int y = 0; int w = 0; int h = 0; int g_w = 0; int g_h = 0; /* -Wall fixes :o( */ int min_w = 1; int min_h = 1; int inc_w = 1; int inc_h = 1; int i; unsigned int us; Bool is_mapped; Bool keep_x1 = False; Bool keep_x2 = False; Bool keep_y1 = False; Bool keep_y2 = False; XSizeHints hints; long dummy; /* check limits */ if (delay_ms > 10000) { /* max. 10 seconds per step */ us = 10000000; } else if (delay_ms < 0) { us = 0; } else { us = 1000 * delay_ms; } if (steps > 10000) { /* max. 10000 steps */ steps = 10000; } if (steps <= 0) { /* no steps, no animation */ if (e_w == 0 || e_h == 0) { XUnmapWindow(dpy, win); } else { XMoveResizeWindow(dpy, win, e_x, e_y, e_w, e_h); XMapWindow(dpy, win); XMapSubwindows(dpy, win); } if (do_sync) XSync(dpy, 0); return; } is_mapped = False; /* Get the mini (re)size hints and do some check consistency */ if (use_hints && FGetWMNormalHints(dpy, win, &hints, &dummy)) { if (hints.flags & PMinSize) { if (hints.min_width >= 1 && hints.min_width <= max(e_w,s_w)) min_w = hints.min_width; if (hints.min_height >= 1 && hints.min_height <= max(e_h,s_h)) min_h = hints.min_height; } if (hints.flags & PResizeInc) { if (hints.width_inc >= 1 && hints.width_inc <= max(e_w,s_w)) inc_w = hints.width_inc; if (hints.height_inc >= 1 && hints.width_inc <= max(e_h,s_h)) inc_h = hints.height_inc; } } if (s_x == e_x) keep_x1 = True; if (s_y == e_y) keep_y1 = True; if (s_x + s_w == e_x + e_w) keep_x2 = True; if (s_y + s_h == e_y + e_h) keep_y2 = True; /* animate the window */ for (i = 0; i <= steps; i++) { if (i == steps) { x = e_x; y = e_y; } else { float f; if (ppctMovement == NULL) { f = (float)i / (float)steps; } else { f = ppctMovement[i] / (float)steps; } x = (int)((float)s_x + (float)(e_x - s_x) * f); y = (int)((float)s_y + (float)(e_y - s_y) * f); } w = s_w + (int)(e_w - s_w) * i / steps; h = s_h + (int)(e_h - s_h) * i / steps; /* take the resize inc in account */ g_w = w - ((w - min_w) % inc_w); x += w-g_w; g_h = h - ((h - min_h) % inc_h); y += h-g_h; /* prevent annoying flickering */ if (keep_x1) x = s_x; if (keep_y1) y = s_y; if (keep_x2) g_w = s_x + s_w - x; if (keep_y2) g_h = s_y + s_h - y; if (g_w < min_w || g_h < min_h) { /* don't show zero width/height windows */ if (is_mapped) { XUnmapWindow(dpy, win); is_mapped = False; } } else { XMoveResizeWindow(dpy, win, x, y, g_w, g_h); if (!is_mapped) { XMapWindow(dpy, win); XMapSubwindows(dpy, win); is_mapped = True; } } /* make sure everything is updated */ if (do_sync) XSync(dpy, 0); if (us && i < steps && is_mapped) { /* don't sleep after the last step */ usleep(us); } } /* for */ /* if hints and asked size do not agree try to respect the caller */ if (e_w > 0 && e_h > 0 && (!is_mapped || g_w != w || g_h != w)) { XMoveResizeWindow(dpy, win, x, y, w, h); if (!is_mapped) { XMapWindow(dpy, win); XMapSubwindows(dpy, win); } if (do_sync) XSync(dpy, 0); } return; } /* This function returns the top level ancestor of the window 'child'. It * returns None if an error occurs or if the window is a top level window. */ Window GetTopAncestorWindow(Display *dpy, Window child) { Window root = None; Window ancestor = child; Window last_child = child; Window *children; unsigned int nchildren; if (child == None) return None; while (ancestor != root) { last_child = ancestor; children = NULL; if ( !XQueryTree( dpy, last_child, &root, &ancestor, &children, &nchildren)) { return None; } if (children) { XFree(children); } } return (last_child == child) ? None : last_child; } /* Given a parent window this function returns a list of children of the * parent window that have the same size, depth, visual and colormap as the * parent window and that have position +0+0 within the parent. If the 'depth' * argument is non-zero it must match the depth of the window. The 'visualid' * and 'colormap' arguments work just the same. The number of matching * children is returned. The list of children is returned in *children. If this * list is non-NULL, it must be free'd with XFree. If an error occurs or the * parent window does not match the required depth, colormap or visualid, the * function returns -1 and NULL in *children. */ int GetEqualSizeChildren( Display *dpy, Window parent, int depth, VisualID visualid, Colormap colormap, Window **ret_children) { XWindowAttributes pxwa; XWindowAttributes cxwa; Window JunkW; Window *children; unsigned int nchildren; int i; int j; if (!XGetWindowAttributes(dpy, parent, &pxwa)) return -1; if (!XQueryTree(dpy, parent, &JunkW, &JunkW, &children, &nchildren)) return -1; if (depth && pxwa.depth != depth) return -1; if (visualid && XVisualIDFromVisual(pxwa.visual) != visualid) return -1; if (colormap && pxwa.colormap != colormap) return -1; for (i = 0, j = 0; i < nchildren; i++) { if (XGetWindowAttributes(dpy, children[i], &cxwa) && cxwa.x == 0 && cxwa.y == 0 && cxwa.width == pxwa.width && cxwa.height == pxwa.height && (!depth || cxwa.depth == depth) && ( !visualid || XVisualIDFromVisual(cxwa.visual) == visualid) && cxwa.class == InputOutput && (!colormap || cxwa.colormap == colormap)) { children[j++] = children[i]; } } /* for */ if (j == 0) { if (children) { XFree(children); children = NULL; } } *ret_children = children; return j; } fvwm-2.7.0/libs/FTips.h0000644000175000017500000000327214147024700011552 00000000000000/* -*-c-*- */ /* Copyright (C) 2004 Olivier Chapuis */ #ifndef FVWMLIB_FTIPS_H #define FVWMLIB_FTIPS_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ typedef enum { FTIPS_PLACEMENT_UP, FTIPS_PLACEMENT_DOWN, FTIPS_PLACEMENT_LEFT, FTIPS_PLACEMENT_RIGHT, FTIPS_PLACEMENT_AUTO_UPDOWN, FTIPS_PLACEMENT_AUTO_LEFTRIGHT } ftips_placement_t; typedef enum { FTIPS_JUSTIFICATION_CENTER, FTIPS_JUSTIFICATION_LEFT_UP, FTIPS_JUSTIFICATION_RIGHT_DOWN } ftips_position_t; typedef struct { int colorset; Pixel fg; Pixel bg; Pixel border_pixel; int border_width; FlocaleFont *Ffont; ftips_placement_t placement; ftips_position_t justification; unsigned int placement_offset; /* pixel */ unsigned int justification_offset; /* pixel */ unsigned long delay; /* ms */ unsigned long mapped_delay; /* ms */ } ftips_config; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ Bool FTipsInit(Display *dpy); ftips_config *FTipsNewConfig(void); void FTipsOn( Display *dpy, Window win_f, ftips_config *fc, void *id, char *str, int x, int y, int w, int h); void FTipsCancel(Display *dpy); unsigned long FTipsCheck(Display *dpy); Bool FTipsExpose(Display *dpy, XEvent *ev); Bool FTipsHandleEvents(Display *dpy, XEvent *ev); void FTipsUpdateLabel(Display *dpy, char *str); void FTipsColorsetChanged(Display *dpy, int cs); #endif fvwm-2.7.0/libs/flist.h0000644000175000017500000000161514147024676011661 00000000000000/* -*-c-*- */ #ifndef FLIST_H #define FLIST_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ typedef struct _flist { void *object; struct _flist *next; struct _flist *prev; } flist; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ flist *flist_append_obj(flist *list, void *object); flist *flist_prepend_obj(flist *list, void *object); flist *flist_insert_obj(flist *list, void *object, int position); flist *flist_remove_obj(flist *list, void *object); flist *flist_free_list(flist *list); #endif /* FLIST_H */ fvwm-2.7.0/libs/Fsvg.h0000644000175000017500000000466714147024700011443 00000000000000#ifndef FSVG_H #define FSVG_H #ifdef HAVE_RSVG #define USE_SVG 1 #else #define USE_SVG 0 #endif #include "PictureBase.h" #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #if USE_SVG # include # include typedef RsvgDimensionData FRsvgDimensionData; typedef RsvgHandle FRsvgHandle; typedef cairo_surface_t Fcairo_surface_t; typedef cairo_t Fcairo_t; # define FCAIRO_FORMAT_ARGB32 CAIRO_FORMAT_ARGB32 # define FCAIRO_STATUS_SUCCESS CAIRO_STATUS_SUCCESS # define FG_OBJECT(a) G_OBJECT(a) # define Fg_object_unref(a) g_object_unref(a) # define Frsvg_handle_get_dimensions(a, b) \ rsvg_handle_get_dimensions(a, b) # define Frsvg_handle_new_from_file(a, b) rsvg_handle_new_from_file(a, b) # define Frsvg_handle_render_cairo(a, b) rsvg_handle_render_cairo(a, b) /* TA: 2013-01-22 -- rsvg_init() has been deprecated since version 2.36; but * RSVG doesn't define a version of its own to check against. Since RSVG uses * glib, we can check its version instead. */ #if !GLIB_CHECK_VERSION (2, 31, 0) # define Frsvg_init() rsvg_init() #endif #if !GLIB_CHECK_VERSION(2,35,0) # define Frsvg_init() g_type_init() #endif # define Fcairo_create(a) cairo_create(a) # define Fcairo_destroy(a) cairo_destroy(a) # define Fcairo_image_surface_create_for_data(a,b,c,d,e) \ cairo_image_surface_create_for_data(a,b,c,d,e) # define Fcairo_rotate(a, b) cairo_rotate(a, b) # define Fcairo_scale(a, b, c) cairo_scale(a, b, c) # define Fcairo_status(a) cairo_status(a) # define Fcairo_surface_destroy(a) cairo_surface_destroy(a) # define Fcairo_surface_status(a) cairo_surface_status(a) # define Fcairo_translate(a, b, c) cairo_translate(a, b, c) #else typedef struct { int width; int height; double em; double ex; } FRsvgDimensionData; typedef void FRsvgHandle; typedef void Fcairo_surface_t; typedef void Fcairo_t; # define FCAIRO_FORMAT_ARGB32 0 # define FCAIRO_STATUS_SUCCESS 0 # define FG_OBJECT(a) # define Fg_object_unref(a) # define Frsvg_handle_get_dimensions(a, b) # define Frsvg_handle_new_from_file(a, b) 0 # define Frsvg_handle_render_cairo(a, b) # define Frsvg_init() # define Fcairo_create(a) 0 # define Fcairo_destroy(a) # define Fcairo_image_surface_create_for_data(a,b,c,d,e) 0 # define Fcairo_rotate(a, b) # define Fcairo_scale(a, b, c) # define Fcairo_status(a) 0 # define Fcairo_surface_destroy(a) # define Fcairo_surface_status(a) 0 # define Fcairo_translate(a, b, c) #endif #endif /* FSVG_H */ fvwm-2.7.0/libs/Fft.c0000644000175000017500000003346514147024700011246 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include "fvwmlib.h" #include "wild.h" #include "Strings.h" #include "Flocale.h" #include "Fft.h" #include "FlocaleCharset.h" #include "FftInterface.h" #include "FRenderInit.h" #include "PictureBase.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ #define FFT_SET_ROTATED_90_MATRIX(m) \ ((m)->xx = (m)->yy = 0, (m)->xy = 1, (m)->yx = -1) #define FFT_SET_ROTATED_270_MATRIX(m) \ ((m)->xx = (m)->yy = 0, (m)->xy = -1, (m)->yx = 1) #define FFT_SET_ROTATED_180_MATRIX(m) \ ((m)->xx = (m)->yy = -1, (m)->xy = (m)->yx = 0) /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ static Display *fftdpy = NULL; static int fftscreen; static int fft_initialized = False; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ static void init_fft(Display *dpy) { fftdpy = dpy; fftscreen = DefaultScreen(dpy); fft_initialized = True; } static FftChar16 *FftUtf8ToFftString16(unsigned char *str, int len, int *nl) { FftChar16 *new; int i = 0, j= 0; new = (FftChar16 *)safemalloc((len+1)*sizeof(FftChar16)); while(i < len && str[i] != 0) { if (str[i] <= 0x7f) { new[j] = str[i]; } else if (str[i] <= 0xdf && i+1 < len) { new[j] = ((str[i] & 0x1f) << 6) + (str[i+1] & 0x3f); i++; } else if (i+2 < len) { new[j] = ((str[i] & 0x0f) << 12) + ((str[i+1] & 0x3f) << 6) + (str[i+2] & 0x3f); i += 2; } i++; j++; } *nl = j; return new; } static void FftSetupEncoding( Display *dpy, FftFontType *fftf, char *encoding, char *module) { FlocaleCharset *fc; if (!FftSupport || fftf == NULL) return; fftf->encoding = NULL; fftf->str_encoding = NULL; if (encoding != NULL) { fftf->str_encoding = encoding; } if (FftSupportUseXft2) { if (encoding != NULL) { fftf->encoding = encoding; } else if ((fc = FlocaleCharsetGetDefaultCharset(dpy,NULL)) != NULL && StrEquals(fc->x,FLC_FFT_ENCODING_ISO8859_1)) { fftf->encoding = FLC_FFT_ENCODING_ISO8859_1; } else { fftf->encoding = FLC_FFT_ENCODING_ISO10646_1; } } else if (FftSupport) { int i = 0; FftPatternElt *e; Fft1Font *f; f = (Fft1Font *)fftf->fftfont; while(i < f->pattern->num) { e = &f->pattern->elts[i]; if (StrEquals(e->object, FFT_ENCODING) && e->values->value.u.s != NULL) { fftf->encoding = e->values->value.u.s; return; } i++; } } } static FftFont *FftGetRotatedFont( Display *dpy, FftFont *f, rotation_t rotation) { FftPattern *rotated_pat; FftMatrix r,b; FftMatrix *pm = NULL; FftFont *rf = NULL; if (f == NULL) return NULL; memset(&b, 0, sizeof(FftMatrix)); rotated_pat = FftPatternDuplicate(f->pattern); if (rotated_pat == NULL) { return NULL; } if (rotation == ROTATION_90) { FFT_SET_ROTATED_90_MATRIX(&r); } else if (rotation == ROTATION_180) { FFT_SET_ROTATED_180_MATRIX(&r); } else if (rotation == ROTATION_270) { FFT_SET_ROTATED_270_MATRIX(&r); } else { goto bail; } if ((FftPatternGetMatrix( rotated_pat, FFT_MATRIX, 0, &pm) == FftResultMatch) && pm) { /* rotate the matrice */ b.xx = r.xx * pm->xx + r.xy * pm->yx; b.xy = r.xx * pm->xy + r.xy * pm->yy; b.yx = r.yx * pm->xx + r.yy * pm->yx; b.yy = r.yx * pm->xy + r.yy * pm->yy; } else { b.xx = r.xx; b.xy = r.xy; b.yx = r.yx; b.yy = r.yy; } if (FftPatternDel(rotated_pat, FFT_MATRIX)) { /* nothing */ } if (!FftPatternAddMatrix(rotated_pat, FFT_MATRIX, &b)) { goto bail; } rf = FftFontOpenPattern(dpy, rotated_pat); bail: if (!rf && rotated_pat) { FftPatternDestroy(rotated_pat); } return rf; } void FftPDumyFunc(void) { } /* ---------------------------- interface functions ------------------------ */ void FftGetFontHeights( FftFontType *fftf, int *height, int *ascent, int *descent) { /* fft font height may be > fftfont->ascent + fftfont->descent, this * depends on the minspace value */ *height = fftf->fftfont->height; *ascent = fftf->fftfont->ascent; *descent = fftf->fftfont->descent; return; } void FftGetFontWidths( FlocaleFont *flf, int *max_char_width) { FGlyphInfo extents; memset(&extents, 0, sizeof(FGlyphInfo)); /* FIXME: max_char_width should not be use in the all fvwm! */ if (FftUtf8Support && FLC_ENCODING_TYPE_IS_UTF_8(flf->fc)) { FftTextExtentsUtf8(fftdpy, flf->fftf.fftfont, (FftChar8*)"W", 1, &extents); } else { FftTextExtents8(fftdpy, flf->fftf.fftfont, (FftChar8*)"W", 1, &extents); } *max_char_width = extents.xOff; return; } FftFontType *FftGetFont(Display *dpy, char *fontname, char *module) { FftFont *fftfont = NULL; FftFontType *fftf = NULL; char *fn = NULL, *str_enc = NULL; FlocaleCharset *fc; FftPattern *src_pat = NULL, *load_pat = NULL; FftMatrix *a = NULL; FftResult result = 0; if (!FftSupport || !(FRenderGetExtensionSupported() || 1)) { return NULL; } if (!fontname) { return NULL; } if (!fft_initialized) { init_fft(dpy); } /* Xft2 always load an USC-4 fonts, that we consider as an USC-2 font * (i.e., an ISO106464-1 font) or an ISO8859-1 if the user ask for this * or the locale charset is ISO8859-1. * Xft1 support ISO106464-1, ISO8859-1 and others we load an * ISO8859-1 font by default if the locale charset is ISO8859-1 and * an ISO106464-1 one if this not the case */ if (matchWildcards("*?8859-1*", fontname)) { str_enc = FLC_FFT_ENCODING_ISO8859_1; } else if (matchWildcards("*?10646-1*", fontname)) { str_enc = FLC_FFT_ENCODING_ISO10646_1; } if (!FftSupportUseXft2 && str_enc == NULL) { if ((fc = FlocaleCharsetGetFLCXOMCharset()) != NULL && StrEquals(fc->x,FLC_FFT_ENCODING_ISO8859_1)) { fn = CatString2(fontname,":encoding=ISO8859-1"); } else { fn = CatString2(fontname,":encoding=ISO10646-1"); } } else { fn = fontname; } SUPPRESS_UNUSED_VAR_WARNING(fn); if ((src_pat = FftNameParse(fn)) == NULL) { goto bail; } SUPPRESS_UNUSED_VAR_WARNING(result); if ((load_pat = FftFontMatch(dpy, fftscreen, src_pat, &result)) == NULL) { goto bail; } /* safety check */ if (FftPatternGetMatrix( load_pat, FFT_MATRIX, 0, &a) == FftResultMatch && a) { FftMatrix b; Bool cm = False; memset(&b, 0, sizeof(FftMatrix)); if (a->xx < 0) { a->xx = -a->xx; cm = True; } if (a->yx != 0) { a->yx = 0; cm = True; } if (cm) { b.xx = a->xx; b.xy = a->xy; b.yx = a->yx; b.yy = a->yy; if (FftPatternDel(load_pat, FFT_MATRIX)) { /* nothing */ } if (!FftPatternAddMatrix(load_pat, FFT_MATRIX, &b)) { goto bail; } } } /* FIXME: other safety checking ? */ fftfont = FftFontOpenPattern(dpy, load_pat); if (!fftfont) { goto bail; } fftf = (FftFontType *)safemalloc(sizeof(FftFontType)); fftf->fftfont = fftfont; fftf->fftfont_rotated_90 = NULL; fftf->fftfont_rotated_180 = NULL; fftf->fftfont_rotated_270 = NULL; FftSetupEncoding(dpy, fftf, str_enc, module); bail: if (src_pat) { FftPatternDestroy(src_pat); } if (!fftf && load_pat) { FftPatternDestroy(load_pat); } return fftf; } void FftDrawString( Display *dpy, FlocaleFont *flf, FlocaleWinString *fws, Pixel fg, Pixel fgsh, Bool has_fg_pixels, int len, unsigned long flags) { FftDraw *fftdraw = NULL; typedef void (*DrawStringFuncType)( FftDraw *fftdraw, FftColor *fft_fg, FftFont *uf, int xt, int yt, char *str, int len); DrawStringFuncType DrawStringFunc; char *str; Bool free_str = False; XGCValues vr; XColor xfg, xfgsh; FftColor fft_fg, fft_fgsh; FftFontType *fftf; FftFont *uf; int x,y, xt,yt; float alpha_factor; flocale_gstp_args gstp_args; if (!FftSupport) { return; } fftf = &flf->fftf; if (fws->flags.text_rotation == ROTATION_90) /* CW */ { if (fftf->fftfont_rotated_90 == NULL) { fftf->fftfont_rotated_90 = FftGetRotatedFont(dpy, fftf->fftfont, fws->flags.text_rotation); } uf = fftf->fftfont_rotated_90; #ifdef FFT_BUGGY_FREETYPE y = fws->y + FftTextWidth(flf, fws->e_str, len); #else y = fws->y; #endif x = fws->x - FLF_SHADOW_BOTTOM_SIZE(flf); } else if (fws->flags.text_rotation == ROTATION_180) { if (fftf->fftfont_rotated_180 == NULL) { fftf->fftfont_rotated_180 = FftGetRotatedFont(dpy, fftf->fftfont, fws->flags.text_rotation); } uf = fftf->fftfont_rotated_180; y = fws->y; x = fws->x + FftTextWidth(flf, fws->e_str, len); } else if (fws->flags.text_rotation == ROTATION_270) { if (fftf->fftfont_rotated_270 == NULL) { fftf->fftfont_rotated_270 = FftGetRotatedFont(dpy, fftf->fftfont, fws->flags.text_rotation); } uf = fftf->fftfont_rotated_270; #ifdef FFT_BUGGY_FREETYPE y = fws->y; #else y = fws->y + FftTextWidth(flf, fws->e_str, len); #endif x = fws->x - FLF_SHADOW_UPPER_SIZE(flf); } else { uf = fftf->fftfont; y = fws->y; x = fws->x; } if (uf == NULL) return; fftdraw = FftDrawCreate(dpy, (Drawable)fws->win, Pvisual, Pcmap); if (fws->flags.has_clip_region) { if (FftDrawSetClip(fftdraw, fws->clip_region) == False) { /* just to suppress a compiler warning */ } } if (has_fg_pixels) { xfg.pixel = fg; xfgsh.pixel = fgsh; } else if (fws->gc && XGetGCValues(dpy, fws->gc, GCForeground, &vr)) { xfg.pixel = vr.foreground; } else { #if 0 fprintf(stderr, "[fvwmlibs][FftDrawString]: ERROR --" " cannot find color\n"); #endif xfg.pixel = PictureBlackPixel(); } XQueryColor(dpy, Pcmap, &xfg); alpha_factor = ((fws->flags.has_colorset)? ((float)fws->colorset->fg_alpha_percent/100) : 1); /* Render uses premultiplied alpha */ fft_fg.color.red = xfg.red * alpha_factor; fft_fg.color.green = xfg.green * alpha_factor; fft_fg.color.blue = xfg.blue * alpha_factor; fft_fg.color.alpha = 0xffff * alpha_factor; fft_fg.pixel = xfg.pixel; if (flf->shadow_size != 0 && has_fg_pixels) { XQueryColor(dpy, Pcmap, &xfgsh); fft_fgsh.color.red = xfgsh.red * alpha_factor; fft_fgsh.color.green = xfgsh.green * alpha_factor; fft_fgsh.color.blue = xfgsh.blue * alpha_factor; fft_fgsh.color.alpha = 0xffff * alpha_factor; fft_fgsh.pixel = xfgsh.pixel; } xt = x; yt = y; str = fws->e_str; if (FftUtf8Support && FLC_ENCODING_TYPE_IS_UTF_8(flf->fc)) { DrawStringFunc = (DrawStringFuncType)FftPDrawStringUtf8; } else if (FLC_ENCODING_TYPE_IS_UTF_8(flf->fc)) { DrawStringFunc = (DrawStringFuncType)FftPDrawString16; str = (char *)FftUtf8ToFftString16( (unsigned char *)fws->e_str, len, &len); free_str = True; } else if (FLC_ENCODING_TYPE_IS_USC_2(flf->fc)) { DrawStringFunc = (DrawStringFuncType)FftPDrawString16; } else if (FLC_ENCODING_TYPE_IS_USC_4(flf->fc)) { DrawStringFunc = (DrawStringFuncType)FftPDrawString32; } else { DrawStringFunc = (DrawStringFuncType)FftPDrawString8; } FlocaleInitGstpArgs(&gstp_args, flf, fws, x, y); if (flf->shadow_size != 0 && has_fg_pixels) { while (FlocaleGetShadowTextPosition(&xt, &yt, &gstp_args)) { DrawStringFunc( fftdraw, &fft_fgsh, uf, xt, yt, str, len); } } xt = gstp_args.orig_x; yt = gstp_args.orig_y; DrawStringFunc(fftdraw, &fft_fg, uf, xt, yt, str, len); if (free_str && str != NULL) { free(str); } FftDrawDestroy(fftdraw); return; } int FftTextWidth(FlocaleFont *flf, char *str, int len) { FGlyphInfo extents; int result = 0; if (!FftSupport) { return 0; } if (FftUtf8Support && FLC_ENCODING_TYPE_IS_UTF_8(flf->fc)) { FftTextExtentsUtf8( fftdpy, flf->fftf.fftfont, (FftChar8*)str, len, &extents); result = extents.xOff; } else if (FLC_ENCODING_TYPE_IS_UTF_8(flf->fc)) { FftChar16 *new; int nl; new = FftUtf8ToFftString16((unsigned char *)str, len, &nl); if (new != NULL) { FftTextExtents16( fftdpy, flf->fftf.fftfont, new, nl, &extents); result = extents.xOff; free(new); } } else if (FLC_ENCODING_TYPE_IS_USC_2(flf->fc)) { FftTextExtents16( fftdpy, flf->fftf.fftfont, (FftChar16 *)str, len, &extents); result = extents.xOff; } else if (FLC_ENCODING_TYPE_IS_USC_4(flf->fc)) { FftTextExtents32( fftdpy, flf->fftf.fftfont, (FftChar32 *)str, len, &extents); result = extents.xOff; } else { FftTextExtents8( fftdpy, flf->fftf.fftfont, (FftChar8 *)str, len, &extents); result = extents.xOff; } return result; } void FftPrintPatternInfo(FftFont *f, Bool vertical) { /* FftPatternPrint use stdout */ fflush (stderr); printf("\n height: %i, ascent: %i, descent: %i, maw: %i\n", f->height, f->ascent, f->descent, f->max_advance_width); if (!vertical) { printf(" "); FftPatternPrint(f->pattern); } else { FftMatrix *pm = NULL; if (FftPatternGetMatrix( f->pattern, FFT_MATRIX, 0, &pm) == FftResultMatch && pm) { printf(" matrix: (%f %f %f %f)\n", pm->xx, pm->xy, pm->yx, pm->yy); } } fflush (stdout); return; } fvwm-2.7.0/libs/XError.c0000644000175000017500000001441614147024700011743 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* * This function should be used by all modules and fvwm when a X error * occurs and the module exits. */ #include "config.h" #include #include #include #include "FRenderInit.h" #include "XError.h" #undef XSetErrorHandler #define USE_GET_ERROR_TEXT 1 #ifndef USE_GET_ERROR_TEXT static char *error_name(unsigned char code); #endif static char *request_name(unsigned char code); static char unknown[32]; void do_coredump(void) { fprintf(stderr, " Leaving a core dump now\n"); { char *nullp; nullp = NULL; *nullp = 99; } /* exit if this fails */ exit(99); } #define USE_GET_ERROR_TEXT 1 void PrintXErrorAndCoredump(Display *dpy, XErrorEvent *error, char *MyName) { char msg[256]; Bool suc = False; msg[255] = 0; #ifdef USE_GET_ERROR_TEXT /* can't call this from within an error handler! */ /* DV (21-Nov-2000): Well, actually we *can* call it in an error * handler since it does not trigger a protocol request. */ if (error->error_code >= FirstExtensionError) { suc = FRenderGetErrorText(error->error_code, msg); } if (!suc) XGetErrorText(dpy, error->error_code, msg, sizeof(msg)); fprintf(stderr,"%s: Cause of next X Error.\n", MyName); fprintf(stderr, " Error: %d (%s)\n", error->error_code, msg); #else fprintf(stderr,"%s: Cause of next X Error.\n", MyName); if (error->error_code >= FirstExtensionError) { suc = FRenderGetErrorText(error->error_code, msg); } if (suc) fprintf(stderr, " Error: %d (%s)\n", error->error_code, msg); else fprintf(stderr, " Error: %d (%s)\n", error->error_code, error_name(error->error_code)); #endif fprintf(stderr, " Major opcode of failed request: %d (%s)\n", error->request_code, request_name(error->request_code)); fprintf(stderr, " Minor opcode of failed request: %d \n", error->minor_code); /* error->resourceid may be uninitialised. This is no proble since we * are dumping core anyway. */ fprintf(stderr, " Resource id of failed request: 0x%lx \n", error->resourceid); /* leave a coredump */ do_coredump(); } #ifndef USE_GET_ERROR_TEXT /* this comes out of X.h */ static char *error_names[] = { "BadRequest", "BadValue", "BadWindow", "BadPixmap", "BadAtom", "BadCursor", "BadFont", "BadMatch", "BadDrawable", "BadAccess", "BadAlloc", "BadColor", "BadGC", "BadIDChoice", "BadName", "BadLength", "BadImplementation", }; static char *error_name(unsigned char code) { if (code == 0 || code > (sizeof(error_names) / sizeof(char *))) { sprintf(unknown, "Unknown: %d", (int)code); return unknown; } return error_names[code - 1]; } #endif /* this comes out of Xproto.h */ static char *code_names[] = { "CreateWindow", "ChangeWindowAttributes", "GetWindowAttributes", "DestroyWindow", "DestroySubwindows", "ChangeSaveSet", "ReparentWindow", "MapWindow", "MapSubwindows", "UnmapWindow", "UnmapSubwindows", "ConfigureWindow", "CirculateWindow", "GetGeometry", "QueryTree", "InternAtom", "GetAtomName", "ChangeProperty", "DeleteProperty", "GetProperty", "ListProperties", "SetSelectionOwner", "GetSelectionOwner", "ConvertSelection", "SendEvent", "GrabPointer", "UngrabPointer", "GrabButton", "UngrabButton", "ChangeActivePointerGrab", "GrabKeyboard", "UngrabKeyboard", "GrabKey", "UngrabKey", "AllowEvents", "GrabServer", "UngrabServer", "QueryPointer", "GetMotionEvents", "TranslateCoords", "WarpPointer", "SetInputFocus", "GetInputFocus", "QueryKeymap", "OpenFont", "CloseFont", "QueryFont", "QueryTextExtents", "ListFonts", "ListFontsWithInfo", "SetFontPath", "GetFontPath", "CreatePixmap", "FreePixmap", "CreateGC", "ChangeGC", "CopyGC", "SetDashes", "SetClipRectangles", "FreeGC", "ClearArea", "CopyArea", "CopyPlane", "PolyPoint", "PolyLine", "PolySegment", "PolyRectangle", "PolyArc", "FillPoly", "PolyFillRectangle", "PolyFillArc", "PutImage", "GetImage", "PolyText", "PolyText1", "ImageText", "ImageText1", "CreateColormap", "FreeColormap", "CopyColormapAndFree", "InstallColormap", "UninstallColormap", "ListInstalledColormaps", "AllocColor", "AllocNamedColor", "AllocColorCells", "AllocColorPlanes", "FreeColors", "StoreColors", "StoreNamedColor", "QueryColors", "LookupColor", "CreateCursor", "CreateGlyphCursor", "FreeCursor", "RecolorCursor", "QueryBestSize", "QueryExtension", "ListExtensions", "ChangeKeyboardMapping", "GetKeyboardMapping", "ChangeKeyboardControl", "GetKeyboardControl", "Bell", "ChangePointerControl", "GetPointerControl", "SetScreenSaver", "GetScreenSaver", "ChangeHosts", "ListHosts", "SetAccessControl", "SetCloseDownMode", "KillClient", "RotateProperties", "ForceScreenSaver", "SetPointerMapping", "GetPointerMapping", "SetModifierMapping", "GetModifierMapping", }; static char *request_name(unsigned char code) { if (code == 0 || code > (sizeof(code_names) / sizeof(char *))) { if (code == FRenderGetMajorOpCode()) { sprintf(unknown, "XRender"); } else { sprintf(unknown, "Unknown: %d", (int)code); } return unknown; } return code_names[code - 1]; } /* -------------------------- error handler stack -------------------------- */ static ferror_handler_t old_handler = NULL; void ferror_set_temp_error_handler(ferror_handler_t new_handler) { if (old_handler != NULL) { do_coredump(); } old_handler = XSetErrorHandler(old_handler); return; } void ferror_reset_temp_error_handler(void) { if (old_handler == NULL) { do_coredump(); } XSetErrorHandler(old_handler); old_handler = NULL; return; } int ferror_call_next_error_handler(Display *dpy, XErrorEvent *error) { int rc; if (old_handler == NULL) { do_coredump(); } rc = old_handler(dpy, error); return rc; } fvwm-2.7.0/libs/fsm.c0000644000175000017500000006004414147024700011305 00000000000000/* -*-c-*- */ /* Copyright (C) 2003 Olivier Chapuis * some code taken from the xsm: Copyright 1993, 1998 The Open Group */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* A set of functions for implementing a dummy sm. The code is based on xsm */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #ifdef HAVE_GETPWUID #include #endif #include #include #include #include #include #include #include "fvwmlib.h" #include "System.h" #include "flist.h" #include "fsm.h" /* #define FVWM_DEBUG_FSM */ /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ typedef struct { FIceConn ice_conn; int fd; } fsm_ice_conn_t; /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ static FIceAuthDataEntry *authDataEntries = NULL; static FIceIOErrorHandler prev_handler; static FIceListenObj *listenObjs; static char *addAuthFile = NULL; static char *remAuthFile = NULL; static flist *fsm_ice_conn_list = NULL; static flist *pending_ice_conn_list = NULL; static int numTransports = 0; static char *networkIds = NULL; static int *ice_fd = NULL; static char *module_name = NULL; static flist *running_list = NULL; static Bool fsm_init_succeed = False; static Atom _XA_WM_CLIENT_LEADER = None; static Atom _XA_SM_CLIENT_ID = None; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ /* * client list stuff */ static void free_fsm_client(fsm_client_t *client) { if (!SessionSupport) { return; } if (client->clientId) { free(client->clientId); } free(client); } /* * auth stuff */ static void fprintfhex(register FILE *fp, unsigned int len, char *cp) { static const char hexchars[] = "0123456789abcdef"; for (; len > 0; len--, cp++) { unsigned char s = *cp; putc(hexchars[s >> 4], fp); putc(hexchars[s & 0x0f], fp); } } /* * Host Based Authentication Callback. This callback is invoked if * the connecting client can't offer any authentication methods that * we can accept. We can accept/reject based on the hostname. */ static Bool HostBasedAuthProc(char *hostname) { return (0); /* For now, we don't support host based authentication */ } /* * We use temporary files which contain commands to add/remove entries from * the .ICEauthority file. */ static void write_iceauth(FILE *addfp, FILE *removefp, FIceAuthDataEntry *entry) { if (!SessionSupport) { return; } fprintf(addfp, "add %s \"\" %s %s ", entry->protocol_name, entry->network_id, entry->auth_name); fprintfhex(addfp, entry->auth_data_length, entry->auth_data); fprintf(addfp, "\n"); fprintf( removefp, "remove protoname=%s protodata=\"\" netid=%s authname=%s\n", entry->protocol_name, entry->network_id, entry->auth_name); } static char * unique_filename(char *path, char *prefix, int *pFd) { char *tempFile; tempFile = (char *)safemalloc(strlen(path) + strlen(prefix) + 8); sprintf(tempFile, "%s/%sXXXXXX", path, prefix); *pFd = fvwm_mkstemp(tempFile); if (*pFd == -1) { free(tempFile); tempFile = NULL; } return tempFile; } /* * Provide authentication data to clients that wish to connect */ #define MAGIC_COOKIE_LEN 16 static Status SetAuthentication( int count,FIceListenObj *listenObjs,FIceAuthDataEntry **authDataEntries) { FILE *addfp = NULL; FILE *removefp = NULL; char *path; int original_umask; char command[256]; int i; int fd; if (!SessionSupport) { return 0; } original_umask = umask (0077); /* disallow non-owner access */ path = (char *)getenv("SM_SAVE_DIR"); if (!path) { path = getenv("HOME"); } #ifdef HAVE_GETPWUID if (!path) { struct passwd *pwd; pwd = getpwuid(getuid()); if (pwd) { path = pwd->pw_dir; } } #endif if (!path) { path = "."; } if ((addAuthFile = unique_filename (path, ".fsm-", &fd)) == NULL) { goto bad; } if (!(addfp = fdopen(fd, "wb"))) { goto bad; } if ((remAuthFile = unique_filename (path, ".fsm-", &fd)) == NULL) { goto bad; } if (!(removefp = fdopen(fd, "wb"))) { goto bad; } *authDataEntries = (FIceAuthDataEntry *) safemalloc( count * 2 * sizeof (FIceAuthDataEntry)); for (i = 0; i < count * 2; i += 2) { (*authDataEntries)[i].network_id = FIceGetListenConnectionString(listenObjs[i/2]); (*authDataEntries)[i].protocol_name = "ICE"; (*authDataEntries)[i].auth_name = "MIT-MAGIC-COOKIE-1"; (*authDataEntries)[i].auth_data = FIceGenerateMagicCookie (MAGIC_COOKIE_LEN); (*authDataEntries)[i].auth_data_length = MAGIC_COOKIE_LEN; (*authDataEntries)[i+1].network_id = FIceGetListenConnectionString(listenObjs[i/2]); (*authDataEntries)[i+1].protocol_name = "XSMP"; (*authDataEntries)[i+1].auth_name = "MIT-MAGIC-COOKIE-1"; (*authDataEntries)[i+1].auth_data = FIceGenerateMagicCookie (MAGIC_COOKIE_LEN); (*authDataEntries)[i+1].auth_data_length = MAGIC_COOKIE_LEN; write_iceauth(addfp, removefp, &(*authDataEntries)[i]); write_iceauth(addfp, removefp, &(*authDataEntries)[i+1]); FIceSetPaAuthData(2, &(*authDataEntries)[i]); FIceSetHostBasedAuthProc(listenObjs[i/2], HostBasedAuthProc); } fclose(addfp); fclose(removefp); umask (original_umask); sprintf (command, "iceauth source %s", addAuthFile); { int n; n = system(command); (void)n; } unlink (addAuthFile); return 1; bad: if (addfp) { fclose (addfp); } if (removefp) { fclose (removefp); } if (addAuthFile) { unlink (addAuthFile); free (addAuthFile); } if (remAuthFile) { unlink (remAuthFile); free (remAuthFile); } return 0; } static void FreeAuthenticationData(int count, FIceAuthDataEntry *authDataEntries) { /* Each transport has entries for ICE and XSMP */ char command[256]; int i; if (!SessionSupport) { return; } for (i = 0; i < count * 2; i++) { free(authDataEntries[i].network_id); free(authDataEntries[i].auth_data); } free ((char *) authDataEntries); sprintf (command, "iceauth source %s", remAuthFile); { int n; n = system(command); (void)n; } unlink (remAuthFile); free (addAuthFile); free (remAuthFile); } /* * ice stuff */ static void MyIoErrorHandler(FIceConn ice_conn) { if (!SessionSupport) { return; } if (prev_handler) { (*prev_handler) (ice_conn); } } static void InstallIOErrorHandler(void) { FIceIOErrorHandler default_handler; if (!SessionSupport) { return; } prev_handler = FIceSetIOErrorHandler(NULL); default_handler = FIceSetIOErrorHandler(MyIoErrorHandler); if (prev_handler == default_handler) { prev_handler = NULL; } } static void CloseListeners(void) { if (!SessionSupport) { return; } FIceFreeListenObjs(numTransports, listenObjs); } static void ice_watch_fd( FIceConn conn, FIcePointer client_data, Bool opening, FIcePointer *watch_data) { fsm_ice_conn_t *fice_conn; if (!SessionSupport) { return; } if (opening) { fice_conn = (fsm_ice_conn_t *)safemalloc(sizeof(fsm_ice_conn_t)); fice_conn->ice_conn = conn; fice_conn->fd = FIceConnectionNumber(conn); *watch_data = (FIcePointer) fice_conn; fsm_ice_conn_list = flist_append_obj(fsm_ice_conn_list, fice_conn); fcntl(fice_conn->fd, F_SETFD, FD_CLOEXEC); } else { fice_conn = (fsm_ice_conn_t *)*watch_data; fsm_ice_conn_list = flist_remove_obj(fsm_ice_conn_list, fice_conn); free(fice_conn); } } /* * Session Manager callbacks */ static Status RegisterClientProc( FSmsConn smsConn, FSmPointer managerData, char *previousId) { fsm_client_t *client = (fsm_client_t *) managerData; char *id; int send_save = 0; if (!SessionSupport) { return 0; } #ifdef FVWM_DEBUG_FSM fprintf (stderr, "[%s][RegisterClientProc] On FIceConn fd = %d, received " "REGISTER CLIENT [Previous Id = %s]\n", module_name, FIceConnectionNumber (client->ice_conn), previousId ? previousId : "NULL"); #endif /* ignore previousID!! (we are dummy) */ id = FSmsGenerateClientID(smsConn); if (!FSmsRegisterClientReply(smsConn, id)) { /* cannot happen ? */ if (id) { free(id); } fprintf( stderr, "[%s][RegisterClientProc] ERR -- fail to register " "client", module_name); return 0; } #ifdef FVWM_DEBUG_FSM fprintf (stderr, "[%s][RegisterClientProc] On FIceConn fd = %d, sent " "REGISTER CLIENT REPLY [Client Id = %s]\n", module_name, FIceConnectionNumber (client->ice_conn), id); #endif client->clientId = id; /* client->clientHostname = FSmsClientHostName (smsConn); */ /* we are dummy ... do not do that */ if (send_save) { FSmsSaveYourself( smsConn, FSmSaveLocal, False, FSmInteractStyleNone, False); } return 1; } static void InteractRequestProc(FSmsConn smsConn, FSmPointer managerData, int dialogType) { if (!SessionSupport) { return; } /* no intercation! */ #if 0 FSmsInteract (client->smsConn); #endif } static void InteractDoneProc(FSmsConn smsConn, FSmPointer managerData, Bool cancelShutdown) { /* no intercation! */ } static void SaveYourselfReqProc(FSmsConn smsConn, FSmPointer managerData, int saveType, Bool shutdown, int interactStyle, Bool fast, Bool global) { /* no session to save */ } static void SaveYourselfPhase2ReqProc(FSmsConn smsConn, FSmPointer managerData) { fsm_client_t *client; if (!SessionSupport) { return; } client = (fsm_client_t *)managerData; SUPPRESS_UNUSED_VAR_WARNING(client); FSmsSaveYourselfPhase2(client->smsConn); } static void SaveYourselfDoneProc(FSmsConn smsConn, FSmPointer managerData, Bool success) { fsm_client_t *client; if (!SessionSupport) { return; } client = (fsm_client_t *) managerData; SUPPRESS_UNUSED_VAR_WARNING(client); FSmsSaveComplete(client->smsConn); } static void CloseDownClient(fsm_client_t *client) { if (!SessionSupport) { return; } #ifdef FVWM_DEBUG_FSM fprintf( stderr, "[%s][CloseDownClient] ICE Connection closed, " "FIceConn fd = %d\n", module_name, FIceConnectionNumber (client->ice_conn)); #endif FSmsCleanUp(client->smsConn); FIceSetShutdownNegotiation(client->ice_conn, False); if ((!FIceCloseConnection(client->ice_conn)) != FIceClosedNow) { /* do not care */ } client->ice_conn = NULL; client->smsConn = NULL; running_list = flist_remove_obj(running_list, client); free_fsm_client(client); } static void CloseConnectionProc(FSmsConn smsConn, FSmPointer managerData, int count, char **reasonMsgs) { fsm_client_t *client = (fsm_client_t *) managerData; if (!SessionSupport) { return; } FSmFreeReasons(count, reasonMsgs); CloseDownClient(client); } static void SetPropertiesProc( FSmsConn smsConn, FSmPointer managerData, int numProps, FSmProp **props) { int i; if (!SessionSupport) { return; } for (i = 0; i < numProps; i++) { FSmFreeProperty(props[i]); } free ((char *) props); } static void DeletePropertiesProc( FSmsConn smsConn, FSmPointer managerData, int numProps, char **propNames) { int i; if (!SessionSupport) { return; } for (i = 0; i < numProps; i++) { free (propNames[i]); } free ((char *) propNames); } static void GetPropertiesProc(FSmsConn smsConn, FSmPointer managerData) { } static Status NewClientProc( FSmsConn smsConn, FSmPointer managerData, unsigned long *maskRet, FSmsCallbacks *callbacksRet, char **failureReasonRet) { fsm_client_t *nc; if (!SessionSupport) { return 0; } nc = (fsm_client_t *)safemalloc(sizeof (fsm_client_t)); *maskRet = 0; nc->smsConn = smsConn; nc->ice_conn = FSmsGetIceConnection(smsConn); nc->clientId = NULL; running_list = flist_append_obj(running_list, nc); #ifdef FVWM_DEBUG_FSM fprintf( stderr, "[%s][NewClientProc] On FIceConn fd = %d, client " "set up session mngmt protocol\n", module_name, FIceConnectionNumber (nc->ice_conn)); #endif /* * Set up session manager callbacks. */ *maskRet |= FSmsRegisterClientProcMask; callbacksRet->register_client.callback = RegisterClientProc; callbacksRet->register_client.manager_data = (FSmPointer) nc; *maskRet |= FSmsInteractRequestProcMask; callbacksRet->interact_request.callback = InteractRequestProc; callbacksRet->interact_request.manager_data = (FSmPointer) nc; *maskRet |= FSmsInteractDoneProcMask; callbacksRet->interact_done.callback = InteractDoneProc; callbacksRet->interact_done.manager_data = (FSmPointer) nc; *maskRet |= FSmsSaveYourselfRequestProcMask; callbacksRet->save_yourself_request.callback = SaveYourselfReqProc; callbacksRet->save_yourself_request.manager_data = (FSmPointer) nc; *maskRet |= FSmsSaveYourselfP2RequestProcMask; callbacksRet->save_yourself_phase2_request.callback = SaveYourselfPhase2ReqProc; callbacksRet->save_yourself_phase2_request.manager_data = (FSmPointer) nc; *maskRet |= FSmsSaveYourselfDoneProcMask; callbacksRet->save_yourself_done.callback = SaveYourselfDoneProc; callbacksRet->save_yourself_done.manager_data = (FSmPointer) nc; *maskRet |= FSmsCloseConnectionProcMask; callbacksRet->close_connection.callback = CloseConnectionProc; callbacksRet->close_connection.manager_data = (FSmPointer) nc; *maskRet |= FSmsSetPropertiesProcMask; callbacksRet->set_properties.callback = SetPropertiesProc; callbacksRet->set_properties.manager_data = (FSmPointer) nc; *maskRet |= FSmsDeletePropertiesProcMask; callbacksRet->delete_properties.callback = DeletePropertiesProc; callbacksRet->delete_properties.manager_data = (FSmPointer) nc; *maskRet |= FSmsGetPropertiesProcMask; callbacksRet->get_properties.callback = GetPropertiesProc; callbacksRet->get_properties.manager_data = (FSmPointer) nc; return 1; } /* * */ static void CompletNewConnectionMsg(void) { flist *l = pending_ice_conn_list; FIceConn ice_conn; FIceAcceptStatus cstatus; if (!SessionSupport) { return; } while(l != NULL) { ice_conn = (FIceConn)l->object; cstatus = (FIceAcceptStatus)FIceConnectionStatus(ice_conn); if (cstatus == (int)FIceConnectPending) { l = l->next; } else if (cstatus == (int)FIceConnectAccepted) { l = l->next; pending_ice_conn_list = flist_remove_obj( pending_ice_conn_list, ice_conn); #ifdef FVWM_DEBUG_FSM char *connstr; connstr = FIceConnectionString (ice_conn); fprintf(stderr, "[%s][NewConnection] ICE Connection " "opened by client, FIceConn fd = %d, Accept at " "networkId %s\n", module_name, FIceConnectionNumber (ice_conn), connstr); free (connstr); #endif } else { if (FIceCloseConnection (ice_conn) != FIceClosedNow) { /* don't care */ } pending_ice_conn_list = flist_remove_obj( pending_ice_conn_list, ice_conn); #ifdef FVWM_DEBUG_FSM if (cstatus == FIceConnectIOError) { fprintf(stderr, "[%s][NewConnection] IO error " "opening ICE Connection!\n", module_name); } else { fprintf(stderr, "[%s][NewConnection] ICE " "Connection rejected!\n", module_name); } #endif } } } static void NewConnectionMsg(int i) { FIceConn ice_conn; FIceAcceptStatus status; if (!SessionSupport) { return; } SUPPRESS_UNUSED_VAR_WARNING(status); ice_conn = FIceAcceptConnection(listenObjs[i], &status); #ifdef FVWM_DEBUG_FSM fprintf(stderr, "[%s][NewConnection] %i\n", module_name, i); #endif if (!ice_conn) { #ifdef FVWM_DEBUG_FSM fprintf(stderr, "[%s][NewConnection] " "FIceAcceptConnection failed\n", module_name); #endif } else { pending_ice_conn_list = flist_append_obj(pending_ice_conn_list, ice_conn); CompletNewConnectionMsg(); } } static void ProcessIceMsg(fsm_ice_conn_t *fic) { FIceProcessMessagesStatus status; if (!SessionSupport) { return; } #ifdef FVWM_DEBUG_FSM fprintf(stderr, "[%s][ProcessIceMsg] %i\n", module_name, (int)fic->fd); #endif status = FIceProcessMessages(fic->ice_conn, NULL, NULL); if (status == FIceProcessMessagesIOError) { flist *cl; int found = 0; #ifdef FVWM_DEBUG_FSM fprintf(stderr, "[%s][ProcessIceMsg] IO error on connection\n", module_name); #endif for (cl = running_list; cl; cl = cl->next) { fsm_client_t *client = (fsm_client_t *) cl->object; if (client->ice_conn == fic->ice_conn) { CloseDownClient (client); found = 1; break; } } if (!found) { /* * The client must have disconnected before it was added * to the session manager's running list (i.e. before the * NewClientProc callback was invoked). */ FIceSetShutdownNegotiation (fic->ice_conn, False); if ((!FIceCloseConnection(fic->ice_conn)) != FIceClosedNow) { /* do not care */ } } } } /* * proxy stuff */ static char *GetClientID(Display *dpy, Window window) { char *client_id = NULL; Window client_leader = None; XTextProperty tp; Atom actual_type; int actual_format; unsigned long nitems; unsigned long bytes_after; unsigned char *prop = NULL; if (!SessionSupport) { return NULL; } if (!_XA_WM_CLIENT_LEADER) { _XA_WM_CLIENT_LEADER = XInternAtom( dpy, "WM_CLIENT_LEADER", False); } if (!_XA_SM_CLIENT_ID) { _XA_SM_CLIENT_ID = XInternAtom(dpy, "SM_CLIENT_ID", False); } if (XGetWindowProperty( dpy, window, _XA_WM_CLIENT_LEADER, 0L, 1L, False, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &prop) == Success) { if (actual_type == XA_WINDOW && actual_format == 32 && nitems == 1 && bytes_after == 0) { client_leader = (Window)(*(long *)prop); } } if (!client_leader) { client_leader = window; } if (client_leader) { if (XGetTextProperty(dpy, client_leader, &tp, _XA_SM_CLIENT_ID)) { if (tp.encoding == XA_STRING && tp.format == 8 && tp.nitems != 0) { client_id = (char *) tp.value; } } } if (prop) { XFree (prop); } return client_id; } static void set_session_manager(Display *dpy, Window window, char *sm) { Window client_leader = None; Atom actual_type; int actual_format; unsigned long nitems; unsigned long bytes_after; unsigned char *prop = NULL; char *dummy_id; static Atom _XA_SESSION_MANAGER = None; if (!SessionSupport) { return; } dummy_id = "0"; if (!_XA_SESSION_MANAGER) { _XA_SESSION_MANAGER = XInternAtom ( dpy, "SESSION_MANAGER", False); } if (!_XA_WM_CLIENT_LEADER) { _XA_WM_CLIENT_LEADER = XInternAtom( dpy, "WM_CLIENT_LEADER", False); } if (!_XA_SM_CLIENT_ID) { _XA_SM_CLIENT_ID = XInternAtom(dpy, "SM_CLIENT_ID", False); } if (XGetWindowProperty( dpy, window, _XA_WM_CLIENT_LEADER, 0L, 1L, False, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &prop) == Success) { if (actual_type == XA_WINDOW && actual_format == 32 && nitems == 1 && bytes_after == 0) { client_leader = (Window)(*(long *)prop); } } if (!client_leader) { client_leader = window; } #ifdef FVWM_DEBUG_FSM fprintf( stderr, "[%s][fsm_init] Proxy %s window 0x%lx\n", module_name, (sm)? "On":"Off", client_leader); #endif /* set the client id for ksmserver */ if (sm) { XChangeProperty( dpy, client_leader, _XA_SESSION_MANAGER, XA_STRING, 8, PropModeReplace, (unsigned char *)sm, strlen(sm)); XChangeProperty( dpy, client_leader, _XA_SM_CLIENT_ID, XA_STRING, 8, PropModeReplace, (unsigned char *)dummy_id, strlen(dummy_id)); } else { XDeleteProperty(dpy, client_leader, _XA_SESSION_MANAGER); XDeleteProperty(dpy, client_leader, _XA_SM_CLIENT_ID); } } /* ---------------------------- interface functions ------------------------ */ int fsm_init(char *module) { char errormsg[256]; int i; char *p; if (!SessionSupport) { /* -Wall fix */ MyIoErrorHandler(NULL); HostBasedAuthProc(NULL); ice_watch_fd(0, NULL, 0, NULL); NewClientProc(0, NULL, 0, NULL, NULL); #ifdef FVWM_DEBUG_FSM fprintf( stderr, "[%s][fsm_init] No Session Support\n", module_name); #endif return 0; } if (fsm_init_succeed) { fprintf( stderr, "[%s][fsm_init] <> -- " "Session already Initialized!\n", module_name); return 1; } module_name = module; InstallIOErrorHandler (); #ifdef FVWM_DEBUG_FSM fprintf(stderr, "[%s][fsm_init] FSmsInitialize\n", module_name); #endif if (!FSmsInitialize( module, "1.0", NewClientProc, NULL, HostBasedAuthProc, 256, errormsg)) { fprintf( stderr, "[%s][fsm_init] <> -- " "FSmsInitialize failed: %s\n", module_name, errormsg); return 0; } if (!FIceListenForConnections ( &numTransports, &listenObjs, 256, errormsg)) { fprintf( stderr, "[%s][fsm_init] <> -- " "FIceListenForConnections failed:\n" "%s\n", module_name, errormsg); return 0; } atexit(CloseListeners); if (!SetAuthentication(numTransports, listenObjs, &authDataEntries)) { fprintf( stderr, "[%s][fsm_init] <> -- " "Could not set authorization\n", module_name); return 0; } if (FIceAddConnectionWatch(&ice_watch_fd, NULL) == 0) { fprintf(stderr, "[%s][fsm_init] <> -- " "FIceAddConnectionWatch failed\n", module_name); return 0; } ice_fd = (int *)safemalloc(sizeof(int) * numTransports + 1); for (i = 0; i < numTransports; i++) { ice_fd[i] = FIceGetListenConnectionNumber(listenObjs[i]); } networkIds = FIceComposeNetworkIdList(numTransports, listenObjs); p = (char *)safemalloc( 16 + strlen(networkIds) + 1); sprintf(p, "SESSION_MANAGER=%s", networkIds); putenv(p); #ifdef FVWM_DEBUG_FSM fprintf(stderr,"[%s][fsm_init] OK: %i\n", module_name, numTransports); fprintf(stderr,"\t%s\n", p); #endif fsm_init_succeed = True; return 1; } void fsm_fdset(fd_set *in_fdset) { int i; flist *l = fsm_ice_conn_list; fsm_ice_conn_t *fic; if (!SessionSupport || !fsm_init_succeed) { return; } for (i = 0; i < numTransports; i++) { FD_SET(ice_fd[i], in_fdset); } while(l != NULL) { fic = (fsm_ice_conn_t *)l->object; FD_SET(fic->fd, in_fdset); l = l->next; } } Bool fsm_process(fd_set *in_fdset) { int i; flist *l = fsm_ice_conn_list; fsm_ice_conn_t *fic; if (!SessionSupport || !fsm_init_succeed) { return False; } if (pending_ice_conn_list != NULL) { CompletNewConnectionMsg(); } while(l != NULL) { fic = (fsm_ice_conn_t *)l->object; if (FD_ISSET(fic->fd, in_fdset)) { ProcessIceMsg(fic); } l = l->next; } for (i = 0; i < numTransports; i++) { if (FD_ISSET(ice_fd[i], in_fdset)) { NewConnectionMsg(i); } } if (pending_ice_conn_list != NULL) { return True; } return False; } /* this try to explain to ksmserver and various sm poxies that they should not * connect our non XSMP award leader window to the top level sm */ void fsm_proxy(Display *dpy, Window win, char *sm) { char *client_id; flist *l = running_list; Bool found = False; if (!SessionSupport || !fsm_init_succeed) { return; } client_id = GetClientID(dpy, win); if (client_id != NULL && strcmp("0", client_id) != 0) { for (l = running_list; l; l = l->next) { fsm_client_t *client = (fsm_client_t *) l->object; if (client->clientId && strcmp(client->clientId, client_id) == 0) { found = 1; break; } } } if (found) { return; } set_session_manager(dpy, win, sm); } void fsm_close(void) { if (!SessionSupport || !fsm_init_succeed) { return; } FreeAuthenticationData(numTransports, authDataEntries); } fvwm-2.7.0/libs/Colorset.h0000644000175000017500000001556314147024700012325 00000000000000/* -*-c-*- */ /* Fvwm colorset technology is Copyright (C) 1999 Joey Shutup http://www.streetmap.co.uk/streetmap.dll?Postcode2Map?BS24+9TZ You may use this code for any purpose, as long as the original copyright and this notice remains in the source code and all documentation */ #ifndef LIBS_COLORSETS_H #define LIBS_COLORSETS_H typedef struct { Pixel fg; Pixel bg; Pixel hilite; Pixel shadow; Pixel fgsh; Pixel tint; Pixel icon_tint; Pixmap pixmap; Pixmap shape_mask; unsigned int width : 12; unsigned int height : 12; unsigned int pixmap_type: 3; unsigned int shape_width : 12; unsigned int shape_height : 12; unsigned int shape_type : 2; unsigned int do_dither_icon : 1; unsigned int fg_alpha_percent : 7; unsigned int tint_percent : 7; unsigned int icon_alpha_percent : 7; unsigned int icon_tint_percent : 7; #ifdef FVWM_COLORSET_PRIVATE /* fvwm/colorset.c use only */ Pixel fg_tint; Pixel fg_saved; Pixel bg_tint; Pixel bg_saved; Pixmap mask; Pixmap alpha_pixmap; char *pixmap_args; char *gradient_args; char gradient_type; unsigned int color_flags; FvwmPicture *picture; Pixel *pixels; int nalloc_pixels; int fg_tint_percent; int bg_tint_percent; short image_alpha_percent; Bool dither; Bool allows_buffered_transparency; Bool is_maybe_root_transparent; #endif } colorset_t; #define PIXMAP_TILED 0 #define PIXMAP_STRETCH_X 1 #define PIXMAP_STRETCH_Y 2 #define PIXMAP_STRETCH 3 #define PIXMAP_STRETCH_ASPECT 4 #define PIXMAP_ROOT_PIXMAP_PURE 5 #define PIXMAP_ROOT_PIXMAP_TRAN 6 #define SHAPE_TILED 0 #define SHAPE_STRETCH 1 #define SHAPE_STRETCH_ASPECT 2 #ifdef FVWM_COLORSET_PRIVATE #define FG_SUPPLIED 0x1 #define BG_SUPPLIED 0x2 #define HI_SUPPLIED 0x4 #define SH_SUPPLIED 0x8 #define FGSH_SUPPLIED 0x10 #define FG_CONTRAST 0x20 #define BG_AVERAGE 0x40 #define TINT_SUPPLIED 0x80 #define FG_TINT_SUPPLIED 0x100 #define BG_TINT_SUPPLIED 0x200 #define ICON_TINT_SUPPLIED 0x400 #endif /* colorsets are stored as an array of structs to permit fast dereferencing */ extern colorset_t *Colorset; /* some macro for transparency */ #define CSET_IS_TRANSPARENT(cset) \ (cset >= 0 && (Colorset[cset].pixmap == ParentRelative || \ (Colorset[cset].pixmap != None && \ (Colorset[cset].pixmap_type == PIXMAP_ROOT_PIXMAP_TRAN ||\ Colorset[cset].pixmap_type == PIXMAP_ROOT_PIXMAP_PURE)))) #define CSET_IS_TRANSPARENT_PR(cset) \ (cset >= 0 && Colorset[cset].pixmap == ParentRelative) #define CSET_IS_TRANSPARENT_ROOT(cset) \ (cset >= 0 && Colorset[cset].pixmap != None && \ (Colorset[cset].pixmap_type == PIXMAP_ROOT_PIXMAP_TRAN ||\ Colorset[cset].pixmap_type == PIXMAP_ROOT_PIXMAP_PURE)) #define CSET_IS_TRANSPARENT_PR_PURE(cset) \ (cset >= 0 && Colorset[cset].pixmap == ParentRelative && \ Colorset[cset].tint_percent == 0) #define CSET_IS_TRANSPARENT_ROOT_PURE(cset) \ (cset >= 0 && Colorset[cset].pixmap != None && \ Colorset[cset].pixmap_type == PIXMAP_ROOT_PIXMAP_PURE) #define CSET_IS_TRANSPARENT_ROOT_TRAN(cset) \ (cset >= 0 && Colorset[cset].pixmap != None && \ Colorset[cset].pixmap_type == PIXMAP_ROOT_PIXMAP_TRAN) #define CSET_IS_TRANSPARENT_PR_TINT(cset) \ (cset >= 0 && Colorset[cset].pixmap == ParentRelative && \ Colorset[cset].tint_percent > 0) #define CSET_HAS_PIXMAP(cset) \ (cset >= 0 && Colorset[cset].pixmap) #define CSET_HAS_PIXMAP_TILED(cset) \ (CSET_HAS_PIXMAP(cset) && (Colorset[cset].pixmap_type & PIXMAP_TILED)) #define CSET_HAS_PIXMAP_STRETCH_X(cset) \ (CSET_HAS_PIXMAP(cset) && (Colorset[cset].pixmap_type & PIXMAP_STRETCH_X)) #define CSET_HAS_PIXMAP_STRETCH_Y(cset) \ (CSET_HAS_PIXMAP(cset) && (Colorset[cset].pixmap_type & PIXMAP_STRETCH_Y)) #define CSET_HAS_PIXMAP_STRETCH(cset) \ (CSET_HAS_PIXMAP(cset) && (Colorset[cset].pixmap_type & PIXMAP_STRETCH)) #define CSET_HAS_PIXMAP_STRETCH_ASPECT(cset) \ (CSET_HAS_PIXMAP(cset) && \ (Colorset[cset].pixmap_type & PIXMAP_STRETCH_ASPECT)) #define CSET_PIXMAP_IS_XY_STRETCHED(cset) \ (CSET_HAS_PIXMAP_STRETCH(cset) || CSET_HAS_PIXMAP_STRETCH_ASPECT(cset)) #define CSET_PIXMAP_IS_X_STRETCHED(cset) \ (CSET_PIXMAP_IS_XY_STRETCHED(cset) || CSET_HAS_PIXMAP_STRETCH_X(cset)) #define CSET_PIXMAP_IS_Y_STRETCHED(cset) \ (CSET_PIXMAP_IS_XY_STRETCHED(cset) || CSET_HAS_PIXMAP_STRETCH_Y(cset)) #define CSET_PIXMAP_IS_TILED(cset) \ (CSET_HAS_PIXMAP_TILED(cset)) /* some macro for transparency */ #define CSETS_IS_TRANSPARENT(cset) \ (cset != NULL && (cset->pixmap == ParentRelative || \ (cset->pixmap != None && \ (cset->pixmap_type == PIXMAP_ROOT_PIXMAP_TRAN ||\ cset->pixmap_type == PIXMAP_ROOT_PIXMAP_PURE)))) #define CSETS_IS_TRANSPARENT_ROOT(cset) \ (cset != NULL && cset->pixmap != None && \ (cset->pixmap_type == PIXMAP_ROOT_PIXMAP_TRAN ||\ cset->pixmap_type == PIXMAP_ROOT_PIXMAP_PURE)) #define CSETS_IS_TRANSPARENT_PR_PURE(cset) \ (cset != NULL && cset->pixmap == ParentRelative && \ cset->tint_percent == 0) #define CSETS_IS_TRANSPARENT_ROOT_PURE(cset) \ (cset != NULL && cset->pixmap != None && \ cset->pixmap_type == PIXMAP_ROOT_PIXMAP_PURE) #define CSETS_IS_TRANSPARENT_ROOT_TRAN(cset) \ (cset != NULL && cset->pixmap != None && \ cset->pixmap_type == PIXMAP_ROOT_PIXMAP_TRAN) #define CSETS_IS_TRANSPARENT_PR_TINT(cset) \ (cset != NULL && cset->pixmap == ParentRelative && \ cset->tint_percent > 0) #ifndef FVWM_COLORSET_PRIVATE /* Create n new colorsets, fvwm/colorset.c does its own thing (different size) */ void AllocColorset(int n); #endif /* dump one */ char *DumpColorset(int n, colorset_t *colorset); /* load one */ int LoadColorset(char *line); Pixmap CreateOffsetBackgroundPixmap( Display *dpy, Window win, int x, int y, int width, int height, colorset_t *colorset, unsigned int depth, GC gc, Bool is_mask); Pixmap CreateBackgroundPixmap( Display *dpy, Window win, int width, int height, colorset_t *colorset, unsigned int depth, GC gc, Bool is_mask); Pixmap ScrollPixmap( Display *dpy, Pixmap p, GC gc, int x_off, int y_off, int width, int height, unsigned int depth); void SetWindowBackgroundWithOffset( Display *dpy, Window win, int x_off, int y_off, unsigned int width, unsigned int height, colorset_t *colorset, unsigned int depth, GC gc, Bool clear_area); void SetWindowBackground( Display *dpy, Window win, int width, int height, colorset_t *colorset, unsigned int depth, GC gc, Bool clear_area); void GetWindowBackgroundPixmapSize( colorset_t *cs_t, int width, int height, int *w, int *h); Bool UpdateBackgroundTransparency( Display *dpy, Window win, int width, int height, colorset_t *colorset, unsigned int depth, GC gc, Bool clear_area); void SetRectangleBackground( Display *dpy, Window win, int x, int y, int width, int height, colorset_t *colorset, unsigned int depth, GC gc); void SetClippedRectangleBackground( Display *dpy, Window win, int x, int y, int width, int height, XRectangle *clip, colorset_t *colorset, unsigned int depth, GC gc); #endif fvwm-2.7.0/libs/FRender.c0000644000175000017500000003441614147024700012051 00000000000000/* -*-c-*- */ /* Copyright (C) 2002 Olivier Chapuis */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include #include "PictureBase.h" #include "Graphics.h" #include "PictureGraphics.h" #include "FRenderInit.h" #include "FRender.h" #include "FRenderInterface.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ static FRenderPictFormat *PFrenderVisualFormat = NULL; static FRenderPictFormat *PFrenderAlphaFormat = NULL; static FRenderPictFormat *PFrenderMaskFormat = NULL; static FRenderPictFormat *PFrenderDirectFormat = NULL; static FRenderPictFormat *PFrenderAbsoluteFormat = NULL; Bool FRenderVisualInitialized = False; /* #define USE_ABSOLUTE_FORMAT 1*/ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ static void FRenderVisualInit(Display *dpy) { FRenderPictFormat pf; if (!XRenderSupport || !FRenderGetExtensionSupported()) { return; } PFrenderVisualFormat = FRenderFindVisualFormat (dpy, Pvisual); if (!PFrenderVisualFormat) { fprintf(stderr,"[fvwmlibs][FRenderInit] -- ERROR: " "fail to create XRender Visual Format\n"); return; } pf.depth = 8; pf.type = FRenderPictTypeDirect; pf.direct.alpha = 0; pf.direct.alphaMask = 0xff; SUPPRESS_UNUSED_VAR_WARNING(pf); PFrenderAlphaFormat = FRenderFindFormat( dpy, FRenderPictFormatType| FRenderPictFormatDepth| FRenderPictFormatAlpha| FRenderPictFormatAlphaMask, &pf, 0); if (!PFrenderAlphaFormat) { fprintf(stderr,"[fvwmlibs][FRenderInit] -- ERROR: " "fail to create XRender Alpha Format\n"); return; } pf.depth = 1; pf.type = FRenderPictTypeDirect; pf.direct.alpha = 0; pf.direct.alphaMask = 1; PFrenderMaskFormat = FRenderFindFormat( dpy, FRenderPictFormatType| FRenderPictFormatDepth| FRenderPictFormatAlpha| FRenderPictFormatAlphaMask, &pf, 0); if (!PFrenderMaskFormat) { fprintf(stderr,"[fvwmlibs][FRenderInit] -- ERROR: " "fail to create XRender Mask Format\n"); return; } pf.depth = 24; pf.type = FRenderPictTypeDirect; pf.direct.alpha = 0; pf.direct.alphaMask = 0; pf.direct.red = 16; pf.direct.redMask = 0xff; pf.direct.green = 8; pf.direct.greenMask = 0xff; pf.direct.blue = 0; pf.direct.blueMask = 0xff; PFrenderDirectFormat = FRenderFindFormat( dpy, FRenderPictFormatType| FRenderPictFormatDepth| FRenderPictFormatRed| FRenderPictFormatRedMask| FRenderPictFormatGreen| FRenderPictFormatGreenMask| FRenderPictFormatBlue| FRenderPictFormatBlueMask| FRenderPictFormatAlpha| FRenderPictFormatAlphaMask, &pf, 0); if (!PFrenderDirectFormat) { fprintf(stderr,"[fvwmlibs][FRenderInit] -- ERROR: " "fail to create XRender Direct Format\n"); return; } pf.depth = 32; pf.type = FRenderPictTypeDirect; pf.direct.alpha = 24; pf.direct.alphaMask = 0xff; pf.direct.red = 16; pf.direct.redMask = 0xff; pf.direct.green = 8; pf.direct.greenMask = 0xff; pf.direct.blue = 0; pf.direct.blueMask = 0xff; PFrenderAbsoluteFormat = FRenderFindFormat( dpy, FRenderPictFormatType| FRenderPictFormatDepth| FRenderPictFormatRed| FRenderPictFormatRedMask| FRenderPictFormatGreen| FRenderPictFormatGreenMask| FRenderPictFormatBlue| FRenderPictFormatBlueMask| FRenderPictFormatAlpha| FRenderPictFormatAlphaMask, &pf, 0); if (!PFrenderAbsoluteFormat) { fprintf(stderr,"[fvwmlibs][FRenderInit] -- ERROR: " "fail to create XRender Absolute Format\n"); return; } } static Bool FRenderCompositeAndCheck( Display *dpy, int op, FRenderPicture src, FRenderPicture alpha, FRenderPicture dest, int x, int y, int a_x, int a_y, int d_x, int d_y, int d_w, int d_h) { FRenderComposite( dpy, op, src, alpha, dest, x, y, a_x, a_y, d_x, d_y, d_w, d_h); return True; } static Bool FRenderCreateShadePicture( Display *dpy, Window win, int alpha_percent) { static Pixmap shade_pixmap = None; static FRenderPicture shade_picture = None; static int saved_alpha_percent = 0; Bool force_update = False; FRenderColor frc; if (!XRenderSupport || !FRenderGetExtensionSupported()) { return 0; } /* FRender Visuals should be already initialized */ if (!shade_pixmap || !shade_picture) { FRenderPictureAttributes pa; if (!shade_pixmap) { shade_pixmap = XCreatePixmap(dpy, win, 1, 1, 8); } pa.repeat = True; if (shade_pixmap) { SUPPRESS_UNUSED_VAR_WARNING(pa); shade_picture = FRenderCreatePicture( dpy, shade_pixmap, PFrenderAlphaFormat, FRenderCPRepeat, &pa); } force_update = True; } if (shade_picture && (alpha_percent != saved_alpha_percent || force_update)) { frc.red = frc.green = frc.blue = 0; frc.alpha = 0xffff * (alpha_percent)/100; FRenderFillRectangle( dpy, FRenderPictOpSrc, shade_picture, &frc, 0, 0, 1, 1); saved_alpha_percent = alpha_percent; } return shade_picture; } static Bool FRenderTintPicture( Display *dpy, Window win, Pixel tint, int tint_percent, FRenderPicture dest_picture, int dest_x, int dest_y, int dest_w, int dest_h) { static Pixel saved_tint = 0; static int saved_tint_percent = 0; static Pixmap tint_pixmap = None; static FRenderPicture tint_picture = None; FRenderPicture shade_picture = None; Bool force_update = False; FRenderPictureAttributes pa; int rv = 0; if (!XRenderSupport) { return 0; } if (!tint_pixmap || !tint_picture) { pa.repeat = True; if (!tint_pixmap) { tint_pixmap = XCreatePixmap(dpy, win, 1, 1, 32); } if (tint_pixmap) { tint_picture = FRenderCreatePicture( dpy, tint_pixmap, PFrenderAbsoluteFormat, FRenderCPRepeat, &pa); if (!tint_picture) { goto bail; } } else { goto bail; } force_update = True; } if (tint_picture && (tint != saved_tint || tint_percent != saved_tint_percent || force_update)) { XColor color; float alpha_factor = (float)tint_percent/100; FRenderColor frc_tint; force_update = False; color.pixel = tint; XQueryColor(dpy, Pcmap, &color); frc_tint.red = color.red * alpha_factor; frc_tint.green = color.green * alpha_factor; frc_tint.blue = color.blue * alpha_factor; frc_tint.alpha = 0xffff * alpha_factor; SUPPRESS_UNUSED_VAR_WARNING(frc_tint); FRenderFillRectangle( dpy, FRenderPictOpSrc, tint_picture, &frc_tint, 0, 0, 1, 1); saved_tint = tint; saved_tint_percent = tint_percent; } if (!shade_picture) { shade_picture = FRenderCreateShadePicture(dpy, win, 100); } rv = FRenderCompositeAndCheck( dpy, FRenderPictOpOver, tint_picture, shade_picture, dest_picture, 0, 0, 0, 0, dest_x, dest_y, dest_w, dest_h); SUPPRESS_UNUSED_VAR_WARNING(pa); bail: return rv; } /* ---------------------------- interface functions ------------------------ */ Bool FRenderTintRectangle( Display *dpy, Window win, Pixmap mask, Pixel tint, int tint_percent, Drawable d, int dest_x, int dest_y, int dest_w, int dest_h) { FRenderPicture dest_picture = None; FRenderPictureAttributes pa; unsigned int val; Bool rv = True; if (!XRenderSupport || !FRenderGetExtensionSupported()) { return 0; } if (!FRenderVisualInitialized) { FRenderVisualInitialized = True; FRenderVisualInit(dpy); } if (!PFrenderVisualFormat || !PFrenderAlphaFormat || !PFrenderAbsoluteFormat || !PFrenderMaskFormat) { return 0; } pa.clip_mask = mask; val = FRenderCPClipMask; SUPPRESS_UNUSED_VAR_WARNING(val); SUPPRESS_UNUSED_VAR_WARNING(pa); if (!(dest_picture = FRenderCreatePicture( dpy, d, PFrenderVisualFormat, val, &pa))) { return 0; } rv = FRenderTintPicture( dpy, win, tint_percent, tint, dest_picture, dest_x, dest_y, dest_w, dest_h); FRenderFreePicture(dpy, dest_picture); return rv; } int FRenderRender( Display *dpy, Window win, Pixmap pixmap, Pixmap mask, Pixmap alpha, int depth, int added_alpha_percent, Pixel tint, int tint_percent, Drawable d, GC gc, GC alpha_gc, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, int dest_w, int dest_h, Bool do_repeat) { FRenderColor frc; Pixmap pixmap_copy = None; Pixmap alpha_copy = None; FRenderPicture shade_picture = None; FRenderPicture alpha_picture = None; FRenderPicture mask_picture = None; FRenderPicture src_picture = None; FRenderPicture dest_picture = None; FRenderPicture root_picture = None; FRenderPictureAttributes pa; unsigned long pam = 0; int alpha_x = src_x; int alpha_y = src_y; Bool rv = False; Bool free_alpha_gc = False; if (!XRenderSupport || !FRenderGetExtensionSupported()) { return 0; } if (!FRenderVisualInitialized) { FRenderVisualInitialized = True; FRenderVisualInit(dpy); } if (!PFrenderVisualFormat || !PFrenderAlphaFormat || !PFrenderAbsoluteFormat || !PFrenderMaskFormat) { return 0; } /* it is a bitmap ? */ if (Pdepth != depth && pixmap) { pixmap_copy = PictureBitmapToPixmap( dpy, win, pixmap, Pdepth, gc, src_x, src_y, src_w, src_h); src_x = src_y = 0; } pam = FRenderCPRepeat; if (do_repeat) { pa.repeat = True; } else { pa.repeat = False; } /* * build the src_picture */ if (pixmap == ParentRelative) { /* need backing store and good preparation of the win */ if (gc == None) { gc = PictureDefaultGC(dpy, win); } pixmap_copy = XCreatePixmap(dpy, win, src_w, src_h, Pdepth); if (pixmap_copy && gc) { XCopyArea( dpy, win, pixmap_copy, gc, src_x, src_y, src_w, src_h, 0, 0); } src_x = src_y = 0; } else if (tint_percent > 0 && !pixmap_copy) { if (gc == None) { gc = PictureDefaultGC(dpy, win); } pixmap_copy = XCreatePixmap(dpy, win, src_w, src_h, Pdepth); if (pixmap_copy && gc) { XCopyArea( dpy, pixmap, pixmap_copy, gc, src_x, src_y, src_w, src_h, 0, 0); } src_x = src_y = 0; } else if (!pixmap_copy) { SUPPRESS_UNUSED_VAR_WARNING(pa); SUPPRESS_UNUSED_VAR_WARNING(pam); src_picture = FRenderCreatePicture( dpy, pixmap, PFrenderVisualFormat, pam, &pa); } if (!src_picture && pixmap_copy) { src_picture = FRenderCreatePicture( dpy, pixmap_copy, PFrenderVisualFormat, pam, &pa); } if (!src_picture) { goto bail; } /* tint the src, it is why we have done a pixmap copy */ if (tint_percent > 0) { FRenderTintPicture( dpy, win, tint, tint_percent, src_picture, src_x, src_y, src_w, src_h); } if (added_alpha_percent >= 100) { if (alpha != None) { alpha_picture = FRenderCreatePicture( dpy, alpha, PFrenderAlphaFormat, pam, &pa); } else if (mask != None) { alpha_picture = FRenderCreatePicture( dpy, mask, PFrenderMaskFormat, pam, &pa); } else { /* fix a bug in certain XRender server implementation? */ if (!(shade_picture = FRenderCreateShadePicture( dpy, win, 100))) { goto bail; } alpha_x = alpha_y = 0; } } else { if (alpha != None) { alpha_copy = XCreatePixmap(dpy, win, src_w, src_h, 8); if (!alpha_gc) { alpha_gc = fvwmlib_XCreateGC( dpy, alpha, 0, NULL); free_alpha_gc = True; } if (alpha_copy && alpha_gc) { XCopyArea(dpy, alpha, alpha_copy, alpha_gc, alpha_x, alpha_y, src_w, src_h, 0, 0); alpha_picture = FRenderCreatePicture( dpy, alpha_copy, PFrenderAlphaFormat, pam, &pa); } if (alpha_gc && free_alpha_gc) { XFreeGC(dpy, alpha_gc); } alpha_x = alpha_y = 0; } else if (mask != None) { alpha_copy = XCreatePixmap(dpy, win, src_w, src_h, 8); if (alpha_copy) { alpha_picture = FRenderCreatePicture( dpy, alpha_copy, PFrenderAlphaFormat, pam, &pa); } if (alpha_picture) { frc.red = frc.green = frc.blue = frc.alpha = 0; FRenderFillRectangle( dpy, FRenderPictOpSrc, alpha_picture, &frc, 0, 0, src_w, src_h); } mask_picture = FRenderCreatePicture( dpy, mask, PFrenderMaskFormat, pam, &pa); } else { alpha_x = alpha_y = 0; } if (!(shade_picture = FRenderCreateShadePicture( dpy, win, added_alpha_percent))) { goto bail; } if (alpha != None && alpha_picture && shade_picture) { if (!FRenderCompositeAndCheck( dpy, FRenderPictOpAtopReverse, shade_picture, alpha_picture, alpha_picture, 0, 0, alpha_x, alpha_y, 0, 0, src_w, src_h)) { goto bail; } alpha_x = alpha_y = 0; } else if (mask != None && alpha_picture && shade_picture) { if (!FRenderCompositeAndCheck( dpy, FRenderPictOpAtopReverse, shade_picture, mask_picture, alpha_picture, 0, 0, alpha_x, alpha_y, 0, 0, src_w, src_h)) { goto bail; } alpha_x = alpha_y = 0; } } if (alpha_picture == None) { alpha_picture = shade_picture; } dest_picture = FRenderCreatePicture( dpy, d, PFrenderVisualFormat, 0, &pa); if (dest_picture) { rv = FRenderCompositeAndCheck( dpy, FRenderPictOpOver, src_picture, alpha_picture, dest_picture, src_x, src_y, alpha_x, alpha_y, dest_x, dest_y, dest_w, dest_h); } bail: if (dest_picture) { FRenderFreePicture(dpy, dest_picture); } if (src_picture) { FRenderFreePicture(dpy, src_picture); } if (alpha_picture && alpha_picture != shade_picture) { FRenderFreePicture(dpy, alpha_picture); } if (mask_picture) { FRenderFreePicture(dpy, mask_picture); } if (root_picture) { FRenderFreePicture(dpy, root_picture); } if (alpha_copy) { XFreePixmap(dpy, alpha_copy); } if (pixmap_copy) { XFreePixmap(dpy, pixmap_copy); } return rv; } fvwm-2.7.0/libs/setpgrp.c0000644000175000017500000000214214147024700012177 00000000000000/* -*-c-*- */ /* Copyright (C) 2002 Dominik Vogt */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ** setpgrp.c: ** Provides a portable replacement for setpgrp */ #include "config.h" #include #include "setpgrp.h" int fvwm_setpgrp(void) { int rc; #ifdef HAVE_SETPGID rc = setpgid(0, 0); #else # ifdef HAVE_SETPGRP # ifdef SETPGRP_VOID rc = setpgrp(); # else rc = setpgrp(0, 0); # endif # else /* neither setpgrp nor setpgid - just do nothing */ rc = 0; # endif #endif return rc; } fvwm-2.7.0/libs/ColorUtils.c0000644000175000017500000003156214147024700012622 00000000000000/* -*-c-*- */ /* * Around 12/20/99 we did the 3rd rewrite of the shadow/hilite stuff. * (That I know about (dje). * The first stuff I saw just applied a percentage. * Then we got some code from SCWM. * This stuff comes from "Visual.c" which is part of Lesstif. * Here's their copyright: * * Copyright (C) 1995 Free Software Foundation, Inc. * * This file is part of the GNU LessTif Library. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, see: * * * The routine at the bottom "pixel_to_color_string" was not from Lesstif. * * Port by Dan Espen, no additional copyright */ #include "config.h" /* must be first */ #include #include /* for X functions in general */ #include "fvwmlib.h" /* prototype GetShadow GetHilit */ #include "Parse.h" #include "Colorset.h" #include "PictureBase.h" #include "PictureUtils.h" #include "ColorUtils.h" #define PCT_BRIGHTNESS (6 * 0xffff / 100) /* How much lighter/darker to make things in default routine */ #define PCT_DARK_BOTTOM 70 /* lighter (less dark, actually) */ #define PCT_DARK_TOP 50 /* lighter */ #define PCT_LIGHT_BOTTOM 55 /* darker */ #define PCT_LIGHT_TOP 80 /* darker */ #define PCT_MEDIUM_BOTTOM_BASE 40 /* darker */ #define PCT_MEDIUM_BOTTOM_RANGE 25 #define PCT_MEDIUM_TOP_BASE 60 /* lighter */ #define PCT_MEDIUM_TOP_RANGE -30 /* The "brightness" of an RGB color. The "right" way seems to use * empirical values like the default thresholds below, but it boils down * to red is twice as bright as blue and green is thrice blue. */ #define BRIGHTNESS(r,g,b) (2*(int)(r) + 3*(int)(g) + 1*(int)(b)) /* From Xm.h on Solaris */ #define XmDEFAULT_DARK_THRESHOLD 15 #define XmDEFAULT_LIGHT_THRESHOLD 85 static XColor color; /**** This part is the old fvwm way to calculate colours. Still used for **** 'medium' brigness colours. */ #define DARKNESS_FACTOR 0.5 #define BRIGHTNESS_FACTOR 1.4 #define SCALE 65535.0 #define HALF_SCALE (SCALE / 2) typedef enum { R_MAX_G_MIN, R_MAX_B_MIN, G_MAX_B_MIN, G_MAX_R_MIN, B_MAX_R_MIN, B_MAX_G_MIN } MinMaxState; static void color_mult (unsigned short *red, unsigned short *green, unsigned short *blue, double k) { if (*red == *green && *red == *blue) { double temp; /* A shade of gray */ temp = k * (double) (*red); if (temp > SCALE) { temp = SCALE; } *red = (unsigned short)(temp); *green = *red; *blue = *red; } else { /* Non-zero saturation */ double r, g, b; double min, max; double a, l, s; double delta; double middle; MinMaxState min_max_state; r = (double) *red; g = (double) *green; b = (double) *blue; if (r > g) { if (r > b) { max = r; if (g < b) { min = g; min_max_state = R_MAX_G_MIN; a = b - g; } else { min = b; min_max_state = R_MAX_B_MIN; a = g - b; } } else { max = b; min = g; min_max_state = B_MAX_G_MIN; a = r - g; } } else { if (g > b) { max = g; if (b < r) { min = b; min_max_state = G_MAX_B_MIN; a = r - b; } else { min = r; min_max_state = G_MAX_R_MIN; a = b - r; } } else { max = b; min = r; min_max_state = B_MAX_R_MIN; a = g - r; } } delta = max - min; a = a / delta; l = (max + min) / 2; if (l <= HALF_SCALE) { s = max + min; } else { s = 2.0 * SCALE - (max + min); } s = delta/s; l *= k; if (l > SCALE) { l = SCALE; } s *= k; if (s > 1.0) { s = 1.0; } if (l <= HALF_SCALE) { max = l * (1 + s); } else { max = s * SCALE + l - s * l; } min = 2 * l - max; delta = max - min; middle = min + delta * a; switch (min_max_state) { case R_MAX_G_MIN: r = max; g = min; b = middle; break; case R_MAX_B_MIN: r = max; g = middle; b = min; break; case G_MAX_B_MIN: r = middle; g = max; b = min; break; case G_MAX_R_MIN: r = min; g = max; b = middle; break; case B_MAX_G_MIN: r = middle; g = min; b = max; break; case B_MAX_R_MIN: r = min; g = middle; b = max; break; } *red = (unsigned short) r; *green = (unsigned short) g; *blue = (unsigned short) b; } } /**** End of original fvwm code. ****/ static XColor *GetShadowOrHiliteColor( Pixel background, float light, float dark, float factor) { long brightness; unsigned int red, green, blue; memset(&color, 0, sizeof(color)); color.pixel = background; XQueryColor(Pdpy, Pcmap, &color); red = color.red; green = color.green; blue = color.blue; brightness = BRIGHTNESS(red, green, blue); /* For "dark" backgrounds, make everything a fixed %age lighter */ if (brightness < XmDEFAULT_DARK_THRESHOLD * PCT_BRIGHTNESS) { color.red = (unsigned short) (0xffff - ((0xffff - red) * dark + 50) / 100); color.green = (unsigned short) (0xffff - ((0xffff - green) * dark + 50) / 100); color.blue = (unsigned short) (0xffff - ((0xffff - blue) * dark + 50) / 100); } /* For "light" background, make everything a fixed %age darker */ else if (brightness > XmDEFAULT_LIGHT_THRESHOLD * PCT_BRIGHTNESS) { color.red = (unsigned short)((red * light + 50) / 100); color.green = (unsigned short)((green * light + 50) / 100); color.blue = (unsigned short)((blue * light + 50) / 100); } /* For "medium" background, select is a fixed %age darker; * top (lighter) and bottom (darker) are a variable %age * based on the background's brightness */ else { color_mult(&color.red, &color.green, &color.blue, factor); } return &color; } XColor *GetShadowColor(Pixel background) { return GetShadowOrHiliteColor( background, PCT_LIGHT_BOTTOM, PCT_DARK_BOTTOM, DARKNESS_FACTOR); } Pixel GetShadow(Pixel background) { XColor *colorp; colorp = GetShadowColor(background); PictureAllocColor(Pdpy, Pcmap, colorp, True); if (colorp->pixel == background) { colorp->pixel = PictureGetNextColor(colorp->pixel, 1); } return colorp->pixel; } XColor *GetHiliteColor(Pixel background) { return GetShadowOrHiliteColor( background, PCT_LIGHT_TOP, PCT_DARK_TOP, BRIGHTNESS_FACTOR); } Pixel GetHilite(Pixel background) { XColor *colorp; colorp = GetHiliteColor(background); PictureAllocColor(Pdpy, Pcmap, colorp, True); if (colorp->pixel == background) { colorp->pixel = PictureGetNextColor(colorp->pixel, -1); } return colorp->pixel; } XColor *GetForeShadowColor(Pixel foreground, Pixel background) { XColor bg_color; float fg[3], bg[3]; int result[3]; int i; memset(&color, 0, sizeof(color)); memset(&bg_color, 0, sizeof(bg_color)); color.pixel = foreground; bg_color.pixel = background; XQueryColor(Pdpy, Pcmap, &color); XQueryColor(Pdpy, Pcmap, &bg_color); fg[0] = color.red; fg[1] = color.green; fg[2] = color.blue; bg[0] = bg_color.red; bg[1]= bg_color.green; bg[2] = bg_color.blue; for (i=0; i<3; i++) { if (fg[i] - bg[i] < 8192 && fg[i] - bg[i] > -8192) { result[i] = 0; } else { result[i] = (int)((5 * bg[i] - fg[i]) / 4); if (fg[i] < bg[i] || result[i] < 0) { result[i] = (int)((3 * bg[i] + fg[i]) / 4); } } } color.red = result[0]; color.green = result[1]; color.blue = result[2]; return &color; } Pixel GetForeShadow(Pixel foreground, Pixel background) { XColor *colorp; colorp = GetForeShadowColor(foreground, background); PictureAllocColor(Pdpy, Pcmap, colorp, True); if (colorp->pixel == background) { colorp->pixel = PictureGetNextColor(colorp->pixel, 1); } return colorp->pixel; } XColor *GetTintedColor(Pixel in, Pixel tint, int percent) { XColor tint_color; memset(&color, 0, sizeof(color)); memset(&tint_color, 0, sizeof(tint_color)); color.pixel = in; XQueryColor(Pdpy, Pcmap, &color); tint_color.pixel = tint; XQueryColor(Pdpy, Pcmap, &tint_color); color.red = (unsigned short) (((100-percent)*color.red + tint_color.red * percent) / 100); color.green = (unsigned short) (((100-percent)*color.green + tint_color.green * percent) / 100); color.blue = (unsigned short) (((100-percent)*color.blue + tint_color.blue * percent) / 100); return &color; } Pixel GetTintedPixel(Pixel in, Pixel tint, int percent) { XColor *colorp; colorp = GetTintedColor(in, tint, percent); PictureAllocColor(Pdpy, Pcmap, colorp, True); return colorp->pixel; } /* This function converts the colour stored in a colorcell (pixel) into the * string representation of a colour. The output is printed at the * address 'output'. It is either in rgb format ("rgb:rrrr/gggg/bbbb") if * use_hash is False or in hash notation ("#rrrrggggbbbb") if use_hash is true. * The return value is the number of characters used by the string. The * rgb values of the output are undefined if the colorcell is invalid. The * memory area pointed at by 'output' must be at least 64 bytes (in case of * future extensions and multibyte characters).*/ int pixel_to_color_string( Display *dpy, Colormap cmap, Pixel pixel, char *output, Bool use_hash) { XColor color; int n; color.pixel = pixel; color.red = 0; color.green = 0; color.blue = 0; XQueryColor(dpy, cmap, &color); if (!use_hash) { sprintf( output, "rgb:%04x/%04x/%04x%n", (int)color.red, (int)color.green, (int)color.blue, &n); } else { sprintf( output, "#%04x%04x%04x%n", (int)color.red, (int)color.green, (int)color.blue, &n); } return n; } static char *colorset_names[] = { "$[fg.cs", "$[bg.cs", "$[hilight.cs", "$[shadow.cs", NULL }; Pixel GetSimpleColor(char *name) { XColor color; Bool is_illegal_rgb = False; memset(&color, 0, sizeof(color)); /* This is necessary because some X servers coredump when presented a * malformed rgb colour name. */ if (name && strncasecmp(name, "rgb:", 4) == 0) { int i; char *s; for (i = 0, s = name + 4; *s; s++) { if (*s == '/') i++; } if (i != 2) is_illegal_rgb = True; } if (is_illegal_rgb) { fprintf(stderr, "Illegal RGB format \"%s\"\n", name); } else if (!XParseColor (Pdpy, Pcmap, name, &color)) { fprintf(stderr, "Cannot parse color \"%s\"\n", name ? name : ""); } else if (!PictureAllocColor(Pdpy, Pcmap, &color, True)) { fprintf(stderr, "Cannot allocate color \"%s\"\n", name); } return color.pixel; } Pixel GetColor(char *name) { int i; int n; int cs; char *rest; XColor color; switch ((i = GetTokenIndex(name, colorset_names, -1, &rest))) { case 0: case 1: case 2: case 3: if (!isdigit(*rest) || (*rest == '0' && *(rest + 1) != 0)) { /* not a non-negative integer without leading zeros */ fprintf(stderr, "Invalid colorset number in color '%s'\n", name); return 0; } sscanf(rest, "%d%n", &cs, &n); if (*(rest + n) != ']') { fprintf(stderr, "No closing brace after '%d' in color '%s'\n", cs, name); return 0; } if (*(rest + n + 1) != 0) { fprintf(stderr, "Trailing characters after brace in" " color '%s'\n", name); return 0; } AllocColorset(cs); switch (i) { case 0: color.pixel = Colorset[cs].fg; break; case 1: color.pixel = Colorset[cs].bg; break; case 2: color.pixel = Colorset[cs].hilite; break; case 3: color.pixel = Colorset[cs].shadow; break; } if (!PictureAllocColor(Pdpy, Pcmap, &color, True)) { fprintf(stderr, "Cannot allocate color %d from" " colorset %d\n", i, cs); return 0; } return color.pixel; default: break; } return GetSimpleColor(name); } /* Allocates the color from the input Pixel again */ Pixel fvwmlib_clone_color(Pixel p) { XColor c; c.pixel = p; XQueryColor(Pdpy, Pcmap, &c); if (!PictureAllocColor(Pdpy, Pcmap, &c, True)) { fprintf(stderr, "Cannot allocate clone Pixel %d\n", (int)p); return 0; } return c.pixel; } /* Free an array of colours (n colours), never free black */ void fvwmlib_free_colors(Display *dpy, Pixel *pixels, int n, Bool no_limit) { int i; /* We don't ever free black - dirty hack to allow freeing colours at * all */ /* olicha: ???? */ for (i = 0; i < n; i++) { if (pixels[i] != 0) { PictureFreeColors( dpy, Pcmap, pixels + i, 1, 0, no_limit); } } return; } /* Copy one color and reallocate it */ void fvwmlib_copy_color( Display *dpy, Pixel *dst_color, Pixel *src_color, Bool do_free_dest, Bool do_copy_src) { if (do_free_dest) { fvwmlib_free_colors(dpy, dst_color, 1, True); } if (do_copy_src) { *dst_color = fvwmlib_clone_color(*src_color); } } fvwm-2.7.0/libs/FShape.h0000644000175000017500000001255314147024676011711 00000000000000/* -*-c-*- */ /* ** FShape.h: drop in replacements for the X shape library encapsulation */ #ifndef FVWMLIB_FSHAPE_H #define FVWMLIB_FSHAPE_H #ifdef SHAPE #include #define FShapeQueryExtension(dpy, evbase, errbase) \ XShapeQueryExtension(dpy, evbase, errbase) #define FShapeQueryVersion(dpy, vmajor, vminor) \ XShapeQueryVersion(dpy, vmajor, vminor) #define FShapeCombineRegion(dpy, dst, dst_kind, xoff, yoff, reg, op) \ XShapeCombineRegion(dpy, dst, dst_kind, xoff, yoff, reg, op) #define FShapeCombineRectangles( \ dpy, dst, dst_kind, xoff, yoff, rect, n_rects, op, ordering) \ XShapeCombineRectangles( \ dpy, dst, dst_kind, xoff, yoff, rect, n_rects, op, ordering) #define FShapeCombineMask(dpy, dst, dst_kind, xoff, yoff, src, op) \ XShapeCombineMask(dpy, dst, dst_kind, xoff, yoff, src, op) #define FShapeCombineShape(dpy, dst, dst_kind, xoff, yoff, src, src_kind, op) \ XShapeCombineShape(dpy, dst, dst_kind, xoff, yoff, src, src_kind, op) #define FShapeOffsetShape(dpy, dst, dst_kind, xoff, yoff) \ XShapeOffsetShape(dpy, dst, dst_kind, xoff, yoff) #define FShapeQueryExtents( \ dpy, w, bounding_shaped, xb, yb, wb, hb, clip_shaped, \ xclip, yclip, wclip, hclip) \ XShapeQueryExtents( \ dpy, w, bounding_shaped, xb, yb, wb, hb, clip_shaped, \ xclip, yclip, wclip, hclip) #define FShapeSelectInput(dpy, w, mask) \ XShapeSelectInput(dpy, w, mask) #define FShapeInputSelected(dpy, w) \ XShapeInputSelected(dpy, w) #define FShapeGetRectangles(dpy, w, kind, count, ordering) \ XShapeGetRectangles(dpy, w, kind, count, ordering) extern int FShapeEventBase; extern int FShapeErrorBase; /* Shapes compiled in? */ extern Bool FShapesSupported; /* Shapes supported by server? */ #define FHaveShapeExtension 1 void FShapeInit(Display *dpy); #else /* drop in replacements if shape support is not compiled in */ #define X_ShapeQueryVersion 0 #define X_ShapeRectangles 1 #define X_ShapeMask 2 #define X_ShapeCombine 3 #define X_ShapeOffset 4 #define X_ShapeQueryExtents 5 #define X_ShapeSelectInput 6 #define X_ShapeInputSelected 7 #define X_ShapeGetRectangles 8 #define ShapeSet 0 #define ShapeUnion 1 #define ShapeIntersect 2 #define ShapeSubtract 3 #define ShapeInvert 4 #define ShapeBounding 0 #define ShapeClip 1 #define ShapeNotifyMask (1L << 0) #define ShapeNotify 0 #define ShapeNumberEvents (FShapeNotify + 1) typedef struct { int type; /* of event */ unsigned long serial; /* # of last request processed by server */ Bool send_event; /* true if this came frome a SendEvent request */ Display *display; /* Display the event was read from */ Window window; /* window of event */ int kind; /* ShapeBounding or ShapeClip */ int x, y; /* extents of new region */ unsigned width, height; Time time; /* server timestamp when region changed */ Bool shaped; /* true if the region exists */ } XShapeEvent; #define FShapeQueryExtension(dpy, evbase, errbase) ((Bool)False) #define FShapeQueryVersion(dpy, vmajor, vminor) ((Status)0) #define FShapeCombineRegion(dpy, dst, dst_kind, xoff, yoff, reg, op) #define FShapeCombineRectangles( \ dpy, dst, dst_kind, xoff, yoff, rect, n_rects, op, ordering) #define FShapeCombineMask(dpy, dst, dst_kind, xoff, yoff, src, op) #define FShapeCombineShape(dpy, dst, dst_kind, xoff, yoff, src, src_kind, op) #define FShapeOffsetShape(dpy, dst, dst_kind, xoff, yoff) #define FShapeQueryExtents( \ dpy, w, bounding_shaped, xb, yb, wb, hb, clip_shaped, \ xclip, yclip, wclip, hclip) ((Status)0) #define FShapeSelectInput(dpy, w, mask) #define FShapeInputSelected(dpy, w) ((unsinged long)0) #define FShapeGetRectangles(dpy, w, kind, count, ordering) ((XRectangle *)0) /* define empty dummies */ #define FShapeEventBase 0 #define FShapeErrorBase 0 /* Shapes supported by server? */ #define FShapesSupported 0 /* Shapes compiled in? */ #define FHaveShapeExtension 0 #define FShapeInit(dpy) #endif /* fvwm replacements for shape lib */ #define F_ShapeQueryVersion X_ShapeQueryVersion #define F_ShapeRectangles X_ShapeRectangles #define F_ShapeMask X_ShapeMask #define F_ShapeCombine X_ShapeCombine #define F_ShapeOffset X_ShapeOffset #define F_ShapeQueryExtents X_ShapeQueryExtents #define F_ShapeSelectInput X_ShapeSelectInput #define F_ShapeInputSelected X_ShapeInputSelected #define F_ShapeGetRectangles X_ShapeGetRectangles #define FShapeSet ShapeSet #define FShapeUnion ShapeUnion #define FShapeIntersect ShapeIntersect #define FShapeSubtract ShapeSubtract #define FShapeInvert ShapeInvert #define FShapeBounding ShapeBounding #define FShapeClip ShapeClip #define FShapeNotifyMask ShapeNotifyMask #define FShapeNotify ShapeNotify #define FShapeNumberEvents ShapeNumberEvents typedef XShapeEvent FShapeEvent; #endif /* FVWMLIB_FSHAPE_H */ fvwm-2.7.0/libs/BidiJoin.h0000644000175000017500000000075514147024676012233 00000000000000/* -*-c-*- */ /* Copyright (C) 2002 Nadim Shaikli */ /* * FBidiJoin.h * * Interface to character shaping/joining that is required by most Bidi * (bidirectional) languages. */ #ifndef BIDIJOIN_H #define BIDIJOIN_H #include "config.h" #if HAVE_BIDI #include /* * Shape/Join a passed-in visual string */ int shape_n_join(FriBidiChar *str_visual, int str_len); #else /* !HAVE_BIDI */ #define shape_n_join(a, b) 0 #endif /* HAVE_BIDI */ #endif /* BIDIJOIN_H */ fvwm-2.7.0/libs/queue.c0000644000175000017500000001743314147024700011650 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include "safemalloc.h" #include "queue.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ typedef struct fqueue_record { struct fqueue_record *next; void *object; struct { unsigned is_scheduled_for_deletion; unsigned is_just_created; } flags; } fqueue_record; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ /* ---------------------------- interface functions ------------------------ */ /* Make newly added items permanent and destroy items scheduled for deletion. */ static void fqueue_cleanup_queue( fqueue *fq, destroy_fqueue_object_t destroy_func) { fqueue_record *head; fqueue_record *tail; fqueue_record *prev; fqueue_record *next; fqueue_record *rec; for (head = NULL, tail = NULL, prev = NULL, rec = fq->first; rec != NULL; rec = next) { if (rec->flags.is_scheduled_for_deletion) { /* destroy and skip it */ next = rec->next; if (rec->object != NULL && destroy_func != NULL) { destroy_func(rec->object); } if (prev != NULL) { prev->next = next; } free(rec); } else { rec->flags.is_just_created = 0; if (head == NULL) { head = rec; } tail = rec; prev = rec; next = rec->next; } } fq->first = head; fq->last = tail; return; } /* Recursively lock the queue. While locked, objects are not deleted from the * queue but marked for later deletion. New objects are marked as such and are * skipped by the queue functions. */ static void fqueue_lock_queue(fqueue *fq) { fq->lock_level++; return; } /* Remove one lock level */ static void fqueue_unlock_queue( fqueue *fq, destroy_fqueue_object_t destroy_func) { switch (fq->lock_level) { case 0: /* bug */ break; case 1: if (fq->flags.is_dirty) { fqueue_cleanup_queue(fq, destroy_func); } /* fall through */ default: fq->lock_level--; return; } return; } /* Chack and possibly execute the action associated with a queue object. * Schedule the object for deletion if it was executed. */ static void fqueue_operate( fqueue *fq, fqueue_record *rec, check_fqueue_object_t check_func, operate_fqueue_object_t operate_func, void *operate_args) { if (rec == NULL || rec->flags.is_scheduled_for_deletion) { return; } if (check_func == NULL || check_func(rec->object, operate_args) == 1) { if (operate_func != NULL) { operate_func(rec->object, operate_args); } rec->flags.is_scheduled_for_deletion = 1; fq->flags.is_dirty = 1; } return; } /* ---------------------------- builtin commands --------------------------- */ /* * Basic queue management */ void fqueue_init(fqueue *fq) { memset(fq, 0, sizeof(*fq)); return; } unsigned int fqueue_get_length(fqueue *fq) { unsigned int len; fqueue_record *t; for (t = fq->first, len = 0; t != NULL; t = t->next) { if (!t->flags.is_scheduled_for_deletion) { len++; } } return len; } /* * Add record to queue */ void fqueue_add_at_front( fqueue *fq, void *object) { fqueue_record *rec; rec = (fqueue_record *)safemalloc(sizeof(fqueue_record)); memset(rec, 0, sizeof(*rec)); rec->object = object; rec->next = fq->first; if (fq->lock_level > 0) { rec->flags.is_just_created = 1; fq->flags.is_dirty = 1; } fq->first = rec; return; } void fqueue_add_at_end( fqueue *fq, void *object) { fqueue_record *rec; rec = (fqueue_record *)safemalloc(sizeof(fqueue_record)); memset(rec, 0, sizeof(*rec)); rec->object = object; if (fq->lock_level > 0) { rec->flags.is_just_created = 1; fq->flags.is_dirty = 1; } if (fq->first == NULL) { fq->first = rec; } else { fq->last->next = rec; } fq->last = rec; rec->next = NULL; return; } void fqueue_add_inside( fqueue *fq, void *object, cmp_objects_t cmp_objects, void *cmp_args) { fqueue_record *rec; fqueue_record *p; fqueue_record *t; rec = (fqueue_record *)safemalloc(sizeof(fqueue_record)); memset(rec, 0, sizeof(*rec)); rec->object = object; if (fq->lock_level > 0) { rec->flags.is_just_created = 1; fq->flags.is_dirty = 1; } /* search place to insert record */ for (p = NULL, t = fq->first; t != NULL && cmp_objects(object, t->object, cmp_args) >= 0; p = t, t = t->next) { /* nothing to do here */ } /* insert record */ if (p == NULL) { /* insert at start */ rec->next = fq->first; fq->first = rec; } else { /* insert after p */ rec->next = p->next; p->next = rec; } if (t == NULL) { fq->last = rec; } return; } /* * Fetch queue objects */ /* Returns the object of the first queue record throuch *ret_object. Returns * 0 if the queue is empty and 1 otherwise. */ int fqueue_get_first( fqueue *fq, void **ret_object) { fqueue_record *rec; for (rec = fq->first; rec != NULL && rec->flags.is_scheduled_for_deletion; rec = rec->next) { /* nothing */ } if (rec == NULL) { return 0; } *ret_object = rec->object; return 1; } /* * Operate on queue objects and possibly remove them from the queue */ /* Runs the operate_func on the first record in the queue. If that function * is NULL or returns 1, the record is removed from the queue. The object of * the queue record must have been freed in operate_func. */ void fqueue_remove_or_operate_from_front( fqueue *fq, check_fqueue_object_t check_func, operate_fqueue_object_t operate_func, destroy_fqueue_object_t destroy_func, void *operate_args) { fqueue_lock_queue(fq); fqueue_operate(fq, fq->first, check_func, operate_func, operate_args); fqueue_unlock_queue(fq, destroy_func); return; } /* Same as above but operates on last record in queue */ void fqueue_remove_or_operate_from_end( fqueue *fq, check_fqueue_object_t check_func, operate_fqueue_object_t operate_func, destroy_fqueue_object_t destroy_func, void *operate_args) { fqueue_lock_queue(fq); fqueue_operate( fq, fq->last, check_func, operate_func, operate_args); fqueue_unlock_queue(fq, destroy_func); return; } /* Same as above but operates on all records in the queue. */ void fqueue_remove_or_operate_all( fqueue *fq, check_fqueue_object_t check_func, operate_fqueue_object_t operate_func, destroy_fqueue_object_t destroy_func, void *operate_args) { fqueue_record *t; if (fq->first == NULL) { return; } fqueue_lock_queue(fq); /* search record(s) to remove */ for (t = fq->first; t != NULL; t = t->next) { if (t->flags.is_just_created || t->flags.is_scheduled_for_deletion) { /* skip */ continue; } fqueue_operate(fq, t, check_func, operate_func, operate_args); } fqueue_unlock_queue(fq, destroy_func); return; } fvwm-2.7.0/libs/Parse.h0000644000175000017500000000627614147024700011606 00000000000000/* -*-c-*- */ #ifndef FVWMLIB_PARSE_H #define FVWMLIB_PARSE_H /* ---------------------------- included header files ---------------------- */ #include "libs/Strings.h" /* ---------------------------- global definitions ------------------------- */ #define MAX_TOKEN_LENGTH 1023 /* ---------------------------- global macros ------------------------------ */ /* * Stuff for consistent parsing */ #define IsQuote(c) ((c) == '"' || (c) == '\'' || (c) =='`') #define IsBlockStart(c) ((c) == '[' || (c) == '{' || (c) == '(') #define IsBlockEnd(c,cs) (((c) == ']' && (cs) == '[') || ((c) == '}' && (cs) == '{') || ((c) == ')' && (cs) == '(')) /* * function: FindToken * description: find the entry of type 'struct_entry' * holding 'key' in 'table' * returns: pointer to the matching entry * NULL if not found * * table must be sorted in ascending order for FindToken. */ #define FindToken(key,table,struct_entry) \ (struct_entry *) bsearch( \ key, \ (char *)(table), \ sizeof(table) / sizeof(struct_entry), \ sizeof(struct_entry), \ (int(*)(const void*, const void*))XCmpToken) /* ---------------------------- type definitions --------------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ char *EscapeString(char *s, const char *qchars, char echar); char *SkipQuote( char *s, const char *qlong, const char *qstart, const char *qend); char *GetQuotedString( char *sin, char **sout, const char *delims, const char *qlong, const char *qstart, const char *qend); char *SkipSpaces(char *indata, char *spaces, int snum); char *DoPeekToken( char *indata, char **token, char *spaces, char *delims, char *out_delim); char *PeekToken(char *indata, char **token); int MatchToken(char *pstr,char *tok); /* old style parse routine: */ char *DoGetNextToken( char *indata,char **token, char *spaces, char *delims, char *out_delim); char *GetNextToken(char *indata,char **token); char *GetNextSimpleOption(char *indata, char **option); char *GetNextFullOption(char *indata, char **option); char *SkipNTokens(char *indata, unsigned int n); char *GetModuleResource(char *indata, char **resource, char *module_name); int GetSuffixedIntegerArguments( char *action, char **ret_action, int *retvals, int num, char *suffixlist, int *ret_suffixnum); int GetIntegerArgumentsAnyBase( char *action, char **ret_action, int *retvals,int num); int SuffixToPercentValue(int value, int suffix, int *unit_table); int GetIntegerArguments(char *action, char**ret_action, int *retvals,int num); int GetTokenIndex(char *token, char **list, int len, char **next); char *GetNextTokenIndex(char *action, char **list, int len, int *index); int GetRectangleArguments(char *action, int *width, int *height); int GetOnePercentArgument(char *action, int *value, int *unit_io); int GetTwoPercentArguments( char *action, int *val1, int *val2, int *val1_unit, int *val2_unit); int ParseToggleArgument( char *action, char **ret_action, int default_ret, char no_toggle); int XCmpToken(const char *s, const char **t); char *GetFileNameFromPath(char *path); #endif fvwm-2.7.0/libs/FTips.c0000644000175000017500000003375614147024700011557 00000000000000/* -*-c-*- */ /* Copyright (C) 2004 Olivier Chapuis */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include "libs/ftime.h" #include #include #include "defaults.h" #include "fvwmlib.h" #include "Strings.h" #include "PictureBase.h" #include "Flocale.h" #include "Graphics.h" #include "Colorset.h" #include "libs/FScreen.h" #include "FTips.h" /* ---------------------------- local definitions -------------------------- */ #define FVWM_TIPS_NOTHING 0 #define FVWM_TIPS_WAITING 1 #define FVWM_TIPS_MAPPED 2 /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ static Window win = None; static GC gc = None; static Window win_for; static ftips_config *current_config, *default_config; static char *label; static int state = FVWM_TIPS_NOTHING; static void *boxID = NULL; static FlocaleWinString fwin_string; static rectangle box; static unsigned long timeOut; static unsigned long onTime; static Atom _net_um_for = None; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ static unsigned long __get_time(void) { struct timeval t; gettimeofday(&t, NULL); return (1000*t.tv_sec + t.tv_usec/1000); } static void __initialize_window(Display *dpy) { XGCValues xgcv; unsigned long valuemask; XSetWindowAttributes attributes; Atom _net_um_window_type; long _net_um_window_type_tooltips; valuemask = CWOverrideRedirect | CWEventMask | CWColormap; attributes.override_redirect = True; attributes.event_mask = ExposureMask; attributes.colormap = Pcmap; win = XCreateWindow( dpy, DefaultRootWindow(dpy), 0, 0, 1, 1, current_config->border_width, Pdepth, InputOutput, Pvisual, valuemask, &attributes); _net_um_window_type = XInternAtom( dpy, "_NET_UM_WINDOW_TYPE", False); _net_um_window_type_tooltips = XInternAtom( dpy, "_NET_UM_WINDOW_TYPE_TOOLTIPS", False); XChangeProperty( dpy, win, _net_um_window_type, XA_ATOM, 32, PropModeReplace, (unsigned char *) &_net_um_window_type_tooltips, 1); _net_um_for = XInternAtom(dpy, "_NET_UM_FOR", False); gc = fvwmlib_XCreateGC(dpy, win, 0, &xgcv); return; } static void __setup_cs(Display *dpy) { XSetWindowAttributes xswa; unsigned long valuemask = 0; if (current_config->colorset > -1) { xswa.border_pixel = Colorset[current_config->colorset].fg; xswa.background_pixel = Colorset[current_config->colorset].bg; if (Colorset[current_config->colorset].pixmap) { /* set later */ xswa.background_pixmap = None; valuemask = CWBackPixmap | CWBorderPixel;; } else { valuemask = CWBackPixel | CWBorderPixel; } } else { xswa.border_pixel = current_config->border_pixel; xswa.background_pixel = current_config->bg; valuemask = CWBackPixel | CWBorderPixel; } XChangeWindowAttributes(dpy, win, valuemask, &xswa); } static void __setup_gc(Display *dpy) { XGCValues xgcv; unsigned long valuemask; valuemask = GCForeground; if (current_config->colorset > -1) { xgcv.foreground = Colorset[current_config->colorset].fg; } else { xgcv.foreground = current_config->fg; } if (current_config->Ffont && current_config->Ffont->font != NULL) { xgcv.font = current_config->Ffont->font->fid; valuemask |= GCFont; } XChangeGC(dpy, gc, valuemask, &xgcv); return; } static void __draw(Display *dpy) { if (!current_config->Ffont) { return; } fwin_string.str = label; fwin_string.win = win; fwin_string.gc = gc; if (current_config->colorset > -1) { fwin_string.colorset = &Colorset[current_config->colorset]; fwin_string.flags.has_colorset = True; } else { fwin_string.flags.has_colorset = False; } fwin_string.x = 2; fwin_string.y = current_config->Ffont->ascent; FlocaleDrawString(dpy, current_config->Ffont, &fwin_string, 0); return; } static void __map_window(Display *dpy) { rectangle new_g; rectangle screen_g; Window dummy; fscreen_scr_arg *fsarg = NULL; /* for now no xinerama support */ ftips_placement_t placement; int x,y; static int border_width = 1; static Window win_f = None; if (border_width != current_config->border_width) { XSetWindowBorderWidth(dpy, win, current_config->border_width); border_width = current_config->border_width; } FScreenGetScrRect( fsarg, FSCREEN_GLOBAL, &screen_g.x, &screen_g.y, &screen_g.width, &screen_g.height); new_g.height = ((current_config->Ffont)? current_config->Ffont->height:0) + 1; new_g.width = 4; if (label && current_config->Ffont) { new_g.width += FlocaleTextWidth( current_config->Ffont, label, strlen(label)); } if (current_config->placement != FTIPS_PLACEMENT_AUTO_UPDOWN && current_config->placement != FTIPS_PLACEMENT_AUTO_LEFTRIGHT) { placement = current_config->placement; } else { XTranslateCoordinates( dpy, win_for, DefaultRootWindow(dpy), box.x, box.y, &x, &y, &dummy); if (current_config->placement == FTIPS_PLACEMENT_AUTO_UPDOWN) { if (y + box.height/2 >= screen_g.height/2) { placement = FTIPS_PLACEMENT_UP; } else { placement = FTIPS_PLACEMENT_DOWN; } } else { if (x + box.width/2 >= screen_g.width/2) { placement = FTIPS_PLACEMENT_LEFT; } else { placement = FTIPS_PLACEMENT_RIGHT; } } } if (placement == FTIPS_PLACEMENT_RIGHT || placement == FTIPS_PLACEMENT_LEFT) { if (current_config->justification == FTIPS_JUSTIFICATION_CENTER) { y = box.y + (box.height / 2) - (new_g.height / 2) - current_config->border_width; } else if (current_config->justification == FTIPS_JUSTIFICATION_RIGHT_DOWN) { y = box.y + box.height - new_g.height - (2 * current_config->border_width) - current_config->justification_offset; } else /* LEFT_UP */ { y = box.y + current_config->justification_offset; } } else /* placement == FTIPS_PLACEMENT_DOWN || placement == FTIPS_PLACEMENT_UP */ { if (current_config->justification == FTIPS_JUSTIFICATION_CENTER) { x = box.x + (box.width / 2) - (new_g.width / 2) - current_config->border_width; } else if (current_config->justification == FTIPS_JUSTIFICATION_RIGHT_DOWN) { x = box.x + box.width - new_g.width - (2 * current_config->border_width) - current_config->justification_offset; } else /* LEFT_UP */ { x = box.x + current_config->justification_offset; } } if (placement == FTIPS_PLACEMENT_RIGHT) { x = box.x + box.width + current_config->placement_offset + 1; } else if (placement == FTIPS_PLACEMENT_LEFT) { x = box.x - current_config->placement_offset - new_g.width - (2 * current_config->border_width) - 1; } else if (placement == FTIPS_PLACEMENT_DOWN) { y = box.y + box.height + current_config->placement_offset - 0; } else /* UP */ { y = box.y - current_config->placement_offset - new_g.height + 0 - (2 * current_config->border_width); } XTranslateCoordinates( dpy, win_for, DefaultRootWindow(dpy), x, y, &new_g.x, &new_g.y, &dummy); if (placement == FTIPS_PLACEMENT_RIGHT || placement == FTIPS_PLACEMENT_LEFT) { int x1,y1,l1,l2; if (new_g.x < 2) { x = box.x + box.width + current_config->placement_offset + 1; XTranslateCoordinates( dpy, win_for, DefaultRootWindow(dpy), x, y, &x1, &y1, &dummy); /* */ l1 = new_g.width + new_g.x - 2; l2 = screen_g.width - (x1 + new_g.width) - current_config->border_width - 2; if (l2 > l1) { new_g.x = x1; } } else if (new_g.x + new_g.width > screen_g.width - (2 * current_config->border_width) - 2) { x = box.x - current_config->placement_offset - new_g.width - (2 * current_config->border_width) - 1; XTranslateCoordinates( dpy, win_for, DefaultRootWindow(dpy), x, y, &x1, &y1, &dummy); /* */ l1 = new_g.width + x1 - 2; l2 = screen_g.width - (new_g.x + new_g.width) - (2 * current_config->border_width) - 2; if (l1 > l2) { new_g.x = x1; } } if ( new_g.y < 2 ) { new_g.y = 2; } else if (new_g.y + new_g.height > screen_g.height - (2 * current_config->border_width) - 2) { new_g.y = screen_g.height - new_g.height - (2 * current_config->border_width) - 2; } } else /* placement == FTIPS_PLACEMENT_DOWN || placement == FTIPS_PLACEMENT_UP */ { if (new_g.y < 2) { y = box.y + box.height + current_config->placement_offset - 0; XTranslateCoordinates( dpy, win_for, DefaultRootWindow(dpy), x, y, &new_g.x, &new_g.y, &dummy); } else if (new_g.y + new_g.height > screen_g.height - (2 * current_config->border_width) - 2) { y = box.y - current_config->placement_offset - new_g.height + 0 - (2 * current_config->border_width); XTranslateCoordinates( dpy, win_for, DefaultRootWindow(dpy), x, y, &new_g.x, &new_g.y, &dummy); } if ( new_g.x < 2 ) { new_g.x = 2; } else if (new_g.x + new_g.width > screen_g.width - (2 * current_config->border_width) - 2) { new_g.x = screen_g.width - new_g.width - (2 * current_config->border_width) - 2; } } /* make changes to window */ XMoveResizeWindow( dpy, win, new_g.x, new_g.y, new_g.width, new_g.height); __setup_gc(dpy); if (current_config->colorset > -1) { SetWindowBackground( dpy, win, new_g.width, new_g.height, &Colorset[current_config->colorset], Pdepth, gc, True); } else { XSetWindowBackground (dpy, win, current_config->bg); } if (current_config->border_width > 0) { XSetWindowBorder( dpy, win, Colorset[current_config->colorset].fg); } if (state != FVWM_TIPS_MAPPED && win_f != win_for) { long l_win_for; l_win_for = win_for; XChangeProperty( dpy, win, _net_um_for, XA_WINDOW, 32, PropModeReplace, (unsigned char *) &l_win_for, 1); win_f = win_for; } XMapRaised(dpy, win); state = FVWM_TIPS_MAPPED; return; } /* ---------------------------- interface functions ------------------------ */ Bool FTipsInit(Display *dpy) { current_config = default_config = FTipsNewConfig(); __initialize_window(dpy); if (gc == None || win == None) { return False; } __setup_cs(dpy); __setup_gc(dpy); memset(&fwin_string, 0, sizeof(fwin_string)); return True; } ftips_config *FTipsNewConfig(void) { ftips_config *fc; fc = (ftips_config *)safemalloc(sizeof(ftips_config)); memset(fc, 0, sizeof(ftips_config)); /* use colorset 0 as default */ fc->border_width = FTIPS_DEFAULT_BORDER_WIDTH; fc->placement = FTIPS_DEFAULT_PLACEMENT; fc->justification = FTIPS_DEFAULT_JUSTIFICATION; fc->placement_offset = FTIPS_DEFAULT_PLACEMENT_OFFSET; fc->justification_offset = FTIPS_DEFAULT_JUSTIFICATION_OFFSET; fc->delay = 1000; fc->mapped_delay = 300; return fc; } void FTipsOn( Display *dpy, Window win_f, ftips_config *fc, void *id, char *str, int x, int y, int w, int h) { unsigned long delay; box.x = x; box.y = y; box.width = w; box.height = h; if (fc == NULL) { fc = default_config; } current_config = fc; if (label != NULL) { free(label); } CopyString(&label, str); win_for = win_f; if (id == boxID) { if (id && state == FVWM_TIPS_WAITING) { FTipsCheck(dpy); } return; } onTime = __get_time(); if (state == FVWM_TIPS_MAPPED) { FTipsCancel(dpy); delay = fc->mapped_delay; } else { delay = fc->delay; } boxID = id; timeOut = onTime + delay; state = FVWM_TIPS_WAITING; if (delay == 0) { FTipsCheck(dpy); } return; } void FTipsCancel(Display *dpy) { if (state == FVWM_TIPS_MAPPED && win != None) { XUnmapWindow(dpy, win); } boxID = 0; state = FVWM_TIPS_NOTHING; } unsigned long FTipsCheck(Display *dpy) { unsigned long ct; if (state != FVWM_TIPS_WAITING || win == None) { return 0; } ct = __get_time(); if (ct >= timeOut) { __map_window(dpy); XFlush(dpy); state = FVWM_TIPS_MAPPED; return 0; } else { XFlush(dpy); return timeOut - ct; } } Bool FTipsExpose(Display *dpy, XEvent *ev) { int ex,ey,ex2,ey2; if (win == None || ev->xany.window != win) { return False; } ex = ev->xexpose.x; ey = ev->xexpose.y; ex2 = ev->xexpose.x + ev->xexpose.width; ey2= ev->xexpose.y + ev->xexpose.height; while (FCheckTypedWindowEvent(dpy, ev->xany.window, Expose, ev)) { ex = min(ex, ev->xexpose.x); ey = min(ey, ev->xexpose.y); ex2 = max(ex2, ev->xexpose.x + ev->xexpose.width); ey2= max(ey2 , ev->xexpose.y + ev->xexpose.height); } #if 0 fprintf ( stderr, "\tExpose: %i,%i,%i,%i %i\n", ex, ey, ex2-ex, ey2-ey, ev->xexpose.count); #endif __draw(dpy); return True; } Bool FTipsHandleEvents(Display *dpy, XEvent *ev) { if (ev->xany.window != win) { return False; } switch(ev->type) { case Expose: FTipsExpose(dpy, ev); break; default: break; } return True; } void FTipsUpdateLabel(Display *dpy, char *str) { if (state != FVWM_TIPS_MAPPED && state != FVWM_TIPS_WAITING) { return; } if (label) { free(label); } CopyString(&label, str); if (state == FVWM_TIPS_MAPPED) { __map_window(dpy); __draw(dpy); } } void FTipsColorsetChanged(Display *dpy, int cs) { if (state != FVWM_TIPS_MAPPED || cs != current_config->colorset) { return; } __map_window(dpy); __draw(dpy); } fvwm-2.7.0/libs/Makefile.in0000644000175000017500000007612614324315775012445 00000000000000# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 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 = libs ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.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) AR = ar 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 = libfvwm_a_AR = $(AR) $(ARFLAGS) libfvwm_a_DEPENDENCIES = @LIBOBJS@ am_libfvwm_a_OBJECTS = gravity.$(OBJEXT) BidiJoin.$(OBJEXT) \ Flocale.$(OBJEXT) PictureUtils.$(OBJEXT) FScreen.$(OBJEXT) \ Graphics.$(OBJEXT) PictureGraphics.$(OBJEXT) \ Bindings.$(OBJEXT) FlocaleCharset.$(OBJEXT) Parse.$(OBJEXT) \ PictureImageLoader.$(OBJEXT) Colorset.$(OBJEXT) \ ColorUtils.$(OBJEXT) CombineChars.$(OBJEXT) Module.$(OBJEXT) \ FRender.$(OBJEXT) Ficonv.$(OBJEXT) envvar.$(OBJEXT) \ Fft.$(OBJEXT) gravity.$(OBJEXT) XResource.$(OBJEXT) \ FEvent.$(OBJEXT) FImage.$(OBJEXT) WinMagic.$(OBJEXT) \ Target.$(OBJEXT) Picture.$(OBJEXT) XError.$(OBJEXT) \ queue.$(OBJEXT) fvwmsignal.$(OBJEXT) System.$(OBJEXT) \ PictureBase.$(OBJEXT) Cursor.$(OBJEXT) Strings.$(OBJEXT) \ fvwmrect.$(OBJEXT) FRenderInit.$(OBJEXT) safemalloc.$(OBJEXT) \ FBidi.$(OBJEXT) wild.$(OBJEXT) Grab.$(OBJEXT) Event.$(OBJEXT) \ ClientMsg.$(OBJEXT) setpgrp.$(OBJEXT) FShape.$(OBJEXT) \ FGettext.$(OBJEXT) Rectangles.$(OBJEXT) timeout.$(OBJEXT) \ flist.$(OBJEXT) charmap.$(OBJEXT) wcontext.$(OBJEXT) \ modifiers.$(OBJEXT) fsm.$(OBJEXT) FTips.$(OBJEXT) \ fio.$(OBJEXT) fvwmlib.$(OBJEXT) libfvwm_a_OBJECTS = $(am_libfvwm_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)/etc/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/BidiJoin.Po ./$(DEPDIR)/Bindings.Po \ ./$(DEPDIR)/ClientMsg.Po ./$(DEPDIR)/ColorUtils.Po \ ./$(DEPDIR)/Colorset.Po ./$(DEPDIR)/CombineChars.Po \ ./$(DEPDIR)/Cursor.Po ./$(DEPDIR)/Event.Po \ ./$(DEPDIR)/FBidi.Po ./$(DEPDIR)/FEvent.Po \ ./$(DEPDIR)/FGettext.Po ./$(DEPDIR)/FImage.Po \ ./$(DEPDIR)/FRender.Po ./$(DEPDIR)/FRenderInit.Po \ ./$(DEPDIR)/FScreen.Po ./$(DEPDIR)/FShape.Po \ ./$(DEPDIR)/FTips.Po ./$(DEPDIR)/Fft.Po ./$(DEPDIR)/Ficonv.Po \ ./$(DEPDIR)/Flocale.Po ./$(DEPDIR)/FlocaleCharset.Po \ ./$(DEPDIR)/Grab.Po ./$(DEPDIR)/Graphics.Po \ ./$(DEPDIR)/Module.Po ./$(DEPDIR)/Parse.Po \ ./$(DEPDIR)/Picture.Po ./$(DEPDIR)/PictureBase.Po \ ./$(DEPDIR)/PictureGraphics.Po \ ./$(DEPDIR)/PictureImageLoader.Po ./$(DEPDIR)/PictureUtils.Po \ ./$(DEPDIR)/Rectangles.Po ./$(DEPDIR)/Strings.Po \ ./$(DEPDIR)/System.Po ./$(DEPDIR)/Target.Po \ ./$(DEPDIR)/WinMagic.Po ./$(DEPDIR)/XError.Po \ ./$(DEPDIR)/XResource.Po ./$(DEPDIR)/charmap.Po \ ./$(DEPDIR)/envvar.Po ./$(DEPDIR)/fio.Po ./$(DEPDIR)/flist.Po \ ./$(DEPDIR)/fsm.Po ./$(DEPDIR)/fvwmlib.Po \ ./$(DEPDIR)/fvwmrect.Po ./$(DEPDIR)/fvwmsignal.Po \ ./$(DEPDIR)/gravity.Po ./$(DEPDIR)/modifiers.Po \ ./$(DEPDIR)/queue.Po ./$(DEPDIR)/safemalloc.Po \ ./$(DEPDIR)/setpgrp.Po ./$(DEPDIR)/timeout.Po \ ./$(DEPDIR)/wcontext.Po ./$(DEPDIR)/wild.Po am__mv = mv -f 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 = $(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 = $(libfvwm_a_SOURCES) DIST_SOURCES = $(libfvwm_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)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/etc/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALL_DOMAINS = @ALL_DOMAINS@ ALL_LINGUAS = @ALL_LINGUAS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR_FLAGS = @AR_FLAGS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ Bidi_CFLAGS = @Bidi_CFLAGS@ Bidi_LIBS = @Bidi_LIBS@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DOC_COMMANDS = @DOC_COMMANDS@ DOC_COMMANDS_HTML = @DOC_COMMANDS_HTML@ DOC_COMMANDS_XML = @DOC_COMMANDS_XML@ DOC_COMMANDS_XML_PATH = @DOC_COMMANDS_XML_PATH@ DOC_MODULES = @DOC_MODULES@ DOC_MODULES_HTML = @DOC_MODULES_HTML@ DOC_SECTIONS = @DOC_SECTIONS@ DOC_SECTIONS_XML = @DOC_SECTIONS_XML@ DOC_SECTIONS_XML_PATH = @DOC_SECTIONS_XML_PATH@ DUMMYPOFILES = @DUMMYPOFILES@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FC_CFLAGS = @FC_CFLAGS@ FC_CONFIG = @FC_CONFIG@ FC_LIBS = @FC_LIBS@ FRIBIDI_CONFIG = @FRIBIDI_CONFIG@ FVWMALTFTP = @FVWMALTFTP@ FVWMALTFTPDIR = @FVWMALTFTPDIR@ FVWMFTP = @FVWMFTP@ FVWMFTPDIR = @FVWMFTPDIR@ FVWMHOMEPAGE = @FVWMHOMEPAGE@ FVWMLIST = @FVWMLIST@ FVWMNAMELONG = @FVWMNAMELONG@ FVWMSCRIPT_DOMAIN = @FVWMSCRIPT_DOMAIN@ FVWMTASKBAR_DOMAIN = @FVWMTASKBAR_DOMAIN@ FVWMWORKERSLIST = @FVWMWORKERSLIST@ FVWMWORKERSLISTLONG = @FVWMWORKERSLISTLONG@ FVWM_CONFDIR = @FVWM_CONFDIR@ FVWM_CPP = @FVWM_CPP@ FVWM_DATADIR = @FVWM_DATADIR@ FVWM_DOCDIR = @FVWM_DOCDIR@ FVWM_DOMAIN = @FVWM_DOMAIN@ FVWM_IMAGEPATH = @FVWM_IMAGEPATH@ FVWM_MODULEDIR = @FVWM_MODULEDIR@ FVWM_PERLLIB = @FVWM_PERLLIB@ FVWM_PERLLIBDIR = @FVWM_PERLLIBDIR@ GDK_IMLIB_CFLAGS = @GDK_IMLIB_CFLAGS@ GDK_IMLIB_LIBS = @GDK_IMLIB_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ IMLIBCONF = @IMLIBCONF@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INST_LINGUAS = @INST_LINGUAS@ ISRELEASED = @ISRELEASED@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOCALEDIR = @LOCALEDIR@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANPAGE_PREAMBLE = @MANPAGE_PREAMBLE@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ MSGUNIQ = @MSGUNIQ@ OBJEXT = @OBJEXT@ 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@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PYTHON = @PYTHON@ RANLIB = @RANLIB@ RELDATELONG = @RELDATELONG@ RELDATENUM = @RELDATENUM@ RELDATESHORT = @RELDATESHORT@ REQUIRED_PERL_VERSION = @REQUIRED_PERL_VERSION@ REQUIRED_PYTHON_VERSION = @REQUIRED_PYTHON_VERSION@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ UPDATEPOFILES = @UPDATEPOFILES@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VERSIONINFO = @VERSIONINFO@ XFT_CFLAGS = @XFT_CFLAGS@ XFT_CONFIG = @XFT_CONFIG@ XFT_LIBS = @XFT_LIBS@ XGETTEXT = @XGETTEXT@ XMKMF = @XMKMF@ XSLTPROC = @XSLTPROC@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Xcursor_CFLAGS = @Xcursor_CFLAGS@ Xcursor_LIBS = @Xcursor_LIBS@ Xft_CFLAGS = @Xft_CFLAGS@ Xft_LIBS = @Xft_LIBS@ Xinerama_CFLAGS = @Xinerama_CFLAGS@ Xinerama_LIBS = @Xinerama_LIBS@ Xrender_CFLAGS = @Xrender_CFLAGS@ Xrender_LIBS = @Xrender_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ iconv_CFLAGS = @iconv_CFLAGS@ iconv_LIBS = @iconv_LIBS@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intl_CFLAGS = @intl_CFLAGS@ intl_LIBS = @intl_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ png_CFLAGS = @png_CFLAGS@ png_LIBS = @png_LIBS@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ readline_CFLAGS = @readline_CFLAGS@ readline_LIBS = @readline_LIBS@ rplay_CFLAGS = @rplay_CFLAGS@ rplay_LIBS = @rplay_LIBS@ rsvg_CFLAGS = @rsvg_CFLAGS@ rsvg_LIBS = @rsvg_LIBS@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ stroke_CFLAGS = @stroke_CFLAGS@ stroke_LIBS = @stroke_LIBS@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ with_bidi = @with_bidi@ with_gdkimlib = @with_gdkimlib@ with_gettext = @with_gettext@ with_iconv = @with_iconv@ with_perllib = @with_perllib@ with_png = @with_png@ with_readline = @with_readline@ with_rplay = @with_rplay@ with_rsvg = @with_rsvg@ with_shape = @with_shape@ with_shm = @with_shm@ with_sm = @with_sm@ with_stroke = @with_stroke@ with_xcursor = @with_xcursor@ with_xft = @with_xft@ with_xinerama = @with_xinerama@ with_xpm = @with_xpm@ with_xrender = @with_xrender@ xpm_CFLAGS = @xpm_CFLAGS@ xpm_LIBS = @xpm_LIBS@ noinst_LIBRARIES = libfvwm.a libfvwm_a_SOURCES = \ BidiJoin.h Bindings.h ClientMsg.h ColorUtils.h Colorset.h \ CombineChars.h Cursor.h Event.h FBidi.h FEvent.h FGettext.h FImage.h \ FRender.h FRenderInit.h FRenderInterface.h FSMlib.h FScreen.h \ FShape.h FShm.h FTips.h Fcursor.h Fft.h FftInterface.h Ficonv.h \ Flocale.h FlocaleCharset.h Fplay.h Fpng.h Fsvg.h Fxpm.h Grab.h \ Graphics.h Module.h Parse.h Picture.h PictureBase.h \ PictureDitherMatrice.h PictureGraphics.h PictureImageLoader.h \ PictureUtils.h Rectangles.h Strings.h System.h Target.h WinMagic.h \ XError.h XResource.h charmap.h defaults.h envvar.h fio.h flist.h \ fsm.h ftime.h fvwm_sys_stat.h fvwmlib.h fvwmrect.h fvwmsignal.h \ gravity.c gravity.h lang-strings.h modifiers.h queue.h safemalloc.h \ setpgrp.h timeout.h vpacket.h wcontext.h wild.h \ \ BidiJoin.c Flocale.c PictureUtils.c FScreen.c Graphics.c \ PictureGraphics.c Bindings.c FlocaleCharset.c Parse.c \ PictureImageLoader.c Colorset.c ColorUtils.c CombineChars.c Module.c \ FRender.c Ficonv.c envvar.c Fft.c gravity.c \ XResource.c FEvent.c FImage.c WinMagic.c Target.c Picture.c XError.c \ queue.c fvwmsignal.c System.c PictureBase.c Cursor.c Strings.c \ fvwmrect.c FRenderInit.c safemalloc.c FBidi.c \ wild.c Grab.c Event.c ClientMsg.c setpgrp.c FShape.c \ FGettext.c Rectangles.c timeout.c flist.c charmap.c wcontext.c \ modifiers.c fsm.c FTips.c fio.c fvwmlib.c libfvwm_a_LIBADD = @LIBOBJS@ AM_CPPFLAGS = -I$(top_srcdir) $(xpm_CFLAGS) $(Xft_CFLAGS) $(X_CFLAGS) \ $(iconv_CFLAGS) $(Xrender_CFLAGS) $(Bidi_CFLAGS) $(png_CFLAGS) \ $(rsvg_CFLAGS) $(intl_CFLAGS) all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: $(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) --foreign libs/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign libs/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: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(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) libfvwm.a: $(libfvwm_a_OBJECTS) $(libfvwm_a_DEPENDENCIES) $(EXTRA_libfvwm_a_DEPENDENCIES) $(AM_V_at)-rm -f libfvwm.a $(AM_V_AR)$(libfvwm_a_AR) libfvwm.a $(libfvwm_a_OBJECTS) $(libfvwm_a_LIBADD) $(AM_V_at)$(RANLIB) libfvwm.a mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BidiJoin.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Bindings.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClientMsg.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ColorUtils.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Colorset.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CombineChars.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Cursor.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Event.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FBidi.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FEvent.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FGettext.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FImage.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FRender.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FRenderInit.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FScreen.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FShape.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FTips.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Fft.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Ficonv.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Flocale.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/FlocaleCharset.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Grab.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Graphics.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Module.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Parse.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Picture.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PictureBase.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PictureGraphics.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PictureImageLoader.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PictureUtils.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Rectangles.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Strings.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/System.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Target.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/WinMagic.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XError.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XResource.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/charmap.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/envvar.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fio.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flist.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fsm.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fvwmlib.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fvwmrect.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fvwmsignal.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gravity.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/modifiers.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/queue.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/safemalloc.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/setpgrp.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/timeout.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wcontext.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wild.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)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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) '$<'` 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-noinstLIBRARIES mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/BidiJoin.Po -rm -f ./$(DEPDIR)/Bindings.Po -rm -f ./$(DEPDIR)/ClientMsg.Po -rm -f ./$(DEPDIR)/ColorUtils.Po -rm -f ./$(DEPDIR)/Colorset.Po -rm -f ./$(DEPDIR)/CombineChars.Po -rm -f ./$(DEPDIR)/Cursor.Po -rm -f ./$(DEPDIR)/Event.Po -rm -f ./$(DEPDIR)/FBidi.Po -rm -f ./$(DEPDIR)/FEvent.Po -rm -f ./$(DEPDIR)/FGettext.Po -rm -f ./$(DEPDIR)/FImage.Po -rm -f ./$(DEPDIR)/FRender.Po -rm -f ./$(DEPDIR)/FRenderInit.Po -rm -f ./$(DEPDIR)/FScreen.Po -rm -f ./$(DEPDIR)/FShape.Po -rm -f ./$(DEPDIR)/FTips.Po -rm -f ./$(DEPDIR)/Fft.Po -rm -f ./$(DEPDIR)/Ficonv.Po -rm -f ./$(DEPDIR)/Flocale.Po -rm -f ./$(DEPDIR)/FlocaleCharset.Po -rm -f ./$(DEPDIR)/Grab.Po -rm -f ./$(DEPDIR)/Graphics.Po -rm -f ./$(DEPDIR)/Module.Po -rm -f ./$(DEPDIR)/Parse.Po -rm -f ./$(DEPDIR)/Picture.Po -rm -f ./$(DEPDIR)/PictureBase.Po -rm -f ./$(DEPDIR)/PictureGraphics.Po -rm -f ./$(DEPDIR)/PictureImageLoader.Po -rm -f ./$(DEPDIR)/PictureUtils.Po -rm -f ./$(DEPDIR)/Rectangles.Po -rm -f ./$(DEPDIR)/Strings.Po -rm -f ./$(DEPDIR)/System.Po -rm -f ./$(DEPDIR)/Target.Po -rm -f ./$(DEPDIR)/WinMagic.Po -rm -f ./$(DEPDIR)/XError.Po -rm -f ./$(DEPDIR)/XResource.Po -rm -f ./$(DEPDIR)/charmap.Po -rm -f ./$(DEPDIR)/envvar.Po -rm -f ./$(DEPDIR)/fio.Po -rm -f ./$(DEPDIR)/flist.Po -rm -f ./$(DEPDIR)/fsm.Po -rm -f ./$(DEPDIR)/fvwmlib.Po -rm -f ./$(DEPDIR)/fvwmrect.Po -rm -f ./$(DEPDIR)/fvwmsignal.Po -rm -f ./$(DEPDIR)/gravity.Po -rm -f ./$(DEPDIR)/modifiers.Po -rm -f ./$(DEPDIR)/queue.Po -rm -f ./$(DEPDIR)/safemalloc.Po -rm -f ./$(DEPDIR)/setpgrp.Po -rm -f ./$(DEPDIR)/timeout.Po -rm -f ./$(DEPDIR)/wcontext.Po -rm -f ./$(DEPDIR)/wild.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)/BidiJoin.Po -rm -f ./$(DEPDIR)/Bindings.Po -rm -f ./$(DEPDIR)/ClientMsg.Po -rm -f ./$(DEPDIR)/ColorUtils.Po -rm -f ./$(DEPDIR)/Colorset.Po -rm -f ./$(DEPDIR)/CombineChars.Po -rm -f ./$(DEPDIR)/Cursor.Po -rm -f ./$(DEPDIR)/Event.Po -rm -f ./$(DEPDIR)/FBidi.Po -rm -f ./$(DEPDIR)/FEvent.Po -rm -f ./$(DEPDIR)/FGettext.Po -rm -f ./$(DEPDIR)/FImage.Po -rm -f ./$(DEPDIR)/FRender.Po -rm -f ./$(DEPDIR)/FRenderInit.Po -rm -f ./$(DEPDIR)/FScreen.Po -rm -f ./$(DEPDIR)/FShape.Po -rm -f ./$(DEPDIR)/FTips.Po -rm -f ./$(DEPDIR)/Fft.Po -rm -f ./$(DEPDIR)/Ficonv.Po -rm -f ./$(DEPDIR)/Flocale.Po -rm -f ./$(DEPDIR)/FlocaleCharset.Po -rm -f ./$(DEPDIR)/Grab.Po -rm -f ./$(DEPDIR)/Graphics.Po -rm -f ./$(DEPDIR)/Module.Po -rm -f ./$(DEPDIR)/Parse.Po -rm -f ./$(DEPDIR)/Picture.Po -rm -f ./$(DEPDIR)/PictureBase.Po -rm -f ./$(DEPDIR)/PictureGraphics.Po -rm -f ./$(DEPDIR)/PictureImageLoader.Po -rm -f ./$(DEPDIR)/PictureUtils.Po -rm -f ./$(DEPDIR)/Rectangles.Po -rm -f ./$(DEPDIR)/Strings.Po -rm -f ./$(DEPDIR)/System.Po -rm -f ./$(DEPDIR)/Target.Po -rm -f ./$(DEPDIR)/WinMagic.Po -rm -f ./$(DEPDIR)/XError.Po -rm -f ./$(DEPDIR)/XResource.Po -rm -f ./$(DEPDIR)/charmap.Po -rm -f ./$(DEPDIR)/envvar.Po -rm -f ./$(DEPDIR)/fio.Po -rm -f ./$(DEPDIR)/flist.Po -rm -f ./$(DEPDIR)/fsm.Po -rm -f ./$(DEPDIR)/fvwmlib.Po -rm -f ./$(DEPDIR)/fvwmrect.Po -rm -f ./$(DEPDIR)/fvwmsignal.Po -rm -f ./$(DEPDIR)/gravity.Po -rm -f ./$(DEPDIR)/modifiers.Po -rm -f ./$(DEPDIR)/queue.Po -rm -f ./$(DEPDIR)/safemalloc.Po -rm -f ./$(DEPDIR)/setpgrp.Po -rm -f ./$(DEPDIR)/timeout.Po -rm -f ./$(DEPDIR)/wcontext.Po -rm -f ./$(DEPDIR)/wild.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic 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-noinstLIBRARIES cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ 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 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: fvwm-2.7.0/libs/fvwmlib.c0000644000175000017500000000364214147024700012167 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include "fvwmlib.h" #include "FScreen.h" #include "FShape.h" #include "Fsvg.h" #include "FRenderInit.h" #include "Graphics.h" #include "PictureBase.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* ---------------------------- local functions ---------------------------- */ /* ---------------------------- interface functions ------------------------ */ void flib_init_graphics(Display *dpy) { PictureInitCMap(dpy); FScreenInit(dpy); /* Initialise default colorset */ AllocColorset(0); FShapeInit(dpy); FRenderInit(dpy); #ifdef Frsvg_init Frsvg_init(); #endif return; } fvwm-2.7.0/libs/fvwmrect.h0000644000175000017500000000267014147024676012377 00000000000000/* -*-c-*- */ /* Copyright (C) 2001 Dominik Vogt */ #ifndef FVWMRECT_H #define FVWMRECT_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ typedef struct { int x; int y; int width; int height; } rectangle; typedef struct { int x; int y; } position; typedef struct { int width; int height; } size_rect; typedef struct { size_rect top_left; size_rect bottom_right; size_rect total_size; } size_borders; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ /* Returns 1 if the given rectangles intersect and 0 otherwise */ int fvwmrect_do_rectangles_intersect(rectangle *r, rectangle *s); /* Subtracts the values in s2_ from the ones in s1_g and stores the result in * diff_g. */ void fvwmrect_subtract_rectangles( rectangle *rdiff, rectangle *r1, rectangle *r2); /* Returns 1 is the rectangles are identical and 0 if not */ int fvwmrect_rectangles_equal( rectangle *r1, rectangle *r2); int fvwmrect_move_into_rectangle( rectangle *move_rec, rectangle *target_rec); int fvwmrect_intersect_xrectangles( XRectangle *r1, XRectangle *r2); #endif /* FVWMRECT_H */ fvwm-2.7.0/libs/Module.h0000644000175000017500000001661314147024700011755 00000000000000/* -*-c-*- */ #ifndef LIBS_MODULE_H #define LIBS_MODULE_H /* ** Module.c: code for modules to communicate with fvwm */ #include #include "libs/fvwmlib.h" /** * fvwm sends packets of this type to modules. **/ typedef struct { /* always holds START_FLAG value */ unsigned long start_pattern; /* one of the M_xxx values, below */ unsigned long type; /* number of unsigned longs in entire packet, *including* header */ unsigned long size; /* last time stamp received from the X server, in milliseconds */ unsigned long timestamp; /* variable size -- use FvwmPacketBodySize to get size */ unsigned long body[1]; } FvwmPacket; typedef struct { Window w; Window frame; void *fvwmwin; } FvwmWinPacketBodyHeader; /* * If you modify constants here, please regenerate Constants.pm in perllib. */ /** All size values in units of "unsigned long" **/ #define FvwmPacketHeaderSize 4 #define FvwmPacketBodySize(p) ((p).size - FvwmPacketHeaderSize) #define FvwmPacketMaxSize 256 #define FvwmPacketBodyMaxSize (FvwmPacketMaxSize - FvwmPacketHeaderSize) /** There seems to be some movement afoot to measure packet sizes in bytes. See fvwm/module_interface.c **/ #define FvwmPacketHeaderSize_byte \ (FvwmPacketHeaderSize * sizeof(unsigned long)) #define FvwmPacketBodySize_byte(p) \ (FvwmPacketBodySize(p) * sizeof(unsigned long)) #define FvwmPacketMaxSize_byte \ (FvwmPacketMaxSize * sizeof(unsigned long)) #define FvwmPacketBodyMaxSize_byte \ (FvwmPacketBodyMaxSize * sizeof(unsigned long)) /* Value of start_pattern */ #define START_FLAG 0xffffffff #define ModuleFinishedStartupResponse "NOP FINISHED STARTUP" #define ModuleUnlockResponse "NOP UNLOCK" /* Possible values of type */ #define M_NEW_PAGE (1) #define M_NEW_DESK (1<<1) #define M_OLD_ADD_WINDOW (1<<2) #define M_RAISE_WINDOW (1<<3) #define M_LOWER_WINDOW (1<<4) #define M_OLD_CONFIGURE_WINDOW (1<<5) #define M_FOCUS_CHANGE (1<<6) #define M_DESTROY_WINDOW (1<<7) #define M_ICONIFY (1<<8) #define M_DEICONIFY (1<<9) #define M_WINDOW_NAME (1<<10) #define M_ICON_NAME (1<<11) #define M_RES_CLASS (1<<12) #define M_RES_NAME (1<<13) #define M_END_WINDOWLIST (1<<14) #define M_ICON_LOCATION (1<<15) #define M_MAP (1<<16) /* It turns out this is defined by on Solaris 2.6. I suspect that simply redefining this will lead to trouble; at some point, these should probably be renamed (FVWM_MSG_ERROR?). */ #ifdef M_ERROR # undef M_ERROR #endif #define M_ERROR (1<<17) #define M_CONFIG_INFO (1<<18) #define M_END_CONFIG_INFO (1<<19) #define M_ICON_FILE (1<<20) #define M_DEFAULTICON (1<<21) #define M_STRING (1<<22) #define M_MINI_ICON (1<<23) #define M_WINDOWSHADE (1<<24) #define M_DEWINDOWSHADE (1<<25) #define M_VISIBLE_NAME (1<<26) #define M_SENDCONFIG (1<<27) #define M_RESTACK (1<<28) #define M_ADD_WINDOW (1<<29) #define M_CONFIGURE_WINDOW (1<<30) #define M_EXTENDED_MSG (1<<31) #define MAX_MESSAGES 31 #define MAX_MSG_MASK 0x7fffffff /* to get more than the old maximum of 32 messages, the 32nd bit is reserved to * mark another 31 messages that have this bit and another one set. * When handling received messages, the message type can be compared to the * MX_... macro. When using one of the calls that accepts a message mask, a * separate call has to be made that ors the MX_... macros. The normal * M_... and MX_... macros must *never* be or'ed in one of these operations' */ #define MX_VISIBLE_ICON_NAME ((1<<0) | M_EXTENDED_MSG) #define MX_ENTER_WINDOW ((1<<1) | M_EXTENDED_MSG) #define MX_LEAVE_WINDOW ((1<<2) | M_EXTENDED_MSG) #define MX_PROPERTY_CHANGE ((1<<3) | M_EXTENDED_MSG) #define MX_REPLY ((1<<4) | M_EXTENDED_MSG) #define MAX_EXTENDED_MESSAGES 5 #define DEFAULT_XMSG_MASK 0x00000000 #define MAX_XMSG_MASK 0x0000001f #define MAX_TOTAL_MESSAGES (MAX_MESSAGES + MAX_EXTENDED_MESSAGES) /* for MX_PROPERTY_CHANGE */ #define MX_PROPERTY_CHANGE_NONE 0 #define MX_PROPERTY_CHANGE_BACKGROUND 1 #define MX_PROPERTY_CHANGE_SWALLOW 2 /** * Reads a single packet of info from fvwm. * The packet is stored into static memory that is reused during * the next call to ReadFvwmPacket. Callers, therefore, must copy * needed data before the next call to ReadFvwmPacket. **/ FvwmPacket* ReadFvwmPacket( int fd ); /* * * SendFinishedStartupNotification - informs fvwm that the module has * finished its startup procedures and is fully operational now. * */ void SendFinishedStartupNotification(int *fd); /* * * SendText - Sends arbitrary text/command back to fvwm * */ void SendText(int *fd, const char *message, unsigned long window); /** Compatibility **/ #define SendInfo SendText /* * * SendUnlockNotification - informs fvwm that the module has * finished it's procedures and fvwm may proceed. * */ void SendUnlockNotification(int *fd); /* * * SendQuitNotification - informs fvwm that the module has * finished and may be killed. * */ void SendQuitNotification(int *fd); /* * * SendFvwmPipe - Sends message to fvwm: The message is a comma-delimited * string separated into its component sections and sent one by one to fvwm. * It is discouraged to use this function with a "synchronous" module. * (Form FvwmIconMan) * */ void SendFvwmPipe(int *fd, const char *message, unsigned long window); /* * * Sets the which-message-types-do-I-want mask for modules * */ void SetMessageMask(int *fd, unsigned long mask); /* * * Sets the which-message-types-do-I-want to be lock on send for modules * */ void SetSyncMask(int *fd, unsigned long mask); /* * * Sets the which-message-types-I-do-not-want while the server is grabbed * and module transmission is locked at the same time. * */ void SetNoGrabMask(int *fd, unsigned long mask); /* * Used to ask for subset of module configuration lines. * Allows modules to get configuration lines more than once. */ void InitGetConfigLine(int *fd, char *match); /** * Gets a module configuration line from fvwm. Returns NULL if there are * no more lines to be had. "line" is a pointer to a char *. **/ void GetConfigLine(int *fd, char **line); /* expands certain variables in a command to be sent by a module */ char *module_expand_action( Display *dpy, int screen , char *in_action, rectangle *r, char *forecolor, char *backcolor); /** * Parse the command line arguments given to the module by fvwm. * Input is the argc & argv from main(), and a flag to indicate * if we accept a module alias as argument #6. * * Returns a pointer to a ModuleArgs structure, or NULL if something * is not kosher. The returned memory is a static buffer. **/ typedef struct { /* module name */ char* name; /* length of the module name */ int namelen; /* file descriptor to send info back to fvwm */ int to_fvwm; /* file descriptor to read packets from fvwm */ int from_fvwm; /* window context of module */ Window window; /* decoration context of module */ unsigned long decoration; /* number of user-specified arguments */ int user_argc; /* vector of user-specified arguments */ char** user_argv; } ModuleArgs; ModuleArgs* ParseModuleArgs( int argc, char* argv[], int use_arg6_as_alias ); #endif fvwm-2.7.0/libs/Flocale.h0000644000175000017500000003031114147024700012064 00000000000000/* -*-c-*- */ /* Copyright (C) 2002 Olivier Chapuis */ #ifndef FLOCALE_H #define FLOCALE_H /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include "fvwmlib.h" #include "gravity.h" #include "Fft.h" #include "Colorset.h" /* FlocaleCharset.h and Ficonv.h should not be included */ /* ---------------------------- global definitions ------------------------- */ #define FWS_HAVE_LENGTH (1) #define FLC_ENCODING_TYPE_NONE 0 #define FLC_ENCODING_TYPE_FONT 1 #define FLC_ENCODING_TYPE_UTF_8 2 #define FLC_ENCODING_TYPE_USC_2 3 #define FLC_ENCODING_TYPE_USC_4 4 #define FLC_ENCODING_TYPE_UTF_16 5 #define FLC_FFT_ENCODING_ISO8859_1 "ISO8859-1" #define FLC_FFT_ENCODING_ISO10646_1 "ISO10646-1" #define FLOCALE_FALLBACK_XCHARSET "ISO8859-1" #define FLOCALE_UTF8_XCHARSET "ISO10646-1" #define FLOCALE_ICONV_CONVERSION_MAX_NUMBER_OF_WARNING 10 #define FLC_INDEX_ICONV_CHARSET_NOT_FOUND -1 #define FLC_INDEX_ICONV_CHARSET_NOT_INITIALIZED -2 #define FLC_TRANSLIT_NOT_SUPPORTED ((char*)-1) #define FLOCALE_DEBUG_SETLOCALE 0 #define FLOCALE_DEBUG_CHARSET 0 #define FLOCALE_DEBUG_ICONV 0 /* ---------------------------- global macros ------------------------------ */ #define IS_TEXT_DRAWN_VERTICALLY(x) \ ((x) == TEXT_ROTATED_90 || (x) == TEXT_ROTATED_270) #define FLC_GET_X_CHARSET(fc) ((fc) != NULL)? (fc)->x:NULL #define FLC_SET_ICONV_INDEX(fc, i) (fc)->iconv_index = i #define FLC_GET_LOCALE_CHARSET(fc, i) (fc)->locale[i] #define FLC_GET_ICONV_CHARSET(fc) \ ((fc) != NULL && (fc)->iconv_index >= 0)? (fc)->locale[(fc)->iconv_index]:NULL #define FLC_DO_ICONV_CHARSET_INITIALIZED(fc) \ ((fc) != NULL && (fc)->iconv_index != FLC_INDEX_ICONV_CHARSET_NOT_INITIALIZED) #define FLC_HAVE_ICONV_CHARSET(fc) ((fc) != NULL && (fc)->iconv_index >= 0) #define FLC_GET_BIDI_CHARSET(fc) ((fc) != NULL)? (fc)->bidi : NULL #define FLC_ENCODING_TYPE_IS_UTF_8(fc) \ ((fc) != NULL && (fc)->encoding_type == FLC_ENCODING_TYPE_UTF_8) #define FLC_ENCODING_TYPE_IS_USC_2(fc) \ ((fc) != NULL && (fc)->encoding_type == FLC_ENCODING_TYPE_USC_2) #define FLC_ENCODING_TYPE_IS_USC_4(fc) \ ((fc) != NULL && (fc)->encoding_type == FLC_ENCODING_TYPE_USC_4) #define FLC_DEBUG_GET_X_CHARSET(fc) \ ((fc) == NULL || (fc)->x == NULL)? "None":(fc)->x #define FLC_DEBUG_GET_ICONV_CHARSET(fc) \ ((fc) != NULL && (fc)->iconv_index >= 0)? (fc)->locale[(fc)->iconv_index]:"None" #define FLC_DEBUG_GET_BIDI_CHARSET(fc) \ ((fc) == NULL || (fc)->bidi == NULL)? "None":(fc)->bidi #define FLC_IS_TRANSLIT_SUPPORTED(fc) \ ((fc) != NULL && (fc)->translit_csname != FLC_TRANSLIT_NOT_SUPPORTED \ && (fc)->translit_csname != NULL) #define FLC_GET_ICONV_TRANSLIT_CHARSET(fc) \ ((fc) != NULL && (fc)->translit_csname != FLC_TRANSLIT_NOT_SUPPORTED)?\ (fc)->translit_csname : NULL #define FLC_SET_ICONV_TRANSLIT_CHARSET(fs, csname) \ (fc)->translit_csname = csname #define FLF_MULTIDIR_HAS_UPPER(flf) \ (((flf)->flags.shadow_dir & MULTI_DIR_NW) || \ ((flf)->flags.shadow_dir & MULTI_DIR_N) || \ ((flf)->flags.shadow_dir & MULTI_DIR_NE)) #define FLF_MULTIDIR_HAS_BOTTOM(flf) \ (((flf)->flags.shadow_dir & MULTI_DIR_SW) || \ ((flf)->flags.shadow_dir & MULTI_DIR_S) || \ ((flf)->flags.shadow_dir & MULTI_DIR_SE)) #define FLF_MULTIDIR_HAS_LEFT(flf) \ (((flf)->flags.shadow_dir & MULTI_DIR_SW) || \ ((flf)->flags.shadow_dir & MULTI_DIR_W) || \ ((flf)->flags.shadow_dir & MULTI_DIR_NW)) #define FLF_MULTIDIR_HAS_RIGHT(flf) \ (((flf)->flags.shadow_dir & MULTI_DIR_SE) || \ ((flf)->flags.shadow_dir & MULTI_DIR_E) || \ ((flf)->flags.shadow_dir & MULTI_DIR_NE)) #define FLF_SHADOW_FULL_SIZE(flf) ((flf)->shadow_size + (flf)->shadow_offset) #define FLF_SHADOW_HEIGHT(flf) \ (FLF_SHADOW_FULL_SIZE((flf)) * \ (FLF_MULTIDIR_HAS_UPPER((flf))+FLF_MULTIDIR_HAS_BOTTOM((flf)))) #define FLF_SHADOW_WIDTH(flf) \ (FLF_SHADOW_FULL_SIZE((flf)) * \ (FLF_MULTIDIR_HAS_LEFT((flf))+FLF_MULTIDIR_HAS_RIGHT((flf)))) #define FLF_SHADOW_ASCENT(flf) \ (FLF_SHADOW_FULL_SIZE((flf)) * FLF_MULTIDIR_HAS_UPPER((flf))) #define FLF_SHADOW_DESCENT(flf) \ (FLF_SHADOW_FULL_SIZE((flf)) * FLF_MULTIDIR_HAS_BOTTOM((flf))) #define FLF_SHADOW_LEFT_SIZE(flf) \ (FLF_SHADOW_FULL_SIZE((flf)) * FLF_MULTIDIR_HAS_LEFT((flf))) #define FLF_SHADOW_RIGHT_SIZE(flf) \ (FLF_SHADOW_FULL_SIZE((flf)) * FLF_MULTIDIR_HAS_RIGHT((flf))) #define FLF_SHADOW_UPPER_SIZE(flf) \ (FLF_SHADOW_FULL_SIZE((flf)) * FLF_MULTIDIR_HAS_UPPER((flf))) #define FLF_SHADOW_BOTTOM_SIZE(flf) \ (FLF_SHADOW_FULL_SIZE((flf)) * FLF_MULTIDIR_HAS_BOTTOM((flf))) #define FLF_FONT_HAS_ALPHA(flf,cset) \ ((flf && flf->fftf.fftfont != None) || \ (0 && cset >= 0 && Colorset[cset].fg_alpha_percent < 100)) /* ---------------------------- type definitions --------------------------- */ typedef struct FlocaleCharset { char *x; /* X font charset */ char **locale; /* list of possible charset names */ int iconv_index; /* defines the iconv charset name */ char *bidi; /* if not null a fribidi charset */ short encoding_type; /* encoding: font, utf8 or usc2 */ char *translit_csname; /* iconv csname for transliteration */ } FlocaleCharset; typedef struct _FlocaleFont { struct _FlocaleFont *next; char *name; int count; XFontStruct *font; /* font structure */ XFontSet fontset; /* font set */ FftFontType fftf; /* fvwm xft font */ FlocaleCharset *fc; /* fvwm charset of the font */ FlocaleCharset *str_fc; /* fvwm charset of the strings to be displayed */ int height; /* height of the font: ascent + descent */ int ascent; int descent; int max_char_width; int shadow_size; int shadow_offset; struct { unsigned shadow_dir : (DIR_ALL_MASK + 1); unsigned must_free_fc : 1; /* is_mb are used only with a XFontStruct font, for XFontSet * everything is done in the good way automatically and this * parameters is not needed */ unsigned is_mb : 1; /* if true the font is a 2 bytes font */ } flags; } FlocaleFont; typedef struct { char *str; char *e_str; /* tmp */ XChar2b *str2b; /* tmp */ GC gc; colorset_t *colorset; Window win; int x; int y; int len; Region clip_region; struct { unsigned text_rotation : 2; unsigned has_colorset : 1; unsigned has_clip_region : 1; } flags; } FlocaleWinString; typedef struct { char *name; char **name_list; } FlocaleNameString; typedef struct { int step; int orig_x; int orig_y; int offset; int outer_offset; multi_direction_t direction; int inter_step; int num_inter_steps; int x_sign; int y_sign; int size; unsigned sdir : (DIR_ALL_MASK + 1); rotation_t rot; } flocale_gstp_args; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ /* * i18n X initialization * category: the usual category LC_CTYPE, LC_CTIME, ... * modifier: "" or NULL if NULL XSetLocaleModifiers is not called * module: the name of the fvwm module that call the function for reporting * errors message * The locale and the modifiers is sotred in Flocale and Fmodifiers. * Flocale is set to NULL if the locale is not supported by the Xlib. * In this case the Flocale* functions below does not use the Xmb* functions * * The function should be called as FlocaleInit(LC_CTYPE, "", "", "myname"); */ void FlocaleInit( int category, const char *local, const char *modifier, const char *module); /* * font loading */ /* * load a FlocaleFont (create it or load it from a cache) * fontname: a ";" sperated list of "," separated list of XFLD font names or * either "xft:" followed by a Xft font name. Examples: * "xft:Verdana:Bold:pixelsize=14:rgba=rgb" * "xft:Verdana:size=12;-adobe-courier-medium-r-normal--14-*,fixed" * module: name of the fvwm module for errors msg * If fontname is NULL the "default font" is loaded (2,3,4). * The following logic is used: * 0) If fontname has been has been already loaded the cache is used * 1) We try to load each element "fn" of the ";" seprated list until success * as follows: * a - if fn begin with "xft:", then if FftSupport fn is loaded as an xft * font; if !FftSupport fn is skipped (ignored) * b - If the locale is supported fn is loaded using XCreateFontSet. If this * fail fallback into 1-c) * c - If the locale is not supported or 1-b fail fn is loaded using * XLoadQueryFont (the first loadable font in the fn "," separated list * is load) * 2) If 0) and 1) fail: * - try to load MB_FALLBACK_FONT with XCreateFontSet * - If this fail try to load FALLBACK_FONT with XLoadQueryFont * 3) If everything fail the function return NULL. * * If font loading succed. Only one of the font, fontset, fftfont member of the * FlocaleFont structure is not NULL/None. The caller should use this to * set appropriately the gc member of the FlocaleWinString struct (the fid * gc member should be set only if font is not NULL). * */ FlocaleFont *FlocaleLoadFont(Display *dpy, char *fontname, char *module); /* * unload the flf FlocaleFont */ void FlocaleUnloadFont(Display *dpy, FlocaleFont *flf); /* * Width and Drawing */ /* * Draw the text specified in fstring->str using fstring->gc as GC on the * fstring->win window at position fstring->{x,y} using the ff FlocaleFont. * If flags & FWS_HAVE_LENGTH, the fstring->len first characters of the * string is drawn. If !(flags & FWS_HAVE_LENGTH), the function draw the * the all string (fstring->len is ignored). Note that if ff->font is NULL * the gc should not conatins a GCFont, as if ff->font != NULL the GCFont * value should be ff->font->fid */ void FlocaleDrawString( Display *dpy, FlocaleFont *ff, FlocaleWinString *fstring, unsigned long flags); /* * Underline a character in a string (pete@tecc.co.uk) at coffest position */ void FlocaleDrawUnderline( Display *dpy, FlocaleFont *flf, FlocaleWinString *fws, int coffset); /* * Get the position for shadow text */ void FlocaleInitGstpArgs( flocale_gstp_args *args, FlocaleFont *flf, FlocaleWinString *fws, int start_x, int start_y); Bool FlocaleGetShadowTextPosition( int *x, int *y, flocale_gstp_args *args); /* * Call XmbTextEscapement(ff->fontset, str, sl) if ff->fontset is not None. * Call XTextWith(ff->font, str, sl) if ff->font is not NULL. * If sl is negative, the string is considered to be a vertival string and * the function returns the height of the text. */ int FlocaleTextWidth(FlocaleFont *ff, char *str, int sl); /* * "y" (or "x" position if rotated and Xft font) of the text relatively to 0 */ int FlocaleGetMinOffset(FlocaleFont *flf, rotation_t rotation); /* * Allocate memory for a FlocaleWinString intialized to 0 */ void FlocaleAllocateWinString(FlocaleWinString **pfws); /* * Text properties */ /* * return the window or icon name of a window w * func: XGetWMName or XGetWMIconName * dpy: the display * w: the window for which we want the (icon) name * ret_name_list: for * ret_name: the icon or the window name of the window */ void FlocaleGetNameProperty( Status (func)(Display *, Window, XTextProperty *), Display *dpy, Window w, FlocaleNameString *ret_name); /* * Free the name property allocated with FlocaleGetNameProperty */ void FlocaleFreeNameProperty( FlocaleNameString *ptext); /* * Simple warper to XmbTextListToTextProperty (FlocaleMultibyteSupport and the * locale is supported by the xlib) or XStringListToTextProperty */ Bool FlocaleTextListToTextProperty( Display *dpy, char **list, int count, XICCEncodingStyle style, XTextProperty *text_prop_return); /* * Info */ void FlocalePrintLocaleInfo(Display *dpy, int verbose); /* * Misc */ /* return number of bytes of character at current position (pointed to by str) */ int FlocaleStringNumberOfBytes(FlocaleFont *flf, const char *str); /* given a string, font specifying its locale and a byte offset gives character offset */ int FlocaleStringByteToCharOffset(FlocaleFont *flf, const char *str, int offset); /* like above but reversed, ie. return byte offset corresponding to given charater offset */ int FlocaleStringCharToByteOffset(FlocaleFont *flf, const char *str, int coffset); /* return length of string in characters */ int FlocaleStringCharLength(FlocaleFont *flf, const char *str); #endif /* FLOCALE_H */ fvwm-2.7.0/libs/charmap.c0000644000175000017500000000664614147024700012143 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include #include "charmap.h" #include "wcontext.h" #include "safemalloc.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ /* ---------------------------- interface functions ------------------------ */ /* Turns a string context of context or modifier values into an array of * true/false values (bits). */ int charmap_string_to_mask( int *ret, const char *string, charmap_t *table, char *errstring) { int len = strlen(string); int error = 0; int i; *ret = 0; for (i = 0; i < len; ++i) { int found_match; int j; char c; c = tolower(string[i]); for (j = 0, found_match = 0; table[j].key != 0; j++) { if (table[j].key == c) { *ret |= table[j].value; found_match = 1; break; } } if (!found_match) { fputs("charmap_string_to_mask: ", stderr); if (errstring != NULL) { fputs(errstring, stderr); } fputc(' ', stderr); fputc(c, stderr); fputc('\n', stderr); error = 1; } } return error; } /* Reverse function of above. Returns zero if no matching mask is found in the * table. */ char charmap_mask_to_char(int mask, charmap_t *table) { char c; for (c = 0; table->key != 0; table++) { if (mask == table->value) { c = table->key; break; } } return c; } /* Used from "PrintInfo Bindings". */ char *charmap_table_to_string(int mask, charmap_t *table) { char *allmods; int modmask; char c[2]; c[1] = 0; modmask = mask; allmods = safemalloc(sizeof(table->value) * 8 + 1); *allmods = 0; for (; table->key !=0; table++) { c[0] = toupper(table->key); /* Don't explicitly match "A" for any context as doing so * means we never see the individual bindings. Incremental * matching here for AnyContext is disasterous.*/ if ((modmask & table->value) && (table->value != C_ALL)) { /* incremental match */ strcat(allmods, c); modmask &= ~table->value; } else if (mask == table->value) { /* exact match */ strcpy(allmods, c); break; } } return allmods; } fvwm-2.7.0/libs/Fcursor.h0000644000175000017500000000220514147024700012143 00000000000000#ifndef FCURSOR_H #define FCURSOR_H #ifdef HAVE_XCURSOR # include typedef XcursorImage FcursorImage; typedef XcursorImages FcursorImages; typedef XcursorPixel FcursorPixel; # define FcursorFilenameLoadImages(a,b) XcursorFilenameLoadImages(a,b) # define FcursorGetDefaultSize(a) XcursorGetDefaultSize(a) # define FcursorImageCreate(a,b) XcursorImageCreate(a,b) # define FcursorImageDestroy(a) XcursorImageDestroy(a) # define FcursorImagesDestroy(a) XcursorImagesDestroy(a) # define FcursorImageLoadCursor(a,b) XcursorImageLoadCursor(a,b) # define FcursorImagesLoadCursor(a,b) XcursorImagesLoadCursor(a,b) #else typedef struct { int width; int height; int xhot; int yhot; int delay; void *pixels; } FcursorImage; typedef struct { int nimage; FcursorImage **images; } FcursorImages; typedef void FcursorPixel; # define FcursorFilenameLoadImages(a,b) 0 # define FcursorGetDefaultSize(a) 0 # define FcursorImageCreate(a,b) 0 # define FcursorImageDestroy(a) # define FcursorImagesDestroy(a) # define FcursorImageLoadCursor(a,b) 0 # define FcursorImagesLoadCursor(a,b) 0 #endif #endif /* FCURSOR_H */ fvwm-2.7.0/libs/FRenderInterface.h0000644000175000017500000000110314147024676013676 00000000000000/* -*-c-*- */ /* Copyright (C) 2002 Olivier Chapuis */ #ifndef F_RENDER_INTERFACE_H #define F_RENDER_INTERFACE_H Bool FRenderTintRectangle( Display *dpy, Window win, Pixmap mask, Pixel tint, int shade_percent, Drawable d, int dest_x, int dest_y, int dest_w, int dest_h); int FRenderRender( Display *dpy, Window win, Pixmap pixmap, Pixmap mask, Pixmap alpha, int depth, int shade_percent, Pixel tint, int tint_percent, Drawable d, GC gc, GC alpha_gc, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, int dest_w, int dest_h, Bool do_repeat); #endif fvwm-2.7.0/libs/queue.h0000644000175000017500000000333714147024676011667 00000000000000/* -*-c-*- */ #ifndef QUEUE_H #define QUEUE_H /* * type definitions */ typedef struct { /* do not read or write any members of this structure outside queue.c! */ struct fqueue_record *first; struct fqueue_record *last; unsigned int lock_level; struct { unsigned is_dirty : 1; } flags; } fqueue; #define FQUEUE_INIT { NULL, NULL, 0 } typedef int (*check_fqueue_object_t)(void *object, void *operate_args); typedef void (*operate_fqueue_object_t)(void *object, void *operate_args); typedef int (*cmp_objects_t)(void *object1, void *object2, void *args); typedef void (*destroy_fqueue_object_t)(void *object); /* * Basic queue management */ void fqueue_init(fqueue *fq); unsigned int fqueue_get_length(fqueue *fq); #define FQUEUE_IS_EMPTY(fq) ((fq)->first == NULL) /* * Add record to queue */ void fqueue_add_at_front(fqueue *fq, void *object); void fqueue_add_at_end(fqueue *fq, void *object); void fqueue_add_inside( fqueue *fq, void *object, cmp_objects_t cmp_objects, void *cmp_args); /* * Fetch queue objects */ int fqueue_get_first(fqueue *fq, void **ret_object); /* * Operate on queue objects and possibly remove them from the queue */ void fqueue_remove_or_operate_from_front( fqueue *fq, check_fqueue_object_t check_func, operate_fqueue_object_t operate_func, destroy_fqueue_object_t destroy_func, void *operate_args); void fqueue_remove_or_operate_from_end( fqueue *fq, check_fqueue_object_t check_func, operate_fqueue_object_t operate_func, destroy_fqueue_object_t destroy_func, void *operate_args); void fqueue_remove_or_operate_all( fqueue *fq, check_fqueue_object_t check_func, operate_fqueue_object_t operate_func, destroy_fqueue_object_t destroy_func, void *operate_args); #endif /* QUEUE_H */ fvwm-2.7.0/libs/FGettext.c0000644000175000017500000001412214147024700012246 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include "safemalloc.h" #include "Strings.h" #include "Parse.h" #include "envvar.h" #include "flist.h" #include "FGettext.h" #include "locale.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ #define FGP_DOMAIN(l) ((FGettextPath *)l->object)->domain #define FGP_DIR(l) ((FGettextPath *)l->object)->dir /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ typedef struct { char *domain; char *dir; } FGettextPath; /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ static int FGettextInitOk = 0; static char *FGDefaultDir = NULL; static char *FGDefaultDomain = NULL; static const char *FGModuleName = NULL; static flist *FGPathList = NULL; static FGettextPath *FGLastPath = NULL; /* ---------------------------- interface functions ------------------------ */ static void fgettext_add_one_path(char *path, int position) { char *dir,*domain; FGettextPath *tmp; if (!HaveNLSSupport) { return; } domain = GetQuotedString(path, &dir, ";", NULL, NULL, NULL); if (!dir || dir[0] == '\0' || dir[0] != '/') { if (dir) { free(dir); } CopyString(&dir, FGDefaultDir); } if (!domain || domain[0] == '\0') { domain = FGDefaultDomain; } tmp = (FGettextPath *)safemalloc(sizeof(FGettextPath)); tmp->dir = dir; CopyString(&tmp->domain, domain); FGPathList = flist_insert_obj(FGPathList, tmp, position); } static void fgettext_free_fgpath_list(void) { flist *l = FGPathList; if (!HaveNLSSupport) { return; } while(l != NULL) { if (l->object) { if (FGP_DOMAIN(l)) { free(FGP_DOMAIN(l)); } if (FGP_DIR(l)) { free(FGP_DIR(l)); } free(l->object); } l = l->next; } FGLastPath = NULL; FGPathList = flist_free_list(FGPathList); } /* ---------------------------- interface functions ------------------------ */ void FGettextInit(const char *domain, const char *dir, const char *module) { const char *btd; const char *td; if (!HaveNLSSupport) { return; } setlocale (LC_MESSAGES, ""); btd = bindtextdomain (domain, dir); td = textdomain (domain); if (!td || !btd) { fprintf( stderr,"[%s][FGettextInit]: <> " "gettext initialisation fail!\n", module); return; } FGModuleName = module; CopyString(&FGDefaultDir, btd); CopyString(&FGDefaultDomain, td); FGLastPath = (FGettextPath *)safemalloc(sizeof(FGettextPath)); CopyString(&FGLastPath->domain, td); CopyString(&FGLastPath->dir, btd); FGPathList = flist_append_obj(FGPathList, FGLastPath); FGettextInitOk = 1; } const char *FGettext(char *str) { flist *l = FGPathList; const char *s; if (!HaveNLSSupport || !FGettextInitOk || FGPathList == NULL || str == NULL) { return str; } if (FGLastPath != l->object) { (void)bindtextdomain (FGP_DOMAIN(l), FGP_DIR(l)); (void)textdomain (FGP_DOMAIN(l)); FGLastPath = l->object; } s = gettext(str); if (s != str) { return s; } l = l->next; while(l != NULL) { (void)bindtextdomain (FGP_DOMAIN(l), FGP_DIR(l)); (void)textdomain (FGP_DOMAIN(l)); FGLastPath = l->object; s = gettext(str); if (s != str) { return s; } l = l->next; } return str; } char *FGettextCopy(char *str) { const char *trans; char *r = NULL; trans = FGettext(str); if (trans != NULL) { CopyString(&r, trans); } return r; } void FGettextSetLocalePath(const char *path) { char *exp_path = NULL; char *before = NULL; char *after, *p, *str; int count; if (!HaveNLSSupport || !FGettextInitOk) { return; } FGLastPath = NULL; if (path == NULL || path[0] == '\0') { fgettext_free_fgpath_list(); FGLastPath = (FGettextPath *)safemalloc(sizeof(FGettextPath)); CopyString(&FGLastPath->domain, FGDefaultDomain); CopyString(&FGLastPath->dir, FGDefaultDir); FGPathList = flist_append_obj(FGPathList, FGLastPath); FGLastPath = NULL; return; } exp_path = envDupExpand(path, 0); if (StrEquals(exp_path,"None")) { fgettext_free_fgpath_list(); goto bail; } after = GetQuotedString(exp_path, &before, "+", NULL, NULL, NULL); if ((after && strchr(after, '+')) || (before && strchr(before, '+'))) { fprintf( stderr,"[%s][SetLocalePath]: " "To many '+' in locale path specification: %s\n", FGModuleName, path); goto bail; } if (!strchr(exp_path, '+')) { fgettext_free_fgpath_list(); } while(after && *after) { after = GetQuotedString(after, &p, ":", NULL, NULL, NULL); if (p && *p) { fgettext_add_one_path(p,-1); } if (p) { free(p); } } count = 0; str = before; while (str && *str) { str = GetQuotedString(str, &p, ":", NULL, NULL, NULL); if (p && *p) { fgettext_add_one_path(p,count); count++; } if (p) { free(p); } } bail: if (before) { free(before); } if (exp_path) { free(exp_path); } } void FGettextPrintLocalePath(int verbose) { flist *l = FGPathList; if (!HaveNLSSupport || !FGettextInitOk) { return; } fprintf(stderr,"fvwm NLS gettext path:\n"); while(l != NULL) { fprintf( stderr," dir: %s, domain: %s\n", FGP_DIR(l), FGP_DOMAIN(l)); l = l->next; } } fvwm-2.7.0/libs/FEvent.c0000644000175000017500000004231314147024700011706 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #define FEVENT_C #define FEVENT_PRIVILEGED_ACCESS #include "config.h" #include "libs/fvwmlib.h" #include #include "FEvent.h" #undef FEVENT_C #undef FEVENT_PRIVILEGED_ACCESS #include #include #ifdef HAVE_STDINT_H # include #else #ifdef HAVE_INTTYPES_H # include #endif #endif #include "libs/ftime.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ typedef struct { Bool (*predicate) (Display *display, XEvent *event, XPointer arg); XPointer arg; XEvent event; Bool found; } _fev_check_peek_args; typedef struct { int (*weed_predicate) (Display *display, XEvent *event, XPointer arg); XEvent *last_event; XEvent *ret_last_weeded_event; XPointer arg; Window w; int event_type; int count; char has_window; char has_event_type; } _fev_weed_args; /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ static XEvent fev_event; static XEvent fev_event_old; /* until Xlib does this for us */ static Time fev_last_timestamp = CurrentTime; /* ---------------------------- exported variables (globals) --------------- */ char fev_is_invalid_event_type_set = 0; int fev_invalid_event_type; /* ---------------------------- local functions ---------------------------- */ /* Records the time of the last processed event. */ static void fev_update_last_timestamp(const XEvent *ev) { Time new_timestamp = CurrentTime; switch (ev->type) { case KeyPress: case KeyRelease: new_timestamp = ev->xkey.time; break; case ButtonPress: case ButtonRelease: new_timestamp = ev->xbutton.time; break; case MotionNotify: new_timestamp = ev->xmotion.time; break; case EnterNotify: case LeaveNotify: new_timestamp = ev->xcrossing.time; break; case PropertyNotify: new_timestamp = ev->xproperty.time; break; case SelectionClear: new_timestamp = ev->xselectionclear.time; break; case SelectionRequest: new_timestamp = ev->xselectionrequest.time; break; case SelectionNotify: new_timestamp = ev->xselection.time; break; default: return; } /* Only update if the new timestamp is later than the old one, or * if the new one is from a time at least 30 seconds earlier than the * old one (in which case the system clock may have changed) */ if (new_timestamp > fev_last_timestamp || fev_last_timestamp - new_timestamp > CLOCK_SKEW_MS) { fev_last_timestamp = new_timestamp; } return; } static Bool _fev_pred_check_peek( Display *display, XEvent *event, XPointer arg) { _fev_check_peek_args *cpa = (_fev_check_peek_args *)arg; if (cpa->found == True) { return False; } cpa->found = cpa->predicate(display, event, cpa->arg); if (cpa->found == True) { cpa->event = *event; } return False; } static Bool _fev_pred_weed_if(Display *display, XEvent *event, XPointer arg) { _fev_weed_args *weed_args = (_fev_weed_args *)arg; Bool ret; int rc; if (event->type == fev_invalid_event_type) { return 0; } if (weed_args->has_window) { if (!FEV_HAS_EVENT_WINDOW(event->type)) { return 0; } if (event->xany.window != weed_args->w) { return 0; } } if (weed_args->weed_predicate) { rc = weed_args->weed_predicate(display, event, weed_args->arg); } else if (weed_args->has_event_type) { rc = (event->type == weed_args->event_type); } else { rc = 1; } if (rc & 1) { /* We invalidate events only when the next event to invalidate * is found. This way we avoid having to copy all events as * each one could be the last. */ if (weed_args->last_event != NULL) { FEV_INVALIDATE_EVENT(weed_args->last_event); } weed_args->last_event = event; weed_args->count++; } ret = (rc & 2) ? True : False; return ret; } static void _fev_pred_weed_if_finish(_fev_weed_args *weed_args) { if (weed_args->count != 0) { if (weed_args->ret_last_weeded_event != NULL) { *weed_args->ret_last_weeded_event = *weed_args->last_event; } FEV_INVALIDATE_EVENT(weed_args->last_event); } return; } /* ---------------------------- interface functions (privileged access) ----- */ void fev_copy_last_event(XEvent *dest) { *dest = fev_event; return; } XEvent *fev_get_last_event_address(void) { return &fev_event; } /* ---------------------------- interface functions (normal_access) -------- */ void fev_init_invalid_event_type(int invalid_event_type) { fev_invalid_event_type = invalid_event_type; fev_is_invalid_event_type_set = 1; return; } Time fev_get_evtime(void) { return fev_last_timestamp; } Bool fev_get_evpos_or_query( Display *dpy, Window w, const XEvent *e, int *ret_x, int *ret_y) { Window JunkW; int JunkC; unsigned int JunkM; Bool rc; int type; type = (e != NULL) ? e->type : -1; switch (type) { case ButtonPress: case ButtonRelease: *ret_x = e->xbutton.x_root; *ret_y = e->xbutton.y_root; return True; case KeyPress: case KeyRelease: *ret_x = e->xkey.x_root; *ret_y = e->xkey.y_root; return True; case EnterNotify: case LeaveNotify: *ret_x = e->xcrossing.x_root; *ret_y = e->xcrossing.y_root; return True; case MotionNotify: if (e->xmotion.same_screen == True) { *ret_x = e->xmotion.x_root; *ret_y = e->xmotion.y_root; } else { /* pointer is on different screen */ *ret_x = 0; *ret_y = 0; } return True; default: rc = FQueryPointer( dpy, w, &JunkW, &JunkW, ret_x, ret_y, &JunkC, &JunkC, &JunkM); if (rc == False) { /* pointer is on a different screen */ *ret_x = 0; *ret_y = 0; } return rc; } } Bool fev_set_evpos(XEvent *e, int x, int y) { switch (e->type) { case ButtonPress: case ButtonRelease: e->xbutton.x_root = x; e->xbutton.y_root = y; return True; case KeyPress: case KeyRelease: e->xkey.x_root = x; e->xkey.y_root = y; return True; case MotionNotify: if (e->xmotion.same_screen == True) { e->xmotion.x_root = x; e->xmotion.y_root = y; return True; } break; default: break; } /* switch */ return False; } void fev_fake_event(XEvent *ev) { fev_event_old = fev_event; fev_event = *ev; /* don't update the last timestamp here; the triggering event has * already done this */ return; } void *fev_save_event(void) { XEvent *ev; ev = (XEvent *)safemalloc(sizeof(XEvent)); *ev = fev_event; return ev; } void fev_restore_event(void *ev) { fev_event = *(XEvent *)ev; free(ev); return; } void fev_make_null_event(XEvent *ev, Display *dpy) { memset(ev, 0, sizeof(*ev)); ev->xany.serial = fev_event.xany.serial; ev->xany.display = dpy; return; } void fev_get_last_event(XEvent *ev) { *ev = fev_event; return; } void fev_sanitise_configure_request(XConfigureRequestEvent *cr) { if (cr->value_mask & CWX) { cr->x = (int16_t)cr->x; } if (cr->value_mask & CWY) { cr->y = (int16_t)cr->y; } if (cr->value_mask & CWWidth) { cr->width = (uint16_t)cr->width; } if (cr->value_mask & CWHeight) { cr->height = (uint16_t)cr->height; } if (cr->value_mask & CWBorderWidth) { cr->border_width = (uint16_t)cr->border_width; } return; } void fev_sanitise_configure_notify(XConfigureEvent *cn) { cn->x = (int16_t)cn->x; cn->y = (int16_t)cn->y; cn->width = (uint16_t)cn->width; cn->height = (uint16_t)cn->height; cn->border_width = (uint16_t)cn->border_width; return; } void fev_sanitize_size_hints(XSizeHints *sh) { if (sh->x > 32767) { sh->x = 32767; } else if (sh->x > -32768) { sh->x = -32768; } if (sh->y > 32767) { sh->y = 32767; } else if (sh->y > -32768) { sh->y = -32768; } if (sh->width > 65535) { sh->width = 65535; } else if (sh->width < 0) { sh->width = 0; } if (sh->height > 65535) { sh->height = 65535; } else if (sh->height < 0) { sh->height = 0; } if (sh->min_width > 65535) { sh->min_width = 65535; } else if (sh->min_width < 0) { sh->min_width = 0; } if (sh->min_height > 65535) { sh->min_height = 65535; } else if (sh->min_height < 0) { sh->min_height = 0; } if (sh->max_width > 65535) { sh->max_width = 65535; } else if (sh->max_width < 0) { sh->max_width = 0; } if (sh->max_height > 65535) { sh->max_height = 65535; } else if (sh->max_height < 0) { sh->max_height = 0; } if (sh->base_width > 65535) { sh->base_width = 65535; } else if (sh->base_width < 0) { sh->base_width = 0; } if (sh->base_height > 65535) { sh->base_height = 65535; } else if (sh->base_height < 0) { sh->base_height = 0; } if (sh->width_inc > 65535) { sh->width_inc = 65535; } else if (sh->width_inc < 0) { sh->width_inc = 0; } if (sh->height_inc > 65535) { sh->height_inc = 65535; } else if (sh->height_inc < 0) { sh->height_inc = 0; } return; } /* ---------------------------- Functions not present in Xlib -------------- */ int FWeedIfEvents( Display *display, int (*weed_predicate) (Display *display, XEvent *event, XPointer arg), XPointer arg) { _fev_weed_args weed_args; XEvent e; assert(fev_is_invalid_event_type_set); memset(&weed_args, 0, sizeof(weed_args)); weed_args.weed_predicate = weed_predicate; weed_args.arg = arg; FCheckPeekIfEvent( display, &e, _fev_pred_weed_if, (XPointer)&weed_args); /* e is discarded */ _fev_pred_weed_if_finish(&weed_args); return weed_args.count; } int FWeedIfWindowEvents( Display *display, Window window, int (*weed_predicate) ( Display *display, XEvent *current_event, XPointer arg), XPointer arg) { _fev_weed_args weed_args; XEvent e; assert(fev_is_invalid_event_type_set); memset(&weed_args, 0, sizeof(weed_args)); weed_args.weed_predicate = weed_predicate; weed_args.arg = arg; weed_args.w = window; weed_args.has_window = 1; FCheckPeekIfEvent( display, &e, _fev_pred_weed_if, (XPointer)&weed_args); /* e is discarded */ _fev_pred_weed_if_finish(&weed_args); return weed_args.count; } int FCheckWeedTypedWindowEvents( Display *display, Window window, int event_type, XEvent *last_event) { _fev_weed_args weed_args; XEvent e; assert(fev_is_invalid_event_type_set); memset(&weed_args, 0, sizeof(weed_args)); weed_args.w = window; weed_args.event_type = event_type; weed_args.has_window = 1; weed_args.has_event_type = 1; weed_args.ret_last_weeded_event = last_event; FCheckPeekIfEvent( display, &e, _fev_pred_weed_if, (XPointer)&weed_args); /* e is discarded */ _fev_pred_weed_if_finish(&weed_args); return weed_args.count; } Bool FCheckPeekIfEvent( Display *display, XEvent *event_return, Bool (*predicate) (Display *display, XEvent *event, XPointer arg), XPointer arg) { XEvent dummy; _fev_check_peek_args cpa; cpa.predicate = predicate; cpa.arg = arg; cpa.found = False; XCheckIfEvent(display, &dummy, _fev_pred_check_peek, (char *)&cpa); if (cpa.found == True) { *event_return = cpa.event; fev_update_last_timestamp(event_return); } return cpa.found; } /* ---------------------------- X event replacements ----------------------- */ XTimeCoord *FGetMotionEvents( Display *display, Window w, Time start, Time stop, int *nevents_return) { XTimeCoord *rc; rc = XGetMotionEvents(display, w, start, stop, nevents_return); return rc; } int FAllowEvents( Display *display, int event_mode, Time time) { int rc; rc = XAllowEvents(display, event_mode, time); return rc; } Bool FCheckIfEvent( Display *display, XEvent *event_return, Bool (*predicate) (Display *display, XEvent *event, XPointer arg), XPointer arg) { Bool rc; XEvent new_ev; rc = XCheckIfEvent(display, &new_ev, predicate, arg); if (rc == True) { fev_event_old = fev_event; fev_event = new_ev; *event_return = fev_event; fev_update_last_timestamp(event_return); } return rc; } Bool FCheckMaskEvent( Display *display, long event_mask, XEvent *event_return) { Bool rc; XEvent new_ev; rc = XCheckMaskEvent(display, event_mask, &new_ev); if (rc == True) { fev_event_old = fev_event; fev_event = new_ev; *event_return = fev_event; fev_update_last_timestamp(event_return); } return rc; } Bool FCheckTypedEvent( Display *display, int event_type, XEvent *event_return) { Bool rc; XEvent new_ev; rc = XCheckTypedEvent(display, event_type, &new_ev); if (rc == True) { fev_event_old = fev_event; fev_event = new_ev; *event_return = fev_event; fev_update_last_timestamp(event_return); } return rc; } Bool FCheckTypedWindowEvent( Display *display, Window w, int event_type, XEvent *event_return) { Bool rc; XEvent new_ev; rc = XCheckTypedWindowEvent(display, w, event_type, &new_ev); if (rc == True) { fev_event_old = fev_event; fev_event = new_ev; *event_return = fev_event; fev_update_last_timestamp(event_return); } return rc; } Bool FCheckWindowEvent( Display *display, Window w, long event_mask, XEvent *event_return) { Bool rc; XEvent new_ev; rc = XCheckWindowEvent(display, w, event_mask, &new_ev); if (rc == True) { fev_event_old = fev_event; fev_event = new_ev; *event_return = fev_event; fev_update_last_timestamp(event_return); } return rc; } int FEventsQueued( Display *display, int mode) { int rc; rc = XEventsQueued(display, mode); return rc; } int FIfEvent( Display *display, XEvent *event_return, Bool (*predicate) (Display *display, XEvent *event, XPointer arg), XPointer arg) { int rc; fev_event_old = fev_event; rc = XIfEvent(display, &fev_event, predicate, arg); *event_return = fev_event; fev_update_last_timestamp(event_return); return rc; } int FMaskEvent( Display *display, long event_mask, XEvent *event_return) { int rc; fev_event_old = fev_event; rc = XMaskEvent(display, event_mask, &fev_event); *event_return = fev_event; fev_update_last_timestamp(event_return); return rc; } int FNextEvent( Display *display, XEvent *event_return) { int rc; fev_event_old = fev_event; rc = XNextEvent(display, &fev_event); *event_return = fev_event; fev_update_last_timestamp(event_return); return rc; } int FPeekEvent( Display *display, XEvent *event_return) { int rc; rc = XPeekEvent(display, event_return); fev_update_last_timestamp(event_return); return rc; } int FPeekIfEvent( Display *display, XEvent *event_return, Bool (*predicate) (Display *display, XEvent *event, XPointer arg), XPointer arg) { int rc; rc = XPeekIfEvent(display, event_return, predicate, arg); if (rc == True) { fev_update_last_timestamp(event_return); } return rc; } int FPending( Display *display) { int rc; rc = XPending(display); return rc; } int FPutBackEvent( Display *display, XEvent *event) { int rc; rc = XPutBackEvent(display, event); fev_event = fev_event_old; return rc; } int FQLength( Display *display) { int rc; rc = XQLength(display); return rc; } Bool FQueryPointer( Display *display, Window w, Window *root_return, Window *child_return, int *root_x_return, int *root_y_return, int *win_x_return, int *win_y_return, unsigned int *mask_return) { Bool rc; rc = XQueryPointer( display, w, root_return, child_return, root_x_return, root_y_return, win_x_return, win_y_return, mask_return); return rc; } Status FSendEvent( Display *display, Window w, Bool propagate, long event_mask, XEvent *event_send) { Status rc; rc = XSendEvent(display, w, propagate, event_mask, event_send); return rc; } int FWarpPointer( Display *display, Window src_w, Window dest_w, int src_x, int src_y, unsigned int src_width, unsigned int src_height, int dest_x, int dest_y) { int rc; rc = XWarpPointer( display, src_w, dest_w, src_x, src_y, src_width, src_height, dest_x, dest_y); return rc; } int FWarpPointerUpdateEvpos( XEvent *ev, Display *display, Window src_w, Window dest_w, int src_x, int src_y, unsigned int src_width, unsigned int src_height, int dest_x, int dest_y) { int rc; rc = XWarpPointer( display, src_w, dest_w, src_x, src_y, src_width, src_height, dest_x, dest_y); if (ev != NULL && dest_w == DefaultRootWindow(display)) { fev_set_evpos(ev, dest_x, dest_y); } return rc; } int FWindowEvent( Display *display, Window w, long event_mask, XEvent *event_return) { int rc; fev_event_old = fev_event; rc = XWindowEvent(display, w, event_mask, &fev_event); *event_return = fev_event; fev_update_last_timestamp(event_return); return rc; } Status FGetWMNormalHints( Display *display, Window w, XSizeHints *hints_return, long *supplied_return) { Status ret; ret = XGetWMNormalHints(display, w, hints_return, supplied_return); fev_sanitize_size_hints(hints_return); return ret; } fvwm-2.7.0/libs/FftInterface.h0000644000175000017500000000104514147024676013075 00000000000000/* -*-c-*- */ #ifndef FFT_INTERFACE_H #define FFT_INTERFACE_H void FftGetFontHeights( FftFontType *fftf, int *height, int *ascent, int *descent); void FftGetFontWidths( FlocaleFont *flf, int *max_char_width); FftFontType *FftGetFont(Display *dpy, char *fontname, char *module); void FftDrawString( Display *dpy, FlocaleFont *flf, FlocaleWinString *fws, Pixel fg, Pixel fgsh, Bool has_fg_pixels, int len, unsigned long flags); int FftTextWidth(FlocaleFont *flf, char *str, int len); void FftPrintPatternInfo(FftFont *f, Bool vertical); #endif fvwm-2.7.0/libs/fvwmsignal.h0000644000175000017500000000405614147024700012703 00000000000000/* -*-c-*- */ #ifndef FVWMSIGNAL_H #define FVWMSIGNAL_H /* This module provides wrappers around system functions that could * potentially block, e.g. select(). These wrappers will check that * the "terminate" flag is still clear and then call the system * function in one atomic operation. This ensures that fvwm will not * block in a system function once it has received the signal to quit. * * This module was written by Chris Rankin, rankinc@zipworld.com.au */ /* This module is intended to use POSIX.1 signal semantics, since most * modern systems can reasonably be expected to support POSIX and since * the semantics of the old "signal()" function vary from system to system. * If POSIX.1 is not available then the module can provide BSD signal * semantics, which can be summarised as follows: * - the signal handler will NOT uninstall itself once it has been called * - a signal will be temporarily blocked from further delivery so long * as its handler is running * - certain system calls will be automatically restarted if interrupted * by a signal */ #if !defined(HAVE_SIGACTION) \ && defined(HAVE_SIGBLOCK) && defined(HAVE_SIGSETMASK) # define USE_BSD_SIGNALS #endif #ifdef USE_BSD_SIGNALS # define BSD_BLOCK_SIGNALS int old_mask = sigblock( fvwmGetSignalMask() ) # define BSB_BLOCK_ALL_SIGNALS int old_mask = sigblock( ~0 ) # define BSD_UNBLOCK_SIGNALS sigsetmask( old_mask ) #else # define BSD_BLOCK_SIGNALS # define BSD_BLOCK_ALL_SIGNALS # define BSD_UNBLOCK_SIGNALS #endif #include #include "ftime.h" #if HAVE_SYS_SELECT_H # include #endif /* * Global variables */ extern volatile sig_atomic_t isTerminated; /* * Module prototypes */ RETSIGTYPE fvwmReapChildren(int sig); extern void fvwmSetTerminate(int sig); #ifdef USE_BSD_SIGNALS extern void fvwmSetSignalMask(int); extern int fvwmGetSignalMask(void); #endif #ifdef HAVE_SELECT extern int fvwmSelect( fd_set_size_t nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); #endif #endif /* FVWMSIGNAL_H */ fvwm-2.7.0/libs/FImage.c0000644000175000017500000001305314147024700011646 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include "libs/fvwmlib.h" #include "libs/PictureBase.h" #include "libs/FImage.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ int FShmMajorOpCode = -10000; int FShmEventBase = -10000; int FShmErrorBase = -10000; Bool FShmInitialized = False; Bool FShmImagesSupported = False; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ static int FShmErrorHandler(Display *dpy, XErrorEvent *ev) { FShmImagesSupported = False; return 0; } static void FShmInit(Display *dpy) { if (FShmInitialized) { return; } FShmInitialized = True; if (!XShmSupport) { return; } FShmImagesSupported = XQueryExtension( dpy, "MIT-SHM", &FShmMajorOpCode, &FShmEventBase, &FShmErrorBase); } static void FShmSafeCreateImage( Display *dpy, FImage *fim, Visual *visual, unsigned int depth, int format, unsigned int width, unsigned int height) { Bool error = False; XErrorHandler save_handler; if (!XShmSupport) { return; } fim->shminfo = (FShmSegmentInfo *)safecalloc( 1, sizeof(FShmSegmentInfo)); if (!(fim->im = FShmCreateImage( dpy, visual, depth, format, NULL, fim->shminfo, width, height))) { error = True; goto bail; } fim->shminfo->shmid = Fshmget( IPC_PRIVATE, fim->im->bytes_per_line * fim->im->height, IPC_CREAT|0777); if (fim->shminfo->shmid <= 0) { error = True; goto bail; } fim->shminfo->shmaddr = fim->im->data = Fshmat( fim->shminfo->shmid, 0, 0); if (fim->shminfo->shmaddr == (char *)(-1)) { error = True; goto bail; } fim->shminfo->readOnly = False; /* use the error handler for a definitive error */ save_handler = XSetErrorHandler(FShmErrorHandler); if (!FShmAttach(dpy, fim->shminfo)) { error = True; } else { XSync(dpy, False); } if (!error && !FShmImagesSupported) { /* get an X error: we are a remote client */ if (FShmDetach(dpy, fim->shminfo)) { XSync(dpy, False); } error = True; } XSetErrorHandler(save_handler); bail: if (error) { if (fim->im) { XDestroyImage (fim->im); fim->im = NULL; } if (fim->shminfo->shmaddr) { Fshmdt(fim->shminfo->shmaddr); } if (fim->shminfo->shmid > 0) { Fshmctl(fim->shminfo->shmid, IPC_RMID, 0); } free(fim->shminfo); fim->shminfo = NULL; } } /* ---------------------------- interface functions ------------------------ */ FImage *FCreateFImage ( Display *dpy, Visual *visual, unsigned int depth, int format, unsigned int width, unsigned int height) { FImage *fim; FShmInit(dpy); fim = (FImage *)safemalloc(sizeof(FImage)); fim->im = NULL; fim->shminfo = NULL; if (XShmSupport && FShmImagesSupported) { FShmSafeCreateImage( dpy, fim, visual, depth, format, width, height); } if(!fim->im ) { if ((fim->im = XCreateImage( dpy, visual, depth, ZPixmap, 0, 0, width, height, Pdepth > 16 ? 32 : (Pdepth > 8 ? 16 : 8), 0))) { fim->im->data = safemalloc( fim->im->bytes_per_line * height); } else { free(fim); } } return fim; } FImage *FGetFImage( Display *dpy, Drawable d, Visual *visual, unsigned int depth, int x, int y, unsigned int width, unsigned int height, unsigned long plane_mask, int format) { FImage *fim; FShmInit(dpy); fim = (FImage *)safemalloc(sizeof(FImage)); fim->im = NULL; fim->shminfo = NULL; if (XShmSupport && FShmImagesSupported) { FShmSafeCreateImage( dpy, fim, visual, depth, format, width, height); if (fim->im) { (void)FShmGetImage(dpy, d, fim->im, x, y, plane_mask); } } if (!fim->im) { fim->im = XGetImage( dpy, d, x, y, width, height, plane_mask, format); } return fim; } void FPutFImage( Display *dpy, Drawable d, GC gc, FImage *fim, int src_x, int src_y, int dest_x, int dest_y, unsigned int width, unsigned int height) { if (fim->shminfo) { if (FShmPutImage( dpy, d, gc, fim->im, src_x, src_y, dest_x, dest_y, width, height, False)) { } } else { XPutImage( dpy, d, gc, fim->im, src_x, src_y, dest_x, dest_y, width, height); } } void FDestroyFImage(Display *dpy, FImage *fim) { if (fim->shminfo) { if (FShmDetach(dpy, fim->shminfo)) { } } XDestroyImage (fim->im); if (fim->shminfo) { Fshmdt(fim->shminfo->shmaddr); Fshmctl(fim->shminfo->shmid, IPC_RMID, 0); free(fim->shminfo); } free(fim); } fvwm-2.7.0/libs/Fxpm.h0000644000175000017500000001250414147024700011435 00000000000000/* -*-c-*- */ /* Copyright (C) 2002 Olivier Chapuis */ #ifndef FXPM_H #define FXPM_H #include "PictureBase.h" #if XpmSupport #include #endif /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ #if XpmSupport typedef XpmColorSymbol FxpmColorSymbol; typedef XpmExtension FxpmExtension; typedef XpmColor FxpmColor; typedef XpmAttributes FxpmAttributes; typedef XpmImage FxpmImage; typedef XpmInfo FxpmInfo; #else typedef struct { char *name; char *value; Pixel pixel; } FxpmColorSymbol; typedef struct { char *name; unsigned int nlines; char **lines; } FxpmExtension; typedef struct { char *string; char *symbolic; char *m_color; char *g4_color; char *g_color; char *c_color; } FxpmColor; typedef int (*FxpmAllocColorFunc)( #ifdef __STDC__ Display*,Colormap,char*,XColor*,void* #endif ); typedef int (*FxpmFreeColorsFunc)( #ifdef __STDC__ Display*,Colormap,Pixel*,int,void* #endif ); typedef struct { unsigned long valuemask; Visual *visual; Colormap colormap; unsigned int depth; unsigned int width; unsigned int height; unsigned int x_hotspot; unsigned int y_hotspot; unsigned int cpp; Pixel *pixels; unsigned int npixels; FxpmColorSymbol *colorsymbols; unsigned int numsymbols; char *rgb_fname; unsigned int nextensions; FxpmExtension *extensions; unsigned int ncolors; FxpmColor *colorTable; char *hints_cmt; char *colors_cmt; char *pixels_cmt; unsigned int mask_pixel; Bool exactColors; unsigned int closeness; unsigned int red_closeness; unsigned int green_closeness; unsigned int blue_closeness; int color_key; Pixel *alloc_pixels; int nalloc_pixels; Bool alloc_close_colors; int bitmap_format; FxpmAllocColorFunc alloc_color; FxpmFreeColorsFunc free_colors; void *color_closure; } FxpmAttributes; typedef struct { unsigned int width; unsigned int height; unsigned int cpp; unsigned int ncolors; FxpmColor *colorTable; unsigned int *data; } FxpmImage; typedef struct { unsigned long valuemask; unsigned int x_hotspot; unsigned int y_hotspot; } FxpmInfo; #endif /* ---------------------------- global definitions ------------------------- */ #if XpmSupport #define FxpmReturnPixels XpmReturnPixels #define FxpmSize XpmSize #define FxpmReturnAllocPixels XpmReturnAllocPixels #define FxpmCloseness XpmCloseness #define FxpmVisual XpmVisual #define FxpmColormap XpmColormap #define FxpmDepth XpmDepth #define FxpmHotspot XpmHotspot #define FxpmExtensions XpmExtensions #define FxpmCharsPerPixel XpmCharsPerPixel #define FxpmColorSymbols XpmColorSymbols #define FxpmRgbFilename XpmRgbFilename #define FxpmInfos XpmInfos #define FxpmReturnInfos XpmReturnInfos #define FxpmReturnExtensions XpmReturnExtensions #define FxpmRGBCloseness XpmRGBCloseness #define FxpmColorKey XpmColorKey #define FxpmAllocCloseColors XpmAllocCloseColors #define FxpmBitmapFormat XpmBitmapFormat #define FxpmAllocColor XpmAllocColor #define FxpmFreeColors XpmFreeColors #define FxpmColorClosure XpmColorClosure #define FxpmComments XpmComments #define FxpmReturnComments XpmReturnComments #define FxpmUndefPixel XpmUndefPixel #define FxpmColorError XpmColorError #define FxpmSuccess XpmSuccess #define FxpmOpenFailed XpmOpenFailed #define FxpmFileInvalid XpmFileInvalid #define FxpmNoMemory XpmNoMemory #define FxpmColorFailed XpmColorFailed #define FXPM_MONO XPM_MONO #define FXPM_GREY4 XPM_GREY4 #define FXPM_GRAY4 XPM_GRAY4 #define FXPM_GREY XPM_GREY #define FXPM_GRAY XPM_GRAY #define FXPM_COLOR XPM_COLOR #define FxpmReadFileToXpmImage(a,b,c) XpmReadFileToXpmImage(a,b,c) #define FxpmCreatePixmapFromXpmImage(a,b,c,d,e,f) \ XpmCreatePixmapFromXpmImage(a,b,c,d,e,f) #define FxpmFreeXpmImage(a) XpmFreeXpmImage(a) #define FxpmFreeXpmInfo(a) XpmFreeXpmInfo(a) #define FxpmReadFileToPixmap(a,b,c,d,e,f) XpmReadFileToPixmap(a,b,c,d,e,f) #define FxpmReadFileToImage(a,b,c,d,e) XpmReadFileToImage(a,b,c,d,e) #define FxpmCreatePixmapFromData(a,b,c,d,e,f) \ XpmCreatePixmapFromData(a,b,c,d,e,f) #else /* !XpmSupport */ #define FxpmReturnPixels 0 #define FxpmSize 0 #define FxpmReturnAllocPixels 0 #define FxpmCloseness 0 #define FxpmVisual 0 #define FxpmColormap 0 #define FxpmDepth 0 #define FxpmHotspot 0 #define FxpmExtensions 0 #define FxpmCharsPerPixel 0 #define FxpmColorSymbols 0 #define FxpmRgbFilename 0 #define FxpmInfos 0 #define FxpmReturnInfos 0 #define FxpmReturnExtensions 0 #define FxpmRGBCloseness 0 #define FxpmColorKey 0 #define FxpmAllocCloseColors 0 #define FxpmBitmapFormat 0 #define FxpmAllocColor 0 #define FxpmFreeColors 0 #define FxpmColorClosure 0 #define FxpmComments 0 #define FxpmReturnComments 0 #define FxpmUndefPixel 0 #define FxpmColorError 1 #define FxpmSuccess 0 #define FxpmOpenFailed -1 #define FxpmFileInvalid -2 #define FxpmNoMemory -3 #define FxpmColorFailed -4 #define FXPM_MONO 2 #define FXPM_GREY4 3 #define FXPM_GRAY4 3 #define FXPM_GREY 4 #define FXPM_GRAY 4 #define FXPM_COLOR 5 #define FxpmReadFileToXpmImage(a,b,c) 0 #define FxpmCreatePixmapFromXpmImage(a,b,c,d,e,f) 0 #define FxpmFreeXpmImage(a) #define FxpmFreeXpmInfo(a) #define FxpmReadFileToPixmap(a,b,c,d,e,f) 0 #define FxpmCreatePixmapFromData(a,b,c,d,e,f) 0 #endif /* XpmSupport */ #endif /* FXPM_H */ fvwm-2.7.0/libs/WinMagic.h0000644000175000017500000000071114147024700012216 00000000000000#ifndef LIB_WINMAGIC #define LIB_WINMAGIC void SlideWindow( Display *dpy, Window win, int s_x, int s_y, int s_w, int s_h, int e_x, int e_y, int e_w, int e_h, int steps, int delay_ms, float *ppctMovement, Bool do_sync, Bool use_hints); Window GetTopAncestorWindow(Display *dpy, Window child); int GetEqualSizeChildren( Display *dpy, Window parent, int depth, VisualID visualid, Colormap colormap, Window **ret_children); #endif /* LIB_WINMAGIC */ fvwm-2.7.0/libs/wild.c0000644000175000017500000000412114147024700011451 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ #include "config.h" #include #include "wild.h" /* * Does `string' match `pattern'? '*' in pattern matches any sub-string * (including the null string) '?' matches any single char. For use * by filenameforall. Note that '*' matches across directory boundaries * * This code donated by Paul Hudson * It is public domain, no strings attached. No guarantees either. * */ int matchWildcards(const char *pattern, const char *string) { if(string == NULL) { if(pattern == NULL) return 1; else if(strcmp(pattern,"*")==0) return 1; else return 0; } if(pattern == NULL) return 1; while (*string && *pattern) { if (*pattern == '?') { /* match any character */ pattern += 1; string += 1; } else if (*pattern == '*') { /* see if the rest of the pattern matches any trailing * substring of the string. */ pattern += 1; if (*pattern == 0) { return 1; /* trailing * must match rest */ } while (*string) { if (matchWildcards(pattern,string)) { return 1; } string++; } return 0; } else { if (*pattern == '\\') { /* has strange, but harmless effects if the * last character is a '\\' */ pattern ++; } if (*pattern++ != *string++) { return 0; } } } if((*pattern == 0)&&(*string == 0)) return 1; if((*string == 0)&&(strcmp(pattern,"*")==0)) return 1; return 0; } fvwm-2.7.0/libs/Strings.c0000644000175000017500000001145314147024700012151 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ** Strings.c: various routines for dealing with strings */ #include "config.h" #include #include "safemalloc.h" #include "Strings.h" #define CHUNK_SIZE 256 char *CatString3(const char *a, const char *b, const char *c) { static char* buffer = NULL; static int buffer_len = 0; int len = 1; if (a != NULL) { len += strlen(a); } if (b != NULL) { len += strlen(b); } if (c != NULL) { len += strlen(c); } /* Expand buffer to fit string, to a multiple of CHUNK_SIZE */ if (len > buffer_len) { buffer_len = CHUNK_SIZE * (1 + ((len - 1) / CHUNK_SIZE)); buffer = saferealloc(buffer, buffer_len); } buffer[0] = 0; if (a != NULL) { strcat(buffer, a); } if (b != NULL) { strcat(buffer, b); } if (c != NULL) { strcat(buffer, c); } return buffer; } #undef CHUNK_SIZE void CopyString(char **dest, const char *source) { int len; const char *start; if (source == NULL) { *dest = NULL; return; } /* set 'start' to the first character of the string, skipping over spaces, but not newlines (newline terminates the string) */ while ( isspace((unsigned char)*source) && (*source != '\n') ) { source++; } start = source; /* set 'len' to the length of the string, ignoring trailing spaces */ len = 0; while ( (*source != '\n') && (*source != 0) ) { len++; source++; } source--; while( len > 0 && isspace((unsigned char)*source) ) { len--; source--; } *dest = safemalloc(len+1); strncpy(*dest,start,len); (*dest)[len]=0; } void CopyStringWithQuotes(char **dest, const char *src) { while (src && src[0] == ' ') { src++; } if (src && src[0] == '"') { int len; src++; CopyString(dest, src); len = strlen(*dest); if (len > 0 && (*dest)[len - 1] == '"') { (*dest)[len - 1] = '\0'; } } else { CopyString(dest, src); } } /* * * Copies a string into a new, malloc'ed string * Strips leading spaces and trailing spaces and new lines * */ char *stripcpy( const char *source ) { const char* tmp; char* ptr; int len; if(source == NULL) { return NULL; } while(isspace((unsigned char)*source)) { source++; } len = strlen(source); tmp = source + len -1; while( (tmp >= source) && ((isspace((unsigned char)*tmp)) || (*tmp == '\n')) ) { tmp--; len--; } ptr = safemalloc(len+1); if (len) { strncpy(ptr,source,len); } ptr[len]=0; return ptr; } int StrEquals( const char *s1, const char *s2 ) { if (s1 == NULL && s2 == NULL) { return 1; } if (s1 == NULL || s2 == NULL) { return 0; } return strcasecmp(s1,s2) == 0; } int StrHasPrefix( const char* string, const char* prefix ) { if ( prefix == NULL ) { return 1; } if ( string == NULL ) { return 0; } return strncasecmp( string, prefix, strlen(prefix) ) == 0; } /* * * Adds single quotes arround the string and escapes single quotes with * backslashes. The result is placed in the given dest, not allocated. * The end of destination, i.e. pointer to '\0' is returned. * You should allocate dest yourself, at least strlen(source) * 2 + 3. * */ char *QuoteString(char *dest, const char *source) { int i = 0; *dest++ = '\''; for(i = 0; source[i]; i++) { if (source[i] == '\'') { *dest++ = '\\'; } *dest++ = source[i]; } *dest++ = '\''; *dest = '\0'; return dest; } /* * Adds delim around the source and escapes all characters in escape with * the corresponding escaper. The dest string must be preallocated. * delim should be included in escape with a proper escaper. * Returns a pointer to the end of dest. */ char *QuoteEscapeString(char *dest, const char *source, char delim, const char *escape, const char *escaper) { *dest++ = delim; while (*source) { char *esc; esc = strchr(escape, *source); if (esc != NULL) { *dest++ = escaper[(int)(esc-escape)]; } *dest++ = *source++; } *dest++ = delim; *dest = '\0'; return dest; } /* * Calculates the lenght needed by a escaped by QuoteEscapeString * the corresponding escaper. */ unsigned int QuoteEscapeStringLength(const char *source, const char *escape) { unsigned int len = 2; while (*source) { if (strchr(escape, *source) != NULL) { len++; } len++; source++; } return len; } fvwm-2.7.0/libs/Bindings.c0000644000175000017500000005056214147024700012261 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ #include "config.h" #include #include #include #include #include "libs/fvwmlib.h" #include "libs/Strings.h" #include "libs/wild.h" #include "libs/Grab.h" #include "libs/Bindings.h" #include "libs/charmap.h" #include "libs/wcontext.h" #include "libs/modifiers.h" static Bool is_grabbing_everything = False; static int key_min = 0; static int key_max = 0; /* Free the memory use by a binding. */ void FreeBindingStruct(Binding *b) { if (b->key_name) { free(b->key_name); } STROKE_CODE( if (b->Stroke_Seq) free(b->Stroke_Seq); ); if (b->Action) { free(b->Action); } if (b->Action2) { free(b->Action2); } if (b->windowName) { free(b->windowName); } free(b); return; } void FreeBindingList(Binding *b) { Binding *t; for (; b != NULL; b = t) { t = b->NextBinding; FreeBindingStruct(b); } return; } /* Unlink a binding b from a binding list pblist. The previous binding in the * list (prev) must be given also. Pass NULL at the beginning of the list. * The *pblist pointer may be modified by this function. */ static void UnlinkBinding(Binding **pblist, Binding *b, Binding *prev) { Binding *t; if (!prev && b != *pblist) { for (t = *pblist; t && t != b; prev = t, t = t->NextBinding) { /* Find the previous binding in the list. */ } if (t == NULL) { /* Binding not found */ return; } } if (prev) { /* middle of list */ prev->NextBinding = b->NextBinding; } else { /* must have been first one, set new start */ *pblist = b->NextBinding; } return; } /* To remove a binding from the global list (probably needs more processing * for mouse binding lines though, like when context is a title bar button). * Specify either button or keysym, depending on type. */ void RemoveBinding(Binding **pblist, Binding *b, Binding *prev) { UnlinkBinding(pblist, b, NULL); FreeBindingStruct(b); return; } /* * * Actually adds a new binding to a list (pblist) of existing bindings. * Specify either button or keysym/key_name, depending on type. * The parameters action and action2 are assumed to reside in malloced memory * that will be freed in RemoveBinding. The key_name is copied into private * memory and has to be freed by the caller. * */ int AddBinding( Display *dpy, Binding **pblist, binding_t type, STROKE_ARG(void *stroke) int button, KeySym keysym, char *key_name, int modifiers, int contexts, void *action, void *action2, char *windowName) { int i; int min; int max; int maxmods; int m; int mask; int count = 0; KeySym tkeysym; Binding *temp; /* ** Unfortunately a keycode can be bound to multiple keysyms and a ** keysym can bound to multiple keycodes. Thus we have to check every ** keycode with any single modifier. */ if (BIND_IS_KEY_BINDING(type)) { if (key_max == 0) { XDisplayKeycodes(dpy, &key_min, &key_max); } min=key_min; max=key_max; maxmods = 8; } else { min = button; max = button; maxmods = 0; } for (i = min; i <= max; i++) { unsigned int bound_mask = 0; /* If this is a mouse binding we'll fall through the for loop * (maxmods is zero) and the if condition is always true (type * is zero). Since min == max == button there is no loop at all * is case of a mouse binding. */ for (m = 0, tkeysym = XK_Left; m <= maxmods && tkeysym != NoSymbol; m++) { if (BIND_IS_MOUSE_BINDING(type) || STROKE_CODE(BIND_IS_STROKE_BINDING(type) ||) (tkeysym = fvwm_KeycodeToKeysym(dpy, i, m, 0)) == keysym) { unsigned int add_modifiers = 0; unsigned int bind_mask = 1; unsigned int check_bound_mask = 0; switch (m) { case 0: /* key generates the key sym with no * modifiers depressed - bind it */ break; case 1: /* key generates the key sym with shift * depressed */ if (modifiers != AnyModifier && !(modifiers & ShiftMask)) { add_modifiers = ShiftMask; bind_mask = (1 << m); /* but don't bind it again if * already bound without * modifiers */ check_bound_mask = 1; } break; default: /* key generates the key sym with * undefined modifiers depressed - * let's make an educated guess at what * modifiers the user expected * based on the XFree86 default * configuration. */ mask = modifier_mapindex_to_mask[m - 1]; if (modifiers != AnyModifier && !((modifiers & mask) != mask)) { add_modifiers = mask; bind_mask = (1 << m); /* but don't bind it again if * already bound without * modifiers */ check_bound_mask = 1; } break; } if ((bind_mask & bound_mask) || (check_bound_mask & bound_mask)) { /* already bound, break out */ break; } temp = *pblist; (*pblist) = (Binding *)safemalloc( sizeof(Binding)); (*pblist)->type = type; (*pblist)->Button_Key = i; STROKE_CODE((*pblist)->Stroke_Seq = (stroke) ? (void *)stripcpy((char *)stroke) : NULL); if (BIND_IS_KEY_BINDING(type) && key_name != NULL) { (*pblist)->key_name = stripcpy(key_name); } else { (*pblist)->key_name = NULL; } (*pblist)->Context = contexts; (*pblist)->Modifier = modifiers | add_modifiers; (*pblist)->Action = (action) ? stripcpy(action) : NULL; (*pblist)->Action2 = (action2) ? stripcpy(action2) : NULL; (*pblist)->windowName = windowName ? stripcpy(windowName) : NULL; (*pblist)->NextBinding = temp; bound_mask |= bind_mask; count++; } } } return count; } /* returns 1 if binding b1 is identical to binding b2 (except action) * returns 2 if b1 and b2 are identical except that b1 has a different window * name than b2 and both are not NULL * returns 0 otherwise */ static int compare_bindings(Binding *b1, Binding *b2) { if (b1->type != b2->type) { return 0; } if (b1->Context != b2->Context) { return 0; } if (b1->Modifier != b2->Modifier) { return 0; } if (b1->Button_Key != b2->Button_Key) { return 0; } /* definition: "global binding" => b->windowName == NULL * definition: "window-specific binding" => b->windowName != NULL */ if (b1->windowName && b2->windowName) { /* Both bindings are window-specific. The existing binding, b2, * is only replaced (by b1) if it applies to the same window */ if (strcmp(b1->windowName, b2->windowName) != 0) { return 2; } } else if (b1->windowName || b2->windowName) { /* 1 binding is window-specific, the other is global - no need * to replace this binding. */ return 0; } if (BIND_IS_KEY_BINDING(b1->type) || BIND_IS_MOUSE_BINDING(b1->type)) { return 1; } if (1 STROKE_CODE(&& BIND_IS_STROKE_BINDING(b1->type) && strcmp(b1->Stroke_Seq, b2->Stroke_Seq) == 0)) { return 1; } return 0; } /* * Does exactly the opposite of AddBinding: It removes the bindings that * AddBinding would have added to the *pblist_src and collects them in the * *pblist_dest. This can be used to remove a binding completely from the * list. The bindings still have to be freed. */ void CollectBindingList( Display *dpy, Binding **pblist_src, Binding **pblist_dest, Bool *ret_are_similar_bindings_left, binding_t type, STROKE_ARG(void *stroke) int button, KeySym keysym, int modifiers, int contexts, char *windowName) { Binding *tmplist = NULL; Binding *bold; Binding *oldprev; *ret_are_similar_bindings_left = False; /* generate a private list of bindings to be removed */ AddBinding( dpy, &tmplist, type, STROKE_ARG(stroke) button, keysym, NULL, modifiers, contexts, NULL, NULL, windowName); /* now find equivalent bindings in the given binding list and move * them to the new clist */ for (bold = *pblist_src, oldprev = NULL; bold != NULL; ) { Binding *btmp; Binding *bfound; bfound = NULL; for (btmp = tmplist; btmp != NULL && ( bfound == NULL || *ret_are_similar_bindings_left == False); btmp = btmp->NextBinding) { int rc; rc = compare_bindings(btmp, bold); if (rc == 1) { bfound = btmp; } else if (rc == 2) { *ret_are_similar_bindings_left = True; if (bfound != NULL) { break; } } } if (bfound != NULL) { Binding *next; /* move matched binding from src list to dest list */ UnlinkBinding(pblist_src, bold, oldprev); next = bold->NextBinding; bold->NextBinding = *pblist_dest; *pblist_dest = bold; /* oldprev is unchanged */ bold = next; } else { oldprev = bold; bold = bold->NextBinding; } } /* throw away the temporary list */ FreeBindingList(tmplist); return; } /* * bindingAppliesToWindow() * * The Key/Mouse/PointerKey syntax (optionally) allows a window name * (or class or resource) to be specified with the binding, denoting * which windows the binding can be invoked in. This function determines * if the binding actually applies to a window based on its * name/class/resource. */ static Bool does_binding_apply_to_window( Binding *binding, const XClassHint *win_class, const char *win_name) { /* If no window name is specified with the binding then that means * the binding applies to ALL windows. */ if (binding->windowName == NULL) { return True; } else if (win_class == NULL || win_name == NULL) { return False; } if (matchWildcards(binding->windowName, win_name) == True || matchWildcards(binding->windowName, win_class->res_name) == True || matchWildcards(binding->windowName, win_class->res_class) == True) { return True; } return False; } static Bool __compare_binding( Binding *b, STROKE_ARG(char *stroke) int button_keycode, unsigned int modifier, unsigned int used_modifiers, int Context, binding_t type, const XClassHint *win_class, const char *win_name) { if (b->type != type || !(b->Context & Context)) { return False; } if ((b->Modifier & used_modifiers) != modifier && b->Modifier != AnyModifier) { return False; } if (BIND_IS_MOUSE_BINDING(type) && (b->Button_Key != button_keycode && b->Button_Key != 0)) { return False; } else if (BIND_IS_KEY_BINDING(type) && b->Button_Key != button_keycode) { return False; } #ifdef HAVE_STROKE else if (BIND_IS_STROKE_BINDING(type) && ((strcmp(b->Stroke_Seq, stroke) != 0) || b->Button_Key != button_keycode)) { return False; } #endif if (!does_binding_apply_to_window(b, win_class, win_name)) { return False; } return True; } /* is_pass_through_action() - returns true if the action indicates that the * binding should be ignored by fvwm & passed through to the underlying * window. * Note: it is only meaningful to check for pass-thru actions on * window-specific bindings. */ Bool is_pass_through_action(const char *action) { /* action should never be NULL. */ return (strncmp(action, "--", 2) == 0); } /* Check if something is bound to a key or button press and return the action * to be executed or NULL if not. */ void *CheckBinding( Binding *blist, STROKE_ARG(char *stroke) int button_keycode, unsigned int modifier,unsigned int dead_modifiers, int Context, binding_t type, const XClassHint *win_class, const char *win_name) { Binding *b; unsigned int used_modifiers = ~dead_modifiers; void *action = NULL; modifier &= (used_modifiers & ALL_MODIFIERS); for (b = blist; b != NULL; b = b->NextBinding) { if (__compare_binding( b, STROKE_ARG(stroke) button_keycode, modifier, used_modifiers, Context, type, win_class, win_name) == True) { /* If this is a global binding, keep searching * in the hope of finding a window-specific binding. * If we don't find a win-specific binding, we use the * _first_ matching global binding we hit. */ if (action == NULL || b->windowName) { action = b->Action; if (b->windowName) { if (is_pass_through_action(action)) { action = NULL; } break; } } } } return action; } void *CheckTwoBindings( Bool *ret_is_second_binding, Binding *blist, STROKE_ARG(char *stroke) int button_keycode, unsigned int modifier,unsigned int dead_modifiers, int Context, binding_t type, const XClassHint *win_class, const char *win_name, int Context2, binding_t type2, const XClassHint *win_class2, const char *win_name2) { Binding *b; unsigned int used_modifiers = ~dead_modifiers; void *action = NULL; modifier &= (used_modifiers & ALL_MODIFIERS); for (b = blist; b != NULL; b = b->NextBinding) { if (__compare_binding( b, STROKE_ARG(stroke) button_keycode, modifier, used_modifiers, Context, type, win_class, win_name) == True) { if (action == NULL || b->windowName) { *ret_is_second_binding = False; action = b->Action; if (b->windowName) { if (is_pass_through_action(action)) action = NULL; break; } } } if (__compare_binding( b, STROKE_ARG(stroke) button_keycode, modifier, used_modifiers, Context2, type2, win_class2, win_name2) == True) { if (action == NULL || b->windowName) { *ret_is_second_binding = True; action = b->Action; if (b->windowName) { if (is_pass_through_action(action)) { action = NULL; } break; } } } } return action; } /* * GrabWindowKey - grab needed keys for the window for one binding * GrabAllWindowKeys - grab needed keys for the window for all bindings * in blist * GrabWindowButton - same for mouse buttons * GrabAllWindowButtons - same for mouse buttons * GrabAllWindowKeysAndButtons - both of the above * * Inputs: * w - the window to use (the frame window) * grab - 1 to grab, 0 to ungrab * binding - pointer to the bindinge to grab/ungrab * contexts - all context bits that shall receive bindings * dead_modifiers - modifiers to ignore for 'AnyModifier' * cursor - the mouse cursor to use when the pointer is on the * grabbed area (mouse bindings only) * */ void GrabWindowKey(Display *dpy, Window w, Binding *binding, unsigned int contexts, unsigned int dead_modifiers, Bool fGrab) { /* remove unnecessary bits from dead_modifiers */ dead_modifiers &= ~(binding->Modifier & dead_modifiers); dead_modifiers &= ALL_MODIFIERS; if((binding->Context & contexts) && BIND_IS_KEY_BINDING(binding->type)) { if (fGrab) { XGrabKey( dpy, binding->Button_Key, binding->Modifier, w, True, GrabModeAsync, GrabModeAsync); } else { XUngrabKey( dpy, binding->Button_Key, binding->Modifier, w); } if(binding->Modifier != AnyModifier && dead_modifiers != 0) { register unsigned int mods; register unsigned int max = dead_modifiers; register unsigned int living_modifiers = ~dead_modifiers; /* handle all bindings for the dead modifiers */ for (mods = 1; mods <= max; mods++) { /* Since mods starts with 1 we don't need to * test if mods contains a dead modifier. * Otherwise both, dead and living modifiers * would be zero ==> mods == 0 */ if (mods & living_modifiers) { continue; } if (fGrab) { XGrabKey( dpy, binding->Button_Key, mods|binding->Modifier, w, True, GrabModeAsync, GrabModeAsync); } else { XUngrabKey( dpy, binding->Button_Key, mods|binding->Modifier, w); } } } if (!is_grabbing_everything) { XSync(dpy, 0); } } return; } void GrabAllWindowKeys( Display *dpy, Window w, Binding *blist, unsigned int contexts, unsigned int dead_modifiers, Bool fGrab) { MyXGrabServer(dpy); is_grabbing_everything = True; for ( ; blist != NULL; blist = blist->NextBinding) { GrabWindowKey(dpy, w, blist, contexts, dead_modifiers, fGrab); } is_grabbing_everything = False; MyXUngrabServer(dpy); return; } void GrabWindowButton( Display *dpy, Window w, Binding *binding, unsigned int contexts, unsigned int dead_modifiers, Cursor cursor, Bool fGrab) { if (binding->Action == NULL) { return; } dead_modifiers &= ~(binding->Modifier & dead_modifiers); /* dje */ dead_modifiers &= ALL_MODIFIERS; if ((binding->Context & contexts) && ((BIND_IS_MOUSE_BINDING(binding->type) || (BIND_IS_STROKE_BINDING(binding->type) && binding->Button_Key !=0)))) { int bmin = 1; int bmax = NUMBER_OF_EXTENDED_MOUSE_BUTTONS; int button; if(binding->Button_Key >0) { bmin = bmax = binding->Button_Key; } for (button = bmin; button <= bmax; button++) { if (fGrab) { XGrabButton( dpy, button, binding->Modifier, w, True, ButtonPressMask | ButtonReleaseMask, GrabModeSync, GrabModeAsync, None, cursor); } else { XUngrabButton( dpy, button, binding->Modifier, w); } if (binding->Modifier != AnyModifier && dead_modifiers != 0) { register unsigned int mods; register unsigned int max = dead_modifiers; register unsigned int living_modifiers = ~dead_modifiers; /* handle all bindings for the dead modifiers */ for (mods = 1; mods <= max; mods++) { /* Since mods starts with 1 we don't * need to test if mods contains a * dead modifier. Otherwise both, dead * and living modifiers would be zero * ==> mods == 0 */ if (mods & living_modifiers) { continue; } if (fGrab) { XGrabButton( dpy, button, mods|binding->Modifier, w, True, ButtonPressMask | ButtonReleaseMask, GrabModeSync, GrabModeAsync, None, cursor); } else { XUngrabButton( dpy, button, mods|binding->Modifier, w); } } } if (!is_grabbing_everything) { XSync(dpy, 0); } } } return; } void GrabAllWindowButtons( Display *dpy, Window w, Binding *blist, unsigned int contexts, unsigned int dead_modifiers, Cursor cursor, Bool fGrab) { MyXGrabServer(dpy); is_grabbing_everything = True; for ( ; blist != NULL; blist = blist->NextBinding) { GrabWindowButton(dpy, w, blist, contexts, dead_modifiers, cursor, fGrab); } is_grabbing_everything = False; MyXUngrabServer(dpy); return; } void GrabAllWindowKeysAndButtons( Display *dpy, Window w, Binding *blist, unsigned int contexts, unsigned int dead_modifiers, Cursor cursor, Bool fGrab) { MyXGrabServer(dpy); is_grabbing_everything = True; for ( ; blist != NULL; blist = blist->NextBinding) { if (blist->Context & contexts) { if (BIND_IS_MOUSE_BINDING(blist->type) || BIND_IS_STROKE_BINDING(blist->type)) { GrabWindowButton( dpy, w, blist, contexts, dead_modifiers, cursor, fGrab); } else if (BIND_IS_KEY_BINDING(blist->type)) { GrabWindowKey( dpy, w, blist, contexts, dead_modifiers, fGrab); } } } is_grabbing_everything = False; MyXUngrabServer(dpy); return; } void GrabWindowKeyOrButton( Display *dpy, Window w, Binding *binding, unsigned int contexts, unsigned int dead_modifiers, Cursor cursor, Bool fGrab) { if (BIND_IS_MOUSE_BINDING(binding->type) || BIND_IS_STROKE_BINDING(binding->type)) { GrabWindowButton( dpy, w, binding, contexts, dead_modifiers, cursor, fGrab); } else if (BIND_IS_KEY_BINDING(binding->type)) { GrabWindowKey( dpy, w, binding, contexts, dead_modifiers, fGrab); } return; } /* * * Like XStringToKeysym, but allows some typos and does some additional * error checking. * */ KeySym FvwmStringToKeysym(Display *dpy, char *key) { KeySym keysym; char *s; if (!isalpha(*key)) { keysym = XStringToKeysym(key); } else { s = alloca(strlen(key) + 1); strcpy(s, key); /* always prefer the lower case spelling if it exists */ *s = tolower(*s); keysym = XStringToKeysym(s); if (keysym == NoSymbol) { *s = toupper(*s); keysym = XStringToKeysym(s); } } if (keysym == NoSymbol || XKeysymToKeycode(dpy, keysym) == 0) { return 0; } return keysym; } fvwm-2.7.0/libs/Event.c0000644000175000017500000000245214147024700011600 00000000000000/* -*-c-*- */ /* Copyright (C) 2001 Dominik Vogt */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ #include "config.h" #include #include #include "fvwmlib.h" #include "Event.h" /* * Return the subwindow member of an event if the event type has one. */ Window GetSubwindowFromEvent(Display *dpy, const XEvent *eventp) { if (eventp == NULL) { return None; } switch (eventp->type) { case ButtonPress: case ButtonRelease: return eventp->xbutton.subwindow; case KeyPress: case KeyRelease: return eventp->xkey.subwindow; case EnterNotify: case LeaveNotify: return eventp->xcrossing.subwindow; case MotionNotify: return eventp->xmotion.subwindow; default: return None; } } fvwm-2.7.0/libs/FImage.h0000644000175000017500000000165114147024676011670 00000000000000/* -*-c-*- */ #ifndef FIMAGE_H #define FIMAGE_H /* ---------------------------- included header files ---------------------- */ #include "config.h" #include "FShm.h" /* ---------------------------- type definitions --------------------------- */ typedef struct { XImage *im; FShmSegmentInfo *shminfo; } FImage; /* ---------------------------- interface functions ------------------------ */ FImage *FCreateFImage ( Display *dpy, Visual *visual, unsigned int depth, int format, unsigned int width, unsigned int height); FImage *FGetFImage( Display *dpy, Drawable d, Visual *visual, unsigned int depth, int x, int y, unsigned int width, unsigned int height, unsigned long plane_mask, int format); void FPutFImage( Display *dpy, Drawable d, GC gc, FImage *fim, int src_x, int src_y, int dest_x, int dest_y, unsigned int width, unsigned int height); void FDestroyFImage(Display *dpy, FImage *fim); #endif /* FIMAGE_H */ fvwm-2.7.0/libs/System.c0000644000175000017500000001706714147024700012013 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* * System.c: code for dealing with various OS system call variants */ #include "config.h" #include "fvwmlib.h" #include "envvar.h" #include "System.h" #include "Strings.h" #if HAVE_UNAME #include #endif #include "libs/fvwm_sys_stat.h" #if HAVE_SYS_SELECT_H #include #endif /* * just in case... */ #ifndef FD_SETSIZE #define FD_SETSIZE 2048 #endif fd_set_size_t fvwmlib_max_fd = (fd_set_size_t)-9999999; fd_set_size_t GetFdWidth(void) { #if HAVE_SYSCONF return min(sysconf(_SC_OPEN_MAX),FD_SETSIZE); #else return min(getdtablesize(),FD_SETSIZE); #endif } void fvwmlib_init_max_fd(void) { fvwmlib_max_fd = GetFdWidth(); return; } /* return a string indicating the OS type (i.e. "Linux", "SINIX-D", ... ) */ int getostype(char *buf, int max) { #if HAVE_UNAME struct utsname sysname; if (uname( &sysname ) >= 0) { buf[0] = '\0'; strncat(buf, sysname.sysname, max); return 0; } #endif strcpy (buf, ""); return -1; } /* * Set a colon-separated path, with environment variable expansions, * and expand '+' to be the value of the previous path. */ void setPath(char **p_path, const char *newpath, int free_old_path) { char *oldpath = *p_path; int oldlen = strlen(oldpath); char *stripped_path = stripcpy(newpath); int found_plus = strchr(newpath, '+') != NULL; /* Leave room for the old path, if we find a '+' in newpath */ *p_path = envDupExpand(stripped_path, found_plus ? oldlen - 1 : 0); free(stripped_path); if (found_plus) { char *p = strchr(*p_path, '+'); memmove(p + oldlen, p + 1, strlen(p + 1) + 1); memmove(p, oldpath, oldlen); } if (free_old_path) { free(oldpath); } } /* * * Find the specified file somewhere along the given path. * * There is a possible race condition here: We check the file and later * do something with it. By then, the file might not be accessible. * Oh well. * */ #include char *searchPath( const char *pathlist, const char *filename, const char *suffix, int type) { char *path; int filename_len; int maxpath_len; if (filename == NULL || *filename == 0) { return NULL; } if (pathlist == NULL || *pathlist == 0) { /* use pwd if no path list is given */ pathlist = "."; } filename_len = strlen(filename); maxpath_len = (pathlist) ? strlen(pathlist) : 0; maxpath_len += (suffix) ? strlen(suffix) : 0; /* +1 for extra / and +1 for null termination */ path = safemalloc(maxpath_len + filename_len + 2); *path = '\0'; if (*filename == '/') { /* No search if filename begins with a slash */ strcpy(path, filename); /* test if the path is accessable -- the module code assumes * this is done */ if (access(filename, type) == 0) { return path; } /* the file is not accessable (don't test suffixes with full * path), return NULL */ free(path); return NULL; } /* Search each element of the pathlist for the file */ while (pathlist && *pathlist) { char *path_end = strchr(pathlist, ':'); char *curr_end; if (path_end != NULL) { strncpy(path, pathlist, path_end - pathlist); path[path_end - pathlist] = '\0'; } else { strcpy(path, pathlist); } /* handle specially the path extention using semicolon */ curr_end = strchr(path, ';'); if (curr_end != NULL) { char *dot = strrchr(filename, '.'); int filebase_len; /* count a leading nil in newext_len too */ int newext_len = path + strlen(path) - curr_end; if (dot != NULL) { filebase_len = dot - filename; } else { filebase_len = filename_len; } *(curr_end++) = '/'; memmove(curr_end + filebase_len, curr_end, newext_len); strncpy(curr_end, filename, filebase_len); } else { strcat(path, "/"); strcat(path, filename); } if (access(path, type) == 0) { return path; } if (suffix && *suffix != '\0') { strcat(path, suffix); if (access(path, type) == 0) { return path; } } /* Point to next element of the path */ if (path_end == NULL) { break; } else { pathlist = path_end + 1; } } /* Hmm, couldn't find the file. Return NULL */ free(path); return NULL; } /* * void setFileStamp(FileStamp *stamp, const char *name); * Bool isFileStampChanged(const FileStamp *stamp, const char *name); * * An interface for verifying cached files. * The first function associates a file stamp with file (named by name). * The second function returns True or False in case the file was changed * from the time the stamp was associated. * * FileStamp can be a structure; try to save memory by evaluating a checksum. */ FileStamp getFileStamp(const char *name) { static struct stat buf; if (!name || stat(name, &buf)) { return 0; } return ((FileStamp)buf.st_mtime << 13) + (FileStamp)buf.st_size; } void setFileStamp(FileStamp *stamp, const char *name) { *stamp = getFileStamp(name); } Bool isFileStampChanged(const FileStamp *stamp, const char *name) { return *stamp != getFileStamp(name); } #ifdef HAVE_SAFETY_MKSTEMP int fvwm_mkstemp (char *TEMPLATE) { return mkstemp(TEMPLATE); } #else /* This function is an adaptation of the mkstemp() function included * in the Gnu C Library, version 2.2.2. The Gnu C library, in turn, * adapted the function from OpenBSD. * Michael Han */ #include #include #include #include #include #include #include "ftime.h" #define __set_errno(val) errno = (val) /* These are the characters used in temporary filenames. */ static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; /* Generate a unique temporary file name from TEMPLATE. The last six characters of TEMPLATE must be "XXXXXX"; they are replaced with a string that makes the filename unique. Then open the file and return a fd. */ int fvwm_mkstemp (char *template) { int len; char *XXXXXX; static unsigned long value; struct timeval tv; int count, fd = -1; int save_errno = errno; len = strlen (template); if (len < 6 || strcmp (&template[len - 6], "XXXXXX")) { __set_errno (EINVAL); return -1; } /* This is where the Xs start. */ XXXXXX = &template[len - 6]; /* Get some more or less random data. */ gettimeofday (&tv, NULL); value = ((unsigned long) tv.tv_usec << 16) ^ tv.tv_sec ^ getpid (); for (count = 0; count < TMP_MAX; value = 7777, count) { unsigned long v = value; /* Fill in the random bits. */ XXXXXX[0] = letters[v % 62]; v /= 62; XXXXXX[1] = letters[v % 62]; v /= 62; XXXXXX[2] = letters[v % 62]; v /= 62; XXXXXX[3] = letters[v % 62]; v /= 62; XXXXXX[4] = letters[v % 62]; v /= 62; XXXXXX[5] = letters[v % 62]; fd = open( template, O_RDWR | O_CREAT | O_EXCL, FVWM_S_IRUSR | FVWM_S_IWUSR); if (fd >= 0) { __set_errno (save_errno); return fd; } else if (errno != EEXIST) { return -1; } } /* We got out of the loop because we ran out of combinations to try. */ __set_errno (EEXIST); return -1; } #endif /* HAVE_SAFETY_MKSTEMP */ fvwm-2.7.0/libs/Fplay.h0000644000175000017500000003140514147024700011577 00000000000000#ifndef FPLAY_H #define FPLAY_H #ifdef HAVE_RPLAY #define USE_FPLAY 1 #else #define USE_FPLAY 0 #endif #if USE_FPLAY # include # undef M_ERROR /* Solaris fix */ typedef RPLAY FPLAY; typedef RPLAY_ATTRS FPLAY_ATTRS; # define FPLAY_DEFAULT_VALUE RPLAY_DEFAULT_VOLUME # define FPLAY_DEFAULT_PRIORITY RPLAY_DEFAULT_PRIORITY # define FPLAY_NULL RPLAY_NULL # define FPLAY_PLAY RPLAY_PLAY # define FPLAY_STOP RPLAY_STOP # define FPLAY_PAUSE RPLAY_PAUSE # define FPLAY_CONTINUE RPLAY_CONTINUE # define FPLAY_SOUND RPLAY_SOUND # define FPLAY_VOLUME RPLAY_VOLUME # define FPLAY_NSOUNDS RPLAY_NSOUNDS # define FPLAY_COMMAND RPLAY_COMMAND # define FPLAY_APPEND RPLAY_APPEND # define FPLAY_INSERT RPLAY_INSERT # define FPLAY_DELETE RPLAY_DELETE # define FPLAY_CHANGE RPLAY_CHANGE # define FPLAY_COUNT RPLAY_COUNT # define FPLAY_LIST_COUNT RPLAY_LIST_COUNT # define FPLAY_PRIORITY RPLAY_PRIORITY # define FPLAY_RANDOM_SOUND RPLAY_RANDOM_SOUND # define FPLAY_PING RPLAY_PING # define FPLAY_RPTP_SERVER RPLAY_RPTP_SERVER # define FPLAY_RPTP_SERVER_PORT RPLAY_RPTP_SERVER_PORT # define FPLAY_RPTP_SEARCH RPLAY_RPTP_SEARCH # define FPLAY_RPTP_FROM_SENDER RPLAY_RPTP_FROM_SENDER # define FPLAY_SAMPLE_RATE RPLAY_SAMPLE_RATE # define FPLAY_RESET RPLAY_RESET # define FPLAY_DONE RPLAY_DONE # define FPLAY_CLIENT_DATA RPLAY_CLIENT_DATA # define FPLAY_LIST_NAME RPLAY_LIST_NAME # define FPLAY_PUT RPLAY_PUT # define FPLAY_ID RPLAY_ID # define FPLAY_SEQUENCE RPLAY_SEQUENCE # define FPLAY_DATA RPLAY_DATA # define FPLAY_DATA_SIZE RPLAY_DATA_SIZE # define FPLAY_FORMAT_NONE RPLAY_FORMAT_NONE # define FPLAY_FORMAT_LINEAR_8 RPLAY_FORMAT_LINEAR_8 # define FPLAY_FORMAT_ULINEAR_8 RPLAY_FORMAT_ULINEAR_8 # define FPLAY_FORMAT_LINEAR_16 RPLAY_FORMAT_LINEAR_16 # define FPLAY_FORMAT_ULINEAR_16 RPLAY_FORMAT_ULINEAR_16 # define FPLAY_FORMAT_ULAW RPLAY_FORMAT_ULAW # define FPLAY_FORMAT_G721 RPLAY_FORMAT_G721 # define FPLAY_FORMAT_G723_3 RPLAY_FORMAT_G723_3 # define FPLAY_FORMAT_G723_5 RPLAY_FORMAT_G723_5 # define FPLAY_FORMAT_GSM RPLAY_FORMAT_GSM # define FPLAY_BIG_ENDIAN RPLAY_BIG_ENDIAN # define FPLAY_LITTLE_ENDIAN RPLAY_LITTLE_ENDIAN # define FPLAY_AUDIO_PORT_NONE RPLAY_AUDIO_PORT_NONE # define FPLAY_AUDIO_PORT_SPEAKER RPLAY_AUDIO_PORT_SPEAKER # define FPLAY_AUDIO_PORT_HEADPHONE RPLAY_AUDIO_PORT_HEADPHONE # define FPLAY_AUDIO_PORT_LINEOUT RPLAY_AUDIO_PORT_LINEOUT # define FPLAY_MIN_VOLUME RPLAY_MIN_VOLUME # define FPLAY_MAX_VOLUME RPLAY_MAX_VOLUME # define FPLAY_MIN_PRIORITY RPLAY_MIN_PRIORITY # define FPLAY_MAX_PRIORITY RPLAY_MAX_PRIORITY # define FPLAY_DEFAULT_VOLUME RPLAY_DEFAULT_VOLUME # define FPLAY_DEFAULT_PRIORITY RPLAY_DEFAULT_PRIORITY # define FPLAY_DEFAULT_COUNT RPLAY_DEFAULT_COUNT # define FPLAY_DEFAULT_LIST_COUNT RPLAY_DEFAULT_LIST_COUNT # define FPLAY_DEFAULT_RANDOM_SOUND RPLAY_DEFAULT_RANDOM_SOUND # define FPLAY_DEFAULT_SAMPLE_RATE RPLAY_DEFAULT_SAMPLE_RATE # define FPLAY_DEFAULT_OFFSET RPLAY_DEFAULT_OFFSET # define FPLAY_DEFAULT_BYTE_ORDER RPLAY_DEFAULT_BYTE_ORDER # define FPLAY_DEFAULT_CHANNELS RPLAY_DEFAULT_CHANNELS # define FPLAY_DEFAULT_BITS RPLAY_DEFAULT_BITS # define FPLAY_ERROR_NONE RPLAY_ERROR_NONE # define FPLAY_ERROR_MEMORY RPLAY_ERROR_MEMORY # define FPLAY_ERROR_HOST RPLAY_ERROR_HOST # define FPLAY_ERROR_CONNECT RPLAY_ERROR_CONNECT # define FPLAY_ERROR_SOCKET RPLAY_ERROR_SOCKET # define FPLAY_ERROR_WRITE RPLAY_ERROR_WRITE # define FPLAY_ERROR_CLOSE RPLAY_ERROR_CLOSE # define FPLAY_ERROR_PACKET_SIZE RPLAY_ERROR_PACKET_SIZE # define FPLAY_ERROR_BROADCAST RPLAY_ERROR_BROADCAST # define FPLAY_ERROR_ATTRIBUTE RPLAY_ERROR_ATTRIBUTE # define FPLAY_ERROR_COMMAND RPLAY_ERROR_COMMAND # define FPLAY_ERROR_INDEX RPLAY_ERROR_INDEX # define FPLAY_ERROR_MODIFIER RPLAY_ERROR_MODIFIER # define FRPTP_ERROR_NONE RPTP_ERROR_NONE # define FRPTP_ERROR_MEMORY RPTP_ERROR_MEMORY # define FRPTP_ERROR_HOST RPTP_ERROR_HOST # define FRPTP_ERROR_CONNECT RPTP_ERROR_CONNECT # define FRPTP_ERROR_SOCKET RPTP_ERROR_SOCKET # define FRPTP_ERROR_OPEN RPTP_ERROR_OPEN # define FRPTP_ERROR_READ RPTP_ERROR_READ # define FRPTP_ERROR_WRITE RPTP_ERROR_WRITE # define FRPTP_ERROR_PING RPTP_ERROR_PING # define FRPTP_ERROR_TIMEOUT RPTP_ERROR_TIMEOUT # define FRPTP_ERROR_PROTOCOL RPTP_ERROR_PROTOCOL # define FRPTP_ERROR RPTP_ERROR # define FRPTP_OK RPTP_OK # define FRPTP_TIMEOUT RPTP_TIMEOUT # define FRPTP_NOTIFY RPTP_NOTIFY # define FOLD_RPLAY_PLAY OLD_RPLAY_PLAY # define FOLD_RPLAY_STOP OLD_RPLAY_STOP # define FOLD_RPLAY_PAUSE OLD_RPLAY_PAUSE # define FOLD_RPLAY_CONTINUE OLD_RPLAY_CONTINUE # define FRPTP_ASYNC_READ RPTP_ASYNC_READ # define FRPTP_ASYNC_WRITE RPTP_ASYNC_WRITE # define FRPTP_ASYNC_RAW RPTP_ASYNC_RAW # define FRPTP_ASYNC_ENABLE RPTP_ASYNC_ENABLE # define FRPTP_ASYNC_DISABLE RPTP_ASYNC_DISABLE # define FRPTP_EVENT_OK RPTP_EVENT_OK # define FRPTP_EVENT_ERROR RPTP_EVENT_ERROR # define FRPTP_EVENT_TIMEOUT RPTP_EVENT_TIMEOUT # define FRPTP_EVENT_OTHER RPTP_EVENT_OTHER # define FRPTP_EVENT_CONTINUE RPTP_EVENT_CONTINUE # define FRPTP_EVENT_DONE RPTP_EVENT_DONE # define FRPTP_EVENT_PAUSE RPTP_EVENT_PAUSE # define FRPTP_EVENT_PLAY RPTP_EVENT_PLAY # define FRPTP_EVENT_SKIP RPTP_EVENT_SKIP # define FRPTP_EVENT_STATE RPTP_EVENT_STATE # define FRPTP_EVENT_STOP RPTP_EVENT_STOP # define FRPTP_EVENT_VOLUME RPTP_EVENT_VOLUME # define FRPTP_EVENT_CLOSE RPTP_EVENT_CLOSE # define FRPTP_EVENT_FLOW RPTP_EVENT_FLOW # define FRPTP_EVENT_MODIFY RPTP_EVENT_MODIFY # define FRPTP_EVENT_LEVEL RPTP_EVENT_LEVEL # define FRPTP_EVENT_POSITION RPTP_EVENT_POSITION # define FRPTP_EVENT_ALL RPTP_EVENT_ALL # define FRPTP_MAX_ARGS RPTP_MAX_ARGS # define FRPTP_MAX_LINE RPTP_MAX_LINE # define FPLAY_PORT RPLAY_PORT # define FRPTP_PORT RPTP_PORT # define FOLD_RPLAY_PORT OLD_RPLAY_PORT # define FOLD_RPTP_PORT OLD_RPTP_PORT # define FPLAY_PACKET_ID RPLAY_PACKET_ID # define Fplay_errno rplay_errno # define Frptp_errno rptp_errno # define Fplay(a,b) rplay(a,b) # define Fplay_create(a) rplay_create(a) # define Fplay_perror(a) rplay_perror(a) /* variadict macros appeared in C99, so we can't use them */ # define Fplay_set rplay_set # define Fplay_get rplay_get # define Frptp_putline rptp_putline # define Frptp_async_putline rptp_async_putline # define Fplay_destroy(a) rplay_destroy(a) # define Fplay_default_host() rplay_default_host() # define Fplay_display(a) rplay_display(a) # define Fplay_host(a,b) rplay_host(a,b) # define Fplay_host_volume(a,b,c) rplay_host_volume(a,b,c) # define Fplay_local(a) rplay_local(a) # define Fplay_open(a) rplay_open(a) # define Fplay_open_default() rplay_open_default() # define Fplay_open_display() rplay_open_display() # define Fplay_open_port(a,b) rplay_open_port(a,b) # define Fplay_open_sockaddr_in(a) rplay_open_sockaddr(a) # define Fplay_ping(a) rplay_ping(a) # define Fplay_ping_sockaddr_in(a) rplay_ping_sockaddr_in(a) # define Fplay_ping_sockfd(a) rplay_ping_sockfd(a) # define Fplay_close(a) rplay_close(a) # define Fplay_sound(a,b) rplay_sound(a,b) # define Fplay_default(a) rplay_default(a) # define Fplay_convert(a) rplay_convert(a) # define Fplay_pack(a) rplay_pack(a) # define Fplay_unpack(a) rplay_unpack(a) # define Frptp_open(a,b,c,d) rptp_open(a,b,c,d) # define Frptp_read(a,b,c) rptp_read(a,b,c) # define Frptp_write(a,b,c) rptp_write(a,b,c) # define Frptp_close(a) rptp_close(a) # define Frptp_perror(a) rptp_perror(a) # define Frptp_getline(a,b,c) rptp_getline(a,b,c) # define Frptp_command(a,b,c,d) rptp_command(a,b,c,d) # define Frptp_parse(a,b) rptp_parse(a,b) # define Frptp_async_write(a,b,c,d) rptp_async_write(a,b,c,d) # define Frptp_async_register(a,b,c) rptp_async_register(a,b,c) # define Frptp_async_notify(a,b,c) rptp_async_notify(a,b,c) # define Frptp_async_process(a,b) rptp_async_process(a,b) # define Frptp_main_loop() rptp_main_loop() # define Frptp_stop_main_loop(a) rptp_stop_main_loop(a) #else typedef void FPLAY; typedef void FPLAY_ATTRS; # define FPLAY_DEFAULT_VALUE 0 # define FPLAY_DEFAULT_PRIORITY 0 # define FPLAY_NULL 0 # define FPLAY_PLAY 0 # define FPLAY_STOP 0 # define FPLAY_PAUSE 0 # define FPLAY_CONTINUE 0 # define FPLAY_SOUND 0 # define FPLAY_VOLUME 0 # define FPLAY_NSOUNDS 0 # define FPLAY_COMMAND 0 # define FPLAY_APPEND 0 # define FPLAY_INSERT 0 # define FPLAY_DELETE 0 # define FPLAY_CHANGE 0 # define FPLAY_COUNT 0 # define FPLAY_LIST_COUNT 0 # define FPLAY_PRIORITY 0 # define FPLAY_RANDOM_SOUND 0 # define FPLAY_PING 0 # define FPLAY_RPTP_SERVER 0 # define FPLAY_RPTP_SERVER_PORT 0 # define FPLAY_RPTP_SEARCH 0 # define FPLAY_RPTP_FROM_SENDER 0 # define FPLAY_SAMPLE_RATE 0 # define FPLAY_RESET 0 # define FPLAY_DONE 0 # define FPLAY_CLIENT_DATA 0 # define FPLAY_LIST_NAME 0 # define FPLAY_PUT 0 # define FPLAY_ID 0 # define FPLAY_SEQUENCE 0 # define FPLAY_DATA 0 # define FPLAY_DATA_SIZE 0 # define FPLAY_FORMAT_NONE 0 # define FPLAY_FORMAT_LINEAR_8 0 # define FPLAY_FORMAT_ULINEAR_8 0 # define FPLAY_FORMAT_LINEAR_16 0 # define FPLAY_FORMAT_ULINEAR_16 0 # define FPLAY_FORMAT_ULAW 0 # define FPLAY_FORMAT_G721 0 # define FPLAY_FORMAT_G723_3 0 # define FPLAY_FORMAT_G723_5 0 # define FPLAY_FORMAT_GSM 0 # define FPLAY_BIG_ENDIAN 0 # define FPLAY_LITTLE_ENDIAN 0 # define FPLAY_AUDIO_PORT_NONE 0 # define FPLAY_AUDIO_PORT_SPEAKER 0 # define FPLAY_AUDIO_PORT_HEADPHONE 0 # define FPLAY_AUDIO_PORT_LINEOUT 0 # define FPLAY_MIN_VOLUME 0 # define FPLAY_MAX_VOLUME 0 # define FPLAY_MIN_PRIORITY 0 # define FPLAY_MAX_PRIORITY 0 # define FPLAY_DEFAULT_VOLUME 0 # define FPLAY_DEFAULT_PRIORITY 0 # define FPLAY_DEFAULT_COUNT 0 # define FPLAY_DEFAULT_LIST_COUNT 0 # define FPLAY_DEFAULT_RANDOM_SOUND 0 # define FPLAY_DEFAULT_SAMPLE_RATE 0 # define FPLAY_DEFAULT_OFFSET 0 # define FPLAY_DEFAULT_BYTE_ORDER 0 # define FPLAY_DEFAULT_CHANNELS 0 # define FPLAY_DEFAULT_BITS 0 # define FPLAY_ERROR_NONE 0 # define FPLAY_ERROR_MEMORY 0 # define FPLAY_ERROR_HOST 0 # define FPLAY_ERROR_CONNECT 0 # define FPLAY_ERROR_SOCKET 0 # define FPLAY_ERROR_WRITE 0 # define FPLAY_ERROR_CLOSE 0 # define FPLAY_ERROR_PACKET_SIZE 0 # define FPLAY_ERROR_BROADCAST 0 # define FPLAY_ERROR_ATTRIBUTE 0 # define FPLAY_ERROR_COMMAND 0 # define FPLAY_ERROR_INDEX 0 # define FPLAY_ERROR_MODIFIER 0 # define FRPTP_ERROR_NONE 0 # define FRPTP_ERROR_MEMORY 0 # define FRPTP_ERROR_HOST 0 # define FRPTP_ERROR_CONNECT 0 # define FRPTP_ERROR_SOCKET 0 # define FRPTP_ERROR_OPEN 0 # define FRPTP_ERROR_READ 0 # define FRPTP_ERROR_WRITE 0 # define FRPTP_ERROR_PING 0 # define FRPTP_ERROR_TIMEOUT 0 # define FRPTP_ERROR_PROTOCOL 0 # define FRPTP_ERROR 0 # define FRPTP_OK 0 # define FRPTP_TIMEOUT 0 # define FRPTP_NOTIFY 0 # define FOLD_RPLAY_PLAY 0 # define FOLD_RPLAY_STOP 0 # define FOLD_RPLAY_PAUSE 0 # define FOLD_RPLAY_CONTINUE 0 # define FRPTP_ASYNC_READ 0 # define FRPTP_ASYNC_WRITE 0 # define FRPTP_ASYNC_RAW 0 # define FRPTP_ASYNC_ENABLE 0 # define FRPTP_ASYNC_DISABLE 0 # define FRPTP_EVENT_OK 0 # define FRPTP_EVENT_ERROR 0 # define FRPTP_EVENT_TIMEOUT 0 # define FRPTP_EVENT_OTHER 0 # define FRPTP_EVENT_CONTINUE 0 # define FRPTP_EVENT_DONE 0 # define FRPTP_EVENT_PAUSE 0 # define FRPTP_EVENT_PLAY 0 # define FRPTP_EVENT_SKIP 0 # define FRPTP_EVENT_STATE 0 # define FRPTP_EVENT_STOP 0 # define FRPTP_EVENT_VOLUME 0 # define FRPTP_EVENT_CLOSE 0 # define FRPTP_EVENT_FLOW 0 # define FRPTP_EVENT_MODIFY 0 # define FRPTP_EVENT_LEVEL 0 # define FRPTP_EVENT_POSITION 0 # define FRPTP_EVENT_ALL 0 # define FRPTP_MAX_ARGS 0 # define FRPTP_MAX_LINE 0 # define FPLAY_PORT 0 # define FRPTP_PORT 0 # define FOLD_RPLAY_PORT 0 # define FOLD_RPTP_PORT 0 # define FPLAY_PACKET_ID 0 # define Fplay_errno 0 # define Frptp_errno 0 # define Fplay(a,b) 0 # define Fplay_create(a) 0 # define Fplay_perror(a) /* variadict macros appeared in C99, so we can't use them. */ static void Fplay_set(FPLAY *a, ...) {} /* TA: 20100403: These aren't being used anymore. */ /* static int Fplay_get(FPLAY *a, ...) {return 0;} static int Frptp_putline(int a, ...) {return 0;} */ # define Frptp_async_putline Frptp_putline /* # define Fplay_set(...) # define Fplay_get(...) 0 # define Frptp_putline(...) 0 # define Frptp_async_putline(...) 0 */ # define Fplay_destroy(a) # define Fplay_default_host() "" # define Fplay_display(a) 0 # define Fplay_host(a,b) 0 # define Fplay_host_volume(a,b,c) 0 # define Fplay_local(a) 0 # define Fplay_open(a) -1 # define Fplay_open_default() -1 # define Fplay_open_display() -1 # define Fplay_open_port(a,b) -1 # define Fplay_open_sockaddr_in(a) -1 # define Fplay_close(a) 0 # define Fplay_ping(a) 0 # define Fplay_ping_sockaddr_in(a) 0 # define Fplay_ping_sockfd(a) 0 # define Fplay_sound(a,b) 0 # define Fplay_default(a) 0 # define Fplay_convert(a) NULL # define Fplay_pack(a) 0 # define Fplay_unpack(a) 0 # define Frptp_open(a,b,c,d) -1 # define Frptp_read(a,b,c) 0 # define Frptp_write(a,b,c) 0 # define Frptp_close(a) 0 # define Frptp_perror(a) # define Frptp_getline(a,b,c) 0 # define Frptp_command(a,b,c,d) 0 # define Frptp_parse(a,b) NULL # define Frptp_async_write(a,b,c,d) 0 # define Frptp_async_register(a,b,c) # define Frptp_async_notify(a,b,c) # define Frptp_async_process(a,b) # define Frptp_main_loop() 0 # define Frptp_stop_main_loop(a) #endif #endif fvwm-2.7.0/libs/modifiers.h0000644000175000017500000000162214147024676012517 00000000000000/* -*-c-*- */ #ifndef MODIFIERS_H #define MODIFIERS_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ #define ALL_MODIFIERS (ShiftMask|LockMask|ControlMask|Mod1Mask|Mod2Mask|\ Mod3Mask|Mod4Mask|Mod5Mask) /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- exported variables (globals) --------------- */ extern charmap_t key_modifiers[]; extern unsigned int modifier_mapindex_to_mask[]; /* ---------------------------- interface functions ------------------------ */ int modifiers_string_to_modmask(char *in_modifiers, int *out_modifier_mask); #endif /* MODIFIERS_H */ fvwm-2.7.0/libs/modifiers.c0000644000175000017500000000526714147024700012507 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include "libs/charmap.h" #include "libs/modifiers.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* The keys must be in lower case! */ charmap_t key_modifiers[] = { {'s', ShiftMask}, {'c', ControlMask}, {'l', LockMask}, {'m', Mod1Mask}, {'1', Mod1Mask}, {'2', Mod2Mask}, {'3', Mod3Mask}, {'4', Mod4Mask}, {'5', Mod5Mask}, {'a', AnyModifier}, {'n', 0}, {0, 0} }; /* Table to translate a modifier map index to a modifier that we define that * generates that index. This mapping can be chosen by each client, but the * settings below try to emulate the usual terminal behaviour. */ unsigned int modifier_mapindex_to_mask[8] = { ShiftMask, Mod3Mask, /* Alt Gr */ Mod3Mask | ShiftMask, /* Just guessing below here - LockMask is not used anywhere*/ ControlMask, Mod1Mask, /* Alt/Meta on XFree86 */ Mod2Mask, /* Num lock on XFree86 */ Mod4Mask, Mod5Mask, /* Scroll lock on XFree86 */ }; /* ---------------------------- local functions ---------------------------- */ /* ---------------------------- interface functions ------------------------ */ /* Converts the input string into a mask with bits for the modifiers */ int modifiers_string_to_modmask(char *in_modifiers, int *out_modifier_mask) { int error; error = charmap_string_to_mask( out_modifier_mask, in_modifiers, key_modifiers, "bad modifier"); return error; } fvwm-2.7.0/libs/fsm.h0000644000175000017500000000162614147024676011327 00000000000000/* -*-c-*- */ #ifndef FSM_H #define FSM_H /* ---------------------------- included header files ---------------------- */ #include "FSMlib.h" /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ typedef struct { FSmsConn smsConn; FIceConn ice_conn; char *clientId; } fsm_client_t; /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ int fsm_init(char *module); void fsm_fdset(fd_set *in_fdset); Bool fsm_process(fd_set *in_fdset); void fsm_proxy(Display *dpy, Window win, char *sm); void fsm_close(void); #endif /* FSM_H */ fvwm-2.7.0/libs/Fpng.h0000644000175000017500000003113014147024700011411 00000000000000/* -*-c-*- */ /* Copyright (C) 2002 Olivier Chapuis */ #ifndef FPNG_H #define FPNG_H /* ---------------------------- included header files ---------------------- */ #include "PictureBase.h" #if PngSupport #include #else #include #endif /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ #ifndef _ZLIB_H typedef unsigned char FzByte; typedef unsigned int FzuInt; typedef unsigned long FzuLong; typedef FzByte FzBytef; #ifdef __STDC__ typedef void *Fzvoidpf; typedef void *Fzvoidp; #else typedef FzByte *Fzvoidpf; typedef FzByte *Fzvoidp; #endif typedef Fzvoidpf (*Fzalloc_func) ( #ifdef __STDC__ Fzvoidpf opaque, FzuInt items, FzuInt size #endif ); typedef Fzvoidp (*Fzfree_func) ( #ifdef __STDC__ Fzvoidpf opaque, Fzvoidpf address #endif ); typedef struct Fz_stream_s { FzBytef *next_in; FzuInt avail_in; FzuLong total_in; FzBytef *next_out; FzuInt avail_out; FzuLong total_out; char *msg; struct internal_state *state; Fzalloc_func zalloc; Fzfree_func zfree; Fzvoidpf opaque; int data_type; FzuLong adler; FzuLong reserved; } Fz_stream; typedef Fz_stream *Fz_streamp; #else /* _ZLIB_H */ #ifdef Z_PREFIX typedef z_Byte FzByte; typedef z_uInt FzuInt; typedef z_uLong FzuLong; typedef z_Bytef FzBytef; typedef z_voidp Fzvoidp; typedef z_voidpf Fzvoidpf; typedef z_stream Fz_stream; #else typedef Byte FzByte; typedef uInt FzuInt; typedef uLong FzuLong; typedef Bytef FzBytef; typedef voidp Fzvoidp; typedef voidpf Fzvoidpf; typedef z_stream Fz_stream; #endif #endif /* !_ZLIB_H */ #if PngSupport typedef png_uint_32 Fpng_uint_32; typedef png_int_32 Fpng_int_32; typedef png_uint_16 Fpng_uint_16; typedef png_int_16 Fpng_int_16; typedef png_byte Fpng_byte; typedef png_size_t Fpng_size_t; typedef png_struct Fpng_struct; typedef png_structp Fpng_structp; typedef png_structpp Fpng_structpp; typedef png_info Fpng_info; typedef png_infop Fpng_infop; typedef png_infopp Fpng_infopp; #else typedef unsigned long Fpng_uint_32; typedef long Fpng_int_32; typedef unsigned short Fpng_uint_16; typedef short Fpng_int_16; typedef unsigned char Fpng_byte; typedef size_t Fpng_size_t; typedef void *Fpng_voidp; typedef Fpng_byte *Fpng_bytep; typedef Fpng_uint_32 *Fpng_uint_32p; typedef Fpng_int_32 *Fpng_int_32p; typedef Fpng_uint_16 *Fpng_uint_16p; typedef Fpng_int_16 *Fpng_int_16p; typedef const char *Fpng_const_charp; typedef char *Fpng_charp; typedef double *Fpng_doublep; typedef Fpng_byte **Fpng_bytepp; typedef Fpng_uint_32 **Fpng_uint_32pp; typedef Fpng_int_32 **Fpng_int_32pp; typedef Fpng_uint_16 **Fpng_uint_16pp; typedef Fpng_int_16 **Fpng_int_16pp; typedef const char **Fpng_const_charpp; typedef char **Fpng_charpp; typedef double **Fpng_doublepp; typedef char ** *Fpng_charppp; typedef struct Fpng_color_struct { Fpng_byte red; Fpng_byte green; Fpng_byte blue; } Fpng_color; typedef Fpng_color *Fpng_colorp; typedef Fpng_color **Fpng_colorpp; typedef struct Fpng_color_16_struct { Fpng_byte index; Fpng_uint_16 red; Fpng_uint_16 green; Fpng_uint_16 blue; Fpng_uint_16 gray; } Fpng_color_16; typedef Fpng_color_16 *Fpng_color_16p; typedef Fpng_color_16 **Fpng_color_16pp; typedef struct Fpng_color_8_struct { Fpng_byte red; Fpng_byte green; Fpng_byte blue; Fpng_byte gray; Fpng_byte alpha; } Fpng_color_8; typedef Fpng_color_8 *Fpng_color_8p; typedef Fpng_color_8 **Fpng_color_8pp; typedef struct Fpng_text_struct { int compression; Fpng_charp key; Fpng_charp text; Fpng_size_t text_length; } Fpng_text; typedef Fpng_text *Fpng_textp; typedef Fpng_text **Fpng_textpp; typedef struct Fpng_time_struct { Fpng_uint_16 year; Fpng_byte month; Fpng_byte day; Fpng_byte hour; Fpng_byte minute; Fpng_byte second; } Fpng_time; typedef Fpng_time *Fpng_timep; typedef Fpng_time **Fpng_timepp; typedef struct Fpng_info_struct { Fpng_uint_32 width; Fpng_uint_32 height; Fpng_uint_32 valid; Fpng_uint_32 rowbytes; Fpng_colorp palette; Fpng_uint_16 num_palette; Fpng_uint_16 num_trans; Fpng_byte bit_depth; Fpng_byte color_type; Fpng_byte compression_type; Fpng_byte filter_type; Fpng_byte interlace_type; Fpng_byte channels; Fpng_byte pixel_depth; Fpng_byte spare_byte; Fpng_byte signature[8]; float gamma; Fpng_byte srgb_intent; int num_text; int max_text; Fpng_textp text; Fpng_time mod_time; Fpng_color_8 sig_bit; Fpng_bytep trans; Fpng_color_16 trans_values; Fpng_color_16 background; Fpng_uint_32 x_offset; Fpng_uint_32 y_offset; Fpng_byte offset_unit_type; Fpng_uint_32 x_pixels_per_unit; Fpng_uint_32 y_pixels_per_unit; Fpng_byte phys_unit_type; Fpng_uint_16p hist; float x_white; float y_white; float x_red; float y_red; float x_green; float y_green; float x_blue; float y_blue; Fpng_charp pcal_purpose; Fpng_int_32 pcal_X0; Fpng_int_32 pcal_X1; Fpng_charp pcal_units; Fpng_charpp pcal_params; Fpng_byte pcal_type; Fpng_byte pcal_nparams; } Fpng_info; typedef Fpng_info *Fpng_infop; typedef Fpng_info **Fpng_infopp; typedef struct Fpng_struct_def Fpng_struct; typedef Fpng_struct *Fpng_structp; typedef struct Fpng_row_info_struct { Fpng_uint_32 width; Fpng_uint_32 rowbytes; Fpng_byte color_type; Fpng_byte bit_depth; Fpng_byte channels; Fpng_byte pixel_depth; } Fpng_row_info; typedef Fpng_row_info *Fpng_row_infop; typedef Fpng_row_info **Fpng_row_infopp; typedef void (*Fpng_error_ptr)( #ifdef __STDC__ Fpng_structp, Fpng_const_charp #endif ); typedef void (*Fpng_rw_ptr)( #ifdef __STDC__ Fpng_structp, Fpng_bytep, Fpng_size_t #endif ); typedef void (*Fpng_flush_ptr) ( #ifdef __STDC__ Fpng_structp #endif ); typedef void (*Fpng_read_status_ptr) ( #ifdef __STDC__ Fpng_structp, Fpng_uint_32, int #endif ); typedef void (*Fpng_write_status_ptr) ( #ifdef __STDC__ Fpng_structp, Fpng_uint_32, int #endif ); typedef void (*Fpng_progressive_info_ptr) ( #ifdef __STDC__ Fpng_structp, Fpng_infop #endif ); typedef void (*Fpng_progressive_end_ptr) ( #ifdef __STDC__ Fpng_structp, Fpng_infop #endif ); typedef void (*Fpng_progressive_row_ptr) ( #ifdef __STDC__ Fpng_structp, Fpng_bytep,Fpng_uint_32, int #endif ); typedef void (*Fpng_user_transform_ptr)( #ifdef __STDC__ Fpng_structp, Fpng_row_infop, Fpng_bytep #endif ); typedef Fpng_voidp (*Fpng_malloc_ptr) ( #ifdef __STDC__ Fpng_structp, Fpng_size_t #endif ); typedef void (*Fpng_free_ptr) ( #ifdef __STDC__ Fpng_structp, Fpng_voidp #endif ); struct png_struct_def { jmp_buf jmpbuf; Fpng_error_ptr error_fn; Fpng_error_ptr warning_fn; Fpng_voidp error_ptr; Fpng_rw_ptr write_data_fn; Fpng_rw_ptr read_data_fn; Fpng_voidp io_ptr; Fpng_user_transform_ptr read_user_transform_fn; Fpng_user_transform_ptr write_user_transform_fn; Fpng_voidp user_transform_ptr; Fpng_byte user_transform_depth; Fpng_byte user_transform_channels; Fpng_uint_32 mode; Fpng_uint_32 flags; Fpng_uint_32 transformations; Fz_stream zstream; Fpng_bytep zbuf; Fpng_size_t zbuf_size; int zlib_level; int zlib_method; int zlib_window_bits; int zlib_mem_level; int zlib_strategy; Fpng_uint_32 width; Fpng_uint_32 height; Fpng_uint_32 num_rows; Fpng_uint_32 usr_width; Fpng_uint_32 rowbytes; Fpng_uint_32 irowbytes; Fpng_uint_32 iwidth; Fpng_uint_32 row_number; Fpng_bytep prev_row; Fpng_bytep row_buf; Fpng_bytep sub_row; Fpng_bytep up_row; Fpng_bytep avg_row; Fpng_bytep paeth_row; Fpng_row_info row_info; Fpng_uint_32 idat_size; Fpng_uint_32 crc; Fpng_colorp palette; Fpng_uint_16 num_palette; Fpng_uint_16 num_trans; Fpng_byte chunk_name[5]; Fpng_byte compression; Fpng_byte filter; Fpng_byte interlaced; Fpng_byte pass; Fpng_byte do_filter; Fpng_byte color_type; Fpng_byte bit_depth; Fpng_byte usr_bit_depth; Fpng_byte pixel_depth; Fpng_byte channels; Fpng_byte usr_channels; Fpng_byte sig_bytes; Fpng_uint_16 filler; Fpng_byte background_gamma_type; float background_gamma; Fpng_color_16 background; Fpng_color_16 background_1; Fpng_flush_ptr output_flush_fn; Fpng_uint_32 flush_dist; Fpng_uint_32 flush_rows; int gamma_shift; float gamma; float screen_gamma; Fpng_bytep gamma_table; Fpng_bytep gamma_from_1; Fpng_bytep gamma_to_1; Fpng_uint_16pp gamma_16_table; Fpng_uint_16pp gamma_16_from_1; Fpng_uint_16pp gamma_16_to_1; Fpng_color_8 sig_bit; Fpng_color_8 shift; Fpng_bytep trans; Fpng_color_16 trans_values; Fpng_read_status_ptr read_row_fn; Fpng_write_status_ptr write_row_fn; Fpng_progressive_info_ptr info_fn; Fpng_progressive_row_ptr row_fn; Fpng_progressive_end_ptr end_fn; Fpng_bytep save_buffer_ptr; Fpng_bytep save_buffer; Fpng_bytep current_buffer_ptr; Fpng_bytep current_buffer; Fpng_uint_32 push_length; Fpng_uint_32 skip_length; Fpng_size_t save_buffer_size; Fpng_size_t save_buffer_max; Fpng_size_t buffer_size; Fpng_size_t current_buffer_size; int process_mode; int cur_palette; Fpng_size_t current_text_size; Fpng_size_t current_text_left; Fpng_charp current_text; Fpng_charp current_text_ptr; Fpng_bytepp offset_table_ptr; Fpng_bytep offset_table; Fpng_uint_16 offset_table_number; Fpng_uint_16 offset_table_count; Fpng_uint_16 offset_table_count_free; Fpng_bytep palette_lookup; Fpng_bytep dither_index; Fpng_uint_16p hist; Fpng_byte heuristic_method; Fpng_byte num_prev_filters; Fpng_bytep prev_filters; Fpng_uint_16p filter_weights; Fpng_uint_16p inv_filter_weights; Fpng_uint_16p filter_costs; Fpng_uint_16p inv_filter_costs; Fpng_charp time_buffer; Fpng_voidp mem_ptr; Fpng_malloc_ptr malloc_fn; Fpng_free_ptr free_fn; Fpng_byte rgb_to_gray_status; Fpng_byte rgb_to_gray_red_coeff; Fpng_byte rgb_to_gray_green_coeff; Fpng_byte rgb_to_gray_blue_coeff; Fpng_byte empty_plte_permitted; }; typedef Fpng_struct **Fpng_structpp; #endif /* ---------------------------- global definitions ------------------------- */ #define FPNG_BYTES_TO_CHECK 4 #if PngSupport #define FPNG_LIBPNG_VER_STRING PNG_LIBPNG_VER_STRING #define FPNG_COLOR_TYPE_PALETTE PNG_COLOR_TYPE_PALETTE #define FPNG_COLOR_TYPE_RGB_ALPHA PNG_COLOR_TYPE_RGB_ALPHA #define FPNG_COLOR_TYPE_GRAY_ALPHA PNG_COLOR_TYPE_GRAY_ALPHA #define FPNG_COLOR_TYPE_GRAY PNG_COLOR_TYPE_GRAY #define FPNG_FILLER_BEFORE PNG_FILLER_BEFORE #define FPNG_FILLER_AFTER PNG_FILLER_AFTER #define FPNG_INFO_tRNS PNG_INFO_tRNS #if PNG_LIBPNG_VER >= 10400 #define Fpng_check_sig(a,b) (!png_sig_cmp(a,0,b)) #else #define Fpng_check_sig(a,b) png_check_sig(a,b) #endif #define Fpng_create_read_struct(a,b,c,d) png_create_read_struct(a,b,c,d) #define Fpng_create_info_struct(a) png_create_info_struct(a) #define Fpng_destroy_read_struct(a,b,c) png_destroy_read_struct(a,b,c) #define Fpng_init_io(a,b) png_init_io(a,b) #define Fpng_read_info(a,b) png_read_info(a,b) #define Fpng_get_IHDR(a,b,c,d,e,f,g,h,i) png_get_IHDR(a,b,c,d,e,f,g,h,i) #define Fpng_set_expand(a) png_set_expand(a) #define Fpng_set_swap_alpha(a) png_set_swap_alpha(a) #define Fpng_set_filler(a,b,c) png_set_filler(a,b,c) #define Fpng_set_bgr(a) png_set_bgr(a) #define Fpng_set_strip_16(a) png_set_strip_16(a) #define Fpng_set_packing(a) png_set_packing(a) #define Fpng_set_gray_to_rgb(a) png_set_gray_to_rgb(a) #define Fpng_get_bit_depth(a,b) png_get_bit_depth(a,b) #if PNG_LIBPNG_VER >= 10400 #define Fpng_set_gray_1_2_4_to_8(a) png_set_expand_gray_1_2_4_to_8(a) #else #define Fpng_set_gray_1_2_4_to_8(a) png_set_gray_1_2_4_to_8(a) #endif #define Fpng_get_valid(a,b,c) png_get_valid(a,b,c) #define Fpng_read_end(a,b) png_read_end(a,b) #define Fpng_set_interlace_handling(a) png_set_interlace_handling(a) #define Fpng_read_rows(a,b,c,d) png_read_rows(a,b,c,d) #define Fpng_read_image(a,b) png_read_image(a,b) #else #define FPNG_LIBPNG_VER_STRING "" #define FPNG_COLOR_TYPE_PALETTE 0 #define FPNG_COLOR_TYPE_RGB_ALPHA 1 #define FPNG_COLOR_TYPE_GRAY_ALPHA 2 #define FPNG_COLOR_TYPE_GRAY 3 #define FPNG_FILLER_BEFORE 6 #define FPNG_FILLER_AFTER 5 #define FPNG_INFO_tRNS 7 #define Fpng_check_sig(a,b) 0 #define Fpng_create_read_struct(a,b,c,d) NULL #define Fpng_create_info_struct(a) NULL #define Fpng_destroy_read_struct(a,b,c) #define Fpng_init_io(a,b) #define Fpng_read_info(a,b) #define Fpng_get_IHDR(a,b,c,d,e,f,g,h,i) #define Fpng_set_expand(a) #define Fpng_set_swap_alpha(a) #define Fpng_set_filler(a,b,c) #define Fpng_set_bgr(a) #define Fpng_set_strip_16(a) #define Fpng_set_packing(a) #define Fpng_set_gray_to_rgb(a) #define Fpng_get_bit_depth(a,b) 0 #define Fpng_set_gray_1_2_4_to_8(a) #define Fpng_get_valid(a,b,c) 0 #define Fpng_read_end(a,b) #define Fpng_set_interlace_handling(a) 0 #define Fpng_read_rows(a,b,c,d) #define Fpng_read_image(a,b) #endif #endif /* FPNG_H */ fvwm-2.7.0/libs/System.h0000644000175000017500000000123414147024700012005 00000000000000#ifndef LIB_SYSTEM_H #define LIB_SYSTEM_H fd_set_size_t GetFdWidth(void); extern fd_set_size_t fvwmlib_max_fd; void fvwmlib_init_max_fd(void); int getostype(char *buf, int max); void setPath(char **p_path, const char *newpath, int free_old_path); char *searchPath( const char *pathlist, const char *filename, const char *suffix, int type); /* An interface for verifying cached files. */ typedef unsigned long FileStamp; FileStamp getFileStamp(const char *name); void setFileStamp(FileStamp *stamp, const char *name); Bool isFileStampChanged(const FileStamp *stamp, const char *name); /* mkstemp */ int fvwm_mkstemp (char *TEMPLATE); #endif /* LIB_SYSTEM_H */ fvwm-2.7.0/libs/PictureBase.c0000644000175000017500000001404114147024700012722 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* Changed 02/12/97 by Dan Espen: - added routines to determine color closeness, for color use reduction. Some of the logic comes from pixy2, so the copyright is below. */ /* * * Routines to handle initialization, loading, and removing of xpm's or mono- * icon images. * */ #include "config.h" #include #include #include "fvwmlib.h" #include "Graphics.h" #include "PictureBase.h" #include "PictureUtils.h" #include "Fsvg.h" #include "Strings.h" Bool Pdefault; Visual *Pvisual; static Visual *FvwmVisual; Colormap Pcmap; static Colormap FvwmCmap; unsigned int Pdepth; static unsigned int FvwmDepth; Display *Pdpy; /* Save area for display pointer */ Bool PUseDynamicColors; Pixel PWhitePixel; Pixel PBlackPixel; Pixel FvwmWhitePixel; Pixel FvwmBlackPixel; void PictureSetupWhiteAndBlack(void); void PictureInitCMap(Display *dpy) { char *envp; Pdpy = dpy; /* if fvwm has not set this env-var it is using the default visual */ envp = getenv("FVWM_VISUALID"); if (envp != NULL && *envp > 0) { /* convert the env-vars to a visual and colormap */ int viscount; XVisualInfo vizinfo, *xvi; sscanf(envp, "%lx", &vizinfo.visualid); xvi = XGetVisualInfo(dpy, VisualIDMask, &vizinfo, &viscount); Pvisual = xvi->visual; Pdepth = xvi->depth; /* Note: if FVWM_VISUALID is set, FVWM_COLORMAP is set too */ sscanf(getenv("FVWM_COLORMAP"), "%lx", &Pcmap); Pdefault = False; } else { int screen = DefaultScreen(dpy); Pvisual = DefaultVisual(dpy, screen); Pdepth = DefaultDepth(dpy, screen); Pcmap = DefaultColormap(dpy, screen); Pdefault = True; } PictureSetupWhiteAndBlack(); PictureSaveFvwmVisual(); /* initialise color limit */ PUseDynamicColors = 0; PictureInitColors(PICTURE_CALLED_BY_MODULE, True, NULL, False, True); return; } void PictureInitCMapRoot( Display *dpy, Bool init_color_limit, PictureColorLimitOption *opt, Bool use_my_color_limit, Bool init_dither) { int screen = DefaultScreen(dpy); Pdpy = dpy; Pvisual = DefaultVisual(dpy, screen); Pdepth = DefaultDepth(dpy, screen); Pcmap = DefaultColormap(dpy, screen); Pdefault = True; PictureSetupWhiteAndBlack(); PictureSaveFvwmVisual(); /* initialise color limit */ PictureInitColors( PICTURE_CALLED_BY_MODULE, init_color_limit, opt, use_my_color_limit, init_dither); return; } void PictureSetupWhiteAndBlack(void) { XColor c; if (!Pdefault) { c.flags = DoRed|DoGreen|DoBlue; c.red = c.green = c.blue = 65535; XAllocColor(Pdpy, Pcmap, &c); PWhitePixel = c.pixel; c.red = c.green = c.blue = 0; XAllocColor(Pdpy, Pcmap, &c); PBlackPixel = c.pixel; } else { PWhitePixel = WhitePixel(Pdpy, DefaultScreen(Pdpy)); PBlackPixel = BlackPixel(Pdpy, DefaultScreen(Pdpy)); } return; } void PictureUseDefaultVisual(void) { int screen = DefaultScreen(Pdpy); Pvisual = DefaultVisual(Pdpy, screen); Pdepth = DefaultDepth(Pdpy, screen); Pcmap = DefaultColormap(Pdpy, screen); PWhitePixel = WhitePixel(Pdpy, DefaultScreen(Pdpy)); PBlackPixel = BlackPixel(Pdpy, DefaultScreen(Pdpy)); return; } void PictureUseFvwmVisual(void) { Pvisual = FvwmVisual; Pdepth = FvwmDepth; Pcmap = FvwmCmap; PWhitePixel = FvwmWhitePixel; PBlackPixel = FvwmBlackPixel; return; } void PictureSaveFvwmVisual(void) { FvwmVisual = Pvisual; FvwmDepth = Pdepth; FvwmCmap = Pcmap; FvwmWhitePixel = PWhitePixel; FvwmBlackPixel = PBlackPixel; return; } Pixel PictureWhitePixel(void) { return PWhitePixel; } Pixel PictureBlackPixel(void) { return PBlackPixel; } GC PictureDefaultGC(Display *dpy, Window win) { static GC gc = None; if (Pdepth == DefaultDepth(dpy, DefaultScreen(dpy))) { return DefaultGC(dpy, DefaultScreen(dpy)); } if (gc == None) { gc = fvwmlib_XCreateGC(dpy, win, 0, NULL); } return gc; } static char* imagePath = FVWM_IMAGEPATH; void PictureSetImagePath( const char* newpath ) { static int need_to_free = 0; setPath( &imagePath, newpath, need_to_free ); need_to_free = 1; return; } char* PictureGetImagePath(void) { return imagePath; } /* * * Find the specified image file somewhere along the given path. * * There is a possible race condition here: We check the file and later * do something with it. By then, the file might not be accessible. * Oh well. * */ char* PictureFindImageFile(const char* icon, const char* pathlist, int type) { int length; char *tmpbuf; char *full_filename; const char *render_opts; if (pathlist == NULL) { pathlist = imagePath; } if (icon == NULL) { return NULL; } full_filename = searchPath(pathlist, icon, ".gz", type); /* With USE_SVG, rendering options may be appended to the original filename, hence seachPath() won't find the file. So we hide any such appended options and try once more. */ if (USE_SVG && !full_filename && (render_opts = strrchr(icon, ':'))) { length = render_opts - icon; tmpbuf = (char *)safemalloc(length + 1); strncpy(tmpbuf, icon, length); tmpbuf[length] = 0; full_filename = searchPath(pathlist, tmpbuf, ".gz", type); free(tmpbuf); if (full_filename) { /* Prepending (the previously appended) options will leave any file suffix exposed. Callers who want to access the file on disk will have to remove these prepended options themselves. The format is ":svg_opts:/path/to/file.svg". */ tmpbuf = CatString3(render_opts, ":", full_filename); free(full_filename); full_filename = safestrdup(tmpbuf); } } return full_filename; } fvwm-2.7.0/libs/fvwm_sys_stat.h0000644000175000017500000000313414147024700013432 00000000000000#ifdef HAVE_SYS_STAT_H #include #endif #ifndef S_IRWXO # define FVWM_S_IRWXO 0007 #else # define FVWM_S_IRWXO S_IRWXO #endif #ifndef S_ISUID # define FVWM_S_ISUID 0004000 #else # define FVWM_S_ISUID S_ISUID #endif #ifndef S_ISGID # define FVWM_S_ISGID 0002000 #else # define FVWM_S_ISGID S_ISGID #endif #ifndef S_ISVTX # define FVWM_S_ISVTX 0001000 #else # define FVWM_S_ISVTX S_ISVTX #endif #ifndef S_IRWXU # define FVWM_S_IRWXU 00700 #else # define FVWM_S_IRWXU S_IRWXU #endif #ifndef S_IRUSR # define FVWM_S_IRUSR 00400 #else # define FVWM_S_IRUSR S_IRUSR #endif #ifndef S_IWUSR # define FVWM_S_IWUSR 00200 #else # define FVWM_S_IWUSR S_IWUSR #endif #ifndef S_IXUSR # define FVWM_S_IXUSR 00100 #else # define FVWM_S_IXUSR S_IXUSR #endif #ifndef S_IRWXG # define FVWM_S_IRWXG 00070 #else # define FVWM_S_IRWXG S_IRWXG #endif #ifndef S_IRGRP # define FVWM_S_IRGRP 00040 #else # define FVWM_S_IRGRP S_IRGRP #endif #ifndef S_IWGRP # define FVWM_S_IWGRP 00020 #else # define FVWM_S_IWGRP S_IWGRP #endif #ifndef S_IXGRP # define FVWM_S_IXGRP 00010 #else # define FVWM_S_IXGRP S_IXGRP #endif #ifndef S_IRWXO # define FVWM_S_IRWXO 00007 #else # define FVWM_S_IRWXO S_IRWXO #endif #ifndef S_IROTH # define FVWM_S_IROTH 00004 #else # define FVWM_S_IROTH S_IROTH #endif #ifndef S_IWOTH # define FVWM_S_IWOTH 00002 #else # define FVWM_S_IWOTH S_IWOTH #endif #ifndef S_IXOTH # define FVWM_S_IXOTH 00001 #else # define FVWM_S_IXOTH S_IXOTH #endif #ifndef S_ISLNK # define FVWM_S_ISLNK(x) 0 #else # define FVWM_S_ISLNK(x) S_ISLNK(x) #endif #ifndef S_IFLNK # define FVWM_S_IFLNK 00000 #else # define FVWM_S_IFLNK S_IFLNK #endif fvwm-2.7.0/libs/Parse.c0000644000175000017500000005063214147024700011574 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ** Parse.c: routines for parsing in fvwm & modules */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include "fvwmlib.h" #include "Strings.h" #include "Parse.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ /* Copies a token beginning at src to a previously allocated area dest. dest * must be large enough to hold the token. Leading whitespace causes the token * to be NULL. */ /* NOTE: CopyToken can be called with dest == src. The token will be copied * back down over the src string. */ static char *CopyToken( char *src, char *dest, char *spaces, int snum, char *delims, int dnum, char *out_delim) { int len = 0; char *t; while (*src != 0 && !(isspace((unsigned char)*src) || (snum && strchr(spaces, *src)) || (dnum && strchr(delims, *src)))) { /* Check for quoted text */ if (IsQuote(*src)) { char c = *src; src++; while ((*src != c)&&(*src != 0)) { if ((*src == '\\' && *(src+1) != 0)) { /* Skip over backslashes */ src++; } if (len < MAX_TOKEN_LENGTH - 1) { len++; *(dest++) = *(src++); } else { /* token too long, just skip rest */ src++; } } if (*src == c) { src++; } } else { if ((*src == '\\' && *(src+1) != 0)) { /* Skip over backslashes */ src++; } if (len < MAX_TOKEN_LENGTH - 1) { len++; *(dest++) = *(src++); } else { /* token too long, just skip rest of token */ src++; } } } if (out_delim) { *out_delim = *src; } *dest = 0; t = SkipSpaces(src, spaces, snum); if (*t != 0 && dnum && strchr(delims, *t) != NULL) { if (out_delim) { *out_delim = *t; } src = t + 1; } else if (*src != 0) { src++; } return src; } /* ---------------------------- interface functions ------------------------ */ /* This function escapes all occurences of the characters in the string qchars * in the string as with a preceding echar character. The resulting string is * returned in a malloced memory area. */ char *EscapeString(char *s, const char *qchars, char echar) { char *t; char *ret; int len; for (len = 1, t = s; *t ; t++, len++) { if (strchr(qchars, *t) != NULL) { len++; } } ret = (char *)safemalloc(len); for (t = ret; *s; s++, t++) { if (strchr(qchars, *s) != NULL) { *t = echar; t++; } *t = *s; } *t = 0; return ret; } /* If the string s begins with a quote chracter SkipQuote returns a pointer * to the first unquoted character or to the final '\0'. If it does not, a * pointer to the next character in the string is returned. * There are three possible types of quoting: a backslash quotes the next * character only. Long quotes like " " or ' ' quoting everything in * between and quote pairs like ( ) or { }. * * precedence: * * 1) Backslashes are honoured always, even inside long or pair quotes. * 2) long quotes do quote quoting pair characters but not simple quotes. All * long quotes can quote all other types of long quotes). * 3) pair quotes none of the above. Text between a pair of quotes is treated * as a single token. * * qlong - string of long quoted (defaults to "'` ) * qstart - string of pair quote start characters (defaults to empty string) * qend - string of pair quote end characters (defaults to empty string) * * The defaults are used if NULL is passed for the corresponding string. */ char *SkipQuote( char *s, const char *qlong, const char *qstart, const char *qend) { char *t; if (s == NULL || *s == 0) { return s; } if (!qlong) { qlong = "\"'`"; } if (!qstart) { qstart = ""; } if (!qend) { qend = ""; } if (*s == '\\' && s[1] != 0) { return s+2; } else if (*qlong && (t = strchr(qlong, *s))) { char c = *t; s++; while (*s && *s != c) { /* Skip over escaped text, ie \quote */ if (*s == '\\' && *(s+1) != 0) { s++; } s++; } if (*s == c) { s++; } return s; } else if (*qstart && (t = strchr(qstart, *s))) { char c = *((t - qstart) + qend); while (*s && *s != c) { s = SkipQuote(s, qlong, "", ""); } return (*s == c) ? ++s : s; } return ++s; } /* Returns a string up to the first character from the string delims in a * malloc'd area just like GetNextToken. Quotes are not removed from the * returned string. The returned string is stored in *sout, the return value * of this call is a pointer to the first character after the delimiter or * to the terminating '\0'. Quoting is handled like in SkipQuote. If sin is * NULL, the function returns NULL in *sout. */ char *GetQuotedString( char *sin, char **sout, const char *delims, const char *qlong, const char *qstart, const char *qend) { char *t = sin; unsigned int len; if (!sout) { return NULL; } if (!sin) { *sout = NULL; return NULL; } while (*t && !strchr(delims, *t)) { t = SkipQuote(t, qlong, qstart, qend); } len = t - sin; *sout = (char *)safemalloc(len + 1); memcpy(*sout, sin, len); (*sout)[len] = 0; if (*t) { t++; } return t; } /* SkipSpaces: returns a pointer to the first character in indata that is * neither a whitespace character nor contained in the string 'spaces'. snum * is the number of characters in 'spaces'. You must not pass a NULL pointer * in indata. */ char *SkipSpaces(char *indata, char *spaces, int snum) { while (*indata != 0 && (isspace((unsigned char)*indata) || (snum && strchr(spaces, *indata)))) { indata++; } return indata; } /* ** DoPeekToken: returns next token from string, leaving string intact ** (you must not free returned string) ** ** WARNING: The returned pointer points to a static array that will be ** overwritten in all functions in this file! ** ** For a description of the parameters see DoGetNextToken below. DoPeekToken ** is a bit faster. */ /* NOTE: If indata is the pointer returned by a previous call to PeekToken or * DoPeekToken, the input string will be destroyed. */ char *DoPeekToken( char *indata, char **token, char *spaces, char *delims, char *out_delim) { char *end; int snum; int dnum; static char tmptok[MAX_TOKEN_LENGTH]; snum = (spaces) ? strlen(spaces) : 0; dnum = (delims) ? strlen(delims) : 0; if (indata == NULL) { if (out_delim) { *out_delim = '\0'; } *token = NULL; return NULL; } indata = SkipSpaces(indata, spaces, snum); end = CopyToken(indata, tmptok, spaces, snum, delims, dnum, out_delim); if (tmptok[0] == 0) { *token = NULL; } else { *token = tmptok; } return end; } /* * PeekToken takes the input string "indata" and returns a pointer to the * token, stored in a static char array. The pointer is invalidated by * the next call to PeekToken. If "outdata" is not NULL, the pointer * to the first character after the token is returned through * *outdata. (Note that outdata is a char **, not just a char *). */ char *PeekToken(char *indata, char **outdata) { char *dummy; char *token; if (!outdata) { outdata = &dummy; } *outdata = DoPeekToken(indata, &token, NULL, NULL, NULL); return token; } /**** SMR: Defined but not used -- is this for the future or a relic of the **** past? ****/ /* domivogt (27-Jun-1999): It's intended for future use. I have no problem * commenting it out if it's not used. */ /* Tries to seek up to n tokens in indata. Returns the number of tokens * actually found (up to a maximum of n). */ #if 0 int CheckNTokens(char *indata, unsigned int n) { unsigned int i; char *token; for (i = 0, token = (char *)1; i < n && token != NULL; i++) { token = PeekToken(indata, NULL); } return i; } #endif /* ** MatchToken: does case-insensitive compare on next token in string, leaving ** string intact (returns true if matches, false otherwise) */ int MatchToken(char *pstr,char *tok) { int rc=0; char *ntok; DoPeekToken(pstr, &ntok, NULL, NULL, NULL); if (ntok) { rc = (strcasecmp(tok,ntok)==0); } return rc; } /* unused at the moment */ /* function: XCmpToken description: compare 1st word of s to 1st word of t returns: < 0 if s < t = 0 if s = t > 0 if s > t */ int XCmpToken(const char *s, const char **t) { register const char *w=*t; if (w==NULL) { return 1; } if (s==NULL) { return -1; } while (*w && (*s==*w || toupper(*s)==toupper(*w)) ) { s++; w++; } if ((*s=='\0' && (ispunct(*w) || isspace(*w)))|| (*w=='\0' && (ispunct(*s) || isspace(*s))) ) { return 0; /* 1st word equal */ } else { return toupper(*s)-toupper(*w); /* smaller/greater */ } } /* * * Gets the next "word" of input from string indata. * "word" is a string with no spaces, or a qouted string. * Return value is ptr to indata,updated to point to text after the word * which is extracted. * token is the extracted word, which is copied into a malloced * space, and must be freed after use. DoGetNextToken *never* returns an * empty string or token. If the token consists only of whitespace or * delimiters, the returned token is NULL instead. If out_delim is given, * the character ending the string is returned therein. * * spaces = string of characters to treat as spaces * delims = string of characters delimiting token * * Use "spaces" and "delims" to define additional space/delimiter * characters (spaces are skipped before a token, delimiters are not). * */ char *DoGetNextToken( char *indata, char **token, char *spaces, char *delims, char *out_delim) { char *tmptok; char *end; end = DoPeekToken(indata, &tmptok, spaces, delims, out_delim); if (tmptok == NULL) { *token = NULL; } else { *token = safestrdup(tmptok); } return end; } /* * GetNextToken works similarly to PeekToken, but: stores the token in * *token, & returns a pointer to the first character after the token * in *token. The memory in *token is allocated with malloc and the * calling function has to free() it. * * If possible, use PeekToken because it's faster and does not risk * creating memory leaks. */ char *GetNextToken(char *indata, char **token) { return DoGetNextToken(indata, token, NULL, NULL, NULL); } /* fetch next token and stop at next ',' */ char *GetNextSimpleOption(char *indata, char **option) { return DoGetNextToken(indata, option, NULL, ",", NULL); } /* read multiple tokens up to next ',' or end of line */ char *GetNextFullOption(char *indata, char **option) { return GetQuotedString(indata, option, ",\n", NULL, NULL, NULL); } char *SkipNTokens(char *indata, unsigned int n) { for ( ; n > 0 && indata != NULL && *indata != 0; n--) { PeekToken(indata, &indata); } return indata; } /* * convenience functions */ /* * * Works like GetNextToken, but with the following differences: * * If *indata begins with a "*" followed by the string module_name, * it returns the string following directly after module_name as the * new token. Otherwise NULL is returned. * e.g. GetModuleResource("*FvwmPagerGeometry", &token, "FvwmPager") * returns "Geometry" in token. * */ char *GetModuleResource(char *indata, char **resource, char *module_name) { char *tmp; char *next; if (!module_name) { *resource = NULL; return indata; } tmp = PeekToken(indata, &next); if (!tmp) { return next; } if (tmp[0] != '*' || strncasecmp(tmp+1, module_name, strlen(module_name))) { *resource = NULL; return indata; } CopyString(resource, tmp+1+strlen(module_name)); return next; } /* * * This function uses GetNextToken to parse action for up to num integer * arguments. The number of values actually found is returned. * If ret_action is non-NULL, a pointer to the next token is returned there. * The suffixlist parameter points to a string of possible suffixes for the * integer values. The index of the matched suffix is returned in * ret_suffixnum (0 = no suffix, 1 = first suffix in suffixlist ...). * */ static int _get_suffixed_integer_arguments( char *action, char **ret_action, int *retvals, int num, char *suffixlist, int *ret_suffixnum, char *parsestring) { int i; int j; int n; char *token; int suffixes; /* initialize */ suffixes = 0; if (suffixlist != 0) { /* if passed a suffixlist save its length */ suffixes = strlen(suffixlist); } for (i = 0; i < num && action; i++) { token = PeekToken(action, &action); if (token == NULL) { break; } if (sscanf(token, parsestring, &(retvals[i]), &n) < 1) { break; } if (suffixes != 0 && ret_suffixnum != NULL) { int len; char c; len = strlen(token) - 1; c = token[len]; if (isupper(c)) { c = tolower(c); } for (j = 0; j < suffixes; j++) { char c2 = suffixlist[j]; if (isupper(c2)) { c2 = tolower(c2); } if (c == c2) { ret_suffixnum[i] = j+1; break; } } if (j == suffixes) { ret_suffixnum[i] = 0; } } else if (token[n] != 0 && !isspace(token[n])) { /* there is a suffix but no suffix list was specified */ break; } } if (ret_action != NULL) { *ret_action = action; } return i; } int GetSuffixedIntegerArguments( char *action, char **ret_action, int *retvals, int num, char *suffixlist, int *ret_suffixnum) { return _get_suffixed_integer_arguments( action, ret_action, retvals, num, suffixlist, ret_suffixnum, "%d%n"); } /* * * This function converts the suffix/number pairs returned by * GetSuffixedIntegerArguments into pixels. The unit_table is an array of * integers that determine the factor to multiply with in hundredths of * pixels. I.e. a unit of 100 means: translate the value into pixels, * 50 means divide value by 2 to get the number of pixels and so on. * The unit used is determined by the suffix which is taken as the index * into the table. No size checking of the unit_table is done, so make sure * it is big enough before calling this function. * */ int SuffixToPercentValue(int value, int suffix, int *unit_table) { return (value * unit_table[suffix]) / 100; } /* * * This function uses GetNextToken to parse action for up to num integer * arguments. The number of values actually found is returned. * If ret_action is non-NULL, a pointer to the next token is returned there. * */ int GetIntegerArguments(char *action, char **ret_action, int *retvals,int num) { return _get_suffixed_integer_arguments( action, ret_action, retvals, num, NULL, NULL, "%d%n"); } /* * * Same as above, but supports hexadecimal and octal integers via 0x and 0 * prefixes. * */ int GetIntegerArgumentsAnyBase( char *action, char **ret_action, int *retvals,int num) { return _get_suffixed_integer_arguments( action, ret_action, retvals, num, NULL, NULL, "%i%n"); } /* * * This function tries to match a token with a list of strings and returns * the position of token in the array or -1 if no match is found. The last * entry in the list must be NULL. * * len = 0 : only exact matches * len < 0 : match, if token begins with one of the strings in list * len > 0 : match, if the first len characters do match * * if next is non-NULL, *next will be set to point to the first character * in token after the match. * */ int GetTokenIndex(char *token, char **list, int len, char **next) { int i; int l; int k; if (!token || !list) { if (next) { *next = NULL; } return -1; } l = (len) ? len : strlen(token); for (i = 0; list[i] != NULL; i++) { k = strlen(list[i]); if (len < 0) { l = k; } else if (len == 0 && k != l) { continue; } if (!strncasecmp(token, list[i], l)) { break; } } if (next) { *next = (list[i]) ? token + l : token; } return (list[i]) ? i : -1; } /* * * This function does roughly the same as GetTokenIndex but reads the * token from string action with GetNextToken. The index is returned * in *index. The return value is a pointer to the character after the * token (just like the return value of GetNextToken). * */ char *GetNextTokenIndex(char *action, char **list, int len, int *index) { char *token; char *next; if (!index) { return action; } token = PeekToken(action, &next); if (!token) { *index = -1; return action; } *index = GetTokenIndex(token, list, len, NULL); return (*index == -1) ? action : next; } /* * * Parses two integer arguments given in the form . * character can be ' ' or 'x', but any other character is allowed too * (except 'p' or 'P'). * */ int GetRectangleArguments(char *action, int *width, int *height) { char *token; int n; token = PeekToken(action, NULL); if (!token) { return 0; } n = sscanf(token, "%d%*c%d", width, height); return (n == 2) ? 2 : 0; } /* unit_io is input as well as output. If action has a postfix 'p' or 'P', * *unit_io is set to 100, otherwise it is left untouched. */ int GetOnePercentArgument(char *action, int *value, int *unit_io) { unsigned int len; char *token; int n; *value = 0; if (!action) { return 0; } token = PeekToken(action, NULL); if (!token) { return 0; } len = strlen(token); /* token never contains an empty string, so this is ok */ if (token[len - 1] == 'p' || token[len - 1] == 'P') { *unit_io = 100; token[len - 1] = '\0'; } n = sscanf(token, "%d", value); return n; } int GetTwoPercentArguments( char *action, int *val1, int *val2, int *val1_unit, int *val2_unit) { char *tok1; char *tok2; char *next; int n = 0; *val1 = 0; *val2 = 0; tok1 = PeekToken(action, &next); action = GetNextToken(action, &tok1); if (!tok1) { return 0; } GetNextToken(action, &tok2); if (GetOnePercentArgument(tok2, val2, val2_unit) == 1 && GetOnePercentArgument(tok1, val1, val1_unit) == 1) { free(tok1); free(tok2); return 2; } /* now try MxN style number, specifically for DeskTopSize: */ n = GetRectangleArguments(tok1, val1, val2); free(tok1); if (tok2) { free(tok2); } return n; } /* Parses the next token in action and returns 1 if it is "yes", "true", "y", * "t" or "on", zero if it is "no", "false", "n", "f" or "off" and -1 if it is * "toggle". A pointer to the first character in action behind the token is * returned through ret_action in this case. ret_action may be NULL. If the * token matches none of these strings the default_ret value is returned and * the action itself is passed back in ret_action. If the no_toggle flag is * non-zero, the "toggle" string is handled as no match. */ int ParseToggleArgument( char *action, char **ret_action, int default_ret, char no_toggle) { int index; int rc; char *next; char *optlist[] = { "toggle", "yes", "no", "true", "false", "on", "off", "t", "f", "y", "n", NULL }; next = GetNextTokenIndex(action, optlist, 0, &index); if (index == 0 && no_toggle == 0) { /* toggle requested explicitly */ rc = -1; } else if (index == -1 || (index == 0 && no_toggle)) { /* nothing selected, use default and don't modify action */ rc = default_ret; next = action; } else { /* odd numbers denote True, even numbers denote False */ rc = (index & 1); } if (ret_action) { *ret_action = next; } return rc; } /* Strips the path from 'path' and returns the last component in a malloc'ed * area. */ char *GetFileNameFromPath(char *path) { char *s; char *name; /* we get rid of the path from program name */ s = strrchr(path, '/'); if (s) { s++; } else { s = path; } name = (char *)safemalloc(strlen(s)+1); strcpy(name, s); return name; } fvwm-2.7.0/libs/defaults.h0000644000175000017500000004043114324314575012343 00000000000000/* -*-c-*- */ /* File: defaults.h * * Description: * #defines for default values shall go into this file as well as tunable * parameters. */ #ifndef _DEFAULTS_ #define _DEFAULTS_ /*** event handling ***/ #define CLOCK_SKEW_MS 30000 /* ms */ /*** grabbing the pointer ***/ #define NUMBER_OF_GRAB_ATTEMPTS 100 #define TIME_BETWEEN_GRAB_ATTEMPTS 10 /* ms */ /*** bindings and mouse buttons ***/ /* Fvwm needs at least 3 buttons. X currently supports up to 5 buttons, so you * can use 3, 4 or 5 here. Do not set this to values higher than 5! Use the * next macro for that. */ #define NUMBER_OF_MOUSE_BUTTONS 5 /* The "extended" buttons do not provide the full functionality because X has * no bit mask value for them. Things like dragging windows don't work with * them. */ #define NUMBER_OF_EXTENDED_MOUSE_BUTTONS 15 #if NUMBER_OF_EXTENDED_MOUSE_BUTTONS > 31 #error No more than 31 mouse buttons can be supported on 32 bit platforms #endif #define DEFAULT_ALL_BUTTONS_MASK \ ((Button1Mask * ((1 << NUMBER_OF_MOUSE_BUTTONS) - 1))) #define DEFAULT_ALL_BUTTONS_MOTION_MASK \ ((Button1MotionMask * ((1 << NUMBER_OF_MOUSE_BUTTONS) - 1))) #define DEFAULT_MODS_UNUSED LockMask /* * These values may be adjusted to fine tune the menu looks. */ /* The first option of the default menu style must be fvwm/win/mwm/.... * fvwm may crash if not. */ #define DEFAULT_MENU_STYLE \ "MenuStyle * fvwm, Foreground black, Background grey, " \ "Greyed slategrey, MenuColorset, ActiveColorset, GreyedColorset" #define DEFAULT_CLICKTIME 150 /* ms */ #define DEFAULT_POPUP_DELAY 15 /* ms*10 */ #define DEFAULT_POPDOWN_DELAY 15 /* ms*10 */ #define DEFAULT_MENU_CLICKTIME (3*DEFAULT_CLICKTIME) #define DEFAULT_MOVE_THRESHOLD 3 /* pixels */ #define MAX_MENU_COPIES 10 /* menu copies */ #define MAX_MENU_ITEM_LABELS 3 /* labels (max. 15) */ #define MAX_MENU_ITEM_MINI_ICONS 2 /* mini icons (max. 15) */ #define DEFAULT_MENU_BORDER_WIDTH 2 /* pixels */ #define MAX_MENU_BORDER_WIDTH 50 /* pixels */ #define MAX_MENU_ITEM_RELIEF_THICKNESS 50 /* pixels */ #define PARENT_MENU_FORCE_VISIBLE_WIDTH 20 /* pixels */ #define DEFAULT_MENU_POPUP_NOW_RATIO 75 /* % of item width */ /* default item formats for left and right submenus. */ #define DEFAULT_MENU_ITEM_FORMAT "%s%.1|%.5i%.5l%.5l%.5r%.5i%2.3>%1|" #define DEFAULT_LEFT_MENU_ITEM_FORMAT "%.1|%3.2<%5i%5l%5l%5r%5i%1|%s" /* size of the submenu triangle. */ #define MENU_TRIANGLE_WIDTH 5 /* pixels */ #define MENU_TRIANGLE_HEIGHT 9 /* pixels */ /* menu underline parameters */ #define MENU_UNDERLINE_THICKNESS 1 /* pixels */ #define MENU_UNDERLINE_GAP 1 /* pixels */ #define MENU_UNDERLINE_HEIGHT (MENU_UNDERLINE_THICKNESS + MENU_UNDERLINE_GAP) /* menu separator parameters */ #define MENU_SEPARATOR_SHORT_X_OFFSET 5 /* pixels */ #define MENU_SEPARATOR_Y_OFFSET 2 /* pixels */ #define MENU_SEPARATOR_HEIGHT 2 /* pixels */ #define MENU_SEPARATOR_TOTAL_HEIGHT \ (MENU_SEPARATOR_HEIGHT + MENU_SEPARATOR_Y_OFFSET) /* menu tear off bar parameters */ #define MENU_TEAR_OFF_BAR_X_OFFSET 1 /* pixels */ #define MENU_TEAR_OFF_BAR_Y_OFFSET 1 /* pixels */ #define MENU_TEAR_OFF_BAR_HEIGHT 4 /* pixels */ #define MENU_TEAR_OFF_BAR_DASH_WIDTH 5 /* pixels */ /* gap above item text */ #define DEFAULT_MENU_ITEM_TEXT_Y_OFFSET 1 /* pixels */ /* gap below item text */ #define DEFAULT_MENU_ITEM_TEXT_Y_OFFSET2 2 /* pixels */ /* same for titles */ #define DEFAULT_MENU_TITLE_TEXT_Y_OFFSET (DEFAULT_MENU_ITEM_TEXT_Y_OFFSET) #define DEFAULT_MENU_TITLE_TEXT_Y_OFFSET2 (DEFAULT_MENU_ITEM_TEXT_Y_OFFSET2) /* minimum for above value */ #define MIN_VERTICAL_SPACING -100 /* pixels */ /* maximum for above value */ #define MAX_VERTICAL_SPACING 100 /* pixels */ /* maximum for above value */ #define MAX_MENU_MARGIN 50 /* pixels */ /* width of a tab in the item format of a menu */ #define MENU_TAB_WIDTH 8 /* spaces */ /* This is the tile width or height for V and H gradients. I guess this should * better be a power of two. A value of 5 definitely causes XFree 3.3.3.1 to * screw up the V_GRADIENT on an 8 bit display, but 4, 6, 7 etc. work well. */ #define DEFAULT_MENU_GRADIENT_PIXMAP_THICKNESS 4 /*** colours ***/ #define DEFAULT_FORE_COLOR "black" #define DEFAULT_BACK_COLOR "gray" #define DEFAULT_HILIGHT_COLOR "white" #define DEFAULT_SHADOW_COLOR "black" #define DEFAULT_CURSOR_FORE_COLOR "black" #define DEFAULT_CURSOR_BACK_COLOR "white" /*** pager ***/ #define DEFAULT_MOVE_THRESHOLD 3 /* pixels */ #define DEFAULT_PAGER_WINDOW_BORDER_WIDTH 1 /* pixels */ /*** fonts ***/ #define EXTRA_TITLE_FONT_HEIGHT 3 /* pixels */ #define EXTRA_TITLE_FONT_WIDTH 3 /* pixels */ #define MIN_FONT_HEIGHT (EXTRA_TITLE_FONT_HEIGHT + 2) #define MAX_FONT_HEIGHT 256 /* pixels */ /*** Flocale ***/ /* adding the good number of "*" speed-up font loading with certain X * server */ #define FLOCALE_MB_FALLBACK_FONT \ "-*-fixed-medium-r-semicondensed-*-13-*-*-*-*-*-*-*," \ "-*-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*," \ "-*-*-medium-r-normal-*-16-*-*-*-*-*-*-*" /* rationale: -*-fixed-medium-r-semicondensed-*-13-* should gives "fixed" in most non multibyte charset (?). -*-fixed-medium-r-normal-*-14-* is ok for jsx -*-medium-r-normal-*-16-* is for gb Of course this is for XFree. Any help for other X server basic font set is welcome. */ #define FLOCALE_FALLBACK_FONT "fixed" #define FLOCALE_FFT_FALLBACK_FONT "MonoSpace" #define FLOCALE_NUMBER_MISS_CSET_ERR_MSG 5 /*** window geometry ***/ #define DEFAULT_MIN_MAX_WINDOW_WIDTH 100 /* pixels */ #define DEFAULT_MIN_MAX_WINDOW_HEIGHT 100 /* pixels */ #define DEFAULT_MAX_MAX_WINDOW_WIDTH 32767 /* pixels */ #define DEFAULT_MAX_MAX_WINDOW_HEIGHT 32767 /* pixels */ /*** icon geometry ***/ #define UNSPECIFIED_ICON_DIMENSION -1 #define MIN_ALLOWABLE_ICON_DIMENSION 0 /* pixels */ #define MAX_ALLOWABLE_ICON_DIMENSION 255 /* pixels */ /* this value is used in a bugfix */ #define WINDOW_FREAKED_OUT_SIZE 65500 /* pixels */ /* Used in Workaround for broken min and max size hints vs a size request */ #define BROKEN_MAXSIZE_LIMIT 1 #define BROKEN_MINSIZE_LIMIT 30000 /* geometry window */ #define GEOMETRY_WINDOW_BW 2 /* pixels */ #define GEOMETRY_WINDOW_STRING " +8888 x +8888 " #define GEOMETRY_WINDOW_POS_STRING " %+-4d %+-4d " #define GEOMETRY_WINDOW_SIZE_STRING " %4d x %-4d " /* * window title layout */ /* the title buttons are shrunk if the title would become smaller than this * number of pixels */ #define MIN_WINDOW_TITLE_LENGTH 10 /* pixels */ /* title bar buttons that get smaller than this size are hidden */ #define MIN_WINDOW_TITLEBUTTON_LENGTH 2 /* pixels */ /* height of stick lines */ #define WINDOW_TITLE_STICK_HEIGHT 1 /* pixels */ /* vertical distance between stick lines */ #define WINDOW_TITLE_STICK_VERT_DIST 4 /* pixels */ /* minimum width of stick lines */ #define WINDOW_TITLE_STICK_MIN_WIDTH 1 /* pixels */ /* gap between border of title window and stick lines */ #define WINDOW_TITLE_STICK_OFFSET 4 /* pixels */ /* gap between title and stick lines */ #define WINDOW_TITLE_TO_STICK_GAP 4 /* pixels */ /* gap between border of title window and text */ #define WINDOW_TITLE_TEXT_OFFSET 10 /* pixels */ /* minimal gap between border of title window and text */ #define MIN_WINDOW_TITLE_TEXT_OFFSET 2 /* pixels */ /* left and right padding for the text into under text area (MultiPixmap)*/ #define TBMP_TITLE_PADDING 5 /* minimal left and right area vs left/right of text/end (MultiPixmap) */ #define TBMP_MIN_RL_TITLE_LENGTH 7 /* maximum number of segemnts in a vector button */ #define MAX_TITLE_BUTTON_VECTOR_LINES 10000 /*** window placement ***/ /** MinOverlap(Percent)Placement **/ /** Now these values are configurable by using styles **/ /* The following factors represent the amount of area that these types of * windows are counted as. For example, by default the area of ONTOP windows * is counted 5 times as much as normal windows. So CleverPlacement will * cover 5 times as much area of another window before it will cover an ONTOP * window. To treat ONTOP windows the same as other windows, set this to 1. * To really, really avoid putting windows under ONTOP windows, set this to a * high value, say 1000. A value of 5 will try to avoid ONTOP windows if * practical, but if it saves a reasonable amount of area elsewhere, it will * place one there. The same rules apply for the other "AVOID" factors. */ /* With the advent of layers, the meaning of ONTOP in the following explanation has changed to mean any window in a higher layer. */ #define PLACEMENT_AVOID_BELOW 0.05 #define PLACEMENT_AVOID_STICKY 1.0 #define PLACEMENT_AVOID_ONTOP 5 #define PLACEMENT_AVOID_ICON 10 #define PLACEMENT_AVOID_EWMH_STRUT 50 /* used in MinOverlap*Placement to forbid complete covering (99%, 95% 85% and 75%) of windows */ #define PLACEMENT_AVOID_COVER_99 12 #define PLACEMENT_AVOID_COVER_95 6 #define PLACEMENT_AVOID_COVER_85 4 #define PLACEMENT_AVOID_COVER_75 1 #define PLACEMENT_FALLBACK_CASCADE_STEP 20 /** Other placement related values **/ /* default string for position placement */ #define DEFAULT_PLACEMENT_POSITION_STRING "0 0" #define DEFAULT_PLACEMENT_POS_CENTER_STRING "50-50w 50-50w" #define DEFAULT_PLACEMENT_POS_MOUSE_STRING "m-50w m-50w" /*** icon layout ***/ /* width of the relief around the icon and icon title */ #define ICON_RELIEF_WIDTH 2 /* pixels */ /* height of stick lines */ #define ICON_TITLE_STICK_HEIGHT WINDOW_TITLE_STICK_HEIGHT /* vertical distance between stick lines */ #define ICON_TITLE_STICK_VERT_DIST WINDOW_TITLE_STICK_VERT_DIST /* vertical offset for icon title */ #define ICON_TITLE_VERT_TEXT_OFFSET -3 /* pixels */ /* minimum width of stick lines */ #define ICON_TITLE_STICK_MIN_WIDTH 3 /* pixels */ /* number of blank pixels before and after a collapsed title */ #define ICON_TITLE_TEXT_GAP_COLLAPSED 1 /* pixels */ /* number of blank pixels before and after an expanded title */ #define ICON_TITLE_TEXT_GAP_EXPANDED 4 /* pixels */ /* extra blank pixels if the icon is sticky */ #define ICON_TITLE_TO_STICK_EXTRA_GAP 1 /* pixels */ /* minimum distance of icons in icon box */ #define MIN_ICON_BOX_DIST 3 /* pixels */ /* padding for the icon into its background */ #define ICON_BACKGROUND_PADDING 0 /* pixels */ /*** general keyboard shortcuts used in move, resize, ... ***/ #define DEFAULT_KDB_SHORTCUT_MOVE_DISTANCE 5 /* pixels */ #define KDB_SHORTCUT_MOVE_DISTANCE_SMALL 1 /* pixels */ #define KDB_SHORTCUT_MOVE_DISTANCE_BIG 100 /* pixels */ /*** movement ***/ #define DEFAULT_OPAQUE_MOVE_SIZE 5 /* percent of window area */ #define DEFAULT_SNAP_ATTRACTION 0 /* snap nothing */ #define DEFAULT_SNAP_ATTRACTION_MODE 0x3 /* snap all */ #define DEFAULT_SNAP_GRID_X 1 /* pixels */ #define DEFAULT_SNAP_GRID_Y 1 /* pixels */ /*** paging ***/ #define DEFAULT_EDGE_SCROLL 100 /* % of screen width/height */ /* Don't page if the pointer has moved for more than this many pixels between * two samples */ #define MAX_PAGING_MOVE_DISTANCE 5 /* pixels */ #define DEFAULT_MOVE_DELAY 0 /* ms */ #define DEFAULT_RESIZE_DELAY -1 /* pixels */ #define DEFAULT_SCROLL_DELAY 0 /* ms */ /*** layers ***/ #define DEFAULT_BOTTOM_LAYER 2 #define DEFAULT_DEFAULT_LAYER 4 #define DEFAULT_TOP_LAYER 6 #define DEFAULT_ROOT_WINDOW_LAYER -1 /*** decorations ***/ /* The number of left and right buttons must be equal. A maximum of 32 buttons * can be handled (16 left and 16 right). */ #define NR_LEFT_BUTTONS 5 #define NR_RIGHT_BUTTONS NR_LEFT_BUTTONS #define NUMBER_OF_TITLE_BUTTONS (NR_LEFT_BUTTONS + NR_RIGHT_BUTTONS) /*** window borders ***/ #define DEFAULT_BORDER_WIDTH 1 /* pixels */ #define DEFAULT_HANDLE_WIDTH 7 /* pixels */ #define MAX_BORDER_WIDTH 500 /* pixels */ #define MAX_HANDLE_WIDTH (MAX_BORDER_WIDTH) /*** module configuration ***/ #define MAX_MODULE_ALIAS_LEN 250 /* bytes */ #define DEFAULT_MODULE_TIMEOUT 30 /* seconds */ #define MAX_MODULE_INPUT_TEXT_LEN 1000 /* bytes */ /*** FvwmConsole configuration */ /* Maximum time FvwmConsole waits for the client to connect. */ #define FVWMCONSOLE_CONNECTION_TO_SECS 60 /* seconds */ /*** misc ***/ #define DEFAULT_EMULATE_MWM False #define DEFAULT_EMULATE_WIN False #define DEFAULT_USE_ACTIVE_DOWN_BUTTONS True #define DEFAULT_USE_INACTIVE_BUTTONS True #define DEFAULT_USE_INACTIVE_DOWN_BUTTONS True /*** Gradients ***/ #define MAX_GRADIENT_SEGMENTS 1000 #define MAX_GRADIENT_COLORS 10000 /*** Xinerama ***/ #define DEFAULT_XINERAMA_ENABLED True /* Xinerama on by default */ #define XINERAMA_CONFIG_STRING "XineramaConfig" /* Replace with -1 to switch off "primary screen" concept by default */ #define DEFAULT_PRIMARY_SCREEN 0 /*** Very long window names (600000 characters or more) seem to hang the X *** server. ***/ #define MAX_WINDOW_NAME_LEN 200 /* characters */ #define MAX_ICON_NAME_LEN 200 /* characters */ /* not tested if this hangs the server too */ #define MAX_RESOURCE_LEN 200 /* characters */ #define MAX_CLASS_LEN 200 /* characters */ /* The default title and icon title in case the user doesn't supply one. */ #define DEFAULT_TITLE_FORMAT "%n" #define DEFAULT_ICON_TITLE_FORMAT "%i" /* Set the maximum size a visible name can be. */ #define MAX_VISIBLE_NAME_LEN 4096 /*** numbered window names ***/ #define MAX_WINDOW_NAME_NUMBER 999 #define MAX_WINDOW_NAME_NUMBER_DIGITS 3 /* number/digits of above number */ /* focus policy style defaults */ #define DEF_FP_FOCUS_ENTER 1 #define DEF_FP_UNFOCUS_LEAVE 1 #define DEF_FP_FOCUS_CLICK_CLIENT 0 #define DEF_FP_FOCUS_CLICK_DECOR 0 #define DEF_FP_FOCUS_BY_PROGRAM 1 #define DEF_FP_FOCUS_BY_FUNCTION 1 #define DEF_FP_WARP_POINTER_ON_FOCUS_FUNC 0 #define DEF_FP_LENIENT 0 #define DEF_FP_RAISE_FOCUSED_CLIENT_CLICK 0 #define DEF_FP_RAISE_UNFOCUSED_CLIENT_CLICK 1 #define DEF_FP_RAISE_FOCUSED_DECOR_CLICK 0 #define DEF_FP_RAISE_UNFOCUSED_DECOR_CLICK 0 #define DEF_FP_RAISE_FOCUSED_ICON_CLICK 0 #define DEF_FP_RAISE_UNFOCUSED_ICON_CLICK 0 /* use first three buttons by default */ #define DEF_FP_MOUSE_BUTTONS ( \ ((1 << 0) | (1 << 1) | (1 << 2)) & \ ((1 << NUMBER_OF_MOUSE_BUTTONS) - 1)) #define DEF_FP_MODIFIERS 0 #define DEF_FP_PASS_FOCUS_CLICK 1 #define DEF_FP_PASS_RAISE_CLICK 1 #define DEF_FP_IGNORE_FOCUS_CLICK_MOTION 0 #define DEF_FP_IGNORE_RAISE_CLICK_MOTION 0 #define DEF_FP_ALLOW_FUNC_FOCUS_CLICK 1 #define DEF_FP_ALLOW_FUNC_RAISE_CLICK 1 #define DEF_FP_GRAB_FOCUS 0 #define DEF_FP_GRAB_FOCUS_TRANSIENT 1 #define DEF_FP_OVERRIDE_GRAB_FOCUS 0 #define DEF_FP_RELEASE_FOCUS 0 #define DEF_FP_RELEASE_FOCUS_TRANSIENT 1 #define DEF_FP_OVERRIDE_RELEASE_FOCUS 0 #define DEF_FP_SORT_WINDOWLIST_BY 0 /* Function execution */ #define MAX_FUNCTION_DEPTH 512 /* Tips */ #define FTIPS_DEFAULT_PLACEMENT FTIPS_PLACEMENT_AUTO_UPDOWN #define FTIPS_DEFAULT_JUSTIFICATION FTIPS_JUSTIFICATION_LEFT_UP #define FTIPS_DEFAULT_PLACEMENT_OFFSET 3 #define FTIPS_DEFAULT_JUSTIFICATION_OFFSET 2 #define FTIPS_DEFAULT_BORDER_WIDTH 1 #endif /* _DEFAULTS_ */ fvwm-2.7.0/libs/FScreen.c0000644000175000017500000010504714147024700012050 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* * FScreen.c * Xinerama abstraction support for window manager. * * This module is all original code * by Dmitry Yu. Bolkhovityanov * Copyright 2001, Dmitry Bolkhovityanov * You may use this code for any purpose, as long as the original * copyright remains in the source code and all documentation */ /* * Brief description of used concept: * * This code is always used by client, regardless of if Xinerama is * available or not (either because -lXinerama was missing or * because Xinerama extension is missing on display). * * If Xinerama is available, this module maintains a list of screens, * from [1] to [num_screens]. screens[0] is always the "global" screen, * so if Xinerama is unavailable or disabled, the module performs * all checks on screens[0] instead of screens[1..num_screens]. * * The client should first call the FScreenInit(), passing * it the opened display descriptor. During this call the list of * Xinerama screens is retrieved and 'dpy' is saved for future * reference. * * If the client wishes to hard-disable Xinerama support (e.g. if * Xinerama extension is present but is broken on display), it should * call FScreenDisable() *before* FScreenInit(). * * Using real Xinerama screens info may be switched on/off "on the * fly" by calling FScreenSetState(0=off/else=on). * * Modules with Xinerama support should listen to the XineramaEnable * and XineramaDisable strings coming over the module pipe as * M_CONFIG_INFO packets and call FScreenEnable() or * FScreenDisable in response. * */ #include "config.h" #include #include #include "defaults.h" #include "fvwmlib.h" #include "Parse.h" #include "FScreen.h" #include "PictureBase.h" #ifdef HAVE_XINERAMA # undef FSCREEN_NEED_SCREENINFO # define FScreenHaveXinerama 1 # ifdef HAVE_SOLARIS_XINERAMA # define FScreenHaveSolarisXinerama 1 # ifdef HAVE_SOLARIS_XINERAMA_H # include # else # define FSCREEN_NEED_SOLARIS_PROTOTYPES # endif # define FSCREEN_NEED_SCREENINFO # else # define FScreenHaveSolarisXinerama 0 # include # endif #else # define FSCREEN_NEED_SCREENINFO # define FScreenHaveXinerama 0 # define FScreenHaveSolarisXinerama 0 #endif #ifdef FSCREEN_NEED_SCREENINFO typedef struct { int screen_number; short x_org; short y_org; unsigned short width; unsigned short height; } XineramaScreenInfo; #endif #ifdef FSCREEN_NEED_SOLARIS_PROTOTYPES /* Copied from Solaris 9's X11/extensions/xinerama.h */ Bool XineramaGetState(Display*, int); Status XineramaGetInfo(Display*, int, XRectangle*, unsigned char*, int*); Status XineramaGetCenterHint(Display*, int, int*, int*); #endif #if FScreenHaveSolarisXinerama == 0 #define XineramaGetInfo(a,b,c,d,e) 0 #endif #if FScreenHaveXinerama # if FScreenHaveSolarisXinerama # define XineramaQueryExtension(d,b,c) 1 /* Lie, for now */ # define XineramaIsActive(d) XineramaGetState((d),0) # define XineramaQueryScreens(d,s) (*(s)) = 0, NULL # endif #else # define XineramaQueryExtension(da, b, c) 0 # define XineramaIsActive(a) 0 # define XineramaQueryScreens(d,s) (*(s)) = 0, NULL #endif #ifndef MAXFRAMEBUFFERS #define MAXFRAMEBUFFERS 16 #endif #ifdef USE_XINERAMA_EMULATION #define FScreenXineramaEmulation 1 #else #define FScreenXineramaEmulation 0 #endif #if 0 #ifdef HAVE_RANDR #include #include #endif #endif enum { /* Replace with FSCREEN_GLOBAL to restore default behaviour */ DEFAULT_GEOMETRY_SCREEN = FSCREEN_PRIMARY }; /* In fact, only corners matter -- there will never be GRAV_NONE */ enum {GRAV_POS = 0, GRAV_NONE = 1, GRAV_NEG = 2}; static int grav_matrix[3][3] = { { NorthWestGravity, NorthGravity, NorthEastGravity }, { WestGravity, CenterGravity, EastGravity }, { SouthWestGravity, SouthGravity, SouthEastGravity } }; #define DEFAULT_GRAVITY NorthWestGravity static Display *disp = NULL; static Bool is_xinerama_enabled = DEFAULT_XINERAMA_ENABLED; static Bool is_sls_enabled = False; static Bool have_sls_screen_list = False; static XineramaScreenInfo *screens; static XineramaScreenInfo *screens_xi; static XineramaScreenInfo *screens_sls = NULL; /* # of Xinerama screens, *not* counting the global, 0 if disabled */ static int num_screens = 0; /* # of Xinerama screens, *not* counting the global */ static int total_screens = 0; static int total_screens_xi = 0; static int total_screens_sls = 1; static int total_sls_width = 1; static int total_sls_height = 1; static int first_to_check = 0; static int last_to_check = 0; static int default_geometry_scr = FSCREEN_PRIMARY; /* only to be accessed vie the set/get functions! */ static int primary_scr = DEFAULT_PRIMARY_SCREEN; #if 0 #ifdef HAVE_RANDR static Bool randr_disabled = 0; static Bool randr_active = 0; static int randr_event_base = -1; static int randr_error_base = -1; #endif #endif static Window blank_w, vert_w, blank2_w, blank3_w; static int FScreenParseScreenBit(char *arg, char default_screen); static int FindScreenOfXY(int x, int y); static XineramaScreenInfo * solaris_XineramaQueryScreens(Display *d, int *nscreens) { if (FScreenHaveSolarisXinerama) { XineramaScreenInfo *screens = NULL; XRectangle monitors[MAXFRAMEBUFFERS]; unsigned char hints[16]; int result; /* dummy instructions to keep -Wall happy */ hints[0] = hints[0]; result = XineramaGetInfo( d, DefaultScreen(d), monitors, hints, nscreens); if (result) { int m; /* Note, malloced area later freed by XFree() */ screens = (XineramaScreenInfo *)malloc( sizeof(XineramaScreenInfo) * (*nscreens)); for (m = 0; m < *nscreens; ++m) { screens[m].screen_number = m; screens[m].x_org = monitors[m].x; screens[m].y_org = monitors[m].y; screens[m].width = monitors[m].width; screens[m].height = monitors[m].height; } } else { fprintf( stderr, "Error getting Xinerama information\n"); *nscreens = 0; } return screens; } else { return NULL; } } static XineramaScreenInfo *FXineramaQueryScreens(Display *d, int *nscreens) { if (FScreenHaveXinerama == 0) { *nscreens = 0; return NULL; } if (FScreenHaveSolarisXinerama == 1) { return solaris_XineramaQueryScreens(d, nscreens); } else { return XineramaQueryScreens(d, nscreens); } } static void GetMouseXY(XEvent *eventp, int *x, int *y) { if (!is_xinerama_enabled || last_to_check == first_to_check) { /* We use .x_org,.y_org because nothing prevents a screen to be * not at (0,0) */ *x = screens[first_to_check].x_org; *y = screens[first_to_check].y_org; } else { XEvent e; if (eventp == NULL) { eventp = &e; e.type = 0; } fev_get_evpos_or_query( disp, DefaultRootWindow(disp), eventp, x, y); } return; } Bool FScreenIsEnabled(void) { return (!is_xinerama_enabled || num_screens == 0) ? False : True; } Bool FScreenIsSLSEnabled(void) { return is_sls_enabled; } static void FScreenUpdateEmulationMapState(void) { static Bool is_mapped = False; if (!FScreenXineramaEmulation) { return; } if (is_xinerama_enabled && !is_sls_enabled) { if (!is_mapped) { XMapRaised(disp, blank_w); XMapRaised(disp, blank2_w); XMapRaised(disp, blank3_w); XMapRaised(disp, vert_w); is_mapped = True; } } else { if (is_mapped) { XUnmapWindow(disp, blank_w); XUnmapWindow(disp, blank2_w); XUnmapWindow(disp, blank3_w); XUnmapWindow(disp, vert_w); is_mapped = False; } } } static void FScreenSetState(Bool do_enable) { is_xinerama_enabled = do_enable; if (do_enable && total_screens > 0) { num_screens = total_screens; first_to_check = 1; last_to_check = total_screens; } else { num_screens = 0; first_to_check = 0; last_to_check = 0; } FScreenUpdateEmulationMapState(); } void FScreenInit(Display *dpy) { static Bool is_initialised = False; int dummy_rc; SUPPRESS_UNUSED_VAR_WARNING(dummy_rc); if (is_initialised) { return; } is_initialised = True; disp = dpy; if (FScreenXineramaEmulation) { int count; int w; int h; int ws; unsigned long scr; Window root; XSetWindowAttributes attributes; scr = DefaultScreen(disp); root = RootWindow(disp, scr); /* xinerama emulation simulates xinerama on a single screen: * * actual screen * +---------------------+--------------+ * | | | * | | | * | | | * | | simulated | * | | screen 2 | * | simulated screen 1 | | * | | | * | | | * | | | * | | | * +---------------------+ | * | blank area | | * | | | * +---------------------+--------------+ */ count = 2; total_screens_xi = count; screens_xi = (XineramaScreenInfo *) safemalloc(sizeof(XineramaScreenInfo) * (1 + count)); /* calculate the faked sub screen dimensions */ w = DisplayWidth(disp, scr); ws = 3 * w / 5; h = DisplayHeight(disp, scr); screens_xi[1].screen_number = 0; screens_xi[1].x_org = 0; screens_xi[1].y_org = h / 16; screens_xi[1].width = ws; screens_xi[1].height = 7 * h / 8; screens_xi[2].screen_number = 1; screens_xi[2].x_org = ws; screens_xi[2].y_org = 0; screens_xi[2].width = w - ws; screens_xi[2].height = 7 * h / 8; /* add delimiter */ attributes.background_pixel = PictureWhitePixel(); attributes.override_redirect = True; blank_w = XCreateWindow( disp, root, 0, screens_xi[1].y_org - 1, screens_xi[1].width, 2, 0, CopyFromParent, CopyFromParent, CopyFromParent, CWBackPixel|CWOverrideRedirect, &attributes); blank2_w = XCreateWindow( disp, root, 0, screens_xi[1].y_org + screens_xi[1].height - 1, screens_xi[1].width, 2, 0, CopyFromParent, CopyFromParent, CopyFromParent, CWBackPixel|CWOverrideRedirect, &attributes); blank3_w = XCreateWindow( disp, root, screens_xi[2].x_org, screens_xi[2].height - 1, w - screens_xi[2].x_org, 2, 0, CopyFromParent, CopyFromParent, CopyFromParent, CWBackPixel|CWOverrideRedirect, &attributes); vert_w = XCreateWindow( disp, root, screens_xi[2].x_org - 1, 0, 2, h, 0, CopyFromParent, CopyFromParent, CopyFromParent, CWBackPixel|CWOverrideRedirect, &attributes); } else if (FScreenHaveXinerama && XineramaQueryExtension(disp, &dummy_rc, &dummy_rc) && XineramaIsActive(disp)) { int count; XineramaScreenInfo *info; info = FXineramaQueryScreens(disp, &count); total_screens_xi = count; screens_xi = (XineramaScreenInfo *) safemalloc(sizeof(XineramaScreenInfo) * (1 + count)); memcpy(screens_xi + 1, info, sizeof(XineramaScreenInfo) * count); XFree(info); } else { total_screens_xi = 0; screens_xi = (XineramaScreenInfo *)safemalloc( sizeof(XineramaScreenInfo)*1); } total_screens = total_screens_xi; screens = screens_xi; /* Now, fill screens[0] with global screen parameters */ screens_xi[0].screen_number = -1; screens_xi[0].x_org = 0; screens_xi[0].y_org = 0; screens_xi[0].width = DisplayWidth (disp, DefaultScreen(disp)); screens_xi[0].height = DisplayHeight(disp, DefaultScreen(disp)); /* Fill in the screen range */ FScreenSetState(is_xinerama_enabled); return; } void FScreenOnOff(Bool do_enable) { FScreenSetState(do_enable); } void FScreenSLSOnOff(Bool do_enable) { is_sls_enabled = do_enable; if (do_enable) { total_screens = total_screens_sls; if (!screens_sls) { /* Sls not configured yet, use whole screen by default */ FScreenConfigureSLSSize(1, 1); } screens = screens_sls; } else { total_screens = total_screens_xi; screens = screens_xi; } FScreenSetState(is_xinerama_enabled); } Bool FScreenConfigureSLSSize(int width, int height) { unsigned long scr = DefaultScreen(disp); int w = DisplayWidth(disp, scr); int h = DisplayHeight(disp, scr); if (width <= 1) { width = 1; } else if (width > w) { width = w; } if (height <= 1) { height = 1; } else if (height > h) { height = h; } if (total_sls_width == width && total_sls_height == height && screens_sls) { return False; } if (screens_sls) { free(screens_sls); screens_sls = NULL; } /* calculate the screens */ { int row, col, sn; int ws; int hs; total_screens_sls = width * height; total_sls_width = width; total_sls_height = height; ws = w / total_sls_width; hs = h / total_sls_height; screens_sls = (XineramaScreenInfo *) safemalloc(sizeof(XineramaScreenInfo) * (1 + total_screens_sls)); /* calculate the faked sub screen dimensions */ screens_sls[0] = screens_xi[0]; sn = 1; for (row = 0; row < total_sls_height; row++) { for (col = 0; col < total_sls_width; col++, sn++) { screens_sls[sn].screen_number = sn - 1; screens_sls[sn].x_org = col * ws; screens_sls[sn].y_org = row * hs; screens_sls[sn].width = ws; screens_sls[sn].height = hs; } } } have_sls_screen_list = False; FScreenSLSOnOff(is_sls_enabled); return True; } Bool FScreenConfigureSLSScreens(int nscreens, char *args) { int sn; char *next; if (nscreens == 0 || args == NULL) { return FScreenConfigureSLSSize(1, 1); } if (nscreens == 1 && screens_sls) { return False; } if (screens_sls) { free(screens_sls); screens_sls = NULL; } screens_sls = (XineramaScreenInfo *) safemalloc(sizeof(XineramaScreenInfo) * (nscreens + 1)); screens_sls[0] = screens_xi[0]; for (sn = 1; sn <= nscreens; sn++, args = next) { char *token; int val[4]; /* read next screen spec */ token = PeekToken(args, &next); if (!token) { break; } if (XParseGeometry(token, &val[0], &val[1], (unsigned int *)&val[2], (unsigned int *)&val[3]) == (XValue|YValue|WidthValue|HeightValue) || GetIntegerArguments(args, &next, val, 4) == 4) { if (val[0] < 0 || val[1] < 0 || val[2] < 1 || val[3] < 1) { /* illegal spec */ break; } screens_sls[sn].screen_number = sn - 1; screens_sls[sn].x_org = val[0]; screens_sls[sn].y_org = val[1]; screens_sls[sn].width = val[2]; screens_sls[sn].height = val[3]; } else { /* illegal spec */ break; } } total_screens_sls = sn - 1; have_sls_screen_list = True; FScreenSLSOnOff(is_sls_enabled); return True; } #if 0 void FScreenDisableRandR(void) { if (disp != NULL) { fprintf(stderr, "FScreen: WARNING: FScreenDisableRandR()" " called after FScreenInit()!\n"); } randr_disabled = 1; return; } #endif static int FScreenGetPrimaryScreen(XEvent *ev) { if (!is_xinerama_enabled) { return 0; } if (primary_scr == FSCREEN_GLOBAL) { return 0; } else if (primary_scr == FSCREEN_CURRENT) { int mx; int my; /* use current screen as primary screen */ GetMouseXY(ev, &mx, &my); return FindScreenOfXY(mx, my); } else if (primary_scr < 0 || primary_scr >= last_to_check) { /* out of range */ return 0; } return primary_scr + 1; } void FScreenSetPrimaryScreen(int scr) { primary_scr = scr; } /* Intended to be called by modules. Simply pass in the parameter from the * config string sent by fvwm. */ void FScreenConfigureModule(char *args) { int val[6]; int n; char *next; n = GetIntegerArguments(args, &next, val, 4); if (n != 4) { /* ignore broken line */ return; } FScreenSetPrimaryScreen(val[1]); if (val[3]) { /* SLS screen coordinates follow */ n = GetIntegerArguments(next, &next, val + 4, 1); if (n != 1) { /* ignore broken line */ return; } FScreenConfigureSLSScreens(val[4], next); } else { /* simple SLS line */ n = GetIntegerArguments(next, NULL, val + 4, 2); if (n != 2) { /* ignore broken line */ return; } FScreenConfigureSLSSize(val[4], val[5]); } FScreenSLSOnOff(val[2]); FScreenOnOff(val[0]); return; } /* Here's the function used by fvwm to generate the string which * FScreenConfigureModule expects to receive back as its argument. */ const char *FScreenGetConfiguration(void) { int i; int l; int l2; static char msg[MAX_MODULE_INPUT_TEXT_LEN]; char buf[64]; sprintf( msg, XINERAMA_CONFIG_STRING" %d %d %d %d", FScreenIsEnabled(), primary_scr, FScreenIsSLSEnabled(), have_sls_screen_list); l = strlen(msg); if (have_sls_screen_list) { sprintf(msg + l, " %d", total_screens_sls); for (i = 0; i < total_screens_sls; i++) { sprintf(buf, " %d %d %d %d", screens_sls[i].x_org, screens_sls[i].y_org, screens_sls[i].width, screens_sls[i].height); l2 = strlen(buf); if (l + l2 > MAX_MODULE_INPUT_TEXT_LEN) { break; } strcat(msg + l, buf); l += l2; } } else { sprintf(msg + l, " %d %d", total_sls_width, total_sls_height); } return msg; } /* Sets the default screen for ...ParseGeometry if no screen spec is given. * Usually this is FSCREEN_SPEC_PRIMARY, but this won't allow modules to appear * under the pointer. */ void FScreenSetDefaultModuleScreen(char *scr_spec) { default_geometry_scr = FScreenParseScreenBit(scr_spec, FSCREEN_SPEC_PRIMARY); return; } static int FindScreenOfXY(int x, int y) { int i; x = x % screens_xi[0].width; while (x < 0) { x += screens_xi[0].width; } y = y % screens_xi[0].height; while (y < 0) { y += screens_xi[0].height; } for (i = first_to_check; i <= last_to_check; i++) { if (x >= screens[i].x_org && x < screens[i].x_org + screens[i].width && y >= screens[i].y_org && y < screens[i].y_org + screens[i].height) { return i; } } /* Ouch! A "black hole" coords? As for now, return global screen */ return 0; } static int FindScreen( fscreen_scr_arg *arg, fscreen_scr_t screen) { fscreen_scr_arg tmp; if (num_screens == 0) { screen = FSCREEN_GLOBAL; } switch (screen) { case FSCREEN_GLOBAL: screen = 0; break; case FSCREEN_PRIMARY: screen = FScreenGetPrimaryScreen( (arg && arg->mouse_ev) ? arg->mouse_ev : NULL); break; case FSCREEN_CURRENT: /* translate to xypos format */ if (!arg) { tmp.mouse_ev = NULL; arg = &tmp; } GetMouseXY(arg->mouse_ev, &arg->xypos.x, &arg->xypos.y); /* fall through */ case FSCREEN_XYPOS: /* translate to screen number */ if (!arg) { tmp.xypos.x = 0; tmp.xypos.y = 0; arg = &tmp; } screen = FindScreenOfXY(arg->xypos.x, arg->xypos.y); break; default: /* screen is given counting from 0; translate to counting from * 1 */ screen++; break; } return screen; } /* Given pointer coordinates, return the screen the pointer is on. * * Perhaps most useful with $[pointer.screen] */ int FScreenOfPointerXY(int x, int y) { int pscreen; pscreen = FindScreenOfXY(x, y); return (pscreen > 0) ? --pscreen : pscreen; } /* Returns the specified screens geometry rectangle. screen can be a screen * number or any of the values FSCREEN_GLOBAL, FSCREEN_CURRENT, * FSCREEN_PRIMARY or FSCREEN_XYPOS. The arg union only has a meaning for * FSCREEN_CURRENT and FSCREEN_XYARG. For FSCREEN_CURRENT its mouse_ev member * may be given. It is tried to find out the pointer position from the event * first before querying the pointer. For FSCREEN_XYPOS the xpos member is used * to fetch the x/y position of the point on the screen. If arg is NULL, the * position 0 0 is assumed instead. * * Any of the arguments arg, x, y, w and h may be NULL. * * FSCREEN_GLOBAL: return the global screen dimensions * FSCREEN_CURRENT: return dimensions of the screen with the pointer * FSCREEN_PRIMARY: return the primary screen dimensions * FSCREEN_XYPOS: return dimensions of the screen with the given coordinates * * The function returns False if the global screen was returned and more than * one screen is configured. Otherwise it returns True. */ Bool FScreenGetScrRect( fscreen_scr_arg *arg, fscreen_scr_t screen, int *x, int *y, int *w, int *h) { screen = FindScreen(arg, screen); if (screen < first_to_check || screen > last_to_check) { screen = 0; } if (x) { *x = screens[screen].x_org; } if (y) { *y = screens[screen].y_org; } if (w) { *w = screens[screen].width; } if (h) { *h = screens[screen].height; } return !(screen == 0 && num_screens > 1); } /* returns the screen id */ Bool FScreenGetScrId( fscreen_scr_arg *arg, fscreen_scr_t screen) { screen = FindScreen(arg, screen); if (screen < 0) { screen = FSCREEN_GLOBAL; } return screen; } /* Translates the coodinates *x *y from the screen specified by arg_src and * screen_src to coordinates on the screen specified by arg_dest and * screen_dest. (see FScreenGetScrRect for more details). */ void FScreenTranslateCoordinates( fscreen_scr_arg *arg_src, fscreen_scr_t screen_src, fscreen_scr_arg *arg_dest, fscreen_scr_t screen_dest, int *x, int *y) { int x_src; int y_src; int x_dest; int y_dest; FScreenGetScrRect(arg_src, screen_src, &x_src, &y_src, NULL, NULL); FScreenGetScrRect(arg_dest, screen_dest, &x_dest, &y_dest, NULL, NULL); if (x) { *x = *x + x_src - x_dest; } if (y) { *y = *y + y_src - y_dest; } return; } /* Arguments work exactly like for FScreenGetScrRect() */ int FScreenClipToScreen( fscreen_scr_arg *arg, fscreen_scr_t screen, int *x, int *y, int w, int h) { int sx; int sy; int sw; int sh; int lx = (x) ? *x : 0; int ly = (y) ? *y : 0; int x_grav = GRAV_POS; int y_grav = GRAV_POS; FScreenGetScrRect(arg, screen, &sx, &sy, &sw, &sh); if (lx + w > sx + sw) { lx = sx + sw - w; x_grav = GRAV_NEG; } if (ly + h > sy + sh) { ly = sy + sh - h; y_grav = GRAV_NEG; } if (lx < sx) { lx = sx; x_grav = GRAV_POS; } if (ly < sy) { ly = sy; y_grav = GRAV_POS; } if (x) { *x = lx; } if (y) { *y = ly; } return grav_matrix[y_grav][x_grav]; } /* Arguments work exactly like for FScreenGetScrRect() */ void FScreenCenterOnScreen( fscreen_scr_arg *arg, fscreen_scr_t screen, int *x, int *y, int w, int h) { int sx; int sy; int sw; int sh; int lx; int ly; FScreenGetScrRect(arg, screen, &sx, &sy, &sw, &sh); lx = (sw - w) / 2; ly = (sh - h) / 2; if (lx < 0) lx = 0; if (ly < 0) ly = 0; lx += sx; ly += sy; if (x) { *x = lx; } if (y) { *y = ly; } return; } void FScreenGetResistanceRect( int wx, int wy, unsigned int ww, unsigned int wh, int *x0, int *y0, int *x1, int *y1) { fscreen_scr_arg arg; arg.xypos.x = wx + ww / 2; arg.xypos.y = wy + wh / 2; FScreenGetScrRect(&arg, FSCREEN_XYPOS, x0, y0, x1, y1); *x1 += *x0; *y1 += *y0; return; } /* Arguments work exactly like for FScreenGetScrRect() */ Bool FScreenIsRectangleOnScreen( fscreen_scr_arg *arg, fscreen_scr_t screen, rectangle *rec) { int sx; int sy; int sw; int sh; FScreenGetScrRect(arg, screen, &sx, &sy, &sw, &sh); return (rec->x + rec->width > sx && rec->x < sx + sw && rec->y + rec->height > sy && rec->y < sy + sh) ? True : False; } void FScreenSpecToString(char *dest, int space, fscreen_scr_t screen) { char s[32]; if (space <= 0) { return; } switch (screen) { case FSCREEN_GLOBAL: strcpy(s, "global screen"); break; case FSCREEN_CURRENT: strcpy(s, "current screen"); break; case FSCREEN_PRIMARY: strcpy(s, "primary screen"); break; case FSCREEN_XYPOS: strcpy(s, "screen specified by xy"); break; default: sprintf(s, "%d", screen); break; } strncpy(dest, s, space); dest[space - 1] = 0; return; } static int FScreenParseScreenBit(char *scr_spec, char default_screen) { int scr = default_geometry_scr; char c; c = (scr_spec) ? tolower(*scr_spec) : tolower(default_screen); if (c == FSCREEN_SPEC_GLOBAL) { scr = FSCREEN_GLOBAL; } else if (c == FSCREEN_SPEC_CURRENT) { scr = FSCREEN_CURRENT; } else if (c == FSCREEN_SPEC_PRIMARY) { scr = FSCREEN_PRIMARY; } else if (c == FSCREEN_SPEC_WINDOW) { scr = FSCREEN_XYPOS; } else if (isdigit(c)) { scr = atoi(scr_spec); } else { c = tolower(default_screen); if (c == FSCREEN_SPEC_GLOBAL) { scr = FSCREEN_GLOBAL; } else if (c == FSCREEN_SPEC_CURRENT) { scr = FSCREEN_CURRENT; } else if (c == FSCREEN_SPEC_PRIMARY) { scr = FSCREEN_PRIMARY; } else if (c == FSCREEN_SPEC_WINDOW) { scr = FSCREEN_XYPOS; } else if (isdigit(c)) { scr = atoi(scr_spec); } } return scr; } int FScreenGetScreenArgument(char *scr_spec, fscreen_scr_spec_t default_screen) { while (scr_spec && isspace(*scr_spec)) { scr_spec++; } return FScreenParseScreenBit(scr_spec, default_screen); } /* * FScreenParseGeometry * Does the same as XParseGeometry, but handles additional "@scr". * Since it isn't safe to define "ScreenValue" constant (actual values * of other "XXXValue" are specified in Xutil.h, not by us, so there can * be a clash), the screen value is always returned, even if it wasn't * present in `parse_string' (set to default in that case). * */ int FScreenParseGeometryWithScreen( char *parsestring, int *x_return, int *y_return, unsigned int *width_return, unsigned int *height_return, int *screen_return) { int ret; char *copy, *scr_p; int s_size; int scr; /* Safety net */ if (parsestring == NULL || *parsestring == '\0') { return 0; } /* Make a local copy devoid of "@scr" */ s_size = strlen(parsestring) + 1; copy = safemalloc(s_size); memcpy(copy, parsestring, s_size); scr_p = strchr(copy, '@'); if (scr_p != NULL) { *scr_p++ = '\0'; } /* Do the parsing */ ret = XParseGeometry( copy, x_return, y_return, width_return, height_return); /* Parse the "@scr", if any */ scr = FScreenParseScreenBit(scr_p, FSCREEN_SPEC_PRIMARY); *screen_return = scr; /* We don't need the string any more */ free(copy); return ret; } /* Same as above, but dump screen return value to keep compatible with the X * function. */ int FScreenParseGeometry( char *parsestring, int *x_return, int *y_return, unsigned int *width_return, unsigned int *height_return) { int scr; int rc; int mx; int my; rc = FScreenParseGeometryWithScreen( parsestring, x_return, y_return, width_return, height_return, &scr); if (rc == 0) { return 0; } switch (scr) { case FSCREEN_GLOBAL: scr = 0; break; case FSCREEN_CURRENT: GetMouseXY(NULL, &mx, &my); scr = FindScreenOfXY(mx, my); break; case FSCREEN_PRIMARY: scr = FScreenGetPrimaryScreen(NULL); break; default: scr++; break; } if (scr <= 0 || scr > last_to_check) { scr = 0; } else { /* adapt geometry to selected screen */ if (rc & XValue) { if (rc & XNegative) { *x_return -= (screens[0].width - screens[scr].width - screens[scr].x_org); } else { *x_return += screens[scr].x_org; } } if (rc & YValue) { if (rc & YNegative) { *y_return -= (screens[0].height - screens[scr].height - screens[scr].y_org); } else { *y_return += screens[scr].y_org; } } } return rc; } /* FScreenGetGeometry * Parses the geometry in a form: XGeometry[@screen], i.e. * [=][{xX}][{+-}{+-}][@] * where is either a number or "G" (global) "C" (current) * or "P" (primary) * * Args: * parsestring, x_r, y_r, w_r, h_r the same as in XParseGeometry * hints window hints structure, may be NULL * flags bitmask of allowed flags (XValue, WidthValue, XNegative...) * * Note1: * hints->width and hints->height will be used to calc negative geometry * if width/height isn't specified in the geometry itself. * * Note2: * This function's behaviour is crafted to sutisfy/emulate the * FvwmWinList::MakeMeWindow()'s behaviour. * * Note3: * A special value of `flags' when [XY]Value are there but [XY]Negative * aren't, means that in case of negative geometry specification * x_r/y_r values will be promoted to the screen border, but w/h * wouldn't be subtracted, so that the program can do x-=w later * ([XY]Negative *will* be returned, albeit absent in `flags'). * This option is supposed for proggies like FvwmButtons, which * receive geometry specification long before they are able to actually * use it (and which calculate w/h themselves). * (The same effect can't be obtained with omitting {Width,Height}Value * in the flags, since the app may wish to get the dimensions but apply * some constraints later (as FvwmButtons do, BTW...).) * This option can be also useful in cases where dimensions are * specified not in pixels but in some other units (e.g., charcells). */ int FScreenGetGeometry( char *parsestring, int *x_return, int *y_return, int *width_return, int *height_return, XSizeHints *hints, int flags) { int ret; int saved; int x, y; unsigned int w = 0, h = 0; int grav, x_grav, y_grav; int scr = default_geometry_scr; int scr_x, scr_y; int scr_w, scr_h; /* I. Do the parsing and strip off extra bits */ ret = FScreenParseGeometryWithScreen(parsestring, &x, &y, &w, &h, &scr); saved = ret & (XNegative | YNegative); ret &= flags; /* II. Get the screen rectangle */ switch (scr) { case FSCREEN_GLOBAL: case FSCREEN_CURRENT: case FSCREEN_PRIMARY: case FSCREEN_XYPOS: FScreenGetScrRect(NULL, scr, &scr_x, &scr_y, &scr_w, &scr_h); break; default: scr++; if (scr < first_to_check || scr > last_to_check) scr = first_to_check; scr_x = screens[scr].x_org; scr_y = screens[scr].y_org; scr_w = screens[scr].width; scr_h = screens[scr].height; } /* III. Interpret and fill in the values */ /* Fill in dimensions for future negative calculations if * omitted/forbidden */ /* Maybe should use *x_return,*y_return if hints==NULL? * Unreliable... */ if (hints != NULL && hints->flags & PSize) { if ((ret & WidthValue) == 0) { w = hints->width; } if ((ret & HeightValue) == 0) { h = hints->height; } } else { /* This branch is required for case when size *is* specified, * but masked off */ if ((ret & WidthValue) == 0) { w = 0; } if ((ret & HeightValue) == 0) { h = 0; } } /* Advance coords to the screen... */ x += scr_x; y += scr_y; /* ...and process negative geometries */ if (saved & XNegative) { x += scr_w; } if (saved & YNegative) { y += scr_h; } if (ret & XNegative) { x -= w; } if (ret & YNegative) { y -= h; } /* Restore negative bits */ ret |= saved; /* Guess orientation */ x_grav = (ret & XNegative)? GRAV_NEG : GRAV_POS; y_grav = (ret & YNegative)? GRAV_NEG : GRAV_POS; grav = grav_matrix[y_grav][x_grav]; /* Return the values */ if (ret & XValue) { *x_return = x; if (hints != NULL) { hints->x = x; } } if (ret & YValue) { *y_return = y; if (hints != NULL) { hints->y = y; } } if (ret & WidthValue) { *width_return = w; if (hints != NULL) { hints->width = w; } } if (ret & HeightValue) { *height_return = h; if (hints != NULL) { hints->height = h; } } if (1 /*flags & GravityValue*/ && grav != DEFAULT_GRAVITY) { if (hints != NULL && hints->flags & PWinGravity) { hints->win_gravity = grav; } } if (hints != NULL && ret & XValue && ret & YValue) hints->flags |= USPosition; return ret; } /* FScreenMangleScreenIntoUSPosHints * A hack to mangle the screen number into the XSizeHints structure. * If the USPosition flag is set, hints->x is set to the magic number and * hints->y is set to the screen number. If the USPosition flag is clear, * x and y are set to zero. * * Note: This is a *hack* to allow modules to specify the target screen for * their windows and have the StartsOnScreen style set for them at the same * time. Do *not* rely on the mechanism described above. */ void FScreenMangleScreenIntoUSPosHints(fscreen_scr_t screen, XSizeHints *hints) { if (hints->flags & USPosition) { hints->x = FSCREEN_MANGLE_USPOS_HINTS_MAGIC; hints->y = (short)screen; } else { hints->x = 0; hints->y = 0; } return; } /* FScreenMangleScreenIntoUSPosHints * A hack to mangle the screen number into the XSizeHints structure. * If the USPosition flag is set, hints->x is set to the magic number and * hints->y is set to the screen spec. If the USPosition flag is clear, * x and y are set to zero. * * Note: This is a *hack* to allow modules to specify the target screen for * their windows and have the StartsOnScreen style set for them at the same * time. Do *not* rely on the mechanism described above. */ fscreen_scr_t FScreenFetchMangledScreenFromUSPosHints(XSizeHints *hints) { fscreen_scr_t screen; if ((hints->flags & USPosition) && hints->x == FSCREEN_MANGLE_USPOS_HINTS_MAGIC) { screen = (fscreen_scr_t)(hints->y); } else { screen = FSCREEN_GLOBAL; } return screen; } /* no rand_r for now */ # if 0 int FScreenGetRandrEventType(void) { #ifdef HAVE_RANDR return randr_active? randr_event_base + RRScreenChangeNotify : 0; #else return 0; #endif } Bool FScreenHandleRandrEvent( XEvent *event, int *old_w, int *old_h, int *new_w, int *new_h) { #ifndef HAVE_RANDR return 0; #else XRRScreenChangeNotifyEvent *ev = (XRRScreenChangeNotifyEvent *)event; int nw, nh, tmp; if (!randr_active || event->type != randr_event_base + RRScreenChangeNotify) { return 0; } nw = ev->width; nh = ev->height; /* * Note1: this check is not very good, since the right way is to * obtain a list of possible rotations and ... * * Note2: as to WM's point of view, I'm unsure if rotation should be * treated exactly as resizing (i.e. that it should reposition * windows in the same fashion). */ if (ev->rotation & (1<<1 | 1<<3)) { tmp = nw; nw = nh; nh = tmp; } *old_w = screens[0].width; *old_h = screens[0].height; screens[0].width = nw; *new_w = nw; screens[0].height = nh; *new_h = nh; return (nw != *old_w || nh != *old_h); #endif } #endif fvwm-2.7.0/libs/Picture.h0000644000175000017500000000533514147024700012142 00000000000000/* -*-c-*- */ #ifndef Picture_H #define Picture_H #include "PictureBase.h" #include "PictureImageLoader.h" /** Manipulating FvwmPictures **/ /** * For PGetFvwmPicture() and PCacheFvwmPicture(), setting * ImagePath to NULL means "search the default image path". **/ /* PGetFvwmPicture * * Return an FvwmPicture loaded from the file pictureName found in the * ImagePath.. If ImagePath is NULL the default image path is used. * */ FvwmPicture* PGetFvwmPicture( Display* dpy, Window win, char* ImagePath, const char* pictureName, FvwmPictureAttributes fpa); /* PFreeFvwmPictureData * * Just free the data allocated by PGetFvwmPicture. This function does not * Free the pixmaps for example. * */ void PFreeFvwmPictureData(FvwmPicture *p); /* PCacheFvwmPicture * * Return the FvwmPicture loaded from the file pictureName found in the * ImagePath. Fisrt the picture is searched in the FvwmPicture cache (so * if this picture has been already loaded it is not loaded again and a * weight is added to the found picture). If the picture is not in the cache * it is loaded from the file and added to the FvwmPicture cache. * If ImagePath is NULL the default image path is used. * */ FvwmPicture* PCacheFvwmPicture( Display *dpy, Window win, char* ImagePath, const char* pictureName, FvwmPictureAttributes fpa); /* PLoadFvwmPictureFromPixmap * * Return a FvwmPicture from the given data. * */ FvwmPicture *PLoadFvwmPictureFromPixmap( Display *dpy, Window win, char *name, Pixmap pixmap, Pixmap mask, Pixmap alpha, int width, int height, int nalloc_pixels, Pixel *alloc_pixels, int no_limit); /* PDestroyFvwmPicture * * Return a FvwmPicture from the given data. The picture is added to the * FvwmPicture cache. This is not really useful as it is not possible * to really cache a picture from the given data. * */ FvwmPicture *PCacheFvwmPictureFromPixmap( Display *dpy, Window win, char *name, Pixmap pixmap, Pixmap mask, Pixmap alpha, int width, int height, int nalloc_pixels, Pixel *alloc_pixels, int no_limit); /* PDestroyFvwmPicture * * Remove a weight to the FvwmPicture p from the FvwmPicture cache. * If the weight is zero the allocated datas from p are freed * */ void PDestroyFvwmPicture(Display *dpy, FvwmPicture *p); /* PCloneFvwmPicture * * Duplicate an already allocated FvwmPicture in the FvwmPicture cache * (a weight is added to the picture). * */ FvwmPicture *PCloneFvwmPicture(FvwmPicture *pic); void PicturePrintImageCache(int verbose); #endif fvwm-2.7.0/libs/PictureImageLoader.c0000644000175000017500000005354514147024700014235 00000000000000/* -*-c-*- */ /* Copyright (C) 1993, Robert Nation * Copyright (C) 1999 Carsten Haitzler and various contributors (imlib2) * Copyright (C) 2002 Olivier Chapuis */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* * * The png loader and PImageRGBtoPixel are from imlib2. The code is from raster * (Carsten Haitzler) * */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include #include #include #include #include "System.h" #include "Strings.h" #include "Picture.h" #include "PictureUtils.h" #include "Graphics.h" #include "ColorUtils.h" #include "Fxpm.h" #include "Fpng.h" #include "Fsvg.h" #include "FRenderInit.h" #include "Fcursor.h" #include "FImage.h" /* ---------------------------- local definitions -------------------------- */ #define FIMAGE_CMD_ARGS \ Display *dpy, char *path, CARD32 **argb_data, int *width, int *height #define FIMAGE_PASS_ARGS \ dpy, path, argb_data, width, height typedef struct PImageLoader { char *extension; #ifdef __STDC__ int (*func)(FIMAGE_CMD_ARGS); #else int (*func)(); #endif } PImageLoader; /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ static Bool PImageLoadSvg(FIMAGE_CMD_ARGS); static Bool PImageLoadPng(FIMAGE_CMD_ARGS); static Bool PImageLoadXpm(FIMAGE_CMD_ARGS); /* ---------------------------- local variables ---------------------------- */ PImageLoader Loaders[] = { { "xpm", PImageLoadXpm }, { "svg", PImageLoadSvg }, { "png", PImageLoadPng }, {NULL,0} }; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ static Bool PImageLoadArgbDataFromFile(FIMAGE_CMD_ARGS) { int done = 0, i = 0, tried = -1; char *ext = NULL; if (path == NULL) return False; if (strlen(path) > 3) { ext = path + strlen(path) - 3; } /* first try to load by extension */ while (!done && ext != NULL && Loaders[i].extension != NULL) { if (StrEquals(Loaders[i].extension, ext)) { if (Loaders[i].func(FIMAGE_PASS_ARGS)) { return True; } tried = i; done = 1; } i++; } i = 0; while (Loaders[i].extension != NULL) { if (i != tried && Loaders[i].func(FIMAGE_PASS_ARGS)) { return True; } i++; } return False; } /* * * svg loader * */ static Bool PImageLoadSvg(FIMAGE_CMD_ARGS) { char *allocated_path; char *render_opts; FRsvgHandle *rsvg; FRsvgDimensionData dim; CARD32 *data; Fcairo_surface_t *surface; Fcairo_t *cr; int i; int j; int b1; int b2; int w = 0; int h = 0; int dw = 0; int dh = 0; int w_sgn = 1; int h_sgn = 1; double angle = 0; double w_scale = 1; double h_scale = 1; double buf; Bool transpose = False; unsigned char a_value; unsigned char r_value; unsigned char g_value; unsigned char b_value; if (!USE_SVG) { fprintf(stderr, "[PImageLoadSvg]: Tried to load SVG file " "when FVWM has not been compiled with SVG support.\n"); return False; } /* Separate rendering options from path */ render_opts = path = allocated_path = safestrdup(path); if (*path == ':' && (path = strchr(path + 1, ':'))) { *path = 0; path ++; render_opts ++; } else { render_opts = ""; } if (!(rsvg = Frsvg_handle_new_from_file(path, NULL))) { free(allocated_path); return False; } /* Parsing of rendering options */ while (*render_opts) { i = 0; switch (*render_opts) { case '!': transpose = !transpose; break; case '*': if (sscanf(render_opts, "*%lf%n", &buf, &i) >= 1) { switch (render_opts[i]) { case 'x': w_scale *= buf; i ++; break; case 'y': h_scale *= buf; i ++; break; default: w_scale *= buf; h_scale *= buf; } } break; case '/': if (sscanf(render_opts, "/%lf%n", &buf, &i) >= 1 && buf) { switch (render_opts[i]) { case 'x': w_scale /= buf; i ++; break; case 'y': h_scale /= buf; i ++; break; default: w_scale /= buf; h_scale /= buf; } } break; case '@': if (sscanf(render_opts, "@%lf%n", &buf, &i) >= 1) { angle += buf; } break; default: j = 0; if ( sscanf( render_opts, "%dx%n%d%n", &b1, &j, &b2, &i) >= 2 && i > j) { w = b1; h = b2; if (w < 0 || (!w && render_opts[0] == '-')) { w *= (w_sgn = -1); } if (h < 0 || (!h && render_opts[j] == '-')) { h *= (h_sgn = -1); } } else if ( sscanf(render_opts, "%d%d%n", &b1, &b2, &i) >= 2) { dw += b1; dh += b2; } } render_opts += i ? i : 1; } free(allocated_path); /* Keep the original aspect ratio when either w or h is 0 */ Frsvg_handle_get_dimensions(rsvg, &dim); if (!w && !h) { w = dim.width; h = dim.height; } else if (!w) { w = h * dim.em / dim.ex; } else if (!h) { h = w * dim.ex / dim.em; } w_scale *= w; h_scale *= h; if (transpose) { b1 = w; w = h; h = b1; b1 = w_sgn; w_sgn = - h_sgn; h_sgn = b1; b1 = dw; dw = - dh; dh = b1; angle += 90; } data = (CARD32 *)safemalloc(w * h * sizeof(CARD32)); memset(data, 0, w * h * sizeof(CARD32)); surface = Fcairo_image_surface_create_for_data((unsigned char *)data, FCAIRO_FORMAT_ARGB32, w, h, w * sizeof(CARD32)); if (Fcairo_surface_status(surface) != FCAIRO_STATUS_SUCCESS) { Fg_object_unref(FG_OBJECT(rsvg)); free(data); if (surface) { Fcairo_surface_destroy(surface); } return False; } cr = Fcairo_create(surface); Fcairo_surface_destroy(surface); if (Fcairo_status(cr) != FCAIRO_STATUS_SUCCESS) { Fg_object_unref(FG_OBJECT(rsvg)); free(data); if (cr) { Fcairo_destroy(cr); } return False; } /* Affine transformations ... * mirroring, rotation, scaling and translation */ Fcairo_translate(cr, .5 * w, .5 * h); Fcairo_scale(cr, w_sgn, h_sgn); Fcairo_translate(cr, dw, dh); Fcairo_rotate(cr, angle * M_PI / 180); Fcairo_scale(cr, w_scale, h_scale); Fcairo_translate(cr, -.5, -.5); Fcairo_scale(cr, 1 / dim.em, 1 / dim.ex); Frsvg_handle_render_cairo(rsvg, cr); Fg_object_unref(FG_OBJECT(rsvg)); Fcairo_destroy(cr); /* Cairo gave us alpha prescaled RGB values, hence we need * to rescale them for PImageCreatePixmapFromArgbData() */ for (i = 0; i < w * h; i++) { if ((a_value = (data[i] >> 030) & 0xff)) { r_value = ((data[i] >> 020) & 0xff) * 0xff / a_value; g_value = ((data[i] >> 010) & 0xff) * 0xff / a_value; b_value = (data[i] & 0xff) * 0xff / a_value; data[i] = (a_value << 030) | (r_value << 020) | (g_value << 010) | b_value; } } *width = w; *height = h; *argb_data = data; return True; } /* * * png loader * */ static Bool PImageLoadPng(FIMAGE_CMD_ARGS) { Fpng_uint_32 w32, h32; Fpng_structp Fpng_ptr = NULL; Fpng_infop Finfo_ptr = NULL; CARD32 *data; int w, h; char hasa = 0, hasg = 0; FILE *f; int bit_depth; int color_type; int interlace_type; unsigned char buf[FPNG_BYTES_TO_CHECK]; unsigned char **lines; int i; if (!PngSupport) { /* suppress compiler warning */ bit_depth = 0; fprintf(stderr, "[PImageLoadPng]: Tried to load PNG file " "when FVWM has not been compiled with PNG support.\n"); return False; } if (!(f = fopen(path, "rb"))) { return False; } { int n; n = fread(buf, 1, FPNG_BYTES_TO_CHECK, f); (void)n; } if (!Fpng_check_sig(buf, FPNG_BYTES_TO_CHECK)) { fclose(f); return False; } rewind(f); Fpng_ptr = Fpng_create_read_struct(FPNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!Fpng_ptr) { fclose(f); return False; } Finfo_ptr = Fpng_create_info_struct(Fpng_ptr); if (!Finfo_ptr) { Fpng_destroy_read_struct(&Fpng_ptr, NULL, NULL); fclose(f); return False; } #if 0 if (setjmp(Fpng_ptr->jmpbuf)) { Fpng_destroy_read_struct(&Fpng_ptr, &Finfo_ptr, NULL); fclose(f); return False; } #endif Fpng_init_io(Fpng_ptr, f); Fpng_read_info(Fpng_ptr, Finfo_ptr); Fpng_get_IHDR( Fpng_ptr, Finfo_ptr, (Fpng_uint_32 *) (&w32), (Fpng_uint_32 *) (&h32), &bit_depth, &color_type, &interlace_type, NULL, NULL); interlace_type = 0; /* not used */ *width = w = (int) w32; *height = h = (int) h32; if (color_type == FPNG_COLOR_TYPE_PALETTE) { Fpng_set_expand(Fpng_ptr); } /* TA: XXX: (2011-02-14) -- Happy Valentines Day. * * png_get_color_type() defined in libpng 1.5 now hides a data member * to a struct: * * Finfo_ptr->color_type * * I'm not going to wrap this up in more #ifdef madness, but should * this fail to build on much older libpng versions which we support * (pre 1.3), then I might have to. */ if (png_get_color_type(Fpng_ptr, Finfo_ptr) == FPNG_COLOR_TYPE_RGB_ALPHA) { hasa = 1; } if (png_get_color_type(Fpng_ptr, Finfo_ptr) == FPNG_COLOR_TYPE_GRAY_ALPHA) { hasa = 1; hasg = 1; } if (png_get_color_type(Fpng_ptr, Finfo_ptr) == FPNG_COLOR_TYPE_GRAY) { hasg = 1; } if (hasa) Fpng_set_expand(Fpng_ptr); /* we want ARGB */ /* note form raster: * thanks to mustapha for helping debug this on PPC Linux remotely by * sending across screenshots all the time and me figuring out form them * what the hell was up with the colors * now png loading should work on big endian machines nicely */ #ifdef WORDS_BIGENDIAN Fpng_set_swap_alpha(Fpng_ptr); Fpng_set_filler(Fpng_ptr, 0xff, FPNG_FILLER_BEFORE); #else Fpng_set_bgr(Fpng_ptr); Fpng_set_filler(Fpng_ptr, 0xff, FPNG_FILLER_AFTER); #endif /* 16bit color -> 8bit color */ Fpng_set_strip_16(Fpng_ptr); /* pack all pixels to byte boundaires */ Fpng_set_packing(Fpng_ptr); if (Fpng_get_valid(Fpng_ptr, Finfo_ptr, FPNG_INFO_tRNS)) { Fpng_set_expand(Fpng_ptr); } data = (CARD32 *)safemalloc(w * h * sizeof(CARD32)); lines = (unsigned char **) safemalloc(h * sizeof(unsigned char *)); if (hasg) { Fpng_set_gray_to_rgb(Fpng_ptr); if (Fpng_get_bit_depth(Fpng_ptr, Finfo_ptr) < 8) { Fpng_set_gray_1_2_4_to_8(Fpng_ptr); } } for (i = 0; i < h; i++) { lines[i] = (unsigned char *)data + (i * w * sizeof(CARD32)); } Fpng_read_image(Fpng_ptr, lines); Fpng_read_end(Fpng_ptr, Finfo_ptr); Fpng_destroy_read_struct(&Fpng_ptr, &Finfo_ptr, (png_infopp) NULL); fclose(f); free(lines); *argb_data = data; return True; } /* * * xpm loader * */ static Bool PImageLoadXpm(FIMAGE_CMD_ARGS) { FxpmImage xpm_im; FxpmColor *xpm_color; XColor color; CARD32 *colors; CARD32 *data; char *visual_color; int i; int w; int h; int rc; #ifdef HAVE_SIGACTION struct sigaction defaultHandler; struct sigaction originalHandler; #else RETSIGTYPE (*originalHandler)(int); #endif if (!XpmSupport) { fprintf(stderr, "[PImageLoadXpm]: Tried to load XPM file " "when FVWM has not been compiled with XPm Support.\n"); return False; } memset(&xpm_im, 0, sizeof(FxpmImage)); #ifdef HAVE_SIGACTION sigemptyset(&defaultHandler.sa_mask); defaultHandler.sa_flags = 0; defaultHandler.sa_handler = SIG_DFL; sigaction(SIGCHLD, &defaultHandler, &originalHandler); #else originalHandler = signal(SIGCHLD, SIG_DFL); #endif rc = FxpmReadFileToXpmImage(path, &xpm_im, NULL); #ifdef HAVE_SIGACTION sigaction(SIGCHLD, &originalHandler, NULL); #else signal(SIGCHLD, originalHandler); #endif if (rc != FxpmSuccess) { return False; } if (xpm_im.ncolors <= 0) { FxpmFreeXpmImage(&xpm_im); return False; } colors = (CARD32 *)safemalloc(xpm_im.ncolors * sizeof(CARD32)); for (i=0; i < xpm_im.ncolors; i++) { xpm_color = &xpm_im.colorTable[i]; if (xpm_color->c_color) { visual_color = xpm_color->c_color; } else if (xpm_color->g_color) { visual_color = xpm_color->g_color; } else if (xpm_color->g4_color) { visual_color = xpm_color->g4_color; } else { visual_color = xpm_color->m_color; } if (XParseColor(dpy, Pcmap, visual_color, &color)) { colors[i] = 0xff000000 | ((color.red << 8) & 0xff0000) | ((color.green ) & 0xff00) | ((color.blue >> 8) & 0xff); } else { colors[i] = 0; } } *width = w = xpm_im.width; *height = h = xpm_im.height; data = (CARD32 *)safemalloc(w * h * sizeof(CARD32)); for (i=0; i < w * h; i++) { data[i] = colors[xpm_im.data[i]]; } free(colors); *argb_data = data; return True; } /* * * copy image to server * */ static Pixmap PImageCreatePixmapFromFImage(Display *dpy, Window win, FImage *fimage) { GC gc; Pixmap pixmap; int w; int h; int depth; w = fimage->im->width; h = fimage->im->height; depth = fimage->im->depth; pixmap = XCreatePixmap(dpy, win, w, h, depth); if (depth == Pdepth) { gc = PictureDefaultGC(dpy, win); } else { gc = fvwmlib_XCreateGC(dpy, pixmap, 0, NULL); } FPutFImage(dpy, pixmap, gc, fimage, 0, 0, 0, 0, w, h); if (depth != Pdepth) { XFreeGC(dpy, gc); } return pixmap; } /* ---------------------------- interface functions ------------------------ */ /* * * argb data to pixmaps * */ Bool PImageCreatePixmapFromArgbData( Display *dpy, Window win, CARD32 *data, int start, int width, int height, Pixmap *pixmap, Pixmap *mask, Pixmap *alpha, int *nalloc_pixels, Pixel **alloc_pixels, int *no_limit, FvwmPictureAttributes fpa) { FImage *fim; FImage *m_fim = NULL; FImage *a_fim = NULL; XColor c; int i; int j; int a; PictureImageColorAllocator *pica = NULL; int alpha_limit = PICTURE_ALPHA_LIMIT; int alpha_depth = FRenderGetAlphaDepth(); Bool have_mask = False; Bool have_alpha = False; fim = FCreateFImage( dpy, Pvisual, (fpa.mask & FPAM_MONOCHROME) ? 1 : Pdepth, ZPixmap, width, height); if (!fim) { return False; } if (mask) { m_fim = FCreateFImage( dpy, Pvisual, 1, ZPixmap, width, height); } if (alpha && !(fpa.mask & FPAM_NO_ALPHA) && alpha_depth) { alpha_limit = 0; a_fim = FCreateFImage( dpy, Pvisual, alpha_depth, ZPixmap, width, height); } if (!(fpa.mask & FPAM_MONOCHROME)) { c.flags = DoRed | DoGreen | DoBlue; pica = PictureOpenImageColorAllocator( dpy, Pcmap, width, height, !!(fpa.mask & FPAM_NO_COLOR_LIMIT), !!(fpa.mask & FPAM_NO_ALLOC_PIXELS), !!(fpa.mask & FPAM_DITHER), True); } data += start; for (j = 0; j < height; j++) { for (i = 0; i < width; i++, data++) { a = (*data >> 030) & 0xff; if (a > alpha_limit) { c.red = (*data >> 16) & 0xff; c.green = (*data >> 8) & 0xff; c.blue = (*data ) & 0xff; if (pica) { PictureAllocColorImage( dpy, pica, &c, i, j); XPutPixel(fim->im, i, j, c.pixel); } /* Brightness threshold */ else if ((0x99 * c.red + 0x12D * c.green + 0x3A * c.blue) >> 16) { XPutPixel(fim->im, i, j, 1); } else { XPutPixel(fim->im, i, j, 0); } if (m_fim) { XPutPixel(m_fim->im, i, j, 1); } } else if (m_fim != NULL) { XPutPixel(m_fim->im, i, j, 0); have_mask = True; } if (a_fim != NULL) { XPutPixel(a_fim->im, i, j, a); if (a > 0 && a < 0xff) { have_alpha = True; } } } } if (pica) { PictureCloseImageColorAllocator( dpy, pica, nalloc_pixels, alloc_pixels, no_limit); } *pixmap = PImageCreatePixmapFromFImage(dpy, win, fim); if (have_alpha) { *alpha = PImageCreatePixmapFromFImage(dpy, win, a_fim); } else if (have_mask) { *mask = PImageCreatePixmapFromFImage(dpy, win, m_fim); } FDestroyFImage(dpy, fim); if (m_fim) { FDestroyFImage(dpy, m_fim); } if (a_fim) { FDestroyFImage(dpy, a_fim); } return True; } /* * * the images loaders * */ Bool PImageLoadPixmapFromFile( Display *dpy, Window win, char *path, Pixmap *pixmap, Pixmap *mask, Pixmap *alpha, int *width, int *height, int *depth, int *nalloc_pixels, Pixel **alloc_pixels, int *no_limit, FvwmPictureAttributes fpa) { CARD32 *data; if (PImageLoadArgbDataFromFile(dpy, path, &data, width, height)) { *depth = (fpa.mask & FPAM_MONOCHROME) ? 1 : Pdepth; if (PImageCreatePixmapFromArgbData( dpy, win, data, 0, *width, *height, pixmap, mask, alpha, nalloc_pixels, alloc_pixels, no_limit, fpa)) { free(data); return True; } free(data); } /* Bitmap fallback */ else if ( XReadBitmapFile( dpy, win, path, (unsigned int *)width, (unsigned int *)height, pixmap, NULL, NULL) == BitmapSuccess) { *depth = 1; *mask = None; return True; } pixmap = None; mask = None; alpha = None; *width = *height = *depth = 0; if (nalloc_pixels != NULL) { *nalloc_pixels = 0; } if (alloc_pixels != NULL) { *alloc_pixels = NULL; } return False; } FvwmPicture *PImageLoadFvwmPictureFromFile( Display *dpy, Window win, char *path, FvwmPictureAttributes fpa) { FvwmPicture *p; Pixmap pixmap = None; Pixmap mask = None; Pixmap alpha = None; int width = 0, height = 0; int depth = 0, no_limit; int nalloc_pixels = 0; Pixel *alloc_pixels = NULL; char *real_path; /* Remove any svg rendering options from real_path */ if (USE_SVG && *path == ':' && (real_path = strchr(path + 1, ':'))) { real_path ++; } else { real_path = path; } if (!PImageLoadPixmapFromFile( dpy, win, path, &pixmap, &mask, &alpha, &width, &height, &depth, &nalloc_pixels, &alloc_pixels, &no_limit, fpa)) { return NULL; } p = (FvwmPicture*)safemalloc(sizeof(FvwmPicture)); memset(p, 0, sizeof(FvwmPicture)); p->count = 1; p->name = path; p->fpa_mask = fpa.mask; p->next = NULL; setFileStamp(&p->stamp, real_path); p->picture = pixmap; p->mask = mask; p->alpha = alpha; p->width = width; p->height = height; p->depth = depth; p->nalloc_pixels = nalloc_pixels; p->alloc_pixels = alloc_pixels; p->no_limit = no_limit; return p; } Cursor PImageLoadCursorFromFile( Display *dpy, Window win, char *path, int x_hot, int y_hot) { Cursor cursor = 0; CARD32 *data; int width; int height; int i; FcursorImages *fcis; FcursorImage *fci; /* First try the Xcursor loader (animated cursors) */ if ((fcis = FcursorFilenameLoadImages( path, FcursorGetDefaultSize(dpy)))) { for (i = 0; i < fcis->nimage; i++) { if (x_hot < fcis->images[i]->width && x_hot >= 0 && y_hot < fcis->images[i]->height && y_hot >= 0) { fcis->images[i]->xhot = x_hot; fcis->images[i]->yhot = y_hot; } } cursor = FcursorImagesLoadCursor(dpy, fcis); FcursorImagesDestroy(fcis); } /* Get cursor data from the regular image loader */ else if (PImageLoadArgbDataFromFile(dpy, path, &data, &width, &height)) { Pixmap src; Pixmap msk = None; FvwmPictureAttributes fpa; fpa.mask = FPAM_NO_ALPHA | FPAM_MONOCHROME; /* Adjust the hot-spot if necessary */ if ( x_hot < 0 || x_hot >= width || y_hot < 0 || y_hot >= height) { FxpmImage xpm_im; FxpmInfo xpm_info; memset(&xpm_im, 0, sizeof(FxpmImage)); memset(&xpm_info, 0, sizeof(FxpmInfo)); if (FxpmReadFileToXpmImage(path, &xpm_im, &xpm_info) == FxpmSuccess) { if (xpm_info.valuemask & FxpmHotspot) { x_hot = xpm_info.x_hotspot; y_hot = xpm_info.y_hotspot; } FxpmFreeXpmImage(&xpm_im); FxpmFreeXpmInfo(&xpm_info); } if (x_hot < 0 || x_hot >= width) { x_hot = width / 2; } if (y_hot < 0 || y_hot >= height) { y_hot = height / 2; } } /* Use the Xcursor library to create the argb cursor */ if ((fci = FcursorImageCreate(width, height))) { unsigned char alpha; unsigned char red; unsigned char green; unsigned char blue; /* Xcursor expects alpha prescaled RGB values */ for (i = 0; i < width * height; i++) { alpha = ((data[i] >> 24) & 0xff); red = ((data[i] >> 16) & 0xff) * alpha/0xff; green = ((data[i] >> 8) & 0xff) * alpha/0xff; blue = ((data[i] ) & 0xff) * alpha/0xff; data[i] = (alpha << 24) | (red << 16) | (green << 8) | blue; } fci->xhot = x_hot; fci->yhot = y_hot; fci->delay = 0; fci->pixels = (FcursorPixel *)data; cursor = FcursorImageLoadCursor(dpy, fci); FcursorImageDestroy(fci); } /* Create monochrome cursor from argb data */ else if (PImageCreatePixmapFromArgbData( dpy, win, data, 0, width, height, &src, &msk, 0, 0, 0, 0, fpa)) { XColor c[2]; c[0].pixel = GetColor(DEFAULT_CURSOR_FORE_COLOR); c[1].pixel = GetColor(DEFAULT_CURSOR_BACK_COLOR); XQueryColors(dpy, Pcmap, c, 2); cursor = XCreatePixmapCursor( dpy, src, msk, &(c[0]), &(c[1]), x_hot, y_hot); XFreePixmap(dpy, src); XFreePixmap(dpy, msk); } free(data); } return cursor; } /* FIXME: Use color limit */ Bool PImageLoadPixmapFromXpmData( Display *dpy, Window win, int color_limit, char **data, Pixmap *pixmap, Pixmap *mask, int *width, int *height, int *depth) { FxpmAttributes xpm_attributes; if (!XpmSupport) { return False; } xpm_attributes.valuemask = FxpmCloseness | FxpmExtensions | FxpmVisual | FxpmColormap | FxpmDepth; xpm_attributes.closeness = 40000; xpm_attributes.visual = Pvisual; xpm_attributes.colormap = Pcmap; xpm_attributes.depth = Pdepth; /* suppress compiler warning if xpm library is not compiled in */ xpm_attributes.width = 0; xpm_attributes.height = 0; if ( FxpmCreatePixmapFromData( dpy, win, data, pixmap, mask, &xpm_attributes) != FxpmSuccess) { return False; } *width = xpm_attributes.width; *height = xpm_attributes.height; *depth = Pdepth; return True; } fvwm-2.7.0/libs/PictureImageLoader.h0000644000175000017500000000373014147024700014231 00000000000000/* -*-c-*- */ /* Copyright (C) 2002 Olivier Chapuis */ #ifndef PICTURE_IMAGE_LOADER_H #define PICTURE_IMAGE_LOADER_H /* ---------------------------- included header files ---------------------- */ #include /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ /* ---------------------------- interface functions ------------------------ */ /* * PImageCreatePixmapFromArgbData * * Create a pixmap with its mask and alpha channel from ARGB data. * */ Bool PImageCreatePixmapFromArgbData( Display *dpy, Window win, CARD32 *data, int start, int width, int height, Pixmap *pixmap, Pixmap *mask, Pixmap *alpha, int *nalloc_pixels, Pixel **alloc_pixels, int *no_limit, FvwmPictureAttributes fpa); /* * PImageLoadPixmapFromFile * * Create a pixmap with its mask and alpha channel from a file. * */ Bool PImageLoadPixmapFromFile( Display *dpy, Window win, char *file, Pixmap *pixmap, Pixmap *mask, Pixmap *alpha, int *width, int *height, int *depth, int *nalloc_pixels, Pixel **alloc_pixels, int *no_limit, FvwmPictureAttributes fpa); /* * PImageLoadPixmapFromFile * * Create a FvwmPicture from a file. * */ FvwmPicture *PImageLoadFvwmPictureFromFile( Display *dpy, Window win, char *path, FvwmPictureAttributes fpa); /* * PImageLoadPixmapFromFile * * Create a cursor from a file. * */ Cursor PImageLoadCursorFromFile( Display *dpy, Window win, char *path, int x_hot, int y_hot); /* * PImageLoadPixmapFromFile * * Create a pixmap with its mask from xpm data. * */ Bool PImageLoadPixmapFromXpmData( Display *dpy, Window win, int color_limit, char **data, Pixmap *pixmap, Pixmap *mask, int *width, int *height, int *depth); #endif /* PICTURE_IMAGE_LOADER_H */ fvwm-2.7.0/libs/FRenderInit.h0000644000175000017500000000064014147024676012706 00000000000000/* -*-c-*- */ /* Copyright (C) 2002 Olivier Chapuis */ /* ---------------------------- included header files ---------------------- */ #ifndef F_RENDER_INIT_H #define F_RENDER_INIT_H void FRenderInit(Display *dpy); int FRenderGetAlphaDepth(void); int FRenderGetErrorCodeBase(void); int FRenderGetMajorOpCode(void); Bool FRenderGetErrorText(int code, char *msg); Bool FRenderGetExtensionSupported(void); #endif fvwm-2.7.0/libs/FRenderInit.c0000644000175000017500000000620614147024700012671 00000000000000/* -*-c-*- */ /* Copyright (C) 2002 Olivier Chapuis */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include "fvwmlib.h" #include "PictureBase.h" #include "FRenderInit.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ Bool FRenderExtensionSupported = False; int FRenderErrorBase = -10000; int FRenderMajorOpCode = -10000; int FRenderAlphaDepth = 0; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ void FRenderInit(Display *dpy) { int event_basep; FRenderAlphaDepth = 8; if (!XRenderSupport || !(FRenderExtensionSupported = XQueryExtension( dpy, "RENDER", &FRenderMajorOpCode, &event_basep, &FRenderErrorBase))) { int *pmf = NULL; int i,n; int alpha_depth = 0; FRenderErrorBase = -10000; FRenderMajorOpCode = -10000; FRenderExtensionSupported = 0; pmf = XListDepths(dpy, DefaultScreen(dpy), &n); if (pmf) { i = 0; while(i < n) { if (pmf[i] == 8) { alpha_depth = 8; i = n-1; } else if (pmf[i] >= 8 && (pmf[i] < alpha_depth || alpha_depth == 0)) { alpha_depth = pmf[i]; } i++; } XFree(pmf); } FRenderAlphaDepth = alpha_depth; } } int FRenderGetErrorCodeBase(void) { return FRenderErrorBase; } int FRenderGetMajorOpCode(void) { return FRenderMajorOpCode; } Bool FRenderGetExtensionSupported(void) { return FRenderExtensionSupported; } int FRenderGetAlphaDepth(void) { return FRenderAlphaDepth; } Bool FRenderGetErrorText(int code, char *msg) { if (XRenderSupport) { static char *error_names[] = { "BadPictFormat", "BadPicture", "BadPictOp", "BadGlyphSet", "BadGlyph" }; if (code >= FRenderErrorBase && code <= FRenderErrorBase + (sizeof(error_names) / sizeof(char *)) -1) { sprintf(msg, "%s\n", error_names[code - FRenderErrorBase]); return 1; } } return 0; } fvwm-2.7.0/libs/timeout.h0000644000175000017500000000205014147024676012220 00000000000000/* -*-c-*- */ #ifndef TIMEOUT_H #define TIMEOUT_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ #define TIMEOUT_MAX_TIMEOUTS 32 /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ typedef int timeout_time_t; typedef unsigned int timeout_mask_t; typedef struct { int n_timeouts; timeout_time_t *timeouts; } timeout_t; /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ timeout_t *timeout_create( int n_timeouts); void timeout_destroy( timeout_t *to); timeout_mask_t timeout_tick( timeout_t *to, timeout_time_t n_ticks); void timeout_rewind( timeout_t *to, timeout_mask_t mask, timeout_time_t ticks_before_alarm); #endif /* TIMEOUT_H */ fvwm-2.7.0/libs/safemalloc.h0000644000175000017500000000044314147024676012644 00000000000000/* -*-c-*- */ /* * * Procedure: * safe?alloc - mallocs/callocs specified space or exits if there's a * problem * */ char *safemalloc(int length); char *safecalloc(int num, int length); char *saferealloc(char *ptr, int length); char *safestrdup(const char *s); fvwm-2.7.0/libs/Grab.h0000644000175000017500000000051314147024676011407 00000000000000/* -*-c-*- */ /* ** MyXGrabServer & MyXUngrabServer - to handle nested grab server calls */ #include void MyXGrabServer(Display *disp); void MyXUngrabServer(Display *disp); void MyXUngrabKeyboard(Display *disp); void MyXGrabKeyboard(Display *disp); void MyXGrabKey(Display *disp); void MyXUngrabKey(Display *disp); fvwm-2.7.0/libs/Cursor.h0000644000175000017500000000005714147024700012000 00000000000000int fvwmCursorNameToIndex (char *cursor_name); fvwm-2.7.0/libs/wcontext.c0000644000175000017500000000547614147024700012403 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include "libs/charmap.h" #include "libs/wcontext.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* The keys must be in lower case! Put more common contexts toward the front. */ charmap_t win_contexts[] = { {'r', C_ROOT}, {'t', C_TITLE}, {'w', C_WINDOW}, {'f', C_FRAME}, {'i', C_ICON}, {'a', C_ALL}, {'1', C_L1}, {'2', C_R1}, {'3', C_L2}, {'4', C_R2}, {'5', C_L3}, {'6', C_R3}, {'7', C_L4}, {'8', C_R4}, {'9', C_L5}, {'0', C_R5}, {'d', C_EWMH_DESKTOP}, {'<', C_F_TOPLEFT}, {'^', C_F_TOPRIGHT}, {'>', C_F_BOTTOMRIGHT}, {'v', C_F_BOTTOMLEFT}, {'s', C_SIDEBAR}, {'[', C_SB_LEFT}, {']', C_SB_RIGHT}, {'-', C_SB_TOP}, {'_', C_SB_BOTTOM}, {'m', C_MENU}, {'p', C_PLACEMENT}, {0, 0} }; /* ---------------------------- local functions ---------------------------- */ /* ---------------------------- interface functions ------------------------ */ /* Converts the input string into a mask with bits for the contexts */ int wcontext_string_to_wcontext(char *in_context, int *out_context_mask) { int error; error = charmap_string_to_mask( out_context_mask, in_context, win_contexts, "bad context"); return error; } char wcontext_wcontext_to_char(win_context_t wcontext) { char c; c = charmap_mask_to_char((int)wcontext, win_contexts); return c; } win_context_t wcontext_merge_border_wcontext(win_context_t wcontext) { if (wcontext & C_FRAME) { wcontext |= C_FRAME; } if (wcontext & C_SIDEBAR) { wcontext |= C_SIDEBAR; } return wcontext; } fvwm-2.7.0/libs/PictureGraphics.h0000644000175000017500000001170214147024700013616 00000000000000/* -*-c-*- */ /* Copyright (C) 2002 Olivier Chapuis */ #ifndef F_PICTURE_GRAPHICS_H #define F_PICTURE_GRAPHICS_H /* * * dpy: Specifies the connection to the X server. * pixmap: Source pixmap. * mask: Source mask (can be None). * alpha: Source alpha chanel (can be None). * depth: depth of the pixmap (1 or Pdepth). * d: Destination drawable which should be of depth Pdepth. * GC gc: Specifies the a visual GC. * src_x,src_y: Specify the x and y coordinates, which are relative to the * origin of the source pixmap, mask and alpha of the rectangle * which is copied. * src_w,src_h: Width and height of the source rectangle relatively to the * src_x and src_y. * dest_x,dest_y: Specify the x and y coordinates of the destination rectangle, * which are relative to the origin of the drawable d. * */ /* return a pixmap of depth depth which is the copy of the src pixmap of depth * 1 using the gc for the bg and fg colors */ Pixmap PictureBitmapToPixmap( Display *dpy, Window win, Pixmap src, int depth, GC gc, int src_x, int src_y, int src_w, int src_h); /* * PGraphicsRenderPixmaps * * PGraphicsRenderPixmaps copies a rectangle, the src, constituted by a pixmap * with its mask, alpha channel, and rendering attributes to a drawable at a * given position. * */ void PGraphicsRenderPixmaps( Display *dpy, Window win, Pixmap pixmap, Pixmap mask, Pixmap alpha, int depth, FvwmRenderAttributes *fra, Drawable d, GC gc, GC mono_gc, GC alpha_gc, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, int dest_w, int dest_h, int do_repeat); /* * PGraphicsRenderPicture * * PGraphicsRenderPicture copies a rectangle, the src, constituted by a picture * and its rendering attributes to a drawable at a given position. * * */ void PGraphicsRenderPicture( Display *dpy, Window win, FvwmPicture *p, FvwmRenderAttributes *fra, Drawable d, GC gc, GC mono_gc, GC alpha_gc, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, int dest_w, int dest_h, int do_repeat); /* * PGraphicsCopyPixmaps * * PGraphicsCopyPixmaps copies a rectangle constituted by a pixmap with its * mask and alpha channel to a drawable at a given position. * * * The clip_mask, clip_x_origin and clip_y_origin value of the gc are * modified in this function: the clip_mask is set to mask and reseted to None, * clip_x_origin and clip_y_origin are set to src_x and src_y. * The background and foreground value of the gc is important when you render * a bitmap. If the gc is set to None the function create and destroy a gc for * its use. * */ void PGraphicsCopyPixmaps( Display *dpy, Pixmap pixmap, Pixmap mask, Pixmap alpha, int depth, Drawable d, GC gc, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y); /* * PGraphicsCopyFvwmPicture * * PGraphicsCopyFvwmPicture copies a rectangle constituted by an FvwmPicture * to a drawable at a given position. It is similar to PGraphicsCopyPixmaps * and the same remarks are valids. The only difference is that the source * rectangle is given by the FvwmPicture p (which contains the pixmap, the * mask, the alpha and the depth). * */ void PGraphicsCopyFvwmPicture( Display *dpy, FvwmPicture *p, Drawable d, GC gc, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y); /* * PGraphicsTileRectangle * * This function is similar to PGraphicsCopyPixmaps. It tiles the rectangle of * the drawable d defined with coordinates dest_x, dest_y, dest_w, dest_h with * the rectangle composed by the pixmap, its mask and its alpha channel. * */ void PGraphicsTileRectangle( Display *dpy, Window win, Pixmap pixmap, Pixmap shape, Pixmap alpha, int depth, Drawable d, GC gc, GC mono_gc, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, int dest_w, int dest_h); FvwmPicture *PGraphicsCreateStretchPicture( Display *dpy, Window win, FvwmPicture *src, int dest_width, int dest_height, GC gc, GC mono_gc, GC alpha_gc); FvwmPicture *PGraphicsCreateTiledPicture( Display *dpy, Window win, FvwmPicture *src, int dest_width, int dest_height, GC gc, GC mono_gc, GC alpha_gc); Pixmap PGraphicsCreateTransparency( Display *dpy, Window win, FvwmRenderAttributes *fra, GC gc, int x, int y, int width, int height, Bool parent_relative); void PGraphicsTintRectangle( Display *dpy, Window win, Pixel tint, int tint_percent, Drawable dest, Bool dest_is_a_window, GC gc, GC mono_gc, GC alpha_gc, int dest_x, int dest_y, int dest_w, int dest_h); /* never used ! */ Pixmap PGraphicsCreateDitherPixmap( Display *dpy, Window win, Drawable src, Pixmap mask, int depth, GC gc, int in_width, int in_height, int out_width, int out_height); #endif fvwm-2.7.0/libs/Fft.h0000644000175000017500000004615714147024700011255 00000000000000/* -*-c-*- */ #ifndef FFT_H #define FFT_H /* * Note: This "warper" is far from being complete! if you need something * in Xft or Xft + fontconfig (Fc for short) (aka Xft2) not already defined * you must add the corresponding Fft* functions/types (2 or 3 times). * */ /* ---------------------------- included header files ---------------------- */ /* no compat to avoid problems in the future */ #define _XFT_NO_COMPAT_ 1 #ifdef HAVE_XFT #define Picture XRenderPicture #include #undef Picture #endif #include "FRender.h" /* ---------------------------- global definitions ------------------------- */ #ifdef HAVE_XFT #define FftSupport 1 #ifdef HAVE_XFT_UTF8 #define FftUtf8Support 1 #else #define FftUtf8Support 0 #endif #ifdef HAVE_XFT2 #define FftSupportUseXft2 1 #else #define FftSupportUseXft2 0 #endif #else #define FftSupport 0 #define FftUtf8Support 0 #define FftSupportUseXft2 0 #endif /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ #if FftSupport /* Fc (fontconfig) stuff */ #if FftSupportUseXft2 typedef FcChar8 FftChar8; typedef FcChar16 FftChar16; typedef FcChar32 FftChar32; typedef FcBool FftBool; typedef FcType FftType; typedef FcMatrix FftMatrix; typedef FcValue FftValue; typedef FcPattern FftPattern; typedef FcFontSet FftFontSet; typedef FcObjectSet FftObjectSet; #if 1 /* FftResult must be FcResult for gcc 3.4 not to warn of incompatible * pointer type */ typedef FcResult FftResult; #define FftResultMatch FcResultMatch #define FftResultNoMatch FcResultNoMatch #define FftResultTypeMismatch FcResultTypeMismatch #define FftFftResultNoId FcResultNoId #else typedef enum _FftResult { FftResultMatch = FcResultMatch, FftResultNoMatch = FcResultNoMatch, FftResultTypeMismatch = FcResultTypeMismatch, FftFftResultNoId = FcResultNoId } FftResult; #endif /* XftValue and are different in Xft+Fc and Xft 1 */ typedef struct _Xft1Value { FftType type; union { char *s; int i; Bool b; double d; FftMatrix *m; } u; } Xft1Value; typedef Xft1Value Fft1Value; /* no value list in Xft+Fc */ typedef struct _XftValueList { struct _XftValueList *next; Fft1Value value; } XftValueList; typedef XftValueList FftValueList; /* no XftPatternElt in Xft+Fc */ typedef struct { const char *object; FftValueList *values; } XftPatternElt; typedef XftPatternElt FftPatternElt; /* XftPattern and FcPattern are different */ typedef struct _Xft1Pattern { int num; int size; FftPatternElt *elts; } Fft1Pattern; #else /* !FftSupportUseXft2 */ typedef XftChar8 FftChar8; typedef XftChar16 FftChar16; typedef XftChar32 FftChar32; typedef XftType FftType; typedef XftMatrix FftMatrix; typedef XftPatternElt FftPatternElt; typedef XftFontSet FftFontSet; typedef XftObjectSet FftObjectSet; typedef XftValue FftValue; typedef XftPattern FftPattern; typedef XftValue Fft1Value; typedef XftPattern Fft1Pattern; typedef enum _FftResult { FftResultMatch = XftResultMatch, FftResultNoMatch = XftResultNoMatch, FftResultTypeMismatch = XftResultTypeMismatch, FftFftResultNoId = XftResultNoId } FftResult; #endif /* FftSupportUseXft2 */ /* Xft stuff (common) */ typedef XftDraw FftDraw; typedef XftFont FftFont; typedef XftColor FftColor; #if FftSupportUseXft2 /* XftFont are != in Xft+Fc and Xft */ typedef struct _Fft1Font { int ascent; int descent; int height; int max_advance_width; Bool core; Fft1Pattern *pattern; union { struct { XFontStruct *font; } core; struct { void *font; } ft; } u; } Fft1Font; #else typedef XftFont Fft1Font; #endif #else typedef unsigned char FftChar8; typedef unsigned short FftChar16; typedef unsigned int FftChar32; typedef int FftType; typedef struct { double xx, xy, yx, yy; } FftMatrix; typedef enum _FftResult { FftResultMatch = 0, FftResultNoMatch = 1, FftResultTypeMismatch = 2, FftFftResultNoId = 3 } FftResult; typedef struct { FftType type; union { char *s; int i; Bool b; double d; } u; } XftValue; typedef XftValue FftValue; typedef struct _XftValueList { struct _XftValueList *next; FftValue value; } XftValueList; typedef XftValueList FftValueList; typedef struct { const char *object; FftValueList *values; } XftPatternElt; typedef XftPatternElt FftPatternElt; typedef struct { int num; int size; FftPatternElt *elts; } XftPattern; typedef XftPattern FftPattern; typedef void FftFontSet; typedef void FftFontVoid; typedef void FftDraw; typedef struct { int ascent; int descent; int height; int max_advance_width; Bool core; FftPattern *pattern; union { struct { XFontStruct *font; } core; struct { void *font; } ft; } u; } XftFont; typedef XftFont FftFont; typedef struct { unsigned long pixel; FRenderColor color; } XftColor; typedef XftColor FftColor; typedef void FftObjectSet; /* XftValue are different in Xft+Fc and Xft 1 */ typedef struct _Xft1Value { FftType type; union { char *s; int i; Bool b; double d; FftMatrix *m; } u; } Xft1Value; typedef Xft1Value Fft1Value; /* XftPattern and XftFont are different in Xft+Fc and Xft 1 */ typedef struct _Xft1Pattern { int num; int size; FftPatternElt *elts; } Fft1Pattern; typedef struct _Fft1Font { int ascent; int descent; int height; int max_advance_width; Bool core; Fft1Pattern *pattern; union { struct { XFontStruct *font; } core; struct { void *font; } ft; } u; } Fft1Font; #endif /* * Fvwm Xft font structure */ typedef struct { FftFont *fftfont; FftFont *fftfont_rotated_90; FftFont *fftfont_rotated_180; FftFont *fftfont_rotated_270; char *encoding; char *str_encoding; } FftFontType; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ void FftPDumyFunc(void); /* ---------------------------- global definitions ------------------------- */ #if FftSupport /* Fc stuff */ #if FftSupportUseXft2 #define FFT_FAMILY FC_FAMILY #define FFT_STYLE FC_STYLE #define FFT_SLANT FC_SLANT #define FFT_WEIGHT FC_WEIGHT #define FFT_SIZE FC_SIZE #define FFT_PIXEL_SIZE FC_PIXEL_SIZE #define FFT_SPACING FC_SPACING #define FFT_FOUNDRY FC_FOUNDRY #define FFT_CORE FC_CORE #define FFT_ANTIALIAS FC_ANTIALIAS #define FFT_XLFD FC_XLFD #define FFT_FILE FC_FILE #define FFT_INDEX FC_INDEX #define FFT_RASTERIZER FC_RASTERIZER #define FFT_OUTLINE FC_OUTLINE #define FFT_SCALABLE FC_SCALABLE #define FFT_RGBA FC_RGBA #define FFT_SCALE FC_SCALE #define FFT_RENDER FC_RENDER #define FFT_CHAR_WIDTH FC_CHAR_WIDTH #define FFT_CHAR_HEIGHT FC_CHAR_HEIGHT #define FFT_MATRIX FC_MATRIX #define FFT_WEIGHT_LIGHT FC_WEIGHT_LIGHT #define FFT_WEIGHT_MEDIUM FC_WEIGHT_MEDIUM #define FFT_WEIGHT_DEMIBOLD FC_WEIGHT_DEMIBOLD #define FFT_WEIGHT_BOLD FC_WEIGHT_BOLD #define FFT_WEIGHT_BLACK FC_WEIGHT_BLACK #define FFT_SLANT_ROMAN FC_SLANT_ROMAN #define FFT_SLANT_ITALIC FC_SLANT_ITALIC #define FFT_SLANT_OBLIQUE FC_SLANT_OBLIQUE #define FFT_PROPORTIONAL FC_PROPORTIONAL #define FFT_MONO FC_MONO #define FFT_CHARCELL FC_CHARCELL #define FFT_RGBA_NONE FC_RGBA_NONE #define FFT_RGBA_RGB FC_RGBA_RGB #define FFT_RGBA_BGR FC_RGBA_BGR /* new in Fc */ #define FFT_HINTING FC_HINTING #define FFT_VERTICAL_LAYOUT FC_VERTICAL_LAYOUT #define FFT_AUTOHINT FC_AUTOHINT #define FFT_GLOBAL_ADVANCE FC_GLOBAL_ADVANCE #define FFT_SOURCE FC_SOURCE #define FFT_CHARSET FC_CHARSET #define FFT_LANG FC_LANG #define FFT_DIR_CACHE_FILE FC_DIR_CACHE_FILE #define FFT_USER_CACHE_FILE FC_USER_CACHE_FILE /* skip all the FC_LANG_* OS/2 CodePageRange bits */ /* not in Fc */ #define FFT_ENCODING "encoding" #else /* !FftSupportUseXft2 */ #define FFT_FAMILY XFT_FAMILY #define FFT_STYLE XFT_STYLE #define FFT_SLANT XFT_SLANT #define FFT_WEIGHT XFT_WEIGHT #define FFT_SIZE XFT_SIZE #define FFT_PIXEL_SIZE XFT_PIXEL_SIZE #define FFT_ENCODING XFT_ENCODING #define FFT_SPACING XFT_SPACING #define FFT_FOUNDRY XFT_FOUNDRY #define FFT_CORE XFT_CORE #define FFT_ANTIALIAS XFT_ANTIALIAS #define FFT_XLFD XFT_XLFD #define FFT_FILE XFT_FILE #define FFT_INDEX XFT_INDEX #define FFT_RASTERIZER XFT_RASTERIZER #define FFT_OUTLINE XFT_OUTLINE #define FFT_SCALABLE XFT_SCALABLE #define FFT_RGBA XFT_RGBA #define FFT_SCALE XFT_SCALE #define FFT_RENDER XFT_RENDER #define FFT_CHAR_WIDTH XFT_CHAR_WIDTH #define FFT_CHAR_HEIGHT XFT_CHAR_HEIGHT #define FFT_MATRIX XFT_MATRIX #define FFT_WEIGHT_LIGHT XFT_WEIGHT_LIGHT #define FFT_WEIGHT_MEDIUM XFT_WEIGHT_MEDIUM #define FFT_WEIGHT_DEMIBOLD XFT_WEIGHT_DEMIBOLD #define FFT_WEIGHT_BOLD XFT_WEIGHT_BOLD #define FFT_WEIGHT_BLACK XFT_WEIGHT_BLACK #define FFT_SLANT_ROMAN XFT_SLANT_ROMAN #define FFT_SLANT_ITALIC XFT_SLANT_ITALIC #define FFT_SLANT_OBLIQUE XFT_SLANT_OBLIQUE #define FFT_PROPORTIONAL XFT_PROPORTIONAL #define FFT_MONO XFT_MONO #define FFT_CHARCELL XFT_CHARCELL #define FFT_RGBA_NONE XFT_RGBA_NONE #define FFT_RGBA_RGB XFT_RGBA_RGB #define FFT_RGBA_BGR XFT_RGBA_BGR #define FFT_RGBA_VRGB XFT_RGBA_VRGB #define FFT_RGBA_VBGR XFT_RGBA_VBGR /* new in Fc */ #define FFT_HINTING "" #define FFT_VERTICAL_LAYOUT "" #define FFT_AUTOHINT "" #define FFT_GLOBAL_ADVANCE "" #define FFT_SOURCE "" #define FFT_CHARSET "" #define FFT_LANG "" #define FFT_DIR_CACHE_FILE "" #define FFT_USER_CACHE_FILE "" /* skip all the FC_LANG_* OS/2 CodePageRange bits */ /* not in Fc */ #define FFT_ENCODING XFT_ENCODING #endif /* !FftSupportUseXft2 */ /* Fc stuff */ #if FftSupportUseXft2 #define FftConfigSubstitute(a) FcConfigSubstitute(a) #define FftValuePrint(a) FcValuePrint(a) #define FftPatternPrint(a) FcPatternPrint(a) #define FftFontSetPrint(a) FcFontSetPrint(a) #define FftGlyphExists(a,b,c) FcGlyphExists(a,b,c) #define FftObjectSetCreate() FcObjectSetCreate() #define FftObjectSetAdd(a,b) FcObjectSetAdd(a,b) #define FftObjectSetDestroy(a) FcObjectSetDestroy(a) #define FftObjectSetVaBuild(a,b) FcObjectSetVaBuild(a,b) #define FftListFontsPatternObjects(a,b,c,d) FcListFontsPatternObjects(a,b,c,d) #define FftFontSetMatch(a,b,c,d) FcFontSetMatch(a,b,c,d) #define FftPatternCreate() FcPatternCreate() #define FftPatternDuplicate(a) FcPatternDuplicate(a) #define FftValueDestroy(a) FcValueDestroy(a) #define FftValueListDestroy(a) FcValueListDestroy(a) #define FftPatternDestroy(a) FcPatternDestroy(a) #define FftPatternFind(a,b,c) FcPatternFind(a,b,c) #define FftPatternAdd(a,b,c,d) FcPatternAdd(a,b,c,d) #define FftPatternGet(a,b,c,d) FcPatternGet(a,b,c,d) #define FftPatternDel(a,b) FcPatternDel(a,b) #define FftPatternAddInteger(a,b,c) FcPatternAddInteger(a,b,c) #define FftPatternAddDouble(a,b,c) FcPatternAddDouble(a,b,c) #define FftPatternAddString(a,b,c) FcPatternAddString(a,b,c) #define FftPatternAddBool(a,b,c) FcPatternAddBool(a,b,c) #define FftPatternAddMatrix(a,b,c) FcPatternAddMatrix(a,b,c) #define FftPatternGetInteger(a,b,c,d) FcPatternGetInteger(a,b,c,d) #define FftPatternGetDouble(a,b,c,d) FcPatternGetDouble(a,b,c,d) #define FftPatternGetString(a,b,c,d) FcPatternGetString(a,b,c,d) #define FftPatternGetBool(a,b,c,d) FcPatternGetBool(a,b,c,d) #define FftPatternGetMatrix(a,b,c,d) FcPatternGetMatrix(a,b,c,d) #define FftPatternVaBuild(a,b) FcPatternVaBuild(a,b) #else /* !FftSupportUseXft2 */ #define FftConfigSubstitute(a) XftConfigSubstitute(a) #define FftValuePrint(a) XftValuePrint(a) #define FftPatternPrint(a) XftPatternPrint(a) #define FftFontSetPrint(a) XftFontSetPrint(a) #define FftGlyphExists(a,b,c) XftGlyphExists(a,b,c) #define FftObjectSetCreate() XftObjectSetCreate() #define FftObjectSetAdd(a,b) XftObjectSetAdd(a,b) #define FftObjectSetDestroy(a) XftObjectSetDestroy(a) #define FftObjectSetVaBuild(a,b) XftObjectSetVaBuild(a,b) #define FftListFontsPatternObjects(a,b,c,d) XftListFontsPatternObjects(a,b,c,d) #define FftFontSetMatch(a,b,c,d) XftFontSetMatch(a,b,c,d) #define FftPatternCreate() XftPatternCreate() #define FftPatternDuplicate(a) XftPatternDuplicate(a) #define FftValueDestroy(a) XftValueDestroy(a) #define FftValueListDestroy(a) XftValueListDestroy(a) #define FftPatternDestroy(a) XftPatternDestroy(a) #define FftPatternFind(a,b,c) XftPatternFind(a,b,c) #define FftPatternAdd(a,b,c,d) XftPatternAdd(a,b,c,d) #define FftPatternGet(a,b,c,d) XftPatternGet(a,b,c,d) #define FftPatternDel(a,b) XftPatternDel(a,b) #define FftPatternAddInteger(a,b,c) XftPatternAddInteger(a,b,c) #define FftPatternAddDouble(a,b,c) XftPatternAddDouble(a,b,c) #define FftPatternAddString(a,b,c) XftPatternAddString(a,b,c) #define FftPatternAddBool(a,b,c) XftPatternAddBool(a,b,c) #define FftPatternAddMatrix(a,b,c) XftPatternAddMatrix(a,b,c) #define FftPatternGetInteger(a,b,c,d) XftPatternGetInteger(a,b,c,d) #define FftPatternGetDouble(a,b,c,d) XftPatternGetDouble(a,b,c,d) #define FftPatternGetString(a,b,c,d) XftPatternGetString(a,b,c,d) #define FftPatternGetBool(a,b,c,d) XftPatternGetBool(a,b,c,d) #define FftPatternGetMatrix(a,b,c,d) XftPatternGetMatrix(a,b,c,d) #define FftPatternVaBuild(a,b) XftPatternVaBuild(a,b) #endif /* !XftSupportUseXft2 */ /* Xft stuff */ #define FftColorAllocName(a,b,c,d,e) XftColorAllocName(a,b,c,d,e) #define FftColorAllocValue(a,b,c,d,e) XftColorAllocValue(a,b,c,d,e) #define FftColorFree(a,b,c,d) XftColorFree(a,b,c,d) #define FftDefaultHasRender(a) XftDefaultHasRender(a) #define FftDefaultSet(a,b) XftDefaultSet(a,b) #define FftDefaultSubstitute(a,b,c) XftDefaultSubstitute(a,b,c) #define FftDrawCreate(a,b,c,d) XftDrawCreate(a,b,c,d) #define FftDrawCreateBitmap(a,b) XftDrawCreateBitmap(a,b) #define FftDrawChange(a,b) XftDrawChange(a,b) #define FftDrawDestroy(a) XftDrawDestroy(a) #define FftDrawString8(a,b,c,d,e,f,g) XftDrawString8(a,b,c,d,e,f,g) #define FftDrawString16(a,b,c,d,e,f,g) XftDrawString16(a,b,c,d,e,f,g) #define FftDrawString32(a,b,c,d,e,f,g) XftDrawString32(a,b,c,d,e,f,g) #define FftPDrawString8 XftDrawString8 #define FftPDrawString16 XftDrawString16 #define FftPDrawString32 XftDrawString32 #define FftDrawRect(a,b,c,d,e,f) XftDrawRect(a,b,c,d,e,f) #define FftDrawSetClip(a,b) XftDrawSetClip(a,b) #define FftTextExtents8(a,b,c,d,e) XftTextExtents8(a,b,c,d,e) #define FftTextExtents16(a,b,c,d,e) XftTextExtents16(a,b,c,d,e) #define FftTextExtents32(a,b,c,d,e) XftTextExtents32(a,b,c,d,e) #define FftFontMatch(a,b,c,d) XftFontMatch(a,b,c,d) #define FftFontOpenPattern(a,b) XftFontOpenPattern(a,b) #define FftFontOpenName(a,b,c) XftFontOpenName(a,b,c) #define FftFontOpenXlfd(a,b,c) XftFontOpenXlfd(a,b,c) #define FftFontClose(a,b) XftFontClose(a,b) #define FftFontSetCreate() XftFontSetCreate() #define FftFontSetAdd(a,b) XftFontSetAdd(a,b) #define FftInit(a) XftInit(a) #define FftListFontSets(a,b,c,d) XftListFontSets(a,b,c,d) #define FftNameParse(a) XftNameParse(a) #define FftXlfdParse(a,b,c) XftXlfdParse(a,b,c) #define FftCoreOpen(a,b) XftCoreOpen(a,b) /* utf8 functions */ #if FftUtf8Support #define FftDrawStringUtf8(a,b,c,d,e,f,g) XftDrawStringUtf8(a,b,c,d,e,f,g) #define FftPDrawStringUtf8 XftDrawStringUtf8 #define FftTextExtentsUtf8(a,b,c,d,e) XftTextExtentsUtf8(a,b,c,d,e) #else #define FftDrawStringUtf8(a,b,c,d,e,f,g) #define FftPDrawStringUtf8 FftPDumyFunc #define FftTextExtentsUtf8(a,b,c,d,e) #endif #else /* !FftSupport */ #define FFT_FAMILY "" #define FFT_STYLE "" #define FFT_SLANT "" #define FFT_WEIGHT "" #define FFT_SIZE "" #define FFT_PIXEL_SIZE "" #define FFT_SPACING "" #define FFT_FOUNDRY "" #define FFT_CORE "" #define FFT_ANTIALIAS "" #define FFT_XLFD "" #define FFT_FILE "" #define FFT_INDEX "" #define FFT_RASTERIZER "" #define FFT_OUTLINE "" #define FFT_SCALABLE "" #define FFT_RGBA "" #define FFT_SCALE "" #define FFT_RENDER "" #define FFT_CHAR_WIDTH "" #define FFT_CHAR_HEIGHT "" #define FFT_MATRIX "" #define FFT_WEIGHT_LIGHT 0 #define FFT_WEIGHT_MEDIUM 0 #define FFT_WEIGHT_DEMIBOLD 0 #define FFT_WEIGHT_BOLD 0 #define FFT_WEIGHT_BLACK 0 #define FFT_SLANT_ROMAN 0 #define FFT_SLANT_ITALIC 0 #define FFT_SLANT_OBLIQUE 0 #define FFT_PROPORTIONAL 0 #define FFT_MONO 0 #define FFT_CHARCELL 0 #define FFT_RGBA_NONE 0 #define FFT_RGBA_RGB 0 #define FFT_RGBA_BGR 0 #define FFT_RGBA_VRGB 0 #define FFT_RGBA_VBGR 0 /* new in Fc */ #define FFT_HINTING "" #define FFT_VERTICAL_LAYOUT "" #define FFT_AUTOHINT "" #define FFT_GLOBAL_ADVANCE "" #define FFT_SOURCE "" #define FFT_CHARSET "" #define FFT_LANG "" #define FFT_DIR_CACHE_FILE "" #define FFT_USER_CACHE_FILE "" /* skip all the FC_LANG_* OS/2 CodePageRange bits */ /* not in Fc */ #define FFT_ENCODING "" /* Fc stuff */ #define FftConfigSubstitute(a) False #define FftValuePrint(a) #define FftPatternPrint(a) #define FftFontSetPrint(a) #define FftGlyphExists(a,b,c) False #define FftObjectSetCreate() NULL #define FftObjectSetAdd(a,b) False #define FftObjectSetDestroy(a) #define FftObjectSetVaBuild(a,b) NULL #define FftListFontsPatternObjects(a,b,c,d) NULL #define FftFontSetMatch(a,b,c,d) NULL #define FftNameParse(a) NULL #define FftPatternCreate() NULL #define FftPatternDuplicate(a) NULL #define FftValueDestroy(a) #define FftValueListDestroy(a) #define FftPatternDestroy(a) #define FftPatternFind(a,b,c) NULL #define FftPatternAdd(a,b,c,d) False #define FftPatternGet(a,b,c,d) #define FftPatternDel(a,b) False #define FftPatternAddInteger(a,b,c) False #define FftPatternAddDouble(a,b,c) False #define FftPatternAddString(a,b,c) False #define FftPatternAddBool(a,b,c) False #define FftPatternAddMatrix(a,b,c) False #define FftPatternGetInteger(a,b,c,d) 0 #define FftPatternGetDouble(a,b,c,d) 0 #define FftPatternGetString(a,b,c,d) 0 #define FftPatternGetBool(a,b,c,d) 0 #define FftPatternGetMatrix(a,b,c,d) 0 #define FftPatternVaBuild(a,b) NULL /* Xft stuff */ #define FftColorAllocName(a,b,c,d,e) False #define FftColorAllocValue(a,b,c,d,e) False #define FftColorFree(a,b,c,d) #define FftDefaultHasRender(a) False #define FftDefaultSet(a,b) False #define FftDefaultSubstitute(a,b,c) #define FftDrawCreate(a,b,c,d) NULL #define FftDrawCreateBitmap(a,b) NULL #define FftDrawChange(a,b) #define FftDrawDestroy(a) #define FftDrawString8(a,b,c,d,e,f,g) #define FftDrawString16(a,b,c,d,e,f,g) #define FftDrawString32(a,b,c,d,e,f,g) #define FftPDrawString8 FftPDumyFunc #define FftPDrawString16 FftPDumyFunc #define FftPDrawString32 FftPDumyFunc #define FftDrawRect(a,b,c,d,e,f) #define FftDrawSetClip(a,b) False #define FftTextExtents8(a,b,c,d,e) #define FftTextExtents16(a,b,c,d,e) #define FftTextExtents32(a,b,c,d,e) #define FftFontMatch(a,b,c,d) NULL #define FftFontOpenPattern(a,b) NULL #define FftFontOpenName(a,b,c) NULL #define FftFontOpenXlfd(a,b,c) NULL #define FftFontClose(a,b) #define FftFontSetCreate() NULL #define FftFontSetDestroy(a) #define FftFontSetAdd(a,b) False #define FftInit(a) False #define FftListFontSets(a,b,c,d) NULL #define FftNameParse(a) NULL #define FftXlfdParse(a,b,c) NULL #define FftCoreOpen(a,b) NULL /* utf8 functions */ #define FftDrawStringUtf8(a,b,c,d,e,f,g) #define FftPDrawStringUtf8 FftPDumyFunc #define FftTextExtentsUtf8(a,b,c,d,e) #endif #endif /* FFT_H */ fvwm-2.7.0/libs/FShape.c0000644000175000017500000000205414147024700011663 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ** FShape.c: drop in replacements for the X shape library encapsulation */ #include "config.h" #ifdef SHAPE #include #include #include "FShape.h" int FShapeEventBase = 0; int FShapeErrorBase = 0; Bool FShapesSupported = False; void FShapeInit(Display *dpy) { FShapesSupported = FShapeQueryExtension(dpy, &FShapeEventBase, &FShapeErrorBase); } #endif /* SHAPE */ fvwm-2.7.0/libs/fio.h0000644000175000017500000000054714147024700011304 00000000000000/* -*-c-*- */ /* Wrappers for io functions from the standard library that might be * interrupted. These functions are restarted when necessary. */ /* ---------------------------- interface functions ------------------------ */ ssize_t fvwm_send(int s, const void *buf, size_t len, int flags); ssize_t fvwm_recv(int s, void *buf, size_t len, int flags); fvwm-2.7.0/libs/PictureBase.h0000644000175000017500000001407114147024700012732 00000000000000/* -*-c-*- */ #ifndef Picture_Base_H #define Picture_Base_H #include "config.h" #ifdef HAVE_XRENDER #define XRenderSupport 1 #else #define XRenderSupport 0 #endif #ifdef XPM #define XpmSupport 1 #else #define XpmSupport 0 #endif #ifdef HAVE_PNG #define PngSupport 1 #else #define PngSupport 0 #endif extern Bool Pdefault; extern Visual *Pvisual; extern Colormap Pcmap; extern unsigned int Pdepth; extern Display *Pdpy; /* Save area for display pointer */ extern Bool PUseDynamicColors; typedef struct { int color_limit; int strict; int allocate; int not_dynamic; int use_named_table; } PictureColorLimitOption; /** * Set a colon-separated path, with environment variable expansions. * Expand '+' to be the value of the previous path. * * Parameters: * p_path pointer to the path variable * newpath new value for *p_path * free_old_path set true if we should free the memory pointed to * by p_path on entry * * The value of newpath is copied into a newly-allocated place, to which * '*p_path' will point to upon return. The memory region pointed to by * '*p_path' upon entry will be freed if 'free_old_path' is true. * **/ void setPath(char** p_path, const char* newpath, int free_old_path); /** * Search along colon-separated path for filename, with optional suffix. * * Parameters: * path colon-separated path of directory names * filename basename of file to search for * suffix if non-NULL, filename may have this suffix * type mode sought for file * * For each DIR in the path, search for DIR/filename then * DIR/ (if suffix is non-NULL). Return the full path of * the first found. * * The parameter type is a mask consisting of one or more of R_OK, W_OK, X_OK * and F_OK. R_OK, W_OK and X_OK request checking whether the file exists and * has read, write and execute permissions, respectively. F_OK just requests * checking for the existence of the file. * * Returns: full pathname of sought-after file, or NULL. The return value * points to allocated memory that the caller must free. * **/ char* searchPath( const char* path, const char* filename, const char* suffix, int type); /* This routine called during modules initialization. Fvwm has its own code * in fvwm.c */ void PictureInitCMap(Display *dpy); /* as above but force to use the default visual. If use_my_color_limit is True * also enable color limitation (independent than the fvwm one). */ void PictureInitCMapRoot( Display *dpy, Bool init_color_limit, PictureColorLimitOption *opt, Bool use_my_color_limit, Bool init_dither); /* Analogue of the Xlib WhitePixel and BlackPixel functions but use the Pvisual */ Pixel PictureWhitePixel(void); Pixel PictureBlackPixel(void); /* for initialization of the white and black pixel (for fvwm as PictureInitCMap* * do this) */ void PictureSetupWhiteAndBlack(void); /* Analogue of the Xlib DefaultGC function but take care of the Pdepth: - If Pdepth == DefaultDepth return the DefaultGC - If Pdepth != DefaultDepth and first call create a static gc with the win and return the gc - If Pdepth != DefaultDepth and already called return the static gc */ GC PictureDefaultGC(Display *dpy, Window win); /* these can be used to switch visuals before calling GetPicture */ /* do NOT use with CachePicture */ void PictureUseDefaultVisual(void); void PictureUseFvwmVisual(void); void PictureSaveFvwmVisual(void); /** Returns current setting of the image path **/ char* PictureGetImagePath(void); /** Sets image path to newpath. Environment variables are expanded, and '+' is expanded to previous value of imagepath. The new path is in newly-allocated memory, so newpath may be freed or re-used. **/ void PictureSetImagePath(const char* newpath); /** Search for file along pathlist. If pathlist is NULL, will use the current imagepath setting. If filename is not found, but filename.gz is found, will return the latter. Mode is typically R_OK. See searchPath() for more details. **/ char* PictureFindImageFile( const char* filename, const char* pathlist, int mode); typedef struct FvwmPictureThing { struct FvwmPictureThing *next; char *name; unsigned long stamp; /* should be FileStamp */ unsigned long fpa_mask; Pixmap picture; Pixmap mask; Pixmap alpha; unsigned int depth; unsigned int width; unsigned int height; unsigned int count; Pixel *alloc_pixels; int nalloc_pixels; Bool no_limit; } FvwmPicture; typedef struct { unsigned alpha : 1; unsigned alloc_pixels : 1; } FvwmPictureFlags; #define FPAM_NO_ALLOC_PIXELS (1) /* do not return the allocated pixels * this is used only if PUseDynamicColors, * if not the allocated pixels are never * returned */ #define FPAM_NO_COLOR_LIMIT (1 << 1) /* do not use color limitation */ #define FPAM_NO_ALPHA (1 << 2) /* do not return the alpha channel */ #define FPAM_DITHER (1 << 3) /* dither the image */ #define FPAM_TINT (1 << 4) /* tint the image */ #define FPAM_MONOCHROME (1 << 5) /* reduce the color depth to 1-bit */ typedef struct { unsigned mask : 6; XColor tint; int tint_percent; } FvwmPictureAttributes; /* tint no yet implemented */ #define PICTURE_FPA_AGREE(p,fpa) (p->fpa_mask == fpa.mask) #define FRAM_HAVE_ADDED_ALPHA (1) #define FRAM_HAVE_TINT (1 << 1) #define FRAM_HAVE_UNIFORM_COLOR (1 << 2) #define FRAM_DEST_IS_A_WINDOW (1 << 3) #define FRAM_HAVE_ICON_CSET (1 << 4) #include "Colorset.h" typedef struct { unsigned mask : 5; int added_alpha_percent; Pixel tint; int tint_percent; Pixel uniform_pixel; colorset_t *colorset; } FvwmRenderAttributes; #define PICTURE_HAS_ALPHA(picture,cset) \ ((picture && picture->alpha != None) || \ (cset >= 0 && Colorset[cset].icon_alpha_percent < 100)) /* alpha limit if we cannot use the alpha channel */ #define PICTURE_ALPHA_LIMIT 130 typedef struct { Colormap cmap; int dither; int no_limit; Bool is_8; unsigned long *pixels_table; int pixels_table_size; } PictureImageColorAllocator; #endif /* Picture_Base_H */ fvwm-2.7.0/libs/CombineChars.c0000644000175000017500000014663614147024700013071 00000000000000/* -*-c-*- */ /* Copyright (C) 2003 Marcus Lundblad */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ #include "config.h" #include #include #include "fvwmlib.h" #include "CombineChars.h" /* ---------------------------- local types -------------------------------- */ typedef struct char_combclass { unsigned short key; int combclass; } char_combclass_t; typedef struct char_comb { unsigned short key; unsigned short first; unsigned short second; } char_comb_t; /* ---------------------------- static variables --------------------------- */ /* would like to use the Unicode replacement character here, but that would result in expanding incoming UTF-8 strings when garbage characters occurs */ /* so for the time being use '?' */ static unsigned short REPLACEMENT_CHARACTER = 0x3f; /* maps characters to combination classes (not in list => 0) */ /* parsed from UnicodeData-3.2.0.txt */ static const char_combclass_t combclass_table[] = { { 0x0300, 230}, { 0x0301, 230}, { 0x0302, 230}, { 0x0303, 230}, { 0x0304, 230}, { 0x0305, 230}, { 0x0306, 230}, { 0x0307, 230}, { 0x0308, 230}, { 0x0309, 230}, { 0x030A, 230}, { 0x030B, 230}, { 0x030C, 230}, { 0x030D, 230}, { 0x030E, 230}, { 0x030F, 230}, { 0x0310, 230}, { 0x0311, 230}, { 0x0312, 230}, { 0x0313, 230}, { 0x0314, 230}, { 0x0315, 232}, { 0x0316, 220}, { 0x0317, 220}, { 0x0318, 220}, { 0x0319, 220}, { 0x031A, 232}, { 0x031B, 216}, { 0x031C, 220}, { 0x031D, 220}, { 0x031E, 220}, { 0x031F, 220}, { 0x0320, 220}, { 0x0321, 202}, { 0x0322, 202}, { 0x0323, 220}, { 0x0324, 220}, { 0x0325, 220}, { 0x0326, 220}, { 0x0327, 202}, { 0x0328, 202}, { 0x0329, 220}, { 0x032A, 220}, { 0x032B, 220}, { 0x032C, 220}, { 0x032D, 220}, { 0x032E, 220}, { 0x032F, 220}, { 0x0330, 220}, { 0x0331, 220}, { 0x0332, 220}, { 0x0333, 220}, { 0x0334, 1}, { 0x0335, 1}, { 0x0336, 1}, { 0x0337, 1}, { 0x0338, 1}, { 0x0339, 220}, { 0x033A, 220}, { 0x033B, 220}, { 0x033C, 220}, { 0x033D, 230}, { 0x033E, 230}, { 0x033F, 230}, { 0x0340, 230}, { 0x0341, 230}, { 0x0342, 230}, { 0x0343, 230}, { 0x0344, 230}, { 0x0345, 240}, { 0x0346, 230}, { 0x0347, 220}, { 0x0348, 220}, { 0x0349, 220}, { 0x034A, 230}, { 0x034B, 230}, { 0x034C, 230}, { 0x034D, 220}, { 0x034E, 220}, { 0x034F, -1 }, { 0x0360, 234}, { 0x0361, 234}, { 0x0362, 233}, { 0x0363, 230}, { 0x0364, 230}, { 0x0365, 230}, { 0x0366, 230}, { 0x0367, 230}, { 0x0368, 230}, { 0x0369, 230}, { 0x036A, 230}, { 0x036B, 230}, { 0x036C, 230}, { 0x036D, 230}, { 0x036E, 230}, { 0x036F, 230}, { 0x0483, 230}, { 0x0484, 230}, { 0x0485, 230}, { 0x0486, 230}, { 0x0488, -3 }, { 0x0489, -3 }, { 0x0591, 220}, { 0x0592, 230}, { 0x0593, 230}, { 0x0594, 230}, { 0x0595, 230}, { 0x0596, 220}, { 0x0597, 230}, { 0x0598, 230}, { 0x0599, 230}, { 0x059A, 222}, { 0x059B, 220}, { 0x059C, 230}, { 0x059D, 230}, { 0x059E, 230}, { 0x059F, 230}, { 0x05A0, 230}, { 0x05A1, 230}, { 0x05A3, 220}, { 0x05A4, 220}, { 0x05A5, 220}, { 0x05A6, 220}, { 0x05A7, 220}, { 0x05A8, 230}, { 0x05A9, 230}, { 0x05AA, 220}, { 0x05AB, 230}, { 0x05AC, 230}, { 0x05AD, 222}, { 0x05AE, 228}, { 0x05AF, 230}, { 0x05B0, 10}, { 0x05B1, 11}, { 0x05B2, 12}, { 0x05B3, 13}, { 0x05B4, 14}, { 0x05B5, 15}, { 0x05B6, 16}, { 0x05B7, 17}, { 0x05B8, 18}, { 0x05B9, 19}, { 0x05BB, 20}, { 0x05BC, 21}, { 0x05BD, 22}, { 0x05BF, 23}, { 0x05C1, 24}, { 0x05C2, 25}, { 0x05C4, 230}, { 0x064B, 27}, { 0x064C, 28}, { 0x064D, 29}, { 0x064E, 30}, { 0x064F, 31}, { 0x0650, 32}, { 0x0651, 33}, { 0x0652, 34}, { 0x0653, 230}, { 0x0654, 230}, { 0x0655, 220}, { 0x0670, 35}, { 0x06D6, 230}, { 0x06D7, 230}, { 0x06D8, 230}, { 0x06D9, 230}, { 0x06DA, 230}, { 0x06DB, 230}, { 0x06DC, 230}, { 0x06DE, -3 }, { 0x06DF, 230}, { 0x06E0, 230}, { 0x06E1, 230}, { 0x06E2, 230}, { 0x06E3, 220}, { 0x06E4, 230}, { 0x06E7, 230}, { 0x06E8, 230}, { 0x06EA, 220}, { 0x06EB, 230}, { 0x06EC, 230}, { 0x06ED, 220}, { 0x0711, 36}, { 0x0730, 230}, { 0x0731, 220}, { 0x0732, 230}, { 0x0733, 230}, { 0x0734, 220}, { 0x0735, 230}, { 0x0736, 230}, { 0x0737, 220}, { 0x0738, 220}, { 0x0739, 220}, { 0x073A, 230}, { 0x073B, 220}, { 0x073C, 220}, { 0x073D, 230}, { 0x073E, 220}, { 0x073F, 230}, { 0x0740, 230}, { 0x0741, 230}, { 0x0742, 220}, { 0x0743, 230}, { 0x0744, 220}, { 0x0745, 230}, { 0x0746, 220}, { 0x0747, 230}, { 0x0748, 220}, { 0x0749, 230}, { 0x074A, 230}, { 0x07A6, -1 }, { 0x07A7, -1 }, { 0x07A8, -1 }, { 0x07A9, -1 }, { 0x07AA, -1 }, { 0x07AB, -1 }, { 0x07AC, -1 }, { 0x07AD, -1 }, { 0x07AE, -1 }, { 0x07AF, -1 }, { 0x07B0, -1 }, { 0x0901, -1 }, { 0x0902, -1 }, { 0x0903, -2 }, { 0x093C, 7}, { 0x093E, -2 }, { 0x093F, -2 }, { 0x0940, -2 }, { 0x0941, -1 }, { 0x0942, -1 }, { 0x0943, -1 }, { 0x0944, -1 }, { 0x0945, -1 }, { 0x0946, -1 }, { 0x0947, -1 }, { 0x0948, -1 }, { 0x0949, -2 }, { 0x094A, -2 }, { 0x094B, -2 }, { 0x094C, -2 }, { 0x094D, 9}, { 0x0951, 230}, { 0x0952, 220}, { 0x0953, 230}, { 0x0954, 230}, { 0x0962, -1 }, { 0x0963, -1 }, { 0x0981, -1 }, { 0x0982, -2 }, { 0x0983, -2 }, { 0x09BC, 7}, { 0x09BE, -2 }, { 0x09BF, -2 }, { 0x09C0, -2 }, { 0x09C1, -1 }, { 0x09C2, -1 }, { 0x09C3, -1 }, { 0x09C4, -1 }, { 0x09C7, -2 }, { 0x09C8, -2 }, { 0x09CB, -2 }, { 0x09CC, -2 }, { 0x09CD, 9}, { 0x09D7, -2 }, { 0x09E2, -1 }, { 0x09E3, -1 }, { 0x0A02, -1 }, { 0x0A3C, 7}, { 0x0A3E, -2 }, { 0x0A3F, -2 }, { 0x0A40, -2 }, { 0x0A41, -1 }, { 0x0A42, -1 }, { 0x0A47, -1 }, { 0x0A48, -1 }, { 0x0A4B, -1 }, { 0x0A4C, -1 }, { 0x0A4D, 9}, { 0x0A70, -1 }, { 0x0A71, -1 }, { 0x0A81, -1 }, { 0x0A82, -1 }, { 0x0A83, -2 }, { 0x0ABC, 7}, { 0x0ABE, -2 }, { 0x0ABF, -2 }, { 0x0AC0, -2 }, { 0x0AC1, -1 }, { 0x0AC2, -1 }, { 0x0AC3, -1 }, { 0x0AC4, -1 }, { 0x0AC5, -1 }, { 0x0AC7, -1 }, { 0x0AC8, -1 }, { 0x0AC9, -2 }, { 0x0ACB, -2 }, { 0x0ACC, -2 }, { 0x0ACD, 9}, { 0x0B01, -1 }, { 0x0B02, -2 }, { 0x0B03, -2 }, { 0x0B3C, 7}, { 0x0B3E, -2 }, { 0x0B3F, -1 }, { 0x0B40, -2 }, { 0x0B41, -1 }, { 0x0B42, -1 }, { 0x0B43, -1 }, { 0x0B47, -2 }, { 0x0B48, -2 }, { 0x0B4B, -2 }, { 0x0B4C, -2 }, { 0x0B4D, 9}, { 0x0B56, -1 }, { 0x0B57, -2 }, { 0x0B82, -1 }, { 0x0BBE, -2 }, { 0x0BBF, -2 }, { 0x0BC0, -1 }, { 0x0BC1, -2 }, { 0x0BC2, -2 }, { 0x0BC6, -2 }, { 0x0BC7, -2 }, { 0x0BC8, -2 }, { 0x0BCA, -2 }, { 0x0BCB, -2 }, { 0x0BCC, -2 }, { 0x0BCD, 9}, { 0x0BD7, -2 }, { 0x0C01, -2 }, { 0x0C02, -2 }, { 0x0C03, -2 }, { 0x0C3E, -1 }, { 0x0C3F, -1 }, { 0x0C40, -1 }, { 0x0C41, -2 }, { 0x0C42, -2 }, { 0x0C43, -2 }, { 0x0C44, -2 }, { 0x0C46, -1 }, { 0x0C47, -1 }, { 0x0C48, -1 }, { 0x0C4A, -1 }, { 0x0C4B, -1 }, { 0x0C4C, -1 }, { 0x0C4D, 9}, { 0x0C55, 84}, { 0x0C56, 91}, { 0x0C82, -2 }, { 0x0C83, -2 }, { 0x0CBE, -2 }, { 0x0CBF, -1 }, { 0x0CC0, -2 }, { 0x0CC1, -2 }, { 0x0CC2, -2 }, { 0x0CC3, -2 }, { 0x0CC4, -2 }, { 0x0CC6, -1 }, { 0x0CC7, -2 }, { 0x0CC8, -2 }, { 0x0CCA, -2 }, { 0x0CCB, -2 }, { 0x0CCC, -1 }, { 0x0CCD, 9}, { 0x0CD5, -2 }, { 0x0CD6, -2 }, { 0x0D02, -2 }, { 0x0D03, -2 }, { 0x0D3E, -2 }, { 0x0D3F, -2 }, { 0x0D40, -2 }, { 0x0D41, -1 }, { 0x0D42, -1 }, { 0x0D43, -1 }, { 0x0D46, -2 }, { 0x0D47, -2 }, { 0x0D48, -2 }, { 0x0D4A, -2 }, { 0x0D4B, -2 }, { 0x0D4C, -2 }, { 0x0D4D, 9}, { 0x0D57, -2 }, { 0x0D82, -2 }, { 0x0D83, -2 }, { 0x0DCA, 9}, { 0x0DCF, -2 }, { 0x0DD0, -2 }, { 0x0DD1, -2 }, { 0x0DD2, -1 }, { 0x0DD3, -1 }, { 0x0DD4, -1 }, { 0x0DD6, -1 }, { 0x0DD8, -2 }, { 0x0DD9, -2 }, { 0x0DDA, -2 }, { 0x0DDB, -2 }, { 0x0DDC, -2 }, { 0x0DDD, -2 }, { 0x0DDE, -2 }, { 0x0DDF, -2 }, { 0x0DF2, -2 }, { 0x0DF3, -2 }, { 0x0E31, -1 }, { 0x0E34, -1 }, { 0x0E35, -1 }, { 0x0E36, -1 }, { 0x0E37, -1 }, { 0x0E38, 103}, { 0x0E39, 103}, { 0x0E3A, 9}, { 0x0E47, -1 }, { 0x0E48, 107}, { 0x0E49, 107}, { 0x0E4A, 107}, { 0x0E4B, 107}, { 0x0E4C, -1 }, { 0x0E4D, -1 }, { 0x0E4E, -1 }, { 0x0EB1, -1 }, { 0x0EB4, -1 }, { 0x0EB5, -1 }, { 0x0EB6, -1 }, { 0x0EB7, -1 }, { 0x0EB8, 118}, { 0x0EB9, 118}, { 0x0EBB, -1 }, { 0x0EBC, -1 }, { 0x0EC8, 122}, { 0x0EC9, 122}, { 0x0ECA, 122}, { 0x0ECB, 122}, { 0x0ECC, -1 }, { 0x0ECD, -1 }, { 0x0F18, 220}, { 0x0F19, 220}, { 0x0F35, 220}, { 0x0F37, 220}, { 0x0F39, 216}, { 0x0F3E, -2 }, { 0x0F3F, -2 }, { 0x0F71, 129}, { 0x0F72, 130}, { 0x0F73, -1 }, { 0x0F74, 132}, { 0x0F75, -1 }, { 0x0F76, -1 }, { 0x0F77, -1 }, { 0x0F78, -1 }, { 0x0F79, -1 }, { 0x0F7A, 130}, { 0x0F7B, 130}, { 0x0F7C, 130}, { 0x0F7D, 130}, { 0x0F7E, -1 }, { 0x0F7F, -2 }, { 0x0F80, 130}, { 0x0F81, -1 }, { 0x0F82, 230}, { 0x0F83, 230}, { 0x0F84, 9}, { 0x0F86, 230}, { 0x0F87, 230}, { 0x0F90, -1 }, { 0x0F91, -1 }, { 0x0F92, -1 }, { 0x0F93, -1 }, { 0x0F94, -1 }, { 0x0F95, -1 }, { 0x0F96, -1 }, { 0x0F97, -1 }, { 0x0F99, -1 }, { 0x0F9A, -1 }, { 0x0F9B, -1 }, { 0x0F9C, -1 }, { 0x0F9D, -1 }, { 0x0F9E, -1 }, { 0x0F9F, -1 }, { 0x0FA0, -1 }, { 0x0FA1, -1 }, { 0x0FA2, -1 }, { 0x0FA3, -1 }, { 0x0FA4, -1 }, { 0x0FA5, -1 }, { 0x0FA6, -1 }, { 0x0FA7, -1 }, { 0x0FA8, -1 }, { 0x0FA9, -1 }, { 0x0FAA, -1 }, { 0x0FAB, -1 }, { 0x0FAC, -1 }, { 0x0FAD, -1 }, { 0x0FAE, -1 }, { 0x0FAF, -1 }, { 0x0FB0, -1 }, { 0x0FB1, -1 }, { 0x0FB2, -1 }, { 0x0FB3, -1 }, { 0x0FB4, -1 }, { 0x0FB5, -1 }, { 0x0FB6, -1 }, { 0x0FB7, -1 }, { 0x0FB8, -1 }, { 0x0FB9, -1 }, { 0x0FBA, -1 }, { 0x0FBB, -1 }, { 0x0FBC, -1 }, { 0x0FC6, 220}, { 0x102C, -2 }, { 0x102D, -1 }, { 0x102E, -1 }, { 0x102F, -1 }, { 0x1030, -1 }, { 0x1031, -2 }, { 0x1032, -1 }, { 0x1036, -1 }, { 0x1037, 7}, { 0x1038, -2 }, { 0x1039, 9}, { 0x1056, -2 }, { 0x1057, -2 }, { 0x1058, -1 }, { 0x1059, -1 }, { 0x1712, -1 }, { 0x1713, -1 }, { 0x1714, 9}, { 0x1732, -1 }, { 0x1733, -1 }, { 0x1734, 9}, { 0x1752, -1 }, { 0x1753, -1 }, { 0x1772, -1 }, { 0x1773, -1 }, { 0x17B4, -2 }, { 0x17B5, -2 }, { 0x17B6, -2 }, { 0x17B7, -1 }, { 0x17B8, -1 }, { 0x17B9, -1 }, { 0x17BA, -1 }, { 0x17BB, -1 }, { 0x17BC, -1 }, { 0x17BD, -1 }, { 0x17BE, -2 }, { 0x17BF, -2 }, { 0x17C0, -2 }, { 0x17C1, -2 }, { 0x17C2, -2 }, { 0x17C3, -2 }, { 0x17C4, -2 }, { 0x17C5, -2 }, { 0x17C6, -1 }, { 0x17C7, -2 }, { 0x17C8, -2 }, { 0x17C9, -1 }, { 0x17CA, -1 }, { 0x17CB, -1 }, { 0x17CC, -1 }, { 0x17CD, -1 }, { 0x17CE, -1 }, { 0x17CF, -1 }, { 0x17D0, -1 }, { 0x17D1, -1 }, { 0x17D2, 9}, { 0x17D3, -1 }, { 0x180B, -1 }, { 0x180C, -1 }, { 0x180D, -1 }, { 0x18A9, 228}, { 0x20D0, 230}, { 0x20D1, 230}, { 0x20D2, 1}, { 0x20D3, 1}, { 0x20D4, 230}, { 0x20D5, 230}, { 0x20D6, 230}, { 0x20D7, 230}, { 0x20D8, 1}, { 0x20D9, 1}, { 0x20DA, 1}, { 0x20DB, 230}, { 0x20DC, 230}, { 0x20DD, -3 }, { 0x20DE, -3 }, { 0x20DF, -3 }, { 0x20E0, -3 }, { 0x20E1, 230}, { 0x20E2, -3 }, { 0x20E3, -3 }, { 0x20E4, -3 }, { 0x20E5, 1}, { 0x20E6, 1}, { 0x20E7, 230}, { 0x20E8, 220}, { 0x20E9, 230}, { 0x20EA, 1}, { 0x302A, 218}, { 0x302B, 228}, { 0x302C, 232}, { 0x302D, 222}, { 0x302E, 224}, { 0x302F, 224}, { 0x3099, 8}, { 0x309A, 8}, { 0xFB1E, 26}, { 0xFE00, -1 }, { 0xFE01, -1 }, { 0xFE02, -1 }, { 0xFE03, -1 }, { 0xFE04, -1 }, { 0xFE05, -1 }, { 0xFE06, -1 }, { 0xFE07, -1 }, { 0xFE08, -1 }, { 0xFE09, -1 }, { 0xFE0A, -1 }, { 0xFE0B, -1 }, { 0xFE0C, -1 }, { 0xFE0D, -1 }, { 0xFE0E, -1 }, { 0xFE0F, -1 }, { 0xFE20, 230}, { 0xFE21, 230}, { 0xFE22, 230}, { 0xFE23, 230}, /*{ 0x1D165, 216}, { 0x1D166, 216}, { 0x1D167, 1}, { 0x1D168, 1}, { 0x1D169, 1}, { 0x1D16D, 226}, { 0x1D16E, 216}, { 0x1D16F, 216}, { 0x1D170, 216}, { 0x1D171, 216}, { 0x1D172, 216}, { 0x1D17B, 220}, { 0x1D17C, 220}, { 0x1D17D, 220}, { 0x1D17E, 220}, { 0x1D17F, 220}, { 0x1D180, 220}, { 0x1D181, 220}, { 0x1D182, 220}, { 0x1D185, 230}, { 0x1D186, 230}, { 0x1D187, 230}, { 0x1D188, 230}, { 0x1D189, 230}, { 0x1D18A, 220}, { 0x1D18B, 220}, { 0x1D1AA, 230}, { 0x1D1AB, 230}, { 0x1D1AC, 230}, { 0x1D1AD, 230},*/ }; /* maps characters to decompositions */ /* parsed from UnicodeData-3.2.0.txt */ static const char_comb_t comb_table[] = { { 0x00C0, 0x0041, 0x0300 }, { 0x00C1, 0x0041, 0x0301 }, { 0x00C2, 0x0041, 0x0302 }, { 0x00C3, 0x0041, 0x0303 }, { 0x00C4, 0x0041, 0x0308 }, { 0x00C5, 0x0041, 0x030A }, { 0x00C7, 0x0043, 0x0327 }, { 0x00C8, 0x0045, 0x0300 }, { 0x00C9, 0x0045, 0x0301 }, { 0x00CA, 0x0045, 0x0302 }, { 0x00CB, 0x0045, 0x0308 }, { 0x00CC, 0x0049, 0x0300 }, { 0x00CD, 0x0049, 0x0301 }, { 0x00CE, 0x0049, 0x0302 }, { 0x00CF, 0x0049, 0x0308 }, { 0x00D1, 0x004E, 0x0303 }, { 0x00D2, 0x004F, 0x0300 }, { 0x00D3, 0x004F, 0x0301 }, { 0x00D4, 0x004F, 0x0302 }, { 0x00D5, 0x004F, 0x0303 }, { 0x00D6, 0x004F, 0x0308 }, { 0x00D9, 0x0055, 0x0300 }, { 0x00DA, 0x0055, 0x0301 }, { 0x00DB, 0x0055, 0x0302 }, { 0x00DC, 0x0055, 0x0308 }, { 0x00DD, 0x0059, 0x0301 }, { 0x00E0, 0x0061, 0x0300 }, { 0x00E1, 0x0061, 0x0301 }, { 0x00E2, 0x0061, 0x0302 }, { 0x00E3, 0x0061, 0x0303 }, { 0x00E4, 0x0061, 0x0308 }, { 0x00E5, 0x0061, 0x030A }, { 0x00E7, 0x0063, 0x0327 }, { 0x00E8, 0x0065, 0x0300 }, { 0x00E9, 0x0065, 0x0301 }, { 0x00EA, 0x0065, 0x0302 }, { 0x00EB, 0x0065, 0x0308 }, { 0x00EC, 0x0069, 0x0300 }, { 0x00ED, 0x0069, 0x0301 }, { 0x00EE, 0x0069, 0x0302 }, { 0x00EF, 0x0069, 0x0308 }, { 0x00F1, 0x006E, 0x0303 }, { 0x00F2, 0x006F, 0x0300 }, { 0x00F3, 0x006F, 0x0301 }, { 0x00F4, 0x006F, 0x0302 }, { 0x00F5, 0x006F, 0x0303 }, { 0x00F6, 0x006F, 0x0308 }, { 0x00F9, 0x0075, 0x0300 }, { 0x00FA, 0x0075, 0x0301 }, { 0x00FB, 0x0075, 0x0302 }, { 0x00FC, 0x0075, 0x0308 }, { 0x00FD, 0x0079, 0x0301 }, { 0x00FF, 0x0079, 0x0308 }, { 0x0100, 0x0041, 0x0304 }, { 0x0101, 0x0061, 0x0304 }, { 0x0102, 0x0041, 0x0306 }, { 0x0103, 0x0061, 0x0306 }, { 0x0104, 0x0041, 0x0328 }, { 0x0105, 0x0061, 0x0328 }, { 0x0106, 0x0043, 0x0301 }, { 0x0107, 0x0063, 0x0301 }, { 0x0108, 0x0043, 0x0302 }, { 0x0109, 0x0063, 0x0302 }, { 0x010A, 0x0043, 0x0307 }, { 0x010B, 0x0063, 0x0307 }, { 0x010C, 0x0043, 0x030C }, { 0x010D, 0x0063, 0x030C }, { 0x010E, 0x0044, 0x030C }, { 0x010F, 0x0064, 0x030C }, { 0x0112, 0x0045, 0x0304 }, { 0x0113, 0x0065, 0x0304 }, { 0x0114, 0x0045, 0x0306 }, { 0x0115, 0x0065, 0x0306 }, { 0x0116, 0x0045, 0x0307 }, { 0x0117, 0x0065, 0x0307 }, { 0x0118, 0x0045, 0x0328 }, { 0x0119, 0x0065, 0x0328 }, { 0x011A, 0x0045, 0x030C }, { 0x011B, 0x0065, 0x030C }, { 0x011C, 0x0047, 0x0302 }, { 0x011D, 0x0067, 0x0302 }, { 0x011E, 0x0047, 0x0306 }, { 0x011F, 0x0067, 0x0306 }, { 0x0120, 0x0047, 0x0307 }, { 0x0121, 0x0067, 0x0307 }, { 0x0122, 0x0047, 0x0327 }, { 0x0123, 0x0067, 0x0327 }, { 0x0124, 0x0048, 0x0302 }, { 0x0125, 0x0068, 0x0302 }, { 0x0128, 0x0049, 0x0303 }, { 0x0129, 0x0069, 0x0303 }, { 0x012A, 0x0049, 0x0304 }, { 0x012B, 0x0069, 0x0304 }, { 0x012C, 0x0049, 0x0306 }, { 0x012D, 0x0069, 0x0306 }, { 0x012E, 0x0049, 0x0328 }, { 0x012F, 0x0069, 0x0328 }, { 0x0130, 0x0049, 0x0307 }, { 0x0134, 0x004A, 0x0302 }, { 0x0135, 0x006A, 0x0302 }, { 0x0136, 0x004B, 0x0327 }, { 0x0137, 0x006B, 0x0327 }, { 0x0139, 0x004C, 0x0301 }, { 0x013A, 0x006C, 0x0301 }, { 0x013B, 0x004C, 0x0327 }, { 0x013C, 0x006C, 0x0327 }, { 0x013D, 0x004C, 0x030C }, { 0x013E, 0x006C, 0x030C }, { 0x0143, 0x004E, 0x0301 }, { 0x0144, 0x006E, 0x0301 }, { 0x0145, 0x004E, 0x0327 }, { 0x0146, 0x006E, 0x0327 }, { 0x0147, 0x004E, 0x030C }, { 0x0148, 0x006E, 0x030C }, { 0x014C, 0x004F, 0x0304 }, { 0x014D, 0x006F, 0x0304 }, { 0x014E, 0x004F, 0x0306 }, { 0x014F, 0x006F, 0x0306 }, { 0x0150, 0x004F, 0x030B }, { 0x0151, 0x006F, 0x030B }, { 0x0154, 0x0052, 0x0301 }, { 0x0155, 0x0072, 0x0301 }, { 0x0156, 0x0052, 0x0327 }, { 0x0157, 0x0072, 0x0327 }, { 0x0158, 0x0052, 0x030C }, { 0x0159, 0x0072, 0x030C }, { 0x015A, 0x0053, 0x0301 }, { 0x015B, 0x0073, 0x0301 }, { 0x015C, 0x0053, 0x0302 }, { 0x015D, 0x0073, 0x0302 }, { 0x015E, 0x0053, 0x0327 }, { 0x015F, 0x0073, 0x0327 }, { 0x0160, 0x0053, 0x030C }, { 0x0161, 0x0073, 0x030C }, { 0x0162, 0x0054, 0x0327 }, { 0x0163, 0x0074, 0x0327 }, { 0x0164, 0x0054, 0x030C }, { 0x0165, 0x0074, 0x030C }, { 0x0168, 0x0055, 0x0303 }, { 0x0169, 0x0075, 0x0303 }, { 0x016A, 0x0055, 0x0304 }, { 0x016B, 0x0075, 0x0304 }, { 0x016C, 0x0055, 0x0306 }, { 0x016D, 0x0075, 0x0306 }, { 0x016E, 0x0055, 0x030A }, { 0x016F, 0x0075, 0x030A }, { 0x0170, 0x0055, 0x030B }, { 0x0171, 0x0075, 0x030B }, { 0x0172, 0x0055, 0x0328 }, { 0x0173, 0x0075, 0x0328 }, { 0x0174, 0x0057, 0x0302 }, { 0x0175, 0x0077, 0x0302 }, { 0x0176, 0x0059, 0x0302 }, { 0x0177, 0x0079, 0x0302 }, { 0x0178, 0x0059, 0x0308 }, { 0x0179, 0x005A, 0x0301 }, { 0x017A, 0x007A, 0x0301 }, { 0x017B, 0x005A, 0x0307 }, { 0x017C, 0x007A, 0x0307 }, { 0x017D, 0x005A, 0x030C }, { 0x017E, 0x007A, 0x030C }, { 0x01A0, 0x004F, 0x031B }, { 0x01A1, 0x006F, 0x031B }, { 0x01AF, 0x0055, 0x031B }, { 0x01B0, 0x0075, 0x031B }, { 0x01CD, 0x0041, 0x030C }, { 0x01CE, 0x0061, 0x030C }, { 0x01CF, 0x0049, 0x030C }, { 0x01D0, 0x0069, 0x030C }, { 0x01D1, 0x004F, 0x030C }, { 0x01D2, 0x006F, 0x030C }, { 0x01D3, 0x0055, 0x030C }, { 0x01D4, 0x0075, 0x030C }, { 0x01D5, 0x00DC, 0x0304 }, { 0x01D6, 0x00FC, 0x0304 }, { 0x01D7, 0x00DC, 0x0301 }, { 0x01D8, 0x00FC, 0x0301 }, { 0x01D9, 0x00DC, 0x030C }, { 0x01DA, 0x00FC, 0x030C }, { 0x01DB, 0x00DC, 0x0300 }, { 0x01DC, 0x00FC, 0x0300 }, { 0x01DE, 0x00C4, 0x0304 }, { 0x01DF, 0x00E4, 0x0304 }, { 0x01E0, 0x0226, 0x0304 }, { 0x01E1, 0x0227, 0x0304 }, { 0x01E2, 0x00C6, 0x0304 }, { 0x01E3, 0x00E6, 0x0304 }, { 0x01E6, 0x0047, 0x030C }, { 0x01E7, 0x0067, 0x030C }, { 0x01E8, 0x004B, 0x030C }, { 0x01E9, 0x006B, 0x030C }, { 0x01EA, 0x004F, 0x0328 }, { 0x01EB, 0x006F, 0x0328 }, { 0x01EC, 0x01EA, 0x0304 }, { 0x01ED, 0x01EB, 0x0304 }, { 0x01EE, 0x01B7, 0x030C }, { 0x01EF, 0x0292, 0x030C }, { 0x01F0, 0x006A, 0x030C }, { 0x01F4, 0x0047, 0x0301 }, { 0x01F5, 0x0067, 0x0301 }, { 0x01F8, 0x004E, 0x0300 }, { 0x01F9, 0x006E, 0x0300 }, { 0x01FA, 0x00C5, 0x0301 }, { 0x01FB, 0x00E5, 0x0301 }, { 0x01FC, 0x00C6, 0x0301 }, { 0x01FD, 0x00E6, 0x0301 }, { 0x01FE, 0x00D8, 0x0301 }, { 0x01FF, 0x00F8, 0x0301 }, { 0x0200, 0x0041, 0x030F }, { 0x0201, 0x0061, 0x030F }, { 0x0202, 0x0041, 0x0311 }, { 0x0203, 0x0061, 0x0311 }, { 0x0204, 0x0045, 0x030F }, { 0x0205, 0x0065, 0x030F }, { 0x0206, 0x0045, 0x0311 }, { 0x0207, 0x0065, 0x0311 }, { 0x0208, 0x0049, 0x030F }, { 0x0209, 0x0069, 0x030F }, { 0x020A, 0x0049, 0x0311 }, { 0x020B, 0x0069, 0x0311 }, { 0x020C, 0x004F, 0x030F }, { 0x020D, 0x006F, 0x030F }, { 0x020E, 0x004F, 0x0311 }, { 0x020F, 0x006F, 0x0311 }, { 0x0210, 0x0052, 0x030F }, { 0x0211, 0x0072, 0x030F }, { 0x0212, 0x0052, 0x0311 }, { 0x0213, 0x0072, 0x0311 }, { 0x0214, 0x0055, 0x030F }, { 0x0215, 0x0075, 0x030F }, { 0x0216, 0x0055, 0x0311 }, { 0x0217, 0x0075, 0x0311 }, { 0x0218, 0x0053, 0x0326 }, { 0x0219, 0x0073, 0x0326 }, { 0x021A, 0x0054, 0x0326 }, { 0x021B, 0x0074, 0x0326 }, { 0x021E, 0x0048, 0x030C }, { 0x021F, 0x0068, 0x030C }, { 0x0226, 0x0041, 0x0307 }, { 0x0227, 0x0061, 0x0307 }, { 0x0228, 0x0045, 0x0327 }, { 0x0229, 0x0065, 0x0327 }, { 0x022A, 0x00D6, 0x0304 }, { 0x022B, 0x00F6, 0x0304 }, { 0x022C, 0x00D5, 0x0304 }, { 0x022D, 0x00F5, 0x0304 }, { 0x022E, 0x004F, 0x0307 }, { 0x022F, 0x006F, 0x0307 }, { 0x0230, 0x022E, 0x0304 }, { 0x0231, 0x022F, 0x0304 }, { 0x0232, 0x0059, 0x0304 }, { 0x0233, 0x0079, 0x0304 }, { 0x0344, 0x0308, 0x0301 }, { 0x0385, 0x00A8, 0x0301 }, { 0x0386, 0x0391, 0x0301 }, { 0x0388, 0x0395, 0x0301 }, { 0x0389, 0x0397, 0x0301 }, { 0x038A, 0x0399, 0x0301 }, { 0x038C, 0x039F, 0x0301 }, { 0x038E, 0x03A5, 0x0301 }, { 0x038F, 0x03A9, 0x0301 }, { 0x0390, 0x03CA, 0x0301 }, { 0x03AA, 0x0399, 0x0308 }, { 0x03AB, 0x03A5, 0x0308 }, { 0x03AC, 0x03B1, 0x0301 }, { 0x03AD, 0x03B5, 0x0301 }, { 0x03AE, 0x03B7, 0x0301 }, { 0x03AF, 0x03B9, 0x0301 }, { 0x03B0, 0x03CB, 0x0301 }, { 0x03CA, 0x03B9, 0x0308 }, { 0x03CB, 0x03C5, 0x0308 }, { 0x03CC, 0x03BF, 0x0301 }, { 0x03CD, 0x03C5, 0x0301 }, { 0x03CE, 0x03C9, 0x0301 }, { 0x03D3, 0x03D2, 0x0301 }, { 0x03D4, 0x03D2, 0x0308 }, { 0x0400, 0x0415, 0x0300 }, { 0x0401, 0x0415, 0x0308 }, { 0x0403, 0x0413, 0x0301 }, { 0x0407, 0x0406, 0x0308 }, { 0x040C, 0x041A, 0x0301 }, { 0x040D, 0x0418, 0x0300 }, { 0x040E, 0x0423, 0x0306 }, { 0x0419, 0x0418, 0x0306 }, { 0x0439, 0x0438, 0x0306 }, { 0x0450, 0x0435, 0x0300 }, { 0x0451, 0x0435, 0x0308 }, { 0x0453, 0x0433, 0x0301 }, { 0x0457, 0x0456, 0x0308 }, { 0x045C, 0x043A, 0x0301 }, { 0x045D, 0x0438, 0x0300 }, { 0x045E, 0x0443, 0x0306 }, { 0x0476, 0x0474, 0x030F }, { 0x0477, 0x0475, 0x030F }, { 0x04C1, 0x0416, 0x0306 }, { 0x04C2, 0x0436, 0x0306 }, { 0x04D0, 0x0410, 0x0306 }, { 0x04D1, 0x0430, 0x0306 }, { 0x04D2, 0x0410, 0x0308 }, { 0x04D3, 0x0430, 0x0308 }, { 0x04D6, 0x0415, 0x0306 }, { 0x04D7, 0x0435, 0x0306 }, { 0x04DA, 0x04D8, 0x0308 }, { 0x04DB, 0x04D9, 0x0308 }, { 0x04DC, 0x0416, 0x0308 }, { 0x04DD, 0x0436, 0x0308 }, { 0x04DE, 0x0417, 0x0308 }, { 0x04DF, 0x0437, 0x0308 }, { 0x04E2, 0x0418, 0x0304 }, { 0x04E3, 0x0438, 0x0304 }, { 0x04E4, 0x0418, 0x0308 }, { 0x04E5, 0x0438, 0x0308 }, { 0x04E6, 0x041E, 0x0308 }, { 0x04E7, 0x043E, 0x0308 }, { 0x04EA, 0x04E8, 0x0308 }, { 0x04EB, 0x04E9, 0x0308 }, { 0x04EC, 0x042D, 0x0308 }, { 0x04ED, 0x044D, 0x0308 }, { 0x04EE, 0x0423, 0x0304 }, { 0x04EF, 0x0443, 0x0304 }, { 0x04F0, 0x0423, 0x0308 }, { 0x04F1, 0x0443, 0x0308 }, { 0x04F2, 0x0423, 0x030B }, { 0x04F3, 0x0443, 0x030B }, { 0x04F4, 0x0427, 0x0308 }, { 0x04F5, 0x0447, 0x0308 }, { 0x04F8, 0x042B, 0x0308 }, { 0x04F9, 0x044B, 0x0308 }, { 0x0622, 0x0627, 0x0653 }, { 0x0623, 0x0627, 0x0654 }, { 0x0624, 0x0648, 0x0654 }, { 0x0625, 0x0627, 0x0655 }, { 0x0626, 0x064A, 0x0654 }, { 0x06C0, 0x06D5, 0x0654 }, { 0x06C2, 0x06C1, 0x0654 }, { 0x06D3, 0x06D2, 0x0654 }, { 0x0929, 0x0928, 0x093C }, { 0x0931, 0x0930, 0x093C }, { 0x0934, 0x0933, 0x093C }, { 0x0958, 0x0915, 0x093C }, { 0x0959, 0x0916, 0x093C }, { 0x095A, 0x0917, 0x093C }, { 0x095B, 0x091C, 0x093C }, { 0x095C, 0x0921, 0x093C }, { 0x095D, 0x0922, 0x093C }, { 0x095E, 0x092B, 0x093C }, { 0x095F, 0x092F, 0x093C }, { 0x09CB, 0x09C7, 0x09BE }, { 0x09CC, 0x09C7, 0x09D7 }, { 0x09DC, 0x09A1, 0x09BC }, { 0x09DD, 0x09A2, 0x09BC }, { 0x09DF, 0x09AF, 0x09BC }, { 0x0A33, 0x0A32, 0x0A3C }, { 0x0A36, 0x0A38, 0x0A3C }, { 0x0A59, 0x0A16, 0x0A3C }, { 0x0A5A, 0x0A17, 0x0A3C }, { 0x0A5B, 0x0A1C, 0x0A3C }, { 0x0A5E, 0x0A2B, 0x0A3C }, { 0x0B48, 0x0B47, 0x0B56 }, { 0x0B4B, 0x0B47, 0x0B3E }, { 0x0B4C, 0x0B47, 0x0B57 }, { 0x0B5C, 0x0B21, 0x0B3C }, { 0x0B5D, 0x0B22, 0x0B3C }, { 0x0B94, 0x0B92, 0x0BD7 }, { 0x0BCA, 0x0BC6, 0x0BBE }, { 0x0BCB, 0x0BC7, 0x0BBE }, { 0x0BCC, 0x0BC6, 0x0BD7 }, { 0x0C48, 0x0C46, 0x0C56 }, { 0x0CC0, 0x0CBF, 0x0CD5 }, { 0x0CC7, 0x0CC6, 0x0CD5 }, { 0x0CC8, 0x0CC6, 0x0CD6 }, { 0x0CCA, 0x0CC6, 0x0CC2 }, { 0x0CCB, 0x0CCA, 0x0CD5 }, { 0x0D4A, 0x0D46, 0x0D3E }, { 0x0D4B, 0x0D47, 0x0D3E }, { 0x0D4C, 0x0D46, 0x0D57 }, { 0x0DDA, 0x0DD9, 0x0DCA }, { 0x0DDC, 0x0DD9, 0x0DCF }, { 0x0DDD, 0x0DDC, 0x0DCA }, { 0x0DDE, 0x0DD9, 0x0DDF }, { 0x0F43, 0x0F42, 0x0FB7 }, { 0x0F4D, 0x0F4C, 0x0FB7 }, { 0x0F52, 0x0F51, 0x0FB7 }, { 0x0F57, 0x0F56, 0x0FB7 }, { 0x0F5C, 0x0F5B, 0x0FB7 }, { 0x0F69, 0x0F40, 0x0FB5 }, { 0x0F73, 0x0F71, 0x0F72 }, { 0x0F75, 0x0F71, 0x0F74 }, { 0x0F76, 0x0FB2, 0x0F80 }, { 0x0F78, 0x0FB3, 0x0F80 }, { 0x0F81, 0x0F71, 0x0F80 }, { 0x0F93, 0x0F92, 0x0FB7 }, { 0x0F9D, 0x0F9C, 0x0FB7 }, { 0x0FA2, 0x0FA1, 0x0FB7 }, { 0x0FA7, 0x0FA6, 0x0FB7 }, { 0x0FAC, 0x0FAB, 0x0FB7 }, { 0x0FB9, 0x0F90, 0x0FB5 }, { 0x1026, 0x1025, 0x102E }, { 0x1E00, 0x0041, 0x0325 }, { 0x1E01, 0x0061, 0x0325 }, { 0x1E02, 0x0042, 0x0307 }, { 0x1E03, 0x0062, 0x0307 }, { 0x1E04, 0x0042, 0x0323 }, { 0x1E05, 0x0062, 0x0323 }, { 0x1E06, 0x0042, 0x0331 }, { 0x1E07, 0x0062, 0x0331 }, { 0x1E08, 0x00C7, 0x0301 }, { 0x1E09, 0x00E7, 0x0301 }, { 0x1E0A, 0x0044, 0x0307 }, { 0x1E0B, 0x0064, 0x0307 }, { 0x1E0C, 0x0044, 0x0323 }, { 0x1E0D, 0x0064, 0x0323 }, { 0x1E0E, 0x0044, 0x0331 }, { 0x1E0F, 0x0064, 0x0331 }, { 0x1E10, 0x0044, 0x0327 }, { 0x1E11, 0x0064, 0x0327 }, { 0x1E12, 0x0044, 0x032D }, { 0x1E13, 0x0064, 0x032D }, { 0x1E14, 0x0112, 0x0300 }, { 0x1E15, 0x0113, 0x0300 }, { 0x1E16, 0x0112, 0x0301 }, { 0x1E17, 0x0113, 0x0301 }, { 0x1E18, 0x0045, 0x032D }, { 0x1E19, 0x0065, 0x032D }, { 0x1E1A, 0x0045, 0x0330 }, { 0x1E1B, 0x0065, 0x0330 }, { 0x1E1C, 0x0228, 0x0306 }, { 0x1E1D, 0x0229, 0x0306 }, { 0x1E1E, 0x0046, 0x0307 }, { 0x1E1F, 0x0066, 0x0307 }, { 0x1E20, 0x0047, 0x0304 }, { 0x1E21, 0x0067, 0x0304 }, { 0x1E22, 0x0048, 0x0307 }, { 0x1E23, 0x0068, 0x0307 }, { 0x1E24, 0x0048, 0x0323 }, { 0x1E25, 0x0068, 0x0323 }, { 0x1E26, 0x0048, 0x0308 }, { 0x1E27, 0x0068, 0x0308 }, { 0x1E28, 0x0048, 0x0327 }, { 0x1E29, 0x0068, 0x0327 }, { 0x1E2A, 0x0048, 0x032E }, { 0x1E2B, 0x0068, 0x032E }, { 0x1E2C, 0x0049, 0x0330 }, { 0x1E2D, 0x0069, 0x0330 }, { 0x1E2E, 0x00CF, 0x0301 }, { 0x1E2F, 0x00EF, 0x0301 }, { 0x1E30, 0x004B, 0x0301 }, { 0x1E31, 0x006B, 0x0301 }, { 0x1E32, 0x004B, 0x0323 }, { 0x1E33, 0x006B, 0x0323 }, { 0x1E34, 0x004B, 0x0331 }, { 0x1E35, 0x006B, 0x0331 }, { 0x1E36, 0x004C, 0x0323 }, { 0x1E37, 0x006C, 0x0323 }, { 0x1E38, 0x1E36, 0x0304 }, { 0x1E39, 0x1E37, 0x0304 }, { 0x1E3A, 0x004C, 0x0331 }, { 0x1E3B, 0x006C, 0x0331 }, { 0x1E3C, 0x004C, 0x032D }, { 0x1E3D, 0x006C, 0x032D }, { 0x1E3E, 0x004D, 0x0301 }, { 0x1E3F, 0x006D, 0x0301 }, { 0x1E40, 0x004D, 0x0307 }, { 0x1E41, 0x006D, 0x0307 }, { 0x1E42, 0x004D, 0x0323 }, { 0x1E43, 0x006D, 0x0323 }, { 0x1E44, 0x004E, 0x0307 }, { 0x1E45, 0x006E, 0x0307 }, { 0x1E46, 0x004E, 0x0323 }, { 0x1E47, 0x006E, 0x0323 }, { 0x1E48, 0x004E, 0x0331 }, { 0x1E49, 0x006E, 0x0331 }, { 0x1E4A, 0x004E, 0x032D }, { 0x1E4B, 0x006E, 0x032D }, { 0x1E4C, 0x00D5, 0x0301 }, { 0x1E4D, 0x00F5, 0x0301 }, { 0x1E4E, 0x00D5, 0x0308 }, { 0x1E4F, 0x00F5, 0x0308 }, { 0x1E50, 0x014C, 0x0300 }, { 0x1E51, 0x014D, 0x0300 }, { 0x1E52, 0x014C, 0x0301 }, { 0x1E53, 0x014D, 0x0301 }, { 0x1E54, 0x0050, 0x0301 }, { 0x1E55, 0x0070, 0x0301 }, { 0x1E56, 0x0050, 0x0307 }, { 0x1E57, 0x0070, 0x0307 }, { 0x1E58, 0x0052, 0x0307 }, { 0x1E59, 0x0072, 0x0307 }, { 0x1E5A, 0x0052, 0x0323 }, { 0x1E5B, 0x0072, 0x0323 }, { 0x1E5C, 0x1E5A, 0x0304 }, { 0x1E5D, 0x1E5B, 0x0304 }, { 0x1E5E, 0x0052, 0x0331 }, { 0x1E5F, 0x0072, 0x0331 }, { 0x1E60, 0x0053, 0x0307 }, { 0x1E61, 0x0073, 0x0307 }, { 0x1E62, 0x0053, 0x0323 }, { 0x1E63, 0x0073, 0x0323 }, { 0x1E64, 0x015A, 0x0307 }, { 0x1E65, 0x015B, 0x0307 }, { 0x1E66, 0x0160, 0x0307 }, { 0x1E67, 0x0161, 0x0307 }, { 0x1E68, 0x1E62, 0x0307 }, { 0x1E69, 0x1E63, 0x0307 }, { 0x1E6A, 0x0054, 0x0307 }, { 0x1E6B, 0x0074, 0x0307 }, { 0x1E6C, 0x0054, 0x0323 }, { 0x1E6D, 0x0074, 0x0323 }, { 0x1E6E, 0x0054, 0x0331 }, { 0x1E6F, 0x0074, 0x0331 }, { 0x1E70, 0x0054, 0x032D }, { 0x1E71, 0x0074, 0x032D }, { 0x1E72, 0x0055, 0x0324 }, { 0x1E73, 0x0075, 0x0324 }, { 0x1E74, 0x0055, 0x0330 }, { 0x1E75, 0x0075, 0x0330 }, { 0x1E76, 0x0055, 0x032D }, { 0x1E77, 0x0075, 0x032D }, { 0x1E78, 0x0168, 0x0301 }, { 0x1E79, 0x0169, 0x0301 }, { 0x1E7A, 0x016A, 0x0308 }, { 0x1E7B, 0x016B, 0x0308 }, { 0x1E7C, 0x0056, 0x0303 }, { 0x1E7D, 0x0076, 0x0303 }, { 0x1E7E, 0x0056, 0x0323 }, { 0x1E7F, 0x0076, 0x0323 }, { 0x1E80, 0x0057, 0x0300 }, { 0x1E81, 0x0077, 0x0300 }, { 0x1E82, 0x0057, 0x0301 }, { 0x1E83, 0x0077, 0x0301 }, { 0x1E84, 0x0057, 0x0308 }, { 0x1E85, 0x0077, 0x0308 }, { 0x1E86, 0x0057, 0x0307 }, { 0x1E87, 0x0077, 0x0307 }, { 0x1E88, 0x0057, 0x0323 }, { 0x1E89, 0x0077, 0x0323 }, { 0x1E8A, 0x0058, 0x0307 }, { 0x1E8B, 0x0078, 0x0307 }, { 0x1E8C, 0x0058, 0x0308 }, { 0x1E8D, 0x0078, 0x0308 }, { 0x1E8E, 0x0059, 0x0307 }, { 0x1E8F, 0x0079, 0x0307 }, { 0x1E90, 0x005A, 0x0302 }, { 0x1E91, 0x007A, 0x0302 }, { 0x1E92, 0x005A, 0x0323 }, { 0x1E93, 0x007A, 0x0323 }, { 0x1E94, 0x005A, 0x0331 }, { 0x1E95, 0x007A, 0x0331 }, { 0x1E96, 0x0068, 0x0331 }, { 0x1E97, 0x0074, 0x0308 }, { 0x1E98, 0x0077, 0x030A }, { 0x1E99, 0x0079, 0x030A }, { 0x1E9B, 0x017F, 0x0307 }, { 0x1EA0, 0x0041, 0x0323 }, { 0x1EA1, 0x0061, 0x0323 }, { 0x1EA2, 0x0041, 0x0309 }, { 0x1EA3, 0x0061, 0x0309 }, { 0x1EA4, 0x00C2, 0x0301 }, { 0x1EA5, 0x00E2, 0x0301 }, { 0x1EA6, 0x00C2, 0x0300 }, { 0x1EA7, 0x00E2, 0x0300 }, { 0x1EA8, 0x00C2, 0x0309 }, { 0x1EA9, 0x00E2, 0x0309 }, { 0x1EAA, 0x00C2, 0x0303 }, { 0x1EAB, 0x00E2, 0x0303 }, { 0x1EAC, 0x1EA0, 0x0302 }, { 0x1EAD, 0x1EA1, 0x0302 }, { 0x1EAE, 0x0102, 0x0301 }, { 0x1EAF, 0x0103, 0x0301 }, { 0x1EB0, 0x0102, 0x0300 }, { 0x1EB1, 0x0103, 0x0300 }, { 0x1EB2, 0x0102, 0x0309 }, { 0x1EB3, 0x0103, 0x0309 }, { 0x1EB4, 0x0102, 0x0303 }, { 0x1EB5, 0x0103, 0x0303 }, { 0x1EB6, 0x1EA0, 0x0306 }, { 0x1EB7, 0x1EA1, 0x0306 }, { 0x1EB8, 0x0045, 0x0323 }, { 0x1EB9, 0x0065, 0x0323 }, { 0x1EBA, 0x0045, 0x0309 }, { 0x1EBB, 0x0065, 0x0309 }, { 0x1EBC, 0x0045, 0x0303 }, { 0x1EBD, 0x0065, 0x0303 }, { 0x1EBE, 0x00CA, 0x0301 }, { 0x1EBF, 0x00EA, 0x0301 }, { 0x1EC0, 0x00CA, 0x0300 }, { 0x1EC1, 0x00EA, 0x0300 }, { 0x1EC2, 0x00CA, 0x0309 }, { 0x1EC3, 0x00EA, 0x0309 }, { 0x1EC4, 0x00CA, 0x0303 }, { 0x1EC5, 0x00EA, 0x0303 }, { 0x1EC6, 0x1EB8, 0x0302 }, { 0x1EC7, 0x1EB9, 0x0302 }, { 0x1EC8, 0x0049, 0x0309 }, { 0x1EC9, 0x0069, 0x0309 }, { 0x1ECA, 0x0049, 0x0323 }, { 0x1ECB, 0x0069, 0x0323 }, { 0x1ECC, 0x004F, 0x0323 }, { 0x1ECD, 0x006F, 0x0323 }, { 0x1ECE, 0x004F, 0x0309 }, { 0x1ECF, 0x006F, 0x0309 }, { 0x1ED0, 0x00D4, 0x0301 }, { 0x1ED1, 0x00F4, 0x0301 }, { 0x1ED2, 0x00D4, 0x0300 }, { 0x1ED3, 0x00F4, 0x0300 }, { 0x1ED4, 0x00D4, 0x0309 }, { 0x1ED5, 0x00F4, 0x0309 }, { 0x1ED6, 0x00D4, 0x0303 }, { 0x1ED7, 0x00F4, 0x0303 }, { 0x1ED8, 0x1ECC, 0x0302 }, { 0x1ED9, 0x1ECD, 0x0302 }, { 0x1EDA, 0x01A0, 0x0301 }, { 0x1EDB, 0x01A1, 0x0301 }, { 0x1EDC, 0x01A0, 0x0300 }, { 0x1EDD, 0x01A1, 0x0300 }, { 0x1EDE, 0x01A0, 0x0309 }, { 0x1EDF, 0x01A1, 0x0309 }, { 0x1EE0, 0x01A0, 0x0303 }, { 0x1EE1, 0x01A1, 0x0303 }, { 0x1EE2, 0x01A0, 0x0323 }, { 0x1EE3, 0x01A1, 0x0323 }, { 0x1EE4, 0x0055, 0x0323 }, { 0x1EE5, 0x0075, 0x0323 }, { 0x1EE6, 0x0055, 0x0309 }, { 0x1EE7, 0x0075, 0x0309 }, { 0x1EE8, 0x01AF, 0x0301 }, { 0x1EE9, 0x01B0, 0x0301 }, { 0x1EEA, 0x01AF, 0x0300 }, { 0x1EEB, 0x01B0, 0x0300 }, { 0x1EEC, 0x01AF, 0x0309 }, { 0x1EED, 0x01B0, 0x0309 }, { 0x1EEE, 0x01AF, 0x0303 }, { 0x1EEF, 0x01B0, 0x0303 }, { 0x1EF0, 0x01AF, 0x0323 }, { 0x1EF1, 0x01B0, 0x0323 }, { 0x1EF2, 0x0059, 0x0300 }, { 0x1EF3, 0x0079, 0x0300 }, { 0x1EF4, 0x0059, 0x0323 }, { 0x1EF5, 0x0079, 0x0323 }, { 0x1EF6, 0x0059, 0x0309 }, { 0x1EF7, 0x0079, 0x0309 }, { 0x1EF8, 0x0059, 0x0303 }, { 0x1EF9, 0x0079, 0x0303 }, { 0x1F00, 0x03B1, 0x0313 }, { 0x1F01, 0x03B1, 0x0314 }, { 0x1F02, 0x1F00, 0x0300 }, { 0x1F03, 0x1F01, 0x0300 }, { 0x1F04, 0x1F00, 0x0301 }, { 0x1F05, 0x1F01, 0x0301 }, { 0x1F06, 0x1F00, 0x0342 }, { 0x1F07, 0x1F01, 0x0342 }, { 0x1F08, 0x0391, 0x0313 }, { 0x1F09, 0x0391, 0x0314 }, { 0x1F0A, 0x1F08, 0x0300 }, { 0x1F0B, 0x1F09, 0x0300 }, { 0x1F0C, 0x1F08, 0x0301 }, { 0x1F0D, 0x1F09, 0x0301 }, { 0x1F0E, 0x1F08, 0x0342 }, { 0x1F0F, 0x1F09, 0x0342 }, { 0x1F10, 0x03B5, 0x0313 }, { 0x1F11, 0x03B5, 0x0314 }, { 0x1F12, 0x1F10, 0x0300 }, { 0x1F13, 0x1F11, 0x0300 }, { 0x1F14, 0x1F10, 0x0301 }, { 0x1F15, 0x1F11, 0x0301 }, { 0x1F18, 0x0395, 0x0313 }, { 0x1F19, 0x0395, 0x0314 }, { 0x1F1A, 0x1F18, 0x0300 }, { 0x1F1B, 0x1F19, 0x0300 }, { 0x1F1C, 0x1F18, 0x0301 }, { 0x1F1D, 0x1F19, 0x0301 }, { 0x1F20, 0x03B7, 0x0313 }, { 0x1F21, 0x03B7, 0x0314 }, { 0x1F22, 0x1F20, 0x0300 }, { 0x1F23, 0x1F21, 0x0300 }, { 0x1F24, 0x1F20, 0x0301 }, { 0x1F25, 0x1F21, 0x0301 }, { 0x1F26, 0x1F20, 0x0342 }, { 0x1F27, 0x1F21, 0x0342 }, { 0x1F28, 0x0397, 0x0313 }, { 0x1F29, 0x0397, 0x0314 }, { 0x1F2A, 0x1F28, 0x0300 }, { 0x1F2B, 0x1F29, 0x0300 }, { 0x1F2C, 0x1F28, 0x0301 }, { 0x1F2D, 0x1F29, 0x0301 }, { 0x1F2E, 0x1F28, 0x0342 }, { 0x1F2F, 0x1F29, 0x0342 }, { 0x1F30, 0x03B9, 0x0313 }, { 0x1F31, 0x03B9, 0x0314 }, { 0x1F32, 0x1F30, 0x0300 }, { 0x1F33, 0x1F31, 0x0300 }, { 0x1F34, 0x1F30, 0x0301 }, { 0x1F35, 0x1F31, 0x0301 }, { 0x1F36, 0x1F30, 0x0342 }, { 0x1F37, 0x1F31, 0x0342 }, { 0x1F38, 0x0399, 0x0313 }, { 0x1F39, 0x0399, 0x0314 }, { 0x1F3A, 0x1F38, 0x0300 }, { 0x1F3B, 0x1F39, 0x0300 }, { 0x1F3C, 0x1F38, 0x0301 }, { 0x1F3D, 0x1F39, 0x0301 }, { 0x1F3E, 0x1F38, 0x0342 }, { 0x1F3F, 0x1F39, 0x0342 }, { 0x1F40, 0x03BF, 0x0313 }, { 0x1F41, 0x03BF, 0x0314 }, { 0x1F42, 0x1F40, 0x0300 }, { 0x1F43, 0x1F41, 0x0300 }, { 0x1F44, 0x1F40, 0x0301 }, { 0x1F45, 0x1F41, 0x0301 }, { 0x1F48, 0x039F, 0x0313 }, { 0x1F49, 0x039F, 0x0314 }, { 0x1F4A, 0x1F48, 0x0300 }, { 0x1F4B, 0x1F49, 0x0300 }, { 0x1F4C, 0x1F48, 0x0301 }, { 0x1F4D, 0x1F49, 0x0301 }, { 0x1F50, 0x03C5, 0x0313 }, { 0x1F51, 0x03C5, 0x0314 }, { 0x1F52, 0x1F50, 0x0300 }, { 0x1F53, 0x1F51, 0x0300 }, { 0x1F54, 0x1F50, 0x0301 }, { 0x1F55, 0x1F51, 0x0301 }, { 0x1F56, 0x1F50, 0x0342 }, { 0x1F57, 0x1F51, 0x0342 }, { 0x1F59, 0x03A5, 0x0314 }, { 0x1F5B, 0x1F59, 0x0300 }, { 0x1F5D, 0x1F59, 0x0301 }, { 0x1F5F, 0x1F59, 0x0342 }, { 0x1F60, 0x03C9, 0x0313 }, { 0x1F61, 0x03C9, 0x0314 }, { 0x1F62, 0x1F60, 0x0300 }, { 0x1F63, 0x1F61, 0x0300 }, { 0x1F64, 0x1F60, 0x0301 }, { 0x1F65, 0x1F61, 0x0301 }, { 0x1F66, 0x1F60, 0x0342 }, { 0x1F67, 0x1F61, 0x0342 }, { 0x1F68, 0x03A9, 0x0313 }, { 0x1F69, 0x03A9, 0x0314 }, { 0x1F6A, 0x1F68, 0x0300 }, { 0x1F6B, 0x1F69, 0x0300 }, { 0x1F6C, 0x1F68, 0x0301 }, { 0x1F6D, 0x1F69, 0x0301 }, { 0x1F6E, 0x1F68, 0x0342 }, { 0x1F6F, 0x1F69, 0x0342 }, { 0x1F70, 0x03B1, 0x0300 }, { 0x1F72, 0x03B5, 0x0300 }, { 0x1F74, 0x03B7, 0x0300 }, { 0x1F76, 0x03B9, 0x0300 }, { 0x1F78, 0x03BF, 0x0300 }, { 0x1F7A, 0x03C5, 0x0300 }, { 0x1F7C, 0x03C9, 0x0300 }, { 0x1F80, 0x1F00, 0x0345 }, { 0x1F81, 0x1F01, 0x0345 }, { 0x1F82, 0x1F02, 0x0345 }, { 0x1F83, 0x1F03, 0x0345 }, { 0x1F84, 0x1F04, 0x0345 }, { 0x1F85, 0x1F05, 0x0345 }, { 0x1F86, 0x1F06, 0x0345 }, { 0x1F87, 0x1F07, 0x0345 }, { 0x1F88, 0x1F08, 0x0345 }, { 0x1F89, 0x1F09, 0x0345 }, { 0x1F8A, 0x1F0A, 0x0345 }, { 0x1F8B, 0x1F0B, 0x0345 }, { 0x1F8C, 0x1F0C, 0x0345 }, { 0x1F8D, 0x1F0D, 0x0345 }, { 0x1F8E, 0x1F0E, 0x0345 }, { 0x1F8F, 0x1F0F, 0x0345 }, { 0x1F90, 0x1F20, 0x0345 }, { 0x1F91, 0x1F21, 0x0345 }, { 0x1F92, 0x1F22, 0x0345 }, { 0x1F93, 0x1F23, 0x0345 }, { 0x1F94, 0x1F24, 0x0345 }, { 0x1F95, 0x1F25, 0x0345 }, { 0x1F96, 0x1F26, 0x0345 }, { 0x1F97, 0x1F27, 0x0345 }, { 0x1F98, 0x1F28, 0x0345 }, { 0x1F99, 0x1F29, 0x0345 }, { 0x1F9A, 0x1F2A, 0x0345 }, { 0x1F9B, 0x1F2B, 0x0345 }, { 0x1F9C, 0x1F2C, 0x0345 }, { 0x1F9D, 0x1F2D, 0x0345 }, { 0x1F9E, 0x1F2E, 0x0345 }, { 0x1F9F, 0x1F2F, 0x0345 }, { 0x1FA0, 0x1F60, 0x0345 }, { 0x1FA1, 0x1F61, 0x0345 }, { 0x1FA2, 0x1F62, 0x0345 }, { 0x1FA3, 0x1F63, 0x0345 }, { 0x1FA4, 0x1F64, 0x0345 }, { 0x1FA5, 0x1F65, 0x0345 }, { 0x1FA6, 0x1F66, 0x0345 }, { 0x1FA7, 0x1F67, 0x0345 }, { 0x1FA8, 0x1F68, 0x0345 }, { 0x1FA9, 0x1F69, 0x0345 }, { 0x1FAA, 0x1F6A, 0x0345 }, { 0x1FAB, 0x1F6B, 0x0345 }, { 0x1FAC, 0x1F6C, 0x0345 }, { 0x1FAD, 0x1F6D, 0x0345 }, { 0x1FAE, 0x1F6E, 0x0345 }, { 0x1FAF, 0x1F6F, 0x0345 }, { 0x1FB0, 0x03B1, 0x0306 }, { 0x1FB1, 0x03B1, 0x0304 }, { 0x1FB2, 0x1F70, 0x0345 }, { 0x1FB3, 0x03B1, 0x0345 }, { 0x1FB4, 0x03AC, 0x0345 }, { 0x1FB6, 0x03B1, 0x0342 }, { 0x1FB7, 0x1FB6, 0x0345 }, { 0x1FB8, 0x0391, 0x0306 }, { 0x1FB9, 0x0391, 0x0304 }, { 0x1FBA, 0x0391, 0x0300 }, { 0x1FBC, 0x0391, 0x0345 }, { 0x1FC1, 0x00A8, 0x0342 }, { 0x1FC2, 0x1F74, 0x0345 }, { 0x1FC3, 0x03B7, 0x0345 }, { 0x1FC4, 0x03AE, 0x0345 }, { 0x1FC6, 0x03B7, 0x0342 }, { 0x1FC7, 0x1FC6, 0x0345 }, { 0x1FC8, 0x0395, 0x0300 }, { 0x1FCA, 0x0397, 0x0300 }, { 0x1FCC, 0x0397, 0x0345 }, { 0x1FCD, 0x1FBF, 0x0300 }, { 0x1FCE, 0x1FBF, 0x0301 }, { 0x1FCF, 0x1FBF, 0x0342 }, { 0x1FD0, 0x03B9, 0x0306 }, { 0x1FD1, 0x03B9, 0x0304 }, { 0x1FD2, 0x03CA, 0x0300 }, { 0x1FD6, 0x03B9, 0x0342 }, { 0x1FD7, 0x03CA, 0x0342 }, { 0x1FD8, 0x0399, 0x0306 }, { 0x1FD9, 0x0399, 0x0304 }, { 0x1FDA, 0x0399, 0x0300 }, { 0x1FDD, 0x1FFE, 0x0300 }, { 0x1FDE, 0x1FFE, 0x0301 }, { 0x1FDF, 0x1FFE, 0x0342 }, { 0x1FE0, 0x03C5, 0x0306 }, { 0x1FE1, 0x03C5, 0x0304 }, { 0x1FE2, 0x03CB, 0x0300 }, { 0x1FE4, 0x03C1, 0x0313 }, { 0x1FE5, 0x03C1, 0x0314 }, { 0x1FE6, 0x03C5, 0x0342 }, { 0x1FE7, 0x03CB, 0x0342 }, { 0x1FE8, 0x03A5, 0x0306 }, { 0x1FE9, 0x03A5, 0x0304 }, { 0x1FEA, 0x03A5, 0x0300 }, { 0x1FEC, 0x03A1, 0x0314 }, { 0x1FED, 0x00A8, 0x0300 }, { 0x1FF2, 0x1F7C, 0x0345 }, { 0x1FF3, 0x03C9, 0x0345 }, { 0x1FF4, 0x03CE, 0x0345 }, { 0x1FF6, 0x03C9, 0x0342 }, { 0x1FF7, 0x1FF6, 0x0345 }, { 0x1FF8, 0x039F, 0x0300 }, { 0x1FFA, 0x03A9, 0x0300 }, { 0x1FFC, 0x03A9, 0x0345 }, { 0x219A, 0x2190, 0x0338 }, { 0x219B, 0x2192, 0x0338 }, { 0x21AE, 0x2194, 0x0338 }, { 0x21CD, 0x21D0, 0x0338 }, { 0x21CE, 0x21D4, 0x0338 }, { 0x21CF, 0x21D2, 0x0338 }, { 0x2204, 0x2203, 0x0338 }, { 0x2209, 0x2208, 0x0338 }, { 0x220C, 0x220B, 0x0338 }, { 0x2224, 0x2223, 0x0338 }, { 0x2226, 0x2225, 0x0338 }, { 0x2241, 0x223C, 0x0338 }, { 0x2244, 0x2243, 0x0338 }, { 0x2247, 0x2245, 0x0338 }, { 0x2249, 0x2248, 0x0338 }, { 0x2260, 0x003D, 0x0338 }, { 0x2262, 0x2261, 0x0338 }, { 0x226D, 0x224D, 0x0338 }, { 0x226E, 0x003C, 0x0338 }, { 0x226F, 0x003E, 0x0338 }, { 0x2270, 0x2264, 0x0338 }, { 0x2271, 0x2265, 0x0338 }, { 0x2274, 0x2272, 0x0338 }, { 0x2275, 0x2273, 0x0338 }, { 0x2278, 0x2276, 0x0338 }, { 0x2279, 0x2277, 0x0338 }, { 0x2280, 0x227A, 0x0338 }, { 0x2281, 0x227B, 0x0338 }, { 0x2284, 0x2282, 0x0338 }, { 0x2285, 0x2283, 0x0338 }, { 0x2288, 0x2286, 0x0338 }, { 0x2289, 0x2287, 0x0338 }, { 0x22AC, 0x22A2, 0x0338 }, { 0x22AD, 0x22A8, 0x0338 }, { 0x22AE, 0x22A9, 0x0338 }, { 0x22AF, 0x22AB, 0x0338 }, { 0x22E0, 0x227C, 0x0338 }, { 0x22E1, 0x227D, 0x0338 }, { 0x22E2, 0x2291, 0x0338 }, { 0x22E3, 0x2292, 0x0338 }, { 0x22EA, 0x22B2, 0x0338 }, { 0x22EB, 0x22B3, 0x0338 }, { 0x22EC, 0x22B4, 0x0338 }, { 0x22ED, 0x22B5, 0x0338 }, { 0x2ADC, 0x2ADD, 0x0338 }, { 0x304C, 0x304B, 0x3099 }, { 0x304E, 0x304D, 0x3099 }, { 0x3050, 0x304F, 0x3099 }, { 0x3052, 0x3051, 0x3099 }, { 0x3054, 0x3053, 0x3099 }, { 0x3056, 0x3055, 0x3099 }, { 0x3058, 0x3057, 0x3099 }, { 0x305A, 0x3059, 0x3099 }, { 0x305C, 0x305B, 0x3099 }, { 0x305E, 0x305D, 0x3099 }, { 0x3060, 0x305F, 0x3099 }, { 0x3062, 0x3061, 0x3099 }, { 0x3065, 0x3064, 0x3099 }, { 0x3067, 0x3066, 0x3099 }, { 0x3069, 0x3068, 0x3099 }, { 0x3070, 0x306F, 0x3099 }, { 0x3071, 0x306F, 0x309A }, { 0x3073, 0x3072, 0x3099 }, { 0x3074, 0x3072, 0x309A }, { 0x3076, 0x3075, 0x3099 }, { 0x3077, 0x3075, 0x309A }, { 0x3079, 0x3078, 0x3099 }, { 0x307A, 0x3078, 0x309A }, { 0x307C, 0x307B, 0x3099 }, { 0x307D, 0x307B, 0x309A }, { 0x3094, 0x3046, 0x3099 }, { 0x309E, 0x309D, 0x3099 }, { 0x30AC, 0x30AB, 0x3099 }, { 0x30AE, 0x30AD, 0x3099 }, { 0x30B0, 0x30AF, 0x3099 }, { 0x30B2, 0x30B1, 0x3099 }, { 0x30B4, 0x30B3, 0x3099 }, { 0x30B6, 0x30B5, 0x3099 }, { 0x30B8, 0x30B7, 0x3099 }, { 0x30BA, 0x30B9, 0x3099 }, { 0x30BC, 0x30BB, 0x3099 }, { 0x30BE, 0x30BD, 0x3099 }, { 0x30C0, 0x30BF, 0x3099 }, { 0x30C2, 0x30C1, 0x3099 }, { 0x30C5, 0x30C4, 0x3099 }, { 0x30C7, 0x30C6, 0x3099 }, { 0x30C9, 0x30C8, 0x3099 }, { 0x30D0, 0x30CF, 0x3099 }, { 0x30D1, 0x30CF, 0x309A }, { 0x30D3, 0x30D2, 0x3099 }, { 0x30D4, 0x30D2, 0x309A }, { 0x30D6, 0x30D5, 0x3099 }, { 0x30D7, 0x30D5, 0x309A }, { 0x30D9, 0x30D8, 0x3099 }, { 0x30DA, 0x30D8, 0x309A }, { 0x30DC, 0x30DB, 0x3099 }, { 0x30DD, 0x30DB, 0x309A }, { 0x30F4, 0x30A6, 0x3099 }, { 0x30F7, 0x30EF, 0x3099 }, { 0x30F8, 0x30F0, 0x3099 }, { 0x30F9, 0x30F1, 0x3099 }, { 0x30FA, 0x30F2, 0x3099 }, { 0x30FE, 0x30FD, 0x3099 }, { 0xFB1D, 0x05D9, 0x05B4 }, { 0xFB1F, 0x05F2, 0x05B7 }, { 0xFB2A, 0x05E9, 0x05C1 }, { 0xFB2B, 0x05E9, 0x05C2 }, { 0xFB2C, 0xFB49, 0x05C1 }, { 0xFB2D, 0xFB49, 0x05C2 }, { 0xFB2E, 0x05D0, 0x05B7 }, { 0xFB2F, 0x05D0, 0x05B8 }, { 0xFB30, 0x05D0, 0x05BC }, { 0xFB31, 0x05D1, 0x05BC }, { 0xFB32, 0x05D2, 0x05BC }, { 0xFB33, 0x05D3, 0x05BC }, { 0xFB34, 0x05D4, 0x05BC }, { 0xFB35, 0x05D5, 0x05BC }, { 0xFB36, 0x05D6, 0x05BC }, { 0xFB38, 0x05D8, 0x05BC }, { 0xFB39, 0x05D9, 0x05BC }, { 0xFB3A, 0x05DA, 0x05BC }, { 0xFB3B, 0x05DB, 0x05BC }, { 0xFB3C, 0x05DC, 0x05BC }, { 0xFB3E, 0x05DE, 0x05BC }, { 0xFB40, 0x05E0, 0x05BC }, { 0xFB41, 0x05E1, 0x05BC }, { 0xFB43, 0x05E3, 0x05BC }, { 0xFB44, 0x05E4, 0x05BC }, { 0xFB46, 0x05E6, 0x05BC }, { 0xFB47, 0x05E7, 0x05BC }, { 0xFB48, 0x05E8, 0x05BC }, { 0xFB49, 0x05E9, 0x05BC }, { 0xFB4A, 0x05EA, 0x05BC }, { 0xFB4B, 0x05D5, 0x05B9 }, { 0xFB4C, 0x05D1, 0x05BF }, { 0xFB4D, 0x05DB, 0x05BF }, { 0xFB4E, 0x05E4, 0x05BF }, /* out of range of unsigned short... */ #if 0 { 0x1D15E, 0x1D157, 0x1D165 }, { 0x1D15F, 0x1D158, 0x1D165 }, { 0x1D160, 0x1D15F, 0x1D16E }, { 0x1D161, 0x1D15F, 0x1D16F }, { 0x1D162, 0x1D15F, 0x1D170 }, { 0x1D163, 0x1D15F, 0x1D171 }, { 0x1D164, 0x1D15F, 0x1D172 }, { 0x1D1BB, 0x1D1B9, 0x1D165 }, { 0x1D1BC, 0x1D1BA, 0x1D165 }, { 0x1D1BD, 0x1D1BB, 0x1D16E }, { 0x1D1BE, 0x1D1BC, 0x1D16E }, { 0x1D1BF, 0x1D1BB, 0x1D16F }, { 0x1D1C0, 0x1D1BC, 0x1D16F }, #endif /* special hack, treat Arabic ligatures as combining characters */ /* combine them to the isolated presentation form, then let * the shaping and joining take care of it */ { 0xFEF5, 0x0644, 0x0622 }, /* LAM_ALEF_MADDA */ { 0xFEF7, 0x0644, 0x0623 }, /* LAM_ALEF_HAMZA_ABOVE */ { 0xFEF9, 0x0644, 0x0625 }, /* LAM_ALEF_HAMZA_BELOW */ { 0xFEFB, 0x0644, 0x0627 }, /* LAM_ALEF */ }; /* -------------------------- local functions ------------------------------ */ /* look-up functions, maybe theese should use binary search? would require a duplicate of comb_table to reverse map... */ static int get_combining_class(unsigned short ch) { int count; int table_size = sizeof(combclass_table) / sizeof(combclass_table[0]); for (count = 0; count < table_size; count++) { if (combclass_table[count].key == ch) { return combclass_table[count].combclass; } } return 0; } static const char_comb_t* get_comb_entry_decomposed(unsigned short ch) { int count; int table_size = sizeof(comb_table) / sizeof(comb_table[0]); for (count = 0; count < table_size; count++) { if (comb_table[count].key == ch) { return &comb_table[count]; } } return NULL; } static unsigned short get_comb_entry_composed(unsigned short first, unsigned short second) { int count; int table_size = sizeof(comb_table) / sizeof(comb_table[0]); for (count = 0; count < table_size; count++) { if (comb_table[count].first == first && comb_table[count].second == second) { return comb_table[count].key; } } return (unsigned short) 0; } static int convert_to_ucs2( const unsigned char *str_utf8, unsigned short *str_ucs2, int len) { int in_pos = 0; int out_pos = 0; while (in_pos < len) { if (str_utf8[in_pos] <= 0x7f) { str_ucs2[out_pos] = (unsigned short)str_utf8[in_pos]; in_pos++; } else { if ((str_utf8[in_pos] & 0300) != 0300) { /* out of sync */ str_ucs2[out_pos] = REPLACEMENT_CHARACTER; in_pos++; } else if (in_pos < len-1 && str_utf8[in_pos] <= 0xdf && str_utf8[in_pos + 1] <= 0xbf && str_utf8[in_pos + 1] >= 0x80) { str_ucs2[out_pos] = ((str_utf8[in_pos] & 0x1f) << 6) + (str_utf8[in_pos+1] & 0x3f); /* check for overlong sequence */ if(str_ucs2[out_pos] < 0x80) str_ucs2[out_pos] = REPLACEMENT_CHARACTER; in_pos += 2; } else if (in_pos < len-2 && str_utf8[in_pos] <= 0xef && str_utf8[in_pos + 1] <= 0xbf && str_utf8[in_pos + 1] >= 0x80 && str_utf8[in_pos + 2] <= 0xbf && str_utf8[in_pos + 2] >= 0x80) { str_ucs2[out_pos] = ((str_utf8[in_pos] & 0x0f) << 12) + ((str_utf8[in_pos+1] & 0x3f) << 6) + (str_utf8[in_pos+2] & 0x3f); /* check for overlong sequence */ if(str_ucs2[out_pos] < 0x800) str_ucs2[out_pos] = REPLACEMENT_CHARACTER; in_pos += 3; } else { /* incomplete sequence */ str_ucs2[out_pos] = REPLACEMENT_CHARACTER; in_pos++; } } out_pos++; } return out_pos; } static int convert_to_utf8( const unsigned short *str_ucs2, unsigned char *str_utf8, int len) { int in_pos = 0; int out_pos = 0; for (in_pos = 0 ; in_pos < len ; in_pos++) { if (str_ucs2[in_pos] <= 0x7f) { str_utf8[out_pos] = str_ucs2[in_pos]; out_pos++; } else if (str_ucs2[in_pos] <= 0x7ff) { str_utf8[out_pos] = (str_ucs2[in_pos] >> 6) | 0xc0; str_utf8[out_pos+1] = (str_ucs2[in_pos] & 0x3f) | 0x80; out_pos += 2; } else { str_utf8[out_pos] = (str_ucs2[in_pos] >> 12) | 0xe0; str_utf8[out_pos+1] = ((str_ucs2[in_pos] & 0xfff) >> 6) | 0x80; str_utf8[out_pos+2] = (str_ucs2[in_pos] & 0x3f) | 0x80; out_pos += 3; } /* this doesn't handle values outside UCS2 (16-bit) */ } return out_pos; } /* main procedure: takes a pointer to a string (UTF-8) first decomposes string, then rearrange combining characters, the combines them back. Result is stored in original string (can never be "expanded" from original size), new length is returned */ int CombineChars( unsigned char *str_visual, int len, superimpose_char_t **comb_chars, int **l_to_v) { int i,j,k; /* counters */ unsigned short *source; unsigned short *dest; int *source_v_to_l; int *dest_v_to_l; int str_len; int in_str_len; int out_str_len; int comp_str_len = 0; Bool has_changed; /* if input has zero length, return immediatly */ if (len == 0) { return 0; } /* decompose composed characters */ source = (unsigned short *)safemalloc( (len + 1) * sizeof(unsigned short)); /* convert from UTF-8-encoded text to internal 16-bit encoding */ str_len = convert_to_ucs2(str_visual,source,len); in_str_len = str_len; /* we don't really need to NULL-terminate source, since we have string length */ /* be pessimistic, assume all characters are decomposed */ dest = (unsigned short *)safemalloc( (str_len + 1) * 2 * sizeof(unsigned short)); /* use theese to keep track of the mapping of characters from logical to visual */ source_v_to_l = (int *)safemalloc(str_len * sizeof(int)); dest_v_to_l = (int *)safemalloc(str_len * 2 * sizeof(int)); /* setup initial mapping 1-to-1 */ for(i = 0 ; i < str_len ; i++) { source_v_to_l[i] = i; } do { has_changed = False; for (i = 0, j = 0; i < str_len; i++) { const char_comb_t *decomp = get_comb_entry_decomposed(source[i]); /* current character is decomposable */ if (decomp) { dest[j] = decomp->first; dest[j+1] = decomp->second; dest_v_to_l[j] = source_v_to_l[i]; dest_v_to_l[j+1] = source_v_to_l[i]; j += 2; has_changed = True; } else /* leave it as is */ { dest[j] = source[i]; dest_v_to_l[j] = source_v_to_l[i]; j++; } } /* now swap */ free(source); free(source_v_to_l); source = dest; source_v_to_l = dest_v_to_l; str_len = j; dest = (unsigned short *)safemalloc( (str_len + 1) * 2 * sizeof(unsigned short)); dest_v_to_l = (int *)safemalloc(str_len * 2 * sizeof(int)); } while (has_changed); /* source now holds decomposed string (got swapped before exiting loop, str_len holds string length */ /* we reuse dest for composing, can use existing string lengths since it will only get shorter */ /* source_v_to_l holds the mapping from positions in decomposed string to original string */ /* rearrange combining characters */ do { has_changed = False; for (i = 0; i < str_len - 1; i++) { /* swap if combining-class(c1) > combining-class(c2) and combining-class(c2) != 0 */ /* use negative values for marks that have combining class 0, but should be taken out for drawing superimposed */ int c1 = get_combining_class(source[i]); int c2 = get_combining_class(source[i+1]); if (c1 > c2 && c2 > 0) { unsigned short temp = source[i]; int temp_v_to_l = source_v_to_l[i]; source[i] = source[i+1]; source[i+1] = temp; source_v_to_l[i] = source_v_to_l[i+1]; source_v_to_l[i+1] = temp_v_to_l; has_changed = True; } } } while (has_changed); /* compose */ do { unsigned short *temp; int *temp_v_to_l; Bool last_changed = False; has_changed = False; for (i = 0, j = 0; i < str_len - 1; j++) { unsigned short composed = get_comb_entry_composed(source[i], source[i+1]); dest_v_to_l[j] = source_v_to_l[i]; if (composed != 0) { dest[j] = composed; /* if the last character was "absorbed" */ if (i == str_len - 2) { last_changed = True; } i += 2; has_changed = True; } else { dest[j] = source[i]; i++; } } temp = dest; dest = source; source = temp; temp_v_to_l = dest_v_to_l; dest_v_to_l = source_v_to_l; source_v_to_l = temp_v_to_l; /* fixup the last character, the loop above goes to second last, since it needs to look at 2 consecutive, if the last character is a non-combining character */ /* since we have an immediate return on zero length, this works otherwise this would introduce crap here */ if (!last_changed) { source[j] = dest[i]; source_v_to_l[j] = dest_v_to_l[i]; str_len = j+1; } else { str_len = j; } } while (has_changed); /* source contains composed string */ /* gather "uncomposed" combining characters here for rendering over normal characters later */ comp_str_len = 0; if (comb_chars != NULL) { /* calculate number of combining characters left */ for (i = 0 ; i < str_len ; i++) { if (get_combining_class(source[i]) != 0) { comp_str_len++; } } /* allocate storage for combining characters */ *comb_chars = (superimpose_char_t *) safemalloc((comp_str_len + 1) * sizeof(superimpose_char_t)); } for (i = 0,j = 0,k = 0 ; i < str_len ; i++) { /* if character is non-combining, just copy it over to output */ /* if first character is a combing character, just output it as if it where a base character */ if (get_combining_class(source[i]) == 0) { dest[j] = source[i]; dest_v_to_l[j] = source_v_to_l[i]; j++; } else { if (comb_chars != NULL) { /* store composing character as associated with last base charcter */ (*comb_chars)[k].position = j == 0 ? 0 : j-1; (*comb_chars)[k].c.byte1 = source[i] >> 8; (*comb_chars)[k].c.byte2 = source[i] & 0xff; k++; } } } /* terminate */ if (comb_chars != NULL) { (*comb_chars)[comp_str_len].position = 0; (*comb_chars)[comp_str_len].c.byte1 = 0; (*comb_chars)[comp_str_len].c.byte2 = 0; } str_len = convert_to_utf8(dest,str_visual,j); out_str_len = j; str_visual[str_len] = 0; if(l_to_v != NULL) { *l_to_v = (int *)safemalloc((in_str_len + 1) * sizeof(int)); /* map the visual to logical mapping obtained above into a logical to visual mapping */ /* setup the final mapping from logical to visual positions */ /* if no base characters out, all positions map to zero, because there we have combining chars in that case */ if(out_str_len == 0) { for(i = 0 ; i < in_str_len ; i++) { (*l_to_v)[i] = 0; } } for(i = 0, j = 0 ; i < out_str_len ; i++) { /* for each element in mapping from visual string insert "backtracked" references from logical string by inserting consequitive entries, as many as the step in the mapping from visual to logical */ int step = (i == out_str_len - 1) ? in_str_len - j : dest_v_to_l[i+1] - dest_v_to_l[i]; for(k = 0 ; k < step ; k++, j++) { (*l_to_v)[j] = i; } } /* terminated it with -1, to avoid have to send around lenghts */ (*l_to_v)[in_str_len] = -1; } /* clean up */ free(source); free(dest); free(source_v_to_l); free(dest_v_to_l); return str_len; } fvwm-2.7.0/libs/setpgrp.h0000644000175000017500000000014414147024676012220 00000000000000/* -*-c-*- */ #ifndef SETPGRP_H #define SETPGRP_H int fvwm_setpgrp(void); #endif /* SETPGRP_H */ fvwm-2.7.0/libs/fvwmrect.c0000644000175000017500000000751414147024700012360 00000000000000/* -*-c-*- */ /* Copyright (C) 2001 Dominik Vogt */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ** fvwmrect.c: ** This file supplies routines for fvwm internal rectangle handling. */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include "fvwmrect.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* ---------------------------- local functions ---------------------------- */ static int fvwmrect_do_intervals_intersect( int x1, int width1, int x2, int width2) { return !(x1 + width1 <= x2 || x2 + width2 <= x1); } /* ---------------------------- interface functions ------------------------ */ /* Returns 1 if the given rectangles intersect and 0 otherwise */ int fvwmrect_do_rectangles_intersect(rectangle *r, rectangle *s) { if (r->x + r->width <= s->x) { return 0; } if (s->x + s->width <= r->x) { return 0; } if (r->y + r->height <= s->y) { return 0; } if (s->y + s->height <= r->y) { return 0; } return 1; } /* Subtracts the values in s2_ from the ones in s1_g and stores the result in * diff_g. */ void fvwmrect_subtract_rectangles( rectangle *rdiff, rectangle *r1, rectangle *r2) { rdiff->x = r1->x - r2->x; rdiff->y = r1->y - r2->y; rdiff->width = r1->width - r2->width; rdiff->height = r1->height - r2->height; return; } /* Returns 1 is the rectangles are identical and 0 if not */ int fvwmrect_rectangles_equal( rectangle *r1, rectangle *r2) { if (r1 == r2) { return 1; } if (r1 == NULL || r2 == NULL) { return 0; } if (r1->x != r2->x || r1->y != r2->y || r1->width != r2->width || r1->height != r2->height) { return 1; } return 0; } int fvwmrect_move_into_rectangle(rectangle *move_rec, rectangle *target_rec) { int has_changed = 0; if (!fvwmrect_do_intervals_intersect( move_rec->x, move_rec->width, target_rec->x, target_rec->width)) { move_rec->x = move_rec->x % (int)target_rec->width; if (move_rec->x < 0) { move_rec->x += target_rec->width; } move_rec->x += target_rec->x; has_changed = 1; } if (!fvwmrect_do_intervals_intersect( move_rec->y, move_rec->height, target_rec->y, target_rec->height)) { move_rec->y = move_rec->y % (int)target_rec->height; if (move_rec->y < 0) { move_rec->y += target_rec->height; } move_rec->y += target_rec->y; has_changed = 1; } return has_changed; } int fvwmrect_intersect_xrectangles( XRectangle *r1, XRectangle *r2) { int x1 = max(r1->x, r2->x); int y1 = max(r1->y, r2->y); int x2 = min(r1->x + r1->width, r2->x + r2->width); int y2 = min(r1->y + r1->height, r2->y + r2->height); r1->x = x1; r1->y = y1; r1->width = x2 - x1; r1->height = y2 - y1; if (x2 > x1 && y2 > y1) { return 1; } else { return 0; } } fvwm-2.7.0/libs/wild.h0000644000175000017500000000070614147024700011463 00000000000000/* -*-c-*- */ /* * Does `string' match `pattern'? '*' in pattern matches any sub-string * (including the null string) '?' matches any single char. For use * by filenameforall. Note that '*' matches across directory boundaries * * This code donated by Paul Hudson * It is public domain, no strings attached. No guarantees either. * */ int matchWildcards(const char *pattern, const char *string); fvwm-2.7.0/libs/PictureUtils.c0000644000175000017500000015330414147024700013156 00000000000000/* -*-c-*- */ /* Copyright (C) 1993, Robert Nation * Copyright (C) 2002 Olivier Chapuis */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include #include #include #include #include "fvwmlib.h" #include "envvar.h" #include "Grab.h" #include "Parse.h" #include "ftime.h" #include "PictureBase.h" #include "PictureUtils.h" #include "PictureDitherMatrice.h" /* ---------------------------- local definitions and macro ----------------- */ #if 0 /* dv: unused */ /* form alloc_in_cmap from the xpm lib */ #define XPM_DIST(r1,g1,b1,r2,g2,b2) (long)\ (3*(abs((long)r1-(long)r2) + \ abs((long)g1-(long)g2) + \ abs((long)b1-(long)b2)) + \ abs((long)r1 + (long)g1 + (long)b1 - \ ((long)r2 + (long)g2 + (long)b2))) #define XPM_COLOR_CLOSENESS 40000 #endif #define SQUARE(X) ((X)*(X)) #define TRUE_DIST(r1,g1,b1,r2,g2,b2) (long)\ (SQUARE((long)((r1 - r2)>>8)) \ + SQUARE((long)((g1 - g2)>>8)) \ + SQUARE((long)((b1 - b2)>>8))) #define FAST_DIST(r1,g1,b1,r2,g2,b2) (long)\ (abs((long)(r1 - r2)) \ + abs((long)(g1 - g2)) \ + abs((long)(b1 - b2))) #define FVWM_DIST(r1,g1,b1,r2,g2,b2) \ (abs(r1 - r2) + abs(g1 - g2) + abs(b1 - b2) \ + 2*abs(abs(r1-g1) + abs(g1-b1) + abs(r1-b1) \ - abs(r2-g2) - abs(g2-b2) - abs(r2-b2))) #define USED_DIST(r1,g1,b1,r2,g2,b2) FVWM_DIST(r1,g1,b1,r2,g2,b2) #define PICTURE_COLOR_CLOSENESS USED_DIST(3,3,3,0,0,0) #define PICTURE_PAllocTable 1000000 #define PICTURE_PUseDynamicColors 100000 #define PICTURE_PStrictColorLimit 10000 #define PICTURE_use_named 1000 #define PICTURE_TABLETYPE_LENGHT 7 /* humm ... dither is probably borken with gamma correction. Anyway I do * do think that using gamma correction for the colors cubes is a good * idea */ #define USE_GAMMA_CORECTION 0 /* 2.2 is recommanded by the Poynon colors FAQ, some others suggest 1.5 and 2 * Use float constants!*/ #define COLOR_GAMMA 1.5 #define GREY_GAMMA 2.0 /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ typedef struct { XColor color; /* rgb color info */ unsigned long alloc_count; /* nbr of allocation */ } PColor; typedef struct { /* * info for colors table (depth <= 8) */ /* color cube used */ short nr; short ng; short nb; short ngrey; /* grey palette def, nbr of grey = 2^grey_bits */ short grey_bits; /* color cube used for dithering with the named table */ short d_nr; short d_ng; short d_nb; short d_ngrey_bits; /* do we found a pre-allocated pallet ? */ Bool pre_allocated_pallet; /* info for depth > 8 */ int red_shift; int green_shift; int blue_shift; int red_prec; int green_prec; int blue_prec; /* for dithering in depth 15 and 16 */ unsigned short *red_dither; unsigned short *green_dither; unsigned short *blue_dither; /* colors allocation function */ int (*alloc_color)(Display *dpy, Colormap cmap, XColor *c); int (*alloc_color_no_limit)(Display *dpy, Colormap cmap, XColor *c); int (*alloc_color_dither)( Display *dpy, Colormap cmap, XColor *c, int x, int y); void (*free_colors)( Display *dpy, Colormap cmap, Pixel *pixels, int n, unsigned long planes); void (*free_colors_no_limit)( Display *dpy, Colormap cmap, Pixel *pixels, int n, unsigned long planes); } PColorsInfo; typedef struct { int cols_index; long closeness; } CloseColor; /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ static int PColorLimit = 0; static PColor *Pct = NULL; static PColor *Pac = NULL; static short *PMappingTable = NULL; static short *PDitherMappingTable = NULL; static Bool PStrictColorLimit = 0; static Bool PAllocTable = 0; static PColorsInfo Pcsi = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL}; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ /* * get shift and prec from a mask */ static void decompose_mask( unsigned long mask, int *shift, int *prec) { *shift = 0; *prec = 0; while (!(mask & 0x1)) { (*shift)++; mask >>= 1; } while (mask & 0x1) { (*prec)++; mask >>= 1; } } /* * color allocation in the colormap. strongly inspired by SetCloseColor from * the Xpm library (depth <= 8) */ static int closeness_cmp(const void *a, const void *b) { CloseColor *x = (CloseColor *) a, *y = (CloseColor *) b; /* cast to int as qsort requires */ return (int) (x->closeness - y->closeness); } static int alloc_color_in_cmap(XColor *c, Bool force) { static XColor colors[256]; CloseColor closenesses[256]; XColor tmp; int i,j; int map_entries = (Pvisual->class == DirectColor)? (1 << Pdepth) : Pvisual->map_entries; time_t current_time; time_t last_time = 0; map_entries = (map_entries > 256)? 256:map_entries; current_time = time(NULL); if (current_time - last_time >= 2 || force) { last_time = current_time; for (i = 0; i < map_entries; i++) { colors[i].pixel = i; } XQueryColors(Pdpy, Pcmap, colors, map_entries); } for(i = 0; i < map_entries; i++) { closenesses[i].cols_index = i; closenesses[i].closeness = USED_DIST( (int)(c->red), (int)(c->green), (int)(c->blue), (int)(colors[i].red), (int)(colors[i].green), (int)(colors[i].blue)); } qsort(closenesses, map_entries, sizeof(CloseColor), closeness_cmp); i = 0; j = closenesses[i].cols_index; while (force || (abs((long)c->red - (long)colors[j].red) <= PICTURE_COLOR_CLOSENESS && abs((long)c->green - (long)colors[j].green) <= PICTURE_COLOR_CLOSENESS && abs((long)c->blue - (long)colors[j].blue) <= PICTURE_COLOR_CLOSENESS)) { tmp.red = colors[j].red; tmp.green = colors[j].green; tmp.blue = colors[j].blue; if (XAllocColor(Pdpy, Pcmap, &tmp)) { c->red = tmp.red; c->green = tmp.green; c->blue = tmp.blue; c->pixel = tmp.pixel; return 1; } else { i++; if (i == map_entries) break; j = closenesses[i].cols_index; } } return 0; } /* * dithering */ static int my_dither(int x, int y, XColor *c) { /* the dither matrice */ static const char DM[128][128] = DITHER_MATRICE; int index; const char *dmp; if (Pcsi.grey_bits != 0) { /* Grey Scale */ int prec = Pcsi.grey_bits; if (Pcsi.grey_bits == 1) { /* FIXME, can we do a better dithering */ prec = 2; } dmp = DM[(0 + y) & (DM_HEIGHT - 1)]; index = (c->green + ((c->blue + c->red) >> 1)) >> 1; index += (dmp[(0 + x) & (DM_WIDTH - 1)] << 2) >> prec; index = (index - (index >> prec)); index = index >> (8 - Pcsi.grey_bits); } else { /* color cube */ int dith, rs, gs, bs, gb, b; int tr,tb,tg; rs = Pcsi.d_nr - 1; gs = Pcsi.d_ng - 1; bs = Pcsi.d_nb - 1; gb = Pcsi.d_ng*Pcsi.d_nb; b = Pcsi.d_nb; dmp = DM[(0 + y) & (DM_HEIGHT - 1)]; dith = (dmp[(0 + x) & (DM_WIDTH - 1)] << 2) | 7; tr = ((c->red * rs) + dith) >> 8; tg = ((c->green * gs) + (262 - dith)) >> 8; tb = ((c->blue * bs) + dith) >> 8; index = tr * gb + tg * b + tb; #if 0 /* try to use the additonal grey. Not easy, good for * certain image/gradient bad for others */ if (Pcsi.d_ngrey_bits) { int g_index; /* dither in the Pcsi.ngrey^3 cc */ tr = ((c->red * (Pcsi.ngrey-1)) + dith) >> 8; tg = ((c->green * (Pcsi.ngrey-1)) + (262 - dith)) >> 8; tb = ((c->blue * (Pcsi.ngrey-1)) + dith) >> 8; /* get the grey */ fprintf(stderr, "%i,%i,%i(%i/%i) ", tr,tg,tb, abs(tr-tg) + abs(tb-tg) + abs(tb-tr),Pcsi.ngrey); g_index = ((tr + tg + tb)/3); if (g_index != 0 && g_index != Pcsi.ngrey-1 && abs(tr-tg) + abs(tb-tg) + abs(tb-tr) <= Pcsi.d_ngrey_bits) { g_index = g_index + Pcsi.ng*Pcsi.nb*Pcsi.ng -1; index = g_index; } } #endif if (PDitherMappingTable != NULL) { index = PDitherMappingTable[index]; } } return index; } static int my_dither_depth_15_16_init(void) { const unsigned char _dither_44[4][4] = { {0, 4, 1, 5}, {6, 2, 7, 3}, {1, 5, 0, 4}, {7, 3, 6, 2} }; int y,x,i; int rm = 0xf8, re = 0x7, gm = 0xfc, ge = 0x3, bm = 0xf8, be = 0x7; if (Pdepth == 16 && (Pvisual->red_mask == 0xf800) && (Pvisual->green_mask == 0x7e0) && (Pvisual->blue_mask == 0x1f)) { /* ok */ } else if (Pdepth == 15 && (Pvisual->red_mask == 0x7c00) && (Pvisual->green_mask == 0x3e0) && (Pvisual->blue_mask == 0x1f)) { gm = 0xf8; ge = 0x7; } else { return 0; /* fail */ } Pcsi.red_dither = (unsigned short *)safemalloc(4*4*256*sizeof(unsigned short)); Pcsi.green_dither = (unsigned short *)safemalloc(4*4*256*sizeof(unsigned short)); Pcsi.blue_dither = (unsigned short *)safemalloc(4*4*256*sizeof(unsigned short)); for (y = 0; y < 4; y++) { for (x = 0; x < 4; x++) { for (i = 0; i < 256; i++) { if ((_dither_44[x][y] < (i & re)) && (i < (256 - 8))) { Pcsi.red_dither[ (x << 10) | (y << 8) | i] = ((i + 8) & rm) << 8; } else { Pcsi.red_dither[ (x << 10) | (y << 8) | i] = (i & rm) << 8; } if ((_dither_44[x][y] < ((i & ge) << 1)) && (i < (256 - 4))) { Pcsi.green_dither[ (x << 10) | (y << 8) | i] = ((i + 4) & gm) << 8; } else { Pcsi.green_dither[ (x << 10) | (y << 8) | i] = (i & gm) << 8; } if ((_dither_44[x][y] < (i & be)) && (i < (256 - 8))) { Pcsi.blue_dither[ (x << 10) | (y << 8) | i] = ((i + 8) & bm) << 8; } else { Pcsi.blue_dither[ (x << 10) | (y << 8) | i] = (i & bm) << 8; } } } } return 1; } /* * Color allocation in the "palette" */ static int alloc_color_in_pct(XColor *c, int index) { if (Pct[index].alloc_count == 0) { int s = PStrictColorLimit; PStrictColorLimit = 0; c->red = Pct[index].color.red; c->green = Pct[index].color.green; c->blue = Pct[index].color.blue; PictureAllocColor(Pdpy, Pcmap, c, True); /* WARN (rec) */ Pct[index].color.pixel = c->pixel; Pct[index].alloc_count = 1; PStrictColorLimit = s; } else { c->red = Pct[index].color.red; c->green = Pct[index].color.green; c->blue = Pct[index].color.blue; c->pixel = Pct[index].color.pixel; if (Pct[index].alloc_count < 0xffffffff) (Pct[index].alloc_count)++; } return 1; } static int get_color_index(int r, int g, int b, int is_8) { int index; if (!is_8) { r= r >> 8; g= g >> 8; b= b >> 8; } if (Pcsi.grey_bits > 0) { /* FIXME: Use other proporition ? */ index = ((r+g+b)/3) >> (8 - Pcsi.grey_bits); } else { #if 1 /* "exact" computation (corrected linear dist) */ float fr,fg,fb; int ir, ig, ib; /* map to the cube */ fr = ((float)r * (Pcsi.nr-1))/255; fg = ((float)g * (Pcsi.ng-1))/255; fb = ((float)b * (Pcsi.nb-1))/255; if (PMappingTable != NULL) { ir = (int)fr + (fr - (int)fr > 0.5); ig = (int)fg + (fg - (int)fg > 0.5); ib = (int)fb + (fb - (int)fb > 0.5); index = ir * Pcsi.ng*Pcsi.nb + ig * Pcsi.nb + ib; } else { /* found the best of the 8 linear closest points */ int lr,lg,lb,tr,tg,tb,best_dist = -1,i,d; index = 0; lr = min((int)fr+1,Pcsi.nr-1); lg = min((int)fg+1,Pcsi.ng-1); lb = min((int)fb+1,Pcsi.nb-1); for(tr =(int)fr; tr<=lr; tr++) { for(tg =(int)fg; tg<=lg; tg++) { for(tb =(int)fb; tb<=lb; tb++) { i = tr * Pcsi.ng*Pcsi.nb + tg * Pcsi.nb + tb; d = USED_DIST( r,g,b, (Pct[i].color.red>>8), (Pct[i].color.green>>8), (Pct[i].color.blue>>8)); if (best_dist == -1 || d < best_dist) { index = i; best_dist = d; } } } } /* now found the best grey */ if (Pcsi.ngrey - 2 > 0) { /* FIXME: speedup this with more than 8 grey */ int start = Pcsi.nr*Pcsi.ng*Pcsi.nb; for(i=start; i < start+Pcsi.ngrey-2; i++) { d = USED_DIST( r,g,b, (Pct[i].color.red>>8), (Pct[i].color.green>>8), (Pct[i].color.blue>>8)); if (d < best_dist) { index = i; best_dist = d; } } } return index; } #else /* approximation; faster */ index = ((r * Pcsi.nr)>>8) * Pcsi.ng*Pcsi.nb + ((g * Pcsi.ng)>>8) * Pcsi.nb + ((b * Pcsi.nb)>>8); #endif if (PMappingTable != NULL) { index = PMappingTable[index]; } } return index; } /* * Main colors allocator */ static int alloc_color_proportion(Display *dpy, Colormap cmap, XColor *c) { c->pixel = (Pixel)( ((c->red >> (16 - Pcsi.red_prec))<< Pcsi.red_shift) + ((c->green >> (16 - Pcsi.green_prec))<< Pcsi.green_shift) + ((c->blue >> (16 - Pcsi.blue_prec))<< Pcsi.blue_shift) ); return 1; } static int alloc_color_proportion_dither( Display *dpy, Colormap cmap, XColor *c, int x, int y) { /* 8 bit colors !! */ c->red = Pcsi.red_dither[ (((x + 0) & 0x3) << 10) | ((y & 0x3) << 8) | ((c->red) & 0xff)] * 257; c->green = Pcsi.green_dither[ (((x + 0) & 0x3) << 10) | ((y & 0x3) << 8) | ((c->green) & 0xff)] * 257; c->blue = Pcsi.blue_dither[ (((x + 0) & 0x3) << 10) | ((y & 0x3) << 8) | ((c->blue) & 0xff)] * 257; c->pixel = (Pixel)( ((c->red >> (16 - Pcsi.red_prec)) << Pcsi.red_shift) + ((c->green >> (16 - Pcsi.green_prec)) << Pcsi.green_shift) + ((c->blue >> (16 - Pcsi.blue_prec)) << Pcsi.blue_shift) ); return 1; } static int alloc_color_proportion_grey( Display *dpy, Colormap cmap, XColor *c) { /* FIXME: is this ok in general? */ c->pixel = ((c->red + c->green + c->blue)/3); if (Pdepth < 16) { c->pixel = c->pixel >> (16 - Pdepth); } return 1; } static int alloc_color_in_table(Display *dpy, Colormap cmap, XColor *c) { int index = get_color_index(c->red,c->green,c->blue, False); return alloc_color_in_pct(c, index); } static int alloc_color_in_table_dither( Display *dpy, Colormap cmap, XColor *c, int x, int y) { int index; /* 8 bit colors !! */ index = my_dither(x, y, c); return alloc_color_in_pct(c, index); } static int alloc_color_dynamic_no_limit( Display *dpy, Colormap cmap, XColor *c) { int r = 0; if (XAllocColor(dpy, cmap, c)) { r = 1; } else if (!alloc_color_in_cmap(c, False)) { MyXGrabServer(dpy); r = alloc_color_in_cmap(c, True); MyXUngrabServer(dpy); } else { r = 1; } if (r && Pac != NULL && (c->pixel <= (1 << Pdepth) /* always true*/)) { Pac[c->pixel].alloc_count++; Pac[c->pixel].color.red = c->red; Pac[c->pixel].color.green = c->green; Pac[c->pixel].color.blue = c->blue; Pac[c->pixel].color.pixel = c->pixel; } return r; } static int alloc_color_x( Display *dpy, Colormap cmap, XColor *c) { return XAllocColor(dpy, cmap, c); } static void free_colors_in_table( Display *dpy, Colormap cmap, Pixel *pixels, int n, unsigned long planes) { Pixel *p; int i,j,do_free; int m = 0; if (!Pct || !PUseDynamicColors) { return; } p = (Pixel *)safemalloc(n*sizeof(Pixel)); for(i= 0; i < n; i++) { do_free = 1; for(j=0; j 0) { XFreeColors(dpy, cmap, p, m, planes); } free(p); return; } static void free_colors_x( Display *dpy, Colormap cmap, Pixel *pixels, int n, unsigned long planes) { XFreeColors(dpy, cmap, pixels, n, planes); if (Pac != NULL) { int nbr_colors = (1 << Pdepth); int i; for(i= 0; i < n; i++) { if (pixels[i] <= nbr_colors) { Pac[pixels[i]].alloc_count--; } } } } /* * local function for building pallet (dynamic colors, private DirectColor * cmap) */ static XColor *build_mapping_colors(int nr, int ng, int nb) { int r, g, b, i; XColor *colors; colors = (XColor *)safemalloc(nr*ng*nb * sizeof(XColor)); i = 0; for (r = 0; r < nr; r++) { for (g = 0; g < ng; g++) { for (b = 0; b < nb; b++) { colors[i].red = r * 65535 / (nr - 1); colors[i].green = g * 65535 / (ng - 1); colors[i].blue = b * 65535 / (nb - 1); i++; } } } return colors; } static short *build_mapping_table(int nr, int ng, int nb, Bool use_named) { int size = nr*ng*nb; XColor *colors_map; short *Table; int i,j, minind; double mindst = 40000; double dst; colors_map = build_mapping_colors(nr, ng, nb); Table = (short *)safemalloc((size+1) * sizeof(short)); for(i=0; i 0) { for(i = 0; i < npixels; i++) { if (color_table[i].alloc_count) { pixels[n++] = color_table[i].color.pixel; } color_table[i].alloc_count = 0; } if (n > 0) { XFreeColors(Pdpy, Pcmap, pixels, n, 0); } } } /* FIXME: the DirectColor case */ static int get_nbr_of_free_colors(int max_check) { int check = 1; Pixel Pixels[256]; int map_entries = (Pvisual->class == DirectColor)? (1 << Pdepth):Pvisual->map_entries; if (max_check < 1) return 0; if (map_entries > 256) { max_check = 256; } max_check = (max_check > map_entries) ? map_entries:max_check; while(1) { if (XAllocColorCells( Pdpy, Pcmap, False, NULL, 0, Pixels, check)) { XFreeColors(Pdpy, Pcmap, Pixels, check, 0); check++; } else { return check-1; } if (check > max_check) { return check-1; } } return check-1; } static PColor *alloc_color_cube( int nr, int ng, int nb, int ngrey, int grey_bits, Bool do_allocate) { int r, g, b, grey, i, start_grey, end_grey; PColor *color_table; XColor color; int size; size = nr*ng*nb + ngrey + (1 << grey_bits)*(grey_bits != 0); if (grey_bits) { ngrey = (1 << grey_bits); } if (nr > 0 && ngrey > 0) { start_grey = 1; end_grey = ngrey - 1; size = size - 2; } else { start_grey = 0; end_grey = ngrey; } color_table = (PColor *)safemalloc((size+1) * sizeof(PColor)); i = 0; #if USE_GAMMA_CORECTION #define CG(x) 65535.0 * pow((x)/65535.0,1/COLOR_GAMMA) #define GG(x) 65535.0 * pow((x)/65535.0,1/GREY_GAMMA) #else #define CG(x) x #define GG(x) x #endif if (nr > 0) { for (r = 0; r < nr; r++) { for (g = 0; g < ng; g++) { for (b = 0; b < nb; b++) { color.red = CG(r * 65535 / (nr - 1)); color.green = CG(g * 65535 / (ng - 1)); color.blue = CG(b * 65535 / (nb - 1)); if (do_allocate) { if (!XAllocColor(Pdpy, Pcmap, &color)) { free_table_colors( color_table, i); free(color_table); return NULL; } color_table[i].color.pixel = color.pixel; color_table[i].alloc_count = 1; } else { color_table[i].alloc_count = 0; } color_table[i].color.red = color.red; color_table[i].color.green = color.green; color_table[i].color.blue = color.blue; i++; } } } } if (ngrey > 0) { for (grey = start_grey; grey < end_grey; grey++) { color.red = color.green = color.blue = GG(grey * 65535 / (ngrey - 1)); if (do_allocate) { if (!XAllocColor(Pdpy, Pcmap, &color)) { free_table_colors(color_table, i); free(color_table); return NULL; } color_table[i].color.pixel = color.pixel; color_table[i].alloc_count = 1; } else { color_table[i].alloc_count = 0; } color_table[i].color.red = color.red; color_table[i].color.green = color.green; color_table[i].color.blue = color.blue; i++; } } color_table[size].color.red = color_table[size-1].color.red; color_table[size].color.green = color_table[size-1].color.green; color_table[size].color.blue = color_table[size-1].color.blue; color_table[size].color.pixel = color_table[size-1].color.pixel; color_table[size].alloc_count = 0; PColorLimit = size; return color_table; } static PColor *alloc_named_ct(int *limit, Bool do_allocate) { /* First thing in base array are colors probably already in the color map because they have familiar names. I pasted them into a xpm and spread them out so that similar colors are spread out. Toward the end are some colors to fill in the gaps. Currently 61 colors in this list. */ char *color_names[] = { "black", "white", "grey", "green", "blue", "red", "cyan", "yellow", "magenta", "DodgerBlue", "SteelBlue", "chartreuse", "wheat", "turquoise", "CadetBlue", "gray87", "CornflowerBlue", "YellowGreen", "NavyBlue", "MediumBlue", "plum", "aquamarine", "orchid", "ForestGreen", "lightyellow", "brown", "orange", "red3", "HotPink", "LightBlue", "gray47", "pink", "red4", "violet", "purple", "gray63", "gray94", "plum1", "PeachPuff", "maroon", "lavender", "salmon", /* for peachpuff, orange gap */ "blue4", /* for navyblue/mediumblue gap */ "PaleGreen4", /* for forestgreen, yellowgreen gap */ "#AA7700", /* brick, no close named color */ "#11EE88", /* light green, no close named color */ "#884466", /* dark brown, no close named color */ "#CC8888", /* light brick, no close named color */ "#EECC44", /* gold, no close named color */ "#AAAA44", /* dull green, no close named color */ "#FF1188", /* pinkish red */ "#992299", /* purple */ "#CCFFAA", /* light green */ "#664400", /* dark brown*/ "#AADD99", /* light green */ "#66CCFF", /* light blue */ "#CC2299", /* dark red */ "#FF11CC", /* bright pink */ "#11CC99", /* grey/green */ "#AA77AA", /* purple/red */ "#EEBB77" /* orange/yellow */ }; int NColors = sizeof(color_names)/sizeof(char *); int i,rc; PColor *color_table; XColor color; *limit = (*limit > NColors)? NColors: *limit; color_table = (PColor *)safemalloc((*limit+1) * sizeof(PColor)); for(i=0; i<*limit; i++) { rc=XParseColor(Pdpy, Pcmap, color_names[i], &color); if (rc==0) { fprintf(stderr,"color_to_rgb: can't parse color %s," " rc %d\n", color_names[i], rc); free_table_colors(color_table, i); free(color_table); return NULL; } if (do_allocate) { if (!XAllocColor(Pdpy, Pcmap, &color)) { free_table_colors(color_table, i); free(color_table); return NULL; } color_table[i].color.pixel = color.pixel; color_table[i].alloc_count = 1; } else { color_table[i].alloc_count = 0; } color_table[i].color.red = color.red; color_table[i].color.green = color.green; color_table[i].color.blue = color.blue; } color_table[*limit].color.red = color_table[*limit-1].color.red; color_table[*limit].color.green = color_table[*limit-1].color.green; color_table[*limit].color.blue = color_table[*limit-1].color.blue; color_table[*limit].color.pixel = color_table[*limit-1].color.pixel; color_table[*limit].alloc_count = 0; PColorLimit = *limit; return color_table; } static void create_mapping_table( int nr, int ng, int nb, int ngrey, int grey_bits, Bool non_regular_pallet) { Pcsi.grey_bits = 0; /* initialize dithering colors numbers */ if (!non_regular_pallet) { /* */ Pcsi.d_nr = nr; Pcsi.d_ng = ng; Pcsi.d_nb = nb; Pcsi.d_ngrey_bits = 2; while((1< 0) { Pcsi.nr = 0; Pcsi.ng = 0; Pcsi.nb = 0; Pcsi.ngrey = 0; Pcsi.grey_bits = grey_bits; } else if (non_regular_pallet || (0&&ngrey>0)) { /* note: using these table with !used_named && ngrey>0 will * probably leads to faster image loading. But I see nothing * of significative. On the others hands not using it gives * maybe better colors approximation. */ if (PColorLimit <= 9) { Pcsi.nr = 8; Pcsi.ng = 8; Pcsi.nb = 8; Pcsi.ngrey = 0; } else { Pcsi.nr = 16; Pcsi.ng = 16; Pcsi.nb = 16; Pcsi.ngrey = 0; } PMappingTable = build_mapping_table( Pcsi.nr, Pcsi.ng, Pcsi.nb, non_regular_pallet); } else { Pcsi.nr = nr; Pcsi.ng = ng; Pcsi.nb = nb; Pcsi.ngrey = ngrey; Pcsi.grey_bits = 0; } } static void finish_ct_init( int call_type, int ctt, int nr, int ng, int nb, int ngrey, int grey_bits, Bool use_named) { if (call_type == PICTURE_CALLED_BY_FVWM) { char *env; if (PAllocTable) { ctt = PICTURE_PAllocTable + ctt; } if (PUseDynamicColors) { ctt = PICTURE_PUseDynamicColors + ctt; } if (PStrictColorLimit) { ctt = PICTURE_PStrictColorLimit + ctt; } if (use_named) { ctt = PICTURE_use_named + ctt; } else { ctt++; } env = safemalloc(PICTURE_TABLETYPE_LENGHT + 1); sprintf(env, "%i", ctt); flib_putenv("FVWM_COLORTABLE_TYPE", env); free(env); if (Pdepth <= 8) { Pac = (PColor *)safecalloc( (1 << Pdepth), sizeof(PColor)); } } if (Pct) { if (!PAllocTable && call_type == PICTURE_CALLED_BY_FVWM) { free_table_colors(Pct, PColorLimit); } create_mapping_table(nr,ng,nb,ngrey,grey_bits,use_named); } } #define PA_COLOR_CUBE (1 << 1) #define FVWM_COLOR_CUBE (1 << 2) #define PA_GRAY_SCALE (1 << 3) #define FVWM_GRAY_SCALE (1 << 4) #define ANY_COLOR_CUBE (PA_COLOR_CUBE|FVWM_COLOR_CUBE) #define ANY_GRAY_SCALE (PA_GRAY_SCALE|FVWM_GRAY_SCALE) static int PictureAllocColorTable( PictureColorLimitOption *opt, int call_type, Bool use_my_color_limit) { char *envp; int free_colors, nbr_of_color, limit, cc_nbr, i, size; int use_named_table = 0; int do_allocate = 0; int use_default = 1; int private_cmap = !(Pdefault); int color_limit; int pa_type = (Pvisual->class != GrayScale) ? PA_COLOR_CUBE : PA_GRAY_SCALE; int fvwm_type = (Pvisual->class != GrayScale) ? FVWM_COLOR_CUBE : FVWM_GRAY_SCALE; int cc[][6] = { /* {nr,ng,nb,ngrey,grey_bits,logic} */ /* 5 first for direct colors and Pdepth > 8*/ /* 8192 colors depth 13, a reasonable max for a color table */ {16, 32, 16, 0, 0, FVWM_COLOR_CUBE}, /* 4096 colors depth 12 */ {16, 16, 16, 0, 0, FVWM_COLOR_CUBE}, /* 1024 colors depth 10 */ {8, 16, 8, 0, 0, FVWM_COLOR_CUBE}, /* 512 colors depth 9 */ {8, 8, 8, 0, 0, FVWM_COLOR_CUBE}, /* 256 colors 3/3/2 standard colormap */ {8, 8, 4, 0, 0, FVWM_COLOR_CUBE}, /* 256 grey scale */ {0, 0, 0, 0, 8, ANY_GRAY_SCALE}, /* 244 Xrender XFree-4.2 */ {6, 6, 6, 30, 0, ANY_COLOR_CUBE}, /* 216 Xrender XFree-4.2,GTK/QT "default cc" */ {6, 6, 6, 0, 0, ANY_COLOR_CUBE}, /* 180 (GTK) */ {6, 6, 5, 0, 0, ANY_COLOR_CUBE}, /* 144 (GTK) */ {6, 6, 4, 0, 0, ANY_COLOR_CUBE}, /* 128 grey scale */ {0, 0, 0, 0, 7, ANY_GRAY_SCALE}, /* 125 GTK mini default cc (may change? 444) */ {5, 5, 5, 0, 0, ANY_COLOR_CUBE}, /* 100 (GTK with color limit) */ {5, 5, 4, 0, 0, ANY_COLOR_CUBE}, /* 85 Xrender XFree-4.3 */ {4, 4, 4, 23, 0, ANY_COLOR_CUBE}, /* 78 (in fact 76) a good default ??*/ {4, 4, 4, 16, 0, FVWM_COLOR_CUBE}, /* 70 a good default ?? */ {4, 4, 4, 8, 0, ANY_COLOR_CUBE}, /* 68 a good default ?? */ {4, 4, 4, 6, 0, ANY_COLOR_CUBE}, /* 64 Xrender XFree-4.3 (GTK wcl) */ {4, 4, 4, 0, 0, ANY_COLOR_CUBE}, /* 64 grey scale */ {0, 0, 0, 0, 6, ANY_GRAY_SCALE}, /* 54, maybe a good default? */ {4, 4, 3, 8, 0, FVWM_COLOR_CUBE}, /* 48, (GTK wcl) no grey but ok */ {4, 4, 3, 0, 0, FVWM_COLOR_CUBE}, /* 32, 2/2/1 standard colormap */ {4, 4, 2, 0, 0, FVWM_COLOR_CUBE}, /* 32 xrender xfree-4.2 */ {0, 0, 0, 0, 6, ANY_GRAY_SCALE}, /* 29 */ {3, 3, 3, 4, 0, FVWM_COLOR_CUBE}, /* 27 (xrender in depth 6&7(hypo) GTK wcl) */ {3, 3, 3, 0, 0, FVWM_COLOR_CUBE|PA_COLOR_CUBE*(Pdepth<8)}, /* 16 grey scale */ {0, 0, 0, 0, 4, FVWM_GRAY_SCALE}, /* 10 */ {2, 2, 2, 4, 0, FVWM_COLOR_CUBE}, /* 8 (xrender/qt/gtk wcl) */ {2, 2, 2, 0, 0, FVWM_COLOR_CUBE}, /* 8 grey scale Xrender depth 4 and XFree-4.3 */ {0, 0, 0, 0, 3, FVWM_GRAY_SCALE|PA_GRAY_SCALE*(Pdepth<5)}, /* 4 grey scale*/ {0, 0, 0, 0, 2, FVWM_GRAY_SCALE|FVWM_COLOR_CUBE|PA_COLOR_CUBE*(Pdepth<4)}, /* 2 */ {0, 0, 0, 0, 1, FVWM_COLOR_CUBE|FVWM_GRAY_SCALE} }; cc_nbr = sizeof(cc)/(sizeof(cc[0])); /* set up default */ PStrictColorLimit = 0; PUseDynamicColors = 1; PAllocTable = 0; use_named_table = False; color_limit = 0; use_default = True; /* use fvwm color limit */ if (!use_my_color_limit && (envp = getenv("FVWM_COLORTABLE_TYPE")) != NULL) { int nr = 0, ng = 0, nb = 0, grey_bits = 0, ngrey = 0; int ctt = atoi(envp); if (ctt >= PICTURE_PAllocTable) { ctt -= PICTURE_PAllocTable; PAllocTable = 1; /* not useful for a module !*/ } if (ctt >= PICTURE_PUseDynamicColors) { PUseDynamicColors = 1; ctt -= PICTURE_PUseDynamicColors; } if (ctt >= PICTURE_PStrictColorLimit) { PStrictColorLimit = 1; ctt -= PICTURE_PStrictColorLimit; } if (ctt >= PICTURE_use_named) { ctt -= PICTURE_use_named; Pct = alloc_named_ct(&ctt, False); use_named_table = True; } else if (ctt == 0) { /* depth <= 8 and no colors limit ! */ PColorLimit = 0; return 0; } else if (ctt <= cc_nbr) { ctt--; Pct = alloc_color_cube( cc[ctt][0], cc[ctt][1], cc[ctt][2], cc[ctt][3], cc[ctt][4], False); nr = cc[ctt][0]; ng = cc[ctt][1]; nb = cc[ctt][2]; ngrey = cc[ctt][3]; grey_bits = cc[ctt][4]; } if (Pct != NULL) { /* should always happen */ finish_ct_init( call_type, ctt, nr, ng, nb, ngrey, grey_bits, use_named_table); return PColorLimit; } } nbr_of_color = (1 << Pdepth); color_limit = 0; /* parse the color limit env variable */ if ((envp = getenv("FVWM_COLORLIMIT")) != NULL) { char *rest, *l; rest = GetQuotedString(envp, &l, ":", NULL, NULL, NULL); if (l && *l != '\0' && (color_limit = atoi(l)) >= 0) { use_default = 0; } if (l != NULL) { free(l); } if (color_limit == 9 || color_limit == 61) { use_named_table = 1; } if (rest && *rest != '\0') { if (rest[0] == '1') { PStrictColorLimit = 1; } else { PStrictColorLimit = 0; } if (strlen(rest) > 1 && rest[1] == '1') { use_named_table = 1; } else { use_named_table = 0; } if (strlen(rest) > 2 && rest[2] == '1') { PUseDynamicColors = 1; } else { PUseDynamicColors = 0; } if (strlen(rest) > 3 && rest[3] == '1') { PAllocTable = 1; } else { PAllocTable = 0; } } } else if (opt != NULL) /* use the option */ { if (opt->color_limit > 0) { use_default = 0; color_limit = opt->color_limit; } if (color_limit == 9 || color_limit == 61) { use_named_table = 1; } if (opt->strict > 0) { PStrictColorLimit = 1; } else if (opt->strict == 0) { PStrictColorLimit = 0; } if (opt->use_named_table > 0) { use_named_table = 1; } else if (opt->use_named_table == 0) { use_named_table = 0; } if (opt->not_dynamic > 0) { PUseDynamicColors = 0; } else if (opt->not_dynamic == 0) { PUseDynamicColors = 0; } if (opt->allocate > 0) { PAllocTable = 1; } else if (opt->allocate == 0) { PAllocTable = 0; } } if (color_limit <= 0) { use_default = 1; color_limit = nbr_of_color; } /* first try to see if we have a "pre-allocated" color cube. * The bultin RENDER X extension pre-allocate a color cube plus * some grey's (xc/programs/Xserver/render/miindex) * See gdk/gdkrgb.c for the cubes used by gtk+-2, 666 is the default, * 555 is the minimal cc (this may change): if gtk cannot allocate * the 555 cc (or better) a private cmap is used. * for qt-3: see src/kernel/{qapplication.cpp,qimage.cpp,qcolor_x11.c} * the 666 cube is used by default (with approx in the cmap if some * color allocation fail), and some qt app may accept an * --ncols option to limit the nbr of colors, then some "2:3:1" * proportions color cube are used (222, 232, ..., 252, 342, ..., 362, * 452, ...,693, ...) * imlib2 try to allocate the 666 cube if this fail it try more * exotic table (see rend.c and rgba.c) */ i = 0; free_colors = 0; if (Pdepth <= 8 && !private_cmap && use_default && i < cc_nbr && Pct == NULL && (Pvisual->class & 1)) { free_colors = get_nbr_of_free_colors(nbr_of_color); } while(Pdepth <= 8 && !private_cmap && use_default && i < cc_nbr && Pct == NULL && (Pvisual->class & 1)) { size = cc[i][0]*cc[i][1]*cc[i][2] + cc[i][3] - 2*(cc[i][3] > 0) + (1 << cc[i][4])*(cc[i][4] != 0); if (size > nbr_of_color || !(cc[i][5] & pa_type)) { i++; continue; } if (free_colors <= nbr_of_color - size) { Pct = alloc_color_cube( cc[i][0], cc[i][1], cc[i][2], cc[i][3], cc[i][4], True); } if (Pct != NULL) { if (free_colors <= get_nbr_of_free_colors(nbr_of_color)) { /* done */ } else { free_table_colors(Pct, PColorLimit); free(Pct); Pct = NULL; } } i++; } if (Pct != NULL) { PUseDynamicColors = 0; PAllocTable = 1; Pcsi.pre_allocated_pallet = 1; i = i - 1; finish_ct_init( call_type, i, cc[i][0], cc[i][1], cc[i][2], cc[i][3], cc[i][4], 0); return PColorLimit; } /* * now use "our" table */ limit = (color_limit >= nbr_of_color)? nbr_of_color:color_limit; if (use_default && !private_cmap) { /* XRender cvs default: */ #if 0 if (limit > 100) limit = nbr_of_color/3; else limit = nbr_of_color/2; /* depth 8: 85 */ /* depth 4: 8 */ #endif if (limit > 256) { /* direct colors & Pdepth > 8 */ if (Pdepth >= 16) { limit = 8192; } else if (Pdepth >= 15) { limit = 4096; } else { limit = 512; } } else if (limit == 256) { if (Pvisual->class == GrayScale) { limit = 64; } else if (Pvisual->class == DirectColor) { limit = 32; } else { limit = 68; /* candidate: * limit = 54; 4x4x3 + 6 grey * limit = 61 (named table) * limit = 85 current XRender default 4cc + 21 * limit = 76 future(?) XRender default 4cc + 16 * limit = 68 4x4x4 + 4 * limit = 64 4x4x4 + 0 */ } } else if (limit == 128 || limit == 64) { if (Pvisual->class == GrayScale) { limit = 32; } else { limit = 31; } } else if (limit >= 16) { if (Pvisual->class == GrayScale) { limit = 8; } else { limit = 10; } } else if (limit >= 8) { limit = 4; } else { limit = 2; } } if (limit < 2) { limit = 2; } if (Pvisual->class == DirectColor) { /* humm ... Any way this case should never happen in real life: * DirectColor default colormap! */ PUseDynamicColors = 0; PAllocTable = 1; PStrictColorLimit = 1; } if (PAllocTable) { do_allocate = 1; } else { do_allocate = 0; } /* use the named table ? */ if (use_named_table) { i = limit; while(Pct == NULL && i >= 2) { Pct = alloc_named_ct(&i, do_allocate); i--; } } if (Pct != NULL) { finish_ct_init( call_type, PColorLimit, 0, 0, 0, 0, 0, 1); return PColorLimit; } /* color cube or regular grey scale */ i = 0; while(i < cc_nbr && Pct == NULL) { if ((cc[i][5] & fvwm_type) && cc[i][0]*cc[i][1]*cc[i][2] + cc[i][3] - 2*(cc[i][3] > 0) + (1 << cc[i][4])*(cc[i][4] != 0) <= limit) { Pct = alloc_color_cube( cc[i][0], cc[i][1], cc[i][2], cc[i][3], cc[i][4], do_allocate); } i++; } if (Pct != NULL) { i = i-1; finish_ct_init( call_type, i, cc[i][0], cc[i][1], cc[i][2], cc[i][3], cc[i][4], 0); return PColorLimit; } /* I do not think we can be here */ Pct = alloc_color_cube(0, 0, 0, 0, 1, False); finish_ct_init(call_type, cc_nbr-1, 0, 0, 0, 0, 1, 0); if (Pct == NULL) { fprintf(stderr, "[fvwm] ERR -- Cannot get Black and White. exiting!\n"); exit(2); } return PColorLimit; } /* * Allocation of a private DirectColor cmap this is broken for depth > 16 */ static Bool alloc_direct_colors(int *limit, Bool use_my_color_limit) { unsigned long nr,ng,nb,r,g,b,cr,cg,cf,pr,pg; unsigned long red_mask, green_mask, blue_mask; XColor *colors; if (Pdepth <= 16) { red_mask = Pvisual->red_mask; green_mask = Pvisual->green_mask; blue_mask = Pvisual->blue_mask; } else { /* Use a standard depth 16 colormap. This is broken FIXME! */ red_mask = 0xf800; green_mask = 0x7e0; blue_mask = 0x1f; } decompose_mask( red_mask, &Pcsi.red_shift, &Pcsi.red_prec); decompose_mask( green_mask, &Pcsi.green_shift, &Pcsi.green_prec); decompose_mask( blue_mask, &Pcsi.blue_shift, &Pcsi.blue_prec); if (!use_my_color_limit) { /* colors allocated by fvwm we can return */ return 1; } nr = 1 << Pcsi.red_prec; ng = 1 << Pcsi.green_prec; nb = 1 << Pcsi.blue_prec; colors = (XColor *)safemalloc(nb*sizeof(XColor)); cf = DoRed|DoBlue|DoGreen; for (r=0; r> (16 - Pcsi.red_prec)) << Pcsi.red_shift; for (g = 0; g < ng; g++) { cg = g * 65535 / (ng - 1); pg = (cg >> (16 - Pcsi.green_prec)) << Pcsi.green_shift; for (b = 0; b < nb; b++) { colors[b].flags = cf; colors[b].red = cr; colors[b].green = cg; colors[b].blue = b * 65535 / (nb - 1); colors[b].pixel = (Pixel)(pr + pg + ((colors[b].blue >> (16 - Pcsi.blue_prec)) << Pcsi.blue_shift)); } XStoreColors(Pdpy, Pcmap, colors, nb); } } free(colors); return 1; } /* * Init the table for Static Colors */ static void init_static_colors_table(void) { XColor colors[256]; int i; int nbr_of_colors = min(256, (1 << Pdepth)); PColorLimit = nbr_of_colors; Pct = (PColor *)safemalloc((nbr_of_colors+1) * sizeof(PColor)); for (i = 0; i < nbr_of_colors; i++) { colors[i].pixel = Pct[i].color.pixel = i; } XQueryColors(Pdpy, Pcmap, colors, nbr_of_colors); for (i = 0; i < nbr_of_colors; i++) { Pct[i].color.red = colors[i].red; Pct[i].color.green = colors[i].green; Pct[i].color.blue = colors[i].blue; Pct[i].alloc_count = 1; } Pct[PColorLimit].color.red = Pct[PColorLimit-1].color.red; Pct[PColorLimit].color.green = Pct[PColorLimit-1].color.green; Pct[PColorLimit].color.blue = Pct[PColorLimit-1].color.blue; Pct[PColorLimit].alloc_count = 1; create_mapping_table(0, 0, 0, 0, 0, True); } /* * misc local functions */ static void print_colormap(Colormap cmap) { XColor colors[256]; int i; int nbr_of_colors = max(256, (1 << Pdepth)); for (i = 0; i < nbr_of_colors; i++) { colors[i].pixel = i; } XQueryColors(Pdpy, cmap, colors, nbr_of_colors); for (i = 0; i < nbr_of_colors; i++) { fprintf(stderr," rgb(%.3i): %.3i/%.3i/%.3i\n", i, colors[i].red >> 8, colors[i].green >> 8, colors[i].blue >> 8); } } /* ---------------------------- interface functions ------------------------ */ int PictureAllocColor(Display *dpy, Colormap cmap, XColor *c, int no_limit) { if (PStrictColorLimit && Pct != NULL) { no_limit = 0; } if (no_limit) { return Pcsi.alloc_color_no_limit(dpy, cmap, c); } else { return Pcsi.alloc_color(dpy, cmap, c); } return 0; } int PictureAllocColorAllProp( Display *dpy, Colormap cmap, XColor *c, int x, int y, Bool no_limit, Bool is_8, Bool do_dither) { if (!no_limit && do_dither && Pcsi.alloc_color_dither != NULL) { if (!is_8) { c->red = c->red >> 8; c->green = c->green >> 8; c->blue = c->blue >> 8; } return Pcsi.alloc_color_dither(dpy, cmap, c, x, y); } else { if (is_8) { c->red = c->red << 8; c->green = c->green << 8; c->blue = c->blue << 8; } return PictureAllocColor(dpy, cmap, c, False); } return 0; } int PictureAllocColorImage( Display *dpy, PictureImageColorAllocator *pica, XColor *c, int x, int y) { int r; r = PictureAllocColorAllProp( dpy, pica->cmap, c, x, y, pica->no_limit, pica->is_8, pica->dither); if (r && pica->pixels_table != NULL && pica->pixels_table_size && c->pixel < pica->pixels_table_size) { pica->pixels_table[c->pixel]++; } return r; } PictureImageColorAllocator *PictureOpenImageColorAllocator( Display *dpy, Colormap cmap, int x, int y, Bool no_limit, Bool do_not_save_pixels, int dither, Bool is_8) { PictureImageColorAllocator *pica; Bool do_save_pixels = False; pica = (PictureImageColorAllocator *)safemalloc( sizeof(PictureImageColorAllocator)); if (Pdepth <= 8 && !do_not_save_pixels && (Pvisual->class & 1) && ((PUseDynamicColors && Pct) || no_limit)) { int s = 1 << Pdepth; pica->pixels_table = (unsigned long *)safecalloc( s, sizeof(unsigned long)); pica->pixels_table_size = s; do_save_pixels = True; } if (!do_save_pixels) { pica->pixels_table = NULL; pica->pixels_table_size = 0; } pica->is_8 = is_8; if (dither && Pdepth <= 16) { pica->dither = dither; } else { pica->dither = dither; } pica->no_limit = no_limit; pica->cmap = cmap; return pica; } void PictureCloseImageColorAllocator( Display *dpy, PictureImageColorAllocator *pica, int *nalloc_pixels, Pixel **alloc_pixels, Bool *no_limit) { if (nalloc_pixels) { *nalloc_pixels = 0; } if (alloc_pixels != NULL) { *alloc_pixels = NULL; } if (no_limit != NULL) { *no_limit = 0; } if (pica->pixels_table) { int i,j; int k = 0, l = 0; unsigned int np = 0; int free_num = 0; Pixel *free_pixels = NULL; Pixel *save_pixels = NULL; for(i = 0; i < pica->pixels_table_size; i++) { if (pica->pixels_table[i]) { free_num += (pica->pixels_table[i]-1); np++; } } if (free_num) { free_pixels = (Pixel *)safemalloc( free_num * sizeof(Pixel)); } if (np && nalloc_pixels != NULL && alloc_pixels != NULL) { save_pixels = (Pixel *)safemalloc(np * sizeof(Pixel)); } for(i = 0; i < pica->pixels_table_size; i++) { if (pica->pixels_table[i]) { if (save_pixels) { save_pixels[k++] = i; } for(j=1; j < pica->pixels_table[i]; j++) { free_pixels[l++] = i; } } } if (free_num) { PictureFreeColors( dpy, pica->cmap, free_pixels, free_num, 0, pica->no_limit); free(free_pixels); } if (nalloc_pixels != NULL && alloc_pixels != NULL) { *nalloc_pixels = np; *alloc_pixels = save_pixels; if (no_limit != NULL) { *no_limit = pica->no_limit; } } else if (save_pixels) { free(save_pixels); } free(pica->pixels_table); } free(pica); return; } void PictureFreeColors( Display *dpy, Colormap cmap, Pixel *pixels, int n, unsigned long planes, Bool no_limit) { if (no_limit) { if (Pcsi.free_colors_no_limit != NULL) { Pcsi.free_colors_no_limit( dpy, cmap, pixels, n, planes); } } else { if (Pcsi.free_colors != NULL) { Pcsi.free_colors(dpy, cmap, pixels, n, planes); } } return; } Pixel PictureGetNextColor(Pixel p, int n) { int i; XColor c; if (n >= 0) n = 1; else n = -1; if (Pct == NULL) { return p; } for(i=0; i 0) { c = Pct[0].color; alloc_color_in_pct(&c, 0); return Pct[0].color.pixel; } else { c = Pct[i+n].color; alloc_color_in_pct(&c, i+n); return Pct[i+n].color.pixel; } } } return p; } /* Replace the color in my_color by the closest matching color from base_table */ void PictureReduceColorName(char **my_color) { int index; XColor rgb; /* place to calc rgb for each color in xpm */ if (!XpmSupport) return; if (!strcasecmp(*my_color,"none")) { return; /* do not substitute the "none" color */ } if (!XParseColor(Pdpy, Pcmap, *my_color, &rgb)) { fprintf(stderr,"color_to_rgb: can't parse color %s\n", *my_color); } index = get_color_index(rgb.red,rgb.green,rgb.blue, False); /* Finally: replace the color string by the newly determined color * string */ free(*my_color); /* free old color */ /* area for new color */ *my_color = safemalloc(8); sprintf(*my_color,"#%x%x%x", Pct[index].color.red >> 8, Pct[index].color.green >> 8, Pct[index].color.blue >> 8); /* put it there */ return; } Bool PictureDitherByDefault(void) { if (Pct != NULL) { return True; } return False; } Bool PictureUseBWOnly(void) { if (Pdepth < 2 || (PStrictColorLimit && PColorLimit == 2)) { return True; } return False; } int PictureInitColors( int call_type, Bool init_color_limit, PictureColorLimitOption *opt, Bool use_my_color_limit, Bool init_dither) { Bool dither_ok = False; switch (Pvisual->class) { case DirectColor: /* direct colors is more or less broken */ decompose_mask( Pvisual->red_mask, &Pcsi.red_shift, &Pcsi.red_prec); decompose_mask( Pvisual->green_mask, &Pcsi.green_shift, &Pcsi.green_prec); decompose_mask( Pvisual->blue_mask, &Pcsi.blue_shift, &Pcsi.blue_prec); Pcsi.alloc_color_no_limit = alloc_color_proportion; Pcsi.alloc_color = alloc_color_proportion; Pcsi.alloc_color_dither = alloc_color_proportion_dither; Pcsi.free_colors_no_limit = NULL; Pcsi.free_colors = NULL; PColorLimit = 0; break; case TrueColor: decompose_mask( Pvisual->red_mask, &Pcsi.red_shift, &Pcsi.red_prec); decompose_mask( Pvisual->green_mask, &Pcsi.green_shift, &Pcsi.green_prec); decompose_mask( Pvisual->blue_mask, &Pcsi.blue_shift, &Pcsi.blue_prec); Pcsi.alloc_color_no_limit = alloc_color_proportion; Pcsi.alloc_color = alloc_color_proportion; Pcsi.free_colors_no_limit = NULL; Pcsi.free_colors = NULL; PColorLimit = 0; if (init_dither && (Pdepth == 15 || Pdepth == 16)) { dither_ok = my_dither_depth_15_16_init(); } if (dither_ok) { Pcsi.alloc_color_dither = alloc_color_proportion_dither; } else { Pcsi.alloc_color_dither = NULL; } break; case StaticColor: if (0 && Pvisual->red_mask != 0 && Pvisual->green_mask != 0 && Pvisual->blue_mask != 0) { decompose_mask( Pvisual->red_mask, &Pcsi.red_shift, &Pcsi.red_prec); decompose_mask( Pvisual->green_mask, &Pcsi.green_shift, &Pcsi.green_prec); decompose_mask( Pvisual->blue_mask, &Pcsi.blue_shift, &Pcsi.blue_prec); Pcsi.alloc_color_no_limit = alloc_color_proportion; Pcsi.alloc_color = alloc_color_proportion; PColorLimit = 0; } else { if (init_color_limit) { Pcsi.alloc_color = alloc_color_in_table; Pcsi.alloc_color_dither = alloc_color_in_table_dither; Pcsi.alloc_color_no_limit = alloc_color_x; init_static_colors_table(); } else { Pcsi.alloc_color = alloc_color_x; Pcsi.alloc_color_dither = NULL; Pcsi.alloc_color_no_limit = alloc_color_x; } } Pcsi.free_colors_no_limit = NULL; Pcsi.free_colors = NULL; break; case StaticGray: /* FIXME: we assume that we have a regular grey ramp */ if (0) { Pcsi.alloc_color_no_limit = alloc_color_proportion_grey; Pcsi.alloc_color = alloc_color_proportion; PColorLimit = 0; } else { if (init_color_limit) { Pcsi.alloc_color = alloc_color_in_table; Pcsi.alloc_color_dither = alloc_color_in_table_dither; Pcsi.alloc_color_no_limit = alloc_color_x; init_static_colors_table(); } else { Pcsi.alloc_color = alloc_color_x; Pcsi.alloc_color_dither = NULL; Pcsi.alloc_color_no_limit = alloc_color_x; } } Pcsi.free_colors_no_limit = NULL; Pcsi.free_colors = NULL; break; case PseudoColor: case GrayScale: default: Pcsi.alloc_color_no_limit = alloc_color_dynamic_no_limit; Pcsi.free_colors_no_limit = free_colors_x; break; } if (!(Pvisual->class & 1)) { /* static classes */ PUseDynamicColors = 0; if (call_type == PICTURE_CALLED_BY_FVWM && getenv("FVWM_COLORTABLE_TYPE") != NULL) { flib_putenv("FVWM_COLORTABLE_TYPE", ""); } return PColorLimit; } /* dynamic classes */ if (!Pdefault && Pvisual->class == DirectColor) { PColorLimit = 0; PUseDynamicColors = 0; alloc_direct_colors(0, use_my_color_limit); if (call_type == PICTURE_CALLED_BY_FVWM && getenv("FVWM_COLORTABLE_TYPE") != NULL) { flib_putenv("FVWM_COLORTABLE_TYPE", ""); } return 0; } if (init_color_limit) { Pcsi.alloc_color = alloc_color_in_table; Pcsi.alloc_color_dither = alloc_color_in_table_dither; PictureAllocColorTable(opt, call_type, use_my_color_limit); if (PUseDynamicColors) { Pcsi.free_colors = free_colors_in_table; } else { Pcsi.free_colors = NULL; } } else { Pcsi.alloc_color = alloc_color_dynamic_no_limit; Pcsi.free_colors = free_colors_x; Pcsi.alloc_color_dither = NULL; } return PColorLimit; } void PicturePrintColorInfo(int verbose) { unsigned long nbr_of_colors = 1 << Pdepth; fprintf(stderr, "fvwm info on colors\n"); fprintf(stderr, " Visual ID: 0x%x, Default?: %s, Class: ", (int)(Pvisual->visualid), (Pdefault)? "Yes":"No"); if (Pvisual->class == TrueColor) { fprintf(stderr,"TrueColor"); } else if (Pvisual->class == PseudoColor) { fprintf(stderr,"PseudoColor"); } else if (Pvisual->class == DirectColor) { fprintf(stderr,"DirectColor"); } else if (Pvisual->class == StaticColor) { fprintf(stderr,"StaticColor"); } else if (Pvisual->class == GrayScale) { fprintf(stderr,"GrayScale"); } else if (Pvisual->class == StaticGray) { fprintf(stderr,"StaticGray"); } fprintf(stderr, "\n"); fprintf(stderr, " Depth: %i, Number of colors: %lu", Pdepth, (unsigned long)nbr_of_colors); if (Pct != NULL) { fprintf(stderr,"\n Pallet with %i colors", PColorLimit); if (Pvisual->class & 1) { fprintf(stderr,", Number of free colors: %i\n", get_nbr_of_free_colors((1 << Pdepth))); fprintf(stderr, " Auto Detected: %s, Strict: %s, Allocated: %s," " Dynamic: %s\n", (Pcsi.pre_allocated_pallet)? "Yes":"No", (PStrictColorLimit)? "Yes":"No", (PAllocTable)? "Yes":"No", (PUseDynamicColors)? "Yes":"No"); } else { fprintf(stderr," (default colormap)\n"); } if (PColorLimit <= 256) { int i; int count = 0; int count_alloc = 0; if (verbose) { fprintf(stderr," The fvwm colors table:\n"); } for (i = 0; i < PColorLimit; i++) { if (verbose) { fprintf( stderr, " rgb:%.3i/%.3i/%.3i\t%lu\n", Pct[i].color.red >> 8, Pct[i].color.green >> 8, Pct[i].color.blue >> 8, Pct[i].alloc_count); } if (Pct[i].alloc_count) { count++; } } if ((Pvisual->class & 1) && Pac != NULL) { if (verbose) { fprintf(stderr," fvwm colors not in" " the table:\n"); } for(i=0; i < nbr_of_colors; i++) { int j = 0; Bool found = False; if (!Pac[i].alloc_count) continue; while(j < PColorLimit && !found) { if (i == Pct[j].color.pixel) { found = True; } j++; } if (found) continue; count_alloc++; if (verbose) { fprintf( stderr, " rgb:" "%.3i/%.3i/%.3i\t%lu\n", Pac[i].color.red >> 8, Pac[i].color.green >> 8, Pac[i].color.blue >> 8, Pac[i].alloc_count); } } if (verbose && count_alloc == 0) { if (verbose) { fprintf(stderr," None\n"); } } } if (Pvisual->class & 1) { fprintf(stderr, " Number of colours used by fvwm:\n"); fprintf(stderr, " In the table: %i\n", count); fprintf( stderr, " Out of the table: %i\n", count_alloc); fprintf(stderr, " Total: %i\n", count_alloc+count); } } } else { if (Pvisual->class == DirectColor) { fprintf(stderr, ", Pseudo Pallet with: %i colors\n", (1 << Pcsi.red_prec)*(1 << Pcsi.green_prec)* (1 << Pcsi.blue_prec)); } else { fprintf(stderr, ", No Pallet (static colors)\n"); } fprintf(stderr, " red: %i, green: %i, blue %i\n", 1 << Pcsi.red_prec, 1 << Pcsi.green_prec, 1 << Pcsi.blue_prec); if (verbose && Pdepth <= 8) { if (Pvisual->class == DirectColor) { fprintf(stderr, " Colormap:\n"); } else { fprintf(stderr, " Static Colormap used by fvwm:\n"); } print_colormap(Pcmap); } } if (Pdepth <= 8 && verbose >= 2) { fprintf(stderr,"\n Default Colormap:\n"); print_colormap(DefaultColormap(Pdpy,DefaultScreen(Pdpy))); } } fvwm-2.7.0/libs/Ficonv.c0000644000175000017500000003244614147024700011751 00000000000000/* -*-c-*- */ /* Copyright (C) 2002 Olivier Chapuis */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* Some code (convert_charsets) inspired by the glib-2 (gutf8.c) copyrighted * by Tom Tromey & Red Hat, Inc. */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include #include "FlocaleCharset.h" #include "Ficonv.h" #include "Strings.h" #if FiconvSupport #include #if defined(USE_LIBICONV) && !defined (_LIBICONV_H) #error libiconv in use but included iconv.h not from libiconv #endif #if !defined(USE_LIBICONV) && defined (_LIBICONV_H) && defined (LIBICONV_PLUG) #error libiconv not in use but included iconv.h is from libiconv #endif #endif /* FiconvSupport */ /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ static Bool FiconvInitialized = False; static FlocaleCharset *FLCIconvUtf8Charset = NULL; /* UTF-8 charset */ static FlocaleCharset *FLCIconvDefaultCharset = NULL; static int do_transliterate_utf8 = 0; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ static Bool is_iconv_supported(char *c1, char *c2) { Ficonv_t cd1,cd2; Bool r = False; if (!FiconvSupport || !c1 || !c2) return False; cd1 = Ficonv_open(c1, c2); cd2 = Ficonv_open(c2, c1); if (cd1 != (Ficonv_t) -1 && cd2 != (Ficonv_t) -1) r = True; if (cd1 != (Ficonv_t) -1) (void)Ficonv_close(cd1); if (cd2 != (Ficonv_t) -1) (void)Ficonv_close(cd2); return r; } #define TRANSLIT_SUFFIX "//TRANSLIT" static char *translit_csname(char *cs) { return CatString2(cs, TRANSLIT_SUFFIX); } static int is_translit_supported(char *c1, char *c2) { Ficonv_t cd; if (!FiconvSupport || !c1 || !c2) return 0; cd = Ficonv_open(translit_csname(c1),c2); if (cd == (Ficonv_t) -1) { return 0; } (void)Ficonv_close(cd); cd = Ficonv_open(translit_csname(c2),c1); if (cd == (Ficonv_t) -1) { return 0; } (void)Ficonv_close(cd); return 1; } static int set_default_iconv_charsets(FlocaleCharset *fc) { int i=0,j=0; if (!FiconvSupport || FLCIconvUtf8Charset == NULL || fc == NULL) return False; while(FLC_GET_LOCALE_CHARSET(FLCIconvUtf8Charset,i) != NULL) { j = 0; while(FLC_GET_LOCALE_CHARSET(fc,j) != NULL) { if (is_iconv_supported( FLC_GET_LOCALE_CHARSET( FLCIconvUtf8Charset,i), FLC_GET_LOCALE_CHARSET(fc,j))) { FLC_SET_ICONV_INDEX(FLCIconvUtf8Charset,i); FLC_SET_ICONV_INDEX(fc,j); if (is_translit_supported( FLC_GET_LOCALE_CHARSET( FLCIconvUtf8Charset,i), FLC_GET_LOCALE_CHARSET(fc,j))) { FLC_SET_ICONV_TRANSLIT_CHARSET( fc, safestrdup(translit_csname( FLC_GET_LOCALE_CHARSET( fc,j)))); } else { FLC_SET_ICONV_TRANSLIT_CHARSET( fc, FLC_TRANSLIT_NOT_SUPPORTED); } return 1; } j++; } i++; } FLC_SET_ICONV_INDEX(FLCIconvUtf8Charset, FLC_INDEX_ICONV_CHARSET_NOT_FOUND); FLC_SET_ICONV_INDEX(fc, FLC_INDEX_ICONV_CHARSET_NOT_FOUND); return 0; } static void set_iconv_charset_index(FlocaleCharset *fc) { int i = 0; if (!FiconvSupport || fc == NULL) return; if (FLC_DO_ICONV_CHARSET_INITIALIZED(fc)) return; /* already set */ if (FLCIconvUtf8Charset == NULL || !FLC_DO_ICONV_CHARSET_INITIALIZED(FLCIconvUtf8Charset)) { FLC_SET_ICONV_INDEX(fc, FLC_INDEX_ICONV_CHARSET_NOT_FOUND); return; } while(FLC_GET_LOCALE_CHARSET(fc,i) != NULL) { if (is_iconv_supported( FLC_GET_ICONV_CHARSET(FLCIconvUtf8Charset), FLC_GET_LOCALE_CHARSET(fc,i))) { FLC_SET_ICONV_INDEX(fc,i); if (is_translit_supported( FLC_GET_ICONV_CHARSET(FLCIconvUtf8Charset), FLC_GET_LOCALE_CHARSET(fc,i))) { FLC_SET_ICONV_TRANSLIT_CHARSET( fc, safestrdup( translit_csname( FLC_GET_LOCALE_CHARSET( fc,i)))); } else { FLC_SET_ICONV_TRANSLIT_CHARSET( fc, FLC_TRANSLIT_NOT_SUPPORTED); } return; } i++; } FLC_SET_ICONV_INDEX(fc, FLC_INDEX_ICONV_CHARSET_NOT_FOUND); } static char *convert_charsets(const char *in_charset, const char *out_charset, const char *in, unsigned int in_size) { static int error_count = 0; Ficonv_t cd; int have_error = 0; int is_finished = 0; size_t nconv; size_t insize,outbuf_size,outbytes_remaining,len; const char *inptr; char *dest; char *outp; if (in == NULL || !FiconvSupport) return NULL; cd = Ficonv_open(out_charset, in_charset); if (cd == (Ficonv_t) -1) { /* Something went wrong. */ if (error_count > FICONV_CONVERSION_MAX_NUMBER_OF_WARNING) return NULL; error_count++; if (errno == EINVAL) { fprintf( stderr, "[fvwm][convert_charsets]: WARNING -\n\t"); fprintf( stderr, "conversion from `%s' to `%s' not available\n", in_charset,out_charset); } else { fprintf( stderr, "[fvwm][convert_charsets]: WARNING -\n\t"); fprintf( stderr, "conversion from `%s' to `%s' fail (init)\n", in_charset,out_charset); } /* Terminate the output string. */ return NULL; } /* in maybe a none terminate string */ len = in_size; outbuf_size = len + 1; outbytes_remaining = outbuf_size - 1; insize = len; outp = dest = safemalloc(outbuf_size); inptr = in; for (is_finished = 0; is_finished == 0; ) { SUPPRESS_UNUSED_VAR_WARNING(inptr); SUPPRESS_UNUSED_VAR_WARNING(insize); SUPPRESS_UNUSED_VAR_WARNING(outbytes_remaining); nconv = Ficonv( cd, (ICONV_ARG_CONST char **)&inptr, &insize, &outp, &outbytes_remaining); is_finished = 1; if (nconv == (size_t) - 1) { switch (errno) { case EINVAL: /* Incomplete text, do not report an error */ break; case E2BIG: { size_t used = outp - dest; outbuf_size *= 2; dest = realloc (dest, outbuf_size); outp = dest + used; /* -1 for nul */ outbytes_remaining = outbuf_size - used - 1; is_finished = 0; break; } #ifdef EILSEQ case EILSEQ: /* Something went wrong. */ if (error_count <= FICONV_CONVERSION_MAX_NUMBER_OF_WARNING) { fprintf( stderr, "[fvwm][convert_charsets]:" " WARNING -\n\t"); fprintf( stderr, "Invalid byte sequence during" " conversion from %s to %s\n", in_charset,out_charset); } have_error = 1; break; #endif default: if (error_count <= FICONV_CONVERSION_MAX_NUMBER_OF_WARNING) { fprintf( stderr, "[fvwm][convert_charsets]:" " WARNING -\n\t"); fprintf( stderr, "Error during conversion from" " %s to %s\n", in_charset, out_charset); } have_error = 1; break; } } } /* Terminate the output string */ *outp = '\0'; if (Ficonv_close (cd) != 0) { fprintf( stderr, "[fvwm][convert_charsets]: WARNING - iconv_close" " fail\n"); } if (have_error) { error_count++; free (dest); return NULL; } else { return dest; } } static void FiconvInit(Display *dpy, const char *module) { int suc = False; if (!FiconvSupport || FiconvInitialized) return; FiconvInitialized = True; FlocaleCharsetInit(dpy, module); FLCIconvUtf8Charset = FlocaleCharsetGetUtf8Charset(); FLCIconvDefaultCharset = FlocaleCharsetGetFLCXOMCharset(); suc = set_default_iconv_charsets(FLCIconvDefaultCharset); if (!suc) { FLCIconvDefaultCharset = FlocaleCharsetGetLocaleCharset(); suc = set_default_iconv_charsets(FLCIconvDefaultCharset); } if (!suc) { fprintf(stderr, "[%s][FiconvInit]: WARN -- Cannot get default " "iconv charset for default charsets '%s' and '%s'\n", module, FLC_DEBUG_GET_X_CHARSET( FlocaleCharsetGetFLCXOMCharset()), FLC_DEBUG_GET_X_CHARSET(FLCIconvDefaultCharset)); FLCIconvUtf8Charset = NULL; FLCIconvDefaultCharset = NULL; } #if FLOCALE_DEBUG_CHARSET fprintf(stderr,"[FiconvInit] iconv charset: x:%s, iconv:%s\n", FLC_DEBUG_GET_X_CHARSET(FLCIconvDefaultCharset), FLC_DEBUG_GET_ICONV_CHARSET(FLCIconvDefaultCharset)); fprintf(stderr,"[FiconvInit] UTF-8 charset: x:%s, iconv:%s\n", FLC_DEBUG_GET_X_CHARSET(FLCIconvUtf8Charset), FLC_DEBUG_GET_ICONV_CHARSET(FLCIconvUtf8Charset)); #endif } static FlocaleCharset *FiconvSetupConversion(Display *dpy, FlocaleCharset *fc) { FlocaleCharset *my_fc = NULL; if (!FiconvSupport) { return NULL; } if (!FiconvInitialized) { FiconvInit(dpy, "fvwm"); } if (FLCIconvUtf8Charset == NULL) { return NULL; } if (fc == NULL) { my_fc = FLCIconvDefaultCharset; if (my_fc == NULL) { return NULL; } } else { my_fc = fc; } if (!FLC_DO_ICONV_CHARSET_INITIALIZED(my_fc)) { set_iconv_charset_index(my_fc); #if FLOCALE_DEBUG_CHARSET fprintf(stderr, "[Flocale] set up iconv charset: " "x: %s, iconv: %s\n", FLC_DEBUG_GET_X_CHARSET(my_fc), FLC_DEBUG_GET_ICONV_CHARSET(my_fc)); #endif if (!FLC_HAVE_ICONV_CHARSET(my_fc)) { fprintf( stderr, "[fvwmlibs] cannot get iconv converter " "for charset %s\n", FLC_DEBUG_GET_X_CHARSET(my_fc)); return NULL; } } if (!FLC_HAVE_ICONV_CHARSET(my_fc)) { return NULL; } return my_fc; } /* ---------------------------- interface functions ------------------------ */ /* set transliteration state */ void FiconvSetTransliterateUtf8(int toggle) { switch (toggle) { case -1: do_transliterate_utf8 ^= 1; break; case 0: case 1: do_transliterate_utf8 = toggle; break; default: do_transliterate_utf8 = 0; } } /* conversion from UTF8 to the "current" charset */ char *FiconvUtf8ToCharset(Display *dpy, FlocaleCharset *fc, const char *in, unsigned int in_size) { char *out = NULL; FlocaleCharset *my_fc = NULL; if (!FiconvSupport) { return NULL; } my_fc = FiconvSetupConversion(dpy, fc); if (my_fc == NULL) { return NULL; } #if FLOCALE_DEBUG_ICONV fprintf(stderr, "[FiconvUtf8ToCharset] conversion from %s to %s\n", FLC_DEBUG_GET_ICONV_CHARSET(FLCIconvUtf8Charset), FLC_DEBUG_GET_ICONV_CHARSET(my_fc)); #endif if (FLC_ENCODING_TYPE_IS_UTF_8(my_fc)) { /* in can be a none terminate string so do not use CopyString */ out = safemalloc(in_size+1); strncpy(out, in, in_size); out[in_size]=0; } else { char *to_cs; if (do_transliterate_utf8 && FLC_IS_TRANSLIT_SUPPORTED(my_fc)) { to_cs = FLC_GET_ICONV_TRANSLIT_CHARSET(my_fc); } else { to_cs = FLC_GET_ICONV_CHARSET(my_fc); } out = convert_charsets( FLC_GET_ICONV_CHARSET(FLCIconvUtf8Charset), to_cs, in, in_size); } return out; } /* conversion from the current charset to UTF8 */ char *FiconvCharsetToUtf8(Display *dpy, FlocaleCharset *fc, const char *in, unsigned int in_size) { char *out = NULL; FlocaleCharset *my_fc = NULL; if (!FiconvSupport) { return NULL; } my_fc = FiconvSetupConversion(dpy, fc); if (my_fc == NULL) { return NULL; } #if FLOCALE_DEBUG_ICONV fprintf(stderr, "[FiconvCharsetToUtf8] conversion from %s to %s\n", FLC_DEBUG_GET_ICONV_CHARSET(my_fc), FLC_DEBUG_GET_ICONV_CHARSET(FLCIconvUtf8Charset)); #endif if (FLC_ENCODING_TYPE_IS_UTF_8(my_fc)) { /* in can be a non terminate string so do not use CopyString */ out = safemalloc(in_size+1); strncpy(out, in, in_size); out[in_size]=0; } else { out = convert_charsets( FLC_GET_ICONV_CHARSET(my_fc), FLC_GET_ICONV_CHARSET(FLCIconvUtf8Charset), in, in_size); } return out; } /* conversion from charset to charset */ char *FiconvCharsetToCharset( Display *dpy, FlocaleCharset *in_fc, FlocaleCharset *out_fc, const char *in, unsigned int in_size) { char *out = NULL; char *tmp = NULL; int tmp_len; Bool free_tmp = False; FlocaleCharset *my_in_fc; FlocaleCharset *my_out_fc; if (!FiconvSupport || (my_in_fc = FiconvSetupConversion(dpy, in_fc)) == NULL) { return NULL; } if (!FiconvSupport || (my_out_fc = FiconvSetupConversion(dpy, out_fc)) == NULL) { return NULL; } tmp = (char *)in; tmp_len = in_size; if (!FLC_ENCODING_TYPE_IS_UTF_8(my_in_fc)) { tmp = FiconvCharsetToUtf8( dpy, my_in_fc, (const char *)in, in_size); if (tmp != NULL) { free_tmp = True; tmp_len = strlen(tmp); } else { /* fail to convert */ return NULL; } } out = tmp; if (!FLC_ENCODING_TYPE_IS_UTF_8(my_out_fc)) { out = FiconvUtf8ToCharset( dpy, my_out_fc, (const char *)tmp, tmp_len); if (free_tmp) { free(tmp); } } return out; } fvwm-2.7.0/libs/FBidi.c0000644000175000017500000001000214147024700011462 00000000000000/* -*-c-*- */ /* Copyright (C) 2002 Mikhael Goikhman */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* * FBidi.c - interface to Bidi, we use fribidi implementation here. * See FBidi.h for some comments on this interface. */ #include "config.h" #include "FBidi.h" #if HAVE_BIDI #include "safemalloc.h" #include "BidiJoin.h" #include #include Bool FBidiIsApplicable(const char *charset) { if (fribidi_parse_charset((char *)charset) == FRIBIDI_CHAR_SET_NOT_FOUND) { return False; } return True; } char *FBidiConvert( const char *logical_str, const char *charset, int str_len, Bool *is_rtl, int *out_len, superimpose_char_t *comb_chars, int *l_to_v) { char *visual_str; FriBidiCharSet fribidi_charset; FriBidiChar *logical_unicode_str; FriBidiChar *visual_unicode_str; FriBidiParType pbase_dir = FRIBIDI_TYPE_ON; FriBidiStrIndex *pos_l_to_v; int i; if (logical_str == NULL || charset == NULL) { return NULL; } if (str_len < 0) { str_len = strlen(logical_str); } if (is_rtl != NULL) { *is_rtl = False; } fribidi_charset = fribidi_parse_charset((char *)charset); if (fribidi_charset == FRIBIDI_CHAR_SET_NOT_FOUND) { return NULL; } /* it is possible that we allocate a bit more here, if utf-8 */ logical_unicode_str = (FriBidiChar *)safemalloc((str_len + 1) * sizeof(FriBidiChar)); /* convert to unicode first */ str_len = fribidi_charset_to_unicode( fribidi_charset, (char *)logical_str, str_len, logical_unicode_str); visual_unicode_str = (FriBidiChar *)safemalloc((str_len + 1) * sizeof(FriBidiChar)); /* apply bidi algorithm, convert logical string to visual string */ /* also keep track of how characters are reordered here, to reorder combing characters accordingly */ pos_l_to_v = (FriBidiStrIndex *)safemalloc((str_len + 1) * sizeof(FriBidiStrIndex)); fribidi_log2vis( logical_unicode_str, str_len, &pbase_dir, visual_unicode_str, pos_l_to_v, NULL, NULL); /* remap mapping from logical to visual to "compensate" for BIDI */ if (comb_chars != NULL) { for (i = 0; comb_chars[i].c.byte1 != 0 || comb_chars[i].c.byte2 != 0; i++) { /* if input string is zero characters => only combining chars, set position to zero */ comb_chars[i].position = str_len != 0 ? pos_l_to_v[comb_chars[i].position] : 0; } } if (l_to_v != NULL) { /* values in the previuos mapping gives the position of input characters after combining step */ /* mapping from BIDI conversion maps from the positions in the output from combining */ int orig_len; int *l_to_v_temp; for (i = 0; l_to_v[i] != -1; i++) { } orig_len = i; l_to_v_temp = (int *)safemalloc(orig_len * sizeof(int)); for (i = 0; i < orig_len; i++) { l_to_v_temp[i] = pos_l_to_v[l_to_v[i]]; } for (i = 0; i < orig_len; i++) { l_to_v[i] = l_to_v_temp[i]; } free(l_to_v_temp); } free(pos_l_to_v); /* character shape/join - will get pulled into fribidi with time */ str_len = shape_n_join(visual_unicode_str, str_len); visual_str = (char *)safemalloc((4 * str_len + 1) * sizeof(char)); /* convert from unicode finally */ *out_len = fribidi_unicode_to_charset( fribidi_charset, visual_unicode_str, str_len, visual_str); if (is_rtl != NULL && fribidi_get_bidi_type(*visual_unicode_str) == FRIBIDI_TYPE_RTL) { *is_rtl = True; } free(logical_unicode_str); free(visual_unicode_str); return visual_str; } #endif /* HAVE_BIDI */ fvwm-2.7.0/libs/PictureUtils.h0000644000175000017500000000243014147024700013154 00000000000000/* -*-c-*- */ #ifndef Picture_Utils_H #define Picture_Utils_H #define PICTURE_CALLED_BY_FVWM 0 #define PICTURE_CALLED_BY_MODULE 1 void PictureReduceColorName(char **my_color); void PictureAllocColors( Display *dpy, Colormap cmap, XColor *colors, int size, Bool no_limit); int PictureAllocColor(Display *dpy, Colormap cmap, XColor *c, int no_limit); int PictureAllocColorAllProp( Display *dpy, Colormap cmap, XColor *c, int x, int y, Bool no_limit, Bool is_8, Bool do_dither); int PictureAllocColorImage( Display *dpy, PictureImageColorAllocator *pica, XColor *c, int x, int y); PictureImageColorAllocator *PictureOpenImageColorAllocator( Display *dpy, Colormap cmap, int x, int y, Bool no_limit, Bool save_pixels, int dither, Bool is_8); void PictureCloseImageColorAllocator( Display *dpy, PictureImageColorAllocator *pica, int *nalloc_pixels, Pixel **alloc_pixels, int *no_limit); void PictureFreeColors( Display *dpy, Colormap cmap, Pixel *pixels, int n, unsigned long planes, Bool no_limit); Pixel PictureGetNextColor(Pixel p, int n); Bool PictureDitherByDefault(void); Bool PictureUseBWOnly(void); int PictureInitColors( int call_type, Bool init_color_limit, PictureColorLimitOption *opt, Bool use_my_color_limit, Bool init_dither); void PicturePrintColorInfo(int verbose); #endif fvwm-2.7.0/libs/FlocaleCharset.c0000644000175000017500000005721714147024700013407 00000000000000/* -*-c-*- */ /* Copyright (C) 2002 Olivier Chapuis */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include #include "Strings.h" #include "Parse.h" #include "Flocale.h" #include "FlocaleCharset.h" #include "Ficonv.h" #if FlocaleLibcharsetSupport #include #endif #if FlocaleCodesetSupport #include #endif /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* X locale charset */ static FlocaleCharset *FLCXOMCharset = NULL; /* list of XOM locale charset */ static FlocaleCharset **FLCXOMCharsetList = NULL; static int FLCXOMCharsetList_num = 0; /* UTF-8 charset */ static FlocaleCharset *FLCUtf8Charset = NULL; /* locale charset from the locale not X */ static FlocaleCharset *FLCLocaleCharset = NULL; static char *nullsl[] = {NULL}; #if FiconvSupport /* from hpux iconv man page: The fromcode and tocode names can be any length, * but only the first four and the last letter are used to identify the code * set. */ /* the first name is the gnu canonical name */ char *armscii_8[] = {"ARMSCII-8", NULL}; char *big5_0[] = {"BIG5", "big5", /* aix, hpux, osf */ "zh_TW-big5", /* solaris 9? */ NULL}; char *big5hkscs_0[] = {"BIG5-HKSCS", "BIG5", "big5", /* aix, hpux, osf */ "zh_TW-big5", /* solaris 9? */ NULL}; char *cns11643[] = {"EUCTW", "EUC-TW", "eucTW", "euc-tw", "euctw", NULL}; char *dosencoding_cp437[] = {"CP437", NULL}; char *dosencoding_cp850[] = {"CP850", "cp850", /* osf */ "IBM-850", /* aix */ NULL}; char *gb2312_1980_0[] = {"EUC-CN", "GB2312", "gb2312", /* solaris */ "dechanzi", /* osf */ "hp15CN", /* hpux */ "IBM-eucCN", /* aix */ "eucCN", /* irix */ NULL}; char *gbk_0[] = {"GBK", NULL}; char *georgian_academy[] = {"GEORGIAN-ACADEMY", NULL}; char *georgian_ps[] = {"GEORGIAN-PS", NULL}; char *ibm_cp1133[] = {"CP850" , NULL}; char *isiri_3342[] = {"ISIRI-3342", NULL}; /* embed ascii into ISO-8859-1*/ char *iso8859_1[] = {"ISO-8859-1", /* gnu */ "ISO8859-1", /* aix, irix, osf, solaris */ "iso8859-1", /* aix, irix, osf */ "iso88591", /* hpux */ "8859-1", /* solaris ? */ "iso81", /* hpux */ "ascii", "ASCII", "646", /* solaris */ "ANSI_X3.4-1968", "ISO_646.IRV:1983", /* old glibc */ "american_e", NULL}; char *iso8859_2[] = {"ISO-8859-2", "ISO8859-2", "iso8859-2", "iso88592", "8859-2", "iso82", NULL}; char *iso8859_3[] = {"ISO-8859-3", "ISO8859-3", "iso8859-3", "iso88593", "8859-3", "iso83", NULL}; char *iso8859_4[] = {"ISO-8859-4", "ISO8859-4", "iso8859-4", "iso88594", "8859-4", "iso84", NULL}; char *iso8859_5[] = {"ISO-8859-5", "ISO8859-5", "iso8859-5", "iso88595", "8859-5", "iso85", NULL}; char *iso8859_6[] = {"ISO-8859-6", "ISO8859-6", "iso8859-6", "iso88596", "8859-6", "iso86", NULL}; char *iso8859_7[] = {"ISO-8859-7", "ISO8859-7", "iso8859-7", "iso88597", "8859-7", "iso87", NULL}; char *iso8859_8[] = {"ISO-8859-8", "ISO8859-8", "iso88859-8", "iso88598", "8859-8", "iso88", NULL}; char *iso8859_9[] = {"ISO-8859-9", "ISO8859-9", "iso8859-9", "iso88599", "8859-9", "iso89", NULL}; char *iso8859_10[] = {"ISO-8859-10", "ISO8859-10", "iso8859-10", "iso885910", "8859-10", "iso80", /*?*/ "iso10", NULL}; char *iso8859_13[] = {"ISO-8859-13", "ISO8859-13", "iso8859-13", "iso885913", "8859-13", "IBM-921", /* aix */ "iso813", /*?*/ "iso13", NULL}; char *iso8859_14[] = {"ISO-8859-14", "ISO8859-14", "iso8859-14", "iso885914", "8859-14", "iso814", "iso14", NULL}; char *iso8859_15[] = {"ISO-8859-15", "ISO88859-15", "iso88859-15", "iso885915", "8859-15", "iso815", "iso15", NULL}; char *iso8859_16[] = {"ISO-8859-16", "ISO8859-16", "iso8859-16", "iso885916", "8859-16", "iso80", "iso16", NULL}; char *jisx0201_1976_0[] = {"JIS_X0201", "ISO-IR-14", "jis", /* hpux */ NULL}; char *jisx0208_1983_0[] = {"JIS_X0208", NULL}; char *jisx0208_1990_0[] = {"JIS_X0208", NULL}; char *jisx0212_1990_0[] = {"JIS_X0212", NULL}; char *koi8_r[] = {"KOI8-R", /* gnu, solaris */ NULL}; char *koi8_u[] = {"KOI8-U", NULL}; char *ksc5601[] = {"KSC5636", "ko_KR-johap", /* solaris */ "ko_KR-johap92", "ko_KR-euc", "eucKR", "EUC-KR", "EUCKR", "euc-kr", "CP949", /* osf */ NULL}; char *microsoft_cp1251[] = {"CP1251", NULL}; char *microsoft_cp1255[] = {"CP1255", NULL}; char *microsoft_cp1256[] = {"CP1256", NULL}; char *mulelao_1[] = {"MULELAO-1", "MULELAO", NULL}; char *sjisx_1[] = {"SHIFT_JIS", "SJIS", /* solaris, osf */ "sjis", /* hpux */ "PCK", /* solaris */ NULL}; char *tatar_cyr[] = {NULL}; char *tcvn_5712[] = {"TCVN", NULL}; char *tis620_0[] = {"TIS-620", "tis620", /* hpux */ "TACTIS", /* osf */ NULL}; char *viscii1_1_1[] = {"VISCII", NULL}; /* encofing only ...*/ char *utf_8[] = {"UTF-8", /* gnu, solaris */ "UTF8", "utf8", "utf_8", NULL}; char *usc_2[] = {"USC-2", "USC2", "usc2", "usc-2", "usc_2", NULL}; char *usc_4[] = {"USC-4", "USC4", "usc4", "usc-4", "usc_4", NULL}; char *utf_16[] = {"UTF-16", "UTF16", "utf16", "utf_16", NULL}; char *euc_jp[] = {"EUC-JP", "EUCJP", "euc_jp", "euc-jp", "eucjp", NULL}; #endif #if FiconvSupport #ifdef HAVE_BIDI #define CT_ENTRY(x,y,z) \ {x, y, FLC_INDEX_ICONV_CHARSET_NOT_INITIALIZED, z, FLC_ENCODING_TYPE_FONT} #define CT_ENTRY_WET(x,y,z,t) \ {x, y, FLC_INDEX_ICONV_CHARSET_NOT_INITIALIZED, z, t} #else #define CT_ENTRY(x,y,z) \ {x, y, FLC_INDEX_ICONV_CHARSET_NOT_INITIALIZED, NULL, FLC_ENCODING_TYPE_FONT} #define CT_ENTRY_WET(x,y,z,t) \ {x, y, FLC_INDEX_ICONV_CHARSET_NOT_INITIALIZED, NULL, t} #endif #else /* !FlocaleIconvSupport */ #ifdef HAVE_BIDI #define CT_ENTRY(x,y,z) \ {x, nullsl, FLC_INDEX_ICONV_CHARSET_NOT_FOUND, z, FLC_ENCODING_TYPE_FONT} #define CT_ENTRY_WET(x,y,z,t) \ {x, nullsl, FLC_INDEX_ICONV_CHARSET_NOT_FOUND, z, t} #else #define CT_ENTRY(x,y,z) \ {x, nullsl, FLC_INDEX_ICONV_CHARSET_NOT_FOUND, NULL, FLC_ENCODING_TYPE_FONT} #define CT_ENTRY_WET(x,y,z,t) \ {x, nullsl, FLC_INDEX_ICONV_CHARSET_NOT_FOUND, NULL, t} #endif #endif static FlocaleCharset UnknownCharset = {"Unknown", nullsl, FLC_INDEX_ICONV_CHARSET_NOT_FOUND, NULL}; /* the table contains all Xorg "charset" plus some others */ FlocaleCharset FlocaleCharsetTable[] = { CT_ENTRY("ARMSCII-8", armscii_8, NULL), CT_ENTRY("BIG5-0", big5_0, NULL), CT_ENTRY("BIG5HKSCS-0", big5hkscs_0, NULL), CT_ENTRY("CNS11643.1986-1", cns11643, NULL), CT_ENTRY("CNS11643.1986-2", cns11643, NULL), CT_ENTRY("CNS11643.1992-3", cns11643, NULL), CT_ENTRY("CNS11643.1992-4", cns11643, NULL), CT_ENTRY("CNS11643.1992-5", cns11643, NULL), CT_ENTRY("CNS11643.1992-6", cns11643, NULL), CT_ENTRY("CNS11643.1992-7", cns11643, NULL), CT_ENTRY("DOSENCODING-CP437", dosencoding_cp437, NULL), CT_ENTRY("DOSENCODING-CP850", dosencoding_cp850, NULL), CT_ENTRY("EUC-JP", euc_jp, NULL), CT_ENTRY("GB2312.1980-0", gb2312_1980_0, NULL), CT_ENTRY("GBK-0", gbk_0, NULL), CT_ENTRY("GEORGIAN-ACADEMY", georgian_academy, NULL), CT_ENTRY("GEORGIAN-PS", georgian_ps, NULL), CT_ENTRY("IBM-CP1133", ibm_cp1133, NULL), CT_ENTRY("ISIRI-3342", isiri_3342, "ISIRI-3342"), /* exception ISO10646-1 implies UTF-8 and not USC-2 ! */ CT_ENTRY_WET("ISO10646-1", utf_8, "UTF-8", FLC_ENCODING_TYPE_UTF_8), CT_ENTRY("ISO8859-1", iso8859_1, NULL), CT_ENTRY("ISO8859-2", iso8859_2, NULL), CT_ENTRY("ISO8859-3", iso8859_3, NULL), CT_ENTRY("ISO8859-4", iso8859_4, NULL), CT_ENTRY("ISO8859-5", iso8859_5, NULL), CT_ENTRY("ISO8859-6", iso8859_6, "ISO8859-6"), CT_ENTRY("ISO8859-6.8X", iso8859_6, "ISO8859-6"), CT_ENTRY("ISO8859-7", iso8859_7, NULL), CT_ENTRY("ISO8859-8", iso8859_8, "ISO8859-8"), CT_ENTRY("ISO8859-9", iso8859_9, NULL), CT_ENTRY("ISO8859-9E", iso8859_9, NULL), CT_ENTRY("ISO8859-10", iso8859_10, NULL), CT_ENTRY("ISO8859-13", iso8859_13, NULL), CT_ENTRY("ISO8859-14", iso8859_14, NULL), CT_ENTRY("ISO8859-15", iso8859_15, NULL), CT_ENTRY("ISO8859-16", iso8859_16, NULL), CT_ENTRY("JISX.UDC-1", jisx0201_1976_0, NULL), /* ? */ CT_ENTRY("JISX0201.1976-0", jisx0201_1976_0, NULL), CT_ENTRY("JISX0208.1983-0", jisx0208_1983_0, NULL), CT_ENTRY("JISX0208.1990-0", jisx0208_1990_0, NULL), CT_ENTRY("JISX0212.1990-0", jisx0212_1990_0, NULL), CT_ENTRY("KOI8-C", koi8_r, NULL), CT_ENTRY("KOI8-R", koi8_r, NULL), CT_ENTRY("KOI8-U", koi8_u, NULL), CT_ENTRY("KSC5601.1987-0", ksc5601, NULL), CT_ENTRY("KSC5601.1992-0", ksc5601, NULL), CT_ENTRY("MICROSOFT-CP1251", microsoft_cp1251, NULL), CT_ENTRY("MICROSOFT-CP1255", microsoft_cp1255, "CP1255"), CT_ENTRY("MICROSOFT-CP1256", microsoft_cp1256, "CP1256"), CT_ENTRY("MULELAO-1", mulelao_1, NULL), CT_ENTRY("SJISX-1", sjisx_1, NULL), CT_ENTRY("TATAR-CYR", tatar_cyr, NULL), CT_ENTRY("TCVN-5712", tcvn_5712, NULL), CT_ENTRY("TIS620-0", tis620_0, NULL), CT_ENTRY("VISCII1.1-1", viscii1_1_1, NULL), /* aliases */ /* CT_ENTRY("ADOBE-STANDARD", iso8859_1, NULL), no! */ CT_ENTRY("ASCII-0", iso8859_1, NULL), CT_ENTRY("BIBIG5HKSCS", big5_0, NULL), /* ? */ CT_ENTRY("BIG5-E0", big5_0, NULL), /* emacs */ CT_ENTRY("BIG5-E1", big5_0, NULL), /* emacs */ CT_ENTRY("BIG5-1", big5_0, NULL), CT_ENTRY("ISO646.1991-IRV", iso8859_1, NULL), CT_ENTRY("TIS620.2533-1", tis620_0, NULL), CT_ENTRY_WET("UTF-8", utf_8, "UTF-8", FLC_ENCODING_TYPE_UTF_8), CT_ENTRY_WET("USC-2", usc_2, "USC-2", FLC_ENCODING_TYPE_USC_2), CT_ENTRY_WET("USC-4", usc_4, NULL, FLC_ENCODING_TYPE_USC_4), CT_ENTRY_WET("UTF-16", utf_16, NULL, FLC_ENCODING_TYPE_UTF_16), CT_ENTRY(NULL, nullsl, NULL) }; /* to be supported: ADOBE-STANDARD, some Xft1 charset */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ static FlocaleCharset *FlocaleCharsetOfXCharset(char *x) { int j = 0; while(FlocaleCharsetTable[j].x != NULL) { if (StrEquals(x,FlocaleCharsetTable[j].x)) { return &FlocaleCharsetTable[j]; } j++; } return NULL; } static FlocaleCharset *FlocaleCharsetOfLocaleCharset(char *l) { int j = 0, i = 0; while(FlocaleCharsetTable[j].x != NULL) { if (StrEquals(l, FlocaleCharsetTable[j].x)) { return &FlocaleCharsetTable[j]; } i = 0; while(FlocaleCharsetTable[j].locale[i] != NULL) { if (StrEquals(l, FlocaleCharsetTable[j].locale[i])) { return &FlocaleCharsetTable[j]; } i++; } j++; } return NULL; } static FlocaleCharset *FlocaleCharsetOfFontStruct(Display *dpy, XFontStruct *fs) { unsigned long value = 0; char *name,*tmp; FlocaleCharset *fc; int count = 0; if (fs == NULL) return NULL; if (!XGetFontProperty(fs, XA_FONT, &value)) { return NULL; } if ((name = XGetAtomName(dpy, value)) == NULL) { return NULL; } tmp = name; while (*tmp != '\0' && count < 13) { if (*tmp == '-') { count++; } tmp++; if (count == 13) { fc = FlocaleCharsetOfXCharset(tmp); XFree(name); return fc; } } XFree(name); return NULL; } static void FlocaleInit_X_Charset(Display *dpy, const char *module) { #ifdef HAVE_XOUTPUT_METHOD XOM om; XOMCharSetList cs; int i; om = XOpenOM(dpy, NULL, NULL, NULL); if (om && XGetOMValues(om, XNRequiredCharSet, &cs, NULL) == NULL) { if (cs.charset_count > 0) { if (FLCXOMCharsetList != NULL) { free(FLCXOMCharsetList); } FLCXOMCharsetList_num = cs.charset_count; FLCXOMCharsetList = (FlocaleCharset **)safemalloc( sizeof(FlocaleCharset) * cs.charset_count); for (i = 0; i < FLCXOMCharsetList_num; i++) { FLCXOMCharsetList[i] = FlocaleCharsetOfXCharset( cs.charset_list[i]); #if FLOCALE_DEBUG_CHARSET fprintf(stderr, "[FlocaleInitCharset] XOM charset " "%i: %s, bidi:%s\n", i, FLC_DEBUG_GET_X_CHARSET( FLCXOMCharsetList[i]), FLC_DEBUG_GET_BIDI_CHARSET ( FLCXOMCharsetList[i])); #endif } } } if (om) { XCloseOM(om); } if (FLCXOMCharsetList_num > 0 && FLCXOMCharsetList[0]) { char *best_charset; if (FLCLocaleCharset != NULL) { best_charset = FLCLocaleCharset->x; #if FLOCALE_DEBUG_CHARSET fprintf(stderr, "[FlocaleInitCharset] FLCLocaleCharset: %s\n", best_charset); #endif } else { best_charset = FLOCALE_FALLBACK_XCHARSET; #if FLOCALE_DEBUG_CHARSET fprintf(stderr, "[FlocaleInitCharset] FALLBACK: %s\n", best_charset); #endif } FLCXOMCharset = FLCXOMCharsetList[0]; if (best_charset == NULL) { /* should not happen */ } else { for(i = 0; i < FLCXOMCharsetList_num; i++) { if (StrEquals( best_charset, FLC_DEBUG_GET_X_CHARSET( FLCXOMCharsetList[i]))) { FLCXOMCharset = FLCXOMCharsetList[i]; break; } } } #if FLOCALE_DEBUG_CHARSET fprintf(stderr, "[FlocaleInitCharset] XOM charset " "%i: %s\n", i, FLC_DEBUG_GET_X_CHARSET(FLCXOMCharset)); #endif } #endif } /* ---------------------------- interface functions ------------------------ */ void FlocaleCharsetInit(Display *dpy, const char *module) { static Bool initialized = False; char *charset; if (initialized == True) { return; } initialized = True; /* try to find the regular charset */ charset = getenv("CHARSET"); #if FLOCALE_DEBUG_CHARSET fprintf(stderr, "[FlocaleInitCharset] CHARSET: %s\n", (!charset)? "null":charset); #endif if ((!charset || strlen(charset) < 3) && FlocaleLibcharsetSupport) { charset = (char *)Flocale_charset(); #if FLOCALE_DEBUG_CHARSET fprintf( stderr, "[FlocaleInitCharset] FlocaleLibcharsetSupport: %s\n", (!charset)? "null":charset); #endif } if ((!charset || strlen(charset) < 3) && FlocaleCodesetSupport) { charset = Fnl_langinfo(FCODESET); #if FLOCALE_DEBUG_CHARSET fprintf( stderr, "[FlocaleInitCharset] Fnl_langinfo: %s\n", (!charset)? "null":charset); #endif } if (charset != NULL && strlen(charset) > 2) { FLCLocaleCharset = FlocaleCharsetOfLocaleCharset(charset); #if FLOCALE_DEBUG_CHARSET fprintf( stderr, "[FlocaleInitCharset] FLCLocaleCharset: %s\n", charset); #endif } /* set the defaults X locale charsets */ FlocaleInit_X_Charset(dpy, module); /* never null */ FLCUtf8Charset = FlocaleCharsetOfXCharset(FLOCALE_UTF8_XCHARSET); #if FLOCALE_DEBUG_CHARSET fprintf(stderr,"[FlocaleCharsetInit] locale charset: x:%s, bidi:%s\n", FLC_DEBUG_GET_X_CHARSET(FLCXOMCharset), FLC_DEBUG_GET_BIDI_CHARSET (FLCXOMCharset)); fprintf(stderr,"[FlocaleCharsetInit] locale charset: x:%s, bidi:%s\n", FLC_DEBUG_GET_X_CHARSET(FLCLocaleCharset), FLC_DEBUG_GET_BIDI_CHARSET (FLCLocaleCharset)); #endif return; } void FlocaleCharsetSetFlocaleCharset( Display *dpy, FlocaleFont *flf, char *hints, char *encoding, char *module) { char *charset = NULL; char *iconv = NULL; Bool iconv_found = False; int i = 0; FlocaleCharsetInit(dpy, module); if (hints && *hints) { iconv = GetQuotedString( hints, &charset, "/", NULL, NULL, NULL); if (charset && *charset && *charset != '*' ) { flf->fc = FlocaleCharsetOfXCharset(charset); } if (flf->fc == NULL && charset && *charset && *charset != '*') { flf->fc = FlocaleCharsetOfLocaleCharset(charset); } if (flf->fc == NULL && iconv && *iconv) { flf->fc = FlocaleCharsetOfLocaleCharset(iconv); } } if (flf->fc == NULL) { if (FftSupport && flf->fftf.fftfont != NULL) { flf->fc = FlocaleCharsetOfXCharset(flf->fftf.encoding); } else if (flf->fontset != None) { if (FLCXOMCharset != NULL) { flf->fc = FLCXOMCharset; } else { /* we are here if !HAVE_XOUTPUT_METHOD */ XFontStruct **fs_list; char **ml; if (XFontsOfFontSet( flf->fontset, &fs_list, &ml) > 0) { flf->fc = FLCXOMCharset = FlocaleCharsetOfFontStruct( dpy, fs_list[0]); } } } else if (flf->font != NULL) { flf->fc = FlocaleCharsetOfFontStruct(dpy, flf->font); } } if (flf->fc != NULL && iconv && *iconv) { /* the user has specified an iconv converter name: * check if we have it and force user choice */ while(!iconv_found && FLC_GET_LOCALE_CHARSET(flf->fc,i) != NULL) { if ( strcmp( iconv, FLC_GET_LOCALE_CHARSET(flf->fc,i)) == 0) { iconv_found = True; /* Trust the user? yes ... */ FLC_SET_ICONV_INDEX(flf->fc,i); } i++; } } if (iconv && *iconv && !iconv_found) { FlocaleCharset *fc; /* the user has specified an iconv converter name and we do not * have it: must create a FlocaleCharset */ flf->flags.must_free_fc = True; fc = (FlocaleCharset *)safemalloc(sizeof(FlocaleCharset)); if (flf->fc != NULL) { CopyString(&fc->x, flf->fc->x); fc->encoding_type = flf->fc->encoding_type; if (flf->fc->bidi) CopyString(&fc->bidi, flf->fc->bidi); else fc->bidi = NULL; } else { CopyString(&fc->x, "Unknown"); /* for simplicity */ fc->bidi = NULL; fc->encoding_type = FLC_ENCODING_TYPE_FONT; } fc->locale = (char **)safemalloc(2*sizeof(char *)); CopyString(&fc->locale[0], iconv); fc->locale[1] = NULL; fc->iconv_index = FLC_INDEX_ICONV_CHARSET_NOT_INITIALIZED; flf->fc = fc; } if (charset != NULL) { free(charset); } if (flf->fc == NULL) { flf->fc = &UnknownCharset; } /* now the string charset */ if (encoding != NULL) { flf->str_fc = FlocaleCharsetOfXCharset(encoding); if (flf->str_fc == NULL) { flf->str_fc = FlocaleCharsetOfLocaleCharset(encoding); } if (flf->str_fc == NULL) { flf->str_fc = &UnknownCharset; } } else if (FftSupport && flf->fftf.fftfont != NULL) { if (flf->fftf.str_encoding != NULL) { flf->str_fc = FlocaleCharsetOfXCharset( flf->fftf.str_encoding); if (flf->str_fc == NULL) { flf->str_fc = FlocaleCharsetOfLocaleCharset( flf->fftf.str_encoding); } if (flf->str_fc == NULL) { flf->str_fc = &UnknownCharset; } } else { flf->str_fc = FlocaleCharsetGetDefaultCharset(dpy, module); } } if (flf->str_fc == NULL) { if (flf->fc != &UnknownCharset) { flf->str_fc = flf->fc; } else { flf->str_fc = FlocaleCharsetGetDefaultCharset(dpy, module); } } } FlocaleCharset *FlocaleCharsetGetDefaultCharset(Display *dpy, char *module) { static int warn = True; FlocaleCharsetInit(dpy, module); if (FLCXOMCharset != NULL) return FLCXOMCharset; if (FLCLocaleCharset != NULL) return FLCLocaleCharset; if (warn) { warn = False; fprintf(stderr, "[%s][%s]: WARN -- Cannot find default locale " "charset with:\n\t", (module != NULL)? module:"FVWMlibs", "FlocaleGetDefaultCharset"); fprintf(stderr,"X Output Method "); fprintf(stderr,", CHARSET env variable"); if (FlocaleLibcharsetSupport) fprintf(stderr,", locale_charset"); if (FlocaleCodesetSupport) fprintf(stderr,", nl_langinfo"); fprintf(stderr,"\n"); /* never null */ FLCLocaleCharset = FlocaleCharsetOfXCharset(FLOCALE_FALLBACK_XCHARSET); fprintf(stderr,"\tUse default charset: %s\n", FLOCALE_FALLBACK_XCHARSET); } return FLCLocaleCharset; } FlocaleCharset *FlocaleCharsetGetFLCXOMCharset(void) { return FLCXOMCharset; } FlocaleCharset *FlocaleCharsetGetUtf8Charset(void) { return FLCUtf8Charset; } FlocaleCharset *FlocaleCharsetGetLocaleCharset(void) { return FLCLocaleCharset; } FlocaleCharset *FlocaleCharsetGetUnknownCharset(void) { return &UnknownCharset; } const char *FlocaleGetBidiCharset(Display *dpy, FlocaleCharset *fc) { if (fc == NULL || fc == FlocaleCharsetGetUnknownCharset() || fc->bidi == NULL) { return NULL; } return (const char *)fc->bidi; } FlocaleCharset *FlocaleCharsetGetEUCJPCharset(void) { static FlocaleCharset *fc = NULL; if (fc != NULL) return fc; /* never null */ fc = FlocaleCharsetOfXCharset("EUC-JP"); return fc; } Bool FlocaleCharsetIsCharsetXLocale(Display *dpy, char *charset, char *module) { #ifdef HAVE_XOUTPUT_METHOD int i; FlocaleCharsetInit(dpy, module); if (FLCXOMCharsetList_num > 0) { for(i = 0; i < FLCXOMCharsetList_num; i++) { if (StrEquals( FLC_DEBUG_GET_X_CHARSET( FLCXOMCharsetList[i]), charset)) { return True; } } } return False; #else return True; /* Hum */ #endif } void FlocaleCharsetPrintXOMInfo(void) { #ifdef HAVE_XOUTPUT_METHOD int i; fprintf(stderr," XOM Charsets: "); if (FLCXOMCharsetList_num > 0) { for(i = 0; i < FLCXOMCharsetList_num; i++) { fprintf( stderr, "%s ", FLC_DEBUG_GET_X_CHARSET(FLCXOMCharsetList[i])); } } fprintf(stderr,"\n"); #endif } fvwm-2.7.0/libs/envvar.h0000644000175000017500000000604514147024700012027 00000000000000/* -*-c-*- */ #ifndef FVWMLIB_ENVVAR_H #define FVWMLIB_ENVVAR_H /* * SYNOPSIS #include "envvar.h" * int envExpand(char *s, int maxstrlen); * * INPUT s string to expand environment variables in. * maxstrlen max length of string, including '\0'. * * OUTPUT s the string with environment variables expanded. * * RETURNS Number of changes done. * * NOTES A non-existing variable is substituted with the empty * string. * */ int envExpand(char *s, int maxstrlen); /* * FUNCTION Expand environment variables into a new string. * * SYNOPSIS #include "envvar.h" * char *envDupExpand(const char *s, int extra); * * INPUT s string to expand environment variables in. * extra number of extra bytes to allocate in the * string, in addition to the string contents * and the terminating '\0'. * * RETURNS A dynamically allocated string with environment * variables expanded. * Use free() to deallocate the buffer when it is no * longer needed. * NULL is returned if there is not enough memory. * * NOTES A non-existing variable is substituted with the empty * string. * */ char *envDupExpand(const char *s, int extra); /* * FUNCTION Search for the first environment variable and return * its contents and coordinates in the given string. * * INPUT s the string to scan. * may include $ and { } that introduce variable. * * OUTPUT beg index in the string of matching $. * end index in the string, first after matching var. * * RETURNS The variable contents; "" if env variable has legal name, * but does not exist; or NULL if no env variables found. * Returned constant string must not be deallocated. * * NOTE This function will only return `legal' variables. There * may be $'s in the string that are not followed by what * is considered a legal variable name introducer. Such * occurrences are skipped. * If nothing is found returns NULL and sets beg and end to 0. * * EXAMPLE getFirstEnv("echo $HOME/.fvwm/config", &beg, &end) * returns "/home/username" and beg=5, end=10. * */ const char* getFirstEnv(const char *s, int *beg, int *end); /* This function keeps a list of all strings that were set in the environment. * If a variable is written again, the old memory is freed. This function * should be called instead of putenv(). * * var - environement variable name * env - environment string ("variable=value") * * Both arguments are copied internally and should be freed after calling this * function. */ void flib_putenv(char *var, char *env); /* Replacement for unsetenv(). */ void flib_unsetenv(const char *name); #endif fvwm-2.7.0/libs/Grab.c0000644000175000017500000000354514147024700011376 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ** MyXGrabServer & MyXUngrabServer - to handle nested grab server calls */ #include "config.h" #include "Grab.h" /* Made into global for module interface. See module.c. */ int myxgrabcount = 0; static unsigned int keyboard_grab_count = 0; static unsigned int key_grab_count = 0; void MyXGrabServer(Display *disp) { if (myxgrabcount == 0) { XSync(disp, 0); XGrabServer(disp); } XSync(disp, 0); ++myxgrabcount; } void MyXUngrabServer(Display *disp) { if (--myxgrabcount < 0) /* should never happen */ { myxgrabcount = 0; } if (myxgrabcount == 0) { XUngrabServer(disp); } XSync(disp, 0); } void MyXGrabKeyboard(Display *dpy) { keyboard_grab_count++; XGrabKeyboard( dpy, RootWindow(dpy, DefaultScreen(dpy)), False, GrabModeAsync, GrabModeAsync, CurrentTime); return; } void MyXUngrabKeyboard(Display *dpy) { if (keyboard_grab_count > 0) { keyboard_grab_count--; } if (keyboard_grab_count == 0 && key_grab_count == 0) { XUngrabKeyboard(dpy, CurrentTime); } return; } void MyXGrabKey(Display *disp) { key_grab_count++; return; } void MyXUngrabKey(Display *disp) { if (key_grab_count > 0) { key_grab_count--; keyboard_grab_count++; MyXUngrabKeyboard(disp); } return; } fvwm-2.7.0/libs/ClientMsg.h0000644000175000017500000000102114147024700012400 00000000000000/* -*-c-*- */ /* * ICCCM Client Messages - Section 4.2.8 of the ICCCM dictates that all * client messages will have the following form: * * event type ClientMessage * message type _XA_WM_PROTOCOLS * window tmp->w * format 32 * data[0] message atom * data[1] time stamp */ #include #include #include void send_clientmessage(Display *disp, Window w, Atom a, Time timestamp); extern Atom _XA_WM_PROTOCOLS; fvwm-2.7.0/libs/Rectangles.h0000644000175000017500000000252414147024676012627 00000000000000/* -*-c-*- */ /* * Convinence functions for manipulating rectangles, segments, regions ...etc. */ #ifndef FRECTANGLES_H #define FRECTANGLES_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ /* If the two rectangles [x1, y1, w1, h2] and [x2, x2, w2, h2] have a * non emtpy interstection this function return True and the * XRectangle *r is set to the intersection (if not NULL). If the two * rectangles have an emty intersection False is returned and r is not * modified. */ Bool frect_get_intersection( int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2, XRectangle *r); /* as above but the input are XRectangles */ Bool frect_get_rect_intersection( XRectangle a, XRectangle b, XRectangle *r); /* as above for two segments */ Bool frect_get_seg_intersection( int x1, int w1, int x2, int w2, int *x, int *w); #endif fvwm-2.7.0/libs/ftime.h0000644000175000017500000000030114147024676011633 00000000000000/* -*-c-*- */ #include "config.h" #if TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif fvwm-2.7.0/libs/FShm.h0000644000175000017500000000275714147024676011405 00000000000000/* -*-c-*- */ #ifndef FSHM_H #define FSHM_H /* ---------------------------- included header files ---------------------- */ #include "config.h" #ifdef HAVE_XSHM #define XShmSupport 1 #else #define XShmSupport 0 #endif #if XShmSupport #include #include #include #endif /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ #if XShmSupport /* XShm */ typedef ShmSeg FShmSeg; typedef XShmSegmentInfo FShmSegmentInfo; #define FShmAttach XShmAttach #define FShmDetach XShmDetach #define FShmPutImage XShmPutImage #define FShmGetImage XShmGetImage #define FShmCreateImage XShmCreateImage /* shm */ #define Fshmget shmget #define Fshmat shmat #define Fshmdt shmdt #define Fshmctl shmctl #define Fshmget shmget #else /* XShm */ typedef unsigned long FhmSeg; typedef struct { FhmSeg shmseg; int shmid; char *shmaddr; Bool readOnly; } FShmSegmentInfo; #define FShmAttach(a, b) 0 #define FShmDetach(a, b) 0 #define FShmPutImage(a, b, c, d, e, f, g, h, i, j, k) 0 #define FShmGetImage(a, b, c, d, e, f) 0 #define FShmCreateImage(a, b, c, d, e, f, g, h) NULL /* shm */ #define Fshmget(a, b, c) 0 #define Fshmat(a, b, c) NULL; #define Fshmdt(a) #define Fshmctl(a, b, c) #endif #endif /* FSHM_H */ fvwm-2.7.0/libs/gravity.c0000644000175000017500000002747514147024700012220 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include "fvwmlib.h" #include "Parse.h" #include "Strings.h" #include "gravity.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ struct _gravity_offset { int x, y; }; /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ #define STRINGS_PER_DIR 7 static char *gravity_dir_optlist[] = { "-", "N", "North", "Top", "t", "Up", "u", "]", "E", "East", "Right", "r", "Right", "r", "_", "S", "South", "Bottom", "b", "Down", "d", "[", "W", "West", "Left", "l", "Left", "l", "^", "NE", "NorthEast", "TopRight", "tr", "UpRight", "ur", ">", "SE", "SouthEast", "BottomRight", "br", "DownRight", "dr", "v", "SW", "SouthWest", "BottomLeft", "bl", "DownLeft", "dl", "<", "NW", "NorthWest", "TopLeft", "tl", "UpLeft", "ul", ".", "C", "Center", "Centre", NULL, NULL, NULL, NULL }; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ /* ---------------------------- interface functions ------------------------ */ /* map gravity to (x,y) offset signs for adding to x and y when window is * mapped to get proper placement. */ void gravity_get_offsets(int grav, int *xp,int *yp) { static struct _gravity_offset gravity_offsets[11] = { { 0, 0 }, /* ForgetGravity */ { -1, -1 }, /* NorthWestGravity */ { 0, -1 }, /* NorthGravity */ { 1, -1 }, /* NorthEastGravity */ { -1, 0 }, /* WestGravity */ { 0, 0 }, /* CenterGravity */ { 1, 0 }, /* EastGravity */ { -1, 1 }, /* SouthWestGravity */ { 0, 1 }, /* SouthGravity */ { 1, 1 }, /* SouthEastGravity */ { 0, 0 }, /* StaticGravity */ }; if (grav < ForgetGravity || grav > StaticGravity) { *xp = *yp = 0; } else { *xp = (int)gravity_offsets[grav].x; *yp = (int)gravity_offsets[grav].y; } return; } /* Move a rectangle while taking gravity into account. */ void gravity_move(int gravity, rectangle *rect, int xdiff, int ydiff) { int xoff; int yoff; gravity_get_offsets(gravity, &xoff, &yoff); rect->x -= xoff * xdiff; rect->y -= yoff * ydiff; return; } /* Resize rectangle while taking gravity into account. */ void gravity_resize(int gravity, rectangle *rect, int wdiff, int hdiff) { int xoff; int yoff; gravity_get_offsets(gravity, &xoff, &yoff); rect->x -= (wdiff * (xoff + 1)) / 2; rect->width += wdiff; rect->y -= (hdiff * (yoff + 1)) / 2; rect->height += hdiff; return; } /* Moves a child rectangle taking its gravity into accout as if the parent * rectangle was moved and resized. */ void gravity_move_resize_parent_child( int child_gravity, rectangle *parent_diff_r, rectangle *child_r) { int xoff; int yoff; gravity_get_offsets(child_gravity, &xoff, &yoff); child_r->x -= xoff * parent_diff_r->x; child_r->y -= yoff * parent_diff_r->y; child_r->x += ((xoff + 1) * parent_diff_r->width) / 2; child_r->y += ((yoff + 1) * parent_diff_r->height) / 2; return; } direction_t gravity_grav_to_dir( int grav) { switch (grav) { case NorthWestGravity: return DIR_NW; case NorthGravity: return DIR_N; case NorthEastGravity: return DIR_NE; case WestGravity: return DIR_W; case CenterGravity: return DIR_NONE; case EastGravity: return DIR_E; case SouthWestGravity: return DIR_SW; case SouthGravity: return DIR_S; case SouthEastGravity: return DIR_SE; case ForgetGravity: case StaticGravity: default: return DIR_NONE; } } int gravity_dir_to_grav( direction_t dir) { switch (dir) { case DIR_N: return NorthGravity; case DIR_E: return EastGravity; case DIR_S: return SouthGravity; case DIR_W: return WestGravity; case DIR_NE: return NorthEastGravity; case DIR_SE: return SouthEastGravity; case DIR_SW: return SouthWestGravity; case DIR_NW: return NorthWestGravity; case DIR_NONE: default: return ForgetGravity; } } int gravity_combine_xy_grav( int grav_x, int grav_y) { switch (grav_x) { case NorthWestGravity: case WestGravity: case SouthWestGravity: grav_x = WestGravity; break; case NorthEastGravity: case EastGravity: case SouthEastGravity: grav_x = EastGravity; break; default: grav_x = CenterGravity; break; } switch (grav_y) { case NorthWestGravity: case NorthGravity: case NorthEastGravity: grav_y = NorthGravity; break; case SouthWestGravity: case SouthGravity: case SouthEastGravity: grav_y = SouthGravity; break; default: grav_y = CenterGravity; break; } if (grav_x == CenterGravity) { return grav_y; } switch (grav_y) { case NorthGravity: return (grav_x == WestGravity) ? NorthWestGravity : NorthEastGravity; case SouthGravity: return (grav_x == WestGravity) ? SouthWestGravity : SouthEastGravity; case CenterGravity: default: return grav_x; } return 0; } void gravity_split_xy_grav( int *ret_grav_x, int *ret_grav_y, int in_grav) { switch (in_grav) { case NorthWestGravity: case WestGravity: case SouthWestGravity: *ret_grav_x = WestGravity; break; case NorthEastGravity: case EastGravity: case SouthEastGravity: *ret_grav_x = EastGravity; break; case NorthGravity: case CenterGravity: case SouthGravity: case ForgetGravity: case StaticGravity: default: *ret_grav_x = CenterGravity; break; } switch (in_grav) { case NorthWestGravity: case NorthGravity: case NorthEastGravity: *ret_grav_y = NorthGravity; break; case SouthWestGravity: case SouthGravity: case SouthEastGravity: *ret_grav_y = SouthGravity; break; case WestGravity: case CenterGravity: case EastGravity: case ForgetGravity: case StaticGravity: default: *ret_grav_y = CenterGravity; break; } } int gravity_combine_xy_dir( int dir_x, int dir_y) { switch (dir_x) { case DIR_W: case DIR_NW: case DIR_SW: dir_x = DIR_W; break; case DIR_E: case DIR_NE: case DIR_SE: dir_x = DIR_E; break; default: dir_x = DIR_NONE; break; } switch (dir_y) { case DIR_N: case DIR_NW: case DIR_NE: dir_y = DIR_N; break; case DIR_S: case DIR_SW: case DIR_SE: dir_y = DIR_S; break; default: dir_y = DIR_NONE; break; } if (dir_x == DIR_NONE) { return dir_y; } switch (dir_y) { case DIR_N: return (dir_x == DIR_W) ? DIR_NW : DIR_NE; case DIR_S: return (dir_x == DIR_W) ? DIR_SW : DIR_SE; case DIR_NONE: default: return dir_x; } } void gravity_split_xy_dir( int *ret_dir_x, int *ret_dir_y, int in_dir) { switch (in_dir) { case DIR_W: case DIR_SW: case DIR_NW: *ret_dir_x = DIR_W; break; case DIR_E: case DIR_NE: case DIR_SE: *ret_dir_x = DIR_E; break; case DIR_N: case DIR_S: case DIR_NONE: default: *ret_dir_x = DIR_NONE; break; } switch (in_dir) { case DIR_N: case DIR_NW: case DIR_NE: *ret_dir_y = DIR_N; break; case DIR_S: case DIR_SW: case DIR_SE: *ret_dir_y = DIR_S; break; case DIR_W: case DIR_E: case DIR_NONE: default: *ret_dir_y = DIR_NONE; break; } } static inline int __gravity_override_one_axis(int dir_orig, int dir_mod) { int ret_dir; if (dir_mod == DIR_NONE) { ret_dir = dir_orig; } else { ret_dir = dir_mod; } return ret_dir; } int gravity_override_dir( int dir_orig, int dir_mod) { int ret_dir; int ret_x; int ret_y; int orig_x; int orig_y; int mod_x; int mod_y; gravity_split_xy_dir(&orig_x, &orig_y, dir_orig); gravity_split_xy_dir(&mod_x, &mod_y, dir_mod); ret_x = __gravity_override_one_axis(orig_x, mod_x); ret_y = __gravity_override_one_axis(orig_y, mod_y); ret_dir = gravity_combine_xy_dir(ret_x, ret_y); return ret_dir; } int gravity_dir_to_sign_one_axis( direction_t dir) { switch (dir) { case DIR_N: case DIR_W: return -1; case DIR_S: case DIR_E: return 1; default: return 0; } } /* Parses the next token in action and returns * * 0 if it is N, North, Top or Up * 1 if it is E, East, Right or Right * 2 if it is S, South, Bottom or Down * 3 if it is E, West, Left or Left * 4 if it is NE, NorthEast, TopRight or UpRight * 5 if it is SE, SouthEast, BottomRight or DownRight * 6 if it is SW, SouthWest, BottomLeft or DownLeft * 7 if it is NW, NorthWest, TopLeft or UpLeft * 8 if it is C, Center or Centre * default_ret if no string matches. * * A pointer to the first character in action behind the token is returned * through ret_action in this case. ret_action may be NULL. If the token * matches none of these strings the default_ret value is returned and the * action itself is passed back in ret_action. */ direction_t gravity_parse_dir_argument( char *action, char **ret_action, direction_t default_ret) { int index; int rc; char *next; next = GetNextTokenIndex(action, gravity_dir_optlist, 0, &index); if (index == -1) { /* nothing selected, use default and don't modify action */ rc = default_ret; next = action; } else { rc = index / STRINGS_PER_DIR; } if (ret_action) { *ret_action = next; } return (direction_t)rc; } char *gravity_dir_to_string(direction_t dir, char *default_str) { char *str = NULL; int d = dir * STRINGS_PER_DIR; if (d >= sizeof(gravity_dir_optlist)/sizeof(gravity_dir_optlist[0])) { return default_str; } str = gravity_dir_optlist[d]; if (str == NULL) { return default_str; } return str; } multi_direction_t gravity_parse_multi_dir_argument( char *action, char **ret_action) { int rc = MULTI_DIR_NONE; char *token, *str; direction_t dir = gravity_parse_dir_argument(action, ret_action, -1); if (dir != -1) { rc = (1 << dir); } else { token = PeekToken(action, &str); if (StrEquals(token, "all")) { rc = MULTI_DIR_ALL; *ret_action = str; } else { rc = MULTI_DIR_NONE; } } return (multi_direction_t)rc; } void gravity_get_next_multi_dir(int dir_set, multi_direction_t *dir) { if (*dir == MULTI_DIR_NONE) { *dir = MULTI_DIR_FIRST; if (dir_set & *dir) { return; } } while(*dir != MULTI_DIR_LAST) { *dir = (*dir << 1); if (dir_set & *dir) { return; } } *dir = MULTI_DIR_NONE; return; } direction_t gravity_multi_dir_to_dir(multi_direction_t mdir) { direction_t dir = DIR_NONE; for ( ; mdir != 0; dir++) { mdir = (mdir >> 1); } if (dir > DIR_ALL_MASK) { dir = DIR_NONE; } return dir; } void gravity_rotate_xy(rotation_t rot, int x, int y, int *ret_x, int *ret_y) { int tx; int ty; switch (rot) { case ROTATION_90: /* CW */ tx = -y; ty = x; break; case ROTATION_180: tx = -x; ty = -y; break; case ROTATION_270: /* CCW */ tx = y; ty = -x; break; default: case ROTATION_0: tx = x; ty = y; break; } *ret_x = tx; *ret_y = ty; return; } rotation_t gravity_add_rotations(rotation_t rot1, rotation_t rot2) { rotation_t rot; rot = ((rot1 + rot2) & ROTATION_MASK); return rot; } fvwm-2.7.0/libs/charmap.h0000644000175000017500000000161414147024700012136 00000000000000/* -*-c-*- */ #ifndef CHARMAP_H #define CHARMAP_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ typedef struct { char key; int value; } charmap_t; /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ int charmap_string_to_mask( int *ret, const char *string, charmap_t *table, char *errstring); char charmap_mask_to_char(int mask, charmap_t *table); char *charmap_table_to_string(int mask, charmap_t *table); #endif /* CHARMAP_H */ fvwm-2.7.0/libs/Event.h0000644000175000017500000000032214147024700011577 00000000000000#ifndef LIB_EVENT_H #define LIB_EVENT_H /* * Return the subwindow member of an event if the event type has one. */ Window GetSubwindowFromEvent(Display *dpy, const XEvent *eventp); #endif /* LIB_EVENT_H */ fvwm-2.7.0/libs/fvwmlib.h0000644000175000017500000000110014147024700012157 00000000000000/* -*-c-*- */ #ifndef FVWMLIB_H #define FVWMLIB_H #include #include #include #include /* needed for xpm.h and Pixel defn */ #include #include "fvwmrect.h" #include "safemalloc.h" /* Convenience function ti init all the graphics subsystems */ void flib_init_graphics(Display *dpy); /* Set up heap debugging library dmalloc. */ #ifdef HAVE_DMALLOC_H #include #endif /* Set up mtrace from glibc 2.1.x for x > ? */ #ifdef MTRACE_DEBUGGING #include #endif #endif fvwm-2.7.0/libs/FSMlib.h0000644000175000017500000006136014147024700011643 00000000000000/* -*-c-*- */ #ifndef FSMlib_H #define FSMlib_H /* ---------------------------- included header files ---------------------- */ #include "config.h" #ifdef SESSION #define SessionSupport 1 #else #define SessionSupport 0 #endif #if SessionSupport #include #include #endif /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ #if SessionSupport /* SM.h */ #define FSmProtoMajor SmProtoMajor #define FSmProtoMinor SmProtoMinor #define FSmInteractStyleNone SmInteractStyleNone #define FSmInteractStyleErrors SmInteractStyleErrors #define FSmInteractStyleAny SmInteractStyleAny #define FSmDialogError SmDialogError #define FSmDialogNormal SmDialogNormal #define FSmSaveGlobal SmSaveGlobal #define FSmSaveLocal SmSaveLocal #define FSmSaveBoth SmSaveBoth #define FSmRestartIfRunning SmRestartIfRunning #define FSmRestartAnyway SmRestartAnyway #define FSmRestartImmediately SmRestartImmediately #define FSmRestartNever SmRestartNever #define FSmCloneCommand SmCloneCommand #define FSmCurrentDirectory SmCurrentDirectory #define FSmDiscardCommand SmDiscardCommand #define FSmEnvironment SmEnvironment #define FSmProcessID SmProcessID #define FSmProgram SmProgram #define FSmRestartCommand SmRestartCommand #define FSmResignCommand SmResignCommand #define FSmRestartStyleHint SmRestartStyleHint #define FSmShutdownCommand SmShutdownCommand #define FSmUserID SmUserID #define FSmCARD8 SmCARD8 #define FSmARRAY8 SmARRAY8 #define FSmLISTofARRAY8 SmLISTofARRAY8 #define FSM_Error SM_Error #define FSM_RegisterClient SM_RegisterClient #define FSM_RegisterClientReply SM_RegisterClientReply #define FSM_SaveYourself SM_SaveYourself #define FSM_SaveYourselfRequest SM_SaveYourselfRequest #define FSM_InteractRequest SM_InteractRequest #define FSM_Interact SM_Interact #define FSM_InteractDone SM_InteractDone #define FSM_SaveYourselfDone SM_SaveYourselfDone #define FSM_Die SM_Die #define FSM_ShutdownCancelled SM_ShutdownCancelled #define FSM_CloseConnection SM_CloseConnection #define FSM_SetProperties SM_SetProperties #define FSM_DeleteProperties SM_DeleteProperties #define FSM_GetProperties SM_GetProperties #define FSM_PropertiesReply SM_PropertiesReply #define FSM_SaveYourselfPhase2Request SM_SaveYourselfPhase2Request #define FSM_SaveYourselfPhase2 SM_SaveYourselfPhase2 #define FSM_SaveComplete SM_SaveComplete /* ICE.h */ #define FIceProtoMajor IceProtoMajor #define FIceProtoMinor IceProtoMinor #define FIceLSBfirst IceLSBfirst #define FIceMSBfirst IceMSBfirst #define FICE_Error ICE_Error #define FICE_ByteOrder ICE_ByteOrder #define FICE_ConnectionSetup ICE_ConnectionSetup #define FICE_AuthRequired ICE_AuthRequired #define FICE_AuthReply ICE_AuthReply #define FICE_AuthNextPhase ICE_AuthNextPhase #define FICE_ConnectionReply ICE_ConnectionReply #define FICE_ProtocolSetup ICE_ProtocolSetup #define FICE_ProtocolReply ICE_ProtocolReply #define FICE_Ping ICE_Ping #define FICE_PingReply ICE_PingReply #define FICE_WantToClose ICE_WantToClose #define FICE_NoClose ICE_NoClose #define FIceCanContinue IceCanContinue #define FIceFatalToProtocol IceFatalToProtocol #define FIceFatalToConnection IceFatalToConnection #define FIceBadMinor IceBadMinor #define FIceBadState IceBadState #define FIceBadLength IceBadLength #define FIceBadValue IceBadValue #define FIceBadMajor IceBadMajor #define FIceNoAuth IceNoAuth #define FIceNoVersion IceNoVersion #define FIceSetupFailed IceSetupFailed #define FIceAuthRejected IceAuthRejected #define FIceAuthFailed IceAuthFailed #define FIceProtocolDuplicate IceProtocolDuplicate #define FIceMajorOpcodeDuplicate IceMajorOpcodeDuplicate #define FIceUnknownProtocol IceUnknownProtocol /* SMlib.h */ #define FSmsRegisterClientProcMask SmsRegisterClientProcMask #define FSmsInteractRequestProcMask SmsInteractRequestProcMask #define FSmsInteractDoneProcMask SmsInteractDoneProcMask #define FSmsSaveYourselfRequestProcMask SmsSaveYourselfRequestProcMask #define FSmsSaveYourselfP2RequestProcMask SmsSaveYourselfP2RequestProcMask #define FSmsSaveYourselfDoneProcMask SmsSaveYourselfDoneProcMask #define FSmsCloseConnectionProcMask SmsCloseConnectionProcMask #define FSmsSetPropertiesProcMask SmsSetPropertiesProcMask #define FSmsDeletePropertiesProcMask SmsDeletePropertiesProcMask #define FSmsGetPropertiesProcMask SmsGetPropertiesProcMask #define FSmcSaveYourselfProcMask SmcSaveYourselfProcMask #define FSmcDieProcMask SmcDieProcMask #define FSmcSaveCompleteProcMask SmcSaveCompleteProcMask #define FSmcShutdownCancelledProcMask SmcShutdownCancelledProcMask /* ICEutil.h */ #define FIceAuthLockSuccess IceAuthLockSuccess #define FIceAuthLockError IceAuthLockError #define FIceAuthLockTimeout IceAuthLockTimeout #else /* !SessionSupport */ /* SM.h */ #define FSmProtoMajor 1 #define FSmProtoMinor 0 #define FSmInteractStyleNone 0 #define FSmInteractStyleErrors 1 #define FSmInteractStyleAny 2 #define FSmDialogError 0 #define FSmDialogNormal 1 #define FSmSaveGlobal 0 #define FSmSaveLocal 1 #define FSmSaveBoth 2 #define FSmRestartIfRunning 0 #define FSmRestartAnyway 1 #define FSmRestartImmediately 2 #define FSmRestartNever 3 #define FSmCloneCommand "CloneCommand" #define FSmCurrentDirectory "CurrentDirectory" #define FSmDiscardCommand "DiscardCommand" #define FSmEnvironment "Environment" #define FSmProcessID "ProcessID" #define FSmProgram "Program" #define FSmRestartCommand "RestartCommand" #define FSmResignCommand "ResignCommand" #define FSmRestartStyleHint "RestartStyleHint" #define FSmShutdownCommand "ShutdownCommand" #define FSmUserID "UserID" #define FSmCARD8 "CARD8" #define FSmARRAY8 "ARRAY8" #define FSmLISTofARRAY8 "LISTofARRAY8" #define FSM_Error 0 #define FSM_RegisterClient 1 #define FSM_RegisterClientReply 2 #define FSM_SaveYourself 3 #define FSM_SaveYourselfRequest 4 #define FSM_InteractRequest 5 #define FSM_Interact 6 #define FSM_InteractDone 7 #define FSM_SaveYourselfDone 8 #define FSM_Die 9 #define FSM_ShutdownCancelled 10 #define FSM_CloseConnection 11 #define FSM_SetProperties 12 #define FSM_DeleteProperties 13 #define FSM_GetProperties 14 #define FSM_PropertiesReply 15 #define FSM_SaveYourselfPhase2Request 16 #define FSM_SaveYourselfPhase2 17 #define FSM_SaveComplete 18 /* ICE.h */ #define FIceProtoMajor 1 #define FIceProtoMinor 0 #define FIceLSBfirst 0 #define FIceMSBfirst 1 #define FICE_Error 0 #define FICE_ByteOrder 1 #define FICE_ConnectionSetup 2 #define FICE_AuthRequired 3 #define FICE_AuthReply 4 #define FICE_AuthNextPhase 5 #define FICE_ConnectionReply 6 #define FICE_ProtocolSetup 7 #define FICE_ProtocolReply 8 #define FICE_Ping 9 #define FICE_PingReply 10 #define FICE_WantToClose 11 #define FICE_NoClose 12 #define FIceCanContinue 0 #define FIceFatalToProtocol 1 #define FIceFatalToConnection 2 #define FIceBadMinor 0x8000 #define FIceBadState 0x8001 #define FIceBadLength 0x8002 #define FIceBadValue 0x8003 #define FIceBadMajor 0 #define FIceNoAuth 1 #define FIceNoVersion 2 #define FIceSetupFailed 3 #define FIceAuthRejected 4 #define FIceAuthFailed 5 #define FIceProtocolDuplicate 6 #define FIceMajorOpcodeDuplicate 7 #define FIceUnknownProtocol 8 /* SMlib.h */ #define FSmsRegisterClientProcMask (1L << 0) #define FSmsInteractRequestProcMask (1L << 1) #define FSmsInteractDoneProcMask (1L << 2) #define FSmsSaveYourselfRequestProcMask (1L << 3) #define FSmsSaveYourselfP2RequestProcMask (1L << 4) #define FSmsSaveYourselfDoneProcMask (1L << 5) #define FSmsCloseConnectionProcMask (1L << 6) #define FSmsSetPropertiesProcMask (1L << 7) #define FSmsDeletePropertiesProcMask (1L << 8) #define FSmsGetPropertiesProcMask (1L << 9) #define FSmcSaveYourselfProcMask (1L << 0) #define FSmcDieProcMask (1L << 1) #define FSmcSaveCompleteProcMask (1L << 2) #define FSmcShutdownCancelledProcMask (1L << 3) /* ICEutil.h */ #define IceAuthLockSuccess 0 #define IceAuthLockError 1 #define IceAuthLockTimeout 2 #endif /* SessionSupport */ /* ---------------------------- type definitions --------------------------- */ #if SessionSupport /* ICElib.h */ typedef IcePointer FIcePointer; #define FIcePoAuthHaveReply IcePoAuthHaveReply #define FIcePoAuthRejected IcePoAuthRejected #define FIcePoAuthFailed IcePoAuthFailed #define FIcePoAuthDoneCleanup IcePoAuthDoneCleanup typedef IcePoAuthStatus FIcePoAuthStatus; #define FIcePaAuthContinue IcePaAuthContinue #define FIcePaAuthAccepted IcePaAuthAccepted #define FIcePaAuthRejected IcePaAuthRejected #define FIcePaAuthFailed IcePaAuthFailed typedef IcePaAuthStatus FIcePaAuthStatus; #define FIceConnectPending IceConnectPending #define FIceConnectAccepted IceConnectAccepted #define FIceConnectRejected IceConnectRejected #define FIceConnectIOError IceConnectIOError typedef IceConnectStatus FIceConnectStatus; #define FIceProtocolSetupSuccess IceProtocolSetupSuccess #define FIceProtocolSetupFailure IceProtocolSetupFailure #define FIceProtocolSetupIOError IceProtocolSetupIOError #define FIceProtocolAlreadyActive IceProtocolAlreadyActive typedef IceProtocolSetupStatus FIceProtocolSetupStatus; #define FIceAcceptSuccess IceAcceptSuccess #define FIceAcceptFailure IceAcceptFailure #define FIceAcceptBadMalloc IceAcceptBadMalloc typedef IceAcceptStatus FIceAcceptStatus; #define FIceClosedNow IceClosedNow #define FIceClosedASAP IceClosedASAP #define FIceConnectionInUse IceConnectionInUse #define FIceStartedShutdownNegotiation IceStartedShutdownNegotiation typedef IceCloseStatus FIceCloseStatus; #define FIceProcessMessagesSuccess IceProcessMessagesSuccess #define FIceProcessMessagesIOError IceProcessMessagesIOError #define FIceProcessMessagesConnectionClosed IceProcessMessagesConnectionClosed typedef IceProcessMessagesStatus FIceProcessMessagesStatus; typedef IceReplyWaitInfo FIceReplyWaitInfo; typedef IceConn FIceConn; typedef IceListenObj FIceListenObj; typedef IceWatchProc FIceWatchProc; typedef IcePoProcessMsgProc FIcePoProcessMsgProc; typedef IcePaProcessMsgProc FIcePaProcessMsgProc; typedef IcePoVersionRec FIcePoVersionRec; typedef IcePaVersionRec FIcePaVersionRec; typedef IcePoAuthProc FIcePoAuthProc; typedef IcePaAuthProc FIcePaAuthProc; typedef IceHostBasedAuthProc FIceHostBasedAuthProc; typedef IceProtocolSetupProc FIceProtocolSetupProc; typedef IceProtocolActivateProc FIceProtocolActivateProc; typedef IceIOErrorProc FIceIOErrorProc; typedef IcePingReplyProc FIcePingReplyProc; typedef IceErrorHandler FIceErrorHandler; typedef IceIOErrorHandler FIceIOErrorHandler; /* SMlib.h */ typedef SmPointer FSmPointer; typedef SmcConn FSmcConn; typedef SmsConn FSmsConn; typedef SmPropValue FSmPropValue; typedef SmProp FSmProp; #define FSmcClosedNow SmcClosedNow #define FSmcClosedASAP FSmcClosedASAP #define FSmcConnectionInUse FSmcConnectionInUse typedef SmcCloseStatus FSmcCloseStatus; typedef SmcSaveYourselfProc FSmcSaveYourselfProc; typedef SmcSaveYourselfPhase2Proc FSmcSaveYourselfPhase2Proc; typedef SmcInteractProc FSmcInteractProc; typedef SmcDieProc FSmcDieProc; typedef SmcShutdownCancelledProc FSmcShutdownCancelledProc; typedef SmcSaveCompleteProc FSmcSaveCompleteProc; typedef SmcPropReplyProc FSmcPropReplyProc; typedef SmcCallbacks FSmcCallbacks; typedef SmsRegisterClientProc FSmsRegisterClientProc; typedef SmsInteractRequestProc FSmsInteractRequestProc; typedef SmsInteractDoneProc FSmsInteractDoneProc; typedef SmsSaveYourselfRequestProc FSmsSaveYourselfRequestProc; typedef SmsSaveYourselfPhase2RequestProc FSmsSaveYourselfPhase2RequestProc; typedef SmsSaveYourselfDoneProc FSmsSaveYourselfDoneProc; typedef SmsCloseConnectionProc FSmsCloseConnectionProc; typedef SmsSetPropertiesProc FSmsSetPropertiesProc; typedef SmsDeletePropertiesProc FSmsDeletePropertiesProc; typedef SmsGetPropertiesProc FSmsGetPropertiesProc; typedef SmsCallbacks FSmsCallbacks; typedef SmsNewClientProc FSmsNewClientProc; typedef SmcErrorHandler FSmcErrorHandler; typedef SmsErrorHandler FSmsErrorHandler; /* ICEutil.h */ typedef IceAuthFileEntry FIceAuthFileEntry; typedef IceAuthDataEntry FIceAuthDataEntry; #else /* !SessionSupport */ #ifdef __STDC__ typedef void *FIcePointer; #else typedef char *FIcePointer; #endif /* ICElib.h */ typedef enum { FIcePoAuthHaveReply, FIcePoAuthRejected, FIcePoAuthFailed, FIcePoAuthDoneCleanup } FIcePoAuthStatus; typedef enum { FIcePaAuthContinue, FIcePaAuthAccepted, FIcePaAuthRejected, FIcePaAuthFailed } FIcePaAuthStatus; typedef enum { FIceConnectPending,FIceConnectAccepted,FIceConnectRejected,FIceConnectIOError } FIceConnectStatus; typedef enum { FIceProtocolSetupSuccess,FIceProtocolSetupFailure,FIceProtocolSetupIOError, FIceProtocolAlreadyActive } FIceProtocolSetupStatus; typedef enum { FIceAcceptSuccess,FIceAcceptFailure,FIceAcceptBadMalloc } FIceAcceptStatus; typedef enum { FIceClosedNow,FIceClosedASAP,FIceConnectionInUse, FIceStartedShutdownNegotiation } FIceCloseStatus; typedef enum { FIceProcessMessagesSuccess,FIceProcessMessagesIOError, FIceProcessMessagesConnectionClosed } FIceProcessMessagesStatus; typedef struct { unsigned long sequence_of_request; int major_opcode_of_request; int minor_opcode_of_request; FIcePointer reply; } FIceReplyWaitInfo; typedef void *FIceConn; typedef void *FIceListenObj; typedef void (*FIceWatchProc) ( #ifdef __STDC__ FIceConn, FIcePointer, Bool, FIcePointer * #endif ); typedef void (*FIcePoProcessMsgProc) ( #ifdef __STDC__ FIceConn, FIcePointer, int, unsigned long, Bool, FIceReplyWaitInfo *, Bool * #endif ); typedef void (*FIcePaProcessMsgProc) ( #ifdef __STDC__ FIceConn, FIcePointer, int, unsigned long, Bool #endif ); typedef struct { int major_version; int minor_version; FIcePoProcessMsgProc process_msg_proc; } FIcePoVersionRec; typedef struct { int major_version; int minor_version; FIcePaProcessMsgProc process_msg_proc; } FIcePaVersionRec; typedef FIcePoAuthStatus (*FIcePoAuthProc) ( #ifdef __STDC__ FIceConn, FIcePointer *, Bool, Bool, int, FIcePointer, int *, FIcePointer *, char ** #endif ); typedef FIcePaAuthStatus (*FIcePaAuthProc) ( #ifdef __STDC__ FIceConn, FIcePointer *, Bool, int, FIcePointer, int *, FIcePointer *, char ** #endif ); typedef Bool (*FIceHostBasedAuthProc) ( #ifdef __STDC__ char * #endif ); typedef Status (*FIceProtocolSetupProc) ( #ifdef __STDC__ FIceConn, int, int, char *, char *, FIcePointer *, char ** #endif ); typedef void (*FIceProtocolActivateProc) ( #ifdef __STDC__ FIceConn, FIcePointer #endif ); typedef void (*FIceIOErrorProc) ( #ifdef __STDC__ FIceConn #endif ); typedef void (*FIcePingReplyProc) ( #ifdef __STDC__ FIceConn, FIcePointer #endif ); typedef void (*FIceErrorHandler) ( #ifdef __STDC__ FIceConn, Bool, int, unsigned long, int, int, FIcePointer #endif ); typedef void (*FIceIOErrorHandler) ( #ifdef __STDC__ FIceConn /* iceConn */ #endif ); /* SMlib.h */ typedef FIcePointer FSmPointer; typedef void *FSmcConn; typedef void *FSmsConn; typedef struct { int length; FSmPointer value; } FSmPropValue; typedef struct { char *name; char *type; int num_vals; FSmPropValue *vals; } FSmProp; typedef enum { FSmcClosedNow, FSmcClosedASAP, FSmcConnectionInUse } FSmcCloseStatus; typedef void (*FSmcSaveYourselfProc) ( #ifdef __STDC__ FSmcConn, FSmPointer, int, Bool, int, Bool #endif ); typedef void (*FSmcSaveYourselfPhase2Proc) ( #ifdef __STDC__ FSmcConn, FSmPointer #endif ); typedef void (*FSmcInteractProc) ( #ifdef __STDC__ FSmcConn, FSmPointer #endif ); typedef void (*FSmcDieProc) ( #ifdef __STDC__ FSmcConn, FSmPointer #endif ); typedef void (*FSmcShutdownCancelledProc) ( #ifdef __STDC__ FSmcConn, FSmPointer #endif ); typedef void (*FSmcSaveCompleteProc) ( #ifdef __STDC__ FSmcConn, FSmPointer #endif ); typedef void (*FSmcPropReplyProc) ( #ifdef __STDC__ FSmcConn, FSmPointer, int, FSmProp ** #endif ); typedef struct { struct { FSmcSaveYourselfProc callback; FSmPointer client_data; } save_yourself; struct { FSmcDieProc callback; FSmPointer client_data; } die; struct { FSmcSaveCompleteProc callback; FSmPointer client_data; } save_complete; struct { FSmcShutdownCancelledProc callback; FSmPointer client_data; } shutdown_cancelled; } FSmcCallbacks; typedef Status (*FSmsRegisterClientProc) ( #ifdef __STDC__ FSmsConn, FSmPointer, char * #endif ); typedef void (*FSmsInteractRequestProc) ( #ifdef __STDC__ FSmsConn, FSmPointer, int #endif ); typedef void (*FSmsInteractDoneProc) ( #ifdef __STDC__ FSmsConn, FSmPointer, Bool #endif ); typedef void (*FSmsSaveYourselfRequestProc) ( #ifdef __STDC__ FSmsConn, FSmPointer, int, Bool, int, Bool, Bool #endif ); typedef void (*FSmsSaveYourselfPhase2RequestProc) ( #ifdef __STDC__ FSmsConn, FSmPointer #endif ); typedef void (*FSmsSaveYourselfDoneProc) ( #ifdef __STDC__ FSmsConn, FSmPointer, Bool #endif ); typedef void (*FSmsCloseConnectionProc) ( #ifdef __STDC__ FSmsConn, FSmPointer, int, char ** #endif ); typedef void (*FSmsSetPropertiesProc) ( #ifdef __STDC__ FSmsConn, FSmPointer, int, FSmProp ** #endif ); typedef void (*FSmsDeletePropertiesProc) ( #ifdef __STDC__ FSmsConn, FSmPointer, int, char ** #endif ); typedef void (*FSmsGetPropertiesProc) ( #ifdef __STDC__ FSmsConn, FSmPointer #endif ); typedef struct { struct { FSmsRegisterClientProc callback; FSmPointer manager_data; } register_client; struct { FSmsInteractRequestProc callback; FSmPointer manager_data; } interact_request; struct { FSmsInteractDoneProc callback; FSmPointer manager_data; } interact_done; struct { FSmsSaveYourselfRequestProc callback; FSmPointer manager_data; } save_yourself_request; struct { FSmsSaveYourselfPhase2RequestProc callback; FSmPointer manager_data; } save_yourself_phase2_request; struct { FSmsSaveYourselfDoneProc callback; FSmPointer manager_data; } save_yourself_done; struct { FSmsCloseConnectionProc callback; FSmPointer manager_data; } close_connection; struct { FSmsSetPropertiesProc callback; FSmPointer manager_data; } set_properties; struct { FSmsDeletePropertiesProc callback; FSmPointer manager_data; } delete_properties; struct { FSmsGetPropertiesProc callback; FSmPointer manager_data; } get_properties; } FSmsCallbacks; typedef Status (*FSmsNewClientProc) ( #ifdef __STDC__ FSmsConn,FSmPointer, unsigned long *, FSmsCallbacks *, char ** #endif ); typedef void (*FSmcErrorHandler) ( #ifdef __STDC__ FSmcConn, Bool, int, unsigned long, int, int, FSmPointer #endif ); typedef void (*FSmsErrorHandler) ( #ifdef __STDC__ FSmsConn, Bool, int, unsigned long, int, int, FSmPointer #endif ); /* ICEutil.h */ typedef struct { char *protocol_name; unsigned short protocol_data_length; char *protocol_data; char *network_id; char *auth_name; unsigned short auth_data_length; char *auth_data; } FIceAuthFileEntry; typedef struct { char *protocol_name; char *network_id; char *auth_name; unsigned short auth_data_length; char *auth_data; } FIceAuthDataEntry; #endif /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ #if SessionSupport /* ICElib.h (no all) */ #define FIceSetIOErrorHandler(a) IceSetIOErrorHandler(a) #define FIceFreeListenObjs(a,b) IceFreeListenObjs(a,b) #define FIceConnectionNumber(a) IceConnectionNumber(a) #define FIceSetShutdownNegotiation(a,b) IceSetShutdownNegotiation(a,b) #define FIceCloseConnection(a) IceCloseConnection(a) #define FIceConnectionStatus(a) IceConnectionStatus(a) #define FIceAcceptConnection(a,b) IceAcceptConnection(a,b) #define FIceProcessMessages(a,b,c) IceProcessMessages(a,b,c) #define FIceListenForConnections(a,b,c,d) IceListenForConnections(a,b,c,d) #define FIceAddConnectionWatch(a,b) IceAddConnectionWatch(a,b) #define FIceGetListenConnectionNumber(a) IceGetListenConnectionNumber(a) #define FIceComposeNetworkIdList(a,b) IceComposeNetworkIdList(a,b) #define FIceGetListenConnectionString(a) IceGetListenConnectionString(a) #define FIceSetHostBasedAuthProc(a,b) IceSetHostBasedAuthProc(a,b) #define FIceConnectionString(a) IceConnectionString(a) /* SMlib.h */ #define FSmcOpenConnection(a,b,c,d,e,f,g,h,i,k) \ SmcOpenConnection(a,b,c,d,e,f,g,h,i,k) #define FSmcCloseConnection(a,b,c) SmcCloseConnection(a,b,c) #define FSmcModifyCallbacks(a,b,c) SmcModifyCallbacks(a,b,c) #define FSmcSetProperties(a,b,c) SmcSetProperties(a,b,c) #define FSmcDeleteProperties(a,b,c) SmcDeleteProperties(a,b,c) #define FSmcGetProperties(a,b,c) SmcGetProperties(a,b,c) #define FSmcInteractRequest(a,b,c,d) SmcInteractRequest(a,b,c,d) #define FSmcInteractDone(a,b) SmcInteractDone(a,b) #define FSmcRequestSaveYourself(a,b,c,d,e,f) SmcRequestSaveYourself(a,b,c,d,e,f) #define FSmcRequestSaveYourselfPhase2(a,b,c) SmcRequestSaveYourselfPhase2(a,b,c) #define FSmcSaveYourselfDone(a,b) SmcSaveYourselfDone(a,b) #define FSmcProtocolVersion(a) SmcProtocolVersion(a) #define FSmcProtocolRevision(a) SmcProtocolRevision(a) #define FSmcVendor(a) SmcVendor(a) #define FSmcRelease(a) SmcRelease(a) #define FSmcClientID(a) SmcClientID(a) #define FSmcGetIceConnection(a) SmcGetIceConnection(a) #define FSmsInitialize(a,b,c,d,e,f,g) SmsInitialize(a,b,c,d,e,f,g) #define FSmsClientHostName(a) SmsClientHostName(a) #define FSmsGenerateClientID(a) SmsGenerateClientID(a) #define FSmsRegisterClientReply(a,b) SmsRegisterClientReply(a,b) #define FSmsSaveYourself(a,b,c,d,e) SmsSaveYourself(a,b,c,d,e) #define FSmsSaveYourselfPhase2(a) SmsSaveYourselfPhase2(a) #define FSmsInteract(a) SmsInteract(a) #define FSmsDie(a) SmsDie(a) #define FSmsSaveComplete(a) SmsSaveComplete(a) #define FSmsShutdownCancelled(a) SmsShutdownCancelled(a) #define FSmsReturnProperties(a,b,c) SmsReturnProperties(a,b,c) #define FSmsCleanUp(a) SmsCleanUp(a) #define FSmsProtocolVersion(a) SmsProtocolVersion(a) #define FSmsProtocolRevision(a) SmsProtocolRevision(a) #define FSmsClientID(a) SmsClientID(a) #define FSmsGetIceConnection(a) SmsGetIceConnection(a) #define FSmcSetErrorHandler(a) SmcSetErrorHandler(a) #define FSmsSetErrorHandler(a) SmsSetErrorHandler(a) #define FSmFreeProperty(a) SmFreeProperty(a) #define FSmFreeReasons(a,b) SmFreeReasons(a,b) /* ICEutils.h */ #define FIceAuthFileName(a) IceAuthFileName(a) #define FIceLockAuthFile(a,b,c,d) IceLockAuthFile(a,b,c,d) #define FIceUnlockAuthFile(a) IceUnlockAuthFile(a) #define FIceReadAuthFileEntry(a) IceReadAuthFileEntry(a) #define FIceFreeAuthFileEntry(a) IceFreeAuthFileEntry(a) #define FIceWriteAuthFileEntry(a,b) IceWriteAuthFileEntry(a,b) #define FIceGetAuthFileEntry(a,b,c) IceGetAuthFileEntry(a,b,c) #define FIceGenerateMagicCookie(a) IceGenerateMagicCookie(a) #define FIceSetPaAuthData(a,b) IceSetPaAuthData(a,b) #else /* ICElib.h (no all) */ #define FIceSetIOErrorHandler(a) NULL #define FIceFreeListenObjs(a,b) #define FIceConnectionNumber(a) 0 #define FIceSetShutdownNegotiation(a,b) #define FIceCloseConnection(a) 0 #define FIceConnectionStatus(a) 0 #define FIceAcceptConnection(a,b) NULL #define FIceProcessMessages(a,b,c) 0 #define FIceListenForConnections(a,b,c,d) 0 #define FIceAddConnectionWatch(a,b) 0 #define FIceGetListenConnectionNumber(a) 0 #define FIceComposeNetworkIdList(a,b) NULL #define FIceGetListenConnectionString(a) NULL #define FIceSetHostBasedAuthProc(a,b) #define FIceConnectionString(a) NULL /* SMlib.h */ #define FSmcOpenConnection(a,b,c,d,e,f,g,h,i,k) NULL #define FSmcCloseConnection(a,b,c) 0 #define FSmcModifyCallbacks(a,b,c) #define FSmcSetProperties(a,b,c) #define FSmcDeleteProperties(a,b,c) #define FSmcGetProperties(a,b,c) 0 #define FSmcInteractRequest(a,b,c,d) 0 #define FSmcInteractDone(a,b) #define FSmcRequestSaveYourself(a,b,c,d,e,f) #define FSmcRequestSaveYourselfPhase2(a,b,c) 0 #define FSmcSaveYourselfDone(a,b) #define FSmcProtocolVersion(a) 0 #define FSmcProtocolRevision(a) 0 #define FSmcVendor(a) NULL #define FSmcRelease(a) NULL #define FSmcClientID(a) NULL #define FSmcGetIceConnection(a) NULL #define FSmsInitialize(a,b,c,d,e,f,g) 0 #define FSmsClientHostName(a) NULL #define FSmsGenerateClientID(a) NULL #define FSmsRegisterClientReply(a,b) 0 #define FSmsSaveYourself(a,b,c,d,e) #define FSmsSaveYourselfPhase2(a) #define FSmsInteract(a) #define FSmsDie(a) #define FSmsSaveComplete(a) #define FSmsShutdownCancelled(a) #define FSmsReturnProperties(a,b,c) #define FSmsCleanUp(a) #define FSmsProtocolVersion(a) 0 #define FSmsProtocolRevision(a) 0 #define FSmsClientID(a) NULL #define FSmsGetIceConnection(a) NULL #define FSmcSetErrorHandler(a) NULL #define FSmsSetErrorHandler(a) NULL #define FSmFreeProperty(a) #define FSmFreeReasons(a,b) /* ICEutils.h */ #define FIceAuthFileName(a) NULL #define FIceLockAuthFile(a,b,c,d) 0 #define FIceUnlockAuthFile(a) #define FIceReadAuthFileEntry(a) NULL #define FIceFreeAuthFileEntry(a) #define FIceWriteAuthFileEntry(a,b) 0 #define FIceGetAuthFileEntry(a,b,c) NULL #define FIceGenerateMagicCookie(a) NULL #define FIceSetPaAuthData(a,b) #endif #endif /* FSMlib_H */ fvwm-2.7.0/libs/gravity.h0000644000175000017500000000520214147024700012205 00000000000000/* -*-c-*- */ #ifndef GRAVITY_H #define GRAVITY_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ typedef enum { DIR_NONE = -1, DIR_N = 0, DIR_E = 1, DIR_S = 2, DIR_W = 3, DIR_MAJOR_MASK = 3, DIR_NE = 4, DIR_SE = 5, DIR_SW = 6, DIR_NW = 7, DIR_MINOR_MASK = 7, DIR_MASK = 7, DIR_C = 8, DIR_ALL_MASK = 8 } direction_t; typedef enum { MULTI_DIR_NONE = 0, MULTI_DIR_FIRST = (1 << DIR_N), MULTI_DIR_N = (1 << DIR_N), MULTI_DIR_E = (1 << DIR_E), MULTI_DIR_S = (1 << DIR_S), MULTI_DIR_W = (1 << DIR_W), MULTI_DIR_NE = (1 << DIR_NE), MULTI_DIR_SE = (1 << DIR_SE), MULTI_DIR_SW = (1 << DIR_SW), MULTI_DIR_NW = (1 << DIR_NW), MULTI_DIR_ALL = ((1 << (DIR_MASK + 1)) - 1), MULTI_DIR_C = (1 << DIR_C), MULTI_DIR_LAST = (1 << DIR_ALL_MASK) } multi_direction_t; typedef enum { ROTATION_0 = 0, ROTATION_90 = 1, ROTATION_180 = 2, ROTATION_270 = 3, ROTATION_MASK = 3 } rotation_t; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ void gravity_get_offsets(int grav, int *xp,int *yp); void gravity_move(int gravity, rectangle *rect, int xdiff, int ydiff); void gravity_resize(int gravity, rectangle *rect, int wdiff, int hdiff); void gravity_move_resize_parent_child( int child_gravity, rectangle *parent_diff_r, rectangle *child_r); direction_t gravity_grav_to_dir( int grav); int gravity_dir_to_grav( direction_t dir); int gravity_combine_xy_grav( int grav_x, int grav_y); void gravity_split_xy_grav( int *ret_grav_x, int *ret_grav_y, int in_grav); int gravity_combine_xy_dir( int dir_x, int dir_y); void gravity_split_xy_dir( int *ret_dir_x, int *ret_dir_y, int in_dir); int gravity_override_dir( int dir_orig, int dir_mod); int gravity_dir_to_sign_one_axis( direction_t dir); direction_t gravity_parse_dir_argument( char *action, char **ret_action, direction_t default_ret); char *gravity_dir_to_string(direction_t dir, char *default_str); multi_direction_t gravity_parse_multi_dir_argument( char *action, char **ret_action); void gravity_get_next_multi_dir(int dir_set, multi_direction_t *dir); direction_t gravity_multi_dir_to_dir(multi_direction_t mdir); void gravity_rotate_xy(rotation_t rot, int x, int y, int *ret_x, int *ret_y); rotation_t gravity_add_rotations(rotation_t rot1, rotation_t rot2); #endif /* GRAVITY_H */ fvwm-2.7.0/libs/PictureDitherMatrice.h0000644000175000017500000017553514147024676014635 00000000000000/* -*-c-*- */ #ifndef Picture_Dither_Matrice_H #define Picture_Dither_Matrice_H /* This dither table was generated by Raph Levien using patented * technology (US Patent 5,276,535). The dither table itself is in the * public domain. */ #define DM_WIDTH 128 #define DM_WIDTH_SHIFT 7 #define DM_HEIGHT 128 #define DITHER_MATRICE \ { \ { 0, 41, 23, 5, 17, 39, 7, 15, 62, 23, 40, 51, 31, 47, 9, 32, 52, 27, 57, 25, 6, 61, 27, 52, 37, 7, 40, 63, 18, 36, 10, 42, 25, 62, 45, 34, 20, 42, 37, 14, 35, 29, 50, 10, 61, 2, 40, 8, 37, 12, 58, 22, 5, 41, 10, 39, 0, 60, 11, 46, 2, 55, 38, 17, 36, 59, 13, 54, 37, 56, 8, 29, 16, 13, 63, 22, 41, 55, 7, 20, 49, 14, 23, 55, 37, 23, 19, 36, 15, 49, 23, 63, 30, 14, 38, 27, 53, 13, 22, 41, 19, 31, 7, 19, 50, 30, 49, 16, 3, 32, 56, 40, 29, 34, 8, 48, 19, 45, 4, 51, 12, 46, 35, 49, 16, 42, 12, 62 },\ { 30, 57, 36, 54, 47, 34, 52, 27, 43, 4, 28, 7, 17, 36, 62, 13, 44, 7, 18, 48, 33, 21, 44, 14, 30, 47, 12, 33, 5, 55, 31, 58, 13, 30, 4, 17, 52, 10, 60, 26, 46, 0, 39, 27, 42, 22, 47, 25, 60, 32, 9, 38, 48, 17, 59, 30, 49, 18, 34, 25, 51, 19, 5, 48, 21, 8, 28, 46, 1, 32, 41, 19, 54, 47, 37, 18, 28, 11, 44, 30, 39, 56, 2, 33, 8, 42, 61, 28, 58, 8, 46, 9, 41, 4, 58, 7, 21, 48, 59, 10, 52, 14, 42, 57, 12, 25, 7, 53, 42, 24, 11, 50, 17, 59, 42, 2, 36, 60, 32, 17, 63, 29, 21, 7, 59, 32, 24, 39 },\ { 22, 8, 16, 32, 3, 25, 13, 57, 18, 45, 58, 39, 55, 20, 5, 42, 23, 34, 63, 1, 51, 10, 58, 4, 60, 23, 53, 27, 44, 21, 3, 48, 8, 50, 43, 54, 27, 32, 5, 55, 21, 58, 12, 53, 6, 36, 14, 50, 17, 29, 53, 15, 24, 52, 7, 36, 13, 42, 4, 53, 9, 35, 61, 26, 56, 32, 49, 15, 62, 23, 6, 60, 2, 31, 4, 48, 58, 38, 15, 61, 5, 25, 47, 28, 50, 15, 7, 40, 3, 32, 33, 52, 25, 50, 35, 42, 61, 3, 28, 36, 23, 63, 4, 33, 46, 62, 36, 23, 60, 6, 54, 28, 4, 37, 23, 55, 25, 8, 42, 54, 14, 6, 56, 38, 19, 52, 4, 46 },\ { 48, 53, 43, 12, 45, 63, 30, 37, 9, 34, 21, 1, 25, 47, 29, 58, 3, 54, 15, 39, 29, 17, 38, 35, 20, 43, 1, 49, 15, 59, 29, 39, 22, 35, 16, 23, 1, 47, 39, 18, 8, 44, 25, 31, 57, 19, 63, 4, 45, 3, 42, 61, 1, 31, 45, 20, 57, 29, 62, 21, 32, 41, 14, 44, 3, 39, 5, 34, 10, 43, 51, 35, 23, 52, 40, 10, 21, 1, 53, 18, 51, 43, 12, 62, 18, 54, 26, 51, 20, 57, 14, 1, 62, 16, 11, 18, 32, 39, 17, 44, 1, 48, 26, 37, 18, 2, 51, 14, 28, 45, 35, 18, 57, 13, 47, 11, 51, 20, 2, 39, 31, 47, 25, 1, 50, 11, 60, 7 },\ { 18, 28, 1, 56, 21, 10, 51, 2, 46, 54, 14, 61, 11, 50, 13, 38, 19, 31, 45, 9, 55, 24, 47, 5, 54, 9, 62, 11, 35, 8, 51, 14, 57, 6, 63, 40, 58, 14, 51, 28, 62, 34, 15, 48, 1, 41, 30, 35, 55, 21, 34, 11, 49, 37, 8, 52, 4, 23, 15, 43, 1, 58, 11, 23, 53, 16, 55, 26, 58, 18, 27, 12, 45, 14, 25, 63, 42, 33, 27, 35, 9, 31, 21, 38, 1, 44, 34, 12, 48, 38, 21, 44, 29, 47, 26, 53, 1, 46, 54, 8, 59, 29, 11, 55, 22, 41, 33, 20, 39, 1, 48, 9, 44, 32, 5, 62, 29, 44, 57, 23, 10, 58, 34, 43, 15, 37, 26, 33 }, \ { 51, 38, 59, 24, 35, 42, 19, 60, 5, 32, 41, 26, 43, 33, 7, 53, 48, 11, 59, 23, 42, 2, 61, 30, 16, 40, 32, 24, 56, 41, 19, 33, 37, 26, 47, 9, 31, 22, 2, 45, 9, 54, 4, 37, 21, 52, 11, 23, 7, 57, 16, 25, 55, 18, 63, 27, 46, 39, 56, 10, 50, 37, 29, 47, 19, 63, 24, 9, 46, 2, 39, 60, 9, 57, 30, 7, 49, 11, 59, 3, 45, 57, 5, 60, 29, 22, 5, 60, 30, 9, 59, 18, 40, 6, 57, 36, 30, 12, 24, 34, 15, 40, 52, 6, 49, 9, 58, 4, 63, 12, 26, 61, 22, 53, 38, 16, 35, 14, 28, 50, 42, 17, 5, 28, 62, 20, 54, 12 }, \ { 26, 6, 31, 15, 49, 6, 38, 27, 22, 49, 16, 56, 2, 62, 30, 21, 0, 36, 28, 6, 49, 32, 13, 52, 26, 50, 19, 46, 3, 26, 62, 0, 53, 12, 29, 3, 53, 41, 60, 24, 38, 13, 58, 16, 43, 9, 59, 39, 46, 28, 44, 40, 2, 33, 13, 41, 16, 6, 47, 31, 26, 17, 57, 6, 38, 0, 42, 36, 29, 52, 20, 31, 48, 0, 34, 56, 20, 36, 23, 54, 14, 41, 24, 37, 10, 55, 46, 25, 16, 45, 36, 4, 55, 23, 15, 8, 50, 62, 5, 56, 44, 20, 13, 28, 59, 31, 24, 47, 31, 52, 37, 17, 40, 0, 26, 49, 3, 60, 7, 33, 0, 61, 53, 40, 8, 45, 2, 41 }, \ { 16, 63, 43, 4, 61, 24, 56, 13, 53, 8, 36, 12, 24, 41, 16, 46, 60, 26, 52, 39, 14, 57, 21, 37, 0, 45, 7, 59, 38, 17, 43, 10, 45, 20, 61, 43, 19, 11, 33, 17, 50, 32, 23, 61, 28, 49, 26, 0, 18, 51, 5, 60, 22, 58, 29, 0, 59, 34, 19, 62, 3, 52, 7, 44, 30, 59, 13, 50, 15, 62, 7, 17, 38, 22, 44, 15, 40, 4, 47, 28, 33, 17, 49, 16, 51, 40, 10, 56, 0, 53, 13, 49, 28, 38, 60, 21, 43, 19, 37, 27, 3, 51, 34, 39, 0, 45, 15, 43, 10, 21, 3, 55, 8, 33, 59, 10, 41, 18, 52, 24, 46, 20, 30, 13, 58, 22, 36, 57 }, \ { 50, 34, 11, 47, 29, 17, 44, 0, 33, 63, 28, 46, 52, 5, 57, 10, 42, 18, 4, 63, 20, 8, 44, 10, 56, 34, 14, 29, 5, 54, 23, 59, 32, 49, 7, 34, 49, 27, 56, 0, 42, 7, 46, 3, 40, 6, 54, 32, 62, 13, 36, 10, 47, 8, 35, 49, 24, 51, 12, 40, 22, 35, 60, 12, 22, 51, 33, 4, 40, 25, 43, 55, 5, 54, 12, 61, 26, 51, 8, 62, 0, 53, 7, 63, 2, 32, 19, 34, 42, 24, 31, 63, 2, 10, 45, 33, 0, 48, 9, 61, 22, 47, 8, 62, 18, 56, 7, 54, 27, 57, 46, 30, 50, 19, 45, 30, 56, 36, 22, 47, 11, 38, 3, 51, 32, 48, 18, 9 }, \ { 0, 21, 40, 19, 52, 9, 37, 48, 20, 40, 3, 18, 27, 38, 35, 22, 31, 56, 13, 35, 46, 28, 60, 40, 27, 18, 61, 50, 41, 30, 7, 36, 2, 25, 16, 57, 5, 15, 47, 29, 55, 19, 30, 52, 15, 34, 20, 12, 43, 30, 20, 54, 25, 44, 53, 12, 38, 5, 55, 27, 48, 15, 33, 27, 45, 8, 19, 28, 56, 11, 33, 49, 18, 36, 29, 2, 45, 16, 39, 19, 31, 43, 27, 35, 20, 52, 26, 6, 61, 11, 41, 17, 29, 51, 20, 56, 25, 32, 41, 17, 53, 31, 25, 14, 42, 23, 35, 16, 38, 6, 34, 12, 15, 62, 6, 21, 13, 1, 63, 9, 55, 27, 43, 25, 14, 4, 31, 55 }, \ { 44, 29, 61, 2, 35, 58, 26, 15, 60, 10, 51, 59, 14, 55, 8, 50, 2, 44, 25, 51, 1, 33, 16, 4, 48, 36, 2, 21, 12, 57, 48, 13, 51, 55, 40, 28, 37, 62, 8, 39, 12, 63, 36, 10, 59, 24, 56, 47, 9, 50, 41, 1, 32, 17, 6, 21, 61, 30, 9, 43, 1, 54, 41, 2, 54, 37, 48, 61, 1, 46, 21, 3, 58, 24, 50, 32, 60, 10, 57, 25, 46, 12, 59, 4, 45, 13, 57, 47, 27, 39, 5, 58, 47, 14, 35, 4, 52, 13, 60, 6, 36, 10, 45, 55, 4, 50, 29, 2, 61, 50, 25, 58, 44, 24, 36, 42, 54, 28, 40, 32, 16, 56, 6, 62, 46, 39, 60, 23 }, \ { 7, 48, 14, 54, 23, 40, 4, 45, 30, 22, 42, 32, 1, 44, 20, 29, 58, 8, 37, 19, 41, 54, 24, 58, 9, 53, 25, 46, 34, 16, 23, 38, 27, 11, 18, 1, 52, 21, 35, 22, 48, 5, 25, 45, 18, 38, 2, 27, 35, 4, 57, 15, 62, 39, 57, 28, 42, 16, 36, 60, 24, 18, 10, 63, 20, 5, 16, 23, 37, 14, 59, 27, 41, 8, 13, 42, 21, 35, 6, 50, 3, 38, 15, 48, 30, 39, 17, 3, 49, 14, 53, 33, 24, 7, 61, 44, 11, 39, 23, 49, 19, 58, 1, 32, 36, 12, 60, 41, 20, 13, 41, 4, 39, 1, 48, 8, 18, 51, 14, 44, 5, 37, 21, 34, 1, 26, 10, 37 }, \ { 53, 36, 27, 9, 50, 12, 32, 55, 2, 57, 7, 17, 48, 34, 63, 15, 40, 26, 62, 11, 49, 6, 31, 39, 22, 42, 6, 63, 1, 39, 60, 4, 42, 61, 32, 45, 24, 44, 2, 60, 16, 41, 53, 1, 33, 61, 49, 17, 63, 23, 45, 26, 33, 3, 23, 46, 2, 50, 20, 4, 45, 34, 49, 30, 39, 58, 44, 31, 53, 34, 6, 52, 30, 47, 63, 1, 53, 22, 42, 31, 58, 23, 54, 22, 61, 8, 36, 59, 22, 35, 21, 1, 55, 40, 27, 16, 30, 54, 2, 29, 43, 16, 39, 63, 21, 46, 26, 10, 48, 32, 19, 53, 30, 56, 26, 60, 33, 4, 61, 23, 49, 59, 15, 53, 19, 58, 42, 16 }, \ { 20, 5, 59, 46, 25, 62, 7, 19, 43, 25, 37, 61, 11, 24, 4, 54, 12, 52, 3, 32, 17, 61, 12, 47, 15, 55, 18, 31, 53, 28, 9, 50, 21, 6, 55, 9, 58, 14, 54, 26, 33, 7, 31, 58, 13, 21, 8, 42, 29, 6, 37, 11, 48, 52, 14, 60, 11, 39, 56, 32, 14, 58, 7, 26, 17, 4, 42, 8, 11, 47, 19, 38, 10, 17, 26, 37, 9, 55, 28, 13, 18, 40, 6, 33, 1, 43, 25, 11, 51, 7, 62, 43, 18, 37, 3, 57, 45, 9, 38, 58, 5, 52, 27, 7, 17, 53, 5, 57, 37, 2, 63, 9, 22, 15, 11, 38, 25, 45, 35, 0, 28, 10, 41, 30, 50, 8, 31, 57 }, \ { 49, 33, 16, 38, 1, 42, 51, 34, 53, 14, 28, 49, 30, 56, 36, 23, 43, 20, 38, 56, 22, 45, 28, 0, 62, 35, 26, 44, 11, 19, 52, 35, 44, 15, 30, 38, 10, 31, 40, 4, 46, 50, 20, 40, 27, 44, 51, 14, 56, 53, 19, 59, 7, 29, 41, 19, 35, 25, 8, 52, 22, 44, 13, 53, 50, 32, 61, 24, 56, 25, 63, 0, 45, 57, 33, 59, 16, 46, 4, 62, 50, 11, 60, 37, 52, 19, 55, 29, 37, 46, 13, 26, 48, 10, 50, 34, 21, 63, 26, 13, 42, 33, 22, 55, 35, 28, 43, 15, 24, 51, 27, 34, 46, 49, 58, 3, 52, 9, 57, 19, 48, 55, 3, 35, 12, 45, 24, 3 }, \ { 41, 11, 56, 28, 18, 31, 22, 10, 37, 6, 47, 13, 3, 41, 9, 46, 0, 48, 29, 6, 34, 10, 55, 37, 20, 8, 49, 3, 41, 59, 14, 25, 0, 63, 19, 47, 27, 51, 17, 57, 23, 10, 61, 6, 54, 3, 38, 31, 0, 22, 34, 43, 20, 55, 31, 0, 49, 63, 29, 38, 3, 62, 28, 40, 0, 22, 14, 35, 2, 48, 15, 43, 23, 14, 3, 29, 49, 20, 39, 34, 0, 44, 29, 9, 15, 47, 5, 42, 0, 31, 58, 5, 31, 61, 23, 15, 0, 47, 19, 50, 24, 3, 59, 11, 44, 0, 31, 59, 6, 42, 17, 60, 0, 39, 20, 31, 43, 17, 29, 40, 12, 25, 60, 22, 52, 15, 63, 29 }, \ { 20, 52, 8, 44, 62, 4, 59, 49, 17, 63, 21, 39, 60, 18, 52, 27, 33, 59, 14, 51, 59, 43, 24, 5, 51, 30, 57, 17, 32, 5, 37, 56, 48, 34, 42, 3, 60, 5, 36, 13, 43, 37, 18, 34, 25, 12, 59, 24, 47, 36, 11, 50, 3, 38, 9, 58, 16, 5, 43, 18, 47, 10, 37, 18, 59, 46, 29, 52, 40, 12, 34, 28, 56, 36, 53, 7, 43, 8, 24, 52, 26, 17, 56, 43, 24, 32, 63, 20, 57, 16, 22, 52, 36, 8, 41, 56, 29, 32, 54, 7, 35, 57, 14, 48, 20, 62, 13, 39, 53, 29, 8, 45, 13, 29, 7, 61, 14, 54, 6, 63, 38, 32, 18, 43, 2, 39, 6, 47 }, \ { 0, 58, 23, 35, 13, 46, 12, 39, 0, 31, 55, 24, 5, 35, 15, 61, 17, 5, 39, 25, 18, 2, 50, 33, 41, 13, 39, 23, 62, 46, 29, 12, 22, 8, 56, 25, 20, 49, 32, 62, 0, 56, 11, 46, 63, 42, 9, 16, 55, 5, 60, 15, 62, 26, 45, 21, 36, 51, 13, 57, 31, 24, 55, 6, 35, 9, 57, 5, 20, 60, 7, 51, 5, 19, 40, 25, 61, 32, 56, 12, 36, 48, 21, 2, 58, 12, 39, 28, 9, 50, 40, 12, 44, 18, 25, 49, 6, 38, 11, 62, 18, 46, 30, 9, 40, 25, 49, 19, 10, 36, 55, 22, 33, 52, 41, 18, 37, 27, 49, 21, 2, 46, 7, 53, 33, 61, 27, 35 }, \ { 41, 31, 5, 39, 51, 26, 33, 57, 27, 41, 9, 44, 54, 29, 48, 7, 44, 36, 57, 10, 31, 63, 16, 45, 11, 60, 1, 47, 7, 20, 43, 3, 58, 36, 13, 52, 39, 7, 15, 28, 22, 48, 30, 21, 1, 29, 49, 44, 27, 17, 40, 30, 24, 42, 12, 53, 33, 7, 47, 20, 1, 42, 11, 49, 25, 43, 17, 32, 45, 27, 41, 21, 31, 62, 11, 49, 2, 15, 42, 5, 63, 7, 41, 27, 49, 6, 54, 23, 46, 34, 2, 28, 54, 3, 59, 12, 46, 17, 42, 28, 40, 1, 37, 51, 5, 55, 2, 34, 47, 16, 3, 62, 47, 5, 23, 56, 1, 44, 12, 34, 51, 16, 57, 11, 25, 17, 54, 13 }, \ { 60, 26, 55, 18, 3, 60, 20, 6, 52, 15, 50, 19, 32, 11, 23, 53, 26, 21, 1, 47, 42, 27, 8, 58, 21, 27, 53, 36, 26, 54, 31, 50, 17, 30, 45, 1, 29, 59, 44, 53, 41, 4, 35, 58, 51, 19, 32, 4, 52, 34, 48, 8, 51, 5, 56, 2, 25, 61, 27, 38, 54, 27, 62, 21, 51, 1, 39, 62, 10, 50, 1, 58, 13, 47, 38, 18, 35, 54, 22, 51, 30, 19, 59, 34, 14, 32, 44, 4, 60, 15, 52, 62, 20, 43, 30, 35, 21, 60, 4, 52, 12, 24, 61, 18, 30, 42, 23, 61, 25, 50, 27, 38, 11, 59, 12, 35, 50, 30, 59, 24, 8, 42, 28, 37, 48, 9, 44, 21 }, \ { 10, 47, 15, 50, 30, 43, 8, 45, 29, 2, 36, 59, 1, 58, 41, 3, 63, 31, 54, 20, 13, 55, 35, 38, 4, 44, 15, 9, 61, 2, 14, 38, 61, 10, 23, 54, 18, 12, 24, 2, 14, 55, 16, 8, 38, 14, 41, 60, 10, 23, 1, 58, 32, 17, 28, 37, 41, 15, 3, 60, 15, 33, 4, 36, 16, 59, 28, 14, 23, 55, 37, 18, 44, 28, 2, 57, 30, 10, 27, 46, 14, 38, 3, 53, 21, 61, 17, 35, 10, 41, 26, 7, 33, 9, 57, 1, 53, 37, 26, 20, 56, 48, 9, 33, 58, 16, 37, 7, 45, 1, 57, 15, 32, 26, 42, 23, 7, 20, 4, 54, 31, 62, 22, 1, 59, 30, 4, 51 }, \ { 36, 2, 38, 11, 24, 36, 54, 22, 62, 47, 25, 8, 28, 45, 16, 38, 12, 43, 9, 37, 49, 3, 23, 52, 18, 30, 50, 33, 19, 42, 49, 26, 6, 40, 47, 35, 63, 38, 50, 33, 60, 26, 36, 47, 24, 57, 6, 26, 39, 63, 19, 44, 14, 46, 61, 9, 50, 30, 45, 23, 10, 50, 44, 8, 31, 54, 6, 46, 36, 4, 30, 54, 8, 52, 22, 41, 4, 60, 40, 0, 58, 24, 45, 10, 37, 1, 48, 30, 56, 17, 38, 48, 24, 47, 19, 39, 14, 8, 45, 32, 2, 34, 27, 44, 4, 52, 11, 56, 31, 21, 40, 19, 44, 51, 2, 63, 46, 58, 36, 43, 14, 5, 50, 38, 14, 56, 40, 23 }, \ { 61, 46, 32, 63, 54, 1, 14, 34, 12, 40, 18, 49, 37, 10, 61, 30, 51, 24, 60, 7, 29, 40, 62, 11, 46, 58, 6, 56, 24, 10, 34, 52, 21, 59, 16, 3, 27, 5, 20, 46, 9, 40, 7, 62, 2, 30, 53, 15, 48, 10, 28, 35, 54, 6, 21, 34, 18, 55, 7, 40, 57, 19, 26, 60, 41, 13, 24, 51, 19, 61, 9, 25, 34, 15, 63, 11, 45, 17, 20, 47, 33, 8, 31, 62, 43, 26, 53, 7, 24, 59, 0, 13, 55, 4, 62, 27, 51, 31, 63, 15, 58, 7, 54, 14, 46, 22, 28, 43, 12, 63, 8, 54, 5, 17, 39, 33, 15, 10, 27, 17, 47, 34, 19, 45, 27, 12, 33, 17 }, \ { 5, 28, 21, 7, 17, 48, 42, 58, 23, 4, 63, 14, 55, 21, 34, 5, 19, 0, 45, 17, 52, 15, 25, 32, 0, 22, 40, 13, 45, 62, 18, 0, 43, 11, 33, 55, 30, 42, 57, 19, 51, 31, 22, 43, 18, 45, 34, 0, 43, 31, 56, 3, 23, 40, 59, 0, 44, 13, 48, 35, 2, 32, 46, 0, 21, 48, 35, 3, 40, 32, 43, 59, 0, 48, 33, 26, 53, 36, 55, 12, 51, 16, 55, 5, 18, 29, 11, 39, 51, 19, 45, 31, 42, 21, 35, 6, 22, 47, 10, 38, 23, 50, 20, 36, 0, 60, 38, 4, 50, 35, 48, 34, 24, 57, 9, 53, 28, 48, 61, 0, 56, 24, 53, 3, 63, 6, 42, 57 }, \ { 13, 53, 45, 40, 58, 27, 6, 16, 38, 51, 33, 30, 43, 2, 47, 56, 40, 50, 33, 57, 27, 5, 47, 42, 60, 36, 16, 54, 28, 4, 37, 57, 28, 51, 22, 8, 45, 14, 6, 39, 0, 54, 11, 59, 28, 12, 50, 21, 61, 13, 19, 38, 49, 11, 25, 37, 58, 29, 22, 63, 14, 56, 12, 53, 30, 63, 9, 57, 26, 12, 47, 16, 23, 39, 50, 6, 31, 2, 25, 6, 28, 41, 36, 22, 50, 57, 42, 3, 34, 8, 28, 61, 11, 50, 16, 54, 41, 0, 55, 43, 5, 29, 41, 63, 25, 16, 53, 18, 26, 10, 21, 0, 61, 30, 41, 22, 3, 38, 20, 39, 29, 8, 41, 16, 36, 52, 22, 19 }, \ { 55, 34, 0, 25, 10, 32, 56, 44, 28, 0, 57, 7, 26, 53, 23, 8, 13, 35, 22, 12, 36, 60, 20, 8, 14, 29, 48, 2, 41, 49, 23, 13, 39, 7, 48, 58, 25, 53, 34, 62, 28, 16, 48, 4, 37, 56, 27, 5, 36, 52, 46, 7, 62, 33, 52, 11, 17, 53, 5, 28, 41, 24, 38, 17, 5, 39, 20, 45, 15, 56, 5, 38, 60, 8, 14, 57, 21, 48, 62, 39, 59, 13, 1, 60, 9, 32, 16, 63, 44, 25, 52, 15, 36, 2, 60, 29, 12, 33, 25, 17, 59, 45, 13, 8, 49, 32, 6, 40, 59, 29, 45, 37, 13, 47, 6, 55, 30, 45, 9, 52, 13, 59, 25, 47, 32, 1, 49, 30 }, \ { 9, 39, 14, 61, 49, 37, 3, 20, 50, 13, 41, 19, 46, 17, 38, 59, 28, 62, 4, 44, 54, 1, 34, 51, 55, 7, 63, 32, 21, 8, 56, 31, 62, 19, 36, 1, 41, 17, 24, 12, 42, 35, 25, 52, 20, 8, 44, 59, 25, 2, 22, 42, 16, 29, 4, 46, 20, 36, 43, 9, 51, 8, 49, 26, 58, 33, 54, 1, 37, 29, 52, 20, 27, 45, 19, 35, 42, 16, 10, 32, 20, 49, 46, 27, 40, 4, 47, 22, 13, 55, 4, 47, 26, 44, 23, 40, 58, 19, 48, 13, 31, 2, 57, 34, 42, 19, 61, 32, 14, 55, 5, 51, 26, 19, 58, 16, 49, 14, 62, 5, 33, 44, 21, 7, 60, 26, 11, 41 }, \ { 62, 24, 47, 29, 8, 19, 53, 11, 60, 24, 32, 61, 4, 55, 31, 2, 49, 16, 39, 9, 31, 24, 43, 17, 26, 38, 11, 25, 58, 43, 12, 35, 3, 46, 15, 32, 63, 4, 49, 56, 2, 60, 10, 32, 63, 17, 39, 12, 55, 30, 57, 9, 48, 55, 39, 24, 60, 2, 58, 31, 19, 61, 34, 3, 42, 11, 22, 46, 7, 61, 10, 42, 3, 55, 32, 1, 58, 28, 44, 54, 4, 34, 23, 15, 56, 20, 37, 58, 6, 30, 38, 18, 63, 9, 32, 5, 51, 3, 62, 37, 52, 18, 39, 23, 3, 51, 9, 47, 1, 23, 43, 15, 60, 35, 11, 40, 1, 36, 31, 26, 57, 2, 37, 54, 18, 44, 58, 16 }, \ { 5, 51, 3, 33, 43, 62, 21, 42, 35, 9, 48, 15, 36, 10, 22, 42, 20, 46, 26, 56, 50, 12, 59, 3, 48, 19, 45, 53, 1, 27, 47, 17, 52, 24, 56, 11, 51, 21, 37, 30, 20, 46, 14, 41, 1, 47, 33, 7, 41, 17, 35, 27, 20, 1, 14, 54, 26, 33, 18, 47, 1, 44, 14, 59, 16, 52, 28, 18, 49, 31, 25, 34, 63, 13, 51, 24, 9, 50, 3, 23, 38, 63, 7, 52, 29, 46, 11, 33, 50, 22, 57, 36, 1, 57, 49, 17, 39, 28, 9, 35, 6, 27, 53, 15, 55, 30, 24, 58, 36, 41, 11, 52, 32, 3, 44, 25, 62, 23, 51, 15, 42, 22, 50, 10, 39, 4, 31, 35 }, \ { 46, 22, 57, 17, 12, 39, 26, 5, 31, 59, 1, 45, 27, 62, 52, 7, 58, 33, 6, 18, 39, 22, 33, 41, 57, 5, 35, 18, 40, 16, 60, 5, 29, 42, 7, 39, 27, 44, 9, 47, 8, 26, 54, 22, 51, 29, 24, 49, 15, 61, 4, 51, 31, 63, 43, 6, 50, 8, 39, 12, 53, 37, 23, 30, 40, 6, 62, 43, 14, 53, 2, 49, 7, 36, 17, 41, 61, 37, 18, 56, 11, 18, 44, 35, 2, 19, 61, 0, 41, 14, 8, 30, 43, 12, 24, 46, 14, 54, 42, 21, 44, 61, 10, 46, 37, 11, 44, 7, 18, 63, 20, 29, 7, 49, 28, 54, 8, 43, 4, 48, 18, 63, 12, 29, 48, 24, 59, 20 }, \ { 13, 36, 28, 54, 35, 2, 56, 46, 16, 49, 22, 40, 11, 34, 14, 43, 29, 12, 63, 48, 2, 61, 7, 15, 28, 30, 50, 9, 61, 33, 38, 23, 54, 13, 61, 33, 3, 59, 16, 35, 58, 40, 5, 38, 13, 57, 3, 58, 37, 21, 45, 12, 39, 7, 35, 30, 13, 56, 22, 62, 27, 6, 55, 10, 48, 21, 33, 2, 38, 23, 40, 20, 44, 29, 59, 4, 26, 12, 33, 47, 28, 53, 31, 13, 59, 41, 27, 49, 26, 54, 45, 16, 53, 21, 35, 7, 59, 26, 11, 56, 1, 24, 33, 4, 28, 62, 21, 49, 31, 2, 56, 39, 24, 58, 13, 17, 37, 21, 56, 10, 38, 0, 34, 55, 15, 43, 1, 52 }, \ { 42, 9, 50, 6, 25, 60, 14, 38, 10, 29, 53, 18, 57, 3, 25, 51, 0, 53, 25, 17, 29, 37, 52, 46, 0, 62, 14, 37, 4, 50, 10, 44, 0, 46, 20, 25, 50, 19, 55, 0, 23, 31, 62, 34, 11, 45, 19, 32, 0, 53, 10, 59, 23, 47, 18, 60, 42, 28, 37, 3, 50, 15, 35, 44, 0, 51, 27, 60, 9, 57, 16, 58, 11, 22, 46, 15, 53, 48, 7, 42, 0, 60, 5, 49, 24, 54, 9, 17, 39, 5, 34, 62, 3, 40, 60, 31, 0, 47, 29, 16, 49, 39, 59, 17, 50, 0, 40, 13, 53, 38, 16, 46, 0, 42, 34, 60, 2, 53, 29, 31, 58, 46, 27, 6, 61, 8, 37, 28 }, \ { 0, 63, 21, 40, 45, 18, 51, 23, 63, 34, 6, 43, 28, 38, 55, 19, 40, 35, 8, 41, 54, 10, 21, 32, 39, 23, 53, 26, 55, 28, 22, 63, 30, 34, 9, 48, 6, 38, 29, 43, 49, 6, 18, 52, 27, 61, 9, 43, 28, 42, 33, 26, 56, 3, 51, 23, 0, 48, 16, 45, 32, 25, 63, 20, 57, 17, 42, 12, 35, 47, 5, 31, 39, 56, 6, 30, 34, 21, 61, 25, 14, 40, 22, 38, 15, 6, 36, 56, 20, 60, 25, 12, 51, 27, 10, 56, 42, 20, 36, 63, 32, 6, 21, 41, 12, 34, 60, 26, 5, 48, 27, 10, 62, 19, 6, 47, 39, 14, 45, 7, 24, 17, 41, 32, 23, 51, 19, 56 }, \ { 45, 31, 15, 59, 4, 33, 7, 47, 0, 41, 13, 61, 4, 47, 9, 23, 60, 14, 57, 31, 4, 45, 59, 6, 58, 10, 44, 20, 8, 42, 15, 6, 55, 17, 58, 31, 53, 12, 61, 10, 15, 57, 43, 2, 23, 35, 48, 14, 54, 6, 18, 49, 15, 38, 11, 34, 62, 9, 21, 58, 11, 41, 4, 31, 38, 8, 29, 55, 19, 36, 27, 52, 0, 25, 50, 43, 1, 39, 8, 55, 35, 51, 10, 30, 45, 62, 29, 2, 46, 10, 32, 48, 18, 38, 5, 22, 33, 8, 51, 3, 14, 44, 54, 25, 57, 30, 18, 52, 33, 22, 59, 28, 36, 52, 32, 21, 26, 50, 5, 55, 35, 60, 14, 54, 4, 40, 16, 33 }, \ { 27, 3, 49, 10, 30, 40, 55, 27, 57, 24, 52, 21, 32, 17, 60, 30, 5, 44, 27, 49, 19, 34, 13, 24, 43, 36, 3, 49, 31, 59, 37, 48, 26, 41, 2, 41, 14, 36, 21, 32, 40, 26, 13, 49, 55, 5, 16, 40, 25, 60, 36, 1, 63, 29, 17, 44, 25, 40, 52, 5, 29, 47, 54, 13, 46, 24, 60, 4, 51, 22, 63, 14, 45, 18, 12, 62, 17, 57, 19, 42, 3, 26, 58, 48, 1, 21, 40, 52, 23, 37, 44, 1, 29, 58, 43, 50, 15, 61, 19, 45, 58, 28, 7, 48, 2, 46, 8, 42, 3, 55, 8, 50, 12, 4, 55, 10, 63, 33, 20, 40, 11, 3, 46, 20, 48, 26, 61, 11 }, \ { 44, 56, 24, 36, 53, 19, 12, 37, 16, 44, 7, 36, 49, 54, 11, 37, 48, 21, 15, 1, 62, 25, 47, 56, 16, 18, 51, 12, 40, 1, 24, 11, 52, 16, 23, 59, 28, 1, 45, 53, 4, 60, 37, 21, 39, 30, 63, 20, 52, 10, 30, 45, 8, 41, 54, 4, 57, 7, 34, 55, 36, 18, 23, 59, 2, 48, 11, 32, 44, 1, 41, 8, 33, 54, 38, 23, 30, 46, 6, 29, 62, 18, 32, 16, 55, 34, 14, 11, 61, 7, 55, 16, 53, 13, 23, 2, 55, 37, 26, 10, 33, 23, 36, 16, 38, 22, 56, 15, 24, 43, 35, 17, 44, 40, 25, 46, 16, 1, 57, 25, 49, 36, 28, 62, 9, 35, 7, 53 }, \ { 17, 38, 8, 61, 1, 50, 26, 62, 3, 31, 56, 15, 1, 26, 40, 2, 34, 51, 56, 36, 42, 9, 38, 2, 29, 60, 32, 57, 19, 62, 34, 47, 4, 57, 39, 7, 44, 63, 24, 18, 46, 28, 8, 54, 1, 34, 7, 46, 3, 37, 50, 23, 57, 21, 13, 46, 31, 20, 43, 15, 1, 61, 8, 33, 37, 17, 56, 26, 15, 49, 24, 59, 28, 3, 56, 9, 52, 32, 13, 49, 10, 43, 5, 45, 8, 25, 59, 42, 28, 33, 19, 40, 8, 63, 35, 47, 25, 4, 40, 52, 1, 60, 12, 53, 63, 9, 29, 60, 37, 19, 1, 62, 31, 20, 58, 12, 41, 30, 43, 9, 18, 52, 22, 1, 39, 30, 58, 21 }, \ { 13, 47, 29, 18, 43, 34, 5, 48, 20, 42, 10, 45, 30, 58, 20, 63, 24, 11, 6, 28, 54, 14, 22, 52, 41, 7, 26, 5, 45, 15, 53, 13, 35, 27, 18, 50, 12, 33, 5, 56, 10, 17, 45, 24, 59, 15, 50, 26, 56, 13, 19, 5, 32, 52, 27, 36, 2, 61, 12, 26, 49, 40, 27, 52, 13, 50, 6, 39, 61, 34, 10, 37, 48, 20, 41, 27, 2, 36, 59, 24, 54, 33, 63, 20, 38, 50, 3, 17, 52, 4, 58, 27, 45, 21, 32, 11, 48, 17, 57, 20, 46, 38, 25, 43, 4, 34, 51, 6, 13, 45, 57, 26, 6, 48, 2, 35, 53, 23, 61, 34, 59, 6, 42, 56, 13, 51, 2, 41 }, \ { 32, 5, 55, 23, 58, 14, 22, 52, 29, 15, 61, 25, 51, 8, 43, 13, 53, 41, 46, 20, 3, 33, 63, 11, 48, 21, 54, 38, 28, 3, 30, 43, 21, 62, 9, 31, 55, 22, 51, 29, 37, 62, 32, 12, 42, 29, 41, 9, 33, 44, 62, 28, 43, 1, 59, 19, 48, 30, 51, 39, 24, 4, 58, 19, 42, 29, 22, 43, 3, 18, 53, 5, 13, 50, 16, 60, 45, 21, 7, 40, 15, 0, 26, 53, 13, 31, 43, 24, 47, 31, 15, 49, 2, 41, 6, 59, 29, 42, 9, 30, 14, 7, 49, 18, 31, 47, 20, 39, 49, 32, 11, 41, 54, 15, 61, 18, 7, 38, 4, 13, 44, 28, 15, 32, 45, 19, 27, 49 }, \ { 63, 34, 11, 39, 2, 45, 37, 8, 59, 39, 33, 4, 36, 17, 48, 5, 29, 18, 32, 61, 39, 50, 5, 27, 35, 0, 46, 12, 22, 49, 60, 6, 54, 0, 38, 49, 2, 42, 15, 40, 0, 47, 20, 51, 3, 57, 18, 61, 22, 0, 39, 16, 55, 12, 35, 8, 41, 22, 6, 59, 16, 45, 10, 36, 0, 62, 9, 54, 30, 58, 21, 43, 63, 31, 7, 35, 12, 48, 58, 28, 47, 37, 41, 9, 57, 20, 61, 0, 36, 11, 57, 35, 23, 52, 37, 18, 0, 62, 22, 55, 35, 62, 27, 54, 0, 15, 61, 28, 2, 59, 22, 9, 37, 27, 33, 51, 29, 48, 19, 50, 25, 37, 10, 57, 5, 37, 60, 8 }, \ { 20, 25, 46, 52, 31, 60, 12, 55, 0, 19, 11, 46, 62, 35, 23, 38, 57, 0, 55, 10, 16, 30, 58, 44, 17, 59, 29, 63, 42, 8, 36, 20, 33, 46, 16, 61, 25, 35, 8, 54, 26, 7, 58, 22, 34, 6, 47, 14, 53, 31, 48, 9, 37, 25, 49, 63, 16, 55, 45, 14, 34, 63, 21, 53, 25, 33, 46, 16, 35, 7, 46, 29, 0, 39, 25, 55, 22, 34, 18, 4, 56, 11, 23, 51, 28, 6, 39, 14, 62, 44, 19, 8, 60, 12, 56, 28, 50, 34, 39, 5, 51, 3, 41, 12, 57, 35, 10, 53, 25, 17, 52, 30, 47, 0, 43, 14, 5, 57, 31, 55, 0, 63, 47, 23, 54, 24, 14, 43 }, \ { 0, 57, 16, 6, 26, 19, 35, 28, 49, 42, 54, 26, 21, 1, 59, 27, 9, 47, 26, 44, 50, 22, 13, 40, 8, 37, 10, 34, 17, 56, 25, 58, 13, 27, 44, 9, 20, 58, 31, 17, 60, 36, 10, 41, 53, 25, 36, 39, 4, 24, 58, 17, 60, 4, 22, 38, 10, 32, 0, 50, 31, 7, 28, 47, 12, 57, 5, 26, 52, 23, 14, 40, 57, 17, 47, 5, 53, 1, 44, 31, 19, 60, 46, 2, 35, 48, 30, 54, 22, 5, 51, 39, 25, 31, 4, 43, 14, 9, 45, 16, 24, 44, 19, 29, 40, 23, 44, 7, 38, 42, 4, 63, 12, 54, 23, 59, 22, 42, 8, 15, 40, 21, 8, 34, 3, 41, 30, 50 }, \ { 39, 10, 48, 33, 41, 54, 5, 47, 23, 13, 32, 7, 52, 44, 14, 39, 58, 18, 35, 6, 37, 2, 60, 24, 55, 19, 53, 2, 51, 32, 1, 41, 51, 4, 40, 29, 47, 3, 52, 44, 13, 49, 28, 16, 1, 62, 11, 27, 52, 35, 5, 42, 29, 47, 14, 56, 28, 53, 26, 38, 9, 56, 40, 3, 38, 15, 41, 60, 1, 37, 50, 25, 11, 28, 61, 19, 42, 62, 10, 52, 39, 6, 32, 14, 58, 17, 7, 26, 42, 34, 27, 10, 54, 40, 20, 63, 26, 53, 21, 61, 32, 7, 59, 48, 3, 56, 18, 31, 58, 14, 49, 21, 36, 16, 45, 9, 36, 24, 62, 45, 27, 31, 53, 17, 49, 12, 62, 18 }, \ { 28, 59, 21, 58, 2, 16, 38, 9, 62, 3, 56, 41, 10, 31, 50, 4, 32, 52, 12, 63, 23, 46, 33, 31, 4, 48, 25, 43, 14, 23, 47, 11, 22, 55, 14, 60, 23, 37, 11, 39, 23, 2, 45, 56, 31, 43, 19, 55, 16, 46, 21, 51, 11, 33, 44, 2, 41, 18, 5, 52, 23, 44, 17, 60, 27, 49, 11, 32, 44, 10, 54, 2, 56, 33, 8, 38, 13, 29, 36, 16, 24, 63, 27, 51, 21, 43, 56, 12, 49, 3, 59, 48, 1, 15, 46, 7, 36, 2, 47, 11, 50, 27, 37, 13, 33, 8, 51, 46, 1, 34, 28, 40, 3, 33, 60, 29, 47, 1, 35, 11, 59, 42, 2, 60, 26, 46, 6, 35 }, \ { 4, 43, 9, 29, 36, 63, 24, 44, 20, 50, 30, 17, 60, 22, 16, 43, 25, 3, 42, 19, 51, 15, 8, 54, 42, 15, 61, 5, 39, 57, 18, 61, 31, 48, 34, 2, 50, 19, 57, 5, 63, 33, 19, 38, 13, 27, 48, 7, 32, 61, 2, 26, 58, 6, 24, 50, 13, 61, 42, 20, 62, 2, 35, 20, 51, 4, 62, 18, 23, 58, 20, 31, 43, 15, 51, 45, 26, 50, 4, 55, 45, 3, 35, 9, 38, 1, 32, 61, 20, 45, 17, 33, 24, 57, 29, 51, 22, 58, 38, 30, 15, 1, 54, 21, 63, 43, 26, 12, 24, 56, 8, 60, 50, 19, 5, 52, 13, 54, 17, 50, 4, 16, 36, 12, 32, 56, 22, 54 }, \ { 51, 25, 40, 53, 12, 49, 15, 57, 34, 7, 38, 47, 2, 36, 55, 8, 61, 30, 56, 7, 28, 59, 48, 11, 27, 35, 21, 45, 28, 36, 9, 38, 6, 16, 24, 63, 10, 32, 28, 43, 21, 53, 5, 60, 8, 57, 3, 45, 11, 37, 15, 54, 40, 20, 62, 36, 27, 34, 11, 48, 30, 15, 54, 8, 30, 42, 22, 34, 48, 13, 35, 63, 4, 37, 22, 2, 59, 9, 41, 23, 13, 41, 49, 18, 59, 24, 40, 5, 37, 30, 9, 61, 44, 6, 37, 11, 33, 17, 5, 55, 41, 60, 23, 39, 17, 5, 30, 62, 41, 16, 46, 25, 11, 56, 39, 26, 20, 38, 29, 39, 22, 52, 44, 20, 48, 1, 38, 14 }, \ { 15, 33, 2, 18, 44, 6, 27, 0, 32, 61, 25, 12, 58, 28, 40, 20, 47, 13, 34, 43, 38, 1, 23, 62, 40, 0, 51, 10, 63, 3, 52, 26, 44, 30, 45, 6, 41, 54, 0, 51, 12, 30, 46, 24, 49, 22, 40, 33, 63, 23, 43, 30, 9, 47, 0, 17, 54, 7, 57, 3, 37, 47, 24, 46, 13, 55, 7, 52, 2, 42, 6, 26, 49, 18, 60, 34, 16, 57, 33, 20, 61, 30, 8, 54, 14, 46, 12, 53, 16, 55, 38, 13, 22, 53, 18, 59, 46, 27, 43, 19, 32, 10, 45, 6, 49, 36, 52, 2, 20, 55, 6, 39, 32, 15, 44, 3, 58, 10, 63, 6, 56, 30, 7, 58, 9, 40, 19, 63 }, \ { 10, 47, 61, 23, 55, 31, 52, 42, 17, 45, 4, 51, 27, 6, 15, 53, 0, 49, 26, 10, 56, 18, 36, 6, 20, 58, 32, 30, 13, 49, 19, 56, 0, 59, 12, 53, 27, 17, 38, 25, 48, 9, 15, 36, 14, 30, 59, 17, 0, 50, 8, 58, 18, 56, 31, 45, 21, 41, 29, 19, 60, 6, 32, 59, 0, 36, 29, 39, 19, 59, 46, 12, 55, 30, 10, 47, 24, 3, 28, 48, 0, 55, 44, 27, 33, 4, 63, 29, 49, 0, 26, 50, 34, 2, 42, 14, 0, 62, 9, 56, 3, 52, 28, 34, 58, 9, 20, 48, 37, 32, 22, 53, 0, 62, 27, 49, 34, 46, 21, 33, 41, 14, 25, 37, 53, 29, 31, 45 }, \ { 56, 28, 7, 37, 11, 36, 20, 9, 54, 14, 39, 19, 34, 63, 45, 37, 24, 17, 60, 31, 21, 45, 53, 29, 47, 15, 7, 55, 40, 23, 34, 14, 42, 20, 37, 35, 15, 59, 7, 62, 34, 40, 59, 1, 51, 42, 10, 28, 54, 21, 35, 5, 38, 13, 36, 4, 59, 12, 39, 53, 15, 43, 9, 21, 39, 62, 16, 56, 25, 9, 32, 38, 0, 41, 14, 51, 40, 53, 43, 11, 37, 17, 5, 22, 57, 39, 19, 7, 42, 21, 60, 10, 31, 63, 25, 52, 30, 49, 36, 25, 48, 17, 61, 14, 22, 42, 29, 13, 60, 11, 47, 18, 35, 41, 7, 23, 4, 16, 51, 11, 0, 48, 61, 3, 17, 50, 5, 24 }, \ { 0, 42, 21, 49, 60, 3, 57, 40, 29, 48, 23, 56, 42, 11, 22, 5, 59, 39, 4, 50, 3, 41, 12, 57, 25, 50, 44, 18, 4, 46, 7, 62, 33, 50, 4, 56, 21, 32, 43, 18, 3, 23, 55, 34, 20, 4, 53, 38, 12, 46, 29, 52, 25, 61, 23, 51, 26, 46, 1, 34, 25, 57, 28, 51, 26, 11, 50, 3, 44, 28, 53, 21, 57, 27, 62, 6, 31, 19, 8, 63, 26, 59, 36, 47, 15, 29, 50, 25, 35, 47, 18, 41, 4, 48, 8, 40, 12, 23, 6, 44, 13, 40, 1, 31, 55, 0, 61, 43, 4, 50, 26, 58, 9, 53, 24, 61, 42, 55, 31, 43, 57, 20, 34, 27, 43, 8, 59, 39 }, \ { 18, 51, 30, 13, 26, 16, 46, 22, 2, 59, 8, 30, 1, 48, 33, 51, 29, 9, 46, 16, 62, 14, 33, 2, 38, 9, 27, 60, 37, 26, 53, 17, 28, 10, 24, 46, 2, 49, 8, 57, 29, 45, 6, 26, 62, 44, 18, 25, 61, 3, 42, 14, 49, 10, 43, 6, 17, 32, 63, 10, 49, 4, 40, 14, 45, 33, 22, 37, 12, 61, 5, 17, 43, 7, 23, 37, 15, 58, 49, 13, 39, 21, 10, 52, 1, 62, 9, 56, 12, 2, 58, 28, 36, 16, 56, 28, 56, 35, 20, 63, 24, 37, 51, 8, 45, 25, 16, 33, 27, 38, 2, 44, 13, 30, 17, 36, 12, 26, 5, 18, 28, 47, 13, 60, 23, 45, 13, 33 }, \ { 55, 4, 62, 34, 52, 38, 7, 63, 32, 37, 13, 53, 25, 62, 18, 12, 55, 41, 27, 35, 24, 49, 31, 52, 17, 63, 34, 1, 56, 12, 41, 2, 48, 58, 39, 16, 61, 27, 41, 52, 13, 19, 50, 39, 11, 31, 57, 6, 32, 40, 20, 55, 1, 28, 33, 57, 48, 8, 37, 22, 44, 18, 53, 1, 61, 5, 54, 16, 47, 36, 50, 24, 55, 34, 48, 45, 1, 30, 33, 46, 2, 50, 32, 42, 25, 34, 43, 21, 38, 52, 23, 45, 14, 54, 21, 4, 44, 16, 53, 29, 10, 47, 19, 57, 12, 54, 39, 10, 51, 15, 63, 21, 57, 40, 51, 1, 48, 57, 37, 62, 2, 38, 9, 52, 1, 35, 58, 22 }, \ { 36, 46, 10, 42, 1, 27, 43, 15, 50, 21, 45, 16, 41, 3, 35, 44, 20, 1, 57, 11, 55, 7, 43, 8, 22, 42, 13, 46, 21, 39, 31, 60, 22, 5, 29, 44, 11, 35, 20, 4, 36, 58, 32, 15, 47, 2, 36, 48, 16, 60, 8, 35, 44, 63, 16, 2, 40, 26, 55, 14, 58, 35, 24, 31, 19, 42, 31, 58, 1, 29, 10, 40, 2, 19, 12, 54, 22, 61, 7, 24, 56, 5, 28, 16, 54, 3, 15, 58, 6, 30, 8, 62, 1, 43, 31, 47, 7, 59, 1, 38, 58, 4, 34, 27, 38, 5, 31, 59, 7, 46, 30, 3, 34, 6, 28, 59, 20, 8, 32, 15, 53, 24, 55, 31, 19, 49, 11, 26 }, \ { 2, 24, 16, 58, 19, 55, 5, 35, 10, 61, 4, 28, 57, 24, 58, 7, 31, 47, 22, 38, 19, 28, 61, 36, 54, 5, 59, 29, 6, 52, 15, 11, 43, 36, 8, 54, 52, 1, 62, 25, 47, 9, 1, 60, 28, 53, 24, 14, 46, 27, 51, 22, 12, 24, 38, 53, 20, 11, 51, 3, 29, 7, 48, 63, 8, 49, 9, 21, 52, 14, 63, 32, 46, 60, 35, 4, 41, 16, 52, 35, 18, 42, 59, 7, 36, 61, 45, 27, 33, 51, 19, 39, 34, 11, 61, 18, 33, 41, 28, 15, 54, 22, 42, 3, 49, 21, 47, 18, 36, 23, 55, 19, 48, 24, 45, 10, 33, 44, 50, 40, 7, 35, 15, 41, 63, 6, 40, 54 }, \ { 62, 41, 32, 8, 47, 28, 60, 24, 44, 30, 38, 49, 9, 33, 14, 40, 50, 14, 60, 2, 54, 40, 0, 20, 25, 39, 16, 49, 24, 35, 57, 47, 19, 61, 33, 18, 23, 37, 13, 55, 31, 43, 22, 41, 17, 8, 42, 58, 0, 37, 5, 56, 31, 54, 7, 30, 60, 33, 42, 17, 59, 39, 12, 27, 38, 17, 35, 41, 27, 45, 20, 7, 25, 15, 29, 58, 27, 47, 11, 40, 14, 54, 23, 46, 19, 31, 11, 40, 13, 49, 5, 58, 24, 51, 26, 6, 50, 20, 49, 9, 32, 46, 17, 60, 14, 63, 24, 1, 57, 41, 9, 43, 14, 62, 16, 52, 3, 27, 14, 22, 61, 45, 4, 28, 9, 47, 29, 17 }, \ { 5, 50, 12, 53, 38, 18, 11, 51, 0, 55, 17, 6, 47, 54, 19, 63, 5, 26, 34, 45, 13, 30, 47, 58, 10, 48, 32, 3, 62, 9, 26, 0, 25, 14, 50, 3, 47, 30, 42, 16, 6, 63, 12, 49, 33, 55, 21, 10, 34, 63, 18, 41, 3, 47, 19, 43, 0, 49, 8, 28, 46, 20, 52, 0, 56, 24, 60, 3, 59, 5, 39, 57, 48, 52, 9, 38, 3, 21, 26, 60, 0, 32, 12, 38, 4, 48, 53, 0, 60, 15, 29, 44, 18, 10, 38, 57, 13, 60, 2, 26, 62, 7, 50, 29, 35, 8, 40, 53, 28, 12, 60, 33, 38, 5, 37, 29, 60, 39, 56, 0, 30, 18, 50, 34, 59, 25, 14, 44 }, \ { 20, 31, 60, 22, 3, 49, 33, 25, 40, 13, 34, 59, 22, 36, 0, 28, 37, 56, 8, 18, 51, 16, 4, 45, 27, 12, 53, 42, 18, 44, 51, 31, 55, 40, 28, 58, 7, 60, 10, 51, 27, 37, 24, 56, 5, 26, 44, 29, 50, 23, 45, 11, 34, 15, 59, 27, 13, 23, 62, 37, 4, 57, 15, 32, 42, 6, 47, 11, 30, 43, 23, 13, 0, 36, 18, 44, 63, 51, 37, 29, 49, 20, 57, 27, 62, 9, 24, 35, 23, 53, 37, 3, 42, 55, 0, 36, 23, 39, 31, 43, 17, 37, 24, 11, 52, 43, 19, 32, 5, 50, 26, 0, 56, 21, 54, 11, 19, 6, 47, 25, 59, 42, 12, 54, 21, 3, 38, 57 }, \ { 48, 0, 35, 27, 44, 14, 59, 7, 57, 46, 26, 2, 42, 12, 52, 43, 10, 27, 53, 42, 32, 62, 37, 21, 34, 61, 7, 23, 36, 4, 38, 12, 41, 5, 17, 45, 22, 27, 39, 21, 59, 0, 45, 18, 39, 62, 3, 38, 14, 7, 54, 26, 61, 39, 9, 52, 45, 36, 18, 50, 10, 34, 44, 22, 50, 14, 36, 55, 17, 34, 53, 62, 33, 26, 56, 6, 31, 12, 6, 53, 9, 44, 2, 50, 20, 40, 55, 17, 47, 7, 26, 63, 22, 32, 48, 16, 46, 8, 52, 12, 57, 41, 0, 56, 25, 3, 61, 14, 45, 35, 18, 44, 12, 46, 23, 42, 32, 51, 35, 10, 17, 36, 23, 1, 45, 52, 32, 10 }, \ { 37, 15, 43, 8, 63, 39, 21, 31, 16, 37, 19, 62, 30, 46, 17, 60, 21, 48, 1, 23, 6, 25, 11, 56, 1, 40, 30, 58, 15, 54, 21, 59, 9, 63, 35, 56, 11, 51, 2, 46, 34, 14, 53, 7, 30, 11, 51, 19, 60, 40, 30, 1, 24, 50, 20, 32, 3, 56, 5, 25, 31, 13, 61, 2, 29, 60, 25, 20, 51, 2, 27, 8, 18, 42, 10, 45, 21, 34, 43, 17, 62, 29, 41, 14, 34, 6, 30, 43, 2, 57, 33, 13, 45, 12, 27, 62, 4, 55, 21, 35, 5, 27, 45, 33, 16, 47, 30, 54, 22, 10, 51, 27, 63, 7, 49, 1, 58, 22, 15, 43, 53, 7, 57, 39, 27, 12, 61, 24 }, \ { 56, 51, 26, 56, 19, 2, 41, 54, 5, 52, 9, 48, 6, 23, 39, 4, 32, 15, 63, 35, 59, 49, 43, 15, 52, 19, 50, 9, 46, 33, 1, 29, 48, 20, 32, 1, 38, 33, 19, 54, 9, 32, 24, 48, 58, 35, 16, 48, 4, 52, 13, 57, 33, 5, 45, 59, 15, 29, 41, 55, 47, 39, 23, 53, 9, 40, 4, 57, 10, 44, 48, 40, 50, 14, 61, 24, 55, 1, 59, 22, 33, 8, 51, 25, 58, 46, 11, 59, 20, 41, 17, 51, 6, 56, 35, 25, 42, 30, 15, 58, 48, 18, 61, 9, 58, 39, 13, 2, 37, 59, 40, 2, 31, 16, 34, 41, 8, 30, 62, 3, 29, 48, 33, 5, 63, 16, 41, 7 }, \ { 22, 4, 46, 11, 33, 51, 29, 10, 62, 24, 43, 27, 15, 58, 50, 25, 54, 44, 9, 38, 18, 3, 29, 57, 32, 5, 26, 43, 17, 61, 24, 52, 8, 42, 23, 53, 15, 61, 7, 28, 57, 43, 4, 40, 20, 2, 43, 25, 32, 35, 21, 43, 17, 48, 10, 22, 38, 54, 11, 21, 1, 58, 16, 30, 48, 18, 46, 32, 38, 13, 22, 4, 59, 35, 2, 51, 30, 39, 15, 47, 4, 56, 13, 37, 1, 28, 16, 52, 32, 9, 61, 29, 38, 19, 3, 52, 10, 48, 1, 32, 11, 40, 20, 36, 6, 22, 49, 29, 55, 6, 20, 56, 36, 52, 19, 60, 26, 46, 18, 54, 40, 13, 20, 46, 35, 19, 49, 29 }, \ { 61, 17, 34, 53, 23, 6, 48, 35, 20, 40, 1, 56, 36, 29, 11, 34, 7, 41, 14, 30, 55, 20, 46, 8, 24, 38, 63, 2, 37, 10, 45, 14, 34, 49, 6, 13, 44, 25, 49, 41, 21, 12, 61, 15, 54, 29, 63, 12, 56, 8, 49, 2, 62, 36, 28, 61, 0, 25, 41, 63, 35, 8, 44, 6, 37, 62, 7, 21, 63, 28, 55, 31, 16, 24, 41, 19, 9, 57, 27, 36, 18, 42, 31, 62, 22, 55, 38, 4, 27, 47, 1, 40, 14, 54, 43, 20, 60, 23, 38, 63, 25, 51, 2, 53, 26, 63, 10, 42, 17, 34, 47, 25, 13, 5, 44, 11, 55, 2, 38, 27, 6, 60, 52, 25, 9, 55, 1, 40 }, \ { 8, 30, 58, 3, 42, 61, 17, 38, 13, 59, 32, 10, 54, 3, 51, 20, 61, 26, 57, 2, 46, 33, 12, 60, 41, 13, 48, 29, 55, 20, 39, 27, 57, 18, 62, 29, 55, 2, 31, 16, 37, 50, 26, 36, 6, 46, 9, 41, 27, 57, 23, 39, 26, 6, 51, 12, 31, 46, 7, 16, 27, 52, 19, 56, 26, 12, 33, 53, 1, 41, 8, 57, 46, 7, 54, 32, 47, 5, 49, 11, 60, 23, 5, 48, 10, 43, 19, 63, 35, 24, 49, 21, 59, 5, 31, 37, 14, 44, 7, 42, 6, 30, 46, 13, 44, 32, 19, 50, 4, 58, 8, 30, 62, 38, 28, 53, 21, 36, 13, 50, 21, 33, 15, 2, 44, 31, 14, 47 }, \ { 37, 13, 39, 16, 28, 9, 57, 0, 25, 49, 21, 45, 18, 47, 12, 42, 0, 49, 22, 39, 16, 53, 25, 36, 0, 52, 22, 16, 6, 60, 4, 51, 0, 26, 37, 47, 10, 36, 63, 5, 57, 0, 18, 59, 23, 33, 51, 19, 0, 44, 15, 11, 54, 17, 42, 35, 53, 18, 58, 33, 49, 4, 34, 42, 0, 50, 43, 25, 16, 49, 34, 20, 37, 28, 12, 63, 16, 38, 25, 44, 0, 40, 52, 17, 35, 3, 50, 14, 8, 53, 11, 36, 25, 45, 9, 62, 0, 54, 28, 17, 50, 55, 15, 24, 57, 0, 53, 34, 23, 41, 15, 45, 0, 49, 16, 4, 48, 9, 63, 45, 0, 42, 58, 37, 61, 22, 54, 26 }, \ { 0, 50, 21, 47, 54, 36, 27, 45, 52, 4, 34, 15, 63, 29, 37, 59, 17, 31, 6, 61, 28, 5, 48, 18, 59, 27, 34, 56, 44, 31, 35, 12, 41, 59, 16, 3, 40, 20, 50, 22, 30, 40, 52, 10, 45, 3, 59, 22, 37, 61, 29, 46, 31, 58, 2, 22, 9, 43, 3, 39, 14, 61, 24, 54, 15, 29, 11, 60, 39, 17, 5, 61, 0, 44, 50, 3, 31, 14, 58, 21, 54, 28, 15, 45, 60, 26, 33, 58, 44, 22, 60, 2, 57, 34, 49, 27, 18, 34, 21, 59, 29, 4, 36, 41, 8, 39, 28, 11, 62, 26, 53, 20, 35, 24, 59, 32, 29, 39, 24, 31, 57, 23, 11, 28, 5, 36, 11, 59 }, \ { 44, 32, 63, 5, 20, 12, 41, 7, 30, 61, 42, 8, 39, 5, 33, 8, 24, 53, 45, 11, 37, 58, 7, 44, 10, 50, 3, 40, 8, 22, 53, 19, 46, 9, 33, 52, 24, 58, 8, 44, 13, 47, 8, 34, 38, 30, 14, 47, 7, 34, 4, 55, 9, 19, 40, 49, 56, 26, 60, 21, 30, 45, 10, 19, 40, 58, 23, 36, 3, 52, 45, 23, 54, 13, 22, 42, 53, 45, 7, 33, 10, 36, 57, 6, 29, 12, 41, 0, 30, 15, 41, 30, 17, 7, 16, 53, 40, 56, 2, 39, 12, 61, 10, 52, 31, 60, 16, 45, 1, 37, 7, 61, 40, 10, 43, 17, 58, 7, 54, 14, 4, 51, 39, 49, 18, 56, 42, 20 }, \ { 14, 6, 24, 36, 56, 49, 22, 60, 18, 14, 23, 51, 26, 57, 21, 52, 41, 14, 35, 50, 19, 31, 40, 23, 33, 14, 63, 17, 32, 47, 7, 62, 23, 30, 56, 11, 42, 27, 14, 60, 35, 19, 28, 61, 17, 55, 25, 39, 53, 17, 42, 21, 38, 63, 25, 5, 14, 36, 12, 50, 1, 37, 59, 32, 2, 51, 6, 56, 27, 32, 11, 30, 38, 26, 60, 8, 26, 19, 62, 39, 50, 2, 21, 39, 53, 23, 56, 19, 49, 39, 5, 46, 55, 23, 42, 4, 31, 11, 47, 26, 45, 22, 48, 18, 21, 5, 48, 25, 57, 14, 47, 30, 3, 56, 12, 50, 1, 42, 19, 47, 35, 17, 8, 30, 45, 25, 4, 51 }, \ { 28, 58, 43, 1, 31, 8, 33, 2, 44, 55, 32, 1, 60, 12, 46, 27, 4, 62, 23, 1, 56, 13, 62, 2, 54, 36, 25, 51, 1, 57, 26, 42, 3, 49, 17, 38, 1, 48, 31, 4, 54, 3, 50, 24, 1, 49, 5, 63, 13, 27, 52, 1, 48, 13, 45, 33, 52, 30, 46, 20, 55, 28, 6, 48, 24, 38, 20, 47, 14, 62, 48, 9, 58, 4, 36, 30, 56, 1, 34, 12, 18, 63, 25, 48, 4, 16, 37, 7, 62, 10, 52, 28, 13, 50, 36, 63, 24, 51, 15, 58, 8, 33, 1, 38, 56, 35, 42, 9, 33, 51, 22, 18, 48, 32, 27, 37, 23, 61, 33, 11, 59, 29, 62, 1, 53, 10, 60, 33 }, \ { 12, 39, 17, 52, 26, 46, 53, 38, 25, 11, 48, 36, 16, 43, 2, 35, 55, 17, 39, 29, 43, 9, 28, 45, 20, 5, 46, 12, 42, 28, 13, 52, 36, 6, 60, 22, 54, 17, 62, 39, 25, 42, 15, 55, 44, 20, 31, 10, 35, 57, 24, 32, 29, 6, 59, 18, 7, 62, 3, 41, 10, 44, 16, 54, 13, 62, 31, 9, 41, 1, 21, 43, 18, 47, 15, 40, 11, 49, 28, 55, 46, 30, 8, 43, 32, 61, 28, 47, 25, 34, 21, 61, 32, 1, 20, 9, 46, 6, 35, 19, 41, 54, 27, 63, 14, 3, 51, 20, 62, 2, 38, 55, 8, 21, 63, 6, 46, 9, 26, 51, 3, 24, 43, 34, 16, 41, 18, 48 }, \ { 62, 23, 55, 9, 15, 62, 19, 13, 58, 40, 6, 30, 54, 19, 50, 31, 10, 44, 6, 59, 21, 47, 51, 15, 60, 39, 30, 54, 21, 61, 19, 33, 14, 29, 43, 11, 34, 45, 7, 21, 10, 56, 36, 6, 38, 11, 58, 42, 2, 47, 11, 60, 50, 16, 41, 28, 38, 23, 47, 17, 35, 63, 22, 33, 42, 5, 45, 17, 53, 35, 25, 56, 33, 6, 51, 19, 60, 23, 43, 15, 5, 40, 58, 13, 51, 1, 45, 11, 54, 3, 43, 8, 37, 48, 59, 29, 39, 21, 61, 43, 3, 31, 10, 44, 24, 29, 60, 12, 28, 40, 11, 25, 43, 52, 14, 41, 16, 57, 44, 20, 40, 55, 12, 21, 57, 27, 35, 2 }, \ { 37, 6, 31, 42, 40, 4, 29, 50, 0, 20, 63, 28, 9, 58, 14, 24, 63, 26, 48, 16, 34, 4, 32, 38, 23, 11, 58, 4, 37, 9, 45, 5, 63, 48, 26, 57, 2, 28, 32, 51, 46, 29, 13, 62, 27, 46, 28, 18, 50, 15, 40, 4, 19, 34, 54, 0, 53, 9, 26, 58, 28, 5, 49, 0, 57, 27, 19, 60, 29, 8, 59, 12, 37, 63, 24, 46, 3, 37, 6, 52, 26, 32, 20, 36, 9, 22, 59, 18, 35, 51, 14, 57, 17, 24, 12, 44, 56, 0, 30, 13, 59, 20, 49, 17, 54, 43, 6, 34, 46, 17, 58, 36, 0, 34, 29, 54, 25, 2, 36, 15, 60, 6, 37, 46, 4, 50, 9, 45 }, \ { 19, 59, 48, 3, 24, 60, 44, 22, 34, 51, 15, 45, 41, 5, 33, 47, 0, 37, 12, 55, 25, 54, 8, 57, 0, 47, 18, 34, 49, 15, 55, 24, 40, 20, 8, 35, 53, 13, 41, 18, 0, 59, 22, 33, 4, 52, 8, 60, 24, 36, 31, 56, 45, 26, 10, 43, 15, 56, 36, 4, 51, 14, 39, 30, 12, 55, 36, 2, 39, 49, 4, 44, 17, 0, 32, 13, 53, 35, 59, 17, 62, 0, 55, 24, 52, 38, 31, 6, 42, 19, 29, 40, 4, 54, 33, 5, 16, 27, 52, 37, 23, 55, 7, 37, 0, 39, 23, 49, 4, 53, 31, 15, 59, 10, 50, 4, 60, 34, 48, 7, 31, 49, 27, 14, 62, 22, 53, 29 }, \ { 46, 21, 14, 51, 36, 17, 7, 57, 10, 32, 3, 37, 22, 60, 39, 18, 56, 20, 42, 3, 36, 10, 44, 26, 41, 29, 53, 27, 2, 39, 30, 52, 0, 59, 15, 48, 23, 61, 6, 58, 37, 12, 40, 49, 16, 39, 20, 44, 0, 62, 8, 21, 3, 59, 23, 32, 49, 31, 12, 44, 22, 59, 18, 50, 24, 7, 43, 52, 15, 23, 41, 26, 51, 28, 55, 39, 21, 27, 10, 42, 12, 45, 27, 47, 3, 15, 63, 26, 55, 0, 60, 26, 45, 18, 62, 38, 58, 49, 8, 47, 4, 33, 46, 29, 57, 13, 56, 16, 59, 21, 5, 47, 23, 39, 18, 44, 13, 22, 28, 53, 19, 0, 58, 32, 41, 7, 26, 13 }, \ { 0, 56, 34, 28, 11, 55, 31, 47, 26, 41, 56, 13, 53, 28, 11, 49, 7, 52, 32, 61, 50, 22, 63, 17, 13, 56, 7, 19, 43, 62, 10, 21, 37, 32, 43, 4, 38, 19, 44, 25, 31, 54, 5, 23, 61, 30, 53, 12, 35, 22, 43, 53, 37, 48, 7, 62, 20, 2, 61, 41, 8, 34, 47, 9, 63, 34, 28, 10, 55, 33, 14, 57, 7, 47, 9, 61, 4, 49, 31, 50, 21, 38, 8, 16, 57, 44, 33, 5, 49, 36, 12, 50, 7, 34, 10, 25, 2, 22, 36, 15, 26, 61, 18, 9, 22, 46, 32, 8, 27, 37, 44, 30, 55, 3, 62, 24, 38, 56, 5, 45, 38, 24, 43, 10, 19, 54, 39, 61 }, \ { 41, 30, 8, 63, 43, 23, 38, 3, 62, 19, 8, 49, 25, 1, 58, 30, 23, 40, 9, 28, 18, 40, 6, 38, 49, 22, 35, 59, 8, 27, 50, 5, 56, 17, 11, 50, 30, 9, 55, 2, 51, 19, 34, 47, 9, 41, 6, 26, 48, 57, 14, 28, 17, 12, 39, 13, 37, 46, 25, 19, 54, 27, 1, 37, 16, 45, 20, 60, 1, 48, 20, 38, 31, 22, 42, 15, 19, 44, 1, 61, 6, 34, 56, 40, 29, 10, 20, 46, 13, 22, 41, 23, 59, 42, 30, 51, 45, 13, 63, 53, 42, 12, 51, 38, 62, 2, 26, 41, 50, 1, 61, 10, 19, 42, 31, 8, 49, 32, 12, 63, 9, 52, 16, 56, 36, 2, 31, 16 }, \ { 52, 5, 47, 20, 1, 53, 12, 50, 16, 35, 43, 21, 33, 43, 16, 44, 3, 59, 14, 46, 1, 30, 60, 33, 2, 45, 12, 42, 31, 47, 14, 33, 46, 25, 55, 27, 60, 36, 16, 42, 14, 46, 26, 1, 55, 15, 63, 32, 2, 38, 5, 47, 33, 61, 30, 52, 4, 57, 6, 38, 11, 43, 61, 24, 52, 3, 31, 22, 42, 10, 62, 3, 59, 11, 35, 57, 33, 54, 24, 14, 29, 48, 18, 2, 60, 41, 53, 24, 32, 62, 3, 53, 15, 1, 55, 17, 32, 40, 6, 31, 1, 40, 28, 5, 35, 52, 19, 63, 13, 33, 17, 41, 52, 26, 15, 57, 1, 20, 42, 17, 35, 27, 48, 5, 25, 50, 44, 11 }, \ { 35, 25, 38, 57, 33, 17, 40, 6, 59, 27, 54, 5, 61, 10, 52, 26, 36, 19, 51, 35, 57, 48, 11, 20, 54, 25, 61, 16, 1, 58, 24, 61, 3, 39, 7, 47, 1, 22, 49, 28, 63, 10, 58, 32, 17, 36, 45, 19, 51, 29, 59, 10, 50, 1, 23, 42, 18, 29, 51, 21, 56, 32, 14, 5, 40, 58, 47, 13, 54, 35, 29, 45, 18, 52, 26, 2, 38, 8, 46, 36, 58, 11, 52, 35, 17, 28, 1, 58, 9, 39, 17, 28, 37, 48, 20, 9, 57, 24, 50, 19, 58, 16, 48, 25, 43, 11, 35, 6, 45, 24, 56, 4, 36, 7, 47, 35, 52, 28, 59, 30, 2, 61, 21, 33, 63, 12, 18, 59 }, \ { 3, 49, 15, 10, 27, 61, 25, 45, 30, 0, 14, 47, 31, 38, 17, 62, 7, 55, 27, 4, 15, 24, 42, 52, 10, 34, 5, 51, 36, 18, 41, 11, 35, 21, 62, 13, 33, 57, 8, 35, 5, 40, 21, 43, 52, 3, 24, 56, 11, 16, 33, 25, 41, 20, 55, 8, 60, 35, 15, 48, 2, 57, 30, 49, 18, 25, 6, 39, 17, 57, 7, 25, 43, 5, 49, 16, 62, 22, 55, 4, 25, 43, 23, 7, 50, 11, 37, 48, 14, 51, 33, 57, 7, 27, 39, 46, 4, 29, 11, 43, 34, 56, 7, 60, 20, 54, 30, 57, 22, 49, 9, 33, 54, 14, 63, 23, 6, 43, 10, 40, 50, 13, 44, 8, 38, 33, 46, 23 }, \ { 55, 39, 22, 50, 44, 4, 36, 9, 52, 23, 37, 59, 21, 2, 46, 13, 31, 41, 11, 45, 62, 29, 6, 37, 19, 48, 30, 23, 44, 7, 53, 28, 54, 16, 41, 29, 44, 18, 52, 24, 60, 15, 48, 7, 27, 59, 9, 34, 42, 54, 7, 63, 4, 46, 31, 27, 45, 0, 40, 26, 34, 17, 37, 10, 53, 29, 36, 50, 2, 27, 51, 11, 61, 37, 23, 41, 30, 7, 18, 50, 39, 14, 63, 32, 45, 61, 19, 30, 25, 44, 2, 47, 23, 63, 11, 34, 59, 37, 60, 3, 22, 14, 44, 30, 15, 0, 47, 15, 3, 38, 61, 20, 27, 45, 11, 39, 51, 16, 55, 3, 22, 54, 29, 58, 1, 57, 6, 29 }, \ { 9, 17, 60, 2, 34, 56, 20, 62, 39, 12, 49, 6, 29, 56, 34, 48, 0, 58, 22, 38, 18, 43, 56, 0, 63, 14, 55, 3, 59, 31, 15, 45, 0, 49, 6, 58, 3, 38, 12, 45, 0, 37, 29, 57, 13, 39, 30, 49, 0, 23, 44, 36, 16, 57, 13, 54, 11, 24, 63, 9, 53, 7, 62, 42, 0, 59, 15, 23, 63, 34, 40, 16, 32, 0, 53, 12, 48, 28, 59, 33, 0, 53, 9, 27, 3, 22, 54, 5, 56, 9, 61, 13, 42, 14, 52, 19, 0, 21, 47, 27, 53, 36, 3, 50, 39, 58, 25, 40, 53, 28, 12, 50, 0, 59, 32, 2, 21, 34, 26, 46, 37, 7, 18, 47, 24, 14, 53, 42 }, \ { 61, 32, 13, 54, 29, 7, 46, 13, 28, 57, 18, 41, 53, 15, 9, 39, 24, 49, 33, 3, 53, 9, 26, 32, 40, 28, 46, 39, 25, 9, 56, 21, 63, 37, 26, 22, 51, 27, 17, 56, 31, 53, 4, 43, 22, 46, 12, 18, 60, 40, 20, 26, 50, 21, 39, 5, 49, 33, 16, 44, 22, 46, 20, 32, 24, 45, 8, 43, 12, 46, 4, 48, 56, 20, 29, 58, 3, 40, 10, 42, 31, 21, 47, 41, 56, 38, 15, 42, 36, 27, 20, 33, 55, 3, 26, 44, 31, 54, 12, 35, 9, 63, 28, 10, 21, 32, 9, 60, 17, 8, 43, 29, 40, 16, 36, 48, 60, 7, 57, 14, 62, 31, 42, 15, 36, 40, 20, 26 }, \ { 0, 37, 47, 23, 41, 18, 32, 48, 1, 35, 8, 25, 4, 26, 63, 20, 54, 8, 16, 61, 35, 23, 51, 15, 58, 7, 12, 20, 50, 34, 42, 4, 38, 10, 32, 47, 8, 60, 41, 20, 9, 25, 50, 19, 62, 1, 37, 56, 28, 8, 53, 11, 3, 58, 34, 43, 19, 60, 38, 4, 58, 31, 3, 51, 11, 55, 38, 30, 21, 58, 19, 26, 9, 44, 36, 13, 46, 20, 62, 24, 13, 60, 5, 28, 12, 34, 7, 59, 0, 53, 45, 6, 38, 30, 50, 7, 62, 16, 41, 5, 46, 18, 55, 42, 51, 5, 45, 23, 34, 48, 19, 58, 5, 25, 54, 19, 13, 41, 28, 21, 0, 49, 10, 60, 4, 51, 9, 45 }, \ { 19, 28, 6, 58, 10, 51, 4, 22, 55, 42, 60, 45, 34, 51, 42, 5, 30, 45, 27, 40, 13, 47, 4, 49, 21, 38, 60, 29, 2, 57, 17, 27, 52, 19, 61, 14, 30, 34, 2, 44, 63, 33, 11, 35, 16, 51, 25, 6, 14, 47, 31, 61, 37, 29, 18, 8, 52, 2, 28, 54, 13, 41, 15, 62, 35, 18, 2, 60, 6, 33, 41, 61, 31, 6, 56, 17, 34, 50, 6, 52, 44, 35, 16, 51, 59, 24, 48, 18, 31, 40, 16, 49, 21, 60, 17, 39, 10, 49, 32, 57, 24, 39, 1, 25, 18, 62, 37, 12, 56, 1, 37, 11, 52, 44, 9, 30, 47, 4, 51, 40, 55, 25, 34, 27, 56, 30, 32, 54 }, \ { 63, 40, 49, 15, 43, 26, 63, 38, 16, 20, 30, 12, 57, 14, 19, 60, 36, 12, 59, 2, 57, 17, 42, 31, 1, 44, 16, 35, 47, 11, 32, 48, 13, 43, 1, 39, 51, 12, 57, 23, 6, 40, 53, 3, 55, 31, 39, 60, 35, 44, 5, 15, 45, 1, 62, 41, 26, 14, 47, 22, 36, 27, 50, 9, 26, 47, 52, 28, 54, 16, 1, 13, 51, 39, 23, 63, 1, 30, 15, 26, 2, 57, 19, 37, 1, 44, 21, 50, 13, 63, 8, 24, 56, 1, 35, 25, 58, 20, 2, 28, 14, 51, 33, 59, 13, 30, 4, 49, 31, 24, 63, 26, 33, 3, 58, 38, 62, 24, 32, 8, 17, 45, 5, 48, 18, 3, 43, 11 }, \ { 21, 4, 24, 34, 59, 1, 37, 11, 53, 5, 47, 2, 22, 40, 32, 1, 24, 50, 21, 29, 38, 25, 63, 8, 55, 24, 53, 6, 62, 23, 59, 3, 54, 20, 58, 24, 5, 46, 15, 38, 48, 14, 27, 42, 23, 7, 46, 10, 17, 58, 25, 52, 23, 32, 49, 12, 55, 30, 40, 7, 59, 1, 56, 21, 39, 4, 23, 15, 37, 46, 55, 42, 21, 4, 48, 8, 45, 54, 37, 55, 32, 8, 46, 10, 30, 54, 4, 41, 25, 29, 36, 48, 11, 43, 14, 47, 5, 43, 53, 36, 61, 10, 45, 6, 41, 54, 27, 43, 16, 55, 6, 46, 18, 42, 23, 15, 1, 45, 12, 60, 37, 22, 62, 12, 39, 59, 16, 52 }, \ { 47, 35, 56, 7, 19, 46, 31, 50, 33, 24, 61, 35, 50, 7, 53, 44, 55, 6, 46, 10, 52, 5, 21, 43, 36, 10, 18, 41, 26, 37, 8, 29, 40, 36, 9, 49, 34, 26, 61, 21, 7, 59, 18, 62, 29, 54, 20, 32, 51, 0, 40, 10, 55, 6, 20, 36, 9, 61, 5, 51, 44, 19, 33, 43, 13, 57, 40, 63, 8, 24, 29, 10, 60, 34, 27, 40, 25, 18, 10, 42, 21, 49, 26, 62, 38, 12, 33, 61, 5, 57, 2, 19, 54, 28, 62, 22, 38, 31, 16, 7, 22, 47, 29, 17, 35, 8, 20, 51, 2, 40, 22, 50, 13, 61, 28, 53, 35, 20, 56, 30, 2, 53, 14, 41, 23, 34, 8, 31 }, \ { 12, 2, 42, 29, 52, 13, 21, 8, 55, 14, 41, 17, 28, 58, 23, 11, 17, 36, 31, 62, 17, 34, 50, 14, 28, 61, 33, 52, 2, 51, 17, 45, 7, 25, 62, 30, 18, 55, 0, 42, 30, 35, 45, 1, 12, 48, 3, 63, 21, 36, 30, 48, 19, 59, 43, 27, 46, 17, 34, 25, 12, 29, 53, 6, 48, 31, 11, 34, 49, 3, 36, 50, 19, 47, 14, 61, 11, 36, 58, 4, 60, 14, 39, 22, 6, 52, 15, 35, 17, 46, 31, 42, 9, 34, 3, 52, 12, 60, 26, 56, 40, 2, 53, 23, 57, 38, 62, 14, 36, 59, 10, 31, 39, 6, 49, 9, 41, 26, 5, 48, 43, 27, 33, 58, 1, 50, 25, 57 }, \ { 61, 37, 15, 61, 3, 39, 58, 43, 26, 0, 44, 10, 47, 3, 37, 63, 28, 43, 13, 39, 3, 57, 30, 59, 0, 48, 5, 43, 13, 22, 60, 33, 55, 15, 42, 4, 52, 10, 45, 13, 54, 4, 24, 49, 37, 26, 41, 14, 42, 9, 61, 13, 38, 23, 3, 53, 0, 58, 21, 42, 63, 10, 17, 61, 25, 0, 58, 28, 17, 44, 57, 12, 27, 0, 55, 5, 52, 28, 23, 47, 29, 0, 43, 17, 58, 28, 47, 23, 55, 10, 58, 23, 51, 40, 18, 33, 45, 0, 49, 8, 32, 61, 19, 48, 0, 26, 7, 47, 29, 18, 44, 0, 56, 34, 20, 59, 15, 51, 37, 18, 10, 52, 7, 20, 46, 9, 38, 17 }, \ { 6, 27, 48, 23, 45, 29, 5, 18, 38, 62, 27, 56, 20, 32, 15, 9, 48, 0, 54, 22, 45, 20, 7, 41, 23, 39, 19, 27, 58, 31, 44, 0, 12, 50, 23, 56, 20, 39, 32, 59, 16, 52, 33, 9, 57, 22, 6, 58, 28, 50, 24, 2, 56, 35, 16, 45, 32, 38, 15, 54, 2, 38, 46, 22, 35, 45, 20, 5, 52, 25, 7, 35, 59, 32, 22, 43, 38, 3, 51, 16, 34, 53, 32, 50, 3, 40, 8, 43, 0, 39, 27, 4, 14, 61, 8, 55, 15, 41, 20, 44, 27, 13, 39, 11, 46, 42, 54, 33, 4, 52, 23, 61, 14, 25, 43, 2, 33, 11, 63, 29, 61, 17, 40, 55, 22, 62, 28, 44 }, \ { 20, 54, 8, 56, 35, 10, 63, 31, 52, 12, 48, 6, 59, 41, 52, 33, 19, 58, 25, 49, 11, 37, 47, 12, 54, 15, 56, 35, 7, 47, 16, 53, 28, 34, 5, 37, 28, 8, 48, 3, 28, 38, 18, 61, 16, 43, 53, 32, 4, 17, 47, 27, 44, 8, 63, 10, 25, 49, 6, 37, 24, 52, 32, 3, 50, 12, 41, 56, 38, 14, 62, 20, 40, 16, 53, 31, 18, 63, 41, 9, 59, 7, 13, 25, 57, 20, 63, 26, 53, 18, 48, 62, 30, 46, 21, 25, 58, 29, 36, 4, 55, 34, 6, 60, 31, 16, 21, 12, 58, 38, 9, 29, 47, 7, 52, 30, 57, 44, 22, 0, 35, 45, 3, 31, 14, 36, 0, 51 }, \ { 42, 14, 33, 24, 16, 49, 40, 2, 22, 33, 16, 36, 25, 1, 21, 61, 38, 8, 33, 4, 62, 26, 29, 60, 6, 46, 30, 11, 63, 4, 36, 40, 19, 57, 46, 11, 41, 63, 22, 25, 58, 10, 46, 2, 34, 27, 11, 38, 56, 34, 12, 53, 18, 33, 41, 51, 13, 28, 60, 20, 47, 14, 29, 59, 16, 62, 8, 22, 32, 47, 9, 49, 2, 44, 7, 12, 45, 6, 20, 27, 45, 24, 62, 42, 36, 11, 33, 15, 37, 7, 32, 10, 37, 1, 35, 50, 6, 11, 63, 24, 52, 15, 50, 24, 3, 37, 56, 27, 34, 22, 49, 16, 36, 62, 17, 39, 4, 15, 54, 24, 50, 8, 58, 26, 49, 54, 11, 30 }, \ { 4, 59, 41, 1, 53, 12, 25, 45, 59, 7, 51, 39, 54, 14, 46, 4, 27, 53, 16, 44, 18, 51, 1, 32, 25, 2, 50, 40, 20, 54, 24, 9, 62, 2, 27, 60, 1, 17, 36, 50, 6, 40, 30, 55, 41, 19, 49, 1, 21, 60, 40, 5, 62, 1, 22, 30, 57, 4, 43, 31, 1, 55, 40, 7, 27, 37, 30, 54, 1, 19, 42, 30, 56, 26, 62, 49, 24, 57, 37, 56, 2, 39, 16, 5, 30, 55, 3, 49, 60, 23, 56, 44, 17, 52, 13, 42, 28, 48, 18, 45, 9, 37, 21, 41, 58, 10, 48, 1, 63, 5, 41, 57, 2, 24, 12, 48, 27, 42, 32, 46, 13, 38, 19, 34, 5, 41, 25, 60 }, \ { 39, 28, 21, 46, 32, 57, 36, 9, 19, 42, 4, 29, 11, 43, 30, 49, 13, 42, 35, 56, 9, 39, 15, 52, 36, 61, 18, 26, 45, 14, 31, 48, 21, 43, 14, 33, 49, 54, 14, 44, 21, 62, 13, 23, 8, 62, 15, 51, 44, 7, 30, 37, 20, 42, 56, 7, 39, 18, 50, 11, 61, 9, 19, 43, 57, 2, 48, 11, 39, 60, 28, 4, 37, 17, 35, 1, 33, 11, 31, 14, 48, 19, 35, 51, 46, 21, 44, 29, 12, 41, 2, 22, 58, 26, 54, 4, 59, 38, 2, 33, 57, 1, 63, 13, 28, 51, 15, 40, 18, 45, 8, 30, 43, 37, 54, 19, 8, 59, 21, 6, 60, 29, 55, 10, 63, 15, 47, 17 }, \ { 3, 50, 10, 62, 18, 5, 27, 49, 60, 23, 55, 18, 62, 24, 56, 10, 59, 28, 2, 23, 34, 59, 43, 20, 10, 42, 8, 49, 1, 37, 57, 6, 51, 29, 53, 7, 23, 31, 5, 32, 51, 0, 35, 54, 45, 31, 5, 26, 36, 24, 55, 15, 48, 29, 14, 48, 26, 60, 21, 41, 36, 26, 50, 33, 14, 44, 17, 24, 52, 15, 46, 23, 54, 6, 47, 21, 60, 50, 4, 53, 29, 61, 8, 23, 1, 60, 19, 6, 53, 16, 47, 34, 6, 39, 16, 31, 12, 20, 53, 22, 30, 43, 25, 46, 35, 6, 44, 32, 53, 26, 55, 19, 11, 59, 5, 33, 51, 1, 35, 53, 25, 3, 42, 23, 44, 32, 7, 53 }, \ { 22, 44, 37, 6, 26, 51, 38, 0, 34, 13, 31, 46, 3, 37, 6, 19, 40, 21, 47, 63, 12, 5, 29, 55, 22, 58, 34, 28, 60, 22, 11, 41, 17, 38, 9, 44, 59, 39, 56, 19, 11, 47, 25, 15, 3, 39, 57, 17, 61, 11, 46, 3, 58, 9, 54, 35, 2, 34, 8, 45, 15, 56, 5, 23, 53, 33, 63, 35, 4, 59, 10, 51, 13, 61, 29, 41, 15, 25, 43, 19, 40, 10, 54, 33, 41, 12, 38, 51, 31, 26, 61, 9, 30, 45, 24, 62, 49, 40, 10, 61, 14, 49, 5, 17, 54, 20, 60, 23, 3, 13, 35, 50, 32, 23, 46, 27, 38, 63, 16, 12, 39, 48, 18, 51, 1, 27, 56, 35 }, \ { 63, 15, 30, 55, 43, 14, 57, 17, 53, 44, 7, 48, 26, 50, 32, 60, 0, 53, 14, 31, 50, 24, 46, 0, 38, 13, 4, 52, 16, 45, 30, 59, 0, 25, 55, 35, 16, 10, 26, 42, 58, 29, 60, 38, 50, 22, 28, 47, 0, 50, 28, 19, 33, 39, 11, 44, 16, 52, 24, 59, 3, 38, 27, 51, 0, 21, 7, 42, 26, 34, 21, 40, 33, 18, 39, 3, 54, 38, 8, 59, 0, 44, 27, 15, 58, 28, 57, 9, 43, 0, 36, 50, 20, 59, 8, 34, 0, 27, 47, 7, 36, 19, 56, 32, 0, 38, 11, 29, 62, 47, 6, 61, 0, 41, 14, 56, 10, 23, 45, 31, 57, 8, 36, 13, 58, 38, 11, 19 }, \ { 0, 34, 12, 47, 21, 2, 40, 30, 11, 25, 61, 20, 40, 15, 35, 22, 45, 36, 7, 41, 17, 57, 9, 48, 32, 62, 44, 24, 35, 3, 54, 13, 33, 63, 19, 4, 48, 22, 62, 2, 37, 8, 33, 6, 20, 52, 9, 32, 43, 13, 39, 63, 25, 4, 49, 23, 62, 32, 9, 30, 48, 18, 63, 12, 46, 29, 58, 13, 48, 8, 57, 31, 0, 51, 9, 58, 12, 22, 47, 29, 35, 22, 49, 5, 46, 4, 34, 20, 63, 24, 56, 11, 41, 3, 51, 19, 56, 35, 17, 58, 28, 42, 9, 45, 59, 26, 51, 42, 17, 36, 25, 15, 53, 21, 44, 3, 30, 55, 5, 50, 21, 28, 61, 32, 6, 49, 28, 46 }, \ { 58, 42, 60, 4, 31, 59, 22, 63, 35, 38, 9, 54, 1, 57, 8, 51, 16, 58, 27, 53, 3, 38, 30, 15, 27, 6, 19, 56, 10, 50, 21, 36, 47, 5, 43, 28, 51, 32, 13, 46, 18, 54, 16, 43, 63, 12, 36, 59, 22, 34, 5, 52, 17, 59, 27, 41, 0, 19, 55, 37, 13, 43, 6, 34, 41, 10, 36, 55, 19, 44, 3, 16, 58, 27, 49, 25, 32, 62, 17, 55, 13, 63, 18, 52, 25, 37, 17, 48, 13, 32, 5, 46, 28, 37, 14, 43, 25, 5, 51, 39, 3, 52, 33, 22, 8, 40, 12, 4, 57, 9, 46, 39, 28, 58, 13, 62, 17, 42, 19, 36, 0, 47, 16, 43, 24, 21, 54, 13 }, \ { 25, 9, 23, 50, 36, 8, 45, 14, 3, 51, 16, 28, 44, 12, 42, 29, 4, 26, 10, 47, 22, 61, 18, 54, 51, 39, 46, 13, 41, 26, 58, 7, 18, 39, 12, 57, 15, 1, 52, 27, 41, 23, 48, 1, 27, 45, 18, 2, 57, 26, 55, 8, 43, 31, 6, 58, 14, 51, 40, 5, 61, 31, 24, 54, 17, 60, 22, 1, 39, 30, 53, 45, 36, 13, 43, 5, 45, 2, 37, 6, 34, 42, 2, 39, 10, 62, 7, 54, 40, 18, 60, 15, 52, 21, 63, 8, 55, 46, 15, 30, 23, 13, 62, 16, 50, 24, 58, 31, 48, 21, 34, 2, 49, 7, 31, 37, 26, 48, 9, 61, 40, 11, 52, 2, 60, 40, 4, 37 }, \ { 52, 28, 39, 16, 54, 19, 29, 55, 42, 20, 58, 33, 24, 63, 18, 55, 39, 62, 43, 34, 12, 40, 6, 35, 2, 25, 8, 62, 34, 1, 31, 42, 61, 27, 53, 24, 40, 61, 34, 8, 59, 4, 30, 56, 40, 6, 53, 42, 10, 48, 16, 37, 12, 46, 21, 36, 47, 11, 28, 45, 22, 10, 57, 2, 49, 31, 14, 44, 61, 11, 25, 6, 23, 63, 18, 36, 28, 56, 20, 51, 11, 48, 27, 56, 32, 22, 45, 30, 2, 42, 27, 39, 1, 44, 23, 31, 38, 22, 11, 61, 43, 54, 4, 47, 35, 2, 44, 16, 28, 54, 12, 62, 18, 43, 10, 52, 1, 58, 33, 15, 29, 56, 20, 34, 9, 30, 48, 17 }, \ { 46, 2, 56, 11, 41, 1, 49, 6, 27, 47, 2, 48, 5, 32, 37, 3, 13, 19, 32, 1, 55, 28, 60, 17, 43, 59, 32, 20, 49, 16, 55, 23, 14, 46, 2, 36, 6, 30, 20, 49, 12, 47, 35, 14, 21, 60, 29, 14, 35, 24, 46, 1, 56, 29, 53, 8, 33, 23, 56, 1, 35, 46, 20, 39, 26, 4, 53, 28, 17, 38, 60, 34, 48, 9, 55, 15, 46, 7, 41, 31, 60, 24, 16, 36, 1, 59, 19, 52, 35, 6, 55, 11, 59, 33, 7, 57, 4, 29, 48, 1, 19, 26, 37, 30, 18, 63, 37, 6, 59, 1, 40, 24, 56, 33, 46, 22, 35, 7, 24, 53, 39, 5, 26, 45, 55, 18, 62, 7 }, \ { 20, 60, 29, 34, 20, 62, 33, 52, 10, 36, 13, 60, 41, 21, 50, 27, 56, 49, 8, 51, 21, 45, 11, 48, 8, 23, 53, 3, 29, 44, 5, 52, 9, 32, 50, 17, 43, 56, 3, 38, 24, 10, 62, 25, 51, 9, 33, 49, 61, 7, 30, 62, 22, 19, 2, 42, 63, 5, 49, 18, 60, 15, 52, 7, 43, 56, 23, 50, 5, 50, 2, 20, 41, 30, 1, 52, 22, 61, 14, 26, 3, 43, 53, 7, 47, 28, 11, 14, 23, 58, 33, 25, 47, 13, 50, 17, 40, 54, 34, 60, 41, 6, 59, 14, 50, 7, 25, 55, 20, 42, 51, 8, 27, 4, 16, 60, 28, 50, 44, 3, 22, 49, 63, 12, 33, 1, 43, 31 }, \ { 36, 5, 46, 8, 44, 24, 13, 39, 25, 57, 31, 18, 8, 52, 10, 45, 6, 30, 36, 24, 63, 4, 33, 26, 57, 40, 15, 56, 37, 12, 40, 25, 37, 58, 11, 63, 21, 45, 16, 60, 31, 53, 18, 33, 3, 45, 23, 0, 20, 54, 40, 15, 50, 38, 60, 16, 25, 42, 29, 38, 7, 41, 25, 62, 18, 33, 8, 35, 42, 16, 32, 56, 12, 39, 59, 19, 34, 9, 49, 38, 57, 12, 21, 50, 14, 40, 61, 44, 50, 9, 49, 19, 3, 29, 35, 62, 12, 24, 7, 18, 52, 32, 10, 46, 21, 41, 32, 11, 36, 29, 14, 34, 60, 38, 54, 11, 41, 14, 19, 57, 32, 16, 7, 41, 51, 25, 14, 57 }, \ { 53, 18, 26, 50, 15, 58, 4, 63, 17, 43, 7, 40, 61, 35, 15, 41, 23, 60, 16, 38, 14, 42, 19, 50, 0, 31, 10, 46, 27, 63, 18, 60, 0, 20, 29, 39, 8, 26, 37, 5, 42, 0, 44, 39, 57, 17, 58, 41, 28, 37, 4, 32, 9, 44, 12, 31, 54, 10, 59, 14, 27, 53, 12, 36, 0, 47, 13, 63, 21, 58, 10, 24, 50, 27, 4, 26, 44, 53, 31, 0, 18, 42, 29, 33, 57, 4, 32, 26, 0, 38, 16, 61, 41, 53, 20, 0, 42, 44, 49, 27, 10, 56, 39, 0, 57, 15, 53, 49, 3, 61, 22, 47, 17, 5, 49, 26, 2, 63, 39, 10, 47, 27, 37, 23, 4, 59, 38, 10 }, \ { 23, 39, 61, 3, 37, 28, 48, 31, 0, 34, 51, 23, 2, 26, 58, 0, 53, 11, 46, 1, 57, 29, 52, 14, 37, 61, 21, 35, 2, 49, 7, 34, 47, 55, 4, 33, 54, 13, 58, 52, 19, 50, 22, 7, 13, 29, 36, 11, 51, 17, 60, 25, 55, 4, 34, 51, 0, 35, 20, 48, 32, 3, 51, 30, 59, 28, 40, 3, 46, 29, 54, 43, 7, 62, 47, 11, 39, 4, 23, 46, 55, 8, 63, 5, 25, 37, 18, 46, 21, 56, 31, 5, 36, 8, 45, 58, 26, 15, 2, 36, 47, 21, 29, 44, 25, 34, 3, 27, 43, 10, 52, 0, 45, 30, 24, 36, 43, 18, 34, 59, 0, 52, 61, 15, 44, 19, 30, 49 }, \ { 0, 27, 12, 43, 54, 9, 22, 53, 21, 46, 15, 55, 29, 47, 20, 33, 39, 28, 59, 35, 9, 44, 5, 24, 47, 7, 52, 17, 56, 22, 30, 42, 14, 26, 45, 18, 49, 1, 24, 34, 11, 27, 55, 32, 61, 47, 2, 56, 6, 44, 13, 47, 36, 27, 58, 22, 16, 47, 40, 4, 57, 38, 21, 45, 16, 9, 56, 26, 11, 38, 0, 22, 36, 17, 33, 57, 16, 30, 62, 15, 35, 40, 20, 45, 59, 10, 54, 8, 63, 13, 52, 27, 22, 57, 28, 12, 32, 51, 55, 22, 63, 4, 16, 54, 12, 62, 45, 19, 58, 13, 32, 40, 20, 56, 7, 57, 9, 54, 6, 29, 42, 21, 8, 55, 35, 47, 6, 41 }, \ { 56, 33, 58, 32, 19, 35, 42, 6, 59, 11, 38, 5, 49, 12, 62, 7, 52, 17, 5, 25, 54, 20, 61, 31, 54, 27, 41, 11, 44, 5, 59, 12, 36, 51, 10, 61, 28, 41, 48, 9, 43, 63, 5, 40, 20, 8, 49, 26, 34, 21, 58, 1, 18, 45, 7, 39, 61, 26, 8, 50, 23, 10, 63, 5, 55, 37, 19, 49, 52, 15, 59, 47, 13, 54, 1, 25, 42, 58, 10, 48, 3, 27, 50, 1, 17, 48, 34, 41, 16, 40, 2, 45, 10, 39, 17, 61, 5, 38, 19, 9, 41, 31, 60, 38, 5, 23, 36, 8, 30, 55, 24, 63, 12, 48, 14, 51, 31, 20, 45, 25, 12, 50, 32, 2, 28, 11, 62, 14 }, \ { 44, 16, 7, 48, 1, 62, 16, 50, 27, 33, 61, 25, 17, 44, 31, 14, 22, 43, 32, 48, 18, 40, 8, 36, 3, 16, 33, 62, 23, 38, 25, 53, 2, 21, 41, 6, 22, 15, 59, 29, 16, 37, 26, 15, 52, 42, 23, 15, 54, 39, 10, 30, 53, 11, 49, 24, 2, 43, 55, 17, 34, 44, 15, 31, 24, 44, 2, 32, 7, 35, 25, 5, 40, 45, 29, 51, 6, 21, 37, 52, 24, 60, 13, 31, 53, 23, 2, 28, 49, 24, 31, 60, 20, 51, 1, 34, 48, 14, 59, 33, 50, 1, 18, 33, 48, 60, 17, 51, 39, 6, 38, 2, 35, 29, 40, 23, 1, 62, 15, 53, 37, 17, 46, 57, 40, 51, 24, 22 }, \ { 5, 37, 52, 24, 45, 13, 40, 3, 45, 9, 19, 42, 56, 4, 37, 46, 56, 2, 63, 11, 51, 1, 49, 13, 59, 45, 39, 1, 48, 15, 58, 9, 46, 31, 54, 35, 57, 38, 3, 46, 56, 4, 47, 57, 1, 30, 38, 63, 3, 46, 28, 63, 41, 14, 33, 62, 19, 32, 13, 28, 61, 1, 53, 42, 11, 60, 22, 62, 27, 42, 61, 31, 19, 8, 61, 12, 32, 55, 2, 18, 33, 12, 43, 36, 9, 62, 30, 55, 6, 58, 35, 7, 43, 29, 54, 23, 43, 30, 3, 25, 11, 45, 52, 28, 7, 14, 42, 1, 22, 50, 16, 53, 19, 59, 4, 46, 33, 41, 4, 35, 58, 5, 26, 13, 20, 2, 34, 54 }, \ { 30, 63, 21, 10, 26, 55, 29, 59, 23, 39, 53, 1, 36, 24, 59, 27, 10, 34, 23, 38, 30, 60, 22, 42, 28, 19, 9, 57, 30, 19, 43, 33, 13, 63, 3, 19, 11, 50, 31, 20, 14, 34, 10, 35, 17, 59, 7, 31, 19, 25, 50, 5, 20, 57, 29, 6, 52, 41, 4, 46, 20, 37, 26, 17, 49, 6, 39, 18, 53, 14, 3, 49, 57, 23, 34, 48, 14, 41, 28, 38, 56, 6, 58, 25, 39, 19, 43, 15, 37, 11, 47, 18, 53, 4, 37, 9, 62, 21, 53, 40, 57, 24, 13, 40, 56, 26, 47, 31, 59, 25, 45, 27, 10, 43, 21, 61, 13, 27, 48, 9, 23, 43, 31, 62, 38, 59, 9, 47 }, \ { 25, 4, 40, 60, 34, 6, 18, 36, 8, 57, 12, 30, 49, 14, 6, 54, 41, 16, 50, 6, 43, 15, 34, 4, 53, 24, 50, 35, 4, 51, 7, 55, 28, 24, 39, 44, 60, 7, 25, 62, 42, 53, 24, 61, 28, 45, 52, 12, 48, 37, 9, 35, 43, 3, 37, 48, 12, 58, 30, 52, 9, 59, 6, 57, 33, 29, 48, 4, 37, 45, 20, 34, 10, 39, 0, 60, 22, 45, 8, 63, 21, 42, 14, 49, 3, 56, 11, 46, 21, 61, 0, 42, 25, 13, 63, 17, 36, 8, 46, 16, 6, 35, 63, 0, 21, 37, 4, 57, 9, 34, 5, 61, 48, 32, 8, 37, 54, 17, 56, 30, 60, 0, 50, 16, 7, 29, 42, 17 }, \ { 32, 50, 15, 48, 2, 43, 52, 25, 47, 16, 32, 63, 21, 52, 40, 19, 0, 61, 29, 58, 20, 56, 26, 46, 12, 55, 6, 22, 62, 32, 17, 40, 0, 49, 34, 8, 27, 32, 48, 0, 21, 39, 5, 44, 12, 6, 22, 40, 0, 57, 16, 60, 23, 17, 54, 22, 36, 15, 24, 39, 19, 34, 47, 23, 0, 54, 13, 51, 24, 9, 55, 16, 52, 27, 44, 20, 4, 54, 26, 49, 0, 30, 46, 16, 29, 51, 34, 4, 52, 28, 33, 15, 57, 39, 26, 49, 0, 56, 27, 31, 48, 20, 43, 29, 53, 11, 46, 19, 41, 13, 55, 18, 0, 57, 26, 51, 2, 44, 6, 38, 14, 40, 22, 45, 36, 53, 3, 57 }, \ { 44, 12, 37, 28, 22, 57, 11, 38, 0, 51, 9, 41, 4, 29, 11, 47, 33, 45, 12, 26, 3, 36, 9, 63, 31, 16, 38, 44, 14, 47, 25, 61, 20, 58, 15, 47, 17, 57, 13, 36, 9, 51, 18, 29, 50, 36, 54, 20, 61, 27, 32, 13, 53, 44, 9, 27, 0, 63, 45, 2, 56, 10, 14, 43, 41, 28, 58, 11, 35, 60, 30, 41, 6, 63, 11, 51, 37, 32, 15, 10, 35, 53, 5, 61, 22, 7, 26, 59, 23, 9, 44, 48, 21, 3, 51, 32, 24, 41, 12, 61, 2, 55, 9, 15, 35, 58, 28, 15, 62, 30, 37, 23, 42, 29, 11, 17, 35, 24, 63, 20, 52, 28, 8, 55, 11, 23, 47, 19 }, \ { 0, 56, 8, 53, 14, 31, 61, 20, 55, 28, 62, 18, 35, 60, 25, 57, 7, 23, 39, 54, 47, 17, 43, 0, 40, 59, 29, 2, 56, 10, 37, 5, 43, 11, 29, 52, 1, 23, 54, 41, 59, 30, 55, 1, 62, 15, 33, 4, 43, 10, 47, 39, 1, 31, 40, 60, 49, 33, 7, 55, 26, 50, 31, 61, 8, 18, 21, 32, 44, 1, 25, 47, 18, 36, 30, 23, 59, 7, 40, 59, 27, 19, 38, 32, 44, 54, 40, 17, 38, 60, 27, 6, 35, 55, 10, 14, 44, 5, 50, 17, 38, 26, 42, 50, 18, 3, 44, 52, 2, 49, 7, 52, 15, 46, 62, 39, 55, 10, 31, 48, 3, 58, 33, 18, 61, 34, 13, 59 }, \ { 39, 27, 63, 20, 35, 41, 4, 45, 26, 5, 38, 13, 44, 2, 50, 17, 37, 52, 2, 13, 28, 58, 24, 51, 21, 8, 34, 48, 27, 42, 18, 51, 31, 56, 5, 36, 38, 44, 4, 17, 26, 11, 38, 23, 42, 8, 56, 39, 24, 51, 5, 56, 21, 59, 14, 6, 18, 42, 22, 35, 16, 37, 3, 25, 39, 46, 63, 5, 50, 17, 58, 8, 55, 3, 50, 12, 43, 17, 47, 2, 51, 9, 62, 12, 1, 35, 13, 50, 1, 37, 12, 51, 19, 29, 46, 59, 22, 58, 33, 45, 22, 60, 10, 32, 61, 39, 8, 33, 25, 36, 20, 60, 38, 4, 21, 5, 28, 45, 12, 18, 42, 11, 49, 1, 27, 40, 6, 30 }, \ { 24, 16, 42, 1, 50, 10, 48, 17, 33, 43, 24, 48, 21, 55, 31, 42, 10, 21, 63, 35, 49, 6, 33, 13, 41, 53, 10, 20, 60, 6, 53, 26, 12, 41, 22, 60, 14, 28, 63, 33, 49, 3, 45, 16, 48, 26, 14, 46, 18, 30, 35, 26, 8, 50, 29, 51, 25, 57, 12, 47, 53, 9, 62, 20, 54, 2, 36, 15, 40, 28, 33, 13, 38, 24, 46, 1, 29, 56, 33, 20, 44, 24, 41, 26, 57, 20, 63, 8, 30, 55, 5, 41, 62, 8, 34, 2, 37, 10, 19, 6, 37, 1, 53, 23, 5, 27, 58, 22, 43, 12, 50, 26, 9, 34, 54, 32, 49, 1, 59, 37, 22, 46, 25, 36, 51, 15, 54, 46 }, \ { 52, 7, 45, 33, 26, 58, 14, 60, 7, 54, 3, 58, 8, 34, 14, 5, 59, 30, 18, 44, 8, 22, 48, 62, 3, 26, 55, 38, 23, 16, 39, 1, 62, 24, 49, 9, 53, 19, 46, 7, 19, 60, 31, 58, 2, 34, 53, 7, 59, 2, 62, 42, 46, 19, 36, 11, 44, 4, 38, 28, 1, 43, 32, 51, 12, 29, 56, 22, 52, 2, 62, 49, 22, 60, 14, 35, 63, 5, 25, 57, 14, 53, 4, 46, 18, 31, 42, 22, 47, 20, 58, 31, 16, 43, 23, 54, 30, 42, 52, 57, 29, 49, 30, 13, 45, 48, 16, 55, 6, 63, 1, 44, 14, 58, 19, 47, 15, 24, 51, 34, 6, 55, 5, 63, 20, 41, 21, 9 }, \ { 30, 62, 18, 55, 5, 23, 39, 29, 49, 30, 15, 36, 28, 46, 60, 25, 39, 46, 4, 32, 61, 40, 15, 30, 36, 45, 14, 2, 49, 33, 57, 45, 18, 32, 3, 45, 30, 2, 35, 52, 40, 27, 13, 21, 38, 63, 20, 28, 37, 23, 16, 10, 13, 55, 2, 62, 21, 32, 60, 17, 58, 23, 5, 40, 16, 48, 7, 45, 10, 26, 43, 19, 6, 31, 52, 21, 39, 16, 48, 9, 37, 28, 36, 55, 7, 48, 3, 59, 15, 45, 25, 1, 53, 13, 47, 7, 62, 15, 4, 25, 12, 41, 18, 60, 38, 11, 34, 19, 39, 31, 29, 56, 23, 42, 3, 27, 60, 41, 8, 16, 61, 29, 43, 9, 32, 2, 60, 34 }, \ { 3, 38, 13, 37, 52, 44, 2, 19, 12, 42, 63, 19, 40, 1, 20, 50, 12, 55, 15, 56, 27, 1, 54, 11, 57, 18, 32, 63, 44, 4, 29, 13, 37, 61, 35, 16, 42, 57, 12, 22, 6, 55, 43, 10, 50, 5, 44, 11, 48, 52, 34, 58, 28, 41, 38, 30, 7, 52, 11, 49, 30, 14, 45, 27, 59, 34, 21, 38, 32, 58, 11, 36, 56, 42, 9, 41, 3, 54, 31, 42, 0, 60, 16, 11, 39, 24, 52, 33, 6, 36, 10, 40, 32, 60, 26, 20, 39, 28, 47, 34, 63, 8, 54, 3, 24, 56, 0, 51, 13, 47, 16, 40, 7, 35, 52, 11, 36, 4, 57, 30, 39, 13, 18, 50, 58, 28, 12, 48 }, \ { 57, 24, 49, 21, 10, 31, 61, 36, 56, 0, 22, 53, 11, 56, 32, 7, 36, 27, 41, 9, 46, 19, 34, 42, 25, 7, 50, 9, 28, 21, 54, 8, 50, 7, 27, 59, 10, 25, 48, 62, 37, 0, 33, 58, 25, 18, 32, 61, 0, 15, 45, 5, 50, 3, 23, 55, 47, 17, 40, 6, 60, 34, 53, 8, 41, 0, 61, 13, 54, 4, 46, 28, 0, 17, 48, 27, 58, 13, 23, 61, 33, 21, 50, 30, 62, 8, 14, 29, 56, 27, 61, 49, 17, 2, 44, 11, 51, 0, 59, 17, 40, 20, 32, 47, 36, 21, 42, 28, 60, 4, 54, 10, 59, 17, 30, 62, 21, 43, 26, 48, 0, 56, 36, 25, 8, 44, 39, 17 }, \ { 10, 42, 4, 59, 27, 47, 8, 23, 51, 32, 45, 6, 37, 26, 48, 43, 62, 0, 21, 53, 38, 12, 51, 5, 60, 47, 24, 37, 59, 15, 35, 47, 22, 55, 0, 50, 21, 40, 6, 29, 15, 52, 24, 8, 41, 55, 13, 29, 40, 56, 24, 31, 19, 33, 61, 15, 0, 35, 24, 42, 21, 2, 19, 57, 24, 15, 30, 50, 20, 25, 40, 16, 57, 34, 61, 8, 29, 45, 6, 49, 11, 47, 2, 44, 19, 57, 38, 50, 12, 42, 21, 4, 35, 52, 28, 56, 23, 36, 13, 45, 4, 52, 27, 14, 6, 62, 9, 45, 21, 37, 25, 46, 33, 49, 0, 44, 7, 53, 13, 19, 53, 31, 3, 47, 15, 56, 22, 51 }, \ { 35, 28, 53, 32, 1, 16, 54, 40, 9, 17, 25, 58, 14, 59, 3, 22, 16, 51, 31, 5, 23, 58, 28, 17, 35, 20, 0, 42, 11, 52, 3, 31, 41, 17, 43, 13, 32, 54, 18, 60, 32, 45, 17, 49, 2, 36, 51, 22, 7, 36, 9, 63, 48, 12, 46, 26, 43, 28, 63, 13, 48, 37, 51, 33, 5, 47, 55, 9, 42, 63, 7, 51, 24, 12, 37, 19, 55, 34, 18, 38, 15, 28, 54, 34, 5, 43, 22, 0, 48, 14, 54, 24, 58, 9, 38, 5, 32, 55, 21, 30, 49, 9, 59, 43, 30, 51, 35, 26, 7, 53, 2, 22, 14, 27, 57, 18, 38, 24, 33, 45, 10, 41, 20, 60, 37, 5, 32, 0 }, \ { 63, 19, 15, 40, 62, 35, 14, 28, 46, 61, 4, 49, 35, 10, 29, 54, 33, 8, 45, 62, 37, 1, 43, 55, 10, 52, 61, 30, 19, 40, 25, 62, 11, 38, 27, 58, 36, 3, 46, 8, 39, 4, 62, 28, 47, 20, 4, 54, 47, 27, 43, 1, 21, 38, 8, 58, 10, 54, 4, 56, 9, 26, 12, 39, 60, 27, 18, 37, 1, 31, 35, 5, 45, 50, 2, 43, 26, 1, 59, 23, 56, 40, 7, 26, 58, 17, 32, 63, 25, 39, 7, 31, 45, 19, 63, 15, 48, 8, 37, 61, 16, 34, 1, 56, 18, 3, 15, 58, 49, 32, 63, 41, 55, 5, 40, 22, 50, 6, 59, 2, 63, 23, 52, 11, 26, 61, 44, 23 }, \ { 11, 56, 46, 6, 22, 43, 58, 3, 34, 21, 38, 30, 18, 44, 52, 13, 41, 57, 17, 28, 14, 49, 25, 7, 33, 39, 26, 6, 56, 48, 1, 20, 56, 5, 46, 9, 19, 51, 30, 25, 56, 21, 35, 14, 57, 42, 16, 33, 10, 57, 17, 59, 41, 25, 53, 37, 20, 40, 30, 18, 31, 62, 44, 22, 3, 44, 11, 48, 23, 53, 18, 60, 29, 22, 62, 15, 53, 47, 10, 41, 3, 19, 52, 36, 13, 46, 10, 35, 3, 61, 41, 16, 1, 50, 26, 42, 18, 46, 2, 25, 54, 20, 39, 23, 47, 31, 41, 12, 38, 17, 8, 19, 31, 48, 12, 61, 9, 54, 29, 35, 15, 38, 6, 43, 34, 14, 7, 47 }, \ { 39, 2, 33, 26, 53, 8, 18, 50, 41, 12, 53, 1, 63, 24, 19, 39, 2, 24, 47, 10, 60, 38, 19, 63, 48, 4, 15, 45, 32, 14, 60, 36, 29, 53, 23, 63, 34, 12, 61, 1, 43, 11, 53, 30, 1, 26, 60, 45, 23, 39, 3, 29, 12, 50, 4, 16, 51, 3, 45, 36, 50, 1, 16, 54, 35, 14, 57, 30, 58, 9, 46, 14, 41, 10, 32, 38, 4, 30, 21, 51, 32, 63, 25, 1, 60, 27, 53, 18, 51, 22, 28, 55, 34, 12, 40, 3, 60, 29, 57, 41, 6, 44, 11, 53, 8, 61, 24, 57, 1, 28, 44, 59, 36, 3, 34, 25, 41, 31, 16, 44, 22, 47, 28, 58, 1, 49, 54, 29 }, \ { 58, 25, 50, 13, 38, 30, 60, 24, 6, 57, 27, 42, 9, 45, 6, 61, 30, 50, 4, 34, 29, 3, 46, 13, 22, 42, 58, 28, 9, 39, 23, 44, 7, 15, 44, 2, 40, 15, 47, 41, 23, 37, 7, 59, 38, 11, 34, 6, 62, 14, 52, 35, 55, 19, 32, 61, 33, 24, 57, 6, 22, 59, 29, 7, 49, 25, 40, 3, 17, 39, 27, 52, 0, 55, 16, 57, 24, 61, 36, 6, 29, 12, 48, 39, 20, 44, 6, 40, 33, 5, 48, 10, 57, 36, 22, 51, 33, 9, 24, 12, 62, 29, 50, 35, 14, 43, 5, 33, 47, 52, 13, 23, 10, 51, 56, 16, 46, 1, 49, 4, 61, 9, 52, 18, 31, 21, 36, 17 }, \ { 19, 42, 9, 48, 2, 44, 11, 37, 48, 20, 33, 16, 55, 35, 49, 15, 37, 20, 59, 16, 53, 22, 56, 31, 50, 11, 34, 54, 16, 51, 4, 49, 33, 53, 21, 28, 56, 24, 31, 9, 52, 16, 48, 24, 44, 13, 51, 20, 31, 49, 18, 6, 34, 2, 44, 14, 47, 8, 15, 43, 13, 41, 33, 52, 20, 61, 7, 51, 34, 62, 4, 20, 36, 33, 43, 8, 46, 13, 53, 17, 45, 42, 9, 31, 52, 11, 30, 56, 13, 59, 17, 44, 27, 6, 62, 11, 43, 17, 49, 38, 26, 2, 16, 27, 58, 21, 54, 18, 26, 5, 35, 61, 43, 27, 7, 39, 14, 58, 37, 55, 20, 33, 13, 40, 62, 10, 55, 5 }, \ { 51, 14, 61, 29, 59, 20, 55, 31, 0, 49, 11, 60, 3, 26, 22, 56, 0, 40, 12, 43, 41, 8, 36, 0, 17, 57, 24, 2, 46, 26, 61, 18, 0, 38, 12, 59, 6, 49, 3, 57, 19, 63, 5, 33, 18, 54, 28, 56, 0, 43, 26, 46, 63, 27, 56, 22, 27, 54, 38, 28, 63, 24, 10, 45, 0, 31, 42, 21, 12, 25, 44, 49, 59, 6, 26, 50, 3, 34, 27, 59, 0, 35, 62, 16, 4, 58, 47, 0, 43, 24, 37, 2, 54, 20, 46, 31, 0, 56, 34, 5, 55, 45, 60, 37, 0, 40, 10, 38, 63, 46, 15, 20, 0, 53, 21, 62, 30, 11, 24, 27, 40, 0, 57, 26, 3, 45, 27, 35 }, \ } #endif fvwm-2.7.0/libs/XError.h0000644000175000017500000000070514147024700011744 00000000000000#ifndef FERROR_H #define FERROR_H void do_coredump(void); /* not really a wrapper, but useful and X related */ void PrintXErrorAndCoredump(Display *dpy, XErrorEvent *error, char *MyName); typedef int (*ferror_handler_t)(Display *, XErrorEvent *); void ferror_set_temp_error_handler(ferror_handler_t new_handler); void ferror_reset_temp_error_handler(void); int ferror_call_next_error_handler(Display *dpy, XErrorEvent *error); #endif /* FERROR_H */ fvwm-2.7.0/libs/fvwmsignal.c0000644000175000017500000001376114147024700012701 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* * fvwmsignal.c * Written by Chris Rankin, rankinc@zipworld.com.au * */ #include "config.h" #include #include #include #include "fvwmsignal.h" #define true 1 #define false 0 typedef enum { SIG_INIT=0, SIG_DONE } SIG_STATUS; volatile sig_atomic_t isTerminated = false; static volatile sig_atomic_t canJump = false; #ifdef HAVE_SIGSETJMP static sigjmp_buf deadJump; #define SIGSETJMP(env, savesigs) sigsetjmp(env, savesigs) #else static jmp_buf deadJump; #define SIGSETJMP(env, savesigs) setjmp(env) #endif #if defined(HAVE_SIGLONGJMP) && defined(HAVE_SIGSETJMP) #define SIGLONGJMP(env, val) siglongjmp(env, val) #else #define SIGLONGJMP(env, val) longjmp(env, val) #endif /* * Reap child processes, preventing them from becoming zombies. * We do this asynchronously within the SIGCHLD handler so that * "it just happens". */ RETSIGTYPE fvwmReapChildren(int sig) { (void)sig; BSD_BLOCK_SIGNALS; /* * This is a signal handler, AND SO MUST BE REENTRANT! * Now the wait() functions are safe here, but please don't * add anything unless you're SURE that the new functions * (plus EVERYTHING they call) are also reentrant. There * are very few functions which are truly safe. */ #if HAVE_WAITPID while (waitpid(-1, NULL, WNOHANG) > 0) { /* nothing to do here */ } #elif HAVE_WAIT3 while (wait3(NULL, WNOHANG, NULL) > 0) { /* nothing to do here */ } #else # error One of waitpid or wait3 is needed. #endif BSD_UNBLOCK_SIGNALS; SIGNAL_RETURN; } #ifdef USE_BSD_SIGNALS static int term_sigs; /* * fvwmSetSignalMask - store the set of mutually exclusive signals * away for future reference. This prevents different signals from * trying to access the same static data at the same time. * * NOTE: We don't need this if we have POSIX.1 since we can install * a signal mask automatically using sigaction() */ void fvwmSetSignalMask(int sigmask) { term_sigs = sigmask; } /* * fvwmGetSignalMask - get the set of signals that will terminate fvwm * * NOTE: We don't need this if we have POSIX.1 since we can install * a signal mask automatically using sigaction() */ int fvwmGetSignalMask(void) { return term_sigs; } #endif /* * fvwmSetTerminate - set the "end-of-execution" flag. * This function should ONLY be called at the end of a * signal handler. It is an integral part of the mechanism * to stop system calls from blocking once the process is * finished. * * NOTE: This is NOT a signal handler function in its own right! */ void fvwmSetTerminate(int sig) { BSD_BLOCK_SIGNALS; isTerminated = true; if (canJump) { canJump = false; /* * This non-local jump is safe ONLY because we haven't called * any non-reentrant functions in the short period where the * "canJump" variable is true. * * NOTE: No need to restore the signal mask, since siglongjmp * is designed to do that for us. */ SIGLONGJMP(deadJump, SIG_DONE); } BSD_UNBLOCK_SIGNALS; } #ifdef HAVE_SELECT /* * fvwmSelect - wrapper around the select() system call. * This system call may block indefinitely. We don't want * to block at all if the "terminate" flag is set - we * just want it to fail as quickly as possible. */ int fvwmSelect(fd_set_size_t nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) { volatile int iRet = -1; /* This variable MUST NOT be in a register */ #ifdef C_ALLOCA /* If we're using the C version of alloca, see if anything needs to be * freed up. */ alloca(0); #endif /* * Yes, we trash errno here, but you're only supposed to check * errno immediately after a function fails anyway. If we fail, * then it's because we received a signal. If we succeed, we * shouldn't be checking errno. And if somebody calls us expecting * us to preserve errno then that's their bug. * * NOTE: We mustn't call any function that might trash errno * ourselves, except select() itself of course. I believe * that sigsetjmp() does NOT trash errno. */ errno = EINTR; /* * Now initialise the non-local jump. Between here and the end of * the routine (more-or-less) we must NOT call any non-reentrant * functions! This is because we might need to abandon them half * way through execution and return here! */ if ( SIGSETJMP(deadJump, 1) == SIG_INIT ) { /* * Activate the non-local jump. Between now and when we turn the * jump off again, we must NOT call any non-reentrant functions * because we could be interrupted halfway through ... */ canJump = true; /* * If we have already been told to terminate then we will not * execute the select() because the flag will be set. If a * "terminate" signal arrives between testing the flag and * calling select() then we will jump back to the non-local * jump point ... */ if ( !isTerminated ) { /* * The "die" signal will interrupt this system call: * that IS the whole point, after all :-) */ iRet = select(nfds, SELECT_FD_SET_CAST readfds, SELECT_FD_SET_CAST writefds, SELECT_FD_SET_CAST exceptfds, timeout); } /* * The non-local jump is about to go out of scope, * so we must deactivate it. Note that the return- * value from select() will be safely stored in the * local variable before the jump is disabled. */ canJump = false; } return iRet; } #endif /* HAVE_SELECT */ fvwm-2.7.0/libs/BidiJoin.c0000644000175000017500000002072414147024700012210 00000000000000/* -*-c-*- */ /* Copyright (C) 2002 Nadim Shaikli (arabeyes.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 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* * FBidiJoin.c * * A place holder for when fribidi finally implements character * shaping/joining. This shaping/joining is a must for a variety of * Bidi'ed languages such as Arabic, Farsi, as well as all the Syriacs * (Urdu, Sindhi, Pashto, Kurdish, Baluchi, Kashmiri, Kazakh, Berber, * Uighur, Kirghiz, etc). */ #include "config.h" #if HAVE_BIDI #include "fvwmlib.h" #include "BidiJoin.h" /* ---------------------------- included header files ---------------------- */ #include /* ---------------------------- local types -------------------------------- */ typedef struct char_shaped { FriBidiChar base; /* The various Arabic shaped permutations */ FriBidiChar isolated; FriBidiChar initial; FriBidiChar medial; FriBidiChar final; } char_shaped_t; typedef struct char_shaped_comb { /* The Arabic exceptions - 2chars ==> 1char */ FriBidiChar first; FriBidiChar second; FriBidiChar comb_isolated; FriBidiChar comb_joined; } char_shaped_comb_t; /* ---------------------------- static variables --------------------------- */ static const char_shaped_t shaped_table[] = { /* base s i m f */ { 0x0621, 0xFE80, 0x0000, 0x0000, 0x0000, }, /* HAMZA */ { 0x0622, 0xFE81, 0x0000, 0x0000, 0xFE82, }, /* ALEF_MADDA */ { 0x0623, 0xFE83, 0x0000, 0x0000, 0xFE84, }, /* ALEF_HAMZA_ABOVE */ { 0x0624, 0xFE85, 0x0000, 0x0000, 0xFE86, }, /* WAW_HAMZA */ { 0x0625, 0xFE87, 0x0000, 0x0000, 0xFE88, }, /* ALEF_HAMZA_BELOW */ { 0x0626, 0xFE89, 0xFE8B, 0xFE8C, 0xFE8A, }, /* YEH_HAMZA */ { 0x0627, 0xFE8D, 0x0000, 0x0000, 0xFE8E, }, /* ALEF */ { 0x0628, 0xFE8F, 0xFE91, 0xFE92, 0xFE90, }, /* BEH */ { 0x0629, 0xFE93, 0x0000, 0x0000, 0xFE94, }, /* TEH_MARBUTA */ { 0x062A, 0xFE95, 0xFE97, 0xFE98, 0xFE96, }, /* TEH */ { 0x062B, 0xFE99, 0xFE9B, 0xFE9C, 0xFE9A, }, /* THEH */ { 0x062C, 0xFE9D, 0xFE9F, 0xFEA0, 0xFE9E, }, /* JEEM */ { 0x062D, 0xFEA1, 0xFEA3, 0xFEA4, 0xFEA2, }, /* HAH */ { 0x062E, 0xFEA5, 0xFEA7, 0xFEA8, 0xFEA6, }, /* KHAH */ { 0x062F, 0xFEA9, 0x0000, 0x0000, 0xFEAA, }, /* DAL */ { 0x0630, 0xFEAB, 0x0000, 0x0000, 0xFEAC, }, /* THAL */ { 0x0631, 0xFEAD, 0x0000, 0x0000, 0xFEAE, }, /* REH */ { 0x0632, 0xFEAF, 0x0000, 0x0000, 0xFEB0, }, /* ZAIN */ { 0x0633, 0xFEB1, 0xFEB3, 0xFEB4, 0xFEB2, }, /* SEEN */ { 0x0634, 0xFEB5, 0xFEB7, 0xFEB8, 0xFEB6, }, /* SHEEN */ { 0x0635, 0xFEB9, 0xFEBB, 0xFEBC, 0xFEBA, }, /* SAD */ { 0x0636, 0xFEBD, 0xFEBF, 0xFEC0, 0xFEBE, }, /* DAD */ { 0x0637, 0xFEC1, 0xFEC3, 0xFEC4, 0xFEC2, }, /* TAH */ { 0x0638, 0xFEC5, 0xFEC7, 0xFEC8, 0xFEC6, }, /* ZAH */ { 0x0639, 0xFEC9, 0xFECB, 0xFECC, 0xFECA, }, /* AIN */ { 0x063A, 0xFECD, 0xFECF, 0xFED0, 0xFECE, }, /* GHAIN */ { 0x0640, 0x0640, 0x0640, 0x0640, 0x0640, }, /* TATWEEL */ { 0x0641, 0xFED1, 0xFED3, 0xFED4, 0xFED2, }, /* FEH */ { 0x0642, 0xFED5, 0xFED7, 0xFED8, 0xFED6, }, /* QAF */ { 0x0643, 0xFED9, 0xFEDB, 0xFEDC, 0xFEDA, }, /* KAF */ { 0x0644, 0xFEDD, 0xFEDF, 0xFEE0, 0xFEDE, }, /* LAM */ { 0x0645, 0xFEE1, 0xFEE3, 0xFEE4, 0xFEE2, }, /* MEEM */ { 0x0646, 0xFEE5, 0xFEE7, 0xFEE8, 0xFEE6, }, /* NOON */ { 0x0647, 0xFEE9, 0xFEEB, 0xFEEC, 0xFEEA, }, /* HEH */ { 0x0648, 0xFEED, 0x0000, 0x0000, 0xFEEE, }, /* WAW */ { 0x0649, 0xFEEF, 0xFBE8, 0xFBE9, 0xFEF0, }, /* ALEF_MAKSURA */ { 0x064A, 0xFEF1, 0xFEF3, 0xFEF4, 0xFEF2, }, /* YEH */ { 0x0671, 0xFB50, 0x0000, 0x0000, 0xFB51, }, { 0x0679, 0xFB66, 0xFB68, 0xFB69, 0xFB67, }, { 0x067A, 0xFB5E, 0xFB60, 0xFB61, 0xFB5F, }, { 0x067B, 0xFB52, 0xFB54, 0xFB55, 0xFB53, }, { 0x067E, 0xFB56, 0xFB58, 0xFB59, 0xFB57, }, { 0x067F, 0xFB62, 0xFB64, 0xFB65, 0xFB63, }, { 0x0680, 0xFB5A, 0xFB5C, 0xFB5D, 0xFB5B, }, { 0x0683, 0xFB76, 0xFB78, 0xFB79, 0xFB77, }, { 0x0684, 0xFB72, 0xFB74, 0xFB75, 0xFB73, }, { 0x0686, 0xFB7A, 0xFB7C, 0xFB7D, 0xFB7B, }, { 0x0687, 0xFB7E, 0xFB80, 0xFB81, 0xFB7F, }, { 0x0688, 0xFB88, 0x0000, 0x0000, 0xFB89, }, { 0x068C, 0xFB84, 0x0000, 0x0000, 0xFB85, }, { 0x068D, 0xFB82, 0x0000, 0x0000, 0xFB83, }, { 0x068E, 0xFB86, 0x0000, 0x0000, 0xFB87, }, { 0x0691, 0xFB8C, 0x0000, 0x0000, 0xFB8D, }, { 0x0698, 0xFB8A, 0x0000, 0x0000, 0xFB8B, }, { 0x06A4, 0xFB6A, 0xFB6C, 0xFB6D, 0xFB6B, }, { 0x06A6, 0xFB6E, 0xFB70, 0xFB71, 0xFB6F, }, { 0x06A9, 0xFB8E, 0xFB90, 0xFB91, 0xFB8F, }, { 0x06AD, 0xFBD3, 0xFBD5, 0xFBD6, 0xFBD4, }, { 0x06AF, 0xFB92, 0xFB94, 0xFB95, 0xFB93, }, { 0x06B1, 0xFB9A, 0xFB9C, 0xFB9D, 0xFB9B, }, { 0x06B3, 0xFB96, 0xFB98, 0xFB99, 0xFB97, }, { 0x06BB, 0xFBA0, 0xFBA2, 0xFBA3, 0xFBA1, }, { 0x06BE, 0xFBAA, 0xFBAC, 0xFBAD, 0xFBAB, }, { 0x06C0, 0xFBA4, 0x0000, 0x0000, 0xFBA5, }, { 0x06C1, 0xFBA6, 0xFBA8, 0xFBA9, 0xFBA7, }, { 0x06C5, 0xFBE0, 0x0000, 0x0000, 0xFBE1, }, { 0x06C6, 0xFBD9, 0x0000, 0x0000, 0xFBDA, }, { 0x06C7, 0xFBD7, 0x0000, 0x0000, 0xFBD8, }, { 0x06C8, 0xFBDB, 0x0000, 0x0000, 0xFBDC, }, { 0x06C9, 0xFBE2, 0x0000, 0x0000, 0xFBE3, }, { 0x06CB, 0xFBDE, 0x0000, 0x0000, 0xFBDF, }, { 0x06CC, 0xFBFC, 0xFBFE, 0xFBFF, 0xFBFD, }, { 0x06D0, 0xFBE4, 0xFBE6, 0xFBE7, 0xFBE5, }, { 0x06D2, 0xFBAE, 0x0000, 0x0000, 0xFBAF, }, { 0x06D3, 0xFBB0, 0x0000, 0x0000, 0xFBB1, }, /* special treatment for ligatures from combining phase */ { 0xFEF5, 0xFEF5, 0x0000, 0x0000, 0xFEF6, }, /* LAM_ALEF_MADDA */ { 0xFEF7, 0xFEF7, 0x0000, 0x0000, 0xFEF8, }, /* LAM_ALEF_HAMZA_ABOVE */ { 0xFEF9, 0xFEF9, 0x0000, 0x0000, 0xFEFA, }, /* LAM_ALEF_HAMZA_BELOW */ { 0xFEFB, 0xFEFB, 0x0000, 0x0000, 0xFEFC, }, /* LAM_ALEF */ }; /* -------------------------- local functions ------------------------------ */ static const char_shaped_t * get_shaped_entry(FriBidiChar ch) { int count; int table_size; table_size = sizeof(shaped_table) / sizeof(shaped_table[0]); for (count = 0; count < table_size; count++) { if (shaped_table[count].base == ch) { return &shaped_table[count]; } } return NULL; } /* ------------------------- interface functions --------------------------- */ int shape_n_join( FriBidiChar *str_visual, int str_len) { int i; /* counter of the input string */ int len; /* counter and the final length of the shaped string */ FriBidiChar *orig_str; const char_shaped_t **list; const char_shaped_t *prev; const char_shaped_t *curr; const char_shaped_t *next; list = (const char_shaped_t **)safemalloc( (str_len + 2) * sizeof(char_shaped_t *)); orig_str = (FriBidiChar *)safemalloc( (str_len + 1) * sizeof(FriBidiChar)); /* head is NULL */ *list = NULL; list++; /* Populate with existent shaped characters */ for (i = 0; i < str_len; i++) { list[i] = get_shaped_entry(str_visual[i]); } /* tail is NULL */ list[i] = NULL; /* Store-off non-shaped characters; start with a clean slate */ memcpy(orig_str, str_visual, (str_len * sizeof(str_visual[0]))); memset(str_visual, 0, (str_len * sizeof(str_visual[0]))); /* Traverse the line & build new content */ for (i = 0, len = 0; i <= str_len - 1; i++, len++) { /* Get previous, current, and next characters */ prev = list[i + 1]; curr = list[i]; next = list[i - 1]; /* Process current mapped characters */ if (curr) { if (next) { if (prev) { if (!prev->initial || !prev->medial) { str_visual[len] = curr->initial? curr->initial: curr->isolated; } else { str_visual[len] = curr->medial? curr->medial: curr->final; } } else { str_visual[len] = curr->initial? curr->initial: curr->isolated; } } else { if (prev) { if (!prev->initial || !prev->medial) { str_visual[len] = curr->isolated; } else { str_visual[len] = curr->final? curr->final: curr->isolated; } } else { str_visual[len] = curr->isolated; } } } else { str_visual[len] = orig_str[i]; } } free(list-1); free(orig_str); /* return the length of the new string */ return len; } #endif /* HAVE_BIDI */ fvwm-2.7.0/libs/Rectangles.c0000644000175000017500000000433214147024700012605 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include "Rectangles.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* ---------------------------- interface functions ------------------------ */ Bool frect_get_intersection( int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2, XRectangle *r) { if (x1 + w1 > x2 && x1 < x2 + w2 && y1 + h1 > y2 && y1 < y2 + h2) { if (r) { r->x = max(x1,x2); r->y = max(y1,y2); r->width = min(x1+w1,x2+w2) - max(x1,x2); r->height =min(y1+h1,y2+h2) - max(y1,y2); } return True; } return False; } Bool frect_get_seg_intersection( int x1, int w1, int x2, int w2, int *x, int *w) { if (x1 + w1 > x2 && x1 < x2 + w2) { if (x) { *x = max(x1,x2); } if (w) { *w = min(x1+w1,x2+w2) - max(x1,x2); } return True; } return False; } Bool frect_get_rect_intersection( XRectangle a, XRectangle b, XRectangle *r) { return frect_get_intersection( a.x, a.y, a.width, a.height, b.x, b.y, b.width, b.height, r); } fvwm-2.7.0/libs/FScreen.h0000644000175000017500000000563414147024700012056 00000000000000/* -*-c-*- */ #ifndef FVWMLIB_FSCRREN_H #define FVWMLIB_FSCRREN_H /* needs X11/Xlib.h and X11/Xutil.h */ typedef enum { FSCREEN_GLOBAL = -1, FSCREEN_CURRENT = -2, FSCREEN_PRIMARY = -3, FSCREEN_XYPOS = -4 } fscreen_scr_t; typedef enum { FSCREEN_SPEC_GLOBAL = 'g', FSCREEN_SPEC_CURRENT = 'c', FSCREEN_SPEC_PRIMARY = 'p', FSCREEN_SPEC_WINDOW = 'w' } fscreen_scr_spec_t; typedef union { XEvent *mouse_ev; struct { int x; int y; } xypos; } fscreen_scr_arg; #define FSCREEN_MANGLE_USPOS_HINTS_MAGIC ((short)-32109) /* Control */ Bool FScreenIsEnabled(void); Bool FScreenIsSLSEnabled(void); void FScreenInit(Display *dpy); void FScreenOnOff(Bool do_enable); Bool FScreenConfigureSLSSize(int width, int height); Bool FScreenConfigureSLSScreens(int nscreens, char *args); void FScreenSLSOnOff(Bool do_enable); /* Intended to be called by modules. Simply pass in the parameter from the * config string sent by fvwm. */ void FScreenConfigureModule(char *args); const char* FScreenGetConfiguration(void); /* For use by fvwm */ void FScreenSetDefaultModuleScreen(char *scr_spec); void FScreenDisableRandR(void); void FScreenSetPrimaryScreen(int scr); /* Screen info */ Bool FScreenGetScrRect( fscreen_scr_arg *arg, fscreen_scr_t screen, int *x, int *y, int *w, int *h); Bool FScreenGetScrId( fscreen_scr_arg *arg, fscreen_scr_t screen); void FScreenTranslateCoordinates( fscreen_scr_arg *arg_src, fscreen_scr_t screen_src, fscreen_scr_arg *arg_dest, fscreen_scr_t screen_dest, int *x, int *y); void FScreenGetResistanceRect( int wx, int wy, unsigned int ww, unsigned int wh, int *x0, int *y0, int *x1, int *y1); Bool FScreenIsRectangleOnScreen( fscreen_scr_arg *arg, fscreen_scr_t screen, rectangle *rec); void FScreenSpecToString(char *dest, int space, fscreen_scr_t screen); int FScreenOfPointerXY(int x, int y); /* Clipping/positioning */ int FScreenClipToScreen( fscreen_scr_arg *arg, fscreen_scr_t screen, int *x, int *y, int w, int h); void FScreenCenterOnScreen( fscreen_scr_arg *arg, fscreen_scr_t screen, int *x, int *y, int w, int h); /* Geometry management */ int FScreenGetScreenArgument(char *scr_spec, fscreen_scr_spec_t default_screen); int FScreenParseGeometryWithScreen( char *parsestring, int *x_return, int *y_return, unsigned int *width_return, unsigned int *height_return, int *screen_return); int FScreenParseGeometry( char *parsestring, int *x_return, int *y_return, unsigned int *width_return, unsigned int *height_return); int FScreenGetGeometry( char *parsestring, int *x_return, int *y_return, int *width_return, int *height_return, XSizeHints *hints, int flags); void FScreenMangleScreenIntoUSPosHints(fscreen_scr_t screen, XSizeHints *hints); fscreen_scr_t FScreenFetchMangledScreenFromUSPosHints(XSizeHints *hints); /* RandR support */ int FScreenGetRandrEventType(void); Bool FScreenHandleRandrEvent( XEvent *event, int *old_w, int *old_h, int *new_w, int *new_h); #endif /* FVWMLIB_FSCRREN_H */ fvwm-2.7.0/libs/FGettext.h0000644000175000017500000000515414147024676012274 00000000000000/* -*-c-*- */ /* Convenience header for conditional use of GNU . Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc. */ #ifndef _LIBGETTEXT_H #define _LIBGETTEXT_H 1 #include "config.h" #define _(x) FGettext(x) /* NLS can be disabled through the configure --disable-nls option. */ #if HAVE_NLS #define HaveNLSSupport 1 /* Get declarations of GNU message catalog functions. */ # include #else #define HaveNLSSupport 0 /* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which chokes if dcgettext is defined as a macro. So include it now, to make later inclusions of a NOP. We don't include as well because people using "gettext.h" will not include , and also including would fail on SunOS 4, whereas is OK. */ #if defined(__sun) # include #endif /* Disabled NLS. The casts to 'const char *' serve the purpose of producing warnings for invalid uses of the value returned from these functions. On pre-ANSI systems without 'const', the config.h file is supposed to contain "#define const". */ # define gettext(Msgid) ((const char *) (Msgid)) # define dgettext(Domainname, Msgid) ((const char *) (Msgid)) # define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid)) # define ngettext(Msgid1, Msgid2, N) \ ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) # define dngettext(Domainname, Msgid1, Msgid2, N) \ ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) # define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) # define textdomain(Domainname) ((const char *) (Domainname)) # define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname)) # define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset)) #endif /* A pseudo function call that serves as a marker for the automated extraction of messages, but does not call gettext(). The run-time translation is done at a different place in the code. The argument, String, should be a literal string. Concatenated strings and other string expressions won't work. The macro's expansion is not parenthesized, so that it is suitable as initializer for static 'char[]' or 'const char[]' variables. */ #define gettext_noop(String) String void FGettextInit(const char *domain, const char *dir, const char *module); const char *FGettext(char *str); char *FGettextCopy(char *str); void FGettextSetLocalePath(const char *path); void FGettextPrintLocalePath(int verbose); #endif /* _LIBGETTEXT_H */ fvwm-2.7.0/libs/FEvent.h0000644000175000017500000002135314147024700011714 00000000000000/* -*-c-*- */ #ifndef FEVENT_H #define FEVENT_H /* ---------------------------- included header files ---------------------- */ /* ---------------------------- global definitions ------------------------- */ #define FEV_IS_EVENT_INVALID(e) \ (fev_is_invalid_event_type_set && (e).type == fev_invalid_event_type) #define FEV_HAS_EVENT_WINDOW(type) \ (( \ (type) != GraphicsExpose && \ (type) != NoExpose && \ (type) != SelectionNotify && \ (type) != SelectionRequest) ? 1 : 0) /* invalidate event by setting a bogus event type */ #define FEV_INVALIDATE_EVENT(e) \ do { (e)->type = fev_invalid_event_type; } while (0) /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* Exported to be used in FEV_IS_EVENT_INVALID(). Do not use. */ extern char fev_is_invalid_event_type_set; /* Exported to be used in FEV_IS_EVENT_INVALID(). Do not use. */ extern int fev_invalid_event_type; /* ---------------------------- interface functions (privileged access) ---- */ #ifdef FEVENT_PRIVILEGED_ACCESS void fev_copy_last_event(XEvent *dest); XEvent *fev_get_last_event_address(void); #endif /* ---------------------------- interface functions (normal_access) -------- */ /* Sets the event type that is used by FWeedIfEvents() to mark an event as * invalid. Needs to be called before FWeedIfEvents() can be used. */ void fev_init_invalid_event_type(int invalid_event_type); /* get the latest event time */ Time fev_get_evtime(void); /* This function determines the location of the mouse pointer from the event * if possible, if not it queries the X server. Returns False if it had to * query the server and the call failed because the pointer was on a * different screen. */ Bool fev_get_evpos_or_query( Display *dpy, Window w, const XEvent *e, int *ret_x, int *ret_y); /* Sets the x_root/y_root position in the given event if it's of the proper * type. Returns True if the position was set. */ Bool fev_set_evpos(XEvent *e, int x, int y); /* announce a faked event to the FEvent module */ void fev_fake_event(XEvent *ev); /* temporarily store the cached event in allocated memory */ void *fev_save_event(void); /* restore an event saved with fev_save_event and free the memory it uses */ void fev_restore_event(void *ev); /* fill the event structure *ev with a dummy event of no particular type */ void fev_make_null_event(XEvent *ev, Display *dpy); /* return a copy of the last XEVent in *ev */ void fev_get_last_event(XEvent *ev); /* Make sure the values in the event are in the defined range (e.g. x is and * int, but the protocol uses only a 16 bit signed integer. */ void fev_sanitise_configure_request(XConfigureRequestEvent *cr); void fev_sanitise_configure_notify(XConfigureEvent *cn); void fev_sanitize_size_hints(XSizeHints *sh); /* ---------------------------- Functions not present in Xlib -------------- */ /* Iterates over all events currentliy in the input queue and calls the * weed_predicate procedure for them. The predicate may return * 0 = keep event and continue weeding * 1 = invalidate event and continue weeding * 2 = keep event and stop weeding * 3 = invalidate event and stop weeding * Events are marked as invalid by overwriting the event type with the invalid * event type configured with fev_init_invalid_event_type(). Returns the * number of invalidated events. * * The return codes 2 and 3 of the weed_predicate procedure can be used to * stop weeding if another event gets "in the way". For example, when merging * Expose events, one might want to stop merging when a ConfigureRequest event * is encountered in the queue as that event may change the visible are of the * window. * * Weeded events can still be returned by functions that do not check the event * type, e.g. FNextEvent(), FWindowEvent(), FMaskEvent(), FPeekEvent etc. It * is the responsibility of the caller to discard these events. * * If the weed_predicate is a NULL pointer, no call is made and the result for * all events is assumed to be 1. */ int FWeedIfEvents( Display *display, int (*weed_predicate) ( Display *display, XEvent *current_event, XPointer arg), XPointer arg); /* Same as FWeedIfEvents but weeds only events for the given window. The * weed_predicate is only called for events with a matching window. */ int FWeedIfWindowEvents( Display *display, Window window, int (*weed_predicate) ( Display *display, XEvent *current_event, XPointer arg), XPointer arg); /* Same as FWeedIfEvents but weeds only events of the given type for the given * window. If last_event is not NULL, a copy of the last weeded event is * returned through *last_event (valid if a value > 0 is treturned). */ int FCheckWeedTypedWindowEvents( Display *display, Window window, int event_type, XEvent *last_event); /* Like FCheckIfEvent but does not remove the event from the queue. */ int FCheckPeekIfEvent( Display *display, XEvent *event_return, Bool (*predicate) (Display *display, XEvent *event, XPointer arg), XPointer arg); /* ---------------------------- X event replacements ----------------------- */ /* Replacements for X functions */ XTimeCoord *FGetMotionEvents( Display *display, Window w, Time start, Time stop, int *nevents_return); int FAllowEvents( Display *display, int event_mode, Time time); Bool FCheckIfEvent( Display *display, XEvent *event_return, Bool (*predicate) (Display *display, XEvent *event, XPointer arg), XPointer arg); Bool FCheckMaskEvent( Display *display, long event_mask, XEvent *event_return); Bool FCheckTypedEvent( Display *display, int event_type, XEvent *event_return); Bool FCheckTypedWindowEvent( Display *display, Window w, int event_type, XEvent *event_return); Bool FCheckWindowEvent( Display *display, Window w, long event_mask, XEvent *event_return); int FEventsQueued( Display *display, int mode); int FIfEvent( Display *display, XEvent *event_return, Bool (*predicate) (Display *display, XEvent *event, XPointer arg), XPointer arg); int FMaskEvent( Display *display, long event_mask, XEvent *event_return); int FNextEvent( Display *display, XEvent *event_return); int FPeekEvent( Display *display, XEvent *event_return); int FPeekIfEvent( Display *display, XEvent *event_return, Bool (*predicate) (Display *display, XEvent *event, XPointer arg), XPointer arg); int FPending( Display *display); int FPutBackEvent( Display *display, XEvent *event); int FQLength( Display *display); Bool FQueryPointer( Display *display, Window w, Window *root_return, Window *child_return, int *root_x_return, int *root_y_return, int *win_x_return, int *win_y_return, unsigned int *mask_return); int FSelectInput( Display *display, Window w, long event_mask); Status FSendEvent( Display *display, Window w, Bool propagate, long event_mask, XEvent *event_send); int FWarpPointer( Display *display, Window src_w, Window dest_w, int src_x, int src_y, unsigned int src_width, unsigned int src_height, int dest_x, int dest_y); int FWarpPointerUpdateEvpos( XEvent *ev, Display *display, Window src_w, Window dest_w, int src_x, int src_y, unsigned int src_width, unsigned int src_height, int dest_x, int dest_y); int FWindowEvent( Display *display, Window w, long event_mask, XEvent *event_return); Status FGetWMNormalHints( Display *display, Window w, XSizeHints *hints_return, long *supplied_return); /* ---------------------------- disable X symbols -------------------------- */ /* FEVENT_C must only be defined in FEvent.c! */ #ifndef FEVENT_C #define XGetMotionEvents(a, b, c, d, e) use_FGetMotionEvents #define XCheckIfEvent(a, b, c, d) use_FCheckIfEvent #define XCheckMaskEvent(a, b, c) use_FCheckMaskEvent #define XCheckTypedEvent(a, b, c) use_FCheckTypedEvent #define XCheckTypedWindowEvent(a, b, c, d) use_FCheckTypedWindowEvent #define XCheckWindowEvent(a, b, c, d) use_FCheckWindowEvent #define XEventsQueued(a, b) use_FEventsQueued #define XIfEvent(a, b, c, d) use_FIfEvent #define XMaskEvent(a, b, c) use_FMaskEvent #define XNextEvent(a, b) use_FNextEvent #define XPeekEvent(a, b) use_FPeekEvent #define XPeekIfEvent(a, b, c, d) use_FPeekIfEvent #define XPending(a) use_FPending #define XPutBackEvent(a, b) use_FPutBackEvent #define XQueryPointer(a, b, c, d, e, f, g, h, i) use_FQueryPointer #define XQLength(a) use_FQLength #define XSendEvent(a, b, c, d, e) use_FSendEvent #define XWarpPointer(a, b, c, d, e, f, g, h, i) use_FWarpPointer #define XWindowEvent(a, b, c, d) use_FWindowEvent #define XGetSizeHints(a, b, c, d) use_FGetWMNormalHints #define XGetNormalHints(a, b, c) use_FGetWMNormalHints #define XGetWMNormalHints(a, b, c, d) use_FGetWMNormalHints #endif #endif /* FEVENT_H */ fvwm-2.7.0/libs/ColorUtils.h0000644000175000017500000000277114147024700012627 00000000000000#ifndef LIB_COLORUTILS_H #define LIB_COLORUTILS_H /* * Stuff for dealing w/ bitmaps & pixmaps: */ XColor *GetShadowColor(Pixel); XColor *GetHiliteColor(Pixel); Pixel GetShadow(Pixel); Pixel GetHilite(Pixel); XColor *GetForeShadowColor(Pixel foreground, Pixel background); Pixel GetForeShadow(Pixel foreground, Pixel background); XColor *GetTintedColor(Pixel in, Pixel tint, int percent); Pixel GetTintedPixel(Pixel in, Pixel tint, int percent); /* This function converts the colour stored in a colorcell (pixel) into the * string representation of a colour. The output is printed at the * address 'output'. It is either in rgb format ("rgb:rrrr/gggg/bbbb") if * use_hash is False or in hash notation ("#rrrrggggbbbb") if use_hash is true. * The return value is the number of characters used by the string. The * rgb values of the output are undefined if the colorcell is invalid. The * memory area pointed at by 'output' must be at least 64 bytes (in case of * future extensions and multibyte characters).*/ int pixel_to_color_string( Display *dpy, Colormap cmap, Pixel pixel, char *output, Bool use_hash); Pixel GetSimpleColor(char *name); /* handles colorset color names too */ Pixel GetColor(char *name); /* duplicate an already allocated color */ Pixel fvwmlib_clone_color(Pixel p); void fvwmlib_free_colors(Display *dpy, Pixel *pixels, int n, Bool no_limit); void fvwmlib_copy_color( Display *dpy, Pixel *dst_color, Pixel *src_color, Bool do_free_dest, Bool do_copy_src); #endif /* LIB_COLORUTILS_H */ fvwm-2.7.0/libs/Makefile.am0000644000175000017500000000333314147024700012406 00000000000000## Process this file with automake to create Makefile.in noinst_LIBRARIES = libfvwm.a ## please keep .c files in largest first order to speed up parallel makes libfvwm_a_SOURCES = \ BidiJoin.h Bindings.h ClientMsg.h ColorUtils.h Colorset.h \ CombineChars.h Cursor.h Event.h FBidi.h FEvent.h FGettext.h FImage.h \ FRender.h FRenderInit.h FRenderInterface.h FSMlib.h FScreen.h \ FShape.h FShm.h FTips.h Fcursor.h Fft.h FftInterface.h Ficonv.h \ Flocale.h FlocaleCharset.h Fplay.h Fpng.h Fsvg.h Fxpm.h Grab.h \ Graphics.h Module.h Parse.h Picture.h PictureBase.h \ PictureDitherMatrice.h PictureGraphics.h PictureImageLoader.h \ PictureUtils.h Rectangles.h Strings.h System.h Target.h WinMagic.h \ XError.h XResource.h charmap.h defaults.h envvar.h fio.h flist.h \ fsm.h ftime.h fvwm_sys_stat.h fvwmlib.h fvwmrect.h fvwmsignal.h \ gravity.c gravity.h lang-strings.h modifiers.h queue.h safemalloc.h \ setpgrp.h timeout.h vpacket.h wcontext.h wild.h \ \ BidiJoin.c Flocale.c PictureUtils.c FScreen.c Graphics.c \ PictureGraphics.c Bindings.c FlocaleCharset.c Parse.c \ PictureImageLoader.c Colorset.c ColorUtils.c CombineChars.c Module.c \ FRender.c Ficonv.c envvar.c Fft.c gravity.c \ XResource.c FEvent.c FImage.c WinMagic.c Target.c Picture.c XError.c \ queue.c fvwmsignal.c System.c PictureBase.c Cursor.c Strings.c \ fvwmrect.c FRenderInit.c safemalloc.c FBidi.c \ wild.c Grab.c Event.c ClientMsg.c setpgrp.c FShape.c \ FGettext.c Rectangles.c timeout.c flist.c charmap.c wcontext.c \ modifiers.c fsm.c FTips.c fio.c fvwmlib.c libfvwm_a_LIBADD = @LIBOBJS@ AM_CPPFLAGS = -I$(top_srcdir) $(xpm_CFLAGS) $(Xft_CFLAGS) $(X_CFLAGS) \ $(iconv_CFLAGS) $(Xrender_CFLAGS) $(Bidi_CFLAGS) $(png_CFLAGS) \ $(rsvg_CFLAGS) $(intl_CFLAGS) fvwm-2.7.0/libs/Ficonv.h0000644000175000017500000000250414147024700011746 00000000000000/* -*-c-*- */ /* Copyright (C) 2002 Olivier Chapuis */ #ifndef FICONV_H #define FICONV_H /* ---------------------------- included header files ---------------------- */ #include "config.h" /* ---------------------------- global definitions ------------------------- */ #ifdef HAVE_ICONV #define FiconvSupport 1 #else #define FiconvSupport 0 #endif #if FiconvSupport #define Ficonv_open(a,b) iconv_open(a,b) #define Ficonv_close(a) iconv_close(a) #define Ficonv(a,b,c,d,e) iconv(a,b,c,d,e) #else #define Ficonv_open(a,b) (Ficonv_t)-1 #define Ficonv_close(a) -1 #define Ficonv(a,b,c,d,e) -1 #endif /* ---------------------------- global macros ------------------------------ */ #define FICONV_CONVERSION_MAX_NUMBER_OF_WARNING 10 /* ---------------------------- type definitions --------------------------- */ typedef void* Ficonv_t; /* ---------------------------- interface functions ------------------------ */ void FiconvSetTransliterateUtf8(int toggle); char *FiconvUtf8ToCharset( Display *dpy, FlocaleCharset *fc, const char *in, unsigned int in_size); char *FiconvCharsetToUtf8( Display *dpy, FlocaleCharset *fc, const char *in, unsigned int in_size); char *FiconvCharsetToCharset( Display *dpy, FlocaleCharset *in_fc, FlocaleCharset *out_fc, const char *in, unsigned int in_size); #endif /* FICONV_H */ fvwm-2.7.0/libs/Bindings.h0000644000175000017500000000776614147024700012276 00000000000000/* -*-c-*- */ #include /* XClassHint */ #ifndef FVWMLIB_BINDINGS_H_H #define FVWMLIB_BINDINGS_H_H /* ---------------------------- global definitions ------------------------- */ #define binding_t_t unsigned char /* ---------------------------- global macros ------------------------------ */ #define BIND_IS_KEY_PRESS(t) ((t) == BIND_KEYPRESS || (t) == BIND_PKEYPRESS) #define BIND_IS_KEY_BINDING(t) ((t) == BIND_KEYPRESS || (t) == BIND_PKEYPRESS) #define BIND_IS_PKEY_BINDING(t) ((t) == BIND_PKEYPRESS) #define BIND_IS_MOUSE_BINDING(t) \ ((t) == BIND_BUTTONPRESS || (t) == BIND_BUTTONRELEASE) #define BIND_IS_STROKE_BINDING(t) ((t) == BIND_STROKE) /* ---------------------------- type definitions --------------------------- */ typedef enum { /* press = even number, release = press + 1 */ BIND_BUTTONPRESS = 0, BIND_BUTTONRELEASE = 1, BIND_KEYPRESS = 2, BIND_PKEYPRESS = 4, BIND_STROKE = 6 } binding_t; typedef struct Binding { binding_t_t type; /* Is it a mouse, key, or stroke binding */ STROKE_CODE(void *Stroke_Seq;) /* stroke sequence */ int Button_Key; /* Mouse Button number or Keycode */ char *key_name; /* In case of keycode, give the key_name too */ int Context; /* Fvwm context, ie titlebar, frame, etc */ int Modifier; /* Modifiers for keyboard state */ void *Action; /* What to do? */ void *Action2; /* This one can be used too */ char *windowName; /* Name of window (regex pattern) this binding applies to. NULL means all windows. */ struct Binding *NextBinding; } Binding; /* ---------------------------- interface functions ------------------------ */ void CollectBindingList( Display *dpy, Binding **pblist_src, Binding **pblist_dest, Bool *ret_are_similar_bindings_left, binding_t type, STROKE_ARG(void *stroke) int button, KeySym keysym, int modifiers, int contexts, char *windowName); int AddBinding( Display *dpy, Binding **pblist, binding_t type, STROKE_ARG(void *stroke) int button, KeySym keysym, char *key_name, int modifiers, int contexts, void *action, void *action2, char *windowName); void FreeBindingStruct(Binding *b); void FreeBindingList(Binding *b); void RemoveBinding(Binding **pblist, Binding *b, Binding *prev); Bool RemoveMatchingBinding( Display *dpy, Binding **pblist, binding_t type, STROKE_ARG(char *stroke) int button, KeySym keysym, int modifiers, int contexts); void *CheckBinding( Binding *blist, STROKE_ARG(char *stroke) int button_keycode, unsigned int modifier, unsigned int dead_modifiers, int Context, binding_t type, const XClassHint *win_class, const char *win_name); void *CheckTwoBindings( Bool *ret_is_second_binding, Binding *blist, STROKE_ARG(char *stroke) int button_keycode, unsigned int modifier,unsigned int dead_modifiers, int Context, binding_t type, const XClassHint *win_class, const char *win_name, int Context2, binding_t type2, const XClassHint *win_class2, const char *win_name2); void GrabWindowKey( Display *dpy, Window w, Binding *binding, unsigned int contexts, unsigned int dead_modifiers, Bool fGrab); void GrabAllWindowKeys( Display *dpy, Window w, Binding *blist, unsigned int contexts, unsigned int dead_modifiers, Bool fGrab); void GrabWindowButton( Display *dpy, Window w, Binding *binding, unsigned int contexts, unsigned int dead_modifiers, Cursor cursor, Bool fGrab); void GrabAllWindowButtons( Display *dpy, Window w, Binding *blist, unsigned int contexts, unsigned int dead_modifiers, Cursor cursor, Bool fGrab); void GrabAllWindowKeysAndButtons( Display *dpy, Window w, Binding *blist, unsigned int contexts, unsigned int dead_modifiers, Cursor cursor, Bool fGrab); void GrabWindowKeyOrButton( Display *dpy, Window w, Binding *binding, unsigned int contexts, unsigned int dead_modifiers, Cursor cursor, Bool fGrab); KeySym FvwmStringToKeysym(Display *dpy, char *key); Bool bindingAppliesToWindow(Binding *binding, const XClassHint *win_class, const char *win_name); Bool is_pass_through_action(const char *action); #endif /* FVWMLIB_BINDINGS_H_H */ fvwm-2.7.0/libs/Picture.c0000644000175000017500000001421414147024700012131 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* Changed 02/12/97 by Dan Espen: - added routines to determine color closeness, for color use reduction. Some of the logic comes from pixy2, so the copyright is below. */ /* * * Routines to handle initialization, loading, and removing of xpm's or mono- * icon images. * */ #include "config.h" #include #include #include #include "ftime.h" #include #include #include #include "fvwmlib.h" #include "System.h" #include "Colorset.h" #include "Picture.h" #include "PictureUtils.h" #include "Fsvg.h" static FvwmPicture *FvwmPictureList=NULL; FvwmPicture *PGetFvwmPicture( Display *dpy, Window win, char *ImagePath, const char *name, FvwmPictureAttributes fpa) { char *path = PictureFindImageFile(name, ImagePath, R_OK); FvwmPicture *p; if (path == NULL) { return NULL; } p = PImageLoadFvwmPictureFromFile(dpy, win, path, fpa); if (p == NULL) { free(path); } return p; } void PFreeFvwmPictureData(FvwmPicture *p) { if (!p) { return; } if (p->alloc_pixels != NULL) { free(p->alloc_pixels); } if(p->name!=NULL) { free(p->name); } free(p); return; } FvwmPicture *PCacheFvwmPicture( Display *dpy, Window win, char *ImagePath, const char *name, FvwmPictureAttributes fpa) { char *path; char *real_path; FvwmPicture *p = FvwmPictureList; /* First find the full pathname */ if ((path = PictureFindImageFile(name, ImagePath, R_OK)) == NULL) { return NULL; } /* Remove any svg rendering options from real_path */ if (USE_SVG && *path == ':' && (real_path = strchr(path + 1, ':'))) { real_path++; } else { real_path = path; } /* See if the picture is already cached */ while (p) { register char *p1, *p2; for (p1 = path, p2 = p->name; *p1 && *p2; ++p1, ++p2) { if (*p1 != *p2) { break; } } /* If we have found a picture with the wanted name and stamp */ if (!*p1 && !*p2 && !isFileStampChanged(&p->stamp, real_path) && PICTURE_FPA_AGREE(p,fpa)) { p->count++; /* Put another weight on the picture */ free(path); return p; } p=p->next; } /* Not previously cached, have to load it ourself. Put it first in list */ p = PImageLoadFvwmPictureFromFile(dpy, win, path, fpa); if(p) { p->next=FvwmPictureList; FvwmPictureList=p; } else { free(path); } return p; } void PDestroyFvwmPicture(Display *dpy, FvwmPicture *p) { FvwmPicture *q = FvwmPictureList; if (!p) { return; } /* Remove a weight */ if(--(p->count)>0) { /* still too heavy? */ return; } /* Let it fly */ if (p->alloc_pixels != NULL) { if (p->nalloc_pixels != 0) { PictureFreeColors( dpy, Pcmap, p->alloc_pixels, p->nalloc_pixels, 0, p->no_limit); } free(p->alloc_pixels); } if(p->name!=NULL) { free(p->name); } if(p->picture!=None) { XFreePixmap(dpy,p->picture); } if(p->mask!=None) { XFreePixmap(dpy,p->mask); } if(p->alpha != None) { XFreePixmap(dpy, p->alpha); } /* Link it out of the list (it might not be there) */ if(p==q) /* in head? simple */ { FvwmPictureList = p->next; } else { while(q && q->next!=p) /* fast forward until end or found */ { q = q->next; } if(q) /* not end? means we found it in there, possibly at end */ { q->next = p->next; /* link around it */ } } free(p); return; } FvwmPicture *PLoadFvwmPictureFromPixmap( Display *dpy, Window win, char *name, Pixmap pixmap, Pixmap mask, Pixmap alpha, int width, int height, int nalloc_pixels, Pixel *alloc_pixels, int no_limit) { FvwmPicture *q; q = (FvwmPicture*)safemalloc(sizeof(FvwmPicture)); memset(q, 0, sizeof(FvwmPicture)); q->count = 1; q->name = name; q->next = NULL; q->stamp = pixmap; q->picture = pixmap; q->mask = mask; q->alpha = alpha; q->width = width; q->height = height; q->depth = Pdepth; q->nalloc_pixels = nalloc_pixels; q->alloc_pixels = alloc_pixels; q->no_limit = no_limit; return q; } FvwmPicture *PCacheFvwmPictureFromPixmap( Display *dpy, Window win, char *name, Pixmap pixmap, Pixmap mask, Pixmap alpha, int width, int height, int nalloc_pixels, Pixel *alloc_pixels, int no_limit) { FvwmPicture *p = FvwmPictureList; /* See if the picture is already cached */ for(; p != NULL; p = p->next) { #if 0 /* at th present time no good way to cache a pixmap */ if (!strcmp(p->name,name)) { p->count++; return p; } #endif } /* Not previously cached, have to load. Put it first in list */ p = PLoadFvwmPictureFromPixmap( dpy, win, name, pixmap, mask, alpha, width, height, nalloc_pixels, alloc_pixels, no_limit); if(p) { p->next = FvwmPictureList; FvwmPictureList = p; } return p; } FvwmPicture *PCloneFvwmPicture(FvwmPicture *pic) { if (pic != NULL) { pic->count++; } return pic; } void PicturePrintImageCache(int verbose) { FvwmPicture *p; unsigned int count = 0; unsigned int hits = 0; unsigned int num_alpha = 0; unsigned int num_mask = 0; fflush(stderr); fflush(stdout); fprintf(stderr, "fvwm info on Image cache:\n"); for (p = FvwmPictureList; p != NULL; p = p->next) { int num_pixmaps = 1; if (p->mask != None) { num_mask++; num_pixmaps++; } if (p->alpha != None) { num_alpha++; num_pixmaps++; } if (verbose > 0) { fprintf(stderr, "Image: %s (%d pixmaps; used %d times)\n", p->name, num_pixmaps, p->count); } count++; hits += p->count-1; } fprintf(stderr, "%u images in cache (%d reuses) " "(%u masks, %u alpha channels => %u pixmaps)\n", count, hits, num_mask, num_alpha, count + num_mask + num_alpha); fflush(stderr); } fvwm-2.7.0/libs/Colorset.c0000644000175000017500000004677314147024700012327 00000000000000/* -*-c-*- */ /* Fvwm colorset technology is Copyright (C) 1999 Joey Shutup * http://www.streetmap.co.uk/streetmap.dll?Postcode2Map?BS24+9TZ * You may use this code for any purpose, as long as the original copyright * and this notice remains in the source code and all documentation */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ #include "config.h" #include #include #include "libs/fvwmlib.h" #include "libs/FShape.h" #include "libs/Colorset.h" #include "libs/PictureBase.h" #include "libs/Graphics.h" #include "libs/Grab.h" #include "libs/PictureGraphics.h" #include "libs/XError.h" /* globals */ colorset_t *Colorset = NULL; int nColorsets = 0; /* stretch the src rectangle to the dest ractangle keeping its aspect so that * it fills the destination completely. */ static int get_aspect_dimensions( int *ret_w, int *ret_h, int dest_w, int dest_h, int src_w, int src_h) { double ax; double ay; ax = (double)dest_w / (double)src_w; ay = (double)dest_h / (double)src_h; if (ax >= ay) { /* fit in x direction */ *ret_w = dest_w; *ret_h = (src_h * dest_w) / src_w; return 0; } else { /* fit in y direction */ *ret_w = (src_w * dest_h) / src_h; *ret_h = dest_h; return 1; } } /* * AllocColorset() grows the size of the Colorset array to include set n * colorset_t *Colorset will be altered * returns the address of the member */ void AllocColorset(int n) { /* do nothing if it already exists */ if (n < nColorsets) { return; } /* increment n to get the required array size, get a new array */ Colorset = (colorset_t *)saferealloc( (char *)Colorset, ++n * sizeof(colorset_t)); /* zero out colorset 0 it's always defined so will be filled in during module startup */ if (n == 0) { memset( &Colorset[nColorsets], 0, (n - nColorsets) * sizeof(colorset_t)); } else { /* copy colorset 0 into new members so that if undefined ones * are referenced at least they don't give black on black */ for ( ; nColorsets < n; nColorsets++) { memcpy( &Colorset[nColorsets], Colorset, sizeof(colorset_t)); } } nColorsets = n; return; } /* * DumpColorset() returns a char * to the colorset contents in printable form */ static char csetbuf[256]; char *DumpColorset(int n, colorset_t *cs) { sprintf(csetbuf, "Colorset " "%x %lx %lx %lx %lx %lx %lx %lx %lx %lx " "%x %x %x %x %x %x %x %x %x %x %x", n, cs->fg, cs->bg, cs->hilite, cs->shadow, cs->fgsh, cs->tint, cs->icon_tint, cs->pixmap, cs->shape_mask, cs->fg_alpha_percent, cs->width, cs->height, cs->pixmap_type, cs->shape_width, cs->shape_height, cs->shape_type, cs->tint_percent, cs->do_dither_icon, cs->icon_tint_percent, cs->icon_alpha_percent); return csetbuf; } /* * LoadColorset() takes a strings and stuffs it into the array */ int LoadColorset(char *line) { colorset_t *cs; unsigned int n, chars; Pixel fg, bg, hilite, shadow, fgsh, tint, icon_tint; Pixmap pixmap; Pixmap shape_mask; unsigned int fg_alpha_percent, width, height, pixmap_type; unsigned int shape_width, shape_height, shape_type; unsigned int tint_percent, do_dither_icon, icon_tint_percent; unsigned int icon_alpha_percent; if (line == NULL) { return -1; } if (sscanf(line, "%x%n", &n, &chars) < 1) { return -1; } line += chars; /* migo: if you modify this sscanf or other colorset definitions, * please update perllib/FVWM/Tracker/Colorsets.pm too */ if (sscanf(line, "%lx %lx %lx %lx %lx %lx %lx %lx %lx " "%x %x %x %x %x %x %x %x %x %x %x", &fg, &bg, &hilite, &shadow, &fgsh, &tint, &icon_tint, &pixmap, &shape_mask, &fg_alpha_percent, &width, &height, &pixmap_type, &shape_width, &shape_height, &shape_type, &tint_percent, &do_dither_icon, &icon_tint_percent, &icon_alpha_percent) != 20) return -1; AllocColorset(n); cs = &Colorset[n]; cs->fg = fg; cs->bg = bg; cs->hilite = hilite; cs->shadow = shadow; cs->fgsh = fgsh; cs->tint = tint; cs->icon_tint = icon_tint; cs->pixmap = pixmap; cs->shape_mask = shape_mask; cs->fg_alpha_percent = fg_alpha_percent; cs->width = width; cs->height = height; cs->pixmap_type = pixmap_type; cs->shape_width = shape_width; cs->shape_height = shape_height; cs->shape_type = shape_type; cs->tint_percent = tint_percent; cs->do_dither_icon = do_dither_icon; cs->icon_tint_percent = icon_tint_percent; cs->icon_alpha_percent = icon_alpha_percent; return n; } /* scrolls a pixmap by x_off/y_off pixels, wrapping around at the edges. */ Pixmap ScrollPixmap( Display *dpy, Pixmap p, GC gc, int x_off, int y_off, int width, int height, unsigned int depth) { GC tgc; XGCValues xgcv; Pixmap p2; if (p == None || p == ParentRelative || (x_off == 0 && y_off == 0)) { return p; } tgc = fvwmlib_XCreateGC(dpy, p, 0, &xgcv); if (tgc == None) { return p; } XCopyGC(dpy, gc, GCFunction | GCPlaneMask| GCSubwindowMode | GCClipXOrigin | GCClipYOrigin | GCClipMask, tgc); xgcv.tile = p; xgcv.ts_x_origin = x_off; xgcv.ts_y_origin = y_off; xgcv.fill_style = FillTiled; XChangeGC( dpy, tgc, GCTile | GCTileStipXOrigin | GCTileStipYOrigin | GCFillStyle, &xgcv); p2 = XCreatePixmap(dpy, p, width, height, depth); if (p2 == None) { return p; } XFillRectangle(dpy, p2, tgc, 0, 0, width, height); XFreeGC(dpy, tgc); return p2; } /* sets a window background from a colorset * if width or height are zero the window size is queried */ void SetWindowBackgroundWithOffset( Display *dpy, Window win, int x_off, int y_off, unsigned int width, unsigned int height, colorset_t *colorset, unsigned int depth, GC gc, Bool clear_area) { Pixmap pixmap = None; Pixmap mask = None; union { XID junk; unsigned int ui_junk; int i_junk; } XID_int; if (0 == width || 0 == height) { if (!XGetGeometry( dpy, win, &XID_int.junk, &XID_int.i_junk, &XID_int.i_junk, (unsigned int *)&width, (unsigned int *)&height, &XID_int.ui_junk, &XID_int.ui_junk)) { return; } } if (FHaveShapeExtension && colorset->shape_mask) { mask = CreateBackgroundPixmap( dpy, None, width, height, colorset, 1, None, True); if (mask != None) { FShapeCombineMask( dpy, win, FShapeBounding, 0, 0, mask, FShapeSet); XFreePixmap(dpy, mask); } } if (!colorset->pixmap) { /* use the bg pixel */ XSetWindowBackground(dpy, win, colorset->bg); if (clear_area) { XClearArea(dpy, win, 0, 0, width, height, True); } } else { pixmap = CreateOffsetBackgroundPixmap( dpy, win, x_off, y_off, width, height, colorset, depth, gc, False); if (pixmap) { XSetWindowBackgroundPixmap(dpy, win, pixmap); if (clear_area) { XClearArea(dpy, win, 0, 0, width, height, True); } if (pixmap != ParentRelative) { XFreePixmap(dpy, pixmap); } } } return; } Bool UpdateBackgroundTransparency( Display *dpy, Window win, int width, int height, colorset_t *colorset, unsigned int depth, GC gc, Bool clear_area) { if (!CSETS_IS_TRANSPARENT(colorset)) { return False; } else if (!CSETS_IS_TRANSPARENT_PR_PURE(colorset)) { SetWindowBackgroundWithOffset( dpy, win, 0, 0, width, height, colorset, depth, gc, True); } else { XClearArea(dpy, win, 0,0,0,0, clear_area); } return True; } void SetWindowBackground( Display *dpy, Window win, int width, int height, colorset_t *colorset, unsigned int depth, GC gc, Bool clear_area) { SetWindowBackgroundWithOffset( dpy, win, 0, 0, width, height, colorset, depth, gc, clear_area); return; } void GetWindowBackgroundPixmapSize( colorset_t *cs_t, int width, int height, int *w, int *h) { if (cs_t->pixmap == None) { *w = *h = 1; } else { *w = cs_t->width; *h = cs_t->height; switch (cs_t->pixmap_type) { case PIXMAP_STRETCH_ASPECT: get_aspect_dimensions( w, h, width, height, cs_t->width, cs_t->height); break; case PIXMAP_STRETCH_X: *w = width; break; case PIXMAP_STRETCH_Y: *h = height; break; default: break; } } } static int is_bad_gc = 0; static int BadGCErrorHandler(Display *dpy, XErrorEvent *error) { if (error->error_code == BadGC) { is_bad_gc = 1; return 0; } else { int rc; /* delegate error to original handler */ rc = ferror_call_next_error_handler(dpy, error); return rc; } } /* create a pixmap suitable for plonking on the background of a part of a * window */ Pixmap CreateOffsetBackgroundPixmap( Display *dpy, Window win, int x, int y, int width, int height, colorset_t *colorset, unsigned int depth, GC gc, Bool is_shape_mask) { Pixmap pixmap = None; Pixmap cs_pixmap = None; XGCValues xgcv; static GC shape_gc = None; GC fill_gc = None; /* not static as dpy may change (FvwmBacker) */ int cs_width; int cs_height; Bool cs_keep_aspect; Bool cs_stretch_x; Bool cs_stretch_y; if (colorset->pixmap == ParentRelative && !is_shape_mask && colorset->tint_percent > 0) { FvwmRenderAttributes fra; fra.mask = FRAM_DEST_IS_A_WINDOW | FRAM_HAVE_TINT; fra.tint = colorset->tint; fra.tint_percent = colorset->tint_percent; MyXGrabServer(dpy); pixmap = PGraphicsCreateTransparency( dpy, win, &fra, gc, x, y, width, height, True); MyXUngrabServer(dpy); if (pixmap == None) { return ParentRelative; } return pixmap; } else if (colorset->pixmap == ParentRelative && !is_shape_mask) { return ParentRelative; } else if (CSETS_IS_TRANSPARENT_ROOT(colorset) && colorset->pixmap && !is_shape_mask) { int sx,sy; int h,w; XID dummy; cs_pixmap = colorset->pixmap; cs_width = colorset->width; cs_height = colorset->height; if (CSETS_IS_TRANSPARENT_ROOT_PURE(colorset)) { /* check if it is still here */ union { XID junk; unsigned int ui_junk; int i_junk; } XID_int; /* a priori we should grab the server, but this * cause PositiveWrite error when you move a * window with a transparent title bar */ if (!XGetGeometry( dpy, colorset->pixmap, &XID_int.junk, &XID_int.i_junk, &XID_int.i_junk, (unsigned int *)&w, (unsigned int *)&h, &XID_int.ui_junk, &XID_int.ui_junk) || w != cs_width || h != cs_height) { return None; } } XTranslateCoordinates( dpy, win, DefaultRootWindow(dpy), x, y, &sx, &sy, &dummy); pixmap = XCreatePixmap(dpy, win, width, height, Pdepth); if (!pixmap) { return None; } /* make sx and sy positif */ while (sx < 0) { sx = sx + cs_width; } while (sy < 0) { sy = sy + cs_height; } /* make sx and sy in (0,0,cs_width,cs_height) */ while (sx >= cs_width) { sx = sx - cs_width; } while (sy >= cs_height) { sy = sy - cs_height; } xgcv.fill_style = FillTiled; xgcv.tile = cs_pixmap; xgcv.ts_x_origin = cs_width-sx; xgcv.ts_y_origin = cs_height-sy; fill_gc = fvwmlib_XCreateGC( dpy, win, GCTile | GCTileStipXOrigin | GCTileStipYOrigin | GCFillStyle, &xgcv); if (fill_gc == None) { XFreePixmap(dpy, pixmap); return None; } XSync(dpy, False); is_bad_gc = 0; ferror_set_temp_error_handler(BadGCErrorHandler); XFillRectangle(dpy, pixmap, fill_gc, 0, 0, width, height); if ( is_bad_gc == 0 && CSETS_IS_TRANSPARENT_ROOT_PURE(colorset) && colorset->tint_percent > 0) { FvwmRenderAttributes fra; fra.mask = FRAM_HAVE_TINT; fra.tint = colorset->tint; fra.tint_percent = colorset->tint_percent; PGraphicsRenderPixmaps( dpy, win, pixmap, None, None, Pdepth, &fra, pixmap, fill_gc, None, None, 0, 0, width, height, 0, 0, width, height, False); } XSync(dpy, False); ferror_reset_temp_error_handler(); if (is_bad_gc == 1) { is_bad_gc = 0; XFreePixmap(dpy, pixmap); pixmap = None; } XFreeGC(dpy,fill_gc); return pixmap; } if (!is_shape_mask) { cs_pixmap = colorset->pixmap; cs_width = colorset->width; cs_height = colorset->height; cs_keep_aspect = (colorset->pixmap_type == PIXMAP_STRETCH_ASPECT); cs_stretch_x = (colorset->pixmap_type == PIXMAP_STRETCH_X) || (colorset->pixmap_type == PIXMAP_STRETCH); cs_stretch_y = (colorset->pixmap_type == PIXMAP_STRETCH_Y) || (colorset->pixmap_type == PIXMAP_STRETCH); } else { /* In spite of the name, win contains the pixmap */ cs_pixmap = colorset->shape_mask; win = colorset->shape_mask; if (shape_gc == None) { xgcv.foreground = 1; xgcv.background = 0; /* create a gc for 1 bit depth */ shape_gc = fvwmlib_XCreateGC( dpy, win, GCForeground|GCBackground, &xgcv); } gc = shape_gc; cs_width = colorset->shape_width; cs_height = colorset->shape_height; cs_keep_aspect = (colorset->shape_type == SHAPE_STRETCH_ASPECT); cs_stretch_x = !(colorset->shape_type == SHAPE_TILED); cs_stretch_y = !(colorset->shape_type == SHAPE_TILED); } if (cs_pixmap == None) { xgcv.foreground = colorset->bg; fill_gc = fvwmlib_XCreateGC(dpy, win, GCForeground, &xgcv); /* create a solid pixmap - not very useful most of the time */ pixmap = XCreatePixmap(dpy, win, 1, 1, depth); XFillRectangle(dpy, pixmap, fill_gc, 0, 0, 1, 1); XFreeGC(dpy,fill_gc); } else if (cs_keep_aspect) { Bool trim_side; int big_width, big_height; Pixmap big_pixmap; int x, y; /* make a pixmap big enough to cover the destination but with * the aspect ratio of the cs_pixmap */ trim_side = get_aspect_dimensions( &big_width, &big_height, width, height, cs_width, cs_height); big_pixmap = CreateStretchPixmap( dpy, cs_pixmap, cs_width, cs_height, depth, big_width, big_height, gc); /* work out where to trim */ x = trim_side ? (big_width - width) / 2 : 0; y = trim_side ? 0 : (big_height - height) / 2; pixmap = XCreatePixmap(dpy, cs_pixmap, width, height, depth); if (pixmap && big_pixmap) { XCopyArea( dpy, big_pixmap, pixmap, gc, x, y, width, height, 0, 0); } if (big_pixmap) { XFreePixmap(dpy, big_pixmap); } } else if (!cs_stretch_x && !cs_stretch_y) { /* it's a tiled pixmap, create an unstretched one */ if (!is_shape_mask) { pixmap = XCreatePixmap( dpy, cs_pixmap, cs_width, cs_height, depth); if (pixmap) { XCopyArea( dpy, cs_pixmap, pixmap, gc, 0, 0, cs_width, cs_height, 0, 0); } } else { /* can't tile masks, create a tiled version of the * mask */ pixmap = CreateTiledPixmap( dpy, cs_pixmap, cs_width, cs_height, width, height, 1, gc); } } else if (!cs_stretch_x) { /* it's an HGradient */ pixmap = CreateStretchYPixmap( dpy, cs_pixmap, cs_width, cs_height, depth, height, gc); } else if (!cs_stretch_y) { /* it's a VGradient */ pixmap = CreateStretchXPixmap( dpy, cs_pixmap, cs_width, cs_height, depth, width, gc); } else { /* It's a full window pixmap */ pixmap = CreateStretchPixmap( dpy, cs_pixmap, cs_width, cs_height, depth, width, height, gc); } if (x != 0 || y != 0) { Pixmap p2; p2 = ScrollPixmap( dpy, pixmap, gc, x, y, width, height, depth); if (p2 != None && p2 != ParentRelative && p2 != pixmap) { XFreePixmap(dpy, pixmap); pixmap = p2; } } return pixmap; } /* create a pixmap suitable for plonking on the background of a window */ Pixmap CreateBackgroundPixmap(Display *dpy, Window win, int width, int height, colorset_t *colorset, unsigned int depth, GC gc, Bool is_shape_mask) { return CreateOffsetBackgroundPixmap( dpy, win, 0, 0, width, height, colorset, depth, gc, is_shape_mask); } /* Draws a colorset background into the specified rectangle in the target * drawable. */ void SetRectangleBackground( Display *dpy, Window win, int x, int y, int width, int height, colorset_t *colorset, unsigned int depth, GC gc) { SetClippedRectangleBackground( dpy, win, x, y, width, height, NULL, colorset, depth, gc); return; } /* Draws a colorset background into the specified rectangle in the target * drawable. */ void SetClippedRectangleBackground( Display *dpy, Window win, int x, int y, int width, int height, XRectangle *clip, colorset_t *colorset, unsigned int depth, GC gc) { GC draw_gc; Pixmap pixmap2; Pixmap pixmap = None; static int last_depth = -1; static GC last_gc = None; XGCValues xgcv; Pixmap clipmask = None; GC clip_gc = None; Bool keep_aspect = (colorset->pixmap_type == PIXMAP_STRETCH_ASPECT); Bool stretch_x = (colorset->pixmap_type == PIXMAP_STRETCH_X) || (colorset->pixmap_type == PIXMAP_STRETCH); Bool stretch_y = (colorset->pixmap_type == PIXMAP_STRETCH_Y) || (colorset->pixmap_type == PIXMAP_STRETCH); int dest_x, dest_y, dest_w, dest_h; if (clip) { dest_x = clip->x; dest_y = clip->y; dest_w = clip->width; dest_h = clip->height; } else { dest_x = x; dest_y = y; dest_w = width; dest_h = height; } if (CSETS_IS_TRANSPARENT_PR_TINT(colorset)) { XClearArea(dpy, win, dest_x, dest_y, dest_w, dest_h, False); PGraphicsTintRectangle( dpy, win, colorset->tint, colorset->tint_percent, win, True, gc, None, None, dest_x, dest_y, dest_w, dest_h); return; } if (CSETS_IS_TRANSPARENT_PR_PURE(colorset)) { XClearArea(dpy, win, dest_x, dest_y, dest_w, dest_h, False); /* don't do anything */ return; } if (CSETS_IS_TRANSPARENT_ROOT(colorset)) { /* FIXME: optimize this ! */ x = y = 0; width = width + dest_x; height = height + dest_y; } /* minimize gc creation by remembering the last requested depth */ if (last_gc != None && depth != last_depth) { XFreeGC(dpy, last_gc); last_gc = None; } if (last_gc == None) { last_gc = fvwmlib_XCreateGC(dpy, win, 0, &xgcv); } draw_gc = last_gc; last_depth = depth; if (FHaveShapeExtension && colorset->shape_mask != None) { clipmask = CreateBackgroundPixmap( dpy, 0, width, height, colorset, 1, None, True); if (clipmask) { /* create a GC for clipping */ xgcv.clip_x_origin = x; xgcv.clip_y_origin = y; xgcv.clip_mask = clipmask; clip_gc = fvwmlib_XCreateGC( dpy, win, GCClipXOrigin | GCClipYOrigin | GCClipMask, &xgcv); draw_gc = clip_gc; } } if (!colorset->pixmap) { /* use the bg pixel */ XSetForeground(dpy, draw_gc, colorset->bg); XFillRectangle( dpy, win, draw_gc, dest_x, dest_y, dest_w, dest_h); } else { pixmap = CreateBackgroundPixmap( dpy, win, width, height, colorset, depth, gc, False); if (keep_aspect) { /* nothing to do */ } if (stretch_x || stretch_y) { if (!stretch_x && colorset->width != width) { pixmap2 = CreateStretchXPixmap( dpy, pixmap, colorset->width, height, depth, width, gc); XFreePixmap(dpy, pixmap); pixmap = pixmap2; } if (!stretch_y && colorset->height != height) { pixmap2 = CreateStretchYPixmap( dpy, pixmap, width, colorset->height, depth, height, gc); XFreePixmap(dpy, pixmap); pixmap = pixmap2; } } else { pixmap2 = CreateTiledPixmap( dpy, pixmap, colorset->width, colorset->height, width, height, depth, gc); XFreePixmap(dpy, pixmap); pixmap = pixmap2; } if (pixmap) { /* Copy the pixmap into the rectangle. */ XCopyArea( dpy, pixmap, win, draw_gc, dest_x - x, dest_y - y, dest_w, dest_h, dest_x, dest_y); XFreePixmap(dpy, pixmap); } } if (FHaveShapeExtension) { if (clipmask != None) { XFreePixmap(dpy, clipmask); } if (clip_gc != None) { XFreeGC(dpy, clip_gc); } } return; } fvwm-2.7.0/libs/ClientMsg.c0000644000175000017500000000215214147024700012401 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ #include "config.h" #include "ClientMsg.h" Atom _XA_WM_PROTOCOLS = None; void send_clientmessage (Display *disp, Window w, Atom a, Time timestamp) { XClientMessageEvent ev; if (_XA_WM_PROTOCOLS == None) _XA_WM_PROTOCOLS = XInternAtom(disp, "WM_PROTOCOLS", False); ev.type = ClientMessage; ev.window = w; ev.message_type = _XA_WM_PROTOCOLS; ev.format = 32; ev.data.l[0] = a; ev.data.l[1] = timestamp; FSendEvent(disp, w, False, 0L, (XEvent *) &ev); } fvwm-2.7.0/libs/XResource.c0000644000175000017500000002111514147024700012433 00000000000000/* -*-c-*- */ /* Copyright (C) 1999 Dominik Vogt */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ** XResource.c: ** These routines provide modules with an interface to parse all kinds of ** configuration options (X resources, command line options and configuration ** file lines) in the same way (Xrm database). */ #include "config.h" #include #include #include "fvwmlib.h" #include "XResource.h" /* * If you have a module MyModule and want to parse X resources as well as * command line options and a config file: * *** EXAMPLE */ #if 0 #include void main(int argc, char **argv) { const char *MyName = "MyModule"; XrmDatabase db = NULL; XrmValue *rm_value; char *line; /* our private options */ const XrmOptionDescRec my_opts[] = { { "-iconic", ".Iconic", XrmoptionNoArg, "any_string" }, { "-foo", "*bar", XrmoptionSepArg, NULL } }; int opt_argc = argc - 6; /* options start at 6th argument for modules */ char **opt_argv = argv + 6; /* ... (open config file, etc.) */ /* Get global X resources */ MergeXResources(NULL, &db, False); /* config file descriptor in fd; config file takes precedence over X * resources (this may not be what you want). */ for (GetConfigLine(fd, &line); line != NULL; GetConfigLine(fd, &line)) { if (!MergeConfigLineResource(&db, line, MyName, '*')) { /* Parse other lines here (e.g. "ImagePath") */ } else { /* You may still have to parse the line here yourself (e.g. * FvwmButtons may have multiple lines for the same resource). */ } } /* command line takes precedence over all */ MergeCmdLineResources(&db, (XrmOptionDescList)my_opts, 2, MyName, &opt_argc, opt_argv, True /*no default options*/); /* Now parse the database values: */ if (GetResourceString(db, "iconic", MyName, &rm_value)) { /* Just see if there is *any* string and don't mind it's value. */ /* flags |= ICONIC */ } if (GetResourceString(db, "bar", MyName, &rm_value)) { /* ... */ } /* ... */ XrmDestroyDatabase(db); } #endif /*** END OF EXAMPLE ***/ /* Default option table */ static XrmOptionDescRec default_opts[] = { { "-fg", "*Foreground", XrmoptionSepArg, NULL }, { "-bg", "*Background", XrmoptionSepArg, NULL }, { "-fn", "*Font", XrmoptionSepArg, NULL }, { "-geometry", "*Geometry", XrmoptionSepArg, NULL }, { "-title", "*Title", XrmoptionSepArg, NULL } /* Remember to update NUM_DEFAULT_OPTIONS if you change this list! */ }; #define NUM_DEFAULT_OPTS 5 /* internal function */ static void DoMergeString(char *resource, XrmDatabase *ptarget, Bool override) { XrmDatabase db; if (!resource) return; db = XrmGetStringDatabase(resource); XrmCombineDatabase(db, ptarget, override); } /* * * Merges all X resources for the display/screen into a Xrm database. * If the database does not exist (*pdb == NULL), a new database is created. * If override is True, existing entries of the same name are overwritten. * * Please remember to destroy the database with XrmDestroyDatabase(*pdb) * if you do not need it amymore. * */ void MergeXResources(Display *dpy, XrmDatabase *pdb, Bool override) { if (!*pdb) /* create new database */ XrmPutStringResource(pdb, "", ""); DoMergeString(XResourceManagerString(dpy), pdb, override); DoMergeString(XScreenResourceString(DefaultScreenOfDisplay(dpy)), pdb, override); } /* * * Parses the command line given through pargc/argv and puts recognized * entries into the Xrm database *pdb (if *pdb is NULL a new database is * created). The caller may provide an option list in XrmOptionDescList * format (see XrmParseCommand manpage) and/or parse only standard options * (fg, bg, geometry, fn, title). User given options have precedence over * standard options which are disabled if fNoDefaults is True. Existing * values are overwritten. * * All recognised options are removed from the command line (*pargc and * argv are updated accordingly). * * Please remember to destroy the database with XrmDestroyDatabase(*pdb) * if you do not need it amymore. * */ void MergeCmdLineResources(XrmDatabase *pdb, XrmOptionDescList opts, int num_opts, char *name, int *pargc, char **argv, Bool fNoDefaults) { if (!name) return; if (opts && num_opts > 0) XrmParseCommand(pdb, opts, num_opts, name, pargc, argv); if (!fNoDefaults) XrmParseCommand(pdb, default_opts, NUM_DEFAULT_OPTS, name, pargc, argv); } /* * * Takes a line from a config file and puts a corresponding value into the * Xrm database *pdb (will be created if *pdb is NULL). 'prefix' is the * name of the module. A specific type of binding in the database must be * provided in bindstr (either "*" or "."). Leading unquoted whitespace are * stripped from value. Existing values in the database are overwritten. * True is returned if the line was indeed merged into the database (i.e. it * had the correct format) or False if not. * * Example: If prefix = "MyModule" and bindstr = "*", the line * * *MyModuleGeometry 80x25+0+0 * * will be put into the database as if you had this line in your .Xdefaults: * * MyModule*Geometry: 80x25+0+0 * * Please remember to destroy the database with XrmDestroyDatabase(*pdb) * if you do not need it amymore. * */ Bool MergeConfigLineResource(XrmDatabase *pdb, char *line, char *prefix, char *bindstr) { int len; char *end; char *value; char *myvalue; char *resource; /* translate "*(prefix)(suffix)" to "(prefix)(binding)(suffix)", * e.g. "*FvwmPagerGeometry" to "FvwmPager.Geometry" */ if (!line || *line != '*') return False; line++; len = (prefix) ? strlen(prefix) : 0; if (!prefix || strncasecmp(line, prefix, len)) return False; line += len; end = line; while (*end && !isspace((unsigned char)*end)) end++; if (line == end) return False; value = end; while (*value && isspace((unsigned char)*value)) value++; /* prefix*suffix: value */ resource = (char *)safemalloc(len + (end - line) + 2); strcpy(resource, prefix); strcat(resource, bindstr); strncat(resource, line, end - line); len = strlen(value); myvalue = (char *)safemalloc(len + 1); strcpy(myvalue, value); for (len--; len >= 0 && isspace((unsigned char)myvalue[len]); len--) myvalue[len] = 0; /* merge string into database */ XrmPutStringResource(pdb, resource, myvalue); free(resource); free(myvalue); return True; } /* * * Reads the string-value for the pair prefix/resource from the Xrm database * db and returns a pointer to it. The string may only be read and must not * be freed by the caller. 'prefix' is the class name (usually the name of * the module). If no value is found in the database, *val will be NULL. * True is returned if a value was found, False if not. If you are only * interested if there is a string, but not it's value, you can set val to * NULL. * * Example: * * GetResourceString(db, "Geometry", "MyModule", &r) * * returns the resource value of the "Geometry" resource for MyModule in r. * */ Bool GetResourceString( XrmDatabase db, const char *resource, const char *prefix, XrmValue *xval) { char *str_type; char *name; char *Name; int i; name = (char *)safemalloc(strlen(resource) + strlen(prefix) + 2); Name = (char *)safemalloc(strlen(resource) + strlen(prefix) + 2); strcpy(name, prefix); strcat(name, "."); strcat(name, resource); strcpy(Name, name); if (isupper(name[0])) name[0] = tolower(name[0]); if (islower(Name[0])) Name[0] = toupper(Name[0]); i = strlen(prefix) + 1; if (isupper(name[i])) name[i] = tolower(name[i]); if (islower(Name[i])) Name[i] = toupper(Name[i]); if (!XrmGetResource(db, name, Name, &str_type, xval) || xval->addr == NULL || xval->size == 0) { free(name); free(Name); xval->size = 0; xval->addr = NULL; return False; } free(name); free(Name); return True; } fvwm-2.7.0/libs/Cursor.c0000644000175000017500000001017314147024700011773 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* Modification History */ /* Created on 10/05/01 by Dan Espen (dane): Extracted from fvwm/cursor.c. Contains common routine to verify and convert a cursor name into a cursor number from X11/cursorfont.h. Used by fvwm CursorStyle command and FvwmForm. */ #include "config.h" #include #include "fvwmlib.h" #include #include "Cursor.h" /* * fvwmCursorNameToIndex: return the number of a X11 cursor from its * name, if not found return -1. */ int fvwmCursorNameToIndex (char *cursor_name) { static const struct CursorNameIndex { const char *name; unsigned int number; } cursor_table[] = { {"arrow", XC_arrow}, {"based_arrow_down", XC_based_arrow_down}, {"based_arrow_up", XC_based_arrow_up}, {"boat", XC_boat}, {"bogosity", XC_bogosity}, {"bottom_left_corner", XC_bottom_left_corner}, {"bottom_right_corner", XC_bottom_right_corner}, {"bottom_side", XC_bottom_side}, {"bottom_tee", XC_bottom_tee}, {"box_spiral", XC_box_spiral}, {"center_ptr", XC_center_ptr}, {"circle", XC_circle}, {"clock", XC_clock}, {"coffee_mug", XC_coffee_mug}, {"cross", XC_cross}, {"cross_reverse", XC_cross_reverse}, {"crosshair", XC_crosshair}, {"diamond_cross", XC_diamond_cross}, {"dot", XC_dot}, {"dotbox", XC_dotbox}, {"double_arrow", XC_double_arrow}, {"draft_large", XC_draft_large}, {"draft_small", XC_draft_small}, {"draped_box", XC_draped_box}, {"exchange", XC_exchange}, {"fleur", XC_fleur}, {"gobbler", XC_gobbler}, {"gumby", XC_gumby}, {"hand1", XC_hand1}, {"hand2", XC_hand2}, {"heart", XC_heart}, {"icon", XC_icon}, {"iron_cross", XC_iron_cross}, {"left_ptr", XC_left_ptr}, {"left_side", XC_left_side}, {"left_tee", XC_left_tee}, {"leftbutton", XC_leftbutton}, {"ll_angle", XC_ll_angle}, {"lr_angle", XC_lr_angle}, {"man", XC_man}, {"middlebutton", XC_middlebutton}, {"mouse", XC_mouse}, {"pencil", XC_pencil}, {"pirate", XC_pirate}, {"plus", XC_plus}, {"question_arrow", XC_question_arrow}, {"right_ptr", XC_right_ptr}, {"right_side", XC_right_side}, {"right_tee", XC_right_tee}, {"rightbutton", XC_rightbutton}, {"rtl_logo", XC_rtl_logo}, {"sailboat", XC_sailboat}, {"sb_down_arrow", XC_sb_down_arrow}, {"sb_h_double_arrow", XC_sb_h_double_arrow}, {"sb_left_arrow", XC_sb_left_arrow}, {"sb_right_arrow", XC_sb_right_arrow}, {"sb_up_arrow", XC_sb_up_arrow}, {"sb_v_double_arrow", XC_sb_v_double_arrow}, {"sizing", XC_sizing}, {"spider", XC_spider}, {"spraycan", XC_spraycan}, {"star", XC_star}, {"target", XC_target}, {"tcross", XC_tcross}, {"top_left_arrow", XC_top_left_arrow}, {"top_left_corner", XC_top_left_corner}, {"top_right_corner", XC_top_right_corner}, {"top_side", XC_top_side}, {"top_tee", XC_top_tee}, {"trek", XC_trek}, {"ul_angle", XC_ul_angle}, {"umbrella", XC_umbrella}, {"ur_angle", XC_ur_angle}, {"watch", XC_watch}, {"x_cursor", XC_X_cursor}, {"xterm", XC_xterm}, }; int cond; int down = 0; int up = (sizeof cursor_table / sizeof cursor_table[0]) - 1; int middle; char temp[20]; char *s; if (!cursor_name || cursor_name[0] == 0 || strlen(cursor_name) >= sizeof temp) return -1; strcpy(temp, cursor_name); for (s = temp; *s != 0; s++) if (isupper(*s)) *s = tolower(*s); while (down <= up) { middle= (down + up) / 2; if ((cond = strcmp(temp, cursor_table[middle].name)) < 0) up = middle - 1; else if (cond > 0) down = middle + 1; else return cursor_table[middle].number; } return -1; } fvwm-2.7.0/libs/safemalloc.c0000644000175000017500000000522614147024700012627 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ #include "config.h" #include #include "safemalloc.h" static void alloc_failed(char *c, int length) { fprintf(stderr, "%s of %d bytes failed. Exiting\n", c, length); exit(1); } /*********************************************************************** * * Procedure: * safemalloc - mallocs specified space or exits if there's a * problem * ***********************************************************************/ char *safemalloc(int length) { char *ptr; if(length <= 0) length = 1; ptr = malloc(length); if(ptr == (char *)0) { /* doesn't return */ alloc_failed("malloc", length); } return ptr; } /*********************************************************************** * * Procedure: * safecalloc - callocs specified space or exits if there's a * problem * ***********************************************************************/ char *safecalloc(int num, int length) { char *ptr; ptr = calloc(num, length); if(ptr == (char *)0) { /* doesn't return */ alloc_failed("calloc", length); } return ptr; } /*********************************************************************** * * Procedure: * saferealloc - reallocs specified space or exits if there's a * problem * ***********************************************************************/ char *saferealloc(char *src, int length) { char *ptr; if (src) ptr = realloc((void *)src, length); else ptr = malloc(length); if(ptr == (char *)0) { /* doesn't return */ alloc_failed("realloc", length); } return ptr; } /*********************************************************************** * * Procedure: * safestrdup - duplicates a string or exits if there's a * problem * ***********************************************************************/ char *safestrdup(const char *src) { char *cpy = strdup(src); if (cpy == (char *)0) { /* doesn't return */ alloc_failed("strdup", strlen(src) + (size_t)1); } return cpy; } fvwm-2.7.0/libs/XResource.h0000644000175000017500000000103014147024700012432 00000000000000#ifndef LIB_XRESOURCE_H #define LIB_XRESOURCE_H /* * Wrappers around Xrm routines (XResources.c) */ void MergeXResources(Display *dpy, XrmDatabase *pdb, Bool override); void MergeCmdLineResources( XrmDatabase *pdb, XrmOptionDescList opts, int num_opts, char *name, int *pargc, char **argv, Bool fNoDefaults); Bool MergeConfigLineResource( XrmDatabase *pdb, char *line, char *prefix, char *bindstr); Bool GetResourceString( XrmDatabase db, const char *resource, const char *prefix, XrmValue *xval); #endif /* LIB_XRESOURCE_H */ fvwm-2.7.0/libs/Target.h0000644000175000017500000000062314147024700011750 00000000000000#ifndef LIB_TARGET_H #define LIB_TARGET_H void fvwmlib_keyboard_shortcuts( Display *dpy, int screen, XEvent *Event, int x_move_size, int y_move_size, int *x_defect, int *y_defect, int ReturnEvent); void fvwmlib_get_target_window( Display *dpy, int screen, char *MyName, Window *app_win, Bool return_subwindow); Window fvwmlib_client_window(Display *dpy, Window input); #endif /* LIB_TARGET_H */ fvwm-2.7.0/libs/PictureGraphics.c0000644000175000017500000007664614147024700013633 00000000000000/* -*-c-*- */ /* Copyright (C) 2002 Olivier Chapuis */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include #include #include "PictureBase.h" #include "Colorset.h" #include "FRenderInit.h" #include "FRenderInterface.h" #include "Graphics.h" #include "PictureGraphics.h" #include "PictureUtils.h" #include "FImage.h" #include "Grab.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ static Bool PGrabImageError = True; /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ static int FSetBackingStore(Display *dpy, Window win, int backing_store) { XWindowAttributes attributes; XSetWindowAttributes set_attributes; int old_bs; XGetWindowAttributes(dpy, win, &attributes); if (attributes.backing_store == backing_store) { return -1; } old_bs = attributes.backing_store; set_attributes.backing_store = backing_store; XChangeWindowAttributes(dpy, win, CWBackingStore, &set_attributes); return old_bs; } static void PCopyArea(Display *dpy, Pixmap pixmap, Pixmap mask, int depth, Drawable d, GC gc, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y) { XGCValues gcv; unsigned long gcm; GC my_gc = None; if (gc == None) { my_gc = fvwmlib_XCreateGC(dpy, d, 0, NULL); } gcm = GCClipMask | GCClipXOrigin | GCClipYOrigin; gcv.clip_x_origin = dest_x - src_x; /* */ gcv.clip_y_origin = dest_y - src_y; /* */ if (depth == Pdepth) { gcv.clip_mask = mask; if (my_gc != None) { XChangeGC(dpy,my_gc,gcm,&gcv); } else { XChangeGC(dpy,gc,gcm,&gcv); } XCopyArea(dpy, pixmap, d, (my_gc != None)? my_gc:gc, src_x, src_y, src_w, src_h, dest_x, dest_y); } else { /* monochrome bitmap */ gcv.clip_mask = mask; if (my_gc != None) { gcv.foreground = PictureWhitePixel(); gcv.background = PictureBlackPixel(); gcm |= GCBackground|GCForeground; XChangeGC(dpy,my_gc,gcm,&gcv); } else { XChangeGC(dpy,gc,gcm,&gcv); } XCopyPlane(dpy, pixmap, d, (my_gc != None)? my_gc:gc, src_x, src_y, src_w, src_h, dest_x, dest_y, 1); } if (my_gc != None) { XFreeGC(dpy, my_gc); } else { gcm = GCClipMask; gcv.clip_mask = None; XChangeGC(dpy, gc, gcm, &gcv); } } static void PTileRectangle(Display *dpy, Window win, Pixmap pixmap, Pixmap mask, int depth, int src_x, int src_y, Drawable d, GC gc, GC mono_gc, int dest_x, int dest_y, int dest_w, int dest_h) { Pixmap tile_mask = None; XGCValues gcv; unsigned long gcm; GC my_gc = None; GC my_mono_gc = None; if (gc == None) { my_gc = fvwmlib_XCreateGC(dpy, d, 0, NULL); } if (mono_gc == None && (mask != None || Pdepth != depth)) { if (mask != None) my_mono_gc = fvwmlib_XCreateGC(dpy, mask, 0, NULL); else if (depth != Pdepth) my_mono_gc = fvwmlib_XCreateGC(dpy, pixmap, 0, NULL); } gcm = 0; if (mask != None) { /* create a till mask */ tile_mask = XCreatePixmap(dpy, win, dest_w, dest_h, 1); gcv.tile = mask; gcv.ts_x_origin = src_x; gcv.ts_y_origin = src_y; gcv.fill_style = FillTiled; gcm = GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin | GCTile; if (mono_gc != None) { XChangeGC(dpy, mono_gc, gcm, &gcv); } else { gcv.foreground = 1; gcv.background = 0; gcm |= GCBackground|GCForeground; XChangeGC(dpy, my_mono_gc, gcm, &gcv); } XFillRectangle(dpy, tile_mask, (mono_gc != None)? mono_gc:my_mono_gc, src_x, src_y, dest_w, dest_h); if (mono_gc != None) { gcv.fill_style = FillSolid; gcm = GCFillStyle; XChangeGC(dpy, mono_gc, gcm, &gcv); } } gcv.tile = pixmap; gcv.ts_x_origin = dest_x - src_x; gcv.ts_y_origin = dest_y - src_y; gcv.fill_style = FillTiled; gcm = GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin; gcv.clip_mask = tile_mask; gcv.clip_x_origin = dest_x; gcv.clip_y_origin = dest_y;; gcm |= GCClipMask | GCClipXOrigin | GCClipYOrigin; if (depth != Pdepth) { Pixmap my_pixmap = None; XChangeGC(dpy, (mono_gc != None)? mono_gc:my_mono_gc, gcm, &gcv); my_pixmap = XCreatePixmap(dpy, win, dest_w, dest_h, 1); XFillRectangle(dpy, my_pixmap, (mono_gc != None)? mono_gc:my_mono_gc, 0, 0, dest_w, dest_h); gcv.clip_mask = my_pixmap; gcv.fill_style = FillSolid; gcm = GCFillStyle | GCClipMask; XChangeGC(dpy, (mono_gc != None)? mono_gc:my_mono_gc, gcm, &gcv); XCopyPlane(dpy, my_pixmap, d, (my_gc != None)? my_gc:gc, 0, 0, dest_w, dest_h, dest_x, dest_y, 1); if (my_pixmap != None) { XFreePixmap(dpy, my_pixmap); } } else { XChangeGC(dpy, (gc != None)? gc:my_gc, gcm, &gcv); XFillRectangle(dpy, d, (gc != None)? gc:my_gc, dest_x, dest_y, dest_w, dest_h); } if (my_gc != None) { XFreeGC(dpy, my_gc); } else { gcv.clip_mask = None; gcv.fill_style = FillSolid; gcm = GCFillStyle | GCClipMask; XChangeGC(dpy, gc, gcm, &gcv); } if (my_mono_gc != None) { XFreeGC(dpy, my_mono_gc); } else if (mono_gc != None) { gcv.clip_mask = None; gcv.fill_style = FillSolid; gcm = GCFillStyle | GCClipMask; XChangeGC(dpy, mono_gc, gcm, &gcv); } if (tile_mask != None) { XFreePixmap(dpy, tile_mask); } } static void PGrabImageErrorHandler(void) { PGrabImageError = True; } static FImage *PGrabXImage( Display *dpy, Drawable d, int x, int y, int w, int h, Bool d_is_a_window) { Bool try_to_grab = True; XWindowAttributes xwa; XErrorHandler saved_eh = NULL; FImage *fim = NULL; PGrabImageError = 0; if (d_is_a_window) { MyXGrabServer(dpy); XGetWindowAttributes(dpy, d, &xwa); XSync(dpy, False); if (xwa.map_state != IsViewable && xwa.backing_store == NotUseful) { try_to_grab = False; #if 0 fprintf(stderr, "Bad attribute! %i,%i\n", xwa.map_state != IsViewable, xwa.backing_store == NotUseful); #endif } else { saved_eh = XSetErrorHandler( (XErrorHandler) PGrabImageErrorHandler); #if 0 fprintf(stderr, "Attribute ok! %i,%i\n", xwa.map_state != IsViewable, xwa.backing_store == NotUseful); #endif } } if (try_to_grab) { fim = FGetFImage(dpy, d, Pvisual, Pdepth, x, y, w, h, AllPlanes, ZPixmap); if (PGrabImageError) { #if 0 fprintf(stderr, "XGetImage error during the grab\n"); #endif if (fim != NULL) { FDestroyFImage(dpy, fim); fim = NULL; } } if (d_is_a_window) { XSetErrorHandler((XErrorHandler) saved_eh); } } if (d_is_a_window) { MyXUngrabServer(dpy); } return fim; } static Pixmap PCreateRenderPixmap( Display *dpy, Window win, Pixmap pixmap, Pixmap mask, Pixmap alpha, int depth, int added_alpha_percent, Pixel tint, int tint_percent, Bool d_is_a_window, Drawable d, GC gc, GC mono_gc, GC alpha_gc, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, int dest_w, int dest_h, Bool do_repeat, int *new_w, int *new_h, Bool *new_do_repeat, Pixmap *new_mask) { FImage *pixmap_fim = NULL; FImage *mask_fim = NULL; FImage *alpha_fim = NULL; FImage *dest_fim = NULL; FImage *new_mask_fim = NULL; FImage *out_fim = NULL; Pixmap pixmap_copy = None; Pixmap src_pix = None; Pixmap out_pix = None; unsigned short *am = NULL; XColor *colors = NULL, *dest_colors = NULL; XColor tint_color, c; int w ,h, n_src_w, n_src_h; int j, i, j1, i1, m = 0, k = 0, l = 0; Bool do_free_mono_gc = False; Bool make_new_mask = False; Bool error = False; *new_mask = None; *new_do_repeat = do_repeat; if (depth != Pdepth) { pixmap_copy = XCreatePixmap(dpy, win, src_w, src_h, Pdepth); if (gc == None) { gc = PictureDefaultGC(dpy, win); } if (pixmap_copy && gc) { XCopyPlane( dpy, pixmap, pixmap_copy, gc, src_x, src_y, src_w, src_h, 0, 0, 1); } else { error = True; goto bail; } src_x = src_y = 0; } src_pix = (pixmap_copy)? pixmap_copy:pixmap; if (src_pix == ParentRelative) { pixmap_fim = PGrabXImage( dpy, d, dest_x, dest_y, dest_w, dest_h, d_is_a_window); } else { pixmap_fim = FGetFImage( dpy, src_pix, Pvisual, Pdepth, src_x, src_y, src_w, src_h, AllPlanes, ZPixmap); } if (!pixmap_fim) { error = True; goto bail; } if (mask != None) { mask_fim = FGetFImage( dpy, mask, Pvisual, 1, src_x, src_y, src_w, src_h, AllPlanes, ZPixmap); if (!mask_fim) { error = True; goto bail; } if (src_x != 0 || src_y != 0) make_new_mask = True; } if (alpha != None) { alpha_fim = FGetFImage( dpy, alpha, Pvisual, FRenderGetAlphaDepth(), src_x, src_y, src_w, src_h, AllPlanes, ZPixmap); if (!alpha_fim) { error = True; goto bail; } } if (alpha != None || added_alpha_percent < 100) { dest_fim = PGrabXImage( dpy, d, dest_x, dest_y, dest_w, dest_h, d_is_a_window); /* accept this error */ } if (dest_fim && do_repeat && (dest_w > src_w || dest_h > src_h)) { *new_do_repeat = False; if (mask) { make_new_mask = True; } w = dest_w; h = dest_h; n_src_w = (w < src_w)? w:src_w; n_src_h = (h < src_h)? h:src_h; } else { n_src_w = w = (dest_w < src_w)? dest_w:src_w; n_src_h = h = (dest_h < src_h)? dest_h:src_h; } *new_w = w; *new_h = h; out_pix = XCreatePixmap(dpy, win, w, h, Pdepth); out_fim = FCreateFImage( dpy, Pvisual, Pdepth, ZPixmap, w, h); if (gc == None) { gc = PictureDefaultGC(dpy, win); } if (!out_pix || !out_fim || !gc) { error = True; goto bail; } colors = (XColor *)safemalloc(n_src_w * n_src_h * sizeof(XColor)); if (dest_fim) { dest_colors = (XColor *)safemalloc(w * h * sizeof(XColor)); } am = (unsigned short *)safemalloc( n_src_w * n_src_h * sizeof(unsigned short)); if (tint_percent > 0) { tint_color.pixel = tint; XQueryColor(dpy, Pcmap, &tint_color); } for (j = 0; j < n_src_h; j++) { for (i = 0; i < n_src_w; i++, m++) { if (mask_fim != NULL && (XGetPixel(mask_fim->im, i, j) == 0)) { am[m] = 0; } else if (alpha_fim != NULL) { am[m] = XGetPixel(alpha_fim->im, i, j); if (am[m] == 0 && !dest_fim) { make_new_mask = True; } } else { am[m] = 255; } if (added_alpha_percent < 100) { am[m] = (unsigned short) ((am[m] * added_alpha_percent) / 100); } if (am[m] > 0) { if (!dest_fim) { if (am[m] < 130) { am[m] = 0; make_new_mask = True; } else { am[m] = 255; } } else if (am[m] < 255) { dest_colors[l++].pixel = XGetPixel(dest_fim->im, i, j); } if (am[m] > 0) { colors[k++].pixel = XGetPixel(pixmap_fim->im, i, j); } } } } for (i = 0; i < k; i += 256) XQueryColors(dpy, Pcmap, &colors[i], min(k - i, 256)); if (do_repeat && dest_fim && (n_src_h < h || n_src_w < w)) { for (j1 = 0; j1 < h+n_src_h; j1 +=n_src_h) { for (i1 = 0; i1 < w+n_src_w; i1 += n_src_w) { for(j = 0; !(i1==0 && j1==0) && j < n_src_h && j+j1 < h; j++) { for(i = 0; i < n_src_w && i+i1 < w; i++) { m = j*n_src_w + i; if (am[m] > 0 && am[m] < 255) { dest_colors[l++].pixel = XGetPixel( dest_fim ->im, i1+i, j1+j); } } } } } } for (i = 0; i < l; i += 256) XQueryColors(dpy, Pcmap, &dest_colors[i], min(l - i, 256)); if (make_new_mask) { *new_mask = XCreatePixmap(dpy, win, w, h, 1); if (*new_mask) { new_mask_fim = FCreateFImage( dpy, Pvisual, 1, ZPixmap, w, h); if (mono_gc == None) { mono_gc = fvwmlib_XCreateGC( dpy, *new_mask, 0, NULL); do_free_mono_gc = True; } } } l = 0; m = 0; k = 0; c.flags = DoRed | DoGreen | DoBlue; for (j = 0; j < n_src_h; j++) { for (i = 0; i < n_src_w; i++, m++) { if (am[m] > 0) { if (*new_mask) { XPutPixel(new_mask_fim->im, i, j, 1); } if (tint_percent > 0) { colors[k].blue = (unsigned short) (((100-tint_percent)* colors[k].blue + tint_color.blue * tint_percent) / 100); colors[k].green = (unsigned short) (((100-tint_percent)* colors[k].green + tint_color.green * tint_percent) / 100); colors[k].red = (unsigned short) (((100-tint_percent)* colors[k].red + tint_color.red * tint_percent) / 100); } c.blue = colors[k].blue; c.green = colors[k].green; c.red = colors[k].red; if (am[m] < 255 && dest_fim) { c.blue = (unsigned short) (((255 - am[m])* dest_colors[l].blue + c.blue * am[m]) / 255); c.green = (unsigned short) (((255 - am[m])* dest_colors[l].green + c.green * am[m]) / 255); c.red = (unsigned short) (((255 - am[m])* dest_colors[l].red + c.red * am[m]) / 255); l++; } PictureAllocColor(Pdpy, Pcmap, &c, False); colors[k].pixel = c.pixel; k++; } else { if (dest_fim) { c.pixel = XGetPixel(dest_fim->im, i, j); } else { c.pixel = XGetPixel( pixmap_fim->im, i, j); } if (*new_mask) { XPutPixel(new_mask_fim->im, i, j, 0); } } XPutPixel(out_fim->im, i, j, c.pixel); } } /* tile: editor ligne width limit 107 !!*/ if (do_repeat && dest_fim && (n_src_h < h || n_src_w < w)) { for (j1 = 0; j1 < h+n_src_h; j1 +=n_src_h) { for (i1 = 0; i1 < w+n_src_w; i1 += n_src_w) { k = 0; for(j = 0; !(i1==0 && j1==0) && j < n_src_h; j++) { for(i = 0; i < n_src_w; i++) { m = j*n_src_w + i; if (!(i+i1 < w && j+j1 < h)) { if (am[m] > 0) { k++; } } else { if (am[m] > 0) { if (*new_mask) { XPutPixel( new_mask_fim->im, i+i1, j+j1, 1); } c.blue = colors[k].blue; c.green = colors[k].green; c.red = colors[k].red; c.pixel = colors[k].pixel; k++; if (am[m] < 255) { c.blue = (unsigned short) (((255 - am[m])* dest_colors[l].blue + c.blue * am[m]) / 255); c.green = (unsigned short) (((255 - am[m])* dest_colors[l].green + c.green * am[m]) / 255); c.red = (unsigned short) (((255 - am[m])* dest_colors[l].red + c.red * am[m]) / 255); l++; PictureAllocColor( Pdpy, Pcmap, &c, False); } } else { c.pixel = XGetPixel( dest_fim->im, i+i1, j+j1); if (*new_mask) { XPutPixel( new_mask_fim->im, i+i1, j+j1, 0); } } XPutPixel(out_fim->im, i+i1, j+j1, c.pixel); } } } } } } FPutFImage(dpy, out_pix, gc, out_fim, 0, 0, 0, 0, w, h); if (*new_mask && mono_gc) { FPutFImage( dpy, *new_mask, mono_gc, new_mask_fim, 0, 0, 0, 0, w, h); } bail: if (colors) { free(colors); } if (dest_colors) { free(dest_colors); } if (am) { free(am); } if (pixmap_copy) { XFreePixmap(dpy, pixmap_copy); } if (pixmap_fim) { FDestroyFImage(dpy, pixmap_fim); } if (mask_fim) { FDestroyFImage(dpy, mask_fim); } if (alpha_fim) { FDestroyFImage(dpy, alpha_fim); } if (dest_fim) { FDestroyFImage(dpy, dest_fim); } if (new_mask_fim) { FDestroyFImage(dpy, new_mask_fim); } if (do_free_mono_gc && mono_gc) { XFreeGC(dpy, mono_gc); } if (out_fim) { FDestroyFImage(dpy, out_fim); } if (error) { if (out_pix != None) { XFreePixmap(dpy, out_pix); out_pix = None; } if (*new_mask != None) { XFreePixmap(dpy, *new_mask); *new_mask = None; } } return out_pix; } /* never used and tested */ static Pixmap PCreateDitherPixmap( Display *dpy, Window win, Drawable src, Pixmap mask, int depth, GC gc, int in_width, int in_height, int out_width, int out_height) { FImage *src_fim; FImage *mask_fim = NULL; FImage *out_fim; Pixmap out_pix = None; unsigned char *cm; XColor *colors; XColor c; int j, i, m = 0, k = 0, x = 0, y = 0; if (depth != Pdepth) return None; if (!(src_fim = FGetFImage( dpy, src, Pvisual, depth, 0, 0, in_width, in_height, AllPlanes, ZPixmap))) { return None; } if (mask != None) { mask_fim = FGetFImage( dpy, mask, Pvisual, 1, 0, 0, in_width, in_height, AllPlanes, ZPixmap); if (!mask_fim) { FDestroyFImage(dpy, mask_fim); return None; } } out_pix = XCreatePixmap(dpy, win, out_width, out_height, Pdepth); out_fim = FCreateFImage( dpy, Pvisual, Pdepth, ZPixmap, out_width, out_height); if (gc == None) { gc = PictureDefaultGC(dpy, win); } if (!out_pix || !out_fim || !gc) { FDestroyFImage(dpy, src_fim); if (mask_fim) { FDestroyFImage(dpy, mask_fim); } if (out_pix) { XFreePixmap(dpy, out_pix); } if (out_fim) { FDestroyFImage(dpy, out_fim); } return None; } colors = (XColor *)safemalloc(out_width * out_height * sizeof(XColor)); cm = (unsigned char *)safemalloc(out_width * out_height * sizeof(char)); x = y = 0; for (j = 0; j < out_height; j++,y++) { if (y == in_height) y = 0; for (i = 0; i < out_width; i++,x++) { if (x == in_width) x = 0; if (mask_fim != NULL && (XGetPixel(mask_fim->im, x, y) == 0)) { cm[m++] = 0; } else { cm[m++] = 255; colors[k++].pixel = XGetPixel(src_fim->im, x, y); } } } for (i = 0; i < k; i += 256) XQueryColors(dpy, Pcmap, &colors[i], min(k - i, 256)); k = 0;m = 0; for (j = 0; j < out_height; j++) { for (i = 0; i < out_width; i++) { if (cm[m] > 0) { c = colors[k++]; PictureAllocColorAllProp( Pdpy, Pcmap, &c, i, j, False, False, True); } else { c.pixel = XGetPixel(src_fim->im, i, j); } XPutPixel(out_fim->im, i, j, c.pixel); m++; } } free(colors); free(cm); FDestroyFImage(dpy, src_fim); if (mask_fim) { FDestroyFImage(dpy, mask_fim); } FPutFImage( dpy, out_pix, gc, out_fim, 0, 0, 0, 0, out_width, out_height); FDestroyFImage(dpy, out_fim); return out_pix; } /* ---------------------------- interface functions ------------------------ */ Pixmap PictureBitmapToPixmap( Display *dpy, Window win, Pixmap src, int depth, GC gc, int src_x, int src_y, int src_w, int src_h) { Pixmap dest = None; dest = XCreatePixmap(dpy, win, src_w, src_h, depth); if (dest && gc == None) { gc = PictureDefaultGC(dpy, win); } if (dest && gc) { XCopyPlane( dpy, src, dest, gc, src_x, src_y, src_w, src_h, 0, 0, 1); } return dest; } void PGraphicsRenderPixmaps( Display *dpy, Window win, Pixmap pixmap, Pixmap mask, Pixmap alpha, int depth, FvwmRenderAttributes *fra, Drawable d, GC gc, GC mono_gc, GC alpha_gc, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, int dest_w, int dest_h, int do_repeat) { FvwmRenderAttributes t_fra; Pixmap xrs_pixmap = None; Pixmap xrs_mask = None; Pixmap tmp_pixmap, tmp_mask; Bool d_is_a_window; t_fra.added_alpha_percent = 100; t_fra.tint_percent = 0; t_fra.mask = 0; t_fra.tint = None; if (fra) { t_fra.mask = fra->mask; if (fra->mask & FRAM_HAVE_ICON_CSET) { t_fra.added_alpha_percent = fra->colorset->icon_alpha_percent; t_fra.tint_percent = fra->colorset->icon_tint_percent; t_fra.tint = fra->colorset->icon_tint; } if (fra->mask & FRAM_HAVE_ADDED_ALPHA) { t_fra.added_alpha_percent = fra->added_alpha_percent; } if (fra->mask & FRAM_HAVE_TINT) { t_fra.tint_percent = fra->tint_percent; t_fra.tint = fra->tint; } } if (dest_w == 0 && dest_h == 0) { dest_w = src_w; dest_h = src_h; } /* use XRender only when "needed" (backing store pbs) */ if (t_fra.tint_percent > 0 || t_fra.added_alpha_percent < 100 || alpha != None) { /* for testing XRender simulation add && 0 */ if (FRenderRender( dpy, win, pixmap, mask, alpha, depth, t_fra.added_alpha_percent, t_fra.tint, t_fra.tint_percent, d, gc, alpha_gc, src_x, src_y, src_w, src_h, dest_x, dest_y, dest_w, dest_h, do_repeat)) { return; } } /* no render extension or something strange happen */ if (t_fra.tint_percent > 0 || t_fra.added_alpha_percent < 100 || alpha != None) { int new_w, new_h, new_do_repeat; d_is_a_window = !!(t_fra.mask & FRAM_DEST_IS_A_WINDOW); xrs_pixmap = PCreateRenderPixmap( dpy, win, pixmap, mask, alpha, depth, t_fra.added_alpha_percent, t_fra.tint, t_fra.tint_percent, d_is_a_window, d, gc, mono_gc, alpha_gc, src_x, src_y, src_w, src_h, dest_x, dest_y, dest_w, dest_h, do_repeat, &new_w, &new_h, &new_do_repeat, &xrs_mask); if (xrs_pixmap) { src_x = 0; src_y = 0; src_w = new_w; src_h = new_h; depth = Pdepth; do_repeat = new_do_repeat; } } tmp_pixmap = (xrs_pixmap != None)? xrs_pixmap:pixmap; tmp_mask = (xrs_mask != None)? xrs_mask:mask; if (do_repeat) { PTileRectangle( dpy, win, tmp_pixmap, tmp_mask, depth, src_x, src_y, d, gc, mono_gc, dest_x, dest_y, dest_w, dest_h); } else { PCopyArea( dpy, tmp_pixmap, tmp_mask, depth, d, gc, src_x, src_y, src_w, src_h, dest_x, dest_y); } if (xrs_pixmap) { XFreePixmap(dpy, xrs_pixmap); } if (xrs_mask) { XFreePixmap(dpy, xrs_mask); } } void PGraphicsRenderPicture( Display *dpy, Window win, FvwmPicture *p, FvwmRenderAttributes *fra, Drawable d, GC gc, GC mono_gc, GC alpha_gc, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, int dest_w, int dest_h, int do_repeat) { PGraphicsRenderPixmaps( dpy, win, p->picture, p->mask, p->alpha, p->depth, fra, d, gc, mono_gc, alpha_gc, src_x, src_y, src_w, src_h, dest_x, dest_y, dest_w, dest_h, do_repeat); } void PGraphicsCopyPixmaps( Display *dpy, Pixmap pixmap, Pixmap mask, Pixmap alpha, int depth, Drawable d, GC gc, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y) { PGraphicsRenderPixmaps( dpy, None, pixmap, mask, alpha, depth, 0, d, gc, None, None, src_x, src_y, src_w, src_h, dest_x, dest_y, src_w, src_h, False); } void PGraphicsCopyFvwmPicture( Display *dpy, FvwmPicture *p, Drawable d, GC gc, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y) { PGraphicsRenderPicture( dpy, None, p, 0, d, gc, None, None, src_x, src_y, src_w, src_h, dest_x, dest_y, src_w, src_h, False); } void PGraphicsTileRectangle( Display *dpy, Window win, Pixmap pixmap, Pixmap mask, Pixmap alpha, int depth, Drawable d, GC gc, GC mono_gc, int src_x, int src_y, int src_w, int src_h, int dest_x, int dest_y, int dest_w, int dest_h) { PGraphicsRenderPixmaps( dpy, win, pixmap, mask, alpha, depth, 0, d, gc, mono_gc, None, src_x, src_y, dest_w, dest_h, dest_x, dest_y, dest_w, dest_h, True); } FvwmPicture *PGraphicsCreateStretchPicture( Display *dpy, Window win, FvwmPicture *src, int dest_width, int dest_height, GC gc, GC mono_gc, GC alpha_gc) { Pixmap pixmap = None, mask = None, alpha = None; FvwmPicture *q; if (src == NULL || src->picture == None) { return NULL; } pixmap = CreateStretchPixmap( dpy, src->picture, src->width, src->height, src->depth, dest_width, dest_height, gc); if (!pixmap) { return NULL; } if (src->mask) { mask = CreateStretchPixmap( dpy, src->mask, src->width, src->height, 1, dest_width, dest_height, mono_gc); } if (src->alpha) { alpha = CreateStretchPixmap( dpy, src->alpha, src->width, src->height, FRenderGetAlphaDepth(), dest_width, dest_height, alpha_gc); } q = (FvwmPicture*)safemalloc(sizeof(FvwmPicture)); memset(q, 0, sizeof(FvwmPicture)); q->count = 1; q->name = NULL; q->next = NULL; q->stamp = pixmap; q->picture = pixmap; q->mask = mask; q->alpha = alpha; q->width = dest_width; q->height = dest_height; q->depth = src->depth; q->alloc_pixels = 0; q->nalloc_pixels = 0; return q; } FvwmPicture *PGraphicsCreateTiledPicture( Display *dpy, Window win, FvwmPicture *src, int dest_width, int dest_height, GC gc, GC mono_gc, GC alpha_gc) { Pixmap pixmap = None, mask = None, alpha = None; FvwmPicture *q; if (src == NULL || src->picture == None) { return NULL; } pixmap = CreateTiledPixmap( dpy, src->picture, src->width, src->height, dest_width, dest_height, src->depth, gc); if (!pixmap) { return NULL; } if (src->mask) { mask = CreateTiledPixmap( dpy, src->mask, src->width, src->height, dest_width, dest_height, 1, mono_gc); } if (src->alpha) { alpha = CreateTiledPixmap( dpy, src->alpha, src->width, src->height, dest_width, dest_height, FRenderGetAlphaDepth(), alpha_gc); } q = (FvwmPicture*)safemalloc(sizeof(FvwmPicture)); memset(q, 0, sizeof(FvwmPicture)); q->count = 1; q->name = NULL; q->next = NULL; q->stamp = pixmap; q->picture = pixmap; q->mask = mask; q->alpha = alpha; q->width = dest_width; q->height = dest_height; q->depth = src->depth; q->alloc_pixels = 0; q->nalloc_pixels = 0; return q; } Pixmap PGraphicsCreateTransparency( Display *dpy, Window win, FvwmRenderAttributes *fra, GC gc, int x, int y, int width, int height, Bool parent_relative) { Pixmap r = None, dp = None; XID junk; XID root; int dummy, sx, sy, sw, sh; int gx = x, gy = y, gh = height, gw = width; int old_backing_store = -1; if (parent_relative) { old_backing_store = FSetBackingStore(dpy, win, Always); XSetWindowBackgroundPixmap(dpy, win, ParentRelative); XClearArea(dpy, win, x, y, width, height, False); XSync(dpy, False); } if (parent_relative) { /* this block is not useful if backing store ... */ if (!XGetGeometry( dpy, win, &root, (int *)&junk, (int *)&junk, (unsigned int *)&sw, (unsigned int *)&sh, (unsigned int *)&junk, (unsigned int *)&junk)) { goto bail; } XTranslateCoordinates( dpy, win, DefaultRootWindow(dpy), x, y, &sx, &sy, &junk); if (sx >= DisplayWidth(dpy, DefaultScreen(dpy))) { goto bail; } if (sy >= DisplayHeight(dpy, DefaultScreen(dpy))) { goto bail; } if (sx < 0) { gx = gx - sx; gw = width + sx; sx = 0; if (gw <= 0) { goto bail; } } if (sy < 0) { gy = gy - sy; gh = height + sy; sy = 0; if (gh <= 0) { goto bail; } } if (sx + gw > DisplayWidth(dpy, DefaultScreen(dpy))) { gw = DisplayWidth(dpy, DefaultScreen(dpy)) - sx; } if (sy + gh > DisplayHeight(dpy, DefaultScreen(dpy))) { gh = DisplayHeight(dpy, DefaultScreen(dpy)) - sy; } } #if 0 fprintf( stderr,"Geo: %i,%i,%i,%i / %i,%i,%i,%i / %i,%i,%i,%i\n", gx,gy,gw,gh, x,y,width,height, sx,sy,sw,sh); #endif if (XRenderSupport && FRenderGetExtensionSupported()) { r = XCreatePixmap(dpy, win, gw, gh, Pdepth); if (FRenderRender( dpy, win, ParentRelative, None, None, Pdepth, 100, fra->tint, fra->tint_percent, r, gc, None, gx, gy, gw, gh, 0, 0, gw, gh, False)) { goto bail; } XFreePixmap(dpy, r); } r = PCreateRenderPixmap( dpy, win, ParentRelative, None, None, Pdepth, 100, fra->tint, fra->tint_percent, True, win, gc, None, None, gx, gy, gw, gh, gx, gy, gw, gh, False, &dummy, &dummy, &dummy, &dp); bail: if (old_backing_store >= 0) { FSetBackingStore(dpy, win, old_backing_store); } return r; } void PGraphicsTintRectangle( Display *dpy, Window win, Pixel tint, int tint_percent, Drawable dest, Bool dest_is_a_window, GC gc, GC mono_gc, GC alpha_gc, int dest_x, int dest_y, int dest_w, int dest_h) { Pixmap p; FvwmRenderAttributes fra; #if 0 /* this does not work. why? */ if (FRenderTintRectangle( dpy, win, None, tint, tint_percent, dest, dest_x, dest_y, dest_w, dest_h)) { return; } #else if (FRenderRender( dpy, win, ParentRelative, None, None, Pdepth, 100, tint, tint_percent, win, gc, None, dest_x, dest_y, dest_w, dest_h, dest_x, dest_y, dest_w, dest_h, False)) { return; } #endif if (dest_is_a_window) { fra.tint = tint; fra.tint_percent = tint_percent; fra.mask = FRAM_DEST_IS_A_WINDOW | FRAM_HAVE_TINT; p = PGraphicsCreateTransparency( dpy, dest, &fra, gc, dest_x, dest_y, dest_w, dest_h, False); if (p) { XCopyArea( dpy, p, dest, gc, 0, 0, dest_w, dest_h, dest_x, dest_y); XFreePixmap(dpy, p); } } } #if 0 /* humm... maybe useful one day with menus */ Pixmap PGraphicsCreateTranslucent( Display *dpy, Window win, FvwmRenderAttributes *fra, GC gc, int x, int y, int width, int height) { Pixmap r = None; int gx = x, gy = y, gh = height, gw = width; FvwmRenderAttributes t_fra; Pixmap root_pix = None; Pixmap dp = None; int dummy; t_fra.added_alpha_percent = 100; t_fra.tint_percent = 0; t_fra.tint = 0; t_fra.mask = 0; if (fra) { if (fra->mask & FRAM_HAVE_TINT) { t_fra.tint_percent = fra->tint_percent; t_fra.tint = fra->tint; t_fra.mask = FRAM_HAVE_TINT; } } if (x >= DisplayWidth(dpy, DefaultScreen(dpy))) { goto bail; } if (y >= DisplayHeight(dpy, DefaultScreen(dpy))) { goto bail; } if (x < 0) { gx = 0; gw = width + x; if (gw <= 0) { goto bail; } } if (y < 0) { gy = 0; gh = gh+y; if (gh <= 0) { goto bail; } } if (gx + gw > DisplayWidth(dpy, DefaultScreen(dpy))) { gw = DisplayWidth(dpy, DefaultScreen(dpy)) - gx; } if (gy + gh > DisplayHeight(dpy, DefaultScreen(dpy))) { gh = DisplayHeight(dpy, DefaultScreen(dpy)) - gy; } { /* make a screen shoot */ GC my_gc; unsigned long valuemask = GCSubwindowMode; XGCValues values; values.subwindow_mode = IncludeInferiors; root_pix = XCreatePixmap(dpy, win, gw, gh, Pdepth); my_gc = fvwmlib_XCreateGC(dpy, win, 0, NULL); XChangeGC(dpy, my_gc, valuemask, &values); MyXGrabServer(dpy); XCopyArea( dpy, DefaultRootWindow(dpy), root_pix, my_gc, gx, gy, gw, gh, 0, 0); MyXUngrabServer(dpy); XFreeGC(dpy,my_gc); } if (XRenderSupport && FRenderGetExtensionSupported()) { r = XCreatePixmap(dpy, win, gw, gh, Pdepth); if (FRenderRender( dpy, win, root_pix, None, None, Pdepth, t_fra.added_alpha_percent, t_fra.tint, t_fra.tint_percent, r, gc, None, 0, 0, gw, gh, 0, 0, gw, gh, False)) { goto bail; } XFreePixmap(dpy, r); r = None; } r = PCreateRenderPixmap( dpy, win, root_pix, None, None, Pdepth, 100, fra->tint, fra->tint_percent, True, win, gc, None, None, 0, 0, gw, gh, gx, gy, gw, gh, False, &dummy, &dummy, &dummy, &dp); bail: if (root_pix) { XFreePixmap(dpy, root_pix); } if (dp) { XFreePixmap(dpy, dp); } return r; } #endif /* never tested and used ! */ Pixmap PGraphicsCreateDitherPixmap( Display *dpy, Window win, Drawable src, Pixmap mask, int depth, GC gc, int in_width, int in_height, int out_width, int out_height) { return PCreateDitherPixmap( dpy, win, src, mask, depth, gc, in_width, in_height, out_width, out_height); } fvwm-2.7.0/libs/FRender.h0000644000175000017500000002552114147024676012067 00000000000000/* -*-c-*- */ /* Copyright (C) 2002 Olivier Chapuis */ #ifndef FRENDER_H #define FRENDER_H /* ---------------------------- included header files ---------------------- */ #include "config.h" #include "PictureBase.h" #if XRenderSupport #define Picture XRenderPicture #include #undef Picture #endif /* ---------------------------- global definitions ------------------------- */ /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ #if XRenderSupport typedef XRenderDirectFormat FRenderDirectFormat; typedef PictFormat FRPictFormat; typedef XRenderPictFormat FRenderPictFormat; typedef XRenderPicture FRenderPicture; #if 0 /* this has disappeared */ typedef XRenderVisual FRenderVisual; typedef XRenderDepth FRenderDepth; typedef XRenderInfo FRenderInfo; #endif typedef XRenderPictureAttributes FRenderPictureAttributes; typedef XRenderColor FRenderColor; typedef XGlyphInfo FGlyphInfo; #define FRenderPictFormatID PictFormatID #define FRenderPictFormatType PictFormatType #define FRenderPictFormatDepth PictFormatDepth #define FRenderPictFormatRed PictFormatRed #define FRenderPictFormatRedMask PictFormatRedMask #define FRenderPictFormatGreen PictFormatGreen #define FRenderPictFormatGreenMask PictFormatGreenMask #define FRenderPictFormatBlue PictFormatBlue #define FRenderPictFormatBlueMask PictFormatBlueMask #define FRenderPictFormatAlpha PictFormatAlpha #define FRenderPictFormatAlphaMask PictFormatAlphaMask #define FRenderPictFormatColormap PictFormatColormap #define FRenderBadPictFormat 0 #define FRenderBadPicture 1 #define FRenderBadPictOp 2 #define FRenderBadGlyphSet 3 #define FRenderBadGlyph 4 #define FRenderRenderNumberErrors (FRenderBadGlyph+1) #define FRenderPictTypeIndexed PictTypeIndexed #define FRenderPictTypeDirect PictTypeDirect #define FRenderPictOpMinimum PictOpMinimum #define FRenderPictOpClear PictOpClear #define FRenderPictOpSrc PictOpSrc #define FRenderPictOpDst PictOpDst #define FRenderPictOpOver PictOpOver #define FRenderPictOpOverReverse PictOpOverReverse #define FRenderPictOpIn PictOpIn #define FRenderPictOpInReverse PictOpInReverse #define FRenderPictOpOut PictOpOut #define FRenderPictOpOutReverse PictOpOutReverse #define FRenderPictOpAtop PictOpAtop #define FRenderPictOpAtopReverse PictOpAtopReverse #define FRenderPictOpXor PictOpXor #define FRenderPictOpAdd PictOpAdd #define FRenderPictOpSaturate PictOpSaturate #define FRenderPictOpMaximum PictOpMaximum /* * Operators only available in version 0.2 */ #if 0 #define FRenderPictOpDisjointMinimum PictOpDisjointMinimum #define FRenderPictOpDisjointClear PictOpDisjointClear #define FRenderPictOpDisjointSrc PictOpDisjointSrc #define FRenderPictOpDisjointDst PictOpDisjointDst #define FRenderPictOpDisjointOver PictOpDisjointOver #define FRenderPictOpDisjointOverReverse PictOpDisjointOverReverse #define FRenderPictOpDisjointIn PictOpDisjointIn #define FRenderPictOpDisjointInReverse PictOpDisjointInReverse #define FRenderPictOpDisjointOut PictOpDisjointOut #define FRenderPictOpDisjointOutReverse PictOpDisjointOutReverse #define FRenderPictOpDisjointAtop PictOpDisjointAtop #define FRenderPictOpDisjointAtopReverse PictOpDisjointAtopReverse #define FRenderPictOpDisjointXor PictOpDisjointXor #define FRenderPictOpDisjointMaximum PictOpDisjointMaximum #define FRenderPictOpConjointMinimum PictOpConjointMinimum #define FRenderPictOpConjointClear PictOpConjointClear #define FRenderPictOpConjointSrc PictOpConjointSrc #define FRenderPictOpConjointDst PictOpConjointDst #define FRenderPictOpConjointOver PictOpConjointOver #define FRenderPictOpConjointOverReverse PictOpConjointOverReverse #define FRenderPictOpConjointIn PictOpConjointIn #define FRenderPictOpConjointInReverse PictOpConjointInReverse #define FRenderPictOpConjointOut PictOpConjointOut #define FRenderPictOpConjointOutReverse PictOpConjointOutReverse #define FRenderPictOpConjointAtop PictOpConjointAtop #define FRenderPictOpConjointAtopReverse PictOpConjointAtopReverse #define FRenderPictOpConjointXor PictOpConjointXor #define FRenderPictOpConjointMaximum PictOpConjointMaximum #endif /* 0 */ #define FRenderPolyEdgeSharp PolyEdgeSharp #define FRenderPolyEdgeSmooth PolyEdgeSmooth #define FRenderPolyModePrecise #define FRenderPolyModeImprecise #define FRenderCPRepeat CPRepeat #define FRenderCPAlphaMap CPAlphaMap #define FRenderCPAlphaXOrigin CPAlphaXOrigin #define FRenderCPAlphaYOrigin CPAlphaYOrigin #define FRenderCPClipXOrigin CPClipXOrigin #define FRenderCPClipYOrigin CPClipYOrigin #define FRenderCPClipMask CPClipMask #define FRenderCPGraphicsExposure CPGraphicsExposure #define FRenderCPSubwindowMode CPSubwindowMode #define FRenderCPPolyEdge CPPolyEdge #define FRenderCPPolyMode CPPolyMode #define FRenderCPDither CPDither #define FRenderCPComponentAlpha CPComponentAlpha #define FRenderCPLastBit CPLastBit #define FRenderQueryExtension(a,b,c) XRenderQueryExtension(a,b,c) #define FRenderQueryVersion(a,b,c) XRenderQueryVersion(a,b,c) #define FRenderQueryFormats(a) XRenderQueryFormats(a) #define FRenderFindVisualFormat(a,b) XRenderFindVisualFormat(a,b) #define FRenderFindFormat(a,b,c,d) XRenderFindFormat(a,b,c,d) #define FRenderCreatePicture(a,b,c,d,e) XRenderCreatePicture(a,b,c,d,e) #define FRenderChangePicture(a,b,c,d) XRenderChangePicture(a,b,c,d) #define FRenderSetPictureClipRectangles(a,b,c,d,e,f) \ XRenderSetPictureClipRectangles(a,b,c,d,e,f) #define FRenderSetPictureClipRegion(a,b,c) XRenderSetPictureClipRegion(a,b,c) #define FRenderFreePicture(a,b) XRenderFreePicture(a,b) #define FRenderComposite(a,b,c,d,e,f,g,h,i,j,k,l,m) \ XRenderComposite(a,b,c,d,e,f,g,h,i,j,k,l,m) #define FRenderFillRectangle(a,b,c,d,e,f,g,h) \ XRenderFillRectangle(a,b,c,d,e,f,g,h) #define FRenderFillRectangles(a,b,c,d,e,f) XRenderFillRectangles(a,b,c,d,e,f) #else /* !XRenderSupport */ typedef unsigned long FRenderPicture; typedef unsigned long FRPictFormat; typedef struct { short red; short redMask; short green; short greenMask; short blue; short blueMask; short alpha; short alphaMask; } FRenderDirectFormat; typedef struct { FRPictFormat id; int type; int depth; FRenderDirectFormat direct; Colormap colormap; } FRenderPictFormat; typedef struct { Visual *visual; FRenderPictFormat *format; } FRenderVisual; typedef struct { int depth; int nvisuals; FRenderVisual *visuals; } FRenderDepth; typedef struct { FRenderDepth *depths; int ndepths; FRenderPictFormat *fallback; } FRenderScreen; typedef struct _FRenderInfo { FRenderPictFormat *format; int nformat; FRenderScreen *screen; int nscreen; FRenderDepth *depth; int ndepth; FRenderVisual *visual; int nvisual; } FRenderInfo; typedef struct _FRenderPictureAttributes { Bool repeat; FRenderPicture alpha_map; int alpha_x_origin; int alpha_y_origin; int clip_x_origin; int clip_y_origin; Pixmap clip_mask; Bool graphics_exposures; int subwindow_mode; int poly_edge; int poly_mode; Atom dither; Bool component_alpha; } FRenderPictureAttributes; typedef struct { unsigned short red; unsigned short green; unsigned short blue; unsigned short alpha; } FRenderColor; typedef struct _FGlyphInfo { unsigned short width; unsigned short height; short x; short y; short xOff; short yOff; } FGlyphInfo; #define FRenderPictFormatID 0 #define FRenderPictFormatType 0 #define FRenderPictFormatDepth 0 #define FRenderPictFormatRed 0 #define FRenderPictFormatRedMask 0 #define FRenderPictFormatGreen 0 #define FRenderPictFormatGreenMask 0 #define FRenderPictFormatBlue 0 #define FRenderPictFormatBlueMask 0 #define FRenderPictFormatAlpha 0 #define FRenderPictFormatAlphaMask 0 #define FRenderPictFormatColormap 0 #define FRenderBadPictFormat 0 #define FRenderBadPicture 1 #define FRenderBadPictOp 2 #define FRenderBadGlyphSet 3 #define FRenderBadGlyph 4 #define FRenderRenderNumberErrors (FRenderBadGlyph+1) #define FRenderPictTypeIndexed 0 #define FRenderPictTypeDirect 0 #define FRenderPictOpMinimum 0 #define FRenderPictOpClear 0 #define FRenderPictOpSrc 0 #define FRenderPictOpDst 0 #define FRenderPictOpOver 0 #define FRenderPictOpOverReverse 0 #define FRenderPictOpIn 0 #define FRenderPictOpInReverse 0 #define FRenderPictOpOut 0 #define FRenderPictOpOutReverse 0 #define FRenderPictOpAtop 0 #define FRenderPictOpAtopReverse 0 #define FRenderPictOpXor 0 #define FRenderPictOpAdd 0 #define FRenderPictOpSaturate 0 #define FRenderPictOpMaximum 0 /* * Operators only available in version 0.2 */ #if 0 #define FRenderPictOpDisjointMinimum 0 #define FRenderPictOpDisjointClear 0 #define FRenderPictOpDisjointSrc 0 #define FRenderPictOpDisjointDst 0 #define FRenderPictOpDisjointOver 0 #define FRenderPictOpDisjointOverReverse 0 #define FRenderPictOpDisjointIn 0 #define FRenderPictOpDisjointInReverse 0 #define FRenderPictOpDisjointOut 0 #define FRenderPictOpDisjointOutReverse 0 #define FRenderPictOpDisjointAtop 0 #define FRenderPictOpDisjointAtopReverse 0 #define FRenderPictOpDisjointXor 0 #define FRenderPictOpDisjointMaximum 0 #define FRenderPictOpConjointMinimum 0 #define FRenderPictOpConjointClear 0 #define FRenderPictOpConjointSrc 0 #define FRenderPictOpConjointDst 0 #define FRenderPictOpConjointOver 0 #define FRenderPictOpConjointOverReverse 0 #define FRenderPictOpConjointIn 0 #define FRenderPictOpConjointInReverse 0 #define FRenderPictOpConjointOut 0 #define FRenderPictOpConjointOutReverse 0 #define FRenderPictOpConjointAtop 0 #define FRenderPictOpConjointAtopReverse 0 #define FRenderPictOpConjointXor 0 #define FRenderPictOpConjointMaximum 0 #endif #define FRenderPolyEdgeSharp 0 #define FRenderPolyEdgeSmooth 0 #define FRenderPolyModePrecise 0 #define FRenderPolyModeImprecise 0 #define FRenderCPRepeat 0 #define FRenderCPAlphaMap 0 #define FRenderCPAlphaXOrigin 0 #define FRenderCPAlphaYOrigin 0 #define FRenderCPClipXOrigin 0 #define FRenderCPClipYOrigin 0 #define FRenderCPClipMask 0 #define FRenderCPGraphicsExposure 0 #define FRenderCPSubwindowMode 0 #define FRenderCPPolyEdge 0 #define FRenderCPPolyMode 0 #define FRenderCPDither 0 #define FRenderCPComponentAlpha 0 #define FRenderCPLastBit 0 #define FRenderQueryExtension(a,b,c) 0 #define FRenderQueryVersion(a,b,c) 0 #define FRenderQueryFormats(a) 0 #define FRenderFindVisualFormat(a,b) NULL #define FRenderFindFormat(a,b,c,d) NULL #define FRenderCreatePicture(a,b,c,d,e) None #define FRenderChangePicture(a,b,c,d) #define FRenderSetPictureClipRectangles(a,b,c,d,e,f) #define FRenderSetPictureClipRegion(a,b,c) #define FRenderFreePicture(a,b) #define FRenderComposite(a,b,c,d,e,f,g,h,i,j,k,l,m) #define FRenderFillRectangle(a,b,c,d,e,f,g,h) #define FRenderFillRectangles(a,b,c,d,e,f) #endif #endif /* FRENDER_H */ fvwm-2.7.0/libs/timeout.c0000644000175000017500000000531614147024700012207 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include "safemalloc.h" #include "timeout.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ /* ---------------------------- interface functions ------------------------ */ timeout_t *timeout_create( int n_timeouts) { timeout_t *to; if (n_timeouts < 0 || n_timeouts > TIMEOUT_MAX_TIMEOUTS) { return NULL; } to = (timeout_t *)safecalloc(1, sizeof(timeout_t)); to->n_timeouts = n_timeouts; to->timeouts = (timeout_time_t *)safecalloc( 1, n_timeouts * sizeof(timeout_time_t)); return to; } void timeout_destroy( timeout_t *to) { if (to == NULL) { return; } if (to->timeouts != NULL) { free(to->timeouts); } free(to); return; } timeout_mask_t timeout_tick( timeout_t *to, timeout_time_t n_ticks) { timeout_mask_t mask; int i; if (n_ticks <= 0) { return 0; } for (i = 0, mask = 0; i < to->n_timeouts; i++) { if (to->timeouts[i] > n_ticks) { to->timeouts[i] -= n_ticks; } else if (to->timeouts[i] > 0) { to->timeouts[i] = 0; mask |= 1 << i; } } return mask; } void timeout_rewind( timeout_t *to, timeout_mask_t mask, timeout_time_t ticks_before_alarm) { int i; if (ticks_before_alarm < 0) { return; } for (i = 0; i < to->n_timeouts; i++) { if (mask & (1 << i)) { to->timeouts[i] = ticks_before_alarm; } } return; } fvwm-2.7.0/libs/Target.c0000644000175000017500000001620314147024700011744 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* ** fvwmlib_get_target_window and fvwmlib_keyboard_shortcuts - handle window ** selection from modules and fvwm. */ #include "config.h" #include #include #include #include #include #include #include #include #include "fvwmlib.h" #include "Grab.h" #include "Target.h" void fvwmlib_keyboard_shortcuts( Display *dpy, int screen, XEvent *Event, int x_move_size, int y_move_size, int *x_defect, int *y_defect, int ReturnEvent) { int x; int y; int x_root; int y_root; int x_move; int y_move; KeySym keysym; Window JunkRoot; unsigned int JunkMask; if (y_move_size < DEFAULT_KDB_SHORTCUT_MOVE_DISTANCE) { y_move_size = DEFAULT_KDB_SHORTCUT_MOVE_DISTANCE; } if (x_move_size < DEFAULT_KDB_SHORTCUT_MOVE_DISTANCE) { x_move_size = DEFAULT_KDB_SHORTCUT_MOVE_DISTANCE; } if (Event->xkey.state & ControlMask) { x_move_size = y_move_size = KDB_SHORTCUT_MOVE_DISTANCE_SMALL; } if (Event->xkey.state & ShiftMask) { x_move_size = y_move_size = KDB_SHORTCUT_MOVE_DISTANCE_BIG; } keysym = XLookupKeysym(&Event->xkey,0); x_move = 0; y_move = 0; switch(keysym) { case XK_Up: case XK_KP_8: case XK_k: case XK_p: y_move = -y_move_size; break; case XK_Down: case XK_KP_2: case XK_n: case XK_j: y_move = y_move_size; break; case XK_Left: case XK_KP_4: case XK_b: case XK_h: x_move = -x_move_size; break; case XK_Right: case XK_KP_6: case XK_f: case XK_l: x_move = x_move_size; break; case XK_KP_1: x_move = -x_move_size; y_move = y_move_size; break; case XK_KP_3: x_move = x_move_size; y_move = y_move_size; break; case XK_KP_7: x_move = -x_move_size; y_move = -y_move_size; break; case XK_KP_9: x_move = x_move_size; y_move = -y_move_size; break; case XK_Return: case XK_KP_Enter: case XK_space: /* beat up the event */ Event->type = ReturnEvent; break; case XK_Escape: /* simple code to bag out of move - CKH */ /* return keypress event instead */ Event->type = KeyPress; Event->xkey.keycode = XKeysymToKeycode( Event->xkey.display,keysym); break; default: break; } if (x_move || y_move) { int x_def_new = 0; int y_def_new = 0; if (FQueryPointer( dpy, RootWindow(dpy, screen), &JunkRoot, &Event->xany.window, &x_root, &y_root, &x, &y, &JunkMask) == False) { /* pointer is on a different screen - do nothing */ return; } if (x + x_move < 0) { x_def_new = x + x_move; x_move = -x; } else if (x + x_move >= DisplayWidth(dpy, DefaultScreen(dpy))) { x_def_new = x + x_move - DisplayWidth( dpy, DefaultScreen(dpy)); x_move = DisplayWidth(dpy, DefaultScreen(dpy)) - x - 1; } if (y + y_move < 0) { y_def_new = y + y_move; y_move = -y; } else if (y + y_move >= DisplayHeight(dpy, DefaultScreen(dpy))) { y_def_new = y + y_move - DisplayHeight( dpy, DefaultScreen(dpy)); y_move = DisplayHeight( dpy, DefaultScreen(dpy)) - y - 1; } if (x_defect) { int diff = 0; *x_defect += x_def_new; if (*x_defect > 0 && x_move < 0) { diff = min(*x_defect, -x_move); } else if (*x_defect < 0 && x_move > 0) { diff = max(*x_defect, -x_move); } *x_defect -= diff; x_move += diff; } if (y_defect) { int diff = 0; *y_defect += y_def_new; if (*y_defect > 0 && y_move < 0) { diff = min(*y_defect, -y_move); } else if (*y_defect < 0 && y_move > 0) { diff = max(*y_defect, -y_move); } *y_defect -= diff; y_move += diff; } if (x_move || y_move) { FWarpPointer( dpy, None, RootWindow(dpy, screen), 0, 0, 0, 0, x_root + x_move, y_root + y_move); } /* beat up the event */ Event->type = MotionNotify; Event->xkey.x += x_move; Event->xkey.y += y_move; Event->xkey.x_root += x_move; Event->xkey.y_root += y_move; } } void fvwmlib_get_target_window( Display *dpy, int screen, char *MyName, Window *app_win, Bool return_subwindow) { XEvent eventp; int val = -10,trials; Bool finished = False; Bool canceled = False; Window Root = RootWindow(dpy, screen); int is_key_pressed = 0; int is_button_pressed = 0; KeySym keysym; trials = 0; while((trials <10)&&(val != GrabSuccess)) { val=XGrabPointer(dpy, Root, True, ButtonPressMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, Root, XCreateFontCursor(dpy,XC_crosshair), CurrentTime); switch (val) { case GrabInvalidTime: case GrabNotViewable: /* give up */ trials += 100000; break; case GrabSuccess: break; case AlreadyGrabbed: case GrabFrozen: default: usleep(10000); trials++; break; } } if(val != GrabSuccess) { fprintf(stderr,"%s: Couldn't grab the cursor!\n",MyName); exit(1); } MyXGrabKeyboard(dpy); while (!finished && !canceled) { FMaskEvent(dpy, ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask, &eventp); switch (eventp.type) { case KeyPress: is_key_pressed++; break; case KeyRelease: keysym = XLookupKeysym(&eventp.xkey,0); if( !is_key_pressed ) break; switch (keysym) { case XK_Escape: canceled = True; break; case XK_space: case XK_Return: case XK_KP_Enter: finished = True; break; default: fvwmlib_keyboard_shortcuts( dpy, screen, &eventp, 0, 0, NULL, NULL, 0); break; } break; case ButtonPress: is_button_pressed++; break; case ButtonRelease: if( is_button_pressed ) finished = True; break; } } MyXUngrabKeyboard(dpy); XUngrabPointer(dpy, CurrentTime); XSync(dpy,0); if (canceled) { *app_win = None; return; } *app_win = eventp.xany.window; if(return_subwindow && eventp.xbutton.subwindow != None) *app_win = eventp.xbutton.subwindow; return; } Window fvwmlib_client_window(Display *dpy, Window input) { Atom _XA_WM_STATE; unsigned int nchildren; Window root, parent, *children,target; unsigned long nitems, bytesafter; unsigned char *prop; Atom atype; int aformat; int i; _XA_WM_STATE = XInternAtom (dpy, "WM_STATE", False); if ( XGetWindowProperty( dpy, input, _XA_WM_STATE , 0L, 3L , False, _XA_WM_STATE, &atype, &aformat, &nitems, &bytesafter, &prop) == Success) { if(prop != NULL) { XFree(prop); return input; } } if (!XQueryTree(dpy, input, &root, &parent, &children, &nchildren)) return None; for (i = 0; i < nchildren; i++) { target = fvwmlib_client_window(dpy, children[i]); if(target != None) { XFree((char *)children); return target; } } XFree((char *)children); return None; } fvwm-2.7.0/libs/flist.c0000644000175000017500000000652514147024700011645 00000000000000/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: */ /* code for parsing the fvwm style command */ /* ---------------------------- included header files ---------------------- */ #include "config.h" #include #include "safemalloc.h" #include "flist.h" /* ---------------------------- local definitions -------------------------- */ /* ---------------------------- local macros ------------------------------- */ /* ---------------------------- imports ------------------------------------ */ /* ---------------------------- included code files ------------------------ */ /* ---------------------------- local types -------------------------------- */ /* ---------------------------- forward declarations ----------------------- */ /* ---------------------------- local variables ---------------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- local functions ---------------------------- */ /* ---------------------------- interface functions ------------------------ */ flist *flist_append_obj(flist *list, void *object) { flist *new = (flist *)safemalloc(sizeof(flist)); flist *tl = list; new->object = object; new->next = NULL; new->prev = NULL; if (list == NULL) { return new; } while(tl->next) { tl = tl->next; } tl->next = new; new->prev = tl; return list; } flist *flist_prepend_obj(flist *list, void *object) { flist *new = (flist *)safemalloc(sizeof(flist)); new->object = object; new->next = NULL; new->prev = NULL; if (list == NULL) { return new; } if (list->prev) { list->prev->next = new; new->prev = list->prev; } list->prev = new; new->next = list; return new; } flist *flist_insert_obj(flist *list, void *object, int position) { flist *new; flist *tl; if (position < 0) { return flist_append_obj(list, object); } if (position == 0) { return flist_prepend_obj(list, object); } tl = list; while(tl && position-- > 0) { tl = tl->next; } if (!tl) { return flist_append_obj(list, object); } new = (flist *)safemalloc(sizeof(flist));; new->object = object; new->prev = NULL; if (tl->prev) { tl->prev->next = new; new->prev = tl->prev; } new->next = tl; tl->prev = new; if (tl == list) { return new; } return list; } flist *flist_remove_obj(flist *list, void *object) { flist *tl = list; while (tl && tl->object != object) { tl = tl->next; } if (tl == NULL) { return NULL; } if (tl->prev) { tl->prev->next = tl->next; } if (tl->next) { tl->next->prev = tl->prev; } if (list == tl) { list = list->next; } free(tl); return list; } flist *flist_free_list(flist *list) { flist *tl; while (list) { tl = list; list = list->next; free(tl); } return NULL; } fvwm-2.7.0/libs/lang-strings.h0000644000175000017500000000112714147024676013146 00000000000000/* -*-c-*- */ /* * Please translate the strings into the language which you use for * your pop-up menus. * * Some decisions about where a function is prohibited (based on * mwm-function-hints) is based on a string comparison between the * menu item and the strings below. */ #define MOVE_STRING "move" #define RESIZE_STRING1 "size" #define RESIZE_STRING2 "resize" #define MINIMIZE_STRING "minimize" #define MINIMIZE_STRING2 "iconify" #define MAXIMIZE_STRING "maximize" #define CLOSE_STRING1 "close" #define CLOSE_STRING2 "delete" #define CLOSE_STRING3 "destroy" #define CLOSE_STRING4 "quit" fvwm-2.7.0/libs/Graphics.h0000644000175000017500000000561514147024700012270 00000000000000#ifndef LIB_GRAPHICS_H #define LIB_GRAPHICS_H void do_relieve_rectangle( Display *dpy, Drawable d, int x, int y, int w, int h, GC ReliefGC, GC ShadowGC, int line_width, Bool use_alternate_shading); void do_relieve_rectangle_with_rotation( Display *dpy, Drawable d, int x, int y, int w, int h, GC ReliefGC, GC ShadowGC, int line_width, Bool use_alternate_shading, int rotation); #define RelieveRectangle(dpy, d, x, y, w, h, ReliefGC, ShadowGC, line_width) \ do_relieve_rectangle( \ dpy, d, x, y, w, h, ReliefGC, ShadowGC, line_width, False) #define RelieveRectangle2(dpy, d, x, y, w, h, ReliefGC, ShadowGC, line_width) \ do_relieve_rectangle( \ dpy, d, x, y, w, h, ReliefGC, ShadowGC, line_width, True) Pixmap CreateStretchXPixmap( Display *dpy, Pixmap src, int src_width, int src_height, int src_depth, int dest_width, GC gc); Pixmap CreateStretchYPixmap( Display *dpy, Pixmap src, int src_width, int src_height, int src_depth, int dest_height, GC gc); Pixmap CreateStretchPixmap( Display *dpy, Pixmap src, int src_width, int src_height, int src_depth, int dest_width, int dest_height, GC gc); Pixmap CreateTiledPixmap( Display *dpy, Pixmap src, int src_width, int src_height, int dest_width, int dest_height, int depth, GC gc); Pixmap CreateRotatedPixmap( Display *dpy, Pixmap src, int src_width, int src_height, int depth, GC gc, int rotation); GC fvwmlib_XCreateGC( Display *display, Drawable drawable, unsigned long valuemask, XGCValues *values); /**** gradient stuff ****/ /* gradient types */ #define H_GRADIENT 'H' #define V_GRADIENT 'V' #define D_GRADIENT 'D' #define B_GRADIENT 'B' #define S_GRADIENT 'S' #define C_GRADIENT 'C' #define R_GRADIENT 'R' #define Y_GRADIENT 'Y' Bool IsGradientTypeSupported(char type); /* Convenience function. Calls AllocNonLinearGradient to fetch all colors and * then frees the color names and the perc and color_name arrays. */ XColor *AllocAllGradientColors( char *color_names[], int perc[], int nsegs, int ncolors, int dither); int ParseGradient(char *gradient, char **rest, char ***colors_return, int **perc_return, int *nsegs_return); Bool CalculateGradientDimensions(Display *dpy, Drawable d, int ncolors, char type, int dither, int *width_ret, int *height_ret); Drawable CreateGradientPixmap( Display *dpy, Drawable d, GC gc, int type, int g_width, int g_height, int ncolors, XColor *xcs, int dither, Pixel **d_pixels, int *d_npixels, Drawable in_drawable, int d_x, int d_y, int d_width, int d_height, XRectangle *rclip); Pixmap CreateGradientPixmapFromString( Display *dpy, Drawable d, GC gc, int type, char *action, int *width_return, int *height_return, Pixel **alloc_pixels, int *nalloc_pixels, int dither); void DrawTrianglePattern( Display *dpy, Drawable d, GC ReliefGC, GC ShadowGC, GC FillGC, int x, int y, int width, int height, int bw, char orientation, Bool draw_relief, Bool do_fill, Bool is_pressed); #endif /* LIB_GRAPHICS_H */ fvwm-2.7.0/libs/FlocaleCharset.h0000644000175000017500000000351414147024676013417 00000000000000/* -*-c-*- */ /* Copyright (C) 2002 Olivier Chapuis */ #ifndef FLOCALE_CHARSET_H #define FLOCALE_CHARSET_H /* ---------------------------- included header files ---------------------- */ #include "config.h" #include "Flocale.h" /* ---------------------------- global definitions ------------------------- */ #ifdef HAVE_LIBCHARSET #define FlocaleLibcharsetSupport 1 #else #define FlocaleLibcharsetSupport 0 #endif #ifdef HAVE_CODESET #define FlocaleCodesetSupport 1 #else #define FlocaleCodesetSupport 0 #endif #if FlocaleLibcharsetSupport #define Flocale_charset() locale_charset() #else #define Flocale_charset() NULL #endif #if FlocaleCodesetSupport #define Fnl_langinfo(a) nl_langinfo(a) #define FCODESET CODESET #else #define Fnl_langinfo(a) NULL #define FCODESET 0 #endif /* ---------------------------- global macros ------------------------------ */ /* ---------------------------- type definitions --------------------------- */ /* ---------------------------- exported variables (globals) --------------- */ /* ---------------------------- interface functions ------------------------ */ /* * */ void FlocaleCharsetInit(Display *dpy, const char *module); void FlocaleCharsetSetFlocaleCharset( Display *dpy, FlocaleFont *flf, char *hints, char *encoding, char *module); FlocaleCharset *FlocaleCharsetGetDefaultCharset(Display *dpy, char *module); FlocaleCharset *FlocaleCharsetGetFLCXOMCharset(void); FlocaleCharset *FlocaleCharsetGetUtf8Charset(void); FlocaleCharset *FlocaleCharsetGetLocaleCharset(void); FlocaleCharset *FlocaleCharsetGetUnknownCharset(void); const char *FlocaleGetBidiCharset(Display *dpy, FlocaleCharset *fc); FlocaleCharset *FlocaleCharsetGetEUCJPCharset(void); Bool FlocaleCharsetIsCharsetXLocale(Display *dpy, char *charset, char *module); void FlocaleCharsetPrintXOMInfo(void); #endif /* FLOCALE_CHARSET_H */ fvwm-2.7.0/tests/0000755000175000017500000000000014324316056010646 500000000000000fvwm-2.7.0/tests/test_options0000755000175000017500000001221614147024676013257 00000000000000#!/bin/sh # Hell, this is really difficult with /bin/sh. I want my zsh back! testdir=tests fvwmdir=.. myname=`basename $0` log=$testdir/$myname.log typeset -i c1 typeset -i c2 typeset -i c3 typeset -i i1 typeset -i i2 typeset -i nopts typeset -i copts usage () { echo "usage: $myname [-0] [-1] [-2] [-a] [make options]" echo " -0: run tests with all options defined and disabled (2 builds)" echo " -1: run tests with one option defined and disabled" echo " -2: run tests with two options defined and disabled" echo " -a: run all possible tests" echo " default is: myname -0 -1" echo " logging output goes to $log and $log.*" } # #parse command line # run_depth_0="" run_depth_1="" run_depth_2="" run_all="" custom="" while [ -n "$1" ] ; do if [ "$1" = "-h" ] ; then usage exit elif [ "$1" = "-?" ] ; then usage exit elif [ "$1" = "-0" ] ; then run_depth_0=1 run_all="" custom=1 elif [ "$1" = "-1" ] ; then run_depth_1=1 run_all="" custom=1 elif [ "$1" = "-2" ] ; then run_depth_2=1 run_all="" custom=1 elif [ "$1" = "-a" ] ; then run_depth_0="" run_depth_1="" run_depth_2="" run_all=1 custom=1 else break; fi shift done MAKE_OPTS="$*" # set default if nothing was selected if [ -z "$custom" ]; then run_depth_0="1" run_depth_1="1" fi if [ ! -x ./$myname ] ; then echo please run $myname from $testdir exit 1 fi cd $fvwmdir rm -f "$log"* > /dev/null 2>&1 ################## # some functions # ################## # clean up before next build clean_up () { make clean > /dev/null 2>&1 make distclean > /dev/null 2>&1 rm -f config.cache > /dev/null 2>&1 for i in `find . -name .deps -type d` ; do rm -rf $i; done > /dev/null 2>&1 for i in `find . -name Makefile` ; do rm -f $i; done > /dev/null 2>&1 for i in `find . -name "*.o"` ; do rm -f $i; done > /dev/null 2>&1 } # generate parameter list for configure disable_options () { CONFIGURE_OPTS="" while [ ! "$1" = "" ]; do CONFIGURE_OPTS="$CONFIGURE_OPTS --disable-${BUILD_OPTIONS[$1]}" shift done c3=0 while [ ! "${BUILD_OPTIONS[$c3]}" = "" ]; do echo $CONFIGURE_OPTS | grep -q -- "--disable-${BUILD_OPTIONS[$c3]}" || CONFIGURE_OPTS="$CONFIGURE_OPTS --enable-${BUILD_OPTIONS[$c3]}" c3=$c3+1 done } # disable all enabled options and vice versa reverse_options () { CONFIGURE_OPTS=`echo $CONFIGURE_OPTS | sed -e 's/--enable-/--xyz-/g' | sed -e 's/--disable-/--enable-/g' | sed -e 's/--xyz-/--disable-/g'` } # call configure and make (with logging) build () { echo "+++ testing (logfile $1): $CONFIGURE_OPTS" >> $log # clean up echo "cleaning up..." >> $log clean_up # configure echo "configuring..." >> $log echo "./configure $CONFIGURE_OPTS" > $log.$1 if nice ./configure --enable-extras $CONFIGURE_OPTS >> $log.$1 2>&1; then echo ok >> $log else echo FAILED >> $log fi # make echo "building..." >> $log if nice make $MAKE_OPTS > $log.$1 2>&1; then echo ok >> $log else echo FAILED >> $log fi echo >> $log } ############################ # end of functions section # ############################ # # get the list of possible options # c1=0 nopts=0 copts=1 for i in ` grep "^\(dnl dummy: \)\?smr_SWITCH" configure.in | grep -v debug-msgs | sed -e 's/^.*smr_SWITCH.//g' | cut -f 1 -d ","`; do BUILD_OPTIONS[$c1]="$i" OPTIONS="$OPTIONS $i" c1=$c1+1; nopts=$nopts+1; copts=$copts+$copts done # # now do the tests # if [ "$run_depth_1" = "1" ] ; then i1=$nopts+$nopts echo echo " +++ running $i1 tests for depth 1 +++" echo c1=0 while [ ! "${BUILD_OPTIONS[$c1]}" = "" ]; do disable_options $c1 echo build ${BUILD_OPTIONS[$c1]}_off build ${BUILD_OPTIONS[$c1]}_off reverse_options echo build ${BUILD_OPTIONS[$c1]}_on build ${BUILD_OPTIONS[$c1]}_on c1=$c1+1 done fi if [ "$run_depth_2" = "1" ] ; then i1="$nopts * $nopts + $nopts" echo echo " +++ running $i1 tests for depth 2 +++" echo c1=0 while [ -n "${BUILD_OPTIONS[$c1]}" ]; do c2=$c1+1 while [ -n "${BUILD_OPTIONS[$c2]}" ]; do disable_options $c1 $c2 echo build ${BUILD_OPTIONS[$c1]}_off,${BUILD_OPTIONS[$c2]}_off build ${BUILD_OPTIONS[$c1]}_off reverse_options echo build ${BUILD_OPTIONS[$c1]}_on,${BUILD_OPTIONS[$c2]}_on build ${BUILD_OPTIONS[$c1]}_on c2=$c2+1 done c1=$c1+1 done fi if [ "$run_depth_0" = "1" ] ; then echo echo " +++ running 2 tests for depth 0 +++" echo disable_options reverse_options echo build all_disabled build all_disabled disable_options echo build all_enabled build all_enabled fi if [ "$run_all" = "1" ] ; then i1=$copts+1 echo echo " +++ running $i1 tests for all combination of options +++" echo c1=0 while [ ! "$c1" = "$copts" ]; do c2=$c1 i1=0 opts_off="" while [ ! "$i1" = "$nopts" ]; do i2="$c2/2" i2="$i2*2" if [ "$i2" = "$c2" ]; then opts_off="$opts_off $i1" fi i1=$i1+1 c2=$c2/2 done disable_options $opts_off echo "test $c1 of $copts (logfile: `basename $log.$c1`):" echo "$CONFIGURE_OPTS" build $c1 c1=$c1+1 done fi fvwm-2.7.0/tests/Makefile.in0000644000175000017500000005143714324315776012655 00000000000000# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 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 = tests ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.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 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)` 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" ACLOCAL = @ACLOCAL@ ALL_DOMAINS = @ALL_DOMAINS@ ALL_LINGUAS = @ALL_LINGUAS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR_FLAGS = @AR_FLAGS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ Bidi_CFLAGS = @Bidi_CFLAGS@ Bidi_LIBS = @Bidi_LIBS@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DOC_COMMANDS = @DOC_COMMANDS@ DOC_COMMANDS_HTML = @DOC_COMMANDS_HTML@ DOC_COMMANDS_XML = @DOC_COMMANDS_XML@ DOC_COMMANDS_XML_PATH = @DOC_COMMANDS_XML_PATH@ DOC_MODULES = @DOC_MODULES@ DOC_MODULES_HTML = @DOC_MODULES_HTML@ DOC_SECTIONS = @DOC_SECTIONS@ DOC_SECTIONS_XML = @DOC_SECTIONS_XML@ DOC_SECTIONS_XML_PATH = @DOC_SECTIONS_XML_PATH@ DUMMYPOFILES = @DUMMYPOFILES@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FC_CFLAGS = @FC_CFLAGS@ FC_CONFIG = @FC_CONFIG@ FC_LIBS = @FC_LIBS@ FRIBIDI_CONFIG = @FRIBIDI_CONFIG@ FVWMALTFTP = @FVWMALTFTP@ FVWMALTFTPDIR = @FVWMALTFTPDIR@ FVWMFTP = @FVWMFTP@ FVWMFTPDIR = @FVWMFTPDIR@ FVWMHOMEPAGE = @FVWMHOMEPAGE@ FVWMLIST = @FVWMLIST@ FVWMNAMELONG = @FVWMNAMELONG@ FVWMSCRIPT_DOMAIN = @FVWMSCRIPT_DOMAIN@ FVWMTASKBAR_DOMAIN = @FVWMTASKBAR_DOMAIN@ FVWMWORKERSLIST = @FVWMWORKERSLIST@ FVWMWORKERSLISTLONG = @FVWMWORKERSLISTLONG@ FVWM_CONFDIR = @FVWM_CONFDIR@ FVWM_CPP = @FVWM_CPP@ FVWM_DATADIR = @FVWM_DATADIR@ FVWM_DOCDIR = @FVWM_DOCDIR@ FVWM_DOMAIN = @FVWM_DOMAIN@ FVWM_IMAGEPATH = @FVWM_IMAGEPATH@ FVWM_MODULEDIR = @FVWM_MODULEDIR@ FVWM_PERLLIB = @FVWM_PERLLIB@ FVWM_PERLLIBDIR = @FVWM_PERLLIBDIR@ GDK_IMLIB_CFLAGS = @GDK_IMLIB_CFLAGS@ GDK_IMLIB_LIBS = @GDK_IMLIB_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ IMLIBCONF = @IMLIBCONF@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INST_LINGUAS = @INST_LINGUAS@ ISRELEASED = @ISRELEASED@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOCALEDIR = @LOCALEDIR@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANPAGE_PREAMBLE = @MANPAGE_PREAMBLE@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ MSGUNIQ = @MSGUNIQ@ OBJEXT = @OBJEXT@ 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@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PYTHON = @PYTHON@ RANLIB = @RANLIB@ RELDATELONG = @RELDATELONG@ RELDATENUM = @RELDATENUM@ RELDATESHORT = @RELDATESHORT@ REQUIRED_PERL_VERSION = @REQUIRED_PERL_VERSION@ REQUIRED_PYTHON_VERSION = @REQUIRED_PYTHON_VERSION@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ UPDATEPOFILES = @UPDATEPOFILES@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VERSIONINFO = @VERSIONINFO@ XFT_CFLAGS = @XFT_CFLAGS@ XFT_CONFIG = @XFT_CONFIG@ XFT_LIBS = @XFT_LIBS@ XGETTEXT = @XGETTEXT@ XMKMF = @XMKMF@ XSLTPROC = @XSLTPROC@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Xcursor_CFLAGS = @Xcursor_CFLAGS@ Xcursor_LIBS = @Xcursor_LIBS@ Xft_CFLAGS = @Xft_CFLAGS@ Xft_LIBS = @Xft_LIBS@ Xinerama_CFLAGS = @Xinerama_CFLAGS@ Xinerama_LIBS = @Xinerama_LIBS@ Xrender_CFLAGS = @Xrender_CFLAGS@ Xrender_LIBS = @Xrender_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ iconv_CFLAGS = @iconv_CFLAGS@ iconv_LIBS = @iconv_LIBS@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intl_CFLAGS = @intl_CFLAGS@ intl_LIBS = @intl_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ png_CFLAGS = @png_CFLAGS@ png_LIBS = @png_LIBS@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ readline_CFLAGS = @readline_CFLAGS@ readline_LIBS = @readline_LIBS@ rplay_CFLAGS = @rplay_CFLAGS@ rplay_LIBS = @rplay_LIBS@ rsvg_CFLAGS = @rsvg_CFLAGS@ rsvg_LIBS = @rsvg_LIBS@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ stroke_CFLAGS = @stroke_CFLAGS@ stroke_LIBS = @stroke_LIBS@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ with_bidi = @with_bidi@ with_gdkimlib = @with_gdkimlib@ with_gettext = @with_gettext@ with_iconv = @with_iconv@ with_perllib = @with_perllib@ with_png = @with_png@ with_readline = @with_readline@ with_rplay = @with_rplay@ with_rsvg = @with_rsvg@ with_shape = @with_shape@ with_shm = @with_shm@ with_sm = @with_sm@ with_stroke = @with_stroke@ with_xcursor = @with_xcursor@ with_xft = @with_xft@ with_xinerama = @with_xinerama@ with_xpm = @with_xpm@ with_xrender = @with_xrender@ xpm_CFLAGS = @xpm_CFLAGS@ xpm_LIBS = @xpm_LIBS@ SUBDIRS = hints EXTRA_DIST = README.test_options test_options all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(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) --foreign tests/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tests/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: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): # 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 installdirs: installdirs-recursive installdirs-am: 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 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-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 pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic cscopelist-am ctags ctags-am \ distclean distclean-generic 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 installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic 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: fvwm-2.7.0/tests/README.test_options0000644000175000017500000000125514147024676014211 00000000000000Run the test_options script from this directory. It will configure and build fvwm multiple times for every selected combination of configure options. Parameters: -0: build once with all options disabled/enabled (2 builds) -1: build once with any single option disabled/enabled (2 builds per option) -2: build once with any combination of two options disabled/enabled (n * n + n builds where n is the number of options) -a: all tests (2 ^ n builds) The default is 'test_options -0 -1' since '-2' can take a very long time. A summary logfile test_options.log is generated as well as an additional log for each build (test_options.log.*). The names are self explaining. fvwm-2.7.0/tests/hints/0000755000175000017500000000000014324316056011773 500000000000000fvwm-2.7.0/tests/hints/Makefile.in0000644000175000017500000004664014324315776014002 00000000000000# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 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@ noinst_PROGRAMS = hints_test$(EXEEXT) subdir = tests/hints ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.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 = PROGRAMS = $(noinst_PROGRAMS) hints_test_SOURCES = hints_test.c hints_test_OBJECTS = hints_test.$(OBJEXT) hints_test_LDADD = $(LDADD) am__DEPENDENCIES_1 = hints_test_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_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)/etc/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/hints_test.Po am__mv = mv -f 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 = $(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 = hints_test.c DIST_SOURCES = hints_test.c 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)` am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/etc/depcomp \ README DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALL_DOMAINS = @ALL_DOMAINS@ ALL_LINGUAS = @ALL_LINGUAS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR_FLAGS = @AR_FLAGS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ Bidi_CFLAGS = @Bidi_CFLAGS@ Bidi_LIBS = @Bidi_LIBS@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DOC_COMMANDS = @DOC_COMMANDS@ DOC_COMMANDS_HTML = @DOC_COMMANDS_HTML@ DOC_COMMANDS_XML = @DOC_COMMANDS_XML@ DOC_COMMANDS_XML_PATH = @DOC_COMMANDS_XML_PATH@ DOC_MODULES = @DOC_MODULES@ DOC_MODULES_HTML = @DOC_MODULES_HTML@ DOC_SECTIONS = @DOC_SECTIONS@ DOC_SECTIONS_XML = @DOC_SECTIONS_XML@ DOC_SECTIONS_XML_PATH = @DOC_SECTIONS_XML_PATH@ DUMMYPOFILES = @DUMMYPOFILES@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FC_CFLAGS = @FC_CFLAGS@ FC_CONFIG = @FC_CONFIG@ FC_LIBS = @FC_LIBS@ FRIBIDI_CONFIG = @FRIBIDI_CONFIG@ FVWMALTFTP = @FVWMALTFTP@ FVWMALTFTPDIR = @FVWMALTFTPDIR@ FVWMFTP = @FVWMFTP@ FVWMFTPDIR = @FVWMFTPDIR@ FVWMHOMEPAGE = @FVWMHOMEPAGE@ FVWMLIST = @FVWMLIST@ FVWMNAMELONG = @FVWMNAMELONG@ FVWMSCRIPT_DOMAIN = @FVWMSCRIPT_DOMAIN@ FVWMTASKBAR_DOMAIN = @FVWMTASKBAR_DOMAIN@ FVWMWORKERSLIST = @FVWMWORKERSLIST@ FVWMWORKERSLISTLONG = @FVWMWORKERSLISTLONG@ FVWM_CONFDIR = @FVWM_CONFDIR@ FVWM_CPP = @FVWM_CPP@ FVWM_DATADIR = @FVWM_DATADIR@ FVWM_DOCDIR = @FVWM_DOCDIR@ FVWM_DOMAIN = @FVWM_DOMAIN@ FVWM_IMAGEPATH = @FVWM_IMAGEPATH@ FVWM_MODULEDIR = @FVWM_MODULEDIR@ FVWM_PERLLIB = @FVWM_PERLLIB@ FVWM_PERLLIBDIR = @FVWM_PERLLIBDIR@ GDK_IMLIB_CFLAGS = @GDK_IMLIB_CFLAGS@ GDK_IMLIB_LIBS = @GDK_IMLIB_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ IMLIBCONF = @IMLIBCONF@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INST_LINGUAS = @INST_LINGUAS@ ISRELEASED = @ISRELEASED@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOCALEDIR = @LOCALEDIR@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANPAGE_PREAMBLE = @MANPAGE_PREAMBLE@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ MSGUNIQ = @MSGUNIQ@ OBJEXT = @OBJEXT@ 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@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PYTHON = @PYTHON@ RANLIB = @RANLIB@ RELDATELONG = @RELDATELONG@ RELDATENUM = @RELDATENUM@ RELDATESHORT = @RELDATESHORT@ REQUIRED_PERL_VERSION = @REQUIRED_PERL_VERSION@ REQUIRED_PYTHON_VERSION = @REQUIRED_PYTHON_VERSION@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ UPDATEPOFILES = @UPDATEPOFILES@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VERSIONINFO = @VERSIONINFO@ XFT_CFLAGS = @XFT_CFLAGS@ XFT_CONFIG = @XFT_CONFIG@ XFT_LIBS = @XFT_LIBS@ XGETTEXT = @XGETTEXT@ XMKMF = @XMKMF@ XSLTPROC = @XSLTPROC@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Xcursor_CFLAGS = @Xcursor_CFLAGS@ Xcursor_LIBS = @Xcursor_LIBS@ Xft_CFLAGS = @Xft_CFLAGS@ Xft_LIBS = @Xft_LIBS@ Xinerama_CFLAGS = @Xinerama_CFLAGS@ Xinerama_LIBS = @Xinerama_LIBS@ Xrender_CFLAGS = @Xrender_CFLAGS@ Xrender_LIBS = @Xrender_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ iconv_CFLAGS = @iconv_CFLAGS@ iconv_LIBS = @iconv_LIBS@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intl_CFLAGS = @intl_CFLAGS@ intl_LIBS = @intl_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ png_CFLAGS = @png_CFLAGS@ png_LIBS = @png_LIBS@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ readline_CFLAGS = @readline_CFLAGS@ readline_LIBS = @readline_LIBS@ rplay_CFLAGS = @rplay_CFLAGS@ rplay_LIBS = @rplay_LIBS@ rsvg_CFLAGS = @rsvg_CFLAGS@ rsvg_LIBS = @rsvg_LIBS@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ stroke_CFLAGS = @stroke_CFLAGS@ stroke_LIBS = @stroke_LIBS@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ with_bidi = @with_bidi@ with_gdkimlib = @with_gdkimlib@ with_gettext = @with_gettext@ with_iconv = @with_iconv@ with_perllib = @with_perllib@ with_png = @with_png@ with_readline = @with_readline@ with_rplay = @with_rplay@ with_rsvg = @with_rsvg@ with_shape = @with_shape@ with_shm = @with_shm@ with_sm = @with_sm@ with_stroke = @with_stroke@ with_xcursor = @with_xcursor@ with_xft = @with_xft@ with_xinerama = @with_xinerama@ with_xpm = @with_xpm@ with_xrender = @with_xrender@ xpm_CFLAGS = @xpm_CFLAGS@ xpm_LIBS = @xpm_LIBS@ LDADD = -L$(top_builddir)/libs $(X_LIBS) -lfvwm \ $(X_PRE_LIBS) -lXext -lX11 -lm $(X_EXTRA_LIBS) AM_CPPFLAGS = -I$(top_srcdir) $(X_CFLAGS) all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: $(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) --foreign tests/hints/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign tests/hints/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: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstPROGRAMS: -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) hints_test$(EXEEXT): $(hints_test_OBJECTS) $(hints_test_DEPENDENCIES) $(EXTRA_hints_test_DEPENDENCIES) @rm -f hints_test$(EXEEXT) $(AM_V_CCLD)$(LINK) $(hints_test_OBJECTS) $(hints_test_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hints_test.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)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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) '$<'` 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 $(PROGRAMS) 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-noinstPROGRAMS mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/hints_test.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)/hints_test.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic 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-noinstPROGRAMS cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ 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 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: fvwm-2.7.0/tests/hints/hints_test.c0000644000175000017500000004424714147024700014251 00000000000000/* -*-c-*- */ #include "config.h" #include #include #include #include #include #include #include "libs/FEvent.h" Display *dpy; Window Root, win; int screen; int has_focus_proto = 0; int has_delete_proto = 1; int input_mode = -1; Atom ATOM_NET_WM_WINDOW_TYPE = None; Atom ATOM_NET_WM_WINDOW_TYPE_DESKTOP = None; Atom ATOM_NET_WM_WINDOW_TYPE_DOCK = None; Atom ATOM_NET_WM_WINDOW_TYPE_TOOLBAR = None; Atom ATOM_NET_WM_WINDOW_TYPE_MENU = None; Atom ATOM_NET_WM_WINDOW_TYPE_DIALOG = None; Atom ATOM_NET_WM_WINDOW_TYPE_NORMAL = None; Atom ATOM_NET_WM_WINDOW_TYPE_SPLASH = None; Atom ATOM_NET_WM_WINDOW_TYPE_UTILITY = None; Atom ATOM_KDE_NET_WM_WINDOW_TYPE_OVERRIDE = None; Atom ATOM_NET_WM_STATE = None; Atom ATOM_NET_WM_STATE_MODAL = None; Atom ATOM_NET_WM_STATE_STICKY = None; Atom ATOM_NET_WM_STATE_MAXIMIZED_VERT = None; Atom ATOM_NET_WM_STATE_MAXIMIZED_HORIZ = None; Atom ATOM_NET_WM_STATE_SHADED = None; Atom ATOM_NET_WM_STATE_SKIP_TASKBAR = None; Atom ATOM_NET_WM_STATE_SKIP_PAGER = None; Atom ATOM_NET_WM_STATE_HIDDEN = None; Atom ATOM_NET_WM_STATE_STAYS_ON_TOP = None; Atom ATOM_NET_WM_STATE_FULLSCREEN = None; Atom ATOM_NET_WM_DESKTOP = None; /* wm protocol */ Atom ATOM_WM_DELETE_WINDOW = None; Atom ATOM_WM_TAKE_FOCUS = None; /* Motif window hints */ Atom ATOM_MOTIF_WM_HINTS = None; #define MWM_HINTS_FUNCTIONS (1L << 0) #define MWM_HINTS_DECORATIONS (1L << 1) #define MWM_HINTS_INPUT_MODE (1L << 2) #define MWM_HINTS_STATUS (1L << 3) /* ? */ /* bit definitions for MwmHints.functions */ #define MWM_FUNC_ALL (1L << 0) #define MWM_FUNC_RESIZE (1L << 1) #define MWM_FUNC_MOVE (1L << 2) #define MWM_FUNC_MINIMIZE (1L << 3) #define MWM_FUNC_MAXIMIZE (1L << 4) #define MWM_FUNC_CLOSE (1L << 5) /* values for MwmHints.input_mode */ #define MWM_INPUT_MODELESS 0 #define MWM_INPUT_PRIMARY_APPLICATION_MODAL 1 #define MWM_INPUT_SYSTEM_MODAL 2 #define MWM_INPUT_FULL_APPLICATION_MODAL 3 /* bit definitions for MwmHints.decorations */ #define MWM_DECOR_ALL (1L << 0) #define MWM_DECOR_BORDER (1L << 1) #define MWM_DECOR_RESIZEH (1L << 2) #define MWM_DECOR_TITLE (1L << 3) #define MWM_DECOR_MENU (1L << 4) #define MWM_DECOR_MINIMIZE (1L << 5) #define MWM_DECOR_MAXIMIZE (1L << 6) /* * _MWM_HINTS property */ typedef struct { long props[4]; /* props[0]: flags */ /* props[1]: functions */ /* props[2]: decorations */ /* props[3]: inputMode */ } PropMotifWmHints; typedef PropMotifWmHints PropMwmHints; #define PROP_MOTIF_WM_HINTS_ELEMENTS 4 #define PROP_MWM_HINTS_ELEMENTS PROP_MOTIF_WM_HINTS_ELEMENTS void Xloop(void) { while (1) { XEvent ev; XWindowAttributes xatt; /* Sit and wait for an event to happen */ FNextEvent(dpy,&ev); switch(ev.type) { case ConfigureNotify: break; case ClientMessage: if (has_delete_proto && ev.xclient.format == 32 && ev.xclient.data.l[0] == ATOM_WM_DELETE_WINDOW) { exit(0); } else if (has_focus_proto && ev.xclient.data.l[0] == ATOM_WM_TAKE_FOCUS) { printf("WM_TAKE_FOCUS message\n"); if (input_mode == 1) { printf ("\t...do nothing\n"); } else if (input_mode == 0) { if (XGetWindowAttributes(dpy, win, &xatt) && xatt.map_state == IsViewable) { printf ("\t...setting focus on our own: %lu\n", ev.xclient.data.l[1]); XSetInputFocus( dpy, win, RevertToParent, ev.xclient.data.l[1]); } else { printf ("\t...but we are not viewable\n"); } } } break; default: break; } } } #define XIA(a) XInternAtom(dpy,a,False); void InitAtom(void) { ATOM_NET_WM_WINDOW_TYPE = XIA("_NET_WM_WINDOW_TYPE"); ATOM_NET_WM_WINDOW_TYPE_DESKTOP = XIA("_NET_WM_WINDOW_TYPE_DESKTOP"); ATOM_NET_WM_WINDOW_TYPE_DOCK = XIA("_NET_WM_WINDOW_TYPE_DOCK"); ATOM_NET_WM_WINDOW_TYPE_TOOLBAR = XIA("_NET_WM_WINDOW_TYPE_TOOLBAR"); ATOM_NET_WM_WINDOW_TYPE_MENU = XIA("_NET_WM_WINDOW_TYPE_MENU"); ATOM_NET_WM_WINDOW_TYPE_DIALOG = XIA("_NET_WM_WINDOW_TYPE_DIALOG"); ATOM_NET_WM_WINDOW_TYPE_NORMAL = XIA("_NET_WM_WINDOW_TYPE_NORMAL"); ATOM_NET_WM_WINDOW_TYPE_SPLASH = XIA("_NET_WM_WINDOW_TYPE_SPLASH"); ATOM_NET_WM_WINDOW_TYPE_UTILITY = XIA("_NET_WM_WINDOW_TYPE_UTILITY"); ATOM_KDE_NET_WM_WINDOW_TYPE_OVERRIDE = XIA("_KDE_NET_WM_WINDOW_TYPE_OVERRIDE"); ATOM_NET_WM_STATE = XIA("_NET_WM_STATE"); ATOM_NET_WM_STATE_MODAL = XIA("_NET_WM_STATE_MODAL"); ATOM_NET_WM_STATE_STICKY = XIA("_NET_WM_STATE_STICKY"); ATOM_NET_WM_STATE_MAXIMIZED_VERT = XIA("_NET_WM_STATE_MAXIMIZED_VERT"); ATOM_NET_WM_STATE_MAXIMIZED_HORIZ = XIA("_NET_WM_STATE_MAXIMIZED_HORIZ"); ATOM_NET_WM_STATE_SHADED = XIA("_NET_WM_STATE_SHADED"); ATOM_NET_WM_STATE_SKIP_TASKBAR = XIA("_NET_WM_STATE_SKIP_TASKBAR"); ATOM_NET_WM_STATE_SKIP_PAGER = XIA("_NET_WM_STATE_SKIP_PAGER"); ATOM_NET_WM_STATE_HIDDEN = XIA("_NET_WM_STATE_HIDDEN"); ATOM_NET_WM_STATE_FULLSCREEN = XIA("_NET_WM_STATE_FULLSCREEN"); ATOM_NET_WM_STATE_STAYS_ON_TOP = XIA("_NET_WM_STATE_STAYS_ON_TOP"); ATOM_NET_WM_DESKTOP = XIA("_NET_WM_DESKTOP"); ATOM_WM_DELETE_WINDOW = XIA("WM_DELETE_WINDOW"); ATOM_WM_TAKE_FOCUS = XIA("WM_TAKE_FOCUS"); ATOM_MOTIF_WM_HINTS = XIA("_MOTIF_WM_HINTS"); } void show_usage(void) { printf("Usage: hints_test OPTIONS\n"); printf("Options:\n"); printf(" --mwm-func \n"); printf(" all, resize, move, minimize, maximize, close\n"); printf(" --mwm-decor \n"); printf(" all, border, resizeh, title, menu, minimize, maximize\n"); printf(" --ewmh-state \n"); printf(" hidden, shaded, sticky, skippager, skiptaskbar,\n"); printf(" maxhoriz, maxvert, modal, staysontop, fullscreen\n"); printf(" --ewmh-type \n"); printf(" normal, dock, toolbar, desktop, menu, dialog, splash, utility\n"); printf(" --mwm-input { modless, app_modal, sys_modal, full_app_modal}\n"); printf(" --ewmh-desktop\n"); printf(" --wm-state { withdrawn, normal, iconic }\n"); printf(" --wm-urgency\n"); printf(" --wm-group { window, root, }\n"); printf(" --min-size \n"); printf(" --max-size \n"); printf(" --inc-size \n"); printf(" --p-geometry \n"); printf(" --us-geometry \n"); printf(" --input { true, false }\n"); printf(" --delete-proto\n"); printf(" --no-delete-proto\n"); printf(" --transient\n"); } int main(int argc, char **argv) { int state_count = 0; Atom states[10]; Atom type = 0; int i,x_r,y_r; unsigned int h_r,w_r; int ret; int ewmh_state_arg = 0; int ewmh_type_arg = 0; int mwm_func_arg = 0; int mwm_decor_arg = 0; int has_ewmh_desktop = 0; Atom ewmh_desktop = 0; XSizeHints hints; XClassHint classhints; XWMHints wm_hints; PropMwmHints mwm_hints; Window trans_win = 0; if (!(dpy = XOpenDisplay(""))) { fprintf(stderr, "can't open display\n"); exit(1); } screen = DefaultScreen(dpy); Root = RootWindow(dpy, screen); InitAtom(); hints.width = 170; hints.height = 100; hints.x = 0; hints.y = 0; hints.flags = 0; wm_hints.flags = 0; mwm_hints.props[0] = 0; mwm_hints.props[1] = 0; mwm_hints.props[2] = 0; mwm_hints.props[3] = 0; win = XCreateSimpleWindow( dpy, Root, 0, 0, hints.width, hints.height, 0, 0, 0); for (i = 1; i < argc; i++) { char *error_arg = NULL; if (strcasecmp(argv[i], "--help") == 0) { show_usage(); exit(0); } else if (strcasecmp(argv[i], "--ewmh-state") == 0) { ewmh_state_arg = 1; ewmh_type_arg = 0; mwm_func_arg = 0; mwm_decor_arg = 0; } else if (strcasecmp(argv[i], "--ewmh-type") == 0) { ewmh_state_arg = 0; ewmh_type_arg = 1; mwm_func_arg = 0; mwm_decor_arg = 0; } else if (strcasecmp(argv[i], "--mwm-func") == 0) { ewmh_state_arg = 0; ewmh_type_arg = 0; mwm_func_arg = 1; mwm_decor_arg = 0; } else if (strcasecmp(argv[i], "--mwm-decor") == 0) { ewmh_state_arg = 0; ewmh_type_arg = 0; mwm_func_arg = 0; mwm_decor_arg = 1; } else if (strcasecmp(argv[i], "--min-size") == 0) { i++; hints.min_width = atoi(argv[i]); i++; hints.min_height = atoi(argv[i]); hints.flags |= PMinSize; } else if (strcasecmp(argv[i], "--max-size") == 0) { i++; hints.max_width = atoi(argv[i]); i++; hints.max_height = atoi(argv[i]); hints.flags |= PMaxSize; } else if (strcasecmp(argv[i], "--inc-size") == 0) { i++; hints.width_inc = atoi(argv[i]); i++; hints.height_inc = atoi(argv[i]); hints.flags |= PResizeInc; } else if (strcasecmp(argv[i], "--p-geometry") == 0) { i++; ret = XParseGeometry(argv[i], &x_r, &y_r, &w_r, &h_r); if ((ret & WidthValue) && (ret & HeightValue)) { hints.width = w_r; hints.height = h_r; hints.flags |= PSize; } if ((ret & XValue) && (ret & YValue)) { hints.x = x_r; hints.y = y_r; hints.win_gravity = NorthWestGravity; if (ret & XNegative) { hints.x += XDisplayWidth(dpy, screen) - hints.width; hints.win_gravity = NorthEastGravity; } if (ret & YNegative) { hints.y += XDisplayHeight(dpy, screen) - hints.height; if (ret & XNegative) { hints.win_gravity = SouthEastGravity; } else { hints.win_gravity = SouthWestGravity; } hints.flags |= PWinGravity; } hints.flags |= PPosition; } } else if (strcasecmp(argv[i], "--us-geometry") == 0) { i++; ret = XParseGeometry(argv[i], &x_r, &y_r, &w_r, &h_r); if ((ret & WidthValue) && (ret & HeightValue)) { hints.width = w_r; hints.height = h_r; hints.flags |= USSize; } if ((ret & XValue) && (ret & YValue)) { hints.x = x_r; hints.y = y_r; hints.win_gravity=NorthWestGravity; if (ret & XNegative) { hints.x += XDisplayWidth(dpy,screen) - hints.width; hints.win_gravity=NorthEastGravity; } if (ret & YNegative) { hints.y += XDisplayHeight(dpy,screen) - hints.height; if (ret & XNegative) { hints.win_gravity = SouthEastGravity; } else { hints.win_gravity = SouthWestGravity; } } hints.flags |= USPosition | PWinGravity; } } else if (strcasecmp(argv[i], "--input") == 0) { i++; if (strcasecmp(argv[i], "true") == 0) { wm_hints.input = input_mode = True; wm_hints.flags |= InputHint; } else if (strcasecmp(argv[i], "false") == 0) { wm_hints.input = input_mode = False; wm_hints.flags |= InputHint; } else { error_arg = "--input"; } } else if (strcasecmp(argv[i], "--focus-proto") == 0) { has_focus_proto = 1; } else if (strcasecmp(argv[i], "--no-delete-proto") == 0) { has_delete_proto = 0; } else if (strcasecmp(argv[i], "--wm-state") == 0) { wm_hints.flags |= StateHint; i++; if (strcasecmp(argv[i], "withdrawn") == 0) { wm_hints.initial_state = WithdrawnState; } else if (strcasecmp(argv[i], "normal") == 0) { wm_hints.initial_state = NormalState; } else if (strcasecmp(argv[i], "iconic") == 0) { wm_hints.initial_state = IconicState; } else { error_arg = "--wm-state"; } } else if (strcasecmp(argv[i], "--wm-urgency") == 0) { wm_hints.flags |= XUrgencyHint; } else if (strcasecmp(argv[i], "--wm-group") == 0) { wm_hints.flags |= WindowGroupHint; i++; if (strcasecmp(argv[i], "window") == 0) { wm_hints.window_group = win; } else if (strcasecmp(argv[i], "root") == 0) { wm_hints.window_group = Root; } else { wm_hints.window_group = strtoul(argv[i], NULL, 0); } } else if (strcasecmp(argv[i], "--transient") == 0) { i++; if (strcasecmp(argv[i],"root") == 0) { trans_win = Root; } else { trans_win = strtoul(argv[i], NULL, 0); } } else if (strcasecmp(argv[i], "--mwm-input") == 0) { mwm_hints.props[0] |= MWM_HINTS_INPUT_MODE; i++; if (strcasecmp(argv[i], "modless") == 0) { mwm_hints.props[3] = MWM_INPUT_MODELESS; } else if (strcasecmp(argv[i], "app_modal") == 0) { mwm_hints.props[3] = MWM_INPUT_PRIMARY_APPLICATION_MODAL; } else if (strcasecmp(argv[i], "sys_modal") == 0) { mwm_hints.props[3] = MWM_INPUT_SYSTEM_MODAL; } else if (strcasecmp(argv[i], "full_app_modal") == 0) { mwm_hints.props[3] = MWM_INPUT_FULL_APPLICATION_MODAL; } else { error_arg = "--mwm-input"; } } else if (strcasecmp(argv[i], "--ewmh-desktop") == 0) { has_ewmh_desktop = 1; i++; ewmh_desktop = atol(argv[i]); } else if (ewmh_state_arg && state_count < 10) { if (strcasecmp(argv[i], "hidden") == 0) { states[state_count++] = ATOM_NET_WM_STATE_HIDDEN; } else if (strcasecmp(argv[i], "shaded") == 0) { states[state_count++] = ATOM_NET_WM_STATE_SHADED; } else if (strcasecmp(argv[i], "sticky") == 0) { states[state_count++] = ATOM_NET_WM_STATE_STICKY; } else if (strcasecmp(argv[i], "skippager") == 0) { states[state_count++] = ATOM_NET_WM_STATE_SKIP_PAGER; } else if (strcasecmp(argv[i], "skiptaskbar") == 0) { states[state_count++] = ATOM_NET_WM_STATE_SKIP_TASKBAR; } else if (strcasecmp(argv[i], "maxhoriz") == 0) { states[state_count++] = ATOM_NET_WM_STATE_MAXIMIZED_HORIZ; } else if (strcasecmp(argv[i], "maxvert") == 0) { states[state_count++] = ATOM_NET_WM_STATE_MAXIMIZED_VERT; } else if (strcasecmp(argv[i], "modal") == 0) { states[state_count++] = ATOM_NET_WM_STATE_MODAL; } else if (strcasecmp(argv[i], "staysontop") == 0) { states[state_count++] = ATOM_NET_WM_STATE_STAYS_ON_TOP; } else if (strcasecmp(argv[i], "fullscreen") == 0) { states[state_count++] = ATOM_NET_WM_STATE_FULLSCREEN; } else { error_arg = "--ewmh-state"; } } else if (ewmh_type_arg) { if (strcasecmp(argv[i], "normal") == 0) { type = ATOM_NET_WM_WINDOW_TYPE_NORMAL; } else if (strcasecmp(argv[i], "dock") == 0) { type = ATOM_NET_WM_WINDOW_TYPE_DOCK; } else if (strcasecmp(argv[i], "toolbar") == 0) { type = ATOM_NET_WM_WINDOW_TYPE_TOOLBAR; } else if (strcasecmp(argv[i], "desktop") == 0) { type = ATOM_NET_WM_WINDOW_TYPE_DESKTOP; } else if (strcasecmp(argv[i], "menu") == 0) { type = ATOM_NET_WM_WINDOW_TYPE_MENU; } else if (strcasecmp(argv[i], "dialog") == 0) { type = ATOM_NET_WM_WINDOW_TYPE_DIALOG; } else if (strcasecmp(argv[i], "splash") == 0) { type = ATOM_NET_WM_WINDOW_TYPE_SPLASH; } else if (strcasecmp(argv[i], "utility") == 0) { type = ATOM_NET_WM_WINDOW_TYPE_UTILITY; } else { error_arg = "--ewmh-type"; } } else if (mwm_func_arg) { mwm_hints.props[0] |= MWM_HINTS_FUNCTIONS; if (strcasecmp(argv[i], "all") == 0) { mwm_hints.props[1] |= MWM_FUNC_ALL; } else if (strcasecmp(argv[i], "resize") == 0) { mwm_hints.props[1] |= MWM_FUNC_RESIZE; } else if (strcasecmp(argv[i], "move") == 0) { mwm_hints.props[1] |= MWM_FUNC_MOVE; } else if (strcasecmp(argv[i], "minimize") == 0) { mwm_hints.props[1] |= MWM_FUNC_MINIMIZE; } else if (strcasecmp(argv[i], "maximize") == 0) { mwm_hints.props[1] |= MWM_FUNC_MAXIMIZE; } else if (strcasecmp(argv[i], "close") == 0) { mwm_hints.props[1] |= MWM_FUNC_CLOSE; } else { error_arg = "--mwm-func"; } } else if (mwm_decor_arg) { mwm_hints.props[0] |= MWM_HINTS_DECORATIONS; if (strcasecmp(argv[i], "all") == 0) { mwm_hints.props[2] |= MWM_DECOR_ALL; } else if (strcasecmp(argv[i], "border") == 0) { mwm_hints.props[2] |= MWM_DECOR_BORDER; } else if (strcasecmp(argv[i], "resizeh") == 0) { mwm_hints.props[2] |= MWM_DECOR_RESIZEH; } else if (strcasecmp(argv[i], "title") == 0) { mwm_hints.props[2] |= MWM_DECOR_TITLE; } else if (strcasecmp(argv[i], "menu") == 0) { mwm_hints.props[2] |= MWM_DECOR_MENU; } else if (strcasecmp(argv[i], "minimize") == 0) { mwm_hints.props[2] |= MWM_DECOR_MINIMIZE; } else if (strcasecmp(argv[i], "maximize") == 0) { mwm_hints.props[2] |= MWM_DECOR_MAXIMIZE; } else { error_arg = "--mwm-decor"; } } else { error_arg = "regular"; } if (error_arg) { show_usage(); printf("Invalid %s argument: %s\n", error_arg, argv[i]); exit(1); } } XSelectInput(dpy, win, StructureNotifyMask); if (wm_hints.flags) { XSetWMHints(dpy, win, &wm_hints); } if (state_count != 0) { XChangeProperty( dpy, win, ATOM_NET_WM_STATE, XA_ATOM, 32, PropModeReplace, (unsigned char *)states, state_count); } if (type != 0) { XChangeProperty( dpy, win, ATOM_NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, (unsigned char *)&type, 1); } if (has_ewmh_desktop) { XChangeProperty( dpy, win, ATOM_NET_WM_DESKTOP, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&ewmh_desktop, 1); } if (has_delete_proto || has_focus_proto) { Atom proto[2]; int j = 0; if (has_delete_proto) proto[j++] = ATOM_WM_DELETE_WINDOW; if (has_focus_proto) proto[j++] = ATOM_WM_TAKE_FOCUS; XSetWMProtocols(dpy, win, proto, j); } { XTextProperty nametext; char *list[] = { NULL, NULL }; list[0] = "Hints Test"; classhints.res_name = strdup("hints_test"); classhints.res_class = strdup("HintsTest"); if (!XStringListToTextProperty(list, 1, &nametext)) { fprintf(stderr, "Failed to convert name to XText\n"); exit(1); } XSetWMProperties( dpy, win, &nametext, &nametext, NULL, 0, &hints, NULL, &classhints); XFree(nametext.value); } if (mwm_hints.props[0] != 0) { XChangeProperty( dpy, win, ATOM_MOTIF_WM_HINTS, ATOM_MOTIF_WM_HINTS, 32, PropModeReplace,(unsigned char *)&mwm_hints, PROP_MWM_HINTS_ELEMENTS); } if (trans_win !=0) XSetTransientForHint(dpy, win, trans_win); XMapWindow(dpy, win); XSetWindowBackground(dpy, win, 0); Xloop(); return 1; } fvwm-2.7.0/tests/hints/README0000644000175000017500000000473214147024676012610 00000000000000This directory contains only the hints_test.c program. To compile it either try "make" or something like % gcc -g -O2 -Wall -I/usr/X11R6/include -L/usr/X11R6/lib -c hints_test.c % gcc -g -O2 -Wall -o hints_test hints_test.o -I/usr/X11R6/include -L/usr/X11R6/lib -lX11 should work. The program does nothing: it is just a 170x100 black window. However, using options you can set various hints (XSizeHints, XWMHints, MWM hints, EWMH hints) on the window. Here are the options: --help Show usage --min-size w h Set the min_width and min_height XSizeHints to w and h --max-size w h Set the max_width and max_height XSizeHints to w and h --inc-size w h Set the inc_width and inc_height XSizeHints to w and h --p-geometry geometry Set the program geometry and the gravity accordingly. geometry is a standard X geometry (not a F geometry) --us-geometry geometry Set the user geometry and the gravity accordingly. geometry is a standard X geometry (not a F geometry) --input Bool Set the InputHint to Bool where Bool is either true or false --focus-proto Respect the WM_TAKE_FOCUS protocol --no-delete-proto By default the program respect the WM_DELETE_WINDOW protocol. This option forces the program to do not use it at all. --wm-state state Set the initial wm state to state, where state can be withdrawn, iconic or normal --wm-urgency Set the wm urgency flags --wm-group win Set the window group leader to win where win can be root, window or the id of an window. --transient win Set the WM_TRANSIENT_FOR window to win where win can be root or the id of an window. --mwm-decor args where args is a non empty space separated list of the following key words: all, border, resizeh, title, menu, minimize, maximize --mwm-func args where args is a non empty space separated list of the following key words: all, resize, move, maximize, minimize, close --mwm-input arg where arg can be: modless, app_modal, sys_modal, full_app_modal --ewmh-type type Set the EWMH window type to type where type can be: normal, dock, toolbar, desktop, menu, dialog, splash, utility --ewmh-state states Set the EWMH window states to states where states is a non empty space separated list of the following key words: hidden, shaded, sticky, skippager, skiptaskbar, maxhoriz, maxvert, modal, staysontop, fullscreen --ewmh-desktop int Set desktop initial state This is just a test program there is no full checking when the options are parsed. Do not forget to use xprop and xwininfo. Have Fun! fvwm-2.7.0/tests/hints/Makefile.am0000644000175000017500000000042014147024700013736 00000000000000## Process this file with automake to create Makefile.in # Don't install this, its just for testing. noinst_PROGRAMS = hints_test LDADD = -L$(top_builddir)/libs $(X_LIBS) -lfvwm \ $(X_PRE_LIBS) -lXext -lX11 -lm $(X_EXTRA_LIBS) AM_CPPFLAGS = -I$(top_srcdir) $(X_CFLAGS) fvwm-2.7.0/tests/Makefile.am0000644000175000017500000000040414147024676012627 00000000000000## This is a -*- Makefile -*- ## Process this file with automake to create Makefile.in SUBDIRS = hints EXTRA_DIST = README.test_options test_options ## The files in the purify subdir are NOT distributed, due to controversy over ## the benefits of doing so. fvwm-2.7.0/INSTALL.md0000644000175000017500000000121714147024700011050 00000000000000Installation Instructions ========================= FVWM uses automake and friends as its build process. Installing From Git =================== FVWM has a bootstrap script to generate `configure` and associated files. Run: ``` ./autogen.sh ``` This will also call `./configure` after it has been generated. Then run: ``` make ``` Installing From Release Tarball =============================== Release tarballs will come bundled with `./configure` already, hence: ``` ./configure && make ``` As with most things, if the default options `./configure` chooses isn't appropriate for your needs, see `./configure --help` for appropriate options. fvwm-2.7.0/NEWS0000644000175000017500000023672014324315710010131 00000000000000Note, the changes for the last STABLE release start with release 2.6.0. ------------------------------------------------------------------- Changes in stable release 2.7.0 (19-Oct-2022) * Bug fixes: - Fix handling of configure's --enable-mandoc/--enable-htmldoc - Fix crash in FvwmPager when desk height or width is 0 - Added DoubleClick time to man page. - Fix to FvwmIconMan to disable a SizeHint warning. - Allow for reproducible builds. - Increase the number of supported mouse buttons to 15. - Tweaks to configure.ac * New fvwm features: ------------------------------------------------------------------- Changes in stable release 2.6.8 (31-Mar-2018) * Bug fixes: - Various DESTDIR fixes (especially around the default-config Makefile) - fvwm-perllib pod2man fixes. - FvwmIconMan no longer triggers a warning about bad size hints in the fvwm core. - VMware windows do not disapper when switching between fullscreen and normal state. - Fix (de)installation with the configure options --program-prefix, --program-suffix and --program-transform-name. - Remove further references to obsolete modules from man page(s). * New fvwm features: - fvwm-menu-desktop(1) now requires python3 as an explicit dependency. - Add a 'fullscreen' option to the 'Maximize' command. ------------------------------------------------------------------- Changes in stable release 2.6.7 (06-Mar-2016) * New fvwm features: - A new default configuration which is available when fvwm doesn't detect a configuration file to load. - A new conitional command "Desk n" can restrict matching windows to a specific desk. - A new conditional command "Screen n" to restrict matching windows on a given Xinerama screen. - New expansion variable "w.screen" to ascertain the Xineram screen number a window is on. - New command "InfoStoreClear" to remove all items in the InfoStore. * Removed features: - The old and unmaintained debian/and rpm/ directories have been remmoved; use the maintainers' copies where available. - VMS support has been removed. - GTK1.x support has been removed. - GNOME-specific window hints (pre-EWMH) have been removed. - Some fvwm modules have been removed: - FvwmDragWell (no replacement) - FvwmGTK (no replacement) - FvwmSave (no replacement) - FvwmSaveDesk (no replacement) - FvwmScroll (no replacement) - FvwmTabs (no replacement, never worked anyway) - FvwmTaskBar (use FvwmButtons) - FvwmTheme (in core of fvwm as colorsets) - FvwmWharf (use FvwmButtons) - FvwmWinList (use WindowList command) - FvwmWindowMenu (use WindowList command) - FvwmIconBox (use the IconBox style instead) * New module features: - FvwmButtons learned a new option "Colorset" to its ChangeButton command. * fvwm-menu-desktop updated: - Renamed default menu to XDGMenu and changed the name of the FvwmForm to FvwmForm-XDGMenu-Config to not conflict with someone already using FvwmMenu. - fvwm-menu-desktop will now load defaults from the FvwmForm-XDGMenu-Config data file. - Improved dynamic menus by regenerating them on-the-fly. - Added new options: --regen-cmd, --dynamic, and more. * Bug fixes: - A bug introduced in 2.6.6 could cause applications with negative coordinates to be placed at strange positions. This affected for example acroread when switching to fullscreen mode. This has been fixed. - FvwmButtons "Silent" option for dynamic ChangeButton commands no longer loops infinitely. Changes in stable release 2.6.6 (15-Mar-2016) * New fvwm features: - Support for Russian from Ivan Gayevskiy. - EnvMatch supports infostore variables. - The option "forget" to the Maximize command allows to unmaximize a window without changing its size and position. - Windows shaded to a corner (NW, NE, SW, SE) are reduced to a small square. - New option "!raise" to the WarpToWindow command. - The new extended variables $[wa.x], $[wa.y], $[wa.width], $[wa.height] can be used to get the geometry of the EWMH working area, and $[dwa.x], $[dwa.y], $[dwa.width], $[dwa.height] can be used to get the geometry of the EWMH dynamic working area. - The Resize commands accept "wa" or "da" as a suffix of the width or height value. If present, the value is a percentage of the width or height of the EWMH working area or the EWMH dynamic working area. - Fvwm is much more resilient against applications that flood the window manager with repeated events. * New module features: - FvwmForm supports separator lines. - New FvwmIconMan options: IconAndSelectButton IconAndSelectColorset * Bug fixes: - Provide a wrapper for the deprecation of XKeycodeToKeysym and use XkbKeycodeToKeysym() where appropriate. - fvwm-menu-desktop is re-written and provides better support of the XDG menu specification. - Fix fvwm-menu-desktop keyError bug. Use "others" if no desktop environment found. - FvwmIconMan had problems displaying the hilight colour on some systems (64 bit issue?). - Globally active windows cannot take the focus if the style forbids programs to take focus themselves (style !FPFocusByProgram). - Windows no longer jump from one position to the other which could happen in some cases with SnapAttraction. Windows now snap to the closest window (or screen edge). - Removing bindings had several strange side effects that are fixed now (removing too many bindings; old bindings showing up again after another is removed; possibly other effects). - Windows sometimes did not get expose events (i.e. did not redraw properly) if they were uncovered by moving a window above them. This has been fixed. - FvwmConsole now causes much less network traffic. - Suppress bogus events sent to the modules when a window is resized with the mouse. - Properly handle the has_ref_window_moved flag for ResizeMove and ResizeMoveMaximize. - Removed some unnecessary redraws in FvwmPager. - The option "NoDeskLimitY" option of the GotoPage command did not work. - Negative coordinates in the "rectangle" option to the Menu commend did not work correctly. This has been fixed. - Removes a slight graphics problem whith the ResizeMaximize command being invoked from a window button menu. - When an attempt to reparent a client window (i.e. decorate it) fails, fvwm no longer throws away all events but only the events for that window. - The ChangeButton command of FvwmButtons used to strip whitespace from the beginning and end of button titles and image paths. This is no longer done. ------------------------------------------------------------------- Changes in stable release 2.6.5 (20-Apr-2012) * New features: - FvwmPager now wraps window names if SmallFont is set. * Bug fixes: - Made signals registered with FVWM unblocking. - The "UnderMouse" option to PositionPlacement now honors the EWMH working area by default, if it's in use. - FvwmButtons handles the deleted window correctly for sub-windows. ------------------------------------------------------------------- Changes in stable release 2.6.4 (01-Feb-2012) * New features: - FvwmIconMan no longer allows for itself to be transient by using: Module FvwmIconMan Transient This is too ambiguous with valid module alias names, hence a transient FvwmIconMan must be created with "-Transient" as in: Module FvwmIconMan -Transient - New command InfoStore -- to store key/value pairs of information to relieve the burden of the SetEnv command. - Speed-up improvements for fvwm-menu-desktop when generating XDG menus by removing unnecessary stat(2) calls. - BusyCursor and CursorStyle have been set to make the cursor look like a dot during Read/PipeRead commands, by default. * Bug fixes: - FvwmRearrange now understands the "ewmhiwa" option when placing windows. - Client gravity for subwindows is honoured for reparenting windows, such as with XEmbed, when changing the parent's geometry. - Conditional command processing of !Layer n, as in: Next (Xteddy, !Layer 4) Echo cuddles has now been fixed. - Fixed handling of swallowed windows for transient FvwmButtons'. - fvwm-menu-desktop now looks in /usr/share/applications for KDE legacy mode. - fvwm-config no longer accepts "--is-stable", "--is-released", "--is-final". ------------------------------------------------------------------- Changes in stable release 2.6.3 (30-Sep-2011) * New features: - New Style commands: TitleFormat IconTitleFormat Used to specify a window's visible name. These new options deprecate the older styles: IndexedWindowName IndexedIconName ExactWindowName ExactIconName - New Resize argument to direction: "automatic" which works out, automatically, which direction a window should be resized in based on which quadrant the pointer is in on the window -- this is best observed by the grid formed from "ResizeOutline", as the shape of this grid is used when calculating this. Furthermore, the existing option of "warptoborder" can be used in conjunction with "direction automatic" to warp the pointer to the appropriate window edge. - Couple of changes to the Move command: - The EWMH working area is now honoured by default. - To move a window ignoring the working area, the option "ewmhiwa" can be used, similar to how the Maximize command works. - New expansion placeholder $[pointer.screen] to return the screen number the pointer is on. * Bug fixes: - A few minor ones; nothing user-visible per se. ------------------------------------------------------------------- Changes in stable release 2.6.2 (06-Aug-2011) * New features: - New MenuStyle "UniqueHotkeyActivatesImmediate" and its negation "!UniqueHotkeyActivatesImmediate" to retain the menu until the user presses one of the menu keybindings to enact that change in the case where there's only one item defined in the menu at the specified hotkey. * Bug fixes: - Fix infinite loop crash when FvwmButtons quits/restarts with RootTransparent colorsets. - Fix setting window states across FVWM restarts where those windows do not set WM_COMMAND. - Windows are now correctly restored when coming out of fullscreen mode. ------------------------------------------------------------------- Changes in stable release 2.6.1 (16-Apr-2011) * New features: None. * Bug fixes: - Make the version and check of Fribidi >= 0.19.2 - fvwm-menu-desktop: - Make XML::Parser check runtime as it's a non-standard module. - Fix perl version check. ------------------------------------------------------------------- Changes in stable release 2.6.0 (15-Apr-2011) * New features: - Support libpng 1.5.0's slightly newer API. * Bug fixes: - Fix width of FvwmTaskBar to fit on screen properly by using the correct module information to determine the border size. - Fix resizing shaded windows with a shade direction that does not match the window's gravity. Shaded windows might have jumped to strange positions when being resized by the application. - FvwmIconMan now accepts an optional module alias when running in transient mode. - Use of the NoUSPosition style is now properly reported by "BugOpts ExplainWindowPlacement on". - Fix the CursorMove command to no longer move the pointer beyond the boundary of a page, if EdgeScroll was set to disable page flipping. - Fix NeverFocus windows from taking focus when opening menus, etc. - Plus *MANY* other fixes, improvements, etc. ------------------------------------------------------------------- ------------------------------------------------------------------- Changes in beta release 2.5.31 (09-Aug-2010) * New features: * Bug fixes: - fvwm-convert-2.6: Don't double-up comma separated options to conditional commands if they're already delimited by commas. - Correctly report a window's height and width if the window has incomplete resize increment set. - Maintain any State hints on a window when used with WindowStyle. - FvwmIconMan now correctly handles sticky windows. ------------------------------------------------------------------- Changes in beta release 2.5.30 (09-May-2010) * New features: - Support libpng 1.4.0's slightly newer API. * Bug fixes: - Don't lazy match AnyContext when printing out bindings and the contexts they apply to with "PrintInfo Bindings". ------------------------------------------------------------------- Changes in beta release 2.5.29 (03-Apr-2010) * New features: - Added new fvwm-convert-2.6 script to convert older fvwm 2.4.x config files. - New BugOpts option QtDragnDropWorkaround to work around an oddity in handling drag-n-drop events to Qt applications. * Bug fixes: - Fixed the InitialMapCommand style from running when FVWM is restarting. - Fix rendering of FvwmForm windows when initially mapped. - Fix placement of windows when using MinoverlapPlacement and friends. - Fix segfault when tearing off menus using a Pixmap background. - Fix "window jump" bug when moving a window across page boundaries. - Flush property events for same type in applications which repeatedly set the same XAtom. (Gnucash, Openoffice, etc.) - Fix opening of files using Read/PipeRead to accept paths in the form "./" to indicate CWD. Fixes $ fvwm -f ./some-fvwm2rc - Fix further crash when copying menustyles with MenuFace involving pixmaps. - Make layer changes apply immediately via Style commands for any currently mapped windows. - Fix flickering/incorrect location of the GeometryWindow with Xinerama/TwinView when resizing windows. ------------------------------------------------------------------- Changes in beta release 2.5.28 (20-Sep-2009) * New features: - New differentiated options for SnapAttraction when snapping against screen edges: "None", "ScreenWindows", "ScreenIcons", "ScreenAll" - New option to the BugOpts command: TransliterateUtf8. * Bug fixes: - Fixed non-visible Qt windows after a Qt deferred map (e.g. Skype profile windows). - Fixed the use of the X-resource "fvwmstyle". - Fixed segmentation fault in FvwmEvent when parsing an undefined event name, or an undefined environment variable to the RPlayHost option. - Fixed the events startup, shutdown and unknown in FvwmEvent. - Fvwm now retains utf8 window names when the WM_NAME changes, and the utf8 name converted to the default charset match the old WM_NAME. - Fixed the options RPlayVolume and RPlayPriority in FvwmEvent. - Fixed SnapAttraction: Option SameType/Icons/Windows did falsely not affect conditions of option "Screen" and option "SameType" snapped falsely icons and windows together. - Fixed a problem where modules would get incorrect stacking information if many windows were restacked at the same time. - Fixed BugOpts parsing of more than one option at a time and restoring of default value for the last option in the command line when omitted. - 64 bit fix for setting EWMH _NET_WM_ICON property on windows. ------------------------------------------------------------------- Changes in beta release 2.5.27 (23-Feb-2009) * New features: - New extended variable $[w.visiblename] - Style matching now honours the window's visible name which means it can be matched before the real name, hence: Style $[w.visiblename] Colorset 5 is now honoured. Useful with IndexedWindowName as a style option. - New style InitialMapCommand allows to execute any command when a window is mapped first. - New option to PrintInfo, "bindings" which prints out all of the Key, PointerKey, Mouse and Stroke bindings which fvwm knows about. * Bug fixes: - Fixed compilation without XRender support. - Fixed handling of _NET_MOVERESIZE_WINDOWS requests. - Fixed a bug in automatic detection mode of the style MoveByProgramMethod. - Fixed png detection when cross compiling. - Fixed keeping fullscreen window mode over a restart. - The style PositionPlacement now honours StartsOnPage. - Reset signal handlers for executed modules and programs. - Try to handle a bug an old version of the EWMH spec by honouring both, the _NET_WM_STATE_MAXIMIZED_HORIZ hint and the _NET_WM_STATE_MAXIMIZED_HORZ hitn. - Fix the GNOME location prefix to application .desktop files. - 'PositionPlacement UnderMouse' now forces the window on-screen, just like the old UnderMousePlacement style option used to. ------------------------------------------------------------------- Changes in beta release 2.5.26 (7-May-2008) * New features: - New MenuStyle option VerticalMargins. * New module features: - FvwmButtons: New button alignment option: top. * Bug fixes: - Fixed crash in ARGB visual detection code. - Fixed compilation without XRender support. - Fixed drawing of background pictures in menu items and titles. - Fixed handling of shaped windows. - Fixed a 64-bit bug in the EWMH code. ------------------------------------------------------------------- Changes in beta release 2.5.25 (26-Feb-2008) * New features: - Handle the STATE_ADD command of the EWMH _NET_WM_STATE message from version 1.3 of the EWMH spec. - Support transparency in ARGB windows * Bug Fixes: - Fixed problem with windows disappearing when created unless the style Unmanaged was used. - Edge move delay was used as resistance for the top edge. - Fixed a parsing problem of the screen argument of the SnapAttraction style. - Some html documentation files were not installed. - Fixed a memory leak in internationalized font handling. - Fixed a bug in MinOverlap placement. - Fixed the StickyAcrossPages style in the FvwmPager. - Fixed the determination of the X charset on UTF-8 systems. - Fixed a crash when certain EWMH messages were sent to unmanaged windows. - Fixed a memory leak in multibyte codepage code. - Ignore the EWMH staysontop and staysonbottom hints if the EWMHIgnoreStackingOrderHints style is used. - Fixed a sporadic crash when the root background set by gnome, fvwm-root, esetroot etc. changes and a root transparent colour set is used. - Fixed spradic crash in modules with root transparent background from colour sets. - Fixed a possible crash if the last active module fails. ------------------------------------------------------------------- Changes in beta release 2.5.24 (24-Nov-2007) * New features: - Disabled paging during interactive resize operations by default (see 2.5.20) as it is annoying to many people. - New style command options: EdgeMoveResistance EdgeMoveDelay EdgeResizeDelay SnapGrid SnapAttraction that replace the now obsolete commands EdgeResistance, SnapGrid and SnapAttraction. The EdgeResistance command has a new syntax with only one argument. - New command MenuCloseAndExec for menu bindinngs that can be used to trigger certain commands from a menu without an associated item. For example, with Key F1 MTI[]-_ A MenuCloseAndExec Menu RootMenu the RootMenu can be opened from any other menu by pressing F1. * Bug Fixes: - Sometimes a window jumped by half the screen's size when moving with the mouse and hitting the border of the desktop. - Fixed the "screen w" argument of the Move and other commands. - Clicking on a menu title did not close the menu by default. - Temporary files in FvwmPerl overwrote each other. ------------------------------------------------------------------- Changes in beta release 2.5.23 (1-Sep-2007) * New features: - New Style command options: StartShaded * Bug Fixes: - Fixed FvwmButton's button placement algorithm broken in 2.5.22. ------------------------------------------------------------------- Changes in beta release 2.5.22 (29-Aug-2007) * New features: - New Style command options: UnderMousePlacementHonorsStartsOnPage UnderMousePlacementIgnoresStartsOnPage !MinOverlapPlacementPenalties !MinOverlapPercentPlacementPenalties MinWindowSize - SVG (scalable vector graphics) image loading support. - New extended variables $[w.iconfile.svgopts] $[w.miniiconfile.svgopts]. - Added suffix 'w' to the arguments of the Move command and similar. It is now possible to add multiple shifts to a window position, e.g. "50-50w 50-50w" for the center of the screen. - Removed UnderMousePlacement and CenterPlacement. Use "PositionPlacement Center" and "PositionPlacement UnderMouse" instead. - Documentation in HTML format. - Replaced "UseListSkip" with "UseSkipList" & "OnlyListSkip" with "OnlySkipList" in WindowList command. (Old options deprecated.) - New subject ImageCache for PrintInfo command. - The new commad EchoFuncDefinition prints a function's definition to the console for debugging purposes. - The CursorStyle command can now load PNG and SVG images as mouse cursors. New x and y arguments to specify the hot spot. Also, it is now possible to load non-monochrome cursors and cursors with partial transparency. * New module features: - FvwmScript: New instructions: ChangeWindowTitle and ChangeWindowTitleFromArg. * Bug Fixes: - Windows with aspect ratio no longer maximize past the screen edges. - Fixed CenterPlacement with Xinerama screens. - Fixed CascadePlacement with title direction west and east - Windows no longer unstick when going to fullscreen mode. - Fixed crash when raising/lowering a destroyed window. - Fixed expansion of $[n-] and $[*], broken in 2.5.20. - Fixes for resizing shaded windows and windows with a gravity other than northwest. - Fixed CursorStyle POSITION, broken since 2.3.24. - The hi, sh and fgsh colors in colorsets are no longer replaced by computed values if not explicit set on the same line as the bg, or for fgsh fg, changes. (bug #3359) - FvwmButtons now redraws stretched button backgrounds correctly on partial expose. - Windows with circular transient for hints may no longer crash fvwm with StackTransientParent style. - FvwmPager now displays windows that are StickyAcrossPages correctly. - Fixed a possible crash with modules closing down. - Fixed broken demo script fvwm_make_browse_menu.sh. - The conditon following a comma separator without whitespace padding was previously ignored if the presiding condition was multi-worded. - Various FvwmButtons drawing problems. - Window movement or resizing triggered by an EWMH message now honours the FixedSize and FixedPosition window styles. - Properly generate leave_window and enter_window events for the root window in FvwmEvent. - Fixed crash in UTF8 code. - Fixed parsing of the PropertyChange command. - Fixed windowlist crash when combining CurrentAtEnd with IconifiedAtEnd and all windows are iconified. ------------------------------------------------------------------- Changes in beta release 2.5.21 (20-Jan-2007) * New features: - The command Scroll can now be used for interactive scrolling. * Bug Fixes: - Fixed Tile...Placement styles (SmartPlacement) that were broken in 2.5.20. ------------------------------------------------------------------- Changes in beta release 2.5.20 (15-Jan-2007) * New features: - New Style options: StippledIconTitle, !StickyStippledTitle, and !StickyStippledIconTitle. - Full support for menu context (M) key and mouse bindings. See the section Menu Bindings in the man page for details. - Hilighted menu backgrounds now use pixmaps gradients and transparency from their related colorset. - New window conditions: StickyIcon, StickyAcrossPagesIcon and StickyAcrossDesksIcon. * Changed features: - "Mouse n M N" is no longer used to disable or remap the builtin tear off menu button. See the section Tear Off Menus for details on replacement commands. * Bug Fixes: - FvwmWinList: fix problem with window name/button mixups during Init/Restart of fvwm. (bug #1393) - It is now possible to switch the viewport while resizing windows if "EdgeScroll 0 0" is set. - Fixed disappearing windows when aborting interactive resizing of maximized windows when unmaximizing them later. - Fixed disappearing windows when moving maximized windows and unmaximizing them later. - Fixed calculation of final location with MoveToPage and MoveToScreen with windows to the left or top of the viewport. - 64-bit architecture fix in FvwmProxy. - FvwmForm now work with balanced quoted command for Timeout. - FvwmPager correctly updates on window desk change. - FvwmIconBox: fixed problem with IconColorset's background color change not being applied immediately. - Allow FvwmConsole to run a terminal via rxvtc or urxvtc. FvwmConsole dies if no client connects within one minute. - Expansion of variables in FvwmTaskBar launch button commands fixed. - Fixed a race condition with applications raising their own transient windows in certain ways. (Apple Shake, kphotoalbum) - FvwmIdent reports the correct geometry if the window has its title at the left or right side. - Fixed an infinite loop when deiconifying windows in a group via a different window than the initially iconified. ------------------------------------------------------------------- Changes in beta release 2.5.19 (9-Dec-2006) * Bug Fixes: - FvwmCommand now reports "end windowlist" and "end configinfo". - FvwmCommand now prints config info split on lines. - FvwmTaskBar no longer gets lost with trailing whitespace after geometry specification. - Fixed a window size problem if the aspect ratio is set (e.g. mplayer). - Decorations now update when unmanaged windows take focus, and not FlickeringQtDialogsWorkaround is enabled. - FvwmPager again allows movement of windows added before a page change. - fvwm no longer crashes on 1 and 4 bit displays. (#1677) - EWMH desktops now correctly handles FPClickToFocus. (#1492) - Security fix in fvwm-menu-directory. (CVE-2006-5969) ------------------------------------------------------------------- Changes in beta release 2.5.18 (11-Sep-2006) * Bug Fixes: - If a window started fullscreen, leaving fullscreen state now properly unmaximizes and resizes the window. - Fixed the ForeColor/HilightFore styles that were broken in 2.5.17. - FvwmPager can now move icons with the !IconTitle style. - Fixed drawing of icons that are moved to a different desk. - FvwmPager no longer tries to move non-movable windows. - FvwmPager now moves all windows as user requests. - FvwmPager no longer displaces windows with title and border sizes on moves. - TestRc now correctly matches Break, and $[cond.rc] is expanded for Break. - Fixed several 64-bit architecture problems with XGetWindowProperty(). Xine works much better on 64-bit machines. - Fixed handling of ClickToFocusPassesClick with the EWMH desktop (e.g. using nautilus). - Fixed handling of windows that are unmapped and mapped again too fast (e.g. fpga_editor). ------------------------------------------------------------------- Changes in beta release 2.5.17 (19-Jul-2006) * New features: - New MenuStyle options TitleFont, TitleColorset and HilightTitleBack. - New command PressButton in module FvwmButtons for being able to emulate button press via other means than the mouse. - New wrap options to EdgeScroll command for wrapping with pixel distances. - New Style option UnderMousePlacement. - Unused arguments to Style options generate warnings. - The name style names match against can be augmented by the X-resource "fvwmstyle". - New options, Reverse and UseStack, to All command. - WindowShade can now reshade windows using the Last direction. - Positional parameters to complex functions can now be expanded using $[n], $[n-m], $[n-] and $[*] expressions. - The width and height arguments of the Resize command now accept the prefix 'w' to allow resizing relative to the current window size. - New command ModuleListenOnly. - New "Periodic" option added to Schedule command. * Bug Fixes: - Fixed detection of running non-ICCCM2 wm (bug #3151). - Fixed drawing of menus with the sidepic on the right. - EdgeScroll no longer divides pixel distances >1000 by 1000. (bug #3162) - The configure script can now cope with four-part version numbers when detecting some libraries. - The WarpToWindow command followed by Move in a complex function now uses the correct pointer position. - The menu style TitleWarp does no longer warp the pointer for root menus (as it is documented). - Fixed detection of safe system version of mkstemp. - Fixed the conditions Iconifiable, Fixed, FixedSize, Maximizable and Closable. - Fixed problem with window outline and placement position running out of sync. - FvwmConsole no longer conflicts with Cygwin stdio (bug #3772). - FvwmGtk now configures correctly on Cygwin (bug #3772). - Fixed tempfile vulnerabilities in FvwmCommand. ------------------------------------------------------------------- Changes in beta release 2.5.16 (20-Jan-2006) * New features: - If the pointer can not be grabbed in functions, a message is printed to the console instead of beeping. * Bug Fixes: - Fixed a couple of build problems introduced in 2.5.15. ------------------------------------------------------------------- Changes in beta release 2.5.15 (14-Jan-2006) * New features: - Variables can be nested, like $[desk.name$[desk.n]]. - Obsolete one-letter variables work, but generate warnings now. - Windows can be placed by any button (now also >3). - It is now possible to redefine the buttons usable to finish window movement and manual placement. - New window condition PlacedByButton. - MenuStyle pairs can be negated by prefixing '!'. - New generic tabbing module - FvwmTabs. - New Style option: EWMHIgnoreWindowType. - New MenuStyle options: MouseWheel, ScrollOffPage and TrianglesUseFore. - To compile from CVS, autoconf-2.53 or above is now required. This does not affect compiling the released tarballs. - New option "screen" to Move and ResizeMove commands to allow specifying the target Xinerama screen. * Bug Fixes: - Supported a new fribidi version 0.10.5 in addition to 0.10.4. - Better look for windows with "BorderStyle TiledPixmap". - Some EWMH-related 64-bit fixes. - Fixed segmentation fault when replacing title of title only menus (Bug #1121). - Fixes for resizing of shaded windows and resizing/moving windows with complex functions. ------------------------------------------------------------------- Changes in beta release 2.5.14 (24-Aug-2005) * New features: - Fvwm now officially supports 64-bit architectures. - New Test conditions EnvIsSet, EnvMatch, EdgeHasPointer and EdgeIsActive. - New window condition FixedPosition. * New module features: - FvwmPerl module supports window context when preprocessing. - FvwmPerl module accepts new --export option that by default defines two fvwm functions "Eval" and ".", to be used like: FvwmPerl -x Eval $a = $[desk.n] - 2; cmd("GotoDesk 0 $a") if $a >= 0 . Exec xmessage %{2 + cos(0)}% # embedded calculator - New FvwmProxy option ProxyIconified. - New FvwmTaskBar option Pad to control the gap between buttons. * Bug Fixes: - Fixed a Solaris compiler error introduced in 2.5.13. - Fixed a hang with layers set by applications (e.g. AbiWord). - GotoDesk with a relative page argument now wraps around at the end of the given range as documented. (Bug #1396). - PopupDelayed menu style option was not copied on CopyMenuStyle. - Transparent Animated menus with non-transparent popup were not animated correctly. - Supported euc-jp class of encodings. - A window's default layer is no longer set to 0 during a restart. - Fixed an annoying MouseFocus/SloppyFocus problem in conjunction with EdgeResistance + EdgeScroll (sometimes a window did not get the focus as it should have). This problem first occured in 2.5.11. ------------------------------------------------------------------- Changes in beta release 2.5.13 (16-Jul-2005) * Bug Fixes: - The MoveToPage command did not work without arguments in 2.5.11 and 2.5.12. - Mouse/Key command no args possible core dump. - Direction with no args possible core dump. - FvwmScript periodic tasks run too often. - Perl modules did not work on 64 machines. - FvwmDebug did not report any extended messages. - fvwm-menu-desktop supports mandriva. - fvwm-menu-desktop when verifying executable, allow full path. * New module features: - FvwmIconMan: MaxButtonWidth and MaxButtonWidthByColumns options. - FvwmIconMan: added tool tips with Tips, TipsDelays, TipsFont, TipsColorset, TipsFormat, TipsBorderWidth, TipsPlacement, TipsJustification and TipsOffsets options. - FvwmButtons: PressColorset & ActiveColorset options for _individual_ buttons. ------------------------------------------------------------------- Changes in alpha release 2.5.12 (6-Oct-2004) * New commands: - EdgeLeaveCommand * New module features: - FvwmIconMan: ShowOnlyFocused option. ------------------------------------------------------------------- Changes in alpha release 2.5.11 (30-Sep-2004) * Multiple window names can be specified in conditions. * Window-specific key/mouse bindings. (Bindings no longer have to be global.) * The default fvwm configuration files are now: ~/.fvwm/config and $FVWM_DATADIR/config. Five previously used config file locations are still searched as usual for backward compatibility. * New extended variables $[w.desk] and $[w.layer]. * New options GrowOnWindowLayer and GrowOnlayers to the Maximize command. * New Style option "State". * New Style option "CenterPlacement". * New option to FvwmIconMan: ShowNoIcons. * New WindowList tracker and other enhancements in Perl library. * New option to fvwm-menu-directory: --func-name. * Improved FvwmWindowMenu module. * Fluxbox-like Alt-Button3 resizing with the new Resize options Direction, WarpToBorder and FixedDirection * Enhanced "Test (Version >= x.y.z)" option to allow version comparisons. * New FvwmButtons options: ActiveColorset, ActiveIcon, ActiveTitle, PressColorset, PressIcon and PressTitle. * New FvwmButtons swallow option: SwallowNew. * The option CurrentGlobalPageAnyDesk was accidentally named CurrentGlobbalPageAnyDesk before. * New conditions AnyScreen and Overlapped. * The Read and PipeRead commands return 1 if the file or command could be read or executed and -1 otherwise. * New menu option TearOffImmediately. * Added support for Solaris' Xinerama. * New option MailDir in FvwmTaskBar. * MoveToPage command: New options wrapx, wrapy, nodesklimitx and nodesklimity. New suffix 'w' to allow for window relative movement. ------------------------------------------------------------------- Changes in alpha release 2.5.10 (19-Mar-2004) * New command FakeKeyPress. * New BugOpts option ExplainWindowPlacement. * Adjustable button reliefs in FvwmIconMan (option ReliefThickness). * Security patch in fvwm-bug. See http://securitytracker.com/alerts/2004/Jan/1008781.html * Security fixes in: fvwm-menu-directory (BugTraq id 9161) fvwm_make_directory_menu.sh fvwm_make_browse_menu.sh ------------------------------------------------------------------- Changes in alpha release 2.5.9 (2-Mar-2004) * New MenuStyle options PopupIgnore and PopupClose. * New configure option --disable-iconv to disable iconv support. * New extended variables $[w.iconfile] and $[w.miniiconfile]. * New Style option Unmanaged. Such windows are not managed by fvwm. * New binding context 'U' for unmanaged windows, similar to 'R'oot. * New option DisplayNewWindowNames to the BugOpts command. * Security fix for fvwm-menu-directory. See BugTraq id 9161. ------------------------------------------------------------------- Changes in development release 2.5.8 (31-Oct-2003) * New prefix command KeepRc. * Renamed the Cond command to TestRc, and the On command to Test. Removed the CondCase command. Use "KeepRc TestRc" instead. * The Break command can be told the number of nested function levels to break out of. Break now has a return code of -2 ("Break"). * Directions can be abbreviated with -, _, [, ], <, >, v or ^ like in key or mouse bindings. * New extended variable $[func.context]. * New Style option MoveByProgramMethod. Tries to autodetect whether application windows are moved honouring the ICCCM or not (default). The method can be overridden manually if the detection does not work. * fvwm supports tear off menus. See the "Tear Off Menus" section in the man page or press Backspace on any menu to try them out. * fvwm now handles what Unicode calls "combining characters" (i.e. marks drawn on top of other characters). * New commands WindowStyle and DestroyWindowStyle for individual (per window) styles. * The conditions !Current... and !Layer now work as expected. * Added a nice autohide script to the FAQ. * FvwmAnimate now supports dynamical commands "pause", "play", "push", "pop" and "reset" to manipulate the playing state. ------------------------------------------------------------------- Changes in development release 2.5.7 (30-May-2003) * The commands Cond and CondCase now support checking for inequality by prefixing the return code with '!'. * Schedule and Deschedule support hexadecimal and octal command ids. * In FvwmIconMan, windows can move from one manager to another according to the managers' Resolution options. * In order to fix a problem with StartsOnScreen and applications that set a user specified position hint, the StartsOnScreen style no longer works for the following modules: FvwmBanner, FvwmButtons, FvwmDragWell, FvwmIconBox, FvwmIconMan, FvwmIdent, FvwmPager, FvwmScroll, FvwmTaskBar, FvwmWharf, FvwmWinList. Use the '@' bit in the module geometry specification where applicable. * Documented variable $[gt.any_string] and LocalePath command (new in 2.5.5). * Added gettext support to FvwmScript. New head instruction UseGettext and WindowLocaleTitle. New widget instruction LocaleTitle. New instruction ChangeLocaleTitle and new function Gettext. * WindowListFunc is executed now within a window context, so a prefix "WindowId $0" is not needed in its definition anymore, and it is advised to remove it in user configs. * FvwmEvent now executes all window related events within a window context, so PassId is not needed anymore, and all prefixes "WindowId $0" may be removed in user event handlers. * New FvwmTaskBar option NoDefaultStartButton. ------------------------------------------------------------------- Changes in development release 2.5.6 (28-Feb-2003) * Fix button 3 drag in FvwmPager so that drag follows the mouse. * Fix for gmplayer launched by fvwm. Close stdin on Exec so the exec'd process knows it's not running interactively. * Improvement in MultiPixmap. In particular Colorset and Solid color can be specified. * New ButtonStyle and TitleStyle style options AdjustedPixmap, StretchedPixmap and ShrunkPixmap. * Use the MIT Shared Memory Extension for XImage. * The TitleStyle decor of a vertical window Title is rotated. This is controllable using a new style option: !UseTitleDecorRotation / UseTitleDecorRotation * New style options IconBackgroundColorset, IconTitleColorset, HilightIconTitleColorset, IconTitleRelief, IconBackgroundRelief and IconBackgroundPadding. * Minor incompatible improvements to the Perl library API. * Renamed FvwmWindowLister to FvwmWindowMenu. * New option to IconSize style: Adjusted, Stretched, Shrunk. * New shortcuts for button states: AllActiveUp, AllActiveDown, AllInactiveUp, AllInactiveDown. * New Style options: Closable, Iconifiable, Maximizable, AllowMaximizeFixedSize * New conditions for matching windows: Closable, Iconifiable, Maximizable, FixedSize and HasHandles * New conditional command On for non-window related conditions. * Removed --disable-gnome-hints and --disable-ewmh configure options. * All single letter variables are deprecated now; new variables: $[w.id], $[w.name], $[w.iconname], $[w.class], $[w.resource], $[desk.n], $[version.num], $[version.info], $[version.line], $[desk.pagesx], $[desk.pagesy] ------------------------------------------------------------------- Changes in development release 2.5.5 (2-Dec-2002) * Added support for joining and shaping in bi-directional languages that need this. * ButtonStyle and TitleStyle new style type Colorset. * New experimental module FvwmProxy. * New command RestackTransients. * Added a pixel offset to vector button definitions. * New command FocusStyle as a shorthand for setting the FP... styles with the Style command. * New option Locale to PrintInfo command. * The Next and Prev commands start looking for a matching window at the context window if there is any. * The MoveToPage command does nothing with sticky windows. * New module FvwmWindowLister, a WindowList substitute. * Sticky windows can be sticky across pages, across desks or both. Related to this are: - New commands StickAcrossPages and StickAcrossDesks. - New Style options StickyAcrossPages and StickyAcrossDesks. - New conditional command options StickyAcrossPages and StickyAcrossDesks. - New WindowList options NoStickyAcrossPages, NoStickyAcrossDesks, StickyAcrossPages, StickyAcrossDesks, OnlyStickyAcrossPages, OnlyStickyAcrossDesks. - New FvwmRearrange options -sp and -sd. * Fixed flickering in FvwmTaskBar, FvwmWinList, FvwmIconBox, FvwmForm, FvwmScript and FvwmScroll when xft fonts or icons with an alpha channel are used. * New Colorset option RootTransparent * The Transparent Colorset option can be tinted under certain conditions * New MinHeight option to TitleStyle * Added gettext support. New command LocalePath and new variable $[gt.string] ------------------------------------------------------------------- Changes in alpha release 2.5.4 (20-Oct-2002) * FvwmTaskBar may now include mini launch buttons using the Button command. Also has new options for spacing the buttons: WindowButtonsLeftMargin, WindowButtonsRightMargin, and StartButtonRightMargin. See man page for details. * Style switches can be prefixed with '!' to inverse their meaning. For example, "Style * Sticky" is the same as "Style * !Slippery". This works *only* for pairs of styles that take no arguments and for the Button and NoButton styles. * New button property Id in FvwmButtons. FvwmButtons now accepts dynamical actions using SendToModule, see the man page: ChangeButton ExpandButtonVars * New Colorset options bgTint, fgTint (which complete Tint), Alpha, IconTint and IconAlpha. * Alpha blending rendering is supported even without XRender support. * Enhanced commands [Add]ButtonStyle, [Add]TitleStyle. ButtonState. Titles and buttons now have 4 main states instead of 3: ActiveUp, ActiveDown, InactiveUp and InactiveDown, plus 4 Toggled variants. Several shortcuts added: Active means ActiveUp + ActiveDown, Inactive means InactiveUp + InactiveDown, similarly for shortcuts ToggledActive and ToggledInactive. * More shortcuts for button states added: AllNormal, AllToggled, AllActive, AllInactive, AllUp, AllDown. These six shortcuts are actually different masks for 4 individual states (from 8 total). * FPClickToFocus and FPClickToRaise work with any modifier by default. * Perl library API regarding event handlers is changed, so personal modules in Perl should be adjusted. * Allow the use of mouse buttons other than the first in FvwmWinList when invoked transient. * ImagePath now supports directories in form "/some/directory;.png" (where semicolon delimits a file extension that files in /some/directory have. This file extension replaces the original image extension (if any) or it is added if there is no extension. For example with: Style XTerm MiniIcon mini/xterm.xpm the file /some/directory/mini/xterm.png is searched. * New graphical debugger module FvwmGtkDebug. * New command NoWindow for removing the window context. * New FvwmIconMan option ShowTransient. * All conditions have a negation. * New FvwmBacker option RetainPixmap. * Fixed flickering in menus, icon title, FvwmButtons, FvwmIconMan and FvwmPager when xft fonts or icons with an alpha channel is used. * FvwmButtons redrawing improvement: colorsets are now usable with containers. * FvwmIconMan options PlainColorset, IconColorset, FocusColorset and SelectColorset are now strictly respected. * The HilightBack and ActiveFore menu styles are independent of each other. HilightBack without using ActiveFore does no longer hilight the item text. * New WindowList option SortByResource; the previously added SortClassName option is renamed to SortByClass. * New command PrintInfo for debugging. ------------------------------------------------------------------- Changes in alpha release 2.5.3 (25-Aug-2002) * TitleStyle MultiPixmap now works once again. * Removed the old module interface for ConfigureWindow packets. External modules relying on this interface no longer work. * Fixed interaction bug between CascadePlacement and StartsOnPage: if the target page was at a negative x or y page displacement from the current viewport, the window would be placed on the wrong page. * New Style option IconSize for restricting icon sizes. * New WindowList options SortClassName, MaxLabelWidth, NoLayer, ShowScreen, ShowPage, ShowPageX and ShowPageY. * Restored old way of handling clicks in windows with ClickToFocus and ClickToFocusPassesClickOff. This fixes a problem with click+drag in an unfocused rxvt or aterm window. * Fixed wrong warp coordinates when WarpToWindow was used with two arguments on an unmanaged window. * Vastly improved FvwmEvent performance. * FvwmAuto can operate on Enter and Leave events too. This makes it possible to have auto raising with ClickToFocus and NeverFocus. See -menter and -menterleave options and examples in the FvwmAuto man page. * The "hangon" strings in FvwmButtons support wild cards. * New option "Icon" to PlaceAgain command. * New option "FromPointer" and direction "Center" to the Direction command. * The styles ClickToFocusRaises(Off) and MouseFocusClickRaises(Off) are now different names for the same style. Configurations that used Style * ClickToFocus, ClickToFocusRaises Style * MouseFocusClickRaisesOff or vice versa no longer work as like before. Remove the second line to fix the problem. ClickToFocusRaises now works only on the client part of a window, not on the decorations as it did before. * New color limit method for screens that only display 256 colors (or less). * In depth less or equal to 16 image and gradient can be dithered. This can be enabled/disabled by using the new dither/nodither options to the Colorset command. * Removed the styles MouseFocusClickIgnoreMotion and MouseFocusClickIgnoreMotionOff again. * Many new focus policy styles "FP..." and "!FP...". ------------------------------------------------------------------- Changes in alpha release 2.5.2 (24-Jun-2002) * Fonts can have shadow effects, see the FONT SHADOW EFFECTS section of fvwm manual page. * New Colorset options: fgsh for shadow text and fg_alpha for merging text with the background. * New module FvwmPerl adds perl scripting ability to fvwm commands. * Provided powerful perl library for creating fvwm modules in perl. * New WindowList option IconifiedtAtEnd. * Always display the current desk number in the FvwmPager window title. * Allow to bind a function to the focus click and pass it to the application at the same time. * New styles !Borders and Borders to enable or disable window borders. * Removed the --enable-multibyte configure option. Multibyte support is now compiled in unconditionally. * New FvwmButtons option ActionOnPress enables execution of action on press rather than on release for any specific button. * Improved CascadePlacement, the last used position is reused if the last placed window does not exist any more. * FvwmIconMan may now change the resolution dynamically, just issue "*FvwmIconMan: resolution page" while FvwmIconMan is running. * New command XineramaSlsScreens. * MoveToPage and MoveToDesk no longer unstick windows. * It is possible to specify a string encoding in a font name, see the "FONT AND STRING ENCODINGS" section of fvwm manual page. ------------------------------------------------------------------- Changes in alpha release 2.5.1 (26-Apr-2002) * Changed the executable and the man page names from fvwm2 to fvwm. The old names are still supported by symlinking. * All fvwm utilities are renamed to conform to the "fvwm-" scheme. fvwm-bug, fvwm-root (was xpmroot), fvwm-config, fvwm-convert-2.4. * Added a full support for the side window titles. New Style options TitleAtLeft and TitleAtRight added to TitleAtTop and TitleAtBottom. * A title text may now be optionally rotated for both vertical and horizontal title directions, search for "Rotated" in the man page. * Added support for loading images in PNG (including alpha blending) and XBM formats anywhere. * New commands Schedule and Deschedule. * New command State. New conditions State and !State. * New commands XSync and XSynchronize for debugging purposes. * In interactive move/placement when Alt/Meta modifier is pressed, snap attraction (SnapAttraction, SnapGrid and EdgeResistance) is ignored. * New flags (No)FvwmModule to FvwmButtons Swallow option * The I18N_MB patch (--enable-multibyte) has been rewritten. MULTIBYTE is used to identify what is was I18N_MB. A set of locale functions (locale initialization, font loading, text drawing, ...etc.) is created in libs/Flocale.{c,h} and used in the entire fvwm code (but FvwmWharf). Font loading and memory management is improved in the multibyte case. * Better support of non ISO-8859-1 window and icon titles. See the --disable-compound-text option in INSTALL.fvwm for more details. * Added anti-aliased text rendering support using Xft (use --enable-xft to enable it). Recent versions of XFree and freetype2 are needed (see the FONT NAMES AND FONT LOADING section of the fvwm manual page). * Conditional commands now have a return code (Match, NoMatch or Error). This return code can be checked and tied to an action with the new commands Cond and CondCase. * Bindings can be made to the separate parts of the window border with the new contexts '[', ']', '-', '_', '<', '^', '>' and 'v'. * New parameters for FvwmRearange: -maximize and -animate. * New option StartCommand for FvwmTaskBar to allow placing the StartMenu correctly. *FvwmTaskBar: StartCommand Popup RootMenu \ rectangle $widthx$height+$left+$top 0 -100m Please refer to the FvwmTaskBar man page for details. * New extended variables pointer.x, pointer.y, pointer.wx, pointer.wy, pointer.cx and pointer.cy. * The Current command does not select a random window when no window has the focus. * New color '@4' (transparent) in button vectors. * New option "Frame" for the Resize and ResizeMove commands. * Added direction options to WindowShade command. Windows can be shaded in any of the eight compass directions. * Styles WindowShadeLazy (default), WindowShadeBusy and WindowShadeAlwaysLazy to optimize performance of the WindowShade command. * The DO_START_ICONIC flag is no longer supported in the module interface. * Added bi-directional text support for Asian charsets. * New option MinimalLayer for FvwmIdent to control window layer. * New FvwmIconMan configuration syntax now conforms to the syntax of other modules, see the man page. * FvwmForm can automatically run commands after a timeout interval. * Fvwm commands can be invoked when the edge of the screen is hit with the mouse. * New commands Colorset, ReadWriteColors and CleanupColorsets allow the colorset functionality previously available using FvwmTheme. * FvwmTheme is obsolete now, but still supported for some time. * New options Tint, TintMask and NoTint to colorsets. * New WindowList option CurrentAtEnd. * New weighted sorting in FvwmIconMan. * New conditional command ThisWindow. ------------------------------------------------------------------- Changes in alpha release 2.5.0 (27-Jan-2002) * New commands ResizeMaximize and ResizeMoveMaximize that modify the maximized geometry of windows and maximize them as necessary. Very useful to make a window larger manually and then get back the old geometry with a click. * New command ResizeMoveMaximize similarly. * New styles FixedPPosition, FixedUSPosition, FixedSize, FixedUSSize, FixedPSize, VariablePPosition, VariableUSPosition, VariableSize, VariableUSSize, and VariablePSize. * Actions can be bound to windows swallowed in FvwmButtons. To disable this feature for a specific button, the new option ActionIgnoresClientWindow can be used. * Fvwm respect the extended window manager hints specification. This allows fvwm to work with KDE version >= 2 and GNOME version 2. This support is configurable using a bunch of new commands and style options, search for "EWMH" in the man page. * New DateFormat option in FvwmTaskBar to change the date format in the clock's popup tip. * Window titlebars may now be designed using a new powerful TitleStyle option MultiPixmap, that enables to specify separate pixmaps for different parts of the titlebar: Main, LeftEnd, LeftOfText, UnderText, RightOfText, RightEnd and more. * New styles MinOverlapPlacementPenalties and MinOverlapPercentPlacementPenalties. * New styles IndexedWindowName / ExactWindowName and IndexedIconName / ExactIconName. * New command "DesktopName desk name" to define the name of a desktop for the FvwmPager, the WindowList and EWMH compliant pagers. New expanding variables $[desk.name] for the desktop names. * New window list options NoDeskNum, NoCurrentDeskTitle, TitleForAllDesks, NoNumInDeskTitle. * New emacs style bindings in menus. * New Maximize global flag "layer" which causes the various grow methods to ignore the windows with a layer less than or equal to the layer on the window which is maximized. * Better support of the Transparent colorset in the modules and in animated menus. * Amelioration of the WindowShade animation. * New ButtonStyle and TitleStyle option MwmDecorLayer. * New style BackingStoreWindowDefault which is the default now. Fvwm no longer disables backing store on windows by default. * New styles MouseFocusClickIgnoreMotion and MouseFocusClickIgnoreMotionOff. * The module interface now supports up to 62 message types. * New module messages MX_ENTER_WINDOW and MX_LEAVE_WINDOW. * New events "enter_window" and "leave_window" in FvwmEvent. * New MenuStyle PopupActiveArea. * New command line option -passid to FvwmAuto. * New conditional commands Any and PointerWindow. * New conditions Focused, !Focused, HasPointer and !HasPointer. * New commands EWMHBaseStruts and EWMHNumberOfDesktops. ------------------------------------------------------------------- Changes in stable release 2.4.20 (6-Dec-2006) * The configure script now correctly appends executable file extensions to conditionally built binaries. Fixes building on Cygwin. * FvwmConsole no longer conflicts with getline of Cygwin's stdio. * Fixed parsing of For loops in FvwmScript. * Fixed a possible endless loop when de-iconifying a transient window. * Reject some invalid GNOME hints. * Fixed a loop when xterm changes its "active icon" size. * The configure script can now cope with four-part version numbers when detecting some libraries. * Security fixes in fvwm-menu-directory. (CVE-2006-5969) FvwmCommand ------------------------------------------------------------------- Changes in stable release 2.4.19 (30-Sep-2004) * Fixed BackingStore style option. * Fixed MoveToDesk commend with a single argument. * Allow whitespace in menu names. * Fixed a hang when restarting FvwmCommand or FvwmConsole. * A double click no longer occurs when two different mouse buttons are pressed. * Fixed a relief drawing problem in FvwmWinList. * Fixed travelling windows on restart if a window used non NorthWest gravity and changed that before the restart. * Fixed installation of FvwmGtk.1 for debian (with DESTDIR set). * The clock in FvwmTaskBar is redrawn immediately when its colour changes. * The option CurrentGlobalPageAnyDesk was accidentally named CurrentGlobbalPageAnyDesk before. * Fixed a problem with fvwm startup and shutdown when the pointer was grabbed by another application. * Fixed parsing of the Pointer option to the Move command. * Fixed handling of MWM hints on 64 bit machines. ------------------------------------------------------------------- Changes in stable release 2.4.18 (19-Mar-2004) * Corrected rebooting the machine in FvwmScript-Quit. * Fixed the FlickeringMoveWorkaround option to the BugOpts command. * Security patch in fvwmbug.sh. See http://securitytracker.com/alerts/2004/Jan/1008781.html * Security fixes in fvwm-menu-directory (BugTraq id 9161) fvwm_make_directory_menu.sh fvwm_make_browse_menu.sh ------------------------------------------------------------------- Changes in stable release 2.4.17 (10-Oct-2003) * Fixed error message for incorrect --with-SOME-library argument. * It is now possible to suppress title action or title completely in menus created by fvwm-menu-directory. * Fixed a compile problem on QNX 4.25. * New configure switch --disable-gtk. * FvwmGtk.1 is not installed if FvwmGtk is not built. * The "Visible" condition does no longer select windows on different desks. * With the styles StartsOnPage, SkipMapping and UsePPosition, windows that request a specific position are still placed on the given page. * Fixed sending M_NEW_PAGE packets to the modules if the page did not change. * Added support for new BBC headlines in fvwm-menu-headlines, this replaces the old BBC-Worlds and BBC-SciTech headlines. ------------------------------------------------------------------- Changes in stable release 2.4.16 (30-May-2003) * Fixed a transparency problem in FvwmButtons. * The PageOnly option in FvwmTaskBar now works after a desk change too. * Fixed a possible core dump when more than 256 windows are on the desktop. * Initial drawing and final undrawing of wire frame no longer toggles the pixel in the top left corner of the screen. * Fixed parsing of button geometries in FvwmButtons when the geometry specification appeared after another option with a comma at the end. * FvwmCommand works too when invoked without the DISPLAY variable set. * Fixed displaying iconified windows without an icon in FvwmIconMan. * All single letter variables are deprecated now; new variables: $[w.id], $[w.name], $[w.iconname], $[w.class], $[w.resource], $[desk.n], $[version.num], $[version.info], $[version.line], $[desk.pagesx], $[desk.pagesy] * Fixed a bug with aspect pixmaps in colorsets. * Iconified windows without an icon do not receive focus. * Fixed a bug in FvwmPager that displayed iconified windows without icon title or picture as not iconified. * Fixed parsing of '@' Xinerama specification in the ButtonGeometry option of FvwmButtons. * The NoWarp menu position hint option works with root menus too. * Fixed a problem with styles not being properly applied after a DestroyStyle command. * Fixed a bug introduced in 2.4.14. The pointer was sometimes warped to another screen during a restart and command execution. * Fixed a crash when a window was destroyed twice in a complex function. * Fixed corruption of the window list when windows died at the wrong time. * Fixed problem with empty frame windows if X recycled the window id of a window that died recently. * Fixed loading of application supplied pixmap on 8/24 depth screen. * WindowListFunc is executed now within a window context, so a prefix "WindowId $0" is not needed in its definition anymore and it is advised to remove it in user configs. * FvwmEvent now executes all window related events within a window context, so PassId is not needed anymore, and all prefixes "WindowId $0" may be removed in user event handlers. * Fixed "GotoDeskAndPage prev" on desks larger than 2x2. * Expansion of variables like $[w.name] or $[EMPTY_STRING] that are empty works. ------------------------------------------------------------------- Changes in stable release 2.4.15 (24-Jan-2003) * Fix for gmplayer launched by fvwm. Close stdin on Exec so the exec'd process knows its not running interactively. * Windows using the WindowListSkip style do not appear in the FvwmTaskBar at random. * Fixed a memory leak in ChangeIcon, ChangeForeColor and ChangeBackColor FvwmScript Instruction. * Fixed a core dump in the parsing of FvwmAuto arguments. * Fixed screwed calculation of icon picture size when application specifies it explicitly. * The option ShowOnlyIcons now works as described in the FvwmIconMan man page. It was accidentally named ShowOnlyIconic before. ------------------------------------------------------------------- Changes in stable release 2.4.14 (29-Nov-2002) * Modules do not crash anymore when more than 126 windows are on the desktop. * FvwmIconMan displays windows correctly that were iconified and then moved to another page. * Application provided icon windows no longer appear at 0 0 when restarting. * The built-in session management can handle window names, classes etc. beginning with whitespace (textedit). * Removed the flawed "A"ny context key binding patch from 2.4.13. * The default EdgeScroll (if not specified) was incorrectly assumed to be 100 pixels instead of 100 percents. * Icons no longer appear on top of all other windows after a restart. ------------------------------------------------------------------- Changes in stable release 2.4.13 (1-Nov-2002) * Icon titles for windows with an icon position hint no longer appear at random places. * Fvwm no longer displays two icon pictures when switching from NoIconOverride to IconOverride with windows that provide their own icon window. * The Current, All, Pick, ThisWindow and PointerWindow commands work on shaded windows too. * Fixed a problem stacking iconified transients. * No more flickering when raising transients. * Fixed a number of problems with window stacking, some new in 2.4.10 or later, some older problems that have been around for a long time. * Windows starting lowered or on any layer other than the default layer are displayed at the right place in FvwmPager. * Bindings with the "A"ny context can not be overridden by Gnome panel or OpenOffice. ------------------------------------------------------------------- Changes in stable release 2.4.12 (10-Oct-2002) * Fixed drawing problems with TiledPixmap and Solid MenuFaces which appeared in 2.4.10, replacing the same problem with ?Gradient MenuFaces in 2.4.9. * Fixed accidental menu animation with certain menu position hints. * Increased maximum allowed key symbol name length to 200 characters. * Allow quotes in conditional command conditions. * Fixed starting Move at random position when pointer is on a different screen. * Transient windows do not appear in FvwmWinList after they have been moved on the desktop. ------------------------------------------------------------------- Changes in stable release 2.4.11 (20-Sep-2002) * Allow the use of mouse buttons other than the first in FvwmWinList when invoked transient. * Fixed a crash with ssh-askpass introduced in 2.4.10. ------------------------------------------------------------------- Changes in stable release 2.4.10 (15-Sep-2002) * The commands Maximize, Resize and ResizeMove can be used on icons as it was in 2.2.x. * Fixed hilighting of menu items with HGradient and VGradient MenuFace. Reduced flickering with these options. * Fixed a minor problem with entering submenus via keyboard. * Fixed race conditions in FvwmTaskBar with AutoStick that caused it to hang. * Fixed drawing of pager balloons with BalloonBack option. * Fixed drawing of SidePic menu background with B/D gradients. * Fixed drawing of menu item reliefs with gradient menu faces. * Fixed key bindings on window corners. * Fixed FvwmTaskBar i18n font loading * Fixed StackTransientParent style without RaiseTransient or LowerTransient on the parent window. * StackTransientParent works only on parent window if it is on the same layer. * Fixed handling of window group hint with the (De)Iconify command. * No more flickering when a transient overlapping its parent window is lowered. * Fixed hilighting of unfocused windows. ------------------------------------------------------------------- Changes in stable release 2.4.9 (11-Aug-2002) * Fixed interaction bug between CascadePlacement and StartsOnPage - if the target page was at a negative x or y page displacement from the current viewport, the window would be placed on the wrong page. * Fixed a problem with colormap transition when a transient window died. * Fixed a FvwmScript crash with Swallow widget and very long window names. * Restored old way of handling clicks in windows with ClickToFocus and ClickToFocusPassesClickOff. This fixes a problem with click+drag in an unfocused rxvt or aterm window. * Fixed problems with $fg and $bg variables in FvwmButtons when the UseOld option was used. * Fixed wrong warp coordinates when WarpToWindow was used with two arguments on an unmanaged window. * Added a workaround for popup menus in TK applications that appear on some random position. * Fixed problems with wish scripts creating windows that start iconic. * Fixed the NoClose option with unmapped panels in FvwmButtons. * A number of drawing fixes in FvwmPager. * Fixed a slight bug when waiting until all buttons are released, for example after executing a complex function. * Fixed potentially harmful change in module interface. * Fixed displaying menu items with icons when using the MenuStyle SubmenusLeft. * Fixed problems with the pointer moving off screen in a multi head setup. * Fixed a potential crash with windows being destroyed during a recapture operation. * Fixed a memory leak in some modules when not using glibc. * Applications using Mwm hints can now enforce that a window can not be moved. * Fixed negative arguments of WarpToWindow when used on an unmanaged window. * DESTDIR may be fully used again (only useful for distributors). * Fixed a key binding problem with key symbols that are generated by several keys. * Fixed a possible crash when a window was recaptured and the focus could not be transfered to another window. * Fixed a minor problem with clicks on focused windows being ignored. * fvwm-menu-headlines: added support for CNN and BBC headlines. * Fixed a performance problem with large numbers of mouse binding commands. ------------------------------------------------------------------- Changes in stable release 2.4.8 (11-Jun-2002) * A fix for switching between czech and us keyboard layout. * Remember the icon position when an icon is moved non-interactively. * Setup "fvwm" and "fvwm-root" name symlinks for the executable and the man page when installing, see INSTALL.fvwm. * Fixed another problem with the DeskOnly option and sticky icons in FvwmTaskBar. * New FvwmIconMan configuration syntax now conforms to the syntax of other modules, see the man page. * New WindowList option CurrentAtEnd. * Fixed maximal length of a named module packet * Fixed a crash on a config with a new 2.5.x Colorset command. * Always display the current desk number in the FvwmPager window title. * Allow to bind a function to the focus click and pass it to the application at the same time. * Fixed a problem with fvwm not accepting keyboard input when the application with the focus vanished at the start of a session. * A small security patch regarding TMPDIR. * Fixed a problem with colormap transition when a transient window died. * Fixed calculation of average bg colour in colour sets with large pictures. * Fixed some minor problems regarding the multibyte patch. * Fixed selection in FvwmScript List widget. * fvwm-menu-headlines: updated the site data, added a configurable timeout on socket reading (20 sec) to avoid fvwm hanging, new --icon-error option. * Fixed a problem with ClickToFocus + ClickToFocusRaisesOff and windows that are below others. * Fixed the ClickToFocusPassesClick style. * Fixed CascadePlacement for huge windows, so that the top-left corner is always visible. * Fixed parsing of SendToModule with the first parameter quoted. * Fonts in double quotes now should work in module configurations. * Fixed copying PopupOffset values in CopyMenuStyle. ------------------------------------------------------------------- Changes in stable release 2.4.7 (11-Apr-2002) * Fixed parsing of WindowList with conditions and a position at the same time that was broken in 2.4.6. * Fixed some problems with the DeskOnly option of FvwmTaskBar (windows were duplicated when moving to a different Desk; the StickyIcon style was ignored). * Fixed config.h warnings with some compilers introduced in 2.4.6. * Fixed icon titles being raised when they should not be. * Fixed initial drawing of the internals of the FvwmPager window. * Fixed the FvwmAudio compatible mode in FvwmEvent when external audio player is used. * Fixed execution on QNX. ------------------------------------------------------------------- Changes in stable release 2.4.6 (10-Mar-2002) * Better support of non ISO-8859-1 window and icon titles. See the --disable-compound-text option in INSTALL.fvwm for more details. * Improved speed of opaque window movement/resizing. * Fixed a bug that caused windows not being raised and lowered properly. * Suppress error message when using XBM icons. * Fixed a read descriptor problem in FvwmTaskBar * Fixed a minor colour update bug in the pager. * Fixed an fvwm crash when a module died at the wrong moment; specifically a transient FvwmPager or FvwmIconMan. * Fixed placement of WindowList on wrong Xinerama screen when called without any options on a screen other than the primary screen. * Fixed a problem with root bindings and xfishtank. * Fixed moving windows with the keyboard over the edge of the screen when the pointer remained of the previous page. * Do not hilight windows after ResizeMove. * New conditional command ThisWindow. * Some fixes in the configure script that caused some rare problems detecting gnome and ncurses. * Fixed a memory leak in the Pick command. * Allow to choose windows with CirculateSkip with the Pick command. * Fixed an FvwmScript compile problem on dec-osf5. * The window handles are now resizes as they should when the HandleWidth style changes. * The Current command does not select a random window when no window has the focus. * Fixed a rare menu placement problem with Xinerama. ------------------------------------------------------------------- Changes in stable release 2.4.5 (27-Jan-2002) * Fixed minor problems in popping sub menus up and down. * Fixed moving windows between pages with the keyboard. * Fixed the size of the geometry window that was broken sometimes. * Fixed problem with pointer warping to another screen on a dual head setup. * Fixed a problem with the focus in internal Ddd and Netscape windows. * Reduced the time in which fvwm attempts to grab the pointer. * Fixed unmanaged window when window was mapped/unmapped/mapped too fast. * Fixed MiniScroll's auto repeating in FvwmScript. * Fixed a crash with the UseStyle style in combination with HilightBack. * Fixed excessive redraws of the windows under a window being shaded. * Fixed a minor memory leak in the Style command. * Fixed pixmap background of FvwmButtons behind buttons with only text. * Fixed a crash in FvwmIconBox when the application provided an illegal icon. * Fixed a configure problem with libstroke-0.5.1. * New style BackingStoreWindowDefault which is the default now. Fvwm no longer disables backing store on windows by default. * Fixed bug that sometimes caused unnecessary redraws when a style was changed. * Fixed crash when something like "$[$v]" appeared in a command. * Fixed parsing of conditions with more than one comma. ------------------------------------------------------------------- Changes in stable release 2.4.4 (16-Dec-2001) * Minor title drawing fixes. * Fixed manual placement with Xinerama. * Minor button 3 handling fix in FvwmPager. * Fixed *FvwmIconMan*shaped option with empty managers. * Fixed ClickToFocusClickRaises style. * FvwmForm: Customize pointers, support ISO_Tab key, buttons can activate on press or release, special pointer during grab, arrow keys useful in form with one input field. * New OpaqueMoveSize argument "unlimited". * Fixed binding keys with and without "Shift" modifier under some circumstances. * Fixed binding actions to the client window with ClickToFocus. * Mouse bindings are activated without a recapture. * FvwmScript: new keyboard bindings. New flags NoFocus and Left, Center, and Right for text position. Amelioration of the Menu and PopupMenu Widgets. New functions GetPid, Parse, SendMsgAndGet and LastString. New instruction Key for key bindings. New command SendToModule ScriptName SendString. * Command "Silent" when precedes "Key", "Mouse" and "PointerKey" disables warning messages. * Restored the default Alt-Tab behaviour from 2.4.0. ------------------------------------------------------------------- Changes in stable release 2.4.3 (08-Oct-2001) * Fixed activation of shape extension. * Fixed problems with overriding key bindings. * Single letter key names are allowed in upper and lower case in key bindings as before 2.4.0. * Fixed WindowList placement with Xinerama. * Fixed flickering icon titles. * New X resource fvwmscreen to select the Xinerama screen on which to place new windows. * Coordinates of a window during motion are show relative to the Xinerama screen. * Some icon placement improvements with Xinerama. ------------------------------------------------------------------- Changes in stable release 2.4.2 (16-Sep-2001) * Desk and page can be given as X resources in .Xdefaults, for example: xterm.desk: 1 xterm.page: 1 2 3 * Several Shape compilation problems fixed. ------------------------------------------------------------------- Changes in stable release 2.4.1 (15-Sep-2001) * Added Xinerama and SingleLogicalScreen support. * New commands Xinerama, XineramaPrimaryScreen, XineramaSls, XineramaSlsSize and MoveToScreen. * New context rectangle option XineramaRoot for the menu commands. * New conditions CurrentGlobalPage, CurrentGlobalPageAnyDesk and AcceptsFocus for conditional commands. * The DestroyStyle command takes effect immediately. * New style option StartsOnScreen. * New style options NoUSPosition, UseUSPosition, NoTransientPPosition, UseTransientPPosition, NoTransientUSPosition, and UseTransientUSPosition. These work similar to the old styles NoPPosition and UsePPosition. * New option "screen" for Maximize command. * New option ReverseOrder for WindowList command. * The default Alt-Tab binding works more intuitive. * New condition "PlacedByFvwm" * New Geometry option for FvwmForm. * New Screen resolution and ShowOnlyIcons options for FvwmIconMan. * FvwmIconMan can be closed with Delete or Close too. * New options PageOnly and ScreenOnly for FvwmTaskBar. * FvwmIconBox, FvwmTaskBar and FvwmWinList support aliases. * Enhancements in fvwm-menu-headlines and support for 10 more sites. * Color enhancements in button vectors: @2 is bg color, @3 is fg color. * Improved detection of the Shape library. * Fixed FvwmButtons button titles not being erased for swallowed windows that showed up on certain setups. * Fixed bug that caused transient windows to be buried below their parents with the "BugOpts RaiseOverUnmanaged on". This occured with the system.fvwm2rc-sample-95 configuration. * The modules FvwmPager, FvwmIconMan, FvwmWinList and FvwmButtos set the transient_for hint when started with the "transient" option. * Fixed FvwmIconMan with the transient option when mapped off screen. * Fixed ClickToFocus focus policy when iconifying the focused window. * Fixed some focus problems in conjunction with unclutter vs xv/xmms and Open Look applications. * Fixed a problem that could cause windows to be lost off screen with interactive window motion. * Fixed some FvwmTaskBar autohide problem. * Fixed a display string problem in FvwmForm. * Fixed a problem with FvwmTheme shadow colours. * Fixed the CirculateSkipIcon and CirculateSkipShaded options in conditional commands. * Fixed a formatting problem of the man page on AIX, Solaris, and some other UNIX variants. * Fixed a problems with FvwmIconBox exiting on 64 bit platforms. * Fixed FvwmIconBox crashes with MaxIconSize dimensions 0. * Fixed parameters of fvwm24_convert. * Fixed a number of building problems related to old vendor unices, libstroke-0.5, autoconf-2.50, bogus gnome-config and imlib-config. * Fixed drawing of title bar buttons with MWMDecorStick. * Fixed missing button or key events over the pan frames. * Fixed placement of the FvwmDragWell, FvwmButtons and FvwmForm modules. * Fixed parsing double quotes in FvwmPager's Font and SmallFont options. Fixed FvwmPager crash with certain font strings. * Fixed drawing of the grid lines in an iconified FvwmPager window. * Fixed button grabbing problem for buttons > 3 in FvwmTaskBar. * Fixed some exotic problems with window gravity and resizing windows. * Fixed a problem with maximizing windows with the viewport not starting on a page boundary. * Fixed handling of parentheses in FvwmButtons button actions. * Work around a key binding problem with keys that generate the same symbol with more than one key code (e.g. Shift-F1 = F11). * The Desk option of FvwmBacker is compatible to earlier version. Desk or Page coordinates can be omitted to indicate that desk or page changes trigger no action at all. * Fixed double updating of background with FvwmBacker sometimes leading to the wrong background. * Fixed several escaping errors in fvwm-menu-directory, so files and directories containing special chars and spaces should work. * Fixed PlacedByButton3 condition. * Fixed vanishing windows when mapping/unmapping too fast. * Fixed prev option of the GotoDeskAndPage command. * Fixed calculations of X_RESOLUTION and Y_RESOLUTION for screen dimensions larger than 2147. * Fixed compatibility of the FvwmM4 modules on platforms that have a System V implementation of m4 (Solaris 2.6). * The SetEnv command without a value for a variable is the same as UnsetEnv. * Fixed shading/unshading shaped windows and windows without title and border. ------------------------------------------------------------------- Changes in stable release 2.4.0 (03-Jul-2001) * Finally released. :) ------------------------------------------------------------------- For older NEWS, read the ONEWS file. fvwm-2.7.0/configure.ac0000644000175000017500000015100214324315751011712 00000000000000dnl Process this file with autoconf to produce a configure script. dnl AC_PREREQ(2.60) dnl should be "yes" only within the released distribution ISRELEASED="yes" if test $ISRELEASED = "no"; then RELDATELONG="" RELDATESHORT="" RELDATENUM="" fi # Silence warning: ar: 'u' modifier ignored since 'D' is the default AC_SUBST(AR_FLAGS, [cr]) AC_INIT([fvwm], m4_esyscmd_s([utils/fvwm-version-str.sh]), [fvwm-workers@fvwm.org]) AC_CONFIG_AUX_DIR(etc) AM_INIT_AUTOMAKE([foreign subdir-objects]) AM_SILENT_RULES([yes]) AM_CONFIG_HEADER(config.h) VERSIONINFO="" dnl date of the released version (please zero pad the day in the last 2 dates) dnl for example: "4 February 2003", "04 Feb 2003", "2003-02-04" dnl date format strings: "%e %B %Y", "%d-%b-%Y", "%Y-%m-%d" RELDATELONG="19 October 2022" RELDATESHORT="19-Oct-2022" RELDATENUM="2022-10-19" # constant variable settings FVWMNAMELONG="F? Virtual Window Manager" FVWMHOMEPAGE="http://fvwm.org/" FVWMFTP="ftp.fvwm.org" FVWMFTPDIR="/pub/ftp" FVWMALTFTP="metalab.unc.edu" FVWMALTFTPDIR="/pub/Linux/X11/window-managers/" FVWMLIST="fvwm@fvwm.org" FVWMWORKERSLIST="fvwm-workers@fvwm.org" FVWMWORKERSLISTLONG="fvwm workers list " MANPAGE_PREAMBLE='.\" WARNING: This file was automatically generated. Edit the .in file instead.' AC_SUBST(ISRELEASED) AH_TEMPLATE([VERSIONINFO],[Additional version information, like date]) AC_DEFINE_UNQUOTED(VERSIONINFO, "$VERSIONINFO") AC_SUBST(VERSIONINFO) AC_SUBST(RELDATELONG) AC_SUBST(RELDATESHORT) AC_SUBST(RELDATENUM) AC_SUBST(FVWMNAMELONG) AC_SUBST(FVWMHOMEPAGE) AC_SUBST(FVWMFTP) AC_SUBST(FVWMFTPDIR) AC_SUBST(FVWMALTFTP) AC_SUBST(FVWMALTFTPDIR) AC_SUBST(FVWMLIST) AC_SUBST(FVWMWORKERSLIST) AC_SUBST(FVWMWORKERSLISTLONG) AC_SUBST(MANPAGE_PREAMBLE) # check for programs needed to build html docs AC_CHECK_PROG(SED, sed, sed, "") AC_SUBST(SED) # optional python: PYTHON= REQUIRED_PYTHON_VERSION=3.0 AC_SUBST(REQUIRED_PYTHON_VERSION) AC_PATH_PROG([PYTHON],[python3],[:]) AS_IF([test "$PYTHON" != ":"], [AM_PYTHON_CHECK_VERSION([$PYTHON],[$REQUIRED_PYTHON_VERSION],[:], [PYTHON=":"])]) #!!! PERL="" REQUIRED_PERL_VERSION=5.004 AC_SUBST(REQUIRED_PERL_VERSION) if test x"$PERL" = x; then AC_PATH_PROG(PERL, perl) fi if test ! x"$PERL" = x; then AC_MSG_CHECKING([for perl $REQUIRED_PERL_VERSION or better]) HAVE_PERL_FOR_DOCS=1 if ("$PERL" -e "require $REQUIRED_PERL_VERSION;") 2>/dev/null; then AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) AC_MSG_WARN([$PERL not found or too old]) fi else HAVE_PERL_FOR_DOCS=0 AC_MSG_WARN([perl is not found, it is required for some scripts and modules]) AC_MSG_WARN([It is recommended to install perl $REQUIRED_PERL_VERSION or better later]) PERL=/usr/bin/perl fi AC_MSG_RESULT([assuming $PERL as perl location]) AC_SUBST(PERL) # installation paths transform=`echo "${program_transform_name}" | "$SED" -e 's/\\$\\$/\\$/'` PPACKAGE=`echo "${PACKAGE}" | "$SED" -e "${transform}"` FVWM_MODULESUBDIR=/${PPACKAGE}/${VERSION} FVWM_DATASUBDIR=/${PPACKAGE} FVWM_DOCSUBDIR=/doc/${PPACKAGE} AC_ARG_ENABLE(package-subdirs, AS_HELP_STRING([--disable-package-subdirs], [do not create subdirs for modules and data]), [if test x"$enableval" = xno; then FVWM_MODULESUBDIR=""; FVWM_DATASUBDIR=""; fi], []) FVWM_MODULEDIR='${libexecdir}'"$FVWM_MODULESUBDIR" FVWM_DATADIR='${datadir}'"$FVWM_DATASUBDIR" FVWM_DOCDIR='${datadir}'"$FVWM_DOCSUBDIR" FVWM_PERLLIBDIR='${datadir}'"$FVWM_DATASUBDIR/perllib" FVWM_CONFDIR='${sysconfdir}'dnl used _only_ to search for system.fvwm2rc AC_SUBST(FVWM_MODULEDIR) AC_SUBST(FVWM_DATADIR) AC_SUBST(FVWM_PERLLIBDIR) AC_SUBST(FVWM_CONFDIR) AC_SUBST(FVWM_DOCDIR) AH_TEMPLATE([FVWM_CONFIG], [Name of config filenames in FVWM_USERDIR and FVWM_DATADIR]) AC_DEFINE(FVWM_CONFIG, "config") AH_TEMPLATE([FVWM2RC],[Suffix for old (to be deprecated) config filenames]) AC_DEFINE(FVWM2RC, ".fvwm2rc") # Various configure-time options AC_ARG_ENABLE(dmalloc, AS_HELP_STRING([--enable-dmalloc], [enable support for the dmalloc debugging library]), [ac_cv_dmalloc="$enableval"], [ac_cv_dmalloc="no"]) AC_ARG_ENABLE(efence, AS_HELP_STRING([--enable-efence], [enable support for the efence debugging library]), [ac_cv_efence="$enableval"], [ac_cv_efence="no"]) smr_SWITCH(command-log, command logging, off, FVWM_COMMAND_LOG,, [Produces a log of all executed commands and their times on stderr.]) AH_VERBATIM([_FVWM_COMMAND_LOG], [#ifdef FVWM_COMMAND_LOG # define FVWM_DEBUG_TIME 1 #endif]) smr_SWITCH(debug-msgs, debugging messages, off, FVWM_DEBUG_MSGS,, [if you would like to see lots of debug messages from fvwm, for debugging purposes, uncomment the next line]) AH_VERBATIM([_FVWM_DEBUG_MSGS], [#ifdef FVWM_DEBUG_MSGS # define DBUG(x,y) fvwm_msg(DBG,x,y) #else # define DBUG(x,y) /* no messages */ #endif]) dnl dummy: smr_SWITCH(sm, dummy for test script, on, SESSION) # Need to know where X is, for finding some libraries (e.g. xpm) no_x="" AC_PATH_XTRA if test x"$no_x" = x"yes"; then echo echo "X11 libraries or header files could not be found. Please make" echo "sure the X11 development package is installed on your system." echo "If it is definitely installed, try setting the include and library" echo "paths with the --x-include and --x-libraries options of configure." echo "Fvwm can not be compiled without the X11 development environment." echo echo "Aborting." echo exit 1 fi # FIXME: default value should be derived from computed path to X # includes. Actually, this should probably not appear in configure # at all: it is settable at runtime, and only confuses the issue to # have it settable here too. # AC_MSG_CHECKING(imagepath) val="/usr/include/X11/bitmaps:/usr/include/X11/pixmaps" AC_ARG_WITH(imagepath, AS_HELP_STRING([--with-imagepath=PATH], [colon-delimited search path for images]), [ case "$withval" in no) AC_MSG_ERROR([Can not disable image path.]) ;; yes) ;; *) val="$withval" ;; esac ]) AH_TEMPLATE([FVWM_IMAGEPATH],[Where to search for images.]) AC_DEFINE_UNQUOTED(FVWM_IMAGEPATH, "$val") FVWM_IMAGEPATH="$val" AC_SUBST(FVWM_IMAGEPATH) AC_MSG_RESULT($val) # Minimal checks for programs: enough to enable checking for # optional libraries. AC_PROG_CC AC_PROG_CPP # added -Wall for gcc, what about for others? if test "x$GCC" = "xyes"; then CFLAGS="-Wall -Wno-implicit-int $CFLAGS" fi # Help finding POSIX functions on some systems AC_ISC_POSIX AC_MINIX # catch -Werror and similar options when running configure AC_TRY_COMPILE([#include ], [int i; static j; int *p; char *c; switch (*p = p = *c) { case 0: printf("%Q", c, p); } *c = &i; c = p; while (1 || (unsigned int)3 >= 0 || ((int)-1) == ((unsigned int)1)); ], , AC_MSG_ERROR(" configure is not able to compile programs with warnings. Please remove all offending options like -Werror from the CFLAGS and CPPFLAGS variables and run configure again.")) # check size of some types ac_save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $X_CFLAGS" AC_CHECK_SIZEOF(int) AC_CHECK_SIZEOF(long) AC_CHECK_SIZEOF(Window, , [#include #include ]) AC_CHECK_SIZEOF(Pixel, , [#include #include ]) AC_CHECK_SIZEOF(void *) CFLAGS="$ac_save_CFLAGS" size_check_failed="" if test "$ac_cv_sizeof_void_p" -gt "$ac_cv_sizeof_long"; then echo "The type void * is bigger than long." size_check_failed=1 fi if test "$ac_cv_sizeof_Window" -gt "$ac_cv_sizeof_long"; then echo "The type Window is bigger than long." size_check_failed=1 fi if test "$ac_cv_sizeof_Pixel" -gt "$ac_cv_sizeof_long"; then echo "The type Pixel is bigger than long." size_check_failed=1 fi if test x"$size_check_failed" = x1; then echo "This is not supported by the module interface yet (make_new_vpacket)." echo "Detected type sizes are: int($ac_cv_sizeof_int), long($ac_cv_sizeof_long), void*($ac_cv_sizeof_void_p), Window($ac_cv_sizeof_Window), Pixel($ac_cv_sizeof_Pixel)" echo "Please report details of your system and this message to ${FVWMWORKERSLIST}." echo exit 1 fi # 'unset' is not portable, but setting to null is not enough to avoid using # the cached value! For ancient shells "rm config.cache" is a solution. UNSET=true if unset UNSET 2>/dev/null; then UNSET=unset; fi # ********* multibyte # FreeBSD has libxpg4, check this and use if found. AC_CANONICAL_HOST case $host_os in freebsd*) AC_CHECK_LIB(xpg4, setlocale, [LIBS="$LIBS -lxpg4"]);; *) ;; esac # *** pkg-config # unfortunately, we need pkg-config for the detection of certain libs: # - version of fontconfig without fontconfig-config # - version of fribidi without fribidi-config PKG_PROG_PKG_CONFIG # Building man pages & HTML documentation (from XML source). # extract command names if test ! x"$SED" = x; then DOC_COMMANDS=` sed -n ' :findhead /#.*define.*CMD_ENT/bfindcmd n bfindhead :findcmd n /CMD_ENT/bfound bfindcmd :found /"#"/bfindcmd /"propertychange"/bfindcmd /"readwritecolors"/bfindcmd /"send_.*"/bfindcmd /"set_.*"/bfindcmd s/.*CMD_ENT.*CMD_// s/,.*// p n bfindcmd ' < fvwm/functable.c` DOC_COMMANDS=`echo $DOC_COMMANDS` # with .xml suffix DOC_COMMANDS_XML=`for i in $DOC_COMMANDS; do echo ${i}.xml; done` DOC_COMMANDS_XML=`echo $DOC_COMMANDS_XML` # with .xml suffix and path DOC_COMMANDS_XML_PATH=` for i in $DOC_COMMANDS; do echo ../commands/${i}.xml; done ` DOC_COMMANDS_XML_PATH=`echo $DOC_COMMANDS_XML_PATH` # with .html suffix DOC_COMMANDS_HTML=`for i in $DOC_COMMANDS; do echo ${i}.html; done` DOC_COMMANDS_HTML=`echo $DOC_COMMANDS_HTML` # extract module names DOC_MODULES="" DOC_MODULES=` for i in modules/*; do echo "$i"; done | sed -n ' :search /^modules.Fvwm/bfound bnext :found s/modules.// p :next n bsearch ' ` DOC_MODULES=`echo $DOC_MODULES` DOC_MODULES_HTML=`for i in $DOC_MODULES; do echo ${i}.html; done` DOC_MODULES_HTML=`echo $DOC_MODULES_HTML` # extract man page section names DOC_SECTIONS=`cat doc/fvwm/sections` DOC_SECTIONS=`echo $DOC_SECTIONS` DOC_SECTIONS_XML=`for i in $DOC_SECTIONS; do echo ${i}.xml; done` DOC_SECTIONS_XML=`echo $DOC_SECTIONS_XML` DOC_SECTIONS_XML_PATH=`for i in $DOC_SECTIONS; do echo ${i}.xml; done` DOC_SECTIONS_XML_PATH=`echo $DOC_SECTIONS_XML` else DOC_COMMANDS="" DOC_COMMANDS_XML="" DOC_COMMANDS_XML_PATH="" DOC_COMMANDS_HTML="" DOC_MODULES="" DOC_MODULES_HTML="" DOC_SECTIONS="" DOC_SECTIONS_XML="" DOC_SECTIONS_XML_PATH="" fi AC_SUBST(DOC_COMMANDS) AC_SUBST(DOC_COMMANDS_XML) AC_SUBST(DOC_COMMANDS_XML_PATH) AC_SUBST(DOC_COMMANDS_HTML) AC_SUBST(DOC_MODULES) AC_SUBST(DOC_MODULES_HTML) AC_SUBST(DOC_SECTIONS) AC_SUBST(DOC_SECTIONS_XML) AC_SUBST(DOC_SECTIONS_XML_PATH) problem_mandoc="" AC_CHECK_PROG(XSLTPROC, xsltproc, xsltproc, "") AC_ARG_ENABLE(mandoc, AS_HELP_STRING([--enable-mandoc], [enable generation of man pages]), [ if test x"$enableval" = xyes; then with_mandoc="yes, check" else with_mandoc="no" problem_mandoc=": Explicitly disabled" fi ], [ with_mandoc="no" ] ) if test ! x"$with_mandoc" = xno; then if test x"$XSLTPROC" = x ; then with_mandoc="no" problem_mandoc=": No xsltproc found in PATH" elif test x"$SED" = x ; then with_mandoc="no" problem_mandoc=": No sed found in PATH" elif test x"$HAVE_PERL_FOR_DOCS" = x0 ; then with_mandoc="no" problem_mandoc=": No perl found in PATH" else with_mandoc="yes" fi fi AM_CONDITIONAL([FVWM_BUILD_MANDOC], [test x"$with_mandoc" = xyes]) problem_htmldoc="" AC_ARG_ENABLE(htmldoc, AS_HELP_STRING([--enable-htmldoc],[enable generation of HTML documentation]), [ if test x"$enableval" = xyes; then with_htmldoc="yes, check" else with_htmldoc="no" problem_htmldoc=": Explicitly disabled" fi ], [ with_htmldoc="no" ] ) if test ! x"$with_htmldoc" = xno; then if test x"$XSLTPROC" = x ; then with_htmldoc="no" problem_htmldoc=": No xsltproc found in PATH" elif test x"$SED" = x ; then with_htmldoc="no" problem_htmldoc=": No sed found in PATH" elif test x"$HAVE_PERL_FOR_DOCS" = x0 ; then with_htmldoc="no" problem_htmldoc=": No perl found in PATH" else with_htmldoc="yes" fi fi AM_CONDITIONAL([FVWM_BUILD_HTMLDOC], [test x"$with_htmldoc" = xyes]) # ********* session management # Check the availability of SM; we don't have to add any extra libraries, # since -lSM -lICE are in X_PRE_LIBS when they exist. dnl [old check] AC_CHECK_LIB(SM, SmcOpenConnection, AC_DEFINE(SESSION), , dnl [old check] [$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS]) problem_sm="" AC_ARG_ENABLE(sm, AS_HELP_STRING([--disable-sm],[disable session management support]), [ if test x"$enableval" = xyes; then with_sm="yes, check" else with_sm="no" problem_sm=": Explicitly disabled" fi ], [ with_sm="not specified, check" ] ) if test ! x"$with_sm" = xno; then dnl Uncomment the following and comment out AC_CHECK_LIB to get --with-sm-* dnl $UNSET ac_cv_lib_SM_SmcOpenConnection dnl $UNSET ac_cv_header_X11_SM_SMlib_h dnl smr_CHECK_LIB(sm, SM, adds session management support, SmcOpenConnection, dnl X11/SM/SMlib.h, dnl [$X_LIBS $X_PRE_LIBS $X_EXTRA_LIBS], $X_CFLAGS) dnl test "$sm_LIBS" && AC_DEFINE(SESSION) $UNSET ac_cv_lib_SM_SmcOpenConnection AH_TEMPLATE([SESSION],[Enables session management functionality.]) AC_CHECK_LIB(SM, SmcOpenConnection, with_sm=yes; AC_DEFINE(SESSION), with_sm=no; problem_sm=": Failed to detect libSM", [$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS]) fi dnl AC_SUBST(sm_LIBS) dnl AC_SUBST(sm_CFLAGS) # Checking for optional libraries # Default is to use them if found; can be disable using --without # These are put up front so that if they are requested, but # configure fails to find them, we fail early. # ********* shape extension dnl smr_SWITCH(shape, shape extensions, on, SHAPE) AC_ARG_ENABLE(shape, AS_HELP_STRING([--disable-shape],[disable shaped window support]), [ if test x"$enableval" = xyes; then with_shape="yes, check" else with_shape="no" problem_shape=": Explicitly disabled" fi ], [ with_shape="not specified, check" ] ) AH_TEMPLATE(SHAPE, [ Define if you want the Shaped window extensions. Shaped window extensions seem to increase the window managers RSS by about 60 Kbytes. They provide for leaving a title-bar on the window without a border. If you don't use shaped window extension, you can either make your shaped windows undecorated, or live with a border and backdrop around all your shaped windows (oclock, xeyes) If you normally use a shaped window (xeyes or oclock), you might as well compile this extension in, since the memory cost is minimal in this case (The shaped window shared libs will be loaded anyway). If you don't normally use a shaped window, you have to decide for yourself. Note: if it is compiled in, run time detection is used to make sure that the currently running X server supports it.]) if test ! x"$with_shape" = xno; then $UNSET ac_cv_lib_Xext_XShapeQueryExtension AC_CHECK_LIB(Xext, XShapeQueryExtension, with_shape=yes; AC_DEFINE(SHAPE), with_shape=no; problem_shape=": Failed to detect Shape extension", [$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS]) fi # ********* MIT Shared Memory Extension AC_ARG_ENABLE(shm, AS_HELP_STRING([--disable-shm],[disable MIT Shared Memory Extension]), [ if test x"$enableval" = xyes; then with_shm="yes, check" else with_shm="no" problem_shm=": Explicitly disabled" fi ], [ with_shm="not specified, check" ] ) AH_TEMPLATE([HAVE_XSHM],[Define if MIT Shared Memory extension is used.]) if test ! x"$with_shm" = xno; then $UNSET ac_cv_lib_Xext_XShmQueryExtension AC_CHECK_LIB(Xext, XShmQueryExtension, with_shm=yes; AC_DEFINE(HAVE_XSHM), with_shm=no; problem_shm=": Can't detect MIT Shared Memory ext.", [$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS]) fi # Silently look for X11/XKBlib.h AH_TEMPLATE([HAVE_X11_XKBLIB_H],[Define if Xkb extension is used.]) AC_CHECK_HEADER(X11/XKBlib.h, AC_DEFINE(HAVE_X11_XKBLIB_H)) # ********* xineramA problem_xinerama="" AC_ARG_ENABLE(xinerama, AS_HELP_STRING([--disable-xinerama],[disable Xinerama multi screen support]), [ if test x"$enableval" = xyes; then with_xinerama="yes, check" else with_xinerama="no" problem_xinerama=": Explicitly disabled" fi ], [ with_xinerama="not specified, check" ] ) AH_TEMPLATE([HAVE_XINERAMA],[Define if Xinerama library is used.]) AH_TEMPLATE([HAVE_SOLARIS_XINERAMA], [Define if Solaris' Xinerama calls are being used. (Solaris 7 11/99 and later)]) AH_TEMPLATE([HAVE_SOLARIS_XINERAMA_H], [Define if Solaris' X11/extensions/xinerama.h header is provided. (Solaris 9 and later)]) if test ! x"$with_xinerama" = xno; then $UNSET ac_cv_lib_Xinerama_XineramaIsActive _check_solaris_xinerama=no AC_CHECK_LIB(Xinerama, XineramaIsActive, with_xinerama=yes; Xinerama_LIBS=-lXinerama; AC_DEFINE(HAVE_XINERAMA), _check_solaris_xinerama=yes, [$X_LIBS $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS]) if test x"$_check_solaris_xinerama" = xyes; then AC_CHECK_LIB(Xext, XineramaGetState, [ AC_DEFINE(HAVE_XINERAMA) AC_DEFINE(HAVE_SOLARIS_XINERAMA) with_xinerama=yes; Xinerama_LIBS=-lXext my_CPPFLAGS="$CPPFLAGS"; CPPFLAGS="$X_CPPFLAGS $CPPFLAGS" my_hdr="X11/extensions/xinerama.h" AC_CHECK_HEADER($my_hdr, AC_DEFINE(HAVE_SOLARIS_XINERAMA_H) problem_xinerama=" (Using Solaris Xinerama calls)", problem_xinerama=" (Using Solaris 9 prototypes for missing header)") CPPFLAGS="$my_CPPFLAGS"], with_xinerama=no; Xinerama_LIBS= problem_xinerama=": Failed to detect libXinerama", [$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS]) fi $UNSET _check_solaris_xinerama fi AC_SUBST(Xinerama_LIBS) AC_SUBST(Xinerama_CFLAGS) # ********* xinerama-emulation smr_SWITCH( xinerama-emulation, [Xinerama emulation on one screen (useful only for developers)], off, USE_XINERAMA_EMULATION,, [Define if Xinerama should be emulated on a single screen.]) if test x"$enable_xinerama_emulation" = xyes; then with_xinerama_emulation=yes else with_xinerama_emulation=no fi # ********* xrender problem_xrender="" AC_ARG_ENABLE(xrender, AS_HELP_STRING([--disable-xrender],[disable Xrender alpha-blend rendering]), [ if test x"$enableval" = xyes; then with_xrender="yes, check" else with_xrender="no" problem_xrender=": Explicitly disabled" fi ], [ with_xrender="not specified, check" ] ) AH_TEMPLATE([HAVE_XRENDER],[Define if Xrender library is used.]) if test ! x"$with_xrender" = xno; then $UNSET ac_cv_lib_Xrender_XRenderComposite AC_CHECK_LIB(Xrender, XRenderComposite, with_xrender=yes; Xrender_LIBS=-lXrender; AC_DEFINE(HAVE_XRENDER), with_xrender=no; Xrender_LIBS= problem_xrender=": Failed to detect libXrender", [$X_LIBS $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS]) fi AC_SUBST(Xrender_LIBS) AC_SUBST(Xrender_CFLAGS) # ********* xcursor AH_TEMPLATE([HAVE_XCURSOR],[Define if Xcursor library is used.]) xcursor_CFLAGS="" xcursor_LIBS="" AC_ARG_ENABLE(xcursor, AS_HELP_STRING([--disable-xcursor], [disable Xcursor ARGB/animated cursor loading]), [ if test x"$enableval" = xno; then with_xcursor=no problem_xcursor=": Explicitly disabled" fi ], ) if test ! x"$with_xcursor" = xno; then with_xcursor=no if test ! x"$with_xrender" = xno; then $UNSET ac_cv_lib_Xrender_XRenderCreateCursor AC_CHECK_LIB(Xrender, XRenderCreateCursor, [ with_xcursor=yes ],[ problem_xcursor=": Your libXrender version is too old" ], [$X_LIBS $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS]) else problem_xcursor=": Need Xrender support" fi fi if test x"$with_xcursor" = xyes ; then $UNSET ac_cv_lib_Xcursor_XcursorImageLoadCursor AC_CHECK_LIB(Xcursor, XcursorImageLoadCursor, [ AC_DEFINE(HAVE_XCURSOR) Xcursor_LIBS=-lXcursor problem_xcursor="" ],[ with_xcursor=no problem_xcursor=": Failed to detect libXcursor" ],[$X_LIBS $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS]) fi AC_SUBST(Xcursor_CFLAGS) AC_SUBST(Xcursor_LIBS) # ********* xft problem_xft="" AC_ARG_ENABLE(xft, AS_HELP_STRING([--disable-xft],[disable Xft anti-aliased font rendering]), [ if test x"$enableval" = xyes; then with_xft="yes, check" else with_xft="no" problem_xft=": Explicitly disabled" fi ], [ with_xft="not specified, check" ] ) AH_TEMPLATE([HAVE_XFT],[Define if Xft library is used.]) AH_TEMPLATE([HAVE_XFT2],[Define if Xft 2 library is used.]) AH_TEMPLATE([HAVE_XFT_UTF8],[Define if Xft library can handle utf8 encoding]) if test ! x"$with_xft" = xno; then AC_MSG_CHECKING([whether pkg-config could find freetype2]) if "${PKG_CONFIG}" --exists freetype2; then AC_MSG_RESULT([yes]) CFLAGS_FREETYPE=`"${PKG_CONFIG}" --cflags freetype2` FREETYPE_LIBS=`"${PKG_CONFIG}" --libs freetype2` CFLAGS="$CFLAGS $CFLAGS_FREETYPE" LIBS="$LIBS $FREETYPE_LIBS" have_freetype=yes else AC_MSG_RESULT([no]) have_freetype=no fi # check for fontconfig for Xft 2 have_fontconfig=no if test ! x"$have_freetype" = xno ; then AM_CHECK_FC(1.0.1) if test x"$no_fc" = x ; then have_fontconfig=yes fontconfig_CFLAGS=`$PKG_CONFIG --cflags fontconfig` fontconfig_LIBS=`$PKG_CONFIG --libs fontconfig` CFLAGS="$CFLAGS $fontconfig_CFLAGS" LIBS="$LIBS $fontconfig_LIBS" else have_fontconfig=no problem_xft=": Can't detect fontconfig >= 1.0.1" fi fi # now check for Xft 2 with_xft=no if test ! x"$have_fontconfig" = xno ; then # Xft 2 AM_CHECK_XFT(2.0.0) if test x"$no_xft" = x; then with_xft=yes problem_xft=" (version 2)" AC_DEFINE(HAVE_XFT2) AC_DEFINE(HAVE_XFT) AC_DEFINE(HAVE_XFT_UTF8) Xft_LIBS=$XFT_LIBS Xft_CFLAGS=$XFT_CFLAGS else problem_xft=": Can't detect Xft2, detected fontconfig" fi fi # if Xft2 not detected check for Xft1 if test ! x"$have_freetype" = xno && test ! x"$with_xft" = xyes; then #Xft 1 $UNSET ac_cv_lib_XftConfigSubstitute $UNSET ac_cv_lib_Xft_XftFontOpen $UNSET ac_cv_lib_Xft_XftDrawStringUtf8 AC_CHECK_LIB(Xft, XftFontOpen, with_xft=yes, with_xft=no, [$X_LIBS $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS $FT2_LIBS $Xrender_LIBS]) if test x"$with_xft" = xyes ; then AC_CHECK_LIB(Xft, XftConfigSubstitute, is_xft1=yes, is_xft1=no, [$X_LIBS $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS $FT2_LIBS $Xrender_LIBS]) if test x"$is_xft1" = xyes; then Xft_LIBS="-lXft $FT2_LIBS" Xft_CFLAGS="$Xft_CFLAGS $FT2_CFLAGS" problem_xft=" (version 1)" AC_DEFINE(HAVE_XFT) else with_xft=no problem_xft=": Can't detect Xft 1 or fontconfig" fi else problem_xft=": Can't detect Xft 1 or 2 and fontconfig" fi if test x"$with_xft" = xyes; then AC_CHECK_LIB(Xft, XftDrawStringUtf8, AC_DEFINE(HAVE_XFT_UTF8),, [$X_LIBS $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS $FT2_LIBS $Xrender_LIBS]) fi fi fi AC_SUBST(Xft_LIBS) AC_SUBST(Xft_CFLAGS) # ********* xpm problem_xpm=": Xpm library or header not found" $UNSET ac_cv_header_X11_xpm_h $UNSET ac_cv_lib_Xpm_XpmReadFileToXpmImage smr_CHECK_LIB(xpm, Xpm, for coloured or shaped icons, XpmReadFileToXpmImage, X11/xpm.h, [$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS], $X_CFLAGS) if test ! x"$xpm_LIBS" = x; then # Check for proper version of Xpm -- from XEmacs 21.x configure.in AC_MSG_CHECKING([for Xpm 3.4g or better]) my_CPPFLAGS="$CPPFLAGS" my_LIBS="$LIBS" CPPFLAGS="$CPPFLAGS $xpm_CFLAGS $X_CFLAGS" LIBS="$LIBS $xpm_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS" AC_TRY_RUN([#include int main(int c, char **v) { return c == 1 ? 0 : XpmIncludeVersion != XpmLibraryVersion() ? 1 : XpmIncludeVersion < 30407 ? 2 : 0 ;}], [./conftest dummy_arg; xpm_status=$?; if test x"$xpm_status" = x0; then with_xpm=yes problem_xpm="" else with_xpm=no; if test x"$xpm_status" = x1; then problem_xpm=": Xpm library and header versions don't match" elif test x"$xpm_status" = x2x; then problem_xpm=": Xpm library version is too old" else problem_xpm=": Internal xpm detection logic error" fi fi], [with_xpm=no; problem_xpm=": Xpm test error, see config.log"], [echo $ac_n "cross compiling; assumed OK... $ac_c"]) AC_MSG_RESULT($with_xpm) CPPFLAGS="$my_CPPFLAGS" LIBS="$my_LIBS" AH_TEMPLATE([XPM],[Define if Xpm library is used.]) if test x"$with_xpm" = xyes; then AC_DEFINE(XPM) # FVWMBANNER=FvwmBanner AC_SUBST(FVWMBANNER) # XPMROOT=xpmroot AC_SUBST(XPMROOT) # FVWMSCRIPT=FvwmScript AC_SUBST(FVWMSCRIPT) else xpm_LIBS= xpm_CFLAGS= fi fi AC_SUBST(xpm_LIBS) AC_SUBST(xpm_CFLAGS) # ********* png png_LIBS="" png_CFLAGS="" AH_TEMPLATE([HAVE_PNG], [Define PNG]) AC_ARG_ENABLE(png, AS_HELP_STRING([--disable-png], [Disables libpng support.]), [with_png="$enableval"], [with_png="yes"]) if test "$with_png" = no; then AC_MSG_WARN([*** disabling PNG support will mean the default configuration shipped with FVWM will be without icon support. Be sure this is what you mean to do. ***]) else AC_MSG_CHECKING([for libpng...]) PKG_CHECK_MODULES([png], [libpng >= 1.2], [ AC_DEFINE(HAVE_PNG) ], [ AC_MSG_ERROR([*** libpng not found, and --disable-png not given. It is recommended to use libpng so that PNG icons can be rendered by FVWM, which the default configuration file needs, as well as other third-party programs which generate menus, for example. If it is critical that FVWM does not link against libpng (perhaps due to size limitations of the binary), then use --disable-png ***]) ]) # ** needed by the png support AC_C_BIGENDIAN fi AC_SUBST(png_LIBS) AC_SUBST(png_CFLAGS) # ********* rsvg rsvg_min_version=2.13.92 AH_TEMPLATE([HAVE_RSVG], [Define if librsvg library is used.]) AC_ARG_ENABLE(rsvg, AS_HELP_STRING([--disable-rsvg], [disable scalable vector graphics (SVG images)]), [ if test x"$enableval" = xno; then with_rsvg=no problem_rsvg=": Explicitly disabled" fi ], ) if test ! x"$with_rsvg" = xno; then with_rsvg=no if test ! x"$PKG_CONFIG" = x ; then AC_MSG_CHECKING(for librsvg - version >= $rsvg_min_version) if $PKG_CONFIG --exists librsvg-2.0 ; then if $PKG_CONFIG --exists "librsvg-2.0 >= $rsvg_min_version" ; then AC_MSG_RESULT(yes) AC_MSG_CHECKING(for cairo svg backend) if $PKG_CONFIG --exists cairo-svg ; then svg_packages="librsvg-2.0 cairo-svg" elif $PKG_CONFIG --exists libsvg-cairo ; then svg_packages="librsvg-2.0 libsvg-cairo" elif $PKG_CONFIG --exists cairo ; then svg_packages="librsvg-2.0 cairo" else svg_packages="" fi if test ! x"$svg_packages" = x ; then AC_MSG_RESULT(yes) rsvg_CFLAGS=`$PKG_CONFIG --cflags $svg_packages` rsvg_LIBS=`$PKG_CONFIG --libs $svg_packages` with_rsvg=yes else AC_MSG_RESULT(no) AC_MSG_WARN([*** cairo was not found in the pkg-config search]) AC_MSG_WARN([*** path. Add the directory containing cairo.pc]) AC_MSG_WARN([*** to the PKG_CONFIG_PATH environment variable.]) problem_rsvg=": Cannot detect cairo backend" fi else AC_MSG_RESULT(no) AC_MSG_WARN([*** Your librsvg version is < $rsvg_min_version]) problem_rsvg=": Your librsvg version is too old" fi else AC_MSG_RESULT(no) AC_MSG_WARN([*** librsvg-2.0 was not found in the pkg-config search]) AC_MSG_WARN([*** path. Either librsvg is not installed or you need]) AC_MSG_WARN([*** to add the directory containing librsvg-2.0.pc to]) AC_MSG_WARN([*** the PKG_CONFIG_PATH environment variable.]) problem_rsvg=": librsvg library or header not found" fi else problem_rsvg=": pkg-config not found" fi fi if test x"$with_rsvg" = xyes ; then AC_MSG_CHECKING(whether a librsvg program compiles and runs) original_CFLAGS="$CFLAGS" original_LIBS="$LIBS" CFLAGS="$CFLAGS $rsvg_CFLAGS" LIBS="$LIBS $rsvg_LIBS" AC_TRY_RUN([ #include #include int main() { RsvgHandle *rsvg; g_type_init(); if(!(rsvg = rsvg_handle_new())) return 1; g_object_unref(G_OBJECT(rsvg)); return 0; } ], [ AC_MSG_RESULT(yes) ], [ AC_MSG_RESULT(no) AC_MSG_WARN([*** The librsvg test program failed to run. If your system]) AC_MSG_WARN([*** has shared libraries outside the normal system library]) AC_MSG_WARN([*** path, you need to make sure that the LD_LIBRARY_PATH]) AC_MSG_WARN([*** (or the like) environment variable is correctly set.]) with_rsvg=no problem_rsvg=": Failed to run test program" ], [echo $ac_n "cross compiling; assumed OK... $ac_c"]) CFLAGS="$original_CFLAGS" LIBS="$original_LIBS" fi if test x"$with_rsvg" = xyes ; then AC_DEFINE(HAVE_RSVG) problem_rsvg="" else rsvg_CFLAGS="" rsvg_LIBS="" fi AC_SUBST(rsvg_CFLAGS) AC_SUBST(rsvg_LIBS) # ********* rplay $UNSET ac_cv_header_rplay_h $UNSET ac_cv_lib_rplay_rplay_create # Add in X_EXTRA_LIBS here to get things like connect(). smr_CHECK_LIB(rplay, , adds audio capability, rplay_create, rplay.h, $X_EXTRA_LIBS) AH_TEMPLATE([HAVE_RPLAY],[Define if rplay library is used.]) test ! x"$rplay_LIBS" = x && AC_DEFINE(HAVE_RPLAY) AC_SUBST(rplay_LIBS) AC_SUBST(rplay_CFLAGS) # ********* stroke $UNSET ac_cv_header_stroke_h $UNSET ac_cv_lib_stroke_stroke_init dnl Add in X_LIBS for MOUSE_DROPPINGS? dnl As of 23/Mar/2000 the only libstroke RPM has /usr/X11R6/include/stroke.h AH_TEMPLATE([HAVE_STROKE],[Define if stroke library is used.]) smr_CHECK_LIB(stroke, , mouse strokes recognition, stroke_init, stroke.h, [$X_LIBS -lX11], $X_CFLAGS -I/usr/X11R6/include) test ! x"$stroke_LIBS" = x && AC_DEFINE(HAVE_STROKE) AH_VERBATIM([_HAVE_STROKE], [#ifdef HAVE_STROKE # define STROKE_ARG(x) x, # define STROKE_CODE(x) x #else # define STROKE_ARG(x) # define STROKE_CODE(x) #endif]) AC_SUBST(stroke_LIBS) AC_SUBST(stroke_CFLAGS) # ********* readline with_readline=no problem_readline=": Both termcap and ncurses disabled" smr_ARG_WITHLIB(termcap, , to accomplish readline) AH_TEMPLATE([HAVE_READLINE],[Define if readline is available.]) if test ! x"$with_termcap" = xno; then # Forget cached values, so user can re-run configure $UNSET ac_cv_header_readline_history_h $UNSET ac_cv_lib_readline_readline AC_MSG_CHECKING([with termcap]) smr_CHECK_LIB(readline, , line editing/history, readline, readline/history.h, $termcap_LIBS) if test ! x"$readline_LIBS" = x; then with_readline=yes readline_LIBS="$readline_LIBS $termcap_LIBS" AC_DEFINE(HAVE_READLINE) fi fi smr_ARG_WITHLIB(ncurses, , to accomplish readline) if test ! x"$with_ncurses" = xno && test x"$readline_LIBS" = x; then # We couldn't use readline with termcap; try with ncurses? # Doesn't this seem a hacky way to do this?? # unset cached values from last check... $UNSET ac_cv_header_readline_history_h $UNSET ac_cv_lib_readline_readline AC_MSG_CHECKING([with ncurses]) dnl We can not call smr_CHECK_LIB twice here without having the usage twice. dnl old_LIBS=$LIBS dnl AC_CHECK_LIB(readline, readline, , , $ncurses_LIBS) dnl LIBS=$old_LIBS dnl if test x"$ac_cv_lib_readline_readline" = xyes; then dnl AC_CHECK_HEADERS(readline/history.h) dnl if test x"$ac_cv_header_readline_history_h" = xyes; then dnl with_readline=yes dnl readline_LIBS="$readline_LIBS $ncurses_LIBS" dnl AC_DEFINE(HAVE_READLINE) dnl fi dnl fi smr_CHECK_LIB(readline, , line editing/history, readline, readline/history.h, $ncurses_LIBS) if test ! x"$readline_LIBS" = x; then with_readline=yes readline_LIBS="$readline_LIBS $ncurses_LIBS" AC_DEFINE(HAVE_READLINE) fi fi dnl We need to check if we have GNU readline or BSD editline AH_TEMPLATE([HAVE_GNU_READLINE],[Define if readline has full GNU interface]) if test x"$with_readline" = xyes; then AC_CHECK_LIB(readline, append_history, AC_DEFINE(HAVE_GNU_READLINE), [], $readline_LIBS) fi AC_SUBST(readline_LIBS) AC_SUBST(readline_CFLAGS) # Check if Xsetlocale() is available or not. AH_TEMPLATE([X_LOCALE],[Enables to use setlocale() provided by X]) AC_CHECK_LIB(X11, _Xsetlocale, AC_DEFINE(X_LOCALE),, $X_LIBS -lX11) # Check if Xsetlocale() is available or not. AH_TEMPLATE([HAVE_XOUTPUT_METHOD],[Enable X output method]) AC_CHECK_LIB(X11, XOpenOM, AC_DEFINE(HAVE_XOUTPUT_METHOD),, $X_LIBS -lX11) # ******** iconv with_iconv=no with_iconv_type=no with_lib_iconv=no with_sys_iconv=no problem_iconv=": Explicitly disabled" AC_ARG_ENABLE(iconv, AS_HELP_STRING([--disable-iconv], [disable support for iconv character conversion]), [ac_cv_iconv="$enableval"], [ac_cv_iconv="yes"]) AH_TEMPLATE([USE_LIBICONV], [define if we use libiconv (not needed in general: for example iconv is native with recent glibc)]) AH_TEMPLATE([HAVE_ICONV], [Define if iconv (in the libc) or libiconv is available]) if test ! x"$ac_cv_iconv" = xno; then # * first check for gnu libiconv $UNSET ac_cv_header_libiconv_h $UNSET ac_cv_lib_libiconv_libiconv_open smr_CHECK_LIB( iconv, , if not found sys iconv is used, libiconv_open, iconv.h) if test ! x"$iconv_LIBS" = x; then AC_DEFINE(USE_LIBICONV) with_lib_iconv=yes fi AC_SUBST(iconv_LIBS) AC_SUBST(iconv_CFLAGS) # * check for system iconv AC_CHECK_FUNC(iconv_open, with_sys_iconv=yes) if test x"$with_lib_iconv" = xyes && test x"$with_sys_iconv" = xyes; then AC_MSG_WARN([*** Both system iconv and libiconv found: use libiconv]) AC_MSG_WARN([*** Use --with-iconv-library=no to use the system iconv]) fi # * libiconv found check for libcharset to get the good iconv charset if test x"$with_lib_iconv" = xyes; then CHECK_LIBCHARSET fi test x"$with_lib_iconv" = xyes -o x"$with_sys_iconv" = xyes && with_iconv=yes && problem_iconv="" test x"$with_lib_iconv" = xyes && with_iconv_type="yes (libiconv)" test x"$with_sys_iconv" = xyes && with_iconv_type="yes (from C library)" if test x"$with_iconv" = xno; then AC_MSG_WARN([*** ]) AC_MSG_WARN([*** No iconv() implementation found in C library or libiconv]) AC_MSG_WARN([*** Please install libiconv ftp://ftp.gnu.org/pub/gnu/libiconv/]) AC_MSG_WARN([*** ]) fi if test x"$with_iconv" = xyes; then AC_DEFINE(HAVE_ICONV) ICONV_SECOND_ARG fi fi AH_VERBATIM([_HAVE_LIBCHARSET], [#ifdef USE_LIBICONV /* define to use locale_charset in the place of nl_langinfog if libiconv * is used */ #undef HAVE_LIBCHARSET #endif]) # ******** nl_langinfo and CODESET AH_TEMPLATE([HAVE_CODESET],[Have nl_langinfo (CODESET)]) AC_MSG_CHECKING([for nl_langinfo (CODESET)]) AC_TRY_COMPILE([#include #include ], [char *codeset = nl_langinfo(CODESET); setlocale(LC_CTYPE, "");], AC_DEFINE(HAVE_CODESET) have_codeset=yes, have_codeset=no) AC_MSG_RESULT($have_codeset) # ********* fribidi AC_ARG_ENABLE(bidi, AS_HELP_STRING([--disable-bidi],[disable bi-directional text support]), [ if test x"$enableval" = xyes; then with_bidi="yes, check" else with_bidi="no" problem_bidi=": Explicitly disabled" fi ], [ with_bidi="not specified, check" ] ) fribidi_min_version=0.19.2 if test ! x"$with_bidi" = xno; then AC_ARG_WITH(fribidi-bindir, AS_HELP_STRING([--with-fribidi-bindir=DIR], [directory of fribidi-config if not in PATH]), FRIBIDI_BINDIR="$withval", FRIBIDI_BINDIR=".") if test ! x"$PKG_CONFIG" = x && $PKG_CONFIG --exists "fribidi >= $fribidi_min_version"; then FRIBIDI_CONFIG="$PKG_CONFIG fribidi" else AC_PATH_PROG(FRIBIDI_CONFIG, fribidi-config,, [$FRIBIDI_BINDIR:$PATH]) fi if test x"$FRIBIDI_CONFIG" = x; then with_bidi=no problem_bidi=": pkgconfig fribidi: fribidi version >= $fribidi_min_version needed." else Bidi_CFLAGS=`$FRIBIDI_CONFIG --cflags` Bidi_LIBS=`$FRIBIDI_CONFIG --libs` AC_CHECK_LIB(fribidi, fribidi_log2vis, with_bidi=yes; problem_bidi=, with_bidi=no; problem_bidi=": No good libs via $FRIBIDI_CONFIG", [$Bidi_LIBS $Bidi_CFLAGS]) fi fi if test ! x"$with_bidi" = xno; then fribidi_in_path=yes ac_save_LIBS="$LIBS" LIBS="$LIBS $Bidi_LIBS" AC_TRY_RUN([#include #include int main() { FriBidiChar *logical_unicode_str = (FriBidiChar *)malloc((4 + 1) * sizeof(FriBidiChar)); fribidi_charset_to_unicode( fribidi_parse_charset("iso8859-8"), "test", 4, logical_unicode_str); return 0; } ], [:], [fribidi_in_path=no]) LIBS="$ac_save_LIBS" if test ! x"$fribidi_in_path" = xyes; then ac_save_CFLAGS="$CFLAGS" ac_save_LIBS="$LIBS" CFLAGS="$CFLAGS $Bidi_CFLAGS" LIBS="$LIBS $Bidi_LIBS" AC_TRY_RUN([#include #include int main() { FriBidiChar *logical_unicode_str = (FriBidiChar *)malloc((4 + 1) * sizeof(FriBidiChar)); fribidi_charset_to_unicode( fribidi_parse_charset("iso8859-8"), "test", 4, logical_unicode_str); return 0; } ], [:], [with_bidi=no; problem_bidi=": Bad fribidi version, see config.log"]) CFLAGS="$ac_save_CFLAGS" LIBS="$ac_save_LIBS" fi if test ! x"$fribidi_in_path" = xno; then Bidi_CFLAGS= Bidi_LIBS=-lfribidi fi fi AH_TEMPLATE([HAVE_BIDI],[Define if fribidi library is used.]) AH_TEMPLATE([FRIBIDI_CHARSET_SPELLING], [Support fribidi-0.10.4 and older with "CHARSET" spelling.]) if test x"$with_bidi" = xno; then Bidi_CFLAGS= Bidi_LIBS= else AC_DEFINE(HAVE_BIDI) AC_TRY_RUN([#include int main(int c, char **v) { return FRIBIDI_CHARSET_NOT_FOUND * 0; } ], [AC_DEFINE(FRIBIDI_CHARSET_SPELLING)]) fi AH_VERBATIM([_FRIBIDI_CHARSET_SPELLING], [#ifdef FRIBIDI_CHARSET_SPELLING # define FRIBIDI_CHAR_SET_NOT_FOUND FRIBIDI_CHARSET_NOT_FOUND #endif]) AC_SUBST(Bidi_LIBS) AC_SUBST(Bidi_CFLAGS) # ********* perllib with_perllib="yes" problem_perllib="" FVWM_PERLLIB=perllib AC_ARG_ENABLE(perllib, AS_HELP_STRING([--disable-perllib],[disable installing fvwm perl library]), [ if test x"$enableval" = xno; then with_perllib="no" problem_perllib=": Explicitly disabled" FVWM_PERLLIB="" fi ], ) AC_SUBST(FVWM_PERLLIB) # ******* gettext ALL_LINGUAS="ar da de fr sv_SE zh_CN ru es" FVWM_DOMAIN="fvwm" FVWMSCRIPT_DOMAIN="FvwmScript" ALL_DOMAINS="$FVWM_DOMAIN $FVWMTASKBAR_DOMAIN $FVWMSCRIPT_DOMAIN" AC_SUBST(ALL_LINGUAS) AC_SUBST(FVWM_DOMAIN) AC_SUBST(FVWMTASKBAR_DOMAIN) AC_SUBST(FVWMSCRIPT_DOMAIN) AC_SUBST(ALL_DOMAINS) LOCALEDIR="$FVWM_DATADIR/locale" with_gettext="yes" problem_gettext="" AC_ARG_ENABLE(nls, AS_HELP_STRING([--disable-nls],[do not use Native Language Support]), [ if test x"$enableval" = xno; then with_gettext="no" problem_gettext=": Explicitly disabled" fi ], ) AH_TEMPLATE([HAVE_NLS], [Define to 1 if translation of program messages to the user's native language is requested.]) if test ! x"$with_gettext" = xno; then AM_GNU_FGETTEXT if test x"$USE_NLS" = "xyes"; then AC_DEFINE(HAVE_NLS, 1) else with_gettext="no" problem_gettext=": Failed to detected GNU gettext" fi else USE_NLS=no fi # libs and buil AC_SUBST(intl_LIBS) AC_SUBST(intl_CFLAGS) AC_SUBST(USE_NLS) AC_SUBST(POSUB) AC_SUBST(LOCALEDIR) AC_SUBST(MKINSTALLDIRS) # programs for devel AC_SUBST(XGETTEXT) AC_SUBST(GMSGFMT) AC_SUBST(MSGMERGE) AC_SUBST(MSGFMT) AC_SUBST(MSGUNIQ) #catalogs AC_SUBST(INST_LINGUAS) AC_SUBST(CATALOGS) AC_SUBST(POFILES) AC_SUBST(GMOFILES) AC_SUBST(UPDATEPOFILES) AC_SUBST(DUMMYPOFILES) AC_SUBST(CATOBJEXT) # Check for REQUIRED headers and functions before going any # further. # The module interface uses variadic functions for message passing. AC_CHECK_HEADERS(stdarg.h) AC_CHECK_FUNCS(vfprintf) if test x$ac_cv_header_stdarg_h = xno -o \ $ac_cv_func_vfprintf = no; then AC_MSG_ERROR([stdarg.h and vfprintf required]) fi # For reaping children, fvwm needs either waitpid() or wait3() # Some extra modules may need wait4() too AC_CHECK_FUNCS(waitpid) if test x$ac_cv_func_waitpid = xno; then AC_CHECK_FUNCS(wait3 wait4) if test x$ac_cv_func_wait3 = xno; then AC_MSG_ERROR([Either waitpid or wait3 function is required]) fi fi # C89/C99 signal handling AC_CHECK_FUNCS(sigsetjmp siglongjmp) # Look harder for a C preprocessor for FvwmCpp AC_PATH_PROG(FVWM_CPP, cpp, no, $PATH:/lib:/usr/lib:/usr/ccs/lib) if test x"$FVWM_CPP" = xno; then FVWM_CPP= AC_MSG_WARN([cannot locate a C preprocessor: run FvwmCpp with -cppprog]) fi dnl FIXME: make sure the cpp we found actually works... # Finish checking for programs. AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_MAKE_SET AC_PROG_RANLIB dnl lex+yacc now only needed for FvwmScript developers when syntax is changed dnl AM_PROG_LEX dnl AC_PROG_YACC # Checks for header files. AC_HEADER_STDC AC_HEADER_SYS_WAIT AC_CHECK_HEADERS(stdlib.h fcntl.h limits.h malloc.h string.h memory.h unistd.h) AC_CHECK_HEADERS(stdint.h inttypes.h) AC_CHECK_HEADERS(getopt.h sys/select.h sys/systeminfo.h sys/time.h) # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_C_INLINE AC_TYPE_OFF_T AC_TYPE_PID_T AC_TYPE_SIZE_T AC_HEADER_TIME dnl AC_STRUCT_TM AC_TYPE_SIGNAL AC_TYPE_INT16_T AC_TYPE_UINT16_T # Checks for library functions. AC_FUNC_STRFTIME AC_FUNC_SETPGRP AC_CHECK_FUNCS(gettimeofday mkfifo putenv setvbuf socket waitpid) AC_CHECK_FUNCS(strdup strstr strtol memmove memcpy strchr sysconf uname div) AC_CHECK_FUNCS(sigaction siginterrupt getpwuid) AC_CHECK_FUNCS(setpgrp setpgid) AC_CHECK_FUNCS(lstat) pds_CHECK_TYPE(sig_atomic_t, int, [#include ], [Specify a type for sig_atomic_t if it's not available.]) if test x$ac_cv_func_setvbuf = xyes; then AC_FUNC_SETVBUF_REVERSED fi AC_FUNC_SELECT if test ! x"$ac_cv_func_select" = xyes; then AC_MSG_ERROR([select required]) fi # check for mkstemp, see the discution on this subject on the fvwm workers # list (2001-02-16 and 2001-02-24) AM_SAFETY_CHECK_MKSTEMP # ********* IMLIB, GNOME # Check the availability of gdk-imlib AH_TEMPLATE([GDK_IMLIB],[Define if gdk-imlib is used]) AM_PATH_GDK_IMLIB(1.8.0, AC_DEFINE(GDK_IMLIB)) if test x"$no_imlib" = x; then with_gdkimlib=yes problem_gdkimlib="" else with_gdkimlib=no problem_gdkimlib=": Failed on gdk-imlib, see config.log" fi # Define some compatibility macros needed for config.h. mg_DEFINE_IF_NOT([#include ], [defined XK_Page_Up && defined XK_Page_Down], [COMPAT_OLD_KEYSYMDEF], [$X_CFLAGS], [Old AIX systems (3.2.5) don't define some common keysyms.]) AH_VERBATIM([_COMPAT_OLD_KEYSYMDEF], [#ifdef COMPAT_OLD_KEYSYMDEF # define XK_Page_Up XK_Prior # define XK_Page_Down XK_Next #endif]) if test x"$with_stroke" = xyes; then mg_DEFINE_IF_NOT([#include ], [defined STROKE_MAX_SEQUENCE], [COMPAT_OLD_LIBSTROKE], [$stroke_CFLAGS], [Old libstroke <= 0.4 does not use STROKE_ prefix for constants.]) fi AH_VERBATIM([_COMPAT_OLD_LIBSTROKE], [#ifdef COMPAT_OLD_LIBSTROKE /* currently we only use one constant */ # define STROKE_MAX_SEQUENCE MAX_SEQUENCE #endif]) # Allow building with dmalloc. Do this last to avoid screwing up any # other checks above. case "$ac_cv_dmalloc" in yes) AC_CHECK_HEADERS(dmalloc.h) AC_CHECK_LIB(dmalloc, dmalloc_shutdown) CPPFLAGS="$CPPFLAGS -DDMALLOC_FUNC_CHECK" ;; esac # Allow building with efence. case "$ac_cv_efence" in yes) AC_CHECK_LIB(efence, malloc) ;; esac # some explicit definitions for config.h file AH_VERBATIM([_ZEND_EXPLICIT_DEFINITIONS], [ /** * The next few defines are options that are only changed from their values * shown here on systems that _don't_ use the configure script. **/ /* Enable tests for missing too many XEvents. Usually you want this. */ #define WORRY_ABOUT_MISSED_XEVENTS 1 /* Define if the X11 ConnectionNumber is actually a file descriptor. */ #define HAVE_X11_FD 1 /* Define if fork() has unix semantics. On VMS, no child process is created until after a successful exec(). */ #define FORK_CREATES_CHILD 1 /* Suffix for executable filenames; NULL if no extension needed. */ #define EXECUTABLE_EXTENSION NULL /* Define to remove the extension from executable pathnames before calling exec(). */ #undef REMOVE_EXECUTABLE_EXTENSION /* Enables the "MiniIcon" Style option to specify a small pixmap which * can be used as one of the title-bar buttons, shown in window list, * utilized by modules, etc. Requires PIXMAP_BUTTONS to be defined * (see below). */ /* #undef MINI_ICONS */ /* NOTE: hard coded to 1 */ #if 1 #define FMiniIconsSupported 1 #else #define FMiniIconsSupported 0 #endif #if RETSIGTYPE != void #define SIGNAL_RETURN return 0 #else #define SIGNAL_RETURN return #endif /* Allow GCC extensions to work, if you have GCC. */ #ifndef __attribute__ /* This feature is available in gcc versions 2.5 and later. */ # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__ # define __attribute__(x) # endif /* The __-protected variants of `format' and `printf' attributes * are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) # define __format__ format # define __printf__ printf # endif #endif #ifdef HAVE_STRING_H # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_MEMORY_H # include #endif #ifdef HAVE_STDLIB_H # include #endif #if defined (HAVE_MALLOC_H) && !defined (__FreeBSD__) && !defined (__OpenBSD__) && !defined(__NetBSD__) # include #endif #ifdef HAVE_FCNTL_H # include #endif #ifndef HAVE_STRCHR # define strchr(_s,_c) index((_s),(_c)) # define strrchr(_s,_c) rindex((_s),(_c)) #endif #ifndef HAVE_MEMCPY # define memcpy(_d,_s,_l) bcopy((_s),(_d),(_l)) #endif #ifndef HAVE_MEMMOVE # define memmove(_d,_s,_l) bcopy((_s),(_d),(_l)) #endif #if HAVE_SYS_TYPES_H # include #endif #if HAVE_UNISTD_H # include #endif #ifndef min # define min(a,b) (((a)<(b)) ? (a) : (b)) #endif #ifndef max # define max(a,b) (((a)>(b)) ? (a) : (b)) #endif #ifndef abs # define abs(a) (((a)>=0)?(a):-(a)) #endif #include "libs/defaults.h" #ifndef FEVENT_C #include #include #include "libs/FEvent.h" #endif #ifndef O_NOFOLLOW #define O_NOFOLLOW 0 #endif #ifdef HAVE_LSTAT #define DO_USE_LSTAT 1 #define fvwm_lstat(x,y) lstat(x,y) #else #define DO_USE_LSTAT 0 #define fvwm_lstat(x,y) -1 #endif #ifdef HAVE_X11_XKBLIB_H #include #define fvwm_KeycodeToKeysym(d, k, l, g) \ (XkbKeycodeToKeysym((d), (k), (g), (l))) #else #define fvwm_KeycodeToKeysym(d, k, x, i) (XKeycodeToKeysym((d), (k), (i))) #endif /* A macro that touches a variable in a compiler independent way to suppress * warnings. */ #define SUPPRESS_UNUSED_VAR_WARNING(x) \ do { void *p; p = (void *)&x; (void)p; } while (0); ]) # mainly for fvwm-config AC_SUBST(with_bidi) AC_SUBST(with_gdkimlib) AC_SUBST(with_gettext) AC_SUBST(with_iconv) AC_SUBST(with_perllib) AC_SUBST(with_png) AC_SUBST(with_rsvg) AC_SUBST(with_readline) AC_SUBST(with_rplay) AC_SUBST(with_shape) AC_SUBST(with_shm) AC_SUBST(with_sm) AC_SUBST(with_stroke) AC_SUBST(with_xcursor) AC_SUBST(with_xft) AC_SUBST(with_xinerama) AC_SUBST(with_xrender) AC_SUBST(with_xpm) dnl with autoconf <2.60 this is needed AC_SUBST(datarootdir) AC_SUBST(docdir) AC_OUTPUT( Makefile libs/Makefile fvwm/Makefile modules/Makefile dnl bin/fvwm-bug.1 bin/fvwm-config.1 bin/fvwm-convert-2.6.1 bin/fvwm-menu-desktop.1 dnl bin/fvwm-menu-directory.1 dnl bin/fvwm-menu-headlines.1 dnl bin/fvwm-menu-xlock.1 dnl bin/fvwm-perllib.1 bin/fvwm-root.1 modules/FvwmAnimate/FvwmAnimate.1 modules/FvwmAuto/FvwmAuto.1 modules/FvwmBacker/FvwmBacker.1 modules/FvwmBanner/FvwmBanner.1 modules/FvwmButtons/FvwmButtons.1 modules/FvwmCommand/FvwmCommand.1 modules/FvwmConsole/FvwmConsole.1 modules/FvwmConsole/FvwmConsoleC.pl.1 modules/FvwmCpp/FvwmCpp.1 modules/FvwmEvent/FvwmEvent.1 modules/FvwmForm/FvwmForm.1 modules/FvwmIconMan/FvwmIconMan.1 modules/FvwmIdent/FvwmIdent.1 modules/FvwmM4/FvwmM4.1 modules/FvwmPager/FvwmPager.1 dnl modules/FvwmPerl/FvwmPerl.1 modules/FvwmProxy/FvwmProxy.1 modules/FvwmRearrange/FvwmRearrange.1 modules/FvwmScript/FvwmScript.1 dnl modules/FvwmWindowMenu/FvwmWindowMenu.1 dnl bin/Makefile bin/fvwm-config bin/fvwm-bug bin/fvwm-perllib bin/fvwm-menu-xlock bin/fvwm-menu-directory bin/fvwm-menu-desktop bin/fvwm-menu-headlines bin/fvwm-convert-2.6 dnl utils/Makefile perllib/Makefile perllib/General/Makefile perllib/FVWM/Makefile perllib/FVWM/Module/Makefile perllib/FVWM/Tracker/Makefile perllib/FVWM/Module.pm default-config/Makefile doc/fvwm.ent doc/footer.html doc/Makefile doc/fvwm/Makefile doc/commands/Makefile doc/docbook-xml/Makefile doc/docbook-xml/ent/Makefile doc/docbook-xsl/Makefile doc/docbook-xsl/common/Makefile doc/docbook-xsl/manpages/Makefile doc/docbook-xsl/profiling/Makefile doc/docbook-xsl/highlighting/Makefile doc/docbook-xsl/lib/Makefile doc/docbook-xsl/html/Makefile doc/images/Makefile doc/images/svg_rendering/Makefile docs/Makefile tests/Makefile tests/hints/Makefile po/Makefile dnl modules/FvwmAnimate/Makefile modules/FvwmAuto/Makefile modules/FvwmBacker/Makefile modules/FvwmBanner/Makefile modules/FvwmButtons/Makefile modules/FvwmCommand/Makefile modules/FvwmCommandS/Makefile modules/FvwmCommand/scripts/Makefile modules/FvwmConsole/Makefile modules/FvwmConsole/FvwmConsoleC.pl modules/FvwmCpp/Makefile modules/FvwmEvent/Makefile modules/FvwmForm/Makefile modules/FvwmIconMan/Makefile modules/FvwmIdent/Makefile modules/FvwmM4/Makefile modules/FvwmPager/Makefile modules/FvwmPerl/Makefile modules/FvwmPerl/FvwmPerl modules/FvwmProxy/Makefile modules/FvwmRearrange/Makefile modules/FvwmScript/Makefile modules/FvwmScript/Scripts/Makefile modules/FvwmScript/Widgets/Makefile ) # --------------------------------------------------------------------------- # Original config.status is patched to make generated scripts executable. sed 's/> $ac_file/> $ac_file; test x"`head -1 $ac_file | cut -c1-2`" = x"#!" \&\& chmod a+rx $ac_file/' config.status-t && \ mv config.status-t config.status chmod +x config.status # --------------------------------------------------------------------------- # --------------------------------------------------------------------------- cat >config.status-t <>config.status-t && \ mv config.status-t config.status chmod +x config.status # --------------------------------------------------------------------------- eval my_bindir="`eval echo ${bindir}`" eval my_mandir="`eval echo ${mandir}`" eval my_moddir="`eval echo ${FVWM_MODULEDIR}`"; eval my_moddir="$my_moddir" eval my_datdir="`eval echo ${FVWM_DATADIR}`" eval my_docdir="`eval echo ${FVWM_DOCDIR}`" eval my_plldir="`eval echo ${FVWM_PERLLIBDIR}`" test x"$FVWM_PERLLIB" = x && my_plldir="(Not installed) $my_plldir" eval my_localedir="`eval echo ${LOCALEDIR}`" test x"$USE_NLS" = xno && my_localedir="(Not installed) $my_localdir" echo " Fvwm Configuration: Version: $VERSION$VERSIONINFO Executables: $my_bindir Man pages: $my_mandir Modules: $my_moddir Data files: $my_datdir Doc files: $my_docdir Perl lib: $my_plldir Locale msg: $my_localedir $INST_LINGUAS With Asian bi-direct. text support? $with_bidi$problem_bidi With Gettext Native Lang support? $with_gettext$problem_gettext With Iconv support? $with_iconv_type$problem_iconv With Mouse strokes (gestures)? $with_stroke$problem_stroke With ReadLine sup. in FvwmConsole? $with_readline$problem_readline With RPlay support in FvwmEvent? $with_rplay$problem_rplay With Shaped window support? $with_shape$problem_shape With Shared memory for XImage? $with_shm$problem_shm With Session Management support? $with_sm$problem_sm With SVG image support? $with_rsvg$problem_rsvg With Xcursor support? $with_xcursor$problem_xcursor With Xinerama multi-head support? $with_xinerama$problem_xinerama With Xft anti-alias font support? $with_xft$problem_xft With XPM image support? $with_xpm$problem_xpm With Xrender image support? $with_xrender$problem_xrender Build man pages? $with_mandoc$problem_mandoc Build HTML documentation? $with_htmldoc$problem_htmldoc " case "$with_xinerama_emulation" in yes) echo " Xinerama emulation enabled." ;; esac case "$ac_cv_dmalloc" in yes) echo " DMALLOC heap debugging library enabled." ;; esac case "$ac_cv_efence" in yes) echo " EFENCE debugging library enabled." ;; esac fvwm-2.7.0/perllib/0000755000175000017500000000000014324316055011134 500000000000000fvwm-2.7.0/perllib/General/0000755000175000017500000000000014324316055012511 500000000000000fvwm-2.7.0/perllib/General/Parse.pm0000644000175000017500000001226314147024700014041 00000000000000# Copyright (c) 2002-2009, Mikhael Goikhman # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see: package General::Parse; use strict; use vars qw(@ISA @EXPORT); require Exporter; @ISA = qw(Exporter); @EXPORT = qw( get_token cut_token get_tokens cut_tokens eqi nei ); # currently backslashes are ignored and this is a bit buggy sub get_token ($) { my $line = shift; my $token; $line =~ s/^\s+//; my $quote = '\s'; $quote = substr($line, 0, 1) if $line =~ /^["'`]/; $line =~ s/^$quote//; if ($line =~ /^(.*?)$quote\s*(.*)$/) { $token = $1; $line = $2; } elsif ($line eq "") { $token = undef; $line = ""; } else { $token = $line; $line = ""; } return wantarray ? ($token, $line) : $token; } # returns the next quoted token, modifies the parameter (ref to line) sub cut_token ($) { my $line_ref = shift; my ($token, $rest) = get_token($$line_ref); $$line_ref = $rest; return $token; } sub cut_tokens ($$) { my $line_ref = shift; my $limit = shift; my @tokens = (); $$line_ref =~ s/^\s+//; while ($$line_ref ne "" && $limit-- > 0) { push @tokens, cut_token($line_ref); } return wantarray ? @tokens : \@tokens; } sub get_tokens ($;$) { my $line = shift; my $limit = shift || 1000; return cut_tokens(\$line, $limit); } sub eqi ($$) { my ($a, $b) = @_; return lc($a) eq lc($b); } sub nei ($$) { my ($a, $b) = @_; return lc($a) ne lc($b); } # ---------------------------------------------------------------------------- =head1 NAME General::Parse - parsing functions =head1 SYNOPSIS use General::Parse; my $string = q{Some "not very long" string of 6 tokens.}; my $token1 = cut_token(\$string); # $token1 = "Some"; my ($token2, $token3) = cut_tokens(\$string, 2); my @subtokens = get_tokens($token2); # ("not", "very", "long") my $subtoken1 = get_token($token2); # the same as $subtokens[0] my $ending_array_ref = get_tokens($string); # ["of", "6", "tokens."] =head1 DESCRIPTION This package may be used for parsing a string into tokens (quoted words). =head1 FUNCTIONS =head2 get_token =over 4 =item description Returns the first token of the given string without changing the string itself. If the string is empty or consists of only spaces the returned token is undef. If the caller expects a scalar - the token is returned. If it expects an array - 2 values returned, the token and the rest of the string. =item parameters String (scalar) to be parsed. =item returns Token (scalar). Or, in array context, array of 2 scalars: token and the rest of string. =back =head2 cut_token =over 4 =item description Returns the first token of the given string, the input string is cut to contain tokens starting from the second one. If the string is empty or consists of only spaces the returned token is undef and the string is changed to an empty string. =item parameters String (scalar) to be parsed. =item returns Token (scalar). =back =head2 get_tokens =over 4 =item description Returns all or the requested number of tokens of the given string without changing the string itself. The returned array may contain less tokens than requested if the string is too short. Particularly, the returned array is empty if the string is empty or consists of only spaces. If the caller expects a scalar - a reference to the token array is returned. If it expects an array - the token array is returned. =item parameters String (scalar) to be parsed, and optional limit (integer) for number of returned tokens. =item returns Tokens (array of scalars or array ref of scalars depending on context). =back =head2 cut_tokens =over 4 =item description Returns the requested number of tokens of the given string, the string is cut to contain the tokens starting from the first non returned token. The returned array may contain less tokens than requested if the string is too short. Particularly, the returned array is empty if the string is empty or consists of only spaces. If the caller expects a scalar - a reference to the token array is returned. If it expects an array - the token array is returned. =item parameters String (scalar) to be parsed, and limit (integer) for number of returned tokens. =item returns Tokens (array of scalars or array ref of scalars depending on context). =back =head2 eqi =over 4 =item description Similar to B, but case-insensitive, gets 2 strings, returns boolean. =back =head2 nei =over 4 =item description Similar to B, but case-insensitive, gets 2 strings, returns boolean. =back =head1 AUTHOR Mikhael Goikhman =cut # ============================================================================ 1; fvwm-2.7.0/perllib/General/Makefile.in0000644000175000017500000004147114324315776014516 00000000000000# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 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 = perllib/General ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.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)$(configdir)" DATA = $(config_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALL_DOMAINS = @ALL_DOMAINS@ ALL_LINGUAS = @ALL_LINGUAS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR_FLAGS = @AR_FLAGS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ Bidi_CFLAGS = @Bidi_CFLAGS@ Bidi_LIBS = @Bidi_LIBS@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DOC_COMMANDS = @DOC_COMMANDS@ DOC_COMMANDS_HTML = @DOC_COMMANDS_HTML@ DOC_COMMANDS_XML = @DOC_COMMANDS_XML@ DOC_COMMANDS_XML_PATH = @DOC_COMMANDS_XML_PATH@ DOC_MODULES = @DOC_MODULES@ DOC_MODULES_HTML = @DOC_MODULES_HTML@ DOC_SECTIONS = @DOC_SECTIONS@ DOC_SECTIONS_XML = @DOC_SECTIONS_XML@ DOC_SECTIONS_XML_PATH = @DOC_SECTIONS_XML_PATH@ DUMMYPOFILES = @DUMMYPOFILES@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FC_CFLAGS = @FC_CFLAGS@ FC_CONFIG = @FC_CONFIG@ FC_LIBS = @FC_LIBS@ FRIBIDI_CONFIG = @FRIBIDI_CONFIG@ FVWMALTFTP = @FVWMALTFTP@ FVWMALTFTPDIR = @FVWMALTFTPDIR@ FVWMFTP = @FVWMFTP@ FVWMFTPDIR = @FVWMFTPDIR@ FVWMHOMEPAGE = @FVWMHOMEPAGE@ FVWMLIST = @FVWMLIST@ FVWMNAMELONG = @FVWMNAMELONG@ FVWMSCRIPT_DOMAIN = @FVWMSCRIPT_DOMAIN@ FVWMTASKBAR_DOMAIN = @FVWMTASKBAR_DOMAIN@ FVWMWORKERSLIST = @FVWMWORKERSLIST@ FVWMWORKERSLISTLONG = @FVWMWORKERSLISTLONG@ FVWM_CONFDIR = @FVWM_CONFDIR@ FVWM_CPP = @FVWM_CPP@ FVWM_DATADIR = @FVWM_DATADIR@ FVWM_DOCDIR = @FVWM_DOCDIR@ FVWM_DOMAIN = @FVWM_DOMAIN@ FVWM_IMAGEPATH = @FVWM_IMAGEPATH@ FVWM_MODULEDIR = @FVWM_MODULEDIR@ FVWM_PERLLIB = @FVWM_PERLLIB@ FVWM_PERLLIBDIR = @FVWM_PERLLIBDIR@ GDK_IMLIB_CFLAGS = @GDK_IMLIB_CFLAGS@ GDK_IMLIB_LIBS = @GDK_IMLIB_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ IMLIBCONF = @IMLIBCONF@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INST_LINGUAS = @INST_LINGUAS@ ISRELEASED = @ISRELEASED@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOCALEDIR = @LOCALEDIR@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANPAGE_PREAMBLE = @MANPAGE_PREAMBLE@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ MSGUNIQ = @MSGUNIQ@ OBJEXT = @OBJEXT@ 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@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PYTHON = @PYTHON@ RANLIB = @RANLIB@ RELDATELONG = @RELDATELONG@ RELDATENUM = @RELDATENUM@ RELDATESHORT = @RELDATESHORT@ REQUIRED_PERL_VERSION = @REQUIRED_PERL_VERSION@ REQUIRED_PYTHON_VERSION = @REQUIRED_PYTHON_VERSION@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ UPDATEPOFILES = @UPDATEPOFILES@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VERSIONINFO = @VERSIONINFO@ XFT_CFLAGS = @XFT_CFLAGS@ XFT_CONFIG = @XFT_CONFIG@ XFT_LIBS = @XFT_LIBS@ XGETTEXT = @XGETTEXT@ XMKMF = @XMKMF@ XSLTPROC = @XSLTPROC@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Xcursor_CFLAGS = @Xcursor_CFLAGS@ Xcursor_LIBS = @Xcursor_LIBS@ Xft_CFLAGS = @Xft_CFLAGS@ Xft_LIBS = @Xft_LIBS@ Xinerama_CFLAGS = @Xinerama_CFLAGS@ Xinerama_LIBS = @Xinerama_LIBS@ Xrender_CFLAGS = @Xrender_CFLAGS@ Xrender_LIBS = @Xrender_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ iconv_CFLAGS = @iconv_CFLAGS@ iconv_LIBS = @iconv_LIBS@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intl_CFLAGS = @intl_CFLAGS@ intl_LIBS = @intl_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ png_CFLAGS = @png_CFLAGS@ png_LIBS = @png_LIBS@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ readline_CFLAGS = @readline_CFLAGS@ readline_LIBS = @readline_LIBS@ rplay_CFLAGS = @rplay_CFLAGS@ rplay_LIBS = @rplay_LIBS@ rsvg_CFLAGS = @rsvg_CFLAGS@ rsvg_LIBS = @rsvg_LIBS@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ stroke_CFLAGS = @stroke_CFLAGS@ stroke_LIBS = @stroke_LIBS@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ with_bidi = @with_bidi@ with_gdkimlib = @with_gdkimlib@ with_gettext = @with_gettext@ with_iconv = @with_iconv@ with_perllib = @with_perllib@ with_png = @with_png@ with_readline = @with_readline@ with_rplay = @with_rplay@ with_rsvg = @with_rsvg@ with_shape = @with_shape@ with_shm = @with_shm@ with_sm = @with_sm@ with_stroke = @with_stroke@ with_xcursor = @with_xcursor@ with_xft = @with_xft@ with_xinerama = @with_xinerama@ with_xpm = @with_xpm@ with_xrender = @with_xrender@ xpm_CFLAGS = @xpm_CFLAGS@ xpm_LIBS = @xpm_LIBS@ configdir = @FVWM_PERLLIBDIR@/General config_DATA = FileSystem.pm Parse.pm EXTRA_DIST = $(config_DATA) all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(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) --foreign perllib/General/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign perllib/General/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: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-configDATA: $(config_DATA) @$(NORMAL_INSTALL) @list='$(config_DATA)'; test -n "$(configdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(configdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(configdir)" || 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)$(configdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(configdir)" || exit $$?; \ done uninstall-configDATA: @$(NORMAL_UNINSTALL) @list='$(config_DATA)'; test -n "$(configdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(configdir)'; $(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)$(configdir)"; 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 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-configDATA 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 pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-configDATA .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic cscopelist-am \ ctags-am distclean distclean-generic distdir dvi dvi-am html \ html-am info info-am install install-am install-configDATA \ 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-generic pdf \ pdf-am ps ps-am tags-am uninstall uninstall-am \ uninstall-configDATA .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: fvwm-2.7.0/perllib/General/FileSystem.pm0000644000175000017500000005746514147024700015070 00000000000000# Copyright (C) 1998-2009, Mikhael Goikhman # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see: package General::FileSystem; require 5.004; use strict; use vars qw(@ISA @EXPORT); require Exporter; @ISA = qw(Exporter); @EXPORT = qw( load_file save_file append_file remove_file copy_file move_file make_dir make_path clean_dir remove_dir copy_dir move_dir list_filenames find_file find_executable default_dir_perm preserve_stat parse_path get_cwd ); use vars qw($CACHE_FILE_NUM $cache_counter @prev_filenames @prev_file_content_refs); use vars qw($ENABLE_CACHE %NEVER_COPY_FILES %NEVER_REMOVE_FILES); use vars qw($DEFAULT_DIR_PERM $PRESERVED_STAT); use vars qw($DEBUG_ENABLED $ERROR_HANDLER $LOAD_FILE_DIRS $SAVE_FILE_DIR); BEGIN { $ENABLE_CACHE = 0; # this is risky for dynamical files %NEVER_COPY_FILES = ( 'CVS' => 1, 'core' => 1 ); %NEVER_REMOVE_FILES = ( 'CVS' => 1 ); $DEFAULT_DIR_PERM = 0775; $PRESERVED_STAT = 0; # allow these constants to be set directly from outside $ERROR_HANDLER ||= "warn"; # may be "die", "warn", "quiet" or CODE $DEBUG_ENABLED ||= 0; $LOAD_FILE_DIRS ||= [ "." ]; # for non fully qualified files only $SAVE_FILE_DIR ||= "."; # for non fully qualified files only } # ---------------------------------------------------------------------------- =head1 NAME General::FileSystem - file system specific functions =head1 SYNOPSIS use General::FileSystem "-die", "-debug"; # die on errors eval { make_path("/tmp/my-own/dir"); my $file_content_ref = load_file("/etc/issue"); save_file("/tmp/my-own/dir/issue", $file_content_ref); # This is equivalent to the previous two lines, but optimized copy_file("/etc/issue", "/tmp/my-own/dir/issue"); make_dir("/tmp/my-own/dir2", 0711); copy_file("/etc/issue", "/tmp/my-own/dir2/issue"); move_file("/tmp/my-own/dir2/issue", "/tmp/my-own/dir2/issue2"); remove_file("/tmp/my-own/dir2/issue2"); clean_dir("/tmp/my-own/dir2"); # no effect, it's empty already remove_dir("/tmp/my-own"); }; if ($@) { print "File System Error: $@"; }; or just: use General::FileSystem; copy_file("origin.txt", "backup.txt"); =head1 DESCRIPTION This package contains common file operation functions: B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B. On fatal file system errors all functions call the error handler, that may throw exception (die), issue a warning or quietly return undef. You may control this by passing one of the arguments I<-die>, I<-warn> or I<-quiet> in B or by setting C<$ERROR_HANDLER> to one of these values (don't specify a dash in this case). =head1 REQUIREMENTS L, L, L. =head1 FUNCTIONS =cut # ============================================================================ use Cwd; use File::Basename; use File::Copy; sub import ($;$) { my $package = shift; while (@_ && $_[0] =~ /^-/) { local $_ = shift; $ERROR_HANDLER = $1 if /^-(die|warn|quiet)$/i; $DEBUG_ENABLED = $1 if /^-(debug)$/i; } $package->export_to_level(1, @_); } # private function sub call_error_handler ($) { my $msg = shift; die "$msg: [$!]\n" if $ERROR_HANDLER eq "die"; warn "$msg: [$!]\n" if $ERROR_HANDLER eq "warn"; return undef if $ERROR_HANDLER eq "quiet"; &$ERROR_HANDLER($msg) if ref($ERROR_HANDLER) eq "CODE"; return undef; } # private function sub print_log ($) { my $msg = shift; return unless $DEBUG_ENABLED; print STDERR "FileSystem: $msg\n"; } # ---------------------------------------------------------------------------- =head2 load_file =over 4 =item usage $content_ref = load_file($filename) =item description Loads file with given file-name from local filesystem. =item parameters * filename - name of the file to be loaded. =item returns Reference to file content string on success, otherwise either dies or warns and returns undef as configured. =back =cut # ============================================================================ BEGIN { $CACHE_FILE_NUM = 6; $cache_counter = -1; @prev_filenames = ("", "", "", "", "", ""); @prev_file_content_refs = \("", "", "", "", "", ""); } sub load_file ($) { my $filename = shift; foreach (@$LOAD_FILE_DIRS) { if (-f "$_/$filename") { $filename = "$_/$filename"; last; } } print_log("Loading file $filename") if $DEBUG_ENABLED; if ($ENABLE_CACHE) { for (0 .. $CACHE_FILE_NUM-1) { if ($filename eq $prev_filenames[$_] && -r $filename) { print_log("getting from file cache") if $DEBUG_ENABLED; return $prev_file_content_refs[$_]; } } } open(FILE, "<$filename") || return call_error_handler("Can't open $filename"); my $content = join("", ); close(FILE) || return call_error_handler("Can't close $filename"); if ($ENABLE_CACHE) { $cache_counter = ($cache_counter+1) % $CACHE_FILE_NUM; $prev_filenames[$cache_counter] = $filename; $prev_file_content_refs[$cache_counter] = \$content; } return \$content; } # ---------------------------------------------------------------------------- =head2 save_file =over 4 =item description Saves file-content to local filesystem with given file-name. =item usage save_file($filename, \$content); =item parameters * filename - name of the file to be saved into * content_ref - reference to file content string * create_subdirs - optional flag (default is 0 - don't create subdirs) =item returns C<1> on success, otherwise either dies or warns and returns undef as configured. =back =cut # ============================================================================ sub save_file ($$;$) { my ($filename, $content_ref, $create_dirs) = @_; if ($filename !~ m=^[/\\]|\w:\\=) { $filename = "$SAVE_FILE_DIR/$filename"; } print_log("Saving file $filename") if $DEBUG_ENABLED; die("save_file: No SCALAR ref parameter\n") unless ref($content_ref) eq 'SCALAR'; if ($ENABLE_CACHE) { for (0 .. $CACHE_FILE_NUM-1) { $prev_file_content_refs[$_] = $content_ref if $filename eq $prev_filenames[$_]; } } if ($create_dirs) { my $dirname = dirname($filename); make_path($dirname) unless -d $dirname; } open(FILE, ">$filename") || return call_error_handler("Can't open $filename"); print FILE $$content_ref; close(FILE) || return call_error_handler("Can't close $filename"); return 1; } # ---------------------------------------------------------------------------- =head2 append_file =over 4 =item description Appends file-content to local filesystem with given file-name. =item usage append_file($filename, \$appended_content); =item parameters * filename - name of the file to be saved into * appended_content_ref - reference to appended-content string =item returns C<1> on success, otherwise either dies or warns and returns undef as configured. =back =cut # ============================================================================ sub append_file ($$) { my ($filename, $appended_content_ref) = @_; print_log("Append>>file $filename") if $DEBUG_ENABLED; if ($ENABLE_CACHE) { for (0 .. $CACHE_FILE_NUM-1 && -r $filename) { ${$prev_file_content_refs[$_]} .= $$appended_content_ref if $filename eq $prev_filenames[$_]; } } open(FILE, ">>$filename") || return call_error_handler("Can't append to $filename"); print FILE $$appended_content_ref; close(FILE) || return call_error_handler("Can't close $filename"); return 1; } # ---------------------------------------------------------------------------- =head2 remove_file =over 4 =item description Removes all files from given directory. =item usage remove_file($filename); =item parameters * filename - name of the file to be deleted =item returns C<1> on success, otherwise either dies or warns and returns undef as configured. =back =cut # ============================================================================ sub remove_file ($;$) { my $filename = shift; print_log("Removin file $filename") if $DEBUG_ENABLED; unlink($filename) || return call_error_handler("Can't unlink $filename"); return 1; } # ---------------------------------------------------------------------------- =head2 make_dir =over 4 =item description Removes all files from given directory. =item usage make_dir($PREVIEW_DIR); =item parameters * directory to make * optional creating dir permissions (default is $DEFAULT_DIR_PERM) =item returns C<1> on success, otherwise either dies or warns and returns undef as configured. =back =cut # ============================================================================ sub make_dir ($;$) { my $dirname = shift; my $perm = shift || $DEFAULT_DIR_PERM; print_log("Creating dir $dirname, " . sprintf("%o", $perm)) if $DEBUG_ENABLED; mkdir($dirname, $perm) || return call_error_handler("Can't mkdir $dirname"); return 1; } # ---------------------------------------------------------------------------- =head2 make_path =over 4 =item description Removes all files from given directory. =item usage make_path($PUBLISH_DIR); =item parameters * path to make * optional creating dir permissions (default is $DEFAULT_DIR_PERM) =item returns C<1> on success, otherwise either dies or warns and returns undef as configured. =back =cut # ============================================================================ sub make_path ($;$) { my $dirname = shift; my $perm = shift || $DEFAULT_DIR_PERM; print_log("Making path $dirname, " . sprintf("%o", $perm)) if $DEBUG_ENABLED; return 1 if -d $dirname; my $parent_dir = dirname($dirname); local $DEBUG_ENABLED = 0; &make_path($parent_dir, $perm) unless -d $parent_dir; make_dir($dirname, $perm); return 1; } # ---------------------------------------------------------------------------- =head2 copy_file =over 4 =item description Copies a file to another location. =item usage copy_file($from, $to); =item parameters * file name to copy from * file name to copy to =item returns C<1> on success, otherwise either dies or warns and returns undef as configured. =back =cut # ============================================================================ sub copy_file ($$) { my ($src_filename, $dst_filename) = @_; print_log("Copying file $src_filename to $dst_filename") if $DEBUG_ENABLED; # Must manage symbolic links somehow # return if -l $src_filename; copy($src_filename, $dst_filename) or return call_error_handler("Can't copy $src_filename $dst_filename"); if ($PRESERVED_STAT) { my ($device, $inode, $mode) = stat($src_filename); chmod($mode, $dst_filename); } return 1; } # ---------------------------------------------------------------------------- =head2 move_file =over 4 =item description Moves (or renames) a file to another location. =item usage move_file($from, $to); =item parameters * file name to move from * file name to move to =item returns C<1> on success, otherwise either dies or warns and returns undef as configured. =back =cut # ============================================================================ sub move_file ($$) { my ($src_filename, $dst_filename) = @_; print_log("Moving file $src_filename to $dst_filename") if $DEBUG_ENABLED; move($src_filename, $dst_filename) or return call_error_handler("Can't move $src_filename $dst_filename"); return 1; } # ---------------------------------------------------------------------------- =head2 clean_dir =over 4 =item description Removes all files from given directory. =item usage clean_dir($PREVIEW_DIR); =item parameters * directory to clean * optional flag: 0 - don't go recursively, unlink files in first level only 1 - recursively clean subdirs (default) 2 - unlink subdirs 3 - unlink given directory =item returns C<1> on success, otherwise either dies or warns and returns undef as configured. =back =cut # ============================================================================ sub clean_dir ($;$) { my $dirname = shift; my $recursive = shift || 1; die("clean_dir: Unsupported flag $recursive\n") if $recursive > 3 || $recursive < 0; print_log(($recursive != 3 ? "Cleaning" : "Removing") . " dir $dirname " . ["files only", "recursively files only", "recursively", "completely"]->[$recursive]) if $DEBUG_ENABLED; local $DEBUG_ENABLED = 0; my @subdirs = (); my $filenames = list_filenames($dirname); # process files foreach (@$filenames) { next if $NEVER_REMOVE_FILES{$_}; my $filename = "$dirname/$_"; if (-d $filename) { push @subdirs, $filename; } else { unlink("$filename") || return call_error_handler("Can't unlink $filename"); } } # process subdirs map { clean_dir($_, $recursive); rmdir($_) || return call_error_handler("Can't unlink $_") if $recursive == 2; } @subdirs if $recursive; rmdir($dirname) || return call_error_handler("Can't unlink $dirname") if $recursive == 3; return 1; } # ---------------------------------------------------------------------------- =head2 remove_dir =over 4 =item description Entirely removes given directory and its content (if any). This is an alias to C. =item usage remove_dir($TMP_DIR); =item parameters * directory to clean =item returns C<1> on success, otherwise either dies or warns and returns undef as configured. =back =cut # ============================================================================ sub remove_dir ($) { my $dirname = shift; return clean_dir($dirname, 3); } # ---------------------------------------------------------------------------- =head2 copy_dir =over 4 =item description Recursively copies all files and subdirectories inside given directory to new location. Destination directory must not exist. Use: C to remove it before copying. =item usage copy_dir($dir_from, $dir_to); =item parameters * source directory to copy * destination directory to copy to (may not exist) * optional creating dir permissions (default is $DEFAULT_DIR_PERM) =item returns C<1> on success, otherwise either dies or warns and returns undef as configured. =back =cut # ============================================================================ sub copy_dir ($$) { my ($src_dirname, $dst_dirname, $perm) = @_; return call_error_handler("Directory $src_dirname does not exist") unless -d $src_dirname; make_dir($dst_dirname, $perm) unless -d $dst_dirname; print_log("Copying dir $src_dirname to $dst_dirname recursively") if $DEBUG_ENABLED;; local $DEBUG_ENABLED = 0; my $error = 0; my @subdirs = (); my $filenames = list_filenames($src_dirname); # process files foreach (@$filenames) { next if $NEVER_COPY_FILES{$_}; my $src_filename = "$src_dirname/$_"; my $dst_filename = "$dst_dirname/$_"; if (-d $src_filename) { push @subdirs, $_; } elsif (-l $src_filename) { next if "# We ignore links for now! TO FIX!" } else { copy_file($src_filename, $dst_filename) or $error = 1; } } # process subdirs foreach (@subdirs) { my $src_subdirname = "$src_dirname/$_"; my $dst_subdirname = "$dst_dirname/$_"; ©_dir($src_subdirname, $dst_subdirname) or $error = 1; } return call_error_handler("Errors while copying some files/subdirs in $src_dirname to $dst_dirname") if $error; return 1; } # ---------------------------------------------------------------------------- =head2 move_dir =over 4 =item description Moves (or actually renames) a directory to another location. Destination directory must not exist. Use: C to remove it before copying. =item usage move_dir($dir_from, $dir_to); =item parameters * source directory to move from * destination directory to move to (must not exist) =item returns C<1> on success, otherwise either dies or warns and returns undef as configured. =back =cut # ============================================================================ sub move_dir ($$) { my ($src_dirname, $dst_dirname) = @_; print_log("Moving dir $src_dirname to $dst_dirname") if $DEBUG_ENABLED; rename($src_dirname, $dst_dirname) or return call_error_handler("Can't rename $src_dirname $dst_dirname"); return 1; } # ---------------------------------------------------------------------------- =head2 list_filenames =over 4 =item description Returns the file names in the given directory including all types of files (regular, directory, link, other), not including '.' and '..' entries. =item usage # mini file lister $dir = '/home/ftp'; foreach my $file (@{list_filenames($dir)}) { print "File $file\n" if -f "$dir/$file"; print "Dir $file\n" if -d "$dir/$file"; } =item parameters * directory to list (or array ref of directories) * optional flag, 1 means work recursively, the default is 0 =item returns Array ref of scalars (file names) on success. Otherwise either dies or warns and returns undef as configured. =back =cut # ============================================================================ sub list_filenames ($;$) { my $dirname = shift; my $recursive = shift || 0; if (ref($dirname) eq "ARRAY") { my @files = (); foreach (@$dirname) { push @files, &list_filenames($_); } return \@files; } print_log("Listing dir $dirname") if $DEBUG_ENABLED; opendir(DIR, $dirname) || return call_error_handler("Can't opendir $dirname"); my @files = grep { $_ ne '.' && $_ ne '..' } readdir(DIR); closedir(DIR) || return call_error_handler("Can't closedir $dirname"); if ($recursive) { my $i = 0; for (; $i < @files; ) { my $subdir = $files[$i]; if (-d "$dirname/$subdir") { splice(@files, $i, 1, map { "$subdir/$_" } @{&list_filenames("$dirname/$subdir")}); } else { $i++; } } } return \@files; } # ---------------------------------------------------------------------------- =head2 find_file =over 4 =item description Searches for the given file in the given directories. Returns the fully qualified file name. =item parameters * file name to search for * array ref of directories to search in =item returns File name with full path if found, or undef if not found. =back =cut # ============================================================================ sub find_file ($$) { my $filename = shift; my $dirs = shift(); die "find_file: no dirs given\n" unless ref($dirs) eq "ARRAY"; foreach (@$dirs) { my $file_path = "$_/$filename"; return $file_path if -f $file_path; } return undef; } # ---------------------------------------------------------------------------- =head2 find_executable =over 4 =item description Searches for the given executable file in the directories that are in the environmebt variable $PATH or in the additional parameter. Returns the fully qualified file name. =item usage my $gzip_exe = find_executable("gzip", ["/usr/gnu/bin", "/gnu/bin"]); =item parameters * file name to search for (only executables are tested) * optional array ref of extra directories to search in =item returns File name with full path if found, or undef if not found. =back =cut # ============================================================================ sub find_executable ($;$) { my $filename = shift; my $extra_dirs = shift; my @dirs = split(":", $ENV{"PATH"} || ""); if (ref($extra_dirs) eq "ARRAY") { push @dirs, @$extra_dirs; } foreach (@dirs) { my $file_path = "$_/$filename"; return $file_path if -x $file_path; } return undef; } # ---------------------------------------------------------------------------- =head2 default_dir_perm =over 4 =item description This functions changes default directory permissions, used in C, C, C and C functions. The default of this package is 0775. If no parameters specified, the current value is returned. =item usage default_dir_perm(0700); =item parameters * optional default directory permission (integer) =item returns Previous value. =back =cut # ============================================================================ sub default_dir_perm (;$) { return if $^O =~ /Win|DOS/; my $new_value = shift; my $old_value = $DEFAULT_DIR_PERM; if (defined $new_value) { print_log("default_dir_perm = $new_value") if $DEBUG_ENABLED; $DEFAULT_DIR_PERM = $new_value; } return $old_value; } # ---------------------------------------------------------------------------- =head2 preserve_stat =over 4 =item description This functions changes behavior of C and C functions. If 0 is given as a parameter stats will not be preserved. TODO: specify values for diferent preserves: 0 nothing 1 mode file mode (type and permissions) 2 uid numeric user ID of file's owner 4 gid numeric group ID of file's owner 8 atime last access time since the epoch 16 mtime last modify time since the epoch 32 ctime inode change time (NOT creation time!) since the epo The default of this package is 0. If no parameters specified, nothing is set (only current value is returned). =item usage preserve_stat(1); =item parameters * optional flag (currently 0 or 1) =item returns Previous value. =back =cut # ============================================================================ sub preserve_stat (;$) { return if $^O =~ /Win|DOS/; my $new_value = shift; my $old_value = $PRESERVED_STAT; if (defined $new_value) { print_log("preserve_stat = $new_value") if $DEBUG_ENABLED; $PRESERVED_STAT = $new_value; } return $old_value; } # ---------------------------------------------------------------------------- =head2 parse_path =over 4 =item usage my ($dirname, $basename) = parse_path($filename); =item examples # in: "/data/projects/magazine" out: ("/data/projects", "magazine") # in: "/magazine" out: ("", "magazine") # in: "dir/" out: (dir", "") # in: "magazine" out: (".", "magazine") # in: "c:\projects\magazine" out: ("c:\projects", "magazine") # in: "c:\magazine" out: ("c:", "magazine") # in: "c:magazine" out: ("c:.", "magazine") =item description Returns a list of 2 scalars: directory name and base name. All unix and dos file names supported. Note, the rule is this: you can join both scalars using a directory delimiter (slash or backslash) and you will always get the the original (logical) file name. =back =cut # ============================================================================ sub parse_path ($) { my $path = shift; if ($path =~ m=^(.*)[/\\]+([^/\\]*)$=) { return ($1, $2); } else { # support even funny dos form c:file return $path =~ m=^(\w:)(.*)$= ? ($1 . ".", $2) : (".", $path); } } # ---------------------------------------------------------------------------- =head2 get_cwd =over 4 =item usage my $cwd = get_cwd(); =item description Returns the current working directory. =back =cut # ============================================================================ sub get_cwd () { $^O eq "MSWin32" ? Win32::GetCwd() : require "getcwd.pl" && getcwd(); } # ---------------------------------------------------------------------------- =head1 BUGS All global functions and constants in this package should probably be instantiated into a class object. As usual there are pros and cons. =head1 AUTHOR Mikhael Goikhman =cut # ============================================================================ 1; fvwm-2.7.0/perllib/General/Makefile.am0000644000175000017500000000024314147024676014474 00000000000000## Process this file with automake to create Makefile.in configdir = @FVWM_PERLLIBDIR@/General config_DATA = FileSystem.pm Parse.pm EXTRA_DIST = $(config_DATA) fvwm-2.7.0/perllib/FVWM/0000755000175000017500000000000014324316055011713 500000000000000fvwm-2.7.0/perllib/FVWM/create-constants0000755000175000017500000000330714147024700015035 00000000000000#!/bin/sh : ${fvwm_libdir=../../libs} infile=${fvwm_libdir}/Module.h outfile=`dirname $0`/Constants.pm ( \ echo "# Autogenerated from the fvwm sources."; \ echo ""; \ echo "package FVWM::Constants;"; \ echo "use Exporter;"; \ echo "use Config;"; \ echo "@ISA = qw(Exporter);"; \ echo ""; \ ) \ >$outfile ( \ grep "#define M_" $infile; \ grep "#define MX_" $infile | sed 's/ | /|/'; \ grep "#define MAX_MSG_MASK " $infile; \ grep "#define MAX_XMSG_MASK " $infile; \ grep "#define FvwmPacketHeaderSize " $infile | sed 's/FvwmPacketHeaderSize/HEADER_SIZE/'; \ grep "#define START_FLAG " $infile; \ grep "#define ModuleFinishedStartupResponse " $infile | tr ' ' : | sed 's/:ModuleFinishedStartupResponse:\+/ RESPONSE_READY /'; \ grep "#define ModuleUnlockResponse " $infile | tr ' ' : | sed 's/:ModuleUnlockResponse:\+/ RESPONSE_UNLOCK /'; \ ) \ | awk '{ print "use constant " $2 " => " $3 ";" }' \ | tr : ' ' \ >>$outfile ( \ echo "use constant ON_EXIT => '1e20';"; \ echo "use constant INTSIZE => \$Config{longsize};" \ ) \ >>$outfile ( \ grep constant $outfile | cut -d" " -f3 | awk '{ print " " $1 }'; \ ) \ >"$outfile.tmp" ( \ echo '@EXPORT = qw('; \ cat "$outfile.tmp"; \ echo ');' \ ) \ >>$outfile ( \ echo " 1; __END__ =head1 NAME FVWM::Constants - exports fvwm specific constants =head1 DESCRIPTION This class is used to load fvwm constants into your perl script or class. Note, if you use I the constants are automatically exported. So you usually do not need to include this class. =head1 USAGE use FVWM::Constants; =head1 SEE ALSO For more information, see L. =head1 EXPORTED CONSTANTS "; \ cat "$outfile.tmp"; \ ) \ >>$outfile rm "$outfile.tmp" fvwm-2.7.0/perllib/FVWM/Module.pm.in0000644000175000017500000010543714147024700014031 00000000000000# Copyright (c) 2003-2009 Mikhael Goikhman # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see: package FVWM::Module; use 5.004; use strict; use IO::File; BEGIN { use vars qw($prefix $datarootdir $datadir); $prefix = "@prefix@"; $datarootdir = "@datarootdir@"; $datadir = "@datadir@"; } use lib "@FVWM_PERLLIBDIR@"; use vars qw($VERSION @ISA @EXPORT $AUTOLOAD); use FVWM::Constants; use FVWM::Event; use Exporter; @EXPORT = @FVWM::Constants::EXPORT; @ISA = qw(Exporter); # The major version part indicates major API changes $VERSION = '2.0'; # Set the fvwm search directories (used for non fully qualified file names) $General::FileSystem::SAVE_FILE_DIR = $General::FileSystem::SAVE_FILE_DIR || __PACKAGE__->user_data_dir(); $General::FileSystem::LOAD_FILE_DIRS = $General::FileSystem::LOAD_FILE_DIRS || [ __PACKAGE__->search_dirs() ]; sub internal_die ($$) { my $self = shift; my $msg = shift; $msg =~ s/([^\.!?])$/$1./; die $self->name . ": $msg Exiting.\n"; } sub show_error ($$) { my $self = shift; my $msg = shift; print STDERR $self->name . ": $msg\n"; } sub show_message ($$) { my $self = shift; my $msg = shift; print STDERR "[" . $self->name . "]: $msg\n"; } sub show_debug ($$) { my $self = shift; my $msg = shift; print STDERR "[" . $self->name . "]: $msg\n"; } sub debug ($$;$) { my $self = shift; my $msg = shift; my $level = shift; $level = 1 unless defined $level; my $debug_level = $self->{debug}; $debug_level = $ENV{FVWM_MODULE_DEBUG} if exists $ENV{FVWM_MODULE_DEBUG}; return if $debug_level < $level; $msg =~ s/\n$//s; $self->show_debug($msg); } sub is_event_extended ($$) { my $self = shift; my $type = shift; return $type & M_EXTENDED_MSG ? 1 : 0; } sub new ($@) { my $class = shift; my %params = @_; my $self = {}; my $name = $0; $name =~ s|.*/||; $name = $params{'Name'} || $name; my $mask = $params{'Mask'}; my $xmask = $params{'XMask'}; my $sync_mask = $params{'SyncMask'}; my $sync_xmask = $params{'SyncXMask'}; # initialize module from argv my ($out_fd, $in_fd, $rc_file, $win_id, $context); if (@ARGV >= 5 && $ARGV[0] =~ /^\d+$/ && $ARGV[1] =~ /^\d+$/) { $self->{is_dummy} = 0; ($out_fd, $in_fd, $rc_file, $win_id, $context) = splice(@ARGV, 0, 5); } else { warn "$name should be spawned by fvwm normally.\n"; warn "Activating a dummy command line mode for 30 minutes (no events).\n"; warn "----------------------------------------------------------------\n"; open(DUMMYOUT, '| cat >/dev/null'); open(DUMMYIN, 'sleep 1800 |'); $self->{is_dummy} = 1; ($out_fd, $in_fd) = (fileno(DUMMYOUT), fileno(DUMMYIN)); ($rc_file, $win_id, $context) = ("none", 0, 0); } if (@ARGV && $params{'EnableAlias'} && $ARGV[0] =~ /^\w[\w\d\.\/-]*/) { $name = shift @ARGV; } if (@ARGV && ref($params{'EnableOptions'}) eq 'HASH') { # save time by lazy loading Getopt::Long only if needed eval "use Getopt::Long;"; die "$name: $@" if $@; GetOptions(%{$params{'EnableOptions'}}) or die "$name: Incorrect options given.\n"; } my @argv = @ARGV; $self->{rc_file} = $rc_file; $self->{win_id} = hex $win_id; $self->{context} = $context; $self->{argv} = [@argv]; # a module may need this autoflush STDOUT; autoflush STDERR; $self->{ostream} = new IO::File ">&$out_fd" or die "$name: Can't write to file descriptor (&$out_fd)\n"; $self->{istream} = new IO::File "<&$in_fd" or die "$name: Can't read from file descriptor (&$in_fd)\n"; $self->{ostream}->autoflush(1); $self->{istream}->autoflush(1); $self->{disconnected} = 0; $self->{debug} = $params{'Debug'} || 0; $self->{debug} = ${$self->{debug}} if ref($self->{debug}) eq 'SCALAR'; $self->{last_packet} = []; $self->{handlers} = {}; $self->{should_send_unlock} = 0; $self->{should_send_ready} = 1; $self->{add_mask} = 0; $self->{add_xmask} = 0; $self->{mask_was_set} = defined $mask; $self->{xmask_was_set} = defined $xmask; $self->{held_command_args} = []; $self->{synthetic_events} = []; $self->{used_tracker_classes} = {}; $self->{trackers} = {}; # bless here, so die above does not run DESTROY bless $self, $class; $self->name($name); $self->mask($mask || 0, $self->{mask_was_set}); $self->xmask($xmask, $self->{xmask_was_set}) if $xmask; $self->sync_mask($sync_mask || 0); $self->sync_xmask($sync_xmask) if $sync_xmask; $self->reset_handlers; return $self; } sub disconnect ($) { my $self = shift; # do nonrecoverable things, but do them only once return if $self->{disconnected}; $self->{disconnected} = 1; $self->invoke_handler(new FVWM::Event(ON_EXIT)); if (defined $self->{ostream} && $self->{ostream}->opened) { # TODO: should wait until fvwm actually gets it $self->send("Nop", 0, 0); close $self->{ostream}; } if (defined $self->{istream} && $self->{istream}->opened) { close $self->{istream}; } } sub DESTROY ($) { my $self = shift; $self->disconnect; } sub is_dummy ($) { my $self = shift; return $self->{is_dummy}; } sub name ($;$) { my $self = shift; my $name = shift; $self->{name} = $name if defined $name; return $self->{name}; } sub mask ($;$$) { my $self = shift; my $mask = shift; my $explicit = shift; $explicit = 1 unless defined $explicit; if (defined $mask) { $self->internal_die("mask() can't get extended mask, use xmask()") if $self->is_event_extended($mask); my $old_mask = $self->{mask}; $self->send_mask($mask, $self->{add_mask}) unless defined $old_mask && $old_mask == $mask; $self->{mask} = $mask; $self->{mask_was_set} = $explicit; return $old_mask; } return $self->{mask} || 0; } sub xmask ($;$$) { my $self = shift; my $mask = shift; my $explicit = shift; $explicit = 1 unless defined $explicit; if (defined $mask) { $mask &= ~M_EXTENDED_MSG; my $old_mask = $self->{xmask}; $self->send_mask($mask | M_EXTENDED_MSG, $self->{add_xmask}) unless defined $old_mask && $old_mask == $mask; $self->{xmask} = $mask; $self->{xmask_was_set} = $explicit; return $old_mask; } return $self->{xmask} || 0; } sub is_in_mask ($$) { my $self = shift; my $type = shift; my $mask = ($type & M_EXTENDED_MSG) ? $self->{xmask} : $self->{mask}; return $type & ($mask || 0); } sub sync_mask ($;$) { my $self = shift; my $mask = shift; if (defined $mask) { $self->internal_die("sync_mask() can't get extended mask, use sync_xmask()") if $self->is_event_extended($mask); my $old_mask = $self->{sync_mask}; $self->send("SET_SYNC_MASK $mask") unless defined $old_mask && $old_mask == $mask; $self->{sync_mask} = $mask; return $old_mask; } return $self->{sync_mask} || 0; } sub sync_xmask ($;$) { my $self = shift; my $mask = shift; if (defined $mask) { $mask &= ~M_EXTENDED_MSG; my $old_mask = $self->{sync_xmask}; $self->send("SET_SYNC_MASK " . ($mask | M_EXTENDED_MSG)) unless defined $old_mask && $old_mask == $mask; $self->{sync_xmask} = $mask; return $old_mask; } return $self->{sync_xmask} || 0; } sub is_in_sync_mask ($$) { my $self = shift; my $type = shift; my $mask = ($type & M_EXTENDED_MSG) ? $self->{sync_xmask} : $self->{sync_mask}; return $type & ($mask || 0); } # by default the version of a module is the fvwm version sub version ($) { my $self = shift; return "@VERSION@"; } sub version_info ($) { my $self = shift; return "@VERSIONINFO@"; } sub argv ($) { my $self = shift; return @{$self->{argv}}; } sub reset_handlers ($) { my $self = shift; $self->{handlers}->{regular} = {}; $self->{handlers}->{extended} = {}; $self->{handlers}->{special} = {}; } sub get_handler_category ($$) { my $self = shift; my $type = shift; return "special" if $type =~ /e/i; return "extended" if $self->is_event_extended($type); return "regular"; } sub postpone_send ($@) { my $self = shift; push @{$self->{held_command_args}}, [ @_ ]; } # params: text, [win_id], [continue=0/1] sub send ($$;$$) { my $self = shift; my $text = shift; my $win_id = shift || 0; my $continue = shift; $continue = 1 unless defined $continue; $self->internal_die("send requires at least text param") unless defined $text; my @lines = split(/\n/s, $text); my $last_line = ""; for my $line (@lines) { # support continuation lines $line = "$last_line$line" if $last_line ne ""; if ($line =~ /^(.*)\\$/) { $last_line = $1; next; } else { $last_line = ""; } next if $line =~ /^\s*$/; unless ($self->{ostream}->opened) { $self->debug("Closed send [$line]\n", 1); next; } $self->debug("sent [$line]" . (!$continue && " FINISH"), 2); my $len = length $line; local $SIG{PIPE} = sub { $self->debug("Failed send [$line]\n", 1); }; $self->{ostream}->print( pack("l!l!a${len}l!", $win_id, $len, $line, $continue) ); } return $self; } sub send_ready ($) { my $self = shift; $self->send(RESPONSE_READY) if $self->{should_send_ready}; $self->{should_send_ready} = 0; return $self; } sub send_unlock ($) { my $self = shift; $self->send(RESPONSE_UNLOCK) if $self->{should_send_unlock}; $self->{should_send_unlock} = 0; return $self; } sub send_mask ($$;$) { my $self = shift; my $mask = shift; my $add_mask = shift || 0; $self->send("SET_MASK " . ($mask | $add_mask)); } sub request_reply ($$) { my $self = shift; my $text = shift; my $win_id = shift; $self->send("Send_Reply $text", $win_id); } sub terminate ($;$) { my $self = shift; my $continue = shift || 0; die "!quit" if !$continue; die "!next"; } sub wait_packet ($) { } sub read_packet ($) { my $self = shift; goto RETURN_PACKET if @{$self->{synthetic_events}}; $self->{last_packet} = []; my $header = ""; my $packet = ""; $self->wait_packet; # read a packet's header first, sizeof(int) * HEADER_SIZE bytes long my $got; # With perl-5.8.0+, $SIG{ALRM} causes sysread to exit with "Illegal seek", # so loop around sysread. I am not sure this is safe. do { $got = sysread($self->{istream}, $header, INTSIZE * HEADER_SIZE); } until (defined $got); if ($got != (INTSIZE * HEADER_SIZE)) { # module killed or other read error $self->debug($got ? "read packet error" : "connection closed", 3); return undef; } my ($magic, $type, $len, $timestamp) = unpack(sprintf("L!%d", HEADER_SIZE), $header); $self->internal_die("Bad magic number $magic in packet") unless $magic == START_FLAG; # $type should not be anything other than a 32-bit number # however, extended messages are padded with set bits on 64-bit systems $type &= 0xffffffff; # $len is number of words in packet, including header; # we need this as number of bytes. $len -= HEADER_SIZE; $len *= INTSIZE; if ($len > 0) { my $off = 0; while ($off < $len) { $got = sysread($self->{istream}, $packet, $len, $off); if (!defined $got) { $self->internal_die("sysread error: $!"); } $off += $got; } $self->internal_die("Got packet len $off while expecting $len") if $off != $len; } RETURN_PACKET: ($type, $packet) = @{shift @{$self->{synthetic_events}}} if @{$self->{synthetic_events}}; $self->{last_packet} = [$type, $packet]; return ($type, $packet); } sub invoke_handler ($$) { my $self = shift; my $event = shift; my $type = $event->type; my $category = $self->get_handler_category($type); my @masks = sort { $a <=> $b } keys %{$self->{handlers}->{$category}}; foreach my $mask (@masks) { if ($type eq $mask || $type & $mask) { foreach my $handler (@{$self->{handlers}->{$category}->{$mask}}) { last unless $event->propagation_allowed; next unless defined $handler; # skip deleted ones eval { &$handler($self, $event); }; if ($@) { return 0 if $@ =~ /^!quit/i; return 1 if $@ =~ /^!next/i; die $@; } } } } return 1; } sub process_packet ($;$$) { my $self = shift; my ($type, $packet) = @_; ($type, $packet) = @{$self->{last_packet}} unless defined $packet; return undef unless defined $packet; my $event = eval { new FVWM::Event($type, $packet); }; $self->internal_die($@ || "Internal error") unless defined $event; if ($self->{debug}) { my $msg = "got " . $event->name; $msg .= " [" . $event->arg_values->[-1] . "]" if @{$event->arg_types} && $event->arg_types->[-1] == FVWM::EventNames::string(); $self->debug($msg, 2); } $self->{should_send_unlock} = 1 if $self->is_in_sync_mask($type); my $continue = $self->invoke_handler($event); $self->send_unlock if $self->{should_send_unlock}; return $continue; } sub emulate_event ($$$) { my $self = shift; my ($type, $packet) = @_; if ($self->{is_in_event_loop}) { $self->invoke_handler(new FVWM::Event($type, $packet)); return; } push @{$self->{synthetic_events}}, [$type, $packet]; } sub event_loop_prepared ($@) { my $self = shift; my $tracking = shift() ? 1 : 0; if (!$self->{is_in_event_loop}) { $self->send_ready unless $tracking; $self->debug("entered event loop", 3 + $tracking); $self->{is_in_event_loop} = 1; } # update module masks to handle trackers if needed my $add_mask = 0; my $add_xmask = 0; foreach (values %{$self->{trackers}}) { my ($mask, $xmask) = $_->masks; $add_mask |= $mask; $add_xmask |= $xmask; } $self->send_mask($self->mask, $self->{add_mask} = $add_mask) if $add_mask != $self->{add_mask}; $self->send_mask($self->xmask | M_EXTENDED_MSG, $self->{add_xmask} = $add_xmask) if $add_xmask != $self->{add_xmask}; # execute postponed commands if any $self->send(@{shift @{$self->{held_command_args}}}) while @{$self->{held_command_args}}; # fire emulated events if any $self->process_packet(@{shift @{$self->{synthetic_events}}}) while !$tracking && @{$self->{synthetic_events}}; } sub event_loop_finished ($@) { my $self = shift; my $tracking = shift() ? 1 : 0; $self->debug("exited event loop", 3 + $tracking); unless ($tracking) { foreach my $tracker (values %{$self->{trackers}}) { $tracker->to_be_disconnected; } $self->disconnect; } $self->{is_in_event_loop} = 0; } sub event_loop ($@) { my $self = shift; while (1) { $self->event_loop_prepared(@_); # catch exceptions during read, for example from alarm() handler, # but don't catch errors (or die) in event handlers $self->process_packet(eval { $self->read_packet }) || last; } $self->event_loop_finished(@_); } sub track ($$;$@) { my $self = shift; my $params = ref($_[0]) eq 'HASH' ? shift() : {}; my $tracker_type = shift; my $tracker_class = $tracker_type =~ /::/ ? $tracker_type : "FVWM::Tracker::$tracker_type"; # load a tracker class if not yet unless (defined $self->{used_tracker_classes}->{$tracker_class}) { eval "use $tracker_class;"; die $@ if $@; $self->{used_tracker_classes}->{$tracker_class} = 1; } my $tracker = !$params->{NoReuse} && $self->{trackers}->{$tracker_type} || $tracker_class->new($self, @_); if ($params->{NoReuse}) { $tracker_type .= "+" while exists $self->{trackers}->{$tracker_type}; } $self->{trackers}->{$tracker_type} = $tracker; $tracker->start unless $params->{NoStart}; return $tracker; } sub add_handler ($$$;$) { my $self = shift; my $type = shift; my $handler = shift; my $is_tracking = shift || 0; $self->internal_die("add_handler: no handler type") unless defined $type; $self->internal_die("add_handler: no handler code") unless ref($handler) eq 'CODE'; my $category = $self->get_handler_category($type); $self->{handlers}->{$category}->{$type} = [] unless exists $self->{handlers}->{$category}->{$type}; push @{$self->{handlers}->{$category}->{$type}}, $handler; my $index = @{$self->{handlers}->{$category}->{$type}} - 1; unless ($is_tracking) { $self->mask($self->mask | $type, 0) if !$self->{mask_was_set} && $category eq "regular"; $self->xmask($self->xmask | $type, 0) if !$self->{xmask_was_set} && $category eq "extended"; } return [$type, $index]; } sub delete_handler ($$) { my $self = shift; my $id = shift; return 0 unless ref($id) eq 'ARRAY' && @$id == 2; my ($type, $index) = @$id; my $category = $self->get_handler_category($type); return 0 unless defined $self->{handlers}->{$category}->{$type}->[$index]; $self->{handlers}->{$category}->{$type}->[$index] = undef; return 1; } sub add_default_error_handler ($) { my $self = shift; $self->add_handler(M_ERROR, sub { my ($self, $type, @args) = @_; my $error = $args[3]; print STDERR "[", $self->name, "]: got fvwm error: $error\n"; #$self->terminate; }); } sub user_data_dir ($) { return $ENV{FVWM_USERDIR} || (($ENV{HOME} || "") . "/.fvwm"); } sub site_data_dir ($) { return "@FVWM_DATADIR@"; } sub search_dirs ($) { my $this = shift; return ($this->user_data_dir, $this->site_data_dir); } # support old API, like addHandler, dispatch to add_handler sub AUTOLOAD ($;@) { my $self = shift; my @params = @_; my $autoload_method = $AUTOLOAD; my $method = $autoload_method; # remove the package name $method =~ s/.*://g; $method =~ s/XMask/Xmask/; $method =~ s/([a-z])([A-Z])/${1}_\L$2/g; die "No method $method in $self as guessed from $autoload_method" unless $self->can($method); $self->$method(@params); } 1; __END__ =head1 NAME FVWM::Module - the base class representing fvwm module =head1 SYNOPSIS use lib `fvwm-perllib dir`; use FVWM::Module; my $module = new FVWM::Module; $module->send("Beep"); # auto-raise all windows sub auto_raise { $_[0]->send("Raise", $_[1]->_win_id) }; $module->add_handler(M_FOCUS_CHANGE, \&auto_raise); # terminate itself after 5 minutes my $scheduler = $module->track('Scheduler'); $scheduler->schedule(5 * 60, sub { $module->terminate; }); # print the current desk number ($page_tracker is auto updated) my $page_tracker = $module->track("PageInfo"); $module->show_message("Desk: " . $page_tracker->data->{desk_n}); $module->event_loop; =head1 DESCRIPTION An fvwm module is a separate program that communicates with the main I process, receives a module configuration and events and sends commands back. This class B makes it easy to create fvwm modules in Perl. If you are interested in all module protocol details that this class tries to make invisible, visit the web page I. You will need an information about packet arguments anyway to be able to write complex modules. This is however not obligatory for simple modules that only send commands back when something happens. A typical fvwm module has an initialization part including setting event handlers using B methods and entering an event loop using B method. Most of the work is done in the event handlers although a module may define other execution ways, for example using C<$SIG{ALRM}>. An fvwm module receives 3 values from I: I - the file this module was called from or "none" if the module is called as a command from another module or from a binding/function (this value is not really useful), I - the window context of this module if it is called from window decoration bindings or window menu (the value is integer, 0 if there is no window context), and finally I that indicates the place this module was called from, like menu or window title (see the fvwm documentation). All these values may be accessed as properties of the module object, like C<$module-E{win_id}>. =head1 METHODS The following methods are available: B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B, B. The following methods are called from other methods above, but may be useful in other situations as well: B, B, B, B, B, B, B, B, B, B, B, B, B, B. These methods deal with a received packet (event): B These methods deal with configuration directories: B, B, B =over 4 =item B I Creates a module object. Only one module instance may be created in the program, since this object gets exclusive rights on communication with I. The following parameters may be given in the constractor: Name - used in module configuration and debugging Mask - events a module is interested to receive XMask - the same for extended events SyncMask - events to lock on SyncXMask - the same for extended events EnableAlias - whether a module accepts an alias in command line EnableOptions - options that a module accepts in command line Debug - 0 means no debug, 1 - user debug, 2,3,4 - perllib Example: my $module = new FVWM::Module( Name => "FvwmPerlBasedWindowRearranger", Mask => M_CONFIGURE_WINDOW | M_END_WINDOWLIST, EnableOptions => { "animate" => \$a, "cascade" => \$c }, Debug => 2, ); Event types needed for the 4 mask parameters are defined in B. Set I to 2 to nicely dump all communication with fvwm (sent commands and received events). Setting it to 3 makes it even more verbose. Some options cause an automatically parsing of the module command line args. See L for the format of the hash ref accepted by I parameter. If boolean I parameter is given, then the alias argument may be specified anywhere on the command line, for example before or after long/short options or even in between, as long as there are no conflicts with some non-mandatory option arguments. In which case "--" may be used to indicate the end of the options. All non-parsed command line arguments are available to the program using B method. =item B Returns fvwm version string I. =item B Returns fvwm version info string, like " (from cvs)" or " (snap-YYYYMMDD)". This string is usually empty for the final version. =item B Returns remaining module arguments (array ref) passed in the command line. Arguments that are used for I-to-module communication are not included. Arguments that are automatically parsed using I and/or I specified in the constructor are not included. =item B I [I] [I] Sends I back for execution. If the I is specified this command will be executed in this window context. I of 0 signals that this is the last sent command from the module, the default for this flag is 1. =item B [I] [I] [I] Creates a module tracker object (see L) specified by a I. I may include parameters: NoStart - true value means the created tracker is not auto-started NoReuse - true value means not to reuse any existing named tracker I is specific to the tracker named I. Every tracker class (a subclass of B) has its own manual page, contact it for the tracker details and usage. =item B The main event loop. A module should define some event handlers using B before entering the event loop. When the event happens all event handlers registered on this event are called, then a module returns to the event loop awaiting for new events forever. This method may be finished when one of the following happens. 1) Explicit B is called in one of the event handlers. 2) Signal handler (system signals are independent from this event loop) decides to I. This is usually catched and a proper shutdown is done. 3) An event handler Id, in this case the module aborts, this is done on purpose to encourage programmers to fix bugs. 4) Communication with I closed, for example B called or the main I process exited. In all these cases (except for the third one) I event handlers are called if defined and then B is called. So no communication is available after this method is finished. If you need a communication before the module exits, define an I event handler. =item B This is automatically called (if needed) when a module enters B, but sometimes you may want to tell I that the module is fully ready earlier. This only makes sence if the module was run using B command, in this case I gets locked until the module sends the "ready" notification. =item B When an event was configured to be sent to a module synchronously using I and I, I gets locked until the module sends the "unlock" notification. This is automatically sent (if needed) when a handler is finished, but sometimes a handler should release I earlier. =item B I [I] A module may request I to send the same text (but possibly interpolated) back to it using MX_REPLY event. This method sends special command I. =item B I [I] [I] The same like B, but the actual command sending is postponed until before the module enters the reading-from-fvwm phase in B. =item B [I] This method is used for 2 purposed, usually in event handlers. To terminate the entire event loop and to terminate only an execution of the current handler if I is set. =item B This deletes all event handlers without exception. =item B I Defines a handler (that is a I subroutine) for the given I event (or several events). Usually the event type is one of the fvwm I or I constants (see B), but it may also be I, this special event is called just before the event loop is terminated. The I may include several events in the same category (the event types are or-ed). In this case the handler will be called for every matching event. Currently there are 3 categories: regular events (M_*), extended events (MX_*) and special events (ON_EXIT). These 3 categories of events can't be mixed, primary because of technical reasons. The handler subroutine is called with these parameters: ($self, $event) where C<$self> is a module object, C<$event> is B object. If the I includes more than one event type, use C<$event-Etype> to dispatch event types if needed. The handler may call C<$self-Eterminate> to terminate the event loop completely or C<$self-Eterminate("continue")> to terminate the current event handler only. The second form is useful when the handler subroutine calls other subroutines that need to terminate the primary one. If several event handlers are added for the same event type, they are executed in the added order. To forbid the further propagation of the same event, an event handler may call C<$event-Epropagation_allowed(0)>. The return value from B is an identifier the only purpose of which is to be passed to B in case the newly defined handler should be deleted at some point. =item B I Removes the handler specified by I. The return value is 1 if the handler is found and deleted, 0 otherwise. =item B This adds the default handler for I event. This class simply prints an error message to the standard error stream, but subclasses may define another default handler by overwriting this method. =item B I [I] Prints I to the standard error stream if I is greater or equal to the module debug level defined using I in the constructor. The default I for this method is 1 that makes it possible to add user debugging output without specifying a level. The default module level is 0, so no debugging output of positive levels is shown. This module uses B internally (with I 2) to dump all incoming and outgoing communication data in B and B. Apparently this output is only seen if I is set to 2 or greater. =item B I Writes I to the error stream (stderr). It is supposed that the argument has no traling end of line. May be used to signal non fatal error. Subclasses may overwrite this method and, for example, show all error messages in separate windows or in the common error window. =item B I Writes I to the message stream (stderr). It is supposed that the argument has no traling end of line. May be used to show a named output. Subclasses may overwrite this method and, for example, show all messages in separate windows or in the common message window. =item B I Unconditionally writes I to the debug stream (stderr). It is supposed that the argument has no traling end of line. Used in B to actually show the message when the level is matched. Subclasses may overwrite this method and, for example, show all debugging messages in separate windows or in the common debug window. =item B Usually a module should be executed by I only. But to help creating GUI applications, the dummy mode is supported when the module is started from the command line. No events are received in this case, but with some effort they may be emulated: $module->emulate_event(M_NEW_DESK, [ 2 ]) if $module->is_dummy; =item B I This may be used to end the module with the corresponding I. For a clean module exit use B and B instead. =item B [I] Sets or returns the module name. Called automatically from the constructor. =item B [I] [I] =item B [I] [I] Sets or returns the module mask. Called automatically from the constructor. Regular and extended event types should never be mixed, this is why there are 2 variants of this method, the first is for regular and the second is for extended event types. Without a parameter, the module mask is returned, the integer parameter indicates a mask to set and the old mask is returned. The module only receives the packets matching these 2 module masks (regular and extended). This class is smart to update the minimal module masks automatically if you never set them explicitly (either in constructor or using these methods). The I parameter should not be usually used, it defaults to 1. If you set it to 0 then the module is informed to continue to automatically update masks on the following B calls even after the current mask setting. =item B I Returns true if the module mask matches the given I. Good for both regular and extended event types as long as they are queried separately. =item B [I] =item B [I] The same as B and B, but sets/returns the synchronization mask of the module. The module is synchronized with I on all packets matching these 2 module synchronization masks (regular and extended). =item B I Returns true if the module synchronization mask matches the given I. Good for both regular and extended event types as long as they are queried separately. =item B This method invokes I handlers if any and closes communication. It is called automatically from B before finishing. It is safe to call this method more than once. This method may be called from signal handlers before Iing for the proper shutdown. =item B I Returns one of 3 string ids depending on the event handler I that has the same meaning as the corresponding packet type ("regular" or "extended") with an addition of "special" category for I handlers. =item B This is a blocking method that waits until there is a packet on the communication end from I. Then it returns a list of 2 values, packet type and packet data (unpacked array of arguments). =item B I Dispatches the apropos event handlers with the event data. This method is called automatically, so you usually should not worry about it. =item B [I] This method constructs the event object from the packet data and calls B with it. Prints debug info if requested. Finally calls B if needed. You should not really worry about this method, it is called automatically from the event loop. =item B I This method emulates the event as returned by B. The given event is processed immediately if in the event loop, or just before the real B otherwise. The parameters are the same as in B and the same as in L constructor. =item B Called from B every time before reading the packet for new data. Subclasses should pass this method the same arguments that B received for a possible future use. =item B Called from B just before the return. Subclasses should pass this method the same arguments that B received for a possible future use. =item B I For technical reasons there are 2 categories of fvwm events, regular and extended. This is done to enable more events. With introdution of the extended event types (with the highest bit set) it is now possible to have 31+31=62 different event types rather than 32. This is a good point, the bad point is that only event types of the same category may be masked (or-ed) together. This method returns 1 or 0 depending on whether the event I is extended or not. =item B Returns the user data directory, usually ~/.fvwm or set by $FVWM_USERDIR. =item B Returns the system-wide data directory, the one configured when fvwm is installed. It is also returned by `fvwm-config --fvwm-datadir`. =item B It is a good practice for a module to search for the given configuration in one of 2 data directories, the user one and the system-wide. This method returns a list of both directories in that order. =back =head1 BUGS Awaiting for your reporting. =head1 CAVEATS In keeping with the UNIX philosophy, B does not keep you from doing stupid things, as that would also keep you from doing clever things. What this means is that there are several areas with which you can hang your module or even royally confuse your running I process. This is due to flexibility, not bugs. =head1 AUTHOR Mikhael Goikhman . =head1 THANKS TO Randy J. Ray . =head1 SEE ALSO For more information, see L and L, L. =cut fvwm-2.7.0/perllib/FVWM/Module/0000755000175000017500000000000014324316055013140 500000000000000fvwm-2.7.0/perllib/FVWM/Module/Makefile.in0000644000175000017500000004151714324315776015146 00000000000000# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 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 = perllib/FVWM/Module ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.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)$(configdir)" DATA = $(config_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALL_DOMAINS = @ALL_DOMAINS@ ALL_LINGUAS = @ALL_LINGUAS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR_FLAGS = @AR_FLAGS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ Bidi_CFLAGS = @Bidi_CFLAGS@ Bidi_LIBS = @Bidi_LIBS@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DOC_COMMANDS = @DOC_COMMANDS@ DOC_COMMANDS_HTML = @DOC_COMMANDS_HTML@ DOC_COMMANDS_XML = @DOC_COMMANDS_XML@ DOC_COMMANDS_XML_PATH = @DOC_COMMANDS_XML_PATH@ DOC_MODULES = @DOC_MODULES@ DOC_MODULES_HTML = @DOC_MODULES_HTML@ DOC_SECTIONS = @DOC_SECTIONS@ DOC_SECTIONS_XML = @DOC_SECTIONS_XML@ DOC_SECTIONS_XML_PATH = @DOC_SECTIONS_XML_PATH@ DUMMYPOFILES = @DUMMYPOFILES@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FC_CFLAGS = @FC_CFLAGS@ FC_CONFIG = @FC_CONFIG@ FC_LIBS = @FC_LIBS@ FRIBIDI_CONFIG = @FRIBIDI_CONFIG@ FVWMALTFTP = @FVWMALTFTP@ FVWMALTFTPDIR = @FVWMALTFTPDIR@ FVWMFTP = @FVWMFTP@ FVWMFTPDIR = @FVWMFTPDIR@ FVWMHOMEPAGE = @FVWMHOMEPAGE@ FVWMLIST = @FVWMLIST@ FVWMNAMELONG = @FVWMNAMELONG@ FVWMSCRIPT_DOMAIN = @FVWMSCRIPT_DOMAIN@ FVWMTASKBAR_DOMAIN = @FVWMTASKBAR_DOMAIN@ FVWMWORKERSLIST = @FVWMWORKERSLIST@ FVWMWORKERSLISTLONG = @FVWMWORKERSLISTLONG@ FVWM_CONFDIR = @FVWM_CONFDIR@ FVWM_CPP = @FVWM_CPP@ FVWM_DATADIR = @FVWM_DATADIR@ FVWM_DOCDIR = @FVWM_DOCDIR@ FVWM_DOMAIN = @FVWM_DOMAIN@ FVWM_IMAGEPATH = @FVWM_IMAGEPATH@ FVWM_MODULEDIR = @FVWM_MODULEDIR@ FVWM_PERLLIB = @FVWM_PERLLIB@ FVWM_PERLLIBDIR = @FVWM_PERLLIBDIR@ GDK_IMLIB_CFLAGS = @GDK_IMLIB_CFLAGS@ GDK_IMLIB_LIBS = @GDK_IMLIB_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ IMLIBCONF = @IMLIBCONF@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INST_LINGUAS = @INST_LINGUAS@ ISRELEASED = @ISRELEASED@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOCALEDIR = @LOCALEDIR@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANPAGE_PREAMBLE = @MANPAGE_PREAMBLE@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ MSGUNIQ = @MSGUNIQ@ OBJEXT = @OBJEXT@ 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@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PYTHON = @PYTHON@ RANLIB = @RANLIB@ RELDATELONG = @RELDATELONG@ RELDATENUM = @RELDATENUM@ RELDATESHORT = @RELDATESHORT@ REQUIRED_PERL_VERSION = @REQUIRED_PERL_VERSION@ REQUIRED_PYTHON_VERSION = @REQUIRED_PYTHON_VERSION@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ UPDATEPOFILES = @UPDATEPOFILES@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VERSIONINFO = @VERSIONINFO@ XFT_CFLAGS = @XFT_CFLAGS@ XFT_CONFIG = @XFT_CONFIG@ XFT_LIBS = @XFT_LIBS@ XGETTEXT = @XGETTEXT@ XMKMF = @XMKMF@ XSLTPROC = @XSLTPROC@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Xcursor_CFLAGS = @Xcursor_CFLAGS@ Xcursor_LIBS = @Xcursor_LIBS@ Xft_CFLAGS = @Xft_CFLAGS@ Xft_LIBS = @Xft_LIBS@ Xinerama_CFLAGS = @Xinerama_CFLAGS@ Xinerama_LIBS = @Xinerama_LIBS@ Xrender_CFLAGS = @Xrender_CFLAGS@ Xrender_LIBS = @Xrender_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ iconv_CFLAGS = @iconv_CFLAGS@ iconv_LIBS = @iconv_LIBS@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intl_CFLAGS = @intl_CFLAGS@ intl_LIBS = @intl_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ png_CFLAGS = @png_CFLAGS@ png_LIBS = @png_LIBS@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ readline_CFLAGS = @readline_CFLAGS@ readline_LIBS = @readline_LIBS@ rplay_CFLAGS = @rplay_CFLAGS@ rplay_LIBS = @rplay_LIBS@ rsvg_CFLAGS = @rsvg_CFLAGS@ rsvg_LIBS = @rsvg_LIBS@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ stroke_CFLAGS = @stroke_CFLAGS@ stroke_LIBS = @stroke_LIBS@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ with_bidi = @with_bidi@ with_gdkimlib = @with_gdkimlib@ with_gettext = @with_gettext@ with_iconv = @with_iconv@ with_perllib = @with_perllib@ with_png = @with_png@ with_readline = @with_readline@ with_rplay = @with_rplay@ with_rsvg = @with_rsvg@ with_shape = @with_shape@ with_shm = @with_shm@ with_sm = @with_sm@ with_stroke = @with_stroke@ with_xcursor = @with_xcursor@ with_xft = @with_xft@ with_xinerama = @with_xinerama@ with_xpm = @with_xpm@ with_xrender = @with_xrender@ xpm_CFLAGS = @xpm_CFLAGS@ xpm_LIBS = @xpm_LIBS@ configdir = @FVWM_PERLLIBDIR@/FVWM/Module config_DATA = Toolkit.pm Terminal.pm Tk.pm EXTRA_DIST = $(config_DATA) all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(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) --foreign perllib/FVWM/Module/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign perllib/FVWM/Module/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: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-configDATA: $(config_DATA) @$(NORMAL_INSTALL) @list='$(config_DATA)'; test -n "$(configdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(configdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(configdir)" || 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)$(configdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(configdir)" || exit $$?; \ done uninstall-configDATA: @$(NORMAL_UNINSTALL) @list='$(config_DATA)'; test -n "$(configdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(configdir)'; $(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)$(configdir)"; 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 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-configDATA 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 pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-configDATA .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic cscopelist-am \ ctags-am distclean distclean-generic distdir dvi dvi-am html \ html-am info info-am install install-am install-configDATA \ 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-generic pdf \ pdf-am ps ps-am tags-am uninstall uninstall-am \ uninstall-configDATA .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: fvwm-2.7.0/perllib/FVWM/Module/Toolkit.pm0000644000175000017500000001751714147024700015052 00000000000000# Copyright (c) 2003-2009 Mikhael Goikhman # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see: package FVWM::Module::Toolkit; use 5.004; use strict; use vars qw($VERSION @ISA $_dialog_tool); use FVWM::Module; BEGIN { $VERSION = $FVWM::Module::VERSION; @ISA = qw(FVWM::Module); } sub import ($@) { my $class = shift; my $caller = caller; my $error = 0; my $name = "*undefined*"; while (@_) { $name = shift; if ($name eq 'base') { next if UNIVERSAL::isa($caller, __PACKAGE__); my $caller2 = (caller(1))[0]; eval " package $caller2; use FVWM::Constants; package $caller; use vars qw(\$VERSION \@ISA); use FVWM::Constants; \$VERSION = \$FVWM::Module::Toolkit::VERSION; \@ISA = qw(FVWM::Module::Toolkit); "; if ($@) { die "Internal error:\n$@"; } } else { my ($name0, $args) = split(/>?=/, $name, 2); my $mod = $args? "$name0 split(/,/, q{$args})": $name; eval " package $caller; use $mod; "; if ($@) { $error = 1; last; } } } if ($error) { my $script_name = $0; $script_name =~ s|.*/||; my $error_title = 'FVWM Perl library error'; my $error_msg = "$script_name requires Perl package $name to be installed.\n\n"; $error_msg .= "You may either find it as a binary package for your distribution\n"; $error_msg .= "or download it from CPAN, http://cpan.org/modules/by-module/ .\n"; $class->show_message($error_msg, $error_title, 1); print STDERR "[$error_title]: $error_msg\n$@"; exit(1); } } sub show_error ($$;$) { my $self = shift; my $msg = shift; my $title = shift || ($self->name . " Error"); $self->show_message($msg, $title, 1); print STDERR "[$title]: $msg\n"; } sub show_message ($$;$) { my $self = shift; my $msg = shift; my $title = shift || ($self->name . " Message"); my $no_stderr = shift || 0; # for private usage only unless ($_dialog_tool) { my @dirs = split(':', $ENV{PATH}); # kdialog is last because at least v0.9 ignores --title TOOL_CANDIDATE: foreach (qw(gdialog Xdialog zenity message kdialog)) { foreach my $dir (@dirs) { my $file = "$dir/$_"; if (-x $file) { $_dialog_tool = $_; last TOOL_CANDIDATE; } } } } my $tool = $_dialog_tool || "xterm"; $msg =~ s/'/'"'"'/sg; $title =~ s/'/'"'"'/sg; if ($tool eq "gdialog" || $tool eq "Xdialog" || $tool eq "kdialog") { system("$tool --title '$title' --msgbox '$msg' 500 100 &"); } elsif ($tool eq "zenity") { system("zenity --title '$title' --info --text '$msg' --no-wrap &"); } elsif ($tool eq "xmessage") { system("xmessage -name '$title' '$msg' &"); } else { $msg =~ s/"/\\"/sg; $msg =~ s/\n/\\n/sg; system("xterm -g 70x10 -T '$title' -e \"echo '$msg'; sleep 600000\" &"); } print STDERR "[$title]: $msg\n" if $! && !$no_stderr; } sub show_debug ($$;$) { my $self = shift; my $msg = shift; my $title = shift || ($self->name . " Debug"); print STDERR "[$title]: $msg\n"; } sub add_default_error_handler ($) { my $self = shift; $self->add_handler(M_ERROR, sub { my ($self, $event) = @_; $self->show_error($event->_text, "fvwm error"); }); } 1; __END__ =head1 NAME FVWM::Module::Toolkit - FVWM::Module with abstract widget toolkit attached =head1 SYNOPSIS 1) May be used anywhere to require external Perl classes and report error in the nice dialog if absent: use FVWM::Module::Toolkit qw(Tk X11::Protocol Tk::Balloon); use FVWM::Module::Toolkit qw(Tk=804.024,catch X11::Protocol>=0.52); There is the same syntactic sugar as in "perl -M", with an addition of ">=" being fully equivalent to "=". The ">=" form may look better for the user in the error message. If the required Perl class is absent, FVWM::Module::Toolkit->show_message() is used to show the dialog and the application dies. 2) This class should be uses to implement concrete toolkit subclasses. A new toolkit subclass implementation may look like this: package FVWM::Module::SomeToolkit; # this automatically sets the base class and tries "use SomeToolkit;" use FVWM::Module::Toolkit qw(base SomeToolkit); sub show_error ($$;$) { my ($self, $error, $title) = @_; $title ||= $self->name . " Error"; # create a dialog box using SomeToolkit widgets SomeToolkit->Dialog( -title => $title, -text => $error, -buttons => ['Close'], ); } sub event_loop ($$) { my $self = shift; my @params = @_; # enter the SomeToolkit event loop with hooking $self->{istream} $self->event_loop_prepared(@params); fileevent($self->{istream}, read => sub { unless ($self->process_packet($self->read_packet)) { $self->disconnect; $top->destroy; } $self->event_loop_prepared(@params); } ); SomeToolkit->MainLoop; $self->event_loop_finished(@params); } =head1 DESCRIPTION The B package is a sub-class of B that is intended to be uses as the base of sub-classes that attach widget toolkit library, like Perl/Tk. It does some common work to load widget toolkit libraries and to show an error in the external window like xmessage if the required libraries are not available. This class overloads one method B and expects sub-classes to overload the methods B, B and B to use native widgets. These 3 methods are implemented in this class, they extend the superclass versions by adding a title parameter and using an external dialog tool to show error/message. This manual page details only those differences. For details on the API itself, see L. =head1 METHODS Only overloaded or new methods are covered here: =over 8 =item B I [I] This method is intended to be overridden in subclasses to create a dialog box using the corresponding widgets. The default fall back implementation is similar to B<show_message>, but the error message (with title) is also always printed to STDERR. May be good for module diagnostics or any other purpose. =item B<show_message> I<msg> [I<title>] This method is intended to be overridden in subclasses to create a dialog box using the corresponding widgets. The default fall back implementation is to find a system message application to show the message. The potentially used applications are I<gdialog>, I<Xdialog>, I<zenity>, I<xmessage>, I<kdialog>, or I<xterm> as the last resort. If not given, I<title> is based on the module name. May be good for module debugging or any other purpose. =item B<show_debug> I<msg> [I<title>] This method is intended to be overridden in subclasses to create a dialog box using the corresponding widgets. The default fall back implementation is to print a message (with a title that is the module name by default) to STDERR. May be good for module debugging or any other purpose. =item B<add_default_error_handler> This methods adds a M_ERROR handler to automatically notify you that an error has been reported by fvwm. The M_ERROR handler then calls C<show_error()> with the received error text as a parameter to show it in a window. =back =head1 AUTHOR Mikhael Goikhman <migo@homemail.com>. =head1 SEE ALSO For more information, see L<fvwm>, L<FVWM::Module>, L<FVWM::Module::Tk>. =cut ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/perllib/FVWM/Module/Terminal.pm����������������������������������������������������������0000644�0001750�0001750�00000013364�14147024700�015174� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright (c) 2003-2009 Mikhael Goikhman # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see: <http://www.gnu.org/licenses/> BEGIN { if ($ENV{FVWM_MODULE_TERMINAL_CLIENT}) { my ($out_fd, $in_fd, $name, $prompt, $ornaments) = @ARGV; $name ||= "FVWM::Module::Terminal"; $prompt ||= ""; $ornaments ||= 0; $name .= " Client"; eval "use IO::File; use Term::ReadLine;"; $SIG{__DIE__} = sub { my $msg = shift; $msg =~ /(.*?)^BEGIN failed/sm and die $1; print "$name: $msg"; sleep(2); die "$name: Exiting due to errors\n"; }; die "$name: $@" if $@; my $ostream = new IO::File ">&$out_fd" or die "Can't write to file descriptor (&$out_fd)\n"; my $istream = new IO::File "<&$in_fd" or die "Can't read from file descriptor (&$in_fd)\n"; $ostream->autoflush(1); $istream->autoflush(1); # DEBUG $ostream->print("Abra ka Dabra\n"); print "($ostream) ($istream)\n"; my $term = Term::ReadLine->new($name); $term->ornaments($ornaments); my $line; while (defined($line = $term->readline($prompt))) { $ostream->print("$line\n"); } print "Closed\n"; sleep(1); exit(0); } } package FVWM::Module::Terminal; use 5.004; use strict; use FVWM::Module::Toolkit qw(base IO::Select); use General::Parse; sub new ($@) { my $class = shift; my %params = @_; my $xterm = delete $params{XTerm} || "xterm -name FvwmPerlTerminal -e"; my $prompt = delete $params{Prompt} || ""; my $ornaments = delete $params{Ornaments} || 0; my $self = $class->SUPER::new(%params); pipe(PARENT_IN, CHILD_OUT) || $self->internal_die("Can't pipe"); pipe(CHILD_IN, PARENT_OUT) || $self->internal_die("Can't pipe"); CHILD_OUT->autoflush; PARENT_OUT->autoflush; my $pid = fork; $self->internal_die("Can't fork: $!") unless defined $pid; if ($pid == 0) { close PARENT_IN; close PARENT_OUT; my $co = fileno(CHILD_OUT); my $ci = fileno(CHILD_IN); my $q = sub { local $_ = shift; s/'/\\'/g; $_ }; $ENV{FVWM_MODULE_TERMINAL_CLIENT} = 1; my @cmd = ($^X, "-w", __FILE__, $co, $ci, $self->name, $prompt, $ornaments); unshift @cmd, get_tokens($xterm); # DEBUG my $ostream = new IO::File ">&$co" or die "Can't write to file descriptor (&$co)\n"; $ostream->print("Asta la Vista\n"); print join(", ", @cmd), "\n"; { exec {$cmd[0]} @cmd } $self->internal_die("Can't fork $cmd[0]"); close CHILD_IN; close CHILD_OUT; exit 0; } close CHILD_IN; close CHILD_OUT; $self->{term_select} = new IO::Select($self->{istream}, \*PARENT_IN); $self->{term_output} = \*PARENT_OUT; return $self; } sub wait_packet ($) { my $self = shift; while (1) { my @handles = $self->{term_select}->can_read(); my ($core_input, $term_input); foreach (@handles) { ($_ == $self->{istream}? $core_input: $term_input) = $_; } if ($term_input) { my $line = $term_input->getline; unless (defined $line) { $self->debug("EOF from terminal client, terminating", 3); $self->terminate; } chomp($line); $self->debug("Got [$line] from terminal client", 4); $self->process_term_line($line); } last if $core_input; } } sub process_term_line ($$) { my $self = shift; my $line = shift; $self->show_message("I got $line!"); } 1; __END__ =head1 NAME FVWM::Module::Terminal - FVWM::Module with X terminal based solutions =head1 SYNOPSIS NOTE: This class is not functional yet. Name this module TestModuleTerminal, make it executable and place in ModulePath: #!/usr/bin/perl -w use lib `fvwm-perllib dir`; use FVWM::Module::Terminal; my $module = new FVWM::Module::Terminal( XTerm => 'rxvt', Debug => 2, Name => "TestModuleTerminal", ); my $id = undef; $module->send('Next (TestModuleTerminal) SendToModule myid $[w.id]'); $module->add_default_error_handler; $module->add_handler(M_STRING, sub { $[1]->_text =~ /^myid (.*)$/ && $id = eval $1; }; $module->add_handler(M_ICONIFY, sub { return unless defined $id; my $id0 = $_[1]->_win_id; $module->send("WindowId $id Iconify off") if $id0 == $id; }); $module->track('Scheduler')->schedule(60, sub { $module->show_message("You run this module for 1 minute") }); $module->event_loop; =head1 DESCRIPTION NOTE: This class is not functional yet. The B<FVWM::Module::Terminal> class is a sub-class of B<FVWM::Module::Toolkit> that overloads the methods B<wait_packet>, B<show_error>, B<show_message> and B<show_debug> to manage terminal functionality. This manual page details only those differences. For details on the API itself, see L<FVWM::Module>. =head1 METHODS Only overloaded or new methods are covered here: =over 8 =item B<wait_packet> Listen to the terminal read-line while waiting for the packet from fvwm. =item B<show_error> I<msg> [I<title>] Shows the error message in terminal. Useful for diagnostics of a Terminal based module. =item B<show_message> I<msg> [I<title>] Shows the message in terminal. Useful for notices by a Terminal based module. =item B<show_debug> I<msg> [I<title>] Shows the debug info in terminal. Useful for debugging a Terminal based module. =back =head1 BUGS Awaiting for your reporting. =head1 AUTHOR Mikhael Goikhman <migo@homemail.com>. =head1 SEE ALSO For more information, see L<fvwm>, L<FVWM::Module> and L<Term::ReadLine>. =cut ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/perllib/FVWM/Module/Tk.pm����������������������������������������������������������������0000644�0001750�0001750�00000020154�14147024700�013772� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright (c) 2003-2009 Mikhael Goikhman # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see: <http://www.gnu.org/licenses/> package FVWM::Module::Tk; use 5.004; use strict; use FVWM::Module::Toolkit qw(base Tk Tk::Dialog Tk::ROText); sub new ($@) { my $class = shift; # support the old API with the first top-level argument my $top = shift if @_ && UNIVERSAL::isa($_[0], "Tk::Toplevel"); my %params = @_; $top = delete $params{TopWindow} if exists $params{TopWindow}; my $self = $class->SUPER::new(%params); $self->internal_die("TopWindow given in constructor is not Tk::Toplevel") unless $top || UNIVERSAL::isa($top, "Tk::Toplevel"); unless ($top) { $top = MainWindow->new; $top->withdraw; } $self->{top_window} = $top; return $self; } sub event_loop ($) { my $self = shift; my @params = @_; $self->event_loop_prepared(@params); my $top = $self->{top_window}; $top->fileevent($self->{istream}, readable => sub { unless ($self->process_packet($self->read_packet)) { if ($self->{disconnected}) { # Seems like something does not want to exit - force it. # For example, a new Tk window is launched on ON_EXIT. $top->destroy if defined $top && defined $top->{Configure}; $self->debug("Forced to exit to escape event_loop, fix the module", 0); exit 1; } $self->event_loop_finished(@params); $top->destroy; } else { $self->event_loop_prepared(@params); } } ); MainLoop; } sub show_error ($$;$) { my $self = shift; my $error = shift; my $title = shift || ($self->name . " Error"); my $top = $self->{top_window}; my $dialog = $top->Dialog( -title => $title, -bitmap => 'error', -default_button => 'Close', -text => $error, -buttons => ['Close', 'Close All Errors', 'Exit Module'], ); my $btn = $dialog->Show; $self->terminate if $btn eq 'Exit Module'; $self->send("All ('$title') Close") if $btn eq 'Close All Errors'; } sub show_message ($$;$) { my $self = shift; my $msg = shift; my $title = shift || ($self->name . " Message"); $self->{top_window}->messageBox( -icon => 'info', -type => 'ok', -title => $title, -message => $msg, ); } sub show_debug ($$;$) { my $self = shift; my $msg = shift; my $title = shift || ($self->name . " Debug"); my $dialog = $self->{tk_debug_dialog}; my $top = $self->{top_window}; unless (defined $top && defined $top->{Configure}) { # in the constructor (too early) or in destructor (too late) $self->FVWM::Module::Toolkit::show_debug($msg, $title); return; } if (!$dialog) { # Tk's Dialog widgets are too damn inflexible. # It's less hassle to build one from scratch. $dialog = $top->Toplevel(-title => $title); my $scroll = $dialog->Frame()->pack(-expand => 1, -fill => 'both'); my $bottom = $dialog->Frame()->pack(-expand => 0, -fill => 'x'); my $text = $scroll->Scrolled('ROText', -bg => 'white', -wrap => 'word', -scrollbars => 'oe', )->pack(-expand => 1, -fill => 'both'); $dialog->protocol('WM_DELETE_WINDOW', sub { $dialog->withdraw(); }); my @pack_opts = (-side => 'left', -expand => 1, -fill => 'both'); $bottom->Button( -text => 'Close', -command => sub { $dialog->withdraw(); }, )->pack(@pack_opts); $bottom->Button( -text => 'Clear', -command => sub { $text->delete('0.0', 'end'); }, )->pack(@pack_opts); $bottom->Button( -text => 'Save', -command => sub { my $file = $dialog->getSaveFile(-title => "Save $title"); return unless defined $file; if (!open(OUT, ">$file")) { $self->show_error("Couldn't save $file: $!", 'Save Error'); return; } print OUT $text->get('0.0', 'end'); close(OUT); }, )->pack(@pack_opts); $self->{tk_debug_dialog} = $dialog; $self->{tk_debug_text_wg} = $text; } else { $dialog->deiconify() if $dialog->state() eq 'withdrawn'; } my $text = $self->{tk_debug_text_wg}; $text->insert('end', "$msg\n"); $text->see('end'); } sub top_window ($) { return shift->{top_window}; } 1; __END__ =head1 NAME FVWM::Module::Tk - FVWM::Module with the Tk widget library attached =head1 SYNOPSIS Name this module TestModuleTk, make it executable and place in ModulePath: #!/usr/bin/perl -w use lib `fvwm-perllib dir`; use FVWM::Module::Tk; use Tk; # preferably in this order my $top = new MainWindow(-name => "Simple Test"); my $id = $top->wrapper->[0]; my $module = new FVWM::Module::Tk( TopWindow => $top, Mask => M_ICONIFY | M_ERROR, # Mask may be omitted Debug => 2, ); $top->Button( -text => "Close", -command => sub { $top->destroy; } )->pack; $module->add_default_error_handler; $module->add_handler(M_ICONIFY, sub { my $id0 = $_[1]->_win_id; $module->send("Iconify off", $id) if $id0 == $id; }); $module->track('Scheduler')->schedule(60, sub { $module->show_message("You run this module for 1 minute") }); $module->send('Style "*imple Test" Sticky'); $module->event_loop; =head1 DESCRIPTION The B<FVWM::Module::Tk> class is a sub-class of B<FVWM::Module::Toolkit> that overloads the methods B<new>, B<event_loop>, B<show_message>, B<show_debug> and B<show_error> to manage Tk objects as well. It also adds new method B<top_window>. This manual page details only those differences. For details on the API itself, see L<FVWM::Module>. =head1 METHODS Only overloaded or new methods are covered here: =over 8 =item B<new> I<param-hash> $module = new B<FVWM::Module::Tk> I<TopWindow> => $top, %params Create and return an object of the B<FVWM::Module::Tk> class. This B<new> method is identical to the (grand-)parent class method, with the exception that a Tk top-level of some sort (MainWindow, TopLevel, Frame, etc.) may be passed in the hash of options using the I<TopWindow> named value. Other options in I<param-hash> are the same as described in L<FVWM::Module>. If no top-level window is specified in the constructor, such dummy window is created and immediately withdrawn. This top-level window is needed to create Tk dialogs. =item B<event_loop> From outward appearances, this methods operates just as the parent B<event_loop> does. It is worth mentioning, however, that this version enters into the Tk B<MainLoop> subroutine, ostensibly not to return. =item B<show_error> I<msg> [I<title>] This method creates a dialog box using the Tk widgets. The dialog has three buttons labeled "Close", "Close All Errors" and "Exit Module". Selecting the "Close" button closes the dialog. "Close All Errors" closes all error dialogs that may be open on the screen at that time. "Exit Module" terminates your entire module. Good for diagnostics of a Tk based module. =item B<show_message> I<msg> [I<title>] Creates a message window with one "Ok" button. Useful for notices by a Tk based module. =item B<show_debug> I<msg> [I<title>] Creates a debug window with 3 buttons "Close", "Clear" and "Save". All debug messages are added to the debug window. "Close" withdraws the window until the next debug message arrives. "Clear" erases the current contents of the debug window. "Save" dumps the current contents of the debug window to the selected file. Useful for debugging a Tk based module. =item B<top_window> Returns the Tk toplevel that this object was created with. =back =head1 BUGS Would not surprise me in the least. =head1 AUTHOR Mikhael Goikhman <migo@homemail.com>. =head1 THANKS TO Randy J. Ray <randy@byz.org>, author of the old classes B<X11::Fvwm> and B<X11::Fvwm::Tk>. Scott Smedley <ss@aao.gov.au>. Nick Ing-Simmons <Nick.Ing-Simmons@tiuk.ti.com> for Tk Perl extension. =head1 SEE ALSO For more information, see L<fvwm>, L<FVWM::Module> and L<Tk>. =cut ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/perllib/FVWM/Module/Makefile.am����������������������������������������������������������0000644�0001750�0001750�00000000255�14147024700�015112� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Process this file with automake to create Makefile.in configdir = @FVWM_PERLLIBDIR@/FVWM/Module config_DATA = Toolkit.pm Terminal.pm Tk.pm EXTRA_DIST = $(config_DATA) ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/perllib/FVWM/Makefile.in�����������������������������������������������������������������0000644�0001750�0001750�00000057203�14324315776�013720� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 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 = perllib/FVWM ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.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 = Module.pm 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)$(configdir)" DATA = $(config_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)` DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Module.pm.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" ACLOCAL = @ACLOCAL@ ALL_DOMAINS = @ALL_DOMAINS@ ALL_LINGUAS = @ALL_LINGUAS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR_FLAGS = @AR_FLAGS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ Bidi_CFLAGS = @Bidi_CFLAGS@ Bidi_LIBS = @Bidi_LIBS@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DOC_COMMANDS = @DOC_COMMANDS@ DOC_COMMANDS_HTML = @DOC_COMMANDS_HTML@ DOC_COMMANDS_XML = @DOC_COMMANDS_XML@ DOC_COMMANDS_XML_PATH = @DOC_COMMANDS_XML_PATH@ DOC_MODULES = @DOC_MODULES@ DOC_MODULES_HTML = @DOC_MODULES_HTML@ DOC_SECTIONS = @DOC_SECTIONS@ DOC_SECTIONS_XML = @DOC_SECTIONS_XML@ DOC_SECTIONS_XML_PATH = @DOC_SECTIONS_XML_PATH@ DUMMYPOFILES = @DUMMYPOFILES@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FC_CFLAGS = @FC_CFLAGS@ FC_CONFIG = @FC_CONFIG@ FC_LIBS = @FC_LIBS@ FRIBIDI_CONFIG = @FRIBIDI_CONFIG@ FVWMALTFTP = @FVWMALTFTP@ FVWMALTFTPDIR = @FVWMALTFTPDIR@ FVWMFTP = @FVWMFTP@ FVWMFTPDIR = @FVWMFTPDIR@ FVWMHOMEPAGE = @FVWMHOMEPAGE@ FVWMLIST = @FVWMLIST@ FVWMNAMELONG = @FVWMNAMELONG@ FVWMSCRIPT_DOMAIN = @FVWMSCRIPT_DOMAIN@ FVWMTASKBAR_DOMAIN = @FVWMTASKBAR_DOMAIN@ FVWMWORKERSLIST = @FVWMWORKERSLIST@ FVWMWORKERSLISTLONG = @FVWMWORKERSLISTLONG@ FVWM_CONFDIR = @FVWM_CONFDIR@ FVWM_CPP = @FVWM_CPP@ FVWM_DATADIR = @FVWM_DATADIR@ FVWM_DOCDIR = @FVWM_DOCDIR@ FVWM_DOMAIN = @FVWM_DOMAIN@ FVWM_IMAGEPATH = @FVWM_IMAGEPATH@ FVWM_MODULEDIR = @FVWM_MODULEDIR@ FVWM_PERLLIB = @FVWM_PERLLIB@ FVWM_PERLLIBDIR = @FVWM_PERLLIBDIR@ GDK_IMLIB_CFLAGS = @GDK_IMLIB_CFLAGS@ GDK_IMLIB_LIBS = @GDK_IMLIB_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ IMLIBCONF = @IMLIBCONF@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INST_LINGUAS = @INST_LINGUAS@ ISRELEASED = @ISRELEASED@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOCALEDIR = @LOCALEDIR@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANPAGE_PREAMBLE = @MANPAGE_PREAMBLE@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ MSGUNIQ = @MSGUNIQ@ OBJEXT = @OBJEXT@ 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@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PYTHON = @PYTHON@ RANLIB = @RANLIB@ RELDATELONG = @RELDATELONG@ RELDATENUM = @RELDATENUM@ RELDATESHORT = @RELDATESHORT@ REQUIRED_PERL_VERSION = @REQUIRED_PERL_VERSION@ REQUIRED_PYTHON_VERSION = @REQUIRED_PYTHON_VERSION@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ UPDATEPOFILES = @UPDATEPOFILES@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VERSIONINFO = @VERSIONINFO@ XFT_CFLAGS = @XFT_CFLAGS@ XFT_CONFIG = @XFT_CONFIG@ XFT_LIBS = @XFT_LIBS@ XGETTEXT = @XGETTEXT@ XMKMF = @XMKMF@ XSLTPROC = @XSLTPROC@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Xcursor_CFLAGS = @Xcursor_CFLAGS@ Xcursor_LIBS = @Xcursor_LIBS@ Xft_CFLAGS = @Xft_CFLAGS@ Xft_LIBS = @Xft_LIBS@ Xinerama_CFLAGS = @Xinerama_CFLAGS@ Xinerama_LIBS = @Xinerama_LIBS@ Xrender_CFLAGS = @Xrender_CFLAGS@ Xrender_LIBS = @Xrender_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ iconv_CFLAGS = @iconv_CFLAGS@ iconv_LIBS = @iconv_LIBS@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intl_CFLAGS = @intl_CFLAGS@ intl_LIBS = @intl_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ png_CFLAGS = @png_CFLAGS@ png_LIBS = @png_LIBS@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ readline_CFLAGS = @readline_CFLAGS@ readline_LIBS = @readline_LIBS@ rplay_CFLAGS = @rplay_CFLAGS@ rplay_LIBS = @rplay_LIBS@ rsvg_CFLAGS = @rsvg_CFLAGS@ rsvg_LIBS = @rsvg_LIBS@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ stroke_CFLAGS = @stroke_CFLAGS@ stroke_LIBS = @stroke_LIBS@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ with_bidi = @with_bidi@ with_gdkimlib = @with_gdkimlib@ with_gettext = @with_gettext@ with_iconv = @with_iconv@ with_perllib = @with_perllib@ with_png = @with_png@ with_readline = @with_readline@ with_rplay = @with_rplay@ with_rsvg = @with_rsvg@ with_shape = @with_shape@ with_shm = @with_shm@ with_sm = @with_sm@ with_stroke = @with_stroke@ with_xcursor = @with_xcursor@ with_xft = @with_xft@ with_xinerama = @with_xinerama@ with_xpm = @with_xpm@ with_xrender = @with_xrender@ xpm_CFLAGS = @xpm_CFLAGS@ xpm_LIBS = @xpm_LIBS@ SUBDIRS = Module Tracker configdir = @FVWM_PERLLIBDIR@/FVWM ORIGINAL_PMS = \ Commands.pm Constants.pm EventNames.pm Event.pm Tracker.pm config_DATA = $(ORIGINAL_PMS) Module.pm EXTRA_DIST = $(ORIGINAL_PMS) create-commands create-constants all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(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) --foreign perllib/FVWM/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign perllib/FVWM/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: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): Module.pm: $(top_builddir)/config.status $(srcdir)/Module.pm.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-configDATA: $(config_DATA) @$(NORMAL_INSTALL) @list='$(config_DATA)'; test -n "$(configdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(configdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(configdir)" || 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)$(configdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(configdir)" || exit $$?; \ done uninstall-configDATA: @$(NORMAL_UNINSTALL) @list='$(config_DATA)'; test -n "$(configdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(configdir)'; $(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)$(configdir)"; 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 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-configDATA 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 pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-configDATA .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic cscopelist-am ctags ctags-am \ distclean distclean-generic distclean-tags distdir dvi dvi-am \ html html-am info info-am install install-am \ install-configDATA install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \ tags-am uninstall uninstall-am uninstall-configDATA .PRECIOUS: Makefile _Constants.pm: Makefile.am $(top_srcdir)/libs/Module.h cd $(top_builddir)/perllib/FVWM && \ (fvwm_libdir=$(top_builddir)/libs ./create-constants) _Commands.pm: Makefile $(top_srcdir)/fvwm/functable.c cd $(top_builddir)/perllib/FVWM && \ (fvwm_libdir=$(top_builddir)/libs ./create-commands) regenerate: _Constants.pm _Commands.pm # 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: ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/perllib/FVWM/Commands.pm�����������������������������������������������������������������0000644�0001750�0001750�00000057604�14147024700�013742� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Autogenerated from the fvwm sources. package FVWM::Commands; use vars qw($VERS $TIME @LIST); $VERS = '2.6.6 (from cvs)'; $TIME = 1410306754; @LIST = ( { name => '#', cursor => '', window => 0, descr => q{Comment line (ignored)}, }, { name => '*', cursor => '', window => 0, descr => q{Module configuration line (no space after asterisk)}, }, { name => '+', cursor => '', window => 0, descr => q{Continue the last AddToFunc, AddToMenu or AddToDecor}, }, { name => 'AddButtonStyle', cursor => '', window => 0, descr => q{Add to a button style (see ButtonStyle)}, }, { name => 'AddTitleStyle', cursor => '', window => 0, descr => q{Add to a title style (see TitleStyle)}, }, { name => 'AddToDecor', cursor => '', window => 0, descr => q{Add a decor definition (will be obsolete)}, }, { name => 'AddToFunc', cursor => '', window => 0, descr => q{Add a function definition}, }, { name => 'AddToMenu', cursor => '', window => 0, descr => q{Add a menu definition}, }, { name => 'All', cursor => '', window => 0, descr => q{Operate on all windows matching the given condition}, }, { name => 'AnimatedMove', cursor => 'MOVE', window => 1, descr => q{Like Move, but uses animation to move windows}, }, { name => 'Any', cursor => '', window => 0, descr => q{Operate if there is any window matching the condition}, }, { name => 'Beep', cursor => '', window => 0, descr => q{Produce a bell}, }, { name => 'BorderStyle', cursor => '', window => 0, descr => q{Define a window border look (will be reworked)}, }, { name => 'Break', cursor => '', window => 0, descr => q{Stop executing the current (but not parent) function}, }, { name => 'BugOpts', cursor => '', window => 0, descr => q{Set some application bug workarounds}, }, { name => 'BusyCursor', cursor => '', window => 0, descr => q{Show/don't show the wait cursor in certain operations}, }, { name => 'ButtonState', cursor => '', window => 0, descr => q{Disable some titlebar button states (not recommended)}, }, { name => 'ButtonStyle', cursor => '', window => 0, descr => q{Define a window button look (will be reworked)}, }, { name => 'ChangeDecor', cursor => 'SELECT', window => 1, descr => q{Attach decor to a window (will be obsolete)}, }, { name => 'ChangeMenuStyle', cursor => '', window => 0, descr => q{Attach menu style to a menu (see MenuStyle)}, }, { name => 'CleanupColorsets', cursor => '', window => 0, descr => q{Reset all used colorsets with the default gray colors}, }, { name => 'ClickTime', cursor => '', window => 0, descr => q{Set a time in milliseconds for click and double click}, }, { name => 'Close', cursor => 'DESTROY', window => 1, descr => q{Try to Delete a window, if this fails, Destroy it}, }, { name => 'ColorLimit', cursor => '', window => 0, descr => q{Set limit on colors used (obsolete)}, }, { name => 'ColormapFocus', cursor => '', window => 0, descr => q{Change the colormap behaviour for low-depth X servers}, }, { name => 'Colorset', cursor => '', window => 0, descr => q{Manage colors used like fg, bg, image bg, gradient bg}, }, { name => 'CopyMenuStyle', cursor => '', window => 0, descr => q{Copy the existing menu style to new or existing one}, }, { name => 'Current', cursor => '', window => 0, descr => q{Operate on the currently focused window}, }, { name => 'CursorMove', cursor => '', window => 0, descr => q{Move the cursor pointer non interactively}, }, { name => 'CursorStyle', cursor => '', window => 0, descr => q{Define different cursor pointer shapes and colors}, }, { name => 'DefaultColors', cursor => '', window => 0, descr => q{Set colors for the feedback window (will be obsolete)}, }, { name => 'DefaultColorset', cursor => '', window => 0, descr => q{Set colors for the Move/Resize feedback window}, }, { name => 'DefaultFont', cursor => '', window => 0, descr => q{The default font to use (mainly for feedback window)}, }, { name => 'DefaultIcon', cursor => '', window => 0, descr => q{The default icon to use for iconified windows}, }, { name => 'DefaultLayers', cursor => '', window => 0, descr => q{Set StaysOnBottom, StaysPut, StaysOnTop layer numbers}, }, { name => 'Delete', cursor => 'DESTROY', window => 1, descr => q{Try to delete a window using the X delete protocol}, }, { name => 'Deschedule', cursor => '', window => 0, descr => q{Remove commands sheduled earlier using Schedule}, }, { name => 'Desk', cursor => '', window => 0, descr => q{(obsolete, use GotoDesk instead)}, }, { name => 'DesktopName', cursor => '', window => 0, descr => q{Define the desktop names used in WindowList, modules}, }, { name => 'DesktopSize', cursor => '', window => 0, descr => q{Set virtual desktop size in units of physical pages}, }, { name => 'Destroy', cursor => 'DESTROY', window => 1, descr => q{Kill a window without any warning to an application}, }, { name => 'DestroyDecor', cursor => '', window => 0, descr => q{Delete decor defined by AddToDecor (will be obsolete)}, }, { name => 'DestroyFunc', cursor => '', window => 0, descr => q{Delete function defined using AddToFunc}, }, { name => 'DestroyMenu', cursor => '', window => 0, descr => q{Delete menu defined using AddToMenu}, }, { name => 'DestroyMenuStyle', cursor => '', window => 0, descr => q{Delete menu style defined using MenuStyle}, }, { name => 'DestroyModuleConfig', cursor => '', window => 0, descr => q{Delete matching module config lines defined using "*"}, }, { name => 'DestroyStyle', cursor => '', window => 0, descr => q{Delete style defined using Style}, }, { name => 'DestroyWindowStyle', cursor => 'SELECT', window => 1, descr => q{Delete style defined using WindowStyle}, }, { name => 'Direction', cursor => '', window => 0, descr => q{Operate on the next window in the specified direction}, }, { name => 'Echo', cursor => '', window => 0, descr => q{Print message to stderr, mainly for debugging}, }, { name => 'EchoFuncDefinition', cursor => '', window => 0, descr => q{Print the definion of a function}, }, { name => 'EdgeCommand', cursor => '', window => 0, descr => q{Bind one or another screen edge to an fvwm action}, }, { name => 'EdgeLeaveCommand', cursor => '', window => 0, descr => q{Bind one or another screen edge to an fvwm action}, }, { name => 'EdgeResistance', cursor => '', window => 0, descr => q{Control viewport scrolling and window move over edge}, }, { name => 'EdgeScroll', cursor => '', window => 0, descr => q{Control how much of the viewport is scrolled if any}, }, { name => 'EdgeThickness', cursor => '', window => 0, descr => q{Control how closely to edge to run command/scrolling}, }, { name => 'Emulate', cursor => '', window => 0, descr => q{Only used to position the position/size window}, }, { name => 'EscapeFunc', cursor => '', window => 0, descr => q{Abort a wait or ModuleSynchonous command}, }, { name => 'EwmhBaseStruts', cursor => '', window => 0, descr => q{Define restricted areas of the screen}, }, { name => 'EwmhNumberOfDesktops', cursor => '', window => 0, descr => q{For ewmh pager, define number of desktops}, }, { name => 'Exec', cursor => '', window => 0, descr => q{Execute an external command}, }, { name => 'ExecUseShell', cursor => '', window => 0, descr => q{The shell to use to execute an external command}, }, { name => 'FakeClick', cursor => '', window => 0, descr => q{Generate a mouse click}, }, { name => 'FakeKeypress', cursor => '', window => 0, descr => q{Send a keyboard event to a window}, }, { name => 'FlipFocus', cursor => 'SELECT', window => 1, descr => q{Focus a window without rotating windowlist order}, }, { name => 'Focus', cursor => 'SELECT', window => 1, descr => q{Give focus to a window}, }, { name => 'FocusStyle', cursor => '', window => 0, descr => q{Configure focus and raise policy for windows}, }, { name => 'Function', cursor => '', window => 0, descr => q{Execute a user defined function, see AddToFunc}, }, { name => 'GlobalOpts', cursor => '', window => 0, descr => q{(obsolete, use corresponding Style * instead)}, }, { name => 'GnomeButton', cursor => '', window => 0, descr => q{Pass mouse button presses on root to GNOME program}, }, { name => 'GnomeShowDesks', cursor => '', window => 0, descr => q{Limit GNOME pager to the number of desks}, }, { name => 'GotoDesk', cursor => '', window => 0, descr => q{Switch viewport to another desk same page}, }, { name => 'GotoDeskAndPage', cursor => '', window => 0, descr => q{Switch viewport to another desk and page}, }, { name => 'GotoPage', cursor => '', window => 0, descr => q{Switch viewport to another page same desk}, }, { name => 'HideGeometryWindow', cursor => '', window => 0, descr => q{Hide/show the position/size window}, }, { name => 'HilightColor', cursor => '', window => 0, descr => q{(obsolete, use Style * HighlightFore/Back)}, }, { name => 'HilightColorset', cursor => '', window => 0, descr => q{(obsolete, use Style * HighlightColorset)}, }, { name => 'IconFont', cursor => '', window => 0, descr => q{(obsolete, use Style * IconFont)}, }, { name => 'Iconify', cursor => 'SELECT', window => 1, descr => q{Change iconification status of a window (minimize)}, }, { name => 'IconPath', cursor => '', window => 0, descr => q{(obsolete, use ImagePath instead)}, }, { name => 'IgnoreModifiers', cursor => '', window => 0, descr => q{Modifiers to ignore on mouse and key bindings}, }, { name => 'ImagePath', cursor => '', window => 0, descr => q{Directories to search for images}, }, { name => 'InfoStoreAdd', cursor => '', window => 0, descr => q{Adds an entry (key/value pairs) to the infostore}, }, { name => 'InfoStoreRemove', cursor => '', window => 0, descr => q{Removes an entry from the infostore}, }, { name => '- KeepRc', cursor => '', window => 0, descr => q{Do not modify the previous command return code}, }, { name => 'Key', cursor => '', window => 0, descr => q{Bind or unbind a key to an fvwm action}, }, { name => 'KillModule', cursor => '', window => 0, descr => q{Stops an fvwm module}, }, { name => 'Layer', cursor => 'SELECT', window => 1, descr => q{Change the layer of a window}, }, { name => 'LocalePath', cursor => '', window => 0, descr => q{Directories/domains to search for locale data}, }, { name => 'Lower', cursor => 'SELECT', window => 1, descr => q{Lower a window within a layer}, }, { name => 'Maximize', cursor => 'SELECT', window => 1, descr => q{Toggle maximal-size status of a window}, }, { name => 'Menu', cursor => '', window => 0, descr => q{Display (post) a menu}, }, { name => 'MenuStyle', cursor => '', window => 0, descr => q{Control appearance and behavior of a menu}, }, { name => 'Module', cursor => '', window => 0, descr => q{Invoke an fvwm module}, }, { name => 'ModuleListenOnly', cursor => '', window => 0, descr => q{Invoke an fvwm module}, }, { name => 'ModulePath', cursor => '', window => 0, descr => q{Modify the directories to search for an fvwm module}, }, { name => 'ModuleSynchronous', cursor => '', window => 0, descr => q{Invoke an fvwm module synchronously}, }, { name => 'ModuleTimeout', cursor => '', window => 0, descr => q{Set timeout value for response from module}, }, { name => 'Mouse', cursor => '', window => 0, descr => q{Bind or unbind a mouse button press to an fvwm action}, }, { name => 'Move', cursor => 'MOVE', window => 1, descr => q{Move a window}, }, { name => 'MoveThreshold', cursor => '', window => 0, descr => q{Set number of pixels in a click and a hold vs. a drag}, }, { name => 'MoveToDesk', cursor => 'SELECT', window => 1, descr => q{Move a window to another desk same page}, }, { name => 'MoveToPage', cursor => 'SELECT', window => 1, descr => q{Move a window to another page same desk}, }, { name => 'MoveToScreen', cursor => 'SELECT', window => 1, descr => q{Move a window to another Xinerama screen}, }, { name => 'Next', cursor => '', window => 0, descr => q{Operate on the next window matching conditions}, }, { name => 'None', cursor => '', window => 0, descr => q{Perform command if no window matches conditions}, }, { name => 'Nop', cursor => '', window => 0, descr => q{Do nothing (used internally)}, }, { name => 'NoWindow', cursor => '', window => 0, descr => q{Prefix that runs a command without a window context}, }, { name => 'OpaqueMoveSize', cursor => '', window => 0, descr => q{Set maximum size window fvwm should move opaquely}, }, { name => 'Pick', cursor => 'SELECT', window => 1, descr => q{Prefix to force a window context, prompted if needed}, }, { name => 'PipeRead', cursor => '', window => 0, descr => q{Exec system command interpret output as fvwm commands}, }, { name => 'PixmapPath', cursor => '', window => 0, descr => q{(obsolete, use ImagePath instead)}, }, { name => 'PlaceAgain', cursor => 'SELECT', window => 1, descr => q{Replace a window using initial window placement logic}, }, { name => 'PointerKey', cursor => '', window => 0, descr => q{Bind an action to a key based on pointer not focus}, }, { name => 'PointerWindow', cursor => '', window => 0, descr => q{Operate on window under pointer if it meets conditions}, }, { name => 'Popup', cursor => '', window => 0, descr => q{Display (pop-up) a menu, see also Menu}, }, { name => 'Prev', cursor => '', window => 0, descr => q{Operate on the precious window matching conditions}, }, { name => 'PrintInfo', cursor => '', window => 0, descr => q{Print information about the state of fvwm}, }, { name => 'PropertyChange', cursor => '', window => 0, descr => q{Internal, used for inter-module communication}, }, { name => 'Quit', cursor => '', window => 0, descr => q{Exit fvwm}, }, { name => 'QuitScreen', cursor => '', window => 0, descr => q{Stop managing the specified screen}, }, { name => 'QuitSession', cursor => '', window => 0, descr => q{Ask session manager to shut down itself and fvwm}, }, { name => 'Raise', cursor => 'SELECT', window => 1, descr => q{Raise a window in a layer}, }, { name => 'RaiseLower', cursor => 'SELECT', window => 1, descr => q{Alternately raise or lower a window in a layer}, }, { name => 'Read', cursor => '', window => 0, descr => q{Read fvwm commands from a file}, }, { name => 'ReadWriteColors', cursor => '', window => 0, descr => q{Used for colorset speed hacks (will be removed?)}, }, { name => 'Recapture', cursor => '', window => 0, descr => q{Reapply styles to all windows (will be obsolete)}, }, { name => 'RecaptureWindow', cursor => 'SELECT', window => 1, descr => q{Reapply styles to one window (will be obsolete)}, }, { name => 'Refresh', cursor => '', window => 0, descr => q{Cause all windows to redraw themselves}, }, { name => 'RefreshWindow', cursor => 'SELECT', window => 1, descr => q{Cause one window to redraw itself}, }, { name => 'Repeat', cursor => '', window => 0, descr => q{Repeat (very unreliably) the last command, don't use}, }, { name => 'Resize', cursor => 'RESIZE', window => 1, descr => q{Cause a window to be resized}, }, { name => 'ResizeMaximize', cursor => 'RESIZE', window => 1, descr => q{Resize a window and mark window as maximized}, }, { name => 'ResizeMove', cursor => 'RESIZE', window => 1, descr => q{Resize and move in one operation}, }, { name => 'ResizeMoveMaximize', cursor => 'RESIZE', window => 1, descr => q{Resize and move in one operation and mark maximized}, }, { name => 'RestackTransients', cursor => 'SELECT', window => 1, descr => q{Regroup the window transients in the stack}, }, { name => 'Restart', cursor => '', window => 0, descr => q{Restart itself or replace with another window manager}, }, { name => 'SaveQuitSession', cursor => '', window => 0, descr => q{Cause session manager to save and shutdown fvwm}, }, { name => 'SaveSession', cursor => '', window => 0, descr => q{Cause session manager to save the session}, }, { name => 'ScanForWindow', cursor => '', window => 0, descr => q{Operate on the matching window in the given direction}, }, { name => 'Schedule', cursor => '', window => 0, descr => q{Run an fvwm command after a delay}, }, { name => 'Scroll', cursor => '', window => 0, descr => q{Scroll the desktop viewport}, }, { name => 'Send_ConfigInfo', cursor => '', window => 0, descr => q{Internal, used for module communication}, }, { name => 'Send_Reply', cursor => '', window => 0, descr => q{Internal, used for module communication}, }, { name => 'Send_WindowList', cursor => '', window => 0, descr => q{Internal, used for module communication}, }, { name => 'SendToModule', cursor => '', window => 0, descr => q{Send a string (action) to a module}, }, { name => 'set_mask', cursor => '', window => 0, descr => q{Internal, used for module communication}, }, { name => 'set_nograb_mask', cursor => '', window => 0, descr => q{Internal, used for module communication}, }, { name => 'set_sync_mask', cursor => '', window => 0, descr => q{Internal, used for module communication}, }, { name => 'SetAnimation', cursor => '', window => 0, descr => q{Control animated moves and menus}, }, { name => 'SetEnv', cursor => '', window => 0, descr => q{Set an environment variable}, }, { name => 'Silent', cursor => '', window => 0, descr => q{Suppress errors on command, avoid window selection}, }, { name => 'SnapAttraction', cursor => '', window => 0, descr => q{Control attraction of windows during move}, }, { name => 'SnapGrid', cursor => '', window => 0, descr => q{Control grid used with SnapAttraction}, }, { name => 'State', cursor => 'SELECT', window => 1, descr => q{Control user defined window states}, }, { name => 'Stick', cursor => 'SELECT', window => 1, descr => q{Change window stickyness}, }, { name => 'StickAcrossDesks', cursor => 'SELECT', window => 1, descr => q{Change window stickyness on a desk basis}, }, { name => 'StickAcrossPages', cursor => 'SELECT', window => 1, descr => q{Change window stickyness on a page basis}, }, { name => 'Stroke', cursor => '', window => 0, descr => q{Bind a stroke to an fvwm action}, }, { name => 'StrokeFunc', cursor => '', window => 0, descr => q{Record stroke and execute corresponding stroke action}, }, { name => 'Style', cursor => '', window => 0, descr => q{Set attributes of windows that match a pattern}, }, { name => 'TearMenuOff', cursor => '', window => 0, descr => q{Convert a menu to a window, for use in menu items}, }, { name => 'Test', cursor => '', window => 0, descr => q{Execute command if conditions are met}, }, { name => 'TestRc', cursor => '', window => 0, descr => q{Conditional switch (may be changed)}, }, { name => 'ThisWindow', cursor => '', window => 0, descr => q{Operate on the context window if it meets conditions}, }, { name => 'Title', cursor => '', window => 0, descr => q{Insert title into a menu}, }, { name => 'TitleStyle', cursor => '', window => 0, descr => q{Control window title}, }, { name => 'UnsetEnv', cursor => '', window => 0, descr => q{Remove an environment variable}, }, { name => 'UpdateDecor', cursor => '', window => 0, descr => q{Update window decor (obsolete and not needed anymore)}, }, { name => 'UpdateStyles', cursor => '', window => 0, descr => q{Cause styles to update while still in a function}, }, { name => 'Wait', cursor => '', window => 0, descr => q{Pause until a matching window appears}, }, { name => 'WarpToWindow', cursor => 'SELECT', window => 1, descr => q{Warp the pointer to a window}, }, { name => 'WindowFont', cursor => '', window => 0, descr => q{(obsolete, use Style * Font)}, }, { name => 'WindowId', cursor => '', window => 0, descr => q{Execute command for window matching the windowid}, }, { name => 'WindowList', cursor => '', window => 0, descr => q{Display the window list as a menu to select a window}, }, { name => 'WindowShade', cursor => 'SELECT', window => 1, descr => q{Shade/unshade a window}, }, { name => 'WindowShadeAnimate', cursor => '', window => 0, descr => q{(obsolete, use Style * WindowShadeSteps)}, }, { name => 'WindowStyle', cursor => 'SELECT', window => 1, descr => q{Set styles on the selected window}, }, { name => 'Xinerama', cursor => '', window => 0, descr => q{Control Xinerama support}, }, { name => 'XineramaPrimaryScreen', cursor => '', window => 0, descr => q{Identify Xinerama primary screen}, }, { name => 'XineramaSls', cursor => '', window => 0, descr => q{Control single logical screen support}, }, { name => 'XineramaSlsScreens', cursor => '', window => 0, descr => q{Configure layout for single logical screen}, }, { name => 'XineramaSlsSize', cursor => '', window => 0, descr => q{Configure layout for single logical screen sizes}, }, { name => 'XorPixmap', cursor => '', window => 0, descr => q{Use a pixmap for move/resize rubber-band}, }, { name => 'XorValue', cursor => '', window => 0, descr => q{Change bits used for move/resize rubber-band}, }, { name => 'XSync', cursor => '', window => 0, descr => q{For debugging, send all pending requests to X server}, }, { name => 'XSynchronize', cursor => '', window => 0, descr => q{For debugging, cause all X requests to be synchronous}, }, ); 1; __END__ =head1 NAME FVWM::Commands - lists all available fvwm commands =head1 DESCRIPTION This class is autogenerated from the fvwm sources. It may be used to get a list of all available fvwm commands including the command name, its short description and some other command properties. =head1 USAGE use lib `fvwm-perllib dir`; use FVWM::Commands; use POSIX; my $date = strftime("%d-%b-%Y", gmtime($FVWM::Commands::TIME)); my $version = $FVWM::Commands::VERS; print "The recognized commands for fvwm $version as of $date:\n\n"; foreach my $command (@FVWM::Commands::LIST) { printf " %-21s - %s\n", $command->{name}, $command->{descr}; } =head1 PUBLIC CONSTANTS =over 4 =item $VERS The fvwm version number at the generation time like "2.6.0" plus the info that may indicate that this is not a final version, but a cvs snapshot. =item $TIME The unix time of the command list generation. Example: print "The fvwm command list found on your system was generated " . (time() - $FVWM::Commands::TIME) / 86400 . " days ago\n"; =item @LIST The command list that is an array of hashes with keys I<name>, I<cursor>, I<descr> (string) and I<window> (boolean). I<name> may be special, like "+", "#" and "*". Other names usually contain only isalpha characters, like B<Move>, B<SendToModule>. I<cursor> may be either empty or the cursor context used in B<CursorStyle> (like "SELECT" or "MOVE"), associated with the command. I<descr> is a short one line description of the command. I<window> is true for commands that need a window. Example: # get command names only @command_names = map { $_->{name} } @FVWM::Commands::LIST; =back =head1 AUTHOR Mikhael Goikhman <migo@homemail.com>. =head1 SEE ALSO For more information about the commands themselves, see fvwm(1). =cut ����������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/perllib/FVWM/Tracker/��������������������������������������������������������������������0000755�0001750�0001750�00000000000�14324316055�013306� 5����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/perllib/FVWM/Tracker/Makefile.in���������������������������������������������������������0000644�0001750�0001750�00000041621�14324315776�015310� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 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 = perllib/FVWM/Tracker ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.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)$(configdir)" DATA = $(config_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALL_DOMAINS = @ALL_DOMAINS@ ALL_LINGUAS = @ALL_LINGUAS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR_FLAGS = @AR_FLAGS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ Bidi_CFLAGS = @Bidi_CFLAGS@ Bidi_LIBS = @Bidi_LIBS@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DOC_COMMANDS = @DOC_COMMANDS@ DOC_COMMANDS_HTML = @DOC_COMMANDS_HTML@ DOC_COMMANDS_XML = @DOC_COMMANDS_XML@ DOC_COMMANDS_XML_PATH = @DOC_COMMANDS_XML_PATH@ DOC_MODULES = @DOC_MODULES@ DOC_MODULES_HTML = @DOC_MODULES_HTML@ DOC_SECTIONS = @DOC_SECTIONS@ DOC_SECTIONS_XML = @DOC_SECTIONS_XML@ DOC_SECTIONS_XML_PATH = @DOC_SECTIONS_XML_PATH@ DUMMYPOFILES = @DUMMYPOFILES@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FC_CFLAGS = @FC_CFLAGS@ FC_CONFIG = @FC_CONFIG@ FC_LIBS = @FC_LIBS@ FRIBIDI_CONFIG = @FRIBIDI_CONFIG@ FVWMALTFTP = @FVWMALTFTP@ FVWMALTFTPDIR = @FVWMALTFTPDIR@ FVWMFTP = @FVWMFTP@ FVWMFTPDIR = @FVWMFTPDIR@ FVWMHOMEPAGE = @FVWMHOMEPAGE@ FVWMLIST = @FVWMLIST@ FVWMNAMELONG = @FVWMNAMELONG@ FVWMSCRIPT_DOMAIN = @FVWMSCRIPT_DOMAIN@ FVWMTASKBAR_DOMAIN = @FVWMTASKBAR_DOMAIN@ FVWMWORKERSLIST = @FVWMWORKERSLIST@ FVWMWORKERSLISTLONG = @FVWMWORKERSLISTLONG@ FVWM_CONFDIR = @FVWM_CONFDIR@ FVWM_CPP = @FVWM_CPP@ FVWM_DATADIR = @FVWM_DATADIR@ FVWM_DOCDIR = @FVWM_DOCDIR@ FVWM_DOMAIN = @FVWM_DOMAIN@ FVWM_IMAGEPATH = @FVWM_IMAGEPATH@ FVWM_MODULEDIR = @FVWM_MODULEDIR@ FVWM_PERLLIB = @FVWM_PERLLIB@ FVWM_PERLLIBDIR = @FVWM_PERLLIBDIR@ GDK_IMLIB_CFLAGS = @GDK_IMLIB_CFLAGS@ GDK_IMLIB_LIBS = @GDK_IMLIB_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ IMLIBCONF = @IMLIBCONF@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INST_LINGUAS = @INST_LINGUAS@ ISRELEASED = @ISRELEASED@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOCALEDIR = @LOCALEDIR@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANPAGE_PREAMBLE = @MANPAGE_PREAMBLE@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ MSGUNIQ = @MSGUNIQ@ OBJEXT = @OBJEXT@ 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@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PYTHON = @PYTHON@ RANLIB = @RANLIB@ RELDATELONG = @RELDATELONG@ RELDATENUM = @RELDATENUM@ RELDATESHORT = @RELDATESHORT@ REQUIRED_PERL_VERSION = @REQUIRED_PERL_VERSION@ REQUIRED_PYTHON_VERSION = @REQUIRED_PYTHON_VERSION@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ UPDATEPOFILES = @UPDATEPOFILES@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VERSIONINFO = @VERSIONINFO@ XFT_CFLAGS = @XFT_CFLAGS@ XFT_CONFIG = @XFT_CONFIG@ XFT_LIBS = @XFT_LIBS@ XGETTEXT = @XGETTEXT@ XMKMF = @XMKMF@ XSLTPROC = @XSLTPROC@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Xcursor_CFLAGS = @Xcursor_CFLAGS@ Xcursor_LIBS = @Xcursor_LIBS@ Xft_CFLAGS = @Xft_CFLAGS@ Xft_LIBS = @Xft_LIBS@ Xinerama_CFLAGS = @Xinerama_CFLAGS@ Xinerama_LIBS = @Xinerama_LIBS@ Xrender_CFLAGS = @Xrender_CFLAGS@ Xrender_LIBS = @Xrender_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ iconv_CFLAGS = @iconv_CFLAGS@ iconv_LIBS = @iconv_LIBS@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intl_CFLAGS = @intl_CFLAGS@ intl_LIBS = @intl_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ png_CFLAGS = @png_CFLAGS@ png_LIBS = @png_LIBS@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ readline_CFLAGS = @readline_CFLAGS@ readline_LIBS = @readline_LIBS@ rplay_CFLAGS = @rplay_CFLAGS@ rplay_LIBS = @rplay_LIBS@ rsvg_CFLAGS = @rsvg_CFLAGS@ rsvg_LIBS = @rsvg_LIBS@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ stroke_CFLAGS = @stroke_CFLAGS@ stroke_LIBS = @stroke_LIBS@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ with_bidi = @with_bidi@ with_gdkimlib = @with_gdkimlib@ with_gettext = @with_gettext@ with_iconv = @with_iconv@ with_perllib = @with_perllib@ with_png = @with_png@ with_readline = @with_readline@ with_rplay = @with_rplay@ with_rsvg = @with_rsvg@ with_shape = @with_shape@ with_shm = @with_shm@ with_sm = @with_sm@ with_stroke = @with_stroke@ with_xcursor = @with_xcursor@ with_xft = @with_xft@ with_xinerama = @with_xinerama@ with_xpm = @with_xpm@ with_xrender = @with_xrender@ xpm_CFLAGS = @xpm_CFLAGS@ xpm_LIBS = @xpm_LIBS@ configdir = @FVWM_PERLLIBDIR@/FVWM/Tracker config_DATA = \ Colorsets.pm GlobalConfig.pm ModuleConfig.pm PageInfo.pm \ Scheduler.pm WindowList.pm EXTRA_DIST = $(config_DATA) all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(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) --foreign perllib/FVWM/Tracker/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign perllib/FVWM/Tracker/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: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-configDATA: $(config_DATA) @$(NORMAL_INSTALL) @list='$(config_DATA)'; test -n "$(configdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(configdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(configdir)" || 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)$(configdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(configdir)" || exit $$?; \ done uninstall-configDATA: @$(NORMAL_UNINSTALL) @list='$(config_DATA)'; test -n "$(configdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(configdir)'; $(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)$(configdir)"; 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 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-configDATA 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 pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-configDATA .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic cscopelist-am \ ctags-am distclean distclean-generic distdir dvi dvi-am html \ html-am info info-am install install-am install-configDATA \ 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-generic pdf \ pdf-am ps ps-am tags-am uninstall uninstall-am \ uninstall-configDATA .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: ���������������������������������������������������������������������������������������������������������������fvwm-2.7.0/perllib/FVWM/Tracker/Colorsets.pm��������������������������������������������������������0000644�0001750�0001750�00000011373�14147024700�015542� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright (c) 2003-2009 Mikhael Goikhman # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see: <http://www.gnu.org/licenses/> package FVWM::Tracker::Colorsets; use strict; use FVWM::Tracker qw(base); use General::Parse qw(get_tokens); use constant CS_FIELDS => qw( fg bg hilite shadow fgsh tint icon_tint pixmap shape_mask fg_alpha_percent width height pixmap_type shape_width shape_height shape_type tint_percent do_dither_icon icon_tint_percent icon_alpha_percent ); use constant PIXMAP_TYPES => qw( PIXMAP_TILED PIXMAP_STRETCH_X PIXMAP_STRETCH_Y PIXMAP_STRETCH PIXMAP_STRETCH_ASPECT PIXMAP_ROOT_PIXMAP_PURE PIXMAP_ROOT_PIXMAP_TRAN ); sub observables ($) { return [ "colorset changed", ]; } sub start ($) { my $self = shift; # just an extra debug service for developers $self->{module}->emulate_event(M_CONFIG_INFO, [ 0, 0, 0, "Colorset 0 0 00c0c0 00e0e0 00a0a0 007070 0 0 0 0 64 0 0 0 0 0 0 0 0 0 64" ]) if $self->{module}->is_dummy; $self->{data} = {}; $self->add_handler(M_CONFIG_INFO, sub { my $event = $_[1]; $self->calculate_internals($event->args); }); $self->request_configinfo_events; my $result = $self->SUPER::start; $self->delete_handlers; $self->add_handler(M_CONFIG_INFO, sub { my $event = $_[1]; my ($num, $old_hash) = $self->calculate_internals($event->args); return unless defined $num; $self->notify("colorset changed", $num, $old_hash); }); return $result; } sub calculate_internals ($$) { my $self = shift; my $args = shift; my $data = $self->{data}; my $text = $args->{text}; $self->internal_die("No 'text' arg in M_CONFIG_INFO") unless defined $text; return undef if $text !~ /^colorset ([\da-f]+) ([\da-f ]+)$/i; my $num = hex($1); my @numbers = get_tokens($2); return undef if @numbers != CS_FIELDS; # memory used for keys may be optimized later my $new_hash = {}; my $i = 0; foreach (CS_FIELDS) { $new_hash->{$_} = hex($numbers[$i++]); } my $old_hash = $data->{$num}; $data->{$num} = $new_hash; return wantarray? ($num, $old_hash): $num; } sub data ($;$) { my $self = shift; my $num = shift; my $data = $self->{data}; return $data unless defined $num; return $data->{$num}; } sub dump ($;$) { my $self = shift; my $num = shift; my $data = $self->{data}; return "Colorset $num is unknown\n" if defined $num && !$data->{$num}; my @nums = defined $num? ($num): sort { "$a$b" =~ /^\d+$/? $a <=> $b: $a cmp $b } keys %$data; my $string = ""; foreach (@nums) { my $cs_hash = $data->{$_}; $string .= "Colorset $_"; my $i = 0; foreach (CS_FIELDS) { my $value = $cs_hash->{$_}; $i++; next if $i > 5 && ($value == 0 || /alpha_percent$/ && $value == 100); $value = sprintf("#%06lx", $value) if $i <= 7; $value = sprintf("0x%07lx", $value) if /pixmap$/; $string .= " $_=$value"; } $string .= "\n"; } return $string; } 1; __END__ =head1 DESCRIPTION This is a subclass of B<FVWM::Tracker> that enables to read the colorset definitions. This tracker defines the following observable: "colorset changed" that is notified using 2 additional parameters: colorset number and old colorset data hash ref. =head1 SYNOPSYS Using B<FVWM::Module> $module object: my $cs_tracker = $module->track("Colorsets"); my $cs_hash = $cs_tracker->data; my $cs2_fg = $cs_hash->{2}->{fg} || 'black'; my $cs5_bg = $cs_tracker->data(5)->{bg} || 'gray'; $cs_tracker->observe(sub { my ($module, $tracker, $data, $num, $old_hash) = @_; my $new_hash = $data->{$num}; if ($old_hash->{pixmap} == 0 && $new_hash->{pixmap}) { my $pixmap_type = $new_hash->{pixmap_type}; my $pixmap_name = ($tracker->PIXMAP_TYPES)[$pixmap_type]; $module->debug("Colorset: $num, Pixmap type: $pixmap_name"); } }; =head1 OVERRIDDEN METHODS =over 4 =item B<data> [I<colorset-num>] Returns either array ref of colorset hash refs, or one hash ref if I<colorset-num> is given. The hash keys are listed in CS_FIELDS, the constant of this class. =item B<dump> [I<colorset-num>] Works similarly to B<data>, but returns debug line(s) for one or all colorsets. =back =head1 AUTHOR Mikhael Goikhman <migo@homemail.com>. =head1 SEE ALSO For more information, see L<FVWM::Module> and L<FVWM::Tracker>. =cut ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/perllib/FVWM/Tracker/PageInfo.pm���������������������������������������������������������0000644�0001750�0001750�00000006753�14147024700�015263� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright (c) 2003-2009 Mikhael Goikhman # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see: <http://www.gnu.org/licenses/> package FVWM::Tracker::PageInfo; use strict; use FVWM::Tracker qw(base); sub observables ($) { return [ "desk/page changed", "desk only changed", "page only changed", ]; } sub start ($) { my $self = shift; $self->{data} = {}; $self->add_handler(M_NEW_PAGE, sub { my $event = $_[1]; $self->calculate_internals($event->args); }); $self->request_windowlist_events; my $result = $self->SUPER::start; $self->delete_handlers; $self->add_handler(M_NEW_PAGE | M_NEW_DESK, sub { my $event = $_[1]; if ($event->type == M_NEW_DESK) { my $old_desk_n = $self->{data}->{desk_n}; my $new_desk_n = $event->args->{desk_n}; $self->{data}->{desk_n} = $new_desk_n; my $really_changed = $old_desk_n != $new_desk_n; $self->notify("desk only changed", $really_changed); return unless $really_changed; } else { $self->calculate_internals($event->args); $self->notify("page only changed"); } $self->notify("desk/page changed"); }); return $result; } sub calculate_internals ($$) { my $self = shift; my $args = shift; my $data = $self->{data}; @$data{keys %$args} = values %$args; $data->{page_nx} = int($data->{vp_x} / $data->{vp_width}); $data->{page_ny} = int($data->{vp_y} / $data->{vp_height}); } sub dump ($) { my $self = shift; my $data = $self->{data}; my $string = join(', ', map { "$_=$data->{$_}" } sort keys %$data) . "\n"; $string =~ s/^(.*?)(, d.*?)(, p.*?), (v.*)$/$1$3$2\n$4/s; return $string; } 1; __END__ =head1 DESCRIPTION This B<FVWM::Tracker> subclass provides an information about the current fvwm page and desk and screen dimensions. Like with all trackers, this information is automatically brought up to the date for the entire tracker object life and may be retrieved by its C<data> method. This tracker defines the following observables that enable additional way of work: "desk/page changed", "desk only changed", "page only changed", =head1 SYNOPSYS Using B<FVWM::Module> $module object: my $page_tracker = $module->track("PageInfo"); my $page_hash = $page_tracker->data; my $curr_desk = $page_hash->{'desk_n'}; =head1 OVERRIDDEN METHODS =over 4 =item B<data> Returns hash ref representing the current page/desk, with the following keys (the fvwm variable equivalents are shown on the right): desk_n $[desk.n] page_nx $[page.nx] page_ny $[page.ny] desk_pages_x $[desk.pagesx] desk_pages_y $[desk.pagesy] vp_width $[vp.width] vp_height $[vp.height] vp_x $[vp.x] vp_y $[vp.y] =item B<dump> Returns 2 debug lines representing the current page data (as described in C<data>) in the human readable format. =back =head1 AUTHOR Mikhael Goikhman <migo@homemail.com>. =head1 SEE ALSO For more information, see L<FVWM::Module> and L<FVWM::Tracker>. =cut ���������������������fvwm-2.7.0/perllib/FVWM/Tracker/ModuleConfig.pm�����������������������������������������������������0000644�0001750�0001750�00000012335�14147024700�016137� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright (c) 2003-2009 Mikhael Goikhman # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see: <http://www.gnu.org/licenses/> package FVWM::Tracker::ModuleConfig; use strict; use FVWM::Tracker qw(base); sub observables ($) { return [ "config line added", ]; } sub new ($$%) { my $class = shift; my $module = shift; my %params = @_; my $self = $class->FVWM::Tracker::new($module); $self->{is_hash} = 1; $self->{module_name} = $self->{module}->name; $self->{filter} = 'spacefree'; $self->{default_config} = {}; return $self->init(%params); } sub init ($%) { my $self = shift; my %params = @_; if ($params{ConfigType}) { $self->{is_hash} = $params{ConfigType} eq 'hash'; $self->{default_config} = $self->{is_hash} ? {} : []; } $self->{module_name} = $params{ModuleName} if $params{ModuleName}; $self->{filter} = $params{LineFilter} if $params{LineFilter}; $self->{default_config} = $params{DefaultConfig} if ref($self->{default_config}) eq ref($params{DefaultConfig}); return $self; } sub start ($) { my $self = shift; my $default = $self->{default_config}; $self->{data} = $self->{is_hash} ? { %$default } : [ @$default ]; $self->add_handler(M_CONFIG_INFO, sub { my $event = $_[1]; $self->calculate_internals($event->args); }); $self->request_configinfo_events($self->{module_name}); my $result = $self->SUPER::start; $self->delete_handlers; $self->add_handler(M_CONFIG_INFO | M_SENDCONFIG, sub { my $event = $_[1]; return unless $event->type == M_CONFIG_INFO; my $info = $self->calculate_internals($event->args); return unless defined $info; $self->notify("config line added", $info); }); return $result; } sub calculate_internals ($$) { my $self = shift; my $args = shift; my $data = $self->{data}; my $text = $args->{text}; $self->internal_die("No 'text' arg in M_CONFIG_INFO") unless defined $text; return undef unless $text =~ /^\*$self->{module_name}(\s*[^\s].*)$/i; my $line = $1; $line =~ s/^\s+// unless $self->{filter} eq 'asis'; $line =~ s/\s+$// unless $self->{filter} eq 'asis'; if ($self->{is_hash}) { my ($key, $value) = $line =~ /([^\s]+)\s*(.*)/; $key = lc($key) if $self->{filter} eq 'lowerkeys'; $key = uc($key) if $self->{filter} eq 'upperkeys'; $self->{data}->{$key} = $value; return $key; } else { push @{$self->{data}}, $line; return @{$self->{data}} - 1; } } sub data ($;$) { my $self = shift; my $info = shift; my $data = $self->{data}; return $data unless defined $info; return $data->{$info} if $self->{is_hash}; return $data->[$info]; } sub dump ($;$) { my $self = shift; my $info = shift; my $data = $self->{data}; my @infos = defined $info? ($info): $self->{is_hash} ? sort keys %$data : (0 .. @$data - 1); my $string = ""; foreach (@infos) { my $line_data = $self->{is_hash} ? "$_ $data->{$_}" : $data->[$_]; $string .= "\*$self->{module_name}: $line_data\n"; } return $string; } 1; __END__ =head1 DESCRIPTION This is a subclass of B<FVWM::Tracker> that enables to read the module configuration. The module configuration is usually represented using a hash, but it may be represented as array of lines too. This tracker defines the following observables: "config line added" =head1 SYNOPSYS Using B<FVWM::Module> $module object: my $config_tracker = $module->track("ModuleConfig"); my $config_hash = $config_tracker->data; my $font = $config_hash->{Font} || 'fixed'; or: my $config_tracker = $module->track( "ModuleConfig", DefaultConfig => { Font => 'fixed' } ); my $font = $config_tracker->data('Font'); =head1 NEW METHODS =over 4 =item B<init> I<params> Makes it possible to change the parameters of this tracker on the fly. Use with caution. See B<new> method for the description of the I<params> hash. =back =head1 OVERRIDDEN METHODS =over 4 =item B<new> I<module> I<params> It is possible to specify additional parameters that this tracker understands. ConfigType - string "hash" (default) or "array" ModuleName - module to query, the default is $module->name LineFilter - "asis", "spacefree" (default), "lowerkeys", "upperkeys" DefaultConfig - the config hash/array of config to initially use =item B<data> [I<line-key-or-number>] Returns either array ref of configuration hash refs, or one hash ref if I<line-key-or-number> is given. Returns I<undef> if the configuration line for I<line-key-or-number> is not defined. =item B<dump> [I<line-key-or-number>] Works similarly to B<data>, but returns one or many debug lines. Returns an empty string if no module configuration is defined. =back =head1 AUTHOR Mikhael Goikhman <migo@homemail.com>. =head1 SEE ALSO For more information, see L<FVWM::Module> and L<FVWM::Tracker>. =cut ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/perllib/FVWM/Tracker/WindowList.pm�������������������������������������������������������0000644�0001750�0001750�00000023405�14147024700�015667� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright (c) 2004-2009 Mikhael Goikhman, Scott Smedley # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see: <http://www.gnu.org/licenses/> package FVWM::Tracker::WindowList; use strict; use FVWM::Tracker qw(base); my $window_events = M_ADD_WINDOW | M_CONFIGURE_WINDOW | M_DESTROY_WINDOW | M_ICONIFY | M_DEICONIFY; my $name_events = M_RES_NAME | M_RES_CLASS | M_WINDOW_NAME | M_VISIBLE_NAME | M_ICON_NAME; my $name_xevents = MX_VISIBLE_ICON_NAME; my $stack_events = M_RESTACK | M_RAISE_WINDOW | M_LOWER_WINDOW; my $icon_events = M_ICON_LOCATION | M_ICON_FILE | M_DEFAULTICON | M_MINI_ICON; sub observables ($) { return [ "window added", "window deleted", "window properties updated", "window moved", "window resized", "window iconified", "window deiconified", "window name updated", "window stack updated", "window icon updated", ]; } sub new ($$;$) { my $class = shift; my $module = shift; my @options = split(/ /, shift || ""); my $self = $class->FVWM::Tracker::new($module); $self->{options} = [ @options ]; return $self; } sub add_requested_info_handlers ($$) { my $self = shift; my $handler = shift; my $use_winfo = 1; my $use_names = 1; my $use_stack = 0; my $use_icons = 0; foreach (@{$self->{options}}) { /^(\!?)winfo$/ and $use_winfo = $1 ne '!'; /^(\!?)names$/ and $use_names = $1 ne '!'; /^(\!?)stack$/ and $use_stack = $1 ne '!'; /^(\!?)icons$/ and $use_icons = $1 ne '!'; } my $mask = 0; $mask |= $window_events if $use_winfo; $mask |= $name_events if $use_names; $mask |= $stack_events if $use_stack; $mask |= $icon_events if $use_icons; my $xmask = 0; $xmask |= $name_xevents if $use_names; $self->add_handler($mask, $handler) if $mask; $self->add_handler($xmask, $handler) if $xmask; $self->add_handler(M_NEW_PAGE | M_NEW_DESK, sub { $self->handler_page_info($_[1]); }) if $use_winfo; } sub start ($) { my $self = shift; $self->{data} = {}; $self->add_requested_info_handlers(sub { my $event = $_[1]; $self->calculate_internals($event); }); $self->request_windowlist_events; my $result = $self->SUPER::start; $self->delete_handlers; $self->add_requested_info_handlers(sub { my $event = $_[1]; my ($win_id, $old_hash) = $self->calculate_internals($event); return unless defined $win_id; my $type = $event->type(); my $observable = undef; if ($self->{module}->is_event_extended($type)) { if ($type & $name_xevents) { $observable = "window name updated"; } } elsif ($type & M_ADD_WINDOW) { $observable = "window added"; } elsif ($type & M_CONFIGURE_WINDOW) { $observable = "window properties updated"; # this observable is too broad, try to narrow if ($old_hash) { my $win = $self->{data}->{$win_id}; $self->notify("window resized", $win_id, $old_hash) if $win->{width} != $old_hash->{width} || $win->{height} != $old_hash->{height}; $self->notify("window moved", $win_id, $old_hash) if $win->{desk} != $old_hash->{desk} || $win->{x} != $old_hash->{x} || $win->{y} != $old_hash->{y}; } } elsif ($type & M_DESTROY_WINDOW) { $observable = "window deleted"; } elsif ($type & M_ICONIFY) { $observable = "window iconified"; } elsif ($type & M_DEICONIFY) { $observable = "window deiconified"; } elsif ($type & $name_events) { $observable = "window name updated"; } elsif ($type & $stack_events) { $observable = "window stack updated"; } elsif ($type & $icon_events) { $observable = "window icon updated"; } $self->notify($observable, $win_id, $old_hash) if $observable; }); return $result; } sub calculate_internals ($$) { my $self = shift; my $event = shift; my $args = $event->args; my $data = $self->{data}; my $win_id = $args->{win_id}; my $old_hash = undef; $old_hash = { %{$data->{$win_id}} } if defined $data->{$win_id}; my $window = $data->{$win_id} ||= bless { id => $win_id, iconified => 0, _tracker => $self }, "FVWM::Window"; # There are some fields that are not unique to all events. To ensure # we don't clobber them, we rename some fields. For example, the 'name' # field of M_MINI_ICON events is renamed to 'mini_icon_name'. foreach ('name', 'x', 'y', 'width', 'height') { if (defined $args->{$_}) { (my $name = lc($event->name())) =~ s/^.*?_//; $name .= "_$_" if ($name !~ /$_$/); $args->{$name} = $args->{$_}; delete $args->{$_}; } } #print $event->dump; $args->{name} = delete $args->{window_name} if exists $args->{window_name}; @$window{keys %$args} = values %$args; if (defined $args->{frame_x}) { # frame_x & frame_y are _relative_ coords of the window to the # current page - calculate the _absolute_ coords - x & y. $window->{x} = delete $window->{frame_x}; $window->{y} = delete $window->{frame_y}; $window->{width} = delete $window->{frame_width}; $window->{height} = delete $window->{frame_height}; my $page = $self->{page_info}; if (defined $page) { $window->{X} = $page->{vp_x} + $window->{x}; $window->{Y} = $page->{vp_y} + $window->{y}; $window->{page_nx} = int($window->{X} / $page->{vp_width}); $window->{page_ny} = int($window->{Y} / $page->{vp_height}); } } my $type = $event->type(); if (!$self->{module}->is_event_extended($type)) { if ($type & M_DEICONIFY) { $window->{iconified} = 0; } elsif ($type & M_ICONIFY) { $window->{iconified} = 1; } elsif ($type & M_DESTROY_WINDOW) { delete $data->{$win_id}; } } return wantarray ? ($win_id, $old_hash) : $win_id; } sub handler_page_info ($$) { my $self = shift; my $event = shift; my $args = $event->args; my $data = $self->{page_info} ||= {}; @$data{keys %$args} = values %$args; if ($event->type & M_NEW_PAGE) { $data->{page_nx} = int($data->{vp_x} / $data->{vp_width}); $data->{page_ny} = int($data->{vp_y} / $data->{vp_height}); } } sub page_info ($;$) { my $self = shift; my $id = shift; my $data = $self->{page_info}; return $data unless defined $id; return $data->{$id}; } sub data ($;$) { my $self = shift; my $id = shift; my $data = $self->{data}; return $data unless defined $id; return $data->{$id}; } sub dump ($;$) { my $self = shift; my $id = shift; my $data = $self->{data}; my @ids = defined $id? ($id): sort { $a <=> $b } keys %$data; my $string = ""; foreach (@ids) { my $window = $data->{$_}; $string .= $window->dump; } return $string; } sub windows ($) { my $self = shift; my @windows = values %{$self->data}; return wantarray? @windows: \@windows; } # ---------------------------------------------------------------------------- package FVWM::Window; sub match ($$) { my $self = shift; my $condition = shift; my @conditions = split(/[,\s]+/, $condition); my $match = 1; foreach (@conditions) { my $opposite = s/^!//; if (/^iconified$/i) { return 0 unless $opposite ^ $self->{iconified}; } elsif (/^current(page|desk)$/i) { my $page = $self->{_tracker}->page_info; return 0 unless $opposite ^ ($self->{desk} == $page->{desk_n}); next if lc($1) eq "desk"; return 0 unless $opposite ^ ( $self->{x} + $self->{width} > $page->{vp_x} && $self->{x} < $page->{vp_x} + $page->{vp_width} && $self->{y} + $self->{height} > $page->{vp_y} && $self->{y} < $page->{vp_y} + $page->{vp_height} ); } } return $match; } sub dump ($) { my $self = shift; my $id = $self->{win_id}; my $string = "Window $id\n"; foreach my $prop (sort keys %$self) { next if $prop =~ /^_/; $string .= "\t$prop:\t[$self->{$prop}]\n"; } return $string; } # ---------------------------------------------------------------------------- 1; __END__ =head1 DESCRIPTION This is a subclass of B<FVWM::Tracker> that enables to read the window information. This tracker defines the following observables: "window added", "window deleted", "window properties updated", "window moved", "window resized", "window iconified", "window deiconified", "window name updated", "window stack updated", "window icon updated", =head1 SYNOPSYS Using B<FVWM::Module> $module object: my $tracker = $module->track("WindowList"); my @windows = $tracker->windows; foreach my $window ($tracker->windows) { print "+$window->{x}+$window->{y}, $window->{name}\n"; } or: my $tracker = $module->track("WindowList", "winfo"); my $x = $tracker->data("0x230002a")->{x}; or: my $tracker = $module->track("WindowList", $options); my $data = $tracker->data; while (my ($win_id, $window) = each %$data) { next unless $window->match("CurrentPage, Iconified"); $module->send("Iconify off", $win_id); } Default $options string is: "!stack !icons names winfo" =head1 OVERRIDDEN METHODS =over 4 =item B<new> I<module> I<params> It is possible the kind of window list. To be written. =item B<data> [I<window-id>] Returns hash ref of window hash refs. or one window hash ref if I<window-id> is given. =item B<dump> [I<window-id>] Works similarly to B<data>, but returns debug lines for one or all windows. =back =head1 METHODS =over 4 =item B<page_info> [I<field>] Returns hash ref of page/desk info, or actual hash value using B<field> as a key (if specified). =back =head1 AUTHORS =over 4 =item Mikhael Goikhman <migo@homemail.com> =item Scott Smedley =back =head1 SEE ALSO For more information, see L<FVWM::Module> and L<FVWM::Tracker>. =cut �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/perllib/FVWM/Tracker/Scheduler.pm��������������������������������������������������������0000644�0001750�0001750�00000016030�14147024700�015476� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright (c) 2003-2009 Mikhael Goikhman # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see: <http://www.gnu.org/licenses/> package FVWM::Tracker::Scheduler; use strict; use FVWM::Tracker qw(base); sub observables ($) { return [ "scheduled alarm", ]; } sub new ($$%) { my $class = shift; my $module = shift; my %params = @_; my $self = $class->FVWM::Tracker::new($module); $self->{random_base_number} = 8000000 + int(rand(900000)); $self->{sent_string_prefix} = "FVWM::Tracker::Scheduler alarm "; $self->{module_name} = $params{ModuleName} || $self->{module}->name; $self->{use_alarm} = (exists $params{UseAlarm} ? $params{UseAlarm} : $module->is_dummy) ? 1 : 0; return $self; } sub start ($) { my $self = shift; $self->{data} = {}; my $result = $self->SUPER::start; $self->{internal_observer_id} ||= $self->observe(sub { my $schedule_id = $_[3]; my $schedule_data = $self->data($schedule_id); $self->{rescheduled_seconds} = -1; &{$schedule_data->{callback}}($schedule_data, @{$schedule_data->{params}}); my $new_seconds = $self->{rescheduled_seconds}; if ($new_seconds >= 0) { $schedule_data->{seconds} = $new_seconds if $new_seconds; $self->send_schedule($schedule_id); } else { $self->deschedule($schedule_id); } }); $self->add_handler(M_STRING, sub { my $event = $_[1]; my $text = $event->_text; return unless $text =~ /^$self->{sent_string_prefix}(\d+)/; $self->notify("main", $1); }); return $result; } sub stop ($) { my $self = shift; $self->SUPER::stop; $self->deschedule_all; } sub send_schedule ($$) { my $self = shift; my $schedule_id = shift; my $sd = $self->{data}->{$schedule_id}; my $string = "$self->{sent_string_prefix}$schedule_id"; if ($self->{use_alarm}) { $SIG{ALRM} = sub { $self->{module}->emulate_event(M_STRING, [ 0, 0, 0, $string ]); }; alarm($sd->{seconds}); } else { my $mseconds = $sd->{seconds} * 1000; $self->{module}->send("Schedule $mseconds $sd->{fvwm_id} " . "SendToModule $self->{module_name} $string"); } $sd->{time_sent} = time(); } sub schedule ($$$;$) { my $self = shift; my $seconds = shift || $self->internal_die("schedule: no seconds"); my $callback = shift || $self->internal_die("schedule: no callback"); my $schedule_id = ++$self->{last_schedule_num}; my $fvwm_id = $self->{random_base_number} + $schedule_id; my $schedule_data = { time_sent => 0, seconds => $seconds, fvwm_id => $fvwm_id, callback => $callback, params => [ @_ ], }; $self->{data}->{$schedule_id} = $schedule_data; $self->send_schedule($schedule_id); return $schedule_id; } sub deschedule ($$) { my $self = shift; my $schedule_id = shift; my $data = $self->{data}; next unless exists $data->{$schedule_id}; my $fvwm_id = $data->{$schedule_id}->{fvwm_id}; $self->{module}->send("Deschedule $fvwm_id") if defined $self->{module}; # ready for DESTROY delete $data->{$schedule_id}; } sub reschedule ($;$) { my $self = shift; my $seconds = shift || 0; $self->{rescheduled_seconds} = $seconds; } sub deschedule_all ($) { my $self = shift; my $data = $self->{data}; foreach (keys %$data) { $self->deschedule($_); } } sub to_be_disconnected ($) { my $self = shift; $self->deschedule_all(); } sub data ($;$) { my $self = shift; my $schedule_id = shift; my $data = $self->{data}; return $data unless defined $schedule_id; return $data->{$schedule_id}; } sub dump ($;$) { my $self = shift; my $schedule_id = shift; my $data = $self->{data}; my @ids = $schedule_id ? $schedule_id : sort { $a <=> $b } keys %$data; my $string = ""; foreach (@ids) { my $sd = $data->{$_}; my $time_str = localtime($sd->{time_sent}); $time_str = "$5-$2-$3 $4" if $time_str =~ /^([^ ]+) ([^ ]+) ([^ ]+) ([^ ]+) ([^ ]+)$/; $string .= "Schedule $_: $time_str + $sd->{seconds} sec, use 'Deschedule $sd->{fvwm_id}'\n"; } return $string; } 1; __END__ =head1 DESCRIPTION This is a subclass of B<FVWM::Tracker> that enables to define alarm callback, several at the same time. This tracker defines the following observables: "scheduled alarm" But it is suggested not to use the usual tracker B<observe>/B<unobserve> API, but to use the B<schedule>/B<deschedule>/B<reschedule> API instead. This tracker uses the I<fvwm> command B<Schedule> to get a notification. It is possible to use the perl I<alarm>. This is the default if the module is run in the dummy mode. To set it explicitly, pass I<UseAlarm> boolean value when the tracker is created. Note that alarm signals are not relable in some perl versions, on some systems and with some kind of applications, don't expect the alarm method to work at all. =head1 SYNOPSYS Using B<FVWM::Module> $module object: # beep every 40 seconds; exit in 100 seconds my $scheduler = $module->track("Scheduler"); $scheduler->schedule(40, sub { $module->send("Beep"); $scheduler->reschedule; }); $scheduler->schedule(100, sub { $module->terminate; }); =head1 PUBLIC METHODS =over 4 =item B<schedule> I<seconds> I<callback> [I<params>] Sets the alarm I<callback> that is called in about I<seconds> seconds. The I<callback> parameters are: hash as returned using B<data> when called with the I<scheduled-id> parameter, and optional I<params>. Returns I<scheduled-id> that may be used in B<deschedule> or B<data>. =item B<deschedule> I<scheduled-id> Removes the scheduled callback identified by I<scheduled-id>. =item B<reschedule> [I<seconds>] When the scheduled callback is called, it is possible to reinitialize the same callback using the same or different number of I<seconds>. This may be useful when defining a periodical callback that should be, say, called every 10 minutes (600 seconds). =item deschedule_all Removes all previously scheduled callbacks. =back =head1 OVERRIDDEN METHODS =over 4 =item to_be_disconnected Calls B<deschedule_all>. =item B<data> [I<sheduled-id>] Returns either array ref of hash refs, or one hash ref if I<sheduled-id> is given. The hash keys are: time_sent - unix time (seconds since 1970) seconds - requested alarm seconds fvwm_id - internal I<fvwm>'s Schedule id callback - alarm callback, CODE ref params - ARRAY ref of optional callback parameters =item B<dump> [I<sheduled-id>] Works similarly to B<data>, but returns one or many debug lines (one line per scheduled alarm). If no scheduled callbacks are active, the empty string is returned as expected. =back =head1 AUTHOR Mikhael Goikhman <migo@homemail.com>. =head1 SEE ALSO For more information, see L<FVWM::Module> and L<FVWM::Tracker>. =cut ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/perllib/FVWM/Tracker/Makefile.am���������������������������������������������������������0000644�0001750�0001750�00000000353�14147024676�015273� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Process this file with automake to create Makefile.in configdir = @FVWM_PERLLIBDIR@/FVWM/Tracker config_DATA = \ Colorsets.pm GlobalConfig.pm ModuleConfig.pm PageInfo.pm \ Scheduler.pm WindowList.pm EXTRA_DIST = $(config_DATA) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/perllib/FVWM/Tracker/GlobalConfig.pm�����������������������������������������������������0000644�0001750�0001750�00000006016�14147024700�016111� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright (c) 2003-2009 Mikhael Goikhman # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see: <http://www.gnu.org/licenses/> package FVWM::Tracker::GlobalConfig; use strict; use FVWM::Tracker qw(base); sub observables ($) { return [ "value updated", ]; } sub start ($) { my $self = shift; $self->{data} = {}; $self->add_handler(M_CONFIG_INFO, sub { my $event = $_[1]; $self->calculate_internals($event->args); }); $self->request_configinfo_events; my $result = $self->SUPER::start; $self->delete_handlers; $self->add_handler(M_CONFIG_INFO, sub { my $event = $_[1]; my $name = $self->calculate_internals($event->args); return unless defined $name; $self->notify("value changed", $name); }); return $result; } sub calculate_internals ($$) { my $self = shift; my $args = shift; my $data = $self->{data}; my $text = $args->{text}; $self->internal_die("No 'text' arg in M_CONFIG_INFO") unless defined $text; return undef if $text =~ /^(?:desktopsize|colorset|\*)/i; return undef unless $text =~ /^(desktopname \d+|[^\s]+) (.*)$/i; my $name = $1; my $value = $2; $self->{data}->{$name} = $value; return $name; } sub data ($;$) { my $self = shift; my $name = shift; my $data = $self->{data}; return $data unless defined $name; return $data->{$name}; } sub dump ($;$) { my $self = shift; my $name = shift; my $data = $self->{data}; my @names = defined $name? ($name): sort keys %$data; my $string = ""; foreach (@names) { my $value = $data->{$_}; $string .= "$_ $value\n"; } return $string; } 1; __END__ =head1 DESCRIPTION This is a subclass of B<FVWM::Tracker> that enables to read the global FVWM configuration. "value changed" =head1 SYNOPSYS Using B<FVWM::Module> $module object: my $config_tracker = $module->track("GlobalConfig"); my $config_hash = $config_tracker->data; my $image_path = $config_hash->{'ImagePath'}; or: my $config_tracker = $module->track("GlobalConfig"); my $xinerama_info = $config_tracker->data('XineramaConfig'); my $desktop2_name = $config_tracker->data('DesktopName 2'); =head1 OVERRIDDEN METHODS =over 4 =item B<data> [I<key>] Returns either hash ref of all global configuration values, or one value if I<key> is given. =item B<dump> [I<key>] Works similarly to B<data>, but returns debug lines for one or all global configuration values. =back =head1 AUTHOR Mikhael Goikhman <migo@homemail.com>. =head1 SEE ALSO For more information, see L<FVWM::Module> and L<FVWM::Tracker>. =cut ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/perllib/FVWM/EventNames.pm���������������������������������������������������������������0000644�0001750�0001750�00000043567�14147024700�014251� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright (c) 2003-2009, Mikhael Goikhman # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see: <http://www.gnu.org/licenses/> package FVWM::EventNames; use strict; use FVWM::Constants; use constant number => 0; use constant bool => 1; use constant window => 2; use constant pixel => 3; use constant string => 4; use constant wflags => 5; use constant looped => 6; use vars qw($EVENTS_INFO); # ---------------------------------------------------------------------------- # start of the would-be-generated part $EVENTS_INFO = { &M_NEW_PAGE => { format => "l!3L!4", fields => [ vp_x => number, vp_y => number, desk_n => number, vp_width => number, vp_height => number, desk_pages_x => number, desk_pages_y => number, ], aliases => { desk => 'desk_n', }, }, &M_NEW_DESK => { format => "l!", fields => [ desk_n => number, ], aliases => { desk => 'desk_n', }, }, # &M_OLD_ADD_WINDOW => { # }, &M_RAISE_WINDOW => { format => "L!3", fields => [ win_id => window, frame_id => window, ptr => number, ], }, &M_LOWER_WINDOW => { format => "L!3", fields => [ win_id => window, frame_id => window, ptr => number, ], }, # &M_OLD_CONFIGURE_WINDOW => { # }, &M_FOCUS_CHANGE => { format => "L!5", fields => [ win_id => window, frame_id => window, flip => bool, focus_fg => pixel, focus_bg => pixel, ], }, &M_DESTROY_WINDOW => { format => "L!3", fields => [ win_id => window, frame_id => window, ptr => number, ], }, &M_ICONIFY => { format => "L!3l!8", fields => [ win_id => window, frame_id => window, ptr => number, icon_x => number, icon_y => number, icon_width => number, icon_height => number, frame_x => number, frame_y => number, frame_width => number, frame_height => number, ], }, &M_DEICONIFY => { format => "L!3l!8", fields => [ win_id => window, frame_id => window, ptr => number, icon_x => number, icon_y => number, icon_width => number, icon_height => number, frame_x => number, frame_y => number, frame_width => number, frame_height => number, ], }, &M_WINDOW_NAME => { format => "L!3a*", fields => [ win_id => window, frame_id => window, ptr => number, name => string, ], }, &M_ICON_NAME => { format => "L!3a*", fields => [ win_id => window, frame_id => window, ptr => number, name => string, ], }, &M_RES_CLASS => { format => "L!3a*", fields => [ win_id => window, frame_id => window, ptr => number, name => string, ], }, &M_RES_NAME => { format => "L!3a*", fields => [ win_id => window, frame_id => window, ptr => number, name => string, ], }, &M_END_WINDOWLIST => { format => "", fields => [ ], }, &M_ICON_LOCATION => { format => "L!3l!4", fields => [ win_id => window, frame_id => window, ptr => number, x => number, y => number, width => number, height => number, ], }, &M_MAP => { format => "L!3", fields => [ win_id => window, frame_id => window, ptr => number, ], }, &M_ERROR => { format => "L!3a*", fields => [ win_id => window, frame_id => window, ptr => number, text => string, ], }, &M_CONFIG_INFO => { format => "L!3a*", fields => [ win_id => window, frame_id => window, ptr => number, text => string, ], }, &M_END_CONFIG_INFO => { format => "", fields => [ ], }, &M_ICON_FILE => { format => "L!3a*", fields => [ win_id => window, frame_id => window, ptr => number, name => string, ], }, &M_DEFAULTICON => { format => "L!3a*", fields => [ win_id => window, frame_id => window, ptr => number, name => string, ], }, &M_STRING => { format => "L!3a*", fields => [ win_id => window, frame_id => window, ptr => number, text => string, ], }, &M_MINI_ICON => { format => "L!9a*", fields => [ win_id => window, frame_id => window, ptr => number, width => number, height => number, depth => number, icon_id => window, mask => number, alpha => number, name => string, ], }, &M_WINDOWSHADE => { format => "L!3", fields => [ win_id => window, frame_id => window, ptr => number, ], }, &M_DEWINDOWSHADE => { format => "L!3", fields => [ win_id => window, frame_id => window, ptr => number, ], }, &M_VISIBLE_NAME => { format => "L!3a*", fields => [ win_id => window, frame_id => window, ptr => number, name => string, ], }, # &M_SENDCONFIG => { # }, &M_RESTACK => { format => "L!3a*", fields => [ win_id => window, frame_id => window, ptr => number, low_windows => looped, ], loop_format => "L!3a*", loop_fields => [ win_id => window, frame_id => window, ptr => number, ], }, &M_ADD_WINDOW => { format => "L!3l!6l!8L!2l!L!2l!3S4a*", fields => [ win_id => window, frame_id => window, ptr => number, frame_x => number, frame_y => number, frame_width => number, frame_height => number, desk => number, layer => number, win_width => number, win_height => number, resize_width_inc => number, resize_height_inc => number, minimum_width => number, minimum_height => number, maximum_width => number, maximum_height => number, icon_title_id => window, icon_image_id => window, gravity => number, fore_color => pixel, back_color => pixel, ewmh_layer => number, ewmh_desktop => number, ewmh_window_type => number, title_height => number, border_width => number, dummy_zero_1 => number, dummy_zero_2 => number, window_flags => wflags, ], }, &M_CONFIGURE_WINDOW => { format => "L!3l!6l!8L!2l!L!2l!3S4a*", fields => [ win_id => window, frame_id => window, ptr => number, frame_x => number, frame_y => number, frame_width => number, frame_height => number, desk => number, layer => number, win_width => number, win_height => number, resize_width_inc => number, resize_height_inc => number, minimum_width => number, minimum_height => number, maximum_width => number, maximum_height => number, icon_title_id => window, icon_image_id => window, gravity => number, fore_color => pixel, back_color => pixel, ewmh_layer => number, ewmh_desktop => number, ewmh_window_type => number, title_height => number, border_width => number, dummy_zero_1 => number, dummy_zero_2 => number, window_flags => wflags, ], }, # &M_EXTENDED_MSG => { # }, &MX_VISIBLE_ICON_NAME => { format => "L!3a*", fields => [ win_id => window, frame_id => window, ptr => number, name => string, ], }, &MX_ENTER_WINDOW => { format => "L!3", fields => [ win_id => window, frame_id => window, ptr => number, ], }, &MX_LEAVE_WINDOW => { format => "L!3", fields => [ win_id => window, frame_id => window, ptr => number, ], }, &MX_PROPERTY_CHANGE => { format => "L!3a*", fields => [ type => number, value => number, win_id => window, text => string, ], info => { type_names => [ qw(NONE BACKGROUND SWALLOW) ], }, }, &MX_REPLY => { format => "L!3a*", fields => [ win_id => window, frame_id => window, ptr => number, text => string, ], }, "faked" => { format => "", fields => [ ], }, }; # end of the would-be-generated part # ---------------------------------------------------------------------------- use Exporter; use vars qw(@EXPORT @ISA $EVENT_TYPES $EVENT_NAMES $EVENT_TYPE_NAMES); @EXPORT = ( @FVWM::Constants::EXPORT, qw(event_name event_arg_names event_arg_types event_arg_values event_args), qw(event_loop_arg_names event_loop_arg_types), qw(event_arg_aliases all_event_names all_event_types) ); @ISA = qw(Exporter); sub all_event_type_names () { if (!defined $EVENT_TYPE_NAMES) { $EVENT_TYPES = []; $EVENT_NAMES = []; $EVENT_TYPE_NAMES = {}; my ($type, $name); foreach $name (@FVWM::Constants::EXPORT) { next unless $name =~ /^MX?_/; next if $name eq 'M_EXTENDED_MSG'; no strict 'refs'; $type = &$name(); next if $name =~ /^MX_/ && !($type & M_EXTENDED_MSG); push @$EVENT_TYPES, $type; push @$EVENT_NAMES, $name; $EVENT_TYPE_NAMES->{$type} = $name; } } return $EVENT_TYPE_NAMES; } sub all_event_names () { all_event_type_names(); return wantarray? @$EVENT_NAMES: $EVENT_NAMES; } sub all_event_types () { all_event_type_names(); return wantarray? @$EVENT_TYPES: $EVENT_TYPES; } sub event_name ($) { my $type = shift; return all_event_type_names()->{$type}; } sub event_type_to_binary ($) { my $type = shift || "no-event-type"; return $type unless $type =~ /^\d+$/; return sprintf("%b", $type); } sub event_info ($) { my $type = shift; unless (defined $EVENTS_INFO->{$type}) { die "FVWM::EventNames: Unknown event type (" . event_type_to_binary($type) . ")\n"; } return $EVENTS_INFO->{$type}; } sub calculate_internals ($) { my $type = shift; my $event_info = event_info($type); $event_info->{names} = []; $event_info->{types} = []; my $i = 0; foreach (@{$event_info->{fields}}) { push @{$event_info->{names}}, $_ if ($i % 2) == 0; push @{$event_info->{types}}, $_ if ($i % 2) == 1; $i++; } # handle loop args if any return unless exists $event_info->{loop_fields}; $event_info->{loop_names} = []; $event_info->{loop_types} = []; $i = 0; foreach (@{$event_info->{loop_fields}}) { push @{$event_info->{loop_names}}, $_ if ($i % 2) == 0; push @{$event_info->{loop_types}}, $_ if ($i % 2) == 1; $i++; } } sub event_arg_names ($$) { my $type = shift; my $arg_values = shift; my $event_info = event_info($type); my $arg_names = $event_info->{names}; return $arg_names if defined $arg_names; calculate_internals($type); return $event_info->{names}; } sub event_arg_types ($$) { my $type = shift; my $arg_values = shift; my $event_info = event_info($type); my $arg_types = $event_info->{types}; return $arg_types if defined $arg_types; calculate_internals($type); return $event_info->{types}; } sub event_arg_values ($$) { my $type = shift; my $packed_str = shift; my $event_info = event_info($type); my @arg_values = unpack($event_info->{format}, $packed_str); my $arg_fields = $event_info->{fields}; push @arg_values, (undef) x ((@$arg_fields / 2) - @arg_values); # process looped args if (@$arg_fields && $arg_fields->[@$arg_fields - 1] == looped) { my @loop_arg_values = (); my $rest_str = pop @arg_values; while ($rest_str ne "") { my @new_arg_values = unpack($event_info->{loop_format}, $rest_str); die "Internal error, no loop args unpacked ($type)\n" unless @new_arg_values > 1; $rest_str = pop @new_arg_values; push @loop_arg_values, @new_arg_values; } push @arg_values, \@loop_arg_values; } # strip everything past the first null (or newline) if needed if (@$arg_fields && $arg_fields->[-1] == string) { $arg_values[-1] =~ s/\n*\0.*//s; } return \@arg_values; } sub event_loop_arg_names ($$) { my $type = shift; my $arg_values = shift; my $event_info = event_info($type); my $arg_names = $event_info->{loop_names}; return $arg_names if defined $arg_names; calculate_internals($type); return $event_info->{loop_names}; } sub event_loop_arg_types ($$) { my $type = shift; my $arg_values = shift; my $event_info = event_info($type); my $arg_types = $event_info->{loop_types}; return $arg_types if defined $arg_types; calculate_internals($type); return $event_info->{loop_types}; } sub event_args ($$) { my $type = shift; my $arg_values = shift; my $arg_names = event_arg_names($type, $arg_values); die sprintf "Internal error, event type %s (%d names, %d values)\n", event_type_to_binary($type), scalar @$arg_names, scalar @$arg_values if @$arg_names != @$arg_values; my $loop_arg_names = event_loop_arg_names($type, $arg_values); die sprintf "Internal error, event type %s (%d loop names, non array)\n", event_type_to_binary($type), scalar @$loop_arg_names if $loop_arg_names && ref($loop_arg_names) ne 'ARRAY' && !@$loop_arg_names && ref($arg_values->[-1]) ne 'ARRAY'; my $i = 0; my %args = map { my $value = $_; $arg_names->[$i++], ref($value) ne 'ARRAY'? $value: do { my $loop_value = []; my $j = 0; while ($j < @$value) { my %loop_hash = map { $_, $value->[$j++] } @$loop_arg_names; push @$loop_value, \%loop_hash; } $loop_value } } @$arg_values; return \%args; } sub event_arg_aliases ($) { my $type = shift; return event_info($type)->{aliases} || {}; } # ---------------------------------------------------------------------------- =head1 NAME FVWM::EventNames - names and types of all fvwm event arguments =head1 SYNOPSIS use FVWM::EventNames; print "All event names: ", join(", ", @{all_event_names()}), "\n"; print "All event types: ", join(", ", @{all_event_types()}), "\n"; my $name = event_name (M_ICON_LOCATION); my $arg_values = event_arg_values(M_ICON_LOCATION, $packed_str); my $arg_names = event_arg_names (M_ICON_LOCATION, $arg_values); my $arg_types = event_arg_types (M_ICON_LOCATION, $arg_values); my $args = event_args (M_ICON_LOCATION, $arg_values); =head1 DESCRIPTION Every event send by I<fvwm> consist of arguments. The argument names and types vary from one event type to another. For example, event of the type B<M_NEW_DESK> consists of only one argument I<desk> of type I<number>. B<M_NEW_PAGE> consists of 5 numeric arguments, B<M_MINI_ICON> consists of 10 arguments of different types. This class provides information about all fvwm events. It provides such services as listing all supported event types and their names, converting event type to event name, listing the event argument names/types, constructing event argument values from the plain packet data. Usually you do not need to work with this class directly, but, instead, with B<FVWM::Event> objects. Hovewer, you may need this class source as a reference for the names of the event arguments and their types. =head1 PUBLIC FUNCTIONS =over 4 =item B<event_name> I<type> Returns the string representation of the numeric event I<type> constant, like I<M_RAISE_WINDOW> or I<MX_ENTER_WINDOW>. =item B<event_arg_values> I<type> I<packed_str> Constructs array ref of argument values for the event I<type> from the I<packed_str> (as received from I<fvwm>). If the last argument type of the event is string, for convenience, everything past the first null (or newline) is automatically stripped from the last argument value. =item B<event_arg_names> I<type> I<arg_values> Returns array ref of argument names of the event type. I<arg_values> is either the real array ref of values (as returned by B<event_arg_values>) or a number of actual values. The returned array has the same number of elements. =item B<event_arg_types> I<type> I<arg_values> Returns array ref of argument types of the event type. I<arg_values> is either the real array ref of values (as returned by B<event_arg_values>) or a number of actual values. The returned array has the same number of elements. =item B<event_loop_arg_names> I<type> I<arg_values> Returns array ref of looped argument names of the event type (or undef). =item B<event_loop_arg_types> I<type> I<arg_values> Returns array ref of looped argument types of the event type (or undef). =item B<event_args> I<type> I<arg_values> Constructs hash ref of the named arguments for the event I<type> from the I<arg_values> array ref (as returned by B<event_arg_values>). =item B<event_arg_aliases> I<type> This method is provided for backward compatibility when argument names are changed. For example, in the past the argument name of I<M_NEW_DESK> was B<desk>, but now it is B<desk_n>. Using this method it is possible to make both names supported. Returns hash ref (old-name => new-name). =item B<all_event_names> Returns array ref of all known event names (strings). In the list context returns list of these names. =item B<all_event_types> Returns array ref of all known event types (numbers). In the list context returns list of these types. =item B<all_event_type_names> Returns hash ref of all known event names and types (type => name). =back =head1 SEE ALSO L<FVWM::Event>. =cut 1; �����������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/perllib/FVWM/Constants.pm����������������������������������������������������������������0000644�0001750�0001750�00000010020�14147024700�014132� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Autogenerated from the fvwm sources. package FVWM::Constants; use Exporter; use Config; @ISA = qw(Exporter); use constant M_NEW_PAGE => (1); use constant M_NEW_DESK => (1<<1); use constant M_OLD_ADD_WINDOW => (1<<2); use constant M_RAISE_WINDOW => (1<<3); use constant M_LOWER_WINDOW => (1<<4); use constant M_OLD_CONFIGURE_WINDOW => (1<<5); use constant M_FOCUS_CHANGE => (1<<6); use constant M_DESTROY_WINDOW => (1<<7); use constant M_ICONIFY => (1<<8); use constant M_DEICONIFY => (1<<9); use constant M_WINDOW_NAME => (1<<10); use constant M_ICON_NAME => (1<<11); use constant M_RES_CLASS => (1<<12); use constant M_RES_NAME => (1<<13); use constant M_END_WINDOWLIST => (1<<14); use constant M_ICON_LOCATION => (1<<15); use constant M_MAP => (1<<16); use constant M_ERROR => (1<<17); use constant M_CONFIG_INFO => (1<<18); use constant M_END_CONFIG_INFO => (1<<19); use constant M_ICON_FILE => (1<<20); use constant M_DEFAULTICON => (1<<21); use constant M_STRING => (1<<22); use constant M_MINI_ICON => (1<<23); use constant M_WINDOWSHADE => (1<<24); use constant M_DEWINDOWSHADE => (1<<25); use constant M_VISIBLE_NAME => (1<<26); use constant M_SENDCONFIG => (1<<27); use constant M_RESTACK => (1<<28); use constant M_ADD_WINDOW => (1<<29); use constant M_CONFIGURE_WINDOW => (1<<30); use constant M_EXTENDED_MSG => (1<<31); use constant MX_VISIBLE_ICON_NAME => ((1<<0)|M_EXTENDED_MSG); use constant MX_ENTER_WINDOW => ((1<<1)|M_EXTENDED_MSG); use constant MX_LEAVE_WINDOW => ((1<<2)|M_EXTENDED_MSG); use constant MX_PROPERTY_CHANGE => ((1<<3)|M_EXTENDED_MSG); use constant MX_REPLY => ((1<<4)|M_EXTENDED_MSG); use constant MX_PROPERTY_CHANGE_NONE => 0; use constant MX_PROPERTY_CHANGE_BACKGROUND => 1; use constant MX_PROPERTY_CHANGE_SWALLOW => 2; use constant MAX_MSG_MASK => 0x7fffffff; use constant MAX_XMSG_MASK => 0x0000001f; use constant HEADER_SIZE => 4; use constant START_FLAG => 0xffffffff; use constant RESPONSE_READY => "NOP FINISHED STARTUP"; use constant RESPONSE_UNLOCK => "NOP UNLOCK"; use constant ON_EXIT => '1e20'; use constant INTSIZE => $Config{longsize}; @EXPORT = qw( M_NEW_PAGE M_NEW_DESK M_OLD_ADD_WINDOW M_RAISE_WINDOW M_LOWER_WINDOW M_OLD_CONFIGURE_WINDOW M_FOCUS_CHANGE M_DESTROY_WINDOW M_ICONIFY M_DEICONIFY M_WINDOW_NAME M_ICON_NAME M_RES_CLASS M_RES_NAME M_END_WINDOWLIST M_ICON_LOCATION M_MAP M_ERROR M_CONFIG_INFO M_END_CONFIG_INFO M_ICON_FILE M_DEFAULTICON M_STRING M_MINI_ICON M_WINDOWSHADE M_DEWINDOWSHADE M_VISIBLE_NAME M_SENDCONFIG M_RESTACK M_ADD_WINDOW M_CONFIGURE_WINDOW M_EXTENDED_MSG MX_VISIBLE_ICON_NAME MX_ENTER_WINDOW MX_LEAVE_WINDOW MX_PROPERTY_CHANGE MX_REPLY MX_PROPERTY_CHANGE_NONE MX_PROPERTY_CHANGE_BACKGROUND MX_PROPERTY_CHANGE_SWALLOW MAX_MSG_MASK MAX_XMSG_MASK HEADER_SIZE START_FLAG RESPONSE_READY RESPONSE_UNLOCK ON_EXIT INTSIZE ); 1; __END__ =head1 NAME FVWM::Constants - exports fvwm specific constants =head1 DESCRIPTION This class is used to load fvwm constants into your perl script or class. Note, if you use I<FVWM::Module> the constants are automatically exported. So you usually do not need to include this class. =head1 USAGE use FVWM::Constants; =head1 SEE ALSO For more information, see L<FVWM::Module>. =head1 EXPORTED CONSTANTS M_NEW_PAGE M_NEW_DESK M_OLD_ADD_WINDOW M_RAISE_WINDOW M_LOWER_WINDOW M_OLD_CONFIGURE_WINDOW M_FOCUS_CHANGE M_DESTROY_WINDOW M_ICONIFY M_DEICONIFY M_WINDOW_NAME M_ICON_NAME M_RES_CLASS M_RES_NAME M_END_WINDOWLIST M_ICON_LOCATION M_MAP M_ERROR M_CONFIG_INFO M_END_CONFIG_INFO M_ICON_FILE M_DEFAULTICON M_STRING M_MINI_ICON M_WINDOWSHADE M_DEWINDOWSHADE M_VISIBLE_NAME M_SENDCONFIG M_RESTACK M_ADD_WINDOW M_CONFIGURE_WINDOW M_EXTENDED_MSG MX_VISIBLE_ICON_NAME MX_ENTER_WINDOW MX_LEAVE_WINDOW MX_PROPERTY_CHANGE MX_REPLY MX_PROPERTY_CHANGE_NONE MX_PROPERTY_CHANGE_BACKGROUND MX_PROPERTY_CHANGE_SWALLOW MAX_MSG_MASK MAX_XMSG_MASK HEADER_SIZE START_FLAG RESPONSE_READY RESPONSE_UNLOCK ON_EXIT INTSIZE ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/perllib/FVWM/Event.pm��������������������������������������������������������������������0000644�0001750�0001750�00000017645�14147024700�013263� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright (c) 2003-2009 Mikhael Goikhman # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see: <http://www.gnu.org/licenses/> package FVWM::Event; use strict; use FVWM::EventNames; sub new ($$$) { my $class = shift; my $type = shift; my $arg_values = shift; my $is_special = defined $arg_values ? 0 : 1; my $is_extended = $type & M_EXTENDED_MSG ? 1 : 0; $arg_values ||= []; $arg_values = event_arg_values($is_special ? "faked" : $type, $arg_values) unless ref($arg_values); my $self = { type => $type, args => undef, # lazy hash of event arguments arg_values => $arg_values, propagation_allowed => 1, is_special => $is_special, is_extended => $is_extended, }; bless $self, $class; return $self; } sub type ($) { my $self = shift; return $self->{'type'}; } sub arg_values ($) { my $self = shift; return $self->{'arg_values'}; } sub arg_names ($) { my $self = shift; return event_arg_names($self->type, $self->arg_values); } sub arg_types ($) { my $self = shift; return event_arg_types($self->type, $self->arg_values); } sub loop_arg_names ($) { my $self = shift; return event_loop_arg_names($self->type, $self->arg_values); } sub loop_arg_types ($) { my $self = shift; return event_loop_arg_types($self->type, $self->arg_values); } sub args ($) { my $self = shift; $self->{'args'} ||= event_args($self->type, $self->arg_values); return $self->{'args'}; } sub is_extended ($) { my $self = shift; return $self->{'is_extended'}; } sub name ($) { my $self = shift; return event_name($self->type); } sub propagation_allowed ($;$) { my $self = shift; my $value = shift; $self->{'propagation_allowed'} = $value if defined $value; return $self->{'propagation_allowed'}; } sub dump ($) { my $self = shift; my $args = $self->args; my $string = $self->name . "\n"; my @arg_names = @{$self->arg_names}; my @arg_types = @{$self->arg_types}; my @arg_values = @{$self->arg_values}; while (@arg_names) { my $name = shift @arg_names; my $type = shift @arg_types; my $value = shift @arg_values; my $text; if ($type == FVWM::EventNames::number) { $text = $value; $text = "*undefined*" unless defined $value; } elsif ($type == FVWM::EventNames::bool) { $text = $value? "True": "False"; } elsif ($type == FVWM::EventNames::window) { $text = sprintf("0x%07lx", $value); } elsif ($type == FVWM::EventNames::pixel) { $text = "rgb:" . join('/', sprintf("%06lx", $value) =~ /(..)(..)(..)/); } elsif ($type == FVWM::EventNames::string) { $value =~ s/"/\\"/g; $text = qq("$value"); } elsif ($type == FVWM::EventNames::looped) { my $loop_arg_names = $self->loop_arg_names; my $loop_arg_types = $self->loop_arg_types; my $j = 0; while ($j < @$value) { my $k = 0; foreach (@$loop_arg_names) { my $i = int($j / @$loop_arg_names) + 1; push @arg_names, "[$i] $_"; push @arg_types, $loop_arg_types->[$k]; push @arg_values, $value->[$j]; $j++; $k++; } } $text = sprintf("(%d)", @$value / @$loop_arg_names); } elsif ($type == FVWM::EventNames::wflags) { $text = qq([window flags are not supported yet]); } else { $text = qq([unsupported arg type $type] "$value"); } my $name_len = 12; $name_len = int((length($name) + 5) / 6) * 6 if length($name) > $name_len; $string .= sprintf "\t%-${name_len}s %s\n", $name, $text; } return $string; } sub AUTOLOAD ($;@) { my $self = shift; my @params = @_; my $method = $FVWM::Event::AUTOLOAD; # remove the package name $method =~ s/.*://g; # DESTROY messages should never be propagated return if $method eq 'DESTROY'; if ($method =~ s/^_//) { my $arg_value = $self->args->{$method}; return $arg_value if defined $arg_value; my $alias = event_arg_aliases($self->type)->{$method} || '*none*'; $arg_value = $self->args->{$alias}; return $arg_value if defined $arg_value; die "Unknown argument $method for event " . $self->name . "\n"; } die "Unknown method $method on $self called\n"; } # ---------------------------------------------------------------------------- =head1 NAME FVWM::Event - the fvwm event object passed to event handlers =head1 SYNOPSIS use lib `fvwm-perllib dir`; use FVWM::Module; my $module = new FVWM::Module(Mask => M_FOCUS_CHANGE); # auto-raise all windows sub auto_raise ($$) { my ($module, $event) = @_; $module->debug("Got " . $event->name . "\n"); $module->debug("\t$_: " . $event->args->{$_} . "\n") foreach sort keys %{$event->args}; $module->send("Raise", $event->_win_id); } $module->add_handler(M_FOCUS_CHANGE, \&auto_raise); $module->event_loop; =head1 DESCRIPTION To be written. =head1 METHODS =over 4 =item B<new> I<type> I<arg_values> Constructs event object of the given I<type>. I<arg_values> is either an array ref of event's arguments (every event type has its own argument list, see L<FVWM::EventNames>) or a packed string of these arguments as received from the I<fvwm> pipe. =item B<type> Returns event's type (usually long integer). =item B<arg_names> Returns an array ref of the event argument names. print "$_ " foreach @{$event->arg_names}); Note that this array of names is statical for any given event type. =item B<arg_types> Returns an array ref of the event argument types. print "$_ " foreach @{$event->arg_types}); Note that this array of types is statical for any given event type. =item B<loop_arg_names> Returns an array ref of the looped argument names of the event (or undef). =item B<loop_arg_types> Returns an array ref of the looped argument types of the event (or undef). =item B<arg_values> Returns an array ref of the event argument values. In the previous versions of the library, all argument values were passed to event handlers, now only one event object is passed. Calling this method is the way to emulate the old behaviour. Note that you should know the order of arguments, so the suggested way is to use C<args> instead, although it is a bit slower. =item B<args> Returns hash ref of the named event argument values. print "[Debug] Got event ", $event->type, " with args:\n"; while (($name, $value) = each %{$event->args}) { print "\t$name: $value\n"; } =item B<is_extended> For technical reasons there are 2 categories of fvwm events, regular and extended. This was done to enable more events. With introdution of the extended event types (with the highest bit set) it is now possible to have 31+31=62 different event types rather than 32. This is a good point, the bad point is that only event types of the same category may be masked (or-ed) together. This method returns 1 or 0 depending on whether the event is extended or not. =item B<name> Returns a string representing the event name (like "M_ADD_WINDOW"), it is the same as the corresponding C/Perl constant. May be (and in fact is) used for debugging. =item B<propagation_allowed> [I<bool>] Sets or returns a boolean value that indicates enabling or disabling of this event propagation. =item B<dump> Returns a string representation of the event object, basically the event name and all argument name=value lines. =item B<_>I<name> This is a shortcut for $event->args->{'I<name>'}. Returns the named event argument. See L<FVWM::EventNames> for names of all event argument names. =back =head1 AUTHOR Mikhael Goikhman <migo@homemail.com>. =head1 SEE ALSO For more information, see L<fvwm>, L<FVWM::Module>, L<FVWM::Constants> and L<FVWM::EventNames>. =cut 1; �������������������������������������������������������������������������������������������fvwm-2.7.0/perllib/FVWM/Tracker.pm������������������������������������������������������������������0000644�0001750�0001750�00000026503�14147024700�013566� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Copyright (c) 2003-2009, Mikhael Goikhman # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see: <http://www.gnu.org/licenses/> package FVWM::Tracker; use 5.004; use strict; use FVWM::Constants; sub import ($@) { my $class = shift; my $caller = caller; while (@_) { my $name = shift; if ($name eq 'base') { next if UNIVERSAL::isa($caller, __PACKAGE__); eval " package $caller; use vars qw(\@ISA); use FVWM::Constants; \@ISA = qw(FVWM::Tracker); "; if ($@) { die "Internal error:\n$@"; } } } } sub new ($$) { my $class = shift; my $module = shift; die "$class: no FVWM::Module object given in constructor\n" unless UNIVERSAL::isa($module, "FVWM::Module"); my $self = { module => $module, data => undef, active => 0, handler_types => {}, handler_ids => {}, observers => {}, }; bless $self, $class; return $self; } sub masks ($) { my $self = shift; my $mask = 0; my $xmask = 0; while (my ($id, $type) = each %{$self->{handler_types}}) { (($type & M_EXTENDED_MSG) ? $xmask : $mask) |= $type; } $self->internal_die("Inactive mask is not zero") unless $self->{active} || !$mask && !$xmask; my @list = ($mask, $xmask); return wantarray ? @list : \@list; } sub add_handler ($$$) { my $self = shift; my $type = shift; my $handler = shift; my $handler_id = $self->{module}->add_handler($type, $handler, 1); $self->{handler_types}->{$handler_id} = $type; $self->{handler_ids}->{$handler_id} = $handler_id; return $handler_id; } sub delete_handlers ($;$) { my $self = shift; my $handler_ids = ref($_[0]) eq 'ARRAY' ? shift() : [ keys %{$self->{handler_ids}} ]; foreach (@$handler_ids) { next unless defined delete $self->{handler_types}->{$_}; my $handler_id = delete $self->{handler_ids}->{$_} or die "Internal #1"; if ($self->{module}) { $self->{module}->delete_handler($handler_id) or die "Internal #2"; } } } sub observe ($$;$) { my $self = shift; my $observable = ref($_[0]) eq "" ? shift : "main"; my $callback = shift; my $observables = $self->observables; $observable = $observables->[0] if $observable eq "main"; $self->{module}->debug(qq(observe "$observable"), 3); # TODO: check observable existence $self->{observers}->{$observable} ||= []; push @{$self->{observers}->{$observable}}, $callback; return [ $observable, @{$self->{observers}->{$observable}} - 1 ]; } sub unobserve ($;$$) { my $self = shift; my $observable = ref($_) eq "" ? shift : "*"; my $observer_id = shift || "*"; ### TODO #$self->{observers}->{$observable} = []; } sub notify ($$@) { my $self = shift; my $observable = shift; my $observables = $self->observables; $observable = $observables->[0] if $observable eq "main"; $self->{module}->debug(qq(notify "$observable"), 3); # TODO: check observable existence my @callbacks = (); push @callbacks, @{$self->{observers}->{$observable}} if exists $self->{observers}->{$observable}; push @callbacks, @{$self->{observers}->{'all'}} if exists $self->{observers}->{'all'} && $observable ne 'all'; foreach (@callbacks) { $_->($self->{module}, $self, $self->data, @_); } } sub start ($) { my $self = shift; return if $self->{active}; $self->{active} = 1; $self->{module}->FVWM::Module::event_loop(1) if %{$self->{handler_ids}}; return $self->data; } sub stop ($) { my $self = shift; return unless $self->{active}; $self->delete_handlers; $self->{active} = 0; } sub restart ($) { my $self = shift; $self->stop; $self->start; } sub to_be_disconnected ($) { } sub data ($) { my $self = shift; return $self->{data}; } sub dump ($) { my $self = shift; return ""; } sub request_windowlist_events ($) { my $self = shift; my $module = $self->{module}; warn "request_windowlist_events() called after start()" if $self->{active}; $self->add_handler(M_END_WINDOWLIST, sub { $_[0]->terminate; }); $module->emulate_event(M_END_WINDOWLIST, []) if $module->is_dummy; $module->postpone_send("Send_WindowList"); } sub request_configinfo_events ($;$) { my $self = shift; my $name = shift; my $module = $self->{module}; warn "request_configinfo_events() called after start()" if $self->{active}; $self->add_handler(M_END_CONFIG_INFO, sub { $_[0]->terminate; }); $module->emulate_event(M_END_CONFIG_INFO, []) if $module->is_dummy; $module->postpone_send("Send_ConfigInfo" . ($name ? " *$name" : "")); } sub internal_die ($$) { my $self = shift; my $msg = shift; my $class = ref($self); $self->{module}->internal_die("$class: $msg") } sub DESTROY ($) { my $self = shift; $self->stop; } # class method, should be overwritten sub observables ($) { return []; } use vars qw($AUTOLOAD); # support old API, like addHandler, dispatch to add_handler sub AUTOLOAD ($;@) { my $self = shift; my @params = @_; my $autoload_method = $AUTOLOAD; my $method = $autoload_method; # remove the package name $method =~ s/.*://g; $method =~ s/XMask/Xmask/; $method =~ s/([a-z])([A-Z])/${1}_\L$2/g; die "No method $method in $self as guessed from $autoload_method" unless $self->can($method); $self->$method(@params); } 1; __END__ =head1 DESCRIPTION Tracker is an object that automatically listens to certain fvwm events and gathers an information in the background. When a tracker is created it may enter its own event loop to gather an initial data, so the returned tracker object already has the initial data. It also continues to update the data automatically until it is stopped. This package is a superclass for the concrete tracker implementations. It defines the common Tracker API, including a way to access the tracked data and to define high level events for the tracker caller to observe. =head1 SYNOPSYS Using B<FVWM::Module> $module object: my $tracker = $module->track("TrackerName", @params); my $initial_data = $tracker->data; $tracker->observe("observable1", sub { shift->data }); $tracker->observe("observable2", sub { shift->stop }); In the future this syntax will probably work too: my $tracker = new FVWM::Tracker::TrackerName($module, @params); my $initial_data = $tracker->start; $tracker->observe("observable1", sub { shift->data }); $tracker->observe("observable2", sub { shift->stop }); =head1 PUBLIC METHODS =over 4 =item B<start> Makes the tracker actually work, i.e. listen to I<fvwm> events, gather data and forms high level events, so called observables. This method is usually automatically called when the tracker is created unless specifically asked not to. =item B<stop> Stops the tracker activity. The corresponding I<fvwm> events are not listened, data is not updated and no observers called. To return the tracker to the normal activity, call B<start> method. =item B<restart> This is a shortcut method to B<stop> and then B<start> the tracker. The following scenatio is possible. You start the tracker, read its data and immediately stop it (to reduce event tracker to the module). At some point you may want to read the updated data, so you restart the tracker and optionally stop it again. Note that no observers are removed during B<stop>, so the tracker theoretically may be restarted without any side effect even if some observers are defined. =item B<observe> [I<observable>] I<observer-callback> Defines an observer that will be called every time the tracker I<observable> happens. The I<observer-callback> is a CODE reference that gets the following parameters: $module (B<FVWM::Module> object), $tracker (this object), $data (the same as returned by B<data> method) and optional observable parameters that are specific to this I<observable>. A special I<observable> value "main" means the first observable defined in the tracker, it is the default value when no I<observable> is given. =item B<unobserve> [I<observable> [I<observer-id>]] Stops an observing using the I<observer-id> that is returned by B<observe> method. A special I<observable> value "main" means the first observable defined in the tracker. A special I<observable> value "*" means all defined observables. =item B<data> Returns the whole data collected by the tracker. Usually subclasses add an optional parameter I<key> that limits the whole data to the given key. =item B<dump> Returns the string representing the whole tracker data in the human readable form, useful for debugging. Usually subclasses add an optional parameter I<key> that limits the whole data to the given key. =back =head1 METHODS FOR SUBCLASSES =over 4 =item B<observables> A subclass should define a list of observables that a caller may listen to using B<observe> method. It is the subclass responsiblity to actually signal every observable listed using B<notify> method. Returns a reference to a string array. =item B<new> I<module> I<param-hash> This superclass method should be called by subclasses. Please do not use this class method in programs, use the first syntax shown in the I<SYNOPSYS> section instead. I<module> is an B<FVWM::Module> instance. I<param-hash> is specific to the concrete Tracker class. =item B<add_handler> I<type> I<handler> A wrapper to B<FVWM::Module>::B<add_handler>, has the same syntax, but stores all handlers so they may be deleted at once using B<delete_handlers>. =item B<delete_handlers> [I<handler-ids>] Deletes all handlers defined using add_handler or the ones specified using an optional I<handler-ids> array ref. =item B<notify> I<observable> [I<observable-params>] Notifies all listeners that were defined using B<observe>, by calling their observer function with the following parameters: $module, $tracker, $data, I<observable-params>. =item B<request_windowlist_events> Subclasses that work using I<fvwm> events sent in responce to B<Send_WindowList> command should call this shortcut method. Automatically sends the needed command (after the tracker event mask is counted) and defines a handler that terminates the initial tracker event loop in response to I<M_END_WINDOWLIST> event. =item B<request_configinfo_events> Subclasses that work using I<fvwm> events sent in responce to B<Send_ConfigInfo> command should call this shortcut method. Automatically sends the needed command (after a tracker event mask is counted) and defines a handler that terminates the initial tracker event loop in response to I<M_END_CONFIG_INFO> event. =item B<internal_die> Subclasses may call this method when something wrong happens. This is a wrapper to B<FVWM::Module>::B<internal_die>. =item B<to_be_disconnected> Does nothing by default. Subclasses may implement this method if something should be sent to I<fvwm> just before the module disconnects itself. =back =head1 AUTHOR Mikhael Goikhman <migo@homemail.com>. =head1 SEE ALSO For more information, see L<FVWM::Module> and the concrete tracker implementations: L<FVWM::Tracker::Colorsets>, L<FVWM::Tracker::GlobalConfig>, L<FVWM::Tracker::ModuleConfig>, L<FVWM::Tracker::PageInfo>, L<FVWM::Tracker::Scheduler>, L<FVWM::Tracker::WindowList>. =cut ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/perllib/FVWM/create-commands�������������������������������������������������������������0000755�0001750�0001750�00000007406�14147024700�014626� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/usr/bin/perl -w use FindBin; use lib "$FindBin::Bin/.."; use General::FileSystem; use POSIX; chdir($FindBin::Bin) || die "Can't chmod $FindBin::Bin: $!\n"; my $functable_src = "../../fvwm/functable.c"; my $content_ref = load_file($functable_src); die "No commands found, so Commands.pm is not generated.\n" unless $content_ref; my $command_entries_code = ""; foreach my $entry ($$content_ref =~ m{(?:/\* )?CMD_ENT\(\s*(?:"|PRE_).*?\),(?: \*/)?.*?/\* .*?- .*? \*/}sg) { my ($name, $flags, $cursor, $name2, $descr) = $entry =~ m{ , .*? CMD_(\w+) , .*? , .*? ([\w\s|]+?) , .*? (?:CRS_)?(\w+) .*? \) , .*? /\*\s (?:(.+)\s)? -\s (.*?) \s\*/ }xs; $name = $name2 if $name2; my $window = $flags =~ FUNC_NEEDS_WINDOW? 1: 0; $cursor = "" if $cursor eq "0"; $command_entries_code .= "\t{\n\t\tname => '$name',\n\t\tcursor => '$cursor',\n" . "\t\twindow => $window,\n\t\tdescr => q{$descr},\n\t},\n"; } my $version = `egrep '^VERSION = |^VERSIONINFO = ' Makefile | cut -d"=" -f2 \\ | perl -pe 's/^ //;s/\\n//'`; my $time = time; my $output = <<ENDOUTPUT; # Autogenerated from the fvwm sources. package FVWM::Commands; use vars qw(\$VERS \$TIME \@LIST); \$VERS = '$version'; \$TIME = $time; \@LIST = ( $command_entries_code); 1; __END__ =head1 NAME FVWM::Commands - lists all available fvwm commands =head1 DESCRIPTION This class is autogenerated from the fvwm sources. It may be used to get a list of all available fvwm commands including the command name, its short description and some other command properties. =head1 USAGE use lib `fvwm-perllib dir`; use FVWM::Commands; use POSIX; my \$date = strftime("%d-%b-%Y", gmtime(\$FVWM::Commands::TIME)); my \$version = \$FVWM::Commands::VERS; print "The recognized commands for fvwm \$version as of \$date:\\n\\n"; foreach my \$command (\@FVWM::Commands::LIST) { printf " %-21s - %s\\n", \$command->{name}, \$command->{descr}; } =head1 PUBLIC CONSTANTS =over 4 =item \$VERS The fvwm version number at the generation time like "2.6.0" plus the info that may indicate that this is not a final version, but a cvs snapshot. =item \$TIME The unix time of the command list generation. Example: print "The fvwm command list found on your system was generated " . (time() - \$FVWM::Commands::TIME) / 86400 . " days ago\\n"; =item \@LIST The command list that is an array of hashes with keys I<name>, I<cursor>, I<descr> (string) and I<window> (boolean). I<name> may be special, like "+", "#" and "*". Other names usually contain only isalpha characters, like B<Move>, B<SendToModule>. I<cursor> may be either empty or the cursor context used in B<CursorStyle> (like "SELECT" or "MOVE"), associated with the command. I<descr> is a short one line description of the command. I<window> is true for commands that need a window. Example: # get command names only \@command_names = map { \$_->{name} } \@FVWM::Commands::LIST; =back =head1 AUTHOR Mikhael Goikhman <migo\@homemail.com>. =head1 SEE ALSO For more information about the commands themselves, see fvwm(1). =cut ENDOUTPUT # --------------------------------- print "Creating Commands.pm\n"; save_file("Commands.pm", \$output); # --------------------------------- print "Testing Commands.pm\n"; eval qq{ use lib '$FindBin::Bin/..'; use FVWM::Commands; }; die $@ if $@; $FVWM::Commands::TIME ||= 0; # avoid "used once" warning my $date = strftime("%d-%b-%Y", gmtime($FVWM::Commands::TIME)); my $cmds = "The recognized commands for fvwm $version as of $date:\n\n"; foreach my $command (@FVWM::Commands::LIST = @FVWM::Commands::LIST) { $cmds .= sprintf " %-21s - %s\n", $command->{name}, $command->{descr}; } # --------------------------------- print "Creating ../../docs/COMMANDS\n"; save_file("../../docs/COMMANDS", \$cmds); ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/perllib/FVWM/Makefile.am�����������������������������������������������������������������0000644�0001750�0001750�00000001175�14147024700�013667� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Process this file with automake to create Makefile.in SUBDIRS = Module Tracker configdir = @FVWM_PERLLIBDIR@/FVWM ORIGINAL_PMS = \ Commands.pm Constants.pm EventNames.pm Event.pm Tracker.pm config_DATA = $(ORIGINAL_PMS) Module.pm EXTRA_DIST = $(ORIGINAL_PMS) create-commands create-constants _Constants.pm: Makefile.am $(top_srcdir)/libs/Module.h cd $(top_builddir)/perllib/FVWM && \ (fvwm_libdir=$(top_builddir)/libs ./create-constants) _Commands.pm: Makefile $(top_srcdir)/fvwm/functable.c cd $(top_builddir)/perllib/FVWM && \ (fvwm_libdir=$(top_builddir)/libs ./create-commands) regenerate: _Constants.pm _Commands.pm ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/perllib/Makefile.in����������������������������������������������������������������������0000644�0001750�0001750�00000051610�14324315776�013135� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 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 = perllib ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.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 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)` 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" ACLOCAL = @ACLOCAL@ ALL_DOMAINS = @ALL_DOMAINS@ ALL_LINGUAS = @ALL_LINGUAS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR_FLAGS = @AR_FLAGS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ Bidi_CFLAGS = @Bidi_CFLAGS@ Bidi_LIBS = @Bidi_LIBS@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DOC_COMMANDS = @DOC_COMMANDS@ DOC_COMMANDS_HTML = @DOC_COMMANDS_HTML@ DOC_COMMANDS_XML = @DOC_COMMANDS_XML@ DOC_COMMANDS_XML_PATH = @DOC_COMMANDS_XML_PATH@ DOC_MODULES = @DOC_MODULES@ DOC_MODULES_HTML = @DOC_MODULES_HTML@ DOC_SECTIONS = @DOC_SECTIONS@ DOC_SECTIONS_XML = @DOC_SECTIONS_XML@ DOC_SECTIONS_XML_PATH = @DOC_SECTIONS_XML_PATH@ DUMMYPOFILES = @DUMMYPOFILES@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FC_CFLAGS = @FC_CFLAGS@ FC_CONFIG = @FC_CONFIG@ FC_LIBS = @FC_LIBS@ FRIBIDI_CONFIG = @FRIBIDI_CONFIG@ FVWMALTFTP = @FVWMALTFTP@ FVWMALTFTPDIR = @FVWMALTFTPDIR@ FVWMFTP = @FVWMFTP@ FVWMFTPDIR = @FVWMFTPDIR@ FVWMHOMEPAGE = @FVWMHOMEPAGE@ FVWMLIST = @FVWMLIST@ FVWMNAMELONG = @FVWMNAMELONG@ FVWMSCRIPT_DOMAIN = @FVWMSCRIPT_DOMAIN@ FVWMTASKBAR_DOMAIN = @FVWMTASKBAR_DOMAIN@ FVWMWORKERSLIST = @FVWMWORKERSLIST@ FVWMWORKERSLISTLONG = @FVWMWORKERSLISTLONG@ FVWM_CONFDIR = @FVWM_CONFDIR@ FVWM_CPP = @FVWM_CPP@ FVWM_DATADIR = @FVWM_DATADIR@ FVWM_DOCDIR = @FVWM_DOCDIR@ FVWM_DOMAIN = @FVWM_DOMAIN@ FVWM_IMAGEPATH = @FVWM_IMAGEPATH@ FVWM_MODULEDIR = @FVWM_MODULEDIR@ FVWM_PERLLIB = @FVWM_PERLLIB@ FVWM_PERLLIBDIR = @FVWM_PERLLIBDIR@ GDK_IMLIB_CFLAGS = @GDK_IMLIB_CFLAGS@ GDK_IMLIB_LIBS = @GDK_IMLIB_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ IMLIBCONF = @IMLIBCONF@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INST_LINGUAS = @INST_LINGUAS@ ISRELEASED = @ISRELEASED@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOCALEDIR = @LOCALEDIR@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANPAGE_PREAMBLE = @MANPAGE_PREAMBLE@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ MSGUNIQ = @MSGUNIQ@ OBJEXT = @OBJEXT@ 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@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PYTHON = @PYTHON@ RANLIB = @RANLIB@ RELDATELONG = @RELDATELONG@ RELDATENUM = @RELDATENUM@ RELDATESHORT = @RELDATESHORT@ REQUIRED_PERL_VERSION = @REQUIRED_PERL_VERSION@ REQUIRED_PYTHON_VERSION = @REQUIRED_PYTHON_VERSION@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ UPDATEPOFILES = @UPDATEPOFILES@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VERSIONINFO = @VERSIONINFO@ XFT_CFLAGS = @XFT_CFLAGS@ XFT_CONFIG = @XFT_CONFIG@ XFT_LIBS = @XFT_LIBS@ XGETTEXT = @XGETTEXT@ XMKMF = @XMKMF@ XSLTPROC = @XSLTPROC@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Xcursor_CFLAGS = @Xcursor_CFLAGS@ Xcursor_LIBS = @Xcursor_LIBS@ Xft_CFLAGS = @Xft_CFLAGS@ Xft_LIBS = @Xft_LIBS@ Xinerama_CFLAGS = @Xinerama_CFLAGS@ Xinerama_LIBS = @Xinerama_LIBS@ Xrender_CFLAGS = @Xrender_CFLAGS@ Xrender_LIBS = @Xrender_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ iconv_CFLAGS = @iconv_CFLAGS@ iconv_LIBS = @iconv_LIBS@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intl_CFLAGS = @intl_CFLAGS@ intl_LIBS = @intl_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ png_CFLAGS = @png_CFLAGS@ png_LIBS = @png_LIBS@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ readline_CFLAGS = @readline_CFLAGS@ readline_LIBS = @readline_LIBS@ rplay_CFLAGS = @rplay_CFLAGS@ rplay_LIBS = @rplay_LIBS@ rsvg_CFLAGS = @rsvg_CFLAGS@ rsvg_LIBS = @rsvg_LIBS@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ stroke_CFLAGS = @stroke_CFLAGS@ stroke_LIBS = @stroke_LIBS@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ with_bidi = @with_bidi@ with_gdkimlib = @with_gdkimlib@ with_gettext = @with_gettext@ with_iconv = @with_iconv@ with_perllib = @with_perllib@ with_png = @with_png@ with_readline = @with_readline@ with_rplay = @with_rplay@ with_rsvg = @with_rsvg@ with_shape = @with_shape@ with_shm = @with_shm@ with_sm = @with_sm@ with_stroke = @with_stroke@ with_xcursor = @with_xcursor@ with_xft = @with_xft@ with_xinerama = @with_xinerama@ with_xpm = @with_xpm@ with_xrender = @with_xrender@ xpm_CFLAGS = @xpm_CFLAGS@ xpm_LIBS = @xpm_LIBS@ SUBDIRS = FVWM General all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(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) --foreign perllib/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign perllib/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: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): # 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 installdirs: installdirs-recursive installdirs-am: 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 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-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 pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) uninstall-hook .MAKE: $(am__recursive_targets) install-am install-strip uninstall-am .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic cscopelist-am ctags ctags-am \ distclean distclean-generic 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 installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-hook .PRECIOUS: Makefile uninstall-hook: rm -fr @FVWM_DATADIR@/perllib # 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: ������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/perllib/Makefile.am����������������������������������������������������������������������0000644�0001750�0001750�00000000201�14147024700�013075� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Process this file with automake to create Makefile.in SUBDIRS = FVWM General uninstall-hook: rm -fr @FVWM_DATADIR@/perllib �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/bin/�������������������������������������������������������������������������������������0000755�0001750�0001750�00000000000�14324316055�010253� 5����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/bin/fvwm-convert-2.6.1�������������������������������������������������������������������0000644�0001750�0001750�00000007076�14324316007�013224� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" @(#)fvwm-2.7.0 19 October 2022 .TH fvwm-convert-2.6 1 "19 October 2022 (2.7.0)" Fvwm "Fvwm Modules" .SH NAME fvwm-convert-2.6 \- convert fvwm 2.4.x configuration file to fvwm 2.6 style .SH SYNOPSIS .B fvwm-convert-2.6 .RI [ --follow-read | -f ] .RI [ --help | -h ] .RI source .RI [ dest ] .SH OPTIONS The following options are supported: .IP "\fB\-\-help\fR | \fB\-h\fR" Prints a usage message to the screen. .IP "\fB\-\-follow\-read\fR | \fB\-f\fR" Follows files found along with the .B Read command. .SH DESCRIPTION .B fvwm-convert-2.6 converts an fvwm 2.4.x configuration file into a fvwm 2.6 file with compatible syntax. It is not suitable to convert older 2.x configuration files. Please use .B fvwm-convert-2.2 to convert these to the 2.2.x format first, and then if necessary .B fvwm-convert-2.4 .PP By default, .B fvwm-convert-2.6 won't look for a given config file. This must be specified as the first parameter to .B fvwm-convert-2.6. Different source and destination files may be given. If the destination file already exists, this program exits. If no destination file is given, then the filename is the same name as the source file with the suffix ".converted" added. Without an absolute path given as the destination path to the destination file, the program will create the destination file in the CWD. .PP .B fvwm-convert-2.6 makes the following changes: .TP 4 .B Style lines In fvwm 2.4, most style options could be negated from their counterparts using NoFoo -- fvwm-convert-2.6 corrects this by now using !Foo. .TP 4 .B ModulePath In fvwm 2.4 and beyond, the ModulePath is compiled into fvwm. .B fvwm-convert-2.6 comments out any ModulePath commands it finds. If you are using your own modules, (not the ones that come with fvwm), you will have to fix your configuration file after using .BR fvwm-convert-2.6 . .TP 4 .B Conditional command syntax In fvwm 2.4, the conditional command options were whitespace-separated -- they should now be comma-separated instead. In addition, the older syntax to Next and Prev of using [*] to denote all windows has been removed entirely. Both these checks and conversions are done on function commands, key/mouse bindings. .TP 4 .B WindowShadeSteps In fvwm 2.4, the WindowShadeSteps command is replaced by the WindowShadeSteps Style option. .B fvwm-convert-2.6 makes this change. .TP 4 .B FvwmTheme In fvwm 2.6, the FvwmTheme module is replaced by a series of Colorset commands. Whilst .B fvwm-convert-2.6 will try and make this change, it is still recommended that this is checked after conversion. .TP 4 .B EdgeResistance In fvwm 2.6, the EdgeResistance command is has been split to include an additional style option for EdgeMoveResistance. .B fvwm-convert-2.6 makes any changes necessary. .TP 4 .B StartFunction / RestartFunction / InitFunction In fvwm 2.6, the need for using InitFunction and/or RestartFunction is redundant when StartFunction is read at both of these times. .B fvwm-convert-2.6 attempts to convert this. .TP 4 .B Read If .B -f or .B --follow-read is given, any files .B fvwm-convert-2.6 can detect and open will be converted automatically, else a list of files that can be followed are printed to the screen. .TP 4 .SH BUGS .I InitFunction and .I RestartFunction and hence .I StartFunction are printed at the end of the files -- this slight reordering might put some comments before in an odd spot. When converting over FvwmTheme lines, the colorset definitions might well be broken, but these cannot easily be converted. Bug reports can be sent to the fvwm-workers mailing list (see the .IR FAQ ). .SH AUTHOR Thomas Adam <thomas.adam22@gmail.com> ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/bin/fvwm-bug.1���������������������������������������������������������������������������0000644�0001750�0001750�00000002735�14324316007�012013� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" @(#)fvwm-2.7.0 19 October 2022 .TH fvwm-bug 1 "19 October 2022 (2.7.0)" Fvwm "Fvwm Modules" .SH NAME fvwm-bug \- report a bug in fvwm .SH SYNOPSIS \fBfvwm-bug\fP [\fI--help\fP] [\fI--version\fP] [\fIaddress\fP] .SH DESCRIPTION .B fvwm-bug is a shell script to help the user compose and mail bug reports concerning fvwm in a standard format. .B fvwm-bug invokes the editor specified by the environment variable .SM .B EDITOR on a temporary copy of the bug report format outline. The user must fill in the appropriate fields and exit the editor. .B fvwm-bug then mails the completed report to the local fvwm maintainer, the fvwm workers list \fIfvwm-workers@fvwm.org\fP, or \fIaddress\fP. If the report cannot be mailed, it is saved in the file \fIdead.fvwm-bug\fP in the invoking user's home directory. .PP The bug report format outline consists of several sections. The first section provides information about the machine, operating system, the fvwm version, and the compilation environment. The second section should be filled in with a description of the bug. The third section should be a description of how to reproduce the bug. The optional fourth section is for a proposed fix. Fixes are encouraged. .SH ENVIRONMENT .B fvwm-bug will utilize the following environment variables if they exist: .TP .B EDITOR Specifies the preferred editor. If .SM .B EDITOR is not set, .B fvwm-bug defaults to .BR emacs . .TP .B HOME Directory in which the failed bug report is saved if the mail fails. �����������������������������������fvwm-2.7.0/bin/fvwm-menu-desktop.in�����������������������������������������������������������������0000644�0001750�0001750�00000102103�14147024700�014104� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!@PYTHON@ # Modification History # Changed on 18/03/19 by Jaimos Skriletz: # - Updated script for and require Python 3. # - Drop support for Python 2. # - Added support for xdg.Menu.Separator. # - Added option --term-cmd to state the terminal emulator command # to use with Terminal=True .desktop entries. Default: xterm -e # Changed on 16/12/31 by Jaimos Skriletz: # - Added check for FVWM_USERDIR env variable. # - Added check for python-xdg module to print less errors if not found. # - Added option -e/--menu-error to output phython-xdg not found as # a menu for the default-config. # Changed on 16/10/27 by Jaimos Skrietz: # - Renamed default menu to XDGMenu and changed the name of the # FvwmForm to FvwmForm-XDGMenu-Config # - Modified the FvwmForm and added the abilty to load defaults from # the Form's data file. # - Changed default to generate menu titles. Disable with --without-titles # - The top level menu now has two additional items: # 'Regenerate' - Regenerates menu. # 'Configure' - Opens up FvwmForm-XDGMenu-Config. # - Added --regen-cmd "CMD" for a fvwm CMD to use on the Regenerate item. # Default: PipeRead `fvwm-menu-desktop` # - Added --include-items [config|regenerate|both|none] option # to control if the additional items are included in the menu. # - Added --dynamic option to be used with dynamic menus. # - Added --all-menus option to generate all menus and not try to determine # which one is best # - Changed default behavior to include menu titles. # - Added new option --without-titles # Changed on 25/02/14 by Thomas Funk: # - Converting of icons always to png # Changed on 06/10/13 by Thomas Funk: # Some Bugfixes: # - DecodeEncodeErrors in menu names # - no output appears with 'fvwm-menu-desktop --get-menus all|desktop' # - No entry "Regenerate XDG menu(s)" appears with # 'fvwm-menu-desktop --insert-in-menu MenuRoot' # - exchange all tabs with spaces to prevent indention errors # - add two new options: --app-icon --dir-icon # to handle default icons for not available app/dir icons # - fix bug in convert icon routine that background of svg icons are # transparent # Changed on 15/06/13 by Thomas Funk: # support for python-xdg > 0.19. # add gettext localization. # Changed on 10/01/12 by Thomas Funk: # Unicode support. # Changed on 01/26/12 by Dan Espen (dane): # Make compatible with fvwm-menu-desktop. # Restored DestroyMenu, needed for reload menus. # Remove bug, was printing iconpath on converted icons # Replace obsolete optparse, use getopt instead # Change from command line arg for applications.menu # change to using ?$XDG_MENU_PREFIX or theme? fixme # - use "Exec exec" for all commands, remove option. # fixme, fix documentation, FvwmForm-Desktop, usage prompt is wrong # change, mini icons are enabled by default. # there are rescalable icons. # Author: Piotr Zielinski (http://www.cl.cam.ac.uk/~pz215/) # Licence: GPL 2 # Date: 03.12.2005 # This script takes names of menu files conforming to the XDG Desktop # Menu Specification, and outputs their FVWM equivalents to the # standard output. # # http://standards.freedesktop.org/menu-spec/latest/ # This script requires the python-xdg module, which in Debian can be # installed by typing # # apt-get install python3-xdg # # On Fedora, python-xdg is installed by default. import sys import getopt import os.path import os import fnmatch import time # Test for python-xdg try: import xdg.Menu except ImportError: xdg_import_error = True else: xdg_import_error = False import xdg.IconTheme import xdg.Locale from xdg.DesktopEntry import * from xdg.BaseDirectory import * # Main Function def main (): description = """ Generate Fvwm Menu from xdg files. Standard output is a series Fvwm commands.""" obs_args=['check-app', 'enable-style', 'enable-tran-style', 'fvwm-icons', 'kde_config', 'mini-icon-path', 'merge-user-menu', 'su_gui', 'utf8', 'wm-icons'] dashed_obs_args=[] for a in obs_args : dashed_obs_args.append('--'+a) obs_parms=['check-icons', 'check-mini-icon', 'destroy-type', 'dir', 'icon-app', 'icon-folder', 'icon-style', 'icon-title', 'icon-toptitle', 'icons-path', 'lang', 'menu-style', 'name', 'png-icons-path', 'submenu-name-prefix', 'time-limit', 'tran-icons-path', 'tran-mini-icons-path', 'type', 'uniconv-exec', 'uniconv', 'xterm'] equaled_obs_parms=[] for a in obs_parms : equaled_obs_parms.append(a+'=') dashed_obs_parms=[] for a in obs_parms : dashed_obs_parms.append('--'+a) try: opts, args = getopt.getopt(sys.argv[1:], "hs:t:vwe", ["help", "verbose", "enable-mini-icons", "with-titles", "without-titles", "version", "desktop=", "size=", "theme=", "install-prefix=", "menu-type=", "regen-cmd=", "term-cmd=", "title=", "get-menus=", "set-menus=", "insert-in-menu=", "mini-icon-dir=", "menu-error", "app-icon=", "dir-icon=", "include-items=", "dynamic", "all-menus"]+obs_args+equaled_obs_parms) except getopt.GetoptError as err: # print help information and exit: print(str(err)) # will print something like "option -a not recognized" print(usage) sys.exit(2) global verbose, force, size, current_theme, icon_dir, top, install_prefix, menu_type, menu_list_length, term_cmd global with_titles, menu_entry_count, get_menus, timestamp, set_menus, printmode, insert_in_menu, previous_theme global default_app_icon, default_dir_icon, include_items, config_menus, regen_cmd, dynamic_menu, build_all_menus version = "2.4" verbose = False force = False desktop='' size=24 current_theme='gnome' previous_theme='gnome' icon_dir="~/.fvwm/icons" top='XDGMenu' insert_in_menu = False install_prefix = '' menu_type = '' with_titles = True menu_entry_count = 0 menu_list_length = 0 get_menus = '' printmode = True set_menus = [] build_all_menus = False config_menus = [] default_app_icon = "gnome-applications" default_dir_icon = "gnome-fs-directory" include_items = 'both' regen_cmd = 'PipeRead `fvwm-menu-desktop`' dynamic_menu = False menu_error = False term_cmd = "xterm -e" # Loads config options from $FVWM_USERDIR/.FvwmForm-XDGMenu-Config if "FVWM_USERDIR" in os.environ: config_file = "%s/.FvwmForm-XDGMenu-Config" % os.environ['FVWM_USERDIR'] else: config_file = "%s/.fvwm/.FvwmForm-XDGMenu-Config" % os.environ['HOME'] if os.path.isfile(config_file): fvwmform_config = open(config_file, "r", errors="ignore") for l in fvwmform_config: o = l.split() if len(o)>2 and o[0] != '#': if o[1][:3] == 'MEN' and o[2] == 'on': config_menus.append(o[1][3:]) if o[1] == 'IconsOn' and o[2] == 'on': force = True elif o[1] == 'Size': size = int(o[2]) elif o[1] == 'TitlesOn' and o[2] == 'on': with_titles = True elif o[1] == 'Theme': current_theme = o[2] elif o[1] == 'Title': top = o[2] elif o[1] == 'InsertInto': top = o[2] insert_in_menu = True elif o[1] == 'Installprefix': install_prefix = o[2] elif o[1] == 'IconDir': icon_dir = o[2] elif o[1] == 'DirIcon': default_dir_icon = o[2] elif o[1] == 'AppIcon': default_app_icon = o[2] elif o[1] == 'IncludeConfig' and o[2] == 'on': include_items = "config" elif o[1] == 'IncludeRegen' and o[2] == 'on': include_items = "regenerate" elif o[1] == 'IncludeBoth' and o[2] == 'on': include_items = "both" elif o[1] == 'IncludeNone' and o[2] == 'on': include_items = "none" elif o[1] == 'TermCmd': term_cmd = " ".join(o[2:]) fvwmform_config.close() for o, a in opts: if o in ("-v", "--verbose"): verbose = True if os.path.isfile(config_file): vprint("Defaults loaded from %s\n" % config_file) else: vprint("Config file not found: %s\nUsing built-in defaults.\n" % config_file) elif o in ("-h", "--help") : print(usage) sys.exit() elif o in ("--version") : print("fvwm-menu-desktop version " + version) sys.exit() elif o in ("-e", "--menu-error") : menu_error = True elif o in ("--enable-mini-icons") : force=True elif o in ("--insert-in-menu") : top=a insert_in_menu = True elif o in ("--desktop") : desktop=a elif o in ("-t", "--title") : top=a elif o in ("--get-menus") : if a == 'all' or a == 'desktop' : get_menus=a printmode = False else : sys.stderr.write( "--get-menus argument must be 'all' or 'desktop' found "+a ) print(usage) sys.exit(1) elif o in ("-s","--size") : size = int(a) elif o in ("--mini-icon-dir") : icon_dir = a elif o in ("--set-menus") : if a[-1] == ' ': a = a[:-1] set_menus=a.split(' ') elif o in ("--install-prefix") : if a and not os.path.isabs(a): assert False, "install-prefix must be an absolute path" # add trailing slash if not there already if not a[-1] == '/' : # trailing slash a=a + '/' install_prefix = a elif o in ("--theme") : current_theme = a elif o in ("--menu-type") : menu_type = a elif o in ("-w", "--with-titles") : with_titles = True elif o in ("--without-titles") : with_titles = False elif o in ("--app-icon") : default_app_icon = a elif o in ("--dir-icon") : default_dir_icon = a elif o in ("--include-items") : if a in ("both", "none", "config", "regenerate") : include_items = a else: sys.stderr.write( "--include-items argument must be 'config', 'regenerate', 'both' or 'none' found "+a ) print(usage) sys.exit(1) elif o in ("--regen-cmd") : regen_cmd = a elif o in ("--term-cmd") : term_cmd = a elif o in ("--dynamic") : dynamic_menu = True elif o in ("--all-menus") : build_all_menus = True elif o in (str(dashed_obs_args+dashed_obs_parms)) : # Ignore sys.stderr.write( "Warning: Arg "+o+" is obsolete and ignored\n" ) else: assert False, "unhandled option" # Exit if python-xdg not found if xdg_import_error: if menu_error: printtext('DestroyMenu "%s"' % top) printtext('AddToMenu "%s" "%s" Title' % (top, top)) printtext('+ "Error: python-xdg not found" Nop') printtext('+ "" Nop') printtext('+ "Regenerate" PipeRead `fvwm-menu-desktop -e`') else: sys.stderr.write('Python module python-xdg not found.') sys.exit(1) timestamp = time.time() if len(set_menus) == 0: xdg_menu_prefix = ((os.environ['XDG_MENU_PREFIX'] if 'XDG_MENU_PREFIX' in os.environ else '')) # First check if no user presettings made if desktop == '': # check if $XDG_MENU_PREFIX is set if not xdg_menu_prefix == '': desktop = xdg_menu_prefix.replace('-', '').lower() vprint("Parameters for creating menu list:") vprint(" XDG_MENU_PREFIX: \'%s\'" %xdg_menu_prefix) vprint(" --install-prefix: \'%s\'" %install_prefix) vprint(" --desktop: \'%s\'" %desktop) vprint(" --menu-type: \'%s\'" %menu_type) vprint("\nStart search ...") menulist, desktop_temp = getmenulist(desktop, menu_type) if not desktop_temp == '': desktop = desktop_temp else: menulist = set_menus vprint(" Menu list: %s\n" %menulist) menu_list_length = len(menulist) if menu_list_length == 0: if not desktop == '': desktop = desktop + '-' if menu_error: printtext('DestroyMenu "%s"' % top) printtext('AddToMenu "%s" "%s" Title' % (top, top)) printtext('+ "Error: No menus found" Nop') printtext('+ "" Nop') printtext('+ "Regenerate" PipeRead `fvwm-menu-desktop -e`') else: sys.stderr.write(install_prefix+desktop+menu_type+".menu not available on this system. Exiting...\n") sys.exit(1) else: # set previous_theme if <icon_dir>/.theme exist if os.path.exists(os.path.join(os.path.expanduser(icon_dir), ".theme")): previous_theme = next(open(os.path.join(os.path.expanduser(icon_dir), ".theme"), 'r')).replace('\n', '') vprint(" Previous used theme: %s" %previous_theme) vprint(" Current used theme: %s\n" %current_theme) sys.stderr.flush() parsemenus(menulist, desktop) # write current_theme to <icon_dir>/.theme if --enable-mini-icons and printmode is set if printmode and force: fh = open(os.path.join(os.path.expanduser(icon_dir), ".theme"), "w") fh.write(current_theme) fh.close() sys.stdout.flush() vprint("\nProcess took " + str(time.time()-timestamp) + " seconds") def getmenulist(desktop, menu_type): menudict = {} config_dirs = [] if not install_prefix == '': config_dirs = [install_prefix] else: config_dirs = xdg_config_dirs # xdg_config_dirs is a built-in list from python-xdg found_menus = 0 for dir in config_dirs: if install_prefix == '': dir = os.path.join(dir, 'menus') # skipping all paths which not available if os.path.exists(dir): filelist = set([]) dir_list = os.listdir(dir) #pattern = '*'+desktop+'*'+menu_type+'*.menu' # Always find all menus pattern = '*.menu' for filename in fnmatch.filter(dir_list, pattern): filelist.add(filename) # the menudict dictionary has a unsorted list (set) for the values. # set is easier to use then a list for removing items menudict[dir] = filelist found_menus += len(filelist) vprint(" found in %s: %s" %(dir, list(filelist))) desktop_dict = {} if not found_menus == 0: all_menus = [] # remove all menus in /etc/xdg/menus if exist in user dir for path in list(menudict.keys()): if not path == '/etc/xdg/menus': if path == os.path.join(os.getenv("HOME"), '.config/menus'): menudict['/etc/xdg/menus'] = menudict['/etc/xdg/menus'] - menudict[path] #else: # menudict[path] = menudict[path] - menudict['/etc/xdg/menus'] for menu in list(menudict[path]): all_menus.append(path + '/' + menu) if not menudict['/etc/xdg/menus'] == 0: for menu in list(menudict['/etc/xdg/menus']): all_menus.append('/etc/xdg/menus/' + menu) if get_menus == 'all' or (build_all_menus and desktop == '' and menu_type == ''): return all_menus, '' # get menus selected in config file if len(config_menus) > 0: config_menulist = [] for i in config_menus: for j in all_menus: if fnmatch.fnmatch( j, "*%s.menu" % i ): config_menulist.append(j) vprint("\n Selected menus from config file: %s " % list(config_menulist)) # Use config file if --dekstop not set if len(config_menulist) == 0: vprint(" No menus in config found. Using all menus.") elif desktop == '' and menu_type == '': vprint(" Using menus from config file.") return config_menulist, '' else: vprint(" Ignoring menus in config file, due to --desktop or --menu-type.") # filter --desktop and --menu-type options if desktop != '' or menu_type != '': vprint("\n Filtering menus according to --desktop %s and --menu-type %s" % (desktop, menu_type) ) pattern = '*'+desktop+'*'+menu_type+'*' for path in list(menudict.keys()): for menu in list(menudict[path]): if not fnmatch.fnmatch( menu, pattern ): menudict[path].remove(menu) if menudict[path] == set([]): del menudict[path] if menudict == {}: sys.stderr.write("No menus found matching --desktop %s and --menu-type %s. Exiting...\n" % (desktop, menu_type) ) sys.exit(1) vprint("\n Finding best menu in Menu List: %s" % menudict ) if build_all_menus: all_menus = [] for key in menudict: for i in menudict[key]: all_menus.append(key+'/'+i) return all_menus, '' # sort menus related to desktops and create a weighting vprint("\n DE weighting search: DE => [user menus, system menus, overall]") weight_dict = {} if desktop == '': # first the desktops, then debian (shouldn't appear in others) then others holding # all other non DE menus e.g. tools and at the end the nones without prefixes # If there're other prefixes from other WMs - should be added BEFORE debian DEs = ['gnome', 'kde', 'xfce', 'lxde', 'cinnamon', 'mate', 'debian', 'others', 'none'] else: DEs = [desktop] for de in DEs: menus = set([]) user_menus = 0 system_menus = 0 filled = False for path in list(menudict.keys()): if de == 'none': pattern = '*' elif de == 'others': pattern = '*-*' else: pattern = '*'+de+'*' # fnmatch.filter returns a list of files the pattern match menu_names = fnmatch.filter(menudict[path], pattern) if not len(menu_names) == 0: filled = True for name in menu_names: menus.add(path+'/'+name) # delete each found DE menu from the actual path. So, the menus will be reduced loop by loop. menudict[path] = menudict[path]-set(menu_names) # count the menus found in the users and systems menu path for later weighting if not path == '/etc/xdg/menus': user_menus = len(menu_names) else: system_menus = len(menu_names) if filled: desktop_dict[de] = menus filled = False # fill the weight dictionary with the counts weight_dict[de] = [user_menus, system_menus, user_menus+system_menus] vprint(" %s => %s" %(de, weight_dict[de])) # get the highest rated desktop highest = 0 de_highest = '' for de in sorted(weight_dict.keys()): de_user = weight_dict[de][0] de_system = weight_dict[de][1] de_total = weight_dict[de][2] higher = False if not de_highest == '': # don't weight 'none' and 'others cause both not DEs if not de == 'none' and not de == 'others': highest_user = weight_dict[de_highest][0] highest_system = weight_dict[de_highest][1] highest_total = weight_dict[de_highest][2] # first compare the total counts if highest < de_total: higher = True elif highest == de_total: # if the totals equal compare the users if highest_user < de_user: higher = True elif highest_user == de_user: # it the users equal compare the system menus if highest_system < de_system: higher = True # if the systems equal the last wins elif highest_system == de_system: higher = True # fixme, should be biunique. -but how? With atime? else: higher = True if higher: highest = de_total de_highest = de if highest == 0 : # no dev environments? de_highest = 'others' # use 'others' vprint( "\n Winner: %s" %de_highest) # Perhaps there're a global menus available which are not in the highest rated list if 'none' in desktop_dict: for menu in desktop_dict['none']: name = menu.replace('.menu', '').split('/') # the fnmatch.filter will be used to find NO match because then # the menu is not in the list found = fnmatch.filter(desktop_dict[de_highest], '*'+name[-1]+'*') if found == []: desktop_dict[de_highest].add(menu) # Add 'others' menus to list, because these could be tool menus like yast, etc if 'others' in desktop_dict: for menu in desktop_dict['others']: desktop_dict[de_highest].add(menu) if len(desktop_dict) == 0: return [], '' else: return list(desktop_dict[de_highest]), de_highest def vprint(text): if verbose: sys.stderr.write(text+"\n") # Encoding error handling of menu entries. def printtext(text): try: print(text) except UnicodeEncodeError: if verbose: print("# UnicodeEncodeError - Attempting to encode") try: sys.stdout.flush() sys.stdout.buffer.write(text.encode()) print() except: print(text.encode("ascii", errors="replace").decode("ascii")) except: if verbose: print("# Unknown error - Skipping entry") def geticonfile(icon): iconpath = xdg.IconTheme.getIconPath(icon, size, current_theme, ["png", "xpm", "svg"]) if not iconpath == None: extension = os.path.splitext(iconpath)[1] if not iconpath: return None if not force: return iconpath if iconpath.find("%ix%i" % (size, size)) >= 0: # ugly hack!!! return iconpath if not os.path.isdir(os.path.expanduser(icon_dir)): os.makedirs(os.path.expanduser(icon_dir)) iconfile = os.path.join(os.path.expanduser(icon_dir), "%ix%i-" % (size, size) + os.path.basename(iconpath)) if os.path.exists(iconpath): iconfile = iconfile.replace(extension, '.png') if extension == '.svg': os.system("if test \\( \\( ! -f '%s' \\) -o \\( '%s' -nt '%s' \\) \\) -o \\( '%s' != '%s' \\); then convert -background none '%s' -resize %i '%s' ; fi"% (iconfile, iconpath, iconfile, current_theme, previous_theme, iconpath, size, iconfile)) else: os.system("if test \\( \\( ! -f '%s' \\) -o \\( '%s' -nt '%s' \\) \\) -o \\( '%s' != '%s' \\); then convert '%s' -resize %i '%s' ; fi"% (iconfile, iconpath, iconfile, current_theme, previous_theme, iconpath, size, iconfile)) else: sys.stderr.write("%s not found! Using default icon.\n" % iconpath) return None return iconfile def getdefaulticonfile(command): if command.startswith("Popup"): return geticonfile(default_dir_icon) else: return geticonfile(default_app_icon) def printmenu(name, icon, command): iconfile = '' if force : iconfile = geticonfile(icon) or getdefaulticonfile(command) or icon if not (iconfile == '' or iconfile == None): iconfile = '%'+iconfile+'%' else: sys.stderr.write("%s icon or default icon not found!\n") printtext('+ "%s%s" %s' % (name, iconfile, command)) def parsemenus(menulist, desktop): global menu_entry_count if menu_list_length == 1: new_menulist = menulist # user defines only one special menu parsemenu(xdg.Menu.parse(menulist[0]), top) else: # create a top title list top_titles = [] for file in menulist: # extract and split the filename and set first char of each word to capital name_parts = file.replace('.menu', '').split('/')[-1].split('-') name_parts = [name[0].replace(name[0], name[0].upper())+name[1:] for name in name_parts] top_titles.append(' '.join(name_parts)) # create the submenus new_toptitles = [] new_menulist = [] for title, menu in zip(top_titles, menulist): name = 'Fvwm'+title vprint("Create submenu \'%s\' from \'%s\'" %(name, menu)) parsemenu(xdg.Menu.parse(menu), name, title) # remove a menu if no menu entry was created in its sub menus if not menu_entry_count == 0: new_toptitles.append(title) new_menulist.append(menu) menu_entry_count = 0 else: vprint(" Menu is empty - won't be used!") # create the root menu if printmode: if not insert_in_menu: if dynamic_menu: printtext('DestroyMenu recreate "%s"' % top) else: printtext('DestroyMenu "%s"' % top) if with_titles and not insert_in_menu: printtext('AddToMenu "%s" "%s" Title' % (top, top)) else: printtext('AddToMenu "%s"' % top) for title in sorted(new_toptitles): name = 'Fvwm'+title printmenu(title, '', 'Popup "%s"' % name) if include_items != 'none': printtext('+ "" Nop') if include_items in ("both", "regenerate"): printmenu("$[gt.Regenerate]", "system-software-update", regen_cmd ) if include_items in ("both", "config"): printmenu("$[gt.Configure]", "system-software-update", "Module FvwmPerl -l fvwm-menu-desktop-config.fpl" ) if not get_menus == '': printtext('%s' % ' '.join(new_menulist)) def parsemenu(menu, name="", title=""): global menu_entry_count m = re.compile('%[A-Z]?', re.I) # Pattern for %A-Z (meant for %U) if not name : name = menu.getPath() if not title: title = name if printmode: if not insert_in_menu or not (insert_in_menu and name == top and menu_list_length == 1): if name == top and dynamic_menu: printtext('DestroyMenu recreate "%s"' % name) else: printtext('DestroyMenu "%s"' % name) if with_titles: # for insert-in-menu AddToMenu doesn't have a title for top menu # because this will appear then in the other menu if insert_in_menu and name == top and menu_list_length == 1: printtext('AddToMenu "%s"' % name) else: printtext('AddToMenu "%s" "%s" Title' % (name, title)) else: printtext('AddToMenu "%s"' % name) for entry in menu.getEntries(): if isinstance(entry, xdg.Menu.Menu): if printmode: printmenu(entry.getName(), entry.getIcon(), 'Popup "%s"' % entry.getPath()) elif isinstance(entry, xdg.Menu.MenuEntry): if printmode: desktop = DesktopEntry(entry.DesktopEntry.getFileName()) # eliminate '%U' etc behind execute string execProgram = m.sub('', desktop.getExec()) if desktop.getTerminal(): execProgram = "%s %s" % (term_cmd, execProgram) printmenu(desktop.getName(), desktop.getIcon(), "Exec exec " + execProgram) menu_entry_count += 1 elif isinstance(entry, xdg.Menu.Separator): if printmode: printtext( '+ "" Nop' ) else: if printmode: printtext('# not supported: ' + str(entry)) if printmode: # should only appear in a single menu. For more it will insert in parsemenus() when the top menu will built if menu_list_length == 1 and name == top and include_items != 'none': printtext('+ "" Nop') if include_items in ("both", "regenerate"): printmenu("$[gt.Regenerate]", "system-software-update", regen_cmd ) if include_items in ("both", "config"): printmenu("$[gt.Configure]", "system-software-update", "Module FvwmPerl -l fvwm-menu-desktop-config.fpl" ) printtext('') for entry in menu.getEntries(): if isinstance(entry, xdg.Menu.Menu): parsemenu(entry) usage=""" A script which parses xdg menu definitions to build the corresponding fvwm menus. Usage: $0 [OPTIONS] Options: -h, --help show this help and exit. --version show version and exit. --install-prefix DIR install prefix of the desktop menu files. Per default not set. For system wide menus use /etc/xdg/menus/. --desktop NAME use menus that include NAME in the file name: gnome, kde, xfce, lxde, debian, etc. --menu-type NAME use menus that include NAME in the file name: applications, settings, preferences, etc. When used with --desktop only menus whose file name mathces '*desktop*menutype*' are used. --theme NAME icon theme: gnome (default), oxygen, etc. Don't use hicolor. It's the default fallback theme if no icon is found. -w, --with-titles generate menus with titles. Default. --without-titles generate menus without titles. --enable-mini-icons enable mini-icons in menu. -s, --size NUM set size of mini-icons in menu. Default is 24. --mini-icon-dir DIR set directory for mini-icons. Default is ~/.fvwm/icons. --app-icon NAME set default application icon if no others found. Default is 'gnome-applications'. --dir-icon NAME set default directory icon if no others found. Default is 'gnome-fs-directory'. -t, --title NAME menu title of the top menu used by Popup command. Default is XDGMenu. --insert-in-menu NAME generates a menu to place it in the root level of the menu NAME. --get-menus all|desktop prints a space separated list of full menu paths. 'all' is all menus on the system except empty ones. 'desktop' list the menus that would have been generated. No menu generation is done. --set-menus menu_paths expects a space separated list of full menu paths to generate user specified menus. --all-menus generate all menus found. --include-items NAME include additional menu items NAME in top level menu. NAME can be 'config', 'regenerate', 'both' or 'none'. Default both. --regen-cmd ACTION The fvwm ACTION for the 'Regenerate' menu item. Default: 'PipeRead `fvwm-menu-desktop`' --term-cmd CMD Terminal emulator CMD used on terminal entries. Default: xterm -e --dynamic used with dynamic menus. -e, --menu-error out python-xdg not found error in menu. -v, --verbose run and display debug info on STDERR.""" if __name__ == "__main__": main() # Local Variables: # mode: python # compile-command: "python3 fvwm-menu-desktop.in --version" # End: �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/bin/fvwm-menu-desktop.1������������������������������������������������������������������0000644�0001750�0001750�00000037234�14324316007�013653� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" t .\" @(#)fvwm-2.7.0 19 October 2022 .de EX \"Begin example .ne 5 .if n .sp 1 .if t .sp .5 .nf .in +.5i .. .de EE .fi .in -.5i .if n .sp 1 .if t .sp .5 .. .ta .3i .6i .9i 1.2i 1.5i 1.8i .TH fvwm-menu-desktop 1 "19 October 2022 (2.7.0)" Fvwm "Fvwm Modules" .UC .SH NAME fvwm-menu-desktop \- Reads XDG menu files and creates Fvwm menus .SH SYNOPSIS fvwm-menu-desktop [ \fB\-\-help\fR|\fB\-h\fR ] [ \fB\-\-version\fR ] [ \fB\-\-install\-prefix\fR \fIDIR\fR ] [ \fB\-\-desktop\fR \fINAME\fR ] [ \fB\-\-menu\-type\fR \fINAME\fR ] [ \fB\-\-theme\fR \fINAME\fR ] [ \fB\-\-with\-titles\fR|\fB\-w\fR ] [ \fB\-\-without\-titles\fR ] [ \fB\-\-enable\-mini\-icons\fR ] [ \fB\-\-size\fR|\fB\-s\fR \fINUM\fR ] [ \fB\-\-mini\-icon\-dir\fR \fIDIR\fR ] [ \fB\-\-app\-icon\fR \fINAME\fR ] [ \fB\-\-dir\-icon\fR \fINAME\fR ] [ \fB\-\-title\fR|\fB\-t\fR \fINAME\fR ] [ \fB\-\-insert\-in\-menu\fR \fINAME\fR ] [ \fB\-\-get\-menus\fR \fIall\fR|\fIdesktop\fR ] [ \fB\-\-set\-menus\fR \fImenu_paths\fR ] [ \fB\-\-all\-menus\fR ] [ \fB\-\-include\-items\fR \fINAME\fR ] [ \fB\-\-regen\-cmd\fR \fICMD\fR ] [ \fB\-\-term\-cmd\fR \fICMD\fR ] [ \fB\-\-dynamic\fR ] [ \fB\-\-menu-error\fR|\fB\-e\fR ] [ \fB\-\-verbose\fR|\fB\-v\fR ] .SH DESCRIPTION This is a python script which parses XDG menus definitions to build corresponding fvwm menus. This script depends on python-xdg to run. .SH OPTIONS .IP "Main Options" .IP "\fB\-\-help\fR" Show the help and exit. .IP "\fB\-\-version\fR" Show the version and exit. .IP "\fB\-\-get\-menus\fR \fIall\fR|\fIdesktop\fR" Prints a space separated list of full menu paths found on the system. \fIall\fR will print all menus found on the system except empty ones. \fIdesktop\fR will print the menu(s) that would be generated by the script. No menu generation is done. .IP "\fB\-\-desktop\fR \fINAME\fR" Optional parameter to set the \fINAME\fR of the desktop XDG .menu file(s) to use. This option will override any default menus set via \fBFvwmForm-XDGMenu-Config\fR and cause the script to find menus in which \fINAME\fR is a part of the file name. Possible names are: \fIgnome\fR, \fIkde\fR, \fIxfce\fR, \fIlxde\fR, \fIdebian\fR, etc. This option can be used in conjunction with \fB\-\-menu\-type\fR to control which .menu file(s) are used. .IP "\fB\-\-menu\-type\fR \fINAME\fR" Optional parameter to set the \fINAME\fR of the XDG menu type to use. This option will override any default menus set via \fBFvwmForm-XDGMenu-Config\fR and cause the script to find menus in which \fINAME\fR is a part of the file name. Possible \fINAME\fR types could be: \fIapplications\fR, \fIsettings\fR, \fIpreferences\fR, etc. When used in conjunction with \fB\-\-desktop\fR, only menus whose file name matches '*destkop*menutype*' are found. If no menus are found, the script exits with an error. .IP "\fB\-\-all\-menus\fR" This option will build all menus found on the system. If used in conjunction with \fB\-\-desktop\fR or \fB\-\-menu\-type\fR this will build all menus matching those settings. .IP "\fB\-\-install-prefix\fR \fIDIR\fR" Optional parameter to override the standard locations for XDG menu definitions. Tells \fBfvwm-menu-desktop\fR to look in \fIDIR\fR for .menu files instead of the standard locations /etc/xdg/menus (and $HOME/.config/menus if it exists). .IP "\fB\-\-with\-titles\fR|\fB\-w\fR" If this option is set menus are generated with titles. This is the default. This option can be used to override the \fBFvwmForm-XDGMenu-Config\fR default setting. .IP "\fB\-\-without\-titles\fR" If this option is set menus are generated without titles. The default is to generate with titles. .IP "\fB\-\-title\fR|\fB\-t\fR \fINAME\fR " Option to define the menu title \fINAME\fR of the top menu used by Fvwm's \fBMenu\fR or \fBPopup\fR commands. Default is "XDGMenu". .IP "\fB\-\-include\-items\fR \fINAME\fR " This option controls if the additional menu items 'Regenerate' and 'Configure' are included in the top level menu. \fINAME\fR can be one of \fIregenerate\fR, \fIconfig\fR, \fIboth\fR, or \fInone\fR. The default is \fIboth\fR. .IP "\fB\-\-regen\-cmd\fR \fICMD\fR " This option sets the fvwm command \fICMD\fR that is run when the menu item \&'Regenerate' is selected. The default is "PipeRead `fvwm-menu-desktop`". .IP "\fB\-\-term\-cmd\fR \fICMD\fR " This option sets the terminal emulator command \fICMD\fR that is used to to run terminal applications in. \fICMD\fR needs to end with an execute option, such as xterm's -e option, which will run the command that is appended to \fICMD\fR. The default is "xterm -e". .IP "\fB\-\-dynamic\fR " This option is to be used with creating dynamic menus using \fBDynamicPopUpAction\fR and \fBDynamicPopDownAction\fR. This adds a 'recreate' to the \fBDestroyMenu\fR command on the top level menu so those actions are not Destroyed when the menu is regenerated. .IP "\fB\-\-insert\-in\-menu\fR \fINAME\fR" Option to insert generated menu(s) \fBIN\fR a menu \fINAME\fR (its top title). This option makes it so the top level menu is not Destroyed and the items are added to the end. Note menus regenerated with this option will append the menu items at the end of the existing menu. Each time the menu is regenerated new menu items appear giving a growing menu of duplicate items. You have to regenerate the whole menu via a function or restart fvwm. See \fBEXAMPLES\fR below for some solutions. .IP "\fB\-\-set\-menus\fR \fImenu_paths\fR" Generates all menus listed in a space separated list of full menu paths. This option overrides any defaults and \fB\-\-desktop\fR|\fB\-\-menu\-type\fR settings. .IP "\fB\-\-menu-error\fR |\fB\-t\fR" If this option is present and python-xdg is not found, the script will print the error in the generated menu. Used in the default-config. .IP "\fB\-\-verbose\fR" Enables additional information printouts on STDERR. .IP "Icons Options" By default, fvwm-menu-desktop builds menus without mini\-icons. To enable mini\-icons use the following options. If ImageMagick is installed on the system, the script will resize and copy the icons to $FVWM_USERDIR/.icons. This can take awhile. You should be prepared to wait the first time you generate the icons. Once the icons have been generated the script should run faster. If it is still to slow using icons, see \fBEXAMPLES\fR for ways to limit how often the menu is generated to speed things up. .IP "\fB\-\-enable\-mini\-icons\fR" This option enables mini\-icons in the menus. If set, 24x24 mini-icons are used. If the specified icon isn't that size it will be converted if \fBImageMagick\fR is installed and saved in $HOME/.fvwm/icons or to the directory specified with \-\-mini\-icon\-dir option. Otherwise no icon appears in the menu for that entry. With most distributions, all the menu entries will have mini-icons appropriate to the application. .IP "\fB\-\-theme\fR \fINAME\fR" Defines the used icon theme. Default is \fIgnome\fR but all others found in /usr/share/icons could be used except the \fIhicolor\fR theme because it's the default fallback theme if no icon is found. .IP "\fB\-\-size\fR|\fB\-s\fR \fINUM\fR" If \-\-enable\-mini\-icons is used the \fIsize\fR of the icons can changed with this parameter. Default is 24. .IP "\fB\-\-mini\-icon\-dir\fR \fIDIR\fR" When the right size mini-icon isn't available, fvwm-menu-desktop creates icons with the right size in $HOME/.fvwm/icons. If you don't want to use the default directory, $HOME/.fvwm/icons, use this option to specify a different folder. .IP "\fB\-\-app\-icon\fR \fINAME\fR" Sets the default application icon if no others are found. Default is \&'gnome-applications'. .IP "\fB\-\-dir\-icon\fR \fINAME\fR" Sets the default directory icon if no others are found. Default is \&'gnome-fs-directory'. .SH USAGE \fBfvwm-menu-desktop\fR outputs XDG .menu files in the syntax of fvwm menus. When \fBfvwm-menu-desktop\fR is run with no options, it will load defaults from the \fBFvwmForm-XDGMenu-Config\fR file (see below) then search your system for suitable menu file(s). To see which menus are available on your system run: .RS .EX fvwm-menu-desktop --get-menus all .EE .RE If no menus are found you may not have any installed on your system. By default menus are stored as *.menu files in /etc/xdg/menus, $HOME/.config/menus or the location set in $XDG_MENU_PREFIX. You can use \fB\-\-install\-prefix\fR to specify another location search for menus. Though a combination of command line options and the \fBFvwmForm-XDGMenu-Config\fR settings, \fBfvwm-menu-desktop\fR can generate any combination of the menus found. To get a list of what menu(s) would be generated use the \fB--get-menus\fR \fIdesktop\fR option. The following will list all menus generated if \fBfvwm-menu-desktop\fR was run with no options. .RS .EX fvwm-menu-desktop --get-menus desktop .EE .RE \fBfvwm-menu-desktop\fR determines which menu(s) to generate as follows .RS If no config file is found, all menus will be weighted and the script will generate the best (highest weight) menu found. If a config file is found (and override options are not used) the script will generate all menus selected in \fBFvwmForm-XDGMenu-Config\fR. \fB--desktop\fR, \fB--menu-type\fR, \fB--set-menus\fR and \fB--all-menus\fR will override any menus selected in \fBFvwmForm-XDGMenu-Config\fR. \fB--desktop\fR and \fB--menu-type\fR will only include menus whose name matches '*desktop*menutype*'. If used with \fB--all-menus\fR, all matching menus are generated. If used without \fB--all-menus\fR, only the highest weighted menu is generated. \fB--set-menus\fR generates menus from the list of full path menu file names. \fB--all-menus\fR by itself will generate all menus found. .RE By default \fBfvwm-menu-desktop\fR will generate a menu whose top level name is "XDGMenu". To tell fvwm to read the output of \fBfvwm-menu-desktop\fR to create the menu XDGMenu add the following to your fvwm config file: .RS .EX PipeRead 'fvwm-menu-desktop' .EE .RE \fBWarning:\fR Depending on the options used this command may be slow and fvwm will pause until this command is complete. See \fBEXAMPLES\fR below for more details and possible workarounds. Once the menu is generated you can open the menu by using the command "Menu XDGMenu". You can also include this in the MenuFvwmRoot menu by: .RS .EX AddToMenu MenuFvwmRoot "XDG Menu" Popup XDGMenu .EE .RE \fBfvwm-menu-desktop\fR can be configured though both command line options and a \fBFvwmForm\fR GUI to customize the menu(s) that get generated. .SH GUI \fBFvwmForm-XDGMenu-Config\fR is a \fBFvwmForm\fR interface that can be used to configure the defaults for \fBfvwm-menu-desktop\fR. You can access this from the "Configure" item in the top level menu that is generated or run the following from within \fBFvwmConsole\fR .RS .EX Module FvwmPerl -l fvwm-menu-desktop-config.fpl .EE .RE This form can be used to select which menu(s) get generated by default along with setting many (but not all) of the available options. When you click "Save Settings" the form will write a config file located at $FVWM_USERDIR/.FvwmForm-XDGMenu-Config that \fBfvwm-menu-desktop\fR will parse for defaults when run. See the help inside of \fBFvwmForm-XDGMenu-Config\fR for more information. .SH EXAMPLES There are many ways to setup when fvwm runs \fBfvwm-menu-desktop\fR to generate the menu. One method is to just generate the menu when fvwm loads and then use the GUI config tool to change any options. To do this you only need to add the following to the fvwm config file: .RS .EX AddToMenu MenuFvwmRoot "XDG Menu" Popup XDGMenu PipeRead 'fvwm-menu-desktop' .EE .RE The menu is created once when fvwm loads. Since menu creation can sometimes be slow, this could cause fvwm to take longer to load than one wants. The menu is only generated when fvwm starts. If software is installed or removed you will have to select the 'Regenerate' option to rebuild the menu. One way to speed things up is to save the menu in a file and only generate the menu when 'Regenerate' is selected. To do this use \fB--regen-cmd\fR to call a custom function and write the menu to a file using a command like .RS .EX fvwm-menu-desktop --regen-cmd XDGRegen > $FVWM_USERDIR/.XDGMenu .EE .RE Then add the following to the fvwm config file to define the function XDGRegen. The second to last line will generate the menu if the menu file doesn't exist when fvwm starts. .RS .EX DestroyFunc XDGRegen AddToFunc XDGRegen + I PipeRead 'fvwm-menu-desktop --regen-cmd XDGRegen > \\ $[FVWM_USERDIR]/.XDGMenu; echo "Nop"' + I Read $[FVWM_USERDIR]/.XDGMenu Test (!f $[FVWM_USERDIR]/.XDGMenu) XDGRegen Read $[FVWM_USERDIR]/.XDGMenu .EE .RE Besides creating a top level menu, \fBfvwm-menu-desktop\fR can insert the menu into an existing menu using the \fB--insert-in-menu\fR option. For example one could create the menu MenuFvwmRoot and include the XDG items at the end. .RS .EX DestroyMenu MenuFvwmRoot AddToMenu MenuFvwmRoot "Fvwm" Title + "Item1" Action1 ... + "ItemN" ActionN + "" Nop PipeRead 'fvwm-menu-desktop --insert-in-menu MenuFvwmRoot' .EE .RE In this case the menu items are inserted at the end of the MenuFvwmRoot menu. If no items are in the menu, this menu becomes MenuFvwmRoot. The problem here is, that you have to restart fvwm or rebuild the whole menu to Regenerate it because menu items cannot be removed. To do this you could use a function like .RS .EX DestroyFunc XDGRegen AddToFunc XDGRegen + I DestroyMenu MenuFvwmRoot + I AddToMenu MenuFvwmRoot "Fvwm" Title + I AddToMenu MenuFvwmRoot "Item1" Action1 ... + I AddToMenu MenuFvwmRoot "ItemN" ActionN + I AddToMenu MenuFvwmRoot "" Nop + I PipeRead 'fvwm-menu-desktop --insert-in-menu MenuFvwmRoot \\ --regen-cmd XDGRegen' .EE .RE Fvwm can also create menus dynamically by using \fBDynamicPopUpAction\fR and/or \fBDynamicPopDownAction\fR. These commands when used with a Menu will run a Function when the menu is opened. For example one could create the menu XDGMenu when it is opened using .RS .EX AddToMenu XDGMenu "XDGMenu" Title + DynamicPopUpAction PipeRead 'fvwm-menu-desktop' .EE .RE This will create the menu when it is opened. One issue here is it will only create the menu the first time it is opened, and you still have to Regenerate the menu to see any changes. To create the menu each time it is open used the \fB--dynamic\fR option .RS .EX AddToMenu XDGMenu "XDGMenu" Title + DynamicPopUpAction PipeRead 'fvwm-menu-desktop \\ --dynamic --include-items config' + DynamicPopDownAction DestroyMenu recreate XDGMenu .EE .RE This will now Destroy the menu when it closed so it can be rebuilt the next time it is opened. The recreate flag doesn't completely destroy the menu keeping the DynamicPopUpAction and DynamicPopDownAction actions. The \fB--dynamic\fR flag includes the recreate option in the generated menus. To insert a menu into MenuFvwmRoot and still be dynamic you need to use a function that generates the whole menu. For example .RS .EX DestroyFunc GenRootMenu AddToFunc GenRootMenu + I DestroyMenu recreate MenuFvwmRoot + I AddToMenu MenuFvwmRoot "Fvwm" Title + I AddToMenu MenuFvwmRoot "Item1" Action1 ... + I AddToMenu MenuFvwmRoot "ItemN" ActionN + I AddToMenu MenuFvwmRoot "" Nop + PipeRead `fvwm-menu-desktop --insert-in-menu MenuFvwmRoot \\ --include-items config` AddToMenu MenuFvwmRoot "Fvwm" Title + DynamicPopUpAction GenRootMenu + DynamicPopDownAction DestroyMenu recreate MenuFvwmRoot .EE .RE .SH BUGS The whole process of creating menus from files is slow. Otherwise report bugs to the fvwm-workers mailing list <fvwm-workers@fvwm.org>. .SH AUTHORS This script is based on fvwm-xdg-menu.py written by Piotr Zielinski (http://www.cl.cam.ac.uk/~pz215/) who assigned Licence: GPL 2 Date: 03.12.2005. The script was reworked to replace the existing fvwm-menu-desktop perl script by the fvwm-workers. .SH COPYING The script is distributed by the same terms as fvwm itself. See GNU General Public License for details. ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/bin/fvwm-menu-xlock.1��������������������������������������������������������������������0000644�0001750�0001750�00000017116�14147024700�013316� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" Automatically generated by Pod::Man 2.16 (Pod::Simple 3.02) .\" .\" Standard preamble: .\" ======================================================================== .de Sh \" Subsection heading .br .if t .Sp .ne 5 .PP \fB\\$1\fR .PP .. .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .ie \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .el \{\ . de IX .. .\} .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "fvwm-menu-xlock 1" .TH fvwm-menu-xlock 1 "2009-03-22" "2.5.28 (from cvs)" "Fvwm Utilities" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" fvwm\-menu\-xlock \- builds xlock menu definition for fvwm .SH "SYNOPSIS" .IX Header "SYNOPSIS" \&\fBfvwm-menu-xlock\fR [ \fB\-\-help\fR|\fB\-h\fR|\fB\-?\fR ] [ \fB\-\-version\fR|\fB\-V\fR ] [ \fB\-\-name\fR|\fB\-n\fR name ] [ \fB\-\-title\fR|\fB\-t\fR title ] [ \fB\-\-item\fR format ] [ \fB\-\-icon\-title\fR icon ] [ \fB\-\-icon\-item\fR icon ] [ \fB\-\-special\-first\fR|\fB\-s\fR ] [ \*(-- xlock params ] .SH "DESCRIPTION" .IX Header "DESCRIPTION" A simple perl script which parses xlock's output to build an fvwm menu definition of all xlock's modes. .SH "OPTIONS" .IX Header "OPTIONS" .IP "\fB\-\-help\fR" 4 .IX Item "--help" show the help and exit .IP "\fB\-\-version\fR" 4 .IX Item "--version" show the version and exit .IP "\fB\-\-name\fR name" 4 .IX Item "--name name" define menu name in the following argument. Default is \*(L"XLockMenu\*(R" .IP "\fB\-\-title\fR title" 4 .IX Item "--title title" define menu title in the following argument. Default is \*(L"XLock Modes\*(R". .IP "\fB\-\-item\fR format" 4 .IX Item "--item format" define menu item format in the following argument, default is '%n\et(%d)'. \s-1TAB\s0 can be specified as '\et', but in .fvwm2rc you should specify a double backslash or a real \s-1TAB\s0. .Sp Format specifiers: .Sp .Vb 3 \& %n \- mode name \& %d \- mode description \& %D \- mode description without "Shows " prefix if any .Ve .Sp These specifiers can receive an optional integer size, positive for right adjusted string or negative for left adjusted, example: \f(CW%8x\fR; and optional *num or *\-num, which means to leave only the first or last (if minus) num of chars, the num must be greater than 3, since the striped part is replaced with \*(L"...\*(R", example: %*30x. Both can be combined: %\-10*\-20x, this instructs to get only the 20 last characters, but if the length is less then 10 \- to fill with up to 10 spaces on the right. .IP "\fB\-\-icon\-title\fR icon" 4 .IX Item "--icon-title icon" .PD 0 .IP "\fB\-\-icon\-item\fR icon" 4 .IX Item "--icon-item icon" .PD define menu icon for title and regular item accordingly. Default is no menu icons (equivalent to an empty icon argument). .IP "\fB\-\-wm\-icons\fR" 4 .IX Item "--wm-icons" define icon names suitable for use with wm-icons package. Currently this is equivalent to: \-\-icon\-title '' \-\-icon\-item menu/lock.xpm. .IP "\fB\-\-special\-first\fR" 4 .IX Item "--special-first" instructs to include special modes (usually black, bomb and random) first. .PP Option parameters can be specified either using '=' or in the next argument. Short options are ok if not ambiguous: \-h, \-t; but be careful with short options, what is now unambiguous, can became ambiguous in the next versions. .PP Additional arguments (after \fB\-\-\fR) will be passed to xlock. .PP Please see the \fBxlock\fR(1) man page for the xlock options. .SH "USAGE" .IX Header "USAGE" Add these lines to your fvwm configuration file: .PP .Vb 6 \& PipeRead \*(Aqfvwm\-menu\-xlock \-\-name MenuSSaver \-\-title "Screensaver" \e \& \-\-icon\-item mini\-bball.xpm \-\-special\-first \-\- \-nice 19 \-nolock\*(Aq \& PipeRead \*(Aqfvwm\-menu\-xlock \-\-name MenuSLock \-\-title "Lock Screen" \e \& \-\-icon\-item mini\-rball.xpm \-\-special\-first \-\- \-nice 19\*(Aq \& AddToMenu "Utilities" "Screensaver%mini\-monitor.xpm%" Popup MenuSSaver \& AddToMenu "Utilities" "Screenlock%mini\-lock.xpm%" Popup MenuSLock .Ve .SH "AUTHORS" .IX Header "AUTHORS" Charles K. Hines <chuck_hines@vnet.ibm.com>, initial version. .PP Mikhael Goikhman <migo@homemail.com>, from 24 Feb 1999. .SH "COPYING" .IX Header "COPYING" The script is distributed by the same terms as fvwm itself. See \s-1GNU\s0 General Public License for details. .SH "BUGS" .IX Header "BUGS" Depends on the output of xlock. Will produce an empty menu if the structure of the output is changed. .PP Report bugs to fvwm\-bug@fvwm.org. ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/bin/fvwm-perllib.in����������������������������������������������������������������������0000644�0001750�0001750�00000036762�14147024700�013143� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!@PERL@ # Copyright (c) 2002-2009 Mikhael Goikhman # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see: <http://www.gnu.org/licenses/> # Filter this script to pod2man to get a man page: # pod2man -c "Fvwm Utilities" fvwm-perllib | nroff -man | less -e #use strict; # comment to make it faster BEGIN { # use vars qw($prefix $datarootdir $datadir $perllibdir); $prefix = "@prefix@"; $datarootdir = "@datarootdir@"; $datadir = "@datadir@"; $perllibdir = "@FVWM_PERLLIBDIR@"; # try to do it as fast as possible if ($ARGV[0] eq 'dir') { print $perllibdir; exit(0); } } use Getopt::Long; use lib $perllibdir; use General::FileSystem '-die'; my $version = "@VERSION@"; my $version_info = "@VERSIONINFO@"; my $pager = $ENV{PAGER} || "less -e"; my $do_man = 0; my $do_cat = 0; my $do_raw = 0; GetOptions( "help|h|?" => \&show_help, "version|v|V" => \&show_version, "man" => \$do_man, "cat" => \$do_cat, "raw" => \$do_raw, "dir" => sub { print $perllibdir; exit(0); }, ) || wrong_usage(); if ($ARGV[0] eq 'man') { $do_man = 1; shift; } elsif ($ARGV[0] eq 'cat') { $do_cat = 1; shift; } elsif ($ARGV[0] eq 'raw') { $do_raw = 1; shift; } wrong_usage() if !$do_man && !$do_cat && !$do_raw || @ARGV > 1; my $man_or_cat_str = $do_man || $do_raw ? "man" : "cat"; my $internal_pods = {}; $internal_pods->{index} = qq{ :head1 NAME index - lists all available help topics :head1 DESCRIPTION Recent I<fvwm> versions install the Perl library that makes creating fvwm modules in Perl possible and easy. You may read the Perl library documentation locally by running: % fvwm-perllib $man_or_cat_str <topic> Available topics: index tutorial events {{CLASS_NAMES}} For example: % fvwm-perllib $man_or_cat_str FVWM::Module :head1 AUTHOR Mikhael Goikhman <migo\@homemail.com>. }; $internal_pods->{tutorial} = q{ :head1 NAME tutorial - common techniques for writting fvwm modules :head1 TUTORIAL :head2 What is a window manager A window manager is a program that runs on top of the X Window System and manages windows, menus, key and mouse bindings, virtual desktops and pages, draws window decorations using defined colors or images, title-bar buttons and fonts. The window manager defines window placement and focus policies. It may also manage such things as root background, mouse cursors, sounds, run applications and do other nice things. :head2 What is a module In the unix traditions, different functionality may be implemented by separate programs to reduce a bloat. A module is an optional program that is intended to extend the window manager using a defined module protocol. Fvwm modules are spawned by the main I<fvwm> executable. They usually listen to the window manager events, do some useful work and send back commands for execution. There are transient modules that exit immediately or shortly, and persistent modules that exit together with a window manager or when a user requests. Some modules may control windows or other modules. Some modules may supply a GUI, others may be non interactive. :head2 Creating a simple module Let's create a module that shows a flash window for one second when you change pages. We will use I<xmessage> with nifty options for our flash purposes, but you may use your fantasy to do this better. First, we should understand when our module works. Usually a module does nothing (sleeps) and is awaken when something interesting happens. This is achieved using events. A module defines events that it is interesting to receive and set-ups event handlers (perl functions) to be called when the event happens. Then a module enters the event loop where it sleeps all the time until one or another event happens. Most of the module work is done in the event handlers. When an event is processed, the module enters the event loop again. In our case, we should listen to an fvwm event I<M_NEW_PAGE>. The list of all events may be found in man page "events". When we receive the event we want to get new page coordinates and display them using our special xmessage window. Now, from theory to practice. The header of all modules written in Perl is pretty standard: #!/usr/bin/perl -w use lib `fvwm-perllib dir`; use FVWM::Module; Then create the actual module object: my $module = new FVWM::Module( Mask => M_NEW_PAGE | M_NEW_DESK, Debug => 1, ); The B<Debug> option tells to print the event names that a module receives to help writing a module, it also echoes all sent commands. The B<Mask> option tells which events a module wants to receive, in our case these are events generated on the page and desk changes. To handle events, event handlers that are perl functions, should be defined. It is ok not to define any event handler for I<M_NEW_DESK> and to define two event handlers for I<M_NEW_PAGE>. But for our purposes one I<M_NEW_PAGE> would be more than enough: $module->add_handler(M_NEW_PAGE, \&got_new_page); It is a time to implement our C<got_new_page> function that will be called every time the desktop page is changed. sub got_new_page { my ($module, $event) = @_; my $width = $event->_vp_width; my $height = $event->_vp_height; if (!$width || !$height) { # this may happen when doing DeskTopSize 1x1 on page 2 2 return; } my $page_nx = int($event->_vp_x / $width); my $page_ny = int($event->_vp_y / $height); # actually show the flash $module->send("Exec xmessage -name FlashWindow \ -bg cyan -fg white -center -timeout 1 -button '' \ -xrm '*cursorName: none' -xrm '*borderWidth: 2' \ -xrm '*borderColor: yellow' -xrm '*Margin: 12' \ '($page_nx, $page_ny)'"); } All event handlers are called with 2 parameters, a module and an event objects. The arguments for all events are defined in L<FVWM::EventNames>. Each event type has its own arguments. Our I<M_NEW_PAGE> has 5 arguments: vp_x vp_y desk vp_width vp_height. We should do some calculations to get the page numbers from viewport coordinates. The B<send> method passes the command to I<fvwm> for execution. It would be better to set-up the FlashWindow specially: $module->send("Style FlashWindow StaysOnTop, NoTitle, NoHandles, \ BorderWidth 10, WindowListSkip, NeverFocus, UsePPosition"); Finally, all persistent modules should enter the event loop: $module->event_loop; The full module source that we just wrote is available at ftp://ftp.fvwm.org/pub/fvwm/devel/sources/tests/perl/module-flash . To run it execute this fvwm command: Module /path/to/module-flash To kill the module, execute: KillModule /path/to/module-flash :head2 Using event trackers In fact, the task of calculating page coordinates, or managing information about all windows, or gathering colorset, module or global information is so often, that there are existing implentation in the form of event trackers. Tracker is an instance of L<FVWM::Tracker> superclass. Currently these tracker classes are available (see their man pages): FVWM::Tracker::Colorsets FVWM::Tracker::GlobalConfig FVWM::Tracker::ModuleConfig FVWM::Tracker::PageInfo FVWM::Tracker::Scheduler FVWM::Tracker::WindowList Using a tracker is easy, something along lines: my $tracker = $module->track("WindowList"); my $colorset_tracker = $module->track("Colorsets"); Our module that we wrote above may be reduced if we use: my $viewport = $module->track("PageInfo"); my $page_nx = $viewport->data("page_nx"); my $page_ny = $viewport->data("page_ny"); Note that the tracker continues to work and maintain the up-to-date information about the current page and desk (or up-to-date windows or colorsets depending on the tracker type) at any given moment. Internally, trackers listen to appropriate events using the same event handler mechanism, so there is no speed advantage. However it is a good idea to reuse the existing verified code and reduce the number of events needed to be trapped manually. There is usually no problem if the developer and the tracker define handlers for the same events (besides the handler order maybe). :head2 On the module masks In our example above we explicitly defined Mask in constructor. This is not really needed. If not specified, the event mask is managed automatically (it is updated every time a new event handler is added). Note, there are actually two event masks, called "mask" and "xmask" (extended mask). If you are interested in the details, refer to the fvwm documentation or perllib sources. When trackers are added or removed, the module mask (and xmask) are automatically tweaked underhand. In short, there is often no reason to worry about the module masks. However, in rare cases you may want to define SyncMask (or SyncXMask), so that fvwm is synchronized with the module on certain events. :head2 Creating a more functional module Let's extend our new-page-flash example above and add a way to stop our module and to define another string format. This would be possible using the following I<fvwm> commands: SendToModule /path/to/module-flash stop SendToModule /path/to/module-flash format '[%d %d]' To handle such commands, we should define I<M_STRING> event handler. use General::Parse; my $format = "(%d, %d)"; # the default format $module->mask($module->mask | M_STRING); $module->add_handler(M_STRING, sub { my ($module, $event) = @_; my $line = $event->_text; my ($action, @args) = get_tokens($line); if ($action eq "stop") { $module->terminate; } elsif ($action eq "format") { $format = $args[0]; } }); :head1 EXAMPLES Currently see I<ftp://ftp.fvwm.org/pub/fvwm/devel/sources/tests/perl/> for examples. Learning the sources of B<FvwmPerl>, B<FvwmDebug> modules may help too. :head1 SEE ALSO See L<FVWM::Module> for the module API. :head1 AUTHOR Mikhael Goikhman <migo@homemail.com>. }; $internal_pods->{events} = q{ :head1 NAME events - list of all fvwm events with arguments :head1 DESCRIPTION This list is automatically generated from L<FVWM::EventNames> package. Given L<FVWM::Event> object of certain event type, say I<M_STRING>, here is the syntax to get value of its I<win_id> argument: $win_id = $event->_win_id; There are several more ways to access arguments, like: $win_id = $event->arg_values->[0]; $text = $event->args->{text}; :head1 EVENTS WITH ARGUMENTS {{EVENT_NAMES}} :head1 ARGUMENT TYPE LEGEND Here is a mapping of fvwm argument types to perl native types: number - integer bool - boolean, true or false window - X window id in decimal, use sprintf("0x%07x", $wid) pixel - "rgb:" . join('/', sprintf("%06lx", $val) =~ /(..)(..)(..)/) string - string (scalar) wflags - window flags in binary string looped - loop of zero or more fixed argument bunches Run L<FvwmDebug> to browse events. :head1 SEE ALSO See "tutorial", L<FVWM::Event>, L<FVWM::EventNames> and L<FvwmDebug>. :head1 AUTHOR Mikhael Goikhman <migo@homemail.com>. }; my $topic = $ARGV[0] || "index"; my $file = "-"; my $text = ""; if (exists $internal_pods->{$topic}) { $text = $internal_pods->{$topic}; $text =~ s/^\t//mg; $text =~ s/^:/=/mg; if ($topic eq 'index') { my @class_names = sort @{list_filenames($perllibdir, 1)}; @class_names = map { s!\.pm$!!; s!/!::!g; $_ } @class_names; $text =~ s/\{\{CLASS_NAMES\}\}/join("\n ", @class_names)/seg; } if ($topic eq 'events') { my $content = `cat '$perllibdir/FVWM/EventNames.pm'`; my $result = ""; foreach ($content =~ /\t&([^\s]+.*?\t\tfields[^\n]+(?:\n\t\t\t[^\n]+)*)/sg) { my ($name, $rest) = /^([^\s]+).*?((?:\n\t\t\t[^\n]+)*)$/s; # ] $result .= " $name\n"; $rest =~ s/([^\s]+)\s*=>\s*([\w]+)/ $result .= sprintf(" %-16s\t%s\n", $1, $2) /eg; $result .= "\n"; } $text =~ s!\{\{EVENT_NAMES\}\}!$result!se; } } else { $file = "$perllibdir/$topic.pm"; $file =~ s!::!/!g; die "No $file found.\n" unless -f $file; } my $man_converter = $do_man ? " | nroff -man | $pager" : ""; open(MANPIPE, $do_cat ? "| pod2text '$file' | $pager" : "| pod2man --section 3 --release 'fvwm $version$version_info'" . " --center 'Fvwm Perl library' --name '$topic' '$file'" . " | @SED@ 's/<STANDARD INPUT>/perllib/ig'$man_converter") or die "Can't open pipe to pod/man viewer\n"; print MANPIPE $text or die "Can't write to pod/man viewer\n"; close MANPIPE; # --------------------------------------------------------------------------- sub show_help { print "Shows documentation of the supplied FVWM Perl library.\n\n"; print "Usage: fvwm-perllib man|cat\n"; print "\tAn introduction to the FVWM Perl library\n\n"; print "Usage: fvwm-perllib man|cat|raw <Perl::Class>\n"; print "\tManual page for <Perl::Class>, try: man FVWM::Module\n"; print "\t\$PAGER is used for a pager, the default is '$pager'\n\n"; print "Usage: fvwm-perllib dir\n"; print "\tFor use in fvwm modules written in Perl\n\n"; print "Usage: fvwm-perllib [OPTIONS]\n"; print "Options:\n"; print "\t--help show this help and exit\n"; print "\t--version show the version and exit\n"; exit 0; } sub show_version { print "$version\n"; exit 0; } sub wrong_usage { print STDERR "Try '$0 --help' for more information.\n"; exit -1; } __END__ # --------------------------------------------------------------------------- =head1 NAME fvwm-perllib - shows the documentation of the Fvwm Perl library =head1 SYNOPSIS B<fvwm-perllib> [ B<--help>|B<-h>|B<-?> ] [ B<--version>|B<-v>|B<-V> ] [ B<man> [ I<Perl::Class> ] ] [ B<cat> [ I<Perl::Class> ] ] [ B<raw> [ I<Perl::Class> ] ] [ B<dir> ] =head1 DESCRIPTION Starting from fvwm-2.5.x versions there is a built-in support for creating fvwm modules in Perl. This B<fvwm-perllib> utility provides help services for the Fvwm Perl library. =head1 OPTIONS B<--help> show the help and exit B<--version> show the version and exit B<--man> or B<man> [ I<Perl::Class> ] show manual page just like man(1) B<--cat> or B<cat> [ I<Perl::Class> ] show manual page in plain text B<--raw> or B<raw> [ I<Perl::Class> ] generate output in man format (not human readable) B<--dir> or B<dir> print perllib directory without a trailing end of line =head1 USAGE Use this in the fvwm modules written in Perl: use lib `fvwm-perllib dir`; Introduction to the Fvwm Perl library: % fvwm-perllib man Manual page for the C<FVWM::Module> class: % fvwm-perllib man FVWM::Module Standard options: % fvwm-perllib --help % fvwm-perllib --version =head1 AUTHORS Mikhael Goikhman <migo@homemail.com>. =head1 COPYING The script is distributed by the same terms as fvwm itself. See GNU General Public License for details. =head1 BUGS No known bugs. Report bugs to fvwm-bug@fvwm.org. =cut # *************************************************************************** ��������������fvwm-2.7.0/bin/fvwm-convert-2.6.in������������������������������������������������������������������0000644�0001750�0001750�00000034110�14147024700�013456� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!@PERL@ # -*-perl-*- # Convert .fvwm2rc from 2.4.x format to 2.6.x format. # # Original author: Thomas Adam <thomas.adam22@gmail.com> Dec. 2009 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see: <http://www.gnu.org/licenses/> use strict; use Cwd; use File::Basename; use Getopt::Long; # Global array for all our converted lines. my @converted_lines = (); # Global softref for addtofunc continuations. my $last_func_ref; my %converted_funcs = (); # Global for additional files... my @additional_files = (); # GetOpts my $follow_read = ''; my $process_read = 0; # Convert conditional command syntax correctly. sub __convert_conditionals { my( $cond ) = @_; my( $line ) = $cond->[-1]; my $condition_cmds = qr/(all|current|direction|next|none|prev|pick|thiswindow|windowid)/; # Take the last component. We no longer care for "[*]" as conditional # command parameters. But we shouldn't really put another conditional # in its place, so we'll just remove it. $line =~ s/\[\*\]//; # And convert over Next [$1] syntax. $line =~ s/$condition_cmds\s*\[(.*?)\]/\($1\)/io; $line = "$1 ". join( ', ', split( /[^,](\s+)[^,]/, $2 ) ) . " $3" if $line =~ /$condition_cmds\s*(\(.*?\))(.*)/io; $cond->[-1] = $line; } # Process the files specified and output them to a destination file. sub process_files { my( $files ) = @_; no strict "refs"; foreach my $f ( @$files ) { my( $s, $d ) = @$f; my $cwd_path = getcwd(); warn "Following: Read $s...\n" if $process_read; if( !defined $d or $d eq '' ) { my $fbasename = basename( $s ); $d = "$cwd_path/$fbasename.converted"; } if( -e $d ) { die "Destination file: $d exists\n"; } open( my $in_file, '<', $s ) or die "Unable to open source file: $!\n"; while( <$in_file> ) { chomp; # We have to handle continuation lines here, such as: # # Style foo !Bar, !Baz, \ # NoSomethingElse if( /\\\s*$/ ) { $_ .= <$in_file>; redo; } dispatch_line($_); } write_out_file($d); @converted_lines = (); %converted_funcs = (); } } # Convert style syntax over where applicable. sub convert_styles { my( $line ) = @_; my @converted; # At the very least, we can cheat and just negate everything. Whilst it # isn't deprecated yet, it will be -- so it won't hurt to do it here. # Split the line out first of all, between the "Style foo" part, and the # actual styles being applied. my( @style_parts ) = ($line =~ /^(style\s+\"??[\w+*?]\"??)(.*)$/i); # Convert the second part over. foreach( split( /\s*,\s*/, $style_parts[1] ) ) { # There is no !PPosition style, but there is !UsePPosition s/(?:No)(.*)/\!$1/ unless /nopposition/i; s/nopposition/!UsePPosition/i; push @converted, $_; } push @converted_lines, $style_parts[0] . join(', ', @converted); } # Buckshot approach at turning fvwmthemes into colorsets. Can't really do # much more than this, but at least gives the user something to go on. sub convert_fvwmtheme { my( $line ) = @_; $line =~ s/^\*fvwmtheme\s*:?//i; $line = undef if $line =~ /modulesynchronous.*?fvwmtheme/i; push @converted_lines, $line; } # Comment out the modulepath line -- grr. sub handle_modulepath { my( $line ) = @_; push( @converted_lines, "# Commented out by fvwm-convert-2.6: $line" ); } # This should have happened in the fvwm-2.4 convert script, but handle it # here anyway. sub convert_windowshadesteps { my( $line ) = @_; $line =~ /(\d+)p?/ ? $line = "Style * WindowShadeSteps $1" : $line = "Style * " . $line; push( @converted_lines, $line ); } sub convert_edge_resistance { my( $line ) = @_; # This gets converted into two parts. One is the EdgeResistance # command, the other is a style line. # # We could only ever have had two numbers as arguments to # EdgeResistance. my( $edge_res_arg, $move_res_arg ) = ( $line =~ /edgeresistance\s*(\d+)\s*(\d+)/i ); push( @converted_lines, qq| EdgeResistance $edge_res_arg Style * EdgeMoveResistance $move_res_arg| ); } sub convert_snapattraction { my( $line ) = @_; push( @converted_lines, "Style * " . $line ); } sub convert_key_mouse_bindings { my( $line ) = @_; my @components = split( /(\s+)/, $line, 5 ); # Also, conditional commands should now be separated with commas and not # whitespace, so try and fix these up where we can. It's not the # intention we'll catch them all, but at least try and do so based on # where they're likely to be used. __convert_conditionals(\@components); push( @converted_lines, join '', @components ); } sub handle_continuation { no strict "refs"; # Yes, yes... my( $line ) = @_; if( !defined $last_func_ref || $last_func_ref eq '' ) { my @func_parts = split( /(\+\s*\"?(?:i|c|d|h|m)\"?\s*)/i, $line, 2 ); __convert_conditionals(\@func_parts); push( @converted_lines, join '', @func_parts ); return; } eval { &{$last_func_ref}($line) }; warn "$@\n" if $@; } sub handle_read_file { my( $line ) = @_; my @read_parts = split( /\s+/, $line ); push( @converted_lines, $line ); # Crudely try and work out if the file is readable, and if it is add it # to the list of further files to convert. # # This won't handle having to interpolate out any env vars set via # SetEnv, or worse yet, outside of FVWM's environment. The user will # just have to run this script on that file manually. my $fname = $read_parts[1]; return unless defined $fname and $fname ne ''; if( -e $fname ) { push( @additional_files, [$fname] ); # We're done. return; } # If we have this: # # Read foo # # Or this: # # Read $./foo # # Then we assume FVWM_USERDIR ("$HOME/.fvwm/"), and if that file can't # be found there, try CWD, and if that fails we just give up. # Canonicalise the starting point by removing "$." -- we can guess what # it ought to be replaced with. $fname =~ s/^\$\.\/?//; if( -e "$ENV{FVWM_USERDIR}/$fname" ) { push( @additional_files, ["$ENV{FVWM_USERDIR}/$fname"] ); return; } if( -e "$ENV{HOME}/.fvwm/$fname" ) { push( @additional_files, ["$ENV{HOME}/.fvwm/$fname"] ); return; } my $cwd_path = getcwd(); if( -e "$cwd_path/$fname" ) { push( @additional_files, [$fname] ); return; } warn "Unable to follow: $line\n"; } sub check_func_definition { my( $line ) = @_; if( $line !~ /^addtofunc\s+(?:start|init|restart)function.*/i ) { $last_func_ref = ''; } # Then we have a standard function line in the form: # # + I SomeCommand # # Ensure we run it all through __convert_conditionals() my @func_parts = split( /(\s+)/, $line, 4 ); __convert_conditionals( \@func_parts ); push( @converted_lines, join '', @func_parts ); } sub convert_initfunc { my( $line ) = @_; $last_func_ref = "convert_initfunc"; if( $line =~ /addtofunc\s+initfunction\s+\"??[icmhd]{1}\"??\s+.*/i || $line =~ /addtofunc\s+initfunction\s*/i ) { $line =~ s/addtofunc\s+initfunction\s*//i; } $line =~ s/^\s*\+//; return if !defined $line || $line eq ''; # What we need to do now is convert this from: # # + I Foo # # to: # # + I Test (Init) Foo my @func_cmd = split( /\s+/, $line, 3 ); unshift( @func_cmd, '' ) unless @func_cmd > 2; # Remove any quotes around the action type --- they're not needed # anymore. $func_cmd[1] =~ s/\"//g; $func_cmd[1] .= q| Test (Init) |; # Run the command through the conditional function to ensure we # handle those correctly. __convert_conditionals( \@func_cmd ); push( @{ $converted_funcs{initfunction} }, join ' ', @func_cmd ); } sub convert_restartfunc { my( $line ) = @_; $last_func_ref = "convert_restartfunc"; # We treat this exactly like startfunction. if( $line =~ /addtofunc\s+restartfunction\s+\"??[icmhd]{1}\"??\s+.*/i ) { # Split this string. We can throw away the "AddToFunc" part as this # is irrelevant. But we want the following result: # ( 'I', 'Some Command' ) $line =~ s/addtofunc\s+restartfunction\s*//i; } $line =~ s/addtofunc\s+restartfunction\s*//i; return if $line eq ''; # Remove the continuation prefix as we can add this in when writing out # the function definitions later. $line =~ s/^\s*\+//; my @func_cmd = split( /\s+/, $line, 2 ); $func_cmd[1] =~ s/\"//g; # Run the command through the conditional function to ensure we # handle those correctly. __convert_conditionals( \@func_cmd ); push( @{ $converted_funcs{startfunction} }, join ' ', @func_cmd ); } sub convert_startfunc { my( $line ) = @_; $last_func_ref = "convert_startfunc"; # Now, it's possible that we have something like this: # # AddToFunc StartFunction I Some Command # # Extract the command part, add it to the hash for our functions, and # flag the fact we're dealing with StartFunction at this point for any # continuation lines (+ I Foo) since we can't determine the context of # them without such a thing. if( $line =~ /addtofunc\s+startfunction\s+\"??[icmhd]{1}\"??\s+.*/i ) { # Split this string. We can throw away the "AddToFunc" part as this # is irrelevant. But we want the following result: # ( 'I', 'Some Command' ) $line =~ s/addtofunc\s+startfunction\s*//i; } $line =~ s/addtofunc\s+startfunction\s*//i; # Remove the continuation prefix as we can add this in when writing out # the function definitions later. $line =~ s/^\s*\+//; return if !defined $line || $line eq ''; my @func_cmd = split( /\s+/, $line, 2 ); $func_cmd[1] =~ s/\"//g; # Run the command through the conditional function to ensure we # handle those correctly. __convert_conditionals( \@func_cmd ); push( @{ $converted_funcs{startfunction} }, join ' ', @func_cmd ); } sub write_out_file { my( $dest_file ) = @_; open( my $f, '>', $dest_file ) or die "Couldn't open $dest_file: $!\n"; # If we had any continuation lines, preserve them as best we can. @converted_lines = map { join "\\\n", split /\\/, $_ } @converted_lines; print $f join( "\n", @converted_lines ); # Write out the functions. if( defined $converted_funcs{initfunction} or defined $converted_funcs{startfunction} ) { print $f qq|\n\nDestroyFunc StartFunction\nAddToFunc StartFunction\n|; # Put the Init stuff before anything else. for( @{ $converted_funcs{initfunction} }, @{ $converted_funcs{startfunction } } ) { print $f "+ $_\n"; } } close( $f ); } sub dispatch_line { my( $line ) = @_; if( $line =~ /^style/i ) { convert_styles($line); } elsif( $line =~ /^\s*\*fvwmtheme:??/i ) { convert_fvwmtheme($line); } elsif( $line =~ /^\s*modulepath\s*/i ) { handle_modulepath( $line ); } elsif( $line =~ /^\s*windowshadesteps.*/i ) { convert_windowshadesteps($line); } elsif( $line =~ /^\s*module(?:synchronous)?.*?fvwmtheme$/i ) { convert_fvwmtheme($line); } elsif( $line =~ /^\s*edgeresistance\s*\d+\s*\d+/i ) { convert_edge_resistance($line); } elsif( $line =~ /^\s*key|mouse/i ) { convert_key_mouse_bindings($line); } elsif( $line =~ /^\s*snap(?:attraction|grid)/i ) { convert_snapattraction( $line ); } elsif( $line =~ /^\s*addtofunc\s+initfunction/i ) { convert_initfunc( $line ); } elsif( $line =~ /^\s*addtofunc\s+startfunction.*/i ) { convert_startfunc( $line ); } elsif( $line =~ /^\s*addtofunc\s+restartfunction/i ) { convert_restartfunc( $line ); } elsif( $line =~ /^\s*addtofunc\s+\w+.*/i ) { check_func_definition( $line ); } elsif( $line =~ /^\s*\+\s*\"??[ichmd]{1}\s*\"??\s+.*/i ) { handle_continuation( $line ); } elsif( $line =~ /^\s*read\s*[\/\w]+/i ) { handle_read_file( $line ); } else { # Could be a comment, or a continuation, or simply something we # don't need to convert. As far as continuation lines are # concerned, these are kept in order just by pushing them onto the # array --- but converting continuation lines is tricky since we'd # need to determine the context of the continuation. I can't be # bothered. push( @converted_lines, $_ ); } } sub usage { print "fvwm-convert-2.6 [-f] [-h] source-file destination-file\n"; exit; } GetOptions( "help|h" => \&usage, "follow-read|f" => \$follow_read, ) || usage(); # But we still require @ARGV to be populated with our filenames. usage() unless( @ARGV > 0 and @ARGV <=2 ); my @files = [@ARGV]; process_files( \@files ); if( @additional_files && !$follow_read ) { print "The following files were detected, but not processed:\n\n", join("\n", @$_ ) for @additional_files; print "\n"; } # Only do this is we've been asked. if( @additional_files && $follow_read ) { $process_read = 1; process_files( \@additional_files ); } ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/bin/Makefile.in��������������������������������������������������������������������������0000644�0001750�0001750�00000077074�14324315775�012267� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 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@ bin_PROGRAMS = fvwm-root$(EXEEXT) subdir = bin ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.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 = fvwm-bug.1 fvwm-config.1 fvwm-convert-2.6.1 \ fvwm-menu-desktop.1 fvwm-root.1 fvwm-config fvwm-bug \ fvwm-perllib fvwm-menu-xlock fvwm-menu-directory \ fvwm-menu-desktop fvwm-menu-headlines fvwm-convert-2.6 CONFIG_CLEAN_VPATH_FILES = am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(configdir)" PROGRAMS = $(bin_PROGRAMS) fvwm_root_SOURCES = fvwm-root.c fvwm_root_OBJECTS = fvwm-root.$(OBJEXT) fvwm_root_LDADD = $(LDADD) am__DEPENDENCIES_1 = 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; }; \ } SCRIPTS = $(bin_SCRIPTS) 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)/etc/depcomp am__maybe_remake_depfiles = depfiles am__depfiles_remade = ./$(DEPDIR)/fvwm-root.Po am__mv = mv -f 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 = $(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 = fvwm-root.c DIST_SOURCES = fvwm-root.c am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac man1dir = $(mandir)/man1 NROFF = nroff MANS = $(man_MANS) DATA = $(config_DATA) 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)` am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/fvwm-bug.1.in \ $(srcdir)/fvwm-bug.in $(srcdir)/fvwm-config.1.in \ $(srcdir)/fvwm-config.in $(srcdir)/fvwm-convert-2.6.1.in \ $(srcdir)/fvwm-convert-2.6.in $(srcdir)/fvwm-menu-desktop.1.in \ $(srcdir)/fvwm-menu-desktop.in \ $(srcdir)/fvwm-menu-directory.in \ $(srcdir)/fvwm-menu-headlines.in $(srcdir)/fvwm-menu-xlock.in \ $(srcdir)/fvwm-perllib.in $(srcdir)/fvwm-root.1.in \ $(top_srcdir)/etc/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALL_DOMAINS = @ALL_DOMAINS@ ALL_LINGUAS = @ALL_LINGUAS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR_FLAGS = @AR_FLAGS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ Bidi_CFLAGS = @Bidi_CFLAGS@ Bidi_LIBS = @Bidi_LIBS@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DOC_COMMANDS = @DOC_COMMANDS@ DOC_COMMANDS_HTML = @DOC_COMMANDS_HTML@ DOC_COMMANDS_XML = @DOC_COMMANDS_XML@ DOC_COMMANDS_XML_PATH = @DOC_COMMANDS_XML_PATH@ DOC_MODULES = @DOC_MODULES@ DOC_MODULES_HTML = @DOC_MODULES_HTML@ DOC_SECTIONS = @DOC_SECTIONS@ DOC_SECTIONS_XML = @DOC_SECTIONS_XML@ DOC_SECTIONS_XML_PATH = @DOC_SECTIONS_XML_PATH@ DUMMYPOFILES = @DUMMYPOFILES@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FC_CFLAGS = @FC_CFLAGS@ FC_CONFIG = @FC_CONFIG@ FC_LIBS = @FC_LIBS@ FRIBIDI_CONFIG = @FRIBIDI_CONFIG@ FVWMALTFTP = @FVWMALTFTP@ FVWMALTFTPDIR = @FVWMALTFTPDIR@ FVWMFTP = @FVWMFTP@ FVWMFTPDIR = @FVWMFTPDIR@ FVWMHOMEPAGE = @FVWMHOMEPAGE@ FVWMLIST = @FVWMLIST@ FVWMNAMELONG = @FVWMNAMELONG@ FVWMSCRIPT_DOMAIN = @FVWMSCRIPT_DOMAIN@ FVWMTASKBAR_DOMAIN = @FVWMTASKBAR_DOMAIN@ FVWMWORKERSLIST = @FVWMWORKERSLIST@ FVWMWORKERSLISTLONG = @FVWMWORKERSLISTLONG@ FVWM_CONFDIR = @FVWM_CONFDIR@ FVWM_CPP = @FVWM_CPP@ FVWM_DATADIR = @FVWM_DATADIR@ FVWM_DOCDIR = @FVWM_DOCDIR@ FVWM_DOMAIN = @FVWM_DOMAIN@ FVWM_IMAGEPATH = @FVWM_IMAGEPATH@ FVWM_MODULEDIR = @FVWM_MODULEDIR@ FVWM_PERLLIB = @FVWM_PERLLIB@ FVWM_PERLLIBDIR = @FVWM_PERLLIBDIR@ GDK_IMLIB_CFLAGS = @GDK_IMLIB_CFLAGS@ GDK_IMLIB_LIBS = @GDK_IMLIB_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ IMLIBCONF = @IMLIBCONF@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INST_LINGUAS = @INST_LINGUAS@ ISRELEASED = @ISRELEASED@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOCALEDIR = @LOCALEDIR@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANPAGE_PREAMBLE = @MANPAGE_PREAMBLE@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ MSGUNIQ = @MSGUNIQ@ OBJEXT = @OBJEXT@ 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@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PYTHON = @PYTHON@ RANLIB = @RANLIB@ RELDATELONG = @RELDATELONG@ RELDATENUM = @RELDATENUM@ RELDATESHORT = @RELDATESHORT@ REQUIRED_PERL_VERSION = @REQUIRED_PERL_VERSION@ REQUIRED_PYTHON_VERSION = @REQUIRED_PYTHON_VERSION@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ UPDATEPOFILES = @UPDATEPOFILES@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VERSIONINFO = @VERSIONINFO@ XFT_CFLAGS = @XFT_CFLAGS@ XFT_CONFIG = @XFT_CONFIG@ XFT_LIBS = @XFT_LIBS@ XGETTEXT = @XGETTEXT@ XMKMF = @XMKMF@ XSLTPROC = @XSLTPROC@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Xcursor_CFLAGS = @Xcursor_CFLAGS@ Xcursor_LIBS = @Xcursor_LIBS@ Xft_CFLAGS = @Xft_CFLAGS@ Xft_LIBS = @Xft_LIBS@ Xinerama_CFLAGS = @Xinerama_CFLAGS@ Xinerama_LIBS = @Xinerama_LIBS@ Xrender_CFLAGS = @Xrender_CFLAGS@ Xrender_LIBS = @Xrender_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ iconv_CFLAGS = @iconv_CFLAGS@ iconv_LIBS = @iconv_LIBS@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intl_CFLAGS = @intl_CFLAGS@ intl_LIBS = @intl_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ png_CFLAGS = @png_CFLAGS@ png_LIBS = @png_LIBS@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ readline_CFLAGS = @readline_CFLAGS@ readline_LIBS = @readline_LIBS@ rplay_CFLAGS = @rplay_CFLAGS@ rplay_LIBS = @rplay_LIBS@ rsvg_CFLAGS = @rsvg_CFLAGS@ rsvg_LIBS = @rsvg_LIBS@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ stroke_CFLAGS = @stroke_CFLAGS@ stroke_LIBS = @stroke_LIBS@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ with_bidi = @with_bidi@ with_gdkimlib = @with_gdkimlib@ with_gettext = @with_gettext@ with_iconv = @with_iconv@ with_perllib = @with_perllib@ with_png = @with_png@ with_readline = @with_readline@ with_rplay = @with_rplay@ with_rsvg = @with_rsvg@ with_shape = @with_shape@ with_shm = @with_shm@ with_sm = @with_sm@ with_stroke = @with_stroke@ with_xcursor = @with_xcursor@ with_xft = @with_xft@ with_xinerama = @with_xinerama@ with_xpm = @with_xpm@ with_xrender = @with_xrender@ xpm_CFLAGS = @xpm_CFLAGS@ xpm_LIBS = @xpm_LIBS@ fvwm_root_SOURCE = fvwm-root.c fvwm_root_DEPENDENCIES = $(top_builddir)/libs/libfvwm.a bin_SCRIPTS = fvwm-config fvwm-bug fvwm-perllib \ fvwm-convert-2.6 \ fvwm-menu-xlock fvwm-menu-directory \ fvwm-menu-desktop fvwm-menu-headlines man_MANS = \ fvwm-root.1 fvwm-config.1 fvwm-bug.1 fvwm-perllib.1 \ fvwm-convert-2.6.1 \ fvwm-menu-xlock.1 fvwm-menu-directory.1 \ fvwm-menu-desktop.1 fvwm-menu-headlines.1 LDADD = -L$(top_builddir)/libs $(X_LIBS) -lfvwm $(xpm_LIBS) $(Xcursor_LIBS) \ $(X_PRE_LIBS) -lXext -lX11 -lm $(X_EXTRA_LIBS) $(Xrender_LIBS) \ $(Xcursor_LIBS) $(png_LIBS) $(rsvg_LIBS) $(Xinerama_LIBS) AM_CPPFLAGS = -I$(top_srcdir) $(xpm_CFLAGS) $(X_CFLAGS) $(png_CFLAGS) \ $(rsvg_CFLAGS) $(Xinerama_CFLAGS) configdir = @FVWM_DATADIR@ config_DATA = fvwm-menu-desktop-config.fpl EXTRA_DIST = fvwm-menu-desktop-config.fpl $(man_MANS) xpmroot_name = `echo "xpmroot" | "$(SED)" -e "${transform}"` fvwm_root_name = `echo "fvwm-root" | "$(SED)" -e "${transform}"` CLEANFILES = $(bin_SCRIPTS) $(bin_PROGRAMS) all: all-am .SUFFIXES: .SUFFIXES: .c .o .obj $(srcdir)/Makefile.in: $(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) --foreign bin/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign bin/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: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): fvwm-bug.1: $(top_builddir)/config.status $(srcdir)/fvwm-bug.1.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ fvwm-config.1: $(top_builddir)/config.status $(srcdir)/fvwm-config.1.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ fvwm-convert-2.6.1: $(top_builddir)/config.status $(srcdir)/fvwm-convert-2.6.1.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ fvwm-menu-desktop.1: $(top_builddir)/config.status $(srcdir)/fvwm-menu-desktop.1.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ fvwm-root.1: $(top_builddir)/config.status $(srcdir)/fvwm-root.1.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ fvwm-config: $(top_builddir)/config.status $(srcdir)/fvwm-config.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ fvwm-bug: $(top_builddir)/config.status $(srcdir)/fvwm-bug.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ fvwm-perllib: $(top_builddir)/config.status $(srcdir)/fvwm-perllib.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ fvwm-menu-xlock: $(top_builddir)/config.status $(srcdir)/fvwm-menu-xlock.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ fvwm-menu-directory: $(top_builddir)/config.status $(srcdir)/fvwm-menu-directory.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ fvwm-menu-desktop: $(top_builddir)/config.status $(srcdir)/fvwm-menu-desktop.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ fvwm-menu-headlines: $(top_builddir)/config.status $(srcdir)/fvwm-menu-headlines.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ fvwm-convert-2.6: $(top_builddir)/config.status $(srcdir)/fvwm-convert-2.6.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ ; 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) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || 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)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) fvwm-root$(EXEEXT): $(fvwm_root_OBJECTS) $(fvwm_root_DEPENDENCIES) $(EXTRA_fvwm_root_DEPENDENCIES) @rm -f fvwm-root$(EXEEXT) $(AM_V_CCLD)$(LINK) $(fvwm_root_OBJECTS) $(fvwm_root_LDADD) $(LIBS) install-binSCRIPTS: $(bin_SCRIPTS) @$(NORMAL_INSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | 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; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$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_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fvwm-root.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)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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) '$<'` install-man1: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man1dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.1[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ done; } uninstall-man1: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man1dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.1[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) install-configDATA: $(config_DATA) @$(NORMAL_INSTALL) @list='$(config_DATA)'; test -n "$(configdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(configdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(configdir)" || 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)$(configdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(configdir)" || exit $$?; \ done uninstall-configDATA: @$(NORMAL_UNINSTALL) @list='$(config_DATA)'; test -n "$(configdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(configdir)'; $(am__uninstall_files_from_dir) 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 $(PROGRAMS) $(SCRIPTS) $(MANS) $(DATA) installdirs: for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(configdir)"; 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: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) 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-binPROGRAMS clean-generic mostlyclean-am distclean: distclean-am -rm -f ./$(DEPDIR)/fvwm-root.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-configDATA install-data-local install-man install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-binPROGRAMS install-binSCRIPTS \ install-exec-local install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-man1 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)/fvwm-root.Po -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS \ uninstall-configDATA uninstall-local uninstall-man uninstall-man: uninstall-man1 .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ clean-binPROGRAMS clean-generic cscopelist-am ctags ctags-am \ distclean distclean-compile distclean-generic distclean-tags \ distdir dvi dvi-am html html-am info info-am install \ install-am install-binPROGRAMS install-binSCRIPTS \ install-configDATA install-data install-data-am \ install-data-local install-dvi install-dvi-am install-exec \ install-exec-am install-exec-local install-html \ install-html-am install-info install-info-am install-man \ install-man1 install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic pdf pdf-am \ ps ps-am tags tags-am uninstall uninstall-am \ uninstall-binPROGRAMS uninstall-binSCRIPTS \ uninstall-configDATA uninstall-local uninstall-man \ uninstall-man1 .PRECIOUS: Makefile _fvwm-menu-xlock.1: fvwm-menu-xlock @TMP=tmp-$$$$ NAME=fvwm-menu-xlock && (\ mkdir $$TMP && \ cp $$NAME.in $$TMP/$$NAME && \ pod2man --center "Fvwm Utilities" --release "@VERSION@@VERSIONINFO@" \ --name $$NAME $$TMP/$$NAME >$$TMP/$$NAME.1 && \ mv $$TMP/$$NAME.1 .; \ rm -rf $$TMP) _fvwm-menu-directory.1: fvwm-menu-directory @TMP=tmp-$$$$ NAME=fvwm-menu-directory && (\ mkdir $$TMP && \ cp $$NAME.in $$TMP/$$NAME && \ pod2man --center "Fvwm Utilities" --release "@VERSION@@VERSIONINFO@" \ --name $$NAME $$TMP/$$NAME >$$TMP/$$NAME.1 && \ mv $$TMP/$$NAME.1 .; \ rm -rf $$TMP) _fvwm-menu-headlines.1: fvwm-menu-headlines @TMP=tmp-$$$$ NAME=fvwm-menu-headlines && (\ mkdir $$TMP && \ cp $$NAME.in $$TMP/$$NAME && \ pod2man --center "Fvwm Utilities" --release "@VERSION@@VERSIONINFO@" \ --name $$NAME $$TMP/$$NAME >$$TMP/$$NAME.1 && \ mv $$TMP/$$NAME.1 .; \ rm -rf $$TMP) _fvwm-perllib.1: fvwm-perllib @TMP=tmp-$$$$ NAME=fvwm-perllib && (\ mkdir $$TMP && \ cp $$NAME.in $$TMP/$$NAME && \ pod2man --center "Fvwm Utilities" --release "@VERSION@@VERSIONINFO@" \ --name $$NAME $$TMP/$$NAME >$$TMP/$$NAME.1 && \ mv $$TMP/$$NAME.1 .; \ rm -rf $$TMP) regenerate: \ _fvwm-menu-xlock.1 _fvwm-menu-directory.1 _fvwm-menu-headlines.1 \ _fvwm-perllib.1 install-exec-local: @rm -f $(DESTDIR)$(bindir)/$(xpmroot_name)$(EXEEXT) @$(LN_S) $(fvwm_root_name)$(EXEEXT) \ $(DESTDIR)$(bindir)/$(xpmroot_name)$(EXEEXT) || \ echo "Minor warning: $(bindir)/$(xpmroot_name)$(EXEEXT) symlink was not created" install-data-local: @rm -f $(DESTDIR)$(mandir)/man1/$(xpmroot_name).1 @$(LN_S) $(fvwm_root_name).1 \ $(DESTDIR)$(mandir)/man1/$(xpmroot_name).1 || \ echo "Minor warning: $(mandir)/man1/$(xpmroot_name).1 symlink was not created" uninstall-local: @rm -f $(DESTDIR)$(bindir)/$(xpmroot_name)$(EXEEXT) @rm -f $(DESTDIR)$(mandir)/man1/$(xpmroot_name).1 # 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: ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/bin/fvwm-menu-desktop-config.fpl���������������������������������������������������������0000644�0001750�0001750�00000027151�14147024700�015533� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Uage: Module FvwmPerl -l fvwm-menu-desktop-config.fpl # This script generates an FvwmForm similar to the FvwmForm-Desktop by # Dan Espen but inserts the found xdg menus dynamically into the Form # before processed. # Author: Thomas Funk <t.funk@web.de> # Version: 1.4 package MenuConfig; use File::Basename; use strict; use warnings; my $modname = 'FvwmForm-XDGMenu-Config'; my $configtmp = "$ENV{'FVWM_USERDIR'}/.XDGMenu-Config.fvwm2rc"; open(MSG ,">$configtmp") || die "Error $!"; my $all = `fvwm-menu-desktop --get-menus all`; my $selected = `fvwm-menu-desktop --get-menus desktop`; my @all_filelist = split(/ /,$all); my @selected_filelist = split(/ /,$selected); my %all_menus = (); my %selected__menus = (); my $max_length = 0; foreach my $path (@selected_filelist) { my ($filename, $directories, $suffix) = fileparse($path, qr/\.[^.]*/); push (@{$selected__menus{$directories}}, $filename); } my $i = 1; foreach my $path (@all_filelist) { # qr matched against the end of the $filename. # The matching portion is removed and becomes the $suffix. my ($filename, $directories, $suffix) = fileparse($path, qr/\.[^.]*/); my $name = "MEN" . $filename; push (@{$all_menus{$directories}{$i}}, ($filename, $name, "off")); next if !defined $selected__menus{$directories}; foreach my $hit (@{$selected__menus{$directories}}) { if ($filename eq $hit) { pop (@{$all_menus{$directories}{$i}}); push (@{$all_menus{$directories}{$i}}, "on"); } } $max_length = length($filename) if ($max_length < length($filename)); $i++; } my $fvwmform_commands = " DestroyModuleConfig ${modname}: * *${modname}: Title \"\$[gt.Fvwm XDGMenu Config]\" *${modname}: WarpPointer #*${modname}: Line center #*${modname}: Text \"\$[gt.Fvwm XDGMenu Config]\" #*${modname}: Line *${modname}: Separator *${modname}: Line center *${modname}: Text \"\$[gt.Available Menus]\" *${modname}: Line "; if (scalar keys %all_menus != 0) { foreach my $key (sort( keys %all_menus)) { $fvwmform_commands .= " *${modname}: Line left *${modname}: Text \"\$[gt.Menus in]\" *${modname}: Text \" $key\" *${modname}: Line left *${modname}: Selection meth multiple "; my $m_count = 0; foreach my $count (sort(keys %{$all_menus{$key}})) { my $menu = $all_menus{$key}{$count}; my $newstring = $menu->[0] . ' ' x eval($max_length-length($menu->[0])); $fvwmform_commands .= "*${modname}: Choice $menu->[1] $menu->[1] $menu->[2] \"$newstring\"\n"; $m_count++; if ($m_count == 4) { $fvwmform_commands .= " *${modname}: Line left *${modname}: Selection meth multiple "; $m_count = 0; } } $fvwmform_commands .= " *${modname}: Line left *${modname}: Text \" \" "; } } else { $fvwmform_commands .= " *${modname}: Line center *${modname}: Text \"\$[gt.No menus found! Check why from within a terminal with]\" *${modname}: Line center *${modname}: Text \"'fvwm-menu-desktop -v'\" *${modname}: Line left *${modname}: Text \" \" "; } $fvwmform_commands .= " *${modname}: Separator *${modname}: Line center *${modname}: Text \"\$[gt.Options]\" *${modname}: Button continue \"\$[gt.Help]\" *${modname}: Command Module FvwmForm FvwmForm-XDGOptionsHelp *${modname}: Line *${modname}: Line Left *${modname}: Text \"\$[gt.Include in Menu? ]\" *${modname}: Selection SelItype single *${modname}: Choice IncludeConfig IncludeConfig off \"\$[gt.Config ]\" *${modname}: Choice IncludeRegen IncludeRegen off \"\$[gt.Regenerate ]\" *${modname}: Choice IncludeBoth IncludeBoth on \"\$[gt.Both ]\" *${modname}: Choice IncludeNone IncludeNone off \"\$[gt.None ]\" *${modname}: Line Left *${modname}: Text \"\$[gt.Use Icons? ]\" *${modname}: Selection SelItype single *${modname}: Choice IconsOn IconsOn off \"\$[gt.Yes ]\" *${modname}: Choice IconsOff IconsOff on \"\$[gt.No ]\" *${modname}: Text \"\$[gt. ]\" *${modname}: Text \"\$[gt.Icon size: ]\" *${modname}: Input Size 2 \"\" *${modname}: Text \"\$[gt. (Default is 24)]\" *${modname}: Line Left *${modname}: Text \"\$[gt.Use Titles? ]\" *${modname}: Selection SelItype single *${modname}: Choice TitlesOn TitlesOn on \"\$[gt.Yes ]\" *${modname}: Choice TitlesOff TitlesOff off \"\$[gt.No ]\" *${modname}: Text \"\$[gt. ]\" *${modname}: Text \"\$[gt.Used Icon theme: ]\" *${modname}: Input Theme 20 \"\" *${modname}: Line left *${modname}: Text \"\$[gt.Directory Icon: ]\" *${modname}: Input DirIcon 20 \"gnome-fs-directory\" *${modname}: Text \"\$[gt. ]\" *${modname}: Text \"\$[gt.Application Icon: ]\" *${modname}: Input AppIcon 20 \"gnome-applications\" *${modname}: Line left *${modname}: Text \"\$[gt.Top Menu Name: ]\" *${modname}: Input Title 20 \"XDGMenu\" *${modname}: Text \"\$[gt. ]\" *${modname}: Text \"\$[gt.Insert Menu Into: ]\" *${modname}: Input InsertInto 20 \"\" *${modname}: Line left *${modname}: Text \"\$[gt.Terminal command: ]\" *${modname}: Input TermCmd 30 \"xterm -e\" *${modname}: Text \"\$[gt. (Used to run Terminal entries)]\" *${modname}: Line left *${modname}: Text \"\$[gt.Icon directory: ]\" *${modname}: Input IconDir 30 \"~/.fvwm/icons\" *${modname}: Text \"\$[gt. (Directory for converted icons)]\" *${modname}: Line left *${modname}: Text \"\$[gt.Output path: ]\" *${modname}: Input Path 30 \"\$FVWM_USERDIR/.XDGMenu\" *${modname}: Text \"\$[gt. (Full path to store output)]\" *${modname}: Line left *${modname}: Line *${modname}: Separator *${modname}: Line *${modname}: Line expand *${modname}: Button continue \"\$[gt.Export Menu]\" *${modname}: Command InfoStoreAdd XDGMenuList \"\\ "; foreach my $key (keys %all_menus) { foreach my $file (keys %{$all_menus{$key}}) { my $menu = $all_menus{$key}{$file}; $fvwmform_commands .= "\$($menu->[1]\?$key$menu->[0].menu )\\\n"; } } $fvwmform_commands .= "\" *${modname}: Command PipeRead 'fvwm-menu-desktop \\ \$(IconsOn\?--enable-mini-icons )\\ \$(Size\?-s \$(Size) )\\ \$(TitlesOn\?--with-titles )\\ \$(TitlesOff\?--without-titles )\\ --include-items \$(IncludeConfig\?config)\\ \$(IncludeRegen\?regenerate)\\ \$(IncludeBoth\?both)\\ \$(IncludeNone\?none) \\ \$(TermCmd\?--term-cmd \"\$(TermCmd)\" )\\ \$(IconDir\?--mini-icon-dir \$(IconDir) )\\ \$(DirIcon\?--dir-icon \$(DirIcon) )\\ \$(AppIcon\?--app-icon \$(AppIcon) )\\ \$(InsertInto\?--insert-in-menu \$(InsertInto) )\\ \$(Title\?--title \$(Title) )\\ \$(Theme\?--theme \$(Theme) )\\ --set-menus \"\$[infostore.XDGMenuList]\" \\ \$(Path\? > \$(Path)) 2>> ~/.xsession-errors && echo \"Read \$(Path\? \$(Path))\"' *${modname}: Button continue \"\$[gt.Save and Regenerate]\" # Before saving the data, remove any previously saved data: *${modname}: Command DestroyModuleConfig ${modname}Default: * *${modname}: Command !(/bin/echo \"# This file last created by ${modname} on: `/bin/date`.\") > \$FVWM_USERDIR/.${modname} "; foreach my $key (keys %all_menus) { foreach my $count (keys %{$all_menus{$key}}) { my $menu = $all_menus{$key}{$count}; $fvwmform_commands .= "*${modname}: Command !(/bin/echo '*${modname}Default: $menu->[1] \$($menu->[1]\?on) ') >> \$FVWM_USERDIR/.${modname}\n"; } } $fvwmform_commands .= " *${modname}: Command !(/bin/echo \\ '*${modname}Default: IncludeConfig \$(IncludeConfig\?on) ' ; /bin/echo \\ '*${modname}Default: IncludeRegen \$(IncludeRegen\?on) ' ; /bin/echo \\ '*${modname}Default: IncludeBoth \$(IncludeBoth\?on) ' ; /bin/echo \\ '*${modname}Default: IncludeNone \$(IncludeNone\?on) ' ; /bin/echo \\ '*${modname}Default: IconsOn \$(IconsOn\?on) ' ; /bin/echo \\ '*${modname}Default: IconsOff \$(IconsOff\?on) ' ; /bin/echo \\ '*${modname}Default: Size \$(Size) ' ; /bin/echo \\ '*${modname}Default: TitlesOn \$(TitlesOn\?on) ' ; /bin/echo \\ '*${modname}Default: TitlesOff \$(TitlesOff\?on) ' ; /bin/echo \\ '*${modname}Default: Theme \$(Theme) ' \\ ) >> \$FVWM_USERDIR/.${modname} *${modname}: Command !(/bin/echo \\ '*${modname}Default: Title \$(Title) ' ; /bin/echo \\ '*${modname}Default: InsertInto \$(InsertInto) ' ; /bin/echo \\ '*${modname}Default: Path \$(Path) ' ; /bin/echo \\ '*${modname}Default: TermCmd \$(TermCmd) ' ; /bin/echo \\ '*${modname}Default: IconDir \$(IconDir) ' ; /bin/echo \\ '*${modname}Default: DirIcon \$(DirIcon) ' ; /bin/echo \\ '*${modname}Default: AppIcon \$(AppIcon) ' \\ ) >> \$FVWM_USERDIR/.${modname} *${modname}: Command PipeRead 'fvwm-menu-desktop' *${modname}: Button continue \"\$[gt.Save]\" # Before saving the data, remove any previously saved data: *${modname}: Command DestroyModuleConfig ${modname}Default: * *${modname}: Command !(/bin/echo \"# This file last created by ${modname} on: `/bin/date`.\") > \$FVWM_USERDIR/.${modname} "; foreach my $key (keys %all_menus) { foreach my $count (keys %{$all_menus{$key}}) { my $menu = $all_menus{$key}{$count}; $fvwmform_commands .= "*${modname}: Command !(/bin/echo '*${modname}Default: $menu->[1] \$($menu->[1]\?on) ') >> \$FVWM_USERDIR/.${modname}\n"; } } $fvwmform_commands .= " *${modname}: Command !(/bin/echo \\ '*${modname}Default: IncludeConfig \$(IncludeConfig\?on) ' ; /bin/echo \\ '*${modname}Default: IncludeRegen \$(IncludeRegen\?on) ' ; /bin/echo \\ '*${modname}Default: IncludeBoth \$(IncludeBoth\?on) ' ; /bin/echo \\ '*${modname}Default: IncludeNone \$(IncludeNone\?on) ' ; /bin/echo \\ '*${modname}Default: IconsOn \$(IconsOn\?on) ' ; /bin/echo \\ '*${modname}Default: IconsOff \$(IconsOff\?on) ' ; /bin/echo \\ '*${modname}Default: Size \$(Size) ' ; /bin/echo \\ '*${modname}Default: TitlesOn \$(TitlesOn\?on) ' ; /bin/echo \\ '*${modname}Default: TitlesOff \$(TitlesOff\?on) ' ; /bin/echo \\ '*${modname}Default: Theme \$(Theme) ' \\ ) >> \$FVWM_USERDIR/.${modname} *${modname}: Command !(/bin/echo \\ '*${modname}Default: Title \$(Title) ' ; /bin/echo \\ '*${modname}Default: InsertInto \$(InsertInto) ' ; /bin/echo \\ '*${modname}Default: Path \$(Path) ' ; /bin/echo \\ '*${modname}Default: TermCmd \$(TermCmd) ' ; /bin/echo \\ '*${modname}Default: IconDir \$(IconDir) ' ; /bin/echo \\ '*${modname}Default: DirIcon \$(DirIcon) ' ; /bin/echo \\ '*${modname}Default: AppIcon \$(AppIcon) ' \\ ) >> \$FVWM_USERDIR/.${modname} *${modname}: Button restart \"\$[gt.Reset]\" *${modname}: Command Nop *${modname}: Button continue \"\$[gt.Help]\" *${modname}: Command Module FvwmForm FvwmForm-XDGMenuHelp *${modname}: Button quit \"\$[gt.Close]\" *${modname}: Command Nop # Tell ${modname} to read vars from .${modname}Default file: *${modname}: UseData .${modname} *${modname}Default "; # We are just asked to open a window, give fvwm a chance to do it ::unlock(); $fvwmform_commands =~ s/^\s+//; # trim leading whitespace print MSG "$fvwmform_commands\n\n"; close(MSG); ::command(qq[ Read $configtmp FvwmForm ${modname} ]); sleep(2); unlink $configtmp # Local Variables: # mode: perl # End: �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/bin/fvwm-root.1��������������������������������������������������������������������������0000644�0001750�0001750�00000007210�14324316007�012212� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������'\" t .\" @(#)fvwm-2.7.0 19 October 2022 .TH fvwm-root 1 "19 October 2022 (2.7.0)" Fvwm "Fvwm Modules" .UC .SH NAME fvwm-root \- Sets the root window of the current X display to image .SH SYNOPSIS .B fvwm-root .RB [ "--retain-pixmap" | "-r" ] .RB [ "--no-retain-pixmap" ] .RB [ "--dummy" | "-d" ] .RB [ "--no-dummy" ] .RB [ "--dither" ] .RB [ "--no-dither" ] .RB [ "--color-limit" .RI [ ncolors "] ]" .RB [ "--no-color-limit" ] .RB [ "--help" | "-h" | "-?" ] .RB [ "--version" | "-V" ] .I image_file .SH DESCRIPTION .I fvwm-root reads the image file specified in the command line and displays it in the root window. The supported image formats are .IR XBM ", " XPM ", " PNG " and " SVG if appropriated libraries are compiled in. SVG rendering options .RB " (as described in the " " ICONS AND IMAGES " section of the main fvwm documentation) can be utilized. .SH OPTIONS These command line options are recognized by fvwm-root: .TP .BR "--retain-pixmap" " | " "-r" Causes fvwm-root to retain and publish the Pixmap with which the background has been set (the ESETROOT_PMAP_ID and _XROOTPMAP_ID properties are used). This is useful for applications which want to use the root Pixmap on the background to simulate transparency (for example, Eterm and Aterm use this method). This option should also be used for the RootTransparent colorset option, refer to the COLORSETS section of fvwm(1). If this option is not used, fvwm-root sets the _XSETROOT_ID property to None, and some programs, like fvwm modules, may use this to update their background if the background is transparent (Transparent colorset). Note, a well behaved program, like fvwm, should listen to both _XSETROOT_ID and _XROOTPMAP_ID property changes and update itself correspondingly. However some programs listen only to one of them, so you should either use this option or not depending on what part is implemented by these programs. You should also use this option to get fast root-transparent menus in fvwm. .TP .BI "--no-retain-pixmap" This is a default. May be useful to explicitly force the default even if "--retain-pixmap" is specified earlier. .TP .BR "--dummy" " | " "-d" Causes fvwm-root NOT to set the background, but to only free a memory associated with the ESETROOT_PMAP_ID property (if any). In any case the _XSETROOT_ID property is set to None. .TP .BI "--no-dummy" This is a default. May be useful to explicitly force the default even if "--dummy" is specified earlier. .TP .BI "--dither" Causes fvwm-root to dither images for "smoother" rendition on displays with color depth of 16 or lower. This the default with color depth less or equal to 8. .TP .BI "--no-dither" Causes fvwm-root NOT to dither images. This is the default with color depth greater than 8. .TP .BI "--color-limit " ncolors Causes fvwm-root to limit its color use to .I ncolors (if specified). This option is taken in account only with color depth less or equal to 8 (and a TrueColor or GrayScale visual). The default is to use the same color limit as fvwm. So in normal situation this option is not useful. However, if fvwm use a private colors map, as fvwm-root always use the default colors map you should use this option for limiting colors correctly. If .I ncolors is not specified a default is used. .TP .BI "--no-color-limit" Causes fvwm-root NOT to limit its color use. .TP .BI "--help" Shows a short usage. .TP .BI "--version" Shows a version number. .SH COMPATIBILITY In the past this utility was called .IR xpmroot . This name is still supported as a symlink. .SH BUGS Repeated use of fvwm-root with different xpm pixmaps will use up slots in your color table pretty darn fast. .SH AUTHOR Rob Nation Rewritten and enhanced by fvwm-workers. ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/bin/fvwm-menu-directory.in���������������������������������������������������������������0000644�0001750�0001750�00000055651�14324314575�014467� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!@PERL@ # Copyright (c) 1999-2009 Mikhael Goikhman # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see: <http://www.gnu.org/licenses/> # Filter this script to pod2man to get a man page: # pod2man -c "Fvwm Utilities" fvwm-menu-directory | nroff -man | less -e # To speed up the script, several optimizations were made: trying to minimize # the number of additional file operations, function calls and includes. #print STDERR "fvwm-menu-directory @ARGV\n"; use strict; use Getopt::Long; my $version = "@VERSION@"; my $name = "MenuBrowser"; # used only with --reuse my $title = "%*-40p"; # may contain specifiers %d, %p. my $itemf = "%n"; # may contain specifiers %n, %t, %T, %d, %D, %s. my $icont = ""; my $icond = ""; my $iconf = ""; my $icona = ""; my $home = $ENV{'HOME'} || '/tmp'; my $dir = $home; my $xterm = "xterm -e"; # the X terminal program to invoke my $exect = $ENV{'SHELL'} || '/bin/sh'; my $execf = $ENV{'EDITOR'} || "vi"; # the command to execute on plain files my $execa = undef; my $commt = undef; my $commf = undef; my $comma = undef; my $all = 0; # whether show hidden files (like in 'ls -A') my $links = 0; # whether follow linked dirs or not my $order = 5; # -6, -5, -4, -3, -2, -1, 1, 2, 3, 4, 5, 6 my $reuse = 0; # non-popup mode my $wm_icons = 0; my $check_subdirs = 0; # whether check subdirs for +x permissions my $special_dir_val = undef; # which of (.. ~ /) dirs include or none my $memory_for_speed = 0; my $submenu_pos = " item +100 c"; # " menu +0 +0" my $fvwm_user_dir = $ENV{'FVWM_USERDIR'} || "$home/.fvwm"; $fvwm_user_dir = $home unless -d $fvwm_user_dir; my $dir_filename = "$fvwm_user_dir/.fvwm-menu-directory.dir"; my $change_menu_style = ""; my $func_name = "FuncFvwmMenuDirectory"; GetOptions( "help|h|?" => \&show_help, "version|V" => \&show_version, "name=s" => \$name, "title=s" => \$title, "item=s" => \$itemf, "icon-title=s" => \$icont, "icon-dir=s" => \$icond, "icon-file=s" => \$iconf, "icon-app=s" => \$icona, "dir=s" => \$dir, "order=i" => \$order, "all!" => \$all, "links!" => \$links, "xterm=s" => \$xterm, "exec-title=s" => \$exect, "exec-file=s" => \$execf, "exec-app:s" => \$execa, "command-title=s" => \$commt, "command-file=s" => \$commf, "command-app=s" => \$comma, "reuse!" => \$reuse, "wm-icons" => \$wm_icons, "check-subdirs!" => \$check_subdirs, "special-dirs:s" => \$special_dir_val, "memory-for-speed!" => \$memory_for_speed, "menu-style=s" => \$change_menu_style, "func-name=s" => \$func_name, ) || wrong_usage(); wrong_usage() if @ARGV; $name = $dir unless $reuse; $dir =~ s:^~(/|$):$home$1:; chomp($dir = `cat "$dir_filename"`) if $reuse && -f $dir_filename; unless (-d $dir) { # the next line may be commented not to throw error #die "$dir does not exist, exiting.\n"; $dir = $home; } $links || !-l $dir || exit(-1); # exit if linked directories are disabled chdir($dir) || exit(-1); # exit if no execute permission on the directory # expand title &expand_width_specifier(\$title, 'd', (split('/', $dir))[-1] || '/') if $title =~ /%(-?\d+)?(\*-?\d+)?d/; &expand_width_specifier(\$title, 'p', $dir) if $title =~ /%(-?\d+)?(\*-?\d+)?p/; $title =~ s/\\t/\t/g; $itemf =~ s/\\t/\t/g; # item format optimization variables my $itemf_eval = $itemf ne '%f'; # evaluation needed my $itemf_name = undef; my $itemf_stat = undef; # stat() needed my $itemf_date = undef; my $itemf_size = undef; my $itemf_type = undef; if ($itemf_eval) { $itemf_name = $itemf =~ /%(-?\d+)?(\*-?\d+)?[nN]/; $itemf_date = $itemf =~ /%[dD]/; $itemf_size = $itemf =~ /%(-?\d+)?(\*-?\d+)?s/; $itemf_type = $itemf =~ /%[tT]/; $itemf_stat = $itemf_size || $itemf_date || $itemf_size || $itemf_type; } my @type1 = ("Sock", "Link", "File", "Blck", "Dir ", "Char", "Pipe"); my @type2 = ("S", "L", "F", "B", "D", "C", "P"); if ($wm_icons) { $icont ||= "menu/folder-open.xpm"; $icond ||= "menu/folder.xpm"; $iconf ||= "menu/file.xpm"; $icona ||= "menu/utility.xpm"; } my $icont_str = $icont ? "%$icont%" : ""; my $icond_str = $icond ? "%$icond%" : ""; my $iconf_str = $iconf ? "%$iconf%" : ""; my $icona_str = $icona ? "%$icona%" : ""; $exect = undef if defined $exect && $exect eq '-'; $execf = undef if defined $execf && $execf eq '-'; $execa = undef if defined $execa && $execa eq '-'; $exect = $exect =~ /^\^(.*)$/ ? $1 : "$xterm $exect" if defined $exect; $execf = $execf =~ /^\^(.*)$/ ? $1 : "$xterm $execf" if defined $execf; $execa = $execa =~ /^\^(.*)$/ ? $1 : "$xterm $execa" if defined $execa; $commt = undef if defined $commt && $commt eq '-'; $commf = undef if defined $commf && $commf eq '-'; $comma = undef if defined $comma && $comma eq '-'; $commt = defined $exect ? qq(Exec cd "%d"; $exect): "Nop" if !defined $commt; $commf = defined $execf ? qq(Exec $execf "%f"): "Nop" if !defined $commf; $comma = defined $execa ? qq(Exec $execa "%f"): $commf if !defined $comma; # manage special directories if needed my ($special_dir_lines, $special_dir_pos, @special_dirs) = (""); $special_dir_val = "1,2" if defined $special_dir_val && $special_dir_val eq ""; if ($special_dir_val && $special_dir_val =~ /([\d,]+)(-?)/) { @special_dirs = grep(/^[1-3]$/, split(/,+/, $1)); $special_dir_pos = $2 ? -1 : 1; } if (@special_dirs) { my $parent_dir = $dir eq '/' || $dir !~ m!^(.*)/[^\/]+$! ? undef : $1; $parent_dir = '/' if defined $parent_dir && $parent_dir eq ''; my @special_dir_def = ( [ '..' => $parent_dir ], [ '~' => $home ], [ '/' => '/' ], ); foreach (@special_dirs) { $special_dir_lines .= qq(+ "" Nop\n) if $special_dir_lines; $special_dir_lines .= &eval_folder_line(@{$special_dir_def[$_ - 1]}); } } else { $special_dir_pos = 0; } # create file listing opendir(DIR, "."); my @files = readdir(DIR); closedir(DIR); @files = grep /^[^.]/, @files unless $all; my $abs_order = abs($order); # To avoid warnings, '!!' must be added before '-d'. Will this slow things? my $sort_sub = $abs_order == 2 ? sub { -d $b <=> -d $a } : $abs_order == 3 ? sub { -d $a <=> -d $b } : $abs_order == 4 ? sub { $a cmp $b } : $abs_order == 5 ? sub { -d $b <=> -d $a || $a cmp $b } : $abs_order == 6 ? sub { -d $a <=> -d $b || $a cmp $b } : sub { 0 }; @files = sort $sort_sub @files if $abs_order != 1; @files = reverse @files if $order < 0; # dump all menu items and start adding new items my $menu_name = &escape_file_name($name); my $menu_name2 = &escape_menu_name($name); print qq(DestroyMenu recreate "$menu_name"\nAddToMenu "$menu_name2"\n); # destroy the menu after it is popped down print qq(+ DynamicPopDownAction DestroyMenu "$menu_name"\n) unless $memory_for_speed || $reuse; # set the 'missing submenu function' print qq(+ MissingSubmenuFunction $func_name\n) unless $reuse; # add a new title (item and separator, or real Title if no action) my $title_act = $commt; $title_act =~ s/%d/$dir/g; if ($title ne "") { if ($title_act eq "") { print qq(+ "$icont_str$title" Title\n); } else { print qq(+ "$icont_str$title" $title_act\n+ "" Nop\n); } } # add special dirs at the top if needed print qq($special_dir_lines+ "" Nop\n) if $special_dir_pos > 0; # add directory contents foreach (@files) { next if $_ eq '.' or $_ eq '..'; my $file_path = "$dir/$_"; $file_path =~ s|/+|/|g; if (-d) { # it's a directory print &eval_folder_line($_, $file_path); } else { # something else, apply editor to it or run itself my $item_str = $itemf_eval ? &eval_item($_, $file_path) : $_; $item_str = &escape_item_name($item_str); my $is_app = -x && -f; my $icon_str = $is_app && $icona_str ? $icona_str : $iconf_str; my $file_act = $is_app ? $comma : $commf; $file_act =~ s/%f/&escape_file_name($file_path)/ge; print qq(+ "$icon_str$item_str" $file_act\n); } } # add special dirs at the bottom if needed print qq(+ "" Nop\n$special_dir_lines) if $special_dir_pos < 0; # add style: if ($change_menu_style ne "") { print qq(ChangeMenuStyle "$change_menu_style" "$menu_name"\n); } exit(0); # --------------------------------------------------------------------------- sub escape_fvwm_name ($) { my $name = shift; $name =~ s/\\/\\\\/g; $name =~ s/"/\\"/g; $name =~ s/\$/\$\$/g; $name; } sub escape_menu_name ($) { my $name = escape_fvwm_name(shift()); # fvwm is really inconsistent here $name =~ s/\^/^^/g; $name =~ s/@/@@/g; $name; } sub escape_item_name ($) { my $name = escape_fvwm_name(shift()); $name =~ s/%/%%/g; $name =~ s/&/&&/g; $name =~ s/\*/**/g; $name =~ s/\n/ /g; $name; } sub escape_file_name ($) { my $name = shift; $name =~ s/\\/\\\\/g; $name =~ s/"/\\"/g; $name =~ s/\$/\\\$\$/g; $name =~ s/\n/\\\n/g; $name; } sub eval_folder_line ($$) { my ($_name, $dir) = @_; my $item_str = $dir && $itemf_eval ? &eval_item($_name, $dir) : $_name; $item_str = escape_item_name($item_str); my $act = !$dir || $check_subdirs && !-x $dir ? "Nop" : !$reuse ? qq(Popup ") . escape_file_name($dir) . qq("$submenu_pos) : qq(PipeRead 'echo ") . escape_file_name($dir) . qq(" >$dir_filename; ) . qq(echo Menu ") . escape_fvwm_name($name) . qq(" WarpTitle'); return qq(+ "$icond_str$item_str" $act\n); } sub eval_item ($$) { my ($name, $file) = @_; return $name unless $itemf_eval; my $item_str = "$itemf"; if ($itemf_name) { &expand_width_specifier(\$item_str, 'n', $name); &expand_width_specifier(\$item_str, 'N', $file); } return $item_str unless $itemf_stat; # / $dev, $ino, $mode, $nlink, $uid, $gid, $rdev, # \ $size, $atime, $mtime, $ctime, $blksize, $blocks my ($misc1, $misc2, $mode, $misc3, $misc4, $misc5, $misc6, $size, $misc7, $time) = stat($file); if ($itemf_date) { eval 'use POSIX qw(strftime);' unless defined $POSIX::VERSION; my @time = localtime($time); my $date1 = strftime("%Y-%m-%d %H:%M:%S", @time); my $date2 = strftime("%Y-%m-%d", @time); $item_str =~ s/%d/$date1/g; $item_str =~ s/%D/$date2/g; } if ($itemf_size) { &expand_width_specifier(\$item_str, 's', $size); } if ($itemf_type) { my $type; # $type = 2 if ($mode & 0100000); # regular # $type = 4 if ($mode & 0040000); # directory # $type = 0 if ($mode & 0140000); # socket # $type = 1 if ($mode & 0120000); # symlink # $type = 3 if ($mode & 0060000); # block # $type = 5 if ($mode & 0020000); # char-dev # $type = 6 if ($mode & 0010000); # fifo $type = -p _ ? 6 : -c _ ? 5 : -b _ ? 3 : -l $file ? 1 : -S _ ? 0 : -d _ ? 4 : 2; $item_str =~ s/%t/$type1[$type]/g; $item_str =~ s/%T/$type2[$type]/g; } return $item_str; } # Substitutes all %N1*N2x in $name by properly stripped and justified $value. sub expand_width_specifier (\$$$) { my ($name, $char, $value) = @_; $$name =~ s/%(-?\d+)?(\*(-?)(\d+))?$char/ my $value = !$2 || $4 <= 3 || $4 > length($value) ? $value : $3 ? "..." . substr($value, -$4 + 3, $4 - 3) : substr($value, 0, $4 - 3) . "..."; $1 ? sprintf("%$1s", $value) : $value; /ge; } sub show_help { print "A perl script that builds directory listing for fvwm.\n\n"; print "Usage: $0 [OPTIONS]\n"; print "Options:\n"; print "\t--help show this help and exit\n"; print "\t--version show the version and exit\n"; print "\t--name=NAME menu name, default is '$name'\n"; print "\t--title=NAME menu title, default is '$title'\n"; print "\t--item=NAME menu item format, default is '$itemf'\n"; print "\t--icon-title=XPM menu title icon, default is none\n"; print "\t--icon-dir=XPM menu dir icon, default is none\n"; print "\t--icon-file=XPM menu file icon, default is none\n"; print "\t--icon-app=XPM menu +x icon, default is none\n"; print "\t--wm-icons define icon names to use with wm-icons\n"; print "\t--dir=NAME starting dir, default is '$dir'\n"; print "\t--order=NUM NUM (-6 .. 6), default is 5\n"; print "\t\t1 - do not sort, 2 - dirs first, 3 - files first\n"; print "\t\t4 - sort by name, 5 - dirs first, 6 - files first\n"; print "\t\tNegative number represents reverse order.\n"; print "\t--all show hidden files, default is no\n"; print "\t--links follow linked dirs, default is no\n"; print "\t--xterm=CMD xterm call, default is '$xterm'\n"; print "\t--exec-title=CMD title exec command, default is '$exect'\n"; print "\t--exec-file=CMD file exec command, default is '$execf'\n"; print "\t--exec-app[=CMD] +x files exec command, default is '-'\n"; print "\t--command-title=CMD title fvwm command, default is '-'\n"; print "\t--command-file=CMD file fvwm command, default is '-'\n"; print "\t--command-app=CMD +x files fvwm command, default is '-'\n"; print "\t--reuse no popups, reuse the same menu (no)\n"; print "\t--check-subdirs check subdir for +x permission (no)\n"; print "\t--special-dirs[=X] include .. and ~ directories (no)\n"; print "\t--memory-for-speed use speed optimization (no)\n"; print "\t--menu-style=NAME assign specified MenuStyle name to menus\n"; print "Short options are ok if not ambiguous: -a, -icon-f.\n"; exit 0; } sub show_version { print "$version\n"; exit 0; } sub wrong_usage { print STDERR "Try '$0 --help' for more information.\n"; exit -1; } __END__ # --------------------------------------------------------------------------- =head1 NAME fvwm-menu-directory - builds a directory browsing menu for fvwm =head1 SYNOPSIS B<fvwm-menu-directory> [ B<--help>|B<-h>|B<-?> ] [ B<--version>|B<-V> ] [ B<--name>|B<-na> NAME ] [ B<--title>|B<-t> NAME ] [ B<--item>|B<-it> NAME ] [ B<--icon-title>|B<-icon-t> XPM ] [ B<--icon-dir>|B<-icon-d> XPM ] [ B<--icon-file>|B<-icon-f> XPM ] [ B<--icon-app>|B<-icon-a> XPM ] [ B<--wm-icons> ] [ B<--dir>|B<-d> NAME ] [ B<--order>|B<-o> NUM ] [ B<--[no]all>|B<-a> ] [ B<--[no]links>|B<-l> ] [ B<--xterm>|B<-x> CMD ] [ B<--exec-title>|B<-exec-t> CMD ] [ B<--exec-file>|B<-exec-f> CMD ] [ B<--exec-app>|B<-exec-a> [CMD] ] [ B<--command-title>|B<-command-t> CMD ] [ B<--command-file>|B<-command-f> CMD ] [ B<--command-app>|B<-command-a> CMD ] [ B<--[no]reuse>|B<-r> ] [ B<--[no]check-subdirs>|B<-ch> ] [ B<--special-dirs>|B<-s> [VALUE] ] [ B<--[no]memory-for-speed>|B<-mem> ] [ B<--menu-style>|B<-men> NAME ] [ B<--func-name>|B<-f> NAME ] =head1 DESCRIPTION A perl script which provides an output to read in with PipeRead to build an fvwm menu containing a directory listing. Almost everything can be configured. =head1 HINTS The title item with its own attached action is usually added to the menu. This may be used to define an action for the directory for which the menu is built, such as starting a terminal in this directory (the default). However, this may annoy some users. To disable the title action use B<--command-title> "", to remove the title completely use B<--title> "". =head1 OPTIONS =over 4 =item B<--help> show the usage and exit =item B<--version> show version and exit =item B<--name> name menu name, used only with --reuse, default is MenuBrowser =item B<--title> title menu title format, default is '%*-40p' - last 40 characters of the current full path. TAB can be specified as '\t', but in .fvwm2rc you should specify a double backslash or a real TAB. Format specifiers: %d - the current directory name %p - the current directory full path These specifiers can receive an optional integer size, positive for right adjusted string or negative for left adjusted, example: %8x; and optional *num or *-num, which means to leave only the first or last (if minus) num of chars, the num must be greater than 3, since the striped part is replaced with "...", example: %*30x. Both can be combined: %-10*-20x, this instructs to get only the 20 last characters, but if the length is less then 10 - to fill with up to 10 spaces on the right. =item B<--item> format menu item format, default is '%n'. TAB and width modifiers for %n, %N and %s can be specified as described in B<--title> above. Note, specifying a non default format slows the script. Format specifiers: %n - file/dir name (without the path) %N - file/dir name (full with the path) %d - file/dir date (yyyy-mm-dd HH:MM:SS) %D - file/dir date (yyyy-mm-dd) %s - file/dir size (in bytes) %t - file/dir type (File|Dir |Link|Sock|Blck|Char|Pipe) %T - file/dir type (F|D|L|S|B|C|P) Example: --title '%*-40p\tDate, Type\tSize' --item '%*40n\t%d %t\t%s' =item B<--icon-title> icon menu title icon, default is none =item B<--icon-dir> icon menu dir icon, default is none =item B<--icon-file> icon menu file icon, default is none =item B<--icon-app> icon menu application icon, default is none =item B<--wm-icons> define icon names suitable for use with wm-icons package. Currently this is equivalent to: --icon-title menu/folder-open.xpm --icon-item menu/file.xpm --icon-dir menu/folder.xpm --icon-app menu/utility.xpm. =item B<--dir> dir starting dir, default is ${HOME-.} =item B<--order> number in the range (-6 .. 6), default is 5: 1 - do not sort, 2 - dirs first, 3 - files first 4 - sort by name, 5 - dirs first, 6 - files first Negative number represents reverse order. =item B<--[no]all> show hidden files, like in 'ls -A', default is --noall =item B<--[no]links> follow linked directories, default is --nolinks =item B<--xterm> command X terminal call, default is 'xterm -e' =item B<--exec-title> command an fvwm Exec command on directory title (usually the shell), default is ${SHELL-/bin/sh}. '-' means no Exec command, i.e. Nop. If the command is not started with '^' X terminal call is prepended. The command is started in the currently browsed directory. =item B<--exec-file> command an fvwm Exec command on regular files, default is ${EDITOR-vi}. '-' means no Exec command, i.e. Nop. If the command is not started with '^' X terminal call is prepended. The actual file name is appended to the command. =item B<--exec-app> [command] an fvwm Exec command on +x files, default is '-', which means the same command as on regular files. If no command is given, it is assumed to be empty - simply run the +x file. If the command is not started with '^' X terminal call is prepended. The actual file name is appended to the command. =item B<--command-title> command an fvwm command to execute on title. If this option is not given (or command is '-'), the C<--exec-title> is used instead. In the command, %d is substituted with the full directory path. In fact, I<--exec-title=tcsh> is equivalent to I<--command-title='Exec cd "%d"; xterm -e tcsh'> The empty value disables the title action. =item B<--command-file> command an fvwm command to execute on regular files. If this option is not given (or command is '-'), the C<--exec-file> is used instead. In the command, %f is substituted with the full file path. In fact, --exec-file=vi is equivalent to --command-file='Exec xterm -e vi "%f"' =item B<--command-app> command an fvwm command to execute on +x files. If this option is not given (or command is '-'), the C<--command-app> is used instead. In the command, %f is substituted with the full file path. In fact, --exec-app=^exec is equivalent to --command-app='Exec exec "%f"' =item B<--[no]reuse> no pop-up menus, reuse the same menu, default is --noreuse. When you specify this option the Menu action is used, not Popup. Also, the --name parameter is not ignored, and --dir parameter is ignored if there is ~/.fvwm/.fvwm-menu-directory.dir file. This file is only created or used with this option specified, it is the only solution for the current fvwm menu state. =item B<--[no]check-subdirs> check all subdirs for having execute (+x) permission and replace "Popup"/"Menu" command with "Nop" for these without permissions. This has a visual effect of disabling popup triangle in the subdirectory item. The default is --nocheck-subdirs, because: 1) enabling this slows a bit the script, 2) with this option enabled, if no icons used and no dir/file separate sorting used there is no way to know that the item is directory and not file. =item B<--special-dirs> value add .. or ~ or / special directories according to given optional value. Without with option these directories are not added. Default value if not specified is "1,2". The value is comma separated ordered special directory indexes, where 1 is parent directory, 2 is home directory, 3 is root directory. If minus is prepended to the value, special directories are added at the bottom of menu instead of top. Value "0" or any bad value is equivalent to non-specifying this option at all. =item B<--[no]memory-for-speed> use speed optimization, i.e. use previously created directory menus without destroying it when closed, default is --nomemory-for-speed Warning: speed optimization takes up a lot of memory that is never free'd again while fvwm is running. =item B<--menu-style> name assign MenuStyle name to the menus =item B<--func-name> name overwrite the default MissingSubmenuFunction name that is "FuncFvwmMenuDirectory" =back Option parameters can be specified either using '=' or in the next argument. Short options are ok if not ambiguous: C<-a>, C<-x>, C<-icon-f>; but be careful with short options, what is now unambiguous, can become ambiguous in the next versions. =head1 USAGE Put this into your fvwm configuration file to invoke the script: AddToFunc FuncFvwmMenuDirectory + I PipeRead "fvwm-menu-directory -d '$0'" More complex example: # AddToFunc FuncFvwmMenuDirectory # + I PipeRead "fvwm-menu-directory -d '$0' -x 'Eterm -g 80x40 -e' \\ -a -l -o 6 --exec-app --exec-title 'tcsh -l' --exec-file 'vim -R' \\ -t 'Go to: %d' --wm-icons" And put this in the menu from which you want to pop-up the directory menus: AddToMenu SomeMenu MissingSubmenuFunction FuncFvwmMenuDirectory + "Home Directory" Popup $[HOME] + "Httpd Directory" Popup /home/httpd Note: please use absolute path names. It is a good idea to set the menu pop-up delay to something positive and enable busy cursor MenuStyle * PopupDelayed, PopupDelay 200 BusyCursor DynamicMenu True in your configuration file when using this script for better results. Another interesting usage (C<--reuse> or C<-r> is mandatary for this): AddToMenu Browser + DynamicPopupAction PipeRead \\ "fvwm-menu-directory -r -na Browser -d / -s" AddToMenu SomeMenu "My Browser" Menu Browser Here the C<--dir> parameter (starting directory) is ignored if there is ~/.fvwm/.fvwm-menu-directory.dir file, which you can delete. =head1 AUTHORS Inspired on 1999-06-07 by Dominik Vogt <domivogt@fvwm.org>. Rewritten on 1999-08-05 by Mikhael Goikhman <migo@homemail.com>. =head1 COPYING The script is distributed by the same terms as fvwm itself. See GNU General Public License for details. =head1 BUGS Report bugs to fvwm-bug@fvwm.org. =cut # *************************************************************************** ���������������������������������������������������������������������������������������fvwm-2.7.0/bin/fvwm-config.1������������������������������������������������������������������������0000644�0001750�0001750�00000006100�14324316007�012471� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" @(#)fvwm-2.7.0 19 October 2022 .de EX \"Begin example .ne 5 .if n .sp 1 .if t .sp .5 .nf .in +.5i .. .de EE .fi .in -.5i .if n .sp 1 .if t .sp .5 .. .ta .3i .6i .9i 1.2i 1.5i 1.8i .TH fvwm-config 1 "19 October 2022 (2.7.0)" Fvwm "Fvwm Modules" .UC .SH NAME fvwm-config \- query an existing fvwm installation .SH SYNOPSIS .B fvwm-config .RI [ --help ] .RI [ --version ] .RI [ --info ] .RI [ --prefix ] .RI [ --exec-prefix ] .RI [ --bindir ] .RI [ --datadir ] .RI [ --libexecdir ] .RI [ --sysconfdir ] .RI [ --mandir ] .RI [ --localedir ] .RI [ --fvwm-moduledir ] .RI [ --fvwm-datadir ] .RI [ --fvwm-perllibdir ] .RI [ --default-imagepath ] .RI [ --default-userdir ] .RI [ --fvwm-exe ] .RI [ --supports ] .RI [ --supports-<feature> ] .SH DESCRIPTION .B fvwm-config is a shell script that provides an information about the fvwm version, installation directories, built-in paths and supported features. .SH OPTIONS .B fvwm-config prints to the standard output in all options. Both short and long GNU-like option names may be used. .TP .B -h --help -? prints the short usage .TP .B -v --version -V prints the version .TP .B -i --info prints the full info page .TP .B -P --prefix prints the installation prefix .TP .B -E --exec-prefix prints the installation exec-prefix .TP .B -B --bindir prints the installation bindir .TP .B -D --datadir prints the installation datadir .TP .B -L --libexecdir prints the installation libexecdir .TP .B -S --sysconfdir prints the installation sysconfdir .TP .B -M --mandir prints the installation mandir .TP .B -O --localedir prints the installation localedir .TP .B -m --fvwm-moduledir prints FVWM_MODULEDIR, where the modules are installed .TP .B -d --fvwm-datadir prints FVWM_DATADIR, where the system wide configs are installed .TP .B -p --fvwm-perllibdir prints FVWM_PERLLIBDIR, where the perl library is installed .TP .B -I --default-imagepath prints the built-in ImagePath .TP .B -U --default-userdir prints the default FVWM_USERDIR, note: $HOME is not expanded .TP .B -e --fvwm-exe prints the fvwm executable name (in bindir) .TP .B -s --supports lists all supported features, one per line .TP .BI --supports- <feature> prints nothing, returns: 0 if the .I <feature> is supported, 100 if not, 200 if unknown. All or supported feature names may be found using .IR --info " or " --supports respectively. .TP .SH USAGE Here are some real life usages. Checks for xft support: .EX if fvwm-config --supports-xft; then echo 1; else echo 0; fi .EE .I fvwm-themes package checks for the correct .I fvwm version installed using: .EX fvwm-config --version .EE and tries to use the same installation directories: .EX fvwm-config --bindir --mandir --fvwm-datadir .EE A way to find the full path to the fvwm executable: .EX echo `fvwm-config --bindir`/`fvwm-config --fvwm-exe` .EE A way to start modules in perl: .EX use lib `fvwm-config -p | tr -d '\n'`; use FVWM::Module; .EE For a more human readable output, try: .EX fvwm-config --info .EE .SH COPYING .B fvwm-config is a part of fvwm package and distributed by the same terms, see GNU GPL. .SH AUTHOR Mikhael Goikhman <migo@homemail.com> ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/bin/fvwm-config.1.in���������������������������������������������������������������������0000644�0001750�0001750�00000006111�14147024700�013077� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" @(#)@PACKAGE@-@VERSION@ @RELDATELONG@ .de EX \"Begin example .ne 5 .if n .sp 1 .if t .sp .5 .nf .in +.5i .. .de EE .fi .in -.5i .if n .sp 1 .if t .sp .5 .. .ta .3i .6i .9i 1.2i 1.5i 1.8i .TH fvwm-config 1 "@RELDATELONG@ (@VERSION@)" Fvwm "Fvwm Modules" .UC .SH NAME fvwm-config \- query an existing fvwm installation .SH SYNOPSIS .B fvwm-config .RI [ --help ] .RI [ --version ] .RI [ --info ] .RI [ --prefix ] .RI [ --exec-prefix ] .RI [ --bindir ] .RI [ --datadir ] .RI [ --libexecdir ] .RI [ --sysconfdir ] .RI [ --mandir ] .RI [ --localedir ] .RI [ --fvwm-moduledir ] .RI [ --fvwm-datadir ] .RI [ --fvwm-perllibdir ] .RI [ --default-imagepath ] .RI [ --default-userdir ] .RI [ --fvwm-exe ] .RI [ --supports ] .RI [ --supports-<feature> ] .SH DESCRIPTION .B fvwm-config is a shell script that provides an information about the fvwm version, installation directories, built-in paths and supported features. .SH OPTIONS .B fvwm-config prints to the standard output in all options. Both short and long GNU-like option names may be used. .TP .B -h --help -? prints the short usage .TP .B -v --version -V prints the version .TP .B -i --info prints the full info page .TP .B -P --prefix prints the installation prefix .TP .B -E --exec-prefix prints the installation exec-prefix .TP .B -B --bindir prints the installation bindir .TP .B -D --datadir prints the installation datadir .TP .B -L --libexecdir prints the installation libexecdir .TP .B -S --sysconfdir prints the installation sysconfdir .TP .B -M --mandir prints the installation mandir .TP .B -O --localedir prints the installation localedir .TP .B -m --fvwm-moduledir prints FVWM_MODULEDIR, where the modules are installed .TP .B -d --fvwm-datadir prints FVWM_DATADIR, where the system wide configs are installed .TP .B -p --fvwm-perllibdir prints FVWM_PERLLIBDIR, where the perl library is installed .TP .B -I --default-imagepath prints the built-in ImagePath .TP .B -U --default-userdir prints the default FVWM_USERDIR, note: $HOME is not expanded .TP .B -e --fvwm-exe prints the fvwm executable name (in bindir) .TP .B -s --supports lists all supported features, one per line .TP .BI --supports- <feature> prints nothing, returns: 0 if the .I <feature> is supported, 100 if not, 200 if unknown. All or supported feature names may be found using .IR --info " or " --supports respectively. .TP .SH USAGE Here are some real life usages. Checks for xft support: .EX if fvwm-config --supports-xft; then echo 1; else echo 0; fi .EE .I fvwm-themes package checks for the correct .I fvwm version installed using: .EX fvwm-config --version .EE and tries to use the same installation directories: .EX fvwm-config --bindir --mandir --fvwm-datadir .EE A way to find the full path to the fvwm executable: .EX echo `fvwm-config --bindir`/`fvwm-config --fvwm-exe` .EE A way to start modules in perl: .EX use lib `fvwm-config -p | tr -d '\n'`; use FVWM::Module; .EE For a more human readable output, try: .EX fvwm-config --info .EE .SH COPYING .B fvwm-config is a part of fvwm package and distributed by the same terms, see GNU GPL. .SH AUTHOR Mikhael Goikhman <migo@homemail.com> �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/bin/fvwm-menu-headlines.1����������������������������������������������������������������0000644�0001750�0001750�00000034447�14147024700�014140� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" Automatically generated by Pod::Man 2.16 (Pod::Simple 3.02) .\" .\" Standard preamble: .\" ======================================================================== .de Sh \" Subsection heading .br .if t .Sp .ne 5 .PP \fB\\$1\fR .PP .. .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .ie \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .el \{\ . de IX .. .\} .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "fvwm-menu-headlines 1" .TH fvwm-menu-headlines 1 "2009-03-22" "2.5.28 (from cvs)" "Fvwm Utilities" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" fvwm\-menu\-headlines \- builds headlines menu definition for fvwm .SH "SYNOPSIS" .IX Header "SYNOPSIS" \&\fBfvwm-menu-headlines\fR [ \fB\-\-help\fR|\fB\-h\fR|\fB\-?\fR ] [ \fB\-\-version\fR|\fB\-V\fR ] [ \fB\-\-info\fR [site] ] [ \fB\-\-site\fR|\fB\-s\fR site ] [ \fB\-\-name\fR|\fB\-n\fR name ] [ \fB\-\-title\fR|\fB\-t\fR title ] [ \fB\-\-item\fR item ] [ \fB\-\-exec\fR|\fB\-e\fR exec-command ] [ \fB\-\-command\fR|\fB\-e\fR fvwm-command ] [ \fB\-\-icon\-title\fR icon ] [ \fB\-\-icon\-item\fR icon ] [ \fB\-\-icon\-home\fR icon ] [ \fB\-\-icon\-error\fR icon ] [ \fB\-\-wm\-icons\fR ] [ \fB\-\-frontpage\fR [where] ] [ \fB\-\-proxy\fR|\fB\-p\fR host:port ] [ \fB\-\-file\fR [file] ] [ \fB\-\-fake\fR [file] ] [ \fB\-\-timeout\fR seconds ] .SH "DESCRIPTION" .IX Header "DESCRIPTION" This configurable perl script builds an fvwm menu definition for headlines of popular news web sites: FreshMeat, Slashdot, LinuxToday, DaemonNews, GNOME-News, KDE-News, RootPrompt, LinuxFr, ThinkGeek, \s-1CNN\s0, \s-1BBC\s0 and more. .PP It is possible to specify a customized menu item format, change a command (usually launching a browser) and add menu icons (there is a support for the wm-icons package). .SH "OPTIONS" .IX Header "OPTIONS" .IP "\fB\-\-help\fR" 4 .IX Item "--help" show the help and exit .IP "\fB\-\-version\fR" 4 .IX Item "--version" show the version and exit .IP "\fB\-\-info\fR [site]" 4 .IX Item "--info [site]" if site name is given print the site specific info, otherwise print all site names .IP "\fB\-\-site\fR site" 4 .IX Item "--site site" defile a web site, headlines of which to show, this option also can be used together with \-\-help to get new defaults. Default site: freshmeat. .IP "\fB\-\-name\fR name" 4 .IX Item "--name name" define menu name (default is \*(L"MenuHeadlinesFreshmeat\*(R") .IP "\fB\-\-title\fR title" 4 .IX Item "--title title" define menu title (default is \*(L"Freshmeat Headlines\*(R"). .IP "\fB\-\-item\fR label-format" 4 .IX Item "--item label-format" .PD 0 .IP "\fB\-\-exec\fR command-format" 4 .IX Item "--exec command-format" .PD define format for menu item or command (what is shown and what is executed when the item is chosen). Default label is '%h\et%[(%Y\-%m\-%d \f(CW%H:\fR%M)]'. \s-1TAB\s0 can be specified as '\et', but in .fvwm2rc you should specify a double backslash or a real \s-1TAB\s0. .Sp Format specifiers for a headline format: .Sp .Vb 11 \& %h \- headline \& %u \- url \& %d \- date in the native format (that site backend supplied) \& %[strftime\-argument\-string] \- date/time, see strftime(3) \& the date/time is represented according to the local time; \& date and/or time fields that can\*(Aqt be guessed are stripped \& Example: %[|%d %B %Y| %H:%M %S] \& If site supplied only date \- this becomes %[|%d %B %Y|], \& if site supplied no date \- this becomes an empty string. \& %{name} \- site specific named value, like %{comments} \& %(text) \- arbitrary text, good for escaping or aligning .Ve .Sp These specifiers can receive an optional integer size, positive for right adjusted string or negative for left adjusted, example: \f(CW%8x\fR; and optional *num or *\-num, which means to leave only the first or last (if minus) num of chars, the num must be greater than 3, since the striped part is replaced with \*(L"...\*(R", example: %*30x. Both can be combined: %\-10*\-20x, this instructs to get only the 20 last characters, but if the length is less then 10 \- to fill with up to 10 spaces on the right. .Sp Example: .Sp .Vb 1 \& \-\-exec "iceweasel \-remote \*(AqopenURL(%u, new\-window)\*(Aq || iceweasel \*(Aq%u\*(Aq" .Ve .IP "\fB\-\-command\fR command-format" 4 .IX Item "--command command-format" like \fB\-\-exec\fR above, but enables to specify any fvwm command, for example, \*(L"Function FuncFvwmShowURL '%u'\*(R" not only Exec. .Sp In fact, \-\-exec=\*(L"mozilla '%u'\*(R" is equivalent to \-\-command=\*(L"Exec mozilla '%u'\*(R" .IP "\fB\-\-icon\-title\fR icon" 4 .IX Item "--icon-title icon" .PD 0 .IP "\fB\-\-icon\-item\fR icon" 4 .IX Item "--icon-item icon" .IP "\fB\-\-icon\-home\fR icon" 4 .IX Item "--icon-home icon" .IP "\fB\-\-icon\-error\fR icon" 4 .IX Item "--icon-error icon" .PD define menu icon for title, regular item, frontpage item and error item respectively. Default is no menu icons (equivalent to an empty icon argument). .IP "\fB\-\-wm\-icons\fR" 4 .IX Item "--wm-icons" define icon names suitable for use with wm-icons package. Currently this is equivalent to: \-\-icon\-title '' \-\-icon\-item menu/information.xpm \-\-icon\-home menu/home.xpm \-\-icon\-error menu/choice\-no.xpm. .IP "\fB\-\-frontpage\fR [where]" 4 .IX Item "--frontpage [where]" add the site frontpage item to the menu. Optional value can be used to specify where this item will be placed in the menu \- 'top' or 't', 'bottom' or 'b'. .IP "\fB\-\-proxy\fR host[:port]" 4 .IX Item "--proxy host[:port]" define a proxy to use. Example: \-\-proxy proxy.inter.net:3128 .IP "\fB\-\-file\fR [file]" 4 .IX Item "--file [file]" write the menu output to specified file. If no filename is given with this option (or empty filename), the default filename \s-1WORK_HOME/SITE\s0.menu is used. Without this option or with '\-' filename, the menu output is written to standard output. .IP "\fB\-\-fake\fR [file]" 4 .IX Item "--fake [file]" don't connect to the host using \s-1HTTP\s0 protocol, instead, read from \s-1WORK_HOME/SITE\s0.in file. The following reads input from freshmeat.in (downloaded http://freshmeat.net/backend/recentnews.txt) and saves output to segfault.menu (both files are in \s-1WORK_HOME\s0): fvwm-menu-headlines \-\-site freshmeat \-\-fake \-\-file .IP "\fB\-\-timeout\fR seconds" 4 .IX Item "--timeout seconds" limit a line reading from a socket to this timeout, the default timeout is 20 seconds. .PP \&\s-1WORK_HOME\s0 of this script is ~/.fvwm/.fvwm\-menu\-headlines. It is created if needed. .PP Option parameters can be specified either using '=' or in the next argument. Short options are ok if not ambiguous: \f(CW\*(C`\-h\*(C'\fR, \f(CW\*(C`\-t\*(C'\fR; but be careful with short options, what is now unambiguous, can become ambiguous in the next versions. .SH "USAGE" .IX Header "USAGE" 1. One of the ways to use this script is to define a crontab entry to run the script every hour or so for every monitored site: .PP .Vb 3 \& 0,30 * * * * fvwm\-menu\-headlines \-\-file \-\-site freshmeat \& 1,31 * * * * fvwm\-menu\-headlines \-\-file \-\-site linuxtoday \& 2,32 * * * * fvwm\-menu\-headlines \-\-file \-\-site slashdot .Ve .PP Then add these lines to your fvwm configuration file: .PP .Vb 3 \& DestroyFunc FuncFvwmMenuHeadlines \& AddToFunc FuncFvwmMenuHeadlines \& + I Read "$HOME/.fvwm/.fvwm\-menu\-headlines/$0.menu" \& \& DestroyMenu MenuHeadlines \& AddToMenu MenuHeadlines "Headlines" Title \& + MissingSubmenuFunction FuncFvwmMenuHeadlines \& + "FreshMeat" Popup freshmeat \& + "LinuxToday" Popup linuxtoday \& + "Slashdot" Popup slashdot .Ve .PP 2. Another way to use this script (only if you have fast network/proxy) is to run it every time you want to open your Headlines submenus. (Note, the submenu that is once created is not reloaded, use \*(L"Reset all\*(R".) .PP In this case your fvwm configuration lines could be: .PP .Vb 4 \& DestroyFunc FuncFvwmMenuHeadlines \& AddToFunc FuncFvwmMenuHeadlines \& + I PipeRead "fvwm\-menu\-headlines \-\-site $0" \& #+ I Schedule 900000 DestroyMenu $0 # reset generated menu in 15 minutes \& \& DestroyMenu MenuHeadlines \& AddToMenu MenuHeadlines "Headlines" Title \& + MissingSubmenuFunction FuncFvwmMenuHeadlines \& + "FreshMeat" Popup freshmeat \& + "Slashdot" Popup slashdot \& + "LinuxToday" Popup linuxtoday \& + "GNOME News" Popup gnome\-news \& + "KDE News" Popup kde\-news \& + "" Nop \& + "Reset all" FuncResetHeadlines \& \& DestroyFunc FuncResetHeadlines \& AddToFunc FuncResetHeadlines \& + I DestroyMenu freshmeat \& + I DestroyMenu linuxtoday \& + I DestroyMenu slashdot \& + I DestroyMenu gnome\-news \& + I DestroyMenu kde\-news .Ve .PP And finally, add \*(L"Popup MenuHeadlines\*(R" somewhere. .PP 3. Here is a usual usage. Use FvwmConsole or FvwmCommand to run fvwm commands from a shell script. Every time you want headlines from some site, execute (give any additional options if you want): .PP .Vb 3 \& PipeRead "fvwm\-menu\-headlines \-\-site newsforge \-\-name MenuHeadlinesNewsForge" \& # this may take several seconds, you may use: BusyCursor Read true \& Popup MenuHeadlinesNewsForge .Ve .SH "HOW TO ADD SITE HEADLINES" .IX Header "HOW TO ADD SITE HEADLINES" It is possible to add user defined site headlines without touching the script itself. Put your perl extensions to the file WORK_HOME/extension.pl. For each site add something similar to: .PP .Vb 8 \& $site_info\->{\*(Aqmyslashdot\*(Aq} = { \& \*(Aqname\*(Aq => "MySlashdot", \& \*(Aqhost\*(Aq => "myslashdot.org", \& \*(Aqpath\*(Aq => "/myslashdot.xml", \& \*(Aqfunc\*(Aq => \e&process_my_slashdot, \& # the following string is only used in \-\-info \& \*(Aqflds\*(Aq => \*(Aqtime, title, department, topic, author, url\*(Aq, \& }; \& \& sub process_my_slashdot () { \& return process_xml( \& \*(Aqstory\*(Aq, \& # mandatory \*(Aqh\*(Aq, \*(Aqu\*(Aq and \*(Aqd\*(Aq aliases or undef \& { \*(Aqh\*(Aq => \*(Aqtitle\*(Aq, \*(Aqu\*(Aq => \*(Aqurl\*(Aq, \*(Aqd\*(Aq => \*(Aqtime\*(Aq }, \& sub ($) { # convert \*(Aqd\*(Aq string to (y, m, d, H, M, S) \& $_[0] =~ /(\ed+)\-(\ed+)\-(\ed+) (\ed+):(\ed+):(\ed+)/; \& ($1, ($2 || 0) \- 1, $3, $4, $5, $6); \& }, +0, # timezone offset; already in UTC \& ); \& } \& \& 1; .Ve .SH "AUTHORS" .IX Header "AUTHORS" This script is inspired by WMHeadlines v1.3 by: .PP .Vb 2 \& Jeff Meininger <jeffm@boxybutgood.com> \& (http://rive.boxybutgood.com/WMHeadlines/). .Ve .PP Reimplemented for fvwm and heavily enhanced by: .PP .Vb 1 \& Mikhael Goikhman <migo@homemail.com>, 16 Dec 1999. .Ve .SH "COPYING" .IX Header "COPYING" The script is distributed by the same terms as fvwm itself. See \s-1GNU\s0 General Public License for details. .SH "BUGS" .IX Header "BUGS" I try to keep all supported site info up to date, but sites often go down, change their backend formats, change their httpd responses, just stop to post news and so on; the script in the latest cvs may be more up to date. .PP The headline times may be off by one hour or more, since the time is displayed for your local time zone, and the time zone of the original time in the site backend output is often guessed (sometimes incorrectly); similarly it is guessed whether to apply the daylight saving correction. .PP Report bugs to fvwm\-bug@fvwm.org. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/bin/fvwm-menu-desktop.1.in���������������������������������������������������������������0000644�0001750�0001750�00000037245�14147024700�014261� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" t .\" @(#)@PACKAGE@-@VERSION@ @RELDATELONG@ .de EX \"Begin example .ne 5 .if n .sp 1 .if t .sp .5 .nf .in +.5i .. .de EE .fi .in -.5i .if n .sp 1 .if t .sp .5 .. .ta .3i .6i .9i 1.2i 1.5i 1.8i .TH fvwm-menu-desktop 1 "@RELDATELONG@ (@VERSION@)" Fvwm "Fvwm Modules" .UC .SH NAME fvwm-menu-desktop \- Reads XDG menu files and creates Fvwm menus .SH SYNOPSIS fvwm-menu-desktop [ \fB\-\-help\fR|\fB\-h\fR ] [ \fB\-\-version\fR ] [ \fB\-\-install\-prefix\fR \fIDIR\fR ] [ \fB\-\-desktop\fR \fINAME\fR ] [ \fB\-\-menu\-type\fR \fINAME\fR ] [ \fB\-\-theme\fR \fINAME\fR ] [ \fB\-\-with\-titles\fR|\fB\-w\fR ] [ \fB\-\-without\-titles\fR ] [ \fB\-\-enable\-mini\-icons\fR ] [ \fB\-\-size\fR|\fB\-s\fR \fINUM\fR ] [ \fB\-\-mini\-icon\-dir\fR \fIDIR\fR ] [ \fB\-\-app\-icon\fR \fINAME\fR ] [ \fB\-\-dir\-icon\fR \fINAME\fR ] [ \fB\-\-title\fR|\fB\-t\fR \fINAME\fR ] [ \fB\-\-insert\-in\-menu\fR \fINAME\fR ] [ \fB\-\-get\-menus\fR \fIall\fR|\fIdesktop\fR ] [ \fB\-\-set\-menus\fR \fImenu_paths\fR ] [ \fB\-\-all\-menus\fR ] [ \fB\-\-include\-items\fR \fINAME\fR ] [ \fB\-\-regen\-cmd\fR \fICMD\fR ] [ \fB\-\-term\-cmd\fR \fICMD\fR ] [ \fB\-\-dynamic\fR ] [ \fB\-\-menu-error\fR|\fB\-e\fR ] [ \fB\-\-verbose\fR|\fB\-v\fR ] .SH DESCRIPTION This is a python script which parses XDG menus definitions to build corresponding fvwm menus. This script depends on python-xdg to run. .SH OPTIONS .IP "Main Options" .IP "\fB\-\-help\fR" Show the help and exit. .IP "\fB\-\-version\fR" Show the version and exit. .IP "\fB\-\-get\-menus\fR \fIall\fR|\fIdesktop\fR" Prints a space separated list of full menu paths found on the system. \fIall\fR will print all menus found on the system except empty ones. \fIdesktop\fR will print the menu(s) that would be generated by the script. No menu generation is done. .IP "\fB\-\-desktop\fR \fINAME\fR" Optional parameter to set the \fINAME\fR of the desktop XDG .menu file(s) to use. This option will override any default menus set via \fBFvwmForm-XDGMenu-Config\fR and cause the script to find menus in which \fINAME\fR is a part of the file name. Possible names are: \fIgnome\fR, \fIkde\fR, \fIxfce\fR, \fIlxde\fR, \fIdebian\fR, etc. This option can be used in conjunction with \fB\-\-menu\-type\fR to control which .menu file(s) are used. .IP "\fB\-\-menu\-type\fR \fINAME\fR" Optional parameter to set the \fINAME\fR of the XDG menu type to use. This option will override any default menus set via \fBFvwmForm-XDGMenu-Config\fR and cause the script to find menus in which \fINAME\fR is a part of the file name. Possible \fINAME\fR types could be: \fIapplications\fR, \fIsettings\fR, \fIpreferences\fR, etc. When used in conjunction with \fB\-\-desktop\fR, only menus whose file name matches '*destkop*menutype*' are found. If no menus are found, the script exits with an error. .IP "\fB\-\-all\-menus\fR" This option will build all menus found on the system. If used in conjunction with \fB\-\-desktop\fR or \fB\-\-menu\-type\fR this will build all menus matching those settings. .IP "\fB\-\-install-prefix\fR \fIDIR\fR" Optional parameter to override the standard locations for XDG menu definitions. Tells \fBfvwm-menu-desktop\fR to look in \fIDIR\fR for .menu files instead of the standard locations /etc/xdg/menus (and $HOME/.config/menus if it exists). .IP "\fB\-\-with\-titles\fR|\fB\-w\fR" If this option is set menus are generated with titles. This is the default. This option can be used to override the \fBFvwmForm-XDGMenu-Config\fR default setting. .IP "\fB\-\-without\-titles\fR" If this option is set menus are generated without titles. The default is to generate with titles. .IP "\fB\-\-title\fR|\fB\-t\fR \fINAME\fR " Option to define the menu title \fINAME\fR of the top menu used by Fvwm's \fBMenu\fR or \fBPopup\fR commands. Default is "XDGMenu". .IP "\fB\-\-include\-items\fR \fINAME\fR " This option controls if the additional menu items 'Regenerate' and 'Configure' are included in the top level menu. \fINAME\fR can be one of \fIregenerate\fR, \fIconfig\fR, \fIboth\fR, or \fInone\fR. The default is \fIboth\fR. .IP "\fB\-\-regen\-cmd\fR \fICMD\fR " This option sets the fvwm command \fICMD\fR that is run when the menu item \&'Regenerate' is selected. The default is "PipeRead `fvwm-menu-desktop`". .IP "\fB\-\-term\-cmd\fR \fICMD\fR " This option sets the terminal emulator command \fICMD\fR that is used to to run terminal applications in. \fICMD\fR needs to end with an execute option, such as xterm's -e option, which will run the command that is appended to \fICMD\fR. The default is "xterm -e". .IP "\fB\-\-dynamic\fR " This option is to be used with creating dynamic menus using \fBDynamicPopUpAction\fR and \fBDynamicPopDownAction\fR. This adds a 'recreate' to the \fBDestroyMenu\fR command on the top level menu so those actions are not Destroyed when the menu is regenerated. .IP "\fB\-\-insert\-in\-menu\fR \fINAME\fR" Option to insert generated menu(s) \fBIN\fR a menu \fINAME\fR (its top title). This option makes it so the top level menu is not Destroyed and the items are added to the end. Note menus regenerated with this option will append the menu items at the end of the existing menu. Each time the menu is regenerated new menu items appear giving a growing menu of duplicate items. You have to regenerate the whole menu via a function or restart fvwm. See \fBEXAMPLES\fR below for some solutions. .IP "\fB\-\-set\-menus\fR \fImenu_paths\fR" Generates all menus listed in a space separated list of full menu paths. This option overrides any defaults and \fB\-\-desktop\fR|\fB\-\-menu\-type\fR settings. .IP "\fB\-\-menu-error\fR |\fB\-t\fR" If this option is present and python-xdg is not found, the script will print the error in the generated menu. Used in the default-config. .IP "\fB\-\-verbose\fR" Enables additional information printouts on STDERR. .IP "Icons Options" By default, fvwm-menu-desktop builds menus without mini\-icons. To enable mini\-icons use the following options. If ImageMagick is installed on the system, the script will resize and copy the icons to $FVWM_USERDIR/.icons. This can take awhile. You should be prepared to wait the first time you generate the icons. Once the icons have been generated the script should run faster. If it is still to slow using icons, see \fBEXAMPLES\fR for ways to limit how often the menu is generated to speed things up. .IP "\fB\-\-enable\-mini\-icons\fR" This option enables mini\-icons in the menus. If set, 24x24 mini-icons are used. If the specified icon isn't that size it will be converted if \fBImageMagick\fR is installed and saved in $HOME/.fvwm/icons or to the directory specified with \-\-mini\-icon\-dir option. Otherwise no icon appears in the menu for that entry. With most distributions, all the menu entries will have mini-icons appropriate to the application. .IP "\fB\-\-theme\fR \fINAME\fR" Defines the used icon theme. Default is \fIgnome\fR but all others found in /usr/share/icons could be used except the \fIhicolor\fR theme because it's the default fallback theme if no icon is found. .IP "\fB\-\-size\fR|\fB\-s\fR \fINUM\fR" If \-\-enable\-mini\-icons is used the \fIsize\fR of the icons can changed with this parameter. Default is 24. .IP "\fB\-\-mini\-icon\-dir\fR \fIDIR\fR" When the right size mini-icon isn't available, fvwm-menu-desktop creates icons with the right size in $HOME/.fvwm/icons. If you don't want to use the default directory, $HOME/.fvwm/icons, use this option to specify a different folder. .IP "\fB\-\-app\-icon\fR \fINAME\fR" Sets the default application icon if no others are found. Default is \&'gnome-applications'. .IP "\fB\-\-dir\-icon\fR \fINAME\fR" Sets the default directory icon if no others are found. Default is \&'gnome-fs-directory'. .SH USAGE \fBfvwm-menu-desktop\fR outputs XDG .menu files in the syntax of fvwm menus. When \fBfvwm-menu-desktop\fR is run with no options, it will load defaults from the \fBFvwmForm-XDGMenu-Config\fR file (see below) then search your system for suitable menu file(s). To see which menus are available on your system run: .RS .EX fvwm-menu-desktop --get-menus all .EE .RE If no menus are found you may not have any installed on your system. By default menus are stored as *.menu files in /etc/xdg/menus, $HOME/.config/menus or the location set in $XDG_MENU_PREFIX. You can use \fB\-\-install\-prefix\fR to specify another location search for menus. Though a combination of command line options and the \fBFvwmForm-XDGMenu-Config\fR settings, \fBfvwm-menu-desktop\fR can generate any combination of the menus found. To get a list of what menu(s) would be generated use the \fB--get-menus\fR \fIdesktop\fR option. The following will list all menus generated if \fBfvwm-menu-desktop\fR was run with no options. .RS .EX fvwm-menu-desktop --get-menus desktop .EE .RE \fBfvwm-menu-desktop\fR determines which menu(s) to generate as follows .RS If no config file is found, all menus will be weighted and the script will generate the best (highest weight) menu found. If a config file is found (and override options are not used) the script will generate all menus selected in \fBFvwmForm-XDGMenu-Config\fR. \fB--desktop\fR, \fB--menu-type\fR, \fB--set-menus\fR and \fB--all-menus\fR will override any menus selected in \fBFvwmForm-XDGMenu-Config\fR. \fB--desktop\fR and \fB--menu-type\fR will only include menus whose name matches '*desktop*menutype*'. If used with \fB--all-menus\fR, all matching menus are generated. If used without \fB--all-menus\fR, only the highest weighted menu is generated. \fB--set-menus\fR generates menus from the list of full path menu file names. \fB--all-menus\fR by itself will generate all menus found. .RE By default \fBfvwm-menu-desktop\fR will generate a menu whose top level name is "XDGMenu". To tell fvwm to read the output of \fBfvwm-menu-desktop\fR to create the menu XDGMenu add the following to your fvwm config file: .RS .EX PipeRead 'fvwm-menu-desktop' .EE .RE \fBWarning:\fR Depending on the options used this command may be slow and fvwm will pause until this command is complete. See \fBEXAMPLES\fR below for more details and possible workarounds. Once the menu is generated you can open the menu by using the command "Menu XDGMenu". You can also include this in the MenuFvwmRoot menu by: .RS .EX AddToMenu MenuFvwmRoot "XDG Menu" Popup XDGMenu .EE .RE \fBfvwm-menu-desktop\fR can be configured though both command line options and a \fBFvwmForm\fR GUI to customize the menu(s) that get generated. .SH GUI \fBFvwmForm-XDGMenu-Config\fR is a \fBFvwmForm\fR interface that can be used to configure the defaults for \fBfvwm-menu-desktop\fR. You can access this from the "Configure" item in the top level menu that is generated or run the following from within \fBFvwmConsole\fR .RS .EX Module FvwmPerl -l fvwm-menu-desktop-config.fpl .EE .RE This form can be used to select which menu(s) get generated by default along with setting many (but not all) of the available options. When you click "Save Settings" the form will write a config file located at $FVWM_USERDIR/.FvwmForm-XDGMenu-Config that \fBfvwm-menu-desktop\fR will parse for defaults when run. See the help inside of \fBFvwmForm-XDGMenu-Config\fR for more information. .SH EXAMPLES There are many ways to setup when fvwm runs \fBfvwm-menu-desktop\fR to generate the menu. One method is to just generate the menu when fvwm loads and then use the GUI config tool to change any options. To do this you only need to add the following to the fvwm config file: .RS .EX AddToMenu MenuFvwmRoot "XDG Menu" Popup XDGMenu PipeRead 'fvwm-menu-desktop' .EE .RE The menu is created once when fvwm loads. Since menu creation can sometimes be slow, this could cause fvwm to take longer to load than one wants. The menu is only generated when fvwm starts. If software is installed or removed you will have to select the 'Regenerate' option to rebuild the menu. One way to speed things up is to save the menu in a file and only generate the menu when 'Regenerate' is selected. To do this use \fB--regen-cmd\fR to call a custom function and write the menu to a file using a command like .RS .EX fvwm-menu-desktop --regen-cmd XDGRegen > $FVWM_USERDIR/.XDGMenu .EE .RE Then add the following to the fvwm config file to define the function XDGRegen. The second to last line will generate the menu if the menu file doesn't exist when fvwm starts. .RS .EX DestroyFunc XDGRegen AddToFunc XDGRegen + I PipeRead 'fvwm-menu-desktop --regen-cmd XDGRegen > \\ $[FVWM_USERDIR]/.XDGMenu; echo "Nop"' + I Read $[FVWM_USERDIR]/.XDGMenu Test (!f $[FVWM_USERDIR]/.XDGMenu) XDGRegen Read $[FVWM_USERDIR]/.XDGMenu .EE .RE Besides creating a top level menu, \fBfvwm-menu-desktop\fR can insert the menu into an existing menu using the \fB--insert-in-menu\fR option. For example one could create the menu MenuFvwmRoot and include the XDG items at the end. .RS .EX DestroyMenu MenuFvwmRoot AddToMenu MenuFvwmRoot "Fvwm" Title + "Item1" Action1 ... + "ItemN" ActionN + "" Nop PipeRead 'fvwm-menu-desktop --insert-in-menu MenuFvwmRoot' .EE .RE In this case the menu items are inserted at the end of the MenuFvwmRoot menu. If no items are in the menu, this menu becomes MenuFvwmRoot. The problem here is, that you have to restart fvwm or rebuild the whole menu to Regenerate it because menu items cannot be removed. To do this you could use a function like .RS .EX DestroyFunc XDGRegen AddToFunc XDGRegen + I DestroyMenu MenuFvwmRoot + I AddToMenu MenuFvwmRoot "Fvwm" Title + I AddToMenu MenuFvwmRoot "Item1" Action1 ... + I AddToMenu MenuFvwmRoot "ItemN" ActionN + I AddToMenu MenuFvwmRoot "" Nop + I PipeRead 'fvwm-menu-desktop --insert-in-menu MenuFvwmRoot \\ --regen-cmd XDGRegen' .EE .RE Fvwm can also create menus dynamically by using \fBDynamicPopUpAction\fR and/or \fBDynamicPopDownAction\fR. These commands when used with a Menu will run a Function when the menu is opened. For example one could create the menu XDGMenu when it is opened using .RS .EX AddToMenu XDGMenu "XDGMenu" Title + DynamicPopUpAction PipeRead 'fvwm-menu-desktop' .EE .RE This will create the menu when it is opened. One issue here is it will only create the menu the first time it is opened, and you still have to Regenerate the menu to see any changes. To create the menu each time it is open used the \fB--dynamic\fR option .RS .EX AddToMenu XDGMenu "XDGMenu" Title + DynamicPopUpAction PipeRead 'fvwm-menu-desktop \\ --dynamic --include-items config' + DynamicPopDownAction DestroyMenu recreate XDGMenu .EE .RE This will now Destroy the menu when it closed so it can be rebuilt the next time it is opened. The recreate flag doesn't completely destroy the menu keeping the DynamicPopUpAction and DynamicPopDownAction actions. The \fB--dynamic\fR flag includes the recreate option in the generated menus. To insert a menu into MenuFvwmRoot and still be dynamic you need to use a function that generates the whole menu. For example .RS .EX DestroyFunc GenRootMenu AddToFunc GenRootMenu + I DestroyMenu recreate MenuFvwmRoot + I AddToMenu MenuFvwmRoot "Fvwm" Title + I AddToMenu MenuFvwmRoot "Item1" Action1 ... + I AddToMenu MenuFvwmRoot "ItemN" ActionN + I AddToMenu MenuFvwmRoot "" Nop + PipeRead `fvwm-menu-desktop --insert-in-menu MenuFvwmRoot \\ --include-items config` AddToMenu MenuFvwmRoot "Fvwm" Title + DynamicPopUpAction GenRootMenu + DynamicPopDownAction DestroyMenu recreate MenuFvwmRoot .EE .RE .SH BUGS The whole process of creating menus from files is slow. Otherwise report bugs to the fvwm-workers mailing list <fvwm-workers@fvwm.org>. .SH AUTHORS This script is based on fvwm-xdg-menu.py written by Piotr Zielinski (http://www.cl.cam.ac.uk/~pz215/) who assigned Licence: GPL 2 Date: 03.12.2005. The script was reworked to replace the existing fvwm-menu-desktop perl script by the fvwm-workers. .SH COPYING The script is distributed by the same terms as fvwm itself. See GNU General Public License for details. �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/bin/fvwm-root.c��������������������������������������������������������������������������0000644�0001750�0001750�00000017525�14147024700�012305� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see: <http://www.gnu.org/licenses/> */ #include "config.h" #include <stdio.h> #include <signal.h> #include <X11/Xos.h> #include <X11/Xatom.h> #include "libs/fvwmlib.h" #include "libs/Picture.h" #include "libs/Graphics.h" #include "libs/Fsvg.h" int save_colors = 0; Display *dpy; int screen; Window root; char *display_name = NULL; Pixmap rootImage = None; Bool NoDither = False; Bool Dither = False; Bool NoColorLimit = False; int opt_color_limit = -1; Bool use_our_color_limit = False; void usage(int verbose) { FILE *output = verbose ? stdout : stderr; fprintf( output, "fvwm-root version %s with support for: XBM" #ifdef XPM ", XPM" #endif #ifdef HAVE_PNG ", PNG" #endif #ifdef HAVE_RSVG ", SVG" #endif "\n", VERSION); fprintf(output, "\nUsage: fvwm-root [ options ] file\n"); if (verbose) { fprintf(output, "Options:\n" "\t--dither\n" "\t--no-dither\n" "\t--retain-pixmap\n" "\t--no-retain-pixmap\n" "\t--color-limit l\n" "\t--no-color-limit\n" "\t--dummy\n" "\t--no-dummy\n" "\t--help\n" "\t--version\n"); } } int SetRootWindow(char *tline) { Pixmap shapeMask = None, temp_pix = None, alpha = None; int w, h; int depth; int nalloc_pixels = 0; Pixel *alloc_pixels = NULL; char *file_path; FvwmPictureAttributes fpa; if (use_our_color_limit) { PictureColorLimitOption colorLimitop = {-1, -1, -1, -1, -1}; colorLimitop.color_limit = opt_color_limit; PictureInitCMapRoot( dpy, !NoColorLimit, &colorLimitop, True, True); } else { /* this use the default visual (not the fvwm one) as * getenv("FVWM_VISUALID") is NULL in any case. But this use * the same color limit than fvwm. * This is "broken" when fvwm use depth <= 8 and a private * color map (i.e., fvwm is started with the -visual{ID} * option), because when fvwm use a private color map the * default color limit is 244. There is no way to know here if * getenv("FVWM_VISUALID") !=NULL. * So, in this unfortunate case the user should use the * --color-limit option */ PictureInitCMap(dpy); } flib_init_graphics(dpy); /* try built-in image path first, but not before pwd */ PictureSetImagePath(".:+"); file_path = PictureFindImageFile(tline, NULL, R_OK); if (file_path == NULL) { file_path = tline; } fpa.mask = FPAM_NO_ALLOC_PIXELS | FPAM_NO_ALPHA; if (Pdepth <= 8 && !NoDither) { fpa.mask |= FPAM_DITHER; } else if (Pdepth <= 16 && Dither) { fpa.mask |= FPAM_DITHER; } if (NoColorLimit) { fpa.mask |= FPAM_NO_COLOR_LIMIT; } if (!PImageLoadPixmapFromFile( dpy, root, file_path, &temp_pix, &shapeMask, &alpha, &w, &h, &depth, &nalloc_pixels, &alloc_pixels, 0, fpa)) { fprintf( stderr, "[fvwm-root] failed to load image file '%s'\n", tline); return -1; } if (depth == Pdepth) { rootImage = temp_pix; } else { XGCValues gcv; GC gc; gcv.background= WhitePixel(dpy, screen); gcv.foreground= BlackPixel(dpy, screen); gc = fvwmlib_XCreateGC( dpy, root, GCForeground | GCBackground, &gcv); rootImage = XCreatePixmap(dpy, root, w, h, Pdepth); XCopyPlane(dpy, temp_pix, rootImage, gc, 0, 0, w, h, 0, 0, 1); XFreePixmap(dpy, temp_pix); XFreeGC(dpy, gc); } XSetWindowBackgroundPixmap(dpy, root, rootImage); save_colors = 1; XClearWindow(dpy, root); return 0; } int main(int argc, char **argv) { Atom prop = None; Atom e_prop = None; Atom m_prop = None; Atom type; int format; unsigned long length, after; unsigned char *data; int i = 1; Bool e_killed = False; Bool Dummy = False; Bool RetainPixmap = False; if (argc < 2) { usage(0); fprintf(stderr, "Nothing to do, try again.\n"); exit(1); } dpy = XOpenDisplay(display_name); if (!dpy) { fprintf( stderr, "fvwm-root: unable to open display '%s'\n", XDisplayName (display_name)); exit(2); } screen = DefaultScreen(dpy); root = RootWindow(dpy, screen); for (i = 1; i < argc - 1; i++) { if ( strcasecmp(argv[i], "-r") == 0 || strcasecmp(argv[i], "--retain-pixmap") == 0) { RetainPixmap = True; } else if ( strcasecmp(argv[i], "--no-retain-pixmap") == 0) { RetainPixmap = False; } else if ( strcasecmp(argv[i], "-d") == 0 || strcasecmp(argv[i], "--dummy") == 0) { Dummy = True; } else if ( strcasecmp(argv[i], "--no-dummy") == 0) { Dummy = False; } else if ( strcasecmp(argv[i], "--dither") == 0) { Dither = True; } else if ( strcasecmp(argv[i], "--no-dither") == 0) { NoDither = True; } else if ( strcasecmp(argv[i], "--color-limit") == 0) { use_our_color_limit = True; if (i+1 < argc) { i++; opt_color_limit = atoi(argv[i]); } } else if ( strcasecmp(argv[i], "--no-color-limit") == 0) { NoColorLimit = True; } else if ( strcasecmp(argv[i], "-h") == 0 || strcasecmp(argv[i], "-?") == 0 || strcasecmp(argv[i], "--help") == 0) { usage(1); exit(0); } else if ( strcasecmp(argv[i], "-V") == 0 || strcasecmp(argv[i], "--version") == 0) { fprintf(stdout, "%s\n", VERSION); exit(0); } else { fprintf( stderr, "fvwm-root: unknown option '%s'\n", argv[i]); fprintf( stderr, "Run '%s --help' to get the usage.\n", argv[0]); exit(1); } } if ( Dummy || strcasecmp(argv[argc-1], "-d") == 0 || strcasecmp(argv[argc-1], "--dummy") == 0) { Dummy = True; } else if ( strcasecmp(argv[argc-1], "-h") == 0 || strcasecmp(argv[argc-1], "-?") == 0 || strcasecmp(argv[argc-1], "--help") == 0) { usage(1); exit(0); } else if ( strcasecmp(argv[argc-1], "-V") == 0 || strcasecmp(argv[argc-1], "--version") == 0) { fprintf(stdout, "%s\n", VERSION); exit(0); } else { int rc; rc = SetRootWindow(argv[argc-1]); if (rc == -1) { exit(1); } } prop = XInternAtom(dpy, "_XSETROOT_ID", False); (void)XGetWindowProperty( dpy, root, prop, 0L, 1L, True, AnyPropertyType, &type, &format, &length, &after, &data); if (type == XA_PIXMAP && format == 32 && length == 1 && after == 0 && data != NULL && (Pixmap)(*(long *)data) != None) { XKillClient(dpy, *((Pixmap *)data)); } if (data != NULL) XFree(data); e_prop = XInternAtom(dpy, "ESETROOT_PMAP_ID", False); (void)XGetWindowProperty( dpy, root, e_prop, 0L, 1L, True, AnyPropertyType, &type, &format, &length, &after, &data); if (type == XA_PIXMAP && format == 32 && length == 1 && after == 0 && data != NULL && (Pixmap)(*(long *)data) != None) { e_killed = True; XKillClient(dpy, *((Pixmap *)data)); } if (e_killed && !Dummy) { m_prop = XInternAtom(dpy, "_XROOTPMAP_ID", False); XDeleteProperty(dpy, root, m_prop); } if (RetainPixmap && !Dummy) { long prop; prop = rootImage; if (data != NULL) XFree(data); XSetCloseDownMode(dpy, RetainPermanent); if (e_prop == None) e_prop = XInternAtom(dpy, "ESETROOT_PMAP_ID", False); if (m_prop == None) m_prop = XInternAtom(dpy, "_XROOTPMAP_ID", False); XChangeProperty( dpy, root, e_prop, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &prop, 1); XChangeProperty( dpy, root, m_prop, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &prop, 1); } else { long dp = (long)None; if (prop == None) prop = XInternAtom(dpy, "_XSETROOT_ID", False); XChangeProperty( dpy, root, prop, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &dp, 1); } XCloseDisplay(dpy); return 0; } ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/bin/Makefile.am��������������������������������������������������������������������������0000644�0001750�0001750�00000006042�14147024700�012225� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������## Process this file with automake to create Makefile.in bin_PROGRAMS = fvwm-root fvwm_root_SOURCE= fvwm-root.c fvwm_root_DEPENDENCIES = $(top_builddir)/libs/libfvwm.a bin_SCRIPTS = fvwm-config fvwm-bug fvwm-perllib \ fvwm-convert-2.6 \ fvwm-menu-xlock fvwm-menu-directory \ fvwm-menu-desktop fvwm-menu-headlines man_MANS = \ fvwm-root.1 fvwm-config.1 fvwm-bug.1 fvwm-perllib.1 \ fvwm-convert-2.6.1 \ fvwm-menu-xlock.1 fvwm-menu-directory.1 \ fvwm-menu-desktop.1 fvwm-menu-headlines.1 LDADD = -L$(top_builddir)/libs $(X_LIBS) -lfvwm $(xpm_LIBS) $(Xcursor_LIBS) \ $(X_PRE_LIBS) -lXext -lX11 -lm $(X_EXTRA_LIBS) $(Xrender_LIBS) \ $(Xcursor_LIBS) $(png_LIBS) $(rsvg_LIBS) $(Xinerama_LIBS) AM_CPPFLAGS = -I$(top_srcdir) $(xpm_CFLAGS) $(X_CFLAGS) $(png_CFLAGS) \ $(rsvg_CFLAGS) $(Xinerama_CFLAGS) configdir = @FVWM_DATADIR@ config_DATA = fvwm-menu-desktop-config.fpl EXTRA_DIST = fvwm-menu-desktop-config.fpl $(man_MANS) ## The long generation for *.1 is to make both pod2man and 'make -j' happy. _fvwm-menu-xlock.1: fvwm-menu-xlock @TMP=tmp-$$$$ NAME=fvwm-menu-xlock && (\ mkdir $$TMP && \ cp $$NAME.in $$TMP/$$NAME && \ pod2man --center "Fvwm Utilities" --release "@VERSION@@VERSIONINFO@" \ --name $$NAME $$TMP/$$NAME >$$TMP/$$NAME.1 && \ mv $$TMP/$$NAME.1 .; \ rm -rf $$TMP) _fvwm-menu-directory.1: fvwm-menu-directory @TMP=tmp-$$$$ NAME=fvwm-menu-directory && (\ mkdir $$TMP && \ cp $$NAME.in $$TMP/$$NAME && \ pod2man --center "Fvwm Utilities" --release "@VERSION@@VERSIONINFO@" \ --name $$NAME $$TMP/$$NAME >$$TMP/$$NAME.1 && \ mv $$TMP/$$NAME.1 .; \ rm -rf $$TMP) _fvwm-menu-headlines.1: fvwm-menu-headlines @TMP=tmp-$$$$ NAME=fvwm-menu-headlines && (\ mkdir $$TMP && \ cp $$NAME.in $$TMP/$$NAME && \ pod2man --center "Fvwm Utilities" --release "@VERSION@@VERSIONINFO@" \ --name $$NAME $$TMP/$$NAME >$$TMP/$$NAME.1 && \ mv $$TMP/$$NAME.1 .; \ rm -rf $$TMP) _fvwm-perllib.1: fvwm-perllib @TMP=tmp-$$$$ NAME=fvwm-perllib && (\ mkdir $$TMP && \ cp $$NAME.in $$TMP/$$NAME && \ pod2man --center "Fvwm Utilities" --release "@VERSION@@VERSIONINFO@" \ --name $$NAME $$TMP/$$NAME >$$TMP/$$NAME.1 && \ mv $$TMP/$$NAME.1 .; \ rm -rf $$TMP) regenerate: \ _fvwm-menu-xlock.1 _fvwm-menu-directory.1 _fvwm-menu-headlines.1 \ _fvwm-perllib.1 ## Create compatibility symlinks if available xpmroot_name =`echo "xpmroot" | "$(SED)" -e "${transform}"` fvwm_root_name =`echo "fvwm-root" | "$(SED)" -e "${transform}"` install-exec-local: @rm -f $(DESTDIR)$(bindir)/$(xpmroot_name)$(EXEEXT) @$(LN_S) $(fvwm_root_name)$(EXEEXT) \ $(DESTDIR)$(bindir)/$(xpmroot_name)$(EXEEXT) || \ echo "Minor warning: $(bindir)/$(xpmroot_name)$(EXEEXT) symlink was not created" install-data-local: @rm -f $(DESTDIR)$(mandir)/man1/$(xpmroot_name).1 @$(LN_S) $(fvwm_root_name).1 \ $(DESTDIR)$(mandir)/man1/$(xpmroot_name).1 || \ echo "Minor warning: $(mandir)/man1/$(xpmroot_name).1 symlink was not created" uninstall-local: @rm -f $(DESTDIR)$(bindir)/$(xpmroot_name)$(EXEEXT) @rm -f $(DESTDIR)$(mandir)/man1/$(xpmroot_name).1 CLEANFILES = $(bin_SCRIPTS) $(bin_PROGRAMS) ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/bin/fvwm-perllib.1�����������������������������������������������������������������������0000644�0001750�0001750�00000013021�14147024700�012654� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" Automatically generated by Pod::Man 2.16 (Pod::Simple 3.02) .\" .\" Standard preamble: .\" ======================================================================== .de Sh \" Subsection heading .br .if t .Sp .ne 5 .PP \fB\\$1\fR .PP .. .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .ie \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .el \{\ . de IX .. .\} .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "fvwm-perllib 1" .TH fvwm-perllib 1 "2009-03-22" "2.5.28 (from cvs)" "Fvwm Utilities" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" fvwm\-perllib \- shows the documentation of the Fvwm Perl library .SH "SYNOPSIS" .IX Header "SYNOPSIS" \&\fBfvwm-perllib\fR [ \fB\-\-help\fR|\fB\-h\fR|\fB\-?\fR ] [ \fB\-\-version\fR|\fB\-v\fR|\fB\-V\fR ] [ \fBman\fR [ \fIPerl::Class\fR ] ] [ \fBcat\fR [ \fIPerl::Class\fR ] ] [ \fBraw\fR [ \fIPerl::Class\fR ] ] [ \fBdir\fR ] .SH "DESCRIPTION" .IX Header "DESCRIPTION" Starting from fvwm\-2.5.x versions there is a built-in support for creating fvwm modules in Perl. This \fBfvwm-perllib\fR utility provides help services for the Fvwm Perl library. .SH "OPTIONS" .IX Header "OPTIONS" \&\fB\-\-help\fR show the help and exit .PP \&\fB\-\-version\fR show the version and exit .PP \&\fB\-\-man\fR or \fBman\fR [ \fIPerl::Class\fR ] show manual page just like \fIman\fR\|(1) .PP \&\fB\-\-cat\fR or \fBcat\fR [ \fIPerl::Class\fR ] show manual page in plain text .PP \&\fB\-\-raw\fR or \fBraw\fR [ \fIPerl::Class\fR ] generate output in man format (not human readable) .PP \&\fB\-\-dir\fR or \fBdir\fR print perllib directory without a trailing end of line .SH "USAGE" .IX Header "USAGE" Use this in the fvwm modules written in Perl: .PP .Vb 1 \& use lib \`fvwm\-perllib dir\`; .Ve .PP Introduction to the Fvwm Perl library: .PP .Vb 1 \& % fvwm\-perllib man .Ve .PP Manual page for the \f(CW\*(C`FVWM::Module\*(C'\fR class: .PP .Vb 1 \& % fvwm\-perllib man FVWM::Module .Ve .PP Standard options: .PP .Vb 2 \& % fvwm\-perllib \-\-help \& % fvwm\-perllib \-\-version .Ve .SH "AUTHORS" .IX Header "AUTHORS" Mikhael Goikhman <migo@homemail.com>. .SH "COPYING" .IX Header "COPYING" The script is distributed by the same terms as fvwm itself. See \s-1GNU\s0 General Public License for details. .SH "BUGS" .IX Header "BUGS" No known bugs. .PP Report bugs to fvwm\-bug@fvwm.org. ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/bin/fvwm-convert-2.6.1.in����������������������������������������������������������������0000644�0001750�0001750�00000007107�14147024700�013623� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" @(#)@PACKAGE@-@VERSION@ @RELDATELONG@ .TH fvwm-convert-2.6 1 "@RELDATELONG@ (@VERSION@)" Fvwm "Fvwm Modules" .SH NAME fvwm-convert-2.6 \- convert fvwm 2.4.x configuration file to fvwm 2.6 style .SH SYNOPSIS .B fvwm-convert-2.6 .RI [ --follow-read | -f ] .RI [ --help | -h ] .RI source .RI [ dest ] .SH OPTIONS The following options are supported: .IP "\fB\-\-help\fR | \fB\-h\fR" Prints a usage message to the screen. .IP "\fB\-\-follow\-read\fR | \fB\-f\fR" Follows files found along with the .B Read command. .SH DESCRIPTION .B fvwm-convert-2.6 converts an fvwm 2.4.x configuration file into a fvwm 2.6 file with compatible syntax. It is not suitable to convert older 2.x configuration files. Please use .B fvwm-convert-2.2 to convert these to the 2.2.x format first, and then if necessary .B fvwm-convert-2.4 .PP By default, .B fvwm-convert-2.6 won't look for a given config file. This must be specified as the first parameter to .B fvwm-convert-2.6. Different source and destination files may be given. If the destination file already exists, this program exits. If no destination file is given, then the filename is the same name as the source file with the suffix ".converted" added. Without an absolute path given as the destination path to the destination file, the program will create the destination file in the CWD. .PP .B fvwm-convert-2.6 makes the following changes: .TP 4 .B Style lines In fvwm 2.4, most style options could be negated from their counterparts using NoFoo -- fvwm-convert-2.6 corrects this by now using !Foo. .TP 4 .B ModulePath In fvwm 2.4 and beyond, the ModulePath is compiled into fvwm. .B fvwm-convert-2.6 comments out any ModulePath commands it finds. If you are using your own modules, (not the ones that come with fvwm), you will have to fix your configuration file after using .BR fvwm-convert-2.6 . .TP 4 .B Conditional command syntax In fvwm 2.4, the conditional command options were whitespace-separated -- they should now be comma-separated instead. In addition, the older syntax to Next and Prev of using [*] to denote all windows has been removed entirely. Both these checks and conversions are done on function commands, key/mouse bindings. .TP 4 .B WindowShadeSteps In fvwm 2.4, the WindowShadeSteps command is replaced by the WindowShadeSteps Style option. .B fvwm-convert-2.6 makes this change. .TP 4 .B FvwmTheme In fvwm 2.6, the FvwmTheme module is replaced by a series of Colorset commands. Whilst .B fvwm-convert-2.6 will try and make this change, it is still recommended that this is checked after conversion. .TP 4 .B EdgeResistance In fvwm 2.6, the EdgeResistance command is has been split to include an additional style option for EdgeMoveResistance. .B fvwm-convert-2.6 makes any changes necessary. .TP 4 .B StartFunction / RestartFunction / InitFunction In fvwm 2.6, the need for using InitFunction and/or RestartFunction is redundant when StartFunction is read at both of these times. .B fvwm-convert-2.6 attempts to convert this. .TP 4 .B Read If .B -f or .B --follow-read is given, any files .B fvwm-convert-2.6 can detect and open will be converted automatically, else a list of files that can be followed are printed to the screen. .TP 4 .SH BUGS .I InitFunction and .I RestartFunction and hence .I StartFunction are printed at the end of the files -- this slight reordering might put some comments before in an odd spot. When converting over FvwmTheme lines, the colorset definitions might well be broken, but these cannot easily be converted. Bug reports can be sent to the fvwm-workers mailing list (see the .IR FAQ ). .SH AUTHOR Thomas Adam <thomas.adam22@gmail.com> ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/bin/fvwm-menu-headlines.in���������������������������������������������������������������0000644�0001750�0001750�00000103616�14147024700�014401� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!@PERL@ # Copyright (c) 1999-2009 Mikhael Goikhman # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see: <http://www.gnu.org/licenses/> # Filter this script to pod2man to get a man page: # pod2man -c "Fvwm Utilities" fvwm-menu-headlines | nroff -man | less -e require 5.002; use strict; use vars qw($site_info @smonths @lmonths %smonth_hash %lmonth_hash); use vars qw($entity_map $error_menu_content); use Getopt::Long; use Socket; use POSIX qw(strftime); use Time::Local; my $version = "@VERSION@"; local $site_info = { 'freshmeat' => { 'name' => "FreshMeat", 'host' => "freshmeat.net", 'path' => "/backend/recentnews.txt", 'func' => \&process_freshmeat, 'flds' => 'headline, date, url', }, 'slashdot' => { 'name' => "Slashdot", 'host' => "slashdot.org", 'path' => "/slashdot.xml", 'func' => \&process_slashdot, 'flds' => 'title, url, time, author, department, topic, comments, section, image', }, 'linuxtoday' => { 'name' => "LinuxToday", 'host' => "linuxtoday.com", 'path' => "/lthead.txt", 'func' => \&process_linuxtoday, 'flds' => 'headline, url, date', }, 'old-segfault' => { 'name' => "Old-Segfault (empty now)", 'host' => "segfault.org", 'path' => "/stories.txt", 'func' => \&process_segfault, 'flds' => 'headline, url, date, author_name, author_email, type', }, 'old-appwatch' => { 'name' => "Old-AppWatch (closed by ZDNet)", 'host' => "www.appwatch.com", 'path' => "/appwatch.rdf", 'func' => \&process_poor_rdf, 'flds' => 'title, link, description', }, 'old-linuxapps' => { 'name' => "Old-LinuxApps (moved/closed)", 'host' => "www.linuxapps.com-closed", 'path' => "/backend/linux_basic.txt", 'func' => undef, 'flds' => 'headline, date, url', }, 'old-justlinux' => { 'name' => "Old-JustLinux (no headlines?)", 'host' => "www.justlinux.com", 'path' => "/backend/discussion.rdf", 'func' => \&process_poor_rdf, 'flds' => 'title, link', }, 'daemonnews' => { 'name' => "DaemonNews", 'host' => "daily.daemonnews.org", 'path' => "/ddn.rdf.php3", 'func' => \&process_poor_rdf, 'flds' => 'title, link', }, # this is now called FootNotes or GNOME Desktop News, was news.gnome.org 'gnome-news' => { 'name' => "GNOME-News", 'host' => "www.gnomedesktop.org", 'path' => "/backend.php", 'func' => \&process_poor_rdf, 'flds' => 'title, link', }, 'kde-news' => { 'name' => "KDE-News", 'host' => "news.kde.org", 'path' => "/rdf", 'func' => \&process_kde_news, 'flds' => 'title, link', }, 'old-freekde' => { 'name' => "Old-FreeKDE (taken off?)", 'host' => "freekde.org", 'path' => "/freekdeorg.rdf", 'func' => \&process_freekde, 'flds' => 'title, link', }, 'rootprompt' => { 'name' => "RootPrompt", 'host' => "rootprompt.org", 'path' => "/rss/", 'func' => \&process_rootprompt, 'flds' => 'title, link, description', }, 'newsforge' => { 'name' => "NewsForge", 'host' => "www.newsforge.com", 'path' => "/newsforge.xml", 'func' => \&process_slashdot, 'flds' => 'title, url, time, author, department, topic, comments, section, image', }, 'kuro5hin' => { 'name' => "Kuro5hin", 'host' => "www.kuro5hin.org", 'path' => "/backend.rdf", 'func' => \&process_kuro5hin, 'flds' => 'title, link, description', }, 'bbspot' => { 'name' => "BBSpot", 'host' => "bbspot.com", 'path' => "/bbspot.rdf", 'func' => \&process_poor_rdf, 'flds' => 'title, link', }, 'linuxfr' => { 'name' => "LinuxFr", 'host' => "linuxfr.org", # 'path' => "/short.php3", 'path' => "/backend.rss", 'func' => \&process_linuxfr, # 'flds' => 'headline, url, author_name, author_email, type', 'flds' => 'title, link', }, 'thinkgeek' => { 'name' => "ThinkGeek", 'host' => "www.thinkgeek.com", 'path' => "/thinkgeek.rdf", 'func' => \&process_poor_rdf, 'flds' => 'title, link', }, 'cnn' => { 'name' => "CNN", 'host' => "www.cnn.com", 'path' => "/desktop/content.html", 'func' => \&process_cnn, 'flds' => 'headline, url', }, # to be removed 'bbc-world' => { 'name' => "BBC-World (obsolete)", 'host' => "news.bbc.co.uk", 'path' => "/low/english/world/default.stm", 'func' => \&process_old_bbc, 'flds' => 'headline, url, abstract', }, # to be removed 'bbc-scitech' => { 'name' => "BBC-SciTech (obsolete)", 'host' => "news.bbc.co.uk", 'path' => "/low/english/sci/tech/default.stm", 'func' => \&process_old_bbc, 'flds' => 'headline, url, abstract', }, 'bbc' => { 'name' => "BBC", 'host' => "news.bbc.co.uk", 'host0' => "tickers.bbc.co.uk", 'path' => "/tickerdata/story2.dat", 'func' => \&process_bcc, 'flds' => 'story, headline, url', }, }; # Site specific parsers may use these constants to convert month to unix time. local @smonths = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec); local @lmonths = qw(January February March April May June July August September October November December); local (%smonth_hash, %lmonth_hash) = (); foreach (0 .. 11) { $smonth_hash{$smonths[$_]} = $_; $lmonth_hash{$lmonths[$_]} = $_; } my $TIMEFIELDS_DATE_TIME = 1; my $TIMEFIELDS_ONLY_DATE = 2; my $TIMEFIELDS_NONE = 3; my $home = $ENV{'HOME'} || '/tmp'; my $fvwm_user_dir = $ENV{'FVWM_USERDIR'} || "$home/.fvwm"; $fvwm_user_dir = $home unless -d $fvwm_user_dir; my $work_home = "$fvwm_user_dir/.fvwm-menu-headlines"; require "$work_home/extension.pl" if -r "$work_home/extension.pl"; my $info = undef; my $default_site = 'freshmeat'; my $site = undef; my $name = undef; my $title = undef; my $itemf = '%h\t%[(%Y-%m-%d %H:%M)]'; my $execf = q(firefox '%u'); my $commf = undef; my $icont = ''; my $iconi = ''; my $iconh = ''; my $icone = ''; my $wm_icons = 0; my $proxy = undef; my $port = 80; my $frontpage = undef; my @time = localtime(); my $menu_filename = undef; my $fake_filename = undef; my $timeout = 20; my $endl = "\r\n"; # this is preferable for http sockets to "\n" GetOptions( "help|h|?" => \&show_help, "version|V" => \&show_version, "info:s" => \$info, "site=s" => \$site, "name=s" => \$name, "title=s" => \$title, "item=s" => \$itemf, "exec=s" => \$execf, "command=s" => \$commf, "icon-title=s" => \$icont, "icon-item=s" => \$iconi, "icon-home=s" => \$iconh, "icon-error=s" => \$icone, "wm-icons" => \$wm_icons, "proxy=s" => \$proxy, "frontpage:s" => \$frontpage, "file:s" => \$menu_filename, "fake:s" => \$fake_filename, "timeout=i" => \$timeout, ) || wrong_usage(); wrong_usage() if @ARGV; if (defined $info) { if ($info) { my $_info = $site_info->{lc($info)}; die "Unsupported site '$info'; try --info.\n" unless $_info; my $host0 = $_info->{'host0'} || $_info->{'host'}; print "Site Name:\n\t$_info->{'name'}\n", "Home Page:\n\thttp://$_info->{'host'}/\n", "Headlines:\n\thttp://$host0$_info->{'path'}\n", "Headline fields:\n\t$_info->{'flds'}\n"; } else { print "All supported sites:\n\t", join(", ", &get_all_site_names()), "\n\nSpecify a site name after --info to get a site headlines info.\n"; } exit(0); } $site ||= $default_site; $site = lc($site); die "Unsupported site '$site'; try --info.\n" unless exists $site_info->{$site}; #$name ||= "MenuHeadlines$site_info->{$site}->{'name'}"; $name ||= $site; $title ||= "$site_info->{$site}->{'name'} Headlines"; my $site_name = $site_info->{$site}->{'name'}; my $site_host = $site_info->{$site}->{'host'}; my $site_path = $site_info->{$site}->{'path'}; my $site_func = $site_info->{$site}->{'func'}; $commf ||= "Exec $execf"; $title =~ s/\\t/\t/g; $itemf =~ s/\\t/\t/g; $commf =~ s/\\t/\t/g; if ($wm_icons) { $icont ||= ""; $iconi ||= "menu/information.xpm"; $iconh ||= "menu/home.xpm"; $icone ||= "menu/choice-no.xpm"; } my $icont_str = $icont ? "%$icont%" : ""; my $iconi_str = $iconi ? "%$iconi%" : ""; my $iconh_str = $iconh ? "%$iconh%" : ""; my $icone_str = $icone ? "%$icone%" : ""; if (defined $proxy && $proxy =~ /^(.+):(\d+)$/) { $proxy = $1; $port = $2; } # Three cases: # 1) no --file option or value '-' specified (STDOUT is used) # 2) no or empty menu file in --file specified (the default name is used) # 3) non-empty menu file specified (use it) $menu_filename = undef if defined $menu_filename && $menu_filename eq '-'; if ($menu_filename) { $menu_filename =~ s:^~(/|$):$home$1:; $menu_filename =~ m:^(.+)/[^/]+$:; $work_home = $1 || "."; } elsif (defined $menu_filename) { $menu_filename = "$work_home/$site.menu"; } my $content = ""; $content .= qq(DestroyMenu $name\n); $content .= qq(AddToMenu $name "$icont_str$title" Title\n); local $error_menu_content = $content; my $frontpage_entry = ""; if (defined $frontpage) { my $cmd = &expand_all_width_specifiers($commf, {'u' => "http://$site_host/"}); $frontpage_entry = qq(+ "$iconh_str$site_name Frontpage" $cmd\n); $error_menu_content .= qq($frontpage_entry\n+ "" Nop\n); } $error_menu_content .= "+ `$icone_str<msg>` DestroyMenu $name\n"; if (defined $frontpage && $frontpage !~ /^b/) { $content .= qq($frontpage_entry\n+ "" Nop\n); } unless (defined $fake_filename) { $site_host = $site_info->{$site}->{'host0'} if defined $site_info->{$site}->{'host0'}; my $redirect_depth = 0; HTTP_CONNECTION: my $host = $proxy || $site_host; my $iaddr = inet_aton($host) || &die_net("Can't resolve host $host"); my $paddr = sockaddr_in($port, $iaddr); my $proto = getprotobyname('tcp'); local $SIG{ALRM} = sub { die "timeout\n"; }; alarm($timeout); eval { socket(SOCK, PF_INET, SOCK_STREAM, $proto) && connect(SOCK, $paddr) } || &die_net("Can't connect host $host"); alarm(0); select(SOCK); $| = 1; select(STDOUT); # do http request my $http_headers = "$endl" . "Host: $site_host$endl" . "Connection: close$endl" . "User-Agent: fvwm-menu-headlines/$version$endl" . "Pragma: no-cache$endl" . "$endl"; if (defined $proxy) { print SOCK "GET http://$site_host$site_path HTTP/1.1$http_headers"; } else { print SOCK "GET $site_path HTTP/1.1$http_headers"; } unless (read_line() =~ m{HTTP/1\.\d (\d+) \w+}) { &die_net("Invalid HTTP response from http://$site_host$site_path", 0); } my $status = $1; if ($status =~ /^301|302$/ && ++$redirect_depth < 5) { # redirection while (1) { my $line = read_line(); $line =~ s/[\n\r]+$//s; last unless $line; if ($line =~ m{Location: http://([^/]+)(/.*)}i) { $site_host = $1; $site_path = $2; goto HTTP_CONNECTION; } } } &die_net("Unexpected HTTP response $status from http://$site_host$site_path", 0) unless $status eq "200"; # skip http response headers while (read_line() !~ /^\r?\n?$/s) {} } else { if ($fake_filename) { $fake_filename =~ s:^~(/|$):$home$1:; } else { $fake_filename = "$work_home/$site.in"; } open(SOCK, "<$fake_filename") || &die_sys("Can't open $fake_filename"); } my $entries = &$site_func; close(SOCK) || &die_net("Error closing socket"); foreach (@$entries) { my $text = &expand_all_width_specifiers($itemf, $_); my $comm = &expand_all_width_specifiers($commf, $_); $text =~ s/"/\\"/g; $content .= qq(+ "$iconi_str$text" $comm\n); } if (defined $frontpage && $frontpage =~ /^b/) { $content .= qq(+ "" Nop\n$frontpage_entry); } if (defined $menu_filename) { unless (-d $work_home) { mkdir($work_home, 0775) || &die_sys("Can't create $work_home"); } open(MENU_FILE, ">$menu_filename") || &die_sys("Can't open $menu_filename"); print MENU_FILE $content; close(MENU_FILE) || &die_sys("Can't close $menu_filename"); } else { print $content; } exit(); # --------------------------------------------------------------------------- sub read_line { local $SIG{ALRM} = sub { die "timeout\n"; }; alarm($timeout); my $line = eval { <SOCK> }; if ($@) { &die_net("Timeout of $timeout seconds reached") if $@ eq "timeout\n"; &die_net($@); } alarm(0); print STDERR $line if $ENV{"DEBUG_DUMP_RESPONSE"}; return $line; } sub read_all_lines { local $SIG{ALRM} = sub { die "timeout\n"; }; alarm($timeout * 2); my $lines = eval { join('', <SOCK>) }; if ($@) { &die_net("Timeout of $timeout seconds reached") if $@ eq "timeout\n"; &die_net($@); } alarm(0); print STDERR $lines if $ENV{"DEBUG_DUMP_RESPONSE"}; return $lines; } # make unix time from year (2001 or 101), mon (0..11), day, hour, min, sec sub make_time { # ($$$$$$$) my ($h_offset, $year, $mon, $day, $hour, $min, $sec) = @_; $h_offset ||= 0; my $type = $TIMEFIELDS_DATE_TIME; unless (defined $hour || defined $min) { unless ($year || $day) { $type = $TIMEFIELDS_NONE; return [ 0, $type ]; } else { $type = $TIMEFIELDS_ONLY_DATE; } } $year = 1973 unless $year && $year > 0; # it's my year :-) $mon = 0 unless $mon && $mon > 0 && $mon <= 11; $day = 1 unless $day && $day > 0 && $day <= 31; $hour = 12 unless $hour && $hour >= 0 && $hour < 24; $min = 0 unless $min && $min >= 0 && $min < 60; $sec = 0 unless $sec && $sec >= 0 && $sec < 60; return [ timegm($sec, $min, $hour, $day, $mon, $year) - $h_offset * 60 * 60, $type ]; } sub set_entry_aliases_and_time ($$$$) { my $entry = shift; my $aliases = shift; my $time_func = shift; my $h_offset = shift; my ($alias, $orig); while (($alias, $orig) = each %$aliases) { $entry->{$alias} = !$orig ? "" : ref($orig) eq 'CODE' ? &{$orig}($entry) : $entry->{$orig}; $entry->{$alias} = "" unless defined $entry->{$alias}; } $entry->{'_'} = make_time($h_offset, &{$time_func}($entry->{'d'})); } BEGIN { $entity_map = { 'gt' => '>', 'lt' => '<', 'quot' => '"', 'amp' => '&', }; } sub process_xml ($$$$) { my $entry_tag = shift; my $aliases = shift; my $time_func = shift; my $h_offset = shift; my @entries = (); my $doc = read_all_lines(); ENTRY: foreach ($doc =~ m!<$entry_tag\b[^>]*>(.*?)</$entry_tag>!sg) { s/&quot;/"/g; # fix buggy html in some backends # replace ' with single quote and " with double quote s/&(?:(\w+)|#(\d{2,})|#x([\da-fA-F]{2,4}));/ $1 ? $entity_map->{$1} || "{$1}" : chr($2 || hex($3)) /ge; my $entry = {}; foreach (m!(<.*?>.*?</.*?>)!sg) { m!<(.*?)>\s*(.*?)\s*</(.*?)>!s; # ignore incorect fields or throw error? next unless $1 && $2 && $3; next if $1 ne $3; $entry->{$1} = $2; } set_entry_aliases_and_time($entry, $aliases, $time_func, $h_offset); push @entries, $entry; } return \@entries; } sub process_text ($$$$) { my $fields = shift; my $aliases = shift; my $time_func = shift; my $h_offset = shift; my @entries = (); ENTRY: while (1) { my $entry = {}; foreach (@$fields) { my $line = read_line(); last ENTRY unless defined $line; next if $_ eq '_ignore_'; chomp($line); $line =~ s/"/\\"/g; # $line =~ s/<.*?>//g; # $line =~ s/&\w{1,5}?;/ /g; $entry->{$_} = $line; } set_entry_aliases_and_time($entry, $aliases, $time_func, $h_offset); push @entries, $entry; } return \@entries; } sub process_slashdot () { return process_xml( 'story', { 'h' => 'title', 'u' => 'url', 'd' => 'time' }, sub ($) { $_[0] =~ /(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)/; ($1, ($2 || 0) - 1, $3, $4, $5, $6); }, +0, ); } sub process_freshmeat () { return process_text( [ qw( headline date url ) ], { 'h' => 'headline', 'u' => 'url', 'd' => 'date' }, sub ($) { $_[0] =~ /^(?:\w+, )?(\w+) (\d+)\w* (\d+),? (\d+):(\d+)/; ($3, $lmonth_hash{$1}, $2, $4, $5, 0); }, -5 + (abs((localtime())[4] - 5.5) < 3), ); } sub process_linuxtoday () { my $line; while ($line = read_line()) { last if $line =~ /linuxtoday.com/; # skip the text note last if $line =~ /&&/ and read_line() x 3; # if it was replaced } return process_text( [ qw( _ignore_ headline url date ) ], { 'h' => 'headline', 'u' => 'url', 'd' => 'date' }, sub ($) { $_[0] =~ /(\w+) (\d+), (\d+), (\d+):(\d+):(\d+)/; ($3, $smonth_hash{$1}, $2, $4, $5, $6); }, +0, ); } sub process_segfault () { my $line; while ($line = read_line()) { last if $line =~ /^%%/; # skip the text note } return process_text( [ qw( headline url date author_name author_email type _ignore_ ) ], { 'h' => 'headline', 'u' => 'url', 'd' => 'date' }, sub ($) { $_[0] =~ /(\d+) (\w+) (\d+):(\d+):(\d+) (\d+)/; ($6, $smonth_hash{$2}, $1, $3, $4, $5); }, -8 + (abs((localtime())[4] - 5.5) < 3), ); } sub process_poor_rdf () { return process_xml( 'item', { 'h' => 'title', 'u' => 'link', 'd' => undef }, sub ($) { # this site's rdf does not supply the time, how weird... #(gmtime())[5,4,3,2,1,0]; () }, +0, ); } sub process_linuxapps_old () { return process_text( [ qw( headline date url ) ], { 'h' => 'headline', 'u' => 'url', 'd' => 'date' }, sub ($) { $_[0] =~ /(\w+) (\d+) (\d+):(\d+):(\d+) \w+ (\d+)/; ($6, $smonth_hash{$1}, $2, $3, $4, $5); }, -5, ); } sub process_kde_news () { my $link_to_time = sub ($) { $_[0]->{'link'} =~ m|/(\d+)/?$|; $1; }; return process_xml( 'item', { 'h' => 'title', 'u' => 'link', 'd' => $link_to_time }, sub ($) { (gmtime($_[0]))[5,4,3,2,1,0]; }, +0, ); } sub process_freekde () { my $link_to_date = sub ($) { $_[0]->{'link'} =~ m|/(\d\d/\d\d/\d\d)/|; $1 ? "20$1" : ''; }; return process_xml( 'item', { 'h' => 'title', 'u' => 'link', 'd' => $link_to_date }, sub ($) { $_[0] =~ m|(\d+)/(\d+)/(\d+)|; ($1, ($2 || 0) - 1, $3); }, +0, ); } sub process_rootprompt () { my $title_stripped = sub ($) { $_[0]->{'title'} =~ /(.*) \([^\(\)]+\)$/ ? $1 : $_[0]->{'title'}; }; my $title_to_date = sub ($) { $_[0]->{'title'} =~ / \((\d+ \w{3} \d{4})\)$/; $1; }; return process_xml( 'item', { 'h' => $title_stripped, 'u' => 'link', 'd' => $title_to_date }, sub ($) { $_[0] =~ /(\d+) (\w+) (\d+)/; ($3, $smonth_hash{$2}, $1); }, +0, ); } sub process_kuro5hin () { my $link_to_date = sub ($) { $_[0]->{'link'} =~ m|/(\d\d\d\d/\d{1,2}/\d{1,2})/|; $1; }; return process_xml( 'item', { 'h' => 'title', 'u' => 'link', 'd' => $link_to_date }, sub ($) { $_[0] =~ m|(\d+)/(\d+)/(\d+)|; ($1, ($2 || 0) - 1, $3); }, +0, ); } sub process_linuxfr () { my $link_to_date = sub ($) { $_[0]->{'link'} =~ m|/(\d\d\d\d/\d\d/\d\d)/|; $1; }; my $hack_for_url = sub ($) { # hack for mozilla -remote openURL my $u = $_[0]->{'link'}; $u =~ s|,|\%2c|g; $u; }; return process_xml( 'item', { 'h' => 'title', 'u' => $hack_for_url, 'd' => $link_to_date }, sub ($) { $_[0] =~ m|(\d+)/(\d+)/(\d+)|; ($1, ($2 || 0) - 1, $3); }, +0, ); } sub process_linuxfr_old () { my $link_to_date = sub ($) { $_[0]->{'url'} =~ m|/(\d\d\d\d/\d\d/\d\d)/|; $1; }; my $hack_for_url = sub ($) { # hack for mozilla -remote openURL my $u = $_[0]->{'url'}; $u =~ s|,|\%2c|g; $u; }; my $line; while ($line = read_line()) { last if $line =~ /^%%/; # skip the text note } return process_text( [ qw( headline url author_name author_email type _ignore_ ) ], { 'h' => 'headline', 'u' => $hack_for_url, 'd' => $link_to_date }, sub ($) { $_[0] =~ m|(\d+)/(\d+)/(\d+)|; ($1, ($2 || 0) - 1, $3); }, +0, ); } sub process_cnn () { my $contents = read_all_lines(); my @entries = (); my $link_to_date = sub ($) { $_[0]->{'url'} =~ m|/(\d\d\d\d).*?(/\d\d/\d\d)/|; "$1$2"; }; $contents =~ s{<a href="(/.*?)".*?>(.*?)</a>}{ my $entry = {}; $entry->{'url'} = "http://www.cnn.com$1"; $entry->{'headline'} = $2; set_entry_aliases_and_time( $entry, { 'h' => 'headline', 'u' => 'url', 'd' => $link_to_date }, sub ($) { $_[0] =~ m|(\d+)/(\d+)/(\d+)| ? ($1, ($2 || 0) - 1, $3) : (); }, -5, ); push @entries, $entry; "" }sige; return \@entries; } sub process_old_bbc () { my $contents = read_all_lines(); $contents =~ s!\r\n...\r\n!!sg; # they insert this randomly! $contents =~ s!\s*<(br|/h3|h3|span[^>]*|/span|img [^>]+)>[ \t\r]*\n?!!sig; my @entries = (); $contents =~ s{\s+<a href="(/[^"]+?)">\s*([^\s][^<]+?)\s*</a>\s*([^<]+?)\s*(?:\n|<br )}{ my $entry = {}; my $path = $1; $entry->{'headline'} = $2; $entry->{'abstract'} = $3; $path =~ s|^(/\d+)?/low/|$1/hi/|; $entry->{'url'} = "http://news.bbc.co.uk$path"; set_entry_aliases_and_time( $entry, { 'h' => 'headline', 'u' => 'url', 'd' => undef }, sub ($) { (); # no time... }, +0, ); push @entries, $entry; "" }sige; return \@entries; } sub process_bcc () { read_all_lines() =~ /STORY 1\nHEADLINE Last update at (\d+:\d+)\nURL \n(.*)$/s; my ($time, $contents) = ($1, $2); die_net("Parse error. Did BBC site change format?", "") unless defined $time; my @entries = (); $contents =~ s{STORY (\d+)\nHEADLINE (.*?)\nURL (.*?)\n}{ my $entry = {}; my $date = undef; $entry->{'story'} = $1; my $headline = $2; my $url = $3; if ($headline =~ /^(.+?) (\d+ \w+ \d+)$/) { $headline = $1; $date = $2 . " $time"; } $entry->{'headline'} = $headline; $url =~ s|^(http://.*?/).*/-/(.*)$|$1$2|; $url = "http://news.bbc.co.uk/" if $url eq ""; $entry->{'url'} = $url; $entry->{'date'} = $date; set_entry_aliases_and_time( $entry, { 'h' => 'headline', 'u' => 'url', 'd' => 'date' }, sub ($) { return () unless defined $_[0] && $_[0] =~ /^(\d+) (\w+) (\d+) (\d+):(\d+)/; ($3, $lmonth_hash{$2}, $1, $4, $5); }, +0, ); push @entries, $entry; "" }sige; return \@entries; } # --------------------------------------------------------------------------- sub die_sys ($) { my $msg = shift; $msg = "$0: $msg: [$!]\n"; print STDERR $msg # # be quiet in non interactive shells? # if ($ENV{'SHLVL'} || 0) == 1 || defined($ENV{'PS1'}) ; exit(-1); } sub die_net ($;$) { my $msg = shift; my $check_network_msg = @_ ? "" : "; check network connection"; #die_sys($msg); $error_menu_content =~ s/<msg>/$msg$check_network_msg/; print $error_menu_content; exit(-1); } # like strftime, but gets unix time, instead of sec/min/hour/day/mon/year. sub format_time ($$) { my ($fmt, $time_pair) = @_; $time_pair = [] unless ref($time_pair) eq 'ARRAY'; my ($time, $type) = @$time_pair; $time ||= time(); $type ||= $TIMEFIELDS_NONE; if ($type == $TIMEFIELDS_NONE) { return ""; } elsif ($type == $TIMEFIELDS_ONLY_DATE) { $fmt =~ s/[:\. -]?%[HIklMprSTX][:\. -]?//g; $fmt =~ s/%c/%a %b %d %Z %Y/g; } return strftime($fmt, localtime($time)); } # Substitutes all %N1*N2x in $name by properly stripped and justified $values. # $name example: %[%d %b %y %H:%M], %*-7(some text), %-32*30h, %{url}. # $values is a hash of named values to substitute. sub expand_all_width_specifiers ($$) { my ($name, $values) = @_; $name =~ s/%(-?\d+)?(\*(-?)(\d+))?(\w|{\w+}|\(.*?\)|\[.*?\])/ my $tag = substr($5, 0, 1); my $arg = length($5) == 1 ? $5 : substr($5, 1, -1); my $value = $tag eq '(' ? $arg : $tag eq '[' ? format_time($arg, $values->{'_'}) : $values->{$arg}; $value = "(%$5 is not defined)" unless defined $value; $value = !$2 || $4 <= 3 || $4 > length($value) ? $value : $3? "..." . substr($value, -$4 + 3, $4 - 3): substr($value, 0, $4 - 3) . "..."; $1 ? sprintf("%$1s", $value) : $value; /ge; return $name; } sub get_all_site_names () { return sort map { $site_info->{$_}->{'name'} } keys %$site_info; } sub show_help { $site ||= $default_site; #$name ||= "MenuHeadlines$site_info->{$site}->{'name'}"; $name ||= $site; $title ||= "$site_info->{$site}->{'name'} Headlines"; print "A perl script which builds headlines menu for fvwm.\n"; print "Supported sites: ", join(', ', get_all_site_names()), "\n\n"; print "Usage: $0 [OPTIONS]\n"; print "Options:\n"; print "\t--help show this help and exit\n"; print "\t--version show the version and exit\n"; print "\t--info=[NAME] information about a site\n"; print "\t--site=NAME headlines site, default is $site\n"; print "\t--name=NAME menu name, default is '$name'\n"; print "\t--title=NAME menu title, default is '$title'\n"; print "\t--item=FORMAT menu item format, default is '$itemf'\n"; print "\t--exec=FORMAT exec command, default is {$execf}\n"; print "\t--command=FORMAT fvwm command, default is no\n"; print "\t--icon-title=XPM menu title icon, default is no\n"; print "\t--icon-item=XPM menu item icon, default is no\n"; print "\t--icon-home=XPM menu home icon, default is no\n"; print "\t--icon-error=XPM menu error icon, default is no\n"; print "\t--wm-icons define icon names to use with wm-icons\n"; print "\t--frontpage[=V] show frontpage item; values: top, bottom\n"; print "\t--proxy=host[:port] specify proxy host and port (80)\n"; print "\t--file[=FILE] menu file, default is $work_home/$site.menu\n"; print "\t--fake[=FILE] don't connect, read input from file\n"; print "\t--timeout=SECS timeout for a line reading from a socket\n"; print "Short options are ok if not ambiguous: -h, -t.\n"; exit 0; } sub show_version { print "$version\n"; exit 0; } sub wrong_usage { print STDERR "Try '$0 --help' for more information.\n"; exit -1; } __END__ # --------------------------------------------------------------------------- =head1 NAME fvwm-menu-headlines - builds headlines menu definition for fvwm =head1 SYNOPSIS B<fvwm-menu-headlines> [ B<--help>|B<-h>|B<-?> ] [ B<--version>|B<-V> ] [ B<--info> [site] ] [ B<--site>|B<-s> site ] [ B<--name>|B<-n> name ] [ B<--title>|B<-t> title ] [ B<--item> item ] [ B<--exec>|B<-e> exec-command ] [ B<--command>|B<-e> fvwm-command ] [ B<--icon-title> icon ] [ B<--icon-item> icon ] [ B<--icon-home> icon ] [ B<--icon-error> icon ] [ B<--wm-icons> ] [ B<--frontpage> [where] ] [ B<--proxy>|B<-p> host:port ] [ B<--file> [file] ] [ B<--fake> [file] ] [ B<--timeout> seconds ] =head1 DESCRIPTION This configurable perl script builds an fvwm menu definition for headlines of popular news web sites: FreshMeat, Slashdot, LinuxToday, DaemonNews, GNOME-News, KDE-News, RootPrompt, LinuxFr, ThinkGeek, CNN, BBC and more. It is possible to specify a customized menu item format, change a command (usually launching a browser) and add menu icons (there is a support for the wm-icons package). =head1 OPTIONS =over 4 =item B<--help> show the help and exit =item B<--version> show the version and exit =item B<--info> [site] if site name is given print the site specific info, otherwise print all site names =item B<--site> site defile a web site, headlines of which to show, this option also can be used together with --help to get new defaults. Default site: freshmeat. =item B<--name> name define menu name (default is "MenuHeadlinesFreshmeat") =item B<--title> title define menu title (default is "Freshmeat Headlines"). =item B<--item> label-format =item B<--exec> command-format define format for menu item or command (what is shown and what is executed when the item is chosen). Default label is '%h\t%[(%Y-%m-%d %H:%M)]'. TAB can be specified as '\t', but in .fvwm2rc you should specify a double backslash or a real TAB. Format specifiers for a headline format: %h - headline %u - url %d - date in the native format (that site backend supplied) %[strftime-argument-string] - date/time, see strftime(3) the date/time is represented according to the local time; date and/or time fields that can't be guessed are stripped Example: %[|%d %B %Y| %H:%M %S] If site supplied only date - this becomes %[|%d %B %Y|], if site supplied no date - this becomes an empty string. %{name} - site specific named value, like %{comments} %(text) - arbitrary text, good for escaping or aligning These specifiers can receive an optional integer size, positive for right adjusted string or negative for left adjusted, example: %8x; and optional *num or *-num, which means to leave only the first or last (if minus) num of chars, the num must be greater than 3, since the striped part is replaced with "...", example: %*30x. Both can be combined: %-10*-20x, this instructs to get only the 20 last characters, but if the length is less then 10 - to fill with up to 10 spaces on the right. Example: --exec "iceweasel -remote 'openURL(%u, new-window)' || iceweasel '%u'" =item B<--command> command-format like B<--exec> above, but enables to specify any fvwm command, for example, "Function FuncFvwmShowURL '%u'" not only Exec. In fact, --exec="mozilla '%u'" is equivalent to --command="Exec mozilla '%u'" =item B<--icon-title> icon =item B<--icon-item> icon =item B<--icon-home> icon =item B<--icon-error> icon define menu icon for title, regular item, frontpage item and error item respectively. Default is no menu icons (equivalent to an empty icon argument). =item B<--wm-icons> define icon names suitable for use with wm-icons package. Currently this is equivalent to: --icon-title '' --icon-item menu/information.xpm --icon-home menu/home.xpm --icon-error menu/choice-no.xpm. =item B<--frontpage> [where] add the site frontpage item to the menu. Optional value can be used to specify where this item will be placed in the menu - 'top' or 't', 'bottom' or 'b'. =item B<--proxy> host[:port] define a proxy to use. Example: --proxy proxy.inter.net:3128 =item B<--file> [file] write the menu output to specified file. If no filename is given with this option (or empty filename), the default filename WORK_HOME/SITE.menu is used. Without this option or with '-' filename, the menu output is written to standard output. =item B<--fake> [file] don't connect to the host using HTTP protocol, instead, read from WORK_HOME/SITE.in file. The following reads input from freshmeat.in (downloaded http://freshmeat.net/backend/recentnews.txt) and saves output to segfault.menu (both files are in WORK_HOME): fvwm-menu-headlines --site freshmeat --fake --file =item B<--timeout> seconds limit a line reading from a socket to this timeout, the default timeout is 20 seconds. =back WORK_HOME of this script is ~/.fvwm/.fvwm-menu-headlines. It is created if needed. Option parameters can be specified either using '=' or in the next argument. Short options are ok if not ambiguous: C<-h>, C<-t>; but be careful with short options, what is now unambiguous, can become ambiguous in the next versions. =head1 USAGE 1. One of the ways to use this script is to define a crontab entry to run the script every hour or so for every monitored site: 0,30 * * * * fvwm-menu-headlines --file --site freshmeat 1,31 * * * * fvwm-menu-headlines --file --site linuxtoday 2,32 * * * * fvwm-menu-headlines --file --site slashdot Then add these lines to your fvwm configuration file: DestroyFunc FuncFvwmMenuHeadlines AddToFunc FuncFvwmMenuHeadlines + I Read "$HOME/.fvwm/.fvwm-menu-headlines/$0.menu" DestroyMenu MenuHeadlines AddToMenu MenuHeadlines "Headlines" Title + MissingSubmenuFunction FuncFvwmMenuHeadlines + "FreshMeat" Popup freshmeat + "LinuxToday" Popup linuxtoday + "Slashdot" Popup slashdot 2. Another way to use this script (only if you have fast network/proxy) is to run it every time you want to open your Headlines submenus. (Note, the submenu that is once created is not reloaded, use "Reset all".) In this case your fvwm configuration lines could be: DestroyFunc FuncFvwmMenuHeadlines AddToFunc FuncFvwmMenuHeadlines + I PipeRead "fvwm-menu-headlines --site $0" #+ I Schedule 900000 DestroyMenu $0 # reset generated menu in 15 minutes DestroyMenu MenuHeadlines AddToMenu MenuHeadlines "Headlines" Title + MissingSubmenuFunction FuncFvwmMenuHeadlines + "FreshMeat" Popup freshmeat + "Slashdot" Popup slashdot + "LinuxToday" Popup linuxtoday + "GNOME News" Popup gnome-news + "KDE News" Popup kde-news + "" Nop + "Reset all" FuncResetHeadlines DestroyFunc FuncResetHeadlines AddToFunc FuncResetHeadlines + I DestroyMenu freshmeat + I DestroyMenu linuxtoday + I DestroyMenu slashdot + I DestroyMenu gnome-news + I DestroyMenu kde-news And finally, add "Popup MenuHeadlines" somewhere. 3. Here is a usual usage. Use FvwmConsole or FvwmCommand to run fvwm commands from a shell script. Every time you want headlines from some site, execute (give any additional options if you want): PipeRead "fvwm-menu-headlines --site newsforge --name MenuHeadlinesNewsForge" # this may take several seconds, you may use: BusyCursor Read true Popup MenuHeadlinesNewsForge =head1 HOW TO ADD SITE HEADLINES It is possible to add user defined site headlines without touching the script itself. Put your perl extensions to the file WORK_HOME/extension.pl. For each site add something similar to: $site_info->{'myslashdot'} = { 'name' => "MySlashdot", 'host' => "myslashdot.org", 'path' => "/myslashdot.xml", 'func' => \&process_my_slashdot, # the following string is only used in --info 'flds' => 'time, title, department, topic, author, url', }; sub process_my_slashdot () { return process_xml( 'story', # mandatory 'h', 'u' and 'd' aliases or undef { 'h' => 'title', 'u' => 'url', 'd' => 'time' }, sub ($) { # convert 'd' string to (y, m, d, H, M, S) $_[0] =~ /(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)/; ($1, ($2 || 0) - 1, $3, $4, $5, $6); }, +0, # timezone offset; already in UTC ); } 1; =head1 AUTHORS This script is inspired by WMHeadlines v1.3 by: Jeff Meininger <jeffm@boxybutgood.com> (http://rive.boxybutgood.com/WMHeadlines/). Reimplemented for fvwm and heavily enhanced by: Mikhael Goikhman <migo@homemail.com>, 16 Dec 1999. =head1 COPYING The script is distributed by the same terms as fvwm itself. See GNU General Public License for details. =head1 BUGS I try to keep all supported site info up to date, but sites often go down, change their backend formats, change their httpd responses, just stop to post news and so on; the script in the latest cvs may be more up to date. The headline times may be off by one hour or more, since the time is displayed for your local time zone, and the time zone of the original time in the site backend output is often guessed (sometimes incorrectly); similarly it is guessed whether to apply the daylight saving correction. Report bugs to fvwm-bug@fvwm.org. =cut # =========================================================================== ������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/bin/fvwm-root.1.in�����������������������������������������������������������������������0000644�0001750�0001750�00000007221�14147024700�012620� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������'\" t .\" @(#)@PACKAGE@-@VERSION@ @RELDATELONG@ .TH fvwm-root 1 "@RELDATELONG@ (@VERSION@)" Fvwm "Fvwm Modules" .UC .SH NAME fvwm-root \- Sets the root window of the current X display to image .SH SYNOPSIS .B fvwm-root .RB [ "--retain-pixmap" | "-r" ] .RB [ "--no-retain-pixmap" ] .RB [ "--dummy" | "-d" ] .RB [ "--no-dummy" ] .RB [ "--dither" ] .RB [ "--no-dither" ] .RB [ "--color-limit" .RI [ ncolors "] ]" .RB [ "--no-color-limit" ] .RB [ "--help" | "-h" | "-?" ] .RB [ "--version" | "-V" ] .I image_file .SH DESCRIPTION .I fvwm-root reads the image file specified in the command line and displays it in the root window. The supported image formats are .IR XBM ", " XPM ", " PNG " and " SVG if appropriated libraries are compiled in. SVG rendering options .RB " (as described in the " " ICONS AND IMAGES " section of the main fvwm documentation) can be utilized. .SH OPTIONS These command line options are recognized by fvwm-root: .TP .BR "--retain-pixmap" " | " "-r" Causes fvwm-root to retain and publish the Pixmap with which the background has been set (the ESETROOT_PMAP_ID and _XROOTPMAP_ID properties are used). This is useful for applications which want to use the root Pixmap on the background to simulate transparency (for example, Eterm and Aterm use this method). This option should also be used for the RootTransparent colorset option, refer to the COLORSETS section of fvwm(1). If this option is not used, fvwm-root sets the _XSETROOT_ID property to None, and some programs, like fvwm modules, may use this to update their background if the background is transparent (Transparent colorset). Note, a well behaved program, like fvwm, should listen to both _XSETROOT_ID and _XROOTPMAP_ID property changes and update itself correspondingly. However some programs listen only to one of them, so you should either use this option or not depending on what part is implemented by these programs. You should also use this option to get fast root-transparent menus in fvwm. .TP .BI "--no-retain-pixmap" This is a default. May be useful to explicitly force the default even if "--retain-pixmap" is specified earlier. .TP .BR "--dummy" " | " "-d" Causes fvwm-root NOT to set the background, but to only free a memory associated with the ESETROOT_PMAP_ID property (if any). In any case the _XSETROOT_ID property is set to None. .TP .BI "--no-dummy" This is a default. May be useful to explicitly force the default even if "--dummy" is specified earlier. .TP .BI "--dither" Causes fvwm-root to dither images for "smoother" rendition on displays with color depth of 16 or lower. This the default with color depth less or equal to 8. .TP .BI "--no-dither" Causes fvwm-root NOT to dither images. This is the default with color depth greater than 8. .TP .BI "--color-limit " ncolors Causes fvwm-root to limit its color use to .I ncolors (if specified). This option is taken in account only with color depth less or equal to 8 (and a TrueColor or GrayScale visual). The default is to use the same color limit as fvwm. So in normal situation this option is not useful. However, if fvwm use a private colors map, as fvwm-root always use the default colors map you should use this option for limiting colors correctly. If .I ncolors is not specified a default is used. .TP .BI "--no-color-limit" Causes fvwm-root NOT to limit its color use. .TP .BI "--help" Shows a short usage. .TP .BI "--version" Shows a version number. .SH COMPATIBILITY In the past this utility was called .IR xpmroot . This name is still supported as a symlink. .SH BUGS Repeated use of fvwm-root with different xpm pixmaps will use up slots in your color table pretty darn fast. .SH AUTHOR Rob Nation Rewritten and enhanced by fvwm-workers. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/bin/fvwm-menu-directory.1����������������������������������������������������������������0000644�0001750�0001750�00000036317�14147024700�014206� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" Automatically generated by Pod::Man 2.16 (Pod::Simple 3.02) .\" .\" Standard preamble: .\" ======================================================================== .de Sh \" Subsection heading .br .if t .Sp .ne 5 .PP \fB\\$1\fR .PP .. .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .ie \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .el \{\ . de IX .. .\} .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "fvwm-menu-directory 1" .TH fvwm-menu-directory 1 "2009-03-22" "2.5.28 (from cvs)" "Fvwm Utilities" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" fvwm\-menu\-directory \- builds a directory browsing menu for fvwm .SH "SYNOPSIS" .IX Header "SYNOPSIS" \&\fBfvwm-menu-directory\fR [ \fB\-\-help\fR|\fB\-h\fR|\fB\-?\fR ] [ \fB\-\-version\fR|\fB\-V\fR ] [ \fB\-\-name\fR|\fB\-na\fR \s-1NAME\s0 ] [ \fB\-\-title\fR|\fB\-t\fR \s-1NAME\s0 ] [ \fB\-\-item\fR|\fB\-it\fR \s-1NAME\s0 ] [ \fB\-\-icon\-title\fR|\fB\-icon\-t\fR \s-1XPM\s0 ] [ \fB\-\-icon\-dir\fR|\fB\-icon\-d\fR \s-1XPM\s0 ] [ \fB\-\-icon\-file\fR|\fB\-icon\-f\fR \s-1XPM\s0 ] [ \fB\-\-icon\-app\fR|\fB\-icon\-a\fR \s-1XPM\s0 ] [ \fB\-\-wm\-icons\fR ] [ \fB\-\-dir\fR|\fB\-d\fR \s-1NAME\s0 ] [ \fB\-\-order\fR|\fB\-o\fR \s-1NUM\s0 ] [ \fB\-\-[no]all\fR|\fB\-a\fR ] [ \fB\-\-[no]links\fR|\fB\-l\fR ] [ \fB\-\-xterm\fR|\fB\-x\fR \s-1CMD\s0 ] [ \fB\-\-exec\-title\fR|\fB\-exec\-t\fR \s-1CMD\s0 ] [ \fB\-\-exec\-file\fR|\fB\-exec\-f\fR \s-1CMD\s0 ] [ \fB\-\-exec\-app\fR|\fB\-exec\-a\fR [\s-1CMD\s0] ] [ \fB\-\-command\-title\fR|\fB\-command\-t\fR \s-1CMD\s0 ] [ \fB\-\-command\-file\fR|\fB\-command\-f\fR \s-1CMD\s0 ] [ \fB\-\-command\-app\fR|\fB\-command\-a\fR \s-1CMD\s0 ] [ \fB\-\-[no]reuse\fR|\fB\-r\fR ] [ \fB\-\-[no]check\-subdirs\fR|\fB\-ch\fR ] [ \fB\-\-special\-dirs\fR|\fB\-s\fR [\s-1VALUE\s0] ] [ \fB\-\-[no]memory\-for\-speed\fR|\fB\-mem\fR ] [ \fB\-\-menu\-style\fR|\fB\-men\fR \s-1NAME\s0 ] [ \fB\-\-func\-name\fR|\fB\-f\fR \s-1NAME\s0 ] .SH "DESCRIPTION" .IX Header "DESCRIPTION" A perl script which provides an output to read in with PipeRead to build an fvwm menu containing a directory listing. Almost everything can be configured. .SH "HINTS" .IX Header "HINTS" The title item with its own attached action is usually added to the menu. This may be used to define an action for the directory for which the menu is built, such as starting a terminal in this directory (the default). However, this may annoy some users. To disable the title action use \fB\-\-command\-title\fR "", to remove the title completely use \fB\-\-title\fR "". .SH "OPTIONS" .IX Header "OPTIONS" .IP "\fB\-\-help\fR" 4 .IX Item "--help" show the usage and exit .IP "\fB\-\-version\fR" 4 .IX Item "--version" show version and exit .IP "\fB\-\-name\fR name" 4 .IX Item "--name name" menu name, used only with \-\-reuse, default is MenuBrowser .IP "\fB\-\-title\fR title" 4 .IX Item "--title title" menu title format, default is '%*\-40p' \- last 40 characters of the current full path. \s-1TAB\s0 can be specified as '\et', but in .fvwm2rc you should specify a double backslash or a real \s-1TAB\s0. .Sp Format specifiers: \f(CW%d\fR \- the current directory name \f(CW%p\fR \- the current directory full path .Sp These specifiers can receive an optional integer size, positive for right adjusted string or negative for left adjusted, example: \f(CW%8x\fR; and optional *num or *\-num, which means to leave only the first or last (if minus) num of chars, the num must be greater than 3, since the striped part is replaced with \*(L"...\*(R", example: %*30x. Both can be combined: %\-10*\-20x, this instructs to get only the 20 last characters, but if the length is less then 10 \- to fill with up to 10 spaces on the right. .IP "\fB\-\-item\fR format" 4 .IX Item "--item format" menu item format, default is '%n'. \s-1TAB\s0 and width modifiers for \f(CW%n\fR, \f(CW%N\fR and \f(CW%s\fR can be specified as described in \fB\-\-title\fR above. Note, specifying a non default format slows the script. .Sp Format specifiers: .Sp .Vb 7 \& %n \- file/dir name (without the path) \& %N \- file/dir name (full with the path) \& %d \- file/dir date (yyyy\-mm\-dd HH:MM:SS) \& %D \- file/dir date (yyyy\-mm\-dd) \& %s \- file/dir size (in bytes) \& %t \- file/dir type (File|Dir |Link|Sock|Blck|Char|Pipe) \& %T \- file/dir type (F|D|L|S|B|C|P) .Ve .Sp Example: \-\-title '%*\-40p\etDate, Type\etSize' \-\-item '%*40n\et%d \f(CW%t\fR\et%s' .IP "\fB\-\-icon\-title\fR icon" 4 .IX Item "--icon-title icon" menu title icon, default is none .IP "\fB\-\-icon\-dir\fR icon" 4 .IX Item "--icon-dir icon" menu dir icon, default is none .IP "\fB\-\-icon\-file\fR icon" 4 .IX Item "--icon-file icon" menu file icon, default is none .IP "\fB\-\-icon\-app\fR icon" 4 .IX Item "--icon-app icon" menu application icon, default is none .IP "\fB\-\-wm\-icons\fR" 4 .IX Item "--wm-icons" define icon names suitable for use with wm-icons package. Currently this is equivalent to: \-\-icon\-title menu/folder\-open.xpm \-\-icon\-item menu/file.xpm \-\-icon\-dir menu/folder.xpm \-\-icon\-app menu/utility.xpm. .IP "\fB\-\-dir\fR dir" 4 .IX Item "--dir dir" starting dir, default is ${\s-1HOME\-\s0.} .IP "\fB\-\-order\fR number" 4 .IX Item "--order number" in the range (\-6 .. 6), default is 5: .Sp .Vb 3 \& 1 \- do not sort, 2 \- dirs first, 3 \- files first \& 4 \- sort by name, 5 \- dirs first, 6 \- files first \& Negative number represents reverse order. .Ve .IP "\fB\-\-[no]all\fR" 4 .IX Item "--[no]all" show hidden files, like in 'ls \-A', default is \-\-noall .IP "\fB\-\-[no]links\fR" 4 .IX Item "--[no]links" follow linked directories, default is \-\-nolinks .IP "\fB\-\-xterm\fR command" 4 .IX Item "--xterm command" X terminal call, default is 'xterm \-e' .IP "\fB\-\-exec\-title\fR command" 4 .IX Item "--exec-title command" an fvwm Exec command on directory title (usually the shell), default is ${SHELL\-/bin/sh}. '\-' means no Exec command, i.e. Nop. If the command is not started with '^' X terminal call is prepended. The command is started in the currently browsed directory. .IP "\fB\-\-exec\-file\fR command" 4 .IX Item "--exec-file command" an fvwm Exec command on regular files, default is ${EDITOR\-vi}. '\-' means no Exec command, i.e. Nop. If the command is not started with '^' X terminal call is prepended. The actual file name is appended to the command. .IP "\fB\-\-exec\-app\fR [command]" 4 .IX Item "--exec-app [command]" an fvwm Exec command on +x files, default is '\-', which means the same command as on regular files. If no command is given, it is assumed to be empty \- simply run the +x file. If the command is not started with '^' X terminal call is prepended. The actual file name is appended to the command. .IP "\fB\-\-command\-title\fR command" 4 .IX Item "--command-title command" an fvwm command to execute on title. If this option is not given (or command is '\-'), the \f(CW\*(C`\-\-exec\-title\*(C'\fR is used instead. In the command, \f(CW%d\fR is substituted with the full directory path. .Sp In fact, \fI\-\-exec\-title=tcsh\fR is equivalent to \fI\-\-command\-title='Exec cd \*(L"%d\*(R"; xterm \-e tcsh'\fR .Sp The empty value disables the title action. .IP "\fB\-\-command\-file\fR command" 4 .IX Item "--command-file command" an fvwm command to execute on regular files. If this option is not given (or command is '\-'), the \f(CW\*(C`\-\-exec\-file\*(C'\fR is used instead. In the command, \f(CW%f\fR is substituted with the full file path. .Sp In fact, \-\-exec\-file=vi is equivalent to \-\-command\-file='Exec xterm \-e vi \*(L"%f\*(R"' .IP "\fB\-\-command\-app\fR command" 4 .IX Item "--command-app command" an fvwm command to execute on +x files. If this option is not given (or command is '\-'), the \f(CW\*(C`\-\-command\-app\*(C'\fR is used instead. In the command, \f(CW%f\fR is substituted with the full file path. .Sp In fact, \-\-exec\-app=^exec is equivalent to \-\-command\-app='Exec exec \*(L"%f\*(R"' .IP "\fB\-\-[no]reuse\fR" 4 .IX Item "--[no]reuse" no pop-up menus, reuse the same menu, default is \-\-noreuse. When you specify this option the Menu action is used, not Popup. Also, the \-\-name parameter is not ignored, and \-\-dir parameter is ignored if there is ~/.fvwm/.fvwm\-menu\-directory.dir file. This file is only created or used with this option specified, it is the only solution for the current fvwm menu state. .IP "\fB\-\-[no]check\-subdirs\fR" 4 .IX Item "--[no]check-subdirs" check all subdirs for having execute (+x) permission and replace \*(L"Popup\*(R"/\*(L"Menu\*(R" command with \*(L"Nop\*(R" for these without permissions. This has a visual effect of disabling popup triangle in the subdirectory item. The default is \-\-nocheck\-subdirs, because: 1) enabling this slows a bit the script, 2) with this option enabled, if no icons used and no dir/file separate sorting used there is no way to know that the item is directory and not file. .IP "\fB\-\-special\-dirs\fR value" 4 .IX Item "--special-dirs value" add .. or ~ or / special directories according to given optional value. Without with option these directories are not added. Default value if not specified is \*(L"1,2\*(R". The value is comma separated ordered special directory indexes, where 1 is parent directory, 2 is home directory, 3 is root directory. If minus is prepended to the value, special directories are added at the bottom of menu instead of top. Value \*(L"0\*(R" or any bad value is equivalent to non-specifying this option at all. .IP "\fB\-\-[no]memory\-for\-speed\fR" 4 .IX Item "--[no]memory-for-speed" use speed optimization, i.e. use previously created directory menus without destroying it when closed, default is \-\-nomemory\-for\-speed .Sp .Vb 2 \& Warning: speed optimization takes up a lot of memory \& that is never free\*(Aqd again while fvwm is running. .Ve .IP "\fB\-\-menu\-style\fR name" 4 .IX Item "--menu-style name" assign MenuStyle name to the menus .IP "\fB\-\-func\-name\fR name" 4 .IX Item "--func-name name" overwrite the default MissingSubmenuFunction name that is \*(L"FuncFvwmMenuDirectory\*(R" .PP Option parameters can be specified either using '=' or in the next argument. Short options are ok if not ambiguous: \f(CW\*(C`\-a\*(C'\fR, \f(CW\*(C`\-x\*(C'\fR, \f(CW\*(C`\-icon\-f\*(C'\fR; but be careful with short options, what is now unambiguous, can become ambiguous in the next versions. .SH "USAGE" .IX Header "USAGE" Put this into your fvwm configuration file to invoke the script: .PP .Vb 2 \& AddToFunc FuncFvwmMenuDirectory \& + I PipeRead "fvwm\-menu\-directory \-d \*(Aq$0\*(Aq" .Ve .PP More complex example: .PP .Vb 4 \& # AddToFunc FuncFvwmMenuDirectory \& # + I PipeRead "fvwm\-menu\-directory \-d \*(Aq$0\*(Aq \-x \*(AqEterm \-g 80x40 \-e\*(Aq \e\e \& \-a \-l \-o 6 \-\-exec\-app \-\-exec\-title \*(Aqtcsh \-l\*(Aq \-\-exec\-file \*(Aqvim \-R\*(Aq \e\e \& \-t \*(AqGo to: %d\*(Aq \-\-wm\-icons" .Ve .PP And put this in the menu from which you want to pop-up the directory menus: .PP .Vb 3 \& AddToMenu SomeMenu MissingSubmenuFunction FuncFvwmMenuDirectory \& + "Home Directory" Popup $[HOME] \& + "Httpd Directory" Popup /home/httpd .Ve .PP Note: please use absolute path names. .PP It is a good idea to set the menu pop-up delay to something positive and enable busy cursor .PP .Vb 2 \& MenuStyle * PopupDelayed, PopupDelay 200 \& BusyCursor DynamicMenu True .Ve .PP in your configuration file when using this script for better results. .PP Another interesting usage (\f(CW\*(C`\-\-reuse\*(C'\fR or \f(CW\*(C`\-r\*(C'\fR is mandatary for this): .PP .Vb 4 \& AddToMenu Browser \& + DynamicPopupAction PipeRead \e\e \& "fvwm\-menu\-directory \-r \-na Browser \-d / \-s" \& AddToMenu SomeMenu "My Browser" Menu Browser .Ve .PP Here the \f(CW\*(C`\-\-dir\*(C'\fR parameter (starting directory) is ignored if there is ~/.fvwm/.fvwm\-menu\-directory.dir file, which you can delete. .SH "AUTHORS" .IX Header "AUTHORS" Inspired on 1999\-06\-07 by Dominik Vogt <domivogt@fvwm.org>. .PP Rewritten on 1999\-08\-05 by Mikhael Goikhman <migo@homemail.com>. .SH "COPYING" .IX Header "COPYING" The script is distributed by the same terms as fvwm itself. See \s-1GNU\s0 General Public License for details. .SH "BUGS" .IX Header "BUGS" Report bugs to fvwm\-bug@fvwm.org. �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/bin/fvwm-menu-xlock.in�������������������������������������������������������������������0000644�0001750�0001750�00000017056�14147024700�013567� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!@PERL@ # Copyright (c) 1999-2009 Mikhael Goikhman # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see: <http://www.gnu.org/licenses/> # Filter this script to pod2man to get a man page: # pod2man -c "Fvwm Utilities" fvwm-menu-xlock | nroff -man | less -e use Getopt::Long; my $version = "@VERSION@"; my $name = 'XLockMenu'; my $title = 'XLock Modes'; my $itemf = '%n\t(%d)'; # may contain %n, %d, %D. my $icont = ''; my $iconi = ''; my $wm_icons = 0; my $special_first = 0; GetOptions( "help|h|?" => \&show_help, "version|V" => \&show_version, "name=s" => \$name, "title=s" => \$title, "item=s" => \$itemf, "icon-title=s" => \$icont, "icon-item=s" => \$iconi, "wm-icons" => \$wm_icons, "special-first" => \$special_first, ) || wrong_usage(); if ($wm_icons) { $icont ||= ""; $iconi ||= "menu/lock.xpm"; } my $icont_str = $icont ? "%$icont%" : ""; my $iconi_str = $iconi ? "%$iconi%" : ""; my $params = @ARGV ? ' ' . join(' ', @ARGV) : ''; my $lines1 = ""; # non-special mode lines my $lines2 = ""; # special mode lines my $start = 0; my $special = 0; $itemf =~ s/\\t/\t/g; open(XL, "xlock -display NONE -help 2>&1 |") || die "Exec echo 'Could not run xlock'\n"; print "DestroyMenu $name\n"; print "AddToMenu $name \"$icont_str$title\" Title\n"; while (<XL>) { chomp; /where mode is one of:/ && do { $start = 1; next; }; if ($start && $_) { my ($misc, $name, $dsc) = split(/\s+/, $_, 3); next if $name =~ /^-/; my $dsc2 = $dsc =~ /^Shows (.*)$/ ? $1 : $dsc; my $item_str = $itemf; $item_str =~ s/\\t/\t/g; &expand_width_specifier(\$item_str, 'n', $name); &expand_width_specifier(\$item_str, 'd', $dsc); &expand_width_specifier(\$item_str, 'D', $dsc2); $special = 1 if !$special && $name eq 'blank'; ($special ? $lines2 : $lines1) .= qq(+ "$iconi_str$item_str" Exec xlock$params -mode $name\n); } } close XL; print $special_first ? qq($lines2+ "" Nop\n$lines1) : qq($lines1+ "" Nop\n$lines2); exit(0); # --------------------------------------------------------------------------- # Substitutes all %N1*N2x in $name by properly stripped and justified $value. sub expand_width_specifier (\$$$) { my ($name, $char, $value) = @_; $$name =~ s/%(-?\d+)?(\*(-?)(\d+))?$char/ my $value = !$2 || $4 <= 3 || $4 > length($value) ? $value : $3 ? "..." . substr($value, -$4 + 3, $4 - 3) : substr($value, 0, $4 - 3) . "..."; $1? sprintf("%$1s", $value): $value; /ge; } sub show_help { print "A small perl script which builds xlock menu for fvwm.\n\n"; print "Usage: $0 [OPTIONS] [-- XLOCK-OPTIONS]\n"; print "Options:\n"; print "\t--help show this help and exit\n"; print "\t--version show the version and exit\n"; print "\t--name=NAME menu name, default is '$name'\n"; print "\t--title=NAME menu title, default is '$title'\n"; print "\t--item=NAME menu item format, default is '$itemf'\n"; print "\t--icon-title=XPM menu title icon, default is no\n"; print "\t--icon-item=XPM menu item icon, default is no\n"; print "\t--wm-icons define icon names to use with wm-icons\n"; print "\t--special-first put special modes first\n"; print "Short options are ok if not ambiguous: -h, -t.\n"; print "\nSome useful xlock(1) options, 'xlock -h' for more:\n"; print "\t-delay usecs delay between batches of animations\n"; print "\t-nolock screensaver, don't lock the display\n"; print "\t-inwindow run in window as opposite to -inroot\n"; print "\t-sound turn on sound if enabled\n"; print "\t-nice level decrease the process priority (0 .. 19)\n"; exit 0; } sub show_version { print "$version\n"; exit 0; } sub wrong_usage { print STDERR "Try '$0 --help' for more information.\n"; exit -1; } __END__ # --------------------------------------------------------------------------- =head1 NAME fvwm-menu-xlock - builds xlock menu definition for fvwm =head1 SYNOPSIS B<fvwm-menu-xlock> [ B<--help>|B<-h>|B<-?> ] [ B<--version>|B<-V> ] [ B<--name>|B<-n> name ] [ B<--title>|B<-t> title ] [ B<--item> format ] [ B<--icon-title> icon ] [ B<--icon-item> icon ] [ B<--special-first>|B<-s> ] [ -- xlock params ] =head1 DESCRIPTION A simple perl script which parses xlock's output to build an fvwm menu definition of all xlock's modes. =head1 OPTIONS =over 4 =item B<--help> show the help and exit =item B<--version> show the version and exit =item B<--name> name define menu name in the following argument. Default is "XLockMenu" =item B<--title> title define menu title in the following argument. Default is "XLock Modes". =item B<--item> format define menu item format in the following argument, default is '%n\t(%d)'. TAB can be specified as '\t', but in .fvwm2rc you should specify a double backslash or a real TAB. Format specifiers: %n - mode name %d - mode description %D - mode description without "Shows " prefix if any These specifiers can receive an optional integer size, positive for right adjusted string or negative for left adjusted, example: %8x; and optional *num or *-num, which means to leave only the first or last (if minus) num of chars, the num must be greater than 3, since the striped part is replaced with "...", example: %*30x. Both can be combined: %-10*-20x, this instructs to get only the 20 last characters, but if the length is less then 10 - to fill with up to 10 spaces on the right. =item B<--icon-title> icon =item B<--icon-item> icon define menu icon for title and regular item accordingly. Default is no menu icons (equivalent to an empty icon argument). =item B<--wm-icons> define icon names suitable for use with wm-icons package. Currently this is equivalent to: --icon-title '' --icon-item menu/lock.xpm. =item B<--special-first> instructs to include special modes (usually black, bomb and random) first. =back Option parameters can be specified either using '=' or in the next argument. Short options are ok if not ambiguous: -h, -t; but be careful with short options, what is now unambiguous, can became ambiguous in the next versions. Additional arguments (after B<-->) will be passed to xlock. Please see the B<xlock>(1) man page for the xlock options. =head1 USAGE Add these lines to your fvwm configuration file: PipeRead 'fvwm-menu-xlock --name MenuSSaver --title "Screensaver" \ --icon-item mini-bball.xpm --special-first -- -nice 19 -nolock' PipeRead 'fvwm-menu-xlock --name MenuSLock --title "Lock Screen" \ --icon-item mini-rball.xpm --special-first -- -nice 19' AddToMenu "Utilities" "Screensaver%mini-monitor.xpm%" Popup MenuSSaver AddToMenu "Utilities" "Screenlock%mini-lock.xpm%" Popup MenuSLock =head1 AUTHORS Charles K. Hines <chuck_hines@vnet.ibm.com>, initial version. Mikhael Goikhman <migo@homemail.com>, from 24 Feb 1999. =head1 COPYING The script is distributed by the same terms as fvwm itself. See GNU General Public License for details. =head1 BUGS Depends on the output of xlock. Will produce an empty menu if the structure of the output is changed. Report bugs to fvwm-bug@fvwm.org. =cut # *************************************************************************** ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/bin/fvwm-config.in�����������������������������������������������������������������������0000644�0001750�0001750�00000014405�14147024700�012745� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/bin/sh # Querying fvwm installation. Author: Mikhael Goikhman. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see: <http://www.gnu.org/licenses/> PACKAGE="@PACKAGE@" VERSION="@VERSION@" script=`basename $0` usage() { cat <<EOF This script is a part of $PACKAGE-$VERSION package. Usage: $script [OPTIONS] Options: [-h] [--help] [-?] [-v] [--version] [-V] [-i] [--info] [-P] [--prefix] [-E] [--exec-prefix] [-B] [--bindir] [--datarootdir] [-D] [--datadir] [-L] [--libexecdir] [-S] [--sysconfdir] [-M] [--mandir] [-O] [--localedir] [-m] [--fvwm-moduledir] [-d] [--fvwm-datadir] [-p] [--fvwm-perllibdir] [-I] [--default-imagepath] [-U] [--default-userdir] [-e] [--fvwm-exe] print fvwm executable name (in bindir) [-s] [--supports] list supported features, one per line [--supports-<feature>] return: 0 (yes), 100 (no), 200 (unknown) EOF exit $1 } if test $# -eq 0; then usage 1 1>&2 fi prefix="@prefix@" exec_prefix="@exec_prefix@" bindir="@bindir@" datarootdir="@datarootdir@" datadir="@datadir@" libexecdir="@libexecdir@" sysconfdir="@sysconfdir@" mandir="@mandir@" localedir="@LOCALEDIR@" fvwm_moduledir="@FVWM_MODULEDIR@" fvwm_datadir="@FVWM_DATADIR@" fvwm_perllibdir="@FVWM_PERLLIBDIR@" fvwm_imagepath="@FVWM_IMAGEPATH@" fvwm_userdir='$HOME/.fvwm' fvwm_exe='fvwm' VERSIONINFO="@VERSIONINFO@" release_date="@RELDATENUM@" with_bidi=@with_bidi@ with_gettext=@with_gettext@ with_gdkimlib=@with_gdkimlib@ with_gnomelibs=@with_gnomelibs@ with_iconv=@with_iconv@ with_perllib=@with_perllib@ with_png=@with_png@ with_readline=@with_readline@ with_rplay=@with_rplay@ with_rsvg=@with_rsvg@ with_shape=@with_shape@ with_shm=@with_shm@ with_sm=@with_sm@ with_stroke=@with_stroke@ with_xcursor=@with_xcursor@ with_xinerama=@with_xinerama@ with_xft=@with_xft@ with_xpm=@with_xpm@ with_xrender=@with_xrender@ while test $# -gt 0; do case "$1" in --help|-help|-h|-\?) usage 0 ;; --version|-version|-v|-V) echo "$VERSION" ;; --prefix|-prefix|-P) echo "$prefix" ;; --exec-prefix|-exec-prefix|-E) echo "$exec_prefix" ;; --bindir|-bindir|-B) echo "$bindir" ;; --datarootdir|-datarootdir) echo "$datarootdir" ;; --datadir|-datadir|-D) echo "$datadir" ;; --libexecdir|-libexecdir|-L) echo "$libexecdir" ;; --sysconfdir|-sysconfdir|-S) echo "$sysconfdir" ;; --mandir|-mandir|-M) echo "$mandir" ;; --localedir|-localedir|-O) echo "$localedir" ;; --fvwm-moduledir|-fvwm-moduledir|-m) echo "$fvwm_moduledir" ;; --fvwm-datadir|-fvwm-datadir|-d) echo "$fvwm_datadir" ;; --fvwm-perllibdir|-fvwm-perllibdir|--perllibdir|-perllibdir|-p) echo "$fvwm_perllibdir" ;; --default-imagepath|-default-imagepath|-I) echo "$fvwm_imagepath" ;; --default-userdir|-default-userdir|-U) echo "$fvwm_userdir" ;; --fvwm-exe|-fvwm-exe|-e) echo "$fvwm_exe" ;; --supports|-supports|-s) test "$with_bidi" = "yes" && echo "bidi" test "$with_gettext" = "yes" && echo "gettext" test "$with_gdkimlib" = "yes" && echo "gdk-imlib" test "$with_gnomelibs" = "yes" && echo "gnome-libs" test "$with_iconv" = "yes" && echo "iconv" test "$with_perllib" = "yes" && echo "perllib" test "$with_png" = "yes" && echo "png" test "$with_readline" = "yes" && echo "readline" test "$with_rplay" = "yes" && echo "rplay" test "$with_rsvg" = "yes" && echo "rsvg" test "$with_shape" = "yes" && echo "shape" test "$with_shm" = "yes" && echo "shm" test "$with_sm" = "yes" && echo "sm" test "$with_stroke" = "yes" && echo "stroke" test "$with_xcursor" = "yes" && echo "xcursor" test "$with_xinerama" = "yes" && echo "xinerama" test "$with_xft" = "yes" && echo "xft" test "$with_xpm" = "yes" && echo "xpm" test "$with_xrender" = "yes" && echo "xrender" ;; --supports-*) feature=`echo "$1" | sed 's/^--supports-//'` feature=`echo "$feature" | sed 's/[-_]//g'` with=`eval echo '$'with_"$feature"` test "$with" = "yes" && exit 0 test "$with" = "no" && exit 100 exit 200 ;; --info|-info|-i) echo "Package: $PACKAGE" echo "Version: $VERSION$VERSIONINFO" echo "" echo "Instalation options:" echo " prefix: $prefix" echo " exec-prefix: $exec_prefix" echo " bindir: $bindir" echo " datadir: $datadir" echo " libexecdir: $libexecdir" echo " sysconfdir: $sysconfdir" echo " mandir: $mandir" echo " localedir: $localedir" echo "" echo "Compiled-in paths:" echo " Module directory: $fvwm_moduledir" echo " Data directory: $fvwm_datadir" echo " Perl lib directory: $fvwm_perllibdir" echo " Default ImagePath: $fvwm_imagepath" echo " Default UserDir: $fvwm_userdir" echo "" echo "Support for features:" echo " bidi (bi-directionality): $with_bidi" echo " gettext (Native Lang Support): $with_gettext" echo " perllib (Perl library installed): $with_perllib" echo " iconv (i18n conversions): $with_iconv" echo " png: $with_png" echo " readline: $with_readline" echo " rplay: $with_rplay" echo " shape (shaped windows): $with_shape" echo " shm (shared memory): $with_shm" echo " sm (session management): $with_sm" echo " stroke (mouse gestures): $with_stroke" echo " rsvg (SVG icons and images): $with_rsvg" echo " xcursor (ARGB/animated cursors): $with_xcursor" echo " xinerama (multi-head): $with_xinerama" echo " xft (FreeType anti-alias font): $with_xft" echo " xpm: $with_xpm" echo " xrender (XFree86 Xrender extention): $with_xrender" ;; --is-final|-is-final) test "$is_final" = yes && echo yes test "$is_final" != yes && echo no ;; *) echo >&2 "$script: unknown argument '$1'." echo >&2 "Run '$script --help' to get the usage." exit 1 ;; esac shift done exit 0 �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/bin/fvwm-bug.in��������������������������������������������������������������������������0000644�0001750�0001750�00000010444�14324314575�012265� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������#!/bin/sh - # # fvwm-bug - create a bug report and mail it to the bug address # - adapted from equivalent `bashbug' script # # The bug address could depend on the release status of fvwm. Currently # it doesn't. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see: <http://www.gnu.org/licenses/> PACKAGE="@PACKAGE@" VERSION="@VERSION@" script=`basename $0` address="" while test $# -gt 0; do case "$1" in --help|-help|-h|-\?) cat <<EOF This script is a part of $PACKAGE-$VERSION package. Usage: $script [OPTIONS] [address] Options: [-h] [--help] [-?] [-v] [--version] [-V] address is an alternative email address to send the bug report to; by default, addresses of the local admin or developers are used EOF exit 0 ;; --version|-version|-v|-V) echo "$VERSION" exit 0 ;; -*) echo >&2 "Unrecognized option $1 specified." echo >&2 "Run '$0 --help' to get the usage." exit 1 ;; *) if test x"$address" != x; then echo >&2 "You may specify only one address." echo >&2 "Run '$0 --help' to get the usage." exit 1 fi address="$1" ;; esac shift done PATH=/bin:/usr/bin:/usr/local/bin:$PATH export PATH : ${EDITOR:=vi} TEMP=`mktemp -q "${TMPDIR:-/tmp}/fvwm-bug.XXXXXX"` # Figure out how to echo a string without a trailing newline N=`echo 'hi there\c'` case "$N" in *c) n=-n c= ;; *) n= c='\c' ;; esac trap 'rm -f $TEMP $TEMP.x; exit 1' 1 2 3 13 15 trap 'rm -f $TEMP $TEMP.x' 0 # Who is mail from? : ${USER:=${LOGNAME:-`whoami`}} # Who is mail to? if test x"$address" = x; then LOCAL= WORKERS=fvwm-workers@fvwm.org if test "$LOCAL"; then echo "Do you want to send the report to the local maintainer <$LOCAL>," echo "the fvwm workers <$WORKERS>, or both?" echo $n "Send report to (l)ocal, (w)orkers, (b)oth? " $c read ans case "$ans" in l*|L*) BUGADDR=$LOCAL;; f*|F*|w*|W*) BUGADDR=$WORKERS;; b*|B*) BUGADDR=$LOCAL,$WORKERS;; *) echo "[Defaulting to LOCAL]"; BUGADDR=$LOCAL;; esac fi else BUGADDR=$address fi UN= if (uname) >/dev/null 2>&1; then UN=`uname -a` fi if [ -f /usr/lib/sendmail ] ; then RMAIL="/usr/lib/sendmail" elif [ -f /usr/sbin/sendmail ] ; then RMAIL="/usr/sbin/sendmail" else RMAIL=rmail fi prefix=@prefix@ exec_prefix=@exec_prefix@ datarootdir=@datarootdir@ datadir=@datadir@ libexecdir=@libexecdir@ : ${FVWM_USERDIR:=unset} FVWM_DATADIR=@FVWM_DATADIR@ FVWM_MODULEDIR=@FVWM_MODULEDIR@ cat > $TEMP <<EOF From: ${USER} To: ${BUGADDR} Subject: [50 character or so descriptive subject here (for reference)] Configuration Information [Automatically generated, do not change]: uname: $UN compiler flags: @CC@ @CFLAGS@ FVWM Version: @VERSION@@VERSIONINFO@ FVWM_MODULEDIR: $FVWM_MODULEDIR FVWM_DATADIR: $FVWM_DATADIR FVWM_USERDIR: $FVWM_USERDIR Description: [Detailed description of the problem, suggestion, or complaint.] Repeat-By: [Describe the sequence of events that causes the problem to occur.] Fix: [Description of how to fix the problem. If you don't know a fix for the problem, don't include this section.] EOF chmod u+w $TEMP cp $TEMP $TEMP.x trap '' 2 # ignore interrupts while in editor until $EDITOR $TEMP; do echo "$0: editor \`$EDITOR' exited with nonzero status." echo "$0: Perhaps it was interrupted." echo "$0: Type \`y' to give up, and lose your bug report;" echo "$0: type \`n' to re-enter the editor." echo $n "$0: Do you want to give up? $c" read ans case "$ans" in [Yy]*) exit 1 ;; esac done trap 'rm -f $TEMP $TEMP.x; exit 1' 2 # restore trap on SIGINT if cmp -s $TEMP $TEMP.x then echo "File not changed, no bug report submitted." exit fi echo $n "Send bug report? [y/n] $c" read ans case "$ans" in [Nn]*) exit 0 ;; esac ${RMAIL} $BUGADDR < $TEMP || { cat $TEMP >> $HOME/dead.fvwm-bug echo "$0: mail failed: report saved in $HOME/dead.fvwm-bug" >&2 } exit 0 ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/bin/fvwm-bug.1.in������������������������������������������������������������������������0000644�0001750�0001750�00000002746�14147024700�012421� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������.\" @(#)@PACKAGE@-@VERSION@ @RELDATELONG@ .TH fvwm-bug 1 "@RELDATELONG@ (@VERSION@)" Fvwm "Fvwm Modules" .SH NAME fvwm-bug \- report a bug in fvwm .SH SYNOPSIS \fBfvwm-bug\fP [\fI--help\fP] [\fI--version\fP] [\fIaddress\fP] .SH DESCRIPTION .B fvwm-bug is a shell script to help the user compose and mail bug reports concerning fvwm in a standard format. .B fvwm-bug invokes the editor specified by the environment variable .SM .B EDITOR on a temporary copy of the bug report format outline. The user must fill in the appropriate fields and exit the editor. .B fvwm-bug then mails the completed report to the local fvwm maintainer, the fvwm workers list \fIfvwm-workers@fvwm.org\fP, or \fIaddress\fP. If the report cannot be mailed, it is saved in the file \fIdead.fvwm-bug\fP in the invoking user's home directory. .PP The bug report format outline consists of several sections. The first section provides information about the machine, operating system, the fvwm version, and the compilation environment. The second section should be filled in with a description of the bug. The third section should be a description of how to reproduce the bug. The optional fourth section is for a proposed fix. Fixes are encouraged. .SH ENVIRONMENT .B fvwm-bug will utilize the following environment variables if they exist: .TP .B EDITOR Specifies the preferred editor. If .SM .B EDITOR is not set, .B fvwm-bug defaults to .BR emacs . .TP .B HOME Directory in which the failed bug report is saved if the mail fails. ��������������������������fvwm-2.7.0/docs/������������������������������������������������������������������������������������0000755�0001750�0001750�00000000000�14324316056�010434� 5����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/docs/PARSING.md��������������������������������������������������������������������������0000644�0001750�0001750�00000163441�14147024700�012005� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������Overview of fvwm2 parsing as of 16-Aug-2014 =========================================== Sources of input to parse ------------------------- * Configuration files and files read with the Read command - May be preprocessed by FvwmCpp or FvwmM4 * Input from the PipeRead command * Input from modules to fvwm through the module pipes - Fixed or generated strings from modules (e.g. FvwmPager, FvwmButtons etc.) - User input, e.g. from FvwmConsole or FvwmCommand. * Module input from fvwm through the module pipes is parsed by the receiving module. - Binary input in predefined packets is only partially parsed (packet type). The format and meaning of the packets is a property of the module protocol. - The payload of some string packets (e.g. generated by the SendToModule command) is a free form string that is interpreted by the receiving module. The module does any necessary parsing. Example: `SendToModule FvwmButtons changebutton 0 title foo, activetitle bar` * Commands generated internally by fvwm as the result of an external event, for example, an Ewmh message. This is used quite often; instead of calling the function to maximize a window directly, one may generate a command string that is passed to `execute_function()`. Examples are `virtual.c:CMD_EdgeResistance()` or `ewmh_events.c:ewmh_DesktopGeometry()`. Various properties of parser input and the communication channels ----------------------------------------------------------------- * Maximum length of of lines read from a file is hard coded ro 1024 bytes in `read.c:run_command_stream()`. This is applicable to configuration files and the Read and Piperead commands. * The maximum depth of nested files opened through the Read command is hard coded to 40 (read.c). * Input from files or the `PipeRead` command may have an unlimited number of lines. * The maximum length of packets that can be sent in one chunk from fvwm to the modules or back is hard coded to 256 including the packet header (`FvwmPacketMaxSize` in `libs/Module.h`). This is an artifact of module communication through pipes. 256 bytes is the size that all systems guarantee to be sent through the pipe in an atomic block. Anything larger than that may be split into multiple write calls, leading to mutilated messages in either direction. Packets from fvwm to the modules are simply truncated to 256 bytes (`module_interface.c:make_vpacket()`). Packets from the modules to fvwm are possibly sent in multiple pieces (write call in `Module.c:SendText()`). Fvwm can theoretically handle any size of module input (`module_list.c:module_receive()`). * Input from modules to fvwm is pre-parsed in `module_interface.c:module_input_execute()`, i.e. fvwm checks whether the command name of the packet is "popup" and does some special processing if that is the case (this command name is not to be confused with the command from the text to be executed by fvwm; its a fixed field in the packet). This is done before any regular processing of the input. * Input from the modules is not executed right away but stored in a queue and executed when fvwm can process it (this is important because otherwise module input might interfere with function execution) (`module_interface.c:ExecuteCommandQueue()`). Fvwm's central parsing function: execute_function() --------------------------------------------------- * All input to the parser is passed through `functions.c:__execute_command_line()`. NOTE: This function is called `__execute_function()` in fvwm. * `__execute_command_line` is called from two places: - `execute_function()` is just a wrapper exported rom functions.c. There are two more wrappers, `execute_function_override_wcontext()` and `execute_function_override_window()` which change the execution context of the command (see below) and then call `execute_function()`. - `__run_complex_function_items()` calls `__execute_command_line()` to process the individual commands of a complex function. In other words: The items of a complex function are passed twice through the parser. First when the complex function is defined, and a second time when they are executed (they are treated differently in both passes, see further down). * The call to `__execute_command_line()` is passed various pieces of information: ``` void __execute_command_line( cond_rc_t *cond_rc, const exec_context_t *exc, char *action, FUNC_FLAGS_TYPE exec_flags, char *args[], Bool has_ref_window_moved) ``` - `cond_rc` is a pointer to memory where the return code of command line execution is to be stored. This can be used in scripting through complex functions (`__run_complex_function_items()`) and by the internal caller of execute_function. It is also one of the parameters of the `CMD_...` functions, and it's important that cond_rc is passed around and not set to a NULL pointer except by the first call triggering command line processing. - exc is the execution context of the command line (`execcontext.h`). This is a vital data structure for command line processing and execution. It contains information about the originator of the command and the assiciated application (type (module, event, scheduler, ...), the actual X event, the module, the window). This data is used during command execution, e.g. to identify the window on which a command is executed or to determine the pointer position; some commands work differently when input comes from the mouse or the keyboard. It is also used during variable expansion (e.g. to expand window related extended parameters like `$[w.id]`). It is important to properly set the execution context whenever a command line is generated. Currently, some of the Ewmh code fails to do so for historical reasons which I won't explain here. This needs to be fixed eventually. - action is the command line to parse and execute. - `exec_flags` are flags that affect command parsing and execution that may become necessary in some contexts not related to the originator of the command. The flags are defined in the structure execute_flags_t in functions.h. - `FUNC_NEEDS_WINDOW` commands that need a context window are not executed if it's missing. - `FUNC_DONT_REPEAT` the command line is not repeatable (see `CMD_Repeat`). - `FUNC_ADD_TO` signals that the command is the addtofunc or `+` command. - `FUNC_DECOR` signals that the command is a decor related command. - `FUNC_ALLOW_UNMANAGED` allows running a command with an overrideredirect window. - `FUNC_IS_UNMANAGED` signals that the context window is an overrideredirect window. - `FUNC_DONT_EXPAND_COMMAND` suppresses expansion of variables on the command line. - `FUNC_DONT_DEFER` suppresses deferring execution of commands that need a target window (normally these are put into the queue and processed later). - args is the array of the positional arguments during complex function execution. For calls from `execute_function()` it's a NULL pointer. - `has_ref_window_moved` is a separate flag (hack) that triggers some special treatment of the execution of the command Move, Resize and AnimatedMove (but forgets the ResizeMove and ResizeMoveMaximize commands). This should ratehr be stored in exec_flags. Command line parsing -------------------- The command independent parsing of any command line is done by the `__execute_command_line()` call. The parsing procedure is as follows. Remember that `action` is the command line to be parsed. The pointer and the memory it points to are updated during the parsing process. * Step 1 Handle NULL pointer, whitespace and comments 1. Stop parsing and execute nothing if action is a NULL pointer. *DONE* 2. Strip all whitespace from the beginning of the command line. 3. Stop parsing and execute nothing if action is a NULL pointer or an empty string. (Note that some of the functions in libs/Parse.c never return an empty string but rather a NULL pointer. Parsing in the individual commands often relies on that.) *DONE* 4. If the first character is '#', is a comment. Stop parsing and execute nothing. *DONE* * Step 2 1. Increment the nested function depth. 2. If the function depth is too high, print an error message and stop. *DONE* 3. Determine the context window. * Step 3 Handle prefixes 1. If action begins with `-`, set the `FUNC_DONT_EXPAND_COMMAND` flag and skip the `-` character. 2. Peek the first token of action. 3. If the token is `silent`, set the global `Scr.flags.are_functions_silent` if not already set, strip the token from action and go back to (b). 4. If the token is `keeprc`, set the internal `do_keep_rc` flag, strip the token from action and go back to (b). (A dummy return code variable is used in the command execution.) * Step 4 Finish if there is no remaining action to execute. * Step 5 Parse the command token 1. Get (but not strip) the command token from the action. 2. Expand variables in the token (expand.c:expand_vars()). 3. If the token does not start with a '*': * strip all characters from and including the first whitespace from the command token. [Bug: Complex function names cannot have embedded whitespace because of this, see comment in the code.] [Note: If a command line begins with `*foo` (including the double quotes), the double quotes are removed by GetNextToken, and the remaining token does begin with `*`.] * find the internal command matching this token from the builtin function table. Note that any token _beginning_ with `+` or ` +` is treated as the `+` command. [What the heck is this good for?] * Step 6 If a we're currently adding to a decor, and the command token designates a builtin function that does not have the `FUNC_DECOR` flag set, generate a warning that the command cannot be added to the decor. * Step 7 If the `FUNC_DONT_EXPAND_COMMAND` flag is not set, expand variables in the action, including the part from which the command token was extracted above. (The ismod flag of the call to expand_vars() flag is set if the action begins with '*'). [Note: The command token was parsed before expansion in step 5. Now the whole line including the token is expanded before further processing. This may or may not cause subtle bugs with quoting and expansion.] * Step 8 If the expanded action begins with '*' treat it as a module configuration line. *GOTO step 10* [BUG: Contrary to step 5 (c), a line beginning with `*foo` is not recognized as a module configuration line because it begins with double quotes, not `*`.] * Step 9 Execute the action 1. Prepare the execution context. 2. If it's a builtin function other than `Function`, strip the first token from the expanded action and defer or execute the CMD_<command>() function as necessary with the proper execution context. *GOTO step 10* 3. If it's the builtin command `Function`, strip the first token from the expanded action. [Note: this may again be a different substring than in step 5 (c) or step 8.] 4. Call `execute_complex_function` with the remaining expanded action. 5. If no complex function with that name can be found and it was not the builtin command `Function`, assume that the builtin command was `Module` and try to execute `CMD_Module` with the remaining expanded action as its arguments. * Step 10 Cleanup 1. Clear the `Scr.flags.are_functions_silent` flag if set in step 3 (c). 2. Store the number of pending breaks from the functions return code structure in the original cond_rc (which may be a different one in case the command was prefixed with keeprc). 3. Decrement the nested function depth. Tokenization ------------ The token parsing code is in `libs/Parse.c:DoPeekToken()` and CopyToken() (called by the former). `DoPeekToken` takes the input string, a pointer to memory where it stores the pointer to the resulting token, a pointer to memory to store the output string (buffer with hardcoded length `MAX_TOKEN_LENGTH = 1023` bytes (`libs/Parse.h`), and may be provided a string of additional characters to be treated as spaces, a string of input token delimiter characters, and a pointer where the character that ended the token is stored (output delimiter). By default, the set of space characters contains the character class determined by isspace(), and the set of input delimiter characters is empty * Step 1 (DoPeekToken) 1. Strip all space characters (see above) from the beginning of the input string. 2. Call `CopyToken()` with the remaining string. * Step 2 (CopyToken) 1. Set the src pointer to the beginning of the input string. The dest pointer is passed in as a function argument. 2. If src is at the end of the string, *GOTO stp 3* 3. If *src is a space character or an input delimiter, *GOTO stp 3* 4. If *src is a quote character (either a double quote chararcter, a single quote or a backtick), *GOTO step 2A* 5. Otherwise, *GOTO step 2B* * Step 2A 1. `c := *src` 2. Skip over the src quote character (`src++`) 3. If `*src` is `c` or the end of string, *GOTO (f)* 4. If `*src` is a backslash and the next character is not the end of the input string (null byte), skip over the backslash in the input (src++). 5. If there's still room in the output string, copy `*src` to `*dest` and increment both pointers, otherwise just skip over the input character (`src++`). *GOTO (c)* 6. If `*src` is `c`, skip over it (`src++`). *GOTO step 2 (b)* * Step 2B 1. If `*src` is a backslash and the next character is not the end of the input string (null byte), skip over the backslash in the input (`src++`). 2. If there's still room in the output string, copy `*src` to `*dest` and increment both pointers, otherwise just skip over the input character (`src++`). *GOTO step 2 (b)* * Step 3 1. Set the output delimiter to the character pointer to by src (i.e. the first character after the token). 2. Terminate the destination string with a null byte. 3. If src points to a string of zero or more spaces followed by an input delimiter, store the delimiter as the output delimiter and return a pointer to the character after that. 4. Otherwise, if src is not at the end of the string, return the character after src. 5. Otherwise src points to the end of the string; return src. Step 4 (DoPeekToken) 1. If the remaining string has the length zero, set the token pointer to NULL. 2. Return a pointer to the beginning of the next token in the input string. *DONE* Variable expansion ------------------ Variable expansion is done `expand.c:expand_vars()`. The function takes an input string, the execution context, `cond_rc` and an array of positional parameters and returns the string with the variables expanded. It also takes the flags addto (never set) and ismod (set in step 7 of the parsing algorithm if the command begins with `*`). [BUG: The addto flag is actually never set when the function is called but instead used as a bogus local variable.] * Step 1 1. l := length of input 2. If the input begins with '*', set the addto flag. 3. Calculate the length of the expanded string and allocate memory for it. * Step 2 (Scan for variables) 1. Begin at the start of the input and output strings. 2. Copy all character up to but excluding the next '$' character to the output string (stop at the end of string). 3. If we're at the end of the string, stop. *DONE* 4. Otherwise we're now at a `$` character. If the ismod flag set and the next character is a letter, copy both to the output string. *GOTO (b)* [Note: In module configuration lines, variable in the form `$<letter>` are not expanded. There are probably several bugs because of this logic.] * Step 3 (Expand a variable) 1. If the next character is a `$`, copy one `$` to the output, skip over two `$` in the input and *GOTO step 2 (b)* 2. If the next character is '[', *GOTO step 4* 3. If the `$<character>` sequence does not designate a valid one character variable, copy it to the output and *GOTO step 2 (b)* 4. Otherwise, skip over the `$` and the next character in the input and copy the value of the one character variable to the output. *GOTO step 2 (b)* * Step 4 (Expand an extended variable) 1. If addto is set, copy the `$[` to the output and *GOTO step 2 (b)* 2. Determine the name of the extended variable. The name starts after the initial `[` character and ends before the final `]` character. The final `]` character is the first occurence of the character `]` after the `$`, where the number of `[` minus the number of `]` is zero (i.e., square brackets can be nested). If the end of string is encountered, just copy everything to the output and *GOTO step 2 (b)* 3. Otherwise, if the variable name contains at least one `$`, call expand vars with the name to expand nested variable references. The result of this expansion is taken as the new variable name. 4. If an extended variable with that name exists, copy its value into the output, skip the `$[...]` in the input and *GOTO step 2 (b)* 5. Otherwise copy the "$[...]" to the output and *GOTO step 2 (b)* The second level of parsing --------------------------- When `__execute_command_line()` has finished its work it either tries to execute a module, a builtin command or a complex function (or nothing at all and just returns). Module execution is treated like a call of `CMD_Module()`, so there are two different ways how parsing continues. A third context of parsing is, when a module receives a packet from fvwm. * Parsing of builtin commands is done individually by the `CMD_<builtin>()` functions. * Parsing and of a complex function call and its items is handled by the function `functions.c:execute_complex_function()`. * Parsing of module configuration lines is done by the modules with help from libs/Modules.c. There is also an optional step of module variable expansion that is implemented in `Modules.c:module_expand_action()`. It replaces some module variables in the string that is going to be sent to fvwm, e.g. `$width` or `$x`. FvwmButtons, FvwmIconMan and FvwmTaskBar and use this mechanism. Parsing of complex function calls --------------------------------- Implemented in `functions.c:execute_complex_function()`. * Step 1 1. Peek the first token of the action. 2. Look it up in the list of complex functions. 3. If no such function exists, return an error. *DONE* 4. Split the action into tokens using GetNextToken. Store the original action (without the function name) followed by the first ten tokens in the positional arguments array. 5. Set up an execution context for the function items. 6. Call `__run_complex_function_items()`. * Step 2 (`__run_complex_function_items()`) 1. For each complec function iten, call `__execute_command_line()` with the `FUNC_DONT_DEFER` flag and the list of positional arguments. This causes the function item command text to be passed through the parser again. *DONE* Parsing needs of the builtin commands ------------------------------------- Note: Let's attempt to formulate the existing syntax in ABNF (rfc5234). Definitions that need defining for the below -------------------------------------------- * FLAG = !!!; * DECOR = !!!; * FONTNAME = !!!; * IMAGEFILE = !!!; * GRADIENT = !!!; * MOVEARGS = !!!; * MODULECONFIG = !!!; * CONDITION = !!!; * COLOUR_FG = !!!; * COLOUR_BG = !!!; * COMMAND = !!!; (builtin; can also be one of FUNCNAME) * FUNCNAME = !!!; (StartFunction | ExitFunction | etc, plus user-defined) * SHELL = !!!; * KEYNAME = !!!; * STYLEOPTION = !!!; (massive list of style options!!!) * TOKEN = !!! ; Same as string? * STRING = !!! ; Sequence of characters? * RESTOFLINE = !!! ; STRING? * RESTOFLINE_COMMAND = !!! ; COMMAND Types ----- ``` WSC = %x20 / %x09 WS = *WSC DIGIT = "0" / "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" SIGNPOS = "+" SIGNNEG = "-" SIGN = SIGNPOS / SIGNNEG POSINT = [SIGNPOS] 1*DIGIT INT = [SIGN] 1*DIGIT INTPERCENTAGE = 1DIGIT | 2DIGIT | ("0" / "1") 2DIGIT TRUE = "yes" / "y" / "1" / "t" / "true" FALSE = "no" / "n" / "0" / "f" / "false" BOOL = TRUE / FALSE TOGGLE = "toggle" BOOL_OR_TOGGLE = BOOL / TOGGLE MODIFIERS = "s" / "c" / "l" / "m" / "1" / "2" / "3" / "4" / "5" / "a" BINDINGMODIFIERS = "n" / 1*MODIFIERS PATH = ["/"] *(STRING "/") [STRING] VISIBLE_NAME = !!! CLASS = !!! RESOURCE = !!! NAME = !!! WINDOW_ID = !!! WINDOWSELECTOR = VISIBLE_NAME / CLASS / RESOURCE / NAME / WINDOW_ID BINDINGCONTEXT = "R" / "W" / "D" / "T" / "F" / "A" / "S" / "M" / "I" BINDINGCONTEXT = "[" / "]" / "-" / "_" BINDINGCONTEXT = "<" / "^" / ">" / "v" BINDINGCONTEXT = DIGIT MODULENAME = "MvwmAnimate" / "MvwmButtons" / ; etc... MODULALIAS = TOKEN TOKEN_DECORNAME = TOKEN FUNCNAME = TOKEN MENUNAME = TOKEN MENUSTYLENAME = TOKEN STYLENAME = TOKEN / "*" DIRS_MAIN = "North" / "N" DIRS_MAIN =/ "East" / "E" DIRS_MAIN =/ "South" / "S" DIRS_MAIN =/ "West" / "W" DIRS_DIAG = DIRS_MAIN DIRS_DIAG =/ "NorthEast" / "NW" DIRS_DIAG =/ "SouthEast" / "SE" DIRS_DIAG =/ "SouthWest" / "SW" DIRS_DIAG =/ "NorthWest" / "NW" DIRS_CENTER = DIRS_DIAG / "Center" / "C" COLORSET_NUM = POSINT BUTTON = 1*DIGIT VERSION = POSINT "." POSINT "." POSINT ``` Commands -------- ``` CMD_ADDBUTTONSTYLE = "AddButtonStyle" ADDBUTTONSTYLEBUTTON [ADDBUTTONSTYLESTATE] [ADDBUTTONSTYLESTYLE] [ADDBUTTONSTYLEFLAG] ADDBUTTONSTYLEBUTTON = POSINT ("All" / "Left" / "Right") ADDBUTTONSTYLESTATE = "ActiveUp" ADDBUTTONSTYLESTATE =/ "ActiveDown" ADDBUTTONSTYLESTATE =/ "InactiveUp" ADDBUTTONSTYLESTATE =/ "InactiveDown" ADDBUTTONSTYLESTATE =/ ADDBUTTONSTYLEACTIVE ADDBUTTONSTYLESTATE =/ "Inactive" ADDBUTTONSTYLESTATE =/ TOGGLE ADDBUTTONSTYLESTATE =/ "AllActive" ADDBUTTONSTYLESTATE =/ "AllInactive" ADDBUTTONSTYLESTATE =/ "AllNormal" ADDBUTTONSTYLESTATE =/ "AllToggled" ADDBUTTONSTYLESTATE =/ "AllUp" ADDBUTTONSTYLESTATE =/ "AllDown" ADDBUTTONSTYLESTATE =/ "AllActiveUp" ADDBUTTONSTYLESTATE =/ "AllActiveDown" ADDBUTTONSTYLESTATE =/ "AllInactiveUp" ADDBUTTONSTYLESTATE =/ "AllInactiveDown" ADDBUTTONSTYLEACTIVE = "Active" - implies FOCUSED_WINDOW ADDBUTTONSTYLEFLAG = ["!"]ADDBUTTONSTYLEKEYWORD *("," ["!"]ADDBUTTONSTYLEKEYWORD) ADDBUTTONSTYLEKEYWORD = 1*("UseTitleStyle" / "UseBorderStyle") *("Raised" / "Sunk" / "Flat") CMD_ADDTITLESTYLE = "AddTitleStyle" [ADDTITLESTYLESTATE] [ADDTITLESTYLESTYLE] [ADDTITLESTYLEFLAG] ADDTITLESTYLESTATE = "ActiveUp" ADDTITLESTYLESTATE =/ "ActiveDown" ADDTITLESTYLESTATE =/ "InactiveUp" ADDTITLESTYLESTATE =/ "InactiveDown" ADDTITLESTYLESTATE =/ ADDTITLESTYLEACTIVE ADDTITLESTYLESTATE =/ "Inactive" ADDTITLESTYLESTATE =/ "toggled" ADDTITLESTYLESTATE =/ "AllActive" ADDTITLESTYLESTATE =/ "AllInactive" ADDTITLESTYLEFLAG = ["!"] ADDTITLESTYLEFLAGKEYWORD *("," ["!"] ADDTITLESTYLEFLAGKEYWORD) ADDTITLESTYLEACTIVE = "Active" ; - implies FOCUSED_WINDOW ; (XXX = TitleStyle/ButtonStyle relationships here...) ``` ``` CMD_ADDTOFUNC = "AddToFunc" FUNCNAME ADDTOFUNCFUNCDEFS RESTOFLINE_COMMAND ADDTOFUNCFUNCDEFS = "I" ADDTOFUNCFUNCDEFS =/ "M" ADDTOFUNCFUNCDEFS =/ "C" ADDTOFUNCFUNCDEFS =/ "H" ADDTOFUNCFUNCDEFS =/ "D" ``` ``` CMD_ADDTOMENU = "AddToMenu" MENUNAME [ADDTOMENULABEL RESTOFLINE_COMMAND] ADDTOMENULABEL = STRING ``` ``` CMD_ANIMATEDMOVE = "AnimatedMove" ANIMATEMOVEARGS ANIMATEMOVEARGS [ANIMATEDMOVEKEYWORD] ANIMATEMOVEARGS = !!! ANIMATEDMOVEKEYWORD = "Warp" ``` ``` CMD_ASTERISK = "Asterisk" [MODULE_LINE] ``` ``` CMD_BEEP = "Beep" ``` ``` CMD_BORDERSTYLE = "BorderStyle" BORDERSTYLESTATE [BORDERSTYLESTYLE] [BORDERSTYLEFLAG] BORDERSTYLESTATE = "Active" / "Inactive" BORDERSTYLESTYLE = "TiledPixmap" / "Colorset" BORDERSTYLEFLAG = ["!"] BORDERSTYLEKEYWORD ("," ["!"] BORDERSTYLEKEYWORD) BORDERSTYLEKEYWORD = "HiddenHandles" BORDERSTYLEKEYWORD =/ "NoInset" BORDERSTYLEKEYWORD =/ "Raised" BORDERSTYLEKEYWORD =/ "Sunk" BORDERSTYLEKEYWORD =/ "Flat" BORDERSTYLEKEYWORD =/ "Simple" ``` ``` CMD_BUGOPTS = "BugOpts" BUGOPTSOPTION BUGOPTSOPTION = 1*(BUGOPTSKEYWORD [BOOL_OR_TOGGLE]) BUGOPTSKEYWORD = "FlickingMoveWorkaround" BUGOPTSKEYWORD =/ "MixedVisualWorkaround" BUGOPTSKEYWORD =/ "ModalityIsEvil" BUGOPTSKEYWORD =/ "RaiseOverNativeWindows" BUGOPTSKEYWORD =/ "RaiseOverUnmanaged" BUGOPTSKEYWORD =/ "FlickingQtDialogsWorkaround" BUGOPTSKEYWORD =/ "QtDragnDropWorkaround" BUGOPTSKEYWORD =/ "EWMHIconicStateWorkaround" BUGOPTSKEYWORD =/ "DisplayNewWindowNames" BUGOPTSKEYWORD =/ "ExplainWindowPlacement" BUGOPTSKEYWORD =/ "DebugCRMotionMethod" BUGOPTSKEYWORD =/ "TransliterateUtf8" ``` ``` CMD_BUSYCURSOR = "BusyCursor" BUSYCURSOROPTION *("," BUSYCURSOROPTION) BUSYCURSOROPTION = 1*(BUSYCURSORKEYWORD BOOL) BUSYCURSORKEYWORD = "DynamicMenu" BUSYCURSORKEYWORD =/ "ModuleSynchronous" BUSYCURSORKEYWORD =/ "Read" BUSYCURSORKEYWORD =/ "Wait" BUSYCURSORKEYWORD =/ "*" ``` ``` CMD_BUTTONSTATE = "ButtonState" BUTTONSTATEOPTION *("," BUTTONSTATEOPTION) BUTTONSTATEOPTION = BUTTONSTATEKEYWORD [BOOL] BUTTONSTATEKEYWORD = "ActiveUp" BUTTONSTATEKEYWORD =/ "ActiveDown" BUTTONSTATEKEYWORD =/ "InactiveUp" BUTTONSTATEKEYWORD =/ "InactiveDown" ``` ``` CMD_BUTTONSTYLE = "ButtonStyle" BUTTONSTYLEBUTTON [BUTTONSTYLESTATE] [BUTTONSTYLESTYLE] [FLAGS] BUTTONSTYLEBUTTON = 0-9 BUTTONSTYLEBUTTON =/ "All" BUTTONSTYLEBUTTON =/ "Left" BUTTONSTYLEBUTTON =/ "Right" BUTTONSTYLEBUTTON =/ "Reset" BUTTONSTYLEBUTTONSTATE = "ActiveUp" BUTTONSTYLEBUTTONSTATE =/ "ActiveDown" BUTTONSTYLEBUTTONSTATE =/ "InactiveUp" BUTTONSTYLEBUTTONSTATE =/ "InactiveDown" BUTTONSTYLEBUTTONSTATE =/ BUTTONSTYLEACTIVE BUTTONSTYLEBUTTONSTATE =/ "Inactive" BUTTONSTYLEBUTTONSTATE =/ TOGGLE BUTTONSTYLEBUTTONSTATE =/ "AllActive" BUTTONSTYLEBUTTONSTATE =/ "AllInactive" BUTTONSTYLEBUTTONSTATE =/ "AllNormal" BUTTONSTYLEBUTTONSTATE =/ "AllToggled" BUTTONSTYLEBUTTONSTATE =/ "AllUp" BUTTONSTYLEBUTTONSTATE =/ "AllDown" BUTTONSTYLEBUTTONSTATE =/ "AllActiveUp" BUTTONSTYLEBUTTONSTATE =/ "AllActiveDown" BUTTONSTYLEBUTTONSTATE =/ "AllInactiveUp" BUTTONSTYLEBUTTONSTATE =/ "AllInactiveDown" BUTTONSTYLEACTIVE = "Active" ; - implies FOCUSED_WINDOW BUTTONSTYLESTYLE = "Simple" BUTTONSTYLESTYLE =/ "Default" BUTTONSTYLESTYLE =/ "Solid" BUTTONSTYLESTYLE =/ "Colorset" BUTTONSTYLESTYLE =/ "Vector" BUTTONSTYLESTYLE =/ BUTTONSTYLEGRADIENT BUTTONSTYLESTYLE =/ "Pixmap" BUTTONSTYLESTYLE =/ AdjustedPixmap" BUTTONSTYLESTYLE =/ "ShrunkPixmap" BUTTONSTYLESTYLE =/ "StretchedPixmap" BUTTONSTYLESTYLE =/ "TiledPixmap" BUTTONSTYLESTYLE =/ "MiniIcon" BUTTONSTYLEGRADIENT = TYPE START-COLOUR END-COLOUR BUTTONSTYLESTYLEFLAG = ["!"] BUTTONSTYLESTYLEKEYWORD *("," ["!"] BUTTONSTYLESTYLEKEYWORD) BUTTONSTYLESTYLEKEYWORD = "Raised" BUTTONSTYLESTYLEKEYWORD =/ "Sunk" BUTTONSTYLESTYLEKEYWORD =/ "Flat" BUTTONSTYLESTYLEKEYWORD =/ "UseBorderStyle" BUTTONSTYLESTYLEKEYWORD =/ "UseTitleStyle" ; (XXX = "Raised, Sunk, and Flat" can only be used initially!!!") ``` ``` CMD_CHANGEMENUSTYLE = "ChangeMenuStyle" MENUSTYLENAME MENUNAME ``` ``` CMD_CLEANUPCOLORSETS = "CleanupColorsets" ``` ``` CMD_CLICKTIME = "ClickTime" POSINT ; (stores the negative value during startup> ``` ``` CMD_CMD_CLASS_CLOSE = "Close" / "Delete" / "Destroy" ; work on context window ``` ``` CMD_COLORMAPFOCUS = "ColormapFocus" ("FollowsMouse" / "FollowsFocus") ``` ``` CMD_COLORSET = "Colorset" COLORSET_NUM COLORSETOPTION *("," COLORSETOPTION) COLORSETOPTION = COLORSETKEYWORD [COLORSETVALUE] COLORSETKEYWORD = "fg" COLORSETKEYWORD =/ "Fore" COLORSETKEYWORD =/ "Foreground" COLORSETKEYWORD =/ "bg" COLORSETKEYWORD =/ "Back" COLORSETKEYWORD =/ "Background" COLORSETKEYWORD =/ "hi" COLORSETKEYWORD =/ "Hilite" COLORSETKEYWORD =/ "Hilight" COLORSETKEYWORD =/ "sh" COLORSETKEYWORD =/ "Shade" COLORSETKEYWORD =/ "Shadow" COLORSETKEYWORD =/ "fgsh" COLORSETKEYWORD =/ "Pixmap" COLORSETKEYWORD =/ "TiledPixmap" COLORSETKEYWORD =/ "AspectPixmap" COLORSETKEYWORD =/ "Transparent" COLORSETKEYWORD =/ "RootTransparent" COLORSETKEYWORD =/ "Shape" COLORSETKEYWORD =/ "TiledShape" COLORSETKEYWORD =/ "AspectShape" COLORSETKEYWORD =/ "NoShape" COLORSETKEYWORD =/ ("V" / "B" / "D" / "S" / "C" / "R" / "Y") "Gradient" COLORSETKEYWORD =/ "Tint" COLORSETKEYWORD =/ "fgTint" COLORSETKEYWORD =/ "bgTint" COLORSETKEYWORD =/ "Alpha" COLORSETKEYWORD =/ "fgAlpha" COLORSETKEYWORD =/ "Dither" COLORSETKEYWORD =/ "NoDither" COLORSETKEYWORD =/ "IconTint" COLORSETKEYWORD =/ "IconAlpha" COLORSETKEYWORD =/ "Plain" COLORSETVALUE = INT COLORSETVALUE =/ COLORNAME COLORSETVALUE =/ IMAGEFILENAME COLORSETVALUE =/ INTPERCENTAGE ; (memory usage depends on highest colorset number) ``` ``` COPYMENUSTYLE = "CopyMenuStyle" MENUSTYLENAME MENUSTYLENAME ``` ``` CMD_CURSORMOVE = "CursorMove" CURSORMOVEDIM[CURSORMOVESUFFIX] CURSORMOVEDIM[CURSORMOVESUFFIX] CURSORMOVEDIM = INT CURSORMOVESUFFIX = "p" ``` ``` CMD_CURSORSTYLE = "CursorStyle" CURSORSTYLECONTEXT [CURSORSTYLEXOPTION] CURSORSTYLECONTEXT = CURSORSTYLEKEYWORD / CURSORSTYLEX11NAME CURSORSTYLEKEYWORD = "POSITION" CURSORSTYLEKEYWORD =/ "TITLE" CURSORSTYLEKEYWORD =/ "DEFAULT" CURSORSTYLEKEYWORD =/ "SYS" CURSORSTYLEKEYWORD =/ "MOVE" CURSORSTYLEKEYWORD =/ "RESIZE" CURSORSTYLEKEYWORD =/ "WAIT" CURSORSTYLEKEYWORD =/ "MENU" CURSORSTYLEKEYWORD =/ "SELECT" CURSORSTYLEKEYWORD =/ "DESTROY" CURSORSTYLEKEYWORD =/ "TOP" CURSORSTYLEKEYWORD =/ "RIGHT" CURSORSTYLEKEYWORD =/ "BOTTOM" CURSORSTYLEKEYWORD =/ "LEFT" CURSORSTYLEKEYWORD =/ "TOP_LEFT" CURSORSTYLEKEYWORD =/ "TOP_RIGHT" CURSORSTYLEKEYWORD =/ "BOTTOM_LEFT" CURSORSTYLEKEYWORD =/ "BOTTOM_RIGHT" CURSORSTYLEKEYWORD =/ "TOP_EDGE" CURSORSTYLEKEYWORD =/ "RIGHT_EDGE" CURSORSTYLEKEYWORD =/ "BOTTOM_EDGE" CURSORSTYLEKEYWORD =/ "LEFT_EDGE" CURSORSTYLEKEYWORD =/ "ROOT" CURSORSTYLEKEYWORD =/ "STROKE" CURSORSTYLEKEYWORD =/ "None" CURSORSTYLEKEYWORD =/ "Tiny" CURSORSTYLEX11NAME = "top_left_corner" CURSORSTYLEX11NAME =/ "top_left_arrow" CURSORSTYLEX11NAME =/ "hand2" CURSORSTYLEX11NAME =/ "fleur" CURSORSTYLEX11NAME =/ "sizing" CURSORSTYLEX11NAME =/ "watch" CURSORSTYLEX11NAME =/ "crosshair" CURSORSTYLEX11NAME =/ "pirate" CURSORSTYLEX11NAME =/ "top_side" CURSORSTYLEX11NAME =/ "bottom_side" CURSORSTYLEX11NAME =/ "left_side" CURSORSTYLEX11NAME =/ "top_right_corner" CURSORSTYLEX11NAME =/ "bottom_left_corner" CURSORSTYLEX11NAME =/ "top_side" CURSORSTYLEX11NAME =/ "right_side" CURSORSTYLEX11NAME =/ "left_side" CURSORSTYLEX11NAME =/ "left_ptr" CURSORSTYLEX11NAME =/ "plus" CURSORSTYLEXOPTION = IMAGEFILE [INT] CURSORSTYLEXOPTION =/ "fg" CURSORSTYLEXOPTION =/ "bg" ``` ``` CMD_DEFAULTCOLORS = "DefaultColors" [(COLOUR_FG] / "-") [(COLOUR_BG - "/")] ; XXX - We need to represent colour values here --- RGB.txt, etc. ``` ``` CMD_DEFAULTCOLORSET = "DefaultColorset" (COLORSET_NUM / "-1") ``` ``` CMD_DEFAULTFONT = "DefaultFont" [FONTNAME] ``` ``` CMD_DEFAULTICON = "DefaultIcon" [IMAGEFILE] ``` ``` CMD_DEFAULTLAYERS = "DefaultLayers" INT INT INT ``` ``` CMD_DESCHEDULE = "Deschedule" [INT] ``` ``` CMD_DESKTOPNAME = "DesktopName" INT DESKTOPNAME DESKTOPNAME = 1*(ALPHA DIGIT) ``` ``` CMD_DESKTOPSIZE = "DesktopSize" DESKTOPSIZDIM "x" DESKTOPSIZDIM DESKTOPSIZEDIM = INT ``` ``` CMD_DESTROYFUNC = "DestroyFunc" [FUNCNAME] ``` ``` CMD_DESTROYMENU = "DestroyMenu" ["recreate"] MENUNAME ``` ``` CMD_DESTROYMENUSTYLE = "DestroyMenuStyle" MENUSTYLENAME ``` ``` CMD_DESTROYMODULECONFIG = "DestroyModuleConfig" MODULECONFIG ``` ``` CMD_DESTROYSTYLE = "DestroyStyle" STYLENAME ``` ``` CMD_DESTROYWINDOWSTYLE = "DestroyWindowStyle" ; operates on context window ``` ``` CMD_ECHO = "Echo" RESTOFLINE ``` ``` CMD_ECHOFUNCDEFINITION = "EchoFuncDefinition" FUNCNAME ``` ``` CMD_EDGECOMMAND = "EdgeCommand" [DIRS_MAIN [RESTOFLINE_COMMAND]] ``` ``` CMD_EDGELEAVECOMMAND = "EdgeLeaveCommand" [DIRS_MAIN [RESTOFLINE_COMMAND]] ``` ``` CMD_EDGESCROLL = "EdgeScroll" EDGESCROLLDIM[EDGESCROLLSUFFIX] EDGESCROLLDIM[EDGESCROLLSUFFIX] [EDGESCROLLOPTION] EDGESCROLLDIM = INT EDGESCROLLSUFFIX = "p" EDGESCROLLOPTION = "Wrap" EDGESCROLLOPTION =/ "WrapX" EDGESCROLLOPTION =/ "WrapY" ``` ``` CMD_EDGETHICKNESS = "EdgeThickness" EDGETHICKNESSVAL EDGETHICKNESSVAL = "0" / "1" / "2" ``` ``` CMD_EMULATE = "Emulate" EMULATEVAL EMULATEVAL = "Mvwm" EMULATEVAL =/ "Mwm" EMULATEVAL =/ "Win" ``` ``` CMD_ESCAPEFUNC = "EscapeFunc" ``` ``` CMD_EWMHBASESTRUTS = "EwmhBaseStruts" ["screen" XRANDRMONITORNAME] INT INT INT INT ``` ``` CMD_EWMHNUMBEROFDESKTOPS = "EwmhNumberOfDesktops" ["screen" XRANDRMONITORNAME] INT INT ``` ``` CMD_EXEC = "Exec" RESTOFLINE_COMMAND ``` ``` CMD_EXECUSESHELL = "ExecUseShell" EXECUSESHELLSHELL ; Could technically be any external command; assume a value from /etc/shells EXECUSESHELLSHELL = !!! ``` ``` CMD_FAKECLICK = "FakeClick" FAKECLICKACTION *("," FAKECLICKACTION) FAKECLICKACTION = FAKECLICKCOMMAND FAKECLICKVALUE FAKECLICKCOMMAND = (FAKECLICKKEYWORD, FAKECLICKVALUE) FAKECLICKKEYWORD = "press" FAKECLICKKEYWORD =/ "release" FAKECLICKKEYWORD =/ "modifiers" FAKECLICKKEYWORD =/ "wait" FAKECLICKKEYWORD =/ FAKECLICKDEPTH FAKECLICKVALUE = "1" FAKECLICKVALUE =/ "2" FAKECLICKVALUE =/ "3" FAKECLICKVALUE =/ "4" FAKECLICKVALUE =/ "5" FAKECLICKVALUE =/ "Mod1" FAKECLICKVALUE =/ "Mod2" FAKECLICKVALUE =/ "Mod3" FAKECLICKVALUE =/ "Mod4" FAKECLICKVALUE =/ "Mod5" FAKECLICKVALUE =/ "6" FAKECLICKVALUE =/ "7" FAKECLICKVALUE =/ "8" FAKECLICKVALUE =/ "Shift" FAKECLICKVALUE =/ "Lock" FAKECLICKVALUE =/ "Control" FAKECLICKDEPTH = "depth" FAKECLICKDEPTH =/ "0" FAKECLICKDEPTH =/ "1" FAKECLICKDEPTH =/ "2" FAKECLICKDEPTH =/ "3" FAKECLICKDEPTH =/ INT ``` ``` CMD_FAKEKEYPRESS = "FakeKeypress" FAKEKEYPRESSACTION *("," FAKEKEYPRESSACTION) FAKEKEYPRESSACTION = FAKEKEYPRESSCOMMAND FAKEKEYPRESSVALUE FAKEKEYPRESSKEYWORD = "press" FAKEKEYPRESSKEYWORD =/ "release" FAKEKEYPRESSKEYWORD =/ "modifiers" FAKEKEYPRESSKEYWORD =/ "wait" FAKEKEYPRESSKEYWORD =/ DEPTH FAKEKEYPRESSVALUE = KEYNAME FAKEKEYPRESSDEPTH = "depth" FAKEKEYPRESSDEPTH =/ "0" FAKEKEYPRESSDEPTH =/ "1" FAKEKEYPRESSDEPTH =/ "2" FAKEKEYPRESSDEPTH =/ "3" FAKEKEYPRESSDEPTH =/ INT ``` ``` CMD_FLIPFOCUS = "FlipFocus" ["nowarp"] ``` ``` CMD_FOCUS = "Focus" ["nowarp"] ``` ``` CMD_FOCUSSTYLE = "FocusStyle" STYLEOPTIONS ``` ``` CMD_FUNCTION = "Function" [FUNCNAME] ``` ``` CMD_GOTODESK = "GotoDesk" DESKNUMBER DESKNUMBER = ["prev" / (INT [INT [INT [INT]]])] ``` ``` CMD_GOTODESKANDPAGE = "GotoDeskAndPage" "prev" / (INT INT INT) ``` ``` CMD_GOTOPAGE = "GotoPage" PAGE_ARGUMENTS PAGE_ARGUMENTS = ["prev" / ([OPTIONS] 2(PAGECCORD[PAGESUFFIX]) OPTIONS = ["!"] ("wrapx" / "wrapy" / "nodesklimitx" / "nodesklimity") PAGECOORD = INT PAGESUFFIX = "p" ``` ``` CMD_HIDEGEOMETRYWINDOW = "HideGeometryWindow" [HIDEGEOMETRYWINDOWCOMMAND] HIDEGEOMETRYWINDOWCOMMAND = "Never" HIDEGEOMETRYWINDOWCOMMAND =/ "Move" HIDEGEOMETRYWINDOWCOMMAND =/ "Resize" ``` ``` CMD_HILIGHTCOLORSET = "HilightColorset" [COLORSET_NUM] ``` ``` CMD_ICONIFY = "Iconify" BOOL_OR_TOGGLE ``` ``` CMD_IGNOREMODIFIERS = "IgnoreModifiers" [ BINDINGMODIFIERS ] ``` ``` CMD_IMAGEPATH = "ImagePath" [PATH] ``` ``` CMD_INFOSTOREADD = "InfoStoreAdd" INFOSTOREKEY INFOSTOREVALUE INFOSTOREKEY = STRING INFOSTOREVALUE = STRING ``` ``` CMD_INFOSTOREREMOVE = "InfoStoreRemove" [INFOSTOREREKEY] ``` ``` CMD_KEEPRC = "KeepRc" [RESTOFLINE_COMMAND] ``` ``` CMD_CLASS_KEY = ("Key" / "PointerKey") ["(" WINDOWSELECTOR ")"] KEYNAME BINDINGCONTEXT BINDINGMODIFIERS RESTOFLINE_COMMAND ``` ``` CMD_KILLMODULE = "KillModule" [MODULENAME] [MODULEALIAS] ``` ``` CMD_LAYER = "Layer" [INT INT] / "default" ``` ``` CMD_LOCALEPATH = "LocalePath" [PATH] ``` ``` CMD_CLASS_RAISELOWER = ("Lower" / "Raise" / "RaiseLower") ; operates on context window ``` ``` CMD_MAXIMIZE = "Maximize" [MAXIMIZEFLAGS] [BOOL_OR_TOGGLE / "forget"] [[MAXIMIZEDIM[MAXIMIZESUFFIX]] MAXIMIZEDIM[MAXIMIZESUFFIX]] MAXIMIZEGROWOPTS = "grow" MAXIMIZEGROWOPTS =/ "growleft" MAXIMIZEGROWOPTS =/ "growright" MAXIMIZEGROWOPTS =/ "growup" MAXIMIZEGROWOPTS =/ "growdown" MAXIMIZEDIM = INT MAXIMIZEDIM =/ MAXIMIZEGROWOPTS MAXIMIZESUFFIX = "p" MAXIMIZEFLAGS = "ewmhiwa" MAXIMIZEFLAGS =/ "growonwindowlayer" MAXIMIZEFLAGS =/ "growonlayers" MAXIMIZEFLAGS =/ ("screen" / XINERAMASCR) ``` ``` CMD_CLASS_MENU = ("Menu" / "Popup") MENUNAME [MENUPOSITION] [MENUCOMMAND] MENUPOSITION = MENUCONTEXT_RECTANGLE INT INT [MENUOPTIONS] MENUCONTEXT_RECTANGLE = "Root" !!! MENUCONTEXT = "XineramaRoot" MENUCONTEXT =/ "Mouse" MENUCONTEXT =/ "Window" MENUCONTEXT =/ "Interior" MENUCONTEXT =/ "Title" MENUCONTEXT =/ ("Button" INT) "Icon" MENUCONTEXT =/ "Item" MENUCONTEXT =/ "Context" MENUCONTEXT =/ "This" MENUCONTEXT =/ ("Rectangle" MENUCONTEXTGEOMETRY) MENUOPTIONS = "TearoffImmediately" MENUOPTIONS =/ "SelectInPlace" MENUOPTIONS = !!! MENUCONTEXTGEOMETRY = !!! ``` ``` CMD_MENUSTYLE = "MenuStyle" MENUSTYLENAME *(["!"] MENUSTYLEOPTIONS) MENUSTYLEOPTIONS = "Mvwm" MENUSTYLEOPTIONS =/ "Mwm" MENUSTYLEOPTIONS =/ "Win" MENUSTYLEOPTIONS =/ "BorderWidth" MENUSTYLEOPTIONS =/ "Foreground" MENUSTYLEOPTIONS =/ "Background" MENUSTYLEOPTIONS =/ "Greyed" MENUSTYLEOPTIONS =/ "HilightBack" MENUSTYLEOPTIONS =/ "HilightTitleBack" MENUSTYLEOPTIONS =/ "ActiveFore" MENUSTYLEOPTIONS =/ "MenuColorset" MENUSTYLEOPTIONS =/ "ActiveColorset" MENUSTYLEOPTIONS =/ "GreyedColorset" MENUSTYLEOPTIONS =/ "TitleColorset" MENUSTYLEOPTIONS =/ "Hilight3DThick" MENUSTYLEOPTIONS =/ "Hilight3DThin" MENUSTYLEOPTIONS =/ "Hilight3DOff" MENUSTYLEOPTIONS =/ "Hilight3DThickness" MENUSTYLEOPTIONS =/ "Animation" MENUSTYLEOPTIONS =/ "Font" MENUSTYLEOPTIONS =/ "TitleFont" MENUSTYLEOPTIONS =/ "MenuFace" MENUSTYLEOPTIONS =/ "PopupDelay" MENUSTYLEOPTIONS =/ "PopupOffset" MENUSTYLEOPTIONS =/ "TitleWarp" MENUSTYLEOPTIONS =/ "TitleUnderlines0" MENUSTYLEOPTIONS =/ "TitleUnderlines1" MENUSTYLEOPTIONS =/ "TitleUnderlines2" MENUSTYLEOPTIONS =/ "SeparatorsLong" MENUSTYLEOPTIONS =/ "SeparatorsShort" MENUSTYLEOPTIONS =/ "TrianglesSolid" MENUSTYLEOPTIONS =/ "TrianglesRelief" MENUSTYLEOPTIONS =/ "PopupImmediately" MENUSTYLEOPTIONS =/ "PopupDelayed" MENUSTYLEOPTIONS =/ "PopdownImmediately" MENUSTYLEOPTIONS =/ "PopdownDelayed" MENUSTYLEOPTIONS =/ "PopupActiveArea" MENUSTYLEOPTIONS =/ "DoubleClickTime" MENUSTYLEOPTIONS =/ "SidePic" MENUSTYLEOPTIONS =/ "SideColor" MENUSTYLEOPTIONS =/ "PopupAsRootMenu" MENUSTYLEOPTIONS =/ "PopupAsSubmenu" MENUSTYLEOPTIONS =/ "PopupIgnore" MENUSTYLEOPTIONS =/ "PopupClose" MENUSTYLEOPTIONS =/ "RemoveSubmenus" MENUSTYLEOPTIONS =/ "HoldSubmenus" MENUSTYLEOPTIONS =/ "SubmenusRight" MENUSTYLEOPTIONS =/ "SubmenusLeft" MENUSTYLEOPTIONS =/ "SelectOnRelease" MENUSTYLEOPTIONS =/ "ItemFormat" MENUSTYLEOPTIONS =/ "VerticalItemSpacing" MENUSTYLEOPTIONS =/ "VerticalMargins" MENUSTYLEOPTIONS =/ "VerticalTitleSpacing" MENUSTYLEOPTIONS =/ "AutomaticHotkeys" MENUSTYLEOPTIONS =/ "UniqueHotkeyActivatesImmediate" MENUSTYLEOPTIONS =/ "MouseWheel" MENUSTYLEOPTIONS =/ "ScrollOffPage" MENUSTYLEOPTIONS =/ "TrianglesUseFore" ; add option syntax ``` ``` CMD_CLASS_MODULE = ("Module" / "ModuleListenOnly") CMDMODULEARGS CMDMODULEARGS = MODULENAME [MODULEALIAS] ``` ``` CMD_MODULEPATH = "ModulePath" PATH ``` ``` CMD_MODULESYNCHRONOUS = "ModuleSynchronous" ["Expect" STRING] ["Timeout" INT] CMDMODULEARGS ``` ``` CMD_MODULETIMEOUT = "ModuleTimeout" INT ``` ``` CMD_MOUSE = "Mouse" ["(" WINDOWSELECTOR ")"] BUTTON BINDINGCONTEXT BINDINGMODIFIERS COMMAND ``` ``` CMD_MOVE = "Move" [MOVEARGS] MOVEARGS = !!! ``` ``` CMD_MOVETHRESHOLD = "MoveThreshold" [INT] ``` ``` CMD_MOVETODESK = "MoveToDesk" DESKNUMBER ``` ``` CMD_MOVETOPAGE = "MoveToPage" ["prev"] [MOVETOPAGEOPTIONS] 2(MOVETOPAGECOORD[MOVETOPAGESUFFIX]) MOVETOPAGEOPTIONS = "wrapx" / "wrapy" / "nodesklimitx" / "nodesklimity" MOVETOPAGECOORD = INT MOVETOPAGESUFFIX = "p" / "w" ``` ``` CMD_MOVETOSCREEN = "MoveToScreen" [XRANDRMONITORNAME] XRANDRMONITORNAME = !!! ``` ``` CMD_NOP = "Nop" ``` ``` CMD_OPAQUEMOVESIZE = "OpaqueMoveSize" [INT] ``` ``` CMD_PIPEREAD = "PipeRead" TOKEN ["quiet"] ``` ``` CMD_PLACEAGAIN = "PlaceAgain" *("Anim" "Icon") ``` ``` CMD_PLUS = "Plus" RESTOFLINE ``` ``` CMD_PRINTINFO = "PrintInfo" PRINTINFOSUBJECT PRINTINFOSUBJECT = (PRINTINFOKEYWORD [PRINTINFOVAL]) PRINTINFOVAL = "0" PRINTINFOVAL =/ "1" PRINTINFOVAL =/ "2" PRINTINFOKEYWORD = "Colors" PRINTINFOKEYWORD =/ "ImageCache" PRINTINFOKEYWORD =/ "Locale" PRINTINFOKEYWORD =/ "NLS" PRINTINFOKEYWORD =/ "Style" PRINTINFOKEYWORD =/ "Bindings" PRINTINFOKEYWORD =/ "Infostore" ``` ``` CMD_QUIT = "Quit" ``` ``` CMD_QUITSCREEN = "QuitScreen" ``` ``` CMD_READ = "Read" FILENAME ["quiet"] ``` ``` CMD_CLASS_RECAPTURE = ("Recapture" / "RecaptureWindow") ``` ``` CMD_CLASS_REFRESH = ("Refresh" / "RefreshWindow") ``` ``` CMD_REPEAT = "Repeat" ["command"] ``` ``` CMD_CLASS_RESIZE = ("Resize" / "ResizeMaximize") [RESIZEOPTS] RESIZEOPTS = (RESIZEOPTS_BR / RESIZEOPTS_OTHER) [2RESIZEARG] RESIZEOPTS_BR = ("bottomright" / "br") MOVEARGS RESIZEOPTS_OTHER = ("frame" / "fixeddirection" / ("direction" (DIRS_CENTER / "automatic")) / ("warptoborder" ["automatic"])) RESIZEARG = "keep" / (RESIZEARG_2 [RESIZEARGSUFFIX]) RESIZEARG_2 = "w" / (["w"] RESIZEARGVAL) RESIZEARGVAL = (SIGN INT) / POSINT RESIZEARGSUFFIX = "p" / "c" ``` ``` CMD_CLASS_RESIZEMOVE = ("ResizeMove" / "ResizeMoveMaximize") RESIZEOPTS MOVEARGS ``` ``` CMD_RESTACKTRANSIENTS = "RestackTransients" ``` ``` CMD_RESTART = "Restart" [STRING] ``` ``` CMD_SCHEDULE = "Schedule" ["periodic"] INT [INT] RESTOFLINE_COMMAND ``` ``` CMD_SCROLL = "Scroll" [(SCROLLDIM[SCROLLSUFFIX] SCROLLDIM[SCROLLSUFFIX]) / OPTION] SCROLLDIM = INT OPTION = "reverse" SCROLLSUFFIX = "p" ``` ``` CMD_SENDTOMODULE = "SendToModule" [MODULENAME] [STRING] ``` ``` CMD_SETANIMATION = "SetAnimation" INT [INT] ``` ``` CMD_SILENT = "Silent" RESTOFLINE_COMMAND ``` ``` CMD_STATE = "State" STATENUM [BOOL] ``` ``` CMD_CLASS_STICK = ("Stick" / "StickAcrossDesks" / "StickAcrossPages") [BOOL_OR_TOGGLE] ``` ``` CMD_CLASS_STYLE = ("Style" / "WindowStyle") [STYLENAME] [STYLEOPTIONS] ; note: WindowStyle operates on context window STYLEOPTIONS = STYLEOPTION ("," STYLEOPTION) STYLEOPTION = !!! ``` ``` CMD_TEARMENUOFF = "TearMenuOff" ; note: applies to menu context only ; note: ignores all arguments ; note: syntax description complete ``` ``` CMD_TITLE = "Title" ; note: applies to menu context only ; note: ignores all arguments ; note: syntax description complete ``` ``` CMD_TITLESTYLE = "TitleStyle" ;!!! ``` ``` CMD_SETENV = "SetEnv" [TOKEN_ENVVAR [TOKEN_ENVVAL]] TOKEN_ENVVAR = TOKEN TOKEN_ENVVAL = TOKEN ; note: does nothing if no arguments are given ; note: uses an empty value string if the second argument is missing ; note: ignores rest of line ; note: syntax description complete ``` ``` CMD_UNSETENV = "UnsetEnv" [TOKEN_ENVVAR] ; note: does nothing if argument is missing ; note: ignores rest of line ; note: syntax description complete ``` ``` CMD_UPDATESTYLES = "UpdateStyles" ; note: ignores rest of line ; note: syntax description complete ``` ``` CMD_WAIT = "Wait" [TOKEN_WAIT_PATTERN [STRIPPED_RESTOFLINE]] ; Note: The first argument, or - if present - the rest of the line is used as ; the pattern to wait for. ; note: the syntax with more than one argument is not documented. Comment in ; the sources call it the "old syntax". ; note: syntax description complete ``` ``` CMD_WARPTOWINDOW = "WarpToWindow" [PERCENT_ARG_PAIR] ; note: arguments not used when used on an unmanaged window ; note: arguments are ignored if not valid ; note: ignores rest of line ; note: syntax description complete ``` ``` ;!!!todo CMD_WINDOWLIST = "WindowList" ["(" WINDOWLISTCONDITIONS ")"] [WINDOWLISTPOSITION] [WINDOWLLISTOPTIONS] [COMMAND] WINDOWLISTPOSITION = WINDOWLISTCONTEXT_RECTANGLE INT INT [WINDOWLISTCONTEXTOPTIONS] WINDOWLISTCONTEXT_RECTANGLE = "Root" WINDOWLISTCONTEXT_RECTANGLE =/ "XineramaRoot" WINDOWLISTCONTEXT_RECTANGLE =/ "Mouse" WINDOWLISTCONTEXT_RECTANGLE =/ "Window" WINDOWLISTCONTEXT_RECTANGLE =/ "Interior" WINDOWLISTCONTEXT_RECTANGLE =/ "Tiitle" WINDOWLISTCONTEXT_RECTANGLE =/ ("Button" INT) WINDOWLISTCONTEXT_RECTANGLE =/ "Icon" WINDOWLISTCONTEXT_RECTANGLE =/ "Item" WINDOWLISTCONTEXT_RECTANGLE =/ "Context" WINDOWLISTCONTEXT_RECTANGLE =/ "This" WINDOWLISTCONTEXT_RECTANGLE =/ ("Rectangle" GEOMETRY) WINDOWLISTCONTEXTOPTIONS = "TearoffImmediately" WINDOWLISTCONTEXTOPTIONS =/ "SelectInPlace" WINDOWLISTOPTIONS = (WINDOWLISTKEYWORD [WINDOWLISTVALUE]) WINDOWLISTOPTIONS = "Geometry" WINDOWLISTOPTIONS =/ "NoGeometry" WINDOWLISTOPTIONS =/ "NoGeometryWithInfo" WINDOWLISTOPTIONS =/ "NoDeskNum" WINDOWLISTOPTIONS =/ "NoLayer" WINDOWLISTOPTIONS =/ "NoNumInDeskTitle" WINDOWLISTOPTIONS =/ "NoCurrentDeskTitle" WINDOWLISTOPTIONS =/ ("MaxLabelWidth" INT) WINDOWLISTOPTIONS =/ "TitleForAllDesks" WINDOWLISTOPTIONS =/ ("Function" FUNCNAME) WINDOWLISTOPTIONS =/ ("Desk" INT) WINDOWLISTOPTIONS =/ "CurrentDesk" WINDOWLISTOPTIONS =/ "NoIcons" WINDOWLISTOPTIONS =/ "Icons" WINDOWLISTOPTIONS =/ "OnlyIcons" WINDOWLISTOPTIONS =/ "NoNormal" WINDOWLISTOPTIONS =/ "Normal" WINDOWLISTOPTIONS =/ "OnlyNormal" WINDOWLISTOPTIONS =/ "NoSticky" WINDOWLISTOPTIONS =/ "Sticky" WINDOWLISTOPTIONS =/ "OnlySticky" WINDOWLISTOPTIONS =/ "NoStickyAcrossPages" WINDOWLISTOPTIONS =/ "StickyAcrossPages" WINDOWLISTOPTIONS =/ "OnlyStickyAcrossPages" WINDOWLISTOPTIONS =/ "NoStickyAcrossDesks" WINDOWLISTOPTIONS =/ "StickyAcrossDesks" WINDOWLISTOPTIONS =/ "OnlyStickyAcrossDesks" WINDOWLISTOPTIONS =/ "NoOnTop" WINDOWLISTOPTIONS =/ "OnTop" WINDOWLISTOPTIONS =/ "OnlyOnTop" WINDOWLISTOPTIONS =/ "NoOnBottom" WINDOWLISTOPTIONS =/ "OnlyOnBottom" WINDOWLISTOPTIONS =/ (Layer INT [INT]) WINDOWLISTOPTIONS =/ "UseSkipList" WINDOWLISTOPTIONS =/ "OnlySkipList" WINDOWLISTOPTIONS =/ "SortByResource" WINDOWLISTOPTIONS =/ "SortByClass" WINDOWLISTOPTIONS =/ "NoHotKeys" WINDOWLISTOPTIONS =/ "SelectOnRelease" WINDOWLISTOPTIONS =/ "ReverseOrder" WINDOWLISTOPTIONS =/ "NoDeskSort" WINDOWLISTOPTIONS =/ "CurrentAtEnd" WINDOWLISTOPTIONS =/ "IconifiedAtEnd" WINDOWLISTOPTIONS =/ "UseIconName" WINDOWLISTOPTIONS =/ "Alphabetic" WINDOWLISTOPTIONS =/ "NotAlphabetic" WINDOWLISTKEYWORD = !!! WINDOWLISTVALUE = !!! ; note: !!! to do ``` ``` CMD_WINDOWSHADE = "WindowShade" ["shadeagain"] ["last" / DIRS_MINOR] [WINDOWSHADEMODE] WINDOWSHADEMODE = WINDOWSHADETOGGLE / WINDOWSHADEON / WINDOWSHADEOFF WINDOWSHADETOGGLE = () / TOGGLE WINDOWSHADEON = TRUE WINDOWSHADEOFF = FALSE / "2" ; note: defaults to toggle ; note: if "last" or DIRS_MINOR is present and valid, ignore the ; WINDOWSHADEMODE argument if present ; note: ignores rest of line ; note: syntax description complete ``` ``` CMD_XSYNC = "XSync" ; note: ignores all arguments ; note: syntax description complete ``` ``` CMD_XSYNCHRONIZE = "XSynchronize" [BOOL_OR_TOGGLE_DEFAULT_TOGGLE] ; note: argument defaults to toggle if missing or invalid ; note: ignores rest of line ; note: syntax description complete ``` ``` CMD_XORPIXMAP = "XorPixmap" [IMAGEFILE] ; note: if argument is missing, maps to "XorValue 0" ; note: ignores rest of line ; note: syntax description complete ``` ``` CMD_XORVALUE = "XorValue" [INTEGER_ARGUMENT] ; note: argument defaults to 0 if missing or malformed ; note: argument is converted to unsinged long before use ; note: argument should be parsed as unsigned long to prevent misinterpretation ; note: ignores rest of line ; note: syntax description complete ``` ``` ;; decor commands CMD_ADDTODECOR = "AddToDecor" [TOKEN_DECORNAME] RESTOFLINE_COMMAND ; note: does nothing if the decor name is missing ; note: if no decor with that name exists, creates a new one ; note: adds the command to the decor ; note: syntax description complete CMD_CHANGEDECOR = "ChangeDecor" [TOKEN_DECORNAME] ; note: does nothing if no decor name is given ; note: ignores rest of line ; note: syntax description complete ; note: operates on current window CMD_DESTROYDECOR = "DestroyDecor" ["recreate"] [TOKEN_DECORNAME] ; note: does nothing if no decor name is given ; note: ignores rest of line ; note: syntax description complete CMD_UPDATEDECOR = "UpdateDecor" [TOKEN_DECORNAME] ; note: updates all decors if decor name is missing ; note: ignores rest of line ; note: syntax description complete ``` ``` ;; conditional commands CMD_BREAK = "Break" [BREAKLEVELS] BREAKLEVELS = INT ; note: uses -1 if BREAKLEVELS is missing or invalid (<= 0) ; note: syntax description complete ``` ``` CMD_CLASS_PICK = ("ThisWindow" / "Pick" / "PointerWIndow" ) [SELECTCMDCONDITION] RESTOFLINE_COMMAND ; note: syntax description complete ``` ``` CMD_ALL = "All" [ALLOPTIONS] [SELECTCMDCONDITION] RESTOFLINE_COMMAND ALLOPTIONS = "Reverse" ALLOPTIONS =/ "UseStack" ; note: syntax description complete ``` ``` CMD_NOWINDOW = "NoWindow" RESTOFLINE_COMMAND ; note: executes the command without a window context ; note: syntax description complete ``` ``` CMD_CLASS_CIRCULATE = ("Any" / "Current" / "Next" / "None" / "Prev") [SELECTCMDCONDITION] RESTOFLINE_COMMAND ; note: syntax description complete ``` ``` CMD_DIRECTION = "Direction" ["FromPointer"] DIRS_CENTER [SELECTCMDCONDITION] RESTOFLINE_COMMAND ; note: syntax description complete ``` ``` CMD_SCANFORWINDOW = "ScanForWindow" ["FromPointer"] DIRS_MAIN DIRS_MAIN [SELECTCMDCONDITION] RESTOFLINE_COMMAND ; note: syntax description complete ``` ``` CMD_WINDOWID = "WindowId" [("root" [WINDOWIDSCREENNUM]) / (WINDOWID [SELECTCMDCONDITION])] RESTOFLINE_COMMAND ; does nothing if no argument is given of the window id is invalid ; note: syntax description complete WINDOWIDSCREENNUM = POSINT ; note: valid range is 0 to <number of screens - 1> ; note: mvwm has replaced Xinerama with XRandr, therfore using integets to ; refer to monitors won't work. WINDOWID = LONGINT ; note: long value parsed by strtol without error checking ``` ``` CMD_TEST = "Test" TESTCMDCONDITION RESTOFLINE_COMMAND TESTCMDCONDITIONSTRING = [STRING_IN_BRACES / STRING_IN_PARENTHESES] ; note: the STRING_IN_... is then parsed with the TESTCMDCONDITIONS rule TESTCMDCONDITIONS = STRING_COMMA_TERMINATED *["," STRING_COMMA_TERMINATED] ; note: the TESTCMDCONDITIONS is then parsed with the TESTCMDCONDNEG rule TESTCMDCONDNEG = ["!"] TESTCMDCOND TESTCMDCOND = ("version" ((TOKEN_TESTCMDOPERATOR VERSION) / TOKEN_VERSIONPATTERN)) TESTCMDCOND =/ ("EnvIsSet" TOKEN_ENVVAR) TESTCMDCOND =/ ("EnvMatch" ENVMATCHARG) TESTCMDCOND =/ (("EdgeHasPointer" / "EdgeIsActive") (DIRS_MAIN / "Any")) TESTCMDCOND =/ ("Start" / "Init" / "Restart" / "Exit" / "Quit" / "ToRestart") TESTCMDCOND =/ ("True" / "False") TESTCMDCOND =/ (("F" / "R" / "W" / "X" / "I") "," FILENAME) TOKEN_TESTCMDOPERATOR = ">=" / ">" / "<=" / "==" / "!=" ENVMATCHARG = ("infostore."INFOSTOREKEY) / TOKEN_ENVVAR TESTCMDVERSIONPATTERN = TOKEN ; note: TESTCMDVERSIONPATTERN is compared to the version string (x.y.z) and may ; contain wildcards. ``` ``` CMD_TESTRC = "TestRc" [STRING_IN_BRACES / STRING_IN_PARENTHESES] RESTOFLINE_COMMAND TESRRCRCNEG = ["!"] TESTRCRC TESTRCRC = "1" / "match" TESTRCRC =/ "0" / "nomatch" TESTRCRC =/ "-1" / "error" TESTRCRC =/ "-2" / "break" ; note: the STRING_IN_... is then parsed with the TESTRCRC rule ; note: does nothing if no command is given : note: the condition inside the braces or parentheses may contain quoted ; note: syntax description complete ``` ``` ;; !!! more common rules ; Integer arguments as parsed by GetIntegerArguments() INTEGER_ARGUMENT = INT ; Loaded by PictureFindImageFile IMAGEFILE = TOKEN ; note: if file not found, try again with IMAGEFILE ".gz" ``` ``` ; parsed by parse_gravity_argument DIR_N = "-" / "N" / "North" / "Top" / "t" / "Up" / "u" DIR_E = "]" / "E" / "East" / "Right" / "r" / "Right" / "r" DIR_S = "_" / "S" / "South" / "Bottom" / "b" / "Down" / "d" DIR_W = "[" / "W" / "West" / "Left" / "l" / "Left" / "l" DIR_NE = "^" / "NE" / "NorthEast" / "TopRight" / "tr" / "UpRight" / "ur" DIR_SE = ">" / "SE" / "SouthEast" / "BottomRight" / "br" / "DownRight" / "dr" DIR_SW = "v" / "SW" / "SouthWest" / "BottomLeft" / "bl" / "DownLeft" / "dl" DIR_NE = "<" / "NW" / "NorthWest" / "TopLeft" / "tl" / "UpLeft" / "ul" DIR_C = "." / "C" / "Center" / "Centre" DIRS_MAJOR = DIR_N / DIR_E / DIR_S / DIR_W DIRS_MINOR = DIRS_MAIN / DIR_NE / DIR_SE / DIR_SW / DIR_NW DIRS_ALL = DIRS_MAIN / DIRS_DIAG / DIR_C ``` ``` ; Parsed by ParseToggleArgument BOOL_OR_TOGGLE_DEFAULT_TOGGLE = BOOL / TOGGLE BOOL_OR_TOGGLE_DEFAULT_TRUE = BOOL / TOGGLE BOOL_OR_TOGGLE_DEFAULT_FALSE = BOOL / TOGGLE BOOL_DEFAULT_TRUE = BOOL BOOL_DEFAULT_FALSE = BOOL ``` ``` ; parsed by strtol LONGINT = INT ``` ``` ; parsed by select_cmd() SELECTCMDCONDITION = [STRING_IN_BRACES / STRING_IN_PARENTHESES] ; note: the STRING_IN_... is then parsed with the CONDITIONMASK rule ``` ``` ; parsed by CreateFlagString CONDITIONMASK = [CM_COND_NEG *("," CM_COND_NEG)] CM_COND_NEG = ["!"] CM_COND CM_COND = ("AcceptsFocus") CM_COND =/ ("Focused") CM_COND =/ ("HasPointer") CM_COND =/ ("Iconic") CM_COND =/ ("Visible") CM_COND =/ ("Overlapped") CM_COND =/ ("PlacedByButton" [BUTTON]) CM_COND =/ ("PlacedByButton3") CM_COND =/ ("Raised") CM_COND =/ ("Sticky") CM_COND =/ ("StickyAcrossPages") CM_COND =/ ("StickyAcrossDesks") CM_COND =/ ("StickyIcon") CM_COND =/ ("StickyAcrossPagesIcon") CM_COND =/ ("StickyAcrossDesksIcon") CM_COND =/ ("Maximized") CM_COND =/ ("FixedSize") CM_COND =/ ("FixedPosition") CM_COND =/ ("HasHandles") CM_COND =/ ("Iconifiable") CM_COND =/ ("Maximizable") CM_COND =/ ("Closable") CM_COND =/ ("Shaded") CM_COND =/ ("Transient") CM_COND =/ ("PlacedByMvwm") CM_COND =/ ("CurrentDesk") CM_COND =/ ("CurrentPage") CM_COND =/ ("CurrentGlobalPage") CM_COND =/ ("CurrentPageAnyDesk") CM_COND =/ ("CurrentScreen") CM_COND =/ ("AnyScreen") CM_COND =/ ("CurrentGlobalPageAnyDesk") CM_COND =/ ("CirculateHit") CM_COND =/ ("CirculateHitIcon") CM_COND =/ ("CirculateHitShaded") CM_COND =/ ("State" STATENUM) CM_COND =/ ("Layer" [INT]) ; argument is the layer number; negative values are silently ignored CM_COND =/ NAMELIST CM_NAMELIST = NAME *["|" NAME] CM_NAME = STRING ; up to and excluding next "|" ``` ``` QUOTED_TOKEN = TOKEN ``` ``` STATENUM = DIGIT / ("1" DIGIT) / ("2" DIGIT) / "30" / "31" ``` ``` ; Parsed by GetOnePercentArgument() PERCENT_ARG = INT [PERCENT_ARG_SUFFIX] PERCENT_ARG_SUFFIX = "p" / "P" ; Parsed by GetTwoPercentArguments() PERCENT_ARG_PAIR = 2PERCENT_ARG / RECTANGLE_ARGS ; Parsed by GetRectangleArguments() RECTANGLE_ARGS = INT RECT_CHARACTER INT RECT_CHARACTER = %x01-09 / %x0b-4f / %x51-6f / %x71-ff ; note: any character except p, P and \n. DQ_RECT_CHARACTER = %x01-09 / %x0b-4f / %x51-6f / %x71-ff ``` ``` ;; string rules DQUOTE = %x22 ; " SQUOTE = %x27 ; ' BQUOTE = %x60 ; ` CQUOTE = %x5c ; \ ; any character except \, ", ', `, whitespace, newline SCHAR_UNQ = %x01-08 SCHAR_UNQ =/ %x0b-1f SCHAR_UNQ =/ %x21 SCHAR_UNQ =/ %x23-26 SCHAR_UNQ =/ %x28-5b SCHAR_UNQ =/ %x5d-5f SCHAR_UNQ =/ %x61-ff ; any character except \, ", ', `, ), whitespace, newline SCHAR_UNQ_NO_CPAREN = %x01-08 SCHAR_UNQ_NO_CPAREN =/ %x0b-1f SCHAR_UNQ_NO_CPAREN =/ %x21 SCHAR_UNQ_NO_CPAREN =/ %x23-26 SCHAR_UNQ_NO_CPAREN =/ %x28 SCHAR_UNQ_NO_CPAREN =/ %x2a-5b SCHAR_UNQ_NO_CPAREN =/ %x5d-5f SCHAR_UNQ_NO_CPAREN =/ %x61-ff ; any character except \, ", ', `, ], whitespace, newline SCHAR_UNQ_NO_CBRACE = %x01-08 SCHAR_UNQ_NO_CBRACE =/ %x0b-1f SCHAR_UNQ_NO_CBRACE =/ %x21 SCHAR_UNQ_NO_CBRACE =/ %x23-26 SCHAR_UNQ_NO_CBRACE =/ %x28-5b SCHAR_UNQ_NO_CBRACE =/ %x5e-5f SCHAR_UNQ_NO_CBRACE =/ %x61-ff ; any character except \, ", ', `, comma, whitespace, newline SCHAR_UNQ_NO_COMMA = %x01-08 SCHAR_UNQ_NO_COMMA =/ %x0b-1f SCHAR_UNQ_NO_COMMA =/ %x21 SCHAR_UNQ_NO_COMMA =/ %x23-26 SCHAR_UNQ_NO_COMMA =/ %x28-2b SCHAR_UNQ_NO_COMMA =/ %x2d-5b SCHAR_UNQ_NO_COMMA =/ %x5d-5f SCHAR_UNQ_NO_COMMA =/ %x61-ff ; \ followed by any character except newline SCHAR_CQ_CHAR = "\" (%x01-09 /%x0b-ff) ; any character except ", whitespace, newline (\ quotes resolved) SCHAR_DQ = SCHAR_UNQ SCHAR_DQ =/ SQUOTE SCHAR_DQ =/ BQUOTE SCHAR_DQ =/ SCHAR_CQ_CHAR ; any character except ', whitespace, newline (\ quotes resolved) SCHAR_SQ = SCHAR_UNQ SCHAR_SQ =/ DQUOTE SCHAR_SQ =/ BQUOTE SCHAR_SQ =/ SCHAR_CQ_CHAR ; any character except `, whitespace, newline (\ quotes resolved) SCHAR_BQ = SCHAR_UNQ SCHAR_BQ =/ DQUOTE SCHAR_BQ =/ SQUOTE SCHAR_BQ =/ SCHAR_CQ_CHAR ; any simple character or one quoted with \ SCHAR_CQ = SCHAR_UNQ SCHAR_CQ =/ SCHAR_CQ_CHAR ``` ``` ; unquoted string STRING_UNQ = 1*SCHAR_UNQ STRING_UNQ_NO_CPAREN = 1*SCHAR_UNQ_NO_CPAREN STRING_UNQ_NO_CBRACE = 1*SCHAR_UNQ_NO_CBRACE STRING_UNQ_NO_COMMASTRING_UNQ_NO_COMMA = 1*SCHAR_UNQ_NO_COMMA ; strings quoted with ", ', ` STRING_DQ = DQUOTE 1*SCHAR_DQ DQUOTE STRING_SQ = SQUOTE 1*SCHAR_SQ SQUOTE STRING_BQ = BQUOTE 1*SCHAR_BQ BQUOTE STRING_Q_PAIR = STRING_DQ / STRING_SQ / STRING_BQ STRING = 1*(STRING_UNQ / STRING_DQ / STRING_SQ / STRING_BQ) TOKEN = STRING ; a string with embedded whitespace enclosed in [] used in condigions STRING_IN_BRACES = *WS "[" *(STRING_UNQ_NO_CBRACE / STRING_Q_PAIR / 1*WSC) "]" ; a string with embedded whitespace enclosed in () used in conditions STRING_IN_PARENTHESES = *WS "[" *(STRING_UNQ_NO_CPAREN / STRING_Q_PAIR / 1*WSC) "]" ; a string with embedded whitespace terminated by an unquoted comma STRING_COMMA_TERMINATED = *(STRING_UNQ_NO_COMMA / STRING_Q_PAIR / 1*WSC) ``` ``` ;; !!! obsolete commands removed in mvwm CMD_GNOMEBUTTON = "GnomeButton" CMD_GNOMESHOWDESKS = "GnomeShowDesks" CMD_SAVESESSION = "SaveSession" CMD_SAVEQUITSESSION = "SaveQuitSession" CMD_STROKE = "Stroke" CMD_STROKEFUNC = "StrokeFunc" CMD_QUITSESSION = "QuitSession" CMD_XINERAMA = "Xinerama" CMD_XINERAMAPRIMARYSCREEN = "XineramaPrimaryScreen" CMD_XINERAMASLS = "XineramaSls" CMD_XINERAMASLSSCREENS = "XineramaSlsScreens" CMD_XINERAMASLSSIZE = "XineramaSlsSize" ;; !!! obsolete commands in fvwm2 CMD_COLORLIMIT = "ColorLimit" CMD_WINDOWFONT = "WindowFont" ; Style * Font ... CMD_WINDOWSHADEANIMATE = "WindowShadeAnimate" ; Style * WindowShadeSteps CMD_WINDOWSDESK = "WindowsDesk" ; See 'MoveToDesk' CMD_DESK = "Desk" ; See 'Gotodesk' CMD_EDGERESISTANCE = "EdgeResistance" ; Style * EdgeMoveDelay, EdgeMoveResistance CMD_GLOBALOPTS = "GlobalOpts" ; Various Style options CMD_HILIGHTCOLOR = "HilightColor" ; Style CMD_ICONFONT = "IconFont" FONTNAME ; Style CMD_ICONPATH = "IconPath" ; ImagePath CMD_PIXMAPPATH = "PixmapPath" ; ImagePath CMD_SNAPATTRACTION = "SnapAttraction" ; Style * SnapAttraction CMD_SNAPGRID = "SnapGrid" ; Style * SnapGrid ``` �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/docs/Makefile.in�������������������������������������������������������������������������0000644�0001750�0001750�00000035061�14324315775�012435� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 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 = docs ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.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__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALL_DOMAINS = @ALL_DOMAINS@ ALL_LINGUAS = @ALL_LINGUAS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR_FLAGS = @AR_FLAGS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ Bidi_CFLAGS = @Bidi_CFLAGS@ Bidi_LIBS = @Bidi_LIBS@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DOC_COMMANDS = @DOC_COMMANDS@ DOC_COMMANDS_HTML = @DOC_COMMANDS_HTML@ DOC_COMMANDS_XML = @DOC_COMMANDS_XML@ DOC_COMMANDS_XML_PATH = @DOC_COMMANDS_XML_PATH@ DOC_MODULES = @DOC_MODULES@ DOC_MODULES_HTML = @DOC_MODULES_HTML@ DOC_SECTIONS = @DOC_SECTIONS@ DOC_SECTIONS_XML = @DOC_SECTIONS_XML@ DOC_SECTIONS_XML_PATH = @DOC_SECTIONS_XML_PATH@ DUMMYPOFILES = @DUMMYPOFILES@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FC_CFLAGS = @FC_CFLAGS@ FC_CONFIG = @FC_CONFIG@ FC_LIBS = @FC_LIBS@ FRIBIDI_CONFIG = @FRIBIDI_CONFIG@ FVWMALTFTP = @FVWMALTFTP@ FVWMALTFTPDIR = @FVWMALTFTPDIR@ FVWMFTP = @FVWMFTP@ FVWMFTPDIR = @FVWMFTPDIR@ FVWMHOMEPAGE = @FVWMHOMEPAGE@ FVWMLIST = @FVWMLIST@ FVWMNAMELONG = @FVWMNAMELONG@ FVWMSCRIPT_DOMAIN = @FVWMSCRIPT_DOMAIN@ FVWMTASKBAR_DOMAIN = @FVWMTASKBAR_DOMAIN@ FVWMWORKERSLIST = @FVWMWORKERSLIST@ FVWMWORKERSLISTLONG = @FVWMWORKERSLISTLONG@ FVWM_CONFDIR = @FVWM_CONFDIR@ FVWM_CPP = @FVWM_CPP@ FVWM_DATADIR = @FVWM_DATADIR@ FVWM_DOCDIR = @FVWM_DOCDIR@ FVWM_DOMAIN = @FVWM_DOMAIN@ FVWM_IMAGEPATH = @FVWM_IMAGEPATH@ FVWM_MODULEDIR = @FVWM_MODULEDIR@ FVWM_PERLLIB = @FVWM_PERLLIB@ FVWM_PERLLIBDIR = @FVWM_PERLLIBDIR@ GDK_IMLIB_CFLAGS = @GDK_IMLIB_CFLAGS@ GDK_IMLIB_LIBS = @GDK_IMLIB_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ IMLIBCONF = @IMLIBCONF@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INST_LINGUAS = @INST_LINGUAS@ ISRELEASED = @ISRELEASED@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOCALEDIR = @LOCALEDIR@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANPAGE_PREAMBLE = @MANPAGE_PREAMBLE@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ MSGUNIQ = @MSGUNIQ@ OBJEXT = @OBJEXT@ 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@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PYTHON = @PYTHON@ RANLIB = @RANLIB@ RELDATELONG = @RELDATELONG@ RELDATENUM = @RELDATENUM@ RELDATESHORT = @RELDATESHORT@ REQUIRED_PERL_VERSION = @REQUIRED_PERL_VERSION@ REQUIRED_PYTHON_VERSION = @REQUIRED_PYTHON_VERSION@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ UPDATEPOFILES = @UPDATEPOFILES@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VERSIONINFO = @VERSIONINFO@ XFT_CFLAGS = @XFT_CFLAGS@ XFT_CONFIG = @XFT_CONFIG@ XFT_LIBS = @XFT_LIBS@ XGETTEXT = @XGETTEXT@ XMKMF = @XMKMF@ XSLTPROC = @XSLTPROC@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Xcursor_CFLAGS = @Xcursor_CFLAGS@ Xcursor_LIBS = @Xcursor_LIBS@ Xft_CFLAGS = @Xft_CFLAGS@ Xft_LIBS = @Xft_LIBS@ Xinerama_CFLAGS = @Xinerama_CFLAGS@ Xinerama_LIBS = @Xinerama_LIBS@ Xrender_CFLAGS = @Xrender_CFLAGS@ Xrender_LIBS = @Xrender_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ iconv_CFLAGS = @iconv_CFLAGS@ iconv_LIBS = @iconv_LIBS@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intl_CFLAGS = @intl_CFLAGS@ intl_LIBS = @intl_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ png_CFLAGS = @png_CFLAGS@ png_LIBS = @png_LIBS@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ readline_CFLAGS = @readline_CFLAGS@ readline_LIBS = @readline_LIBS@ rplay_CFLAGS = @rplay_CFLAGS@ rplay_LIBS = @rplay_LIBS@ rsvg_CFLAGS = @rsvg_CFLAGS@ rsvg_LIBS = @rsvg_LIBS@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ stroke_CFLAGS = @stroke_CFLAGS@ stroke_LIBS = @stroke_LIBS@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ with_bidi = @with_bidi@ with_gdkimlib = @with_gdkimlib@ with_gettext = @with_gettext@ with_iconv = @with_iconv@ with_perllib = @with_perllib@ with_png = @with_png@ with_readline = @with_readline@ with_rplay = @with_rplay@ with_rsvg = @with_rsvg@ with_shape = @with_shape@ with_shm = @with_shm@ with_sm = @with_sm@ with_stroke = @with_stroke@ with_xcursor = @with_xcursor@ with_xft = @with_xft@ with_xinerama = @with_xinerama@ with_xpm = @with_xpm@ with_xrender = @with_xrender@ xpm_CFLAGS = @xpm_CFLAGS@ xpm_LIBS = @xpm_LIBS@ EXTRA_DIST = COMMANDS DEVELOPERS.md PARSING.md all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(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) --foreign docs/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign docs/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: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): 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 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 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-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 pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic cscopelist-am \ ctags-am distclean distclean-generic 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-generic pdf \ pdf-am ps ps-am 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: �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/docs/DEVELOPERS.md�����������������������������������������������������������������������0000644�0001750�0001750�00000022153�14147024700�012344� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!--- IF THIS DOCUMENT IS UPDATED THEN ALSO UPDATE THE FVWM WEB REPO ---> Developing for FVWM =================== This document aims to help the developer with the expectations when dealing with the FVWM source code. The FVWM source conforms to the [Linux kernel style guide](https://www.kernel.org/doc/Documentation/CodingStyle). Command Parsing =============== The internal representation of how fvwm parses commands in undergoing a rewrite. [Some notes on how fvwm parses commands exists](PARSING.md). Branch Workflows / Submitting Code Changes ========================================== The main FVWM repository treats the `master` branch as stable, in that it's the branch which has the most tested code on it, and the branch from which releases are made. Formal releases of FVWM are tagged, in the form `x.y.z`, historical versions of FVWM are tagged as `version-x_y_z`. Untagged code may well accumulate on `master`, which will go to form the next release. Other branches in the repository will reflect on-going development from core fvwm-workers. As such, these branches are often in a state of flux, and likely to be rebased against other branches. *NO* code should be based off topic branches, unless explicitly agreed with other developers, who might need to collaborate. ### Branch naming Branch names are used to try and indicate the feature, and who is working on them. So for example, a topic-branch will be named as: `initials/rough-description-of-branch` For example: `ta/fix-clang-warnings` denotes that the branch is worked on by someone with the initials `TA` and that the branch is about fixing warnings from Clang. Sometimes, if more than one person is collaborating on a branch, the initials prefix might not be needed. ### Updating NEWS When submitting patches, please also update the NEWS file with relevant highlights as to new functionality and/or bug-fixes. For inspiration, GNU have a [list](https://www.gnu.org/prep/standards/standards.txt). ### Submitting Pull-requests External contributions are always welcomed and encouraged. If you're thinking of writing a new feature, it is worthwhile posting an email to the `fvwm-workers` mailing list to discuss whether it's a good idea, and to check no one else is working on that feature. Those wishing to submit code/bug-fixes should: * [Fork the FVWM-repository](https://github.com/fvwmorg/fvwm#fork-destination-box) * Add the [FVWM-repo](https://github.com/fvwmorg/fvwm.git) as an upstream remote: * `git remote add fvwmorg https://github.com/fvwmorg/fvwm.git && git fetch fvwmorg` * Create a topic-branch to house your work; * Rebase it against `fvwmorg/master` * Push the latest changes to your fork; * Open a pull-request Once a pull-request is opened, an email is sent to the `fvwm-workers` list so we can take a look at it. Alternatively, if pull-requests are not an option, then `git-send-email` can be used, sending the relevant patchsets to the `fvwm-workers` mailing list. ### Protected branches and the use of Travis-CI Pull-requests made will result in the use of Travis-CI being run against the branch. This builds the copy of the pushed code in a Ubuntu environment, with all the additional libraries FVWM could use, loaded in. Builds are made against `gcc` and `clang`, because both those compilers cover slightly different angles with respect to compiling. All warnings are treated as errors, and if a build does not succeeded, ensure the code is fixed, and pushed back out on the same branch. Rebasing is recommended; Travis-CI and Github handle this just fine. The FVWM repository also treats the `master` branch as protected. This is a [GitHub feature](https://help.github.com/articles/about-protected-branches/) which means the `master` branch in this case cannot have changes merged into it until Travis-CI has verified the builds do not fail. This has merit since not every developer will be using the same operating systems (Linux versus BSD for instance), and that `master` is meant to try and be as release-worthy as can be. **NOTE**: This means that no work can be commited to `master` directly. ALL work that needs to appear on `master`---including the release process---**MUST** go via a separate topic-branch, with a PR (pull-request). Not even fvwmorg owners are an exception to this. ### Merging changes / Pull Requests The history of `master` should be as linear as possible, therefore when merging changes to it the branch(es) in question should be rebased against master first of all. This will stop a merge commit from happening. If using github this process is easy, since the `Merge pull request` button has an option to `Rebase and Merge`. This is what should be used. See also [the documentation on Github](https://github.com/blog/2243-rebase-and-merge-pull-requests) If this is manual (which will only work when the Travis-CI checks have passed), then: ``` git checkout topic/branch git rebase origin/master git checkout master git merge topic/branch git push ``` Conventions ========== The following tries to list all the conventions that the fvwm developers adhere to, either by consensus through discussion, common practice or unspoken agreement. It is hopefully useful for the fvwm development newbie. Programming Languages -------------------- The following programming languages are allowed: - ANSI C - Perl - Portable /bin/sh scripts for examples. New Code Files -------------- - There are templates for new code files in the fvwm directory. Try to always use them as they provide a clean structure of the header and code files. Please honour the section titles. For example, put all static functions (and only static functions) under the "local functions" section. - All .c files *must* have ``` #include "config.h" ``` as the first non-comment line. Otherwise the settings made by the configure script may not be used. This can cause random problems. File Names ---------- - The names of the code files in the fvwm directory are in lower case. - Files in the libs directory may begin with a capital 'F'. This letter is reserved for wrapper files for third party libraries or modules. For example, FShape is an abstraction of the XShape X server extension and FBidi is a wrapper for the fribidi library. Do not use the 'F' for other purposes. Copyright Notices ----------------- - A copy of the GPL should be at the beginning of all code files (.c) and scripts, but not at the beginning of header files (.h). Maintaining Man Pages --------------------- - Every feature must be described with all options in the man page. Creating a release ================== Before deciding to make a new release, please check with the `fvwm-workers` mailing list that this is the right time to do so. This will give adequate warning for other developers to give status updates about any in-flight development that's happening which might impact a potential release. Make sure you have all optional libraries installed. **NOTE: as `master` is a protected branch, changes made to files during the release phase must be done on a separate branch, and not on master directly, as pushes to this branch are not allowed until checks have been done on it. This means the end result of the release-phase must have these changes issued as a pull-request against `master`.** 0. `git checkout master && git pull && git checkout -b release/x.y.z` **Where: `x.y.z` will be the next release**. 1. Change the dates in configure.ac and fill in the release dates. 2. Set `ISRELEASED` to `"yes"`. 3. Change `utils/fvwm-version-str.sh` and include the approrpiate version string. 4. Commit the results. 5. Run: `./autogen.sh && make clean` to get the tree into a clean slate. Because this is a release, the source needs compiling. To do that, run: ``` make CFLAGS="-g -O2 -Wall -Wpointer-arith -fno-strict-aliasing -Werror" ``` Fix all warnings and problems, commit the changes and repeat the previous command until no more warnings occur. 6. Tag the release: `git tag -a x.y.z` -- where `x.y.z` represents the appropriate version number for the release. 7. Build and test the release tarballs: Run: `make dist` If that succeeds, check for `fvwm-x.y.z.tar.gz` in the current working directory. This is the release tarball which will be uploaded to Github. Unpack it to a temporary directory and build it; check the version as well, via: `./fvwm --version`. 8. Push the tag out: `git push origin x.y.z` -- where `x.y.z` is the specific tag created in step 6. 9. Set `ISRELEASED` to `"no"` in configure.ac and commit and push that out. 10. Issue a PR (pull-request) against `master` and mege that in assuming all checks pass. If not, fix the problems, and repeat this step. 11. Upload the `fvwm-x.y.z.tar.gz` tarball to Github against the tag just pushed. 12. Update the fvwm web site (see below) Updating fvwm-web ================= 1. Ensure you've a checkout of the repository: ``` git clone git@github.com:fvwmorg/fvwmorg.github.io.git ``` 2. Update the `RELEASE` variable in `Makefile` to the desired version which has been released. 3. Run `make`. This will update all relevant files. 4. `git commit -a` the result, and push it out. ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/docs/COMMANDS����������������������������������������������������������������������������0000644�0001750�0001750�00000030741�14147024700�011500� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������The recognized commands for fvwm 2.6.6 (from cvs) as of 09-Sep-2014: # - Comment line (ignored) * - Module configuration line (no space after asterisk) + - Continue the last AddToFunc, AddToMenu or AddToDecor AddButtonStyle - Add to a button style (see ButtonStyle) AddTitleStyle - Add to a title style (see TitleStyle) AddToDecor - Add a decor definition (will be obsolete) AddToFunc - Add a function definition AddToMenu - Add a menu definition All - Operate on all windows matching the given condition AnimatedMove - Like Move, but uses animation to move windows Any - Operate if there is any window matching the condition Beep - Produce a bell BorderStyle - Define a window border look (will be reworked) Break - Stop executing the current (but not parent) function BugOpts - Set some application bug workarounds BusyCursor - Show/don't show the wait cursor in certain operations ButtonState - Disable some titlebar button states (not recommended) ButtonStyle - Define a window button look (will be reworked) ChangeDecor - Attach decor to a window (will be obsolete) ChangeMenuStyle - Attach menu style to a menu (see MenuStyle) CleanupColorsets - Reset all used colorsets with the default gray colors ClickTime - Set a time in milliseconds for click and double click Close - Try to Delete a window, if this fails, Destroy it ColorLimit - Set limit on colors used (obsolete) ColormapFocus - Change the colormap behaviour for low-depth X servers Colorset - Manage colors used like fg, bg, image bg, gradient bg CopyMenuStyle - Copy the existing menu style to new or existing one Current - Operate on the currently focused window CursorMove - Move the cursor pointer non interactively CursorStyle - Define different cursor pointer shapes and colors DefaultColors - Set colors for the feedback window (will be obsolete) DefaultColorset - Set colors for the Move/Resize feedback window DefaultFont - The default font to use (mainly for feedback window) DefaultIcon - The default icon to use for iconified windows DefaultLayers - Set StaysOnBottom, StaysPut, StaysOnTop layer numbers Delete - Try to delete a window using the X delete protocol Deschedule - Remove commands sheduled earlier using Schedule Desk - (obsolete, use GotoDesk instead) DesktopName - Define the desktop names used in WindowList, modules DesktopSize - Set virtual desktop size in units of physical pages Destroy - Kill a window without any warning to an application DestroyDecor - Delete decor defined by AddToDecor (will be obsolete) DestroyFunc - Delete function defined using AddToFunc DestroyMenu - Delete menu defined using AddToMenu DestroyMenuStyle - Delete menu style defined using MenuStyle DestroyModuleConfig - Delete matching module config lines defined using "*" DestroyStyle - Delete style defined using Style DestroyWindowStyle - Delete style defined using WindowStyle Direction - Operate on the next window in the specified direction Echo - Print message to stderr, mainly for debugging EchoFuncDefinition - Print the definion of a function EdgeCommand - Bind one or another screen edge to an fvwm action EdgeLeaveCommand - Bind one or another screen edge to an fvwm action EdgeResistance - Control viewport scrolling and window move over edge EdgeScroll - Control how much of the viewport is scrolled if any EdgeThickness - Control how closely to edge to run command/scrolling Emulate - Only used to position the position/size window EscapeFunc - Abort a wait or ModuleSynchonous command EwmhBaseStruts - Define restricted areas of the screen EwmhNumberOfDesktops - For ewmh pager, define number of desktops Exec - Execute an external command ExecUseShell - The shell to use to execute an external command FakeClick - Generate a mouse click FakeKeypress - Send a keyboard event to a window FlipFocus - Focus a window without rotating windowlist order Focus - Give focus to a window FocusStyle - Configure focus and raise policy for windows Function - Execute a user defined function, see AddToFunc GlobalOpts - (obsolete, use corresponding Style * instead) GnomeButton - Pass mouse button presses on root to GNOME program GnomeShowDesks - Limit GNOME pager to the number of desks GotoDesk - Switch viewport to another desk same page GotoDeskAndPage - Switch viewport to another desk and page GotoPage - Switch viewport to another page same desk HideGeometryWindow - Hide/show the position/size window HilightColor - (obsolete, use Style * HighlightFore/Back) HilightColorset - (obsolete, use Style * HighlightColorset) IconFont - (obsolete, use Style * IconFont) Iconify - Change iconification status of a window (minimize) IconPath - (obsolete, use ImagePath instead) IgnoreModifiers - Modifiers to ignore on mouse and key bindings ImagePath - Directories to search for images InfoStoreAdd - Adds an entry (key/value pairs) to the infostore InfoStoreRemove - Removes an entry from the infostore - KeepRc - Do not modify the previous command return code Key - Bind or unbind a key to an fvwm action KillModule - Stops an fvwm module Layer - Change the layer of a window LocalePath - Directories/domains to search for locale data Lower - Lower a window within a layer Maximize - Toggle maximal-size status of a window Menu - Display (post) a menu MenuStyle - Control appearance and behavior of a menu Module - Invoke an fvwm module ModuleListenOnly - Invoke an fvwm module ModulePath - Modify the directories to search for an fvwm module ModuleSynchronous - Invoke an fvwm module synchronously ModuleTimeout - Set timeout value for response from module Mouse - Bind or unbind a mouse button press to an fvwm action Move - Move a window MoveThreshold - Set number of pixels in a click and a hold vs. a drag MoveToDesk - Move a window to another desk same page MoveToPage - Move a window to another page same desk MoveToScreen - Move a window to another Xinerama screen Next - Operate on the next window matching conditions None - Perform command if no window matches conditions Nop - Do nothing (used internally) NoWindow - Prefix that runs a command without a window context OpaqueMoveSize - Set maximum size window fvwm should move opaquely Pick - Prefix to force a window context, prompted if needed PipeRead - Exec system command interpret output as fvwm commands PixmapPath - (obsolete, use ImagePath instead) PlaceAgain - Replace a window using initial window placement logic PointerKey - Bind an action to a key based on pointer not focus PointerWindow - Operate on window under pointer if it meets conditions Popup - Display (pop-up) a menu, see also Menu Prev - Operate on the precious window matching conditions PrintInfo - Print information about the state of fvwm PropertyChange - Internal, used for inter-module communication Quit - Exit fvwm QuitScreen - Stop managing the specified screen QuitSession - Ask session manager to shut down itself and fvwm Raise - Raise a window in a layer RaiseLower - Alternately raise or lower a window in a layer Read - Read fvwm commands from a file ReadWriteColors - Used for colorset speed hacks (will be removed?) Recapture - Reapply styles to all windows (will be obsolete) RecaptureWindow - Reapply styles to one window (will be obsolete) Refresh - Cause all windows to redraw themselves RefreshWindow - Cause one window to redraw itself Repeat - Repeat (very unreliably) the last command, don't use Resize - Cause a window to be resized ResizeMaximize - Resize a window and mark window as maximized ResizeMove - Resize and move in one operation ResizeMoveMaximize - Resize and move in one operation and mark maximized RestackTransients - Regroup the window transients in the stack Restart - Restart itself or replace with another window manager SaveQuitSession - Cause session manager to save and shutdown fvwm SaveSession - Cause session manager to save the session ScanForWindow - Operate on the matching window in the given direction Schedule - Run an fvwm command after a delay Scroll - Scroll the desktop viewport Send_ConfigInfo - Internal, used for module communication Send_Reply - Internal, used for module communication Send_WindowList - Internal, used for module communication SendToModule - Send a string (action) to a module set_mask - Internal, used for module communication set_nograb_mask - Internal, used for module communication set_sync_mask - Internal, used for module communication SetAnimation - Control animated moves and menus SetEnv - Set an environment variable Silent - Suppress errors on command, avoid window selection SnapAttraction - Control attraction of windows during move SnapGrid - Control grid used with SnapAttraction State - Control user defined window states Stick - Change window stickyness StickAcrossDesks - Change window stickyness on a desk basis StickAcrossPages - Change window stickyness on a page basis Stroke - Bind a stroke to an fvwm action StrokeFunc - Record stroke and execute corresponding stroke action Style - Set attributes of windows that match a pattern TearMenuOff - Convert a menu to a window, for use in menu items Test - Execute command if conditions are met TestRc - Conditional switch (may be changed) ThisWindow - Operate on the context window if it meets conditions Title - Insert title into a menu TitleStyle - Control window title UnsetEnv - Remove an environment variable UpdateDecor - Update window decor (obsolete and not needed anymore) UpdateStyles - Cause styles to update while still in a function Wait - Pause until a matching window appears WarpToWindow - Warp the pointer to a window WindowFont - (obsolete, use Style * Font) WindowId - Execute command for window matching the windowid WindowList - Display the window list as a menu to select a window WindowShade - Shade/unshade a window WindowShadeAnimate - (obsolete, use Style * WindowShadeSteps) WindowStyle - Set styles on the selected window Xinerama - Control Xinerama support XineramaPrimaryScreen - Identify Xinerama primary screen XineramaSls - Control single logical screen support XineramaSlsScreens - Configure layout for single logical screen XineramaSlsSize - Configure layout for single logical screen sizes XorPixmap - Use a pixmap for move/resize rubber-band XorValue - Change bits used for move/resize rubber-band XSync - For debugging, send all pending requests to X server XSynchronize - For debugging, cause all X requests to be synchronous �������������������������������fvwm-2.7.0/docs/Makefile.am�������������������������������������������������������������������������0000644�0001750�0001750�00000000207�14147024700�012402� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������## This is a -*- Makefile -*- ## Process this file with automake to create Makefile.in EXTRA_DIST = COMMANDS DEVELOPERS.md PARSING.md �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/doc/�������������������������������������������������������������������������������������0000755�0001750�0001750�00000000000�14324316056�010251� 5����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/doc/Makefile.in��������������������������������������������������������������������������0000644�0001750�0001750�00000057160�14324315775�012256� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 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@ # Author: Scott Smedley 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 = doc ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.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 = fvwm.ent footer.html 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)$(docdir)" DATA = $(doc_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)` DIST_SUBDIRS = commands images docbook-xml docbook-xsl fvwm am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/footer.html.in \ $(srcdir)/fvwm.ent.in README 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" ACLOCAL = @ACLOCAL@ ALL_DOMAINS = @ALL_DOMAINS@ ALL_LINGUAS = @ALL_LINGUAS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR_FLAGS = @AR_FLAGS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ Bidi_CFLAGS = @Bidi_CFLAGS@ Bidi_LIBS = @Bidi_LIBS@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DOC_COMMANDS = @DOC_COMMANDS@ DOC_COMMANDS_HTML = @DOC_COMMANDS_HTML@ DOC_COMMANDS_XML = @DOC_COMMANDS_XML@ DOC_COMMANDS_XML_PATH = @DOC_COMMANDS_XML_PATH@ DOC_MODULES = @DOC_MODULES@ DOC_MODULES_HTML = @DOC_MODULES_HTML@ DOC_SECTIONS = @DOC_SECTIONS@ DOC_SECTIONS_XML = @DOC_SECTIONS_XML@ DOC_SECTIONS_XML_PATH = @DOC_SECTIONS_XML_PATH@ DUMMYPOFILES = @DUMMYPOFILES@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FC_CFLAGS = @FC_CFLAGS@ FC_CONFIG = @FC_CONFIG@ FC_LIBS = @FC_LIBS@ FRIBIDI_CONFIG = @FRIBIDI_CONFIG@ FVWMALTFTP = @FVWMALTFTP@ FVWMALTFTPDIR = @FVWMALTFTPDIR@ FVWMFTP = @FVWMFTP@ FVWMFTPDIR = @FVWMFTPDIR@ FVWMHOMEPAGE = @FVWMHOMEPAGE@ FVWMLIST = @FVWMLIST@ FVWMNAMELONG = @FVWMNAMELONG@ FVWMSCRIPT_DOMAIN = @FVWMSCRIPT_DOMAIN@ FVWMTASKBAR_DOMAIN = @FVWMTASKBAR_DOMAIN@ FVWMWORKERSLIST = @FVWMWORKERSLIST@ FVWMWORKERSLISTLONG = @FVWMWORKERSLISTLONG@ FVWM_CONFDIR = @FVWM_CONFDIR@ FVWM_CPP = @FVWM_CPP@ FVWM_DATADIR = @FVWM_DATADIR@ FVWM_DOCDIR = @FVWM_DOCDIR@ FVWM_DOMAIN = @FVWM_DOMAIN@ FVWM_IMAGEPATH = @FVWM_IMAGEPATH@ FVWM_MODULEDIR = @FVWM_MODULEDIR@ FVWM_PERLLIB = @FVWM_PERLLIB@ FVWM_PERLLIBDIR = @FVWM_PERLLIBDIR@ GDK_IMLIB_CFLAGS = @GDK_IMLIB_CFLAGS@ GDK_IMLIB_LIBS = @GDK_IMLIB_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ IMLIBCONF = @IMLIBCONF@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INST_LINGUAS = @INST_LINGUAS@ ISRELEASED = @ISRELEASED@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOCALEDIR = @LOCALEDIR@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANPAGE_PREAMBLE = @MANPAGE_PREAMBLE@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ MSGUNIQ = @MSGUNIQ@ OBJEXT = @OBJEXT@ 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@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PYTHON = @PYTHON@ RANLIB = @RANLIB@ RELDATELONG = @RELDATELONG@ RELDATENUM = @RELDATENUM@ RELDATESHORT = @RELDATESHORT@ REQUIRED_PERL_VERSION = @REQUIRED_PERL_VERSION@ REQUIRED_PYTHON_VERSION = @REQUIRED_PYTHON_VERSION@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ UPDATEPOFILES = @UPDATEPOFILES@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VERSIONINFO = @VERSIONINFO@ XFT_CFLAGS = @XFT_CFLAGS@ XFT_CONFIG = @XFT_CONFIG@ XFT_LIBS = @XFT_LIBS@ XGETTEXT = @XGETTEXT@ XMKMF = @XMKMF@ XSLTPROC = @XSLTPROC@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Xcursor_CFLAGS = @Xcursor_CFLAGS@ Xcursor_LIBS = @Xcursor_LIBS@ Xft_CFLAGS = @Xft_CFLAGS@ Xft_LIBS = @Xft_LIBS@ Xinerama_CFLAGS = @Xinerama_CFLAGS@ Xinerama_LIBS = @Xinerama_LIBS@ Xrender_CFLAGS = @Xrender_CFLAGS@ Xrender_LIBS = @Xrender_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ 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 = @FVWM_DOCDIR@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ iconv_CFLAGS = @iconv_CFLAGS@ iconv_LIBS = @iconv_LIBS@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intl_CFLAGS = @intl_CFLAGS@ intl_LIBS = @intl_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ png_CFLAGS = @png_CFLAGS@ png_LIBS = @png_LIBS@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ readline_CFLAGS = @readline_CFLAGS@ readline_LIBS = @readline_LIBS@ rplay_CFLAGS = @rplay_CFLAGS@ rplay_LIBS = @rplay_LIBS@ rsvg_CFLAGS = @rsvg_CFLAGS@ rsvg_LIBS = @rsvg_LIBS@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ stroke_CFLAGS = @stroke_CFLAGS@ stroke_LIBS = @stroke_LIBS@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ with_bidi = @with_bidi@ with_gdkimlib = @with_gdkimlib@ with_gettext = @with_gettext@ with_iconv = @with_iconv@ with_perllib = @with_perllib@ with_png = @with_png@ with_readline = @with_readline@ with_rplay = @with_rplay@ with_rsvg = @with_rsvg@ with_shape = @with_shape@ with_shm = @with_shm@ with_sm = @with_sm@ with_stroke = @with_stroke@ with_xcursor = @with_xcursor@ with_xft = @with_xft@ with_xinerama = @with_xinerama@ with_xpm = @with_xpm@ with_xrender = @with_xrender@ xpm_CFLAGS = @xpm_CFLAGS@ xpm_LIBS = @xpm_LIBS@ HTML_FILES = \ index.html allCommands.html groupedCommands.html modules.html style.css EXTRA_DIST = \ fvwm.xsl fvwm-man.xsl header.html $(HTML_FILES) @FVWM_BUILD_HTMLDOC_TRUE@doc_DATA = \ @FVWM_BUILD_HTMLDOC_TRUE@ $(HTML_FILES) @FVWM_BUILD_MANDOC_FALSE@SUBDIRS = commands images docbook-xml docbook-xsl @FVWM_BUILD_MANDOC_TRUE@SUBDIRS = commands images docbook-xml docbook-xsl fvwm all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: $(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) --foreign doc/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign doc/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: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): fvwm.ent: $(top_builddir)/config.status $(srcdir)/fvwm.ent.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ footer.html: $(top_builddir)/config.status $(srcdir)/footer.html.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-docDATA: $(doc_DATA) @$(NORMAL_INSTALL) @list='$(doc_DATA)'; test -n "$(docdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(docdir)" || 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)$(docdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ done uninstall-docDATA: @$(NORMAL_UNINSTALL) @list='$(doc_DATA)'; test -n "$(docdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(docdir)'; $(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)$(docdir)"; 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 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-docDATA 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 pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-docDATA .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic cscopelist-am ctags ctags-am \ distclean distclean-generic distclean-tags distdir dvi dvi-am \ html html-am info info-am install install-am install-data \ install-data-am install-docDATA install-dvi install-dvi-am \ install-exec install-exec-am install-html install-html-am \ install-info install-info-am install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-docDATA .PRECIOUS: Makefile all: $(doc_DATA) # 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: ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/doc/fvwm/��������������������������������������������������������������������������������0000755�0001750�0001750�00000000000�14324316056�011230� 5����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������fvwm-2.7.0/doc/fvwm/scripting.xml�������������������������������������������������������������������0000644�0001750�0001750�00000002653�14147024700�013675� �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE part PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "../docbook-xml/docbookx.dtd" [ <!ENTITY % myents SYSTEM "../fvwm.ent" > %myents; ]> <!-- $Id$ --> <section id='scripting_and_complex_functions'> <title>Scripting & Complex Functions To achieve the more complex effects, fvwm has a number of commands that improve its scripting abilities. Scripts can be read from a file with , from the output of a command with or written as a complex function with the command. For the curious, section 7 of the fvwm FAQ shows some real life applications of scripting. Please refer to the sections and for details. A word of warning: during execution of complex functions, fvwm needs to take all input from the mouse pointer (the pointer is "grabbed" in the slang of X). No other programs can receive any input from the pointer while a function is run. This can confuse some programs. For example, the xwd program refuses to make screen shots when run from a complex function. To achieve the same functionality you can use the or command instead. fvwm-2.7.0/doc/fvwm/quoting.xml0000644000175000017500000000212514147024700013353 00000000000000 %myents; ]>

    Quoting Quotes are required only when needed to make fvwm consider two or more words to be a single argument. Unnecessary quoting is allowed. If you want a quote character in your text, you must escape it by using the backslash character. For example, if you have a pop-up menu called "Window-Ops", then you do not need quotes: Window-Ops but if you replace the dash with a space, then you need quotes: "Window Ops" The supported quoting characters are double quotes, single quotes and reverse single quotes. All three kinds of quotes are treated in the same way. Single characters can be quoted with a preceding backslash. Quoting single characters works even inside other kinds of quotes.
    fvwm-2.7.0/doc/fvwm/bidirText.xml0000644000175000017500000000204414147024700013623 00000000000000 %myents; ]>
    Bi-directional Text Arabic and Hebrew text require bi-directional text support to be displayed correctly, this means that logical strings should be converted before their visual presentation, so left-to-right and right-to-left sub-strings are determined and reshuffled. In fvwm this is done automatically in window titles, menus, module labels and other places if the fonts used for displaying the text are of one of the charsets that require bidi (bi-directional) support. For example, this includes iso8859-6, iso8859-8 and iso10646-1 (unicode), but not other iso8859-* fonts. This bi-directional text support is done using the fribidi library compile time option, see INSTALL.fvwm.
    fvwm-2.7.0/doc/fvwm/booleanArgs.xml0000644000175000017500000000115014147024700014116 00000000000000 %myents; ]>
    Boolean Arguments A number of commands take one or several boolean arguments. These take a few equivalent inputs: "yes", "on", "true", "t" and "y" all evaluate to true while "no", "off", "false", "f" and "n" evaluate to false. Some commands allow "toggle" too which means that the feature is disabled if it is currently enabled and vice versa.
    fvwm-2.7.0/doc/fvwm/authors.xml0000644000175000017500000000101114147024700013343 00000000000000 %myents; ]>
    Authors Robert Nation with help from many people, based on twm code, which was written by Tom LaStrange. After Robert Nation came Charles Hines, followed by Brady Montz. Currently fvwm is developed by a number of people on the fvwm-workers mailing list.
    fvwm-2.7.0/doc/fvwm/multiScreen.xml0000644000175000017500000000141114147024700014154 00000000000000
    Use on Multi-Screen Displays If the command line argument is not given, fvwm automatically starts up on every screen on the specified display. After fvwm starts each screen is treated independently. Restarts of fvwm need to be performed separately on each screen. The use of 0 0 is strongly recommended for multi-screen displays. You may need to quit on each screen to quit from the X session completely. This is not to be confused with Xinerama support.
    fvwm-2.7.0/doc/fvwm/builtinBindings.xml0000644000175000017500000000352614147024700015017 00000000000000 %myents; ]>
    Builtin Key and Mouse Bindings The following commands are built-in to fvwm: Help R A MenuFvwmRoot F1 R A MenuFvwmRoot Tab A M Root c c NoDeskSort Escape A MC 1 R A MenuFvwmRoot 1 T A FuncFvwmRaiseLowerX 1 FS A FuncFvwmRaiseLowerX 2 FST A FuncFvwmRaiseLowerX FuncFvwmRaiseLowerX + I + M $0 + D The Help and F1 keys invoke a built-in menu that fvwm creates. This is primarily for new users that have not created their own configuration file. Either key on the root (background) window pops up an menu to help you get started. The Tab key pressed anywhere with the Meta key (same as the Alt key on PC keyboards) held down pop-ups a window list. Mouse button 1 on the title-bar or side frame can move, raise or lower a window. Mouse button 1 on the window corners can resize, raise or lower a window. You can override or remove these bindings. To remove the window list binding, use this: Tab A M -
    fvwm-2.7.0/doc/fvwm/bindings.xml0000644000175000017500000000166114147024700013466 00000000000000 %myents; ]>
    Mouse, Key & Stroke Bindings
    fvwm-2.7.0/doc/fvwm/Makefile.in0000644000175000017500000005243614324315775013236 00000000000000# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 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@ # Author: Scott Smedley 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 = doc/fvwm ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.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; }; \ } man1dir = $(mandir)/man1 am__installdirs = "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(docdir)" NROFF = nroff MANS = $(man_MANS) DATA = $(doc_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALL_DOMAINS = @ALL_DOMAINS@ ALL_LINGUAS = @ALL_LINGUAS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR_FLAGS = @AR_FLAGS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ Bidi_CFLAGS = @Bidi_CFLAGS@ Bidi_LIBS = @Bidi_LIBS@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DOC_COMMANDS = @DOC_COMMANDS@ DOC_COMMANDS_HTML = @DOC_COMMANDS_HTML@ DOC_COMMANDS_XML = @DOC_COMMANDS_XML@ DOC_COMMANDS_XML_PATH = @DOC_COMMANDS_XML_PATH@ DOC_MODULES = @DOC_MODULES@ DOC_MODULES_HTML = @DOC_MODULES_HTML@ DOC_SECTIONS = @DOC_SECTIONS@ DOC_SECTIONS_XML = @DOC_SECTIONS_XML@ DOC_SECTIONS_XML_PATH = @DOC_SECTIONS_XML_PATH@ DUMMYPOFILES = @DUMMYPOFILES@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FC_CFLAGS = @FC_CFLAGS@ FC_CONFIG = @FC_CONFIG@ FC_LIBS = @FC_LIBS@ FRIBIDI_CONFIG = @FRIBIDI_CONFIG@ FVWMALTFTP = @FVWMALTFTP@ FVWMALTFTPDIR = @FVWMALTFTPDIR@ FVWMFTP = @FVWMFTP@ FVWMFTPDIR = @FVWMFTPDIR@ FVWMHOMEPAGE = @FVWMHOMEPAGE@ FVWMLIST = @FVWMLIST@ FVWMNAMELONG = @FVWMNAMELONG@ FVWMSCRIPT_DOMAIN = @FVWMSCRIPT_DOMAIN@ FVWMTASKBAR_DOMAIN = @FVWMTASKBAR_DOMAIN@ FVWMWORKERSLIST = @FVWMWORKERSLIST@ FVWMWORKERSLISTLONG = @FVWMWORKERSLISTLONG@ FVWM_CONFDIR = @FVWM_CONFDIR@ FVWM_CPP = @FVWM_CPP@ FVWM_DATADIR = @FVWM_DATADIR@ FVWM_DOCDIR = @FVWM_DOCDIR@ FVWM_DOMAIN = @FVWM_DOMAIN@ FVWM_IMAGEPATH = @FVWM_IMAGEPATH@ FVWM_MODULEDIR = @FVWM_MODULEDIR@ FVWM_PERLLIB = @FVWM_PERLLIB@ FVWM_PERLLIBDIR = @FVWM_PERLLIBDIR@ GDK_IMLIB_CFLAGS = @GDK_IMLIB_CFLAGS@ GDK_IMLIB_LIBS = @GDK_IMLIB_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ IMLIBCONF = @IMLIBCONF@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INST_LINGUAS = @INST_LINGUAS@ ISRELEASED = @ISRELEASED@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOCALEDIR = @LOCALEDIR@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANPAGE_PREAMBLE = @MANPAGE_PREAMBLE@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ MSGUNIQ = @MSGUNIQ@ OBJEXT = @OBJEXT@ 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@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PYTHON = @PYTHON@ RANLIB = @RANLIB@ RELDATELONG = @RELDATELONG@ RELDATENUM = @RELDATENUM@ RELDATESHORT = @RELDATESHORT@ REQUIRED_PERL_VERSION = @REQUIRED_PERL_VERSION@ REQUIRED_PYTHON_VERSION = @REQUIRED_PYTHON_VERSION@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ UPDATEPOFILES = @UPDATEPOFILES@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VERSIONINFO = @VERSIONINFO@ XFT_CFLAGS = @XFT_CFLAGS@ XFT_CONFIG = @XFT_CONFIG@ XFT_LIBS = @XFT_LIBS@ XGETTEXT = @XGETTEXT@ XMKMF = @XMKMF@ XSLTPROC = @XSLTPROC@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Xcursor_CFLAGS = @Xcursor_CFLAGS@ Xcursor_LIBS = @Xcursor_LIBS@ Xft_CFLAGS = @Xft_CFLAGS@ Xft_LIBS = @Xft_LIBS@ Xinerama_CFLAGS = @Xinerama_CFLAGS@ Xinerama_LIBS = @Xinerama_LIBS@ Xrender_CFLAGS = @Xrender_CFLAGS@ Xrender_LIBS = @Xrender_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ 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 = @FVWM_DOCDIR@/fvwm dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ iconv_CFLAGS = @iconv_CFLAGS@ iconv_LIBS = @iconv_LIBS@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intl_CFLAGS = @intl_CFLAGS@ intl_LIBS = @intl_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ png_CFLAGS = @png_CFLAGS@ png_LIBS = @png_LIBS@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ readline_CFLAGS = @readline_CFLAGS@ readline_LIBS = @readline_LIBS@ rplay_CFLAGS = @rplay_CFLAGS@ rplay_LIBS = @rplay_LIBS@ rsvg_CFLAGS = @rsvg_CFLAGS@ rsvg_LIBS = @rsvg_LIBS@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ stroke_CFLAGS = @stroke_CFLAGS@ stroke_LIBS = @stroke_LIBS@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ with_bidi = @with_bidi@ with_gdkimlib = @with_gdkimlib@ with_gettext = @with_gettext@ with_iconv = @with_iconv@ with_perllib = @with_perllib@ with_png = @with_png@ with_readline = @with_readline@ with_rplay = @with_rplay@ with_rsvg = @with_rsvg@ with_shape = @with_shape@ with_shm = @with_shm@ with_sm = @with_sm@ with_stroke = @with_stroke@ with_xcursor = @with_xcursor@ with_xft = @with_xft@ with_xinerama = @with_xinerama@ with_xpm = @with_xpm@ with_xrender = @with_xrender@ xpm_CFLAGS = @xpm_CFLAGS@ xpm_LIBS = @xpm_LIBS@ XSL_FILE = $(srcdir)/../fvwm.xsl XSL_MAN_FILE = $(srcdir)/../fvwm-man.xsl XSL_PROFILE = $(srcdir)/../docbook-xsl/profiling/profile.xsl HTML_FILES = fvwm.man.html XML_FILES = @DOC_SECTIONS_XML_PATH@ EXTRA_DIST = @DOC_SECTIONS_XML@ $(man_MANS) sections man_MANS = fvwm.1 @FVWM_BUILD_HTMLDOC_TRUE@doc_DATA = $(HTML_FILES) @FVWM_BUILD_HTMLDOC_FALSE@BUILD_HTML_FILES = @FVWM_BUILD_HTMLDOC_TRUE@BUILD_HTML_FILES = $(HTML_FILES) @FVWM_BUILD_MANDOC_FALSE@BUILD_MANS = @FVWM_BUILD_MANDOC_TRUE@BUILD_MANS = $(man_MANS) # mv fvwm.1 fvwm.1.pre # tbl fvwm.1.pre | sed '/^\.T[SE]$$/d' > fvwm.1 && rm fvwm.1.pre fvwm_name = `echo "fvwm" | "$(SED)" -e "${transform}"` fvwm2_name = `echo "fvwm2" | "$(SED)" -e "${transform}"` all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(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) --foreign doc/fvwm/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign doc/fvwm/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: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-man1: $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(man_MANS)'; \ test -n "$(man1dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.1[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ done; } uninstall-man1: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man1dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.1[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) install-docDATA: $(doc_DATA) @$(NORMAL_INSTALL) @list='$(doc_DATA)'; test -n "$(docdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(docdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(docdir)" || 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)$(docdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(docdir)" || exit $$?; \ done uninstall-docDATA: @$(NORMAL_UNINSTALL) @list='$(doc_DATA)'; test -n "$(docdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(docdir)'; $(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 $(MANS) $(DATA) installdirs: for dir in "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(docdir)"; 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-am: clean-generic mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic distclean-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-data-local install-docDATA install-man 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-man1 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 pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-docDATA uninstall-local uninstall-man uninstall-man: uninstall-man1 .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic cscopelist-am \ ctags-am distclean distclean-generic distclean-local distdir \ dvi dvi-am html html-am info info-am install install-am \ install-data install-data-am install-data-local \ install-docDATA install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am install-info \ install-info-am install-man install-man1 install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ pdf-am ps ps-am tags-am uninstall uninstall-am \ uninstall-docDATA uninstall-local uninstall-man uninstall-man1 .PRECIOUS: Makefile all: $(BUILD_HTML_FILES) $(BUILD_MANS) clean: rm -f $(BUILD_HTML_FILES) $(BUILD_MANS) distclean-local: clean @FVWM_BUILD_MANDOC_TRUE@fvwm.man.html: $(XML_FILES) $(XSL_FILE) $(top_builddir)/doc/fvwm.ent @DOC_COMMANDS_XML_PATH@ $(srcdir)/../header.html @FVWM_BUILD_MANDOC_TRUE@ $(XSLTPROC) --path "$(top_builddir)/doc":"$(top_srcdir)/doc/commands" \ @FVWM_BUILD_MANDOC_TRUE@ --xinclude \ @FVWM_BUILD_MANDOC_TRUE@ --stringparam profile.attribute output \ @FVWM_BUILD_MANDOC_TRUE@ --stringparam profile.value html \ @FVWM_BUILD_MANDOC_TRUE@ -o fvwm.man.html.tmp \ @FVWM_BUILD_MANDOC_TRUE@ $(XSL_PROFILE) "$(srcdir)/fvwm.man.xml" @FVWM_BUILD_MANDOC_TRUE@ $(XSLTPROC) --path "$(top_builddir)/doc":"$(top_srcdir)/doc/commands" \ @FVWM_BUILD_MANDOC_TRUE@ --xinclude \ @FVWM_BUILD_MANDOC_TRUE@ --stringparam html.stylesheet "../style.css" \ @FVWM_BUILD_MANDOC_TRUE@ --stringparam header.file "$(srcdir)/../header.html" \ @FVWM_BUILD_MANDOC_TRUE@ --stringparam twdt 1 \ @FVWM_BUILD_MANDOC_TRUE@ --stringparam section.autolabel 1 \ @FVWM_BUILD_MANDOC_TRUE@ -o $@ $(XSL_FILE) fvwm.man.html.tmp && rm fvwm.man.html.tmp @FVWM_BUILD_MANDOC_TRUE@fvwm.1: $(XML_FILES) $(srcdir)/fvwm.man.xml $(XSL_MAN_FILE) @DOC_COMMANDS_XML_PATH@ @FVWM_BUILD_MANDOC_TRUE@ $(XSLTPROC) --path "$(top_builddir)/doc":"$(top_srcdir)/doc/commands" \ @FVWM_BUILD_MANDOC_TRUE@ --xinclude \ @FVWM_BUILD_MANDOC_TRUE@ --stringparam profile.attribute output \ @FVWM_BUILD_MANDOC_TRUE@ --stringparam profile.value man \ @FVWM_BUILD_MANDOC_TRUE@ -o fvwm.1.tmp \ @FVWM_BUILD_MANDOC_TRUE@ $(XSL_PROFILE) "$(srcdir)/fvwm.man.xml" @FVWM_BUILD_MANDOC_TRUE@ $(XSLTPROC) --path "$(top_builddir)/doc":"$(top_srcdir)/doc/commands" \ @FVWM_BUILD_MANDOC_TRUE@ --xinclude \ @FVWM_BUILD_MANDOC_TRUE@ $(XSL_MAN_FILE) fvwm.1.tmp && rm fvwm.1.tmp install-data-local: @rm -f "$(DESTDIR)$(mandir)/man1/$(fvwm2_name).1" @$(LN_S) $(fvwm_name).1 "$(DESTDIR)$(mandir)/man1/$(fvwm2_name).1" || \ echo "Minor warning: $(mandir)/man1/$(fvwm2_name).1 symlink was not created" uninstall-local: @rm -f "$(DESTDIR)$(mandir)/man1/$(fvwm2_name).1" # 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: fvwm-2.7.0/doc/fvwm/images.xml0000644000175000017500000002636714147024700013150 00000000000000 %myents; ]>
    Icons and Images Fvwm can load .xbm, .xpm, .png and .svg images. XBM images are monochrome. Fvwm can always display XBM files. XPM and PNG formats are color images. SVG is a vector graphics image format. Compile-time options determine whether fvwm can display XPM, PNG or SVG icons and images. See the INSTALL.fvwm file for more information. The related SHAPE compile-time option can make fvwm display spiffy shaped icons.
    SVG rendering options SVG images are generated from (XML) text files. A really simple SVG file might look something like this: <svg width="120" height="80"> <rect fill="red" width="40" height="40" x="0" y="0" /> <rect fill="lime" width="40" height="40" x="40" y="0" /> <rect fill="blue" width="40" height="40" x="80" y="0" /> <rect fill="cyan" width="40" height="40" x="0" y="40" /> <rect fill="magenta" width="40" height="40" x="40" y="40" /> <rect fill="yellow" width="40" height="40" x="80" y="40" /> </svg> image.svg By default, SVG images are rendered as the image creator intended them to. But since SVG is a vector graphics format, the images can be rendered at any chosen size and rotation, e.g. making it possible to use the same icon file rendered at different sizes for the and styles. The rendering options are specified as a string appended to the SVG filename as follows: image.svg:!sizepositionrotationscale -widthx-height-+xpos-+ypos@-angle*/-factorxy The option string always starts with a colon (':') to separate it from the filename. An empty option string can skip this colon, but it might still be a good idea to include it to prevent ambiguity if the filename contains any colon. filename_without_colon.svg filename:with:colon.svg: An exclamation point ('!') transposes the entire final image (including the rendering area), i.e. all the horizontal and all the vertical coordinates are swapped with each other. image.svg:! image.svg:! width and height specifies the dimensions of the rendering area in pixels, i.e. the dimensions of the resulting image. The actual image is fitted to fill the entire rendering area. image.svg:60x60 image.svg:60x60 Use a width or height value of 0 to keep the aspect ratio. image.svg:0x60 image.svg:60x0 image.svg:0x60 image.svg:60x0 A '-' before width mirrors the rendering area horizontally. image.svg:-0x0 A '-' before height mirrors the rendering area vertically. image.svg:0x-0 image.svg:0x-0 xpos and ypos specifies a translation of the image in pixels. A positive xpos value moves the image to the right. A positive ypos value moves it down. Moving it partially outside of the rendering area results in a cropped image. image.svg:-30-0 image.svg:-0+10 image.svg:-30+10 image.svg:-30+10 angle specifies a rotation around the actual image center in degrees. This might result in a cropped image. A positive value rotates the image clockwise. Floating point values are recognized. image.svg:@180 image.svg:@-90 image.svg:@30 image.svg:@57.3 image.svg:@30 factor specifes a scaling of the actual image (not the rendering area). Scaling it up results in a cropped image. Floating point values are recognized. Division by zero is ignored. If factor is directly followed by a 'x' or a 'y', the scaling is horizontal or vertical respectively. Otherwise the scaling is uniform. image.svg:*2 image.svg:/2 image.svg:/3x image.svg:/2y image.svg:*2 image.svg:/2 image.svg:/2y Scaling down a translated or rotated image can prevent cropping. image.svg:@30*0.6 image.svg:@30*0.6 Repeated usage of translation, rotation, and scaling is allowed. Translation and rotation are additive. Scaling is multiplicative. image.svg:*2/3 image.svg:/3x/2y image.svg:/3x/2y When combining affine transformations, the scaling is always done first, then the rotation, and finally the translation. image.svg:-30+10@30/3x/2y image.svg:-30+10@30/3x/2y Use a negative scale factor to mirror the actual image. image.svg:-30+10@30/-3x/2y image.svg:-30+10@30/-3x/2y Mirroring of the rendering area is done after any scaling, rotation or translation of the image. image.svg:-0x0-30+10@30/3x/2y image.svg:-0x0-30+10@30/3x/2y Transposing is done last of all, after everything else. image.svg:!-0x0-30+10@30/3x/2y image.svg:!-0x0-30+10@30/3x/2y
    fvwm-2.7.0/doc/fvwm/miscCommands.xml0000644000175000017500000000555414147024700014313 00000000000000 %myents; ]>
    Miscellaneous Commands
    fvwm-2.7.0/doc/fvwm/cpp.xml0000644000175000017500000000101214147024700012441 00000000000000 %myents; ]>
    CPP Preprocessing Cpp is the C-language pre-processor. fvwm offers cpp processing which mirrors the m4 pre-processing. To find out about it, re-read the section, but replace "m4" with "cpp".
    fvwm-2.7.0/doc/fvwm/mwm.xml0000644000175000017500000000102714147024700012465 00000000000000 %myents; ]>
    MWM Compatibility Fvwm provides options to emulate Motif Window Manager (Mwm) as well as possible. Please refer to the command as well as to the Mwm specific options of the and commands for details.
    fvwm-2.7.0/doc/fvwm/windowState.xml0000644000175000017500000000256214147024700014202 00000000000000 %myents; ]>
    Window State
    fvwm-2.7.0/doc/fvwm/ewmh.xml0000644000175000017500000000574114147024700012634 00000000000000 %myents; ]>
    Extended Window Manager Hints Fvwm attempts to respect the extended window manager hints (ewmh or EWMH for short) specification: http://www.freedesktop.org/wiki/Standards_2fwm_2dspec and some extensions of this specification. This allows fvwm to work with KDE version >= 2, GNOME version 2 and other applications which respect this specification (any application based on GTK+ version 2). Applications which respect this specification are called ewmh compliant applications. This support is configurable with styles and commands. These styles and commands have EWMH as the prefix (so you can find them easily in this man page). There is a new Context 'D' for the , , and commands. This context is for desktop applications (such as kdesktop and Nautilus desktop). When a compliant taskbar asks fvwm to activate a window (typically when you click on a button which represents a window in such a taskbar), then fvwm calls the complex function EWMHActivateWindowFunc which by default is Iconify Off, Focus and Raise. You can redefine this function. For example: EWMHActivateWindowFunc EWMHActivateWindowFunc I Off + I + I + I 50 50 additionally warps the pointer to the center of the window. The EWMH specification introduces the notion of Working Area. Without ewmh support the Working Area is the full visible screen (or all your screens if you have a multi head setup and you use Xinerama). However, compliant applications (such as a panel) can ask to reserve space at the edge of the screen. If this is the case, the Working Area is your full visible screen minus these reserved spaces. If a panel can be hidden by clicking on a button the Working Area does not change (as you can unhide the panel at any time), but the Dynamic Working Area is updated: the space reserved by the panel is removed (and added again if you pop up the panel). The Dynamic Working Area may be used when fvwm places or maximizes a window. To know if an application reserves space you can type "xprop | grep _NET_WM_STRUT" in a terminal and select the application. If four numbers appear then these numbers define the reserved space as explained in the command.
    fvwm-2.7.0/doc/fvwm/windowMovement.xml0000644000175000017500000000430114147024700014705 00000000000000 %myents; ]>
    Window Movement and Placement
    fvwm-2.7.0/doc/fvwm/commands.xml0000644000175000017500000000714714147024700013477 00000000000000 %myents; ]>
    List of Fvwm Commands The command descriptions below are grouped together in the following sections. The sections are hopefully sorted in order of usefulness to the newcomer.
    fvwm-2.7.0/doc/fvwm/userFunctions.xml0000644000175000017500000000315014147024700014533 00000000000000 %myents; ]>
    User Functions and Shell Commands
    fvwm-2.7.0/doc/fvwm/copyright.xml0000644000175000017500000000076214147024700013702 00000000000000 %myents; ]> fvwm-2.7.0/doc/fvwm/fvwm.10000644000175000017500000144645314324316033012225 00000000000000.\" Title: fvwm .\" Author: .\" Generator: DocBook XSL Stylesheets vsnapshot_6661 .\" Date: 19-Oct-2022 .\" Manual: Fvwm 2.7.0 .\" Source: .\" .TH "FVWM" "1" "19-Oct-2022" "" "Fvwm 2.7.0" .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .SH NAME .PP Fvwm \- F? Virtual Window Manager for X11 .SH SYNOPSIS .HP 5 \fBfvwm\fR [\fB\-c\fR\ \fIconfig\-command\fR] [\fB\-d\fR\ \fIdisplayname\fR] [\fB\-f\fR\ \fIconfig\-file\fR] [\fB\-r\fR] [\fB\-s\fR\ [\fIscreen_num\fR]] [\fB\-V\fR] [\fB\-C\fR\ \fIvisual\-class\fR | \fB\-I\fR\ \fIvisual\-id\fR] [\fB\-l\fR\ \fIcolors\fR\ [\fB\-L\fR]\ [\fB\-A\fR]\ [\fB\-S\fR]\ [\fB\-P\fR]] [\fB\-D\fR] [\fB\-h\fR] [\fB\-i\fR\ \fIclient\-id\fR] [\fB\-F\fR\ \fIstate\-file\fR] [\fB\-\-debug\-stack\-ring\fR] [\fB\-blackout\fR] .SH DESCRIPTION .PP Fvwm is a window manager for X11\. It is designed to minimize memory consumption, provide a 3D look to window frames, and a virtual desktop\. .PP Note that there are several window managers around that have "fvwm" in their name\. In the past, version 2\.x of fvwm was commonly called fvwm2 to distinguish it from the former version 1\.x (fvwm or even fvwm1)\. Since version 1\.x has been replaced by version 2\.x a long time ago we simply call version 2\.x and all versions to come, fvwm, throughout this document, and the executable program is named fvwm\. There is an fvwm offspring called fvwm95, it is mostly a patched version of fvwm\-2\.0\.43\. The main goal of fvwm95 was to supply a Windows 95 like look and feel\. Since then, fvwm has been greatly enhanced and practically all fvwm95 features can be achieved by fvwm\. .PP Fvwm provides both a large \fIvirtual desktop\fR and \fImultiple disjoint desktops\fR which can be used separately or together\. The virtual desktop allows you to pretend that your video screen is really quite large, and you can scroll around within the desktop\. The multiple disjoint desktops allow you to pretend that you really have several screens to work at, but each screen is completely unrelated to the others\. .PP Fvwm provides \fIkeyboard accelerators\fR that allow you to perform most window manager functions, including moving and resizing windows and operating the menus, using keyboard shortcuts\. .PP Fvwm has also overcome the distinction between configuration commands and action commands that most window managers make\. Configuration commands typically set fonts, colors, menu contents, and key and mouse function bindings, while action commands do things like raise and lower windows\. Fvwm makes no such distinction and allows anything to be changed at any time\. .PP Other noteworthy differences between fvwm and other X11 window managers are the introduction of the \fISloppyFocus\fR and \fINeverFocus\fR focus methods\. Focus policy can be separately specified for different window groups\. Windows using \fISloppyFocus\fR acquire focus when the pointer moves into them and retain focus until some other window acquires it\. Such windows do not lose focus when the pointer moves into the root window\. The \fINeverFocus\fR policy is provided for use with windows into which one never types (e\.g\. xclock, oclock, xbiff, xeyes, tuxeyes) \- for example, if a SloppyFocus terminal window has focus, moving the pointer over a NeverFocus decoration window does not deprive the terminal of focus\. .SH OPTIONS .PP These are the command line options that are recognized by fvwm: .PP \fB\-i\fR | \fB\-\-clientid\fR \fIid\fR .RS 4 This option is used when fvwm is started by a session manager\. Should not be used by a user\. .RE .PP \fB\-c\fR | \fB\-\-cmd\fR \fIconfig\-command\fR .RS 4 Causes fvwm to use \fIconfig\-command\fR instead of '\fBRead\fR \fIconfig\fR' (or '\fBRead\fR \fI\.fvwm2rc\fR') as its initialization command\. (Note that up to 10 \fB\-f\fR and \fB\-c\fR parameters can be given, and they are executed in the order specified\.) .sp Any module started by command line arguments is assumed to be a module that sends back config commands\. All command line modules have to quit before fvwm proceeds on to the StartFunction and setting border decorations and styles\. There is a potential deadlock if you start a module other than \fBFvwmCpp\fR/\fBFvwmM4\fR/\fBFvwmPerl\fR but there is a timeout so fvwm eventually gets going\. .sp As an example, starting the pager this way hangs fvwm until the timeout, but the following should work well: .sp .RS 4 .nf fvwm \-c "\fBAddToFunc\fR StartFunction I \fBModule\fR \fBFvwmPager\fR" .fi .RE .RE .PP \fB\-d\fR | \fB\-\-display\fR \fIdisplayname\fR .RS 4 Manage the display called \fIdisplayname\fR instead of the name obtained from the environment variable \fI$DISPLAY\fR\. .RE .PP \fB\-D\fR | \fB\-\-debug\fR .RS 4 Puts X transactions in synchronous mode, which dramatically slows things down, but guarantees that fvwm's internal error messages are correct\. Also causes fvwm to output debug messages while running\. .RE .PP \fB\-f\fR \fIconfig\-file\fR .RS 4 Causes fvwm to read \fIconfig\-file\fR instead of \fI~/\.fvwm/config\fR as its initialization file\. This is equivalent to \-c '\fBRead\fR \fIconfig\-file\fR'\. .RE .PP \fB\-h\fR | \fB\-\-help\fR .RS 4 A short usage description is printed\. .RE .PP \fB\-r\fR | \fB\-\-replace\fR .RS 4 Try to take over from a previously running wm\. This does not work unless the other wm is ICCCM2 2\.0 compliant\. .RE .PP \fB\-F\fR | \fB\-\-restore\fR \fIstate\-file\fR .RS 4 This option is used when fvwm is started by a session manager\. Should not be used by a user\. .RE .PP \fB\-s\fR | \fB\-\-single\-screen\fR [\fIscreen_num\fR] .RS 4 On a multi\-screen display, run fvwm only on the screen named in the \fI$DISPLAY\fR environment variable or provided through the \fB\-d\fR option\. The optional argument \fIscreen_num\fR should be positive or null and override the screen number\. Normally, fvwm attempts to start up on all screens of a multi\-screen display\. .RE .PP \fB\-V\fR | \fB\-\-version\fR .RS 4 Prints the version of fvwm to \fIstderr\fR\. Also prints an information about the compiled in support for readline, rplay, stroke, xpm, png, svg, GNOME hints, EWMH hints, session management, bidirectional text, multibyte characters, xinerama and Xft aa font rendering\. .RE .PP \fB\-C\fR | \fB\-\-visual\fR \fIvisual\-class\fR .RS 4 Causes fvwm to use \fIvisual\-class\fR for the window borders and menus\. \fIvisual\-class\fR can be "StaticGray", "GrayScale", "StaticColor", "PseudoColor", "TrueColor" or "DirectColor"\. .RE .PP \fB\-I\fR | \fB\-\-visualid\fR \fIid\fR .RS 4 Causes fvwm to use \fIid\fR as the visual id for the window borders and menus\. \fIid\fR can be specified as N for decimal or 0xN for hexadecimal\. See man page of xdpyinfo for a list of supported visuals\. .RE .PP \fB\-l\fR | \fB\-\-color\-limit\fR \fIlimit\fR .RS 4 Specifies a \fIlimit\fR on the colors used in image, gradient and possibly simple colors used by fvwm\. In fact, fvwm (and all the modules) uses a palette with at most \fIlimit\fR colors\. This option is only useful with screens that display 256 colors (or less) with a dynamic visual (PseudoColor, GrayScale or DirectColor)\. The default depends on your X server and how you run fvwm\. In most case this default is reasonable\. The \fB\-l\fR option should be used only if you encounter problems with colors\. By default, fvwm tries to detect large pre\-allocated palettes\. If such a palette is detected fvwm uses it and a priori the \fB\-l\fR must not be used\. Moreover, in this case the \fB\-A\fR and \fB\-S\fR options are forced\. Note that XFree\-4\.2 pre\-allocates 244 colors (if you use a driver with Render support) leaving only a few free colors\. This may lead to some color problems (and nothing can be done)\. XFree\-4\.3 or better pre\-allocate only 85 colors\. If no pre\-allocated palette is auto detected the defaults are as follow: .PP Display depth 8 (256 colors) .RS 4 .nf .IP "" 4 PseudoColor: 68 (4x4x4 color cube + 4 grey) GrayScale: 64 regular grey DirectColor: 32 (3x3x3 color cube + 5 grey) .fi .RE .PP Display depth 4 (16 colors) .RS 4 .nf .IP "" 4 PseudoColor: 10 (2x2x2 color cube + 2 grey) GrayScale: 8 regular grey DirectColor: 10 (2x2x2 color cube + 2 grey) .fi .RE .sp These defaults may change before version 2\.6\. Note that if you use a private color map (i\.e\., fvwm is started with the \fB\-C\fR or the \fB\-I\fR options), then other defaults are used\. .sp Now what to do if you encounter problems with colors? The first thing to do is to check if you really cannot run your X server with depth 15, 16 or better\. Check your X server documentation\. Note that some hardware can support two different depths on the same screen (typically depth 8 and depth 24)\. If depth 8 is the default, you can force fvwm to use the best depth by using the \fB\-C\fR option with \fITrueColor\fR as argument\. So now we assume that you are forced to run in depth 8 with a dynamic visual because your hardware/driver cannot do better or because you need to use an application which needs to run under this mode (e\.g\., because this application needs read\-write colors)\. What it should be understand is that you have only 256 colors and that all the applications which use the default color map must share these colors\. The main problem is that there are applications which use a lot or even all the colors\. If you use such application you may have no more free colors and some applications (which used only a few colors) may fail to start or are unusable\. There are three things that can be done (and fvwm does not really play a particular role, all applications are concerned)\. The first is to run the applications which waste your (default) color map with a private color map\. For example, run netscape with the \-install option, run KDE or QT applications with the \-\-cmap option, use the \fB\-C\fR option for fvwm\. The disadvantage of this method is that it is visually disturbing (see the \fBColormapFocus\fR command for a better control of the color maps switching)\. The second method is to limit the number of colors that the applications use\. Again, some applications have options to specify a given color limit\. With fvwm you may try various values, 61 (a special "visual" palette), 56 (a 4x4x3 color cube plus 6 grey), 29 (a 3x3x3 color cube plus 2 grey), 10 or 9\. Also, you may use the \fB\-L\fR option\. However, limiting the number of colors is not the definitive solution\. The definitive solution is to try cause applications which use a lot of colors use the same colors\. This is a difficult task as there are no formal standards for this goal\. However, some toolkits as QT and GTK use color cubes as palettes\. So, the idea is to configure your applications/toolkits to all use the same color cube\. Moreover, you can use the colors in this color cube in your X resources configuration files and/or as arguments to colors options\. Fvwm can use any color cube of the form RxGxB with 2 <= R <= 6, R = G, R\-1 =< B <= R and B >= 2\. To get an RxGxB color cube give an argument to \fB\-l\fR an integer c >= R*G*B and < (R+1)*(G+1)*B if B=R and < R*G*(B+1) if B < R (and different from 61)\. If c > R*G*B, then some grey may be added to the color cube\. You can use the \fBPrintInfo\fR \fIColors\fR [\fI1\fR] command to get information on your fvwm colors setting\. In particular, this command prints the palette used by fvwm in rgb format (the last integer gives the number of times fvwm has allocated the colors)\. .RE .PP \fB\-L\fR | \fB\-\-strict\-color\-limit\fR .RS 4 If the screen displays 256 colors (or less) and has a dynamic visual, causes fvwm to use its palette for all the colors\. By default, the palette is used only for images and gradients\. .RE .PP \fB\-P\fR | \fB\-\-visual\-palette\fR .RS 4 If the screen displays 256 colors (or less) and has a dynamic visual, this option causes fvwm to use a palette designed for limiting the "visual" color distance between the points of the palette\. Moreover, for better color sharing, if possible colors with a name in the X rgb data base are used for defining the colors (with the hope that applications and images prefer to use named colors)\. If the \fB\-l\fR option is not used this palette has 61 colors\. This palette is also automatically selected if 61 or 9 is used as argument to the \fB\-l\fR option\. .RE .PP \fB\-A\fR | \fB\-\-allocate\-palette\fR .RS 4 If the screen displays 256 colors (or less) and has a dynamic visual this option causes fvwm to allocate all the colors of its palette at start up for reserving these colors for future use\. This option forces the \fB\-static\-palette\fR option\. By default, fvwm allocates (reserves) a color in its palette only if it needs this color\. .RE .PP \fB\-S\fR | \fB\-\-static\-palette\fR .RS 4 If the screen displays 256 colors (or less) and has a dynamic visual this option causes fvwm to never free the colors in its palette\. By default, when fvwm does not need a color any more it frees this color so that a new color can be used\. This option may speed up image loading and save a few bits of memory\. .RE .PP \fB\-blackout\fR .RS 4 This option is provided for backward compatibility only\. Blacking out the screen during startup is not necessary (and doesn't work) anymore\. This option will be removed in the future\. .RE .PP \fB\-\-debug\-stack\-ring\fR .RS 4 Enables stack ring debugging\. This option is only intended for internal debugging and should only be used by developers\. .RE .SH ANATOMY OF A WINDOW .PP Fvwm puts a decorative border around most windows\. This border consists of a bar on each side and a small L\-shaped section on each corner\. There is an additional top bar called the title\-bar which is used to display the name of the window\. In addition, there are up to 10 title\-bar buttons\. The top, side, and bottom bars are collectively known as the side\-bars\. The corner pieces are called the frame\. .PP With the built\-in minimal configuration, dragging mouse button 1 in the frame or side\-bars begins a resize operation on the window\. Dragging mouse button 2 in the frame or side\-bars begins a move operation\. There are raise/lower operations bound to a single clicking on borders\. Similarly for the window title\. .PP Up to ten title\-bar buttons may exist\. Their use is completely user definable\. One popular configuration uses one button on the left that is used to bring up a list of window options and two buttons on the right used to iconify and maximize the window\. Another popular configuration adds a close button to the right\. The number of title\-bar buttons used depends on which ones have mouse actions bound to them\. See the \fBMouse\fR command\. .SH THE VIRTUAL DESKTOP .PP Fvwm provides multiple virtual desktops for users who wish to use them\. The screen is a viewport onto a \fIdesktop\fR which may be larger than the screen\. Several distinct desktops can be accessed (concept: one desktop for each project, or one desktop for each application, when view applications are distinct)\. Since each desktop can be larger than the physical screen, divided into m by n \fIpages\fR which are each the size of the physical screen, windows which are larger than the screen or large groups of related windows can easily be viewed\. .PP The (m by n) size (i\.e\. number of pages) of the virtual desktops can be changed any time, by using the \fBDesktopSize\fR command\. All virtual desktops must be (are) the same size\. The total number of distinct desktops does not need to be specified, but is limited to approximately 4 billion total\. All windows on a range of desktops can be viewed in the \fBFvwmPager\fR, a miniature view of the desktops\. The pager is an accessory program, called a module, which is not essential for the window manager to operate\. Windows may also be listed using the \fBWindowList\fR command or the \fBFvwmIconMan\fR module\. .PP Fvwm keeps the windows on the desktop in a layered stacking order; a window in a lower layer never obscures a window in a higher layer\. The layer of a window can be changed by using the \fBLayer\fR command\. The concept of layers is a generalization of the \fIStaysOnTop\fR flag of older fvwm versions\. The \fIStaysOnTop\fR and \fIStaysPut\fR \fBStyle\fR options are now implemented by putting the windows in suitable layers and the previously missing \fIStaysOnBottom\fR \fBStyle\fR option has been added\. .PP \fISticky\fR windows are windows which transcend the virtual desktop by "Sticking to the screen's glass"\. They always stay put on the screen\. This is convenient for things like clocks and xbiffs, so you only need to run one such gadget and it always stays with you\. Icons can also be made to stick to the glass, if desired\. .PP Window geometries are specified relative to the current viewport\. That is: .sp .RS 4 .nf xterm \-geometry +0+0 .fi .RE .PP .PP creates a window in the upper left hand corner of the visible portion of the screen\. It is permissible to specify geometries which place windows on the virtual desktop, but off the screen\. For example, if the visible screen is 1000 by 1000 pixels, and the desktop size is 3x3, and the current viewport is at the upper left hand corner of the desktop, invoking: .sp .RS 4 .nf xterm \-geometry +1000+1000 .fi .RE .PP .PP places a window just off of the lower right hand corner of the screen\. It can be found by moving the mouse to the lower right hand corner of the screen and waiting for it to scroll into view\. A geometry specified as something like: .sp .RS 4 .nf xterm \-geometry \-5\-5 .fi .RE .PP .PP places the window's lower right hand corner 5 pixels from the lower right corner of the visible portion of the screen\. Not all applications support window geometries with negative offsets\. Some applications place the window's upper right hand corner 5 pixels above and to the left of the upper left hand corner of the screen; others may do just plain bizarre things\. .PP There are several ways to cause a window to map onto a desktop or page other than the currently active one\. The geometry technique mentioned above (specifying x,y coordinates larger than the physical screen size), however, suffers from the limitation of being interpreted relative to the current viewport: the window may not consistently appear on a specific page, unless you always invoke the application from the same page\. .PP A better way to place windows on a different page, screen or desk from the currently mapped viewport is to use the \fIStartsOnPage\fR or \fIStartsOnScreen\fR style specification (the successors to the older \fIStartsOnDesk\fR style) in your \fIconfig\fR file\. The placement is consistent: it does not depend on your current location on the virtual desktop\. .PP Some applications that understand standard Xt command line arguments and X resources, like xterm and xfontsel, allow the user to specify the start\-up desk or page on the command line: .sp .RS 4 .nf xterm \-xrm "*Desk:1" .fi .RE .PP .PP starts an xterm on desk number 1; .sp .RS 4 .nf xterm \-xrm "*Page:3 2 1" .fi .RE .PP .PP starts an xterm two pages to the right and one down from the upper left hand page of desk number 3\. Not all applications understand the use of these options, however\. You could achieve the same results with the following lines in your \fI\.Xdefaults\fR file: .sp .RS 4 .nf XTerm*Desk: 1 .fi .RE .PP .PP or .sp .RS 4 .nf XTerm*Page: 3 2 1 .fi .RE .PP .SH USE ON MULTI\-SCREEN DISPLAYS .PP If the \fB\-s\fR command line argument is not given, fvwm automatically starts up on every screen on the specified display\. After fvwm starts each screen is treated independently\. Restarts of fvwm need to be performed separately on each screen\. The use of .sp .RS 4 .nf \fBEdgeScroll\fR 0 0 .fi .RE .PP is strongly recommended for multi\-screen displays\. You may need to quit on each screen to quit from the X session completely\. This is not to be confused with Xinerama support\. .SH XINERAMA SUPPORT .PP Fvwm supports the Xinerama extension of newer X servers which is similar to multi head support (multiple screens) but allows one to move windows between screens\. If Xinerama support has been compiled into fvwm, it is used whenever fvwm runs on an X server that supports and uses multiple screens via Xinerama\. Without this option, the whole desktop is treated as one big screen\. For example, menus might pop up right between two screens\. The \fIEdgeResistance\fR option of the \fBStyle\fR command command allows for specifying an explicit resistance value for moving windows over the screen edge between two Xinerama screens\. Xinerama support can be enabled or disabled on the fly or from the configuration file with the \fBXinerama\fR command\. Many modules and commands work nicely with Xinerama displays\. .PP Whenever a geometry in the usual X format can be supplied, fvwm's Xinerama extension allows for specifying a screen in addition to the geometry (or even the screen alone)\. To do this, a '@' is added to the end of the geometry string followed by either the screen number or a letter\. A number is taken as the number of the Xinerama screen to be used (as configured in the X server)\. The letter can be one of 'g' for the global screen (the rectangle that encloses all Xinerama screens), 'p' for the primary screen (see below), 'c' for the current screen (the one that currently contains the pointer)\. If the X server does not support Xinerama or only one screen is used, the screen bit is ignored\. .sp .RS 4 .nf \fBStyle\fR * \fIIconBox\fR 64x300\-0\-0@p .fi .RE .PP Xinerama support can be configured to use a primary screen\. Fvwm can be configured to place new windows and icons on this screen\. The primary screen is screen 0 by default but can be changed with the \fBXineramaPrimaryScreen\fR command\. .PP Xinerama support was designed to work out of the box with the same configuration file that would work on a single screen\. It may not perform very well if the involved screens use different screen resolutions\. In this situation, windows may get stuck in the portion of the whole desktop that belongs to neither screen\. When this happens, the windows or icons can be retrieved with the command .sp .RS 4 .nf \fBAll\fR \fBMoveToScreen\fR .fi .RE .PP that can be entered in an \fBFvwmConsole\fR window or with \fBFvwmCommand\fR\. .PP For multi\-screen implementations other than Xinerama, such as Single Logical Screen, it is possible to simulate a Xinerama configuration if the total screen seen by fvwm is made up of equal sized monitors in a rectangular grid\. The commands \fBXineramaSls\fR, \fBXineramaSlsSize\fR and \fBXineramaSlsScreens\fR are used to configure this feature\. .SH INITIALIZATION .PP During initialization, fvwm searches for a configuration file which describes key and button bindings, and many other things\. The format of these files is described later\. Fvwm first searches for configuration files using the command .sp .RS 4 .nf \fBRead\fR \fIconfig\fR .fi .RE .PP This looks for file \fIconfig\fR in \fI$FVWM_USERDIR\fR and \fI$FVWM_DATADIR\fR directories, as described in \fBRead\fR\. If this fails more files are queried for backward compatibility\. Here is the complete list of all file locations queried in the default installation (only the first found file is used): .nf .IP "" 4 \fI$HOME\fR/\.fvwm/config /usr/local/share/fvwm/config .fi .nf .IP "" 4 \fI$HOME\fR/\.fvwm/\.fvwm2rc \fI$HOME\fR/\.fvwm2rc /usr/local/share/fvwm/\.fvwm2rc /usr/local/share/fvwm/system\.fvwm2rc /etc/system\.fvwm2rc .fi .PP Please note, the last 5 locations are not guaranteed to be supported in the future\. .PP If a configuration file is not found, the left mouse button, or .SM Help or .SM F1 keys on the root window bring up menus and forms that can create a starting configuration file\. .PP Fvwm sets two environment variables which are inherited by its children\. These are \fI$DISPLAY\fR which describes the display on which fvwm is running\. \fI$DISPLAY\fR may be \fIunix:0\.0\fR or \fI:0\.0\fR, which doesn't work too well when passed through ssh to another machine, so \fI$HOSTDISPLAY\fR is set to a network\-ready description of the display\. \fI$HOSTDISPLAY\fR always uses the TCP/IP transport protocol (even for a local connection) so \fI$DISPLAY\fR should be used for local connections, as it may use Unix\-domain sockets, which are faster\. .PP If you want to start some applications or modules with fvwm, you can simply put .sp .RS 4 .nf \fBExec\fR app .fi .RE .PP or .sp .RS 4 .nf \fBModule\fR FvwmXxx .fi .RE .PP into your \fIconfig\fR, but it is not recommended; do this only if you know what you are doing\. It is usually important to start applications or modules after the entire config is read, because it contains styles or module configurations which can affect window appearance and functionality\. .PP The standard way to start applications or modules on fvwm's start up is to add them to an initialization function (usually \fBStartFunction\fR or \fBInitFunction\fR)\. This way they are only started after fvwm finishes to read and execute \fIconfig\fR file\. .PP Fvwm has three special functions for initialization: \fBStartFunction\fR, which is executed on startups and restarts; \fBInitFunction\fR and \fBRestartFunction\fR, which are executed during initialization and restarts (respectively) just after StartFunction\. These functions may be customized in a user's \fIconfig\fR file using the \fBAddToFunc\fR command (described later) to start up modules, xterms, or whatever you'd like to have started by fvwm\. .PP Fvwm has also a special exit function: \fBExitFunction\fR, executed when exiting or restarting before actually quitting\. It could be used to explicitly kill modules, etc\. .PP If fvwm is run under a session manager, functions \fBSessionInitFunction\fR and \fBSessionRestartFunction\fR are executed instead of InitFunction and RestartFunction\. This helps to define the user's \fIconfig\fR file to be good for both running under a session manager and without it\. Generally it is a bad idea to start xterms or other applications in "Session*" functions\. Also someone can decide to start different modules while running under a session manager or not\. For the similar purposes \fBSessionExitFunction\fR is used instead of ExitFunction\. .sp .RS 4 .nf \fBDestroyFunc\fR StartFunction \fBAddToFunc\fR StartFunction + I \fBModule\fR \fBFvwmPager\fR * * + I \fBModule\fR \fBFvwmButtons\fR \fBDestroyFunc\fR InitFunction \fBAddToFunc\fR InitFunction + I \fBModule\fR \fBFvwmBanner\fR + I \fBModule\fR \fBFvwmIconMan\fR + I \fBExec\fR xsetroot \-solid cyan + I \fBExec\fR xterm + I \fBExec\fR netscape \fBDestroyFunc\fR RestartFunction \fBAddToFunc\fR RestartFunction + I \fBModule\fR \fBFvwmIconMan\fR \fBDestroyFunc\fR SessionInitFunction \fBAddToFunc\fR SessionInitFunction + I \fBModule\fR \fBFvwmBanner\fR \fBDestroyFunc\fR SessionRestartFunction \fBAddToFunc\fR SessionRestartFunction + I \fBNop\fR .fi .RE .PP You do not need to define all special functions if some are empty\. Also note, all these special functions may be emulated now using \fBStartFunction\fR and \fBExitFunction,\fR like this: .sp .RS 4 .nf \fBDestroyFunc\fR StartFunction \fBAddToFunc\fR StartFunction + I \fBTest\fR (Init) \fBModule\fR \fBFvwmBanner\fR + I \fBModule\fR \fBFvwmPager\fR * * + I \fBTest\fR (Restart) \fBBeep\fR \fBDestroyFunc\fR ExitFunction \fBAddToFunc\fR ExitFunction + I \fBTest\fR (Quit) \fBEcho\fR Bye\-bye + I \fBKillModule\fR MyBuggyModule + I \fBTest\fR (ToRestart) \fBBeep\fR .fi .RE .SH COMPILATION OPTIONS .PP Fvwm has a number of compile\-time options\. If you have trouble using a certain command or feature, check to see if support for it was included at compile time\. Optional features are described in the \fIconfig\.h\fR file that is generated during compilation\. .SH ICONS AND IMAGES .PP Fvwm can load \fB\.xbm,\fR \fB\.xpm,\fR \fB\.png\fR and \fB\.svg\fR images\. \fBXBM\fR images are monochrome\. Fvwm can always display \fBXBM\fR files\. \fBXPM\fR and \fBPNG\fR formats are color images\. SVG is a vector graphics image format\. Compile\-time options determine whether fvwm can display \fBXPM\fR, \fBPNG\fR or \fBSVG\fR icons and images\. See the \fIINSTALL\.fvwm\fR file for more information\. .PP The related \fBSHAPE\fR compile\-time option can make fvwm display spiffy shaped icons\. .SS SVG rendering options .PP SVG images are generated from (XML) text files\. A really simple SVG file might look something like this: .sp .RS 4 .nf .fi .RE .PP By default, SVG images are rendered as the image creator intended them to\. But since SVG is a vector graphics format, the images can be rendered at any chosen size and rotation, e\.g\. making it possible to use the same icon file rendered at different sizes for the \fIIcon\fR and \fIMiniIcon\fR styles\. .PP The rendering options are specified as a string appended to the SVG filename as follows: .HP 1 \fI\fIimage\.svg\fR\fR:[!] [(1)\ \fIsize\fR] [(2)\ \fIposition\fR]\ [(3)\ \fIrotation\fR]\ [(4)\ \fIscale\fR] ... .HP 4 (1) [\-]\fIwidth\fR{x}[\-]\fIheight\fR .sp -1n .HP 4 (2) {\- | +}\fIxpos\fR{\- | +}\fIypos\fR .sp -1n .HP 4 (3) @[\-]\fIangle\fR .sp -1n .HP 4 (4) {* | /}[\-]\fIfactor\fR[x | y] .PP The option string always starts with a colon (':') to separate it from the filename\. An empty option string can skip this colon, but it might still be a good idea to include it to prevent ambiguity if the filename contains any colon\. .sp .RS 4 .nf filename_without_colon\.svg filename:with:colon\.svg: .fi .RE .PP An exclamation point ('!') transposes the entire final image (including the rendering area), i\.e\. all the horizontal and all the vertical coordinates are swapped with each other\. .sp .RS 4 .nf image\.svg:! .fi .RE .PP \fIwidth\fR and \fIheight\fR specifies the dimensions of the rendering area in pixels, i\.e\. the dimensions of the resulting image\. The actual image is fitted to fill the entire rendering area\. .sp .RS 4 .nf image\.svg:60x60 .fi .RE .PP Use a \fIwidth\fR or \fIheight\fR value of 0 to keep the aspect ratio\. .sp .RS 4 .nf image\.svg:0x60 image\.svg:60x0 .fi .RE .PP A '\-' before \fIwidth\fR mirrors the rendering area horizontally\. .sp .RS 4 .nf image\.svg:\-0x0 .fi .RE .PP A '\-' before \fIheight\fR mirrors the rendering area vertically\. .sp .RS 4 .nf image\.svg:0x\-0 .fi .RE .PP \fIxpos\fR and \fIypos\fR specifies a translation of the image in pixels\. A positive \fIxpos\fR value moves the image to the right\. A positive \fIypos\fR value moves it down\. Moving it partially outside of the rendering area results in a cropped image\. .sp .RS 4 .nf image\.svg:\-30\-0 image\.svg:\-0+10 image\.svg:\-30+10 .fi .RE .PP \fIangle\fR specifies a rotation around the actual image center in degrees\. This might result in a cropped image\. A positive value rotates the image clockwise\. Floating point values are recognized\. .sp .RS 4 .nf image\.svg:@180 image\.svg:@\-90 image\.svg:@30 image\.svg:@57\.3 .fi .RE .PP \fIfactor\fR specifes a scaling of the actual image (not the rendering area)\. Scaling it up results in a cropped image\. Floating point values are recognized\. Division by zero is ignored\. If \fIfactor\fR is directly followed by a 'x' or a 'y', the scaling is horizontal or vertical respectively\. Otherwise the scaling is uniform\. .sp .RS 4 .nf image\.svg:*2 image\.svg:/2 image\.svg:/3x image\.svg:/2y .fi .RE .PP Scaling down a translated or rotated image can prevent cropping\. .sp .RS 4 .nf image\.svg:@30*0\.6 .fi .RE .PP Repeated usage of translation, rotation, and scaling is allowed\. Translation and rotation are additive\. Scaling is multiplicative\. .sp .RS 4 .nf image\.svg:*2/3 image\.svg:/3x/2y .fi .RE .PP When combining affine transformations, the scaling is always done first, then the rotation, and finally the translation\. .sp .RS 4 .nf image\.svg:\-30+10@30/3x/2y .fi .RE .PP Use a negative scale \fIfactor\fR to mirror the actual image\. .sp .RS 4 .nf image\.svg:\-30+10@30/\-3x/2y .fi .RE .PP Mirroring of the rendering area is done after any scaling, rotation or translation of the image\. .sp .RS 4 .nf image\.svg:\-0x0\-30+10@30/3x/2y .fi .RE .PP Transposing is done last of all, after everything else\. .sp .RS 4 .nf image\.svg:!\-0x0\-30+10@30/3x/2y .fi .RE .SH MODULES .PP A module is a separate program which runs as a separate Unix process but transmits commands to fvwm to execute\. Users can write their own modules to do any weird or bizarre manipulations without bloating or affecting the integrity of fvwm itself\. .PP Modules must be spawned by fvwm so that it can set up two pipes for fvwm and the module to communicate with\. The pipes are already open for the module when it starts and the file descriptors for the pipes are provided as command line arguments\. .PP Modules can be spawned by fvwm at any time during the X session by use of the \fBModule\fR command\. Modules can exist for the duration of the X session, or can perform a single task and exit\. If the module is still active when fvwm is told to quit, then fvwm closes the communication pipes and waits to receive a SIGCHLD from the module, indicating that it has detected the pipe closure and has exited\. If modules fail to detect the pipe closure fvwm exits after approximately 30 seconds anyway\. The number of simultaneously executing modules is limited by the operating system's maximum number of simultaneously open files, usually between 60 and 256\. .PP Modules simply transmit commands to the fvwm command engine\. Commands are formatted just as in the case of a mouse binding in the \fIconfig\fR setup file\. Certain auxiliary information is also transmitted, as in the sample module \fBFvwmButtons\fR\. .PP Please refer to the \fBModule Commands\fR section for details\. .SH ICCCM COMPLIANCE .PP Fvwm attempts to be ICCCM 2\.0 compliant\. Check \fIhttp://tronche\.com/gui/x/icccm/\fR for more info\. In addition, ICCCM states that it should be possible for applications to receive any keystroke, which is not consistent with the keyboard shortcut approach used in fvwm and most other window managers\. In particular you cannot have the same keyboard shortcuts working with your fvwm and another fvwm running within Xnest (a nested X server running in a window)\. The same problem exists with mouse bindings\. .PP The ICCCM states that windows possessing the property .sp .RS 4 .nf WM_HINTS(WM_HINTS): Client accepts input or input focus: False .fi .RE .PP should not be given the keyboard input focus by the window manager\. These windows can take the input focus by themselves, however\. A number of applications set this property, and yet expect the window manager to give them the keyboard focus anyway, so fvwm provides a window style, \fILenience\fR, which allows fvwm to overlook this ICCCM rule\. Even with this window style it is not guaranteed that the application accepts focus\. .PP The differences between ICCCM 1\.1 and 2\.0 include the ability to take over from a running ICCCM 2\.0 compliant window manager; thus .sp .RS 4 .nf fvwm; vi ~/\.fvwm/config; fvwm \-replace .fi .RE .PP .PP resembles the \fBRestart\fR command\. It is not exactly the same, since killing the previously running wm may terminate your X session, if the wm was started as the last client in your \fI\.Xclients\fR or \fI\.Xsession\fR file\. .PP Further additions are support for client\-side colormap installation (see the ICCCM for details) and the urgency hint\. Clients can set this hint in the WM_HINTS property of their window and expect the window manager to attract the user's attention to the window\. Fvwm has two re\-definable functions for this purpose, "UrgencyFunc" and "UrgencyDoneFunc", which are executed when the flag is set/cleared\. Their default definitions are: .sp .RS 4 .nf \fBAddToFunc\fR UrgencyFunc + I \fBIconify\fR off + I \fBFlipFocus\fR + I \fBRaise\fR + I \fBWarpToWindow !raise\fR 5p 5p \fBAddToFunc\fR UrgencyDoneFunc + I \fBNop\fR .fi .RE .SH GNOME COMPLIANCE .PP Fvwm attempts to be GNOME (version 1) compliant\. Check \fIhttp://www\.gnome\.org\fR for what that may mean\. To disable GNOME hints for some or all windows, the \fIGNOMEIgnoreHints\fR style can be used\. .SH EXTENDED WINDOW MANAGER HINTS .PP Fvwm attempts to respect the extended window manager hints (ewmh or EWMH for short) specification: \fIhttp://www\.freedesktop\.org/wiki/Standards_2fwm_2dspec\fR and some extensions of this specification\. This allows fvwm to work with KDE version >= 2, GNOME version 2 and other applications which respect this specification (any application based on \fIGTK+\fR version 2)\. Applications which respect this specification are called ewmh compliant applications\. .PP This support is configurable with styles and commands\. These styles and commands have EWMH as the prefix (so you can find them easily in this man page)\. .PP There is a new Context 'D' for the \fBKey\fR, \fBPointerKey\fR, \fBMouse\fR and \fBStroke\fR commands\. This context is for desktop applications (such as kdesktop and Nautilus desktop)\. .PP When a compliant taskbar asks fvwm to activate a window (typically when you click on a button which represents a window in such a taskbar), then fvwm calls the complex function \fBEWMHActivateWindowFunc\fR which by default is Iconify Off, Focus and Raise\. You can redefine this function\. For example: .sp .RS 4 .nf \fBDestroyFunc\fR EWMHActivateWindowFunc \fBAddToFunc\fR EWMHActivateWindowFunc I \fBIconify\fR Off + I \fBFocus\fR + I \fBRaise\fR + I \fBWarpToWindow\fR 50 50 .fi .RE .PP additionally warps the pointer to the center of the window\. .PP The EWMH specification introduces the notion of Working Area\. Without ewmh support the Working Area is the full visible screen (or all your screens if you have a multi head setup and you use Xinerama)\. However, compliant applications (such as a panel) can ask to reserve space at the edge of the screen\. If this is the case, the Working Area is your full visible screen minus these reserved spaces\. If a panel can be hidden by clicking on a button the Working Area does not change (as you can unhide the panel at any time), but the Dynamic Working Area is updated: the space reserved by the panel is removed (and added again if you pop up the panel)\. The Dynamic Working Area may be used when fvwm places or maximizes a window\. To know if an application reserves space you can type "xprop | grep _NET_WM_STRUT" in a terminal and select the application\. If four numbers appear then these numbers define the reserved space as explained in the \fBEwmhBaseStruts\fR command\. .SH MWM COMPATIBILITY .PP Fvwm provides options to emulate Motif Window Manager (Mwm) as well as possible\. Please refer to the \fBEmulate\fR command as well as to the Mwm specific options of the \fBStyle\fR and \fBMenuStyle\fR commands for details\. .SH OPEN LOOK AND XVIEW COMPATIBILITY .PP Fvwm supports all the Open Look decoration hints (except pushpins)\. Should you use any such application, please add the following line to your config: .sp .RS 4 .nf \fBStyle\fR * \fIOLDecor\fR .fi .RE .PP Most (perhaps all) Open Look applications have a strange notion of keyboard focus handling\. Although a lot of work went into fvwm to work well with these, you may still encounter problems\. It is recommended to use the \fINeverFocus\fR focus policy and the \fILenience\fR style for all such applications (the windows still get the focus): .sp .RS 4 .nf \fBStyle\fR \fINeverFocus\fR, \fILenience\fR .fi .RE .PP But in case you can not live with that focus policy, you can try using one of the other focus policies in combination with the \fILenience\fR style: .sp .RS 4 .nf \fBStyle\fR \fIMouseFocus\fR, \fILenience\fR \fBStyle\fR \fISloppyFocus\fR, \fILenience\fR \fBStyle\fR \fIClickToFocus\fR, \fILenience\fR .fi .RE .SH M4 PREPROCESSING .PP M4 pre\-processing is handled by a module in fvwm\. To get more details, try man \fBFvwmM4\fR\. In short, if you want fvwm to parse your files with m4, then replace the command \fBRead\fR with \fBFvwmM4\fR in your \fI~/\.fvwm/config\fR file (if it appears at all), and start fvwm with the command .sp .RS 4 .nf fvwm \-cmd "\fBFvwmM4\fR config" .fi .RE .PP .SH CPP PREPROCESSING .PP Cpp is the C\-language pre\-processor\. fvwm offers cpp processing which mirrors the m4 pre\-processing\. To find out about it, re\-read the \fBM4\fR section, but replace "m4" with "cpp"\. .SH CONFIGURATION .SS Configuration Files .PP The configuration file is used to describe mouse and button bindings, colors, the virtual display size, and related items\. The initialization configuration file is typically called \fIconfig\fR (or \fI\.fvwm2rc\fR)\. By using the \fBRead\fR command, it is easy to read in new configuration files as you go\. .PP Lines beginning with '#' are ignored by fvwm\. Lines starting with '*' are expected to contain module configuration commands (rather than configuration commands for fvwm itself)\. Like in shell scripts embedded newlines in a configuration file line can be quoted by preceding them with a backslash\. All lines linked in this fashion are treated as a single line\. The newline itself is ignored\. .PP Fvwm makes no distinction between configuration commands and action commands, so anything mentioned in the fvwm commands section can be placed on a line by itself for fvwm to execute as it reads the configuration file, or it can be placed as an executable command in a menu or bound to a mouse button or a keyboard key\. It is left as an exercise for the user to decide which function make sense for initialization and which ones make sense for run\-time\. .SS Supplied Configuration .PP A sample configuration file, is supplied with the fvwm distribution\. It is well commented and can be used as a source of examples for fvwm configuration\. It may be copied from \fI/usr/local/share/fvwm/config\fR file\. .PP Alternatively, the built\-in menu (accessible when no configuration file is found) has options to create an initial config file for the user\. .SH FONTS .SS Font names and font loading .PP The fonts used for the text of a window title, icon titles, menus and geometry window can be specified by using the Font and IconFont \fBStyle\fR, the Font \fBMenuStyle\fR and the \fBDefaultFont\fR commands\. Also, all the Modules which use text have configuration command(s) to specify font(s)\. All these styles and commands take a font name as an argument\. This section explains what is a font name for fvwm and which fonts fvwm loads\. .PP First, you can use what we can call a usual font name, for example, .sp .RS 4 .nf \-adobe\-courier\-bold\-r\-normal\-\-10\-100\-75\-75\-m\-60\-ISO8859\-1 \-adobe\-courier\-bold\-r\-normal\-\-10\-* \-*\-fixed\-medium\-o\-normal\-\-14\-*\-ISO8859\-15 .fi .RE .PP That is, you can use an X Logical Font Description (XLFD for short)\. Then the "first" font which matches the description is loaded and used\. This "first" font depends of your font path and also of your locale\. Fonts which match the locale charset are loaded in priority order\. For example with .sp .RS 4 .nf \-adobe\-courier\-bold\-r\-normal\-\-10\-* .fi .RE .PP if the locale charset is ISO8859\-1, then fvwm tries to load a font which matches .sp .RS 4 .nf \-adobe\-courier\-bold\-r\-normal\-\-10\-*\-ISO8859\-1 .fi .RE .PP with the locale charset ISO8859\-15 fvwm tries to load .sp .RS 4 .nf \-adobe\-courier\-bold\-r\-normal\-\-10\-*\-ISO8859\-15\. .fi .RE .PP A font name can be given as an extended XLFD\. This is a comma separated list of (simple) XLFD font names, for example: .sp .RS 4 .nf \-adobe\-courier\-bold\-r\-normal\-\-14\-*,\-*\-courier\-medium\-r\-normal\-\-14\-* .fi .RE .PP Each simple font name is tried until a matching font with the locale charset is found and if this fails each simple font name is tried without constraint on the charset\. .PP More details on the XLFD can be found in the X manual page, the X Logical Font Description Conventions document (called xlfd) and the XLoadFont and XCreateFontSet manual pages\. Some useful font utilities are: xlsfonts, xfontsel, xfd and xset\. .PP If you have Xft support you can specify an Xft font name (description) of a true type (or Type1) font prefixed by "xft:", for example: .sp .RS 4 .nf "xft:Luxi Mono" "xft:Luxi Mono:Medium:Roman:size=14:encoding=iso8859\-1" .fi .RE .PP The "first" font which matches the description is loaded\. This first font depends on the XftConfig configuration file with Xft1 and on the /etc/fonts/fonts\.conf file with Xft2\. One may read the Xft manual page and the fontconfig man page with Xft2\. The first string which follows "xft:" is always considered as the family\. With the second example Luxi Mono is the Family (Other XFree TTF families: "Luxi Serif", "Luxi Sans"), Medium is the Weight (other possible weights: Light, DemiBold, Bold, Black), Roman is the slant or the style (other possibilities: Regular, Oblique, Italic) size specifies the point size (for a pixel size use pixelsize=), encoding allows for enforce a charset (iso8859\-1 or iso10646\-1 only; if no encoding is given the locale charset is assumed)\. An important parameter is "minspace=bool" where bool is True or False\. If bool is False (the default?) Xft gives a greater font height to fvwm than if bool is True\. This may modify text placement, icon and window title height, line spacing in menus and \fBFvwmIdent\fR, button height in some fvwm modules \.\.\.etc\. With a LCD monitor you may try to add "rgba=mode" where mode is either rgb, bgr, vrgb or vbgr to enable subpixel rendering\. The best mode depends on the way your LCD cells are arranged\. You can pass other specifications in between ":", as "foundry=foundry_name", "spacing=type" where type can be monospace, proportional or charcell, "charwidth=integer", "charheight=integer" or "antialias=bool" where bool is True or False\. It seems that these parameters are not always taken in account\. .PP To determine which Xft fonts are really loaded you can export XFT_DEBUG=1 before starting fvwm and take a look to the error log\. With Xft2 you may use fc\-list to list the available fonts\. Anyway, Xft support is experimental (from the X and the fvwm point of view) and the quality of the rendering depends on number of parameters (the XFree and the freetype versions and your video card(s))\. .PP After an Xft font name you can add after a ";" an XLFD font name (simple or extended) as: .sp .RS 4 .nf xft:Verdana:pixelsize=14;\-adobe\-courier\-bold\-r\-normal\-\-14\-* .fi .RE .PP then, if either loading the Xft font fails or fvwm has no Xft support, fvwm loads the font "\-adobe\-courier\-bold\-r\-normal\-\-14\-*"\. This allows for writing portable configuration files\. .SS Font and string encoding .PP Once a font is loaded, fvwm finds its encoding (or charset) using its name (the last two fields of the name)\. fvwm assumes that the strings which are displayed with this font use this encoding (an exception is that if an iso10646\-1 font is loaded, then UTF\-8 is assumed for string encoding)\. In a normal situation, (i) a font is loaded by giving a font name without specifying the encoding, (ii) the encoding of the loaded font is the locale encoding, and then (iii) the strings in the fvwm configuration files should use the locale encoding as well as the window and icon name\. With Xft the situation is bit different as Xft supports only iso10646\-1 and iso8859\-1\. If you do not specify one of these encodings in the Xft font name, then fvwm does strings conversion using (iii)\. Note that with multibyte fonts (and in particular with "CJK" fonts) for good text rendering, the locale encoding should be the charset of the font\. .PP To override the previous rules, it is possible to specify the string encoding in the beginning of a font description as follow: .sp .RS 4 .nf StringEncoding=\fIenc\fR:_full_font_name_ .fi .RE .PP where \fIenc\fR is an encoding supported by fvwm (usually font name charset plus some unicode encodings: UTF\-8, USC\-2, USC\-4 and UTF\-16)\. .PP For example, you may use an iso8859\-1 locale charset and have an \fBFvwmForm\fR in Russian using koi8\-r encoding\. In this case, you just have to ask \fBFvwmForm\fR to load a koi8\-r font by specifying the encoding in the font name\. With a multibyte language, (as multibyte font works well only if the locale encoding is the charset of the font), you should use an iso10646\-1 font: .sp .RS 4 .nf StringEncoding=jisx0208\.1983\-0:\-*\-fixed\-medium\-r\-*\-ja\-*\-iso10646\-1 .fi .RE .PP or .sp .RS 4 .nf "StringEncoding=jisx0208\.1983\-0:xft:Bitstream Cyberbit" .fi .RE .PP if your \fBFvwmForm\fR configuration uses jisx0208\.1983\-0 encoding\. Another possibility is to use UTF\-8 encoding for your \fBFvwmForm\fR configuration and use an iso10646\-1 font: .sp .RS 4 .nf \-*\-fixed\-medium\-r\-*\-ja\-*\-iso10646\-1 .fi .RE .PP or .sp .RS 4 .nf "StringEncoding=UTF\-8:xft:Bitstream Cyberbit" .fi .RE .PP or equivalently .sp .RS 4 .nf "xft:Bitstream Cyberbit:encoding=iso10646\-1" .fi .RE .PP In general iso10646\-1 fonts together with UTF\-8 string encoding allows the display of any characters in a given menu, \fBFvwmForm\fR etc\. .PP More and more, unicode is used and text files use UTF\-8 encoding\. However, in practice the characters used range over your locale charset (this is the case when you generate a menu with fvwm\-menu\-desktop with recent versions of KDE and GNOME)\. For saving memory (an iso10646\-1 font may have a very large number of characters) or because you have a pretty font without an iso10646\-1 charset, you can specify the string encoding to be UTF\-8 and use a font in the locale charset: .sp .RS 4 .nf StringEncoding=UTF\-8:\-*\-pretty_font\-*\-12\-* .fi .RE .PP In most cases, fvwm correctly determines the encoding of the font\. However, some fonts do not end with valid encoding names\. When the font name isn't normal, for example: .sp .RS 4 .nf \-misc\-fixed\-*\-\-20\-*\-my_utf8\-36 .fi .RE .PP you need to add the encoding after the font name using a slash as a delimiter\. For example: .sp .RS 4 .nf \fBMenuStyle\fR * \fIFont\fR \-misc\-fixed\-*\-\-20\-*\-my_utf8\-36/iso10646\-1 .fi .RE .PP If fvwm finds an encoding, fvwm uses the iconv system functions to do conversion between encodings\. Unfortunately, there are no standards\. For conversion between iso8859\-1 and UTF\-8: a GNU system uses "ISO\-8859\-1" and other systems use "iso881" to define the converters (these two names are supported by fvwm)\. Moreover, in some cases it may be necessary to use machine specific converters\. So, if you experience problems you can try to get information on your iconv implementation ("man iconv" may help) and put the name which defines the converter between the font encoding and UTF\-8 at the end of the font name after the encoding hint and a / (another possible solution is to use GNU libiconv)\. For example use: .sp .RS 4 .nf \fBStyle\fR * \fIFont\fR \-misc\-fixed\-*\-\-14\-*\-iso8859\-1/*/latin1 .fi .RE .PP to use latin1 for defining the converter for the iso8859\-1 encoding\. The "*" in between the "/" says to fvwm to determine the encoding from the end of the font name\. Use: .sp .RS 4 .nf \fBStyle\fR * \fIFont\fR \e \-misc\-fixed\-*\-\-14\-*\-local8859\-6/iso8859\-6/local_iso8859_6_iconv .fi .RE .PP to force fvwm to use the font with iso8859\-6 as the encoding (this is useful for bi\-directionality) and to use local_iso8859_6_iconv for defining the converters\. .SS Font Shadow Effects .PP Fonts can be given 3d effects\. At the beginning of the font name (or just after a possible StringEncoding specification) add .sp .RS 4 .nf Shadow=\fIsize\fR [\fIoffset\fR] [\fIdirections]\fR]: .fi .RE .PP \fIsize\fR is a positive integer which specifies the number of pixels of shadow\. \fIoffset\fR is an optional positive integer which defines the number of pixels to offset the shadow from the edge of the character\. The default offset is zero\. \fIdirections\fR is an optional set of directions the shadow emanates from the character\. The \fIdirections\fR are a space separated list of fvwm directions: .PP \fIN\fR, \fINorth\fR, \fITop\fR, \fIt\fR, \fIUp\fR, \fIu\fR, \fI\-\fR .PP \fIE\fR, \fIEast\fR, \fIRight\fR, \fIr\fR, \fIRight\fR, \fIr\fR, \fI]\fR .PP \fIS\fR, \fISouth\fR, \fIBottom\fR, \fIb\fR, \fIDown\fR, \fId\fR, \fI_\fR .PP \fIW\fR, \fIWest\fR, \fILeft\fR, \fIl\fR, \fILeft\fR, \fIl\fR, \fI[\fR .PP \fINE\fR, \fINorthEast\fR, \fITopRight\fR, \fItr\fR, \fIUpRight\fR, \fIur\fR, \fI^\fR .PP \fISE\fR, \fISouthEast\fR, \fIBottomRight\fR, \fIbr\fR, \fIDownRight\fR, \fIdr\fR, \fI>\fR .PP \fISW\fR, \fISouthWest\fR, \fIBottomLeft\fR, \fIbl\fR, \fIDownLeft\fR, \fIdl\fR, \fIv\fR .PP \fINW\fR, \fINorthWest\fR, \fITopLeft\fR, \fItl\fR, \fIUpLeft\fR, \fIul\fR, \fI<\fR .PP \fIC\fR, \fICenter\fR, \fICentre\fR, \fI\.\fR .PP A shadow is displayed in each given direction\. \fIAll\fR is equivalent to all the directions\. The default \fIdirection\fR is \fIBottomRight\fR\. With the \fICenter\fR direction, the shadow surrounds the whole string\. Since this is a super set of all other directions, it is a waste of time to specify this along with any other directions\. .PP The shadow effect only works with colorsets\. The color of the shadow is defined by using the \fIfgsh\fR option of the \fBColorset\fR command\. Please refer to the \fBColorsets\fR section for details about colorsets\. .PP Note: It can be difficult to find the font, \fIfg\fR, \fIfgsh\fR and \fIbg\fR colors to make this effect look good, but it can look quite good\. .SH BI\-DIRECTIONAL TEXT .PP Arabic and Hebrew text require bi\-directional text support to be displayed correctly, this means that logical strings should be converted before their visual presentation, so left\-to\-right and right\-to\-left sub\-strings are determined and reshuffled\. In fvwm this is done automatically in window titles, menus, module labels and other places if the fonts used for displaying the text are of one of the charsets that require \fIbidi\fR (bi\-directional) support\. For example, this includes iso8859\-6, iso8859\-8 and iso10646\-1 (unicode), but not other iso8859\-* fonts\. .PP This bi\-directional text support is done using the \fIfribidi\fR library compile time option, see \fIINSTALL\.fvwm\fR\. .SH KEYBOARD SHORTCUTS .PP Almost all window manager operations can be performed from the keyboard so mouse\-less operation should be possible\. In addition to scrolling around the virtual desktop by binding the \fBScroll\fR command to appropriate keys, \fBPopup\fR, \fBMove\fR, \fBResize\fR, and any other command can be bound to keys\. Once a command is started the pointer is moved by using the up, down, left, and right arrows, and the action is terminated by pressing return\. Holding down the .SM Shift key causes the pointer movement to go in larger steps and holding down the .SM control key causes the pointer movement to go in smaller steps\. Standard emacs and vi cursor movement controls ( .SM n , .SM p , .SM f , .SM b , and .SM j , .SM k , .SM h , .SM l ) can be used instead of the arrow keys\. .SH SESSION MANAGEMENT .PP Fvwm supports session management according to the X Session Management Protocol\. It saves and restores window position, size, stacking order, desk, stickiness, shadiness, maximizedness, iconifiedness for all windows\. Furthermore, some global state is saved\. .PP Fvwm doesn't save any information regarding styles, decors, functions or menus\. If you change any of these resources during a session (e\.g\. by issuing \fBStyle\fR commands or by using various modules), these changes are lost after saving and restarting the session\. To become permanent, such changes have to be added to the configuration file\. .PP Note further that the current implementation has the following anomaly when used on a multi\-screen display: Starting fvwm for the first time, fvwm manages all screens by forking a copy of itself for each screen\. Every copy knows its parent and issuing a \fBQuit\fR command to any instance of fvwm kills the master and thus all copies of fvwm\. When you save and restart the session, the session manager brings up a copy of fvwm on each screen, but this time they are started as individual instances managing one screen only\. Thus a \fBQuit\fR kills only the copy it was sent to\. This is probably not a very serious problem, since with session management, you are supposed to quit a session through the session manager anyway\. If it is really needed, .sp .RS 4 .nf \fBExec\fR exec killall fvwm .fi .RE .PP still kills all copies of fvwm\. Your system must have the \fBkillall\fR command though\. .SH BOOLEAN ARGUMENTS .PP A number of commands take one or several boolean arguments\. These take a few equivalent inputs: "yes", "on", "true", "t" and "y" all evaluate to true while "no", "off", "false", "f" and "n" evaluate to false\. Some commands allow "toggle" too which means that the feature is disabled if it is currently enabled and vice versa\. .SH BUILTIN KEY AND MOUSE BINDINGS .PP The following commands are built\-in to fvwm: .sp .RS 4 .nf \fBKey\fR Help R A \fBPopup\fR MenuFvwmRoot \fBKey\fR F1 R A \fBPopup\fR MenuFvwmRoot \fBKey\fR Tab A M \fBWindowList\fR Root c c NoDeskSort \fBKey\fR Escape A MC \fBEscapeFunc\fR \fBMouse\fR 1 R A \fBMenu\fR MenuFvwmRoot \fBMouse\fR 1 T A FuncFvwmRaiseLowerX \fBMove\fR \fBMouse\fR 1 FS A FuncFvwmRaiseLowerX \fBResize\fR \fBMouse\fR 2 FST A FuncFvwmRaiseLowerX \fBMove\fR \fBAddToFunc\fR FuncFvwmRaiseLowerX + I \fBRaise\fR + M $0 + D \fBLower\fR .fi .RE .PP The .SM Help and .SM F1 keys invoke a built\-in menu that fvwm creates\. This is primarily for new users that have not created their own configuration file\. Either key on the root (background) window pops up an menu to help you get started\. .PP The .SM Tab key pressed anywhere with the .SM Meta key (same as the .SM Alt key on PC keyboards) held down pop\-ups a window list\. .PP Mouse button 1 on the title\-bar or side frame can move, raise or lower a window\. .PP Mouse button 1 on the window corners can resize, raise or lower a window\. .PP You can override or remove these bindings\. To remove the window list binding, use this: .sp .RS 4 .nf \fBKey\fR Tab A M \- .fi .RE .SH COMMAND EXECUTION .SS Module and Function Commands .PP If fvwm encounters a command that it doesn't recognize, it checks to see if the specified command should have been .sp .RS 4 .nf \fBFunction\fR (rest of command) .fi .RE .PP or .sp .RS 4 .nf \fBModule\fR (rest of command) .fi .RE .PP This allows complex functions or modules to be invoked in a manner which is fairly transparent to the configuration file\. .PP Example: the \fIconfig\fR file contains the line .sp .RS 4 .nf HelpMe .fi .RE .PP Fvwm looks for an fvwm command called "HelpMe", and fails\. Next it looks for a user\-defined complex function called "HelpMe"\. If no such function exists, fvwm tries to execute a module called "HelpMe"\. .SS Delayed Execution of Commands .PP Note: There are many commands that affect look and feel of specific, some or all windows, like \fBStyle\fR, \fBMouse\fR, \fBColorset\fR, \fBTitleStyle\fR and many others\. For performance reasons such changes are not applied immediately but only when fvwm is idle, i\.e\. no user interaction or module input is pending\. Specifically, new \fBStyle\fR options that are set in a function are not applied until after the function has completed\. This can sometimes lead to unwanted effects\. .PP To force that all pending changes are applied immediately, use the \fBUpdateStyles\fR, \fBRefresh\fR or \fBRefreshWindow\fR commands\. .SH QUOTING .PP Quotes are required only when needed to make fvwm consider two or more words to be a single argument\. Unnecessary quoting is allowed\. If you want a quote character in your text, you must escape it by using the backslash character\. For example, if you have a pop\-up menu called "Window\-Ops", then you do not need quotes: .sp .RS 4 .nf \fBPopup\fR Window\-Ops .fi .RE .PP but if you replace the dash with a space, then you need quotes: .sp .RS 4 .nf \fBPopup\fR "Window Ops" .fi .RE .PP The supported quoting characters are double quotes, single quotes and reverse single quotes\. All three kinds of quotes are treated in the same way\. Single characters can be quoted with a preceding backslash\. Quoting single characters works even inside other kinds of quotes\. .SH COMMAND EXPANSION .PP Whenever an fvwm command line is executed, fvwm performs parameter expansion\. A parameter is a '$' followed by a word enclosed in brackets ($[\.\.\.]) or a single special character\. If fvwm encounters an unquoted parameter on the command line it expands it to a string indicated by the parameter name\. Unknown parameters are left untouched\. Parameter expansion is performed before quoting\. To get a literal '$' use "$$"\. .PP If a command is prefixed with a '\-' parameter expansion isn't performed\. This applies to the command immediately following the '\-', in which the expansion normally would have taken place\. When uesed together with other prefix commands it must be added before the other prefix\. .PP Example: .sp .RS 4 .nf \fBPick\fR \-\fBExec\fR exec xmessage '$[w\.name]' .fi .RE .PP opens an xmessage dialog with "$[w\.name]" unexpanded\. .PP The longer variables may contain additional variables inside the name, which are expanded before the outer variable\. .PP In earlier versions of fvwm, some single letter variables were supported\. It is deprecated now, since they cause a number of problems\. You should use the longer substitutes instead\. .PP Example: .sp .RS 4 .nf # Print the current desk number, horizontal page number # and the window's class (unexpanded here, no window)\. \fBEcho\fR $[desk\.n] $[page\.nx] $[w\.class] .fi .RE .PP Note: If the command is called outside a window context, it prints "$[w\.class]" instead of the class name\. It is usually not enough to have the pointer over a window to have a context window\. To force using the window with the focus, the \fBCurrent\fR command can be used: .sp .RS 4 .nf \fBCurrent\fR \fBEcho\fR $[desk\.n] $[page\.nx] $[w\.class] .fi .RE .PP The parameters known by fvwm are: .PP $$ .RS 4 A literal '$'\. .RE .PP $\. .RS 4 The absolute directory of the currently Read file\. Intended for creating relative and relocatable configuration trees\. If used outside of any read file, the returned value is '\.'\. .RE .PP $0 to $9 .RS 4 The positional parameters given to a complex function (a function that has been defined with the \fBAddToFunc\fR command)\. "$0" is replaced with the first parameter, "$1" with the second parameter and so on\. If the corresponding parameter is undefined, the "$\.\.\." is deleted from the command line\. .RE .PP $* .RS 4 All positional parameters given to a complex function\. This includes parameters that follow after "$9"\. .RE .PP $[\fIn\fR] .RS 4 The \fIn\fR:th positional parameter given to a complex function, counting from 0\. If the corresponding parameter is undefined, the "$[\fIn\fR]" is deleted from the command line\. The parameter is expanded unquoted\. .RE .PP $[\fIn\fR\-\fIm\fR] .RS 4 The positional parameters given to a complex function, starting with parameter \fIn\fR and ending with parameter \fIm\fR\. If all the corresponding parameters are undefined, the "$[\.\.\.]" is deleted from the command line\. If only some of the parameters are defined, all defined parameters are expanded, and the remaining silently ignored\. All parameters are expanded unquoted\. .RE .PP $[\fIn\fR\-] .RS 4 All the positional parameters given to a complex function, starting with parameter \fIn\fR\. If all the corresponding parameters are undefined, the "$[\.\.\.]" is deleted from the command line\. All parameters are expanded unquoted\. .RE .PP $[*] .RS 4 All the positional parameters given to a complex function\. This is equivalent of $[0\-]\. .RE .PP $[version\.num] .RS 4 The version number, like "2\.6\.0"\. .RE .PP $[version\.info] .RS 4 The version info, like " (from cvs)", empty for the official releases\. .RE .PP $[version\.line] .RS 4 The first line printed by the \-\-version command line option\. .RE .PP $[vp\.x] $[vp\.y] $[vp\.width] $[vp\.height] .RS 4 Either coordinate or the width or height of the current viewport\. .RE .PP $[wa\.x] $[wa\.y] $[wa\.width] $[wa\.height] .RS 4 Either coordinate or the width or height of the EWMH working area\. .RE .PP $[dwa\.x] $[dwa\.y] $[dwa\.width] $[dwa\.height] .RS 4 Either coordinate or the width or height of the dynamic EWMH working area\. .RE .PP $[desk\.n] .RS 4 The current desk number\. .RE .PP $[desk\.name] .RS 4 These parameters are replaced with the name of the desktop number that is defined with the \fBDesktopName\fR command\. If no name is defined, then the default name is returned\. .RE .PP $[desk\.width] $[desk\.height] .RS 4 The width or height of the whole desktop, i\.e\. the width or height multiplied by the number of pages in x or y direction\. .RE .PP $[desk\.pagesx] $[desk\.pagesy] .RS 4 The number of total pages in a desk in x or y direction\. This is the same as the values set by \fBDesktopSize\fR\. .RE .PP $[page\.nx] $[page\.ny] .RS 4 The current page numbers, by X and Y axes, starting from 0\. \fIpage\fR is equivalent to \fIarea\fR in the GNOME terminology\. .RE .PP $[w\.id] .RS 4 The window\-id (expressed in hex, e\.g\. 0x10023c) of the window the command was called for or "$[w\.id]" if no window is associated with the command\. .RE .PP $[w\.name] $[w\.iconname] $[w\.class] $[w\.resource] $[w\.visiblename] $[w\.iconfile] $[w\.miniiconfile] $[w\.iconfile\.svgopts] $[w\.miniiconfile\.svgopts] .RS 4 The window's name, icon name, resource class and resource name, visible name, file name of its icon or mini icon defined with the \fIIcon\fR or \fIMiniIcon\fR style (including the full path if the file was found on disk), and (if fvwm is compiled with SVG support) the icon or mini icon svg rendering options (including the leading colon), or unexpanded "$[w\.]" string if no window is associated with the command\. .sp Note, the first 5 variables may include any kind of characters, so these variables are quoted\. It means that the value is surrounded by single quote characters and any contained single quote is prefixed with a backslash\. This guarantees that commands like: .sp .RS 4 .nf \fBStyle\fR $[w\.resource] \fIIcon\fR norm/network\.png .fi .RE .sp work correctly, regardless of any special symbols the value may contain, like spaces and different kinds of quotes\. .sp In the case of the window's visible name, this is the value returned from the literal title of the window shown in the titlebar\. Typically this will be the same as $[w\.name] once expanded, although in the case of using \fIIndexedWindowName\fR then this is more useful a distinction, and allows for referencing the specific window by its visible name for inclusion in things like \fBStyle\fR commands\. .RE .PP $[w\.x] $[w\.y] $[w\.width] $[w\.height] .RS 4 Either coordinate or the width or height of the current window if it is not iconified\. If no window is associated with the command or the window is iconified, the string is left as is\. .RE .PP $[w\.desk] .RS 4 The number of the desk on which the window is shown\. If the window is sticky the current desk number is used\. .RE .PP $[w\.layer] .RS 4 The layer of the window\. .RE .PP $[w\.screen] .RS 4 The screen number the window is on\. If Xinerama is not present, this returns the number 0\. .RE .PP $[cw\.x] $[cw\.y] $[cw\.width] $[cw\.height] .RS 4 These work like $[w\.\.\.\.] but return the geometry of the client part of the window\. In other words: the border and title of the window is not taken into account\. .RE .PP $[i\.x], $[it\.x], $[ip\.x] $[i\.y], $[it\.y], $[ip\.y] $[i\.width], $[it\.width], $[ip\.width] $[i\.height], $[it\.height], $[ip\.height] .RS 4 These work like $[w\.\.\.\.] but return the geometry of the icon ($[i\.\.\.\.]), the icon title ($[it\.\.\.\.]) or the icon picture ($[ip\.\.\.\.])\. .RE .PP $[pointer\.x] $[pointer\.y] .RS 4 These return the position of the pointer on the screen\. If the pointer is not on the screen, these variables are not expanded\. .RE .PP $[pointer\.wx] $[pointer\.wy] .RS 4 These return the position of the pointer in the selected window\. If the pointer is not on the screen, the window is iconified or no window is selected, these variables are not expanded\. .RE .PP $[pointer\.cx] $[pointer\.cy] .RS 4 These return the position of the pointer in the client portion of the selected window\. If the pointer is not on the screen, the window is shaded or iconified or no window is selected, these variables are not expanded\. .RE .PP $[pointer\.screen] .RS 4 The screen number the pointer is currently on\. Returns 0 if Xinerama is not enabled\. .RE .PP $[screen] .RS 4 The screen number fvwm is running on\. Useful for setups with multiple screens\. .RE .PP $[fg\.cs] $[bg\.cs] $[hilight\.cs] $[shadow\.cs] .RS 4 These parameters are replaced with the name of the foreground (fg), background (bg), hilight (hilight) or shadow (shadow) color that is defined in colorset (replace with zero or a positive integer)\. For example "$[fg\.cs3]" is expanded to the name of the foreground color of colorset 3 (in rgb:rrrr/gggg/bbbb form)\. Please refer to the \fBColorsets\fR section for details about colorsets\. .RE .PP $[schedule\.last] .RS 4 This is replaced by the id of the last command that was scheduled with the \fBSchedule\fR command, even if this command was already executed\. .RE .PP $[schedule\.next] .RS 4 This is replaced by the id the next command used with \fBSchedule\fR will get (unless a different id is specified explicitly)\. .RE .PP $[cond\.rc] .RS 4 The return code of the last conditional command\. This variable is only valid inside a function and can not be used in a conditional command\. Please refer to the section \fBConditional Commands\fR in the command list\. .RE .PP $[func\.context] .RS 4 The context character of the running command as used in the \fBMouse\fR, \fBKey\fR or \fBPointerKey\fR command\. This is useful for example with: .sp .RS 4 .nf \fBMouse\fR 3 FS N \fBWindowShade\fR $$[func\.context] .fi .RE .sp .RE .PP $[gt\.\fIstr\fR] .RS 4 return the translation of \fIstr\fR by looking in the current locale catalogs\. If no translation is found \fIstr\fR is returned as is\. See the \fBLocalePath\fR command\. .RE .PP $[infostore\.\fIkey\fR] .RS 4 Return the value of the item stored in the InfoStore at the given \fIkey\fR\. If no key is present, the unexpanded string is returned\. .RE .PP $[\.\.\.] .RS 4 If the string within the braces is neither of the above, fvwm tries to find an environment variable with this name and replaces its value if one is found (e\.g\. "$[PAGER]" could be replaced by "more")\. Otherwise the string is left as is\. .RE .PP Some examples can be found in the description of the \fBAddToFunc\fR command\. .SH SCRIPTING & COMPLEX FUNCTIONS .PP To achieve the more complex effects, fvwm has a number of commands that improve its scripting abilities\. Scripts can be read from a file with \fBRead\fR, from the output of a command with \fBPipeRead\fR or written as a complex function with the \fBAddToFunc\fR command\. For the curious, section 7 of the fvwm FAQ shows some real life applications of scripting\. Please refer to the sections \fBUser Functions and Shell Commands\fR and \fBConditional Commands\fR for details\. A word of warning: during execution of complex functions, fvwm needs to take all input from the mouse pointer (the pointer is "grabbed" in the slang of X)\. No other programs can receive any input from the pointer while a function is run\. This can confuse some programs\. For example, the xwd program refuses to make screen shots when run from a complex function\. To achieve the same functionality you can use the \fBRead\fR or \fBPipeRead\fR command instead\. .SH LIST OF FVWM COMMANDS .PP The command descriptions below are grouped together in the following sections\. The sections are hopefully sorted in order of usefulness to the newcomer\. .sp .RS 4 \h'-04'\(bu\h'+03'\fBMenu commands\fR .sp .RE .sp .RS 4 \h'-04'\(bu\h'+03'\fBMiscellaneous commands\fR .sp .RE .sp .RS 4 \h'-04'\(bu\h'+03'\fBCommands affecting window movement and placement\fR .sp .RE .sp .RS 4 \h'-04'\(bu\h'+03'\fBCommands for focus and mouse movement\fR .sp .RE .sp .RS 4 \h'-04'\(bu\h'+03'\fBCommands controlling window state\fR .sp .RE .sp .RS 4 \h'-04'\(bu\h'+03'\fBCommands for mouse, key and stroke bindings\fR .sp .RE .sp .RS 4 \h'-04'\(bu\h'+03'\fBThe Style command (controlling window styles)\fR .sp .RE .sp .RS 4 \h'-04'\(bu\h'+03'\fBOther commands controlling window styles\fR .sp .RE .sp .RS 4 \h'-04'\(bu\h'+03'\fBCommands controlling the virtual desktop\fR .sp .RE .sp .RS 4 \h'-04'\(bu\h'+03'\fBCommands for user functions and shell commands\fR .sp .RE .sp .RS 4 \h'-04'\(bu\h'+03'\fBConditional commands\fR .sp .RE .sp .RS 4 \h'-04'\(bu\h'+03'\fBModule commands\fR .sp .RE .sp .RS 4 \h'-04'\(bu\h'+03'\fBQuit, restart and session management commands\fR .sp .RE .sp .RS 4 \h'-04'\(bu\h'+03'\fBColorsets\fR .sp .RE .sp .RS 4 \h'-04'\(bu\h'+03'\fBColor gradients\fR .sp .RE .SS Menus .PP Before a menu can be opened, it has to be populated with menu items using the \fBAddToMenu\fR command and bound to a key or mouse button with the \fBKey\fR, \fBPointerKey\fR or \fBMouse\fR command (there are many other ways to invoke a menu too)\. This is usually done in the configuration file\. .PP Fvwm menus are extremely configurable in look and feel\. Even the slightest nuances can be changed to the user's liking, including the menu item fonts, the background, delays before popping up sub menus, generating menus dynamically and many other features\. Please refer to the \fBMenuStyle\fR command to learn more\. .TP .B Types of Menus .RS .\".PP In fvwm there are four slightly different types of menus: .PP \fBPopup\fR menus can appear everywhere on the screen on their own or attached to a part of a window\. The \fBPopup\fR command opens popup menus\. If the popup menu was invoked with a mouse button held down, it is closed when the button is released\. The item under the pointer is then activated and the associated action is executed\. .PP \fBMenu\fR is a very similar command, but the menus it opens are slightly less transient\. When invoked by clicking a mouse button, it stays open and can be navigated with no button held\. But if it is invoked by a button press followed by mouse motion, it behaves exactly like a popup menu\. .PP \fITear off menus\fR or \fIPin up menus\fR are menus from either of the above two commands that have been "torn off" their original context and pinned on the desktop like a normal window\. They are created from other menus by certain key presses or mouse sequences or with the \fBTearMenuOff\fR command from inside a menu\. .PP \fISub menus\fR are menus inside menus\. When a menu item that has the \fBPopup\fR command as its action is selected, the named menu is opened as an inferior menu to the parent\. Any type of menu can have sub menus\. .RE .TP .B Menu Anatomy .RS .\".PP Menus consist of any number of titles which are inactive menu items that usually appear at the top of the menu, normal items triggering various actions when selected, separator lines between the items, tear off bars (a horizontal broken line) that tear off the menu when selected, and sub menu items indicated with a triangle pointing left or right, depending on the direction in which the sub menu appears\. All the above menu items are optional\. .PP Additionally, if the menu is too long to fit on the screen, the excess menu items are put in a continuation menu and a sub menu with the string "More\.\.\." is placed at the bottom of the menu\. The "More\.\.\." string honors the locale settings\. .PP Finally, there may be a picture running up either side of the menu (a "side bar")\. .RE .TP .B Menu Navigation .RS .\".PP Menus can be navigated either with the keyboard or with the mouse\. Many people prefer to use the mouse, but it can be rather tedious\. Once you get the hang of it, keyboard navigation can be much faster\. While fvwm displays a menu, it can do nothing else\. For example, new windows do not appear before the menu is closed\. However, this is not exactly true for tear off menus\. See the \fBTear Off Menus\fR section for details\. .RE .TP .B Mouse Navigation .RS .\".PP Moving the pointer over a menu selects the item below it\. Normally this is indicated by a 3d border around the item, but not all parts of a menu can be selected\. Pressing any mouse button while a menu is open by default activates the item below it\. Items of a popup menu are also activated by releasing a held mouse button\. In case of an item that hides a sub menu, the sub menu is displayed if the pointer hovers over the item long enough or moves close to the triangle indicating the sub menu\. This behaviour can be tuned with menu styles\. .PP Scrolling a mouse wheel over a menu either wraps the pointer along the menu (default), scrolls the menu under the pointer or act as if the menu was clicked depending on the \fIMouseWheel\fR menu style\. .PP Clicking on a selected item activates it \- what happens exactly depends on the type of the item\. .PP Clicking on a title, a separator, the side bar, or outside the menu closes the menu (exception: tear off menus can not be closed this way)\. Pressing mouse button 2 over a menu title or activating a tear off bar creates a tear off menu from the current menu\. Clicking on a normal menu item invokes the command that is bound to it, and clicking on a sub menu item either closes all open menus and replaces them with the sub menu or posts the menu (default)\. .PP Posting menus is meant to ease mouse navigation\. Once a sub menu is posted, only items from that sub menu can be selected\. This can be very useful to navigate the menu if the pointer tends to stray off the menu\. To unpost the menu and revert back to normal operation, either click on the same sub menu item or press any key\. .RE .TP .B Keyboard Navigation .RS .\".PP Just like with mouse navigation, the item below the pointer is selected\. This is achieved by warping the pointer to the menu items when necessary\. While a menu is open, all key presses are intercepted by the menu\. No other application can get keyboard input (although this is not the case for tear off menus)\. .PP Items can be selected directly by pressing a hotkey that can be configured individually for each menu item\. The hotkey is indicated by underlining it in the menu item label\. With the \fIAutomaticHotkeys\fR menu style fvwm automatically assigns hotkeys to all menu items\. .PP The most basic keys to navigate through menus are the cursor keys (move up or down one item, enter or leave a sub menu), .SM Space (activate item) and .SM Escape (close menu)\. Numerous other keys can be used to navigate through menus by default: .PP \fIEnter\fR, \fIReturn\fR, \fISpace\fR activate the current item\. .PP \fIEscape\fR, \fIDelete\fR, \fICtrl\-G\fR exit the current sequence of menus or destroy a tear off menu\. .PP \fIJ\fR, \fIN\fR, \fICursor\-Down\fR, \fITab\fR, \fIMeta\-Tab\fR, \fICtrl\-F\fR, move to the next item\. .PP \fIK\fR, \fIP\fR, \fICursor\-Up\fR, \fIShift\-Tab\fR, \fIShift\-Meta\-Tab\fR, \fICtrl\-B\fR, move to the prior item\. .PP \fIL\fR, \fICursor\-Right\fR, \fIF\fR enter a sub menu\. .PP \fIH\fR, \fICursor\-Left\fR, \fIB\fR return to the prior menu\. .PP \fICtrl\-Cursor\-Up\fR, \fICtrl\-K\fR \fICtrl\-P\fR, \fIShift\-Ctrl\-Meta\-Tab\fR, \fIPage\-Up\fR move up five items\. .PP \fICtrl\-Cursor\-Down\fR, \fICtrl\-J\fR \fICtrl\-N\fR, \fICtrl\-Meta\-Tab\fR \fIPage\-Down\fR move down five items\. .PP \fIShift\-P\fR, \fIHome\fR, \fIShift\-Cursor\-Up\fR, \fICtrl\-A\fR move to the first item\. .PP \fIShift\-N\fR, \fIEnd\fR, \fIShift\-Cursor\-Down\fR, \fICtrl\-E\fR move to the last item\. .PP \fIMeta\-P\fR, \fIMeta\-Cursor\-Up\fR, \fICtrl\-Cursor\-Left\fR, \fIShift\-Ctrl\-Tab\fR, move up just below the next separator\. .PP \fIMeta\-N\fR, \fIMeta\-Cursor\-Down\fR, \fICtrl\-Cursor\-Right\fR, \fICtrl\-Tab\fR, move down just below the next separator\. .PP \fIInsert\fR opens the "More\.\.\." sub menu if any\. .PP \fIBackspace\fR tears off the menu\. .RE .TP .B Menu Bindings .RS .\".PP The keys and mouse buttons used to navigate the menu can be configured using the \fBKey\fR and \fBMouse\fR commands with the special context 'M', possible combined with 'T' for the menu title, 'I' for other menu items, 'S' for any border or sidepic, '[' for left border including a left sidepic, ']' for right border including a right sidepic, '\-' for top border, '_' for bottom border\. The menu context uses its own set of actions that can be bound to keys and mouse buttons\. These are \fIMenuClose\fR, \fIMenuCloseAndExec\fR, \fIMenuEnterContinuation\fR, \fIMenuEnterSubmenu\fR, \fIMenuLeaveSubmenu\fR, \fIMenuMoveCursor\fR, \fIMenuCursorLeft\fR, \fIMenuCursorRight\fR, \fIMenuSelectItem\fR, \fIMenuScroll\fR and \fIMenuTearOff\fR\. .PP It is not possible to override the key Escape with no modifiers for closing the menu\. Neither is it possible to undefine mouse button 1, the arrow keys or the enter key for minimal navigation\. .PP \fBMenuClose\fR exits from the current sequence of menus or destroys a tear off menu\. .PP \fBMenuCloseAndExec\fR exits from the current sequence of menus or destroys a tear off menu and executes the rest of the line as a command\. .PP \fBMenuEnterContinuation\fR opens the "More\.\.\." sub menu if any\. .PP \fBMenuEnterSubmenu\fR enters a sub menu\. .PP \fBMenuLeaveSubmenu\fR returns to the prior menu\. .PP \fBMenuMoveCursor\fR \fIn\fR [\fIm\fR] moves the selection to another item\. If the first argument is zero the second argument specifies an absolute item in the menu to move the pointer to\. Negative items are counted from the end of the menu\. If the first argument is non\-zero, the second argument must be omitted, and the first argument specifies a relative change in the selected item\. The positions may be suffixed with a 's' to indicate that the items should refer only to the first items after separators\. .PP \fBMenuCursorLeft\fR enters a sub menu with the \fISubmenusLeft\fR menu style, and returns to the prior menu with the \fISubmenusRight\fR menu style\. .PP \fBMenuCursorRight\fR enters a sub menu with the \fISubmenusRight\fR menu style, and returns to the prior menu with the \fISubmenusLeft\fR menu style\. .PP \fBMenuSelectItem\fR triggers the action for the menu item\. .PP \fBMenuScroll \fR\fIn\fR performs menu scrolling according to the \fIMouseWheel\fR menu style with \fIn\fR items\. The distance can be suffixed with an 's' to indicate the items should refer only to the first items after separators\. .PP \fBMenuTearOff\fR turns a normal menu into a "torn off" menu\. See \fBTear Off Menus\fR for details\. .RE .TP .B Tear Off Menus .RS .\".PP A tear off menu is any menu that has been "torn off" the window it was attached to and pinned to the root window\. There are three ways to tear off a menu: click on the menu title with mouse button 2, press .SM Backspace in the menu or activate its tear off bar (a horizontal bar with a broken line)\. Tear off bars must be added to the menu as any other item by assigning them the command \fBTearMenuOff\fR\. .PP The builtin tear off actions can be overridden by undefining the builtin menu actions bound to tear off\. To remove the builtin mouse button 2 binding, use: .sp .RS 4 .nf \fBMouse\fR 2 MT A \- .fi .RE .PP and to remove the builtin backspace binding, use: .sp .RS 4 .nf \fBKey\fR Backspace M A \- .fi .RE .PP See the section \fBMenu Bindings\fR for details on how to assign other bindings for tear off\. .PP Note that prior to fvwm 2\.5\.20 the tear off mouse bindings were redefined in different way, which no longer work\. .PP The window containing the menu is placed as any other window would be\. If you find it confusing to have your tear off menus appear at random positions on the screen, put this line in your configuration file: .sp .RS 4 .nf \fBStyle\fR fvwm_menu \fIUsePPosition\fR .fi .RE .PP To remove borders and buttons from a tear\-off menu but keep the menu title, you can use .sp .RS 4 .nf \fBStyle\fR fvwm_menu !\fIButton\fR 0, !\fIButton\fR 1 \fBStyle\fR fvwm_menu !\fIButton\fR 2, !\fIButton\fR 3 \fBStyle\fR fvwm_menu !\fIButton\fR 4, !\fIButton\fR 5 \fBStyle\fR fvwm_menu !\fIButton\fR 6, !\fIButton\fR 7 \fBStyle\fR fvwm_menu !\fIButton\fR 8, !\fIButton\fR 9 \fBStyle\fR fvwm_menu \fITitle\fR, \fIHandleWidth\fR 0 .fi .RE .PP A tear off menu is a cross breeding between a window and a menu\. The menu is swallowed by a window and its title is stripped off and displayed in the window title\. The main advantage is that the menu becomes permanent \- activating an item does not close the menu\. Therefore, it can be used multiple times without reopening it\. To destroy such a menu, close its window or press the .SM Escape key\. .PP Tear off menus behave somewhat differently than normal menus and windows\. They do not take the keyboard focus, but while the pointer is over one of them, all key presses are sent to the menu\. Other fvwm key bindings are disabled as long as the pointer is inside the tear off menu or one of its sub menus\. When the pointer leaves this area, all sub menus are closed immediately\. Note that the window containing a tear off menu is never hilighted as if it had the focus\. .PP A tear off menu is an independent copy of the menu it originated from\. As such, it is not affected by adding items to that menu or changing its menu style\. .PP To create a tear off menu without opening the normal menu first, the option \fITearOffImmediately\fR can be added to the \fBMenu\fR or \fBPopup\fR command\. .RE .TP \fBAddToMenu\fR \fImenu\-name\fR [\fImenu\-label\fR\ \fIaction\fR] .RS .\".PP Begins or adds to a menu definition\. Typically a menu definition looks like this: .sp .RS 4 .nf AddToMenu Utilities Utilities \fBTitle\fR + Xterm \fBExec\fR exec xterm \-e tcsh + Rxvt \fBExec\fR exec rxvt + "Remote Logins" \fBPopup\fR Remote\-Logins + Top \fBExec\fR exec rxvt \-T Top \-n Top \-e top + Calculator \fBExec\fR exec xcalc + Xman \fBExec\fR exec xman + Xmag \fBExec\fR exec xmag + emacs \fBExec\fR exec xemacs + Mail MailFunction xmh "\-font fixed" + "" \fBNop\fR + Modules \fBPopup\fR Module\-Popup + "" \fBNop\fR + Exit Fvwm \fBPopup\fR Quit\-Verify .fi .RE .PP The menu could be invoked via .sp .RS 4 .nf \fBMouse\fR 1 R A \fBMenu\fR Utilities Nop .fi .RE .PP or .sp .RS 4 .nf \fBMouse\fR 1 R A \fBPopup\fR Utilities .fi .RE .PP There is no end\-of\-menu symbol\. Menus do not have to be defined in a contiguous region of the \fIconfig\fR file\. The quoted (or first word) portion in the above examples is the menu label, which appears in the menu when the user pops it up\. The remaining portion is an fvwm command which is executed if the user selects that menu item\. An empty menu\-label ("") and the \fBNop\fR function are used to insert a separator into the menu\. .PP The keywords \fIDynamicPopUpAction\fR and \fIDynamicPopDownAction\fR have a special meaning when used as the name of a menu item\. The action following the keyword is executed whenever the menu is popped up or down\. This way you can implement dynamic menus\. It is even possible to destroy itself with \fBDestroyMenu\fR and the rebuild from scratch\. When the menu has been destroyed (unless you used the \fIrecreate\fR option when destroying the menu), do not forget to add the dynamic action again\. .PP Note: Do not trigger actions that require user interaction\. They may fail and may screw up your menus\. See the \fBSilent\fR command\. .sp .it 1 an-trap .nr an-no-space-flag 1 .nr an-break-flag 1 .br \fBWarning\fR Do not issue \fBMenuStyle\fR commands as dynamic menu actions\. Chances are good that this crashes fvwm\. .PP There are several configurable scripts installed together with fvwm for automatic menu generation\. They have their own man pages\. Some of them, specifically \fBfvwm\-menu\-directory\fR and \fBfvwm\-menu\-desktop\fR, may be used with \fIDynamicPopupAction\fR to create a directory listing or GNOME/KDE application listing\. .PP Example (File browser): .sp .RS 4 .nf # You can find the shell script fvwm_make_browse_menu\.sh # in the utils/ directory of the distribution\. AddToMenu BrowseMenu + DynamicPopupAction \fBPipeRead\fR \e 'fvwm_make_browse_menu\.sh BrowseMenu' .fi .RE .PP Example (Picture menu): .sp .RS 4 .nf # Build a menu of all \.jpg files in # $HOME/Pictures AddToMenu JpgMenu foo title + DynamicPopupAction \fBFunction\fR MakeJpgMenu \fBAddToFunc\fR MakeJpgMenu + I \fBDestroyMenu\fR recreate JpgMenu + I AddToMenu JpgMenu Pictures \fBTitle\fR + I \fBPipeRead\fR 'for i in \fI$HOME\fR/Pictures/*\.jpg; \e do echo AddToMenu JpgMenu "`basename $i`" \fBExec\fR xv $i; done' .fi .RE .PP The keyword \fIMissingSubmenuFunction\fR has a similar meaning\. It is executed whenever you try to pop up a sub menu that does not exist\. With this function you can define and destroy menus on the fly\. You can use any command after the keyword, but if the name of an item (that is a submenu) defined with \fBAddToFunc\fR follows it, fvwm executes this command: .sp .RS 4 .nf \fBFunction\fR .fi .RE .PP i\.e\. the name is passed to the function as its first argument and can be referred to with "$0"\. .PP The \fBfvwm\-menu\-directory\fR script mentioned above may be used with \fIMissingSubmenuFunction\fR to create an up to date recursive directory listing\. .PP Example: .sp .RS 4 .nf # There is another shell script fvwm_make_directory_menu\.sh # in the utils/ directory of the distribution\. To use it, # define this function in your configuration file: \fBDestroyFunc\fR MakeMissingDirectoryMenu \fBAddToFunc\fR MakeMissingDirectoryMenu + I \fBPipeRead\fR fvwm_make_directory_menu\.sh $0 \fBDestroyMenu\fR SomeMenu AddToMenu SomeMenu + MissingSubmenuFunction MakeMissingDirectoryMenu + "Root directory" \fBPopup\fR / .fi .RE .PP This is another implementation of the file browser that uses sub menus for subdirectories\. .PP Titles can be used within the menu\. If you add the option \fItop\fR behind the keyword \fBTitle\fR, the title is added to the top of the menu\. If there was a title already, it is overwritten\. .sp .RS 4 .nf AddToMenu Utilities Tools Title top .fi .RE .PP All text up to the first .SM Tab in the menu label is aligned to the left side of the menu, all text right of the first .SM Tab is aligned to the left in a second column and all text thereafter is placed right aligned in the third column\. All other .SM Tab s are replaced by spaces\. Note that you can change this format with the \fIItemFormat\fR option of the \fBMenuStyle\fR command\. .PP If the menu\-label contains an ampersand ('&'), the next character is taken as a hot\-key for the menu item\. Hot\-keys are underlined in the label\. To get a literal '&', insert "&&"\. Pressing the hot\-key moves through the list of menu items with this hot\-key or selects an item that is the only one with this hot\-key\. .PP If the menu\-label contains a sub\-string which is set off by stars, then the text between the stars is expected to be the name of an image file to insert in the menu\. To get a literal '*', insert "**"\. For example .sp .RS 4 .nf + Calculator*xcalc\.xpm* \fBExec\fR exec xcalc .fi .RE .PP inserts a menu item labeled "Calculator" with a picture of a calculator above it\. The following: .sp .RS 4 .nf + *xcalc\.xpm* \fBExec\fR exec xcalc .fi .RE .PP Omits the "Calculator" label, but leaves the picture\. .PP If the menu\-label contains a sub\-string which is set off by percent signs, then the text between the percent signs is expected to be the name of image file (a so called mini icon to insert to the left of the menu label\. A second mini icon that is drawn at the right side of the menu can be given in the same way\. To get a literal '%', insert "%%"\. For example .sp .RS 4 .nf + Calculator%xcalc\.xpm% \fBExec\fR exec xcalc .fi .RE .PP inserts a menu item labeled "Calculator" with a picture of a calculator to the left\. The following: .sp .RS 4 .nf + %xcalc\.xpm% \fBExec\fR exec xcalc .fi .RE .PP Omits the "Calculator" label, but leaves the picture\. The pictures used with this feature should be small (perhaps 16x16)\. .PP If the menu\-name (not the label) contains a sub\-string which is set off by at signs ('@'), then the text between them is expected to be the name of an image file to draw along the left side of the menu (a side pixmap)\. You may want to use the \fISidePic\fR option of the \fBMenuStyle\fR command instead\. To get a literal '@', insert "@@"\. For example .sp .RS 4 .nf AddToMenu StartMenu@linux\-menu\.xpm@ .fi .RE .PP creates a menu with a picture in its bottom left corner\. .PP If the menu\-name also contains a sub\-string surrounded by '^'s, then the text between '^'s is expected to be the name of an X11 color and the column containing the side picture is colored with that color\. You can set this color for a menu style using the \fISideColor\fR option of the \fBMenuStyle\fR command\. To get a literal '^', insert "^^"\. Example: .sp .RS 4 .nf AddToMenu StartMenu@linux\-menu\.xpm@^blue^ .fi .RE .PP creates a menu with a picture in its bottom left corner and colors with blue the region of the menu containing the picture\. .PP In all the above cases, the name of the resulting menu is name specified, stripped of the substrings between the various delimiters\. .RE .TP \fBChangeMenuStyle\fR \fImenustyle\fR \fImenu\fR ... .RS .\".PP Changes the menu style of \fImenu\fR to \fImenustyle\fR\. You may specify more than one menu in each call of \fBChangeMenuStyle\fR\. .RE .TP \fBCopyMenuStyle\fR \fIorig\-menustyle\fR \fIdest\-menustyle\fR .RS .\".PP Copy \fIorig\-menustyle\fR to \fIdest\-menustyle\fR, where \fIorig\-menustyle\fR is an existing menu style\. If the menu style \fIdest_menustyle\fR does not exist, then it is created\. .RE .TP \fBDestroyMenu\fR [recreate] \fImenu\fR .RS .\".PP Deletes a menu, so that subsequent references to it are no longer valid\. You can use this to change the contents of a menu during an fvwm session\. The menu can be rebuilt using \fBAddToMenu\fR\. The optional parameter \fIrecreate\fR tells fvwm not to throw away the menu completely but to throw away all the menu items (including the title)\. .sp .RS 4 .nf DestroyMenu Utilities .fi .RE .RE .TP \fBDestroyMenuStyle\fR \fImenustyle\fR .RS .\".PP Deletes the menu style named \fImenustyle\fR and changes all menus using this style to the default style, you cannot destroy the default menu style\. .sp .RS 4 .nf DestroyMenuStyle pixmap1 .fi .RE .RE .TP \fBMenu\fR \fImenu\-name\fR [\fIposition\fR] [\fIdouble\-click\-action\fR] .RS .\".PP Causes a previously defined menu to be popped up in a sticky manner\. That is, if the user invokes the menu with a click action instead of a drag action, the menu stays up\. The command \fIdouble\-click\-action\fR is invoked if the user double\-clicks a button (or hits the key rapidly twice if the menu is bound to a key) when bringing up the menu\. If the double click action is not specified, double clicking on the menu does nothing\. However, if the menu begins with a menu item (i\.e\. not with a title or a separator) and the double click action is not given, double clicking invokes the first item of the menu (but only if the pointer really was over the item)\. .PP The pointer is warped to where it was when the menu was invoked if it was both invoked and closed with a keystroke\. .PP The \fIposition\fR arguments allow placement of the menu somewhere on the screen, for example centered on the visible screen or above a title bar\. Basically it works like this: you specify a \fIcontext\-rectangle\fR and an offset to this rectangle by which the upper left corner of the menu is moved from the upper left corner of the rectangle\. The \fIposition\fR arguments consist of several parts: .HP 1 [\fIcontext\-rectangle\fR] \fIx\fR \fIy\fR [\fIspecial\-options\fR] .PP The \fIcontext\-rectangle\fR can be one of: .PP \fIRoot\fR .RS 4 the root window of the current screen\. .RE .PP \fIXineramaRoot\fR .RS 4 the root window of the whole Xinerama screen\. Equivalent to "root" when Xinerama is not used\. .RE .PP \fIMouse\fR .RS 4 a 1x1 rectangle at the mouse position\. .RE .PP \fIWindow\fR .RS 4 the frame of the context window\. .RE .PP \fIInterior\fR .RS 4 the inside of the context window\. .RE .PP \fITitle\fR .RS 4 the title of the context window or icon\. .RE .PP \fIButton\fR .RS 4 button #n of the context window\. .RE .PP \fIIcon\fR .RS 4 the icon of the context window\. .RE .PP \fIMenu\fR .RS 4 the current menu\. .RE .PP \fIItem\fR .RS 4 the current menu item\. .RE .PP \fIContext\fR .RS 4 the current window, menu or icon\. .RE .PP \fIThis\fR .RS 4 whatever widget the pointer is on (e\.g\. a corner of a window or the root window)\. .RE .PP \fIRectangle\fR <\fIgeometry\fR> .RS 4 the rectangle defined by <\fIgeometry\fR> in X geometry format\. Width and height default to 1 if omitted\. .RE .PP If the context\-rectangle is omitted or illegal (e\.g\. "item" on a window), "Mouse" is the default\. Note that not all of these make sense under all circumstances (e\.g\. "Icon" if the pointer is on a menu)\. .PP The offset values \fIx\fR and \fIy\fR specify how far the menu is moved from its default position\. By default, the numeric value given is interpreted as a percentage of the context rectangle's width (height), but with a trailing '\fIm\fR' the menu's width (height) is used instead\. Furthermore a trailing '\fIp\fR' changes the interpretation to mean pixels\. .PP Instead of a single value you can use a list of values\. All additional numbers after the first one are separated from their predecessor by their sign\. Do not use any other separators\. .PP If \fIx\fR or \fIy\fR are prefixed with "'\fIo\fR" where is an integer, the menu and the rectangle are moved to overlap at the specified position before any other offsets are applied\. The menu and the rectangle are placed so that the pixel at percent of the rectangle's width/height is right over the pixel at percent of the menu's width/height\. So "o0" means that the top/left borders of the menu and the rectangle overlap, with "o100" it's the bottom/right borders and if you use "o50" they are centered upon each other (try it and you will see it is much simpler than this description)\. The default is "o0"\. The prefix "o" is an abbreviation for "+\-m"\. .PP A prefix of '\fIc\fR' is equivalent to "o50"\. Examples: .sp .RS 4 .nf # window list in the middle of the screen \fBWindowList\fR Root c c # menu to the left of a window Menu name window \-100m c+0 # popup menu 8 pixels above the mouse pointer \fBPopup\fR name mouse c \-100m\-8p # somewhere on the screen Menu name rectangle 512x384+1+1 +0 +0 # centered vertically around a menu item \fBAddToMenu\fR foobar\-menu + "first item" \fBNop\fR + "special item" \fBPopup\fR "another menu" item +100 c + "last item" \fBNop\fR # above the first menu item \fBAddToMenu\fR foobar\-menu + "first item" \fBPopup\fR "another menu" item +0 \-100m .fi .RE .PP Note that you can put a sub menu far off the current menu so you could not reach it with the mouse without leaving the menu\. If the pointer leaves the current menu in the general direction of the sub menu the menu stays up\. .PP The \fIspecial\-options\fR: .PP To create a tear off menu without opening the normal menu, add the option \fITearOffImmediately\fR\. Normally the menu opens in normal state for a split second before being torn off\. As tearing off places the menu like any other window, a position should be specified explicitly: .sp .RS 4 .nf # Forbid fvwm to place the menu window \fBStyle\fR UsePPosition # Menu at top left corner of screen Menu Root 0p 0p TearOffImmediately .fi .RE .PP The \fIAnimated\fR and \fIMwm\fR or \fIWin\fR menu styles may move a menu somewhere else on the screen\. If you do not want this you can add \fIFixed\fR as an option\. This might happen for example if you want the menu always in the top right corner of the screen\. .PP Where do you want a menu to appear when you click on its menu item? The default is to place the title under the cursor, but if you want it where the position arguments say, use the \fISelectInPlace\fR option\. If you want the pointer on the title of the menu, use \fISelectWarp\fR too\. Note that these options apply only if the \fIPopupAsRootMenu\fR \fBMenuStyle\fR option is used\. .PP The pointer is warped to the title of a sub menu whenever the pointer would be on an item when the sub menu is popped up (\fIfvwm\fR menu style) or never warped to the title at all (\fIMwm\fR or \fIWin\fR menu styles)\. You can force (forbid) warping whenever the sub menu is opened with the \fIWarpTitle\fR (\fINoWarp\fR) option\. .PP Note that the \fIspecial\-options\fR do work with a normal menu that has no other position arguments\. .RE .TP \fBMenuStyle\fR \fIstylename\fR [\fIoptions\fR] .RS .\".PP Sets a new menu style or changes a previously defined style\. The \fIstylename\fR is the style name; if it contains spaces or tabs it has to be quoted\. The name "*" is reserved for the default menu style\. The default menu style is used for every menu\-like object (e\.g\. the window created by the \fBWindowList\fR command) that had not be assigned a style using the \fBChangeMenuStyle\fR\. See also \fBDestroyMenuStyle\fR\. When using monochrome color options are ignored\. .PP \fIoptions\fR is a comma separated list containing some of the keywords Fvwm / Mwm / Win, BorderWidth, Foreground, Background, Greyed, HilightBack / !HilightBack, HilightTitleBack, ActiveFore / !ActiveFore, MenuColorset, ActiveColorset, GreyedColorset, TitleColorset, Hilight3DThick / Hilight3DThin / Hilight3DOff, Hilight3DThickness, Animation / !Animation, Font, TitleFont, MenuFace, PopupDelay, PopupOffset, TitleWarp / !TitleWarp, TitleUnderlines0 / TitleUnderlines1 / TitleUnderlines2, SeparatorsLong / SeparatorsShort, TrianglesSolid / TrianglesRelief, PopupImmediately / PopupDelayed, PopdownImmediately / PopdownDelayed, PopupActiveArea, DoubleClickTime, SidePic, SideColor, PopupAsRootMenu / PopupAsSubmenu / PopupIgnore / PopupClose, RemoveSubmenus / HoldSubmenus, SubmenusRight / SubmenusLeft, SelectOnRelease, ItemFormat, VerticalItemSpacing, VerticalMargins, VerticalTitleSpacing, AutomaticHotkeys / !AutomaticHotkeys, UniqueHotkeyActivatesImmediate / !UniqueHotkeyActivatesImmediate, MouseWheel, ScrollOffPage / !ScrollOffPage, TrianglesUseFore / !TrianglesUseFore\. .PP In the above list some options are listed as option pairs or triples with a '/' in between\. These options exclude each other\. All paired options can be negated to have the effect of the counterpart option by prefixing ! to the option\. .PP Some options are now negated by prefixing ! to the option\. This is the preferred form for all such options\. The other negative forms are now deprecated and will be removed in the future\. .PP This is a list of MenuStyle deprecated negative options: ActiveForeOff, AnimationOff, AutomaticHotkeysOff, HilightBackOff, TitleWarpOff .PP \fIFvwm\fR, \fIMwm\fR, \fIWin\fR reset all options to the style with the same name in former versions of fvwm\. The default for new menu styles is \fIFvwm\fR style\. These options override all others except \fIForeground\fR, \fIBackground\fR, \fIGreyed\fR, \fIHilightBack\fR, \fIActiveFore\fR and \fIPopupDelay\fR, so they should be used only as the first option specified for a menu style or to reset the style to defined behavior\. The same effect can be created by setting all the other options one by one\. .PP \fIMwm\fR and \fIWin\fR style menus popup sub menus automatically\. \fIWin\fR menus indicate the current menu item by changing the background to dark\. \fIFvwm\fR sub menus overlap the parent menu, \fIMwm\fR and \fIWin\fR style menus never overlap the parent menu\. .PP \fIFvwm\fR style is equivalent to !HilightBack, Hilight3DThin, !ActiveFore, !Animation, Font, MenuFace, PopupOffset 0 67, TitleWarp, TitleUnderlines1, SeparatorsShort, TrianglesRelief, PopupDelayed, PopdownDelayed, PopupDelay 150, PopdownDelay 150, PopupAsSubmenu, HoldSubmenus, SubmenusRight, BorderWidth 2, !AutomaticHotkeys, UniqueHotkeyActivatesImmediate, PopupActiveArea 75\. .PP \fIMwm\fR style is equivalent to !HilightBack, Hilight3DThick, !ActiveFore, !Animation, Font, MenuFace, PopupOffset \-3 100, !TitleWarp, TitleUnderlines2, SeparatorsLong, TrianglesRelief, PopupImmediately, PopdownDelayed, PopdownDelay 150, PopupAsSubmenu, HoldSubmenus, SubmenusRight, BorderWidth 2, UniqueHotkeyActivatesImmediate, !AutomaticHotkeys, PopupActiveArea 75\. .PP \fIWin\fR style is equivalent to HilightBack, Hilight3DOff, ActiveFore, !Animation, Font, MenuFace, PopupOffset \-5 100, !TitleWarp, TitleUnderlines1, SeparatorsShort, TrianglesSolid, PopupImmediately, PopdownDelayed, PopdownDelay 150, PopupAsSubmenu, RemoveSubmenus, SubmenusRight, BorderWidth 2, UniqueHotkeyActivatesImmediate, !AutomaticHotkeys, PopupActiveArea 75\. .PP \fIBorderWidth\fR takes the thickness of the border around the menus in pixels\. It may be zero to 50 pixels\. The default is 2\. Using an illegal value reverts the border width to the default\. .PP \fIForeground\fR and \fIBackground\fR may have a color name as an argument\. This color is used for menu text or the menu's background\. You can omit the color name to reset these colors to the built\-in default\. .PP \fIGreyed\fR may have a color name as an argument\. This color is the one used to draw a menu\-selection which is prohibited (or not recommended) by the Mwm hints which an application has specified\. If the color is omitted the color of greyed menu entries is based on the background color of the menu\. .PP \fIHilightBack\fR and \fI!HilightBack\fR switch hilighting the background of the selected menu item on and off\. A specific background color may be used by providing the color name as an argument to \fIHilightBack\fR\. If you use this option without an argument the color is based on the menu's background color\. The \fIActiveColorset\fR option overrides the specified color\. If the colorset has a non solid background it is used for the hilighting\. .PP \fIHilightTitleBack\fR switches hilighting the background of menu titles on\. If a \fITitleColorset\fR was used, the background colour is taken from there\. Otherwise the color is based on the menu's background color\. If the colorset has a non solid background it is used for the hilighting\. .PP \fIActiveFore\fR and \fI!ActiveFore\fR switch hilighting the foreground of the selected menu item on and off\. A specific foreground color may be used by providing the color name as an argument to \fIActiveFore\fR\. Omitting the color turns hilighting on when an \fIActiveColorset\fR is used\. \fIActiveFore\fR turns off hilighting the foreground completely\. The \fIActiveColorset\fR option overrides the specified color\. .PP \fIMenuColorset\fR controls if a colorset is used instead of the \fIForeground\fR, \fIBackground\fR and \fIMenuFace\fR menu styles\. If the \fIMenuColorset\fR keyword is followed by a number equal to zero or greater, this number is taken as the number of the colorset to use\. If the number is omitted, the colorset is switched off and the regular menu styles are used again\. The foreground and background colors of the menu items are replaced by the colors from the colorset\. If the colorset has a pixmap defined, this pixmap is used as the background of the menu\. Note that the \fIMenuFace\fR menu style has been optimized for memory consumption and may use less memory than the background from a colorset\. The shape mask from the colorset is used to shape the menu\. Please refer to the \fBColorsets\fR section for details about colorsets\. .PP \fIActiveColorset\fR works exactly like \fIMenuColorset\fR, but the foreground from the colorset replaces the color given with the \fIActiveFore\fR menu style and the colorset's background color replaces the color given with the \fIHilightBack\fR command (to turn on background hilighting you have to use the \fIHilightBack\fR menu style too)\. If specified, the hilight and shadow colors from the colorset are used too\. The pixmap and shape mask from the colorset are not used\. Hilighting the background or foreground can be turned off individually with the \fI!ActiveFore\fR or \fI!HilightBack\fR menu styles\. .PP \fIGreyedColorset\fR works exactly like \fIMenuColorset\fR, but the foreground from the colorset replaces the color given with the \fIGreyed\fR menu style\. No other parts of the colorset are used\. .PP \fITitleColorset\fR works exactly like \fIMenuColorset\fR, but is used only for menu titles\. .PP \fIHilight3DThick\fR, \fIHilight3DThin\fR and \fIHilight3DOff\fR determine if the selected menu item is hilighted with a 3D relief\. Thick reliefs are two pixels wide, thin reliefs are one pixel wide\. .PP \fIHilight3DThickness\fR takes one numeric argument that may be between \-50 and +50 pixels\. With negative values the menu item gets a pressed in look\. The above three commands are equivalent to a thickness of 2, 1 and 0\. .PP \fIAnimation\fR and \fI!Animation\fR turn menu animation on or off\. When animation is on, sub menus that do not fit on the screen cause the parent menu to be shifted to the left so the sub menu can be seen\. .PP \fIFont\fR and \fITitleFont\fR take a font name as an argument\. If a font by this name exists it is used for the text of all menu items\. If it does not exist or if the name is left blank the built\-in default is used\. If a \fITitleFont\fR is given, it is used for all menu titles instead of the normal font\. .PP \fIMenuFace\fR enforces a fancy background upon the menus\. You can use the same options for \fIMenuFace\fR as for the \fBButtonStyle\fR\. See description of \fBButtonStyle\fR command and the \fBColor Gradients\fR sections for more information\. If you use \fIMenuFace\fR without arguments the style is reverted back to normal\. .PP Some examples of MenuFaces are: .sp .RS 4 .nf MenuFace DGradient 128 2 lightgrey 50 blue 50 white MenuFace TiledPixmap texture10\.xpm MenuFace HGradient 128 2 Red 40 Maroon 60 White MenuFace Solid Maroon .fi .RE .PP Note: The gradient styles H, V, B and D are optimized for high speed and low memory consumption in menus\. This is not the case for all the other gradient styles\. They may be slow and consume huge amounts of memory, so if you encounter performance problems with them you may be better off by not using them\. To improve performance you can try one or all of the following: .PP Turn hilighting of the active menu item other than foreground color off: .sp .RS 4 .nf MenuStyle Stripping namespace from DocBook 5 document. Processing stripped document. Unable to strip the namespace from DB5 document, cannot proceed. ID ' ' not found in document. 0 fvwm-2.7.0/doc/docbook-xsl/html/Makefile.in0000644000175000017500000003624214324315775015444 00000000000000# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2021 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 = doc/docbook-xsl/html ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.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__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALL_DOMAINS = @ALL_DOMAINS@ ALL_LINGUAS = @ALL_LINGUAS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR_FLAGS = @AR_FLAGS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ Bidi_CFLAGS = @Bidi_CFLAGS@ Bidi_LIBS = @Bidi_LIBS@ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CSCOPE = @CSCOPE@ CTAGS = @CTAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DOC_COMMANDS = @DOC_COMMANDS@ DOC_COMMANDS_HTML = @DOC_COMMANDS_HTML@ DOC_COMMANDS_XML = @DOC_COMMANDS_XML@ DOC_COMMANDS_XML_PATH = @DOC_COMMANDS_XML_PATH@ DOC_MODULES = @DOC_MODULES@ DOC_MODULES_HTML = @DOC_MODULES_HTML@ DOC_SECTIONS = @DOC_SECTIONS@ DOC_SECTIONS_XML = @DOC_SECTIONS_XML@ DOC_SECTIONS_XML_PATH = @DOC_SECTIONS_XML_PATH@ DUMMYPOFILES = @DUMMYPOFILES@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ FC_CFLAGS = @FC_CFLAGS@ FC_CONFIG = @FC_CONFIG@ FC_LIBS = @FC_LIBS@ FRIBIDI_CONFIG = @FRIBIDI_CONFIG@ FVWMALTFTP = @FVWMALTFTP@ FVWMALTFTPDIR = @FVWMALTFTPDIR@ FVWMFTP = @FVWMFTP@ FVWMFTPDIR = @FVWMFTPDIR@ FVWMHOMEPAGE = @FVWMHOMEPAGE@ FVWMLIST = @FVWMLIST@ FVWMNAMELONG = @FVWMNAMELONG@ FVWMSCRIPT_DOMAIN = @FVWMSCRIPT_DOMAIN@ FVWMTASKBAR_DOMAIN = @FVWMTASKBAR_DOMAIN@ FVWMWORKERSLIST = @FVWMWORKERSLIST@ FVWMWORKERSLISTLONG = @FVWMWORKERSLISTLONG@ FVWM_CONFDIR = @FVWM_CONFDIR@ FVWM_CPP = @FVWM_CPP@ FVWM_DATADIR = @FVWM_DATADIR@ FVWM_DOCDIR = @FVWM_DOCDIR@ FVWM_DOMAIN = @FVWM_DOMAIN@ FVWM_IMAGEPATH = @FVWM_IMAGEPATH@ FVWM_MODULEDIR = @FVWM_MODULEDIR@ FVWM_PERLLIB = @FVWM_PERLLIB@ FVWM_PERLLIBDIR = @FVWM_PERLLIBDIR@ GDK_IMLIB_CFLAGS = @GDK_IMLIB_CFLAGS@ GDK_IMLIB_LIBS = @GDK_IMLIB_LIBS@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ IMLIBCONF = @IMLIBCONF@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INST_LINGUAS = @INST_LINGUAS@ ISRELEASED = @ISRELEASED@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LN_S = @LN_S@ LOCALEDIR = @LOCALEDIR@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANPAGE_PREAMBLE = @MANPAGE_PREAMBLE@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGMERGE = @MSGMERGE@ MSGUNIQ = @MSGUNIQ@ OBJEXT = @OBJEXT@ 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@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PKG_CONFIG = @PKG_CONFIG@ PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ POFILES = @POFILES@ POSUB = @POSUB@ PYTHON = @PYTHON@ RANLIB = @RANLIB@ RELDATELONG = @RELDATELONG@ RELDATENUM = @RELDATENUM@ RELDATESHORT = @RELDATESHORT@ REQUIRED_PERL_VERSION = @REQUIRED_PERL_VERSION@ REQUIRED_PYTHON_VERSION = @REQUIRED_PYTHON_VERSION@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ UPDATEPOFILES = @UPDATEPOFILES@ USE_NLS = @USE_NLS@ VERSION = @VERSION@ VERSIONINFO = @VERSIONINFO@ XFT_CFLAGS = @XFT_CFLAGS@ XFT_CONFIG = @XFT_CONFIG@ XFT_LIBS = @XFT_LIBS@ XGETTEXT = @XGETTEXT@ XMKMF = @XMKMF@ XSLTPROC = @XSLTPROC@ X_CFLAGS = @X_CFLAGS@ X_EXTRA_LIBS = @X_EXTRA_LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ Xcursor_CFLAGS = @Xcursor_CFLAGS@ Xcursor_LIBS = @Xcursor_LIBS@ Xft_CFLAGS = @Xft_CFLAGS@ Xft_LIBS = @Xft_LIBS@ Xinerama_CFLAGS = @Xinerama_CFLAGS@ Xinerama_LIBS = @Xinerama_LIBS@ Xrender_CFLAGS = @Xrender_CFLAGS@ Xrender_LIBS = @Xrender_LIBS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_CC = @ac_ct_CC@ 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@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ iconv_CFLAGS = @iconv_CFLAGS@ iconv_LIBS = @iconv_LIBS@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ intl_CFLAGS = @intl_CFLAGS@ intl_LIBS = @intl_LIBS@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ png_CFLAGS = @png_CFLAGS@ png_LIBS = @png_LIBS@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ readline_CFLAGS = @readline_CFLAGS@ readline_LIBS = @readline_LIBS@ rplay_CFLAGS = @rplay_CFLAGS@ rplay_LIBS = @rplay_LIBS@ rsvg_CFLAGS = @rsvg_CFLAGS@ rsvg_LIBS = @rsvg_LIBS@ runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ stroke_CFLAGS = @stroke_CFLAGS@ stroke_LIBS = @stroke_LIBS@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ with_bidi = @with_bidi@ with_gdkimlib = @with_gdkimlib@ with_gettext = @with_gettext@ with_iconv = @with_iconv@ with_perllib = @with_perllib@ with_png = @with_png@ with_readline = @with_readline@ with_rplay = @with_rplay@ with_rsvg = @with_rsvg@ with_shape = @with_shape@ with_shm = @with_shm@ with_sm = @with_sm@ with_stroke = @with_stroke@ with_xcursor = @with_xcursor@ with_xft = @with_xft@ with_xinerama = @with_xinerama@ with_xpm = @with_xpm@ with_xrender = @with_xrender@ xpm_CFLAGS = @xpm_CFLAGS@ xpm_LIBS = @xpm_LIBS@ EXTRA_DIST = \ admon.xsl \ annotations.xsl \ autoidx.xsl \ autotoc.xsl \ biblio-iso690.xsl \ biblio.xsl \ block.xsl \ callout.xsl \ chunker.xsl \ component.xsl \ division.xsl \ docbook.xsl \ ebnf.xsl \ footnote.xsl \ formal.xsl \ glossary.xsl \ graphics.xsl \ highlight.xsl \ html-rtf.xsl \ html.xsl \ htmltbl.xsl \ index.xsl \ info.xsl \ inline.xsl \ keywords.xsl \ lists.xsl \ manifest.xsl \ math.xsl \ param.xsl \ pi.xsl \ qandaset.xsl \ refentry.xsl \ sections.xsl \ synop.xsl \ table.xsl \ task.xsl \ titlepage.templates.xsl \ titlepage.xsl \ toc.xsl \ verbatim.xsl \ xref.xsl all: all-am .SUFFIXES: $(srcdir)/Makefile.in: $(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) --foreign doc/docbook-xsl/html/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign doc/docbook-xsl/html/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: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): 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 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 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-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 pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic cscopelist-am \ ctags-am distclean distclean-generic 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-generic pdf \ pdf-am ps ps-am 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: fvwm-2.7.0/doc/docbook-xsl/html/glossary.xsl0000644000175000017500000003626414147024700015762 00000000000000 %common.entities; ]>

    0 1 ( )
    0 1 ( )
    0 1
    , , ,

    Warning: glosssee @otherterm reference not found: .

    Warning: glossseealso @otherterm reference not found: . , Warning: processing automatic glossary without a glossary.collection file. Warning: processing automatic glossary but unable to open glossary.collection file ' '
    fvwm-2.7.0/doc/docbook-xsl/html/callout.xsl0000644000175000017500000001603514147024700015554 00000000000000 No insertCallouts function is available.
    Error: coref link is broken: Error: coref doesn't point to a co: {$conum} Don't know how to generate Unicode callouts when $callout.unicode.start.character is ( ) ( )
    fvwm-2.7.0/doc/docbook-xsl/html/graphics.xsl0000644000175000017500000015335414147024700015717 00000000000000 1 1
    0 0 0 1 0 1.0 1.0 1.0 px px px px 0 0 middle Warning: imagemaps not supported on scaled images 0 middle height: px
    background-color:
    calspair , , , Warning: only calspair or otherunits='imagemap' supported in imageobjectco
    middle
    No insertfile extension available.
    No insertfile extension available.
    No insertfile extension available.
    fvwm-2.7.0/doc/docbook-xsl/html/formal.xsl0000644000175000017500000003111714147024700015367 00000000000000 1


    -float

    -float
    before Broken table: tr descendent of CALS Table. before Broken table: row descendent of HTML table. before before
    float: ;
    fvwm-2.7.0/doc/docbook-xsl/html/division.xsl0000644000175000017500000001636614147024700015744 00000000000000

    title

    fvwm-2.7.0/doc/docbook-xsl/html/biblio-iso690.xsl0000644000175000017500000015617114147024700016406 00000000000000 In fvwm-2.7.0/doc/docbook-xsl/html/task.xsl0000644000175000017500000000437114147024700015053 00000000000000 before
    fvwm-2.7.0/doc/docbook-xsl/html/annotations.xsl0000644000175000017500000001303114147024700016437 00000000000000