lisp/ChangeLog, and src/ChangeLog for list of changes.
+2002-04-26 Andrew Choi <akochoi@shaw.ca>
+
+ * configure.in: Add support for powerpc-apple-darwin*.
+ (HAVE_CARBON): Add.
+
+ * make-dist: create directories in mac/Emacs.app.
+
2002-04-25 Pavel Jan\e,Bm\e(Bk <Pavel@Janik.cz>
* make-dist: lwlib-Xol* are removed.
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.53.
+# Generated by GNU Autoconf 2.53a.
#
# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
# Free Software Foundation, Inc.
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
-
-if expr a : '\(a\)' >/dev/null 2>&1; then
- as_expr=expr
-else
- as_expr=false
-fi
-
-
## --------------------- ##
## M4sh Initialization. ##
## --------------------- ##
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
emulate sh
NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
set -o posix
fi
{ LC_MESSAGES=C; export LC_MESSAGES; }
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; 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
+
+
# Name of the executable.
-as_me=`(basename "$0") 2>/dev/null ||
+as_me=`$as_basename "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)$' \| \
/^X\/\(\/\).*/{ s//\1/; q; }
s/.*/./; q'`
+
# PATH needs CR, and LINENO needs CR and PATH.
# Avoid depending upon Character Ranges.
as_cr_letters='abcdefghijklmnopqrstuvwxyz'
as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
test "x$as_lineno_1" != "x$as_lineno_2" &&
test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
CONFIG_SHELL=$as_dir/$as_base
export CONFIG_SHELL
exec "$CONFIG_SHELL" "$0" ${1+"$@"}
fi
rm -f conf$$ conf$$.exe conf$$.file
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ as_mkdir_p=false
+fi
+
as_executable_p="test -f"
# Sed expression to map a string onto a valid CPP name.
--without-toolkit-scroll-bars
don't use Motif or Xaw3d scroll bars
--without-xim don't use X11 XIM
+ --without-carbon don't use Carbon GUI on Mac OS X
--with-x use the X Window System
Some influential environment variables:
running configure, to aid debugging if configure makes a mistake.
It was created by $as_me, which was
-generated by GNU Autoconf 2.53. Invocation command line was
+generated by GNU Autoconf 2.53a. Invocation command line was
$ $0 $@
-ac_config_headers="$ac_config_headers src/config.h:src/config.in"
+
+ ac_config_headers="$ac_config_headers src/config.h:src/config.in"
test "$program_prefix" != NONE &&
fi;
+# Check whether --with-carbon or --without-carbon was given.
+if test "${with_carbon+set}" = set; then
+ withval="$with_carbon"
+
+fi;
+
#### Make srcdir absolute, if it isn't already. It's important to
#### avoid running the path through pwd unnecessarily, since pwd can
#### give you automounter prefixes, which can go away. We do all this
machine=f301 opsys=uxpv
;;
+ ## Darwin / Mac OS X
+ powerpc-apple-darwin* )
+ machine=powermac opsys=darwin
+ # Define CPP as follows to make autoconf work correctly.
+ CPP="cc -E -traditional-cpp"
+ ;;
+
* )
unported=yes
;;
ls a.out conftest 2>/dev/null;
ls a.* conftest.* 2>/dev/null`; do
case $ac_file in
- *.$ac_ext | *.o | *.obj | *.xcoff | *.tds | *.d | *.pdb | *.xSYM ) ;;
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
a.out ) # We found the default executable, but exeext='' is most
# certainly right.
break;;
# `rm'.
for ac_file in `(ls conftest.exe; ls conftest; ls conftest.*) 2>/dev/null`; do
case $ac_file in
- *.$ac_ext | *.o | *.obj | *.xcoff | *.tds | *.d | *.pdb ) ;;
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
*.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
export ac_cv_exeext
break;;
(exit $ac_status); }; then
for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
case $ac_file in
- *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb ) ;;
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
*) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
break;;
esac
CFLAGS=
fi
fi
+echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_prog_cc_stdc=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+#ifdef F77_DUMMY_MAIN
+# ifdef __cplusplus
+ extern "C"
+# endif
+ int F77_DUMMY_MAIN() { return 1; }
+#endif
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX -qlanglvl=ansi
+# Ultrix and OSF/1 -std1
+# HP-UX 10.20 and later -Ae
+# HP-UX older versions -Aa -D_HPUX_SOURCE
+# SVR4 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_stdc=$ac_arg
+break
+else
+ echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+fi
+rm -f conftest.$ac_objext
+done
+rm -f conftest.$ac_ext conftest.$ac_objext
+CC=$ac_save_CC
+
+fi
+
+case "x$ac_cv_prog_cc_stdc" in
+ x|xno)
+ echo "$as_me:$LINENO: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+ *)
+ echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+ CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
# Some people use a C++ compiler to compile C. Since we use `exit',
# in C++ we need to declare it. In case someone uses the same compiler
# for both compiling C and C++ we need to have the C++ compiler decide
-echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5
-echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
-if test "${ac_cv_prog_cc_stdc+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- ac_cv_prog_cc_stdc=no
-ac_save_CC=$CC
-cat >conftest.$ac_ext <<_ACEOF
-#line $LINENO "configure"
-#include "confdefs.h"
-#include <stdarg.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
-struct buf { int x; };
-FILE * (*rcsopen) (struct buf *, struct stat *, int);
-static char *e (p, i)
- char **p;
- int i;
-{
- return p[i];
-}
-static char *f (char * (*g) (char **, int), char **p, ...)
-{
- char *s;
- va_list v;
- va_start (v,p);
- s = g (p, va_arg (v,int));
- va_end (v);
- return s;
-}
-int test (int i, double x);
-struct s1 {int (*f) (int a);};
-struct s2 {int (*f) (double a);};
-int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
-int argc;
-char **argv;
-#ifdef F77_DUMMY_MAIN
-# ifdef __cplusplus
- extern "C"
-# endif
- int F77_DUMMY_MAIN() { return 1; }
-#endif
-int
-main ()
-{
-return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
- ;
- return 0;
-}
-_ACEOF
-# Don't try gcc -ansi; that turns off useful extensions and
-# breaks some systems' header files.
-# AIX -qlanglvl=ansi
-# Ultrix and OSF/1 -std1
-# HP-UX 10.20 and later -Ae
-# HP-UX older versions -Aa -D_HPUX_SOURCE
-# SVR4 -Xc -D__EXTENSIONS__
-for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
-do
- CC="$ac_save_CC $ac_arg"
- rm -f conftest.$ac_objext
-if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
- (eval $ac_compile) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } &&
- { ac_try='test -s conftest.$ac_objext'
- { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
- (eval $ac_try) 2>&5
- ac_status=$?
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); }; }; then
- ac_cv_prog_cc_stdc=$ac_arg
-break
-else
- echo "$as_me: failed program was:" >&5
-cat conftest.$ac_ext >&5
-fi
-rm -f conftest.$ac_objext
-done
-rm -f conftest.$ac_ext conftest.$ac_objext
-CC=$ac_save_CC
-
-fi
-
-case "x$ac_cv_prog_cc_stdc" in
- x|xno)
- echo "$as_me:$LINENO: result: none needed" >&5
-echo "${ECHO_T}none needed" >&6 ;;
- *)
- echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5
-echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
- CC="$CC $ac_cv_prog_cc_stdc" ;;
-esac
-
echo "$as_me:$LINENO: checking for function prototypes" >&5
echo $ECHO_N "checking for function prototypes... $ECHO_C" >&6
if test "$ac_cv_prog_cc_stdc" != no; then
fi
fi
+### Use Mac OS X Carbon API to implement GUI.
+HAVE_CARBON=no
+if test "${with_carbon}" != "no"; then
+ if test "${ac_cv_header_Carbon_Carbon_h+set}" = set; then
+ echo "$as_me:$LINENO: checking for Carbon/Carbon.h" >&5
+echo $ECHO_N "checking for Carbon/Carbon.h... $ECHO_C" >&6
+if test "${ac_cv_header_Carbon_Carbon_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_Carbon_Carbon_h" >&5
+echo "${ECHO_T}$ac_cv_header_Carbon_Carbon_h" >&6
+else
+ # Is the header compilable?
+echo "$as_me:$LINENO: checking Carbon/Carbon.h usability" >&5
+echo $ECHO_N "checking Carbon/Carbon.h usability... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+$ac_includes_default
+#include <Carbon/Carbon.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_header_compiler=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6
+
+# Is the header present?
+echo "$as_me:$LINENO: checking Carbon/Carbon.h presence" >&5
+echo $ECHO_N "checking Carbon/Carbon.h presence... $ECHO_C" >&6
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+#include <Carbon/Carbon.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ egrep -v '^ *\+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.$ac_ext
+echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc in
+ yes:no )
+ { echo "$as_me:$LINENO: WARNING: Carbon/Carbon.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: Carbon/Carbon.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: Carbon/Carbon.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: Carbon/Carbon.h: proceeding with the preprocessor's result" >&2;};;
+ no:yes )
+ { echo "$as_me:$LINENO: WARNING: Carbon/Carbon.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: Carbon/Carbon.h: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: Carbon/Carbon.h: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: Carbon/Carbon.h: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: Carbon/Carbon.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: Carbon/Carbon.h: proceeding with the preprocessor's result" >&2;};;
+esac
+echo "$as_me:$LINENO: checking for Carbon/Carbon.h" >&5
+echo $ECHO_N "checking for Carbon/Carbon.h... $ECHO_C" >&6
+if test "${ac_cv_header_Carbon_Carbon_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_header_Carbon_Carbon_h=$ac_header_preproc
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_Carbon_Carbon_h" >&5
+echo "${ECHO_T}$ac_cv_header_Carbon_Carbon_h" >&6
+
+fi
+if test $ac_cv_header_Carbon_Carbon_h = yes; then
+ HAVE_CARBON=yes
+fi
+
+
+fi
+
+if test "${HAVE_CARBON}" = "yes"; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_CARBON 1
+_ACEOF
+
+fi
+
### Use session management (-lSM -lICE) if available
HAVE_X_SM=no
if test "${HAVE_X11}" = "yes"; then
rm -f conftest*
-ac_config_files="$ac_config_files Makefile lib-src/Makefile.c:lib-src/Makefile.in oldXMenu/Makefile man/Makefile lwlib/Makefile src/Makefile.c:src/Makefile.in lisp/Makefile lispref/Makefile lispintro/Makefile leim/Makefile"
-ac_config_commands="$ac_config_commands default"
+ ac_config_files="$ac_config_files Makefile lib-src/Makefile.c:lib-src/Makefile.in oldXMenu/Makefile man/Makefile lwlib/Makefile src/Makefile.c:src/Makefile.in lisp/Makefile lispref/Makefile lispintro/Makefile leim/Makefile"
+ ac_config_commands="$ac_config_commands default"
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
_ACEOF
cat >>$CONFIG_STATUS <<\_ACEOF
-
## --------------------- ##
## M4sh Initialization. ##
## --------------------- ##
if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
emulate sh
NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
set -o posix
fi
{ LC_MESSAGES=C; export LC_MESSAGES; }
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; 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
+
+
# Name of the executable.
-as_me=`(basename "$0") 2>/dev/null ||
+as_me=`$as_basename "$0" ||
$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
X"$0" : 'X\(//\)$' \| \
X"$0" : 'X\(/\)$' \| \
/^X\/\(\/\).*/{ s//\1/; q; }
s/.*/./; q'`
+
# PATH needs CR, and LINENO needs CR and PATH.
# Avoid depending upon Character Ranges.
as_cr_letters='abcdefghijklmnopqrstuvwxyz'
as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
test "x$as_lineno_1" != "x$as_lineno_2" &&
test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
CONFIG_SHELL=$as_dir/$as_base
export CONFIG_SHELL
exec "$CONFIG_SHELL" "$0" ${1+"$@"}
fi
rm -f conf$$ conf$$.exe conf$$.file
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ as_mkdir_p=false
+fi
+
as_executable_p="test -f"
# Sed expression to map a string onto a valid CPP name.
cat >&5 <<_CSEOF
This file was extended by $as_me, which was
-generated by GNU Autoconf 2.53. Invocation command line was
+generated by GNU Autoconf 2.53a. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
CONFIG_HEADERS = $CONFIG_HEADERS
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
config.status
-configured by $0, generated by GNU Autoconf 2.53,
+configured by $0, generated by GNU Autoconf 2.53a,
with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
/^X\(\/\/\)$/{ s//\1/; q; }
/^X\(\/\).*/{ s//\1/; q; }
s/.*/./; q'`
- { case "$ac_dir" in
- [\\/]* | ?:[\\/]* ) as_incr_dir=;;
- *) as_incr_dir=.;;
-esac
-as_dummy="$ac_dir"
-for as_mkdir_dir in `IFS='/\\'; set X $as_dummy; shift; echo "$@"`; do
- case $as_mkdir_dir in
- # Skip DOS drivespec
- ?:) as_incr_dir=$as_mkdir_dir ;;
- *)
- as_incr_dir=$as_incr_dir/$as_mkdir_dir
- test -d "$as_incr_dir" ||
- mkdir "$as_incr_dir" ||
- { { echo "$as_me:$LINENO: error: cannot create \"$ac_dir\"" >&5
-echo "$as_me: error: cannot create \"$ac_dir\"" >&2;}
- { (exit 1); exit 1; }; }
- ;;
- esac
-done; }
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
ac_builddir=.
/^X\(\/\/\)$/{ s//\1/; q; }
/^X\(\/\).*/{ s//\1/; q; }
s/.*/./; q'`
- { case "$ac_dir" in
- [\\/]* | ?:[\\/]* ) as_incr_dir=;;
- *) as_incr_dir=.;;
-esac
-as_dummy="$ac_dir"
-for as_mkdir_dir in `IFS='/\\'; set X $as_dummy; shift; echo "$@"`; do
- case $as_mkdir_dir in
- # Skip DOS drivespec
- ?:) as_incr_dir=$as_mkdir_dir ;;
- *)
- as_incr_dir=$as_incr_dir/$as_mkdir_dir
- test -d "$as_incr_dir" ||
- mkdir "$as_incr_dir" ||
- { { echo "$as_me:$LINENO: error: cannot create \"$ac_dir\"" >&5
-echo "$as_me: error: cannot create \"$ac_dir\"" >&2;}
- { (exit 1); exit 1; }; }
- ;;
- esac
-done; }
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
rm -f $ac_file
mv $tmp/config.h $ac_file
don't use Motif or Xaw3d scroll bars])
AC_ARG_WITH(xim,
[ --without-xim don't use X11 XIM])
+AC_ARG_WITH(carbon,
+[ --without-carbon don't use Carbon GUI on Mac OS X])
#### Make srcdir absolute, if it isn't already. It's important to
#### avoid running the path through pwd unnecessarily, since pwd can
machine=f301 opsys=uxpv
;;
+ ## Darwin / Mac OS X
+ powerpc-apple-darwin* )
+ machine=powermac opsys=darwin
+ # Define CPP as follows to make autoconf work correctly.
+ CPP="cc -E -traditional-cpp"
+ ;;
+
* )
unported=yes
;;
fi
fi
+### Use Mac OS X Carbon API to implement GUI.
+HAVE_CARBON=no
+if test "${with_carbon}" != "no"; then
+ AC_CHECK_HEADER(Carbon/Carbon.h, HAVE_CARBON=yes)
+fi
+
+if test "${HAVE_CARBON}" = "yes"; then
+ AC_DEFINE(HAVE_CARBON)
+fi
+
### Use session management (-lSM -lICE) if available
HAVE_X_SM=no
if test "${HAVE_X11}" = "yes"; then
+2002-04-26 Andrew Choi <akochoi@shaw.ca>
+
+ * term/mac-win.el: Don't call ediff-toggle-multiframe. Set
+ default directory. Set process-connection-type to nil.
+
2002-04-26 Richard M. Stallman <rms@gnu.org>
* cus-edit.el (customize-face): Use read-face-name
(put 'woman-faces 'custom-loads '("woman"))
(put 'ps-print-vertical 'custom-loads '("ps-print"))
(put 'supercite-hooks 'custom-loads '("supercite"))
-(put 'chinese-calendar 'custom-loads '("cal-china"))
(put 'vhdl-menu 'custom-loads '("vhdl-mode"))
(put 'gnus-newsrc 'custom-loads '("gnus-start"))
+(put 'chinese-calendar 'custom-loads '("cal-china"))
(put 'expand 'custom-loads '("expand"))
(put 'bookmark 'custom-loads '("bookmark"))
(put 'icon 'custom-loads '("icon"))
(put 'dirtrack 'custom-loads '("dirtrack"))
(put 'ediff-window 'custom-loads '("ediff-help" "ediff-wind"))
(put 'bruce 'custom-loads '("bruce"))
-(put 'windows 'custom-loads '("scroll-all" "window" "follow" "windmove"))
+(put 'windows 'custom-loads '("hscroll" "scroll-all" "window" "follow" "windmove"))
(put 'gnus-exit 'custom-loads '("gnus-group" "gnus"))
(put 'speedbar 'custom-loads '("speedbar"))
(put 'etags 'custom-loads '("etags"))
(put 'mh-hook 'custom-loads '("mh-e"))
(put 'yow 'custom-loads '("yow"))
(put 'reftex-defining-label-environments 'custom-loads '("reftex-vars"))
-(put 'asm 'custom-loads '("asm-mode" "cc-vars"))
+(put 'asm 'custom-loads '("asm-mode"))
(put 'gnus-score-files 'custom-loads '("gnus-score" "gnus"))
(put 'mail-abbrev 'custom-loads '("mailabbrev"))
(put 'feedmail 'custom-loads '("feedmail"))
(put 'iso-acc 'custom-loads '("iso-acc"))
(put 'gnus-summary-pick 'custom-loads '("gnus-salt"))
(put 'gnus-thread 'custom-loads '("gnus-sum"))
-(put 'languages 'custom-loads '("cus-edit" "info-look" "ada-mode" "antlr-mode" "asm-mode" "cperl-mode" "dcl-mode" "delphi" "f90" "fortran" "hideshow" "icon" "idlwave" "m4-mode" "meta-mode" "modula2" "octave-mod" "pascal" "perl-mode" "prolog" "ps-mode" "sh-script" "simula" "tcl" "vhdl-mode" "sgml-mode" "xml-lite"))
+(put 'languages 'custom-loads '("cus-edit" "info-look" "ada-mode" "antlr-mode" "asm-mode" "cperl-mode" "dcl-mode" "delphi" "f90" "fortran" "hideshow" "icon" "idlwave" "m4-mode" "meta-mode" "modula2" "octave-mod" "pascal" "perl-mode" "prolog" "ps-mode" "sh-script" "simula" "tcl" "vhdl-mode" "sgml-mode"))
(put 'reftex-miscellaneous-configurations 'custom-loads '("reftex-vars"))
(put 'pong 'custom-loads '("pong"))
(put 'ediff-ptch 'custom-loads '("ediff-ptch"))
(put 'smiley 'custom-loads '("smiley-ems"))
(put 'extensions 'custom-loads '("generic" "time-stamp" "wid-edit" "cust-print" "eldoc" "page-ext"))
(put 'tetris 'custom-loads '("tetris"))
-(put 'appt 'custom-loads '("appt"))
(put 'ebnf-displacement 'custom-loads '("ebnf2ps"))
+(put 'appt 'custom-loads '("appt"))
(put 'snmp 'custom-loads '("snmp-mode"))
(put 'speedbar-faces 'custom-loads '("speedbar" "vhdl-mode"))
(put 'rmail 'custom-loads '("paths" "rmail" "undigest"))
(put 'auto-save 'custom-loads '("files" "startup"))
(put 'tpu 'custom-loads '("tpu-edt" "tpu-extras"))
(put 'w32 'custom-loads '("w32-vars"))
-(put 'viper-hooks 'custom-loads '("viper-init"))
(put 'gnus-cite 'custom-loads '("gnus-cite"))
+(put 'viper-hooks 'custom-loads '("viper-init"))
(put 'gnus-demon 'custom-loads '("gnus-demon"))
(put 'reftex-optimizations-for-large-documents 'custom-loads '("reftex-vars"))
(put 'viper-misc 'custom-loads '("viper-cmd" "viper-init" "viper"))
(put 'cperl-indentation-details 'custom-loads '("cperl-mode"))
(put 'mail-extr 'custom-loads '("mail-extr"))
(put 'double 'custom-loads '("double"))
-(put 'xml-lite 'custom-loads '("xml-lite"))
(put 'imenu 'custom-loads '("imenu"))
(put 'eshell-var 'custom-loads '("esh-var"))
(put 'scribe 'custom-loads '("scribe"))
(put 'generic-x 'custom-loads '("generic-x"))
(put 'partial-completion 'custom-loads '("complete"))
(put 'whitespace 'custom-loads '("whitespace"))
-(put 'maint 'custom-loads '("emacsbug" "gulp" "lisp-mnt"))
+(put 'maint 'custom-loads '("gulp" "lisp-mnt" "emacsbug"))
(put 'pages 'custom-loads '("page-ext"))
(put 'message-interface 'custom-loads '("message"))
-(put 'diary 'custom-loads '("calendar" "diary-lib"))
+(put 'diary 'custom-loads '("calendar" "diary-lib" "solar"))
(put 'custom-magic-faces 'custom-loads '("cus-edit"))
(put 'emacsbug 'custom-loads '("emacsbug"))
(put 'mh-compose 'custom-loads '("mh-comp"))
(put 'apropos 'custom-loads '("apropos"))
(put 'gomoku 'custom-loads '("gomoku"))
(put 'eshell-pred 'custom-loads '("em-pred"))
-(put 'tools 'custom-loads '("add-log" "calculator" "compare-w" "diff-mode" "diff" "ediff" "elide-head" "emerge" "gud" "pcvs-defs" "smerge-mode" "speedbar" "tempo" "tooltip" "vc" "which-func" "rcompile" "copyright" "compile" "ebrowse" "etags" "glasses" "make-mode"))
+(put 'tools 'custom-loads '("add-log" "calculator" "compare-w" "diff-mode" "diff" "ediff" "elide-head" "emerge" "gud" "pcvs-defs" "smerge-mode" "speedbar" "tempo" "tooltip" "vc" "which-func" "copyright" "rcompile" "compile" "ebrowse" "etags" "glasses" "make-mode"))
(put 'gnus-topic 'custom-loads '("gnus-topic"))
(put 'sgml 'custom-loads '("sgml-mode"))
(put 'keyboard 'custom-loads '("mule" "chistory" "type-break"))
(put 'nnmail-retrieve 'custom-loads '("nnmail"))
(put 'gnus-duplicate 'custom-loads '("gnus-dup"))
(put 'find-function 'custom-loads '("find-func"))
-(put 'menu 'custom-loads '("faces" "tmm" "easymenu"))
+(put 'menu 'custom-loads '("faces" "menu-bar" "tmm" "easymenu"))
(put 'eshell-test 'custom-loads '("esh-test"))
(put 'vhdl-highlight 'custom-loads '("vhdl-mode"))
(put 'widgets 'custom-loads '("wid-browse" "wid-edit"))
(put 'log-view 'custom-loads '("log-view"))
(put 'PostScript 'custom-loads '("ps-mode"))
(put 'abbrev-mode 'custom-loads '("abbrev" "cus-edit" "mailabbrev"))
-(put 'eshell-term 'custom-loads '("em-term"))
(put 'earcon 'custom-loads '("earcon"))
+(put 'eshell-term 'custom-loads '("em-term"))
(put 'feedmail-headers 'custom-loads '("feedmail"))
(put 'hypermedia 'custom-loads '("wid-edit" "metamail" "browse-url" "goto-addr"))
(put 'image 'custom-loads '("image-file"))
(put 'reftex-index-support 'custom-loads '("reftex-vars"))
(put 'pascal 'custom-loads '("pascal"))
(put 'rmail-retrieve 'custom-loads '("rmail" "rmailsum"))
-(put 'data 'custom-loads '("text-mode" "arc-mode" "forms" "hexl" "jka-compr" "saveplace" "sort" "tar-mode" "time-stamp" "snmp-mode" "timeclock"))
+(put 'data 'custom-loads '("text-mode" "arc-mode" "forms" "hexl" "jka-compr" "saveplace" "sort" "tar-mode" "time-stamp" "timeclock" "snmp-mode"))
(put 'mail 'custom-loads '("simple" "startup" "time" "gnus" "mail-utils" "mm-decode" "message" "imap" "starttls" "emacsbug" "feedmail" "mail-extr" "mail-hist" "mailalias" "metamail" "mh-e" "mspools" "rmail" "sendmail" "smtpmail" "supercite" "uce" "eudc-vars" "fortune"))
(put 'paren-blinking 'custom-loads '("simple"))
(put 'gnus-summary-sort 'custom-loads '("gnus-sum"))
(custom-put-if-not 'change-log-conditionals-face 'group-documentation nil)
(custom-put-if-not 'mail-source 'custom-version "21.1")
(custom-put-if-not 'mail-source 'group-documentation "The mail-fetching library.")
-(custom-put-if-not 'smtpmail-auth-credentials 'custom-version "21.1")
+(custom-put-if-not 'smtpmail-auth-credentials 'custom-version "21.3")
(custom-put-if-not 'smtpmail-auth-credentials 'standard-value t)
(custom-put-if-not 'minibuffer-prompt 'custom-version "21.3")
(custom-put-if-not 'minibuffer-prompt 'group-documentation nil)
(custom-put-if-not 'tildify 'group-documentation "Adding missing hard spaces or other text fragments into texts.")
(custom-put-if-not 'normal-erase-is-backspace 'custom-version "21.1")
(custom-put-if-not 'normal-erase-is-backspace 'standard-value t)
+(custom-put-if-not 'vc-cvs-global-switches 'custom-version "21.3")
+(custom-put-if-not 'vc-cvs-global-switches 'standard-value t)
(custom-put-if-not 'gnus-article-banner-alist 'custom-version "21.1")
(custom-put-if-not 'gnus-article-banner-alist 'standard-value t)
(custom-put-if-not 'region 'custom-version "21.1")
(custom-put-if-not 'message-buffer-naming-style 'standard-value t)
(custom-put-if-not 'ps-footer-font-size 'custom-version "21.1")
(custom-put-if-not 'ps-footer-font-size 'standard-value t)
+(custom-put-if-not 'hscroll-margin 'custom-version "21.3")
+(custom-put-if-not 'hscroll-margin 'standard-value t)
(custom-put-if-not 'tags-apropos-additional-actions 'custom-version "21.1")
(custom-put-if-not 'tags-apropos-additional-actions 'standard-value t)
(custom-put-if-not 'generic-x 'custom-version "20.3")
(custom-put-if-not 'vcursor-interpret-input 'standard-value t)
(custom-put-if-not 'gnus-audio 'custom-version "21.1")
(custom-put-if-not 'gnus-audio 'group-documentation "Playing sound in Gnus.")
+(custom-put-if-not 'diary-sabbath-candles-minutes 'custom-version "21.1")
+(custom-put-if-not 'diary-sabbath-candles-minutes 'standard-value t)
(custom-put-if-not 'trailing-whitespace 'custom-version "21.1")
(custom-put-if-not 'trailing-whitespace 'group-documentation nil)
(custom-put-if-not 'fortran-comment-line-start 'custom-version "21.1")
(custom-put-if-not 'change-log-version-number-regexp-list 'standard-value t)
(custom-put-if-not 'menu 'custom-version "21.1")
(custom-put-if-not 'menu 'group-documentation "Input from the menus.")
+(custom-put-if-not 'dired-view-command-alist 'custom-version 21.4)
+(custom-put-if-not 'dired-view-command-alist 'standard-value t)
(custom-put-if-not 'gnus-nocem-check-from 'custom-version "21.1")
(custom-put-if-not 'gnus-nocem-check-from 'standard-value t)
(custom-put-if-not 'sgml-validate-command 'custom-version "21.1")
(custom-put-if-not 'message-forward-ignored-headers 'standard-value t)
(custom-put-if-not 'eudc 'custom-version "21.1")
(custom-put-if-not 'eudc 'group-documentation "Emacs Unified Directory Client.")
+(custom-put-if-not 'yank-excluded-properties 'custom-version 21.4)
+(custom-put-if-not 'yank-excluded-properties 'standard-value t)
(custom-put-if-not 'scrolling 'custom-version "21.1")
(custom-put-if-not 'scrolling 'group-documentation "Scrolling windows.")
(custom-put-if-not 'ps-paragraph-regexp 'custom-version "21.1")
(custom-put-if-not 'custom-comment-face 'group-documentation nil)
(custom-put-if-not 'custom-raised-buttons 'custom-version "21.1")
(custom-put-if-not 'custom-raised-buttons 'standard-value t)
-(custom-put-if-not 'gnus-article-x-face-command 'custom-version "21.1")
-(custom-put-if-not 'gnus-article-x-face-command 'standard-value t)
(custom-put-if-not 'gnus-inhibit-user-auto-expire 'custom-version "21.1")
(custom-put-if-not 'gnus-inhibit-user-auto-expire 'standard-value t)
(custom-put-if-not 'show-paren-ring-bell-on-mismatch 'custom-version "20.3")
(custom-put-if-not 'gnus-emphasize-whitespace-regexp 'standard-value t)
(custom-put-if-not 'gnus-summary-show-article-charset-alist 'custom-version "21.1")
(custom-put-if-not 'gnus-summary-show-article-charset-alist 'standard-value t)
+(custom-put-if-not 'mail-use-dsn 'custom-version "21.3")
+(custom-put-if-not 'mail-use-dsn 'standard-value t)
(custom-put-if-not 'xscheme-start-hook 'custom-version 20.3)
(custom-put-if-not 'xscheme-start-hook 'standard-value t)
(custom-put-if-not 'vc-dired-listing-switches 'custom-version "21.1")
(custom-put-if-not 'eval-expression-print-level 'custom-version "21.1")
(custom-put-if-not 'eval-expression-print-level 'standard-value t)
-(defvar custom-versions-load-alist '((20.3 "xscheme") ("20.3.3" "dos-vars") (21.1 "ange-ftp") ("20.4" "files" "help" "sh-script" "compile") ("21.2" "add-log" "sgml-mode") ("21.3" "vc-cvs" "replace" "ange-ftp") (21.3 "ange-ftp") ("20.3" "desktop" "easymenu" "hscroll" "dabbrev" "ffap" "rmail" "paren" "mailabbrev" "frame" "uce" "mouse" "diary-lib" "sendmail" "simple" "debug" "hexl" "vcursor" "vc" "compile" "etags" "help-mode" "browse-url" "add-log" "find-func" "cus-edit" "replace") ("21.1" "server" "debug" "rmailedit" "dabbrev" "isearch" "gnus-start" "mule" "hideshow" "sendmail" "paths" "sgml-mode" "net-utils" "cperl-mode" "rmail" "font-lock" "gnus-nocem" "vc-hooks" "paren" "faces" "vc-rcs" "fortran" "vc" "etags" "cus-edit" "vc-sccs" "gnus-group" "gnus-sum" "add-log" "find-func" "frame" "wid-edit" "smtpmail" "files" "nnmail" "message" "ps-print" "vc-cvs" "simple" "gnus-agent" "flyspell" "gnus-art" "browse-url" "speedbar") ("20.8" "sql"))
+(defvar custom-versions-load-alist '((20.3 "xscheme") (21.4 "simple" "dired") ("20.3.3" "dos-vars") (21.1 "ange-ftp") ("20.4" "files" "help" "sh-script" "compile") ("21.2" "add-log" "sgml-mode") (21.3 "ange-ftp") ("21.3" "sendmail" "replace" "hscroll" "vc-cvs" "ange-ftp" "smtpmail") ("20.3" "desktop" "easymenu" "hscroll" "dabbrev" "ffap" "rmail" "paren" "mailabbrev" "frame" "uce" "mouse" "diary-lib" "sendmail" "simple" "debug" "hexl" "vcursor" "vc" "compile" "etags" "help-mode" "browse-url" "add-log" "find-func" "cus-edit" "replace") ("21.1" "server" "debug" "rmailedit" "dabbrev" "isearch" "gnus-start" "mule" "hideshow" "sendmail" "paths" "sgml-mode" "net-utils" "cperl-mode" "rmail" "font-lock" "gnus-nocem" "vc-hooks" "paren" "faces" "vc-rcs" "fortran" "solar" "vc" "etags" "cus-edit" "vc-sccs" "gnus-group" "gnus-sum" "smtpmail" "add-log" "find-func" "frame" "wid-edit" "files" "nnmail" "message" "ps-print" "vc-cvs" "simple" "gnus-agent" "flyspell" "gnus-art" "browse-url" "speedbar") ("20.8" "sql"))
"For internal use by custom.")
(provide 'cus-load)
"highlight the current line"
(faces frames emulation))
("ibuf-ext.el"
- "extensions for ibuffer"
+ "extensions for ibuffer "
(buffer convenience))
("ibuf-macs.el"
"macros for ibuffer"
("calcsel2.el"
"selection functions for Calc"
nil)
- ("binhex.el"
- "elisp native binhex decode"
- (binhex news))
- ("earcon.el"
- "sound effects for messages"
- nil)
- ("flow-fill.el"
- "interprete RFC2646 \"flowed\" text"
- (mail))
- ("format-spec.el"
- "functions for formatting arbitrary formatting strings"
- (tools))
- ("gnus-agent.el"
- "unplugged support for Gnus"
- nil)
- ("gnus-art.el"
- "article mode commands for Gnus"
- (news))
- ("gnus-async.el"
- "asynchronous support for Gnus"
- (news))
- ("gnus-audio.el"
- "sound effects for Gnus"
- (news mail multimedia))
- ("gnus-bcklg.el"
- "backlog functions for Gnus"
- (news))
- ("gnus-cache.el"
- "cache interface for Gnus"
- (news))
- ("gnus-cite.el"
- "parse citations in articles for Gnus"
- nil)
- ("gnus-cus.el"
- "customization commands for Gnus"
- (news))
- ("gnus-demon.el"
- "daemonic Gnus behaviour"
- (news))
- ("gnus-draft.el"
- "draft message support for Gnus"
- (news))
- ("gnus-dup.el"
- "suppression of duplicate articles in Gnus"
- (news))
- ("gnus-eform.el"
- "a mode for editing forms for Gnus"
- (news))
- ("gnus-ems.el"
- "functions for making Gnus work under different Emacsen"
- (news))
- ("gnus-gl.el"
- "an interface to GroupLens for Gnus"
- (news score))
- ("gnus-group.el"
- "group mode commands for Gnus"
- (news))
- ("gnus-int.el"
- "backend interface functions for Gnus"
- (news))
- ("gnus-kill.el"
- "kill commands for Gnus"
- (news))
- ("gnus-logic.el"
- "advanced scoring code for Gnus"
- (news))
- ("gnus-mh.el"
- "mh-e interface for Gnus"
- (news))
- ("gnus-ml.el"
- "mailing list minor mode for Gnus"
- (news))
- ("gnus-mlspl.el"
- "a group params-based mail splitting mechanism"
- (news mail))
- ("gnus-move.el"
- "commands for moving Gnus from one server to another"
- (news))
- ("gnus-msg.el"
- "mail and post interface for Gnus"
- (news))
- ("gnus-mule.el"
- "provide backward compatibility function to GNUS"
- (news i18n))
- ("gnus-nocem.el"
- "NoCeM pseudo-cancellation treatment"
- (news))
- ("gnus-range.el"
- "range and sequence functions for Gnus"
- (news))
- ("gnus-salt.el"
- "alternate summary mode interfaces for Gnus"
- (news))
- ("gnus-score.el"
- "scoring code for Gnus"
- (news))
- ("gnus-setup.el"
- "initialization & setup for Gnus 5"
- (news))
- ("gnus-soup.el"
- "SOUP packet writing support for Gnus"
- (news mail))
- ("gnus-spec.el"
- "format spec functions for Gnus"
- (news))
- ("gnus-srvr.el"
- "virtual server support for Gnus"
- (news))
- ("gnus-start.el"
- "startup functions for Gnus"
- (news))
- ("gnus-sum.el"
- "summary mode commands for Gnus"
- (news))
- ("gnus-topic.el"
- "a folding minor mode for Gnus group buffers"
- (news))
- ("gnus-undo.el"
- "minor mode for undoing in Gnus"
- (news))
- ("gnus-util.el"
- "utility functions for Gnus"
- (news))
- ("gnus-uu.el"
- "extract (uu)encoded files in Gnus"
- nil)
- ("gnus-vm.el"
- "vm interface for Gnus"
- (news mail))
- ("gnus-win.el"
- "window configuration functions for Gnus"
- (news))
- ("gnus.el"
- "a newsreader for GNU Emacs"
- (news mail))
- ("ietf-drums.el"
- "functions for parsing RFC822bis headers"
- nil)
- ("imap.el"
- "imap library"
- (mail))
- ("mail-parse.el"
- "interface functions for parsing mail"
- nil)
- ("mail-prsvr.el"
- "interface variables for parsing mail"
- nil)
- ("mail-source.el"
- "functions for fetching mail"
- (news mail))
- ("mailcap.el"
- "MIME media types configuration"
- (news mail multimedia))
- ("message.el"
- "composing mail and news messages"
- (mail news))
- ("messcompat.el"
- "making message mode compatible with mail mode"
- (mail news))
- ("mm-bodies.el"
- "functions for decoding MIME things"
- nil)
- ("mm-decode.el"
- "functions for decoding MIME things"
- nil)
- ("mm-encode.el"
- "functions for encoding MIME things "
- nil)
- ("mm-partial.el"
- "showing message/partial"
- (message partial))
- ("mm-util.el"
- "Utility functions for Mule and low level things"
- nil)
- ("mm-uu.el"
- "return uu stuff as mm handles"
- (postscript uudecode binhex shar forward news))
- ("mm-view.el"
- "functions for viewing MIME objects"
- nil)
- ("mml.el"
- "package for parsing and validating MML documents"
- nil)
- ("nnagent.el"
- "offline backend for Gnus"
- (news mail))
- ("nnbabyl.el"
- "rmail mbox access for Gnus"
- (news mail))
- ("nndir.el"
- "single directory newsgroup access for Gnus"
- (news))
- ("nndoc.el"
- "single file access for Gnus"
- (news))
- ("nndraft.el"
- "draft article access for Gnus"
- (news))
- ("nneething.el"
- "arbitrary file access for Gnus"
- (news mail))
- ("nnfolder.el"
- "mail folder access for Gnus"
- (mail))
- ("nngateway.el"
- "posting news via mail gateways"
- (news mail))
- ("nnheader.el"
- "header access macros for Gnus and its backends"
- (news))
- ("nnimap.el"
- "imap backend for Gnus"
- (mail))
- ("nnkiboze.el"
- "select virtual news access for Gnus"
- (news))
- ("nnlistserv.el"
- "retrieving articles via web mailing list archives"
- (news mail))
- ("nnmail.el"
- "mail support functions for the Gnus mail backends"
- (news mail))
- ("nnmbox.el"
- "mail mbox access for Gnus"
- (news mail))
- ("nnmh.el"
- "mhspool access for Gnus"
- (news mail))
- ("nnml.el"
- "mail spool access for Gnus"
- (news mail))
- ("nnoo.el"
- "OO Gnus Backends"
- (news))
- ("nnslashdot.el"
- "interfacing with Slashdot"
- (news))
- ("nnsoup.el"
- "SOUP access for Gnus"
- (news mail))
- ("nnspool.el"
- "spool access for GNU Emacs"
- (news))
- ("nntp.el"
- "nntp access for Gnus"
- (news))
- ("nnultimate.el"
- "interfacing with the Ultimate Bulletin Board system"
- (news))
- ("nnvirtual.el"
- "virtual newsgroups access for Gnus"
- (news))
- ("nnwarchive.el"
- "interfacing with web archives"
- (news egroups mail-archive))
- ("nnweb.el"
- "retrieving articles via web search engines"
- (news))
- ("pop3.el"
- "Post Office Protocol (RFC 1460) interface"
- (mail))
- ("qp.el"
- "Quoted-Printable functions"
- (mail extensions))
- ("rfc1843.el"
- "HZ (rfc1843) decoding"
- (news hz hz+ mail i18n))
- ("rfc2045.el"
- "functions for decoding rfc2045 headers"
- nil)
- ("rfc2047.el"
- "functions for encoding and decoding rfc2047 messages"
- nil)
- ("rfc2104.el"
- "RFC2104 Hashed Message Authentication Codes"
- (mail))
- ("rfc2231.el"
- "functions for decoding rfc2231 headers"
- nil)
- ("score-mode.el"
- "mode for editing Gnus score files"
- (news mail))
- ("smiley-ems.el"
- "displaying smiley faces"
- (news mail multimedia))
- ("starttls.el"
- "STARTTLS functions"
- (tls ssl openssl mail news))
- ("utf7.el"
- "UTF-7 encoding/decoding for Emacs"
- (mail))
- ("uudecode.el"
- "elisp native uudecode"
- (uudecode news))
- ("webmail.el"
- "interface of web mail"
- (hotmail netaddress my-deja netscape))
("appt.el"
"appointment notification functions"
(calendar))
("em-xtra.el"
"extra alias functions"
nil)
- ("esh-arg.el"
- "argument processing"
+ ("esh-arg.el"
+ "argument processing"
+ nil)
+ ("esh-cmd.el"
+ "command invocation"
+ nil)
+ ("esh-ext.el"
+ "commands external to Eshell"
+ nil)
+ ("esh-groups.el"
+ nil
+ nil)
+ ("esh-io.el"
+ "I/O management"
+ nil)
+ ("esh-maint.el"
+ "init code for building eshell"
+ nil)
+ ("esh-mode.el"
+ "user interface"
+ nil)
+ ("esh-module.el"
+ "Eshell modules"
+ (processes))
+ ("esh-opt.el"
+ "command options processing"
+ nil)
+ ("esh-proc.el"
+ "process management"
+ nil)
+ ("esh-test.el"
+ "Eshell test suite"
+ nil)
+ ("esh-util.el"
+ "general utilities"
+ nil)
+ ("esh-var.el"
+ "handling of variables"
+ nil)
+ ("eshell.el"
+ "the Emacs command shell"
+ (processes))
+ ("binhex.el"
+ "elisp native binhex decode"
+ (binhex news))
+ ("earcon.el"
+ "sound effects for messages"
+ nil)
+ ("flow-fill.el"
+ "interprete RFC2646 \"flowed\" text"
+ (mail))
+ ("format-spec.el"
+ "functions for formatting arbitrary formatting strings"
+ (tools))
+ ("gnus-agent.el"
+ "unplugged support for Gnus"
+ nil)
+ ("gnus-art.el"
+ "article mode commands for Gnus"
+ (news))
+ ("gnus-async.el"
+ "asynchronous support for Gnus"
+ (news))
+ ("gnus-audio.el"
+ "sound effects for Gnus"
+ (news mail multimedia))
+ ("gnus-bcklg.el"
+ "backlog functions for Gnus"
+ (news))
+ ("gnus-cache.el"
+ "cache interface for Gnus"
+ (news))
+ ("gnus-cite.el"
+ "parse citations in articles for Gnus"
+ nil)
+ ("gnus-cus.el"
+ "customization commands for Gnus"
+ (news))
+ ("gnus-demon.el"
+ "daemonic Gnus behaviour"
+ (news))
+ ("gnus-draft.el"
+ "draft message support for Gnus"
+ (news))
+ ("gnus-dup.el"
+ "suppression of duplicate articles in Gnus"
+ (news))
+ ("gnus-eform.el"
+ "a mode for editing forms for Gnus"
+ (news))
+ ("gnus-ems.el"
+ "functions for making Gnus work under different Emacsen"
+ (news))
+ ("gnus-gl.el"
+ "an interface to GroupLens for Gnus"
+ (news score))
+ ("gnus-group.el"
+ "group mode commands for Gnus"
+ (news))
+ ("gnus-int.el"
+ "backend interface functions for Gnus"
+ (news))
+ ("gnus-kill.el"
+ "kill commands for Gnus"
+ (news))
+ ("gnus-logic.el"
+ "advanced scoring code for Gnus"
+ (news))
+ ("gnus-mh.el"
+ "mh-e interface for Gnus"
+ (news))
+ ("gnus-ml.el"
+ "mailing list minor mode for Gnus"
+ (news))
+ ("gnus-mlspl.el"
+ "a group params-based mail splitting mechanism"
+ (news mail))
+ ("gnus-move.el"
+ "commands for moving Gnus from one server to another"
+ (news))
+ ("gnus-msg.el"
+ "mail and post interface for Gnus"
+ (news))
+ ("gnus-mule.el"
+ "provide backward compatibility function to GNUS"
+ (news i18n))
+ ("gnus-nocem.el"
+ "NoCeM pseudo-cancellation treatment"
+ (news))
+ ("gnus-range.el"
+ "range and sequence functions for Gnus"
+ (news))
+ ("gnus-salt.el"
+ "alternate summary mode interfaces for Gnus"
+ (news))
+ ("gnus-score.el"
+ "scoring code for Gnus"
+ (news))
+ ("gnus-setup.el"
+ "initialization & setup for Gnus 5"
+ (news))
+ ("gnus-soup.el"
+ "SOUP packet writing support for Gnus"
+ (news mail))
+ ("gnus-spec.el"
+ "format spec functions for Gnus"
+ (news))
+ ("gnus-srvr.el"
+ "virtual server support for Gnus"
+ (news))
+ ("gnus-start.el"
+ "startup functions for Gnus"
+ (news))
+ ("gnus-sum.el"
+ "summary mode commands for Gnus"
+ (news))
+ ("gnus-topic.el"
+ "a folding minor mode for Gnus group buffers"
+ (news))
+ ("gnus-undo.el"
+ "minor mode for undoing in Gnus"
+ (news))
+ ("gnus-util.el"
+ "utility functions for Gnus"
+ (news))
+ ("gnus-uu.el"
+ "extract (uu)encoded files in Gnus"
+ nil)
+ ("gnus-vm.el"
+ "vm interface for Gnus"
+ (news mail))
+ ("gnus-win.el"
+ "window configuration functions for Gnus"
+ (news))
+ ("gnus.el"
+ "a newsreader for GNU Emacs"
+ (news mail))
+ ("ietf-drums.el"
+ "functions for parsing RFC822bis headers"
nil)
- ("esh-cmd.el"
- "command invocation"
+ ("imap.el"
+ "imap library"
+ (mail))
+ ("mail-parse.el"
+ "interface functions for parsing mail"
nil)
- ("esh-ext.el"
- "commands external to Eshell"
+ ("mail-prsvr.el"
+ "interface variables for parsing mail"
nil)
- ("esh-groups.el"
- nil
+ ("mail-source.el"
+ "functions for fetching mail"
+ (news mail))
+ ("mailcap.el"
+ "MIME media types configuration"
+ (news mail multimedia))
+ ("message.el"
+ "composing mail and news messages"
+ (mail news))
+ ("messcompat.el"
+ "making message mode compatible with mail mode"
+ (mail news))
+ ("mm-bodies.el"
+ "functions for decoding MIME things"
nil)
- ("esh-io.el"
- "I/O management"
+ ("mm-decode.el"
+ "functions for decoding MIME things"
nil)
- ("esh-maint.el"
- "init code for building eshell"
+ ("mm-encode.el"
+ "functions for encoding MIME things "
nil)
- ("esh-mode.el"
- "user interface"
+ ("mm-partial.el"
+ "showing message/partial"
+ (message partial))
+ ("mm-util.el"
+ "Utility functions for Mule and low level things"
nil)
- ("esh-module.el"
- "Eshell modules"
- (processes))
- ("esh-opt.el"
- "command options processing"
+ ("mm-uu.el"
+ "return uu stuff as mm handles"
+ (postscript uudecode binhex shar forward news))
+ ("mm-view.el"
+ "functions for viewing MIME objects"
nil)
- ("esh-proc.el"
- "process management"
+ ("mml.el"
+ "package for parsing and validating MML documents"
nil)
- ("esh-test.el"
- "Eshell test suite"
+ ("nnagent.el"
+ "offline backend for Gnus"
+ (news mail))
+ ("nnbabyl.el"
+ "rmail mbox access for Gnus"
+ (news mail))
+ ("nndir.el"
+ "single directory newsgroup access for Gnus"
+ (news))
+ ("nndoc.el"
+ "single file access for Gnus"
+ (news))
+ ("nndraft.el"
+ "draft article access for Gnus"
+ (news))
+ ("nneething.el"
+ "arbitrary file access for Gnus"
+ (news mail))
+ ("nnfolder.el"
+ "mail folder access for Gnus"
+ (mail))
+ ("nngateway.el"
+ "posting news via mail gateways"
+ (news mail))
+ ("nnheader.el"
+ "header access macros for Gnus and its backends"
+ (news))
+ ("nnimap.el"
+ "imap backend for Gnus"
+ (mail))
+ ("nnkiboze.el"
+ "select virtual news access for Gnus"
+ (news))
+ ("nnlistserv.el"
+ "retrieving articles via web mailing list archives"
+ (news mail))
+ ("nnmail.el"
+ "mail support functions for the Gnus mail backends"
+ (news mail))
+ ("nnmbox.el"
+ "mail mbox access for Gnus"
+ (news mail))
+ ("nnmh.el"
+ "mhspool access for Gnus"
+ (news mail))
+ ("nnml.el"
+ "mail spool access for Gnus"
+ (news mail))
+ ("nnoo.el"
+ "OO Gnus Backends"
+ (news))
+ ("nnslashdot.el"
+ "interfacing with Slashdot"
+ (news))
+ ("nnsoup.el"
+ "SOUP access for Gnus"
+ (news mail))
+ ("nnspool.el"
+ "spool access for GNU Emacs"
+ (news))
+ ("nntp.el"
+ "nntp access for Gnus"
+ (news))
+ ("nnultimate.el"
+ "interfacing with the Ultimate Bulletin Board system"
+ (news))
+ ("nnvirtual.el"
+ "virtual newsgroups access for Gnus"
+ (news))
+ ("nnwarchive.el"
+ "interfacing with web archives"
+ (news egroups mail-archive))
+ ("nnweb.el"
+ "retrieving articles via web search engines"
+ (news))
+ ("pop3.el"
+ "Post Office Protocol (RFC 1460) interface"
+ (mail))
+ ("qp.el"
+ "Quoted-Printable functions"
+ (mail extensions))
+ ("rfc1843.el"
+ "HZ (rfc1843) decoding"
+ (news hz hz+ mail i18n))
+ ("rfc2045.el"
+ "functions for decoding rfc2045 headers"
nil)
- ("esh-util.el"
- "general utilities"
+ ("rfc2047.el"
+ "functions for encoding and decoding rfc2047 messages"
nil)
- ("esh-var.el"
- "handling of variables"
+ ("rfc2104.el"
+ "RFC2104 Hashed Message Authentication Codes"
+ (mail))
+ ("rfc2231.el"
+ "functions for decoding rfc2231 headers"
nil)
- ("eshell.el"
- "the Emacs command shell"
- (processes))
+ ("score-mode.el"
+ "mode for editing Gnus score files"
+ (news mail))
+ ("smiley-ems.el"
+ "displaying smiley faces"
+ (news mail multimedia))
+ ("starttls.el"
+ "STARTTLS functions"
+ (tls ssl openssl mail news))
+ ("utf7.el"
+ "UTF-7 encoding/decoding for Emacs"
+ (mail))
+ ("uudecode.el"
+ "elisp native uudecode"
+ (uudecode news))
+ ("webmail.el"
+ "interface of web mail"
+ (hotmail netaddress my-deja netscape))
("ccl.el"
"CCL (Code Conversion Language) compiler"
(ccl mule multilingual character set coding-system))
"translation of untranslatable utf-8 to CJK"
(i18n))
("utf-8.el"
- "Limited UTF-8 decoding/encoding support"
+ "limited UTF-8 decoding/encoding support"
(multilingual unicode utf-8 i18n))
("china-util.el"
"utilities for Chinese"
("net-utils.el"
"network functions"
(network comm))
+ ("netrc.el"
+ ".netrc parsing functionality"
+ (news))
("quickurl.el"
"insert an URL based on text at point in buffer"
(hypermedia))
("underline.el"
"insert/remove underlining (done by overstriking) in Emacs"
(wp))
- ("xml-lite.el"
- "an indentation-engine for XML"
- (xml))
("tool-bar.el"
"setting up the tool bar"
(mouse frames))
;;;***
\f
-;;;### (autoloads nil "cc-langs" "progmodes/cc-langs.el" (15556 56060))
+;;;### (autoloads nil "cc-langs" "progmodes/cc-langs.el" (15557 64404))
;;; Generated autoloads from progmodes/cc-langs.el
(defvar c-mode-syntax-table nil "\
\f
;;;### (autoloads (pike-mode idl-mode java-mode objc-mode c++-mode
;;;;;; c-mode c-initialize-cc-mode) "cc-mode" "progmodes/cc-mode.el"
-;;;;;; (15556 56060))
+;;;;;; (15557 64405))
;;; Generated autoloads from progmodes/cc-mode.el
(autoload (quote c-initialize-cc-mode) "cc-mode" nil nil nil)
;;;***
\f
;;;### (autoloads (c-set-offset c-add-style c-set-style) "cc-styles"
-;;;;;; "progmodes/cc-styles.el" (15556 56060))
+;;;;;; "progmodes/cc-styles.el" (15557 64405))
;;; Generated autoloads from progmodes/cc-styles.el
(autoload (quote c-set-style) "cc-styles" "\
;;;***
\f
-;;;### (autoloads nil "cc-vars" "progmodes/cc-vars.el" (15556 56060))
+;;;### (autoloads nil "cc-vars" "progmodes/cc-vars.el" (15557 64405))
;;; Generated autoloads from progmodes/cc-vars.el
(defconst c-emacs-features (let ((infodock-p (boundp (quote infodock-version))) (comments (let ((table (copy-syntax-table)) entry) (modify-syntax-entry 97 ". 12345678" table) (cond ((arrayp table) (setq entry (aref table 97)) (if (consp entry) (setq entry (car entry)))) ((fboundp (quote get-char-table)) (setq entry (get-char-table 97 table))) ((and (fboundp (quote char-table-p)) (char-table-p table)) (setq entry (car (char-table-range table [97])))) (t (error "CC Mode is incompatible with this version of Emacs"))) (if (= (logand (lsh entry -16) 255) 255) (quote 8-bit) (quote 1-bit))))) (if infodock-p (list comments (quote infodock)) (list comments))) "\
;;;;;; customize-face customize-option-other-window customize-changed-options
;;;;;; customize-option customize-group-other-window customize-group
;;;;;; customize customize-save-variable customize-set-variable
-;;;;;; customize-set-value) "cus-edit" "cus-edit.el" (15552 23095))
+;;;;;; customize-set-value) "cus-edit" "cus-edit.el" (15561 31158))
;;; Generated autoloads from cus-edit.el
(add-hook 'same-window-regexps "\\`\\*Customiz.*\\*\\'")
(autoload (quote customize-face) "cus-edit" "\
Customize SYMBOL, which should be a face name or nil.
-If SYMBOL is nil, customize all faces." t nil)
+If SYMBOL is nil, customize all faces.
+
+Interactively, when point is on text which has a face specified,
+suggest to customized that face, if it's customizable." t nil)
(autoload (quote customize-face-other-window) "cus-edit" "\
-Show customization buffer for face SYMBOL in other window." t nil)
+Show customization buffer for face SYMBOL in other window.
+
+Interactively, when point is on text which has a face specified,
+suggest to customized that face, if it's customizable." t nil)
(autoload (quote customize-customized) "cus-edit" "\
Customize all user options set since the last save in this session." t nil)
;;;***
\f
;;;### (autoloads (diary-mail-entries diary) "diary-lib" "calendar/diary-lib.el"
-;;;;;; (15556 56042))
+;;;;;; (15557 64393))
;;; Generated autoloads from calendar/diary-lib.el
(autoload (quote diary) "diary-lib" "\
;;;;;; dired dired-copy-preserve-time dired-dwim-target dired-keep-marker-symlink
;;;;;; dired-keep-marker-hardlink dired-keep-marker-copy dired-keep-marker-rename
;;;;;; dired-trivial-filenames dired-ls-F-marks-symlinks dired-listing-switches)
-;;;;;; "dired" "dired.el" (15556 56031))
+;;;;;; "dired" "dired.el" (15557 64385))
;;; Generated autoloads from dired.el
(defvar dired-listing-switches "-al" "\
;;;***
\f
;;;### (autoloads (easy-menu-change easy-menu-create-menu easy-menu-do-define
-;;;;;; easy-menu-define) "easymenu" "emacs-lisp/easymenu.el" (15400
-;;;;;; 1475))
+;;;;;; easy-menu-define) "easymenu" "emacs-lisp/easymenu.el" (15561
+;;;;;; 31234))
;;; Generated autoloads from emacs-lisp/easymenu.el
(put (quote easy-menu-define) (quote lisp-indent-function) (quote defun))
(autoload (quote ediff-customize) "ediff-help" nil t nil)
+;;;***
+\f
+;;;### (autoloads (ediff-cond-compile-for-xemacs-or-emacs) "ediff-hook"
+;;;;;; "ediff-hook.el" (15561 31164))
+;;; Generated autoloads from ediff-hook.el
+
+(defvar ediff-window-setup-function)
+
+(autoload (quote ediff-cond-compile-for-xemacs-or-emacs) "ediff-hook" nil nil (quote macro))
+
+(ediff-cond-compile-for-xemacs-or-emacs (defun ediff-xemacs-init-menus nil (if (featurep (quote menubar)) (progn (add-submenu (quote ("Tools")) ediff-menu "OO-Browser...") (add-submenu (quote ("Tools")) ediff-merge-menu "OO-Browser...") (add-submenu (quote ("Tools")) epatch-menu "OO-Browser...") (add-submenu (quote ("Tools")) ediff-misc-menu "OO-Browser...") (add-menu-button (quote ("Tools")) "-------" "OO-Browser...")))) nil)
+
+(ediff-cond-compile-for-xemacs-or-emacs (progn (defvar ediff-menu (quote ("Compare" ["Two Files..." ediff-files t] ["Two Buffers..." ediff-buffers t] ["Three Files..." ediff-files3 t] ["Three Buffers..." ediff-buffers3 t] "---" ["Two Directories..." ediff-directories t] ["Three Directories..." ediff-directories3 t] "---" ["File with Revision..." ediff-revision t] ["Directory Revisions..." ediff-directory-revisions t] "---" ["Windows Word-by-word..." ediff-windows-wordwise t] ["Windows Line-by-line..." ediff-windows-linewise t] "---" ["Regions Word-by-word..." ediff-regions-wordwise t] ["Regions Line-by-line..." ediff-regions-linewise t]))) (defvar ediff-merge-menu (quote ("Merge" ["Files..." ediff-merge-files t] ["Files with Ancestor..." ediff-merge-files-with-ancestor t] ["Buffers..." ediff-merge-buffers t] ["Buffers with Ancestor..." ediff-merge-buffers-with-ancestor t] "---" ["Directories..." ediff-merge-directories t] ["Directories with Ancestor..." ediff-merge-directories-with-ancestor t] "---" ["Revisions..." ediff-merge-revisions t] ["Revisions with Ancestor..." ediff-merge-revisions-with-ancestor t] ["Directory Revisions..." ediff-merge-directory-revisions t] ["Directory Revisions with Ancestor..." ediff-merge-directory-revisions-with-ancestor t]))) (defvar epatch-menu (quote ("Apply Patch" ["To a file..." ediff-patch-file t] ["To a buffer..." ediff-patch-buffer t]))) (defvar ediff-misc-menu (quote ("Ediff Miscellanea" ["Ediff Manual..." ediff-documentation t] ["Customize Ediff..." ediff-customize t] ["List Ediff Sessions..." ediff-show-registry t] ["Use separate frame for Ediff control buffer..." ediff-toggle-multiframe :style toggle :selected (if (and (featurep (quote ediff-util)) (boundp (quote ediff-window-setup-function))) (eq ediff-window-setup-function (quote ediff-setup-windows-multiframe)))] ["Use a toolbar with Ediff control buffer" ediff-toggle-use-toolbar :style toggle :selected (if (featurep (quote ediff-tbar)) (ediff-use-toolbar-p))]))) (if (and (featurep (quote menubar)) (not (featurep (quote infodock))) (not (featurep (quote ediff-hook)))) (ediff-xemacs-init-menus))) (if (featurep (quote menu-bar)) (progn (defvar menu-bar-ediff-misc-menu (make-sparse-keymap "Ediff Miscellanea")) (fset (quote menu-bar-ediff-misc-menu) (symbol-value (quote menu-bar-ediff-misc-menu))) (defvar menu-bar-epatch-menu (make-sparse-keymap "Apply Patch")) (fset (quote menu-bar-epatch-menu) (symbol-value (quote menu-bar-epatch-menu))) (defvar menu-bar-ediff-merge-menu (make-sparse-keymap "Merge")) (fset (quote menu-bar-ediff-merge-menu) (symbol-value (quote menu-bar-ediff-merge-menu))) (defvar menu-bar-ediff-menu (make-sparse-keymap "Compare")) (fset (quote menu-bar-ediff-menu) (symbol-value (quote menu-bar-ediff-menu))) (define-key menu-bar-ediff-menu [window] (quote ("This Window and Next Window" . compare-windows))) (define-key menu-bar-ediff-menu [ediff-windows-linewise] (quote ("Windows Line-by-line..." . ediff-windows-linewise))) (define-key menu-bar-ediff-menu [ediff-windows-wordwise] (quote ("Windows Word-by-word..." . ediff-windows-wordwise))) (define-key menu-bar-ediff-menu [separator-ediff-windows] (quote ("--"))) (define-key menu-bar-ediff-menu [ediff-regions-linewise] (quote ("Regions Line-by-line..." . ediff-regions-linewise))) (define-key menu-bar-ediff-menu [ediff-regions-wordwise] (quote ("Regions Word-by-word..." . ediff-regions-wordwise))) (define-key menu-bar-ediff-menu [separator-ediff-regions] (quote ("--"))) (define-key menu-bar-ediff-menu [ediff-dir-revision] (quote ("Directory Revisions..." . ediff-directory-revisions))) (define-key menu-bar-ediff-menu [ediff-revision] (quote ("File with Revision..." . ediff-revision))) (define-key menu-bar-ediff-menu [separator-ediff-directories] (quote ("--"))) (define-key menu-bar-ediff-menu [ediff-directories3] (quote ("Three Directories..." . ediff-directories3))) (define-key menu-bar-ediff-menu [ediff-directories] (quote ("Two Directories..." . ediff-directories))) (define-key menu-bar-ediff-menu [separator-ediff-files] (quote ("--"))) (define-key menu-bar-ediff-menu [ediff-buffers3] (quote ("Three Buffers..." . ediff-buffers3))) (define-key menu-bar-ediff-menu [ediff-files3] (quote ("Three Files..." . ediff-files3))) (define-key menu-bar-ediff-menu [ediff-buffers] (quote ("Two Buffers..." . ediff-buffers))) (define-key menu-bar-ediff-menu [ediff-files] (quote ("Two Files..." . ediff-files))) (define-key menu-bar-ediff-merge-menu [ediff-merge-dir-revisions-with-ancestor] (quote ("Directory Revisions with Ancestor..." . ediff-merge-directory-revisions-with-ancestor))) (define-key menu-bar-ediff-merge-menu [ediff-merge-dir-revisions] (quote ("Directory Revisions..." . ediff-merge-directory-revisions))) (define-key menu-bar-ediff-merge-menu [ediff-merge-revisions-with-ancestor] (quote ("Revisions with Ancestor..." . ediff-merge-revisions-with-ancestor))) (define-key menu-bar-ediff-merge-menu [ediff-merge-revisions] (quote ("Revisions..." . ediff-merge-revisions))) (define-key menu-bar-ediff-merge-menu [separator-ediff-merge] (quote ("--"))) (define-key menu-bar-ediff-merge-menu [ediff-merge-directories-with-ancestor] (quote ("Directories with Ancestor..." . ediff-merge-directories-with-ancestor))) (define-key menu-bar-ediff-merge-menu [ediff-merge-directories] (quote ("Directories..." . ediff-merge-directories))) (define-key menu-bar-ediff-merge-menu [separator-ediff-merge-dirs] (quote ("--"))) (define-key menu-bar-ediff-merge-menu [ediff-merge-buffers-with-ancestor] (quote ("Buffers with Ancestor..." . ediff-merge-buffers-with-ancestor))) (define-key menu-bar-ediff-merge-menu [ediff-merge-buffers] (quote ("Buffers..." . ediff-merge-buffers))) (define-key menu-bar-ediff-merge-menu [ediff-merge-files-with-ancestor] (quote ("Files with Ancestor..." . ediff-merge-files-with-ancestor))) (define-key menu-bar-ediff-merge-menu [ediff-merge-files] (quote ("Files..." . ediff-merge-files))) (define-key menu-bar-epatch-menu [ediff-patch-buffer] (quote ("To a Buffer..." . ediff-patch-buffer))) (define-key menu-bar-epatch-menu [ediff-patch-file] (quote ("To a File..." . ediff-patch-file))) (define-key menu-bar-ediff-misc-menu [emultiframe] (quote ("Toggle use of separate control buffer frame..." . ediff-toggle-multiframe))) (define-key menu-bar-ediff-misc-menu [eregistry] (quote ("List Ediff Sessions..." . ediff-show-registry))) (define-key menu-bar-ediff-misc-menu [ediff-cust] (quote ("Customize Ediff..." . ediff-customize))) (define-key menu-bar-ediff-misc-menu [ediff-doc] (quote ("Ediff Manual..." . ediff-documentation))))))
+
;;;***
\f
;;;### (autoloads (ediff-show-registry) "ediff-mult" "ediff-mult.el"
;;;***
\f
-;;;### (autoloads (f90-mode) "f90" "progmodes/f90.el" (15552 23097))
+;;;### (autoloads (f90-mode) "f90" "progmodes/f90.el" (15561 31347))
;;; Generated autoloads from progmodes/f90.el
(autoload (quote f90-mode) "f90" "\
-Major mode for editing Fortran 90 code in free format.
+Major mode for editing Fortran 90,95 code in free format.
\\[f90-indent-new-line] corrects current indentation and creates new indented line.
-\\[f90-indent-line] indents the current line correctly.
-\\[f90-indent-subprogram] indents the current subprogram.
+\\[f90-indent-line] indents the current line correctly.
+\\[f90-indent-subprogram] indents the current subprogram.
Type `? or `\\[help-command] to display a list of built-in abbrevs for F90 keywords.
Variables controlling indentation style and extra features:
- f90-do-indent
+ `f90-do-indent'
Extra indentation within do blocks. (default 3)
- f90-if-indent
- Extra indentation within if/select case/where/forall blocks. (default 3)
- f90-type-indent
+ `f90-if-indent'
+ Extra indentation within if/select case/where/forall blocks. (default 3)
+ `f90-type-indent'
Extra indentation within type/interface/block-data blocks. (default 3)
- f90-program-indent
+ `f90-program-indent'
Extra indentation within program/module/subroutine/function blocks.
- (default 2)
- f90-continuation-indent
+ (default 2)
+ `f90-continuation-indent'
Extra indentation applied to continuation lines. (default 5)
- f90-comment-region
+ `f90-comment-region'
String inserted by \\[f90-comment-region] at start of each line in
region. (default \"!!!$\")
- f90-indented-comment-re
+ `f90-indented-comment-re'
Regexp determining the type of comment to be intended like code.
(default \"!\")
- f90-directive-comment-re
+ `f90-directive-comment-re'
Regexp of comment-like directive like \"!HPF\\\\$\", not to be indented.
(default \"!hpf\\\\$\")
- f90-break-delimiters
+ `f90-break-delimiters'
Regexp holding list of delimiters at which lines may be broken.
(default \"[-+*/><=,% \\t]\")
- f90-break-before-delimiters
+ `f90-break-before-delimiters'
Non-nil causes `f90-do-auto-fill' to break lines before delimiters.
(default t)
- f90-beginning-ampersand
+ `f90-beginning-ampersand'
Automatic insertion of & at beginning of continuation lines. (default t)
- f90-smart-end
+ `f90-smart-end'
From an END statement, check and fill the end using matching block start.
Allowed values are 'blink, 'no-blink, and nil, which determine
- whether to blink the matching beginning.) (default 'blink)
- f90-auto-keyword-case
- Automatic change of case of keywords. (default nil)
+ whether to blink the matching beginning. (default 'blink)
+ `f90-auto-keyword-case'
+ Automatic change of case of keywords. (default nil)
The possibilities are 'downcase-word, 'upcase-word, 'capitalize-word.
- f90-leave-line-no
- Do not left-justify line numbers. (default nil)
- f90-startup-message
- Set to nil to inhibit message first time F90 mode is used. (default t)
- f90-keywords-re
+ `f90-leave-line-no'
+ Do not left-justify line numbers. (default nil)
+ `f90-keywords-re'
List of keywords used for highlighting/upcase-keywords etc.
Turning on F90 mode calls the value of the variable `f90-mode-hook'
;;;;;; facemenu-remove-special facemenu-remove-all facemenu-remove-face-props
;;;;;; facemenu-set-read-only facemenu-set-intangible facemenu-set-invisible
;;;;;; facemenu-set-face-from-menu facemenu-set-background facemenu-set-foreground
-;;;;;; facemenu-set-face) "facemenu" "facemenu.el" (15552 23095))
+;;;;;; facemenu-set-face) "facemenu" "facemenu.el" (15557 64385))
;;; Generated autoloads from facemenu.el
(define-key global-map "\M-g" 'facemenu-keymap)
(autoload 'facemenu-keymap "facemenu" "Keymap for face-changing commands." t 'keymap)
;;;***
\f
;;;### (autoloads (find-grep-dired find-name-dired find-dired find-grep-options
-;;;;;; find-ls-option) "find-dired" "find-dired.el" (15505 59086))
+;;;;;; find-ls-option) "find-dired" "find-dired.el" (15561 31174))
;;; Generated autoloads from find-dired.el
(defvar find-ls-option (if (eq system-type (quote berkeley-unix)) (quote ("-ls" . "-gilsb")) (quote ("-exec ls -ld {} \\;" . "-ld"))) "\
\f
;;;### (autoloads (ff-mouse-find-other-file-other-window ff-mouse-find-other-file
;;;;;; ff-find-other-file ff-get-other-file) "find-file" "find-file.el"
-;;;;;; (15400 1472))
+;;;;;; (15561 31174))
;;; Generated autoloads from find-file.el
(autoload (quote ff-get-other-file) "find-file" "\
;;;***
\f
;;;### (autoloads (fortran-mode fortran-tab-mode-default) "fortran"
-;;;;;; "progmodes/fortran.el" (15555 1627))
+;;;;;; "progmodes/fortran.el" (15557 64405))
;;; Generated autoloads from progmodes/fortran.el
(defvar fortran-tab-mode-default nil "\
;;;### (autoloads (global-highlight-changes highlight-compare-with-file
;;;;;; highlight-changes-rotate-faces highlight-changes-previous-change
;;;;;; highlight-changes-next-change highlight-changes-mode highlight-changes-remove-highlight)
-;;;;;; "hilit-chg" "hilit-chg.el" (15556 56033))
+;;;;;; "hilit-chg" "hilit-chg.el" (15557 64386))
;;; Generated autoloads from hilit-chg.el
(defvar highlight-changes-mode nil)
;;;;;; ibuffer-add-saved-filters ibuffer-delete-saved-filters ibuffer-save-filters
;;;;;; ibuffer-or-filter ibuffer-negate-filter ibuffer-exchange-filters
;;;;;; ibuffer-decompose-filter ibuffer-pop-filter ibuffer-filter-disable
-;;;;;; ibuffer-jump-to-filter-group ibuffer-pop-filter-group ibuffer-filters-to-filter-group
-;;;;;; ibuffer-included-in-filters-p ibuffer-backward-filter-group
-;;;;;; ibuffer-forward-filter-group ibuffer-toggle-filter-group
-;;;;;; ibuffer-mouse-toggle-filter-group ibuffer-interactive-filter-by-mode
-;;;;;; ibuffer-mouse-filter-by-mode ibuffer-auto-mode) "ibuf-ext"
-;;;;;; "ibuf-ext.el" (15559 5574))
+;;;;;; ibuffer-switch-to-saved-filter-groups ibuffer-delete-saved-filter-groups
+;;;;;; ibuffer-save-filter-groups ibuffer-yank ibuffer-kill-line
+;;;;;; ibuffer-kill-filter-group ibuffer-jump-to-filter-group ibuffer-clear-filter-groups
+;;;;;; ibuffer-pop-filter-group ibuffer-set-filter-groups-by-mode
+;;;;;; ibuffer-filters-to-filter-group ibuffer-included-in-filters-p
+;;;;;; ibuffer-backward-filter-group ibuffer-forward-filter-group
+;;;;;; ibuffer-toggle-filter-group ibuffer-mouse-toggle-filter-group
+;;;;;; ibuffer-interactive-filter-by-mode ibuffer-mouse-filter-by-mode
+;;;;;; ibuffer-auto-mode) "ibuf-ext" "ibuf-ext.el" (15561 31179))
;;; Generated autoloads from ibuf-ext.el
(autoload (quote ibuffer-auto-mode) "ibuf-ext" "\
(autoload (quote ibuffer-filters-to-filter-group) "ibuf-ext" "\
Make the current filters into a filtering group." t nil)
+(autoload (quote ibuffer-set-filter-groups-by-mode) "ibuf-ext" "\
+Set the current filter groups to filter by mode." t nil)
+
(autoload (quote ibuffer-pop-filter-group) "ibuf-ext" "\
Remove the first filtering group." t nil)
+(autoload (quote ibuffer-clear-filter-groups) "ibuf-ext" "\
+Remove all filtering groups." t nil)
+
(autoload (quote ibuffer-jump-to-filter-group) "ibuf-ext" "\
Move point to the filter group whose name is NAME." t nil)
+(autoload (quote ibuffer-kill-filter-group) "ibuf-ext" "\
+Delete the filtering group named NAME." t nil)
+
+(autoload (quote ibuffer-kill-line) "ibuf-ext" nil t nil)
+
+(autoload (quote ibuffer-yank) "ibuf-ext" nil t nil)
+
+(autoload (quote ibuffer-save-filter-groups) "ibuf-ext" "\
+Save all active filter groups GROUPS as NAME.
+They are added to `ibuffer-saved-filter-groups'. Interactively,
+prompt for NAME, and use the current filters." t nil)
+
+(autoload (quote ibuffer-delete-saved-filter-groups) "ibuf-ext" "\
+Delete saved filter groups with NAME.
+They are removed from `ibuffer-saved-filter-groups'." t nil)
+
+(autoload (quote ibuffer-switch-to-saved-filter-groups) "ibuf-ext" "\
+Set this buffer's filter groups to saved version with NAME.
+The value from `ibuffer-saved-filters' is used.
+If prefix argument ADD is non-nil, then add the saved filters instead
+of replacing the current filters." t nil)
+
(autoload (quote ibuffer-filter-disable) "ibuf-ext" "\
Disable all filters currently in effect in this buffer." t nil)
;;;***
\f
;;;### (autoloads (define-ibuffer-filter define-ibuffer-op define-ibuffer-sorter
-;;;;;; define-ibuffer-column) "ibuf-macs" "ibuf-macs.el" (15559
-;;;;;; 4758))
+;;;;;; define-ibuffer-column) "ibuf-macs" "ibuf-macs.el" (15561
+;;;;;; 31179))
;;; Generated autoloads from ibuf-macs.el
(autoload (quote define-ibuffer-column) "ibuf-macs" "\
;;;***
\f
;;;### (autoloads (ibuffer ibuffer-other-window ibuffer-list-buffers)
-;;;;;; "ibuffer" "ibuffer.el" (15559 12617))
+;;;;;; "ibuffer" "ibuffer.el" (15561 31180))
;;; Generated autoloads from ibuffer.el
(autoload (quote ibuffer-list-buffers) "ibuffer" "\
Optional argument SHRINK means shrink the buffer to minimal size. The
special value `onewindow' means always use another window.
Optional argument FILTER-GROUPS is an initial set of filtering
-groups to use; see `ibuffer-filtering-groups'." t nil)
+groups to use; see `ibuffer-filter-groups'." t nil)
;;;***
\f
;;;***
\f
;;;### (autoloads (define-mail-abbrev build-mail-abbrevs mail-abbrevs-setup)
-;;;;;; "mailabbrev" "mail/mailabbrev.el" (15552 23097))
+;;;;;; "mailabbrev" "mail/mailabbrev.el" (15557 64401))
;;; Generated autoloads from mail/mailabbrev.el
(autoload (quote mail-abbrevs-setup) "mailabbrev" "\
;;;;;; describe-current-coding-system describe-current-coding-system-briefly
;;;;;; describe-coding-system describe-char-after describe-character-set
;;;;;; list-charset-chars read-charset list-character-sets) "mule-diag"
-;;;;;; "international/mule-diag.el" (15556 56053))
+;;;;;; "international/mule-diag.el" (15557 64400))
;;; Generated autoloads from international/mule-diag.el
(autoload (quote list-character-sets) "mule-diag" "\
;;;### (autoloads (clear-rectangle string-insert-rectangle string-rectangle
;;;;;; delete-whitespace-rectangle open-rectangle insert-rectangle
;;;;;; yank-rectangle kill-rectangle extract-rectangle delete-extract-rectangle
-;;;;;; delete-rectangle move-to-column-force) "rect" "rect.el" (15552
-;;;;;; 23097))
+;;;;;; delete-rectangle move-to-column-force) "rect" "rect.el" (15557
+;;;;;; 64391))
;;; Generated autoloads from rect.el
(autoload (quote move-to-column-force) "rect" "\
;;;***
\f
;;;### (autoloads (scroll-all-mode scroll-all-mode) "scroll-all"
-;;;;;; "scroll-all.el" (15559 7260))
+;;;;;; "scroll-all.el" (15561 31204))
;;; Generated autoloads from scroll-all.el
(defvar scroll-all-mode nil "\
;;;;;; mail-archive-file-name mail-header-separator send-mail-function
;;;;;; mail-yank-ignored-headers mail-interactive mail-self-blind
;;;;;; mail-specify-envelope-from mail-from-style) "sendmail" "mail/sendmail.el"
-;;;;;; (15505 59088))
+;;;;;; (15561 31320))
;;; Generated autoloads from mail/sendmail.el
(defvar mail-from-style (quote angles) "\
;;;***
\f
;;;### (autoloads (smtpmail-send-it) "smtpmail" "mail/smtpmail.el"
-;;;;;; (15417 7425))
+;;;;;; (15561 31320))
;;; Generated autoloads from mail/smtpmail.el
(autoload (quote smtpmail-send-it) "smtpmail" nil nil nil)
;;;***
\f
;;;### (autoloads (tmm-prompt tmm-menubar-mouse tmm-menubar) "tmm"
-;;;;;; "tmm.el" (15556 56039))
+;;;;;; "tmm.el" (15557 64393))
;;; Generated autoloads from tmm.el
(define-key global-map "\M-`" 'tmm-menubar)
(define-key global-map [f10] 'tmm-menubar)
\f
;;;### (autoloads (tool-bar-local-item-from-menu tool-bar-add-item-from-menu
;;;;;; tool-bar-local-item tool-bar-add-item tool-bar-mode) "tool-bar"
-;;;;;; "toolbar/tool-bar.el" (15552 23097))
+;;;;;; "toolbar/tool-bar.el" (15557 64408))
;;; Generated autoloads from toolbar/tool-bar.el
(defvar tool-bar-mode nil "\
;;;***
\f
-;;;### (autoloads nil nil ("international/mule-cmds.el" "eshell/esh-ext.el"
+;;;### (autoloads nil nil ("term/x-win.el" "progmodes/cc-cmds.el"
+;;;;;; "replace.el" "menu-bar.el" "international/mule-cmds.el" "eshell/esh-ext.el"
;;;;;; "emulation/viper-ex.el" "calc/calc-bin.el" "loadup.el" "frame.el"
;;;;;; "faces.el" "ediff-init.el" "bindings.el" "international/mule-conf.el"
;;;;;; "calendar/cal-french.el" "textmodes/texnfo-upd.el" "language/slovak.el"
;;;;;; "eshell/em-glob.el" "eshell/em-dirs.el" "eshell/em-cmpl.el"
;;;;;; "eshell/em-alias.el" "emacs-lisp/lisp.el" "mail/uce.el" "gnus/mm-encode.el"
;;;;;; "tempo.el" "emulation/viper-util.el" "gnus/mml.el" "gnus/mm-view.el"
-;;;;;; "calendar/cal-menu.el" "indent.el" "ediff-wind.el" "ediff-hook.el"
-;;;;;; "term/sun-mouse.el" "emacs-lisp/lisp-mode.el" "progmodes/mantemp.el"
-;;;;;; "progmodes/idlw-toolbar.el" "progmodes/ebnf-yac.el" "progmodes/ebnf-otz.el"
-;;;;;; "progmodes/ebnf-iso.el" "progmodes/ebnf-bnf.el" "play/meese.el"
-;;;;;; "play/gametree.el" "obsolete/x-menu.el" "obsolete/x-apollo.el"
-;;;;;; "obsolete/uncompress.el" "obsolete/sun-fns.el" "obsolete/sun-curs.el"
-;;;;;; "obsolete/sc.el" "obsolete/rnews.el" "obsolete/profile.el"
-;;;;;; "obsolete/ooutline.el" "obsolete/c-mode.el" "mail/vms-pmail.el"
-;;;;;; "mail/rfc822.el" "mail/rfc2368.el" "mail/mspools.el" "mail/mh-seq.el"
-;;;;;; "mail/mh-funcs.el" "mail/mailpost.el" "mail/mailheader.el"
-;;;;;; "mail/blessmail.el" "language/romanian.el" "language/misc-lang.el"
-;;;;;; "language/ethiopic.el" "language/english.el" "language/devanagari.el"
-;;;;;; "international/swedish.el" "international/latin-9.el" "international/latin-8.el"
-;;;;;; "international/latin-5.el" "international/latin-4.el" "international/latin-3.el"
-;;;;;; "international/latin-2.el" "international/latin-1.el" "international/ja-dic-utl.el"
+;;;;;; "calendar/cal-menu.el" "indent.el" "ediff-wind.el" "term/sun-mouse.el"
+;;;;;; "emacs-lisp/lisp-mode.el" "progmodes/mantemp.el" "progmodes/idlw-toolbar.el"
+;;;;;; "progmodes/ebnf-yac.el" "progmodes/ebnf-otz.el" "progmodes/ebnf-iso.el"
+;;;;;; "progmodes/ebnf-bnf.el" "play/meese.el" "play/gametree.el"
+;;;;;; "obsolete/x-menu.el" "obsolete/x-apollo.el" "obsolete/uncompress.el"
+;;;;;; "obsolete/sun-fns.el" "obsolete/sun-curs.el" "obsolete/sc.el"
+;;;;;; "obsolete/rnews.el" "obsolete/profile.el" "obsolete/ooutline.el"
+;;;;;; "obsolete/c-mode.el" "mail/vms-pmail.el" "mail/rfc822.el"
+;;;;;; "mail/rfc2368.el" "mail/mspools.el" "mail/mh-seq.el" "mail/mh-funcs.el"
+;;;;;; "mail/mailpost.el" "mail/mailheader.el" "mail/blessmail.el"
+;;;;;; "language/romanian.el" "language/misc-lang.el" "language/ethiopic.el"
+;;;;;; "language/english.el" "language/devanagari.el" "international/swedish.el"
+;;;;;; "international/latin-9.el" "international/latin-8.el" "international/latin-5.el"
+;;;;;; "international/latin-4.el" "international/latin-3.el" "international/latin-2.el"
+;;;;;; "international/latin-1.el" "international/ja-dic-utl.el"
;;;;;; "international/ja-dic-cnv.el" "international/iso-swed.el"
;;;;;; "international/iso-ascii.el" "calc/calcsel2.el" "calc/calccomp.el"
;;;;;; "calc/calc-yank.el" "calc/calc-vec.el" "calc/calc-units.el"
;;;;;; "calc/calc-graph.el" "ediff-diff.el" "ediff-ptch.el" "pcvs-parse.el"
;;;;;; "gnus/mail-source.el" "gnus/mm-decode.el" "gnus/mm-util.el"
;;;;;; "gnus/nneething.el" "international/ucs-tables.el" "allout.el"
-;;;;;; "cus-load.el" "cus-start.el" "finder-inf.el" "format.el"
-;;;;;; "help.el" "isearch.el" "mouse.el" "pcvs-info.el" "window.el"
-;;;;;; "calc/calc-misc.el" "gnus/gnus-ems.el" "gnus/gnus-sum.el"
-;;;;;; "gnus/gnus-uu.el" "gnus/nnimap.el" "gnus/nnmbox.el" "gnus/nnwarchive.el"
-;;;;;; "gnus/pop3.el" "calendar/cal-tex.el" "emacs-lisp/byte-opt.el"
-;;;;;; "emacs-lisp/lucid.el" "international/utf-8.el" "progmodes/ada-prj.el"
-;;;;;; "progmodes/idlw-rinfo.el" "textmodes/fill.el" "custom.el"
-;;;;;; "files.el" "menu-bar.el" "register.el" "replace.el" "simple.el"
-;;;;;; "startup.el" "subr.el" "net/netrc.el" "play/gamegrid.el"
-;;;;;; "progmodes/cc-align.el" "progmodes/cc-bytecomp.el" "progmodes/cc-cmds.el"
-;;;;;; "progmodes/cc-compat.el" "progmodes/cc-defs.el" "progmodes/cc-engine.el"
-;;;;;; "progmodes/cc-menus.el" "term/x-win.el" "subdirs.el" "eshell/esh-groups.el")
-;;;;;; (15559 13260 596690))
+;;;;;; "cus-start.el" "format.el" "help.el" "isearch.el" "mouse.el"
+;;;;;; "pcvs-info.el" "window.el" "calc/calc-misc.el" "gnus/gnus-ems.el"
+;;;;;; "gnus/gnus-sum.el" "gnus/gnus-uu.el" "gnus/nnimap.el" "gnus/nnmbox.el"
+;;;;;; "gnus/nnwarchive.el" "gnus/pop3.el" "calendar/cal-tex.el"
+;;;;;; "emacs-lisp/byte-opt.el" "emacs-lisp/lucid.el" "international/utf-8.el"
+;;;;;; "progmodes/ada-prj.el" "progmodes/idlw-rinfo.el" "textmodes/fill.el"
+;;;;;; "custom.el" "files.el" "register.el" "simple.el" "startup.el"
+;;;;;; "subr.el" "net/netrc.el" "play/gamegrid.el" "progmodes/cc-align.el"
+;;;;;; "progmodes/cc-bytecomp.el" "progmodes/cc-compat.el" "progmodes/cc-defs.el"
+;;;;;; "progmodes/cc-engine.el" "progmodes/cc-menus.el" "cus-load.el"
+;;;;;; "finder-inf.el" "subdirs.el" "eshell/esh-groups.el") (15561
+;;;;;; 41889 615042))
;;;***
\f
;; Copyright (C) 1999, 2000 Free Software Foundation, Inc.
-;; Author: Andrew Choi <akochoi@i-cable.com>
+;; Author: Andrew Choi <akochoi@mac.com>
;; This file is part of GNU Emacs.
;; X Window emulation in macterm.c is not complete enough to start a
;; frame without a minibuffer properly. Call this to tell ediff
;; library to use a single frame.
-(ediff-toggle-multiframe)
+; (ediff-toggle-multiframe)
;; Setup to use the Mac clipboard. The functions mac-cut-function and
;; mac-paste-function are defined in mac.c.
;; big5 or sjis
(setq file-name-coding-system 'mac-roman)
+;; If Emacs is started from the Finder, change the default directory
+;; to the user's home directory.
+(if (string= default-directory "/")
+ (cd "~"))
+
+;; Tell Emacs to use pipes instead of pty's for processes because the
+;; latter sometimes lose characters. Pty support is compiled in since
+;; ange-ftp will not work without it.
+(setq process-connection-type nil)
+
;; (prefer-coding-system 'mac-roman)
;;
+2002-04-13 Andrew Choi <akochoi@shaw.ca>
+
+ * Emacs.app/Contents/Info.plist: New file.
+
+ * Emacs.app/Contents/PkgInfo: New file.
+
+ * Emacs.app/Contents/Resources/English.lproj/InfoPlist.strings:
+ New file.
+
+ * cw5-mcp.xml: Remove file.
+
+ * inc/defs-cw5.h: Remove file.
+
+ * cw6-mcp.xml: Update with new version.
+
+ * mac/inc/defs-cw6.h: New constant MAC_OS8. Remove definition
+ of constant CODEWARRIOR_VERSION_6.
+
+ * mac/src/mac.c:
+ * mac/src/macmenu.c:
+ * mac/src/macterm.c:
+ Test constant __MSL__ instead of CODEWARRIOR_VERSION_6.
+
+ * src/Carbon.r: New File.
+
+ * makefile.MPW: Define MAC_OS and MAC_OS8. Update with change of
+ locations for mac.c, macfns.c, macgui.h, macmenu.c, macterm.c, and
+ macterm.h. Generate DOC from .el instead of .elc versions of
+ files listed in DONTCOMPILE in lisp/Makefile.in.
+
+ * INSTALL: Add installation instructions for Mac OS X.
+
+ * README: Add information for Mac OS X.
+
+ * src/mac.c, inc/macgui.h, src/macfns.c, src/macmenu.c,
+ src/macterm.c, inc/macterm.h: Remove from here and move to src.
+
+2002-04-12 Andrew Choi <akochoi@shaw.ca>
+
+ * src/mac.c (select): Under Carbon, always return true so
+ XTread_socket is called to poll input.
+ (run_mac_command): Not implemented under Carbon.
+ (get_wd): Call PBHGetVolSync and path_from_vol_dir_name to
+ establish pathname.
+ (do_applescript): Use Carbon routines AEGetDescDatASize and
+ AEGetDescData.
+ (Fmac_paste_function): Use Carbon routines GetCurrentScrap,
+ GetScrapFlavorFlags, GetScrapFlavorSize, and GetScrapFlavorData.
+ (Fmac_cut_function): Use Carbon routines ClearCurrentScrap,
+ GetCurrentScrap, and PutScrapFlavor.
+ (Fx_selection_exists_p): Use Carbon routines GetCurrentScrap and
+ GetScrapFlavorFlags.
+
+ * src/macfns.c: Synchronize with changes in w32fns.c.
+ [MAC_OSX]: Include Carbon headers.
+ (x_real_positions): Use Carbon routine GetWindowPortBounds.
+ (x_set_scroll_bar_width): Set width of scroll bar to 16.
+ (x_make_gc): Remove static qualifier.
+
+ * src/macmenu.c: Synchronize with changes in w32menu.c.
+ [MAC_OSX]: Include Carbon headers.
+ (set_frame_menubar): Check equality of vector representation of
+ scroll bars using Fequal instead of EQ.
+ (mac_menu_show): Use Carbon routine GetWindowPort.
+ (mac_dialog): Likewise.
+ (add_menu_item): Use Carbon routines CountMenuItems,
+ EnableMenuItem, and DisableMenuItem.
+
+ * src/macterm.c: Synchronize with changes in w32term.c.
+ [MAC_OSX]: Include Carbon headers.
+ (XDrawLine): Use Carbon routine GetWindowPort.
+ (XClearArea): Likewise.
+ (XClearWindow): Use Carbon routines GetWindowPort and
+ GetWindowPortBounds.
+ (mac_draw_bitmap): Use Carbon routines GetWindowPort and
+ GetPortPixMap.
+ (mac_set_clip_rectangle): Use Carbon routine GetWindowPort.
+ (mac_reset_clipping): Use Carbon routine GetWindowPort.
+ (XFillRectangle): Likewise.
+ (mac_draw_rectangle): Likewise.
+ (mac_draw_rectangle_to_pixmap): Likewise.
+ (mac_draw_string_common): Likewise.
+ (mac_copy_area): Use Carbon routines GetWindowPort and
+ GetPortPixMap.
+ (mac_scroll_area): Use Carbon routines GetWindowPort and
+ GetQDGlobalsScreenBits.
+ (x_flush): Call Carbon routine QDFlushPortBuffer.
+ (x_update_end): Use Carbon routine GetWindowPort; call x_flush.
+ (x_draw_fringe_bitmap): Call mac_reset_clipping before returning.
+ (x_draw_image_glyph_string): Likewise.
+ (x_draw_stretch_glyph_string): Likewise.
+ (construct_mouse_click): Call Carbon routine GetWindowPort.
+ (note_mouse_movement): Call Carbon routine GetWindowPortBounds.
+ (XTmouse_position): Call Carbon routine GetWindowPort.
+ (x_scroll_bar_create): Create scroll bar with proc
+ kControlScrollBarProc.
+ (XTset_vertical_scroll_bar) [MAC_OSX]: Set width to 16.
+ (activate_scroll_bar): Call ActivateControl instead of
+ SetControlMaximum.
+ (deactivate_scroll_bar): Call DeactivateControl instead of
+ SetControlMaximum.
+ (x_scroll_bar_handle_click): Use default case for scroll
+ indicator.
+ (x_scroll_bar_report_motion): Call Carbon routine GetWindowPort.
+ (x_calc_absolute_position): Call Carbon routines GetWindowPort and
+ GetWindowPortBounds.
+ (init_font_name_table): Call Carbon Font Manager routines to
+ iterate through all fonts.
+ (XLoadQueryFont): Call Carbon routines GetPortTextFont,
+ GetPortTextSize, and GetPortTextFace.
+ (do_init_managers): Do not initialize Mac Toolbox under Carbon.
+ (is_emacs_window): New function to filter out non-Emacs windows
+ passed back by WaitNextEvent.
+ (do_mouse_moved): Call Carbon routine GetWindowPort.
+ (do_apple_menu): No apple menu handler under Carbon.
+ (do_zoom_window): Call Carbon routines GetWindowPort,
+ GetQDGlobalsScreenBits, SetWindowStandardState, and
+ GetWindowPortBounds.
+ (init_required_apple_events): Use UPP procedure type converter.
+ (main): Don't define for Carbon version.
+ (XTread_socket): Don't check interrupt_input_blocked. Don't call
+ check_alarm. Call Carbon routines GetWindowPort,
+ GetQDGlobalScreenBits, GetWindowPortBounds, and InvalWindowRect.
+ (NewMacWindow): Set making_terminal_window to 0. Call Carbon
+ routine GetWindowPort.
+ (mac_initialize): Rename from x_initialize. Use new Doc string
+ format.
+
+ * inc/macterm.h: Synchronize with changes in w32term.h.
+
+ * inc/macgui.h [MAC_OSX]: Use OpaqueWindowPtr* instead of
+ WindowPtr.
+
2002-01-28 Kim F. Storm <storm@cua.dk>
* src/macterm.c (x_erase_phys_cursor): Don't erase cursor if
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.9">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>Emacs</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>0.1</string>
+</dict>
+</plist>
--- /dev/null
+APPL????
\ No newline at end of file
--- /dev/null
+/* Localized versions of Info.plist keys */
+
+CFBundleName = "Emacs";
+CFBundleShortVersionString = "Emacs version 21";
+CFBundleGetInfoString = "Emacs version 21, Copyright 2002 FSF.";
-* BUILDING EMACS ON THE MAC OS -*- outline -*-
+* BUILDING EMACS ON MAC OS 8/9 AND MAC OS X -*- outline -*-
-Copyright (c) 2001 Free Software Foundation, Inc.
+Copyright (c) 2001, 2002 Free Software Foundation, Inc.
Permission is granted to anyone to make or distribute verbatim
copies of this document as received, in any medium, provided that
provided also that they carry prominent notices stating who last
changed them.
-You can use either Metrowerks CodeWarrior Pro 5 or 6 or MPW-GM
-(Aug. 2000) to build Emacs.
+* BUILDING EMACS ON MAC OS X
-You will need MPW-GM to build the make-docfile utility and to generate
-the doc string file DOC.
+You should be able to build Emacs on Mac OS X by typing the following
+commands at the top-level directory after the source distribution is
+un-tarred.
-To decompress files, you can use MacGzip from
+ ./configure
+ make
+ make install
- http://persephone.cps.unizar.es/~spd/gzip
+The last step must be performed as root.
-and to untar them, you can use tar 4.0 from
+If you have X Window installed, you need to type `./configure
+--without-x' instead of `./configure'.
- http://hyperarchive.lcs.mit.edu/HyperArchive/Archive/cmp/tar-40b.hqx
+You can type `make bootstrap' instead of `make' to rebuild everything,
+including byte-compiling the Lisp files.
-(Optional) If you wish to fetch files from the Emacs CVS repository
-directly to your Mac, you can use the CVS client MacCVS, which can be
-downloaded from
+If you have not installed the GNU texinfo package on your system, the
+build will complain that makeinfo cannot be found. Instructions for
+installing the GNU texinfo package are given below. Alternatively,
+you can type `make -k' instead of `make' and safely ignore the error
+messages and use the existing info files.
- http://www.wincvs.org/
+After Emacs is installed, you can run it by typing `emacs -nw' from a
+terminal (make sure your path contains /usr/local/bin) or by
+double-clicking on mac/Emacs.app in the Finder. At present,
+command-line options cannot be passed to Emacs running under the Aqua
+GUI. This should soon be fixed.
-(Optional) A subset of the fonts from the GNU intlfonts-1.2
-distribution converted to NFNT format can be obtained from
+To use colors in a terminal, put the following lines in the file
+~/.termcap and log in again.
- ftp://mac-emacs.sourceforge.net/pub/mac-emacs/GNU-fonts.smi.bin
+-----
+# added ANSI color
+vt100|vt100-am|vt100am|dec vt100:\
+ :pa#64:Co#8:Sf=\E[3%dm:Sb=\E[4%dm:op=\E[m:AF=\E[3%dm:AB=\E[4%dm:\
+ :do=^J:co#80:li#24:cl=\E[;H\E[2J:sf=2*\ED:\
+ :le=^H:bs:am:cm=5\E[%i%d;%dH:nd=2\E[C:up=2\E[A:\
+ :ce=3\E[K:cd=50\E[J:so=2\E[7m:se=2\E[m:us=2\E[4m:ue=2\E[m:\
+ :md=2\E[1m:mr=2\E[7m:mb=2\E[5m:me=2\E[m:\
+ :rf=/usr/share/tabset/vt100:\
+ :rs=\E>\E[?3l\E[?4l\E[?5l\E[?7h\E[?8h\E[;r\E[0m\E(B\E)B\E[2J:\
+ :ks=\E[?1h\E=:ke=\E[?1l\E>:\
+ :ku=\EOA:kd=\EOB:kr=\EOC:kl=\EOD:kb=^H:\
+ :ho=\E[H:k1=\EOP:k2=\EOQ:k3=\EOR:k4=\EOS:pt:sr=2*\EM:vt#3:xn:\
+ :sc=\E7:rc=\E8:cs=\E[%i%d;%dr:
+-----
+
+To build a binary distribution of Emacs for Mac OS X, run the shell
+script make-bin-dist in the `mac' directory. This will create a file
+emacs-21.xx.yy-mac-bin.tar.gz.
+
+To install the binary distribution, untar the file and run the shell
+script osx-install in its top-level directory.
+
+To build the `info' files, you need to install the texinfo software.
+
+To install from source, obtain texinfo-4.2.tar.gz from ftp.gnu.org or
+a mirror. Un-tar it, enter its directory and type
+
+ ./configure
+ make
+ make install
+
+The last step needs to be performed as root.
+
+You may also like to install ispell, which will allow you to use
+ispell and flyspell-mode. To install ispell from source, you first
+need to install GNU textutils.
+
+To do so, download textutils-2.0.tar.gz from ftp.gnu.org or a mirror.
+Un-tar it, enter its directory, type
+
+ ./configure --host=powerpc-apple-bsd
+ make
+ make install
+
+Again, the last step needs to be performed as root. Note that if you
+run `make check', the test for `pr' will fail.
+
+Get and un-tar ispell-3.2.06.tar.gz. Look for it here:
+
+ http://fmg-www.cs.ucla.edu/geoff/ispell.html
+
+Go into its directory, type
-### IMPORTANT ### If you use StuffIf Expander to decompress and untar
-the distribution, you *must* set the radio button in the
+ cp local.h.samp local.h
+
+Add a line `#define TERMLIB ""' to the end of local.h.
+
+Set the environment variable TMPDIR to an existing directory. For
+example since `/tmp' exists on my machine and I am using `bash', I
+typed
+
+ export TMPDIR=/tmp
+
+Run `make' and `make install', the latter as root.
+
+
+* BUILDING EMACS ON MAC OS 8/9
+
+You can use either Metrowerks CodeWarrior Pro 6 or MPW-GM (Aug. 2001)
+to build Emacs. MPW-GM can be downloaded free of charge from Apple.
+
+In either case, you will need MPW-GM to build the make-docfile utility
+and to generate the doc string file DOC.
+
+### IMPORTANT ### You can use StuffIf Expander to decompress and untar
+the distribution. However, you *must* set the radio button in the
Preferences->Cross Platform->Convert text files to Macintosh format to
"Never". Otherwise the compiled Lisp files will be corrupted.
-* BUILDING EMACS
+(Optional) A subset of the fonts from the GNU intlfonts-1.2
+distribution converted to NFNT format can be obtained from
+
+ ftp://mac-emacs.sourceforge.net/pub/mac-emacs/GNU-fonts.smi.bin
To build Emacs in the MPW Shell, simply set the directory to
...:emacs:mac: and build the target Emacs of the make file
Emacs.MakeScript
To build Emacs using CodeWarrior, start up the CodeWarrior IDE, choose
-File->Import Project... and select the file cw5-mcp.xml or
-cw6-mcp.xml, depending on which verison of CodeWarrior used. When
+File->Import Project... and select the file cw6-mcp.xml. When
prompted to save the project, navigate to same directory as the file
-cw[56]-mcp.xml, name it emacs-cw5.mcp or emacs-cw6.mcp, and save it
-there. Then choose Project->Make. Note that this does not build the
-DOC file. To do so, use MPW and build the target "Doc" in
-makefile.MPW.
+cw6-mcp.xml, name the project emacs-cw6.mcp, and save it there. Then
+choose Project->Make. Note that this does not build the DOC file. To
+do so, use MPW and build the target "Doc" in makefile.MPW.
Once built, the Emacs application (Emacs CW or Emacs MPW) can be
launched where it is created.
Information box in the Emacs Settings->Code Generation->PPC Processor
dialog and include the Profiler PPC.Lib library.
-To build optimized or debugging version of Emacs in MPW, follow the
-comment in makefile.MPW to enable the -opt speed or -sym on option
-(see note below).
-
* NOTES
-Emacs should build and run on a PowerMac running Mac OS 8.1 - 9.0.
+Emacs should build and run on a PowerMac running Mac OS 8.6 - 10.1.
You will need around 100 MB of disk space for the source files and
intermediate files.
-It will not run on machines with more than 256 MB of physical or
-virtual memory.
-
-Currently there is no support for building the LEIM directory on the
-Mac. However, it can be built on another platform and transferred to
-the Mac.
+It will not run on machines running Mac OS 8/9 with more than 256 MB
+of physical or virtual memory. It does not have this restriction when
+it is run under Mac OS X. But the usual 128MB buffer limit of a
+32-bit Emacs still exists.
-When Emacs is built with "-opt speed" enabled in makefile.MPW,
-optimization causes the functions reset_buffer_local_variables in
-buffer.c, syms_of_lread in lread.c, and x_draw_hollow_cursor in
-macterm.c to crash. Avoid this by enclosing them in the following
-pragmas.
+Under Mac OS 8/9, there is no support for building the LEIM directory.
+However, it can be built on Mac OS X or another platform and
+transferred to the Mac.
- #pragma options opt off
+On Mac OS 8/9, to use the same icon as when Emacs is built on Windows
+NT, define GNU_ICON in mac/src/Emacs.r. Currently Emacs uses a
+generic application icon on the Mac OS X. A better looking one is
+coming soon.
- <function definition...>
- #pragma options opt reset
+Enjoy!
-To use the same icon as when Emacs is built on Windows NT, define
-GNU_ICON in mac/src/Emacs.r.
+Andrew.
+<akochoi@mac.com>
-GNU Emacs for Mac OS
+Emacs for Mac OS 8/9 and Mac OS X
-Copyright (c) 2001 Free Software Foundation, Inc.
+Copyright (c) 2001, 2002 Free Software Foundation, Inc.
Permission is granted to anyone to make or distribute verbatim
copies of this document as received, in any medium, provided that
provided also that they carry prominent notices stating who last
changed them.
-This directory contains the files needed to build GNU Emacs on the Mac
-OS (8.1-9.0). Many of the major features of the Unix version are
+This directory contains the files needed to build Emacs on the Mac OS
+8/9 and Mac OS X. Many of the major features of the Unix version are
supported: multiple frames, colors, scroll bars, menu bars, use of the
mouse, fontsets, international characters, input methods, and coding
systems.
transfer of text to and from other applications via the clipboard, and
sending AppleScript commands to other applications from Emacs.
-The following are not yet supported: unexec (dump-emacs), asynchronous
-subprocesses (start-process), and networking
-(open-network-stream).
+The following are not supported on Mac OS 8/9 : unexec (dump-emacs),
+asynchronous subprocesses (start-process), and networking
+(open-network-stream). These features work fine on Mac OS X.
-There is basic support for synchronous subprocesses (call-process)
-although Unix commands that are used will need to be ported to the
-Mac.
+There is basic support for synchronous subprocesses (call-process) on
+Mac OS 8/9 although Unix commands that are used will need to be
+ported.
-Metrowerks CodeWarrior Pro 5 or Pro 6 or MPW-GM (August 2000) can be
-used to build Emacs on the Mac OS. See the INSTALL file in this
-directory for instructions on building Emacs.
+Metrowerks CodeWarrior Pro 6 or MPW-GM (August 2001) can be used to
+build Emacs on the Mac OS 8/9. On Mac OS X, Emacs can be built using
+the Developer Tools. See the INSTALL file in this directory for
+instructions on building Emacs.
-Binary distributions are available in
+Binary distributions will be available in
ftp://ftp.gnu.org/gnu/mac/emacs/
-At this site you can also find an FAQ related to running GNU Emacs on
-Mac OS.
+Read the Mac OS section of the on-line help to find out about how to
+use Emacs on the Mac.
+
+A number of things do not work yet:
+
++ On Mac OS X, environment variables are not set up correctly when
+ Emacs is started from the Finder.
+
++ Emacs does not respond correctly to C-g when it is not reading
+ input.
+
++ No image support yet.
+
++ There is no mouse-2 and mouse-3 emulation yet.
+
+If your Mac is connected to the Internet, report bugs by typing `M-x
+report-emacs-bug' or by choosing the entry `Send Bug Report...' in
+the `Help' menu. This will send the bug report to the address
+emacs-pretest-bug@gnu.org.
Andrew.
-<akochoi@i-cable.com>
+<akochoi@mac.com>
+++ /dev/null
-<!--
-Copyright (C) 2001 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the Free
-Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.
-
-
-Contributed by Andrew Choi (akochoi@i-cable.com).
-
-Exported from the emacs-cw5.mcp project in Metrowerks CodeWarrior Pro
-5 for distribution. This copyright notice was then added by hand.
-Choose the command File->Import Project... to recreate the
-emacs-cw5.mcp project.
-
--->
-
-<?xml version="1.0"?>
-<?codewarrior exportversion="1.0" ideversion="4.0"?>
-<!DOCTYPE PROJECT [
-
-<!ELEMENT PROJECT (TARGETLIST, TARGETORDER, GROUPLIST, DESIGNLIST?)>
-<!ELEMENT TARGETLIST (TARGET+)>
-<!ELEMENT TARGET (NAME, SETTINGLIST, FILELIST?, LINKORDER?, SEGMENTLIST?, OVERLAYGROUPLIST?, SUBTARGETLIST?, SUBPROJECTLIST?)>
-<!ELEMENT NAME (#PCDATA)>
-<!ELEMENT USERSOURCETREETYPE (#PCDATA)>
-<!ELEMENT PATH (#PCDATA)>
-<!ELEMENT FILELIST (FILE*)>
-<!ELEMENT FILE (PATHTYPE, PATHROOT?, ACCESSPATH?, PATH, PATHFORMAT?, ROOTFILEREF?, FILEKIND?, FILEFLAGS?)>
-<!ELEMENT PATHTYPE (#PCDATA)>
-<!ELEMENT PATHROOT (#PCDATA)>
-<!ELEMENT ACCESSPATH (#PCDATA)>
-<!ELEMENT PATHFORMAT (#PCDATA)>
-<!ELEMENT ROOTFILEREF (PATHTYPE, PATHROOT?, ACCESSPATH?, PATH, PATHFORMAT?)>
-<!ELEMENT FILEKIND (#PCDATA)>
-<!ELEMENT FILEFLAGS (#PCDATA)>
-<!ELEMENT FILEREF (TARGETNAME?, PATHTYPE, PATHROOT?, ACCESSPATH?, PATH, PATHFORMAT?)>
-<!ELEMENT TARGETNAME (#PCDATA)>
-<!ELEMENT SETTINGLIST ((SETTING|PANELDATA)+)>
-<!ELEMENT SETTING (NAME?, (VALUE|(SETTING+)))>
-<!ELEMENT PANELDATA (NAME, VALUE)>
-<!ELEMENT VALUE (#PCDATA)>
-<!ELEMENT LINKORDER (FILEREF*)>
-<!ELEMENT SEGMENTLIST (SEGMENT+)>
-<!ELEMENT SEGMENT (NAME, ATTRIBUTES?, FILEREF*)>
-<!ELEMENT ATTRIBUTES (#PCDATA)>
-<!ELEMENT OVERLAYGROUPLIST (OVERLAYGROUP+)>
-<!ELEMENT OVERLAYGROUP (NAME, BASEADDRESS, OVERLAY*)>
-<!ELEMENT BASEADDRESS (#PCDATA)>
-<!ELEMENT OVERLAY (NAME, FILEREF*)>
-<!ELEMENT SUBTARGETLIST (SUBTARGET+)>
-<!ELEMENT SUBTARGET (TARGETNAME, ATTRIBUTES?)>
-<!ELEMENT SUBPROJECTLIST (SUBPROJECT+)>
-<!ELEMENT SUBPROJECT (FILEREF, SUBPROJECTTARGETLIST)>
-<!ELEMENT SUBPROJECTTARGETLIST (SUBPROJECTTARGET*)>
-<!ELEMENT SUBPROJECTTARGET (TARGETNAME, ATTRIBUTES?)>
-<!ELEMENT TARGETORDER (ORDEREDTARGET|ORDEREDDESIGN)*>
-<!ELEMENT ORDEREDTARGET (NAME)>
-<!ELEMENT ORDEREDDESIGN (NAME, ORDEREDTARGET+)>
-<!ELEMENT GROUPLIST (GROUP|FILEREF)*>
-<!ELEMENT GROUP (NAME, (GROUP|FILEREF)*)>
-<!ELEMENT DESIGNLIST (DESIGN+)>
-<!ELEMENT DESIGN (NAME, DESIGNDATA)>
-<!ELEMENT DESIGNDATA (#PCDATA)>
-]>
-<PROJECT>
- <TARGETLIST>
- <TARGET>
- <NAME>Emacs</NAME>
- <SETTINGLIST>
-
- <!-- Settings for "Source Trees" panel -->
- <SETTING><NAME>UserSourceTrees</NAME><VALUE></VALUE></SETTING>
-
- <!-- Settings for "Custom Keywords" panel -->
- <SETTING><NAME>CustomColor1</NAME>
- <SETTING><NAME>Red</NAME><VALUE>6168</VALUE></SETTING>
- <SETTING><NAME>Green</NAME><VALUE>24672</VALUE></SETTING>
- <SETTING><NAME>Blue</NAME><VALUE>23130</VALUE></SETTING>
- </SETTING>
- <SETTING><NAME>CustomColor2</NAME>
- <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>
- <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>
- </SETTING>
- <SETTING><NAME>CustomColor3</NAME>
- <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>
- <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>
- </SETTING>
- <SETTING><NAME>CustomColor4</NAME>
- <SETTING><NAME>Red</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>Green</NAME><VALUE>32767</VALUE></SETTING>
- <SETTING><NAME>Blue</NAME><VALUE>0</VALUE></SETTING>
- </SETTING>
- <SETTING><NAME>CustomKeywordList1</NAME><VALUE>DEFUN</VALUE></SETTING>
-
- <!-- Settings for "Access Paths" panel -->
- <SETTING><NAME>AlwaysSearchUserPaths</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>InterpretDOSAndUnixPaths</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>UserSearchPaths</NAME>
- <SETTING>
- <SETTING><NAME>SearchPath</NAME>
- <SETTING><NAME>Path</NAME><VALUE>:inc:</VALUE></SETTING>
- <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>
- <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>
- </SETTING>
- <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>SearchPath</NAME>
- <SETTING><NAME>Path</NAME><VALUE>:src:</VALUE></SETTING>
- <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>
- <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>
- </SETTING>
- <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>SearchPath</NAME>
- <SETTING><NAME>Path</NAME><VALUE>::src:</VALUE></SETTING>
- <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>
- <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>
- </SETTING>
- <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>
- </SETTING>
- </SETTING>
- <SETTING><NAME>SystemSearchPaths</NAME>
- <SETTING>
- <SETTING><NAME>SearchPath</NAME>
- <SETTING><NAME>Path</NAME><VALUE>:inc:</VALUE></SETTING>
- <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>
- <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>
- </SETTING>
- <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>SearchPath</NAME>
- <SETTING><NAME>Path</NAME><VALUE>:</VALUE></SETTING>
- <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>
- <SETTING><NAME>PathRoot</NAME><VALUE>CodeWarrior</VALUE></SETTING>
- </SETTING>
- <SETTING><NAME>Recursive</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>HostFlags</NAME><VALUE>All</VALUE></SETTING>
- </SETTING>
- </SETTING>
-
- <!-- Settings for "Target Settings" panel -->
- <SETTING><NAME>Linker</NAME><VALUE>MacOS PPC Linker</VALUE></SETTING>
- <SETTING><NAME>PreLinker</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>PostLinker</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>Targetname</NAME><VALUE>Emacs</VALUE></SETTING>
- <SETTING><NAME>OutputDirectory</NAME>
- <SETTING><NAME>Path</NAME><VALUE>:</VALUE></SETTING>
- <SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>
- <SETTING><NAME>PathRoot</NAME><VALUE>Project</VALUE></SETTING>
- </SETTING>
- <SETTING><NAME>SaveEntriesUsingRelativePaths</NAME><VALUE>false</VALUE></SETTING>
-
- <!-- Settings for "File Mappings" panel -->
- <SETTING><NAME>FileMappings</NAME>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>APPL</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>Appl</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>MMLB</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE>Lib Import PPC</VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>MPLF</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE>Lib Import PPC</VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>MWCD</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>RSRC</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE>.bh</VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE>Balloon Help</VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE>.c</VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE>.c++</VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE>.cc</VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE>.cp</VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE>.cpp</VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE>.exp</VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE>.gc</VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE>GameCode Converter</VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE>.h</VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>true</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE>.l</VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE>Flex Preprocessor</VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE>.p</VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE>MW Pascal PPC</VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE>.pas</VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE>MW Pascal PPC</VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE>.pch</VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE>.pch++</VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE>MW C/C++ PPC</VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE>.ppu</VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE>MW Pascal PPC</VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE>.r</VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE>Rez</VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE>.s</VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE>PPCAsm</VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>TEXT</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE>.y</VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE>Bison Preprocessor</VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>XCOF</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE>XCOFF Import PPC</VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>docu</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>rsrc</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>shlb</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE>PEF Import PPC</VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileType</NAME><VALUE>stub</VALUE></SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE>PEF Import PPC</VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>false</VALUE></SETTING>
- </SETTING>
- <SETTING>
- <SETTING><NAME>FileExtension</NAME><VALUE>.doc</VALUE></SETTING>
- <SETTING><NAME>Compiler</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>Precompile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>Launchable</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>ResourceFile</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>IgnoredByMake</NAME><VALUE>true</VALUE></SETTING>
- </SETTING>
- </SETTING>
-
- <!-- Settings for "Build Extras" panel -->
- <SETTING><NAME>CacheModDates</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>ActivateBrowser</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>DumpBrowserInfo</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>CacheSubprojects</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>UseThirdPartyDebugger</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>DebuggerCommandLine</NAME><VALUE></VALUE></SETTING>
- <PANELDATA><NAME>Debugger Runtime</NAME><VALUE>
- 0002000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000006315C40000000000000010006316550
- 000200000000000000000000063153E000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 0000000000000000000000000000000000000000000000000000000000000000
- 00000000000000000000000000000000
- </VALUE></PANELDATA>
-
- <!-- Settings for "Debugger Target" panel -->
- <SETTING><NAME>LogSystemMessages</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>AutoTargetDLLs</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>StopAtWatchpoints</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>PauseWhileRunning</NAME><VALUE>false</VALUE></SETTING>
- <SETTING><NAME>PauseInterval</NAME><VALUE>5</VALUE></SETTING>
- <SETTING><NAME>PauseUIFlags</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>AltExePath</NAME>
- <SETTING><NAME>Path</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>PathFormat</NAME><VALUE>Generic</VALUE></SETTING>
- <SETTING><NAME>PathRoot</NAME><VALUE>Absolute</VALUE></SETTING>
- </SETTING>
- <SETTING><NAME>StopAtTempBPOnLaunch</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>CacheSymbolics</NAME><VALUE>true</VALUE></SETTING>
- <SETTING><NAME>TempBPFunctionName</NAME><VALUE>main</VALUE></SETTING>
- <SETTING><NAME>TempBPType</NAME><VALUE>false</VALUE></SETTING>
-
- <!-- Settings for "68K CodeGen" panel -->
- <SETTING><NAME>MWCodeGen_68K_codesize</NAME><VALUE>Smart</VALUE></SETTING>
- <SETTING><NAME>MWCodeGen_68K_structalignment</NAME><VALUE>MC68K</VALUE></SETTING>
- <SETTING><NAME>MWCodeGen_68K_fp_mode</NAME><VALUE>SANE</VALUE></SETTING>
- <SETTING><NAME>MWCodeGen_68K_code68020</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWCodeGen_68K_profiler</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWCodeGen_68K_mpwc</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWCodeGen_68K_fourbyteints</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWCodeGen_68K_IEEEdoubles</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWCodeGen_68K_fardata</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWCodeGen_68K_farvtables</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWCodeGen_68K_farstrings</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWCodeGen_68K_pcrelstrings</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWCodeGen_68K_macsbug</NAME><VALUE>New</VALUE></SETTING>
- <SETTING><NAME>MWCodeGen_68K_a6frames</NAME><VALUE>1</VALUE></SETTING>
-
- <!-- Settings for "68K Disassembler" panel -->
- <SETTING><NAME>MWDisassembler_68K_showcode</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWDisassembler_68K_mix</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWDisassembler_68K_nohex</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWDisassembler_68K_showdata</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWDisassembler_68K_showexceptions</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWDisassembler_68K_showsym</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWDisassembler_68K_shownames</NAME><VALUE>1</VALUE></SETTING>
-
- <!-- Settings for "68K Global Optimizer" panel -->
- <SETTING><NAME>GlobalOptimizer_68K_optimizationlevel</NAME><VALUE>Level0</VALUE></SETTING>
- <SETTING><NAME>GlobalOptimizer_68K_optfor</NAME><VALUE>Speed</VALUE></SETTING>
-
- <!-- Settings for "68K Linker" panel -->
- <SETTING><NAME>MWLinker_68K_linksym</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWLinker_68K_symfullpath</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWLinker_68K_linksingle</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWLinker_68K_fastlink</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWLinker_68K_generateMap</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWLinker_68K_nolinkwarnings</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWLinker_68K_glueintosegone</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWLinker_68K_dontdeadstripinitcode</NAME><VALUE>0</VALUE></SETTING>
-
- <!-- Settings for "68K Project" panel -->
- <SETTING><NAME>MWProject_68K_type</NAME><VALUE>Application</VALUE></SETTING>
- <SETTING><NAME>MWProject_68K_outfile</NAME><VALUE>MacOS Toolbox DEBUG 68K</VALUE></SETTING>
- <SETTING><NAME>MWProject_68K_symfilename</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>MWProject_68K_filecreator</NAME><VALUE>1061109567</VALUE></SETTING>
- <SETTING><NAME>MWProject_68K_filetype</NAME><VALUE>1095782476</VALUE></SETTING>
- <SETTING><NAME>MWProject_68K_size</NAME><VALUE>384</VALUE></SETTING>
- <SETTING><NAME>MWProject_68K_flags</NAME><VALUE>22720</VALUE></SETTING>
- <SETTING><NAME>MWProject_68K_rsrcheader</NAME><VALUE>Standard</VALUE></SETTING>
- <SETTING><NAME>MWProject_68K_rsrcname</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>MWProject_68K_rsrctype</NAME><VALUE>1061109567</VALUE></SETTING>
- <SETTING><NAME>MWProject_68K_rsrcid</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWProject_68K_rsrcmulti</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWProject_68K_rsrcstore</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWProject_68K_rsrcmerge</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWProject_68K_rsrcflags</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWProject_68K_a4</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWProject_68K_minsize</NAME><VALUE>384</VALUE></SETTING>
- <SETTING><NAME>MWProject_68K_rsrcsegtype</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWProject_68K_cfm68kcodegen</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWProject_68K_stacksize</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWProject_68K_thedebugger</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWProject_68K_rsrc_custom</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWProject_68K_is_rseg_app</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWProject_68K_is_pilot_lib</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWProject_68K_pilot_main_entry</NAME><VALUE></VALUE></SETTING>
-
- <!-- Settings for "C/C++ Compiler" panel -->
- <SETTING><NAME>MWFrontEnd_C_cplusplus</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWFrontEnd_C_checkprotos</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWFrontEnd_C_arm</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWFrontEnd_C_trigraphs</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWFrontEnd_C_onlystdkeywords</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWFrontEnd_C_enumsalwaysint</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWFrontEnd_C_mpwpointerstyle</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWFrontEnd_C_prefixname</NAME><VALUE>defs-cw5.h</VALUE></SETTING>
- <SETTING><NAME>MWFrontEnd_C_ansistrict</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWFrontEnd_C_mpwcnewline</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWFrontEnd_C_wchar_type</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWFrontEnd_C_enableexceptions</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWFrontEnd_C_dontreusestrings</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWFrontEnd_C_poolstrings</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWFrontEnd_C_dontinline</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWFrontEnd_C_useRTTI</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWFrontEnd_C_multibyteaware</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWFrontEnd_C_unsignedchars</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWFrontEnd_C_autoinline</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWFrontEnd_C_booltruefalse</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWFrontEnd_C_direct_to_som</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWFrontEnd_C_som_env_check</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWFrontEnd_C_alwaysinline</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWFrontEnd_C_inlinelevel</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWFrontEnd_C_ecplusplus</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWFrontEnd_C_objective_c</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWFrontEnd_C_defer_codegen</NAME><VALUE>0</VALUE></SETTING>
-
- <!-- Settings for "C/C++ Warnings" panel -->
- <SETTING><NAME>MWWarning_C_warn_illpragma</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWWarning_C_warn_emptydecl</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWWarning_C_warn_possunwant</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWWarning_C_warn_unusedvar</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWWarning_C_warn_unusedarg</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWWarning_C_warn_extracomma</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWWarning_C_pedantic</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWWarning_C_warningerrors</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWWarning_C_warn_hidevirtual</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWWarning_C_warn_implicitconv</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWWarning_C_warn_notinlined</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWWarning_C_warn_structclass</NAME><VALUE>0</VALUE></SETTING>
-
- <!-- Settings for "CFM68K" panel -->
- <SETTING><NAME>MWCFM68K_exports</NAME><VALUE>None</VALUE></SETTING>
- <SETTING><NAME>MWCFM68K_olddefversion</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWCFM68K_oldimpversion</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWCFM68K_currentversion</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWCFM68K_farthreshold</NAME><VALUE>256</VALUE></SETTING>
- <SETTING><NAME>PCFM68K_sharedata</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWCFM68K_fragmentname</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>MWCFM68K_initname</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>MWCFM68K_mainname</NAME><VALUE>__start</VALUE></SETTING>
- <SETTING><NAME>MWCFM68K_termname</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>MWCFM68K_libfolder</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWCFM68K_alignment</NAME><VALUE>Align_2</VALUE></SETTING>
-
- <!-- Settings for "MacOS Merge Panel" panel -->
- <SETTING><NAME>MWMerge_MacOS_projectType</NAME><VALUE>Application</VALUE></SETTING>
- <SETTING><NAME>MWMerge_MacOS_outputName</NAME><VALUE>Merge Out</VALUE></SETTING>
- <SETTING><NAME>MWMerge_MacOS_outputCreator</NAME><VALUE>1061109567</VALUE></SETTING>
- <SETTING><NAME>MWMerge_MacOS_outputType</NAME><VALUE>1095782476</VALUE></SETTING>
- <SETTING><NAME>MWMerge_MacOS_suppressWarning</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWMerge_MacOS_copyFragments</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWMerge_MacOS_copyResources</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWMerge_MacOS_skipResources</NAME>
- <SETTING><VALUE></VALUE></SETTING>
- <SETTING><VALUE>\ 6ªZ\83</VALUE></SETTING>
- <SETTING><VALUE>\ 6~\97¯</VALUE></SETTING>
- <SETTING><VALUE>\ 6
-|0</VALUE></SETTING>
- </SETTING>
-
- <!-- Settings for "PPC CodeGen" panel -->
- <SETTING><NAME>MWCodeGen_PPC_structalignment</NAME><VALUE>PPC</VALUE></SETTING>
- <SETTING><NAME>MWCodeGen_PPC_tracebacktables</NAME><VALUE>Inline</VALUE></SETTING>
- <SETTING><NAME>MWCodeGen_PPC_processor</NAME><VALUE>Generic</VALUE></SETTING>
- <SETTING><NAME>MWCodeGen_PPC_readonlystrings</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWCodeGen_PPC_tocdata</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWCodeGen_PPC_profiler</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWCodeGen_PPC_fpcontract</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWCodeGen_PPC_schedule</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWCodeGen_PPC_peephole</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWCodeGen_PPC_processorspecific</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWCodeGen_PPC_altivec</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWCodeGen_PPC_vectortocdata</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWCodeGen_PPC_vrsave</NAME><VALUE>0</VALUE></SETTING>
-
- <!-- Settings for "PPC Disassembler" panel -->
- <SETTING><NAME>MWDisassembler_PPC_showcode</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWDisassembler_PPC_extended</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWDisassembler_PPC_mix</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWDisassembler_PPC_nohex</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWDisassembler_PPC_showdata</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWDisassembler_PPC_showexceptions</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWDisassembler_PPC_showsym</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWDisassembler_PPC_shownames</NAME><VALUE>1</VALUE></SETTING>
-
- <!-- Settings for "PPC Global Optimizer" panel -->
- <SETTING><NAME>GlobalOptimizer_PPC_optimizationlevel</NAME><VALUE>Level0</VALUE></SETTING>
- <SETTING><NAME>GlobalOptimizer_PPC_optfor</NAME><VALUE>Speed</VALUE></SETTING>
-
- <!-- Settings for "PPC Linker" panel -->
- <SETTING><NAME>MWLinker_PPC_linksym</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWLinker_PPC_symfullpath</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWLinker_PPC_linkmap</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWLinker_PPC_nolinkwarnings</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWLinker_PPC_dontdeadstripinitcode</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWLinker_PPC_permitmultdefs</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWLinker_PPC_linkmode</NAME><VALUE>Fast</VALUE></SETTING>
- <SETTING><NAME>MWLinker_PPC_initname</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>MWLinker_PPC_mainname</NAME><VALUE>__start</VALUE></SETTING>
- <SETTING><NAME>MWLinker_PPC_termname</NAME><VALUE></VALUE></SETTING>
-
- <!-- Settings for "PPC PEF" panel -->
- <SETTING><NAME>MWPEF_exports</NAME><VALUE>None</VALUE></SETTING>
- <SETTING><NAME>MWPEF_libfolder</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWPEF_sortcode</NAME><VALUE>None</VALUE></SETTING>
- <SETTING><NAME>MWPEF_expandbss</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWPEF_sharedata</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWPEF_olddefversion</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWPEF_oldimpversion</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWPEF_currentversion</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWPEF_fragmentname</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>MWPEF_collapsereloads</NAME><VALUE>0</VALUE></SETTING>
-
- <!-- Settings for "PPC Project" panel -->
- <SETTING><NAME>MWProject_PPC_type</NAME><VALUE>Application</VALUE></SETTING>
- <SETTING><NAME>MWProject_PPC_outfile</NAME><VALUE>Emacs CW</VALUE></SETTING>
- <SETTING><NAME>MWProject_PPC_filecreator</NAME><VALUE>1162690936</VALUE></SETTING>
- <SETTING><NAME>MWProject_PPC_filetype</NAME><VALUE>1095782476</VALUE></SETTING>
- <SETTING><NAME>MWProject_PPC_size</NAME><VALUE>16384</VALUE></SETTING>
- <SETTING><NAME>MWProject_PPC_minsize</NAME><VALUE>16384</VALUE></SETTING>
- <SETTING><NAME>MWProject_PPC_stacksize</NAME><VALUE>512</VALUE></SETTING>
- <SETTING><NAME>MWProject_PPC_flags</NAME><VALUE>22752</VALUE></SETTING>
- <SETTING><NAME>MWProject_PPC_symfilename</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>MWProject_PPC_rsrcname</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>MWProject_PPC_rsrcheader</NAME><VALUE>Native</VALUE></SETTING>
- <SETTING><NAME>MWProject_PPC_rsrctype</NAME><VALUE>1061109567</VALUE></SETTING>
- <SETTING><NAME>MWProject_PPC_rsrcid</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWProject_PPC_rsrcflags</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWProject_PPC_rsrcstore</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWProject_PPC_rsrcmerge</NAME><VALUE>0</VALUE></SETTING>
-
- <!-- Settings for "PPCAsm Panel" panel -->
- <SETTING><NAME>MWAssembler_PPC_auxheader</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWAssembler_PPC_symmode</NAME><VALUE>Mac</VALUE></SETTING>
- <SETTING><NAME>MWAssembler_PPC_dialect</NAME><VALUE>PPC</VALUE></SETTING>
- <SETTING><NAME>MWAssembler_PPC_prefixfile</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>MWAssembler_PPC_typecheck</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWAssembler_PPC_warnings</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWAssembler_PPC_casesensitive</NAME><VALUE>0</VALUE></SETTING>
-
- <!-- Settings for "Rez Compiler" panel -->
- <SETTING><NAME>MWRez_Language_maxwidth</NAME><VALUE>80</VALUE></SETTING>
- <SETTING><NAME>MWRez_Language_script</NAME><VALUE>Roman</VALUE></SETTING>
- <SETTING><NAME>MWRez_Language_alignment</NAME><VALUE>Align1</VALUE></SETTING>
- <SETTING><NAME>MWRez_Language_filtermode</NAME><VALUE>FilterSkip</VALUE></SETTING>
- <SETTING><NAME>MWRez_Language_suppresswarnings</NAME><VALUE>0</VALUE></SETTING>
- <SETTING><NAME>MWRez_Language_escapecontrolchars</NAME><VALUE>1</VALUE></SETTING>
- <SETTING><NAME>MWRez_Language_prefixname</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>MWRez_Language_filteredtypes</NAME><VALUE>'CODE' 'DATA' 'PICT'</VALUE></SETTING>
- </SETTINGLIST>
- <FILELIST>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>InterfaceLib</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Library</FILEKIND>
- <FILEFLAGS></FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>MathLib</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Library</FILEKIND>
- <FILEFLAGS></FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>MSL RuntimePPC.Lib</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Library</FILEKIND>
- <FILEFLAGS></FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>emacs.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>process.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>floatfns.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>editfns.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>macros.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>xdisp.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>window.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>minibuf.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>keymap.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>buffer.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>cmds.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>casefiddle.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>textprop.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>undo.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>syntax.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>search.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>marker.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>insdel.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>indent.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>coding.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>fileio.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>alloc.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>fns.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>eval.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>doc.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>dired.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>charset.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>ccl.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>category.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>callproc.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>casetab.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>callint.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>bytecode.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>abbrev.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>print.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>data.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>intervals.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>regex.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>mktime.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>filemode.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>getloadavg.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>scroll.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>region-cache.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>doprnt.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>cm.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>termcap.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>tparam.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>sysdep.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>lread.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>frame.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>term.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>keyboard.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>fontset.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>dispnew.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>Emacs.r</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>AppleScriptLib</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Library</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>strftime.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>TextEncodingConverter</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Library</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>xfaces.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>macfns.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>macterm.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>composite.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>atimer.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>mac.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>alloca.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>MSL C.PPC.Lib</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Library</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>MSL SIOUX.PPC.Lib</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Library</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>macmenu.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>AppearanceLib</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Library</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- <FILE>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>md5.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- <FILEKIND>Text</FILEKIND>
- <FILEFLAGS>Debug</FILEFLAGS>
- </FILE>
- </FILELIST>
- <LINKORDER>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>abbrev.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>alloc.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>alloca.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>atimer.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>buffer.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>bytecode.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>callint.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>callproc.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>casefiddle.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>casetab.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>category.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>ccl.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>charset.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>cm.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>cmds.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>coding.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>composite.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>data.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>dired.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>dispnew.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>doc.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>doprnt.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>editfns.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>emacs.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>eval.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>fileio.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>filemode.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>floatfns.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>fns.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>fontset.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>frame.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>getloadavg.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>indent.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>insdel.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>intervals.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>keyboard.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>keymap.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>lread.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>macros.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>marker.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>md5.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>minibuf.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>mktime.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>print.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>process.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>regex.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>region-cache.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>scroll.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>search.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>strftime.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>syntax.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>term.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>termcap.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>textprop.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>tparam.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>undo.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>window.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>xdisp.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>sysdep.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>xfaces.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>mac.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>macfns.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>macmenu.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>macterm.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>MSL RuntimePPC.Lib</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>InterfaceLib</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>MathLib</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>AppleScriptLib</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>TextEncodingConverter</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>MSL C.PPC.Lib</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>MSL SIOUX.PPC.Lib</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>AppearanceLib</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>Emacs.r</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- </LINKORDER>
- </TARGET>
- </TARGETLIST>
-
- <TARGETORDER>
- <ORDEREDTARGET><NAME>Emacs</NAME></ORDEREDTARGET>
- </TARGETORDER>
-
- <GROUPLIST>
- <GROUP><NAME>Emacs Source</NAME>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>abbrev.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>alloc.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>alloca.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>atimer.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>buffer.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>bytecode.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>callint.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>callproc.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>casefiddle.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>casetab.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>category.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>ccl.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>charset.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>cm.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>cmds.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>coding.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>composite.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>data.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>dired.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>dispnew.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>doc.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>doprnt.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>editfns.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>emacs.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>eval.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>fileio.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>filemode.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>floatfns.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>fns.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>fontset.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>frame.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>getloadavg.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>indent.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>insdel.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>intervals.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>keyboard.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>keymap.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>lread.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>macros.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>marker.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>md5.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>minibuf.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>mktime.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>print.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>process.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>regex.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>region-cache.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>scroll.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>search.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>strftime.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>syntax.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>sysdep.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>term.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>termcap.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>textprop.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>tparam.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>undo.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>window.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>xdisp.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>xfaces.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- </GROUP>
- <GROUP><NAME>Mac Source</NAME>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>mac.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>macfns.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>macmenu.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>macterm.c</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- </GROUP>
- <GROUP><NAME>Resources</NAME>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>Emacs.r</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- </GROUP>
- <GROUP><NAME>Mac Libraries</NAME>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>MSL RuntimePPC.Lib</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>InterfaceLib</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>MathLib</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>AppleScriptLib</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>TextEncodingConverter</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>AppearanceLib</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- </GROUP>
- <GROUP><NAME>ANSI Libraries</NAME>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>MSL C.PPC.Lib</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- <FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
- <PATHTYPE>Name</PATHTYPE>
- <PATH>MSL SIOUX.PPC.Lib</PATH>
- <PATHFORMAT>MacOS</PATHFORMAT>
- </FILEREF>
- </GROUP>
- </GROUPLIST>
-
-</PROJECT>
02111-1307, USA.
-Contributed by Andrew Choi (akochoi@i-cable.com).
+Contributed by Andrew Choi (akochoi@mac.com).
Exported from the emacs-cw6.mcp project in Metrowerks CodeWarrior Pro
6 for distribution. This copyright notice was then added by hand.
<PROJECT>
<TARGETLIST>
<TARGET>
- <NAME>Emacs</NAME>
+ <NAME>Emacs CW</NAME>
<SETTINGLIST>
<!-- Settings for "Source Trees" panel -->
<SETTING><NAME>Linker</NAME><VALUE>MacOS PPC Linker</VALUE></SETTING>
<SETTING><NAME>PreLinker</NAME><VALUE></VALUE></SETTING>
<SETTING><NAME>PostLinker</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>Targetname</NAME><VALUE>Emacs</VALUE></SETTING>
+ <SETTING><NAME>Targetname</NAME><VALUE>Emacs CW</VALUE></SETTING>
<SETTING><NAME>OutputDirectory</NAME>
<SETTING><NAME>Path</NAME><VALUE>:</VALUE></SETTING>
<SETTING><NAME>PathFormat</NAME><VALUE>MacOS</VALUE></SETTING>
<!-- Settings for "FTP Panel" panel -->
<SETTING><NAME>MWFTP_Post_hostName</NAME><VALUE></VALUE></SETTING>
<SETTING><NAME>MWFTP_Post_username</NAME><VALUE></VALUE></SETTING>
- <SETTING><NAME>MWFTP_Post_password</NAME><VALUE>3654kr6a654npes6544xbe*š\aA‘à"</VALUE></SETTING>
+ <SETTING><NAME>MWFTP_Post_password</NAME><VALUE>35kmm835kpjgj5k5td7à</VALUE></SETTING>
<SETTING><NAME>MWFTP_Post_remoteDir</NAME><VALUE></VALUE></SETTING>
<SETTING><NAME>MWFTP_Post_ftp_PathVersion</NAME><VALUE>0</VALUE></SETTING>
<SETTING><NAME>MWFTP_Post_ftp_PathType</NAME><VALUE>0</VALUE></SETTING>
</TARGETLIST>
<TARGETORDER>
- <ORDEREDTARGET><NAME>Emacs</NAME></ORDEREDTARGET>
+ <ORDEREDTARGET><NAME>Emacs CW</NAME></ORDEREDTARGET>
</TARGETORDER>
<GROUPLIST>
<GROUP><NAME>Emacs Source</NAME>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>abbrev.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>alloc.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>alloca.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>atimer.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>buffer.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>bytecode.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>callint.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>callproc.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>casefiddle.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>casetab.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>category.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>ccl.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>charset.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>cm.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>cmds.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>coding.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>composite.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>data.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>dired.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>dispnew.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>doc.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>doprnt.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>editfns.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>emacs.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>eval.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>fileio.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>filemode.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>floatfns.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>fns.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>fontset.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>frame.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>getloadavg.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>indent.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>insdel.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>intervals.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>keyboard.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>keymap.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>lread.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>macros.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>marker.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>md5.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>minibuf.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>mktime.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>print.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>process.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>regex.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>region-cache.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>scroll.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>search.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>strftime.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>syntax.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>sysdep.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>term.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>termcap.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>textprop.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>tparam.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>undo.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>window.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>xdisp.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>xfaces.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</GROUP>
<GROUP><NAME>Mac Source</NAME>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>mac.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>macfns.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>macmenu.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>macterm.c</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</GROUP>
<GROUP><NAME>Resources</NAME>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>Emacs.r</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</GROUP>
<GROUP><NAME>Mac Libraries</NAME>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>InterfaceLib</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>MathLib</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>AppleScriptLib</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>TextEncodingConverter</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>AppearanceLib</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</GROUP>
<GROUP><NAME>ANSI Libraries</NAME>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>MSL C.PPC.Lib</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>MSL SIOUX.PPC.Lib</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
</FILEREF>
<FILEREF>
- <TARGETNAME>Emacs</TARGETNAME>
+ <TARGETNAME>Emacs CW</TARGETNAME>
<PATHTYPE>Name</PATHTYPE>
<PATH>MSL RuntimePPC.Lib</PATH>
<PATHFORMAT>MacOS</PATHFORMAT>
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
-/* Contributed by Andrew Choi (akochoi@users.sourceforge.net). */
+/* Contributed by Andrew Choi (akochoi@mac.com). */
#ifndef _ALLOCA_H_
#define _ALLOCA_H_
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+/* Contributed by Andrew Choi (akochoi@mac.com). */
+
/* No code in Emacs #includes config.h twice, but some of the code
intended to work with other packages as well (like gmalloc.c)
/* #define GLYPH_DEBUG 1 */
-#define NO_RETURN /* nothing */
\ No newline at end of file
+#define NO_RETURN /* nothing */
+++ /dev/null
-/* Copyright (C) 2001 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the Free
-Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
-
-/* Contributed by Andrew Choi (akochoi@users.sourceforge.net). */
-
-#define emacs 1
-#define HAVE_CONFIG_H
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
-/* Contributed by Andrew Choi (akochoi@users.sourceforge.net). */
+/* Contributed by Andrew Choi (akochoi@mac.com). */
#define emacs 1
#define HAVE_CONFIG_H
-#define CODEWARRIOR_VERSION_6
+#define MAC_OS8 1
+#define MAC_OS 1
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Contributed by Andrew Choi (akochoi@users.sourceforge.net). */
+/* Contributed by Andrew Choi (akochoi@mac.com). */
#ifndef _DIRENT_H
#define _DIRENT_H
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Contributed by Andrew Choi (akochoi@users.sourceforge.net). */
+/* Contributed by Andrew Choi (akochoi@mac.com). */
/* The default search path for Lisp function "load".
This sets load-path. */
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Contributed by Andrew Choi (akochoi@users.sourceforge.net). */
+/* Contributed by Andrew Choi (akochoi@mac.com). */
/* The following line tells the configuration script what sort of
operating system this machine is likely to run.
+++ /dev/null
-/* Definitions and headers for communication on the Mac OS.
- Copyright (C) 2000 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Contributed by Andrew Choi (akochoi@users.sourceforge.net). */
-
-#ifndef EMACS_MACGUI_H
-#define EMACS_MACGUI_H
-
-#include <MacTypes.h>
-#include <Quickdraw.h>
-
-typedef int Pixmap;
-typedef int Bitmap;
-
-typedef int Display; /* fix later */
-
-typedef unsigned long Time;
-typedef RGBColor Color;
-typedef WindowPtr Window;
-
-#define FACE_DEFAULT (~0)
-
-
-/* Emulate XCharStruct. */
-typedef struct _XCharStruct
-{
- int rbearing;
- int lbearing;
- int width;
- int ascent;
- int descent;
-} XCharStruct;
-
-struct MacFontStruct {
- char *fontname;
-
- SInt16 mac_fontnum; /* font number of font used in this window */
- int mac_fontsize; /* size of font */
- Style mac_fontface; /* plain, bold, italics, etc. */
- short mac_scriptcode; /* Mac OS script code for font used */
-
-#if 0
- SInt16 mFontNum; /* font number of font used in this window */
- short mScriptCode; /* Mac OS script code for font used */
- int mFontSize; /* size of font */
- Style mFontFace; /* plain, bold, italics, etc. */
- int mHeight; /* height of one line of text in pixels */
- int mWidth; /* width of one character in pixels */
- int mAscent;
- int mDescent;
- int mLeading;
- char mTwoByte; /* true for two-byte font */
-#endif
-
-/* from Xlib.h */
-#if 0
- XExtData *ext_data; /* hook for extension to hang data */
- Font fid; /* Font id for this font */
- unsigned direction; /* hint about the direction font is painted */
-#endif
- unsigned min_char_or_byte2;/* first character */
- unsigned max_char_or_byte2;/* last character */
- unsigned min_byte1; /* first row that exists */
- unsigned max_byte1; /* last row that exists */
-#if 0
- Bool all_chars_exist; /* flag if all characters have nonzero size */
- unsigned default_char; /* char to print for undefined character */
- int n_properties; /* how many properties there are */
- XFontProp *properties; /* pointer to array of additional properties */
-#endif
- XCharStruct min_bounds; /* minimum bounds over all existing char */
- XCharStruct max_bounds; /* maximum bounds over all existing char */
- XCharStruct *per_char; /* first_char to last_char information */
- int ascent; /* logical extent above baseline for spacing */
- int descent; /* logical decent below baseline for spacing */
-};
-
-typedef struct MacFontStruct MacFontStruct;
-typedef struct MacFontStruct XFontStruct;
-
-
-/* Emulate X GC's by keeping color and font info in a structure. */
-typedef struct _XGCValues
-{
- unsigned long foreground;
- unsigned long background;
- XFontStruct *font;
-} XGCValues;
-
-typedef XGCValues *GC;
-
-extern XGCValues *
-XCreateGC (void *, Window, unsigned long, XGCValues *);
-
-#define GCForeground 0x01
-#define GCBackground 0x02
-#define GCFont 0x03
-#define GCGraphicsExposures 0
-
-/* Bit Gravity */
-
-#define ForgetGravity 0
-#define NorthWestGravity 1
-#define NorthGravity 2
-#define NorthEastGravity 3
-#define WestGravity 4
-#define CenterGravity 5
-#define EastGravity 6
-#define SouthWestGravity 7
-#define SouthGravity 8
-#define SouthEastGravity 9
-#define StaticGravity 10
-
-#define NoValue 0x0000
-#define XValue 0x0001
-#define YValue 0x0002
-#define WidthValue 0x0004
-#define HeightValue 0x0008
-#define AllValues 0x000F
-#define XNegative 0x0010
-#define YNegative 0x0020
-
-#define USPosition (1L << 0) /* user specified x, y */
-#define USSize (1L << 1) /* user specified width, height */
-
-#define PPosition (1L << 2) /* program specified position */
-#define PSize (1L << 3) /* program specified size */
-#define PMinSize (1L << 4) /* program specified minimum size */
-#define PMaxSize (1L << 5) /* program specified maximum size */
-#define PResizeInc (1L << 6) /* program specified resize increments */
-#define PAspect (1L << 7) /* program specified min and max aspect ratios */
-#define PBaseSize (1L << 8) /* program specified base for incrementing */
-#define PWinGravity (1L << 9) /* program specified window gravity */
-
-extern int XParseGeometry ();
-
-#endif /* EMACS_MACGUI_H */
-
+++ /dev/null
-/* Display module for Mac OS.
- Copyright (C) 2000 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Contributed by Andrew Choi (akochoi@users.sourceforge.net). */
-
-#include "macgui.h"
-#include "frame.h"
-
-/* The class of this X application. */
-#define EMACS_CLASS "Emacs"
-
-#define RGB_TO_ULONG(r, g, b) (((r) << 16) | ((g) << 8) | (b))
-
-#define RED_FROM_ULONG(color) ((color) >> 16)
-#define GREEN_FROM_ULONG(color) (((color) >> 8) & 0xff)
-#define BLUE_FROM_ULONG(color) ((color) & 0xff)
-
-#define BLACK_PIX_DEFAULT(f) RGB_TO_ULONG(0,0,0)
-#define WHITE_PIX_DEFAULT(f) RGB_TO_ULONG(255,255,255)
-
-#define FONT_WIDTH(f) ((f)->max_bounds.width)
-#define FONT_HEIGHT(f) ((f)->ascent + (f)->descent)
-#define FONT_BASE(f) ((f)->ascent)
-#define FONT_DESCENT(f) ((f)->descent)
-
-#define FONT_MAX_WIDTH(f) FONT_WIDTH(f) /* fix later */
-
-enum text_cursor_kinds {
- NO_CURSOR = -1,
- FILLED_BOX_CURSOR,
- HOLLOW_BOX_CURSOR,
- BAR_CURSOR
-};
-
-/* Structure recording bitmaps and reference count.
- If REFCOUNT is 0 then this record is free to be reused. */
-
-struct mac_bitmap_record
-{
- char *bitmap_data;
- int refcount;
- int height, width;
-};
-
-
-/* For each display (currently only one on mac), we have a structure that
- records information about it. */
-
-struct mac_display_info
-{
- /* Chain of all mac_display_info structures. */
- struct mac_display_info *next;
-
- /* This is a cons cell of the form (NAME . FONT-LIST-CACHE).
- The same cons cell also appears in x_display_name_list. */
- Lisp_Object name_list_element;
-
- /* Number of frames that are on this display. */
- int reference_count;
-
- /* Dots per inch of the screen. */
- double resx, resy;
-
- /* Number of planes on this screen. */
- int n_planes;
-
- /* Number of bits per pixel on this screen. */
- int n_cbits;
-
- /* Dimensions of this screen. */
- int height, width;
-#if 0
- int height_in,width_in;
-#endif
-
- /* Mask of things that cause the mouse to be grabbed. */
- int grabbed;
-
-#if 0
- /* Emacs bitmap-id of the default icon bitmap for this frame.
- Or -1 if none has been allocated yet. */
- int icon_bitmap_id;
-
-#endif
- /* The root window of this screen. */
- Window root_window;
-
- /* The cursor to use for vertical scroll bars. */
- Cursor vertical_scroll_bar_cursor;
-
-#if 0
- /* color palette information. */
- int has_palette;
- struct w32_palette_entry * color_list;
- unsigned num_colors;
- HPALETTE palette;
-
- /* deferred action flags checked when starting frame update. */
- int regen_palette;
-
- /* Keystroke that has been faked by Emacs and will be ignored when
- received; value is reset after key is received. */
- int faked_key;
-
-#endif
-
- /* A table of all the fonts we have already loaded. */
- struct font_info *font_table;
-
- /* The current capacity of font_table. */
- int font_table_size;
-
- /* The number of fonts actually stored in the font table.
- font_table[n] is used and valid iff 0 <= n < n_fonts. 0 <=
- n_fonts <= font_table_size. and font_table[i].name != 0. */
- int n_fonts;
-
- /* Minimum width over all characters in all fonts in font_table. */
- int smallest_char_width;
-
- /* Minimum font height over all fonts in font_table. */
- int smallest_font_height;
-
- /* Reusable Graphics Context for drawing a cursor in a non-default face. */
- XGCValues *scratch_cursor_gc;
-
- /* These variables describe the range of text currently shown in its
- mouse-face, together with the window they apply to. As long as
- the mouse stays within this range, we need not redraw anything on
- its account. Rows and columns are glyph matrix positions in
- MOUSE_FACE_WINDOW. */
- int mouse_face_beg_row, mouse_face_beg_col;
- int mouse_face_beg_x, mouse_face_beg_y;
- int mouse_face_end_row, mouse_face_end_col;
- int mouse_face_end_x, mouse_face_end_y;
- int mouse_face_past_end;
-
- Lisp_Object mouse_face_window;
-
- int mouse_face_face_id;
-
- /* 1 if a mouse motion event came and we didn't handle it right away because
- gc was in progress. */
- int mouse_face_deferred_gc;
-
- /* FRAME and X, Y position of mouse when last checked for
- highlighting. X and Y can be negative or out of range for the frame. */
- struct frame *mouse_face_mouse_frame;
-
- int mouse_face_mouse_x, mouse_face_mouse_y;
-
- /* Nonzero means defer mouse-motion highlighting. */
- int mouse_face_defer;
-
- int mouse_face_image_state;
-
- char *mac_id_name;
-
- /* Pointer to bitmap records. */
- struct mac_bitmap_record *bitmaps;
-
- /* Allocated size of bitmaps field. */
- int bitmaps_size;
-
- /* Last used bitmap index. */
- int bitmaps_last;
-
- /* The frame (if any) which has the window that has keyboard focus.
- Zero if none. This is examined by Ffocus_frame in w32fns.c. Note
- that a mere EnterNotify event can set this; if you need to know the
- last frame specified in a FocusIn or FocusOut event, use
- w32_focus_event_frame. */
- struct frame *x_focus_frame;
-
- /* The last frame mentioned in a FocusIn or FocusOut event. This is
- separate from w32_focus_frame, because whether or not LeaveNotify
- events cause us to lose focus depends on whether or not we have
- received a FocusIn event for it. */
- struct frame *x_focus_event_frame;
-
- /* The frame which currently has the visual highlight, and should get
- keyboard input (other sorts of input have the frame encoded in the
- event). It points to the focus frame's selected window's
- frame. It differs from w32_focus_frame when we're using a global
- minibuffer. */
- struct frame *x_highlight_frame;
-
- /* Cache of images. */
- struct image_cache *image_cache;
-};
-
-#define x_display_info mac_display_info
-
-/* This is a chain of structures for all the displays currently in use. */
-extern struct mac_display_info one_mac_display_info;
-
-/* This is a chain of structures for all the X displays currently in use. */
-extern struct x_display_info *x_display_list;
-
-/* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
- one for each element of x_display_list and in the same order.
- NAME is the name of the frame.
- FONT-LIST-CACHE records previous values returned by x-list-fonts. */
-extern Lisp_Object x_display_name_list;
-
-/* A flag to control how to display unibyte 8-bit character. */
-extern int unibyte_display_via_language_environment;
-
-extern struct x_display_info *x_display_info_for_display P_ ((Display *));
-extern struct x_display_info *x_display_info_for_name P_ ((Lisp_Object));
-
-extern struct mac_display_info *mac_term_init ();
-
-/* The collection of data describing a window on the Mac. Functions
- defined in macterm.c */
-struct mac_output {
- WindowPtr mWP; /* pointer to QuickDraw window */
- FRAME_PTR mFP; /* points back to the frame struct */
-
-#if 0
- int mNumCols; /* number of characters per column */
- int mNumRows; /* number of characters per row */
- int mLineHeight; /* height of one line of text in pixels */
- int mCharWidth; /* width of one character in pixels */
- int mHomeX; /* X pixel coordinate of lower left corner of character at (0, 0) */
- int mHomeY; /* Y pixel coordinate of lower left corner of character at (0, 0) */
- int mHighlight; /* current highlight state (0 = off). */
- int mTermWinSize; /* num of lines from top of window affected by ins_del_lines; set by set_terminal_window. */
-#endif
-
-#if 0
- /* stuffs used by xfaces.c */
- struct face **param_faces;
- int n_param_faces;
- struct face **computed_faces;
- int n_computed_faces;
- int size_computed_faces;
-#endif
-
- unsigned long background_pixel;
- unsigned long foreground_pixel;
-
- /* Position of the Mac window (x and y offsets in global coordinates). */
- int left_pos;
- int top_pos;
-
- /* Border width of the W32 window as known by the window system. */
- int border_width;
-
- /* Size of the W32 window in pixels. */
- int pixel_height, pixel_width;
-
- /* Height of a line, in pixels. */
- int line_height;
-
- /* Here are the Graphics Contexts for the default font. */
- GC normal_gc; /* Normal video */
- GC reverse_gc; /* Reverse video */
- GC cursor_gc; /* cursor drawing */
-
- /* Width of the internal border. This is a line of background color
- just inside the window's border. When the frame is selected,
- a highlighting is displayed inside the internal border. */
- int internal_border_width;
-
- /* The window used for this frame.
- May be zero while the frame object is being created
- and the window has not yet been created. */
- Window window_desc;
-
- /* The window that is the parent of this window.
- Usually this is a window that was made by the window manager,
- but it can be the root window, and it can be explicitly specified
- (see the explicit_parent field, below). */
- Window parent_desc;
-
- /* Default ASCII font of this frame. */
- XFontStruct *font;
-
- /* The baseline offset of the default ASCII font. */
- int baseline_offset;
-
- /* If a fontset is specified for this frame instead of font, this
- value contains an ID of the fontset, else -1. */
- int fontset;
-
- /* Pixel values used for various purposes.
- border_pixel may be -1 meaning use a gray tile. */
- unsigned long cursor_pixel;
- unsigned long border_pixel;
- unsigned long mouse_pixel;
- unsigned long cursor_foreground_pixel;
-
- /* Foreground color for scroll bars. A value of -1 means use the
- default (black for non-toolkit scroll bars). */
- unsigned long scroll_bar_foreground_pixel;
-
- /* Background color for scroll bars. A value of -1 means use the
- default (background color of the frame for non-toolkit scroll
- bars). */
- unsigned long scroll_bar_background_pixel;
-
- /* Descriptor for the cursor in use for this window. */
- Cursor text_cursor;
- Cursor nontext_cursor;
- Cursor modeline_cursor;
- Cursor cross_cursor;
- Cursor hourglass_cursor;
-#if 0
- /* Window whose cursor is hourglass_cursor. This window is temporarily
- mapped to display a hourglass-cursor. */
- Window hourglass_window;
-
- /* Non-zero means hourglass cursor is currently displayed. */
- unsigned hourglass_p : 1;
-
- /* Flag to set when the window needs to be completely repainted. */
- int needs_exposure;
-
-#endif
-
- /* What kind of text cursor is drawn in this window right now?
- (If there is no cursor (phys_cursor_x < 0), then this means nothing.) */
- enum text_cursor_kinds current_cursor;
-
- /* What kind of text cursor should we draw in the future?
- This should always be filled_box_cursor or bar_cursor. */
- enum text_cursor_kinds desired_cursor;
-
- /* Width of bar cursor (if we are using that). */
- int cursor_width;
-
-#if 0
- DWORD dwStyle;
-#endif
-
- /* The size of the extra width currently allotted for vertical
- scroll bars, in pixels. */
- int vertical_scroll_bar_extra;
-
- /* The extra width currently allotted for the areas in which
- truncation marks, continuation marks, and overlay arrows are
- displayed. */
- int left_fringe_width, right_fringe_width;
- int fringe_cols, fringes_extra;
-
- /* This is the gravity value for the specified window position. */
- int win_gravity;
-
- /* The geometry flags for this window. */
- int size_hint_flags;
-
- /* This is the Emacs structure for the display this frame is on. */
- /* struct w32_display_info *display_info; */
-
- /* Nonzero means our parent is another application's window
- and was explicitly specified. */
- char explicit_parent;
-
- /* Nonzero means tried already to make this frame visible. */
- char asked_for_visible;
-
- /* Nonzero means menubar is currently active. */
- char menubar_active;
-
- /* Always contains NULL on the Mac OS because the menu bar is shared. */
- int menubar_widget;
-
-#if 0
- /* Nonzero means menubar is about to become active, but should be
- brought up to date first. */
- volatile char pending_menu_activation;
-
-#endif
- /* Relief GCs, colors etc. */
- struct relief
- {
- XGCValues *gc;
- unsigned long pixel;
- int allocated_p;
- }
- black_relief, white_relief;
-
- /* The background for which the above relief GCs were set up.
- They are changed only when a different background is involved. */
- unsigned long relief_background;
-};
-
-typedef struct mac_output mac_output;
-
-/* Return the Mac window used for displaying data in frame F. */
-#define FRAME_MAC_WINDOW(f) ((f)->output_data.mac->mWP)
-
-#define FRAME_FOREGROUND_PIXEL(f) ((f)->output_data.mac->foreground_pixel)
-#define FRAME_BACKGROUND_PIXEL(f) ((f)->output_data.mac->background_pixel)
-
-#define FRAME_FONT(f) ((f)->output_data.mac->font)
-#define FRAME_FONTSET(f) ((f)->output_data.mac->fontset)
-
-#define FRAME_INTERNAL_BORDER_WIDTH(f) ((f)->output_data.mac->internal_border_width)
-#define FRAME_LINE_HEIGHT(f) ((f)->output_data.mac->line_height)
-/* Width of the default font of frame F. Must be defined by each
- terminal specific header. */
-#define FRAME_DEFAULT_FONT_WIDTH(F) FONT_WIDTH (FRAME_FONT (F))
-#define FRAME_BASELINE_OFFSET(f) ((f)->output_data.mac->baseline_offset)
-
-/* This gives the w32_display_info structure for the display F is on. */
-#define FRAME_MAC_DISPLAY_INFO(f) (&one_mac_display_info)
-#define FRAME_X_DISPLAY_INFO(f) (&one_mac_display_info)
-
-/* This is the `Display *' which frame F is on. */
-#define FRAME_MAC_DISPLAY(f) (0)
-
-/* This is the 'font_info *' which frame F has. */
-#define FRAME_MAC_FONT_TABLE(f) (FRAME_MAC_DISPLAY_INFO (f)->font_table)
-
-/* These two really ought to be called FRAME_PIXEL_{WIDTH,HEIGHT}. */
-#define PIXEL_WIDTH(f) ((f)->output_data.mac->pixel_width)
-#define PIXEL_HEIGHT(f) ((f)->output_data.mac->pixel_height)
-
-#define FRAME_DESIRED_CURSOR(f) ((f)->output_data.mac->desired_cursor)
-
-/* Value is the smallest width of any character in any font on frame F. */
-
-#define FRAME_SMALLEST_CHAR_WIDTH(F) \
- FRAME_MAC_DISPLAY_INFO(F)->smallest_char_width
-
-/* Value is the smallest height of any font on frame F. */
-
-#define FRAME_SMALLEST_FONT_HEIGHT(F) \
- FRAME_MAC_DISPLAY_INFO(F)->smallest_font_height
-
-/* Return a pointer to the image cache of frame F. */
-
-#define FRAME_X_IMAGE_CACHE(F) FRAME_MAC_DISPLAY_INFO ((F))->image_cache
-
-\f
-/* Total width of fringes reserved for drawing truncation bitmaps,
- continuation bitmaps and alike. The width is in canonical char
- units of the frame. This must currently be the case because window
- sizes aren't pixel values. If it weren't the case, we wouldn't be
- able to split windows horizontally nicely. */
-
-#define FRAME_X_FRINGE_COLS(F) ((F)->output_data.mac->fringe_cols)
-
-/* Total width of fringes in pixels. */
-
-#define FRAME_X_FRINGE_WIDTH(F) ((F)->output_data.mac->fringes_extra)
-
-/* Pixel-width of the left and right fringe. */
-
-#define FRAME_X_LEFT_FRINGE_WIDTH(F) ((F)->output_data.mac->left_fringe_width)
-#define FRAME_X_RIGHT_FRINGE_WIDTH(F) ((F)->output_data.mac->right_fringe_width)
-
-\f
-/* Mac-specific scroll bar stuff. */
-
-/* We represent scroll bars as lisp vectors. This allows us to place
- references to them in windows without worrying about whether we'll
- end up with windows referring to dead scroll bars; the garbage
- collector will free it when its time comes.
-
- We use struct scroll_bar as a template for accessing fields of the
- vector. */
-
-struct scroll_bar {
-
- /* These fields are shared by all vectors. */
- EMACS_INT size_from_Lisp_Vector_struct;
- struct Lisp_Vector *next_from_Lisp_Vector_struct;
-
- /* The window we're a scroll bar for. */
- Lisp_Object window;
-
- /* The next and previous in the chain of scroll bars in this frame. */
- Lisp_Object next, prev;
-
- /* The Mac control handle of this scroll bar. Since this is a full
- 32-bit quantity, we store it split into two 32-bit values. */
- Lisp_Object control_handle_low, control_handle_high;
-
- /* The position and size of the scroll bar in pixels, relative to the
- frame. */
- Lisp_Object top, left, width, height;
-
- /* The starting and ending positions of the handle, relative to the
- handle area (i.e. zero is the top position, not
- SCROLL_BAR_TOP_BORDER). If they're equal, that means the handle
- hasn't been drawn yet.
-
- These are not actually the locations where the beginning and end
- are drawn; in order to keep handles from becoming invisible when
- editing large files, we establish a minimum height by always
- drawing handle bottoms VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
- where they would be normally; the bottom and top are in a
- different co-ordinate system. */
- Lisp_Object start, end;
-
- /* If the scroll bar handle is currently being dragged by the user,
- this is the number of pixels from the top of the handle to the
- place where the user grabbed it. If the handle isn't currently
- being dragged, this is Qnil. */
- Lisp_Object dragging;
-};
-
-/* The number of elements a vector holding a struct scroll_bar needs. */
-#define SCROLL_BAR_VEC_SIZE \
- ((sizeof (struct scroll_bar) \
- - sizeof (EMACS_INT) - sizeof (struct Lisp_Vector *)) \
- / sizeof (Lisp_Object))
-
-/* Turning a lisp vector value into a pointer to a struct scroll_bar. */
-#define XSCROLL_BAR(vec) ((struct scroll_bar *) XVECTOR (vec))
-
-
-/* Building a 32-bit C integer from two 16-bit lisp integers. */
-#define SCROLL_BAR_PACK(low, high) (XINT (high) << 16 | XINT (low))
-
-/* Setting two lisp integers to the low and high words of a 32-bit C int. */
-#define SCROLL_BAR_UNPACK(low, high, int32) \
- (XSETINT ((low), (int32) & 0xffff), \
- XSETINT ((high), ((int32) >> 16) & 0xffff))
-
-
-/* Extract the Mac control handle of the scroll bar from a struct scroll_bar. */
-#define SCROLL_BAR_CONTROL_HANDLE(ptr) \
- ((ControlHandle) SCROLL_BAR_PACK ((ptr)->control_handle_low, (ptr)->control_handle_high))
-
-/* Store a Mac control handle in a struct scroll_bar. */
-#define SET_SCROLL_BAR_CONTROL_HANDLE(ptr, id) \
- (SCROLL_BAR_UNPACK ((ptr)->control_handle_low, (ptr)->control_handle_high, (int) id))
-
-/* Return the inside width of a vertical scroll bar, given the outside
- width. */
-#define VERTICAL_SCROLL_BAR_INSIDE_WIDTH(f,width) \
- ((width) \
- - VERTICAL_SCROLL_BAR_LEFT_BORDER \
- - VERTICAL_SCROLL_BAR_RIGHT_BORDER \
- - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2)
-
-/* Return the length of the rectangle within which the top of the
- handle must stay. This isn't equivalent to the inside height,
- because the scroll bar handle has a minimum height.
-
- This is the real range of motion for the scroll bar, so when we're
- scaling buffer positions to scroll bar positions, we use this, not
- VERTICAL_SCROLL_BAR_INSIDE_HEIGHT. */
-#define VERTICAL_SCROLL_BAR_TOP_RANGE(f,height) \
- (VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, height) - VERTICAL_SCROLL_BAR_MIN_HANDLE - UP_AND_DOWN_ARROWS)
-
-/* Return the inside height of vertical scroll bar, given the outside
- height. See VERTICAL_SCROLL_BAR_TOP_RANGE too. */
-#define VERTICAL_SCROLL_BAR_INSIDE_HEIGHT(f,height) \
- ((height) - VERTICAL_SCROLL_BAR_TOP_BORDER - VERTICAL_SCROLL_BAR_BOTTOM_BORDER)
-
-
-/* Border widths for scroll bars.
-
- Scroll bar windows don't have any borders; their border width is
- set to zero, and we redraw borders ourselves. This makes the code
- a bit cleaner, since we don't have to convert between outside width
- (used when relating to the rest of the screen) and inside width
- (used when sizing and drawing the scroll bar window itself).
-
- The handle moves up and down/back and forth in a rectangle inset
- from the edges of the scroll bar. These are widths by which we
- inset the handle boundaries from the scroll bar edges. */
-#define VERTICAL_SCROLL_BAR_LEFT_BORDER (0)
-#define VERTICAL_SCROLL_BAR_RIGHT_BORDER (0)
-#define VERTICAL_SCROLL_BAR_TOP_BORDER (0)
-#define VERTICAL_SCROLL_BAR_BOTTOM_BORDER (0)
-
-/* Minimum lengths for scroll bar handles, in pixels. */
-#define VERTICAL_SCROLL_BAR_MIN_HANDLE (16)
-
-/* Combined length of up and down arrow boxes in scroll bars, in pixels. */
-#define UP_AND_DOWN_ARROWS (32)
-
-/* Trimming off a few pixels from each side prevents
- text from glomming up against the scroll bar */
-#define VERTICAL_SCROLL_BAR_WIDTH_TRIM (0)
-
-\f
-/* Manipulating pixel sizes and character sizes.
- Knowledge of which factors affect the overall size of the window should
- be hidden in these macros, if that's possible.
-
- Return the upper/left pixel position of the character cell on frame F
- at ROW/COL. */
-#define CHAR_TO_PIXEL_ROW(f, row) \
- ((f)->output_data.mac->internal_border_width \
- + (row) * (f)->output_data.mac->line_height)
-#define CHAR_TO_PIXEL_COL(f, col) \
- ((f)->output_data.mac->internal_border_width \
- + (col) * FONT_WIDTH ((f)->output_data.mac->font))
-
-/* Return the pixel width/height of frame F if it has
- WIDTH columns/HEIGHT rows. */
-#define CHAR_TO_PIXEL_WIDTH(f, width) \
- (CHAR_TO_PIXEL_COL (f, width) \
- + (f)->output_data.mac->vertical_scroll_bar_extra \
- + (f)->output_data.mac->fringes_extra \
- + (f)->output_data.mac->internal_border_width)
-#define CHAR_TO_PIXEL_HEIGHT(f, height) \
- (CHAR_TO_PIXEL_ROW (f, height) \
- + (f)->output_data.mac->internal_border_width)
-
-
-/* Return the row/column (zero-based) of the character cell containing
- the pixel on FRAME at ROW/COL. */
-#define PIXEL_TO_CHAR_ROW(f, row) \
- (((row) - (f)->output_data.mac->internal_border_width) \
- / (f)->output_data.mac->line_height)
-#define PIXEL_TO_CHAR_COL(f, col) \
- (((col) - (f)->output_data.mac->internal_border_width) \
- / FONT_WIDTH ((f)->output_data.mac->font))
-
-/* How many columns/rows of text can we fit in WIDTH/HEIGHT pixels on
- frame F? */
-#define PIXEL_TO_CHAR_WIDTH(f, width) \
- (PIXEL_TO_CHAR_COL (f, ((width) \
- - (f)->output_data.mac->internal_border_width \
- - (f)->output_data.mac->fringes_extra \
- - (f)->output_data.mac->vertical_scroll_bar_extra)))
-#define PIXEL_TO_CHAR_HEIGHT(f, height) \
- (PIXEL_TO_CHAR_ROW (f, ((height) \
- - (f)->output_data.mac->internal_border_width)))
-
-struct frame * check_x_frame (Lisp_Object);
-
-/* Dummy entry for defining tty_display in frame.c. */
-struct x_output
-{
- char _dummy;
-};
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Contributed by Andrew Choi (akochoi@users.sourceforge.net). */
+/* Contributed by Andrew Choi (akochoi@mac.com). */
#ifndef _PWD_H
#define _PWD_H
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Contributed by Andrew Choi (akochoi@users.sourceforge.net). */
+/* Contributed by Andrew Choi (akochoi@mac.com). */
/*
* Define symbols to identify the version of Unix this is.
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Contributed by Andrew Choi (akochoi@users.sourceforge.net). */
+/* Contributed by Andrew Choi (akochoi@mac.com). */
#ifndef _SYS_FILE_H
#define _SYS_FILE_H
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Contributed by Andrew Choi (akochoi@users.sourceforge.net). */
+/* Contributed by Andrew Choi (akochoi@mac.com). */
#ifndef _SYS_IOCTL_H
#define _SYS_IOCTL_H
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Contributed by Andrew Choi (akochoi@users.sourceforge.net). */
+/* Contributed by Andrew Choi (akochoi@mac.com). */
#ifndef _SYS_PARAM_H
#define _SYS_PARAM_H
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Contributed by Andrew Choi (akochoi@users.sourceforge.net). */
+/* Contributed by Andrew Choi (akochoi@mac.com). */
#ifndef _SYS_STAT_H
#define _SYS_STAT_H
#ifdef __MWERKS__
#include <stat.mac.h>
-#ifdef CODEWARRIOR_VERSION_6
+#if __MSL__ >= 0x6000
#define fstat _fstat
#endif
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Contributed by Andrew Choi (akochoi@users.sourceforge.net). */
+/* Contributed by Andrew Choi (akochoi@mac.com). */
#ifndef _SYS_TIME_H
#define _SYS_TIME_H
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Contributed by Andrew Choi (akochoi@users.sourceforge.net). */
+/* Contributed by Andrew Choi (akochoi@mac.com). */
#ifndef _SYS_TYPES_H
#define _SYS_TYPES_H
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Contributed by Andrew Choi (akochoi@users.sourceforge.net). */
+/* Contributed by Andrew Choi (akochoi@mac.com). */
#ifndef _SYS_TERMIO_H
#define _SYS_TERMIO_H
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Contributed by Andrew Choi (akochoi@users.sourceforge.net). */
+/* Contributed by Andrew Choi (akochoi@mac.com). */
#ifndef _UTIME_H_
#define _UTIME_H_
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Contributed by Andrew Choi (akochoi@users.sourceforge.net). */
+/* Contributed by Andrew Choi (akochoi@mac.com). */
#ifndef _UTSNAME_H
#define _UTSNAME_H
--- /dev/null
+#!/bin/sh
+
+#### make-bin-dist: create a binary Emacs distribution tar file for
+#### Mac OS X. This basically runs a `configure' and `make install'
+#### into a temporary directory and archives that directory. It also
+#### places the Emacs application bundle and a installer script in the
+#### tar file. The installer script is run to set up the XML file for
+#### setting the environment variables used by Emacs when it is
+#### started from the Finder.
+
+# Copyright (C) 2002 Free Software Foundation, Inc.
+#
+# This file is part of GNU Emacs.
+#
+# GNU Emacs is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+progname="$0"
+
+### Exit if a command fails.
+#set -e
+
+### Print out each line we read, for debugging's sake.
+set -v
+
+LANGUAGE=C
+LC_ALL=C
+LC_MESSAGES=
+LANG=
+export LANGUAGE LC_ALL LC_MESSAGES LANG
+
+## Don't restrict access to any files.
+umask 0
+
+### Make sure we're running in the right place.
+if [ ! -f Emacs.app/Contents/PkgInfo ]; then
+ echo "${progname}: Can't find \`Emacs.app/Contents/PkgInfo'" >&2
+ echo "${progname} must be run in the \`mac' directory of the Emacs" >&2
+ echo "distribution tree. cd to that directory and try again." >&2
+ exit 1
+fi
+
+### Check whether file ../lisp/version.el exists.
+if [ ! -f ../lisp/version.el ]; then
+ echo "${progname}: Can't find \`../lisp/version.el'" >&2
+ exit 1
+fi
+
+### Find out which version of Emacs this is.
+shortversion=`grep 'defconst[ ]*emacs-version' ../lisp/version.el \
+ | sed -e 's/^.*"\([0-9][0-9]*\.[0-9][0-9]*\).*$/\1/'`
+version=`grep 'defconst[ ]*emacs-version' ../lisp/version.el \
+ | sed -e 's/^[^"]*"\([^"]*\)".*$/\1/'`
+if [ ! "${version}" ]; then
+ echo "${progname}: can't find current Emacs version in \`./lisp/version.el'" >&2
+ exit 1
+fi
+
+echo Version numbers are $version and $shortversion
+
+### Make sure we don't already have a directory emacs-${version}.
+
+emacsname="emacs-${version}${new_extension}"
+
+if [ -d ${emacsname} ]
+then
+ echo Directory "${emacsname}" already exists >&2
+ exit 1
+fi
+
+### Make sure the subdirectory is available.
+tempparent="make-bin-dist.tmp.$$"
+if [ -d ${tempparent} ]; then
+ echo "${progname}: staging directory \`${tempparent}' already exists.
+Perhaps a previous invocation of \`${progname}' failed to clean up after
+itself. Check that directories whose names are of the form
+\`make-dist.tmp.NNNNN' don't contain any important information, remove
+them, and try again." >&2
+ exit 1
+fi
+
+tempparentfull="`pwd`/${tempparent}"
+
+echo Installing into directory ${tempparentfull} >&2
+
+(cd ..; ./configure --prefix=${tempparentfull}; make install)
+
+### This trap ensures that the staging directory will be cleaned up even
+### when the script is interrupted in mid-career.
+trap "echo 'Interrupted...cleaning up the staging directory'; rm -rf ${tempparent}; exit 1" 1 2 15
+
+cp -r Emacs.app ${tempparent}
+
+cp osx-install ${tempparent}
+
+echo "Creating tar file"
+
+mv ${tempparent} ${emacsname}
+
+tar cvf - ${emacsname} | gzip > ${emacsname}-mac-bin.tar.gz
+
+echo "Cleaning up the staging directory"
+rm -rf ${emacsname}
+
+### make-bin-dist ends here
PPCCOptions = {SymOption} {OptOption} -noMapCR -enum int ¶
-typecheck relaxed -w off ¶
-includes unix -i {Includes},{Src} ¶
- -d emacs=1 -d HAVE_CONFIG_H
+ -d emacs=1 -d HAVE_CONFIG_H -d MAC_OS -d MAC_OS8
LinkOptions = {SymOption} -d
CONFIG_H_GROUP = "{Includes}config.h" "{Includes}s-mac.h" "{Includes}utsname.h" "{Includes}m-mac.h"
-DISPEXTERN_H_GROUP = "{Src}dispextern.h" "{Includes}macgui.h"
-INTERVALS_H_GROUP = "{Src}intervals.h" "{Src}dispextern.h" "{Includes}macgui.h"
+DISPEXTERN_H_GROUP = "{Src}dispextern.h" "{Src}macgui.h"
+INTERVALS_H_GROUP = "{Src}intervals.h" "{Src}dispextern.h" "{Src}macgui.h"
WINDOW_H_GROUP = "{Src}window.h" {DISPEXTERN_H_GROUP}
BLOCKINPUT_H_GROUP = "{Src}blockinput.h" "{Src}atimer.h" "{Src}systime.h" ¶
"{Includes}sys:time.h" "{Includes}sys:time.h"
# The list of object files generated from new source files of the Macintosh port.
MacObjects = ¶
- "{Source}mac.c.x" ¶
- "{Source}macfns.c.x" ¶
- "{Source}macmenu.c.x" ¶
- "{Source}macterm.c.x"
+ "{Src}mac.c.x" ¶
+ "{Src}macfns.c.x" ¶
+ "{Src}macmenu.c.x" ¶
+ "{Src}macterm.c.x"
# The next two are the dependency rules for building Emacs.
"{Src}process.h" ¶
"{Src}keyboard.h" ¶
"{Src}syssignal.h" ¶
- "{Includes}macterm.h" ¶
- "{Includes}macgui.h" ¶
+ "{Src}macterm.h" ¶
+ "{Src}macgui.h" ¶
"{Src}frame.h" ¶
"{Src}systime.h"
"{Src}lisp.h" ¶
"{Src}charset.h" ¶
"{Src}fontset.h" ¶
- "{Includes}macterm.h" ¶
- "{Includes}macgui.h" ¶
+ "{Src}macterm.h" ¶
+ "{Src}macgui.h" ¶
"{Src}frame.h" ¶
"{Src}frame.h" ¶
"{Src}fontset.h" ¶
"{Src}systty.h" ¶
"{Includes}termio.h" ¶
"{Includes}sys:types.h" ¶
- "{Includes}macterm.h" ¶
- "{Includes}macgui.h" ¶
+ "{Src}macterm.h" ¶
+ "{Src}macgui.h" ¶
"{Src}frame.h" ¶
"{Src}systime.h"
{DISPEXTERN_H_GROUP} ¶
{WINDOW_H_GROUP} ¶
"{Src}cm.h" ¶
- "{Includes}macterm.h" ¶
- "{Includes}macgui.h" ¶
+ "{Src}macterm.h" ¶
+ "{Src}macgui.h" ¶
"{Src}frame.h"
{Src}termcap.c.x Ä ¶
{DISPEXTERN_H_GROUP} ¶
{BLOCKINPUT_H_GROUP} ¶
{INTERVALS_H_GROUP} ¶
- "{Includes}macterm.h" ¶
- "{Includes}macgui.h" ¶
+ "{Src}macterm.h" ¶
+ "{Src}macgui.h" ¶
"{Src}frame.h"
{Src}xdisp.c.x Ä ¶
"{Src}process.h" ¶
"{Src}region-cache.h" ¶
"{Src}fontset.h" ¶
- "{Includes}macterm.h" ¶
- "{Includes}macgui.h" ¶
+ "{Src}macterm.h" ¶
+ "{Src}macgui.h" ¶
"{Src}frame.h"
{Src}xfaces.c.x Ä ¶
"{Src}charset.h" ¶
"{Src}frame.h" ¶
"{Src}fontset.h" ¶
- "{Includes}macterm.h" ¶
- "{Includes}macgui.h" ¶
+ "{Src}macterm.h" ¶
+ "{Src}macgui.h" ¶
"{Src}frame.h" ¶
"{Src}buffer.h" ¶
{DISPEXTERN_H_GROUP} ¶
"{Includes}sys:types.h" ¶
{DISPEXTERN_H_GROUP}
-{Source}mac.c Ä ¶
+{Src}mac.c Ä ¶
{CONFIG_H_GROUP} ¶
"{Includes}utime.h" ¶
"{Includes}dirent.h" ¶
"{Includes}sys:time.h" ¶
"{Includes}utsname.h"
-{Source}macfns.c Ä ¶
+{Src}macfns.c Ä ¶
{CONFIG_H_GROUP} ¶
"{Src}lisp.h" ¶
"{Src}charset.h" ¶
- "{Includes}macterm.h" ¶
- "{Includes}macgui.h" ¶
+ "{Src}macterm.h" ¶
+ "{Src}macgui.h" ¶
"{Src}frame.h" ¶
"{Src}frame.h" ¶
{WINDOW_H_GROUP} ¶
"{Src}systime.h" ¶
"{Src}bitmaps:gray.xbm"
-{Source}macterm.c Ä ¶
+{Src}macterm.c Ä ¶
{CONFIG_H_GROUP} ¶
"{Src}lisp.h" ¶
{BLOCKINPUT_H_GROUP} ¶
"{Src}syssignal.h" ¶
- "{Includes}macterm.h" ¶
- "{Includes}macgui.h" ¶
+ "{Src}macterm.h" ¶
+ "{Src}macgui.h" ¶
"{Src}frame.h" ¶
"{Includes}alloca.h" ¶
"{Includes}sys:types.h" ¶
"{Src}xmenu.c"
MacSource = ¶
- "{Source}mac.c" ¶
- "{Source}macfns.c" ¶
- "{Source}macterm.c"
+ "{Src}mac.c" ¶
+ "{Src}macfns.c" ¶
+ "{Src}macterm.c"
LispSource = ¶
{Lisp}language:chinese.elc ¶
{Lisp}language:cyrillic.elc ¶
{Lisp}language:indian.elc ¶
- {Lisp}language:devanagari.elc ¶
- {Lisp}language:english.elc ¶
{Lisp}language:ethiopic.elc ¶
{Lisp}language:european.elc ¶
- {Lisp}language:czech.elc ¶
- {Lisp}language:slovak.elc ¶
- {Lisp}language:romanian.elc ¶
- {Lisp}language:greek.elc ¶
- {Lisp}language:hebrew.elc ¶
- {Lisp}language:japanese.elc ¶
- {Lisp}language:korean.elc ¶
- {Lisp}language:lao.elc ¶
- {Lisp}language:thai.elc ¶
{Lisp}language:tibetan.elc ¶
{Lisp}language:vietnamese.elc ¶
- {Lisp}language:misc-lang.elc ¶
{Lisp}paths.el ¶
{Lisp}register.elc ¶
{Lisp}replace.elc ¶
{Lisp}window.elc ¶
{Lisp}version.el
+LispSourceDontCompile = ¶
+ {Lisp}language:devanagari.el ¶
+ {Lisp}language:english.el ¶
+ {Lisp}language:czech.el ¶
+ {Lisp}language:slovak.el ¶
+ {Lisp}language:romanian.el ¶
+ {Lisp}language:greek.el ¶
+ {Lisp}language:hebrew.el ¶
+ {Lisp}language:japanese.el ¶
+ {Lisp}language:korean.el ¶
+ {Lisp}language:lao.el ¶
+ {Lisp}language:thai.el ¶
+ {Lisp}language:misc-lang.el
Doc Ä {DocTarget}DOC
-{DocTarget}DOC Ä {Makefile} {EmacsSource} {MacSource} {LispSource} {Make-DocFileDir}Make-DocFile
+{DocTarget}DOC Ä {Makefile} {EmacsSource} {MacSource} {LispSource} {LispSourceDontCompile} {Make-DocFileDir}Make-DocFile
{Make-DocFileDir}make-docfile {EmacsSource} > {DocTarget}DOC
{Make-DocFileDir}make-docfile {MacSource} >> {DocTarget}DOC
{Make-DocFileDir}make-docfile {LispSource} >> {DocTarget}DOC
+ {Make-DocFileDir}make-docfile {LispSourceDontCompile} >> {DocTarget}DOC
#-----------------------------------------------#
--- /dev/null
+#!/bin/sh
+
+#### osx-install: create the file ~/.MacOSX/environment.plist with
+#### appropriate paths for Emacs to access lisp and bin directories.
+#### On Mac OS X, this file contains values for environment variables
+#### seen by Aqua application launched in the Finder. This script
+#### must be run at the top level of a Mac OS X binary distribution.
+
+# Copyright (C) 2002 Free Software Foundation, Inc.
+#
+# This file is part of GNU Emacs.
+#
+# GNU Emacs is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+progname="$0"
+
+### Exit if a command fails.
+#set -e
+
+### Print out each line we read, for debugging's sake.
+set -v
+
+LANGUAGE=C
+LC_ALL=C
+LC_MESSAGES=
+LANG=
+export LANGUAGE LC_ALL LC_MESSAGES LANG
+
+## Don't restrict access to any files.
+umask 0
+
+### Make sure we're running in the right place.
+if [ ! -d Emacs.app -o ! -d libexec -o ! -d share ]; then
+ echo "${progname} must be run in the top directory of the Emacs" >&2
+ echo "binary distribution tree for Mac OS. cd to that directory" >&2
+ echo "and try again." >&2
+ exit 1
+fi
+
+versionfile=`ls share/emacs/21.*/lisp/version.el`
+
+### Find out which version of Emacs this is.
+shortversion=`grep 'defconst[ ]*emacs-version' ${versionfile} \
+ | sed -e 's/^.*"\([0-9][0-9]*\.[0-9][0-9]*\).*$/\1/'`
+version=`grep 'defconst[ ]*emacs-version' ${versionfile} \
+ | sed -e 's/^[^"]*"\([^"]*\)".*$/\1/'`
+if [ ! "${version}" ]; then
+ echo "${progname}: can't find current Emacs version in \`./lisp/version.el'" >&2
+ exit 1
+fi
+
+echo Version numbers are $version and $shortversion
+
+homedir=`ls -d ~`
+initfile="${homedir}/.MacOSX/environment.plist"
+
+if [ -f ${initfile} ]; then
+ mv ${initfile} ${initfile}.old
+fi
+
+if [ -d ${homedir}/.MacOSX ]; then
+ mkdir ${homedir}/.MacOSX
+fi
+
+execpath=`ls -d libexec/emacs/21.*/powerpc-apple-*/`
+
+echo '<?xml version="1.0" encoding="UTF-8"?>' > ${initfile}
+echo '<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">' >> ${initfile}
+echo '<plist version="0.9">' >> ${initfile}
+echo '<dict>' >> ${initfile}
+echo ' <key>EMACSLOADPATH</key>' >> ${initfile}
+echo " <string>`pwd`/share/emacs/${version}/lisp/</string>" >> ${initfile}
+echo ' <key>EMACSPATH</key>' >> ${initfile}
+echo " <string>`pwd`/${execpath}:`pwd`/bin/</string>" >> ${initfile}
+echo ' <key>EMACSDATA</key>' >> ${initfile}
+echo " <string>`pwd`/share/emacs/${version}/etc/</string>" >> ${initfile}
+echo ' <key>EMACSDOC</key>' >> ${initfile}
+echo " <string>`pwd`/share/emacs/${version}/etc/</string>" >> ${initfile}
+echo ' <key>INFOPATH</key>' >> ${initfile}
+echo " <string>`pwd`/info/</string>" >> ${initfile}
+echo '</dict>' >> ${initfile}
+echo '</plist>' >> ${initfile}
+
+### osx-install ends here
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Contributed by Andrew Choi (akochoi@users.sourceforge.net). */
+/* Contributed by Andrew Choi (akochoi@mac.com). */
+#ifndef TARGET_API_MAC_CARBON
#include "Types.r"
/* added for finder icon balloon help --ben */
#include "Balloons.r"
+#endif
/* Define to use gnu icon */
/* #define GNU_ICON 1 */
}
};
+#ifndef TARGET_API_MAC_CARBON
/* added for finder icon balloon help --ben */
resource 'STR ' (128) { /*help message for emacs icon*/
"GNU Emacs\0xd1the extensible, customizable, self-documenting real-time display editor."
};
+#endif
resource 'MENU' (128, preload) {
128,
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Contributed by Andrew Choi (akochoi@users.sourceforge.net). */
+/* Contributed by Andrew Choi (akochoi@mac.com). */
#include "Types.r"
#include "CodeFragmentTypes.r"
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* Contributed by Andrew Choi (akochoi@users.sourceforge.net). */
+/* Contributed by Andrew Choi (akochoi@mac.com). */
#include <string.h>
#include <Files.h>
+++ /dev/null
-/* Unix emulation routines for GNU Emacs on the Mac OS.
- Copyright (C) 2000 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Contributed by Andrew Choi (akochoi@users.sourceforge.net). */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <errno.h>
-#include <utime.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <string.h>
-#include <pwd.h>
-#include <sys/param.h>
-#if __MWERKS__
-#include <unistd.h>
-#endif
-
-#include <Files.h>
-#include <MacTypes.h>
-#include <TextUtils.h>
-#include <Folders.h>
-#include <Resources.h>
-#include <Aliases.h>
-#include <FixMath.h>
-#include <Timer.h>
-#include <OSA.h>
-#include <AppleScript.h>
-
-#include "lisp.h"
-#include "process.h"
-#include "sysselect.h"
-#include "systime.h"
-
-Lisp_Object QCLIPBOARD;
-
-/* An instance of the AppleScript component. */
-static ComponentInstance as_scripting_component;
-/* The single script context used for all script executions. */
-static OSAID as_script_context;
-
-
-/* When converting from Mac to Unix pathnames, /'s in folder names are
- converted to :'s. This function, used in copying folder names,
- performs a strncat and converts all character a to b in the copy of
- the string s2 appended to the end of s1. */
-
-void
-string_cat_and_replace (char *s1, const char *s2, int n, char a, char b)
-{
- int l1 = strlen (s1);
- int l2 = strlen (s2);
- char *p = s1 + l1;
- int i;
-
- strncat (s1, s2, n);
- for (i = 0; i < l2; i++)
- {
- if (*p == a)
- *p = b;
- p++;
- }
-}
-
-
-/* Convert a Mac pathname to Unix form. A Mac full pathname is one
- that does not begin with a ':' and contains at least one ':'. A Mac
- full pathname causes an '/' to be prepended to the Unix pathname.
- The algorithm for the rest of the pathname is as follows:
- For each segment between two ':',
- if it is non-null, copy as is and then add a '/' at the end,
- otherwise, insert a "../" into the Unix pathname.
- Returns 1 if successful; 0 if fails. */
-
-int
-mac_to_posix_pathname (const char *mfn, char *ufn, int ufnbuflen)
-{
- const char *p, *q, *pe;
-
- strcpy (ufn, "");
-
- if (*mfn == '\0')
- return 1;
-
- p = strchr (mfn, ':');
- if (p != 0 && p != mfn) /* full pathname */
- strcat (ufn, "/");
-
- p = mfn;
- if (*p == ':')
- p++;
-
- pe = mfn + strlen (mfn);
- while (p < pe)
- {
- q = strchr (p, ':');
- if (q)
- {
- if (q == p)
- { /* two consecutive ':' */
- if (strlen (ufn) + 3 >= ufnbuflen)
- return 0;
- strcat (ufn, "../");
- }
- else
- {
- if (strlen (ufn) + (q - p) + 1 >= ufnbuflen)
- return 0;
- string_cat_and_replace (ufn, p, q - p, '/', ':');
- strcat (ufn, "/");
- }
- p = q + 1;
- }
- else
- {
- if (strlen (ufn) + (pe - p) >= ufnbuflen)
- return 0;
- string_cat_and_replace (ufn, p, pe - p, '/', ':');
- /* no separator for last one */
- p = pe;
- }
- }
-
- return 1;
-}
-
-
-extern char *get_temp_dir_name ();
-
-
-/* Convert a Unix pathname to Mac form. Approximately reverse of the
- above in algorithm. */
-
-int
-posix_to_mac_pathname (const char *ufn, char *mfn, int mfnbuflen)
-{
- const char *p, *q, *pe;
- char expanded_pathname[MAXPATHLEN+1];
-
- strcpy (mfn, "");
-
- if (*ufn == '\0')
- return 1;
-
- p = ufn;
-
- /* Check for and handle volume names. Last comparison: strangely
- somewhere "/.emacs" is passed. A temporary fix for now. */
- if (*p == '/' && strchr (p+1, '/') == NULL && strcmp (p, "/.emacs") != 0)
- {
- if (strlen (p) + 1 > mfnbuflen)
- return 0;
- strcpy (mfn, p+1);
- strcat (mfn, ":");
- return 1;
- }
-
- /* expand to emacs dir found by init_emacs_passwd_dir */
- if (strncmp (p, "~emacs/", 7) == 0)
- {
- struct passwd *pw = getpwnam ("emacs");
- p += 7;
- if (strlen (pw->pw_dir) + strlen (p) > MAXPATHLEN)
- return 0;
- strcpy (expanded_pathname, pw->pw_dir);
- strcat (expanded_pathname, p);
- p = expanded_pathname;
- /* now p points to the pathname with emacs dir prefix */
- }
- else if (strncmp (p, "/tmp/", 5) == 0)
- {
- char *t = get_temp_dir_name ();
- p += 5;
- if (strlen (t) + strlen (p) > MAXPATHLEN)
- return 0;
- strcpy (expanded_pathname, t);
- strcat (expanded_pathname, p);
- p = expanded_pathname;
- /* now p points to the pathname with emacs dir prefix */
- }
- else if (*p != '/') /* relative pathname */
- strcat (mfn, ":");
-
- if (*p == '/')
- p++;
-
- pe = p + strlen (p);
- while (p < pe)
- {
- q = strchr (p, '/');
- if (q)
- {
- if (q - p == 2 && *p == '.' && *(p+1) == '.')
- {
- if (strlen (mfn) + 1 >= mfnbuflen)
- return 0;
- strcat (mfn, ":");
- }
- else
- {
- if (strlen (mfn) + (q - p) + 1 >= mfnbuflen)
- return 0;
- string_cat_and_replace (mfn, p, q - p, ':', '/');
- strcat (mfn, ":");
- }
- p = q + 1;
- }
- else
- {
- if (strlen (mfn) + (pe - p) >= mfnbuflen)
- return 0;
- string_cat_and_replace (mfn, p, pe - p, ':', '/');
- p = pe;
- }
- }
-
- return 1;
-}
-
-
-/* The following functions with "sys_" prefix are stubs to Unix
- functions that have already been implemented by CW or MPW. The
- calls to them in Emacs source course are #define'd to call the sys_
- versions by the header files s-mac.h. In these stubs pathnames are
- converted between their Unix and Mac forms. */
-
-
-/* Unix epoch is Jan 1, 1970 while Mac epoch is Jan 1, 1904: 66 years
- + 17 leap days. These are for adjusting time values returned by
- MacOS Toolbox functions. */
-
-#define MAC_UNIX_EPOCH_DIFF ((365L * 66 + 17) * 24 * 60 * 60)
-
-#ifdef __MWERKS__
-#ifndef CODEWARRIOR_VERSION_6
-/* CW Pro 5 epoch is Jan 1, 1900 (aaarghhhhh!); remember, 1900 is not
- a leap year! This is for adjusting time_t values returned by MSL
- functions. */
-#define CW_OR_MPW_UNIX_EPOCH_DIFF ((365L * 70 + 17) * 24 * 60 * 60)
-#else
-/* CW changes Pro 6 to following Unix! */
-#define CW_OR_MPW_UNIX_EPOCH_DIFF ((365L * 66 + 17) * 24 * 60 * 60)
-#endif
-#elif __MRC__
-/* MPW library functions follow Unix (confused?). */
-#define CW_OR_MPW_UNIX_EPOCH_DIFF ((365L * 66 + 17) * 24 * 60 * 60)
-#else
-You lose!!!
-#endif
-
-
-/* Define our own stat function for both MrC and CW. The reason for
- doing this: "stat" is both the name of a struct and function name:
- can't use the same trick like that for sys_open, sys_close, etc. to
- redirect Emacs's calls to our own version that converts Unix style
- filenames to Mac style filename because all sorts of compilation
- errors will be generated if stat is #define'd to be sys_stat. */
-
-int
-stat_noalias (const char *path, struct stat *buf)
-{
- char mac_pathname[MAXPATHLEN+1];
- CInfoPBRec cipb;
-
- if (posix_to_mac_pathname (path, mac_pathname, MAXPATHLEN+1) == 0)
- return -1;
-
- c2pstr (mac_pathname);
- cipb.hFileInfo.ioNamePtr = mac_pathname;
- cipb.hFileInfo.ioVRefNum = 0;
- cipb.hFileInfo.ioDirID = 0;
- cipb.hFileInfo.ioFDirIndex = 0;
- /* set to 0 to get information about specific dir or file */
-
- errno = PBGetCatInfo (&cipb, false);
- if (errno == -43) /* -43: fnfErr defined in Errors.h */
- errno = ENOENT;
- if (errno != noErr)
- return -1;
-
- if (cipb.hFileInfo.ioFlAttrib & 0x10) /* bit 4 = 1 for directories */
- {
- buf->st_mode = S_IFDIR | S_IREAD | S_IEXEC;
-
- if (!(cipb.hFileInfo.ioFlAttrib & 0x1))
- buf->st_mode |= S_IWRITE; /* bit 1 = 1 for locked files/directories */
- buf->st_ino = cipb.dirInfo.ioDrDirID;
- buf->st_dev = cipb.dirInfo.ioVRefNum;
- buf->st_size = cipb.dirInfo.ioDrNmFls;
- /* size of dir = number of files and dirs */
- buf->st_atime
- = buf->st_mtime
- = cipb.dirInfo.ioDrMdDat - MAC_UNIX_EPOCH_DIFF;
- buf->st_ctime = cipb.dirInfo.ioDrCrDat - MAC_UNIX_EPOCH_DIFF;
- }
- else
- {
- buf->st_mode = S_IFREG | S_IREAD;
- if (!(cipb.hFileInfo.ioFlAttrib & 0x1))
- buf->st_mode |= S_IWRITE; /* bit 1 = 1 for locked files/directories */
- if (cipb.hFileInfo.ioFlFndrInfo.fdType == 'APPL')
- buf->st_mode |= S_IEXEC;
- buf->st_ino = cipb.hFileInfo.ioDirID;
- buf->st_dev = cipb.hFileInfo.ioVRefNum;
- buf->st_size = cipb.hFileInfo.ioFlLgLen;
- buf->st_atime
- = buf->st_mtime
- = cipb.hFileInfo.ioFlMdDat - MAC_UNIX_EPOCH_DIFF;
- buf->st_ctime = cipb.hFileInfo.ioFlCrDat - MAC_UNIX_EPOCH_DIFF;
- }
-
- if (cipb.hFileInfo.ioFlFndrInfo.fdFlags & 0x8000)
- {
- /* identify alias files as symlinks */
- buf->st_mode &= ~S_IFREG;
- buf->st_mode |= S_IFLNK;
- }
-
- buf->st_nlink = 1;
- buf->st_uid = getuid ();
- buf->st_gid = getgid ();
- buf->st_rdev = 0;
-
- return 0;
-}
-
-
-int
-lstat (const char *path, struct stat *buf)
-{
- int result;
- char true_pathname[MAXPATHLEN+1];
-
- /* Try looking for the file without resolving aliases first. */
- if ((result = stat_noalias (path, buf)) >= 0)
- return result;
-
- if (find_true_pathname (path, true_pathname, MAXPATHLEN+1) == -1)
- return -1;
-
- return stat_noalias (true_pathname, buf);
-}
-
-
-int
-stat (const char *path, struct stat *sb)
-{
- int result;
- char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];
- int len;
-
- if ((result = stat_noalias (path, sb)) >= 0 &&
- ! (sb->st_mode & S_IFLNK))
- return result;
-
- if (find_true_pathname (path, true_pathname, MAXPATHLEN+1) == -1)
- return -1;
-
- len = readlink (true_pathname, fully_resolved_name, MAXPATHLEN);
- if (len > -1)
- {
- fully_resolved_name[len] = '\0';
- /* in fact our readlink terminates strings */
- return lstat (fully_resolved_name, sb);
- }
- else
- return lstat (true_pathname, sb);
-}
-
-
-#if __MRC__
-/* CW defines fstat in stat.mac.c while MPW does not provide this
- function. Without the information of how to get from a file
- descriptor in MPW StdCLib to a Mac OS file spec, it should be hard
- to implement this function. Fortunately, there is only one place
- where this function is called in our configuration: in fileio.c,
- where only the st_dev and st_ino fields are used to determine
- whether two fildes point to different i-nodes to prevent copying
- a file onto itself equal. What we have here probably needs
- improvement. */
-
-int
-fstat (int fildes, struct stat *buf)
-{
- buf->st_dev = 0;
- buf->st_ino = fildes;
- buf->st_mode = S_IFREG; /* added by T.I. for the copy-file */
- return 0; /* success */
-}
-#endif /* __MRC__ */
-
-
-/* Adapted from Think Reference code example. */
-
-int
-mkdir (const char *dirname, int mode)
-{
-#pragma unused(mode)
-
- HFileParam hfpb;
- char true_pathname[MAXPATHLEN+1], mac_pathname[MAXPATHLEN+1];
-
- if (find_true_pathname (dirname, true_pathname, MAXPATHLEN+1) == -1)
- return -1;
-
- if (posix_to_mac_pathname (true_pathname, mac_pathname, MAXPATHLEN+1) == 0)
- return -1;
-
- c2pstr (mac_pathname);
- hfpb.ioNamePtr = mac_pathname;
- hfpb.ioVRefNum = 0; /* ignored unless name is invalid */
- hfpb.ioDirID = 0; /* parent is the root */
-
- errno = PBDirCreate ((HParmBlkPtr) &hfpb, false);
- /* just return the Mac OSErr code for now */
- return errno == noErr ? 0 : -1;
-}
-
-
-#undef rmdir
-sys_rmdir (const char *dirname)
-{
- HFileParam hfpb;
- char mac_pathname[MAXPATHLEN+1];
-
- if (posix_to_mac_pathname (dirname, mac_pathname, MAXPATHLEN+1) == 0)
- return -1;
-
- c2pstr (mac_pathname);
- hfpb.ioNamePtr = mac_pathname;
- hfpb.ioVRefNum = 0; /* ignored unless name is invalid */
- hfpb.ioDirID = 0; /* parent is the root */
-
- errno = PBHDelete ((HParmBlkPtr) &hfpb, false);
- return errno == noErr ? 0 : -1;
-}
-
-
-#ifdef __MRC__
-/* No implementation yet. */
-int
-execvp (const char *path, ...)
-{
- return -1;
-}
-#endif /* __MRC__ */
-
-
-int
-utime (const char *path, const struct utimbuf *times)
-{
- char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];
- int len;
- char mac_pathname[MAXPATHLEN+1];
- CInfoPBRec cipb;
-
- if (find_true_pathname (path, true_pathname, MAXPATHLEN+1) == -1)
- return -1;
-
- len = readlink (true_pathname, fully_resolved_name, MAXPATHLEN);
- if (len > -1)
- fully_resolved_name[len] = '\0';
- else
- strcpy (fully_resolved_name, true_pathname);
-
- if (!posix_to_mac_pathname (fully_resolved_name, mac_pathname, MAXPATHLEN+1))
- return -1;
-
- c2pstr (mac_pathname);
- cipb.hFileInfo.ioNamePtr = mac_pathname;
- cipb.hFileInfo.ioVRefNum = 0;
- cipb.hFileInfo.ioDirID = 0;
- cipb.hFileInfo.ioFDirIndex = 0;
- /* set to 0 to get information about specific dir or file */
-
- errno = PBGetCatInfo (&cipb, false);
- if (errno != noErr)
- return -1;
-
- if (cipb.hFileInfo.ioFlAttrib & 0x10) /* bit 4 = 1 for directories */
- {
- if (times)
- cipb.dirInfo.ioDrMdDat = times->modtime + MAC_UNIX_EPOCH_DIFF;
- else
- GetDateTime (&cipb.dirInfo.ioDrMdDat);
- }
- else
- {
- if (times)
- cipb.hFileInfo.ioFlMdDat = times->modtime + MAC_UNIX_EPOCH_DIFF;
- else
- GetDateTime (&cipb.hFileInfo.ioFlMdDat);
- }
-
- errno = PBSetCatInfo (&cipb, false);
- return errno == noErr ? 0 : -1;
-}
-
-
-#ifndef F_OK
-#define F_OK 0
-#endif
-#ifndef X_OK
-#define X_OK 1
-#endif
-#ifndef W_OK
-#define W_OK 2
-#endif
-
-/* Like stat, but test for access mode in hfpb.ioFlAttrib */
-int
-access (const char *path, int mode)
-{
- char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];
- int len;
- char mac_pathname[MAXPATHLEN+1];
- CInfoPBRec cipb;
-
- if (find_true_pathname (path, true_pathname, MAXPATHLEN+1) == -1)
- return -1;
-
- len = readlink (true_pathname, fully_resolved_name, MAXPATHLEN);
- if (len > -1)
- fully_resolved_name[len] = '\0';
- else
- strcpy (fully_resolved_name, true_pathname);
-
- if (!posix_to_mac_pathname (fully_resolved_name, mac_pathname, MAXPATHLEN+1))
- return -1;
-
- c2pstr (mac_pathname);
- cipb.hFileInfo.ioNamePtr = mac_pathname;
- cipb.hFileInfo.ioVRefNum = 0;
- cipb.hFileInfo.ioDirID = 0;
- cipb.hFileInfo.ioFDirIndex = 0;
- /* set to 0 to get information about specific dir or file */
-
- errno = PBGetCatInfo (&cipb, false);
- if (errno != noErr)
- return -1;
-
- if (mode == F_OK) /* got this far, file exists */
- return 0;
-
- if (mode & X_OK)
- if (cipb.hFileInfo.ioFlAttrib & 0x10) /* path refers to a directory */
- return 0;
- else
- {
- if (cipb.hFileInfo.ioFlFndrInfo.fdType == 'APPL')
- return 0;
- else
- return -1;
- }
-
- if (mode & W_OK)
- return (cipb.hFileInfo.ioFlAttrib & 0x1) ? -1 : 0;
- /* don't allow if lock bit is on */
-
- return -1;
-}
-
-
-#define DEV_NULL_FD 0x10000
-
-#undef open
-int
-sys_open (const char *path, int oflag)
-{
- char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];
- int len;
- char mac_pathname[MAXPATHLEN+1];
-
- if (strcmp (path, "/dev/null") == 0)
- return DEV_NULL_FD; /* some bogus fd to be ignored in write */
-
- if (find_true_pathname (path, true_pathname, MAXPATHLEN+1) == -1)
- return -1;
-
- len = readlink (true_pathname, fully_resolved_name, MAXPATHLEN);
- if (len > -1)
- fully_resolved_name[len] = '\0';
- else
- strcpy (fully_resolved_name, true_pathname);
-
- if (!posix_to_mac_pathname (fully_resolved_name, mac_pathname, MAXPATHLEN+1))
- return -1;
- else
- {
-#ifdef __MRC__
- int res = open (mac_pathname, oflag);
- /* if (oflag == O_WRONLY || oflag == O_RDWR) */
- if (oflag & O_CREAT)
- fsetfileinfo (mac_pathname, 'EMAx', 'TEXT');
- return res;
-#else
- return open (mac_pathname, oflag);
-#endif
- }
-}
-
-
-#undef creat
-int
-sys_creat (const char *path, mode_t mode)
-{
- char true_pathname[MAXPATHLEN+1];
- int len;
- char mac_pathname[MAXPATHLEN+1];
-
- if (find_true_pathname (path, true_pathname, MAXPATHLEN+1) == -1)
- return -1;
-
- if (!posix_to_mac_pathname (true_pathname, mac_pathname, MAXPATHLEN+1))
- return -1;
- else
- {
-#ifdef __MRC__
- int result = creat (mac_pathname);
- fsetfileinfo (mac_pathname, 'EMAx', 'TEXT');
- return result;
-#else
- return creat (mac_pathname, mode);
-#endif
- }
-}
-
-
-#undef unlink
-int
-sys_unlink (const char *path)
-{
- char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];
- int len;
- char mac_pathname[MAXPATHLEN+1];
-
- if (find_true_pathname (path, true_pathname, MAXPATHLEN+1) == -1)
- return -1;
-
- len = readlink (true_pathname, fully_resolved_name, MAXPATHLEN);
- if (len > -1)
- fully_resolved_name[len] = '\0';
- else
- strcpy (fully_resolved_name, true_pathname);
-
- if (!posix_to_mac_pathname (fully_resolved_name, mac_pathname, MAXPATHLEN+1))
- return -1;
- else
- return unlink (mac_pathname);
-}
-
-
-#undef read
-int
-sys_read (int fildes, char *buf, int count)
-{
- if (fildes == 0) /* this should not be used for console input */
- return -1;
- else
-#ifdef CODEWARRIOR_VERSION_6
- return _read (fildes, buf, count);
-#else
- return read (fildes, buf, count);
-#endif
-}
-
-
-#undef write
-int
-sys_write (int fildes, const char *buf, int count)
-{
- if (fildes == DEV_NULL_FD)
- return count;
- else
-#ifdef CODEWARRIOR_VERSION_6
- return _write (fildes, buf, count);
-#else
- return write (fildes, buf, count);
-#endif
-}
-
-
-#undef rename
-int
-sys_rename (const char * old_name, const char * new_name)
-{
- char true_old_pathname[MAXPATHLEN+1], true_new_pathname[MAXPATHLEN+1];
- char fully_resolved_old_name[MAXPATHLEN+1];
- int len;
- char mac_old_name[MAXPATHLEN+1], mac_new_name[MAXPATHLEN+1];
-
- if (find_true_pathname (old_name, true_old_pathname, MAXPATHLEN+1) == -1)
- return -1;
-
- len = readlink (true_old_pathname, fully_resolved_old_name, MAXPATHLEN);
- if (len > -1)
- fully_resolved_old_name[len] = '\0';
- else
- strcpy (fully_resolved_old_name, true_old_pathname);
-
- if (find_true_pathname (new_name, true_new_pathname, MAXPATHLEN+1) == -1)
- return -1;
-
- if (strcmp (fully_resolved_old_name, true_new_pathname) == 0)
- return 0;
-
- if (!posix_to_mac_pathname (fully_resolved_old_name,
- mac_old_name,
- MAXPATHLEN+1))
- return -1;
-
- if (!posix_to_mac_pathname(true_new_pathname, mac_new_name, MAXPATHLEN+1))
- return -1;
-
- /* If a file with new_name already exists, rename deletes the old
- file in Unix. CW version fails in these situation. So we add a
- call to unlink here. */
- (void) unlink (mac_new_name);
-
- return rename (mac_old_name, mac_new_name);
-}
-
-
-#undef fopen
-extern FILE *fopen (const char *name, const char *mode);
-FILE *
-sys_fopen (const char *name, const char *mode)
-{
- char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];
- int len;
- char mac_pathname[MAXPATHLEN+1];
-
- if (find_true_pathname (name, true_pathname, MAXPATHLEN+1) == -1)
- return 0;
-
- len = readlink (true_pathname, fully_resolved_name, MAXPATHLEN);
- if (len > -1)
- fully_resolved_name[len] = '\0';
- else
- strcpy (fully_resolved_name, true_pathname);
-
- if (!posix_to_mac_pathname (fully_resolved_name, mac_pathname, MAXPATHLEN+1))
- return 0;
- else
- {
-#ifdef __MRC__
- if (mode[0] == 'w' || mode[0] == 'a')
- fsetfileinfo (mac_pathname, 'EMAx', 'TEXT');
-#endif
- return fopen (mac_pathname, mode);
- }
-}
-
-
-#include <Events.h>
-
-long target_ticks = 0;
-
-#ifdef __MRC__
-__sigfun alarm_signal_func = (__sigfun) 0;
-#elif __MWERKS__
-__signal_func_ptr alarm_signal_func = (__signal_func_ptr) 0;
-#else
-You lose!!!
-#endif
-
-
-/* These functions simulate SIG_ALRM. The stub for function signal
- stores the signal handler function in alarm_signal_func if a
- SIG_ALRM is encountered. check_alarm is called in XTread_socket,
- which emacs calls periodically. A pending alarm is represented by
- a non-zero target_ticks value. check_alarm calls the handler
- function pointed to by alarm_signal_func if one has been set up and
- an alarm is pending. */
-
-void
-check_alarm ()
-{
- if (target_ticks && TickCount () > target_ticks)
- {
- target_ticks = 0;
- if (alarm_signal_func)
- (*alarm_signal_func)(SIGALRM);
- }
-}
-
-
-int
-select(n, rfds, wfds, efds, timeout)
- int n;
- SELECT_TYPE *rfds;
- SELECT_TYPE *wfds;
- SELECT_TYPE *efds;
- struct timeval *timeout;
-{
- EMACS_TIME end_time, now;
- EventRecord e;
-
- /* Can only handle wait for keyboard input. */
- if (n > 1 || wfds || efds)
- return -1;
-
- EMACS_GET_TIME (end_time);
- EMACS_ADD_TIME (end_time, end_time, *timeout);
-
- do
- {
- /* Also return true if an event other than a keyDown has
- occurred. This causes kbd_buffer_get_event in keyboard.c to
- call read_avail_input which in turn calls XTread_socket to
- poll for these events. Otherwise these never get processed
- except but a very slow poll timer. */
- if (FD_ISSET (0, rfds) && EventAvail (everyEvent, &e))
- return 1;
-
- /* Also check movement of the mouse. */
- {
- Point mouse_pos;
- static Point old_mouse_pos = {-1, -1};
-
- GetMouse (&mouse_pos);
- if (!EqualPt (mouse_pos, old_mouse_pos))
- {
- old_mouse_pos = mouse_pos;
- return 1;
- }
- }
-
- WaitNextEvent (0, &e, 1UL, NULL); /* Accept no event; wait 1 tic. by T.I.*/
-
- EMACS_GET_TIME (now);
- EMACS_SUB_TIME (now, end_time, now);
- }
- while (!EMACS_TIME_NEG_P (now));
-
- return 0;
-}
-
-
-/* Called in sys_select to wait for an alarm signal to arrive. */
-
-int
-pause ()
-{
- EventRecord e;
- unsigned long tick;
-
- if (!target_ticks) /* no alarm pending */
- return -1;
-
- if ( (tick = TickCount ()) < target_ticks )
- WaitNextEvent (0, &e, target_ticks - tick, NULL); /* Accept no event; just wait. by T.I.*/
-
- target_ticks = 0;
- if (alarm_signal_func)
- (*alarm_signal_func)(SIGALRM);
-
- return 0;
-}
-
-
-int
-alarm (int seconds)
-{
- long remaining = target_ticks ? (TickCount () - target_ticks) / 60 : 0;
-
- target_ticks = seconds ? TickCount () + 60 * seconds : 0;
-
- return (remaining < 0) ? 0 : (unsigned int) remaining;
-}
-
-
-#undef signal
-#ifdef __MRC__
-extern __sigfun signal (int signal, __sigfun signal_func);
-__sigfun
-sys_signal (int signal_num, __sigfun signal_func)
-#elif __MWERKS__
-extern __signal_func_ptr signal (int signal, __signal_func_ptr signal_func);
-__signal_func_ptr
-sys_signal (int signal_num, __signal_func_ptr signal_func)
-#else
- You lose!!!
-#endif
-{
- if (signal_num != SIGALRM)
- return signal (signal_num, signal_func);
- else
- {
-#ifdef __MRC__
- __sigfun old_signal_func;
-#elif __MWERKS__
- __signal_func_ptr old_signal_func;
-#else
- You lose!!!
-#endif
- old_signal_func = alarm_signal_func;
- alarm_signal_func = signal_func;
- return old_signal_func;
- }
-}
-
-
-/* gettimeofday should return the amount of time (in a timeval
- structure) since midnight today. The toolbox function Microseconds
- returns the number of microseconds (in a UnsignedWide value) since
- the machine was booted. Also making this complicated is WideAdd,
- WideSubtract, etc. take wide values. */
-
-int
-gettimeofday (tp)
- struct timeval *tp;
-{
- static inited = 0;
- static wide wall_clock_at_epoch, clicks_at_epoch;
- UnsignedWide uw_microseconds;
- wide w_microseconds;
- time_t sys_time (time_t *);
-
- /* If this function is called for the first time, record the number
- of seconds since midnight and the number of microseconds since
- boot at the time of this first call. */
- if (!inited)
- {
- time_t systime;
- inited = 1;
- systime = sys_time (NULL);
- /* Store microseconds since midnight in wall_clock_at_epoch. */
- WideMultiply (systime, 1000000L, &wall_clock_at_epoch);
- Microseconds (&uw_microseconds);
- /* Store microseconds since boot in clicks_at_epoch. */
- clicks_at_epoch.hi = uw_microseconds.hi;
- clicks_at_epoch.lo = uw_microseconds.lo;
- }
-
- /* Get time since boot */
- Microseconds (&uw_microseconds);
-
- /* Convert to time since midnight*/
- w_microseconds.hi = uw_microseconds.hi;
- w_microseconds.lo = uw_microseconds.lo;
- WideSubtract (&w_microseconds, &clicks_at_epoch);
- WideAdd (&w_microseconds, &wall_clock_at_epoch);
- tp->tv_sec = WideDivide (&w_microseconds, 1000000L, &tp->tv_usec);
-
- return 0;
-}
-
-
-#ifdef __MRC__
-unsigned int
-sleep (unsigned int seconds)
-{
- unsigned long time_up;
- EventRecord e;
-
- time_up = TickCount () + seconds * 60;
- while (TickCount () < time_up)
- {
- /* Accept no event; just wait. by T.I. */
- WaitNextEvent (0, &e, 30, NULL);
- }
-
- return (0);
-}
-#endif /* __MRC__ */
-
-
-/* The time functions adjust time values according to the difference
- between the Unix and CW epoches. */
-
-#undef gmtime
-extern struct tm *gmtime (const time_t *);
-struct tm *
-sys_gmtime (const time_t *timer)
-{
- time_t unix_time = *timer + CW_OR_MPW_UNIX_EPOCH_DIFF;
-
- return gmtime (&unix_time);
-}
-
-
-#undef localtime
-extern struct tm *localtime (const time_t *);
-struct tm *
-sys_localtime (const time_t *timer)
-{
-#ifdef CODEWARRIOR_VERSION_6
- time_t unix_time = *timer;
-#else
- time_t unix_time = *timer + CW_OR_MPW_UNIX_EPOCH_DIFF;
-#endif
-
- return localtime (&unix_time);
-}
-
-
-#undef ctime
-extern char *ctime (const time_t *);
-char *
-sys_ctime (const time_t *timer)
-{
-#ifdef CODEWARRIOR_VERSION_6
- time_t unix_time = *timer;
-#else
- time_t unix_time = *timer + CW_OR_MPW_UNIX_EPOCH_DIFF;
-#endif
-
- return ctime (&unix_time);
-}
-
-
-#undef time
-extern time_t time (time_t *);
-time_t
-sys_time (time_t *timer)
-{
-#ifdef CODEWARRIOR_VERSION_6
- time_t mac_time = time (NULL);
-#else
- time_t mac_time = time (NULL) - CW_OR_MPW_UNIX_EPOCH_DIFF;
-#endif
-
- if (timer)
- *timer = mac_time;
-
- return mac_time;
-}
-
-
-/* MPW strftime broken for "%p" format */
-#ifdef __MRC__
-#undef strftime
-#include <time.h>
-size_t
-sys_strftime (char * s, size_t maxsize, const char * format,
- const struct tm * timeptr)
-{
- if (strcmp (format, "%p") == 0)
- {
- if (maxsize < 3)
- return 0;
- if (timeptr->tm_hour < 12)
- {
- strcpy (s, "AM");
- return 2;
- }
- else
- {
- strcpy (s, "PM");
- return 2;
- }
- }
- else
- return strftime (s, maxsize, format, timeptr);
-}
-#endif /* __MRC__ */
-
-
-/* no subprocesses, empty wait */
-
-int
-wait (int pid)
-{
- return 0;
-}
-
-
-void
-croak (char *badfunc)
-{
- printf ("%s not yet implemented\r\n", badfunc);
- exit (1);
-}
-
-
-char *
-index (const char * str, int chr)
-{
- return strchr (str, chr);
-}
-
-
-char *
-mktemp (char *template)
-{
- int len, k;
- static seqnum = 0;
-
- len = strlen (template);
- k = len - 1;
- while (k >= 0 && template[k] == 'X')
- k--;
-
- k++; /* make k index of first 'X' */
-
- if (k < len)
- {
- /* Zero filled, number of digits equal to the number of X's. */
- sprintf (&template[k], "%0*d", len-k, seqnum++);
-
- return template;
- }
- else
- return 0;
-}
-
-
-/* Emulate getpwuid, getpwnam and others. */
-
-#define PASSWD_FIELD_SIZE 256
-
-static char my_passwd_name[PASSWD_FIELD_SIZE];
-static char my_passwd_dir[MAXPATHLEN+1];
-
-static struct passwd my_passwd =
-{
- my_passwd_name,
- my_passwd_dir,
-};
-
-
-/* Initialized by main () in macterm.c to pathname of emacs directory. */
-
-char emacs_passwd_dir[MAXPATHLEN+1];
-
-char *
-getwd (char *);
-
-void
-init_emacs_passwd_dir ()
-{
- int found = false;
-
- if (getwd (emacs_passwd_dir) && getwd (my_passwd_dir))
- {
- /* Need pathname of first ancestor that begins with "emacs"
- since Mac emacs application is somewhere in the emacs-*
- tree. */
- int len = strlen (emacs_passwd_dir);
- int j = len - 1;
- /* j points to the "/" following the directory name being
- compared. */
- int i = j - 1;
- while (i >= 0 && !found)
- {
- while (i >= 0 && emacs_passwd_dir[i] != '/')
- i--;
- if (emacs_passwd_dir[i] == '/' && i+5 < len)
- found = (strncmp (&(emacs_passwd_dir[i+1]), "emacs", 5) == 0);
- if (found)
- emacs_passwd_dir[j+1] = '\0';
- else
- {
- j = i;
- i = j - 1;
- }
- }
- }
-
- if (!found)
- {
- /* Setting to "/" probably won't work but set it to something
- anyway. */
- strcpy (emacs_passwd_dir, "/");
- strcpy (my_passwd_dir, "/");
- }
-}
-
-
-static struct passwd emacs_passwd =
-{
- "emacs",
- emacs_passwd_dir,
-};
-
-static int my_passwd_inited = 0;
-
-
-static void
-init_my_passwd ()
-{
- char **owner_name;
-
- /* Note: my_passwd_dir initialized in int_emacs_passwd_dir to
- directory where Emacs was started. */
-
- owner_name = (char **) GetResource ('STR ',-16096);
- if (owner_name)
- {
- HLock (owner_name);
- BlockMove ((unsigned char *) *owner_name,
- (unsigned char *) my_passwd_name,
- *owner_name[0]+1);
- HUnlock (owner_name);
- p2cstr ((unsigned char *) my_passwd_name);
- }
- else
- my_passwd_name[0] = 0;
-}
-
-
-struct passwd *
-getpwuid (uid_t uid)
-{
- if (!my_passwd_inited)
- {
- init_my_passwd ();
- my_passwd_inited = 1;
- }
-
- return &my_passwd;
-}
-
-
-struct passwd *
-getpwnam (const char *name)
-{
- if (strcmp (name, "emacs") == 0)
- return &emacs_passwd;
-
- if (!my_passwd_inited)
- {
- init_my_passwd ();
- my_passwd_inited = 1;
- }
-
- return &my_passwd;
-}
-
-
-/* The functions fork, kill, sigsetmask, sigblock, request_sigio,
- setpgrp, setpriority, and unrequest_sigio are defined to be empty
- as in msdos.c. */
-
-
-int
-fork ()
-{
- return -1;
-}
-
-
-int
-kill (int x, int y)
-{
- return -1;
-}
-
-
-void
-sys_subshell ()
-{
- error ("Can't spawn subshell");
-}
-
-
-int
-sigsetmask (int x)
-{
- return 0;
-}
-
-
-int
-sigblock (int mask)
-{
- return 0;
-}
-
-
-void
-request_sigio (void)
-{
-}
-
-
-void
-unrequest_sigio (void)
-{
-}
-
-
-int
-setpgrp ()
-{
- return 0;
-}
-
-
-/* No pipes yet. */
-
-int
-pipe (int _fildes[2])
-{
- errno = EACCES;
- return -1;
-}
-
-
-/* Hard and symbolic links. */
-
-int
-symlink (const char *name1, const char *name2)
-{
- errno = ENOENT;
- return -1;
-}
-
-
-int
-link (const char *name1, const char *name2)
-{
- errno = ENOENT;
- return -1;
-}
-
-
-/* Determine the path name of the file specified by VREFNUM, DIRID,
- and NAME and place that in the buffer PATH of length
- MAXPATHLEN. */
-int
-path_from_vol_dir_name (char *path, int man_path_len, short vol_ref_num,
- long dir_id, ConstStr255Param name)
-{
- Str255 dir_name;
- CInfoPBRec cipb;
- OSErr err;
-
- if (strlen (name) > man_path_len)
- return 0;
-
- memcpy (dir_name, name, name[0]+1);
- memcpy (path, name, name[0]+1);
- p2cstr (path);
-
- cipb.dirInfo.ioDrParID = dir_id;
- cipb.dirInfo.ioNamePtr = dir_name;
-
- do
- {
- cipb.dirInfo.ioVRefNum = vol_ref_num;
- cipb.dirInfo.ioFDirIndex = -1;
- cipb.dirInfo.ioDrDirID = cipb.dirInfo.ioDrParID;
- /* go up to parent each time */
-
- err = PBGetCatInfo (&cipb, false);
- if (err != noErr)
- return 0;
-
- p2cstr (dir_name);
- if (strlen (dir_name) + strlen (path) + 1 >= man_path_len)
- return 0;
-
- strcat (dir_name, ":");
- strcat (dir_name, path);
- /* attach to front since we're going up directory tree */
- strcpy (path, dir_name);
- }
- while (cipb.dirInfo.ioDrDirID != fsRtDirID);
- /* stop when we see the volume's root directory */
-
- return 1; /* success */
-}
-
-
-int
-readlink (const char *path, char *buf, int bufsiz)
-{
- char mac_sym_link_name[MAXPATHLEN+1];
- OSErr err;
- FSSpec fsspec;
- Boolean target_is_folder, was_aliased;
- Str255 directory_name, mac_pathname;
- CInfoPBRec cipb;
-
- if (posix_to_mac_pathname (path, mac_sym_link_name, MAXPATHLEN+1) == 0)
- return -1;
-
- c2pstr (mac_sym_link_name);
- err = FSMakeFSSpec (0, 0, mac_sym_link_name, &fsspec);
- if (err != noErr)
- {
- errno = ENOENT;
- return -1;
- }
-
- err = ResolveAliasFile (&fsspec, true, &target_is_folder, &was_aliased);
- if (err != noErr || !was_aliased)
- {
- errno = ENOENT;
- return -1;
- }
-
- if (path_from_vol_dir_name (mac_pathname, 255, fsspec.vRefNum, fsspec.parID,
- fsspec.name) == 0)
- {
- errno = ENOENT;
- return -1;
- }
-
- if (mac_to_posix_pathname (mac_pathname, buf, bufsiz) == 0)
- {
- errno = ENOENT;
- return -1;
- }
-
- return strlen (buf);
-}
-
-
-/* Convert a path to one with aliases fully expanded. */
-
-static int
-find_true_pathname (const char *path, char *buf, int bufsiz)
-{
- char *q, temp[MAXPATHLEN+1];
- const char *p;
- int len;
-
- if (bufsiz <= 0 || path == 0 || path[0] == '\0')
- return -1;
-
- buf[0] = '\0';
-
- p = path;
- if (*p == '/')
- q = strchr (p + 1, '/');
- else
- q = strchr (p, '/');
- len = 0; /* loop may not be entered, e.g., for "/" */
-
- while (q)
- {
- strcpy (temp, buf);
- strncat (temp, p, q - p);
- len = readlink (temp, buf, bufsiz);
- if (len <= -1)
- {
- if (strlen (temp) + 1 > bufsiz)
- return -1;
- strcpy (buf, temp);
- }
- strcat (buf, "/");
- len++;
- p = q + 1;
- q = strchr(p, '/');
- }
-
- if (len + strlen (p) + 1 >= bufsiz)
- return -1;
-
- strcat (buf, p);
- return len + strlen (p);
-}
-
-
-mode_t
-umask (mode_t numask)
-{
- static mode_t mask = 022;
- mode_t oldmask = mask;
- mask = numask;
- return oldmask;
-}
-
-
-int
-chmod (const char *path, mode_t mode)
-{
- /* say it always succeed for now */
- return 0;
-}
-
-
-int
-dup (int oldd)
-{
-#ifdef __MRC__
- return fcntl (oldd, F_DUPFD, 0);
-#elif __MWERKS__
- /* current implementation of fcntl in fcntl.mac.c simply returns old
- descriptor */
- return fcntl (oldd, F_DUPFD);
-#else
-You lose!!!
-#endif
-}
-
-
-/* This is from the original sysdep.c. Emulate BSD dup2. First close
- newd if it already exists. Then, attempt to dup oldd. If not
- successful, call dup2 recursively until we are, then close the
- unsuccessful ones. */
-
-int
-dup2 (int oldd, int newd)
-{
- int fd, ret;
-
- close (newd);
-
- fd = dup (oldd);
- if (fd == -1)
- return -1;
- if (fd == newd)
- return newd;
- ret = dup2 (oldd, newd);
- close (fd);
- return ret;
-}
-
-
-/* let it fail for now */
-
-char *
-sbrk (int incr)
-{
- return (char *) -1;
-}
-
-
-int
-fsync (int fd)
-{
- return 0;
-}
-
-
-int
-ioctl (int d, int request, void *argp)
-{
- return -1;
-}
-
-
-#ifdef __MRC__
-int
-isatty (int fildes)
-{
- if (fildes >=0 && fildes <= 2)
- return 1;
- else
- return 0;
-}
-
-
-int
-getgid ()
-{
- return 100;
-}
-
-
-int
-getegid ()
-{
- return 100;
-}
-
-
-int
-getuid ()
-{
- return 200;
-}
-
-
-int
-geteuid ()
-{
- return 200;
-}
-#endif /* __MRC__ */
-
-
-#ifdef __MWERKS__
-#ifndef CODEWARRIOR_VERSION_6
-#undef getpid
-int
-getpid ()
-{
- return 9999;
-}
-#endif
-#endif /* __MWERKS__ */
-
-
-/* Return the path to the directory in which Emacs can create
- temporary files. The MacOS "temporary items" directory cannot be
- used because it removes the file written by a process when it
- exits. In that sense it's more like "/dev/null" than "/tmp" (but
- again not exactly). And of course Emacs needs to read back the
- files written by its subprocesses. So here we write the files to a
- directory "Emacs" in the Preferences Folder. This directory is
- created if it does not exist. */
-
-static char *
-get_temp_dir_name ()
-{
- static char *temp_dir_name = NULL;
- short vol_ref_num;
- long dir_id;
- OSErr err;
- Str255 dir_name, full_path;
- CInfoPBRec cpb;
- char unix_dir_name[MAXPATHLEN+1];
- DIR *dir;
-
- /* Cache directory name with pointer temp_dir_name.
- Look for it only the first time. */
- if (!temp_dir_name)
- {
- err = FindFolder (kOnSystemDisk, kPreferencesFolderType, kCreateFolder,
- &vol_ref_num, &dir_id);
- if (err != noErr)
- return NULL;
-
- if (!path_from_vol_dir_name (full_path, 255, vol_ref_num, dir_id, "\p"))
- return NULL;
-
- if (strlen (full_path) + 6 <= MAXPATHLEN)
- strcat (full_path, "Emacs:");
- else
- return NULL;
-
- if (!mac_to_posix_pathname (full_path, unix_dir_name, MAXPATHLEN+1))
- return NULL;
-
- dir = opendir (unix_dir_name); /* check whether temp directory exists */
- if (dir)
- closedir (dir);
- else if (mkdir (unix_dir_name, 0700) != 0) /* create it if not */
- return NULL;
-
- temp_dir_name = (char *) malloc (strlen (unix_dir_name) + 1);
- strcpy (temp_dir_name, unix_dir_name);
- }
-
- return temp_dir_name;
-}
-
-
-/* Allocate and construct an array of pointers to strings from a list
- of strings stored in a 'STR#' resource. The returned pointer array
- is stored in the style of argv and environ: if the 'STR#' resource
- contains numString strings, an pointer array with numString+1
- elements is returned in which the last entry contains a null
- pointer. The pointer to the pointer array is passed by pointer in
- parameter t. The resource ID of the 'STR#' resource is passed in
- parameter StringListID.
- */
-
-void
-get_string_list (char ***t, short string_list_id)
-{
- Handle h;
- Ptr p;
- int i, num_strings;
-
- h = GetResource ('STR#', string_list_id);
- if (h)
- {
- HLock (h);
- p = *h;
- num_strings = * (short *) p;
- p += sizeof(short);
- *t = (char **) malloc (sizeof (char *) * (num_strings + 1));
- for (i = 0; i < num_strings; i++)
- {
- short length = *p++;
- (*t)[i] = (char *) malloc (length + 1);
- strncpy ((*t)[i], p, length);
- (*t)[i][length] = '\0';
- p += length;
- }
- (*t)[num_strings] = 0;
- HUnlock (h);
- }
- else
- {
- /* Return no string in case GetResource fails. Bug fixed by
- Ikegami Tsutomu. Caused MPW build to crash without sym -on
- option (no sym -on implies -opt local). */
- *t = (char **) malloc (sizeof (char *));
- (*t)[0] = 0;
- }
-}
-
-
-static char *
-get_path_to_system_folder ()
-{
- short vol_ref_num;
- long dir_id;
- OSErr err;
- Str255 dir_name, full_path;
- CInfoPBRec cpb;
- static char system_folder_unix_name[MAXPATHLEN+1];
- DIR *dir;
-
- err = FindFolder (kOnSystemDisk, kSystemFolderType, kDontCreateFolder,
- &vol_ref_num, &dir_id);
- if (err != noErr)
- return NULL;
-
- if (!path_from_vol_dir_name (full_path, 255, vol_ref_num, dir_id, "\p"))
- return NULL;
-
- if (!mac_to_posix_pathname (full_path, system_folder_unix_name, MAXPATHLEN+1))
- return NULL;
-
- return system_folder_unix_name;
-}
-
-
-char **environ;
-
-#define ENVIRON_STRING_LIST_ID 128
-
-/* Get environment variable definitions from STR# resource. */
-
-void
-init_environ ()
-{
- int i;
-
- get_string_list (&environ, ENVIRON_STRING_LIST_ID);
-
- i = 0;
- while (environ[i])
- i++;
-
- /* Make HOME directory the one Emacs starts up in if not specified
- by resource. */
- if (getenv ("HOME") == NULL)
- {
- environ = (char **) realloc (environ, sizeof (char *) * (i + 2));
- if (environ)
- {
- environ[i] = (char *) malloc (strlen (my_passwd_dir) + 6);
- if (environ[i])
- {
- strcpy (environ[i], "HOME=");
- strcat (environ[i], my_passwd_dir);
- }
- environ[i+1] = 0;
- i++;
- }
- }
-
- /* Make HOME directory the one Emacs starts up in if not specified
- by resource. */
- if (getenv ("MAIL") == NULL)
- {
- environ = (char **) realloc (environ, sizeof (char *) * (i + 2));
- if (environ)
- {
- char * path_to_system_folder = get_path_to_system_folder ();
- environ[i] = (char *) malloc (strlen (path_to_system_folder) + 22);
- if (environ[i])
- {
- strcpy (environ[i], "MAIL=");
- strcat (environ[i], path_to_system_folder);
- strcat (environ[i], "Eudora Folder/In");
- }
- environ[i+1] = 0;
- }
- }
-}
-
-
-/* Return the value of the environment variable NAME. */
-
-char *
-getenv (const char *name)
-{
- int length = strlen(name);
- char **e;
-
- for (e = environ; *e != 0; e++)
- if (strncmp(*e, name, length) == 0 && (*e)[length] == '=')
- return &(*e)[length + 1];
-
- if (strcmp (name, "TMPDIR") == 0)
- return get_temp_dir_name ();
-
- return 0;
-}
-
-
-#ifdef __MRC__
-/* see Interfaces&Libraries:Interfaces:CIncludes:signal.h */
-char *sys_siglist[] =
-{
- "Zero is not a signal!!!",
- "Abort", /* 1 */
- "Interactive user interrupt", /* 2 */ "?",
- "Floating point exception", /* 4 */ "?", "?", "?",
- "Illegal instruction", /* 8 */ "?", "?", "?", "?", "?", "?", "?",
- "Segment violation", /* 16 */ "?", "?", "?", "?", "?", "?", "?",
- "?", "?", "?", "?", "?", "?", "?", "?",
- "Terminal" /* 32 */
-};
-#elif __MWERKS__
-char *sys_siglist[] =
-{
- "Zero is not a signal!!!",
- "Abort",
- "Floating point exception",
- "Illegal instruction",
- "Interactive user interrupt",
- "Segment violation",
- "Terminal"
-};
-#else
-You lose!!!
-#endif
-
-
-#include <utsname.h>
-
-int
-uname (struct utsname *name)
-{
- char **system_name;
- system_name = GetString (-16413); /* IM - Resource Manager Reference */
- if (system_name)
- {
- BlockMove (*system_name, name->nodename, (*system_name)[0]+1);
- p2cstr (name->nodename);
- return 0;
- }
- else
- return -1;
-}
-
-
-#include <Processes.h>
-#include <EPPC.h>
-
-/* Event class of HLE sent to subprocess. */
-const OSType kEmacsSubprocessSend = 'ESND';
-
-/* Event class of HLE sent back from subprocess. */
-const OSType kEmacsSubprocessReply = 'ERPY';
-
-
-char *
-mystrchr (char *s, char c)
-{
- while (*s && *s != c)
- {
- if (*s == '\\')
- s++;
- s++;
- }
-
- if (*s)
- {
- *s = '\0';
- return s;
- }
- else
- return NULL;
-}
-
-
-char *
-mystrtok (char *s)
-{
- while (*s)
- s++;
-
- return s + 1;
-}
-
-
-void
-mystrcpy (char *to, char *from)
-{
- while (*from)
- {
- if (*from == '\\')
- from++;
- *to++ = *from++;
- }
- *to = '\0';
-}
-
-
-/* Start a Mac subprocess. Arguments for it is passed in argv (null
- terminated). The process should run with the default directory
- "workdir", read input from "infn", and write output and error to
- "outfn" and "errfn", resp. The Process Manager call
- LaunchApplication is used to start the subprocess. We use high
- level events as the mechanism to pass arguments to the subprocess
- and to make Emacs wait for the subprocess to terminate and pass
- back a result code. The bulk of the code here packs the arguments
- into one message to be passed together with the high level event.
- Emacs also sometimes starts a subprocess using a shell to perform
- wildcard filename expansion. Since we don't really have a shell on
- the Mac, this case is detected and the starting of the shell is
- by-passed. We really need to add code here to do filename
- expansion to support such functionality. */
-
-int
-run_mac_command (argv, workdir, infn, outfn, errfn)
- unsigned char **argv;
- const char *workdir;
- const char *infn, *outfn, *errfn;
-{
- char macappname[MAXPATHLEN+1], macworkdir[MAXPATHLEN+1];
- char macinfn[MAXPATHLEN+1], macoutfn[MAXPATHLEN+1], macerrfn[MAXPATHLEN+1];
- int paramlen, argc, newargc, j, retries;
- char **newargv, *param, *p;
- OSErr iErr;
- FSSpec spec;
- LaunchParamBlockRec lpbr;
- EventRecord send_event, reply_event;
- RgnHandle cursor_region_handle;
- TargetID targ;
- unsigned long ref_con, len;
-
- if (posix_to_mac_pathname (workdir, macworkdir, MAXPATHLEN+1) == 0)
- return -1;
- if (posix_to_mac_pathname (infn, macinfn, MAXPATHLEN+1) == 0)
- return -1;
- if (posix_to_mac_pathname (outfn, macoutfn, MAXPATHLEN+1) == 0)
- return -1;
- if (posix_to_mac_pathname (errfn, macerrfn, MAXPATHLEN+1) == 0)
- return -1;
-
- paramlen = strlen (macworkdir) + strlen (macinfn) + strlen (macoutfn)
- + strlen (macerrfn) + 4; /* count nulls at end of strings */
-
- argc = 0;
- while (argv[argc])
- argc++;
-
- if (argc == 0)
- return -1;
-
- /* If a subprocess is invoked with a shell, we receive 3 arguments
- of the form: "<path to emacs bins>/sh" "-c" "<path to emacs
- bins>/<command> <command args>" */
- j = strlen (argv[0]);
- if (j >= 3 && strcmp (argv[0]+j-3, "/sh") == 0
- && argc == 3 && strcmp (argv[1], "-c") == 0)
- {
- char *command, *t, tempmacpathname[MAXPATHLEN+1];
-
- /* The arguments for the command in argv[2] are separated by
- spaces. Count them and put the count in newargc. */
- command = (char *) alloca (strlen (argv[2])+2);
- strcpy (command, argv[2]);
- if (command[strlen (command) - 1] != ' ')
- strcat (command, " ");
-
- t = command;
- newargc = 0;
- t = mystrchr (t, ' ');
- while (t)
- {
- newargc++;
- t = mystrchr (t+1, ' ');
- }
-
- newargv = (char **) alloca (sizeof (char *) * newargc);
-
- t = command;
- for (j = 0; j < newargc; j++)
- {
- newargv[j] = (char *) alloca (strlen (t) + 1);
- mystrcpy (newargv[j], t);
-
- t = mystrtok (t);
- paramlen += strlen (newargv[j]) + 1;
- }
-
- if (strncmp (newargv[0], "~emacs/", 7) == 0)
- {
- if (posix_to_mac_pathname (newargv[0], tempmacpathname, MAXPATHLEN+1)
- == 0)
- return -1;
- }
- else
- { /* sometimes Emacs call "sh" without a path for the command */
-#if 0
- char *t = (char *) alloca (strlen (newargv[0]) + 7 + 1);
- strcpy (t, "~emacs/");
- strcat (t, newargv[0]);
-#endif
- Lisp_Object path;
- openp (Vexec_path, build_string (newargv[0]), Vexec_suffixes, &path,
- 1);
-
- if (NILP (path))
- return -1;
- if (posix_to_mac_pathname (XSTRING (path)->data, tempmacpathname,
- MAXPATHLEN+1) == 0)
- return -1;
- }
- strcpy (macappname, tempmacpathname);
- }
- else
- {
- if (posix_to_mac_pathname (argv[0], macappname, MAXPATHLEN+1) == 0)
- return -1;
-
- newargv = (char **) alloca (sizeof (char *) * argc);
- newargc = argc;
- for (j = 1; j < argc; j++)
- {
- if (strncmp (argv[j], "~emacs/", 7) == 0)
- {
- char *t = strchr (argv[j], ' ');
- if (t)
- {
- char tempcmdname[MAXPATHLEN+1], tempmaccmdname[MAXPATHLEN+1];
- strncpy (tempcmdname, argv[j], t-argv[j]);
- tempcmdname[t-argv[j]] = '\0';
- if (posix_to_mac_pathname (tempcmdname, tempmaccmdname,
- MAXPATHLEN+1) == 0)
- return -1;
- newargv[j] = (char *) alloca (strlen (tempmaccmdname)
- + strlen (t) + 1);
- strcpy (newargv[j], tempmaccmdname);
- strcat (newargv[j], t);
- }
- else
- {
- char tempmaccmdname[MAXPATHLEN+1];
- if (posix_to_mac_pathname (argv[j], tempmaccmdname,
- MAXPATHLEN+1) == 0)
- return -1;
- newargv[j] = (char *) alloca (strlen (tempmaccmdname)+1);
- strcpy (newargv[j], tempmaccmdname);
- }
- }
- else
- newargv[j] = argv[j];
- paramlen += strlen (newargv[j]) + 1;
- }
- }
-
- /* After expanding all the arguments, we now know the length of the
- parameter block to be sent to the subprocess as a message
- attached to the HLE. */
- param = (char *) malloc (paramlen + 1);
- if (!param)
- return -1;
-
- p = param;
- *p++ = newargc;
- /* first byte of message contains number of arguments for command */
- strcpy (p, macworkdir);
- p += strlen (macworkdir);
- *p++ = '\0';
- /* null terminate strings sent so it's possible to use strcpy over there */
- strcpy (p, macinfn);
- p += strlen (macinfn);
- *p++ = '\0';
- strcpy (p, macoutfn);
- p += strlen (macoutfn);
- *p++ = '\0';
- strcpy (p, macerrfn);
- p += strlen (macerrfn);
- *p++ = '\0';
- for (j = 1; j < newargc; j++)
- {
- strcpy (p, newargv[j]);
- p += strlen (newargv[j]);
- *p++ = '\0';
- }
-
- c2pstr (macappname);
-
- iErr = FSMakeFSSpec (0, 0, macappname, &spec);
-
- if (iErr != noErr)
- {
- free (param);
- return -1;
- }
-
- lpbr.launchBlockID = extendedBlock;
- lpbr.launchEPBLength = extendedBlockLen;
- lpbr.launchControlFlags = launchContinue + launchNoFileFlags;
- lpbr.launchAppSpec = &spec;
- lpbr.launchAppParameters = NULL;
-
- iErr = LaunchApplication (&lpbr); /* call the subprocess */
- if (iErr != noErr)
- {
- free (param);
- return -1;
- }
-
- send_event.what = kHighLevelEvent;
- send_event.message = kEmacsSubprocessSend;
- /* Event ID stored in "where" unused */
-
- retries = 3;
- /* OS may think current subprocess has terminated if previous one
- terminated recently. */
- do
- {
- iErr = PostHighLevelEvent (&send_event, &lpbr.launchProcessSN, 0, param,
- paramlen + 1, receiverIDisPSN);
- }
- while (iErr == sessClosedErr && retries-- > 0);
-
- if (iErr != noErr)
- {
- free (param);
- return -1;
- }
-
- cursor_region_handle = NewRgn ();
-
- /* Wait for the subprocess to finish, when it will send us a ERPY
- high level event. */
- while (1)
- if (WaitNextEvent (highLevelEventMask, &reply_event, 180,
- cursor_region_handle)
- && reply_event.message == kEmacsSubprocessReply)
- break;
-
- /* The return code is sent through the refCon */
- iErr = AcceptHighLevelEvent (&targ, &ref_con, NULL, &len);
- if (iErr != noErr)
- {
- DisposeHandle ((Handle) cursor_region_handle);
- free (param);
- return -1;
- }
-
- DisposeHandle ((Handle) cursor_region_handle);
- free (param);
-
- return ref_con;
-}
-
-
-DIR *
-opendir (const char *dirname)
-{
- char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];
- char mac_pathname[MAXPATHLEN+1], vol_name[MAXPATHLEN+1];
- DIR *dirp;
- CInfoPBRec cipb;
- HVolumeParam vpb;
- int len, vol_name_len;
-
- if (find_true_pathname (dirname, true_pathname, MAXPATHLEN+1) == -1)
- return 0;
-
- len = readlink (true_pathname, fully_resolved_name, MAXPATHLEN);
- if (len > -1)
- fully_resolved_name[len] = '\0';
- else
- strcpy (fully_resolved_name, true_pathname);
-
- dirp = (DIR *) malloc (sizeof(DIR));
- if (!dirp)
- return 0;
-
- /* Handle special case when dirname is "/": sets up for readir to
- get all mount volumes. */
- if (strcmp (fully_resolved_name, "/") == 0)
- {
- dirp->getting_volumes = 1; /* special all mounted volumes DIR struct */
- dirp->current_index = 1; /* index for first volume */
- return dirp;
- }
-
- /* Handle typical cases: not accessing all mounted volumes. */
- if (!posix_to_mac_pathname (fully_resolved_name, mac_pathname, MAXPATHLEN+1))
- return 0;
-
- /* Emacs calls opendir without the trailing '/', Mac needs trailing ':' */
- len = strlen (mac_pathname);
- if (mac_pathname[len - 1] != ':' && len < MAXPATHLEN)
- strcat (mac_pathname, ":");
-
- /* Extract volume name */
- vol_name_len = strchr (mac_pathname, ':') - mac_pathname;
- strncpy (vol_name, mac_pathname, vol_name_len);
- vol_name[vol_name_len] = '\0';
- strcat (vol_name, ":");
-
- c2pstr (mac_pathname);
- cipb.hFileInfo.ioNamePtr = mac_pathname;
- /* using full pathname so vRefNum and DirID ignored */
- cipb.hFileInfo.ioVRefNum = 0;
- cipb.hFileInfo.ioDirID = 0;
- cipb.hFileInfo.ioFDirIndex = 0;
- /* set to 0 to get information about specific dir or file */
-
- errno = PBGetCatInfo (&cipb, false);
- if (errno != noErr)
- {
- errno = ENOENT;
- return 0;
- }
-
- if (!(cipb.hFileInfo.ioFlAttrib & 0x10)) /* bit 4 = 1 for directories */
- return 0; /* not a directory */
-
- dirp->dir_id = cipb.dirInfo.ioDrDirID; /* used later in readdir */
- dirp->getting_volumes = 0;
- dirp->current_index = 1; /* index for first file/directory */
-
- c2pstr (vol_name);
- vpb.ioNamePtr = vol_name;
- /* using full pathname so vRefNum and DirID ignored */
- vpb.ioVRefNum = 0;
- vpb.ioVolIndex = -1;
- errno = PBHGetVInfo ((union HParamBlockRec *) &vpb, false);
- if (errno != noErr)
- {
- errno = ENOENT;
- return 0;
- }
-
- dirp->vol_ref_num = vpb.ioVRefNum;
-
- return dirp;
-}
-
-int
-closedir (DIR *dp)
-{
- free (dp);
-
- return 0;
-}
-
-
-struct dirent *
-readdir (DIR *dp)
-{
- HParamBlockRec hpblock;
- CInfoPBRec cipb;
- static struct dirent s_dirent;
- static Str255 s_name;
- int done;
- char *p;
-
- /* Handle the root directory containing the mounted volumes. Call
- PBHGetVInfo specifying an index to obtain the info for a volume.
- PBHGetVInfo returns an error when it receives an index beyond the
- last volume, at which time we should return a nil dirent struct
- pointer. */
- if (dp->getting_volumes)
- {
- hpblock.volumeParam.ioNamePtr = s_name;
- hpblock.volumeParam.ioVRefNum = 0;
- hpblock.volumeParam.ioVolIndex = dp->current_index;
-
- errno = PBHGetVInfo (&hpblock, false);
- if (errno != noErr)
- {
- errno = ENOENT;
- return 0;
- }
-
- p2cstr (s_name);
- strcat (s_name, "/"); /* need "/" for stat to work correctly */
-
- dp->current_index++;
-
- s_dirent.d_ino = hpblock.volumeParam.ioVRefNum;
- s_dirent.d_name = s_name;
-
- return &s_dirent;
- }
- else
- {
- cipb.hFileInfo.ioVRefNum = dp->vol_ref_num;
- cipb.hFileInfo.ioNamePtr = s_name;
- /* location to receive filename returned */
-
- /* return only visible files */
- done = false;
- while (!done)
- {
- cipb.hFileInfo.ioDirID = dp->dir_id;
- /* directory ID found by opendir */
- cipb.hFileInfo.ioFDirIndex = dp->current_index;
-
- errno = PBGetCatInfo (&cipb, false);
- if (errno != noErr)
- {
- errno = ENOENT;
- return 0;
- }
-
- /* insist on an visibile entry */
- if (cipb.hFileInfo.ioFlAttrib & 0x10) /* directory? */
- done = !(cipb.dirInfo.ioDrUsrWds.frFlags & fInvisible);
- else
- done = !(cipb.hFileInfo.ioFlFndrInfo.fdFlags & fInvisible);
-
- dp->current_index++;
- }
-
- p2cstr (s_name);
-
- p = s_name;
- while (*p)
- {
- if (*p == '/')
- *p = ':';
- p++;
- }
-
- s_dirent.d_ino = cipb.dirInfo.ioDrDirID;
- /* value unimportant: non-zero for valid file */
- s_dirent.d_name = s_name;
-
- return &s_dirent;
- }
-}
-
-
-char *
-getwd (char *path)
-{
- char mac_pathname[MAXPATHLEN+1];
- Str255 directory_name;
- OSErr errno;
- CInfoPBRec cipb;
-
- if (path_from_vol_dir_name (mac_pathname, 255, 0, 0, "\p") == 0)
- return NULL;
-
- if (mac_to_posix_pathname (mac_pathname, path, MAXPATHLEN+1) == 0)
- return 0;
- else
- return path;
-}
-
-
-void
-initialize_applescript ()
-{
- AEDesc null_desc;
- OSAError osaerror;
-
- /* if open fails, as_scripting_component is set to NULL. Its
- subsequent use in OSA calls will fail with badComponentInstance
- error. */
- as_scripting_component = OpenDefaultComponent (kOSAComponentType,
- kAppleScriptSubtype);
-
- null_desc.descriptorType = typeNull;
- null_desc.dataHandle = 0;
- osaerror = OSAMakeContext (as_scripting_component, &null_desc,
- kOSANullScript, &as_script_context);
- if (osaerror)
- as_script_context = kOSANullScript;
- /* use default context if create fails */
-}
-
-
-void terminate_applescript()
-{
- OSADispose (as_scripting_component, as_script_context);
- CloseComponent (as_scripting_component);
-}
-
-
-/* Compile and execute the AppleScript SCRIPT and return the error
- status as function value. A zero is returned if compilation and
- execution is successful, in which case RESULT returns a pointer to
- a string containing the resulting script value. Otherwise, the Mac
- error code is returned and RESULT returns a pointer to an error
- string. In both cases the caller should deallocate the storage
- used by the string pointed to by RESULT if it is non-NULL. For
- documentation on the MacOS scripting architecture, see Inside
- Macintosh - Interapplication Communications: Scripting Components. */
-
-static long
-do_applescript (char *script, char **result)
-{
- AEDesc script_desc, result_desc, error_desc;
- OSErr error;
- OSAError osaerror;
- long length;
-
- *result = 0;
-
- error = AECreateDesc (typeChar, script, strlen(script), &script_desc);
- if (error)
- return error;
-
- osaerror = OSADoScript (as_scripting_component, &script_desc, kOSANullScript,
- typeChar, kOSAModeNull, &result_desc);
-
- if (osaerror == errOSAScriptError)
- {
- /* error executing AppleScript: retrieve error message */
- if (!OSAScriptError (as_scripting_component, kOSAErrorMessage, typeChar,
- &error_desc))
- {
- HLock (error_desc.dataHandle);
- length = GetHandleSize(error_desc.dataHandle);
- *result = (char *) xmalloc (length + 1);
- if (*result)
- {
- memcpy (*result, *(error_desc.dataHandle), length);
- *(*result + length) = '\0';
- }
- HUnlock (error_desc.dataHandle);
- AEDisposeDesc (&error_desc);
- }
- }
- else if (osaerror == noErr) /* success: retrieve resulting script value */
- {
- HLock (result_desc.dataHandle);
- length = GetHandleSize(result_desc.dataHandle);
- *result = (char *) xmalloc (length + 1);
- if (*result)
- {
- memcpy (*result, *(result_desc.dataHandle), length);
- *(*result + length) = '\0';
- }
- HUnlock (result_desc.dataHandle);
- }
-
- AEDisposeDesc (&script_desc);
- AEDisposeDesc (&result_desc);
-
- return osaerror;
-}
-
-
-DEFUN ("do-applescript", Fdo_applescript, Sdo_applescript, 1, 1, 0,
- "Compile and execute AppleScript SCRIPT and retrieve and return the\n\
-result. If compilation and execution are successful, the resulting script\n\
-value is returned as a string. Otherwise the function aborts and\n\
-displays the error message returned by the AppleScript scripting\n\
-component.")
- (script)
- Lisp_Object script;
-{
- char *result, *temp;
- Lisp_Object lisp_result;
- long status;
-
- CHECK_STRING (script, 0);
-
- status = do_applescript (XSTRING (script)->data, &result);
- if (status)
- {
- if (!result)
- error ("AppleScript error %ld", status);
- else
- {
- /* Unfortunately only OSADoScript in do_applescript knows how
- how large the resulting script value or error message is
- going to be and therefore as caller memory must be
- deallocated here. It is necessary to free the error
- message before calling error to avoid a memory leak. */
- temp = (char *) alloca (strlen (result) + 1);
- strcpy (temp, result);
- xfree (result);
- error (temp);
- }
- }
- else
- {
- lisp_result = build_string (result);
- xfree (result);
- return lisp_result;
- }
-}
-
-
-DEFUN ("mac-file-name-to-posix", Fmac_file_name_to_posix, Smac_file_name_to_posix, 1,
- 1, 0,
- "Convert Macintosh filename to Posix form.")
- (mac_filename)
- Lisp_Object mac_filename;
-{
- char posix_filename[MAXPATHLEN+1];
-
- CHECK_STRING (mac_filename, 0);
-
- if (mac_to_posix_pathname (XSTRING (mac_filename)->data, posix_filename,
- MAXPATHLEN))
- return build_string (posix_filename);
- else
- return Qnil;
-}
-
-
-DEFUN ("posix-file-name-to-mac", Fposix_file_name_to_mac, Sposix_file_name_to_mac, 1,
- 1, 0,
- "Convert Unix filename to Mac form.")
- (posix_filename)
- Lisp_Object posix_filename;
-{
- char mac_filename[MAXPATHLEN+1];
-
- CHECK_STRING (posix_filename, 0);
-
- if (posix_to_mac_pathname (XSTRING (posix_filename)->data, mac_filename,
- MAXPATHLEN))
- return build_string (mac_filename);
- else
- return Qnil;
-}
-
-
-/* set interprogram-paste-function to mac-paste-function in mac-win.el
- to enable Emacs to obtain the contents of the Mac clipboard. */
-DEFUN ("mac-paste-function", Fmac_paste_function, Smac_paste_function, 0, 0, 0,
- "Return the contents of the Mac clipboard as a string.")
- ()
-{
- Lisp_Object value;
- Handle my_handle;
- long scrap_offset, rc, i;
-
- my_handle = NewHandle (0); /* allocate 0-length data area */
-
- rc = GetScrap (my_handle, 'TEXT', &scrap_offset);
- if (rc < 0)
- return Qnil;
-
- HLock (my_handle);
-
- /* Emacs expects clipboard contents have Unix-style eol's */
- for (i = 0; i < rc; i++)
- if ((*my_handle)[i] == '\r')
- (*my_handle)[i] = '\n';
-
- value = make_string (*my_handle, rc);
-
- HUnlock (my_handle);
-
- DisposeHandle (my_handle);
-
- return value;
-}
-
-
-/* set interprogram-cut-function to mac-cut-function in mac-win.el
- to enable Emacs to write the top of the kill-ring to the Mac clipboard. */
-DEFUN ("mac-cut-function", Fmac_cut_function, Smac_cut_function, 1, 2, 0,
- "Put the value of the string parameter to the Mac clipboard.")
- (value, push)
- Lisp_Object value, push;
-{
- char *buf;
- int len, i;
-
- /* fixme: ignore the push flag for now */
-
- CHECK_STRING (value, 0);
-
- len = XSTRING (value)->size;
- buf = (char *) alloca (len);
- bcopy(XSTRING (value)->data, buf, len);
-
- /* convert to Mac-style eol's before sending to clipboard */
- for (i = 0; i < len; i++)
- if (buf[i] == '\n')
- buf[i] = '\r';
-
- ZeroScrap ();
- PutScrap (len, 'TEXT', buf);
-
- return Qnil;
-}
-
-
-DEFUN ("x-selection-exists-p", Fx_selection_exists_p, Sx_selection_exists_p,
- 0, 1, 0,
- "Whether there is an owner for the given X Selection.\n\
-The arg should be the name of the selection in question, typically one of\n\
-the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\
-\(Those are literal upper-case symbol names, since that's what X expects.)\n\
-For convenience, the symbol nil is the same as `PRIMARY',\n\
-and t is the same as `SECONDARY'.")
- (selection)
- Lisp_Object selection;
-{
- CHECK_SYMBOL (selection, 0);
-
- /* Return nil for PRIMARY and SECONDARY selections; for CLIPBOARD, check
- if the clipboard currently has valid text format contents. */
-
- if (EQ (selection, QCLIPBOARD))
- {
- Lisp_Object val = Qnil;
- Lisp_Object value;
- Handle my_handle;
- long rc, scrap_offset;
-
- my_handle = NewHandle (0);
-
- rc = GetScrap (my_handle, 'TEXT', &scrap_offset);
- if (rc >= 0)
- val = Qt;
-
- DisposeHandle (my_handle);
-
- return val;
- }
- return Qnil;
-}
-
-
-void
-syms_of_mac ()
-{
- QCLIPBOARD = intern ("CLIPBOARD");
- staticpro (&QCLIPBOARD);
-
- defsubr (&Smac_paste_function);
- defsubr (&Smac_cut_function);
- defsubr (&Sx_selection_exists_p);
-
- defsubr (&Sdo_applescript);
- defsubr (&Smac_file_name_to_posix);
- defsubr (&Sposix_file_name_to_mac);
-}
+++ /dev/null
-/* Graphical user interface functions for Mac OS.
- Copyright (C) 2000 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Contributed by Andrew Choi (akochoi@users.sourceforge.net). */
-
-#include <config.h>
-
-#include <signal.h>
-#include <stdio.h>
-#include <math.h>
-#include <limits.h>
-#include <errno.h>
-
-#include "lisp.h"
-#include "charset.h"
-#include "macterm.h"
-#include "frame.h"
-#include "window.h"
-#include "buffer.h"
-#include "dispextern.h"
-#include "fontset.h"
-#include "intervals.h"
-#include "keyboard.h"
-#include "blockinput.h"
-#include "epaths.h"
-#include "termhooks.h"
-#include "coding.h"
-#include "ccl.h"
-#include "systime.h"
-
-/* #include "bitmaps/gray.xbm" */
-#define gray_width 2
-#define gray_height 2
-static unsigned char gray_bits[] = {
- 0x01, 0x02};
-
-/*#include <commdlg.h>
-#include <shellapi.h>*/
-#include <ctype.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <alloca.h>
-#if 0
-#include <unistd.h>
-#endif
-
-#include <Windows.h>
-#include <Gestalt.h>
-#include <TextUtils.h>
-
-#ifndef min
-#define min(a,b) ((a) < (b) ? (a) : (b))
-#endif
-#ifndef max
-#define max(a,b) ((a) > (b) ? (a) : (b))
-#endif
-
-/*extern void free_frame_menubar ();
-extern void x_compute_fringe_widths (struct frame *, int);
-extern double atof ();
-extern int w32_console_toggle_lock_key (int vk_code, Lisp_Object new_state);
-extern int quit_char;*/
-
-/* A definition of XColor for non-X frames. */
-#ifndef HAVE_X_WINDOWS
-typedef struct {
- unsigned long pixel;
- unsigned short red, green, blue;
- char flags;
- char pad;
-} XColor;
-#endif
-
-extern char *lispy_function_keys[];
-
-/* The gray bitmap `bitmaps/gray'. This is done because macterm.c uses
- it, and including `bitmaps/gray' more than once is a problem when
- config.h defines `static' as an empty replacement string. */
-
-int gray_bitmap_width = gray_width;
-int gray_bitmap_height = gray_height;
-unsigned char *gray_bitmap_bits = gray_bits;
-
-/* The name we're using in resource queries. */
-
-Lisp_Object Vx_resource_name;
-
-/* Non-zero means we're allowed to display an hourglass cursor. */
-
-int display_hourglass_p;
-
-/* The background and shape of the mouse pointer, and shape when not
- over text or in the modeline. */
-
-Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
-Lisp_Object Vx_hourglass_pointer_shape;
-
-/* The shape when over mouse-sensitive text. */
-
-Lisp_Object Vx_sensitive_text_pointer_shape;
-
-/* If non-nil, the pointer shape to indicate that windows can be
- dragged horizontally. */
-
-Lisp_Object Vx_window_horizontal_drag_shape;
-
-/* Color of chars displayed in cursor box. */
-
-Lisp_Object Vx_cursor_fore_pixel;
-
-/* Nonzero if using Windows. */
-
-static int mac_in_use;
-
-/* Non nil if no window manager is in use. */
-
-Lisp_Object Vx_no_window_manager;
-
-/* Search path for bitmap files. */
-
-Lisp_Object Vx_bitmap_file_path;
-
-/* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
-
-Lisp_Object Vx_pixel_size_width_font_regexp;
-
-/* Evaluate this expression to rebuild the section of syms_of_macfns
- that initializes and staticpros the symbols declared below. Note
- that Emacs 18 has a bug that keeps C-x C-e from being able to
- evaluate this expression.
-
-(progn
- ;; Accumulate a list of the symbols we want to initialize from the
- ;; declarations at the top of the file.
- (goto-char (point-min))
- (search-forward "/\*&&& symbols declared here &&&*\/\n")
- (let (symbol-list)
- (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
- (setq symbol-list
- (cons (buffer-substring (match-beginning 1) (match-end 1))
- symbol-list))
- (forward-line 1))
- (setq symbol-list (nreverse symbol-list))
- ;; Delete the section of syms_of_... where we initialize the symbols.
- (search-forward "\n /\*&&& init symbols here &&&*\/\n")
- (let ((start (point)))
- (while (looking-at "^ Q")
- (forward-line 2))
- (kill-region start (point)))
- ;; Write a new symbol initialization section.
- (while symbol-list
- (insert (format " %s = intern (\"" (car symbol-list)))
- (let ((start (point)))
- (insert (substring (car symbol-list) 1))
- (subst-char-in-region start (point) ?_ ?-))
- (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
- (setq symbol-list (cdr symbol-list)))))
-
- */
-
-/*&&& symbols declared here &&&*/
-Lisp_Object Qauto_raise;
-Lisp_Object Qauto_lower;
-Lisp_Object Qbar;
-Lisp_Object Qborder_color;
-Lisp_Object Qborder_width;
-Lisp_Object Qbox;
-Lisp_Object Qcursor_color;
-Lisp_Object Qcursor_type;
-Lisp_Object Qgeometry;
-Lisp_Object Qicon_left;
-Lisp_Object Qicon_top;
-Lisp_Object Qicon_type;
-Lisp_Object Qicon_name;
-Lisp_Object Qinternal_border_width;
-Lisp_Object Qleft;
-Lisp_Object Qright;
-Lisp_Object Qmouse_color;
-Lisp_Object Qnone;
-Lisp_Object Qparent_id;
-Lisp_Object Qscroll_bar_width;
-Lisp_Object Qsuppress_icon;
-Lisp_Object Qundefined_color;
-Lisp_Object Qvertical_scroll_bars;
-Lisp_Object Qvisibility;
-Lisp_Object Qwindow_id;
-Lisp_Object Qx_frame_parameter;
-Lisp_Object Qx_resource_name;
-Lisp_Object Quser_position;
-Lisp_Object Quser_size;
-Lisp_Object Qscreen_gamma;
-Lisp_Object Qline_spacing;
-Lisp_Object Qcenter;
-Lisp_Object Qcancel_timer;
-Lisp_Object Qhyper;
-Lisp_Object Qsuper;
-Lisp_Object Qmeta;
-Lisp_Object Qalt;
-Lisp_Object Qctrl;
-Lisp_Object Qcontrol;
-Lisp_Object Qshift;
-
-extern Lisp_Object Qtop;
-extern Lisp_Object Qdisplay;
-Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
-extern Lisp_Object Qtool_bar_lines;
-
-/* These are defined in frame.c. */
-extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
-extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
-extern Lisp_Object Qtool_bar_lines;
-
-extern Lisp_Object Vwindow_system_version;
-
-Lisp_Object Qface_set_after_frame_default;
-
-/* Functions in macterm.c. */
-extern void x_set_offset (struct frame *, int, int, int);
-extern void x_wm_set_icon_position (struct frame *, int, int);
-extern void x_display_cursor (struct window *, int, int, int, int, int);
-extern void x_set_window_size (struct frame *, int, int, int);
-extern void x_make_frame_visible (struct frame *);
-extern struct mac_display_info *x_term_init (Lisp_Object, char *, char *);
-extern struct font_info *x_get_font_info (FRAME_PTR, int);
-extern struct font_info *x_load_font (struct frame *, char *, int);
-extern void x_find_ccl_program (struct font_info *);
-extern struct font_info *x_query_font (struct frame *, char *);
-
-
-/* compare two strings ignoring case */
-
-static int
-stricmp (const char *s, const char *t)
-{
- for ( ; tolower (*s) == tolower (*t); s++, t++)
- if (*s == '\0')
- return 0;
- return tolower (*s) - tolower (*t);
-}
-
-/* compare two strings up to n characters, ignoring case */
-
-static int
-strnicmp (const char *s, const char *t, unsigned int n)
-{
- for ( ; n-- > 0 && tolower (*s) == tolower (*t); s++, t++)
- if (*s == '\0')
- return 0;
- return n == 0 ? 0 : tolower (*s) - tolower (*t);
-}
-
-\f
-/* Error if we are not running on Mac OS. */
-
-void
-check_mac ()
-{
- if (! mac_in_use)
- error ("Mac OS not in use or not initialized");
-}
-
-/* Nonzero if we can use mouse menus.
- You should not call this unless HAVE_MENUS is defined. */
-
-int
-have_menus_p ()
-{
- return mac_in_use;
-}
-
-/* Extract a frame as a FRAME_PTR, defaulting to the selected frame
- and checking validity for Mac. */
-
-FRAME_PTR
-check_x_frame (frame)
- Lisp_Object frame;
-{
- FRAME_PTR f;
-
- if (NILP (frame))
- frame = selected_frame;
- CHECK_LIVE_FRAME (frame, 0);
- f = XFRAME (frame);
- if (! FRAME_MAC_P (f))
- error ("non-mac frame used");
- return f;
-}
-
-/* Let the user specify an display with a frame.
- nil stands for the selected frame--or, if that is not a mac frame,
- the first display on the list. */
-
-static struct mac_display_info *
-check_x_display_info (frame)
- Lisp_Object frame;
-{
- if (NILP (frame))
- {
- struct frame *sf = XFRAME (selected_frame);
-
- if (FRAME_MAC_P (sf) && FRAME_LIVE_P (sf))
- return FRAME_MAC_DISPLAY_INFO (sf);
- else
- return &one_mac_display_info;
- }
- else if (STRINGP (frame))
- return x_display_info_for_name (frame);
- else
- {
- FRAME_PTR f;
-
- CHECK_LIVE_FRAME (frame, 0);
- f = XFRAME (frame);
- if (! FRAME_MAC_P (f))
- error ("non-mac frame used");
- return FRAME_MAC_DISPLAY_INFO (f);
- }
-}
-\f
-/* Return the Emacs frame-object corresponding to an mac window.
- It could be the frame's main window or an icon window. */
-
-/* This function can be called during GC, so use GC_xxx type test macros. */
-
-struct frame *
-x_window_to_frame (dpyinfo, wdesc)
- struct mac_display_info *dpyinfo;
- WindowPtr wdesc;
-{
- Lisp_Object tail, frame;
- struct frame *f;
-
- for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
- {
- frame = XCAR (tail);
- if (!GC_FRAMEP (frame))
- continue;
- f = XFRAME (frame);
- if (!FRAME_W32_P (f) || FRAME_MAC_DISPLAY_INFO (f) != dpyinfo)
- continue;
- /*if (f->output_data.w32->busy_window == wdesc)
- return f;*/
-
- /* MAC_TODO: Check tooltips when supported. */
- if (FRAME_MAC_WINDOW (f) == wdesc)
- return f;
- }
- return 0;
-}
-
-\f
-
-/* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
- id, which is just an int that this section returns. Bitmaps are
- reference counted so they can be shared among frames.
-
- Bitmap indices are guaranteed to be > 0, so a negative number can
- be used to indicate no bitmap.
-
- If you use x_create_bitmap_from_data, then you must keep track of
- the bitmaps yourself. That is, creating a bitmap from the same
- data more than once will not be caught. */
-
-
-/* Functions to access the contents of a bitmap, given an id. */
-
-int
-x_bitmap_height (f, id)
- FRAME_PTR f;
- int id;
-{
- return FRAME_MAC_DISPLAY_INFO (f)->bitmaps[id - 1].height;
-}
-
-int
-x_bitmap_width (f, id)
- FRAME_PTR f;
- int id;
-{
- return FRAME_MAC_DISPLAY_INFO (f)->bitmaps[id - 1].width;
-}
-
-#if 0 /* MAC_TODO : not used anywhere (?) */
-int
-x_bitmap_pixmap (f, id)
- FRAME_PTR f;
- int id;
-{
- return (int) FRAME_MAC_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
-}
-#endif
-
-/* Allocate a new bitmap record. Returns index of new record. */
-
-static int
-x_allocate_bitmap_record (f)
- FRAME_PTR f;
-{
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
- int i;
-
- if (dpyinfo->bitmaps == NULL)
- {
- dpyinfo->bitmaps_size = 10;
- dpyinfo->bitmaps = (struct mac_bitmap_record *)
- xmalloc (dpyinfo->bitmaps_size * sizeof (struct mac_bitmap_record));
- dpyinfo->bitmaps_last = 1;
- return 1;
- }
-
- if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
- return ++dpyinfo->bitmaps_last;
-
- for (i = 0; i < dpyinfo->bitmaps_size; ++i)
- if (dpyinfo->bitmaps[i].refcount == 0)
- return i + 1;
-
- dpyinfo->bitmaps_size *= 2;
- dpyinfo->bitmaps = (struct mac_bitmap_record *)
- xrealloc (dpyinfo->bitmaps,
- dpyinfo->bitmaps_size * sizeof (struct mac_bitmap_record));
- return ++dpyinfo->bitmaps_last;
-}
-
-/* Add one reference to the reference count of the bitmap with id
- ID. */
-
-void
-x_reference_bitmap (f, id)
- FRAME_PTR f;
- int id;
-{
- ++FRAME_MAC_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
-}
-
-/* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at
- BITS. */
-
-int
-x_create_bitmap_from_data (f, bits, width, height)
- struct frame *f;
- char *bits;
- unsigned int width, height;
-{
- struct x_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
- int id;
-
- /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
-
- id = x_allocate_bitmap_record (f);
-
- if (width % 16 != 0)
- return -1;
-
- dpyinfo->bitmaps[id - 1].bitmap_data = (char *) xmalloc (height * width);
- if (! dpyinfo->bitmaps[id - 1].bitmap_data)
- return -1;
-
- bcopy (bits, dpyinfo->bitmaps[id - 1].bitmap_data, height * width);
-
- dpyinfo->bitmaps[id - 1].refcount = 1;
- dpyinfo->bitmaps[id - 1].height = height;
- dpyinfo->bitmaps[id - 1].width = width;
-
- return id;
-}
-
-/* Create bitmap from file FILE for frame F. */
-
-int
-x_create_bitmap_from_file (f, file)
- struct frame *f;
- Lisp_Object file;
-{
- return -1;
-#if 0 /* MAC_TODO : bitmap support */
- struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
- unsigned int width, height;
- HBITMAP bitmap;
- int xhot, yhot, result, id;
- Lisp_Object found;
- int fd;
- char *filename;
- HINSTANCE hinst;
-
- /* Look for an existing bitmap with the same name. */
- for (id = 0; id < dpyinfo->bitmaps_last; ++id)
- {
- if (dpyinfo->bitmaps[id].refcount
- && dpyinfo->bitmaps[id].file
- && !strcmp (dpyinfo->bitmaps[id].file, (char *) XSTRING (file)->data))
- {
- ++dpyinfo->bitmaps[id].refcount;
- return id + 1;
- }
- }
-
- /* Search bitmap-file-path for the file, if appropriate. */
- fd = openp (Vx_bitmap_file_path, file, Qnil, &found, 0);
- if (fd < 0)
- return -1;
- /* LoadLibraryEx won't handle special files handled by Emacs handler. */
- if (fd == 0)
- return -1;
- emacs_close (fd);
-
- filename = (char *) XSTRING (found)->data;
-
- hinst = LoadLibraryEx (filename, NULL, LOAD_LIBRARY_AS_DATAFILE);
-
- if (hinst == NULL)
- return -1;
-
-
- result = XReadBitmapFile (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
- filename, &width, &height, &bitmap, &xhot, &yhot);
- if (result != BitmapSuccess)
- return -1;
-
- id = x_allocate_bitmap_record (f);
- dpyinfo->bitmaps[id - 1].pixmap = bitmap;
- dpyinfo->bitmaps[id - 1].refcount = 1;
- dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (XSTRING (file)->size + 1);
- dpyinfo->bitmaps[id - 1].depth = 1;
- dpyinfo->bitmaps[id - 1].height = height;
- dpyinfo->bitmaps[id - 1].width = width;
- strcpy (dpyinfo->bitmaps[id - 1].file, XSTRING (file)->data);
-
- return id;
-#endif /* MAC_TODO */
-}
-
-/* Remove reference to bitmap with id number ID. */
-
-void
-x_destroy_bitmap (f, id)
- FRAME_PTR f;
- int id;
-{
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
-
- if (id > 0)
- {
- --dpyinfo->bitmaps[id - 1].refcount;
- if (dpyinfo->bitmaps[id - 1].refcount == 0)
- {
- BLOCK_INPUT;
- dpyinfo->bitmaps[id - 1].bitmap_data = NULL;
- UNBLOCK_INPUT;
- }
- }
-}
-
-/* Free all the bitmaps for the display specified by DPYINFO. */
-
-static void
-x_destroy_all_bitmaps (dpyinfo)
- struct mac_display_info *dpyinfo;
-{
- int i;
- for (i = 0; i < dpyinfo->bitmaps_last; i++)
- if (dpyinfo->bitmaps[i].refcount > 0)
- xfree (dpyinfo->bitmaps[i].bitmap_data);
- dpyinfo->bitmaps_last = 0;
-}
-\f
-/* Connect the frame-parameter names for W32 frames
- to the ways of passing the parameter values to the window system.
-
- The name of a parameter, as a Lisp symbol,
- has an `x-frame-parameter' property which is an integer in Lisp
- but can be interpreted as an `enum x_frame_parm' in C. */
-
-struct x_frame_parm_table
-{
- char *name;
- void (*setter) P_ ((struct frame *, Lisp_Object, Lisp_Object));
-};
-
-void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
-static void x_set_line_spacing P_ ((struct frame *, Lisp_Object, Lisp_Object));
-void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
-void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
-void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
-void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
-void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
-void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
-void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
-void x_set_font P_ ((struct frame *, Lisp_Object, Lisp_Object));
-static void x_set_fringe_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
-void x_set_border_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
-void x_set_internal_border_width P_ ((struct frame *, Lisp_Object,
- Lisp_Object));
-void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
-void x_set_autoraise P_ ((struct frame *, Lisp_Object, Lisp_Object));
-void x_set_autolower P_ ((struct frame *, Lisp_Object, Lisp_Object));
-void x_set_vertical_scroll_bars P_ ((struct frame *, Lisp_Object,
- Lisp_Object));
-void x_set_visibility P_ ((struct frame *, Lisp_Object, Lisp_Object));
-void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
-void x_set_scroll_bar_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
-void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object));
-void x_set_unsplittable P_ ((struct frame *, Lisp_Object, Lisp_Object));
-void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
-void x_set_scroll_bar_foreground P_ ((struct frame *, Lisp_Object,
- Lisp_Object));
-void x_set_scroll_bar_background P_ ((struct frame *, Lisp_Object,
- Lisp_Object));
-static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *,
- Lisp_Object,
- Lisp_Object,
- char *, char *,
- int));
-static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object));
-
-static struct x_frame_parm_table x_frame_parms[] =
-{
- "auto-raise", x_set_autoraise,
- "auto-lower", x_set_autolower,
- "background-color", x_set_background_color,
- "border-color", x_set_border_color,
- "border-width", x_set_border_width,
- "cursor-color", x_set_cursor_color,
- "cursor-type", x_set_cursor_type,
- "font", x_set_font,
- "foreground-color", x_set_foreground_color,
- "icon-name", x_set_icon_name,
-#if 0 /* MAC_TODO: no icons for Mac */
- "icon-type", x_set_icon_type,
-#endif
- "internal-border-width", x_set_internal_border_width,
- "menu-bar-lines", x_set_menu_bar_lines,
- "mouse-color", x_set_mouse_color,
- "name", x_explicitly_set_name,
- "scroll-bar-width", x_set_scroll_bar_width,
- "title", x_set_title,
- "unsplittable", x_set_unsplittable,
- "vertical-scroll-bars", x_set_vertical_scroll_bars,
- "visibility", x_set_visibility,
- "tool-bar-lines", x_set_tool_bar_lines,
-#if 0 /* MAC_TODO: cannot set color of scroll bar on the Mac? */
- "scroll-bar-foreground", x_set_scroll_bar_foreground,
- "scroll-bar-background", x_set_scroll_bar_background,
-#endif
- "screen-gamma", x_set_screen_gamma,
- "line-spacing", x_set_line_spacing,
- "left-fringe", x_set_fringe_width,
- "right-fringe", x_set_fringe_width
-};
-
-/* Attach the `x-frame-parameter' properties to
- the Lisp symbol names of parameters relevant to Mac. */
-
-void
-init_x_parm_symbols ()
-{
- int i;
-
- for (i = 0; i < sizeof (x_frame_parms) / sizeof (x_frame_parms[0]); i++)
- Fput (intern (x_frame_parms[i].name), Qx_frame_parameter,
- make_number (i));
-}
-\f
-/* Change the parameters of frame F as specified by ALIST.
- If a parameter is not specially recognized, do nothing;
- otherwise call the `x_set_...' function for that parameter. */
-
-void
-x_set_frame_parameters (f, alist)
- FRAME_PTR f;
- Lisp_Object alist;
-{
- Lisp_Object tail;
-
- /* If both of these parameters are present, it's more efficient to
- set them both at once. So we wait until we've looked at the
- entire list before we set them. */
- int width, height;
-
- /* Same here. */
- Lisp_Object left, top;
-
- /* Same with these. */
- Lisp_Object icon_left, icon_top;
-
- /* Record in these vectors all the parms specified. */
- Lisp_Object *parms;
- Lisp_Object *values;
- int i, p;
- int left_no_change = 0, top_no_change = 0;
- int icon_left_no_change = 0, icon_top_no_change = 0;
-
- struct gcpro gcpro1, gcpro2;
-
- i = 0;
- for (tail = alist; CONSP (tail); tail = Fcdr (tail))
- i++;
-
- parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
- values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
-
- /* Extract parm names and values into those vectors. */
-
- i = 0;
- for (tail = alist; CONSP (tail); tail = Fcdr (tail))
- {
- Lisp_Object elt;
-
- elt = Fcar (tail);
- parms[i] = Fcar (elt);
- values[i] = Fcdr (elt);
- i++;
- }
- /* TAIL and ALIST are not used again below here. */
- alist = tail = Qnil;
-
- GCPRO2 (*parms, *values);
- gcpro1.nvars = i;
- gcpro2.nvars = i;
-
- /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
- because their values appear in VALUES and strings are not valid. */
- top = left = Qunbound;
- icon_left = icon_top = Qunbound;
-
- /* Provide default values for HEIGHT and WIDTH. */
- if (FRAME_NEW_WIDTH (f))
- width = FRAME_NEW_WIDTH (f);
- else
- width = FRAME_WIDTH (f);
-
- if (FRAME_NEW_HEIGHT (f))
- height = FRAME_NEW_HEIGHT (f);
- else
- height = FRAME_HEIGHT (f);
-
- /* Process foreground_color and background_color before anything else.
- They are independent of other properties, but other properties (e.g.,
- cursor_color) are dependent upon them. */
- /* Process default font as well, since fringe widths depends on it. */
- for (p = 0; p < i; p++)
- {
- Lisp_Object prop, val;
-
- prop = parms[p];
- val = values[p];
- if (EQ (prop, Qforeground_color)
- || EQ (prop, Qbackground_color)
- || EQ (prop, Qfont))
- {
- register Lisp_Object param_index, old_value;
-
- param_index = Fget (prop, Qx_frame_parameter);
- old_value = get_frame_param (f, prop);
- store_frame_param (f, prop, val);
- if (NATNUMP (param_index)
- && (XFASTINT (param_index)
- < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
- (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
- }
- }
-
- /* Now process them in reverse of specified order. */
- for (i--; i >= 0; i--)
- {
- Lisp_Object prop, val;
-
- prop = parms[i];
- val = values[i];
-
- if (EQ (prop, Qwidth) && NUMBERP (val))
- width = XFASTINT (val);
- else if (EQ (prop, Qheight) && NUMBERP (val))
- height = XFASTINT (val);
- else if (EQ (prop, Qtop))
- top = val;
- else if (EQ (prop, Qleft))
- left = val;
- else if (EQ (prop, Qicon_top))
- icon_top = val;
- else if (EQ (prop, Qicon_left))
- icon_left = val;
- else if (EQ (prop, Qforeground_color)
- || EQ (prop, Qbackground_color)
- || EQ (prop, Qfont))
- /* Processed above. */
- continue;
- else
- {
- register Lisp_Object param_index, old_value;
-
- param_index = Fget (prop, Qx_frame_parameter);
- old_value = get_frame_param (f, prop);
- store_frame_param (f, prop, val);
- if (NATNUMP (param_index)
- && (XFASTINT (param_index)
- < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
- (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
- }
- }
-
- /* Don't die if just one of these was set. */
- if (EQ (left, Qunbound))
- {
- left_no_change = 1;
- if (f->output_data.mac->left_pos < 0)
- left = Fcons (Qplus,
- Fcons (make_number (f->output_data.mac->left_pos),
- Qnil));
- else
- XSETINT (left, f->output_data.mac->left_pos);
- }
- if (EQ (top, Qunbound))
- {
- top_no_change = 1;
- if (f->output_data.mac->top_pos < 0)
- top = Fcons (Qplus,
- Fcons (make_number (f->output_data.mac->top_pos), Qnil));
- else
- XSETINT (top, f->output_data.mac->top_pos);
- }
-
- /* If one of the icon positions was not set, preserve or default it. */
- if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
- {
- icon_left_no_change = 1;
- icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
- if (NILP (icon_left))
- XSETINT (icon_left, 0);
- }
- if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
- {
- icon_top_no_change = 1;
- icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
- if (NILP (icon_top))
- XSETINT (icon_top, 0);
- }
-
- /* Don't set these parameters unless they've been explicitly
- specified. The window might be mapped or resized while we're in
- this function, and we don't want to override that unless the lisp
- code has asked for it.
-
- Don't set these parameters unless they actually differ from the
- window's current parameters; the window may not actually exist
- yet. */
- {
- Lisp_Object frame;
-
- check_frame_size (f, &height, &width);
-
- XSETFRAME (frame, f);
-
- if (width != FRAME_WIDTH (f)
- || height != FRAME_HEIGHT (f)
- || FRAME_NEW_HEIGHT (f) || FRAME_NEW_WIDTH (f))
- Fset_frame_size (frame, make_number (width), make_number (height));
-
- if ((!NILP (left) || !NILP (top))
- && ! (left_no_change && top_no_change)
- && ! (NUMBERP (left) && XINT (left) == f->output_data.mac->left_pos
- && NUMBERP (top) && XINT (top) == f->output_data.mac->top_pos))
- {
- int leftpos = 0;
- int toppos = 0;
-
- /* Record the signs. */
- f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
- if (EQ (left, Qminus))
- f->output_data.mac->size_hint_flags |= XNegative;
- else if (INTEGERP (left))
- {
- leftpos = XINT (left);
- if (leftpos < 0)
- f->output_data.mac->size_hint_flags |= XNegative;
- }
- else if (CONSP (left) && EQ (XCAR (left), Qminus)
- && CONSP (XCDR (left))
- && INTEGERP (XCAR (XCDR (left))))
- {
- leftpos = - XINT (XCAR (XCDR (left)));
- f->output_data.mac->size_hint_flags |= XNegative;
- }
- else if (CONSP (left) && EQ (XCAR (left), Qplus)
- && CONSP (XCDR (left))
- && INTEGERP (XCAR (XCDR (left))))
- {
- leftpos = XINT (XCAR (XCDR (left)));
- }
-
- if (EQ (top, Qminus))
- f->output_data.mac->size_hint_flags |= YNegative;
- else if (INTEGERP (top))
- {
- toppos = XINT (top);
- if (toppos < 0)
- f->output_data.mac->size_hint_flags |= YNegative;
- }
- else if (CONSP (top) && EQ (XCAR (top), Qminus)
- && CONSP (XCDR (top))
- && INTEGERP (XCAR (XCDR (top))))
- {
- toppos = - XINT (XCAR (XCDR (top)));
- f->output_data.mac->size_hint_flags |= YNegative;
- }
- else if (CONSP (top) && EQ (XCAR (top), Qplus)
- && CONSP (XCDR (top))
- && INTEGERP (XCAR (XCDR (top))))
- {
- toppos = XINT (XCAR (XCDR (top)));
- }
-
-
- /* Store the numeric value of the position. */
- f->output_data.mac->top_pos = toppos;
- f->output_data.mac->left_pos = leftpos;
-
- f->output_data.mac->win_gravity = NorthWestGravity;
-
- /* Actually set that position, and convert to absolute. */
- x_set_offset (f, leftpos, toppos, -1);
- }
-
- if ((!NILP (icon_left) || !NILP (icon_top))
- && ! (icon_left_no_change && icon_top_no_change))
- x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
- }
-
- UNGCPRO;
-}
-
-/* Store the screen positions of frame F into XPTR and YPTR.
- These are the positions of the containing window manager window,
- not Emacs's own window. */
-
-void
-x_real_positions (f, xptr, yptr)
- FRAME_PTR f;
- int *xptr, *yptr;
-{
- Point pt;
- GrafPtr oldport;
-
- SetPt (&pt,
- f->output_data.mac->mWP->portRect.left,
- f->output_data.mac->mWP->portRect.top);
- GetPort (&oldport);
- LocalToGlobal (&pt);
- SetPort (oldport);
-
- *xptr = pt.h;
- *yptr = pt.v;
-}
-
-/* Insert a description of internally-recorded parameters of frame X
- into the parameter alist *ALISTPTR that is to be given to the user.
- Only parameters that are specific to Mac and whose values are not
- correctly recorded in the frame's param_alist need to be considered
- here. */
-
-void
-x_report_frame_params (f, alistptr)
- struct frame *f;
- Lisp_Object *alistptr;
-{
- char buf[16];
- Lisp_Object tem;
-
- /* Represent negative positions (off the top or left screen edge)
- in a way that Fmodify_frame_parameters will understand correctly. */
- XSETINT (tem, f->output_data.mac->left_pos);
- if (f->output_data.mac->left_pos >= 0)
- store_in_alist (alistptr, Qleft, tem);
- else
- store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
-
- XSETINT (tem, f->output_data.mac->top_pos);
- if (f->output_data.mac->top_pos >= 0)
- store_in_alist (alistptr, Qtop, tem);
- else
- store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
-
- store_in_alist (alistptr, Qborder_width,
- make_number (f->output_data.mac->border_width));
- store_in_alist (alistptr, Qinternal_border_width,
- make_number (f->output_data.mac->internal_border_width));
- store_in_alist (alistptr, Qleft_fringe,
- make_number (f->output_data.mac->left_fringe_width));
- store_in_alist (alistptr, Qright_fringe,
- make_number (f->output_data.mac->right_fringe_width));
- store_in_alist (alistptr, Qscroll_bar_width,
- make_number (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
- ? FRAME_SCROLL_BAR_PIXEL_WIDTH(f)
- : 0));
- sprintf (buf, "%ld", (long) FRAME_MAC_WINDOW (f));
- store_in_alist (alistptr, Qwindow_id,
- build_string (buf));
- store_in_alist (alistptr, Qicon_name, f->icon_name);
- FRAME_SAMPLE_VISIBILITY (f);
- store_in_alist (alistptr, Qvisibility,
- (FRAME_VISIBLE_P (f) ? Qt
- : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
- store_in_alist (alistptr, Qdisplay,
- XCAR (FRAME_MAC_DISPLAY_INFO (f)->name_list_element));
-}
-\f
-/* The default colors for the Mac color map */
-typedef struct colormap_t
-{
- unsigned long color;
- char *name;
-} colormap_t;
-
-colormap_t mac_color_map[] =
-{
- { RGB_TO_ULONG(255, 250, 250), "snow" },
- { RGB_TO_ULONG(248, 248, 255), "ghost white" },
- { RGB_TO_ULONG(248, 248, 255), "GhostWhite" },
- { RGB_TO_ULONG(245, 245, 245), "white smoke" },
- { RGB_TO_ULONG(245, 245, 245), "WhiteSmoke" },
- { RGB_TO_ULONG(220, 220, 220), "gainsboro" },
- { RGB_TO_ULONG(255, 250, 240), "floral white" },
- { RGB_TO_ULONG(255, 250, 240), "FloralWhite" },
- { RGB_TO_ULONG(253, 245, 230), "old lace" },
- { RGB_TO_ULONG(253, 245, 230), "OldLace" },
- { RGB_TO_ULONG(250, 240, 230), "linen" },
- { RGB_TO_ULONG(250, 235, 215), "antique white" },
- { RGB_TO_ULONG(250, 235, 215), "AntiqueWhite" },
- { RGB_TO_ULONG(255, 239, 213), "papaya whip" },
- { RGB_TO_ULONG(255, 239, 213), "PapayaWhip" },
- { RGB_TO_ULONG(255, 235, 205), "blanched almond" },
- { RGB_TO_ULONG(255, 235, 205), "BlanchedAlmond" },
- { RGB_TO_ULONG(255, 228, 196), "bisque" },
- { RGB_TO_ULONG(255, 218, 185), "peach puff" },
- { RGB_TO_ULONG(255, 218, 185), "PeachPuff" },
- { RGB_TO_ULONG(255, 222, 173), "navajo white" },
- { RGB_TO_ULONG(255, 222, 173), "NavajoWhite" },
- { RGB_TO_ULONG(255, 228, 181), "moccasin" },
- { RGB_TO_ULONG(255, 248, 220), "cornsilk" },
- { RGB_TO_ULONG(255, 255, 240), "ivory" },
- { RGB_TO_ULONG(255, 250, 205), "lemon chiffon" },
- { RGB_TO_ULONG(255, 250, 205), "LemonChiffon" },
- { RGB_TO_ULONG(255, 245, 238), "seashell" },
- { RGB_TO_ULONG(240, 255, 240), "honeydew" },
- { RGB_TO_ULONG(245, 255, 250), "mint cream" },
- { RGB_TO_ULONG(245, 255, 250), "MintCream" },
- { RGB_TO_ULONG(240, 255, 255), "azure" },
- { RGB_TO_ULONG(240, 248, 255), "alice blue" },
- { RGB_TO_ULONG(240, 248, 255), "AliceBlue" },
- { RGB_TO_ULONG(230, 230, 250), "lavender" },
- { RGB_TO_ULONG(255, 240, 245), "lavender blush" },
- { RGB_TO_ULONG(255, 240, 245), "LavenderBlush" },
- { RGB_TO_ULONG(255, 228, 225), "misty rose" },
- { RGB_TO_ULONG(255, 228, 225), "MistyRose" },
- { RGB_TO_ULONG(255, 255, 255), "white" },
- { RGB_TO_ULONG(0 , 0 , 0 ), "black" },
- { RGB_TO_ULONG(47 , 79 , 79 ), "dark slate gray" },
- { RGB_TO_ULONG(47 , 79 , 79 ), "DarkSlateGray" },
- { RGB_TO_ULONG(47 , 79 , 79 ), "dark slate grey" },
- { RGB_TO_ULONG(47 , 79 , 79 ), "DarkSlateGrey" },
- { RGB_TO_ULONG(105, 105, 105), "dim gray" },
- { RGB_TO_ULONG(105, 105, 105), "DimGray" },
- { RGB_TO_ULONG(105, 105, 105), "dim grey" },
- { RGB_TO_ULONG(105, 105, 105), "DimGrey" },
- { RGB_TO_ULONG(112, 128, 144), "slate gray" },
- { RGB_TO_ULONG(112, 128, 144), "SlateGray" },
- { RGB_TO_ULONG(112, 128, 144), "slate grey" },
- { RGB_TO_ULONG(112, 128, 144), "SlateGrey" },
- { RGB_TO_ULONG(119, 136, 153), "light slate gray" },
- { RGB_TO_ULONG(119, 136, 153), "LightSlateGray" },
- { RGB_TO_ULONG(119, 136, 153), "light slate grey" },
- { RGB_TO_ULONG(119, 136, 153), "LightSlateGrey" },
- { RGB_TO_ULONG(190, 190, 190), "gray" },
- { RGB_TO_ULONG(190, 190, 190), "grey" },
- { RGB_TO_ULONG(211, 211, 211), "light grey" },
- { RGB_TO_ULONG(211, 211, 211), "LightGrey" },
- { RGB_TO_ULONG(211, 211, 211), "light gray" },
- { RGB_TO_ULONG(211, 211, 211), "LightGray" },
- { RGB_TO_ULONG(25 , 25 , 112), "midnight blue" },
- { RGB_TO_ULONG(25 , 25 , 112), "MidnightBlue" },
- { RGB_TO_ULONG(0 , 0 , 128), "navy" },
- { RGB_TO_ULONG(0 , 0 , 128), "navy blue" },
- { RGB_TO_ULONG(0 , 0 , 128), "NavyBlue" },
- { RGB_TO_ULONG(100, 149, 237), "cornflower blue" },
- { RGB_TO_ULONG(100, 149, 237), "CornflowerBlue" },
- { RGB_TO_ULONG(72 , 61 , 139), "dark slate blue" },
- { RGB_TO_ULONG(72 , 61 , 139), "DarkSlateBlue" },
- { RGB_TO_ULONG(106, 90 , 205), "slate blue" },
- { RGB_TO_ULONG(106, 90 , 205), "SlateBlue" },
- { RGB_TO_ULONG(123, 104, 238), "medium slate blue" },
- { RGB_TO_ULONG(123, 104, 238), "MediumSlateBlue" },
- { RGB_TO_ULONG(132, 112, 255), "light slate blue" },
- { RGB_TO_ULONG(132, 112, 255), "LightSlateBlue" },
- { RGB_TO_ULONG(0 , 0 , 205), "medium blue" },
- { RGB_TO_ULONG(0 , 0 , 205), "MediumBlue" },
- { RGB_TO_ULONG(65 , 105, 225), "royal blue" },
- { RGB_TO_ULONG(65 , 105, 225), "RoyalBlue" },
- { RGB_TO_ULONG(0 , 0 , 255), "blue" },
- { RGB_TO_ULONG(30 , 144, 255), "dodger blue" },
- { RGB_TO_ULONG(30 , 144, 255), "DodgerBlue" },
- { RGB_TO_ULONG(0 , 191, 255), "deep sky blue" },
- { RGB_TO_ULONG(0 , 191, 255), "DeepSkyBlue" },
- { RGB_TO_ULONG(135, 206, 235), "sky blue" },
- { RGB_TO_ULONG(135, 206, 235), "SkyBlue" },
- { RGB_TO_ULONG(135, 206, 250), "light sky blue" },
- { RGB_TO_ULONG(135, 206, 250), "LightSkyBlue" },
- { RGB_TO_ULONG(70 , 130, 180), "steel blue" },
- { RGB_TO_ULONG(70 , 130, 180), "SteelBlue" },
- { RGB_TO_ULONG(176, 196, 222), "light steel blue" },
- { RGB_TO_ULONG(176, 196, 222), "LightSteelBlue" },
- { RGB_TO_ULONG(173, 216, 230), "light blue" },
- { RGB_TO_ULONG(173, 216, 230), "LightBlue" },
- { RGB_TO_ULONG(176, 224, 230), "powder blue" },
- { RGB_TO_ULONG(176, 224, 230), "PowderBlue" },
- { RGB_TO_ULONG(175, 238, 238), "pale turquoise" },
- { RGB_TO_ULONG(175, 238, 238), "PaleTurquoise" },
- { RGB_TO_ULONG(0 , 206, 209), "dark turquoise" },
- { RGB_TO_ULONG(0 , 206, 209), "DarkTurquoise" },
- { RGB_TO_ULONG(72 , 209, 204), "medium turquoise" },
- { RGB_TO_ULONG(72 , 209, 204), "MediumTurquoise" },
- { RGB_TO_ULONG(64 , 224, 208), "turquoise" },
- { RGB_TO_ULONG(0 , 255, 255), "cyan" },
- { RGB_TO_ULONG(224, 255, 255), "light cyan" },
- { RGB_TO_ULONG(224, 255, 255), "LightCyan" },
- { RGB_TO_ULONG(95 , 158, 160), "cadet blue" },
- { RGB_TO_ULONG(95 , 158, 160), "CadetBlue" },
- { RGB_TO_ULONG(102, 205, 170), "medium aquamarine" },
- { RGB_TO_ULONG(102, 205, 170), "MediumAquamarine" },
- { RGB_TO_ULONG(127, 255, 212), "aquamarine" },
- { RGB_TO_ULONG(0 , 100, 0 ), "dark green" },
- { RGB_TO_ULONG(0 , 100, 0 ), "DarkGreen" },
- { RGB_TO_ULONG(85 , 107, 47 ), "dark olive green" },
- { RGB_TO_ULONG(85 , 107, 47 ), "DarkOliveGreen" },
- { RGB_TO_ULONG(143, 188, 143), "dark sea green" },
- { RGB_TO_ULONG(143, 188, 143), "DarkSeaGreen" },
- { RGB_TO_ULONG(46 , 139, 87 ), "sea green" },
- { RGB_TO_ULONG(46 , 139, 87 ), "SeaGreen" },
- { RGB_TO_ULONG(60 , 179, 113), "medium sea green" },
- { RGB_TO_ULONG(60 , 179, 113), "MediumSeaGreen" },
- { RGB_TO_ULONG(32 , 178, 170), "light sea green" },
- { RGB_TO_ULONG(32 , 178, 170), "LightSeaGreen" },
- { RGB_TO_ULONG(152, 251, 152), "pale green" },
- { RGB_TO_ULONG(152, 251, 152), "PaleGreen" },
- { RGB_TO_ULONG(0 , 255, 127), "spring green" },
- { RGB_TO_ULONG(0 , 255, 127), "SpringGreen" },
- { RGB_TO_ULONG(124, 252, 0 ), "lawn green" },
- { RGB_TO_ULONG(124, 252, 0 ), "LawnGreen" },
- { RGB_TO_ULONG(0 , 255, 0 ), "green" },
- { RGB_TO_ULONG(127, 255, 0 ), "chartreuse" },
- { RGB_TO_ULONG(0 , 250, 154), "medium spring green" },
- { RGB_TO_ULONG(0 , 250, 154), "MediumSpringGreen" },
- { RGB_TO_ULONG(173, 255, 47 ), "green yellow" },
- { RGB_TO_ULONG(173, 255, 47 ), "GreenYellow" },
- { RGB_TO_ULONG(50 , 205, 50 ), "lime green" },
- { RGB_TO_ULONG(50 , 205, 50 ), "LimeGreen" },
- { RGB_TO_ULONG(154, 205, 50 ), "yellow green" },
- { RGB_TO_ULONG(154, 205, 50 ), "YellowGreen" },
- { RGB_TO_ULONG(34 , 139, 34 ), "forest green" },
- { RGB_TO_ULONG(34 , 139, 34 ), "ForestGreen" },
- { RGB_TO_ULONG(107, 142, 35 ), "olive drab" },
- { RGB_TO_ULONG(107, 142, 35 ), "OliveDrab" },
- { RGB_TO_ULONG(189, 183, 107), "dark khaki" },
- { RGB_TO_ULONG(189, 183, 107), "DarkKhaki" },
- { RGB_TO_ULONG(240, 230, 140), "khaki" },
- { RGB_TO_ULONG(238, 232, 170), "pale goldenrod" },
- { RGB_TO_ULONG(238, 232, 170), "PaleGoldenrod" },
- { RGB_TO_ULONG(250, 250, 210), "light goldenrod yellow" },
- { RGB_TO_ULONG(250, 250, 210), "LightGoldenrodYellow" },
- { RGB_TO_ULONG(255, 255, 224), "light yellow" },
- { RGB_TO_ULONG(255, 255, 224), "LightYellow" },
- { RGB_TO_ULONG(255, 255, 0 ), "yellow" },
- { RGB_TO_ULONG(255, 215, 0 ), "gold" },
- { RGB_TO_ULONG(238, 221, 130), "light goldenrod" },
- { RGB_TO_ULONG(238, 221, 130), "LightGoldenrod" },
- { RGB_TO_ULONG(218, 165, 32 ), "goldenrod" },
- { RGB_TO_ULONG(184, 134, 11 ), "dark goldenrod" },
- { RGB_TO_ULONG(184, 134, 11 ), "DarkGoldenrod" },
- { RGB_TO_ULONG(188, 143, 143), "rosy brown" },
- { RGB_TO_ULONG(188, 143, 143), "RosyBrown" },
- { RGB_TO_ULONG(205, 92 , 92 ), "indian red" },
- { RGB_TO_ULONG(205, 92 , 92 ), "IndianRed" },
- { RGB_TO_ULONG(139, 69 , 19 ), "saddle brown" },
- { RGB_TO_ULONG(139, 69 , 19 ), "SaddleBrown" },
- { RGB_TO_ULONG(160, 82 , 45 ), "sienna" },
- { RGB_TO_ULONG(205, 133, 63 ), "peru" },
- { RGB_TO_ULONG(222, 184, 135), "burlywood" },
- { RGB_TO_ULONG(245, 245, 220), "beige" },
- { RGB_TO_ULONG(245, 222, 179), "wheat" },
- { RGB_TO_ULONG(244, 164, 96 ), "sandy brown" },
- { RGB_TO_ULONG(244, 164, 96 ), "SandyBrown" },
- { RGB_TO_ULONG(210, 180, 140), "tan" },
- { RGB_TO_ULONG(210, 105, 30 ), "chocolate" },
- { RGB_TO_ULONG(178, 34 , 34 ), "firebrick" },
- { RGB_TO_ULONG(165, 42 , 42 ), "brown" },
- { RGB_TO_ULONG(233, 150, 122), "dark salmon" },
- { RGB_TO_ULONG(233, 150, 122), "DarkSalmon" },
- { RGB_TO_ULONG(250, 128, 114), "salmon" },
- { RGB_TO_ULONG(255, 160, 122), "light salmon" },
- { RGB_TO_ULONG(255, 160, 122), "LightSalmon" },
- { RGB_TO_ULONG(255, 165, 0 ), "orange" },
- { RGB_TO_ULONG(255, 140, 0 ), "dark orange" },
- { RGB_TO_ULONG(255, 140, 0 ), "DarkOrange" },
- { RGB_TO_ULONG(255, 127, 80 ), "coral" },
- { RGB_TO_ULONG(240, 128, 128), "light coral" },
- { RGB_TO_ULONG(240, 128, 128), "LightCoral" },
- { RGB_TO_ULONG(255, 99 , 71 ), "tomato" },
- { RGB_TO_ULONG(255, 69 , 0 ), "orange red" },
- { RGB_TO_ULONG(255, 69 , 0 ), "OrangeRed" },
- { RGB_TO_ULONG(255, 0 , 0 ), "red" },
- { RGB_TO_ULONG(255, 105, 180), "hot pink" },
- { RGB_TO_ULONG(255, 105, 180), "HotPink" },
- { RGB_TO_ULONG(255, 20 , 147), "deep pink" },
- { RGB_TO_ULONG(255, 20 , 147), "DeepPink" },
- { RGB_TO_ULONG(255, 192, 203), "pink" },
- { RGB_TO_ULONG(255, 182, 193), "light pink" },
- { RGB_TO_ULONG(255, 182, 193), "LightPink" },
- { RGB_TO_ULONG(219, 112, 147), "pale violet red" },
- { RGB_TO_ULONG(219, 112, 147), "PaleVioletRed" },
- { RGB_TO_ULONG(176, 48 , 96 ), "maroon" },
- { RGB_TO_ULONG(199, 21 , 133), "medium violet red" },
- { RGB_TO_ULONG(199, 21 , 133), "MediumVioletRed" },
- { RGB_TO_ULONG(208, 32 , 144), "violet red" },
- { RGB_TO_ULONG(208, 32 , 144), "VioletRed" },
- { RGB_TO_ULONG(255, 0 , 255), "magenta" },
- { RGB_TO_ULONG(238, 130, 238), "violet" },
- { RGB_TO_ULONG(221, 160, 221), "plum" },
- { RGB_TO_ULONG(218, 112, 214), "orchid" },
- { RGB_TO_ULONG(186, 85 , 211), "medium orchid" },
- { RGB_TO_ULONG(186, 85 , 211), "MediumOrchid" },
- { RGB_TO_ULONG(153, 50 , 204), "dark orchid" },
- { RGB_TO_ULONG(153, 50 , 204), "DarkOrchid" },
- { RGB_TO_ULONG(148, 0 , 211), "dark violet" },
- { RGB_TO_ULONG(148, 0 , 211), "DarkViolet" },
- { RGB_TO_ULONG(138, 43 , 226), "blue violet" },
- { RGB_TO_ULONG(138, 43 , 226), "BlueViolet" },
- { RGB_TO_ULONG(160, 32 , 240), "purple" },
- { RGB_TO_ULONG(147, 112, 219), "medium purple" },
- { RGB_TO_ULONG(147, 112, 219), "MediumPurple" },
- { RGB_TO_ULONG(216, 191, 216), "thistle" },
- { RGB_TO_ULONG(255, 250, 250), "snow1" },
- { RGB_TO_ULONG(238, 233, 233), "snow2" },
- { RGB_TO_ULONG(205, 201, 201), "snow3" },
- { RGB_TO_ULONG(139, 137, 137), "snow4" },
- { RGB_TO_ULONG(255, 245, 238), "seashell1" },
- { RGB_TO_ULONG(238, 229, 222), "seashell2" },
- { RGB_TO_ULONG(205, 197, 191), "seashell3" },
- { RGB_TO_ULONG(139, 134, 130), "seashell4" },
- { RGB_TO_ULONG(255, 239, 219), "AntiqueWhite1" },
- { RGB_TO_ULONG(238, 223, 204), "AntiqueWhite2" },
- { RGB_TO_ULONG(205, 192, 176), "AntiqueWhite3" },
- { RGB_TO_ULONG(139, 131, 120), "AntiqueWhite4" },
- { RGB_TO_ULONG(255, 228, 196), "bisque1" },
- { RGB_TO_ULONG(238, 213, 183), "bisque2" },
- { RGB_TO_ULONG(205, 183, 158), "bisque3" },
- { RGB_TO_ULONG(139, 125, 107), "bisque4" },
- { RGB_TO_ULONG(255, 218, 185), "PeachPuff1" },
- { RGB_TO_ULONG(238, 203, 173), "PeachPuff2" },
- { RGB_TO_ULONG(205, 175, 149), "PeachPuff3" },
- { RGB_TO_ULONG(139, 119, 101), "PeachPuff4" },
- { RGB_TO_ULONG(255, 222, 173), "NavajoWhite1" },
- { RGB_TO_ULONG(238, 207, 161), "NavajoWhite2" },
- { RGB_TO_ULONG(205, 179, 139), "NavajoWhite3" },
- { RGB_TO_ULONG(139, 121, 94), "NavajoWhite4" },
- { RGB_TO_ULONG(255, 250, 205), "LemonChiffon1" },
- { RGB_TO_ULONG(238, 233, 191), "LemonChiffon2" },
- { RGB_TO_ULONG(205, 201, 165), "LemonChiffon3" },
- { RGB_TO_ULONG(139, 137, 112), "LemonChiffon4" },
- { RGB_TO_ULONG(255, 248, 220), "cornsilk1" },
- { RGB_TO_ULONG(238, 232, 205), "cornsilk2" },
- { RGB_TO_ULONG(205, 200, 177), "cornsilk3" },
- { RGB_TO_ULONG(139, 136, 120), "cornsilk4" },
- { RGB_TO_ULONG(255, 255, 240), "ivory1" },
- { RGB_TO_ULONG(238, 238, 224), "ivory2" },
- { RGB_TO_ULONG(205, 205, 193), "ivory3" },
- { RGB_TO_ULONG(139, 139, 131), "ivory4" },
- { RGB_TO_ULONG(240, 255, 240), "honeydew1" },
- { RGB_TO_ULONG(224, 238, 224), "honeydew2" },
- { RGB_TO_ULONG(193, 205, 193), "honeydew3" },
- { RGB_TO_ULONG(131, 139, 131), "honeydew4" },
- { RGB_TO_ULONG(255, 240, 245), "LavenderBlush1" },
- { RGB_TO_ULONG(238, 224, 229), "LavenderBlush2" },
- { RGB_TO_ULONG(205, 193, 197), "LavenderBlush3" },
- { RGB_TO_ULONG(139, 131, 134), "LavenderBlush4" },
- { RGB_TO_ULONG(255, 228, 225), "MistyRose1" },
- { RGB_TO_ULONG(238, 213, 210), "MistyRose2" },
- { RGB_TO_ULONG(205, 183, 181), "MistyRose3" },
- { RGB_TO_ULONG(139, 125, 123), "MistyRose4" },
- { RGB_TO_ULONG(240, 255, 255), "azure1" },
- { RGB_TO_ULONG(224, 238, 238), "azure2" },
- { RGB_TO_ULONG(193, 205, 205), "azure3" },
- { RGB_TO_ULONG(131, 139, 139), "azure4" },
- { RGB_TO_ULONG(131, 111, 255), "SlateBlue1" },
- { RGB_TO_ULONG(122, 103, 238), "SlateBlue2" },
- { RGB_TO_ULONG(105, 89 , 205), "SlateBlue3" },
- { RGB_TO_ULONG(71 , 60 , 139), "SlateBlue4" },
- { RGB_TO_ULONG(72 , 118, 255), "RoyalBlue1" },
- { RGB_TO_ULONG(67 , 110, 238), "RoyalBlue2" },
- { RGB_TO_ULONG(58 , 95 , 205), "RoyalBlue3" },
- { RGB_TO_ULONG(39 , 64 , 139), "RoyalBlue4" },
- { RGB_TO_ULONG(0 , 0 , 255), "blue1" },
- { RGB_TO_ULONG(0 , 0 , 238), "blue2" },
- { RGB_TO_ULONG(0 , 0 , 205), "blue3" },
- { RGB_TO_ULONG(0 , 0 , 139), "blue4" },
- { RGB_TO_ULONG(30 , 144, 255), "DodgerBlue1" },
- { RGB_TO_ULONG(28 , 134, 238), "DodgerBlue2" },
- { RGB_TO_ULONG(24 , 116, 205), "DodgerBlue3" },
- { RGB_TO_ULONG(16 , 78 , 139), "DodgerBlue4" },
- { RGB_TO_ULONG(99 , 184, 255), "SteelBlue1" },
- { RGB_TO_ULONG(92 , 172, 238), "SteelBlue2" },
- { RGB_TO_ULONG(79 , 148, 205), "SteelBlue3" },
- { RGB_TO_ULONG(54 , 100, 139), "SteelBlue4" },
- { RGB_TO_ULONG(0 , 191, 255), "DeepSkyBlue1" },
- { RGB_TO_ULONG(0 , 178, 238), "DeepSkyBlue2" },
- { RGB_TO_ULONG(0 , 154, 205), "DeepSkyBlue3" },
- { RGB_TO_ULONG(0 , 104, 139), "DeepSkyBlue4" },
- { RGB_TO_ULONG(135, 206, 255), "SkyBlue1" },
- { RGB_TO_ULONG(126, 192, 238), "SkyBlue2" },
- { RGB_TO_ULONG(108, 166, 205), "SkyBlue3" },
- { RGB_TO_ULONG(74 , 112, 139), "SkyBlue4" },
- { RGB_TO_ULONG(176, 226, 255), "LightSkyBlue1" },
- { RGB_TO_ULONG(164, 211, 238), "LightSkyBlue2" },
- { RGB_TO_ULONG(141, 182, 205), "LightSkyBlue3" },
- { RGB_TO_ULONG(96 , 123, 139), "LightSkyBlue4" },
- { RGB_TO_ULONG(198, 226, 255), "SlateGray1" },
- { RGB_TO_ULONG(185, 211, 238), "SlateGray2" },
- { RGB_TO_ULONG(159, 182, 205), "SlateGray3" },
- { RGB_TO_ULONG(108, 123, 139), "SlateGray4" },
- { RGB_TO_ULONG(202, 225, 255), "LightSteelBlue1" },
- { RGB_TO_ULONG(188, 210, 238), "LightSteelBlue2" },
- { RGB_TO_ULONG(162, 181, 205), "LightSteelBlue3" },
- { RGB_TO_ULONG(110, 123, 139), "LightSteelBlue4" },
- { RGB_TO_ULONG(191, 239, 255), "LightBlue1" },
- { RGB_TO_ULONG(178, 223, 238), "LightBlue2" },
- { RGB_TO_ULONG(154, 192, 205), "LightBlue3" },
- { RGB_TO_ULONG(104, 131, 139), "LightBlue4" },
- { RGB_TO_ULONG(224, 255, 255), "LightCyan1" },
- { RGB_TO_ULONG(209, 238, 238), "LightCyan2" },
- { RGB_TO_ULONG(180, 205, 205), "LightCyan3" },
- { RGB_TO_ULONG(122, 139, 139), "LightCyan4" },
- { RGB_TO_ULONG(187, 255, 255), "PaleTurquoise1" },
- { RGB_TO_ULONG(174, 238, 238), "PaleTurquoise2" },
- { RGB_TO_ULONG(150, 205, 205), "PaleTurquoise3" },
- { RGB_TO_ULONG(102, 139, 139), "PaleTurquoise4" },
- { RGB_TO_ULONG(152, 245, 255), "CadetBlue1" },
- { RGB_TO_ULONG(142, 229, 238), "CadetBlue2" },
- { RGB_TO_ULONG(122, 197, 205), "CadetBlue3" },
- { RGB_TO_ULONG(83 , 134, 139), "CadetBlue4" },
- { RGB_TO_ULONG(0 , 245, 255), "turquoise1" },
- { RGB_TO_ULONG(0 , 229, 238), "turquoise2" },
- { RGB_TO_ULONG(0 , 197, 205), "turquoise3" },
- { RGB_TO_ULONG(0 , 134, 139), "turquoise4" },
- { RGB_TO_ULONG(0 , 255, 255), "cyan1" },
- { RGB_TO_ULONG(0 , 238, 238), "cyan2" },
- { RGB_TO_ULONG(0 , 205, 205), "cyan3" },
- { RGB_TO_ULONG(0 , 139, 139), "cyan4" },
- { RGB_TO_ULONG(151, 255, 255), "DarkSlateGray1" },
- { RGB_TO_ULONG(141, 238, 238), "DarkSlateGray2" },
- { RGB_TO_ULONG(121, 205, 205), "DarkSlateGray3" },
- { RGB_TO_ULONG(82 , 139, 139), "DarkSlateGray4" },
- { RGB_TO_ULONG(127, 255, 212), "aquamarine1" },
- { RGB_TO_ULONG(118, 238, 198), "aquamarine2" },
- { RGB_TO_ULONG(102, 205, 170), "aquamarine3" },
- { RGB_TO_ULONG(69 , 139, 116), "aquamarine4" },
- { RGB_TO_ULONG(193, 255, 193), "DarkSeaGreen1" },
- { RGB_TO_ULONG(180, 238, 180), "DarkSeaGreen2" },
- { RGB_TO_ULONG(155, 205, 155), "DarkSeaGreen3" },
- { RGB_TO_ULONG(105, 139, 105), "DarkSeaGreen4" },
- { RGB_TO_ULONG(84 , 255, 159), "SeaGreen1" },
- { RGB_TO_ULONG(78 , 238, 148), "SeaGreen2" },
- { RGB_TO_ULONG(67 , 205, 128), "SeaGreen3" },
- { RGB_TO_ULONG(46 , 139, 87 ), "SeaGreen4" },
- { RGB_TO_ULONG(154, 255, 154), "PaleGreen1" },
- { RGB_TO_ULONG(144, 238, 144), "PaleGreen2" },
- { RGB_TO_ULONG(124, 205, 124), "PaleGreen3" },
- { RGB_TO_ULONG(84 , 139, 84 ), "PaleGreen4" },
- { RGB_TO_ULONG(0 , 255, 127), "SpringGreen1" },
- { RGB_TO_ULONG(0 , 238, 118), "SpringGreen2" },
- { RGB_TO_ULONG(0 , 205, 102), "SpringGreen3" },
- { RGB_TO_ULONG(0 , 139, 69 ), "SpringGreen4" },
- { RGB_TO_ULONG(0 , 255, 0 ), "green1" },
- { RGB_TO_ULONG(0 , 238, 0 ), "green2" },
- { RGB_TO_ULONG(0 , 205, 0 ), "green3" },
- { RGB_TO_ULONG(0 , 139, 0 ), "green4" },
- { RGB_TO_ULONG(127, 255, 0 ), "chartreuse1" },
- { RGB_TO_ULONG(118, 238, 0 ), "chartreuse2" },
- { RGB_TO_ULONG(102, 205, 0 ), "chartreuse3" },
- { RGB_TO_ULONG(69 , 139, 0 ), "chartreuse4" },
- { RGB_TO_ULONG(192, 255, 62 ), "OliveDrab1" },
- { RGB_TO_ULONG(179, 238, 58 ), "OliveDrab2" },
- { RGB_TO_ULONG(154, 205, 50 ), "OliveDrab3" },
- { RGB_TO_ULONG(105, 139, 34 ), "OliveDrab4" },
- { RGB_TO_ULONG(202, 255, 112), "DarkOliveGreen1" },
- { RGB_TO_ULONG(188, 238, 104), "DarkOliveGreen2" },
- { RGB_TO_ULONG(162, 205, 90 ), "DarkOliveGreen3" },
- { RGB_TO_ULONG(110, 139, 61 ), "DarkOliveGreen4" },
- { RGB_TO_ULONG(255, 246, 143), "khaki1" },
- { RGB_TO_ULONG(238, 230, 133), "khaki2" },
- { RGB_TO_ULONG(205, 198, 115), "khaki3" },
- { RGB_TO_ULONG(139, 134, 78 ), "khaki4" },
- { RGB_TO_ULONG(255, 236, 139), "LightGoldenrod1" },
- { RGB_TO_ULONG(238, 220, 130), "LightGoldenrod2" },
- { RGB_TO_ULONG(205, 190, 112), "LightGoldenrod3" },
- { RGB_TO_ULONG(139, 129, 76 ), "LightGoldenrod4" },
- { RGB_TO_ULONG(255, 255, 224), "LightYellow1" },
- { RGB_TO_ULONG(238, 238, 209), "LightYellow2" },
- { RGB_TO_ULONG(205, 205, 180), "LightYellow3" },
- { RGB_TO_ULONG(139, 139, 122), "LightYellow4" },
- { RGB_TO_ULONG(255, 255, 0 ), "yellow1" },
- { RGB_TO_ULONG(238, 238, 0 ), "yellow2" },
- { RGB_TO_ULONG(205, 205, 0 ), "yellow3" },
- { RGB_TO_ULONG(139, 139, 0 ), "yellow4" },
- { RGB_TO_ULONG(255, 215, 0 ), "gold1" },
- { RGB_TO_ULONG(238, 201, 0 ), "gold2" },
- { RGB_TO_ULONG(205, 173, 0 ), "gold3" },
- { RGB_TO_ULONG(139, 117, 0 ), "gold4" },
- { RGB_TO_ULONG(255, 193, 37 ), "goldenrod1" },
- { RGB_TO_ULONG(238, 180, 34 ), "goldenrod2" },
- { RGB_TO_ULONG(205, 155, 29 ), "goldenrod3" },
- { RGB_TO_ULONG(139, 105, 20 ), "goldenrod4" },
- { RGB_TO_ULONG(255, 185, 15 ), "DarkGoldenrod1" },
- { RGB_TO_ULONG(238, 173, 14 ), "DarkGoldenrod2" },
- { RGB_TO_ULONG(205, 149, 12 ), "DarkGoldenrod3" },
- { RGB_TO_ULONG(139, 101, 8 ), "DarkGoldenrod4" },
- { RGB_TO_ULONG(255, 193, 193), "RosyBrown1" },
- { RGB_TO_ULONG(238, 180, 180), "RosyBrown2" },
- { RGB_TO_ULONG(205, 155, 155), "RosyBrown3" },
- { RGB_TO_ULONG(139, 105, 105), "RosyBrown4" },
- { RGB_TO_ULONG(255, 106, 106), "IndianRed1" },
- { RGB_TO_ULONG(238, 99 , 99 ), "IndianRed2" },
- { RGB_TO_ULONG(205, 85 , 85 ), "IndianRed3" },
- { RGB_TO_ULONG(139, 58 , 58 ), "IndianRed4" },
- { RGB_TO_ULONG(255, 130, 71 ), "sienna1" },
- { RGB_TO_ULONG(238, 121, 66 ), "sienna2" },
- { RGB_TO_ULONG(205, 104, 57 ), "sienna3" },
- { RGB_TO_ULONG(139, 71 , 38 ), "sienna4" },
- { RGB_TO_ULONG(255, 211, 155), "burlywood1" },
- { RGB_TO_ULONG(238, 197, 145), "burlywood2" },
- { RGB_TO_ULONG(205, 170, 125), "burlywood3" },
- { RGB_TO_ULONG(139, 115, 85 ), "burlywood4" },
- { RGB_TO_ULONG(255, 231, 186), "wheat1" },
- { RGB_TO_ULONG(238, 216, 174), "wheat2" },
- { RGB_TO_ULONG(205, 186, 150), "wheat3" },
- { RGB_TO_ULONG(139, 126, 102), "wheat4" },
- { RGB_TO_ULONG(255, 165, 79 ), "tan1" },
- { RGB_TO_ULONG(238, 154, 73 ), "tan2" },
- { RGB_TO_ULONG(205, 133, 63 ), "tan3" },
- { RGB_TO_ULONG(139, 90 , 43 ), "tan4" },
- { RGB_TO_ULONG(255, 127, 36 ), "chocolate1" },
- { RGB_TO_ULONG(238, 118, 33 ), "chocolate2" },
- { RGB_TO_ULONG(205, 102, 29 ), "chocolate3" },
- { RGB_TO_ULONG(139, 69 , 19 ), "chocolate4" },
- { RGB_TO_ULONG(255, 48 , 48 ), "firebrick1" },
- { RGB_TO_ULONG(238, 44 , 44 ), "firebrick2" },
- { RGB_TO_ULONG(205, 38 , 38 ), "firebrick3" },
- { RGB_TO_ULONG(139, 26 , 26 ), "firebrick4" },
- { RGB_TO_ULONG(255, 64 , 64 ), "brown1" },
- { RGB_TO_ULONG(238, 59 , 59 ), "brown2" },
- { RGB_TO_ULONG(205, 51 , 51 ), "brown3" },
- { RGB_TO_ULONG(139, 35 , 35 ), "brown4" },
- { RGB_TO_ULONG(255, 140, 105), "salmon1" },
- { RGB_TO_ULONG(238, 130, 98 ), "salmon2" },
- { RGB_TO_ULONG(205, 112, 84 ), "salmon3" },
- { RGB_TO_ULONG(139, 76 , 57 ), "salmon4" },
- { RGB_TO_ULONG(255, 160, 122), "LightSalmon1" },
- { RGB_TO_ULONG(238, 149, 114), "LightSalmon2" },
- { RGB_TO_ULONG(205, 129, 98 ), "LightSalmon3" },
- { RGB_TO_ULONG(139, 87 , 66 ), "LightSalmon4" },
- { RGB_TO_ULONG(255, 165, 0 ), "orange1" },
- { RGB_TO_ULONG(238, 154, 0 ), "orange2" },
- { RGB_TO_ULONG(205, 133, 0 ), "orange3" },
- { RGB_TO_ULONG(139, 90 , 0 ), "orange4" },
- { RGB_TO_ULONG(255, 127, 0 ), "DarkOrange1" },
- { RGB_TO_ULONG(238, 118, 0 ), "DarkOrange2" },
- { RGB_TO_ULONG(205, 102, 0 ), "DarkOrange3" },
- { RGB_TO_ULONG(139, 69 , 0 ), "DarkOrange4" },
- { RGB_TO_ULONG(255, 114, 86 ), "coral1" },
- { RGB_TO_ULONG(238, 106, 80 ), "coral2" },
- { RGB_TO_ULONG(205, 91 , 69 ), "coral3" },
- { RGB_TO_ULONG(139, 62 , 47 ), "coral4" },
- { RGB_TO_ULONG(255, 99 , 71 ), "tomato1" },
- { RGB_TO_ULONG(238, 92 , 66 ), "tomato2" },
- { RGB_TO_ULONG(205, 79 , 57 ), "tomato3" },
- { RGB_TO_ULONG(139, 54 , 38 ), "tomato4" },
- { RGB_TO_ULONG(255, 69 , 0 ), "OrangeRed1" },
- { RGB_TO_ULONG(238, 64 , 0 ), "OrangeRed2" },
- { RGB_TO_ULONG(205, 55 , 0 ), "OrangeRed3" },
- { RGB_TO_ULONG(139, 37 , 0 ), "OrangeRed4" },
- { RGB_TO_ULONG(255, 0 , 0 ), "red1" },
- { RGB_TO_ULONG(238, 0 , 0 ), "red2" },
- { RGB_TO_ULONG(205, 0 , 0 ), "red3" },
- { RGB_TO_ULONG(139, 0 , 0 ), "red4" },
- { RGB_TO_ULONG(255, 20 , 147), "DeepPink1" },
- { RGB_TO_ULONG(238, 18 , 137), "DeepPink2" },
- { RGB_TO_ULONG(205, 16 , 118), "DeepPink3" },
- { RGB_TO_ULONG(139, 10 , 80 ), "DeepPink4" },
- { RGB_TO_ULONG(255, 110, 180), "HotPink1" },
- { RGB_TO_ULONG(238, 106, 167), "HotPink2" },
- { RGB_TO_ULONG(205, 96 , 144), "HotPink3" },
- { RGB_TO_ULONG(139, 58 , 98 ), "HotPink4" },
- { RGB_TO_ULONG(255, 181, 197), "pink1" },
- { RGB_TO_ULONG(238, 169, 184), "pink2" },
- { RGB_TO_ULONG(205, 145, 158), "pink3" },
- { RGB_TO_ULONG(139, 99 , 108), "pink4" },
- { RGB_TO_ULONG(255, 174, 185), "LightPink1" },
- { RGB_TO_ULONG(238, 162, 173), "LightPink2" },
- { RGB_TO_ULONG(205, 140, 149), "LightPink3" },
- { RGB_TO_ULONG(139, 95 , 101), "LightPink4" },
- { RGB_TO_ULONG(255, 130, 171), "PaleVioletRed1" },
- { RGB_TO_ULONG(238, 121, 159), "PaleVioletRed2" },
- { RGB_TO_ULONG(205, 104, 137), "PaleVioletRed3" },
- { RGB_TO_ULONG(139, 71 , 93 ), "PaleVioletRed4" },
- { RGB_TO_ULONG(255, 52 , 179), "maroon1" },
- { RGB_TO_ULONG(238, 48 , 167), "maroon2" },
- { RGB_TO_ULONG(205, 41 , 144), "maroon3" },
- { RGB_TO_ULONG(139, 28 , 98 ), "maroon4" },
- { RGB_TO_ULONG(255, 62 , 150), "VioletRed1" },
- { RGB_TO_ULONG(238, 58 , 140), "VioletRed2" },
- { RGB_TO_ULONG(205, 50 , 120), "VioletRed3" },
- { RGB_TO_ULONG(139, 34 , 82 ), "VioletRed4" },
- { RGB_TO_ULONG(255, 0 , 255), "magenta1" },
- { RGB_TO_ULONG(238, 0 , 238), "magenta2" },
- { RGB_TO_ULONG(205, 0 , 205), "magenta3" },
- { RGB_TO_ULONG(139, 0 , 139), "magenta4" },
- { RGB_TO_ULONG(255, 131, 250), "orchid1" },
- { RGB_TO_ULONG(238, 122, 233), "orchid2" },
- { RGB_TO_ULONG(205, 105, 201), "orchid3" },
- { RGB_TO_ULONG(139, 71 , 137), "orchid4" },
- { RGB_TO_ULONG(255, 187, 255), "plum1" },
- { RGB_TO_ULONG(238, 174, 238), "plum2" },
- { RGB_TO_ULONG(205, 150, 205), "plum3" },
- { RGB_TO_ULONG(139, 102, 139), "plum4" },
- { RGB_TO_ULONG(224, 102, 255), "MediumOrchid1" },
- { RGB_TO_ULONG(209, 95 , 238), "MediumOrchid2" },
- { RGB_TO_ULONG(180, 82 , 205), "MediumOrchid3" },
- { RGB_TO_ULONG(122, 55 , 139), "MediumOrchid4" },
- { RGB_TO_ULONG(191, 62 , 255), "DarkOrchid1" },
- { RGB_TO_ULONG(178, 58 , 238), "DarkOrchid2" },
- { RGB_TO_ULONG(154, 50 , 205), "DarkOrchid3" },
- { RGB_TO_ULONG(104, 34 , 139), "DarkOrchid4" },
- { RGB_TO_ULONG(155, 48 , 255), "purple1" },
- { RGB_TO_ULONG(145, 44 , 238), "purple2" },
- { RGB_TO_ULONG(125, 38 , 205), "purple3" },
- { RGB_TO_ULONG(85 , 26 , 139), "purple4" },
- { RGB_TO_ULONG(171, 130, 255), "MediumPurple1" },
- { RGB_TO_ULONG(159, 121, 238), "MediumPurple2" },
- { RGB_TO_ULONG(137, 104, 205), "MediumPurple3" },
- { RGB_TO_ULONG(93 , 71 , 139), "MediumPurple4" },
- { RGB_TO_ULONG(255, 225, 255), "thistle1" },
- { RGB_TO_ULONG(238, 210, 238), "thistle2" },
- { RGB_TO_ULONG(205, 181, 205), "thistle3" },
- { RGB_TO_ULONG(139, 123, 139), "thistle4" },
- { RGB_TO_ULONG(0 , 0 , 0 ), "gray0" },
- { RGB_TO_ULONG(0 , 0 , 0 ), "grey0" },
- { RGB_TO_ULONG(3 , 3 , 3 ), "gray1" },
- { RGB_TO_ULONG(3 , 3 , 3 ), "grey1" },
- { RGB_TO_ULONG(5 , 5 , 5 ), "gray2" },
- { RGB_TO_ULONG(5 , 5 , 5 ), "grey2" },
- { RGB_TO_ULONG(8 , 8 , 8 ), "gray3" },
- { RGB_TO_ULONG(8 , 8 , 8 ), "grey3" },
- { RGB_TO_ULONG(10 , 10 , 10 ), "gray4" },
- { RGB_TO_ULONG(10 , 10 , 10 ), "grey4" },
- { RGB_TO_ULONG(13 , 13 , 13 ), "gray5" },
- { RGB_TO_ULONG(13 , 13 , 13 ), "grey5" },
- { RGB_TO_ULONG(15 , 15 , 15 ), "gray6" },
- { RGB_TO_ULONG(15 , 15 , 15 ), "grey6" },
- { RGB_TO_ULONG(18 , 18 , 18 ), "gray7" },
- { RGB_TO_ULONG(18 , 18 , 18 ), "grey7" },
- { RGB_TO_ULONG(20 , 20 , 20 ), "gray8" },
- { RGB_TO_ULONG(20 , 20 , 20 ), "grey8" },
- { RGB_TO_ULONG(23 , 23 , 23 ), "gray9" },
- { RGB_TO_ULONG(23 , 23 , 23 ), "grey9" },
- { RGB_TO_ULONG(26 , 26 , 26 ), "gray10" },
- { RGB_TO_ULONG(26 , 26 , 26 ), "grey10" },
- { RGB_TO_ULONG(28 , 28 , 28 ), "gray11" },
- { RGB_TO_ULONG(28 , 28 , 28 ), "grey11" },
- { RGB_TO_ULONG(31 , 31 , 31 ), "gray12" },
- { RGB_TO_ULONG(31 , 31 , 31 ), "grey12" },
- { RGB_TO_ULONG(33 , 33 , 33 ), "gray13" },
- { RGB_TO_ULONG(33 , 33 , 33 ), "grey13" },
- { RGB_TO_ULONG(36 , 36 , 36 ), "gray14" },
- { RGB_TO_ULONG(36 , 36 , 36 ), "grey14" },
- { RGB_TO_ULONG(38 , 38 , 38 ), "gray15" },
- { RGB_TO_ULONG(38 , 38 , 38 ), "grey15" },
- { RGB_TO_ULONG(41 , 41 , 41 ), "gray16" },
- { RGB_TO_ULONG(41 , 41 , 41 ), "grey16" },
- { RGB_TO_ULONG(43 , 43 , 43 ), "gray17" },
- { RGB_TO_ULONG(43 , 43 , 43 ), "grey17" },
- { RGB_TO_ULONG(46 , 46 , 46 ), "gray18" },
- { RGB_TO_ULONG(46 , 46 , 46 ), "grey18" },
- { RGB_TO_ULONG(48 , 48 , 48 ), "gray19" },
- { RGB_TO_ULONG(48 , 48 , 48 ), "grey19" },
- { RGB_TO_ULONG(51 , 51 , 51 ), "gray20" },
- { RGB_TO_ULONG(51 , 51 , 51 ), "grey20" },
- { RGB_TO_ULONG(54 , 54 , 54 ), "gray21" },
- { RGB_TO_ULONG(54 , 54 , 54 ), "grey21" },
- { RGB_TO_ULONG(56 , 56 , 56 ), "gray22" },
- { RGB_TO_ULONG(56 , 56 , 56 ), "grey22" },
- { RGB_TO_ULONG(59 , 59 , 59 ), "gray23" },
- { RGB_TO_ULONG(59 , 59 , 59 ), "grey23" },
- { RGB_TO_ULONG(61 , 61 , 61 ), "gray24" },
- { RGB_TO_ULONG(61 , 61 , 61 ), "grey24" },
- { RGB_TO_ULONG(64 , 64 , 64 ), "gray25" },
- { RGB_TO_ULONG(64 , 64 , 64 ), "grey25" },
- { RGB_TO_ULONG(66 , 66 , 66 ), "gray26" },
- { RGB_TO_ULONG(66 , 66 , 66 ), "grey26" },
- { RGB_TO_ULONG(69 , 69 , 69 ), "gray27" },
- { RGB_TO_ULONG(69 , 69 , 69 ), "grey27" },
- { RGB_TO_ULONG(71 , 71 , 71 ), "gray28" },
- { RGB_TO_ULONG(71 , 71 , 71 ), "grey28" },
- { RGB_TO_ULONG(74 , 74 , 74 ), "gray29" },
- { RGB_TO_ULONG(74 , 74 , 74 ), "grey29" },
- { RGB_TO_ULONG(77 , 77 , 77 ), "gray30" },
- { RGB_TO_ULONG(77 , 77 , 77 ), "grey30" },
- { RGB_TO_ULONG(79 , 79 , 79 ), "gray31" },
- { RGB_TO_ULONG(79 , 79 , 79 ), "grey31" },
- { RGB_TO_ULONG(82 , 82 , 82 ), "gray32" },
- { RGB_TO_ULONG(82 , 82 , 82 ), "grey32" },
- { RGB_TO_ULONG(84 , 84 , 84 ), "gray33" },
- { RGB_TO_ULONG(84 , 84 , 84 ), "grey33" },
- { RGB_TO_ULONG(87 , 87 , 87 ), "gray34" },
- { RGB_TO_ULONG(87 , 87 , 87 ), "grey34" },
- { RGB_TO_ULONG(89 , 89 , 89 ), "gray35" },
- { RGB_TO_ULONG(89 , 89 , 89 ), "grey35" },
- { RGB_TO_ULONG(92 , 92 , 92 ), "gray36" },
- { RGB_TO_ULONG(92 , 92 , 92 ), "grey36" },
- { RGB_TO_ULONG(94 , 94 , 94 ), "gray37" },
- { RGB_TO_ULONG(94 , 94 , 94 ), "grey37" },
- { RGB_TO_ULONG(97 , 97 , 97 ), "gray38" },
- { RGB_TO_ULONG(97 , 97 , 97 ), "grey38" },
- { RGB_TO_ULONG(99 , 99 , 99 ), "gray39" },
- { RGB_TO_ULONG(99 , 99 , 99 ), "grey39" },
- { RGB_TO_ULONG(102, 102, 102), "gray40" },
- { RGB_TO_ULONG(102, 102, 102), "grey40" },
- { RGB_TO_ULONG(105, 105, 105), "gray41" },
- { RGB_TO_ULONG(105, 105, 105), "grey41" },
- { RGB_TO_ULONG(107, 107, 107), "gray42" },
- { RGB_TO_ULONG(107, 107, 107), "grey42" },
- { RGB_TO_ULONG(110, 110, 110), "gray43" },
- { RGB_TO_ULONG(110, 110, 110), "grey43" },
- { RGB_TO_ULONG(112, 112, 112), "gray44" },
- { RGB_TO_ULONG(112, 112, 112), "grey44" },
- { RGB_TO_ULONG(115, 115, 115), "gray45" },
- { RGB_TO_ULONG(115, 115, 115), "grey45" },
- { RGB_TO_ULONG(117, 117, 117), "gray46" },
- { RGB_TO_ULONG(117, 117, 117), "grey46" },
- { RGB_TO_ULONG(120, 120, 120), "gray47" },
- { RGB_TO_ULONG(120, 120, 120), "grey47" },
- { RGB_TO_ULONG(122, 122, 122), "gray48" },
- { RGB_TO_ULONG(122, 122, 122), "grey48" },
- { RGB_TO_ULONG(125, 125, 125), "gray49" },
- { RGB_TO_ULONG(125, 125, 125), "grey49" },
- { RGB_TO_ULONG(127, 127, 127), "gray50" },
- { RGB_TO_ULONG(127, 127, 127), "grey50" },
- { RGB_TO_ULONG(130, 130, 130), "gray51" },
- { RGB_TO_ULONG(130, 130, 130), "grey51" },
- { RGB_TO_ULONG(133, 133, 133), "gray52" },
- { RGB_TO_ULONG(133, 133, 133), "grey52" },
- { RGB_TO_ULONG(135, 135, 135), "gray53" },
- { RGB_TO_ULONG(135, 135, 135), "grey53" },
- { RGB_TO_ULONG(138, 138, 138), "gray54" },
- { RGB_TO_ULONG(138, 138, 138), "grey54" },
- { RGB_TO_ULONG(140, 140, 140), "gray55" },
- { RGB_TO_ULONG(140, 140, 140), "grey55" },
- { RGB_TO_ULONG(143, 143, 143), "gray56" },
- { RGB_TO_ULONG(143, 143, 143), "grey56" },
- { RGB_TO_ULONG(145, 145, 145), "gray57" },
- { RGB_TO_ULONG(145, 145, 145), "grey57" },
- { RGB_TO_ULONG(148, 148, 148), "gray58" },
- { RGB_TO_ULONG(148, 148, 148), "grey58" },
- { RGB_TO_ULONG(150, 150, 150), "gray59" },
- { RGB_TO_ULONG(150, 150, 150), "grey59" },
- { RGB_TO_ULONG(153, 153, 153), "gray60" },
- { RGB_TO_ULONG(153, 153, 153), "grey60" },
- { RGB_TO_ULONG(156, 156, 156), "gray61" },
- { RGB_TO_ULONG(156, 156, 156), "grey61" },
- { RGB_TO_ULONG(158, 158, 158), "gray62" },
- { RGB_TO_ULONG(158, 158, 158), "grey62" },
- { RGB_TO_ULONG(161, 161, 161), "gray63" },
- { RGB_TO_ULONG(161, 161, 161), "grey63" },
- { RGB_TO_ULONG(163, 163, 163), "gray64" },
- { RGB_TO_ULONG(163, 163, 163), "grey64" },
- { RGB_TO_ULONG(166, 166, 166), "gray65" },
- { RGB_TO_ULONG(166, 166, 166), "grey65" },
- { RGB_TO_ULONG(168, 168, 168), "gray66" },
- { RGB_TO_ULONG(168, 168, 168), "grey66" },
- { RGB_TO_ULONG(171, 171, 171), "gray67" },
- { RGB_TO_ULONG(171, 171, 171), "grey67" },
- { RGB_TO_ULONG(173, 173, 173), "gray68" },
- { RGB_TO_ULONG(173, 173, 173), "grey68" },
- { RGB_TO_ULONG(176, 176, 176), "gray69" },
- { RGB_TO_ULONG(176, 176, 176), "grey69" },
- { RGB_TO_ULONG(179, 179, 179), "gray70" },
- { RGB_TO_ULONG(179, 179, 179), "grey70" },
- { RGB_TO_ULONG(181, 181, 181), "gray71" },
- { RGB_TO_ULONG(181, 181, 181), "grey71" },
- { RGB_TO_ULONG(184, 184, 184), "gray72" },
- { RGB_TO_ULONG(184, 184, 184), "grey72" },
- { RGB_TO_ULONG(186, 186, 186), "gray73" },
- { RGB_TO_ULONG(186, 186, 186), "grey73" },
- { RGB_TO_ULONG(189, 189, 189), "gray74" },
- { RGB_TO_ULONG(189, 189, 189), "grey74" },
- { RGB_TO_ULONG(191, 191, 191), "gray75" },
- { RGB_TO_ULONG(191, 191, 191), "grey75" },
- { RGB_TO_ULONG(194, 194, 194), "gray76" },
- { RGB_TO_ULONG(194, 194, 194), "grey76" },
- { RGB_TO_ULONG(196, 196, 196), "gray77" },
- { RGB_TO_ULONG(196, 196, 196), "grey77" },
- { RGB_TO_ULONG(199, 199, 199), "gray78" },
- { RGB_TO_ULONG(199, 199, 199), "grey78" },
- { RGB_TO_ULONG(201, 201, 201), "gray79" },
- { RGB_TO_ULONG(201, 201, 201), "grey79" },
- { RGB_TO_ULONG(204, 204, 204), "gray80" },
- { RGB_TO_ULONG(204, 204, 204), "grey80" },
- { RGB_TO_ULONG(207, 207, 207), "gray81" },
- { RGB_TO_ULONG(207, 207, 207), "grey81" },
- { RGB_TO_ULONG(209, 209, 209), "gray82" },
- { RGB_TO_ULONG(209, 209, 209), "grey82" },
- { RGB_TO_ULONG(212, 212, 212), "gray83" },
- { RGB_TO_ULONG(212, 212, 212), "grey83" },
- { RGB_TO_ULONG(214, 214, 214), "gray84" },
- { RGB_TO_ULONG(214, 214, 214), "grey84" },
- { RGB_TO_ULONG(217, 217, 217), "gray85" },
- { RGB_TO_ULONG(217, 217, 217), "grey85" },
- { RGB_TO_ULONG(219, 219, 219), "gray86" },
- { RGB_TO_ULONG(219, 219, 219), "grey86" },
- { RGB_TO_ULONG(222, 222, 222), "gray87" },
- { RGB_TO_ULONG(222, 222, 222), "grey87" },
- { RGB_TO_ULONG(224, 224, 224), "gray88" },
- { RGB_TO_ULONG(224, 224, 224), "grey88" },
- { RGB_TO_ULONG(227, 227, 227), "gray89" },
- { RGB_TO_ULONG(227, 227, 227), "grey89" },
- { RGB_TO_ULONG(229, 229, 229), "gray90" },
- { RGB_TO_ULONG(229, 229, 229), "grey90" },
- { RGB_TO_ULONG(232, 232, 232), "gray91" },
- { RGB_TO_ULONG(232, 232, 232), "grey91" },
- { RGB_TO_ULONG(235, 235, 235), "gray92" },
- { RGB_TO_ULONG(235, 235, 235), "grey92" },
- { RGB_TO_ULONG(237, 237, 237), "gray93" },
- { RGB_TO_ULONG(237, 237, 237), "grey93" },
- { RGB_TO_ULONG(240, 240, 240), "gray94" },
- { RGB_TO_ULONG(240, 240, 240), "grey94" },
- { RGB_TO_ULONG(242, 242, 242), "gray95" },
- { RGB_TO_ULONG(242, 242, 242), "grey95" },
- { RGB_TO_ULONG(245, 245, 245), "gray96" },
- { RGB_TO_ULONG(245, 245, 245), "grey96" },
- { RGB_TO_ULONG(247, 247, 247), "gray97" },
- { RGB_TO_ULONG(247, 247, 247), "grey97" },
- { RGB_TO_ULONG(250, 250, 250), "gray98" },
- { RGB_TO_ULONG(250, 250, 250), "grey98" },
- { RGB_TO_ULONG(252, 252, 252), "gray99" },
- { RGB_TO_ULONG(252, 252, 252), "grey99" },
- { RGB_TO_ULONG(255, 255, 255), "gray100" },
- { RGB_TO_ULONG(255, 255, 255), "grey100" },
- { RGB_TO_ULONG(169, 169, 169), "dark grey" },
- { RGB_TO_ULONG(169, 169, 169), "DarkGrey" },
- { RGB_TO_ULONG(169, 169, 169), "dark gray" },
- { RGB_TO_ULONG(169, 169, 169), "DarkGray" },
- { RGB_TO_ULONG(0 , 0 , 139), "dark blue" },
- { RGB_TO_ULONG(0 , 0 , 139), "DarkBlue" },
- { RGB_TO_ULONG(0 , 139, 139), "dark cyan" },
- { RGB_TO_ULONG(0 , 139, 139), "DarkCyan" },
- { RGB_TO_ULONG(139, 0 , 139), "dark magenta" },
- { RGB_TO_ULONG(139, 0 , 139), "DarkMagenta" },
- { RGB_TO_ULONG(139, 0 , 0 ), "dark red" },
- { RGB_TO_ULONG(139, 0 , 0 ), "DarkRed" },
- { RGB_TO_ULONG(144, 238, 144), "light green" },
- { RGB_TO_ULONG(144, 238, 144), "LightGreen" }
-};
-
-unsigned long
-mac_color_map_lookup (colorname)
- char *colorname;
-{
- Lisp_Object ret = Qnil;
- int i;
-
- BLOCK_INPUT;
-
- for (i = 0; i < sizeof (mac_color_map) / sizeof (mac_color_map[0]); i++)
- if (stricmp (colorname, mac_color_map[i].name) == 0)
- {
- ret = mac_color_map[i].color;
- break;
- }
-
- UNBLOCK_INPUT;
-
- return ret;
-}
-
-Lisp_Object
-x_to_mac_color (colorname)
- char * colorname;
-{
- register Lisp_Object tail, ret = Qnil;
-
- BLOCK_INPUT;
-
- if (colorname[0] == '#')
- {
- /* Could be an old-style RGB Device specification. */
- char *color;
- int size;
- color = colorname + 1;
-
- size = strlen(color);
- if (size == 3 || size == 6 || size == 9 || size == 12)
- {
- unsigned long colorval;
- int i, pos;
- pos = 0;
- size /= 3;
- colorval = 0;
-
- for (i = 0; i < 3; i++)
- {
- char *end;
- char t;
- unsigned long value;
-
- /* The check for 'x' in the following conditional takes into
- account the fact that strtol allows a "0x" in front of
- our numbers, and we don't. */
- if (!isxdigit(color[0]) || color[1] == 'x')
- break;
- t = color[size];
- color[size] = '\0';
- value = strtoul(color, &end, 16);
- color[size] = t;
- if (errno == ERANGE || end - color != size)
- break;
- switch (size)
- {
- case 1:
- value = value * 0x10;
- break;
- case 2:
- break;
- case 3:
- value /= 0x10;
- break;
- case 4:
- value /= 0x100;
- break;
- }
- colorval |= (value << pos);
- pos += 0x8;
- if (i == 2)
- {
- UNBLOCK_INPUT;
- return (colorval);
- }
- color = end;
- }
- }
- }
- else if (strnicmp(colorname, "rgb:", 4) == 0)
- {
- char *color;
- unsigned long colorval;
- int i, pos;
- pos = 0;
-
- colorval = 0;
- color = colorname + 4;
- for (i = 0; i < 3; i++)
- {
- char *end;
- unsigned long value;
-
- /* The check for 'x' in the following conditional takes into
- account the fact that strtol allows a "0x" in front of
- our numbers, and we don't. */
- if (!isxdigit(color[0]) || color[1] == 'x')
- break;
- value = strtoul(color, &end, 16);
- if (errno == ERANGE)
- break;
- switch (end - color)
- {
- case 1:
- value = value * 0x10 + value;
- break;
- case 2:
- break;
- case 3:
- value /= 0x10;
- break;
- case 4:
- value /= 0x100;
- break;
- default:
- value = ULONG_MAX;
- }
- if (value == ULONG_MAX)
- break;
- colorval |= (value << pos);
- pos += 0x8;
- if (i == 2)
- {
- if (*end != '\0')
- break;
- UNBLOCK_INPUT;
- return (colorval);
- }
- if (*end != '/')
- break;
- color = end + 1;
- }
- }
- else if (strnicmp(colorname, "rgbi:", 5) == 0)
- {
- /* This is an RGB Intensity specification. */
- char *color;
- unsigned long colorval;
- int i, pos;
- pos = 0;
-
- colorval = 0;
- color = colorname + 5;
- for (i = 0; i < 3; i++)
- {
- char *end;
- double value;
- unsigned long val;
-
- value = strtod(color, &end);
- if (errno == ERANGE)
- break;
- if (value < 0.0 || value > 1.0)
- break;
- val = (unsigned long)(0x100 * value);
- /* We used 0x100 instead of 0xFF to give an continuous
- range between 0.0 and 1.0 inclusive. The next statement
- fixes the 1.0 case. */
- if (val == 0x100)
- val = 0xFF;
- colorval |= (val << pos);
- pos += 0x8;
- if (i == 2)
- {
- if (*end != '\0')
- break;
- UNBLOCK_INPUT;
- return (colorval);
- }
- if (*end != '/')
- break;
- color = end + 1;
- }
- }
-
- ret = mac_color_map_lookup (colorname);
-
- UNBLOCK_INPUT;
- return ret;
-}
-
-/* Gamma-correct COLOR on frame F. */
-
-void
-gamma_correct (f, color)
- struct frame *f;
- unsigned long *color;
-{
- if (f->gamma)
- {
- unsigned long red, green, blue;
-
- red = pow (RED_FROM_ULONG (*color) / 255.0, f->gamma) * 255.0 + 0.5;
- green = pow (GREEN_FROM_ULONG (*color) / 255.0, f->gamma) * 255.0 + 0.5;
- blue = pow (BLUE_FROM_ULONG (*color) / 255.0, f->gamma) * 255.0 + 0.5;
- *color = RGB_TO_ULONG (red, green, blue);
- }
-}
-
-/* Decide if color named COLOR is valid for the display associated
- with the selected frame; if so, return the rgb values in COLOR_DEF.
- If ALLOC is nonzero, allocate a new colormap cell. */
-
-int
-mac_defined_color (f, color, color_def, alloc)
- FRAME_PTR f;
- char *color;
- XColor *color_def;
- int alloc;
-{
- register Lisp_Object tem;
- unsigned long mac_color_ref;
-
- tem = x_to_mac_color (color);
-
- if (!NILP (tem))
- {
- if (f)
- {
- /* Apply gamma correction. */
- mac_color_ref = XUINT (tem);
- gamma_correct (f, &mac_color_ref);
- XSETINT (tem, mac_color_ref);
- }
-
- color_def->pixel = mac_color_ref;
- color_def->red = RED_FROM_ULONG (mac_color_ref);
- color_def->green = GREEN_FROM_ULONG (mac_color_ref);
- color_def->blue = BLUE_FROM_ULONG (mac_color_ref);
-
- return 1;
- }
- else
- {
- return 0;
- }
-}
-
-/* Given a string ARG naming a color, compute a pixel value from it
- suitable for screen F.
- If F is not a color screen, return DEF (default) regardless of what
- ARG says. */
-
-int
-x_decode_color (f, arg, def)
- FRAME_PTR f;
- Lisp_Object arg;
- int def;
-{
- XColor cdef;
-
- CHECK_STRING (arg, 0);
-
- if (strcmp (XSTRING (arg)->data, "black") == 0)
- return BLACK_PIX_DEFAULT (f);
- else if (strcmp (XSTRING (arg)->data, "white") == 0)
- return WHITE_PIX_DEFAULT (f);
-
-#if 0
- if ((FRAME_MAC_DISPLAY_INFO (f)->n_planes
- * FRAME_MAC_DISPLAY_INFO (f)->n_cbits) == 1)
- return def;
-#endif
-
- if (mac_defined_color (f, XSTRING (arg)->data, &cdef, 1))
- return cdef.pixel;
-
- /* defined_color failed; return an ultimate default. */
- return def;
-}
-\f
-/* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
- the previous value of that parameter, NEW_VALUE is the new value. */
-
-static void
-x_set_line_spacing (f, new_value, old_value)
- struct frame *f;
- Lisp_Object new_value, old_value;
-{
- if (NILP (new_value))
- f->extra_line_spacing = 0;
- else if (NATNUMP (new_value))
- f->extra_line_spacing = XFASTINT (new_value);
- else
- Fsignal (Qerror, Fcons (build_string ("Illegal line-spacing"),
- Fcons (new_value, Qnil)));
- if (FRAME_VISIBLE_P (f))
- redraw_frame (f);
-}
-
-
-/* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
- the previous value of that parameter, NEW_VALUE is the new value. */
-
-static void
-x_set_screen_gamma (f, new_value, old_value)
- struct frame *f;
- Lisp_Object new_value, old_value;
-{
- if (NILP (new_value))
- f->gamma = 0;
- else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
- /* The value 0.4545 is the normal viewing gamma. */
- f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
- else
- Fsignal (Qerror, Fcons (build_string ("Illegal screen-gamma"),
- Fcons (new_value, Qnil)));
-
- clear_face_cache (0);
-}
-
-
-/* Functions called only from `x_set_frame_param'
- to set individual parameters.
-
- If FRAME_MAC_WINDOW (f) is 0,
- the frame is being created and its window does not exist yet.
- In that case, just record the parameter's new value
- in the standard place; do not attempt to change the window. */
-
-void
-x_set_foreground_color (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- FRAME_FOREGROUND_PIXEL (f)
- = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
-
- if (FRAME_MAC_WINDOW (f) != 0)
- {
- update_face_from_frame_parameter (f, Qforeground_color, arg);
- if (FRAME_VISIBLE_P (f))
- redraw_frame (f);
- }
-}
-
-void
-x_set_background_color (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- FRAME_BACKGROUND_PIXEL (f)
- = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
-
- if (FRAME_MAC_WINDOW (f) != 0)
- {
- update_face_from_frame_parameter (f, Qbackground_color, arg);
-
- if (FRAME_VISIBLE_P (f))
- redraw_frame (f);
- }
-}
-
-void
-x_set_mouse_color (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- Cursor cursor, nontext_cursor, mode_cursor, cross_cursor;
- int count;
- int mask_color;
-
- if (!EQ (Qnil, arg))
- f->output_data.mac->mouse_pixel
- = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
- mask_color = FRAME_BACKGROUND_PIXEL (f);
-
- /* Don't let pointers be invisible. */
- if (mask_color == f->output_data.mac->mouse_pixel
- && mask_color == FRAME_BACKGROUND_PIXEL (f))
- f->output_data.mac->mouse_pixel = FRAME_FOREGROUND_PIXEL (f);
-
-#if 0 /* MAC_TODO : cursor changes */
- BLOCK_INPUT;
-
- /* It's not okay to crash if the user selects a screwy cursor. */
- count = x_catch_errors (FRAME_W32_DISPLAY (f));
-
- if (!EQ (Qnil, Vx_pointer_shape))
- {
- CHECK_NUMBER (Vx_pointer_shape, 0);
- cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XINT (Vx_pointer_shape));
- }
- else
- cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
- x_check_errors (FRAME_W32_DISPLAY (f), "bad text pointer cursor: %s");
-
- if (!EQ (Qnil, Vx_nontext_pointer_shape))
- {
- CHECK_NUMBER (Vx_nontext_pointer_shape, 0);
- nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
- XINT (Vx_nontext_pointer_shape));
- }
- else
- nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_left_ptr);
- x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
-
- if (!EQ (Qnil, Vx_hourglass_pointer_shape))
- {
- CHECK_NUMBER (Vx_hourglass_pointer_shape, 0);
- hourglass_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
- XINT (Vx_hourglass_pointer_shape));
- }
- else
- hourglass_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_watch);
- x_check_errors (FRAME_W32_DISPLAY (f), "bad busy pointer cursor: %s");
-
- x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
- if (!EQ (Qnil, Vx_mode_pointer_shape))
- {
- CHECK_NUMBER (Vx_mode_pointer_shape, 0);
- mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
- XINT (Vx_mode_pointer_shape));
- }
- else
- mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
- x_check_errors (FRAME_W32_DISPLAY (f), "bad modeline pointer cursor: %s");
-
- if (!EQ (Qnil, Vx_sensitive_text_pointer_shape))
- {
- CHECK_NUMBER (Vx_sensitive_text_pointer_shape, 0);
- cross_cursor
- = XCreateFontCursor (FRAME_W32_DISPLAY (f),
- XINT (Vx_sensitive_text_pointer_shape));
- }
- else
- cross_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_crosshair);
-
- if (!NILP (Vx_window_horizontal_drag_shape))
- {
- CHECK_NUMBER (Vx_window_horizontal_drag_shape, 0);
- horizontal_drag_cursor
- = XCreateFontCursor (FRAME_X_DISPLAY (f),
- XINT (Vx_window_horizontal_drag_shape));
- }
- else
- horizontal_drag_cursor
- = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_sb_h_double_arrow);
-
- /* Check and report errors with the above calls. */
- x_check_errors (FRAME_W32_DISPLAY (f), "can't set cursor shape: %s");
- x_uncatch_errors (FRAME_W32_DISPLAY (f), count);
-
- {
- XColor fore_color, back_color;
-
- fore_color.pixel = f->output_data.w32->mouse_pixel;
- back_color.pixel = mask_color;
- XQueryColor (FRAME_W32_DISPLAY (f),
- DefaultColormap (FRAME_W32_DISPLAY (f),
- DefaultScreen (FRAME_W32_DISPLAY (f))),
- &fore_color);
- XQueryColor (FRAME_W32_DISPLAY (f),
- DefaultColormap (FRAME_W32_DISPLAY (f),
- DefaultScreen (FRAME_W32_DISPLAY (f))),
- &back_color);
- XRecolorCursor (FRAME_W32_DISPLAY (f), cursor,
- &fore_color, &back_color);
- XRecolorCursor (FRAME_W32_DISPLAY (f), nontext_cursor,
- &fore_color, &back_color);
- XRecolorCursor (FRAME_W32_DISPLAY (f), mode_cursor,
- &fore_color, &back_color);
- XRecolorCursor (FRAME_W32_DISPLAY (f), cross_cursor,
- &fore_color, &back_color);
- XRecolorCursor (FRAME_W32_DISPLAY (f), hourglass_cursor,
- &fore_color, &back_color);
- }
-
- if (FRAME_W32_WINDOW (f) != 0)
- XDefineCursor (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f), cursor);
-
- if (cursor != f->output_data.w32->text_cursor && f->output_data.w32->text_cursor != 0)
- XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->text_cursor);
- f->output_data.w32->text_cursor = cursor;
-
- if (nontext_cursor != f->output_data.w32->nontext_cursor
- && f->output_data.w32->nontext_cursor != 0)
- XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->nontext_cursor);
- f->output_data.w32->nontext_cursor = nontext_cursor;
-
- if (hourglass_cursor != f->output_data.w32->hourglass_cursor
- && f->output_data.w32->hourglass_cursor != 0)
- XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->hourglass_cursor);
- f->output_data.w32->hourglass_cursor = hourglass_cursor;
-
- if (mode_cursor != f->output_data.w32->modeline_cursor
- && f->output_data.w32->modeline_cursor != 0)
- XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->modeline_cursor);
- f->output_data.w32->modeline_cursor = mode_cursor;
-
- if (cross_cursor != f->output_data.w32->cross_cursor
- && f->output_data.w32->cross_cursor != 0)
- XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->cross_cursor);
- f->output_data.w32->cross_cursor = cross_cursor;
-
- XFlush (FRAME_W32_DISPLAY (f));
- UNBLOCK_INPUT;
-
- update_face_from_frame_parameter (f, Qmouse_color, arg);
-#endif /* MAC_TODO */
-}
-
-void
-x_set_cursor_color (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- unsigned long fore_pixel;
-
- if (!NILP (Vx_cursor_fore_pixel))
- fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
- WHITE_PIX_DEFAULT (f));
- else
- fore_pixel = FRAME_BACKGROUND_PIXEL (f);
- f->output_data.mac->cursor_pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
-
- /* Make sure that the cursor color differs from the background color. */
- if (f->output_data.mac->cursor_pixel == FRAME_BACKGROUND_PIXEL (f))
- {
- f->output_data.mac->cursor_pixel = f->output_data.mac->mouse_pixel;
- if (f->output_data.mac->cursor_pixel == fore_pixel)
- fore_pixel = FRAME_BACKGROUND_PIXEL (f);
- }
- FRAME_FOREGROUND_PIXEL (f) = fore_pixel;
-
-#if 0 /* MAC_TODO: cannot figure out what to do (wrong number of params) */
- if (FRAME_MAC_WINDOW (f) != 0)
- {
- if (FRAME_VISIBLE_P (f))
- {
- x_display_cursor (f, 0);
- x_display_cursor (f, 1);
- }
- }
-#endif
-
- update_face_from_frame_parameter (f, Qcursor_color, arg);
-}
-
-/* Set the border-color of frame F to pixel value PIX.
- Note that this does not fully take effect if done before
- F has an window. */
-void
-x_set_border_pixel (f, pix)
- struct frame *f;
- int pix;
-{
- f->output_data.mac->border_pixel = pix;
-
- if (FRAME_MAC_WINDOW (f) != 0 && f->output_data.mac->border_width > 0)
- {
- if (FRAME_VISIBLE_P (f))
- redraw_frame (f);
- }
-}
-
-/* Set the border-color of frame F to value described by ARG.
- ARG can be a string naming a color.
- The border-color is used for the border that is drawn by the server.
- Note that this does not fully take effect if done before
- F has a window; it must be redone when the window is created. */
-
-void
-x_set_border_color (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- int pix;
-
- CHECK_STRING (arg, 0);
- pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
- x_set_border_pixel (f, pix);
- update_face_from_frame_parameter (f, Qborder_color, arg);
-}
-
-/* Value is the internal representation of the specified cursor type
- ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
- of the bar cursor. */
-
-enum text_cursor_kinds
-x_specified_cursor_type (arg, width)
- Lisp_Object arg;
- int *width;
-{
- enum text_cursor_kinds type;
-
- if (EQ (arg, Qbar))
- {
- type = BAR_CURSOR;
- *width = 2;
- }
- else if (CONSP (arg)
- && EQ (XCAR (arg), Qbar)
- && INTEGERP (XCDR (arg))
- && XINT (XCDR (arg)) >= 0)
- {
- type = BAR_CURSOR;
- *width = XINT (XCDR (arg));
- }
- else if (NILP (arg))
- type = NO_CURSOR;
- else
- /* Treat anything unknown as "box cursor".
- It was bad to signal an error; people have trouble fixing
- .Xdefaults with Emacs, when it has something bad in it. */
- type = FILLED_BOX_CURSOR;
-
- return type;
-}
-
-void
-x_set_cursor_type (f, arg, oldval)
- FRAME_PTR f;
- Lisp_Object arg, oldval;
-{
- int width;
-
- FRAME_DESIRED_CURSOR (f) = x_specified_cursor_type (arg, &width);
- f->output_data.mac->cursor_width = width;
-
- /* Make sure the cursor gets redrawn. This is overkill, but how
- often do people change cursor types? */
- update_mode_lines++;
-}
-\f
-#if 0 /* MAC_TODO: really no icon for Mac */
-void
-x_set_icon_type (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- int result;
-
- if (NILP (arg) && NILP (oldval))
- return;
-
- if (STRINGP (arg) && STRINGP (oldval)
- && EQ (Fstring_equal (oldval, arg), Qt))
- return;
-
- if (SYMBOLP (arg) && SYMBOLP (oldval) && EQ (arg, oldval))
- return;
-
- BLOCK_INPUT;
-
- result = x_bitmap_icon (f, arg);
- if (result)
- {
- UNBLOCK_INPUT;
- error ("No icon window available");
- }
-
- UNBLOCK_INPUT;
-}
-#endif
-
-/* Return non-nil if frame F wants a bitmap icon. */
-
-Lisp_Object
-x_icon_type (f)
- FRAME_PTR f;
-{
- Lisp_Object tem;
-
- tem = assq_no_quit (Qicon_type, f->param_alist);
- if (CONSP (tem))
- return XCDR (tem);
- else
- return Qnil;
-}
-
-void
-x_set_icon_name (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- int result;
-
- if (STRINGP (arg))
- {
- if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
- return;
- }
- else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
- return;
-
- f->icon_name = arg;
-
-#if 0
- if (f->output_data.w32->icon_bitmap != 0)
- return;
-
- BLOCK_INPUT;
-
- result = x_text_icon (f,
- (char *) XSTRING ((!NILP (f->icon_name)
- ? f->icon_name
- : !NILP (f->title)
- ? f->title
- : f->name))->data);
-
- if (result)
- {
- UNBLOCK_INPUT;
- error ("No icon window available");
- }
-
- /* If the window was unmapped (and its icon was mapped),
- the new icon is not mapped, so map the window in its stead. */
- if (FRAME_VISIBLE_P (f))
- {
-#ifdef USE_X_TOOLKIT
- XtPopup (f->output_data.w32->widget, XtGrabNone);
-#endif
- XMapWindow (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f));
- }
-
- XFlush (FRAME_W32_DISPLAY (f));
- UNBLOCK_INPUT;
-#endif
-}
-
-extern Lisp_Object x_new_font ();
-extern Lisp_Object x_new_fontset();
-
-void
-x_set_font (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- Lisp_Object result;
- Lisp_Object fontset_name;
- Lisp_Object frame;
-
- CHECK_STRING (arg, 1);
-
- fontset_name = Fquery_fontset (arg, Qnil);
-
- BLOCK_INPUT;
- result = (STRINGP (fontset_name)
- ? x_new_fontset (f, XSTRING (fontset_name)->data)
- : x_new_font (f, XSTRING (arg)->data));
- UNBLOCK_INPUT;
-
- if (EQ (result, Qnil))
- error ("Font `%s' is not defined", XSTRING (arg)->data);
- else if (EQ (result, Qt))
- error ("The characters of the given font have varying widths");
- else if (STRINGP (result))
- {
- if (!NILP (Fequal (result, oldval)))
- return;
- store_frame_param (f, Qfont, result);
- recompute_basic_faces (f);
- }
- else
- abort ();
-
- do_pending_window_change (0);
-
- /* Don't call `face-set-after-frame-default' when faces haven't been
- initialized yet. This is the case when called from
- Fx_create_frame. In that case, the X widget or window doesn't
- exist either, and we can end up in x_report_frame_params with a
- null widget which gives a segfault. */
- if (FRAME_FACE_CACHE (f))
- {
- XSETFRAME (frame, f);
- call1 (Qface_set_after_frame_default, frame);
- }
-}
-
-static void
-x_set_fringe_width (f, new_value, old_value)
- struct frame *f;
- Lisp_Object new_value, old_value;
-{
- x_compute_fringe_widths (f, 1);
-}
-
-void
-x_set_border_width (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- CHECK_NUMBER (arg, 0);
-
- if (XINT (arg) == f->output_data.mac->border_width)
- return;
-
-#if 0
- if (FRAME_MAC_WINDOW (f) != 0)
- error ("Cannot change the border width of a window");
-#endif
-
- f->output_data.mac->border_width = XINT (arg);
-}
-
-void
-x_set_internal_border_width (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- int old = f->output_data.mac->internal_border_width;
-
- CHECK_NUMBER (arg, 0);
- f->output_data.mac->internal_border_width = XINT (arg);
- if (f->output_data.mac->internal_border_width < 0)
- f->output_data.mac->internal_border_width = 0;
-
- if (f->output_data.mac->internal_border_width == old)
- return;
-
- if (FRAME_MAC_WINDOW (f) != 0)
- {
- x_set_window_size (f, 0, f->width, f->height);
- SET_FRAME_GARBAGED (f);
- do_pending_window_change (0);
- }
-}
-
-void
-x_set_visibility (f, value, oldval)
- struct frame *f;
- Lisp_Object value, oldval;
-{
- Lisp_Object frame;
- XSETFRAME (frame, f);
-
- if (NILP (value))
- Fmake_frame_invisible (frame, Qt);
- else if (EQ (value, Qicon))
- Ficonify_frame (frame);
- else
- Fmake_frame_visible (frame);
-}
-
-\f
-/* Change window heights in windows rooted in WINDOW by N lines. */
-
-static void
-x_change_window_heights (window, n)
- Lisp_Object window;
- int n;
-{
- struct window *w = XWINDOW (window);
-
- XSETFASTINT (w->top, XFASTINT (w->top) + n);
- XSETFASTINT (w->height, XFASTINT (w->height) - n);
-
- if (INTEGERP (w->orig_top))
- XSETFASTINT (w->orig_top, XFASTINT (w->orig_top) + n);
- if (INTEGERP (w->orig_height))
- XSETFASTINT (w->orig_height, XFASTINT (w->orig_height) - n);
-
- /* Handle just the top child in a vertical split. */
- if (!NILP (w->vchild))
- x_change_window_heights (w->vchild, n);
-
- /* Adjust all children in a horizontal split. */
- for (window = w->hchild; !NILP (window); window = w->next)
- {
- w = XWINDOW (window);
- x_change_window_heights (window, n);
- }
-}
-
-void
-x_set_menu_bar_lines (f, value, oldval)
- struct frame *f;
- Lisp_Object value, oldval;
-{
- int nlines;
- int olines = FRAME_MENU_BAR_LINES (f);
-
- /* Right now, menu bars don't work properly in minibuf-only frames;
- most of the commands try to apply themselves to the minibuffer
- frame itself, and get an error because you can't switch buffers
- in or split the minibuffer window. */
- if (FRAME_MINIBUF_ONLY_P (f))
- return;
-
- if (INTEGERP (value))
- nlines = XINT (value);
- else
- nlines = 0;
-
- FRAME_MENU_BAR_LINES (f) = 0;
- if (nlines)
- FRAME_EXTERNAL_MENU_BAR (f) = 1;
- else
- {
- if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
- free_frame_menubar (f);
- FRAME_EXTERNAL_MENU_BAR (f) = 0;
-
- /* Adjust the frame size so that the client (text) dimensions
- remain the same. This depends on FRAME_EXTERNAL_MENU_BAR being
- set correctly. */
- x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
- do_pending_window_change (0);
- }
- adjust_glyphs (f);
-}
-
-/* Set the number of lines used for the tool bar of frame F to VALUE.
- VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
- is the old number of tool bar lines. This function changes the
- height of all windows on frame F to match the new tool bar height.
- The frame's height doesn't change. */
-
-void
-x_set_tool_bar_lines (f, value, oldval)
- struct frame *f;
- Lisp_Object value, oldval;
-{
- int delta, nlines, root_height;
- Lisp_Object root_window;
-
- /* Treat tool bars like menu bars. */
- if (FRAME_MINIBUF_ONLY_P (f))
- return;
-
- /* Use VALUE only if an integer >= 0. */
- if (INTEGERP (value) && XINT (value) >= 0)
- nlines = XFASTINT (value);
- else
- nlines = 0;
-
- /* Make sure we redisplay all windows in this frame. */
- ++windows_or_buffers_changed;
-
- delta = nlines - FRAME_TOOL_BAR_LINES (f);
-
- /* Don't resize the tool-bar to more than we have room for. */
- root_window = FRAME_ROOT_WINDOW (f);
- root_height = XINT (XWINDOW (root_window)->height);
- if (root_height - delta < 1)
- {
- delta = root_height - 1;
- nlines = FRAME_TOOL_BAR_LINES (f) + delta;
- }
-
- FRAME_TOOL_BAR_LINES (f) = nlines;
- x_change_window_heights (root_window, delta);
- adjust_glyphs (f);
-
- /* We also have to make sure that the internal border at the top of
- the frame, below the menu bar or tool bar, is redrawn when the
- tool bar disappears. This is so because the internal border is
- below the tool bar if one is displayed, but is below the menu bar
- if there isn't a tool bar. The tool bar draws into the area
- below the menu bar. */
- if (FRAME_MAC_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0)
- {
- updating_frame = f;
- clear_frame ();
- clear_current_matrices (f);
- updating_frame = NULL;
- }
-
- /* If the tool bar gets smaller, the internal border below it
- has to be cleared. It was formerly part of the display
- of the larger tool bar, and updating windows won't clear it. */
- if (delta < 0)
- {
- int height = FRAME_INTERNAL_BORDER_WIDTH (f);
- int width = PIXEL_WIDTH (f);
- int y = nlines * CANON_Y_UNIT (f);
-
- BLOCK_INPUT;
- XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
- 0, y, width, height, 0);
- UNBLOCK_INPUT;
- }
-}
-
-
-/* Change the name of frame F to NAME. If NAME is nil, set F's name to
- w32_id_name.
-
- If EXPLICIT is non-zero, that indicates that lisp code is setting the
- name; if NAME is a string, set F's name to NAME and set
- F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
-
- If EXPLICIT is zero, that indicates that Emacs redisplay code is
- suggesting a new name, which lisp code should override; if
- F->explicit_name is set, ignore the new name; otherwise, set it. */
-
-void
-x_set_name (f, name, explicit)
- struct frame *f;
- Lisp_Object name;
- int explicit;
-{
- /* Make sure that requests from lisp code override requests from
- Emacs redisplay code. */
- if (explicit)
- {
- /* If we're switching from explicit to implicit, we had better
- update the mode lines and thereby update the title. */
- if (f->explicit_name && NILP (name))
- update_mode_lines = 1;
-
- f->explicit_name = ! NILP (name);
- }
- else if (f->explicit_name)
- return;
-
- /* If NAME is nil, set the name to the w32_id_name. */
- if (NILP (name))
- {
- /* Check for no change needed in this very common case
- before we do any consing. */
- if (!strcmp (FRAME_MAC_DISPLAY_INFO (f)->mac_id_name,
- XSTRING (f->name)->data))
- return;
- name = build_string (FRAME_MAC_DISPLAY_INFO (f)->mac_id_name);
- }
- else
- CHECK_STRING (name, 0);
-
- /* Don't change the name if it's already NAME. */
- if (! NILP (Fstring_equal (name, f->name)))
- return;
-
- f->name = name;
-
- /* For setting the frame title, the title parameter should override
- the name parameter. */
- if (! NILP (f->title))
- name = f->title;
-
- if (FRAME_MAC_WINDOW (f))
- {
- if (STRING_MULTIBYTE (name))
-#if 0 /* MAC_TODO: encoding title string */
- name = ENCODE_SYSTEM (name);
-#else
- return;
-#endif
-
- BLOCK_INPUT;
-
- {
- Str255 windowTitle;
- if (strlen (XSTRING (name)->data) < 255)
- {
- strcpy (windowTitle, XSTRING (name)->data);
- c2pstr (windowTitle);
- SetWTitle (FRAME_MAC_WINDOW (f), windowTitle);
- }
- }
-
- UNBLOCK_INPUT;
- }
-}
-
-/* This function should be called when the user's lisp code has
- specified a name for the frame; the name will override any set by the
- redisplay code. */
-void
-x_explicitly_set_name (f, arg, oldval)
- FRAME_PTR f;
- Lisp_Object arg, oldval;
-{
- x_set_name (f, arg, 1);
-}
-
-/* This function should be called by Emacs redisplay code to set the
- name; names set this way will never override names set by the user's
- lisp code. */
-void
-x_implicitly_set_name (f, arg, oldval)
- FRAME_PTR f;
- Lisp_Object arg, oldval;
-{
- x_set_name (f, arg, 0);
-}
-\f
-/* Change the title of frame F to NAME.
- If NAME is nil, use the frame name as the title.
-
- If EXPLICIT is non-zero, that indicates that lisp code is setting the
- name; if NAME is a string, set F's name to NAME and set
- F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
-
- If EXPLICIT is zero, that indicates that Emacs redisplay code is
- suggesting a new name, which lisp code should override; if
- F->explicit_name is set, ignore the new name; otherwise, set it. */
-
-void
-x_set_title (f, name, old_name)
- struct frame *f;
- Lisp_Object name, old_name;
-{
- /* Don't change the title if it's already NAME. */
- if (EQ (name, f->title))
- return;
-
- update_mode_lines = 1;
-
- f->title = name;
-
- if (NILP (name))
- name = f->name;
-
- if (FRAME_MAC_WINDOW (f))
- {
- if (STRING_MULTIBYTE (name))
-#if 0 /* MAC_TODO: encoding title string */
- name = ENCODE_SYSTEM (name);
-#else
- return;
-#endif
-
- BLOCK_INPUT;
-
- {
- Str255 windowTitle;
- if (strlen (XSTRING (name)->data) < 255)
- {
- strcpy (windowTitle, XSTRING (name)->data);
- c2pstr (windowTitle);
- SetWTitle (FRAME_MAC_WINDOW (f), windowTitle);
- }
- }
-
- UNBLOCK_INPUT;
- }
-}
-\f
-void
-x_set_autoraise (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- f->auto_raise = !EQ (Qnil, arg);
-}
-
-void
-x_set_autolower (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- f->auto_lower = !EQ (Qnil, arg);
-}
-
-void
-x_set_unsplittable (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- f->no_split = !NILP (arg);
-}
-
-void
-x_set_vertical_scroll_bars (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
- || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
- || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
- || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
- {
- FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
- = (NILP (arg)
- ? vertical_scroll_bar_none
- : EQ (Qright, arg)
- ? vertical_scroll_bar_right
- : vertical_scroll_bar_left);
-
- /* We set this parameter before creating the window for the
- frame, so we can get the geometry right from the start.
- However, if the window hasn't been created yet, we shouldn't
- call x_set_window_size. */
- if (FRAME_MAC_WINDOW (f))
- x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
- do_pending_window_change (0);
- }
-}
-
-void
-x_set_scroll_bar_width (f, arg, oldval)
- struct frame *f;
- Lisp_Object arg, oldval;
-{
- /* Imitate X without X Toolkit */
-
- int wid = FONT_WIDTH (f->output_data.mac->font);
-
- if (NILP (arg))
- {
- /* Make the actual width at least 14 pixels and a multiple of a
- character width. */
- FRAME_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
-
- /* Use all of that space (aside from required margins) for the
- scroll bar. */
- FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 0;
-
- if (FRAME_MAC_WINDOW (f))
- x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
- do_pending_window_change (0);
- }
- else if (INTEGERP (arg) && XINT (arg) > 0
- && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
- {
- if (XFASTINT (arg) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM)
- XSETINT (arg, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM + 1);
-
- FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg);
- FRAME_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
- if (FRAME_MAC_WINDOW (f))
- x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
- do_pending_window_change (0);
- }
- change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0, 0);
- XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
- XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
-}
-\f
-/* Subroutines of creating an frame. */
-
-/* Make sure that Vx_resource_name is set to a reasonable value.
- Fix it up, or set it to `emacs' if it is too hopeless. */
-
-static void
-validate_x_resource_name ()
-{
- int len = 0;
- /* Number of valid characters in the resource name. */
- int good_count = 0;
- /* Number of invalid characters in the resource name. */
- int bad_count = 0;
- Lisp_Object new;
- int i;
-
- if (STRINGP (Vx_resource_name))
- {
- unsigned char *p = XSTRING (Vx_resource_name)->data;
- int i;
-
- len = STRING_BYTES (XSTRING (Vx_resource_name));
-
- /* Only letters, digits, - and _ are valid in resource names.
- Count the valid characters and count the invalid ones. */
- for (i = 0; i < len; i++)
- {
- int c = p[i];
- if (! ((c >= 'a' && c <= 'z')
- || (c >= 'A' && c <= 'Z')
- || (c >= '0' && c <= '9')
- || c == '-' || c == '_'))
- bad_count++;
- else
- good_count++;
- }
- }
- else
- /* Not a string => completely invalid. */
- bad_count = 5, good_count = 0;
-
- /* If name is valid already, return. */
- if (bad_count == 0)
- return;
-
- /* If name is entirely invalid, or nearly so, use `emacs'. */
- if (good_count == 0
- || (good_count == 1 && bad_count > 0))
- {
- Vx_resource_name = build_string ("emacs");
- return;
- }
-
- /* Name is partly valid. Copy it and replace the invalid characters
- with underscores. */
-
- Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
-
- for (i = 0; i < len; i++)
- {
- int c = XSTRING (new)->data[i];
- if (! ((c >= 'a' && c <= 'z')
- || (c >= 'A' && c <= 'Z')
- || (c >= '0' && c <= '9')
- || c == '-' || c == '_'))
- XSTRING (new)->data[i] = '_';
- }
-}
-
-
-#if 0 /* MAC_TODO: implement resource strings */
-extern char *x_get_string_resource ();
-
-DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
- "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
-This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
-class, where INSTANCE is the name under which Emacs was invoked, or\n\
-the name specified by the `-name' or `-rn' command-line arguments.\n\
-\n\
-The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
-class, respectively. You must specify both of them or neither.\n\
-If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
-and the class is `Emacs.CLASS.SUBCLASS'.")
- (attribute, class, component, subclass)
- Lisp_Object attribute, class, component, subclass;
-{
- register char *value;
- char *name_key;
- char *class_key;
-
- CHECK_STRING (attribute, 0);
- CHECK_STRING (class, 0);
-
- if (!NILP (component))
- CHECK_STRING (component, 1);
- if (!NILP (subclass))
- CHECK_STRING (subclass, 2);
- if (NILP (component) != NILP (subclass))
- error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
-
- validate_x_resource_name ();
-
- /* Allocate space for the components, the dots which separate them,
- and the final '\0'. Make them big enough for the worst case. */
- name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
- + (STRINGP (component)
- ? STRING_BYTES (XSTRING (component)) : 0)
- + STRING_BYTES (XSTRING (attribute))
- + 3);
-
- class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
- + STRING_BYTES (XSTRING (class))
- + (STRINGP (subclass)
- ? STRING_BYTES (XSTRING (subclass)) : 0)
- + 3);
-
- /* Start with emacs.FRAMENAME for the name (the specific one)
- and with `Emacs' for the class key (the general one). */
- strcpy (name_key, XSTRING (Vx_resource_name)->data);
- strcpy (class_key, EMACS_CLASS);
-
- strcat (class_key, ".");
- strcat (class_key, XSTRING (class)->data);
-
- if (!NILP (component))
- {
- strcat (class_key, ".");
- strcat (class_key, XSTRING (subclass)->data);
-
- strcat (name_key, ".");
- strcat (name_key, XSTRING (component)->data);
- }
-
- strcat (name_key, ".");
- strcat (name_key, XSTRING (attribute)->data);
-
- value = x_get_string_resource (Qnil,
- name_key, class_key);
-
- if (value != (char *) 0)
- return build_string (value);
- else
- return Qnil;
-}
-
-/* Used when C code wants a resource value. */
-
-char *
-x_get_resource_string (attribute, class)
- char *attribute, *class;
-{
- char *name_key;
- char *class_key;
- struct frame *sf = SELECTED_FRAME ();
-
- /* Allocate space for the components, the dots which separate them,
- and the final '\0'. */
- name_key = (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name))
- + strlen (attribute) + 2);
- class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
- + strlen (class) + 2);
-
- sprintf (name_key, "%s.%s",
- XSTRING (Vinvocation_name)->data,
- attribute);
- sprintf (class_key, "%s.%s", EMACS_CLASS, class);
-
- return x_get_string_resource (sf, name_key, class_key);
-}
-#endif
-
-/* Types we might convert a resource string into. */
-enum resource_types
-{
- RES_TYPE_NUMBER,
- RES_TYPE_FLOAT,
- RES_TYPE_BOOLEAN,
- RES_TYPE_STRING,
- RES_TYPE_SYMBOL
-};
-
-/* Return the value of parameter PARAM.
-
- First search ALIST, then Vdefault_frame_alist, then the X defaults
- database, using ATTRIBUTE as the attribute name and CLASS as its class.
-
- Convert the resource to the type specified by desired_type.
-
- If no default is specified, return Qunbound. If you call
- w32_get_arg, make sure you deal with Qunbound in a reasonable way,
- and don't let it get stored in any Lisp-visible variables! */
-
-static Lisp_Object
-mac_get_arg (alist, param, attribute, class, type)
- Lisp_Object alist, param;
- char *attribute;
- char *class;
- enum resource_types type;
-{
- register Lisp_Object tem;
-
- tem = Fassq (param, alist);
- if (EQ (tem, Qnil))
- tem = Fassq (param, Vdefault_frame_alist);
- if (EQ (tem, Qnil))
- {
-
-#if 0 /* MAC_TODO: search resource also */
- if (attribute)
- {
- tem = Fx_get_resource (build_string (attribute),
- build_string (class),
- Qnil, Qnil);
-
- if (NILP (tem))
- return Qunbound;
-
- switch (type)
- {
- case RES_TYPE_NUMBER:
- return make_number (atoi (XSTRING (tem)->data));
-
- case RES_TYPE_FLOAT:
- return make_float (atof (XSTRING (tem)->data));
-
- case RES_TYPE_BOOLEAN:
- tem = Fdowncase (tem);
- if (!strcmp (XSTRING (tem)->data, "on")
- || !strcmp (XSTRING (tem)->data, "true"))
- return Qt;
- else
- return Qnil;
-
- case RES_TYPE_STRING:
- return tem;
-
- case RES_TYPE_SYMBOL:
- /* As a special case, we map the values `true' and `on'
- to Qt, and `false' and `off' to Qnil. */
- {
- Lisp_Object lower;
- lower = Fdowncase (tem);
- if (!strcmp (XSTRING (lower)->data, "on")
- || !strcmp (XSTRING (lower)->data, "true"))
- return Qt;
- else if (!strcmp (XSTRING (lower)->data, "off")
- || !strcmp (XSTRING (lower)->data, "false"))
- return Qnil;
- else
- return Fintern (tem, Qnil);
- }
-
- default:
- abort ();
- }
- }
- else
-#endif
- return Qunbound;
- }
- return Fcdr (tem);
-}
-
-/* Record in frame F the specified or default value according to ALIST
- of the parameter named PROP (a Lisp symbol).
- If no value is specified for PROP, look for an X default for XPROP
- on the frame named NAME.
- If that is not found either, use the value DEFLT. */
-
-static Lisp_Object
-x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
- struct frame *f;
- Lisp_Object alist;
- Lisp_Object prop;
- Lisp_Object deflt;
- char *xprop;
- char *xclass;
- enum resource_types type;
-{
- Lisp_Object tem;
-
- tem = mac_get_arg (alist, prop, xprop, xclass, type);
- if (EQ (tem, Qunbound))
- tem = deflt;
- x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
- return tem;
-}
-\f
-DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
- "Parse an X-style geometry string STRING.\n\
-Returns an alist of the form ((top . TOP), (left . LEFT) ... ).\n\
-The properties returned may include `top', `left', `height', and `width'.\n\
-The value of `left' or `top' may be an integer,\n\
-or a list (+ N) meaning N pixels relative to top/left corner,\n\
-or a list (- N) meaning -N pixels relative to bottom/right corner.")
- (string)
- Lisp_Object string;
-{
- int geometry, x, y;
- unsigned int width, height;
- Lisp_Object result;
-
- CHECK_STRING (string, 0);
-
- geometry = XParseGeometry ((char *) XSTRING (string)->data,
- &x, &y, &width, &height);
-
- result = Qnil;
- if (geometry & XValue)
- {
- Lisp_Object element;
-
- if (x >= 0 && (geometry & XNegative))
- element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
- else if (x < 0 && ! (geometry & XNegative))
- element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
- else
- element = Fcons (Qleft, make_number (x));
- result = Fcons (element, result);
- }
-
- if (geometry & YValue)
- {
- Lisp_Object element;
-
- if (y >= 0 && (geometry & YNegative))
- element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
- else if (y < 0 && ! (geometry & YNegative))
- element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
- else
- element = Fcons (Qtop, make_number (y));
- result = Fcons (element, result);
- }
-
- if (geometry & WidthValue)
- result = Fcons (Fcons (Qwidth, make_number (width)), result);
- if (geometry & HeightValue)
- result = Fcons (Fcons (Qheight, make_number (height)), result);
-
- return result;
-}
-
-/* Calculate the desired size and position of this window,
- and return the flags saying which aspects were specified.
-
- This function does not make the coordinates positive. */
-
-#define DEFAULT_ROWS 40
-#define DEFAULT_COLS 80
-
-static int
-x_figure_window_size (f, parms)
- struct frame *f;
- Lisp_Object parms;
-{
- register Lisp_Object tem0, tem1, tem2;
- long window_prompting = 0;
-
- /* Default values if we fall through.
- Actually, if that happens we should get
- window manager prompting. */
- SET_FRAME_WIDTH (f, DEFAULT_COLS);
- f->height = DEFAULT_ROWS;
- /* Window managers expect that if program-specified
- positions are not (0,0), they're intentional, not defaults. */
- f->output_data.mac->top_pos = 0;
- f->output_data.mac->left_pos = 0;
-
- tem0 = mac_get_arg (parms, Qheight, 0, 0, RES_TYPE_NUMBER);
- tem1 = mac_get_arg (parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
- tem2 = mac_get_arg (parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
- if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
- {
- if (!EQ (tem0, Qunbound))
- {
- CHECK_NUMBER (tem0, 0);
- f->height = XINT (tem0);
- }
- if (!EQ (tem1, Qunbound))
- {
- CHECK_NUMBER (tem1, 0);
- SET_FRAME_WIDTH (f, XINT (tem1));
- }
- if (!NILP (tem2) && !EQ (tem2, Qunbound))
- window_prompting |= USSize;
- else
- window_prompting |= PSize;
- }
-
- f->output_data.mac->vertical_scroll_bar_extra
- = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
- ? 0
- : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
- ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
- : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.mac->font)));
- x_compute_fringe_widths (f, 0);
- f->output_data.mac->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
- f->output_data.mac->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
-
- tem0 = mac_get_arg (parms, Qtop, 0, 0, RES_TYPE_NUMBER);
- tem1 = mac_get_arg (parms, Qleft, 0, 0, RES_TYPE_NUMBER);
- tem2 = mac_get_arg (parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
- if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
- {
- if (EQ (tem0, Qminus))
- {
- f->output_data.mac->top_pos = 0;
- window_prompting |= YNegative;
- }
- else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
- && CONSP (XCDR (tem0))
- && INTEGERP (XCAR (XCDR (tem0))))
- {
- f->output_data.mac->top_pos = - XINT (XCAR (XCDR (tem0)));
- window_prompting |= YNegative;
- }
- else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
- && CONSP (XCDR (tem0))
- && INTEGERP (XCAR (XCDR (tem0))))
- {
- f->output_data.mac->top_pos = XINT (XCAR (XCDR (tem0)));
- }
- else if (EQ (tem0, Qunbound))
- f->output_data.mac->top_pos = 0;
- else
- {
- CHECK_NUMBER (tem0, 0);
- f->output_data.mac->top_pos = XINT (tem0);
- if (f->output_data.mac->top_pos < 0)
- window_prompting |= YNegative;
- }
-
- if (EQ (tem1, Qminus))
- {
- f->output_data.mac->left_pos = 0;
- window_prompting |= XNegative;
- }
- else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
- && CONSP (XCDR (tem1))
- && INTEGERP (XCAR (XCDR (tem1))))
- {
- f->output_data.mac->left_pos = - XINT (XCAR (XCDR (tem1)));
- window_prompting |= XNegative;
- }
- else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
- && CONSP (XCDR (tem1))
- && INTEGERP (XCAR (XCDR (tem1))))
- {
- f->output_data.mac->left_pos = XINT (XCAR (XCDR (tem1)));
- }
- else if (EQ (tem1, Qunbound))
- f->output_data.mac->left_pos = 0;
- else
- {
- CHECK_NUMBER (tem1, 0);
- f->output_data.mac->left_pos = XINT (tem1);
- if (f->output_data.mac->left_pos < 0)
- window_prompting |= XNegative;
- }
-
- if (!NILP (tem2) && ! EQ (tem2, Qunbound))
- window_prompting |= USPosition;
- else
- window_prompting |= PPosition;
- }
-
- return window_prompting;
-}
-
-\f
-#if 0
-/* Create and set up the Mac window for frame F. */
-
-static void
-mac_window (f, window_prompting, minibuffer_only)
- struct frame *f;
- long window_prompting;
- int minibuffer_only;
-{
- Rect r;
-
- BLOCK_INPUT;
-
- /* Use the resource name as the top-level window name
- for looking up resources. Make a non-Lisp copy
- for the window manager, so GC relocation won't bother it.
-
- Elsewhere we specify the window name for the window manager. */
-
- {
- char *str = (char *) XSTRING (Vx_resource_name)->data;
- f->namebuf = (char *) xmalloc (strlen (str) + 1);
- strcpy (f->namebuf, str);
- }
-
- SetRect (&r, f->output_data.mac->left_pos, f->output_data.mac->top_pos,
- f->output_data.mac->left_pos + PIXEL_WIDTH (f),
- f->output_data.mac->top_pos + PIXEL_HEIGHT (f));
- FRAME_MAC_WINDOW (f)
- = NewCWindow (NULL, &r, "\p", 1, zoomDocProc, (WindowPtr) -1, 1, (long) f->output_data.mac);
-
- validate_x_resource_name ();
-
- /* x_set_name normally ignores requests to set the name if the
- requested name is the same as the current name. This is the one
- place where that assumption isn't correct; f->name is set, but
- the server hasn't been told. */
- {
- Lisp_Object name;
- int explicit = f->explicit_name;
-
- f->explicit_name = 0;
- name = f->name;
- f->name = Qnil;
- x_set_name (f, name, explicit);
- }
-
- ShowWindow (FRAME_MAC_WINDOW (f));
-
- UNBLOCK_INPUT;
-
- if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
- initialize_frame_menubar (f);
-
- if (FRAME_MAC_WINDOW (f) == 0)
- error ("Unable to create window");
-}
-#endif
-
-/* Handle the icon stuff for this window. Perhaps later we might
- want an x_set_icon_position which can be called interactively as
- well. */
-
-static void
-x_icon (f, parms)
- struct frame *f;
- Lisp_Object parms;
-{
- Lisp_Object icon_x, icon_y;
-
- /* Set the position of the icon. Note that Windows 95 groups all
- icons in the tray. */
- icon_x = mac_get_arg (parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
- icon_y = mac_get_arg (parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
- if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
- {
- CHECK_NUMBER (icon_x, 0);
- CHECK_NUMBER (icon_y, 0);
- }
- else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
- error ("Both left and top icon corners of icon must be specified");
-
- BLOCK_INPUT;
-
- if (! EQ (icon_x, Qunbound))
- x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
-
-#if 0 /* TODO */
- /* Start up iconic or window? */
- x_wm_set_window_state
- (f, (EQ (w32_get_arg (parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL), Qicon)
- ? IconicState
- : NormalState));
-
- x_text_icon (f, (char *) XSTRING ((!NILP (f->icon_name)
- ? f->icon_name
- : f->name))->data);
-#endif
-
- UNBLOCK_INPUT;
-}
-
-
-static void
-x_make_gc (f)
- struct frame *f;
-{
- XGCValues gc_values;
-
- BLOCK_INPUT;
-
- /* Create the GC's of this frame.
- Note that many default values are used. */
-
- /* Normal video */
- gc_values.font = f->output_data.mac->font;
- gc_values.foreground = f->output_data.mac->foreground_pixel;
- gc_values.background = f->output_data.mac->background_pixel;
- f->output_data.mac->normal_gc = XCreateGC (FRAME_MAC_DISPLAY (f),
- FRAME_MAC_WINDOW (f),
- GCFont | GCForeground | GCBackground,
- &gc_values);
-
- /* Reverse video style. */
- gc_values.foreground = f->output_data.mac->background_pixel;
- gc_values.background = f->output_data.mac->foreground_pixel;
- f->output_data.mac->reverse_gc = XCreateGC (FRAME_MAC_DISPLAY (f),
- FRAME_MAC_WINDOW (f),
- GCFont | GCForeground | GCBackground,
- &gc_values);
-
- /* Cursor has cursor-color background, background-color foreground. */
- gc_values.foreground = f->output_data.mac->background_pixel;
- gc_values.background = f->output_data.mac->cursor_pixel;
- f->output_data.mac->cursor_gc = XCreateGC (FRAME_MAC_DISPLAY (f),
- FRAME_MAC_WINDOW (f),
- GCFont | GCForeground | GCBackground,
- &gc_values);
-
- /* Reliefs. */
- f->output_data.mac->white_relief.gc = 0;
- f->output_data.mac->black_relief.gc = 0;
-
- UNBLOCK_INPUT;
-}
-
-
-DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
- 1, 1, 0,
- "Make a new window, which is called a \"frame\" in Emacs terms.\n\
-Returns an Emacs frame object.\n\
-ALIST is an alist of frame parameters.\n\
-If the parameters specify that the frame should not have a minibuffer,\n\
-and do not specify a specific minibuffer window to use,\n\
-then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
-be shared by the new frame.\n\
-\n\
-This function is an internal primitive--use `make-frame' instead.")
- (parms)
- Lisp_Object parms;
-{
- struct frame *f;
- Lisp_Object frame, tem;
- Lisp_Object name;
- int minibuffer_only = 0;
- long window_prompting = 0;
- int width, height;
- int count = BINDING_STACK_SIZE ();
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
- Lisp_Object display;
- struct mac_display_info *dpyinfo = NULL;
- Lisp_Object parent;
- struct kboard *kb;
- char x_frame_name[10];
- static int x_frame_count = 2; /* starts from 2 because terminal frame is F1 */
-
- check_mac ();
-
- /* Use this general default value to start with
- until we know if this frame has a specified name. */
- Vx_resource_name = Vinvocation_name;
-
- display = mac_get_arg (parms, Qdisplay, 0, 0, RES_TYPE_STRING);
- if (EQ (display, Qunbound))
- display = Qnil;
- dpyinfo = check_x_display_info (display);
-#ifdef MULTI_KBOARD
- kb = dpyinfo->kboard;
-#else
- kb = &the_only_kboard;
-#endif
-
- name = mac_get_arg (parms, Qname, "name", "Name", RES_TYPE_STRING);
- if (!STRINGP (name)
- && ! EQ (name, Qunbound)
- && ! NILP (name))
- error ("Invalid frame name--not a string or nil");
-
- if (STRINGP (name))
- Vx_resource_name = name;
-
- /* See if parent window is specified. */
- parent = mac_get_arg (parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
- if (EQ (parent, Qunbound))
- parent = Qnil;
- if (! NILP (parent))
- CHECK_NUMBER (parent, 0);
-
- /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
- /* No need to protect DISPLAY because that's not used after passing
- it to make_frame_without_minibuffer. */
- frame = Qnil;
- GCPRO4 (parms, parent, name, frame);
- tem = mac_get_arg (parms, Qminibuffer, 0, 0, RES_TYPE_SYMBOL);
- if (EQ (tem, Qnone) || NILP (tem))
- f = make_frame_without_minibuffer (Qnil, kb, display);
- else if (EQ (tem, Qonly))
- {
- f = make_minibuffer_frame ();
- minibuffer_only = 1;
- }
- else if (WINDOWP (tem))
- f = make_frame_without_minibuffer (tem, kb, display);
- else
- f = make_frame (1);
-
- if (EQ (name, Qunbound) || NILP (name))
- {
- sprintf (x_frame_name, "F%d", x_frame_count++);
- f->name = build_string (x_frame_name);
- f->explicit_name = 0;
- }
- else
- {
- f->name = name;
- f->explicit_name = 1;
- }
-
- XSETFRAME (frame, f);
-
- /* Note that X Windows does support scroll bars. */
- FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
-
- f->output_method = output_mac;
- f->output_data.mac = (struct mac_output *) xmalloc (sizeof (struct mac_output));
- bzero (f->output_data.mac, sizeof (struct mac_output));
- f->output_data.mac->fontset = -1;
- f->output_data.mac->scroll_bar_foreground_pixel = -1;
- f->output_data.mac->scroll_bar_background_pixel = -1;
-
-#if 0
- FRAME_FONTSET (f) = -1;
-#endif
-
- f->icon_name
- = mac_get_arg (parms, Qicon_name, "iconName", "Title", RES_TYPE_STRING);
- if (! STRINGP (f->icon_name))
- f->icon_name = Qnil;
-
-/* FRAME_W32_DISPLAY_INFO (f) = dpyinfo; */
-#ifdef MULTI_KBOARD
- FRAME_KBOARD (f) = kb;
-#endif
-
- /* Specify the parent under which to make this window. */
-
- if (!NILP (parent))
- {
- f->output_data.mac->parent_desc = (Window) parent;
- f->output_data.mac->explicit_parent = 1;
- }
- else
- {
- f->output_data.mac->parent_desc = FRAME_MAC_DISPLAY_INFO (f)->root_window;
- f->output_data.mac->explicit_parent = 0;
- }
-
- /* Set the name; the functions to which we pass f expect the name to
- be set. */
- if (EQ (name, Qunbound) || NILP (name))
- {
- f->name = build_string (dpyinfo->mac_id_name);
- f->explicit_name = 0;
- }
- else
- {
- f->name = name;
- f->explicit_name = 1;
- /* use the frame's title when getting resources for this frame. */
- specbind (Qx_resource_name, name);
- }
-
- /* Extract the window parameters from the supplied values
- that are needed to determine window geometry. */
- {
- Lisp_Object font;
-
- font = mac_get_arg (parms, Qfont, "font", "Font", RES_TYPE_STRING);
-
- BLOCK_INPUT;
- /* First, try whatever font the caller has specified. */
- if (STRINGP (font))
- {
- tem = Fquery_fontset (font, Qnil);
- if (STRINGP (tem))
- font = x_new_fontset (f, XSTRING (tem)->data);
- else
- font = x_new_font (f, XSTRING (font)->data);
- }
- /* Try out a font which we hope has bold and italic variations. */
- if (! STRINGP (font))
- font = x_new_font (f, "-ETL-fixed-medium-r-*--*-160-*-*-*-*-iso8859-1");
- /* If those didn't work, look for something which will at least work. */
- if (!STRINGP (font))
- font = x_new_font (f, "-*-monaco-*-12-*-mac-roman");
- if (! STRINGP (font))
- font = x_new_font (f, "-*-courier-*-10-*-mac-roman");
- if (! STRINGP (font))
- error ("Cannot find any usable font");
- UNBLOCK_INPUT;
-
- x_default_parameter (f, parms, Qfont, font,
- "font", "Font", RES_TYPE_STRING);
- }
-
- x_default_parameter (f, parms, Qborder_width, make_number (0),
- "borderwidth", "BorderWidth", RES_TYPE_NUMBER);
- /* This defaults to 2 in order to match xterm. We recognize either
- internalBorderWidth or internalBorder (which is what xterm calls
- it). */
- if (NILP (Fassq (Qinternal_border_width, parms)))
- {
- Lisp_Object value;
-
- value = mac_get_arg (parms, Qinternal_border_width,
- "internalBorder", "BorderWidth", RES_TYPE_NUMBER);
- if (! EQ (value, Qunbound))
- parms = Fcons (Fcons (Qinternal_border_width, value),
- parms);
- }
-
- /* Default internalBorderWidth to 0 on Windows to match other programs. */
- x_default_parameter (f, parms, Qinternal_border_width, make_number (0),
- "internalBorderWidth", "BorderWidth", RES_TYPE_NUMBER);
-
- x_default_parameter (f, parms, Qvertical_scroll_bars, Qt,
- "verticalScrollBars", "ScrollBars", RES_TYPE_BOOLEAN);
-
- /* Also do the stuff which must be set before the window exists. */
- x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
- "foreground", "Foreground", RES_TYPE_STRING);
- x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
- "background", "Background", RES_TYPE_STRING);
- x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
- "pointerColor", "Foreground", RES_TYPE_STRING);
- x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
- "cursorColor", "Foreground", RES_TYPE_STRING);
- x_default_parameter (f, parms, Qborder_color, build_string ("black"),
- "borderColor", "BorderColor", RES_TYPE_STRING);
- x_default_parameter (f, parms, Qscreen_gamma, Qnil,
- "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
- x_default_parameter (f, parms, Qline_spacing, Qnil,
- "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
- x_default_parameter (f, parms, Qleft_fringe, Qnil,
- "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
- x_default_parameter (f, parms, Qright_fringe, Qnil,
- "rightFringe", "RightFringe", RES_TYPE_NUMBER);
-
- /* Init faces before x_default_parameter is called for scroll-bar
- parameters because that function calls x_set_scroll_bar_width,
- which calls change_frame_size, which calls Fset_window_buffer,
- which runs hooks, which call Fvertical_motion. At the end, we
- end up in init_iterator with a null face cache, which should not
- happen. */
- init_frame_faces (f);
-
- x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
- "menuBar", "MenuBar", RES_TYPE_NUMBER);
- x_default_parameter (f, parms, Qtool_bar_lines, make_number (0),
- "toolBar", "ToolBar", RES_TYPE_NUMBER);
-#if 0
- x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
- "bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL);
-#endif
- x_default_parameter (f, parms, Qtitle, Qnil,
- "title", "Title", RES_TYPE_STRING);
-
- f->output_data.mac->parent_desc = FRAME_MAC_DISPLAY_INFO (f)->root_window;
- window_prompting = x_figure_window_size (f, parms);
-
- if (window_prompting & XNegative)
- {
- if (window_prompting & YNegative)
- f->output_data.mac->win_gravity = SouthEastGravity;
- else
- f->output_data.mac->win_gravity = NorthEastGravity;
- }
- else
- {
- if (window_prompting & YNegative)
- f->output_data.mac->win_gravity = SouthWestGravity;
- else
- f->output_data.mac->win_gravity = NorthWestGravity;
- }
-
- f->output_data.mac->size_hint_flags = window_prompting;
-
- tem = mac_get_arg (parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
- f->no_split = minibuffer_only || EQ (tem, Qt);
-
- /* Create the window. Add the tool-bar height to the initial frame
- height so that the user gets a text display area of the size he
- specified with -g or via the registry. Later changes of the
- tool-bar height don't change the frame size. This is done so that
- users can create tall Emacs frames without having to guess how
- tall the tool-bar will get. */
- f->height += FRAME_TOOL_BAR_LINES (f);
-
- /* mac_window (f, window_prompting, minibuffer_only); */
- make_mac_frame (f);
-
- x_icon (f, parms);
-
- x_make_gc (f);
-
- /* Now consider the frame official. */
- FRAME_MAC_DISPLAY_INFO (f)->reference_count++;
- Vframe_list = Fcons (frame, Vframe_list);
-
- /* We need to do this after creating the window, so that the
- icon-creation functions can say whose icon they're describing. */
- x_default_parameter (f, parms, Qicon_type, Qnil,
- "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
-
- x_default_parameter (f, parms, Qauto_raise, Qnil,
- "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
- x_default_parameter (f, parms, Qauto_lower, Qnil,
- "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
- x_default_parameter (f, parms, Qcursor_type, Qbox,
- "cursorType", "CursorType", RES_TYPE_SYMBOL);
- x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
- "scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER);
-
- /* Dimensions, especially f->height, must be done via change_frame_size.
- Change will not be effected unless different from the current
- f->height. */
-
- width = f->width;
- height = f->height;
- f->height = 0;
- SET_FRAME_WIDTH (f, 0);
- change_frame_size (f, height, width, 1, 0, 0);
-
- /* Set up faces after all frame parameters are known. */
- call1 (Qface_set_after_frame_default, frame);
-
-#if 0 /* MAC_TODO: when we have window manager hints */
- /* Tell the server what size and position, etc, we want, and how
- badly we want them. This should be done after we have the menu
- bar so that its size can be taken into account. */
- BLOCK_INPUT;
- x_wm_set_size_hint (f, window_prompting, 0);
- UNBLOCK_INPUT;
-#endif
-
- /* Make the window appear on the frame and enable display, unless
- the caller says not to. However, with explicit parent, Emacs
- cannot control visibility, so don't try. */
- if (! f->output_data.mac->explicit_parent)
- {
- Lisp_Object visibility;
-
- visibility = mac_get_arg (parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
- if (EQ (visibility, Qunbound))
- visibility = Qt;
-
-#if 0 /* MAC_TODO: really no iconify on Mac */
- if (EQ (visibility, Qicon))
- x_iconify_frame (f);
- else
-#endif
- if (! NILP (visibility))
- x_make_frame_visible (f);
- else
- /* Must have been Qnil. */
- ;
- }
-
- UNGCPRO;
- return unbind_to (count, frame);
-}
-
-/* FRAME is used only to get a handle on the X display. We don't pass the
- display info directly because we're called from frame.c, which doesn't
- know about that structure. */
-Lisp_Object
-x_get_focus_frame (frame)
- struct frame *frame;
-{
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
- Lisp_Object xfocus;
- if (! dpyinfo->x_focus_frame)
- return Qnil;
-
- XSETFRAME (xfocus, dpyinfo->x_focus_frame);
- return xfocus;
-}
-\f
-DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
- "Internal function called by `color-defined-p', which see.")
- (color, frame)
- Lisp_Object color, frame;
-{
- XColor foo;
- FRAME_PTR f = check_x_frame (frame);
-
- CHECK_STRING (color, 1);
-
- if (mac_defined_color (f, XSTRING (color)->data, &foo, 0))
- return Qt;
- else
- return Qnil;
-}
-
-DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
- "Internal function called by `color-values', which see.")
- (color, frame)
- Lisp_Object color, frame;
-{
- XColor foo;
- FRAME_PTR f = check_x_frame (frame);
-
- CHECK_STRING (color, 1);
-
- if (mac_defined_color (f, XSTRING (color)->data, &foo, 0))
- {
- Lisp_Object rgb[3];
-
- rgb[0] = make_number ((RED_FROM_ULONG (foo.pixel) << 8)
- | RED_FROM_ULONG (foo.pixel));
- rgb[1] = make_number ((GREEN_FROM_ULONG (foo.pixel) << 8)
- | GREEN_FROM_ULONG (foo.pixel));
- rgb[2] = make_number ((BLUE_FROM_ULONG (foo.pixel) << 8)
- | BLUE_FROM_ULONG (foo.pixel));
- return Flist (3, rgb);
- }
- else
- return Qnil;
-}
-
-DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
- "Internal function called by `display-color-p', which see.")
- (display)
- Lisp_Object display;
-{
- struct mac_display_info *dpyinfo = check_x_display_info (display);
-
- if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 2)
- return Qnil;
-
- return Qt;
-}
-
-DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
- 0, 1, 0,
- "Return t if the X display supports shades of gray.\n\
-Note that color displays do support shades of gray.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct mac_display_info *dpyinfo = check_x_display_info (display);
-
- if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 1)
- return Qnil;
-
- return Qt;
-}
-
-DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
- 0, 1, 0,
- "Returns the width in pixels of the X display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct mac_display_info *dpyinfo = check_x_display_info (display);
-
- return make_number (dpyinfo->width);
-}
-
-DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
- Sx_display_pixel_height, 0, 1, 0,
- "Returns the height in pixels of the X display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct mac_display_info *dpyinfo = check_x_display_info (display);
-
- return make_number (dpyinfo->height);
-}
-
-DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
- 0, 1, 0,
- "Returns the number of bitplanes of the display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct mac_display_info *dpyinfo = check_x_display_info (display);
-
- return make_number (dpyinfo->n_planes * dpyinfo->n_cbits);
-}
-
-DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
- 0, 1, 0,
- "Returns the number of color cells of the display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct mac_display_info *dpyinfo = check_x_display_info (display);
-
- /* MAC_TODO: check whether this is right */
- return make_number ((unsigned long) (pow (2, dpyinfo->n_cbits)));
-}
-
-DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
- Sx_server_max_request_size,
- 0, 1, 0,
- "Returns the maximum request size of the server of display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct mac_display_info *dpyinfo = check_x_display_info (display);
-
- return make_number (1);
-}
-
-DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
- "Returns the vendor ID string of the W32 system (Microsoft).\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- return build_string ("Apple Computers");
-}
-
-DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
- "Returns the version numbers of the server of display DISPLAY.\n\
-The value is a list of three integers: the major and minor\n\
-version numbers, and the vendor-specific release\n\
-number. See also the function `x-server-vendor'.\n\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- int mac_major_version, mac_minor_version;
- SInt32 response;
-
- if (Gestalt (gestaltSystemVersion, &response) != noErr)
- error ("Cannot get Mac OS version");
-
- mac_major_version = (response >> 8) & 0xf;
- mac_minor_version = (response >> 4) & 0xf;
-
- return Fcons (make_number (mac_major_version),
- Fcons (make_number (mac_minor_version), Qnil));
-}
-
-DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
- "Returns the number of screens on the server of display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- return make_number (1);
-}
-
-DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
- "Returns the height in millimeters of the X display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- /* MAC_TODO: this is an approximation, and only of the main display */
-
- struct mac_display_info *dpyinfo = check_x_display_info (display);
- short h, v;
-
- ScreenRes (&h, &v);
-
- return make_number ((int) (v / 72.0 * 25.4));
-}
-
-DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
- "Returns the width in millimeters of the X display DISPLAY.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- /* MAC_TODO: this is an approximation, and only of the main display */
-
- struct mac_display_info *dpyinfo = check_x_display_info (display);
- short h, v;
-
- ScreenRes (&h, &v);
-
- return make_number ((int) (h / 72.0 * 25.4));
-}
-
-DEFUN ("x-display-backing-store", Fx_display_backing_store,
- Sx_display_backing_store, 0, 1, 0,
- "Returns an indication of whether display DISPLAY does backing store.\n\
-The value may be `always', `when-mapped', or `not-useful'.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- return intern ("not-useful");
-}
-
-DEFUN ("x-display-visual-class", Fx_display_visual_class,
- Sx_display_visual_class, 0, 1, 0,
- "Returns the visual class of the display DISPLAY.\n\
-The value is one of the symbols `static-gray', `gray-scale',\n\
-`static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct mac_display_info *dpyinfo = check_x_display_info (display);
-
-#if 0
- switch (dpyinfo->visual->class)
- {
- case StaticGray: return (intern ("static-gray"));
- case GrayScale: return (intern ("gray-scale"));
- case StaticColor: return (intern ("static-color"));
- case PseudoColor: return (intern ("pseudo-color"));
- case TrueColor: return (intern ("true-color"));
- case DirectColor: return (intern ("direct-color"));
- default:
- error ("Display has an unknown visual class");
- }
-#endif
-
- error ("Display has an unknown visual class");
-}
-
-DEFUN ("x-display-save-under", Fx_display_save_under,
- Sx_display_save_under, 0, 1, 0,
- "Returns t if the display DISPLAY supports the save-under feature.\n\
-The optional argument DISPLAY specifies which display to ask about.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If omitted or nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- return Qnil;
-}
-\f
-int
-x_pixel_width (f)
- register struct frame *f;
-{
- return PIXEL_WIDTH (f);
-}
-
-int
-x_pixel_height (f)
- register struct frame *f;
-{
- return PIXEL_HEIGHT (f);
-}
-
-int
-x_char_width (f)
- register struct frame *f;
-{
- return FONT_WIDTH (f->output_data.mac->font);
-}
-
-int
-x_char_height (f)
- register struct frame *f;
-{
- return f->output_data.mac->line_height;
-}
-
-int
-x_screen_planes (f)
- register struct frame *f;
-{
- return FRAME_MAC_DISPLAY_INFO (f)->n_planes;
-}
-\f
-/* Return the display structure for the display named NAME.
- Open a new connection if necessary. */
-
-struct mac_display_info *
-x_display_info_for_name (name)
- Lisp_Object name;
-{
- Lisp_Object names;
- struct mac_display_info *dpyinfo;
-
- CHECK_STRING (name, 0);
-
- for (dpyinfo = &one_mac_display_info, names = x_display_name_list;
- dpyinfo;
- dpyinfo = dpyinfo->next, names = XCDR (names))
- {
- Lisp_Object tem;
- tem = Fstring_equal (XCAR (XCAR (names)), name);
- if (!NILP (tem))
- return dpyinfo;
- }
-
- /* Use this general default value to start with. */
- Vx_resource_name = Vinvocation_name;
-
- validate_x_resource_name ();
-
- dpyinfo = x_term_init (name, (unsigned char *) 0,
- (char *) XSTRING (Vx_resource_name)->data);
-
- if (dpyinfo == 0)
- error ("Cannot connect to server %s", XSTRING (name)->data);
-
- mac_in_use = 1;
- XSETFASTINT (Vwindow_system_version, 3);
-
- return dpyinfo;
-}
-
-#if 0 /* MAC_TODO: implement network support */
-DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
- 1, 3, 0, "Open a connection to a server.\n\
-DISPLAY is the name of the display to connect to.\n\
-Optional second arg XRM-STRING is a string of resources in xrdb format.\n\
-If the optional third arg MUST-SUCCEED is non-nil,\n\
-terminate Emacs if we can't open the connection.")
- (display, xrm_string, must_succeed)
- Lisp_Object display, xrm_string, must_succeed;
-{
- unsigned char *xrm_option;
- struct mac_display_info *dpyinfo;
-
- CHECK_STRING (display, 0);
- if (! NILP (xrm_string))
- CHECK_STRING (xrm_string, 1);
-
- if (! EQ (Vwindow_system, intern ("mac")))
- error ("Not using Mac OS");
-
- if (! NILP (xrm_string))
- xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
- else
- xrm_option = (unsigned char *) 0;
-
- validate_x_resource_name ();
-
- /* This is what opens the connection and sets x_current_display.
- This also initializes many symbols, such as those used for input. */
- dpyinfo = mac_term_init (display, xrm_option,
- (char *) XSTRING (Vx_resource_name)->data);
-
- if (dpyinfo == 0)
- {
- if (!NILP (must_succeed))
- fatal ("Cannot connect to server %s.\n",
- XSTRING (display)->data);
- else
- error ("Cannot connect to server %s", XSTRING (display)->data);
- }
-
- mac_in_use = 1;
-
- XSETFASTINT (Vwindow_system_version, 3);
- return Qnil;
-}
-
-DEFUN ("x-close-connection", Fx_close_connection,
- Sx_close_connection, 1, 1, 0,
- "Close the connection to DISPLAY's server.\n\
-For DISPLAY, specify either a frame or a display name (a string).\n\
-If DISPLAY is nil, that stands for the selected frame's display.")
- (display)
- Lisp_Object display;
-{
- struct mac_display_info *dpyinfo = check_x_display_info (display);
- int i;
-
- if (dpyinfo->reference_count > 0)
- error ("Display still has frames on it");
-
- BLOCK_INPUT;
- /* Free the fonts in the font table. */
- for (i = 0; i < dpyinfo->n_fonts; i++)
- if (dpyinfo->font_table[i].name)
- {
- if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
- xfree (dpyinfo->font_table[i].full_name);
- xfree (dpyinfo->font_table[i].name);
- x_unload_font (dpyinfo, dpyinfo->font_table[i].font);
- }
- x_destroy_all_bitmaps (dpyinfo);
-
- x_delete_display (dpyinfo);
- UNBLOCK_INPUT;
-
- return Qnil;
-}
-#endif
-
-DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
- "Return the list of display names that Emacs has connections to.")
- ()
-{
- Lisp_Object tail, result;
-
- result = Qnil;
- for (tail = x_display_name_list; ! NILP (tail); tail = XCDR (tail))
- result = Fcons (XCAR (XCAR (tail)), result);
-
- return result;
-}
-
-DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
- "If ON is non-nil, report errors as soon as the erring request is made.\n\
-If ON is nil, allow buffering of requests.\n\
-This is a noop on W32 systems.\n\
-The optional second argument DISPLAY specifies which display to act on.\n\
-DISPLAY should be either a frame or a display name (a string).\n\
-If DISPLAY is omitted or nil, that stands for the selected frame's display.")
- (on, display)
- Lisp_Object display, on;
-{
- return Qnil;
-}
-
-\f
-/***********************************************************************
- Image types
- ***********************************************************************/
-
-/* Value is the number of elements of vector VECTOR. */
-
-#define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
-
-/* List of supported image types. Use define_image_type to add new
- types. Use lookup_image_type to find a type for a given symbol. */
-
-static struct image_type *image_types;
-
-/* The symbol `image' which is the car of the lists used to represent
- images in Lisp. */
-
-extern Lisp_Object Qimage;
-
-/* The symbol `xbm' which is used as the type symbol for XBM images. */
-
-Lisp_Object Qxbm;
-
-/* Keywords. */
-
-extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
-extern Lisp_Object QCdata;
-Lisp_Object QCtype, QCascent, QCmargin, QCrelief;
-Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
-Lisp_Object QCindex;
-
-/* Other symbols. */
-
-Lisp_Object Qlaplace;
-
-/* Time in seconds after which images should be removed from the cache
- if not displayed. */
-
-Lisp_Object Vimage_cache_eviction_delay;
-
-/* Function prototypes. */
-
-static void define_image_type P_ ((struct image_type *type));
-static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
-static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
-static void x_laplace P_ ((struct frame *, struct image *));
-static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
- Lisp_Object));
-
-
-/* Define a new image type from TYPE. This adds a copy of TYPE to
- image_types and adds the symbol *TYPE->type to Vimage_types. */
-
-static void
-define_image_type (type)
- struct image_type *type;
-{
- /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
- The initialized data segment is read-only. */
- struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
- bcopy (type, p, sizeof *p);
- p->next = image_types;
- image_types = p;
- Vimage_types = Fcons (*p->type, Vimage_types);
-}
-
-
-/* Look up image type SYMBOL, and return a pointer to its image_type
- structure. Value is null if SYMBOL is not a known image type. */
-
-static INLINE struct image_type *
-lookup_image_type (symbol)
- Lisp_Object symbol;
-{
- struct image_type *type;
-
- for (type = image_types; type; type = type->next)
- if (EQ (symbol, *type->type))
- break;
-
- return type;
-}
-
-
-/* Value is non-zero if OBJECT is a valid Lisp image specification. A
- valid image specification is a list whose car is the symbol
- `image', and whose rest is a property list. The property list must
- contain a value for key `:type'. That value must be the name of a
- supported image type. The rest of the property list depends on the
- image type. */
-
-int
-valid_image_p (object)
- Lisp_Object object;
-{
- int valid_p = 0;
-
- if (CONSP (object) && EQ (XCAR (object), Qimage))
- {
- Lisp_Object symbol = Fplist_get (XCDR (object), QCtype);
- struct image_type *type = lookup_image_type (symbol);
-
- if (type)
- valid_p = type->valid_p (object);
- }
-
- return valid_p;
-}
-
-
-/* Log error message with format string FORMAT and argument ARG.
- Signaling an error, e.g. when an image cannot be loaded, is not a
- good idea because this would interrupt redisplay, and the error
- message display would lead to another redisplay. This function
- therefore simply displays a message. */
-
-static void
-image_error (format, arg1, arg2)
- char *format;
- Lisp_Object arg1, arg2;
-{
- add_to_log (format, arg1, arg2);
-}
-
-
-\f
-/***********************************************************************
- Image specifications
- ***********************************************************************/
-
-enum image_value_type
-{
- IMAGE_DONT_CHECK_VALUE_TYPE,
- IMAGE_STRING_VALUE,
- IMAGE_SYMBOL_VALUE,
- IMAGE_POSITIVE_INTEGER_VALUE,
- IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
- IMAGE_NON_NEGATIVE_INTEGER_VALUE,
- IMAGE_ASCENT_VALUE,
- IMAGE_INTEGER_VALUE,
- IMAGE_FUNCTION_VALUE,
- IMAGE_NUMBER_VALUE,
- IMAGE_BOOL_VALUE
-};
-
-/* Structure used when parsing image specifications. */
-
-struct image_keyword
-{
- /* Name of keyword. */
- char *name;
-
- /* The type of value allowed. */
- enum image_value_type type;
-
- /* Non-zero means key must be present. */
- int mandatory_p;
-
- /* Used to recognize duplicate keywords in a property list. */
- int count;
-
- /* The value that was found. */
- Lisp_Object value;
-};
-
-
-static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
- int, Lisp_Object));
-static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
-
-
-/* Parse image spec SPEC according to KEYWORDS. A valid image spec
- has the format (image KEYWORD VALUE ...). One of the keyword/
- value pairs must be `:type TYPE'. KEYWORDS is a vector of
- image_keywords structures of size NKEYWORDS describing other
- allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
-
-static int
-parse_image_spec (spec, keywords, nkeywords, type)
- Lisp_Object spec;
- struct image_keyword *keywords;
- int nkeywords;
- Lisp_Object type;
-{
- int i;
- Lisp_Object plist;
-
- if (!CONSP (spec) || !EQ (XCAR (spec), Qimage))
- return 0;
-
- plist = XCDR (spec);
- while (CONSP (plist))
- {
- Lisp_Object key, value;
-
- /* First element of a pair must be a symbol. */
- key = XCAR (plist);
- plist = XCDR (plist);
- if (!SYMBOLP (key))
- return 0;
-
- /* There must follow a value. */
- if (!CONSP (plist))
- return 0;
- value = XCAR (plist);
- plist = XCDR (plist);
-
- /* Find key in KEYWORDS. Error if not found. */
- for (i = 0; i < nkeywords; ++i)
- if (strcmp (keywords[i].name, XSYMBOL (key)->name->data) == 0)
- break;
-
- if (i == nkeywords)
- continue;
-
- /* Record that we recognized the keyword. If a keywords
- was found more than once, it's an error. */
- keywords[i].value = value;
- ++keywords[i].count;
-
- if (keywords[i].count > 1)
- return 0;
-
- /* Check type of value against allowed type. */
- switch (keywords[i].type)
- {
- case IMAGE_STRING_VALUE:
- if (!STRINGP (value))
- return 0;
- break;
-
- case IMAGE_SYMBOL_VALUE:
- if (!SYMBOLP (value))
- return 0;
- break;
-
- case IMAGE_POSITIVE_INTEGER_VALUE:
- if (!INTEGERP (value) || XINT (value) <= 0)
- return 0;
- break;
-
- case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
- if (INTEGERP (value) && XINT (value) >= 0)
- break;
- if (CONSP (value)
- && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
- && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
- break;
- return 0;
-
- case IMAGE_ASCENT_VALUE:
- if (SYMBOLP (value) && EQ (value, Qcenter))
- break;
- else if (INTEGERP (value)
- && XINT (value) >= 0
- && XINT (value) <= 100)
- break;
- return 0;
-
- case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
- if (!INTEGERP (value) || XINT (value) < 0)
- return 0;
- break;
-
- case IMAGE_DONT_CHECK_VALUE_TYPE:
- break;
-
- case IMAGE_FUNCTION_VALUE:
- value = indirect_function (value);
- if (SUBRP (value)
- || COMPILEDP (value)
- || (CONSP (value) && EQ (XCAR (value), Qlambda)))
- break;
- return 0;
-
- case IMAGE_NUMBER_VALUE:
- if (!INTEGERP (value) && !FLOATP (value))
- return 0;
- break;
-
- case IMAGE_INTEGER_VALUE:
- if (!INTEGERP (value))
- return 0;
- break;
-
- case IMAGE_BOOL_VALUE:
- if (!NILP (value) && !EQ (value, Qt))
- return 0;
- break;
-
- default:
- abort ();
- break;
- }
-
- if (EQ (key, QCtype) && !EQ (type, value))
- return 0;
- }
-
- /* Check that all mandatory fields are present. */
- for (i = 0; i < nkeywords; ++i)
- if (keywords[i].mandatory_p && keywords[i].count == 0)
- return 0;
-
- return NILP (plist);
-}
-
-
-/* Return the value of KEY in image specification SPEC. Value is nil
- if KEY is not present in SPEC. if FOUND is not null, set *FOUND
- to 1 if KEY was found in SPEC, set it to 0 otherwise. */
-
-static Lisp_Object
-image_spec_value (spec, key, found)
- Lisp_Object spec, key;
- int *found;
-{
- Lisp_Object tail;
-
- xassert (valid_image_p (spec));
-
- for (tail = XCDR (spec);
- CONSP (tail) && CONSP (XCDR (tail));
- tail = XCDR (XCDR (tail)))
- {
- if (EQ (XCAR (tail), key))
- {
- if (found)
- *found = 1;
- return XCAR (XCDR (tail));
- }
- }
-
- if (found)
- *found = 0;
- return Qnil;
-}
-
-
-
-\f
-/***********************************************************************
- Image type independent image structures
- ***********************************************************************/
-
-static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
-static void free_image P_ ((struct frame *f, struct image *img));
-
-
-/* Allocate and return a new image structure for image specification
- SPEC. SPEC has a hash value of HASH. */
-
-static struct image *
-make_image (spec, hash)
- Lisp_Object spec;
- unsigned hash;
-{
- struct image *img = (struct image *) xmalloc (sizeof *img);
-
- xassert (valid_image_p (spec));
- bzero (img, sizeof *img);
- img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
- xassert (img->type != NULL);
- img->spec = spec;
- img->data.lisp_val = Qnil;
- img->ascent = DEFAULT_IMAGE_ASCENT;
- img->hash = hash;
- return img;
-}
-
-
-/* Free image IMG which was used on frame F, including its resources. */
-
-static void
-free_image (f, img)
- struct frame *f;
- struct image *img;
-{
- if (img)
- {
- struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
-
- /* Remove IMG from the hash table of its cache. */
- if (img->prev)
- img->prev->next = img->next;
- else
- c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
-
- if (img->next)
- img->next->prev = img->prev;
-
- c->images[img->id] = NULL;
-
- /* Free resources, then free IMG. */
- img->type->free (f, img);
- xfree (img);
- }
-}
-
-
-/* Prepare image IMG for display on frame F. Must be called before
- drawing an image. */
-
-void
-prepare_image_for_display (f, img)
- struct frame *f;
- struct image *img;
-{
- EMACS_TIME t;
-
- /* We're about to display IMG, so set its timestamp to `now'. */
- EMACS_GET_TIME (t);
- img->timestamp = EMACS_SECS (t);
-
- /* If IMG doesn't have a pixmap yet, load it now, using the image
- type dependent loader function. */
- if (img->pixmap == 0 && !img->load_failed_p)
- img->load_failed_p = img->type->load (f, img) == 0;
-}
-
-
-/* Value is the number of pixels for the ascent of image IMG when
- drawn in face FACE. */
-
-int
-image_ascent (img, face)
- struct image *img;
- struct face *face;
-{
- int height = img->height + img->vmargin;
- int ascent;
-
- if (img->ascent == CENTERED_IMAGE_ASCENT)
- {
- if (face->font)
- ascent = height / 2 - (FONT_DESCENT(face->font)
- - FONT_BASE(face->font)) / 2;
- else
- ascent = height / 2;
- }
- else
- ascent = height * img->ascent / 100.0;
-
- return ascent;
-}
-
-
-\f
-/***********************************************************************
- Helper functions for X image types
- ***********************************************************************/
-
-static void x_clear_image P_ ((struct frame *f, struct image *img));
-static unsigned long x_alloc_image_color P_ ((struct frame *f,
- struct image *img,
- Lisp_Object color_name,
- unsigned long dflt));
-
-/* Free X resources of image IMG which is used on frame F. */
-
-static void
-x_clear_image (f, img)
- struct frame *f;
- struct image *img;
-{
-#if 0 /* MAC_TODO: W32 image support */
-
- if (img->pixmap)
- {
- BLOCK_INPUT;
- XFreePixmap (NULL, img->pixmap);
- img->pixmap = 0;
- UNBLOCK_INPUT;
- }
-
- if (img->ncolors)
- {
- int class = FRAME_W32_DISPLAY_INFO (f)->visual->class;
-
- /* If display has an immutable color map, freeing colors is not
- necessary and some servers don't allow it. So don't do it. */
- if (class != StaticColor
- && class != StaticGray
- && class != TrueColor)
- {
- Colormap cmap;
- BLOCK_INPUT;
- cmap = DefaultColormapOfScreen (FRAME_W32_DISPLAY_INFO (f)->screen);
- XFreeColors (FRAME_W32_DISPLAY (f), cmap, img->colors,
- img->ncolors, 0);
- UNBLOCK_INPUT;
- }
-
- xfree (img->colors);
- img->colors = NULL;
- img->ncolors = 0;
- }
-#endif
-}
-
-
-/* Allocate color COLOR_NAME for image IMG on frame F. If color
- cannot be allocated, use DFLT. Add a newly allocated color to
- IMG->colors, so that it can be freed again. Value is the pixel
- color. */
-
-static unsigned long
-x_alloc_image_color (f, img, color_name, dflt)
- struct frame *f;
- struct image *img;
- Lisp_Object color_name;
- unsigned long dflt;
-{
-#if 0 /* MAC_TODO: allocing colors. */
- XColor color;
- unsigned long result;
-
- xassert (STRINGP (color_name));
-
- if (w32_defined_color (f, XSTRING (color_name)->data, &color, 1))
- {
- /* This isn't called frequently so we get away with simply
- reallocating the color vector to the needed size, here. */
- ++img->ncolors;
- img->colors =
- (unsigned long *) xrealloc (img->colors,
- img->ncolors * sizeof *img->colors);
- img->colors[img->ncolors - 1] = color.pixel;
- result = color.pixel;
- }
- else
- result = dflt;
- return result;
-#endif
- return 0;
-}
-
-
-\f
-/***********************************************************************
- Image Cache
- ***********************************************************************/
-
-static void cache_image P_ ((struct frame *f, struct image *img));
-
-
-/* Return a new, initialized image cache that is allocated from the
- heap. Call free_image_cache to free an image cache. */
-
-struct image_cache *
-make_image_cache ()
-{
- struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
- int size;
-
- bzero (c, sizeof *c);
- c->size = 50;
- c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
- size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
- c->buckets = (struct image **) xmalloc (size);
- bzero (c->buckets, size);
- return c;
-}
-
-
-/* Free image cache of frame F. Be aware that X frames share images
- caches. */
-
-void
-free_image_cache (f)
- struct frame *f;
-{
- struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
- if (c)
- {
- int i;
-
- /* Cache should not be referenced by any frame when freed. */
- xassert (c->refcount == 0);
-
- for (i = 0; i < c->used; ++i)
- free_image (f, c->images[i]);
- xfree (c->images);
- xfree (c);
- xfree (c->buckets);
- FRAME_X_IMAGE_CACHE (f) = NULL;
- }
-}
-
-
-/* Clear image cache of frame F. FORCE_P non-zero means free all
- images. FORCE_P zero means clear only images that haven't been
- displayed for some time. Should be called from time to time to
- reduce the number of loaded images. If image-eviction-seconds is
- non-nil, this frees images in the cache which weren't displayed for
- at least that many seconds. */
-
-void
-clear_image_cache (f, force_p)
- struct frame *f;
- int force_p;
-{
- struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
-
- if (c && INTEGERP (Vimage_cache_eviction_delay))
- {
- EMACS_TIME t;
- unsigned long old;
- int i, any_freed_p = 0;
-
- EMACS_GET_TIME (t);
- old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
-
- for (i = 0; i < c->used; ++i)
- {
- struct image *img = c->images[i];
- if (img != NULL
- && (force_p
- || (img->timestamp > old)))
- {
- free_image (f, img);
- any_freed_p = 1;
- }
- }
-
- /* We may be clearing the image cache because, for example,
- Emacs was iconified for a longer period of time. In that
- case, current matrices may still contain references to
- images freed above. So, clear these matrices. */
- if (any_freed_p)
- {
- clear_current_matrices (f);
- ++windows_or_buffers_changed;
- }
- }
-}
-
-
-DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
- 0, 1, 0,
- "Clear the image cache of FRAME.\n\
-FRAME nil or omitted means use the selected frame.\n\
-FRAME t means clear the image caches of all frames.")
- (frame)
- Lisp_Object frame;
-{
- if (EQ (frame, Qt))
- {
- Lisp_Object tail;
-
- FOR_EACH_FRAME (tail, frame)
- if (FRAME_MAC_P (XFRAME (frame)))
- clear_image_cache (XFRAME (frame), 1);
- }
- else
- clear_image_cache (check_x_frame (frame), 1);
-
- return Qnil;
-}
-
-
-/* Return the id of image with Lisp specification SPEC on frame F.
- SPEC must be a valid Lisp image specification (see valid_image_p). */
-
-int
-lookup_image (f, spec)
- struct frame *f;
- Lisp_Object spec;
-{
- struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
- struct image *img;
- int i;
- unsigned hash;
- struct gcpro gcpro1;
- EMACS_TIME now;
-
- /* F must be a window-system frame, and SPEC must be a valid image
- specification. */
- xassert (FRAME_WINDOW_P (f));
- xassert (valid_image_p (spec));
-
- GCPRO1 (spec);
-
- /* Look up SPEC in the hash table of the image cache. */
- hash = sxhash (spec, 0);
- i = hash % IMAGE_CACHE_BUCKETS_SIZE;
-
- for (img = c->buckets[i]; img; img = img->next)
- if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
- break;
-
- /* If not found, create a new image and cache it. */
- if (img == NULL)
- {
- BLOCK_INPUT;
- img = make_image (spec, hash);
- cache_image (f, img);
- img->load_failed_p = img->type->load (f, img) == 0;
-
- /* If we can't load the image, and we don't have a width and
- height, use some arbitrary width and height so that we can
- draw a rectangle for it. */
- if (img->load_failed_p)
- {
- Lisp_Object value;
-
- value = image_spec_value (spec, QCwidth, NULL);
- img->width = (INTEGERP (value)
- ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
- value = image_spec_value (spec, QCheight, NULL);
- img->height = (INTEGERP (value)
- ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
- }
- else
- {
- /* Handle image type independent image attributes
- `:ascent PERCENT', `:margin MARGIN', `:relief RELIEF'. */
- Lisp_Object ascent, margin, relief;
-
- ascent = image_spec_value (spec, QCascent, NULL);
- if (INTEGERP (ascent))
- img->ascent = XFASTINT (ascent);
- else if (EQ (ascent, Qcenter))
- img->ascent = CENTERED_IMAGE_ASCENT;
-
- margin = image_spec_value (spec, QCmargin, NULL);
- if (INTEGERP (margin) && XINT (margin) >= 0)
- img->vmargin = img->hmargin = XFASTINT (margin);
- else if (CONSP (margin) && INTEGERP (XCAR (margin))
- && INTEGERP (XCDR (margin)))
- {
- if (XINT (XCAR (margin)) > 0)
- img->hmargin = XFASTINT (XCAR (margin));
- if (XINT (XCDR (margin)) > 0)
- img->vmargin = XFASTINT (XCDR (margin));
- }
-
- relief = image_spec_value (spec, QCrelief, NULL);
- if (INTEGERP (relief))
- {
- img->relief = XINT (relief);
- img->hmargin += abs (img->relief);
- img->vmargin += abs (img->relief);
- }
- }
- }
-
- /* We're using IMG, so set its timestamp to `now'. */
- EMACS_GET_TIME (now);
- img->timestamp = EMACS_SECS (now);
-
- UNGCPRO;
-
- /* Value is the image id. */
- return img->id;
-}
-
-
-/* Cache image IMG in the image cache of frame F. */
-
-static void
-cache_image (f, img)
- struct frame *f;
- struct image *img;
-{
- struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
- int i;
-
- /* Find a free slot in c->images. */
- for (i = 0; i < c->used; ++i)
- if (c->images[i] == NULL)
- break;
-
- /* If no free slot found, maybe enlarge c->images. */
- if (i == c->used && c->used == c->size)
- {
- c->size *= 2;
- c->images = (struct image **) xrealloc (c->images,
- c->size * sizeof *c->images);
- }
-
- /* Add IMG to c->images, and assign IMG an id. */
- c->images[i] = img;
- img->id = i;
- if (i == c->used)
- ++c->used;
-
- /* Add IMG to the cache's hash table. */
- i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
- img->next = c->buckets[i];
- if (img->next)
- img->next->prev = img;
- img->prev = NULL;
- c->buckets[i] = img;
-}
-
-
-/* Call FN on every image in the image cache of frame F. Used to mark
- Lisp Objects in the image cache. */
-
-void
-forall_images_in_image_cache (f, fn)
- struct frame *f;
- void (*fn) P_ ((struct image *img));
-{
- if (FRAME_LIVE_P (f) && FRAME_MAC_P (f))
- {
- struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
- if (c)
- {
- int i;
- for (i = 0; i < c->used; ++i)
- if (c->images[i])
- fn (c->images[i]);
- }
- }
-}
-
-
-\f
-/***********************************************************************
- Mac support code
- ***********************************************************************/
-
-#if 0 /* MAC_TODO: Mac specific image code. */
-
-static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
- XImage **, Pixmap *));
-static void x_destroy_x_image P_ ((XImage *));
-static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
-
-
-/* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
- frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
- Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
- via xmalloc. Print error messages via image_error if an error
- occurs. Value is non-zero if successful. */
-
-static int
-x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
- struct frame *f;
- int width, height, depth;
- XImage **ximg;
- Pixmap *pixmap;
-{
-#if 0 /* MAC_TODO: Image support for Mac */
- Display *display = FRAME_W32_DISPLAY (f);
- Screen *screen = FRAME_X_SCREEN (f);
- Window window = FRAME_W32_WINDOW (f);
-
- xassert (interrupt_input_blocked);
-
- if (depth <= 0)
- depth = DefaultDepthOfScreen (screen);
- *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
- depth, ZPixmap, 0, NULL, width, height,
- depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
- if (*ximg == NULL)
- {
- image_error ("Unable to allocate X image", Qnil, Qnil);
- return 0;
- }
-
- /* Allocate image raster. */
- (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
-
- /* Allocate a pixmap of the same size. */
- *pixmap = XCreatePixmap (display, window, width, height, depth);
- if (*pixmap == 0)
- {
- x_destroy_x_image (*ximg);
- *ximg = NULL;
- image_error ("Unable to create X pixmap", Qnil, Qnil);
- return 0;
- }
-#endif
- return 1;
-}
-
-
-/* Destroy XImage XIMG. Free XIMG->data. */
-
-static void
-x_destroy_x_image (ximg)
- XImage *ximg;
-{
- xassert (interrupt_input_blocked);
- if (ximg)
- {
- xfree (ximg->data);
- ximg->data = NULL;
- XDestroyImage (ximg);
- }
-}
-
-
-/* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
- are width and height of both the image and pixmap. */
-
-static void
-x_put_x_image (f, ximg, pixmap, width, height)
- struct frame *f;
- XImage *ximg;
- Pixmap pixmap;
-{
- GC gc;
-
- xassert (interrupt_input_blocked);
- gc = XCreateGC (NULL, pixmap, 0, NULL);
- XPutImage (NULL, pixmap, gc, ximg, 0, 0, 0, 0, width, height);
- XFreeGC (NULL, gc);
-}
-
-#endif
-
-\f
-/***********************************************************************
- Searching files
- ***********************************************************************/
-
-static Lisp_Object x_find_image_file P_ ((Lisp_Object));
-
-/* Find image file FILE. Look in data-directory, then
- x-bitmap-file-path. Value is the full name of the file found, or
- nil if not found. */
-
-static Lisp_Object
-x_find_image_file (file)
- Lisp_Object file;
-{
- Lisp_Object file_found, search_path;
- struct gcpro gcpro1, gcpro2;
- int fd;
-
- file_found = Qnil;
- search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
- GCPRO2 (file_found, search_path);
-
- /* Try to find FILE in data-directory, then x-bitmap-file-path. */
- fd = openp (search_path, file, Qnil, &file_found, 0);
-
- if (fd < 0)
- file_found = Qnil;
- else
- close (fd);
-
- UNGCPRO;
- return file_found;
-}
-
-\f
-/***********************************************************************
- XBM images
- ***********************************************************************/
-
-static int xbm_load P_ ((struct frame *f, struct image *img));
-static int xbm_load_image_from_file P_ ((struct frame *f, struct image *img,
- Lisp_Object file));
-static int xbm_image_p P_ ((Lisp_Object object));
-static int xbm_read_bitmap_file_data P_ ((char *, int *, int *,
- unsigned char **));
-
-
-/* Indices of image specification fields in xbm_format, below. */
-
-enum xbm_keyword_index
-{
- XBM_TYPE,
- XBM_FILE,
- XBM_WIDTH,
- XBM_HEIGHT,
- XBM_DATA,
- XBM_FOREGROUND,
- XBM_BACKGROUND,
- XBM_ASCENT,
- XBM_MARGIN,
- XBM_RELIEF,
- XBM_ALGORITHM,
- XBM_HEURISTIC_MASK,
- XBM_LAST
-};
-
-/* Vector of image_keyword structures describing the format
- of valid XBM image specifications. */
-
-static struct image_keyword xbm_format[XBM_LAST] =
-{
- {":type", IMAGE_SYMBOL_VALUE, 1},
- {":file", IMAGE_STRING_VALUE, 0},
- {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
- {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
- {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":foreground", IMAGE_STRING_VALUE, 0},
- {":background", IMAGE_STRING_VALUE, 0},
- {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
- {":relief", IMAGE_INTEGER_VALUE, 0},
- {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
-};
-
-/* Structure describing the image type XBM. */
-
-static struct image_type xbm_type =
-{
- &Qxbm,
- xbm_image_p,
- xbm_load,
- x_clear_image,
- NULL
-};
-
-/* Tokens returned from xbm_scan. */
-
-enum xbm_token
-{
- XBM_TK_IDENT = 256,
- XBM_TK_NUMBER
-};
-
-
-/* Return non-zero if OBJECT is a valid XBM-type image specification.
- A valid specification is a list starting with the symbol `image'
- The rest of the list is a property list which must contain an
- entry `:type xbm..
-
- If the specification specifies a file to load, it must contain
- an entry `:file FILENAME' where FILENAME is a string.
-
- If the specification is for a bitmap loaded from memory it must
- contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
- WIDTH and HEIGHT are integers > 0. DATA may be:
-
- 1. a string large enough to hold the bitmap data, i.e. it must
- have a size >= (WIDTH + 7) / 8 * HEIGHT
-
- 2. a bool-vector of size >= WIDTH * HEIGHT
-
- 3. a vector of strings or bool-vectors, one for each line of the
- bitmap.
-
- Both the file and data forms may contain the additional entries
- `:background COLOR' and `:foreground COLOR'. If not present,
- foreground and background of the frame on which the image is
- displayed, is used. */
-
-static int
-xbm_image_p (object)
- Lisp_Object object;
-{
- struct image_keyword kw[XBM_LAST];
-
- bcopy (xbm_format, kw, sizeof kw);
- if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
- return 0;
-
- xassert (EQ (kw[XBM_TYPE].value, Qxbm));
-
- if (kw[XBM_FILE].count)
- {
- if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
- return 0;
- }
- else
- {
- Lisp_Object data;
- int width, height;
-
- /* Entries for `:width', `:height' and `:data' must be present. */
- if (!kw[XBM_WIDTH].count
- || !kw[XBM_HEIGHT].count
- || !kw[XBM_DATA].count)
- return 0;
-
- data = kw[XBM_DATA].value;
- width = XFASTINT (kw[XBM_WIDTH].value);
- height = XFASTINT (kw[XBM_HEIGHT].value);
-
- /* Check type of data, and width and height against contents of
- data. */
- if (VECTORP (data))
- {
- int i;
-
- /* Number of elements of the vector must be >= height. */
- if (XVECTOR (data)->size < height)
- return 0;
-
- /* Each string or bool-vector in data must be large enough
- for one line of the image. */
- for (i = 0; i < height; ++i)
- {
- Lisp_Object elt = XVECTOR (data)->contents[i];
-
- if (STRINGP (elt))
- {
- if (XSTRING (elt)->size
- < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
- return 0;
- }
- else if (BOOL_VECTOR_P (elt))
- {
- if (XBOOL_VECTOR (elt)->size < width)
- return 0;
- }
- else
- return 0;
- }
- }
- else if (STRINGP (data))
- {
- if (XSTRING (data)->size
- < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
- return 0;
- }
- else if (BOOL_VECTOR_P (data))
- {
- if (XBOOL_VECTOR (data)->size < width * height)
- return 0;
- }
- else
- return 0;
- }
-
- /* Baseline must be a value between 0 and 100 (a percentage). */
- if (kw[XBM_ASCENT].count
- && XFASTINT (kw[XBM_ASCENT].value) > 100)
- return 0;
-
- return 1;
-}
-
-
-/* Scan a bitmap file. FP is the stream to read from. Value is
- either an enumerator from enum xbm_token, or a character for a
- single-character token, or 0 at end of file. If scanning an
- identifier, store the lexeme of the identifier in SVAL. If
- scanning a number, store its value in *IVAL. */
-
-static int
-xbm_scan (fp, sval, ival)
- FILE *fp;
- char *sval;
- int *ival;
-{
- int c;
-
- /* Skip white space. */
- while ((c = fgetc (fp)) != EOF && isspace (c))
- ;
-
- if (c == EOF)
- c = 0;
- else if (isdigit (c))
- {
- int value = 0, digit;
-
- if (c == '0')
- {
- c = fgetc (fp);
- if (c == 'x' || c == 'X')
- {
- while ((c = fgetc (fp)) != EOF)
- {
- if (isdigit (c))
- digit = c - '0';
- else if (c >= 'a' && c <= 'f')
- digit = c - 'a' + 10;
- else if (c >= 'A' && c <= 'F')
- digit = c - 'A' + 10;
- else
- break;
- value = 16 * value + digit;
- }
- }
- else if (isdigit (c))
- {
- value = c - '0';
- while ((c = fgetc (fp)) != EOF
- && isdigit (c))
- value = 8 * value + c - '0';
- }
- }
- else
- {
- value = c - '0';
- while ((c = fgetc (fp)) != EOF
- && isdigit (c))
- value = 10 * value + c - '0';
- }
-
- if (c != EOF)
- ungetc (c, fp);
- *ival = value;
- c = XBM_TK_NUMBER;
- }
- else if (isalpha (c) || c == '_')
- {
- *sval++ = c;
- while ((c = fgetc (fp)) != EOF
- && (isalnum (c) || c == '_'))
- *sval++ = c;
- *sval = 0;
- if (c != EOF)
- ungetc (c, fp);
- c = XBM_TK_IDENT;
- }
-
- return c;
-}
-
-
-/* Replacement for XReadBitmapFileData which isn't available under old
- X versions. FILE is the name of the bitmap file to read. Set
- *WIDTH and *HEIGHT to the width and height of the image. Return in
- *DATA the bitmap data allocated with xmalloc. Value is non-zero if
- successful. */
-
-static int
-xbm_read_bitmap_file_data (file, width, height, data)
- char *file;
- int *width, *height;
- unsigned char **data;
-{
- FILE *fp;
- char buffer[BUFSIZ];
- int padding_p = 0;
- int v10 = 0;
- int bytes_per_line, i, nbytes;
- unsigned char *p;
- int value;
- int LA1;
-
-#define match() \
- LA1 = xbm_scan (fp, buffer, &value)
-
-#define expect(TOKEN) \
- if (LA1 != (TOKEN)) \
- goto failure; \
- else \
- match ()
-
-#define expect_ident(IDENT) \
- if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
- match (); \
- else \
- goto failure
-
- fp = fopen (file, "r");
- if (fp == NULL)
- return 0;
-
- *width = *height = -1;
- *data = NULL;
- LA1 = xbm_scan (fp, buffer, &value);
-
- /* Parse defines for width, height and hot-spots. */
- while (LA1 == '#')
- {
- match ();
- expect_ident ("define");
- expect (XBM_TK_IDENT);
-
- if (LA1 == XBM_TK_NUMBER);
- {
- char *p = strrchr (buffer, '_');
- p = p ? p + 1 : buffer;
- if (strcmp (p, "width") == 0)
- *width = value;
- else if (strcmp (p, "height") == 0)
- *height = value;
- }
- expect (XBM_TK_NUMBER);
- }
-
- if (*width < 0 || *height < 0)
- goto failure;
-
- /* Parse bits. Must start with `static'. */
- expect_ident ("static");
- if (LA1 == XBM_TK_IDENT)
- {
- if (strcmp (buffer, "unsigned") == 0)
- {
- match ();
- expect_ident ("char");
- }
- else if (strcmp (buffer, "short") == 0)
- {
- match ();
- v10 = 1;
- if (*width % 16 && *width % 16 < 9)
- padding_p = 1;
- }
- else if (strcmp (buffer, "char") == 0)
- match ();
- else
- goto failure;
- }
- else
- goto failure;
-
- expect (XBM_TK_IDENT);
- expect ('[');
- expect (']');
- expect ('=');
- expect ('{');
-
- bytes_per_line = (*width + 7) / 8 + padding_p;
- nbytes = bytes_per_line * *height;
- p = *data = (char *) xmalloc (nbytes);
-
- if (v10)
- {
-
- for (i = 0; i < nbytes; i += 2)
- {
- int val = value;
- expect (XBM_TK_NUMBER);
-
- *p++ = val;
- if (!padding_p || ((i + 2) % bytes_per_line))
- *p++ = value >> 8;
-
- if (LA1 == ',' || LA1 == '}')
- match ();
- else
- goto failure;
- }
- }
- else
- {
- for (i = 0; i < nbytes; ++i)
- {
- int val = value;
- expect (XBM_TK_NUMBER);
-
- *p++ = val;
-
- if (LA1 == ',' || LA1 == '}')
- match ();
- else
- goto failure;
- }
- }
-
- fclose (fp);
- return 1;
-
- failure:
-
- fclose (fp);
- if (*data)
- {
- xfree (*data);
- *data = NULL;
- }
- return 0;
-
-#undef match
-#undef expect
-#undef expect_ident
-}
-
-
-/* Load XBM image IMG which will be displayed on frame F from file
- SPECIFIED_FILE. Value is non-zero if successful. */
-
-static int
-xbm_load_image_from_file (f, img, specified_file)
- struct frame *f;
- struct image *img;
- Lisp_Object specified_file;
-{
- int rc;
- unsigned char *data;
- int success_p = 0;
- Lisp_Object file;
- struct gcpro gcpro1;
-
- xassert (STRINGP (specified_file));
- file = Qnil;
- GCPRO1 (file);
-
- file = x_find_image_file (specified_file);
- if (!STRINGP (file))
- {
- image_error ("Cannot find image file `%s'", specified_file, Qnil);
- UNGCPRO;
- return 0;
- }
-
- rc = xbm_read_bitmap_file_data (XSTRING (file)->data, &img->width,
- &img->height, &data);
- if (rc)
- {
- int depth = one_mac_display_info.n_cbits;
- unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
- unsigned long background = FRAME_BACKGROUND_PIXEL (f);
- Lisp_Object value;
-
- xassert (img->width > 0 && img->height > 0);
-
- /* Get foreground and background colors, maybe allocate colors. */
- value = image_spec_value (img->spec, QCforeground, NULL);
- if (!NILP (value))
- foreground = x_alloc_image_color (f, img, value, foreground);
-
- value = image_spec_value (img->spec, QCbackground, NULL);
- if (!NILP (value))
- background = x_alloc_image_color (f, img, value, background);
-
-#if 0 /* MAC_TODO : Port image display to Mac */
- BLOCK_INPUT;
- img->pixmap
- = XCreatePixmapFromBitmapData (FRAME_W32_DISPLAY (f),
- FRAME_W32_WINDOW (f),
- data,
- img->width, img->height,
- foreground, background,
- depth);
- xfree (data);
-
- if (img->pixmap == 0)
- {
- x_clear_image (f, img);
- image_error ("Unable to create X pixmap for `%s'", file, Qnil);
- }
- else
- success_p = 1;
-
- UNBLOCK_INPUT;
-#endif
- }
- else
- image_error ("Error loading XBM image `%s'", img->spec, Qnil);
-
- UNGCPRO;
- return success_p;
-}
-
-
-/* Fill image IMG which is used on frame F with pixmap data. Value is
- non-zero if successful. */
-
-static int
-xbm_load (f, img)
- struct frame *f;
- struct image *img;
-{
- int success_p = 0;
- Lisp_Object file_name;
-
- xassert (xbm_image_p (img->spec));
-
- /* If IMG->spec specifies a file name, create a non-file spec from it. */
- file_name = image_spec_value (img->spec, QCfile, NULL);
- if (STRINGP (file_name))
- success_p = xbm_load_image_from_file (f, img, file_name);
- else
- {
- struct image_keyword fmt[XBM_LAST];
- Lisp_Object data;
- int depth;
- unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
- unsigned long background = FRAME_BACKGROUND_PIXEL (f);
- char *bits;
- int parsed_p;
-
- /* Parse the list specification. */
- bcopy (xbm_format, fmt, sizeof fmt);
- parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
- xassert (parsed_p);
-
- /* Get specified width, and height. */
- img->width = XFASTINT (fmt[XBM_WIDTH].value);
- img->height = XFASTINT (fmt[XBM_HEIGHT].value);
- xassert (img->width > 0 && img->height > 0);
-
- BLOCK_INPUT;
-
- if (fmt[XBM_ASCENT].count)
- img->ascent = XFASTINT (fmt[XBM_ASCENT].value);
-
- /* Get foreground and background colors, maybe allocate colors. */
- if (fmt[XBM_FOREGROUND].count)
- foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
- foreground);
- if (fmt[XBM_BACKGROUND].count)
- background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
- background);
-
- /* Set bits to the bitmap image data. */
- data = fmt[XBM_DATA].value;
- if (VECTORP (data))
- {
- int i;
- char *p;
- int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
-
- p = bits = (char *) alloca (nbytes * img->height);
- for (i = 0; i < img->height; ++i, p += nbytes)
- {
- Lisp_Object line = XVECTOR (data)->contents[i];
- if (STRINGP (line))
- bcopy (XSTRING (line)->data, p, nbytes);
- else
- bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
- }
- }
- else if (STRINGP (data))
- bits = XSTRING (data)->data;
- else
- bits = XBOOL_VECTOR (data)->data;
-
-#if 0 /* MAC_TODO : port Mac display code */
- /* Create the pixmap. */
- depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
- img->pixmap
- = XCreatePixmapFromBitmapData (FRAME_W32_DISPLAY (f),
- FRAME_W32_WINDOW (f),
- bits,
- img->width, img->height,
- foreground, background,
- depth);
-#endif /* MAC_TODO */
-
- if (img->pixmap)
- success_p = 1;
- else
- {
- image_error ("Unable to create pixmap for XBM image `%s'",
- img->spec, Qnil);
- x_clear_image (f, img);
- }
-
- UNBLOCK_INPUT;
- }
-
- return success_p;
-}
-
-
-\f
-/***********************************************************************
- XPM images
- ***********************************************************************/
-
-#if HAVE_XPM
-
-static int xpm_image_p P_ ((Lisp_Object object));
-static int xpm_load P_ ((struct frame *f, struct image *img));
-static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
-
-#include "X11/xpm.h"
-
-/* The symbol `xpm' identifying XPM-format images. */
-
-Lisp_Object Qxpm;
-
-/* Indices of image specification fields in xpm_format, below. */
-
-enum xpm_keyword_index
-{
- XPM_TYPE,
- XPM_FILE,
- XPM_DATA,
- XPM_ASCENT,
- XPM_MARGIN,
- XPM_RELIEF,
- XPM_ALGORITHM,
- XPM_HEURISTIC_MASK,
- XPM_COLOR_SYMBOLS,
- XPM_LAST
-};
-
-/* Vector of image_keyword structures describing the format
- of valid XPM image specifications. */
-
-static struct image_keyword xpm_format[XPM_LAST] =
-{
- {":type", IMAGE_SYMBOL_VALUE, 1},
- {":file", IMAGE_STRING_VALUE, 0},
- {":data", IMAGE_STRING_VALUE, 0},
- {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
- {":relief", IMAGE_INTEGER_VALUE, 0},
- {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
-};
-
-/* Structure describing the image type XBM. */
-
-static struct image_type xpm_type =
-{
- &Qxpm,
- xpm_image_p,
- xpm_load,
- x_clear_image,
- NULL
-};
-
-
-/* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
- for XPM images. Such a list must consist of conses whose car and
- cdr are strings. */
-
-static int
-xpm_valid_color_symbols_p (color_symbols)
- Lisp_Object color_symbols;
-{
- while (CONSP (color_symbols))
- {
- Lisp_Object sym = XCAR (color_symbols);
- if (!CONSP (sym)
- || !STRINGP (XCAR (sym))
- || !STRINGP (XCDR (sym)))
- break;
- color_symbols = XCDR (color_symbols);
- }
-
- return NILP (color_symbols);
-}
-
-
-/* Value is non-zero if OBJECT is a valid XPM image specification. */
-
-static int
-xpm_image_p (object)
- Lisp_Object object;
-{
- struct image_keyword fmt[XPM_LAST];
- bcopy (xpm_format, fmt, sizeof fmt);
- return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
- /* Either `:file' or `:data' must be present. */
- && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
- /* Either no `:color-symbols' or it's a list of conses
- whose car and cdr are strings. */
- && (fmt[XPM_COLOR_SYMBOLS].count == 0
- || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value))
- && (fmt[XPM_ASCENT].count == 0
- || XFASTINT (fmt[XPM_ASCENT].value) < 100));
-}
-
-
-/* Load image IMG which will be displayed on frame F. Value is
- non-zero if successful. */
-
-static int
-xpm_load (f, img)
- struct frame *f;
- struct image *img;
-{
- int rc, i;
- XpmAttributes attrs;
- Lisp_Object specified_file, color_symbols;
-
- /* Configure the XPM lib. Use the visual of frame F. Allocate
- close colors. Return colors allocated. */
- bzero (&attrs, sizeof attrs);
- attrs.visual = FRAME_X_VISUAL (f);
- attrs.colormap = FRAME_X_COLORMAP (f);
- attrs.valuemask |= XpmVisual;
- attrs.valuemask |= XpmColormap;
- attrs.valuemask |= XpmReturnAllocPixels;
-#ifdef XpmAllocCloseColors
- attrs.alloc_close_colors = 1;
- attrs.valuemask |= XpmAllocCloseColors;
-#else
- attrs.closeness = 600;
- attrs.valuemask |= XpmCloseness;
-#endif
-
- /* If image specification contains symbolic color definitions, add
- these to `attrs'. */
- color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
- if (CONSP (color_symbols))
- {
- Lisp_Object tail;
- XpmColorSymbol *xpm_syms;
- int i, size;
-
- attrs.valuemask |= XpmColorSymbols;
-
- /* Count number of symbols. */
- attrs.numsymbols = 0;
- for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
- ++attrs.numsymbols;
-
- /* Allocate an XpmColorSymbol array. */
- size = attrs.numsymbols * sizeof *xpm_syms;
- xpm_syms = (XpmColorSymbol *) alloca (size);
- bzero (xpm_syms, size);
- attrs.colorsymbols = xpm_syms;
-
- /* Fill the color symbol array. */
- for (tail = color_symbols, i = 0;
- CONSP (tail);
- ++i, tail = XCDR (tail))
- {
- Lisp_Object name = XCAR (XCAR (tail));
- Lisp_Object color = XCDR (XCAR (tail));
- xpm_syms[i].name = (char *) alloca (XSTRING (name)->size + 1);
- strcpy (xpm_syms[i].name, XSTRING (name)->data);
- xpm_syms[i].value = (char *) alloca (XSTRING (color)->size + 1);
- strcpy (xpm_syms[i].value, XSTRING (color)->data);
- }
- }
-
- /* Create a pixmap for the image, either from a file, or from a
- string buffer containing data in the same format as an XPM file. */
- BLOCK_INPUT;
- specified_file = image_spec_value (img->spec, QCfile, NULL);
- if (STRINGP (specified_file))
- {
- Lisp_Object file = x_find_image_file (specified_file);
- if (!STRINGP (file))
- {
- image_error ("Cannot find image file `%s'", specified_file, Qnil);
- UNBLOCK_INPUT;
- return 0;
- }
-
- rc = XpmReadFileToPixmap (NULL, FRAME_W32_WINDOW (f),
- XSTRING (file)->data, &img->pixmap, &img->mask,
- &attrs);
- }
- else
- {
- Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
- rc = XpmCreatePixmapFromBuffer (NULL, FRAME_W32_WINDOW (f),
- XSTRING (buffer)->data,
- &img->pixmap, &img->mask,
- &attrs);
- }
- UNBLOCK_INPUT;
-
- if (rc == XpmSuccess)
- {
- /* Remember allocated colors. */
- img->ncolors = attrs.nalloc_pixels;
- img->colors = (unsigned long *) xmalloc (img->ncolors
- * sizeof *img->colors);
- for (i = 0; i < attrs.nalloc_pixels; ++i)
- img->colors[i] = attrs.alloc_pixels[i];
-
- img->width = attrs.width;
- img->height = attrs.height;
- xassert (img->width > 0 && img->height > 0);
-
- /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
- BLOCK_INPUT;
- XpmFreeAttributes (&attrs);
- UNBLOCK_INPUT;
- }
- else
- {
- switch (rc)
- {
- case XpmOpenFailed:
- image_error ("Error opening XPM file (%s)", img->spec, Qnil);
- break;
-
- case XpmFileInvalid:
- image_error ("Invalid XPM file (%s)", img->spec, Qnil);
- break;
-
- case XpmNoMemory:
- image_error ("Out of memory (%s)", img->spec, Qnil);
- break;
-
- case XpmColorFailed:
- image_error ("Color allocation error (%s)", img->spec, Qnil);
- break;
-
- default:
- image_error ("Unknown error (%s)", img->spec, Qnil);
- break;
- }
- }
-
- return rc == XpmSuccess;
-}
-
-#endif /* HAVE_XPM != 0 */
-
-\f
-#if 0 /* MAC_TODO : Color tables on Mac. */
-/***********************************************************************
- Color table
- ***********************************************************************/
-
-/* An entry in the color table mapping an RGB color to a pixel color. */
-
-struct ct_color
-{
- int r, g, b;
- unsigned long pixel;
-
- /* Next in color table collision list. */
- struct ct_color *next;
-};
-
-/* The bucket vector size to use. Must be prime. */
-
-#define CT_SIZE 101
-
-/* Value is a hash of the RGB color given by R, G, and B. */
-
-#define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
-
-/* The color hash table. */
-
-struct ct_color **ct_table;
-
-/* Number of entries in the color table. */
-
-int ct_colors_allocated;
-
-/* Function prototypes. */
-
-static void init_color_table P_ ((void));
-static void free_color_table P_ ((void));
-static unsigned long *colors_in_color_table P_ ((int *n));
-static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
-static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
-
-
-/* Initialize the color table. */
-
-static void
-init_color_table ()
-{
- int size = CT_SIZE * sizeof (*ct_table);
- ct_table = (struct ct_color **) xmalloc (size);
- bzero (ct_table, size);
- ct_colors_allocated = 0;
-}
-
-
-/* Free memory associated with the color table. */
-
-static void
-free_color_table ()
-{
- int i;
- struct ct_color *p, *next;
-
- for (i = 0; i < CT_SIZE; ++i)
- for (p = ct_table[i]; p; p = next)
- {
- next = p->next;
- xfree (p);
- }
-
- xfree (ct_table);
- ct_table = NULL;
-}
-
-
-/* Value is a pixel color for RGB color R, G, B on frame F. If an
- entry for that color already is in the color table, return the
- pixel color of that entry. Otherwise, allocate a new color for R,
- G, B, and make an entry in the color table. */
-
-static unsigned long
-lookup_rgb_color (f, r, g, b)
- struct frame *f;
- int r, g, b;
-{
- unsigned hash = CT_HASH_RGB (r, g, b);
- int i = hash % CT_SIZE;
- struct ct_color *p;
-
- for (p = ct_table[i]; p; p = p->next)
- if (p->r == r && p->g == g && p->b == b)
- break;
-
- if (p == NULL)
- {
- COLORREF color;
- Colormap cmap;
- int rc;
-
- color = RGB_TO_ULONG (r, g, b);
-
- ++ct_colors_allocated;
-
- p = (struct ct_color *) xmalloc (sizeof *p);
- p->r = r;
- p->g = g;
- p->b = b;
- p->pixel = color;
- p->next = ct_table[i];
- ct_table[i] = p;
- }
-
- return p->pixel;
-}
-
-
-/* Look up pixel color PIXEL which is used on frame F in the color
- table. If not already present, allocate it. Value is PIXEL. */
-
-static unsigned long
-lookup_pixel_color (f, pixel)
- struct frame *f;
- unsigned long pixel;
-{
- int i = pixel % CT_SIZE;
- struct ct_color *p;
-
- for (p = ct_table[i]; p; p = p->next)
- if (p->pixel == pixel)
- break;
-
- if (p == NULL)
- {
- XColor color;
- Colormap cmap;
- int rc;
-
- BLOCK_INPUT;
-
- cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
- color.pixel = pixel;
- XQueryColor (NULL, cmap, &color);
- rc = x_alloc_nearest_color (f, cmap, &color);
- UNBLOCK_INPUT;
-
- if (rc)
- {
- ++ct_colors_allocated;
-
- p = (struct ct_color *) xmalloc (sizeof *p);
- p->r = color.red;
- p->g = color.green;
- p->b = color.blue;
- p->pixel = pixel;
- p->next = ct_table[i];
- ct_table[i] = p;
- }
- else
- return FRAME_FOREGROUND_PIXEL (f);
- }
- return p->pixel;
-}
-
-
-/* Value is a vector of all pixel colors contained in the color table,
- allocated via xmalloc. Set *N to the number of colors. */
-
-static unsigned long *
-colors_in_color_table (n)
- int *n;
-{
- int i, j;
- struct ct_color *p;
- unsigned long *colors;
-
- if (ct_colors_allocated == 0)
- {
- *n = 0;
- colors = NULL;
- }
- else
- {
- colors = (unsigned long *) xmalloc (ct_colors_allocated
- * sizeof *colors);
- *n = ct_colors_allocated;
-
- for (i = j = 0; i < CT_SIZE; ++i)
- for (p = ct_table[i]; p; p = p->next)
- colors[j++] = p->pixel;
- }
-
- return colors;
-}
-
-#endif /* MAC_TODO */
-
-\f
-/***********************************************************************
- Algorithms
- ***********************************************************************/
-
-#if 0 /* MAC_TODO : Mac versions of low level algorithms */
-static void x_laplace_write_row P_ ((struct frame *, long *,
- int, XImage *, int));
-static void x_laplace_read_row P_ ((struct frame *, Colormap,
- XColor *, int, XImage *, int));
-
-
-/* Fill COLORS with RGB colors from row Y of image XIMG. F is the
- frame we operate on, CMAP is the color-map in effect, and WIDTH is
- the width of one row in the image. */
-
-static void
-x_laplace_read_row (f, cmap, colors, width, ximg, y)
- struct frame *f;
- Colormap cmap;
- XColor *colors;
- int width;
- XImage *ximg;
- int y;
-{
- int x;
-
- for (x = 0; x < width; ++x)
- colors[x].pixel = XGetPixel (ximg, x, y);
-
- XQueryColors (NULL, cmap, colors, width);
-}
-
-
-/* Write row Y of image XIMG. PIXELS is an array of WIDTH longs
- containing the pixel colors to write. F is the frame we are
- working on. */
-
-static void
-x_laplace_write_row (f, pixels, width, ximg, y)
- struct frame *f;
- long *pixels;
- int width;
- XImage *ximg;
- int y;
-{
- int x;
-
- for (x = 0; x < width; ++x)
- XPutPixel (ximg, x, y, pixels[x]);
-}
-#endif
-
-/* Transform image IMG which is used on frame F with a Laplace
- edge-detection algorithm. The result is an image that can be used
- to draw disabled buttons, for example. */
-
-static void
-x_laplace (f, img)
- struct frame *f;
- struct image *img;
-{
-#if 0 /* MAC_TODO : Mac version */
- Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
- XImage *ximg, *oimg;
- XColor *in[3];
- long *out;
- Pixmap pixmap;
- int x, y, i;
- long pixel;
- int in_y, out_y, rc;
- int mv2 = 45000;
-
- BLOCK_INPUT;
-
- /* Get the X image IMG->pixmap. */
- ximg = XGetImage (NULL, img->pixmap,
- 0, 0, img->width, img->height, ~0, ZPixmap);
-
- /* Allocate 3 input rows, and one output row of colors. */
- for (i = 0; i < 3; ++i)
- in[i] = (XColor *) alloca (img->width * sizeof (XColor));
- out = (long *) alloca (img->width * sizeof (long));
-
- /* Create an X image for output. */
- rc = x_create_x_image_and_pixmap (f, img->width, img->height, 0,
- &oimg, &pixmap);
-
- /* Fill first two rows. */
- x_laplace_read_row (f, cmap, in[0], img->width, ximg, 0);
- x_laplace_read_row (f, cmap, in[1], img->width, ximg, 1);
- in_y = 2;
-
- /* Write first row, all zeros. */
- init_color_table ();
- pixel = lookup_rgb_color (f, 0, 0, 0);
- for (x = 0; x < img->width; ++x)
- out[x] = pixel;
- x_laplace_write_row (f, out, img->width, oimg, 0);
- out_y = 1;
-
- for (y = 2; y < img->height; ++y)
- {
- int rowa = y % 3;
- int rowb = (y + 2) % 3;
-
- x_laplace_read_row (f, cmap, in[rowa], img->width, ximg, in_y++);
-
- for (x = 0; x < img->width - 2; ++x)
- {
- int r = in[rowa][x].red + mv2 - in[rowb][x + 2].red;
- int g = in[rowa][x].green + mv2 - in[rowb][x + 2].green;
- int b = in[rowa][x].blue + mv2 - in[rowb][x + 2].blue;
-
- out[x + 1] = lookup_rgb_color (f, r & 0xffff, g & 0xffff,
- b & 0xffff);
- }
-
- x_laplace_write_row (f, out, img->width, oimg, out_y++);
- }
-
- /* Write last line, all zeros. */
- for (x = 0; x < img->width; ++x)
- out[x] = pixel;
- x_laplace_write_row (f, out, img->width, oimg, out_y);
-
- /* Free the input image, and free resources of IMG. */
- XDestroyImage (ximg);
- x_clear_image (f, img);
-
- /* Put the output image into pixmap, and destroy it. */
- x_put_x_image (f, oimg, pixmap, img->width, img->height);
- x_destroy_x_image (oimg);
-
- /* Remember new pixmap and colors in IMG. */
- img->pixmap = pixmap;
- img->colors = colors_in_color_table (&img->ncolors);
- free_color_table ();
-
- UNBLOCK_INPUT;
-#endif /* MAC_TODO */
-}
-
-
-/* Build a mask for image IMG which is used on frame F. FILE is the
- name of an image file, for error messages. HOW determines how to
- determine the background color of IMG. If it is a list '(R G B)',
- with R, G, and B being integers >= 0, take that as the color of the
- background. Otherwise, determine the background color of IMG
- heuristically. Value is non-zero if successful. */
-
-static int
-x_build_heuristic_mask (f, img, how)
- struct frame *f;
- struct image *img;
- Lisp_Object how;
-{
-#if 0 /* MAC_TODO : Mac version */
- Display *dpy = FRAME_W32_DISPLAY (f);
- XImage *ximg, *mask_img;
- int x, y, rc, look_at_corners_p;
- unsigned long bg;
-
- BLOCK_INPUT;
-
- /* Create an image and pixmap serving as mask. */
- rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
- &mask_img, &img->mask);
- if (!rc)
- {
- UNBLOCK_INPUT;
- return 0;
- }
-
- /* Get the X image of IMG->pixmap. */
- ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
- ~0, ZPixmap);
-
- /* Determine the background color of ximg. If HOW is `(R G B)'
- take that as color. Otherwise, try to determine the color
- heuristically. */
- look_at_corners_p = 1;
-
- if (CONSP (how))
- {
- int rgb[3], i = 0;
-
- while (i < 3
- && CONSP (how)
- && NATNUMP (XCAR (how)))
- {
- rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
- how = XCDR (how);
- }
-
- if (i == 3 && NILP (how))
- {
- char color_name[30];
- XColor exact, color;
- Colormap cmap;
-
- sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
-
- cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
- if (XLookupColor (dpy, cmap, color_name, &exact, &color))
- {
- bg = color.pixel;
- look_at_corners_p = 0;
- }
- }
- }
-
- if (look_at_corners_p)
- {
- unsigned long corners[4];
- int i, best_count;
-
- /* Get the colors at the corners of ximg. */
- corners[0] = XGetPixel (ximg, 0, 0);
- corners[1] = XGetPixel (ximg, img->width - 1, 0);
- corners[2] = XGetPixel (ximg, img->width - 1, img->height - 1);
- corners[3] = XGetPixel (ximg, 0, img->height - 1);
-
- /* Choose the most frequently found color as background. */
- for (i = best_count = 0; i < 4; ++i)
- {
- int j, n;
-
- for (j = n = 0; j < 4; ++j)
- if (corners[i] == corners[j])
- ++n;
-
- if (n > best_count)
- bg = corners[i], best_count = n;
- }
- }
-
- /* Set all bits in mask_img to 1 whose color in ximg is different
- from the background color bg. */
- for (y = 0; y < img->height; ++y)
- for (x = 0; x < img->width; ++x)
- XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg);
-
- /* Put mask_img into img->mask. */
- x_put_x_image (f, mask_img, img->mask, img->width, img->height);
- x_destroy_x_image (mask_img);
- XDestroyImage (ximg);
-
- UNBLOCK_INPUT;
-#endif /* MAC_TODO */
-
- return 1;
-}
-
-
-\f
-/***********************************************************************
- PBM (mono, gray, color)
- ***********************************************************************/
-#ifdef HAVE_PBM
-
-static int pbm_image_p P_ ((Lisp_Object object));
-static int pbm_load P_ ((struct frame *f, struct image *img));
-static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
-
-/* The symbol `pbm' identifying images of this type. */
-
-Lisp_Object Qpbm;
-
-/* Indices of image specification fields in gs_format, below. */
-
-enum pbm_keyword_index
-{
- PBM_TYPE,
- PBM_FILE,
- PBM_DATA,
- PBM_ASCENT,
- PBM_MARGIN,
- PBM_RELIEF,
- PBM_ALGORITHM,
- PBM_HEURISTIC_MASK,
- PBM_LAST
-};
-
-/* Vector of image_keyword structures describing the format
- of valid user-defined image specifications. */
-
-static struct image_keyword pbm_format[PBM_LAST] =
-{
- {":type", IMAGE_SYMBOL_VALUE, 1},
- {":file", IMAGE_STRING_VALUE, 0},
- {":data", IMAGE_STRING_VALUE, 0},
- {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
- {":relief", IMAGE_INTEGER_VALUE, 0},
- {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
-};
-
-/* Structure describing the image type `pbm'. */
-
-static struct image_type pbm_type =
-{
- &Qpbm,
- pbm_image_p,
- pbm_load,
- x_clear_image,
- NULL
-};
-
-
-/* Return non-zero if OBJECT is a valid PBM image specification. */
-
-static int
-pbm_image_p (object)
- Lisp_Object object;
-{
- struct image_keyword fmt[PBM_LAST];
-
- bcopy (pbm_format, fmt, sizeof fmt);
-
- if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm)
- || (fmt[PBM_ASCENT].count
- && XFASTINT (fmt[PBM_ASCENT].value) > 100))
- return 0;
-
- /* Must specify either :data or :file. */
- return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
-}
-
-
-/* Scan a decimal number from *S and return it. Advance *S while
- reading the number. END is the end of the string. Value is -1 at
- end of input. */
-
-static int
-pbm_scan_number (s, end)
- unsigned char **s, *end;
-{
- int c, val = -1;
-
- while (*s < end)
- {
- /* Skip white-space. */
- while (*s < end && (c = *(*s)++, isspace (c)))
- ;
-
- if (c == '#')
- {
- /* Skip comment to end of line. */
- while (*s < end && (c = *(*s)++, c != '\n'))
- ;
- }
- else if (isdigit (c))
- {
- /* Read decimal number. */
- val = c - '0';
- while (*s < end && (c = *(*s)++, isdigit (c)))
- val = 10 * val + c - '0';
- break;
- }
- else
- break;
- }
-
- return val;
-}
-
-
-/* Read FILE into memory. Value is a pointer to a buffer allocated
- with xmalloc holding FILE's contents. Value is null if an error
- occured. *SIZE is set to the size of the file. */
-
-static char *
-pbm_read_file (file, size)
- Lisp_Object file;
- int *size;
-{
- FILE *fp = NULL;
- char *buf = NULL;
- struct stat st;
-
- if (stat (XSTRING (file)->data, &st) == 0
- && (fp = fopen (XSTRING (file)->data, "r")) != NULL
- && (buf = (char *) xmalloc (st.st_size),
- fread (buf, 1, st.st_size, fp) == st.st_size))
- {
- *size = st.st_size;
- fclose (fp);
- }
- else
- {
- if (fp)
- fclose (fp);
- if (buf)
- {
- xfree (buf);
- buf = NULL;
- }
- }
-
- return buf;
-}
-
-
-/* Load PBM image IMG for use on frame F. */
-
-static int
-pbm_load (f, img)
- struct frame *f;
- struct image *img;
-{
- int raw_p, x, y;
- int width, height, max_color_idx = 0;
- XImage *ximg;
- Lisp_Object file, specified_file;
- enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
- struct gcpro gcpro1;
- unsigned char *contents = NULL;
- unsigned char *end, *p;
- int size;
-
- specified_file = image_spec_value (img->spec, QCfile, NULL);
- file = Qnil;
- GCPRO1 (file);
-
- if (STRINGP (specified_file))
- {
- file = x_find_image_file (specified_file);
- if (!STRINGP (file))
- {
- image_error ("Cannot find image file `%s'", specified_file, Qnil);
- UNGCPRO;
- return 0;
- }
-
- contents = pbm_read_file (file, &size);
- if (contents == NULL)
- {
- image_error ("Error reading `%s'", file, Qnil);
- UNGCPRO;
- return 0;
- }
-
- p = contents;
- end = contents + size;
- }
- else
- {
- Lisp_Object data;
- data = image_spec_value (img->spec, QCdata, NULL);
- p = XSTRING (data)->data;
- end = p + STRING_BYTES (XSTRING (data));
- }
-
- /* Check magic number. */
- if (end - p < 2 || *p++ != 'P')
- {
- image_error ("Not a PBM image: `%s'", img->spec, Qnil);
- error:
- xfree (contents);
- UNGCPRO;
- return 0;
- }
-
- switch (*p++)
- {
- case '1':
- raw_p = 0, type = PBM_MONO;
- break;
-
- case '2':
- raw_p = 0, type = PBM_GRAY;
- break;
-
- case '3':
- raw_p = 0, type = PBM_COLOR;
- break;
-
- case '4':
- raw_p = 1, type = PBM_MONO;
- break;
-
- case '5':
- raw_p = 1, type = PBM_GRAY;
- break;
-
- case '6':
- raw_p = 1, type = PBM_COLOR;
- break;
-
- default:
- image_error ("Not a PBM image: `%s'", img->spec, Qnil);
- goto error;
- }
-
- /* Read width, height, maximum color-component. Characters
- starting with `#' up to the end of a line are ignored. */
- width = pbm_scan_number (&p, end);
- height = pbm_scan_number (&p, end);
-
- if (type != PBM_MONO)
- {
- max_color_idx = pbm_scan_number (&p, end);
- if (raw_p && max_color_idx > 255)
- max_color_idx = 255;
- }
-
- if (width < 0
- || height < 0
- || (type != PBM_MONO && max_color_idx < 0))
- goto error;
-
- BLOCK_INPUT;
- if (!x_create_x_image_and_pixmap (f, width, height, 0,
- &ximg, &img->pixmap))
- {
- UNBLOCK_INPUT;
- goto error;
- }
-
- /* Initialize the color hash table. */
- init_color_table ();
-
- if (type == PBM_MONO)
- {
- int c = 0, g;
-
- for (y = 0; y < height; ++y)
- for (x = 0; x < width; ++x)
- {
- if (raw_p)
- {
- if ((x & 7) == 0)
- c = *p++;
- g = c & 0x80;
- c <<= 1;
- }
- else
- g = pbm_scan_number (&p, end);
-
- XPutPixel (ximg, x, y, (g
- ? FRAME_FOREGROUND_PIXEL (f)
- : FRAME_BACKGROUND_PIXEL (f)));
- }
- }
- else
- {
- for (y = 0; y < height; ++y)
- for (x = 0; x < width; ++x)
- {
- int r, g, b;
-
- if (type == PBM_GRAY)
- r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
- else if (raw_p)
- {
- r = *p++;
- g = *p++;
- b = *p++;
- }
- else
- {
- r = pbm_scan_number (&p, end);
- g = pbm_scan_number (&p, end);
- b = pbm_scan_number (&p, end);
- }
-
- if (r < 0 || g < 0 || b < 0)
- {
- xfree (ximg->data);
- ximg->data = NULL;
- XDestroyImage (ximg);
- UNBLOCK_INPUT;
- image_error ("Invalid pixel value in image `%s'",
- img->spec, Qnil);
- goto error;
- }
-
- /* RGB values are now in the range 0..max_color_idx.
- Scale this to the range 0..0xffff supported by X. */
- r = (double) r * 65535 / max_color_idx;
- g = (double) g * 65535 / max_color_idx;
- b = (double) b * 65535 / max_color_idx;
- XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
- }
- }
-
- /* Store in IMG->colors the colors allocated for the image, and
- free the color table. */
- img->colors = colors_in_color_table (&img->ncolors);
- free_color_table ();
-
- /* Put the image into a pixmap. */
- x_put_x_image (f, ximg, img->pixmap, width, height);
- x_destroy_x_image (ximg);
- UNBLOCK_INPUT;
-
- img->width = width;
- img->height = height;
-
- UNGCPRO;
- xfree (contents);
- return 1;
-}
-#endif /* HAVE_PBM */
-
-\f
-/***********************************************************************
- PNG
- ***********************************************************************/
-
-#if HAVE_PNG
-
-#include <png.h>
-
-/* Function prototypes. */
-
-static int png_image_p P_ ((Lisp_Object object));
-static int png_load P_ ((struct frame *f, struct image *img));
-
-/* The symbol `png' identifying images of this type. */
-
-Lisp_Object Qpng;
-
-/* Indices of image specification fields in png_format, below. */
-
-enum png_keyword_index
-{
- PNG_TYPE,
- PNG_DATA,
- PNG_FILE,
- PNG_ASCENT,
- PNG_MARGIN,
- PNG_RELIEF,
- PNG_ALGORITHM,
- PNG_HEURISTIC_MASK,
- PNG_LAST
-};
-
-/* Vector of image_keyword structures describing the format
- of valid user-defined image specifications. */
-
-static struct image_keyword png_format[PNG_LAST] =
-{
- {":type", IMAGE_SYMBOL_VALUE, 1},
- {":data", IMAGE_STRING_VALUE, 0},
- {":file", IMAGE_STRING_VALUE, 0},
- {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
- {":relief", IMAGE_INTEGER_VALUE, 0},
- {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
-};
-
-/* Structure describing the image type `png'. */
-
-static struct image_type png_type =
-{
- &Qpng,
- png_image_p,
- png_load,
- x_clear_image,
- NULL
-};
-
-
-/* Return non-zero if OBJECT is a valid PNG image specification. */
-
-static int
-png_image_p (object)
- Lisp_Object object;
-{
- struct image_keyword fmt[PNG_LAST];
- bcopy (png_format, fmt, sizeof fmt);
-
- if (!parse_image_spec (object, fmt, PNG_LAST, Qpng)
- || (fmt[PNG_ASCENT].count
- && XFASTINT (fmt[PNG_ASCENT].value) > 100))
- return 0;
-
- /* Must specify either the :data or :file keyword. */
- return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
-}
-
-
-/* Error and warning handlers installed when the PNG library
- is initialized. */
-
-static void
-my_png_error (png_ptr, msg)
- png_struct *png_ptr;
- char *msg;
-{
- xassert (png_ptr != NULL);
- image_error ("PNG error: %s", build_string (msg), Qnil);
- longjmp (png_ptr->jmpbuf, 1);
-}
-
-
-static void
-my_png_warning (png_ptr, msg)
- png_struct *png_ptr;
- char *msg;
-{
- xassert (png_ptr != NULL);
- image_error ("PNG warning: %s", build_string (msg), Qnil);
-}
-
-/* Memory source for PNG decoding. */
-
-struct png_memory_storage
-{
- unsigned char *bytes; /* The data */
- size_t len; /* How big is it? */
- int index; /* Where are we? */
-};
-
-
-/* Function set as reader function when reading PNG image from memory.
- PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
- bytes from the input to DATA. */
-
-static void
-png_read_from_memory (png_ptr, data, length)
- png_structp png_ptr;
- png_bytep data;
- png_size_t length;
-{
- struct png_memory_storage *tbr
- = (struct png_memory_storage *) png_get_io_ptr (png_ptr);
-
- if (length > tbr->len - tbr->index)
- png_error (png_ptr, "Read error");
-
- bcopy (tbr->bytes + tbr->index, data, length);
- tbr->index = tbr->index + length;
-}
-
-/* Load PNG image IMG for use on frame F. Value is non-zero if
- successful. */
-
-static int
-png_load (f, img)
- struct frame *f;
- struct image *img;
-{
- Lisp_Object file, specified_file;
- Lisp_Object specified_data;
- int x, y, i;
- XImage *ximg, *mask_img = NULL;
- struct gcpro gcpro1;
- png_struct *png_ptr = NULL;
- png_info *info_ptr = NULL, *end_info = NULL;
- FILE *fp = NULL;
- png_byte sig[8];
- png_byte *pixels = NULL;
- png_byte **rows = NULL;
- png_uint_32 width, height;
- int bit_depth, color_type, interlace_type;
- png_byte channels;
- png_uint_32 row_bytes;
- int transparent_p;
- char *gamma_str;
- double screen_gamma, image_gamma;
- int intent;
- struct png_memory_storage tbr; /* Data to be read */
-
- /* Find out what file to load. */
- specified_file = image_spec_value (img->spec, QCfile, NULL);
- specified_data = image_spec_value (img->spec, QCdata, NULL);
- file = Qnil;
- GCPRO1 (file);
-
- if (NILP (specified_data))
- {
- file = x_find_image_file (specified_file);
- if (!STRINGP (file))
- {
- image_error ("Cannot find image file `%s'", specified_file, Qnil);
- UNGCPRO;
- return 0;
- }
-
- /* Open the image file. */
- fp = fopen (XSTRING (file)->data, "rb");
- if (!fp)
- {
- image_error ("Cannot open image file `%s'", file, Qnil);
- UNGCPRO;
- fclose (fp);
- return 0;
- }
-
- /* Check PNG signature. */
- if (fread (sig, 1, sizeof sig, fp) != sizeof sig
- || !png_check_sig (sig, sizeof sig))
- {
- image_error ("Not a PNG file:` %s'", file, Qnil);
- UNGCPRO;
- fclose (fp);
- return 0;
- }
- }
- else
- {
- /* Read from memory. */
- tbr.bytes = XSTRING (specified_data)->data;
- tbr.len = STRING_BYTES (XSTRING (specified_data));
- tbr.index = 0;
-
- /* Check PNG signature. */
- if (tbr.len < sizeof sig
- || !png_check_sig (tbr.bytes, sizeof sig))
- {
- image_error ("Not a PNG image: `%s'", img->spec, Qnil);
- UNGCPRO;
- return 0;
- }
-
- /* Need to skip past the signature. */
- tbr.bytes += sizeof (sig);
- }
-
- /* Initialize read and info structs for PNG lib. */
- png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
- my_png_error, my_png_warning);
- if (!png_ptr)
- {
- if (fp) fclose (fp);
- UNGCPRO;
- return 0;
- }
-
- info_ptr = png_create_info_struct (png_ptr);
- if (!info_ptr)
- {
- png_destroy_read_struct (&png_ptr, NULL, NULL);
- if (fp) fclose (fp);
- UNGCPRO;
- return 0;
- }
-
- end_info = png_create_info_struct (png_ptr);
- if (!end_info)
- {
- png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
- if (fp) fclose (fp);
- UNGCPRO;
- return 0;
- }
-
- /* Set error jump-back. We come back here when the PNG library
- detects an error. */
- if (setjmp (png_ptr->jmpbuf))
- {
- error:
- if (png_ptr)
- png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
- xfree (pixels);
- xfree (rows);
- if (fp) fclose (fp);
- UNGCPRO;
- return 0;
- }
-
- /* Read image info. */
- if (!NILP (specified_data))
- png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
- else
- png_init_io (png_ptr, fp);
-
- png_set_sig_bytes (png_ptr, sizeof sig);
- png_read_info (png_ptr, info_ptr);
- png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
- &interlace_type, NULL, NULL);
-
- /* If image contains simply transparency data, we prefer to
- construct a clipping mask. */
- if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
- transparent_p = 1;
- else
- transparent_p = 0;
-
- /* This function is easier to write if we only have to handle
- one data format: RGB or RGBA with 8 bits per channel. Let's
- transform other formats into that format. */
-
- /* Strip more than 8 bits per channel. */
- if (bit_depth == 16)
- png_set_strip_16 (png_ptr);
-
- /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
- if available. */
- png_set_expand (png_ptr);
-
- /* Convert grayscale images to RGB. */
- if (color_type == PNG_COLOR_TYPE_GRAY
- || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
- png_set_gray_to_rgb (png_ptr);
-
- /* The value 2.2 is a guess for PC monitors from PNG example.c. */
- gamma_str = getenv ("SCREEN_GAMMA");
- screen_gamma = gamma_str ? atof (gamma_str) : 2.2;
-
- /* Tell the PNG lib to handle gamma correction for us. */
-
-#if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
- if (png_get_sRGB (png_ptr, info_ptr, &intent))
- /* There is a special chunk in the image specifying the gamma. */
- png_set_sRGB (png_ptr, info_ptr, intent);
- else
-#endif
- if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
- /* Image contains gamma information. */
- png_set_gamma (png_ptr, screen_gamma, image_gamma);
- else
- /* Use a default of 0.5 for the image gamma. */
- png_set_gamma (png_ptr, screen_gamma, 0.5);
-
- /* Handle alpha channel by combining the image with a background
- color. Do this only if a real alpha channel is supplied. For
- simple transparency, we prefer a clipping mask. */
- if (!transparent_p)
- {
- png_color_16 *image_background;
-
- if (png_get_bKGD (png_ptr, info_ptr, &image_background))
- /* Image contains a background color with which to
- combine the image. */
- png_set_background (png_ptr, image_background,
- PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
- else
- {
- /* Image does not contain a background color with which
- to combine the image data via an alpha channel. Use
- the frame's background instead. */
- XColor color;
- Colormap cmap;
- png_color_16 frame_background;
-
- BLOCK_INPUT;
- cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
- color.pixel = FRAME_BACKGROUND_PIXEL (f);
- XQueryColor (FRAME_W32_DISPLAY (f), cmap, &color);
- UNBLOCK_INPUT;
-
- bzero (&frame_background, sizeof frame_background);
- frame_background.red = color.red;
- frame_background.green = color.green;
- frame_background.blue = color.blue;
-
- png_set_background (png_ptr, &frame_background,
- PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
- }
- }
-
- /* Update info structure. */
- png_read_update_info (png_ptr, info_ptr);
-
- /* Get number of channels. Valid values are 1 for grayscale images
- and images with a palette, 2 for grayscale images with transparency
- information (alpha channel), 3 for RGB images, and 4 for RGB
- images with alpha channel, i.e. RGBA. If conversions above were
- sufficient we should only have 3 or 4 channels here. */
- channels = png_get_channels (png_ptr, info_ptr);
- xassert (channels == 3 || channels == 4);
-
- /* Number of bytes needed for one row of the image. */
- row_bytes = png_get_rowbytes (png_ptr, info_ptr);
-
- /* Allocate memory for the image. */
- pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
- rows = (png_byte **) xmalloc (height * sizeof *rows);
- for (i = 0; i < height; ++i)
- rows[i] = pixels + i * row_bytes;
-
- /* Read the entire image. */
- png_read_image (png_ptr, rows);
- png_read_end (png_ptr, info_ptr);
- if (fp)
- {
- fclose (fp);
- fp = NULL;
- }
-
- BLOCK_INPUT;
-
- /* Create the X image and pixmap. */
- if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
- &img->pixmap))
- {
- UNBLOCK_INPUT;
- goto error;
- }
-
- /* Create an image and pixmap serving as mask if the PNG image
- contains an alpha channel. */
- if (channels == 4
- && !transparent_p
- && !x_create_x_image_and_pixmap (f, width, height, 1,
- &mask_img, &img->mask))
- {
- x_destroy_x_image (ximg);
- XFreePixmap (FRAME_W32_DISPLAY (f), img->pixmap);
- img->pixmap = 0;
- UNBLOCK_INPUT;
- goto error;
- }
-
- /* Fill the X image and mask from PNG data. */
- init_color_table ();
-
- for (y = 0; y < height; ++y)
- {
- png_byte *p = rows[y];
-
- for (x = 0; x < width; ++x)
- {
- unsigned r, g, b;
-
- r = *p++ << 8;
- g = *p++ << 8;
- b = *p++ << 8;
- XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
-
- /* An alpha channel, aka mask channel, associates variable
- transparency with an image. Where other image formats
- support binary transparency---fully transparent or fully
- opaque---PNG allows up to 254 levels of partial transparency.
- The PNG library implements partial transparency by combining
- the image with a specified background color.
-
- I'm not sure how to handle this here nicely: because the
- background on which the image is displayed may change, for
- real alpha channel support, it would be necessary to create
- a new image for each possible background.
-
- What I'm doing now is that a mask is created if we have
- boolean transparency information. Otherwise I'm using
- the frame's background color to combine the image with. */
-
- if (channels == 4)
- {
- if (mask_img)
- XPutPixel (mask_img, x, y, *p > 0);
- ++p;
- }
- }
- }
-
- /* Remember colors allocated for this image. */
- img->colors = colors_in_color_table (&img->ncolors);
- free_color_table ();
-
- /* Clean up. */
- png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
- xfree (rows);
- xfree (pixels);
-
- img->width = width;
- img->height = height;
-
- /* Put the image into the pixmap, then free the X image and its buffer. */
- x_put_x_image (f, ximg, img->pixmap, width, height);
- x_destroy_x_image (ximg);
-
- /* Same for the mask. */
- if (mask_img)
- {
- x_put_x_image (f, mask_img, img->mask, img->width, img->height);
- x_destroy_x_image (mask_img);
- }
-
- UNBLOCK_INPUT;
- UNGCPRO;
- return 1;
-}
-
-#endif /* HAVE_PNG != 0 */
-
-
-\f
-/***********************************************************************
- JPEG
- ***********************************************************************/
-
-#if HAVE_JPEG
-
-/* Work around a warning about HAVE_STDLIB_H being redefined in
- jconfig.h. */
-#ifdef HAVE_STDLIB_H
-#define HAVE_STDLIB_H_1
-#undef HAVE_STDLIB_H
-#endif /* HAVE_STLIB_H */
-
-#include <jpeglib.h>
-#include <jerror.h>
-#include <setjmp.h>
-
-#ifdef HAVE_STLIB_H_1
-#define HAVE_STDLIB_H 1
-#endif
-
-static int jpeg_image_p P_ ((Lisp_Object object));
-static int jpeg_load P_ ((struct frame *f, struct image *img));
-
-/* The symbol `jpeg' identifying images of this type. */
-
-Lisp_Object Qjpeg;
-
-/* Indices of image specification fields in gs_format, below. */
-
-enum jpeg_keyword_index
-{
- JPEG_TYPE,
- JPEG_DATA,
- JPEG_FILE,
- JPEG_ASCENT,
- JPEG_MARGIN,
- JPEG_RELIEF,
- JPEG_ALGORITHM,
- JPEG_HEURISTIC_MASK,
- JPEG_LAST
-};
-
-/* Vector of image_keyword structures describing the format
- of valid user-defined image specifications. */
-
-static struct image_keyword jpeg_format[JPEG_LAST] =
-{
- {":type", IMAGE_SYMBOL_VALUE, 1},
- {":data", IMAGE_STRING_VALUE, 0},
- {":file", IMAGE_STRING_VALUE, 0},
- {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
- {":relief", IMAGE_INTEGER_VALUE, 0},
- {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
-};
-
-/* Structure describing the image type `jpeg'. */
-
-static struct image_type jpeg_type =
-{
- &Qjpeg,
- jpeg_image_p,
- jpeg_load,
- x_clear_image,
- NULL
-};
-
-
-/* Return non-zero if OBJECT is a valid JPEG image specification. */
-
-static int
-jpeg_image_p (object)
- Lisp_Object object;
-{
- struct image_keyword fmt[JPEG_LAST];
-
- bcopy (jpeg_format, fmt, sizeof fmt);
-
- if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg)
- || (fmt[JPEG_ASCENT].count
- && XFASTINT (fmt[JPEG_ASCENT].value) > 100))
- return 0;
-
- /* Must specify either the :data or :file keyword. */
- return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
-}
-
-
-struct my_jpeg_error_mgr
-{
- struct jpeg_error_mgr pub;
- jmp_buf setjmp_buffer;
-};
-
-static void
-my_error_exit (cinfo)
- j_common_ptr cinfo;
-{
- struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
- longjmp (mgr->setjmp_buffer, 1);
-}
-
-/* Init source method for JPEG data source manager. Called by
- jpeg_read_header() before any data is actually read. See
- libjpeg.doc from the JPEG lib distribution. */
-
-static void
-our_init_source (cinfo)
- j_decompress_ptr cinfo;
-{
-}
-
-
-/* Fill input buffer method for JPEG data source manager. Called
- whenever more data is needed. We read the whole image in one step,
- so this only adds a fake end of input marker at the end. */
-
-static boolean
-our_fill_input_buffer (cinfo)
- j_decompress_ptr cinfo;
-{
- /* Insert a fake EOI marker. */
- struct jpeg_source_mgr *src = cinfo->src;
- static JOCTET buffer[2];
-
- buffer[0] = (JOCTET) 0xFF;
- buffer[1] = (JOCTET) JPEG_EOI;
-
- src->next_input_byte = buffer;
- src->bytes_in_buffer = 2;
- return TRUE;
-}
-
-
-/* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
- is the JPEG data source manager. */
-
-static void
-our_skip_input_data (cinfo, num_bytes)
- j_decompress_ptr cinfo;
- long num_bytes;
-{
- struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
-
- if (src)
- {
- if (num_bytes > src->bytes_in_buffer)
- ERREXIT (cinfo, JERR_INPUT_EOF);
-
- src->bytes_in_buffer -= num_bytes;
- src->next_input_byte += num_bytes;
- }
-}
-
-
-/* Method to terminate data source. Called by
- jpeg_finish_decompress() after all data has been processed. */
-
-static void
-our_term_source (cinfo)
- j_decompress_ptr cinfo;
-{
-}
-
-
-/* Set up the JPEG lib for reading an image from DATA which contains
- LEN bytes. CINFO is the decompression info structure created for
- reading the image. */
-
-static void
-jpeg_memory_src (cinfo, data, len)
- j_decompress_ptr cinfo;
- JOCTET *data;
- unsigned int len;
-{
- struct jpeg_source_mgr *src;
-
- if (cinfo->src == NULL)
- {
- /* First time for this JPEG object? */
- cinfo->src = (struct jpeg_source_mgr *)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
- sizeof (struct jpeg_source_mgr));
- src = (struct jpeg_source_mgr *) cinfo->src;
- src->next_input_byte = data;
- }
-
- src = (struct jpeg_source_mgr *) cinfo->src;
- src->init_source = our_init_source;
- src->fill_input_buffer = our_fill_input_buffer;
- src->skip_input_data = our_skip_input_data;
- src->resync_to_restart = jpeg_resync_to_restart; /* Use default method. */
- src->term_source = our_term_source;
- src->bytes_in_buffer = len;
- src->next_input_byte = data;
-}
-
-
-/* Load image IMG for use on frame F. Patterned after example.c
- from the JPEG lib. */
-
-static int
-jpeg_load (f, img)
- struct frame *f;
- struct image *img;
-{
- struct jpeg_decompress_struct cinfo;
- struct my_jpeg_error_mgr mgr;
- Lisp_Object file, specified_file;
- Lisp_Object specified_data;
- FILE *fp = NULL;
- JSAMPARRAY buffer;
- int row_stride, x, y;
- XImage *ximg = NULL;
- int rc;
- unsigned long *colors;
- int width, height;
- struct gcpro gcpro1;
-
- /* Open the JPEG file. */
- specified_file = image_spec_value (img->spec, QCfile, NULL);
- specified_data = image_spec_value (img->spec, QCdata, NULL);
- file = Qnil;
- GCPRO1 (file);
-
- if (NILP (specified_data))
- {
- file = x_find_image_file (specified_file);
- if (!STRINGP (file))
- {
- image_error ("Cannot find image file `%s'", specified_file, Qnil);
- UNGCPRO;
- return 0;
- }
-
- fp = fopen (XSTRING (file)->data, "r");
- if (fp == NULL)
- {
- image_error ("Cannot open `%s'", file, Qnil);
- UNGCPRO;
- return 0;
- }
- }
-
- /* Customize libjpeg's error handling to call my_error_exit when an
- error is detected. This function will perform a longjmp. */
- mgr.pub.error_exit = my_error_exit;
- cinfo.err = jpeg_std_error (&mgr.pub);
-
- if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
- {
- if (rc == 1)
- {
- /* Called from my_error_exit. Display a JPEG error. */
- char buffer[JMSG_LENGTH_MAX];
- cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
- image_error ("Error reading JPEG image `%s': %s", img->spec,
- build_string (buffer));
- }
-
- /* Close the input file and destroy the JPEG object. */
- if (fp)
- fclose (fp);
- jpeg_destroy_decompress (&cinfo);
-
- BLOCK_INPUT;
-
- /* If we already have an XImage, free that. */
- x_destroy_x_image (ximg);
-
- /* Free pixmap and colors. */
- x_clear_image (f, img);
-
- UNBLOCK_INPUT;
- UNGCPRO;
- return 0;
- }
-
- /* Create the JPEG decompression object. Let it read from fp.
- Read the JPEG image header. */
- jpeg_create_decompress (&cinfo);
-
- if (NILP (specified_data))
- jpeg_stdio_src (&cinfo, fp);
- else
- jpeg_memory_src (&cinfo, XSTRING (specified_data)->data,
- STRING_BYTES (XSTRING (specified_data)));
-
- jpeg_read_header (&cinfo, TRUE);
-
- /* Customize decompression so that color quantization will be used.
- Start decompression. */
- cinfo.quantize_colors = TRUE;
- jpeg_start_decompress (&cinfo);
- width = img->width = cinfo.output_width;
- height = img->height = cinfo.output_height;
-
- BLOCK_INPUT;
-
- /* Create X image and pixmap. */
- if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
- &img->pixmap))
- {
- UNBLOCK_INPUT;
- longjmp (mgr.setjmp_buffer, 2);
- }
-
- /* Allocate colors. When color quantization is used,
- cinfo.actual_number_of_colors has been set with the number of
- colors generated, and cinfo.colormap is a two-dimensional array
- of color indices in the range 0..cinfo.actual_number_of_colors.
- No more than 255 colors will be generated. */
- {
- int i, ir, ig, ib;
-
- if (cinfo.out_color_components > 2)
- ir = 0, ig = 1, ib = 2;
- else if (cinfo.out_color_components > 1)
- ir = 0, ig = 1, ib = 0;
- else
- ir = 0, ig = 0, ib = 0;
-
- /* Use the color table mechanism because it handles colors that
- cannot be allocated nicely. Such colors will be replaced with
- a default color, and we don't have to care about which colors
- can be freed safely, and which can't. */
- init_color_table ();
- colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
- * sizeof *colors);
-
- for (i = 0; i < cinfo.actual_number_of_colors; ++i)
- {
- /* Multiply RGB values with 255 because X expects RGB values
- in the range 0..0xffff. */
- int r = cinfo.colormap[ir][i] << 8;
- int g = cinfo.colormap[ig][i] << 8;
- int b = cinfo.colormap[ib][i] << 8;
- colors[i] = lookup_rgb_color (f, r, g, b);
- }
-
- /* Remember those colors actually allocated. */
- img->colors = colors_in_color_table (&img->ncolors);
- free_color_table ();
- }
-
- /* Read pixels. */
- row_stride = width * cinfo.output_components;
- buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
- row_stride, 1);
- for (y = 0; y < height; ++y)
- {
- jpeg_read_scanlines (&cinfo, buffer, 1);
- for (x = 0; x < cinfo.output_width; ++x)
- XPutPixel (ximg, x, y, colors[buffer[0][x]]);
- }
-
- /* Clean up. */
- jpeg_finish_decompress (&cinfo);
- jpeg_destroy_decompress (&cinfo);
- if (fp)
- fclose (fp);
-
- /* Put the image into the pixmap. */
- x_put_x_image (f, ximg, img->pixmap, width, height);
- x_destroy_x_image (ximg);
- UNBLOCK_INPUT;
- UNGCPRO;
- return 1;
-}
-
-#endif /* HAVE_JPEG */
-
-
-\f
-/***********************************************************************
- TIFF
- ***********************************************************************/
-
-#if HAVE_TIFF
-
-#include <tiffio.h>
-
-static int tiff_image_p P_ ((Lisp_Object object));
-static int tiff_load P_ ((struct frame *f, struct image *img));
-
-/* The symbol `tiff' identifying images of this type. */
-
-Lisp_Object Qtiff;
-
-/* Indices of image specification fields in tiff_format, below. */
-
-enum tiff_keyword_index
-{
- TIFF_TYPE,
- TIFF_DATA,
- TIFF_FILE,
- TIFF_ASCENT,
- TIFF_MARGIN,
- TIFF_RELIEF,
- TIFF_ALGORITHM,
- TIFF_HEURISTIC_MASK,
- TIFF_LAST
-};
-
-/* Vector of image_keyword structures describing the format
- of valid user-defined image specifications. */
-
-static struct image_keyword tiff_format[TIFF_LAST] =
-{
- {":type", IMAGE_SYMBOL_VALUE, 1},
- {":data", IMAGE_STRING_VALUE, 0},
- {":file", IMAGE_STRING_VALUE, 0},
- {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
- {":relief", IMAGE_INTEGER_VALUE, 0},
- {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
-};
-
-/* Structure describing the image type `tiff'. */
-
-static struct image_type tiff_type =
-{
- &Qtiff,
- tiff_image_p,
- tiff_load,
- x_clear_image,
- NULL
-};
-
-
-/* Return non-zero if OBJECT is a valid TIFF image specification. */
-
-static int
-tiff_image_p (object)
- Lisp_Object object;
-{
- struct image_keyword fmt[TIFF_LAST];
- bcopy (tiff_format, fmt, sizeof fmt);
-
- if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff)
- || (fmt[TIFF_ASCENT].count
- && XFASTINT (fmt[TIFF_ASCENT].value) > 100))
- return 0;
-
- /* Must specify either the :data or :file keyword. */
- return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
-}
-
-
-/* Reading from a memory buffer for TIFF images Based on the PNG
- memory source, but we have to provide a lot of extra functions.
- Blah.
-
- We really only need to implement read and seek, but I am not
- convinced that the TIFF library is smart enough not to destroy
- itself if we only hand it the function pointers we need to
- override. */
-
-typedef struct
-{
- unsigned char *bytes;
- size_t len;
- int index;
-}
-tiff_memory_source;
-
-static size_t
-tiff_read_from_memory (data, buf, size)
- thandle_t data;
- tdata_t buf;
- tsize_t size;
-{
- tiff_memory_source *src = (tiff_memory_source *) data;
-
- if (size > src->len - src->index)
- return (size_t) -1;
- bcopy (src->bytes + src->index, buf, size);
- src->index += size;
- return size;
-}
-
-static size_t
-tiff_write_from_memory (data, buf, size)
- thandle_t data;
- tdata_t buf;
- tsize_t size;
-{
- return (size_t) -1;
-}
-
-static toff_t
-tiff_seek_in_memory (data, off, whence)
- thandle_t data;
- toff_t off;
- int whence;
-{
- tiff_memory_source *src = (tiff_memory_source *) data;
- int idx;
-
- switch (whence)
- {
- case SEEK_SET: /* Go from beginning of source. */
- idx = off;
- break;
-
- case SEEK_END: /* Go from end of source. */
- idx = src->len + off;
- break;
-
- case SEEK_CUR: /* Go from current position. */
- idx = src->index + off;
- break;
-
- default: /* Invalid `whence'. */
- return -1;
- }
-
- if (idx > src->len || idx < 0)
- return -1;
-
- src->index = idx;
- return src->index;
-}
-
-static int
-tiff_close_memory (data)
- thandle_t data;
-{
- /* NOOP */
- return 0;
-}
-
-static int
-tiff_mmap_memory (data, pbase, psize)
- thandle_t data;
- tdata_t *pbase;
- toff_t *psize;
-{
- /* It is already _IN_ memory. */
- return 0;
-}
-
-static void
-tiff_unmap_memory (data, base, size)
- thandle_t data;
- tdata_t base;
- toff_t size;
-{
- /* We don't need to do this. */
-}
-
-static toff_t
-tiff_size_of_memory (data)
- thandle_t data;
-{
- return ((tiff_memory_source *) data)->len;
-}
-
-/* Load TIFF image IMG for use on frame F. Value is non-zero if
- successful. */
-
-static int
-tiff_load (f, img)
- struct frame *f;
- struct image *img;
-{
- Lisp_Object file, specified_file;
- Lisp_Object specified_data;
- TIFF *tiff;
- int width, height, x, y;
- uint32 *buf;
- int rc;
- XImage *ximg;
- struct gcpro gcpro1;
- tiff_memory_source memsrc;
-
- specified_file = image_spec_value (img->spec, QCfile, NULL);
- specified_data = image_spec_value (img->spec, QCdata, NULL);
- file = Qnil;
- GCPRO1 (file);
-
- if (NILP (specified_data))
- {
- /* Read from a file */
- file = x_find_image_file (specified_file);
- if (!STRINGP (file))
- {
- image_error ("Cannot find image file `%s'", file, Qnil);
- UNGCPRO;
- return 0;
- }
-
- /* Try to open the image file. */
- tiff = TIFFOpen (XSTRING (file)->data, "r");
- if (tiff == NULL)
- {
- image_error ("Cannot open `%s'", file, Qnil);
- UNGCPRO;
- return 0;
- }
- }
- else
- {
- /* Memory source! */
- memsrc.bytes = XSTRING (specified_data)->data;
- memsrc.len = STRING_BYTES (XSTRING (specified_data));
- memsrc.index = 0;
-
- tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
- (TIFFReadWriteProc) tiff_read_from_memory,
- (TIFFReadWriteProc) tiff_write_from_memory,
- tiff_seek_in_memory,
- tiff_close_memory,
- tiff_size_of_memory,
- tiff_mmap_memory,
- tiff_unmap_memory);
-
- if (!tiff)
- {
- image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
- UNGCPRO;
- return 0;
- }
- }
-
- /* Get width and height of the image, and allocate a raster buffer
- of width x height 32-bit values. */
- TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
- TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
- buf = (uint32 *) xmalloc (width * height * sizeof *buf);
-
- rc = TIFFReadRGBAImage (tiff, width, height, buf, 0);
- TIFFClose (tiff);
- if (!rc)
- {
- image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
- xfree (buf);
- UNGCPRO;
- return 0;
- }
-
- BLOCK_INPUT;
-
- /* Create the X image and pixmap. */
- if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
- {
- UNBLOCK_INPUT;
- xfree (buf);
- UNGCPRO;
- return 0;
- }
-
- /* Initialize the color table. */
- init_color_table ();
-
- /* Process the pixel raster. Origin is in the lower-left corner. */
- for (y = 0; y < height; ++y)
- {
- uint32 *row = buf + y * width;
-
- for (x = 0; x < width; ++x)
- {
- uint32 abgr = row[x];
- int r = TIFFGetR (abgr) << 8;
- int g = TIFFGetG (abgr) << 8;
- int b = TIFFGetB (abgr) << 8;
- XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
- }
- }
-
- /* Remember the colors allocated for the image. Free the color table. */
- img->colors = colors_in_color_table (&img->ncolors);
- free_color_table ();
-
- /* Put the image into the pixmap, then free the X image and its buffer. */
- x_put_x_image (f, ximg, img->pixmap, width, height);
- x_destroy_x_image (ximg);
- xfree (buf);
- UNBLOCK_INPUT;
-
- img->width = width;
- img->height = height;
-
- UNGCPRO;
- return 1;
-}
-
-#endif /* HAVE_TIFF != 0 */
-
-
-\f
-/***********************************************************************
- GIF
- ***********************************************************************/
-
-#if HAVE_GIF
-
-#include <gif_lib.h>
-
-static int gif_image_p P_ ((Lisp_Object object));
-static int gif_load P_ ((struct frame *f, struct image *img));
-
-/* The symbol `gif' identifying images of this type. */
-
-Lisp_Object Qgif;
-
-/* Indices of image specification fields in gif_format, below. */
-
-enum gif_keyword_index
-{
- GIF_TYPE,
- GIF_DATA,
- GIF_FILE,
- GIF_ASCENT,
- GIF_MARGIN,
- GIF_RELIEF,
- GIF_ALGORITHM,
- GIF_HEURISTIC_MASK,
- GIF_IMAGE,
- GIF_LAST
-};
-
-/* Vector of image_keyword structures describing the format
- of valid user-defined image specifications. */
-
-static struct image_keyword gif_format[GIF_LAST] =
-{
- {":type", IMAGE_SYMBOL_VALUE, 1},
- {":data", IMAGE_STRING_VALUE, 0},
- {":file", IMAGE_STRING_VALUE, 0},
- {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
- {":relief", IMAGE_INTEGER_VALUE, 0},
- {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}
-};
-
-/* Structure describing the image type `gif'. */
-
-static struct image_type gif_type =
-{
- &Qgif,
- gif_image_p,
- gif_load,
- x_clear_image,
- NULL
-};
-
-/* Return non-zero if OBJECT is a valid GIF image specification. */
-
-static int
-gif_image_p (object)
- Lisp_Object object;
-{
- struct image_keyword fmt[GIF_LAST];
- bcopy (gif_format, fmt, sizeof fmt);
-
- if (!parse_image_spec (object, fmt, GIF_LAST, Qgif)
- || (fmt[GIF_ASCENT].count
- && XFASTINT (fmt[GIF_ASCENT].value) > 100))
- return 0;
-
- /* Must specify either the :data or :file keyword. */
- return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
-}
-
-/* Reading a GIF image from memory
- Based on the PNG memory stuff to a certain extent. */
-
-typedef struct
-{
- unsigned char *bytes;
- size_t len;
- int index;
-}
-gif_memory_source;
-
-/* Make the current memory source available to gif_read_from_memory.
- It's done this way because not all versions of libungif support
- a UserData field in the GifFileType structure. */
-static gif_memory_source *current_gif_memory_src;
-
-static int
-gif_read_from_memory (file, buf, len)
- GifFileType *file;
- GifByteType *buf;
- int len;
-{
- gif_memory_source *src = current_gif_memory_src;
-
- if (len > src->len - src->index)
- return -1;
-
- bcopy (src->bytes + src->index, buf, len);
- src->index += len;
- return len;
-}
-
-
-/* Load GIF image IMG for use on frame F. Value is non-zero if
- successful. */
-
-static int
-gif_load (f, img)
- struct frame *f;
- struct image *img;
-{
- Lisp_Object file, specified_file;
- Lisp_Object specified_data;
- int rc, width, height, x, y, i;
- XImage *ximg;
- ColorMapObject *gif_color_map;
- unsigned long pixel_colors[256];
- GifFileType *gif;
- struct gcpro gcpro1;
- Lisp_Object image;
- int ino, image_left, image_top, image_width, image_height;
- gif_memory_source memsrc;
- unsigned char *raster;
-
- specified_file = image_spec_value (img->spec, QCfile, NULL);
- specified_data = image_spec_value (img->spec, QCdata, NULL);
- file = Qnil;
- GCPRO1 (file);
-
- if (NILP (specified_data))
- {
- file = x_find_image_file (specified_file);
- if (!STRINGP (file))
- {
- image_error ("Cannot find image file `%s'", specified_file, Qnil);
- UNGCPRO;
- return 0;
- }
-
- /* Open the GIF file. */
- gif = DGifOpenFileName (XSTRING (file)->data);
- if (gif == NULL)
- {
- image_error ("Cannot open `%s'", file, Qnil);
- UNGCPRO;
- return 0;
- }
- }
- else
- {
- /* Read from memory! */
- current_gif_memory_src = &memsrc;
- memsrc.bytes = XSTRING (specified_data)->data;
- memsrc.len = STRING_BYTES (XSTRING (specified_data));
- memsrc.index = 0;
-
- gif = DGifOpen(&memsrc, gif_read_from_memory);
- if (!gif)
- {
- image_error ("Cannot open memory source `%s'", img->spec, Qnil);
- UNGCPRO;
- return 0;
- }
- }
-
- /* Read entire contents. */
- rc = DGifSlurp (gif);
- if (rc == GIF_ERROR)
- {
- image_error ("Error reading `%s'", img->spec, Qnil);
- DGifCloseFile (gif);
- UNGCPRO;
- return 0;
- }
-
- image = image_spec_value (img->spec, QCindex, NULL);
- ino = INTEGERP (image) ? XFASTINT (image) : 0;
- if (ino >= gif->ImageCount)
- {
- image_error ("Invalid image number `%s' in image `%s'",
- image, img->spec);
- DGifCloseFile (gif);
- UNGCPRO;
- return 0;
- }
-
- width = img->width = gif->SWidth;
- height = img->height = gif->SHeight;
-
- BLOCK_INPUT;
-
- /* Create the X image and pixmap. */
- if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
- {
- UNBLOCK_INPUT;
- DGifCloseFile (gif);
- UNGCPRO;
- return 0;
- }
-
- /* Allocate colors. */
- gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
- if (!gif_color_map)
- gif_color_map = gif->SColorMap;
- init_color_table ();
- bzero (pixel_colors, sizeof pixel_colors);
-
- for (i = 0; i < gif_color_map->ColorCount; ++i)
- {
- int r = gif_color_map->Colors[i].Red << 8;
- int g = gif_color_map->Colors[i].Green << 8;
- int b = gif_color_map->Colors[i].Blue << 8;
- pixel_colors[i] = lookup_rgb_color (f, r, g, b);
- }
-
- img->colors = colors_in_color_table (&img->ncolors);
- free_color_table ();
-
- /* Clear the part of the screen image that are not covered by
- the image from the GIF file. Full animated GIF support
- requires more than can be done here (see the gif89 spec,
- disposal methods). Let's simply assume that the part
- not covered by a sub-image is in the frame's background color. */
- image_top = gif->SavedImages[ino].ImageDesc.Top;
- image_left = gif->SavedImages[ino].ImageDesc.Left;
- image_width = gif->SavedImages[ino].ImageDesc.Width;
- image_height = gif->SavedImages[ino].ImageDesc.Height;
-
- for (y = 0; y < image_top; ++y)
- for (x = 0; x < width; ++x)
- XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
-
- for (y = image_top + image_height; y < height; ++y)
- for (x = 0; x < width; ++x)
- XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
-
- for (y = image_top; y < image_top + image_height; ++y)
- {
- for (x = 0; x < image_left; ++x)
- XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
- for (x = image_left + image_width; x < width; ++x)
- XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
- }
-
- /* Read the GIF image into the X image. We use a local variable
- `raster' here because RasterBits below is a char *, and invites
- problems with bytes >= 0x80. */
- raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
-
- if (gif->SavedImages[ino].ImageDesc.Interlace)
- {
- static int interlace_start[] = {0, 4, 2, 1};
- static int interlace_increment[] = {8, 8, 4, 2};
- int pass, inc;
- int row = interlace_start[0];
-
- pass = 0;
-
- for (y = 0; y < image_height; y++)
- {
- if (row >= image_height)
- {
- row = interlace_start[++pass];
- while (row >= image_height)
- row = interlace_start[++pass];
- }
-
- for (x = 0; x < image_width; x++)
- {
- int i = raster[(y * image_width) + x];
- XPutPixel (ximg, x + image_left, row + image_top,
- pixel_colors[i]);
- }
-
- row += interlace_increment[pass];
- }
- }
- else
- {
- for (y = 0; y < image_height; ++y)
- for (x = 0; x < image_width; ++x)
- {
- int i = raster[y* image_width + x];
- XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
- }
- }
-
- DGifCloseFile (gif);
-
- /* Put the image into the pixmap, then free the X image and its buffer. */
- x_put_x_image (f, ximg, img->pixmap, width, height);
- x_destroy_x_image (ximg);
- UNBLOCK_INPUT;
-
- UNGCPRO;
- return 1;
-}
-
-#endif /* HAVE_GIF != 0 */
-
-
-\f
-/***********************************************************************
- Ghostscript
- ***********************************************************************/
-
-#ifdef HAVE_GHOSTSCRIPT
-static int gs_image_p P_ ((Lisp_Object object));
-static int gs_load P_ ((struct frame *f, struct image *img));
-static void gs_clear_image P_ ((struct frame *f, struct image *img));
-
-/* The symbol `postscript' identifying images of this type. */
-
-Lisp_Object Qpostscript;
-
-/* Keyword symbols. */
-
-Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
-
-/* Indices of image specification fields in gs_format, below. */
-
-enum gs_keyword_index
-{
- GS_TYPE,
- GS_PT_WIDTH,
- GS_PT_HEIGHT,
- GS_FILE,
- GS_LOADER,
- GS_BOUNDING_BOX,
- GS_ASCENT,
- GS_MARGIN,
- GS_RELIEF,
- GS_ALGORITHM,
- GS_HEURISTIC_MASK,
- GS_LAST
-};
-
-/* Vector of image_keyword structures describing the format
- of valid user-defined image specifications. */
-
-static struct image_keyword gs_format[GS_LAST] =
-{
- {":type", IMAGE_SYMBOL_VALUE, 1},
- {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
- {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
- {":file", IMAGE_STRING_VALUE, 1},
- {":loader", IMAGE_FUNCTION_VALUE, 0},
- {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
- {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
- {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
- {":relief", IMAGE_INTEGER_VALUE, 0},
- {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
- {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
-};
-
-/* Structure describing the image type `ghostscript'. */
-
-static struct image_type gs_type =
-{
- &Qpostscript,
- gs_image_p,
- gs_load,
- gs_clear_image,
- NULL
-};
-
-
-/* Free X resources of Ghostscript image IMG which is used on frame F. */
-
-static void
-gs_clear_image (f, img)
- struct frame *f;
- struct image *img;
-{
- /* IMG->data.ptr_val may contain a recorded colormap. */
- xfree (img->data.ptr_val);
- x_clear_image (f, img);
-}
-
-
-/* Return non-zero if OBJECT is a valid Ghostscript image
- specification. */
-
-static int
-gs_image_p (object)
- Lisp_Object object;
-{
- struct image_keyword fmt[GS_LAST];
- Lisp_Object tem;
- int i;
-
- bcopy (gs_format, fmt, sizeof fmt);
-
- if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript)
- || (fmt[GS_ASCENT].count
- && XFASTINT (fmt[GS_ASCENT].value) > 100))
- return 0;
-
- /* Bounding box must be a list or vector containing 4 integers. */
- tem = fmt[GS_BOUNDING_BOX].value;
- if (CONSP (tem))
- {
- for (i = 0; i < 4; ++i, tem = XCDR (tem))
- if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
- return 0;
- if (!NILP (tem))
- return 0;
- }
- else if (VECTORP (tem))
- {
- if (XVECTOR (tem)->size != 4)
- return 0;
- for (i = 0; i < 4; ++i)
- if (!INTEGERP (XVECTOR (tem)->contents[i]))
- return 0;
- }
- else
- return 0;
-
- return 1;
-}
-
-
-/* Load Ghostscript image IMG for use on frame F. Value is non-zero
- if successful. */
-
-static int
-gs_load (f, img)
- struct frame *f;
- struct image *img;
-{
- char buffer[100];
- Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
- struct gcpro gcpro1, gcpro2;
- Lisp_Object frame;
- double in_width, in_height;
- Lisp_Object pixel_colors = Qnil;
-
- /* Compute pixel size of pixmap needed from the given size in the
- image specification. Sizes in the specification are in pt. 1 pt
- = 1/72 in, xdpi and ydpi are stored in the frame's X display
- info. */
- pt_width = image_spec_value (img->spec, QCpt_width, NULL);
- in_width = XFASTINT (pt_width) / 72.0;
- img->width = in_width * FRAME_W32_DISPLAY_INFO (f)->resx;
- pt_height = image_spec_value (img->spec, QCpt_height, NULL);
- in_height = XFASTINT (pt_height) / 72.0;
- img->height = in_height * FRAME_W32_DISPLAY_INFO (f)->resy;
-
- /* Create the pixmap. */
- BLOCK_INPUT;
- xassert (img->pixmap == 0);
- img->pixmap = XCreatePixmap (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
- img->width, img->height,
- DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
- UNBLOCK_INPUT;
-
- if (!img->pixmap)
- {
- image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
- return 0;
- }
-
- /* Call the loader to fill the pixmap. It returns a process object
- if successful. We do not record_unwind_protect here because
- other places in redisplay like calling window scroll functions
- don't either. Let the Lisp loader use `unwind-protect' instead. */
- GCPRO2 (window_and_pixmap_id, pixel_colors);
-
- sprintf (buffer, "%lu %lu",
- (unsigned long) FRAME_W32_WINDOW (f),
- (unsigned long) img->pixmap);
- window_and_pixmap_id = build_string (buffer);
-
- sprintf (buffer, "%lu %lu",
- FRAME_FOREGROUND_PIXEL (f),
- FRAME_BACKGROUND_PIXEL (f));
- pixel_colors = build_string (buffer);
-
- XSETFRAME (frame, f);
- loader = image_spec_value (img->spec, QCloader, NULL);
- if (NILP (loader))
- loader = intern ("gs-load-image");
-
- img->data.lisp_val = call6 (loader, frame, img->spec,
- make_number (img->width),
- make_number (img->height),
- window_and_pixmap_id,
- pixel_colors);
- UNGCPRO;
- return PROCESSP (img->data.lisp_val);
-}
-
-
-/* Kill the Ghostscript process that was started to fill PIXMAP on
- frame F. Called from XTread_socket when receiving an event
- telling Emacs that Ghostscript has finished drawing. */
-
-void
-x_kill_gs_process (pixmap, f)
- Pixmap pixmap;
- struct frame *f;
-{
- struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
- int class, i;
- struct image *img;
-
- /* Find the image containing PIXMAP. */
- for (i = 0; i < c->used; ++i)
- if (c->images[i]->pixmap == pixmap)
- break;
-
- /* Kill the GS process. We should have found PIXMAP in the image
- cache and its image should contain a process object. */
- xassert (i < c->used);
- img = c->images[i];
- xassert (PROCESSP (img->data.lisp_val));
- Fkill_process (img->data.lisp_val, Qnil);
- img->data.lisp_val = Qnil;
-
- /* On displays with a mutable colormap, figure out the colors
- allocated for the image by looking at the pixels of an XImage for
- img->pixmap. */
- class = FRAME_W32_DISPLAY_INFO (f)->visual->class;
- if (class != StaticColor && class != StaticGray && class != TrueColor)
- {
- XImage *ximg;
-
- BLOCK_INPUT;
-
- /* Try to get an XImage for img->pixmep. */
- ximg = XGetImage (FRAME_W32_DISPLAY (f), img->pixmap,
- 0, 0, img->width, img->height, ~0, ZPixmap);
- if (ximg)
- {
- int x, y;
-
- /* Initialize the color table. */
- init_color_table ();
-
- /* For each pixel of the image, look its color up in the
- color table. After having done so, the color table will
- contain an entry for each color used by the image. */
- for (y = 0; y < img->height; ++y)
- for (x = 0; x < img->width; ++x)
- {
- unsigned long pixel = XGetPixel (ximg, x, y);
- lookup_pixel_color (f, pixel);
- }
-
- /* Record colors in the image. Free color table and XImage. */
- img->colors = colors_in_color_table (&img->ncolors);
- free_color_table ();
- XDestroyImage (ximg);
-
-#if 0 /* This doesn't seem to be the case. If we free the colors
- here, we get a BadAccess later in x_clear_image when
- freeing the colors. */
- /* We have allocated colors once, but Ghostscript has also
- allocated colors on behalf of us. So, to get the
- reference counts right, free them once. */
- if (img->ncolors)
- {
- Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
- XFreeColors (FRAME_W32_DISPLAY (f), cmap,
- img->colors, img->ncolors, 0);
- }
-#endif
- }
- else
- image_error ("Cannot get X image of `%s'; colors will not be freed",
- img->spec, Qnil);
-
- UNBLOCK_INPUT;
- }
-}
-
-#endif /* HAVE_GHOSTSCRIPT */
-
-\f
-/***********************************************************************
- Window properties
- ***********************************************************************/
-
-DEFUN ("x-change-window-property", Fx_change_window_property,
- Sx_change_window_property, 2, 3, 0,
- "Change window property PROP to VALUE on the X window of FRAME.\n\
-PROP and VALUE must be strings. FRAME nil or omitted means use the\n\
-selected frame. Value is VALUE.")
- (prop, value, frame)
- Lisp_Object frame, prop, value;
-{
-#if 0 /* MAC_TODO : port window properties to Mac */
- struct frame *f = check_x_frame (frame);
- Atom prop_atom;
-
- CHECK_STRING (prop, 1);
- CHECK_STRING (value, 2);
-
- BLOCK_INPUT;
- prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), XSTRING (prop)->data, False);
- XChangeProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
- prop_atom, XA_STRING, 8, PropModeReplace,
- XSTRING (value)->data, XSTRING (value)->size);
-
- /* Make sure the property is set when we return. */
- XFlush (FRAME_W32_DISPLAY (f));
- UNBLOCK_INPUT;
-
-#endif /* MAC_TODO */
-
- return value;
-}
-
-
-DEFUN ("x-delete-window-property", Fx_delete_window_property,
- Sx_delete_window_property, 1, 2, 0,
- "Remove window property PROP from X window of FRAME.\n\
-FRAME nil or omitted means use the selected frame. Value is PROP.")
- (prop, frame)
- Lisp_Object prop, frame;
-{
-#if 0 /* MAC_TODO : port window properties to Mac */
-
- struct frame *f = check_x_frame (frame);
- Atom prop_atom;
-
- CHECK_STRING (prop, 1);
- BLOCK_INPUT;
- prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), XSTRING (prop)->data, False);
- XDeleteProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f), prop_atom);
-
- /* Make sure the property is removed when we return. */
- XFlush (FRAME_W32_DISPLAY (f));
- UNBLOCK_INPUT;
-#endif /* MAC_TODO */
-
- return prop;
-}
-
-
-DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
- 1, 2, 0,
- "Value is the value of window property PROP on FRAME.\n\
-If FRAME is nil or omitted, use the selected frame. Value is nil\n\
-if FRAME hasn't a property with name PROP or if PROP has no string\n\
-value.")
- (prop, frame)
- Lisp_Object prop, frame;
-{
-#if 0 /* MAC_TODO : port window properties to Mac */
-
- struct frame *f = check_x_frame (frame);
- Atom prop_atom;
- int rc;
- Lisp_Object prop_value = Qnil;
- char *tmp_data = NULL;
- Atom actual_type;
- int actual_format;
- unsigned long actual_size, bytes_remaining;
-
- CHECK_STRING (prop, 1);
- BLOCK_INPUT;
- prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), XSTRING (prop)->data, False);
- rc = XGetWindowProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
- prop_atom, 0, 0, False, XA_STRING,
- &actual_type, &actual_format, &actual_size,
- &bytes_remaining, (unsigned char **) &tmp_data);
- if (rc == Success)
- {
- int size = bytes_remaining;
-
- XFree (tmp_data);
- tmp_data = NULL;
-
- rc = XGetWindowProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
- prop_atom, 0, bytes_remaining,
- False, XA_STRING,
- &actual_type, &actual_format,
- &actual_size, &bytes_remaining,
- (unsigned char **) &tmp_data);
- if (rc == Success)
- prop_value = make_string (tmp_data, size);
-
- XFree (tmp_data);
- }
-
- UNBLOCK_INPUT;
-
- return prop_value;
-
-#endif /* MAC_TODO */
- return Qnil;
-}
-
-
-\f
-/***********************************************************************
- Busy cursor
- ***********************************************************************/
-
-/* If non-null, an asynchronous timer that, when it expires, displays
- an hourglass cursor on all frames. */
-
-static struct atimer *hourglass_atimer;
-
-/* Non-zero means an hourglass cursor is currently shown. */
-
-static int hourglass_shown_p;
-
-/* Number of seconds to wait before displaying an hourglass cursor. */
-
-static Lisp_Object Vhourglass_delay;
-
-/* Default number of seconds to wait before displaying an hourglass
- cursor. */
-
-#define DEFAULT_HOURGLASS_DELAY 1
-
-/* Function prototypes. */
-
-static void show_hourglass P_ ((struct atimer *));
-static void hide_hourglass P_ ((void));
-
-
-/* Cancel a currently active hourglass timer, and start a new one. */
-
-void
-start_hourglass ()
-{
-#if 0 /* TODO: cursor shape changes. */
- EMACS_TIME delay;
- int secs, usecs = 0;
-
- cancel_hourglass ();
-
- if (INTEGERP (Vhourglass_delay)
- && XINT (Vhourglass_delay) > 0)
- secs = XFASTINT (Vhourglass_delay);
- else if (FLOATP (Vhourglass_delay)
- && XFLOAT_DATA (Vhourglass_delay) > 0)
- {
- Lisp_Object tem;
- tem = Ftruncate (Vhourglass_delay, Qnil);
- secs = XFASTINT (tem);
- usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
- }
- else
- secs = DEFAULT_HOURGLASS_DELAY;
-
- EMACS_SET_SECS_USECS (delay, secs, usecs);
- hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
- show_hourglass, NULL);
-#endif
-}
-
-
-/* Cancel the hourglass cursor timer if active, hide an hourglass
- cursor if shown. */
-
-void
-cancel_hourglass ()
-{
- if (hourglass_atimer)
- {
- cancel_atimer (hourglass_atimer);
- hourglass_atimer = NULL;
- }
-
- if (hourglass_shown_p)
- hide_hourglass ();
-}
-
-
-/* Timer function of hourglass_atimer. TIMER is equal to
- hourglass_atimer.
-
- Display an hourglass cursor on all frames by mapping the frames'
- hourglass_window. Set the hourglass_p flag in the frames'
- output_data.x structure to indicate that an hourglass cursor is
- shown on the frames. */
-
-static void
-show_hourglass (timer)
- struct atimer *timer;
-{
-#if 0 /* MAC_TODO: cursor shape changes. */
- /* The timer implementation will cancel this timer automatically
- after this function has run. Set hourglass_atimer to null
- so that we know the timer doesn't have to be canceled. */
- hourglass_atimer = NULL;
-
- if (!hourglass_shown_p)
- {
- Lisp_Object rest, frame;
-
- BLOCK_INPUT;
-
- FOR_EACH_FRAME (rest, frame)
- if (FRAME_W32_P (XFRAME (frame)))
- {
- struct frame *f = XFRAME (frame);
-
- f->output_data.w32->hourglass_p = 1;
-
- if (!f->output_data.w32->hourglass_window)
- {
- unsigned long mask = CWCursor;
- XSetWindowAttributes attrs;
-
- attrs.cursor = f->output_data.w32->hourglass_cursor;
-
- f->output_data.w32->hourglass_window
- = XCreateWindow (FRAME_X_DISPLAY (f),
- FRAME_OUTER_WINDOW (f),
- 0, 0, 32000, 32000, 0, 0,
- InputOnly,
- CopyFromParent,
- mask, &attrs);
- }
-
- XMapRaised (FRAME_X_DISPLAY (f),
- f->output_data.w32->hourglass_window);
- XFlush (FRAME_X_DISPLAY (f));
- }
-
- hourglass_shown_p = 1;
- UNBLOCK_INPUT;
- }
-#endif
-}
-
-
-/* Hide the hourglass cursor on all frames, if it is currently shown. */
-
-static void
-hide_hourglass ()
-{
-#if 0 /* TODO: cursor shape changes. */
- if (hourglass_shown_p)
- {
- Lisp_Object rest, frame;
-
- BLOCK_INPUT;
- FOR_EACH_FRAME (rest, frame)
- {
- struct frame *f = XFRAME (frame);
-
- if (FRAME_W32_P (f)
- /* Watch out for newly created frames. */
- && f->output_data.x->hourglass_window)
- {
- XUnmapWindow (FRAME_X_DISPLAY (f),
- f->output_data.x->hourglass_window);
- /* Sync here because XTread_socket looks at the
- hourglass_p flag that is reset to zero below. */
- XSync (FRAME_X_DISPLAY (f), False);
- f->output_data.x->hourglass_p = 0;
- }
- }
-
- hourglass_shown_p = 0;
- UNBLOCK_INPUT;
- }
-#endif
-}
-
-
-\f
-/***********************************************************************
- Tool tips
- ***********************************************************************/
-
-static Lisp_Object x_create_tip_frame P_ ((struct w32_display_info *,
- Lisp_Object));
-
-/* The frame of a currently visible tooltip, or null. */
-
-Lisp_Object tip_frame;
-
-/* If non-nil, a timer started that hides the last tooltip when it
- fires. */
-
-Lisp_Object tip_timer;
-Window tip_window;
-
-/* Create a frame for a tooltip on the display described by DPYINFO.
- PARMS is a list of frame parameters. Value is the frame. */
-
-static Lisp_Object
-x_create_tip_frame (dpyinfo, parms)
- struct w32_display_info *dpyinfo;
- Lisp_Object parms;
-{
-#if 0 /* MAC_TODO : Mac version */
- struct frame *f;
- Lisp_Object frame, tem;
- Lisp_Object name;
- long window_prompting = 0;
- int width, height;
- int count = specpdl_ptr - specpdl;
- struct gcpro gcpro1, gcpro2, gcpro3;
- struct kboard *kb;
-
- check_x ();
-
- /* Use this general default value to start with until we know if
- this frame has a specified name. */
- Vx_resource_name = Vinvocation_name;
-
-#ifdef MULTI_KBOARD
- kb = dpyinfo->kboard;
-#else
- kb = &the_only_kboard;
-#endif
-
- /* Get the name of the frame to use for resource lookup. */
- name = w32_get_arg (parms, Qname, "name", "Name", RES_TYPE_STRING);
- if (!STRINGP (name)
- && !EQ (name, Qunbound)
- && !NILP (name))
- error ("Invalid frame name--not a string or nil");
- Vx_resource_name = name;
-
- frame = Qnil;
- GCPRO3 (parms, name, frame);
- tip_frame = f = make_frame (1);
- XSETFRAME (frame, f);
- FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
-
- f->output_method = output_w32;
- f->output_data.w32 =
- (struct w32_output *) xmalloc (sizeof (struct w32_output));
- bzero (f->output_data.w32, sizeof (struct w32_output));
-#if 0
- f->output_data.w32->icon_bitmap = -1;
-#endif
- f->output_data.w32->fontset = -1;
- f->icon_name = Qnil;
-
-#ifdef MULTI_KBOARD
- FRAME_KBOARD (f) = kb;
-#endif
- f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
- f->output_data.w32->explicit_parent = 0;
-
- /* Set the name; the functions to which we pass f expect the name to
- be set. */
- if (EQ (name, Qunbound) || NILP (name))
- {
- f->name = build_string (dpyinfo->x_id_name);
- f->explicit_name = 0;
- }
- else
- {
- f->name = name;
- f->explicit_name = 1;
- /* use the frame's title when getting resources for this frame. */
- specbind (Qx_resource_name, name);
- }
-
- /* Extract the window parameters from the supplied values
- that are needed to determine window geometry. */
- {
- Lisp_Object font;
-
- font = w32_get_arg (parms, Qfont, "font", "Font", RES_TYPE_STRING);
-
- BLOCK_INPUT;
- /* First, try whatever font the caller has specified. */
- if (STRINGP (font))
- {
- tem = Fquery_fontset (font, Qnil);
- if (STRINGP (tem))
- font = x_new_fontset (f, XSTRING (tem)->data);
- else
- font = x_new_font (f, XSTRING (font)->data);
- }
-
- /* Try out a font which we hope has bold and italic variations. */
- if (!STRINGP (font))
- font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
- if (!STRINGP (font))
- font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
- if (! STRINGP (font))
- font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
- if (! STRINGP (font))
- /* This was formerly the first thing tried, but it finds too many fonts
- and takes too long. */
- font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
- /* If those didn't work, look for something which will at least work. */
- if (! STRINGP (font))
- font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
- UNBLOCK_INPUT;
- if (! STRINGP (font))
- font = build_string ("fixed");
-
- x_default_parameter (f, parms, Qfont, font,
- "font", "Font", RES_TYPE_STRING);
- }
-
- x_default_parameter (f, parms, Qborder_width, make_number (2),
- "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
-
- /* This defaults to 2 in order to match xterm. We recognize either
- internalBorderWidth or internalBorder (which is what xterm calls
- it). */
- if (NILP (Fassq (Qinternal_border_width, parms)))
- {
- Lisp_Object value;
-
- value = w32_get_arg (parms, Qinternal_border_width,
- "internalBorder", "internalBorder", RES_TYPE_NUMBER);
- if (! EQ (value, Qunbound))
- parms = Fcons (Fcons (Qinternal_border_width, value),
- parms);
- }
-
- x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
- "internalBorderWidth", "internalBorderWidth",
- RES_TYPE_NUMBER);
-
- /* Also do the stuff which must be set before the window exists. */
- x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
- "foreground", "Foreground", RES_TYPE_STRING);
- x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
- "background", "Background", RES_TYPE_STRING);
- x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
- "pointerColor", "Foreground", RES_TYPE_STRING);
- x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
- "cursorColor", "Foreground", RES_TYPE_STRING);
- x_default_parameter (f, parms, Qborder_color, build_string ("black"),
- "borderColor", "BorderColor", RES_TYPE_STRING);
-
- /* Init faces before x_default_parameter is called for scroll-bar
- parameters because that function calls x_set_scroll_bar_width,
- which calls change_frame_size, which calls Fset_window_buffer,
- which runs hooks, which call Fvertical_motion. At the end, we
- end up in init_iterator with a null face cache, which should not
- happen. */
- init_frame_faces (f);
-
- f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
- window_prompting = x_figure_window_size (f, parms);
-
- if (window_prompting & XNegative)
- {
- if (window_prompting & YNegative)
- f->output_data.w32->win_gravity = SouthEastGravity;
- else
- f->output_data.w32->win_gravity = NorthEastGravity;
- }
- else
- {
- if (window_prompting & YNegative)
- f->output_data.w32->win_gravity = SouthWestGravity;
- else
- f->output_data.w32->win_gravity = NorthWestGravity;
- }
-
- f->output_data.w32->size_hint_flags = window_prompting;
- {
- XSetWindowAttributes attrs;
- unsigned long mask;
-
- BLOCK_INPUT;
- mask = CWBackPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask;
- /* Window managers looks at the override-redirect flag to
- determine whether or net to give windows a decoration (Xlib
- 3.2.8). */
- attrs.override_redirect = True;
- attrs.save_under = True;
- attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
- /* Arrange for getting MapNotify and UnmapNotify events. */
- attrs.event_mask = StructureNotifyMask;
- tip_window
- = FRAME_W32_WINDOW (f)
- = XCreateWindow (FRAME_W32_DISPLAY (f),
- FRAME_W32_DISPLAY_INFO (f)->root_window,
- /* x, y, width, height */
- 0, 0, 1, 1,
- /* Border. */
- 1,
- CopyFromParent, InputOutput, CopyFromParent,
- mask, &attrs);
- UNBLOCK_INPUT;
- }
-
- x_make_gc (f);
-
- x_default_parameter (f, parms, Qauto_raise, Qnil,
- "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
- x_default_parameter (f, parms, Qauto_lower, Qnil,
- "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
- x_default_parameter (f, parms, Qcursor_type, Qbox,
- "cursorType", "CursorType", RES_TYPE_SYMBOL);
-
- /* Dimensions, especially f->height, must be done via change_frame_size.
- Change will not be effected unless different from the current
- f->height. */
- width = f->width;
- height = f->height;
- f->height = 0;
- SET_FRAME_WIDTH (f, 0);
- change_frame_size (f, height, width, 1, 0, 0);
-
- f->no_split = 1;
-
- UNGCPRO;
-
- /* It is now ok to make the frame official even if we get an error
- below. And the frame needs to be on Vframe_list or making it
- visible won't work. */
- Vframe_list = Fcons (frame, Vframe_list);
-
- /* Now that the frame is official, it counts as a reference to
- its display. */
- FRAME_W32_DISPLAY_INFO (f)->reference_count++;
-
- return unbind_to (count, frame);
-#endif /* MAC_TODO */
- return Qnil;
-}
-
-#ifdef TODO /* Tooltip support not complete. */
-DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
- "Show STRING in a \"tooltip\" window on frame FRAME.\n\
-A tooltip window is a small window displaying a string.\n\
-\n\
-FRAME nil or omitted means use the selected frame.\n\
-\n\
-PARMS is an optional list of frame parameters which can be\n\
-used to change the tooltip's appearance.\n\
-\n\
-Automatically hide the tooltip after TIMEOUT seconds.\n\
-TIMEOUT nil means use the default timeout of 5 seconds.\n\
-\n\
-If the list of frame parameters PARAMS contains a `left' parameters,\n\
-the tooltip is displayed at that x-position. Otherwise it is\n\
-displayed at the mouse position, with offset DX added (default is 5 if\n\
-DX isn't specified). Likewise for the y-position; if a `top' frame\n\
-parameter is specified, it determines the y-position of the tooltip\n\
-window, otherwise it is displayed at the mouse position, with offset\n\
-DY added (default is 10).")
- (string, frame, parms, timeout, dx, dy)
- Lisp_Object string, frame, parms, timeout, dx, dy;
-{
- struct frame *f;
- struct window *w;
- Window root, child;
- Lisp_Object buffer, top, left;
- struct buffer *old_buffer;
- struct text_pos pos;
- int i, width, height;
- int root_x, root_y, win_x, win_y;
- unsigned pmask;
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
- int old_windows_or_buffers_changed = windows_or_buffers_changed;
- int count = specpdl_ptr - specpdl;
-
- specbind (Qinhibit_redisplay, Qt);
-
- GCPRO4 (string, parms, frame, timeout);
-
- CHECK_STRING (string, 0);
- f = check_x_frame (frame);
- if (NILP (timeout))
- timeout = make_number (5);
- else
- CHECK_NATNUM (timeout, 2);
-
- if (NILP (dx))
- dx = make_number (5);
- else
- CHECK_NUMBER (dx, 5);
-
- if (NILP (dy))
- dy = make_number (-10);
- else
- CHECK_NUMBER (dy, 6);
-
- if (NILP (last_show_tip_args))
- last_show_tip_args = Fmake_vector (make_number (3), Qnil);
-
- if (!NILP (tip_frame))
- {
- Lisp_Object last_string = AREF (last_show_tip_args, 0);
- Lisp_Object last_frame = AREF (last_show_tip_args, 1);
- Lisp_Object last_parms = AREF (last_show_tip_args, 2);
-
- if (EQ (frame, last_frame)
- && !NILP (Fequal (last_string, string))
- && !NILP (Fequal (last_parms, parms)))
- {
- struct frame *f = XFRAME (tip_frame);
-
- /* Only DX and DY have changed. */
- if (!NILP (tip_timer))
- {
- Lisp_Object timer = tip_timer;
- tip_timer = Qnil;
- call1 (Qcancel_timer, timer);
- }
-
- BLOCK_INPUT;
- compute_tip_xy (f, parms, dx, dy, &root_x, &root_y);
- XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- root_x, root_y - PIXEL_HEIGHT (f));
- UNBLOCK_INPUT;
- goto start_timer;
- }
- }
-
- /* Hide a previous tip, if any. */
- Fx_hide_tip ();
-
- ASET (last_show_tip_args, 0, string);
- ASET (last_show_tip_args, 1, frame);
- ASET (last_show_tip_args, 2, parms);
-
- /* Add default values to frame parameters. */
- if (NILP (Fassq (Qname, parms)))
- parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
- if (NILP (Fassq (Qinternal_border_width, parms)))
- parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
- if (NILP (Fassq (Qborder_width, parms)))
- parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
- if (NILP (Fassq (Qborder_color, parms)))
- parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
- if (NILP (Fassq (Qbackground_color, parms)))
- parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
- parms);
-
- /* Create a frame for the tooltip, and record it in the global
- variable tip_frame. */
- frame = x_create_tip_frame (FRAME_MAC_DISPLAY_INFO (f), parms);
- f = XFRAME (frame);
-
- /* Set up the frame's root window. Currently we use a size of 80
- columns x 40 lines. If someone wants to show a larger tip, he
- will loose. I don't think this is a realistic case. */
- w = XWINDOW (FRAME_ROOT_WINDOW (f));
- w->left = w->top = make_number (0);
- w->width = make_number (80);
- w->height = make_number (40);
- adjust_glyphs (f);
- w->pseudo_window_p = 1;
-
- /* Display the tooltip text in a temporary buffer. */
- buffer = Fget_buffer_create (build_string (" *tip*"));
- Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer);
- old_buffer = current_buffer;
- set_buffer_internal_1 (XBUFFER (buffer));
- Ferase_buffer ();
- Finsert (1, &string);
- clear_glyph_matrix (w->desired_matrix);
- clear_glyph_matrix (w->current_matrix);
- SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
- try_window (FRAME_ROOT_WINDOW (f), pos);
-
- /* Compute width and height of the tooltip. */
- width = height = 0;
- for (i = 0; i < w->desired_matrix->nrows; ++i)
- {
- struct glyph_row *row = &w->desired_matrix->rows[i];
- struct glyph *last;
- int row_width;
-
- /* Stop at the first empty row at the end. */
- if (!row->enabled_p || !row->displays_text_p)
- break;
-
- /* Let the row go over the full width of the frame. */
- row->full_width_p = 1;
-
- /* There's a glyph at the end of rows that is use to place
- the cursor there. Don't include the width of this glyph. */
- if (row->used[TEXT_AREA])
- {
- last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
- row_width = row->pixel_width - last->pixel_width;
- }
- else
- row_width = row->pixel_width;
-
- height += row->height;
- width = max (width, row_width);
- }
-
- /* Add the frame's internal border to the width and height the X
- window should have. */
- height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
- width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
-
- /* Move the tooltip window where the mouse pointer is. Resize and
- show it. */
- compute_tip_xy (f, parms, dx, dy, &root_x, &root_y);
-
-#if 0 /* TODO : Mac specifics */
- BLOCK_INPUT;
- XMoveResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- root_x, root_y - height, width, height);
- XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
- UNBLOCK_INPUT;
-#endif /* TODO */
-
- /* Draw into the window. */
- w->must_be_updated_p = 1;
- update_single_window (w, 1);
-
- /* Restore original current buffer. */
- set_buffer_internal_1 (old_buffer);
- windows_or_buffers_changed = old_windows_or_buffers_changed;
-
- start_timer:
- /* Let the tip disappear after timeout seconds. */
- tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
- intern ("x-hide-tip"));
-
- UNGCPRO;
- return unbind_to (count, Qnil);
-}
-
-
-DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
- "Hide the current tooltip window, if there is any.\n\
-Value is t is tooltip was open, nil otherwise.")
- ()
-{
- int count;
- Lisp_Object deleted, frame, timer;
- struct gcpro gcpro1, gcpro2;
-
- /* Return quickly if nothing to do. */
- if (NILP (tip_timer) && NILP (tip_frame))
- return Qnil;
-
- frame = tip_frame;
- timer = tip_timer;
- GCPRO2 (frame, timer);
- tip_frame = tip_timer = deleted = Qnil;
-
- count = BINDING_STACK_SIZE ();
- specbind (Qinhibit_redisplay, Qt);
- specbind (Qinhibit_quit, Qt);
-
- if (!NILP (timer))
- call1 (Qcancel_timer, timer);
-
- if (FRAMEP (frame))
- {
- Fdelete_frame (frame, Qnil);
- deleted = Qt;
- }
-
- UNGCPRO;
- return unbind_to (count, deleted);
-}
-#endif
-
-
-\f
-/***********************************************************************
- File selection dialog
- ***********************************************************************/
-
-#if 0 /* MAC_TODO: can standard file dialog */
-extern Lisp_Object Qfile_name_history;
-
-DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
- "Read file name, prompting with PROMPT in directory DIR.\n\
-Use a file selection dialog.\n\
-Select DEFAULT-FILENAME in the dialog's file selection box, if\n\
-specified. Don't let the user enter a file name in the file\n\
-selection dialog's entry field, if MUSTMATCH is non-nil.")
- (prompt, dir, default_filename, mustmatch)
- Lisp_Object prompt, dir, default_filename, mustmatch;
-{
- struct frame *f = SELECTED_FRAME ();
- Lisp_Object file = Qnil;
- int count = specpdl_ptr - specpdl;
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
- char filename[MAX_PATH + 1];
- char init_dir[MAX_PATH + 1];
- int use_dialog_p = 1;
-
- GCPRO5 (prompt, dir, default_filename, mustmatch, file);
- CHECK_STRING (prompt, 0);
- CHECK_STRING (dir, 1);
-
- /* Create the dialog with PROMPT as title, using DIR as initial
- directory and using "*" as pattern. */
- dir = Fexpand_file_name (dir, Qnil);
- strncpy (init_dir, XSTRING (dir)->data, MAX_PATH);
- init_dir[MAX_PATH] = '\0';
- unixtodos_filename (init_dir);
-
- if (STRINGP (default_filename))
- {
- char *file_name_only;
- char *full_path_name = XSTRING (default_filename)->data;
-
- unixtodos_filename (full_path_name);
-
- file_name_only = strrchr (full_path_name, '\\');
- if (!file_name_only)
- file_name_only = full_path_name;
- else
- {
- file_name_only++;
-
- /* If default_file_name is a directory, don't use the open
- file dialog, as it does not support selecting
- directories. */
- if (!(*file_name_only))
- use_dialog_p = 0;
- }
-
- strncpy (filename, file_name_only, MAX_PATH);
- filename[MAX_PATH] = '\0';
- }
- else
- filename[0] = '\0';
-
- if (use_dialog_p)
- {
- OPENFILENAME file_details;
- char *filename_file;
-
- /* Prevent redisplay. */
- specbind (Qinhibit_redisplay, Qt);
- BLOCK_INPUT;
-
- bzero (&file_details, sizeof (file_details));
- file_details.lStructSize = sizeof (file_details);
- file_details.hwndOwner = FRAME_W32_WINDOW (f);
- file_details.lpstrFile = filename;
- file_details.nMaxFile = sizeof (filename);
- file_details.lpstrInitialDir = init_dir;
- file_details.lpstrTitle = XSTRING (prompt)->data;
- file_details.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR;
-
- if (!NILP (mustmatch))
- file_details.Flags |= OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
-
- if (GetOpenFileName (&file_details))
- {
- dostounix_filename (filename);
- file = build_string (filename);
- }
- else
- file = Qnil;
-
- UNBLOCK_INPUT;
- file = unbind_to (count, file);
- }
- /* Open File dialog will not allow folders to be selected, so resort
- to minibuffer completing reads for directories. */
- else
- file = Fcompleting_read (prompt, intern ("read-file-name-internal"),
- dir, mustmatch, dir, Qfile_name_history,
- default_filename, Qnil);
-
- UNGCPRO;
-
- /* Make "Cancel" equivalent to C-g. */
- if (NILP (file))
- Fsignal (Qquit, Qnil);
-
- return unbind_to (count, file);
-}
-#endif
-
-
-\f
-/***********************************************************************
- Tests
- ***********************************************************************/
-
-#if GLYPH_DEBUG
-
-DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
- "Value is non-nil if SPEC is a valid image specification.")
- (spec)
- Lisp_Object spec;
-{
- return valid_image_p (spec) ? Qt : Qnil;
-}
-
-
-DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
- (spec)
- Lisp_Object spec;
-{
- int id = -1;
-
- if (valid_image_p (spec))
- id = lookup_image (SELECTED_FRAME (), spec);
-
- debug_print (spec);
- return make_number (id);
-}
-
-#endif /* GLYPH_DEBUG != 0 */
-
-
-\f
-void
-syms_of_macfns ()
-{
- /* Certainly running on Mac. */
- mac_in_use = 1;
-
- /* The section below is built by the lisp expression at the top of the file,
- just above where these variables are declared. */
- /*&&& init symbols here &&&*/
- Qauto_raise = intern ("auto-raise");
- staticpro (&Qauto_raise);
- Qauto_lower = intern ("auto-lower");
- staticpro (&Qauto_lower);
- Qbar = intern ("bar");
- staticpro (&Qbar);
- Qborder_color = intern ("border-color");
- staticpro (&Qborder_color);
- Qborder_width = intern ("border-width");
- staticpro (&Qborder_width);
- Qbox = intern ("box");
- staticpro (&Qbox);
- Qcursor_color = intern ("cursor-color");
- staticpro (&Qcursor_color);
- Qcursor_type = intern ("cursor-type");
- staticpro (&Qcursor_type);
- Qgeometry = intern ("geometry");
- staticpro (&Qgeometry);
- Qicon_left = intern ("icon-left");
- staticpro (&Qicon_left);
- Qicon_top = intern ("icon-top");
- staticpro (&Qicon_top);
- Qicon_type = intern ("icon-type");
- staticpro (&Qicon_type);
- Qicon_name = intern ("icon-name");
- staticpro (&Qicon_name);
- Qinternal_border_width = intern ("internal-border-width");
- staticpro (&Qinternal_border_width);
- Qleft = intern ("left");
- staticpro (&Qleft);
- Qright = intern ("right");
- staticpro (&Qright);
- Qmouse_color = intern ("mouse-color");
- staticpro (&Qmouse_color);
- Qnone = intern ("none");
- staticpro (&Qnone);
- Qparent_id = intern ("parent-id");
- staticpro (&Qparent_id);
- Qscroll_bar_width = intern ("scroll-bar-width");
- staticpro (&Qscroll_bar_width);
- Qsuppress_icon = intern ("suppress-icon");
- staticpro (&Qsuppress_icon);
- Qundefined_color = intern ("undefined-color");
- staticpro (&Qundefined_color);
- Qvertical_scroll_bars = intern ("vertical-scroll-bars");
- staticpro (&Qvertical_scroll_bars);
- Qvisibility = intern ("visibility");
- staticpro (&Qvisibility);
- Qwindow_id = intern ("window-id");
- staticpro (&Qwindow_id);
- Qx_frame_parameter = intern ("x-frame-parameter");
- staticpro (&Qx_frame_parameter);
- Qx_resource_name = intern ("x-resource-name");
- staticpro (&Qx_resource_name);
- Quser_position = intern ("user-position");
- staticpro (&Quser_position);
- Quser_size = intern ("user-size");
- staticpro (&Quser_size);
- Qscreen_gamma = intern ("screen-gamma");
- staticpro (&Qscreen_gamma);
- Qline_spacing = intern ("line-spacing");
- staticpro (&Qline_spacing);
- Qcenter = intern ("center");
- staticpro (&Qcenter);
- Qcancel_timer = intern ("cancel-timer");
- staticpro (&Qcancel_timer);
- /* This is the end of symbol initialization. */
-
- Qhyper = intern ("hyper");
- staticpro (&Qhyper);
- Qsuper = intern ("super");
- staticpro (&Qsuper);
- Qmeta = intern ("meta");
- staticpro (&Qmeta);
- Qalt = intern ("alt");
- staticpro (&Qalt);
- Qctrl = intern ("ctrl");
- staticpro (&Qctrl);
- Qcontrol = intern ("control");
- staticpro (&Qcontrol);
- Qshift = intern ("shift");
- staticpro (&Qshift);
-
- /* Text property `display' should be nonsticky by default. */
- Vtext_property_default_nonsticky
- = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
-
-
- Qlaplace = intern ("laplace");
- staticpro (&Qlaplace);
-
- Qface_set_after_frame_default = intern ("face-set-after-frame-default");
- staticpro (&Qface_set_after_frame_default);
-
- Fput (Qundefined_color, Qerror_conditions,
- Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
- Fput (Qundefined_color, Qerror_message,
- build_string ("Undefined color"));
-
- init_x_parm_symbols ();
-
- DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
- "List of directories to search for bitmap files for w32.");
- Vx_bitmap_file_path = decode_env_path ((char *) 0, "PATH");
-
- DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
- "The shape of the pointer when over text.\n\
-Changing the value does not affect existing frames\n\
-unless you set the mouse color.");
- Vx_pointer_shape = Qnil;
-
- DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
- "The name Emacs uses to look up resources; for internal use only.\n\
-`x-get-resource' uses this as the first component of the instance name\n\
-when requesting resource values.\n\
-Emacs initially sets `x-resource-name' to the name under which Emacs\n\
-was invoked, or to the value specified with the `-name' or `-rn'\n\
-switches, if present.");
- Vx_resource_name = Qnil;
-
- Vx_nontext_pointer_shape = Qnil;
-
- Vx_mode_pointer_shape = Qnil;
-
- DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape,
- "The shape of the pointer when Emacs is busy.\n\
-This variable takes effect when you create a new frame\n\
-or when you set the mouse color.");
- Vx_hourglass_pointer_shape = Qnil;
-
- DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
- "Non-zero means Emacs displays an hourglass pointer on window systems.");
- display_hourglass_p = 1;
-
- DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
- "*Seconds to wait before displaying an hourglass pointer.\n\
-Value must be an integer or float.");
- Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
-
- DEFVAR_LISP ("x-sensitive-text-pointer-shape",
- &Vx_sensitive_text_pointer_shape,
- "The shape of the pointer when over mouse-sensitive text.\n\
-This variable takes effect when you create a new frame\n\
-or when you set the mouse color.");
- Vx_sensitive_text_pointer_shape = Qnil;
-
- DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
- "A string indicating the foreground color of the cursor box.");
- Vx_cursor_fore_pixel = Qnil;
-
- DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
- "Non-nil if no window manager is in use.\n\
-Emacs doesn't try to figure this out; this is always nil\n\
-unless you set it to something else.");
- /* We don't have any way to find this out, so set it to nil
- and maybe the user would like to set it to t. */
- Vx_no_window_manager = Qnil;
-
- DEFVAR_LISP ("x-pixel-size-width-font-regexp",
- &Vx_pixel_size_width_font_regexp,
- "Regexp matching a font name whose width is the same as `PIXEL_SIZE'.\n\
-\n\
-Since Emacs gets width of a font matching with this regexp from\n\
-PIXEL_SIZE field of the name, font finding mechanism gets faster for\n\
-such a font. This is especially effective for such large fonts as\n\
-Chinese, Japanese, and Korean.");
- Vx_pixel_size_width_font_regexp = Qnil;
-
- DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
- "Time after which cached images are removed from the cache.\n\
-When an image has not been displayed this many seconds, remove it\n\
-from the image cache. Value must be an integer or nil with nil\n\
-meaning don't clear the cache.");
- Vimage_cache_eviction_delay = make_number (30 * 60);
-
-#if 0 /* MAC_TODO: implement get X resource */
- defsubr (&Sx_get_resource);
-#endif
- defsubr (&Sx_change_window_property);
- defsubr (&Sx_delete_window_property);
- defsubr (&Sx_window_property);
- defsubr (&Sxw_display_color_p);
- defsubr (&Sx_display_grayscale_p);
- defsubr (&Sxw_color_defined_p);
- defsubr (&Sxw_color_values);
- defsubr (&Sx_server_max_request_size);
- defsubr (&Sx_server_vendor);
- defsubr (&Sx_server_version);
- defsubr (&Sx_display_pixel_width);
- defsubr (&Sx_display_pixel_height);
- defsubr (&Sx_display_mm_width);
- defsubr (&Sx_display_mm_height);
- defsubr (&Sx_display_screens);
- defsubr (&Sx_display_planes);
- defsubr (&Sx_display_color_cells);
- defsubr (&Sx_display_visual_class);
- defsubr (&Sx_display_backing_store);
- defsubr (&Sx_display_save_under);
-#if 0 /* MAC_TODO: implement XParseGeometry */
- defsubr (&Sx_parse_geometry);
-#endif
- defsubr (&Sx_create_frame);
-#if 0 /* MAC_TODO: implement network support */
- defsubr (&Sx_open_connection);
- defsubr (&Sx_close_connection);
-#endif
- defsubr (&Sx_display_list);
- defsubr (&Sx_synchronize);
-
- /* Setting callback functions for fontset handler. */
- get_font_info_func = x_get_font_info;
-
-#if 0 /* This function pointer doesn't seem to be used anywhere.
- And the pointer assigned has the wrong type, anyway. */
- list_fonts_func = x_list_fonts;
-#endif
-
- load_font_func = x_load_font;
- find_ccl_program_func = x_find_ccl_program;
- query_font_func = x_query_font;
-
- set_frame_fontset_func = x_set_font;
- check_window_system_func = check_mac;
-
-#if 0 /* MAC_TODO: Image support for Mac Images. */
- Qxbm = intern ("xbm");
- staticpro (&Qxbm);
- QCtype = intern (":type");
- staticpro (&QCtype);
- QCconversion = intern (":conversion");
- staticpro (&QCconversion);
- QCheuristic_mask = intern (":heuristic-mask");
- staticpro (&QCheuristic_mask);
- QCcolor_symbols = intern (":color-symbols");
- staticpro (&QCcolor_symbols);
- QCascent = intern (":ascent");
- staticpro (&QCascent);
- QCmargin = intern (":margin");
- staticpro (&QCmargin);
- QCrelief = intern (":relief");
- staticpro (&QCrelief);
- Qpostscript = intern ("postscript");
- staticpro (&Qpostscript);
- QCloader = intern (":loader");
- staticpro (&QCloader);
- QCbounding_box = intern (":bounding-box");
- staticpro (&QCbounding_box);
- QCpt_width = intern (":pt-width");
- staticpro (&QCpt_width);
- QCpt_height = intern (":pt-height");
- staticpro (&QCpt_height);
- QCindex = intern (":index");
- staticpro (&QCindex);
- Qpbm = intern ("pbm");
- staticpro (&Qpbm);
-
-#if HAVE_XPM
- Qxpm = intern ("xpm");
- staticpro (&Qxpm);
-#endif
-
-#if HAVE_JPEG
- Qjpeg = intern ("jpeg");
- staticpro (&Qjpeg);
-#endif
-
-#if HAVE_TIFF
- Qtiff = intern ("tiff");
- staticpro (&Qtiff);
-#endif
-
-#if HAVE_GIF
- Qgif = intern ("gif");
- staticpro (&Qgif);
-#endif
-
-#if HAVE_PNG
- Qpng = intern ("png");
- staticpro (&Qpng);
-#endif
-
- defsubr (&Sclear_image_cache);
-
-#if GLYPH_DEBUG
- defsubr (&Simagep);
- defsubr (&Slookup_image);
-#endif
-#endif /* TODO */
-
- hourglass_atimer = NULL;
- hourglass_shown_p = 0;
-#ifdef TODO /* Tooltip support not complete. */
- defsubr (&Sx_show_tip);
- defsubr (&Sx_hide_tip);
-#endif
- tip_timer = Qnil;
- staticpro (&tip_timer);
- tip_frame = Qnil;
- staticpro (&tip_frame);
-
-#if 0 /* MAC_TODO */
- defsubr (&Sx_file_dialog);
-#endif
-}
-
-
-void
-init_xfns ()
-{
- image_types = NULL;
- Vimage_types = Qnil;
-
-#if 0 /* TODO : Image support for W32 */
- define_image_type (&xbm_type);
- define_image_type (&gs_type);
- define_image_type (&pbm_type);
-
-#if HAVE_XPM
- define_image_type (&xpm_type);
-#endif
-
-#if HAVE_JPEG
- define_image_type (&jpeg_type);
-#endif
-
-#if HAVE_TIFF
- define_image_type (&tiff_type);
-#endif
-
-#if HAVE_GIF
- define_image_type (&gif_type);
-#endif
-
-#if HAVE_PNG
- define_image_type (&png_type);
-#endif
-#endif /* NTEMACS_TODO */
-}
-
-#undef abort
-
-#if 0
-void
-w32_abort()
-{
- int button;
- button = MessageBox (NULL,
- "A fatal error has occurred!\n\n"
- "Select Abort to exit, Retry to debug, Ignore to continue",
- "Emacs Abort Dialog",
- MB_ICONEXCLAMATION | MB_TASKMODAL
- | MB_SETFOREGROUND | MB_ABORTRETRYIGNORE);
- switch (button)
- {
- case IDRETRY:
- DebugBreak ();
- break;
- case IDIGNORE:
- break;
- case IDABORT:
- default:
- abort ();
- break;
- }
-}
-
-/* For convenience when debugging. */
-int
-w32_last_error()
-{
- return GetLastError ();
-}
-#endif
+++ /dev/null
-/* Menu support for GNU Emacs on the for Mac OS.
- Copyright (C) 2000 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Contributed by Andrew Choi (akochoi@users.sourceforge.net). */
-
-#include <config.h>
-#include <signal.h>
-
-#include <stdio.h>
-#include "lisp.h"
-#include "termhooks.h"
-#include "frame.h"
-#include "window.h"
-#include "keyboard.h"
-#include "blockinput.h"
-#include "buffer.h"
-#include "charset.h"
-#include "coding.h"
-#include "keymap.h"
-
-#include <MacTypes.h>
-#include <Menus.h>
-#include <QuickDraw.h>
-#include <ToolUtils.h>
-#include <Fonts.h>
-#include <Controls.h>
-#include <Windows.h>
-#include <Events.h>
-#if defined (__MRC__) || defined (CODEWARRIOR_VERSION_6)
-#include <ControlDefinitions.h>
-#endif
-
-/* This may include sys/types.h, and that somehow loses
- if this is not done before the other system files. */
-#include "macterm.h"
-
-/* Load sys/types.h if not already loaded.
- In some systems loading it twice is suicidal. */
-#ifndef makedev
-#include <sys/types.h>
-#endif
-
-#include "dispextern.h"
-
-#define POPUP_SUBMENU_ID 235
-#define MIN_MENU_ID 256
-#define MIN_SUBMENU_ID 1
-
-#define DIALOG_WINDOW_RESOURCE 130
-
-#define HAVE_DIALOGS 1
-
-#undef HAVE_MULTILINGUAL_MENU
-
-/******************************************************************/
-/* Definitions copied from lwlib.h */
-
-typedef void * XtPointer;
-
-#define True 1
-#define False 0
-
-enum button_type
-{
- BUTTON_TYPE_NONE,
- BUTTON_TYPE_TOGGLE,
- BUTTON_TYPE_RADIO
-};
-
-typedef struct _widget_value
-{
- /* name of widget */
- char* name;
- /* value (meaning depend on widget type) */
- char* value;
- /* keyboard equivalent. no implications for XtTranslations */
- char* key;
- /* Help string or null if none. */
- char *help;
- /* true if enabled */
- Boolean enabled;
- /* true if selected */
- Boolean selected;
- /* The type of a button. */
- enum button_type button_type;
- /* true if menu title */
- Boolean title;
-#if 0
- /* true if was edited (maintained by get_value) */
- Boolean edited;
- /* true if has changed (maintained by lw library) */
- change_type change;
- /* true if this widget itself has changed,
- but not counting the other widgets found in the `next' field. */
- change_type this_one_change;
-#endif
- /* Contents of the sub-widgets, also selected slot for checkbox */
- struct _widget_value* contents;
- /* data passed to callback */
- XtPointer call_data;
- /* next one in the list */
- struct _widget_value* next;
-#if 0
- /* slot for the toolkit dependent part. Always initialize to NULL. */
- void* toolkit_data;
- /* tell us if we should free the toolkit data slot when freeing the
- widget_value itself. */
- Boolean free_toolkit_data;
-
- /* we resource the widget_value structures; this points to the next
- one on the free list if this one has been deallocated.
- */
- struct _widget_value *free_list;
-#endif
-} widget_value;
-
-/* Assumed by other routines to zero area returned. */
-#define malloc_widget_value() (void *)memset (xmalloc (sizeof (widget_value)),\
- 0, (sizeof (widget_value)))
-#define free_widget_value(wv) xfree (wv)
-
-/******************************************************************/
-
-#define min(x,y) (((x) < (y)) ? (x) : (y))
-#define max(x,y) (((x) > (y)) ? (x) : (y))
-
-#ifndef TRUE
-#define TRUE 1
-#define FALSE 0
-#endif /* no TRUE */
-
-Lisp_Object Vmenu_updating_frame;
-
-Lisp_Object Qdebug_on_next_call;
-
-extern Lisp_Object Qmenu_bar;
-extern Lisp_Object Qmouse_click, Qevent_kind;
-
-extern Lisp_Object QCtoggle, QCradio;
-
-extern Lisp_Object Voverriding_local_map;
-extern Lisp_Object Voverriding_local_map_menu_flag;
-
-extern Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
-
-extern Lisp_Object Qmenu_bar_update_hook;
-
-void set_frame_menubar ();
-
-static void push_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
- Lisp_Object, Lisp_Object, Lisp_Object,
- Lisp_Object, Lisp_Object));
-static Lisp_Object mac_dialog_show ();
-static Lisp_Object mac_menu_show ();
-
-static void keymap_panes ();
-static void single_keymap_panes ();
-static void single_menu_item ();
-static void list_of_panes ();
-static void list_of_items ();
-
-static void fill_submenu (MenuHandle, widget_value *, int);
-static void fill_menubar (widget_value *);
-
-\f
-/* This holds a Lisp vector that holds the results of decoding
- the keymaps or alist-of-alists that specify a menu.
-
- It describes the panes and items within the panes.
-
- Each pane is described by 3 elements in the vector:
- t, the pane name, the pane's prefix key.
- Then follow the pane's items, with 5 elements per item:
- the item string, the enable flag, the item's value,
- the definition, and the equivalent keyboard key's description string.
-
- In some cases, multiple levels of menus may be described.
- A single vector slot containing nil indicates the start of a submenu.
- A single vector slot containing lambda indicates the end of a submenu.
- The submenu follows a menu item which is the way to reach the submenu.
-
- A single vector slot containing quote indicates that the
- following items should appear on the right of a dialog box.
-
- Using a Lisp vector to hold this information while we decode it
- takes care of protecting all the data from GC. */
-
-#define MENU_ITEMS_PANE_NAME 1
-#define MENU_ITEMS_PANE_PREFIX 2
-#define MENU_ITEMS_PANE_LENGTH 3
-
-enum menu_item_idx
-{
- MENU_ITEMS_ITEM_NAME = 0,
- MENU_ITEMS_ITEM_ENABLE,
- MENU_ITEMS_ITEM_VALUE,
- MENU_ITEMS_ITEM_EQUIV_KEY,
- MENU_ITEMS_ITEM_DEFINITION,
- MENU_ITEMS_ITEM_TYPE,
- MENU_ITEMS_ITEM_SELECTED,
- MENU_ITEMS_ITEM_HELP,
- MENU_ITEMS_ITEM_LENGTH
-};
-
-static Lisp_Object menu_items;
-
-/* Number of slots currently allocated in menu_items. */
-static int menu_items_allocated;
-
-/* This is the index in menu_items of the first empty slot. */
-static int menu_items_used;
-
-/* The number of panes currently recorded in menu_items,
- excluding those within submenus. */
-static int menu_items_n_panes;
-
-/* Current depth within submenus. */
-static int menu_items_submenu_depth;
-
-/* Flag which when set indicates a dialog or menu has been posted by
- Xt on behalf of one of the widget sets. */
-static int popup_activated_flag;
-
-static int next_menubar_widget_id;
-
-/* This is set nonzero after the user activates the menu bar, and set
- to zero again after the menu bars are redisplayed by prepare_menu_bar.
- While it is nonzero, all calls to set_frame_menubar go deep.
-
- I don't understand why this is needed, but it does seem to be
- needed on Motif, according to Marcus Daniels <marcus@sysc.pdx.edu>. */
-
-int pending_menu_activation;
-\f
-/* Initialize the menu_items structure if we haven't already done so.
- Also mark it as currently empty. */
-
-static void
-init_menu_items ()
-{
- if (NILP (menu_items))
- {
- menu_items_allocated = 60;
- menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil);
- }
-
- menu_items_used = 0;
- menu_items_n_panes = 0;
- menu_items_submenu_depth = 0;
-}
-
-/* Call at the end of generating the data in menu_items.
- This fills in the number of items in the last pane. */
-
-static void
-finish_menu_items ()
-{
-}
-
-/* Call when finished using the data for the current menu
- in menu_items. */
-
-static void
-discard_menu_items ()
-{
- /* Free the structure if it is especially large.
- Otherwise, hold on to it, to save time. */
- if (menu_items_allocated > 200)
- {
- menu_items = Qnil;
- menu_items_allocated = 0;
- }
-}
-
-/* Make the menu_items vector twice as large. */
-
-static void
-grow_menu_items ()
-{
- Lisp_Object old;
- int old_size = menu_items_allocated;
- old = menu_items;
-
- menu_items_allocated *= 2;
- menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil);
- bcopy (XVECTOR (old)->contents, XVECTOR (menu_items)->contents,
- old_size * sizeof (Lisp_Object));
-}
-
-/* Begin a submenu. */
-
-static void
-push_submenu_start ()
-{
- if (menu_items_used + 1 > menu_items_allocated)
- grow_menu_items ();
-
- XVECTOR (menu_items)->contents[menu_items_used++] = Qnil;
- menu_items_submenu_depth++;
-}
-
-/* End a submenu. */
-
-static void
-push_submenu_end ()
-{
- if (menu_items_used + 1 > menu_items_allocated)
- grow_menu_items ();
-
- XVECTOR (menu_items)->contents[menu_items_used++] = Qlambda;
- menu_items_submenu_depth--;
-}
-
-/* Indicate boundary between left and right. */
-
-static void
-push_left_right_boundary ()
-{
- if (menu_items_used + 1 > menu_items_allocated)
- grow_menu_items ();
-
- XVECTOR (menu_items)->contents[menu_items_used++] = Qquote;
-}
-
-/* Start a new menu pane in menu_items..
- NAME is the pane name. PREFIX_VEC is a prefix key for this pane. */
-
-static void
-push_menu_pane (name, prefix_vec)
- Lisp_Object name, prefix_vec;
-{
- if (menu_items_used + MENU_ITEMS_PANE_LENGTH > menu_items_allocated)
- grow_menu_items ();
-
- if (menu_items_submenu_depth == 0)
- menu_items_n_panes++;
- XVECTOR (menu_items)->contents[menu_items_used++] = Qt;
- XVECTOR (menu_items)->contents[menu_items_used++] = name;
- XVECTOR (menu_items)->contents[menu_items_used++] = prefix_vec;
-}
-
-/* Push one menu item into the current pane. NAME is the string to
- display. ENABLE if non-nil means this item can be selected. KEY
- is the key generated by choosing this item, or nil if this item
- doesn't really have a definition. DEF is the definition of this
- item. EQUIV is the textual description of the keyboard equivalent
- for this item (or nil if none). TYPE is the type of this menu
- item, one of nil, `toggle' or `radio'. */
-
-static void
-push_menu_item (name, enable, key, def, equiv, type, selected, help)
- Lisp_Object name, enable, key, def, equiv, type, selected, help;
-{
- if (menu_items_used + MENU_ITEMS_ITEM_LENGTH > menu_items_allocated)
- grow_menu_items ();
-
- XVECTOR (menu_items)->contents[menu_items_used++] = name;
- XVECTOR (menu_items)->contents[menu_items_used++] = enable;
- XVECTOR (menu_items)->contents[menu_items_used++] = key;
- XVECTOR (menu_items)->contents[menu_items_used++] = equiv;
- XVECTOR (menu_items)->contents[menu_items_used++] = def;
- XVECTOR (menu_items)->contents[menu_items_used++] = type;
- XVECTOR (menu_items)->contents[menu_items_used++] = selected;
- XVECTOR (menu_items)->contents[menu_items_used++] = help;
-}
-\f
-/* Look through KEYMAPS, a vector of keymaps that is NMAPS long,
- and generate menu panes for them in menu_items.
- If NOTREAL is nonzero,
- don't bother really computing whether an item is enabled. */
-
-static void
-keymap_panes (keymaps, nmaps, notreal)
- Lisp_Object *keymaps;
- int nmaps;
- int notreal;
-{
- int mapno;
-
- init_menu_items ();
-
- /* Loop over the given keymaps, making a pane for each map.
- But don't make a pane that is empty--ignore that map instead.
- P is the number of panes we have made so far. */
- for (mapno = 0; mapno < nmaps; mapno++)
- single_keymap_panes (keymaps[mapno], Qnil, Qnil, notreal, 10);
-
- finish_menu_items ();
-}
-
-/* This is a recursive subroutine of keymap_panes.
- It handles one keymap, KEYMAP.
- The other arguments are passed along
- or point to local variables of the previous function.
- If NOTREAL is nonzero, only check for equivalent key bindings, don't
- evaluate expressions in menu items and don't make any menu.
-
- If we encounter submenus deeper than MAXDEPTH levels, ignore them. */
-
-static void
-single_keymap_panes (keymap, pane_name, prefix, notreal, maxdepth)
- Lisp_Object keymap;
- Lisp_Object pane_name;
- Lisp_Object prefix;
- int notreal;
- int maxdepth;
-{
- Lisp_Object pending_maps = Qnil;
- Lisp_Object tail, item;
- struct gcpro gcpro1, gcpro2;
-
- if (maxdepth <= 0)
- return;
-
- push_menu_pane (pane_name, prefix);
-
- for (tail = keymap; CONSP (tail); tail = XCDR (tail))
- {
- GCPRO2 (keymap, pending_maps);
- /* Look at each key binding, and if it is a menu item add it
- to this menu. */
- item = XCAR (tail);
- if (CONSP (item))
- single_menu_item (XCAR (item), XCDR (item),
- &pending_maps, notreal, maxdepth);
- else if (VECTORP (item))
- {
- /* Loop over the char values represented in the vector. */
- int len = XVECTOR (item)->size;
- int c;
- for (c = 0; c < len; c++)
- {
- Lisp_Object character;
- XSETFASTINT (character, c);
- single_menu_item (character, XVECTOR (item)->contents[c],
- &pending_maps, notreal, maxdepth);
- }
- }
- UNGCPRO;
- }
-
- /* Process now any submenus which want to be panes at this level. */
- while (!NILP (pending_maps))
- {
- Lisp_Object elt, eltcdr, string;
- elt = Fcar (pending_maps);
- eltcdr = XCDR (elt);
- string = XCAR (eltcdr);
- /* We no longer discard the @ from the beginning of the string here.
- Instead, we do this in mac_menu_show. */
- single_keymap_panes (Fcar (elt), string,
- XCDR (eltcdr), notreal, maxdepth - 1);
- pending_maps = Fcdr (pending_maps);
- }
-}
-\f
-/* This is a subroutine of single_keymap_panes that handles one
- keymap entry.
- KEY is a key in a keymap and ITEM is its binding.
- PENDING_MAPS_PTR points to a list of keymaps waiting to be made into
- separate panes.
- If NOTREAL is nonzero, only check for equivalent key bindings, don't
- evaluate expressions in menu items and don't make any menu.
- If we encounter submenus deeper than MAXDEPTH levels, ignore them. */
-
-static void
-single_menu_item (key, item, pending_maps_ptr, notreal, maxdepth)
- Lisp_Object key, item;
- Lisp_Object *pending_maps_ptr;
- int maxdepth, notreal;
-{
- Lisp_Object map, item_string, enabled;
- struct gcpro gcpro1, gcpro2;
- int res;
-
- /* Parse the menu item and leave the result in item_properties. */
- GCPRO2 (key, item);
- res = parse_menu_item (item, notreal, 0);
- UNGCPRO;
- if (!res)
- return; /* Not a menu item. */
-
- map = XVECTOR (item_properties)->contents[ITEM_PROPERTY_MAP];
-
- if (notreal)
- {
- /* We don't want to make a menu, just traverse the keymaps to
- precompute equivalent key bindings. */
- if (!NILP (map))
- single_keymap_panes (map, Qnil, key, 1, maxdepth - 1);
- return;
- }
-
- enabled = XVECTOR (item_properties)->contents[ITEM_PROPERTY_ENABLE];
- item_string = XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME];
-
- if (!NILP (map) && XSTRING (item_string)->data[0] == '@')
- {
- if (!NILP (enabled))
- /* An enabled separate pane. Remember this to handle it later. */
- *pending_maps_ptr = Fcons (Fcons (map, Fcons (item_string, key)),
- *pending_maps_ptr);
- return;
- }
-
- push_menu_item (item_string, enabled, key,
- XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF],
- XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ],
- XVECTOR (item_properties)->contents[ITEM_PROPERTY_TYPE],
- XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED],
- XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]);
-
- /* Display a submenu using the toolkit. */
- if (! (NILP (map) || NILP (enabled)))
- {
- push_submenu_start ();
- single_keymap_panes (map, Qnil, key, 0, maxdepth - 1);
- push_submenu_end ();
- }
-}
-\f
-/* Push all the panes and items of a menu described by the
- alist-of-alists MENU.
- This handles old-fashioned calls to x-popup-menu. */
-
-static void
-list_of_panes (menu)
- Lisp_Object menu;
-{
- Lisp_Object tail;
-
- init_menu_items ();
-
- for (tail = menu; !NILP (tail); tail = Fcdr (tail))
- {
- Lisp_Object elt, pane_name, pane_data;
- elt = Fcar (tail);
- pane_name = Fcar (elt);
- CHECK_STRING (pane_name, 0);
- push_menu_pane (pane_name, Qnil);
- pane_data = Fcdr (elt);
- CHECK_CONS (pane_data, 0);
- list_of_items (pane_data);
- }
-
- finish_menu_items ();
-}
-
-/* Push the items in a single pane defined by the alist PANE. */
-
-static void
-list_of_items (pane)
- Lisp_Object pane;
-{
- Lisp_Object tail, item, item1;
-
- for (tail = pane; !NILP (tail); tail = Fcdr (tail))
- {
- item = Fcar (tail);
- if (STRINGP (item))
- push_menu_item (item, Qnil, Qnil, Qt, Qnil, Qnil, Qnil, Qnil);
- else if (NILP (item))
- push_left_right_boundary ();
- else
- {
- CHECK_CONS (item, 0);
- item1 = Fcar (item);
- CHECK_STRING (item1, 1);
- push_menu_item (item1, Qt, Fcdr (item), Qt, Qnil, Qnil, Qnil, Qnil);
- }
- }
-}
-\f
-DEFUN ("x-popup-menu", Fx_popup_menu, Sx_popup_menu, 2, 2, 0,
- "Pop up a deck-of-cards menu and return user's selection.\n\
-POSITION is a position specification. This is either a mouse button event\n\
-or a list ((XOFFSET YOFFSET) WINDOW)\n\
-where XOFFSET and YOFFSET are positions in pixels from the top left\n\
-corner of WINDOW's frame. (WINDOW may be a frame object instead of a window.)\n\
-This controls the position of the center of the first line\n\
-in the first pane of the menu, not the top left of the menu as a whole.\n\
-If POSITION is t, it means to use the current mouse position.\n\
-\n\
-MENU is a specifier for a menu. For the simplest case, MENU is a keymap.\n\
-The menu items come from key bindings that have a menu string as well as\n\
-a definition; actually, the \"definition\" in such a key binding looks like\n\
-\(STRING . REAL-DEFINITION). To give the menu a title, put a string into\n\
-the keymap as a top-level element.\n\n\
-If REAL-DEFINITION is nil, that puts a nonselectable string in the menu.\n\
-Otherwise, REAL-DEFINITION should be a valid key binding definition.\n\
-\n\
-You can also use a list of keymaps as MENU.\n\
- Then each keymap makes a separate pane.\n\
-When MENU is a keymap or a list of keymaps, the return value\n\
-is a list of events.\n\n\
-\n\
-Alternatively, you can specify a menu of multiple panes\n\
- with a list of the form (TITLE PANE1 PANE2...),\n\
-where each pane is a list of form (TITLE ITEM1 ITEM2...).\n\
-Each ITEM is normally a cons cell (STRING . VALUE);\n\
-but a string can appear as an item--that makes a nonselectable line\n\
-in the menu.\n\
-With this form of menu, the return value is VALUE from the chosen item.\n\
-\n\
-If POSITION is nil, don't display the menu at all, just precalculate the\n\
-cached information about equivalent key sequences.")
- (position, menu)
- Lisp_Object position, menu;
-{
- Lisp_Object keymap, tem;
- int xpos, ypos;
- Lisp_Object title;
- char *error_name;
- Lisp_Object selection;
- FRAME_PTR f;
- Lisp_Object x, y, window;
- int keymaps = 0;
- int for_click = 0;
- struct gcpro gcpro1;
-
-#ifdef HAVE_MENUS
- if (! NILP (position))
- {
- check_mac ();
-
- /* Decode the first argument: find the window and the coordinates. */
- if (EQ (position, Qt)
- || (CONSP (position) && EQ (XCAR (position), Qmenu_bar)))
- {
- /* Use the mouse's current position. */
- FRAME_PTR new_f = SELECTED_FRAME ();
- Lisp_Object bar_window;
- enum scroll_bar_part part;
- unsigned long time;
-
- if (mouse_position_hook)
- (*mouse_position_hook) (&new_f, 1, &bar_window,
- &part, &x, &y, &time);
- if (new_f != 0)
- XSETFRAME (window, new_f);
- else
- {
- window = selected_window;
- XSETFASTINT (x, 0);
- XSETFASTINT (y, 0);
- }
- }
- else
- {
- tem = Fcar (position);
- if (CONSP (tem))
- {
- window = Fcar (Fcdr (position));
- x = Fcar (tem);
- y = Fcar (Fcdr (tem));
- }
- else
- {
- for_click = 1;
- tem = Fcar (Fcdr (position)); /* EVENT_START (position) */
- window = Fcar (tem); /* POSN_WINDOW (tem) */
- tem = Fcar (Fcdr (Fcdr (tem))); /* POSN_WINDOW_POSN (tem) */
- x = Fcar (tem);
- y = Fcdr (tem);
- }
- }
-
- CHECK_NUMBER (x, 0);
- CHECK_NUMBER (y, 0);
-
- /* Decode where to put the menu. */
-
- if (FRAMEP (window))
- {
- f = XFRAME (window);
- xpos = 0;
- ypos = 0;
- }
- else if (WINDOWP (window))
- {
- CHECK_LIVE_WINDOW (window, 0);
- f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
-
- xpos = (FONT_WIDTH (FRAME_FONT (f))
- * XFASTINT (XWINDOW (window)->left));
- ypos = (FRAME_LINE_HEIGHT (f)
- * XFASTINT (XWINDOW (window)->top));
- }
- else
- /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
- but I don't want to make one now. */
- CHECK_WINDOW (window, 0);
-
- xpos += XINT (x);
- ypos += XINT (y);
-
- XSETFRAME (Vmenu_updating_frame, f);
- }
- Vmenu_updating_frame = Qnil;
-#endif /* HAVE_MENUS */
-
- title = Qnil;
- GCPRO1 (title);
-
- /* Decode the menu items from what was specified. */
-
- keymap = Fkeymapp (menu);
- tem = Qnil;
- if (CONSP (menu))
- tem = Fkeymapp (Fcar (menu));
- if (!NILP (keymap))
- {
- /* We were given a keymap. Extract menu info from the keymap. */
- Lisp_Object prompt;
- keymap = get_keymap (menu);
-
- /* Extract the detailed info to make one pane. */
- keymap_panes (&menu, 1, NILP (position));
-
- /* Search for a string appearing directly as an element of the keymap.
- That string is the title of the menu. */
- prompt = Fkeymap_prompt (keymap);
- if (NILP (title) && !NILP (prompt))
- title = prompt;
-
- /* Make that be the pane title of the first pane. */
- if (!NILP (prompt) && menu_items_n_panes >= 0)
- XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME] = prompt;
-
- keymaps = 1;
- }
- else if (!NILP (tem))
- {
- /* We were given a list of keymaps. */
- int nmaps = XFASTINT (Flength (menu));
- Lisp_Object *maps
- = (Lisp_Object *) alloca (nmaps * sizeof (Lisp_Object));
- int i;
-
- title = Qnil;
-
- /* The first keymap that has a prompt string
- supplies the menu title. */
- for (tem = menu, i = 0; CONSP (tem); tem = Fcdr (tem))
- {
- Lisp_Object prompt;
-
- maps[i++] = keymap = get_keymap (Fcar (tem));
-
- prompt = Fkeymap_prompt (keymap);
- if (NILP (title) && !NILP (prompt))
- title = prompt;
- }
-
- /* Extract the detailed info to make one pane. */
- keymap_panes (maps, nmaps, NILP (position));
-
- /* Make the title be the pane title of the first pane. */
- if (!NILP (title) && menu_items_n_panes >= 0)
- XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME] = title;
-
- keymaps = 1;
- }
- else
- {
- /* We were given an old-fashioned menu. */
- title = Fcar (menu);
- CHECK_STRING (title, 1);
-
- list_of_panes (Fcdr (menu));
-
- keymaps = 0;
- }
-
- if (NILP (position))
- {
- discard_menu_items ();
- UNGCPRO;
- return Qnil;
- }
-
-#ifdef HAVE_MENUS
- /* Display them in a menu. */
- BLOCK_INPUT;
-
- selection = mac_menu_show (f, xpos, ypos, for_click,
- keymaps, title, &error_name);
- UNBLOCK_INPUT;
-
- discard_menu_items ();
-
- UNGCPRO;
-#endif /* HAVE_MENUS */
-
- if (error_name) error (error_name);
- return selection;
-}
-
-#ifdef HAVE_MENUS
-
-DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 2, 0,
- "Pop up a dialog box and return user's selection.\n\
-POSITION specifies which frame to use.\n\
-This is normally a mouse button event or a window or frame.\n\
-If POSITION is t, it means to use the frame the mouse is on.\n\
-The dialog box appears in the middle of the specified frame.\n\
-\n\
-CONTENTS specifies the alternatives to display in the dialog box.\n\
-It is a list of the form (TITLE ITEM1 ITEM2...).\n\
-Each ITEM is a cons cell (STRING . VALUE).\n\
-The return value is VALUE from the chosen item.\n\n\
-An ITEM may also be just a string--that makes a nonselectable item.\n\
-An ITEM may also be nil--that means to put all preceding items\n\
-on the left of the dialog box and all following items on the right.\n\
-\(By default, approximately half appear on each side.)")
- (position, contents)
- Lisp_Object position, contents;
-{
- FRAME_PTR f;
- Lisp_Object window;
-
- check_mac ();
-
- /* Decode the first argument: find the window or frame to use. */
- if (EQ (position, Qt)
- || (CONSP (position) && EQ (XCAR (position), Qmenu_bar)))
- {
-#if 0 /* Using the frame the mouse is on may not be right. */
- /* Use the mouse's current position. */
- FRAME_PTR new_f = SELECTED_FRAME ();
- Lisp_Object bar_window;
- int part;
- unsigned long time;
- Lisp_Object x, y;
-
- (*mouse_position_hook) (&new_f, 1, &bar_window, &part, &x, &y, &time);
-
- if (new_f != 0)
- XSETFRAME (window, new_f);
- else
- window = selected_window;
-#endif
- window = selected_window;
- }
- else if (CONSP (position))
- {
- Lisp_Object tem;
- tem = Fcar (position);
- if (CONSP (tem))
- window = Fcar (Fcdr (position));
- else
- {
- tem = Fcar (Fcdr (position)); /* EVENT_START (position) */
- window = Fcar (tem); /* POSN_WINDOW (tem) */
- }
- }
- else if (WINDOWP (position) || FRAMEP (position))
- window = position;
- else
- window = Qnil;
-
- /* Decode where to put the menu. */
-
- if (FRAMEP (window))
- f = XFRAME (window);
- else if (WINDOWP (window))
- {
- CHECK_LIVE_WINDOW (window, 0);
- f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
- }
- else
- /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
- but I don't want to make one now. */
- CHECK_WINDOW (window, 0);
-
-#ifndef HAVE_DIALOGS
- /* Display a menu with these alternatives
- in the middle of frame F. */
- {
- Lisp_Object x, y, frame, newpos;
- XSETFRAME (frame, f);
- XSETINT (x, x_pixel_width (f) / 2);
- XSETINT (y, x_pixel_height (f) / 2);
- newpos = Fcons (Fcons (x, Fcons (y, Qnil)), Fcons (frame, Qnil));
-
- return Fx_popup_menu (newpos,
- Fcons (Fcar (contents), Fcons (contents, Qnil)));
- }
-#else /* HAVE_DIALOGS */
- {
- Lisp_Object title;
- char *error_name;
- Lisp_Object selection;
-
- /* Decode the dialog items from what was specified. */
- title = Fcar (contents);
- CHECK_STRING (title, 1);
-
- list_of_panes (Fcons (contents, Qnil));
-
- /* Display them in a dialog box. */
- BLOCK_INPUT;
- selection = mac_dialog_show (f, 0, title, &error_name);
- UNBLOCK_INPUT;
-
- discard_menu_items ();
-
- if (error_name) error (error_name);
- return selection;
- }
-#endif /* HAVE_DIALOGS */
-}
-
-/* Activate the menu bar of frame F.
- This is called from keyboard.c when it gets the
- menu_bar_activate_event out of the Emacs event queue.
-
- To activate the menu bar, we signal to the input thread that it can
- return from the WM_INITMENU message, allowing the normal Windows
- processing of the menus.
-
- But first we recompute the menu bar contents (the whole tree).
-
- This way we can safely execute Lisp code. */
-
-void
-x_activate_menubar (f)
- FRAME_PTR f;
-{
- SInt32 menu_choice;
- extern Point saved_menu_event_location;
-
- set_frame_menubar (f, 0, 1);
- BLOCK_INPUT;
-
- menu_choice = MenuSelect (saved_menu_event_location);
- do_menu_choice (menu_choice);
-
- UNBLOCK_INPUT;
-}
-
-/* This callback is called from the menu bar pulldown menu
- when the user makes a selection.
- Figure out what the user chose
- and put the appropriate events into the keyboard buffer. */
-
-void
-menubar_selection_callback (FRAME_PTR f, int client_data)
-{
- Lisp_Object prefix, entry;
- Lisp_Object vector;
- Lisp_Object *subprefix_stack;
- int submenu_depth = 0;
- int i;
-
- if (!f)
- return;
- subprefix_stack = (Lisp_Object *) alloca (f->menu_bar_items_used * sizeof (Lisp_Object));
- vector = f->menu_bar_vector;
- prefix = Qnil;
- i = 0;
- while (i < f->menu_bar_items_used)
- {
- if (EQ (XVECTOR (vector)->contents[i], Qnil))
- {
- subprefix_stack[submenu_depth++] = prefix;
- prefix = entry;
- i++;
- }
- else if (EQ (XVECTOR (vector)->contents[i], Qlambda))
- {
- prefix = subprefix_stack[--submenu_depth];
- i++;
- }
- else if (EQ (XVECTOR (vector)->contents[i], Qt))
- {
- prefix = XVECTOR (vector)->contents[i + MENU_ITEMS_PANE_PREFIX];
- i += MENU_ITEMS_PANE_LENGTH;
- }
- else
- {
- entry = XVECTOR (vector)->contents[i + MENU_ITEMS_ITEM_VALUE];
- if (client_data == i)
- {
- int j;
- struct input_event buf;
- Lisp_Object frame;
-
- XSETFRAME (frame, f);
- buf.kind = MENU_BAR_EVENT;
- buf.frame_or_window = frame;
- buf.arg = frame;
- kbd_buffer_store_event (&buf);
-
- for (j = 0; j < submenu_depth; j++)
- if (!NILP (subprefix_stack[j]))
- {
- buf.kind = MENU_BAR_EVENT;
- buf.frame_or_window = frame;
- buf.arg = subprefix_stack[j];
- kbd_buffer_store_event (&buf);
- }
-
- if (!NILP (prefix))
- {
- buf.kind = MENU_BAR_EVENT;
- buf.frame_or_window = frame;
- buf.arg = prefix;
- kbd_buffer_store_event (&buf);
- }
-
- buf.kind = MENU_BAR_EVENT;
- buf.frame_or_window = frame;
- buf.arg = entry;
- kbd_buffer_store_event (&buf);
-
-#if 0
- /* Queue this to recompute possibly updated menubar. */
- buf.kind = menu_bar_activate_event;
- buf.frame_or_window = frame;
- buf.arg = Qnil;
- kbd_buffer_store_event (&buf);
-#endif
-
- return;
- }
- i += MENU_ITEMS_ITEM_LENGTH;
- }
- }
-}
-
-/* Allocate a widget_value, blocking input. */
-
-widget_value *
-xmalloc_widget_value ()
-{
- widget_value *value;
-
- BLOCK_INPUT;
- value = malloc_widget_value ();
- UNBLOCK_INPUT;
-
- return value;
-}
-
-/* This recursively calls free_widget_value on the tree of widgets.
- It must free all data that was malloc'ed for these widget_values.
- In Emacs, many slots are pointers into the data of Lisp_Strings, and
- must be left alone. */
-
-void
-free_menubar_widget_value_tree (wv)
- widget_value *wv;
-{
- if (! wv) return;
-
- wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
-
- if (wv->contents && (wv->contents != (widget_value*)1))
- {
- free_menubar_widget_value_tree (wv->contents);
- wv->contents = (widget_value *) 0xDEADBEEF;
- }
- if (wv->next)
- {
- free_menubar_widget_value_tree (wv->next);
- wv->next = (widget_value *) 0xDEADBEEF;
- }
- BLOCK_INPUT;
- free_widget_value (wv);
- UNBLOCK_INPUT;
-}
-\f
-/* Return a tree of widget_value structures for a menu bar item
- whose event type is ITEM_KEY (with string ITEM_NAME)
- and whose contents come from the list of keymaps MAPS. */
-
-static widget_value *
-single_submenu (item_key, item_name, maps)
- Lisp_Object item_key, item_name, maps;
-{
- widget_value *wv, *prev_wv, *save_wv, *first_wv;
- int i;
- int submenu_depth = 0;
- Lisp_Object length;
- int len;
- Lisp_Object *mapvec;
- widget_value **submenu_stack;
- int previous_items = menu_items_used;
- int top_level_items = 0;
-
- length = Flength (maps);
- len = XINT (length);
-
- /* Convert the list MAPS into a vector MAPVEC. */
- mapvec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
- for (i = 0; i < len; i++)
- {
- mapvec[i] = Fcar (maps);
- maps = Fcdr (maps);
- }
-
- menu_items_n_panes = 0;
-
- /* Loop over the given keymaps, making a pane for each map.
- But don't make a pane that is empty--ignore that map instead. */
- for (i = 0; i < len; i++)
- {
- if (SYMBOLP (mapvec[i])
- || (CONSP (mapvec[i])
- && NILP (Fkeymapp (mapvec[i]))))
- {
- /* Here we have a command at top level in the menu bar
- as opposed to a submenu. */
- top_level_items = 1;
- push_menu_pane (Qnil, Qnil);
- push_menu_item (item_name, Qt, item_key, mapvec[i],
- Qnil, Qnil, Qnil, Qnil);
- }
- else
- single_keymap_panes (mapvec[i], item_name, item_key, 0, 10);
- }
-
- /* Create a tree of widget_value objects
- representing the panes and their items. */
-
- submenu_stack
- = (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
- wv = xmalloc_widget_value ();
- wv->name = "menu";
- wv->value = 0;
- wv->enabled = 1;
- wv->button_type = BUTTON_TYPE_NONE;
- first_wv = wv;
- save_wv = 0;
- prev_wv = 0;
-
- /* Loop over all panes and items made during this call
- and construct a tree of widget_value objects.
- Ignore the panes and items made by previous calls to
- single_submenu, even though those are also in menu_items. */
- i = previous_items;
- while (i < menu_items_used)
- {
- if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
- {
- submenu_stack[submenu_depth++] = save_wv;
- save_wv = prev_wv;
- prev_wv = 0;
- i++;
- }
- else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
- {
- prev_wv = save_wv;
- save_wv = submenu_stack[--submenu_depth];
- i++;
- }
- else if (EQ (XVECTOR (menu_items)->contents[i], Qt)
- && submenu_depth != 0)
- i += MENU_ITEMS_PANE_LENGTH;
- /* Ignore a nil in the item list.
- It's meaningful only for dialog boxes. */
- else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
- i += 1;
- else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
- {
- /* Create a new pane. */
- Lisp_Object pane_name, prefix;
- char *pane_string;
- pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME];
- prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
-#ifndef HAVE_MULTILINGUAL_MENU
- if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
- pane_name = string_make_unibyte (pane_name);
-#endif
- pane_string = (NILP (pane_name)
- ? "" : (char *) XSTRING (pane_name)->data);
- /* If there is just one top-level pane, put all its items directly
- under the top-level menu. */
- if (menu_items_n_panes == 1)
- pane_string = "";
-
- /* If the pane has a meaningful name,
- make the pane a top-level menu item
- with its items as a submenu beneath it. */
- if (strcmp (pane_string, ""))
- {
- wv = xmalloc_widget_value ();
- if (save_wv)
- save_wv->next = wv;
- else
- first_wv->contents = wv;
- wv->name = pane_string;
- /* Ignore the @ that means "separate pane".
- This is a kludge, but this isn't worth more time. */
- if (!NILP (prefix) && wv->name[0] == '@')
- wv->name++;
- wv->value = 0;
- wv->enabled = 1;
- wv->button_type = BUTTON_TYPE_NONE;
- }
- save_wv = wv;
- prev_wv = 0;
- i += MENU_ITEMS_PANE_LENGTH;
- }
- else
- {
- /* Create a new item within current pane. */
- Lisp_Object item_name, enable, descrip, def, type, selected;
- Lisp_Object help;
-
- item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
- enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
- descrip
- = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
- def = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_DEFINITION];
- type = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_TYPE];
- selected = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_SELECTED];
- help = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_HELP];
-
-#ifndef HAVE_MULTILINGUAL_MENU
- if (STRING_MULTIBYTE (item_name))
- item_name = string_make_unibyte (item_name);
- if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
- descrip = string_make_unibyte (descrip);
-#endif
-
- wv = xmalloc_widget_value ();
- if (prev_wv)
- prev_wv->next = wv;
- else
- save_wv->contents = wv;
-
- wv->name = (char *) XSTRING (item_name)->data;
- if (!NILP (descrip))
- wv->key = (char *) XSTRING (descrip)->data;
- wv->value = 0;
- /* The EMACS_INT cast avoids a warning. There's no problem
- as long as pointers have enough bits to hold small integers. */
- wv->call_data = (!NILP (def) ? (void *) (EMACS_INT) i : 0);
- wv->enabled = !NILP (enable);
-
- if (NILP (type))
- wv->button_type = BUTTON_TYPE_NONE;
- else if (EQ (type, QCradio))
- wv->button_type = BUTTON_TYPE_RADIO;
- else if (EQ (type, QCtoggle))
- wv->button_type = BUTTON_TYPE_TOGGLE;
- else
- abort ();
-
- wv->selected = !NILP (selected);
- if (STRINGP (help))
- wv->help = (char *) XSTRING (help)->data;
- else
- wv->help = NULL;
-
- prev_wv = wv;
-
- i += MENU_ITEMS_ITEM_LENGTH;
- }
- }
-
- /* If we have just one "menu item"
- that was originally a button, return it by itself. */
- if (top_level_items && first_wv->contents && first_wv->contents->next == 0)
- {
- wv = first_wv->contents;
- free_widget_value (first_wv);
- return wv;
- }
-
- return first_wv;
-}
-\f
-/* Set the contents of the menubar widgets of frame F.
- The argument FIRST_TIME is currently ignored;
- it is set the first time this is called, from initialize_frame_menubar. */
-
-void
-set_frame_menubar (f, first_time, deep_p)
- FRAME_PTR f;
- int first_time;
- int deep_p;
-{
- int menubar_widget = f->output_data.mac->menubar_widget;
- Lisp_Object items;
- widget_value *wv, *first_wv, *prev_wv = 0;
- int i;
-
- XSETFRAME (Vmenu_updating_frame, f);
-
- wv = xmalloc_widget_value ();
- wv->name = "menubar";
- wv->value = 0;
- wv->enabled = 1;
- wv->button_type = BUTTON_TYPE_NONE;
- first_wv = wv;
-
- {
- /* Make a widget-value tree representing the entire menu trees. */
-
- struct buffer *prev = current_buffer;
- Lisp_Object buffer;
- int specpdl_count = specpdl_ptr - specpdl;
- int previous_menu_items_used = f->menu_bar_items_used;
- Lisp_Object *previous_items
- = (Lisp_Object *) alloca (previous_menu_items_used
- * sizeof (Lisp_Object));
-
- /* If we are making a new widget, its contents are empty,
- do always reinitialize them. */
- if (! menubar_widget)
- previous_menu_items_used = 0;
-
- buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer;
- specbind (Qinhibit_quit, Qt);
- /* Don't let the debugger step into this code
- because it is not reentrant. */
- specbind (Qdebug_on_next_call, Qnil);
-
- record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
- if (NILP (Voverriding_local_map_menu_flag))
- {
- specbind (Qoverriding_terminal_local_map, Qnil);
- specbind (Qoverriding_local_map, Qnil);
- }
-
- set_buffer_internal_1 (XBUFFER (buffer));
-
- /* Run the Lucid hook. */
- safe_run_hooks (Qactivate_menubar_hook);
- /* If it has changed current-menubar from previous value,
- really recompute the menubar from the value. */
- if (! NILP (Vlucid_menu_bar_dirty_flag))
- call0 (Qrecompute_lucid_menubar);
- safe_run_hooks (Qmenu_bar_update_hook);
- FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
-
- items = FRAME_MENU_BAR_ITEMS (f);
-
- inhibit_garbage_collection ();
-
- /* Save the frame's previous menu bar contents data. */
- bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items,
- previous_menu_items_used * sizeof (Lisp_Object));
-
- /* Fill in the current menu bar contents. */
- menu_items = f->menu_bar_vector;
- menu_items_allocated = XVECTOR (menu_items)->size;
- init_menu_items ();
- for (i = 0; i < XVECTOR (items)->size; i += 4)
- {
- Lisp_Object key, string, maps;
-
- key = XVECTOR (items)->contents[i];
- string = XVECTOR (items)->contents[i + 1];
- maps = XVECTOR (items)->contents[i + 2];
- if (NILP (string))
- break;
-
- wv = single_submenu (key, string, maps);
- if (prev_wv)
- prev_wv->next = wv;
- else
- first_wv->contents = wv;
- /* Don't set wv->name here; GC during the loop might relocate it. */
- wv->enabled = 1;
- wv->button_type = BUTTON_TYPE_NONE;
- prev_wv = wv;
- }
-
- finish_menu_items ();
-
- set_buffer_internal_1 (prev);
- unbind_to (specpdl_count, Qnil);
-
- /* If there has been no change in the Lisp-level contents
- of the menu bar, skip redisplaying it. Just exit. */
-
- for (i = 0; i < previous_menu_items_used; i++)
- if (menu_items_used == i
- || (!EQ (previous_items[i], XVECTOR (menu_items)->contents[i])))
- break;
- if (i == menu_items_used && i == previous_menu_items_used && i != 0)
- {
- free_menubar_widget_value_tree (first_wv);
- menu_items = Qnil;
-
- return;
- }
-
- /* Now GC cannot happen during the lifetime of the widget_value,
- so it's safe to store data from a Lisp_String. */
- wv = first_wv->contents;
- for (i = 0; i < XVECTOR (items)->size; i += 4)
- {
- Lisp_Object string;
- string = XVECTOR (items)->contents[i + 1];
- if (NILP (string))
- break;
- wv->name = (char *) XSTRING (string)->data;
- wv = wv->next;
- }
-
- f->menu_bar_vector = menu_items;
- f->menu_bar_items_used = menu_items_used;
- menu_items = Qnil;
- }
-
- /* Create or update the menu bar widget. */
-
- BLOCK_INPUT;
-
- f->output_data.mac->menubar_widget = NULL; /* always NULL on Mac */
-
- {
- int i = MIN_MENU_ID;
- MenuHandle menu = GetMenuHandle (i);
- while (menu != NULL)
- {
- DeleteMenu (i);
- DisposeMenu (menu);
- menu = GetMenuHandle (++i);
- }
-
- i = MIN_SUBMENU_ID;
- menu = GetMenuHandle (i);
- while (menu != NULL)
- {
- DeleteMenu (i);
- DisposeMenu (menu);
- menu = GetMenuHandle (++i);
- }
- }
-
- fill_menubar (first_wv->contents);
-
- DrawMenuBar ();
-
- free_menubar_widget_value_tree (first_wv);
-
- UNBLOCK_INPUT;
-}
-
-/* Called from Fx_create_frame to create the initial menubar of a
- frame before it is mapped, so that the window is mapped with the
- menubar already there instead of us tacking it on later and
- thrashing the window after it is visible. */
-
-void
-initialize_frame_menubar (f)
- FRAME_PTR f;
-{
- /* This function is called before the first chance to redisplay
- the frame. It has to be, so the frame will have the right size. */
- FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
- set_frame_menubar (f, 1, 1);
-}
-
-/* Get rid of the menu bar of frame F, and free its storage.
- This is used when deleting a frame, and when turning off the menu bar. */
-
-void
-free_frame_menubar (f)
- FRAME_PTR f;
-{
- /* Nothing to do since set_frame_menubar disposes of menus before
- installing new ones. */
-}
-
-\f
-/* mac_menu_show actually displays a menu using the panes and items in
- menu_items and returns the value selected from it; we assume input
- is blocked by the caller. */
-
-/* F is the frame the menu is for.
- X and Y are the frame-relative specified position,
- relative to the inside upper left corner of the frame F.
- FOR_CLICK is nonzero if this menu was invoked for a mouse click.
- KEYMAPS is 1 if this menu was specified with keymaps;
- in that case, we return a list containing the chosen item's value
- and perhaps also the pane's prefix.
- TITLE is the specified menu title.
- ERROR is a place to store an error message string in case of failure.
- (We return nil on failure, but the value doesn't actually matter.) */
-
-static Lisp_Object
-mac_menu_show (f, x, y, for_click, keymaps, title, error)
- FRAME_PTR f;
- int x;
- int y;
- int for_click;
- int keymaps;
- Lisp_Object title;
- char **error;
-{
- int i;
- int menu_item_selection;
- MenuHandle menu;
- Point pos;
- widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0;
- widget_value **submenu_stack
- = (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
- Lisp_Object *subprefix_stack
- = (Lisp_Object *) alloca (menu_items_used * sizeof (Lisp_Object));
- int submenu_depth = 0;
- int first_pane;
- int next_release_must_exit = 0;
-
- *error = NULL;
-
- if (menu_items_used <= MENU_ITEMS_PANE_LENGTH)
- {
- *error = "Empty menu";
- return Qnil;
- }
-
- /* Create a tree of widget_value objects
- representing the panes and their items. */
- wv = xmalloc_widget_value ();
- wv->name = "menu";
- wv->value = 0;
- wv->enabled = 1;
- wv->button_type = BUTTON_TYPE_NONE;
- first_wv = wv;
- first_pane = 1;
-
- /* Loop over all panes and items, filling in the tree. */
- i = 0;
- while (i < menu_items_used)
- {
- if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
- {
- submenu_stack[submenu_depth++] = save_wv;
- save_wv = prev_wv;
- prev_wv = 0;
- first_pane = 1;
- i++;
- }
- else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
- {
- prev_wv = save_wv;
- save_wv = submenu_stack[--submenu_depth];
- first_pane = 0;
- i++;
- }
- else if (EQ (XVECTOR (menu_items)->contents[i], Qt)
- && submenu_depth != 0)
- i += MENU_ITEMS_PANE_LENGTH;
- /* Ignore a nil in the item list.
- It's meaningful only for dialog boxes. */
- else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
- i += 1;
- else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
- {
- /* Create a new pane. */
- Lisp_Object pane_name, prefix;
- char *pane_string;
- pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME];
- prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
-#ifndef HAVE_MULTILINGUAL_MENU
- if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
- pane_name = string_make_unibyte (pane_name);
-#endif
- pane_string = (NILP (pane_name)
- ? "" : (char *) XSTRING (pane_name)->data);
- /* If there is just one top-level pane, put all its items directly
- under the top-level menu. */
- if (menu_items_n_panes == 1)
- pane_string = "";
-
- /* If the pane has a meaningful name,
- make the pane a top-level menu item
- with its items as a submenu beneath it. */
- if (!keymaps && strcmp (pane_string, ""))
- {
- wv = xmalloc_widget_value ();
- if (save_wv)
- save_wv->next = wv;
- else
- first_wv->contents = wv;
- wv->name = pane_string;
- if (keymaps && !NILP (prefix))
- wv->name++;
- wv->value = 0;
- wv->enabled = 1;
- wv->button_type = BUTTON_TYPE_NONE;
- save_wv = wv;
- prev_wv = 0;
- }
- else if (first_pane)
- {
- save_wv = wv;
- prev_wv = 0;
- }
- first_pane = 0;
- i += MENU_ITEMS_PANE_LENGTH;
- }
- else
- {
- /* Create a new item within current pane. */
- Lisp_Object item_name, enable, descrip, def, type, selected, help;
-
- item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
- enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
- descrip
- = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
- def = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_DEFINITION];
- type = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_TYPE];
- selected = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_SELECTED];
- help = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_HELP];
-
-#ifndef HAVE_MULTILINGUAL_MENU
- if (STRING_MULTIBYTE (item_name))
- item_name = string_make_unibyte (item_name);
- if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
- descrip = string_make_unibyte (descrip);
-#endif
-
- wv = xmalloc_widget_value ();
- if (prev_wv)
- prev_wv->next = wv;
- else
- save_wv->contents = wv;
- wv->name = (char *) XSTRING (item_name)->data;
- if (!NILP (descrip))
- wv->key = (char *) XSTRING (descrip)->data;
- wv->value = 0;
- /* Use the contents index as call_data, since we are
- restricted to 16-bits.. */
- wv->call_data = !NILP (def) ? (void *) (EMACS_INT) i : 0;
- wv->enabled = !NILP (enable);
-
- if (NILP (type))
- wv->button_type = BUTTON_TYPE_NONE;
- else if (EQ (type, QCtoggle))
- wv->button_type = BUTTON_TYPE_TOGGLE;
- else if (EQ (type, QCradio))
- wv->button_type = BUTTON_TYPE_RADIO;
- else
- abort ();
-
- wv->selected = !NILP (selected);
-
- if (STRINGP (help))
- wv->help = (char *) XSTRING (help)->data;
- else
- wv->help = NULL;
-
- prev_wv = wv;
-
- i += MENU_ITEMS_ITEM_LENGTH;
- }
- }
-
- /* Deal with the title, if it is non-nil. */
- if (!NILP (title))
- {
- widget_value *wv_title = xmalloc_widget_value ();
- widget_value *wv_sep = xmalloc_widget_value ();
-
- /* Maybe replace this separator with a bitmap or owner-draw item
- so that it looks better. Having two separators looks odd. */
- wv_sep->name = "--";
- wv_sep->next = first_wv->contents;
-
-#ifndef HAVE_MULTILINGUAL_MENU
- if (STRING_MULTIBYTE (title))
- title = string_make_unibyte (title);
-#endif
- wv_title->name = (char *) XSTRING (title)->data;
- wv_title->enabled = True;
- wv_title->button_type = BUTTON_TYPE_NONE;
- wv_title->next = wv_sep;
- first_wv->contents = wv_title;
- }
-
- /* Actually create the menu. */
- menu = NewMenu (POPUP_SUBMENU_ID, "\p");
- fill_submenu (menu, first_wv->contents, 0);
-
- /* Adjust coordinates to be root-window-relative. */
- pos.h = x;
- pos.v = y;
- SetPort (FRAME_MAC_WINDOW (f));
- LocalToGlobal (&pos);
-
- InsertMenu (menu, -1);
-
- /* Display the menu. */
- menu_item_selection = LoWord (PopUpMenuSelect (menu, pos.v, pos.h, 0));
-
- GetMenuItemRefCon (menu, menu_item_selection, &menu_item_selection);
-
- DeleteMenu (POPUP_SUBMENU_ID);
-
-#if 0
- /* Clean up extraneous mouse events which might have been generated
- during the call. */
- discard_mouse_events ();
-#endif
-
- /* Free the widget_value objects we used to specify the
- contents. */
- free_menubar_widget_value_tree (first_wv);
-
- DisposeMenu (menu);
-
- /* Find the selected item, and its pane, to return the proper
- value. */
- if (menu_item_selection != 0)
- {
- Lisp_Object prefix, entry;
-
- prefix = Qnil;
- i = 0;
- while (i < menu_items_used)
- {
- if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
- {
- subprefix_stack[submenu_depth++] = prefix;
- prefix = entry;
- i++;
- }
- else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
- {
- prefix = subprefix_stack[--submenu_depth];
- i++;
- }
- else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
- {
- prefix
- = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
- i += MENU_ITEMS_PANE_LENGTH;
- }
- /* Ignore a nil in the item list. It's meaningful only for
- dialog boxes. */
- else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
- i += 1;
- else
- {
- entry
- = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
- if (menu_item_selection == i)
- {
- if (keymaps != 0)
- {
- int j;
-
- entry = Fcons (entry, Qnil);
- if (!NILP (prefix))
- entry = Fcons (prefix, entry);
- for (j = submenu_depth - 1; j >= 0; j--)
- if (!NILP (subprefix_stack[j]))
- entry = Fcons (subprefix_stack[j], entry);
- }
- return entry;
- }
- i += MENU_ITEMS_ITEM_LENGTH;
- }
- }
- }
-
- return Qnil;
-}
-\f
-
-/* Construct native Mac OS menubar based on widget_value tree. */
-
-static int
-mac_dialog (widget_value *wv)
-{
- char *dialog_name;
- char *prompt;
- char **button_labels;
- UInt32 *ref_cons;
- int nb_buttons;
- int left_count;
- int i;
- int dialog_width;
- Rect rect;
- WindowPtr window_ptr;
- ControlHandle ch;
- int left;
- EventRecord event_record;
- SInt16 part_code;
- int control_part_code;
- Point mouse;
-
- dialog_name = wv->name;
- nb_buttons = dialog_name[1] - '0';
- left_count = nb_buttons - (dialog_name[4] - '0');
- button_labels = (char **) alloca (sizeof (char *) * nb_buttons);
- ref_cons = (int *) alloca (sizeof (UInt32) * nb_buttons);
-
- wv = wv->contents;
- prompt = (char *) alloca (strlen (wv->value) + 1);
- strcpy (prompt, wv->value);
- c2pstr (prompt);
-
- wv = wv->next;
- for (i = 0; i < nb_buttons; i++)
- {
- button_labels[i] = wv->value;
- button_labels[i] = (char *) alloca (strlen (wv->value) + 1);
- strcpy (button_labels[i], wv->value);
- c2pstr (button_labels[i]);
- ref_cons[i] = (UInt32) wv->call_data;
- wv = wv->next;
- }
-
- window_ptr = GetNewCWindow (DIALOG_WINDOW_RESOURCE, NULL, (WindowPtr) -1);
- SetPort (window_ptr);
-
- TextFont (0);
- /* Left and right margins in the dialog are 13 pixels each.*/
- dialog_width = 14;
- /* Calculate width of dialog box: 8 pixels on each side of the text
- label in each button, 12 pixels between buttons. */
- for (i = 0; i < nb_buttons; i++)
- dialog_width += StringWidth (button_labels[i]) + 16 + 12;
-
- if (left_count != 0 && nb_buttons - left_count != 0)
- dialog_width += 12;
-
- dialog_width = max (dialog_width, StringWidth (prompt) + 26);
-
- SizeWindow (window_ptr, dialog_width, 78, 0);
- ShowWindow (window_ptr);
-
- SetPort (window_ptr);
- TextFont (0);
-
- MoveTo (13, 29);
- DrawString (prompt);
-
- left = 13;
- for (i = 0; i < nb_buttons; i++)
- {
- int button_width = StringWidth (button_labels[i]) + 16;
- SetRect (&rect, left, 45, left + button_width, 65);
- ch = NewControl (window_ptr, &rect, button_labels[i], 1, 0, 0, 0,
- kControlPushButtonProc, ref_cons[i]);
- left += button_width + 12;
- if (i == left_count - 1)
- left += 12;
- }
-
- i = 0;
- while (!i)
- {
- if (WaitNextEvent (mDownMask, &event_record, 10, NULL))
- if (event_record.what == mouseDown)
- {
- part_code = FindWindow (event_record.where, &window_ptr);
- if (part_code == inContent)
- {
- mouse = event_record.where;
- GlobalToLocal (&mouse);
- control_part_code = FindControl (mouse, window_ptr, &ch);
- if (control_part_code == kControlButtonPart)
- if (TrackControl (ch, mouse, NULL))
- i = GetControlReference (ch);
- }
- }
- }
-
- DisposeWindow (window_ptr);
-
- return i;
-}
-
-static char * button_names [] = {
- "button1", "button2", "button3", "button4", "button5",
- "button6", "button7", "button8", "button9", "button10" };
-
-static Lisp_Object
-mac_dialog_show (f, keymaps, title, error)
- FRAME_PTR f;
- int keymaps;
- Lisp_Object title;
- char **error;
-{
- int i, nb_buttons=0;
- char dialog_name[6];
- int menu_item_selection;
-
- widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0;
-
- /* Number of elements seen so far, before boundary. */
- int left_count = 0;
- /* 1 means we've seen the boundary between left-hand elts and
- right-hand. */
- int boundary_seen = 0;
-
- *error = NULL;
-
- if (menu_items_n_panes > 1)
- {
- *error = "Multiple panes in dialog box";
- return Qnil;
- }
-
- /* Create a tree of widget_value objects representing the text label
- and buttons. */
- {
- Lisp_Object pane_name, prefix;
- char *pane_string;
- pane_name = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME];
- prefix = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_PREFIX];
- pane_string = (NILP (pane_name)
- ? "" : (char *) XSTRING (pane_name)->data);
- prev_wv = xmalloc_widget_value ();
- prev_wv->value = pane_string;
- if (keymaps && !NILP (prefix))
- prev_wv->name++;
- prev_wv->enabled = 1;
- prev_wv->name = "message";
- first_wv = prev_wv;
-
- /* Loop over all panes and items, filling in the tree. */
- i = MENU_ITEMS_PANE_LENGTH;
- while (i < menu_items_used)
- {
-
- /* Create a new item within current pane. */
- Lisp_Object item_name, enable, descrip, help;
-
- item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
- enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
- descrip
- = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
- help = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_HELP];
-
- if (NILP (item_name))
- {
- free_menubar_widget_value_tree (first_wv);
- *error = "Submenu in dialog items";
- return Qnil;
- }
- if (EQ (item_name, Qquote))
- {
- /* This is the boundary between left-side elts and
- right-side elts. Stop incrementing right_count. */
- boundary_seen = 1;
- i++;
- continue;
- }
- if (nb_buttons >= 9)
- {
- free_menubar_widget_value_tree (first_wv);
- *error = "Too many dialog items";
- return Qnil;
- }
-
- wv = xmalloc_widget_value ();
- prev_wv->next = wv;
- wv->name = (char *) button_names[nb_buttons];
- if (!NILP (descrip))
- wv->key = (char *) XSTRING (descrip)->data;
- wv->value = (char *) XSTRING (item_name)->data;
- wv->call_data = (void *) i;
- /* menu item is identified by its index in menu_items table */
- wv->enabled = !NILP (enable);
- prev_wv = wv;
-
- if (! boundary_seen)
- left_count++;
-
- nb_buttons++;
- i += MENU_ITEMS_ITEM_LENGTH;
- }
-
- /* If the boundary was not specified, by default put half on the
- left and half on the right. */
- if (! boundary_seen)
- left_count = nb_buttons - nb_buttons / 2;
-
- wv = xmalloc_widget_value ();
- wv->name = dialog_name;
-
- /* Dialog boxes use a really stupid name encoding which specifies
- how many buttons to use and how many buttons are on the right.
- The Q means something also. */
- dialog_name[0] = 'Q';
- dialog_name[1] = '0' + nb_buttons;
- dialog_name[2] = 'B';
- dialog_name[3] = 'R';
- /* Number of buttons to put on the right. */
- dialog_name[4] = '0' + nb_buttons - left_count;
- dialog_name[5] = 0;
- wv->contents = first_wv;
- first_wv = wv;
- }
-
- /* Actually create the dialog. */
-#ifdef HAVE_DIALOGS
- menu_item_selection = mac_dialog (first_wv);
-#else
- menu_item_selection = 0;
-#endif
-
- /* Free the widget_value objects we used to specify the
- contents. */
- free_menubar_widget_value_tree (first_wv);
-
- /* Find the selected item, and its pane, to return the proper
- value. */
- if (menu_item_selection != 0)
- {
- Lisp_Object prefix;
-
- prefix = Qnil;
- i = 0;
- while (i < menu_items_used)
- {
- Lisp_Object entry;
-
- if (EQ (XVECTOR (menu_items)->contents[i], Qt))
- {
- prefix
- = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
- i += MENU_ITEMS_PANE_LENGTH;
- }
- else
- {
- entry
- = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
- if (menu_item_selection == i)
- {
- if (keymaps != 0)
- {
- entry = Fcons (entry, Qnil);
- if (!NILP (prefix))
- entry = Fcons (prefix, entry);
- }
- return entry;
- }
- i += MENU_ITEMS_ITEM_LENGTH;
- }
- }
- }
-
- return Qnil;
-}
-\f
-
-/* Is this item a separator? */
-static int
-name_is_separator (name)
- char *name;
-{
- /* Check if name string consists of only dashes ('-') */
- while (*name == '-') name++;
- return (*name == '\0');
-}
-
-static void
-add_menu_item (MenuHandle menu, widget_value *wv, int submenu, int indent,
- int force_disable)
-{
- Str255 item_name;
- int pos, i;
-
- if (name_is_separator (wv->name))
- AppendMenu (menu, "\p-");
- else
- {
- AppendMenu (menu, "\pX");
-
- pos = CountMItems (menu);
-
- strcpy (item_name, "");
- for (i = 0; i < indent; i++)
- strcat (item_name, " ");
- strcat (item_name, wv->name);
- if (wv->key != NULL)
- {
- strcat (item_name, " ");
- strcat (item_name, wv->key);
- }
- c2pstr (item_name);
- SetMenuItemText (menu, pos, item_name);
-
- if (wv->enabled && !force_disable)
- EnableItem (menu, pos);
- else
- DisableItem (menu, pos);
-
- /* Draw radio buttons and tickboxes. */
- {
- if (wv->selected && (wv->button_type == BUTTON_TYPE_TOGGLE ||
- wv->button_type == BUTTON_TYPE_RADIO))
- SetItemMark (menu, pos, checkMark);
- else
- SetItemMark (menu, pos, noMark);
- }
- }
-
- SetMenuItemRefCon (menu, pos, (UInt32) wv->call_data);
-
- if (submenu != NULL)
- SetMenuItemHierarchicalID (menu, pos, submenu);
-}
-
-static int submenu_id;
-
-/* Construct native Mac OS menubar based on widget_value tree. */
-
-static void
-fill_submenu (MenuHandle menu, widget_value *wv, int indent)
-{
- for ( ; wv != NULL; wv = wv->next)
- if (wv->contents)
- {
- add_menu_item (menu, wv, NULL, indent, 1);
-
- fill_submenu (menu, wv->contents, indent + 1);
- }
- else
- add_menu_item (menu, wv, NULL, indent, 0);
-}
-
-
-/* Construct native Mac OS menu based on widget_value tree. */
-
-static void
-fill_menu (MenuHandle menu, widget_value *wv)
-{
- for ( ; wv != NULL; wv = wv->next)
- if (wv->contents)
- {
- MenuHandle submenu = NewMenu (submenu_id, "\pX");
- fill_submenu (submenu, wv->contents, 0);
- InsertMenu (submenu, -1);
- add_menu_item (menu, wv, submenu_id, 0, 0);
- submenu_id++;
- }
- else
- add_menu_item (menu, wv, NULL, 0, 0);
-}
-
-/* Construct native Mac OS menubar based on widget_value tree. */
-
-static void
-fill_menubar (widget_value *wv)
-{
- int id;
-
- submenu_id = MIN_SUBMENU_ID;
-
- for (id = MIN_MENU_ID; wv != NULL; wv = wv->next, id++)
- {
- MenuHandle menu;
- Str255 title;
-
- strcpy (title, wv->name);
- c2pstr (title);
- menu = NewMenu (id, title);
-
- if (wv->contents)
- fill_menu (menu, wv->contents);
-
- InsertMenu (menu, 0);
- }
-}
-
-#endif /* HAVE_MENUS */
-\f
-void
-syms_of_macmenu ()
-{
- staticpro (&menu_items);
- menu_items = Qnil;
-
- Qdebug_on_next_call = intern ("debug-on-next-call");
- staticpro (&Qdebug_on_next_call);
-
- DEFVAR_LISP ("menu-updating-frame", &Vmenu_updating_frame,
- "Frame for which we are updating a menu.\n\
-The enable predicate for a menu command should check this variable.");
- Vmenu_updating_frame = Qnil;
-
- defsubr (&Sx_popup_menu);
-#ifdef HAVE_MENUS
- defsubr (&Sx_popup_dialog);
-#endif
-}
+++ /dev/null
-/* Implementation of GUI terminal on the Mac OS.
- Copyright (C) 2000 Free Software Foundation, Inc.
-
-This file is part of GNU Emacs.
-
-GNU Emacs is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* Contributed by Andrew Choi (akochoi@users.sourceforge.net). */
-
-#include <config.h>
-
-/* On 4.3 these lose if they come after xterm.h. */
-/* Putting these at the beginning seems to be standard for other .c files. */
-#include <signal.h>
-
-#include <stdio.h>
-
-#include "lisp.h"
-#include "blockinput.h"
-
-/* Need syssignal.h for various externs and definitions that may be required
- by some configurations for calls to signal later in this source file. */
-#include "syssignal.h"
-
-/* This may include sys/types.h, and that somehow loses
- if this is not done before the other system files. */
-#include "macterm.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <alloca.h>
-
-#include <Quickdraw.h>
-#include <ToolUtils.h>
-#include <Sound.h>
-#include <Events.h>
-#include <Script.h>
-#include <Resources.h>
-#include <Fonts.h>
-#include <TextUtils.h>
-#include <LowMem.h>
-#include <Controls.h>
-#if defined (__MRC__) || defined (CODEWARRIOR_VERSION_6)
-#include <ControlDefinitions.h>
-#endif
-
-#if __profile__
-#include <profiler.h>
-#endif
-
-#include <sys/types.h>
-
-#include "systty.h"
-#include "systime.h"
-
-#ifndef INCLUDED_FCNTL
-#include <fcntl.h>
-#endif
-#include <ctype.h>
-#include <errno.h>
-#include <setjmp.h>
-#include <sys/stat.h>
-
-#include "charset.h"
-#include "ccl.h"
-#include "frame.h"
-#include "dispextern.h"
-#include "fontset.h"
-#include "termhooks.h"
-#include "termopts.h"
-#include "termchar.h"
-#include "gnu.h"
-#include "disptab.h"
-#include "buffer.h"
-#include "window.h"
-#include "keyboard.h"
-#include "intervals.h"
-#include "process.h"
-#include "atimer.h"
-#include "keymap.h"
-#include "coding.h"
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifndef USE_X_TOOLKIT
-#define x_any_window_to_frame x_window_to_frame
-#define x_top_window_to_frame x_window_to_frame
-#endif
-
-#ifndef min
-#define min(a,b) ((a) < (b) ? (a) : (b))
-#endif
-#ifndef max
-#define max(a,b) ((a) > (b) ? (a) : (b))
-#endif
-
-#define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
-
-\f
-/* Fringe bitmaps. */
-
-enum fringe_bitmap_type
-{
- NO_FRINGE_BITMAP,
- LEFT_TRUNCATION_BITMAP,
- RIGHT_TRUNCATION_BITMAP,
- OVERLAY_ARROW_BITMAP,
- CONTINUED_LINE_BITMAP,
- CONTINUATION_LINE_BITMAP,
- ZV_LINE_BITMAP
-};
-
-/* Bitmap drawn to indicate lines not displaying text if
- `indicate-empty-lines' is non-nil. */
-
-#define zv_width 8
-#define zv_height 72
-#define zv_period 3
-static unsigned char zv_bits[] = {
- 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
- 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
- 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
- 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
- 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
- 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
- 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
- 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
-
-/* An arrow like this: `<-'. */
-
-#define left_width 8
-#define left_height 8
-static unsigned char left_bits[] = {
- 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
-
-/* Right truncation arrow bitmap `->'. */
-
-#define right_width 8
-#define right_height 8
-static unsigned char right_bits[] = {
- 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
-
-/* Marker for continued lines. */
-
-#define continued_width 8
-#define continued_height 8
-static unsigned char continued_bits[] = {
- 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
-
-/* Marker for continuation lines. */
-
-#define continuation_width 8
-#define continuation_height 8
-static unsigned char continuation_bits[] = {
- 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
-
-/* Overlay arrow bitmap. */
-
-#if 0
-/* A bomb. */
-#define ov_width 8
-#define ov_height 8
-static unsigned char ov_bits[] = {
- 0x0c, 0x10, 0x3c, 0x7e, 0x5e, 0x5e, 0x46, 0x3c};
-#else
-/* A triangular arrow. */
-#define ov_width 8
-#define ov_height 8
-static unsigned char ov_bits[] = {
- 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
-#endif
-
-extern Lisp_Object Qhelp_echo;
-
-\f
-/* Non-zero means Emacs uses toolkit scroll bars. */
-
-int x_toolkit_scroll_bars_p;
-
-/* If a string, XTread_socket generates an event to display that string.
- (The display is done in read_char.) */
-
-static Lisp_Object help_echo;
-static Lisp_Object help_echo_window;
-static Lisp_Object help_echo_object;
-static int help_echo_pos;
-
-/* Temporary variable for XTread_socket. */
-
-static Lisp_Object previous_help_echo;
-
-/* Non-zero means that a HELP_EVENT has been generated since Emacs
- start. */
-
-static int any_help_event_p;
-
-/* Non-zero means draw block and hollow cursor as wide as the glyph
- under it. For example, if a block cursor is over a tab, it will be
- drawn as wide as that tab on the display. */
-
-int x_stretch_cursor_p;
-
-/* This is a chain of structures for all the X displays currently in
- use. */
-
-struct x_display_info *x_display_list;
-
-/* This is a list of cons cells, each of the form (NAME
- . FONT-LIST-CACHE), one for each element of x_display_list and in
- the same order. NAME is the name of the frame. FONT-LIST-CACHE
- records previous values returned by x-list-fonts. */
-
-Lisp_Object x_display_name_list;
-
-/* This is display since Mac does not support multiple ones. */
-struct mac_display_info one_mac_display_info;
-
-/* Frame being updated by update_frame. This is declared in term.c.
- This is set by update_begin and looked at by all the XT functions.
- It is zero while not inside an update. In that case, the XT
- functions assume that `selected_frame' is the frame to apply to. */
-
-extern struct frame *updating_frame;
-
-/* This is a frame waiting to be auto-raised, within XTread_socket. */
-
-struct frame *pending_autoraise_frame;
-
-/* Nominal cursor position -- where to draw output.
- HPOS and VPOS are window relative glyph matrix coordinates.
- X and Y are window relative pixel coordinates. */
-
-struct cursor_pos output_cursor;
-
-/* Non-zero means user is interacting with a toolkit scroll bar. */
-
-static int toolkit_scroll_bar_interaction;
-
-/* Mouse movement.
-
- Formerly, we used PointerMotionHintMask (in standard_event_mask)
- so that we would have to call XQueryPointer after each MotionNotify
- event to ask for another such event. However, this made mouse tracking
- slow, and there was a bug that made it eventually stop.
-
- Simply asking for MotionNotify all the time seems to work better.
-
- In order to avoid asking for motion events and then throwing most
- of them away or busy-polling the server for mouse positions, we ask
- the server for pointer motion hints. This means that we get only
- one event per group of mouse movements. "Groups" are delimited by
- other kinds of events (focus changes and button clicks, for
- example), or by XQueryPointer calls; when one of these happens, we
- get another MotionNotify event the next time the mouse moves. This
- is at least as efficient as getting motion events when mouse
- tracking is on, and I suspect only negligibly worse when tracking
- is off. */
-
-/* Where the mouse was last time we reported a mouse event. */
-
-FRAME_PTR last_mouse_frame;
-static Rect last_mouse_glyph;
-static Lisp_Object last_mouse_press_frame;
-
-/* The scroll bar in which the last X motion event occurred.
-
- If the last X motion event occurred in a scroll bar, we set this so
- XTmouse_position can know whether to report a scroll bar motion or
- an ordinary motion.
-
- If the last X motion event didn't occur in a scroll bar, we set
- this to Qnil, to tell XTmouse_position to return an ordinary motion
- event. */
-
-static Lisp_Object last_mouse_scroll_bar;
-
-/* This is a hack. We would really prefer that XTmouse_position would
- return the time associated with the position it returns, but there
- doesn't seem to be any way to wrest the time-stamp from the server
- along with the position query. So, we just keep track of the time
- of the last movement we received, and return that in hopes that
- it's somewhat accurate. */
-
-static Time last_mouse_movement_time;
-
-enum mouse_tracking_type {
- mouse_tracking_none,
- mouse_tracking_mouse_movement,
- mouse_tracking_scroll_bar
-};
-
-enum mouse_tracking_type mouse_tracking_in_progress = mouse_tracking_none;
-
-struct scroll_bar *tracked_scroll_bar = NULL;
-
-/* Incremented by XTread_socket whenever it really tries to read
- events. */
-
-#ifdef __STDC__
-static int volatile input_signal_count;
-#else
-static int input_signal_count;
-#endif
-
-/* Used locally within XTread_socket. */
-
-static int x_noop_count;
-
-/* Initial values of argv and argc. */
-
-extern char **initial_argv;
-extern int initial_argc;
-
-extern Lisp_Object Vcommand_line_args, Vsystem_name;
-
-/* Tells if a window manager is present or not. */
-
-extern Lisp_Object Vx_no_window_manager;
-
-extern Lisp_Object Qface, Qmouse_face;
-
-extern int errno;
-
-/* A mask of extra modifier bits to put into every keyboard char. */
-
-extern int extra_keyboard_modifiers;
-
-static Lisp_Object Qvendor_specific_keysyms;
-
-#if 0
-extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
-#endif
-
-extern Lisp_Object x_icon_type P_ ((struct frame *));
-
-
-#if __MRC__
-QDGlobals qd; /* QuickDraw global information structure. */
-#endif
-
-
-/* Enumeration for overriding/changing the face to use for drawing
- glyphs in x_draw_glyphs. */
-
-enum draw_glyphs_face
-{
- DRAW_NORMAL_TEXT,
- DRAW_INVERSE_VIDEO,
- DRAW_CURSOR,
- DRAW_MOUSE_FACE,
- DRAW_IMAGE_RAISED,
- DRAW_IMAGE_SUNKEN
-};
-
-struct frame * x_window_to_frame (struct mac_display_info *, WindowPtr);
-struct mac_display_info *mac_display_info_for_display (Display *);
-static void x_update_window_end P_ ((struct window *, int, int));
-static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
-void x_delete_display P_ ((struct x_display_info *));
-static unsigned int x_mac_to_emacs_modifiers P_ ((struct x_display_info *,
- unsigned short));
-static int fast_find_position P_ ((struct window *, int, int *, int *,
- int *, int *));
-static void set_output_cursor P_ ((struct cursor_pos *));
-static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
- int *, int *, int *));
-static void note_mode_line_highlight P_ ((struct window *, int, int));
-static void note_mouse_highlight P_ ((struct frame *, int, int));
-static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
-static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
-static void show_mouse_face P_ ((struct x_display_info *,
- enum draw_glyphs_face));
-void clear_mouse_face P_ ((struct mac_display_info *));
-static int x_io_error_quitter P_ ((Display *));
-int x_catch_errors P_ ((Display *));
-void x_uncatch_errors P_ ((Display *, int));
-void x_lower_frame P_ ((struct frame *));
-void x_scroll_bar_clear P_ ((struct frame *));
-int x_had_errors_p P_ ((Display *));
-void x_wm_set_size_hint P_ ((struct frame *, long, int));
-void x_raise_frame P_ ((struct frame *));
-void x_set_window_size P_ ((struct frame *, int, int, int));
-void x_wm_set_window_state P_ ((struct frame *, int));
-void x_wm_set_icon_pixmap P_ ((struct frame *, int));
-void x_initialize P_ ((void));
-static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
-static int x_compute_min_glyph_bounds P_ ((struct frame *));
-enum text_cursor_kinds x_specified_cursor_type P_ ((Lisp_Object, int *));
-static void x_draw_phys_cursor_glyph P_ ((struct window *,
- struct glyph_row *,
- enum draw_glyphs_face));
-static void x_update_end P_ ((struct frame *));
-static void XTframe_up_to_date P_ ((struct frame *));
-static void XTreassert_line_highlight P_ ((int, int));
-static void x_change_line_highlight P_ ((int, int, int, int));
-static void XTset_terminal_modes P_ ((void));
-static void XTreset_terminal_modes P_ ((void));
-static void XTcursor_to P_ ((int, int, int, int));
-static void x_write_glyphs P_ ((struct glyph *, int));
-static void x_clear_end_of_line P_ ((int));
-static void x_clear_frame P_ ((void));
-static void x_clear_cursor P_ ((struct window *));
-static void frame_highlight P_ ((struct frame *));
-static void frame_unhighlight P_ ((struct frame *));
-static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
-static void XTframe_rehighlight P_ ((struct frame *));
-static void x_frame_rehighlight P_ ((struct x_display_info *));
-static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
-static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
-static int x_intersect_rectangles P_ ((Rect *, Rect *, Rect *));
-static void expose_frame P_ ((struct frame *, int, int, int, int));
-static void expose_window_tree P_ ((struct window *, Rect *));
-static void expose_window P_ ((struct window *, Rect *));
-static void expose_area P_ ((struct window *, struct glyph_row *,
- XRectangle *, enum glyph_row_area));
-static void expose_line P_ ((struct window *, struct glyph_row *,
- XRectangle *));
-void x_display_cursor (struct window *, int, int, int, int, int);
-void x_update_cursor P_ ((struct frame *, int));
-static void x_update_cursor_in_window_tree P_ ((struct window *, int));
-static void x_update_window_cursor P_ ((struct window *, int));
-static void x_erase_phys_cursor P_ ((struct window *));
-void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
-static void x_draw_fringe_bitmap P_ ((struct window *, struct glyph_row *,
- enum fringe_bitmap_type, int left_p));
-static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
- GC, int));
-static int x_phys_cursor_in_rect_p P_ ((struct window *, Rect *));
-static void x_draw_row_fringe_bitmaps P_ ((struct window *, struct glyph_row *));
-static void note_overwritten_text_cursor P_ ((struct window *, int, int));
-static void x_flush P_ ((struct frame *f));
-static void x_update_begin P_ ((struct frame *));
-static void x_update_window_begin P_ ((struct window *));
-static void x_draw_vertical_border P_ ((struct window *));
-static void x_after_update_window_line P_ ((struct glyph_row *));
-static INLINE void take_vertical_position_into_account P_ ((struct it *));
-static void x_produce_stretch_glyph P_ ((struct it *));
-
-static void activate_scroll_bars (FRAME_PTR);
-static void deactivate_scroll_bars (FRAME_PTR);
-
-extern int image_ascent (struct image *, struct face *);
-void x_set_offset (struct frame *, int, int, int);
-int x_bitmap_icon (struct frame *, Lisp_Object);
-void x_make_frame_visible (struct frame *);
-
-extern void window_scroll (Lisp_Object, int, int, int);
-
-/* Defined in macmenu.h. */
-extern void menubar_selection_callback (FRAME_PTR, int);
-extern void set_frame_menubar (FRAME_PTR, int, int);
-
-/* X display function emulation */
-
-/* Structure borrowed from Xlib.h to represent two-byte characters in
- dumpglyphs. */
-
-typedef struct {
- unsigned char byte1;
- unsigned char byte2;
-} XChar2b;
-
-static void
-XFreePixmap (display, pixmap)
- Display *display;
- Pixmap pixmap;
-{
- PixMap *p = (PixMap *) pixmap;
-
- xfree (p->baseAddr);
- xfree (p);
-}
-
-
-/* Set foreground color for subsequent QuickDraw commands. Assume
- graphic port has already been set. */
-
-static void
-mac_set_forecolor (unsigned long color)
-{
- RGBColor fg_color;
-
- fg_color.red = RED_FROM_ULONG (color) * 256;
- fg_color.green = GREEN_FROM_ULONG (color) * 256;
- fg_color.blue = BLUE_FROM_ULONG (color) * 256;
-
- RGBForeColor (&fg_color);
-}
-
-
-/* Set background color for subsequent QuickDraw commands. Assume
- graphic port has already been set. */
-
-static void
-mac_set_backcolor (unsigned long color)
-{
- RGBColor bg_color;
-
- bg_color.red = RED_FROM_ULONG (color) * 256;
- bg_color.green = GREEN_FROM_ULONG (color) * 256;
- bg_color.blue = BLUE_FROM_ULONG (color) * 256;
-
- RGBBackColor (&bg_color);
-}
-
-/* Set foreground and background color for subsequent QuickDraw
- commands. Assume that the graphic port has already been set. */
-
-static void
-mac_set_colors (GC gc)
-{
- mac_set_forecolor (gc->foreground);
- mac_set_backcolor (gc->background);
-}
-
-/* Mac version of XDrawLine. */
-
-static void
-XDrawLine (display, w, gc, x1, y1, x2, y2)
- Display *display;
- WindowPtr w;
- GC gc;
- int x1, y1, x2, y2;
-{
- SetPort (w);
- mac_set_colors (gc);
-
- MoveTo (x1, y1);
- LineTo (x2, y2);
-}
-
-/* Mac version of XClearArea. */
-
-void
-XClearArea (display, w, x, y, width, height, exposures)
- Display *display;
- WindowPtr w;
- int x, y;
- unsigned int width, height;
- int exposures;
-{
- struct mac_output *mwp = (mac_output *) GetWRefCon (w);
- Rect r;
- XGCValues xgc;
-
- xgc.foreground = mwp->foreground_pixel;
- xgc.background = mwp->background_pixel;
-
- SetPort (w);
- mac_set_colors (&xgc);
- SetRect (&r, x, y, x + width, y + height);
-
- EraseRect (&r);
-}
-
-/* Mac version of XClearWindow. */
-
-static void
-XClearWindow (display, w)
- Display *display;
- WindowPtr w;
-{
- struct mac_output *mwp = (mac_output *) GetWRefCon (w);
- XGCValues xgc;
-
- xgc.foreground = mwp->foreground_pixel;
- xgc.background = mwp->background_pixel;
-
- SetPort (w);
- mac_set_colors (&xgc);
-
- EraseRect (&(w->portRect));
-}
-
-
-/* Mac replacement for XCopyArea. */
-
-static void
-mac_draw_bitmap (display, w, gc, x, y, bitmap)
- Display *display;
- WindowPtr w;
- GC gc;
- int x, y;
- BitMap *bitmap;
-{
- Rect r;
-
- SetPort (w);
- mac_set_colors (gc);
- SetRect (&r, x, y, x + bitmap->bounds.right, y + bitmap->bounds.bottom);
-
- CopyBits (bitmap, &(w->portBits), &(bitmap->bounds), &r, srcCopy, 0);
-}
-
-
-/* Mac replacement for XSetClipRectangles. */
-
-static void
-mac_set_clip_rectangle (display, w, r)
- Display *display;
- WindowPtr w;
- Rect *r;
-{
- SetPort (w);
-
- ClipRect (r);
-}
-
-
-/* Mac replacement for XSetClipMask. */
-
-static void
-mac_reset_clipping (display, w)
- Display *display;
- WindowPtr w;
-{
- Rect r;
-
- SetPort (w);
-
- SetRect (&r, -32767, -32767, 32767, 32767);
- ClipRect (&r);
-}
-
-
-/* Mac replacement for XCreateBitmapFromBitmapData. */
-
-static void
-mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
- BitMap *bitmap;
- char *bits;
- int w, h;
-{
- int bytes_per_row, i, j;
-
- bitmap->rowBytes = (w + 15) / 16 * 2; /* must be on word boundary */
- bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
- if (!bitmap->baseAddr)
- abort ();
-
- bzero (bitmap->baseAddr, bitmap->rowBytes * h);
- for (i = 0; i < h; i++)
- for (j = 0; j < w; j++)
- if (BitTst (bits, i * w + j))
- BitSet (bitmap->baseAddr, i * bitmap->rowBytes * 8 + j);
-
- SetRect (&(bitmap->bounds), 0, 0, w, h);
-}
-
-
-static void
-mac_free_bitmap (bitmap)
- BitMap *bitmap;
-{
- xfree (bitmap->baseAddr);
-}
-
-/* Mac replacement for XFillRectangle. */
-
-static void
-XFillRectangle (display, w, gc, x, y, width, height)
- Display *display;
- WindowPtr w;
- GC gc;
- int x, y;
- unsigned int width, height;
-{
- Rect r;
-
- SetPort (w);
- mac_set_colors (gc);
- SetRect (&r, x, y, x + width, y + height);
-
- PaintRect (&r); /* using foreground color of gc */
-}
-
-
-/* Mac replacement for XDrawRectangle: dest is a window. */
-
-static void
-mac_draw_rectangle (display, w, gc, x, y, width, height)
- Display *display;
- WindowPtr w;
- GC gc;
- int x, y;
- unsigned int width, height;
-{
- Rect r;
-
- SetPort (w);
- mac_set_colors (gc);
- SetRect (&r, x, y, x + width + 1, y + height + 1);
-
- FrameRect (&r); /* using foreground color of gc */
-}
-
-
-/* Mac replacement for XDrawRectangle: dest is a Pixmap. */
-
-static void
-mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
- Display *display;
- Pixmap p;
- GC gc;
- int x, y;
- unsigned int width, height;
-{
-#if 0 /* MAC_TODO: draw a rectangle in a PixMap */
- Rect r;
-
- SetPort (w);
- mac_set_colors (gc);
- SetRect (&r, x, y, x + width, y + height);
-
- FrameRect (&r); /* using foreground color of gc */
-#endif
-}
-
-
-static void
-mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
- bytes_per_char)
- Display *display;
- WindowPtr w;
- GC gc;
- int x, y;
- char *buf;
- int nchars, mode, bytes_per_char;
-{
- SetPort (w);
- mac_set_colors (gc);
-
- TextFont (gc->font->mac_fontnum);
- TextSize (gc->font->mac_fontsize);
- TextFace (gc->font->mac_fontface);
- TextMode (mode);
-
- MoveTo (x, y);
- DrawText (buf, 0, nchars * bytes_per_char);
-}
-
-
-/* Mac replacement for XDrawString. */
-
-static void
-XDrawString (display, w, gc, x, y, buf, nchars)
- Display *display;
- WindowPtr w;
- GC gc;
- int x, y;
- char *buf;
- int nchars;
-{
- mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
-}
-
-
-/* Mac replacement for XDrawString16. */
-
-static void
-XDrawString16 (display, w, gc, x, y, buf, nchars)
- Display *display;
- WindowPtr w;
- GC gc;
- int x, y;
- XChar2b *buf;
- int nchars;
-{
- mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcOr,
- 2);
-}
-
-
-/* Mac replacement for XDrawImageString. */
-
-static void
-XDrawImageString (display, w, gc, x, y, buf, nchars)
- Display *display;
- WindowPtr w;
- GC gc;
- int x, y;
- char *buf;
- int nchars;
-{
- mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcCopy, 1);
-}
-
-
-/* Mac replacement for XDrawString16. */
-
-static void
-XDrawImageString16 (display, w, gc, x, y, buf, nchars)
- Display *display;
- WindowPtr w;
- GC gc;
- int x, y;
- XChar2b *buf;
- int nchars;
-{
- mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
- 2);
-}
-
-
-/* Mac replacement for XCopyArea: dest must be window. */
-
-static void
-mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
- dest_y)
- Display *display;
- Pixmap src;
- WindowPtr dest;
- GC gc;
- int src_x, src_y;
- unsigned int width, height;
- int dest_x, dest_y;
-{
- Rect src_r, dest_r;
-
- SetPort (dest);
- mac_set_colors (gc);
-
- SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
- SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
-
- CopyBits ((BitMap *) src, &(dest->portBits), &src_r, &dest_r, srcCopy, 0);
-}
-
-
-#if 0
-/* Convert a pair of local coordinates to global (screen) coordinates.
- Assume graphic port has been properly set. */
-static void
-local_to_global_coord (short *h, short *v)
-{
- Point p;
-
- p.h = *h;
- p.v = *v;
-
- LocalToGlobal (&p);
-
- *h = p.h;
- *v = p.v;
-}
-#endif
-
-/* Mac replacement for XCopyArea: used only for scrolling. */
-
-static void
-mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
- Display *display;
- WindowPtr w;
- GC gc;
- int src_x, src_y;
- unsigned int width, height;
- int dest_x, dest_y;
-{
- Rect src_r, dest_r;
-
- SetPort (w);
-#if 0
- mac_set_colors (gc);
-#endif
-
- SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
- SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
-
-#if 0
- /* Need to use global coordinates and screenBits since src and dest
- areas overlap in general. */
- local_to_global_coord (&src_r.left, &src_r.top);
- local_to_global_coord (&src_r.right, &src_r.bottom);
- local_to_global_coord (&dest_r.left, &dest_r.top);
- local_to_global_coord (&dest_r.right, &dest_r.bottom);
-
- CopyBits (&qd.screenBits, &qd.screenBits, &src_r, &dest_r, srcCopy, 0);
-#else
- /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
- color mapping in CopyBits. Otherwise, it will be slow. */
- ForeColor (blackColor);
- BackColor (whiteColor);
- CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
-
- mac_set_colors (gc);
-#endif
-}
-
-
-/* Mac replacement for XCopyArea: dest must be Pixmap. */
-
-static void
-mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
- dest_x, dest_y)
- Display *display;
- Pixmap src;
- Pixmap dest;
- GC gc;
- int src_x, src_y;
- unsigned int width, height;
- int dest_x, dest_y;
-{
- Rect src_r, dest_r;
- int src_right = ((PixMap *) src)->bounds.right;
- int src_bottom = ((PixMap *) src)->bounds.bottom;
- int w = src_right - src_x;
- int h = src_bottom - src_y;
-
- mac_set_colors (gc);
-
- SetRect (&src_r, src_x, src_y, src_right, src_bottom);
- SetRect (&dest_r, dest_x, dest_y, dest_x + w, dest_y + h);
-
- CopyBits ((BitMap *) src, (BitMap *) dest, &src_r, &dest_r, srcCopy, 0);
-}
-
-
-/* Mac replacement for XChangeGC. */
-
-static void
-XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
- XGCValues *xgcv)
-{
- if (mask & GCForeground)
- gc->foreground = xgcv->foreground;
- if (mask & GCBackground)
- gc->background = xgcv->background;
- if (mask & GCFont)
- gc->font = xgcv->font;
-}
-
-
-/* Mac replacement for XCreateGC. */
-
-XGCValues *
-XCreateGC (void * ignore, Window window, unsigned long mask,
- XGCValues *xgcv)
-{
- XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
- bzero (gc, sizeof (XGCValues));
-
- XChangeGC (ignore, gc, mask, xgcv);
-
- return gc;
-}
-
-
-/* Used in xfaces.c. */
-
-void
-XFreeGC (display, gc)
- Display *display;
- GC gc;
-{
- xfree (gc);
-}
-
-
-/* Mac replacement for XGetGCValues. */
-
-static void
-XGetGCValues (void* ignore, XGCValues *gc,
- unsigned long mask, XGCValues *xgcv)
-{
- XChangeGC (ignore, xgcv, mask, gc);
-}
-
-
-/* Mac replacement for XSetForeground. */
-
-static void
-XSetForeground (display, gc, color)
- Display *display;
- GC gc;
- unsigned long color;
-{
- gc->foreground = color;
-}
-
-
-/* Mac replacement for XSetFont. */
-
-static void
-XSetFont (display, gc, font)
- Display *display;
- GC gc;
- XFontStruct *font;
-{
- gc->font = font;
-}
-
-
-static void
-XTextExtents16 (XFontStruct *font, XChar2b *text, int nchars,
- int *direction,int *font_ascent,
- int *font_descent, XCharStruct *cs)
-{
- /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
-}
-
-
-/* x_sync is a no-op on Mac. */
-void
-x_sync (f)
- void *f;
-{
-}
-
-
-/* Flush display of frame F, or of all frames if F is null. */
-
-void
-x_flush (f)
- struct frame *f;
-{
-#if 0 /* Nothing to do for Mac OS (needed in OS X perhaps?). */
- BLOCK_INPUT;
- if (f == NULL)
- {
- Lisp_Object rest, frame;
- FOR_EACH_FRAME (rest, frame)
- x_flush (XFRAME (frame));
- }
- else if (FRAME_X_P (f))
- XFlush (FRAME_MAC_DISPLAY (f));
- UNBLOCK_INPUT;
-#endif
-}
-
-
-/* Remove calls to XFlush by defining XFlush to an empty replacement.
- Calls to XFlush should be unnecessary because the X output buffer
- is flushed automatically as needed by calls to XPending,
- XNextEvent, or XWindowEvent according to the XFlush man page.
- XTread_socket calls XPending. Removing XFlush improves
- performance. */
-
-#define XFlush(DISPLAY) (void) 0
-
-\f
-/* Return the struct mac_display_info corresponding to DPY. There's
- only one. */
-
-struct mac_display_info *
-mac_display_info_for_display (dpy)
- Display *dpy;
-{
- return &one_mac_display_info;
-}
-
-
-\f
-/***********************************************************************
- Starting and ending an update
- ***********************************************************************/
-
-/* Start an update of frame F. This function is installed as a hook
- for update_begin, i.e. it is called when update_begin is called.
- This function is called prior to calls to x_update_window_begin for
- each window being updated. Currently, there is nothing to do here
- because all interesting stuff is done on a window basis. */
-
-void
-x_update_begin (f)
- struct frame *f;
-{
- /* Nothing to do. */
-}
-
-
-/* Start update of window W. Set the global variable updated_window
- to the window being updated and set output_cursor to the cursor
- position of W. */
-
-void
-x_update_window_begin (w)
- struct window *w;
-{
- struct frame *f = XFRAME (WINDOW_FRAME (w));
- struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
-
- updated_window = w;
- set_output_cursor (&w->cursor);
-
- BLOCK_INPUT;
-
- if (f == display_info->mouse_face_mouse_frame)
- {
- /* Don't do highlighting for mouse motion during the update. */
- display_info->mouse_face_defer = 1;
-
- /* If F needs to be redrawn, simply forget about any prior mouse
- highlighting. */
- if (FRAME_GARBAGED_P (f))
- display_info->mouse_face_window = Qnil;
-
-#if 0 /* Rows in a current matrix containing glyphs in mouse-face have
- their mouse_face_p flag set, which means that they are always
- unequal to rows in a desired matrix which never have that
- flag set. So, rows containing mouse-face glyphs are never
- scrolled, and we don't have to switch the mouse highlight off
- here to prevent it from being scrolled. */
-
- /* Can we tell that this update does not affect the window
- where the mouse highlight is? If so, no need to turn off.
- Likewise, don't do anything if the frame is garbaged;
- in that case, the frame's current matrix that we would use
- is all wrong, and we will redisplay that line anyway. */
- if (!NILP (display_info->mouse_face_window)
- && w == XWINDOW (display_info->mouse_face_window))
- {
- int i;
-
- for (i = 0; i < w->desired_matrix->nrows; ++i)
- if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
- break;
-
- if (i < w->desired_matrix->nrows)
- clear_mouse_face (display_info);
- }
-#endif /* 0 */
- }
-
- UNBLOCK_INPUT;
-}
-
-
-/* Draw a vertical window border to the right of window W if W doesn't
- have vertical scroll bars. */
-
-static void
-x_draw_vertical_border (w)
- struct window *w;
-{
- struct frame *f = XFRAME (WINDOW_FRAME (w));
-
- /* Redraw borders between horizontally adjacent windows. Don't
- do it for frames with vertical scroll bars because either the
- right scroll bar of a window, or the left scroll bar of its
- neighbor will suffice as a border. */
- if (!WINDOW_RIGHTMOST_P (w)
- && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
- {
- int x0, x1, y0, y1;
-
- window_box_edges (w, -1, &x0, &y0, &x1, &y1);
- x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f);
- y1 -= 1;
-
- XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
- f->output_data.mac->normal_gc, x1, y0, x1, y1);
- }
-}
-
-
-/* End update of window W (which is equal to updated_window).
-
- Draw vertical borders between horizontally adjacent windows, and
- display W's cursor if CURSOR_ON_P is non-zero.
-
- MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
- glyphs in mouse-face were overwritten. In that case we have to
- make sure that the mouse-highlight is properly redrawn.
-
- W may be a menu bar pseudo-window in case we don't have X toolkit
- support. Such windows don't have a cursor, so don't display it
- here. */
-
-void
-x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
- struct window *w;
- int cursor_on_p, mouse_face_overwritten_p;
-{
- if (!w->pseudo_window_p)
- {
- struct mac_display_info *dpyinfo
- = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
-
- BLOCK_INPUT;
-
- /* If a row with mouse-face was overwritten, arrange for
- XTframe_up_to_date to redisplay the mouse highlight. */
- if (mouse_face_overwritten_p)
- {
- dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
- dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
- dpyinfo->mouse_face_window = Qnil;
- }
-
- if (cursor_on_p)
- x_display_and_set_cursor (w, 1, output_cursor.hpos,
- output_cursor.vpos,
- output_cursor.x, output_cursor.y);
-
- x_draw_vertical_border (w);
- UNBLOCK_INPUT;
- }
-
- updated_window = NULL;
-}
-
-
-/* End update of frame F. This function is installed as a hook in
- update_end. */
-
-void
-x_update_end (f)
- struct frame *f;
-{
- /* Reset the background color of Mac OS Window to that of the frame after
- update so that it is used by Mac Toolbox to clear the update region before
- an update event is generated. */
- SetPort (FRAME_MAC_WINDOW (f));
- mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
-
- /* Mouse highlight may be displayed again. */
- FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
-
- BLOCK_INPUT;
- XFlush (FRAME_MAC_DISPLAY (f));
- UNBLOCK_INPUT;
-}
-
-
-/* This function is called from various places in xdisp.c whenever a
- complete update has been performed. The global variable
- updated_window is not available here. */
-
-void
-XTframe_up_to_date (f)
- struct frame *f;
-{
- if (FRAME_X_P (f))
- {
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
-
- if (dpyinfo->mouse_face_deferred_gc
- || f == dpyinfo->mouse_face_mouse_frame)
- {
- BLOCK_INPUT;
- if (dpyinfo->mouse_face_mouse_frame)
- note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
- dpyinfo->mouse_face_mouse_x,
- dpyinfo->mouse_face_mouse_y);
- dpyinfo->mouse_face_deferred_gc = 0;
- UNBLOCK_INPUT;
- }
- }
-}
-
-
-/* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
- arrow bitmaps, or clear the fringes if no bitmaps are required
- before DESIRED_ROW is made current. The window being updated is
- found in updated_window. This function It is called from
- update_window_line only if it is known that there are differences
- between bitmaps to be drawn between current row and DESIRED_ROW. */
-
-void
-x_after_update_window_line (desired_row)
- struct glyph_row *desired_row;
-{
- struct window *w = updated_window;
-
- xassert (w);
-
- if (!desired_row->mode_line_p && !w->pseudo_window_p)
- {
- BLOCK_INPUT;
- x_draw_row_fringe_bitmaps (w, desired_row);
-
- /* When a window has disappeared, make sure that no rest of
- full-width rows stays visible in the internal border. */
- if (windows_or_buffers_changed)
- {
- struct frame *f = XFRAME (w->frame);
- int width = FRAME_INTERNAL_BORDER_WIDTH (f);
- int height = desired_row->visible_height;
- int x = (window_box_right (w, -1)
- + FRAME_X_RIGHT_FRINGE_WIDTH (f));
- int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
-
- XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
- x, y, width, height, 0);
- }
-
- UNBLOCK_INPUT;
- }
-}
-
-
-/* Draw the bitmap WHICH in one of the left or right fringes of
- window W. ROW is the glyph row for which to display the bitmap; it
- determines the vertical position at which the bitmap has to be
- drawn. */
-
-static void
-x_draw_fringe_bitmap (w, row, which, left_p)
- struct window *w;
- struct glyph_row *row;
- enum fringe_bitmap_type which;
- int left_p;
-{
- struct frame *f = XFRAME (WINDOW_FRAME (w));
- Display *display = FRAME_MAC_DISPLAY (f);
- WindowPtr window = FRAME_MAC_WINDOW (f);
- int x, y, wd, h, dy;
- int b1, b2;
- unsigned char *bits;
- BitMap bitmap;
- XGCValues gcv;
- struct face *face;
-
- /* Must clip because of partially visible lines. */
- x_clip_to_row (w, row, 1);
-
- /* Convert row to frame coordinates. */
- y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
-
- switch (which)
- {
- case NO_FRINGE_BITMAP:
- wd = 0;
- h = 0;
- break;
-
- case LEFT_TRUNCATION_BITMAP:
- wd = left_width;
- h = left_height;
- bits = left_bits;
- break;
-
- case OVERLAY_ARROW_BITMAP:
- wd = ov_width;
- h = ov_height;
- bits = ov_bits;
- break;
-
- case RIGHT_TRUNCATION_BITMAP:
- wd = right_width;
- h = right_height;
- bits = right_bits;
- break;
-
- case CONTINUED_LINE_BITMAP:
- wd = continued_width;
- h = continued_height;
- bits = continued_bits;
- break;
-
- case CONTINUATION_LINE_BITMAP:
- wd = continuation_width;
- h = continuation_height;
- bits = continuation_bits;
- break;
-
- case ZV_LINE_BITMAP:
- wd = zv_width;
- h = zv_height - (y % zv_period);
- bits = zv_bits + (y % zv_period);
- break;
-
- default:
- abort ();
- }
-
- /* Clip bitmap if too high. */
- if (h > row->height)
- h = row->height;
-
- /* Set dy to the offset in the row to start drawing the bitmap. */
- dy = (row->height - h) / 2;
-
- /* Draw the bitmap. I believe these small pixmaps can be cached
- by the server. */
- face = FACE_FROM_ID (f, FRINGE_FACE_ID);
- PREPARE_FACE_FOR_DISPLAY (f, face);
-
- /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
- the fringe. */
- b1 = -1;
- if (left_p)
- {
- if (wd > FRAME_X_LEFT_FRINGE_WIDTH (f))
- wd = FRAME_X_LEFT_FRINGE_WIDTH (f);
- x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
- - wd
- - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);
- if (wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > h)
- {
- /* If W has a vertical border to its left, don't draw over it. */
- int border = ((XFASTINT (w->left) > 0
- && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
- ? 1 : 0);
- b1 = (window_box_left (w, -1)
- - FRAME_X_LEFT_FRINGE_WIDTH (f)
- + border);
- b2 = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);
- }
- }
- else
- {
- if (wd > FRAME_X_RIGHT_FRINGE_WIDTH (f))
- wd = FRAME_X_RIGHT_FRINGE_WIDTH (f);
- x = (window_box_right (w, -1)
- + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - wd) / 2);
- /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
- the fringe. */
- if (wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > h)
- {
- b1 = window_box_right (w, -1);
- b2 = FRAME_X_RIGHT_FRINGE_WIDTH (f);
- }
- }
-
- if (b1 >= 0)
- {
- int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
- XGCValues gcv;
- gcv.foreground = face->background;
-
-#if 0 /* MAC_TODO: stipple */
- /* In case the same realized face is used for fringes and
- for something displayed in the text (e.g. face `region' on
- mono-displays, the fill style may have been changed to
- FillSolid in x_draw_glyph_string_background. */
- if (face->stipple)
- XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
- else
- XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
-#endif
-
- XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
- &gcv,
- b1,
- WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
- row->y)),
- b2,
- row->visible_height);
-
-#if 0 /* MAC_TODO: stipple */
- if (!face->stipple)
- XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
-#endif
- }
-
- if (which == NO_FRINGE_BITMAP)
- return;
-
- mac_create_bitmap_from_bitmap_data (&bitmap, bits, wd, h);
- gcv.foreground = face->foreground;
- gcv.background = face->background;
-
- mac_draw_bitmap (display, window, &gcv, x, y + dy, &bitmap);
-
- mac_free_bitmap (&bitmap);
- mac_reset_clipping (display, window);
-}
-
-
-/* Draw fringe bitmaps for glyph row ROW on window W. Call this
- function with input blocked. */
-
-static void
-x_draw_row_fringe_bitmaps (w, row)
- struct window *w;
- struct glyph_row *row;
-{
- struct frame *f = XFRAME (w->frame);
- enum fringe_bitmap_type bitmap;
-
- xassert (interrupt_input_blocked);
-
- /* If row is completely invisible, because of vscrolling, we
- don't have to draw anything. */
- if (row->visible_height <= 0)
- return;
-
- if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0)
- {
- /* Decide which bitmap to draw in the left fringe. */
- if (row->overlay_arrow_p)
- bitmap = OVERLAY_ARROW_BITMAP;
- else if (row->truncated_on_left_p)
- bitmap = LEFT_TRUNCATION_BITMAP;
- else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
- bitmap = CONTINUATION_LINE_BITMAP;
- else if (row->indicate_empty_line_p)
- bitmap = ZV_LINE_BITMAP;
- else
- bitmap = NO_FRINGE_BITMAP;
-
- x_draw_fringe_bitmap (w, row, bitmap, 1);
- }
-
- if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0)
- {
- /* Decide which bitmap to draw in the right fringe. */
- if (row->truncated_on_right_p)
- bitmap = RIGHT_TRUNCATION_BITMAP;
- else if (row->continued_p)
- bitmap = CONTINUED_LINE_BITMAP;
- else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0)
- bitmap = ZV_LINE_BITMAP;
- else
- bitmap = NO_FRINGE_BITMAP;
-
- x_draw_fringe_bitmap (w, row, bitmap, 0);
- }
-}
-
-\f
-/***********************************************************************
- Line Highlighting
- ***********************************************************************/
-
-/* External interface to control of standout mode. Not used for X
- frames. Aborts when called. */
-
-void
-XTreassert_line_highlight (new, vpos)
- int new, vpos;
-{
- abort ();
-}
-
-
-/* Call this when about to modify line at position VPOS and change
- whether it is highlighted. Not used for X frames. Aborts when
- called. */
-
-void
-x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
- int new_highlight, vpos, y, first_unused_hpos;
-{
- abort ();
-}
-
-
-/* This is called when starting Emacs and when restarting after
- suspend. When starting Emacs, no X window is mapped. And nothing
- must be done to Emacs's own window if it is suspended (though that
- rarely happens). */
-
-void
-XTset_terminal_modes ()
-{
-}
-
-/* This is called when exiting or suspending Emacs. Exiting will make
- the X-windows go away, and suspending requires no action. */
-
-void
-XTreset_terminal_modes ()
-{
-}
-
-
-\f
-/***********************************************************************
- Output Cursor
- ***********************************************************************/
-
-/* Set the global variable output_cursor to CURSOR. All cursor
- positions are relative to updated_window. */
-
-static void
-set_output_cursor (cursor)
- struct cursor_pos *cursor;
-{
- output_cursor.hpos = cursor->hpos;
- output_cursor.vpos = cursor->vpos;
- output_cursor.x = cursor->x;
- output_cursor.y = cursor->y;
-}
-
-
-/* Set a nominal cursor position.
-
- HPOS and VPOS are column/row positions in a window glyph matrix. X
- and Y are window text area relative pixel positions.
-
- If this is done during an update, updated_window will contain the
- window that is being updated and the position is the future output
- cursor position for that window. If updated_window is null, use
- selected_window and display the cursor at the given position. */
-
-void
-XTcursor_to (vpos, hpos, y, x)
- int vpos, hpos, y, x;
-{
- struct window *w;
-
- /* If updated_window is not set, work on selected_window. */
- if (updated_window)
- w = updated_window;
- else
- w = XWINDOW (selected_window);
-
- /* Set the output cursor. */
- output_cursor.hpos = hpos;
- output_cursor.vpos = vpos;
- output_cursor.x = x;
- output_cursor.y = y;
-
- /* If not called as part of an update, really display the cursor.
- This will also set the cursor position of W. */
- if (updated_window == NULL)
- {
- BLOCK_INPUT;
- x_display_cursor (w, 1, hpos, vpos, x, y);
- XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
- UNBLOCK_INPUT;
- }
-}
-
-
-\f
-/***********************************************************************
- Display Iterator
- ***********************************************************************/
-
-/* Function prototypes of this page. */
-
-static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
- struct glyph *,
- XChar2b *,
- int *));
-static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
- int, XChar2b *, int));
-static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
-static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
-static void x_append_glyph P_ ((struct it *));
-static void x_append_composite_glyph P_ ((struct it *));
-static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
- int, int, double));
-static void x_produce_glyphs P_ ((struct it *));
-static void x_produce_image_glyph P_ ((struct it *it));
-
-
-/* Return a pointer to per-char metric information in FONT of a
- character pointed by B which is a pointer to an XChar2b. */
-
-#define PER_CHAR_METRIC(font, b) \
- ((font)->per_char \
- ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
- + (((font)->min_byte1 || (font)->max_byte1) \
- ? (((b)->byte1 - (font)->min_byte1) \
- * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
- : 0)) \
- : &((font)->max_bounds))
-
-
-/* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
- is not contained in the font. */
-
-static INLINE XCharStruct *
-x_per_char_metric (font, char2b)
- XFontStruct *font;
- XChar2b *char2b;
-{
- /* The result metric information. */
- XCharStruct *pcm = NULL;
-
- xassert (font && char2b);
-
- if (font->per_char != NULL)
- {
- if (font->min_byte1 == 0 && font->max_byte1 == 0)
- {
- /* min_char_or_byte2 specifies the linear character index
- corresponding to the first element of the per_char array,
- max_char_or_byte2 is the index of the last character. A
- character with non-zero CHAR2B->byte1 is not in the font.
- A character with byte2 less than min_char_or_byte2 or
- greater max_char_or_byte2 is not in the font. */
- if (char2b->byte1 == 0
- && char2b->byte2 >= font->min_char_or_byte2
- && char2b->byte2 <= font->max_char_or_byte2)
- pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
- }
- else
- {
- /* If either min_byte1 or max_byte1 are nonzero, both
- min_char_or_byte2 and max_char_or_byte2 are less than
- 256, and the 2-byte character index values corresponding
- to the per_char array element N (counting from 0) are:
-
- byte1 = N/D + min_byte1
- byte2 = N\D + min_char_or_byte2
-
- where:
-
- D = max_char_or_byte2 - min_char_or_byte2 + 1
- / = integer division
- \ = integer modulus */
- if (char2b->byte1 >= font->min_byte1
- && char2b->byte1 <= font->max_byte1
- && char2b->byte2 >= font->min_char_or_byte2
- && char2b->byte2 <= font->max_char_or_byte2)
- {
- pcm = (font->per_char
- + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
- * (char2b->byte1 - font->min_byte1))
- + (char2b->byte2 - font->min_char_or_byte2));
- }
- }
- }
- else
- {
- /* If the per_char pointer is null, all glyphs between the first
- and last character indexes inclusive have the same
- information, as given by both min_bounds and max_bounds. */
- if (char2b->byte2 >= font->min_char_or_byte2
- && char2b->byte2 <= font->max_char_or_byte2)
- pcm = &font->max_bounds;
- }
-
- return ((pcm == NULL
- || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
- ? NULL : pcm);
-}
-
-
-/* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
- the two-byte form of C. Encoding is returned in *CHAR2B. */
-
-static INLINE void
-x_encode_char (c, char2b, font_info)
- int c;
- XChar2b *char2b;
- struct font_info *font_info;
-{
- int charset = CHAR_CHARSET (c);
- XFontStruct *font = font_info->font;
-
- /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
- This may be either a program in a special encoder language or a
- fixed encoding. */
- if (font_info->font_encoder)
- {
- /* It's a program. */
- struct ccl_program *ccl = font_info->font_encoder;
-
- if (CHARSET_DIMENSION (charset) == 1)
- {
- ccl->reg[0] = charset;
- ccl->reg[1] = char2b->byte2;
- }
- else
- {
- ccl->reg[0] = charset;
- ccl->reg[1] = char2b->byte1;
- ccl->reg[2] = char2b->byte2;
- }
-
- ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
-
- /* We assume that MSBs are appropriately set/reset by CCL
- program. */
- if (font->max_byte1 == 0) /* 1-byte font */
- char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
- else
- char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
- }
- else if (font_info->encoding[charset])
- {
- /* Fixed encoding scheme. See fontset.h for the meaning of the
- encoding numbers. */
- int enc = font_info->encoding[charset];
-
- if ((enc == 1 || enc == 2)
- && CHARSET_DIMENSION (charset) == 2)
- char2b->byte1 |= 0x80;
-
- if (enc == 1 || enc == 3)
- char2b->byte2 |= 0x80;
-
- if (enc == 4)
- {
- int sjis1, sjis2;
-
- ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
- char2b->byte1 = sjis1;
- char2b->byte2 = sjis2;
- }
- }
-}
-
-
-/* Get face and two-byte form of character C in face FACE_ID on frame
- F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
- means we want to display multibyte text. Value is a pointer to a
- realized face that is ready for display. */
-
-static INLINE struct face *
-x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
- struct frame *f;
- int c, face_id;
- XChar2b *char2b;
- int multibyte_p;
-{
- struct face *face = FACE_FROM_ID (f, face_id);
-
- if (!multibyte_p)
- {
- /* Unibyte case. We don't have to encode, but we have to make
- sure to use a face suitable for unibyte. */
- char2b->byte1 = 0;
- char2b->byte2 = c;
- face_id = FACE_FOR_CHAR (f, face, c);
- face = FACE_FROM_ID (f, face_id);
- }
- else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
- {
- /* Case of ASCII in a face known to fit ASCII. */
- char2b->byte1 = 0;
- char2b->byte2 = c;
- }
- else
- {
- int c1, c2, charset;
-
- /* Split characters into bytes. If c2 is -1 afterwards, C is
- really a one-byte character so that byte1 is zero. */
- SPLIT_CHAR (c, charset, c1, c2);
- if (c2 > 0)
- char2b->byte1 = c1, char2b->byte2 = c2;
- else
- char2b->byte1 = 0, char2b->byte2 = c1;
-
- /* Maybe encode the character in *CHAR2B. */
- if (face->font != NULL)
- {
- struct font_info *font_info
- = FONT_INFO_FROM_ID (f, face->font_info_id);
- if (font_info)
- x_encode_char (c, char2b, font_info);
- }
- }
-
- /* Make sure X resources of the face are allocated. */
- xassert (face != NULL);
- PREPARE_FACE_FOR_DISPLAY (f, face);
-
- return face;
-}
-
-
-/* Get face and two-byte form of character glyph GLYPH on frame F.
- The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
- a pointer to a realized face that is ready for display. */
-
-static INLINE struct face *
-x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
- struct frame *f;
- struct glyph *glyph;
- XChar2b *char2b;
- int *two_byte_p;
-{
- struct face *face;
-
- xassert (glyph->type == CHAR_GLYPH);
- face = FACE_FROM_ID (f, glyph->face_id);
-
- if (two_byte_p)
- *two_byte_p = 0;
-
- if (!glyph->multibyte_p)
- {
- /* Unibyte case. We don't have to encode, but we have to make
- sure to use a face suitable for unibyte. */
- char2b->byte1 = 0;
- char2b->byte2 = glyph->u.ch;
- }
- else if (glyph->u.ch < 128
- && glyph->face_id < BASIC_FACE_ID_SENTINEL)
- {
- /* Case of ASCII in a face known to fit ASCII. */
- char2b->byte1 = 0;
- char2b->byte2 = glyph->u.ch;
- }
- else
- {
- int c1, c2, charset;
-
- /* Split characters into bytes. If c2 is -1 afterwards, C is
- really a one-byte character so that byte1 is zero. */
- SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
- if (c2 > 0)
- char2b->byte1 = c1, char2b->byte2 = c2;
- else
- char2b->byte1 = 0, char2b->byte2 = c1;
-
- /* Maybe encode the character in *CHAR2B. */
- if (charset != CHARSET_ASCII)
- {
- struct font_info *font_info
- = FONT_INFO_FROM_ID (f, face->font_info_id);
- if (font_info)
- {
- x_encode_char (glyph->u.ch, char2b, font_info);
- if (two_byte_p)
- *two_byte_p
- = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
- }
- }
- }
-
- /* Make sure X resources of the face are allocated. */
- xassert (face != NULL);
- PREPARE_FACE_FOR_DISPLAY (f, face);
- return face;
-}
-
-
-/* Store one glyph for IT->char_to_display in IT->glyph_row.
- Called from x_produce_glyphs when IT->glyph_row is non-null. */
-
-static INLINE void
-x_append_glyph (it)
- struct it *it;
-{
- struct glyph *glyph;
- enum glyph_row_area area = it->area;
-
- xassert (it->glyph_row);
- xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
-
- glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
- if (glyph < it->glyph_row->glyphs[area + 1])
- {
- glyph->charpos = CHARPOS (it->position);
- glyph->object = it->object;
- glyph->pixel_width = it->pixel_width;
- glyph->voffset = it->voffset;
- glyph->type = CHAR_GLYPH;
- glyph->multibyte_p = it->multibyte_p;
- glyph->left_box_line_p = it->start_of_box_run_p;
- glyph->right_box_line_p = it->end_of_box_run_p;
- glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
- || it->phys_descent > it->descent);
- glyph->padding_p = 0;
- glyph->glyph_not_available_p = it->glyph_not_available_p;
- glyph->face_id = it->face_id;
- glyph->u.ch = it->char_to_display;
- ++it->glyph_row->used[area];
- }
-}
-
-/* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
- Called from x_produce_glyphs when IT->glyph_row is non-null. */
-
-static INLINE void
-x_append_composite_glyph (it)
- struct it *it;
-{
- struct glyph *glyph;
- enum glyph_row_area area = it->area;
-
- xassert (it->glyph_row);
-
- glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
- if (glyph < it->glyph_row->glyphs[area + 1])
- {
- glyph->charpos = CHARPOS (it->position);
- glyph->object = it->object;
- glyph->pixel_width = it->pixel_width;
- glyph->voffset = it->voffset;
- glyph->type = COMPOSITE_GLYPH;
- glyph->multibyte_p = it->multibyte_p;
- glyph->left_box_line_p = it->start_of_box_run_p;
- glyph->right_box_line_p = it->end_of_box_run_p;
- glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
- || it->phys_descent > it->descent);
- glyph->padding_p = 0;
- glyph->glyph_not_available_p = 0;
- glyph->face_id = it->face_id;
- glyph->u.cmp_id = it->cmp_id;
- ++it->glyph_row->used[area];
- }
-}
-
-
-/* Change IT->ascent and IT->height according to the setting of
- IT->voffset. */
-
-static INLINE void
-take_vertical_position_into_account (it)
- struct it *it;
-{
- if (it->voffset)
- {
- if (it->voffset < 0)
- /* Increase the ascent so that we can display the text higher
- in the line. */
- it->ascent += abs (it->voffset);
- else
- /* Increase the descent so that we can display the text lower
- in the line. */
- it->descent += it->voffset;
- }
-}
-
-
-/* Produce glyphs/get display metrics for the image IT is loaded with.
- See the description of struct display_iterator in dispextern.h for
- an overview of struct display_iterator. */
-
-static void
-x_produce_image_glyph (it)
- struct it *it;
-{
- struct image *img;
- struct face *face;
-
- xassert (it->what == IT_IMAGE);
-
- face = FACE_FROM_ID (it->f, it->face_id);
- img = IMAGE_FROM_ID (it->f, it->image_id);
- xassert (img);
-
- /* Make sure X resources of the face and image are loaded. */
- PREPARE_FACE_FOR_DISPLAY (it->f, face);
- prepare_image_for_display (it->f, img);
-
- it->ascent = it->phys_ascent = image_ascent (img, face);
- it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
- it->pixel_width = img->width + 2 * img->hmargin;
-
- it->nglyphs = 1;
-
- if (face->box != FACE_NO_BOX)
- {
- it->ascent += face->box_line_width;
- it->descent += face->box_line_width;
-
- if (it->start_of_box_run_p)
- it->pixel_width += face->box_line_width;
- if (it->end_of_box_run_p)
- it->pixel_width += face->box_line_width;
- }
-
- take_vertical_position_into_account (it);
-
- if (it->glyph_row)
- {
- struct glyph *glyph;
- enum glyph_row_area area = it->area;
-
- glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
- if (glyph < it->glyph_row->glyphs[area + 1])
- {
- glyph->charpos = CHARPOS (it->position);
- glyph->object = it->object;
- glyph->pixel_width = it->pixel_width;
- glyph->voffset = it->voffset;
- glyph->type = IMAGE_GLYPH;
- glyph->multibyte_p = it->multibyte_p;
- glyph->left_box_line_p = it->start_of_box_run_p;
- glyph->right_box_line_p = it->end_of_box_run_p;
- glyph->overlaps_vertically_p = 0;
- glyph->padding_p = 0;
- glyph->glyph_not_available_p = 0;
- glyph->face_id = it->face_id;
- glyph->u.img_id = img->id;
- ++it->glyph_row->used[area];
- }
- }
-}
-
-
-/* Append a stretch glyph to IT->glyph_row. OBJECT is the source
- of the glyph, WIDTH and HEIGHT are the width and height of the
- stretch. ASCENT is the percentage/100 of HEIGHT to use for the
- ascent of the glyph (0 <= ASCENT <= 1). */
-
-static void
-x_append_stretch_glyph (it, object, width, height, ascent)
- struct it *it;
- Lisp_Object object;
- int width, height;
- double ascent;
-{
- struct glyph *glyph;
- enum glyph_row_area area = it->area;
-
- xassert (ascent >= 0 && ascent <= 1);
-
- glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
- if (glyph < it->glyph_row->glyphs[area + 1])
- {
- glyph->charpos = CHARPOS (it->position);
- glyph->object = object;
- glyph->pixel_width = width;
- glyph->voffset = it->voffset;
- glyph->type = STRETCH_GLYPH;
- glyph->multibyte_p = it->multibyte_p;
- glyph->left_box_line_p = it->start_of_box_run_p;
- glyph->right_box_line_p = it->end_of_box_run_p;
- glyph->overlaps_vertically_p = 0;
- glyph->padding_p = 0;
- glyph->glyph_not_available_p = 0;
- glyph->face_id = it->face_id;
- glyph->u.stretch.ascent = height * ascent;
- glyph->u.stretch.height = height;
- ++it->glyph_row->used[area];
- }
-}
-
-
-/* Produce a stretch glyph for iterator IT. IT->object is the value
- of the glyph property displayed. The value must be a list
- `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
- being recognized:
-
- 1. `:width WIDTH' specifies that the space should be WIDTH *
- canonical char width wide. WIDTH may be an integer or floating
- point number.
-
- 2. `:relative-width FACTOR' specifies that the width of the stretch
- should be computed from the width of the first character having the
- `glyph' property, and should be FACTOR times that width.
-
- 3. `:align-to HPOS' specifies that the space should be wide enough
- to reach HPOS, a value in canonical character units.
-
- Exactly one of the above pairs must be present.
-
- 4. `:height HEIGHT' specifies that the height of the stretch produced
- should be HEIGHT, measured in canonical character units.
-
- 5. `:relative-height FACTOR' specifies that the height of the stretch
- should be FACTOR times the height of the characters having the glyph
- property.
-
- Either none or exactly one of 4 or 5 must be present.
-
- 6. `:ascent ASCENT' specifies that ASCENT percent of the height
- of the stretch should be used for the ascent of the stretch.
- ASCENT must be in the range 0 <= ASCENT <= 100. */
-
-#define NUMVAL(X) \
- ((INTEGERP (X) || FLOATP (X)) \
- ? XFLOATINT (X) \
- : - 1)
-
-
-static void
-x_produce_stretch_glyph (it)
- struct it *it;
-{
- /* (space :width WIDTH :height HEIGHT. */
-#if GLYPH_DEBUG
- extern Lisp_Object Qspace;
-#endif
- extern Lisp_Object QCwidth, QCheight, QCascent;
- extern Lisp_Object QCrelative_width, QCrelative_height;
- extern Lisp_Object QCalign_to;
- Lisp_Object prop, plist;
- double width = 0, height = 0, ascent = 0;
- struct face *face = FACE_FROM_ID (it->f, it->face_id);
- XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
-
- PREPARE_FACE_FOR_DISPLAY (it->f, face);
-
- /* List should start with `space'. */
- xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
- plist = XCDR (it->object);
-
- /* Compute the width of the stretch. */
- if (prop = Fplist_get (plist, QCwidth),
- NUMVAL (prop) > 0)
- /* Absolute width `:width WIDTH' specified and valid. */
- width = NUMVAL (prop) * CANON_X_UNIT (it->f);
- else if (prop = Fplist_get (plist, QCrelative_width),
- NUMVAL (prop) > 0)
- {
- /* Relative width `:relative-width FACTOR' specified and valid.
- Compute the width of the characters having the `glyph'
- property. */
- struct it it2;
- unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
-
- it2 = *it;
- if (it->multibyte_p)
- {
- int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
- - IT_BYTEPOS (*it));
- it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
- }
- else
- it2.c = *p, it2.len = 1;
-
- it2.glyph_row = NULL;
- it2.what = IT_CHARACTER;
- x_produce_glyphs (&it2);
- width = NUMVAL (prop) * it2.pixel_width;
- }
- else if (prop = Fplist_get (plist, QCalign_to),
- NUMVAL (prop) > 0)
- width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
- else
- /* Nothing specified -> width defaults to canonical char width. */
- width = CANON_X_UNIT (it->f);
-
- /* Compute height. */
- if (prop = Fplist_get (plist, QCheight),
- NUMVAL (prop) > 0)
- height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
- else if (prop = Fplist_get (plist, QCrelative_height),
- NUMVAL (prop) > 0)
- height = FONT_HEIGHT (font) * NUMVAL (prop);
- else
- height = FONT_HEIGHT (font);
-
- /* Compute percentage of height used for ascent. If
- `:ascent ASCENT' is present and valid, use that. Otherwise,
- derive the ascent from the font in use. */
- if (prop = Fplist_get (plist, QCascent),
- NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
- ascent = NUMVAL (prop) / 100.0;
- else
- ascent = (double) font->ascent / FONT_HEIGHT (font);
-
- if (width <= 0)
- width = 1;
- if (height <= 0)
- height = 1;
-
- if (it->glyph_row)
- {
- Lisp_Object object = it->stack[it->sp - 1].string;
- if (!STRINGP (object))
- object = it->w->buffer;
- x_append_stretch_glyph (it, object, width, height, ascent);
- }
-
- it->pixel_width = width;
- it->ascent = it->phys_ascent = height * ascent;
- it->descent = it->phys_descent = height - it->ascent;
- it->nglyphs = 1;
-
- if (face->box != FACE_NO_BOX)
- {
- it->ascent += face->box_line_width;
- it->descent += face->box_line_width;
-
- if (it->start_of_box_run_p)
- it->pixel_width += face->box_line_width;
- if (it->end_of_box_run_p)
- it->pixel_width += face->box_line_width;
- }
-
- take_vertical_position_into_account (it);
-}
-
-/* Return proper value to be used as baseline offset of font that has
- ASCENT and DESCENT to draw characters by the font at the vertical
- center of the line of frame F.
-
- Here, out task is to find the value of BOFF in the following figure;
-
- -------------------------+-----------+-
- -+-+---------+-+ | |
- | | | | | |
- | | | | F_ASCENT F_HEIGHT
- | | | ASCENT | |
- HEIGHT | | | | |
- | | |-|-+------+-----------|------- baseline
- | | | | BOFF | |
- | |---------|-+-+ | |
- | | | DESCENT | |
- -+-+---------+-+ F_DESCENT |
- -------------------------+-----------+-
-
- -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
- BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
- DESCENT = FONT->descent
- HEIGHT = FONT_HEIGHT (FONT)
- F_DESCENT = (F->output_data.x->font->descent
- - F->output_data.x->baseline_offset)
- F_HEIGHT = FRAME_LINE_HEIGHT (F)
-*/
-
-#define VCENTER_BASELINE_OFFSET(FONT, F) \
- ((FONT)->descent \
- + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT))) / 2 \
- - ((F)->output_data.mac->font->descent - (F)->output_data.mac->baseline_offset))
-
-/* Produce glyphs/get display metrics for the display element IT is
- loaded with. See the description of struct display_iterator in
- dispextern.h for an overview of struct display_iterator. */
-
-void
-x_produce_glyphs (it)
- struct it *it;
-{
- it->glyph_not_available_p = 0;
-
- if (it->what == IT_CHARACTER)
- {
- XChar2b char2b;
- XFontStruct *font;
- struct face *face = FACE_FROM_ID (it->f, it->face_id);
- XCharStruct *pcm;
- int font_not_found_p;
- struct font_info *font_info;
- int boff; /* baseline offset */
-
- /* Maybe translate single-byte characters to multibyte, or the
- other way. */
- it->char_to_display = it->c;
- if (!ASCII_BYTE_P (it->c))
- {
- if (unibyte_display_via_language_environment
- && SINGLE_BYTE_CHAR_P (it->c)
- && (it->c >= 0240
- || !NILP (Vnonascii_translation_table)))
- {
- it->char_to_display = unibyte_char_to_multibyte (it->c);
- it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
- face = FACE_FROM_ID (it->f, it->face_id);
- }
- else if (!SINGLE_BYTE_CHAR_P (it->c)
- && !it->multibyte_p)
- {
- it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
- it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
- face = FACE_FROM_ID (it->f, it->face_id);
- }
- }
-
- /* Get font to use. Encode IT->char_to_display. */
- x_get_char_face_and_encoding (it->f, it->char_to_display,
- it->face_id, &char2b,
- it->multibyte_p);
- font = face->font;
-
- /* When no suitable font found, use the default font. */
- font_not_found_p = font == NULL;
- if (font_not_found_p)
- {
- font = FRAME_FONT (it->f);
- boff = it->f->output_data.mac->baseline_offset;
- font_info = NULL;
- }
- else
- {
- font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
- boff = font_info->baseline_offset;
- if (font_info->vertical_centering)
- boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
- }
-
- if (it->char_to_display >= ' '
- && (!it->multibyte_p || it->char_to_display < 128))
- {
- /* Either unibyte or ASCII. */
- int stretched_p;
-
- it->nglyphs = 1;
-
- pcm = x_per_char_metric (font, &char2b);
- it->ascent = font->ascent + boff;
- it->descent = font->descent - boff;
-
- if (pcm)
- {
- it->phys_ascent = pcm->ascent + boff;
- it->phys_descent = pcm->descent - boff;
- it->pixel_width = pcm->width;
- }
- else
- {
- it->glyph_not_available_p = 1;
- it->phys_ascent = font->ascent + boff;
- it->phys_descent = font->descent - boff;
- it->pixel_width = FONT_WIDTH (font);
- }
-
- /* If this is a space inside a region of text with
- `space-width' property, change its width. */
- stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
- if (stretched_p)
- it->pixel_width *= XFLOATINT (it->space_width);
-
- /* If face has a box, add the box thickness to the character
- height. If character has a box line to the left and/or
- right, add the box line width to the character's width. */
- if (face->box != FACE_NO_BOX)
- {
- int thick = face->box_line_width;
-
- it->ascent += thick;
- it->descent += thick;
-
- if (it->start_of_box_run_p)
- it->pixel_width += thick;
- if (it->end_of_box_run_p)
- it->pixel_width += thick;
- }
-
- /* If face has an overline, add the height of the overline
- (1 pixel) and a 1 pixel margin to the character height. */
- if (face->overline_p)
- it->ascent += 2;
-
- take_vertical_position_into_account (it);
-
- /* If we have to actually produce glyphs, do it. */
- if (it->glyph_row)
- {
- if (stretched_p)
- {
- /* Translate a space with a `space-width' property
- into a stretch glyph. */
- double ascent = (double) font->ascent / FONT_HEIGHT (font);
- x_append_stretch_glyph (it, it->object, it->pixel_width,
- it->ascent + it->descent, ascent);
- }
- else
- x_append_glyph (it);
-
- /* If characters with lbearing or rbearing are displayed
- in this line, record that fact in a flag of the
- glyph row. This is used to optimize X output code. */
- if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
- it->glyph_row->contains_overlapping_glyphs_p = 1;
- }
- }
- else if (it->char_to_display == '\n')
- {
- /* A newline has no width but we need the height of the line. */
- it->pixel_width = 0;
- it->nglyphs = 0;
- it->ascent = it->phys_ascent = font->ascent + boff;
- it->descent = it->phys_descent = font->descent - boff;
-
- if (face->box != FACE_NO_BOX)
- {
- int thick = face->box_line_width;
- it->ascent += thick;
- it->descent += thick;
- }
- }
- else if (it->char_to_display == '\t')
- {
- int tab_width = it->tab_width * CANON_X_UNIT (it->f);
- int x = it->current_x + it->continuation_lines_width;
- int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
-
- it->pixel_width = next_tab_x - x;
- it->nglyphs = 1;
- it->ascent = it->phys_ascent = font->ascent + boff;
- it->descent = it->phys_descent = font->descent - boff;
-
- if (it->glyph_row)
- {
- double ascent = (double) it->ascent / (it->ascent + it->descent);
- x_append_stretch_glyph (it, it->object, it->pixel_width,
- it->ascent + it->descent, ascent);
- }
- }
- else
- {
- /* A multi-byte character. Assume that the display width of the
- character is the width of the character multiplied by the
- width of the font. */
-
- /* If we found a font, this font should give us the right
- metrics. If we didn't find a font, use the frame's
- default font and calculate the width of the character
- from the charset width; this is what old redisplay code
- did. */
- pcm = x_per_char_metric (font, &char2b);
- if (font_not_found_p || !pcm)
- {
- int charset = CHAR_CHARSET (it->char_to_display);
-
- it->glyph_not_available_p = 1;
- it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
- * CHARSET_WIDTH (charset));
- it->phys_ascent = font->ascent + boff;
- it->phys_descent = font->descent - boff;
- }
- else
- {
- it->pixel_width = pcm->width;
- it->phys_ascent = pcm->ascent + boff;
- it->phys_descent = pcm->descent - boff;
- if (it->glyph_row
- && (pcm->lbearing < 0
- || pcm->rbearing > pcm->width))
- it->glyph_row->contains_overlapping_glyphs_p = 1;
- }
- it->nglyphs = 1;
- it->ascent = font->ascent + boff;
- it->descent = font->descent - boff;
- if (face->box != FACE_NO_BOX)
- {
- int thick = face->box_line_width;
- it->ascent += thick;
- it->descent += thick;
-
- if (it->start_of_box_run_p)
- it->pixel_width += thick;
- if (it->end_of_box_run_p)
- it->pixel_width += thick;
- }
-
- /* If face has an overline, add the height of the overline
- (1 pixel) and a 1 pixel margin to the character height. */
- if (face->overline_p)
- it->ascent += 2;
-
- take_vertical_position_into_account (it);
-
- if (it->glyph_row)
- x_append_glyph (it);
- }
- }
- else if (it->what == IT_COMPOSITION)
- {
- /* Note: A composition is represented as one glyph in the
- glyph matrix. There are no padding glyphs. */
- XChar2b char2b;
- XFontStruct *font;
- struct face *face = FACE_FROM_ID (it->f, it->face_id);
- XCharStruct *pcm;
- int font_not_found_p;
- struct font_info *font_info;
- int boff; /* baseline offset */
- struct composition *cmp = composition_table[it->cmp_id];
-
- /* Maybe translate single-byte characters to multibyte. */
- it->char_to_display = it->c;
- if (unibyte_display_via_language_environment
- && SINGLE_BYTE_CHAR_P (it->c)
- && (it->c >= 0240
- || (it->c >= 0200
- && !NILP (Vnonascii_translation_table))))
- {
- it->char_to_display = unibyte_char_to_multibyte (it->c);
- }
-
- /* Get face and font to use. Encode IT->char_to_display. */
- it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
- face = FACE_FROM_ID (it->f, it->face_id);
- x_get_char_face_and_encoding (it->f, it->char_to_display,
- it->face_id, &char2b, it->multibyte_p);
- font = face->font;
-
- /* When no suitable font found, use the default font. */
- font_not_found_p = font == NULL;
- if (font_not_found_p)
- {
- font = FRAME_FONT (it->f);
- boff = it->f->output_data.mac->baseline_offset;
- font_info = NULL;
- }
- else
- {
- font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
- boff = font_info->baseline_offset;
- if (font_info->vertical_centering)
- boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
- }
-
- /* There are no padding glyphs, so there is only one glyph to
- produce for the composition. Important is that pixel_width,
- ascent and descent are the values of what is drawn by
- draw_glyphs (i.e. the values of the overall glyphs composed). */
- it->nglyphs = 1;
-
- /* If we have not yet calculated pixel size data of glyphs of
- the composition for the current face font, calculate them
- now. Theoretically, we have to check all fonts for the
- glyphs, but that requires much time and memory space. So,
- here we check only the font of the first glyph. This leads
- to incorrect display very rarely, and C-l (recenter) can
- correct the display anyway. */
- if (cmp->font != (void *) font)
- {
- /* Ascent and descent of the font of the first character of
- this composition (adjusted by baseline offset). Ascent
- and descent of overall glyphs should not be less than
- them respectively. */
- int font_ascent = font->ascent + boff;
- int font_descent = font->descent - boff;
- /* Bounding box of the overall glyphs. */
- int leftmost, rightmost, lowest, highest;
- int i, width, ascent, descent;
-
- cmp->font = (void *) font;
-
- /* Initialize the bounding box. */
- pcm = x_per_char_metric (font, &char2b);
- if (pcm)
- {
- width = pcm->width;
- ascent = pcm->ascent;
- descent = pcm->descent;
- }
- else
- {
- width = FONT_WIDTH (font);
- ascent = font->ascent;
- descent = font->descent;
- }
-
- rightmost = width;
- lowest = - descent + boff;
- highest = ascent + boff;
- leftmost = 0;
-
- if (font_info
- && font_info->default_ascent
- && CHAR_TABLE_P (Vuse_default_ascent)
- && !NILP (Faref (Vuse_default_ascent,
- make_number (it->char_to_display))))
- highest = font_info->default_ascent + boff;
-
- /* Draw the first glyph at the normal position. It may be
- shifted to right later if some other glyphs are drawn at
- the left. */
- cmp->offsets[0] = 0;
- cmp->offsets[1] = boff;
-
- /* Set cmp->offsets for the remaining glyphs. */
- for (i = 1; i < cmp->glyph_len; i++)
- {
- int left, right, btm, top;
- int ch = COMPOSITION_GLYPH (cmp, i);
- int face_id = FACE_FOR_CHAR (it->f, face, ch);
-
- face = FACE_FROM_ID (it->f, face_id);
- x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
- it->multibyte_p);
- font = face->font;
- if (font == NULL)
- {
- font = FRAME_FONT (it->f);
- boff = it->f->output_data.mac->baseline_offset;
- font_info = NULL;
- }
- else
- {
- font_info
- = FONT_INFO_FROM_ID (it->f, face->font_info_id);
- boff = font_info->baseline_offset;
- if (font_info->vertical_centering)
- boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
- }
-
- pcm = x_per_char_metric (font, &char2b);
- if (pcm)
- {
- width = pcm->width;
- ascent = pcm->ascent;
- descent = pcm->descent;
- }
- else
- {
- width = FONT_WIDTH (font);
- ascent = font->ascent;
- descent = font->descent;
- }
-
- if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
- {
- /* Relative composition with or without
- alternate chars. */
- left = (leftmost + rightmost - width) / 2;
- btm = - descent + boff;
- if (font_info && font_info->relative_compose
- && (! CHAR_TABLE_P (Vignore_relative_composition)
- || NILP (Faref (Vignore_relative_composition,
- make_number (ch)))))
- {
-
- if (- descent >= font_info->relative_compose)
- /* One extra pixel between two glyphs. */
- btm = highest + 1;
- else if (ascent <= 0)
- /* One extra pixel between two glyphs. */
- btm = lowest - 1 - ascent - descent;
- }
- }
- else
- {
- /* A composition rule is specified by an integer
- value that encodes global and new reference
- points (GREF and NREF). GREF and NREF are
- specified by numbers as below:
-
- 0---1---2 -- ascent
- | |
- | |
- | |
- 9--10--11 -- center
- | |
- ---3---4---5--- baseline
- | |
- 6---7---8 -- descent
- */
- int rule = COMPOSITION_RULE (cmp, i);
- int gref, nref, grefx, grefy, nrefx, nrefy;
-
- COMPOSITION_DECODE_RULE (rule, gref, nref);
- grefx = gref % 3, nrefx = nref % 3;
- grefy = gref / 3, nrefy = nref / 3;
-
- left = (leftmost
- + grefx * (rightmost - leftmost) / 2
- - nrefx * width / 2);
- btm = ((grefy == 0 ? highest
- : grefy == 1 ? 0
- : grefy == 2 ? lowest
- : (highest + lowest) / 2)
- - (nrefy == 0 ? ascent + descent
- : nrefy == 1 ? descent - boff
- : nrefy == 2 ? 0
- : (ascent + descent) / 2));
- }
-
- cmp->offsets[i * 2] = left;
- cmp->offsets[i * 2 + 1] = btm + descent;
-
- /* Update the bounding box of the overall glyphs. */
- right = left + width;
- top = btm + descent + ascent;
- if (left < leftmost)
- leftmost = left;
- if (right > rightmost)
- rightmost = right;
- if (top > highest)
- highest = top;
- if (btm < lowest)
- lowest = btm;
- }
-
- /* If there are glyphs whose x-offsets are negative,
- shift all glyphs to the right and make all x-offsets
- non-negative. */
- if (leftmost < 0)
- {
- for (i = 0; i < cmp->glyph_len; i++)
- cmp->offsets[i * 2] -= leftmost;
- rightmost -= leftmost;
- }
-
- cmp->pixel_width = rightmost;
- cmp->ascent = highest;
- cmp->descent = - lowest;
- if (cmp->ascent < font_ascent)
- cmp->ascent = font_ascent;
- if (cmp->descent < font_descent)
- cmp->descent = font_descent;
- }
-
- it->pixel_width = cmp->pixel_width;
- it->ascent = it->phys_ascent = cmp->ascent;
- it->descent = it->phys_descent = cmp->descent;
-
- if (face->box != FACE_NO_BOX)
- {
- int thick = face->box_line_width;
- it->ascent += thick;
- it->descent += thick;
-
- if (it->start_of_box_run_p)
- it->pixel_width += thick;
- if (it->end_of_box_run_p)
- it->pixel_width += thick;
- }
-
- /* If face has an overline, add the height of the overline
- (1 pixel) and a 1 pixel margin to the character height. */
- if (face->overline_p)
- it->ascent += 2;
-
- take_vertical_position_into_account (it);
-
- if (it->glyph_row)
- x_append_composite_glyph (it);
- }
- else if (it->what == IT_IMAGE)
- x_produce_image_glyph (it);
- else if (it->what == IT_STRETCH)
- x_produce_stretch_glyph (it);
-
- /* Accumulate dimensions. Note: can't assume that it->descent > 0
- because this isn't true for images with `:ascent 100'. */
- xassert (it->ascent >= 0 && it->descent >= 0);
- if (it->area == TEXT_AREA)
- it->current_x += it->pixel_width;
-
- it->descent += it->extra_line_spacing;
-
- it->max_ascent = max (it->max_ascent, it->ascent);
- it->max_descent = max (it->max_descent, it->descent);
- it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
- it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
-}
-
-
-/* Estimate the pixel height of the mode or top line on frame F.
- FACE_ID specifies what line's height to estimate. */
-
-int
-x_estimate_mode_line_height (f, face_id)
- struct frame *f;
- enum face_id face_id;
-{
- int height = 1;
-
- /* This function is called so early when Emacs starts that the face
- cache and mode line face are not yet initialized. */
- if (FRAME_FACE_CACHE (f))
- {
- struct face *face = FACE_FROM_ID (f, face_id);
- if (face)
- height = FONT_HEIGHT (face->font) + 2 * face->box_line_width;
- }
-
- return height;
-}
-
-\f
-/***********************************************************************
- Glyph display
- ***********************************************************************/
-
-/* A sequence of glyphs to be drawn in the same face.
-
- This data structure is not really completely X specific, so it
- could possibly, at least partially, be useful for other systems. It
- is currently not part of the external redisplay interface because
- it's not clear what other systems will need. */
-
-struct glyph_string
-{
- /* X-origin of the string. */
- int x;
-
- /* Y-origin and y-position of the base line of this string. */
- int y, ybase;
-
- /* The width of the string, not including a face extension. */
- int width;
-
- /* The width of the string, including a face extension. */
- int background_width;
-
- /* The height of this string. This is the height of the line this
- string is drawn in, and can be different from the height of the
- font the string is drawn in. */
- int height;
-
- /* Number of pixels this string overwrites in front of its x-origin.
- This number is zero if the string has an lbearing >= 0; it is
- -lbearing, if the string has an lbearing < 0. */
- int left_overhang;
-
- /* Number of pixels this string overwrites past its right-most
- nominal x-position, i.e. x + width. Zero if the string's
- rbearing is <= its nominal width, rbearing - width otherwise. */
- int right_overhang;
-
- /* The frame on which the glyph string is drawn. */
- struct frame *f;
-
- /* The window on which the glyph string is drawn. */
- struct window *w;
-
- /* X display and window for convenience. */
- Display *display;
- Window window;
-
- /* The glyph row for which this string was built. It determines the
- y-origin and height of the string. */
- struct glyph_row *row;
-
- /* The area within row. */
- enum glyph_row_area area;
-
- /* Characters to be drawn, and number of characters. */
- XChar2b *char2b;
- int nchars;
-
- /* A face-override for drawing cursors, mouse face and similar. */
- enum draw_glyphs_face hl;
-
- /* Face in which this string is to be drawn. */
- struct face *face;
-
- /* Font in which this string is to be drawn. */
- XFontStruct *font;
-
- /* Font info for this string. */
- struct font_info *font_info;
-
- /* Non-null means this string describes (part of) a composition.
- All characters from char2b are drawn composed. */
- struct composition *cmp;
-
- /* Index of this glyph string's first character in the glyph
- definition of CMP. If this is zero, this glyph string describes
- the first character of a composition. */
- int gidx;
-
- /* 1 means this glyph strings face has to be drawn to the right end
- of the window's drawing area. */
- unsigned extends_to_end_of_line_p : 1;
-
- /* 1 means the background of this string has been drawn. */
- unsigned background_filled_p : 1;
-
- /* 1 means glyph string must be drawn with 16-bit functions. */
- unsigned two_byte_p : 1;
-
- /* 1 means that the original font determined for drawing this glyph
- string could not be loaded. The member `font' has been set to
- the frame's default font in this case. */
- unsigned font_not_found_p : 1;
-
- /* 1 means that the face in which this glyph string is drawn has a
- stipple pattern. */
- unsigned stippled_p : 1;
-
- /* 1 means only the foreground of this glyph string must be drawn,
- and we should use the physical height of the line this glyph
- string appears in as clip rect. */
- unsigned for_overlaps_p : 1;
-
- /* The GC to use for drawing this glyph string. */
- GC gc;
-
- /* A pointer to the first glyph in the string. This glyph
- corresponds to char2b[0]. Needed to draw rectangles if
- font_not_found_p is 1. */
- struct glyph *first_glyph;
-
- /* Image, if any. */
- struct image *img;
-
- struct glyph_string *next, *prev;
-};
-
-
-#if 0
-
-static void
-x_dump_glyph_string (s)
- struct glyph_string *s;
-{
- fprintf (stderr, "glyph string\n");
- fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
- s->x, s->y, s->width, s->height);
- fprintf (stderr, " ybase = %d\n", s->ybase);
- fprintf (stderr, " hl = %d\n", s->hl);
- fprintf (stderr, " left overhang = %d, right = %d\n",
- s->left_overhang, s->right_overhang);
- fprintf (stderr, " nchars = %d\n", s->nchars);
- fprintf (stderr, " extends to end of line = %d\n",
- s->extends_to_end_of_line_p);
- fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
- fprintf (stderr, " bg width = %d\n", s->background_width);
-}
-
-#endif /* GLYPH_DEBUG */
-
-
-
-static void x_append_glyph_string_lists P_ ((struct glyph_string **,
- struct glyph_string **,
- struct glyph_string *,
- struct glyph_string *));
-static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
- struct glyph_string **,
- struct glyph_string *,
- struct glyph_string *));
-static void x_append_glyph_string P_ ((struct glyph_string **,
- struct glyph_string **,
- struct glyph_string *));
-static int x_left_overwritten P_ ((struct glyph_string *));
-static int x_left_overwriting P_ ((struct glyph_string *));
-static int x_right_overwritten P_ ((struct glyph_string *));
-static int x_right_overwriting P_ ((struct glyph_string *));
-static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
- int));
-static void x_init_glyph_string P_ ((struct glyph_string *,
- XChar2b *, struct window *,
- struct glyph_row *,
- enum glyph_row_area, int,
- enum draw_glyphs_face));
-static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
- enum glyph_row_area, int, int,
- enum draw_glyphs_face, int *, int *, int));
-static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
-static void x_set_glyph_string_gc P_ ((struct glyph_string *));
-static void x_draw_glyph_string_background P_ ((struct glyph_string *,
- int));
-static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
-static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
-static void x_draw_glyph_string_box P_ ((struct glyph_string *));
-static void x_draw_glyph_string P_ ((struct glyph_string *));
-static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
-static void x_set_cursor_gc P_ ((struct glyph_string *));
-static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
-static void x_set_mouse_face_gc P_ ((struct glyph_string *));
-static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
- int *, int *));
-static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
-static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
- unsigned long *, double, int));
-static void x_setup_relief_color P_ ((struct frame *, struct relief *,
- double, int, unsigned long));
-static void x_setup_relief_colors P_ ((struct glyph_string *));
-static void x_draw_image_glyph_string P_ ((struct glyph_string *));
-static void x_draw_image_relief P_ ((struct glyph_string *));
-static void x_draw_image_foreground P_ ((struct glyph_string *));
-static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
-static void x_fill_image_glyph_string P_ ((struct glyph_string *));
-static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
- int, int, int));
-static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
- int, int, int, int, XRectangle *));
-static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
- int, int, int, XRectangle *));
-static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
- enum glyph_row_area));
-static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
- struct glyph_row *,
- enum glyph_row_area, int, int));
-
-#if GLYPH_DEBUG
-static void x_check_font P_ ((struct frame *, XFontStruct *));
-#endif
-
-
-/* Append the list of glyph strings with head H and tail T to the list
- with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
-
-static INLINE void
-x_append_glyph_string_lists (head, tail, h, t)
- struct glyph_string **head, **tail;
- struct glyph_string *h, *t;
-{
- if (h)
- {
- if (*head)
- (*tail)->next = h;
- else
- *head = h;
- h->prev = *tail;
- *tail = t;
- }
-}
-
-
-/* Prepend the list of glyph strings with head H and tail T to the
- list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
- result. */
-
-static INLINE void
-x_prepend_glyph_string_lists (head, tail, h, t)
- struct glyph_string **head, **tail;
- struct glyph_string *h, *t;
-{
- if (h)
- {
- if (*head)
- (*head)->prev = t;
- else
- *tail = t;
- t->next = *head;
- *head = h;
- }
-}
-
-
-/* Append glyph string S to the list with head *HEAD and tail *TAIL.
- Set *HEAD and *TAIL to the resulting list. */
-
-static INLINE void
-x_append_glyph_string (head, tail, s)
- struct glyph_string **head, **tail;
- struct glyph_string *s;
-{
- s->next = s->prev = NULL;
- x_append_glyph_string_lists (head, tail, s, s);
-}
-
-
-/* Set S->gc to a suitable GC for drawing glyph string S in cursor
- face. */
-
-static void
-x_set_cursor_gc (s)
- struct glyph_string *s;
-{
- if (s->font == FRAME_FONT (s->f)
- && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
- && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
- && !s->cmp)
- s->gc = s->f->output_data.mac->cursor_gc;
- else
- {
- /* Cursor on non-default face: must merge. */
- XGCValues xgcv;
- unsigned long mask;
-
- xgcv.background = s->f->output_data.mac->cursor_pixel;
- xgcv.foreground = s->face->background;
-
- /* If the glyph would be invisible, try a different foreground. */
- if (xgcv.foreground == xgcv.background)
- xgcv.foreground = s->face->foreground;
- if (xgcv.foreground == xgcv.background)
- xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
- if (xgcv.foreground == xgcv.background)
- xgcv.foreground = s->face->foreground;
-
- /* Make sure the cursor is distinct from text in this face. */
- if (xgcv.background == s->face->background
- && xgcv.foreground == s->face->foreground)
- {
- xgcv.background = s->face->foreground;
- xgcv.foreground = s->face->background;
- }
-
- IF_DEBUG (x_check_font (s->f, s->font));
- xgcv.font = s->font;
- mask = GCForeground | GCBackground | GCFont;
-
- if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
- XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
- mask, &xgcv);
- else
- FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
- = XCreateGC (s->display, s->window, mask, &xgcv);
-
- s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
- }
-}
-
-
-/* Set up S->gc of glyph string S for drawing text in mouse face. */
-
-static void
-x_set_mouse_face_gc (s)
- struct glyph_string *s;
-{
- int face_id;
- struct face *face;
-
- /* What face has to be used for the mouse face? */
- face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
- face = FACE_FROM_ID (s->f, face_id);
- if (s->first_glyph->type == CHAR_GLYPH)
- face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
- else
- face_id = FACE_FOR_CHAR (s->f, face, 0);
- s->face = FACE_FROM_ID (s->f, face_id);
- PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
-
- /* If font in this face is same as S->font, use it. */
- if (s->font == s->face->font)
- s->gc = s->face->gc;
- else
- {
- /* Otherwise construct scratch_cursor_gc with values from FACE
- but font FONT. */
- XGCValues xgcv;
- unsigned long mask;
-
- xgcv.background = s->face->background;
- xgcv.foreground = s->face->foreground;
- IF_DEBUG (x_check_font (s->f, s->font));
- xgcv.font = s->font;
- mask = GCForeground | GCBackground | GCFont;
-
- if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
- XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
- mask, &xgcv);
- else
- FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
- = XCreateGC (s->display, s->window, mask, &xgcv);
-
- s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
- }
-
- xassert (s->gc != 0);
-}
-
-
-/* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
- Faces to use in the mode line have already been computed when the
- matrix was built, so there isn't much to do, here. */
-
-static INLINE void
-x_set_mode_line_face_gc (s)
- struct glyph_string *s;
-{
- s->gc = s->face->gc;
-}
-
-
-/* Set S->gc of glyph string S for drawing that glyph string. Set
- S->stippled_p to a non-zero value if the face of S has a stipple
- pattern. */
-
-static INLINE void
-x_set_glyph_string_gc (s)
- struct glyph_string *s;
-{
- PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
-
- if (s->hl == DRAW_NORMAL_TEXT)
- {
- s->gc = s->face->gc;
- s->stippled_p = s->face->stipple != 0;
- }
- else if (s->hl == DRAW_INVERSE_VIDEO)
- {
- x_set_mode_line_face_gc (s);
- s->stippled_p = s->face->stipple != 0;
- }
- else if (s->hl == DRAW_CURSOR)
- {
- x_set_cursor_gc (s);
- s->stippled_p = 0;
- }
- else if (s->hl == DRAW_MOUSE_FACE)
- {
- x_set_mouse_face_gc (s);
- s->stippled_p = s->face->stipple != 0;
- }
- else if (s->hl == DRAW_IMAGE_RAISED
- || s->hl == DRAW_IMAGE_SUNKEN)
- {
- s->gc = s->face->gc;
- s->stippled_p = s->face->stipple != 0;
- }
- else
- {
- s->gc = s->face->gc;
- s->stippled_p = s->face->stipple != 0;
- }
-
- /* GC must have been set. */
- xassert (s->gc != 0);
-}
-
-
-/* Return in *R the clipping rectangle for glyph string S. */
-
-static void
-x_get_glyph_string_clip_rect (s, r)
- struct glyph_string *s;
- Rect *r;
-{
- int r_height, r_width;
-
- if (s->row->full_width_p)
- {
- /* Draw full-width. X coordinates are relative to S->w->left. */
- int canon_x = CANON_X_UNIT (s->f);
-
- r->left = WINDOW_LEFT_MARGIN (s->w) * canon_x;
- r_width = XFASTINT (s->w->width) * canon_x;
-
- if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
- {
- int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
- if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
- r->left -= width;
- }
-
- r->left += FRAME_INTERNAL_BORDER_WIDTH (s->f);
-
- /* Unless displaying a mode or menu bar line, which are always
- fully visible, clip to the visible part of the row. */
- if (s->w->pseudo_window_p)
- r_height = s->row->visible_height;
- else
- r_height = s->height;
- }
- else
- {
- /* This is a text line that may be partially visible. */
- r->left = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
- r_width = window_box_width (s->w, s->area);
- r_height = s->row->visible_height;
- }
-
- /* Don't use S->y for clipping because it doesn't take partially
- visible lines into account. For example, it can be negative for
- partially visible lines at the top of a window. */
- if (!s->row->full_width_p
- && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
- r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
- else
- r->top = max (0, s->row->y);
-
- /* If drawing a tool-bar window, draw it over the internal border
- at the top of the window. */
- if (s->w == XWINDOW (s->f->tool_bar_window))
- r->top -= s->f->output_data.mac->internal_border_width;
-
- /* If S draws overlapping rows, it's sufficient to use the top and
- bottom of the window for clipping because this glyph string
- intentionally draws over other lines. */
- if (s->for_overlaps_p)
- {
- r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
- r_height = window_text_bottom_y (s->w) - r->top;
- }
-
- r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top);
-
- r->bottom = r->top + r_height;
- r->right = r->left + r_width;
-}
-
-
-/* Set clipping for output of glyph string S. S may be part of a mode
- line or menu if we don't have X toolkit support. */
-
-static INLINE void
-x_set_glyph_string_clipping (s)
- struct glyph_string *s;
-{
- Rect r;
- x_get_glyph_string_clip_rect (s, &r);
- mac_set_clip_rectangle (s->display, s->window, &r);
-}
-
-
-/* Compute left and right overhang of glyph string S. If S is a glyph
- string for a composition, assume overhangs don't exist. */
-
-static INLINE void
-x_compute_glyph_string_overhangs (s)
- struct glyph_string *s;
-{
- if (s->cmp == NULL
- && s->first_glyph->type == CHAR_GLYPH)
- {
- XCharStruct cs;
- int direction, font_ascent, font_descent;
- XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
- &font_ascent, &font_descent, &cs);
- s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
- s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
- }
-}
-
-
-/* Compute overhangs and x-positions for glyph string S and its
- predecessors, or successors. X is the starting x-position for S.
- BACKWARD_P non-zero means process predecessors. */
-
-static void
-x_compute_overhangs_and_x (s, x, backward_p)
- struct glyph_string *s;
- int x;
- int backward_p;
-{
- if (backward_p)
- {
- while (s)
- {
- x_compute_glyph_string_overhangs (s);
- x -= s->width;
- s->x = x;
- s = s->prev;
- }
- }
- else
- {
- while (s)
- {
- x_compute_glyph_string_overhangs (s);
- s->x = x;
- x += s->width;
- s = s->next;
- }
- }
-}
-
-
-/* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
- frame F. Overhangs of glyphs other than type CHAR_GLYPH are
- assumed to be zero. */
-
-void
-x_get_glyph_overhangs (glyph, f, left, right)
- struct glyph *glyph;
- struct frame *f;
- int *left, *right;
-{
- *left = *right = 0;
-
- if (glyph->type == CHAR_GLYPH)
- {
- XFontStruct *font;
- struct face *face;
- struct font_info *font_info;
- XChar2b char2b;
- XCharStruct *pcm;
-
- face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
- font = face->font;
- font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
- if (font
- && (pcm = x_per_char_metric (font, &char2b)))
- {
- if (pcm->rbearing > pcm->width)
- *right = pcm->rbearing - pcm->width;
- if (pcm->lbearing < 0)
- *left = -pcm->lbearing;
- }
- }
-}
-
-
-/* Return the index of the first glyph preceding glyph string S that
- is overwritten by S because of S's left overhang. Value is -1
- if no glyphs are overwritten. */
-
-static int
-x_left_overwritten (s)
- struct glyph_string *s;
-{
- int k;
-
- if (s->left_overhang)
- {
- int x = 0, i;
- struct glyph *glyphs = s->row->glyphs[s->area];
- int first = s->first_glyph - glyphs;
-
- for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
- x -= glyphs[i].pixel_width;
-
- k = i + 1;
- }
- else
- k = -1;
-
- return k;
-}
-
-
-/* Return the index of the first glyph preceding glyph string S that
- is overwriting S because of its right overhang. Value is -1 if no
- glyph in front of S overwrites S. */
-
-static int
-x_left_overwriting (s)
- struct glyph_string *s;
-{
- int i, k, x;
- struct glyph *glyphs = s->row->glyphs[s->area];
- int first = s->first_glyph - glyphs;
-
- k = -1;
- x = 0;
- for (i = first - 1; i >= 0; --i)
- {
- int left, right;
- x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
- if (x + right > 0)
- k = i;
- x -= glyphs[i].pixel_width;
- }
-
- return k;
-}
-
-
-/* Return the index of the last glyph following glyph string S that is
- not overwritten by S because of S's right overhang. Value is -1 if
- no such glyph is found. */
-
-static int
-x_right_overwritten (s)
- struct glyph_string *s;
-{
- int k = -1;
-
- if (s->right_overhang)
- {
- int x = 0, i;
- struct glyph *glyphs = s->row->glyphs[s->area];
- int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
- int end = s->row->used[s->area];
-
- for (i = first; i < end && s->right_overhang > x; ++i)
- x += glyphs[i].pixel_width;
-
- k = i;
- }
-
- return k;
-}
-
-
-/* Return the index of the last glyph following glyph string S that
- overwrites S because of its left overhang. Value is negative
- if no such glyph is found. */
-
-static int
-x_right_overwriting (s)
- struct glyph_string *s;
-{
- int i, k, x;
- int end = s->row->used[s->area];
- struct glyph *glyphs = s->row->glyphs[s->area];
- int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
-
- k = -1;
- x = 0;
- for (i = first; i < end; ++i)
- {
- int left, right;
- x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
- if (x - left < 0)
- k = i;
- x += glyphs[i].pixel_width;
- }
-
- return k;
-}
-
-
-/* Fill rectangle X, Y, W, H with background color of glyph string S. */
-
-static INLINE void
-x_clear_glyph_string_rect (s, x, y, w, h)
- struct glyph_string *s;
- int x, y, w, h;
-{
- XGCValues xgcv;
-
- xgcv.foreground = s->gc->background;
- XFillRectangle (s->display, s->window, &xgcv, x, y, w, h);
-}
-
-
-/* Draw the background of glyph_string S. If S->background_filled_p
- is non-zero don't draw it. FORCE_P non-zero means draw the
- background even if it wouldn't be drawn normally. This is used
- when a string preceding S draws into the background of S, or S
- contains the first component of a composition. */
-
-static void
-x_draw_glyph_string_background (s, force_p)
- struct glyph_string *s;
- int force_p;
-{
- /* Nothing to do if background has already been drawn or if it
- shouldn't be drawn in the first place. */
- if (!s->background_filled_p)
- {
-#if 0 /* MAC_TODO: stipple */
- if (s->stippled_p)
- {
- /* Fill background with a stipple pattern. */
- XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
- XFillRectangle (s->display, s->window, s->gc, s->x,
- s->y + s->face->box_line_width,
- s->background_width,
- s->height - 2 * s->face->box_line_width);
- XSetFillStyle (s->display, s->gc, FillSolid);
- s->background_filled_p = 1;
- }
- else
-#endif
- if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
- || s->font_not_found_p
- || s->extends_to_end_of_line_p
- || force_p)
- {
- x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
- s->background_width,
- s->height - 2 * s->face->box_line_width);
- s->background_filled_p = 1;
- }
- }
-}
-
-
-/* Draw the foreground of glyph string S. */
-
-static void
-x_draw_glyph_string_foreground (s)
- struct glyph_string *s;
-{
- int i, x;
-
- /* If first glyph of S has a left box line, start drawing the text
- of S to the right of that box line. */
- if (s->face->box != FACE_NO_BOX
- && s->first_glyph->left_box_line_p)
- x = s->x + s->face->box_line_width;
- else
- x = s->x;
-
- /* Draw characters of S as rectangles if S's font could not be
- loaded. */
- if (s->font_not_found_p)
- {
- for (i = 0; i < s->nchars; ++i)
- {
- struct glyph *g = s->first_glyph + i;
- mac_draw_rectangle (s->display, s->window,
- s->gc, x, s->y, g->pixel_width - 1,
- s->height - 1);
- x += g->pixel_width;
- }
- }
- else
- {
- char *char1b = (char *) s->char2b;
- int boff = s->font_info->baseline_offset;
-
- if (s->font_info->vertical_centering)
- boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
-
- /* If we can use 8-bit functions, condense S->char2b. */
- if (!s->two_byte_p)
- for (i = 0; i < s->nchars; ++i)
- char1b[i] = s->char2b[i].byte2;
-
- /* Draw text with XDrawString if background has already been
- filled. Otherwise, use XDrawImageString. (Note that
- XDrawImageString is usually faster than XDrawString.) Always
- use XDrawImageString when drawing the cursor so that there is
- no chance that characters under a box cursor are invisible. */
- if (s->for_overlaps_p
- || (s->background_filled_p && s->hl != DRAW_CURSOR))
- {
- /* Draw characters with 16-bit or 8-bit functions. */
- if (s->two_byte_p)
- XDrawString16 (s->display, s->window, s->gc, x,
- s->ybase - boff, s->char2b, s->nchars);
- else
- XDrawString (s->display, s->window, s->gc, x,
- s->ybase - boff, char1b, s->nchars);
- }
- else
- {
- if (s->two_byte_p)
- XDrawImageString16 (s->display, s->window, s->gc, x,
- s->ybase - boff, s->char2b, s->nchars);
- else
- XDrawImageString (s->display, s->window, s->gc, x,
- s->ybase - boff, char1b, s->nchars);
- }
- }
-}
-
-/* Draw the foreground of composite glyph string S. */
-
-static void
-x_draw_composite_glyph_string_foreground (s)
- struct glyph_string *s;
-{
- int i, x;
-
- /* If first glyph of S has a left box line, start drawing the text
- of S to the right of that box line. */
- if (s->face->box != FACE_NO_BOX
- && s->first_glyph->left_box_line_p)
- x = s->x + s->face->box_line_width;
- else
- x = s->x;
-
- /* S is a glyph string for a composition. S->gidx is the index of
- the first character drawn for glyphs of this composition.
- S->gidx == 0 means we are drawing the very first character of
- this composition. */
-
- /* Draw a rectangle for the composition if the font for the very
- first character of the composition could not be loaded. */
- if (s->font_not_found_p)
- {
- if (s->gidx == 0)
- mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
- s->width - 1, s->height - 1);
- }
- else
- {
- for (i = 0; i < s->nchars; i++, ++s->gidx)
- XDrawString16 (s->display, s->window, s->gc,
- x + s->cmp->offsets[s->gidx * 2],
- s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
- s->char2b + i, 1);
- }
-}
-
-
-#ifdef USE_X_TOOLKIT
-
-static struct frame *x_frame_of_widget P_ ((Widget));
-
-
-/* Return the frame on which widget WIDGET is used.. Abort if frame
- cannot be determined. */
-
-static struct frame *
-x_frame_of_widget (widget)
- Widget widget;
-{
- struct x_display_info *dpyinfo;
- Lisp_Object tail;
- struct frame *f;
-
- dpyinfo = x_display_info_for_display (XtDisplay (widget));
-
- /* Find the top-level shell of the widget. Note that this function
- can be called when the widget is not yet realized, so XtWindow
- (widget) == 0. That's the reason we can't simply use
- x_any_window_to_frame. */
- while (!XtIsTopLevelShell (widget))
- widget = XtParent (widget);
-
- /* Look for a frame with that top-level widget. Allocate the color
- on that frame to get the right gamma correction value. */
- for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
- if (GC_FRAMEP (XCAR (tail))
- && (f = XFRAME (XCAR (tail)),
- (f->output_data.nothing != 1
- && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
- && f->output_data.x->widget == widget)
- return f;
-
- abort ();
-}
-
-
-/* Allocate the color COLOR->pixel on the screen and display of
- widget WIDGET in colormap CMAP. If an exact match cannot be
- allocated, try the nearest color available. Value is non-zero
- if successful. This is called from lwlib. */
-
-int
-x_alloc_nearest_color_for_widget (widget, cmap, color)
- Widget widget;
- Colormap cmap;
- XColor *color;
-{
- struct frame *f = x_frame_of_widget (widget);
- return x_alloc_nearest_color (f, cmap, color);
-}
-
-
-#endif /* USE_X_TOOLKIT */
-
-#if 0
-
-/* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
- CMAP. If an exact match can't be allocated, try the nearest color
- available. Value is non-zero if successful. Set *COLOR to the
- color allocated. */
-
-int
-x_alloc_nearest_color (f, cmap, color)
- struct frame *f;
- Colormap cmap;
- XColor *color;
-{
- Display *display = FRAME_X_DISPLAY (f);
- Screen *screen = FRAME_X_SCREEN (f);
- int rc;
-
- gamma_correct (f, color);
- rc = XAllocColor (display, cmap, color);
- if (rc == 0)
- {
- /* If we got to this point, the colormap is full, so we're going
- to try to get the next closest color. The algorithm used is
- a least-squares matching, which is what X uses for closest
- color matching with StaticColor visuals. */
- int nearest, i;
- unsigned long nearest_delta = ~0;
- int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
- XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
-
- for (i = 0; i < ncells; ++i)
- cells[i].pixel = i;
- XQueryColors (display, cmap, cells, ncells);
-
- for (nearest = i = 0; i < ncells; ++i)
- {
- long dred = (color->red >> 8) - (cells[i].red >> 8);
- long dgreen = (color->green >> 8) - (cells[i].green >> 8);
- long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
- unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
-
- if (delta < nearest_delta)
- {
- nearest = i;
- nearest_delta = delta;
- }
- }
-
- color->red = cells[nearest].red;
- color->green = cells[nearest].green;
- color->blue = cells[nearest].blue;
- rc = XAllocColor (display, cmap, color);
- }
-
-#ifdef DEBUG_X_COLORS
- if (rc)
- register_color (color->pixel);
-#endif /* DEBUG_X_COLORS */
-
- return rc;
-}
-
-
-/* Allocate color PIXEL on frame F. PIXEL must already be allocated.
- It's necessary to do this instead of just using PIXEL directly to
- get color reference counts right. */
-
-unsigned long
-x_copy_color (f, pixel)
- struct frame *f;
- unsigned long pixel;
-{
- XColor color;
-
- color.pixel = pixel;
- BLOCK_INPUT;
- XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
- XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
- UNBLOCK_INPUT;
-#ifdef DEBUG_X_COLORS
- register_color (pixel);
-#endif
- return color.pixel;
-}
-
-
-/* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
- It's necessary to do this instead of just using PIXEL directly to
- get color reference counts right. */
-
-unsigned long
-x_copy_dpy_color (dpy, cmap, pixel)
- Display *dpy;
- Colormap cmap;
- unsigned long pixel;
-{
- XColor color;
-
- color.pixel = pixel;
- BLOCK_INPUT;
- XQueryColor (dpy, cmap, &color);
- XAllocColor (dpy, cmap, &color);
- UNBLOCK_INPUT;
-#ifdef DEBUG_X_COLORS
- register_color (pixel);
-#endif
- return color.pixel;
-}
-
-#endif
-
-/* Allocate a color which is lighter or darker than *COLOR by FACTOR
- or DELTA. Try a color with RGB values multiplied by FACTOR first.
- If this produces the same color as COLOR, try a color where all RGB
- values have DELTA added. Return the allocated color in *COLOR.
- DISPLAY is the X display, CMAP is the colormap to operate on.
- Value is non-zero if successful. */
-
-static int
-mac_alloc_lighter_color (f, color, factor, delta)
- struct frame *f;
- unsigned long *color;
- double factor;
- int delta;
-{
- unsigned long new;
-
- /* Change RGB values by specified FACTOR. Avoid overflow! */
- xassert (factor >= 0);
- new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
- min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
- min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
- if (new == *color)
- new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
- max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
- max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
-
- /* MAC_TODO: Map to palette and retry with delta if same? */
- /* MAC_TODO: Free colors (if using palette)? */
-
- if (new == *color)
- return 0;
-
- *color = new;
-
- return 1;
-}
-
-
-/* Set up the foreground color for drawing relief lines of glyph
- string S. RELIEF is a pointer to a struct relief containing the GC
- with which lines will be drawn. Use a color that is FACTOR or
- DELTA lighter or darker than the relief's background which is found
- in S->f->output_data.x->relief_background. If such a color cannot
- be allocated, use DEFAULT_PIXEL, instead. */
-
-static void
-x_setup_relief_color (f, relief, factor, delta, default_pixel)
- struct frame *f;
- struct relief *relief;
- double factor;
- int delta;
- unsigned long default_pixel;
-{
- XGCValues xgcv;
- struct mac_output *di = f->output_data.mac;
- unsigned long mask = GCForeground;
- unsigned long pixel;
- unsigned long background = di->relief_background;
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
-
- /* MAC_TODO: Free colors (if using palette)? */
-
- /* Allocate new color. */
- xgcv.foreground = default_pixel;
- pixel = background;
- if (mac_alloc_lighter_color (f, &pixel, factor, delta))
- {
- relief->allocated_p = 1;
- xgcv.foreground = relief->pixel = pixel;
- }
-
- if (relief->gc == 0)
- {
-#if 0 /* MAC_TODO: stipple */
- xgcv.stipple = dpyinfo->gray;
- mask |= GCStipple;
-#endif
- relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
- }
- else
- XChangeGC (NULL, relief->gc, mask, &xgcv);
-}
-
-
-/* Set up colors for the relief lines around glyph string S. */
-
-static void
-x_setup_relief_colors (s)
- struct glyph_string *s;
-{
- struct mac_output *di = s->f->output_data.mac;
- unsigned long color;
-
- if (s->face->use_box_color_for_shadows_p)
- color = s->face->box_color;
- else
- {
- XGCValues xgcv;
-
- /* Get the background color of the face. */
- XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
- color = xgcv.background;
- }
-
- if (di->white_relief.gc == 0
- || color != di->relief_background)
- {
- di->relief_background = color;
- x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
- WHITE_PIX_DEFAULT (s->f));
- x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
- BLACK_PIX_DEFAULT (s->f));
- }
-}
-
-
-/* Draw a relief on frame F inside the rectangle given by LEFT_X,
- TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
- to draw, it must be >= 0. RAISED_P non-zero means draw a raised
- relief. LEFT_P non-zero means draw a relief on the left side of
- the rectangle. RIGHT_P non-zero means draw a relief on the right
- side of the rectangle. CLIP_RECT is the clipping rectangle to use
- when drawing. */
-
-static void
-x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
- raised_p, left_p, right_p, clip_rect)
- struct frame *f;
- int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
- Rect *clip_rect;
-{
- int i;
- GC gc;
-
- if (raised_p)
- gc = f->output_data.mac->white_relief.gc;
- else
- gc = f->output_data.mac->black_relief.gc;
- mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), clip_rect);
-
- /* Top. */
- for (i = 0; i < width; ++i)
- XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
- left_x + i * left_p, top_y + i,
- right_x + 1 - i * right_p, top_y + i);
-
- /* Left. */
- if (left_p)
- for (i = 0; i < width; ++i)
- XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
- left_x + i, top_y + i, left_x + i, bottom_y - i);
-
- mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
- if (raised_p)
- gc = f->output_data.mac->black_relief.gc;
- else
- gc = f->output_data.mac->white_relief.gc;
- mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), clip_rect);
-
- /* Bottom. */
- for (i = 0; i < width; ++i)
- XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
- left_x + i * left_p, bottom_y - i,
- right_x + 1 - i * right_p, bottom_y - i);
-
- /* Right. */
- if (right_p)
- for (i = 0; i < width; ++i)
- XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
- right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
-
- mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
-}
-
-
-/* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
- RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
- draw, it must be >= 0. LEFT_P non-zero means draw a line on the
- left side of the rectangle. RIGHT_P non-zero means draw a line
- on the right side of the rectangle. CLIP_RECT is the clipping
- rectangle to use when drawing. */
-
-static void
-x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
- left_p, right_p, clip_rect)
- struct glyph_string *s;
- int left_x, top_y, right_x, bottom_y, left_p, right_p;
- Rect *clip_rect;
-{
- XGCValues xgcv;
-
- xgcv.foreground = s->face->box_color;
- mac_set_clip_rectangle (s->display, s->window, clip_rect);
-
- /* Top. */
- XFillRectangle (s->display, s->window, &xgcv,
- left_x, top_y, right_x - left_x, width);
-
- /* Left. */
- if (left_p)
- XFillRectangle (s->display, s->window, &xgcv,
- left_x, top_y, width, bottom_y - top_y);
-
- /* Bottom. */
- XFillRectangle (s->display, s->window, &xgcv,
- left_x, bottom_y - width, right_x - left_x, width);
-
- /* Right. */
- if (right_p)
- XFillRectangle (s->display, s->window, &xgcv,
- right_x - width, top_y, width, bottom_y - top_y);
-
- mac_reset_clipping (s->display, s->window);
-}
-
-
-/* Draw a box around glyph string S. */
-
-static void
-x_draw_glyph_string_box (s)
- struct glyph_string *s;
-{
- int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
- int left_p, right_p;
- struct glyph *last_glyph;
- Rect clip_rect;
-
- last_x = window_box_right (s->w, s->area);
- if (s->row->full_width_p
- && !s->w->pseudo_window_p)
- {
- last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
- if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
- last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
- }
-
- /* The glyph that may have a right box line. */
- last_glyph = (s->cmp || s->img
- ? s->first_glyph
- : s->first_glyph + s->nchars - 1);
-
- width = s->face->box_line_width;
- raised_p = s->face->box == FACE_RAISED_BOX;
- left_x = s->x;
- right_x = ((s->row->full_width_p
- ? last_x - 1
- : min (last_x, s->x + s->background_width) - 1));
- top_y = s->y;
- bottom_y = top_y + s->height - 1;
-
- left_p = (s->first_glyph->left_box_line_p
- || (s->hl == DRAW_MOUSE_FACE
- && (s->prev == NULL
- || s->prev->hl != s->hl)));
- right_p = (last_glyph->right_box_line_p
- || (s->hl == DRAW_MOUSE_FACE
- && (s->next == NULL
- || s->next->hl != s->hl)));
-
- x_get_glyph_string_clip_rect (s, &clip_rect);
-
- if (s->face->box == FACE_SIMPLE_BOX)
- x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
- left_p, right_p, &clip_rect);
- else
- {
- x_setup_relief_colors (s);
- x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
- width, raised_p, left_p, right_p, &clip_rect);
- }
-}
-
-
-/* Draw foreground of image glyph string S. */
-
-static void
-x_draw_image_foreground (s)
- struct glyph_string *s;
-{
- int x;
- int y = s->ybase - image_ascent (s->img, s->face);
-
- /* If first glyph of S has a left box line, start drawing it to the
- right of that line. */
- if (s->face->box != FACE_NO_BOX
- && s->first_glyph->left_box_line_p)
- x = s->x + s->face->box_line_width;
- else
- x = s->x;
-
- /* If there is a margin around the image, adjust x- and y-position
- by that margin. */
- x += s->img->hmargin;
- y += s->img->vmargin;
-
- if (s->img->pixmap)
- {
-#if 0 /* MAC_TODO: image mask */
- if (s->img->mask)
- {
- /* We can't set both a clip mask and use XSetClipRectangles
- because the latter also sets a clip mask. We also can't
- trust on the shape extension to be available
- (XShapeCombineRegion). So, compute the rectangle to draw
- manually. */
- unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
- | GCFunction);
- XGCValues xgcv;
- XRectangle clip_rect, image_rect, r;
-
- xgcv.clip_mask = s->img->mask;
- xgcv.clip_x_origin = x;
- xgcv.clip_y_origin = y;
- xgcv.function = GXcopy;
- XChangeGC (s->display, s->gc, mask, &xgcv);
-
- x_get_glyph_string_clip_rect (s, &clip_rect);
- image_rect.x = x;
- image_rect.y = y;
- image_rect.width = s->img->width;
- image_rect.height = s->img->height;
- if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
- XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
- r.x - x, r.y - y, r.width, r.height, r.x, r.y);
- }
- else
-#endif
- {
- mac_copy_area (s->display, s->img->pixmap, s->window, s->gc,
- 0, 0, s->img->width, s->img->height, x, y);
-
- /* When the image has a mask, we can expect that at
- least part of a mouse highlight or a block cursor will
- be visible. If the image doesn't have a mask, make
- a block cursor visible by drawing a rectangle around
- the image. I believe it's looking better if we do
- nothing here for mouse-face. */
- if (s->hl == DRAW_CURSOR)
- mac_draw_rectangle (s->display, s->window, s->gc, x, y,
- s->img->width - 1, s->img->height - 1);
- }
- }
- else
- /* Draw a rectangle if image could not be loaded. */
- mac_draw_rectangle (s->display, s->window, s->gc, x, y,
- s->img->width - 1, s->img->height - 1);
-}
-
-
-/* Draw a relief around the image glyph string S. */
-
-static void
-x_draw_image_relief (s)
- struct glyph_string *s;
-{
- int x0, y0, x1, y1, thick, raised_p;
- Rect r;
- int x;
- int y = s->ybase - image_ascent (s->img, s->face);
-
- /* If first glyph of S has a left box line, start drawing it to the
- right of that line. */
- if (s->face->box != FACE_NO_BOX
- && s->first_glyph->left_box_line_p)
- x = s->x + s->face->box_line_width;
- else
- x = s->x;
-
- /* If there is a margin around the image, adjust x- and y-position
- by that margin. */
- x += s->img->hmargin;
- y += s->img->vmargin;
-
- if (s->hl == DRAW_IMAGE_SUNKEN
- || s->hl == DRAW_IMAGE_RAISED)
- {
- thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
- raised_p = s->hl == DRAW_IMAGE_RAISED;
- }
- else
- {
- thick = abs (s->img->relief);
- raised_p = s->img->relief > 0;
- }
-
- x0 = x - thick;
- y0 = y - thick;
- x1 = x + s->img->width + thick - 1;
- y1 = y + s->img->height + thick - 1;
-
- x_setup_relief_colors (s);
- x_get_glyph_string_clip_rect (s, &r);
- x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
-}
-
-
-/* Draw the foreground of image glyph string S to PIXMAP. */
-
-static void
-x_draw_image_foreground_1 (s, pixmap)
- struct glyph_string *s;
- Pixmap pixmap;
-{
- int x;
- int y = s->ybase - s->y - image_ascent (s->img, s->face);
-
- /* If first glyph of S has a left box line, start drawing it to the
- right of that line. */
- if (s->face->box != FACE_NO_BOX
- && s->first_glyph->left_box_line_p)
- x = s->face->box_line_width;
- else
- x = 0;
-
- /* If there is a margin around the image, adjust x- and y-position
- by that margin. */
- x += s->img->hmargin;
- y += s->img->vmargin;
-
- if (s->img->pixmap)
- {
-#if 0 /* MAC_TODO: image mask */
- if (s->img->mask)
- {
- /* We can't set both a clip mask and use XSetClipRectangles
- because the latter also sets a clip mask. We also can't
- trust on the shape extension to be available
- (XShapeCombineRegion). So, compute the rectangle to draw
- manually. */
- unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
- | GCFunction);
- XGCValues xgcv;
-
- xgcv.clip_mask = s->img->mask;
- xgcv.clip_x_origin = x;
- xgcv.clip_y_origin = y;
- xgcv.function = GXcopy;
- XChangeGC (s->display, s->gc, mask, &xgcv);
-
- XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
- 0, 0, s->img->width, s->img->height, x, y);
- XSetClipMask (s->display, s->gc, None);
- }
- else
-#endif
- {
- mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
- 0, 0, s->img->width, s->img->height, x, y);
-
- /* When the image has a mask, we can expect that at
- least part of a mouse highlight or a block cursor will
- be visible. If the image doesn't have a mask, make
- a block cursor visible by drawing a rectangle around
- the image. I believe it's looking better if we do
- nothing here for mouse-face. */
- if (s->hl == DRAW_CURSOR)
- mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
- s->img->width - 1, s->img->height - 1);
- }
- }
- else
- /* Draw a rectangle if image could not be loaded. */
- mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
- s->img->width - 1, s->img->height - 1);
-}
-
-
-/* Draw part of the background of glyph string S. X, Y, W, and H
- give the rectangle to draw. */
-
-static void
-x_draw_glyph_string_bg_rect (s, x, y, w, h)
- struct glyph_string *s;
- int x, y, w, h;
-{
-#if 0 /* MAC_TODO: stipple */
- if (s->stippled_p)
- {
- /* Fill background with a stipple pattern. */
- XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
- XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
- XSetFillStyle (s->display, s->gc, FillSolid);
- }
- else
-#endif
- x_clear_glyph_string_rect (s, x, y, w, h);
-}
-
-
-/* Draw image glyph string S.
-
- s->y
- s->x +-------------------------
- | s->face->box
- |
- | +-------------------------
- | | s->img->vmargin
- | |
- | | +-------------------
- | | | the image
-
- */
-
-static void
-x_draw_image_glyph_string (s)
- struct glyph_string *s;
-{
- int x, y;
- int box_line_width = s->face->box_line_width;
- int height;
- Pixmap pixmap = 0;
-
- height = s->height - 2 * box_line_width;
-
- /* Fill background with face under the image. Do it only if row is
- taller than image or if image has a clip mask to reduce
- flickering. */
- s->stippled_p = s->face->stipple != 0;
- if (height > s->img->height
- || s->img->vmargin
- || s->img->hmargin
-#if 0 /* MAC_TODO: image mask */
- || s->img->mask
-#endif
- || s->img->pixmap == 0
- || s->width != s->background_width)
- {
- if (box_line_width && s->first_glyph->left_box_line_p)
- x = s->x + box_line_width;
- else
- x = s->x;
-
- y = s->y + box_line_width;
-
-#if 0 /* MAC_TODO: image mask */
- if (s->img->mask)
- {
- /* Create a pixmap as large as the glyph string Fill it with
- the background color. Copy the image to it, using its
- mask. Copy the temporary pixmap to the display. */
- Screen *screen = FRAME_X_SCREEN (s->f);
- int depth = DefaultDepthOfScreen (screen);
-
- /* Create a pixmap as large as the glyph string. */
- pixmap = XCreatePixmap (s->display, s->window,
- s->background_width,
- s->height, depth);
-
- /* Don't clip in the following because we're working on the
- pixmap. */
- XSetClipMask (s->display, s->gc, None);
-
- /* Fill the pixmap with the background color/stipple. */
- if (s->stippled_p)
- {
- /* Fill background with a stipple pattern. */
- XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
- XFillRectangle (s->display, pixmap, s->gc,
- 0, 0, s->background_width, s->height);
- XSetFillStyle (s->display, s->gc, FillSolid);
- }
- else
- {
- XGCValues xgcv;
- XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
- &xgcv);
- XSetForeground (s->display, s->gc, xgcv.background);
- XFillRectangle (s->display, pixmap, s->gc,
- 0, 0, s->background_width, s->height);
- XSetForeground (s->display, s->gc, xgcv.foreground);
- }
- }
- else
-#endif
- /* Implementation idea: Is it possible to construct a mask?
- We could look at the color at the margins of the image, and
- say that this color is probably the background color of the
- image. */
- x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
-
- s->background_filled_p = 1;
- }
-
- /* Draw the foreground. */
- if (pixmap != 0)
- {
- x_draw_image_foreground_1 (s, pixmap);
- x_set_glyph_string_clipping (s);
- mac_copy_area (s->display, pixmap, s->window, s->gc,
- 0, 0, s->background_width, s->height, s->x, s->y);
- XFreePixmap (s->display, pixmap);
- }
- else
- x_draw_image_foreground (s);
-
- /* If we must draw a relief around the image, do it. */
- if (s->img->relief
- || s->hl == DRAW_IMAGE_RAISED
- || s->hl == DRAW_IMAGE_SUNKEN)
- x_draw_image_relief (s);
-}
-
-
-/* Draw stretch glyph string S. */
-
-static void
-x_draw_stretch_glyph_string (s)
- struct glyph_string *s;
-{
- xassert (s->first_glyph->type == STRETCH_GLYPH);
- s->stippled_p = s->face->stipple != 0;
-
- if (s->hl == DRAW_CURSOR
- && !x_stretch_cursor_p)
- {
- /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
- as wide as the stretch glyph. */
- int width = min (CANON_X_UNIT (s->f), s->background_width);
-
- /* Draw cursor. */
- x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
-
- /* Clear rest using the GC of the original non-cursor face. */
- if (width < s->background_width)
- {
- GC gc = s->face->gc;
- int x = s->x + width, y = s->y;
- int w = s->background_width - width, h = s->height;
- Rect r;
-
- x_get_glyph_string_clip_rect (s, &r);
- mac_set_clip_rectangle (s->display, s->window, &r);
-
-#if 0 /* MAC_TODO: stipple */
- if (s->face->stipple)
- {
- /* Fill background with a stipple pattern. */
- XSetFillStyle (s->display, gc, FillOpaqueStippled);
- XFillRectangle (s->display, s->window, gc, x, y, w, h);
- XSetFillStyle (s->display, gc, FillSolid);
- }
- else
-#endif
- {
- XGCValues xgcv;
- XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
- XSetForeground (s->display, gc, xgcv.background);
- XFillRectangle (s->display, s->window, gc, x, y, w, h);
- XSetForeground (s->display, gc, xgcv.foreground);
- }
- }
- }
- else
- x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
- s->height);
-
- s->background_filled_p = 1;
-}
-
-
-/* Draw glyph string S. */
-
-static void
-x_draw_glyph_string (s)
- struct glyph_string *s;
-{
- /* If S draws into the background of its successor, draw the
- background of the successor first so that S can draw into it.
- This makes S->next use XDrawString instead of XDrawImageString. */
- if (s->next && s->right_overhang && !s->for_overlaps_p)
- {
- xassert (s->next->img == NULL);
- x_set_glyph_string_gc (s->next);
- x_set_glyph_string_clipping (s->next);
- x_draw_glyph_string_background (s->next, 1);
- }
-
- /* Set up S->gc, set clipping and draw S. */
- x_set_glyph_string_gc (s);
- x_set_glyph_string_clipping (s);
-
- switch (s->first_glyph->type)
- {
- case IMAGE_GLYPH:
- x_draw_image_glyph_string (s);
- break;
-
- case STRETCH_GLYPH:
- x_draw_stretch_glyph_string (s);
- break;
-
- case CHAR_GLYPH:
- if (s->for_overlaps_p)
- s->background_filled_p = 1;
- else
- x_draw_glyph_string_background (s, 0);
- x_draw_glyph_string_foreground (s);
- break;
-
- case COMPOSITE_GLYPH:
- if (s->for_overlaps_p || s->gidx > 0)
- s->background_filled_p = 1;
- else
- x_draw_glyph_string_background (s, 1);
- x_draw_composite_glyph_string_foreground (s);
- break;
-
- default:
- abort ();
- }
-
- if (!s->for_overlaps_p)
- {
- /* Draw underline. */
- if (s->face->underline_p)
- {
- unsigned long h = 1;
- unsigned long dy = s->height - h;
-
- if (s->face->underline_defaulted_p)
- XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
- s->width, h);
- else
- {
- XGCValues xgcv;
- XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
- XSetForeground (s->display, s->gc, s->face->underline_color);
- XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
- s->width, h);
- XSetForeground (s->display, s->gc, xgcv.foreground);
- }
- }
-
- /* Draw overline. */
- if (s->face->overline_p)
- {
- unsigned long dy = 0, h = 1;
-
- if (s->face->overline_color_defaulted_p)
- XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
- s->width, h);
- else
- {
- XGCValues xgcv;
- XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
- XSetForeground (s->display, s->gc, s->face->overline_color);
- XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
- s->width, h);
- XSetForeground (s->display, s->gc, xgcv.foreground);
- }
- }
-
- /* Draw strike-through. */
- if (s->face->strike_through_p)
- {
- unsigned long h = 1;
- unsigned long dy = (s->height - h) / 2;
-
- if (s->face->strike_through_color_defaulted_p)
- XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
- s->width, h);
- else
- {
- XGCValues xgcv;
- XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
- XSetForeground (s->display, s->gc, s->face->strike_through_color);
- XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
- s->width, h);
- XSetForeground (s->display, s->gc, xgcv.foreground);
- }
- }
-
- /* Draw relief. */
- if (s->face->box != FACE_NO_BOX)
- x_draw_glyph_string_box (s);
- }
-
- /* Reset clipping. */
- mac_reset_clipping (s->display, s->window);
-}
-
-
-static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
- struct face **, int));
-
-
-/* Fill glyph string S with composition components specified by S->cmp.
-
- FACES is an array of faces for all components of this composition.
- S->gidx is the index of the first component for S.
- OVERLAPS_P non-zero means S should draw the foreground only, and
- use its physical height for clipping.
-
- Value is the index of a component not in S. */
-
-static int
-x_fill_composite_glyph_string (s, faces, overlaps_p)
- struct glyph_string *s;
- struct face **faces;
- int overlaps_p;
-{
- int i;
-
- xassert (s);
-
- s->for_overlaps_p = overlaps_p;
-
- s->face = faces[s->gidx];
- s->font = s->face->font;
- s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
-
- /* For all glyphs of this composition, starting at the offset
- S->gidx, until we reach the end of the definition or encounter a
- glyph that requires the different face, add it to S. */
- ++s->nchars;
- for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
- ++s->nchars;
-
- /* All glyph strings for the same composition has the same width,
- i.e. the width set for the first component of the composition. */
-
- s->width = s->first_glyph->pixel_width;
-
- /* If the specified font could not be loaded, use the frame's
- default font, but record the fact that we couldn't load it in
- the glyph string so that we can draw rectangles for the
- characters of the glyph string. */
- if (s->font == NULL)
- {
- s->font_not_found_p = 1;
- s->font = FRAME_FONT (s->f);
- }
-
- /* Adjust base line for subscript/superscript text. */
- s->ybase += s->first_glyph->voffset;
-
- xassert (s->face && s->face->gc);
-
- /* This glyph string must always be drawn with 16-bit functions. */
- s->two_byte_p = 1;
-
- return s->gidx + s->nchars;
-}
-
-
-/* Fill glyph string S from a sequence of character glyphs.
-
- FACE_ID is the face id of the string. START is the index of the
- first glyph to consider, END is the index of the last + 1.
- OVERLAPS_P non-zero means S should draw the foreground only, and
- use its physical height for clipping.
-
- Value is the index of the first glyph not in S. */
-
-static int
-x_fill_glyph_string (s, face_id, start, end, overlaps_p)
- struct glyph_string *s;
- int face_id;
- int start, end, overlaps_p;
-{
- struct glyph *glyph, *last;
- int voffset;
- int glyph_not_available_p;
-
- xassert (s->f == XFRAME (s->w->frame));
- xassert (s->nchars == 0);
- xassert (start >= 0 && end > start);
-
- s->for_overlaps_p = overlaps_p,
- glyph = s->row->glyphs[s->area] + start;
- last = s->row->glyphs[s->area] + end;
- voffset = glyph->voffset;
-
- glyph_not_available_p = glyph->glyph_not_available_p;
-
- while (glyph < last
- && glyph->type == CHAR_GLYPH
- && glyph->voffset == voffset
- /* Same face id implies same font, nowadays. */
- && glyph->face_id == face_id
- && glyph->glyph_not_available_p == glyph_not_available_p)
- {
- int two_byte_p;
-
- s->face = x_get_glyph_face_and_encoding (s->f, glyph,
- s->char2b + s->nchars,
- &two_byte_p);
- s->two_byte_p = two_byte_p;
- ++s->nchars;
- xassert (s->nchars <= end - start);
- s->width += glyph->pixel_width;
- ++glyph;
- }
-
- s->font = s->face->font;
- s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
-
- /* If the specified font could not be loaded, use the frame's font,
- but record the fact that we couldn't load it in
- S->font_not_found_p so that we can draw rectangles for the
- characters of the glyph string. */
- if (s->font == NULL || glyph_not_available_p)
- {
- s->font_not_found_p = 1;
- s->font = FRAME_FONT (s->f);
- }
-
- /* Adjust base line for subscript/superscript text. */
- s->ybase += voffset;
-
- xassert (s->face && s->face->gc);
- return glyph - s->row->glyphs[s->area];
-}
-
-
-/* Fill glyph string S from image glyph S->first_glyph. */
-
-static void
-x_fill_image_glyph_string (s)
- struct glyph_string *s;
-{
- xassert (s->first_glyph->type == IMAGE_GLYPH);
- s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
- xassert (s->img);
- s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
- s->font = s->face->font;
- s->width = s->first_glyph->pixel_width;
-
- /* Adjust base line for subscript/superscript text. */
- s->ybase += s->first_glyph->voffset;
-}
-
-
-/* Fill glyph string S from a sequence of stretch glyphs.
-
- ROW is the glyph row in which the glyphs are found, AREA is the
- area within the row. START is the index of the first glyph to
- consider, END is the index of the last + 1.
-
- Value is the index of the first glyph not in S. */
-
-static int
-x_fill_stretch_glyph_string (s, row, area, start, end)
- struct glyph_string *s;
- struct glyph_row *row;
- enum glyph_row_area area;
- int start, end;
-{
- struct glyph *glyph, *last;
- int voffset, face_id;
-
- xassert (s->first_glyph->type == STRETCH_GLYPH);
-
- glyph = s->row->glyphs[s->area] + start;
- last = s->row->glyphs[s->area] + end;
- face_id = glyph->face_id;
- s->face = FACE_FROM_ID (s->f, face_id);
- s->font = s->face->font;
- s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
- s->width = glyph->pixel_width;
- voffset = glyph->voffset;
-
- for (++glyph;
- (glyph < last
- && glyph->type == STRETCH_GLYPH
- && glyph->voffset == voffset
- && glyph->face_id == face_id);
- ++glyph)
- s->width += glyph->pixel_width;
-
- /* Adjust base line for subscript/superscript text. */
- s->ybase += voffset;
-
- xassert (s->face && s->face->gc);
- return glyph - s->row->glyphs[s->area];
-}
-
-
-/* Initialize glyph string S. CHAR2B is a suitably allocated vector
- of XChar2b structures for S; it can't be allocated in
- x_init_glyph_string because it must be allocated via `alloca'. W
- is the window on which S is drawn. ROW and AREA are the glyph row
- and area within the row from which S is constructed. START is the
- index of the first glyph structure covered by S. HL is a
- face-override for drawing S. */
-
-static void
-x_init_glyph_string (s, char2b, w, row, area, start, hl)
- struct glyph_string *s;
- XChar2b *char2b;
- struct window *w;
- struct glyph_row *row;
- enum glyph_row_area area;
- int start;
- enum draw_glyphs_face hl;
-{
- bzero (s, sizeof *s);
- s->w = w;
- s->f = XFRAME (w->frame);
- s->display = FRAME_MAC_DISPLAY (s->f);
- s->window = FRAME_MAC_WINDOW (s->f);
- s->char2b = char2b;
- s->hl = hl;
- s->row = row;
- s->area = area;
- s->first_glyph = row->glyphs[area] + start;
- s->height = row->height;
- s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
-
- /* Display the internal border below the tool-bar window. */
- if (s->w == XWINDOW (s->f->tool_bar_window))
- s->y -= s->f->output_data.mac->internal_border_width;
-
- s->ybase = s->y + row->ascent;
-}
-
-
-/* Set background width of glyph string S. START is the index of the
- first glyph following S. LAST_X is the right-most x-position + 1
- in the drawing area. */
-
-static INLINE void
-x_set_glyph_string_background_width (s, start, last_x)
- struct glyph_string *s;
- int start;
- int last_x;
-{
- /* If the face of this glyph string has to be drawn to the end of
- the drawing area, set S->extends_to_end_of_line_p. */
- struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
-
- if (start == s->row->used[s->area]
- && s->hl == DRAW_NORMAL_TEXT
- && ((s->area == TEXT_AREA && s->row->fill_line_p)
- || s->face->background != default_face->background
- || s->face->stipple != default_face->stipple))
- s->extends_to_end_of_line_p = 1;
-
- /* If S extends its face to the end of the line, set its
- background_width to the distance to the right edge of the drawing
- area. */
- if (s->extends_to_end_of_line_p)
- s->background_width = last_x - s->x + 1;
- else
- s->background_width = s->width;
-}
-
-
-/* Add a glyph string for a stretch glyph to the list of strings
- between HEAD and TAIL. START is the index of the stretch glyph in
- row area AREA of glyph row ROW. END is the index of the last glyph
- in that glyph row area. X is the current output position assigned
- to the new glyph string constructed. HL overrides that face of the
- glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
- is the right-most x-position of the drawing area. */
-
-/* SunOS 4 bundled cc, barfed on continuations in the arg lists here
- and below -- keep them on one line. */
-#define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
- do \
- { \
- s = (struct glyph_string *) alloca (sizeof *s); \
- x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
- START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
- x_append_glyph_string (&HEAD, &TAIL, s); \
- s->x = (X); \
- } \
- while (0)
-
-
-/* Add a glyph string for an image glyph to the list of strings
- between HEAD and TAIL. START is the index of the image glyph in
- row area AREA of glyph row ROW. END is the index of the last glyph
- in that glyph row area. X is the current output position assigned
- to the new glyph string constructed. HL overrides that face of the
- glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
- is the right-most x-position of the drawing area. */
-
-#define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
- do \
- { \
- s = (struct glyph_string *) alloca (sizeof *s); \
- x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
- x_fill_image_glyph_string (s); \
- x_append_glyph_string (&HEAD, &TAIL, s); \
- ++START; \
- s->x = (X); \
- } \
- while (0)
-
-
-/* Add a glyph string for a sequence of character glyphs to the list
- of strings between HEAD and TAIL. START is the index of the first
- glyph in row area AREA of glyph row ROW that is part of the new
- glyph string. END is the index of the last glyph in that glyph row
- area. X is the current output position assigned to the new glyph
- string constructed. HL overrides that face of the glyph; e.g. it
- is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
- right-most x-position of the drawing area. */
-
-#define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
- do \
- { \
- int c, face_id; \
- XChar2b *char2b; \
- \
- c = (ROW)->glyphs[AREA][START].u.ch; \
- face_id = (ROW)->glyphs[AREA][START].face_id; \
- \
- s = (struct glyph_string *) alloca (sizeof *s); \
- char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
- x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
- x_append_glyph_string (&HEAD, &TAIL, s); \
- s->x = (X); \
- START = x_fill_glyph_string (s, face_id, START, END, \
- OVERLAPS_P); \
- } \
- while (0)
-
-
-/* Add a glyph string for a composite sequence to the list of strings
- between HEAD and TAIL. START is the index of the first glyph in
- row area AREA of glyph row ROW that is part of the new glyph
- string. END is the index of the last glyph in that glyph row area.
- X is the current output position assigned to the new glyph string
- constructed. HL overrides that face of the glyph; e.g. it is
- DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
- x-position of the drawing area. */
-
-#define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
- do { \
- int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
- int face_id = (ROW)->glyphs[AREA][START].face_id; \
- struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
- struct composition *cmp = composition_table[cmp_id]; \
- int glyph_len = cmp->glyph_len; \
- XChar2b *char2b; \
- struct face **faces; \
- struct glyph_string *first_s = NULL; \
- int n; \
- \
- base_face = base_face->ascii_face; \
- char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
- faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
- /* At first, fill in `char2b' and `faces'. */ \
- for (n = 0; n < glyph_len; n++) \
- { \
- int c = COMPOSITION_GLYPH (cmp, n); \
- int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
- faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
- x_get_char_face_and_encoding (XFRAME (w->frame), c, \
- this_face_id, char2b + n, 1); \
- } \
- \
- /* Make glyph_strings for each glyph sequence that is drawable by \
- the same face, and append them to HEAD/TAIL. */ \
- for (n = 0; n < cmp->glyph_len;) \
- { \
- s = (struct glyph_string *) alloca (sizeof *s); \
- x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
- x_append_glyph_string (&(HEAD), &(TAIL), s); \
- s->cmp = cmp; \
- s->gidx = n; \
- s->x = (X); \
- \
- if (n == 0) \
- first_s = s; \
- \
- n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
- } \
- \
- ++START; \
- s = first_s; \
- } while (0)
-
-
-/* Build a list of glyph strings between HEAD and TAIL for the glyphs
- of AREA of glyph row ROW on window W between indices START and END.
- HL overrides the face for drawing glyph strings, e.g. it is
- DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
- x-positions of the drawing area.
-
- This is an ugly monster macro construct because we must use alloca
- to allocate glyph strings (because x_draw_glyphs can be called
- asynchronously). */
-
-#define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
- do \
- { \
- HEAD = TAIL = NULL; \
- while (START < END) \
- { \
- struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
- switch (first_glyph->type) \
- { \
- case CHAR_GLYPH: \
- BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
- TAIL, HL, X, LAST_X, \
- OVERLAPS_P); \
- break; \
- \
- case COMPOSITE_GLYPH: \
- BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
- HEAD, TAIL, HL, X, LAST_X,\
- OVERLAPS_P); \
- break; \
- \
- case STRETCH_GLYPH: \
- BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
- HEAD, TAIL, HL, X, LAST_X); \
- break; \
- \
- case IMAGE_GLYPH: \
- BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
- TAIL, HL, X, LAST_X); \
- break; \
- \
- default: \
- abort (); \
- } \
- \
- x_set_glyph_string_background_width (s, START, LAST_X); \
- (X) += s->width; \
- } \
- } \
- while (0)
-
-
-/* Draw glyphs between START and END in AREA of ROW on window W,
- starting at x-position X. X is relative to AREA in W. HL is a
- face-override with the following meaning:
-
- DRAW_NORMAL_TEXT draw normally
- DRAW_CURSOR draw in cursor face
- DRAW_MOUSE_FACE draw in mouse face.
- DRAW_INVERSE_VIDEO draw in mode line face
- DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
- DRAW_IMAGE_RAISED draw an image with a raised relief around it
-
- If REAL_START is non-null, return in *REAL_START the real starting
- position for display. This can be different from START in case
- overlapping glyphs must be displayed. If REAL_END is non-null,
- return in *REAL_END the real end position for display. This can be
- different from END in case overlapping glyphs must be displayed.
-
- If OVERLAPS_P is non-zero, draw only the foreground of characters
- and clip to the physical height of ROW.
-
- Value is the x-position reached, relative to AREA of W. */
-
-static int
-x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
- overlaps_p)
- struct window *w;
- int x;
- struct glyph_row *row;
- enum glyph_row_area area;
- int start, end;
- enum draw_glyphs_face hl;
- int *real_start, *real_end;
- int overlaps_p;
-{
- struct glyph_string *head, *tail;
- struct glyph_string *s;
- int last_x, area_width;
- int x_reached;
- int i, j;
-
- /* Let's rather be paranoid than getting a SEGV. */
- start = max (0, start);
- end = min (end, row->used[area]);
- if (real_start)
- *real_start = start;
- if (real_end)
- *real_end = end;
-
- /* Translate X to frame coordinates. Set last_x to the right
- end of the drawing area. */
- if (row->full_width_p)
- {
- /* X is relative to the left edge of W, without scroll bars
- or fringes. */
- struct frame *f = XFRAME (w->frame);
- int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
-
- x += window_left_x;
- area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
- last_x = window_left_x + area_width;
-
- if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
- {
- int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
- if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
- last_x += width;
- else
- x -= width;
- }
-
- x += FRAME_INTERNAL_BORDER_WIDTH (f);
- last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
- }
- else
- {
- x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
- area_width = window_box_width (w, area);
- last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
- }
-
- /* Build a doubly-linked list of glyph_string structures between
- head and tail from what we have to draw. Note that the macro
- BUILD_GLYPH_STRINGS will modify its start parameter. That's
- the reason we use a separate variable `i'. */
- i = start;
- BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
- overlaps_p);
- if (tail)
- x_reached = tail->x + tail->background_width;
- else
- x_reached = x;
-
- /* If there are any glyphs with lbearing < 0 or rbearing > width in
- the row, redraw some glyphs in front or following the glyph
- strings built above. */
- if (!overlaps_p && row->contains_overlapping_glyphs_p)
- {
- int dummy_x = 0;
- struct glyph_string *h, *t;
-
- /* Compute overhangs for all glyph strings. */
- for (s = head; s; s = s->next)
- x_compute_glyph_string_overhangs (s);
-
- /* Prepend glyph strings for glyphs in front of the first glyph
- string that are overwritten because of the first glyph
- string's left overhang. The background of all strings
- prepended must be drawn because the first glyph string
- draws over it. */
- i = x_left_overwritten (head);
- if (i >= 0)
- {
- j = i;
- BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
- DRAW_NORMAL_TEXT, dummy_x, last_x,
- overlaps_p);
- start = i;
- if (real_start)
- *real_start = start;
- x_compute_overhangs_and_x (t, head->x, 1);
- x_prepend_glyph_string_lists (&head, &tail, h, t);
- }
-
- /* Prepend glyph strings for glyphs in front of the first glyph
- string that overwrite that glyph string because of their
- right overhang. For these strings, only the foreground must
- be drawn, because it draws over the glyph string at `head'.
- The background must not be drawn because this would overwrite
- right overhangs of preceding glyphs for which no glyph
- strings exist. */
- i = x_left_overwriting (head);
- if (i >= 0)
- {
- BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
- DRAW_NORMAL_TEXT, dummy_x, last_x,
- overlaps_p);
- for (s = h; s; s = s->next)
- s->background_filled_p = 1;
- if (real_start)
- *real_start = i;
- x_compute_overhangs_and_x (t, head->x, 1);
- x_prepend_glyph_string_lists (&head, &tail, h, t);
- }
-
- /* Append glyphs strings for glyphs following the last glyph
- string tail that are overwritten by tail. The background of
- these strings has to be drawn because tail's foreground draws
- over it. */
- i = x_right_overwritten (tail);
- if (i >= 0)
- {
- BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
- DRAW_NORMAL_TEXT, x, last_x,
- overlaps_p);
- x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
- x_append_glyph_string_lists (&head, &tail, h, t);
- if (real_end)
- *real_end = i;
- }
-
- /* Append glyph strings for glyphs following the last glyph
- string tail that overwrite tail. The foreground of such
- glyphs has to be drawn because it writes into the background
- of tail. The background must not be drawn because it could
- paint over the foreground of following glyphs. */
- i = x_right_overwriting (tail);
- if (i >= 0)
- {
- BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
- DRAW_NORMAL_TEXT, x, last_x,
- overlaps_p);
- for (s = h; s; s = s->next)
- s->background_filled_p = 1;
- x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
- x_append_glyph_string_lists (&head, &tail, h, t);
- if (real_end)
- *real_end = i;
- }
- }
-
- /* Draw all strings. */
- for (s = head; s; s = s->next)
- x_draw_glyph_string (s);
-
- /* Value is the x-position up to which drawn, relative to AREA of W.
- This doesn't include parts drawn because of overhangs. */
- x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
- if (!row->full_width_p)
- {
- if (area > LEFT_MARGIN_AREA)
- x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
- if (area > TEXT_AREA)
- x_reached -= window_box_width (w, TEXT_AREA);
- }
- return x_reached;
-}
-
-
-/* Fix the display of area AREA of overlapping row ROW in window W. */
-
-void
-x_fix_overlapping_area (w, row, area)
- struct window *w;
- struct glyph_row *row;
- enum glyph_row_area area;
-{
- int i, x;
-
- BLOCK_INPUT;
-
- if (area == LEFT_MARGIN_AREA)
- x = 0;
- else if (area == TEXT_AREA)
- x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
- else
- x = (window_box_width (w, LEFT_MARGIN_AREA)
- + window_box_width (w, TEXT_AREA));
-
- for (i = 0; i < row->used[area];)
- {
- if (row->glyphs[area][i].overlaps_vertically_p)
- {
- int start = i, start_x = x;
-
- do
- {
- x += row->glyphs[area][i].pixel_width;
- ++i;
- }
- while (i < row->used[area]
- && row->glyphs[area][i].overlaps_vertically_p);
-
- x_draw_glyphs (w, start_x, row, area, start, i,
- (row->inverse_p
- ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
- NULL, NULL, 1);
- }
- else
- {
- x += row->glyphs[area][i].pixel_width;
- ++i;
- }
- }
-
- UNBLOCK_INPUT;
-}
-
-
-/* Output LEN glyphs starting at START at the nominal cursor position.
- Advance the nominal cursor over the text. The global variable
- updated_window contains the window being updated, updated_row is
- the glyph row being updated, and updated_area is the area of that
- row being updated. */
-
-void
-x_write_glyphs (start, len)
- struct glyph *start;
- int len;
-{
- int x, hpos, real_start, real_end;
-
- xassert (updated_window && updated_row);
- BLOCK_INPUT;
-
- /* Write glyphs. */
-
- hpos = start - updated_row->glyphs[updated_area];
- x = x_draw_glyphs (updated_window, output_cursor.x,
- updated_row, updated_area,
- hpos, hpos + len,
- (updated_row->inverse_p
- ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
- &real_start, &real_end, 0);
-
- /* If we drew over the cursor, note that it is not visible any more. */
- note_overwritten_text_cursor (updated_window, real_start,
- real_end - real_start);
-
- UNBLOCK_INPUT;
-
- /* Advance the output cursor. */
- output_cursor.hpos += len;
- output_cursor.x = x;
-}
-
-
-/* Insert LEN glyphs from START at the nominal cursor position. */
-
-void
-x_insert_glyphs (start, len)
- struct glyph *start;
- register int len;
-{
- struct frame *f;
- struct window *w;
- int line_height, shift_by_width, shifted_region_width;
- struct glyph_row *row;
- struct glyph *glyph;
- int frame_x, frame_y, hpos, real_start, real_end;
-
- xassert (updated_window && updated_row);
- BLOCK_INPUT;
- w = updated_window;
- f = XFRAME (WINDOW_FRAME (w));
-
- /* Get the height of the line we are in. */
- row = updated_row;
- line_height = row->height;
-
- /* Get the width of the glyphs to insert. */
- shift_by_width = 0;
- for (glyph = start; glyph < start + len; ++glyph)
- shift_by_width += glyph->pixel_width;
-
- /* Get the width of the region to shift right. */
- shifted_region_width = (window_box_width (w, updated_area)
- - output_cursor.x
- - shift_by_width);
-
- /* Shift right. */
- frame_x = WINDOW_TO_FRAME_PIXEL_X (w, output_cursor.x);
- frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
-
- mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
- f->output_data.mac->normal_gc,
- frame_x, frame_y,
- shifted_region_width, line_height,
- frame_x + shift_by_width, frame_y);
-
- /* Write the glyphs. */
- hpos = start - row->glyphs[updated_area];
- x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
- DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
- note_overwritten_text_cursor (w, real_start, real_end - real_start);
-
- /* Advance the output cursor. */
- output_cursor.hpos += len;
- output_cursor.x += shift_by_width;
- UNBLOCK_INPUT;
-}
-
-
-/* Delete N glyphs at the nominal cursor position. Not implemented
- for X frames. */
-
-void
-x_delete_glyphs (n)
- register int n;
-{
- abort ();
-}
-
-
-/* Erase the current text line from the nominal cursor position
- (inclusive) to pixel column TO_X (exclusive). The idea is that
- everything from TO_X onward is already erased.
-
- TO_X is a pixel position relative to updated_area of
- updated_window. TO_X == -1 means clear to the end of this area. */
-
-void
-x_clear_end_of_line (to_x)
- int to_x;
-{
- struct frame *f;
- struct window *w = updated_window;
- int max_x, min_y, max_y;
- int from_x, from_y, to_y;
-
- xassert (updated_window && updated_row);
- f = XFRAME (w->frame);
-
- if (updated_row->full_width_p)
- {
- max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
- if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
- && !w->pseudo_window_p)
- max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
- }
- else
- max_x = window_box_width (w, updated_area);
- max_y = window_text_bottom_y (w);
-
- /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
- of window. For TO_X > 0, truncate to end of drawing area. */
- if (to_x == 0)
- return;
- else if (to_x < 0)
- to_x = max_x;
- else
- to_x = min (to_x, max_x);
-
- to_y = min (max_y, output_cursor.y + updated_row->height);
-
- /* Notice if the cursor will be cleared by this operation. */
- if (!updated_row->full_width_p)
- note_overwritten_text_cursor (w, output_cursor.hpos, -1);
-
- from_x = output_cursor.x;
-
- /* Translate to frame coordinates. */
- if (updated_row->full_width_p)
- {
- from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
- to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
- }
- else
- {
- from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
- to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
- }
-
- min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
- from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
- to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
-
- /* Prevent inadvertently clearing to end of the X window. */
- if (to_x > from_x && to_y > from_y)
- {
- BLOCK_INPUT;
- XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
- from_x, from_y, to_x - from_x, to_y - from_y,
- 0);
- UNBLOCK_INPUT;
- }
-}
-
-
-/* Clear entire frame. If updating_frame is non-null, clear that
- frame. Otherwise clear the selected frame. */
-
-void
-x_clear_frame ()
-{
- struct frame *f;
-
- if (updating_frame)
- f = updating_frame;
- else
- f = SELECTED_FRAME ();
-
- /* Clearing the frame will erase any cursor, so mark them all as no
- longer visible. */
- mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
- output_cursor.hpos = output_cursor.vpos = 0;
- output_cursor.x = -1;
-
- /* We don't set the output cursor here because there will always
- follow an explicit cursor_to. */
- BLOCK_INPUT;
- XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
-
-#if 0 /* Clearing frame on Mac OS clears scroll bars. */
- /* We have to clear the scroll bars, too. If we have changed
- colors or something like that, then they should be notified. */
- x_scroll_bar_clear (f);
-#endif
-
- XFlush (FRAME_MAC_DISPLAY (f));
- UNBLOCK_INPUT;
-}
-
-
-\f
-/* Invert the middle quarter of the frame for .15 sec. */
-
-/* We use the select system call to do the waiting, so we have to make
- sure it's available. If it isn't, we just won't do visual bells. */
-
-#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
-
-/* Subtract the `struct timeval' values X and Y, storing the result in
- *RESULT. Return 1 if the difference is negative, otherwise 0. */
-
-static int
-timeval_subtract (result, x, y)
- struct timeval *result, x, y;
-{
- /* Perform the carry for the later subtraction by updating y. This
- is safer because on some systems the tv_sec member is unsigned. */
- if (x.tv_usec < y.tv_usec)
- {
- int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
- y.tv_usec -= 1000000 * nsec;
- y.tv_sec += nsec;
- }
-
- if (x.tv_usec - y.tv_usec > 1000000)
- {
- int nsec = (y.tv_usec - x.tv_usec) / 1000000;
- y.tv_usec += 1000000 * nsec;
- y.tv_sec -= nsec;
- }
-
- /* Compute the time remaining to wait. tv_usec is certainly
- positive. */
- result->tv_sec = x.tv_sec - y.tv_sec;
- result->tv_usec = x.tv_usec - y.tv_usec;
-
- /* Return indication of whether the result should be considered
- negative. */
- return x.tv_sec < y.tv_sec;
-}
-
-void
-XTflash (f)
- struct frame *f;
-{
- BLOCK_INPUT;
-
- FlashMenuBar (0);
-
- {
- struct timeval wakeup;
-
- EMACS_GET_TIME (wakeup);
-
- /* Compute time to wait until, propagating carry from usecs. */
- wakeup.tv_usec += 150000;
- wakeup.tv_sec += (wakeup.tv_usec / 1000000);
- wakeup.tv_usec %= 1000000;
-
- /* Keep waiting until past the time wakeup. */
- while (1)
- {
- struct timeval timeout;
-
- EMACS_GET_TIME (timeout);
-
- /* In effect, timeout = wakeup - timeout.
- Break if result would be negative. */
- if (timeval_subtract (&timeout, wakeup, timeout))
- break;
-
- /* Try to wait that long--but we might wake up sooner. */
- select (0, NULL, NULL, NULL, &timeout);
- }
- }
-
- FlashMenuBar (0);
-
- UNBLOCK_INPUT;
-}
-
-#endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
-
-
-/* Make audible bell. */
-
-void
-XTring_bell ()
-{
- struct frame *f = SELECTED_FRAME ();
-
-#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
- if (visible_bell)
- XTflash (f);
- else
-#endif
- {
- BLOCK_INPUT;
- SysBeep (1);
- XFlush (FRAME_MAC_DISPLAY (f));
- UNBLOCK_INPUT;
- }
-}
-
-
-\f
-/* Specify how many text lines, from the top of the window,
- should be affected by insert-lines and delete-lines operations.
- This, and those operations, are used only within an update
- that is bounded by calls to x_update_begin and x_update_end. */
-
-void
-XTset_terminal_window (n)
- register int n;
-{
- /* This function intentionally left blank. */
-}
-
-
-\f
-/***********************************************************************
- Line Dance
- ***********************************************************************/
-
-/* Perform an insert-lines or delete-lines operation, inserting N
- lines or deleting -N lines at vertical position VPOS. */
-
-void
-x_ins_del_lines (vpos, n)
- int vpos, n;
-{
- abort ();
-}
-
-
-/* Scroll part of the display as described by RUN. */
-
-void
-x_scroll_run (w, run)
- struct window *w;
- struct run *run;
-{
- struct frame *f = XFRAME (w->frame);
- int x, y, width, height, from_y, to_y, bottom_y;
-
- /* Get frame-relative bounding box of the text display area of W,
- without mode lines. Include in this box the left and right
- fringes of W. */
- window_box (w, -1, &x, &y, &width, &height);
- width += FRAME_X_FRINGE_WIDTH (f);
- x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
-
- from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
- to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
- bottom_y = y + height;
-
- if (to_y < from_y)
- {
- /* Scrolling up. Make sure we don't copy part of the mode
- line at the bottom. */
- if (from_y + run->height > bottom_y)
- height = bottom_y - from_y;
- else
- height = run->height;
- }
- else
- {
- /* Scolling down. Make sure we don't copy over the mode line.
- at the bottom. */
- if (to_y + run->height > bottom_y)
- height = bottom_y - to_y;
- else
- height = run->height;
- }
-
- BLOCK_INPUT;
-
- /* Cursor off. Will be switched on again in x_update_window_end. */
- updated_window = w;
- x_clear_cursor (w);
-
- mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
- f->output_data.mac->normal_gc,
- x, from_y,
- width, height,
- x, to_y);
-
- UNBLOCK_INPUT;
-}
-
-
-\f
-/***********************************************************************
- Exposure Events
- ***********************************************************************/
-
-/* Redisplay an exposed area of frame F. X and Y are the upper-left
- corner of the exposed rectangle. W and H are width and height of
- the exposed area. All are pixel values. W or H zero means redraw
- the entire frame. */
-
-static void
-expose_frame (f, x, y, w, h)
- struct frame *f;
- int x, y, w, h;
-{
- Rect r;
-
- TRACE ((stderr, "expose_frame "));
-
- /* No need to redraw if frame will be redrawn soon. */
- if (FRAME_GARBAGED_P (f))
- {
- TRACE ((stderr, " garbaged\n"));
- return;
- }
-
- /* MAC_TODO: this is a kludge, but if scroll bars are not activated
- or deactivated here, for unknown reasons, activated scroll bars
- are shown in deactivated frames in some instances. */
- if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
- activate_scroll_bars (f);
- else
- deactivate_scroll_bars (f);
-
- /* If basic faces haven't been realized yet, there is no point in
- trying to redraw anything. This can happen when we get an expose
- event while Emacs is starting, e.g. by moving another window. */
- if (FRAME_FACE_CACHE (f) == NULL
- || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
- {
- TRACE ((stderr, " no faces\n"));
- return;
- }
-
- if (w == 0 || h == 0)
- {
- r.left = r.top = 0;
- r.right = CANON_X_UNIT (f) * f->width;
- r.bottom = CANON_Y_UNIT (f) * f->height;
- }
- else
- {
- r.left = x;
- r.top = y;
- r.right = x + w;
- r.bottom = y + h;
- }
-
- TRACE ((stderr, "(%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom));
- expose_window_tree (XWINDOW (f->root_window), &r);
-
- if (WINDOWP (f->tool_bar_window))
- {
- struct window *w = XWINDOW (f->tool_bar_window);
- Rect window_rect;
- Rect intersection_rect;
- int window_x, window_y, window_width, window_height;
-
-
- window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
- window_rect.left = window_x;
- window_rect.top = window_y;
- window_rect.right = window_x + window_width;
- window_rect.bottom = window_y + window_height;
-
- if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
- expose_window (w, &intersection_rect);
- }
-
-#ifndef USE_X_TOOLKIT
- if (WINDOWP (f->menu_bar_window))
- {
- struct window *w = XWINDOW (f->menu_bar_window);
- Rect window_rect;
- Rect intersection_rect;
- int window_x, window_y, window_width, window_height;
-
-
- window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
- window_rect.left = window_x;
- window_rect.top = window_y;
- window_rect.right = window_x + window_width;
- window_rect.bottom = window_y + window_height;
-
- if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
- expose_window (w, &intersection_rect);
- }
-#endif /* not USE_X_TOOLKIT */
-}
-
-
-/* Redraw (parts) of all windows in the window tree rooted at W that
- intersect R. R contains frame pixel coordinates. */
-
-static void
-expose_window_tree (w, r)
- struct window *w;
- Rect *r;
-{
- while (w)
- {
- if (!NILP (w->hchild))
- expose_window_tree (XWINDOW (w->hchild), r);
- else if (!NILP (w->vchild))
- expose_window_tree (XWINDOW (w->vchild), r);
- else
- {
- Rect window_rect;
- Rect intersection_rect;
- struct frame *f = XFRAME (w->frame);
- int window_x, window_y, window_width, window_height;
-
- /* Frame-relative pixel rectangle of W. */
- window_box (w, -1, &window_x, &window_y, &window_width,
- &window_height);
- window_rect.left
- = (window_x
- - FRAME_X_LEFT_FRINGE_WIDTH (f)
- - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_Y_UNIT (f));
- window_rect.top = window_y;
- window_rect.right = window_rect.left
- + (window_width
- + FRAME_X_FRINGE_WIDTH (f)
- + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
- window_rect.bottom = window_rect.top
- + window_height + CURRENT_MODE_LINE_HEIGHT (w);
-
- if (x_intersect_rectangles (r, &window_rect, &intersection_rect))
- expose_window (w, &intersection_rect);
- }
-
- w = NILP (w->next) ? 0 : XWINDOW (w->next);
- }
-}
-
-
-/* Redraw the part of glyph row area AREA of glyph row ROW on window W
- which intersects rectangle R. R is in window-relative coordinates. */
-
-static void
-expose_area (w, row, r, area)
- struct window *w;
- struct glyph_row *row;
- Rect *r;
- enum glyph_row_area area;
-{
- int x;
- struct glyph *first = row->glyphs[area];
- struct glyph *end = row->glyphs[area] + row->used[area];
- struct glyph *last;
- int first_x;
-
- /* Set x to the window-relative start position for drawing glyphs of
- AREA. The first glyph of the text area can be partially visible.
- The first glyphs of other areas cannot. */
- if (area == LEFT_MARGIN_AREA)
- x = 0;
- else if (area == TEXT_AREA)
- x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
- else
- x = (window_box_width (w, LEFT_MARGIN_AREA)
- + window_box_width (w, TEXT_AREA));
-
- if (area == TEXT_AREA && row->fill_line_p)
- /* If row extends face to end of line write the whole line. */
- x_draw_glyphs (w, x, row, area,
- 0, row->used[area],
- row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
- NULL, NULL, 0);
- else
- {
- /* Find the first glyph that must be redrawn. */
- while (first < end
- && x + first->pixel_width < r->left)
- {
- x += first->pixel_width;
- ++first;
- }
-
- /* Find the last one. */
- last = first;
- first_x = x;
- while (last < end
- && x < r->right)
- {
- x += last->pixel_width;
- ++last;
- }
-
- /* Repaint. */
- if (last > first)
- x_draw_glyphs (w, first_x, row, area,
- first - row->glyphs[area],
- last - row->glyphs[area],
- row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
- NULL, NULL, 0);
- }
-}
-
-
-/* Redraw the parts of the glyph row ROW on window W intersecting
- rectangle R. R is in window-relative coordinates. */
-
-static void
-expose_line (w, row, r)
- struct window *w;
- struct glyph_row *row;
- Rect *r;
-{
- xassert (row->enabled_p);
-
- if (row->mode_line_p || w->pseudo_window_p)
- x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
- row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
- NULL, NULL, 0);
- else
- {
- if (row->used[LEFT_MARGIN_AREA])
- expose_area (w, row, r, LEFT_MARGIN_AREA);
- if (row->used[TEXT_AREA])
- expose_area (w, row, r, TEXT_AREA);
- if (row->used[RIGHT_MARGIN_AREA])
- expose_area (w, row, r, RIGHT_MARGIN_AREA);
- x_draw_row_fringe_bitmaps (w, row);
- }
-}
-
-
-/* Return non-zero if W's cursor intersects rectangle R. */
-
-static int
-x_phys_cursor_in_rect_p (w, r)
- struct window *w;
- Rect *r;
-{
- Rect cr, result;
- struct glyph *cursor_glyph;
-
- cursor_glyph = get_phys_cursor_glyph (w);
- if (cursor_glyph)
- {
- cr.left = w->phys_cursor.x;
- cr.top = w->phys_cursor.y;
- cr.right = cr.left + cursor_glyph->pixel_width;
- cr.bottom = cr.top + w->phys_cursor_height;
- return x_intersect_rectangles (&cr, r, &result);
- }
- else
- return 0;
-}
-
-
-/* Redraw a rectangle of window W. R is a rectangle in window
- relative coordinates. Call this function with input blocked. */
-
-static void
-expose_window (w, r)
- struct window *w;
- Rect *r;
-{
- struct glyph_row *row;
- int y;
- int yb = window_text_bottom_y (w);
- int cursor_cleared_p;
-
- /* If window is not yet fully initialized, do nothing. This can
- happen when toolkit scroll bars are used and a window is split.
- Reconfiguring the scroll bar will generate an expose for a newly
- created window. */
- if (w->current_matrix == NULL)
- return;
-
- TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
- r->left, r->top, r->right, r->bottom));
-
- /* Convert to window coordinates. */
- r->left = FRAME_TO_WINDOW_PIXEL_X (w, r->left);
- r->top = FRAME_TO_WINDOW_PIXEL_Y (w, r->top);
- r->right = FRAME_TO_WINDOW_PIXEL_X (w, r->right);
- r->bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r->bottom);
-
- /* Turn off the cursor. */
- if (!w->pseudo_window_p
- && x_phys_cursor_in_rect_p (w, r))
- {
- x_clear_cursor (w);
- cursor_cleared_p = 1;
- }
- else
- cursor_cleared_p = 0;
-
- /* Find the first row intersecting the rectangle R. */
- row = w->current_matrix->rows;
- y = 0;
- while (row->enabled_p
- && y < yb
- && y + row->height < r->top)
- {
- y += row->height;
- ++row;
- }
-
- /* Display the text in the rectangle, one text line at a time. */
- while (row->enabled_p
- && y < yb
- && y < r->bottom)
- {
- expose_line (w, row, r);
- y += row->height;
- ++row;
- }
-
- /* Display the mode line if there is one. */
- if (WINDOW_WANTS_MODELINE_P (w)
- && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
- row->enabled_p)
- && row->y < r->bottom)
- expose_line (w, row, r);
-
- if (!w->pseudo_window_p)
- {
- /* Draw border between windows. */
- x_draw_vertical_border (w);
-
- /* Turn the cursor on again. */
- if (cursor_cleared_p)
- x_update_window_cursor (w, 1);
- }
-
- /* Display scroll bar for this window. */
- if (!NILP (w->vertical_scroll_bar))
- {
- ControlHandle ch
- = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w->vertical_scroll_bar));
-
- Draw1Control (ch);
- }
-}
-
-
-/* Determine the intersection of two rectangles R1 and R2. Return
- the intersection in *RESULT. Value is non-zero if RESULT is not
- empty. */
-
-static int
-x_intersect_rectangles (r1, r2, result)
- Rect *r1, *r2, *result;
-{
- Rect *left, *right;
- Rect *upper, *lower;
- int intersection_p = 0;
-
- /* Rerrange so that R1 is the left-most rectangle. */
- if (r1->left < r2->left)
- left = r1, right = r2;
- else
- left = r2, right = r1;
-
- /* X0 of the intersection is right.x0, if this is inside R1,
- otherwise there is no intersection. */
- if (right->left <= left->right)
- {
- result->left = right->left;
-
- /* The right end of the intersection is the minimum of the
- the right ends of left and right. */
- result->right = min (left->right, right->right);
-
- /* Same game for Y. */
- if (r1->top < r2->top)
- upper = r1, lower = r2;
- else
- upper = r2, lower = r1;
-
- /* The upper end of the intersection is lower.y0, if this is inside
- of upper. Otherwise, there is no intersection. */
- if (lower->top <= upper->bottom)
- {
- result->top = lower->top;
-
- /* The lower end of the intersection is the minimum of the lower
- ends of upper and lower. */
- result->bottom = min (lower->bottom, upper->bottom);
- intersection_p = 1;
- }
- }
-
- return intersection_p;
-}
-
-
-
-
-\f
-static void
-frame_highlight (f)
- struct frame *f;
-{
- x_update_cursor (f, 1);
-}
-
-static void
-frame_unhighlight (f)
- struct frame *f;
-{
- x_update_cursor (f, 1);
-}
-
-/* The focus has changed. Update the frames as necessary to reflect
- the new situation. Note that we can't change the selected frame
- here, because the Lisp code we are interrupting might become confused.
- Each event gets marked with the frame in which it occurred, so the
- Lisp code can tell when the switch took place by examining the events. */
-
-static void
-x_new_focus_frame (dpyinfo, frame)
- struct x_display_info *dpyinfo;
- struct frame *frame;
-{
- struct frame *old_focus = dpyinfo->x_focus_frame;
-
- if (frame != dpyinfo->x_focus_frame)
- {
- /* Set this before calling other routines, so that they see
- the correct value of x_focus_frame. */
- dpyinfo->x_focus_frame = frame;
-
- if (old_focus && old_focus->auto_lower)
- x_lower_frame (old_focus);
-
-#if 0
- selected_frame = frame;
- XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
- selected_frame);
- Fselect_window (selected_frame->selected_window);
- choose_minibuf_frame ();
-#endif /* ! 0 */
-
- if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
- pending_autoraise_frame = dpyinfo->x_focus_frame;
- else
- pending_autoraise_frame = 0;
- }
-
- x_frame_rehighlight (dpyinfo);
-}
-
-/* Handle an event saying the mouse has moved out of an Emacs frame. */
-
-static void
-x_mouse_leave (dpyinfo)
- struct x_display_info *dpyinfo;
-{
- x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
-}
-
-/* The focus has changed, or we have redirected a frame's focus to
- another frame (this happens when a frame uses a surrogate
- mini-buffer frame). Shift the highlight as appropriate.
-
- The FRAME argument doesn't necessarily have anything to do with which
- frame is being highlighted or un-highlighted; we only use it to find
- the appropriate X display info. */
-
-void
-XTframe_rehighlight (frame)
- struct frame *frame;
-{
- x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
-}
-
-static void
-x_frame_rehighlight (dpyinfo)
- struct x_display_info *dpyinfo;
-{
- struct frame *old_highlight = dpyinfo->x_highlight_frame;
-
- if (dpyinfo->x_focus_frame)
- {
- dpyinfo->x_highlight_frame
- = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
- ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
- : dpyinfo->x_focus_frame);
- if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
- {
- FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
- dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
- }
- }
- else
- dpyinfo->x_highlight_frame = 0;
-
- if (dpyinfo->x_highlight_frame != old_highlight)
- {
- if (old_highlight)
- frame_unhighlight (old_highlight);
- if (dpyinfo->x_highlight_frame)
- frame_highlight (dpyinfo->x_highlight_frame);
- }
-}
-
-
-\f
-/* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
-
-#if 0
-/* Initialize mode_switch_bit and modifier_meaning. */
-static void
-x_find_modifier_meanings (dpyinfo)
- struct x_display_info *dpyinfo;
-{
- int min_code, max_code;
- KeySym *syms;
- int syms_per_code;
- XModifierKeymap *mods;
-
- dpyinfo->meta_mod_mask = 0;
- dpyinfo->shift_lock_mask = 0;
- dpyinfo->alt_mod_mask = 0;
- dpyinfo->super_mod_mask = 0;
- dpyinfo->hyper_mod_mask = 0;
-
-#ifdef HAVE_X11R4
- XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
-#else
- min_code = dpyinfo->display->min_keycode;
- max_code = dpyinfo->display->max_keycode;
-#endif
-
- syms = XGetKeyboardMapping (dpyinfo->display,
- min_code, max_code - min_code + 1,
- &syms_per_code);
- mods = XGetModifierMapping (dpyinfo->display);
-
- /* Scan the modifier table to see which modifier bits the Meta and
- Alt keysyms are on. */
- {
- int row, col; /* The row and column in the modifier table. */
-
- for (row = 3; row < 8; row++)
- for (col = 0; col < mods->max_keypermod; col++)
- {
- KeyCode code
- = mods->modifiermap[(row * mods->max_keypermod) + col];
-
- /* Zeroes are used for filler. Skip them. */
- if (code == 0)
- continue;
-
- /* Are any of this keycode's keysyms a meta key? */
- {
- int code_col;
-
- for (code_col = 0; code_col < syms_per_code; code_col++)
- {
- int sym = syms[((code - min_code) * syms_per_code) + code_col];
-
- switch (sym)
- {
- case XK_Meta_L:
- case XK_Meta_R:
- dpyinfo->meta_mod_mask |= (1 << row);
- break;
-
- case XK_Alt_L:
- case XK_Alt_R:
- dpyinfo->alt_mod_mask |= (1 << row);
- break;
-
- case XK_Hyper_L:
- case XK_Hyper_R:
- dpyinfo->hyper_mod_mask |= (1 << row);
- break;
-
- case XK_Super_L:
- case XK_Super_R:
- dpyinfo->super_mod_mask |= (1 << row);
- break;
-
- case XK_Shift_Lock:
- /* Ignore this if it's not on the lock modifier. */
- if ((1 << row) == LockMask)
- dpyinfo->shift_lock_mask = LockMask;
- break;
- }
- }
- }
- }
- }
-
- /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
- if (! dpyinfo->meta_mod_mask)
- {
- dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
- dpyinfo->alt_mod_mask = 0;
- }
-
- /* If some keys are both alt and meta,
- make them just meta, not alt. */
- if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
- {
- dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
- }
-
- XFree ((char *) syms);
- XFreeModifiermap (mods);
-}
-
-#endif
-
-/* Convert between the modifier bits X uses and the modifier bits
- Emacs uses. */
-
-static unsigned int
-x_mac_to_emacs_modifiers (dpyinfo, state)
- struct x_display_info *dpyinfo;
- unsigned short state;
-{
- return (((state & shiftKey) ? shift_modifier : 0)
- | ((state & controlKey) ? ctrl_modifier : 0)
- | ((state & cmdKey) ? meta_modifier : 0)
- | ((state & optionKey) ? alt_modifier : 0));
-}
-
-#if 0
-static unsigned short
-x_emacs_to_x_modifiers (dpyinfo, state)
- struct x_display_info *dpyinfo;
- unsigned int state;
-{
- return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
- | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
- | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
- | ((state & shift_modifier) ? ShiftMask : 0)
- | ((state & ctrl_modifier) ? ControlMask : 0)
- | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
-}
-#endif
-
-/* Convert a keysym to its name. */
-
-char *
-x_get_keysym_name (keysym)
- int keysym;
-{
- char *value;
-
- BLOCK_INPUT;
-#if 0
- value = XKeysymToString (keysym);
-#else
- value = 0;
-#endif
- UNBLOCK_INPUT;
-
- return value;
-}
-
-
-\f
-/* Mouse clicks and mouse movement. Rah. */
-
-/* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
- co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
- glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
- not force the value into range. */
-
-void
-pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
- FRAME_PTR f;
- register int pix_x, pix_y;
- register int *x, *y;
- Rect *bounds;
- int noclip;
-{
- /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
- even for negative values. */
- if (pix_x < 0)
- pix_x -= FONT_WIDTH ((f)->output_data.mac->font) - 1;
- if (pix_y < 0)
- pix_y -= (f)->output_data.mac->line_height - 1;
-
- pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
- pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
-
- if (bounds)
- {
- bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
- bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
- bounds->right = bounds->left + FONT_WIDTH (f->output_data.mac->font);
- bounds->bottom = bounds->top + f->output_data.mac->line_height;
- }
-
- if (!noclip)
- {
- if (pix_x < 0)
- pix_x = 0;
- else if (pix_x > FRAME_WINDOW_WIDTH (f))
- pix_x = FRAME_WINDOW_WIDTH (f);
-
- if (pix_y < 0)
- pix_y = 0;
- else if (pix_y > f->height)
- pix_y = f->height;
- }
-
- *x = pix_x;
- *y = pix_y;
-}
-
-
-/* Given HPOS/VPOS in the current matrix of W, return corresponding
- frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
- can't tell the positions because W's display is not up to date,
- return 0. */
-
-static int
-glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
- struct window *w;
- int hpos, vpos;
- int *frame_x, *frame_y;
-{
- int success_p;
-
- xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
- xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
-
- if (display_completed)
- {
- struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
- struct glyph *glyph = row->glyphs[TEXT_AREA];
- struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
-
- *frame_y = row->y;
- *frame_x = row->x;
- while (glyph < end)
- {
- *frame_x += glyph->pixel_width;
- ++glyph;
- }
-
- success_p = 1;
- }
- else
- {
- *frame_y = *frame_x = 0;
- success_p = 0;
- }
-
- *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
- *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
- return success_p;
-}
-
-
-/* Prepare a mouse-event in *RESULT for placement in the input queue.
-
- If the event is a button press, then note that we have grabbed
- the mouse. */
-
-static Lisp_Object
-construct_mouse_click (result, event, f)
- struct input_event *result;
- EventRecord *event;
- struct frame *f;
-{
- Point mouseLoc;
-
- result->kind = mouse_click;
- result->code = 0; /* only one mouse button */
- result->timestamp = event->when;
- result->modifiers = event->what == mouseDown ? down_modifier : up_modifier;
-
- mouseLoc = event->where;
- SetPort (FRAME_MAC_WINDOW (f));
- GlobalToLocal (&mouseLoc);
- XSETINT (result->x, mouseLoc.h);
- XSETINT (result->y, mouseLoc.v);
-
- XSETFRAME (result->frame_or_window, f);
-
- result->arg = Qnil;
- return Qnil;
-}
-
-\f
-/* Function to report a mouse movement to the mainstream Emacs code.
- The input handler calls this.
-
- We have received a mouse movement event, which is given in *event.
- If the mouse is over a different glyph than it was last time, tell
- the mainstream emacs code by setting mouse_moved. If not, ask for
- another motion event, so we can check again the next time it moves. */
-
-static Point last_mouse_motion_position;
-static Lisp_Object last_mouse_motion_frame;
-
-static void
-note_mouse_movement (frame, pos)
- FRAME_PTR frame;
- Point *pos;
-{
- last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
- last_mouse_motion_position = *pos;
- XSETFRAME (last_mouse_motion_frame, frame);
-
- if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
- {
- frame->mouse_moved = 1;
- last_mouse_scroll_bar = Qnil;
- note_mouse_highlight (frame, -1, -1);
- }
- /* Has the mouse moved off the glyph it was on at the last sighting? */
- else if (pos->h < last_mouse_glyph.left
- || pos->h >= last_mouse_glyph.right
- || pos->v < last_mouse_glyph.top
- || pos->v >= last_mouse_glyph.bottom)
- {
- frame->mouse_moved = 1;
- last_mouse_scroll_bar = Qnil;
- note_mouse_highlight (frame, pos->h, pos->v);
- }
-}
-
-/* This is used for debugging, to turn off note_mouse_highlight. */
-
-int disable_mouse_highlight;
-
-
-\f
-/************************************************************************
- Mouse Face
- ************************************************************************/
-
-/* Find the glyph under window-relative coordinates X/Y in window W.
- Consider only glyphs from buffer text, i.e. no glyphs from overlay
- strings. Return in *HPOS and *VPOS the row and column number of
- the glyph found. Return in *AREA the glyph area containing X.
- Value is a pointer to the glyph found or null if X/Y is not on
- text, or we can't tell because W's current matrix is not up to
- date. */
-
-static struct glyph *
-x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
- struct window *w;
- int x, y;
- int *hpos, *vpos, *area;
-{
- struct glyph *glyph, *end;
- struct glyph_row *row = NULL;
- int x0, i, left_area_width;
-
- /* Find row containing Y. Give up if some row is not enabled. */
- for (i = 0; i < w->current_matrix->nrows; ++i)
- {
- row = MATRIX_ROW (w->current_matrix, i);
- if (!row->enabled_p)
- return NULL;
- if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
- break;
- }
-
- *vpos = i;
- *hpos = 0;
-
- /* Give up if Y is not in the window. */
- if (i == w->current_matrix->nrows)
- return NULL;
-
- /* Get the glyph area containing X. */
- if (w->pseudo_window_p)
- {
- *area = TEXT_AREA;
- x0 = 0;
- }
- else
- {
- left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
- if (x < left_area_width)
- {
- *area = LEFT_MARGIN_AREA;
- x0 = 0;
- }
- else if (x < left_area_width + window_box_width (w, TEXT_AREA))
- {
- *area = TEXT_AREA;
- x0 = row->x + left_area_width;
- }
- else
- {
- *area = RIGHT_MARGIN_AREA;
- x0 = left_area_width + window_box_width (w, TEXT_AREA);
- }
- }
-
- /* Find glyph containing X. */
- glyph = row->glyphs[*area];
- end = glyph + row->used[*area];
- while (glyph < end)
- {
- if (x < x0 + glyph->pixel_width)
- {
- if (w->pseudo_window_p)
- break;
- else if (BUFFERP (glyph->object))
- break;
- }
-
- x0 += glyph->pixel_width;
- ++glyph;
- }
-
- if (glyph == end)
- return NULL;
-
- *hpos = glyph - row->glyphs[*area];
- return glyph;
-}
-
-
-/* Convert frame-relative x/y to coordinates relative to window W.
- Takes pseudo-windows into account. */
-
-static void
-frame_to_window_pixel_xy (w, x, y)
- struct window *w;
- int *x, *y;
-{
- if (w->pseudo_window_p)
- {
- /* A pseudo-window is always full-width, and starts at the
- left edge of the frame, plus a frame border. */
- struct frame *f = XFRAME (w->frame);
- *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
- *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
- }
- else
- {
- *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
- *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
- }
-}
-
-
-/* Take proper action when mouse has moved to the mode or top line of
- window W, x-position X. MODE_LINE_P non-zero means mouse is on the
- mode line. X is relative to the start of the text display area of
- W, so the width of fringes and scroll bars must be subtracted
- to get a position relative to the start of the mode line. */
-
-static void
-note_mode_line_highlight (w, x, mode_line_p)
- struct window *w;
- int x, mode_line_p;
-{
- struct frame *f = XFRAME (w->frame);
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
- Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
- struct glyph_row *row;
-
- if (mode_line_p)
- row = MATRIX_MODE_LINE_ROW (w->current_matrix);
- else
- row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
-
- if (row->enabled_p)
- {
- struct glyph *glyph, *end;
- Lisp_Object help, map;
- int x0;
-
- /* Find the glyph under X. */
- glyph = row->glyphs[TEXT_AREA];
- end = glyph + row->used[TEXT_AREA];
- x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
- + FRAME_X_LEFT_FRINGE_WIDTH (f));
- while (glyph < end
- && x >= x0 + glyph->pixel_width)
- {
- x0 += glyph->pixel_width;
- ++glyph;
- }
-
- if (glyph < end
- && STRINGP (glyph->object)
- && XSTRING (glyph->object)->intervals
- && glyph->charpos >= 0
- && glyph->charpos < XSTRING (glyph->object)->size)
- {
- /* If we're on a string with `help-echo' text property,
- arrange for the help to be displayed. This is done by
- setting the global variable help_echo to the help string. */
- help = Fget_text_property (make_number (glyph->charpos),
- Qhelp_echo, glyph->object);
- if (!NILP (help))
- {
- help_echo = help;
- XSETWINDOW (help_echo_window, w);
- help_echo_object = glyph->object;
- help_echo_pos = glyph->charpos;
- }
-
- /* Change the mouse pointer according to what is under X/Y. */
- map = Fget_text_property (make_number (glyph->charpos),
- Qlocal_map, glyph->object);
- if (KEYMAPP (map))
- cursor = f->output_data.mac->nontext_cursor;
- else
- {
- map = Fget_text_property (make_number (glyph->charpos),
- Qkeymap, glyph->object);
- if (KEYMAPP (map))
- cursor = f->output_data.mac->nontext_cursor;
- }
- }
- }
-
-#if 0 /* MAC_TODO: mouse cursor */
- XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
-#endif
-}
-
-
-/* Take proper action when the mouse has moved to position X, Y on
- frame F as regards highlighting characters that have mouse-face
- properties. Also de-highlighting chars where the mouse was before.
- X and Y can be negative or out of range. */
-
-static void
-note_mouse_highlight (f, x, y)
- struct frame *f;
- int x, y;
-{
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
- int portion;
- Lisp_Object window;
- struct window *w;
-
- /* When a menu is active, don't highlight because this looks odd. */
-#ifdef USE_X_TOOLKIT
- if (popup_activated ())
- return;
-#endif
-
- if (disable_mouse_highlight
- || !f->glyphs_initialized_p)
- return;
-
- dpyinfo->mouse_face_mouse_x = x;
- dpyinfo->mouse_face_mouse_y = y;
- dpyinfo->mouse_face_mouse_frame = f;
-
- if (dpyinfo->mouse_face_defer)
- return;
-
- if (gc_in_progress)
- {
- dpyinfo->mouse_face_deferred_gc = 1;
- return;
- }
-
- /* Which window is that in? */
- window = window_from_coordinates (f, x, y, &portion, 1);
-
- /* If we were displaying active text in another window, clear that. */
- if (! EQ (window, dpyinfo->mouse_face_window))
- clear_mouse_face (dpyinfo);
-
- /* Not on a window -> return. */
- if (!WINDOWP (window))
- return;
-
- /* Convert to window-relative pixel coordinates. */
- w = XWINDOW (window);
- frame_to_window_pixel_xy (w, &x, &y);
-
- /* Handle tool-bar window differently since it doesn't display a
- buffer. */
- if (EQ (window, f->tool_bar_window))
- {
- note_tool_bar_highlight (f, x, y);
- return;
- }
-
- if (portion == 1 || portion == 3)
- {
- /* Mouse is on the mode or top line. */
- note_mode_line_highlight (w, x, portion == 1);
- return;
- }
-#if 0 /* MAC_TODO: mouse cursor */
- else
- XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- f->output_data.x->text_cursor);
-#endif
-
- /* Are we in a window whose display is up to date?
- And verify the buffer's text has not changed. */
- if (/* Within text portion of the window. */
- portion == 0
- && EQ (w->window_end_valid, w->buffer)
- && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
- && (XFASTINT (w->last_overlay_modified)
- == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
- {
- int hpos, vpos, pos, i, area;
- struct glyph *glyph;
-
- /* Find the glyph under X/Y. */
- glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area);
-
- /* Clear mouse face if X/Y not over text. */
- if (glyph == NULL
- || area != TEXT_AREA
- || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
- {
- clear_mouse_face (dpyinfo);
- return;
- }
-
- pos = glyph->charpos;
- xassert (w->pseudo_window_p || BUFFERP (glyph->object));
-
- /* Check for mouse-face and help-echo. */
- {
- Lisp_Object mouse_face, overlay, position;
- Lisp_Object *overlay_vec;
- int len, noverlays;
- struct buffer *obuf;
- int obegv, ozv;
-
- /* If we get an out-of-range value, return now; avoid an error. */
- if (pos > BUF_Z (XBUFFER (w->buffer)))
- return;
-
- /* Make the window's buffer temporarily current for
- overlays_at and compute_char_face. */
- obuf = current_buffer;
- current_buffer = XBUFFER (w->buffer);
- obegv = BEGV;
- ozv = ZV;
- BEGV = BEG;
- ZV = Z;
-
- /* Is this char mouse-active or does it have help-echo? */
- XSETINT (position, pos);
-
- /* Put all the overlays we want in a vector in overlay_vec.
- Store the length in len. If there are more than 10, make
- enough space for all, and try again. */
- len = 10;
- overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
- noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
- if (noverlays > len)
- {
- len = noverlays;
- overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
- noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
- }
-
- /* Sort overlays into increasing priority order. */
- noverlays = sort_overlays (overlay_vec, noverlays, w);
-
- /* Check mouse-face highlighting. */
- if (! (EQ (window, dpyinfo->mouse_face_window)
- && vpos >= dpyinfo->mouse_face_beg_row
- && vpos <= dpyinfo->mouse_face_end_row
- && (vpos > dpyinfo->mouse_face_beg_row
- || hpos >= dpyinfo->mouse_face_beg_col)
- && (vpos < dpyinfo->mouse_face_end_row
- || hpos < dpyinfo->mouse_face_end_col
- || dpyinfo->mouse_face_past_end)))
- {
- /* Clear the display of the old active region, if any. */
- clear_mouse_face (dpyinfo);
-
- /* Find the highest priority overlay that has a mouse-face prop. */
- overlay = Qnil;
- for (i = noverlays - 1; i >= 0; --i)
- {
- mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
- if (!NILP (mouse_face))
- {
- overlay = overlay_vec[i];
- break;
- }
- }
-
- /* If no overlay applies, get a text property. */
- if (NILP (overlay))
- mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
-
- /* Handle the overlay case. */
- if (! NILP (overlay))
- {
- /* Find the range of text around this char that
- should be active. */
- Lisp_Object before, after;
- int ignore;
-
- before = Foverlay_start (overlay);
- after = Foverlay_end (overlay);
- /* Record this as the current active region. */
- fast_find_position (w, XFASTINT (before),
- &dpyinfo->mouse_face_beg_col,
- &dpyinfo->mouse_face_beg_row,
- &dpyinfo->mouse_face_beg_x,
- &dpyinfo->mouse_face_beg_y);
- dpyinfo->mouse_face_past_end
- = !fast_find_position (w, XFASTINT (after),
- &dpyinfo->mouse_face_end_col,
- &dpyinfo->mouse_face_end_row,
- &dpyinfo->mouse_face_end_x,
- &dpyinfo->mouse_face_end_y);
- dpyinfo->mouse_face_window = window;
- dpyinfo->mouse_face_face_id
- = face_at_buffer_position (w, pos, 0, 0,
- &ignore, pos + 1, 1);
-
- /* Display it as active. */
- show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
- }
- /* Handle the text property case. */
- else if (! NILP (mouse_face))
- {
- /* Find the range of text around this char that
- should be active. */
- Lisp_Object before, after, beginning, end;
- int ignore;
-
- beginning = Fmarker_position (w->start);
- XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
- - XFASTINT (w->window_end_pos)));
- before
- = Fprevious_single_property_change (make_number (pos + 1),
- Qmouse_face,
- w->buffer, beginning);
- after
- = Fnext_single_property_change (position, Qmouse_face,
- w->buffer, end);
- /* Record this as the current active region. */
- fast_find_position (w, XFASTINT (before),
- &dpyinfo->mouse_face_beg_col,
- &dpyinfo->mouse_face_beg_row,
- &dpyinfo->mouse_face_beg_x,
- &dpyinfo->mouse_face_beg_y);
- dpyinfo->mouse_face_past_end
- = !fast_find_position (w, XFASTINT (after),
- &dpyinfo->mouse_face_end_col,
- &dpyinfo->mouse_face_end_row,
- &dpyinfo->mouse_face_end_x,
- &dpyinfo->mouse_face_end_y);
- dpyinfo->mouse_face_window = window;
- dpyinfo->mouse_face_face_id
- = face_at_buffer_position (w, pos, 0, 0,
- &ignore, pos + 1, 1);
-
- /* Display it as active. */
- show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
- }
- }
-
- /* Look for a `help-echo' property. */
- {
- Lisp_Object help, overlay;
-
- /* Check overlays first. */
- help = Qnil;
- for (i = noverlays - 1; i >= 0 && NILP (help); --i)
- {
- overlay = overlay_vec[i];
- help = Foverlay_get (overlay, Qhelp_echo);
- }
-
- if (!NILP (help))
- {
- help_echo = help;
- help_echo_window = window;
- help_echo_object = overlay;
- help_echo_pos = pos;
- }
- else
- {
- /* Try text properties. */
- if ((STRINGP (glyph->object)
- && glyph->charpos >= 0
- && glyph->charpos < XSTRING (glyph->object)->size)
- || (BUFFERP (glyph->object)
- && glyph->charpos >= BEGV
- && glyph->charpos < ZV))
- help = Fget_text_property (make_number (glyph->charpos),
- Qhelp_echo, glyph->object);
-
- if (!NILP (help))
- {
- help_echo = help;
- help_echo_window = window;
- help_echo_object = glyph->object;
- help_echo_pos = glyph->charpos;
- }
- }
- }
-
- BEGV = obegv;
- ZV = ozv;
- current_buffer = obuf;
- }
- }
-}
-
-static void
-redo_mouse_highlight ()
-{
- if (!NILP (last_mouse_motion_frame)
- && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
- note_mouse_highlight (XFRAME (last_mouse_motion_frame),
- last_mouse_motion_position.h,
- last_mouse_motion_position.v);
-}
-
-
-\f
-/***********************************************************************
- Tool-bars
- ***********************************************************************/
-
-static int x_tool_bar_item P_ ((struct frame *, int, int,
- struct glyph **, int *, int *, int *));
-
-/* Tool-bar item index of the item on which a mouse button was pressed
- or -1. */
-
-static int last_tool_bar_item;
-
-
-/* Get information about the tool-bar item at position X/Y on frame F.
- Return in *GLYPH a pointer to the glyph of the tool-bar item in
- the current matrix of the tool-bar window of F, or NULL if not
- on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
- item in F->current_tool_bar_items. Value is
-
- -1 if X/Y is not on a tool-bar item
- 0 if X/Y is on the same item that was highlighted before.
- 1 otherwise. */
-
-static int
-x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
- struct frame *f;
- int x, y;
- struct glyph **glyph;
- int *hpos, *vpos, *prop_idx;
-{
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
- struct window *w = XWINDOW (f->tool_bar_window);
- int area;
-
- /* Find the glyph under X/Y. */
- *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area);
- if (*glyph == NULL)
- return -1;
-
- /* Get the start of this tool-bar item's properties in
- f->current_tool_bar_items. */
- if (!tool_bar_item_info (f, *glyph, prop_idx))
- return -1;
-
- /* Is mouse on the highlighted item? */
- if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
- && *vpos >= dpyinfo->mouse_face_beg_row
- && *vpos <= dpyinfo->mouse_face_end_row
- && (*vpos > dpyinfo->mouse_face_beg_row
- || *hpos >= dpyinfo->mouse_face_beg_col)
- && (*vpos < dpyinfo->mouse_face_end_row
- || *hpos < dpyinfo->mouse_face_end_col
- || dpyinfo->mouse_face_past_end))
- return 0;
-
- return 1;
-}
-
-
-/* Handle mouse button event on the tool-bar of frame F, at
- frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
- or ButtonRelase. */
-
-static void
-x_handle_tool_bar_click (f, button_event)
- struct frame *f;
- EventRecord *button_event;
-{
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
- struct window *w = XWINDOW (f->tool_bar_window);
- int hpos, vpos, prop_idx;
- struct glyph *glyph;
- Lisp_Object enabled_p;
- int x = button_event->where.h;
- int y = button_event->where.v;
-
- /* If not on the highlighted tool-bar item, return. */
- frame_to_window_pixel_xy (w, &x, &y);
- if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
- return;
-
- /* If item is disabled, do nothing. */
- enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
- if (NILP (enabled_p))
- return;
-
- if (button_event->what == mouseDown)
- {
- /* Show item in pressed state. */
- show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
- dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
- last_tool_bar_item = prop_idx;
- }
- else
- {
- Lisp_Object key, frame;
- struct input_event event;
-
- /* Show item in released state. */
- show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
- dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
-
- key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
-
- XSETFRAME (frame, f);
- event.kind = TOOL_BAR_EVENT;
- event.frame_or_window = frame;
- event.arg = frame;
- kbd_buffer_store_event (&event);
-
- event.kind = TOOL_BAR_EVENT;
- event.frame_or_window = frame;
- event.arg = key;
- event.modifiers = x_mac_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
- button_event->modifiers);
- kbd_buffer_store_event (&event);
- last_tool_bar_item = -1;
- }
-}
-
-
-/* Possibly highlight a tool-bar item on frame F when mouse moves to
- tool-bar window-relative coordinates X/Y. Called from
- note_mouse_highlight. */
-
-static void
-note_tool_bar_highlight (f, x, y)
- struct frame *f;
- int x, y;
-{
- Lisp_Object window = f->tool_bar_window;
- struct window *w = XWINDOW (window);
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
- int hpos, vpos;
- struct glyph *glyph;
- struct glyph_row *row;
- int i;
- Lisp_Object enabled_p;
- int prop_idx;
- enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
- int mouse_down_p, rc;
-
- /* Function note_mouse_highlight is called with negative x(y
- values when mouse moves outside of the frame. */
- if (x <= 0 || y <= 0)
- {
- clear_mouse_face (dpyinfo);
- return;
- }
-
- rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
- if (rc < 0)
- {
- /* Not on tool-bar item. */
- clear_mouse_face (dpyinfo);
- return;
- }
- else if (rc == 0)
- /* On same tool-bar item as before. */
- goto set_help_echo;
-
- clear_mouse_face (dpyinfo);
-
- /* Mouse is down, but on different tool-bar item? */
- mouse_down_p = (dpyinfo->grabbed
- && f == last_mouse_frame
- && FRAME_LIVE_P (f));
- if (mouse_down_p
- && last_tool_bar_item != prop_idx)
- return;
-
- dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
- draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
-
- /* If tool-bar item is not enabled, don't highlight it. */
- enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
- if (!NILP (enabled_p))
- {
- /* Compute the x-position of the glyph. In front and past the
- image is a space. We include this is the highlighted area. */
- row = MATRIX_ROW (w->current_matrix, vpos);
- for (i = x = 0; i < hpos; ++i)
- x += row->glyphs[TEXT_AREA][i].pixel_width;
-
- /* Record this as the current active region. */
- dpyinfo->mouse_face_beg_col = hpos;
- dpyinfo->mouse_face_beg_row = vpos;
- dpyinfo->mouse_face_beg_x = x;
- dpyinfo->mouse_face_beg_y = row->y;
- dpyinfo->mouse_face_past_end = 0;
-
- dpyinfo->mouse_face_end_col = hpos + 1;
- dpyinfo->mouse_face_end_row = vpos;
- dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
- dpyinfo->mouse_face_end_y = row->y;
- dpyinfo->mouse_face_window = window;
- dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
-
- /* Display it as active. */
- show_mouse_face (dpyinfo, draw);
- dpyinfo->mouse_face_image_state = draw;
- }
-
- set_help_echo:
-
- /* Set help_echo to a help string.to display for this tool-bar item.
- XTread_socket does the rest. */
- help_echo_object = help_echo_window = Qnil;
- help_echo_pos = -1;
- help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
- if (NILP (help_echo))
- help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
-}
-
-
-\f
-/* Find the glyph matrix position of buffer position POS in window W.
- *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
- current glyphs must be up to date. If POS is above window start
- return (0, 0, 0, 0). If POS is after end of W, return end of
- last line in W. */
-
-static int
-fast_find_position (w, pos, hpos, vpos, x, y)
- struct window *w;
- int pos;
- int *hpos, *vpos, *x, *y;
-{
- int i;
- int lastcol;
- int maybe_next_line_p = 0;
- int line_start_position;
- int yb = window_text_bottom_y (w);
- struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
- struct glyph_row *best_row = row;
- int row_vpos = 0, best_row_vpos = 0;
- int current_x;
-
- while (row->y < yb)
- {
- if (row->used[TEXT_AREA])
- line_start_position = row->glyphs[TEXT_AREA]->charpos;
- else
- line_start_position = 0;
-
- if (line_start_position > pos)
- break;
- /* If the position sought is the end of the buffer,
- don't include the blank lines at the bottom of the window. */
- else if (line_start_position == pos
- && pos == BUF_ZV (XBUFFER (w->buffer)))
- {
- maybe_next_line_p = 1;
- break;
- }
- else if (line_start_position > 0)
- {
- best_row = row;
- best_row_vpos = row_vpos;
- }
-
- if (row->y + row->height >= yb)
- break;
-
- ++row;
- ++row_vpos;
- }
-
- /* Find the right column within BEST_ROW. */
- lastcol = 0;
- current_x = best_row->x;
- for (i = 0; i < best_row->used[TEXT_AREA]; i++)
- {
- struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
- int charpos;
-
- charpos = glyph->charpos;
- if (charpos == pos)
- {
- *hpos = i;
- *vpos = best_row_vpos;
- *x = current_x;
- *y = best_row->y;
- return 1;
- }
- else if (charpos > pos)
- break;
- else if (charpos > 0)
- lastcol = i;
-
- current_x += glyph->pixel_width;
- }
-
- /* If we're looking for the end of the buffer,
- and we didn't find it in the line we scanned,
- use the start of the following line. */
- if (maybe_next_line_p)
- {
- ++best_row;
- ++best_row_vpos;
- lastcol = 0;
- current_x = best_row->x;
- }
-
- *vpos = best_row_vpos;
- *hpos = lastcol + 1;
- *x = current_x;
- *y = best_row->y;
- return 0;
-}
-
-
-/* Display the active region described by mouse_face_*
- in its mouse-face if HL > 0, in its normal face if HL = 0. */
-
-static void
-show_mouse_face (dpyinfo, draw)
- struct mac_display_info *dpyinfo;
- enum draw_glyphs_face draw;
-{
- struct window *w = XWINDOW (dpyinfo->mouse_face_window);
- struct frame *f = XFRAME (WINDOW_FRAME (w));
- int i;
- int cursor_off_p = 0;
- struct cursor_pos saved_cursor;
-
- saved_cursor = output_cursor;
-
- /* If window is in the process of being destroyed, don't bother
- to do anything. */
- if (w->current_matrix == NULL)
- goto set_x_cursor;
-
- /* Recognize when we are called to operate on rows that don't exist
- anymore. This can happen when a window is split. */
- if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
- goto set_x_cursor;
-
- set_output_cursor (&w->phys_cursor);
-
- /* Note that mouse_face_beg_row etc. are window relative. */
- for (i = dpyinfo->mouse_face_beg_row;
- i <= dpyinfo->mouse_face_end_row;
- i++)
- {
- int start_hpos, end_hpos, start_x;
- struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
-
- /* Don't do anything if row doesn't have valid contents. */
- if (!row->enabled_p)
- continue;
-
- /* For all but the first row, the highlight starts at column 0. */
- if (i == dpyinfo->mouse_face_beg_row)
- {
- start_hpos = dpyinfo->mouse_face_beg_col;
- start_x = dpyinfo->mouse_face_beg_x;
- }
- else
- {
- start_hpos = 0;
- start_x = 0;
- }
-
- if (i == dpyinfo->mouse_face_end_row)
- end_hpos = dpyinfo->mouse_face_end_col;
- else
- end_hpos = row->used[TEXT_AREA];
-
- /* If the cursor's in the text we are about to rewrite, turn the
- cursor off. */
- if (!w->pseudo_window_p
- && i == output_cursor.vpos
- && output_cursor.hpos >= start_hpos - 1
- && output_cursor.hpos <= end_hpos)
- {
- x_update_window_cursor (w, 0);
- cursor_off_p = 1;
- }
-
- if (end_hpos > start_hpos)
- {
- row->mouse_face_p = draw == DRAW_MOUSE_FACE;
- x_draw_glyphs (w, start_x, row, TEXT_AREA,
- start_hpos, end_hpos, draw, NULL, NULL, 0);
- }
- }
-
- /* If we turned the cursor off, turn it back on. */
- if (cursor_off_p)
- x_display_cursor (w, 1,
- output_cursor.hpos, output_cursor.vpos,
- output_cursor.x, output_cursor.y);
-
- output_cursor = saved_cursor;
-
- set_x_cursor:
-#if 0 /* MAC_TODO: mouse cursor */
- /* Change the mouse cursor. */
- if (draw == DRAW_NORMAL_TEXT)
- XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- f->output_data.x->text_cursor);
- else if (draw == DRAW_MOUSE_FACE)
- XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- f->output_data.x->cross_cursor);
- else
- XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- f->output_data.x->nontext_cursor);
-#endif
- ;
-}
-
-/* Clear out the mouse-highlighted active region.
- Redraw it un-highlighted first. */
-
-void
-clear_mouse_face (dpyinfo)
- struct mac_display_info *dpyinfo;
-{
- if (!NILP (tip_frame))
- return;
-
- if (! NILP (dpyinfo->mouse_face_window))
- show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
-
- dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
- dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
- dpyinfo->mouse_face_window = Qnil;
-}
-
-
-/* Clear any mouse-face on window W. This function is part of the
- redisplay interface, and is called from try_window_id and similar
- functions to ensure the mouse-highlight is off. */
-
-void
-x_clear_mouse_face (w)
- struct window *w;
-{
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
- Lisp_Object window;
-
- XSETWINDOW (window, w);
- if (EQ (window, dpyinfo->mouse_face_window))
- clear_mouse_face (dpyinfo);
-}
-
-
-/* Just discard the mouse face information for frame F, if any.
- This is used when the size of F is changed. */
-
-static void
-cancel_mouse_face (f)
- FRAME_PTR f;
-{
- Lisp_Object window;
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
-
- window = dpyinfo->mouse_face_window;
- if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
- {
- dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
- dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
- dpyinfo->mouse_face_window = Qnil;
- }
-}
-\f
-static struct scroll_bar *x_window_to_scroll_bar ();
-static void x_scroll_bar_report_motion ();
-
-/* Return the current position of the mouse.
- *fp should be a frame which indicates which display to ask about.
-
- If the mouse movement started in a scroll bar, set *fp, *bar_window,
- and *part to the frame, window, and scroll bar part that the mouse
- is over. Set *x and *y to the portion and whole of the mouse's
- position on the scroll bar.
-
- If the mouse movement started elsewhere, set *fp to the frame the
- mouse is on, *bar_window to nil, and *x and *y to the character cell
- the mouse is over.
-
- Set *time to the server time-stamp for the time at which the mouse
- was at this position.
-
- Don't store anything if we don't have a valid set of values to report.
-
- This clears the mouse_moved flag, so we can wait for the next mouse
- movement. */
-
-void
-XTmouse_position (fp, insist, bar_window, part, x, y, time)
- FRAME_PTR *fp;
- int insist;
- Lisp_Object *bar_window;
- enum scroll_bar_part *part;
- Lisp_Object *x, *y;
- unsigned long *time;
-{
- Point mouse_pos;
- int ignore1, ignore2;
- WindowPtr wp = FrontWindow ();
- struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
- Lisp_Object frame, tail;
-
- BLOCK_INPUT;
-
- if (! NILP (last_mouse_scroll_bar) && insist == 0)
- x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
- else
- {
- /* Clear the mouse-moved flag for every frame on this display. */
- FOR_EACH_FRAME (tail, frame)
- XFRAME (frame)->mouse_moved = 0;
-
- last_mouse_scroll_bar = Qnil;
-
- SetPort (wp);
- GetMouse (&mouse_pos);
-
- pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
- &last_mouse_glyph, insist);
-
- *bar_window = Qnil;
- *part = scroll_bar_handle;
- *fp = f;
- XSETINT (*x, mouse_pos.h);
- XSETINT (*y, mouse_pos.v);
- *time = last_mouse_movement_time;
- }
-
- UNBLOCK_INPUT;
-}
-
-\f
-/************************************************************************
- Scroll bars, general
- ************************************************************************/
-
-/* Create a scroll bar and return the scroll bar vector for it. W is
- the Emacs window on which to create the scroll bar. TOP, LEFT,
- WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
- scroll bar. */
-
-static struct scroll_bar *
-x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
- struct window *w;
- int top, left, width, height, disp_top, disp_height;
-{
- struct frame *f = XFRAME (w->frame);
- struct scroll_bar *bar
- = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
- Rect r;
- ControlHandle ch;
-
- BLOCK_INPUT;
-
- r.left = left;
- r.top = disp_top;
- r.right = left + width;
- r.bottom = disp_top + disp_height;
-
- ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
- 0L);
- SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
- SetControlReference (ch, (long) bar);
-
- XSETWINDOW (bar->window, w);
- XSETINT (bar->top, top);
- XSETINT (bar->left, left);
- XSETINT (bar->width, width);
- XSETINT (bar->height, height);
- XSETINT (bar->start, 0);
- XSETINT (bar->end, 0);
- bar->dragging = Qnil;
-
- /* Add bar to its frame's list of scroll bars. */
- bar->next = FRAME_SCROLL_BARS (f);
- bar->prev = Qnil;
- XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
- if (!NILP (bar->next))
- XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
-
- UNBLOCK_INPUT;
- return bar;
-}
-
-
-/* Draw BAR's handle in the proper position.
-
- If the handle is already drawn from START to END, don't bother
- redrawing it, unless REBUILD is non-zero; in that case, always
- redraw it. (REBUILD is handy for drawing the handle after expose
- events.)
-
- Normally, we want to constrain the start and end of the handle to
- fit inside its rectangle, but if the user is dragging the scroll
- bar handle, we want to let them drag it down all the way, so that
- the bar's top is as far down as it goes; otherwise, there's no way
- to move to the very end of the buffer. */
-
-static void
-x_scroll_bar_set_handle (bar, start, end, rebuild)
- struct scroll_bar *bar;
- int start, end;
- int rebuild;
-{
- int dragging = ! NILP (bar->dragging);
- ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
- FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
-
- /* If the display is already accurate, do nothing. */
- if (! rebuild
- && start == XINT (bar->start)
- && end == XINT (bar->end))
- return;
-
- BLOCK_INPUT;
-
- {
- int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
- int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
- int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
-
- /* Make sure the values are reasonable, and try to preserve
- the distance between start and end. */
- {
- int length = end - start;
-
- if (start < 0)
- start = 0;
- else if (start > top_range)
- start = top_range;
- end = start + length;
-
- if (end < start)
- end = start;
- else if (end > top_range && ! dragging)
- end = top_range;
- }
-
- /* Store the adjusted setting in the scroll bar. */
- XSETINT (bar->start, start);
- XSETINT (bar->end, end);
-
- /* Clip the end position, just for display. */
- if (end > top_range)
- end = top_range;
-
- /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
- below top positions, to make sure the handle is always at least
- that many pixels tall. */
- end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
-
- SetControlMinimum (ch, 0);
- /* Don't inadvertently activate deactivated scroll bars */
- if (GetControlMaximum (ch) != -1)
- SetControlMaximum (ch,
- VERTICAL_SCROLL_BAR_TOP_RANGE (f,
- XINT (bar->height))
- - 1);
- SetControlValue (ch, start);
-#if 0 /* MAC_TODO: detect Appearance Manager 1.1 before use. */
- SetControlViewSize (ch, end);
-#endif
- }
-
- UNBLOCK_INPUT;
-}
-
-
-/* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
- nil. */
-
-static void
-x_scroll_bar_remove (bar)
- struct scroll_bar *bar;
-{
- FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
-
- BLOCK_INPUT;
-
- /* Destroy the Mac scroll bar control */
- DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
-
- /* Disassociate this scroll bar from its window. */
- XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
-
- UNBLOCK_INPUT;
-}
-
-
-/* Set the handle of the vertical scroll bar for WINDOW to indicate
- that we are displaying PORTION characters out of a total of WHOLE
- characters, starting at POSITION. If WINDOW has no scroll bar,
- create one. */
-
-static void
-XTset_vertical_scroll_bar (w, portion, whole, position)
- struct window *w;
- int portion, whole, position;
-{
- struct frame *f = XFRAME (w->frame);
- struct scroll_bar *bar;
- int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
- int window_x, window_y, window_width, window_height;
-
- /* Get window dimensions. */
- window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
- top = window_y;
- width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
- height = window_height;
-
- /* Compute the left edge of the scroll bar area. */
- if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
- left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
- else
- left = XFASTINT (w->left);
- left *= CANON_X_UNIT (f);
- left += FRAME_INTERNAL_BORDER_WIDTH (f);
-
- /* Compute the width of the scroll bar which might be less than
- the width of the area reserved for the scroll bar. */
- if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
- sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
- else
- sb_width = width;
-
- /* Compute the left edge of the scroll bar. */
- if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
- sb_left = left + width - sb_width - (width - sb_width) / 2;
- else
- sb_left = left + (width - sb_width) / 2;
-
- /* Adjustments according to Inside Macintosh to make it look nice */
- disp_top = top;
- disp_height = height;
- if (disp_top == 0)
- {
- disp_top = -1;
- disp_height++;
- }
- else if (disp_top == PIXEL_HEIGHT (f) - 16)
- {
- disp_top++;
- disp_height--;
- }
-
- if (sb_left + sb_width == PIXEL_WIDTH (f))
- sb_left++;
-
- /* Does the scroll bar exist yet? */
- if (NILP (w->vertical_scroll_bar))
- {
- BLOCK_INPUT;
- XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
- left, top, width, height, 0);
- UNBLOCK_INPUT;
- bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
- disp_height);
- XSETVECTOR (w->vertical_scroll_bar, bar);
- }
- else
- {
- /* It may just need to be moved and resized. */
- ControlHandle ch;
-
- bar = XSCROLL_BAR (w->vertical_scroll_bar);
- ch = SCROLL_BAR_CONTROL_HANDLE (bar);
-
- BLOCK_INPUT;
-
- /* If already correctly positioned, do nothing. */
- if (XINT (bar->left) == sb_left
- && XINT (bar->top) == top
- && XINT (bar->width) == sb_width
- && XINT (bar->height) == height)
- Draw1Control (ch);
- else
- {
- if (sb_left + sb_width >= PIXEL_WIDTH (f))
- XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
- sb_left - 1, top, 1, height, 0);
-
- HideControl (ch);
- MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
- SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
- disp_height);
- ShowControl (ch);
-
- /* Remember new settings. */
- XSETINT (bar->left, sb_left);
- XSETINT (bar->top, top);
- XSETINT (bar->width, sb_width);
- XSETINT (bar->height, height);
- }
-
- UNBLOCK_INPUT;
- }
-
- /* Set the scroll bar's current state, unless we're currently being
- dragged. */
- if (NILP (bar->dragging))
- {
- int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
-
- if (whole == 0)
- x_scroll_bar_set_handle (bar, 0, top_range, 0);
- else
- {
- int start = ((double) position * top_range) / whole;
- int end = ((double) (position + portion) * top_range) / whole;
- x_scroll_bar_set_handle (bar, start, end, 0);
- }
- }
-}
-
-
-/* The following three hooks are used when we're doing a thorough
- redisplay of the frame. We don't explicitly know which scroll bars
- are going to be deleted, because keeping track of when windows go
- away is a real pain - "Can you say set-window-configuration, boys
- and girls?" Instead, we just assert at the beginning of redisplay
- that *all* scroll bars are to be removed, and then save a scroll bar
- from the fiery pit when we actually redisplay its window. */
-
-/* Arrange for all scroll bars on FRAME to be removed at the next call
- to `*judge_scroll_bars_hook'. A scroll bar may be spared if
- `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
-
-static void
-XTcondemn_scroll_bars (frame)
- FRAME_PTR frame;
-{
- /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
- while (! NILP (FRAME_SCROLL_BARS (frame)))
- {
- Lisp_Object bar;
- bar = FRAME_SCROLL_BARS (frame);
- FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
- XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
- XSCROLL_BAR (bar)->prev = Qnil;
- if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
- XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
- FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
- }
-}
-
-/* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
- Note that WINDOW isn't necessarily condemned at all. */
-static void
-XTredeem_scroll_bar (window)
- struct window *window;
-{
- struct scroll_bar *bar;
-
- /* We can't redeem this window's scroll bar if it doesn't have one. */
- if (NILP (window->vertical_scroll_bar))
- abort ();
-
- bar = XSCROLL_BAR (window->vertical_scroll_bar);
-
- /* Unlink it from the condemned list. */
- {
- FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
-
- if (NILP (bar->prev))
- {
- /* If the prev pointer is nil, it must be the first in one of
- the lists. */
- if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
- /* It's not condemned. Everything's fine. */
- return;
- else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
- window->vertical_scroll_bar))
- FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
- else
- /* If its prev pointer is nil, it must be at the front of
- one or the other! */
- abort ();
- }
- else
- XSCROLL_BAR (bar->prev)->next = bar->next;
-
- if (! NILP (bar->next))
- XSCROLL_BAR (bar->next)->prev = bar->prev;
-
- bar->next = FRAME_SCROLL_BARS (f);
- bar->prev = Qnil;
- XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
- if (! NILP (bar->next))
- XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
- }
-}
-
-/* Remove all scroll bars on FRAME that haven't been saved since the
- last call to `*condemn_scroll_bars_hook'. */
-
-static void
-XTjudge_scroll_bars (f)
- FRAME_PTR f;
-{
- Lisp_Object bar, next;
-
- bar = FRAME_CONDEMNED_SCROLL_BARS (f);
-
- /* Clear out the condemned list now so we won't try to process any
- more events on the hapless scroll bars. */
- FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
-
- for (; ! NILP (bar); bar = next)
- {
- struct scroll_bar *b = XSCROLL_BAR (bar);
-
- x_scroll_bar_remove (b);
-
- next = b->next;
- b->next = b->prev = Qnil;
- }
-
- /* Now there should be no references to the condemned scroll bars,
- and they should get garbage-collected. */
-}
-
-
-static void
-activate_scroll_bars (frame)
- FRAME_PTR frame;
-{
- Lisp_Object bar;
- ControlHandle ch;
-
- bar = FRAME_SCROLL_BARS (frame);
- while (! NILP (bar))
- {
- ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
- SetControlMaximum (ch,
- VERTICAL_SCROLL_BAR_TOP_RANGE (frame,
- XINT (XSCROLL_BAR (bar)
- ->height)) - 1);
-
- bar = XSCROLL_BAR (bar)->next;
- }
-}
-
-
-static void
-deactivate_scroll_bars (frame)
- FRAME_PTR frame;
-{
- Lisp_Object bar;
- ControlHandle ch;
-
- bar = FRAME_SCROLL_BARS (frame);
- while (! NILP (bar))
- {
- ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
- SetControlMaximum (ch, XINT (-1));
-
- bar = XSCROLL_BAR (bar)->next;
- }
-}
-
-/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
- is set to something other than no_event, it is enqueued.
-
- This may be called from a signal handler, so we have to ignore GC
- mark bits. */
-
-static void
-x_scroll_bar_handle_click (bar, part_code, er, bufp)
- struct scroll_bar *bar;
- int part_code;
- EventRecord *er;
- struct input_event *bufp;
-{
- if (! GC_WINDOWP (bar->window))
- abort ();
-
- bufp->kind = scroll_bar_click;
- bufp->frame_or_window = bar->window;
- bufp->arg = Qnil;
-
- bar->dragging = Qnil;
-
- switch (part_code)
- {
- case kControlUpButtonPart:
- bufp->part = scroll_bar_up_arrow;
- break;
- case kControlDownButtonPart:
- bufp->part = scroll_bar_down_arrow;
- break;
- case kControlPageUpPart:
- bufp->part = scroll_bar_above_handle;
- break;
- case kControlPageDownPart:
- bufp->part = scroll_bar_below_handle;
- break;
- case kControlIndicatorPart:
- if (er->what == mouseDown)
- bar->dragging = make_number (0);
- XSETVECTOR (last_mouse_scroll_bar, bar);
- bufp->part = scroll_bar_handle;
- break;
- }
-}
-
-
-/* Handle some mouse motion while someone is dragging the scroll bar.
-
- This may be called from a signal handler, so we have to ignore GC
- mark bits. */
-
-static void
-x_scroll_bar_note_movement (bar, y_pos, t)
- struct scroll_bar *bar;
- int y_pos;
- Time t;
-{
- FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
-
- last_mouse_movement_time = t;
-
- f->mouse_moved = 1;
- XSETVECTOR (last_mouse_scroll_bar, bar);
-
- /* If we're dragging the bar, display it. */
- if (! GC_NILP (bar->dragging))
- {
- /* Where should the handle be now? */
- int new_start = y_pos - 24;
-
- if (new_start != XINT (bar->start))
- {
- int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
-
- x_scroll_bar_set_handle (bar, new_start, new_end, 0);
- }
- }
-}
-
-
-/* Return information to the user about the current position of the
- mouse on the scroll bar. */
-
-static void
-x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
- FRAME_PTR *fp;
- Lisp_Object *bar_window;
- enum scroll_bar_part *part;
- Lisp_Object *x, *y;
- unsigned long *time;
-{
- struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
- WindowPtr wp = FrontWindow ();
- Point mouse_pos;
- struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
- int win_y, top_range;
-
- SetPort (wp);
- GetMouse (&mouse_pos);
-
- win_y = mouse_pos.v - XINT (bar->top);
- top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
-
- win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
-
- win_y -= 24;
-
- if (! NILP (bar->dragging))
- win_y -= XINT (bar->dragging);
-
- if (win_y < 0)
- win_y = 0;
- if (win_y > top_range)
- win_y = top_range;
-
- *fp = f;
- *bar_window = bar->window;
-
- if (! NILP (bar->dragging))
- *part = scroll_bar_handle;
- else if (win_y < XINT (bar->start))
- *part = scroll_bar_above_handle;
- else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
- *part = scroll_bar_handle;
- else
- *part = scroll_bar_below_handle;
-
- XSETINT (*x, win_y);
- XSETINT (*y, top_range);
-
- f->mouse_moved = 0;
- last_mouse_scroll_bar = Qnil;
-
- *time = last_mouse_movement_time;
-}
-\f
-/***********************************************************************
- Text Cursor
- ***********************************************************************/
-
-/* Note if the text cursor of window W has been overwritten by a
- drawing operation that outputs N glyphs starting at HPOS in the
- line given by output_cursor.vpos. N < 0 means all the rest of the
- line after HPOS has been written. */
-
-static void
-note_overwritten_text_cursor (w, hpos, n)
- struct window *w;
- int hpos, n;
-{
- if (updated_area == TEXT_AREA
- && output_cursor.vpos == w->phys_cursor.vpos
- && hpos <= w->phys_cursor.hpos
- && (n < 0
- || hpos + n > w->phys_cursor.hpos))
- w->phys_cursor_on_p = 0;
-}
-
-
-/* Set clipping for output in glyph row ROW. W is the window in which
- we operate. GC is the graphics context to set clipping in.
- WHOLE_LINE_P non-zero means include the areas used for truncation
- mark display and alike in the clipping rectangle.
-
- ROW may be a text row or, e.g., a mode line. Text rows must be
- clipped to the interior of the window dedicated to text display,
- mode lines must be clipped to the whole window. */
-
-static void
-x_clip_to_row (w, row, gc, whole_line_p)
- struct window *w;
- struct glyph_row *row;
- GC gc;
- int whole_line_p;
-{
- struct frame *f = XFRAME (WINDOW_FRAME (w));
- Rect clip_rect;
- int window_x, window_y, window_width, window_height;
-
- window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
-
- clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
- clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
- clip_rect.top = max (clip_rect.top, window_y);
- clip_rect.right = clip_rect.left + window_width;
- clip_rect.bottom = clip_rect.top + row->visible_height;
-
- /* If clipping to the whole line, including trunc marks, extend
- the rectangle to the left and increase its width. */
- if (whole_line_p)
- {
- clip_rect.left -= FRAME_X_LEFT_FRINGE_WIDTH (f);
- clip_rect.right += FRAME_X_FRINGE_WIDTH (f);
- }
-
- mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
-}
-
-
-/* Draw a hollow box cursor on window W in glyph row ROW. */
-
-static void
-x_draw_hollow_cursor (w, row)
- struct window *w;
- struct glyph_row *row;
-{
- struct frame *f = XFRAME (WINDOW_FRAME (w));
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
- Display *dpy = FRAME_MAC_DISPLAY (f);
- int x, y, wd, h;
- XGCValues xgcv;
- struct glyph *cursor_glyph;
- GC gc;
-
- /* Compute frame-relative coordinates from window-relative
- coordinates. */
- x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
- y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
- + row->ascent - w->phys_cursor_ascent);
- h = row->height - 1;
-
- /* Get the glyph the cursor is on. If we can't tell because
- the current matrix is invalid or such, give up. */
- cursor_glyph = get_phys_cursor_glyph (w);
- if (cursor_glyph == NULL)
- return;
-
- /* Compute the width of the rectangle to draw. If on a stretch
- glyph, and `x-stretch-block-cursor' is nil, don't draw a
- rectangle as wide as the glyph, but use a canonical character
- width instead. */
- wd = cursor_glyph->pixel_width - 1;
- if (cursor_glyph->type == STRETCH_GLYPH
- && !x_stretch_cursor_p)
- wd = min (CANON_X_UNIT (f), wd);
-
- /* The foreground of cursor_gc is typically the same as the normal
- background color, which can cause the cursor box to be invisible. */
- xgcv.foreground = f->output_data.mac->cursor_pixel;
- if (dpyinfo->scratch_cursor_gc)
- XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
- else
- dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
- GCForeground, &xgcv);
- gc = dpyinfo->scratch_cursor_gc;
-
- /* Set clipping, draw the rectangle, and reset clipping again. */
- x_clip_to_row (w, row, gc, 0);
- mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
- mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
-}
-
-
-/* Draw a bar cursor on window W in glyph row ROW.
-
- Implementation note: One would like to draw a bar cursor with an
- angle equal to the one given by the font property XA_ITALIC_ANGLE.
- Unfortunately, I didn't find a font yet that has this property set.
- --gerd. */
-
-static void
-x_draw_bar_cursor (w, row, width)
- struct window *w;
- struct glyph_row *row;
- int width;
-{
- /* If cursor hpos is out of bounds, don't draw garbage. This can
- happen in mini-buffer windows when switching between echo area
- glyphs and mini-buffer. */
- if (w->phys_cursor.hpos < row->used[TEXT_AREA])
- {
- struct frame *f = XFRAME (w->frame);
- struct glyph *cursor_glyph;
- GC gc;
- int x;
- unsigned long mask;
- XGCValues xgcv;
- Display *dpy;
- Window window;
-
- cursor_glyph = get_phys_cursor_glyph (w);
- if (cursor_glyph == NULL)
- return;
-
- xgcv.background = f->output_data.mac->cursor_pixel;
- xgcv.foreground = f->output_data.mac->cursor_pixel;
- mask = GCForeground | GCBackground;
- dpy = FRAME_MAC_DISPLAY (f);
- window = FRAME_MAC_WINDOW (f);
- gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
-
- if (gc)
- XChangeGC (dpy, gc, mask, &xgcv);
- else
- {
- gc = XCreateGC (dpy, window, mask, &xgcv);
- FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
- }
-
- if (width < 0)
- width = f->output_data.mac->cursor_width;
-
- x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
- x_clip_to_row (w, row, gc, 0);
- XFillRectangle (dpy, window, gc,
- x,
- WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
- min (cursor_glyph->pixel_width, width),
- row->height);
- mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
- }
-}
-
-
-/* Clear the cursor of window W to background color, and mark the
- cursor as not shown. This is used when the text where the cursor
- is is about to be rewritten. */
-
-static void
-x_clear_cursor (w)
- struct window *w;
-{
- if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
- x_update_window_cursor (w, 0);
-}
-
-
-/* Draw the cursor glyph of window W in glyph row ROW. See the
- comment of x_draw_glyphs for the meaning of HL. */
-
-static void
-x_draw_phys_cursor_glyph (w, row, hl)
- struct window *w;
- struct glyph_row *row;
- enum draw_glyphs_face hl;
-{
- /* If cursor hpos is out of bounds, don't draw garbage. This can
- happen in mini-buffer windows when switching between echo area
- glyphs and mini-buffer. */
- if (w->phys_cursor.hpos < row->used[TEXT_AREA])
- {
- x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
- w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
- hl, 0, 0, 0);
-
- /* When we erase the cursor, and ROW is overlapped by other
- rows, make sure that these overlapping parts of other rows
- are redrawn. */
- if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
- {
- if (row > w->current_matrix->rows
- && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
- x_fix_overlapping_area (w, row - 1, TEXT_AREA);
-
- if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
- && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
- x_fix_overlapping_area (w, row + 1, TEXT_AREA);
- }
- }
-}
-
-
-/* Erase the image of a cursor of window W from the screen. */
-
-static void
-x_erase_phys_cursor (w)
- struct window *w;
-{
- struct frame *f = XFRAME (w->frame);
- struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
- int hpos = w->phys_cursor.hpos;
- int vpos = w->phys_cursor.vpos;
- int mouse_face_here_p = 0;
- struct glyph_matrix *active_glyphs = w->current_matrix;
- struct glyph_row *cursor_row;
- struct glyph *cursor_glyph;
- enum draw_glyphs_face hl;
-
- /* No cursor displayed or row invalidated => nothing to do on the
- screen. */
- if (w->phys_cursor_type == NO_CURSOR)
- goto mark_cursor_off;
-
- /* VPOS >= active_glyphs->nrows means that window has been resized.
- Don't bother to erase the cursor. */
- if (vpos >= active_glyphs->nrows)
- goto mark_cursor_off;
-
- /* If row containing cursor is marked invalid, there is nothing we
- can do. */
- cursor_row = MATRIX_ROW (active_glyphs, vpos);
- if (!cursor_row->enabled_p)
- goto mark_cursor_off;
-
- /* If row is completely invisible, don't attempt to delete a cursor which
- isn't there. This can happen if cursor is at top of a window, and
- we switch to a buffer with a header line in that window. */
- if (cursor_row->visible_height <= 0)
- goto mark_cursor_off;
-
- /* This can happen when the new row is shorter than the old one.
- In this case, either x_draw_glyphs or clear_end_of_line
- should have cleared the cursor. Note that we wouldn't be
- able to erase the cursor in this case because we don't have a
- cursor glyph at hand. */
- if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
- goto mark_cursor_off;
-
- /* If the cursor is in the mouse face area, redisplay that when
- we clear the cursor. */
- if (! NILP (dpyinfo->mouse_face_window)
- && w == XWINDOW (dpyinfo->mouse_face_window)
- && (vpos > dpyinfo->mouse_face_beg_row
- || (vpos == dpyinfo->mouse_face_beg_row
- && hpos >= dpyinfo->mouse_face_beg_col))
- && (vpos < dpyinfo->mouse_face_end_row
- || (vpos == dpyinfo->mouse_face_end_row
- && hpos < dpyinfo->mouse_face_end_col))
- /* Don't redraw the cursor's spot in mouse face if it is at the
- end of a line (on a newline). The cursor appears there, but
- mouse highlighting does not. */
- && cursor_row->used[TEXT_AREA] > hpos)
- mouse_face_here_p = 1;
-
- /* Maybe clear the display under the cursor. */
- if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
- {
- int x;
- int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
-
- cursor_glyph = get_phys_cursor_glyph (w);
- if (cursor_glyph == NULL)
- goto mark_cursor_off;
-
- x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
-
- XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
- x,
- WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
- cursor_row->y)),
- cursor_glyph->pixel_width,
- cursor_row->visible_height,
- 0);
- }
-
- /* Erase the cursor by redrawing the character underneath it. */
- if (mouse_face_here_p)
- hl = DRAW_MOUSE_FACE;
- else if (cursor_row->inverse_p)
- hl = DRAW_INVERSE_VIDEO;
- else
- hl = DRAW_NORMAL_TEXT;
- x_draw_phys_cursor_glyph (w, cursor_row, hl);
-
- mark_cursor_off:
- w->phys_cursor_on_p = 0;
- w->phys_cursor_type = NO_CURSOR;
-}
-
-
-/* Display or clear cursor of window W. If ON is zero, clear the
- cursor. If it is non-zero, display the cursor. If ON is nonzero,
- where to put the cursor is specified by HPOS, VPOS, X and Y. */
-
-void
-x_display_and_set_cursor (w, on, hpos, vpos, x, y)
- struct window *w;
- int on, hpos, vpos, x, y;
-{
- struct frame *f = XFRAME (w->frame);
- int new_cursor_type;
- int new_cursor_width;
- struct glyph_matrix *current_glyphs;
- struct glyph_row *glyph_row;
- struct glyph *glyph;
-
- /* This is pointless on invisible frames, and dangerous on garbaged
- windows and frames; in the latter case, the frame or window may
- be in the midst of changing its size, and x and y may be off the
- window. */
- if (! FRAME_VISIBLE_P (f)
- || FRAME_GARBAGED_P (f)
- || vpos >= w->current_matrix->nrows
- || hpos >= w->current_matrix->matrix_w)
- return;
-
- /* If cursor is off and we want it off, return quickly. */
- if (!on && !w->phys_cursor_on_p)
- return;
-
- current_glyphs = w->current_matrix;
- glyph_row = MATRIX_ROW (current_glyphs, vpos);
- glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
-
- /* If cursor row is not enabled, we don't really know where to
- display the cursor. */
- if (!glyph_row->enabled_p)
- {
- w->phys_cursor_on_p = 0;
- return;
- }
-
- xassert (interrupt_input_blocked);
-
- /* Set new_cursor_type to the cursor we want to be displayed. In a
- mini-buffer window, we want the cursor only to appear if we are
- reading input from this window. For the selected window, we want
- the cursor type given by the frame parameter. If explicitly
- marked off, draw no cursor. In all other cases, we want a hollow
- box cursor. */
- new_cursor_width = -1;
- if (cursor_in_echo_area
- && FRAME_HAS_MINIBUF_P (f)
- && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
- {
- if (w == XWINDOW (echo_area_window))
- new_cursor_type = FRAME_DESIRED_CURSOR (f);
- else
- new_cursor_type = HOLLOW_BOX_CURSOR;
- }
- else
- {
- if (w != XWINDOW (selected_window)
- || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
- {
- extern int cursor_in_non_selected_windows;
-
- if (MINI_WINDOW_P (w) || !cursor_in_non_selected_windows)
- new_cursor_type = NO_CURSOR;
- else
- new_cursor_type = HOLLOW_BOX_CURSOR;
- }
- else if (w->cursor_off_p)
- new_cursor_type = NO_CURSOR;
- else
- {
- struct buffer *b = XBUFFER (w->buffer);
-
- if (EQ (b->cursor_type, Qt))
- new_cursor_type = FRAME_DESIRED_CURSOR (f);
- else
- new_cursor_type = x_specified_cursor_type (b->cursor_type,
- &new_cursor_width);
- }
- }
-
- /* If cursor is currently being shown and we don't want it to be or
- it is in the wrong place, or the cursor type is not what we want,
- erase it. */
- if (w->phys_cursor_on_p
- && (!on
- || w->phys_cursor.x != x
- || w->phys_cursor.y != y
- || new_cursor_type != w->phys_cursor_type))
- x_erase_phys_cursor (w);
-
- /* If the cursor is now invisible and we want it to be visible,
- display it. */
- if (on && !w->phys_cursor_on_p)
- {
- w->phys_cursor_ascent = glyph_row->ascent;
- w->phys_cursor_height = glyph_row->height;
-
- /* Set phys_cursor_.* before x_draw_.* is called because some
- of them may need the information. */
- w->phys_cursor.x = x;
- w->phys_cursor.y = glyph_row->y;
- w->phys_cursor.hpos = hpos;
- w->phys_cursor.vpos = vpos;
- w->phys_cursor_type = new_cursor_type;
- w->phys_cursor_on_p = 1;
-
- switch (new_cursor_type)
- {
- case HOLLOW_BOX_CURSOR:
- x_draw_hollow_cursor (w, glyph_row);
- break;
-
- case FILLED_BOX_CURSOR:
- x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
- break;
-
- case BAR_CURSOR:
- x_draw_bar_cursor (w, glyph_row, new_cursor_width);
- break;
-
- case NO_CURSOR:
- break;
-
- default:
- abort ();
- }
-
-#ifdef HAVE_X_I18N
- if (w == XWINDOW (f->selected_window))
- if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
- xic_set_preeditarea (w, x, y);
-#endif
- }
-
-#ifndef XFlush
- if (updating_frame != f)
- XFlush (FRAME_X_DISPLAY (f));
-#endif
-}
-
-
-/* Display the cursor on window W, or clear it. X and Y are window
- relative pixel coordinates. HPOS and VPOS are glyph matrix
- positions. If W is not the selected window, display a hollow
- cursor. ON non-zero means display the cursor at X, Y which
- correspond to HPOS, VPOS, otherwise it is cleared. */
-
-void
-x_display_cursor (w, on, hpos, vpos, x, y)
- struct window *w;
- int on, hpos, vpos, x, y;
-{
- BLOCK_INPUT;
- x_display_and_set_cursor (w, on, hpos, vpos, x, y);
- UNBLOCK_INPUT;
-}
-
-
-/* Display the cursor on window W, or clear it, according to ON_P.
- Don't change the cursor's position. */
-
-void
-x_update_cursor (f, on_p)
- struct frame *f;
-{
- x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
-}
-
-
-/* Call x_update_window_cursor with parameter ON_P on all leaf windows
- in the window tree rooted at W. */
-
-static void
-x_update_cursor_in_window_tree (w, on_p)
- struct window *w;
- int on_p;
-{
- while (w)
- {
- if (!NILP (w->hchild))
- x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
- else if (!NILP (w->vchild))
- x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
- else
- x_update_window_cursor (w, on_p);
-
- w = NILP (w->next) ? 0 : XWINDOW (w->next);
- }
-}
-
-
-/* Switch the display of W's cursor on or off, according to the value
- of ON. */
-
-static void
-x_update_window_cursor (w, on)
- struct window *w;
- int on;
-{
- /* Don't update cursor in windows whose frame is in the process
- of being deleted. */
- if (w->current_matrix)
- {
- BLOCK_INPUT;
- x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
- w->phys_cursor.x, w->phys_cursor.y);
- UNBLOCK_INPUT;
- }
-}
-
-\f
-#if 0 /* MAC_TODO: no icon and X error handling (?) */
-/* Icons. */
-
-/* Refresh bitmap kitchen sink icon for frame F
- when we get an expose event for it. */
-
-void
-refreshicon (f)
- struct frame *f;
-{
- /* Normally, the window manager handles this function. */
-}
-
-/* Make the x-window of frame F use the gnu icon bitmap. */
-
-int
-x_bitmap_icon (f, file)
- struct frame *f;
- Lisp_Object file;
-{
- int bitmap_id;
-
- if (FRAME_X_WINDOW (f) == 0)
- return 1;
-
- /* Free up our existing icon bitmap if any. */
- if (f->output_data.x->icon_bitmap > 0)
- x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
- f->output_data.x->icon_bitmap = 0;
-
- if (STRINGP (file))
- bitmap_id = x_create_bitmap_from_file (f, file);
- else
- {
- /* Create the GNU bitmap if necessary. */
- if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
- FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
- = x_create_bitmap_from_data (f, gnu_bits,
- gnu_width, gnu_height);
-
- /* The first time we create the GNU bitmap,
- this increments the ref-count one extra time.
- As a result, the GNU bitmap is never freed.
- That way, we don't have to worry about allocating it again. */
- x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
-
- bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
- }
-
- x_wm_set_icon_pixmap (f, bitmap_id);
- f->output_data.x->icon_bitmap = bitmap_id;
-
- return 0;
-}
-
-
-/* Make the x-window of frame F use a rectangle with text.
- Use ICON_NAME as the text. */
-
-int
-x_text_icon (f, icon_name)
- struct frame *f;
- char *icon_name;
-{
- if (FRAME_X_WINDOW (f) == 0)
- return 1;
-
-#ifdef HAVE_X11R4
- {
- XTextProperty text;
- text.value = (unsigned char *) icon_name;
- text.encoding = XA_STRING;
- text.format = 8;
- text.nitems = strlen (icon_name);
-#ifdef USE_X_TOOLKIT
- XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
- &text);
-#else /* not USE_X_TOOLKIT */
- XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
-#endif /* not USE_X_TOOLKIT */
- }
-#else /* not HAVE_X11R4 */
- XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
-#endif /* not HAVE_X11R4 */
-
- if (f->output_data.x->icon_bitmap > 0)
- x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
- f->output_data.x->icon_bitmap = 0;
- x_wm_set_icon_pixmap (f, 0);
-
- return 0;
-}
-\f
-#define X_ERROR_MESSAGE_SIZE 200
-
-/* If non-nil, this should be a string.
- It means catch X errors and store the error message in this string. */
-
-static Lisp_Object x_error_message_string;
-
-/* An X error handler which stores the error message in
- x_error_message_string. This is called from x_error_handler if
- x_catch_errors is in effect. */
-
-static void
-x_error_catcher (display, error)
- Display *display;
- XErrorEvent *error;
-{
- XGetErrorText (display, error->error_code,
- XSTRING (x_error_message_string)->data,
- X_ERROR_MESSAGE_SIZE);
-}
-
-/* Begin trapping X errors for display DPY. Actually we trap X errors
- for all displays, but DPY should be the display you are actually
- operating on.
-
- After calling this function, X protocol errors no longer cause
- Emacs to exit; instead, they are recorded in the string
- stored in x_error_message_string.
-
- Calling x_check_errors signals an Emacs error if an X error has
- occurred since the last call to x_catch_errors or x_check_errors.
-
- Calling x_uncatch_errors resumes the normal error handling. */
-
-void x_check_errors ();
-static Lisp_Object x_catch_errors_unwind ();
-
-int
-x_catch_errors (dpy)
- Display *dpy;
-{
- int count = specpdl_ptr - specpdl;
-
- /* Make sure any errors from previous requests have been dealt with. */
- XSync (dpy, False);
-
- record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
-
- x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
- XSTRING (x_error_message_string)->data[0] = 0;
-
- return count;
-}
-
-/* Unbind the binding that we made to check for X errors. */
-
-static Lisp_Object
-x_catch_errors_unwind (old_val)
- Lisp_Object old_val;
-{
- x_error_message_string = old_val;
- return Qnil;
-}
-
-/* If any X protocol errors have arrived since the last call to
- x_catch_errors or x_check_errors, signal an Emacs error using
- sprintf (a buffer, FORMAT, the x error message text) as the text. */
-
-void
-x_check_errors (dpy, format)
- Display *dpy;
- char *format;
-{
- /* Make sure to catch any errors incurred so far. */
- XSync (dpy, False);
-
- if (XSTRING (x_error_message_string)->data[0])
- error (format, XSTRING (x_error_message_string)->data);
-}
-
-/* Nonzero if we had any X protocol errors
- since we did x_catch_errors on DPY. */
-
-int
-x_had_errors_p (dpy)
- Display *dpy;
-{
- /* Make sure to catch any errors incurred so far. */
- XSync (dpy, False);
-
- return XSTRING (x_error_message_string)->data[0] != 0;
-}
-
-/* Forget about any errors we have had, since we did x_catch_errors on DPY. */
-
-void
-x_clear_errors (dpy)
- Display *dpy;
-{
- XSTRING (x_error_message_string)->data[0] = 0;
-}
-
-/* Stop catching X protocol errors and let them make Emacs die.
- DPY should be the display that was passed to x_catch_errors.
- COUNT should be the value that was returned by
- the corresponding call to x_catch_errors. */
-
-void
-x_uncatch_errors (dpy, count)
- Display *dpy;
- int count;
-{
- unbind_to (count, Qnil);
-}
-
-#if 0
-static unsigned int x_wire_count;
-x_trace_wire ()
-{
- fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
-}
-#endif /* ! 0 */
-
-\f
-/* Handle SIGPIPE, which can happen when the connection to a server
- simply goes away. SIGPIPE is handled by x_connection_signal.
- Don't need to do anything, because the write which caused the
- SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
- which will do the appropriate cleanup for us. */
-
-static SIGTYPE
-x_connection_signal (signalnum) /* If we don't have an argument, */
- int signalnum; /* some compilers complain in signal calls. */
-{
-#ifdef USG
- /* USG systems forget handlers when they are used;
- must reestablish each time */
- signal (signalnum, x_connection_signal);
-#endif /* USG */
-}
-\f
-/* Handling X errors. */
-
-/* Handle the loss of connection to display DISPLAY. */
-
-static SIGTYPE
-x_connection_closed (display, error_message)
- Display *display;
- char *error_message;
-{
- struct x_display_info *dpyinfo = x_display_info_for_display (display);
- Lisp_Object frame, tail;
-
- /* Indicate that this display is dead. */
-
-#if 0 /* Closing the display caused a bus error on OpenWindows. */
-#ifdef USE_X_TOOLKIT
- XtCloseDisplay (display);
-#endif
-#endif
-
- if (dpyinfo)
- dpyinfo->display = 0;
-
- /* First delete frames whose mini-buffers are on frames
- that are on the dead display. */
- FOR_EACH_FRAME (tail, frame)
- {
- Lisp_Object minibuf_frame;
- minibuf_frame
- = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
- if (FRAME_X_P (XFRAME (frame))
- && FRAME_X_P (XFRAME (minibuf_frame))
- && ! EQ (frame, minibuf_frame)
- && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
- Fdelete_frame (frame, Qt);
- }
-
- /* Now delete all remaining frames on the dead display.
- We are now sure none of these is used as the mini-buffer
- for another frame that we need to delete. */
- FOR_EACH_FRAME (tail, frame)
- if (FRAME_X_P (XFRAME (frame))
- && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
- {
- /* Set this to t so that Fdelete_frame won't get confused
- trying to find a replacement. */
- FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
- Fdelete_frame (frame, Qt);
- }
-
- if (dpyinfo)
- x_delete_display (dpyinfo);
-
- if (x_display_list == 0)
- {
- fprintf (stderr, "%s\n", error_message);
- shut_down_emacs (0, 0, Qnil);
- exit (70);
- }
-
- /* Ordinary stack unwind doesn't deal with these. */
-#ifdef SIGIO
- sigunblock (sigmask (SIGIO));
-#endif
- sigunblock (sigmask (SIGALRM));
- TOTALLY_UNBLOCK_INPUT;
-
- clear_waiting_for_input ();
- error ("%s", error_message);
-}
-
-/* This is the usual handler for X protocol errors.
- It kills all frames on the display that we got the error for.
- If that was the only one, it prints an error message and kills Emacs. */
-
-static void
-x_error_quitter (display, error)
- Display *display;
- XErrorEvent *error;
-{
- char buf[256], buf1[356];
-
- /* Note that there is no real way portable across R3/R4 to get the
- original error handler. */
-
- XGetErrorText (display, error->error_code, buf, sizeof (buf));
- sprintf (buf1, "X protocol error: %s on protocol request %d",
- buf, error->request_code);
- x_connection_closed (display, buf1);
-}
-
-/* This is the first-level handler for X protocol errors.
- It calls x_error_quitter or x_error_catcher. */
-
-static int
-x_error_handler (display, error)
- Display *display;
- XErrorEvent *error;
-{
- if (! NILP (x_error_message_string))
- x_error_catcher (display, error);
- else
- x_error_quitter (display, error);
- return 0;
-}
-
-/* This is the handler for X IO errors, always.
- It kills all frames on the display that we lost touch with.
- If that was the only one, it prints an error message and kills Emacs. */
-
-static int
-x_io_error_quitter (display)
- Display *display;
-{
- char buf[256];
-
- sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
- x_connection_closed (display, buf);
- return 0;
-}
-#endif
-\f
-/* Changing the font of the frame. */
-
-/* Give frame F the font named FONTNAME as its default font, and
- return the full name of that font. FONTNAME may be a wildcard
- pattern; in that case, we choose some font that fits the pattern.
- The return value shows which font we chose. */
-
-Lisp_Object
-x_new_font (f, fontname)
- struct frame *f;
- register char *fontname;
-{
- struct font_info *fontp
- = FS_LOAD_FONT (f, 0, fontname, -1);
-
- if (!fontp)
- return Qnil;
-
- f->output_data.mac->font = (XFontStruct *) (fontp->font);
- f->output_data.mac->baseline_offset = fontp->baseline_offset;
- f->output_data.mac->fontset = -1;
-
- /* Compute the scroll bar width in character columns. */
- if (f->scroll_bar_pixel_width > 0)
- {
- int wid = FONT_WIDTH (f->output_data.mac->font);
- f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
- }
- else
- {
- int wid = FONT_WIDTH (f->output_data.mac->font);
- f->scroll_bar_cols = (14 + wid - 1) / wid;
- }
-
- /* Now make the frame display the given font. */
- if (FRAME_MAC_WINDOW (f) != 0)
- {
- XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
- f->output_data.mac->font);
- XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
- f->output_data.mac->font);
- XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
- f->output_data.mac->font);
-
- frame_update_line_height (f);
- x_set_window_size (f, 0, f->width, f->height);
- }
- else
- /* If we are setting a new frame's font for the first time, there
- are no faces yet, so this font's height is the line height. */
- f->output_data.mac->line_height = FONT_HEIGHT (f->output_data.mac->font);
-
- return build_string (fontp->full_name);
-}
-
-/* Give frame F the fontset named FONTSETNAME as its default font, and
- return the full name of that fontset. FONTSETNAME may be a
- wildcard pattern; in that case, we choose some fontset that fits
- the pattern. The return value shows which fontset we chose. */
-
-Lisp_Object
-x_new_fontset (f, fontsetname)
- struct frame *f;
- char *fontsetname;
-{
- int fontset = fs_query_fontset (build_string (fontsetname), 0);
- Lisp_Object result;
-
- if (fontset < 0)
- return Qnil;
-
- if (f->output_data.mac->fontset == fontset)
- /* This fontset is already set in frame F. There's nothing more
- to do. */
- return fontset_name (fontset);
-
- result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
-
- if (!STRINGP (result))
- /* Can't load ASCII font. */
- return Qnil;
-
- /* Since x_new_font doesn't update any fontset information, do it
- now. */
- f->output_data.mac->fontset = fontset;
-
-#ifdef HAVE_X_I18N
- if (FRAME_XIC (f)
- && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
- xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
-#endif
-
- return build_string (fontsetname);
-}
-
-/* Compute actual fringe widths */
-
-void
-x_compute_fringe_widths (f, redraw)
- struct frame *f;
- int redraw;
-{
- int o_left = f->output_data.mac->left_fringe_width;
- int o_right = f->output_data.mac->right_fringe_width;
- int o_cols = f->output_data.mac->fringe_cols;
-
- Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
- Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
- int left_fringe_width, right_fringe_width;
-
- if (!NILP (left_fringe))
- left_fringe = Fcdr (left_fringe);
- if (!NILP (right_fringe))
- right_fringe = Fcdr (right_fringe);
-
- left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
- XINT (left_fringe));
- right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
- XINT (right_fringe));
-
- if (left_fringe_width || right_fringe_width)
- {
- int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
- int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
- int conf_wid = left_wid + right_wid;
- int font_wid = FONT_WIDTH (f->output_data.mac->font);
- int cols = (left_wid + right_wid + font_wid-1) / font_wid;
- int real_wid = cols * font_wid;
- if (left_wid && right_wid)
- {
- if (left_fringe_width < 0)
- {
- /* Left fringe width is fixed, adjust right fringe if necessary */
- f->output_data.mac->left_fringe_width = left_wid;
- f->output_data.mac->right_fringe_width = real_wid - left_wid;
- }
- else if (right_fringe_width < 0)
- {
- /* Right fringe width is fixed, adjust left fringe if necessary */
- f->output_data.mac->left_fringe_width = real_wid - right_wid;
- f->output_data.mac->right_fringe_width = right_wid;
- }
- else
- {
- /* Adjust both fringes with an equal amount.
- Note that we are doing integer arithmetic here, so don't
- lose a pixel if the total width is an odd number. */
- int fill = real_wid - conf_wid;
- f->output_data.mac->left_fringe_width = left_wid + fill/2;
- f->output_data.mac->right_fringe_width = right_wid + fill - fill/2;
- }
- }
- else if (left_fringe_width)
- {
- f->output_data.mac->left_fringe_width = real_wid;
- f->output_data.mac->right_fringe_width = 0;
- }
- else
- {
- f->output_data.mac->left_fringe_width = 0;
- f->output_data.mac->right_fringe_width = real_wid;
- }
- f->output_data.mac->fringe_cols = cols;
- f->output_data.mac->fringes_extra = real_wid;
- }
- else
- {
- f->output_data.mac->left_fringe_width = 0;
- f->output_data.mac->right_fringe_width = 0;
- f->output_data.mac->fringe_cols = 0;
- f->output_data.mac->fringes_extra = 0;
- }
-
- if (redraw && FRAME_VISIBLE_P (f))
- if (o_left != f->output_data.mac->left_fringe_width ||
- o_right != f->output_data.mac->right_fringe_width ||
- o_cols != f->output_data.mac->fringe_cols)
- redraw_frame (f);
-}
-\f
-#if 0 /* MAC_TODO: inline input methods for Mac */
-/***********************************************************************
- X Input Methods
- ***********************************************************************/
-
-#ifdef HAVE_X_I18N
-
-#ifdef HAVE_X11R6
-
-/* XIM destroy callback function, which is called whenever the
- connection to input method XIM dies. CLIENT_DATA contains a
- pointer to the x_display_info structure corresponding to XIM. */
-
-static void
-xim_destroy_callback (xim, client_data, call_data)
- XIM xim;
- XPointer client_data;
- XPointer call_data;
-{
- struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
- Lisp_Object frame, tail;
-
- BLOCK_INPUT;
-
- /* No need to call XDestroyIC.. */
- FOR_EACH_FRAME (tail, frame)
- {
- struct frame *f = XFRAME (frame);
- if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
- {
- FRAME_XIC (f) = NULL;
- if (FRAME_XIC_FONTSET (f))
- {
- XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
- FRAME_XIC_FONTSET (f) = NULL;
- }
- }
- }
-
- /* No need to call XCloseIM. */
- dpyinfo->xim = NULL;
- XFree (dpyinfo->xim_styles);
- UNBLOCK_INPUT;
-}
-
-#endif /* HAVE_X11R6 */
-
-/* Open the connection to the XIM server on display DPYINFO.
- RESOURCE_NAME is the resource name Emacs uses. */
-
-static void
-xim_open_dpy (dpyinfo, resource_name)
- struct x_display_info *dpyinfo;
- char *resource_name;
-{
-#ifdef USE_XIM
- XIM xim;
-
- xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
- dpyinfo->xim = xim;
-
- if (xim)
- {
-#ifdef HAVE_X11R6
- XIMCallback destroy;
-#endif
-
- /* Get supported styles and XIM values. */
- XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
-
-#ifdef HAVE_X11R6
- destroy.callback = xim_destroy_callback;
- destroy.client_data = (XPointer)dpyinfo;
- /* This isn't prototyped in OSF 5.0. */
- XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
-#endif
- }
-
-#else /* not USE_XIM */
- dpyinfo->xim = NULL;
-#endif /* not USE_XIM */
-}
-
-
-#ifdef HAVE_X11R6_XIM
-
-struct xim_inst_t
-{
- struct x_display_info *dpyinfo;
- char *resource_name;
-};
-
-/* XIM instantiate callback function, which is called whenever an XIM
- server is available. DISPLAY is teh display of the XIM.
- CLIENT_DATA contains a pointer to an xim_inst_t structure created
- when the callback was registered. */
-
-static void
-xim_instantiate_callback (display, client_data, call_data)
- Display *display;
- XPointer client_data;
- XPointer call_data;
-{
- struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
- struct x_display_info *dpyinfo = xim_inst->dpyinfo;
-
- /* We don't support multiple XIM connections. */
- if (dpyinfo->xim)
- return;
-
- xim_open_dpy (dpyinfo, xim_inst->resource_name);
-
- /* Create XIC for the existing frames on the same display, as long
- as they have no XIC. */
- if (dpyinfo->xim && dpyinfo->reference_count > 0)
- {
- Lisp_Object tail, frame;
-
- BLOCK_INPUT;
- FOR_EACH_FRAME (tail, frame)
- {
- struct frame *f = XFRAME (frame);
-
- if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
- if (FRAME_XIC (f) == NULL)
- {
- create_frame_xic (f);
- if (FRAME_XIC_STYLE (f) & XIMStatusArea)
- xic_set_statusarea (f);
- if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
- {
- struct window *w = XWINDOW (f->selected_window);
- xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
- }
- }
- }
-
- UNBLOCK_INPUT;
- }
-}
-
-#endif /* HAVE_X11R6_XIM */
-
-
-/* Open a connection to the XIM server on display DPYINFO.
- RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
- connection only at the first time. On X11R6, open the connection
- in the XIM instantiate callback function. */
-
-static void
-xim_initialize (dpyinfo, resource_name)
- struct x_display_info *dpyinfo;
- char *resource_name;
-{
-#ifdef USE_XIM
-#ifdef HAVE_X11R6_XIM
- struct xim_inst_t *xim_inst;
- int len;
-
- dpyinfo->xim = NULL;
- xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
- xim_inst->dpyinfo = dpyinfo;
- len = strlen (resource_name);
- xim_inst->resource_name = (char *) xmalloc (len + 1);
- bcopy (resource_name, xim_inst->resource_name, len + 1);
- XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
- resource_name, EMACS_CLASS,
- xim_instantiate_callback,
- /* Fixme: This is XPointer in
- XFree86 but (XPointer *) on
- Tru64, at least. */
- (XPointer) xim_inst);
-#else /* not HAVE_X11R6_XIM */
- dpyinfo->xim = NULL;
- xim_open_dpy (dpyinfo, resource_name);
-#endif /* not HAVE_X11R6_XIM */
-
-#else /* not USE_XIM */
- dpyinfo->xim = NULL;
-#endif /* not USE_XIM */
-}
-
-
-/* Close the connection to the XIM server on display DPYINFO. */
-
-static void
-xim_close_dpy (dpyinfo)
- struct x_display_info *dpyinfo;
-{
-#ifdef USE_XIM
-#ifdef HAVE_X11R6_XIM
- XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
- NULL, EMACS_CLASS,
- xim_instantiate_callback, NULL);
-#endif /* not HAVE_X11R6_XIM */
- XCloseIM (dpyinfo->xim);
- dpyinfo->xim = NULL;
- XFree (dpyinfo->xim_styles);
-#endif /* USE_XIM */
-}
-
-#endif /* not HAVE_X11R6_XIM */
-
-#endif
-\f
-/* Calculate the absolute position in frame F
- from its current recorded position values and gravity. */
-
-static void
-x_calc_absolute_position (f)
- struct frame *f;
-{
- Point pt;
- int flags = f->output_data.mac->size_hint_flags;
-
- pt.h = pt.v = 0;
-
- /* Find the position of the outside upper-left corner of
- the inner window, with respect to the outer window. */
- if (f->output_data.mac->parent_desc != FRAME_MAC_DISPLAY_INFO (f)->root_window)
- {
- GrafPtr savePort;
- GetPort (&savePort);
- SetPort (FRAME_MAC_WINDOW (f));
- SetPt(&pt, FRAME_MAC_WINDOW (f)->portRect.left, FRAME_MAC_WINDOW (f)->portRect.top);
- LocalToGlobal (&pt);
- SetPort (savePort);
- }
-
- /* Treat negative positions as relative to the leftmost bottommost
- position that fits on the screen. */
- if (flags & XNegative)
- f->output_data.mac->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
- - 2 * f->output_data.mac->border_width - pt.h
- - PIXEL_WIDTH (f)
- + f->output_data.mac->left_pos);
- /* NTEMACS_TODO: Subtract menubar height? */
- if (flags & YNegative)
- f->output_data.mac->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
- - 2 * f->output_data.mac->border_width - pt.v
- - PIXEL_HEIGHT (f)
- + f->output_data.mac->top_pos);
- /* The left_pos and top_pos
- are now relative to the top and left screen edges,
- so the flags should correspond. */
- f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
-}
-
-/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
- to really change the position, and 0 when calling from
- x_make_frame_visible (in that case, XOFF and YOFF are the current
- position values). It is -1 when calling from x_set_frame_parameters,
- which means, do adjust for borders but don't change the gravity. */
-
-void
-x_set_offset (f, xoff, yoff, change_gravity)
- struct frame *f;
- register int xoff, yoff;
- int change_gravity;
-{
- if (change_gravity > 0)
- {
- f->output_data.mac->top_pos = yoff;
- f->output_data.mac->left_pos = xoff;
- f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
- if (xoff < 0)
- f->output_data.mac->size_hint_flags |= XNegative;
- if (yoff < 0)
- f->output_data.mac->size_hint_flags |= YNegative;
- f->output_data.mac->win_gravity = NorthWestGravity;
- }
- x_calc_absolute_position (f);
-
- BLOCK_INPUT;
- x_wm_set_size_hint (f, (long) 0, 0);
-
- MoveWindow (f->output_data.mac->mWP, xoff + 6, yoff + 42, false);
-
- UNBLOCK_INPUT;
-}
-
-/* Call this to change the size of frame F's x-window.
- If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
- for this size change and subsequent size changes.
- Otherwise we leave the window gravity unchanged. */
-
-void
-x_set_window_size (f, change_gravity, cols, rows)
- struct frame *f;
- int change_gravity;
- int cols, rows;
-{
- int pixelwidth, pixelheight;
-
- check_frame_size (f, &rows, &cols);
- f->output_data.mac->vertical_scroll_bar_extra
- = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
- ? 0
- : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
- ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
- : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.mac->font)));
-
- x_compute_fringe_widths (f, 0);
-
- pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
- pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
-
- f->output_data.mac->win_gravity = NorthWestGravity;
- x_wm_set_size_hint (f, (long) 0, 0);
-
- SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
-
- /* Now, strictly speaking, we can't be sure that this is accurate,
- but the window manager will get around to dealing with the size
- change request eventually, and we'll hear how it went when the
- ConfigureNotify event gets here.
-
- We could just not bother storing any of this information here,
- and let the ConfigureNotify event set everything up, but that
- might be kind of confusing to the Lisp code, since size changes
- wouldn't be reported in the frame parameters until some random
- point in the future when the ConfigureNotify event arrives.
-
- We pass 1 for DELAY since we can't run Lisp code inside of
- a BLOCK_INPUT. */
- change_frame_size (f, rows, cols, 0, 1, 0);
- PIXEL_WIDTH (f) = pixelwidth;
- PIXEL_HEIGHT (f) = pixelheight;
-
- /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
- receive in the ConfigureNotify event; if we get what we asked
- for, then the event won't cause the screen to become garbaged, so
- we have to make sure to do it here. */
- SET_FRAME_GARBAGED (f);
-
- XFlush (FRAME_X_DISPLAY (f));
-
- /* If cursor was outside the new size, mark it as off. */
- mark_window_cursors_off (XWINDOW (f->root_window));
-
- /* Clear out any recollection of where the mouse highlighting was,
- since it might be in a place that's outside the new frame size.
- Actually checking whether it is outside is a pain in the neck,
- so don't try--just let the highlighting be done afresh with new size. */
- cancel_mouse_face (f);
-}
-\f
-/* Mouse warping. */
-
-void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
-
-void
-x_set_mouse_position (f, x, y)
- struct frame *f;
- int x, y;
-{
- int pix_x, pix_y;
-
- pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.mac->font) / 2;
- pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.mac->line_height / 2;
-
- if (pix_x < 0) pix_x = 0;
- if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
-
- if (pix_y < 0) pix_y = 0;
- if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
-
- x_set_mouse_pixel_position (f, pix_x, pix_y);
-}
-
-/* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
-
-void
-x_set_mouse_pixel_position (f, pix_x, pix_y)
- struct frame *f;
- int pix_x, pix_y;
-{
-#if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
- BLOCK_INPUT;
-
- XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
- 0, 0, 0, 0, pix_x, pix_y);
- UNBLOCK_INPUT;
-#endif
-}
-\f
-/* focus shifting, raising and lowering. */
-
-static void
-x_focus_on_frame (f)
- struct frame *f;
-{
-#if 0 /* This proves to be unpleasant. */
- x_raise_frame (f);
-#endif
-#if 0
- /* I don't think that the ICCCM allows programs to do things like this
- without the interaction of the window manager. Whatever you end up
- doing with this code, do it to x_unfocus_frame too. */
- XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
- RevertToPointerRoot, CurrentTime);
-#endif /* ! 0 */
-}
-
-static void
-x_unfocus_frame (f)
- struct frame *f;
-{
-#if 0
- /* Look at the remarks in x_focus_on_frame. */
- if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
- XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
- RevertToPointerRoot, CurrentTime);
-#endif /* ! 0 */
-}
-
-/* Raise frame F. */
-
-void
-x_raise_frame (f)
- struct frame *f;
-{
- if (f->async_visible)
- SelectWindow (FRAME_MAC_WINDOW (f));
-}
-
-/* Lower frame F. */
-
-void
-x_lower_frame (f)
- struct frame *f;
-{
- if (f->async_visible)
- SendBehind (FRAME_MAC_WINDOW (f), nil);
-}
-
-void
-XTframe_raise_lower (f, raise_flag)
- FRAME_PTR f;
- int raise_flag;
-{
- if (raise_flag)
- x_raise_frame (f);
- else
- x_lower_frame (f);
-}
-\f
-/* Change of visibility. */
-
-/* This tries to wait until the frame is really visible.
- However, if the window manager asks the user where to position
- the frame, this will return before the user finishes doing that.
- The frame will not actually be visible at that time,
- but it will become visible later when the window manager
- finishes with it. */
-
-void
-x_make_frame_visible (f)
- struct frame *f;
-{
- Lisp_Object type;
- int original_top, original_left;
-
- BLOCK_INPUT;
-
- if (! FRAME_VISIBLE_P (f))
- {
- /* We test FRAME_GARBAGED_P here to make sure we don't
- call x_set_offset a second time
- if we get to x_make_frame_visible a second time
- before the window gets really visible. */
- if (! FRAME_ICONIFIED_P (f)
- && ! f->output_data.mac->asked_for_visible)
- x_set_offset (f, f->output_data.mac->left_pos,
- f->output_data.mac->top_pos, 0);
-
- f->output_data.mac->asked_for_visible = 1;
-
- ShowWindow (FRAME_MAC_WINDOW (f));
- }
-
- XFlush (FRAME_MAC_DISPLAY (f));
-
- /* Synchronize to ensure Emacs knows the frame is visible
- before we do anything else. We do this loop with input not blocked
- so that incoming events are handled. */
- {
- Lisp_Object frame;
- int count;
-
- /* This must come after we set COUNT. */
- UNBLOCK_INPUT;
-
- XSETFRAME (frame, f);
-
- /* Wait until the frame is visible. Process X events until a
- MapNotify event has been seen, or until we think we won't get a
- MapNotify at all.. */
- for (count = input_signal_count + 10;
- input_signal_count < count && !FRAME_VISIBLE_P (f);)
- {
- /* Force processing of queued events. */
- x_sync (f);
-
- /* Machines that do polling rather than SIGIO have been
- observed to go into a busy-wait here. So we'll fake an
- alarm signal to let the handler know that there's something
- to be read. We used to raise a real alarm, but it seems
- that the handler isn't always enabled here. This is
- probably a bug. */
- if (input_polling_used ())
- {
- /* It could be confusing if a real alarm arrives while
- processing the fake one. Turn it off and let the
- handler reset it. */
- extern void poll_for_input_1 P_ ((void));
- int old_poll_suppress_count = poll_suppress_count;
- poll_suppress_count = 1;
- poll_for_input_1 ();
- poll_suppress_count = old_poll_suppress_count;
- }
-
- /* See if a MapNotify event has been processed. */
- FRAME_SAMPLE_VISIBILITY (f);
- }
- }
-}
-
-/* Change from mapped state to withdrawn state. */
-
-/* Make the frame visible (mapped and not iconified). */
-
-void
-x_make_frame_invisible (f)
- struct frame *f;
-{
- /* Don't keep the highlight on an invisible frame. */
- if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
- FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
-
- BLOCK_INPUT;
-
- HideWindow (FRAME_MAC_WINDOW (f));
-
- /* We can't distinguish this from iconification
- just by the event that we get from the server.
- So we can't win using the usual strategy of letting
- FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
- and synchronize with the server to make sure we agree. */
- f->visible = 0;
- FRAME_ICONIFIED_P (f) = 0;
- f->async_visible = 0;
- f->async_iconified = 0;
-
- UNBLOCK_INPUT;
-}
-
-/* Change window state from mapped to iconified. */
-
-void
-x_iconify_frame (f)
- struct frame *f;
-{
-#if 0 /* MAC_TODO: really no iconify on Mac */
- int result;
- Lisp_Object type;
-
- /* Don't keep the highlight on an invisible frame. */
- if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
- FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
-
- if (f->async_iconified)
- return;
-
- BLOCK_INPUT;
-
- FRAME_SAMPLE_VISIBILITY (f);
-
- type = x_icon_type (f);
- if (!NILP (type))
- x_bitmap_icon (f, type);
-
-#ifdef USE_X_TOOLKIT
-
- if (! FRAME_VISIBLE_P (f))
- {
- if (! EQ (Vx_no_window_manager, Qt))
- x_wm_set_window_state (f, IconicState);
- /* This was XtPopup, but that did nothing for an iconified frame. */
- XtMapWidget (f->output_data.x->widget);
- /* The server won't give us any event to indicate
- that an invisible frame was changed to an icon,
- so we have to record it here. */
- f->iconified = 1;
- f->visible = 1;
- f->async_iconified = 1;
- f->async_visible = 0;
- UNBLOCK_INPUT;
- return;
- }
-
- result = XIconifyWindow (FRAME_X_DISPLAY (f),
- XtWindow (f->output_data.x->widget),
- DefaultScreen (FRAME_X_DISPLAY (f)));
- UNBLOCK_INPUT;
-
- if (!result)
- error ("Can't notify window manager of iconification");
-
- f->async_iconified = 1;
- f->async_visible = 0;
-
-
- BLOCK_INPUT;
- XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
-#else /* not USE_X_TOOLKIT */
-
- /* Make sure the X server knows where the window should be positioned,
- in case the user deiconifies with the window manager. */
- if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
- x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
-
- /* Since we don't know which revision of X we're running, we'll use both
- the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
-
- /* X11R4: send a ClientMessage to the window manager using the
- WM_CHANGE_STATE type. */
- {
- XEvent message;
-
- message.xclient.window = FRAME_X_WINDOW (f);
- message.xclient.type = ClientMessage;
- message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
- message.xclient.format = 32;
- message.xclient.data.l[0] = IconicState;
-
- if (! XSendEvent (FRAME_X_DISPLAY (f),
- DefaultRootWindow (FRAME_X_DISPLAY (f)),
- False,
- SubstructureRedirectMask | SubstructureNotifyMask,
- &message))
- {
- UNBLOCK_INPUT_RESIGNAL;
- error ("Can't notify window manager of iconification");
- }
- }
-
- /* X11R3: set the initial_state field of the window manager hints to
- IconicState. */
- x_wm_set_window_state (f, IconicState);
-
- if (!FRAME_VISIBLE_P (f))
- {
- /* If the frame was withdrawn, before, we must map it. */
- XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
- }
-
- f->async_iconified = 1;
- f->async_visible = 0;
-
- XFlush (FRAME_X_DISPLAY (f));
- UNBLOCK_INPUT;
-#endif /* not USE_X_TOOLKIT */
-#endif
-}
-\f
-/* Destroy the X window of frame F. */
-
-void
-x_destroy_window (f)
- struct frame *f;
-{
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
-
- BLOCK_INPUT;
-
- DisposeWindow (FRAME_MAC_WINDOW (f));
-
- free_frame_menubar (f);
- free_frame_faces (f);
-
- xfree (f->output_data.mac);
- f->output_data.mac = 0;
- if (f == dpyinfo->x_focus_frame)
- dpyinfo->x_focus_frame = 0;
- if (f == dpyinfo->x_focus_event_frame)
- dpyinfo->x_focus_event_frame = 0;
- if (f == dpyinfo->x_highlight_frame)
- dpyinfo->x_highlight_frame = 0;
-
- dpyinfo->reference_count--;
-
- if (f == dpyinfo->mouse_face_mouse_frame)
- {
- dpyinfo->mouse_face_beg_row
- = dpyinfo->mouse_face_beg_col = -1;
- dpyinfo->mouse_face_end_row
- = dpyinfo->mouse_face_end_col = -1;
- dpyinfo->mouse_face_window = Qnil;
- dpyinfo->mouse_face_deferred_gc = 0;
- dpyinfo->mouse_face_mouse_frame = 0;
- }
-
- UNBLOCK_INPUT;
-}
-\f
-/* Setting window manager hints. */
-
-/* Set the normal size hints for the window manager, for frame F.
- FLAGS is the flags word to use--or 0 meaning preserve the flags
- that the window now has.
- If USER_POSITION is nonzero, we set the USPosition
- flag (this is useful when FLAGS is 0). */
-
-void
-x_wm_set_size_hint (f, flags, user_position)
- struct frame *f;
- long flags;
- int user_position;
-{
-#if 0 /* MAC_TODO: connect this to the Appearance Manager */
- XSizeHints size_hints;
-
-#ifdef USE_X_TOOLKIT
- Arg al[2];
- int ac = 0;
- Dimension widget_width, widget_height;
- Window window = XtWindow (f->output_data.x->widget);
-#else /* not USE_X_TOOLKIT */
- Window window = FRAME_X_WINDOW (f);
-#endif /* not USE_X_TOOLKIT */
-
- /* Setting PMaxSize caused various problems. */
- size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
-
- size_hints.x = f->output_data.x->left_pos;
- size_hints.y = f->output_data.x->top_pos;
-
-#ifdef USE_X_TOOLKIT
- XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
- XtSetArg (al[ac], XtNheight, &widget_height); ac++;
- XtGetValues (f->output_data.x->widget, al, ac);
- size_hints.height = widget_height;
- size_hints.width = widget_width;
-#else /* not USE_X_TOOLKIT */
- size_hints.height = PIXEL_HEIGHT (f);
- size_hints.width = PIXEL_WIDTH (f);
-#endif /* not USE_X_TOOLKIT */
-
- size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
- size_hints.height_inc = f->output_data.x->line_height;
- size_hints.max_width
- = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
- size_hints.max_height
- = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
-
- /* Calculate the base and minimum sizes.
-
- (When we use the X toolkit, we don't do it here.
- Instead we copy the values that the widgets are using, below.) */
-#ifndef USE_X_TOOLKIT
- {
- int base_width, base_height;
- int min_rows = 0, min_cols = 0;
-
- base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
- base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
-
- check_frame_size (f, &min_rows, &min_cols);
-
- /* The window manager uses the base width hints to calculate the
- current number of rows and columns in the frame while
- resizing; min_width and min_height aren't useful for this
- purpose, since they might not give the dimensions for a
- zero-row, zero-column frame.
-
- We use the base_width and base_height members if we have
- them; otherwise, we set the min_width and min_height members
- to the size for a zero x zero frame. */
-
-#ifdef HAVE_X11R4
- size_hints.flags |= PBaseSize;
- size_hints.base_width = base_width;
- size_hints.base_height = base_height;
- size_hints.min_width = base_width + min_cols * size_hints.width_inc;
- size_hints.min_height = base_height + min_rows * size_hints.height_inc;
-#else
- size_hints.min_width = base_width;
- size_hints.min_height = base_height;
-#endif
- }
-
- /* If we don't need the old flags, we don't need the old hint at all. */
- if (flags)
- {
- size_hints.flags |= flags;
- goto no_read;
- }
-#endif /* not USE_X_TOOLKIT */
-
- {
- XSizeHints hints; /* Sometimes I hate X Windows... */
- long supplied_return;
- int value;
-
-#ifdef HAVE_X11R4
- value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
- &supplied_return);
-#else
- value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
-#endif
-
-#ifdef USE_X_TOOLKIT
- size_hints.base_height = hints.base_height;
- size_hints.base_width = hints.base_width;
- size_hints.min_height = hints.min_height;
- size_hints.min_width = hints.min_width;
-#endif
-
- if (flags)
- size_hints.flags |= flags;
- else
- {
- if (value == 0)
- hints.flags = 0;
- if (hints.flags & PSize)
- size_hints.flags |= PSize;
- if (hints.flags & PPosition)
- size_hints.flags |= PPosition;
- if (hints.flags & USPosition)
- size_hints.flags |= USPosition;
- if (hints.flags & USSize)
- size_hints.flags |= USSize;
- }
- }
-
-#ifndef USE_X_TOOLKIT
- no_read:
-#endif
-
-#ifdef PWinGravity
- size_hints.win_gravity = f->output_data.x->win_gravity;
- size_hints.flags |= PWinGravity;
-
- if (user_position)
- {
- size_hints.flags &= ~ PPosition;
- size_hints.flags |= USPosition;
- }
-#endif /* PWinGravity */
-
-#ifdef HAVE_X11R4
- XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
-#else
- XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
-#endif
-#endif /* MACTODO */
-}
-
-#if 0 /* MACTODO: hide application instead of iconify? */
-/* Used for IconicState or NormalState */
-
-void
-x_wm_set_window_state (f, state)
- struct frame *f;
- int state;
-{
-#ifdef USE_X_TOOLKIT
- Arg al[1];
-
- XtSetArg (al[0], XtNinitialState, state);
- XtSetValues (f->output_data.x->widget, al, 1);
-#else /* not USE_X_TOOLKIT */
- Window window = FRAME_X_WINDOW (f);
-
- f->output_data.x->wm_hints.flags |= StateHint;
- f->output_data.x->wm_hints.initial_state = state;
-
- XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
-#endif /* not USE_X_TOOLKIT */
-}
-
-void
-x_wm_set_icon_pixmap (f, pixmap_id)
- struct frame *f;
- int pixmap_id;
-{
- Pixmap icon_pixmap;
-
-#ifndef USE_X_TOOLKIT
- Window window = FRAME_X_WINDOW (f);
-#endif
-
- if (pixmap_id > 0)
- {
- icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
- f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
- }
- else
- {
- /* It seems there is no way to turn off use of an icon pixmap.
- The following line does it, only if no icon has yet been created,
- for some window managers. But with mwm it crashes.
- Some people say it should clear the IconPixmapHint bit in this case,
- but that doesn't work, and the X consortium said it isn't the
- right thing at all. Since there is no way to win,
- best to explicitly give up. */
-#if 0
- f->output_data.x->wm_hints.icon_pixmap = None;
-#else
- return;
-#endif
- }
-
-#ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
-
- {
- Arg al[1];
- XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
- XtSetValues (f->output_data.x->widget, al, 1);
- }
-
-#else /* not USE_X_TOOLKIT */
-
- f->output_data.x->wm_hints.flags |= IconPixmapHint;
- XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
-
-#endif /* not USE_X_TOOLKIT */
-}
-
-#endif
-
-void
-x_wm_set_icon_position (f, icon_x, icon_y)
- struct frame *f;
- int icon_x, icon_y;
-{
-#if 0 /* MAC_TODO: no icons on Mac */
-#ifdef USE_X_TOOLKIT
- Window window = XtWindow (f->output_data.x->widget);
-#else
- Window window = FRAME_X_WINDOW (f);
-#endif
-
- f->output_data.x->wm_hints.flags |= IconPositionHint;
- f->output_data.x->wm_hints.icon_x = icon_x;
- f->output_data.x->wm_hints.icon_y = icon_y;
-
- XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
-#endif
-}
-
-\f
-/***********************************************************************
- Fonts
- ***********************************************************************/
-
-/* Return a pointer to struct font_info of font FONT_IDX of frame F. */
-
-struct font_info *
-x_get_font_info (f, font_idx)
- FRAME_PTR f;
- int font_idx;
-{
- return (FRAME_MAC_FONT_TABLE (f) + font_idx);
-}
-
-/* the global font name table */
-char **font_name_table = NULL;
-int font_name_table_size = 0;
-int font_name_count = 0;
-
-/* compare two strings ignoring case */
-static int
-stricmp (const char *s, const char *t)
-{
- for ( ; tolower (*s) == tolower (*t); s++, t++)
- if (*s == '\0')
- return 0;
- return tolower (*s) - tolower (*t);
-}
-
-/* compare two strings ignoring case and handling wildcard */
-static int
-wildstrieq (char *s1, char *s2)
-{
- if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
- return true;
-
- return stricmp (s1, s2) == 0;
-}
-
-/* Assume parameter 1 is fully qualified, no wildcards. */
-static int
-mac_font_pattern_match (fontname, pattern)
- char * fontname;
- char * pattern;
-{
- char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
- char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
- char *ptr;
-
- /* Copy fontname so we can modify it during comparison. */
- strcpy (font_name_copy, fontname);
-
- ptr = regex;
- *ptr++ = '^';
-
- /* Turn pattern into a regexp and do a regexp match. */
- for (; *pattern; pattern++)
- {
- if (*pattern == '?')
- *ptr++ = '.';
- else if (*pattern == '*')
- {
- *ptr++ = '.';
- *ptr++ = '*';
- }
- else
- *ptr++ = *pattern;
- }
- *ptr = '$';
- *(ptr + 1) = '\0';
-
- return (fast_c_string_match_ignore_case (build_string (regex),
- font_name_copy) >= 0);
-}
-
-/* Two font specs are considered to match if their foundry, family,
- weight, slant, and charset match. */
-static int
-mac_font_match (char *mf, char *xf)
-{
- char m_foundry[50], m_family[50], m_weight[20], m_slant[2], m_charset[20];
- char x_foundry[50], x_family[50], x_weight[20], x_slant[2], x_charset[20];
-
- if (sscanf (mf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
- m_foundry, m_family, m_weight, m_slant, m_charset) != 5)
- return mac_font_pattern_match (mf, xf);
-
- if (sscanf (xf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
- x_foundry, x_family, x_weight, x_slant, x_charset) != 5)
- return mac_font_pattern_match (mf, xf);
-
- return (wildstrieq (m_foundry, x_foundry)
- && wildstrieq (m_family, x_family)
- && wildstrieq (m_weight, x_weight)
- && wildstrieq (m_slant, x_slant)
- && wildstrieq (m_charset, x_charset))
- || mac_font_pattern_match (mf, xf);
-}
-
-
-static char *
-mac_to_x_fontname (char *name, int size, Style style, short scriptcode)
-{
- char foundry[32], family[32], cs[32];
- char xf[255], *result, *p;
-
- if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
- {
- strcpy(foundry, "Apple");
- strcpy(family, name);
-
- switch (scriptcode)
- {
- case smTradChinese:
- strcpy(cs, "big5-0");
- break;
- case smSimpChinese:
- strcpy(cs, "gb2312.1980-0");
- break;
- case smJapanese:
- strcpy(cs, "jisx0208.1983-sjis");
- break;
- case -smJapanese:
- /* Each Apple Japanese font is entered into the font table
- twice: once as a jisx0208.1983-sjis font and once as a
- jisx0201.1976-0 font. The latter can be used to display
- the ascii charset and katakana-jisx0201 charset. A
- negative script code signals that the name of this latter
- font is being built. */
- strcpy(cs, "jisx0201.1976-0");
- break;
- case smKorean:
- strcpy(cs, "ksc5601.1989-0");
- break;
- default:
- strcpy(cs, "mac-roman");
- break;
- }
- }
-
- sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
- foundry, family, style & bold ? "bold" : "medium",
- style & italic ? 'i' : 'r', size, size * 10, size * 10, cs);
-
- result = (char *) xmalloc (strlen (xf) + 1);
- strcpy (result, xf);
- for (p = result; *p; p++)
- *p = tolower(*p);
- return result;
-}
-
-
-/* Convert an X font spec to the corresponding mac font name, which
- can then be passed to GetFNum after conversion to a Pascal string.
- For ordinary Mac fonts, this should just be their names, like
- "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
- collection contain their charset designation in their names, like
- "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
- names are handled accordingly. */
-static void
-x_font_name_to_mac_font_name (char *xf, char *mf)
-{
- char foundry[32], family[32], weight[20], slant[2], cs[32];
-
- strcpy (mf, "");
-
- if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
- foundry, family, weight, slant, cs) != 5 &&
- sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
- foundry, family, weight, slant, cs) != 5)
- return;
-
- if (strcmp (cs, "big5-0") == 0 || strcmp (cs, "gb2312.1980-0") == 0
- || strcmp (cs, "jisx0208.1983-sjis") == 0
- || strcmp (cs, "jisx0201.1976-0") == 0
- || strcmp (cs, "ksc5601.1989-0") == 0 || strcmp (cs, "mac-roman") == 0)
- strcpy(mf, family);
- else
- sprintf(mf, "%s-%s-%s", foundry, family, cs);
-}
-
-
-/* Sets up the table font_name_table to contain the list of all
- monospace fonts in the system the first time the table is used so
- that the Resource Manager need not be accessed every time this
- information is needed. */
-
-static void
-init_font_name_table ()
-{
- GrafPtr port;
- SInt16 fontnum, old_fontnum;
- int num_mac_fonts = CountResources('FOND');
- int i, j;
- Handle font_handle, font_handle_2;
- short id, scriptcode;
- ResType type;
- Str32 name;
- struct FontAssoc *fat;
- struct AsscEntry *assc_entry;
-
- GetPort (&port); /* save the current font number used */
- old_fontnum = port->txFont;
-
- for (i = 1; i <= num_mac_fonts; i++) /* loop to get all available fonts */
- {
- font_handle = GetIndResource ('FOND', i);
- if (!font_handle)
- continue;
-
- GetResInfo (font_handle, &id, &type, name);
- GetFNum (name, &fontnum);
- p2cstr (name);
- if (fontnum == 0)
- continue;
-
- TextFont (fontnum);
- scriptcode = FontToScript (fontnum);
- do
- {
- HLock (font_handle);
-
- if (GetResourceSizeOnDisk (font_handle) >= sizeof (struct FamRec))
- {
- fat = (struct FontAssoc *) (*font_handle
- + sizeof (struct FamRec));
- assc_entry = (struct AsscEntry *) (*font_handle
- + sizeof (struct FamRec)
- + sizeof (struct FontAssoc));
-
- for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
- {
- if (font_name_table_size == 0)
- {
- font_name_table_size = 16;
- font_name_table = (char **)
- xmalloc (font_name_table_size * sizeof (char *));
- }
- else if (font_name_count >= font_name_table_size ||
- /* fonts in Japanese scripts require two
- entries. */
- scriptcode == smJapanese &&
- font_name_count + 1 >= font_name_table_size)
- {
- font_name_table_size += 16;
- font_name_table = (char **)
- xrealloc (font_name_table,
- font_name_table_size * sizeof (char *));
- }
- font_name_table[font_name_count++]
- = mac_to_x_fontname (name,
- assc_entry->fontSize,
- assc_entry->fontStyle,
- scriptcode);
- /* Both jisx0208.1983-sjis and jisx0201.1976-0 parts
- are contained in Apple Japanese (SJIS) font. */
- if (smJapanese == scriptcode)
- {
- font_name_table[font_name_count++]
- = mac_to_x_fontname (name,
- assc_entry->fontSize,
- assc_entry->fontStyle,
- -smJapanese);
- }
- }
- }
-
- HUnlock (font_handle);
- font_handle_2 = GetNextFOND (font_handle);
- ReleaseResource (font_handle);
- font_handle = font_handle_2;
- }
- while (ResError () == noErr && font_handle);
- }
-
- TextFont (old_fontnum);
-}
-
-
-/* Return a list of at most MAXNAMES font specs matching the one in
- PATTERN. Note that each '*' in the PATTERN matches exactly one
- field of the font spec, unlike X in which an '*' in a font spec can
- match a number of fields. The result is in the Mac implementation
- all fonts must be specified by a font spec with all 13 fields
- (although many of these can be "*'s"). */
-
-Lisp_Object
-x_list_fonts (struct frame *f,
- Lisp_Object pattern,
- int size,
- int maxnames)
-{
- char *ptnstr;
- Lisp_Object newlist = Qnil;
- int n_fonts = 0;
- int i;
- struct gcpro gcpro1, gcpro2;
-
- if (font_name_table == NULL) /* Initialize when first used. */
- init_font_name_table ();
-
- ptnstr = XSTRING (pattern)->data;
-
- GCPRO2 (pattern, newlist);
-
- /* Scan and matching bitmap fonts. */
- for (i = 0; i < font_name_count; i++)
- {
- if (mac_font_pattern_match (font_name_table[i], ptnstr))
- {
- newlist = Fcons (build_string (font_name_table[i]), newlist);
-
- n_fonts++;
- if (n_fonts >= maxnames)
- break;
- }
- }
-
- /* MAC_TODO: add code for matching outline fonts here */
-
- UNGCPRO;
-
- return newlist;
-}
-
-
-#if GLYPH_DEBUG
-
-/* Check that FONT is valid on frame F. It is if it can be found in
- F's font table. */
-
-static void
-x_check_font (f, font)
- struct frame *f;
- XFontStruct *font;
-{
- int i;
- struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
-
- xassert (font != NULL);
-
- for (i = 0; i < dpyinfo->n_fonts; i++)
- if (dpyinfo->font_table[i].name
- && font == dpyinfo->font_table[i].font)
- break;
-
- xassert (i < dpyinfo->n_fonts);
-}
-
-#endif /* GLYPH_DEBUG != 0 */
-
-
-/* Set *W to the minimum width, *H to the minimum font height of FONT.
- Note: There are (broken) X fonts out there with invalid XFontStruct
- min_bounds contents. For example, handa@etl.go.jp reports that
- "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
- have font->min_bounds.width == 0. */
-
-static INLINE void
-x_font_min_bounds (font, w, h)
- MacFontStruct *font;
- int *w, *h;
-{
- *h = FONT_HEIGHT (font);
- *w = font->min_bounds.width;
-
- /* Try to handle the case where FONT->min_bounds has invalid
- contents. Since the only font known to have invalid min_bounds
- is fixed-width, use max_bounds if min_bounds seems to be invalid. */
- if (*w <= 0)
- *w = font->max_bounds.width;
-}
-
-
-/* Compute the smallest character width and smallest font height over
- all fonts available on frame F. Set the members smallest_char_width
- and smallest_font_height in F's x_display_info structure to
- the values computed. Value is non-zero if smallest_font_height or
- smallest_char_width become smaller than they were before. */
-
-static int
-x_compute_min_glyph_bounds (f)
- struct frame *f;
-{
- int i;
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
- MacFontStruct *font;
- int old_width = dpyinfo->smallest_char_width;
- int old_height = dpyinfo->smallest_font_height;
-
- dpyinfo->smallest_font_height = 100000;
- dpyinfo->smallest_char_width = 100000;
-
- for (i = 0; i < dpyinfo->n_fonts; ++i)
- if (dpyinfo->font_table[i].name)
- {
- struct font_info *fontp = dpyinfo->font_table + i;
- int w, h;
-
- font = (MacFontStruct *) fontp->font;
- xassert (font != (MacFontStruct *) ~0);
- x_font_min_bounds (font, &w, &h);
-
- dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
- dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
- }
-
- xassert (dpyinfo->smallest_char_width > 0
- && dpyinfo->smallest_font_height > 0);
-
- return (dpyinfo->n_fonts == 1
- || dpyinfo->smallest_char_width < old_width
- || dpyinfo->smallest_font_height < old_height);
-}
-
-
-/* Determine whether given string is a fully-specified XLFD: all 14
- fields are present, none is '*'. */
-
-static int
-is_fully_specified_xlfd (char *p)
-{
- int i;
- char *q;
-
- if (*p != '-')
- return 0;
-
- for (i = 0; i < 13; i++)
- {
- q = strchr (p + 1, '-');
- if (q == NULL)
- return 0;
- if (q - p == 2 && *(p + 1) == '*')
- return 0;
- p = q;
- }
-
- if (strchr (p + 1, '-') != NULL)
- return 0;
-
- if (*(p + 1) == '*' && *(p + 2) == '\0')
- return 0;
-
- return 1;
-}
-
-
-const int kDefaultFontSize = 9;
-
-
-/* MacLoadQueryFont creates and returns an internal representation for
- a font in a MacFontStruct struct (similar in function to
- XLoadQueryFont in X). There is really no concept corresponding to
- "loading" a font on the Mac. But we check its existence and find
- the font number and all other information for it and store them in
- the returned MacFontStruct. */
-
-static MacFontStruct *
-XLoadQueryFont (Display *dpy, char *fontname)
-{
- int i, size, is_two_byte_font, char_width;
- char *name;
- GrafPtr port;
- SInt16 old_fontnum, old_fontsize;
- Style old_fontface;
- Str32 mfontname;
- SInt16 fontnum;
- Style fontface = normal;
- MacFontStruct *font;
- FontInfo the_fontinfo;
- char s_weight[7], c_slant;
-
- if (is_fully_specified_xlfd (fontname))
- name = fontname;
- else
- {
- for (i = 0; i < font_name_count; i++)
- if (mac_font_pattern_match (font_name_table[i], fontname))
- break;
-
- if (i >= font_name_count)
- return NULL;
-
- name = font_name_table[i];
- }
-
- GetPort (&port); /* save the current font number used */
- old_fontnum = port->txFont;
- old_fontsize = port->txSize;
- old_fontface = port->txFace;
-
- if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
- size = kDefaultFontSize;
-
- if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
- if (strcmp (s_weight, "bold") == 0)
- fontface |= bold;
-
- if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
- if (c_slant == 'i')
- fontface |= italic;
-
- x_font_name_to_mac_font_name (name, mfontname);
- c2pstr (mfontname);
- GetFNum (mfontname, &fontnum);
- if (fontnum == 0)
- return NULL;
-
- font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
-
- font->fontname = (char *) xmalloc (strlen (name) + 1);
- bcopy (name, font->fontname, strlen (name) + 1);
-
- font->mac_fontnum = fontnum;
- font->mac_fontsize = size;
- font->mac_fontface = fontface;
- font->mac_scriptcode = FontToScript (fontnum);
-
- /* Apple Japanese (SJIS) font is listed as both
- "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
- (Roman script) in init_font_name_table(). The latter should be
- treated as a one-byte font. */
- {
- char cs[32];
-
- if (sscanf (name,
- "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
- cs) == 1
- && 0 == strcmp (cs, "jisx0201.1976-0"))
- font->mac_scriptcode = smRoman;
- }
-
- is_two_byte_font = font->mac_scriptcode == smJapanese ||
- font->mac_scriptcode == smTradChinese ||
- font->mac_scriptcode == smSimpChinese ||
- font->mac_scriptcode == smKorean;
-
- TextFont (fontnum);
- TextSize (size);
- TextFace (fontface);
-
- GetFontInfo (&the_fontinfo);
-
- font->ascent = the_fontinfo.ascent;
- font->descent = the_fontinfo.descent;
-
- font->min_byte1 = 0;
- if (is_two_byte_font)
- font->max_byte1 = 1;
- else
- font->max_byte1 = 0;
- font->min_char_or_byte2 = 0x20;
- font->max_char_or_byte2 = 0xff;
-
- if (is_two_byte_font)
- {
- /* Use the width of an "ideographic space" of that font because
- the_fontinfo.widMax returns the wrong width for some fonts. */
- switch (font->mac_scriptcode)
- {
- case smJapanese:
- char_width = StringWidth("\p\x81\x40");
- break;
- case smTradChinese:
- char_width = StringWidth("\p\xa1\x40");
- break;
- case smSimpChinese:
- char_width = StringWidth("\p\xa1\xa1");
- break;
- case smKorean:
- char_width = StringWidth("\p\xa1\xa1");
- break;
- }
- }
- else
- /* Do this instead of use the_fontinfo.widMax, which incorrectly
- returns 15 for 12-point Monaco! */
- char_width = CharWidth ('m');
-
- font->max_bounds.rbearing = char_width;
- font->max_bounds.lbearing = 0;
- font->max_bounds.width = char_width;
- font->max_bounds.ascent = the_fontinfo.ascent;
- font->max_bounds.descent = the_fontinfo.descent;
-
- font->min_bounds = font->max_bounds;
-
- if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
- font->per_char = NULL;
- else
- {
- font->per_char = (XCharStruct *)
- xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
- {
- int c;
-
- for (c = 0x20; c <= 0xff; c++)
- {
- font->per_char[c - 0x20] = font->max_bounds;
- font->per_char[c - 0x20].width = CharWidth (c);
- }
- }
- }
-
- TextFont (old_fontnum); /* restore previous font number, size and face */
- TextSize (old_fontsize);
- TextFace (old_fontface);
-
- return font;
-}
-
-
-/* Load font named FONTNAME of the size SIZE for frame F, and return a
- pointer to the structure font_info while allocating it dynamically.
- If SIZE is 0, load any size of font.
- If loading is failed, return NULL. */
-
-struct font_info *
-x_load_font (f, fontname, size)
- struct frame *f;
- register char *fontname;
- int size;
-{
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
- Lisp_Object font_names;
-
- /* Get a list of all the fonts that match this name. Once we
- have a list of matching fonts, we compare them against the fonts
- we already have by comparing names. */
- font_names = x_list_fonts (f, build_string (fontname), size, 1);
-
- if (!NILP (font_names))
- {
- Lisp_Object tail;
- int i;
-
- for (i = 0; i < dpyinfo->n_fonts; i++)
- for (tail = font_names; CONSP (tail); tail = XCDR (tail))
- if (dpyinfo->font_table[i].name
- && (!strcmp (dpyinfo->font_table[i].name,
- XSTRING (XCAR (tail))->data)
- || !strcmp (dpyinfo->font_table[i].full_name,
- XSTRING (XCAR (tail))->data)))
- return (dpyinfo->font_table + i);
- }
-
- /* Load the font and add it to the table. */
- {
- char *full_name;
- struct MacFontStruct *font;
- struct font_info *fontp;
- unsigned long value;
- int i;
-
- /* If we have found fonts by x_list_font, load one of them. If
- not, we still try to load a font by the name given as FONTNAME
- because XListFonts (called in x_list_font) of some X server has
- a bug of not finding a font even if the font surely exists and
- is loadable by XLoadQueryFont. */
- if (size > 0 && !NILP (font_names))
- fontname = (char *) XSTRING (XCAR (font_names))->data;
-
- font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
- if (!font)
- return NULL;
-
- /* Find a free slot in the font table. */
- for (i = 0; i < dpyinfo->n_fonts; ++i)
- if (dpyinfo->font_table[i].name == NULL)
- break;
-
- /* If no free slot found, maybe enlarge the font table. */
- if (i == dpyinfo->n_fonts
- && dpyinfo->n_fonts == dpyinfo->font_table_size)
- {
- int sz;
- dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
- sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
- dpyinfo->font_table
- = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
- }
-
- fontp = dpyinfo->font_table + i;
- if (i == dpyinfo->n_fonts)
- ++dpyinfo->n_fonts;
-
- /* Now fill in the slots of *FONTP. */
- BLOCK_INPUT;
- fontp->font = font;
- fontp->font_idx = i;
- fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
- bcopy (font->fontname, fontp->name, strlen (font->fontname) + 1);
-
- fontp->full_name = fontp->name;
-
- fontp->size = font->max_bounds.width;
- fontp->height = FONT_HEIGHT (font);
- {
- /* For some font, ascent and descent in max_bounds field is
- larger than the above value. */
- int max_height = font->max_bounds.ascent + font->max_bounds.descent;
- if (max_height > fontp->height)
- fontp->height = max_height;
- }
-
- /* The slot `encoding' specifies how to map a character
- code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
- the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
- (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
- 2:0xA020..0xFF7F). For the moment, we don't know which charset
- uses this font. So, we set information in fontp->encoding[1]
- which is never used by any charset. If mapping can't be
- decided, set FONT_ENCODING_NOT_DECIDED. */
- if (font->mac_scriptcode == smJapanese)
- fontp->encoding[1] = 4;
- else
- {
- fontp->encoding[1]
- = (font->max_byte1 == 0
- /* 1-byte font */
- ? (font->min_char_or_byte2 < 0x80
- ? (font->max_char_or_byte2 < 0x80
- ? 0 /* 0x20..0x7F */
- : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
- : 1) /* 0xA0..0xFF */
- /* 2-byte font */
- : (font->min_byte1 < 0x80
- ? (font->max_byte1 < 0x80
- ? (font->min_char_or_byte2 < 0x80
- ? (font->max_char_or_byte2 < 0x80
- ? 0 /* 0x2020..0x7F7F */
- : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
- : 3) /* 0x20A0..0x7FFF */
- : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
- : (font->min_char_or_byte2 < 0x80
- ? (font->max_char_or_byte2 < 0x80
- ? 2 /* 0xA020..0xFF7F */
- : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
- : 1))); /* 0xA0A0..0xFFFF */
- }
-
-#if 0 /* MAC_TODO: fill these out with more reasonably values */
- fontp->baseline_offset
- = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
- ? (long) value : 0);
- fontp->relative_compose
- = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
- ? (long) value : 0);
- fontp->default_ascent
- = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
- ? (long) value : 0);
-#else
- fontp->baseline_offset = 0;
- fontp->relative_compose = 0;
- fontp->default_ascent = 0;
-#endif
-
- /* Set global flag fonts_changed_p to non-zero if the font loaded
- has a character with a smaller width than any other character
- before, or if the font loaded has a smalle>r height than any
- other font loaded before. If this happens, it will make a
- glyph matrix reallocation necessary. */
- fonts_changed_p = x_compute_min_glyph_bounds (f);
- UNBLOCK_INPUT;
- return fontp;
- }
-}
-
-
-/* Return a pointer to struct font_info of a font named FONTNAME for
- frame F. If no such font is loaded, return NULL. */
-
-struct font_info *
-x_query_font (f, fontname)
- struct frame *f;
- register char *fontname;
-{
- struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
- int i;
-
- for (i = 0; i < dpyinfo->n_fonts; i++)
- if (dpyinfo->font_table[i].name
- && (!strcmp (dpyinfo->font_table[i].name, fontname)
- || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
- return (dpyinfo->font_table + i);
- return NULL;
-}
-
-
-/* Find a CCL program for a font specified by FONTP, and set the member
- `encoder' of the structure. */
-
-void
-x_find_ccl_program (fontp)
- struct font_info *fontp;
-{
- Lisp_Object list, elt;
-
- for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
- {
- elt = XCAR (list);
- if (CONSP (elt)
- && STRINGP (XCAR (elt))
- && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
- >= 0))
- break;
- }
- if (! NILP (list))
- {
- struct ccl_program *ccl
- = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
-
- if (setup_ccl_program (ccl, XCDR (elt)) < 0)
- xfree (ccl);
- else
- fontp->font_encoder = ccl;
- }
-}
-
-
-\f
-/***********************************************************************
- Initialization
- ***********************************************************************/
-
-#ifdef USE_X_TOOLKIT
-static XrmOptionDescRec emacs_options[] = {
- {"-geometry", ".geometry", XrmoptionSepArg, NULL},
- {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
-
- {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
- XrmoptionSepArg, NULL},
- {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
-
- {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
- {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
- {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
- {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
- {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
- {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
- {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
-};
-#endif /* USE_X_TOOLKIT */
-
-static int x_initialized;
-
-#ifdef MULTI_KBOARD
-/* Test whether two display-name strings agree up to the dot that separates
- the screen number from the server number. */
-static int
-same_x_server (name1, name2)
- char *name1, *name2;
-{
- int seen_colon = 0;
- unsigned char *system_name = XSTRING (Vsystem_name)->data;
- int system_name_length = strlen (system_name);
- int length_until_period = 0;
-
- while (system_name[length_until_period] != 0
- && system_name[length_until_period] != '.')
- length_until_period++;
-
- /* Treat `unix' like an empty host name. */
- if (! strncmp (name1, "unix:", 5))
- name1 += 4;
- if (! strncmp (name2, "unix:", 5))
- name2 += 4;
- /* Treat this host's name like an empty host name. */
- if (! strncmp (name1, system_name, system_name_length)
- && name1[system_name_length] == ':')
- name1 += system_name_length;
- if (! strncmp (name2, system_name, system_name_length)
- && name2[system_name_length] == ':')
- name2 += system_name_length;
- /* Treat this host's domainless name like an empty host name. */
- if (! strncmp (name1, system_name, length_until_period)
- && name1[length_until_period] == ':')
- name1 += length_until_period;
- if (! strncmp (name2, system_name, length_until_period)
- && name2[length_until_period] == ':')
- name2 += length_until_period;
-
- for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
- {
- if (*name1 == ':')
- seen_colon++;
- if (seen_colon && *name1 == '.')
- return 1;
- }
- return (seen_colon
- && (*name1 == '.' || *name1 == '\0')
- && (*name2 == '.' || *name2 == '\0'));
-}
-#endif
-
-struct mac_display_info *
-x_term_init (display_name, xrm_option, resource_name)
- Lisp_Object display_name;
- char *xrm_option;
- char *resource_name;
-{
- if (!x_initialized)
- {
- x_initialize ();
- x_initialized = 1;
- }
-
- return &one_mac_display_info;
-}
-\f
-/* Set up use of X before we make the first connection. */
-
-static struct redisplay_interface x_redisplay_interface =
-{
- x_produce_glyphs,
- x_write_glyphs,
- x_insert_glyphs,
- x_clear_end_of_line,
- x_scroll_run,
- x_after_update_window_line,
- x_update_window_begin,
- x_update_window_end,
- XTcursor_to,
- x_flush,
- x_clear_mouse_face,
- x_get_glyph_overhangs,
- x_fix_overlapping_area
-};
-
-
-/* The Mac Event loop code */
-
-#include <Events.h>
-#include <Quickdraw.h>
-#include <Balloons.h>
-#include <Devices.h>
-#include <Fonts.h>
-#include <Gestalt.h>
-#include <Menus.h>
-#include <Processes.h>
-#include <Sound.h>
-#include <ToolUtils.h>
-#include <TextUtils.h>
-#include <Dialogs.h>
-#include <Script.h>
-#include <Scrap.h>
-#include <Types.h>
-#include <TextEncodingConverter.h>
-#include <Resources.h>
-
-#if __MWERKS__
-#include <unix.h>
-#endif
-
-#define M_APPLE 128
-#define I_ABOUT 1
-
-#define WINDOW_RESOURCE 128
-#define TERM_WINDOW_RESOURCE 129
-
-#define DEFAULT_NUM_COLS 80
-
-#define MIN_DOC_SIZE 64
-#define MAX_DOC_SIZE 32767
-
-/* sleep time for WaitNextEvent */
-#define WNE_SLEEP_AT_SUSPEND 10
-#define WNE_SLEEP_AT_RESUME 1
-
-/* true when cannot handle any Mac OS events */
-static int handling_window_update = 0;
-
-/* the flag appl_is_suspended is used both for determining the sleep
- time to be passed to WaitNextEvent and whether the cursor should be
- drawn when updating the display. The cursor is turned off when
- Emacs is suspended. Redrawing it is unnecessary and what needs to
- be done depends on whether the cursor lies inside or outside the
- redraw region. So we might as well skip drawing it when Emacs is
- suspended. */
-static Boolean app_is_suspended = false;
-static long app_sleep_time = WNE_SLEEP_AT_RESUME;
-
-#define EXTRA_STACK_ALLOC (256 * 1024)
-
-#define ARGV_STRING_LIST_ID 129
-#define ABOUT_ALERT_ID 128
-#define RAM_TOO_LARGE_ALERT_ID 129
-
-Boolean terminate_flag = false;
-
-/* true if using command key as meta key */
-Lisp_Object Vmac_command_key_is_meta;
-
-/* convert input from Mac keyboard (assumed to be in Mac Roman coding)
- to this text encoding */
-int mac_keyboard_text_encoding;
-int current_mac_keyboard_text_encoding = kTextEncodingMacRoman;
-
-/* Set in term/mac-win.el to indicate that event loop can now generate
- drag and drop events. */
-Lisp_Object Qmac_ready_for_drag_n_drop;
-
-Lisp_Object drag_and_drop_file_list;
-
-Point saved_menu_event_location;
-
-/* Apple Events */
-static void init_required_apple_events(void);
-static pascal OSErr do_ae_open_application(const AppleEvent *, AppleEvent *, long);
-static pascal OSErr do_ae_print_documents(const AppleEvent *, AppleEvent *, long);
-static pascal OSErr do_ae_open_documents(AppleEvent *, AppleEvent *, long);
-static pascal OSErr do_ae_quit_application(AppleEvent *, AppleEvent *, long);
-
-extern void init_emacs_passwd_dir ();
-extern int emacs_main (int, char **, char **);
-extern void check_alarm ();
-
-extern void initialize_applescript();
-extern void terminate_applescript();
-
-
-static void
-do_get_menus (void)
-{
- Handle menubar_handle;
- MenuHandle menu_handle;
-
- menubar_handle = GetNewMBar (128);
- if(menubar_handle == NULL)
- abort ();
- SetMenuBar (menubar_handle);
- DrawMenuBar ();
-
- menu_handle = GetMenuHandle (M_APPLE);
- if(menu_handle != NULL)
- AppendResMenu (menu_handle,'DRVR');
- else
- abort ();
-}
-
-
-static void
-do_init_managers (void)
-{
- InitGraf (&qd.thePort);
- InitFonts ();
- FlushEvents (everyEvent, 0);
- InitWindows ();
- InitMenus ();
- TEInit ();
- InitDialogs (NULL);
- InitCursor ();
-
- /* set up some extra stack space for use by emacs */
- SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
-
- /* MaxApplZone must be called for AppleScript to execute more
- complicated scripts */
- MaxApplZone ();
- MoreMasters ();
-}
-
-
-static void
-do_check_ram_size (void)
-{
- SInt32 physical_ram_size, logical_ram_size;
-
- if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
- || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
- || physical_ram_size > 256 * 1024 * 1024
- || logical_ram_size > 256 * 1024 * 1024)
- {
- StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
- exit (1);
- }
-}
-
-
-static void
-do_window_update (WindowPtr win)
-{
- struct mac_output *mwp = (mac_output *) GetWRefCon (win);
- struct frame *f = mwp->mFP;
-
- if (f)
- {
- if (f->async_visible == 0)
- {
- f->async_visible = 1;
- f->async_iconified = 0;
- SET_FRAME_GARBAGED (f);
-
- /* An update event is equivalent to MapNotify on X, so report
- visibility changes properly. */
- if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
- /* Force a redisplay sooner or later to update the
- frame titles in case this is the second frame. */
- record_asynch_buffer_change ();
- }
- else
- {
- BeginUpdate (win);
- handling_window_update = 1;
-
- expose_frame (f, 0, 0, 0, 0);
-
- handling_window_update = 0;
- EndUpdate (win);
- }
- }
-}
-
-static void
-do_window_activate (WindowPtr win)
-{
- mac_output *mwp = (mac_output *) GetWRefCon (win);
- struct frame *f = mwp->mFP;
-
- if (f)
- {
- x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
- activate_scroll_bars (f);
- }
-}
-
-static void
-do_window_deactivate (WindowPtr win)
-{
- mac_output *mwp = (mac_output *) GetWRefCon (win);
- struct frame *f = mwp->mFP;
-
- if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
- {
- x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
- deactivate_scroll_bars (f);
- }
-}
-
-static void
-do_app_resume ()
-{
- mac_output *mwp = (mac_output *) GetWRefCon (FrontWindow ());
- struct frame *f = mwp->mFP;
-
- SetCursor (&qd.arrow);
-
- if (f)
- {
- x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
- activate_scroll_bars (f);
- }
-
- app_is_suspended = false;
- app_sleep_time = WNE_SLEEP_AT_RESUME;
-}
-
-static void
-do_app_suspend ()
-{
- mac_output *mwp = (mac_output *) GetWRefCon (FrontWindow ());
- struct frame *f = mwp->mFP;
-
- if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
- {
- x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
- deactivate_scroll_bars (f);
- }
-
- app_is_suspended = true;
- app_sleep_time = WNE_SLEEP_AT_SUSPEND;
-}
-
-
-static void
-do_mouse_moved (Point mouse_pos)
-{
- WindowPtr wp = FrontWindow ();
- struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
-
- SetPort (wp);
- GlobalToLocal (&mouse_pos);
-
- note_mouse_movement (f, &mouse_pos);
-}
-
-
-static void
-do_os_event (EventRecord *erp)
-{
- switch((erp->message >> 24) & 0x000000FF)
- {
- case suspendResumeMessage:
- if((erp->message & resumeFlag) == 1)
- do_app_resume ();
- else
- do_app_suspend ();
- break;
-
- case mouseMovedMessage: /* never reached */
- do_mouse_moved (erp->where);
- break;
- }
-}
-
-static void
-do_events (EventRecord *erp)
-{
- switch (erp->what)
- {
- case updateEvt:
- do_window_update ((WindowPtr) erp->message);
- break;
-
- case osEvt:
- do_os_event (erp);
- break;
-
- case activateEvt:
- if ((erp->modifiers & activeFlag) != 0)
- do_window_activate ((WindowPtr) erp->message);
- else
- do_window_deactivate ((WindowPtr) erp->message);
- break;
- }
-}
-
-static void
-do_apple_menu (SInt16 menu_item)
-{
- Str255 item_name;
- SInt16 da_driver_refnum;
-
- if (menu_item == I_ABOUT)
- NoteAlert (ABOUT_ALERT_ID, NULL);
- else
- {
- GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
- da_driver_refnum = OpenDeskAcc (item_name);
- }
-}
-
-void
-do_menu_choice (SInt32 menu_choice)
-{
- SInt16 menu_id, menu_item;
-
- menu_id = HiWord (menu_choice);
- menu_item = LoWord (menu_choice);
-
- if (menu_id == 0)
- return;
-
- switch (menu_id)
- {
- case M_APPLE:
- do_apple_menu (menu_item);
- break;
-
- default:
- {
- WindowPtr wp = FrontWindow ();
- struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
- MenuHandle menu = GetMenuHandle (menu_id);
- if (menu)
- {
- UInt32 refcon;
-
- GetMenuItemRefCon (menu, menu_item, &refcon);
- menubar_selection_callback (f, refcon);
- }
- }
- }
-
- HiliteMenu (0);
-}
-
-
-/* Handle drags in size box. Based on code contributed by Ben
- Mesander and IM - Window Manager A. */
-
-static void
-do_grow_window (WindowPtr w, EventRecord *e)
-{
- long grow_size;
- Rect limit_rect;
- int rows, columns;
- mac_output *mwp = (mac_output *) GetWRefCon (w);
- struct frame *f = mwp->mFP;
-
- SetRect(&limit_rect, MIN_DOC_SIZE, MIN_DOC_SIZE, MAX_DOC_SIZE, MAX_DOC_SIZE);
-
- grow_size = GrowWindow (w, e->where, &limit_rect);
-
- /* see if it really changed size */
- if (grow_size != 0)
- {
- rows = PIXEL_TO_CHAR_HEIGHT (f, HiWord (grow_size));
- columns = PIXEL_TO_CHAR_WIDTH (f, LoWord (grow_size));
-
- x_set_window_size (f, 0, columns, rows);
- }
-}
-
-
-/* Handle clicks in zoom box. Calculation of "standard state" based
- on code in IM - Window Manager A and code contributed by Ben
- Mesander. The standard state of an Emacs window is 80-characters
- wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
-
-static void
-do_zoom_window (WindowPtr w, int zoom_in_or_out)
-{
- GrafPtr save_port;
- Rect zoom_rect, port_rect;
- Point top_left;
- int w_title_height, columns, rows, width, height, dummy, x, y;
- mac_output *mwp = (mac_output *) GetWRefCon (w);
- struct frame *f = mwp->mFP;
-
- GetPort (&save_port);
- SetPort (w);
- EraseRect (&(w->portRect)); /* erase to avoid flicker */
- if (zoom_in_or_out == inZoomOut)
- {
- SetPt(&top_left, w->portRect.left, w->portRect.top);
- LocalToGlobal (&top_left);
-
- /* calculate height of window's title bar */
- w_title_height = top_left.v - 1
- - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight();
-
- /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
- zoom_rect = qd.screenBits.bounds;
- zoom_rect.top += w_title_height;
- InsetRect (&zoom_rect, 8, 4); /* not too tight */
-
- zoom_rect.right = zoom_rect.left
- + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
-
- (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState = zoom_rect;
- }
-
- ZoomWindow (w, zoom_in_or_out, w == FrontWindow());
-
- /* retrieve window size and update application values */
- port_rect = w->portRect;
- rows = PIXEL_TO_CHAR_HEIGHT (f, port_rect.bottom - port_rect.top);
- columns = PIXEL_TO_CHAR_WIDTH (f, port_rect.right - port_rect.left);
- x_set_window_size (mwp->mFP, 0, columns, rows);
-
- SetPort (save_port);
-}
-
-
-/* Intialize AppleEvent dispatcher table for the required events. */
-void
-init_required_apple_events ()
-{
- OSErr err;
- long result;
-
- /* Make sure we have apple events before starting. */
- err = Gestalt (gestaltAppleEventsAttr, &result);
- if (err != noErr)
- abort ();
-
- if (!(result & (1 << gestaltAppleEventsPresent)))
- abort ();
-
- err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
- NewAEEventHandlerProc ((AEEventHandlerProcPtr) do_ae_open_application),
- 0L, false);
- if (err != noErr)
- abort ();
-
- err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
- NewAEEventHandlerProc ((AEEventHandlerProcPtr) do_ae_open_documents),
- 0L, false);
- if (err != noErr)
- abort ();
-
- err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
- NewAEEventHandlerProc ((AEEventHandlerProcPtr) do_ae_print_documents),
- 0L, false);
- if (err != noErr)
- abort ();
-
- err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
- NewAEEventHandlerProc ((AEEventHandlerProcPtr) do_ae_quit_application),
- 0L, false);
- if (err != noErr)
- abort ();
-}
-
-
-/* Open Application Apple Event */
-static pascal OSErr
-do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
-{
- return noErr;
-}
-
-
-/* Defined in mac.c. */
-extern int
-path_from_vol_dir_name (char *, int, short, long, char *);
-
-
-/* Called when we receive an AppleEvent with an ID of
- "kAEOpenDocuments". This routine gets the direct parameter,
- extracts the FSSpecs in it, and puts their names on a list. */
-static pascal OSErr
-do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
-{
- OSErr err, err2;
- AEDesc the_desc;
- AEKeyword keyword;
- DescType actual_type;
- Size actual_size;
-
- err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
- if (err != noErr)
- goto descriptor_error_exit;
-
- /* Check to see that we got all of the required parameters from the
- event descriptor. For an 'odoc' event this should just be the
- file list. */
- err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
- &actual_type, (Ptr) &keyword,
- sizeof (keyword), &actual_size);
- /* No error means that we found some unused parameters.
- errAEDescNotFound means that there are no more parameters. If we
- get an error code other than that, flag it. */
- if ((err == noErr) || (err != errAEDescNotFound))
- {
- err = errAEEventNotHandled;
- goto error_exit;
- }
- err = noErr;
-
- /* Got all the parameters we need. Now, go through the direct
- object list and parse it up. */
- {
- long num_files_to_open;
-
- err = AECountItems (&the_desc, &num_files_to_open);
- if (err == noErr)
- {
- int i;
-
- /* AE file list is one based so just use that for indexing here. */
- for (i = 1; (err == noErr) && (i <= num_files_to_open); i++) {
- FSSpec fs;
- Str255 path_name, unix_path_name;
-
- err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
- (Ptr) &fs, sizeof (fs), &actual_size);
- if (err != noErr) break;
-
- if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID,
- fs.name) &&
- mac_to_posix_pathname (path_name, unix_path_name, 255))
- drag_and_drop_file_list = Fcons (build_string (unix_path_name),
- drag_and_drop_file_list);
- }
- }
- }
-
-error_exit:
- /* Nuke the coerced file list in any case */
- err2 = AEDisposeDesc(&the_desc);
-
-descriptor_error_exit:
- /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
- return err;
-}
-
-
-/* Print Document Apple Event */
-static pascal OSErr
-do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
-{
- return errAEEventNotHandled;
-}
-
-
-static pascal OSErr
-do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
-{
- /* FixMe: Do we need an unwind-protect or something here? And what
- do we do about unsaved files. Currently just forces quit rather
- than doing recursive callback to get user input. */
-
- terminate_flag = true;
-
- /* Fkill_emacs doesn't return. We have to return. (TI) */
- return noErr;
-}
-
-
-#if __profile__
-void
-profiler_exit_proc ()
-{
- ProfilerDump ("\pEmacs.prof");
- ProfilerTerm ();
-}
-#endif
-
-/* These few functions implement Emacs as a normal Mac application
- (almost): set up the heap and the Toolbox, handle necessary
- system events plus a few simple menu events. They also set up
- Emacs's access to functions defined in the rest of this file.
- Emacs uses function hooks to perform all its terminal I/O. A
- complete list of these functions appear in termhooks.h. For what
- they do, read the comments there and see also w32term.c and
- xterm.c. What's noticeably missing here is the event loop, which
- is normally present in most Mac application. After performing the
- necessary Mac initializations, main passes off control to
- emacs_main (corresponding to main in emacs.c). Emacs_main calls
- mac_read_socket (defined further below) to read input. This is
- where WaitNextEvent is called to process Mac events. This is also
- where check_alarm in sysdep.c is called to simulate alarm signals.
- This makes the cursor jump back to its correct position after
- briefly jumping to that of the matching parenthesis, print useful
- hints and prompts in the minibuffer after the user stops typing for
- a wait, etc. */
-
-#undef main
-int
-main (void)
-{
-#if __profile__ /* is the profiler on? */
- if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
- exit(1);
-#endif
-
-#if __MWERKS__
- /* set creator and type for files created by MSL */
- _fcreator = 'EMAx';
- _ftype = 'TEXT';
-#endif
-
- do_init_managers ();
-
- do_get_menus ();
-
- do_check_ram_size ();
-
- init_emacs_passwd_dir ();
-
- init_environ ();
-
- initialize_applescript ();
-
- init_required_apple_events ();
-
- {
- char **argv;
- int argc = 0;
-
- /* set up argv array from STR# resource */
- get_string_list (&argv, ARGV_STRING_LIST_ID);
- while (argv[argc])
- argc++;
-
- /* free up AppleScript resources on exit */
- atexit (terminate_applescript);
-
-#if __profile__ /* is the profiler on? */
- atexit (profiler_exit_proc);
-#endif
-
- /* 3rd param "envp" never used in emacs_main */
- (void) emacs_main (argc, argv, 0);
- }
-
- /* Never reached - real exit in Fkill_emacs */
- return 0;
-}
-
-
-/* Table for translating Mac keycode to X keysym values. Contributed
- by Sudhir Shenoy. */
-static unsigned char keycode_to_xkeysym_table[] = {
-/* 0x00 - 0x3f */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-/* 0x40 */
- 0, '\xae' /* kp. */, 0, '\xaa' /* kp* */,
- 0, '\xab' /* kp+ */, 0, '\x7f' /* kp_clr */,
- 0, 0, 0, '\xaf' /* kp/ */,
- '\x8d' /* kp_ent */, 0, '\xad' /* kp- */, 0,
-/* 0x50 */
- 0, '\xbd' /* kp= */, '\xb0' /* kp0 */, '\xb1' /* kp1 */,
- '\xb2' /* kp2 */, '\xb3' /* kp3 */, '\xb4' /* kp4 */, '\xb5' /* kp5 */,
- '\xb6' /* kp6 */, '\xb7' /* kp7 */, 0, '\xb8' /* kp8 */,
- '\xb9' /* kp9 */, 0, 0, 0,
-/* 0x60 */
- '\xc2' /* F5 */, '\xc3' /* F6 */, '\xc4' /* F7 */, '\xc0' /* F3 */,
- '\xc5' /* F8 */, '\xc6' /* F9 */, 0, '\xc8' /* F11 */,
- 0, '\xca' /* F13 */, 0, '\xcb' /* F14 */,
- 0, '\xc7' /* F10 */, 0, '\xc9' /* F12 */,
-/* 0x70 */
- 0, '\xcc' /* F15 */, '\x9e' /* ins */, '\x95' /* home */,
- '\x9a' /* pgup */, '\x9f' /* del */, '\xc1' /* F4 */, '\x9c' /* end */,
- '\xbf' /* F2 */, '\x9b' /* pgdown */, '\xbe' /* F1 */, '\x51' /* left */,
- '\x53' /* right */, '\x54' /* down */, '\x52' /* up */, 0
-};
-
-static int
-keycode_to_xkeysym (int keyCode, int *xKeySym)
-{
- *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
- return *xKeySym != 0;
-}
-
-/* Emacs calls this whenever it wants to read an input event from the
- user. */
-int
-XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
-{
- int count = 0;
- EventRecord er;
- int the_modifiers;
- EventMask event_mask;
-
- if (interrupt_input_blocked)
- {
- interrupt_input_pending = 1;
- return -1;
- }
-
- interrupt_input_pending = 0;
- BLOCK_INPUT;
-
- /* So people can tell when we have read the available input. */
- input_signal_count++;
-
- if (numchars <= 0)
- abort ();
-
- /* Don't poll for events to process (specifically updateEvt) if
- window update currently already in progress. A call to redisplay
- (in do_window_update) can be preempted by another call to
- redisplay, causing blank regions to be left on the screen and the
- cursor to be left at strange places. */
- if (handling_window_update)
- {
- UNBLOCK_INPUT;
- return 0;
- }
-
- if (terminate_flag)
- Fkill_emacs (make_number (1));
-
- /* It is necessary to set this (additional) argument slot of an
- event to nil because keyboard.c protects incompletely processed
- event from being garbage collected by placing them in the
- kbd_buffer_gcpro vector. */
- bufp->arg = Qnil;
-
- event_mask = everyEvent;
- if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
- event_mask -= highLevelEventMask;
-
- while (WaitNextEvent (event_mask, &er, 0L, NULL) && numchars > 0)
- switch (er.what)
- {
- case mouseDown:
- case mouseUp:
- {
- WindowPtr window_ptr = FrontWindow ();
- SInt16 part_code;
-
- if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
- && er.what == mouseUp)
- {
- struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
- Point mouse_loc = er.where;
-
- /* Convert to local coordinates of new window. */
- SetPort (window_ptr);
- GlobalToLocal (&mouse_loc);
-
- bufp->code = 0; /* only one mouse button */
- bufp->kind = scroll_bar_click;
- bufp->frame_or_window = tracked_scroll_bar->window;
- bufp->part = scroll_bar_handle;
- bufp->modifiers = up_modifier;
- bufp->timestamp = er.when * (1000 / 60);
- /* ticks to milliseconds */
-
- XSETINT (bufp->x, tracked_scroll_bar->left + 2);
- XSETINT (bufp->y, mouse_loc.v - 24);
- tracked_scroll_bar->dragging = Qnil;
- mouse_tracking_in_progress = mouse_tracking_none;
- tracked_scroll_bar = NULL;
- count++;
- bufp++;
- numchars--;
- break;
- }
-
- part_code = FindWindow (er.where, &window_ptr);
-
- switch (part_code)
- {
- case inMenuBar:
- {
- struct frame *f = ((mac_output *)
- GetWRefCon (FrontWindow ()))->mFP;
- saved_menu_event_location = er.where;
- bufp->kind = menu_bar_activate_event;
- XSETFRAME (bufp->frame_or_window, f);
- count++;
- bufp++;
- numchars--;
- }
- break;
-
- case inContent:
- if (window_ptr != FrontWindow ())
- SelectWindow (window_ptr);
- else
- {
- int control_part_code;
- ControlHandle ch;
- struct mac_output *mwp = (mac_output *)
- GetWRefCon (window_ptr);
- Point mouse_loc = er.where;
-
- /* convert to local coordinates of new window */
- SetPort (window_ptr);
- GlobalToLocal (&mouse_loc);
- control_part_code = FindControl (mouse_loc, window_ptr, &ch);
-
- bufp->code = 0; /* only one mouse button */
- XSETINT (bufp->x, mouse_loc.h);
- XSETINT (bufp->y, mouse_loc.v);
- bufp->timestamp = er.when * (1000 / 60);
- /* ticks to milliseconds */
-
- if (control_part_code != 0)
- {
- struct scroll_bar *bar = (struct scroll_bar *)
- GetControlReference (ch);
- x_scroll_bar_handle_click (bar, control_part_code, &er,
- bufp);
- if (er.what == mouseDown
- && control_part_code == kControlIndicatorPart)
- {
- mouse_tracking_in_progress = mouse_tracking_scroll_bar;
- tracked_scroll_bar = bar;
- }
- else
- {
- mouse_tracking_in_progress = mouse_tracking_none;
- tracked_scroll_bar = NULL;
- }
- }
- else
- {
- bufp->kind = mouse_click;
- XSETFRAME (bufp->frame_or_window, mwp->mFP);
- if (er.what == mouseDown)
- mouse_tracking_in_progress = mouse_tracking_mouse_movement;
- else
- mouse_tracking_in_progress = mouse_tracking_none;
- }
-
- switch (er.what)
- {
- case mouseDown:
- bufp->modifiers = down_modifier;
- break;
- case mouseUp:
- bufp->modifiers = up_modifier;
- break;
- }
-
- count++;
- bufp++;
- numchars--;
- }
- break;
-
- case inDrag:
- DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
- break;
-
- case inGoAway:
- if (TrackGoAway (window_ptr, er.where))
- {
- bufp->kind = delete_window_event;
- XSETFRAME (bufp->frame_or_window,
- ((mac_output *) GetWRefCon (window_ptr))->mFP);
- count++;
- bufp++;
- numchars--;
- }
- break;
-
- /* window resize handling added --ben */
- case inGrow:
- do_grow_window(window_ptr, &er);
- break;
-
- /* window zoom handling added --ben */
- case inZoomIn:
- case inZoomOut:
- if (TrackBox (window_ptr, er.where, part_code))
- do_zoom_window (window_ptr, part_code);
- break;
-
- default:
- break;
- }
- }
- break;
-
- case updateEvt:
- case osEvt:
- case activateEvt:
- do_events (&er);
- break;
-
- case keyDown:
- case autoKey:
- {
- int keycode = (er.message & keyCodeMask) >> 8;
- int xkeysym;
-
- ObscureCursor ();
-
- if (keycode == 0x33) /* delete key (charCode translated to 0x8) */
- {
- bufp->code = 0x7f;
- bufp->kind = ascii_keystroke;
- }
- else if (keycode_to_xkeysym (keycode, &xkeysym))
- {
- bufp->code = 0xff00 | xkeysym;
- bufp->kind = non_ascii_keystroke;
- }
- else
- {
- if (er.modifiers
- & (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
- {
- /* This code comes from Keyboard Resource, Appendix
- C of IM - Text. This is necessary since shift is
- ignored in KCHR table translation when option or
- command is pressed. */
- int new_modifiers = er.modifiers & 0xf600;
- /* mask off option and command */
- int new_keycode = keycode | new_modifiers;
- Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
- unsigned long some_state = 0;
- bufp->code = KeyTranslate (kchr_ptr, new_keycode,
- &some_state) & 0xff;
- }
- else
- bufp->code = er.message & charCodeMask;
- bufp->kind = ascii_keystroke;
- }
- }
-
- /* If variable mac-convert-keyboard-input-to-latin-1 is non-nil,
- convert non-ASCII characters typed at the Mac keyboard
- (presumed to be in the Mac Roman encoding) to iso-latin-1
- encoding before they are passed to Emacs. This enables the
- Mac keyboard to be used to enter non-ASCII iso-latin-1
- characters directly. */
- if (mac_keyboard_text_encoding != kTextEncodingMacRoman
- && bufp->kind == ascii_keystroke && bufp->code >= 128)
- {
- static TECObjectRef converter = NULL;
- OSStatus the_err = noErr;
- OSStatus convert_status = noErr;
-
- if (converter == NULL)
- {
- the_err = TECCreateConverter (&converter,
- kTextEncodingMacRoman,
- mac_keyboard_text_encoding);
- current_mac_keyboard_text_encoding = mac_keyboard_text_encoding;
- }
- else if (mac_keyboard_text_encoding != current_mac_keyboard_text_encoding)
- {
- /* Free the converter for the current encoding before
- creating a new one. */
- TECDisposeConverter (converter);
- the_err = TECCreateConverter (&converter,
- kTextEncodingMacRoman,
- mac_keyboard_text_encoding);
- current_mac_keyboard_text_encoding = mac_keyboard_text_encoding;
- }
-
- if (the_err == noErr)
- {
- unsigned char ch = bufp->code;
- ByteCount actual_input_length, actual_output_length;
- unsigned char outch;
-
- convert_status = TECConvertText (converter, &ch, 1,
- &actual_input_length,
- &outch, 1,
- &actual_output_length);
- if (convert_status == noErr
- && actual_input_length == 1
- && actual_output_length == 1)
- bufp->code = outch;
- }
- }
-
- the_modifiers = 0;
- if (er.modifiers & shiftKey)
- the_modifiers |= shift_modifier;
- if (er.modifiers & controlKey)
- the_modifiers |= ctrl_modifier;
- /* use option or command key as meta depending on value of
- mac-command-key-is-meta */
- if (er.modifiers
- & (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
- the_modifiers |= meta_modifier;
- bufp->modifiers = the_modifiers;
-
- {
- mac_output *mwp = (mac_output *) GetWRefCon (FrontWindow ());
- XSETFRAME (bufp->frame_or_window, mwp->mFP);
- }
-
- bufp->timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
-
- count++;
- bufp++;
- numchars--;
- break;
-
- case kHighLevelEvent:
- drag_and_drop_file_list = Qnil;
-
- AEProcessAppleEvent(&er);
-
- /* Build a drag_n_drop type event as is done in
- constuct_drag_n_drop in w32term.c. */
- if (!NILP (drag_and_drop_file_list))
- {
- struct frame *f;
- WindowPtr wp;
- Lisp_Object frame;
-
- wp = FrontWindow ();
- if (!wp)
- f = NULL;
- else
- f = ((mac_output *) GetWRefCon (wp))->mFP;
-
- bufp->kind = drag_n_drop;
- bufp->code = 0;
- bufp->timestamp = er.when * (1000 / 60);
- /* ticks to milliseconds */
- bufp->modifiers = 0;
-
- XSETINT (bufp->x, 0);
- XSETINT (bufp->y, 0);
-
- XSETFRAME (frame, f);
- bufp->frame_or_window = Fcons (frame, drag_and_drop_file_list);
-
- /* Regardless of whether Emacs was suspended or in the
- foreground, ask it to redraw its entire screen.
- Otherwise parts of the screen can be left in an
- inconsistent state. */
- if (wp)
- InvalRect (&(wp->portRect));
-
- count++;
- bufp++;
- numchars--;
- }
-
- default:
- break;
- }
-
- /* If the focus was just given to an autoraising frame,
- raise it now. */
- /* ??? This ought to be able to handle more than one such frame. */
- if (pending_autoraise_frame)
- {
- x_raise_frame (pending_autoraise_frame);
- pending_autoraise_frame = 0;
- }
-
- check_alarm (); /* simulate the handling of a SIGALRM */
-
- {
- static Point old_mouse_pos = { -1, -1 };
-
- if (app_is_suspended)
- {
- old_mouse_pos.h = -1;
- old_mouse_pos.v = -1;
- }
- else
- {
- Point mouse_pos;
- WindowPtr wp = FrontWindow ();
- struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
- Lisp_Object bar;
- struct scroll_bar *sb;
-
- SetPort (wp);
- GetMouse (&mouse_pos);
-
- if (!EqualPt (mouse_pos, old_mouse_pos))
- {
- if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
- && tracked_scroll_bar)
- x_scroll_bar_note_movement (tracked_scroll_bar,
- mouse_pos.v
- - XINT (tracked_scroll_bar->top),
- TickCount() * (1000 / 60));
- else
- note_mouse_movement (f, &mouse_pos);
-
- old_mouse_pos = mouse_pos;
- }
- }
- }
-
- UNBLOCK_INPUT;
-
- return count;
-}
-
-
-/* Need to override CodeWarrior's input function so no conversion is
- done on newlines Otherwise compiled functions in .elc files will be
- read incorrectly. Defined in ...:MSL C:MSL
- Common:Source:buffer_io.c. */
-#ifdef __MWERKS__
-void
-__convert_to_newlines (unsigned char * p, size_t * n)
-{
-#pragma unused(p,n)
-}
-
-void
-__convert_from_newlines (unsigned char * p, size_t * n)
-{
-#pragma unused(p,n)
-}
-#endif
-
-
-/* Initialize the struct pointed to by MW to represent a new COLS x
- ROWS Macintosh window, using font with name FONTNAME and size
- FONTSIZE. */
-void
-NewMacWindow (FRAME_PTR fp)
-{
- mac_output *mwp;
- static int making_terminal_window = 1;
-
- mwp = fp->output_data.mac;
-
- if (making_terminal_window)
- {
- if (!(mwp->mWP = GetNewCWindow (TERM_WINDOW_RESOURCE, NULL,
- (WindowPtr) -1)))
- abort ();
- making_terminal_window = 0;
- }
- else
- if (!(mwp->mWP = GetNewCWindow (WINDOW_RESOURCE, NULL, (WindowPtr) -1)))
- abort ();
-
-
- SetWRefCon (mwp->mWP, (long) mwp);
- /* so that update events can find this mac_output struct */
- mwp->mFP = fp; /* point back to emacs frame */
-
- SetPort (mwp->mWP);
-
- mwp->fontset = -1;
-
- SizeWindow (mwp->mWP, mwp->pixel_width, mwp->pixel_height, false);
- ShowWindow (mwp->mWP);
-
-}
-
-
-void make_mac_frame (struct frame *f)
-{
- FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
- FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
-
- NewMacWindow(f);
- f->output_data.mac->background_pixel = 0xffffff;
- f->output_data.mac->foreground_pixel = 0;
-
- f->output_data.mac->cursor_pixel = 0;
- f->output_data.mac->border_pixel = 0x00ff00;
- f->output_data.mac->mouse_pixel = 0xff00ff;
- f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
-
- f->output_data.mac->desired_cursor = FILLED_BOX_CURSOR;
-
- f->output_data.mac->fontset = -1;
- f->output_data.mac->scroll_bar_foreground_pixel = -1;
- f->output_data.mac->scroll_bar_background_pixel = -1;
- f->output_data.mac->left_pos = 4;
- f->output_data.mac->top_pos = 4;
- f->output_data.mac->border_width = 0;
- f->output_data.mac->explicit_parent = 0;
-
- f->output_data.mac->internal_border_width = 0;
-
- f->output_method = output_mac;
-
- f->auto_raise = 1;
- f->auto_lower = 1;
-
- f->new_width = 0;
- f->new_height = 0;
-}
-
-void make_mac_terminal_frame (struct frame *f)
-{
- Lisp_Object frame;
-
- XSETFRAME (frame, f);
-
- f->output_method = output_mac;
- f->output_data.mac = (struct mac_output *)
- xmalloc (sizeof (struct mac_output));
- bzero (f->output_data.mac, sizeof (struct mac_output));
- f->output_data.mac->fontset = -1;
- f->output_data.mac->scroll_bar_foreground_pixel = -1;
- f->output_data.mac->scroll_bar_background_pixel = -1;
-
- XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
-
- f->width = 96;
- f->height = 4;
-
- make_mac_frame (f);
-
- Fmodify_frame_parameters (frame,
- Fcons (Fcons (Qfont,
- build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
- Fmodify_frame_parameters (frame,
- Fcons (Fcons (Qforeground_color,
- build_string ("black")), Qnil));
- Fmodify_frame_parameters (frame,
- Fcons (Fcons (Qbackground_color,
- build_string ("white")), Qnil));
-}
-
-void
-mac_initialize_display_info ()
-{
- struct mac_display_info *dpyinfo = &one_mac_display_info;
- GDHandle main_device_handle;
-
- bzero (dpyinfo, sizeof (*dpyinfo));
-
- /* Put it on x_display_name_list. */
- x_display_name_list = Fcons (Fcons (build_string ("Mac"), Qnil),
- x_display_name_list);
- dpyinfo->name_list_element = XCAR (x_display_name_list);
-
- main_device_handle = LMGetMainDevice();
-
- dpyinfo->reference_count = 0;
- dpyinfo->resx = 75.0;
- dpyinfo->resy = 75.0;
- dpyinfo->n_planes = 1;
- dpyinfo->n_cbits = 16;
- dpyinfo->height = (**main_device_handle).gdRect.bottom;
- dpyinfo->width = (**main_device_handle).gdRect.right;
- dpyinfo->grabbed = 0;
- dpyinfo->root_window = NULL;
-
- dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
- dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
- dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
- dpyinfo->mouse_face_window = Qnil;
-
-}
-
-void
-x_initialize ()
-{
- rif = &x_redisplay_interface;
-
- clear_frame_hook = x_clear_frame;
- ins_del_lines_hook = x_ins_del_lines;
- change_line_highlight_hook = x_change_line_highlight;
- delete_glyphs_hook = x_delete_glyphs;
- ring_bell_hook = XTring_bell;
- reset_terminal_modes_hook = XTreset_terminal_modes;
- set_terminal_modes_hook = XTset_terminal_modes;
- update_begin_hook = x_update_begin;
- update_end_hook = x_update_end;
- set_terminal_window_hook = XTset_terminal_window;
- read_socket_hook = XTread_socket;
- frame_up_to_date_hook = XTframe_up_to_date;
- reassert_line_highlight_hook = XTreassert_line_highlight;
- mouse_position_hook = XTmouse_position;
- frame_rehighlight_hook = XTframe_rehighlight;
- frame_raise_lower_hook = XTframe_raise_lower;
-
- set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
- condemn_scroll_bars_hook = XTcondemn_scroll_bars;
- redeem_scroll_bar_hook = XTredeem_scroll_bar;
- judge_scroll_bars_hook = XTjudge_scroll_bars;
-
- estimate_mode_line_height_hook = x_estimate_mode_line_height;
-
- scroll_region_ok = 1; /* we'll scroll partial frames */
- char_ins_del_ok = 0; /* just as fast to write the line */
- line_ins_del_ok = 1; /* we'll just blt 'em */
- fast_clear_end_of_line = 1; /* X does this well */
- memory_below_frame = 0; /* we don't remember what scrolls
- off the bottom */
- baud_rate = 19200;
-
- x_noop_count = 0;
- last_tool_bar_item = -1;
- any_help_event_p = 0;
-
- /* Try to use interrupt input; if we can't, then start polling. */
- Fset_input_mode (Qt, Qnil, Qt, Qnil);
-
-#ifdef USE_X_TOOLKIT
- XtToolkitInitialize ();
- Xt_app_con = XtCreateApplicationContext ();
- XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
-
- /* Install an asynchronous timer that processes Xt timeout events
- every 0.1s. This is necessary because some widget sets use
- timeouts internally, for example the LessTif menu bar, or the
- Xaw3d scroll bar. When Xt timouts aren't processed, these
- widgets don't behave normally. */
- {
- EMACS_TIME interval;
- EMACS_SET_SECS_USECS (interval, 0, 100000);
- start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
- }
-#endif
-
-#if USE_TOOLKIT_SCROLL_BARS
- xaw3d_arrow_scroll = False;
- xaw3d_pick_top = True;
-#endif
-
-#if 0
- /* Note that there is no real way portable across R3/R4 to get the
- original error handler. */
- XSetErrorHandler (x_error_handler);
- XSetIOErrorHandler (x_io_error_quitter);
-
- /* Disable Window Change signals; they are handled by X events. */
-#ifdef SIGWINCH
- signal (SIGWINCH, SIG_DFL);
-#endif /* ! defined (SIGWINCH) */
-
- signal (SIGPIPE, x_connection_signal);
-#endif
-
- mac_initialize_display_info ();
-}
-
-
-void
-syms_of_macterm ()
-{
-#if 0
- staticpro (&x_error_message_string);
- x_error_message_string = Qnil;
-#endif
-
- staticpro (&x_display_name_list);
- x_display_name_list = Qnil;
-
- staticpro (&last_mouse_scroll_bar);
- last_mouse_scroll_bar = Qnil;
-
- staticpro (&Qvendor_specific_keysyms);
- Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
-
- staticpro (&last_mouse_press_frame);
- last_mouse_press_frame = Qnil;
-
- Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
- staticpro (&Qmac_ready_for_drag_n_drop);
-
- help_echo = Qnil;
- staticpro (&help_echo);
- help_echo_object = Qnil;
- staticpro (&help_echo_object);
- help_echo_window = Qnil;
- staticpro (&help_echo_window);
- previous_help_echo = Qnil;
- staticpro (&previous_help_echo);
- help_echo_pos = -1;
-
- DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
- "*Non-nil means draw block cursor as wide as the glyph under it.\n\
-For example, if a block cursor is over a tab, it will be drawn as\n\
-wide as that tab on the display.");
- x_stretch_cursor_p = 0;
-
- DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
- "If not nil, Emacs uses toolkit scroll bars.");
-#if USE_TOOLKIT_SCROLL_BARS
- x_toolkit_scroll_bars_p = 1;
-#else
- x_toolkit_scroll_bars_p = 0;
-#endif
-
- staticpro (&last_mouse_motion_frame);
- last_mouse_motion_frame = Qnil;
-
- DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
- "Non-nil means that the command key is used as the Emacs meta key.\n\
-Otherwise the option key is used.");
- Vmac_command_key_is_meta = Qt;
-
- DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
- "One of the Text Encoding Base constant values defined in the\n\
-Basic Text Constants section of Inside Macintosh - Text Encoding\n\
-Conversion Manager. Its value determines the encoding characters\n\
-typed at the Mac keyboard (presumed to be in the MacRoman encoding)\n\
-will convert into. E.g., if it is set to kTextEncodingMacRoman (0),\n\
-its default value, no conversion takes place. If it is set to\n\
-kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),\n\
-characters typed on Mac keyboard are first converted into the\n\
-ISO Latin-1 or ISO Latin-2 encoding, respectively before being\n\
-passed to Emacs. Together with Emacs's set-keyboard-coding-system\n\
-command, this enables the Mac keyboard to be used to enter non-ASCII\n\
-characters directly.");
- mac_keyboard_text_encoding = kTextEncodingMacRoman;
-}
src src/m src/s src/bitmaps lib-src oldXMenu lwlib \
nt nt/inc nt/inc/sys nt/inc/arpa nt/inc/netinet nt/icons \
etc etc/e lock info man msdos vms mac mac/inc mac/inc/sys \
- mac/src
+ mac/src mac/Emacs.app mac/Emacs.app/Contents \
+ mac/Emacs.app/Contents/MacOS mac/Emacs.app/Contents/Resources \
+ mac/Emacs.app/Contents/Resources/English.lproj
do
echo " ${tempdir}/${subdir}"
mkdir ${tempdir}/${subdir}
(cd mac/src
ln [a-z]*.c *.r ../../${tempdir}/mac/src)
+echo "Making links to \`mac/Emacs.app/Contents'"
+(cd mac/Emacs.app/Contents
+ ln Info.plist PkgInfo ../../../${tempdir}/mac/Emacs.app/Contents)
+
+echo "Making links to \`mac/Emacs.app/Contents/Resources/English.lproj'"
+(cd mac/Emacs.app/Contents/Resources/English.lproj
+ ln InfoPlist.strings ../../../../../${tempdir}/mac/Emacs.app/Contents/Resources/English.lproj)
+
echo "Making links to \`msdos'"
(cd msdos
ln ChangeLog emacs.ico emacs.pif ../${tempdir}/msdos
@c This is part of the Emacs manual.
-@c Copyright (C) 2000,2001 Free Software Foundation, Inc.
+@c Copyright (C) 2000,2001,2002 Free Software Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Mac OS, MS-DOS, Antinews, Top
@appendix Emacs and the Mac OS
@cindex Mac OS
@cindex Macintosh
- Emacs built on the Mac OS supports many of its major features:
+ Emacs built on Mac OS X supports most of its major features:
multiple frames, colors, scroll bars, menu bars, use of the mouse,
-fontsets, international characters, input methods, coding systems, and
-synchronous subprocesses (@code{call-process}). Much of this works in
-the same way as on other platforms and is therefore documented in the
-rest of this manual. This section describes the peculiarities of using
-Emacs under the Mac OS.
-
- The following features of Emacs are not yet supported on the Mac:
-unexec (@code{dump-emacs}), asynchronous subprocesses
+fontsets, international characters, input methods, coding systems,
+asynchronous and synchronous subprocesses, unexec (@code{dump-emacs}),
+and networking (@code{open-network-stream}). Support for various
+image file formats has not been implemented yet.
+
+ The following features of Emacs are not yet supported on the Mac OS
+8 or 9: unexec (@code{dump-emacs}), asynchronous subprocesses
(@code{start-process}), and networking (@code{open-network-stream}).
As a result, packages such as Gnus, GUD, and Comint do not work.
+However, synchronous subprocesses (@code{call-process}) are supported.
+Since external programs to handle commands such as @code{print-buffer}
+and @code{diff} are not available on Mac OS 8 or 9, they are not
+supported.
- Since external programs to handle commands such as
-@code{print-buffer} and @code{diff} are not available on the Mac OS,
-they are not supported in the Mac OS version.
+ Most of the features that are supported work in the same way as on
+other platforms and are therefore documented in the rest of this
+manual. This section describes the peculiarities of using Emacs under
+the Mac OS.
@menu
* Input: Mac Input. Keyboard input on the Mac.
@section Environment Variables and Command Line Arguments.
@cindex environment variables (Mac OS)
- Environment variables and command line arguments for Emacs can be set
-by modifying the @samp{STR#} resources 128 and 129, respectively. A common
-environment variable that one may want to set is @samp{HOME}.
+ On Mac OS X, when Emacs is run in a terminal, it inherits the values
+of environment variables from the shell from which it is invoked.
+However, when it is run from the Finder as a GUI application, it
+inherits no environment variable values.
+
+ On Mac OS 8 or 9, environment variables and command line arguments
+for Emacs can be set by modifying the @samp{STR#} resources 128 and
+129, respectively. A common environment variable that one may want to
+set is @samp{HOME}.
The way to set an environment variable is by adding a string of the
form
@file{/} will display all volumes on the system. You can use @file{..}
to go up a directory level.
- To access files and folders on the desktop, look in the folder
-@file{Desktop Folder} in your boot volume (this folder is usually
-invisible in the Mac @code{Finder}).
-
- Emacs creates the Mac folder @file{:Preferences:Emacs:} in the
-@file{System Folder} and uses it as the temporary directory. Emacs
-maps the directory name @file{/tmp/} to that. Therefore it
-is best to avoid naming a volume @file{tmp}. If everything works
-correctly, the program should leave no files in it when it exits. You
-should be able to set the environment variable @code{TMPDIR} to use
-another directory but this folder will still be created.
+ On Mac OS 8 or 9, to access files and folders on the desktop, look
+in the folder @file{Desktop Folder} in your boot volume (this folder
+is usually invisible in the Mac @code{Finder}).
+
+ On Mac OS 8 or 9, Emacs creates the Mac folder
+@file{:Preferences:Emacs:} in the @file{System Folder} and uses it as
+the temporary directory. Emacs maps the directory name @file{/tmp/}
+to that. Therefore it is best to avoid naming a volume @file{tmp}.
+If everything works correctly, the program should leave no files in it
+when it exits. You should be able to set the environment variable
+@code{TMPDIR} to use another directory but this folder will still be
+created.
@node Mac Font Specs
+2002-04-26 Andrew Choi <akochoi@shaw.ca>
+
+ * Makefile.in (C_SWITCH_SYSTEM_TEMACS): Add.
+ [HAVE_CARBON]: Include Mac object files.
+
+ * alloc.c, callproc.c, dispextern.h, dispnew.c, emacs.c,
+ fontset.c, frame.c, frame.h, keyboard.c, sysdep.c, term.c,
+ termcap.c, window.c, xdisp.c, xfaces.c: Use macros MAC_OS8,
+ MAC_OSX, and MAC_OS instead of macintosh.
+
+ * editfns.c [MAC_OS8]: Include stdio.h.
+
+ * emacs.c [MAC_OS8]: Call mac_initialize instead of x_term_init.
+
+ * fontset.c [MAC_OS]: Set Vdefault_fontset to ETL Fixed instead of
+ Apple Monaco.
+
+ * process.c: Declare QCfamily and QCfilter as extern.
+ (wait_reading_process_input) [MAC_OSX]: Clear bit for stdin before
+ calling select.
+
+ * termcap.c [MAC_OSX]: Don't define tgetnum, PC, tputs, and
+ tgetent.
+
+ * tparam.c [MAC_OSX]: Don't define BC and UP.
+
+ * config.in [HAVE_CARBON]: Add.
+
+ * mac.c, macgui.h, macfns.c, macmenu.c, macterm.c, macterm.h: Move
+ here from mac/src and mac/inc.
+
+ * s/darwin.h, m/powermac.h, unexmacosx.c: New files.
+
2002-04-26 Gerd Moellmann <gerd@gnu.org>
* xterm.c (x_draw_phys_cursor_glyph): Undo last change. Compute
#define LD_SWITCH_SYSTEM_TEMACS
#endif
+/* Some s/SYSTEM.h files define this to request special switches
+ for compiling temacs. */
+#ifndef C_SWITCH_SYSTEM_TEMACS
+#define C_SWITCH_SYSTEM_TEMACS
+#endif
+
/* Some m/MACHINE.h files define this to request special switches in ld. */
#ifndef LD_SWITCH_MACHINE
#define LD_SWITCH_MACHINE
/* C_SWITCH_X_SITE must come before C_SWITCH_X_MACHINE and C_SWITCH_X_SYSTEM
since it may have -I options that should override those two. */
-ALL_CFLAGS=-Demacs -DHAVE_CONFIG_H $(TOOLKIT_DEFINES) $(MYCPPFLAG) -I. -I${srcdir} C_SWITCH_MACHINE C_SWITCH_SYSTEM C_SWITCH_SITE C_SWITCH_X_SITE C_SWITCH_X_MACHINE C_SWITCH_X_SYSTEM ${CFLAGS}
+ALL_CFLAGS=-Demacs -DHAVE_CONFIG_H $(TOOLKIT_DEFINES) $(MYCPPFLAG) -I. -I${srcdir} C_SWITCH_MACHINE C_SWITCH_SYSTEM C_SWITCH_SITE C_SWITCH_X_SITE C_SWITCH_X_MACHINE C_SWITCH_X_SYSTEM C_SWITCH_SYSTEM_TEMACS ${CFLAGS}
.c.o:
$(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $<
#endif
#endif
+#ifdef HAVE_CARBON
+XMENU_OBJ =
+MAC_OBJ = mac.o macterm.o macfns.o macmenu.o fontset.o
+emacsapp = ../mac/Emacs.app/
+#else
+XMENU_OBJ = xmenu.o
+#endif
/* lastfile must follow all files
whose initialized data areas should be dumped as pure by dump-emacs. */
-obj= dispnew.o frame.o scroll.o xdisp.o xmenu.o window.o \
+obj= dispnew.o frame.o scroll.o xdisp.o $(XMENU_OBJ) window.o \
charset.o coding.o category.o ccl.o\
cm.o term.o xfaces.o $(XOBJ) \
emacs.o keyboard.o macros.o keymap.o sysdep.o \
process.o callproc.o \
region-cache.o sound.o atimer.o \
doprnt.o strftime.o intervals.o textprop.o composite.o md5.o \
- $(MSDOS_OBJ)
+ $(MSDOS_OBJ) $(MAC_OBJ)
/* Object files used on some machine or other.
These go in the DOC file on all machines
in case they are needed there. */
SOME_MACHINE_OBJECTS = sunfns.o dosfns.o msdos.o \
- xterm.o xfns.o xmenu.o xselect.o xrdb.o xsmfns.o
+ xterm.o xfns.o xmenu.o xselect.o xrdb.o \
+ mac.o macterm.o macfns.o macmenu.o
#ifdef TERMINFO
sunfns.o: sunfns.c buffer.h window.h dispextern.h $(config_h)
+#ifdef HAVE_CARBON
+abbrev.o buffer.o callint.o cmds.o dispnew.o editfns.o fileio.o frame.o \
+ fontset.o indent.o insdel.o keyboard.o macros.o minibuf.o msdos.o process.o \
+ scroll.o sysdep.o term.o widget.o window.o xdisp.o xfaces.o xfns.o xmenu.o \
+ xterm.o xselect.o sound.o: macgui.h
+mac.o: mac.c process.h sysselect.h systime.h $(config_h)
+macfns.o: macfns.c charset.h macterm.h macgui.h frame.h window.h buffer.h \
+ dispextern.h macgui.h fontset.h $(INTERVAL_SRC) keyboard.h blockinput.h \
+ atimer.h systime.h epaths.h termhooks.h coding.h ccl.h systime.h $(config_h)
+macmenu.o: macmenu.c termhooks.h frame.h window.h dispextern.h macgui.h \
+ keyboard.h blockinput.h atimer.h systime.h buffer.h macterm.h $(config_h)
+macterm.o: blockinput.h atimer.h systime.h syssignal.h macterm.h macgui.h \
+ frame.h charset.h ccl.h dispextern.h fontset.h termhooks.h termopts.h \
+ termchar.h gnu.h disptab.h buffer.h window.h keyboard.h $(INTERVAL_SRC) \
+ process.h coding.h $(config_h)
+
+macosx-app: ${emacsapp}Contents/MacOS/Emacs \
+ ${emacsapp}Contents/Resources/Emacs.rsrc
+
+${emacsapp}Contents/MacOS/Emacs: emacs
+ if [ -d ${emacsapp}Contents/MacOS/ ]; then true; else \
+ mkdir ${emacsapp}Contents/MacOS/; \
+ fi
+ cd ${emacsapp}Contents/MacOS/; cp ../../../../src/emacs Emacs
+
+${emacsapp}Contents/Resources/Emacs.rsrc: ../mac/src/Emacs.r
+ /Developer/Tools/Rez -useDF -o \
+ ${emacsapp}Contents/Resources/Emacs.rsrc \
+ /System/Library/Frameworks/Carbon.framework/Headers/Carbon.r \
+ ../mac/src/Emacs.r
+#endif
+
${libsrc}emacstool: ${libsrc}emacstool.c
cd ${libsrc}; ${MAKE} ${MFLAGS} emacstool
bootstrapclean:
#ifdef GC_CHECK_STRING_BYTES
if (!noninteractive
-#ifdef macintosh
+#ifdef MAC_OS8
&& current_sblock
#endif
)
call_process_cleanup (fdpid)
Lisp_Object fdpid;
{
-#if defined (MSDOS) || defined (macintosh)
+#if defined (MSDOS) || defined (MAC_OS8)
/* for MSDOS fdpid is really (fd . tempfile) */
register Lisp_Object file;
file = Fcdr (fdpid);
emacs_close (XFASTINT (Fcar (fdpid)));
if (strcmp (XSTRING (file)-> data, NULL_DEVICE) != 0)
unlink (XSTRING (file)->data);
-#else /* not MSDOS and not macintosh */
+#else /* not MSDOS and not MAC_OS8 */
register int pid = XFASTINT (Fcdr (fdpid));
if (call_process_exited)
char *outf, *tempfile;
int outfilefd;
#endif
-#ifdef macintosh
+#ifdef MAC_OS8
char *tempfile;
int outfilefd;
#endif
fd[1] = outfilefd;
#endif /* MSDOS */
-#ifdef macintosh
+#ifdef MAC_OS8
/* Since we don't have pipes on the Mac, create a temporary file to
hold the output of the subprocess. */
tempfile = (char *) alloca (STRING_BYTES (XSTRING (Vtemp_file_name_pattern)) + 1);
}
fd[0] = filefd;
fd[1] = outfilefd;
-#endif /* macintosh */
+#endif /* MAC_OS8 */
if (INTEGERP (buffer))
fd[1] = emacs_open (NULL_DEVICE, O_WRONLY, 0), fd[0] = -1;
else
{
#ifndef MSDOS
-#ifndef macintosh
+#ifndef MAC_OS8
errno = 0;
if (pipe (fd) == -1)
{
current_dir = ENCODE_FILE (current_dir);
-#ifdef macintosh
+#ifdef MAC_OS8
{
/* Call run_mac_command in sysdep.c here directly instead of doing
a child_setup as for MSDOS and other platforms. Note that this
report_file_error ("Cannot re-open temporary file", Qnil);
}
}
-#else /* not macintosh */
+#else /* not MAC_OS8 */
#ifdef MSDOS /* MW, July 1993 */
/* Note that on MSDOS `child_setup' actually returns the child process
exit status, not its PID, so we assign it to `synch_process_retcode'
if (fd_error >= 0)
emacs_close (fd_error);
#endif /* not MSDOS */
-#endif /* not macintosh */
+#endif /* not MAC_OS8 */
environ = save_environ;
/* Enable sending signal if user quits below. */
call_process_exited = 0;
-#if defined(MSDOS) || defined(macintosh)
+#if defined(MSDOS) || defined(MAC_OS8)
/* MSDOS needs different cleanup information. */
record_unwind_protect (call_process_cleanup,
Fcons (make_number (fd[0]), build_string (tempfile)));
#else
record_unwind_protect (call_process_cleanup,
Fcons (make_number (fd[0]), make_number (pid)));
-#endif /* not MSDOS and not macintosh */
+#endif /* not MSDOS and not MAC_OS8 */
if (BUFFERP (buffer))
/* Define as `fork' if `vfork' does not work. */
#undef vfork
+/* Define if we should use the Carbon API on Mac OS X. */
+#undef HAVE_CARBON
+
+#ifdef HAVE_CARBON
+#define HAVE_WINDOW_SYSTEM
+#define HAVE_MOUSE
+#define HAVE_MENUS
+#endif
+
+/* Define if we have the session management (SM) library. */
+#undef HAVE_X_SM
+
/* Define to empty if the keyword `volatile' does not work. Warning: valid
code using `volatile' can become incorrect without. Disable with care. */
#undef volatile
#include "w32gui.h"
#endif
-#ifdef macintosh
+#ifdef MAC_OS
#include "macgui.h"
#endif
#include "w32term.h"
#endif /* HAVE_NTGUI */
-#ifdef macintosh
+#ifdef MAC_OS
#include "macterm.h"
-#endif /* macintosh */
+#endif /* MAC_OS */
/* Include systime.h after xterm.h to avoid double inclusion of time.h. */
}
#endif /* HAVE_NTGUI */
-#ifdef macintosh
+#ifdef MAC_OS
if (!inhibit_window_system)
{
Vwindow_system = intern ("mac");
adjust_frame_glyphs_initially ();
return;
}
-#endif /* macintosh */
+#endif /* MAC_OS */
/* If no window system has been specified, try to use the terminal. */
if (! isatty (0))
#include <unistd.h>
#endif
+/* Without this, sprintf on Mac OS Classic will produce wrong
+ result. */
+#ifdef MAC_OS8
+#include <stdio.h>
+#endif
+
#include <ctype.h>
#include "lisp.h"
run_time_remap (argv[0]);
#endif
+#ifdef MAC_OSX
+ if (!initialized)
+ unexec_init_emacs_zone ();
+#endif
+
sort_args (argc, argv);
argc = 0;
while (argv[argc]) argc++;
}
#endif /* NeXT */
+#ifdef MAC_OSX
+ /* Skip process serial number passed in the form -psn_x_y as
+ command-line argument. */
+ if (argc > skip_args + 1 && strncmp (argv[skip_args+1], "-psn_", 5) == 0)
+ skip_args++;
+#endif /* MAC_OSX */
+
#ifdef VMS
/* If -map specified, map the data file in. */
{
CANNOT_DUMP is defined. */
syms_of_keyboard ();
-#ifdef macintosh
+#ifdef MAC_OS8
/* init_window_once calls make_terminal_frame which on Mac OS
creates a full-fledge output_mac type frame. This does not
work correctly before syms_of_textprop, syms_of_macfns,
syms_of_ccl, syms_of_fontset, syms_of_xterm, syms_of_search,
- syms_of_frame, x_term_init, and init_keyboard have already
+ syms_of_frame, mac_initialize, and init_keyboard have already
been called. */
syms_of_textprop ();
syms_of_macfns ();
syms_of_search ();
syms_of_frame ();
- x_term_init ();
+ mac_initialize ();
init_keyboard ();
#endif
/* The basic levels of Lisp must come first. */
/* And data must come first of all
for the sake of symbols like error-message. */
-#ifndef macintosh
- /* Called before init_window_once for Mac OS. */
+#ifndef MAC_OS8
+ /* Called before init_window_once for Mac OS Classic. */
syms_of_data ();
#endif
syms_of_alloc ();
syms_of_casetab ();
syms_of_callproc ();
syms_of_category ();
-#ifndef macintosh
- /* Called before init_window_once for Mac OS. */
+#ifndef MAC_OS8
+ /* Called before init_window_once for Mac OS Classic. */
syms_of_ccl ();
#endif
syms_of_charset ();
syms_of_marker ();
syms_of_minibuf ();
syms_of_process ();
-#ifndef macintosh
- /* Called before init_window_once for Mac OS. */
+#ifndef MAC_OS8
+ /* Called before init_window_once for Mac OS Classic. */
syms_of_search ();
syms_of_frame ();
#endif
#ifdef HAVE_SOUND
syms_of_sound ();
#endif
-#ifndef macintosh
- /* Called before init_window_once for Mac OS. */
+#ifndef MAC_OS8
+ /* Called before init_window_once for Mac OS Classic. */
syms_of_textprop ();
#endif
syms_of_composite ();
#endif /* HAVE_X_WINDOWS */
#ifndef HAVE_NTGUI
-#ifndef macintosh
+#ifndef MAC_OS
+ /* Called before init_window_once for Mac OS Classic. */
syms_of_xmenu ();
#endif
#endif
syms_of_fontset ();
#endif /* HAVE_NTGUI */
+#ifdef HAVE_CARBON
+ syms_of_macterm ();
+ syms_of_macfns ();
+ syms_of_macmenu ();
+ syms_of_fontset ();
+#endif /* HAVE_CARBON */
+
#ifdef SYMS_SYSTEM
SYMS_SYSTEM;
#endif
#endif /* VMS */
init_display (); /* Determine terminal type. init_sys_modes uses results. */
}
-#ifndef macintosh
- /* Called before init_window_once for Mac OS. */
+#ifndef MAC_OS8
+ /* Called before init_window_once for Mac OS Classic. */
init_keyboard (); /* This too must precede init_sys_modes. */
#endif
#ifdef VMS
FONTSET_ID (Vdefault_fontset) = make_number (0);
FONTSET_NAME (Vdefault_fontset)
= build_string ("-*-*-*-*-*-*-*-*-*-*-*-*-fontset-default");
-#if defined (macintosh)
+#if defined (MAC_OS)
FONTSET_ASCII (Vdefault_fontset)
= Fcons (make_number (0),
- build_string ("-apple-monaco-medium-r-*--*-120-*-*-*-*-mac-roman"));
+ build_string ("-ETL-fixed-medium-r-*--*-160-*-*-*-*-iso8859-1"));
#elif defined (WINDOWSNT)
FONTSET_ASCII (Vdefault_fontset)
= Fcons (make_number (0),
#ifdef WINDOWSNT
#include "w32term.h"
#endif
-#ifdef macintosh
+#ifdef MAC_OS
#include "macterm.h"
#endif
#include "buffer.h"
f->output_method = output_termcap;
f->output_data.x = &tty_display;
#else
-#ifdef macintosh
+#ifdef MAC_OS8
make_mac_terminal_frame (f);
#else
f->output_data.x = &tty_display;
-#endif /* macintosh */
+#endif /* MAC_OS8 */
#endif /* WINDOWSNT */
#endif /* MSDOS */
abort ();
#else /* not MSDOS */
-#ifdef macintosh
+#ifdef MAC_OS
if (sf->output_method != output_mac)
error ("Not running on a Macintosh screen; cannot make a new Macintosh frame");
#else
return Qnil;
if (NILP (force) && !other_visible_frames (f)
-#ifdef macintosh
+#ifdef MAC_OS8
/* Terminal frame deleted before any other visible frames are
created. */
&& strcmp (XSTRING (f->name)->data, "F1") != 0
vertical_scroll_bar_right
};
-#if !defined(MSDOS) && !defined(WINDOWSNT) && !defined(macintosh)
+#if !defined(MSDOS) && !defined(WINDOWSNT) && !defined(MAC_OS)
#if !defined(HAVE_X_WINDOWS)
/* A structure describing a termcap frame display. */
extern struct x_output tty_display;
-#endif /* ! MSDOS && ! WINDOWSNT && ! macintosh */
+#endif /* ! MSDOS && ! WINDOWSNT && ! MAC_OS */
struct frame
{
/* Number of lines of menu bar. */
int menu_bar_lines;
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (macintosh)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS)
/* Nonzero means using a menu bar that comes from the X toolkit. */
int external_menu_bar;
#endif
#ifdef HAVE_NTGUI
#define FRAME_WINDOW_P(f) FRAME_W32_P (f)
#endif
-#ifdef macintosh
+#ifdef MAC_OS
#define FRAME_WINDOW_P(f) FRAME_MAC_P (f)
#endif
#ifndef FRAME_WINDOW_P
/* Nonzero if this frame should display a menu bar
in a way that does not use any text lines. */
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (macintosh)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS)
#define FRAME_EXTERNAL_MENU_BAR(f) (f)->external_menu_bar
#else
#define FRAME_EXTERNAL_MENU_BAR(f) 0
#include "w32term.h"
#endif /* HAVE_NTGUI */
-#ifdef macintosh
+#ifdef MAC_OS
#include "macterm.h"
#endif
#ifdef HAVE_WINDOW_SYSTEM
/* Make all keyboard buffers much bigger when using X windows. */
-#ifdef macintosh
-/* But not too big (local data > 32K error) if on macintosh. */
+#ifdef MAC_OS8
+/* But not too big (local data > 32K error) if on Mac OS Classic. */
#define KBD_BUFFER_SIZE 512
#else
#define KBD_BUFFER_SIZE 4096
abort ();
#endif
}
-#if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (macintosh)
+#if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (MAC_OS)
else if (event->kind == delete_window_event)
{
/* Make an event (delete-frame (FRAME)). */
XSETBUFFER (obj, current_buffer);
kbd_fetch_ptr = event + 1;
}
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (macintosh)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS)
else if (event->kind == menu_bar_activate_event)
{
kbd_fetch_ptr = event + 1;
}
#endif /* HAVE_MOUSE */
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (macintosh)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS)
case MENU_BAR_EVENT:
if (EQ (event->arg, event->frame_or_window))
/* This is the prefix key. We translate this to
--- /dev/null
+/* Machine description file for Apple Power Macintosh
+ Copyright (C) 2001 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+
+/* The following line tells the configuration script what sort of
+ operating system this machine is likely to run.
+ USUAL-OPSYS="darwin" */
+
+/* Define WORDS_BIG_ENDIAN iff lowest-numbered byte in a word
+ is the most significant byte. */
+
+#define WORDS_BIG_ENDIAN
+
+/* Define NO_ARG_ARRAY if you cannot take the address of the first of a
+ * group of arguments and treat it as an array of the arguments. */
+
+#define NO_ARG_ARRAY
+
+/* Define WORD_MACHINE if addresses and such have
+ * to be corrected before they can be used as byte counts. */
+
+/* #define WORD_MACHINE */
+
+/* Now define a symbol for the cpu type, if your compiler
+ does not define it automatically:
+ Ones defined so far include vax, m68000, ns16000, pyramid,
+ orion, tahoe, APOLLO and many others */
+
+/* Use type int rather than a union, to represent Lisp_Object */
+/* This is desirable for most machines. */
+
+#define NO_UNION_TYPE
+
+/* Define EXPLICIT_SIGN_EXTEND if XINT must explicitly sign-extend
+ the 24-bit bit field into an int. In other words, if bit fields
+ are always unsigned.
+
+ If you use NO_UNION_TYPE, this flag does not matter. */
+
+/* #define EXPLICIT_SIGN_EXTEND */
+
+/* Data type of load average, as read out of kmem. */
+
+#define LOAD_AVE_TYPE long
+
+/* Convert that into an integer that is 100 for a load average of 1.0 */
+
+#define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / FSCALE)
+
+/* Define CANNOT_DUMP on machines where unexec does not work.
+ Then the function dump-emacs will not be defined
+ and temacs will do (load "loadup") automatically unless told otherwise. */
+
+/* #define CANNOT_DUMP */
+
+/* Define VIRT_ADDR_VARIES if the virtual addresses of
+ pure and impure space as loaded can vary, and even their
+ relative order cannot be relied on.
+
+ Otherwise Emacs assumes that text space precedes data space,
+ numerically. */
+
+/* #define VIRT_ADDR_VARIES * */
+
+/* Define C_ALLOCA if this machine does not support a true alloca
+ and the one written in C should be used instead.
+ Define HAVE_ALLOCA to say that the system provides a properly
+ working alloca function and it should be used.
+ Define neither one if an assembler-language alloca
+ in the file alloca.s should be used. */
+
+/* #define C_ALLOCA */
+/* #define HAVE_ALLOCA */
+
+/* Define NO_REMAP if memory segmentation makes it not work well
+ to change the boundary between the text section and data section
+ when Emacs is dumped. If you define this, the preloaded Lisp
+ code will not be sharable; but that's better than failing completely. */
+
+#define NO_REMAP
+
+/* Some really obscure 4.2-based systems (like Sequent DYNIX)
+ * do not support asynchronous I/O (using SIGIO) on sockets,
+ * even though it works fine on tty's. If you have one of
+ * these systems, define the following, and then use it in
+ * config.h (or elsewhere) to decide when (not) to use SIGIO.
+ *
+ * You'd think this would go in an operating-system description file,
+ * but since it only occurs on some, but not all, BSD systems, the
+ * reasonable place to select for it is in the machine description
+ * file.
+ */
+
+/* #define NO_SOCK_SIGIO */
+
+
+/* After adding support for a new system, modify the large case
+ statement in the `configure' script to recognize reasonable
+ configuration names, and add a description of the system to
+ `etc/MACHINES'.
+
+ If you've just fixed a problem in an existing configuration file,
+ you should also check `etc/MACHINES' to make sure its descriptions
+ of known problems in that configuration should be updated. */
--- /dev/null
+/* Unix emulation routines for GNU Emacs on the Mac OS.
+ Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Contributed by Andrew Choi (akochoi@mac.com). */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <errno.h>
+#include <utime.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <pwd.h>
+#include <sys/param.h>
+#if __MWERKS__
+#include <unistd.h>
+#endif
+
+#ifdef MAC_OSX
+#undef mktime
+#undef DEBUG
+#undef free
+#undef malloc
+#undef realloc
+#include <Carbon/Carbon.h>
+#undef free
+#define free unexec_free
+#undef malloc
+#define malloc unexec_malloc
+#undef realloc
+#define realloc unexec_realloc
+#else /* not MAC_OSX */
+#include <Files.h>
+#include <MacTypes.h>
+#include <TextUtils.h>
+#include <Folders.h>
+#include <Resources.h>
+#include <Aliases.h>
+#include <FixMath.h>
+#include <Timer.h>
+#include <OSA.h>
+#include <AppleScript.h>
+#include <Scrap.h>
+#endif /* not MAC_OSX */
+
+#include "lisp.h"
+#include "process.h"
+#include "sysselect.h"
+#include "systime.h"
+
+Lisp_Object QCLIPBOARD;
+
+/* An instance of the AppleScript component. */
+static ComponentInstance as_scripting_component;
+/* The single script context used for all script executions. */
+static OSAID as_script_context;
+
+
+/* When converting from Mac to Unix pathnames, /'s in folder names are
+ converted to :'s. This function, used in copying folder names,
+ performs a strncat and converts all character a to b in the copy of
+ the string s2 appended to the end of s1. */
+
+void
+string_cat_and_replace (char *s1, const char *s2, int n, char a, char b)
+{
+ int l1 = strlen (s1);
+ int l2 = strlen (s2);
+ char *p = s1 + l1;
+ int i;
+
+ strncat (s1, s2, n);
+ for (i = 0; i < l2; i++)
+ {
+ if (*p == a)
+ *p = b;
+ p++;
+ }
+}
+
+
+/* Convert a Mac pathname to Posix form. A Mac full pathname is one
+ that does not begin with a ':' and contains at least one ':'. A Mac
+ full pathname causes an '/' to be prepended to the Posix pathname.
+ The algorithm for the rest of the pathname is as follows:
+ For each segment between two ':',
+ if it is non-null, copy as is and then add a '/' at the end,
+ otherwise, insert a "../" into the Posix pathname.
+ Returns 1 if successful; 0 if fails. */
+
+int
+mac_to_posix_pathname (const char *mfn, char *ufn, int ufnbuflen)
+{
+ const char *p, *q, *pe;
+
+ strcpy (ufn, "");
+
+ if (*mfn == '\0')
+ return 1;
+
+ p = strchr (mfn, ':');
+ if (p != 0 && p != mfn) /* full pathname */
+ strcat (ufn, "/");
+
+ p = mfn;
+ if (*p == ':')
+ p++;
+
+ pe = mfn + strlen (mfn);
+ while (p < pe)
+ {
+ q = strchr (p, ':');
+ if (q)
+ {
+ if (q == p)
+ { /* two consecutive ':' */
+ if (strlen (ufn) + 3 >= ufnbuflen)
+ return 0;
+ strcat (ufn, "../");
+ }
+ else
+ {
+ if (strlen (ufn) + (q - p) + 1 >= ufnbuflen)
+ return 0;
+ string_cat_and_replace (ufn, p, q - p, '/', ':');
+ strcat (ufn, "/");
+ }
+ p = q + 1;
+ }
+ else
+ {
+ if (strlen (ufn) + (pe - p) >= ufnbuflen)
+ return 0;
+ string_cat_and_replace (ufn, p, pe - p, '/', ':');
+ /* no separator for last one */
+ p = pe;
+ }
+ }
+
+ return 1;
+}
+
+
+extern char *get_temp_dir_name ();
+
+
+/* Convert a Posix pathname to Mac form. Approximately reverse of the
+ above in algorithm. */
+
+int
+posix_to_mac_pathname (const char *ufn, char *mfn, int mfnbuflen)
+{
+ const char *p, *q, *pe;
+ char expanded_pathname[MAXPATHLEN+1];
+
+ strcpy (mfn, "");
+
+ if (*ufn == '\0')
+ return 1;
+
+ p = ufn;
+
+ /* Check for and handle volume names. Last comparison: strangely
+ somewhere "/.emacs" is passed. A temporary fix for now. */
+ if (*p == '/' && strchr (p+1, '/') == NULL && strcmp (p, "/.emacs") != 0)
+ {
+ if (strlen (p) + 1 > mfnbuflen)
+ return 0;
+ strcpy (mfn, p+1);
+ strcat (mfn, ":");
+ return 1;
+ }
+
+ /* expand to emacs dir found by init_emacs_passwd_dir */
+ if (strncmp (p, "~emacs/", 7) == 0)
+ {
+ struct passwd *pw = getpwnam ("emacs");
+ p += 7;
+ if (strlen (pw->pw_dir) + strlen (p) > MAXPATHLEN)
+ return 0;
+ strcpy (expanded_pathname, pw->pw_dir);
+ strcat (expanded_pathname, p);
+ p = expanded_pathname;
+ /* now p points to the pathname with emacs dir prefix */
+ }
+ else if (strncmp (p, "/tmp/", 5) == 0)
+ {
+ char *t = get_temp_dir_name ();
+ p += 5;
+ if (strlen (t) + strlen (p) > MAXPATHLEN)
+ return 0;
+ strcpy (expanded_pathname, t);
+ strcat (expanded_pathname, p);
+ p = expanded_pathname;
+ /* now p points to the pathname with emacs dir prefix */
+ }
+ else if (*p != '/') /* relative pathname */
+ strcat (mfn, ":");
+
+ if (*p == '/')
+ p++;
+
+ pe = p + strlen (p);
+ while (p < pe)
+ {
+ q = strchr (p, '/');
+ if (q)
+ {
+ if (q - p == 2 && *p == '.' && *(p+1) == '.')
+ {
+ if (strlen (mfn) + 1 >= mfnbuflen)
+ return 0;
+ strcat (mfn, ":");
+ }
+ else
+ {
+ if (strlen (mfn) + (q - p) + 1 >= mfnbuflen)
+ return 0;
+ string_cat_and_replace (mfn, p, q - p, ':', '/');
+ strcat (mfn, ":");
+ }
+ p = q + 1;
+ }
+ else
+ {
+ if (strlen (mfn) + (pe - p) >= mfnbuflen)
+ return 0;
+ string_cat_and_replace (mfn, p, pe - p, ':', '/');
+ p = pe;
+ }
+ }
+
+ return 1;
+}
+
+#ifndef MAC_OSX
+
+/* The following functions with "sys_" prefix are stubs to Unix
+ functions that have already been implemented by CW or MPW. The
+ calls to them in Emacs source course are #define'd to call the sys_
+ versions by the header files s-mac.h. In these stubs pathnames are
+ converted between their Unix and Mac forms. */
+
+
+/* Unix epoch is Jan 1, 1970 while Mac epoch is Jan 1, 1904: 66 years
+ + 17 leap days. These are for adjusting time values returned by
+ MacOS Toolbox functions. */
+
+#define MAC_UNIX_EPOCH_DIFF ((365L * 66 + 17) * 24 * 60 * 60)
+
+#ifdef __MWERKS__
+#if __MSL__ < 0x6000
+/* CW Pro 5 epoch is Jan 1, 1900 (aaarghhhhh!); remember, 1900 is not
+ a leap year! This is for adjusting time_t values returned by MSL
+ functions. */
+#define CW_OR_MPW_UNIX_EPOCH_DIFF ((365L * 70 + 17) * 24 * 60 * 60)
+#else /* __MSL__ >= 0x6000 */
+/* CW changes Pro 6 to follow Unix! */
+#define CW_OR_MPW_UNIX_EPOCH_DIFF ((365L * 66 + 17) * 24 * 60 * 60)
+#endif /* __MSL__ >= 0x6000 */
+#elif __MRC__
+/* MPW library functions follow Unix (confused?). */
+#define CW_OR_MPW_UNIX_EPOCH_DIFF ((365L * 66 + 17) * 24 * 60 * 60)
+#else /* not __MRC__ */
+You lose!!!
+#endif /* not __MRC__ */
+
+
+/* Define our own stat function for both MrC and CW. The reason for
+ doing this: "stat" is both the name of a struct and function name:
+ can't use the same trick like that for sys_open, sys_close, etc. to
+ redirect Emacs's calls to our own version that converts Unix style
+ filenames to Mac style filename because all sorts of compilation
+ errors will be generated if stat is #define'd to be sys_stat. */
+
+int
+stat_noalias (const char *path, struct stat *buf)
+{
+ char mac_pathname[MAXPATHLEN+1];
+ CInfoPBRec cipb;
+
+ if (posix_to_mac_pathname (path, mac_pathname, MAXPATHLEN+1) == 0)
+ return -1;
+
+ c2pstr (mac_pathname);
+ cipb.hFileInfo.ioNamePtr = mac_pathname;
+ cipb.hFileInfo.ioVRefNum = 0;
+ cipb.hFileInfo.ioDirID = 0;
+ cipb.hFileInfo.ioFDirIndex = 0;
+ /* set to 0 to get information about specific dir or file */
+
+ errno = PBGetCatInfo (&cipb, false);
+ if (errno == -43) /* -43: fnfErr defined in Errors.h */
+ errno = ENOENT;
+ if (errno != noErr)
+ return -1;
+
+ if (cipb.hFileInfo.ioFlAttrib & 0x10) /* bit 4 = 1 for directories */
+ {
+ buf->st_mode = S_IFDIR | S_IREAD | S_IEXEC;
+
+ if (!(cipb.hFileInfo.ioFlAttrib & 0x1))
+ buf->st_mode |= S_IWRITE; /* bit 1 = 1 for locked files/directories */
+ buf->st_ino = cipb.dirInfo.ioDrDirID;
+ buf->st_dev = cipb.dirInfo.ioVRefNum;
+ buf->st_size = cipb.dirInfo.ioDrNmFls;
+ /* size of dir = number of files and dirs */
+ buf->st_atime
+ = buf->st_mtime
+ = cipb.dirInfo.ioDrMdDat - MAC_UNIX_EPOCH_DIFF;
+ buf->st_ctime = cipb.dirInfo.ioDrCrDat - MAC_UNIX_EPOCH_DIFF;
+ }
+ else
+ {
+ buf->st_mode = S_IFREG | S_IREAD;
+ if (!(cipb.hFileInfo.ioFlAttrib & 0x1))
+ buf->st_mode |= S_IWRITE; /* bit 1 = 1 for locked files/directories */
+ if (cipb.hFileInfo.ioFlFndrInfo.fdType == 'APPL')
+ buf->st_mode |= S_IEXEC;
+ buf->st_ino = cipb.hFileInfo.ioDirID;
+ buf->st_dev = cipb.hFileInfo.ioVRefNum;
+ buf->st_size = cipb.hFileInfo.ioFlLgLen;
+ buf->st_atime
+ = buf->st_mtime
+ = cipb.hFileInfo.ioFlMdDat - MAC_UNIX_EPOCH_DIFF;
+ buf->st_ctime = cipb.hFileInfo.ioFlCrDat - MAC_UNIX_EPOCH_DIFF;
+ }
+
+ if (cipb.hFileInfo.ioFlFndrInfo.fdFlags & 0x8000)
+ {
+ /* identify alias files as symlinks */
+ buf->st_mode &= ~S_IFREG;
+ buf->st_mode |= S_IFLNK;
+ }
+
+ buf->st_nlink = 1;
+ buf->st_uid = getuid ();
+ buf->st_gid = getgid ();
+ buf->st_rdev = 0;
+
+ return 0;
+}
+
+
+int
+lstat (const char *path, struct stat *buf)
+{
+ int result;
+ char true_pathname[MAXPATHLEN+1];
+
+ /* Try looking for the file without resolving aliases first. */
+ if ((result = stat_noalias (path, buf)) >= 0)
+ return result;
+
+ if (find_true_pathname (path, true_pathname, MAXPATHLEN+1) == -1)
+ return -1;
+
+ return stat_noalias (true_pathname, buf);
+}
+
+
+int
+stat (const char *path, struct stat *sb)
+{
+ int result;
+ char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];
+ int len;
+
+ if ((result = stat_noalias (path, sb)) >= 0 &&
+ ! (sb->st_mode & S_IFLNK))
+ return result;
+
+ if (find_true_pathname (path, true_pathname, MAXPATHLEN+1) == -1)
+ return -1;
+
+ len = readlink (true_pathname, fully_resolved_name, MAXPATHLEN);
+ if (len > -1)
+ {
+ fully_resolved_name[len] = '\0';
+ /* in fact our readlink terminates strings */
+ return lstat (fully_resolved_name, sb);
+ }
+ else
+ return lstat (true_pathname, sb);
+}
+
+
+#if __MRC__
+/* CW defines fstat in stat.mac.c while MPW does not provide this
+ function. Without the information of how to get from a file
+ descriptor in MPW StdCLib to a Mac OS file spec, it should be hard
+ to implement this function. Fortunately, there is only one place
+ where this function is called in our configuration: in fileio.c,
+ where only the st_dev and st_ino fields are used to determine
+ whether two fildes point to different i-nodes to prevent copying
+ a file onto itself equal. What we have here probably needs
+ improvement. */
+
+int
+fstat (int fildes, struct stat *buf)
+{
+ buf->st_dev = 0;
+ buf->st_ino = fildes;
+ buf->st_mode = S_IFREG; /* added by T.I. for the copy-file */
+ return 0; /* success */
+}
+#endif /* __MRC__ */
+
+
+int
+mkdir (const char *dirname, int mode)
+{
+#pragma unused(mode)
+
+ HFileParam hfpb;
+ char true_pathname[MAXPATHLEN+1], mac_pathname[MAXPATHLEN+1];
+
+ if (find_true_pathname (dirname, true_pathname, MAXPATHLEN+1) == -1)
+ return -1;
+
+ if (posix_to_mac_pathname (true_pathname, mac_pathname, MAXPATHLEN+1) == 0)
+ return -1;
+
+ c2pstr (mac_pathname);
+ hfpb.ioNamePtr = mac_pathname;
+ hfpb.ioVRefNum = 0; /* ignored unless name is invalid */
+ hfpb.ioDirID = 0; /* parent is the root */
+
+ errno = PBDirCreate ((HParmBlkPtr) &hfpb, false);
+ /* just return the Mac OSErr code for now */
+ return errno == noErr ? 0 : -1;
+}
+
+
+#undef rmdir
+sys_rmdir (const char *dirname)
+{
+ HFileParam hfpb;
+ char mac_pathname[MAXPATHLEN+1];
+
+ if (posix_to_mac_pathname (dirname, mac_pathname, MAXPATHLEN+1) == 0)
+ return -1;
+
+ c2pstr (mac_pathname);
+ hfpb.ioNamePtr = mac_pathname;
+ hfpb.ioVRefNum = 0; /* ignored unless name is invalid */
+ hfpb.ioDirID = 0; /* parent is the root */
+
+ errno = PBHDelete ((HParmBlkPtr) &hfpb, false);
+ return errno == noErr ? 0 : -1;
+}
+
+
+#ifdef __MRC__
+/* No implementation yet. */
+int
+execvp (const char *path, ...)
+{
+ return -1;
+}
+#endif /* __MRC__ */
+
+
+int
+utime (const char *path, const struct utimbuf *times)
+{
+ char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];
+ int len;
+ char mac_pathname[MAXPATHLEN+1];
+ CInfoPBRec cipb;
+
+ if (find_true_pathname (path, true_pathname, MAXPATHLEN+1) == -1)
+ return -1;
+
+ len = readlink (true_pathname, fully_resolved_name, MAXPATHLEN);
+ if (len > -1)
+ fully_resolved_name[len] = '\0';
+ else
+ strcpy (fully_resolved_name, true_pathname);
+
+ if (!posix_to_mac_pathname (fully_resolved_name, mac_pathname, MAXPATHLEN+1))
+ return -1;
+
+ c2pstr (mac_pathname);
+ cipb.hFileInfo.ioNamePtr = mac_pathname;
+ cipb.hFileInfo.ioVRefNum = 0;
+ cipb.hFileInfo.ioDirID = 0;
+ cipb.hFileInfo.ioFDirIndex = 0;
+ /* set to 0 to get information about specific dir or file */
+
+ errno = PBGetCatInfo (&cipb, false);
+ if (errno != noErr)
+ return -1;
+
+ if (cipb.hFileInfo.ioFlAttrib & 0x10) /* bit 4 = 1 for directories */
+ {
+ if (times)
+ cipb.dirInfo.ioDrMdDat = times->modtime + MAC_UNIX_EPOCH_DIFF;
+ else
+ GetDateTime (&cipb.dirInfo.ioDrMdDat);
+ }
+ else
+ {
+ if (times)
+ cipb.hFileInfo.ioFlMdDat = times->modtime + MAC_UNIX_EPOCH_DIFF;
+ else
+ GetDateTime (&cipb.hFileInfo.ioFlMdDat);
+ }
+
+ errno = PBSetCatInfo (&cipb, false);
+ return errno == noErr ? 0 : -1;
+}
+
+
+#ifndef F_OK
+#define F_OK 0
+#endif
+#ifndef X_OK
+#define X_OK 1
+#endif
+#ifndef W_OK
+#define W_OK 2
+#endif
+
+/* Like stat, but test for access mode in hfpb.ioFlAttrib */
+int
+access (const char *path, int mode)
+{
+ char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];
+ int len;
+ char mac_pathname[MAXPATHLEN+1];
+ CInfoPBRec cipb;
+
+ if (find_true_pathname (path, true_pathname, MAXPATHLEN+1) == -1)
+ return -1;
+
+ len = readlink (true_pathname, fully_resolved_name, MAXPATHLEN);
+ if (len > -1)
+ fully_resolved_name[len] = '\0';
+ else
+ strcpy (fully_resolved_name, true_pathname);
+
+ if (!posix_to_mac_pathname (fully_resolved_name, mac_pathname, MAXPATHLEN+1))
+ return -1;
+
+ c2pstr (mac_pathname);
+ cipb.hFileInfo.ioNamePtr = mac_pathname;
+ cipb.hFileInfo.ioVRefNum = 0;
+ cipb.hFileInfo.ioDirID = 0;
+ cipb.hFileInfo.ioFDirIndex = 0;
+ /* set to 0 to get information about specific dir or file */
+
+ errno = PBGetCatInfo (&cipb, false);
+ if (errno != noErr)
+ return -1;
+
+ if (mode == F_OK) /* got this far, file exists */
+ return 0;
+
+ if (mode & X_OK)
+ if (cipb.hFileInfo.ioFlAttrib & 0x10) /* path refers to a directory */
+ return 0;
+ else
+ {
+ if (cipb.hFileInfo.ioFlFndrInfo.fdType == 'APPL')
+ return 0;
+ else
+ return -1;
+ }
+
+ if (mode & W_OK)
+ return (cipb.hFileInfo.ioFlAttrib & 0x1) ? -1 : 0;
+ /* don't allow if lock bit is on */
+
+ return -1;
+}
+
+
+#define DEV_NULL_FD 0x10000
+
+#undef open
+int
+sys_open (const char *path, int oflag)
+{
+ char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];
+ int len;
+ char mac_pathname[MAXPATHLEN+1];
+
+ if (strcmp (path, "/dev/null") == 0)
+ return DEV_NULL_FD; /* some bogus fd to be ignored in write */
+
+ if (find_true_pathname (path, true_pathname, MAXPATHLEN+1) == -1)
+ return -1;
+
+ len = readlink (true_pathname, fully_resolved_name, MAXPATHLEN);
+ if (len > -1)
+ fully_resolved_name[len] = '\0';
+ else
+ strcpy (fully_resolved_name, true_pathname);
+
+ if (!posix_to_mac_pathname (fully_resolved_name, mac_pathname, MAXPATHLEN+1))
+ return -1;
+ else
+ {
+#ifdef __MRC__
+ int res = open (mac_pathname, oflag);
+ /* if (oflag == O_WRONLY || oflag == O_RDWR) */
+ if (oflag & O_CREAT)
+ fsetfileinfo (mac_pathname, 'EMAx', 'TEXT');
+ return res;
+#else /* not __MRC__ */
+ return open (mac_pathname, oflag);
+#endif /* not __MRC__ */
+ }
+}
+
+
+#undef creat
+int
+sys_creat (const char *path, mode_t mode)
+{
+ char true_pathname[MAXPATHLEN+1];
+ int len;
+ char mac_pathname[MAXPATHLEN+1];
+
+ if (find_true_pathname (path, true_pathname, MAXPATHLEN+1) == -1)
+ return -1;
+
+ if (!posix_to_mac_pathname (true_pathname, mac_pathname, MAXPATHLEN+1))
+ return -1;
+ else
+ {
+#ifdef __MRC__
+ int result = creat (mac_pathname);
+ fsetfileinfo (mac_pathname, 'EMAx', 'TEXT');
+ return result;
+#else /* not __MRC__ */
+ return creat (mac_pathname, mode);
+#endif /* not __MRC__ */
+ }
+}
+
+
+#undef unlink
+int
+sys_unlink (const char *path)
+{
+ char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];
+ int len;
+ char mac_pathname[MAXPATHLEN+1];
+
+ if (find_true_pathname (path, true_pathname, MAXPATHLEN+1) == -1)
+ return -1;
+
+ len = readlink (true_pathname, fully_resolved_name, MAXPATHLEN);
+ if (len > -1)
+ fully_resolved_name[len] = '\0';
+ else
+ strcpy (fully_resolved_name, true_pathname);
+
+ if (!posix_to_mac_pathname (fully_resolved_name, mac_pathname, MAXPATHLEN+1))
+ return -1;
+ else
+ return unlink (mac_pathname);
+}
+
+
+#undef read
+int
+sys_read (int fildes, char *buf, int count)
+{
+ if (fildes == 0) /* this should not be used for console input */
+ return -1;
+ else
+#if __MSL__ >= 0x6000
+ return _read (fildes, buf, count);
+#else
+ return read (fildes, buf, count);
+#endif
+}
+
+
+#undef write
+int
+sys_write (int fildes, const char *buf, int count)
+{
+ if (fildes == DEV_NULL_FD)
+ return count;
+ else
+#if __MSL__ >= 0x6000
+ return _write (fildes, buf, count);
+#else
+ return write (fildes, buf, count);
+#endif
+}
+
+
+#undef rename
+int
+sys_rename (const char * old_name, const char * new_name)
+{
+ char true_old_pathname[MAXPATHLEN+1], true_new_pathname[MAXPATHLEN+1];
+ char fully_resolved_old_name[MAXPATHLEN+1];
+ int len;
+ char mac_old_name[MAXPATHLEN+1], mac_new_name[MAXPATHLEN+1];
+
+ if (find_true_pathname (old_name, true_old_pathname, MAXPATHLEN+1) == -1)
+ return -1;
+
+ len = readlink (true_old_pathname, fully_resolved_old_name, MAXPATHLEN);
+ if (len > -1)
+ fully_resolved_old_name[len] = '\0';
+ else
+ strcpy (fully_resolved_old_name, true_old_pathname);
+
+ if (find_true_pathname (new_name, true_new_pathname, MAXPATHLEN+1) == -1)
+ return -1;
+
+ if (strcmp (fully_resolved_old_name, true_new_pathname) == 0)
+ return 0;
+
+ if (!posix_to_mac_pathname (fully_resolved_old_name,
+ mac_old_name,
+ MAXPATHLEN+1))
+ return -1;
+
+ if (!posix_to_mac_pathname(true_new_pathname, mac_new_name, MAXPATHLEN+1))
+ return -1;
+
+ /* If a file with new_name already exists, rename deletes the old
+ file in Unix. CW version fails in these situation. So we add a
+ call to unlink here. */
+ (void) unlink (mac_new_name);
+
+ return rename (mac_old_name, mac_new_name);
+}
+
+
+#undef fopen
+extern FILE *fopen (const char *name, const char *mode);
+FILE *
+sys_fopen (const char *name, const char *mode)
+{
+ char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];
+ int len;
+ char mac_pathname[MAXPATHLEN+1];
+
+ if (find_true_pathname (name, true_pathname, MAXPATHLEN+1) == -1)
+ return 0;
+
+ len = readlink (true_pathname, fully_resolved_name, MAXPATHLEN);
+ if (len > -1)
+ fully_resolved_name[len] = '\0';
+ else
+ strcpy (fully_resolved_name, true_pathname);
+
+ if (!posix_to_mac_pathname (fully_resolved_name, mac_pathname, MAXPATHLEN+1))
+ return 0;
+ else
+ {
+#ifdef __MRC__
+ if (mode[0] == 'w' || mode[0] == 'a')
+ fsetfileinfo (mac_pathname, 'EMAx', 'TEXT');
+#endif /* not __MRC__ */
+ return fopen (mac_pathname, mode);
+ }
+}
+
+
+#include <Events.h>
+
+long target_ticks = 0;
+
+#ifdef __MRC__
+__sigfun alarm_signal_func = (__sigfun) 0;
+#elif __MWERKS__
+__signal_func_ptr alarm_signal_func = (__signal_func_ptr) 0;
+#else /* not __MRC__ and not __MWERKS__ */
+You lose!!!
+#endif /* not __MRC__ and not __MWERKS__ */
+
+
+/* These functions simulate SIG_ALRM. The stub for function signal
+ stores the signal handler function in alarm_signal_func if a
+ SIG_ALRM is encountered. check_alarm is called in XTread_socket,
+ which emacs calls periodically. A pending alarm is represented by
+ a non-zero target_ticks value. check_alarm calls the handler
+ function pointed to by alarm_signal_func if one has been set up and
+ an alarm is pending. */
+
+void
+check_alarm ()
+{
+ if (target_ticks && TickCount () > target_ticks)
+ {
+ target_ticks = 0;
+ if (alarm_signal_func)
+ (*alarm_signal_func)(SIGALRM);
+ }
+}
+
+
+int
+select (n, rfds, wfds, efds, timeout)
+ int n;
+ SELECT_TYPE *rfds;
+ SELECT_TYPE *wfds;
+ SELECT_TYPE *efds;
+ struct timeval *timeout;
+{
+#ifdef TARGET_API_MAC_CARBON
+ return 1;
+#else /* not TARGET_API_MAC_CARBON */
+ EMACS_TIME end_time, now;
+ EventRecord e;
+
+ /* Can only handle wait for keyboard input. */
+ if (n > 1 || wfds || efds)
+ return -1;
+
+ EMACS_GET_TIME (end_time);
+ EMACS_ADD_TIME (end_time, end_time, *timeout);
+
+ do
+ {
+ /* Also return true if an event other than a keyDown has
+ occurred. This causes kbd_buffer_get_event in keyboard.c to
+ call read_avail_input which in turn calls XTread_socket to
+ poll for these events. Otherwise these never get processed
+ except but a very slow poll timer. */
+ if (FD_ISSET (0, rfds) && EventAvail (everyEvent, &e))
+ return 1;
+
+ /* Also check movement of the mouse. */
+ {
+ Point mouse_pos;
+ static Point old_mouse_pos = {-1, -1};
+
+ GetMouse (&mouse_pos);
+ if (!EqualPt (mouse_pos, old_mouse_pos))
+ {
+ old_mouse_pos = mouse_pos;
+ return 1;
+ }
+ }
+
+ WaitNextEvent (0, &e, 1UL, NULL); /* Accept no event; wait 1
+ tic. by T.I. */
+
+ EMACS_GET_TIME (now);
+ EMACS_SUB_TIME (now, end_time, now);
+ }
+ while (!EMACS_TIME_NEG_P (now));
+
+ return 0;
+#endif /* not TARGET_API_MAC_CARBON */
+}
+
+
+/* Called in sys_select to wait for an alarm signal to arrive. */
+
+int
+pause ()
+{
+ EventRecord e;
+ unsigned long tick;
+
+ if (!target_ticks) /* no alarm pending */
+ return -1;
+
+ if ((tick = TickCount ()) < target_ticks)
+ WaitNextEvent (0, &e, target_ticks - tick, NULL); /* Accept no event;
+ just wait. by T.I. */
+
+ target_ticks = 0;
+ if (alarm_signal_func)
+ (*alarm_signal_func)(SIGALRM);
+
+ return 0;
+}
+
+
+int
+alarm (int seconds)
+{
+ long remaining = target_ticks ? (TickCount () - target_ticks) / 60 : 0;
+
+ target_ticks = seconds ? TickCount () + 60 * seconds : 0;
+
+ return (remaining < 0) ? 0 : (unsigned int) remaining;
+}
+
+
+#undef signal
+#ifdef __MRC__
+extern __sigfun signal (int signal, __sigfun signal_func);
+__sigfun
+sys_signal (int signal_num, __sigfun signal_func)
+#elif __MWERKS__
+extern __signal_func_ptr signal (int signal, __signal_func_ptr signal_func);
+__signal_func_ptr
+sys_signal (int signal_num, __signal_func_ptr signal_func)
+#else /* not __MRC__ and not __MWERKS__ */
+ You lose!!!
+#endif /* not __MRC__ and not __MWERKS__ */
+{
+ if (signal_num != SIGALRM)
+ return signal (signal_num, signal_func);
+ else
+ {
+#ifdef __MRC__
+ __sigfun old_signal_func;
+#elif __MWERKS__
+ __signal_func_ptr old_signal_func;
+#else
+ You lose!!!
+#endif
+ old_signal_func = alarm_signal_func;
+ alarm_signal_func = signal_func;
+ return old_signal_func;
+ }
+}
+
+
+/* gettimeofday should return the amount of time (in a timeval
+ structure) since midnight today. The toolbox function Microseconds
+ returns the number of microseconds (in a UnsignedWide value) since
+ the machine was booted. Also making this complicated is WideAdd,
+ WideSubtract, etc. take wide values. */
+
+int
+gettimeofday (tp)
+ struct timeval *tp;
+{
+ static inited = 0;
+ static wide wall_clock_at_epoch, clicks_at_epoch;
+ UnsignedWide uw_microseconds;
+ wide w_microseconds;
+ time_t sys_time (time_t *);
+
+ /* If this function is called for the first time, record the number
+ of seconds since midnight and the number of microseconds since
+ boot at the time of this first call. */
+ if (!inited)
+ {
+ time_t systime;
+ inited = 1;
+ systime = sys_time (NULL);
+ /* Store microseconds since midnight in wall_clock_at_epoch. */
+ WideMultiply (systime, 1000000L, &wall_clock_at_epoch);
+ Microseconds (&uw_microseconds);
+ /* Store microseconds since boot in clicks_at_epoch. */
+ clicks_at_epoch.hi = uw_microseconds.hi;
+ clicks_at_epoch.lo = uw_microseconds.lo;
+ }
+
+ /* Get time since boot */
+ Microseconds (&uw_microseconds);
+
+ /* Convert to time since midnight*/
+ w_microseconds.hi = uw_microseconds.hi;
+ w_microseconds.lo = uw_microseconds.lo;
+ WideSubtract (&w_microseconds, &clicks_at_epoch);
+ WideAdd (&w_microseconds, &wall_clock_at_epoch);
+ tp->tv_sec = WideDivide (&w_microseconds, 1000000L, &tp->tv_usec);
+
+ return 0;
+}
+
+
+#ifdef __MRC__
+unsigned int
+sleep (unsigned int seconds)
+{
+ unsigned long time_up;
+ EventRecord e;
+
+ time_up = TickCount () + seconds * 60;
+ while (TickCount () < time_up)
+ {
+ /* Accept no event; just wait. by T.I. */
+ WaitNextEvent (0, &e, 30, NULL);
+ }
+
+ return (0);
+}
+#endif /* __MRC__ */
+
+
+/* The time functions adjust time values according to the difference
+ between the Unix and CW epoches. */
+
+#undef gmtime
+extern struct tm *gmtime (const time_t *);
+struct tm *
+sys_gmtime (const time_t *timer)
+{
+ time_t unix_time = *timer + CW_OR_MPW_UNIX_EPOCH_DIFF;
+
+ return gmtime (&unix_time);
+}
+
+
+#undef localtime
+extern struct tm *localtime (const time_t *);
+struct tm *
+sys_localtime (const time_t *timer)
+{
+#if __MSL__ >= 0x6000
+ time_t unix_time = *timer;
+#else
+ time_t unix_time = *timer + CW_OR_MPW_UNIX_EPOCH_DIFF;
+#endif
+
+ return localtime (&unix_time);
+}
+
+
+#undef ctime
+extern char *ctime (const time_t *);
+char *
+sys_ctime (const time_t *timer)
+{
+#if __MSL__ >= 0x6000
+ time_t unix_time = *timer;
+#else
+ time_t unix_time = *timer + CW_OR_MPW_UNIX_EPOCH_DIFF;
+#endif
+
+ return ctime (&unix_time);
+}
+
+
+#undef time
+extern time_t time (time_t *);
+time_t
+sys_time (time_t *timer)
+{
+#if __MSL__ >= 0x6000
+ time_t mac_time = time (NULL);
+#else
+ time_t mac_time = time (NULL) - CW_OR_MPW_UNIX_EPOCH_DIFF;
+#endif
+
+ if (timer)
+ *timer = mac_time;
+
+ return mac_time;
+}
+
+
+/* MPW strftime broken for "%p" format */
+#ifdef __MRC__
+#undef strftime
+#include <time.h>
+size_t
+sys_strftime (char * s, size_t maxsize, const char * format,
+ const struct tm * timeptr)
+{
+ if (strcmp (format, "%p") == 0)
+ {
+ if (maxsize < 3)
+ return 0;
+ if (timeptr->tm_hour < 12)
+ {
+ strcpy (s, "AM");
+ return 2;
+ }
+ else
+ {
+ strcpy (s, "PM");
+ return 2;
+ }
+ }
+ else
+ return strftime (s, maxsize, format, timeptr);
+}
+#endif /* __MRC__ */
+
+
+/* no subprocesses, empty wait */
+
+int
+wait (int pid)
+{
+ return 0;
+}
+
+
+void
+croak (char *badfunc)
+{
+ printf ("%s not yet implemented\r\n", badfunc);
+ exit (1);
+}
+
+
+char *
+index (const char * str, int chr)
+{
+ return strchr (str, chr);
+}
+
+
+char *
+mktemp (char *template)
+{
+ int len, k;
+ static seqnum = 0;
+
+ len = strlen (template);
+ k = len - 1;
+ while (k >= 0 && template[k] == 'X')
+ k--;
+
+ k++; /* make k index of first 'X' */
+
+ if (k < len)
+ {
+ /* Zero filled, number of digits equal to the number of X's. */
+ sprintf (&template[k], "%0*d", len-k, seqnum++);
+
+ return template;
+ }
+ else
+ return 0;
+}
+
+
+/* Emulate getpwuid, getpwnam and others. */
+
+#define PASSWD_FIELD_SIZE 256
+
+static char my_passwd_name[PASSWD_FIELD_SIZE];
+static char my_passwd_dir[MAXPATHLEN+1];
+
+static struct passwd my_passwd =
+{
+ my_passwd_name,
+ my_passwd_dir,
+};
+
+
+/* Initialized by main () in macterm.c to pathname of emacs directory. */
+
+char emacs_passwd_dir[MAXPATHLEN+1];
+
+char *
+getwd (char *);
+
+void
+init_emacs_passwd_dir ()
+{
+ int found = false;
+
+ if (getwd (emacs_passwd_dir) && getwd (my_passwd_dir))
+ {
+ /* Need pathname of first ancestor that begins with "emacs"
+ since Mac emacs application is somewhere in the emacs-*
+ tree. */
+ int len = strlen (emacs_passwd_dir);
+ int j = len - 1;
+ /* j points to the "/" following the directory name being
+ compared. */
+ int i = j - 1;
+ while (i >= 0 && !found)
+ {
+ while (i >= 0 && emacs_passwd_dir[i] != '/')
+ i--;
+ if (emacs_passwd_dir[i] == '/' && i+5 < len)
+ found = (strncmp (&(emacs_passwd_dir[i+1]), "emacs", 5) == 0);
+ if (found)
+ emacs_passwd_dir[j+1] = '\0';
+ else
+ {
+ j = i;
+ i = j - 1;
+ }
+ }
+ }
+
+ if (!found)
+ {
+ /* Setting to "/" probably won't work but set it to something
+ anyway. */
+ strcpy (emacs_passwd_dir, "/");
+ strcpy (my_passwd_dir, "/");
+ }
+}
+
+
+static struct passwd emacs_passwd =
+{
+ "emacs",
+ emacs_passwd_dir,
+};
+
+static int my_passwd_inited = 0;
+
+
+static void
+init_my_passwd ()
+{
+ char **owner_name;
+
+ /* Note: my_passwd_dir initialized in int_emacs_passwd_dir to
+ directory where Emacs was started. */
+
+ owner_name = (char **) GetResource ('STR ',-16096);
+ if (owner_name)
+ {
+ HLock (owner_name);
+ BlockMove ((unsigned char *) *owner_name,
+ (unsigned char *) my_passwd_name,
+ *owner_name[0]+1);
+ HUnlock (owner_name);
+ p2cstr ((unsigned char *) my_passwd_name);
+ }
+ else
+ my_passwd_name[0] = 0;
+}
+
+
+struct passwd *
+getpwuid (uid_t uid)
+{
+ if (!my_passwd_inited)
+ {
+ init_my_passwd ();
+ my_passwd_inited = 1;
+ }
+
+ return &my_passwd;
+}
+
+
+struct passwd *
+getpwnam (const char *name)
+{
+ if (strcmp (name, "emacs") == 0)
+ return &emacs_passwd;
+
+ if (!my_passwd_inited)
+ {
+ init_my_passwd ();
+ my_passwd_inited = 1;
+ }
+
+ return &my_passwd;
+}
+
+
+/* The functions fork, kill, sigsetmask, sigblock, request_sigio,
+ setpgrp, setpriority, and unrequest_sigio are defined to be empty
+ as in msdos.c. */
+
+
+int
+fork ()
+{
+ return -1;
+}
+
+
+int
+kill (int x, int y)
+{
+ return -1;
+}
+
+
+void
+sys_subshell ()
+{
+ error ("Can't spawn subshell");
+}
+
+
+int
+sigsetmask (int x)
+{
+ return 0;
+}
+
+
+int
+sigblock (int mask)
+{
+ return 0;
+}
+
+
+void
+request_sigio (void)
+{
+}
+
+
+void
+unrequest_sigio (void)
+{
+}
+
+
+int
+setpgrp ()
+{
+ return 0;
+}
+
+
+/* No pipes yet. */
+
+int
+pipe (int _fildes[2])
+{
+ errno = EACCES;
+ return -1;
+}
+
+
+/* Hard and symbolic links. */
+
+int
+symlink (const char *name1, const char *name2)
+{
+ errno = ENOENT;
+ return -1;
+}
+
+
+int
+link (const char *name1, const char *name2)
+{
+ errno = ENOENT;
+ return -1;
+}
+
+#endif /* ! MAC_OSX */
+
+/* Determine the path name of the file specified by VREFNUM, DIRID,
+ and NAME and place that in the buffer PATH of length
+ MAXPATHLEN. */
+int
+path_from_vol_dir_name (char *path, int man_path_len, short vol_ref_num,
+ long dir_id, ConstStr255Param name)
+{
+ Str255 dir_name;
+ CInfoPBRec cipb;
+ OSErr err;
+
+ if (strlen (name) > man_path_len)
+ return 0;
+
+ memcpy (dir_name, name, name[0]+1);
+ memcpy (path, name, name[0]+1);
+ p2cstr (path);
+
+ cipb.dirInfo.ioDrParID = dir_id;
+ cipb.dirInfo.ioNamePtr = dir_name;
+
+ do
+ {
+ cipb.dirInfo.ioVRefNum = vol_ref_num;
+ cipb.dirInfo.ioFDirIndex = -1;
+ cipb.dirInfo.ioDrDirID = cipb.dirInfo.ioDrParID;
+ /* go up to parent each time */
+
+ err = PBGetCatInfo (&cipb, false);
+ if (err != noErr)
+ return 0;
+
+ p2cstr (dir_name);
+ if (strlen (dir_name) + strlen (path) + 1 >= man_path_len)
+ return 0;
+
+ strcat (dir_name, ":");
+ strcat (dir_name, path);
+ /* attach to front since we're going up directory tree */
+ strcpy (path, dir_name);
+ }
+ while (cipb.dirInfo.ioDrDirID != fsRtDirID);
+ /* stop when we see the volume's root directory */
+
+ return 1; /* success */
+}
+
+#ifndef MAC_OSX
+
+int
+readlink (const char *path, char *buf, int bufsiz)
+{
+ char mac_sym_link_name[MAXPATHLEN+1];
+ OSErr err;
+ FSSpec fsspec;
+ Boolean target_is_folder, was_aliased;
+ Str255 directory_name, mac_pathname;
+ CInfoPBRec cipb;
+
+ if (posix_to_mac_pathname (path, mac_sym_link_name, MAXPATHLEN+1) == 0)
+ return -1;
+
+ c2pstr (mac_sym_link_name);
+ err = FSMakeFSSpec (0, 0, mac_sym_link_name, &fsspec);
+ if (err != noErr)
+ {
+ errno = ENOENT;
+ return -1;
+ }
+
+ err = ResolveAliasFile (&fsspec, true, &target_is_folder, &was_aliased);
+ if (err != noErr || !was_aliased)
+ {
+ errno = ENOENT;
+ return -1;
+ }
+
+ if (path_from_vol_dir_name (mac_pathname, 255, fsspec.vRefNum, fsspec.parID,
+ fsspec.name) == 0)
+ {
+ errno = ENOENT;
+ return -1;
+ }
+
+ if (mac_to_posix_pathname (mac_pathname, buf, bufsiz) == 0)
+ {
+ errno = ENOENT;
+ return -1;
+ }
+
+ return strlen (buf);
+}
+
+
+/* Convert a path to one with aliases fully expanded. */
+
+static int
+find_true_pathname (const char *path, char *buf, int bufsiz)
+{
+ char *q, temp[MAXPATHLEN+1];
+ const char *p;
+ int len;
+
+ if (bufsiz <= 0 || path == 0 || path[0] == '\0')
+ return -1;
+
+ buf[0] = '\0';
+
+ p = path;
+ if (*p == '/')
+ q = strchr (p + 1, '/');
+ else
+ q = strchr (p, '/');
+ len = 0; /* loop may not be entered, e.g., for "/" */
+
+ while (q)
+ {
+ strcpy (temp, buf);
+ strncat (temp, p, q - p);
+ len = readlink (temp, buf, bufsiz);
+ if (len <= -1)
+ {
+ if (strlen (temp) + 1 > bufsiz)
+ return -1;
+ strcpy (buf, temp);
+ }
+ strcat (buf, "/");
+ len++;
+ p = q + 1;
+ q = strchr(p, '/');
+ }
+
+ if (len + strlen (p) + 1 >= bufsiz)
+ return -1;
+
+ strcat (buf, p);
+ return len + strlen (p);
+}
+
+
+mode_t
+umask (mode_t numask)
+{
+ static mode_t mask = 022;
+ mode_t oldmask = mask;
+ mask = numask;
+ return oldmask;
+}
+
+
+int
+chmod (const char *path, mode_t mode)
+{
+ /* say it always succeed for now */
+ return 0;
+}
+
+
+int
+dup (int oldd)
+{
+#ifdef __MRC__
+ return fcntl (oldd, F_DUPFD, 0);
+#elif __MWERKS__
+ /* current implementation of fcntl in fcntl.mac.c simply returns old
+ descriptor */
+ return fcntl (oldd, F_DUPFD);
+#else
+You lose!!!
+#endif
+}
+
+
+/* This is from the original sysdep.c. Emulate BSD dup2. First close
+ newd if it already exists. Then, attempt to dup oldd. If not
+ successful, call dup2 recursively until we are, then close the
+ unsuccessful ones. */
+
+int
+dup2 (int oldd, int newd)
+{
+ int fd, ret;
+
+ close (newd);
+
+ fd = dup (oldd);
+ if (fd == -1)
+ return -1;
+ if (fd == newd)
+ return newd;
+ ret = dup2 (oldd, newd);
+ close (fd);
+ return ret;
+}
+
+
+/* let it fail for now */
+
+char *
+sbrk (int incr)
+{
+ return (char *) -1;
+}
+
+
+int
+fsync (int fd)
+{
+ return 0;
+}
+
+
+int
+ioctl (int d, int request, void *argp)
+{
+ return -1;
+}
+
+
+#ifdef __MRC__
+int
+isatty (int fildes)
+{
+ if (fildes >=0 && fildes <= 2)
+ return 1;
+ else
+ return 0;
+}
+
+
+int
+getgid ()
+{
+ return 100;
+}
+
+
+int
+getegid ()
+{
+ return 100;
+}
+
+
+int
+getuid ()
+{
+ return 200;
+}
+
+
+int
+geteuid ()
+{
+ return 200;
+}
+#endif /* __MRC__ */
+
+
+#ifdef __MWERKS__
+#if __MSL__ < 0x6000
+#undef getpid
+int
+getpid ()
+{
+ return 9999;
+}
+#endif
+#endif /* __MWERKS__ */
+
+#endif /* ! MAC_OSX */
+
+
+/* Return the path to the directory in which Emacs can create
+ temporary files. The MacOS "temporary items" directory cannot be
+ used because it removes the file written by a process when it
+ exits. In that sense it's more like "/dev/null" than "/tmp" (but
+ again not exactly). And of course Emacs needs to read back the
+ files written by its subprocesses. So here we write the files to a
+ directory "Emacs" in the Preferences Folder. This directory is
+ created if it does not exist. */
+
+char *
+get_temp_dir_name ()
+{
+ static char *temp_dir_name = NULL;
+ short vol_ref_num;
+ long dir_id;
+ OSErr err;
+ Str255 dir_name, full_path;
+ CInfoPBRec cpb;
+ char unix_dir_name[MAXPATHLEN+1];
+ DIR *dir;
+
+ /* Cache directory name with pointer temp_dir_name.
+ Look for it only the first time. */
+ if (!temp_dir_name)
+ {
+ err = FindFolder (kOnSystemDisk, kPreferencesFolderType, kCreateFolder,
+ &vol_ref_num, &dir_id);
+ if (err != noErr)
+ return NULL;
+
+ if (!path_from_vol_dir_name (full_path, 255, vol_ref_num, dir_id, "\p"))
+ return NULL;
+
+ if (strlen (full_path) + 6 <= MAXPATHLEN)
+ strcat (full_path, "Emacs:");
+ else
+ return NULL;
+
+ if (!mac_to_posix_pathname (full_path, unix_dir_name, MAXPATHLEN+1))
+ return NULL;
+
+ dir = opendir (unix_dir_name); /* check whether temp directory exists */
+ if (dir)
+ closedir (dir);
+ else if (mkdir (unix_dir_name, 0700) != 0) /* create it if not */
+ return NULL;
+
+ temp_dir_name = (char *) malloc (strlen (unix_dir_name) + 1);
+ strcpy (temp_dir_name, unix_dir_name);
+ }
+
+ return temp_dir_name;
+}
+
+#ifndef MAC_OSX
+
+/* Allocate and construct an array of pointers to strings from a list
+ of strings stored in a 'STR#' resource. The returned pointer array
+ is stored in the style of argv and environ: if the 'STR#' resource
+ contains numString strings, an pointer array with numString+1
+ elements is returned in which the last entry contains a null
+ pointer. The pointer to the pointer array is passed by pointer in
+ parameter t. The resource ID of the 'STR#' resource is passed in
+ parameter StringListID.
+ */
+
+void
+get_string_list (char ***t, short string_list_id)
+{
+ Handle h;
+ Ptr p;
+ int i, num_strings;
+
+ h = GetResource ('STR#', string_list_id);
+ if (h)
+ {
+ HLock (h);
+ p = *h;
+ num_strings = * (short *) p;
+ p += sizeof(short);
+ *t = (char **) malloc (sizeof (char *) * (num_strings + 1));
+ for (i = 0; i < num_strings; i++)
+ {
+ short length = *p++;
+ (*t)[i] = (char *) malloc (length + 1);
+ strncpy ((*t)[i], p, length);
+ (*t)[i][length] = '\0';
+ p += length;
+ }
+ (*t)[num_strings] = 0;
+ HUnlock (h);
+ }
+ else
+ {
+ /* Return no string in case GetResource fails. Bug fixed by
+ Ikegami Tsutomu. Caused MPW build to crash without sym -on
+ option (no sym -on implies -opt local). */
+ *t = (char **) malloc (sizeof (char *));
+ (*t)[0] = 0;
+ }
+}
+
+
+static char *
+get_path_to_system_folder ()
+{
+ short vol_ref_num;
+ long dir_id;
+ OSErr err;
+ Str255 dir_name, full_path;
+ CInfoPBRec cpb;
+ static char system_folder_unix_name[MAXPATHLEN+1];
+ DIR *dir;
+
+ err = FindFolder (kOnSystemDisk, kSystemFolderType, kDontCreateFolder,
+ &vol_ref_num, &dir_id);
+ if (err != noErr)
+ return NULL;
+
+ if (!path_from_vol_dir_name (full_path, 255, vol_ref_num, dir_id, "\p"))
+ return NULL;
+
+ if (!mac_to_posix_pathname (full_path, system_folder_unix_name,
+ MAXPATHLEN+1))
+ return NULL;
+
+ return system_folder_unix_name;
+}
+
+
+char **environ;
+
+#define ENVIRON_STRING_LIST_ID 128
+
+/* Get environment variable definitions from STR# resource. */
+
+void
+init_environ ()
+{
+ int i;
+
+ get_string_list (&environ, ENVIRON_STRING_LIST_ID);
+
+ i = 0;
+ while (environ[i])
+ i++;
+
+ /* Make HOME directory the one Emacs starts up in if not specified
+ by resource. */
+ if (getenv ("HOME") == NULL)
+ {
+ environ = (char **) realloc (environ, sizeof (char *) * (i + 2));
+ if (environ)
+ {
+ environ[i] = (char *) malloc (strlen (my_passwd_dir) + 6);
+ if (environ[i])
+ {
+ strcpy (environ[i], "HOME=");
+ strcat (environ[i], my_passwd_dir);
+ }
+ environ[i+1] = 0;
+ i++;
+ }
+ }
+
+ /* Make HOME directory the one Emacs starts up in if not specified
+ by resource. */
+ if (getenv ("MAIL") == NULL)
+ {
+ environ = (char **) realloc (environ, sizeof (char *) * (i + 2));
+ if (environ)
+ {
+ char * path_to_system_folder = get_path_to_system_folder ();
+ environ[i] = (char *) malloc (strlen (path_to_system_folder) + 22);
+ if (environ[i])
+ {
+ strcpy (environ[i], "MAIL=");
+ strcat (environ[i], path_to_system_folder);
+ strcat (environ[i], "Eudora Folder/In");
+ }
+ environ[i+1] = 0;
+ }
+ }
+}
+
+
+/* Return the value of the environment variable NAME. */
+
+char *
+getenv (const char *name)
+{
+ int length = strlen(name);
+ char **e;
+
+ for (e = environ; *e != 0; e++)
+ if (strncmp(*e, name, length) == 0 && (*e)[length] == '=')
+ return &(*e)[length + 1];
+
+ if (strcmp (name, "TMPDIR") == 0)
+ return get_temp_dir_name ();
+
+ return 0;
+}
+
+
+#ifdef __MRC__
+/* see Interfaces&Libraries:Interfaces:CIncludes:signal.h */
+char *sys_siglist[] =
+{
+ "Zero is not a signal!!!",
+ "Abort", /* 1 */
+ "Interactive user interrupt", /* 2 */ "?",
+ "Floating point exception", /* 4 */ "?", "?", "?",
+ "Illegal instruction", /* 8 */ "?", "?", "?", "?", "?", "?", "?",
+ "Segment violation", /* 16 */ "?", "?", "?", "?", "?", "?", "?",
+ "?", "?", "?", "?", "?", "?", "?", "?",
+ "Terminal" /* 32 */
+};
+#elif __MWERKS__
+char *sys_siglist[] =
+{
+ "Zero is not a signal!!!",
+ "Abort",
+ "Floating point exception",
+ "Illegal instruction",
+ "Interactive user interrupt",
+ "Segment violation",
+ "Terminal"
+};
+#else /* not __MRC__ and not __MWERKS__ */
+You lose!!!
+#endif /* not __MRC__ and not __MWERKS__ */
+
+
+#include <utsname.h>
+
+int
+uname (struct utsname *name)
+{
+ char **system_name;
+ system_name = GetString (-16413); /* IM - Resource Manager Reference */
+ if (system_name)
+ {
+ BlockMove (*system_name, name->nodename, (*system_name)[0]+1);
+ p2cstr (name->nodename);
+ return 0;
+ }
+ else
+ return -1;
+}
+
+
+#include <Processes.h>
+#include <EPPC.h>
+
+/* Event class of HLE sent to subprocess. */
+const OSType kEmacsSubprocessSend = 'ESND';
+
+/* Event class of HLE sent back from subprocess. */
+const OSType kEmacsSubprocessReply = 'ERPY';
+
+
+char *
+mystrchr (char *s, char c)
+{
+ while (*s && *s != c)
+ {
+ if (*s == '\\')
+ s++;
+ s++;
+ }
+
+ if (*s)
+ {
+ *s = '\0';
+ return s;
+ }
+ else
+ return NULL;
+}
+
+
+char *
+mystrtok (char *s)
+{
+ while (*s)
+ s++;
+
+ return s + 1;
+}
+
+
+void
+mystrcpy (char *to, char *from)
+{
+ while (*from)
+ {
+ if (*from == '\\')
+ from++;
+ *to++ = *from++;
+ }
+ *to = '\0';
+}
+
+
+/* Start a Mac subprocess. Arguments for it is passed in argv (null
+ terminated). The process should run with the default directory
+ "workdir", read input from "infn", and write output and error to
+ "outfn" and "errfn", resp. The Process Manager call
+ LaunchApplication is used to start the subprocess. We use high
+ level events as the mechanism to pass arguments to the subprocess
+ and to make Emacs wait for the subprocess to terminate and pass
+ back a result code. The bulk of the code here packs the arguments
+ into one message to be passed together with the high level event.
+ Emacs also sometimes starts a subprocess using a shell to perform
+ wildcard filename expansion. Since we don't really have a shell on
+ the Mac, this case is detected and the starting of the shell is
+ by-passed. We really need to add code here to do filename
+ expansion to support such functionality. */
+
+int
+run_mac_command (argv, workdir, infn, outfn, errfn)
+ unsigned char **argv;
+ const char *workdir;
+ const char *infn, *outfn, *errfn;
+{
+#ifdef TARGET_API_MAC_CARBON
+ return -1;
+#else /* not TARGET_API_MAC_CARBON */
+ char macappname[MAXPATHLEN+1], macworkdir[MAXPATHLEN+1];
+ char macinfn[MAXPATHLEN+1], macoutfn[MAXPATHLEN+1], macerrfn[MAXPATHLEN+1];
+ int paramlen, argc, newargc, j, retries;
+ char **newargv, *param, *p;
+ OSErr iErr;
+ FSSpec spec;
+ LaunchParamBlockRec lpbr;
+ EventRecord send_event, reply_event;
+ RgnHandle cursor_region_handle;
+ TargetID targ;
+ unsigned long ref_con, len;
+
+ if (posix_to_mac_pathname (workdir, macworkdir, MAXPATHLEN+1) == 0)
+ return -1;
+ if (posix_to_mac_pathname (infn, macinfn, MAXPATHLEN+1) == 0)
+ return -1;
+ if (posix_to_mac_pathname (outfn, macoutfn, MAXPATHLEN+1) == 0)
+ return -1;
+ if (posix_to_mac_pathname (errfn, macerrfn, MAXPATHLEN+1) == 0)
+ return -1;
+
+ paramlen = strlen (macworkdir) + strlen (macinfn) + strlen (macoutfn)
+ + strlen (macerrfn) + 4; /* count nulls at end of strings */
+
+ argc = 0;
+ while (argv[argc])
+ argc++;
+
+ if (argc == 0)
+ return -1;
+
+ /* If a subprocess is invoked with a shell, we receive 3 arguments
+ of the form: "<path to emacs bins>/sh" "-c" "<path to emacs
+ bins>/<command> <command args>" */
+ j = strlen (argv[0]);
+ if (j >= 3 && strcmp (argv[0]+j-3, "/sh") == 0
+ && argc == 3 && strcmp (argv[1], "-c") == 0)
+ {
+ char *command, *t, tempmacpathname[MAXPATHLEN+1];
+
+ /* The arguments for the command in argv[2] are separated by
+ spaces. Count them and put the count in newargc. */
+ command = (char *) alloca (strlen (argv[2])+2);
+ strcpy (command, argv[2]);
+ if (command[strlen (command) - 1] != ' ')
+ strcat (command, " ");
+
+ t = command;
+ newargc = 0;
+ t = mystrchr (t, ' ');
+ while (t)
+ {
+ newargc++;
+ t = mystrchr (t+1, ' ');
+ }
+
+ newargv = (char **) alloca (sizeof (char *) * newargc);
+
+ t = command;
+ for (j = 0; j < newargc; j++)
+ {
+ newargv[j] = (char *) alloca (strlen (t) + 1);
+ mystrcpy (newargv[j], t);
+
+ t = mystrtok (t);
+ paramlen += strlen (newargv[j]) + 1;
+ }
+
+ if (strncmp (newargv[0], "~emacs/", 7) == 0)
+ {
+ if (posix_to_mac_pathname (newargv[0], tempmacpathname, MAXPATHLEN+1)
+ == 0)
+ return -1;
+ }
+ else
+ { /* sometimes Emacs call "sh" without a path for the command */
+#if 0
+ char *t = (char *) alloca (strlen (newargv[0]) + 7 + 1);
+ strcpy (t, "~emacs/");
+ strcat (t, newargv[0]);
+#endif /* 0 */
+ Lisp_Object path;
+ openp (Vexec_path, build_string (newargv[0]), EXEC_SUFFIXES, &path,
+ 1);
+
+ if (NILP (path))
+ return -1;
+ if (posix_to_mac_pathname (XSTRING (path)->data, tempmacpathname,
+ MAXPATHLEN+1) == 0)
+ return -1;
+ }
+ strcpy (macappname, tempmacpathname);
+ }
+ else
+ {
+ if (posix_to_mac_pathname (argv[0], macappname, MAXPATHLEN+1) == 0)
+ return -1;
+
+ newargv = (char **) alloca (sizeof (char *) * argc);
+ newargc = argc;
+ for (j = 1; j < argc; j++)
+ {
+ if (strncmp (argv[j], "~emacs/", 7) == 0)
+ {
+ char *t = strchr (argv[j], ' ');
+ if (t)
+ {
+ char tempcmdname[MAXPATHLEN+1], tempmaccmdname[MAXPATHLEN+1];
+ strncpy (tempcmdname, argv[j], t-argv[j]);
+ tempcmdname[t-argv[j]] = '\0';
+ if (posix_to_mac_pathname (tempcmdname, tempmaccmdname,
+ MAXPATHLEN+1) == 0)
+ return -1;
+ newargv[j] = (char *) alloca (strlen (tempmaccmdname)
+ + strlen (t) + 1);
+ strcpy (newargv[j], tempmaccmdname);
+ strcat (newargv[j], t);
+ }
+ else
+ {
+ char tempmaccmdname[MAXPATHLEN+1];
+ if (posix_to_mac_pathname (argv[j], tempmaccmdname,
+ MAXPATHLEN+1) == 0)
+ return -1;
+ newargv[j] = (char *) alloca (strlen (tempmaccmdname)+1);
+ strcpy (newargv[j], tempmaccmdname);
+ }
+ }
+ else
+ newargv[j] = argv[j];
+ paramlen += strlen (newargv[j]) + 1;
+ }
+ }
+
+ /* After expanding all the arguments, we now know the length of the
+ parameter block to be sent to the subprocess as a message
+ attached to the HLE. */
+ param = (char *) malloc (paramlen + 1);
+ if (!param)
+ return -1;
+
+ p = param;
+ *p++ = newargc;
+ /* first byte of message contains number of arguments for command */
+ strcpy (p, macworkdir);
+ p += strlen (macworkdir);
+ *p++ = '\0';
+ /* null terminate strings sent so it's possible to use strcpy over there */
+ strcpy (p, macinfn);
+ p += strlen (macinfn);
+ *p++ = '\0';
+ strcpy (p, macoutfn);
+ p += strlen (macoutfn);
+ *p++ = '\0';
+ strcpy (p, macerrfn);
+ p += strlen (macerrfn);
+ *p++ = '\0';
+ for (j = 1; j < newargc; j++)
+ {
+ strcpy (p, newargv[j]);
+ p += strlen (newargv[j]);
+ *p++ = '\0';
+ }
+
+ c2pstr (macappname);
+
+ iErr = FSMakeFSSpec (0, 0, macappname, &spec);
+
+ if (iErr != noErr)
+ {
+ free (param);
+ return -1;
+ }
+
+ lpbr.launchBlockID = extendedBlock;
+ lpbr.launchEPBLength = extendedBlockLen;
+ lpbr.launchControlFlags = launchContinue + launchNoFileFlags;
+ lpbr.launchAppSpec = &spec;
+ lpbr.launchAppParameters = NULL;
+
+ iErr = LaunchApplication (&lpbr); /* call the subprocess */
+ if (iErr != noErr)
+ {
+ free (param);
+ return -1;
+ }
+
+ send_event.what = kHighLevelEvent;
+ send_event.message = kEmacsSubprocessSend;
+ /* Event ID stored in "where" unused */
+
+ retries = 3;
+ /* OS may think current subprocess has terminated if previous one
+ terminated recently. */
+ do
+ {
+ iErr = PostHighLevelEvent (&send_event, &lpbr.launchProcessSN, 0, param,
+ paramlen + 1, receiverIDisPSN);
+ }
+ while (iErr == sessClosedErr && retries-- > 0);
+
+ if (iErr != noErr)
+ {
+ free (param);
+ return -1;
+ }
+
+ cursor_region_handle = NewRgn ();
+
+ /* Wait for the subprocess to finish, when it will send us a ERPY
+ high level event. */
+ while (1)
+ if (WaitNextEvent (highLevelEventMask, &reply_event, 180,
+ cursor_region_handle)
+ && reply_event.message == kEmacsSubprocessReply)
+ break;
+
+ /* The return code is sent through the refCon */
+ iErr = AcceptHighLevelEvent (&targ, &ref_con, NULL, &len);
+ if (iErr != noErr)
+ {
+ DisposeHandle ((Handle) cursor_region_handle);
+ free (param);
+ return -1;
+ }
+
+ DisposeHandle ((Handle) cursor_region_handle);
+ free (param);
+
+ return ref_con;
+#endif /* not TARGET_API_MAC_CARBON */
+}
+
+
+DIR *
+opendir (const char *dirname)
+{
+ char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];
+ char mac_pathname[MAXPATHLEN+1], vol_name[MAXPATHLEN+1];
+ DIR *dirp;
+ CInfoPBRec cipb;
+ HVolumeParam vpb;
+ int len, vol_name_len;
+
+ if (find_true_pathname (dirname, true_pathname, MAXPATHLEN+1) == -1)
+ return 0;
+
+ len = readlink (true_pathname, fully_resolved_name, MAXPATHLEN);
+ if (len > -1)
+ fully_resolved_name[len] = '\0';
+ else
+ strcpy (fully_resolved_name, true_pathname);
+
+ dirp = (DIR *) malloc (sizeof(DIR));
+ if (!dirp)
+ return 0;
+
+ /* Handle special case when dirname is "/": sets up for readir to
+ get all mount volumes. */
+ if (strcmp (fully_resolved_name, "/") == 0)
+ {
+ dirp->getting_volumes = 1; /* special all mounted volumes DIR struct */
+ dirp->current_index = 1; /* index for first volume */
+ return dirp;
+ }
+
+ /* Handle typical cases: not accessing all mounted volumes. */
+ if (!posix_to_mac_pathname (fully_resolved_name, mac_pathname, MAXPATHLEN+1))
+ return 0;
+
+ /* Emacs calls opendir without the trailing '/', Mac needs trailing ':' */
+ len = strlen (mac_pathname);
+ if (mac_pathname[len - 1] != ':' && len < MAXPATHLEN)
+ strcat (mac_pathname, ":");
+
+ /* Extract volume name */
+ vol_name_len = strchr (mac_pathname, ':') - mac_pathname;
+ strncpy (vol_name, mac_pathname, vol_name_len);
+ vol_name[vol_name_len] = '\0';
+ strcat (vol_name, ":");
+
+ c2pstr (mac_pathname);
+ cipb.hFileInfo.ioNamePtr = mac_pathname;
+ /* using full pathname so vRefNum and DirID ignored */
+ cipb.hFileInfo.ioVRefNum = 0;
+ cipb.hFileInfo.ioDirID = 0;
+ cipb.hFileInfo.ioFDirIndex = 0;
+ /* set to 0 to get information about specific dir or file */
+
+ errno = PBGetCatInfo (&cipb, false);
+ if (errno != noErr)
+ {
+ errno = ENOENT;
+ return 0;
+ }
+
+ if (!(cipb.hFileInfo.ioFlAttrib & 0x10)) /* bit 4 = 1 for directories */
+ return 0; /* not a directory */
+
+ dirp->dir_id = cipb.dirInfo.ioDrDirID; /* used later in readdir */
+ dirp->getting_volumes = 0;
+ dirp->current_index = 1; /* index for first file/directory */
+
+ c2pstr (vol_name);
+ vpb.ioNamePtr = vol_name;
+ /* using full pathname so vRefNum and DirID ignored */
+ vpb.ioVRefNum = 0;
+ vpb.ioVolIndex = -1;
+ errno = PBHGetVInfo ((union HParamBlockRec *) &vpb, false);
+ if (errno != noErr)
+ {
+ errno = ENOENT;
+ return 0;
+ }
+
+ dirp->vol_ref_num = vpb.ioVRefNum;
+
+ return dirp;
+}
+
+int
+closedir (DIR *dp)
+{
+ free (dp);
+
+ return 0;
+}
+
+
+struct dirent *
+readdir (DIR *dp)
+{
+ HParamBlockRec hpblock;
+ CInfoPBRec cipb;
+ static struct dirent s_dirent;
+ static Str255 s_name;
+ int done;
+ char *p;
+
+ /* Handle the root directory containing the mounted volumes. Call
+ PBHGetVInfo specifying an index to obtain the info for a volume.
+ PBHGetVInfo returns an error when it receives an index beyond the
+ last volume, at which time we should return a nil dirent struct
+ pointer. */
+ if (dp->getting_volumes)
+ {
+ hpblock.volumeParam.ioNamePtr = s_name;
+ hpblock.volumeParam.ioVRefNum = 0;
+ hpblock.volumeParam.ioVolIndex = dp->current_index;
+
+ errno = PBHGetVInfo (&hpblock, false);
+ if (errno != noErr)
+ {
+ errno = ENOENT;
+ return 0;
+ }
+
+ p2cstr (s_name);
+ strcat (s_name, "/"); /* need "/" for stat to work correctly */
+
+ dp->current_index++;
+
+ s_dirent.d_ino = hpblock.volumeParam.ioVRefNum;
+ s_dirent.d_name = s_name;
+
+ return &s_dirent;
+ }
+ else
+ {
+ cipb.hFileInfo.ioVRefNum = dp->vol_ref_num;
+ cipb.hFileInfo.ioNamePtr = s_name;
+ /* location to receive filename returned */
+
+ /* return only visible files */
+ done = false;
+ while (!done)
+ {
+ cipb.hFileInfo.ioDirID = dp->dir_id;
+ /* directory ID found by opendir */
+ cipb.hFileInfo.ioFDirIndex = dp->current_index;
+
+ errno = PBGetCatInfo (&cipb, false);
+ if (errno != noErr)
+ {
+ errno = ENOENT;
+ return 0;
+ }
+
+ /* insist on an visibile entry */
+ if (cipb.hFileInfo.ioFlAttrib & 0x10) /* directory? */
+ done = !(cipb.dirInfo.ioDrUsrWds.frFlags & fInvisible);
+ else
+ done = !(cipb.hFileInfo.ioFlFndrInfo.fdFlags & fInvisible);
+
+ dp->current_index++;
+ }
+
+ p2cstr (s_name);
+
+ p = s_name;
+ while (*p)
+ {
+ if (*p == '/')
+ *p = ':';
+ p++;
+ }
+
+ s_dirent.d_ino = cipb.dirInfo.ioDrDirID;
+ /* value unimportant: non-zero for valid file */
+ s_dirent.d_name = s_name;
+
+ return &s_dirent;
+ }
+}
+
+
+char *
+getwd (char *path)
+{
+ char mac_pathname[MAXPATHLEN+1];
+ Str255 directory_name;
+ OSErr errno;
+ CInfoPBRec cipb;
+
+ if (path_from_vol_dir_name (mac_pathname, 255, 0, 0, "\p") == 0)
+ return NULL;
+
+ if (mac_to_posix_pathname (mac_pathname, path, MAXPATHLEN+1) == 0)
+ return 0;
+ else
+ return path;
+}
+
+#endif /* ! MAC_OSX */
+
+
+void
+initialize_applescript ()
+{
+ AEDesc null_desc;
+ OSAError osaerror;
+
+ /* if open fails, as_scripting_component is set to NULL. Its
+ subsequent use in OSA calls will fail with badComponentInstance
+ error. */
+ as_scripting_component = OpenDefaultComponent (kOSAComponentType,
+ kAppleScriptSubtype);
+
+ null_desc.descriptorType = typeNull;
+ null_desc.dataHandle = 0;
+ osaerror = OSAMakeContext (as_scripting_component, &null_desc,
+ kOSANullScript, &as_script_context);
+ if (osaerror)
+ as_script_context = kOSANullScript;
+ /* use default context if create fails */
+}
+
+
+void terminate_applescript()
+{
+ OSADispose (as_scripting_component, as_script_context);
+ CloseComponent (as_scripting_component);
+}
+
+
+/* Compile and execute the AppleScript SCRIPT and return the error
+ status as function value. A zero is returned if compilation and
+ execution is successful, in which case RESULT returns a pointer to
+ a string containing the resulting script value. Otherwise, the Mac
+ error code is returned and RESULT returns a pointer to an error
+ string. In both cases the caller should deallocate the storage
+ used by the string pointed to by RESULT if it is non-NULL. For
+ documentation on the MacOS scripting architecture, see Inside
+ Macintosh - Interapplication Communications: Scripting Components. */
+
+static long
+do_applescript (char *script, char **result)
+{
+ AEDesc script_desc, result_desc, error_desc;
+ OSErr error;
+ OSAError osaerror;
+ long length;
+
+ *result = 0;
+
+ error = AECreateDesc (typeChar, script, strlen(script), &script_desc);
+ if (error)
+ return error;
+
+ osaerror = OSADoScript (as_scripting_component, &script_desc, kOSANullScript,
+ typeChar, kOSAModeNull, &result_desc);
+
+ if (osaerror == errOSAScriptError)
+ {
+ /* error executing AppleScript: retrieve error message */
+ if (!OSAScriptError (as_scripting_component, kOSAErrorMessage, typeChar,
+ &error_desc))
+ {
+#if TARGET_API_MAC_CARBON
+ length = AEGetDescDataSize (&error_desc);
+ *result = (char *) xmalloc (length + 1);
+ if (*result)
+ {
+ AEGetDescData (&error_desc, *result, length);
+ *(*result + length) = '\0';
+ }
+#else /* not TARGET_API_MAC_CARBON */
+ HLock (error_desc.dataHandle);
+ length = GetHandleSize(error_desc.dataHandle);
+ *result = (char *) xmalloc (length + 1);
+ if (*result)
+ {
+ memcpy (*result, *(error_desc.dataHandle), length);
+ *(*result + length) = '\0';
+ }
+ HUnlock (error_desc.dataHandle);
+#endif /* not TARGET_API_MAC_CARBON */
+ AEDisposeDesc (&error_desc);
+ }
+ }
+ else if (osaerror == noErr) /* success: retrieve resulting script value */
+ {
+#if TARGET_API_MAC_CARBON
+ length = AEGetDescDataSize (&result_desc);
+ *result = (char *) xmalloc (length + 1);
+ if (*result)
+ {
+ AEGetDescData (&result_desc, *result, length);
+ *(*result + length) = '\0';
+ }
+#else /* not TARGET_API_MAC_CARBON */
+ HLock (result_desc.dataHandle);
+ length = GetHandleSize(result_desc.dataHandle);
+ *result = (char *) xmalloc (length + 1);
+ if (*result)
+ {
+ memcpy (*result, *(result_desc.dataHandle), length);
+ *(*result + length) = '\0';
+ }
+ HUnlock (result_desc.dataHandle);
+#endif /* not TARGET_API_MAC_CARBON */
+ }
+
+ AEDisposeDesc (&script_desc);
+ AEDisposeDesc (&result_desc);
+
+ return osaerror;
+}
+
+
+DEFUN ("do-applescript", Fdo_applescript, Sdo_applescript, 1, 1, 0,
+ doc: /* Compile and execute AppleScript SCRIPT and retrieve and return the result.
+If compilation and execution are successful, the resulting script
+value is returned as a string. Otherwise the function aborts and
+displays the error message returned by the AppleScript scripting
+component. */)
+ (script)
+ Lisp_Object script;
+{
+ char *result, *temp;
+ Lisp_Object lisp_result;
+ long status;
+
+ CHECK_STRING (script);
+
+ status = do_applescript (XSTRING (script)->data, &result);
+ if (status)
+ {
+ if (!result)
+ error ("AppleScript error %ld", status);
+ else
+ {
+ /* Unfortunately only OSADoScript in do_applescript knows how
+ how large the resulting script value or error message is
+ going to be and therefore as caller memory must be
+ deallocated here. It is necessary to free the error
+ message before calling error to avoid a memory leak. */
+ temp = (char *) alloca (strlen (result) + 1);
+ strcpy (temp, result);
+ xfree (result);
+ error (temp);
+ }
+ }
+ else
+ {
+ lisp_result = build_string (result);
+ xfree (result);
+ return lisp_result;
+ }
+}
+
+
+DEFUN ("mac-file-name-to-posix", Fmac_file_name_to_posix,
+ Smac_file_name_to_posix, 1, 1, 0,
+ doc: /* Convert Macintosh filename to Posix form. */)
+ (mac_filename)
+ Lisp_Object mac_filename;
+{
+ char posix_filename[MAXPATHLEN+1];
+
+ CHECK_STRING (mac_filename);
+
+ if (mac_to_posix_pathname (XSTRING (mac_filename)->data, posix_filename,
+ MAXPATHLEN))
+ return build_string (posix_filename);
+ else
+ return Qnil;
+}
+
+
+DEFUN ("posix-file-name-to-mac", Fposix_file_name_to_mac,
+ Sposix_file_name_to_mac, 1, 1, 0,
+ doc: /* Convert Posix filename to Mac form. */)
+ (posix_filename)
+ Lisp_Object posix_filename;
+{
+ char mac_filename[MAXPATHLEN+1];
+
+ CHECK_STRING (posix_filename);
+
+ if (posix_to_mac_pathname (XSTRING (posix_filename)->data, mac_filename,
+ MAXPATHLEN))
+ return build_string (mac_filename);
+ else
+ return Qnil;
+}
+
+
+/* set interprogram-paste-function to mac-paste-function in mac-win.el
+ to enable Emacs to obtain the contents of the Mac clipboard. */
+DEFUN ("mac-paste-function", Fmac_paste_function, Smac_paste_function, 0, 0, 0,
+ doc: /* Return the contents of the Mac clipboard as a string. */)
+ ()
+{
+#if TARGET_API_MAC_CARBON
+ ScrapRef scrap;
+ ScrapFlavorFlags sff;
+ Size s;
+ int i;
+ char *data;
+
+ if (GetCurrentScrap (&scrap) != noErr)
+ return Qnil;
+
+ if (GetScrapFlavorFlags (scrap, kScrapFlavorTypeText, &sff) != noErr)
+ return Qnil;
+
+ if (GetScrapFlavorSize (scrap, kScrapFlavorTypeText, &s) != noErr)
+ return Qnil;
+
+ if ((data = (char*) alloca (s)) == NULL)
+ return Qnil;
+
+ if (GetScrapFlavorData (scrap, kScrapFlavorTypeText, &s, data) != noErr
+ || s == 0)
+ return Qnil;
+
+ /* Emacs expects clipboard contents have Unix-style eol's */
+ for (i = 0; i < s; i++)
+ if (data[i] == '\r')
+ data[i] = '\n';
+
+ return make_string (data, s);
+#else /* not TARGET_API_MAC_CARBON */
+ Lisp_Object value;
+ Handle my_handle;
+ long scrap_offset, rc, i;
+
+ my_handle = NewHandle (0); /* allocate 0-length data area */
+
+ rc = GetScrap (my_handle, 'TEXT', &scrap_offset);
+ if (rc < 0)
+ return Qnil;
+
+ HLock (my_handle);
+
+ /* Emacs expects clipboard contents have Unix-style eol's */
+ for (i = 0; i < rc; i++)
+ if ((*my_handle)[i] == '\r')
+ (*my_handle)[i] = '\n';
+
+ value = make_string (*my_handle, rc);
+
+ HUnlock (my_handle);
+
+ DisposeHandle (my_handle);
+
+ return value;
+#endif /* not TARGET_API_MAC_CARBON */
+}
+
+
+/* set interprogram-cut-function to mac-cut-function in mac-win.el
+ to enable Emacs to write the top of the kill-ring to the Mac clipboard. */
+DEFUN ("mac-cut-function", Fmac_cut_function, Smac_cut_function, 1, 2, 0,
+ doc: /* Put the value of the string parameter to the Mac clipboard. */)
+ (value, push)
+ Lisp_Object value, push;
+{
+ char *buf;
+ int len, i;
+
+ /* fixme: ignore the push flag for now */
+
+ CHECK_STRING (value);
+
+ len = XSTRING (value)->size;
+ buf = (char *) alloca (len+1);
+ bcopy (XSTRING (value)->data, buf, len);
+ buf[len] = '\0';
+
+ /* convert to Mac-style eol's before sending to clipboard */
+ for (i = 0; i < len; i++)
+ if (buf[i] == '\n')
+ buf[i] = '\r';
+
+#if TARGET_API_MAC_CARBON
+ {
+ ScrapRef scrap;
+ ClearCurrentScrap ();
+ if (GetCurrentScrap (&scrap) != noErr)
+ error ("cannot get current scrap");
+
+ if (PutScrapFlavor (scrap, kScrapFlavorTypeText, kScrapFlavorMaskNone, len,
+ buf) != noErr)
+ error ("cannot put to scrap");
+ }
+#else /* not TARGET_API_MAC_CARBON */
+ ZeroScrap ();
+ PutScrap (len, 'TEXT', buf);
+#endif /* not TARGET_API_MAC_CARBON */
+
+ return Qnil;
+}
+
+
+DEFUN ("x-selection-exists-p", Fx_selection_exists_p, Sx_selection_exists_p,
+ 0, 1, 0,
+ doc: /* Whether there is an owner for the given X Selection.
+The arg should be the name of the selection in question, typically one of
+the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.
+(Those are literal upper-case symbol names, since that's what X expects.)
+For convenience, the symbol nil is the same as `PRIMARY',
+and t is the same as `SECONDARY'. */)
+ (selection)
+ Lisp_Object selection;
+{
+ CHECK_SYMBOL (selection);
+
+ /* Return nil for PRIMARY and SECONDARY selections; for CLIPBOARD, check
+ if the clipboard currently has valid text format contents. */
+
+ if (EQ (selection, QCLIPBOARD))
+ {
+ Lisp_Object val = Qnil;
+
+#if TARGET_API_MAC_CARBON
+ ScrapRef scrap;
+ ScrapFlavorFlags sff;
+
+ if (GetCurrentScrap (&scrap) == noErr)
+ if (GetScrapFlavorFlags (scrap, kScrapFlavorTypeText, &sff) == noErr)
+ val = Qt;
+#else /* not TARGET_API_MAC_CARBON */
+ Handle my_handle;
+ long rc, scrap_offset;
+
+ my_handle = NewHandle (0);
+
+ rc = GetScrap (my_handle, 'TEXT', &scrap_offset);
+ if (rc >= 0)
+ val = Qt;
+
+ DisposeHandle (my_handle);
+#endif /* not TARGET_API_MAC_CARBON */
+
+ return val;
+ }
+ return Qnil;
+}
+
+
+void
+syms_of_mac ()
+{
+ QCLIPBOARD = intern ("CLIPBOARD");
+ staticpro (&QCLIPBOARD);
+
+ defsubr (&Smac_paste_function);
+ defsubr (&Smac_cut_function);
+#if 0
+ defsubr (&Sx_selection_exists_p);
+#endif /* 0 */
+
+ defsubr (&Sdo_applescript);
+ defsubr (&Smac_file_name_to_posix);
+ defsubr (&Sposix_file_name_to_mac);
+}
--- /dev/null
+/* Graphical user interface functions for Mac OS.
+ Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Contributed by Andrew Choi (akochoi@mac.com). */
+
+#include <config.h>
+
+#include <signal.h>
+#include <stdio.h>
+#include <math.h>
+#include <limits.h>
+#include <errno.h>
+
+#include "lisp.h"
+#include "charset.h"
+#include "macterm.h"
+#include "frame.h"
+#include "window.h"
+#include "buffer.h"
+#include "dispextern.h"
+#include "fontset.h"
+#include "intervals.h"
+#include "keyboard.h"
+#include "blockinput.h"
+#include "epaths.h"
+#include "termhooks.h"
+#include "coding.h"
+#include "ccl.h"
+#include "systime.h"
+
+/* #include "bitmaps/gray.xbm" */
+#define gray_width 2
+#define gray_height 2
+static unsigned char gray_bits[] = {
+ 0x01, 0x02};
+
+/*#include <commdlg.h>
+#include <shellapi.h>*/
+#include <ctype.h>
+
+#include <stdlib.h>
+#include <string.h>
+#ifndef MAC_OSX
+#include <alloca.h>
+#endif
+
+#ifdef MAC_OSX
+#undef mktime
+#undef DEBUG
+#undef Z
+#undef free
+#undef malloc
+#undef realloc
+/* Macros max and min defined in lisp.h conflict with those in
+ precompiled header Carbon.h. */
+#undef max
+#undef min
+#include <Carbon/Carbon.h>
+#undef Z
+#define Z (current_buffer->text->z)
+#undef free
+#define free unexec_free
+#undef malloc
+#define malloc unexec_malloc
+#undef realloc
+#define realloc unexec_realloc
+#undef min
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#undef max
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#else /* not MAC_OSX */
+#include <Windows.h>
+#include <Gestalt.h>
+#include <TextUtils.h>
+#endif /* not MAC_OSX */
+
+/*extern void free_frame_menubar ();
+extern double atof ();
+extern int w32_console_toggle_lock_key (int vk_code, Lisp_Object new_state);
+extern int quit_char;*/
+
+/* A definition of XColor for non-X frames. */
+#ifndef HAVE_X_WINDOWS
+typedef struct {
+ unsigned long pixel;
+ unsigned short red, green, blue;
+ char flags;
+ char pad;
+} XColor;
+#endif
+
+extern char *lispy_function_keys[];
+
+/* The gray bitmap `bitmaps/gray'. This is done because macterm.c uses
+ it, and including `bitmaps/gray' more than once is a problem when
+ config.h defines `static' as an empty replacement string. */
+
+int gray_bitmap_width = gray_width;
+int gray_bitmap_height = gray_height;
+unsigned char *gray_bitmap_bits = gray_bits;
+
+/* The name we're using in resource queries. */
+
+Lisp_Object Vx_resource_name;
+
+/* Non-zero means we're allowed to display an hourglass cursor. */
+
+int display_hourglass_p;
+
+/* The background and shape of the mouse pointer, and shape when not
+ over text or in the modeline. */
+
+Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
+Lisp_Object Vx_hourglass_pointer_shape;
+
+/* The shape when over mouse-sensitive text. */
+
+Lisp_Object Vx_sensitive_text_pointer_shape;
+
+/* If non-nil, the pointer shape to indicate that windows can be
+ dragged horizontally. */
+
+Lisp_Object Vx_window_horizontal_drag_shape;
+
+/* Color of chars displayed in cursor box. */
+
+Lisp_Object Vx_cursor_fore_pixel;
+
+/* Nonzero if using Windows. */
+
+static int mac_in_use;
+
+/* Non nil if no window manager is in use. */
+
+Lisp_Object Vx_no_window_manager;
+
+/* Search path for bitmap files. */
+
+Lisp_Object Vx_bitmap_file_path;
+
+/* Regexp matching a font name whose width is the same as `PIXEL_SIZE'. */
+
+Lisp_Object Vx_pixel_size_width_font_regexp;
+
+/* Evaluate this expression to rebuild the section of syms_of_macfns
+ that initializes and staticpros the symbols declared below. Note
+ that Emacs 18 has a bug that keeps C-x C-e from being able to
+ evaluate this expression.
+
+(progn
+ ;; Accumulate a list of the symbols we want to initialize from the
+ ;; declarations at the top of the file.
+ (goto-char (point-min))
+ (search-forward "/\*&&& symbols declared here &&&*\/\n")
+ (let (symbol-list)
+ (while (looking-at "Lisp_Object \\(Q[a-z_]+\\)")
+ (setq symbol-list
+ (cons (buffer-substring (match-beginning 1) (match-end 1))
+ symbol-list))
+ (forward-line 1))
+ (setq symbol-list (nreverse symbol-list))
+ ;; Delete the section of syms_of_... where we initialize the symbols.
+ (search-forward "\n /\*&&& init symbols here &&&*\/\n")
+ (let ((start (point)))
+ (while (looking-at "^ Q")
+ (forward-line 2))
+ (kill-region start (point)))
+ ;; Write a new symbol initialization section.
+ (while symbol-list
+ (insert (format " %s = intern (\"" (car symbol-list)))
+ (let ((start (point)))
+ (insert (substring (car symbol-list) 1))
+ (subst-char-in-region start (point) ?_ ?-))
+ (insert (format "\");\n staticpro (&%s);\n" (car symbol-list)))
+ (setq symbol-list (cdr symbol-list)))))
+
+ */
+
+/*&&& symbols declared here &&&*/
+Lisp_Object Qauto_raise;
+Lisp_Object Qauto_lower;
+Lisp_Object Qbar;
+Lisp_Object Qborder_color;
+Lisp_Object Qborder_width;
+Lisp_Object Qbox;
+Lisp_Object Qcursor_color;
+Lisp_Object Qcursor_type;
+Lisp_Object Qgeometry;
+Lisp_Object Qicon_left;
+Lisp_Object Qicon_top;
+Lisp_Object Qicon_type;
+Lisp_Object Qicon_name;
+Lisp_Object Qinternal_border_width;
+Lisp_Object Qleft;
+Lisp_Object Qright;
+Lisp_Object Qmouse_color;
+Lisp_Object Qnone;
+Lisp_Object Qparent_id;
+Lisp_Object Qscroll_bar_width;
+Lisp_Object Qsuppress_icon;
+Lisp_Object Qundefined_color;
+Lisp_Object Qvertical_scroll_bars;
+Lisp_Object Qvisibility;
+Lisp_Object Qwindow_id;
+Lisp_Object Qx_frame_parameter;
+Lisp_Object Qx_resource_name;
+Lisp_Object Quser_position;
+Lisp_Object Quser_size;
+Lisp_Object Qscreen_gamma;
+Lisp_Object Qline_spacing;
+Lisp_Object Qcenter;
+Lisp_Object Qcancel_timer;
+Lisp_Object Qhyper;
+Lisp_Object Qsuper;
+Lisp_Object Qmeta;
+Lisp_Object Qalt;
+Lisp_Object Qctrl;
+Lisp_Object Qcontrol;
+Lisp_Object Qshift;
+
+extern Lisp_Object Qtop;
+extern Lisp_Object Qdisplay;
+Lisp_Object Qscroll_bar_foreground, Qscroll_bar_background;
+extern Lisp_Object Qtool_bar_lines;
+
+/* These are defined in frame.c. */
+extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
+extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
+extern Lisp_Object Qtool_bar_lines;
+
+extern Lisp_Object Vwindow_system_version;
+
+Lisp_Object Qface_set_after_frame_default;
+
+extern int mac_initialized;
+
+/* Functions in macterm.c. */
+extern void x_set_offset (struct frame *, int, int, int);
+extern void x_wm_set_icon_position (struct frame *, int, int);
+extern void x_display_cursor (struct window *, int, int, int, int, int);
+extern void x_set_window_size (struct frame *, int, int, int);
+extern void x_make_frame_visible (struct frame *);
+extern struct mac_display_info *mac_term_init (Lisp_Object, char *, char *);
+extern struct font_info *x_get_font_info (FRAME_PTR, int);
+extern struct font_info *x_load_font (struct frame *, char *, int);
+extern void x_find_ccl_program (struct font_info *);
+extern struct font_info *x_query_font (struct frame *, char *);
+extern void mac_initialize ();
+
+/* compare two strings ignoring case */
+
+static int
+stricmp (const char *s, const char *t)
+{
+ for ( ; tolower (*s) == tolower (*t); s++, t++)
+ if (*s == '\0')
+ return 0;
+ return tolower (*s) - tolower (*t);
+}
+
+/* compare two strings up to n characters, ignoring case */
+
+static int
+strnicmp (const char *s, const char *t, unsigned int n)
+{
+ for ( ; n-- > 0 && tolower (*s) == tolower (*t); s++, t++)
+ if (*s == '\0')
+ return 0;
+ return n == 0 ? 0 : tolower (*s) - tolower (*t);
+}
+
+\f
+/* Error if we are not running on Mac OS. */
+
+void
+check_mac ()
+{
+ if (! mac_in_use)
+ error ("Mac OS not in use or not initialized");
+}
+
+/* Nonzero if we can use mouse menus.
+ You should not call this unless HAVE_MENUS is defined. */
+
+int
+have_menus_p ()
+{
+ return mac_in_use;
+}
+
+/* Extract a frame as a FRAME_PTR, defaulting to the selected frame
+ and checking validity for Mac. */
+
+FRAME_PTR
+check_x_frame (frame)
+ Lisp_Object frame;
+{
+ FRAME_PTR f;
+
+ if (NILP (frame))
+ frame = selected_frame;
+ CHECK_LIVE_FRAME (frame);
+ f = XFRAME (frame);
+ if (! FRAME_MAC_P (f))
+ error ("non-mac frame used");
+ return f;
+}
+
+/* Let the user specify an display with a frame.
+ nil stands for the selected frame--or, if that is not a mac frame,
+ the first display on the list. */
+
+static struct mac_display_info *
+check_x_display_info (frame)
+ Lisp_Object frame;
+{
+ if (!mac_initialized)
+ {
+ mac_initialize ();
+ mac_initialized = 1;
+ }
+
+ if (NILP (frame))
+ {
+ struct frame *sf = XFRAME (selected_frame);
+
+ if (FRAME_MAC_P (sf) && FRAME_LIVE_P (sf))
+ return FRAME_MAC_DISPLAY_INFO (sf);
+ else
+ return &one_mac_display_info;
+ }
+ else if (STRINGP (frame))
+ return x_display_info_for_name (frame);
+ else
+ {
+ FRAME_PTR f;
+
+ CHECK_LIVE_FRAME (frame);
+ f = XFRAME (frame);
+ if (! FRAME_MAC_P (f))
+ error ("non-mac frame used");
+ return FRAME_MAC_DISPLAY_INFO (f);
+ }
+}
+\f
+/* Return the Emacs frame-object corresponding to an mac window.
+ It could be the frame's main window or an icon window. */
+
+/* This function can be called during GC, so use GC_xxx type test macros. */
+
+struct frame *
+x_window_to_frame (dpyinfo, wdesc)
+ struct mac_display_info *dpyinfo;
+ WindowPtr wdesc;
+{
+ Lisp_Object tail, frame;
+ struct frame *f;
+
+ for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
+ {
+ frame = XCAR (tail);
+ if (!GC_FRAMEP (frame))
+ continue;
+ f = XFRAME (frame);
+ if (!FRAME_W32_P (f) || FRAME_MAC_DISPLAY_INFO (f) != dpyinfo)
+ continue;
+ /*if (f->output_data.w32->hourglass_window == wdesc)
+ return f;*/
+
+ /* MAC_TODO: Check tooltips when supported. */
+ if (FRAME_MAC_WINDOW (f) == wdesc)
+ return f;
+ }
+ return 0;
+}
+
+\f
+
+/* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
+ id, which is just an int that this section returns. Bitmaps are
+ reference counted so they can be shared among frames.
+
+ Bitmap indices are guaranteed to be > 0, so a negative number can
+ be used to indicate no bitmap.
+
+ If you use x_create_bitmap_from_data, then you must keep track of
+ the bitmaps yourself. That is, creating a bitmap from the same
+ data more than once will not be caught. */
+
+
+/* Functions to access the contents of a bitmap, given an id. */
+
+int
+x_bitmap_height (f, id)
+ FRAME_PTR f;
+ int id;
+{
+ return FRAME_MAC_DISPLAY_INFO (f)->bitmaps[id - 1].height;
+}
+
+int
+x_bitmap_width (f, id)
+ FRAME_PTR f;
+ int id;
+{
+ return FRAME_MAC_DISPLAY_INFO (f)->bitmaps[id - 1].width;
+}
+
+#if 0 /* MAC_TODO : not used anywhere (?) */
+int
+x_bitmap_pixmap (f, id)
+ FRAME_PTR f;
+ int id;
+{
+ return (int) FRAME_MAC_DISPLAY_INFO (f)->bitmaps[id - 1].pixmap;
+}
+#endif
+
+/* Allocate a new bitmap record. Returns index of new record. */
+
+static int
+x_allocate_bitmap_record (f)
+ FRAME_PTR f;
+{
+ struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+ int i;
+
+ if (dpyinfo->bitmaps == NULL)
+ {
+ dpyinfo->bitmaps_size = 10;
+ dpyinfo->bitmaps = (struct mac_bitmap_record *)
+ xmalloc (dpyinfo->bitmaps_size * sizeof (struct mac_bitmap_record));
+ dpyinfo->bitmaps_last = 1;
+ return 1;
+ }
+
+ if (dpyinfo->bitmaps_last < dpyinfo->bitmaps_size)
+ return ++dpyinfo->bitmaps_last;
+
+ for (i = 0; i < dpyinfo->bitmaps_size; ++i)
+ if (dpyinfo->bitmaps[i].refcount == 0)
+ return i + 1;
+
+ dpyinfo->bitmaps_size *= 2;
+ dpyinfo->bitmaps = (struct mac_bitmap_record *)
+ xrealloc (dpyinfo->bitmaps,
+ dpyinfo->bitmaps_size * sizeof (struct mac_bitmap_record));
+ return ++dpyinfo->bitmaps_last;
+}
+
+/* Add one reference to the reference count of the bitmap with id
+ ID. */
+
+void
+x_reference_bitmap (f, id)
+ FRAME_PTR f;
+ int id;
+{
+ ++FRAME_MAC_DISPLAY_INFO (f)->bitmaps[id - 1].refcount;
+}
+
+/* Create a bitmap for frame F from a HEIGHT x WIDTH array of bits at
+ BITS. */
+
+int
+x_create_bitmap_from_data (f, bits, width, height)
+ struct frame *f;
+ char *bits;
+ unsigned int width, height;
+{
+ struct x_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+ int id;
+
+ /* MAC_TODO: for now fail if width is not mod 16 (toolbox requires it) */
+
+ id = x_allocate_bitmap_record (f);
+
+ if (width % 16 != 0)
+ return -1;
+
+ dpyinfo->bitmaps[id - 1].bitmap_data = (char *) xmalloc (height * width);
+ if (! dpyinfo->bitmaps[id - 1].bitmap_data)
+ return -1;
+
+ bcopy (bits, dpyinfo->bitmaps[id - 1].bitmap_data, height * width);
+
+ dpyinfo->bitmaps[id - 1].refcount = 1;
+ dpyinfo->bitmaps[id - 1].height = height;
+ dpyinfo->bitmaps[id - 1].width = width;
+
+ return id;
+}
+
+/* Create bitmap from file FILE for frame F. */
+
+int
+x_create_bitmap_from_file (f, file)
+ struct frame *f;
+ Lisp_Object file;
+{
+ return -1;
+#if 0 /* MAC_TODO : bitmap support */
+ struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
+ unsigned int width, height;
+ HBITMAP bitmap;
+ int xhot, yhot, result, id;
+ Lisp_Object found;
+ int fd;
+ char *filename;
+ HINSTANCE hinst;
+
+ /* Look for an existing bitmap with the same name. */
+ for (id = 0; id < dpyinfo->bitmaps_last; ++id)
+ {
+ if (dpyinfo->bitmaps[id].refcount
+ && dpyinfo->bitmaps[id].file
+ && !strcmp (dpyinfo->bitmaps[id].file, (char *) XSTRING (file)->data))
+ {
+ ++dpyinfo->bitmaps[id].refcount;
+ return id + 1;
+ }
+ }
+
+ /* Search bitmap-file-path for the file, if appropriate. */
+ fd = openp (Vx_bitmap_file_path, file, "", &found, 0);
+ if (fd < 0)
+ return -1;
+ /* LoadLibraryEx won't handle special files handled by Emacs handler. */
+ if (fd == 0)
+ return -1;
+ emacs_close (fd);
+
+ filename = (char *) XSTRING (found)->data;
+
+ hinst = LoadLibraryEx (filename, NULL, LOAD_LIBRARY_AS_DATAFILE);
+
+ if (hinst == NULL)
+ return -1;
+
+
+ result = XReadBitmapFile (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
+ filename, &width, &height, &bitmap, &xhot, &yhot);
+ if (result != BitmapSuccess)
+ return -1;
+
+ id = x_allocate_bitmap_record (f);
+ dpyinfo->bitmaps[id - 1].pixmap = bitmap;
+ dpyinfo->bitmaps[id - 1].refcount = 1;
+ dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (XSTRING (file)->size + 1);
+ dpyinfo->bitmaps[id - 1].depth = 1;
+ dpyinfo->bitmaps[id - 1].height = height;
+ dpyinfo->bitmaps[id - 1].width = width;
+ strcpy (dpyinfo->bitmaps[id - 1].file, XSTRING (file)->data);
+
+ return id;
+#endif /* MAC_TODO */
+}
+
+/* Remove reference to bitmap with id number ID. */
+
+void
+x_destroy_bitmap (f, id)
+ FRAME_PTR f;
+ int id;
+{
+ struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+
+ if (id > 0)
+ {
+ --dpyinfo->bitmaps[id - 1].refcount;
+ if (dpyinfo->bitmaps[id - 1].refcount == 0)
+ {
+ BLOCK_INPUT;
+ dpyinfo->bitmaps[id - 1].bitmap_data = NULL;
+ UNBLOCK_INPUT;
+ }
+ }
+}
+
+/* Free all the bitmaps for the display specified by DPYINFO. */
+
+static void
+x_destroy_all_bitmaps (dpyinfo)
+ struct mac_display_info *dpyinfo;
+{
+ int i;
+ for (i = 0; i < dpyinfo->bitmaps_last; i++)
+ if (dpyinfo->bitmaps[i].refcount > 0)
+ xfree (dpyinfo->bitmaps[i].bitmap_data);
+ dpyinfo->bitmaps_last = 0;
+}
+\f
+/* Connect the frame-parameter names for W32 frames
+ to the ways of passing the parameter values to the window system.
+
+ The name of a parameter, as a Lisp symbol,
+ has an `x-frame-parameter' property which is an integer in Lisp
+ but can be interpreted as an `enum x_frame_parm' in C. */
+
+struct x_frame_parm_table
+{
+ char *name;
+ void (*setter) P_ ((struct frame *, Lisp_Object, Lisp_Object));
+};
+
+void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
+static void x_set_line_spacing P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_font P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_border_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_internal_border_width P_ ((struct frame *, Lisp_Object,
+ Lisp_Object));
+void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_autoraise P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_autolower P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_vertical_scroll_bars P_ ((struct frame *, Lisp_Object,
+ Lisp_Object));
+void x_set_visibility P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_scroll_bar_width P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_unsplittable P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
+void x_set_scroll_bar_foreground P_ ((struct frame *, Lisp_Object,
+ Lisp_Object));
+void x_set_scroll_bar_background P_ ((struct frame *, Lisp_Object,
+ Lisp_Object));
+static Lisp_Object x_default_scroll_bar_color_parameter P_ ((struct frame *,
+ Lisp_Object,
+ Lisp_Object,
+ char *, char *,
+ int));
+static void x_set_screen_gamma P_ ((struct frame *, Lisp_Object, Lisp_Object));
+
+static struct x_frame_parm_table x_frame_parms[] =
+{
+ "auto-raise", x_set_autoraise,
+ "auto-lower", x_set_autolower,
+ "background-color", x_set_background_color,
+ "border-color", x_set_border_color,
+ "border-width", x_set_border_width,
+ "cursor-color", x_set_cursor_color,
+ "cursor-type", x_set_cursor_type,
+ "font", x_set_font,
+ "foreground-color", x_set_foreground_color,
+ "icon-name", x_set_icon_name,
+#if 0 /* MAC_TODO: no icons for Mac */
+ "icon-type", x_set_icon_type,
+#endif
+ "internal-border-width", x_set_internal_border_width,
+ "menu-bar-lines", x_set_menu_bar_lines,
+ "mouse-color", x_set_mouse_color,
+ "name", x_explicitly_set_name,
+ "scroll-bar-width", x_set_scroll_bar_width,
+ "title", x_set_title,
+ "unsplittable", x_set_unsplittable,
+ "vertical-scroll-bars", x_set_vertical_scroll_bars,
+ "visibility", x_set_visibility,
+ "tool-bar-lines", x_set_tool_bar_lines,
+#if 0 /* MAC_TODO: cannot set color of scroll bar on the Mac? */
+ "scroll-bar-foreground", x_set_scroll_bar_foreground,
+ "scroll-bar-background", x_set_scroll_bar_background,
+#endif
+ "screen-gamma", x_set_screen_gamma,
+ "line-spacing", x_set_line_spacing
+};
+
+/* Attach the `x-frame-parameter' properties to
+ the Lisp symbol names of parameters relevant to Mac. */
+
+void
+init_x_parm_symbols ()
+{
+ int i;
+
+ for (i = 0; i < sizeof (x_frame_parms) / sizeof (x_frame_parms[0]); i++)
+ Fput (intern (x_frame_parms[i].name), Qx_frame_parameter,
+ make_number (i));
+}
+\f
+/* Change the parameters of frame F as specified by ALIST.
+ If a parameter is not specially recognized, do nothing;
+ otherwise call the `x_set_...' function for that parameter. */
+
+void
+x_set_frame_parameters (f, alist)
+ FRAME_PTR f;
+ Lisp_Object alist;
+{
+ Lisp_Object tail;
+
+ /* If both of these parameters are present, it's more efficient to
+ set them both at once. So we wait until we've looked at the
+ entire list before we set them. */
+ int width, height;
+
+ /* Same here. */
+ Lisp_Object left, top;
+
+ /* Same with these. */
+ Lisp_Object icon_left, icon_top;
+
+ /* Record in these vectors all the parms specified. */
+ Lisp_Object *parms;
+ Lisp_Object *values;
+ int i, p;
+ int left_no_change = 0, top_no_change = 0;
+ int icon_left_no_change = 0, icon_top_no_change = 0;
+
+ struct gcpro gcpro1, gcpro2;
+
+ i = 0;
+ for (tail = alist; CONSP (tail); tail = Fcdr (tail))
+ i++;
+
+ parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
+ values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
+
+ /* Extract parm names and values into those vectors. */
+
+ i = 0;
+ for (tail = alist; CONSP (tail); tail = Fcdr (tail))
+ {
+ Lisp_Object elt;
+
+ elt = Fcar (tail);
+ parms[i] = Fcar (elt);
+ values[i] = Fcdr (elt);
+ i++;
+ }
+ /* TAIL and ALIST are not used again below here. */
+ alist = tail = Qnil;
+
+ GCPRO2 (*parms, *values);
+ gcpro1.nvars = i;
+ gcpro2.nvars = i;
+
+ /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
+ because their values appear in VALUES and strings are not valid. */
+ top = left = Qunbound;
+ icon_left = icon_top = Qunbound;
+
+ /* Provide default values for HEIGHT and WIDTH. */
+ if (FRAME_NEW_WIDTH (f))
+ width = FRAME_NEW_WIDTH (f);
+ else
+ width = FRAME_WIDTH (f);
+
+ if (FRAME_NEW_HEIGHT (f))
+ height = FRAME_NEW_HEIGHT (f);
+ else
+ height = FRAME_HEIGHT (f);
+
+ /* Process foreground_color and background_color before anything else.
+ They are independent of other properties, but other properties (e.g.,
+ cursor_color) are dependent upon them. */
+ for (p = 0; p < i; p++)
+ {
+ Lisp_Object prop, val;
+
+ prop = parms[p];
+ val = values[p];
+ if (EQ (prop, Qforeground_color) || EQ (prop, Qbackground_color))
+ {
+ register Lisp_Object param_index, old_value;
+
+ param_index = Fget (prop, Qx_frame_parameter);
+ old_value = get_frame_param (f, prop);
+ store_frame_param (f, prop, val);
+ if (NATNUMP (param_index)
+ && (XFASTINT (param_index)
+ < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
+ (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
+ }
+ }
+
+ /* Now process them in reverse of specified order. */
+ for (i--; i >= 0; i--)
+ {
+ Lisp_Object prop, val;
+
+ prop = parms[i];
+ val = values[i];
+
+ if (EQ (prop, Qwidth) && NUMBERP (val))
+ width = XFASTINT (val);
+ else if (EQ (prop, Qheight) && NUMBERP (val))
+ height = XFASTINT (val);
+ else if (EQ (prop, Qtop))
+ top = val;
+ else if (EQ (prop, Qleft))
+ left = val;
+ else if (EQ (prop, Qicon_top))
+ icon_top = val;
+ else if (EQ (prop, Qicon_left))
+ icon_left = val;
+ else if (EQ (prop, Qforeground_color) || EQ (prop, Qbackground_color))
+ /* Processed above. */
+ continue;
+ else
+ {
+ register Lisp_Object param_index, old_value;
+
+ param_index = Fget (prop, Qx_frame_parameter);
+ old_value = get_frame_param (f, prop);
+ store_frame_param (f, prop, val);
+ if (NATNUMP (param_index)
+ && (XFASTINT (param_index)
+ < sizeof (x_frame_parms)/sizeof (x_frame_parms[0])))
+ (*x_frame_parms[XINT (param_index)].setter)(f, val, old_value);
+ }
+ }
+
+ /* Don't die if just one of these was set. */
+ if (EQ (left, Qunbound))
+ {
+ left_no_change = 1;
+ if (f->output_data.mac->left_pos < 0)
+ left = Fcons (Qplus,
+ Fcons (make_number (f->output_data.mac->left_pos),
+ Qnil));
+ else
+ XSETINT (left, f->output_data.mac->left_pos);
+ }
+ if (EQ (top, Qunbound))
+ {
+ top_no_change = 1;
+ if (f->output_data.mac->top_pos < 0)
+ top = Fcons (Qplus,
+ Fcons (make_number (f->output_data.mac->top_pos), Qnil));
+ else
+ XSETINT (top, f->output_data.mac->top_pos);
+ }
+
+ /* If one of the icon positions was not set, preserve or default it. */
+ if (EQ (icon_left, Qunbound) || ! INTEGERP (icon_left))
+ {
+ icon_left_no_change = 1;
+ icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
+ if (NILP (icon_left))
+ XSETINT (icon_left, 0);
+ }
+ if (EQ (icon_top, Qunbound) || ! INTEGERP (icon_top))
+ {
+ icon_top_no_change = 1;
+ icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
+ if (NILP (icon_top))
+ XSETINT (icon_top, 0);
+ }
+
+ /* Don't set these parameters unless they've been explicitly
+ specified. The window might be mapped or resized while we're in
+ this function, and we don't want to override that unless the lisp
+ code has asked for it.
+
+ Don't set these parameters unless they actually differ from the
+ window's current parameters; the window may not actually exist
+ yet. */
+ {
+ Lisp_Object frame;
+
+ check_frame_size (f, &height, &width);
+
+ XSETFRAME (frame, f);
+
+ if (width != FRAME_WIDTH (f)
+ || height != FRAME_HEIGHT (f)
+ || FRAME_NEW_HEIGHT (f) || FRAME_NEW_WIDTH (f))
+ Fset_frame_size (frame, make_number (width), make_number (height));
+
+ if ((!NILP (left) || !NILP (top))
+ && ! (left_no_change && top_no_change)
+ && ! (NUMBERP (left) && XINT (left) == f->output_data.mac->left_pos
+ && NUMBERP (top) && XINT (top) == f->output_data.mac->top_pos))
+ {
+ int leftpos = 0;
+ int toppos = 0;
+
+ /* Record the signs. */
+ f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
+ if (EQ (left, Qminus))
+ f->output_data.mac->size_hint_flags |= XNegative;
+ else if (INTEGERP (left))
+ {
+ leftpos = XINT (left);
+ if (leftpos < 0)
+ f->output_data.mac->size_hint_flags |= XNegative;
+ }
+ else if (CONSP (left) && EQ (XCAR (left), Qminus)
+ && CONSP (XCDR (left))
+ && INTEGERP (XCAR (XCDR (left))))
+ {
+ leftpos = - XINT (XCAR (XCDR (left)));
+ f->output_data.mac->size_hint_flags |= XNegative;
+ }
+ else if (CONSP (left) && EQ (XCAR (left), Qplus)
+ && CONSP (XCDR (left))
+ && INTEGERP (XCAR (XCDR (left))))
+ {
+ leftpos = XINT (XCAR (XCDR (left)));
+ }
+
+ if (EQ (top, Qminus))
+ f->output_data.mac->size_hint_flags |= YNegative;
+ else if (INTEGERP (top))
+ {
+ toppos = XINT (top);
+ if (toppos < 0)
+ f->output_data.mac->size_hint_flags |= YNegative;
+ }
+ else if (CONSP (top) && EQ (XCAR (top), Qminus)
+ && CONSP (XCDR (top))
+ && INTEGERP (XCAR (XCDR (top))))
+ {
+ toppos = - XINT (XCAR (XCDR (top)));
+ f->output_data.mac->size_hint_flags |= YNegative;
+ }
+ else if (CONSP (top) && EQ (XCAR (top), Qplus)
+ && CONSP (XCDR (top))
+ && INTEGERP (XCAR (XCDR (top))))
+ {
+ toppos = XINT (XCAR (XCDR (top)));
+ }
+
+
+ /* Store the numeric value of the position. */
+ f->output_data.mac->top_pos = toppos;
+ f->output_data.mac->left_pos = leftpos;
+
+ f->output_data.mac->win_gravity = NorthWestGravity;
+
+ /* Actually set that position, and convert to absolute. */
+ x_set_offset (f, leftpos, toppos, -1);
+ }
+
+ if ((!NILP (icon_left) || !NILP (icon_top))
+ && ! (icon_left_no_change && icon_top_no_change))
+ x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
+ }
+
+ UNGCPRO;
+}
+
+/* Store the screen positions of frame F into XPTR and YPTR.
+ These are the positions of the containing window manager window,
+ not Emacs's own window. */
+
+void
+x_real_positions (f, xptr, yptr)
+ FRAME_PTR f;
+ int *xptr, *yptr;
+{
+ Point pt;
+ GrafPtr oldport;
+
+#ifdef TARGET_API_MAC_CARBON
+ {
+ Rect r;
+
+ GetWindowPortBounds (f->output_data.mac->mWP, &r);
+ SetPt (&pt, r.left, r.top);
+ }
+#else /* not TARGET_API_MAC_CARBON */
+ SetPt (&pt,
+ f->output_data.mac->mWP->portRect.left,
+ f->output_data.mac->mWP->portRect.top);
+#endif /* not TARGET_API_MAC_CARBON */
+ GetPort (&oldport);
+ LocalToGlobal (&pt);
+ SetPort (oldport);
+
+ *xptr = pt.h;
+ *yptr = pt.v;
+}
+
+/* Insert a description of internally-recorded parameters of frame X
+ into the parameter alist *ALISTPTR that is to be given to the user.
+ Only parameters that are specific to Mac and whose values are not
+ correctly recorded in the frame's param_alist need to be considered
+ here. */
+
+void
+x_report_frame_params (f, alistptr)
+ struct frame *f;
+ Lisp_Object *alistptr;
+{
+ char buf[16];
+ Lisp_Object tem;
+
+ /* Represent negative positions (off the top or left screen edge)
+ in a way that Fmodify_frame_parameters will understand correctly. */
+ XSETINT (tem, f->output_data.mac->left_pos);
+ if (f->output_data.mac->left_pos >= 0)
+ store_in_alist (alistptr, Qleft, tem);
+ else
+ store_in_alist (alistptr, Qleft, Fcons (Qplus, Fcons (tem, Qnil)));
+
+ XSETINT (tem, f->output_data.mac->top_pos);
+ if (f->output_data.mac->top_pos >= 0)
+ store_in_alist (alistptr, Qtop, tem);
+ else
+ store_in_alist (alistptr, Qtop, Fcons (Qplus, Fcons (tem, Qnil)));
+
+ store_in_alist (alistptr, Qborder_width,
+ make_number (f->output_data.mac->border_width));
+ store_in_alist (alistptr, Qinternal_border_width,
+ make_number (f->output_data.mac->internal_border_width));
+ sprintf (buf, "%ld", (long) FRAME_MAC_WINDOW (f));
+ store_in_alist (alistptr, Qwindow_id,
+ build_string (buf));
+ store_in_alist (alistptr, Qicon_name, f->icon_name);
+ FRAME_SAMPLE_VISIBILITY (f);
+ store_in_alist (alistptr, Qvisibility,
+ (FRAME_VISIBLE_P (f) ? Qt
+ : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
+ store_in_alist (alistptr, Qdisplay,
+ XCAR (FRAME_MAC_DISPLAY_INFO (f)->name_list_element));
+}
+\f
+/* The default colors for the Mac color map */
+typedef struct colormap_t
+{
+ unsigned long color;
+ char *name;
+} colormap_t;
+
+colormap_t mac_color_map[] =
+{
+ { RGB_TO_ULONG(255, 250, 250), "snow" },
+ { RGB_TO_ULONG(248, 248, 255), "ghost white" },
+ { RGB_TO_ULONG(248, 248, 255), "GhostWhite" },
+ { RGB_TO_ULONG(245, 245, 245), "white smoke" },
+ { RGB_TO_ULONG(245, 245, 245), "WhiteSmoke" },
+ { RGB_TO_ULONG(220, 220, 220), "gainsboro" },
+ { RGB_TO_ULONG(255, 250, 240), "floral white" },
+ { RGB_TO_ULONG(255, 250, 240), "FloralWhite" },
+ { RGB_TO_ULONG(253, 245, 230), "old lace" },
+ { RGB_TO_ULONG(253, 245, 230), "OldLace" },
+ { RGB_TO_ULONG(250, 240, 230), "linen" },
+ { RGB_TO_ULONG(250, 235, 215), "antique white" },
+ { RGB_TO_ULONG(250, 235, 215), "AntiqueWhite" },
+ { RGB_TO_ULONG(255, 239, 213), "papaya whip" },
+ { RGB_TO_ULONG(255, 239, 213), "PapayaWhip" },
+ { RGB_TO_ULONG(255, 235, 205), "blanched almond" },
+ { RGB_TO_ULONG(255, 235, 205), "BlanchedAlmond" },
+ { RGB_TO_ULONG(255, 228, 196), "bisque" },
+ { RGB_TO_ULONG(255, 218, 185), "peach puff" },
+ { RGB_TO_ULONG(255, 218, 185), "PeachPuff" },
+ { RGB_TO_ULONG(255, 222, 173), "navajo white" },
+ { RGB_TO_ULONG(255, 222, 173), "NavajoWhite" },
+ { RGB_TO_ULONG(255, 228, 181), "moccasin" },
+ { RGB_TO_ULONG(255, 248, 220), "cornsilk" },
+ { RGB_TO_ULONG(255, 255, 240), "ivory" },
+ { RGB_TO_ULONG(255, 250, 205), "lemon chiffon" },
+ { RGB_TO_ULONG(255, 250, 205), "LemonChiffon" },
+ { RGB_TO_ULONG(255, 245, 238), "seashell" },
+ { RGB_TO_ULONG(240, 255, 240), "honeydew" },
+ { RGB_TO_ULONG(245, 255, 250), "mint cream" },
+ { RGB_TO_ULONG(245, 255, 250), "MintCream" },
+ { RGB_TO_ULONG(240, 255, 255), "azure" },
+ { RGB_TO_ULONG(240, 248, 255), "alice blue" },
+ { RGB_TO_ULONG(240, 248, 255), "AliceBlue" },
+ { RGB_TO_ULONG(230, 230, 250), "lavender" },
+ { RGB_TO_ULONG(255, 240, 245), "lavender blush" },
+ { RGB_TO_ULONG(255, 240, 245), "LavenderBlush" },
+ { RGB_TO_ULONG(255, 228, 225), "misty rose" },
+ { RGB_TO_ULONG(255, 228, 225), "MistyRose" },
+ { RGB_TO_ULONG(255, 255, 255), "white" },
+ { RGB_TO_ULONG(0 , 0 , 0 ), "black" },
+ { RGB_TO_ULONG(47 , 79 , 79 ), "dark slate gray" },
+ { RGB_TO_ULONG(47 , 79 , 79 ), "DarkSlateGray" },
+ { RGB_TO_ULONG(47 , 79 , 79 ), "dark slate grey" },
+ { RGB_TO_ULONG(47 , 79 , 79 ), "DarkSlateGrey" },
+ { RGB_TO_ULONG(105, 105, 105), "dim gray" },
+ { RGB_TO_ULONG(105, 105, 105), "DimGray" },
+ { RGB_TO_ULONG(105, 105, 105), "dim grey" },
+ { RGB_TO_ULONG(105, 105, 105), "DimGrey" },
+ { RGB_TO_ULONG(112, 128, 144), "slate gray" },
+ { RGB_TO_ULONG(112, 128, 144), "SlateGray" },
+ { RGB_TO_ULONG(112, 128, 144), "slate grey" },
+ { RGB_TO_ULONG(112, 128, 144), "SlateGrey" },
+ { RGB_TO_ULONG(119, 136, 153), "light slate gray" },
+ { RGB_TO_ULONG(119, 136, 153), "LightSlateGray" },
+ { RGB_TO_ULONG(119, 136, 153), "light slate grey" },
+ { RGB_TO_ULONG(119, 136, 153), "LightSlateGrey" },
+ { RGB_TO_ULONG(190, 190, 190), "gray" },
+ { RGB_TO_ULONG(190, 190, 190), "grey" },
+ { RGB_TO_ULONG(211, 211, 211), "light grey" },
+ { RGB_TO_ULONG(211, 211, 211), "LightGrey" },
+ { RGB_TO_ULONG(211, 211, 211), "light gray" },
+ { RGB_TO_ULONG(211, 211, 211), "LightGray" },
+ { RGB_TO_ULONG(25 , 25 , 112), "midnight blue" },
+ { RGB_TO_ULONG(25 , 25 , 112), "MidnightBlue" },
+ { RGB_TO_ULONG(0 , 0 , 128), "navy" },
+ { RGB_TO_ULONG(0 , 0 , 128), "navy blue" },
+ { RGB_TO_ULONG(0 , 0 , 128), "NavyBlue" },
+ { RGB_TO_ULONG(100, 149, 237), "cornflower blue" },
+ { RGB_TO_ULONG(100, 149, 237), "CornflowerBlue" },
+ { RGB_TO_ULONG(72 , 61 , 139), "dark slate blue" },
+ { RGB_TO_ULONG(72 , 61 , 139), "DarkSlateBlue" },
+ { RGB_TO_ULONG(106, 90 , 205), "slate blue" },
+ { RGB_TO_ULONG(106, 90 , 205), "SlateBlue" },
+ { RGB_TO_ULONG(123, 104, 238), "medium slate blue" },
+ { RGB_TO_ULONG(123, 104, 238), "MediumSlateBlue" },
+ { RGB_TO_ULONG(132, 112, 255), "light slate blue" },
+ { RGB_TO_ULONG(132, 112, 255), "LightSlateBlue" },
+ { RGB_TO_ULONG(0 , 0 , 205), "medium blue" },
+ { RGB_TO_ULONG(0 , 0 , 205), "MediumBlue" },
+ { RGB_TO_ULONG(65 , 105, 225), "royal blue" },
+ { RGB_TO_ULONG(65 , 105, 225), "RoyalBlue" },
+ { RGB_TO_ULONG(0 , 0 , 255), "blue" },
+ { RGB_TO_ULONG(30 , 144, 255), "dodger blue" },
+ { RGB_TO_ULONG(30 , 144, 255), "DodgerBlue" },
+ { RGB_TO_ULONG(0 , 191, 255), "deep sky blue" },
+ { RGB_TO_ULONG(0 , 191, 255), "DeepSkyBlue" },
+ { RGB_TO_ULONG(135, 206, 235), "sky blue" },
+ { RGB_TO_ULONG(135, 206, 235), "SkyBlue" },
+ { RGB_TO_ULONG(135, 206, 250), "light sky blue" },
+ { RGB_TO_ULONG(135, 206, 250), "LightSkyBlue" },
+ { RGB_TO_ULONG(70 , 130, 180), "steel blue" },
+ { RGB_TO_ULONG(70 , 130, 180), "SteelBlue" },
+ { RGB_TO_ULONG(176, 196, 222), "light steel blue" },
+ { RGB_TO_ULONG(176, 196, 222), "LightSteelBlue" },
+ { RGB_TO_ULONG(173, 216, 230), "light blue" },
+ { RGB_TO_ULONG(173, 216, 230), "LightBlue" },
+ { RGB_TO_ULONG(176, 224, 230), "powder blue" },
+ { RGB_TO_ULONG(176, 224, 230), "PowderBlue" },
+ { RGB_TO_ULONG(175, 238, 238), "pale turquoise" },
+ { RGB_TO_ULONG(175, 238, 238), "PaleTurquoise" },
+ { RGB_TO_ULONG(0 , 206, 209), "dark turquoise" },
+ { RGB_TO_ULONG(0 , 206, 209), "DarkTurquoise" },
+ { RGB_TO_ULONG(72 , 209, 204), "medium turquoise" },
+ { RGB_TO_ULONG(72 , 209, 204), "MediumTurquoise" },
+ { RGB_TO_ULONG(64 , 224, 208), "turquoise" },
+ { RGB_TO_ULONG(0 , 255, 255), "cyan" },
+ { RGB_TO_ULONG(224, 255, 255), "light cyan" },
+ { RGB_TO_ULONG(224, 255, 255), "LightCyan" },
+ { RGB_TO_ULONG(95 , 158, 160), "cadet blue" },
+ { RGB_TO_ULONG(95 , 158, 160), "CadetBlue" },
+ { RGB_TO_ULONG(102, 205, 170), "medium aquamarine" },
+ { RGB_TO_ULONG(102, 205, 170), "MediumAquamarine" },
+ { RGB_TO_ULONG(127, 255, 212), "aquamarine" },
+ { RGB_TO_ULONG(0 , 100, 0 ), "dark green" },
+ { RGB_TO_ULONG(0 , 100, 0 ), "DarkGreen" },
+ { RGB_TO_ULONG(85 , 107, 47 ), "dark olive green" },
+ { RGB_TO_ULONG(85 , 107, 47 ), "DarkOliveGreen" },
+ { RGB_TO_ULONG(143, 188, 143), "dark sea green" },
+ { RGB_TO_ULONG(143, 188, 143), "DarkSeaGreen" },
+ { RGB_TO_ULONG(46 , 139, 87 ), "sea green" },
+ { RGB_TO_ULONG(46 , 139, 87 ), "SeaGreen" },
+ { RGB_TO_ULONG(60 , 179, 113), "medium sea green" },
+ { RGB_TO_ULONG(60 , 179, 113), "MediumSeaGreen" },
+ { RGB_TO_ULONG(32 , 178, 170), "light sea green" },
+ { RGB_TO_ULONG(32 , 178, 170), "LightSeaGreen" },
+ { RGB_TO_ULONG(152, 251, 152), "pale green" },
+ { RGB_TO_ULONG(152, 251, 152), "PaleGreen" },
+ { RGB_TO_ULONG(0 , 255, 127), "spring green" },
+ { RGB_TO_ULONG(0 , 255, 127), "SpringGreen" },
+ { RGB_TO_ULONG(124, 252, 0 ), "lawn green" },
+ { RGB_TO_ULONG(124, 252, 0 ), "LawnGreen" },
+ { RGB_TO_ULONG(0 , 255, 0 ), "green" },
+ { RGB_TO_ULONG(127, 255, 0 ), "chartreuse" },
+ { RGB_TO_ULONG(0 , 250, 154), "medium spring green" },
+ { RGB_TO_ULONG(0 , 250, 154), "MediumSpringGreen" },
+ { RGB_TO_ULONG(173, 255, 47 ), "green yellow" },
+ { RGB_TO_ULONG(173, 255, 47 ), "GreenYellow" },
+ { RGB_TO_ULONG(50 , 205, 50 ), "lime green" },
+ { RGB_TO_ULONG(50 , 205, 50 ), "LimeGreen" },
+ { RGB_TO_ULONG(154, 205, 50 ), "yellow green" },
+ { RGB_TO_ULONG(154, 205, 50 ), "YellowGreen" },
+ { RGB_TO_ULONG(34 , 139, 34 ), "forest green" },
+ { RGB_TO_ULONG(34 , 139, 34 ), "ForestGreen" },
+ { RGB_TO_ULONG(107, 142, 35 ), "olive drab" },
+ { RGB_TO_ULONG(107, 142, 35 ), "OliveDrab" },
+ { RGB_TO_ULONG(189, 183, 107), "dark khaki" },
+ { RGB_TO_ULONG(189, 183, 107), "DarkKhaki" },
+ { RGB_TO_ULONG(240, 230, 140), "khaki" },
+ { RGB_TO_ULONG(238, 232, 170), "pale goldenrod" },
+ { RGB_TO_ULONG(238, 232, 170), "PaleGoldenrod" },
+ { RGB_TO_ULONG(250, 250, 210), "light goldenrod yellow" },
+ { RGB_TO_ULONG(250, 250, 210), "LightGoldenrodYellow" },
+ { RGB_TO_ULONG(255, 255, 224), "light yellow" },
+ { RGB_TO_ULONG(255, 255, 224), "LightYellow" },
+ { RGB_TO_ULONG(255, 255, 0 ), "yellow" },
+ { RGB_TO_ULONG(255, 215, 0 ), "gold" },
+ { RGB_TO_ULONG(238, 221, 130), "light goldenrod" },
+ { RGB_TO_ULONG(238, 221, 130), "LightGoldenrod" },
+ { RGB_TO_ULONG(218, 165, 32 ), "goldenrod" },
+ { RGB_TO_ULONG(184, 134, 11 ), "dark goldenrod" },
+ { RGB_TO_ULONG(184, 134, 11 ), "DarkGoldenrod" },
+ { RGB_TO_ULONG(188, 143, 143), "rosy brown" },
+ { RGB_TO_ULONG(188, 143, 143), "RosyBrown" },
+ { RGB_TO_ULONG(205, 92 , 92 ), "indian red" },
+ { RGB_TO_ULONG(205, 92 , 92 ), "IndianRed" },
+ { RGB_TO_ULONG(139, 69 , 19 ), "saddle brown" },
+ { RGB_TO_ULONG(139, 69 , 19 ), "SaddleBrown" },
+ { RGB_TO_ULONG(160, 82 , 45 ), "sienna" },
+ { RGB_TO_ULONG(205, 133, 63 ), "peru" },
+ { RGB_TO_ULONG(222, 184, 135), "burlywood" },
+ { RGB_TO_ULONG(245, 245, 220), "beige" },
+ { RGB_TO_ULONG(245, 222, 179), "wheat" },
+ { RGB_TO_ULONG(244, 164, 96 ), "sandy brown" },
+ { RGB_TO_ULONG(244, 164, 96 ), "SandyBrown" },
+ { RGB_TO_ULONG(210, 180, 140), "tan" },
+ { RGB_TO_ULONG(210, 105, 30 ), "chocolate" },
+ { RGB_TO_ULONG(178, 34 , 34 ), "firebrick" },
+ { RGB_TO_ULONG(165, 42 , 42 ), "brown" },
+ { RGB_TO_ULONG(233, 150, 122), "dark salmon" },
+ { RGB_TO_ULONG(233, 150, 122), "DarkSalmon" },
+ { RGB_TO_ULONG(250, 128, 114), "salmon" },
+ { RGB_TO_ULONG(255, 160, 122), "light salmon" },
+ { RGB_TO_ULONG(255, 160, 122), "LightSalmon" },
+ { RGB_TO_ULONG(255, 165, 0 ), "orange" },
+ { RGB_TO_ULONG(255, 140, 0 ), "dark orange" },
+ { RGB_TO_ULONG(255, 140, 0 ), "DarkOrange" },
+ { RGB_TO_ULONG(255, 127, 80 ), "coral" },
+ { RGB_TO_ULONG(240, 128, 128), "light coral" },
+ { RGB_TO_ULONG(240, 128, 128), "LightCoral" },
+ { RGB_TO_ULONG(255, 99 , 71 ), "tomato" },
+ { RGB_TO_ULONG(255, 69 , 0 ), "orange red" },
+ { RGB_TO_ULONG(255, 69 , 0 ), "OrangeRed" },
+ { RGB_TO_ULONG(255, 0 , 0 ), "red" },
+ { RGB_TO_ULONG(255, 105, 180), "hot pink" },
+ { RGB_TO_ULONG(255, 105, 180), "HotPink" },
+ { RGB_TO_ULONG(255, 20 , 147), "deep pink" },
+ { RGB_TO_ULONG(255, 20 , 147), "DeepPink" },
+ { RGB_TO_ULONG(255, 192, 203), "pink" },
+ { RGB_TO_ULONG(255, 182, 193), "light pink" },
+ { RGB_TO_ULONG(255, 182, 193), "LightPink" },
+ { RGB_TO_ULONG(219, 112, 147), "pale violet red" },
+ { RGB_TO_ULONG(219, 112, 147), "PaleVioletRed" },
+ { RGB_TO_ULONG(176, 48 , 96 ), "maroon" },
+ { RGB_TO_ULONG(199, 21 , 133), "medium violet red" },
+ { RGB_TO_ULONG(199, 21 , 133), "MediumVioletRed" },
+ { RGB_TO_ULONG(208, 32 , 144), "violet red" },
+ { RGB_TO_ULONG(208, 32 , 144), "VioletRed" },
+ { RGB_TO_ULONG(255, 0 , 255), "magenta" },
+ { RGB_TO_ULONG(238, 130, 238), "violet" },
+ { RGB_TO_ULONG(221, 160, 221), "plum" },
+ { RGB_TO_ULONG(218, 112, 214), "orchid" },
+ { RGB_TO_ULONG(186, 85 , 211), "medium orchid" },
+ { RGB_TO_ULONG(186, 85 , 211), "MediumOrchid" },
+ { RGB_TO_ULONG(153, 50 , 204), "dark orchid" },
+ { RGB_TO_ULONG(153, 50 , 204), "DarkOrchid" },
+ { RGB_TO_ULONG(148, 0 , 211), "dark violet" },
+ { RGB_TO_ULONG(148, 0 , 211), "DarkViolet" },
+ { RGB_TO_ULONG(138, 43 , 226), "blue violet" },
+ { RGB_TO_ULONG(138, 43 , 226), "BlueViolet" },
+ { RGB_TO_ULONG(160, 32 , 240), "purple" },
+ { RGB_TO_ULONG(147, 112, 219), "medium purple" },
+ { RGB_TO_ULONG(147, 112, 219), "MediumPurple" },
+ { RGB_TO_ULONG(216, 191, 216), "thistle" },
+ { RGB_TO_ULONG(255, 250, 250), "snow1" },
+ { RGB_TO_ULONG(238, 233, 233), "snow2" },
+ { RGB_TO_ULONG(205, 201, 201), "snow3" },
+ { RGB_TO_ULONG(139, 137, 137), "snow4" },
+ { RGB_TO_ULONG(255, 245, 238), "seashell1" },
+ { RGB_TO_ULONG(238, 229, 222), "seashell2" },
+ { RGB_TO_ULONG(205, 197, 191), "seashell3" },
+ { RGB_TO_ULONG(139, 134, 130), "seashell4" },
+ { RGB_TO_ULONG(255, 239, 219), "AntiqueWhite1" },
+ { RGB_TO_ULONG(238, 223, 204), "AntiqueWhite2" },
+ { RGB_TO_ULONG(205, 192, 176), "AntiqueWhite3" },
+ { RGB_TO_ULONG(139, 131, 120), "AntiqueWhite4" },
+ { RGB_TO_ULONG(255, 228, 196), "bisque1" },
+ { RGB_TO_ULONG(238, 213, 183), "bisque2" },
+ { RGB_TO_ULONG(205, 183, 158), "bisque3" },
+ { RGB_TO_ULONG(139, 125, 107), "bisque4" },
+ { RGB_TO_ULONG(255, 218, 185), "PeachPuff1" },
+ { RGB_TO_ULONG(238, 203, 173), "PeachPuff2" },
+ { RGB_TO_ULONG(205, 175, 149), "PeachPuff3" },
+ { RGB_TO_ULONG(139, 119, 101), "PeachPuff4" },
+ { RGB_TO_ULONG(255, 222, 173), "NavajoWhite1" },
+ { RGB_TO_ULONG(238, 207, 161), "NavajoWhite2" },
+ { RGB_TO_ULONG(205, 179, 139), "NavajoWhite3" },
+ { RGB_TO_ULONG(139, 121, 94), "NavajoWhite4" },
+ { RGB_TO_ULONG(255, 250, 205), "LemonChiffon1" },
+ { RGB_TO_ULONG(238, 233, 191), "LemonChiffon2" },
+ { RGB_TO_ULONG(205, 201, 165), "LemonChiffon3" },
+ { RGB_TO_ULONG(139, 137, 112), "LemonChiffon4" },
+ { RGB_TO_ULONG(255, 248, 220), "cornsilk1" },
+ { RGB_TO_ULONG(238, 232, 205), "cornsilk2" },
+ { RGB_TO_ULONG(205, 200, 177), "cornsilk3" },
+ { RGB_TO_ULONG(139, 136, 120), "cornsilk4" },
+ { RGB_TO_ULONG(255, 255, 240), "ivory1" },
+ { RGB_TO_ULONG(238, 238, 224), "ivory2" },
+ { RGB_TO_ULONG(205, 205, 193), "ivory3" },
+ { RGB_TO_ULONG(139, 139, 131), "ivory4" },
+ { RGB_TO_ULONG(240, 255, 240), "honeydew1" },
+ { RGB_TO_ULONG(224, 238, 224), "honeydew2" },
+ { RGB_TO_ULONG(193, 205, 193), "honeydew3" },
+ { RGB_TO_ULONG(131, 139, 131), "honeydew4" },
+ { RGB_TO_ULONG(255, 240, 245), "LavenderBlush1" },
+ { RGB_TO_ULONG(238, 224, 229), "LavenderBlush2" },
+ { RGB_TO_ULONG(205, 193, 197), "LavenderBlush3" },
+ { RGB_TO_ULONG(139, 131, 134), "LavenderBlush4" },
+ { RGB_TO_ULONG(255, 228, 225), "MistyRose1" },
+ { RGB_TO_ULONG(238, 213, 210), "MistyRose2" },
+ { RGB_TO_ULONG(205, 183, 181), "MistyRose3" },
+ { RGB_TO_ULONG(139, 125, 123), "MistyRose4" },
+ { RGB_TO_ULONG(240, 255, 255), "azure1" },
+ { RGB_TO_ULONG(224, 238, 238), "azure2" },
+ { RGB_TO_ULONG(193, 205, 205), "azure3" },
+ { RGB_TO_ULONG(131, 139, 139), "azure4" },
+ { RGB_TO_ULONG(131, 111, 255), "SlateBlue1" },
+ { RGB_TO_ULONG(122, 103, 238), "SlateBlue2" },
+ { RGB_TO_ULONG(105, 89 , 205), "SlateBlue3" },
+ { RGB_TO_ULONG(71 , 60 , 139), "SlateBlue4" },
+ { RGB_TO_ULONG(72 , 118, 255), "RoyalBlue1" },
+ { RGB_TO_ULONG(67 , 110, 238), "RoyalBlue2" },
+ { RGB_TO_ULONG(58 , 95 , 205), "RoyalBlue3" },
+ { RGB_TO_ULONG(39 , 64 , 139), "RoyalBlue4" },
+ { RGB_TO_ULONG(0 , 0 , 255), "blue1" },
+ { RGB_TO_ULONG(0 , 0 , 238), "blue2" },
+ { RGB_TO_ULONG(0 , 0 , 205), "blue3" },
+ { RGB_TO_ULONG(0 , 0 , 139), "blue4" },
+ { RGB_TO_ULONG(30 , 144, 255), "DodgerBlue1" },
+ { RGB_TO_ULONG(28 , 134, 238), "DodgerBlue2" },
+ { RGB_TO_ULONG(24 , 116, 205), "DodgerBlue3" },
+ { RGB_TO_ULONG(16 , 78 , 139), "DodgerBlue4" },
+ { RGB_TO_ULONG(99 , 184, 255), "SteelBlue1" },
+ { RGB_TO_ULONG(92 , 172, 238), "SteelBlue2" },
+ { RGB_TO_ULONG(79 , 148, 205), "SteelBlue3" },
+ { RGB_TO_ULONG(54 , 100, 139), "SteelBlue4" },
+ { RGB_TO_ULONG(0 , 191, 255), "DeepSkyBlue1" },
+ { RGB_TO_ULONG(0 , 178, 238), "DeepSkyBlue2" },
+ { RGB_TO_ULONG(0 , 154, 205), "DeepSkyBlue3" },
+ { RGB_TO_ULONG(0 , 104, 139), "DeepSkyBlue4" },
+ { RGB_TO_ULONG(135, 206, 255), "SkyBlue1" },
+ { RGB_TO_ULONG(126, 192, 238), "SkyBlue2" },
+ { RGB_TO_ULONG(108, 166, 205), "SkyBlue3" },
+ { RGB_TO_ULONG(74 , 112, 139), "SkyBlue4" },
+ { RGB_TO_ULONG(176, 226, 255), "LightSkyBlue1" },
+ { RGB_TO_ULONG(164, 211, 238), "LightSkyBlue2" },
+ { RGB_TO_ULONG(141, 182, 205), "LightSkyBlue3" },
+ { RGB_TO_ULONG(96 , 123, 139), "LightSkyBlue4" },
+ { RGB_TO_ULONG(198, 226, 255), "SlateGray1" },
+ { RGB_TO_ULONG(185, 211, 238), "SlateGray2" },
+ { RGB_TO_ULONG(159, 182, 205), "SlateGray3" },
+ { RGB_TO_ULONG(108, 123, 139), "SlateGray4" },
+ { RGB_TO_ULONG(202, 225, 255), "LightSteelBlue1" },
+ { RGB_TO_ULONG(188, 210, 238), "LightSteelBlue2" },
+ { RGB_TO_ULONG(162, 181, 205), "LightSteelBlue3" },
+ { RGB_TO_ULONG(110, 123, 139), "LightSteelBlue4" },
+ { RGB_TO_ULONG(191, 239, 255), "LightBlue1" },
+ { RGB_TO_ULONG(178, 223, 238), "LightBlue2" },
+ { RGB_TO_ULONG(154, 192, 205), "LightBlue3" },
+ { RGB_TO_ULONG(104, 131, 139), "LightBlue4" },
+ { RGB_TO_ULONG(224, 255, 255), "LightCyan1" },
+ { RGB_TO_ULONG(209, 238, 238), "LightCyan2" },
+ { RGB_TO_ULONG(180, 205, 205), "LightCyan3" },
+ { RGB_TO_ULONG(122, 139, 139), "LightCyan4" },
+ { RGB_TO_ULONG(187, 255, 255), "PaleTurquoise1" },
+ { RGB_TO_ULONG(174, 238, 238), "PaleTurquoise2" },
+ { RGB_TO_ULONG(150, 205, 205), "PaleTurquoise3" },
+ { RGB_TO_ULONG(102, 139, 139), "PaleTurquoise4" },
+ { RGB_TO_ULONG(152, 245, 255), "CadetBlue1" },
+ { RGB_TO_ULONG(142, 229, 238), "CadetBlue2" },
+ { RGB_TO_ULONG(122, 197, 205), "CadetBlue3" },
+ { RGB_TO_ULONG(83 , 134, 139), "CadetBlue4" },
+ { RGB_TO_ULONG(0 , 245, 255), "turquoise1" },
+ { RGB_TO_ULONG(0 , 229, 238), "turquoise2" },
+ { RGB_TO_ULONG(0 , 197, 205), "turquoise3" },
+ { RGB_TO_ULONG(0 , 134, 139), "turquoise4" },
+ { RGB_TO_ULONG(0 , 255, 255), "cyan1" },
+ { RGB_TO_ULONG(0 , 238, 238), "cyan2" },
+ { RGB_TO_ULONG(0 , 205, 205), "cyan3" },
+ { RGB_TO_ULONG(0 , 139, 139), "cyan4" },
+ { RGB_TO_ULONG(151, 255, 255), "DarkSlateGray1" },
+ { RGB_TO_ULONG(141, 238, 238), "DarkSlateGray2" },
+ { RGB_TO_ULONG(121, 205, 205), "DarkSlateGray3" },
+ { RGB_TO_ULONG(82 , 139, 139), "DarkSlateGray4" },
+ { RGB_TO_ULONG(127, 255, 212), "aquamarine1" },
+ { RGB_TO_ULONG(118, 238, 198), "aquamarine2" },
+ { RGB_TO_ULONG(102, 205, 170), "aquamarine3" },
+ { RGB_TO_ULONG(69 , 139, 116), "aquamarine4" },
+ { RGB_TO_ULONG(193, 255, 193), "DarkSeaGreen1" },
+ { RGB_TO_ULONG(180, 238, 180), "DarkSeaGreen2" },
+ { RGB_TO_ULONG(155, 205, 155), "DarkSeaGreen3" },
+ { RGB_TO_ULONG(105, 139, 105), "DarkSeaGreen4" },
+ { RGB_TO_ULONG(84 , 255, 159), "SeaGreen1" },
+ { RGB_TO_ULONG(78 , 238, 148), "SeaGreen2" },
+ { RGB_TO_ULONG(67 , 205, 128), "SeaGreen3" },
+ { RGB_TO_ULONG(46 , 139, 87 ), "SeaGreen4" },
+ { RGB_TO_ULONG(154, 255, 154), "PaleGreen1" },
+ { RGB_TO_ULONG(144, 238, 144), "PaleGreen2" },
+ { RGB_TO_ULONG(124, 205, 124), "PaleGreen3" },
+ { RGB_TO_ULONG(84 , 139, 84 ), "PaleGreen4" },
+ { RGB_TO_ULONG(0 , 255, 127), "SpringGreen1" },
+ { RGB_TO_ULONG(0 , 238, 118), "SpringGreen2" },
+ { RGB_TO_ULONG(0 , 205, 102), "SpringGreen3" },
+ { RGB_TO_ULONG(0 , 139, 69 ), "SpringGreen4" },
+ { RGB_TO_ULONG(0 , 255, 0 ), "green1" },
+ { RGB_TO_ULONG(0 , 238, 0 ), "green2" },
+ { RGB_TO_ULONG(0 , 205, 0 ), "green3" },
+ { RGB_TO_ULONG(0 , 139, 0 ), "green4" },
+ { RGB_TO_ULONG(127, 255, 0 ), "chartreuse1" },
+ { RGB_TO_ULONG(118, 238, 0 ), "chartreuse2" },
+ { RGB_TO_ULONG(102, 205, 0 ), "chartreuse3" },
+ { RGB_TO_ULONG(69 , 139, 0 ), "chartreuse4" },
+ { RGB_TO_ULONG(192, 255, 62 ), "OliveDrab1" },
+ { RGB_TO_ULONG(179, 238, 58 ), "OliveDrab2" },
+ { RGB_TO_ULONG(154, 205, 50 ), "OliveDrab3" },
+ { RGB_TO_ULONG(105, 139, 34 ), "OliveDrab4" },
+ { RGB_TO_ULONG(202, 255, 112), "DarkOliveGreen1" },
+ { RGB_TO_ULONG(188, 238, 104), "DarkOliveGreen2" },
+ { RGB_TO_ULONG(162, 205, 90 ), "DarkOliveGreen3" },
+ { RGB_TO_ULONG(110, 139, 61 ), "DarkOliveGreen4" },
+ { RGB_TO_ULONG(255, 246, 143), "khaki1" },
+ { RGB_TO_ULONG(238, 230, 133), "khaki2" },
+ { RGB_TO_ULONG(205, 198, 115), "khaki3" },
+ { RGB_TO_ULONG(139, 134, 78 ), "khaki4" },
+ { RGB_TO_ULONG(255, 236, 139), "LightGoldenrod1" },
+ { RGB_TO_ULONG(238, 220, 130), "LightGoldenrod2" },
+ { RGB_TO_ULONG(205, 190, 112), "LightGoldenrod3" },
+ { RGB_TO_ULONG(139, 129, 76 ), "LightGoldenrod4" },
+ { RGB_TO_ULONG(255, 255, 224), "LightYellow1" },
+ { RGB_TO_ULONG(238, 238, 209), "LightYellow2" },
+ { RGB_TO_ULONG(205, 205, 180), "LightYellow3" },
+ { RGB_TO_ULONG(139, 139, 122), "LightYellow4" },
+ { RGB_TO_ULONG(255, 255, 0 ), "yellow1" },
+ { RGB_TO_ULONG(238, 238, 0 ), "yellow2" },
+ { RGB_TO_ULONG(205, 205, 0 ), "yellow3" },
+ { RGB_TO_ULONG(139, 139, 0 ), "yellow4" },
+ { RGB_TO_ULONG(255, 215, 0 ), "gold1" },
+ { RGB_TO_ULONG(238, 201, 0 ), "gold2" },
+ { RGB_TO_ULONG(205, 173, 0 ), "gold3" },
+ { RGB_TO_ULONG(139, 117, 0 ), "gold4" },
+ { RGB_TO_ULONG(255, 193, 37 ), "goldenrod1" },
+ { RGB_TO_ULONG(238, 180, 34 ), "goldenrod2" },
+ { RGB_TO_ULONG(205, 155, 29 ), "goldenrod3" },
+ { RGB_TO_ULONG(139, 105, 20 ), "goldenrod4" },
+ { RGB_TO_ULONG(255, 185, 15 ), "DarkGoldenrod1" },
+ { RGB_TO_ULONG(238, 173, 14 ), "DarkGoldenrod2" },
+ { RGB_TO_ULONG(205, 149, 12 ), "DarkGoldenrod3" },
+ { RGB_TO_ULONG(139, 101, 8 ), "DarkGoldenrod4" },
+ { RGB_TO_ULONG(255, 193, 193), "RosyBrown1" },
+ { RGB_TO_ULONG(238, 180, 180), "RosyBrown2" },
+ { RGB_TO_ULONG(205, 155, 155), "RosyBrown3" },
+ { RGB_TO_ULONG(139, 105, 105), "RosyBrown4" },
+ { RGB_TO_ULONG(255, 106, 106), "IndianRed1" },
+ { RGB_TO_ULONG(238, 99 , 99 ), "IndianRed2" },
+ { RGB_TO_ULONG(205, 85 , 85 ), "IndianRed3" },
+ { RGB_TO_ULONG(139, 58 , 58 ), "IndianRed4" },
+ { RGB_TO_ULONG(255, 130, 71 ), "sienna1" },
+ { RGB_TO_ULONG(238, 121, 66 ), "sienna2" },
+ { RGB_TO_ULONG(205, 104, 57 ), "sienna3" },
+ { RGB_TO_ULONG(139, 71 , 38 ), "sienna4" },
+ { RGB_TO_ULONG(255, 211, 155), "burlywood1" },
+ { RGB_TO_ULONG(238, 197, 145), "burlywood2" },
+ { RGB_TO_ULONG(205, 170, 125), "burlywood3" },
+ { RGB_TO_ULONG(139, 115, 85 ), "burlywood4" },
+ { RGB_TO_ULONG(255, 231, 186), "wheat1" },
+ { RGB_TO_ULONG(238, 216, 174), "wheat2" },
+ { RGB_TO_ULONG(205, 186, 150), "wheat3" },
+ { RGB_TO_ULONG(139, 126, 102), "wheat4" },
+ { RGB_TO_ULONG(255, 165, 79 ), "tan1" },
+ { RGB_TO_ULONG(238, 154, 73 ), "tan2" },
+ { RGB_TO_ULONG(205, 133, 63 ), "tan3" },
+ { RGB_TO_ULONG(139, 90 , 43 ), "tan4" },
+ { RGB_TO_ULONG(255, 127, 36 ), "chocolate1" },
+ { RGB_TO_ULONG(238, 118, 33 ), "chocolate2" },
+ { RGB_TO_ULONG(205, 102, 29 ), "chocolate3" },
+ { RGB_TO_ULONG(139, 69 , 19 ), "chocolate4" },
+ { RGB_TO_ULONG(255, 48 , 48 ), "firebrick1" },
+ { RGB_TO_ULONG(238, 44 , 44 ), "firebrick2" },
+ { RGB_TO_ULONG(205, 38 , 38 ), "firebrick3" },
+ { RGB_TO_ULONG(139, 26 , 26 ), "firebrick4" },
+ { RGB_TO_ULONG(255, 64 , 64 ), "brown1" },
+ { RGB_TO_ULONG(238, 59 , 59 ), "brown2" },
+ { RGB_TO_ULONG(205, 51 , 51 ), "brown3" },
+ { RGB_TO_ULONG(139, 35 , 35 ), "brown4" },
+ { RGB_TO_ULONG(255, 140, 105), "salmon1" },
+ { RGB_TO_ULONG(238, 130, 98 ), "salmon2" },
+ { RGB_TO_ULONG(205, 112, 84 ), "salmon3" },
+ { RGB_TO_ULONG(139, 76 , 57 ), "salmon4" },
+ { RGB_TO_ULONG(255, 160, 122), "LightSalmon1" },
+ { RGB_TO_ULONG(238, 149, 114), "LightSalmon2" },
+ { RGB_TO_ULONG(205, 129, 98 ), "LightSalmon3" },
+ { RGB_TO_ULONG(139, 87 , 66 ), "LightSalmon4" },
+ { RGB_TO_ULONG(255, 165, 0 ), "orange1" },
+ { RGB_TO_ULONG(238, 154, 0 ), "orange2" },
+ { RGB_TO_ULONG(205, 133, 0 ), "orange3" },
+ { RGB_TO_ULONG(139, 90 , 0 ), "orange4" },
+ { RGB_TO_ULONG(255, 127, 0 ), "DarkOrange1" },
+ { RGB_TO_ULONG(238, 118, 0 ), "DarkOrange2" },
+ { RGB_TO_ULONG(205, 102, 0 ), "DarkOrange3" },
+ { RGB_TO_ULONG(139, 69 , 0 ), "DarkOrange4" },
+ { RGB_TO_ULONG(255, 114, 86 ), "coral1" },
+ { RGB_TO_ULONG(238, 106, 80 ), "coral2" },
+ { RGB_TO_ULONG(205, 91 , 69 ), "coral3" },
+ { RGB_TO_ULONG(139, 62 , 47 ), "coral4" },
+ { RGB_TO_ULONG(255, 99 , 71 ), "tomato1" },
+ { RGB_TO_ULONG(238, 92 , 66 ), "tomato2" },
+ { RGB_TO_ULONG(205, 79 , 57 ), "tomato3" },
+ { RGB_TO_ULONG(139, 54 , 38 ), "tomato4" },
+ { RGB_TO_ULONG(255, 69 , 0 ), "OrangeRed1" },
+ { RGB_TO_ULONG(238, 64 , 0 ), "OrangeRed2" },
+ { RGB_TO_ULONG(205, 55 , 0 ), "OrangeRed3" },
+ { RGB_TO_ULONG(139, 37 , 0 ), "OrangeRed4" },
+ { RGB_TO_ULONG(255, 0 , 0 ), "red1" },
+ { RGB_TO_ULONG(238, 0 , 0 ), "red2" },
+ { RGB_TO_ULONG(205, 0 , 0 ), "red3" },
+ { RGB_TO_ULONG(139, 0 , 0 ), "red4" },
+ { RGB_TO_ULONG(255, 20 , 147), "DeepPink1" },
+ { RGB_TO_ULONG(238, 18 , 137), "DeepPink2" },
+ { RGB_TO_ULONG(205, 16 , 118), "DeepPink3" },
+ { RGB_TO_ULONG(139, 10 , 80 ), "DeepPink4" },
+ { RGB_TO_ULONG(255, 110, 180), "HotPink1" },
+ { RGB_TO_ULONG(238, 106, 167), "HotPink2" },
+ { RGB_TO_ULONG(205, 96 , 144), "HotPink3" },
+ { RGB_TO_ULONG(139, 58 , 98 ), "HotPink4" },
+ { RGB_TO_ULONG(255, 181, 197), "pink1" },
+ { RGB_TO_ULONG(238, 169, 184), "pink2" },
+ { RGB_TO_ULONG(205, 145, 158), "pink3" },
+ { RGB_TO_ULONG(139, 99 , 108), "pink4" },
+ { RGB_TO_ULONG(255, 174, 185), "LightPink1" },
+ { RGB_TO_ULONG(238, 162, 173), "LightPink2" },
+ { RGB_TO_ULONG(205, 140, 149), "LightPink3" },
+ { RGB_TO_ULONG(139, 95 , 101), "LightPink4" },
+ { RGB_TO_ULONG(255, 130, 171), "PaleVioletRed1" },
+ { RGB_TO_ULONG(238, 121, 159), "PaleVioletRed2" },
+ { RGB_TO_ULONG(205, 104, 137), "PaleVioletRed3" },
+ { RGB_TO_ULONG(139, 71 , 93 ), "PaleVioletRed4" },
+ { RGB_TO_ULONG(255, 52 , 179), "maroon1" },
+ { RGB_TO_ULONG(238, 48 , 167), "maroon2" },
+ { RGB_TO_ULONG(205, 41 , 144), "maroon3" },
+ { RGB_TO_ULONG(139, 28 , 98 ), "maroon4" },
+ { RGB_TO_ULONG(255, 62 , 150), "VioletRed1" },
+ { RGB_TO_ULONG(238, 58 , 140), "VioletRed2" },
+ { RGB_TO_ULONG(205, 50 , 120), "VioletRed3" },
+ { RGB_TO_ULONG(139, 34 , 82 ), "VioletRed4" },
+ { RGB_TO_ULONG(255, 0 , 255), "magenta1" },
+ { RGB_TO_ULONG(238, 0 , 238), "magenta2" },
+ { RGB_TO_ULONG(205, 0 , 205), "magenta3" },
+ { RGB_TO_ULONG(139, 0 , 139), "magenta4" },
+ { RGB_TO_ULONG(255, 131, 250), "orchid1" },
+ { RGB_TO_ULONG(238, 122, 233), "orchid2" },
+ { RGB_TO_ULONG(205, 105, 201), "orchid3" },
+ { RGB_TO_ULONG(139, 71 , 137), "orchid4" },
+ { RGB_TO_ULONG(255, 187, 255), "plum1" },
+ { RGB_TO_ULONG(238, 174, 238), "plum2" },
+ { RGB_TO_ULONG(205, 150, 205), "plum3" },
+ { RGB_TO_ULONG(139, 102, 139), "plum4" },
+ { RGB_TO_ULONG(224, 102, 255), "MediumOrchid1" },
+ { RGB_TO_ULONG(209, 95 , 238), "MediumOrchid2" },
+ { RGB_TO_ULONG(180, 82 , 205), "MediumOrchid3" },
+ { RGB_TO_ULONG(122, 55 , 139), "MediumOrchid4" },
+ { RGB_TO_ULONG(191, 62 , 255), "DarkOrchid1" },
+ { RGB_TO_ULONG(178, 58 , 238), "DarkOrchid2" },
+ { RGB_TO_ULONG(154, 50 , 205), "DarkOrchid3" },
+ { RGB_TO_ULONG(104, 34 , 139), "DarkOrchid4" },
+ { RGB_TO_ULONG(155, 48 , 255), "purple1" },
+ { RGB_TO_ULONG(145, 44 , 238), "purple2" },
+ { RGB_TO_ULONG(125, 38 , 205), "purple3" },
+ { RGB_TO_ULONG(85 , 26 , 139), "purple4" },
+ { RGB_TO_ULONG(171, 130, 255), "MediumPurple1" },
+ { RGB_TO_ULONG(159, 121, 238), "MediumPurple2" },
+ { RGB_TO_ULONG(137, 104, 205), "MediumPurple3" },
+ { RGB_TO_ULONG(93 , 71 , 139), "MediumPurple4" },
+ { RGB_TO_ULONG(255, 225, 255), "thistle1" },
+ { RGB_TO_ULONG(238, 210, 238), "thistle2" },
+ { RGB_TO_ULONG(205, 181, 205), "thistle3" },
+ { RGB_TO_ULONG(139, 123, 139), "thistle4" },
+ { RGB_TO_ULONG(0 , 0 , 0 ), "gray0" },
+ { RGB_TO_ULONG(0 , 0 , 0 ), "grey0" },
+ { RGB_TO_ULONG(3 , 3 , 3 ), "gray1" },
+ { RGB_TO_ULONG(3 , 3 , 3 ), "grey1" },
+ { RGB_TO_ULONG(5 , 5 , 5 ), "gray2" },
+ { RGB_TO_ULONG(5 , 5 , 5 ), "grey2" },
+ { RGB_TO_ULONG(8 , 8 , 8 ), "gray3" },
+ { RGB_TO_ULONG(8 , 8 , 8 ), "grey3" },
+ { RGB_TO_ULONG(10 , 10 , 10 ), "gray4" },
+ { RGB_TO_ULONG(10 , 10 , 10 ), "grey4" },
+ { RGB_TO_ULONG(13 , 13 , 13 ), "gray5" },
+ { RGB_TO_ULONG(13 , 13 , 13 ), "grey5" },
+ { RGB_TO_ULONG(15 , 15 , 15 ), "gray6" },
+ { RGB_TO_ULONG(15 , 15 , 15 ), "grey6" },
+ { RGB_TO_ULONG(18 , 18 , 18 ), "gray7" },
+ { RGB_TO_ULONG(18 , 18 , 18 ), "grey7" },
+ { RGB_TO_ULONG(20 , 20 , 20 ), "gray8" },
+ { RGB_TO_ULONG(20 , 20 , 20 ), "grey8" },
+ { RGB_TO_ULONG(23 , 23 , 23 ), "gray9" },
+ { RGB_TO_ULONG(23 , 23 , 23 ), "grey9" },
+ { RGB_TO_ULONG(26 , 26 , 26 ), "gray10" },
+ { RGB_TO_ULONG(26 , 26 , 26 ), "grey10" },
+ { RGB_TO_ULONG(28 , 28 , 28 ), "gray11" },
+ { RGB_TO_ULONG(28 , 28 , 28 ), "grey11" },
+ { RGB_TO_ULONG(31 , 31 , 31 ), "gray12" },
+ { RGB_TO_ULONG(31 , 31 , 31 ), "grey12" },
+ { RGB_TO_ULONG(33 , 33 , 33 ), "gray13" },
+ { RGB_TO_ULONG(33 , 33 , 33 ), "grey13" },
+ { RGB_TO_ULONG(36 , 36 , 36 ), "gray14" },
+ { RGB_TO_ULONG(36 , 36 , 36 ), "grey14" },
+ { RGB_TO_ULONG(38 , 38 , 38 ), "gray15" },
+ { RGB_TO_ULONG(38 , 38 , 38 ), "grey15" },
+ { RGB_TO_ULONG(41 , 41 , 41 ), "gray16" },
+ { RGB_TO_ULONG(41 , 41 , 41 ), "grey16" },
+ { RGB_TO_ULONG(43 , 43 , 43 ), "gray17" },
+ { RGB_TO_ULONG(43 , 43 , 43 ), "grey17" },
+ { RGB_TO_ULONG(46 , 46 , 46 ), "gray18" },
+ { RGB_TO_ULONG(46 , 46 , 46 ), "grey18" },
+ { RGB_TO_ULONG(48 , 48 , 48 ), "gray19" },
+ { RGB_TO_ULONG(48 , 48 , 48 ), "grey19" },
+ { RGB_TO_ULONG(51 , 51 , 51 ), "gray20" },
+ { RGB_TO_ULONG(51 , 51 , 51 ), "grey20" },
+ { RGB_TO_ULONG(54 , 54 , 54 ), "gray21" },
+ { RGB_TO_ULONG(54 , 54 , 54 ), "grey21" },
+ { RGB_TO_ULONG(56 , 56 , 56 ), "gray22" },
+ { RGB_TO_ULONG(56 , 56 , 56 ), "grey22" },
+ { RGB_TO_ULONG(59 , 59 , 59 ), "gray23" },
+ { RGB_TO_ULONG(59 , 59 , 59 ), "grey23" },
+ { RGB_TO_ULONG(61 , 61 , 61 ), "gray24" },
+ { RGB_TO_ULONG(61 , 61 , 61 ), "grey24" },
+ { RGB_TO_ULONG(64 , 64 , 64 ), "gray25" },
+ { RGB_TO_ULONG(64 , 64 , 64 ), "grey25" },
+ { RGB_TO_ULONG(66 , 66 , 66 ), "gray26" },
+ { RGB_TO_ULONG(66 , 66 , 66 ), "grey26" },
+ { RGB_TO_ULONG(69 , 69 , 69 ), "gray27" },
+ { RGB_TO_ULONG(69 , 69 , 69 ), "grey27" },
+ { RGB_TO_ULONG(71 , 71 , 71 ), "gray28" },
+ { RGB_TO_ULONG(71 , 71 , 71 ), "grey28" },
+ { RGB_TO_ULONG(74 , 74 , 74 ), "gray29" },
+ { RGB_TO_ULONG(74 , 74 , 74 ), "grey29" },
+ { RGB_TO_ULONG(77 , 77 , 77 ), "gray30" },
+ { RGB_TO_ULONG(77 , 77 , 77 ), "grey30" },
+ { RGB_TO_ULONG(79 , 79 , 79 ), "gray31" },
+ { RGB_TO_ULONG(79 , 79 , 79 ), "grey31" },
+ { RGB_TO_ULONG(82 , 82 , 82 ), "gray32" },
+ { RGB_TO_ULONG(82 , 82 , 82 ), "grey32" },
+ { RGB_TO_ULONG(84 , 84 , 84 ), "gray33" },
+ { RGB_TO_ULONG(84 , 84 , 84 ), "grey33" },
+ { RGB_TO_ULONG(87 , 87 , 87 ), "gray34" },
+ { RGB_TO_ULONG(87 , 87 , 87 ), "grey34" },
+ { RGB_TO_ULONG(89 , 89 , 89 ), "gray35" },
+ { RGB_TO_ULONG(89 , 89 , 89 ), "grey35" },
+ { RGB_TO_ULONG(92 , 92 , 92 ), "gray36" },
+ { RGB_TO_ULONG(92 , 92 , 92 ), "grey36" },
+ { RGB_TO_ULONG(94 , 94 , 94 ), "gray37" },
+ { RGB_TO_ULONG(94 , 94 , 94 ), "grey37" },
+ { RGB_TO_ULONG(97 , 97 , 97 ), "gray38" },
+ { RGB_TO_ULONG(97 , 97 , 97 ), "grey38" },
+ { RGB_TO_ULONG(99 , 99 , 99 ), "gray39" },
+ { RGB_TO_ULONG(99 , 99 , 99 ), "grey39" },
+ { RGB_TO_ULONG(102, 102, 102), "gray40" },
+ { RGB_TO_ULONG(102, 102, 102), "grey40" },
+ { RGB_TO_ULONG(105, 105, 105), "gray41" },
+ { RGB_TO_ULONG(105, 105, 105), "grey41" },
+ { RGB_TO_ULONG(107, 107, 107), "gray42" },
+ { RGB_TO_ULONG(107, 107, 107), "grey42" },
+ { RGB_TO_ULONG(110, 110, 110), "gray43" },
+ { RGB_TO_ULONG(110, 110, 110), "grey43" },
+ { RGB_TO_ULONG(112, 112, 112), "gray44" },
+ { RGB_TO_ULONG(112, 112, 112), "grey44" },
+ { RGB_TO_ULONG(115, 115, 115), "gray45" },
+ { RGB_TO_ULONG(115, 115, 115), "grey45" },
+ { RGB_TO_ULONG(117, 117, 117), "gray46" },
+ { RGB_TO_ULONG(117, 117, 117), "grey46" },
+ { RGB_TO_ULONG(120, 120, 120), "gray47" },
+ { RGB_TO_ULONG(120, 120, 120), "grey47" },
+ { RGB_TO_ULONG(122, 122, 122), "gray48" },
+ { RGB_TO_ULONG(122, 122, 122), "grey48" },
+ { RGB_TO_ULONG(125, 125, 125), "gray49" },
+ { RGB_TO_ULONG(125, 125, 125), "grey49" },
+ { RGB_TO_ULONG(127, 127, 127), "gray50" },
+ { RGB_TO_ULONG(127, 127, 127), "grey50" },
+ { RGB_TO_ULONG(130, 130, 130), "gray51" },
+ { RGB_TO_ULONG(130, 130, 130), "grey51" },
+ { RGB_TO_ULONG(133, 133, 133), "gray52" },
+ { RGB_TO_ULONG(133, 133, 133), "grey52" },
+ { RGB_TO_ULONG(135, 135, 135), "gray53" },
+ { RGB_TO_ULONG(135, 135, 135), "grey53" },
+ { RGB_TO_ULONG(138, 138, 138), "gray54" },
+ { RGB_TO_ULONG(138, 138, 138), "grey54" },
+ { RGB_TO_ULONG(140, 140, 140), "gray55" },
+ { RGB_TO_ULONG(140, 140, 140), "grey55" },
+ { RGB_TO_ULONG(143, 143, 143), "gray56" },
+ { RGB_TO_ULONG(143, 143, 143), "grey56" },
+ { RGB_TO_ULONG(145, 145, 145), "gray57" },
+ { RGB_TO_ULONG(145, 145, 145), "grey57" },
+ { RGB_TO_ULONG(148, 148, 148), "gray58" },
+ { RGB_TO_ULONG(148, 148, 148), "grey58" },
+ { RGB_TO_ULONG(150, 150, 150), "gray59" },
+ { RGB_TO_ULONG(150, 150, 150), "grey59" },
+ { RGB_TO_ULONG(153, 153, 153), "gray60" },
+ { RGB_TO_ULONG(153, 153, 153), "grey60" },
+ { RGB_TO_ULONG(156, 156, 156), "gray61" },
+ { RGB_TO_ULONG(156, 156, 156), "grey61" },
+ { RGB_TO_ULONG(158, 158, 158), "gray62" },
+ { RGB_TO_ULONG(158, 158, 158), "grey62" },
+ { RGB_TO_ULONG(161, 161, 161), "gray63" },
+ { RGB_TO_ULONG(161, 161, 161), "grey63" },
+ { RGB_TO_ULONG(163, 163, 163), "gray64" },
+ { RGB_TO_ULONG(163, 163, 163), "grey64" },
+ { RGB_TO_ULONG(166, 166, 166), "gray65" },
+ { RGB_TO_ULONG(166, 166, 166), "grey65" },
+ { RGB_TO_ULONG(168, 168, 168), "gray66" },
+ { RGB_TO_ULONG(168, 168, 168), "grey66" },
+ { RGB_TO_ULONG(171, 171, 171), "gray67" },
+ { RGB_TO_ULONG(171, 171, 171), "grey67" },
+ { RGB_TO_ULONG(173, 173, 173), "gray68" },
+ { RGB_TO_ULONG(173, 173, 173), "grey68" },
+ { RGB_TO_ULONG(176, 176, 176), "gray69" },
+ { RGB_TO_ULONG(176, 176, 176), "grey69" },
+ { RGB_TO_ULONG(179, 179, 179), "gray70" },
+ { RGB_TO_ULONG(179, 179, 179), "grey70" },
+ { RGB_TO_ULONG(181, 181, 181), "gray71" },
+ { RGB_TO_ULONG(181, 181, 181), "grey71" },
+ { RGB_TO_ULONG(184, 184, 184), "gray72" },
+ { RGB_TO_ULONG(184, 184, 184), "grey72" },
+ { RGB_TO_ULONG(186, 186, 186), "gray73" },
+ { RGB_TO_ULONG(186, 186, 186), "grey73" },
+ { RGB_TO_ULONG(189, 189, 189), "gray74" },
+ { RGB_TO_ULONG(189, 189, 189), "grey74" },
+ { RGB_TO_ULONG(191, 191, 191), "gray75" },
+ { RGB_TO_ULONG(191, 191, 191), "grey75" },
+ { RGB_TO_ULONG(194, 194, 194), "gray76" },
+ { RGB_TO_ULONG(194, 194, 194), "grey76" },
+ { RGB_TO_ULONG(196, 196, 196), "gray77" },
+ { RGB_TO_ULONG(196, 196, 196), "grey77" },
+ { RGB_TO_ULONG(199, 199, 199), "gray78" },
+ { RGB_TO_ULONG(199, 199, 199), "grey78" },
+ { RGB_TO_ULONG(201, 201, 201), "gray79" },
+ { RGB_TO_ULONG(201, 201, 201), "grey79" },
+ { RGB_TO_ULONG(204, 204, 204), "gray80" },
+ { RGB_TO_ULONG(204, 204, 204), "grey80" },
+ { RGB_TO_ULONG(207, 207, 207), "gray81" },
+ { RGB_TO_ULONG(207, 207, 207), "grey81" },
+ { RGB_TO_ULONG(209, 209, 209), "gray82" },
+ { RGB_TO_ULONG(209, 209, 209), "grey82" },
+ { RGB_TO_ULONG(212, 212, 212), "gray83" },
+ { RGB_TO_ULONG(212, 212, 212), "grey83" },
+ { RGB_TO_ULONG(214, 214, 214), "gray84" },
+ { RGB_TO_ULONG(214, 214, 214), "grey84" },
+ { RGB_TO_ULONG(217, 217, 217), "gray85" },
+ { RGB_TO_ULONG(217, 217, 217), "grey85" },
+ { RGB_TO_ULONG(219, 219, 219), "gray86" },
+ { RGB_TO_ULONG(219, 219, 219), "grey86" },
+ { RGB_TO_ULONG(222, 222, 222), "gray87" },
+ { RGB_TO_ULONG(222, 222, 222), "grey87" },
+ { RGB_TO_ULONG(224, 224, 224), "gray88" },
+ { RGB_TO_ULONG(224, 224, 224), "grey88" },
+ { RGB_TO_ULONG(227, 227, 227), "gray89" },
+ { RGB_TO_ULONG(227, 227, 227), "grey89" },
+ { RGB_TO_ULONG(229, 229, 229), "gray90" },
+ { RGB_TO_ULONG(229, 229, 229), "grey90" },
+ { RGB_TO_ULONG(232, 232, 232), "gray91" },
+ { RGB_TO_ULONG(232, 232, 232), "grey91" },
+ { RGB_TO_ULONG(235, 235, 235), "gray92" },
+ { RGB_TO_ULONG(235, 235, 235), "grey92" },
+ { RGB_TO_ULONG(237, 237, 237), "gray93" },
+ { RGB_TO_ULONG(237, 237, 237), "grey93" },
+ { RGB_TO_ULONG(240, 240, 240), "gray94" },
+ { RGB_TO_ULONG(240, 240, 240), "grey94" },
+ { RGB_TO_ULONG(242, 242, 242), "gray95" },
+ { RGB_TO_ULONG(242, 242, 242), "grey95" },
+ { RGB_TO_ULONG(245, 245, 245), "gray96" },
+ { RGB_TO_ULONG(245, 245, 245), "grey96" },
+ { RGB_TO_ULONG(247, 247, 247), "gray97" },
+ { RGB_TO_ULONG(247, 247, 247), "grey97" },
+ { RGB_TO_ULONG(250, 250, 250), "gray98" },
+ { RGB_TO_ULONG(250, 250, 250), "grey98" },
+ { RGB_TO_ULONG(252, 252, 252), "gray99" },
+ { RGB_TO_ULONG(252, 252, 252), "grey99" },
+ { RGB_TO_ULONG(255, 255, 255), "gray100" },
+ { RGB_TO_ULONG(255, 255, 255), "grey100" },
+ { RGB_TO_ULONG(169, 169, 169), "dark grey" },
+ { RGB_TO_ULONG(169, 169, 169), "DarkGrey" },
+ { RGB_TO_ULONG(169, 169, 169), "dark gray" },
+ { RGB_TO_ULONG(169, 169, 169), "DarkGray" },
+ { RGB_TO_ULONG(0 , 0 , 139), "dark blue" },
+ { RGB_TO_ULONG(0 , 0 , 139), "DarkBlue" },
+ { RGB_TO_ULONG(0 , 139, 139), "dark cyan" },
+ { RGB_TO_ULONG(0 , 139, 139), "DarkCyan" },
+ { RGB_TO_ULONG(139, 0 , 139), "dark magenta" },
+ { RGB_TO_ULONG(139, 0 , 139), "DarkMagenta" },
+ { RGB_TO_ULONG(139, 0 , 0 ), "dark red" },
+ { RGB_TO_ULONG(139, 0 , 0 ), "DarkRed" },
+ { RGB_TO_ULONG(144, 238, 144), "light green" },
+ { RGB_TO_ULONG(144, 238, 144), "LightGreen" }
+};
+
+unsigned long
+mac_color_map_lookup (colorname)
+ char *colorname;
+{
+ Lisp_Object ret = Qnil;
+ int i;
+
+ BLOCK_INPUT;
+
+ for (i = 0; i < sizeof (mac_color_map) / sizeof (mac_color_map[0]); i++)
+ if (stricmp (colorname, mac_color_map[i].name) == 0)
+ {
+ ret = mac_color_map[i].color;
+ break;
+ }
+
+ UNBLOCK_INPUT;
+
+ return ret;
+}
+
+Lisp_Object
+x_to_mac_color (colorname)
+ char * colorname;
+{
+ register Lisp_Object tail, ret = Qnil;
+
+ BLOCK_INPUT;
+
+ if (colorname[0] == '#')
+ {
+ /* Could be an old-style RGB Device specification. */
+ char *color;
+ int size;
+ color = colorname + 1;
+
+ size = strlen(color);
+ if (size == 3 || size == 6 || size == 9 || size == 12)
+ {
+ unsigned long colorval;
+ int i, pos;
+ pos = 0;
+ size /= 3;
+ colorval = 0;
+
+ for (i = 0; i < 3; i++)
+ {
+ char *end;
+ char t;
+ unsigned long value;
+
+ /* The check for 'x' in the following conditional takes into
+ account the fact that strtol allows a "0x" in front of
+ our numbers, and we don't. */
+ if (!isxdigit(color[0]) || color[1] == 'x')
+ break;
+ t = color[size];
+ color[size] = '\0';
+ value = strtoul(color, &end, 16);
+ color[size] = t;
+ if (errno == ERANGE || end - color != size)
+ break;
+ switch (size)
+ {
+ case 1:
+ value = value * 0x10;
+ break;
+ case 2:
+ break;
+ case 3:
+ value /= 0x10;
+ break;
+ case 4:
+ value /= 0x100;
+ break;
+ }
+ colorval |= (value << pos);
+ pos += 0x8;
+ if (i == 2)
+ {
+ UNBLOCK_INPUT;
+ return (colorval);
+ }
+ color = end;
+ }
+ }
+ }
+ else if (strnicmp(colorname, "rgb:", 4) == 0)
+ {
+ char *color;
+ unsigned long colorval;
+ int i, pos;
+ pos = 0;
+
+ colorval = 0;
+ color = colorname + 4;
+ for (i = 0; i < 3; i++)
+ {
+ char *end;
+ unsigned long value;
+
+ /* The check for 'x' in the following conditional takes into
+ account the fact that strtol allows a "0x" in front of
+ our numbers, and we don't. */
+ if (!isxdigit(color[0]) || color[1] == 'x')
+ break;
+ value = strtoul(color, &end, 16);
+ if (errno == ERANGE)
+ break;
+ switch (end - color)
+ {
+ case 1:
+ value = value * 0x10 + value;
+ break;
+ case 2:
+ break;
+ case 3:
+ value /= 0x10;
+ break;
+ case 4:
+ value /= 0x100;
+ break;
+ default:
+ value = ULONG_MAX;
+ }
+ if (value == ULONG_MAX)
+ break;
+ colorval |= (value << pos);
+ pos += 0x8;
+ if (i == 2)
+ {
+ if (*end != '\0')
+ break;
+ UNBLOCK_INPUT;
+ return (colorval);
+ }
+ if (*end != '/')
+ break;
+ color = end + 1;
+ }
+ }
+ else if (strnicmp(colorname, "rgbi:", 5) == 0)
+ {
+ /* This is an RGB Intensity specification. */
+ char *color;
+ unsigned long colorval;
+ int i, pos;
+ pos = 0;
+
+ colorval = 0;
+ color = colorname + 5;
+ for (i = 0; i < 3; i++)
+ {
+ char *end;
+ double value;
+ unsigned long val;
+
+ value = strtod(color, &end);
+ if (errno == ERANGE)
+ break;
+ if (value < 0.0 || value > 1.0)
+ break;
+ val = (unsigned long)(0x100 * value);
+ /* We used 0x100 instead of 0xFF to give an continuous
+ range between 0.0 and 1.0 inclusive. The next statement
+ fixes the 1.0 case. */
+ if (val == 0x100)
+ val = 0xFF;
+ colorval |= (val << pos);
+ pos += 0x8;
+ if (i == 2)
+ {
+ if (*end != '\0')
+ break;
+ UNBLOCK_INPUT;
+ return (colorval);
+ }
+ if (*end != '/')
+ break;
+ color = end + 1;
+ }
+ }
+
+ ret = mac_color_map_lookup (colorname);
+
+ UNBLOCK_INPUT;
+ return ret;
+}
+
+/* Gamma-correct COLOR on frame F. */
+
+void
+gamma_correct (f, color)
+ struct frame *f;
+ unsigned long *color;
+{
+ if (f->gamma)
+ {
+ unsigned long red, green, blue;
+
+ red = pow (RED_FROM_ULONG (*color) / 255.0, f->gamma) * 255.0 + 0.5;
+ green = pow (GREEN_FROM_ULONG (*color) / 255.0, f->gamma) * 255.0 + 0.5;
+ blue = pow (BLUE_FROM_ULONG (*color) / 255.0, f->gamma) * 255.0 + 0.5;
+ *color = RGB_TO_ULONG (red, green, blue);
+ }
+}
+
+/* Decide if color named COLOR is valid for the display associated
+ with the selected frame; if so, return the rgb values in COLOR_DEF.
+ If ALLOC is nonzero, allocate a new colormap cell. */
+
+int
+mac_defined_color (f, color, color_def, alloc)
+ FRAME_PTR f;
+ char *color;
+ XColor *color_def;
+ int alloc;
+{
+ register Lisp_Object tem;
+ unsigned long mac_color_ref;
+
+ tem = x_to_mac_color (color);
+
+ if (!NILP (tem))
+ {
+ if (f)
+ {
+ /* Apply gamma correction. */
+ mac_color_ref = XUINT (tem);
+ gamma_correct (f, &mac_color_ref);
+ XSETINT (tem, mac_color_ref);
+ }
+
+ color_def->pixel = mac_color_ref;
+ color_def->red = RED_FROM_ULONG (mac_color_ref);
+ color_def->green = GREEN_FROM_ULONG (mac_color_ref);
+ color_def->blue = BLUE_FROM_ULONG (mac_color_ref);
+
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+/* Given a string ARG naming a color, compute a pixel value from it
+ suitable for screen F.
+ If F is not a color screen, return DEF (default) regardless of what
+ ARG says. */
+
+int
+x_decode_color (f, arg, def)
+ FRAME_PTR f;
+ Lisp_Object arg;
+ int def;
+{
+ XColor cdef;
+
+ CHECK_STRING (arg);
+
+ if (strcmp (XSTRING (arg)->data, "black") == 0)
+ return BLACK_PIX_DEFAULT (f);
+ else if (strcmp (XSTRING (arg)->data, "white") == 0)
+ return WHITE_PIX_DEFAULT (f);
+
+#if 0
+ if ((FRAME_MAC_DISPLAY_INFO (f)->n_planes
+ * FRAME_MAC_DISPLAY_INFO (f)->n_cbits) == 1)
+ return def;
+#endif
+
+ if (mac_defined_color (f, XSTRING (arg)->data, &cdef, 1))
+ return cdef.pixel;
+
+ /* defined_color failed; return an ultimate default. */
+ return def;
+}
+\f
+/* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
+ the previous value of that parameter, NEW_VALUE is the new value. */
+
+static void
+x_set_line_spacing (f, new_value, old_value)
+ struct frame *f;
+ Lisp_Object new_value, old_value;
+{
+ if (NILP (new_value))
+ f->extra_line_spacing = 0;
+ else if (NATNUMP (new_value))
+ f->extra_line_spacing = XFASTINT (new_value);
+ else
+ Fsignal (Qerror, Fcons (build_string ("Illegal line-spacing"),
+ Fcons (new_value, Qnil)));
+ if (FRAME_VISIBLE_P (f))
+ redraw_frame (f);
+}
+
+
+/* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
+ the previous value of that parameter, NEW_VALUE is the new value. */
+
+static void
+x_set_screen_gamma (f, new_value, old_value)
+ struct frame *f;
+ Lisp_Object new_value, old_value;
+{
+ if (NILP (new_value))
+ f->gamma = 0;
+ else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
+ /* The value 0.4545 is the normal viewing gamma. */
+ f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
+ else
+ Fsignal (Qerror, Fcons (build_string ("Illegal screen-gamma"),
+ Fcons (new_value, Qnil)));
+
+ clear_face_cache (0);
+}
+
+
+/* Functions called only from `x_set_frame_param'
+ to set individual parameters.
+
+ If FRAME_MAC_WINDOW (f) is 0,
+ the frame is being created and its window does not exist yet.
+ In that case, just record the parameter's new value
+ in the standard place; do not attempt to change the window. */
+
+void
+x_set_foreground_color (f, arg, oldval)
+ struct frame *f;
+ Lisp_Object arg, oldval;
+{
+ FRAME_FOREGROUND_PIXEL (f)
+ = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
+
+ if (FRAME_MAC_WINDOW (f) != 0)
+ {
+ update_face_from_frame_parameter (f, Qforeground_color, arg);
+ if (FRAME_VISIBLE_P (f))
+ redraw_frame (f);
+ }
+}
+
+void
+x_set_background_color (f, arg, oldval)
+ struct frame *f;
+ Lisp_Object arg, oldval;
+{
+ FRAME_BACKGROUND_PIXEL (f)
+ = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
+
+ if (FRAME_MAC_WINDOW (f) != 0)
+ {
+ update_face_from_frame_parameter (f, Qbackground_color, arg);
+
+ if (FRAME_VISIBLE_P (f))
+ redraw_frame (f);
+ }
+}
+
+void
+x_set_mouse_color (f, arg, oldval)
+ struct frame *f;
+ Lisp_Object arg, oldval;
+{
+ Cursor cursor, nontext_cursor, mode_cursor, cross_cursor;
+ int count;
+ int mask_color;
+
+ if (!EQ (Qnil, arg))
+ f->output_data.mac->mouse_pixel
+ = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
+ mask_color = FRAME_BACKGROUND_PIXEL (f);
+
+ /* Don't let pointers be invisible. */
+ if (mask_color == f->output_data.mac->mouse_pixel
+ && mask_color == FRAME_BACKGROUND_PIXEL (f))
+ f->output_data.mac->mouse_pixel = FRAME_FOREGROUND_PIXEL (f);
+
+#if 0 /* MAC_TODO : cursor changes */
+ BLOCK_INPUT;
+
+ /* It's not okay to crash if the user selects a screwy cursor. */
+ count = x_catch_errors (FRAME_W32_DISPLAY (f));
+
+ if (!EQ (Qnil, Vx_pointer_shape))
+ {
+ CHECK_NUMBER (Vx_pointer_shape);
+ cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XINT (Vx_pointer_shape));
+ }
+ else
+ cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
+ x_check_errors (FRAME_W32_DISPLAY (f), "bad text pointer cursor: %s");
+
+ if (!EQ (Qnil, Vx_nontext_pointer_shape))
+ {
+ CHECK_NUMBER (Vx_nontext_pointer_shape);
+ nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
+ XINT (Vx_nontext_pointer_shape));
+ }
+ else
+ nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_left_ptr);
+ x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
+
+ if (!EQ (Qnil, Vx_hourglass_pointer_shape))
+ {
+ CHECK_NUMBER (Vx_hourglass_pointer_shape);
+ hourglass_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
+ XINT (Vx_hourglass_pointer_shape));
+ }
+ else
+ hourglass_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_watch);
+ x_check_errors (FRAME_W32_DISPLAY (f), "bad busy pointer cursor: %s");
+
+ x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
+ if (!EQ (Qnil, Vx_mode_pointer_shape))
+ {
+ CHECK_NUMBER (Vx_mode_pointer_shape);
+ mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
+ XINT (Vx_mode_pointer_shape));
+ }
+ else
+ mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
+ x_check_errors (FRAME_W32_DISPLAY (f), "bad modeline pointer cursor: %s");
+
+ if (!EQ (Qnil, Vx_sensitive_text_pointer_shape))
+ {
+ CHECK_NUMBER (Vx_sensitive_text_pointer_shape);
+ cross_cursor
+ = XCreateFontCursor (FRAME_W32_DISPLAY (f),
+ XINT (Vx_sensitive_text_pointer_shape));
+ }
+ else
+ cross_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_crosshair);
+
+ if (!NILP (Vx_window_horizontal_drag_shape))
+ {
+ CHECK_NUMBER (Vx_window_horizontal_drag_shape);
+ horizontal_drag_cursor
+ = XCreateFontCursor (FRAME_W32_DISPLAY (f),
+ XINT (Vx_window_horizontal_drag_shape));
+ }
+ else
+ horizontal_drag_cursor
+ = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_sb_h_double_arrow);
+
+ /* Check and report errors with the above calls. */
+ x_check_errors (FRAME_W32_DISPLAY (f), "can't set cursor shape: %s");
+ x_uncatch_errors (FRAME_W32_DISPLAY (f), count);
+
+ {
+ XColor fore_color, back_color;
+
+ fore_color.pixel = f->output_data.w32->mouse_pixel;
+ back_color.pixel = mask_color;
+ XQueryColor (FRAME_W32_DISPLAY (f),
+ DefaultColormap (FRAME_W32_DISPLAY (f),
+ DefaultScreen (FRAME_W32_DISPLAY (f))),
+ &fore_color);
+ XQueryColor (FRAME_W32_DISPLAY (f),
+ DefaultColormap (FRAME_W32_DISPLAY (f),
+ DefaultScreen (FRAME_W32_DISPLAY (f))),
+ &back_color);
+ XRecolorCursor (FRAME_W32_DISPLAY (f), cursor,
+ &fore_color, &back_color);
+ XRecolorCursor (FRAME_W32_DISPLAY (f), nontext_cursor,
+ &fore_color, &back_color);
+ XRecolorCursor (FRAME_W32_DISPLAY (f), mode_cursor,
+ &fore_color, &back_color);
+ XRecolorCursor (FRAME_W32_DISPLAY (f), cross_cursor,
+ &fore_color, &back_color);
+ XRecolorCursor (FRAME_W32_DISPLAY (f), hourglass_cursor,
+ &fore_color, &back_color);
+ }
+
+ if (FRAME_W32_WINDOW (f) != 0)
+ XDefineCursor (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f), cursor);
+
+ if (cursor != f->output_data.w32->text_cursor && f->output_data.w32->text_cursor != 0)
+ XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->text_cursor);
+ f->output_data.w32->text_cursor = cursor;
+
+ if (nontext_cursor != f->output_data.w32->nontext_cursor
+ && f->output_data.w32->nontext_cursor != 0)
+ XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->nontext_cursor);
+ f->output_data.w32->nontext_cursor = nontext_cursor;
+
+ if (hourglass_cursor != f->output_data.w32->hourglass_cursor
+ && f->output_data.w32->hourglass_cursor != 0)
+ XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->hourglass_cursor);
+ f->output_data.w32->hourglass_cursor = hourglass_cursor;
+
+ if (mode_cursor != f->output_data.w32->modeline_cursor
+ && f->output_data.w32->modeline_cursor != 0)
+ XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->modeline_cursor);
+ f->output_data.w32->modeline_cursor = mode_cursor;
+
+ if (cross_cursor != f->output_data.w32->cross_cursor
+ && f->output_data.w32->cross_cursor != 0)
+ XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->cross_cursor);
+ f->output_data.w32->cross_cursor = cross_cursor;
+
+ XFlush (FRAME_W32_DISPLAY (f));
+ UNBLOCK_INPUT;
+
+ update_face_from_frame_parameter (f, Qmouse_color, arg);
+#endif /* MAC_TODO */
+}
+
+void
+x_set_cursor_color (f, arg, oldval)
+ struct frame *f;
+ Lisp_Object arg, oldval;
+{
+ unsigned long fore_pixel;
+
+ if (!NILP (Vx_cursor_fore_pixel))
+ fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
+ WHITE_PIX_DEFAULT (f));
+ else
+ fore_pixel = FRAME_BACKGROUND_PIXEL (f);
+ f->output_data.mac->cursor_pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
+
+ /* Make sure that the cursor color differs from the background color. */
+ if (f->output_data.mac->cursor_pixel == FRAME_BACKGROUND_PIXEL (f))
+ {
+ f->output_data.mac->cursor_pixel = f->output_data.mac->mouse_pixel;
+ if (f->output_data.mac->cursor_pixel == fore_pixel)
+ fore_pixel = FRAME_BACKGROUND_PIXEL (f);
+ }
+ FRAME_FOREGROUND_PIXEL (f) = fore_pixel;
+
+#if 0 /* MAC_TODO: cannot figure out what to do (wrong number of params) */
+ if (FRAME_MAC_WINDOW (f) != 0)
+ {
+ if (FRAME_VISIBLE_P (f))
+ {
+ x_display_cursor (f, 0);
+ x_display_cursor (f, 1);
+ }
+ }
+#endif
+
+ update_face_from_frame_parameter (f, Qcursor_color, arg);
+}
+
+/* Set the border-color of frame F to pixel value PIX.
+ Note that this does not fully take effect if done before
+ F has an window. */
+void
+x_set_border_pixel (f, pix)
+ struct frame *f;
+ int pix;
+{
+ f->output_data.mac->border_pixel = pix;
+
+ if (FRAME_MAC_WINDOW (f) != 0 && f->output_data.mac->border_width > 0)
+ {
+ if (FRAME_VISIBLE_P (f))
+ redraw_frame (f);
+ }
+}
+
+/* Set the border-color of frame F to value described by ARG.
+ ARG can be a string naming a color.
+ The border-color is used for the border that is drawn by the server.
+ Note that this does not fully take effect if done before
+ F has a window; it must be redone when the window is created. */
+
+void
+x_set_border_color (f, arg, oldval)
+ struct frame *f;
+ Lisp_Object arg, oldval;
+{
+ int pix;
+
+ CHECK_STRING (arg);
+ pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
+ x_set_border_pixel (f, pix);
+ update_face_from_frame_parameter (f, Qborder_color, arg);
+}
+
+/* Value is the internal representation of the specified cursor type
+ ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
+ of the bar cursor. */
+
+enum text_cursor_kinds
+x_specified_cursor_type (arg, width)
+ Lisp_Object arg;
+ int *width;
+{
+ enum text_cursor_kinds type;
+
+ if (EQ (arg, Qbar))
+ {
+ type = BAR_CURSOR;
+ *width = 2;
+ }
+ else if (CONSP (arg)
+ && EQ (XCAR (arg), Qbar)
+ && INTEGERP (XCDR (arg))
+ && XINT (XCDR (arg)) >= 0)
+ {
+ type = BAR_CURSOR;
+ *width = XINT (XCDR (arg));
+ }
+ else if (NILP (arg))
+ type = NO_CURSOR;
+ else
+ /* Treat anything unknown as "box cursor".
+ It was bad to signal an error; people have trouble fixing
+ .Xdefaults with Emacs, when it has something bad in it. */
+ type = FILLED_BOX_CURSOR;
+
+ return type;
+}
+
+void
+x_set_cursor_type (f, arg, oldval)
+ FRAME_PTR f;
+ Lisp_Object arg, oldval;
+{
+ int width;
+
+ FRAME_DESIRED_CURSOR (f) = x_specified_cursor_type (arg, &width);
+ f->output_data.mac->cursor_width = width;
+
+ /* Make sure the cursor gets redrawn. This is overkill, but how
+ often do people change cursor types? */
+ update_mode_lines++;
+}
+\f
+#if 0 /* MAC_TODO: really no icon for Mac */
+void
+x_set_icon_type (f, arg, oldval)
+ struct frame *f;
+ Lisp_Object arg, oldval;
+{
+ int result;
+
+ if (NILP (arg) && NILP (oldval))
+ return;
+
+ if (STRINGP (arg) && STRINGP (oldval)
+ && EQ (Fstring_equal (oldval, arg), Qt))
+ return;
+
+ if (SYMBOLP (arg) && SYMBOLP (oldval) && EQ (arg, oldval))
+ return;
+
+ BLOCK_INPUT;
+
+ result = x_bitmap_icon (f, arg);
+ if (result)
+ {
+ UNBLOCK_INPUT;
+ error ("No icon window available");
+ }
+
+ UNBLOCK_INPUT;
+}
+#endif /* MAC_TODO */
+
+/* Return non-nil if frame F wants a bitmap icon. */
+
+Lisp_Object
+x_icon_type (f)
+ FRAME_PTR f;
+{
+ Lisp_Object tem;
+
+ tem = assq_no_quit (Qicon_type, f->param_alist);
+ if (CONSP (tem))
+ return XCDR (tem);
+ else
+ return Qnil;
+}
+
+void
+x_set_icon_name (f, arg, oldval)
+ struct frame *f;
+ Lisp_Object arg, oldval;
+{
+ int result;
+
+ if (STRINGP (arg))
+ {
+ if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
+ return;
+ }
+ else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
+ return;
+
+ f->icon_name = arg;
+
+#if 0 /* MAC_TODO */
+ if (f->output_data.w32->icon_bitmap != 0)
+ return;
+
+ BLOCK_INPUT;
+
+ result = x_text_icon (f,
+ (char *) XSTRING ((!NILP (f->icon_name)
+ ? f->icon_name
+ : !NILP (f->title)
+ ? f->title
+ : f->name))->data);
+
+ if (result)
+ {
+ UNBLOCK_INPUT;
+ error ("No icon window available");
+ }
+
+ /* If the window was unmapped (and its icon was mapped),
+ the new icon is not mapped, so map the window in its stead. */
+ if (FRAME_VISIBLE_P (f))
+ {
+#ifdef USE_X_TOOLKIT
+ XtPopup (f->output_data.w32->widget, XtGrabNone);
+#endif
+ XMapWindow (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f));
+ }
+
+ XFlush (FRAME_W32_DISPLAY (f));
+ UNBLOCK_INPUT;
+#endif /* MAC_TODO */
+}
+
+extern Lisp_Object x_new_font ();
+extern Lisp_Object x_new_fontset();
+
+void
+x_set_font (f, arg, oldval)
+ struct frame *f;
+ Lisp_Object arg, oldval;
+{
+ Lisp_Object result;
+ Lisp_Object fontset_name;
+ Lisp_Object frame;
+ int old_fontset = FRAME_FONTSET(f);
+
+ CHECK_STRING (arg);
+
+ fontset_name = Fquery_fontset (arg, Qnil);
+
+ BLOCK_INPUT;
+ result = (STRINGP (fontset_name)
+ ? x_new_fontset (f, XSTRING (fontset_name)->data)
+ : x_new_font (f, XSTRING (arg)->data));
+ UNBLOCK_INPUT;
+
+ if (EQ (result, Qnil))
+ error ("Font `%s' is not defined", XSTRING (arg)->data);
+ else if (EQ (result, Qt))
+ error ("The characters of the given font have varying widths");
+ else if (STRINGP (result))
+ {
+ if (STRINGP (fontset_name))
+ {
+ /* Fontset names are built from ASCII font names, so the
+ names may be equal despite there was a change. */
+ if (old_fontset == FRAME_FONTSET (f))
+ return;
+ }
+ else if (!NILP (Fequal (result, oldval)))
+ return;
+
+ store_frame_param (f, Qfont, result);
+ recompute_basic_faces (f);
+ }
+ else
+ abort ();
+
+ do_pending_window_change (0);
+
+ /* Don't call `face-set-after-frame-default' when faces haven't been
+ initialized yet. This is the case when called from
+ Fx_create_frame. In that case, the X widget or window doesn't
+ exist either, and we can end up in x_report_frame_params with a
+ null widget which gives a segfault. */
+ if (FRAME_FACE_CACHE (f))
+ {
+ XSETFRAME (frame, f);
+ call1 (Qface_set_after_frame_default, frame);
+ }
+}
+
+void
+x_set_border_width (f, arg, oldval)
+ struct frame *f;
+ Lisp_Object arg, oldval;
+{
+ CHECK_NUMBER (arg);
+
+ if (XINT (arg) == f->output_data.mac->border_width)
+ return;
+
+#if 0 /* MAC_TODO */
+ if (FRAME_MAC_WINDOW (f) != 0)
+ error ("Cannot change the border width of a window");
+#endif
+
+ f->output_data.mac->border_width = XINT (arg);
+}
+
+void
+x_set_internal_border_width (f, arg, oldval)
+ struct frame *f;
+ Lisp_Object arg, oldval;
+{
+ int old = f->output_data.mac->internal_border_width;
+
+ CHECK_NUMBER (arg);
+ f->output_data.mac->internal_border_width = XINT (arg);
+ if (f->output_data.mac->internal_border_width < 0)
+ f->output_data.mac->internal_border_width = 0;
+
+ if (f->output_data.mac->internal_border_width == old)
+ return;
+
+ if (FRAME_MAC_WINDOW (f) != 0)
+ {
+ x_set_window_size (f, 0, f->width, f->height);
+ SET_FRAME_GARBAGED (f);
+ do_pending_window_change (0);
+ }
+ else
+ SET_FRAME_GARBAGED (f);
+}
+
+void
+x_set_visibility (f, value, oldval)
+ struct frame *f;
+ Lisp_Object value, oldval;
+{
+ Lisp_Object frame;
+ XSETFRAME (frame, f);
+
+ if (NILP (value))
+ Fmake_frame_invisible (frame, Qt);
+ else if (EQ (value, Qicon))
+ Ficonify_frame (frame);
+ else
+ Fmake_frame_visible (frame);
+}
+
+\f
+/* Change window heights in windows rooted in WINDOW by N lines. */
+
+static void
+x_change_window_heights (window, n)
+ Lisp_Object window;
+ int n;
+{
+ struct window *w = XWINDOW (window);
+
+ XSETFASTINT (w->top, XFASTINT (w->top) + n);
+ XSETFASTINT (w->height, XFASTINT (w->height) - n);
+
+ if (INTEGERP (w->orig_top))
+ XSETFASTINT (w->orig_top, XFASTINT (w->orig_top) + n);
+ if (INTEGERP (w->orig_height))
+ XSETFASTINT (w->orig_height, XFASTINT (w->orig_height) - n);
+
+ /* Handle just the top child in a vertical split. */
+ if (!NILP (w->vchild))
+ x_change_window_heights (w->vchild, n);
+
+ /* Adjust all children in a horizontal split. */
+ for (window = w->hchild; !NILP (window); window = w->next)
+ {
+ w = XWINDOW (window);
+ x_change_window_heights (window, n);
+ }
+}
+
+void
+x_set_menu_bar_lines (f, value, oldval)
+ struct frame *f;
+ Lisp_Object value, oldval;
+{
+ int nlines;
+ int olines = FRAME_MENU_BAR_LINES (f);
+
+ /* Right now, menu bars don't work properly in minibuf-only frames;
+ most of the commands try to apply themselves to the minibuffer
+ frame itself, and get an error because you can't switch buffers
+ in or split the minibuffer window. */
+ if (FRAME_MINIBUF_ONLY_P (f))
+ return;
+
+ if (INTEGERP (value))
+ nlines = XINT (value);
+ else
+ nlines = 0;
+
+ FRAME_MENU_BAR_LINES (f) = 0;
+ if (nlines)
+ FRAME_EXTERNAL_MENU_BAR (f) = 1;
+ else
+ {
+ if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
+ free_frame_menubar (f);
+ FRAME_EXTERNAL_MENU_BAR (f) = 0;
+
+ /* Adjust the frame size so that the client (text) dimensions
+ remain the same. This depends on FRAME_EXTERNAL_MENU_BAR being
+ set correctly. */
+ x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
+ do_pending_window_change (0);
+ }
+ adjust_glyphs (f);
+}
+
+
+/* Set the number of lines used for the tool bar of frame F to VALUE.
+ VALUE not an integer, or < 0 means set the lines to zero. OLDVAL
+ is the old number of tool bar lines. This function changes the
+ height of all windows on frame F to match the new tool bar height.
+ The frame's height doesn't change. */
+
+void
+x_set_tool_bar_lines (f, value, oldval)
+ struct frame *f;
+ Lisp_Object value, oldval;
+{
+ int delta, nlines, root_height;
+ Lisp_Object root_window;
+
+ /* Treat tool bars like menu bars. */
+ if (FRAME_MINIBUF_ONLY_P (f))
+ return;
+
+ /* Use VALUE only if an integer >= 0. */
+ if (INTEGERP (value) && XINT (value) >= 0)
+ nlines = XFASTINT (value);
+ else
+ nlines = 0;
+
+ /* Make sure we redisplay all windows in this frame. */
+ ++windows_or_buffers_changed;
+
+ delta = nlines - FRAME_TOOL_BAR_LINES (f);
+
+ /* Don't resize the tool-bar to more than we have room for. */
+ root_window = FRAME_ROOT_WINDOW (f);
+ root_height = XINT (XWINDOW (root_window)->height);
+ if (root_height - delta < 1)
+ {
+ delta = root_height - 1;
+ nlines = FRAME_TOOL_BAR_LINES (f) + delta;
+ }
+
+ FRAME_TOOL_BAR_LINES (f) = nlines;
+ x_change_window_heights (root_window, delta);
+ adjust_glyphs (f);
+
+ /* We also have to make sure that the internal border at the top of
+ the frame, below the menu bar or tool bar, is redrawn when the
+ tool bar disappears. This is so because the internal border is
+ below the tool bar if one is displayed, but is below the menu bar
+ if there isn't a tool bar. The tool bar draws into the area
+ below the menu bar. */
+ if (FRAME_MAC_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0)
+ {
+ updating_frame = f;
+ clear_frame ();
+ clear_current_matrices (f);
+ updating_frame = NULL;
+ }
+
+ /* If the tool bar gets smaller, the internal border below it
+ has to be cleared. It was formerly part of the display
+ of the larger tool bar, and updating windows won't clear it. */
+ if (delta < 0)
+ {
+ int height = FRAME_INTERNAL_BORDER_WIDTH (f);
+ int width = PIXEL_WIDTH (f);
+ int y = nlines * CANON_Y_UNIT (f);
+
+ BLOCK_INPUT;
+ XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
+ 0, y, width, height, 0);
+ UNBLOCK_INPUT;
+
+ if (WINDOWP (f->tool_bar_window))
+ clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
+ }
+}
+
+
+/* Change the name of frame F to NAME. If NAME is nil, set F's name to
+ w32_id_name.
+
+ If EXPLICIT is non-zero, that indicates that lisp code is setting the
+ name; if NAME is a string, set F's name to NAME and set
+ F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
+
+ If EXPLICIT is zero, that indicates that Emacs redisplay code is
+ suggesting a new name, which lisp code should override; if
+ F->explicit_name is set, ignore the new name; otherwise, set it. */
+
+void
+x_set_name (f, name, explicit)
+ struct frame *f;
+ Lisp_Object name;
+ int explicit;
+{
+ /* Make sure that requests from lisp code override requests from
+ Emacs redisplay code. */
+ if (explicit)
+ {
+ /* If we're switching from explicit to implicit, we had better
+ update the mode lines and thereby update the title. */
+ if (f->explicit_name && NILP (name))
+ update_mode_lines = 1;
+
+ f->explicit_name = ! NILP (name);
+ }
+ else if (f->explicit_name)
+ return;
+
+ /* If NAME is nil, set the name to the w32_id_name. */
+ if (NILP (name))
+ {
+ /* Check for no change needed in this very common case
+ before we do any consing. */
+ if (!strcmp (FRAME_MAC_DISPLAY_INFO (f)->mac_id_name,
+ XSTRING (f->name)->data))
+ return;
+ name = build_string (FRAME_MAC_DISPLAY_INFO (f)->mac_id_name);
+ }
+ else
+ CHECK_STRING (name);
+
+ /* Don't change the name if it's already NAME. */
+ if (! NILP (Fstring_equal (name, f->name)))
+ return;
+
+ f->name = name;
+
+ /* For setting the frame title, the title parameter should override
+ the name parameter. */
+ if (! NILP (f->title))
+ name = f->title;
+
+ if (FRAME_MAC_WINDOW (f))
+ {
+ if (STRING_MULTIBYTE (name))
+#if 0 /* MAC_TODO: encoding title string */
+ name = ENCODE_SYSTEM (name);
+#else
+ return;
+#endif
+
+ BLOCK_INPUT;
+
+ {
+ Str255 windowTitle;
+ if (strlen (XSTRING (name)->data) < 255)
+ {
+ strcpy (windowTitle, XSTRING (name)->data);
+ c2pstr (windowTitle);
+ SetWTitle (FRAME_MAC_WINDOW (f), windowTitle);
+ }
+ }
+
+ UNBLOCK_INPUT;
+ }
+}
+
+/* This function should be called when the user's lisp code has
+ specified a name for the frame; the name will override any set by the
+ redisplay code. */
+void
+x_explicitly_set_name (f, arg, oldval)
+ FRAME_PTR f;
+ Lisp_Object arg, oldval;
+{
+ x_set_name (f, arg, 1);
+}
+
+/* This function should be called by Emacs redisplay code to set the
+ name; names set this way will never override names set by the user's
+ lisp code. */
+void
+x_implicitly_set_name (f, arg, oldval)
+ FRAME_PTR f;
+ Lisp_Object arg, oldval;
+{
+ x_set_name (f, arg, 0);
+}
+\f
+/* Change the title of frame F to NAME.
+ If NAME is nil, use the frame name as the title.
+
+ If EXPLICIT is non-zero, that indicates that lisp code is setting the
+ name; if NAME is a string, set F's name to NAME and set
+ F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
+
+ If EXPLICIT is zero, that indicates that Emacs redisplay code is
+ suggesting a new name, which lisp code should override; if
+ F->explicit_name is set, ignore the new name; otherwise, set it. */
+
+void
+x_set_title (f, name, old_name)
+ struct frame *f;
+ Lisp_Object name, old_name;
+{
+ /* Don't change the title if it's already NAME. */
+ if (EQ (name, f->title))
+ return;
+
+ update_mode_lines = 1;
+
+ f->title = name;
+
+ if (NILP (name))
+ name = f->name;
+
+ if (FRAME_MAC_WINDOW (f))
+ {
+ if (STRING_MULTIBYTE (name))
+#if 0 /* MAC_TODO: encoding title string */
+ name = ENCODE_SYSTEM (name);
+#else
+ return;
+#endif
+
+ BLOCK_INPUT;
+
+ {
+ Str255 windowTitle;
+ if (strlen (XSTRING (name)->data) < 255)
+ {
+ strcpy (windowTitle, XSTRING (name)->data);
+ c2pstr (windowTitle);
+ SetWTitle (FRAME_MAC_WINDOW (f), windowTitle);
+ }
+ }
+
+ UNBLOCK_INPUT;
+ }
+}
+\f
+void
+x_set_autoraise (f, arg, oldval)
+ struct frame *f;
+ Lisp_Object arg, oldval;
+{
+ f->auto_raise = !EQ (Qnil, arg);
+}
+
+void
+x_set_autolower (f, arg, oldval)
+ struct frame *f;
+ Lisp_Object arg, oldval;
+{
+ f->auto_lower = !EQ (Qnil, arg);
+}
+
+void
+x_set_unsplittable (f, arg, oldval)
+ struct frame *f;
+ Lisp_Object arg, oldval;
+{
+ f->no_split = !NILP (arg);
+}
+
+void
+x_set_vertical_scroll_bars (f, arg, oldval)
+ struct frame *f;
+ Lisp_Object arg, oldval;
+{
+ if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
+ || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
+ || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
+ || (!NILP (arg) && ! FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
+ {
+ FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
+ = (NILP (arg)
+ ? vertical_scroll_bar_none
+ : EQ (Qright, arg)
+ ? vertical_scroll_bar_right
+ : vertical_scroll_bar_left);
+
+ /* We set this parameter before creating the window for the
+ frame, so we can get the geometry right from the start.
+ However, if the window hasn't been created yet, we shouldn't
+ call x_set_window_size. */
+ if (FRAME_MAC_WINDOW (f))
+ x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
+ do_pending_window_change (0);
+ }
+}
+
+void
+x_set_scroll_bar_width (f, arg, oldval)
+ struct frame *f;
+ Lisp_Object arg, oldval;
+{
+ /* Imitate X without X Toolkit */
+
+ int wid = FONT_WIDTH (f->output_data.mac->font);
+
+ if (NILP (arg))
+ {
+#ifdef MAC_OSX
+ FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 16; /* Aqua scroll bars. */
+ FRAME_SCROLL_BAR_COLS (f) = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) +
+ wid - 1) / wid;
+#else /* not MAC_OSX */
+ /* Make the actual width at least 14 pixels and a multiple of a
+ character width. */
+ FRAME_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
+
+ /* Use all of that space (aside from required margins) for the
+ scroll bar. */
+ FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = 0;
+#endif /* not MAC_OSX */
+ if (FRAME_MAC_WINDOW (f))
+ x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
+ do_pending_window_change (0);
+ }
+ else if (INTEGERP (arg) && XINT (arg) > 0
+ && XFASTINT (arg) != FRAME_SCROLL_BAR_PIXEL_WIDTH (f))
+ {
+ if (XFASTINT (arg) <= 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM)
+ XSETINT (arg, 2 * VERTICAL_SCROLL_BAR_WIDTH_TRIM + 1);
+
+ FRAME_SCROLL_BAR_PIXEL_WIDTH (f) = XFASTINT (arg);
+ FRAME_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
+ if (FRAME_MAC_WINDOW (f))
+ x_set_window_size (f, 0, FRAME_WIDTH (f), FRAME_HEIGHT (f));
+ do_pending_window_change (0);
+ }
+ change_frame_size (f, 0, FRAME_WIDTH (f), 0, 0, 0);
+ XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
+ XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
+}
+\f
+/* Subroutines of creating an frame. */
+
+/* Make sure that Vx_resource_name is set to a reasonable value.
+ Fix it up, or set it to `emacs' if it is too hopeless. */
+
+static void
+validate_x_resource_name ()
+{
+ int len = 0;
+ /* Number of valid characters in the resource name. */
+ int good_count = 0;
+ /* Number of invalid characters in the resource name. */
+ int bad_count = 0;
+ Lisp_Object new;
+ int i;
+
+ if (STRINGP (Vx_resource_name))
+ {
+ unsigned char *p = XSTRING (Vx_resource_name)->data;
+ int i;
+
+ len = STRING_BYTES (XSTRING (Vx_resource_name));
+
+ /* Only letters, digits, - and _ are valid in resource names.
+ Count the valid characters and count the invalid ones. */
+ for (i = 0; i < len; i++)
+ {
+ int c = p[i];
+ if (! ((c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z')
+ || (c >= '0' && c <= '9')
+ || c == '-' || c == '_'))
+ bad_count++;
+ else
+ good_count++;
+ }
+ }
+ else
+ /* Not a string => completely invalid. */
+ bad_count = 5, good_count = 0;
+
+ /* If name is valid already, return. */
+ if (bad_count == 0)
+ return;
+
+ /* If name is entirely invalid, or nearly so, use `emacs'. */
+ if (good_count == 0
+ || (good_count == 1 && bad_count > 0))
+ {
+ Vx_resource_name = build_string ("emacs");
+ return;
+ }
+
+ /* Name is partly valid. Copy it and replace the invalid characters
+ with underscores. */
+
+ Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
+
+ for (i = 0; i < len; i++)
+ {
+ int c = XSTRING (new)->data[i];
+ if (! ((c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z')
+ || (c >= '0' && c <= '9')
+ || c == '-' || c == '_'))
+ XSTRING (new)->data[i] = '_';
+ }
+}
+
+
+#if 0 /* MAC_TODO: implement resource strings */
+extern char *x_get_string_resource ();
+
+DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
+ doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
+This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
+class, where INSTANCE is the name under which Emacs was invoked, or
+the name specified by the `-name' or `-rn' command-line arguments.
+
+The optional arguments COMPONENT and SUBCLASS add to the key and the
+class, respectively. You must specify both of them or neither.
+If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
+and the class is `Emacs.CLASS.SUBCLASS'. */)
+ (attribute, class, component, subclass)
+ Lisp_Object attribute, class, component, subclass;
+{
+ register char *value;
+ char *name_key;
+ char *class_key;
+
+ CHECK_STRING (attribute);
+ CHECK_STRING (class);
+
+ if (!NILP (component))
+ CHECK_STRING (component);
+ if (!NILP (subclass))
+ CHECK_STRING (subclass);
+ if (NILP (component) != NILP (subclass))
+ error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
+
+ validate_x_resource_name ();
+
+ /* Allocate space for the components, the dots which separate them,
+ and the final '\0'. Make them big enough for the worst case. */
+ name_key = (char *) alloca (STRING_BYTES (XSTRING (Vx_resource_name))
+ + (STRINGP (component)
+ ? STRING_BYTES (XSTRING (component)) : 0)
+ + STRING_BYTES (XSTRING (attribute))
+ + 3);
+
+ class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
+ + STRING_BYTES (XSTRING (class))
+ + (STRINGP (subclass)
+ ? STRING_BYTES (XSTRING (subclass)) : 0)
+ + 3);
+
+ /* Start with emacs.FRAMENAME for the name (the specific one)
+ and with `Emacs' for the class key (the general one). */
+ strcpy (name_key, XSTRING (Vx_resource_name)->data);
+ strcpy (class_key, EMACS_CLASS);
+
+ strcat (class_key, ".");
+ strcat (class_key, XSTRING (class)->data);
+
+ if (!NILP (component))
+ {
+ strcat (class_key, ".");
+ strcat (class_key, XSTRING (subclass)->data);
+
+ strcat (name_key, ".");
+ strcat (name_key, XSTRING (component)->data);
+ }
+
+ strcat (name_key, ".");
+ strcat (name_key, XSTRING (attribute)->data);
+
+ value = x_get_string_resource (Qnil,
+ name_key, class_key);
+
+ if (value != (char *) 0)
+ return build_string (value);
+ else
+ return Qnil;
+}
+
+/* Used when C code wants a resource value. */
+
+char *
+x_get_resource_string (attribute, class)
+ char *attribute, *class;
+{
+ char *name_key;
+ char *class_key;
+ struct frame *sf = SELECTED_FRAME ();
+
+ /* Allocate space for the components, the dots which separate them,
+ and the final '\0'. */
+ name_key = (char *) alloca (STRING_BYTES (XSTRING (Vinvocation_name))
+ + strlen (attribute) + 2);
+ class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
+ + strlen (class) + 2);
+
+ sprintf (name_key, "%s.%s",
+ XSTRING (Vinvocation_name)->data,
+ attribute);
+ sprintf (class_key, "%s.%s", EMACS_CLASS, class);
+
+ return x_get_string_resource (sf, name_key, class_key);
+}
+#endif /* MAC_TODO */
+
+/* Types we might convert a resource string into. */
+enum resource_types
+{
+ RES_TYPE_NUMBER,
+ RES_TYPE_FLOAT,
+ RES_TYPE_BOOLEAN,
+ RES_TYPE_STRING,
+ RES_TYPE_SYMBOL
+};
+
+/* Return the value of parameter PARAM.
+
+ First search ALIST, then Vdefault_frame_alist, then the X defaults
+ database, using ATTRIBUTE as the attribute name and CLASS as its class.
+
+ Convert the resource to the type specified by desired_type.
+
+ If no default is specified, return Qunbound. If you call
+ w32_get_arg, make sure you deal with Qunbound in a reasonable way,
+ and don't let it get stored in any Lisp-visible variables! */
+
+static Lisp_Object
+mac_get_arg (alist, param, attribute, class, type)
+ Lisp_Object alist, param;
+ char *attribute;
+ char *class;
+ enum resource_types type;
+{
+ register Lisp_Object tem;
+
+ tem = Fassq (param, alist);
+ if (EQ (tem, Qnil))
+ tem = Fassq (param, Vdefault_frame_alist);
+ if (EQ (tem, Qnil))
+ {
+
+#if 0 /* MAC_TODO: search resource also */
+ if (attribute)
+ {
+ tem = Fx_get_resource (build_string (attribute),
+ build_string (class),
+ Qnil, Qnil);
+
+ if (NILP (tem))
+ return Qunbound;
+
+ switch (type)
+ {
+ case RES_TYPE_NUMBER:
+ return make_number (atoi (XSTRING (tem)->data));
+
+ case RES_TYPE_FLOAT:
+ return make_float (atof (XSTRING (tem)->data));
+
+ case RES_TYPE_BOOLEAN:
+ tem = Fdowncase (tem);
+ if (!strcmp (XSTRING (tem)->data, "on")
+ || !strcmp (XSTRING (tem)->data, "true"))
+ return Qt;
+ else
+ return Qnil;
+
+ case RES_TYPE_STRING:
+ return tem;
+
+ case RES_TYPE_SYMBOL:
+ /* As a special case, we map the values `true' and `on'
+ to Qt, and `false' and `off' to Qnil. */
+ {
+ Lisp_Object lower;
+ lower = Fdowncase (tem);
+ if (!strcmp (XSTRING (lower)->data, "on")
+ || !strcmp (XSTRING (lower)->data, "true"))
+ return Qt;
+ else if (!strcmp (XSTRING (lower)->data, "off")
+ || !strcmp (XSTRING (lower)->data, "false"))
+ return Qnil;
+ else
+ return Fintern (tem, Qnil);
+ }
+
+ default:
+ abort ();
+ }
+ }
+ else
+#endif /* MAC_TODO */
+ return Qunbound;
+ }
+ return Fcdr (tem);
+}
+
+/* Record in frame F the specified or default value according to ALIST
+ of the parameter named PROP (a Lisp symbol).
+ If no value is specified for PROP, look for an X default for XPROP
+ on the frame named NAME.
+ If that is not found either, use the value DEFLT. */
+
+static Lisp_Object
+x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
+ struct frame *f;
+ Lisp_Object alist;
+ Lisp_Object prop;
+ Lisp_Object deflt;
+ char *xprop;
+ char *xclass;
+ enum resource_types type;
+{
+ Lisp_Object tem;
+
+ tem = mac_get_arg (alist, prop, xprop, xclass, type);
+ if (EQ (tem, Qunbound))
+ tem = deflt;
+ x_set_frame_parameters (f, Fcons (Fcons (prop, tem), Qnil));
+ return tem;
+}
+\f
+/* XParseGeometry copied from w32xfns.c */
+
+/*
+ * XParseGeometry parses strings of the form
+ * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
+ * width, height, xoffset, and yoffset are unsigned integers.
+ * Example: "=80x24+300-49"
+ * The equal sign is optional.
+ * It returns a bitmask that indicates which of the four values
+ * were actually found in the string. For each value found,
+ * the corresponding argument is updated; for each value
+ * not found, the corresponding argument is left unchanged.
+ */
+
+static int
+read_integer (string, NextString)
+ register char *string;
+ char **NextString;
+{
+ register int Result = 0;
+ int Sign = 1;
+
+ if (*string == '+')
+ string++;
+ else if (*string == '-')
+ {
+ string++;
+ Sign = -1;
+ }
+ for (; (*string >= '0') && (*string <= '9'); string++)
+ {
+ Result = (Result * 10) + (*string - '0');
+ }
+ *NextString = string;
+ if (Sign >= 0)
+ return (Result);
+ else
+ return (-Result);
+}
+
+int
+XParseGeometry (string, x, y, width, height)
+ char *string;
+ int *x, *y;
+ unsigned int *width, *height; /* RETURN */
+{
+ int mask = NoValue;
+ register char *strind;
+ unsigned int tempWidth, tempHeight;
+ int tempX, tempY;
+ char *nextCharacter;
+
+ if ((string == NULL) || (*string == '\0')) return (mask);
+ if (*string == '=')
+ string++; /* ignore possible '=' at beg of geometry spec */
+
+ strind = (char *)string;
+ if (*strind != '+' && *strind != '-' && *strind != 'x')
+ {
+ tempWidth = read_integer (strind, &nextCharacter);
+ if (strind == nextCharacter)
+ return (0);
+ strind = nextCharacter;
+ mask |= WidthValue;
+ }
+
+ if (*strind == 'x' || *strind == 'X')
+ {
+ strind++;
+ tempHeight = read_integer (strind, &nextCharacter);
+ if (strind == nextCharacter)
+ return (0);
+ strind = nextCharacter;
+ mask |= HeightValue;
+ }
+
+ if ((*strind == '+') || (*strind == '-'))
+ {
+ if (*strind == '-')
+ {
+ strind++;
+ tempX = -read_integer (strind, &nextCharacter);
+ if (strind == nextCharacter)
+ return (0);
+ strind = nextCharacter;
+ mask |= XNegative;
+
+ }
+ else
+ {
+ strind++;
+ tempX = read_integer (strind, &nextCharacter);
+ if (strind == nextCharacter)
+ return (0);
+ strind = nextCharacter;
+ }
+ mask |= XValue;
+ if ((*strind == '+') || (*strind == '-'))
+ {
+ if (*strind == '-')
+ {
+ strind++;
+ tempY = -read_integer (strind, &nextCharacter);
+ if (strind == nextCharacter)
+ return (0);
+ strind = nextCharacter;
+ mask |= YNegative;
+
+ }
+ else
+ {
+ strind++;
+ tempY = read_integer (strind, &nextCharacter);
+ if (strind == nextCharacter)
+ return (0);
+ strind = nextCharacter;
+ }
+ mask |= YValue;
+ }
+ }
+
+ /* If strind isn't at the end of the string the it's an invalid
+ geometry specification. */
+
+ if (*strind != '\0') return (0);
+
+ if (mask & XValue)
+ *x = tempX;
+ if (mask & YValue)
+ *y = tempY;
+ if (mask & WidthValue)
+ *width = tempWidth;
+ if (mask & HeightValue)
+ *height = tempHeight;
+ return (mask);
+}
+
+DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
+ doc: /* Parse an X-style geometry string STRING.
+Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
+The properties returned may include `top', `left', `height', and `width'.
+The value of `left' or `top' may be an integer,
+or a list (+ N) meaning N pixels relative to top/left corner,
+or a list (- N) meaning -N pixels relative to bottom/right corner. */)
+ (string)
+ Lisp_Object string;
+{
+ int geometry, x, y;
+ unsigned int width, height;
+ Lisp_Object result;
+
+ CHECK_STRING (string);
+
+ geometry = XParseGeometry ((char *) XSTRING (string)->data,
+ &x, &y, &width, &height);
+
+ result = Qnil;
+ if (geometry & XValue)
+ {
+ Lisp_Object element;
+
+ if (x >= 0 && (geometry & XNegative))
+ element = Fcons (Qleft, Fcons (Qminus, Fcons (make_number (-x), Qnil)));
+ else if (x < 0 && ! (geometry & XNegative))
+ element = Fcons (Qleft, Fcons (Qplus, Fcons (make_number (x), Qnil)));
+ else
+ element = Fcons (Qleft, make_number (x));
+ result = Fcons (element, result);
+ }
+
+ if (geometry & YValue)
+ {
+ Lisp_Object element;
+
+ if (y >= 0 && (geometry & YNegative))
+ element = Fcons (Qtop, Fcons (Qminus, Fcons (make_number (-y), Qnil)));
+ else if (y < 0 && ! (geometry & YNegative))
+ element = Fcons (Qtop, Fcons (Qplus, Fcons (make_number (y), Qnil)));
+ else
+ element = Fcons (Qtop, make_number (y));
+ result = Fcons (element, result);
+ }
+
+ if (geometry & WidthValue)
+ result = Fcons (Fcons (Qwidth, make_number (width)), result);
+ if (geometry & HeightValue)
+ result = Fcons (Fcons (Qheight, make_number (height)), result);
+
+ return result;
+}
+
+/* Calculate the desired size and position of this window,
+ and return the flags saying which aspects were specified.
+
+ This function does not make the coordinates positive. */
+
+#define DEFAULT_ROWS 40
+#define DEFAULT_COLS 80
+
+static int
+x_figure_window_size (f, parms)
+ struct frame *f;
+ Lisp_Object parms;
+{
+ register Lisp_Object tem0, tem1, tem2;
+ long window_prompting = 0;
+
+ /* Default values if we fall through.
+ Actually, if that happens we should get
+ window manager prompting. */
+ SET_FRAME_WIDTH (f, DEFAULT_COLS);
+ f->height = DEFAULT_ROWS;
+ /* Window managers expect that if program-specified
+ positions are not (0,0), they're intentional, not defaults. */
+ f->output_data.mac->top_pos = 0;
+ f->output_data.mac->left_pos = 0;
+
+ tem0 = mac_get_arg (parms, Qheight, 0, 0, RES_TYPE_NUMBER);
+ tem1 = mac_get_arg (parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
+ tem2 = mac_get_arg (parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
+ if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
+ {
+ if (!EQ (tem0, Qunbound))
+ {
+ CHECK_NUMBER (tem0);
+ f->height = XINT (tem0);
+ }
+ if (!EQ (tem1, Qunbound))
+ {
+ CHECK_NUMBER (tem1);
+ SET_FRAME_WIDTH (f, XINT (tem1));
+ }
+ if (!NILP (tem2) && !EQ (tem2, Qunbound))
+ window_prompting |= USSize;
+ else
+ window_prompting |= PSize;
+ }
+
+ f->output_data.mac->vertical_scroll_bar_extra
+ = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
+ ? 0
+ : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
+ ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
+ : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.mac->font)));
+
+ x_compute_fringe_widths (f, 0);
+
+ f->output_data.mac->pixel_width = CHAR_TO_PIXEL_WIDTH (f, f->width);
+ f->output_data.mac->pixel_height = CHAR_TO_PIXEL_HEIGHT (f, f->height);
+
+ tem0 = mac_get_arg (parms, Qtop, 0, 0, RES_TYPE_NUMBER);
+ tem1 = mac_get_arg (parms, Qleft, 0, 0, RES_TYPE_NUMBER);
+ tem2 = mac_get_arg (parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
+ if (! EQ (tem0, Qunbound) || ! EQ (tem1, Qunbound))
+ {
+ if (EQ (tem0, Qminus))
+ {
+ f->output_data.mac->top_pos = 0;
+ window_prompting |= YNegative;
+ }
+ else if (CONSP (tem0) && EQ (XCAR (tem0), Qminus)
+ && CONSP (XCDR (tem0))
+ && INTEGERP (XCAR (XCDR (tem0))))
+ {
+ f->output_data.mac->top_pos = - XINT (XCAR (XCDR (tem0)));
+ window_prompting |= YNegative;
+ }
+ else if (CONSP (tem0) && EQ (XCAR (tem0), Qplus)
+ && CONSP (XCDR (tem0))
+ && INTEGERP (XCAR (XCDR (tem0))))
+ {
+ f->output_data.mac->top_pos = XINT (XCAR (XCDR (tem0)));
+ }
+ else if (EQ (tem0, Qunbound))
+ f->output_data.mac->top_pos = 0;
+ else
+ {
+ CHECK_NUMBER (tem0);
+ f->output_data.mac->top_pos = XINT (tem0);
+ if (f->output_data.mac->top_pos < 0)
+ window_prompting |= YNegative;
+ }
+
+ if (EQ (tem1, Qminus))
+ {
+ f->output_data.mac->left_pos = 0;
+ window_prompting |= XNegative;
+ }
+ else if (CONSP (tem1) && EQ (XCAR (tem1), Qminus)
+ && CONSP (XCDR (tem1))
+ && INTEGERP (XCAR (XCDR (tem1))))
+ {
+ f->output_data.mac->left_pos = - XINT (XCAR (XCDR (tem1)));
+ window_prompting |= XNegative;
+ }
+ else if (CONSP (tem1) && EQ (XCAR (tem1), Qplus)
+ && CONSP (XCDR (tem1))
+ && INTEGERP (XCAR (XCDR (tem1))))
+ {
+ f->output_data.mac->left_pos = XINT (XCAR (XCDR (tem1)));
+ }
+ else if (EQ (tem1, Qunbound))
+ f->output_data.mac->left_pos = 0;
+ else
+ {
+ CHECK_NUMBER (tem1);
+ f->output_data.mac->left_pos = XINT (tem1);
+ if (f->output_data.mac->left_pos < 0)
+ window_prompting |= XNegative;
+ }
+
+ if (!NILP (tem2) && ! EQ (tem2, Qunbound))
+ window_prompting |= USPosition;
+ else
+ window_prompting |= PPosition;
+ }
+
+ return window_prompting;
+}
+
+\f
+#if 0 /* MAC_TODO */
+/* Create and set up the Mac window for frame F. */
+
+static void
+mac_window (f, window_prompting, minibuffer_only)
+ struct frame *f;
+ long window_prompting;
+ int minibuffer_only;
+{
+ Rect r;
+
+ BLOCK_INPUT;
+
+ /* Use the resource name as the top-level window name
+ for looking up resources. Make a non-Lisp copy
+ for the window manager, so GC relocation won't bother it.
+
+ Elsewhere we specify the window name for the window manager. */
+
+ {
+ char *str = (char *) XSTRING (Vx_resource_name)->data;
+ f->namebuf = (char *) xmalloc (strlen (str) + 1);
+ strcpy (f->namebuf, str);
+ }
+
+ SetRect (&r, f->output_data.mac->left_pos, f->output_data.mac->top_pos,
+ f->output_data.mac->left_pos + PIXEL_WIDTH (f),
+ f->output_data.mac->top_pos + PIXEL_HEIGHT (f));
+ FRAME_MAC_WINDOW (f)
+ = NewCWindow (NULL, &r, "\p", 1, zoomDocProc, (WindowPtr) -1, 1, (long) f->output_data.mac);
+
+ validate_x_resource_name ();
+
+ /* x_set_name normally ignores requests to set the name if the
+ requested name is the same as the current name. This is the one
+ place where that assumption isn't correct; f->name is set, but
+ the server hasn't been told. */
+ {
+ Lisp_Object name;
+ int explicit = f->explicit_name;
+
+ f->explicit_name = 0;
+ name = f->name;
+ f->name = Qnil;
+ x_set_name (f, name, explicit);
+ }
+
+ ShowWindow (FRAME_MAC_WINDOW (f));
+
+ UNBLOCK_INPUT;
+
+ if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
+ initialize_frame_menubar (f);
+
+ if (FRAME_MAC_WINDOW (f) == 0)
+ error ("Unable to create window");
+}
+#endif /* MAC_TODO */
+
+/* Handle the icon stuff for this window. Perhaps later we might
+ want an x_set_icon_position which can be called interactively as
+ well. */
+
+static void
+x_icon (f, parms)
+ struct frame *f;
+ Lisp_Object parms;
+{
+ Lisp_Object icon_x, icon_y;
+
+ /* Set the position of the icon. Note that Windows 95 groups all
+ icons in the tray. */
+ icon_x = mac_get_arg (parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
+ icon_y = mac_get_arg (parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
+ if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
+ {
+ CHECK_NUMBER (icon_x);
+ CHECK_NUMBER (icon_y);
+ }
+ else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
+ error ("Both left and top icon corners of icon must be specified");
+
+ BLOCK_INPUT;
+
+ if (! EQ (icon_x, Qunbound))
+ x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
+
+#if 0 /* TODO */
+ /* Start up iconic or window? */
+ x_wm_set_window_state
+ (f, (EQ (w32_get_arg (parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL), Qicon)
+ ? IconicState
+ : NormalState));
+
+ x_text_icon (f, (char *) XSTRING ((!NILP (f->icon_name)
+ ? f->icon_name
+ : f->name))->data);
+#endif
+
+ UNBLOCK_INPUT;
+}
+
+
+void
+x_make_gc (f)
+ struct frame *f;
+{
+ XGCValues gc_values;
+
+ BLOCK_INPUT;
+
+ /* Create the GC's of this frame.
+ Note that many default values are used. */
+
+ /* Normal video */
+ gc_values.font = f->output_data.mac->font;
+ gc_values.foreground = FRAME_FOREGROUND_PIXEL (f);
+ gc_values.background = FRAME_BACKGROUND_PIXEL (f);
+ f->output_data.mac->normal_gc = XCreateGC (FRAME_MAC_DISPLAY (f),
+ FRAME_MAC_WINDOW (f),
+ GCFont | GCForeground | GCBackground,
+ &gc_values);
+
+ /* Reverse video style. */
+ gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
+ gc_values.background = FRAME_FOREGROUND_PIXEL (f);
+ f->output_data.mac->reverse_gc = XCreateGC (FRAME_MAC_DISPLAY (f),
+ FRAME_MAC_WINDOW (f),
+ GCFont | GCForeground | GCBackground,
+ &gc_values);
+
+ /* Cursor has cursor-color background, background-color foreground. */
+ gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
+ gc_values.background = f->output_data.mac->cursor_pixel;
+ f->output_data.mac->cursor_gc = XCreateGC (FRAME_MAC_DISPLAY (f),
+ FRAME_MAC_WINDOW (f),
+ GCFont | GCForeground | GCBackground,
+ &gc_values);
+
+ /* Reliefs. */
+ f->output_data.mac->white_relief.gc = 0;
+ f->output_data.mac->black_relief.gc = 0;
+
+ UNBLOCK_INPUT;
+}
+
+
+DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
+ 1, 1, 0,
+ doc: /* Make a new window, which is called a \"frame\" in Emacs terms.
+Returns an Emacs frame object.
+ALIST is an alist of frame parameters.
+If the parameters specify that the frame should not have a minibuffer,
+and do not specify a specific minibuffer window to use,
+then `default-minibuffer-frame' must be a frame whose minibuffer can
+be shared by the new frame.
+
+This function is an internal primitive--use `make-frame' instead. */)
+ (parms)
+ Lisp_Object parms;
+{
+ struct frame *f;
+ Lisp_Object frame, tem;
+ Lisp_Object name;
+ int minibuffer_only = 0;
+ long window_prompting = 0;
+ int width, height;
+ int count = BINDING_STACK_SIZE ();
+ struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+ Lisp_Object display;
+ struct mac_display_info *dpyinfo = NULL;
+ Lisp_Object parent;
+ struct kboard *kb;
+ char x_frame_name[10];
+ static int x_frame_count = 2; /* begins at 2 because terminal frame is F1 */
+
+ check_mac ();
+
+ /* Use this general default value to start with
+ until we know if this frame has a specified name. */
+ Vx_resource_name = Vinvocation_name;
+
+ display = mac_get_arg (parms, Qdisplay, 0, 0, RES_TYPE_STRING);
+ if (EQ (display, Qunbound))
+ display = Qnil;
+ dpyinfo = check_x_display_info (display);
+#ifdef MULTI_KBOARD
+ kb = dpyinfo->kboard;
+#else
+ kb = &the_only_kboard;
+#endif
+
+ name = mac_get_arg (parms, Qname, "name", "Name", RES_TYPE_STRING);
+ if (!STRINGP (name)
+ && ! EQ (name, Qunbound)
+ && ! NILP (name))
+ error ("Invalid frame name--not a string or nil");
+
+ if (STRINGP (name))
+ Vx_resource_name = name;
+
+ /* See if parent window is specified. */
+ parent = mac_get_arg (parms, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
+ if (EQ (parent, Qunbound))
+ parent = Qnil;
+ if (! NILP (parent))
+ CHECK_NUMBER (parent);
+
+ /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
+ /* No need to protect DISPLAY because that's not used after passing
+ it to make_frame_without_minibuffer. */
+ frame = Qnil;
+ GCPRO4 (parms, parent, name, frame);
+ tem = mac_get_arg (parms, Qminibuffer, "minibuffer", "Minibuffer",
+ RES_TYPE_SYMBOL);
+ if (EQ (tem, Qnone) || NILP (tem))
+ f = make_frame_without_minibuffer (Qnil, kb, display);
+ else if (EQ (tem, Qonly))
+ {
+ f = make_minibuffer_frame ();
+ minibuffer_only = 1;
+ }
+ else if (WINDOWP (tem))
+ f = make_frame_without_minibuffer (tem, kb, display);
+ else
+ f = make_frame (1);
+
+ if (EQ (name, Qunbound) || NILP (name))
+ {
+ sprintf (x_frame_name, "F%d", x_frame_count++);
+ f->name = build_string (x_frame_name);
+ f->explicit_name = 0;
+ }
+ else
+ {
+ f->name = name;
+ f->explicit_name = 1;
+ }
+
+ XSETFRAME (frame, f);
+
+ /* Note that X Windows does support scroll bars. */
+ FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
+
+ f->output_method = output_mac;
+ f->output_data.mac = (struct mac_output *) xmalloc (sizeof (struct mac_output));
+ bzero (f->output_data.mac, sizeof (struct mac_output));
+ FRAME_FONTSET (f) = -1;
+ f->output_data.mac->scroll_bar_foreground_pixel = -1;
+ f->output_data.mac->scroll_bar_background_pixel = -1;
+
+#if 0
+ FRAME_FONTSET (f) = -1;
+#endif
+
+ f->icon_name
+ = mac_get_arg (parms, Qicon_name, "iconName", "Title", RES_TYPE_STRING);
+ if (! STRINGP (f->icon_name))
+ f->icon_name = Qnil;
+
+/* FRAME_W32_DISPLAY_INFO (f) = dpyinfo; */
+#ifdef MULTI_KBOARD
+ FRAME_KBOARD (f) = kb;
+#endif
+
+ /* Specify the parent under which to make this window. */
+
+ if (!NILP (parent))
+ {
+ f->output_data.mac->parent_desc = (Window) parent;
+ f->output_data.mac->explicit_parent = 1;
+ }
+ else
+ {
+ f->output_data.mac->parent_desc = FRAME_MAC_DISPLAY_INFO (f)->root_window;
+ f->output_data.mac->explicit_parent = 0;
+ }
+
+ /* Set the name; the functions to which we pass f expect the name to
+ be set. */
+ if (EQ (name, Qunbound) || NILP (name))
+ {
+ f->name = build_string (dpyinfo->mac_id_name);
+ f->explicit_name = 0;
+ }
+ else
+ {
+ f->name = name;
+ f->explicit_name = 1;
+ /* use the frame's title when getting resources for this frame. */
+ specbind (Qx_resource_name, name);
+ }
+
+ /* Extract the window parameters from the supplied values
+ that are needed to determine window geometry. */
+ {
+ Lisp_Object font;
+
+ font = mac_get_arg (parms, Qfont, "font", "Font", RES_TYPE_STRING);
+
+ BLOCK_INPUT;
+ /* First, try whatever font the caller has specified. */
+ if (STRINGP (font))
+ {
+ tem = Fquery_fontset (font, Qnil);
+ if (STRINGP (tem))
+ font = x_new_fontset (f, XSTRING (tem)->data);
+ else
+ font = x_new_font (f, XSTRING (font)->data);
+ }
+ /* Try out a font which we hope has bold and italic variations. */
+ if (! STRINGP (font))
+ font = x_new_font (f, "-ETL-fixed-medium-r-*--*-160-*-*-*-*-iso8859-1");
+ /* If those didn't work, look for something which will at least work. */
+ if (!STRINGP (font))
+ font = x_new_font (f, "-*-monaco-*-12-*-mac-roman");
+ if (! STRINGP (font))
+ font = x_new_font (f, "-*-courier-*-10-*-mac-roman");
+ if (! STRINGP (font))
+ error ("Cannot find any usable font");
+ UNBLOCK_INPUT;
+
+ x_default_parameter (f, parms, Qfont, font,
+ "font", "Font", RES_TYPE_STRING);
+ }
+
+ x_default_parameter (f, parms, Qborder_width, make_number (0),
+ "borderwidth", "BorderWidth", RES_TYPE_NUMBER);
+ /* This defaults to 2 in order to match xterm. We recognize either
+ internalBorderWidth or internalBorder (which is what xterm calls
+ it). */
+ if (NILP (Fassq (Qinternal_border_width, parms)))
+ {
+ Lisp_Object value;
+
+ value = mac_get_arg (parms, Qinternal_border_width,
+ "internalBorder", "InternalBorder", RES_TYPE_NUMBER);
+ if (! EQ (value, Qunbound))
+ parms = Fcons (Fcons (Qinternal_border_width, value),
+ parms);
+ }
+ /* Default internalBorderWidth to 0 on Windows to match other programs. */
+ x_default_parameter (f, parms, Qinternal_border_width, make_number (0),
+ "internalBorderWidth", "InternalBorder", RES_TYPE_NUMBER);
+ x_default_parameter (f, parms, Qvertical_scroll_bars, Qright,
+ "verticalScrollBars", "ScrollBars", RES_TYPE_SYMBOL);
+
+ /* Also do the stuff which must be set before the window exists. */
+ x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
+ "foreground", "Foreground", RES_TYPE_STRING);
+ x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
+ "background", "Background", RES_TYPE_STRING);
+ x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
+ "pointerColor", "Foreground", RES_TYPE_STRING);
+ x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
+ "cursorColor", "Foreground", RES_TYPE_STRING);
+ x_default_parameter (f, parms, Qborder_color, build_string ("black"),
+ "borderColor", "BorderColor", RES_TYPE_STRING);
+ x_default_parameter (f, parms, Qscreen_gamma, Qnil,
+ "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
+ x_default_parameter (f, parms, Qline_spacing, Qnil,
+ "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
+ x_default_parameter (f, parms, Qleft_fringe, Qnil,
+ "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
+ x_default_parameter (f, parms, Qright_fringe, Qnil,
+ "rightFringe", "RightFringe", RES_TYPE_NUMBER);
+
+
+ /* Init faces before x_default_parameter is called for scroll-bar
+ parameters because that function calls x_set_scroll_bar_width,
+ which calls change_frame_size, which calls Fset_window_buffer,
+ which runs hooks, which call Fvertical_motion. At the end, we
+ end up in init_iterator with a null face cache, which should not
+ happen. */
+ init_frame_faces (f);
+
+ x_default_parameter (f, parms, Qmenu_bar_lines, make_number (1),
+ "menuBar", "MenuBar", RES_TYPE_NUMBER);
+ x_default_parameter (f, parms, Qtool_bar_lines, make_number (0),
+ "toolBar", "ToolBar", RES_TYPE_NUMBER);
+ x_default_parameter (f, parms, Qbuffer_predicate, Qnil,
+ "bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL);
+ x_default_parameter (f, parms, Qtitle, Qnil,
+ "title", "Title", RES_TYPE_STRING);
+
+ f->output_data.mac->parent_desc = FRAME_MAC_DISPLAY_INFO (f)->root_window;
+ window_prompting = x_figure_window_size (f, parms);
+
+ if (window_prompting & XNegative)
+ {
+ if (window_prompting & YNegative)
+ f->output_data.mac->win_gravity = SouthEastGravity;
+ else
+ f->output_data.mac->win_gravity = NorthEastGravity;
+ }
+ else
+ {
+ if (window_prompting & YNegative)
+ f->output_data.mac->win_gravity = SouthWestGravity;
+ else
+ f->output_data.mac->win_gravity = NorthWestGravity;
+ }
+
+ f->output_data.mac->size_hint_flags = window_prompting;
+
+ tem = mac_get_arg (parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
+ f->no_split = minibuffer_only || EQ (tem, Qt);
+
+ /* Create the window. Add the tool-bar height to the initial frame
+ height so that the user gets a text display area of the size he
+ specified with -g or via the registry. Later changes of the
+ tool-bar height don't change the frame size. This is done so that
+ users can create tall Emacs frames without having to guess how
+ tall the tool-bar will get. */
+ f->height += FRAME_TOOL_BAR_LINES (f);
+
+ /* mac_window (f, window_prompting, minibuffer_only); */
+ make_mac_frame (f);
+
+ x_icon (f, parms);
+
+ x_make_gc (f);
+
+ /* Now consider the frame official. */
+ FRAME_MAC_DISPLAY_INFO (f)->reference_count++;
+ Vframe_list = Fcons (frame, Vframe_list);
+
+ /* We need to do this after creating the window, so that the
+ icon-creation functions can say whose icon they're describing. */
+ x_default_parameter (f, parms, Qicon_type, Qnil,
+ "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
+
+ x_default_parameter (f, parms, Qauto_raise, Qnil,
+ "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
+ x_default_parameter (f, parms, Qauto_lower, Qnil,
+ "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
+ x_default_parameter (f, parms, Qcursor_type, Qbox,
+ "cursorType", "CursorType", RES_TYPE_SYMBOL);
+ x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
+ "scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER);
+
+ /* Dimensions, especially f->height, must be done via change_frame_size.
+ Change will not be effected unless different from the current
+ f->height. */
+ width = f->width;
+ height = f->height;
+
+ f->height = 0;
+ SET_FRAME_WIDTH (f, 0);
+ change_frame_size (f, height, width, 1, 0, 0);
+
+ /* Set up faces after all frame parameters are known. */
+ call1 (Qface_set_after_frame_default, frame);
+
+#if 0 /* MAC_TODO: when we have window manager hints */
+ /* Tell the server what size and position, etc, we want, and how
+ badly we want them. This should be done after we have the menu
+ bar so that its size can be taken into account. */
+ BLOCK_INPUT;
+ x_wm_set_size_hint (f, window_prompting, 0);
+ UNBLOCK_INPUT;
+#endif
+
+ /* Make the window appear on the frame and enable display, unless
+ the caller says not to. However, with explicit parent, Emacs
+ cannot control visibility, so don't try. */
+ if (! f->output_data.mac->explicit_parent)
+ {
+ Lisp_Object visibility;
+
+ visibility = mac_get_arg (parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
+ if (EQ (visibility, Qunbound))
+ visibility = Qt;
+
+#if 0 /* MAC_TODO: really no iconify on Mac */
+ if (EQ (visibility, Qicon))
+ x_iconify_frame (f);
+ else
+#endif
+ if (! NILP (visibility))
+ x_make_frame_visible (f);
+ else
+ /* Must have been Qnil. */
+ ;
+ }
+ UNGCPRO;
+
+ /* Make sure windows on this frame appear in calls to next-window
+ and similar functions. */
+ Vwindow_list = Qnil;
+
+ return unbind_to (count, frame);
+}
+
+/* FRAME is used only to get a handle on the X display. We don't pass the
+ display info directly because we're called from frame.c, which doesn't
+ know about that structure. */
+Lisp_Object
+x_get_focus_frame (frame)
+ struct frame *frame;
+{
+ struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
+ Lisp_Object xfocus;
+ if (! dpyinfo->x_focus_frame)
+ return Qnil;
+
+ XSETFRAME (xfocus, dpyinfo->x_focus_frame);
+ return xfocus;
+}
+\f
+DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
+ doc: /* Internal function called by `color-defined-p', which see. */)
+ (color, frame)
+ Lisp_Object color, frame;
+{
+ XColor foo;
+ FRAME_PTR f = check_x_frame (frame);
+
+ CHECK_STRING (color);
+
+ if (mac_defined_color (f, XSTRING (color)->data, &foo, 0))
+ return Qt;
+ else
+ return Qnil;
+}
+
+DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
+ doc: /* Internal function called by `color-values', which see. */)
+ (color, frame)
+ Lisp_Object color, frame;
+{
+ XColor foo;
+ FRAME_PTR f = check_x_frame (frame);
+
+ CHECK_STRING (color);
+
+ if (mac_defined_color (f, XSTRING (color)->data, &foo, 0))
+ {
+ Lisp_Object rgb[3];
+
+ rgb[0] = make_number ((RED_FROM_ULONG (foo.pixel) << 8)
+ | RED_FROM_ULONG (foo.pixel));
+ rgb[1] = make_number ((GREEN_FROM_ULONG (foo.pixel) << 8)
+ | GREEN_FROM_ULONG (foo.pixel));
+ rgb[2] = make_number ((BLUE_FROM_ULONG (foo.pixel) << 8)
+ | BLUE_FROM_ULONG (foo.pixel));
+ return Flist (3, rgb);
+ }
+ else
+ return Qnil;
+}
+
+DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
+ doc: /* Internal function called by `display-color-p', which see. */)
+ (display)
+ Lisp_Object display;
+{
+ struct mac_display_info *dpyinfo = check_x_display_info (display);
+
+ if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 2)
+ return Qnil;
+
+ return Qt;
+}
+
+DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
+ 0, 1, 0,
+ doc: /* Return t if the X display supports shades of gray.
+Note that color displays do support shades of gray.
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display. */)
+ (display)
+ Lisp_Object display;
+{
+ struct mac_display_info *dpyinfo = check_x_display_info (display);
+
+ if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 1)
+ return Qnil;
+
+ return Qt;
+}
+
+DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
+ 0, 1, 0,
+ doc: /* Returns the width in pixels of the X display DISPLAY.
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display. */)
+ (display)
+ Lisp_Object display;
+{
+ struct mac_display_info *dpyinfo = check_x_display_info (display);
+
+ return make_number (dpyinfo->width);
+}
+
+DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
+ Sx_display_pixel_height, 0, 1, 0,
+ doc: /* Returns the height in pixels of the X display DISPLAY.
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display. */)
+ (display)
+ Lisp_Object display;
+{
+ struct mac_display_info *dpyinfo = check_x_display_info (display);
+
+ return make_number (dpyinfo->height);
+}
+
+DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
+ 0, 1, 0,
+ doc: /* Returns the number of bitplanes of the display DISPLAY.
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display. */)
+ (display)
+ Lisp_Object display;
+{
+ struct mac_display_info *dpyinfo = check_x_display_info (display);
+
+ return make_number (dpyinfo->n_planes * dpyinfo->n_cbits);
+}
+
+DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
+ 0, 1, 0,
+ doc: /* Returns the number of color cells of the display DISPLAY.
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display. */)
+ (display)
+ Lisp_Object display;
+{
+ struct mac_display_info *dpyinfo = check_x_display_info (display);
+
+ /* MAC_TODO: check whether this is right */
+ return make_number ((unsigned long) (pow (2, dpyinfo->n_cbits)));
+}
+
+DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
+ Sx_server_max_request_size,
+ 0, 1, 0,
+ doc: /* Returns the maximum request size of the server of display DISPLAY.
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display. */)
+ (display)
+ Lisp_Object display;
+{
+ struct mac_display_info *dpyinfo = check_x_display_info (display);
+
+ return make_number (1);
+}
+
+DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
+ doc: /* Returns the vendor ID string of the Mac OS system (Apple).
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display. */)
+ (display)
+ Lisp_Object display;
+{
+ return build_string ("Apple Computers");
+}
+
+DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
+ doc: /* Returns the version numbers of the server of display DISPLAY.
+The value is a list of three integers: the major and minor
+version numbers, and the vendor-specific release
+number. See also the function `x-server-vendor'.
+
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display. */)
+ (display)
+ Lisp_Object display;
+{
+ int mac_major_version, mac_minor_version;
+ SInt32 response;
+
+ if (Gestalt (gestaltSystemVersion, &response) != noErr)
+ error ("Cannot get Mac OS version");
+
+ mac_major_version = (response >> 8) & 0xf;
+ mac_minor_version = (response >> 4) & 0xf;
+
+ return Fcons (make_number (mac_major_version),
+ Fcons (make_number (mac_minor_version), Qnil));
+}
+
+DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
+ doc: /* Return the number of screens on the server of display DISPLAY.
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display. */)
+ (display)
+ Lisp_Object display;
+{
+ return make_number (1);
+}
+
+DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
+ doc: /* Return the height in millimeters of the X display DISPLAY.
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display. */)
+ (display)
+ Lisp_Object display;
+{
+ /* MAC_TODO: this is an approximation, and only of the main display */
+
+ struct mac_display_info *dpyinfo = check_x_display_info (display);
+ short h, v;
+
+ ScreenRes (&h, &v);
+
+ return make_number ((int) (v / 72.0 * 25.4));
+}
+
+DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
+ doc: /* Return the width in millimeters of the X display DISPLAY.
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display. */)
+ (display)
+ Lisp_Object display;
+{
+ /* MAC_TODO: this is an approximation, and only of the main display */
+
+ struct mac_display_info *dpyinfo = check_x_display_info (display);
+ short h, v;
+
+ ScreenRes (&h, &v);
+
+ return make_number ((int) (h / 72.0 * 25.4));
+}
+
+DEFUN ("x-display-backing-store", Fx_display_backing_store,
+ Sx_display_backing_store, 0, 1, 0,
+ doc: /* Returns an indication of whether display DISPLAY does backing store.
+The value may be `always', `when-mapped', or `not-useful'.
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display. */)
+ (display)
+ Lisp_Object display;
+{
+ return intern ("not-useful");
+}
+
+DEFUN ("x-display-visual-class", Fx_display_visual_class,
+ Sx_display_visual_class, 0, 1, 0,
+ doc: /* Returns the visual class of the display DISPLAY.
+The value is one of the symbols `static-gray', `gray-scale',
+`static-color', `pseudo-color', `true-color', or `direct-color'.
+
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display. */)
+ (display)
+ Lisp_Object display;
+{
+ struct mac_display_info *dpyinfo = check_x_display_info (display);
+
+#if 0
+ switch (dpyinfo->visual->class)
+ {
+ case StaticGray: return (intern ("static-gray"));
+ case GrayScale: return (intern ("gray-scale"));
+ case StaticColor: return (intern ("static-color"));
+ case PseudoColor: return (intern ("pseudo-color"));
+ case TrueColor: return (intern ("true-color"));
+ case DirectColor: return (intern ("direct-color"));
+ default:
+ error ("Display has an unknown visual class");
+ }
+#endif /* 0 */
+
+ error ("Display has an unknown visual class");
+}
+
+DEFUN ("x-display-save-under", Fx_display_save_under,
+ Sx_display_save_under, 0, 1, 0,
+ doc: /* Returns t if the display DISPLAY supports the save-under feature.
+The optional argument DISPLAY specifies which display to ask about.
+DISPLAY should be either a frame or a display name (a string).
+If omitted or nil, that stands for the selected frame's display. */)
+ (display)
+ Lisp_Object display;
+{
+ return Qnil;
+}
+\f
+int
+x_pixel_width (f)
+ register struct frame *f;
+{
+ return PIXEL_WIDTH (f);
+}
+
+int
+x_pixel_height (f)
+ register struct frame *f;
+{
+ return PIXEL_HEIGHT (f);
+}
+
+int
+x_char_width (f)
+ register struct frame *f;
+{
+ return FONT_WIDTH (f->output_data.mac->font);
+}
+
+int
+x_char_height (f)
+ register struct frame *f;
+{
+ return f->output_data.mac->line_height;
+}
+
+int
+x_screen_planes (f)
+ register struct frame *f;
+{
+ return FRAME_MAC_DISPLAY_INFO (f)->n_planes;
+}
+\f
+/* Return the display structure for the display named NAME.
+ Open a new connection if necessary. */
+
+struct mac_display_info *
+x_display_info_for_name (name)
+ Lisp_Object name;
+{
+ Lisp_Object names;
+ struct mac_display_info *dpyinfo;
+
+ CHECK_STRING (name);
+
+ for (dpyinfo = &one_mac_display_info, names = x_display_name_list;
+ dpyinfo;
+ dpyinfo = dpyinfo->next, names = XCDR (names))
+ {
+ Lisp_Object tem;
+ tem = Fstring_equal (XCAR (XCAR (names)), name);
+ if (!NILP (tem))
+ return dpyinfo;
+ }
+
+ /* Use this general default value to start with. */
+ Vx_resource_name = Vinvocation_name;
+
+ validate_x_resource_name ();
+
+ dpyinfo = mac_term_init (name, (unsigned char *) 0,
+ (char *) XSTRING (Vx_resource_name)->data);
+
+ if (dpyinfo == 0)
+ error ("Cannot connect to server %s", XSTRING (name)->data);
+
+ mac_in_use = 1;
+ XSETFASTINT (Vwindow_system_version, 3);
+
+ return dpyinfo;
+}
+
+#if 0 /* MAC_TODO: implement network support */
+DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
+ 1, 3, 0,
+ doc: /* Open a connection to a server.
+DISPLAY is the name of the display to connect to.
+Optional second arg XRM-STRING is a string of resources in xrdb format.
+If the optional third arg MUST-SUCCEED is non-nil,
+terminate Emacs if we can't open the connection. */)
+ (display, xrm_string, must_succeed)
+ Lisp_Object display, xrm_string, must_succeed;
+{
+ unsigned char *xrm_option;
+ struct mac_display_info *dpyinfo;
+
+ CHECK_STRING (display);
+ if (! NILP (xrm_string))
+ CHECK_STRING (xrm_string);
+
+ if (! EQ (Vwindow_system, intern ("mac")))
+ error ("Not using Mac OS");
+
+ if (! NILP (xrm_string))
+ xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
+ else
+ xrm_option = (unsigned char *) 0;
+
+ validate_x_resource_name ();
+
+ /* This is what opens the connection and sets x_current_display.
+ This also initializes many symbols, such as those used for input. */
+ dpyinfo = mac_term_init (display, xrm_option,
+ (char *) XSTRING (Vx_resource_name)->data);
+
+ if (dpyinfo == 0)
+ {
+ if (!NILP (must_succeed))
+ fatal ("Cannot connect to server %s.\n",
+ XSTRING (display)->data);
+ else
+ error ("Cannot connect to server %s", XSTRING (display)->data);
+ }
+
+ mac_in_use = 1;
+
+ XSETFASTINT (Vwindow_system_version, 3);
+ return Qnil;
+}
+
+DEFUN ("x-close-connection", Fx_close_connection,
+ Sx_close_connection, 1, 1, 0,
+ doc: /* Close the connection to DISPLAY's server.
+For DISPLAY, specify either a frame or a display name (a string).
+If DISPLAY is nil, that stands for the selected frame's display. */)
+ (display)
+ Lisp_Object display;
+{
+ struct mac_display_info *dpyinfo = check_x_display_info (display);
+ int i;
+
+ if (dpyinfo->reference_count > 0)
+ error ("Display still has frames on it");
+
+ BLOCK_INPUT;
+ /* Free the fonts in the font table. */
+ for (i = 0; i < dpyinfo->n_fonts; i++)
+ if (dpyinfo->font_table[i].name)
+ {
+ if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
+ xfree (dpyinfo->font_table[i].full_name);
+ xfree (dpyinfo->font_table[i].name);
+ x_unload_font (dpyinfo, dpyinfo->font_table[i].font);
+ }
+ x_destroy_all_bitmaps (dpyinfo);
+
+ x_delete_display (dpyinfo);
+ UNBLOCK_INPUT;
+
+ return Qnil;
+}
+#endif /* 0 */
+
+DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
+ doc: /* Return the list of display names that Emacs has connections to. */)
+ ()
+{
+ Lisp_Object tail, result;
+
+ result = Qnil;
+ for (tail = x_display_name_list; ! NILP (tail); tail = XCDR (tail))
+ result = Fcons (XCAR (XCAR (tail)), result);
+
+ return result;
+}
+
+DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
+ doc: /* If ON is non-nil, report errors as soon as the erring request is made.
+If ON is nil, allow buffering of requests.
+This is a noop on Mac OS systems.
+The optional second argument DISPLAY specifies which display to act on.
+DISPLAY should be either a frame or a display name (a string).
+If DISPLAY is omitted or nil, that stands for the selected frame's display. */)
+ (on, display)
+ Lisp_Object display, on;
+{
+ return Qnil;
+}
+
+\f
+/***********************************************************************
+ Image types
+ ***********************************************************************/
+
+/* Value is the number of elements of vector VECTOR. */
+
+#define DIM(VECTOR) (sizeof (VECTOR) / sizeof *(VECTOR))
+
+/* List of supported image types. Use define_image_type to add new
+ types. Use lookup_image_type to find a type for a given symbol. */
+
+static struct image_type *image_types;
+
+/* The symbol `image' which is the car of the lists used to represent
+ images in Lisp. */
+
+extern Lisp_Object Qimage;
+
+/* The symbol `xbm' which is used as the type symbol for XBM images. */
+
+Lisp_Object Qxbm;
+
+/* Keywords. */
+
+extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile;
+extern Lisp_Object QCdata, QCtype;
+Lisp_Object QCascent, QCmargin, QCrelief;
+Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask;
+Lisp_Object QCindex;
+
+/* Other symbols. */
+
+Lisp_Object Qlaplace;
+
+/* Time in seconds after which images should be removed from the cache
+ if not displayed. */
+
+Lisp_Object Vimage_cache_eviction_delay;
+
+/* Function prototypes. */
+
+static void define_image_type P_ ((struct image_type *type));
+static struct image_type *lookup_image_type P_ ((Lisp_Object symbol));
+static void image_error P_ ((char *format, Lisp_Object, Lisp_Object));
+static void x_laplace P_ ((struct frame *, struct image *));
+static int x_build_heuristic_mask P_ ((struct frame *, struct image *,
+ Lisp_Object));
+
+
+/* Define a new image type from TYPE. This adds a copy of TYPE to
+ image_types and adds the symbol *TYPE->type to Vimage_types. */
+
+static void
+define_image_type (type)
+ struct image_type *type;
+{
+ /* Make a copy of TYPE to avoid a bus error in a dumped Emacs.
+ The initialized data segment is read-only. */
+ struct image_type *p = (struct image_type *) xmalloc (sizeof *p);
+ bcopy (type, p, sizeof *p);
+ p->next = image_types;
+ image_types = p;
+ Vimage_types = Fcons (*p->type, Vimage_types);
+}
+
+
+/* Look up image type SYMBOL, and return a pointer to its image_type
+ structure. Value is null if SYMBOL is not a known image type. */
+
+static INLINE struct image_type *
+lookup_image_type (symbol)
+ Lisp_Object symbol;
+{
+ struct image_type *type;
+
+ for (type = image_types; type; type = type->next)
+ if (EQ (symbol, *type->type))
+ break;
+
+ return type;
+}
+
+
+/* Value is non-zero if OBJECT is a valid Lisp image specification. A
+ valid image specification is a list whose car is the symbol
+ `image', and whose rest is a property list. The property list must
+ contain a value for key `:type'. That value must be the name of a
+ supported image type. The rest of the property list depends on the
+ image type. */
+
+int
+valid_image_p (object)
+ Lisp_Object object;
+{
+ int valid_p = 0;
+
+ if (CONSP (object) && EQ (XCAR (object), Qimage))
+ {
+ Lisp_Object symbol = Fplist_get (XCDR (object), QCtype);
+ struct image_type *type = lookup_image_type (symbol);
+
+ if (type)
+ valid_p = type->valid_p (object);
+ }
+
+ return valid_p;
+}
+
+
+/* Log error message with format string FORMAT and argument ARG.
+ Signaling an error, e.g. when an image cannot be loaded, is not a
+ good idea because this would interrupt redisplay, and the error
+ message display would lead to another redisplay. This function
+ therefore simply displays a message. */
+
+static void
+image_error (format, arg1, arg2)
+ char *format;
+ Lisp_Object arg1, arg2;
+{
+ add_to_log (format, arg1, arg2);
+}
+
+
+\f
+/***********************************************************************
+ Image specifications
+ ***********************************************************************/
+
+enum image_value_type
+{
+ IMAGE_DONT_CHECK_VALUE_TYPE,
+ IMAGE_STRING_VALUE,
+ IMAGE_SYMBOL_VALUE,
+ IMAGE_POSITIVE_INTEGER_VALUE,
+ IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR,
+ IMAGE_NON_NEGATIVE_INTEGER_VALUE,
+ IMAGE_ASCENT_VALUE,
+ IMAGE_INTEGER_VALUE,
+ IMAGE_FUNCTION_VALUE,
+ IMAGE_NUMBER_VALUE,
+ IMAGE_BOOL_VALUE
+};
+
+/* Structure used when parsing image specifications. */
+
+struct image_keyword
+{
+ /* Name of keyword. */
+ char *name;
+
+ /* The type of value allowed. */
+ enum image_value_type type;
+
+ /* Non-zero means key must be present. */
+ int mandatory_p;
+
+ /* Used to recognize duplicate keywords in a property list. */
+ int count;
+
+ /* The value that was found. */
+ Lisp_Object value;
+};
+
+
+static int parse_image_spec P_ ((Lisp_Object, struct image_keyword *,
+ int, Lisp_Object));
+static Lisp_Object image_spec_value P_ ((Lisp_Object, Lisp_Object, int *));
+
+
+/* Parse image spec SPEC according to KEYWORDS. A valid image spec
+ has the format (image KEYWORD VALUE ...). One of the keyword/
+ value pairs must be `:type TYPE'. KEYWORDS is a vector of
+ image_keywords structures of size NKEYWORDS describing other
+ allowed keyword/value pairs. Value is non-zero if SPEC is valid. */
+
+static int
+parse_image_spec (spec, keywords, nkeywords, type)
+ Lisp_Object spec;
+ struct image_keyword *keywords;
+ int nkeywords;
+ Lisp_Object type;
+{
+ int i;
+ Lisp_Object plist;
+
+ if (!CONSP (spec) || !EQ (XCAR (spec), Qimage))
+ return 0;
+
+ plist = XCDR (spec);
+ while (CONSP (plist))
+ {
+ Lisp_Object key, value;
+
+ /* First element of a pair must be a symbol. */
+ key = XCAR (plist);
+ plist = XCDR (plist);
+ if (!SYMBOLP (key))
+ return 0;
+
+ /* There must follow a value. */
+ if (!CONSP (plist))
+ return 0;
+ value = XCAR (plist);
+ plist = XCDR (plist);
+
+ /* Find key in KEYWORDS. Error if not found. */
+ for (i = 0; i < nkeywords; ++i)
+ if (strcmp (keywords[i].name, XSYMBOL (key)->name->data) == 0)
+ break;
+
+ if (i == nkeywords)
+ continue;
+
+ /* Record that we recognized the keyword. If a keywords
+ was found more than once, it's an error. */
+ keywords[i].value = value;
+ ++keywords[i].count;
+
+ if (keywords[i].count > 1)
+ return 0;
+
+ /* Check type of value against allowed type. */
+ switch (keywords[i].type)
+ {
+ case IMAGE_STRING_VALUE:
+ if (!STRINGP (value))
+ return 0;
+ break;
+
+ case IMAGE_SYMBOL_VALUE:
+ if (!SYMBOLP (value))
+ return 0;
+ break;
+
+ case IMAGE_POSITIVE_INTEGER_VALUE:
+ if (!INTEGERP (value) || XINT (value) <= 0)
+ return 0;
+ break;
+
+ case IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR:
+ if (INTEGERP (value) && XINT (value) >= 0)
+ break;
+ if (CONSP (value)
+ && INTEGERP (XCAR (value)) && INTEGERP (XCDR (value))
+ && XINT (XCAR (value)) >= 0 && XINT (XCDR (value)) >= 0)
+ break;
+ return 0;
+
+ case IMAGE_ASCENT_VALUE:
+ if (SYMBOLP (value) && EQ (value, Qcenter))
+ break;
+ else if (INTEGERP (value)
+ && XINT (value) >= 0
+ && XINT (value) <= 100)
+ break;
+ return 0;
+
+ case IMAGE_NON_NEGATIVE_INTEGER_VALUE:
+ if (!INTEGERP (value) || XINT (value) < 0)
+ return 0;
+ break;
+
+ case IMAGE_DONT_CHECK_VALUE_TYPE:
+ break;
+
+ case IMAGE_FUNCTION_VALUE:
+ value = indirect_function (value);
+ if (SUBRP (value)
+ || COMPILEDP (value)
+ || (CONSP (value) && EQ (XCAR (value), Qlambda)))
+ break;
+ return 0;
+
+ case IMAGE_NUMBER_VALUE:
+ if (!INTEGERP (value) && !FLOATP (value))
+ return 0;
+ break;
+
+ case IMAGE_INTEGER_VALUE:
+ if (!INTEGERP (value))
+ return 0;
+ break;
+
+ case IMAGE_BOOL_VALUE:
+ if (!NILP (value) && !EQ (value, Qt))
+ return 0;
+ break;
+
+ default:
+ abort ();
+ break;
+ }
+
+ if (EQ (key, QCtype) && !EQ (type, value))
+ return 0;
+ }
+
+ /* Check that all mandatory fields are present. */
+ for (i = 0; i < nkeywords; ++i)
+ if (keywords[i].mandatory_p && keywords[i].count == 0)
+ return 0;
+
+ return NILP (plist);
+}
+
+
+/* Return the value of KEY in image specification SPEC. Value is nil
+ if KEY is not present in SPEC. if FOUND is not null, set *FOUND
+ to 1 if KEY was found in SPEC, set it to 0 otherwise. */
+
+static Lisp_Object
+image_spec_value (spec, key, found)
+ Lisp_Object spec, key;
+ int *found;
+{
+ Lisp_Object tail;
+
+ xassert (valid_image_p (spec));
+
+ for (tail = XCDR (spec);
+ CONSP (tail) && CONSP (XCDR (tail));
+ tail = XCDR (XCDR (tail)))
+ {
+ if (EQ (XCAR (tail), key))
+ {
+ if (found)
+ *found = 1;
+ return XCAR (XCDR (tail));
+ }
+ }
+
+ if (found)
+ *found = 0;
+ return Qnil;
+}
+
+
+
+\f
+/***********************************************************************
+ Image type independent image structures
+ ***********************************************************************/
+
+static struct image *make_image P_ ((Lisp_Object spec, unsigned hash));
+static void free_image P_ ((struct frame *f, struct image *img));
+
+
+/* Allocate and return a new image structure for image specification
+ SPEC. SPEC has a hash value of HASH. */
+
+static struct image *
+make_image (spec, hash)
+ Lisp_Object spec;
+ unsigned hash;
+{
+ struct image *img = (struct image *) xmalloc (sizeof *img);
+
+ xassert (valid_image_p (spec));
+ bzero (img, sizeof *img);
+ img->type = lookup_image_type (image_spec_value (spec, QCtype, NULL));
+ xassert (img->type != NULL);
+ img->spec = spec;
+ img->data.lisp_val = Qnil;
+ img->ascent = DEFAULT_IMAGE_ASCENT;
+ img->hash = hash;
+ return img;
+}
+
+
+/* Free image IMG which was used on frame F, including its resources. */
+
+static void
+free_image (f, img)
+ struct frame *f;
+ struct image *img;
+{
+ if (img)
+ {
+ struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
+
+ /* Remove IMG from the hash table of its cache. */
+ if (img->prev)
+ img->prev->next = img->next;
+ else
+ c->buckets[img->hash % IMAGE_CACHE_BUCKETS_SIZE] = img->next;
+
+ if (img->next)
+ img->next->prev = img->prev;
+
+ c->images[img->id] = NULL;
+
+ /* Free resources, then free IMG. */
+ img->type->free (f, img);
+ xfree (img);
+ }
+}
+
+
+/* Prepare image IMG for display on frame F. Must be called before
+ drawing an image. */
+
+void
+prepare_image_for_display (f, img)
+ struct frame *f;
+ struct image *img;
+{
+ EMACS_TIME t;
+
+ /* We're about to display IMG, so set its timestamp to `now'. */
+ EMACS_GET_TIME (t);
+ img->timestamp = EMACS_SECS (t);
+
+ /* If IMG doesn't have a pixmap yet, load it now, using the image
+ type dependent loader function. */
+ if (img->pixmap == 0 && !img->load_failed_p)
+ img->load_failed_p = img->type->load (f, img) == 0;
+}
+
+
+/* Value is the number of pixels for the ascent of image IMG when
+ drawn in face FACE. */
+
+int
+image_ascent (img, face)
+ struct image *img;
+ struct face *face;
+{
+ int height = img->height + img->vmargin;
+ int ascent;
+
+ if (img->ascent == CENTERED_IMAGE_ASCENT)
+ {
+ if (face->font)
+ ascent = height / 2 - (FONT_DESCENT(face->font)
+ - FONT_BASE(face->font)) / 2;
+ else
+ ascent = height / 2;
+ }
+ else
+ ascent = height * img->ascent / 100.0;
+
+ return ascent;
+}
+
+
+\f
+/***********************************************************************
+ Helper functions for X image types
+ ***********************************************************************/
+
+static void x_clear_image P_ ((struct frame *f, struct image *img));
+static unsigned long x_alloc_image_color P_ ((struct frame *f,
+ struct image *img,
+ Lisp_Object color_name,
+ unsigned long dflt));
+
+/* Free X resources of image IMG which is used on frame F. */
+
+static void
+x_clear_image (f, img)
+ struct frame *f;
+ struct image *img;
+{
+#if 0 /* MAC_TODO: W32 image support */
+
+ if (img->pixmap)
+ {
+ BLOCK_INPUT;
+ XFreePixmap (NULL, img->pixmap);
+ img->pixmap = 0;
+ UNBLOCK_INPUT;
+ }
+
+ if (img->ncolors)
+ {
+ int class = FRAME_W32_DISPLAY_INFO (f)->visual->class;
+
+ /* If display has an immutable color map, freeing colors is not
+ necessary and some servers don't allow it. So don't do it. */
+ if (class != StaticColor
+ && class != StaticGray
+ && class != TrueColor)
+ {
+ Colormap cmap;
+ BLOCK_INPUT;
+ cmap = DefaultColormapOfScreen (FRAME_W32_DISPLAY_INFO (f)->screen);
+ XFreeColors (FRAME_W32_DISPLAY (f), cmap, img->colors,
+ img->ncolors, 0);
+ UNBLOCK_INPUT;
+ }
+
+ xfree (img->colors);
+ img->colors = NULL;
+ img->ncolors = 0;
+ }
+#endif /* MAC_TODO */
+}
+
+
+/* Allocate color COLOR_NAME for image IMG on frame F. If color
+ cannot be allocated, use DFLT. Add a newly allocated color to
+ IMG->colors, so that it can be freed again. Value is the pixel
+ color. */
+
+static unsigned long
+x_alloc_image_color (f, img, color_name, dflt)
+ struct frame *f;
+ struct image *img;
+ Lisp_Object color_name;
+ unsigned long dflt;
+{
+#if 0 /* MAC_TODO: allocing colors. */
+ XColor color;
+ unsigned long result;
+
+ xassert (STRINGP (color_name));
+
+ if (w32_defined_color (f, XSTRING (color_name)->data, &color, 1))
+ {
+ /* This isn't called frequently so we get away with simply
+ reallocating the color vector to the needed size, here. */
+ ++img->ncolors;
+ img->colors =
+ (unsigned long *) xrealloc (img->colors,
+ img->ncolors * sizeof *img->colors);
+ img->colors[img->ncolors - 1] = color.pixel;
+ result = color.pixel;
+ }
+ else
+ result = dflt;
+ return result;
+#endif /* MAC_TODO */
+ return 0;
+}
+
+
+\f
+/***********************************************************************
+ Image Cache
+ ***********************************************************************/
+
+static void cache_image P_ ((struct frame *f, struct image *img));
+
+
+/* Return a new, initialized image cache that is allocated from the
+ heap. Call free_image_cache to free an image cache. */
+
+struct image_cache *
+make_image_cache ()
+{
+ struct image_cache *c = (struct image_cache *) xmalloc (sizeof *c);
+ int size;
+
+ bzero (c, sizeof *c);
+ c->size = 50;
+ c->images = (struct image **) xmalloc (c->size * sizeof *c->images);
+ size = IMAGE_CACHE_BUCKETS_SIZE * sizeof *c->buckets;
+ c->buckets = (struct image **) xmalloc (size);
+ bzero (c->buckets, size);
+ return c;
+}
+
+
+/* Free image cache of frame F. Be aware that X frames share images
+ caches. */
+
+void
+free_image_cache (f)
+ struct frame *f;
+{
+ struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
+ if (c)
+ {
+ int i;
+
+ /* Cache should not be referenced by any frame when freed. */
+ xassert (c->refcount == 0);
+
+ for (i = 0; i < c->used; ++i)
+ free_image (f, c->images[i]);
+ xfree (c->images);
+ xfree (c->buckets);
+ xfree (c);
+ FRAME_X_IMAGE_CACHE (f) = NULL;
+ }
+}
+
+
+/* Clear image cache of frame F. FORCE_P non-zero means free all
+ images. FORCE_P zero means clear only images that haven't been
+ displayed for some time. Should be called from time to time to
+ reduce the number of loaded images. If image-eviction-seconds is
+ non-nil, this frees images in the cache which weren't displayed for
+ at least that many seconds. */
+
+void
+clear_image_cache (f, force_p)
+ struct frame *f;
+ int force_p;
+{
+ struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
+
+ if (c && INTEGERP (Vimage_cache_eviction_delay))
+ {
+ EMACS_TIME t;
+ unsigned long old;
+ int i, any_freed_p = 0;
+
+ EMACS_GET_TIME (t);
+ old = EMACS_SECS (t) - XFASTINT (Vimage_cache_eviction_delay);
+
+ for (i = 0; i < c->used; ++i)
+ {
+ struct image *img = c->images[i];
+ if (img != NULL
+ && (force_p
+ || (img->timestamp > old)))
+ {
+ free_image (f, img);
+ any_freed_p = 1;
+ }
+ }
+
+ /* We may be clearing the image cache because, for example,
+ Emacs was iconified for a longer period of time. In that
+ case, current matrices may still contain references to
+ images freed above. So, clear these matrices. */
+ if (any_freed_p)
+ {
+ clear_current_matrices (f);
+ ++windows_or_buffers_changed;
+ }
+ }
+}
+
+
+DEFUN ("clear-image-cache", Fclear_image_cache, Sclear_image_cache,
+ 0, 1, 0,
+ doc: /* Clear the image cache of FRAME.
+FRAME nil or omitted means use the selected frame.
+FRAME t means clear the image caches of all frames. */)
+ (frame)
+ Lisp_Object frame;
+{
+ if (EQ (frame, Qt))
+ {
+ Lisp_Object tail;
+
+ FOR_EACH_FRAME (tail, frame)
+ if (FRAME_MAC_P (XFRAME (frame)))
+ clear_image_cache (XFRAME (frame), 1);
+ }
+ else
+ clear_image_cache (check_x_frame (frame), 1);
+
+ return Qnil;
+}
+
+
+/* Return the id of image with Lisp specification SPEC on frame F.
+ SPEC must be a valid Lisp image specification (see valid_image_p). */
+
+int
+lookup_image (f, spec)
+ struct frame *f;
+ Lisp_Object spec;
+{
+ struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
+ struct image *img;
+ int i;
+ unsigned hash;
+ struct gcpro gcpro1;
+ EMACS_TIME now;
+
+ /* F must be a window-system frame, and SPEC must be a valid image
+ specification. */
+ xassert (FRAME_WINDOW_P (f));
+ xassert (valid_image_p (spec));
+
+ GCPRO1 (spec);
+
+ /* Look up SPEC in the hash table of the image cache. */
+ hash = sxhash (spec, 0);
+ i = hash % IMAGE_CACHE_BUCKETS_SIZE;
+
+ for (img = c->buckets[i]; img; img = img->next)
+ if (img->hash == hash && !NILP (Fequal (img->spec, spec)))
+ break;
+
+ /* If not found, create a new image and cache it. */
+ if (img == NULL)
+ {
+ BLOCK_INPUT;
+ img = make_image (spec, hash);
+ cache_image (f, img);
+ img->load_failed_p = img->type->load (f, img) == 0;
+ xassert (!interrupt_input_blocked);
+
+ /* If we can't load the image, and we don't have a width and
+ height, use some arbitrary width and height so that we can
+ draw a rectangle for it. */
+ if (img->load_failed_p)
+ {
+ Lisp_Object value;
+
+ value = image_spec_value (spec, QCwidth, NULL);
+ img->width = (INTEGERP (value)
+ ? XFASTINT (value) : DEFAULT_IMAGE_WIDTH);
+ value = image_spec_value (spec, QCheight, NULL);
+ img->height = (INTEGERP (value)
+ ? XFASTINT (value) : DEFAULT_IMAGE_HEIGHT);
+ }
+ else
+ {
+ /* Handle image type independent image attributes
+ `:ascent PERCENT', `:margin MARGIN', `:relief RELIEF'. */
+ Lisp_Object ascent, margin, relief;
+
+ ascent = image_spec_value (spec, QCascent, NULL);
+ if (INTEGERP (ascent))
+ img->ascent = XFASTINT (ascent);
+ else if (EQ (ascent, Qcenter))
+ img->ascent = CENTERED_IMAGE_ASCENT;
+
+ margin = image_spec_value (spec, QCmargin, NULL);
+ if (INTEGERP (margin) && XINT (margin) >= 0)
+ img->vmargin = img->hmargin = XFASTINT (margin);
+ else if (CONSP (margin) && INTEGERP (XCAR (margin))
+ && INTEGERP (XCDR (margin)))
+ {
+ if (XINT (XCAR (margin)) > 0)
+ img->hmargin = XFASTINT (XCAR (margin));
+ if (XINT (XCDR (margin)) > 0)
+ img->vmargin = XFASTINT (XCDR (margin));
+ }
+
+ relief = image_spec_value (spec, QCrelief, NULL);
+ if (INTEGERP (relief))
+ {
+ img->relief = XINT (relief);
+ img->hmargin += abs (img->relief);
+ img->vmargin += abs (img->relief);
+ }
+ }
+ }
+
+ /* We're using IMG, so set its timestamp to `now'. */
+ EMACS_GET_TIME (now);
+ img->timestamp = EMACS_SECS (now);
+
+ UNGCPRO;
+
+ /* Value is the image id. */
+ return img->id;
+}
+
+
+/* Cache image IMG in the image cache of frame F. */
+
+static void
+cache_image (f, img)
+ struct frame *f;
+ struct image *img;
+{
+ struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
+ int i;
+
+ /* Find a free slot in c->images. */
+ for (i = 0; i < c->used; ++i)
+ if (c->images[i] == NULL)
+ break;
+
+ /* If no free slot found, maybe enlarge c->images. */
+ if (i == c->used && c->used == c->size)
+ {
+ c->size *= 2;
+ c->images = (struct image **) xrealloc (c->images,
+ c->size * sizeof *c->images);
+ }
+
+ /* Add IMG to c->images, and assign IMG an id. */
+ c->images[i] = img;
+ img->id = i;
+ if (i == c->used)
+ ++c->used;
+
+ /* Add IMG to the cache's hash table. */
+ i = img->hash % IMAGE_CACHE_BUCKETS_SIZE;
+ img->next = c->buckets[i];
+ if (img->next)
+ img->next->prev = img;
+ img->prev = NULL;
+ c->buckets[i] = img;
+}
+
+
+/* Call FN on every image in the image cache of frame F. Used to mark
+ Lisp Objects in the image cache. */
+
+void
+forall_images_in_image_cache (f, fn)
+ struct frame *f;
+ void (*fn) P_ ((struct image *img));
+{
+ if (FRAME_LIVE_P (f) && FRAME_MAC_P (f))
+ {
+ struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
+ if (c)
+ {
+ int i;
+ for (i = 0; i < c->used; ++i)
+ if (c->images[i])
+ fn (c->images[i]);
+ }
+ }
+}
+
+
+\f
+/***********************************************************************
+ Mac support code
+ ***********************************************************************/
+
+#if 0 /* MAC_TODO: Mac specific image code. */
+
+static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
+ XImage **, Pixmap *));
+static void x_destroy_x_image P_ ((XImage *));
+static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
+
+
+/* Create an XImage and a pixmap of size WIDTH x HEIGHT for use on
+ frame F. Set *XIMG and *PIXMAP to the XImage and Pixmap created.
+ Set (*XIMG)->data to a raster of WIDTH x HEIGHT pixels allocated
+ via xmalloc. Print error messages via image_error if an error
+ occurs. Value is non-zero if successful. */
+
+static int
+x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
+ struct frame *f;
+ int width, height, depth;
+ XImage **ximg;
+ Pixmap *pixmap;
+{
+#if 0 /* MAC_TODO: Image support for Mac */
+ Display *display = FRAME_W32_DISPLAY (f);
+ Screen *screen = FRAME_X_SCREEN (f);
+ Window window = FRAME_W32_WINDOW (f);
+
+ xassert (interrupt_input_blocked);
+
+ if (depth <= 0)
+ depth = DefaultDepthOfScreen (screen);
+ *ximg = XCreateImage (display, DefaultVisualOfScreen (screen),
+ depth, ZPixmap, 0, NULL, width, height,
+ depth > 16 ? 32 : depth > 8 ? 16 : 8, 0);
+ if (*ximg == NULL)
+ {
+ image_error ("Unable to allocate X image", Qnil, Qnil);
+ return 0;
+ }
+
+ /* Allocate image raster. */
+ (*ximg)->data = (char *) xmalloc ((*ximg)->bytes_per_line * height);
+
+ /* Allocate a pixmap of the same size. */
+ *pixmap = XCreatePixmap (display, window, width, height, depth);
+ if (*pixmap == 0)
+ {
+ x_destroy_x_image (*ximg);
+ *ximg = NULL;
+ image_error ("Unable to create X pixmap", Qnil, Qnil);
+ return 0;
+ }
+#endif /* MAC_TODO */
+ return 1;
+}
+
+
+/* Destroy XImage XIMG. Free XIMG->data. */
+
+static void
+x_destroy_x_image (ximg)
+ XImage *ximg;
+{
+ xassert (interrupt_input_blocked);
+ if (ximg)
+ {
+ xfree (ximg->data);
+ ximg->data = NULL;
+ XDestroyImage (ximg);
+ }
+}
+
+
+/* Put XImage XIMG into pixmap PIXMAP on frame F. WIDTH and HEIGHT
+ are width and height of both the image and pixmap. */
+
+static void
+x_put_x_image (f, ximg, pixmap, width, height)
+ struct frame *f;
+ XImage *ximg;
+ Pixmap pixmap;
+{
+ GC gc;
+
+ xassert (interrupt_input_blocked);
+ gc = XCreateGC (NULL, pixmap, 0, NULL);
+ XPutImage (NULL, pixmap, gc, ximg, 0, 0, 0, 0, width, height);
+ XFreeGC (NULL, gc);
+}
+
+#endif /* MAC_TODO */
+
+\f
+/***********************************************************************
+ Searching files
+ ***********************************************************************/
+
+static Lisp_Object x_find_image_file P_ ((Lisp_Object));
+
+/* Find image file FILE. Look in data-directory, then
+ x-bitmap-file-path. Value is the full name of the file found, or
+ nil if not found. */
+
+static Lisp_Object
+x_find_image_file (file)
+ Lisp_Object file;
+{
+ Lisp_Object file_found, search_path;
+ struct gcpro gcpro1, gcpro2;
+ int fd;
+
+ file_found = Qnil;
+ search_path = Fcons (Vdata_directory, Vx_bitmap_file_path);
+ GCPRO2 (file_found, search_path);
+
+ /* Try to find FILE in data-directory, then x-bitmap-file-path. */
+ fd = openp (search_path, file, Qnil, &file_found, 0);
+
+ if (fd < 0)
+ file_found = Qnil;
+ else
+ close (fd);
+
+ UNGCPRO;
+ return file_found;
+}
+
+\f
+/***********************************************************************
+ XBM images
+ ***********************************************************************/
+
+static int xbm_load P_ ((struct frame *f, struct image *img));
+static int xbm_load_image_from_file P_ ((struct frame *f, struct image *img,
+ Lisp_Object file));
+static int xbm_image_p P_ ((Lisp_Object object));
+static int xbm_read_bitmap_file_data P_ ((char *, int *, int *,
+ unsigned char **));
+
+
+/* Indices of image specification fields in xbm_format, below. */
+
+enum xbm_keyword_index
+{
+ XBM_TYPE,
+ XBM_FILE,
+ XBM_WIDTH,
+ XBM_HEIGHT,
+ XBM_DATA,
+ XBM_FOREGROUND,
+ XBM_BACKGROUND,
+ XBM_ASCENT,
+ XBM_MARGIN,
+ XBM_RELIEF,
+ XBM_ALGORITHM,
+ XBM_HEURISTIC_MASK,
+ XBM_LAST
+};
+
+/* Vector of image_keyword structures describing the format
+ of valid XBM image specifications. */
+
+static struct image_keyword xbm_format[XBM_LAST] =
+{
+ {":type", IMAGE_SYMBOL_VALUE, 1},
+ {":file", IMAGE_STRING_VALUE, 0},
+ {":width", IMAGE_POSITIVE_INTEGER_VALUE, 0},
+ {":height", IMAGE_POSITIVE_INTEGER_VALUE, 0},
+ {":data", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":foreground", IMAGE_STRING_VALUE, 0},
+ {":background", IMAGE_STRING_VALUE, 0},
+ {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
+ {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":relief", IMAGE_INTEGER_VALUE, 0},
+ {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
+};
+
+/* Structure describing the image type XBM. */
+
+static struct image_type xbm_type =
+{
+ &Qxbm,
+ xbm_image_p,
+ xbm_load,
+ x_clear_image,
+ NULL
+};
+
+/* Tokens returned from xbm_scan. */
+
+enum xbm_token
+{
+ XBM_TK_IDENT = 256,
+ XBM_TK_NUMBER
+};
+
+
+/* Return non-zero if OBJECT is a valid XBM-type image specification.
+ A valid specification is a list starting with the symbol `image'
+ The rest of the list is a property list which must contain an
+ entry `:type xbm..
+
+ If the specification specifies a file to load, it must contain
+ an entry `:file FILENAME' where FILENAME is a string.
+
+ If the specification is for a bitmap loaded from memory it must
+ contain `:width WIDTH', `:height HEIGHT', and `:data DATA', where
+ WIDTH and HEIGHT are integers > 0. DATA may be:
+
+ 1. a string large enough to hold the bitmap data, i.e. it must
+ have a size >= (WIDTH + 7) / 8 * HEIGHT
+
+ 2. a bool-vector of size >= WIDTH * HEIGHT
+
+ 3. a vector of strings or bool-vectors, one for each line of the
+ bitmap.
+
+ Both the file and data forms may contain the additional entries
+ `:background COLOR' and `:foreground COLOR'. If not present,
+ foreground and background of the frame on which the image is
+ displayed, is used. */
+
+static int
+xbm_image_p (object)
+ Lisp_Object object;
+{
+ struct image_keyword kw[XBM_LAST];
+
+ bcopy (xbm_format, kw, sizeof kw);
+ if (!parse_image_spec (object, kw, XBM_LAST, Qxbm))
+ return 0;
+
+ xassert (EQ (kw[XBM_TYPE].value, Qxbm));
+
+ if (kw[XBM_FILE].count)
+ {
+ if (kw[XBM_WIDTH].count || kw[XBM_HEIGHT].count || kw[XBM_DATA].count)
+ return 0;
+ }
+ else
+ {
+ Lisp_Object data;
+ int width, height;
+
+ /* Entries for `:width', `:height' and `:data' must be present. */
+ if (!kw[XBM_WIDTH].count
+ || !kw[XBM_HEIGHT].count
+ || !kw[XBM_DATA].count)
+ return 0;
+
+ data = kw[XBM_DATA].value;
+ width = XFASTINT (kw[XBM_WIDTH].value);
+ height = XFASTINT (kw[XBM_HEIGHT].value);
+
+ /* Check type of data, and width and height against contents of
+ data. */
+ if (VECTORP (data))
+ {
+ int i;
+
+ /* Number of elements of the vector must be >= height. */
+ if (XVECTOR (data)->size < height)
+ return 0;
+
+ /* Each string or bool-vector in data must be large enough
+ for one line of the image. */
+ for (i = 0; i < height; ++i)
+ {
+ Lisp_Object elt = XVECTOR (data)->contents[i];
+
+ if (STRINGP (elt))
+ {
+ if (XSTRING (elt)->size
+ < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR)
+ return 0;
+ }
+ else if (BOOL_VECTOR_P (elt))
+ {
+ if (XBOOL_VECTOR (elt)->size < width)
+ return 0;
+ }
+ else
+ return 0;
+ }
+ }
+ else if (STRINGP (data))
+ {
+ if (XSTRING (data)->size
+ < (width + BITS_PER_CHAR - 1) / BITS_PER_CHAR * height)
+ return 0;
+ }
+ else if (BOOL_VECTOR_P (data))
+ {
+ if (XBOOL_VECTOR (data)->size < width * height)
+ return 0;
+ }
+ else
+ return 0;
+ }
+
+ /* Baseline must be a value between 0 and 100 (a percentage). */
+ if (kw[XBM_ASCENT].count
+ && XFASTINT (kw[XBM_ASCENT].value) > 100)
+ return 0;
+
+ return 1;
+}
+
+
+/* Scan a bitmap file. FP is the stream to read from. Value is
+ either an enumerator from enum xbm_token, or a character for a
+ single-character token, or 0 at end of file. If scanning an
+ identifier, store the lexeme of the identifier in SVAL. If
+ scanning a number, store its value in *IVAL. */
+
+static int
+xbm_scan (fp, sval, ival)
+ FILE *fp;
+ char *sval;
+ int *ival;
+{
+ int c;
+
+ /* Skip white space. */
+ while ((c = fgetc (fp)) != EOF && isspace (c))
+ ;
+
+ if (c == EOF)
+ c = 0;
+ else if (isdigit (c))
+ {
+ int value = 0, digit;
+
+ if (c == '0')
+ {
+ c = fgetc (fp);
+ if (c == 'x' || c == 'X')
+ {
+ while ((c = fgetc (fp)) != EOF)
+ {
+ if (isdigit (c))
+ digit = c - '0';
+ else if (c >= 'a' && c <= 'f')
+ digit = c - 'a' + 10;
+ else if (c >= 'A' && c <= 'F')
+ digit = c - 'A' + 10;
+ else
+ break;
+ value = 16 * value + digit;
+ }
+ }
+ else if (isdigit (c))
+ {
+ value = c - '0';
+ while ((c = fgetc (fp)) != EOF
+ && isdigit (c))
+ value = 8 * value + c - '0';
+ }
+ }
+ else
+ {
+ value = c - '0';
+ while ((c = fgetc (fp)) != EOF
+ && isdigit (c))
+ value = 10 * value + c - '0';
+ }
+
+ if (c != EOF)
+ ungetc (c, fp);
+ *ival = value;
+ c = XBM_TK_NUMBER;
+ }
+ else if (isalpha (c) || c == '_')
+ {
+ *sval++ = c;
+ while ((c = fgetc (fp)) != EOF
+ && (isalnum (c) || c == '_'))
+ *sval++ = c;
+ *sval = 0;
+ if (c != EOF)
+ ungetc (c, fp);
+ c = XBM_TK_IDENT;
+ }
+
+ return c;
+}
+
+
+/* Replacement for XReadBitmapFileData which isn't available under old
+ X versions. FILE is the name of the bitmap file to read. Set
+ *WIDTH and *HEIGHT to the width and height of the image. Return in
+ *DATA the bitmap data allocated with xmalloc. Value is non-zero if
+ successful. */
+
+static int
+xbm_read_bitmap_file_data (file, width, height, data)
+ char *file;
+ int *width, *height;
+ unsigned char **data;
+{
+ FILE *fp;
+ char buffer[BUFSIZ];
+ int padding_p = 0;
+ int v10 = 0;
+ int bytes_per_line, i, nbytes;
+ unsigned char *p;
+ int value;
+ int LA1;
+
+#define match() \
+ LA1 = xbm_scan (fp, buffer, &value)
+
+#define expect(TOKEN) \
+ if (LA1 != (TOKEN)) \
+ goto failure; \
+ else \
+ match ()
+
+#define expect_ident(IDENT) \
+ if (LA1 == XBM_TK_IDENT && strcmp (buffer, (IDENT)) == 0) \
+ match (); \
+ else \
+ goto failure
+
+ fp = fopen (file, "r");
+ if (fp == NULL)
+ return 0;
+
+ *width = *height = -1;
+ *data = NULL;
+ LA1 = xbm_scan (fp, buffer, &value);
+
+ /* Parse defines for width, height and hot-spots. */
+ while (LA1 == '#')
+ {
+ match ();
+ expect_ident ("define");
+ expect (XBM_TK_IDENT);
+
+ if (LA1 == XBM_TK_NUMBER);
+ {
+ char *p = strrchr (buffer, '_');
+ p = p ? p + 1 : buffer;
+ if (strcmp (p, "width") == 0)
+ *width = value;
+ else if (strcmp (p, "height") == 0)
+ *height = value;
+ }
+ expect (XBM_TK_NUMBER);
+ }
+
+ if (*width < 0 || *height < 0)
+ goto failure;
+
+ /* Parse bits. Must start with `static'. */
+ expect_ident ("static");
+ if (LA1 == XBM_TK_IDENT)
+ {
+ if (strcmp (buffer, "unsigned") == 0)
+ {
+ match ();
+ expect_ident ("char");
+ }
+ else if (strcmp (buffer, "short") == 0)
+ {
+ match ();
+ v10 = 1;
+ if (*width % 16 && *width % 16 < 9)
+ padding_p = 1;
+ }
+ else if (strcmp (buffer, "char") == 0)
+ match ();
+ else
+ goto failure;
+ }
+ else
+ goto failure;
+
+ expect (XBM_TK_IDENT);
+ expect ('[');
+ expect (']');
+ expect ('=');
+ expect ('{');
+
+ bytes_per_line = (*width + 7) / 8 + padding_p;
+ nbytes = bytes_per_line * *height;
+ p = *data = (char *) xmalloc (nbytes);
+
+ if (v10)
+ {
+
+ for (i = 0; i < nbytes; i += 2)
+ {
+ int val = value;
+ expect (XBM_TK_NUMBER);
+
+ *p++ = val;
+ if (!padding_p || ((i + 2) % bytes_per_line))
+ *p++ = value >> 8;
+
+ if (LA1 == ',' || LA1 == '}')
+ match ();
+ else
+ goto failure;
+ }
+ }
+ else
+ {
+ for (i = 0; i < nbytes; ++i)
+ {
+ int val = value;
+ expect (XBM_TK_NUMBER);
+
+ *p++ = val;
+
+ if (LA1 == ',' || LA1 == '}')
+ match ();
+ else
+ goto failure;
+ }
+ }
+
+ fclose (fp);
+ return 1;
+
+ failure:
+
+ fclose (fp);
+ if (*data)
+ {
+ xfree (*data);
+ *data = NULL;
+ }
+ return 0;
+
+#undef match
+#undef expect
+#undef expect_ident
+}
+
+
+/* Load XBM image IMG which will be displayed on frame F from file
+ SPECIFIED_FILE. Value is non-zero if successful. */
+
+static int
+xbm_load_image_from_file (f, img, specified_file)
+ struct frame *f;
+ struct image *img;
+ Lisp_Object specified_file;
+{
+ int rc;
+ unsigned char *data;
+ int success_p = 0;
+ Lisp_Object file;
+ struct gcpro gcpro1;
+
+ xassert (STRINGP (specified_file));
+ file = Qnil;
+ GCPRO1 (file);
+
+ file = x_find_image_file (specified_file);
+ if (!STRINGP (file))
+ {
+ image_error ("Cannot find image file `%s'", specified_file, Qnil);
+ UNGCPRO;
+ return 0;
+ }
+
+ rc = xbm_read_bitmap_file_data (XSTRING (file)->data, &img->width,
+ &img->height, &data);
+ if (rc)
+ {
+ int depth = one_mac_display_info.n_cbits;
+ unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
+ unsigned long background = FRAME_BACKGROUND_PIXEL (f);
+ Lisp_Object value;
+
+ xassert (img->width > 0 && img->height > 0);
+
+ /* Get foreground and background colors, maybe allocate colors. */
+ value = image_spec_value (img->spec, QCforeground, NULL);
+ if (!NILP (value))
+ foreground = x_alloc_image_color (f, img, value, foreground);
+
+ value = image_spec_value (img->spec, QCbackground, NULL);
+ if (!NILP (value))
+ background = x_alloc_image_color (f, img, value, background);
+
+#if 0 /* MAC_TODO : Port image display to Mac */
+ BLOCK_INPUT;
+ img->pixmap
+ = XCreatePixmapFromBitmapData (FRAME_W32_DISPLAY (f),
+ FRAME_W32_WINDOW (f),
+ data,
+ img->width, img->height,
+ foreground, background,
+ depth);
+ xfree (data);
+
+ if (img->pixmap == 0)
+ {
+ x_clear_image (f, img);
+ image_error ("Unable to create X pixmap for `%s'", file, Qnil);
+ }
+ else
+ success_p = 1;
+
+ UNBLOCK_INPUT;
+#endif /* MAC_TODO */
+ }
+ else
+ image_error ("Error loading XBM image `%s'", img->spec, Qnil);
+
+ UNGCPRO;
+ return success_p;
+}
+
+
+/* Fill image IMG which is used on frame F with pixmap data. Value is
+ non-zero if successful. */
+
+static int
+xbm_load (f, img)
+ struct frame *f;
+ struct image *img;
+{
+ int success_p = 0;
+ Lisp_Object file_name;
+
+ xassert (xbm_image_p (img->spec));
+
+ /* If IMG->spec specifies a file name, create a non-file spec from it. */
+ file_name = image_spec_value (img->spec, QCfile, NULL);
+ if (STRINGP (file_name))
+ success_p = xbm_load_image_from_file (f, img, file_name);
+ else
+ {
+ struct image_keyword fmt[XBM_LAST];
+ Lisp_Object data;
+ int depth;
+ unsigned long foreground = FRAME_FOREGROUND_PIXEL (f);
+ unsigned long background = FRAME_BACKGROUND_PIXEL (f);
+ char *bits;
+ int parsed_p;
+
+ /* Parse the list specification. */
+ bcopy (xbm_format, fmt, sizeof fmt);
+ parsed_p = parse_image_spec (img->spec, fmt, XBM_LAST, Qxbm);
+ xassert (parsed_p);
+
+ /* Get specified width, and height. */
+ img->width = XFASTINT (fmt[XBM_WIDTH].value);
+ img->height = XFASTINT (fmt[XBM_HEIGHT].value);
+ xassert (img->width > 0 && img->height > 0);
+
+ BLOCK_INPUT;
+
+ if (fmt[XBM_ASCENT].count)
+ img->ascent = XFASTINT (fmt[XBM_ASCENT].value);
+
+ /* Get foreground and background colors, maybe allocate colors. */
+ if (fmt[XBM_FOREGROUND].count)
+ foreground = x_alloc_image_color (f, img, fmt[XBM_FOREGROUND].value,
+ foreground);
+ if (fmt[XBM_BACKGROUND].count)
+ background = x_alloc_image_color (f, img, fmt[XBM_BACKGROUND].value,
+ background);
+
+ /* Set bits to the bitmap image data. */
+ data = fmt[XBM_DATA].value;
+ if (VECTORP (data))
+ {
+ int i;
+ char *p;
+ int nbytes = (img->width + BITS_PER_CHAR - 1) / BITS_PER_CHAR;
+
+ p = bits = (char *) alloca (nbytes * img->height);
+ for (i = 0; i < img->height; ++i, p += nbytes)
+ {
+ Lisp_Object line = XVECTOR (data)->contents[i];
+ if (STRINGP (line))
+ bcopy (XSTRING (line)->data, p, nbytes);
+ else
+ bcopy (XBOOL_VECTOR (line)->data, p, nbytes);
+ }
+ }
+ else if (STRINGP (data))
+ bits = XSTRING (data)->data;
+ else
+ bits = XBOOL_VECTOR (data)->data;
+
+#if 0 /* MAC_TODO : port Mac display code */
+ /* Create the pixmap. */
+ depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
+ img->pixmap
+ = XCreatePixmapFromBitmapData (FRAME_W32_DISPLAY (f),
+ FRAME_W32_WINDOW (f),
+ bits,
+ img->width, img->height,
+ foreground, background,
+ depth);
+#endif /* MAC_TODO */
+
+ if (img->pixmap)
+ success_p = 1;
+ else
+ {
+ image_error ("Unable to create pixmap for XBM image `%s'",
+ img->spec, Qnil);
+ x_clear_image (f, img);
+ }
+
+ UNBLOCK_INPUT;
+ }
+
+ return success_p;
+}
+
+
+\f
+/***********************************************************************
+ XPM images
+ ***********************************************************************/
+
+#if HAVE_XPM
+
+static int xpm_image_p P_ ((Lisp_Object object));
+static int xpm_load P_ ((struct frame *f, struct image *img));
+static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
+
+#include "X11/xpm.h"
+
+/* The symbol `xpm' identifying XPM-format images. */
+
+Lisp_Object Qxpm;
+
+/* Indices of image specification fields in xpm_format, below. */
+
+enum xpm_keyword_index
+{
+ XPM_TYPE,
+ XPM_FILE,
+ XPM_DATA,
+ XPM_ASCENT,
+ XPM_MARGIN,
+ XPM_RELIEF,
+ XPM_ALGORITHM,
+ XPM_HEURISTIC_MASK,
+ XPM_COLOR_SYMBOLS,
+ XPM_LAST
+};
+
+/* Vector of image_keyword structures describing the format
+ of valid XPM image specifications. */
+
+static struct image_keyword xpm_format[XPM_LAST] =
+{
+ {":type", IMAGE_SYMBOL_VALUE, 1},
+ {":file", IMAGE_STRING_VALUE, 0},
+ {":data", IMAGE_STRING_VALUE, 0},
+ {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
+ {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":relief", IMAGE_INTEGER_VALUE, 0},
+ {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
+};
+
+/* Structure describing the image type XBM. */
+
+static struct image_type xpm_type =
+{
+ &Qxpm,
+ xpm_image_p,
+ xpm_load,
+ x_clear_image,
+ NULL
+};
+
+
+/* Value is non-zero if COLOR_SYMBOLS is a valid color symbols list
+ for XPM images. Such a list must consist of conses whose car and
+ cdr are strings. */
+
+static int
+xpm_valid_color_symbols_p (color_symbols)
+ Lisp_Object color_symbols;
+{
+ while (CONSP (color_symbols))
+ {
+ Lisp_Object sym = XCAR (color_symbols);
+ if (!CONSP (sym)
+ || !STRINGP (XCAR (sym))
+ || !STRINGP (XCDR (sym)))
+ break;
+ color_symbols = XCDR (color_symbols);
+ }
+
+ return NILP (color_symbols);
+}
+
+
+/* Value is non-zero if OBJECT is a valid XPM image specification. */
+
+static int
+xpm_image_p (object)
+ Lisp_Object object;
+{
+ struct image_keyword fmt[XPM_LAST];
+ bcopy (xpm_format, fmt, sizeof fmt);
+ return (parse_image_spec (object, fmt, XPM_LAST, Qxpm)
+ /* Either `:file' or `:data' must be present. */
+ && fmt[XPM_FILE].count + fmt[XPM_DATA].count == 1
+ /* Either no `:color-symbols' or it's a list of conses
+ whose car and cdr are strings. */
+ && (fmt[XPM_COLOR_SYMBOLS].count == 0
+ || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value))
+ && (fmt[XPM_ASCENT].count == 0
+ || XFASTINT (fmt[XPM_ASCENT].value) < 100));
+}
+
+
+/* Load image IMG which will be displayed on frame F. Value is
+ non-zero if successful. */
+
+static int
+xpm_load (f, img)
+ struct frame *f;
+ struct image *img;
+{
+ int rc, i;
+ XpmAttributes attrs;
+ Lisp_Object specified_file, color_symbols;
+
+ /* Configure the XPM lib. Use the visual of frame F. Allocate
+ close colors. Return colors allocated. */
+ bzero (&attrs, sizeof attrs);
+ attrs.visual = FRAME_X_VISUAL (f);
+ attrs.colormap = FRAME_X_COLORMAP (f);
+ attrs.valuemask |= XpmVisual;
+ attrs.valuemask |= XpmColormap;
+ attrs.valuemask |= XpmReturnAllocPixels;
+#ifdef XpmAllocCloseColors
+ attrs.alloc_close_colors = 1;
+ attrs.valuemask |= XpmAllocCloseColors;
+#else
+ attrs.closeness = 600;
+ attrs.valuemask |= XpmCloseness;
+#endif
+
+ /* If image specification contains symbolic color definitions, add
+ these to `attrs'. */
+ color_symbols = image_spec_value (img->spec, QCcolor_symbols, NULL);
+ if (CONSP (color_symbols))
+ {
+ Lisp_Object tail;
+ XpmColorSymbol *xpm_syms;
+ int i, size;
+
+ attrs.valuemask |= XpmColorSymbols;
+
+ /* Count number of symbols. */
+ attrs.numsymbols = 0;
+ for (tail = color_symbols; CONSP (tail); tail = XCDR (tail))
+ ++attrs.numsymbols;
+
+ /* Allocate an XpmColorSymbol array. */
+ size = attrs.numsymbols * sizeof *xpm_syms;
+ xpm_syms = (XpmColorSymbol *) alloca (size);
+ bzero (xpm_syms, size);
+ attrs.colorsymbols = xpm_syms;
+
+ /* Fill the color symbol array. */
+ for (tail = color_symbols, i = 0;
+ CONSP (tail);
+ ++i, tail = XCDR (tail))
+ {
+ Lisp_Object name = XCAR (XCAR (tail));
+ Lisp_Object color = XCDR (XCAR (tail));
+ xpm_syms[i].name = (char *) alloca (XSTRING (name)->size + 1);
+ strcpy (xpm_syms[i].name, XSTRING (name)->data);
+ xpm_syms[i].value = (char *) alloca (XSTRING (color)->size + 1);
+ strcpy (xpm_syms[i].value, XSTRING (color)->data);
+ }
+ }
+
+ /* Create a pixmap for the image, either from a file, or from a
+ string buffer containing data in the same format as an XPM file. */
+ BLOCK_INPUT;
+ specified_file = image_spec_value (img->spec, QCfile, NULL);
+ if (STRINGP (specified_file))
+ {
+ Lisp_Object file = x_find_image_file (specified_file);
+ if (!STRINGP (file))
+ {
+ image_error ("Cannot find image file `%s'", specified_file, Qnil);
+ UNBLOCK_INPUT;
+ return 0;
+ }
+
+ rc = XpmReadFileToPixmap (NULL, FRAME_W32_WINDOW (f),
+ XSTRING (file)->data, &img->pixmap, &img->mask,
+ &attrs);
+ }
+ else
+ {
+ Lisp_Object buffer = image_spec_value (img->spec, QCdata, NULL);
+ rc = XpmCreatePixmapFromBuffer (NULL, FRAME_W32_WINDOW (f),
+ XSTRING (buffer)->data,
+ &img->pixmap, &img->mask,
+ &attrs);
+ }
+ UNBLOCK_INPUT;
+
+ if (rc == XpmSuccess)
+ {
+ /* Remember allocated colors. */
+ img->ncolors = attrs.nalloc_pixels;
+ img->colors = (unsigned long *) xmalloc (img->ncolors
+ * sizeof *img->colors);
+ for (i = 0; i < attrs.nalloc_pixels; ++i)
+ img->colors[i] = attrs.alloc_pixels[i];
+
+ img->width = attrs.width;
+ img->height = attrs.height;
+ xassert (img->width > 0 && img->height > 0);
+
+ /* The call to XpmFreeAttributes below frees attrs.alloc_pixels. */
+ BLOCK_INPUT;
+ XpmFreeAttributes (&attrs);
+ UNBLOCK_INPUT;
+ }
+ else
+ {
+ switch (rc)
+ {
+ case XpmOpenFailed:
+ image_error ("Error opening XPM file (%s)", img->spec, Qnil);
+ break;
+
+ case XpmFileInvalid:
+ image_error ("Invalid XPM file (%s)", img->spec, Qnil);
+ break;
+
+ case XpmNoMemory:
+ image_error ("Out of memory (%s)", img->spec, Qnil);
+ break;
+
+ case XpmColorFailed:
+ image_error ("Color allocation error (%s)", img->spec, Qnil);
+ break;
+
+ default:
+ image_error ("Unknown error (%s)", img->spec, Qnil);
+ break;
+ }
+ }
+
+ return rc == XpmSuccess;
+}
+
+#endif /* HAVE_XPM != 0 */
+
+\f
+#if 0 /* MAC_TODO : Color tables on Mac. */
+/***********************************************************************
+ Color table
+ ***********************************************************************/
+
+/* An entry in the color table mapping an RGB color to a pixel color. */
+
+struct ct_color
+{
+ int r, g, b;
+ unsigned long pixel;
+
+ /* Next in color table collision list. */
+ struct ct_color *next;
+};
+
+/* The bucket vector size to use. Must be prime. */
+
+#define CT_SIZE 101
+
+/* Value is a hash of the RGB color given by R, G, and B. */
+
+#define CT_HASH_RGB(R, G, B) (((R) << 16) ^ ((G) << 8) ^ (B))
+
+/* The color hash table. */
+
+struct ct_color **ct_table;
+
+/* Number of entries in the color table. */
+
+int ct_colors_allocated;
+
+/* Function prototypes. */
+
+static void init_color_table P_ ((void));
+static void free_color_table P_ ((void));
+static unsigned long *colors_in_color_table P_ ((int *n));
+static unsigned long lookup_rgb_color P_ ((struct frame *f, int r, int g, int b));
+static unsigned long lookup_pixel_color P_ ((struct frame *f, unsigned long p));
+
+
+/* Initialize the color table. */
+
+static void
+init_color_table ()
+{
+ int size = CT_SIZE * sizeof (*ct_table);
+ ct_table = (struct ct_color **) xmalloc (size);
+ bzero (ct_table, size);
+ ct_colors_allocated = 0;
+}
+
+
+/* Free memory associated with the color table. */
+
+static void
+free_color_table ()
+{
+ int i;
+ struct ct_color *p, *next;
+
+ for (i = 0; i < CT_SIZE; ++i)
+ for (p = ct_table[i]; p; p = next)
+ {
+ next = p->next;
+ xfree (p);
+ }
+
+ xfree (ct_table);
+ ct_table = NULL;
+}
+
+
+/* Value is a pixel color for RGB color R, G, B on frame F. If an
+ entry for that color already is in the color table, return the
+ pixel color of that entry. Otherwise, allocate a new color for R,
+ G, B, and make an entry in the color table. */
+
+static unsigned long
+lookup_rgb_color (f, r, g, b)
+ struct frame *f;
+ int r, g, b;
+{
+ unsigned hash = CT_HASH_RGB (r, g, b);
+ int i = hash % CT_SIZE;
+ struct ct_color *p;
+
+ for (p = ct_table[i]; p; p = p->next)
+ if (p->r == r && p->g == g && p->b == b)
+ break;
+
+ if (p == NULL)
+ {
+ COLORREF color;
+ Colormap cmap;
+ int rc;
+
+ color = RGB_TO_ULONG (r, g, b);
+
+ ++ct_colors_allocated;
+
+ p = (struct ct_color *) xmalloc (sizeof *p);
+ p->r = r;
+ p->g = g;
+ p->b = b;
+ p->pixel = color;
+ p->next = ct_table[i];
+ ct_table[i] = p;
+ }
+
+ return p->pixel;
+}
+
+
+/* Look up pixel color PIXEL which is used on frame F in the color
+ table. If not already present, allocate it. Value is PIXEL. */
+
+static unsigned long
+lookup_pixel_color (f, pixel)
+ struct frame *f;
+ unsigned long pixel;
+{
+ int i = pixel % CT_SIZE;
+ struct ct_color *p;
+
+ for (p = ct_table[i]; p; p = p->next)
+ if (p->pixel == pixel)
+ break;
+
+ if (p == NULL)
+ {
+ XColor color;
+ Colormap cmap;
+ int rc;
+
+ BLOCK_INPUT;
+
+ cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
+ color.pixel = pixel;
+ XQueryColor (NULL, cmap, &color);
+ rc = x_alloc_nearest_color (f, cmap, &color);
+ UNBLOCK_INPUT;
+
+ if (rc)
+ {
+ ++ct_colors_allocated;
+
+ p = (struct ct_color *) xmalloc (sizeof *p);
+ p->r = color.red;
+ p->g = color.green;
+ p->b = color.blue;
+ p->pixel = pixel;
+ p->next = ct_table[i];
+ ct_table[i] = p;
+ }
+ else
+ return FRAME_FOREGROUND_PIXEL (f);
+ }
+ return p->pixel;
+}
+
+
+/* Value is a vector of all pixel colors contained in the color table,
+ allocated via xmalloc. Set *N to the number of colors. */
+
+static unsigned long *
+colors_in_color_table (n)
+ int *n;
+{
+ int i, j;
+ struct ct_color *p;
+ unsigned long *colors;
+
+ if (ct_colors_allocated == 0)
+ {
+ *n = 0;
+ colors = NULL;
+ }
+ else
+ {
+ colors = (unsigned long *) xmalloc (ct_colors_allocated
+ * sizeof *colors);
+ *n = ct_colors_allocated;
+
+ for (i = j = 0; i < CT_SIZE; ++i)
+ for (p = ct_table[i]; p; p = p->next)
+ colors[j++] = p->pixel;
+ }
+
+ return colors;
+}
+
+#endif /* MAC_TODO */
+
+\f
+/***********************************************************************
+ Algorithms
+ ***********************************************************************/
+
+#if 0 /* MAC_TODO : Mac versions of low level algorithms */
+static void x_laplace_write_row P_ ((struct frame *, long *,
+ int, XImage *, int));
+static void x_laplace_read_row P_ ((struct frame *, Colormap,
+ XColor *, int, XImage *, int));
+
+
+/* Fill COLORS with RGB colors from row Y of image XIMG. F is the
+ frame we operate on, CMAP is the color-map in effect, and WIDTH is
+ the width of one row in the image. */
+
+static void
+x_laplace_read_row (f, cmap, colors, width, ximg, y)
+ struct frame *f;
+ Colormap cmap;
+ XColor *colors;
+ int width;
+ XImage *ximg;
+ int y;
+{
+ int x;
+
+ for (x = 0; x < width; ++x)
+ colors[x].pixel = XGetPixel (ximg, x, y);
+
+ XQueryColors (NULL, cmap, colors, width);
+}
+
+
+/* Write row Y of image XIMG. PIXELS is an array of WIDTH longs
+ containing the pixel colors to write. F is the frame we are
+ working on. */
+
+static void
+x_laplace_write_row (f, pixels, width, ximg, y)
+ struct frame *f;
+ long *pixels;
+ int width;
+ XImage *ximg;
+ int y;
+{
+ int x;
+
+ for (x = 0; x < width; ++x)
+ XPutPixel (ximg, x, y, pixels[x]);
+}
+#endif /* MAC_TODO */
+
+/* Transform image IMG which is used on frame F with a Laplace
+ edge-detection algorithm. The result is an image that can be used
+ to draw disabled buttons, for example. */
+
+static void
+x_laplace (f, img)
+ struct frame *f;
+ struct image *img;
+{
+#if 0 /* MAC_TODO : Mac version */
+ Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
+ XImage *ximg, *oimg;
+ XColor *in[3];
+ long *out;
+ Pixmap pixmap;
+ int x, y, i;
+ long pixel;
+ int in_y, out_y, rc;
+ int mv2 = 45000;
+
+ BLOCK_INPUT;
+
+ /* Get the X image IMG->pixmap. */
+ ximg = XGetImage (NULL, img->pixmap,
+ 0, 0, img->width, img->height, ~0, ZPixmap);
+
+ /* Allocate 3 input rows, and one output row of colors. */
+ for (i = 0; i < 3; ++i)
+ in[i] = (XColor *) alloca (img->width * sizeof (XColor));
+ out = (long *) alloca (img->width * sizeof (long));
+
+ /* Create an X image for output. */
+ rc = x_create_x_image_and_pixmap (f, img->width, img->height, 0,
+ &oimg, &pixmap);
+
+ /* Fill first two rows. */
+ x_laplace_read_row (f, cmap, in[0], img->width, ximg, 0);
+ x_laplace_read_row (f, cmap, in[1], img->width, ximg, 1);
+ in_y = 2;
+
+ /* Write first row, all zeros. */
+ init_color_table ();
+ pixel = lookup_rgb_color (f, 0, 0, 0);
+ for (x = 0; x < img->width; ++x)
+ out[x] = pixel;
+ x_laplace_write_row (f, out, img->width, oimg, 0);
+ out_y = 1;
+
+ for (y = 2; y < img->height; ++y)
+ {
+ int rowa = y % 3;
+ int rowb = (y + 2) % 3;
+
+ x_laplace_read_row (f, cmap, in[rowa], img->width, ximg, in_y++);
+
+ for (x = 0; x < img->width - 2; ++x)
+ {
+ int r = in[rowa][x].red + mv2 - in[rowb][x + 2].red;
+ int g = in[rowa][x].green + mv2 - in[rowb][x + 2].green;
+ int b = in[rowa][x].blue + mv2 - in[rowb][x + 2].blue;
+
+ out[x + 1] = lookup_rgb_color (f, r & 0xffff, g & 0xffff,
+ b & 0xffff);
+ }
+
+ x_laplace_write_row (f, out, img->width, oimg, out_y++);
+ }
+
+ /* Write last line, all zeros. */
+ for (x = 0; x < img->width; ++x)
+ out[x] = pixel;
+ x_laplace_write_row (f, out, img->width, oimg, out_y);
+
+ /* Free the input image, and free resources of IMG. */
+ XDestroyImage (ximg);
+ x_clear_image (f, img);
+
+ /* Put the output image into pixmap, and destroy it. */
+ x_put_x_image (f, oimg, pixmap, img->width, img->height);
+ x_destroy_x_image (oimg);
+
+ /* Remember new pixmap and colors in IMG. */
+ img->pixmap = pixmap;
+ img->colors = colors_in_color_table (&img->ncolors);
+ free_color_table ();
+
+ UNBLOCK_INPUT;
+#endif /* MAC_TODO */
+}
+
+
+/* Build a mask for image IMG which is used on frame F. FILE is the
+ name of an image file, for error messages. HOW determines how to
+ determine the background color of IMG. If it is a list '(R G B)',
+ with R, G, and B being integers >= 0, take that as the color of the
+ background. Otherwise, determine the background color of IMG
+ heuristically. Value is non-zero if successful. */
+
+static int
+x_build_heuristic_mask (f, img, how)
+ struct frame *f;
+ struct image *img;
+ Lisp_Object how;
+{
+#if 0 /* MAC_TODO : Mac version */
+ Display *dpy = FRAME_W32_DISPLAY (f);
+ XImage *ximg, *mask_img;
+ int x, y, rc, look_at_corners_p;
+ unsigned long bg;
+
+ BLOCK_INPUT;
+
+ /* Create an image and pixmap serving as mask. */
+ rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
+ &mask_img, &img->mask);
+ if (!rc)
+ {
+ UNBLOCK_INPUT;
+ return 0;
+ }
+
+ /* Get the X image of IMG->pixmap. */
+ ximg = XGetImage (dpy, img->pixmap, 0, 0, img->width, img->height,
+ ~0, ZPixmap);
+
+ /* Determine the background color of ximg. If HOW is `(R G B)'
+ take that as color. Otherwise, try to determine the color
+ heuristically. */
+ look_at_corners_p = 1;
+
+ if (CONSP (how))
+ {
+ int rgb[3], i = 0;
+
+ while (i < 3
+ && CONSP (how)
+ && NATNUMP (XCAR (how)))
+ {
+ rgb[i] = XFASTINT (XCAR (how)) & 0xffff;
+ how = XCDR (how);
+ }
+
+ if (i == 3 && NILP (how))
+ {
+ char color_name[30];
+ XColor exact, color;
+ Colormap cmap;
+
+ sprintf (color_name, "#%04x%04x%04x", rgb[0], rgb[1], rgb[2]);
+
+ cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
+ if (XLookupColor (dpy, cmap, color_name, &exact, &color))
+ {
+ bg = color.pixel;
+ look_at_corners_p = 0;
+ }
+ }
+ }
+
+ if (look_at_corners_p)
+ {
+ unsigned long corners[4];
+ int i, best_count;
+
+ /* Get the colors at the corners of ximg. */
+ corners[0] = XGetPixel (ximg, 0, 0);
+ corners[1] = XGetPixel (ximg, img->width - 1, 0);
+ corners[2] = XGetPixel (ximg, img->width - 1, img->height - 1);
+ corners[3] = XGetPixel (ximg, 0, img->height - 1);
+
+ /* Choose the most frequently found color as background. */
+ for (i = best_count = 0; i < 4; ++i)
+ {
+ int j, n;
+
+ for (j = n = 0; j < 4; ++j)
+ if (corners[i] == corners[j])
+ ++n;
+
+ if (n > best_count)
+ bg = corners[i], best_count = n;
+ }
+ }
+
+ /* Set all bits in mask_img to 1 whose color in ximg is different
+ from the background color bg. */
+ for (y = 0; y < img->height; ++y)
+ for (x = 0; x < img->width; ++x)
+ XPutPixel (mask_img, x, y, XGetPixel (ximg, x, y) != bg);
+
+ /* Put mask_img into img->mask. */
+ x_put_x_image (f, mask_img, img->mask, img->width, img->height);
+ x_destroy_x_image (mask_img);
+ XDestroyImage (ximg);
+
+ UNBLOCK_INPUT;
+#endif /* MAC_TODO */
+
+ return 1;
+}
+
+
+\f
+/***********************************************************************
+ PBM (mono, gray, color)
+ ***********************************************************************/
+#ifdef HAVE_PBM
+
+static int pbm_image_p P_ ((Lisp_Object object));
+static int pbm_load P_ ((struct frame *f, struct image *img));
+static int pbm_scan_number P_ ((unsigned char **, unsigned char *));
+
+/* The symbol `pbm' identifying images of this type. */
+
+Lisp_Object Qpbm;
+
+/* Indices of image specification fields in gs_format, below. */
+
+enum pbm_keyword_index
+{
+ PBM_TYPE,
+ PBM_FILE,
+ PBM_DATA,
+ PBM_ASCENT,
+ PBM_MARGIN,
+ PBM_RELIEF,
+ PBM_ALGORITHM,
+ PBM_HEURISTIC_MASK,
+ PBM_LAST
+};
+
+/* Vector of image_keyword structures describing the format
+ of valid user-defined image specifications. */
+
+static struct image_keyword pbm_format[PBM_LAST] =
+{
+ {":type", IMAGE_SYMBOL_VALUE, 1},
+ {":file", IMAGE_STRING_VALUE, 0},
+ {":data", IMAGE_STRING_VALUE, 0},
+ {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
+ {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":relief", IMAGE_INTEGER_VALUE, 0},
+ {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
+};
+
+/* Structure describing the image type `pbm'. */
+
+static struct image_type pbm_type =
+{
+ &Qpbm,
+ pbm_image_p,
+ pbm_load,
+ x_clear_image,
+ NULL
+};
+
+
+/* Return non-zero if OBJECT is a valid PBM image specification. */
+
+static int
+pbm_image_p (object)
+ Lisp_Object object;
+{
+ struct image_keyword fmt[PBM_LAST];
+
+ bcopy (pbm_format, fmt, sizeof fmt);
+
+ if (!parse_image_spec (object, fmt, PBM_LAST, Qpbm)
+ || (fmt[PBM_ASCENT].count
+ && XFASTINT (fmt[PBM_ASCENT].value) > 100))
+ return 0;
+
+ /* Must specify either :data or :file. */
+ return fmt[PBM_DATA].count + fmt[PBM_FILE].count == 1;
+}
+
+
+/* Scan a decimal number from *S and return it. Advance *S while
+ reading the number. END is the end of the string. Value is -1 at
+ end of input. */
+
+static int
+pbm_scan_number (s, end)
+ unsigned char **s, *end;
+{
+ int c, val = -1;
+
+ while (*s < end)
+ {
+ /* Skip white-space. */
+ while (*s < end && (c = *(*s)++, isspace (c)))
+ ;
+
+ if (c == '#')
+ {
+ /* Skip comment to end of line. */
+ while (*s < end && (c = *(*s)++, c != '\n'))
+ ;
+ }
+ else if (isdigit (c))
+ {
+ /* Read decimal number. */
+ val = c - '0';
+ while (*s < end && (c = *(*s)++, isdigit (c)))
+ val = 10 * val + c - '0';
+ break;
+ }
+ else
+ break;
+ }
+
+ return val;
+}
+
+
+/* Read FILE into memory. Value is a pointer to a buffer allocated
+ with xmalloc holding FILE's contents. Value is null if an error
+ occured. *SIZE is set to the size of the file. */
+
+static char *
+pbm_read_file (file, size)
+ Lisp_Object file;
+ int *size;
+{
+ FILE *fp = NULL;
+ char *buf = NULL;
+ struct stat st;
+
+ if (stat (XSTRING (file)->data, &st) == 0
+ && (fp = fopen (XSTRING (file)->data, "r")) != NULL
+ && (buf = (char *) xmalloc (st.st_size),
+ fread (buf, 1, st.st_size, fp) == st.st_size))
+ {
+ *size = st.st_size;
+ fclose (fp);
+ }
+ else
+ {
+ if (fp)
+ fclose (fp);
+ if (buf)
+ {
+ xfree (buf);
+ buf = NULL;
+ }
+ }
+
+ return buf;
+}
+
+
+/* Load PBM image IMG for use on frame F. */
+
+static int
+pbm_load (f, img)
+ struct frame *f;
+ struct image *img;
+{
+ int raw_p, x, y;
+ int width, height, max_color_idx = 0;
+ XImage *ximg;
+ Lisp_Object file, specified_file;
+ enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type;
+ struct gcpro gcpro1;
+ unsigned char *contents = NULL;
+ unsigned char *end, *p;
+ int size;
+
+ specified_file = image_spec_value (img->spec, QCfile, NULL);
+ file = Qnil;
+ GCPRO1 (file);
+
+ if (STRINGP (specified_file))
+ {
+ file = x_find_image_file (specified_file);
+ if (!STRINGP (file))
+ {
+ image_error ("Cannot find image file `%s'", specified_file, Qnil);
+ UNGCPRO;
+ return 0;
+ }
+
+ contents = pbm_read_file (file, &size);
+ if (contents == NULL)
+ {
+ image_error ("Error reading `%s'", file, Qnil);
+ UNGCPRO;
+ return 0;
+ }
+
+ p = contents;
+ end = contents + size;
+ }
+ else
+ {
+ Lisp_Object data;
+ data = image_spec_value (img->spec, QCdata, NULL);
+ p = XSTRING (data)->data;
+ end = p + STRING_BYTES (XSTRING (data));
+ }
+
+ /* Check magic number. */
+ if (end - p < 2 || *p++ != 'P')
+ {
+ image_error ("Not a PBM image: `%s'", img->spec, Qnil);
+ error:
+ xfree (contents);
+ UNGCPRO;
+ return 0;
+ }
+
+ switch (*p++)
+ {
+ case '1':
+ raw_p = 0, type = PBM_MONO;
+ break;
+
+ case '2':
+ raw_p = 0, type = PBM_GRAY;
+ break;
+
+ case '3':
+ raw_p = 0, type = PBM_COLOR;
+ break;
+
+ case '4':
+ raw_p = 1, type = PBM_MONO;
+ break;
+
+ case '5':
+ raw_p = 1, type = PBM_GRAY;
+ break;
+
+ case '6':
+ raw_p = 1, type = PBM_COLOR;
+ break;
+
+ default:
+ image_error ("Not a PBM image: `%s'", img->spec, Qnil);
+ goto error;
+ }
+
+ /* Read width, height, maximum color-component. Characters
+ starting with `#' up to the end of a line are ignored. */
+ width = pbm_scan_number (&p, end);
+ height = pbm_scan_number (&p, end);
+
+ if (type != PBM_MONO)
+ {
+ max_color_idx = pbm_scan_number (&p, end);
+ if (raw_p && max_color_idx > 255)
+ max_color_idx = 255;
+ }
+
+ if (width < 0
+ || height < 0
+ || (type != PBM_MONO && max_color_idx < 0))
+ goto error;
+
+ BLOCK_INPUT;
+ if (!x_create_x_image_and_pixmap (f, width, height, 0,
+ &ximg, &img->pixmap))
+ {
+ UNBLOCK_INPUT;
+ goto error;
+ }
+
+ /* Initialize the color hash table. */
+ init_color_table ();
+
+ if (type == PBM_MONO)
+ {
+ int c = 0, g;
+
+ for (y = 0; y < height; ++y)
+ for (x = 0; x < width; ++x)
+ {
+ if (raw_p)
+ {
+ if ((x & 7) == 0)
+ c = *p++;
+ g = c & 0x80;
+ c <<= 1;
+ }
+ else
+ g = pbm_scan_number (&p, end);
+
+ XPutPixel (ximg, x, y, (g
+ ? FRAME_FOREGROUND_PIXEL (f)
+ : FRAME_BACKGROUND_PIXEL (f)));
+ }
+ }
+ else
+ {
+ for (y = 0; y < height; ++y)
+ for (x = 0; x < width; ++x)
+ {
+ int r, g, b;
+
+ if (type == PBM_GRAY)
+ r = g = b = raw_p ? *p++ : pbm_scan_number (&p, end);
+ else if (raw_p)
+ {
+ r = *p++;
+ g = *p++;
+ b = *p++;
+ }
+ else
+ {
+ r = pbm_scan_number (&p, end);
+ g = pbm_scan_number (&p, end);
+ b = pbm_scan_number (&p, end);
+ }
+
+ if (r < 0 || g < 0 || b < 0)
+ {
+ xfree (ximg->data);
+ ximg->data = NULL;
+ XDestroyImage (ximg);
+ UNBLOCK_INPUT;
+ image_error ("Invalid pixel value in image `%s'",
+ img->spec, Qnil);
+ goto error;
+ }
+
+ /* RGB values are now in the range 0..max_color_idx.
+ Scale this to the range 0..0xffff supported by X. */
+ r = (double) r * 65535 / max_color_idx;
+ g = (double) g * 65535 / max_color_idx;
+ b = (double) b * 65535 / max_color_idx;
+ XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
+ }
+ }
+
+ /* Store in IMG->colors the colors allocated for the image, and
+ free the color table. */
+ img->colors = colors_in_color_table (&img->ncolors);
+ free_color_table ();
+
+ /* Put the image into a pixmap. */
+ x_put_x_image (f, ximg, img->pixmap, width, height);
+ x_destroy_x_image (ximg);
+ UNBLOCK_INPUT;
+
+ img->width = width;
+ img->height = height;
+
+ UNGCPRO;
+ xfree (contents);
+ return 1;
+}
+#endif /* HAVE_PBM */
+
+\f
+/***********************************************************************
+ PNG
+ ***********************************************************************/
+
+#if HAVE_PNG
+
+#include <png.h>
+
+/* Function prototypes. */
+
+static int png_image_p P_ ((Lisp_Object object));
+static int png_load P_ ((struct frame *f, struct image *img));
+
+/* The symbol `png' identifying images of this type. */
+
+Lisp_Object Qpng;
+
+/* Indices of image specification fields in png_format, below. */
+
+enum png_keyword_index
+{
+ PNG_TYPE,
+ PNG_DATA,
+ PNG_FILE,
+ PNG_ASCENT,
+ PNG_MARGIN,
+ PNG_RELIEF,
+ PNG_ALGORITHM,
+ PNG_HEURISTIC_MASK,
+ PNG_LAST
+};
+
+/* Vector of image_keyword structures describing the format
+ of valid user-defined image specifications. */
+
+static struct image_keyword png_format[PNG_LAST] =
+{
+ {":type", IMAGE_SYMBOL_VALUE, 1},
+ {":data", IMAGE_STRING_VALUE, 0},
+ {":file", IMAGE_STRING_VALUE, 0},
+ {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
+ {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":relief", IMAGE_INTEGER_VALUE, 0},
+ {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
+};
+
+/* Structure describing the image type `png'. */
+
+static struct image_type png_type =
+{
+ &Qpng,
+ png_image_p,
+ png_load,
+ x_clear_image,
+ NULL
+};
+
+
+/* Return non-zero if OBJECT is a valid PNG image specification. */
+
+static int
+png_image_p (object)
+ Lisp_Object object;
+{
+ struct image_keyword fmt[PNG_LAST];
+ bcopy (png_format, fmt, sizeof fmt);
+
+ if (!parse_image_spec (object, fmt, PNG_LAST, Qpng)
+ || (fmt[PNG_ASCENT].count
+ && XFASTINT (fmt[PNG_ASCENT].value) > 100))
+ return 0;
+
+ /* Must specify either the :data or :file keyword. */
+ return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
+}
+
+
+/* Error and warning handlers installed when the PNG library
+ is initialized. */
+
+static void
+my_png_error (png_ptr, msg)
+ png_struct *png_ptr;
+ char *msg;
+{
+ xassert (png_ptr != NULL);
+ image_error ("PNG error: %s", build_string (msg), Qnil);
+ longjmp (png_ptr->jmpbuf, 1);
+}
+
+
+static void
+my_png_warning (png_ptr, msg)
+ png_struct *png_ptr;
+ char *msg;
+{
+ xassert (png_ptr != NULL);
+ image_error ("PNG warning: %s", build_string (msg), Qnil);
+}
+
+/* Memory source for PNG decoding. */
+
+struct png_memory_storage
+{
+ unsigned char *bytes; /* The data */
+ size_t len; /* How big is it? */
+ int index; /* Where are we? */
+};
+
+
+/* Function set as reader function when reading PNG image from memory.
+ PNG_PTR is a pointer to the PNG control structure. Copy LENGTH
+ bytes from the input to DATA. */
+
+static void
+png_read_from_memory (png_ptr, data, length)
+ png_structp png_ptr;
+ png_bytep data;
+ png_size_t length;
+{
+ struct png_memory_storage *tbr
+ = (struct png_memory_storage *) png_get_io_ptr (png_ptr);
+
+ if (length > tbr->len - tbr->index)
+ png_error (png_ptr, "Read error");
+
+ bcopy (tbr->bytes + tbr->index, data, length);
+ tbr->index = tbr->index + length;
+}
+
+/* Load PNG image IMG for use on frame F. Value is non-zero if
+ successful. */
+
+static int
+png_load (f, img)
+ struct frame *f;
+ struct image *img;
+{
+ Lisp_Object file, specified_file;
+ Lisp_Object specified_data;
+ int x, y, i;
+ XImage *ximg, *mask_img = NULL;
+ struct gcpro gcpro1;
+ png_struct *png_ptr = NULL;
+ png_info *info_ptr = NULL, *end_info = NULL;
+ FILE *fp = NULL;
+ png_byte sig[8];
+ png_byte *pixels = NULL;
+ png_byte **rows = NULL;
+ png_uint_32 width, height;
+ int bit_depth, color_type, interlace_type;
+ png_byte channels;
+ png_uint_32 row_bytes;
+ int transparent_p;
+ char *gamma_str;
+ double screen_gamma, image_gamma;
+ int intent;
+ struct png_memory_storage tbr; /* Data to be read */
+
+ /* Find out what file to load. */
+ specified_file = image_spec_value (img->spec, QCfile, NULL);
+ specified_data = image_spec_value (img->spec, QCdata, NULL);
+ file = Qnil;
+ GCPRO1 (file);
+
+ if (NILP (specified_data))
+ {
+ file = x_find_image_file (specified_file);
+ if (!STRINGP (file))
+ {
+ image_error ("Cannot find image file `%s'", specified_file, Qnil);
+ UNGCPRO;
+ return 0;
+ }
+
+ /* Open the image file. */
+ fp = fopen (XSTRING (file)->data, "rb");
+ if (!fp)
+ {
+ image_error ("Cannot open image file `%s'", file, Qnil);
+ UNGCPRO;
+ fclose (fp);
+ return 0;
+ }
+
+ /* Check PNG signature. */
+ if (fread (sig, 1, sizeof sig, fp) != sizeof sig
+ || !png_check_sig (sig, sizeof sig))
+ {
+ image_error ("Not a PNG file:` %s'", file, Qnil);
+ UNGCPRO;
+ fclose (fp);
+ return 0;
+ }
+ }
+ else
+ {
+ /* Read from memory. */
+ tbr.bytes = XSTRING (specified_data)->data;
+ tbr.len = STRING_BYTES (XSTRING (specified_data));
+ tbr.index = 0;
+
+ /* Check PNG signature. */
+ if (tbr.len < sizeof sig
+ || !png_check_sig (tbr.bytes, sizeof sig))
+ {
+ image_error ("Not a PNG image: `%s'", img->spec, Qnil);
+ UNGCPRO;
+ return 0;
+ }
+
+ /* Need to skip past the signature. */
+ tbr.bytes += sizeof (sig);
+ }
+
+ /* Initialize read and info structs for PNG lib. */
+ png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
+ my_png_error, my_png_warning);
+ if (!png_ptr)
+ {
+ if (fp) fclose (fp);
+ UNGCPRO;
+ return 0;
+ }
+
+ info_ptr = png_create_info_struct (png_ptr);
+ if (!info_ptr)
+ {
+ png_destroy_read_struct (&png_ptr, NULL, NULL);
+ if (fp) fclose (fp);
+ UNGCPRO;
+ return 0;
+ }
+
+ end_info = png_create_info_struct (png_ptr);
+ if (!end_info)
+ {
+ png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
+ if (fp) fclose (fp);
+ UNGCPRO;
+ return 0;
+ }
+
+ /* Set error jump-back. We come back here when the PNG library
+ detects an error. */
+ if (setjmp (png_ptr->jmpbuf))
+ {
+ error:
+ if (png_ptr)
+ png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
+ xfree (pixels);
+ xfree (rows);
+ if (fp) fclose (fp);
+ UNGCPRO;
+ return 0;
+ }
+
+ /* Read image info. */
+ if (!NILP (specified_data))
+ png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
+ else
+ png_init_io (png_ptr, fp);
+
+ png_set_sig_bytes (png_ptr, sizeof sig);
+ png_read_info (png_ptr, info_ptr);
+ png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
+ &interlace_type, NULL, NULL);
+
+ /* If image contains simply transparency data, we prefer to
+ construct a clipping mask. */
+ if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
+ transparent_p = 1;
+ else
+ transparent_p = 0;
+
+ /* This function is easier to write if we only have to handle
+ one data format: RGB or RGBA with 8 bits per channel. Let's
+ transform other formats into that format. */
+
+ /* Strip more than 8 bits per channel. */
+ if (bit_depth == 16)
+ png_set_strip_16 (png_ptr);
+
+ /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
+ if available. */
+ png_set_expand (png_ptr);
+
+ /* Convert grayscale images to RGB. */
+ if (color_type == PNG_COLOR_TYPE_GRAY
+ || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ png_set_gray_to_rgb (png_ptr);
+
+ /* The value 2.2 is a guess for PC monitors from PNG example.c. */
+ gamma_str = getenv ("SCREEN_GAMMA");
+ screen_gamma = gamma_str ? atof (gamma_str) : 2.2;
+
+ /* Tell the PNG lib to handle gamma correction for us. */
+
+#if defined(PNG_READ_sRGB_SUPPORTED) || defined(PNG_WRITE_sRGB_SUPPORTED)
+ if (png_get_sRGB (png_ptr, info_ptr, &intent))
+ /* There is a special chunk in the image specifying the gamma. */
+ png_set_sRGB (png_ptr, info_ptr, intent);
+ else
+#endif
+ if (png_get_gAMA (png_ptr, info_ptr, &image_gamma))
+ /* Image contains gamma information. */
+ png_set_gamma (png_ptr, screen_gamma, image_gamma);
+ else
+ /* Use a default of 0.5 for the image gamma. */
+ png_set_gamma (png_ptr, screen_gamma, 0.5);
+
+ /* Handle alpha channel by combining the image with a background
+ color. Do this only if a real alpha channel is supplied. For
+ simple transparency, we prefer a clipping mask. */
+ if (!transparent_p)
+ {
+ png_color_16 *image_background;
+
+ if (png_get_bKGD (png_ptr, info_ptr, &image_background))
+ /* Image contains a background color with which to
+ combine the image. */
+ png_set_background (png_ptr, image_background,
+ PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
+ else
+ {
+ /* Image does not contain a background color with which
+ to combine the image data via an alpha channel. Use
+ the frame's background instead. */
+ XColor color;
+ Colormap cmap;
+ png_color_16 frame_background;
+
+ BLOCK_INPUT;
+ cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
+ color.pixel = FRAME_BACKGROUND_PIXEL (f);
+ XQueryColor (FRAME_W32_DISPLAY (f), cmap, &color);
+ UNBLOCK_INPUT;
+
+ bzero (&frame_background, sizeof frame_background);
+ frame_background.red = color.red;
+ frame_background.green = color.green;
+ frame_background.blue = color.blue;
+
+ png_set_background (png_ptr, &frame_background,
+ PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
+ }
+ }
+
+ /* Update info structure. */
+ png_read_update_info (png_ptr, info_ptr);
+
+ /* Get number of channels. Valid values are 1 for grayscale images
+ and images with a palette, 2 for grayscale images with transparency
+ information (alpha channel), 3 for RGB images, and 4 for RGB
+ images with alpha channel, i.e. RGBA. If conversions above were
+ sufficient we should only have 3 or 4 channels here. */
+ channels = png_get_channels (png_ptr, info_ptr);
+ xassert (channels == 3 || channels == 4);
+
+ /* Number of bytes needed for one row of the image. */
+ row_bytes = png_get_rowbytes (png_ptr, info_ptr);
+
+ /* Allocate memory for the image. */
+ pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
+ rows = (png_byte **) xmalloc (height * sizeof *rows);
+ for (i = 0; i < height; ++i)
+ rows[i] = pixels + i * row_bytes;
+
+ /* Read the entire image. */
+ png_read_image (png_ptr, rows);
+ png_read_end (png_ptr, info_ptr);
+ if (fp)
+ {
+ fclose (fp);
+ fp = NULL;
+ }
+
+ BLOCK_INPUT;
+
+ /* Create the X image and pixmap. */
+ if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
+ &img->pixmap))
+ {
+ UNBLOCK_INPUT;
+ goto error;
+ }
+
+ /* Create an image and pixmap serving as mask if the PNG image
+ contains an alpha channel. */
+ if (channels == 4
+ && !transparent_p
+ && !x_create_x_image_and_pixmap (f, width, height, 1,
+ &mask_img, &img->mask))
+ {
+ x_destroy_x_image (ximg);
+ XFreePixmap (FRAME_W32_DISPLAY (f), img->pixmap);
+ img->pixmap = 0;
+ UNBLOCK_INPUT;
+ goto error;
+ }
+
+ /* Fill the X image and mask from PNG data. */
+ init_color_table ();
+
+ for (y = 0; y < height; ++y)
+ {
+ png_byte *p = rows[y];
+
+ for (x = 0; x < width; ++x)
+ {
+ unsigned r, g, b;
+
+ r = *p++ << 8;
+ g = *p++ << 8;
+ b = *p++ << 8;
+ XPutPixel (ximg, x, y, lookup_rgb_color (f, r, g, b));
+
+ /* An alpha channel, aka mask channel, associates variable
+ transparency with an image. Where other image formats
+ support binary transparency---fully transparent or fully
+ opaque---PNG allows up to 254 levels of partial transparency.
+ The PNG library implements partial transparency by combining
+ the image with a specified background color.
+
+ I'm not sure how to handle this here nicely: because the
+ background on which the image is displayed may change, for
+ real alpha channel support, it would be necessary to create
+ a new image for each possible background.
+
+ What I'm doing now is that a mask is created if we have
+ boolean transparency information. Otherwise I'm using
+ the frame's background color to combine the image with. */
+
+ if (channels == 4)
+ {
+ if (mask_img)
+ XPutPixel (mask_img, x, y, *p > 0);
+ ++p;
+ }
+ }
+ }
+
+ /* Remember colors allocated for this image. */
+ img->colors = colors_in_color_table (&img->ncolors);
+ free_color_table ();
+
+ /* Clean up. */
+ png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
+ xfree (rows);
+ xfree (pixels);
+
+ img->width = width;
+ img->height = height;
+
+ /* Put the image into the pixmap, then free the X image and its buffer. */
+ x_put_x_image (f, ximg, img->pixmap, width, height);
+ x_destroy_x_image (ximg);
+
+ /* Same for the mask. */
+ if (mask_img)
+ {
+ x_put_x_image (f, mask_img, img->mask, img->width, img->height);
+ x_destroy_x_image (mask_img);
+ }
+
+ UNBLOCK_INPUT;
+ UNGCPRO;
+ return 1;
+}
+
+#endif /* HAVE_PNG != 0 */
+
+
+\f
+/***********************************************************************
+ JPEG
+ ***********************************************************************/
+
+#if HAVE_JPEG
+
+/* Work around a warning about HAVE_STDLIB_H being redefined in
+ jconfig.h. */
+#ifdef HAVE_STDLIB_H
+#define HAVE_STDLIB_H_1
+#undef HAVE_STDLIB_H
+#endif /* HAVE_STLIB_H */
+
+#include <jpeglib.h>
+#include <jerror.h>
+#include <setjmp.h>
+
+#ifdef HAVE_STLIB_H_1
+#define HAVE_STDLIB_H 1
+#endif
+
+static int jpeg_image_p P_ ((Lisp_Object object));
+static int jpeg_load P_ ((struct frame *f, struct image *img));
+
+/* The symbol `jpeg' identifying images of this type. */
+
+Lisp_Object Qjpeg;
+
+/* Indices of image specification fields in gs_format, below. */
+
+enum jpeg_keyword_index
+{
+ JPEG_TYPE,
+ JPEG_DATA,
+ JPEG_FILE,
+ JPEG_ASCENT,
+ JPEG_MARGIN,
+ JPEG_RELIEF,
+ JPEG_ALGORITHM,
+ JPEG_HEURISTIC_MASK,
+ JPEG_LAST
+};
+
+/* Vector of image_keyword structures describing the format
+ of valid user-defined image specifications. */
+
+static struct image_keyword jpeg_format[JPEG_LAST] =
+{
+ {":type", IMAGE_SYMBOL_VALUE, 1},
+ {":data", IMAGE_STRING_VALUE, 0},
+ {":file", IMAGE_STRING_VALUE, 0},
+ {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
+ {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":relief", IMAGE_INTEGER_VALUE, 0},
+ {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
+};
+
+/* Structure describing the image type `jpeg'. */
+
+static struct image_type jpeg_type =
+{
+ &Qjpeg,
+ jpeg_image_p,
+ jpeg_load,
+ x_clear_image,
+ NULL
+};
+
+
+/* Return non-zero if OBJECT is a valid JPEG image specification. */
+
+static int
+jpeg_image_p (object)
+ Lisp_Object object;
+{
+ struct image_keyword fmt[JPEG_LAST];
+
+ bcopy (jpeg_format, fmt, sizeof fmt);
+
+ if (!parse_image_spec (object, fmt, JPEG_LAST, Qjpeg)
+ || (fmt[JPEG_ASCENT].count
+ && XFASTINT (fmt[JPEG_ASCENT].value) > 100))
+ return 0;
+
+ /* Must specify either the :data or :file keyword. */
+ return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
+}
+
+
+struct my_jpeg_error_mgr
+{
+ struct jpeg_error_mgr pub;
+ jmp_buf setjmp_buffer;
+};
+
+static void
+my_error_exit (cinfo)
+ j_common_ptr cinfo;
+{
+ struct my_jpeg_error_mgr *mgr = (struct my_jpeg_error_mgr *) cinfo->err;
+ longjmp (mgr->setjmp_buffer, 1);
+}
+
+/* Init source method for JPEG data source manager. Called by
+ jpeg_read_header() before any data is actually read. See
+ libjpeg.doc from the JPEG lib distribution. */
+
+static void
+our_init_source (cinfo)
+ j_decompress_ptr cinfo;
+{
+}
+
+
+/* Fill input buffer method for JPEG data source manager. Called
+ whenever more data is needed. We read the whole image in one step,
+ so this only adds a fake end of input marker at the end. */
+
+static boolean
+our_fill_input_buffer (cinfo)
+ j_decompress_ptr cinfo;
+{
+ /* Insert a fake EOI marker. */
+ struct jpeg_source_mgr *src = cinfo->src;
+ static JOCTET buffer[2];
+
+ buffer[0] = (JOCTET) 0xFF;
+ buffer[1] = (JOCTET) JPEG_EOI;
+
+ src->next_input_byte = buffer;
+ src->bytes_in_buffer = 2;
+ return TRUE;
+}
+
+
+/* Method to skip over NUM_BYTES bytes in the image data. CINFO->src
+ is the JPEG data source manager. */
+
+static void
+our_skip_input_data (cinfo, num_bytes)
+ j_decompress_ptr cinfo;
+ long num_bytes;
+{
+ struct jpeg_source_mgr *src = (struct jpeg_source_mgr *) cinfo->src;
+
+ if (src)
+ {
+ if (num_bytes > src->bytes_in_buffer)
+ ERREXIT (cinfo, JERR_INPUT_EOF);
+
+ src->bytes_in_buffer -= num_bytes;
+ src->next_input_byte += num_bytes;
+ }
+}
+
+
+/* Method to terminate data source. Called by
+ jpeg_finish_decompress() after all data has been processed. */
+
+static void
+our_term_source (cinfo)
+ j_decompress_ptr cinfo;
+{
+}
+
+
+/* Set up the JPEG lib for reading an image from DATA which contains
+ LEN bytes. CINFO is the decompression info structure created for
+ reading the image. */
+
+static void
+jpeg_memory_src (cinfo, data, len)
+ j_decompress_ptr cinfo;
+ JOCTET *data;
+ unsigned int len;
+{
+ struct jpeg_source_mgr *src;
+
+ if (cinfo->src == NULL)
+ {
+ /* First time for this JPEG object? */
+ cinfo->src = (struct jpeg_source_mgr *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ sizeof (struct jpeg_source_mgr));
+ src = (struct jpeg_source_mgr *) cinfo->src;
+ src->next_input_byte = data;
+ }
+
+ src = (struct jpeg_source_mgr *) cinfo->src;
+ src->init_source = our_init_source;
+ src->fill_input_buffer = our_fill_input_buffer;
+ src->skip_input_data = our_skip_input_data;
+ src->resync_to_restart = jpeg_resync_to_restart; /* Use default method. */
+ src->term_source = our_term_source;
+ src->bytes_in_buffer = len;
+ src->next_input_byte = data;
+}
+
+
+/* Load image IMG for use on frame F. Patterned after example.c
+ from the JPEG lib. */
+
+static int
+jpeg_load (f, img)
+ struct frame *f;
+ struct image *img;
+{
+ struct jpeg_decompress_struct cinfo;
+ struct my_jpeg_error_mgr mgr;
+ Lisp_Object file, specified_file;
+ Lisp_Object specified_data;
+ FILE *fp = NULL;
+ JSAMPARRAY buffer;
+ int row_stride, x, y;
+ XImage *ximg = NULL;
+ int rc;
+ unsigned long *colors;
+ int width, height;
+ struct gcpro gcpro1;
+
+ /* Open the JPEG file. */
+ specified_file = image_spec_value (img->spec, QCfile, NULL);
+ specified_data = image_spec_value (img->spec, QCdata, NULL);
+ file = Qnil;
+ GCPRO1 (file);
+
+ if (NILP (specified_data))
+ {
+ file = x_find_image_file (specified_file);
+ if (!STRINGP (file))
+ {
+ image_error ("Cannot find image file `%s'", specified_file, Qnil);
+ UNGCPRO;
+ return 0;
+ }
+
+ fp = fopen (XSTRING (file)->data, "r");
+ if (fp == NULL)
+ {
+ image_error ("Cannot open `%s'", file, Qnil);
+ UNGCPRO;
+ return 0;
+ }
+ }
+
+ /* Customize libjpeg's error handling to call my_error_exit when an
+ error is detected. This function will perform a longjmp. */
+ mgr.pub.error_exit = my_error_exit;
+ cinfo.err = jpeg_std_error (&mgr.pub);
+
+ if ((rc = setjmp (mgr.setjmp_buffer)) != 0)
+ {
+ if (rc == 1)
+ {
+ /* Called from my_error_exit. Display a JPEG error. */
+ char buffer[JMSG_LENGTH_MAX];
+ cinfo.err->format_message ((j_common_ptr) &cinfo, buffer);
+ image_error ("Error reading JPEG image `%s': %s", img->spec,
+ build_string (buffer));
+ }
+
+ /* Close the input file and destroy the JPEG object. */
+ if (fp)
+ fclose (fp);
+ jpeg_destroy_decompress (&cinfo);
+
+ BLOCK_INPUT;
+
+ /* If we already have an XImage, free that. */
+ x_destroy_x_image (ximg);
+
+ /* Free pixmap and colors. */
+ x_clear_image (f, img);
+
+ UNBLOCK_INPUT;
+ UNGCPRO;
+ return 0;
+ }
+
+ /* Create the JPEG decompression object. Let it read from fp.
+ Read the JPEG image header. */
+ jpeg_create_decompress (&cinfo);
+
+ if (NILP (specified_data))
+ jpeg_stdio_src (&cinfo, fp);
+ else
+ jpeg_memory_src (&cinfo, XSTRING (specified_data)->data,
+ STRING_BYTES (XSTRING (specified_data)));
+
+ jpeg_read_header (&cinfo, TRUE);
+
+ /* Customize decompression so that color quantization will be used.
+ Start decompression. */
+ cinfo.quantize_colors = TRUE;
+ jpeg_start_decompress (&cinfo);
+ width = img->width = cinfo.output_width;
+ height = img->height = cinfo.output_height;
+
+ BLOCK_INPUT;
+
+ /* Create X image and pixmap. */
+ if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg,
+ &img->pixmap))
+ {
+ UNBLOCK_INPUT;
+ longjmp (mgr.setjmp_buffer, 2);
+ }
+
+ /* Allocate colors. When color quantization is used,
+ cinfo.actual_number_of_colors has been set with the number of
+ colors generated, and cinfo.colormap is a two-dimensional array
+ of color indices in the range 0..cinfo.actual_number_of_colors.
+ No more than 255 colors will be generated. */
+ {
+ int i, ir, ig, ib;
+
+ if (cinfo.out_color_components > 2)
+ ir = 0, ig = 1, ib = 2;
+ else if (cinfo.out_color_components > 1)
+ ir = 0, ig = 1, ib = 0;
+ else
+ ir = 0, ig = 0, ib = 0;
+
+ /* Use the color table mechanism because it handles colors that
+ cannot be allocated nicely. Such colors will be replaced with
+ a default color, and we don't have to care about which colors
+ can be freed safely, and which can't. */
+ init_color_table ();
+ colors = (unsigned long *) alloca (cinfo.actual_number_of_colors
+ * sizeof *colors);
+
+ for (i = 0; i < cinfo.actual_number_of_colors; ++i)
+ {
+ /* Multiply RGB values with 255 because X expects RGB values
+ in the range 0..0xffff. */
+ int r = cinfo.colormap[ir][i] << 8;
+ int g = cinfo.colormap[ig][i] << 8;
+ int b = cinfo.colormap[ib][i] << 8;
+ colors[i] = lookup_rgb_color (f, r, g, b);
+ }
+
+ /* Remember those colors actually allocated. */
+ img->colors = colors_in_color_table (&img->ncolors);
+ free_color_table ();
+ }
+
+ /* Read pixels. */
+ row_stride = width * cinfo.output_components;
+ buffer = cinfo.mem->alloc_sarray ((j_common_ptr) &cinfo, JPOOL_IMAGE,
+ row_stride, 1);
+ for (y = 0; y < height; ++y)
+ {
+ jpeg_read_scanlines (&cinfo, buffer, 1);
+ for (x = 0; x < cinfo.output_width; ++x)
+ XPutPixel (ximg, x, y, colors[buffer[0][x]]);
+ }
+
+ /* Clean up. */
+ jpeg_finish_decompress (&cinfo);
+ jpeg_destroy_decompress (&cinfo);
+ if (fp)
+ fclose (fp);
+
+ /* Put the image into the pixmap. */
+ x_put_x_image (f, ximg, img->pixmap, width, height);
+ x_destroy_x_image (ximg);
+ UNBLOCK_INPUT;
+ UNGCPRO;
+ return 1;
+}
+
+#endif /* HAVE_JPEG */
+
+
+\f
+/***********************************************************************
+ TIFF
+ ***********************************************************************/
+
+#if HAVE_TIFF
+
+#include <tiffio.h>
+
+static int tiff_image_p P_ ((Lisp_Object object));
+static int tiff_load P_ ((struct frame *f, struct image *img));
+
+/* The symbol `tiff' identifying images of this type. */
+
+Lisp_Object Qtiff;
+
+/* Indices of image specification fields in tiff_format, below. */
+
+enum tiff_keyword_index
+{
+ TIFF_TYPE,
+ TIFF_DATA,
+ TIFF_FILE,
+ TIFF_ASCENT,
+ TIFF_MARGIN,
+ TIFF_RELIEF,
+ TIFF_ALGORITHM,
+ TIFF_HEURISTIC_MASK,
+ TIFF_LAST
+};
+
+/* Vector of image_keyword structures describing the format
+ of valid user-defined image specifications. */
+
+static struct image_keyword tiff_format[TIFF_LAST] =
+{
+ {":type", IMAGE_SYMBOL_VALUE, 1},
+ {":data", IMAGE_STRING_VALUE, 0},
+ {":file", IMAGE_STRING_VALUE, 0},
+ {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
+ {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":relief", IMAGE_INTEGER_VALUE, 0},
+ {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
+};
+
+/* Structure describing the image type `tiff'. */
+
+static struct image_type tiff_type =
+{
+ &Qtiff,
+ tiff_image_p,
+ tiff_load,
+ x_clear_image,
+ NULL
+};
+
+
+/* Return non-zero if OBJECT is a valid TIFF image specification. */
+
+static int
+tiff_image_p (object)
+ Lisp_Object object;
+{
+ struct image_keyword fmt[TIFF_LAST];
+ bcopy (tiff_format, fmt, sizeof fmt);
+
+ if (!parse_image_spec (object, fmt, TIFF_LAST, Qtiff)
+ || (fmt[TIFF_ASCENT].count
+ && XFASTINT (fmt[TIFF_ASCENT].value) > 100))
+ return 0;
+
+ /* Must specify either the :data or :file keyword. */
+ return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
+}
+
+
+/* Reading from a memory buffer for TIFF images Based on the PNG
+ memory source, but we have to provide a lot of extra functions.
+ Blah.
+
+ We really only need to implement read and seek, but I am not
+ convinced that the TIFF library is smart enough not to destroy
+ itself if we only hand it the function pointers we need to
+ override. */
+
+typedef struct
+{
+ unsigned char *bytes;
+ size_t len;
+ int index;
+}
+tiff_memory_source;
+
+static size_t
+tiff_read_from_memory (data, buf, size)
+ thandle_t data;
+ tdata_t buf;
+ tsize_t size;
+{
+ tiff_memory_source *src = (tiff_memory_source *) data;
+
+ if (size > src->len - src->index)
+ return (size_t) -1;
+ bcopy (src->bytes + src->index, buf, size);
+ src->index += size;
+ return size;
+}
+
+static size_t
+tiff_write_from_memory (data, buf, size)
+ thandle_t data;
+ tdata_t buf;
+ tsize_t size;
+{
+ return (size_t) -1;
+}
+
+static toff_t
+tiff_seek_in_memory (data, off, whence)
+ thandle_t data;
+ toff_t off;
+ int whence;
+{
+ tiff_memory_source *src = (tiff_memory_source *) data;
+ int idx;
+
+ switch (whence)
+ {
+ case SEEK_SET: /* Go from beginning of source. */
+ idx = off;
+ break;
+
+ case SEEK_END: /* Go from end of source. */
+ idx = src->len + off;
+ break;
+
+ case SEEK_CUR: /* Go from current position. */
+ idx = src->index + off;
+ break;
+
+ default: /* Invalid `whence'. */
+ return -1;
+ }
+
+ if (idx > src->len || idx < 0)
+ return -1;
+
+ src->index = idx;
+ return src->index;
+}
+
+static int
+tiff_close_memory (data)
+ thandle_t data;
+{
+ /* NOOP */
+ return 0;
+}
+
+static int
+tiff_mmap_memory (data, pbase, psize)
+ thandle_t data;
+ tdata_t *pbase;
+ toff_t *psize;
+{
+ /* It is already _IN_ memory. */
+ return 0;
+}
+
+static void
+tiff_unmap_memory (data, base, size)
+ thandle_t data;
+ tdata_t base;
+ toff_t size;
+{
+ /* We don't need to do this. */
+}
+
+static toff_t
+tiff_size_of_memory (data)
+ thandle_t data;
+{
+ return ((tiff_memory_source *) data)->len;
+}
+
+/* Load TIFF image IMG for use on frame F. Value is non-zero if
+ successful. */
+
+static int
+tiff_load (f, img)
+ struct frame *f;
+ struct image *img;
+{
+ Lisp_Object file, specified_file;
+ Lisp_Object specified_data;
+ TIFF *tiff;
+ int width, height, x, y;
+ uint32 *buf;
+ int rc;
+ XImage *ximg;
+ struct gcpro gcpro1;
+ tiff_memory_source memsrc;
+
+ specified_file = image_spec_value (img->spec, QCfile, NULL);
+ specified_data = image_spec_value (img->spec, QCdata, NULL);
+ file = Qnil;
+ GCPRO1 (file);
+
+ if (NILP (specified_data))
+ {
+ /* Read from a file */
+ file = x_find_image_file (specified_file);
+ if (!STRINGP (file))
+ {
+ image_error ("Cannot find image file `%s'", file, Qnil);
+ UNGCPRO;
+ return 0;
+ }
+
+ /* Try to open the image file. */
+ tiff = TIFFOpen (XSTRING (file)->data, "r");
+ if (tiff == NULL)
+ {
+ image_error ("Cannot open `%s'", file, Qnil);
+ UNGCPRO;
+ return 0;
+ }
+ }
+ else
+ {
+ /* Memory source! */
+ memsrc.bytes = XSTRING (specified_data)->data;
+ memsrc.len = STRING_BYTES (XSTRING (specified_data));
+ memsrc.index = 0;
+
+ tiff = TIFFClientOpen ("memory_source", "r", &memsrc,
+ (TIFFReadWriteProc) tiff_read_from_memory,
+ (TIFFReadWriteProc) tiff_write_from_memory,
+ tiff_seek_in_memory,
+ tiff_close_memory,
+ tiff_size_of_memory,
+ tiff_mmap_memory,
+ tiff_unmap_memory);
+
+ if (!tiff)
+ {
+ image_error ("Cannot open memory source for `%s'", img->spec, Qnil);
+ UNGCPRO;
+ return 0;
+ }
+ }
+
+ /* Get width and height of the image, and allocate a raster buffer
+ of width x height 32-bit values. */
+ TIFFGetField (tiff, TIFFTAG_IMAGEWIDTH, &width);
+ TIFFGetField (tiff, TIFFTAG_IMAGELENGTH, &height);
+ buf = (uint32 *) xmalloc (width * height * sizeof *buf);
+
+ rc = TIFFReadRGBAImage (tiff, width, height, buf, 0);
+ TIFFClose (tiff);
+ if (!rc)
+ {
+ image_error ("Error reading TIFF image `%s'", img->spec, Qnil);
+ xfree (buf);
+ UNGCPRO;
+ return 0;
+ }
+
+ BLOCK_INPUT;
+
+ /* Create the X image and pixmap. */
+ if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
+ {
+ UNBLOCK_INPUT;
+ xfree (buf);
+ UNGCPRO;
+ return 0;
+ }
+
+ /* Initialize the color table. */
+ init_color_table ();
+
+ /* Process the pixel raster. Origin is in the lower-left corner. */
+ for (y = 0; y < height; ++y)
+ {
+ uint32 *row = buf + y * width;
+
+ for (x = 0; x < width; ++x)
+ {
+ uint32 abgr = row[x];
+ int r = TIFFGetR (abgr) << 8;
+ int g = TIFFGetG (abgr) << 8;
+ int b = TIFFGetB (abgr) << 8;
+ XPutPixel (ximg, x, height - 1 - y, lookup_rgb_color (f, r, g, b));
+ }
+ }
+
+ /* Remember the colors allocated for the image. Free the color table. */
+ img->colors = colors_in_color_table (&img->ncolors);
+ free_color_table ();
+
+ /* Put the image into the pixmap, then free the X image and its buffer. */
+ x_put_x_image (f, ximg, img->pixmap, width, height);
+ x_destroy_x_image (ximg);
+ xfree (buf);
+ UNBLOCK_INPUT;
+
+ img->width = width;
+ img->height = height;
+
+ UNGCPRO;
+ return 1;
+}
+
+#endif /* HAVE_TIFF != 0 */
+
+
+\f
+/***********************************************************************
+ GIF
+ ***********************************************************************/
+
+#if HAVE_GIF
+
+#include <gif_lib.h>
+
+static int gif_image_p P_ ((Lisp_Object object));
+static int gif_load P_ ((struct frame *f, struct image *img));
+
+/* The symbol `gif' identifying images of this type. */
+
+Lisp_Object Qgif;
+
+/* Indices of image specification fields in gif_format, below. */
+
+enum gif_keyword_index
+{
+ GIF_TYPE,
+ GIF_DATA,
+ GIF_FILE,
+ GIF_ASCENT,
+ GIF_MARGIN,
+ GIF_RELIEF,
+ GIF_ALGORITHM,
+ GIF_HEURISTIC_MASK,
+ GIF_IMAGE,
+ GIF_LAST
+};
+
+/* Vector of image_keyword structures describing the format
+ of valid user-defined image specifications. */
+
+static struct image_keyword gif_format[GIF_LAST] =
+{
+ {":type", IMAGE_SYMBOL_VALUE, 1},
+ {":data", IMAGE_STRING_VALUE, 0},
+ {":file", IMAGE_STRING_VALUE, 0},
+ {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
+ {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":relief", IMAGE_INTEGER_VALUE, 0},
+ {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":image", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0}
+};
+
+/* Structure describing the image type `gif'. */
+
+static struct image_type gif_type =
+{
+ &Qgif,
+ gif_image_p,
+ gif_load,
+ x_clear_image,
+ NULL
+};
+
+/* Return non-zero if OBJECT is a valid GIF image specification. */
+
+static int
+gif_image_p (object)
+ Lisp_Object object;
+{
+ struct image_keyword fmt[GIF_LAST];
+ bcopy (gif_format, fmt, sizeof fmt);
+
+ if (!parse_image_spec (object, fmt, GIF_LAST, Qgif)
+ || (fmt[GIF_ASCENT].count
+ && XFASTINT (fmt[GIF_ASCENT].value) > 100))
+ return 0;
+
+ /* Must specify either the :data or :file keyword. */
+ return fmt[GIF_FILE].count + fmt[GIF_DATA].count == 1;
+}
+
+/* Reading a GIF image from memory
+ Based on the PNG memory stuff to a certain extent. */
+
+typedef struct
+{
+ unsigned char *bytes;
+ size_t len;
+ int index;
+}
+gif_memory_source;
+
+/* Make the current memory source available to gif_read_from_memory.
+ It's done this way because not all versions of libungif support
+ a UserData field in the GifFileType structure. */
+static gif_memory_source *current_gif_memory_src;
+
+static int
+gif_read_from_memory (file, buf, len)
+ GifFileType *file;
+ GifByteType *buf;
+ int len;
+{
+ gif_memory_source *src = current_gif_memory_src;
+
+ if (len > src->len - src->index)
+ return -1;
+
+ bcopy (src->bytes + src->index, buf, len);
+ src->index += len;
+ return len;
+}
+
+
+/* Load GIF image IMG for use on frame F. Value is non-zero if
+ successful. */
+
+static int
+gif_load (f, img)
+ struct frame *f;
+ struct image *img;
+{
+ Lisp_Object file, specified_file;
+ Lisp_Object specified_data;
+ int rc, width, height, x, y, i;
+ XImage *ximg;
+ ColorMapObject *gif_color_map;
+ unsigned long pixel_colors[256];
+ GifFileType *gif;
+ struct gcpro gcpro1;
+ Lisp_Object image;
+ int ino, image_left, image_top, image_width, image_height;
+ gif_memory_source memsrc;
+ unsigned char *raster;
+
+ specified_file = image_spec_value (img->spec, QCfile, NULL);
+ specified_data = image_spec_value (img->spec, QCdata, NULL);
+ file = Qnil;
+ GCPRO1 (file);
+
+ if (NILP (specified_data))
+ {
+ file = x_find_image_file (specified_file);
+ if (!STRINGP (file))
+ {
+ image_error ("Cannot find image file `%s'", specified_file, Qnil);
+ UNGCPRO;
+ return 0;
+ }
+
+ /* Open the GIF file. */
+ gif = DGifOpenFileName (XSTRING (file)->data);
+ if (gif == NULL)
+ {
+ image_error ("Cannot open `%s'", file, Qnil);
+ UNGCPRO;
+ return 0;
+ }
+ }
+ else
+ {
+ /* Read from memory! */
+ current_gif_memory_src = &memsrc;
+ memsrc.bytes = XSTRING (specified_data)->data;
+ memsrc.len = STRING_BYTES (XSTRING (specified_data));
+ memsrc.index = 0;
+
+ gif = DGifOpen(&memsrc, gif_read_from_memory);
+ if (!gif)
+ {
+ image_error ("Cannot open memory source `%s'", img->spec, Qnil);
+ UNGCPRO;
+ return 0;
+ }
+ }
+
+ /* Read entire contents. */
+ rc = DGifSlurp (gif);
+ if (rc == GIF_ERROR)
+ {
+ image_error ("Error reading `%s'", img->spec, Qnil);
+ DGifCloseFile (gif);
+ UNGCPRO;
+ return 0;
+ }
+
+ image = image_spec_value (img->spec, QCindex, NULL);
+ ino = INTEGERP (image) ? XFASTINT (image) : 0;
+ if (ino >= gif->ImageCount)
+ {
+ image_error ("Invalid image number `%s' in image `%s'",
+ image, img->spec);
+ DGifCloseFile (gif);
+ UNGCPRO;
+ return 0;
+ }
+
+ width = img->width = gif->SWidth;
+ height = img->height = gif->SHeight;
+
+ BLOCK_INPUT;
+
+ /* Create the X image and pixmap. */
+ if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap))
+ {
+ UNBLOCK_INPUT;
+ DGifCloseFile (gif);
+ UNGCPRO;
+ return 0;
+ }
+
+ /* Allocate colors. */
+ gif_color_map = gif->SavedImages[ino].ImageDesc.ColorMap;
+ if (!gif_color_map)
+ gif_color_map = gif->SColorMap;
+ init_color_table ();
+ bzero (pixel_colors, sizeof pixel_colors);
+
+ for (i = 0; i < gif_color_map->ColorCount; ++i)
+ {
+ int r = gif_color_map->Colors[i].Red << 8;
+ int g = gif_color_map->Colors[i].Green << 8;
+ int b = gif_color_map->Colors[i].Blue << 8;
+ pixel_colors[i] = lookup_rgb_color (f, r, g, b);
+ }
+
+ img->colors = colors_in_color_table (&img->ncolors);
+ free_color_table ();
+
+ /* Clear the part of the screen image that are not covered by
+ the image from the GIF file. Full animated GIF support
+ requires more than can be done here (see the gif89 spec,
+ disposal methods). Let's simply assume that the part
+ not covered by a sub-image is in the frame's background color. */
+ image_top = gif->SavedImages[ino].ImageDesc.Top;
+ image_left = gif->SavedImages[ino].ImageDesc.Left;
+ image_width = gif->SavedImages[ino].ImageDesc.Width;
+ image_height = gif->SavedImages[ino].ImageDesc.Height;
+
+ for (y = 0; y < image_top; ++y)
+ for (x = 0; x < width; ++x)
+ XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
+
+ for (y = image_top + image_height; y < height; ++y)
+ for (x = 0; x < width; ++x)
+ XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
+
+ for (y = image_top; y < image_top + image_height; ++y)
+ {
+ for (x = 0; x < image_left; ++x)
+ XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
+ for (x = image_left + image_width; x < width; ++x)
+ XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f));
+ }
+
+ /* Read the GIF image into the X image. We use a local variable
+ `raster' here because RasterBits below is a char *, and invites
+ problems with bytes >= 0x80. */
+ raster = (unsigned char *) gif->SavedImages[ino].RasterBits;
+
+ if (gif->SavedImages[ino].ImageDesc.Interlace)
+ {
+ static int interlace_start[] = {0, 4, 2, 1};
+ static int interlace_increment[] = {8, 8, 4, 2};
+ int pass, inc;
+ int row = interlace_start[0];
+
+ pass = 0;
+
+ for (y = 0; y < image_height; y++)
+ {
+ if (row >= image_height)
+ {
+ row = interlace_start[++pass];
+ while (row >= image_height)
+ row = interlace_start[++pass];
+ }
+
+ for (x = 0; x < image_width; x++)
+ {
+ int i = raster[(y * image_width) + x];
+ XPutPixel (ximg, x + image_left, row + image_top,
+ pixel_colors[i]);
+ }
+
+ row += interlace_increment[pass];
+ }
+ }
+ else
+ {
+ for (y = 0; y < image_height; ++y)
+ for (x = 0; x < image_width; ++x)
+ {
+ int i = raster[y* image_width + x];
+ XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]);
+ }
+ }
+
+ DGifCloseFile (gif);
+
+ /* Put the image into the pixmap, then free the X image and its buffer. */
+ x_put_x_image (f, ximg, img->pixmap, width, height);
+ x_destroy_x_image (ximg);
+ UNBLOCK_INPUT;
+
+ UNGCPRO;
+ return 1;
+}
+
+#endif /* HAVE_GIF != 0 */
+
+
+\f
+/***********************************************************************
+ Ghostscript
+ ***********************************************************************/
+
+#ifdef HAVE_GHOSTSCRIPT
+static int gs_image_p P_ ((Lisp_Object object));
+static int gs_load P_ ((struct frame *f, struct image *img));
+static void gs_clear_image P_ ((struct frame *f, struct image *img));
+
+/* The symbol `postscript' identifying images of this type. */
+
+Lisp_Object Qpostscript;
+
+/* Keyword symbols. */
+
+Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
+
+/* Indices of image specification fields in gs_format, below. */
+
+enum gs_keyword_index
+{
+ GS_TYPE,
+ GS_PT_WIDTH,
+ GS_PT_HEIGHT,
+ GS_FILE,
+ GS_LOADER,
+ GS_BOUNDING_BOX,
+ GS_ASCENT,
+ GS_MARGIN,
+ GS_RELIEF,
+ GS_ALGORITHM,
+ GS_HEURISTIC_MASK,
+ GS_LAST
+};
+
+/* Vector of image_keyword structures describing the format
+ of valid user-defined image specifications. */
+
+static struct image_keyword gs_format[GS_LAST] =
+{
+ {":type", IMAGE_SYMBOL_VALUE, 1},
+ {":pt-width", IMAGE_POSITIVE_INTEGER_VALUE, 1},
+ {":pt-height", IMAGE_POSITIVE_INTEGER_VALUE, 1},
+ {":file", IMAGE_STRING_VALUE, 1},
+ {":loader", IMAGE_FUNCTION_VALUE, 0},
+ {":bounding-box", IMAGE_DONT_CHECK_VALUE_TYPE, 1},
+ {":ascent", IMAGE_NON_NEGATIVE_INTEGER_VALUE, 0},
+ {":margin", IMAGE_POSITIVE_INTEGER_VALUE_OR_PAIR, 0},
+ {":relief", IMAGE_INTEGER_VALUE, 0},
+ {":conversion", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
+ {":heuristic-mask", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
+};
+
+/* Structure describing the image type `ghostscript'. */
+
+static struct image_type gs_type =
+{
+ &Qpostscript,
+ gs_image_p,
+ gs_load,
+ gs_clear_image,
+ NULL
+};
+
+
+/* Free X resources of Ghostscript image IMG which is used on frame F. */
+
+static void
+gs_clear_image (f, img)
+ struct frame *f;
+ struct image *img;
+{
+ /* IMG->data.ptr_val may contain a recorded colormap. */
+ xfree (img->data.ptr_val);
+ x_clear_image (f, img);
+}
+
+
+/* Return non-zero if OBJECT is a valid Ghostscript image
+ specification. */
+
+static int
+gs_image_p (object)
+ Lisp_Object object;
+{
+ struct image_keyword fmt[GS_LAST];
+ Lisp_Object tem;
+ int i;
+
+ bcopy (gs_format, fmt, sizeof fmt);
+
+ if (!parse_image_spec (object, fmt, GS_LAST, Qpostscript)
+ || (fmt[GS_ASCENT].count
+ && XFASTINT (fmt[GS_ASCENT].value) > 100))
+ return 0;
+
+ /* Bounding box must be a list or vector containing 4 integers. */
+ tem = fmt[GS_BOUNDING_BOX].value;
+ if (CONSP (tem))
+ {
+ for (i = 0; i < 4; ++i, tem = XCDR (tem))
+ if (!CONSP (tem) || !INTEGERP (XCAR (tem)))
+ return 0;
+ if (!NILP (tem))
+ return 0;
+ }
+ else if (VECTORP (tem))
+ {
+ if (XVECTOR (tem)->size != 4)
+ return 0;
+ for (i = 0; i < 4; ++i)
+ if (!INTEGERP (XVECTOR (tem)->contents[i]))
+ return 0;
+ }
+ else
+ return 0;
+
+ return 1;
+}
+
+
+/* Load Ghostscript image IMG for use on frame F. Value is non-zero
+ if successful. */
+
+static int
+gs_load (f, img)
+ struct frame *f;
+ struct image *img;
+{
+ char buffer[100];
+ Lisp_Object window_and_pixmap_id = Qnil, loader, pt_height, pt_width;
+ struct gcpro gcpro1, gcpro2;
+ Lisp_Object frame;
+ double in_width, in_height;
+ Lisp_Object pixel_colors = Qnil;
+
+ /* Compute pixel size of pixmap needed from the given size in the
+ image specification. Sizes in the specification are in pt. 1 pt
+ = 1/72 in, xdpi and ydpi are stored in the frame's X display
+ info. */
+ pt_width = image_spec_value (img->spec, QCpt_width, NULL);
+ in_width = XFASTINT (pt_width) / 72.0;
+ img->width = in_width * FRAME_W32_DISPLAY_INFO (f)->resx;
+ pt_height = image_spec_value (img->spec, QCpt_height, NULL);
+ in_height = XFASTINT (pt_height) / 72.0;
+ img->height = in_height * FRAME_W32_DISPLAY_INFO (f)->resy;
+
+ /* Create the pixmap. */
+ BLOCK_INPUT;
+ xassert (img->pixmap == 0);
+ img->pixmap = XCreatePixmap (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
+ img->width, img->height,
+ DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
+ UNBLOCK_INPUT;
+
+ if (!img->pixmap)
+ {
+ image_error ("Unable to create pixmap for `%s'", img->spec, Qnil);
+ return 0;
+ }
+
+ /* Call the loader to fill the pixmap. It returns a process object
+ if successful. We do not record_unwind_protect here because
+ other places in redisplay like calling window scroll functions
+ don't either. Let the Lisp loader use `unwind-protect' instead. */
+ GCPRO2 (window_and_pixmap_id, pixel_colors);
+
+ sprintf (buffer, "%lu %lu",
+ (unsigned long) FRAME_W32_WINDOW (f),
+ (unsigned long) img->pixmap);
+ window_and_pixmap_id = build_string (buffer);
+
+ sprintf (buffer, "%lu %lu",
+ FRAME_FOREGROUND_PIXEL (f),
+ FRAME_BACKGROUND_PIXEL (f));
+ pixel_colors = build_string (buffer);
+
+ XSETFRAME (frame, f);
+ loader = image_spec_value (img->spec, QCloader, NULL);
+ if (NILP (loader))
+ loader = intern ("gs-load-image");
+
+ img->data.lisp_val = call6 (loader, frame, img->spec,
+ make_number (img->width),
+ make_number (img->height),
+ window_and_pixmap_id,
+ pixel_colors);
+ UNGCPRO;
+ return PROCESSP (img->data.lisp_val);
+}
+
+
+/* Kill the Ghostscript process that was started to fill PIXMAP on
+ frame F. Called from XTread_socket when receiving an event
+ telling Emacs that Ghostscript has finished drawing. */
+
+void
+x_kill_gs_process (pixmap, f)
+ Pixmap pixmap;
+ struct frame *f;
+{
+ struct image_cache *c = FRAME_X_IMAGE_CACHE (f);
+ int class, i;
+ struct image *img;
+
+ /* Find the image containing PIXMAP. */
+ for (i = 0; i < c->used; ++i)
+ if (c->images[i]->pixmap == pixmap)
+ break;
+
+ /* Kill the GS process. We should have found PIXMAP in the image
+ cache and its image should contain a process object. */
+ xassert (i < c->used);
+ img = c->images[i];
+ xassert (PROCESSP (img->data.lisp_val));
+ Fkill_process (img->data.lisp_val, Qnil);
+ img->data.lisp_val = Qnil;
+
+ /* On displays with a mutable colormap, figure out the colors
+ allocated for the image by looking at the pixels of an XImage for
+ img->pixmap. */
+ class = FRAME_W32_DISPLAY_INFO (f)->visual->class;
+ if (class != StaticColor && class != StaticGray && class != TrueColor)
+ {
+ XImage *ximg;
+
+ BLOCK_INPUT;
+
+ /* Try to get an XImage for img->pixmep. */
+ ximg = XGetImage (FRAME_W32_DISPLAY (f), img->pixmap,
+ 0, 0, img->width, img->height, ~0, ZPixmap);
+ if (ximg)
+ {
+ int x, y;
+
+ /* Initialize the color table. */
+ init_color_table ();
+
+ /* For each pixel of the image, look its color up in the
+ color table. After having done so, the color table will
+ contain an entry for each color used by the image. */
+ for (y = 0; y < img->height; ++y)
+ for (x = 0; x < img->width; ++x)
+ {
+ unsigned long pixel = XGetPixel (ximg, x, y);
+ lookup_pixel_color (f, pixel);
+ }
+
+ /* Record colors in the image. Free color table and XImage. */
+ img->colors = colors_in_color_table (&img->ncolors);
+ free_color_table ();
+ XDestroyImage (ximg);
+
+#if 0 /* This doesn't seem to be the case. If we free the colors
+ here, we get a BadAccess later in x_clear_image when
+ freeing the colors. */
+ /* We have allocated colors once, but Ghostscript has also
+ allocated colors on behalf of us. So, to get the
+ reference counts right, free them once. */
+ if (img->ncolors)
+ {
+ Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
+ XFreeColors (FRAME_W32_DISPLAY (f), cmap,
+ img->colors, img->ncolors, 0);
+ }
+#endif
+ }
+ else
+ image_error ("Cannot get X image of `%s'; colors will not be freed",
+ img->spec, Qnil);
+
+ UNBLOCK_INPUT;
+ }
+}
+
+#endif /* HAVE_GHOSTSCRIPT */
+
+\f
+/***********************************************************************
+ Window properties
+ ***********************************************************************/
+
+DEFUN ("x-change-window-property", Fx_change_window_property,
+ Sx_change_window_property, 2, 3, 0,
+ doc: /* Change window property PROP to VALUE on the X window of FRAME.
+PROP and VALUE must be strings. FRAME nil or omitted means use the
+selected frame. Value is VALUE. */)
+ (prop, value, frame)
+ Lisp_Object frame, prop, value;
+{
+#if 0 /* MAC_TODO : port window properties to Mac */
+ struct frame *f = check_x_frame (frame);
+ Atom prop_atom;
+
+ CHECK_STRING (prop);
+ CHECK_STRING (value);
+
+ BLOCK_INPUT;
+ prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), XSTRING (prop)->data, False);
+ XChangeProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
+ prop_atom, XA_STRING, 8, PropModeReplace,
+ XSTRING (value)->data, XSTRING (value)->size);
+
+ /* Make sure the property is set when we return. */
+ XFlush (FRAME_W32_DISPLAY (f));
+ UNBLOCK_INPUT;
+
+#endif /* MAC_TODO */
+
+ return value;
+}
+
+
+DEFUN ("x-delete-window-property", Fx_delete_window_property,
+ Sx_delete_window_property, 1, 2, 0,
+ doc: /* Remove window property PROP from X window of FRAME.
+FRAME nil or omitted means use the selected frame. Value is PROP. */)
+ (prop, frame)
+ Lisp_Object prop, frame;
+{
+#if 0 /* MAC_TODO : port window properties to Mac */
+
+ struct frame *f = check_x_frame (frame);
+ Atom prop_atom;
+
+ CHECK_STRING (prop);
+ BLOCK_INPUT;
+ prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), XSTRING (prop)->data, False);
+ XDeleteProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f), prop_atom);
+
+ /* Make sure the property is removed when we return. */
+ XFlush (FRAME_W32_DISPLAY (f));
+ UNBLOCK_INPUT;
+#endif /* MAC_TODO */
+
+ return prop;
+}
+
+
+DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
+ 1, 2, 0,
+ doc: /* Value is the value of window property PROP on FRAME.
+If FRAME is nil or omitted, use the selected frame. Value is nil
+if FRAME hasn't a property with name PROP or if PROP has no string
+value. */)
+ (prop, frame)
+ Lisp_Object prop, frame;
+{
+#if 0 /* MAC_TODO : port window properties to Mac */
+
+ struct frame *f = check_x_frame (frame);
+ Atom prop_atom;
+ int rc;
+ Lisp_Object prop_value = Qnil;
+ char *tmp_data = NULL;
+ Atom actual_type;
+ int actual_format;
+ unsigned long actual_size, bytes_remaining;
+
+ CHECK_STRING (prop);
+ BLOCK_INPUT;
+ prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), XSTRING (prop)->data, False);
+ rc = XGetWindowProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
+ prop_atom, 0, 0, False, XA_STRING,
+ &actual_type, &actual_format, &actual_size,
+ &bytes_remaining, (unsigned char **) &tmp_data);
+ if (rc == Success)
+ {
+ int size = bytes_remaining;
+
+ XFree (tmp_data);
+ tmp_data = NULL;
+
+ rc = XGetWindowProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
+ prop_atom, 0, bytes_remaining,
+ False, XA_STRING,
+ &actual_type, &actual_format,
+ &actual_size, &bytes_remaining,
+ (unsigned char **) &tmp_data);
+ if (rc == Success)
+ prop_value = make_string (tmp_data, size);
+
+ XFree (tmp_data);
+ }
+
+ UNBLOCK_INPUT;
+
+ return prop_value;
+
+#endif /* MAC_TODO */
+ return Qnil;
+}
+
+
+\f
+/***********************************************************************
+ Hourglass cursor
+ ***********************************************************************/
+
+/* If non-null, an asynchronous timer that, when it expires, displays
+ an hourglass cursor on all frames. */
+
+static struct atimer *hourglass_atimer;
+
+/* Non-zero means an hourglass cursor is currently shown. */
+
+static int hourglass_shown_p;
+
+/* Number of seconds to wait before displaying an hourglass cursor. */
+
+static Lisp_Object Vhourglass_delay;
+
+/* Default number of seconds to wait before displaying an hourglass
+ cursor. */
+
+#define DEFAULT_HOURGLASS_DELAY 1
+
+/* Function prototypes. */
+
+static void show_hourglass P_ ((struct atimer *));
+static void hide_hourglass P_ ((void));
+
+
+/* Cancel a currently active hourglass timer, and start a new one. */
+
+void
+start_hourglass ()
+{
+#if 0 /* MAC_TODO: cursor shape changes. */
+ EMACS_TIME delay;
+ int secs, usecs = 0;
+
+ cancel_hourglass ();
+
+ if (INTEGERP (Vhourglass_delay)
+ && XINT (Vhourglass_delay) > 0)
+ secs = XFASTINT (Vhourglass_delay);
+ else if (FLOATP (Vhourglass_delay)
+ && XFLOAT_DATA (Vhourglass_delay) > 0)
+ {
+ Lisp_Object tem;
+ tem = Ftruncate (Vhourglass_delay, Qnil);
+ secs = XFASTINT (tem);
+ usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
+ }
+ else
+ secs = DEFAULT_HOURGLASS_DELAY;
+
+ EMACS_SET_SECS_USECS (delay, secs, usecs);
+ hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
+ show_hourglass, NULL);
+#endif /* MAC_TODO */
+}
+
+
+/* Cancel the hourglass cursor timer if active, hide an hourglass
+ cursor if shown. */
+
+void
+cancel_hourglass ()
+{
+ if (hourglass_atimer)
+ {
+ cancel_atimer (hourglass_atimer);
+ hourglass_atimer = NULL;
+ }
+
+ if (hourglass_shown_p)
+ hide_hourglass ();
+}
+
+
+/* Timer function of hourglass_atimer. TIMER is equal to
+ hourglass_atimer.
+
+ Display an hourglass cursor on all frames by mapping the frames'
+ hourglass_window. Set the hourglass_p flag in the frames'
+ output_data.x structure to indicate that an hourglass cursor is
+ shown on the frames. */
+
+static void
+show_hourglass (timer)
+ struct atimer *timer;
+{
+#if 0 /* MAC_TODO: cursor shape changes. */
+ /* The timer implementation will cancel this timer automatically
+ after this function has run. Set hourglass_atimer to null
+ so that we know the timer doesn't have to be canceled. */
+ hourglass_atimer = NULL;
+
+ if (!hourglass_shown_p)
+ {
+ Lisp_Object rest, frame;
+
+ BLOCK_INPUT;
+
+ FOR_EACH_FRAME (rest, frame)
+ if (FRAME_W32_P (XFRAME (frame)))
+ {
+ struct frame *f = XFRAME (frame);
+
+ f->output_data.w32->hourglass_p = 1;
+
+ if (!f->output_data.w32->hourglass_window)
+ {
+ unsigned long mask = CWCursor;
+ XSetWindowAttributes attrs;
+
+ attrs.cursor = f->output_data.w32->hourglass_cursor;
+
+ f->output_data.w32->hourglass_window
+ = XCreateWindow (FRAME_X_DISPLAY (f),
+ FRAME_OUTER_WINDOW (f),
+ 0, 0, 32000, 32000, 0, 0,
+ InputOnly,
+ CopyFromParent,
+ mask, &attrs);
+ }
+
+ XMapRaised (FRAME_X_DISPLAY (f),
+ f->output_data.w32->hourglass_window);
+ XFlush (FRAME_X_DISPLAY (f));
+ }
+
+ hourglass_shown_p = 1;
+ UNBLOCK_INPUT;
+ }
+#endif /* MAC_TODO */
+}
+
+
+/* Hide the hourglass cursor on all frames, if it is currently shown. */
+
+static void
+hide_hourglass ()
+{
+#if 0 /* MAC_TODO: cursor shape changes. */
+ if (hourglass_shown_p)
+ {
+ Lisp_Object rest, frame;
+
+ BLOCK_INPUT;
+ FOR_EACH_FRAME (rest, frame)
+ {
+ struct frame *f = XFRAME (frame);
+
+ if (FRAME_W32_P (f)
+ /* Watch out for newly created frames. */
+ && f->output_data.x->hourglass_window)
+ {
+ XUnmapWindow (FRAME_X_DISPLAY (f),
+ f->output_data.x->hourglass_window);
+ /* Sync here because XTread_socket looks at the
+ hourglass_p flag that is reset to zero below. */
+ XSync (FRAME_X_DISPLAY (f), False);
+ f->output_data.x->hourglass_p = 0;
+ }
+ }
+
+ hourglass_shown_p = 0;
+ UNBLOCK_INPUT;
+ }
+#endif /* MAC_TODO */
+}
+
+
+\f
+/***********************************************************************
+ Tool tips
+ ***********************************************************************/
+
+static Lisp_Object x_create_tip_frame P_ ((struct mac_display_info *,
+ Lisp_Object));
+
+/* The frame of a currently visible tooltip, or null. */
+
+Lisp_Object tip_frame;
+
+/* If non-nil, a timer started that hides the last tooltip when it
+ fires. */
+
+Lisp_Object tip_timer;
+Window tip_window;
+
+/* If non-nil, a vector of 3 elements containing the last args
+ with which x-show-tip was called. See there. */
+
+Lisp_Object last_show_tip_args;
+
+/* Create a frame for a tooltip on the display described by DPYINFO.
+ PARMS is a list of frame parameters. Value is the frame. */
+
+static Lisp_Object
+x_create_tip_frame (dpyinfo, parms)
+ struct mac_display_info *dpyinfo;
+ Lisp_Object parms;
+{
+#if 0 /* MAC_TODO : Mac version */
+ struct frame *f;
+ Lisp_Object frame, tem;
+ Lisp_Object name;
+ long window_prompting = 0;
+ int width, height;
+ int count = specpdl_ptr - specpdl;
+ struct gcpro gcpro1, gcpro2, gcpro3;
+ struct kboard *kb;
+
+ check_x ();
+
+ /* Use this general default value to start with until we know if
+ this frame has a specified name. */
+ Vx_resource_name = Vinvocation_name;
+
+#ifdef MULTI_KBOARD
+ kb = dpyinfo->kboard;
+#else
+ kb = &the_only_kboard;
+#endif
+
+ /* Get the name of the frame to use for resource lookup. */
+ name = w32_get_arg (parms, Qname, "name", "Name", RES_TYPE_STRING);
+ if (!STRINGP (name)
+ && !EQ (name, Qunbound)
+ && !NILP (name))
+ error ("Invalid frame name--not a string or nil");
+ Vx_resource_name = name;
+
+ frame = Qnil;
+ GCPRO3 (parms, name, frame);
+ tip_frame = f = make_frame (1);
+ XSETFRAME (frame, f);
+ FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
+
+ f->output_method = output_w32;
+ f->output_data.w32 =
+ (struct w32_output *) xmalloc (sizeof (struct w32_output));
+ bzero (f->output_data.w32, sizeof (struct w32_output));
+#if 0
+ f->output_data.w32->icon_bitmap = -1;
+#endif
+ f->output_data.w32->fontset = -1;
+ f->icon_name = Qnil;
+
+#ifdef MULTI_KBOARD
+ FRAME_KBOARD (f) = kb;
+#endif
+ f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
+ f->output_data.w32->explicit_parent = 0;
+
+ /* Set the name; the functions to which we pass f expect the name to
+ be set. */
+ if (EQ (name, Qunbound) || NILP (name))
+ {
+ f->name = build_string (dpyinfo->x_id_name);
+ f->explicit_name = 0;
+ }
+ else
+ {
+ f->name = name;
+ f->explicit_name = 1;
+ /* use the frame's title when getting resources for this frame. */
+ specbind (Qx_resource_name, name);
+ }
+
+ /* Extract the window parameters from the supplied values
+ that are needed to determine window geometry. */
+ {
+ Lisp_Object font;
+
+ font = w32_get_arg (parms, Qfont, "font", "Font", RES_TYPE_STRING);
+
+ BLOCK_INPUT;
+ /* First, try whatever font the caller has specified. */
+ if (STRINGP (font))
+ {
+ tem = Fquery_fontset (font, Qnil);
+ if (STRINGP (tem))
+ font = x_new_fontset (f, XSTRING (tem)->data);
+ else
+ font = x_new_font (f, XSTRING (font)->data);
+ }
+
+ /* Try out a font which we hope has bold and italic variations. */
+ if (!STRINGP (font))
+ font = x_new_font (f, "-adobe-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-1");
+ if (!STRINGP (font))
+ font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
+ if (! STRINGP (font))
+ font = x_new_font (f, "-*-*-medium-r-normal-*-*-140-*-*-c-*-iso8859-1");
+ if (! STRINGP (font))
+ /* This was formerly the first thing tried, but it finds too many fonts
+ and takes too long. */
+ font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
+ /* If those didn't work, look for something which will at least work. */
+ if (! STRINGP (font))
+ font = x_new_font (f, "-*-fixed-*-*-*-*-*-140-*-*-c-*-iso8859-1");
+ UNBLOCK_INPUT;
+ if (! STRINGP (font))
+ font = build_string ("fixed");
+
+ x_default_parameter (f, parms, Qfont, font,
+ "font", "Font", RES_TYPE_STRING);
+ }
+
+ x_default_parameter (f, parms, Qborder_width, make_number (2),
+ "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
+
+ /* This defaults to 2 in order to match xterm. We recognize either
+ internalBorderWidth or internalBorder (which is what xterm calls
+ it). */
+ if (NILP (Fassq (Qinternal_border_width, parms)))
+ {
+ Lisp_Object value;
+
+ value = w32_get_arg (parms, Qinternal_border_width,
+ "internalBorder", "internalBorder", RES_TYPE_NUMBER);
+ if (! EQ (value, Qunbound))
+ parms = Fcons (Fcons (Qinternal_border_width, value),
+ parms);
+ }
+
+ x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
+ "internalBorderWidth", "internalBorderWidth",
+ RES_TYPE_NUMBER);
+
+ /* Also do the stuff which must be set before the window exists. */
+ x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
+ "foreground", "Foreground", RES_TYPE_STRING);
+ x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
+ "background", "Background", RES_TYPE_STRING);
+ x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
+ "pointerColor", "Foreground", RES_TYPE_STRING);
+ x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
+ "cursorColor", "Foreground", RES_TYPE_STRING);
+ x_default_parameter (f, parms, Qborder_color, build_string ("black"),
+ "borderColor", "BorderColor", RES_TYPE_STRING);
+
+ /* Init faces before x_default_parameter is called for scroll-bar
+ parameters because that function calls x_set_scroll_bar_width,
+ which calls change_frame_size, which calls Fset_window_buffer,
+ which runs hooks, which call Fvertical_motion. At the end, we
+ end up in init_iterator with a null face cache, which should not
+ happen. */
+ init_frame_faces (f);
+
+ f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
+ window_prompting = x_figure_window_size (f, parms);
+
+ if (window_prompting & XNegative)
+ {
+ if (window_prompting & YNegative)
+ f->output_data.w32->win_gravity = SouthEastGravity;
+ else
+ f->output_data.w32->win_gravity = NorthEastGravity;
+ }
+ else
+ {
+ if (window_prompting & YNegative)
+ f->output_data.w32->win_gravity = SouthWestGravity;
+ else
+ f->output_data.w32->win_gravity = NorthWestGravity;
+ }
+
+ f->output_data.w32->size_hint_flags = window_prompting;
+ {
+ XSetWindowAttributes attrs;
+ unsigned long mask;
+
+ BLOCK_INPUT;
+ mask = CWBackPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask;
+ /* Window managers looks at the override-redirect flag to
+ determine whether or net to give windows a decoration (Xlib
+ 3.2.8). */
+ attrs.override_redirect = True;
+ attrs.save_under = True;
+ attrs.background_pixel = FRAME_BACKGROUND_PIXEL (f);
+ /* Arrange for getting MapNotify and UnmapNotify events. */
+ attrs.event_mask = StructureNotifyMask;
+ tip_window
+ = FRAME_W32_WINDOW (f)
+ = XCreateWindow (FRAME_W32_DISPLAY (f),
+ FRAME_W32_DISPLAY_INFO (f)->root_window,
+ /* x, y, width, height */
+ 0, 0, 1, 1,
+ /* Border. */
+ 1,
+ CopyFromParent, InputOutput, CopyFromParent,
+ mask, &attrs);
+ UNBLOCK_INPUT;
+ }
+
+ x_make_gc (f);
+
+ x_default_parameter (f, parms, Qauto_raise, Qnil,
+ "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
+ x_default_parameter (f, parms, Qauto_lower, Qnil,
+ "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
+ x_default_parameter (f, parms, Qcursor_type, Qbox,
+ "cursorType", "CursorType", RES_TYPE_SYMBOL);
+
+ /* Dimensions, especially f->height, must be done via change_frame_size.
+ Change will not be effected unless different from the current
+ f->height. */
+ width = f->width;
+ height = f->height;
+ f->height = 0;
+ SET_FRAME_WIDTH (f, 0);
+ change_frame_size (f, height, width, 1, 0, 0);
+
+ f->no_split = 1;
+
+ UNGCPRO;
+
+ /* It is now ok to make the frame official even if we get an error
+ below. And the frame needs to be on Vframe_list or making it
+ visible won't work. */
+ Vframe_list = Fcons (frame, Vframe_list);
+
+ /* Now that the frame is official, it counts as a reference to
+ its display. */
+ FRAME_W32_DISPLAY_INFO (f)->reference_count++;
+
+ return unbind_to (count, frame);
+#endif /* MAC_TODO */
+ return Qnil;
+}
+
+
+DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
+ doc : /* Show STRING in a "tooltip" window on frame FRAME.
+A tooltip window is a small window displaying a string.
+
+FRAME nil or omitted means use the selected frame.
+
+PARMS is an optional list of frame parameters which can be used to
+change the tooltip's appearance.
+
+Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
+means use the default timeout of 5 seconds.
+
+If the list of frame parameters PARAMS contains a `left' parameters,
+the tooltip is displayed at that x-position. Otherwise it is
+displayed at the mouse position, with offset DX added (default is 5 if
+DX isn't specified). Likewise for the y-position; if a `top' frame
+parameter is specified, it determines the y-position of the tooltip
+window, otherwise it is displayed at the mouse position, with offset
+DY added (default is 10). */)
+ (string, frame, parms, timeout, dx, dy)
+ Lisp_Object string, frame, parms, timeout, dx, dy;
+{
+ struct frame *f;
+ struct window *w;
+ Window root, child;
+ Lisp_Object buffer, top, left;
+ struct buffer *old_buffer;
+ struct text_pos pos;
+ int i, width, height;
+ int root_x, root_y, win_x, win_y;
+ unsigned pmask;
+ struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+ int old_windows_or_buffers_changed = windows_or_buffers_changed;
+ int count = specpdl_ptr - specpdl;
+
+ specbind (Qinhibit_redisplay, Qt);
+
+ GCPRO4 (string, parms, frame, timeout);
+
+ CHECK_STRING (string);
+ f = check_x_frame (frame);
+ if (NILP (timeout))
+ timeout = make_number (5);
+ else
+ CHECK_NATNUM (timeout);
+
+ if (NILP (dx))
+ dx = make_number (5);
+ else
+ CHECK_NUMBER (dx);
+
+ if (NILP (dy))
+ dy = make_number (-10);
+ else
+ CHECK_NUMBER (dy);
+
+ if (NILP (last_show_tip_args))
+ last_show_tip_args = Fmake_vector (make_number (3), Qnil);
+
+ if (!NILP (tip_frame))
+ {
+ Lisp_Object last_string = AREF (last_show_tip_args, 0);
+ Lisp_Object last_frame = AREF (last_show_tip_args, 1);
+ Lisp_Object last_parms = AREF (last_show_tip_args, 2);
+
+ if (EQ (frame, last_frame)
+ && !NILP (Fequal (last_string, string))
+ && !NILP (Fequal (last_parms, parms)))
+ {
+ struct frame *f = XFRAME (tip_frame);
+
+ /* Only DX and DY have changed. */
+ if (!NILP (tip_timer))
+ {
+ Lisp_Object timer = tip_timer;
+ tip_timer = Qnil;
+ call1 (Qcancel_timer, timer);
+ }
+
+#if 0 /* MAC_TODO : Mac specifics */
+ BLOCK_INPUT;
+ compute_tip_xy (f, parms, dx, dy, &root_x, &root_y);
+ XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ root_x, root_y - PIXEL_HEIGHT (f));
+ UNBLOCK_INPUT;
+#endif /* MAC_TODO */
+ goto start_timer;
+ }
+ }
+
+ /* Hide a previous tip, if any. */
+ Fx_hide_tip ();
+
+ ASET (last_show_tip_args, 0, string);
+ ASET (last_show_tip_args, 1, frame);
+ ASET (last_show_tip_args, 2, parms);
+
+ /* Add default values to frame parameters. */
+ if (NILP (Fassq (Qname, parms)))
+ parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
+ if (NILP (Fassq (Qinternal_border_width, parms)))
+ parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
+ if (NILP (Fassq (Qborder_width, parms)))
+ parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
+ if (NILP (Fassq (Qborder_color, parms)))
+ parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
+ if (NILP (Fassq (Qbackground_color, parms)))
+ parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
+ parms);
+
+ /* Create a frame for the tooltip, and record it in the global
+ variable tip_frame. */
+ frame = x_create_tip_frame (FRAME_MAC_DISPLAY_INFO (f), parms);
+ f = XFRAME (frame);
+
+ /* Set up the frame's root window. Currently we use a size of 80
+ columns x 40 lines. If someone wants to show a larger tip, he
+ will loose. I don't think this is a realistic case. */
+ w = XWINDOW (FRAME_ROOT_WINDOW (f));
+ w->left = w->top = make_number (0);
+ w->width = make_number (80);
+ w->height = make_number (40);
+ adjust_glyphs (f);
+ w->pseudo_window_p = 1;
+
+ /* Display the tooltip text in a temporary buffer. */
+ buffer = Fget_buffer_create (build_string (" *tip*"));
+ Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer);
+ old_buffer = current_buffer;
+ set_buffer_internal_1 (XBUFFER (buffer));
+ Ferase_buffer ();
+ Finsert (1, &string);
+ clear_glyph_matrix (w->desired_matrix);
+ clear_glyph_matrix (w->current_matrix);
+ SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
+ try_window (FRAME_ROOT_WINDOW (f), pos);
+
+ /* Compute width and height of the tooltip. */
+ width = height = 0;
+ for (i = 0; i < w->desired_matrix->nrows; ++i)
+ {
+ struct glyph_row *row = &w->desired_matrix->rows[i];
+ struct glyph *last;
+ int row_width;
+
+ /* Stop at the first empty row at the end. */
+ if (!row->enabled_p || !row->displays_text_p)
+ break;
+
+ /* Let the row go over the full width of the frame. */
+ row->full_width_p = 1;
+
+ /* There's a glyph at the end of rows that is use to place
+ the cursor there. Don't include the width of this glyph. */
+ if (row->used[TEXT_AREA])
+ {
+ last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
+ row_width = row->pixel_width - last->pixel_width;
+ }
+ else
+ row_width = row->pixel_width;
+
+ height += row->height;
+ width = max (width, row_width);
+ }
+
+ /* Add the frame's internal border to the width and height the X
+ window should have. */
+ height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
+ width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
+
+ /* Move the tooltip window where the mouse pointer is. Resize and
+ show it. */
+#if 0 /* TODO : Mac specifics */
+ compute_tip_xy (f, parms, dx, dy, &root_x, &root_y);
+
+ BLOCK_INPUT;
+ XQueryPointer (FRAME_W32_DISPLAY (f), FRAME_W32_DISPLAY_INFO (f)->root_window,
+ &root, &child, &root_x, &root_y, &win_x, &win_y, &pmask);
+ XMoveResizeWindow (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
+ root_x + 5, root_y - height - 5, width, height);
+ XMapRaised (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f));
+ UNBLOCK_INPUT;
+#endif /* MAC_TODO */
+
+ /* Draw into the window. */
+ w->must_be_updated_p = 1;
+ update_single_window (w, 1);
+
+ /* Restore original current buffer. */
+ set_buffer_internal_1 (old_buffer);
+ windows_or_buffers_changed = old_windows_or_buffers_changed;
+
+ start_timer:
+ /* Let the tip disappear after timeout seconds. */
+ tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
+ intern ("x-hide-tip"));
+
+ UNGCPRO;
+ return unbind_to (count, Qnil);
+}
+
+
+DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
+ doc: /* Hide the current tooltip window, if there is any.
+Value is t is tooltip was open, nil otherwise. */)
+ ()
+{
+ int count;
+ Lisp_Object deleted, frame, timer;
+ struct gcpro gcpro1, gcpro2;
+
+ /* Return quickly if nothing to do. */
+ if (NILP (tip_timer) && NILP (tip_frame))
+ return Qnil;
+
+ frame = tip_frame;
+ timer = tip_timer;
+ GCPRO2 (frame, timer);
+ tip_frame = tip_timer = deleted = Qnil;
+
+ count = BINDING_STACK_SIZE ();
+ specbind (Qinhibit_redisplay, Qt);
+ specbind (Qinhibit_quit, Qt);
+
+ if (!NILP (timer))
+ call1 (Qcancel_timer, timer);
+
+ if (FRAMEP (frame))
+ {
+ Fdelete_frame (frame, Qnil);
+ deleted = Qt;
+ }
+
+ UNGCPRO;
+ return unbind_to (count, deleted);
+}
+
+
+\f
+/***********************************************************************
+ File selection dialog
+ ***********************************************************************/
+
+#if 0 /* MAC_TODO: can standard file dialog */
+extern Lisp_Object Qfile_name_history;
+
+DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
+ doc: /* Read file name, prompting with PROMPT in directory DIR.
+Use a file selection dialog.
+Select DEFAULT-FILENAME in the dialog's file selection box, if
+specified. Don't let the user enter a file name in the file
+selection dialog's entry field, if MUSTMATCH is non-nil. */)
+ (prompt, dir, default_filename, mustmatch)
+ Lisp_Object prompt, dir, default_filename, mustmatch;
+{
+ struct frame *f = SELECTED_FRAME ();
+ Lisp_Object file = Qnil;
+ int count = specpdl_ptr - specpdl;
+ struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
+ char filename[MAX_PATH + 1];
+ char init_dir[MAX_PATH + 1];
+ int use_dialog_p = 1;
+
+ GCPRO5 (prompt, dir, default_filename, mustmatch, file);
+ CHECK_STRING (prompt);
+ CHECK_STRING (dir);
+
+ /* Create the dialog with PROMPT as title, using DIR as initial
+ directory and using "*" as pattern. */
+ dir = Fexpand_file_name (dir, Qnil);
+ strncpy (init_dir, XSTRING (dir)->data, MAX_PATH);
+ init_dir[MAX_PATH] = '\0';
+ unixtodos_filename (init_dir);
+
+ if (STRINGP (default_filename))
+ {
+ char *file_name_only;
+ char *full_path_name = XSTRING (default_filename)->data;
+
+ unixtodos_filename (full_path_name);
+
+ file_name_only = strrchr (full_path_name, '\\');
+ if (!file_name_only)
+ file_name_only = full_path_name;
+ else
+ {
+ file_name_only++;
+
+ /* If default_file_name is a directory, don't use the open
+ file dialog, as it does not support selecting
+ directories. */
+ if (!(*file_name_only))
+ use_dialog_p = 0;
+ }
+
+ strncpy (filename, file_name_only, MAX_PATH);
+ filename[MAX_PATH] = '\0';
+ }
+ else
+ filename[0] = '\0';
+
+ if (use_dialog_p)
+ {
+ OPENFILENAME file_details;
+ char *filename_file;
+
+ /* Prevent redisplay. */
+ specbind (Qinhibit_redisplay, Qt);
+ BLOCK_INPUT;
+
+ bzero (&file_details, sizeof (file_details));
+ file_details.lStructSize = sizeof (file_details);
+ file_details.hwndOwner = FRAME_W32_WINDOW (f);
+ file_details.lpstrFile = filename;
+ file_details.nMaxFile = sizeof (filename);
+ file_details.lpstrInitialDir = init_dir;
+ file_details.lpstrTitle = XSTRING (prompt)->data;
+ file_details.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR;
+
+ if (!NILP (mustmatch))
+ file_details.Flags |= OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
+
+ if (GetOpenFileName (&file_details))
+ {
+ dostounix_filename (filename);
+ file = build_string (filename);
+ }
+ else
+ file = Qnil;
+
+ UNBLOCK_INPUT;
+ file = unbind_to (count, file);
+ }
+ /* Open File dialog will not allow folders to be selected, so resort
+ to minibuffer completing reads for directories. */
+ else
+ file = Fcompleting_read (prompt, intern ("read-file-name-internal"),
+ dir, mustmatch, dir, Qfile_name_history,
+ default_filename, Qnil);
+
+ UNGCPRO;
+
+ /* Make "Cancel" equivalent to C-g. */
+ if (NILP (file))
+ Fsignal (Qquit, Qnil);
+
+ return unbind_to (count, file);
+}
+#endif /* MAC_TODO */
+
+
+\f
+/***********************************************************************
+ Tests
+ ***********************************************************************/
+
+#if GLYPH_DEBUG
+
+DEFUN ("imagep", Fimagep, Simagep, 1, 1, 0,
+ doc: /* Value is non-nil if SPEC is a valid image specification. */)
+ (spec)
+ Lisp_Object spec;
+{
+ return valid_image_p (spec) ? Qt : Qnil;
+}
+
+
+DEFUN ("lookup-image", Flookup_image, Slookup_image, 1, 1, 0, "")
+ (spec)
+ Lisp_Object spec;
+{
+ int id = -1;
+
+ if (valid_image_p (spec))
+ id = lookup_image (SELECTED_FRAME (), spec);
+
+ debug_print (spec);
+ return make_number (id);
+}
+
+#endif /* GLYPH_DEBUG != 0 */
+
+
+\f
+void
+syms_of_macfns ()
+{
+ /* Certainly running on Mac. */
+ mac_in_use = 1;
+
+ /* The section below is built by the lisp expression at the top of the file,
+ just above where these variables are declared. */
+ /*&&& init symbols here &&&*/
+ Qauto_raise = intern ("auto-raise");
+ staticpro (&Qauto_raise);
+ Qauto_lower = intern ("auto-lower");
+ staticpro (&Qauto_lower);
+ Qbar = intern ("bar");
+ staticpro (&Qbar);
+ Qborder_color = intern ("border-color");
+ staticpro (&Qborder_color);
+ Qborder_width = intern ("border-width");
+ staticpro (&Qborder_width);
+ Qbox = intern ("box");
+ staticpro (&Qbox);
+ Qcursor_color = intern ("cursor-color");
+ staticpro (&Qcursor_color);
+ Qcursor_type = intern ("cursor-type");
+ staticpro (&Qcursor_type);
+ Qgeometry = intern ("geometry");
+ staticpro (&Qgeometry);
+ Qicon_left = intern ("icon-left");
+ staticpro (&Qicon_left);
+ Qicon_top = intern ("icon-top");
+ staticpro (&Qicon_top);
+ Qicon_type = intern ("icon-type");
+ staticpro (&Qicon_type);
+ Qicon_name = intern ("icon-name");
+ staticpro (&Qicon_name);
+ Qinternal_border_width = intern ("internal-border-width");
+ staticpro (&Qinternal_border_width);
+ Qleft = intern ("left");
+ staticpro (&Qleft);
+ Qright = intern ("right");
+ staticpro (&Qright);
+ Qmouse_color = intern ("mouse-color");
+ staticpro (&Qmouse_color);
+ Qnone = intern ("none");
+ staticpro (&Qnone);
+ Qparent_id = intern ("parent-id");
+ staticpro (&Qparent_id);
+ Qscroll_bar_width = intern ("scroll-bar-width");
+ staticpro (&Qscroll_bar_width);
+ Qsuppress_icon = intern ("suppress-icon");
+ staticpro (&Qsuppress_icon);
+ Qundefined_color = intern ("undefined-color");
+ staticpro (&Qundefined_color);
+ Qvertical_scroll_bars = intern ("vertical-scroll-bars");
+ staticpro (&Qvertical_scroll_bars);
+ Qvisibility = intern ("visibility");
+ staticpro (&Qvisibility);
+ Qwindow_id = intern ("window-id");
+ staticpro (&Qwindow_id);
+ Qx_frame_parameter = intern ("x-frame-parameter");
+ staticpro (&Qx_frame_parameter);
+ Qx_resource_name = intern ("x-resource-name");
+ staticpro (&Qx_resource_name);
+ Quser_position = intern ("user-position");
+ staticpro (&Quser_position);
+ Quser_size = intern ("user-size");
+ staticpro (&Quser_size);
+ Qscreen_gamma = intern ("screen-gamma");
+ staticpro (&Qscreen_gamma);
+ Qline_spacing = intern ("line-spacing");
+ staticpro (&Qline_spacing);
+ Qcenter = intern ("center");
+ staticpro (&Qcenter);
+ /* This is the end of symbol initialization. */
+
+ Qhyper = intern ("hyper");
+ staticpro (&Qhyper);
+ Qsuper = intern ("super");
+ staticpro (&Qsuper);
+ Qmeta = intern ("meta");
+ staticpro (&Qmeta);
+ Qalt = intern ("alt");
+ staticpro (&Qalt);
+ Qctrl = intern ("ctrl");
+ staticpro (&Qctrl);
+ Qcontrol = intern ("control");
+ staticpro (&Qcontrol);
+ Qshift = intern ("shift");
+ staticpro (&Qshift);
+
+ /* Text property `display' should be nonsticky by default. */
+ Vtext_property_default_nonsticky
+ = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
+
+
+ Qlaplace = intern ("laplace");
+ staticpro (&Qlaplace);
+
+ Qface_set_after_frame_default = intern ("face-set-after-frame-default");
+ staticpro (&Qface_set_after_frame_default);
+
+ Fput (Qundefined_color, Qerror_conditions,
+ Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
+ Fput (Qundefined_color, Qerror_message,
+ build_string ("Undefined color"));
+
+ init_x_parm_symbols ();
+
+ DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
+ doc: /* List of directories to search for bitmap files for w32. */);
+ Vx_bitmap_file_path = decode_env_path ((char *) 0, "PATH");
+
+ DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
+ doc: /* The shape of the pointer when over text.
+Changing the value does not affect existing frames
+unless you set the mouse color. */);
+ Vx_pointer_shape = Qnil;
+
+ DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
+ doc: /* The name Emacs uses to look up resources; for internal use only.
+`x-get-resource' uses this as the first component of the instance name
+when requesting resource values.
+Emacs initially sets `x-resource-name' to the name under which Emacs
+was invoked, or to the value specified with the `-name' or `-rn'
+switches, if present. */);
+ Vx_resource_name = Qnil;
+
+ Vx_nontext_pointer_shape = Qnil;
+
+ Vx_mode_pointer_shape = Qnil;
+
+ DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape,
+ doc: /* The shape of the pointer when Emacs is hourglass.
+This variable takes effect when you create a new frame
+or when you set the mouse color. */);
+ Vx_hourglass_pointer_shape = Qnil;
+
+ DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
+ doc: /* Non-zero means Emacs displays an hourglass pointer on window systems. */);
+ display_hourglass_p = 1;
+
+ DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
+ doc: /* *Seconds to wait before displaying an hourglass pointer.
+Value must be an integer or float. */);
+ Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
+
+ DEFVAR_LISP ("x-sensitive-text-pointer-shape",
+ &Vx_sensitive_text_pointer_shape,
+ doc: /* The shape of the pointer when over mouse-sensitive text.
+This variable takes effect when you create a new frame
+or when you set the mouse color. */);
+ Vx_sensitive_text_pointer_shape = Qnil;
+
+ DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
+ doc: /* A string indicating the foreground color of the cursor box. */);
+ Vx_cursor_fore_pixel = Qnil;
+
+ DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
+ doc: /* Non-nil if no window manager is in use.
+Emacs doesn't try to figure this out; this is always nil
+unless you set it to something else. */);
+ /* We don't have any way to find this out, so set it to nil
+ and maybe the user would like to set it to t. */
+ Vx_no_window_manager = Qnil;
+
+ DEFVAR_LISP ("x-pixel-size-width-font-regexp",
+ &Vx_pixel_size_width_font_regexp,
+ doc: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
+
+Since Emacs gets width of a font matching with this regexp from
+PIXEL_SIZE field of the name, font finding mechanism gets faster for
+such a font. This is especially effective for such large fonts as
+Chinese, Japanese, and Korean. */);
+ Vx_pixel_size_width_font_regexp = Qnil;
+
+ DEFVAR_LISP ("image-cache-eviction-delay", &Vimage_cache_eviction_delay,
+ doc: /* Time after which cached images are removed from the cache.
+When an image has not been displayed this many seconds, remove it
+from the image cache. Value must be an integer or nil with nil
+meaning don't clear the cache. */);
+ Vimage_cache_eviction_delay = make_number (30 * 60);
+
+#if 0 /* MAC_TODO: implement get X resource */
+ defsubr (&Sx_get_resource);
+#endif
+ defsubr (&Sx_change_window_property);
+ defsubr (&Sx_delete_window_property);
+ defsubr (&Sx_window_property);
+ defsubr (&Sxw_display_color_p);
+ defsubr (&Sx_display_grayscale_p);
+ defsubr (&Sxw_color_defined_p);
+ defsubr (&Sxw_color_values);
+ defsubr (&Sx_server_max_request_size);
+ defsubr (&Sx_server_vendor);
+ defsubr (&Sx_server_version);
+ defsubr (&Sx_display_pixel_width);
+ defsubr (&Sx_display_pixel_height);
+ defsubr (&Sx_display_mm_width);
+ defsubr (&Sx_display_mm_height);
+ defsubr (&Sx_display_screens);
+ defsubr (&Sx_display_planes);
+ defsubr (&Sx_display_color_cells);
+ defsubr (&Sx_display_visual_class);
+ defsubr (&Sx_display_backing_store);
+ defsubr (&Sx_display_save_under);
+#if 0 /* MAC_TODO: implement XParseGeometry */
+ defsubr (&Sx_parse_geometry);
+#endif
+ defsubr (&Sx_create_frame);
+#if 0 /* MAC_TODO: implement network support */
+ defsubr (&Sx_open_connection);
+ defsubr (&Sx_close_connection);
+#endif
+ defsubr (&Sx_display_list);
+ defsubr (&Sx_synchronize);
+
+ /* Setting callback functions for fontset handler. */
+ get_font_info_func = x_get_font_info;
+
+#if 0 /* This function pointer doesn't seem to be used anywhere.
+ And the pointer assigned has the wrong type, anyway. */
+ list_fonts_func = x_list_fonts;
+#endif
+
+ load_font_func = x_load_font;
+ find_ccl_program_func = x_find_ccl_program;
+ query_font_func = x_query_font;
+
+ set_frame_fontset_func = x_set_font;
+ check_window_system_func = check_mac;
+
+#if 0 /* MAC_TODO: Image support for Mac Images. */
+ Qxbm = intern ("xbm");
+ staticpro (&Qxbm);
+ QCtype = intern (":type");
+ staticpro (&QCtype);
+ QCconversion = intern (":conversion");
+ staticpro (&QCconversion);
+ QCheuristic_mask = intern (":heuristic-mask");
+ staticpro (&QCheuristic_mask);
+ QCcolor_symbols = intern (":color-symbols");
+ staticpro (&QCcolor_symbols);
+ QCascent = intern (":ascent");
+ staticpro (&QCascent);
+ QCmargin = intern (":margin");
+ staticpro (&QCmargin);
+ QCrelief = intern (":relief");
+ staticpro (&QCrelief);
+ Qpostscript = intern ("postscript");
+ staticpro (&Qpostscript);
+ QCloader = intern (":loader");
+ staticpro (&QCloader);
+ QCbounding_box = intern (":bounding-box");
+ staticpro (&QCbounding_box);
+ QCpt_width = intern (":pt-width");
+ staticpro (&QCpt_width);
+ QCpt_height = intern (":pt-height");
+ staticpro (&QCpt_height);
+ QCindex = intern (":index");
+ staticpro (&QCindex);
+ Qpbm = intern ("pbm");
+ staticpro (&Qpbm);
+
+#if HAVE_XPM
+ Qxpm = intern ("xpm");
+ staticpro (&Qxpm);
+#endif
+
+#if HAVE_JPEG
+ Qjpeg = intern ("jpeg");
+ staticpro (&Qjpeg);
+#endif
+
+#if HAVE_TIFF
+ Qtiff = intern ("tiff");
+ staticpro (&Qtiff);
+#endif
+
+#if HAVE_GIF
+ Qgif = intern ("gif");
+ staticpro (&Qgif);
+#endif
+
+#if HAVE_PNG
+ Qpng = intern ("png");
+ staticpro (&Qpng);
+#endif
+
+ defsubr (&Sclear_image_cache);
+
+#if GLYPH_DEBUG
+ defsubr (&Simagep);
+ defsubr (&Slookup_image);
+#endif
+#endif /* MAC_TODO */
+
+ hourglass_atimer = NULL;
+ hourglass_shown_p = 0;
+
+ defsubr (&Sx_show_tip);
+ defsubr (&Sx_hide_tip);
+ staticpro (&tip_timer);
+ tip_timer = Qnil;
+
+#if 0 /* MAC_TODO */
+ defsubr (&Sx_file_dialog);
+#endif
+}
+
+
+void
+init_xfns ()
+{
+ image_types = NULL;
+ Vimage_types = Qnil;
+
+ define_image_type (&xbm_type);
+#if 0 /* NTEMACS_TODO : Image support for W32 */
+ define_image_type (&gs_type);
+ define_image_type (&pbm_type);
+
+#if HAVE_XPM
+ define_image_type (&xpm_type);
+#endif
+
+#if HAVE_JPEG
+ define_image_type (&jpeg_type);
+#endif
+
+#if HAVE_TIFF
+ define_image_type (&tiff_type);
+#endif
+
+#if HAVE_GIF
+ define_image_type (&gif_type);
+#endif
+
+#if HAVE_PNG
+ define_image_type (&png_type);
+#endif
+#endif /* NTEMACS_TODO */
+}
--- /dev/null
+/* Definitions and headers for communication on the Mac OS.
+ Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Contributed by Andrew Choi (akochoi@mac.com). */
+
+#ifndef EMACS_MACGUI_H
+#define EMACS_MACGUI_H
+
+typedef int Pixmap;
+typedef int Bitmap;
+
+typedef int Display; /* fix later */
+
+typedef unsigned long Time;
+
+#if MAC_OSX
+typedef struct OpaqueWindowPtr* Window;
+#else
+#include <QuickDraw.h>
+typedef WindowPtr Window;
+#endif
+
+#define FACE_DEFAULT (~0)
+
+
+/* Emulate XCharStruct. */
+typedef struct _XCharStruct
+{
+ int rbearing;
+ int lbearing;
+ int width;
+ int ascent;
+ int descent;
+} XCharStruct;
+
+struct MacFontStruct {
+ char *fontname;
+
+ short mac_fontnum; /* font number of font used in this window */
+ int mac_fontsize; /* size of font */
+ short mac_fontface; /* plain, bold, italics, etc. */
+ short mac_scriptcode; /* Mac OS script code for font used */
+
+#if 0
+ SInt16 mFontNum; /* font number of font used in this window */
+ short mScriptCode; /* Mac OS script code for font used */
+ int mFontSize; /* size of font */
+ Style mFontFace; /* plain, bold, italics, etc. */
+ int mHeight; /* height of one line of text in pixels */
+ int mWidth; /* width of one character in pixels */
+ int mAscent;
+ int mDescent;
+ int mLeading;
+ char mTwoByte; /* true for two-byte font */
+#endif /* 0 */
+
+/* from Xlib.h */
+#if 0
+ XExtData *ext_data; /* hook for extension to hang data */
+ Font fid; /* Font id for this font */
+ unsigned direction; /* hint about the direction font is painted */
+#endif /* 0 */
+ unsigned min_char_or_byte2;/* first character */
+ unsigned max_char_or_byte2;/* last character */
+ unsigned min_byte1; /* first row that exists */
+ unsigned max_byte1; /* last row that exists */
+#if 0
+ Bool all_chars_exist; /* flag if all characters have nonzero size */
+ unsigned default_char; /* char to print for undefined character */
+ int n_properties; /* how many properties there are */
+ XFontProp *properties; /* pointer to array of additional properties */
+#endif /* 0 */
+ XCharStruct min_bounds; /* minimum bounds over all existing char */
+ XCharStruct max_bounds; /* maximum bounds over all existing char */
+ XCharStruct *per_char; /* first_char to last_char information */
+ int ascent; /* logical extent above baseline for spacing */
+ int descent; /* logical decent below baseline for spacing */
+};
+
+typedef struct MacFontStruct MacFontStruct;
+typedef struct MacFontStruct XFontStruct;
+
+
+/* Emulate X GC's by keeping color and font info in a structure. */
+typedef struct _XGCValues
+{
+ unsigned long foreground;
+ unsigned long background;
+ XFontStruct *font;
+} XGCValues;
+
+typedef XGCValues *GC;
+
+extern XGCValues *
+XCreateGC (void *, Window, unsigned long, XGCValues *);
+
+#define GCForeground 0x01
+#define GCBackground 0x02
+#define GCFont 0x03
+#define GCGraphicsExposures 0
+
+/* Bit Gravity */
+
+#define ForgetGravity 0
+#define NorthWestGravity 1
+#define NorthGravity 2
+#define NorthEastGravity 3
+#define WestGravity 4
+#define CenterGravity 5
+#define EastGravity 6
+#define SouthWestGravity 7
+#define SouthGravity 8
+#define SouthEastGravity 9
+#define StaticGravity 10
+
+#define NoValue 0x0000
+#define XValue 0x0001
+#define YValue 0x0002
+#define WidthValue 0x0004
+#define HeightValue 0x0008
+#define AllValues 0x000F
+#define XNegative 0x0010
+#define YNegative 0x0020
+
+#define USPosition (1L << 0) /* user specified x, y */
+#define USSize (1L << 1) /* user specified width, height */
+
+#define PPosition (1L << 2) /* program specified position */
+#define PSize (1L << 3) /* program specified size */
+#define PMinSize (1L << 4) /* program specified minimum size */
+#define PMaxSize (1L << 5) /* program specified maximum size */
+#define PResizeInc (1L << 6) /* program specified resize increments */
+#define PAspect (1L << 7) /* program specified min and max aspect ratios */
+#define PBaseSize (1L << 8) /* program specified base for incrementing */
+#define PWinGravity (1L << 9) /* program specified window gravity */
+
+extern int XParseGeometry ();
+
+#endif /* EMACS_MACGUI_H */
+
--- /dev/null
+/* Menu support for GNU Emacs on the for Mac OS.
+ Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Contributed by Andrew Choi (akochoi@mac.com). */
+
+#include <config.h>
+#include <signal.h>
+
+#include <stdio.h>
+#include "lisp.h"
+#include "termhooks.h"
+#include "keyboard.h"
+#include "keymap.h"
+#include "frame.h"
+#include "window.h"
+#include "blockinput.h"
+#include "buffer.h"
+#include "charset.h"
+#include "coding.h"
+
+#ifdef MAC_OSX
+#undef mktime
+#undef DEBUG
+#undef Z
+#undef free
+#undef malloc
+#undef realloc
+/* Macros max and min defined in lisp.h conflict with those in
+ precompiled header Carbon.h. */
+#undef max
+#undef min
+#include <Carbon/Carbon.h>
+#undef Z
+#define Z (current_buffer->text->z)
+#undef free
+#define free unexec_free
+#undef malloc
+#define malloc unexec_malloc
+#undef realloc
+#define realloc unexec_realloc
+#undef min
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#undef max
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#else /* not MAC_OSX */
+#include <MacTypes.h>
+#include <Menus.h>
+#include <QuickDraw.h>
+#include <ToolUtils.h>
+#include <Fonts.h>
+#include <Controls.h>
+#include <Windows.h>
+#include <Events.h>
+#if defined (__MRC__) || (__MSL__ >= 0x6000)
+#include <ControlDefinitions.h>
+#endif
+#endif /* not MAC_OSX */
+
+/* This may include sys/types.h, and that somehow loses
+ if this is not done before the other system files. */
+#include "macterm.h"
+
+/* Load sys/types.h if not already loaded.
+ In some systems loading it twice is suicidal. */
+#ifndef makedev
+#include <sys/types.h>
+#endif
+
+#include "dispextern.h"
+
+#define POPUP_SUBMENU_ID 235
+#define MIN_MENU_ID 256
+#define MIN_SUBMENU_ID 1
+
+#define DIALOG_WINDOW_RESOURCE 130
+
+#define HAVE_DIALOGS 1
+
+#undef HAVE_MULTILINGUAL_MENU
+#undef HAVE_DIALOGS /* TODO: Implement native dialogs. */
+
+/******************************************************************/
+/* Definitions copied from lwlib.h */
+
+typedef void * XtPointer;
+
+enum button_type
+{
+ BUTTON_TYPE_NONE,
+ BUTTON_TYPE_TOGGLE,
+ BUTTON_TYPE_RADIO
+};
+
+/* This structure is based on the one in ../lwlib/lwlib.h, modified
+ for Mac OS. */
+typedef struct _widget_value
+{
+ /* name of widget */
+ char* name;
+ /* value (meaning depend on widget type) */
+ char* value;
+ /* keyboard equivalent. no implications for XtTranslations */
+ char* key;
+ /* Help string or nil if none.
+ GC finds this string through the frame's menu_bar_vector
+ or through menu_items. */
+ Lisp_Object help;
+ /* true if enabled */
+ Boolean enabled;
+ /* true if selected */
+ Boolean selected;
+ /* The type of a button. */
+ enum button_type button_type;
+ /* true if menu title */
+ Boolean title;
+#if 0
+ /* true if was edited (maintained by get_value) */
+ Boolean edited;
+ /* true if has changed (maintained by lw library) */
+ change_type change;
+ /* true if this widget itself has changed,
+ but not counting the other widgets found in the `next' field. */
+ change_type this_one_change;
+#endif
+ /* Contents of the sub-widgets, also selected slot for checkbox */
+ struct _widget_value* contents;
+ /* data passed to callback */
+ XtPointer call_data;
+ /* next one in the list */
+ struct _widget_value* next;
+#if 0
+ /* slot for the toolkit dependent part. Always initialize to NULL. */
+ void* toolkit_data;
+ /* tell us if we should free the toolkit data slot when freeing the
+ widget_value itself. */
+ Boolean free_toolkit_data;
+
+ /* we resource the widget_value structures; this points to the next
+ one on the free list if this one has been deallocated.
+ */
+ struct _widget_value *free_list;
+#endif
+} widget_value;
+
+/* Assumed by other routines to zero area returned. */
+#define malloc_widget_value() (void *)memset (xmalloc (sizeof (widget_value)),\
+ 0, (sizeof (widget_value)))
+#define free_widget_value(wv) xfree (wv)
+
+/******************************************************************/
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif /* no TRUE */
+
+Lisp_Object Vmenu_updating_frame;
+
+Lisp_Object Qdebug_on_next_call;
+
+extern Lisp_Object Qmenu_bar;
+extern Lisp_Object Qmouse_click, Qevent_kind;
+
+extern Lisp_Object QCtoggle, QCradio;
+
+extern Lisp_Object Voverriding_local_map;
+extern Lisp_Object Voverriding_local_map_menu_flag;
+
+extern Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
+
+extern Lisp_Object Qmenu_bar_update_hook;
+
+void set_frame_menubar ();
+
+static void push_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
+ Lisp_Object, Lisp_Object, Lisp_Object,
+ Lisp_Object, Lisp_Object));
+#ifdef HAVE_DIALOGS
+static Lisp_Object mac_dialog_show ();
+#endif
+static Lisp_Object mac_menu_show ();
+
+static void keymap_panes ();
+static void single_keymap_panes ();
+static void single_menu_item ();
+static void list_of_panes ();
+static void list_of_items ();
+
+static void fill_submenu (MenuHandle, widget_value *, int);
+static void fill_menubar (widget_value *);
+
+\f
+/* This holds a Lisp vector that holds the results of decoding
+ the keymaps or alist-of-alists that specify a menu.
+
+ It describes the panes and items within the panes.
+
+ Each pane is described by 3 elements in the vector:
+ t, the pane name, the pane's prefix key.
+ Then follow the pane's items, with 5 elements per item:
+ the item string, the enable flag, the item's value,
+ the definition, and the equivalent keyboard key's description string.
+
+ In some cases, multiple levels of menus may be described.
+ A single vector slot containing nil indicates the start of a submenu.
+ A single vector slot containing lambda indicates the end of a submenu.
+ The submenu follows a menu item which is the way to reach the submenu.
+
+ A single vector slot containing quote indicates that the
+ following items should appear on the right of a dialog box.
+
+ Using a Lisp vector to hold this information while we decode it
+ takes care of protecting all the data from GC. */
+
+#define MENU_ITEMS_PANE_NAME 1
+#define MENU_ITEMS_PANE_PREFIX 2
+#define MENU_ITEMS_PANE_LENGTH 3
+
+enum menu_item_idx
+{
+ MENU_ITEMS_ITEM_NAME = 0,
+ MENU_ITEMS_ITEM_ENABLE,
+ MENU_ITEMS_ITEM_VALUE,
+ MENU_ITEMS_ITEM_EQUIV_KEY,
+ MENU_ITEMS_ITEM_DEFINITION,
+ MENU_ITEMS_ITEM_TYPE,
+ MENU_ITEMS_ITEM_SELECTED,
+ MENU_ITEMS_ITEM_HELP,
+ MENU_ITEMS_ITEM_LENGTH
+};
+
+static Lisp_Object menu_items;
+
+/* Number of slots currently allocated in menu_items. */
+static int menu_items_allocated;
+
+/* This is the index in menu_items of the first empty slot. */
+static int menu_items_used;
+
+/* The number of panes currently recorded in menu_items,
+ excluding those within submenus. */
+static int menu_items_n_panes;
+
+/* Current depth within submenus. */
+static int menu_items_submenu_depth;
+
+/* Flag which when set indicates a dialog or menu has been posted by
+ Xt on behalf of one of the widget sets. */
+static int popup_activated_flag;
+
+static int next_menubar_widget_id;
+
+/* This is set nonzero after the user activates the menu bar, and set
+ to zero again after the menu bars are redisplayed by prepare_menu_bar.
+ While it is nonzero, all calls to set_frame_menubar go deep.
+
+ I don't understand why this is needed, but it does seem to be
+ needed on Motif, according to Marcus Daniels <marcus@sysc.pdx.edu>. */
+
+int pending_menu_activation;
+\f
+/* Initialize the menu_items structure if we haven't already done so.
+ Also mark it as currently empty. */
+
+static void
+init_menu_items ()
+{
+ if (NILP (menu_items))
+ {
+ menu_items_allocated = 60;
+ menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil);
+ }
+
+ menu_items_used = 0;
+ menu_items_n_panes = 0;
+ menu_items_submenu_depth = 0;
+}
+
+/* Call at the end of generating the data in menu_items.
+ This fills in the number of items in the last pane. */
+
+static void
+finish_menu_items ()
+{
+}
+
+/* Call when finished using the data for the current menu
+ in menu_items. */
+
+static void
+discard_menu_items ()
+{
+ /* Free the structure if it is especially large.
+ Otherwise, hold on to it, to save time. */
+ if (menu_items_allocated > 200)
+ {
+ menu_items = Qnil;
+ menu_items_allocated = 0;
+ }
+}
+
+/* Make the menu_items vector twice as large. */
+
+static void
+grow_menu_items ()
+{
+ Lisp_Object old;
+ int old_size = menu_items_allocated;
+ old = menu_items;
+
+ menu_items_allocated *= 2;
+ menu_items = Fmake_vector (make_number (menu_items_allocated), Qnil);
+ bcopy (XVECTOR (old)->contents, XVECTOR (menu_items)->contents,
+ old_size * sizeof (Lisp_Object));
+}
+
+/* Begin a submenu. */
+
+static void
+push_submenu_start ()
+{
+ if (menu_items_used + 1 > menu_items_allocated)
+ grow_menu_items ();
+
+ XVECTOR (menu_items)->contents[menu_items_used++] = Qnil;
+ menu_items_submenu_depth++;
+}
+
+/* End a submenu. */
+
+static void
+push_submenu_end ()
+{
+ if (menu_items_used + 1 > menu_items_allocated)
+ grow_menu_items ();
+
+ XVECTOR (menu_items)->contents[menu_items_used++] = Qlambda;
+ menu_items_submenu_depth--;
+}
+
+/* Indicate boundary between left and right. */
+
+static void
+push_left_right_boundary ()
+{
+ if (menu_items_used + 1 > menu_items_allocated)
+ grow_menu_items ();
+
+ XVECTOR (menu_items)->contents[menu_items_used++] = Qquote;
+}
+
+/* Start a new menu pane in menu_items.
+ NAME is the pane name. PREFIX_VEC is a prefix key for this pane. */
+
+static void
+push_menu_pane (name, prefix_vec)
+ Lisp_Object name, prefix_vec;
+{
+ if (menu_items_used + MENU_ITEMS_PANE_LENGTH > menu_items_allocated)
+ grow_menu_items ();
+
+ if (menu_items_submenu_depth == 0)
+ menu_items_n_panes++;
+ XVECTOR (menu_items)->contents[menu_items_used++] = Qt;
+ XVECTOR (menu_items)->contents[menu_items_used++] = name;
+ XVECTOR (menu_items)->contents[menu_items_used++] = prefix_vec;
+}
+
+/* Push one menu item into the current pane. NAME is the string to
+ display. ENABLE if non-nil means this item can be selected. KEY
+ is the key generated by choosing this item, or nil if this item
+ doesn't really have a definition. DEF is the definition of this
+ item. EQUIV is the textual description of the keyboard equivalent
+ for this item (or nil if none). TYPE is the type of this menu
+ item, one of nil, `toggle' or `radio'. */
+
+static void
+push_menu_item (name, enable, key, def, equiv, type, selected, help)
+ Lisp_Object name, enable, key, def, equiv, type, selected, help;
+{
+ if (menu_items_used + MENU_ITEMS_ITEM_LENGTH > menu_items_allocated)
+ grow_menu_items ();
+
+ XVECTOR (menu_items)->contents[menu_items_used++] = name;
+ XVECTOR (menu_items)->contents[menu_items_used++] = enable;
+ XVECTOR (menu_items)->contents[menu_items_used++] = key;
+ XVECTOR (menu_items)->contents[menu_items_used++] = equiv;
+ XVECTOR (menu_items)->contents[menu_items_used++] = def;
+ XVECTOR (menu_items)->contents[menu_items_used++] = type;
+ XVECTOR (menu_items)->contents[menu_items_used++] = selected;
+ XVECTOR (menu_items)->contents[menu_items_used++] = help;
+}
+\f
+/* Look through KEYMAPS, a vector of keymaps that is NMAPS long,
+ and generate menu panes for them in menu_items.
+ If NOTREAL is nonzero,
+ don't bother really computing whether an item is enabled. */
+
+static void
+keymap_panes (keymaps, nmaps, notreal)
+ Lisp_Object *keymaps;
+ int nmaps;
+ int notreal;
+{
+ int mapno;
+
+ init_menu_items ();
+
+ /* Loop over the given keymaps, making a pane for each map.
+ But don't make a pane that is empty--ignore that map instead.
+ P is the number of panes we have made so far. */
+ for (mapno = 0; mapno < nmaps; mapno++)
+ single_keymap_panes (keymaps[mapno],
+ Fkeymap_prompt (keymaps[mapno]), Qnil, notreal, 10);
+
+ finish_menu_items ();
+}
+
+/* This is a recursive subroutine of keymap_panes.
+ It handles one keymap, KEYMAP.
+ The other arguments are passed along
+ or point to local variables of the previous function.
+ If NOTREAL is nonzero, only check for equivalent key bindings, don't
+ evaluate expressions in menu items and don't make any menu.
+
+ If we encounter submenus deeper than MAXDEPTH levels, ignore them. */
+
+static void
+single_keymap_panes (keymap, pane_name, prefix, notreal, maxdepth)
+ Lisp_Object keymap;
+ Lisp_Object pane_name;
+ Lisp_Object prefix;
+ int notreal;
+ int maxdepth;
+{
+ Lisp_Object pending_maps = Qnil;
+ Lisp_Object tail, item;
+ struct gcpro gcpro1, gcpro2;
+
+ if (maxdepth <= 0)
+ return;
+
+ push_menu_pane (pane_name, prefix);
+
+ for (tail = keymap; CONSP (tail); tail = XCDR (tail))
+ {
+ GCPRO2 (keymap, pending_maps);
+ /* Look at each key binding, and if it is a menu item add it
+ to this menu. */
+ item = XCAR (tail);
+ if (CONSP (item))
+ single_menu_item (XCAR (item), XCDR (item),
+ &pending_maps, notreal, maxdepth);
+ else if (VECTORP (item))
+ {
+ /* Loop over the char values represented in the vector. */
+ int len = XVECTOR (item)->size;
+ int c;
+ for (c = 0; c < len; c++)
+ {
+ Lisp_Object character;
+ XSETFASTINT (character, c);
+ single_menu_item (character, XVECTOR (item)->contents[c],
+ &pending_maps, notreal, maxdepth);
+ }
+ }
+ UNGCPRO;
+ }
+
+ /* Process now any submenus which want to be panes at this level. */
+ while (!NILP (pending_maps))
+ {
+ Lisp_Object elt, eltcdr, string;
+ elt = Fcar (pending_maps);
+ eltcdr = XCDR (elt);
+ string = XCAR (eltcdr);
+ /* We no longer discard the @ from the beginning of the string here.
+ Instead, we do this in mac_menu_show. */
+ single_keymap_panes (Fcar (elt), string,
+ XCDR (eltcdr), notreal, maxdepth - 1);
+ pending_maps = Fcdr (pending_maps);
+ }
+}
+\f
+/* This is a subroutine of single_keymap_panes that handles one
+ keymap entry.
+ KEY is a key in a keymap and ITEM is its binding.
+ PENDING_MAPS_PTR points to a list of keymaps waiting to be made into
+ separate panes.
+ If NOTREAL is nonzero, only check for equivalent key bindings, don't
+ evaluate expressions in menu items and don't make any menu.
+ If we encounter submenus deeper than MAXDEPTH levels, ignore them. */
+
+static void
+single_menu_item (key, item, pending_maps_ptr, notreal, maxdepth)
+ Lisp_Object key, item;
+ Lisp_Object *pending_maps_ptr;
+ int maxdepth, notreal;
+{
+ Lisp_Object map, item_string, enabled;
+ struct gcpro gcpro1, gcpro2;
+ int res;
+
+ /* Parse the menu item and leave the result in item_properties. */
+ GCPRO2 (key, item);
+ res = parse_menu_item (item, notreal, 0);
+ UNGCPRO;
+ if (!res)
+ return; /* Not a menu item. */
+
+ map = XVECTOR (item_properties)->contents[ITEM_PROPERTY_MAP];
+
+ if (notreal)
+ {
+ /* We don't want to make a menu, just traverse the keymaps to
+ precompute equivalent key bindings. */
+ if (!NILP (map))
+ single_keymap_panes (map, Qnil, key, 1, maxdepth - 1);
+ return;
+ }
+
+ enabled = XVECTOR (item_properties)->contents[ITEM_PROPERTY_ENABLE];
+ item_string = XVECTOR (item_properties)->contents[ITEM_PROPERTY_NAME];
+
+ if (!NILP (map) && XSTRING (item_string)->data[0] == '@')
+ {
+ if (!NILP (enabled))
+ /* An enabled separate pane. Remember this to handle it later. */
+ *pending_maps_ptr = Fcons (Fcons (map, Fcons (item_string, key)),
+ *pending_maps_ptr);
+ return;
+ }
+
+ push_menu_item (item_string, enabled, key,
+ XVECTOR (item_properties)->contents[ITEM_PROPERTY_DEF],
+ XVECTOR (item_properties)->contents[ITEM_PROPERTY_KEYEQ],
+ XVECTOR (item_properties)->contents[ITEM_PROPERTY_TYPE],
+ XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED],
+ XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]);
+
+ /* Display a submenu using the toolkit. */
+ if (! (NILP (map) || NILP (enabled)))
+ {
+ push_submenu_start ();
+ single_keymap_panes (map, Qnil, key, 0, maxdepth - 1);
+ push_submenu_end ();
+ }
+}
+\f
+/* Push all the panes and items of a menu described by the
+ alist-of-alists MENU.
+ This handles old-fashioned calls to x-popup-menu. */
+
+static void
+list_of_panes (menu)
+ Lisp_Object menu;
+{
+ Lisp_Object tail;
+
+ init_menu_items ();
+
+ for (tail = menu; !NILP (tail); tail = Fcdr (tail))
+ {
+ Lisp_Object elt, pane_name, pane_data;
+ elt = Fcar (tail);
+ pane_name = Fcar (elt);
+ CHECK_STRING (pane_name);
+ push_menu_pane (pane_name, Qnil);
+ pane_data = Fcdr (elt);
+ CHECK_CONS (pane_data);
+ list_of_items (pane_data);
+ }
+
+ finish_menu_items ();
+}
+
+/* Push the items in a single pane defined by the alist PANE. */
+
+static void
+list_of_items (pane)
+ Lisp_Object pane;
+{
+ Lisp_Object tail, item, item1;
+
+ for (tail = pane; !NILP (tail); tail = Fcdr (tail))
+ {
+ item = Fcar (tail);
+ if (STRINGP (item))
+ push_menu_item (item, Qnil, Qnil, Qt, Qnil, Qnil, Qnil, Qnil);
+ else if (NILP (item))
+ push_left_right_boundary ();
+ else
+ {
+ CHECK_CONS (item);
+ item1 = Fcar (item);
+ CHECK_STRING (item1);
+ push_menu_item (item1, Qt, Fcdr (item), Qt, Qnil, Qnil, Qnil, Qnil);
+ }
+ }
+}
+\f
+DEFUN ("x-popup-menu", Fx_popup_menu, Sx_popup_menu, 2, 2, 0,
+ doc: /* Pop up a deck-of-cards menu and return user's selection.
+POSITION is a position specification. This is either a mouse button
+event or a list ((XOFFSET YOFFSET) WINDOW) where XOFFSET and YOFFSET
+are positions in pixels from the top left corner of WINDOW's frame
+\(WINDOW may be a frame object instead of a window). This controls the
+position of the center of the first line in the first pane of the
+menu, not the top left of the menu as a whole. If POSITION is t, it
+means to use the current mouse position.
+
+MENU is a specifier for a menu. For the simplest case, MENU is a keymap.
+The menu items come from key bindings that have a menu string as well as
+a definition; actually, the \"definition\" in such a key binding looks like
+\(STRING . REAL-DEFINITION). To give the menu a title, put a string into
+the keymap as a top-level element.
+
+If REAL-DEFINITION is nil, that puts a nonselectable string in the menu.
+Otherwise, REAL-DEFINITION should be a valid key binding definition.
+
+You can also use a list of keymaps as MENU. Then each keymap makes a
+separate pane. When MENU is a keymap or a list of keymaps, the return
+value is a list of events.
+
+Alternatively, you can specify a menu of multiple panes with a list of
+the form (TITLE PANE1 PANE2...), where each pane is a list of
+form (TITLE ITEM1 ITEM2...).
+Each ITEM is normally a cons cell (STRING . VALUE); but a string can
+appear as an item--that makes a nonselectable line in the menu.
+With this form of menu, the return value is VALUE from the chosen item.
+
+If POSITION is nil, don't display the menu at all, just precalculate the
+cached information about equivalent key sequences. */)
+ (position, menu)
+ Lisp_Object position, menu;
+{
+ Lisp_Object keymap, tem;
+ int xpos = 0, ypos = 0;
+ Lisp_Object title;
+ char *error_name;
+ Lisp_Object selection;
+ FRAME_PTR f = NULL;
+ Lisp_Object x, y, window;
+ int keymaps = 0;
+ int for_click = 0;
+ struct gcpro gcpro1;
+
+#ifdef HAVE_MENUS
+ if (! NILP (position))
+ {
+ check_mac ();
+
+ /* Decode the first argument: find the window and the coordinates. */
+ if (EQ (position, Qt)
+ || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
+ || EQ (XCAR (position), Qtool_bar))))
+ {
+ /* Use the mouse's current position. */
+ FRAME_PTR new_f = SELECTED_FRAME ();
+ Lisp_Object bar_window;
+ enum scroll_bar_part part;
+ unsigned long time;
+
+ if (mouse_position_hook)
+ (*mouse_position_hook) (&new_f, 1, &bar_window,
+ &part, &x, &y, &time);
+ if (new_f != 0)
+ XSETFRAME (window, new_f);
+ else
+ {
+ window = selected_window;
+ XSETFASTINT (x, 0);
+ XSETFASTINT (y, 0);
+ }
+ }
+ else
+ {
+ tem = Fcar (position);
+ if (CONSP (tem))
+ {
+ window = Fcar (Fcdr (position));
+ x = Fcar (tem);
+ y = Fcar (Fcdr (tem));
+ }
+ else
+ {
+ for_click = 1;
+ tem = Fcar (Fcdr (position)); /* EVENT_START (position) */
+ window = Fcar (tem); /* POSN_WINDOW (tem) */
+ tem = Fcar (Fcdr (Fcdr (tem))); /* POSN_WINDOW_POSN (tem) */
+ x = Fcar (tem);
+ y = Fcdr (tem);
+ }
+ }
+
+ CHECK_NUMBER (x);
+ CHECK_NUMBER (y);
+
+ /* Decode where to put the menu. */
+
+ if (FRAMEP (window))
+ {
+ f = XFRAME (window);
+ xpos = 0;
+ ypos = 0;
+ }
+ else if (WINDOWP (window))
+ {
+ CHECK_LIVE_WINDOW (window);
+ f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
+
+ xpos = (FONT_WIDTH (FRAME_FONT (f))
+ * XFASTINT (XWINDOW (window)->left));
+ ypos = (FRAME_LINE_HEIGHT (f)
+ * XFASTINT (XWINDOW (window)->top));
+ }
+ else
+ /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
+ but I don't want to make one now. */
+ CHECK_WINDOW (window);
+
+ xpos += XINT (x);
+ ypos += XINT (y);
+
+ XSETFRAME (Vmenu_updating_frame, f);
+ }
+ Vmenu_updating_frame = Qnil;
+#endif /* HAVE_MENUS */
+
+ title = Qnil;
+ GCPRO1 (title);
+
+ /* Decode the menu items from what was specified. */
+
+ keymap = get_keymap (menu, 0, 0);
+ if (CONSP (keymap))
+ {
+ /* We were given a keymap. Extract menu info from the keymap. */
+ Lisp_Object prompt;
+
+ /* Extract the detailed info to make one pane. */
+ keymap_panes (&menu, 1, NILP (position));
+
+ /* Search for a string appearing directly as an element of the keymap.
+ That string is the title of the menu. */
+ prompt = Fkeymap_prompt (keymap);
+ if (NILP (title) && !NILP (prompt))
+ title = prompt;
+
+ /* Make that be the pane title of the first pane. */
+ if (!NILP (prompt) && menu_items_n_panes >= 0)
+ XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME] = prompt;
+
+ keymaps = 1;
+ }
+ else if (CONSP (menu) && KEYMAPP (XCAR (menu)))
+ {
+ /* We were given a list of keymaps. */
+ int nmaps = XFASTINT (Flength (menu));
+ Lisp_Object *maps
+ = (Lisp_Object *) alloca (nmaps * sizeof (Lisp_Object));
+ int i;
+
+ title = Qnil;
+
+ /* The first keymap that has a prompt string
+ supplies the menu title. */
+ for (tem = menu, i = 0; CONSP (tem); tem = Fcdr (tem))
+ {
+ Lisp_Object prompt;
+
+ maps[i++] = keymap = get_keymap (Fcar (tem), 1, 0);
+
+ prompt = Fkeymap_prompt (keymap);
+ if (NILP (title) && !NILP (prompt))
+ title = prompt;
+ }
+
+ /* Extract the detailed info to make one pane. */
+ keymap_panes (maps, nmaps, NILP (position));
+
+ /* Make the title be the pane title of the first pane. */
+ if (!NILP (title) && menu_items_n_panes >= 0)
+ XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME] = title;
+
+ keymaps = 1;
+ }
+ else
+ {
+ /* We were given an old-fashioned menu. */
+ title = Fcar (menu);
+ CHECK_STRING (title);
+
+ list_of_panes (Fcdr (menu));
+
+ keymaps = 0;
+ }
+
+ if (NILP (position))
+ {
+ discard_menu_items ();
+ UNGCPRO;
+ return Qnil;
+ }
+
+#ifdef HAVE_MENUS
+ /* Display them in a menu. */
+ BLOCK_INPUT;
+
+ selection = mac_menu_show (f, xpos, ypos, for_click,
+ keymaps, title, &error_name);
+ UNBLOCK_INPUT;
+
+ discard_menu_items ();
+
+ UNGCPRO;
+#endif /* HAVE_MENUS */
+
+ if (error_name) error (error_name);
+ return selection;
+}
+
+#ifdef HAVE_MENUS
+
+DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 2, 0,
+ doc: /* Pop up a dialog box and return user's selection.
+POSITION specifies which frame to use.
+This is normally a mouse button event or a window or frame.
+If POSITION is t, it means to use the frame the mouse is on.
+The dialog box appears in the middle of the specified frame.
+
+CONTENTS specifies the alternatives to display in the dialog box.
+It is a list of the form (TITLE ITEM1 ITEM2...).
+Each ITEM is a cons cell (STRING . VALUE).
+The return value is VALUE from the chosen item.
+
+An ITEM may also be just a string--that makes a nonselectable item.
+An ITEM may also be nil--that means to put all preceding items
+on the left of the dialog box and all following items on the right.
+\(By default, approximately half appear on each side.) */)
+ (position, contents)
+ Lisp_Object position, contents;
+{
+ FRAME_PTR f = NULL;
+ Lisp_Object window;
+
+ check_mac ();
+
+ /* Decode the first argument: find the window or frame to use. */
+ if (EQ (position, Qt)
+ || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
+ || EQ (XCAR (position), Qtool_bar))))
+ {
+#if 0 /* Using the frame the mouse is on may not be right. */
+ /* Use the mouse's current position. */
+ FRAME_PTR new_f = SELECTED_FRAME ();
+ Lisp_Object bar_window;
+ enum scroll_bar_part part;
+ unsigned long time;
+ Lisp_Object x, y;
+
+ (*mouse_position_hook) (&new_f, 1, &bar_window, &part, &x, &y, &time);
+
+ if (new_f != 0)
+ XSETFRAME (window, new_f);
+ else
+ window = selected_window;
+#endif
+ window = selected_window;
+ }
+ else if (CONSP (position))
+ {
+ Lisp_Object tem;
+ tem = Fcar (position);
+ if (CONSP (tem))
+ window = Fcar (Fcdr (position));
+ else
+ {
+ tem = Fcar (Fcdr (position)); /* EVENT_START (position) */
+ window = Fcar (tem); /* POSN_WINDOW (tem) */
+ }
+ }
+ else if (WINDOWP (position) || FRAMEP (position))
+ window = position;
+ else
+ window = Qnil;
+
+ /* Decode where to put the menu. */
+
+ if (FRAMEP (window))
+ f = XFRAME (window);
+ else if (WINDOWP (window))
+ {
+ CHECK_LIVE_WINDOW (window);
+ f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
+ }
+ else
+ /* ??? Not really clean; should be CHECK_WINDOW_OR_FRAME,
+ but I don't want to make one now. */
+ CHECK_WINDOW (window);
+
+#ifndef HAVE_DIALOGS
+ /* Display a menu with these alternatives
+ in the middle of frame F. */
+ {
+ Lisp_Object x, y, frame, newpos;
+ XSETFRAME (frame, f);
+ XSETINT (x, x_pixel_width (f) / 2);
+ XSETINT (y, x_pixel_height (f) / 2);
+ newpos = Fcons (Fcons (x, Fcons (y, Qnil)), Fcons (frame, Qnil));
+
+ return Fx_popup_menu (newpos,
+ Fcons (Fcar (contents), Fcons (contents, Qnil)));
+ }
+#else /* HAVE_DIALOGS */
+ {
+ Lisp_Object title;
+ char *error_name;
+ Lisp_Object selection;
+
+ /* Decode the dialog items from what was specified. */
+ title = Fcar (contents);
+ CHECK_STRING (title);
+
+ list_of_panes (Fcons (contents, Qnil));
+
+ /* Display them in a dialog box. */
+ BLOCK_INPUT;
+ selection = mac_dialog_show (f, 0, title, &error_name);
+ UNBLOCK_INPUT;
+
+ discard_menu_items ();
+
+ if (error_name) error (error_name);
+ return selection;
+ }
+#endif /* HAVE_DIALOGS */
+}
+
+/* Activate the menu bar of frame F.
+ This is called from keyboard.c when it gets the
+ menu_bar_activate_event out of the Emacs event queue.
+
+ To activate the menu bar, we signal to the input thread that it can
+ return from the WM_INITMENU message, allowing the normal Windows
+ processing of the menus.
+
+ But first we recompute the menu bar contents (the whole tree).
+
+ This way we can safely execute Lisp code. */
+
+void
+x_activate_menubar (f)
+ FRAME_PTR f;
+{
+ SInt32 menu_choice;
+ extern Point saved_menu_event_location;
+
+ set_frame_menubar (f, 0, 1);
+ BLOCK_INPUT;
+
+ menu_choice = MenuSelect (saved_menu_event_location);
+ do_menu_choice (menu_choice);
+
+ UNBLOCK_INPUT;
+}
+
+/* This callback is called from the menu bar pulldown menu
+ when the user makes a selection.
+ Figure out what the user chose
+ and put the appropriate events into the keyboard buffer. */
+
+void
+menubar_selection_callback (FRAME_PTR f, int client_data)
+{
+ Lisp_Object prefix, entry;
+ Lisp_Object vector;
+ Lisp_Object *subprefix_stack;
+ int submenu_depth = 0;
+ int i;
+
+ if (!f)
+ return;
+ entry = Qnil;
+ subprefix_stack = (Lisp_Object *) alloca (f->menu_bar_items_used * sizeof (Lisp_Object));
+ vector = f->menu_bar_vector;
+ prefix = Qnil;
+ i = 0;
+ while (i < f->menu_bar_items_used)
+ {
+ if (EQ (XVECTOR (vector)->contents[i], Qnil))
+ {
+ subprefix_stack[submenu_depth++] = prefix;
+ prefix = entry;
+ i++;
+ }
+ else if (EQ (XVECTOR (vector)->contents[i], Qlambda))
+ {
+ prefix = subprefix_stack[--submenu_depth];
+ i++;
+ }
+ else if (EQ (XVECTOR (vector)->contents[i], Qt))
+ {
+ prefix = XVECTOR (vector)->contents[i + MENU_ITEMS_PANE_PREFIX];
+ i += MENU_ITEMS_PANE_LENGTH;
+ }
+ else
+ {
+ entry = XVECTOR (vector)->contents[i + MENU_ITEMS_ITEM_VALUE];
+ /* The EMACS_INT cast avoids a warning. There's no problem
+ as long as pointers have enough bits to hold small integers. */
+ if ((int) (EMACS_INT) client_data == i)
+ {
+ int j;
+ struct input_event buf;
+ Lisp_Object frame;
+
+ XSETFRAME (frame, f);
+ buf.kind = MENU_BAR_EVENT;
+ buf.frame_or_window = frame;
+ buf.arg = frame;
+ kbd_buffer_store_event (&buf);
+
+ for (j = 0; j < submenu_depth; j++)
+ if (!NILP (subprefix_stack[j]))
+ {
+ buf.kind = MENU_BAR_EVENT;
+ buf.frame_or_window = frame;
+ buf.arg = subprefix_stack[j];
+ kbd_buffer_store_event (&buf);
+ }
+
+ if (!NILP (prefix))
+ {
+ buf.kind = MENU_BAR_EVENT;
+ buf.frame_or_window = frame;
+ buf.arg = prefix;
+ kbd_buffer_store_event (&buf);
+ }
+
+ buf.kind = MENU_BAR_EVENT;
+ buf.frame_or_window = frame;
+ buf.arg = entry;
+ kbd_buffer_store_event (&buf);
+
+ f->output_data.mac->menu_command_in_progress = 0;
+ f->output_data.mac->menubar_active = 0;
+ return;
+ }
+ i += MENU_ITEMS_ITEM_LENGTH;
+ }
+ }
+ f->output_data.mac->menu_command_in_progress = 0;
+ f->output_data.mac->menubar_active = 0;
+}
+
+/* Allocate a widget_value, blocking input. */
+
+widget_value *
+xmalloc_widget_value ()
+{
+ widget_value *value;
+
+ BLOCK_INPUT;
+ value = malloc_widget_value ();
+ UNBLOCK_INPUT;
+
+ return value;
+}
+
+/* This recursively calls free_widget_value on the tree of widgets.
+ It must free all data that was malloc'ed for these widget_values.
+ In Emacs, many slots are pointers into the data of Lisp_Strings, and
+ must be left alone. */
+
+void
+free_menubar_widget_value_tree (wv)
+ widget_value *wv;
+{
+ if (! wv) return;
+
+ wv->name = wv->value = wv->key = (char *) 0xDEADBEEF;
+
+ if (wv->contents && (wv->contents != (widget_value*)1))
+ {
+ free_menubar_widget_value_tree (wv->contents);
+ wv->contents = (widget_value *) 0xDEADBEEF;
+ }
+ if (wv->next)
+ {
+ free_menubar_widget_value_tree (wv->next);
+ wv->next = (widget_value *) 0xDEADBEEF;
+ }
+ BLOCK_INPUT;
+ free_widget_value (wv);
+ UNBLOCK_INPUT;
+}
+\f
+/* Return a tree of widget_value structures for a menu bar item
+ whose event type is ITEM_KEY (with string ITEM_NAME)
+ and whose contents come from the list of keymaps MAPS. */
+
+static widget_value *
+single_submenu (item_key, item_name, maps)
+ Lisp_Object item_key, item_name, maps;
+{
+ widget_value *wv, *prev_wv, *save_wv, *first_wv;
+ int i;
+ int submenu_depth = 0;
+ Lisp_Object length;
+ int len;
+ Lisp_Object *mapvec;
+ widget_value **submenu_stack;
+ int previous_items = menu_items_used;
+ int top_level_items = 0;
+
+ length = Flength (maps);
+ len = XINT (length);
+
+ /* Convert the list MAPS into a vector MAPVEC. */
+ mapvec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
+ for (i = 0; i < len; i++)
+ {
+ mapvec[i] = Fcar (maps);
+ maps = Fcdr (maps);
+ }
+
+ menu_items_n_panes = 0;
+
+ /* Loop over the given keymaps, making a pane for each map.
+ But don't make a pane that is empty--ignore that map instead. */
+ for (i = 0; i < len; i++)
+ {
+ if (SYMBOLP (mapvec[i])
+ || (CONSP (mapvec[i]) && !KEYMAPP (mapvec[i])))
+ {
+ /* Here we have a command at top level in the menu bar
+ as opposed to a submenu. */
+ top_level_items = 1;
+ push_menu_pane (Qnil, Qnil);
+ push_menu_item (item_name, Qt, item_key, mapvec[i],
+ Qnil, Qnil, Qnil, Qnil);
+ }
+ else
+ single_keymap_panes (mapvec[i], item_name, item_key, 0, 10);
+ }
+
+ /* Create a tree of widget_value objects
+ representing the panes and their items. */
+
+ submenu_stack
+ = (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
+ wv = xmalloc_widget_value ();
+ wv->name = "menu";
+ wv->value = 0;
+ wv->enabled = 1;
+ wv->button_type = BUTTON_TYPE_NONE;
+ wv->help = Qnil;
+ first_wv = wv;
+ save_wv = 0;
+ prev_wv = 0;
+
+ /* Loop over all panes and items made during this call
+ and construct a tree of widget_value objects.
+ Ignore the panes and items made by previous calls to
+ single_submenu, even though those are also in menu_items. */
+ i = previous_items;
+ while (i < menu_items_used)
+ {
+ if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
+ {
+ submenu_stack[submenu_depth++] = save_wv;
+ save_wv = prev_wv;
+ prev_wv = 0;
+ i++;
+ }
+ else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
+ {
+ prev_wv = save_wv;
+ save_wv = submenu_stack[--submenu_depth];
+ i++;
+ }
+ else if (EQ (XVECTOR (menu_items)->contents[i], Qt)
+ && submenu_depth != 0)
+ i += MENU_ITEMS_PANE_LENGTH;
+ /* Ignore a nil in the item list.
+ It's meaningful only for dialog boxes. */
+ else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
+ i += 1;
+ else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
+ {
+ /* Create a new pane. */
+ Lisp_Object pane_name, prefix;
+ char *pane_string;
+
+ pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME];
+ prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
+
+#ifndef HAVE_MULTILINGUAL_MENU
+ if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
+ {
+ pane_name = ENCODE_SYSTEM (pane_name);
+ AREF (menu_items, i + MENU_ITEMS_PANE_NAME) = pane_name;
+ }
+#endif
+ pane_string = (NILP (pane_name)
+ ? "" : (char *) XSTRING (pane_name)->data);
+ /* If there is just one top-level pane, put all its items directly
+ under the top-level menu. */
+ if (menu_items_n_panes == 1)
+ pane_string = "";
+
+ /* If the pane has a meaningful name,
+ make the pane a top-level menu item
+ with its items as a submenu beneath it. */
+ if (strcmp (pane_string, ""))
+ {
+ wv = xmalloc_widget_value ();
+ if (save_wv)
+ save_wv->next = wv;
+ else
+ first_wv->contents = wv;
+ wv->name = pane_string;
+ /* Ignore the @ that means "separate pane".
+ This is a kludge, but this isn't worth more time. */
+ if (!NILP (prefix) && wv->name[0] == '@')
+ wv->name++;
+ wv->value = 0;
+ wv->enabled = 1;
+ wv->button_type = BUTTON_TYPE_NONE;
+ wv->help = Qnil;
+ }
+ save_wv = wv;
+ prev_wv = 0;
+ i += MENU_ITEMS_PANE_LENGTH;
+ }
+ else
+ {
+ /* Create a new item within current pane. */
+ Lisp_Object item_name, enable, descrip, def, type, selected;
+ Lisp_Object help;
+
+ item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
+ enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
+ descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
+ def = AREF (menu_items, i + MENU_ITEMS_ITEM_DEFINITION);
+ type = AREF (menu_items, i + MENU_ITEMS_ITEM_TYPE);
+ selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED);
+ help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
+
+#ifndef HAVE_MULTILINGUAL_MENU
+ if (STRING_MULTIBYTE (item_name))
+ {
+ item_name = ENCODE_SYSTEM (item_name);
+ AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name;
+ }
+
+ if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
+ {
+ descrip = ENCODE_SYSTEM (descrip);
+ AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip;
+ }
+#endif /* not HAVE_MULTILINGUAL_MENU */
+
+ wv = xmalloc_widget_value ();
+ if (prev_wv)
+ prev_wv->next = wv;
+ else
+ save_wv->contents = wv;
+
+ wv->name = (char *) XSTRING (item_name)->data;
+ if (!NILP (descrip))
+ wv->key = (char *) XSTRING (descrip)->data;
+ wv->value = 0;
+ /* The EMACS_INT cast avoids a warning. There's no problem
+ as long as pointers have enough bits to hold small integers. */
+ wv->call_data = (!NILP (def) ? (void *) (EMACS_INT) i : 0);
+ wv->enabled = !NILP (enable);
+
+ if (NILP (type))
+ wv->button_type = BUTTON_TYPE_NONE;
+ else if (EQ (type, QCradio))
+ wv->button_type = BUTTON_TYPE_RADIO;
+ else if (EQ (type, QCtoggle))
+ wv->button_type = BUTTON_TYPE_TOGGLE;
+ else
+ abort ();
+
+ wv->selected = !NILP (selected);
+ if (!STRINGP (help))
+ help = Qnil;
+
+ wv->help = help;
+
+ prev_wv = wv;
+
+ i += MENU_ITEMS_ITEM_LENGTH;
+ }
+ }
+
+ /* If we have just one "menu item"
+ that was originally a button, return it by itself. */
+ if (top_level_items && first_wv->contents && first_wv->contents->next == 0)
+ {
+ wv = first_wv->contents;
+ free_widget_value (first_wv);
+ return wv;
+ }
+
+ return first_wv;
+}
+\f
+/* Set the contents of the menubar widgets of frame F.
+ The argument FIRST_TIME is currently ignored;
+ it is set the first time this is called, from initialize_frame_menubar. */
+
+void
+set_frame_menubar (f, first_time, deep_p)
+ FRAME_PTR f;
+ int first_time;
+ int deep_p;
+{
+ int menubar_widget = f->output_data.mac->menubar_widget;
+ Lisp_Object items;
+ widget_value *wv, *first_wv, *prev_wv = 0;
+ int i;
+
+ /* We must not change the menubar when actually in use. */
+ if (f->output_data.mac->menubar_active)
+ return;
+
+ XSETFRAME (Vmenu_updating_frame, f);
+
+ if (! menubar_widget)
+ deep_p = 1;
+ else if (pending_menu_activation && !deep_p)
+ deep_p = 1;
+
+ wv = xmalloc_widget_value ();
+ wv->name = "menubar";
+ wv->value = 0;
+ wv->enabled = 1;
+ wv->button_type = BUTTON_TYPE_NONE;
+ wv->help = Qnil;
+ first_wv = wv;
+
+ if (deep_p)
+ {
+ /* Make a widget-value tree representing the entire menu trees. */
+
+ struct buffer *prev = current_buffer;
+ Lisp_Object buffer;
+ int specpdl_count = specpdl_ptr - specpdl;
+ int previous_menu_items_used = f->menu_bar_items_used;
+ Lisp_Object *previous_items
+ = (Lisp_Object *) alloca (previous_menu_items_used
+ * sizeof (Lisp_Object));
+
+ /* If we are making a new widget, its contents are empty,
+ do always reinitialize them. */
+ if (! menubar_widget)
+ previous_menu_items_used = 0;
+
+ buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer;
+ specbind (Qinhibit_quit, Qt);
+ /* Don't let the debugger step into this code
+ because it is not reentrant. */
+ specbind (Qdebug_on_next_call, Qnil);
+
+ record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
+ if (NILP (Voverriding_local_map_menu_flag))
+ {
+ specbind (Qoverriding_terminal_local_map, Qnil);
+ specbind (Qoverriding_local_map, Qnil);
+ }
+
+ set_buffer_internal_1 (XBUFFER (buffer));
+
+ /* Run the Lucid hook. */
+ safe_run_hooks (Qactivate_menubar_hook);
+ /* If it has changed current-menubar from previous value,
+ really recompute the menubar from the value. */
+ if (! NILP (Vlucid_menu_bar_dirty_flag))
+ call0 (Qrecompute_lucid_menubar);
+ safe_run_hooks (Qmenu_bar_update_hook);
+ FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
+
+ items = FRAME_MENU_BAR_ITEMS (f);
+
+ inhibit_garbage_collection ();
+
+ /* Save the frame's previous menu bar contents data. */
+ if (previous_menu_items_used)
+ bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items,
+ previous_menu_items_used * sizeof (Lisp_Object));
+
+ /* Fill in the current menu bar contents. */
+ menu_items = f->menu_bar_vector;
+ menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
+ init_menu_items ();
+ for (i = 0; i < XVECTOR (items)->size; i += 4)
+ {
+ Lisp_Object key, string, maps;
+
+ key = XVECTOR (items)->contents[i];
+ string = XVECTOR (items)->contents[i + 1];
+ maps = XVECTOR (items)->contents[i + 2];
+ if (NILP (string))
+ break;
+
+ wv = single_submenu (key, string, maps);
+ if (prev_wv)
+ prev_wv->next = wv;
+ else
+ first_wv->contents = wv;
+ /* Don't set wv->name here; GC during the loop might relocate it. */
+ wv->enabled = 1;
+ wv->button_type = BUTTON_TYPE_NONE;
+ prev_wv = wv;
+ }
+
+ finish_menu_items ();
+
+ set_buffer_internal_1 (prev);
+ unbind_to (specpdl_count, Qnil);
+
+ /* If there has been no change in the Lisp-level contents
+ of the menu bar, skip redisplaying it. Just exit. */
+
+ for (i = 0; i < previous_menu_items_used; i++)
+ if (menu_items_used == i
+ || (!Fequal (previous_items[i], XVECTOR (menu_items)->contents[i])))
+ break;
+ if (i == menu_items_used && i == previous_menu_items_used && i != 0)
+ {
+ free_menubar_widget_value_tree (first_wv);
+ menu_items = Qnil;
+
+ return;
+ }
+
+ /* Now GC cannot happen during the lifetime of the widget_value,
+ so it's safe to store data from a Lisp_String, as long as
+ local copies are made when the actual menu is created.
+ Windows takes care of this for normal string items, but
+ not for owner-drawn items or additional item-info. */
+ wv = first_wv->contents;
+ for (i = 0; i < XVECTOR (items)->size; i += 4)
+ {
+ Lisp_Object string;
+ string = XVECTOR (items)->contents[i + 1];
+ if (NILP (string))
+ break;
+ wv->name = (char *) XSTRING (string)->data;
+ wv = wv->next;
+ }
+
+ f->menu_bar_vector = menu_items;
+ f->menu_bar_items_used = menu_items_used;
+ menu_items = Qnil;
+ }
+ else
+ {
+ /* Make a widget-value tree containing
+ just the top level menu bar strings. */
+
+ items = FRAME_MENU_BAR_ITEMS (f);
+ for (i = 0; i < XVECTOR (items)->size; i += 4)
+ {
+ Lisp_Object string;
+
+ string = XVECTOR (items)->contents[i + 1];
+ if (NILP (string))
+ break;
+
+ wv = xmalloc_widget_value ();
+ wv->name = (char *) XSTRING (string)->data;
+ wv->value = 0;
+ wv->enabled = 1;
+ wv->button_type = BUTTON_TYPE_NONE;
+ wv->help = Qnil;
+ /* This prevents lwlib from assuming this
+ menu item is really supposed to be empty. */
+ /* The EMACS_INT cast avoids a warning.
+ This value just has to be different from small integers. */
+ wv->call_data = (void *) (EMACS_INT) (-1);
+
+ if (prev_wv)
+ prev_wv->next = wv;
+ else
+ first_wv->contents = wv;
+ prev_wv = wv;
+ }
+
+ /* Forget what we thought we knew about what is in the
+ detailed contents of the menu bar menus.
+ Changing the top level always destroys the contents. */
+ f->menu_bar_items_used = 0;
+ }
+
+ /* Create or update the menu bar widget. */
+
+ BLOCK_INPUT;
+
+ /* Non-null value to indicate menubar has already been "created". */
+ f->output_data.mac->menubar_widget = 1;
+
+ {
+ int i = MIN_MENU_ID;
+ MenuHandle menu = GetMenuHandle (i);
+ while (menu != NULL)
+ {
+ DeleteMenu (i);
+ DisposeMenu (menu);
+ menu = GetMenuHandle (++i);
+ }
+
+ i = MIN_SUBMENU_ID;
+ menu = GetMenuHandle (i);
+ while (menu != NULL)
+ {
+ DeleteMenu (i);
+ DisposeMenu (menu);
+ menu = GetMenuHandle (++i);
+ }
+ }
+
+ fill_menubar (first_wv->contents);
+
+ DrawMenuBar ();
+
+ free_menubar_widget_value_tree (first_wv);
+
+ UNBLOCK_INPUT;
+}
+
+/* Called from Fx_create_frame to create the initial menubar of a frame
+ before it is mapped, so that the window is mapped with the menubar already
+ there instead of us tacking it on later and thrashing the window after it
+ is visible. */
+
+void
+initialize_frame_menubar (f)
+ FRAME_PTR f;
+{
+ /* This function is called before the first chance to redisplay
+ the frame. It has to be, so the frame will have the right size. */
+ FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
+ set_frame_menubar (f, 1, 1);
+}
+
+/* Get rid of the menu bar of frame F, and free its storage.
+ This is used when deleting a frame, and when turning off the menu bar. */
+
+void
+free_frame_menubar (f)
+ FRAME_PTR f;
+{
+ f->output_data.mac->menubar_widget = NULL;
+}
+
+\f
+/* mac_menu_show actually displays a menu using the panes and items in
+ menu_items and returns the value selected from it; we assume input
+ is blocked by the caller. */
+
+/* F is the frame the menu is for.
+ X and Y are the frame-relative specified position,
+ relative to the inside upper left corner of the frame F.
+ FOR_CLICK is nonzero if this menu was invoked for a mouse click.
+ KEYMAPS is 1 if this menu was specified with keymaps;
+ in that case, we return a list containing the chosen item's value
+ and perhaps also the pane's prefix.
+ TITLE is the specified menu title.
+ ERROR is a place to store an error message string in case of failure.
+ (We return nil on failure, but the value doesn't actually matter.) */
+
+static Lisp_Object
+mac_menu_show (f, x, y, for_click, keymaps, title, error)
+ FRAME_PTR f;
+ int x;
+ int y;
+ int for_click;
+ int keymaps;
+ Lisp_Object title;
+ char **error;
+{
+ int i;
+ int menu_item_selection;
+ MenuHandle menu;
+ Point pos;
+ widget_value *wv, *save_wv = 0, *first_wv = 0, *prev_wv = 0;
+ widget_value **submenu_stack
+ = (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
+ Lisp_Object *subprefix_stack
+ = (Lisp_Object *) alloca (menu_items_used * sizeof (Lisp_Object));
+ int submenu_depth = 0;
+ int first_pane;
+
+ *error = NULL;
+
+ if (menu_items_used <= MENU_ITEMS_PANE_LENGTH)
+ {
+ *error = "Empty menu";
+ return Qnil;
+ }
+
+ /* Create a tree of widget_value objects
+ representing the panes and their items. */
+ wv = xmalloc_widget_value ();
+ wv->name = "menu";
+ wv->value = 0;
+ wv->enabled = 1;
+ wv->button_type = BUTTON_TYPE_NONE;
+ wv->help = Qnil;
+ first_wv = wv;
+ first_pane = 1;
+
+ /* Loop over all panes and items, filling in the tree. */
+ i = 0;
+ while (i < menu_items_used)
+ {
+ if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
+ {
+ submenu_stack[submenu_depth++] = save_wv;
+ save_wv = prev_wv;
+ prev_wv = 0;
+ first_pane = 1;
+ i++;
+ }
+ else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
+ {
+ prev_wv = save_wv;
+ save_wv = submenu_stack[--submenu_depth];
+ first_pane = 0;
+ i++;
+ }
+ else if (EQ (XVECTOR (menu_items)->contents[i], Qt)
+ && submenu_depth != 0)
+ i += MENU_ITEMS_PANE_LENGTH;
+ /* Ignore a nil in the item list.
+ It's meaningful only for dialog boxes. */
+ else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
+ i += 1;
+ else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
+ {
+ /* Create a new pane. */
+ Lisp_Object pane_name, prefix;
+ char *pane_string;
+ pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
+ prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
+#ifndef HAVE_MULTILINGUAL_MENU
+ if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
+ {
+ pane_name = ENCODE_SYSTEM (pane_name);
+ AREF (menu_items, i + MENU_ITEMS_PANE_NAME) = pane_name;
+ }
+#endif
+ pane_string = (NILP (pane_name)
+ ? "" : (char *) XSTRING (pane_name)->data);
+ /* If there is just one top-level pane, put all its items directly
+ under the top-level menu. */
+ if (menu_items_n_panes == 1)
+ pane_string = "";
+
+ /* If the pane has a meaningful name,
+ make the pane a top-level menu item
+ with its items as a submenu beneath it. */
+ if (!keymaps && strcmp (pane_string, ""))
+ {
+ wv = xmalloc_widget_value ();
+ if (save_wv)
+ save_wv->next = wv;
+ else
+ first_wv->contents = wv;
+ wv->name = pane_string;
+ if (keymaps && !NILP (prefix))
+ wv->name++;
+ wv->value = 0;
+ wv->enabled = 1;
+ wv->button_type = BUTTON_TYPE_NONE;
+ wv->help = Qnil;
+ save_wv = wv;
+ prev_wv = 0;
+ }
+ else if (first_pane)
+ {
+ save_wv = wv;
+ prev_wv = 0;
+ }
+ first_pane = 0;
+ i += MENU_ITEMS_PANE_LENGTH;
+ }
+ else
+ {
+ /* Create a new item within current pane. */
+ Lisp_Object item_name, enable, descrip, def, type, selected, help;
+
+ item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
+ enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
+ descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
+ def = AREF (menu_items, i + MENU_ITEMS_ITEM_DEFINITION);
+ type = AREF (menu_items, i + MENU_ITEMS_ITEM_TYPE);
+ selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED);
+ help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
+
+#ifndef HAVE_MULTILINGUAL_MENU
+ if (STRINGP (item_name) && STRING_MULTIBYTE (item_name))
+ {
+ item_name = ENCODE_SYSTEM (item_name);
+ AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name;
+ }
+ if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
+ {
+ descrip = ENCODE_SYSTEM (descrip);
+ AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip;
+ }
+#endif /* not HAVE_MULTILINGUAL_MENU */
+
+ wv = xmalloc_widget_value ();
+ if (prev_wv)
+ prev_wv->next = wv;
+ else
+ save_wv->contents = wv;
+ wv->name = (char *) XSTRING (item_name)->data;
+ if (!NILP (descrip))
+ wv->key = (char *) XSTRING (descrip)->data;
+ wv->value = 0;
+ /* Use the contents index as call_data, since we are
+ restricted to 16-bits. */
+ wv->call_data = !NILP (def) ? (void *) (EMACS_INT) i : 0;
+ wv->enabled = !NILP (enable);
+
+ if (NILP (type))
+ wv->button_type = BUTTON_TYPE_NONE;
+ else if (EQ (type, QCtoggle))
+ wv->button_type = BUTTON_TYPE_TOGGLE;
+ else if (EQ (type, QCradio))
+ wv->button_type = BUTTON_TYPE_RADIO;
+ else
+ abort ();
+
+ wv->selected = !NILP (selected);
+ if (!STRINGP (help))
+ help = Qnil;
+
+ wv->help = help;
+
+ prev_wv = wv;
+
+ i += MENU_ITEMS_ITEM_LENGTH;
+ }
+ }
+
+ /* Deal with the title, if it is non-nil. */
+ if (!NILP (title))
+ {
+ widget_value *wv_title = xmalloc_widget_value ();
+ widget_value *wv_sep = xmalloc_widget_value ();
+
+ /* Maybe replace this separator with a bitmap or owner-draw item
+ so that it looks better. Having two separators looks odd. */
+ wv_sep->name = "--";
+ wv_sep->next = first_wv->contents;
+ wv_sep->help = Qnil;
+
+#ifndef HAVE_MULTILINGUAL_MENU
+ if (STRING_MULTIBYTE (title))
+ title = ENCODE_SYSTEM (title);
+#endif
+ wv_title->name = (char *) XSTRING (title)->data;
+ wv_title->enabled = TRUE;
+ wv_title->title = TRUE;
+ wv_title->button_type = BUTTON_TYPE_NONE;
+ wv_title->help = Qnil;
+ wv_title->next = wv_sep;
+ first_wv->contents = wv_title;
+ }
+
+ /* Actually create the menu. */
+ menu = NewMenu (POPUP_SUBMENU_ID, "\p");
+ fill_submenu (menu, first_wv->contents, 0);
+
+ /* Adjust coordinates to be root-window-relative. */
+ pos.h = x;
+ pos.v = y;
+
+#if TARGET_API_MAC_CARBON
+ SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
+#else
+ SetPort (FRAME_MAC_WINDOW (f));
+#endif
+
+ LocalToGlobal (&pos);
+
+ /* No selection has been chosen yet. */
+ menu_item_selection = 0;
+
+ InsertMenu (menu, -1);
+
+ /* Display the menu. */
+ menu_item_selection = LoWord (PopUpMenuSelect (menu, pos.v, pos.h, 0));
+
+ DeleteMenu (POPUP_SUBMENU_ID);
+
+#if 0
+ /* Clean up extraneous mouse events which might have been generated
+ during the call. */
+ discard_mouse_events ();
+#endif
+
+ /* Free the widget_value objects we used to specify the
+ contents. */
+ free_menubar_widget_value_tree (first_wv);
+
+ DisposeMenu (menu);
+
+ /* Find the selected item, and its pane, to return
+ the proper value. */
+ if (menu_item_selection != 0)
+ {
+ Lisp_Object prefix, entry;
+
+ prefix = entry = Qnil;
+ i = 0;
+ while (i < menu_items_used)
+ {
+ if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
+ {
+ subprefix_stack[submenu_depth++] = prefix;
+ prefix = entry;
+ i++;
+ }
+ else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
+ {
+ prefix = subprefix_stack[--submenu_depth];
+ i++;
+ }
+ else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
+ {
+ prefix
+ = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
+ i += MENU_ITEMS_PANE_LENGTH;
+ }
+ /* Ignore a nil in the item list.
+ It's meaningful only for dialog boxes. */
+ else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
+ i += 1;
+ else
+ {
+ entry
+ = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
+ if (menu_item_selection == i)
+ {
+ if (keymaps != 0)
+ {
+ int j;
+
+ entry = Fcons (entry, Qnil);
+ if (!NILP (prefix))
+ entry = Fcons (prefix, entry);
+ for (j = submenu_depth - 1; j >= 0; j--)
+ if (!NILP (subprefix_stack[j]))
+ entry = Fcons (subprefix_stack[j], entry);
+ }
+ return entry;
+ }
+ i += MENU_ITEMS_ITEM_LENGTH;
+ }
+ }
+ }
+
+ return Qnil;
+}
+\f
+
+#ifdef HAVE_DIALOGS
+/* Construct native Mac OS menubar based on widget_value tree. */
+
+static int
+mac_dialog (widget_value *wv)
+{
+ char *dialog_name;
+ char *prompt;
+ char **button_labels;
+ UInt32 *ref_cons;
+ int nb_buttons;
+ int left_count;
+ int i;
+ int dialog_width;
+ Rect rect;
+ WindowPtr window_ptr;
+ ControlHandle ch;
+ int left;
+ EventRecord event_record;
+ SInt16 part_code;
+ int control_part_code;
+ Point mouse;
+
+ dialog_name = wv->name;
+ nb_buttons = dialog_name[1] - '0';
+ left_count = nb_buttons - (dialog_name[4] - '0');
+ button_labels = (char **) alloca (sizeof (char *) * nb_buttons);
+ ref_cons = (UInt32 *) alloca (sizeof (UInt32) * nb_buttons);
+
+ wv = wv->contents;
+ prompt = (char *) alloca (strlen (wv->value) + 1);
+ strcpy (prompt, wv->value);
+ c2pstr (prompt);
+
+ wv = wv->next;
+ for (i = 0; i < nb_buttons; i++)
+ {
+ button_labels[i] = wv->value;
+ button_labels[i] = (char *) alloca (strlen (wv->value) + 1);
+ strcpy (button_labels[i], wv->value);
+ c2pstr (button_labels[i]);
+ ref_cons[i] = (UInt32) wv->call_data;
+ wv = wv->next;
+ }
+
+ window_ptr = GetNewCWindow (DIALOG_WINDOW_RESOURCE, NULL, (WindowPtr) -1);
+
+#if TARGET_API_MAC_CARBON
+ SetPort (GetWindowPort (window_ptr));
+#else
+ SetPort (window_ptr);
+#endif
+
+ TextFont (0);
+ /* Left and right margins in the dialog are 13 pixels each.*/
+ dialog_width = 14;
+ /* Calculate width of dialog box: 8 pixels on each side of the text
+ label in each button, 12 pixels between buttons. */
+ for (i = 0; i < nb_buttons; i++)
+ dialog_width += StringWidth (button_labels[i]) + 16 + 12;
+
+ if (left_count != 0 && nb_buttons - left_count != 0)
+ dialog_width += 12;
+
+ dialog_width = max (dialog_width, StringWidth (prompt) + 26);
+
+ SizeWindow (window_ptr, dialog_width, 78, 0);
+ ShowWindow (window_ptr);
+
+#if TARGET_API_MAC_CARBON
+ SetPort (GetWindowPort (window_ptr));
+#else
+ SetPort (window_ptr);
+#endif
+
+ TextFont (0);
+
+ MoveTo (13, 29);
+ DrawString (prompt);
+
+ left = 13;
+ for (i = 0; i < nb_buttons; i++)
+ {
+ int button_width = StringWidth (button_labels[i]) + 16;
+ SetRect (&rect, left, 45, left + button_width, 65);
+ ch = NewControl (window_ptr, &rect, button_labels[i], 1, 0, 0, 0,
+ kControlPushButtonProc, ref_cons[i]);
+ left += button_width + 12;
+ if (i == left_count - 1)
+ left += 12;
+ }
+
+ i = 0;
+ while (!i)
+ {
+ if (WaitNextEvent (mDownMask, &event_record, 10, NULL))
+ if (event_record.what == mouseDown)
+ {
+ part_code = FindWindow (event_record.where, &window_ptr);
+ if (part_code == inContent)
+ {
+ mouse = event_record.where;
+ GlobalToLocal (&mouse);
+ control_part_code = FindControl (mouse, window_ptr, &ch);
+ if (control_part_code == kControlButtonPart)
+ if (TrackControl (ch, mouse, NULL))
+ i = GetControlReference (ch);
+ }
+ }
+ }
+
+ DisposeWindow (window_ptr);
+
+ return i;
+}
+
+static char * button_names [] = {
+ "button1", "button2", "button3", "button4", "button5",
+ "button6", "button7", "button8", "button9", "button10" };
+
+static Lisp_Object
+mac_dialog_show (f, keymaps, title, error)
+ FRAME_PTR f;
+ int keymaps;
+ Lisp_Object title;
+ char **error;
+{
+ int i, nb_buttons=0;
+ char dialog_name[6];
+ int menu_item_selection;
+
+ widget_value *wv, *first_wv = 0, *prev_wv = 0;
+
+ /* Number of elements seen so far, before boundary. */
+ int left_count = 0;
+ /* 1 means we've seen the boundary between left-hand elts and right-hand. */
+ int boundary_seen = 0;
+
+ *error = NULL;
+
+ if (menu_items_n_panes > 1)
+ {
+ *error = "Multiple panes in dialog box";
+ return Qnil;
+ }
+
+ /* Create a tree of widget_value objects
+ representing the text label and buttons. */
+ {
+ Lisp_Object pane_name, prefix;
+ char *pane_string;
+ pane_name = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME];
+ prefix = XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_PREFIX];
+ pane_string = (NILP (pane_name)
+ ? "" : (char *) XSTRING (pane_name)->data);
+ prev_wv = xmalloc_widget_value ();
+ prev_wv->value = pane_string;
+ if (keymaps && !NILP (prefix))
+ prev_wv->name++;
+ prev_wv->enabled = 1;
+ prev_wv->name = "message";
+ prev_wv->help = Qnil;
+ first_wv = prev_wv;
+
+ /* Loop over all panes and items, filling in the tree. */
+ i = MENU_ITEMS_PANE_LENGTH;
+ while (i < menu_items_used)
+ {
+
+ /* Create a new item within current pane. */
+ Lisp_Object item_name, enable, descrip, help;
+
+ item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
+ enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
+ descrip
+ = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
+ help = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_HELP];
+
+ if (NILP (item_name))
+ {
+ free_menubar_widget_value_tree (first_wv);
+ *error = "Submenu in dialog items";
+ return Qnil;
+ }
+ if (EQ (item_name, Qquote))
+ {
+ /* This is the boundary between left-side elts
+ and right-side elts. Stop incrementing right_count. */
+ boundary_seen = 1;
+ i++;
+ continue;
+ }
+ if (nb_buttons >= 9)
+ {
+ free_menubar_widget_value_tree (first_wv);
+ *error = "Too many dialog items";
+ return Qnil;
+ }
+
+ wv = xmalloc_widget_value ();
+ prev_wv->next = wv;
+ wv->name = (char *) button_names[nb_buttons];
+ if (!NILP (descrip))
+ wv->key = (char *) XSTRING (descrip)->data;
+ wv->value = (char *) XSTRING (item_name)->data;
+ wv->call_data = (void *) i;
+ /* menu item is identified by its index in menu_items table */
+ wv->enabled = !NILP (enable);
+ wv->help = Qnil;
+ prev_wv = wv;
+
+ if (! boundary_seen)
+ left_count++;
+
+ nb_buttons++;
+ i += MENU_ITEMS_ITEM_LENGTH;
+ }
+
+ /* If the boundary was not specified,
+ by default put half on the left and half on the right. */
+ if (! boundary_seen)
+ left_count = nb_buttons - nb_buttons / 2;
+
+ wv = xmalloc_widget_value ();
+ wv->name = dialog_name;
+ wv->help = Qnil;
+
+ /* Dialog boxes use a really stupid name encoding
+ which specifies how many buttons to use
+ and how many buttons are on the right.
+ The Q means something also. */
+ dialog_name[0] = 'Q';
+ dialog_name[1] = '0' + nb_buttons;
+ dialog_name[2] = 'B';
+ dialog_name[3] = 'R';
+ /* Number of buttons to put on the right. */
+ dialog_name[4] = '0' + nb_buttons - left_count;
+ dialog_name[5] = 0;
+ wv->contents = first_wv;
+ first_wv = wv;
+ }
+
+ /* Actually create the dialog. */
+#ifdef HAVE_DIALOGS
+ menu_item_selection = mac_dialog (first_wv);
+#else
+ menu_item_selection = 0;
+#endif
+
+ /* Free the widget_value objects we used to specify the contents. */
+ free_menubar_widget_value_tree (first_wv);
+
+ /* Find the selected item, and its pane, to return the proper
+ value. */
+ if (menu_item_selection != 0)
+ {
+ Lisp_Object prefix;
+
+ prefix = Qnil;
+ i = 0;
+ while (i < menu_items_used)
+ {
+ Lisp_Object entry;
+
+ if (EQ (XVECTOR (menu_items)->contents[i], Qt))
+ {
+ prefix
+ = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
+ i += MENU_ITEMS_PANE_LENGTH;
+ }
+ else
+ {
+ entry
+ = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
+ if (menu_item_selection == i)
+ {
+ if (keymaps != 0)
+ {
+ entry = Fcons (entry, Qnil);
+ if (!NILP (prefix))
+ entry = Fcons (prefix, entry);
+ }
+ return entry;
+ }
+ i += MENU_ITEMS_ITEM_LENGTH;
+ }
+ }
+ }
+
+ return Qnil;
+}
+#endif /* HAVE_DIALOGS */
+\f
+
+/* Is this item a separator? */
+static int
+name_is_separator (name)
+ char *name;
+{
+ char *start = name;
+
+ /* Check if name string consists of only dashes ('-'). */
+ while (*name == '-') name++;
+ /* Separators can also be of the form "--:TripleSuperMegaEtched"
+ or "--deep-shadow". We don't implement them yet, se we just treat
+ them like normal separators. */
+ return (*name == '\0' || start + 2 == name);
+}
+
+static void
+add_menu_item (MenuHandle menu, widget_value *wv, int submenu, int indent,
+ int force_disable)
+{
+ Str255 item_name;
+ int pos, i;
+
+ if (name_is_separator (wv->name))
+ AppendMenu (menu, "\p-");
+ else
+ {
+ AppendMenu (menu, "\pX");
+
+#if TARGET_API_MAC_CARBON
+ pos = CountMenuItems (menu);
+#else
+ pos = CountMItems (menu);
+#endif
+
+ strcpy (item_name, "");
+ for (i = 0; i < indent; i++)
+ strcat (item_name, " ");
+ strcat (item_name, wv->name);
+ if (wv->key != NULL)
+ {
+ strcat (item_name, " ");
+ strcat (item_name, wv->key);
+ }
+ c2pstr (item_name);
+ SetMenuItemText (menu, pos, item_name);
+
+ if (wv->enabled && !force_disable)
+#if TARGET_API_MAC_CARBON
+ EnableMenuItem (menu, pos);
+#else
+ EnableItem (menu, pos);
+#endif
+ else
+#if TARGET_API_MAC_CARBON
+ DisableMenuItem (menu, pos);
+#else
+ DisableItem (menu, pos);
+#endif
+
+ /* Draw radio buttons and tickboxes. */
+ {
+ if (wv->selected && (wv->button_type == BUTTON_TYPE_TOGGLE ||
+ wv->button_type == BUTTON_TYPE_RADIO))
+ SetItemMark (menu, pos, checkMark);
+ else
+ SetItemMark (menu, pos, noMark);
+ }
+ }
+
+ SetMenuItemRefCon (menu, pos, (UInt32) wv->call_data);
+
+ if (submenu != NULL)
+ SetMenuItemHierarchicalID (menu, pos, submenu);
+}
+
+static int submenu_id;
+
+/* Construct native Mac OS menubar based on widget_value tree. */
+
+static void
+fill_submenu (MenuHandle menu, widget_value *wv, int indent)
+{
+ for ( ; wv != NULL; wv = wv->next)
+ if (wv->contents)
+ {
+ add_menu_item (menu, wv, NULL, indent, 1);
+
+ fill_submenu (menu, wv->contents, indent + 1);
+ }
+ else
+ add_menu_item (menu, wv, NULL, indent, 0);
+}
+
+
+/* Construct native Mac OS menu based on widget_value tree. */
+
+static void
+fill_menu (MenuHandle menu, widget_value *wv)
+{
+ for ( ; wv != NULL; wv = wv->next)
+ if (wv->contents)
+ {
+ MenuHandle submenu = NewMenu (submenu_id, "\pX");
+ fill_submenu (submenu, wv->contents, 0);
+ InsertMenu (submenu, -1);
+ add_menu_item (menu, wv, submenu_id, 0, 0);
+ submenu_id++;
+ }
+ else
+ add_menu_item (menu, wv, NULL, 0, 0);
+}
+
+/* Construct native Mac OS menubar based on widget_value tree. */
+
+static void
+fill_menubar (widget_value *wv)
+{
+ int id;
+
+ submenu_id = MIN_SUBMENU_ID;
+
+ for (id = MIN_MENU_ID; wv != NULL; wv = wv->next, id++)
+ {
+ MenuHandle menu;
+ Str255 title;
+
+ strcpy (title, wv->name);
+ c2pstr (title);
+ menu = NewMenu (id, title);
+
+ if (wv->contents)
+ fill_menu (menu, wv->contents);
+
+ InsertMenu (menu, 0);
+ }
+}
+
+#endif /* HAVE_MENUS */
+
+\f
+void
+syms_of_macmenu ()
+{
+ staticpro (&menu_items);
+ menu_items = Qnil;
+
+ Qdebug_on_next_call = intern ("debug-on-next-call");
+ staticpro (&Qdebug_on_next_call);
+
+ DEFVAR_LISP ("menu-updating-frame", &Vmenu_updating_frame,
+ doc: /* Frame for which we are updating a menu.
+The enable predicate for a menu command should check this variable. */);
+ Vmenu_updating_frame = Qnil;
+
+ defsubr (&Sx_popup_menu);
+#ifdef HAVE_MENUS
+ defsubr (&Sx_popup_dialog);
+#endif
+}
--- /dev/null
+/* Implementation of GUI terminal on the Mac OS.
+ Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Contributed by Andrew Choi (akochoi@mac.com). */
+
+#include <config.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "lisp.h"
+#include "charset.h"
+#include "blockinput.h"
+
+#include "macterm.h"
+
+#ifndef MAC_OSX
+#include <alloca.h>
+#endif
+
+#ifdef MAC_OSX
+#undef mktime
+#undef DEBUG
+#undef free
+#undef malloc
+#undef realloc
+/* Macros max and min defined in lisp.h conflict with those in
+ precompiled header Carbon.h. */
+#undef max
+#undef min
+#include <Carbon/Carbon.h>
+#undef free
+#define free unexec_free
+#undef malloc
+#define malloc unexec_malloc
+#undef realloc
+#define realloc unexec_realloc
+#undef min
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#undef max
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#else /* not MAC_OSX */
+#include <Quickdraw.h>
+#include <ToolUtils.h>
+#include <Sound.h>
+#include <Events.h>
+#include <Script.h>
+#include <Resources.h>
+#include <Fonts.h>
+#include <TextUtils.h>
+#include <LowMem.h>
+#include <Controls.h>
+#if defined (__MRC__) || (__MSL__ >= 0x6000)
+#include <ControlDefinitions.h>
+#endif
+#include <Gestalt.h>
+
+#if __profile__
+#include <profiler.h>
+#endif
+#endif /* not MAC_OSX */
+
+#include "systty.h"
+#include "systime.h"
+#include "atimer.h"
+#include "keymap.h"
+
+#include <ctype.h>
+#include <errno.h>
+#include <setjmp.h>
+#include <sys/stat.h>
+
+#include "keyboard.h"
+#include "frame.h"
+#include "dispextern.h"
+#include "fontset.h"
+#include "termhooks.h"
+#include "termopts.h"
+#include "termchar.h"
+#include "gnu.h"
+#include "disptab.h"
+#include "buffer.h"
+#include "window.h"
+#include "intervals.h"
+#include "composite.h"
+#include "coding.h"
+
+#define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
+
+\f
+/* Fringe bitmaps. */
+
+enum fringe_bitmap_type
+{
+ NO_FRINGE_BITMAP,
+ LEFT_TRUNCATION_BITMAP,
+ RIGHT_TRUNCATION_BITMAP,
+ OVERLAY_ARROW_BITMAP,
+ CONTINUED_LINE_BITMAP,
+ CONTINUATION_LINE_BITMAP,
+ ZV_LINE_BITMAP
+};
+
+/* Bitmap drawn to indicate lines not displaying text if
+ `indicate-empty-lines' is non-nil. */
+
+#define zv_width 8
+#define zv_height 72
+#define zv_period 3
+static unsigned char zv_bits[] = {
+ 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+ 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+ 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+ 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+ 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+ 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+ 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
+ 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
+
+/* An arrow like this: `<-'. */
+
+#define left_width 8
+#define left_height 8
+static unsigned char left_bits[] = {
+ 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
+
+/* Right truncation arrow bitmap `->'. */
+
+#define right_width 8
+#define right_height 8
+static unsigned char right_bits[] = {
+ 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
+
+/* Marker for continued lines. */
+
+#define continued_width 8
+#define continued_height 8
+static unsigned char continued_bits[] = {
+ 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
+
+/* Marker for continuation lines. */
+
+#define continuation_width 8
+#define continuation_height 8
+static unsigned char continuation_bits[] = {
+ 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
+
+/* Overlay arrow bitmap. */
+
+#if 0
+/* A bomb. */
+#define ov_width 8
+#define ov_height 8
+static unsigned char ov_bits[] = {
+ 0x0c, 0x10, 0x3c, 0x7e, 0x5e, 0x5e, 0x46, 0x3c};
+#else
+/* A triangular arrow. */
+#define ov_width 8
+#define ov_height 8
+static unsigned char ov_bits[] = {
+ 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
+#endif
+
+extern Lisp_Object Qhelp_echo;
+
+\f
+/* Non-nil means Emacs uses toolkit scroll bars. */
+
+Lisp_Object Vx_toolkit_scroll_bars;
+
+/* If a string, XTread_socket generates an event to display that string.
+ (The display is done in read_char.) */
+
+static Lisp_Object help_echo;
+static Lisp_Object help_echo_window;
+static Lisp_Object help_echo_object;
+static int help_echo_pos;
+
+/* Temporary variable for XTread_socket. */
+
+static Lisp_Object previous_help_echo;
+
+/* Non-zero means that a HELP_EVENT has been generated since Emacs
+ start. */
+
+static int any_help_event_p;
+
+/* Non-zero means autoselect window with the mouse cursor. */
+
+int x_autoselect_window_p;
+
+/* Non-zero means draw block and hollow cursor as wide as the glyph
+ under it. For example, if a block cursor is over a tab, it will be
+ drawn as wide as that tab on the display. */
+
+int x_stretch_cursor_p;
+
+/* Non-zero means make use of UNDERLINE_POSITION font properties. */
+
+int x_use_underline_position_properties;
+
+/* This is a chain of structures for all the X displays currently in
+ use. */
+
+struct x_display_info *x_display_list;
+
+/* This is a list of cons cells, each of the form (NAME
+ . FONT-LIST-CACHE), one for each element of x_display_list and in
+ the same order. NAME is the name of the frame. FONT-LIST-CACHE
+ records previous values returned by x-list-fonts. */
+
+Lisp_Object x_display_name_list;
+
+/* This is display since Mac does not support multiple ones. */
+struct mac_display_info one_mac_display_info;
+
+/* Frame being updated by update_frame. This is declared in term.c.
+ This is set by update_begin and looked at by all the XT functions.
+ It is zero while not inside an update. In that case, the XT
+ functions assume that `selected_frame' is the frame to apply to. */
+
+extern struct frame *updating_frame;
+
+extern int waiting_for_input;
+
+/* This is a frame waiting to be auto-raised, within XTread_socket. */
+
+struct frame *pending_autoraise_frame;
+
+/* Nominal cursor position -- where to draw output.
+ HPOS and VPOS are window relative glyph matrix coordinates.
+ X and Y are window relative pixel coordinates. */
+
+struct cursor_pos output_cursor;
+
+/* Non-zero means user is interacting with a toolkit scroll bar. */
+
+static int toolkit_scroll_bar_interaction;
+
+/* Mouse movement.
+
+ Formerly, we used PointerMotionHintMask (in standard_event_mask)
+ so that we would have to call XQueryPointer after each MotionNotify
+ event to ask for another such event. However, this made mouse tracking
+ slow, and there was a bug that made it eventually stop.
+
+ Simply asking for MotionNotify all the time seems to work better.
+
+ In order to avoid asking for motion events and then throwing most
+ of them away or busy-polling the server for mouse positions, we ask
+ the server for pointer motion hints. This means that we get only
+ one event per group of mouse movements. "Groups" are delimited by
+ other kinds of events (focus changes and button clicks, for
+ example), or by XQueryPointer calls; when one of these happens, we
+ get another MotionNotify event the next time the mouse moves. This
+ is at least as efficient as getting motion events when mouse
+ tracking is on, and I suspect only negligibly worse when tracking
+ is off. */
+
+/* Where the mouse was last time we reported a mouse event. */
+
+FRAME_PTR last_mouse_frame;
+static Rect last_mouse_glyph;
+static Lisp_Object last_mouse_press_frame;
+
+/* The scroll bar in which the last X motion event occurred.
+
+ If the last X motion event occurred in a scroll bar, we set this so
+ XTmouse_position can know whether to report a scroll bar motion or
+ an ordinary motion.
+
+ If the last X motion event didn't occur in a scroll bar, we set
+ this to Qnil, to tell XTmouse_position to return an ordinary motion
+ event. */
+
+static Lisp_Object last_mouse_scroll_bar;
+
+/* This is a hack. We would really prefer that XTmouse_position would
+ return the time associated with the position it returns, but there
+ doesn't seem to be any way to wrest the time-stamp from the server
+ along with the position query. So, we just keep track of the time
+ of the last movement we received, and return that in hopes that
+ it's somewhat accurate. */
+
+static Time last_mouse_movement_time;
+
+enum mouse_tracking_type {
+ mouse_tracking_none,
+ mouse_tracking_mouse_movement,
+ mouse_tracking_scroll_bar
+};
+
+enum mouse_tracking_type mouse_tracking_in_progress = mouse_tracking_none;
+
+struct scroll_bar *tracked_scroll_bar = NULL;
+
+/* Incremented by XTread_socket whenever it really tries to read
+ events. */
+
+#ifdef __STDC__
+static int volatile input_signal_count;
+#else
+static int input_signal_count;
+#endif
+
+/* Used locally within XTread_socket. */
+
+static int x_noop_count;
+
+/* Initial values of argv and argc. */
+
+extern char **initial_argv;
+extern int initial_argc;
+
+extern Lisp_Object Vcommand_line_args, Vsystem_name;
+
+/* Tells if a window manager is present or not. */
+
+extern Lisp_Object Vx_no_window_manager;
+
+extern Lisp_Object Qface, Qmouse_face;
+
+extern int errno;
+
+/* A mask of extra modifier bits to put into every keyboard char. */
+
+extern int extra_keyboard_modifiers;
+
+static Lisp_Object Qvendor_specific_keysyms;
+
+#if 0
+extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
+#endif
+
+extern Lisp_Object x_icon_type P_ ((struct frame *));
+
+
+#if __MRC__
+QDGlobals qd; /* QuickDraw global information structure. */
+#endif
+
+
+/* Enumeration for overriding/changing the face to use for drawing
+ glyphs in x_draw_glyphs. */
+
+enum draw_glyphs_face
+{
+ DRAW_NORMAL_TEXT,
+ DRAW_INVERSE_VIDEO,
+ DRAW_CURSOR,
+ DRAW_MOUSE_FACE,
+ DRAW_IMAGE_RAISED,
+ DRAW_IMAGE_SUNKEN
+};
+
+struct frame * x_window_to_frame (struct mac_display_info *, WindowPtr);
+struct mac_display_info *mac_display_info_for_display (Display *);
+static void x_update_window_end P_ ((struct window *, int, int));
+static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
+static int fast_find_position P_ ((struct window *, int, int *, int *,
+ int *, int *, Lisp_Object));
+static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
+ int *, int *, int *, int *, int));
+static void set_output_cursor P_ ((struct cursor_pos *));
+static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
+ int *, int *, int *, int));
+static void note_mode_line_highlight P_ ((struct window *, int, int));
+static void note_mouse_highlight P_ ((struct frame *, int, int));
+static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
+static void x_handle_tool_bar_click P_ ((struct frame *, EventRecord *));
+static void show_mouse_face P_ ((struct x_display_info *,
+ enum draw_glyphs_face));
+static int cursor_in_mouse_face_p P_ ((struct window *));
+static int clear_mouse_face P_ ((struct mac_display_info *));
+static int x_io_error_quitter P_ ((Display *));
+int x_catch_errors P_ ((Display *));
+void x_uncatch_errors P_ ((Display *, int));
+void x_lower_frame P_ ((struct frame *));
+void x_scroll_bar_clear P_ ((struct frame *));
+int x_had_errors_p P_ ((Display *));
+void x_wm_set_size_hint P_ ((struct frame *, long, int));
+void x_raise_frame P_ ((struct frame *));
+void x_set_window_size P_ ((struct frame *, int, int, int));
+void x_wm_set_window_state P_ ((struct frame *, int));
+void x_wm_set_icon_pixmap P_ ((struct frame *, int));
+void mac_initialize P_ ((void));
+static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
+static int x_compute_min_glyph_bounds P_ ((struct frame *));
+enum text_cursor_kinds x_specified_cursor_type P_ ((Lisp_Object, int *));
+static void x_draw_phys_cursor_glyph P_ ((struct window *,
+ struct glyph_row *,
+ enum draw_glyphs_face));
+static void x_update_end P_ ((struct frame *));
+static void XTframe_up_to_date P_ ((struct frame *));
+static void XTreassert_line_highlight P_ ((int, int));
+static void x_change_line_highlight P_ ((int, int, int, int));
+static void XTset_terminal_modes P_ ((void));
+static void XTreset_terminal_modes P_ ((void));
+static void XTcursor_to P_ ((int, int, int, int));
+static void x_write_glyphs P_ ((struct glyph *, int));
+static void x_clear_end_of_line P_ ((int));
+static void x_clear_frame P_ ((void));
+static void x_clear_cursor P_ ((struct window *));
+static void frame_highlight P_ ((struct frame *));
+static void frame_unhighlight P_ ((struct frame *));
+static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
+static void XTframe_rehighlight P_ ((struct frame *));
+static void x_frame_rehighlight P_ ((struct x_display_info *));
+static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
+static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
+static int x_intersect_rectangles P_ ((Rect *, Rect *, Rect *));
+static void expose_frame P_ ((struct frame *, int, int, int, int));
+static int expose_window_tree P_ ((struct window *, Rect *));
+static int expose_window P_ ((struct window *, Rect *));
+static void expose_area P_ ((struct window *, struct glyph_row *,
+ Rect *, enum glyph_row_area));
+static int expose_line P_ ((struct window *, struct glyph_row *,
+ Rect *));
+void x_display_cursor (struct window *, int, int, int, int, int);
+void x_update_cursor P_ ((struct frame *, int));
+static void x_update_cursor_in_window_tree P_ ((struct window *, int));
+static void x_update_window_cursor P_ ((struct window *, int));
+static void x_erase_phys_cursor P_ ((struct window *));
+void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
+static void x_draw_fringe_bitmap P_ ((struct window *, struct glyph_row *,
+ enum fringe_bitmap_type, int left_p));
+static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
+ GC, int));
+static int x_phys_cursor_in_rect_p P_ ((struct window *, Rect *));
+static void x_draw_row_fringe_bitmaps P_ ((struct window *, struct glyph_row *));
+static void notice_overwritten_cursor P_ ((struct window *,
+ enum glyph_row_area,
+ int, int, int, int));
+static void x_flush P_ ((struct frame *f));
+static void x_update_begin P_ ((struct frame *));
+static void x_update_window_begin P_ ((struct window *));
+static void x_draw_vertical_border P_ ((struct window *));
+static void x_after_update_window_line P_ ((struct glyph_row *));
+static INLINE void take_vertical_position_into_account P_ ((struct it *));
+static void x_produce_stretch_glyph P_ ((struct it *));
+
+static void activate_scroll_bars (FRAME_PTR);
+static void deactivate_scroll_bars (FRAME_PTR);
+
+extern int image_ascent (struct image *, struct face *);
+void x_set_offset (struct frame *, int, int, int);
+int x_bitmap_icon (struct frame *, Lisp_Object);
+void x_make_frame_visible (struct frame *);
+
+extern void window_scroll (Lisp_Object, int, int, int);
+
+/* Defined in macmenu.h. */
+extern void menubar_selection_callback (FRAME_PTR, int);
+extern void set_frame_menubar (FRAME_PTR, int, int);
+
+/* X display function emulation */
+
+/* Structure borrowed from Xlib.h to represent two-byte characters in
+ dumpglyphs. */
+
+typedef struct {
+ unsigned char byte1;
+ unsigned char byte2;
+} XChar2b;
+
+static void
+XFreePixmap (display, pixmap)
+ Display *display;
+ Pixmap pixmap;
+{
+ PixMap *p = (PixMap *) pixmap;
+
+ xfree (p->baseAddr);
+ xfree (p);
+}
+
+
+/* Set foreground color for subsequent QuickDraw commands. Assume
+ graphic port has already been set. */
+
+static void
+mac_set_forecolor (unsigned long color)
+{
+ RGBColor fg_color;
+
+ fg_color.red = RED_FROM_ULONG (color) * 256;
+ fg_color.green = GREEN_FROM_ULONG (color) * 256;
+ fg_color.blue = BLUE_FROM_ULONG (color) * 256;
+
+ RGBForeColor (&fg_color);
+}
+
+
+/* Set background color for subsequent QuickDraw commands. Assume
+ graphic port has already been set. */
+
+static void
+mac_set_backcolor (unsigned long color)
+{
+ RGBColor bg_color;
+
+ bg_color.red = RED_FROM_ULONG (color) * 256;
+ bg_color.green = GREEN_FROM_ULONG (color) * 256;
+ bg_color.blue = BLUE_FROM_ULONG (color) * 256;
+
+ RGBBackColor (&bg_color);
+}
+
+/* Set foreground and background color for subsequent QuickDraw
+ commands. Assume that the graphic port has already been set. */
+
+static void
+mac_set_colors (GC gc)
+{
+ mac_set_forecolor (gc->foreground);
+ mac_set_backcolor (gc->background);
+}
+
+/* Mac version of XDrawLine. */
+
+static void
+XDrawLine (display, w, gc, x1, y1, x2, y2)
+ Display *display;
+ WindowPtr w;
+ GC gc;
+ int x1, y1, x2, y2;
+{
+#if TARGET_API_MAC_CARBON
+ SetPort (GetWindowPort (w));
+#else
+ SetPort (w);
+#endif
+
+ mac_set_colors (gc);
+
+ MoveTo (x1, y1);
+ LineTo (x2, y2);
+}
+
+/* Mac version of XClearArea. */
+
+void
+XClearArea (display, w, x, y, width, height, exposures)
+ Display *display;
+ WindowPtr w;
+ int x, y;
+ unsigned int width, height;
+ int exposures;
+{
+ struct mac_output *mwp = (mac_output *) GetWRefCon (w);
+ Rect r;
+ XGCValues xgc;
+
+ xgc.foreground = mwp->x_compatible.foreground_pixel;
+ xgc.background = mwp->x_compatible.background_pixel;
+
+#if TARGET_API_MAC_CARBON
+ SetPort (GetWindowPort (w));
+#else
+ SetPort (w);
+#endif
+
+ mac_set_colors (&xgc);
+ SetRect (&r, x, y, x + width, y + height);
+
+ EraseRect (&r);
+}
+
+/* Mac version of XClearWindow. */
+
+static void
+XClearWindow (display, w)
+ Display *display;
+ WindowPtr w;
+{
+ struct mac_output *mwp = (mac_output *) GetWRefCon (w);
+ XGCValues xgc;
+
+ xgc.foreground = mwp->x_compatible.foreground_pixel;
+ xgc.background = mwp->x_compatible.background_pixel;
+
+#if TARGET_API_MAC_CARBON
+ SetPort (GetWindowPort (w));
+#else
+ SetPort (w);
+#endif
+
+ mac_set_colors (&xgc);
+
+#if TARGET_API_MAC_CARBON
+ {
+ Rect r;
+
+ GetWindowPortBounds (w, &r);
+ EraseRect (&r);
+ }
+#else /* not TARGET_API_MAC_CARBON */
+ EraseRect (&(w->portRect));
+#endif /* not TARGET_API_MAC_CARBON */
+}
+
+
+/* Mac replacement for XCopyArea. */
+
+static void
+mac_draw_bitmap (display, w, gc, x, y, bitmap)
+ Display *display;
+ WindowPtr w;
+ GC gc;
+ int x, y;
+ BitMap *bitmap;
+{
+ Rect r;
+
+#if TARGET_API_MAC_CARBON
+ SetPort (GetWindowPort (w));
+#else
+ SetPort (w);
+#endif
+
+ mac_set_colors (gc);
+ SetRect (&r, x, y, x + bitmap->bounds.right, y + bitmap->bounds.bottom);
+
+#if TARGET_API_MAC_CARBON
+ {
+ PixMapHandle pmh;
+
+ LockPortBits (GetWindowPort (w));
+ pmh = GetPortPixMap (GetWindowPort (w));
+ CopyBits (bitmap, (BitMap *) *pmh, &(bitmap->bounds), &r, srcCopy, 0);
+ UnlockPortBits (GetWindowPort (w));
+ }
+#else /* not TARGET_API_MAC_CARBON */
+ CopyBits (bitmap, &(w->portBits), &(bitmap->bounds), &r, srcCopy, 0);
+#endif /* not TARGET_API_MAC_CARBON */
+}
+
+
+/* Mac replacement for XSetClipRectangles. */
+
+static void
+mac_set_clip_rectangle (display, w, r)
+ Display *display;
+ WindowPtr w;
+ Rect *r;
+{
+#if TARGET_API_MAC_CARBON
+ SetPort (GetWindowPort (w));
+#else
+ SetPort (w);
+#endif
+
+ ClipRect (r);
+}
+
+
+/* Mac replacement for XSetClipMask. */
+
+static void
+mac_reset_clipping (display, w)
+ Display *display;
+ WindowPtr w;
+{
+ Rect r;
+
+#if TARGET_API_MAC_CARBON
+ SetPort (GetWindowPort (w));
+#else
+ SetPort (w);
+#endif
+
+ SetRect (&r, -32767, -32767, 32767, 32767);
+ ClipRect (&r);
+}
+
+
+/* Mac replacement for XCreateBitmapFromBitmapData. */
+
+static void
+mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
+ BitMap *bitmap;
+ char *bits;
+ int w, h;
+{
+ int bytes_per_row, i, j;
+
+ bitmap->rowBytes = (w + 15) / 16 * 2; /* must be on word boundary */
+ bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
+ if (!bitmap->baseAddr)
+ abort ();
+
+ bzero (bitmap->baseAddr, bitmap->rowBytes * h);
+ for (i = 0; i < h; i++)
+ for (j = 0; j < w; j++)
+ if (BitTst (bits, i * w + j))
+ BitSet (bitmap->baseAddr, i * bitmap->rowBytes * 8 + j);
+
+ SetRect (&(bitmap->bounds), 0, 0, w, h);
+}
+
+
+static void
+mac_free_bitmap (bitmap)
+ BitMap *bitmap;
+{
+ xfree (bitmap->baseAddr);
+}
+
+/* Mac replacement for XFillRectangle. */
+
+static void
+XFillRectangle (display, w, gc, x, y, width, height)
+ Display *display;
+ WindowPtr w;
+ GC gc;
+ int x, y;
+ unsigned int width, height;
+{
+ Rect r;
+
+#if TARGET_API_MAC_CARBON
+ SetPort (GetWindowPort (w));
+#else
+ SetPort (w);
+#endif
+
+ mac_set_colors (gc);
+ SetRect (&r, x, y, x + width, y + height);
+
+ PaintRect (&r); /* using foreground color of gc */
+}
+
+
+/* Mac replacement for XDrawRectangle: dest is a window. */
+
+static void
+mac_draw_rectangle (display, w, gc, x, y, width, height)
+ Display *display;
+ WindowPtr w;
+ GC gc;
+ int x, y;
+ unsigned int width, height;
+{
+ Rect r;
+
+#if TARGET_API_MAC_CARBON
+ SetPort (GetWindowPort (w));
+#else
+ SetPort (w);
+#endif
+
+ mac_set_colors (gc);
+ SetRect (&r, x, y, x + width + 1, y + height + 1);
+
+ FrameRect (&r); /* using foreground color of gc */
+}
+
+
+/* Mac replacement for XDrawRectangle: dest is a Pixmap. */
+
+static void
+mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
+ Display *display;
+ Pixmap p;
+ GC gc;
+ int x, y;
+ unsigned int width, height;
+{
+#if 0 /* MAC_TODO: draw a rectangle in a PixMap */
+ Rect r;
+
+#if TARGET_API_MAC_CARBON
+ SetPort (GetWindowPort (w));
+#else
+ SetPort (w);
+#endif
+
+ mac_set_colors (gc);
+ SetRect (&r, x, y, x + width, y + height);
+
+ FrameRect (&r); /* using foreground color of gc */
+#endif /* 0 */
+}
+
+
+static void
+mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
+ bytes_per_char)
+ Display *display;
+ WindowPtr w;
+ GC gc;
+ int x, y;
+ char *buf;
+ int nchars, mode, bytes_per_char;
+{
+#if TARGET_API_MAC_CARBON
+ SetPort (GetWindowPort (w));
+#else
+ SetPort (w);
+#endif
+
+ mac_set_colors (gc);
+
+ TextFont (gc->font->mac_fontnum);
+ TextSize (gc->font->mac_fontsize);
+ TextFace (gc->font->mac_fontface);
+ TextMode (mode);
+
+ MoveTo (x, y);
+ DrawText (buf, 0, nchars * bytes_per_char);
+}
+
+
+/* Mac replacement for XDrawString. */
+
+static void
+XDrawString (display, w, gc, x, y, buf, nchars)
+ Display *display;
+ WindowPtr w;
+ GC gc;
+ int x, y;
+ char *buf;
+ int nchars;
+{
+ mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
+}
+
+
+/* Mac replacement for XDrawString16. */
+
+static void
+XDrawString16 (display, w, gc, x, y, buf, nchars)
+ Display *display;
+ WindowPtr w;
+ GC gc;
+ int x, y;
+ XChar2b *buf;
+ int nchars;
+{
+ mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcOr,
+ 2);
+}
+
+
+/* Mac replacement for XDrawImageString. */
+
+static void
+XDrawImageString (display, w, gc, x, y, buf, nchars)
+ Display *display;
+ WindowPtr w;
+ GC gc;
+ int x, y;
+ char *buf;
+ int nchars;
+{
+ mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcCopy, 1);
+}
+
+
+/* Mac replacement for XDrawString16. */
+
+static void
+XDrawImageString16 (display, w, gc, x, y, buf, nchars)
+ Display *display;
+ WindowPtr w;
+ GC gc;
+ int x, y;
+ XChar2b *buf;
+ int nchars;
+{
+ mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
+ 2);
+}
+
+
+/* Mac replacement for XCopyArea: dest must be window. */
+
+static void
+mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
+ dest_y)
+ Display *display;
+ Pixmap src;
+ WindowPtr dest;
+ GC gc;
+ int src_x, src_y;
+ unsigned int width, height;
+ int dest_x, dest_y;
+{
+ Rect src_r, dest_r;
+
+#if TARGET_API_MAC_CARBON
+ SetPort (GetWindowPort (dest));
+#else
+ SetPort (dest);
+#endif
+
+ mac_set_colors (gc);
+
+ SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
+ SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
+
+#if TARGET_API_MAC_CARBON
+ {
+ PixMapHandle pmh;
+
+ LockPortBits (GetWindowPort (dest));
+ pmh = GetPortPixMap (GetWindowPort (dest));
+ CopyBits ((BitMap *) &src, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
+ UnlockPortBits (GetWindowPort (dest));
+ }
+#else /* not TARGET_API_MAC_CARBON */
+ CopyBits ((BitMap *) &src, &(dest->portBits), &src_r, &dest_r, srcCopy, 0);
+#endif /* not TARGET_API_MAC_CARBON */
+}
+
+
+#if 0
+/* Convert a pair of local coordinates to global (screen) coordinates.
+ Assume graphic port has been properly set. */
+static void
+local_to_global_coord (short *h, short *v)
+{
+ Point p;
+
+ p.h = *h;
+ p.v = *v;
+
+ LocalToGlobal (&p);
+
+ *h = p.h;
+ *v = p.v;
+}
+#endif
+
+/* Mac replacement for XCopyArea: used only for scrolling. */
+
+static void
+mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
+ Display *display;
+ WindowPtr w;
+ GC gc;
+ int src_x, src_y;
+ unsigned int width, height;
+ int dest_x, dest_y;
+{
+#if TARGET_API_MAC_CARBON
+ Rect gw_r, src_r, dest_r;
+ PixMapHandle pmh;
+
+ SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
+ SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
+
+ SetPort (GetWindowPort (w));
+ mac_set_colors (gc);
+
+ LockPortBits (GetWindowPort (w));
+ pmh = GetPortPixMap (GetWindowPort (w));
+ CopyBits ((BitMap *) *pmh, (BitMap *) *pmh, &src_r, &dest_r, srcCopy, 0);
+ UnlockPortBits (GetWindowPort (w));
+#else /* not TARGET_API_MAC_CARBON */
+ Rect src_r, dest_r;
+
+ SetPort (w);
+#if 0
+ mac_set_colors (gc);
+#endif
+
+ SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
+ SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
+
+#if 0
+ /* Need to use global coordinates and screenBits since src and dest
+ areas overlap in general. */
+ local_to_global_coord (&src_r.left, &src_r.top);
+ local_to_global_coord (&src_r.right, &src_r.bottom);
+ local_to_global_coord (&dest_r.left, &dest_r.top);
+ local_to_global_coord (&dest_r.right, &dest_r.bottom);
+
+ CopyBits (&qd.screenBits, &qd.screenBits, &src_r, &dest_r, srcCopy, 0);
+#else
+ /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
+ color mapping in CopyBits. Otherwise, it will be slow. */
+ ForeColor (blackColor);
+ BackColor (whiteColor);
+ CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
+
+ mac_set_colors (gc);
+#endif
+#endif /* not TARGET_API_MAC_CARBON */
+}
+
+
+/* Mac replacement for XCopyArea: dest must be Pixmap. */
+
+static void
+mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
+ dest_x, dest_y)
+ Display *display;
+ Pixmap src;
+ Pixmap dest;
+ GC gc;
+ int src_x, src_y;
+ unsigned int width, height;
+ int dest_x, dest_y;
+{
+ Rect src_r, dest_r;
+ int src_right = ((PixMap *) src)->bounds.right;
+ int src_bottom = ((PixMap *) src)->bounds.bottom;
+ int w = src_right - src_x;
+ int h = src_bottom - src_y;
+
+ mac_set_colors (gc);
+
+ SetRect (&src_r, src_x, src_y, src_right, src_bottom);
+ SetRect (&dest_r, dest_x, dest_y, dest_x + w, dest_y + h);
+
+ CopyBits ((BitMap *) &src, (BitMap *) &dest, &src_r, &dest_r, srcCopy, 0);
+}
+
+
+/* Mac replacement for XChangeGC. */
+
+static void
+XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
+ XGCValues *xgcv)
+{
+ if (mask & GCForeground)
+ gc->foreground = xgcv->foreground;
+ if (mask & GCBackground)
+ gc->background = xgcv->background;
+ if (mask & GCFont)
+ gc->font = xgcv->font;
+}
+
+
+/* Mac replacement for XCreateGC. */
+
+XGCValues *
+XCreateGC (void * ignore, Window window, unsigned long mask,
+ XGCValues *xgcv)
+{
+ XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
+ bzero (gc, sizeof (XGCValues));
+
+ XChangeGC (ignore, gc, mask, xgcv);
+
+ return gc;
+}
+
+
+/* Used in xfaces.c. */
+
+void
+XFreeGC (display, gc)
+ Display *display;
+ GC gc;
+{
+ xfree (gc);
+}
+
+
+/* Mac replacement for XGetGCValues. */
+
+static void
+XGetGCValues (void* ignore, XGCValues *gc,
+ unsigned long mask, XGCValues *xgcv)
+{
+ XChangeGC (ignore, xgcv, mask, gc);
+}
+
+
+/* Mac replacement for XSetForeground. */
+
+static void
+XSetForeground (display, gc, color)
+ Display *display;
+ GC gc;
+ unsigned long color;
+{
+ gc->foreground = color;
+}
+
+
+/* Mac replacement for XSetFont. */
+
+static void
+XSetFont (display, gc, font)
+ Display *display;
+ GC gc;
+ XFontStruct *font;
+{
+ gc->font = font;
+}
+
+
+static void
+XTextExtents16 (XFontStruct *font, XChar2b *text, int nchars,
+ int *direction,int *font_ascent,
+ int *font_descent, XCharStruct *cs)
+{
+ /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
+}
+
+
+/* x_sync is a no-op on Mac. */
+void
+x_sync (f)
+ void *f;
+{
+}
+
+
+/* Remove calls to XFlush by defining XFlush to an empty replacement.
+ Calls to XFlush should be unnecessary because the X output buffer
+ is flushed automatically as needed by calls to XPending,
+ XNextEvent, or XWindowEvent according to the XFlush man page.
+ XTread_socket calls XPending. Removing XFlush improves
+ performance. */
+
+#if TARGET_API_MAC_CARBON
+#define XFlush(DISPLAY) QDFlushPortBuffer (GetQDGlobalsThePort (), NULL)
+#else
+#define XFlush(DISPLAY) (void) 0
+#endif
+
+/* Flush display of frame F, or of all frames if F is null. */
+
+void
+x_flush (f)
+ struct frame *f;
+{
+#if TARGET_API_MAC_CARBON
+ BLOCK_INPUT;
+ if (f == NULL)
+ {
+ Lisp_Object rest, frame;
+ FOR_EACH_FRAME (rest, frame)
+ x_flush (XFRAME (frame));
+ }
+ else if (FRAME_X_P (f))
+ XFlush (FRAME_MAC_DISPLAY (f));
+ UNBLOCK_INPUT;
+#endif /* TARGET_API_MAC_CARBON */
+}
+
+
+\f
+/* Return the struct mac_display_info corresponding to DPY. There's
+ only one. */
+
+struct mac_display_info *
+mac_display_info_for_display (dpy)
+ Display *dpy;
+{
+ return &one_mac_display_info;
+}
+
+
+\f
+/***********************************************************************
+ Starting and ending an update
+ ***********************************************************************/
+
+/* Start an update of frame F. This function is installed as a hook
+ for update_begin, i.e. it is called when update_begin is called.
+ This function is called prior to calls to x_update_window_begin for
+ each window being updated. */
+
+static void
+x_update_begin (f)
+ struct frame *f;
+{
+ /* Nothing to do. */
+}
+
+
+/* Start update of window W. Set the global variable updated_window
+ to the window being updated and set output_cursor to the cursor
+ position of W. */
+
+static void
+x_update_window_begin (w)
+ struct window *w;
+{
+ struct frame *f = XFRAME (WINDOW_FRAME (w));
+ struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
+
+ updated_window = w;
+ set_output_cursor (&w->cursor);
+
+ BLOCK_INPUT;
+
+ if (f == display_info->mouse_face_mouse_frame)
+ {
+ /* Don't do highlighting for mouse motion during the update. */
+ display_info->mouse_face_defer = 1;
+
+ /* If F needs to be redrawn, simply forget about any prior mouse
+ highlighting. */
+ if (FRAME_GARBAGED_P (f))
+ display_info->mouse_face_window = Qnil;
+
+#if 0 /* Rows in a current matrix containing glyphs in mouse-face have
+ their mouse_face_p flag set, which means that they are always
+ unequal to rows in a desired matrix which never have that
+ flag set. So, rows containing mouse-face glyphs are never
+ scrolled, and we don't have to switch the mouse highlight off
+ here to prevent it from being scrolled. */
+
+ /* Can we tell that this update does not affect the window
+ where the mouse highlight is? If so, no need to turn off.
+ Likewise, don't do anything if the frame is garbaged;
+ in that case, the frame's current matrix that we would use
+ is all wrong, and we will redisplay that line anyway. */
+ if (!NILP (display_info->mouse_face_window)
+ && w == XWINDOW (display_info->mouse_face_window))
+ {
+ int i;
+
+ for (i = 0; i < w->desired_matrix->nrows; ++i)
+ if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
+ break;
+
+ if (i < w->desired_matrix->nrows)
+ clear_mouse_face (display_info);
+ }
+#endif /* 0 */
+ }
+
+ UNBLOCK_INPUT;
+}
+
+
+/* Draw a vertical window border to the right of window W if W doesn't
+ have vertical scroll bars. */
+
+static void
+x_draw_vertical_border (w)
+ struct window *w;
+{
+ struct frame *f = XFRAME (WINDOW_FRAME (w));
+
+ /* Redraw borders between horizontally adjacent windows. Don't
+ do it for frames with vertical scroll bars because either the
+ right scroll bar of a window, or the left scroll bar of its
+ neighbor will suffice as a border. */
+ if (!WINDOW_RIGHTMOST_P (w)
+ && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
+ {
+ int x0, x1, y0, y1;
+
+ window_box_edges (w, -1, &x0, &y0, &x1, &y1);
+ x1 += FRAME_X_RIGHT_FRINGE_WIDTH (f);
+ y1 -= 1;
+
+ XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
+ f->output_data.mac->normal_gc, x1, y0, x1, y1);
+ }
+}
+
+
+/* End update of window W (which is equal to updated_window).
+
+ Draw vertical borders between horizontally adjacent windows, and
+ display W's cursor if CURSOR_ON_P is non-zero.
+
+ MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
+ glyphs in mouse-face were overwritten. In that case we have to
+ make sure that the mouse-highlight is properly redrawn.
+
+ W may be a menu bar pseudo-window in case we don't have X toolkit
+ support. Such windows don't have a cursor, so don't display it
+ here. */
+
+static void
+x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
+ struct window *w;
+ int cursor_on_p, mouse_face_overwritten_p;
+{
+ struct mac_display_info *dpyinfo
+ = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
+
+ if (!w->pseudo_window_p)
+ {
+ BLOCK_INPUT;
+
+ if (cursor_on_p)
+ x_display_and_set_cursor (w, 1, output_cursor.hpos,
+ output_cursor.vpos,
+ output_cursor.x, output_cursor.y);
+
+ x_draw_vertical_border (w);
+ UNBLOCK_INPUT;
+ }
+
+ /* If a row with mouse-face was overwritten, arrange for
+ XTframe_up_to_date to redisplay the mouse highlight. */
+ if (mouse_face_overwritten_p)
+ {
+ dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
+ dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
+ dpyinfo->mouse_face_window = Qnil;
+ }
+
+#if 0
+ /* Unhide the caret. This won't actually show the cursor, unless it
+ was visible before the corresponding call to HideCaret in
+ x_update_window_begin. */
+ if (w32_use_visible_system_caret)
+ SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
+#endif
+
+ updated_window = NULL;
+}
+
+
+/* End update of frame F. This function is installed as a hook in
+ update_end. */
+
+static void
+x_update_end (f)
+ struct frame *f;
+{
+ /* Reset the background color of Mac OS Window to that of the frame after
+ update so that it is used by Mac Toolbox to clear the update region before
+ an update event is generated. */
+#if TARGET_API_MAC_CARBON
+ SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
+#else
+ SetPort (FRAME_MAC_WINDOW (f));
+#endif
+
+ mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
+
+ /* Mouse highlight may be displayed again. */
+ FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
+
+ BLOCK_INPUT;
+ XFlush (FRAME_MAC_DISPLAY (f));
+ UNBLOCK_INPUT;
+}
+
+
+/* This function is called from various places in xdisp.c whenever a
+ complete update has been performed. The global variable
+ updated_window is not available here. */
+
+static void
+XTframe_up_to_date (f)
+ struct frame *f;
+{
+ if (FRAME_X_P (f))
+ {
+ struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+
+ if (dpyinfo->mouse_face_deferred_gc
+ || f == dpyinfo->mouse_face_mouse_frame)
+ {
+ BLOCK_INPUT;
+ if (dpyinfo->mouse_face_mouse_frame)
+ note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
+ dpyinfo->mouse_face_mouse_x,
+ dpyinfo->mouse_face_mouse_y);
+ dpyinfo->mouse_face_deferred_gc = 0;
+ UNBLOCK_INPUT;
+ }
+ }
+}
+
+
+/* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
+ arrow bitmaps, or clear the fringes if no bitmaps are required
+ before DESIRED_ROW is made current. The window being updated is
+ found in updated_window. This function is called from
+ update_window_line only if it is known that there are differences
+ between bitmaps to be drawn between current row and DESIRED_ROW. */
+
+static void
+x_after_update_window_line (desired_row)
+ struct glyph_row *desired_row;
+{
+ struct window *w = updated_window;
+ struct frame *f;
+ int width, height;
+
+ xassert (w);
+
+ if (!desired_row->mode_line_p && !w->pseudo_window_p)
+ {
+ BLOCK_INPUT;
+ x_draw_row_fringe_bitmaps (w, desired_row);
+ UNBLOCK_INPUT;
+ }
+
+ /* When a window has disappeared, make sure that no rest of
+ full-width rows stays visible in the internal border. Could
+ check here if updated_window is the leftmost/rightmost window,
+ but I guess it's not worth doing since vertically split windows
+ are almost never used, internal border is rarely set, and the
+ overhead is very small. */
+ if (windows_or_buffers_changed
+ && desired_row->full_width_p
+ && (f = XFRAME (w->frame),
+ width = FRAME_INTERNAL_BORDER_WIDTH (f),
+ width != 0)
+ && (height = desired_row->visible_height,
+ height > 0))
+ {
+ int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
+ /* Internal border is drawn below the tool bar. */
+ if (WINDOWP (f->tool_bar_window)
+ && w == XWINDOW (f->tool_bar_window))
+ y -= width;
+
+ BLOCK_INPUT;
+
+ XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
+ 0, y, width, height, 0);
+ XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
+ f->output_data.mac->pixel_width - width, y,
+ width, height, 0);
+
+ UNBLOCK_INPUT;
+ }
+}
+
+
+/* Draw the bitmap WHICH in one of the left or right fringes of
+ window W. ROW is the glyph row for which to display the bitmap; it
+ determines the vertical position at which the bitmap has to be
+ drawn. */
+
+static void
+x_draw_fringe_bitmap (w, row, which, left_p)
+ struct window *w;
+ struct glyph_row *row;
+ enum fringe_bitmap_type which;
+ int left_p;
+{
+ struct frame *f = XFRAME (WINDOW_FRAME (w));
+ Display *display = FRAME_MAC_DISPLAY (f);
+ WindowPtr window = FRAME_MAC_WINDOW (f);
+ int x, y, wd, h, dy;
+ int b1, b2;
+ unsigned char *bits;
+ BitMap bitmap;
+ XGCValues gcv;
+ GC gc = f->output_data.mac->normal_gc;
+ struct face *face;
+
+ /* Must clip because of partially visible lines. */
+ x_clip_to_row (w, row, gc, 1);
+
+ /* Convert row to frame coordinates. */
+ y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
+
+ switch (which)
+ {
+ case NO_FRINGE_BITMAP:
+ wd = 0;
+ h = 0;
+ break;
+
+ case LEFT_TRUNCATION_BITMAP:
+ wd = left_width;
+ h = left_height;
+ bits = left_bits;
+ break;
+
+ case OVERLAY_ARROW_BITMAP:
+ wd = ov_width;
+ h = ov_height;
+ bits = ov_bits;
+ break;
+
+ case RIGHT_TRUNCATION_BITMAP:
+ wd = right_width;
+ h = right_height;
+ bits = right_bits;
+ break;
+
+ case CONTINUED_LINE_BITMAP:
+ wd = continued_width;
+ h = continued_height;
+ bits = continued_bits;
+ break;
+
+ case CONTINUATION_LINE_BITMAP:
+ wd = continuation_width;
+ h = continuation_height;
+ bits = continuation_bits;
+ break;
+
+ case ZV_LINE_BITMAP:
+ wd = zv_width;
+ h = zv_height - (y % zv_period);
+ bits = zv_bits + (y % zv_period);
+ break;
+
+ default:
+ abort ();
+ }
+
+ /* Clip bitmap if too high. */
+ if (h > row->height)
+ h = row->height;
+
+ /* Set dy to the offset in the row to start drawing the bitmap. */
+ dy = (row->height - h) / 2;
+
+ /* Draw the bitmap. */
+ face = FACE_FROM_ID (f, FRINGE_FACE_ID);
+ PREPARE_FACE_FOR_DISPLAY (f, face);
+
+ /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
+ the fringe. */
+ b1 = -1;
+ if (left_p)
+ {
+ if (wd > FRAME_X_LEFT_FRINGE_WIDTH (f))
+ wd = FRAME_X_LEFT_FRINGE_WIDTH (f);
+ x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
+ - wd
+ - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);
+ if (wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > h)
+ {
+ /* If W has a vertical border to its left, don't draw over it. */
+ int border = ((XFASTINT (w->left) > 0
+ && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
+ ? 1 : 0);
+ b1 = (window_box_left (w, -1)
+ - FRAME_X_LEFT_FRINGE_WIDTH (f)
+ + border);
+ b2 = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);
+ }
+ }
+ else
+ {
+ if (wd > FRAME_X_RIGHT_FRINGE_WIDTH (f))
+ wd = FRAME_X_RIGHT_FRINGE_WIDTH (f);
+ x = (window_box_right (w, -1)
+ + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - wd) / 2);
+ /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
+ the fringe. */
+ if (wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > h)
+ {
+ b1 = window_box_right (w, -1);
+ b2 = FRAME_X_RIGHT_FRINGE_WIDTH (f);
+ }
+ }
+
+ if (b1 >= 0)
+ {
+ int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
+ XGCValues gcv;
+ gcv.foreground = face->background;
+
+#if 0 /* MAC_TODO: stipple */
+ /* In case the same realized face is used for fringes and
+ for something displayed in the text (e.g. face `region' on
+ mono-displays, the fill style may have been changed to
+ FillSolid in x_draw_glyph_string_background. */
+ if (face->stipple)
+ XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
+ else
+ XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
+#endif
+
+ XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
+ &gcv,
+ b1,
+ WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
+ row->y)),
+ b2,
+ row->visible_height);
+
+#if 0 /* MAC_TODO: stipple */
+ if (!face->stipple)
+ XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
+#endif
+ }
+
+ if (which == NO_FRINGE_BITMAP)
+ {
+ mac_reset_clipping (display, window);
+ return;
+ }
+
+ mac_create_bitmap_from_bitmap_data (&bitmap, bits, wd, h);
+ gcv.foreground = face->foreground;
+ gcv.background = face->background;
+
+ mac_draw_bitmap (display, window, &gcv, x, y + dy, &bitmap);
+
+ mac_free_bitmap (&bitmap);
+ mac_reset_clipping (display, window);
+}
+
+
+/* Draw fringe bitmaps for glyph row ROW on window W. Call this
+ function with input blocked. */
+
+static void
+x_draw_row_fringe_bitmaps (w, row)
+ struct window *w;
+ struct glyph_row *row;
+{
+ struct frame *f = XFRAME (w->frame);
+ enum fringe_bitmap_type bitmap;
+
+ xassert (interrupt_input_blocked);
+
+ /* If row is completely invisible, because of vscrolling, we
+ don't have to draw anything. */
+ if (row->visible_height <= 0)
+ return;
+
+ if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0)
+ {
+ /* Decide which bitmap to draw in the left fringe. */
+ if (row->overlay_arrow_p)
+ bitmap = OVERLAY_ARROW_BITMAP;
+ else if (row->truncated_on_left_p)
+ bitmap = LEFT_TRUNCATION_BITMAP;
+ else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
+ bitmap = CONTINUATION_LINE_BITMAP;
+ else if (row->indicate_empty_line_p)
+ bitmap = ZV_LINE_BITMAP;
+ else
+ bitmap = NO_FRINGE_BITMAP;
+
+ x_draw_fringe_bitmap (w, row, bitmap, 1);
+ }
+
+ if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0)
+ {
+ /* Decide which bitmap to draw in the right fringe. */
+ if (row->truncated_on_right_p)
+ bitmap = RIGHT_TRUNCATION_BITMAP;
+ else if (row->continued_p)
+ bitmap = CONTINUED_LINE_BITMAP;
+ else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0)
+ bitmap = ZV_LINE_BITMAP;
+ else
+ bitmap = NO_FRINGE_BITMAP;
+
+ x_draw_fringe_bitmap (w, row, bitmap, 0);
+ }
+}
+
+\f
+/* This is called when starting Emacs and when restarting after
+ suspend. When starting Emacs, no window is mapped. And nothing
+ must be done to Emacs's own window if it is suspended (though that
+ rarely happens). */
+
+static void
+XTset_terminal_modes ()
+{
+}
+
+/* This is called when exiting or suspending Emacs. Exiting will make
+ the windows go away, and suspending requires no action. */
+
+static void
+XTreset_terminal_modes ()
+{
+}
+
+
+\f
+/***********************************************************************
+ Output Cursor
+ ***********************************************************************/
+
+/* Set the global variable output_cursor to CURSOR. All cursor
+ positions are relative to updated_window. */
+
+static void
+set_output_cursor (cursor)
+ struct cursor_pos *cursor;
+{
+ output_cursor.hpos = cursor->hpos;
+ output_cursor.vpos = cursor->vpos;
+ output_cursor.x = cursor->x;
+ output_cursor.y = cursor->y;
+}
+
+
+/* Set a nominal cursor position.
+
+ HPOS and VPOS are column/row positions in a window glyph matrix. X
+ and Y are window text area relative pixel positions.
+
+ If this is done during an update, updated_window will contain the
+ window that is being updated and the position is the future output
+ cursor position for that window. If updated_window is null, use
+ selected_window and display the cursor at the given position. */
+
+static void
+XTcursor_to (vpos, hpos, y, x)
+ int vpos, hpos, y, x;
+{
+ struct window *w;
+
+ /* If updated_window is not set, work on selected_window. */
+ if (updated_window)
+ w = updated_window;
+ else
+ w = XWINDOW (selected_window);
+
+ /* Set the output cursor. */
+ output_cursor.hpos = hpos;
+ output_cursor.vpos = vpos;
+ output_cursor.x = x;
+ output_cursor.y = y;
+
+ /* If not called as part of an update, really display the cursor.
+ This will also set the cursor position of W. */
+ if (updated_window == NULL)
+ {
+ BLOCK_INPUT;
+ x_display_cursor (w, 1, hpos, vpos, x, y);
+ XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
+ UNBLOCK_INPUT;
+ }
+}
+
+
+\f
+/***********************************************************************
+ Display Iterator
+ ***********************************************************************/
+
+/* Function prototypes of this page. */
+
+static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
+ struct glyph *,
+ XChar2b *,
+ int *));
+static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
+ int, XChar2b *, int));
+static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
+static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
+static void x_append_glyph P_ ((struct it *));
+static void x_append_composite_glyph P_ ((struct it *));
+static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
+ int, int, double));
+static void x_produce_glyphs P_ ((struct it *));
+static void x_produce_image_glyph P_ ((struct it *it));
+
+
+/* Return a pointer to per-char metric information in FONT of a
+ character pointed by B which is a pointer to an XChar2b. */
+
+#define PER_CHAR_METRIC(font, b) \
+ ((font)->per_char \
+ ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
+ + (((font)->min_byte1 || (font)->max_byte1) \
+ ? (((b)->byte1 - (font)->min_byte1) \
+ * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
+ : 0)) \
+ : &((font)->max_bounds))
+
+
+/* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
+ is not contained in the font. */
+
+static INLINE XCharStruct *
+x_per_char_metric (font, char2b)
+ XFontStruct *font;
+ XChar2b *char2b;
+{
+ /* The result metric information. */
+ XCharStruct *pcm = NULL;
+
+ xassert (font && char2b);
+
+ if (font->per_char != NULL)
+ {
+ if (font->min_byte1 == 0 && font->max_byte1 == 0)
+ {
+ /* min_char_or_byte2 specifies the linear character index
+ corresponding to the first element of the per_char array,
+ max_char_or_byte2 is the index of the last character. A
+ character with non-zero CHAR2B->byte1 is not in the font.
+ A character with byte2 less than min_char_or_byte2 or
+ greater max_char_or_byte2 is not in the font. */
+ if (char2b->byte1 == 0
+ && char2b->byte2 >= font->min_char_or_byte2
+ && char2b->byte2 <= font->max_char_or_byte2)
+ pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
+ }
+ else
+ {
+ /* If either min_byte1 or max_byte1 are nonzero, both
+ min_char_or_byte2 and max_char_or_byte2 are less than
+ 256, and the 2-byte character index values corresponding
+ to the per_char array element N (counting from 0) are:
+
+ byte1 = N/D + min_byte1
+ byte2 = N\D + min_char_or_byte2
+
+ where:
+
+ D = max_char_or_byte2 - min_char_or_byte2 + 1
+ / = integer division
+ \ = integer modulus */
+ if (char2b->byte1 >= font->min_byte1
+ && char2b->byte1 <= font->max_byte1
+ && char2b->byte2 >= font->min_char_or_byte2
+ && char2b->byte2 <= font->max_char_or_byte2)
+ {
+ pcm = (font->per_char
+ + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
+ * (char2b->byte1 - font->min_byte1))
+ + (char2b->byte2 - font->min_char_or_byte2));
+ }
+ }
+ }
+ else
+ {
+ /* If the per_char pointer is null, all glyphs between the first
+ and last character indexes inclusive have the same
+ information, as given by both min_bounds and max_bounds. */
+ if (char2b->byte2 >= font->min_char_or_byte2
+ && char2b->byte2 <= font->max_char_or_byte2)
+ pcm = &font->max_bounds;
+ }
+
+ return ((pcm == NULL
+ || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
+ ? NULL : pcm);
+}
+
+
+/* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
+ the two-byte form of C. Encoding is returned in *CHAR2B. */
+
+static INLINE void
+x_encode_char (c, char2b, font_info)
+ int c;
+ XChar2b *char2b;
+ struct font_info *font_info;
+{
+ int charset = CHAR_CHARSET (c);
+ XFontStruct *font = font_info->font;
+
+ /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
+ This may be either a program in a special encoder language or a
+ fixed encoding. */
+ if (font_info->font_encoder)
+ {
+ /* It's a program. */
+ struct ccl_program *ccl = font_info->font_encoder;
+
+ if (CHARSET_DIMENSION (charset) == 1)
+ {
+ ccl->reg[0] = charset;
+ ccl->reg[1] = char2b->byte2;
+ }
+ else
+ {
+ ccl->reg[0] = charset;
+ ccl->reg[1] = char2b->byte1;
+ ccl->reg[2] = char2b->byte2;
+ }
+
+ ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
+
+ /* We assume that MSBs are appropriately set/reset by CCL
+ program. */
+ if (font->max_byte1 == 0) /* 1-byte font */
+ char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
+ else
+ char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
+ }
+ else if (font_info->encoding[charset])
+ {
+ /* Fixed encoding scheme. See fontset.h for the meaning of the
+ encoding numbers. */
+ int enc = font_info->encoding[charset];
+
+ if ((enc == 1 || enc == 2)
+ && CHARSET_DIMENSION (charset) == 2)
+ char2b->byte1 |= 0x80;
+
+ if (enc == 1 || enc == 3)
+ char2b->byte2 |= 0x80;
+
+ if (enc == 4)
+ {
+ int sjis1, sjis2;
+
+ ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
+ char2b->byte1 = sjis1;
+ char2b->byte2 = sjis2;
+ }
+ }
+}
+
+
+/* Get face and two-byte form of character C in face FACE_ID on frame
+ F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
+ means we want to display multibyte text. Value is a pointer to a
+ realized face that is ready for display. */
+
+static INLINE struct face *
+x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
+ struct frame *f;
+ int c, face_id;
+ XChar2b *char2b;
+ int multibyte_p;
+{
+ struct face *face = FACE_FROM_ID (f, face_id);
+
+ if (!multibyte_p)
+ {
+ /* Unibyte case. We don't have to encode, but we have to make
+ sure to use a face suitable for unibyte. */
+ char2b->byte1 = 0;
+ char2b->byte2 = c;
+ face_id = FACE_FOR_CHAR (f, face, c);
+ face = FACE_FROM_ID (f, face_id);
+ }
+ else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
+ {
+ /* Case of ASCII in a face known to fit ASCII. */
+ char2b->byte1 = 0;
+ char2b->byte2 = c;
+ }
+ else
+ {
+ int c1, c2, charset;
+
+ /* Split characters into bytes. If c2 is -1 afterwards, C is
+ really a one-byte character so that byte1 is zero. */
+ SPLIT_CHAR (c, charset, c1, c2);
+ if (c2 > 0)
+ char2b->byte1 = c1, char2b->byte2 = c2;
+ else
+ char2b->byte1 = 0, char2b->byte2 = c1;
+
+ /* Maybe encode the character in *CHAR2B. */
+ if (face->font != NULL)
+ {
+ struct font_info *font_info
+ = FONT_INFO_FROM_ID (f, face->font_info_id);
+ if (font_info)
+ x_encode_char (c, char2b, font_info);
+ }
+ }
+
+ /* Make sure X resources of the face are allocated. */
+ xassert (face != NULL);
+ PREPARE_FACE_FOR_DISPLAY (f, face);
+
+ return face;
+}
+
+
+/* Get face and two-byte form of character glyph GLYPH on frame F.
+ The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
+ a pointer to a realized face that is ready for display. */
+
+static INLINE struct face *
+x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
+ struct frame *f;
+ struct glyph *glyph;
+ XChar2b *char2b;
+ int *two_byte_p;
+{
+ struct face *face;
+
+ xassert (glyph->type == CHAR_GLYPH);
+ face = FACE_FROM_ID (f, glyph->face_id);
+
+ if (two_byte_p)
+ *two_byte_p = 0;
+
+ if (!glyph->multibyte_p)
+ {
+ /* Unibyte case. We don't have to encode, but we have to make
+ sure to use a face suitable for unibyte. */
+ char2b->byte1 = 0;
+ char2b->byte2 = glyph->u.ch;
+ }
+ else if (glyph->u.ch < 128
+ && glyph->face_id < BASIC_FACE_ID_SENTINEL)
+ {
+ /* Case of ASCII in a face known to fit ASCII. */
+ char2b->byte1 = 0;
+ char2b->byte2 = glyph->u.ch;
+ }
+ else
+ {
+ int c1, c2, charset;
+
+ /* Split characters into bytes. If c2 is -1 afterwards, C is
+ really a one-byte character so that byte1 is zero. */
+ SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
+ if (c2 > 0)
+ char2b->byte1 = c1, char2b->byte2 = c2;
+ else
+ char2b->byte1 = 0, char2b->byte2 = c1;
+
+ /* Maybe encode the character in *CHAR2B. */
+ if (charset != CHARSET_ASCII)
+ {
+ struct font_info *font_info
+ = FONT_INFO_FROM_ID (f, face->font_info_id);
+ if (font_info)
+ {
+ x_encode_char (glyph->u.ch, char2b, font_info);
+ if (two_byte_p)
+ *two_byte_p
+ = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
+ }
+ }
+ }
+
+ /* Make sure X resources of the face are allocated. */
+ xassert (face != NULL);
+ PREPARE_FACE_FOR_DISPLAY (f, face);
+ return face;
+}
+
+
+/* Store one glyph for IT->char_to_display in IT->glyph_row.
+ Called from x_produce_glyphs when IT->glyph_row is non-null. */
+
+static INLINE void
+x_append_glyph (it)
+ struct it *it;
+{
+ struct glyph *glyph;
+ enum glyph_row_area area = it->area;
+
+ xassert (it->glyph_row);
+ xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
+
+ glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
+ if (glyph < it->glyph_row->glyphs[area + 1])
+ {
+ glyph->charpos = CHARPOS (it->position);
+ glyph->object = it->object;
+ glyph->pixel_width = it->pixel_width;
+ glyph->voffset = it->voffset;
+ glyph->type = CHAR_GLYPH;
+ glyph->multibyte_p = it->multibyte_p;
+ glyph->left_box_line_p = it->start_of_box_run_p;
+ glyph->right_box_line_p = it->end_of_box_run_p;
+ glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
+ || it->phys_descent > it->descent);
+ glyph->padding_p = 0;
+ glyph->glyph_not_available_p = it->glyph_not_available_p;
+ glyph->face_id = it->face_id;
+ glyph->u.ch = it->char_to_display;
+ ++it->glyph_row->used[area];
+ }
+}
+
+/* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
+ Called from x_produce_glyphs when IT->glyph_row is non-null. */
+
+static INLINE void
+x_append_composite_glyph (it)
+ struct it *it;
+{
+ struct glyph *glyph;
+ enum glyph_row_area area = it->area;
+
+ xassert (it->glyph_row);
+
+ glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
+ if (glyph < it->glyph_row->glyphs[area + 1])
+ {
+ glyph->charpos = CHARPOS (it->position);
+ glyph->object = it->object;
+ glyph->pixel_width = it->pixel_width;
+ glyph->voffset = it->voffset;
+ glyph->type = COMPOSITE_GLYPH;
+ glyph->multibyte_p = it->multibyte_p;
+ glyph->left_box_line_p = it->start_of_box_run_p;
+ glyph->right_box_line_p = it->end_of_box_run_p;
+ glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
+ || it->phys_descent > it->descent);
+ glyph->padding_p = 0;
+ glyph->glyph_not_available_p = 0;
+ glyph->face_id = it->face_id;
+ glyph->u.cmp_id = it->cmp_id;
+ ++it->glyph_row->used[area];
+ }
+}
+
+
+/* Change IT->ascent and IT->height according to the setting of
+ IT->voffset. */
+
+static INLINE void
+take_vertical_position_into_account (it)
+ struct it *it;
+{
+ if (it->voffset)
+ {
+ if (it->voffset < 0)
+ /* Increase the ascent so that we can display the text higher
+ in the line. */
+ it->ascent += abs (it->voffset);
+ else
+ /* Increase the descent so that we can display the text lower
+ in the line. */
+ it->descent += it->voffset;
+ }
+}
+
+
+/* Produce glyphs/get display metrics for the image IT is loaded with.
+ See the description of struct display_iterator in dispextern.h for
+ an overview of struct display_iterator. */
+
+static void
+x_produce_image_glyph (it)
+ struct it *it;
+{
+ struct image *img;
+ struct face *face;
+
+ xassert (it->what == IT_IMAGE);
+
+ face = FACE_FROM_ID (it->f, it->face_id);
+ img = IMAGE_FROM_ID (it->f, it->image_id);
+ xassert (img);
+
+ /* Make sure X resources of the face and image are loaded. */
+ PREPARE_FACE_FOR_DISPLAY (it->f, face);
+ prepare_image_for_display (it->f, img);
+
+ it->ascent = it->phys_ascent = image_ascent (img, face);
+ it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
+ it->pixel_width = img->width + 2 * img->hmargin;
+
+ it->nglyphs = 1;
+
+ if (face->box != FACE_NO_BOX)
+ {
+ if (face->box_line_width > 0)
+ {
+ it->ascent += face->box_line_width;
+ it->descent += face->box_line_width;
+ }
+
+ if (it->start_of_box_run_p)
+ it->pixel_width += abs (face->box_line_width);
+ if (it->end_of_box_run_p)
+ it->pixel_width += abs (face->box_line_width);
+ }
+
+ take_vertical_position_into_account (it);
+
+ if (it->glyph_row)
+ {
+ struct glyph *glyph;
+ enum glyph_row_area area = it->area;
+
+ glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
+ if (glyph < it->glyph_row->glyphs[area + 1])
+ {
+ glyph->charpos = CHARPOS (it->position);
+ glyph->object = it->object;
+ glyph->pixel_width = it->pixel_width;
+ glyph->voffset = it->voffset;
+ glyph->type = IMAGE_GLYPH;
+ glyph->multibyte_p = it->multibyte_p;
+ glyph->left_box_line_p = it->start_of_box_run_p;
+ glyph->right_box_line_p = it->end_of_box_run_p;
+ glyph->overlaps_vertically_p = 0;
+ glyph->padding_p = 0;
+ glyph->glyph_not_available_p = 0;
+ glyph->face_id = it->face_id;
+ glyph->u.img_id = img->id;
+ ++it->glyph_row->used[area];
+ }
+ }
+}
+
+
+/* Append a stretch glyph to IT->glyph_row. OBJECT is the source
+ of the glyph, WIDTH and HEIGHT are the width and height of the
+ stretch. ASCENT is the percentage/100 of HEIGHT to use for the
+ ascent of the glyph (0 <= ASCENT <= 1). */
+
+static void
+x_append_stretch_glyph (it, object, width, height, ascent)
+ struct it *it;
+ Lisp_Object object;
+ int width, height;
+ double ascent;
+{
+ struct glyph *glyph;
+ enum glyph_row_area area = it->area;
+
+ xassert (ascent >= 0 && ascent <= 1);
+
+ glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
+ if (glyph < it->glyph_row->glyphs[area + 1])
+ {
+ glyph->charpos = CHARPOS (it->position);
+ glyph->object = object;
+ glyph->pixel_width = width;
+ glyph->voffset = it->voffset;
+ glyph->type = STRETCH_GLYPH;
+ glyph->multibyte_p = it->multibyte_p;
+ glyph->left_box_line_p = it->start_of_box_run_p;
+ glyph->right_box_line_p = it->end_of_box_run_p;
+ glyph->overlaps_vertically_p = 0;
+ glyph->padding_p = 0;
+ glyph->glyph_not_available_p = 0;
+ glyph->face_id = it->face_id;
+ glyph->u.stretch.ascent = height * ascent;
+ glyph->u.stretch.height = height;
+ ++it->glyph_row->used[area];
+ }
+}
+
+
+/* Produce a stretch glyph for iterator IT. IT->object is the value
+ of the glyph property displayed. The value must be a list
+ `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
+ being recognized:
+
+ 1. `:width WIDTH' specifies that the space should be WIDTH *
+ canonical char width wide. WIDTH may be an integer or floating
+ point number.
+
+ 2. `:relative-width FACTOR' specifies that the width of the stretch
+ should be computed from the width of the first character having the
+ `glyph' property, and should be FACTOR times that width.
+
+ 3. `:align-to HPOS' specifies that the space should be wide enough
+ to reach HPOS, a value in canonical character units.
+
+ Exactly one of the above pairs must be present.
+
+ 4. `:height HEIGHT' specifies that the height of the stretch produced
+ should be HEIGHT, measured in canonical character units.
+
+ 5. `:relative-height FACTOR' specifies that the height of the
+ stretch should be FACTOR times the height of the characters having
+ the glyph property.
+
+ Either none or exactly one of 4 or 5 must be present.
+
+ 6. `:ascent ASCENT' specifies that ASCENT percent of the height
+ of the stretch should be used for the ascent of the stretch.
+ ASCENT must be in the range 0 <= ASCENT <= 100. */
+
+#define NUMVAL(X) \
+ ((INTEGERP (X) || FLOATP (X)) \
+ ? XFLOATINT (X) \
+ : - 1)
+
+
+static void
+x_produce_stretch_glyph (it)
+ struct it *it;
+{
+ /* (space :width WIDTH :height HEIGHT. */
+#if GLYPH_DEBUG
+ extern Lisp_Object Qspace;
+#endif
+ extern Lisp_Object QCwidth, QCheight, QCascent;
+ extern Lisp_Object QCrelative_width, QCrelative_height;
+ extern Lisp_Object QCalign_to;
+ Lisp_Object prop, plist;
+ double width = 0, height = 0, ascent = 0;
+ struct face *face = FACE_FROM_ID (it->f, it->face_id);
+ XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
+
+ PREPARE_FACE_FOR_DISPLAY (it->f, face);
+
+ /* List should start with `space'. */
+ xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
+ plist = XCDR (it->object);
+
+ /* Compute the width of the stretch. */
+ if (prop = Fplist_get (plist, QCwidth),
+ NUMVAL (prop) > 0)
+ /* Absolute width `:width WIDTH' specified and valid. */
+ width = NUMVAL (prop) * CANON_X_UNIT (it->f);
+ else if (prop = Fplist_get (plist, QCrelative_width),
+ NUMVAL (prop) > 0)
+ {
+ /* Relative width `:relative-width FACTOR' specified and valid.
+ Compute the width of the characters having the `glyph'
+ property. */
+ struct it it2;
+ unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
+
+ it2 = *it;
+ if (it->multibyte_p)
+ {
+ int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
+ - IT_BYTEPOS (*it));
+ it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
+ }
+ else
+ it2.c = *p, it2.len = 1;
+
+ it2.glyph_row = NULL;
+ it2.what = IT_CHARACTER;
+ x_produce_glyphs (&it2);
+ width = NUMVAL (prop) * it2.pixel_width;
+ }
+ else if (prop = Fplist_get (plist, QCalign_to),
+ NUMVAL (prop) > 0)
+ width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
+ else
+ /* Nothing specified -> width defaults to canonical char width. */
+ width = CANON_X_UNIT (it->f);
+
+ /* Compute height. */
+ if (prop = Fplist_get (plist, QCheight),
+ NUMVAL (prop) > 0)
+ height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
+ else if (prop = Fplist_get (plist, QCrelative_height),
+ NUMVAL (prop) > 0)
+ height = FONT_HEIGHT (font) * NUMVAL (prop);
+ else
+ height = FONT_HEIGHT (font);
+
+ /* Compute percentage of height used for ascent. If
+ `:ascent ASCENT' is present and valid, use that. Otherwise,
+ derive the ascent from the font in use. */
+ if (prop = Fplist_get (plist, QCascent),
+ NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
+ ascent = NUMVAL (prop) / 100.0;
+ else
+ ascent = (double) FONT_BASE (font) / FONT_HEIGHT (font);
+
+ if (width <= 0)
+ width = 1;
+ if (height <= 0)
+ height = 1;
+
+ if (it->glyph_row)
+ {
+ Lisp_Object object = it->stack[it->sp - 1].string;
+ if (!STRINGP (object))
+ object = it->w->buffer;
+ x_append_stretch_glyph (it, object, width, height, ascent);
+ }
+
+ it->pixel_width = width;
+ it->ascent = it->phys_ascent = height * ascent;
+ it->descent = it->phys_descent = height - it->ascent;
+ it->nglyphs = 1;
+
+ if (face->box != FACE_NO_BOX)
+ {
+ if (face->box_line_width > 0)
+ {
+ it->ascent += face->box_line_width;
+ it->descent += face->box_line_width;
+ }
+
+ if (it->start_of_box_run_p)
+ it->pixel_width += abs (face->box_line_width);
+ if (it->end_of_box_run_p)
+ it->pixel_width += abs (face->box_line_width);
+ }
+
+ take_vertical_position_into_account (it);
+}
+
+/* Return proper value to be used as baseline offset of font that has
+ ASCENT and DESCENT to draw characters by the font at the vertical
+ center of the line of frame F.
+
+ Here, out task is to find the value of BOFF in the following figure;
+
+ -------------------------+-----------+-
+ -+-+---------+-+ | |
+ | | | | | |
+ | | | | F_ASCENT F_HEIGHT
+ | | | ASCENT | |
+ HEIGHT | | | | |
+ | | |-|-+------+-----------|------- baseline
+ | | | | BOFF | |
+ | |---------|-+-+ | |
+ | | | DESCENT | |
+ -+-+---------+-+ F_DESCENT |
+ -------------------------+-----------+-
+
+ -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
+ BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
+ DESCENT = FONT->descent
+ HEIGHT = FONT_HEIGHT (FONT)
+ F_DESCENT = (F->output_data.x->font->descent
+ - F->output_data.x->baseline_offset)
+ F_HEIGHT = FRAME_LINE_HEIGHT (F)
+*/
+
+#define VCENTER_BASELINE_OFFSET(FONT, F) \
+ (FONT_DESCENT (FONT) \
+ + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
+ + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
+ - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F)))
+
+/* Produce glyphs/get display metrics for the display element IT is
+ loaded with. See the description of struct display_iterator in
+ dispextern.h for an overview of struct display_iterator. */
+
+static void
+x_produce_glyphs (it)
+ struct it *it;
+{
+ it->glyph_not_available_p = 0;
+
+ if (it->what == IT_CHARACTER)
+ {
+ XChar2b char2b;
+ XFontStruct *font;
+ struct face *face = FACE_FROM_ID (it->f, it->face_id);
+ XCharStruct *pcm;
+ int font_not_found_p;
+ struct font_info *font_info;
+ int boff; /* baseline offset */
+ /* We may change it->multibyte_p upon unibyte<->multibyte
+ conversion. So, save the current value now and restore it
+ later.
+
+ Note: It seems that we don't have to record multibyte_p in
+ struct glyph because the character code itself tells if or
+ not the character is multibyte. Thus, in the future, we must
+ consider eliminating the field `multibyte_p' in the struct
+ glyph.
+ */
+ int saved_multibyte_p = it->multibyte_p;
+
+ /* Maybe translate single-byte characters to multibyte, or the
+ other way. */
+ it->char_to_display = it->c;
+ if (!ASCII_BYTE_P (it->c))
+ {
+ if (unibyte_display_via_language_environment
+ && SINGLE_BYTE_CHAR_P (it->c)
+ && (it->c >= 0240
+ || !NILP (Vnonascii_translation_table)))
+ {
+ it->char_to_display = unibyte_char_to_multibyte (it->c);
+ it->multibyte_p = 1;
+ it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
+ face = FACE_FROM_ID (it->f, it->face_id);
+ }
+ else if (!SINGLE_BYTE_CHAR_P (it->c)
+ && !it->multibyte_p)
+ {
+ it->multibyte_p = 1;
+ it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
+ face = FACE_FROM_ID (it->f, it->face_id);
+ }
+ }
+
+ /* Get font to use. Encode IT->char_to_display. */
+ x_get_char_face_and_encoding (it->f, it->char_to_display,
+ it->face_id, &char2b,
+ it->multibyte_p);
+ font = face->font;
+
+ /* When no suitable font found, use the default font. */
+ font_not_found_p = font == NULL;
+ if (font_not_found_p)
+ {
+ font = FRAME_FONT (it->f);
+ boff = it->f->output_data.mac->baseline_offset;
+ font_info = NULL;
+ }
+ else
+ {
+ font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
+ boff = font_info->baseline_offset;
+ if (font_info->vertical_centering)
+ boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
+ }
+
+ if (it->char_to_display >= ' '
+ && (!it->multibyte_p || it->char_to_display < 128))
+ {
+ /* Either unibyte or ASCII. */
+ int stretched_p;
+
+ it->nglyphs = 1;
+
+ pcm = x_per_char_metric (font, &char2b);
+ it->ascent = FONT_BASE (font) + boff;
+ it->descent = FONT_DESCENT (font) - boff;
+
+ if (pcm)
+ {
+ it->phys_ascent = pcm->ascent + boff;
+ it->phys_descent = pcm->descent - boff;
+ it->pixel_width = pcm->width;
+ }
+ else
+ {
+ it->glyph_not_available_p = 1;
+ it->phys_ascent = FONT_BASE (font) + boff;
+ it->phys_descent = FONT_DESCENT (font) - boff;
+ it->pixel_width = FONT_WIDTH (font);
+ }
+
+ /* If this is a space inside a region of text with
+ `space-width' property, change its width. */
+ stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
+ if (stretched_p)
+ it->pixel_width *= XFLOATINT (it->space_width);
+
+ /* If face has a box, add the box thickness to the character
+ height. If character has a box line to the left and/or
+ right, add the box line width to the character's width. */
+ if (face->box != FACE_NO_BOX)
+ {
+ int thick = face->box_line_width;
+
+ if (thick > 0)
+ {
+ it->ascent += thick;
+ it->descent += thick;
+ }
+ else
+ thick = -thick;
+
+ if (it->start_of_box_run_p)
+ it->pixel_width += thick;
+ if (it->end_of_box_run_p)
+ it->pixel_width += thick;
+ }
+
+ /* If face has an overline, add the height of the overline
+ (1 pixel) and a 1 pixel margin to the character height. */
+ if (face->overline_p)
+ it->ascent += 2;
+
+ take_vertical_position_into_account (it);
+
+ /* If we have to actually produce glyphs, do it. */
+ if (it->glyph_row)
+ {
+ if (stretched_p)
+ {
+ /* Translate a space with a `space-width' property
+ into a stretch glyph. */
+ double ascent = (double) FONT_BASE (font)
+ / FONT_HEIGHT (font);
+ x_append_stretch_glyph (it, it->object, it->pixel_width,
+ it->ascent + it->descent, ascent);
+ }
+ else
+ x_append_glyph (it);
+
+ /* If characters with lbearing or rbearing are displayed
+ in this line, record that fact in a flag of the
+ glyph row. This is used to optimize X output code. */
+ if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
+ it->glyph_row->contains_overlapping_glyphs_p = 1;
+ }
+ }
+ else if (it->char_to_display == '\n')
+ {
+ /* A newline has no width but we need the height of the line. */
+ it->pixel_width = 0;
+ it->nglyphs = 0;
+ it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
+ it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
+
+ if (face->box != FACE_NO_BOX
+ && face->box_line_width > 0)
+ {
+ it->ascent += face->box_line_width;
+ it->descent += face->box_line_width;
+ }
+ }
+ else if (it->char_to_display == '\t')
+ {
+ int tab_width = it->tab_width * CANON_X_UNIT (it->f);
+ int x = it->current_x + it->continuation_lines_width;
+ int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
+
+ /* If the distance from the current position to the next tab
+ stop is less than a canonical character width, use the
+ tab stop after that. */
+ if (next_tab_x - x < CANON_X_UNIT (it->f))
+ next_tab_x += tab_width;
+
+ it->pixel_width = next_tab_x - x;
+ it->nglyphs = 1;
+ it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
+ it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
+
+ if (it->glyph_row)
+ {
+ double ascent = (double) it->ascent / (it->ascent + it->descent);
+ x_append_stretch_glyph (it, it->object, it->pixel_width,
+ it->ascent + it->descent, ascent);
+ }
+ }
+ else
+ {
+ /* A multi-byte character. Assume that the display width of the
+ character is the width of the character multiplied by the
+ width of the font. */
+
+ /* If we found a font, this font should give us the right
+ metrics. If we didn't find a font, use the frame's
+ default font and calculate the width of the character
+ from the charset width; this is what old redisplay code
+ did. */
+ pcm = x_per_char_metric (font, &char2b);
+ if (font_not_found_p || !pcm)
+ {
+ int charset = CHAR_CHARSET (it->char_to_display);
+
+ it->glyph_not_available_p = 1;
+ it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
+ * CHARSET_WIDTH (charset));
+ it->phys_ascent = FONT_BASE (font) + boff;
+ it->phys_descent = FONT_DESCENT (font) - boff;
+ }
+ else
+ {
+ it->pixel_width = pcm->width;
+ it->phys_ascent = pcm->ascent + boff;
+ it->phys_descent = pcm->descent - boff;
+ if (it->glyph_row
+ && (pcm->lbearing < 0
+ || pcm->rbearing > pcm->width))
+ it->glyph_row->contains_overlapping_glyphs_p = 1;
+ }
+ it->nglyphs = 1;
+ it->ascent = FONT_BASE (font) + boff;
+ it->descent = FONT_DESCENT (font) - boff;
+ if (face->box != FACE_NO_BOX)
+ {
+ int thick = face->box_line_width;
+
+ if (thick > 0)
+ {
+ it->ascent += thick;
+ it->descent += thick;
+ }
+ else
+ thick = - thick;
+
+ if (it->start_of_box_run_p)
+ it->pixel_width += thick;
+ if (it->end_of_box_run_p)
+ it->pixel_width += thick;
+ }
+
+ /* If face has an overline, add the height of the overline
+ (1 pixel) and a 1 pixel margin to the character height. */
+ if (face->overline_p)
+ it->ascent += 2;
+
+ take_vertical_position_into_account (it);
+
+ if (it->glyph_row)
+ x_append_glyph (it);
+ }
+ it->multibyte_p = saved_multibyte_p;
+ }
+ else if (it->what == IT_COMPOSITION)
+ {
+ /* Note: A composition is represented as one glyph in the
+ glyph matrix. There are no padding glyphs. */
+ XChar2b char2b;
+ XFontStruct *font;
+ struct face *face = FACE_FROM_ID (it->f, it->face_id);
+ XCharStruct *pcm;
+ int font_not_found_p;
+ struct font_info *font_info;
+ int boff; /* baseline offset */
+ struct composition *cmp = composition_table[it->cmp_id];
+
+ /* Maybe translate single-byte characters to multibyte. */
+ it->char_to_display = it->c;
+ if (unibyte_display_via_language_environment
+ && SINGLE_BYTE_CHAR_P (it->c)
+ && (it->c >= 0240
+ || (it->c >= 0200
+ && !NILP (Vnonascii_translation_table))))
+ {
+ it->char_to_display = unibyte_char_to_multibyte (it->c);
+ }
+
+ /* Get face and font to use. Encode IT->char_to_display. */
+ it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
+ face = FACE_FROM_ID (it->f, it->face_id);
+ x_get_char_face_and_encoding (it->f, it->char_to_display,
+ it->face_id, &char2b, it->multibyte_p);
+ font = face->font;
+
+ /* When no suitable font found, use the default font. */
+ font_not_found_p = font == NULL;
+ if (font_not_found_p)
+ {
+ font = FRAME_FONT (it->f);
+ boff = it->f->output_data.mac->baseline_offset;
+ font_info = NULL;
+ }
+ else
+ {
+ font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
+ boff = font_info->baseline_offset;
+ if (font_info->vertical_centering)
+ boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
+ }
+
+ /* There are no padding glyphs, so there is only one glyph to
+ produce for the composition. Important is that pixel_width,
+ ascent and descent are the values of what is drawn by
+ draw_glyphs (i.e. the values of the overall glyphs composed). */
+ it->nglyphs = 1;
+
+ /* If we have not yet calculated pixel size data of glyphs of
+ the composition for the current face font, calculate them
+ now. Theoretically, we have to check all fonts for the
+ glyphs, but that requires much time and memory space. So,
+ here we check only the font of the first glyph. This leads
+ to incorrect display very rarely, and C-l (recenter) can
+ correct the display anyway. */
+ if (cmp->font != (void *) font)
+ {
+ /* Ascent and descent of the font of the first character of
+ this composition (adjusted by baseline offset). Ascent
+ and descent of overall glyphs should not be less than
+ them respectively. */
+ int font_ascent = FONT_BASE (font) + boff;
+ int font_descent = FONT_DESCENT (font) - boff;
+ /* Bounding box of the overall glyphs. */
+ int leftmost, rightmost, lowest, highest;
+ int i, width, ascent, descent;
+
+ cmp->font = (void *) font;
+
+ /* Initialize the bounding box. */
+ pcm = x_per_char_metric (font, &char2b);
+ if (pcm)
+ {
+ width = pcm->width;
+ ascent = pcm->ascent;
+ descent = pcm->descent;
+ }
+ else
+ {
+ width = FONT_WIDTH (font);
+ ascent = FONT_BASE (font);
+ descent = FONT_DESCENT (font);
+ }
+
+ rightmost = width;
+ lowest = - descent + boff;
+ highest = ascent + boff;
+ leftmost = 0;
+
+ if (font_info
+ && font_info->default_ascent
+ && CHAR_TABLE_P (Vuse_default_ascent)
+ && !NILP (Faref (Vuse_default_ascent,
+ make_number (it->char_to_display))))
+ highest = font_info->default_ascent + boff;
+
+ /* Draw the first glyph at the normal position. It may be
+ shifted to right later if some other glyphs are drawn at
+ the left. */
+ cmp->offsets[0] = 0;
+ cmp->offsets[1] = boff;
+
+ /* Set cmp->offsets for the remaining glyphs. */
+ for (i = 1; i < cmp->glyph_len; i++)
+ {
+ int left, right, btm, top;
+ int ch = COMPOSITION_GLYPH (cmp, i);
+ int face_id = FACE_FOR_CHAR (it->f, face, ch);
+
+ face = FACE_FROM_ID (it->f, face_id);
+ x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
+ it->multibyte_p);
+ font = face->font;
+ if (font == NULL)
+ {
+ font = FRAME_FONT (it->f);
+ boff = it->f->output_data.mac->baseline_offset;
+ font_info = NULL;
+ }
+ else
+ {
+ font_info
+ = FONT_INFO_FROM_ID (it->f, face->font_info_id);
+ boff = font_info->baseline_offset;
+ if (font_info->vertical_centering)
+ boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
+ }
+
+ pcm = x_per_char_metric (font, &char2b);
+ if (pcm)
+ {
+ width = pcm->width;
+ ascent = pcm->ascent;
+ descent = pcm->descent;
+ }
+ else
+ {
+ width = FONT_WIDTH (font);
+ ascent = 1;
+ descent = 0;
+ }
+
+ if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
+ {
+ /* Relative composition with or without
+ alternate chars. */
+ left = (leftmost + rightmost - width) / 2;
+ btm = - descent + boff;
+ if (font_info && font_info->relative_compose
+ && (! CHAR_TABLE_P (Vignore_relative_composition)
+ || NILP (Faref (Vignore_relative_composition,
+ make_number (ch)))))
+ {
+
+ if (- descent >= font_info->relative_compose)
+ /* One extra pixel between two glyphs. */
+ btm = highest + 1;
+ else if (ascent <= 0)
+ /* One extra pixel between two glyphs. */
+ btm = lowest - 1 - ascent - descent;
+ }
+ }
+ else
+ {
+ /* A composition rule is specified by an integer
+ value that encodes global and new reference
+ points (GREF and NREF). GREF and NREF are
+ specified by numbers as below:
+
+ 0---1---2 -- ascent
+ | |
+ | |
+ | |
+ 9--10--11 -- center
+ | |
+ ---3---4---5--- baseline
+ | |
+ 6---7---8 -- descent
+ */
+ int rule = COMPOSITION_RULE (cmp, i);
+ int gref, nref, grefx, grefy, nrefx, nrefy;
+
+ COMPOSITION_DECODE_RULE (rule, gref, nref);
+ grefx = gref % 3, nrefx = nref % 3;
+ grefy = gref / 3, nrefy = nref / 3;
+
+ left = (leftmost
+ + grefx * (rightmost - leftmost) / 2
+ - nrefx * width / 2);
+ btm = ((grefy == 0 ? highest
+ : grefy == 1 ? 0
+ : grefy == 2 ? lowest
+ : (highest + lowest) / 2)
+ - (nrefy == 0 ? ascent + descent
+ : nrefy == 1 ? descent - boff
+ : nrefy == 2 ? 0
+ : (ascent + descent) / 2));
+ }
+
+ cmp->offsets[i * 2] = left;
+ cmp->offsets[i * 2 + 1] = btm + descent;
+
+ /* Update the bounding box of the overall glyphs. */
+ right = left + width;
+ top = btm + descent + ascent;
+ if (left < leftmost)
+ leftmost = left;
+ if (right > rightmost)
+ rightmost = right;
+ if (top > highest)
+ highest = top;
+ if (btm < lowest)
+ lowest = btm;
+ }
+
+ /* If there are glyphs whose x-offsets are negative,
+ shift all glyphs to the right and make all x-offsets
+ non-negative. */
+ if (leftmost < 0)
+ {
+ for (i = 0; i < cmp->glyph_len; i++)
+ cmp->offsets[i * 2] -= leftmost;
+ rightmost -= leftmost;
+ }
+
+ cmp->pixel_width = rightmost;
+ cmp->ascent = highest;
+ cmp->descent = - lowest;
+ if (cmp->ascent < font_ascent)
+ cmp->ascent = font_ascent;
+ if (cmp->descent < font_descent)
+ cmp->descent = font_descent;
+ }
+
+ it->pixel_width = cmp->pixel_width;
+ it->ascent = it->phys_ascent = cmp->ascent;
+ it->descent = it->phys_descent = cmp->descent;
+
+ if (face->box != FACE_NO_BOX)
+ {
+ int thick = face->box_line_width;
+
+ if (thick > 0)
+ {
+ it->ascent += thick;
+ it->descent += thick;
+ }
+ else
+ thick = - thick;
+
+ if (it->start_of_box_run_p)
+ it->pixel_width += thick;
+ if (it->end_of_box_run_p)
+ it->pixel_width += thick;
+ }
+
+ /* If face has an overline, add the height of the overline
+ (1 pixel) and a 1 pixel margin to the character height. */
+ if (face->overline_p)
+ it->ascent += 2;
+
+ take_vertical_position_into_account (it);
+
+ if (it->glyph_row)
+ x_append_composite_glyph (it);
+ }
+ else if (it->what == IT_IMAGE)
+ x_produce_image_glyph (it);
+ else if (it->what == IT_STRETCH)
+ x_produce_stretch_glyph (it);
+
+ /* Accumulate dimensions. Note: can't assume that it->descent > 0
+ because this isn't true for images with `:ascent 100'. */
+ xassert (it->ascent >= 0 && it->descent >= 0);
+ if (it->area == TEXT_AREA)
+ it->current_x += it->pixel_width;
+
+ it->descent += it->extra_line_spacing;
+
+ it->max_ascent = max (it->max_ascent, it->ascent);
+ it->max_descent = max (it->max_descent, it->descent);
+ it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
+ it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
+}
+
+
+/* Estimate the pixel height of the mode or top line on frame F.
+ FACE_ID specifies what line's height to estimate. */
+
+int
+x_estimate_mode_line_height (f, face_id)
+ struct frame *f;
+ enum face_id face_id;
+{
+ int height = FONT_HEIGHT (FRAME_FONT (f));
+
+ /* This function is called so early when Emacs starts that the face
+ cache and mode line face are not yet initialized. */
+ if (FRAME_FACE_CACHE (f))
+ {
+ struct face *face = FACE_FROM_ID (f, face_id);
+ if (face)
+ {
+ if (face->font)
+ height = FONT_HEIGHT (face->font);
+ if (face->box_line_width > 0)
+ height += 2 * face->box_line_width;
+ }
+ }
+
+ return height;
+}
+
+\f
+/***********************************************************************
+ Glyph display
+ ***********************************************************************/
+
+/* A sequence of glyphs to be drawn in the same face.
+
+ This data structure is not really completely X specific, so it
+ could possibly, at least partially, be useful for other systems. It
+ is currently not part of the external redisplay interface because
+ it's not clear what other systems will need. */
+
+struct glyph_string
+{
+ /* X-origin of the string. */
+ int x;
+
+ /* Y-origin and y-position of the base line of this string. */
+ int y, ybase;
+
+ /* The width of the string, not including a face extension. */
+ int width;
+
+ /* The width of the string, including a face extension. */
+ int background_width;
+
+ /* The height of this string. This is the height of the line this
+ string is drawn in, and can be different from the height of the
+ font the string is drawn in. */
+ int height;
+
+ /* Number of pixels this string overwrites in front of its x-origin.
+ This number is zero if the string has an lbearing >= 0; it is
+ -lbearing, if the string has an lbearing < 0. */
+ int left_overhang;
+
+ /* Number of pixels this string overwrites past its right-most
+ nominal x-position, i.e. x + width. Zero if the string's
+ rbearing is <= its nominal width, rbearing - width otherwise. */
+ int right_overhang;
+
+ /* The frame on which the glyph string is drawn. */
+ struct frame *f;
+
+ /* The window on which the glyph string is drawn. */
+ struct window *w;
+
+ /* X display and window for convenience. */
+ Display *display;
+ Window window;
+
+ /* The glyph row for which this string was built. It determines the
+ y-origin and height of the string. */
+ struct glyph_row *row;
+
+ /* The area within row. */
+ enum glyph_row_area area;
+
+ /* Characters to be drawn, and number of characters. */
+ XChar2b *char2b;
+ int nchars;
+
+ /* A face-override for drawing cursors, mouse face and similar. */
+ enum draw_glyphs_face hl;
+
+ /* Face in which this string is to be drawn. */
+ struct face *face;
+
+ /* Font in which this string is to be drawn. */
+ XFontStruct *font;
+
+ /* Font info for this string. */
+ struct font_info *font_info;
+
+ /* Non-null means this string describes (part of) a composition.
+ All characters from char2b are drawn composed. */
+ struct composition *cmp;
+
+ /* Index of this glyph string's first character in the glyph
+ definition of CMP. If this is zero, this glyph string describes
+ the first character of a composition. */
+ int gidx;
+
+ /* 1 means this glyph strings face has to be drawn to the right end
+ of the window's drawing area. */
+ unsigned extends_to_end_of_line_p : 1;
+
+ /* 1 means the background of this string has been drawn. */
+ unsigned background_filled_p : 1;
+
+ /* 1 means glyph string must be drawn with 16-bit functions. */
+ unsigned two_byte_p : 1;
+
+ /* 1 means that the original font determined for drawing this glyph
+ string could not be loaded. The member `font' has been set to
+ the frame's default font in this case. */
+ unsigned font_not_found_p : 1;
+
+ /* 1 means that the face in which this glyph string is drawn has a
+ stipple pattern. */
+ unsigned stippled_p : 1;
+
+ /* 1 means only the foreground of this glyph string must be drawn,
+ and we should use the physical height of the line this glyph
+ string appears in as clip rect. */
+ unsigned for_overlaps_p : 1;
+
+ /* The GC to use for drawing this glyph string. */
+ GC gc;
+
+ /* A pointer to the first glyph in the string. This glyph
+ corresponds to char2b[0]. Needed to draw rectangles if
+ font_not_found_p is 1. */
+ struct glyph *first_glyph;
+
+ /* Image, if any. */
+ struct image *img;
+
+ struct glyph_string *next, *prev;
+};
+
+
+#if 0
+
+static void
+x_dump_glyph_string (s)
+ struct glyph_string *s;
+{
+ fprintf (stderr, "glyph string\n");
+ fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
+ s->x, s->y, s->width, s->height);
+ fprintf (stderr, " ybase = %d\n", s->ybase);
+ fprintf (stderr, " hl = %d\n", s->hl);
+ fprintf (stderr, " left overhang = %d, right = %d\n",
+ s->left_overhang, s->right_overhang);
+ fprintf (stderr, " nchars = %d\n", s->nchars);
+ fprintf (stderr, " extends to end of line = %d\n",
+ s->extends_to_end_of_line_p);
+ fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
+ fprintf (stderr, " bg width = %d\n", s->background_width);
+}
+
+#endif /* GLYPH_DEBUG */
+
+
+
+static void x_append_glyph_string_lists P_ ((struct glyph_string **,
+ struct glyph_string **,
+ struct glyph_string *,
+ struct glyph_string *));
+static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
+ struct glyph_string **,
+ struct glyph_string *,
+ struct glyph_string *));
+static void x_append_glyph_string P_ ((struct glyph_string **,
+ struct glyph_string **,
+ struct glyph_string *));
+static int x_left_overwritten P_ ((struct glyph_string *));
+static int x_left_overwriting P_ ((struct glyph_string *));
+static int x_right_overwritten P_ ((struct glyph_string *));
+static int x_right_overwriting P_ ((struct glyph_string *));
+static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
+ int));
+static void x_init_glyph_string P_ ((struct glyph_string *,
+ XChar2b *, struct window *,
+ struct glyph_row *,
+ enum glyph_row_area, int,
+ enum draw_glyphs_face));
+static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
+ enum glyph_row_area, int, int,
+ enum draw_glyphs_face, int));
+static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
+static void x_set_glyph_string_gc P_ ((struct glyph_string *));
+static void x_draw_glyph_string_background P_ ((struct glyph_string *,
+ int));
+static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
+static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
+static void x_draw_glyph_string_box P_ ((struct glyph_string *));
+static void x_draw_glyph_string P_ ((struct glyph_string *));
+static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
+static void x_set_cursor_gc P_ ((struct glyph_string *));
+static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
+static void x_set_mouse_face_gc P_ ((struct glyph_string *));
+static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
+ int *, int *));
+static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
+/*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
+ unsigned long *, double, int));*/
+static void x_setup_relief_color P_ ((struct frame *, struct relief *,
+ double, int, unsigned long));
+static void x_setup_relief_colors P_ ((struct glyph_string *));
+static void x_draw_image_glyph_string P_ ((struct glyph_string *));
+static void x_draw_image_relief P_ ((struct glyph_string *));
+static void x_draw_image_foreground P_ ((struct glyph_string *));
+static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
+static void x_fill_image_glyph_string P_ ((struct glyph_string *));
+static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
+ int, int, int));
+static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
+ int, int, int, int, Rect *));
+static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
+ int, int, int, Rect *));
+static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
+ enum glyph_row_area));
+static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
+ struct glyph_row *,
+ enum glyph_row_area, int, int));
+
+#if GLYPH_DEBUG
+static void x_check_font P_ ((struct frame *, XFontStruct *));
+#endif
+
+
+/* Append the list of glyph strings with head H and tail T to the list
+ with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
+
+static INLINE void
+x_append_glyph_string_lists (head, tail, h, t)
+ struct glyph_string **head, **tail;
+ struct glyph_string *h, *t;
+{
+ if (h)
+ {
+ if (*head)
+ (*tail)->next = h;
+ else
+ *head = h;
+ h->prev = *tail;
+ *tail = t;
+ }
+}
+
+
+/* Prepend the list of glyph strings with head H and tail T to the
+ list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
+ result. */
+
+static INLINE void
+x_prepend_glyph_string_lists (head, tail, h, t)
+ struct glyph_string **head, **tail;
+ struct glyph_string *h, *t;
+{
+ if (h)
+ {
+ if (*head)
+ (*head)->prev = t;
+ else
+ *tail = t;
+ t->next = *head;
+ *head = h;
+ }
+}
+
+
+/* Append glyph string S to the list with head *HEAD and tail *TAIL.
+ Set *HEAD and *TAIL to the resulting list. */
+
+static INLINE void
+x_append_glyph_string (head, tail, s)
+ struct glyph_string **head, **tail;
+ struct glyph_string *s;
+{
+ s->next = s->prev = NULL;
+ x_append_glyph_string_lists (head, tail, s, s);
+}
+
+
+/* Set S->gc to a suitable GC for drawing glyph string S in cursor
+ face. */
+
+static void
+x_set_cursor_gc (s)
+ struct glyph_string *s;
+{
+ if (s->font == FRAME_FONT (s->f)
+ && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
+ && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
+ && !s->cmp)
+ s->gc = s->f->output_data.mac->cursor_gc;
+ else
+ {
+ /* Cursor on non-default face: must merge. */
+ XGCValues xgcv;
+ unsigned long mask;
+
+ xgcv.background = s->f->output_data.mac->cursor_pixel;
+ xgcv.foreground = s->face->background;
+
+ /* If the glyph would be invisible, try a different foreground. */
+ if (xgcv.foreground == xgcv.background)
+ xgcv.foreground = s->face->foreground;
+ if (xgcv.foreground == xgcv.background)
+ xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
+ if (xgcv.foreground == xgcv.background)
+ xgcv.foreground = s->face->foreground;
+
+ /* Make sure the cursor is distinct from text in this face. */
+ if (xgcv.background == s->face->background
+ && xgcv.foreground == s->face->foreground)
+ {
+ xgcv.background = s->face->foreground;
+ xgcv.foreground = s->face->background;
+ }
+
+ IF_DEBUG (x_check_font (s->f, s->font));
+ xgcv.font = s->font;
+ mask = GCForeground | GCBackground | GCFont;
+
+ if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
+ XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
+ mask, &xgcv);
+ else
+ FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
+ = XCreateGC (s->display, s->window, mask, &xgcv);
+
+ s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
+ }
+}
+
+
+/* Set up S->gc of glyph string S for drawing text in mouse face. */
+
+static void
+x_set_mouse_face_gc (s)
+ struct glyph_string *s;
+{
+ int face_id;
+ struct face *face;
+
+ /* What face has to be used last for the mouse face? */
+ face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
+ face = FACE_FROM_ID (s->f, face_id);
+ if (face == NULL)
+ face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
+
+ if (s->first_glyph->type == CHAR_GLYPH)
+ face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
+ else
+ face_id = FACE_FOR_CHAR (s->f, face, 0);
+ s->face = FACE_FROM_ID (s->f, face_id);
+ PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
+
+ /* If font in this face is same as S->font, use it. */
+ if (s->font == s->face->font)
+ s->gc = s->face->gc;
+ else
+ {
+ /* Otherwise construct scratch_cursor_gc with values from FACE
+ but font FONT. */
+ XGCValues xgcv;
+ unsigned long mask;
+
+ xgcv.background = s->face->background;
+ xgcv.foreground = s->face->foreground;
+ IF_DEBUG (x_check_font (s->f, s->font));
+ xgcv.font = s->font;
+ mask = GCForeground | GCBackground | GCFont;
+
+ if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
+ XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
+ mask, &xgcv);
+ else
+ FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
+ = XCreateGC (s->display, s->window, mask, &xgcv);
+
+ s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
+ }
+
+ xassert (s->gc != 0);
+}
+
+
+/* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
+ Faces to use in the mode line have already been computed when the
+ matrix was built, so there isn't much to do, here. */
+
+static INLINE void
+x_set_mode_line_face_gc (s)
+ struct glyph_string *s;
+{
+ s->gc = s->face->gc;
+}
+
+
+/* Set S->gc of glyph string S for drawing that glyph string. Set
+ S->stippled_p to a non-zero value if the face of S has a stipple
+ pattern. */
+
+static INLINE void
+x_set_glyph_string_gc (s)
+ struct glyph_string *s;
+{
+ PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
+
+ if (s->hl == DRAW_NORMAL_TEXT)
+ {
+ s->gc = s->face->gc;
+ s->stippled_p = s->face->stipple != 0;
+ }
+ else if (s->hl == DRAW_INVERSE_VIDEO)
+ {
+ x_set_mode_line_face_gc (s);
+ s->stippled_p = s->face->stipple != 0;
+ }
+ else if (s->hl == DRAW_CURSOR)
+ {
+ x_set_cursor_gc (s);
+ s->stippled_p = 0;
+ }
+ else if (s->hl == DRAW_MOUSE_FACE)
+ {
+ x_set_mouse_face_gc (s);
+ s->stippled_p = s->face->stipple != 0;
+ }
+ else if (s->hl == DRAW_IMAGE_RAISED
+ || s->hl == DRAW_IMAGE_SUNKEN)
+ {
+ s->gc = s->face->gc;
+ s->stippled_p = s->face->stipple != 0;
+ }
+ else
+ {
+ s->gc = s->face->gc;
+ s->stippled_p = s->face->stipple != 0;
+ }
+
+ /* GC must have been set. */
+ xassert (s->gc != 0);
+}
+
+
+/* Return in *R the clipping rectangle for glyph string S. */
+
+static void
+x_get_glyph_string_clip_rect (s, r)
+ struct glyph_string *s;
+ Rect *r;
+{
+ int r_height, r_width;
+
+ if (s->row->full_width_p)
+ {
+ /* Draw full-width. X coordinates are relative to S->w->left. */
+ int canon_x = CANON_X_UNIT (s->f);
+
+ r->left = WINDOW_LEFT_MARGIN (s->w) * canon_x;
+ r_width = XFASTINT (s->w->width) * canon_x;
+
+ if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
+ {
+ int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
+ if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
+ r->left -= width;
+ }
+
+ r->left += FRAME_INTERNAL_BORDER_WIDTH (s->f);
+
+ /* Unless displaying a mode or menu bar line, which are always
+ fully visible, clip to the visible part of the row. */
+ if (s->w->pseudo_window_p)
+ r_height = s->row->visible_height;
+ else
+ r_height = s->height;
+ }
+ else
+ {
+ /* This is a text line that may be partially visible. */
+ r->left = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
+ r_width = window_box_width (s->w, s->area);
+ r_height = s->row->visible_height;
+ }
+
+ /* If S draws overlapping rows, it's sufficient to use the top and
+ bottom of the window for clipping because this glyph string
+ intentionally draws over other lines. */
+ if (s->for_overlaps_p)
+ {
+ r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
+ r_height = window_text_bottom_y (s->w) - r->top;
+ }
+ else
+ {
+ /* Don't use S->y for clipping because it doesn't take partially
+ visible lines into account. For example, it can be negative for
+ partially visible lines at the top of a window. */
+ if (!s->row->full_width_p
+ && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
+ r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
+ else
+ r->top = max (0, s->row->y);
+
+ /* If drawing a tool-bar window, draw it over the internal border
+ at the top of the window. */
+ if (s->w == XWINDOW (s->f->tool_bar_window))
+ r->top -= s->f->output_data.mac->internal_border_width;
+ }
+
+ r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top);
+
+ r->bottom = r->top + r_height;
+ r->right = r->left + r_width;
+}
+
+
+/* Set clipping for output of glyph string S. S may be part of a mode
+ line or menu if we don't have X toolkit support. */
+
+static INLINE void
+x_set_glyph_string_clipping (s)
+ struct glyph_string *s;
+{
+ Rect r;
+ x_get_glyph_string_clip_rect (s, &r);
+ mac_set_clip_rectangle (s->display, s->window, &r);
+}
+
+
+/* Compute left and right overhang of glyph string S. If S is a glyph
+ string for a composition, assume overhangs don't exist. */
+
+static INLINE void
+x_compute_glyph_string_overhangs (s)
+ struct glyph_string *s;
+{
+ if (s->cmp == NULL
+ && s->first_glyph->type == CHAR_GLYPH)
+ {
+ XCharStruct cs;
+ int direction, font_ascent, font_descent;
+ XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
+ &font_ascent, &font_descent, &cs);
+ s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
+ s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
+ }
+}
+
+
+/* Compute overhangs and x-positions for glyph string S and its
+ predecessors, or successors. X is the starting x-position for S.
+ BACKWARD_P non-zero means process predecessors. */
+
+static void
+x_compute_overhangs_and_x (s, x, backward_p)
+ struct glyph_string *s;
+ int x;
+ int backward_p;
+{
+ if (backward_p)
+ {
+ while (s)
+ {
+ x_compute_glyph_string_overhangs (s);
+ x -= s->width;
+ s->x = x;
+ s = s->prev;
+ }
+ }
+ else
+ {
+ while (s)
+ {
+ x_compute_glyph_string_overhangs (s);
+ s->x = x;
+ x += s->width;
+ s = s->next;
+ }
+ }
+}
+
+
+/* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
+ frame F. Overhangs of glyphs other than type CHAR_GLYPH are
+ assumed to be zero. */
+
+void
+x_get_glyph_overhangs (glyph, f, left, right)
+ struct glyph *glyph;
+ struct frame *f;
+ int *left, *right;
+{
+ *left = *right = 0;
+
+ if (glyph->type == CHAR_GLYPH)
+ {
+ XFontStruct *font;
+ struct face *face;
+ struct font_info *font_info;
+ XChar2b char2b;
+ XCharStruct *pcm;
+
+ face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
+ font = face->font;
+ font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
+ if (font
+ && (pcm = x_per_char_metric (font, &char2b)))
+ {
+ if (pcm->rbearing > pcm->width)
+ *right = pcm->rbearing - pcm->width;
+ if (pcm->lbearing < 0)
+ *left = -pcm->lbearing;
+ }
+ }
+}
+
+
+/* Return the index of the first glyph preceding glyph string S that
+ is overwritten by S because of S's left overhang. Value is -1
+ if no glyphs are overwritten. */
+
+static int
+x_left_overwritten (s)
+ struct glyph_string *s;
+{
+ int k;
+
+ if (s->left_overhang)
+ {
+ int x = 0, i;
+ struct glyph *glyphs = s->row->glyphs[s->area];
+ int first = s->first_glyph - glyphs;
+
+ for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
+ x -= glyphs[i].pixel_width;
+
+ k = i + 1;
+ }
+ else
+ k = -1;
+
+ return k;
+}
+
+
+/* Return the index of the first glyph preceding glyph string S that
+ is overwriting S because of its right overhang. Value is -1 if no
+ glyph in front of S overwrites S. */
+
+static int
+x_left_overwriting (s)
+ struct glyph_string *s;
+{
+ int i, k, x;
+ struct glyph *glyphs = s->row->glyphs[s->area];
+ int first = s->first_glyph - glyphs;
+
+ k = -1;
+ x = 0;
+ for (i = first - 1; i >= 0; --i)
+ {
+ int left, right;
+ x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
+ if (x + right > 0)
+ k = i;
+ x -= glyphs[i].pixel_width;
+ }
+
+ return k;
+}
+
+
+/* Return the index of the last glyph following glyph string S that is
+ not overwritten by S because of S's right overhang. Value is -1 if
+ no such glyph is found. */
+
+static int
+x_right_overwritten (s)
+ struct glyph_string *s;
+{
+ int k = -1;
+
+ if (s->right_overhang)
+ {
+ int x = 0, i;
+ struct glyph *glyphs = s->row->glyphs[s->area];
+ int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
+ int end = s->row->used[s->area];
+
+ for (i = first; i < end && s->right_overhang > x; ++i)
+ x += glyphs[i].pixel_width;
+
+ k = i;
+ }
+
+ return k;
+}
+
+
+/* Return the index of the last glyph following glyph string S that
+ overwrites S because of its left overhang. Value is negative
+ if no such glyph is found. */
+
+static int
+x_right_overwriting (s)
+ struct glyph_string *s;
+{
+ int i, k, x;
+ int end = s->row->used[s->area];
+ struct glyph *glyphs = s->row->glyphs[s->area];
+ int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
+
+ k = -1;
+ x = 0;
+ for (i = first; i < end; ++i)
+ {
+ int left, right;
+ x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
+ if (x - left < 0)
+ k = i;
+ x += glyphs[i].pixel_width;
+ }
+
+ return k;
+}
+
+
+/* Fill rectangle X, Y, W, H with background color of glyph string S. */
+
+static INLINE void
+x_clear_glyph_string_rect (s, x, y, w, h)
+ struct glyph_string *s;
+ int x, y, w, h;
+{
+ XGCValues xgcv;
+
+ xgcv.foreground = s->gc->background;
+ XFillRectangle (s->display, s->window, &xgcv, x, y, w, h);
+}
+
+
+/* Draw the background of glyph_string S. If S->background_filled_p
+ is non-zero don't draw it. FORCE_P non-zero means draw the
+ background even if it wouldn't be drawn normally. This is used
+ when a string preceding S draws into the background of S, or S
+ contains the first component of a composition. */
+
+static void
+x_draw_glyph_string_background (s, force_p)
+ struct glyph_string *s;
+ int force_p;
+{
+ /* Nothing to do if background has already been drawn or if it
+ shouldn't be drawn in the first place. */
+ if (!s->background_filled_p)
+ {
+ int box_line_width = max (s->face->box_line_width, 0);
+
+#if 0 /* MAC_TODO: stipple */
+ if (s->stippled_p)
+ {
+ /* Fill background with a stipple pattern. */
+ XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
+ XFillRectangle (s->display, s->window, s->gc, s->x,
+ s->y + box_line_width,
+ s->background_width,
+ s->height - 2 * box_line_width);
+ XSetFillStyle (s->display, s->gc, FillSolid);
+ s->background_filled_p = 1;
+ }
+ else
+#endif
+ if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
+ || s->font_not_found_p
+ || s->extends_to_end_of_line_p
+ || force_p)
+ {
+ x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
+ s->background_width,
+ s->height - 2 * box_line_width);
+ s->background_filled_p = 1;
+ }
+ }
+}
+
+
+/* Draw the foreground of glyph string S. */
+
+static void
+x_draw_glyph_string_foreground (s)
+ struct glyph_string *s;
+{
+ int i, x;
+
+ /* If first glyph of S has a left box line, start drawing the text
+ of S to the right of that box line. */
+ if (s->face->box != FACE_NO_BOX
+ && s->first_glyph->left_box_line_p)
+ x = s->x + abs (s->face->box_line_width);
+ else
+ x = s->x;
+
+ /* Draw characters of S as rectangles if S's font could not be
+ loaded. */
+ if (s->font_not_found_p)
+ {
+ for (i = 0; i < s->nchars; ++i)
+ {
+ struct glyph *g = s->first_glyph + i;
+ mac_draw_rectangle (s->display, s->window,
+ s->gc, x, s->y, g->pixel_width - 1,
+ s->height - 1);
+ x += g->pixel_width;
+ }
+ }
+ else
+ {
+ char *char1b = (char *) s->char2b;
+ int boff = s->font_info->baseline_offset;
+
+ if (s->font_info->vertical_centering)
+ boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
+
+ /* If we can use 8-bit functions, condense S->char2b. */
+ if (!s->two_byte_p)
+ for (i = 0; i < s->nchars; ++i)
+ char1b[i] = s->char2b[i].byte2;
+
+ /* Draw text with XDrawString if background has already been
+ filled. Otherwise, use XDrawImageString. (Note that
+ XDrawImageString is usually faster than XDrawString.) Always
+ use XDrawImageString when drawing the cursor so that there is
+ no chance that characters under a box cursor are invisible. */
+ if (s->for_overlaps_p
+ || (s->background_filled_p && s->hl != DRAW_CURSOR))
+ {
+ /* Draw characters with 16-bit or 8-bit functions. */
+ if (s->two_byte_p)
+ XDrawString16 (s->display, s->window, s->gc, x,
+ s->ybase - boff, s->char2b, s->nchars);
+ else
+ XDrawString (s->display, s->window, s->gc, x,
+ s->ybase - boff, char1b, s->nchars);
+ }
+ else
+ {
+ if (s->two_byte_p)
+ XDrawImageString16 (s->display, s->window, s->gc, x,
+ s->ybase - boff, s->char2b, s->nchars);
+ else
+ XDrawImageString (s->display, s->window, s->gc, x,
+ s->ybase - boff, char1b, s->nchars);
+ }
+ }
+}
+
+/* Draw the foreground of composite glyph string S. */
+
+static void
+x_draw_composite_glyph_string_foreground (s)
+ struct glyph_string *s;
+{
+ int i, x;
+
+ /* If first glyph of S has a left box line, start drawing the text
+ of S to the right of that box line. */
+ if (s->face->box != FACE_NO_BOX
+ && s->first_glyph->left_box_line_p)
+ x = s->x + abs (s->face->box_line_width);
+ else
+ x = s->x;
+
+ /* S is a glyph string for a composition. S->gidx is the index of
+ the first character drawn for glyphs of this composition.
+ S->gidx == 0 means we are drawing the very first character of
+ this composition. */
+
+ /* Draw a rectangle for the composition if the font for the very
+ first character of the composition could not be loaded. */
+ if (s->font_not_found_p)
+ {
+ if (s->gidx == 0)
+ mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
+ s->width - 1, s->height - 1);
+ }
+ else
+ {
+ for (i = 0; i < s->nchars; i++, ++s->gidx)
+ XDrawString16 (s->display, s->window, s->gc,
+ x + s->cmp->offsets[s->gidx * 2],
+ s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
+ s->char2b + i, 1);
+ }
+}
+
+
+#ifdef USE_X_TOOLKIT
+
+static struct frame *x_frame_of_widget P_ ((Widget));
+
+
+/* Return the frame on which widget WIDGET is used.. Abort if frame
+ cannot be determined. */
+
+static struct frame *
+x_frame_of_widget (widget)
+ Widget widget;
+{
+ struct x_display_info *dpyinfo;
+ Lisp_Object tail;
+ struct frame *f;
+
+ dpyinfo = x_display_info_for_display (XtDisplay (widget));
+
+ /* Find the top-level shell of the widget. Note that this function
+ can be called when the widget is not yet realized, so XtWindow
+ (widget) == 0. That's the reason we can't simply use
+ x_any_window_to_frame. */
+ while (!XtIsTopLevelShell (widget))
+ widget = XtParent (widget);
+
+ /* Look for a frame with that top-level widget. Allocate the color
+ on that frame to get the right gamma correction value. */
+ for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
+ if (GC_FRAMEP (XCAR (tail))
+ && (f = XFRAME (XCAR (tail)),
+ (f->output_data.nothing != 1
+ && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
+ && f->output_data.x->widget == widget)
+ return f;
+
+ abort ();
+}
+
+
+/* Allocate the color COLOR->pixel on the screen and display of
+ widget WIDGET in colormap CMAP. If an exact match cannot be
+ allocated, try the nearest color available. Value is non-zero
+ if successful. This is called from lwlib. */
+
+int
+x_alloc_nearest_color_for_widget (widget, cmap, color)
+ Widget widget;
+ Colormap cmap;
+ XColor *color;
+{
+ struct frame *f = x_frame_of_widget (widget);
+ return x_alloc_nearest_color (f, cmap, color);
+}
+
+
+#endif /* USE_X_TOOLKIT */
+
+#if 0 /* MAC_TODO */
+
+/* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
+ CMAP. If an exact match can't be allocated, try the nearest color
+ available. Value is non-zero if successful. Set *COLOR to the
+ color allocated. */
+
+int
+x_alloc_nearest_color (f, cmap, color)
+ struct frame *f;
+ Colormap cmap;
+ XColor *color;
+{
+ Display *display = FRAME_X_DISPLAY (f);
+ Screen *screen = FRAME_X_SCREEN (f);
+ int rc;
+
+ gamma_correct (f, color);
+ rc = XAllocColor (display, cmap, color);
+ if (rc == 0)
+ {
+ /* If we got to this point, the colormap is full, so we're going
+ to try to get the next closest color. The algorithm used is
+ a least-squares matching, which is what X uses for closest
+ color matching with StaticColor visuals. */
+ int nearest, i;
+ unsigned long nearest_delta = ~0;
+ int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
+ XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
+
+ for (i = 0; i < ncells; ++i)
+ cells[i].pixel = i;
+ XQueryColors (display, cmap, cells, ncells);
+
+ for (nearest = i = 0; i < ncells; ++i)
+ {
+ long dred = (color->red >> 8) - (cells[i].red >> 8);
+ long dgreen = (color->green >> 8) - (cells[i].green >> 8);
+ long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
+ unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
+
+ if (delta < nearest_delta)
+ {
+ nearest = i;
+ nearest_delta = delta;
+ }
+ }
+
+ color->red = cells[nearest].red;
+ color->green = cells[nearest].green;
+ color->blue = cells[nearest].blue;
+ rc = XAllocColor (display, cmap, color);
+ }
+
+#ifdef DEBUG_X_COLORS
+ if (rc)
+ register_color (color->pixel);
+#endif /* DEBUG_X_COLORS */
+
+ return rc;
+}
+
+
+/* Allocate color PIXEL on frame F. PIXEL must already be allocated.
+ It's necessary to do this instead of just using PIXEL directly to
+ get color reference counts right. */
+
+unsigned long
+x_copy_color (f, pixel)
+ struct frame *f;
+ unsigned long pixel;
+{
+ XColor color;
+
+ color.pixel = pixel;
+ BLOCK_INPUT;
+ XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
+ XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
+ UNBLOCK_INPUT;
+#ifdef DEBUG_X_COLORS
+ register_color (pixel);
+#endif
+ return color.pixel;
+}
+
+
+/* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
+ It's necessary to do this instead of just using PIXEL directly to
+ get color reference counts right. */
+
+unsigned long
+x_copy_dpy_color (dpy, cmap, pixel)
+ Display *dpy;
+ Colormap cmap;
+ unsigned long pixel;
+{
+ XColor color;
+
+ color.pixel = pixel;
+ BLOCK_INPUT;
+ XQueryColor (dpy, cmap, &color);
+ XAllocColor (dpy, cmap, &color);
+ UNBLOCK_INPUT;
+#ifdef DEBUG_X_COLORS
+ register_color (pixel);
+#endif
+ return color.pixel;
+}
+
+#endif /* MAC_TODO */
+
+/* Allocate a color which is lighter or darker than *COLOR by FACTOR
+ or DELTA. Try a color with RGB values multiplied by FACTOR first.
+ If this produces the same color as COLOR, try a color where all RGB
+ values have DELTA added. Return the allocated color in *COLOR.
+ DISPLAY is the X display, CMAP is the colormap to operate on.
+ Value is non-zero if successful. */
+
+static int
+mac_alloc_lighter_color (f, color, factor, delta)
+ struct frame *f;
+ unsigned long *color;
+ double factor;
+ int delta;
+{
+ unsigned long new;
+
+ /* Change RGB values by specified FACTOR. Avoid overflow! */
+ xassert (factor >= 0);
+ new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
+ min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
+ min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
+ if (new == *color)
+ new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
+ max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
+ max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
+
+ /* MAC_TODO: Map to palette and retry with delta if same? */
+ /* MAC_TODO: Free colors (if using palette)? */
+
+ if (new == *color)
+ return 0;
+
+ *color = new;
+
+ return 1;
+}
+
+
+/* Set up the foreground color for drawing relief lines of glyph
+ string S. RELIEF is a pointer to a struct relief containing the GC
+ with which lines will be drawn. Use a color that is FACTOR or
+ DELTA lighter or darker than the relief's background which is found
+ in S->f->output_data.x->relief_background. If such a color cannot
+ be allocated, use DEFAULT_PIXEL, instead. */
+
+static void
+x_setup_relief_color (f, relief, factor, delta, default_pixel)
+ struct frame *f;
+ struct relief *relief;
+ double factor;
+ int delta;
+ unsigned long default_pixel;
+{
+ XGCValues xgcv;
+ struct mac_output *di = f->output_data.mac;
+ unsigned long mask = GCForeground;
+ unsigned long pixel;
+ unsigned long background = di->relief_background;
+ struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+
+ /* MAC_TODO: Free colors (if using palette)? */
+
+ /* Allocate new color. */
+ xgcv.foreground = default_pixel;
+ pixel = background;
+ if (mac_alloc_lighter_color (f, &pixel, factor, delta))
+ {
+ relief->allocated_p = 1;
+ xgcv.foreground = relief->pixel = pixel;
+ }
+
+ if (relief->gc == 0)
+ {
+#if 0 /* MAC_TODO: stipple */
+ xgcv.stipple = dpyinfo->gray;
+ mask |= GCStipple;
+#endif
+ relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
+ }
+ else
+ XChangeGC (NULL, relief->gc, mask, &xgcv);
+}
+
+
+/* Set up colors for the relief lines around glyph string S. */
+
+static void
+x_setup_relief_colors (s)
+ struct glyph_string *s;
+{
+ struct mac_output *di = s->f->output_data.mac;
+ unsigned long color;
+
+ if (s->face->use_box_color_for_shadows_p)
+ color = s->face->box_color;
+ else
+ {
+ XGCValues xgcv;
+
+ /* Get the background color of the face. */
+ XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
+ color = xgcv.background;
+ }
+
+ if (di->white_relief.gc == 0
+ || color != di->relief_background)
+ {
+ di->relief_background = color;
+ x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
+ WHITE_PIX_DEFAULT (s->f));
+ x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
+ BLACK_PIX_DEFAULT (s->f));
+ }
+}
+
+
+/* Draw a relief on frame F inside the rectangle given by LEFT_X,
+ TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
+ to draw, it must be >= 0. RAISED_P non-zero means draw a raised
+ relief. LEFT_P non-zero means draw a relief on the left side of
+ the rectangle. RIGHT_P non-zero means draw a relief on the right
+ side of the rectangle. CLIP_RECT is the clipping rectangle to use
+ when drawing. */
+
+static void
+x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
+ raised_p, left_p, right_p, clip_rect)
+ struct frame *f;
+ int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
+ Rect *clip_rect;
+{
+ int i;
+ GC gc;
+
+ if (raised_p)
+ gc = f->output_data.mac->white_relief.gc;
+ else
+ gc = f->output_data.mac->black_relief.gc;
+ mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), clip_rect);
+
+ /* Top. */
+ for (i = 0; i < width; ++i)
+ XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
+ left_x + i * left_p, top_y + i,
+ right_x + 1 - i * right_p, top_y + i);
+
+ /* Left. */
+ if (left_p)
+ for (i = 0; i < width; ++i)
+ XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
+ left_x + i, top_y + i, left_x + i, bottom_y - i);
+
+ mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
+ if (raised_p)
+ gc = f->output_data.mac->black_relief.gc;
+ else
+ gc = f->output_data.mac->white_relief.gc;
+ mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
+ clip_rect);
+
+ /* Bottom. */
+ for (i = 0; i < width; ++i)
+ XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
+ left_x + i * left_p, bottom_y - i,
+ right_x + 1 - i * right_p, bottom_y - i);
+
+ /* Right. */
+ if (right_p)
+ for (i = 0; i < width; ++i)
+ XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
+ right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
+
+ mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
+}
+
+
+/* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
+ RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
+ draw, it must be >= 0. LEFT_P non-zero means draw a line on the
+ left side of the rectangle. RIGHT_P non-zero means draw a line
+ on the right side of the rectangle. CLIP_RECT is the clipping
+ rectangle to use when drawing. */
+
+static void
+x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
+ left_p, right_p, clip_rect)
+ struct glyph_string *s;
+ int left_x, top_y, right_x, bottom_y, left_p, right_p;
+ Rect *clip_rect;
+{
+ XGCValues xgcv;
+
+ xgcv.foreground = s->face->box_color;
+ mac_set_clip_rectangle (s->display, s->window, clip_rect);
+
+ /* Top. */
+ XFillRectangle (s->display, s->window, &xgcv,
+ left_x, top_y, right_x - left_x, width);
+
+ /* Left. */
+ if (left_p)
+ XFillRectangle (s->display, s->window, &xgcv,
+ left_x, top_y, width, bottom_y - top_y);
+
+ /* Bottom. */
+ XFillRectangle (s->display, s->window, &xgcv,
+ left_x, bottom_y - width, right_x - left_x, width);
+
+ /* Right. */
+ if (right_p)
+ XFillRectangle (s->display, s->window, &xgcv,
+ right_x - width, top_y, width, bottom_y - top_y);
+
+ mac_reset_clipping (s->display, s->window);
+}
+
+
+/* Draw a box around glyph string S. */
+
+static void
+x_draw_glyph_string_box (s)
+ struct glyph_string *s;
+{
+ int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
+ int left_p, right_p;
+ struct glyph *last_glyph;
+ Rect clip_rect;
+
+ last_x = window_box_right (s->w, s->area);
+ if (s->row->full_width_p
+ && !s->w->pseudo_window_p)
+ {
+ last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
+ if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
+ last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
+ }
+
+ /* The glyph that may have a right box line. */
+ last_glyph = (s->cmp || s->img
+ ? s->first_glyph
+ : s->first_glyph + s->nchars - 1);
+
+ width = abs (s->face->box_line_width);
+ raised_p = s->face->box == FACE_RAISED_BOX;
+ left_x = s->x;
+ right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
+ ? last_x - 1
+ : min (last_x, s->x + s->background_width) - 1));
+ top_y = s->y;
+ bottom_y = top_y + s->height - 1;
+
+ left_p = (s->first_glyph->left_box_line_p
+ || (s->hl == DRAW_MOUSE_FACE
+ && (s->prev == NULL
+ || s->prev->hl != s->hl)));
+ right_p = (last_glyph->right_box_line_p
+ || (s->hl == DRAW_MOUSE_FACE
+ && (s->next == NULL
+ || s->next->hl != s->hl)));
+
+ x_get_glyph_string_clip_rect (s, &clip_rect);
+
+ if (s->face->box == FACE_SIMPLE_BOX)
+ x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
+ left_p, right_p, &clip_rect);
+ else
+ {
+ x_setup_relief_colors (s);
+ x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
+ width, raised_p, left_p, right_p, &clip_rect);
+ }
+}
+
+
+/* Draw foreground of image glyph string S. */
+
+static void
+x_draw_image_foreground (s)
+ struct glyph_string *s;
+{
+ int x;
+ int y = s->ybase - image_ascent (s->img, s->face);
+
+ /* If first glyph of S has a left box line, start drawing it to the
+ right of that line. */
+ if (s->face->box != FACE_NO_BOX
+ && s->first_glyph->left_box_line_p)
+ x = s->x + abs (s->face->box_line_width);
+ else
+ x = s->x;
+
+ /* If there is a margin around the image, adjust x- and y-position
+ by that margin. */
+ x += s->img->hmargin;
+ y += s->img->vmargin;
+
+ if (s->img->pixmap)
+ {
+#if 0 /* MAC_TODO: image mask */
+ if (s->img->mask)
+ {
+ /* We can't set both a clip mask and use XSetClipRectangles
+ because the latter also sets a clip mask. We also can't
+ trust on the shape extension to be available
+ (XShapeCombineRegion). So, compute the rectangle to draw
+ manually. */
+ unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
+ | GCFunction);
+ XGCValues xgcv;
+ XRectangle clip_rect, image_rect, r;
+
+ xgcv.clip_mask = s->img->mask;
+ xgcv.clip_x_origin = x;
+ xgcv.clip_y_origin = y;
+ xgcv.function = GXcopy;
+ XChangeGC (s->display, s->gc, mask, &xgcv);
+
+ x_get_glyph_string_clip_rect (s, &clip_rect);
+ image_rect.x = x;
+ image_rect.y = y;
+ image_rect.width = s->img->width;
+ image_rect.height = s->img->height;
+ if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
+ XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
+ r.x - x, r.y - y, r.width, r.height, r.x, r.y);
+ }
+ else
+#endif /* MAC_TODO */
+ {
+ mac_copy_area (s->display, s->img->pixmap, s->window, s->gc,
+ 0, 0, s->img->width, s->img->height, x, y);
+
+ /* When the image has a mask, we can expect that at
+ least part of a mouse highlight or a block cursor will
+ be visible. If the image doesn't have a mask, make
+ a block cursor visible by drawing a rectangle around
+ the image. I believe it's looking better if we do
+ nothing here for mouse-face. */
+ if (s->hl == DRAW_CURSOR)
+ mac_draw_rectangle (s->display, s->window, s->gc, x, y,
+ s->img->width - 1, s->img->height - 1);
+ }
+ }
+ else
+ /* Draw a rectangle if image could not be loaded. */
+ mac_draw_rectangle (s->display, s->window, s->gc, x, y,
+ s->img->width - 1, s->img->height - 1);
+}
+
+
+
+/* Draw a relief around the image glyph string S. */
+
+static void
+x_draw_image_relief (s)
+ struct glyph_string *s;
+{
+ int x0, y0, x1, y1, thick, raised_p;
+ Rect r;
+ int x;
+ int y = s->ybase - image_ascent (s->img, s->face);
+
+ /* If first glyph of S has a left box line, start drawing it to the
+ right of that line. */
+ if (s->face->box != FACE_NO_BOX
+ && s->first_glyph->left_box_line_p)
+ x = s->x + abs (s->face->box_line_width);
+ else
+ x = s->x;
+
+ /* If there is a margin around the image, adjust x- and y-position
+ by that margin. */
+ x += s->img->hmargin;
+ y += s->img->vmargin;
+
+ if (s->hl == DRAW_IMAGE_SUNKEN
+ || s->hl == DRAW_IMAGE_RAISED)
+ {
+ thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
+ raised_p = s->hl == DRAW_IMAGE_RAISED;
+ }
+ else
+ {
+ thick = abs (s->img->relief);
+ raised_p = s->img->relief > 0;
+ }
+
+ x0 = x - thick;
+ y0 = y - thick;
+ x1 = x + s->img->width + thick - 1;
+ y1 = y + s->img->height + thick - 1;
+
+ x_setup_relief_colors (s);
+ x_get_glyph_string_clip_rect (s, &r);
+ x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
+}
+
+
+/* Draw the foreground of image glyph string S to PIXMAP. */
+
+static void
+x_draw_image_foreground_1 (s, pixmap)
+ struct glyph_string *s;
+ Pixmap pixmap;
+{
+ int x;
+ int y = s->ybase - s->y - image_ascent (s->img, s->face);
+
+ /* If first glyph of S has a left box line, start drawing it to the
+ right of that line. */
+ if (s->face->box != FACE_NO_BOX
+ && s->first_glyph->left_box_line_p)
+ x = abs (s->face->box_line_width);
+ else
+ x = 0;
+
+ /* If there is a margin around the image, adjust x- and y-position
+ by that margin. */
+ x += s->img->hmargin;
+ y += s->img->vmargin;
+
+ if (s->img->pixmap)
+ {
+#if 0 /* MAC_TODO: image mask */
+ if (s->img->mask)
+ {
+ /* We can't set both a clip mask and use XSetClipRectangles
+ because the latter also sets a clip mask. We also can't
+ trust on the shape extension to be available
+ (XShapeCombineRegion). So, compute the rectangle to draw
+ manually. */
+ unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
+ | GCFunction);
+ XGCValues xgcv;
+
+ xgcv.clip_mask = s->img->mask;
+ xgcv.clip_x_origin = x;
+ xgcv.clip_y_origin = y;
+ xgcv.function = GXcopy;
+ XChangeGC (s->display, s->gc, mask, &xgcv);
+
+ XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
+ 0, 0, s->img->width, s->img->height, x, y);
+ XSetClipMask (s->display, s->gc, None);
+ }
+ else
+#endif /* MAC_TODO */
+ {
+ mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
+ 0, 0, s->img->width, s->img->height, x, y);
+
+ /* When the image has a mask, we can expect that at
+ least part of a mouse highlight or a block cursor will
+ be visible. If the image doesn't have a mask, make
+ a block cursor visible by drawing a rectangle around
+ the image. I believe it's looking better if we do
+ nothing here for mouse-face. */
+ if (s->hl == DRAW_CURSOR)
+ mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
+ s->img->width - 1, s->img->height - 1);
+ }
+ }
+ else
+ /* Draw a rectangle if image could not be loaded. */
+ mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
+ s->img->width - 1, s->img->height - 1);
+}
+
+
+/* Draw part of the background of glyph string S. X, Y, W, and H
+ give the rectangle to draw. */
+
+static void
+x_draw_glyph_string_bg_rect (s, x, y, w, h)
+ struct glyph_string *s;
+ int x, y, w, h;
+{
+#if 0 /* MAC_TODO: stipple */
+ if (s->stippled_p)
+ {
+ /* Fill background with a stipple pattern. */
+ XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
+ XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
+ XSetFillStyle (s->display, s->gc, FillSolid);
+ }
+ else
+#endif /* MAC_TODO */
+ x_clear_glyph_string_rect (s, x, y, w, h);
+}
+
+
+/* Draw image glyph string S.
+
+ s->y
+ s->x +-------------------------
+ | s->face->box
+ |
+ | +-------------------------
+ | | s->img->vmargin
+ | |
+ | | +-------------------
+ | | | the image
+
+ */
+
+static void
+x_draw_image_glyph_string (s)
+ struct glyph_string *s;
+{
+ int x, y;
+ int box_line_hwidth = abs (s->face->box_line_width);
+ int box_line_vwidth = max (s->face->box_line_width, 0);
+ int height;
+ Pixmap pixmap = 0;
+
+ height = s->height - 2 * box_line_vwidth;
+
+ /* Fill background with face under the image. Do it only if row is
+ taller than image or if image has a clip mask to reduce
+ flickering. */
+ s->stippled_p = s->face->stipple != 0;
+ if (height > s->img->height
+ || s->img->hmargin
+ || s->img->vmargin
+#if 0 /* TODO: image mask */
+ || s->img->mask
+#endif
+ || s->img->pixmap == 0
+ || s->width != s->background_width)
+ {
+ if (box_line_hwidth && s->first_glyph->left_box_line_p)
+ x = s->x + box_line_hwidth;
+ else
+ x = s->x;
+
+ y = s->y + box_line_vwidth;
+#if 0 /* TODO: image mask */
+ if (s->img->mask)
+ {
+ /* Create a pixmap as large as the glyph string. Fill it
+ with the background color. Copy the image to it, using
+ its mask. Copy the temporary pixmap to the display. */
+ Screen *screen = FRAME_X_SCREEN (s->f);
+ int depth = DefaultDepthOfScreen (screen);
+
+ /* Create a pixmap as large as the glyph string. */
+ pixmap = XCreatePixmap (s->display, s->window,
+ s->background_width,
+ s->height, depth);
+
+ /* Don't clip in the following because we're working on the
+ pixmap. */
+ XSetClipMask (s->display, s->gc, None);
+
+ /* Fill the pixmap with the background color/stipple. */
+ if (s->stippled_p)
+ {
+ /* Fill background with a stipple pattern. */
+ XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
+ XFillRectangle (s->display, pixmap, s->gc,
+ 0, 0, s->background_width, s->height);
+ XSetFillStyle (s->display, s->gc, FillSolid);
+ }
+ else
+ {
+ XGCValues xgcv;
+ XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
+ &xgcv);
+ XSetForeground (s->display, s->gc, xgcv.background);
+ XFillRectangle (s->display, pixmap, s->gc,
+ 0, 0, s->background_width, s->height);
+ XSetForeground (s->display, s->gc, xgcv.foreground);
+ }
+ }
+ else
+#endif
+ x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
+
+ s->background_filled_p = 1;
+ }
+
+ /* Draw the foreground. */
+ if (pixmap != 0)
+ {
+ x_draw_image_foreground_1 (s, pixmap);
+ x_set_glyph_string_clipping (s);
+ mac_copy_area (s->display, pixmap, s->window, s->gc,
+ 0, 0, s->background_width, s->height, s->x, s->y);
+ mac_reset_clipping (s->display, s->window);
+ XFreePixmap (s->display, pixmap);
+ }
+ else
+ x_draw_image_foreground (s);
+
+ /* If we must draw a relief around the image, do it. */
+ if (s->img->relief
+ || s->hl == DRAW_IMAGE_RAISED
+ || s->hl == DRAW_IMAGE_SUNKEN)
+ x_draw_image_relief (s);
+}
+
+
+/* Draw stretch glyph string S. */
+
+static void
+x_draw_stretch_glyph_string (s)
+ struct glyph_string *s;
+{
+ xassert (s->first_glyph->type == STRETCH_GLYPH);
+ s->stippled_p = s->face->stipple != 0;
+
+ if (s->hl == DRAW_CURSOR
+ && !x_stretch_cursor_p)
+ {
+ /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
+ as wide as the stretch glyph. */
+ int width = min (CANON_X_UNIT (s->f), s->background_width);
+
+ /* Draw cursor. */
+ x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
+
+ /* Clear rest using the GC of the original non-cursor face. */
+ if (width < s->background_width)
+ {
+ GC gc = s->face->gc;
+ int x = s->x + width, y = s->y;
+ int w = s->background_width - width, h = s->height;
+ Rect r;
+
+ if (s->row->mouse_face_p
+ && cursor_in_mouse_face_p (s->w))
+ {
+ x_set_mouse_face_gc (s);
+ gc = s->gc;
+ }
+ else
+ gc = s->face->gc;
+
+ x_get_glyph_string_clip_rect (s, &r);
+ mac_set_clip_rectangle (s->display, s->window, &r);
+
+#if 0 /* MAC_TODO: stipple */
+ if (s->face->stipple)
+ {
+ /* Fill background with a stipple pattern. */
+ XSetFillStyle (s->display, gc, FillOpaqueStippled);
+ XFillRectangle (s->display, s->window, gc, x, y, w, h);
+ XSetFillStyle (s->display, gc, FillSolid);
+ }
+ else
+#endif /* MAC_TODO */
+ {
+ XGCValues xgcv;
+ XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
+ XSetForeground (s->display, gc, xgcv.background);
+ XFillRectangle (s->display, s->window, gc, x, y, w, h);
+ XSetForeground (s->display, gc, xgcv.foreground);
+ }
+
+ mac_reset_clipping (s->display, s->window);
+ }
+ }
+ else if (!s->background_filled_p)
+ x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
+ s->height);
+
+ s->background_filled_p = 1;
+}
+
+
+/* Draw glyph string S. */
+
+static void
+x_draw_glyph_string (s)
+ struct glyph_string *s;
+{
+ int relief_drawn_p = 0;
+
+ /* If S draws into the background of its successor, draw the
+ background of the successor first so that S can draw into it.
+ This makes S->next use XDrawString instead of XDrawImageString. */
+ if (s->next && s->right_overhang && !s->for_overlaps_p)
+ {
+ xassert (s->next->img == NULL);
+ x_set_glyph_string_gc (s->next);
+ x_set_glyph_string_clipping (s->next);
+ x_draw_glyph_string_background (s->next, 1);
+
+ }
+
+ /* Set up S->gc, set clipping and draw S. */
+ x_set_glyph_string_gc (s);
+
+ /* Draw relief (if any) in advance for char/composition so that the
+ glyph string can be drawn over it. */
+ if (!s->for_overlaps_p
+ && s->face->box != FACE_NO_BOX
+ && (s->first_glyph->type == CHAR_GLYPH
+ || s->first_glyph->type == COMPOSITE_GLYPH))
+
+ {
+ x_set_glyph_string_clipping (s);
+ x_draw_glyph_string_background (s, 1);
+ x_draw_glyph_string_box (s);
+ x_set_glyph_string_clipping (s);
+ relief_drawn_p = 1;
+ }
+ else
+ x_set_glyph_string_clipping (s);
+
+ switch (s->first_glyph->type)
+ {
+ case IMAGE_GLYPH:
+ x_draw_image_glyph_string (s);
+ break;
+
+ case STRETCH_GLYPH:
+ x_draw_stretch_glyph_string (s);
+ break;
+
+ case CHAR_GLYPH:
+ if (s->for_overlaps_p)
+ s->background_filled_p = 1;
+ else
+ x_draw_glyph_string_background (s, 0);
+ x_draw_glyph_string_foreground (s);
+ break;
+
+ case COMPOSITE_GLYPH:
+ if (s->for_overlaps_p || s->gidx > 0)
+ s->background_filled_p = 1;
+ else
+ x_draw_glyph_string_background (s, 1);
+ x_draw_composite_glyph_string_foreground (s);
+ break;
+
+ default:
+ abort ();
+ }
+
+ if (!s->for_overlaps_p)
+ {
+ /* Draw underline. */
+ if (s->face->underline_p)
+ {
+ unsigned long h = 1;
+ unsigned long dy = s->height - h;
+
+ if (s->face->underline_defaulted_p)
+ XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
+ s->width, h);
+ else
+ {
+ XGCValues xgcv;
+ XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
+ XSetForeground (s->display, s->gc, s->face->underline_color);
+ XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
+ s->width, h);
+ XSetForeground (s->display, s->gc, xgcv.foreground);
+ }
+ }
+
+ /* Draw overline. */
+ if (s->face->overline_p)
+ {
+ unsigned long dy = 0, h = 1;
+
+ if (s->face->overline_color_defaulted_p)
+ XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
+ s->width, h);
+ else
+ {
+ XGCValues xgcv;
+ XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
+ XSetForeground (s->display, s->gc, s->face->overline_color);
+ XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
+ s->width, h);
+ XSetForeground (s->display, s->gc, xgcv.foreground);
+ }
+ }
+
+ /* Draw strike-through. */
+ if (s->face->strike_through_p)
+ {
+ unsigned long h = 1;
+ unsigned long dy = (s->height - h) / 2;
+
+ if (s->face->strike_through_color_defaulted_p)
+ XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
+ s->width, h);
+ else
+ {
+ XGCValues xgcv;
+ XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
+ XSetForeground (s->display, s->gc, s->face->strike_through_color);
+ XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
+ s->width, h);
+ XSetForeground (s->display, s->gc, xgcv.foreground);
+ }
+ }
+
+ /* Draw relief. */
+ if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
+ x_draw_glyph_string_box (s);
+ }
+
+ /* Reset clipping. */
+ mac_reset_clipping (s->display, s->window);
+}
+
+
+static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
+ struct face **, int));
+
+
+/* Fill glyph string S with composition components specified by S->cmp.
+
+ FACES is an array of faces for all components of this composition.
+ S->gidx is the index of the first component for S.
+ OVERLAPS_P non-zero means S should draw the foreground only, and
+ use its physical height for clipping.
+
+ Value is the index of a component not in S. */
+
+static int
+x_fill_composite_glyph_string (s, faces, overlaps_p)
+ struct glyph_string *s;
+ struct face **faces;
+ int overlaps_p;
+{
+ int i;
+
+ xassert (s);
+
+ s->for_overlaps_p = overlaps_p;
+
+ s->face = faces[s->gidx];
+ s->font = s->face->font;
+ s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
+
+ /* For all glyphs of this composition, starting at the offset
+ S->gidx, until we reach the end of the definition or encounter a
+ glyph that requires the different face, add it to S. */
+ ++s->nchars;
+ for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
+ ++s->nchars;
+
+ /* All glyph strings for the same composition has the same width,
+ i.e. the width set for the first component of the composition. */
+
+ s->width = s->first_glyph->pixel_width;
+
+ /* If the specified font could not be loaded, use the frame's
+ default font, but record the fact that we couldn't load it in
+ the glyph string so that we can draw rectangles for the
+ characters of the glyph string. */
+ if (s->font == NULL)
+ {
+ s->font_not_found_p = 1;
+ s->font = FRAME_FONT (s->f);
+ }
+
+ /* Adjust base line for subscript/superscript text. */
+ s->ybase += s->first_glyph->voffset;
+
+ xassert (s->face && s->face->gc);
+
+ /* This glyph string must always be drawn with 16-bit functions. */
+ s->two_byte_p = 1;
+
+ return s->gidx + s->nchars;
+}
+
+
+/* Fill glyph string S from a sequence of character glyphs.
+
+ FACE_ID is the face id of the string. START is the index of the
+ first glyph to consider, END is the index of the last + 1.
+ OVERLAPS_P non-zero means S should draw the foreground only, and
+ use its physical height for clipping.
+
+ Value is the index of the first glyph not in S. */
+
+static int
+x_fill_glyph_string (s, face_id, start, end, overlaps_p)
+ struct glyph_string *s;
+ int face_id;
+ int start, end, overlaps_p;
+{
+ struct glyph *glyph, *last;
+ int voffset;
+ int glyph_not_available_p;
+
+ xassert (s->f == XFRAME (s->w->frame));
+ xassert (s->nchars == 0);
+ xassert (start >= 0 && end > start);
+
+ s->for_overlaps_p = overlaps_p;
+ glyph = s->row->glyphs[s->area] + start;
+ last = s->row->glyphs[s->area] + end;
+ voffset = glyph->voffset;
+
+ glyph_not_available_p = glyph->glyph_not_available_p;
+
+ while (glyph < last
+ && glyph->type == CHAR_GLYPH
+ && glyph->voffset == voffset
+ /* Same face id implies same font, nowadays. */
+ && glyph->face_id == face_id
+ && glyph->glyph_not_available_p == glyph_not_available_p)
+ {
+ int two_byte_p;
+
+ s->face = x_get_glyph_face_and_encoding (s->f, glyph,
+ s->char2b + s->nchars,
+ &two_byte_p);
+ s->two_byte_p = two_byte_p;
+ ++s->nchars;
+ xassert (s->nchars <= end - start);
+ s->width += glyph->pixel_width;
+ ++glyph;
+ }
+
+ s->font = s->face->font;
+ s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
+
+ /* If the specified font could not be loaded, use the frame's font,
+ but record the fact that we couldn't load it in
+ S->font_not_found_p so that we can draw rectangles for the
+ characters of the glyph string. */
+ if (s->font == NULL || glyph_not_available_p)
+ {
+ s->font_not_found_p = 1;
+ s->font = FRAME_FONT (s->f);
+ }
+
+ /* Adjust base line for subscript/superscript text. */
+ s->ybase += voffset;
+
+ xassert (s->face && s->face->gc);
+ return glyph - s->row->glyphs[s->area];
+}
+
+
+/* Fill glyph string S from image glyph S->first_glyph. */
+
+static void
+x_fill_image_glyph_string (s)
+ struct glyph_string *s;
+{
+ xassert (s->first_glyph->type == IMAGE_GLYPH);
+ s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
+ xassert (s->img);
+ s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
+ s->font = s->face->font;
+ s->width = s->first_glyph->pixel_width;
+
+ /* Adjust base line for subscript/superscript text. */
+ s->ybase += s->first_glyph->voffset;
+}
+
+
+/* Fill glyph string S from a sequence of stretch glyphs.
+
+ ROW is the glyph row in which the glyphs are found, AREA is the
+ area within the row. START is the index of the first glyph to
+ consider, END is the index of the last + 1.
+
+ Value is the index of the first glyph not in S. */
+
+static int
+x_fill_stretch_glyph_string (s, row, area, start, end)
+ struct glyph_string *s;
+ struct glyph_row *row;
+ enum glyph_row_area area;
+ int start, end;
+{
+ struct glyph *glyph, *last;
+ int voffset, face_id;
+
+ xassert (s->first_glyph->type == STRETCH_GLYPH);
+
+ glyph = s->row->glyphs[s->area] + start;
+ last = s->row->glyphs[s->area] + end;
+ face_id = glyph->face_id;
+ s->face = FACE_FROM_ID (s->f, face_id);
+ s->font = s->face->font;
+ s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
+ s->width = glyph->pixel_width;
+ voffset = glyph->voffset;
+
+ for (++glyph;
+ (glyph < last
+ && glyph->type == STRETCH_GLYPH
+ && glyph->voffset == voffset
+ && glyph->face_id == face_id);
+ ++glyph)
+ s->width += glyph->pixel_width;
+
+ /* Adjust base line for subscript/superscript text. */
+ s->ybase += voffset;
+
+ xassert (s->face);
+ return glyph - s->row->glyphs[s->area];
+}
+
+
+/* Initialize glyph string S. CHAR2B is a suitably allocated vector
+ of XChar2b structures for S; it can't be allocated in
+ x_init_glyph_string because it must be allocated via `alloca'. W
+ is the window on which S is drawn. ROW and AREA are the glyph row
+ and area within the row from which S is constructed. START is the
+ index of the first glyph structure covered by S. HL is a
+ face-override for drawing S. */
+
+static void
+x_init_glyph_string (s, char2b, w, row, area, start, hl)
+ struct glyph_string *s;
+ XChar2b *char2b;
+ struct window *w;
+ struct glyph_row *row;
+ enum glyph_row_area area;
+ int start;
+ enum draw_glyphs_face hl;
+{
+ bzero (s, sizeof *s);
+ s->w = w;
+ s->f = XFRAME (w->frame);
+ s->display = FRAME_MAC_DISPLAY (s->f);
+ s->window = FRAME_MAC_WINDOW (s->f);
+ s->char2b = char2b;
+ s->hl = hl;
+ s->row = row;
+ s->area = area;
+ s->first_glyph = row->glyphs[area] + start;
+ s->height = row->height;
+ s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
+
+ /* Display the internal border below the tool-bar window. */
+ if (s->w == XWINDOW (s->f->tool_bar_window))
+ s->y -= s->f->output_data.mac->internal_border_width;
+
+ s->ybase = s->y + row->ascent;
+}
+
+
+/* Set background width of glyph string S. START is the index of the
+ first glyph following S. LAST_X is the right-most x-position + 1
+ in the drawing area. */
+
+static INLINE void
+x_set_glyph_string_background_width (s, start, last_x)
+ struct glyph_string *s;
+ int start;
+ int last_x;
+{
+ /* If the face of this glyph string has to be drawn to the end of
+ the drawing area, set S->extends_to_end_of_line_p. */
+ struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
+
+ if (start == s->row->used[s->area]
+ && s->area == TEXT_AREA
+ && ((s->hl == DRAW_NORMAL_TEXT
+ && (s->row->fill_line_p
+ || s->face->background != default_face->background
+ || s->face->stipple != default_face->stipple
+ || s->row->mouse_face_p))
+ || s->hl == DRAW_MOUSE_FACE
+ || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
+ && s->row->fill_line_p)))
+ s->extends_to_end_of_line_p = 1;
+
+ /* If S extends its face to the end of the line, set its
+ background_width to the distance to the right edge of the drawing
+ area. */
+ if (s->extends_to_end_of_line_p)
+ s->background_width = last_x - s->x + 1;
+ else
+ s->background_width = s->width;
+}
+
+
+/* Add a glyph string for a stretch glyph to the list of strings
+ between HEAD and TAIL. START is the index of the stretch glyph in
+ row area AREA of glyph row ROW. END is the index of the last glyph
+ in that glyph row area. X is the current output position assigned
+ to the new glyph string constructed. HL overrides that face of the
+ glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
+ is the right-most x-position of the drawing area. */
+
+/* SunOS 4 bundled cc, barfed on continuations in the arg lists here
+ and below -- keep them on one line. */
+#define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
+ do \
+ { \
+ s = (struct glyph_string *) alloca (sizeof *s); \
+ x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
+ START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
+ x_append_glyph_string (&HEAD, &TAIL, s); \
+ s->x = (X); \
+ } \
+ while (0)
+
+
+/* Add a glyph string for an image glyph to the list of strings
+ between HEAD and TAIL. START is the index of the image glyph in
+ row area AREA of glyph row ROW. END is the index of the last glyph
+ in that glyph row area. X is the current output position assigned
+ to the new glyph string constructed. HL overrides that face of the
+ glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
+ is the right-most x-position of the drawing area. */
+
+#define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
+ do \
+ { \
+ s = (struct glyph_string *) alloca (sizeof *s); \
+ x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
+ x_fill_image_glyph_string (s); \
+ x_append_glyph_string (&HEAD, &TAIL, s); \
+ ++START; \
+ s->x = (X); \
+ } \
+ while (0)
+
+
+/* Add a glyph string for a sequence of character glyphs to the list
+ of strings between HEAD and TAIL. START is the index of the first
+ glyph in row area AREA of glyph row ROW that is part of the new
+ glyph string. END is the index of the last glyph in that glyph row
+ area. X is the current output position assigned to the new glyph
+ string constructed. HL overrides that face of the glyph; e.g. it
+ is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
+ right-most x-position of the drawing area. */
+
+#define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
+ do \
+ { \
+ int c, face_id; \
+ XChar2b *char2b; \
+ \
+ c = (ROW)->glyphs[AREA][START].u.ch; \
+ face_id = (ROW)->glyphs[AREA][START].face_id; \
+ \
+ s = (struct glyph_string *) alloca (sizeof *s); \
+ char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
+ x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
+ x_append_glyph_string (&HEAD, &TAIL, s); \
+ s->x = (X); \
+ START = x_fill_glyph_string (s, face_id, START, END, \
+ OVERLAPS_P); \
+ } \
+ while (0)
+
+
+/* Add a glyph string for a composite sequence to the list of strings
+ between HEAD and TAIL. START is the index of the first glyph in
+ row area AREA of glyph row ROW that is part of the new glyph
+ string. END is the index of the last glyph in that glyph row area.
+ X is the current output position assigned to the new glyph string
+ constructed. HL overrides that face of the glyph; e.g. it is
+ DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
+ x-position of the drawing area. */
+
+#define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
+ do { \
+ int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
+ int face_id = (ROW)->glyphs[AREA][START].face_id; \
+ struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
+ struct composition *cmp = composition_table[cmp_id]; \
+ int glyph_len = cmp->glyph_len; \
+ XChar2b *char2b; \
+ struct face **faces; \
+ struct glyph_string *first_s = NULL; \
+ int n; \
+ \
+ base_face = base_face->ascii_face; \
+ char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
+ faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
+ /* At first, fill in `char2b' and `faces'. */ \
+ for (n = 0; n < glyph_len; n++) \
+ { \
+ int c = COMPOSITION_GLYPH (cmp, n); \
+ int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
+ faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
+ x_get_char_face_and_encoding (XFRAME (w->frame), c, \
+ this_face_id, char2b + n, 1); \
+ } \
+ \
+ /* Make glyph_strings for each glyph sequence that is drawable by \
+ the same face, and append them to HEAD/TAIL. */ \
+ for (n = 0; n < cmp->glyph_len;) \
+ { \
+ s = (struct glyph_string *) alloca (sizeof *s); \
+ x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
+ x_append_glyph_string (&(HEAD), &(TAIL), s); \
+ s->cmp = cmp; \
+ s->gidx = n; \
+ s->x = (X); \
+ \
+ if (n == 0) \
+ first_s = s; \
+ \
+ n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
+ } \
+ \
+ ++START; \
+ s = first_s; \
+ } while (0)
+
+
+/* Build a list of glyph strings between HEAD and TAIL for the glyphs
+ of AREA of glyph row ROW on window W between indices START and END.
+ HL overrides the face for drawing glyph strings, e.g. it is
+ DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
+ x-positions of the drawing area.
+
+ This is an ugly monster macro construct because we must use alloca
+ to allocate glyph strings (because x_draw_glyphs can be called
+ asynchronously). */
+
+#define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
+ do \
+ { \
+ HEAD = TAIL = NULL; \
+ while (START < END) \
+ { \
+ struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
+ switch (first_glyph->type) \
+ { \
+ case CHAR_GLYPH: \
+ BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
+ TAIL, HL, X, LAST_X, \
+ OVERLAPS_P); \
+ break; \
+ \
+ case COMPOSITE_GLYPH: \
+ BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
+ HEAD, TAIL, HL, X, LAST_X,\
+ OVERLAPS_P); \
+ break; \
+ \
+ case STRETCH_GLYPH: \
+ BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
+ HEAD, TAIL, HL, X, LAST_X); \
+ break; \
+ \
+ case IMAGE_GLYPH: \
+ BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
+ TAIL, HL, X, LAST_X); \
+ break; \
+ \
+ default: \
+ abort (); \
+ } \
+ \
+ x_set_glyph_string_background_width (s, START, LAST_X); \
+ (X) += s->width; \
+ } \
+ } \
+ while (0)
+
+
+/* Draw glyphs between START and END in AREA of ROW on window W,
+ starting at x-position X. X is relative to AREA in W. HL is a
+ face-override with the following meaning:
+
+ DRAW_NORMAL_TEXT draw normally
+ DRAW_CURSOR draw in cursor face
+ DRAW_MOUSE_FACE draw in mouse face.
+ DRAW_INVERSE_VIDEO draw in mode line face
+ DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
+ DRAW_IMAGE_RAISED draw an image with a raised relief around it
+
+ If OVERLAPS_P is non-zero, draw only the foreground of characters
+ and clip to the physical height of ROW.
+
+ Value is the x-position reached, relative to AREA of W. */
+
+static int
+x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
+ struct window *w;
+ int x;
+ struct glyph_row *row;
+ enum glyph_row_area area;
+ int start, end;
+ enum draw_glyphs_face hl;
+ int overlaps_p;
+{
+ struct glyph_string *head, *tail;
+ struct glyph_string *s;
+ int last_x, area_width;
+ int x_reached;
+ int i, j;
+
+ /* Let's rather be paranoid than getting a SEGV. */
+ end = min (end, row->used[area]);
+ start = max (0, start);
+ start = min (end, start);
+
+ /* Translate X to frame coordinates. Set last_x to the right
+ end of the drawing area. */
+ if (row->full_width_p)
+ {
+ /* X is relative to the left edge of W, without scroll bars
+ or fringes. */
+ struct frame *f = XFRAME (WINDOW_FRAME (w));
+ int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
+
+ x += window_left_x;
+ area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
+ last_x = window_left_x + area_width;
+
+ if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
+ {
+ int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
+ if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
+ last_x += width;
+ else
+ x -= width;
+ }
+
+ x += FRAME_INTERNAL_BORDER_WIDTH (f);
+ last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
+ }
+ else
+ {
+ x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
+ area_width = window_box_width (w, area);
+ last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
+ }
+
+ /* Build a doubly-linked list of glyph_string structures between
+ head and tail from what we have to draw. Note that the macro
+ BUILD_GLYPH_STRINGS will modify its start parameter. That's
+ the reason we use a separate variable `i'. */
+ i = start;
+ BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
+ overlaps_p);
+ if (tail)
+ x_reached = tail->x + tail->background_width;
+ else
+ x_reached = x;
+
+ /* If there are any glyphs with lbearing < 0 or rbearing > width in
+ the row, redraw some glyphs in front or following the glyph
+ strings built above. */
+ if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
+ {
+ int dummy_x = 0;
+ struct glyph_string *h, *t;
+
+ /* Compute overhangs for all glyph strings. */
+ for (s = head; s; s = s->next)
+ x_compute_glyph_string_overhangs (s);
+
+ /* Prepend glyph strings for glyphs in front of the first glyph
+ string that are overwritten because of the first glyph
+ string's left overhang. The background of all strings
+ prepended must be drawn because the first glyph string
+ draws over it. */
+ i = x_left_overwritten (head);
+ if (i >= 0)
+ {
+ j = i;
+ BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
+ DRAW_NORMAL_TEXT, dummy_x, last_x,
+ overlaps_p);
+ start = i;
+ x_compute_overhangs_and_x (t, head->x, 1);
+ x_prepend_glyph_string_lists (&head, &tail, h, t);
+ }
+
+ /* Prepend glyph strings for glyphs in front of the first glyph
+ string that overwrite that glyph string because of their
+ right overhang. For these strings, only the foreground must
+ be drawn, because it draws over the glyph string at `head'.
+ The background must not be drawn because this would overwrite
+ right overhangs of preceding glyphs for which no glyph
+ strings exist. */
+ i = x_left_overwriting (head);
+ if (i >= 0)
+ {
+ BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
+ DRAW_NORMAL_TEXT, dummy_x, last_x,
+ overlaps_p);
+ for (s = h; s; s = s->next)
+ s->background_filled_p = 1;
+ x_compute_overhangs_and_x (t, head->x, 1);
+ x_prepend_glyph_string_lists (&head, &tail, h, t);
+ }
+
+ /* Append glyphs strings for glyphs following the last glyph
+ string tail that are overwritten by tail. The background of
+ these strings has to be drawn because tail's foreground draws
+ over it. */
+ i = x_right_overwritten (tail);
+ if (i >= 0)
+ {
+ BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
+ DRAW_NORMAL_TEXT, x, last_x,
+ overlaps_p);
+ x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
+ x_append_glyph_string_lists (&head, &tail, h, t);
+ }
+
+ /* Append glyph strings for glyphs following the last glyph
+ string tail that overwrite tail. The foreground of such
+ glyphs has to be drawn because it writes into the background
+ of tail. The background must not be drawn because it could
+ paint over the foreground of following glyphs. */
+ i = x_right_overwriting (tail);
+ if (i >= 0)
+ {
+ BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
+ DRAW_NORMAL_TEXT, x, last_x,
+ overlaps_p);
+ for (s = h; s; s = s->next)
+ s->background_filled_p = 1;
+ x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
+ x_append_glyph_string_lists (&head, &tail, h, t);
+ }
+ }
+
+ /* Draw all strings. */
+ for (s = head; s; s = s->next)
+ x_draw_glyph_string (s);
+
+ if (area == TEXT_AREA
+ && !row->full_width_p
+ /* When drawing overlapping rows, only the glyph strings'
+ foreground is drawn, which doesn't erase a cursor
+ completely. */
+ && !overlaps_p)
+ {
+ int x0 = head ? head->x : x;
+ int x1 = tail ? tail->x + tail->background_width : x;
+
+ x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
+ x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
+
+ if (!row->full_width_p && XFASTINT (w->left_margin_width) != 0)
+ {
+ int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
+ x0 -= left_area_width;
+ x1 -= left_area_width;
+ }
+
+ notice_overwritten_cursor (w, area, x0, x1,
+ row->y, MATRIX_ROW_BOTTOM_Y (row));
+ }
+
+ /* Value is the x-position up to which drawn, relative to AREA of W.
+ This doesn't include parts drawn because of overhangs. */
+ x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
+ if (!row->full_width_p)
+ {
+ if (area > LEFT_MARGIN_AREA)
+ x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
+ if (area > TEXT_AREA)
+ x_reached -= window_box_width (w, TEXT_AREA);
+ }
+
+ return x_reached;
+}
+
+
+/* Fix the display of area AREA of overlapping row ROW in window W. */
+
+static void
+x_fix_overlapping_area (w, row, area)
+ struct window *w;
+ struct glyph_row *row;
+ enum glyph_row_area area;
+{
+ int i, x;
+
+ BLOCK_INPUT;
+
+ if (area == LEFT_MARGIN_AREA)
+ x = 0;
+ else if (area == TEXT_AREA)
+ x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
+ else
+ x = (window_box_width (w, LEFT_MARGIN_AREA)
+ + window_box_width (w, TEXT_AREA));
+
+ for (i = 0; i < row->used[area];)
+ {
+ if (row->glyphs[area][i].overlaps_vertically_p)
+ {
+ int start = i, start_x = x;
+
+ do
+ {
+ x += row->glyphs[area][i].pixel_width;
+ ++i;
+ }
+ while (i < row->used[area]
+ && row->glyphs[area][i].overlaps_vertically_p);
+
+ x_draw_glyphs (w, start_x, row, area, start, i,
+ DRAW_NORMAL_TEXT, 1);
+ }
+ else
+ {
+ x += row->glyphs[area][i].pixel_width;
+ ++i;
+ }
+ }
+
+ UNBLOCK_INPUT;
+}
+
+
+/* Output LEN glyphs starting at START at the nominal cursor position.
+ Advance the nominal cursor over the text. The global variable
+ updated_window contains the window being updated, updated_row is
+ the glyph row being updated, and updated_area is the area of that
+ row being updated. */
+
+static void
+x_write_glyphs (start, len)
+ struct glyph *start;
+ int len;
+{
+ int x, hpos;
+
+ xassert (updated_window && updated_row);
+ BLOCK_INPUT;
+
+ /* Write glyphs. */
+
+ hpos = start - updated_row->glyphs[updated_area];
+ x = x_draw_glyphs (updated_window, output_cursor.x,
+ updated_row, updated_area,
+ hpos, hpos + len,
+ DRAW_NORMAL_TEXT, 0);
+
+ UNBLOCK_INPUT;
+
+ /* Advance the output cursor. */
+ output_cursor.hpos += len;
+ output_cursor.x = x;
+}
+
+
+/* Insert LEN glyphs from START at the nominal cursor position. */
+
+static void
+x_insert_glyphs (start, len)
+ struct glyph *start;
+ register int len;
+{
+ struct frame *f;
+ struct window *w;
+ int line_height, shift_by_width, shifted_region_width;
+ struct glyph_row *row;
+ struct glyph *glyph;
+ int frame_x, frame_y, hpos;
+
+ xassert (updated_window && updated_row);
+ BLOCK_INPUT;
+ w = updated_window;
+ f = XFRAME (WINDOW_FRAME (w));
+
+ /* Get the height of the line we are in. */
+ row = updated_row;
+ line_height = row->height;
+
+ /* Get the width of the glyphs to insert. */
+ shift_by_width = 0;
+ for (glyph = start; glyph < start + len; ++glyph)
+ shift_by_width += glyph->pixel_width;
+
+ /* Get the width of the region to shift right. */
+ shifted_region_width = (window_box_width (w, updated_area)
+ - output_cursor.x
+ - shift_by_width);
+
+ /* Shift right. */
+ frame_x = window_box_left (w, updated_area) + output_cursor.x;
+ frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
+
+ mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
+ f->output_data.mac->normal_gc,
+ frame_x, frame_y,
+ shifted_region_width, line_height,
+ frame_x + shift_by_width, frame_y);
+
+ /* Write the glyphs. */
+ hpos = start - row->glyphs[updated_area];
+ x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
+ DRAW_NORMAL_TEXT, 0);
+
+ /* Advance the output cursor. */
+ output_cursor.hpos += len;
+ output_cursor.x += shift_by_width;
+ UNBLOCK_INPUT;
+}
+
+
+/* Delete N glyphs at the nominal cursor position. Not implemented
+ for X frames. */
+
+static void
+x_delete_glyphs (n)
+ register int n;
+{
+ abort ();
+}
+
+
+/* Erase the current text line from the nominal cursor position
+ (inclusive) to pixel column TO_X (exclusive). The idea is that
+ everything from TO_X onward is already erased.
+
+ TO_X is a pixel position relative to updated_area of
+ updated_window. TO_X == -1 means clear to the end of this area. */
+
+static void
+x_clear_end_of_line (to_x)
+ int to_x;
+{
+ struct frame *f;
+ struct window *w = updated_window;
+ int max_x, min_y, max_y;
+ int from_x, from_y, to_y;
+
+ xassert (updated_window && updated_row);
+ f = XFRAME (w->frame);
+
+ if (updated_row->full_width_p)
+ {
+ max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
+ if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
+ && !w->pseudo_window_p)
+ max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
+ }
+ else
+ max_x = window_box_width (w, updated_area);
+ max_y = window_text_bottom_y (w);
+
+ /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
+ of window. For TO_X > 0, truncate to end of drawing area. */
+ if (to_x == 0)
+ return;
+ else if (to_x < 0)
+ to_x = max_x;
+ else
+ to_x = min (to_x, max_x);
+
+ to_y = min (max_y, output_cursor.y + updated_row->height);
+
+ /* Notice if the cursor will be cleared by this operation. */
+ if (!updated_row->full_width_p)
+ notice_overwritten_cursor (w, updated_area,
+ output_cursor.x, -1,
+ updated_row->y,
+ MATRIX_ROW_BOTTOM_Y (updated_row));
+
+ from_x = output_cursor.x;
+
+ /* Translate to frame coordinates. */
+ if (updated_row->full_width_p)
+ {
+ from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
+ to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
+ }
+ else
+ {
+ from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
+ to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
+ }
+
+ min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
+ from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
+ to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
+
+ /* Prevent inadvertently clearing to end of the X window. */
+ if (to_x > from_x && to_y > from_y)
+ {
+ BLOCK_INPUT;
+ XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
+ from_x, from_y, to_x - from_x, to_y - from_y,
+ 0);
+ UNBLOCK_INPUT;
+ }
+}
+
+
+/* Clear entire frame. If updating_frame is non-null, clear that
+ frame. Otherwise clear the selected frame. */
+
+static void
+x_clear_frame ()
+{
+ struct frame *f;
+
+ if (updating_frame)
+ f = updating_frame;
+ else
+ f = SELECTED_FRAME ();
+
+ /* Clearing the frame will erase any cursor, so mark them all as no
+ longer visible. */
+ mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
+ output_cursor.hpos = output_cursor.vpos = 0;
+ output_cursor.x = -1;
+
+ /* We don't set the output cursor here because there will always
+ follow an explicit cursor_to. */
+ BLOCK_INPUT;
+ XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
+
+#if 0 /* Clearing frame on Mac OS clears scroll bars. */
+ /* We have to clear the scroll bars, too. If we have changed
+ colors or something like that, then they should be notified. */
+ x_scroll_bar_clear (f);
+#endif
+
+ XFlush (FRAME_MAC_DISPLAY (f));
+ UNBLOCK_INPUT;
+}
+
+
+\f
+/* Invert the middle quarter of the frame for .15 sec. */
+
+/* We use the select system call to do the waiting, so we have to make
+ sure it's available. If it isn't, we just won't do visual bells. */
+
+#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
+
+/* Subtract the `struct timeval' values X and Y, storing the result in
+ *RESULT. Return 1 if the difference is negative, otherwise 0. */
+
+static int
+timeval_subtract (result, x, y)
+ struct timeval *result, x, y;
+{
+ /* Perform the carry for the later subtraction by updating y. This
+ is safer because on some systems the tv_sec member is unsigned. */
+ if (x.tv_usec < y.tv_usec)
+ {
+ int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
+ y.tv_usec -= 1000000 * nsec;
+ y.tv_sec += nsec;
+ }
+
+ if (x.tv_usec - y.tv_usec > 1000000)
+ {
+ int nsec = (y.tv_usec - x.tv_usec) / 1000000;
+ y.tv_usec += 1000000 * nsec;
+ y.tv_sec -= nsec;
+ }
+
+ /* Compute the time remaining to wait. tv_usec is certainly
+ positive. */
+ result->tv_sec = x.tv_sec - y.tv_sec;
+ result->tv_usec = x.tv_usec - y.tv_usec;
+
+ /* Return indication of whether the result should be considered
+ negative. */
+ return x.tv_sec < y.tv_sec;
+}
+
+void
+XTflash (f)
+ struct frame *f;
+{
+ BLOCK_INPUT;
+
+ FlashMenuBar (0);
+
+ {
+ struct timeval wakeup;
+
+ EMACS_GET_TIME (wakeup);
+
+ /* Compute time to wait until, propagating carry from usecs. */
+ wakeup.tv_usec += 150000;
+ wakeup.tv_sec += (wakeup.tv_usec / 1000000);
+ wakeup.tv_usec %= 1000000;
+
+ /* Keep waiting until past the time wakeup. */
+ while (1)
+ {
+ struct timeval timeout;
+
+ EMACS_GET_TIME (timeout);
+
+ /* In effect, timeout = wakeup - timeout.
+ Break if result would be negative. */
+ if (timeval_subtract (&timeout, wakeup, timeout))
+ break;
+
+ /* Try to wait that long--but we might wake up sooner. */
+ select (0, NULL, NULL, NULL, &timeout);
+ }
+ }
+
+ FlashMenuBar (0);
+
+ UNBLOCK_INPUT;
+}
+
+#endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
+
+
+/* Make audible bell. */
+
+void
+XTring_bell ()
+{
+ struct frame *f = SELECTED_FRAME ();
+
+#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
+ if (visible_bell)
+ XTflash (f);
+ else
+#endif
+ {
+ BLOCK_INPUT;
+ SysBeep (1);
+ XFlush (FRAME_MAC_DISPLAY (f));
+ UNBLOCK_INPUT;
+ }
+}
+
+
+\f
+/* Specify how many text lines, from the top of the window,
+ should be affected by insert-lines and delete-lines operations.
+ This, and those operations, are used only within an update
+ that is bounded by calls to x_update_begin and x_update_end. */
+
+void
+XTset_terminal_window (n)
+ register int n;
+{
+ /* This function intentionally left blank. */
+}
+
+
+\f
+/***********************************************************************
+ Line Dance
+ ***********************************************************************/
+
+/* Perform an insert-lines or delete-lines operation, inserting N
+ lines or deleting -N lines at vertical position VPOS. */
+
+static void
+x_ins_del_lines (vpos, n)
+ int vpos, n;
+{
+ abort ();
+}
+
+
+/* Scroll part of the display as described by RUN. */
+
+static void
+x_scroll_run (w, run)
+ struct window *w;
+ struct run *run;
+{
+ struct frame *f = XFRAME (w->frame);
+ int x, y, width, height, from_y, to_y, bottom_y;
+
+ /* Get frame-relative bounding box of the text display area of W,
+ without mode lines. Include in this box the left and right
+ fringes of W. */
+ window_box (w, -1, &x, &y, &width, &height);
+ width += FRAME_X_FRINGE_WIDTH (f);
+ x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
+
+ from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
+ to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
+ bottom_y = y + height;
+
+ if (to_y < from_y)
+ {
+ /* Scrolling up. Make sure we don't copy part of the mode
+ line at the bottom. */
+ if (from_y + run->height > bottom_y)
+ height = bottom_y - from_y;
+ else
+ height = run->height;
+ }
+ else
+ {
+ /* Scolling down. Make sure we don't copy over the mode line.
+ at the bottom. */
+ if (to_y + run->height > bottom_y)
+ height = bottom_y - to_y;
+ else
+ height = run->height;
+ }
+
+ BLOCK_INPUT;
+
+ /* Cursor off. Will be switched on again in x_update_window_end. */
+ updated_window = w;
+ x_clear_cursor (w);
+
+ mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
+ f->output_data.mac->normal_gc,
+ x, from_y,
+ width, height,
+ x, to_y);
+
+ UNBLOCK_INPUT;
+}
+
+
+\f
+/***********************************************************************
+ Exposure Events
+ ***********************************************************************/
+
+/* Redisplay an exposed area of frame F. X and Y are the upper-left
+ corner of the exposed rectangle. W and H are width and height of
+ the exposed area. All are pixel values. W or H zero means redraw
+ the entire frame. */
+
+static void
+expose_frame (f, x, y, w, h)
+ struct frame *f;
+ int x, y, w, h;
+{
+ Rect r;
+ int mouse_face_overwritten_p = 0;
+
+ TRACE ((stderr, "expose_frame "));
+
+ /* No need to redraw if frame will be redrawn soon. */
+ if (FRAME_GARBAGED_P (f))
+ {
+ TRACE ((stderr, " garbaged\n"));
+ return;
+ }
+
+ /* MAC_TODO: this is a kludge, but if scroll bars are not activated
+ or deactivated here, for unknown reasons, activated scroll bars
+ are shown in deactivated frames in some instances. */
+ if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
+ activate_scroll_bars (f);
+ else
+ deactivate_scroll_bars (f);
+
+ /* If basic faces haven't been realized yet, there is no point in
+ trying to redraw anything. This can happen when we get an expose
+ event while Emacs is starting, e.g. by moving another window. */
+ if (FRAME_FACE_CACHE (f) == NULL
+ || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
+ {
+ TRACE ((stderr, " no faces\n"));
+ return;
+ }
+
+ if (w == 0 || h == 0)
+ {
+ r.left = r.top = 0;
+ r.right = CANON_X_UNIT (f) * f->width;
+ r.bottom = CANON_Y_UNIT (f) * f->height;
+ }
+ else
+ {
+ r.left = x;
+ r.top = y;
+ r.right = x + w;
+ r.bottom = y + h;
+ }
+
+ TRACE ((stderr, "(%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom));
+ mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
+
+ if (WINDOWP (f->tool_bar_window))
+ mouse_face_overwritten_p
+ |= expose_window (XWINDOW (f->tool_bar_window), &r);
+
+ /* Some window managers support a focus-follows-mouse style with
+ delayed raising of frames. Imagine a partially obscured frame,
+ and moving the mouse into partially obscured mouse-face on that
+ frame. The visible part of the mouse-face will be highlighted,
+ then the WM raises the obscured frame. With at least one WM, KDE
+ 2.1, Emacs is not getting any event for the raising of the frame
+ (even tried with SubstructureRedirectMask), only Expose events.
+ These expose events will draw text normally, i.e. not
+ highlighted. Which means we must redo the highlight here.
+ Subsume it under ``we love X''. --gerd 2001-08-15 */
+ /* Included in Windows version because Windows most likely does not
+ do the right thing if any third party tool offers
+ focus-follows-mouse with delayed raise. --jason 2001-10-12 */
+ if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
+ {
+ struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+ if (f == dpyinfo->mouse_face_mouse_frame)
+ {
+ int x = dpyinfo->mouse_face_mouse_x;
+ int y = dpyinfo->mouse_face_mouse_y;
+ clear_mouse_face (dpyinfo);
+ note_mouse_highlight (f, x, y);
+ }
+ }
+}
+
+
+/* Redraw (parts) of all windows in the window tree rooted at W that
+ intersect R. R contains frame pixel coordinates. */
+
+static int
+expose_window_tree (w, r)
+ struct window *w;
+ Rect *r;
+{
+ struct frame *f = XFRAME (w->frame);
+ int mouse_face_overwritten_p = 0;
+
+ while (w && !FRAME_GARBAGED_P (f))
+ {
+ if (!NILP (w->hchild))
+ mouse_face_overwritten_p
+ |= expose_window_tree (XWINDOW (w->hchild), r);
+ else if (!NILP (w->vchild))
+ mouse_face_overwritten_p
+ |= expose_window_tree (XWINDOW (w->vchild), r);
+ else
+ mouse_face_overwritten_p |= expose_window (w, r);
+
+ w = NILP (w->next) ? NULL : XWINDOW (w->next);
+ }
+
+ return mouse_face_overwritten_p;
+}
+
+
+/* Redraw the part of glyph row area AREA of glyph row ROW on window W
+ which intersects rectangle R. R is in window-relative coordinates. */
+
+static void
+expose_area (w, row, r, area)
+ struct window *w;
+ struct glyph_row *row;
+ Rect *r;
+ enum glyph_row_area area;
+{
+ struct glyph *first = row->glyphs[area];
+ struct glyph *end = row->glyphs[area] + row->used[area];
+ struct glyph *last;
+ int first_x, start_x, x;
+
+ if (area == TEXT_AREA && row->fill_line_p)
+ /* If row extends face to end of line write the whole line. */
+ x_draw_glyphs (w, 0, row, area,
+ 0, row->used[area],
+ DRAW_NORMAL_TEXT, 0);
+ else
+ {
+ /* Set START_X to the window-relative start position for drawing glyphs of
+ AREA. The first glyph of the text area can be partially visible.
+ The first glyphs of other areas cannot. */
+ if (area == LEFT_MARGIN_AREA)
+ start_x = 0;
+ else if (area == TEXT_AREA)
+ start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
+ else
+ start_x = (window_box_width (w, LEFT_MARGIN_AREA)
+ + window_box_width (w, TEXT_AREA));
+ x = start_x;
+
+ /* Find the first glyph that must be redrawn. */
+ while (first < end
+ && x + first->pixel_width < r->left)
+ {
+ x += first->pixel_width;
+ ++first;
+ }
+
+ /* Find the last one. */
+ last = first;
+ first_x = x;
+ while (last < end
+ && x < r->right)
+ {
+ x += last->pixel_width;
+ ++last;
+ }
+
+ /* Repaint. */
+ if (last > first)
+ x_draw_glyphs (w, first_x - start_x, row, area,
+ first - row->glyphs[area],
+ last - row->glyphs[area],
+ DRAW_NORMAL_TEXT, 0);
+ }
+}
+
+
+/* Redraw the parts of the glyph row ROW on window W intersecting
+ rectangle R. R is in window-relative coordinates. Value is
+ non-zero if mouse face was overwritten. */
+
+static int
+expose_line (w, row, r)
+ struct window *w;
+ struct glyph_row *row;
+ Rect *r;
+{
+ xassert (row->enabled_p);
+
+ if (row->mode_line_p || w->pseudo_window_p)
+ x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
+ DRAW_NORMAL_TEXT, 0);
+ else
+ {
+ if (row->used[LEFT_MARGIN_AREA])
+ expose_area (w, row, r, LEFT_MARGIN_AREA);
+ if (row->used[TEXT_AREA])
+ expose_area (w, row, r, TEXT_AREA);
+ if (row->used[RIGHT_MARGIN_AREA])
+ expose_area (w, row, r, RIGHT_MARGIN_AREA);
+ x_draw_row_fringe_bitmaps (w, row);
+ }
+
+ return row->mouse_face_p;
+}
+
+
+/* Return non-zero if W's cursor intersects rectangle R. */
+
+static int
+x_phys_cursor_in_rect_p (w, r)
+ struct window *w;
+ Rect *r;
+{
+ Rect cr, result;
+ struct glyph *cursor_glyph;
+
+ cursor_glyph = get_phys_cursor_glyph (w);
+ if (cursor_glyph)
+ {
+ cr.left = w->phys_cursor.x;
+ cr.top = w->phys_cursor.y;
+ cr.right = cr.left + cursor_glyph->pixel_width;
+ cr.bottom = cr.top + w->phys_cursor_height;
+ return x_intersect_rectangles (&cr, r, &result);
+ }
+ else
+ return 0;
+}
+
+
+/* Redraw the part of window W intersection rectagle FR. Pixel
+ coordinates in FR are frame relative. Call this function with
+ input blocked. Value is non-zero if the exposure overwrites
+ mouse-face. */
+
+static int
+expose_window (w, fr)
+ struct window *w;
+ Rect *fr;
+{
+ struct frame *f = XFRAME (w->frame);
+ Rect wr, r;
+ int mouse_face_overwritten_p = 0;
+
+ /* If window is not yet fully initialized, do nothing. This can
+ happen when toolkit scroll bars are used and a window is split.
+ Reconfiguring the scroll bar will generate an expose for a newly
+ created window. */
+ if (w->current_matrix == NULL)
+ return 0;
+
+ /* When we're currently updating the window, display and current
+ matrix usually don't agree. Arrange for a thorough display
+ later. */
+ if (w == updated_window)
+ {
+ SET_FRAME_GARBAGED (f);
+ return 0;
+ }
+
+ /* Frame-relative pixel rectangle of W. */
+ wr.left = XFASTINT (w->left) * CANON_X_UNIT (f);
+ wr.top = XFASTINT (w->top) * CANON_Y_UNIT (f);
+ wr.right = wr.left + XFASTINT (w->width) * CANON_X_UNIT (f);
+ wr.bottom = wr.top + XFASTINT (w->height) * CANON_Y_UNIT (f);
+
+ if (x_intersect_rectangles (fr, &wr, &r))
+ {
+ int yb = window_text_bottom_y (w);
+ struct glyph_row *row;
+ int cursor_cleared_p;
+
+ TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
+ r.left, r.top, r.right, r.bottom));
+
+ /* Convert to window coordinates. */
+ r.left = FRAME_TO_WINDOW_PIXEL_X (w, r.left);
+ r.right = FRAME_TO_WINDOW_PIXEL_X (w, r.right);
+ r.top = FRAME_TO_WINDOW_PIXEL_Y (w, r.top);
+ r.bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r.bottom);
+
+ /* Turn off the cursor. */
+ if (!w->pseudo_window_p
+ && x_phys_cursor_in_rect_p (w, &r))
+ {
+ x_clear_cursor (w);
+ cursor_cleared_p = 1;
+ }
+ else
+ cursor_cleared_p = 0;
+
+ /* Find the first row intersecting the rectangle R. */
+ for (row = w->current_matrix->rows;
+ row->enabled_p;
+ ++row)
+ {
+ int y0 = row->y;
+ int y1 = MATRIX_ROW_BOTTOM_Y (row);
+
+ if ((y0 >= r.top && y0 < r.bottom)
+ || (y1 > r.top && y1 < r.bottom)
+ || (r.top >= y0 && r.top < y1)
+ || (r.bottom > y0 && r.bottom < y1))
+ {
+ if (expose_line (w, row, &r))
+ mouse_face_overwritten_p = 1;
+ }
+
+ if (y1 >= yb)
+ break;
+ }
+
+ /* Display the mode line if there is one. */
+ if (WINDOW_WANTS_MODELINE_P (w)
+ && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
+ row->enabled_p)
+ && row->y < r.bottom)
+ {
+ if (expose_line (w, row, &r))
+ mouse_face_overwritten_p = 1;
+ }
+
+ if (!w->pseudo_window_p)
+ {
+ /* Draw border between windows. */
+ x_draw_vertical_border (w);
+
+ /* Turn the cursor on again. */
+ if (cursor_cleared_p)
+ x_update_window_cursor (w, 1);
+ }
+ }
+
+ /* Display scroll bar for this window. */
+ if (!NILP (w->vertical_scroll_bar))
+ {
+ ControlHandle ch
+ = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w->vertical_scroll_bar));
+
+ Draw1Control (ch);
+ }
+
+ return mouse_face_overwritten_p;
+}
+
+static int
+x_intersect_rectangles (r1, r2, result)
+ Rect *r1, *r2, *result;
+{
+ Rect *left, *right;
+ Rect *upper, *lower;
+ int intersection_p = 0;
+
+ /* Rerrange so that R1 is the left-most rectangle. */
+ if (r1->left < r2->left)
+ left = r1, right = r2;
+ else
+ left = r2, right = r1;
+
+ /* X0 of the intersection is right.x0, if this is inside R1,
+ otherwise there is no intersection. */
+ if (right->left <= left->right)
+ {
+ result->left = right->left;
+
+ /* The right end of the intersection is the minimum of the
+ the right ends of left and right. */
+ result->right = min (left->right, right->right);
+
+ /* Same game for Y. */
+ if (r1->top < r2->top)
+ upper = r1, lower = r2;
+ else
+ upper = r2, lower = r1;
+
+ /* The upper end of the intersection is lower.y0, if this is inside
+ of upper. Otherwise, there is no intersection. */
+ if (lower->top <= upper->bottom)
+ {
+ result->top = lower->top;
+
+ /* The lower end of the intersection is the minimum of the lower
+ ends of upper and lower. */
+ result->bottom = min (lower->bottom, upper->bottom);
+ intersection_p = 1;
+ }
+ }
+
+ return intersection_p;
+}
+
+
+
+
+\f
+static void
+frame_highlight (f)
+ struct frame *f;
+{
+ x_update_cursor (f, 1);
+}
+
+static void
+frame_unhighlight (f)
+ struct frame *f;
+{
+ x_update_cursor (f, 1);
+}
+
+/* The focus has changed. Update the frames as necessary to reflect
+ the new situation. Note that we can't change the selected frame
+ here, because the Lisp code we are interrupting might become confused.
+ Each event gets marked with the frame in which it occurred, so the
+ Lisp code can tell when the switch took place by examining the events. */
+
+static void
+x_new_focus_frame (dpyinfo, frame)
+ struct x_display_info *dpyinfo;
+ struct frame *frame;
+{
+ struct frame *old_focus = dpyinfo->x_focus_frame;
+
+ if (frame != dpyinfo->x_focus_frame)
+ {
+ /* Set this before calling other routines, so that they see
+ the correct value of x_focus_frame. */
+ dpyinfo->x_focus_frame = frame;
+
+ if (old_focus && old_focus->auto_lower)
+ x_lower_frame (old_focus);
+
+#if 0
+ selected_frame = frame;
+ XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
+ selected_frame);
+ Fselect_window (selected_frame->selected_window);
+ choose_minibuf_frame ();
+#endif /* ! 0 */
+
+ if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
+ pending_autoraise_frame = dpyinfo->x_focus_frame;
+ else
+ pending_autoraise_frame = 0;
+ }
+
+ x_frame_rehighlight (dpyinfo);
+}
+
+/* Handle an event saying the mouse has moved out of an Emacs frame. */
+
+void
+x_mouse_leave (dpyinfo)
+ struct x_display_info *dpyinfo;
+{
+ x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
+}
+
+/* The focus has changed, or we have redirected a frame's focus to
+ another frame (this happens when a frame uses a surrogate
+ mini-buffer frame). Shift the highlight as appropriate.
+
+ The FRAME argument doesn't necessarily have anything to do with which
+ frame is being highlighted or un-highlighted; we only use it to find
+ the appropriate X display info. */
+
+static void
+XTframe_rehighlight (frame)
+ struct frame *frame;
+{
+ x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
+}
+
+static void
+x_frame_rehighlight (dpyinfo)
+ struct x_display_info *dpyinfo;
+{
+ struct frame *old_highlight = dpyinfo->x_highlight_frame;
+
+ if (dpyinfo->x_focus_frame)
+ {
+ dpyinfo->x_highlight_frame
+ = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
+ ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
+ : dpyinfo->x_focus_frame);
+ if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
+ {
+ FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
+ dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
+ }
+ }
+ else
+ dpyinfo->x_highlight_frame = 0;
+
+ if (dpyinfo->x_highlight_frame != old_highlight)
+ {
+ if (old_highlight)
+ frame_unhighlight (old_highlight);
+ if (dpyinfo->x_highlight_frame)
+ frame_highlight (dpyinfo->x_highlight_frame);
+ }
+}
+
+
+\f
+/* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
+
+#if 0 /* MAC_TODO */
+/* Initialize mode_switch_bit and modifier_meaning. */
+static void
+x_find_modifier_meanings (dpyinfo)
+ struct x_display_info *dpyinfo;
+{
+ int min_code, max_code;
+ KeySym *syms;
+ int syms_per_code;
+ XModifierKeymap *mods;
+
+ dpyinfo->meta_mod_mask = 0;
+ dpyinfo->shift_lock_mask = 0;
+ dpyinfo->alt_mod_mask = 0;
+ dpyinfo->super_mod_mask = 0;
+ dpyinfo->hyper_mod_mask = 0;
+
+#ifdef HAVE_X11R4
+ XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
+#else
+ min_code = dpyinfo->display->min_keycode;
+ max_code = dpyinfo->display->max_keycode;
+#endif
+
+ syms = XGetKeyboardMapping (dpyinfo->display,
+ min_code, max_code - min_code + 1,
+ &syms_per_code);
+ mods = XGetModifierMapping (dpyinfo->display);
+
+ /* Scan the modifier table to see which modifier bits the Meta and
+ Alt keysyms are on. */
+ {
+ int row, col; /* The row and column in the modifier table. */
+
+ for (row = 3; row < 8; row++)
+ for (col = 0; col < mods->max_keypermod; col++)
+ {
+ KeyCode code
+ = mods->modifiermap[(row * mods->max_keypermod) + col];
+
+ /* Zeroes are used for filler. Skip them. */
+ if (code == 0)
+ continue;
+
+ /* Are any of this keycode's keysyms a meta key? */
+ {
+ int code_col;
+
+ for (code_col = 0; code_col < syms_per_code; code_col++)
+ {
+ int sym = syms[((code - min_code) * syms_per_code) + code_col];
+
+ switch (sym)
+ {
+ case XK_Meta_L:
+ case XK_Meta_R:
+ dpyinfo->meta_mod_mask |= (1 << row);
+ break;
+
+ case XK_Alt_L:
+ case XK_Alt_R:
+ dpyinfo->alt_mod_mask |= (1 << row);
+ break;
+
+ case XK_Hyper_L:
+ case XK_Hyper_R:
+ dpyinfo->hyper_mod_mask |= (1 << row);
+ break;
+
+ case XK_Super_L:
+ case XK_Super_R:
+ dpyinfo->super_mod_mask |= (1 << row);
+ break;
+
+ case XK_Shift_Lock:
+ /* Ignore this if it's not on the lock modifier. */
+ if ((1 << row) == LockMask)
+ dpyinfo->shift_lock_mask = LockMask;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
+ if (! dpyinfo->meta_mod_mask)
+ {
+ dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
+ dpyinfo->alt_mod_mask = 0;
+ }
+
+ /* If some keys are both alt and meta,
+ make them just meta, not alt. */
+ if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
+ {
+ dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
+ }
+
+ XFree ((char *) syms);
+ XFreeModifiermap (mods);
+}
+
+#endif /* MAC_TODO */
+
+/* Convert between the modifier bits X uses and the modifier bits
+ Emacs uses. */
+
+static unsigned int
+x_mac_to_emacs_modifiers (dpyinfo, state)
+ struct x_display_info *dpyinfo;
+ unsigned short state;
+{
+ return (((state & shiftKey) ? shift_modifier : 0)
+ | ((state & controlKey) ? ctrl_modifier : 0)
+ | ((state & cmdKey) ? meta_modifier : 0)
+ | ((state & optionKey) ? alt_modifier : 0));
+}
+
+#if 0 /* MAC_TODO */
+static unsigned short
+x_emacs_to_x_modifiers (dpyinfo, state)
+ struct x_display_info *dpyinfo;
+ unsigned int state;
+{
+ return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
+ | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
+ | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
+ | ((state & shift_modifier) ? ShiftMask : 0)
+ | ((state & ctrl_modifier) ? ControlMask : 0)
+ | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
+}
+#endif /* MAC_TODO */
+
+/* Convert a keysym to its name. */
+
+char *
+x_get_keysym_name (keysym)
+ int keysym;
+{
+ char *value;
+
+ BLOCK_INPUT;
+#if 0
+ value = XKeysymToString (keysym);
+#else
+ value = 0;
+#endif
+ UNBLOCK_INPUT;
+
+ return value;
+}
+
+
+\f
+/* Mouse clicks and mouse movement. Rah. */
+
+/* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
+ co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
+ glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
+ not force the value into range. */
+
+void
+pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
+ FRAME_PTR f;
+ register int pix_x, pix_y;
+ register int *x, *y;
+ Rect *bounds;
+ int noclip;
+{
+ /* Support tty mode: if Vwindow_system is nil, behave correctly. */
+ if (NILP (Vwindow_system))
+ {
+ *x = pix_x;
+ *y = pix_y;
+ return;
+ }
+
+ /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
+ even for negative values. */
+ if (pix_x < 0)
+ pix_x -= FONT_WIDTH (FRAME_FONT (f)) - 1;
+ if (pix_y < 0)
+ pix_y -= (f)->output_data.mac->line_height - 1;
+
+ pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
+ pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
+
+ if (bounds)
+ {
+ bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
+ bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
+ bounds->right = bounds->left + FONT_WIDTH (FRAME_FONT (f)) - 1;
+ bounds->bottom = bounds->top + f->output_data.mac->line_height - 1;
+ }
+
+ if (!noclip)
+ {
+ if (pix_x < 0)
+ pix_x = 0;
+ else if (pix_x > FRAME_WINDOW_WIDTH (f))
+ pix_x = FRAME_WINDOW_WIDTH (f);
+
+ if (pix_y < 0)
+ pix_y = 0;
+ else if (pix_y > f->height)
+ pix_y = f->height;
+ }
+
+ *x = pix_x;
+ *y = pix_y;
+}
+
+
+/* Given HPOS/VPOS in the current matrix of W, return corresponding
+ frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
+ can't tell the positions because W's display is not up to date,
+ return 0. */
+
+int
+glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
+ struct window *w;
+ int hpos, vpos;
+ int *frame_x, *frame_y;
+{
+ int success_p;
+
+ xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
+ xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
+
+ if (display_completed)
+ {
+ struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
+ struct glyph *glyph = row->glyphs[TEXT_AREA];
+ struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
+
+ *frame_y = row->y;
+ *frame_x = row->x;
+ while (glyph < end)
+ {
+ *frame_x += glyph->pixel_width;
+ ++glyph;
+ }
+
+ success_p = 1;
+ }
+ else
+ {
+ *frame_y = *frame_x = 0;
+ success_p = 0;
+ }
+
+ *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
+ *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
+ return success_p;
+}
+
+
+/* Prepare a mouse-event in *RESULT for placement in the input queue.
+
+ If the event is a button press, then note that we have grabbed
+ the mouse. */
+
+static Lisp_Object
+construct_mouse_click (result, event, f)
+ struct input_event *result;
+ EventRecord *event;
+ struct frame *f;
+{
+ Point mouseLoc;
+
+ result->kind = mouse_click;
+ result->code = 0; /* only one mouse button */
+ result->timestamp = event->when;
+ result->modifiers = event->what == mouseDown ? down_modifier : up_modifier;
+
+ mouseLoc = event->where;
+
+#if TARGET_API_MAC_CARBON
+ SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
+#else
+ SetPort (FRAME_MAC_WINDOW (f));
+#endif
+
+ GlobalToLocal (&mouseLoc);
+ XSETINT (result->x, mouseLoc.h);
+ XSETINT (result->y, mouseLoc.v);
+
+ XSETFRAME (result->frame_or_window, f);
+
+ result->arg = Qnil;
+ return Qnil;
+}
+
+\f
+/* Function to report a mouse movement to the mainstream Emacs code.
+ The input handler calls this.
+
+ We have received a mouse movement event, which is given in *event.
+ If the mouse is over a different glyph than it was last time, tell
+ the mainstream emacs code by setting mouse_moved. If not, ask for
+ another motion event, so we can check again the next time it moves. */
+
+static Point last_mouse_motion_position;
+static Lisp_Object last_mouse_motion_frame;
+
+static void
+note_mouse_movement (frame, pos)
+ FRAME_PTR frame;
+ Point *pos;
+{
+#if TARGET_API_MAC_CARBON
+ Rect r;
+#endif
+
+ last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
+ last_mouse_motion_position = *pos;
+ XSETFRAME (last_mouse_motion_frame, frame);
+
+#if TARGET_API_MAC_CARBON
+ if (!PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)))
+#else
+ if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
+#endif
+ {
+ frame->mouse_moved = 1;
+ last_mouse_scroll_bar = Qnil;
+ note_mouse_highlight (frame, -1, -1);
+ }
+ /* Has the mouse moved off the glyph it was on at the last sighting? */
+ else if (pos->h < last_mouse_glyph.left
+ || pos->h >= last_mouse_glyph.right
+ || pos->v < last_mouse_glyph.top
+ || pos->v >= last_mouse_glyph.bottom)
+ {
+ frame->mouse_moved = 1;
+ last_mouse_scroll_bar = Qnil;
+ note_mouse_highlight (frame, pos->h, pos->v);
+ }
+}
+
+/* This is used for debugging, to turn off note_mouse_highlight. */
+
+int disable_mouse_highlight;
+
+
+\f
+/************************************************************************
+ Mouse Face
+ ************************************************************************/
+
+/* Find the glyph under window-relative coordinates X/Y in window W.
+ Consider only glyphs from buffer text, i.e. no glyphs from overlay
+ strings. Return in *HPOS and *VPOS the row and column number of
+ the glyph found. Return in *AREA the glyph area containing X.
+ Value is a pointer to the glyph found or null if X/Y is not on
+ text, or we can't tell because W's current matrix is not up to
+ date. */
+
+static struct glyph *
+x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
+ struct window *w;
+ int x, y;
+ int *hpos, *vpos, *area;
+ int buffer_only_p;
+{
+ struct glyph *glyph, *end;
+ struct glyph_row *row = NULL;
+ int x0, i, left_area_width;
+
+ /* Find row containing Y. Give up if some row is not enabled. */
+ for (i = 0; i < w->current_matrix->nrows; ++i)
+ {
+ row = MATRIX_ROW (w->current_matrix, i);
+ if (!row->enabled_p)
+ return NULL;
+ if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
+ break;
+ }
+
+ *vpos = i;
+ *hpos = 0;
+
+ /* Give up if Y is not in the window. */
+ if (i == w->current_matrix->nrows)
+ return NULL;
+
+ /* Get the glyph area containing X. */
+ if (w->pseudo_window_p)
+ {
+ *area = TEXT_AREA;
+ x0 = 0;
+ }
+ else
+ {
+ left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
+ if (x < left_area_width)
+ {
+ *area = LEFT_MARGIN_AREA;
+ x0 = 0;
+ }
+ else if (x < left_area_width + window_box_width (w, TEXT_AREA))
+ {
+ *area = TEXT_AREA;
+ x0 = row->x + left_area_width;
+ }
+ else
+ {
+ *area = RIGHT_MARGIN_AREA;
+ x0 = left_area_width + window_box_width (w, TEXT_AREA);
+ }
+ }
+
+ /* Find glyph containing X. */
+ glyph = row->glyphs[*area];
+ end = glyph + row->used[*area];
+ while (glyph < end)
+ {
+ if (x < x0 + glyph->pixel_width)
+ {
+ if (w->pseudo_window_p)
+ break;
+ else if (!buffer_only_p || BUFFERP (glyph->object))
+ break;
+ }
+
+ x0 += glyph->pixel_width;
+ ++glyph;
+ }
+
+ if (glyph == end)
+ return NULL;
+
+ *hpos = glyph - row->glyphs[*area];
+ return glyph;
+}
+
+
+/* Convert frame-relative x/y to coordinates relative to window W.
+ Takes pseudo-windows into account. */
+
+static void
+frame_to_window_pixel_xy (w, x, y)
+ struct window *w;
+ int *x, *y;
+{
+ if (w->pseudo_window_p)
+ {
+ /* A pseudo-window is always full-width, and starts at the
+ left edge of the frame, plus a frame border. */
+ struct frame *f = XFRAME (w->frame);
+ *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
+ *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
+ }
+ else
+ {
+ *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
+ *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
+ }
+}
+
+
+/* Take proper action when mouse has moved to the mode or header line of
+ window W, x-position X. MODE_LINE_P non-zero means mouse is on the
+ mode line. X is relative to the start of the text display area of
+ W, so the width of fringes and scroll bars must be subtracted
+ to get a position relative to the start of the mode line. */
+
+static void
+note_mode_line_highlight (w, x, mode_line_p)
+ struct window *w;
+ int x, mode_line_p;
+{
+ struct frame *f = XFRAME (w->frame);
+ struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+ struct Cursor *cursor = dpyinfo->vertical_scroll_bar_cursor;
+ struct glyph_row *row;
+
+ if (mode_line_p)
+ row = MATRIX_MODE_LINE_ROW (w->current_matrix);
+ else
+ row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
+
+ if (row->enabled_p)
+ {
+ struct glyph *glyph, *end;
+ Lisp_Object help, map;
+ int x0;
+
+ /* Find the glyph under X. */
+ glyph = row->glyphs[TEXT_AREA];
+ end = glyph + row->used[TEXT_AREA];
+ x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
+ + FRAME_X_LEFT_FRINGE_WIDTH (f));
+
+ while (glyph < end
+ && x >= x0 + glyph->pixel_width)
+ {
+ x0 += glyph->pixel_width;
+ ++glyph;
+ }
+
+ if (glyph < end
+ && STRINGP (glyph->object)
+ && XSTRING (glyph->object)->intervals
+ && glyph->charpos >= 0
+ && glyph->charpos < XSTRING (glyph->object)->size)
+ {
+ /* If we're on a string with `help-echo' text property,
+ arrange for the help to be displayed. This is done by
+ setting the global variable help_echo to the help string. */
+ help = Fget_text_property (make_number (glyph->charpos),
+ Qhelp_echo, glyph->object);
+ if (!NILP (help))
+ {
+ help_echo = help;
+ XSETWINDOW (help_echo_window, w);
+ help_echo_object = glyph->object;
+ help_echo_pos = glyph->charpos;
+ }
+
+ /* Change the mouse pointer according to what is under X/Y. */
+ map = Fget_text_property (make_number (glyph->charpos),
+ Qlocal_map, glyph->object);
+ if (KEYMAPP (map))
+ cursor = f->output_data.mac->nontext_cursor;
+ else
+ {
+ map = Fget_text_property (make_number (glyph->charpos),
+ Qkeymap, glyph->object);
+ if (KEYMAPP (map))
+ cursor = f->output_data.mac->nontext_cursor;
+ }
+ }
+ }
+
+#if 0 /* MAC_TODO: mouse cursor */
+ XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
+#endif
+}
+
+
+/* Take proper action when the mouse has moved to position X, Y on
+ frame F as regards highlighting characters that have mouse-face
+ properties. Also de-highlighting chars where the mouse was before.
+ X and Y can be negative or out of range. */
+
+static void
+note_mouse_highlight (f, x, y)
+ struct frame *f;
+ int x, y;
+{
+ struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+ int portion;
+ Lisp_Object window;
+ struct window *w;
+ struct buffer *b;
+
+#if 0
+ /* When a menu is active, don't highlight because this looks odd. */
+ if (popup_activated ())
+ return;
+#endif
+
+ if (NILP (Vmouse_highlight)
+ || !f->glyphs_initialized_p)
+ return;
+
+ dpyinfo->mouse_face_mouse_x = x;
+ dpyinfo->mouse_face_mouse_y = y;
+ dpyinfo->mouse_face_mouse_frame = f;
+
+ if (dpyinfo->mouse_face_defer)
+ return;
+
+ if (gc_in_progress)
+ {
+ dpyinfo->mouse_face_deferred_gc = 1;
+ return;
+ }
+
+ /* Which window is that in? */
+ window = window_from_coordinates (f, x, y, &portion, 1);
+
+ /* If we were displaying active text in another window, clear that. */
+ if (! EQ (window, dpyinfo->mouse_face_window))
+ clear_mouse_face (dpyinfo);
+
+ /* Not on a window -> return. */
+ if (!WINDOWP (window))
+ return;
+
+ /* Reset help_echo. It will get recomputed below. */
+ help_echo = Qnil;
+
+ /* Convert to window-relative pixel coordinates. */
+ w = XWINDOW (window);
+ frame_to_window_pixel_xy (w, &x, &y);
+
+ /* Handle tool-bar window differently since it doesn't display a
+ buffer. */
+ if (EQ (window, f->tool_bar_window))
+ {
+ note_tool_bar_highlight (f, x, y);
+ return;
+ }
+
+ /* Mouse is on the mode or header line? */
+ if (portion == 1 || portion == 3)
+ {
+ note_mode_line_highlight (w, x, portion == 1);
+ return;
+ }
+#if 0 /* TODO: mouse cursor */
+ if (portion == 2)
+ cursor = f->output_data.x->horizontal_drag_cursor;
+ else
+ cursor = f->output_data.x->text_cursor;
+#endif
+ /* Are we in a window whose display is up to date?
+ And verify the buffer's text has not changed. */
+ b = XBUFFER (w->buffer);
+ if (/* Within text portion of the window. */
+ portion == 0
+ && EQ (w->window_end_valid, w->buffer)
+ && XFASTINT (w->last_modified) == BUF_MODIFF (b)
+ && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
+ {
+ int hpos, vpos, pos, i, area;
+ struct glyph *glyph;
+ Lisp_Object object;
+ Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
+ Lisp_Object *overlay_vec = NULL;
+ int len, noverlays;
+ struct buffer *obuf;
+ int obegv, ozv, same_region;
+
+ /* Find the glyph under X/Y. */
+ glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
+
+ /* Clear mouse face if X/Y not over text. */
+ if (glyph == NULL
+ || area != TEXT_AREA
+ || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
+ {
+ clear_mouse_face (dpyinfo);
+ /* TODO: mouse cursor */
+ goto set_cursor;
+ }
+
+ pos = glyph->charpos;
+ object = glyph->object;
+ if (!STRINGP (object) && !BUFFERP (object))
+ goto set_cursor;
+
+ /* If we get an out-of-range value, return now; avoid an error. */
+ if (BUFFERP (object) && pos > BUF_Z (b))
+ goto set_cursor;
+
+ /* Make the window's buffer temporarily current for
+ overlays_at and compute_char_face. */
+ obuf = current_buffer;
+ current_buffer = b;
+ obegv = BEGV;
+ ozv = ZV;
+ BEGV = BEG;
+ ZV = Z;
+
+ /* Is this char mouse-active or does it have help-echo? */
+ position = make_number (pos);
+
+ if (BUFFERP (object))
+ {
+ /* Put all the overlays we want in a vector in overlay_vec.
+ Store the length in len. If there are more than 10, make
+ enough space for all, and try again. */
+ len = 10;
+ overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
+ noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
+ if (noverlays > len)
+ {
+ len = noverlays;
+ overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
+ noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
+ }
+
+ /* Sort overlays into increasing priority order. */
+ noverlays = sort_overlays (overlay_vec, noverlays, w);
+ }
+ else
+ noverlays = 0;
+
+ same_region = (EQ (window, dpyinfo->mouse_face_window)
+ && vpos >= dpyinfo->mouse_face_beg_row
+ && vpos <= dpyinfo->mouse_face_end_row
+ && (vpos > dpyinfo->mouse_face_beg_row
+ || hpos >= dpyinfo->mouse_face_beg_col)
+ && (vpos < dpyinfo->mouse_face_end_row
+ || hpos < dpyinfo->mouse_face_end_col
+ || dpyinfo->mouse_face_past_end));
+
+ /* TODO: if (same_region)
+ mouse cursor */
+
+ /* Check mouse-face highlighting. */
+ if (! same_region
+ /* If there exists an overlay with mouse-face overlapping
+ the one we are currently highlighting, we have to
+ check if we enter the overlapping overlay, and then
+ highlight that. */
+ || (OVERLAYP (dpyinfo->mouse_face_overlay)
+ && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
+ {
+ /* Find the highest priority overlay that has a mouse-face
+ property. */
+ overlay = Qnil;
+ for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
+ {
+ mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
+ if (!NILP (mouse_face))
+ overlay = overlay_vec[i];
+ }
+
+ /* If we're actually highlighting the same overlay as
+ before, there's no need to do that again. */
+ if (!NILP (overlay)
+ && EQ (overlay, dpyinfo->mouse_face_overlay))
+ goto check_help_echo;
+
+ dpyinfo->mouse_face_overlay = overlay;
+
+ /* Clear the display of the old active region, if any. */
+ clear_mouse_face (dpyinfo);
+ /* TODO: mouse cursor changes. */
+
+ /* If no overlay applies, get a text property. */
+ if (NILP (overlay))
+ mouse_face = Fget_text_property (position, Qmouse_face, object);
+
+ /* Handle the overlay case. */
+ if (!NILP (overlay))
+ {
+ /* Find the range of text around this char that
+ should be active. */
+ Lisp_Object before, after;
+ int ignore;
+
+ before = Foverlay_start (overlay);
+ after = Foverlay_end (overlay);
+ /* Record this as the current active region. */
+ fast_find_position (w, XFASTINT (before),
+ &dpyinfo->mouse_face_beg_col,
+ &dpyinfo->mouse_face_beg_row,
+ &dpyinfo->mouse_face_beg_x,
+ &dpyinfo->mouse_face_beg_y, Qnil);
+
+ dpyinfo->mouse_face_past_end
+ = !fast_find_position (w, XFASTINT (after),
+ &dpyinfo->mouse_face_end_col,
+ &dpyinfo->mouse_face_end_row,
+ &dpyinfo->mouse_face_end_x,
+ &dpyinfo->mouse_face_end_y, Qnil);
+ dpyinfo->mouse_face_window = window;
+
+ dpyinfo->mouse_face_face_id
+ = face_at_buffer_position (w, pos, 0, 0,
+ &ignore, pos + 1, 1);
+
+ /* Display it as active. */
+ show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
+ /* TODO: mouse cursor changes. */
+ }
+ /* Handle the text property case. */
+ else if (! NILP (mouse_face) && BUFFERP (object))
+ {
+ /* Find the range of text around this char that
+ should be active. */
+ Lisp_Object before, after, beginning, end;
+ int ignore;
+
+ beginning = Fmarker_position (w->start);
+ end = make_number (BUF_Z (XBUFFER (object))
+ - XFASTINT (w->window_end_pos));
+ before
+ = Fprevious_single_property_change (make_number (pos + 1),
+ Qmouse_face,
+ object, beginning);
+ after
+ = Fnext_single_property_change (position, Qmouse_face,
+ object, end);
+
+ /* Record this as the current active region. */
+ fast_find_position (w, XFASTINT (before),
+ &dpyinfo->mouse_face_beg_col,
+ &dpyinfo->mouse_face_beg_row,
+ &dpyinfo->mouse_face_beg_x,
+ &dpyinfo->mouse_face_beg_y, Qnil);
+ dpyinfo->mouse_face_past_end
+ = !fast_find_position (w, XFASTINT (after),
+ &dpyinfo->mouse_face_end_col,
+ &dpyinfo->mouse_face_end_row,
+ &dpyinfo->mouse_face_end_x,
+ &dpyinfo->mouse_face_end_y, Qnil);
+ dpyinfo->mouse_face_window = window;
+
+ if (BUFFERP (object))
+ dpyinfo->mouse_face_face_id
+ = face_at_buffer_position (w, pos, 0, 0,
+ &ignore, pos + 1, 1);
+
+ /* Display it as active. */
+ show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
+ /* TODO: mouse cursor changes. */
+ }
+ else if (!NILP (mouse_face) && STRINGP (object))
+ {
+ Lisp_Object b, e;
+ int ignore;
+
+ b = Fprevious_single_property_change (make_number (pos + 1),
+ Qmouse_face,
+ object, Qnil);
+ e = Fnext_single_property_change (position, Qmouse_face,
+ object, Qnil);
+ if (NILP (b))
+ b = make_number (0);
+ if (NILP (e))
+ e = make_number (XSTRING (object)->size - 1);
+ fast_find_string_pos (w, XINT (b), object,
+ &dpyinfo->mouse_face_beg_col,
+ &dpyinfo->mouse_face_beg_row,
+ &dpyinfo->mouse_face_beg_x,
+ &dpyinfo->mouse_face_beg_y, 0);
+ fast_find_string_pos (w, XINT (e), object,
+ &dpyinfo->mouse_face_end_col,
+ &dpyinfo->mouse_face_end_row,
+ &dpyinfo->mouse_face_end_x,
+ &dpyinfo->mouse_face_end_y, 1);
+ dpyinfo->mouse_face_past_end = 0;
+ dpyinfo->mouse_face_window = window;
+ dpyinfo->mouse_face_face_id
+ = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
+ glyph->face_id, 1);
+ show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
+ /* TODO: mouse cursor changes. */
+ }
+ else if (STRINGP (object) && NILP (mouse_face))
+ {
+ /* A string which doesn't have mouse-face, but
+ the text ``under'' it might have. */
+ struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
+ int start = MATRIX_ROW_START_CHARPOS (r);
+
+ pos = string_buffer_position (w, object, start);
+ if (pos > 0)
+ mouse_face = get_char_property_and_overlay (make_number (pos),
+ Qmouse_face,
+ w->buffer,
+ &overlay);
+ if (!NILP (mouse_face) && !NILP (overlay))
+ {
+ Lisp_Object before = Foverlay_start (overlay);
+ Lisp_Object after = Foverlay_end (overlay);
+ int ignore;
+
+ /* Note that we might not be able to find position
+ BEFORE in the glyph matrix if the overlay is
+ entirely covered by a `display' property. In
+ this case, we overshoot. So let's stop in
+ the glyph matrix before glyphs for OBJECT. */
+ fast_find_position (w, XFASTINT (before),
+ &dpyinfo->mouse_face_beg_col,
+ &dpyinfo->mouse_face_beg_row,
+ &dpyinfo->mouse_face_beg_x,
+ &dpyinfo->mouse_face_beg_y,
+ object);
+
+ dpyinfo->mouse_face_past_end
+ = !fast_find_position (w, XFASTINT (after),
+ &dpyinfo->mouse_face_end_col,
+ &dpyinfo->mouse_face_end_row,
+ &dpyinfo->mouse_face_end_x,
+ &dpyinfo->mouse_face_end_y,
+ Qnil);
+ dpyinfo->mouse_face_window = window;
+ dpyinfo->mouse_face_face_id
+ = face_at_buffer_position (w, pos, 0, 0,
+ &ignore, pos + 1, 1);
+
+ /* Display it as active. */
+ show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
+ /* TODO: mouse cursor changes. */
+ }
+ }
+ }
+
+ check_help_echo:
+
+ /* Look for a `help-echo' property. */
+ {
+ Lisp_Object help, overlay;
+
+ /* Check overlays first. */
+ help = overlay = Qnil;
+ for (i = noverlays - 1; i >= 0 && NILP (help); --i)
+ {
+ overlay = overlay_vec[i];
+ help = Foverlay_get (overlay, Qhelp_echo);
+ }
+
+ if (!NILP (help))
+ {
+ help_echo = help;
+ help_echo_window = window;
+ help_echo_object = overlay;
+ help_echo_pos = pos;
+ }
+ else
+ {
+ Lisp_Object object = glyph->object;
+ int charpos = glyph->charpos;
+
+ /* Try text properties. */
+ if (STRINGP (object)
+ && charpos >= 0
+ && charpos < XSTRING (object)->size)
+ {
+ help = Fget_text_property (make_number (charpos),
+ Qhelp_echo, object);
+ if (NILP (help))
+ {
+ /* If the string itself doesn't specify a help-echo,
+ see if the buffer text ``under'' it does. */
+ struct glyph_row *r
+ = MATRIX_ROW (w->current_matrix, vpos);
+ int start = MATRIX_ROW_START_CHARPOS (r);
+ int pos = string_buffer_position (w, object, start);
+ if (pos > 0)
+ {
+ help = Fget_char_property (make_number (pos),
+ Qhelp_echo, w->buffer);
+ if (!NILP (help))
+ {
+ charpos = pos;
+ object = w->buffer;
+ }
+ }
+ }
+ }
+ else if (BUFFERP (object)
+ && charpos >= BEGV
+ && charpos < ZV)
+ help = Fget_text_property (make_number (charpos), Qhelp_echo,
+ object);
+
+ if (!NILP (help))
+ {
+ help_echo = help;
+ help_echo_window = window;
+ help_echo_object = object;
+ help_echo_pos = charpos;
+ }
+ }
+ }
+
+ BEGV = obegv;
+ ZV = ozv;
+ current_buffer = obuf;
+ }
+
+ set_cursor:
+ /* TODO: mouse cursor changes. */
+ ;
+}
+
+static void
+redo_mouse_highlight ()
+{
+ if (!NILP (last_mouse_motion_frame)
+ && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
+ note_mouse_highlight (XFRAME (last_mouse_motion_frame),
+ last_mouse_motion_position.h,
+ last_mouse_motion_position.v);
+}
+
+
+\f
+/***********************************************************************
+ Tool-bars
+ ***********************************************************************/
+
+static int x_tool_bar_item P_ ((struct frame *, int, int,
+ struct glyph **, int *, int *, int *));
+
+/* Tool-bar item index of the item on which a mouse button was pressed
+ or -1. */
+
+static int last_tool_bar_item;
+
+
+/* Get information about the tool-bar item at position X/Y on frame F.
+ Return in *GLYPH a pointer to the glyph of the tool-bar item in
+ the current matrix of the tool-bar window of F, or NULL if not
+ on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
+ item in F->current_tool_bar_items. Value is
+
+ -1 if X/Y is not on a tool-bar item
+ 0 if X/Y is on the same item that was highlighted before.
+ 1 otherwise. */
+
+static int
+x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
+ struct frame *f;
+ int x, y;
+ struct glyph **glyph;
+ int *hpos, *vpos, *prop_idx;
+{
+ struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+ struct window *w = XWINDOW (f->tool_bar_window);
+ int area;
+
+ /* Find the glyph under X/Y. */
+ *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
+ if (*glyph == NULL)
+ return -1;
+
+ /* Get the start of this tool-bar item's properties in
+ f->current_tool_bar_items. */
+ if (!tool_bar_item_info (f, *glyph, prop_idx))
+ return -1;
+
+ /* Is mouse on the highlighted item? */
+ if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
+ && *vpos >= dpyinfo->mouse_face_beg_row
+ && *vpos <= dpyinfo->mouse_face_end_row
+ && (*vpos > dpyinfo->mouse_face_beg_row
+ || *hpos >= dpyinfo->mouse_face_beg_col)
+ && (*vpos < dpyinfo->mouse_face_end_row
+ || *hpos < dpyinfo->mouse_face_end_col
+ || dpyinfo->mouse_face_past_end))
+ return 0;
+
+ return 1;
+}
+
+
+/* Handle mouse button event on the tool-bar of frame F, at
+ frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
+ or ButtonRelase. */
+
+static void
+x_handle_tool_bar_click (f, button_event)
+ struct frame *f;
+ EventRecord *button_event;
+{
+ struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+ struct window *w = XWINDOW (f->tool_bar_window);
+ int hpos, vpos, prop_idx;
+ struct glyph *glyph;
+ Lisp_Object enabled_p;
+ int x = button_event->where.h;
+ int y = button_event->where.v;
+
+ /* If not on the highlighted tool-bar item, return. */
+ frame_to_window_pixel_xy (w, &x, &y);
+ if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
+ return;
+
+ /* If item is disabled, do nothing. */
+ enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
+ if (NILP (enabled_p))
+ return;
+
+ if (button_event->what == mouseDown)
+ {
+ /* Show item in pressed state. */
+ show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
+ dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
+ last_tool_bar_item = prop_idx;
+ }
+ else
+ {
+ Lisp_Object key, frame;
+ struct input_event event;
+
+ /* Show item in released state. */
+ show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
+ dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
+
+ key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
+
+ XSETFRAME (frame, f);
+ event.kind = TOOL_BAR_EVENT;
+ event.frame_or_window = frame;
+ event.arg = frame;
+ kbd_buffer_store_event (&event);
+
+ event.kind = TOOL_BAR_EVENT;
+ event.frame_or_window = frame;
+ event.arg = key;
+ event.modifiers = x_mac_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
+ button_event->modifiers);
+ kbd_buffer_store_event (&event);
+ last_tool_bar_item = -1;
+ }
+}
+
+
+/* Possibly highlight a tool-bar item on frame F when mouse moves to
+ tool-bar window-relative coordinates X/Y. Called from
+ note_mouse_highlight. */
+
+static void
+note_tool_bar_highlight (f, x, y)
+ struct frame *f;
+ int x, y;
+{
+ Lisp_Object window = f->tool_bar_window;
+ struct window *w = XWINDOW (window);
+ struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+ int hpos, vpos;
+ struct glyph *glyph;
+ struct glyph_row *row;
+ int i;
+ Lisp_Object enabled_p;
+ int prop_idx;
+ enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
+ int mouse_down_p, rc;
+
+ /* Function note_mouse_highlight is called with negative x(y
+ values when mouse moves outside of the frame. */
+ if (x <= 0 || y <= 0)
+ {
+ clear_mouse_face (dpyinfo);
+ return;
+ }
+
+ rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
+ if (rc < 0)
+ {
+ /* Not on tool-bar item. */
+ clear_mouse_face (dpyinfo);
+ return;
+ }
+ else if (rc == 0)
+ /* On same tool-bar item as before. */
+ goto set_help_echo;
+
+ clear_mouse_face (dpyinfo);
+
+ /* Mouse is down, but on different tool-bar item? */
+ mouse_down_p = (dpyinfo->grabbed
+ && f == last_mouse_frame
+ && FRAME_LIVE_P (f));
+ if (mouse_down_p
+ && last_tool_bar_item != prop_idx)
+ return;
+
+ dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
+ draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
+
+ /* If tool-bar item is not enabled, don't highlight it. */
+ enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
+ if (!NILP (enabled_p))
+ {
+ /* Compute the x-position of the glyph. In front and past the
+ image is a space. We include this is the highlighted area. */
+ row = MATRIX_ROW (w->current_matrix, vpos);
+ for (i = x = 0; i < hpos; ++i)
+ x += row->glyphs[TEXT_AREA][i].pixel_width;
+
+ /* Record this as the current active region. */
+ dpyinfo->mouse_face_beg_col = hpos;
+ dpyinfo->mouse_face_beg_row = vpos;
+ dpyinfo->mouse_face_beg_x = x;
+ dpyinfo->mouse_face_beg_y = row->y;
+ dpyinfo->mouse_face_past_end = 0;
+
+ dpyinfo->mouse_face_end_col = hpos + 1;
+ dpyinfo->mouse_face_end_row = vpos;
+ dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
+ dpyinfo->mouse_face_end_y = row->y;
+ dpyinfo->mouse_face_window = window;
+ dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
+
+ /* Display it as active. */
+ show_mouse_face (dpyinfo, draw);
+ dpyinfo->mouse_face_image_state = draw;
+ }
+
+ set_help_echo:
+
+ /* Set help_echo to a help string.to display for this tool-bar item.
+ XTread_socket does the rest. */
+ help_echo_object = help_echo_window = Qnil;
+ help_echo_pos = -1;
+ help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
+ if (NILP (help_echo))
+ help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
+}
+
+
+\f
+/* Find the glyph matrix position of buffer position CHARPOS in window
+ *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
+ current glyphs must be up to date. If CHARPOS is above window
+ start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
+ of last line in W. In the row containing CHARPOS, stop before glyphs
+ having STOP as object. */
+
+#if 0 /* This is a version of fast_find_position that's more correct
+ in the presence of hscrolling, for example. I didn't install
+ it right away because the problem fixed is minor, it failed
+ in 20.x as well, and I think it's too risky to install
+ so near the release of 21.1. 2001-09-25 gerd. */
+
+static int
+fast_find_position (w, charpos, hpos, vpos, x, y, stop)
+ struct window *w;
+ int charpos;
+ int *hpos, *vpos, *x, *y;
+ Lisp_Object stop;
+{
+ struct glyph_row *row, *first;
+ struct glyph *glyph, *end;
+ int i, past_end = 0;
+
+ first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+ row = row_containing_pos (w, charpos, first, NULL, 0);
+ if (row == NULL)
+ {
+ if (charpos < MATRIX_ROW_START_CHARPOS (first))
+ {
+ *x = *y = *hpos = *vpos = 0;
+ return 0;
+ }
+ else
+ {
+ row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
+ past_end = 1;
+ }
+ }
+
+ *x = row->x;
+ *y = row->y;
+ *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
+
+ glyph = row->glyphs[TEXT_AREA];
+ end = glyph + row->used[TEXT_AREA];
+
+ /* Skip over glyphs not having an object at the start of the row.
+ These are special glyphs like truncation marks on terminal
+ frames. */
+ if (row->displays_text_p)
+ while (glyph < end
+ && INTEGERP (glyph->object)
+ && !EQ (stop, glyph->object)
+ && glyph->charpos < 0)
+ {
+ *x += glyph->pixel_width;
+ ++glyph;
+ }
+
+ while (glyph < end
+ && !INTEGERP (glyph->object)
+ && !EQ (stop, glyph->object)
+ && (!BUFFERP (glyph->object)
+ || glyph->charpos < charpos))
+ {
+ *x += glyph->pixel_width;
+ ++glyph;
+ }
+
+ *hpos = glyph - row->glyphs[TEXT_AREA];
+ return past_end;
+}
+
+#else /* not 0 */
+
+static int
+fast_find_position (w, pos, hpos, vpos, x, y, stop)
+ struct window *w;
+ int pos;
+ int *hpos, *vpos, *x, *y;
+ Lisp_Object stop;
+{
+ int i;
+ int lastcol;
+ int maybe_next_line_p = 0;
+ int line_start_position;
+ int yb = window_text_bottom_y (w);
+ struct glyph_row *row, *best_row;
+ int row_vpos, best_row_vpos;
+ int current_x;
+
+ row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+ row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
+
+ while (row->y < yb)
+ {
+ if (row->used[TEXT_AREA])
+ line_start_position = row->glyphs[TEXT_AREA]->charpos;
+ else
+ line_start_position = 0;
+
+ if (line_start_position > pos)
+ break;
+ /* If the position sought is the end of the buffer,
+ don't include the blank lines at the bottom of the window. */
+ else if (line_start_position == pos
+ && pos == BUF_ZV (XBUFFER (w->buffer)))
+ {
+ maybe_next_line_p = 1;
+ break;
+ }
+ else if (line_start_position > 0)
+ {
+ best_row = row;
+ best_row_vpos = row_vpos;
+ }
+
+ if (row->y + row->height >= yb)
+ break;
+
+ ++row;
+ ++row_vpos;
+ }
+
+ /* Find the right column within BEST_ROW. */
+ lastcol = 0;
+ current_x = best_row->x;
+ for (i = 0; i < best_row->used[TEXT_AREA]; i++)
+ {
+ struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
+ int charpos = glyph->charpos;
+
+ if (BUFFERP (glyph->object))
+ {
+ if (charpos == pos)
+ {
+ *hpos = i;
+ *vpos = best_row_vpos;
+ *x = current_x;
+ *y = best_row->y;
+ return 1;
+ }
+ else if (charpos > pos)
+ break;
+ }
+ else if (EQ (glyph->object, stop))
+ break;
+
+ if (charpos > 0)
+ lastcol = i;
+ current_x += glyph->pixel_width;
+ }
+
+ /* If we're looking for the end of the buffer,
+ and we didn't find it in the line we scanned,
+ use the start of the following line. */
+ if (maybe_next_line_p)
+ {
+ ++best_row;
+ ++best_row_vpos;
+ lastcol = 0;
+ current_x = best_row->x;
+ }
+
+ *vpos = best_row_vpos;
+ *hpos = lastcol + 1;
+ *x = current_x;
+ *y = best_row->y;
+ return 0;
+}
+
+#endif /* not 0 */
+
+
+/* Find the position of the glyph for position POS in OBJECT in
+ window W's current matrix, and return in *X/*Y the pixel
+ coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
+
+ RIGHT_P non-zero means return the position of the right edge of the
+ glyph, RIGHT_P zero means return the left edge position.
+
+ If no glyph for POS exists in the matrix, return the position of
+ the glyph with the next smaller position that is in the matrix, if
+ RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
+ exists in the matrix, return the position of the glyph with the
+ next larger position in OBJECT.
+
+ Value is non-zero if a glyph was found. */
+
+static int
+fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
+ struct window *w;
+ int pos;
+ Lisp_Object object;
+ int *hpos, *vpos, *x, *y;
+ int right_p;
+{
+ int yb = window_text_bottom_y (w);
+ struct glyph_row *r;
+ struct glyph *best_glyph = NULL;
+ struct glyph_row *best_row = NULL;
+ int best_x = 0;
+
+ for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+ r->enabled_p && r->y < yb;
+ ++r)
+ {
+ struct glyph *g = r->glyphs[TEXT_AREA];
+ struct glyph *e = g + r->used[TEXT_AREA];
+ int gx;
+
+ for (gx = r->x; g < e; gx += g->pixel_width, ++g)
+ if (EQ (g->object, object))
+ {
+ if (g->charpos == pos)
+ {
+ best_glyph = g;
+ best_x = gx;
+ best_row = r;
+ goto found;
+ }
+ else if (best_glyph == NULL
+ || ((abs (g->charpos - pos)
+ < abs (best_glyph->charpos - pos))
+ && (right_p
+ ? g->charpos < pos
+ : g->charpos > pos)))
+ {
+ best_glyph = g;
+ best_x = gx;
+ best_row = r;
+ }
+ }
+ }
+
+ found:
+
+ if (best_glyph)
+ {
+ *x = best_x;
+ *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
+
+ if (right_p)
+ {
+ *x += best_glyph->pixel_width;
+ ++*hpos;
+ }
+
+ *y = best_row->y;
+ *vpos = best_row - w->current_matrix->rows;
+ }
+
+ return best_glyph != NULL;
+}
+
+
+/* Display the active region described by mouse_face_*
+ in its mouse-face if HL > 0, in its normal face if HL = 0. */
+
+static void
+show_mouse_face (dpyinfo, draw)
+ struct mac_display_info *dpyinfo;
+ enum draw_glyphs_face draw;
+{
+ struct window *w = XWINDOW (dpyinfo->mouse_face_window);
+ struct frame *f = XFRAME (WINDOW_FRAME (w));
+
+ if (/* If window is in the process of being destroyed, don't bother
+ to do anything. */
+ w->current_matrix != NULL
+ /* Don't update mouse highlight if hidden */
+ && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
+ /* Recognize when we are called to operate on rows that don't exist
+ anymore. This can happen when a window is split. */
+ && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
+ {
+ int phys_cursor_on_p = w->phys_cursor_on_p;
+ struct glyph_row *row, *first, *last;
+
+ first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
+ last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
+
+ for (row = first; row <= last && row->enabled_p; ++row)
+ {
+ int start_hpos, end_hpos, start_x;
+
+ /* For all but the first row, the highlight starts at column 0. */
+ if (row == first)
+ {
+ start_hpos = dpyinfo->mouse_face_beg_col;
+ start_x = dpyinfo->mouse_face_beg_x;
+ }
+ else
+ {
+ start_hpos = 0;
+ start_x = 0;
+ }
+
+ if (row == last)
+ end_hpos = dpyinfo->mouse_face_end_col;
+ else
+ end_hpos = row->used[TEXT_AREA];
+
+ if (end_hpos > start_hpos)
+ {
+ x_draw_glyphs (w, start_x, row, TEXT_AREA,
+ start_hpos, end_hpos, draw, 0);
+
+ row->mouse_face_p
+ = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
+ }
+ }
+
+ /* When we've written over the cursor, arrange for it to
+ be displayed again. */
+ if (phys_cursor_on_p && !w->phys_cursor_on_p)
+ x_display_cursor (w, 1,
+ w->phys_cursor.hpos, w->phys_cursor.vpos,
+ w->phys_cursor.x, w->phys_cursor.y);
+ }
+
+#if 0 /* MAC_TODO: mouse cursor */
+ /* Change the mouse cursor. */
+ if (draw == DRAW_NORMAL_TEXT)
+ XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ f->output_data.x->text_cursor);
+ else if (draw == DRAW_MOUSE_FACE)
+ XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ f->output_data.x->cross_cursor);
+ else
+ XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ f->output_data.x->nontext_cursor);
+#endif
+}
+
+/* Clear out the mouse-highlighted active region.
+ Redraw it un-highlighted first. */
+
+static int
+clear_mouse_face (dpyinfo)
+ struct mac_display_info *dpyinfo;
+{
+ int cleared = 0;
+
+ if (! NILP (dpyinfo->mouse_face_window))
+ {
+ show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
+ cleared = 1;
+ }
+
+ dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
+ dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
+ dpyinfo->mouse_face_window = Qnil;
+ dpyinfo->mouse_face_overlay = Qnil;
+ return cleared;
+}
+
+
+/* Clear any mouse-face on window W. This function is part of the
+ redisplay interface, and is called from try_window_id and similar
+ functions to ensure the mouse-highlight is off. */
+
+static void
+x_clear_mouse_face (w)
+ struct window *w;
+{
+ struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
+ Lisp_Object window;
+
+ BLOCK_INPUT;
+ XSETWINDOW (window, w);
+ if (EQ (window, dpyinfo->mouse_face_window))
+ clear_mouse_face (dpyinfo);
+ UNBLOCK_INPUT;
+}
+
+
+/* Just discard the mouse face information for frame F, if any.
+ This is used when the size of F is changed. */
+
+void
+cancel_mouse_face (f)
+ FRAME_PTR f;
+{
+ Lisp_Object window;
+ struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+
+ window = dpyinfo->mouse_face_window;
+ if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
+ {
+ dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
+ dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
+ dpyinfo->mouse_face_window = Qnil;
+ }
+}
+\f
+static struct scroll_bar *x_window_to_scroll_bar ();
+static void x_scroll_bar_report_motion ();
+static void x_check_fullscreen P_ ((struct frame *));
+static void x_check_fullscreen_move P_ ((struct frame *));
+static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
+
+
+/* Try to determine frame pixel position and size of the glyph under
+ frame pixel coordinates X/Y on frame F . Return the position and
+ size in *RECT. Value is non-zero if we could compute these
+ values. */
+
+static int
+glyph_rect (f, x, y, rect)
+ struct frame *f;
+ int x, y;
+ Rect *rect;
+{
+ Lisp_Object window;
+ int part;
+
+ window = window_from_coordinates (f, x, y, &part, 0);
+ if (!NILP (window))
+ {
+ struct window *w = XWINDOW (window);
+ struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+ struct glyph_row *end = r + w->current_matrix->nrows - 1;
+
+ frame_to_window_pixel_xy (w, &x, &y);
+
+ for (; r < end && r->enabled_p; ++r)
+ if (r->y <= y && r->y + r->height > y)
+ {
+ /* Found the row at y. */
+ struct glyph *g = r->glyphs[TEXT_AREA];
+ struct glyph *end = g + r->used[TEXT_AREA];
+ int gx;
+
+ rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
+ rect->bottom = rect->top + r->height;
+
+ if (x < r->x)
+ {
+ /* x is to the left of the first glyph in the row. */
+ rect->left = XINT (w->left);
+ rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
+ return 1;
+ }
+
+ for (gx = r->x; g < end; gx += g->pixel_width, ++g)
+ if (gx <= x && gx + g->pixel_width > x)
+ {
+ /* x is on a glyph. */
+ rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
+ rect->right = rect->left + g->pixel_width;
+ return 1;
+ }
+
+ /* x is to the right of the last glyph in the row. */
+ rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
+ rect->right = XINT (w->left) + XINT (w->width);
+ return 1;
+ }
+ }
+
+ /* The y is not on any row. */
+ return 0;
+}
+
+/* Record the position of the mouse in last_mouse_glyph. */
+static void
+remember_mouse_glyph (f1, gx, gy)
+ struct frame * f1;
+ int gx, gy;
+{
+ if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
+ {
+ int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
+ int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
+
+ /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
+ round down even for negative values. */
+ if (gx < 0)
+ gx -= width - 1;
+ if (gy < 0)
+ gy -= height - 1;
+#if 0
+ /* This was the original code from XTmouse_position, but it seems
+ to give the position of the glyph diagonally next to the one
+ the mouse is over. */
+ gx = (gx + width - 1) / width * width;
+ gy = (gy + height - 1) / height * height;
+#else
+ gx = gx / width * width;
+ gy = gy / height * height;
+#endif
+
+ last_mouse_glyph.left = gx;
+ last_mouse_glyph.top = gy;
+ last_mouse_glyph.right = gx + width;
+ last_mouse_glyph.bottom = gy + height;
+ }
+}
+
+/* Return the current position of the mouse.
+ *fp should be a frame which indicates which display to ask about.
+
+ If the mouse movement started in a scroll bar, set *fp, *bar_window,
+ and *part to the frame, window, and scroll bar part that the mouse
+ is over. Set *x and *y to the portion and whole of the mouse's
+ position on the scroll bar.
+
+ If the mouse movement started elsewhere, set *fp to the frame the
+ mouse is on, *bar_window to nil, and *x and *y to the character cell
+ the mouse is over.
+
+ Set *time to the server time-stamp for the time at which the mouse
+ was at this position.
+
+ Don't store anything if we don't have a valid set of values to report.
+
+ This clears the mouse_moved flag, so we can wait for the next mouse
+ movement. */
+
+static void
+XTmouse_position (fp, insist, bar_window, part, x, y, time)
+ FRAME_PTR *fp;
+ int insist;
+ Lisp_Object *bar_window;
+ enum scroll_bar_part *part;
+ Lisp_Object *x, *y;
+ unsigned long *time;
+{
+ Point mouse_pos;
+ int ignore1, ignore2;
+ WindowPtr wp = FrontWindow ();
+ struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
+ Lisp_Object frame, tail;
+
+ BLOCK_INPUT;
+
+ if (! NILP (last_mouse_scroll_bar) && insist == 0)
+ x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
+ else
+ {
+ /* Clear the mouse-moved flag for every frame on this display. */
+ FOR_EACH_FRAME (tail, frame)
+ XFRAME (frame)->mouse_moved = 0;
+
+ last_mouse_scroll_bar = Qnil;
+
+#if TARGET_API_MAC_CARBON
+ SetPort (GetWindowPort (wp));
+#else
+ SetPort (wp);
+#endif
+
+ GetMouse (&mouse_pos);
+
+ pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
+ &last_mouse_glyph, insist);
+
+ *bar_window = Qnil;
+ *part = scroll_bar_handle;
+ *fp = f;
+ XSETINT (*x, mouse_pos.h);
+ XSETINT (*y, mouse_pos.v);
+ *time = last_mouse_movement_time;
+ }
+
+ UNBLOCK_INPUT;
+}
+
+\f
+/************************************************************************
+ Scroll bars, general
+ ************************************************************************/
+
+/* Create a scroll bar and return the scroll bar vector for it. W is
+ the Emacs window on which to create the scroll bar. TOP, LEFT,
+ WIDTH and HEIGHT are the pixel coordinates and dimensions of the
+ scroll bar. */
+
+static struct scroll_bar *
+x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
+ struct window *w;
+ int top, left, width, height, disp_top, disp_height;
+{
+ struct frame *f = XFRAME (w->frame);
+ struct scroll_bar *bar
+ = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
+ Rect r;
+ ControlHandle ch;
+
+ BLOCK_INPUT;
+
+ r.left = left;
+ r.top = disp_top;
+ r.right = left + width;
+ r.bottom = disp_top + disp_height;
+
+#ifdef TARGET_API_MAC_CARBON
+ ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0,
+ kControlScrollBarProc, 0L);
+#else
+ ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
+ 0L);
+#endif
+ SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
+ SetControlReference (ch, (long) bar);
+
+ XSETWINDOW (bar->window, w);
+ XSETINT (bar->top, top);
+ XSETINT (bar->left, left);
+ XSETINT (bar->width, width);
+ XSETINT (bar->height, height);
+ XSETINT (bar->start, 0);
+ XSETINT (bar->end, 0);
+ bar->dragging = Qnil;
+
+ /* Add bar to its frame's list of scroll bars. */
+ bar->next = FRAME_SCROLL_BARS (f);
+ bar->prev = Qnil;
+ XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
+ if (!NILP (bar->next))
+ XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
+
+ UNBLOCK_INPUT;
+ return bar;
+}
+
+
+/* Draw BAR's handle in the proper position.
+
+ If the handle is already drawn from START to END, don't bother
+ redrawing it, unless REBUILD is non-zero; in that case, always
+ redraw it. (REBUILD is handy for drawing the handle after expose
+ events.)
+
+ Normally, we want to constrain the start and end of the handle to
+ fit inside its rectangle, but if the user is dragging the scroll
+ bar handle, we want to let them drag it down all the way, so that
+ the bar's top is as far down as it goes; otherwise, there's no way
+ to move to the very end of the buffer. */
+
+static void
+x_scroll_bar_set_handle (bar, start, end, rebuild)
+ struct scroll_bar *bar;
+ int start, end;
+ int rebuild;
+{
+ int dragging = ! NILP (bar->dragging);
+ ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
+ FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
+ int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
+ int length = end - start;
+
+ /* If the display is already accurate, do nothing. */
+ if (! rebuild
+ && start == XINT (bar->start)
+ && end == XINT (bar->end))
+ return;
+
+ BLOCK_INPUT;
+
+ /* Make sure the values are reasonable, and try to preserve the
+ distance between start and end. */
+ if (start < 0)
+ start = 0;
+ else if (start > top_range)
+ start = top_range;
+ end = start + length;
+
+ if (end < start)
+ end = start;
+ else if (end > top_range && ! dragging)
+ end = top_range;
+
+ /* Store the adjusted setting in the scroll bar. */
+ XSETINT (bar->start, start);
+ XSETINT (bar->end, end);
+
+ /* Clip the end position, just for display. */
+ if (end > top_range)
+ end = top_range;
+
+ /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
+ top positions, to make sure the handle is always at least that
+ many pixels tall. */
+ end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
+
+ SetControlMinimum (ch, 0);
+ /* Don't inadvertently activate deactivated scroll bars */
+ if (GetControlMaximum (ch) != -1)
+ SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
+ - (end - start));
+ SetControlValue (ch, start);
+#if TARGET_API_MAC_CARBON
+ SetControlViewSize (ch, end - start);
+#endif
+
+ UNBLOCK_INPUT;
+}
+
+
+/* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
+ nil. */
+
+static void
+x_scroll_bar_remove (bar)
+ struct scroll_bar *bar;
+{
+ FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
+
+ BLOCK_INPUT;
+
+ /* Destroy the Mac scroll bar control */
+ DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
+
+ /* Disassociate this scroll bar from its window. */
+ XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
+
+ UNBLOCK_INPUT;
+}
+
+/* Set the handle of the vertical scroll bar for WINDOW to indicate
+ that we are displaying PORTION characters out of a total of WHOLE
+ characters, starting at POSITION. If WINDOW has no scroll bar,
+ create one. */
+static void
+XTset_vertical_scroll_bar (w, portion, whole, position)
+ struct window *w;
+ int portion, whole, position;
+{
+ struct frame *f = XFRAME (w->frame);
+ struct scroll_bar *bar;
+ int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
+ int window_x, window_y, window_width, window_height;
+
+ /* Get window dimensions. */
+ window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
+ top = window_y;
+#ifdef MAC_OSX
+ width = 16;
+#else
+ width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
+#endif
+ height = window_height;
+
+ /* Compute the left edge of the scroll bar area. */
+ if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
+ left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
+ else
+ left = XFASTINT (w->left);
+ left *= CANON_X_UNIT (f);
+ left += FRAME_INTERNAL_BORDER_WIDTH (f);
+
+ /* Compute the width of the scroll bar which might be less than
+ the width of the area reserved for the scroll bar. */
+ if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
+ sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
+ else
+ sb_width = width;
+
+ /* Compute the left edge of the scroll bar. */
+ if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
+ sb_left = left + width - sb_width - (width - sb_width) / 2;
+ else
+ sb_left = left + (width - sb_width) / 2;
+
+ /* Adjustments according to Inside Macintosh to make it look nice */
+ disp_top = top;
+ disp_height = height;
+ if (disp_top == 0)
+ {
+ disp_top = -1;
+ disp_height++;
+ }
+ else if (disp_top == PIXEL_HEIGHT (f) - 16)
+ {
+ disp_top++;
+ disp_height--;
+ }
+
+ if (sb_left + sb_width == PIXEL_WIDTH (f))
+ sb_left++;
+
+ /* Does the scroll bar exist yet? */
+ if (NILP (w->vertical_scroll_bar))
+ {
+ BLOCK_INPUT;
+ XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
+ left, top, width, height, 0);
+ UNBLOCK_INPUT;
+ bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
+ disp_height);
+ XSETVECTOR (w->vertical_scroll_bar, bar);
+ }
+ else
+ {
+ /* It may just need to be moved and resized. */
+ ControlHandle ch;
+
+ bar = XSCROLL_BAR (w->vertical_scroll_bar);
+ ch = SCROLL_BAR_CONTROL_HANDLE (bar);
+
+ BLOCK_INPUT;
+
+ /* If already correctly positioned, do nothing. */
+ if (XINT (bar->left) == sb_left
+ && XINT (bar->top) == top
+ && XINT (bar->width) == sb_width
+ && XINT (bar->height) == height)
+ Draw1Control (ch);
+ else
+ {
+ /* Clear areas not covered by the scroll bar because it's not as
+ wide as the area reserved for it . This makes sure a
+ previous mode line display is cleared after C-x 2 C-x 1, for
+ example. */
+ int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
+ XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
+ left, top, area_width, height, 0);
+
+#if 0
+ if (sb_left + sb_width >= PIXEL_WIDTH (f))
+ XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
+ sb_left - 1, top, 1, height, 0);
+#endif
+
+ HideControl (ch);
+ MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
+ SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
+ disp_height);
+ ShowControl (ch);
+
+ /* Remember new settings. */
+ XSETINT (bar->left, sb_left);
+ XSETINT (bar->top, top);
+ XSETINT (bar->width, sb_width);
+ XSETINT (bar->height, height);
+ }
+
+ UNBLOCK_INPUT;
+ }
+
+ /* Set the scroll bar's current state, unless we're currently being
+ dragged. */
+ if (NILP (bar->dragging))
+ {
+ int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
+
+ if (whole == 0)
+ x_scroll_bar_set_handle (bar, 0, top_range, 0);
+ else
+ {
+ int start = ((double) position * top_range) / whole;
+ int end = ((double) (position + portion) * top_range) / whole;
+ x_scroll_bar_set_handle (bar, start, end, 0);
+ }
+ }
+}
+
+
+/* The following three hooks are used when we're doing a thorough
+ redisplay of the frame. We don't explicitly know which scroll bars
+ are going to be deleted, because keeping track of when windows go
+ away is a real pain - "Can you say set-window-configuration, boys
+ and girls?" Instead, we just assert at the beginning of redisplay
+ that *all* scroll bars are to be removed, and then save a scroll bar
+ from the fiery pit when we actually redisplay its window. */
+
+/* Arrange for all scroll bars on FRAME to be removed at the next call
+ to `*judge_scroll_bars_hook'. A scroll bar may be spared if
+ `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
+
+static void
+XTcondemn_scroll_bars (frame)
+ FRAME_PTR frame;
+{
+ /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
+ while (! NILP (FRAME_SCROLL_BARS (frame)))
+ {
+ Lisp_Object bar;
+ bar = FRAME_SCROLL_BARS (frame);
+ FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
+ XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
+ XSCROLL_BAR (bar)->prev = Qnil;
+ if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
+ XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
+ FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
+ }
+}
+
+
+/* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
+ Note that WINDOW isn't necessarily condemned at all. */
+
+static void
+XTredeem_scroll_bar (window)
+ struct window *window;
+{
+ struct scroll_bar *bar;
+
+ /* We can't redeem this window's scroll bar if it doesn't have one. */
+ if (NILP (window->vertical_scroll_bar))
+ abort ();
+
+ bar = XSCROLL_BAR (window->vertical_scroll_bar);
+
+ /* Unlink it from the condemned list. */
+ {
+ FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
+
+ if (NILP (bar->prev))
+ {
+ /* If the prev pointer is nil, it must be the first in one of
+ the lists. */
+ if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
+ /* It's not condemned. Everything's fine. */
+ return;
+ else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
+ window->vertical_scroll_bar))
+ FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
+ else
+ /* If its prev pointer is nil, it must be at the front of
+ one or the other! */
+ abort ();
+ }
+ else
+ XSCROLL_BAR (bar->prev)->next = bar->next;
+
+ if (! NILP (bar->next))
+ XSCROLL_BAR (bar->next)->prev = bar->prev;
+
+ bar->next = FRAME_SCROLL_BARS (f);
+ bar->prev = Qnil;
+ XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
+ if (! NILP (bar->next))
+ XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
+ }
+}
+
+/* Remove all scroll bars on FRAME that haven't been saved since the
+ last call to `*condemn_scroll_bars_hook'. */
+
+static void
+XTjudge_scroll_bars (f)
+ FRAME_PTR f;
+{
+ Lisp_Object bar, next;
+
+ bar = FRAME_CONDEMNED_SCROLL_BARS (f);
+
+ /* Clear out the condemned list now so we won't try to process any
+ more events on the hapless scroll bars. */
+ FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
+
+ for (; ! NILP (bar); bar = next)
+ {
+ struct scroll_bar *b = XSCROLL_BAR (bar);
+
+ x_scroll_bar_remove (b);
+
+ next = b->next;
+ b->next = b->prev = Qnil;
+ }
+
+ /* Now there should be no references to the condemned scroll bars,
+ and they should get garbage-collected. */
+}
+
+
+static void
+activate_scroll_bars (frame)
+ FRAME_PTR frame;
+{
+ Lisp_Object bar;
+ ControlHandle ch;
+
+ bar = FRAME_SCROLL_BARS (frame);
+ while (! NILP (bar))
+ {
+ ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
+#ifdef TARGET_API_MAC_CARBON
+ ActivateControl (ch);
+#else
+ SetControlMaximum (ch,
+ VERTICAL_SCROLL_BAR_TOP_RANGE (frame,
+ XINT (XSCROLL_BAR (bar)
+ ->height)) - 1);
+#endif
+ bar = XSCROLL_BAR (bar)->next;
+ }
+}
+
+
+static void
+deactivate_scroll_bars (frame)
+ FRAME_PTR frame;
+{
+ Lisp_Object bar;
+ ControlHandle ch;
+
+ bar = FRAME_SCROLL_BARS (frame);
+ while (! NILP (bar))
+ {
+ ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
+#ifdef TARGET_API_MAC_CARBON
+ DeactivateControl (ch);
+#else
+ SetControlMaximum (ch, XINT (-1));
+#endif
+ bar = XSCROLL_BAR (bar)->next;
+ }
+}
+
+/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
+ is set to something other than no_event, it is enqueued.
+
+ This may be called from a signal handler, so we have to ignore GC
+ mark bits. */
+
+static void
+x_scroll_bar_handle_click (bar, part_code, er, bufp)
+ struct scroll_bar *bar;
+ int part_code;
+ EventRecord *er;
+ struct input_event *bufp;
+{
+ if (! GC_WINDOWP (bar->window))
+ abort ();
+
+ bufp->kind = scroll_bar_click;
+ bufp->frame_or_window = bar->window;
+ bufp->arg = Qnil;
+
+ bar->dragging = Qnil;
+
+ switch (part_code)
+ {
+ case kControlUpButtonPart:
+ bufp->part = scroll_bar_up_arrow;
+ break;
+ case kControlDownButtonPart:
+ bufp->part = scroll_bar_down_arrow;
+ break;
+ case kControlPageUpPart:
+ bufp->part = scroll_bar_above_handle;
+ break;
+ case kControlPageDownPart:
+ bufp->part = scroll_bar_below_handle;
+ break;
+#ifdef TARGET_API_MAC_CARBON
+ default:
+#else
+ case kControlIndicatorPart:
+#endif
+ if (er->what == mouseDown)
+ bar->dragging = make_number (0);
+ XSETVECTOR (last_mouse_scroll_bar, bar);
+ bufp->part = scroll_bar_handle;
+ break;
+ }
+}
+
+
+/* Handle some mouse motion while someone is dragging the scroll bar.
+
+ This may be called from a signal handler, so we have to ignore GC
+ mark bits. */
+
+static void
+x_scroll_bar_note_movement (bar, y_pos, t)
+ struct scroll_bar *bar;
+ int y_pos;
+ Time t;
+{
+ FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
+
+ last_mouse_movement_time = t;
+
+ f->mouse_moved = 1;
+ XSETVECTOR (last_mouse_scroll_bar, bar);
+
+ /* If we're dragging the bar, display it. */
+ if (! GC_NILP (bar->dragging))
+ {
+ /* Where should the handle be now? */
+ int new_start = y_pos - 24;
+
+ if (new_start != XINT (bar->start))
+ {
+ int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
+
+ x_scroll_bar_set_handle (bar, new_start, new_end, 0);
+ }
+ }
+}
+
+
+/* Return information to the user about the current position of the
+ mouse on the scroll bar. */
+
+static void
+x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
+ FRAME_PTR *fp;
+ Lisp_Object *bar_window;
+ enum scroll_bar_part *part;
+ Lisp_Object *x, *y;
+ unsigned long *time;
+{
+ struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
+ WindowPtr wp = FrontWindow ();
+ Point mouse_pos;
+ struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
+ int win_y, top_range;
+
+#if TARGET_API_MAC_CARBON
+ SetPort (GetWindowPort (wp));
+#else
+ SetPort (wp);
+#endif
+
+ GetMouse (&mouse_pos);
+
+ win_y = mouse_pos.v - XINT (bar->top);
+ top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
+
+ win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
+
+ win_y -= 24;
+
+ if (! NILP (bar->dragging))
+ win_y -= XINT (bar->dragging);
+
+ if (win_y < 0)
+ win_y = 0;
+ if (win_y > top_range)
+ win_y = top_range;
+
+ *fp = f;
+ *bar_window = bar->window;
+
+ if (! NILP (bar->dragging))
+ *part = scroll_bar_handle;
+ else if (win_y < XINT (bar->start))
+ *part = scroll_bar_above_handle;
+ else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
+ *part = scroll_bar_handle;
+ else
+ *part = scroll_bar_below_handle;
+
+ XSETINT (*x, win_y);
+ XSETINT (*y, top_range);
+
+ f->mouse_moved = 0;
+ last_mouse_scroll_bar = Qnil;
+
+ *time = last_mouse_movement_time;
+}
+\f
+/***********************************************************************
+ Text Cursor
+ ***********************************************************************/
+
+/* Notice if the text cursor of window W has been overwritten by a
+ drawing operation that outputs glyphs starting at START_X and
+ ending at END_X in the line given by output_cursor.vpos.
+ Coordinates are area-relative. END_X < 0 means all the rest
+ of the line after START_X has been written. */
+
+static void
+notice_overwritten_cursor (w, area, x0, x1, y0, y1)
+ struct window *w;
+ enum glyph_row_area area;
+ int x0, x1, y0, y1;
+{
+ if (area == TEXT_AREA
+ && w->phys_cursor_on_p
+ && y0 <= w->phys_cursor.y
+ && y1 >= w->phys_cursor.y + w->phys_cursor_height
+ && x0 <= w->phys_cursor.x
+ && (x1 < 0 || x1 > w->phys_cursor.x))
+ w->phys_cursor_on_p = 0;
+}
+
+
+/* Set clipping for output in glyph row ROW. W is the window in which
+ we operate. GC is the graphics context to set clipping in.
+ WHOLE_LINE_P non-zero means include the areas used for truncation
+ mark display and alike in the clipping rectangle.
+
+ ROW may be a text row or, e.g., a mode line. Text rows must be
+ clipped to the interior of the window dedicated to text display,
+ mode lines must be clipped to the whole window. */
+
+static void
+x_clip_to_row (w, row, gc, whole_line_p)
+ struct window *w;
+ struct glyph_row *row;
+ GC gc;
+ int whole_line_p;
+{
+ struct frame *f = XFRAME (WINDOW_FRAME (w));
+ Rect clip_rect;
+ int window_x, window_y, window_width, window_height;
+
+ window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
+
+ clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
+ clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
+ clip_rect.top = max (clip_rect.top, window_y);
+ clip_rect.right = clip_rect.left + window_width;
+ clip_rect.bottom = clip_rect.top + row->visible_height;
+
+ /* If clipping to the whole line, including trunc marks, extend
+ the rectangle to the left and increase its width. */
+ if (whole_line_p)
+ {
+ clip_rect.left -= FRAME_X_LEFT_FRINGE_WIDTH (f);
+ clip_rect.right += FRAME_X_FRINGE_WIDTH (f);
+ }
+
+ mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
+}
+
+
+/* Draw a hollow box cursor on window W in glyph row ROW. */
+
+static void
+x_draw_hollow_cursor (w, row)
+ struct window *w;
+ struct glyph_row *row;
+{
+ struct frame *f = XFRAME (WINDOW_FRAME (w));
+ struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+ Display *dpy = FRAME_MAC_DISPLAY (f);
+ int x, y, wd, h;
+ XGCValues xgcv;
+ struct glyph *cursor_glyph;
+ GC gc;
+
+ /* Compute frame-relative coordinates from window-relative
+ coordinates. */
+ x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
+ y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
+ + row->ascent - w->phys_cursor_ascent);
+ h = row->height - 1;
+
+ /* Get the glyph the cursor is on. If we can't tell because
+ the current matrix is invalid or such, give up. */
+ cursor_glyph = get_phys_cursor_glyph (w);
+ if (cursor_glyph == NULL)
+ return;
+
+ /* Compute the width of the rectangle to draw. If on a stretch
+ glyph, and `x-stretch-block-cursor' is nil, don't draw a
+ rectangle as wide as the glyph, but use a canonical character
+ width instead. */
+ wd = cursor_glyph->pixel_width - 1;
+ if (cursor_glyph->type == STRETCH_GLYPH
+ && !x_stretch_cursor_p)
+ wd = min (CANON_X_UNIT (f), wd);
+
+ /* The foreground of cursor_gc is typically the same as the normal
+ background color, which can cause the cursor box to be invisible. */
+ xgcv.foreground = f->output_data.mac->cursor_pixel;
+ if (dpyinfo->scratch_cursor_gc)
+ XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
+ else
+ dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
+ GCForeground, &xgcv);
+ gc = dpyinfo->scratch_cursor_gc;
+
+ /* Set clipping, draw the rectangle, and reset clipping again. */
+ x_clip_to_row (w, row, gc, 0);
+ mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
+ mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
+}
+
+
+/* Draw a bar cursor on window W in glyph row ROW.
+
+ Implementation note: One would like to draw a bar cursor with an
+ angle equal to the one given by the font property XA_ITALIC_ANGLE.
+ Unfortunately, I didn't find a font yet that has this property set.
+ --gerd. */
+
+static void
+x_draw_bar_cursor (w, row, width)
+ struct window *w;
+ struct glyph_row *row;
+ int width;
+{
+ /* If cursor hpos is out of bounds, don't draw garbage. This can
+ happen in mini-buffer windows when switching between echo area
+ glyphs and mini-buffer. */
+ if (w->phys_cursor.hpos < row->used[TEXT_AREA])
+ {
+ struct frame *f = XFRAME (w->frame);
+ struct glyph *cursor_glyph;
+ GC gc;
+ int x;
+ unsigned long mask;
+ XGCValues xgcv;
+ Display *dpy;
+ Window window;
+
+ cursor_glyph = get_phys_cursor_glyph (w);
+ if (cursor_glyph == NULL)
+ return;
+
+ xgcv.background = f->output_data.mac->cursor_pixel;
+ xgcv.foreground = f->output_data.mac->cursor_pixel;
+ mask = GCForeground | GCBackground;
+ dpy = FRAME_MAC_DISPLAY (f);
+ window = FRAME_MAC_WINDOW (f);
+ gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
+
+ if (gc)
+ XChangeGC (dpy, gc, mask, &xgcv);
+ else
+ {
+ gc = XCreateGC (dpy, window, mask, &xgcv);
+ FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
+ }
+
+ if (width < 0)
+ width = f->output_data.mac->cursor_width;
+
+ x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
+ x_clip_to_row (w, row, gc, 0);
+ XFillRectangle (dpy, window, gc,
+ x,
+ WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
+ min (cursor_glyph->pixel_width, width),
+ row->height);
+ mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
+ }
+}
+
+
+/* Clear the cursor of window W to background color, and mark the
+ cursor as not shown. This is used when the text where the cursor
+ is is about to be rewritten. */
+
+static void
+x_clear_cursor (w)
+ struct window *w;
+{
+ if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
+ x_update_window_cursor (w, 0);
+}
+
+
+/* Draw the cursor glyph of window W in glyph row ROW. See the
+ comment of x_draw_glyphs for the meaning of HL. */
+
+static void
+x_draw_phys_cursor_glyph (w, row, hl)
+ struct window *w;
+ struct glyph_row *row;
+ enum draw_glyphs_face hl;
+{
+ /* If cursor hpos is out of bounds, don't draw garbage. This can
+ happen in mini-buffer windows when switching between echo area
+ glyphs and mini-buffer. */
+ if (w->phys_cursor.hpos < row->used[TEXT_AREA])
+ {
+ int on_p = w->phys_cursor_on_p;
+ x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
+ w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
+ hl, 0);
+ w->phys_cursor_on_p = on_p;
+
+ /* When we erase the cursor, and ROW is overlapped by other
+ rows, make sure that these overlapping parts of other rows
+ are redrawn. */
+ if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
+ {
+ if (row > w->current_matrix->rows
+ && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
+ x_fix_overlapping_area (w, row - 1, TEXT_AREA);
+
+ if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
+ && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
+ x_fix_overlapping_area (w, row + 1, TEXT_AREA);
+ }
+ }
+}
+
+
+/* Erase the image of a cursor of window W from the screen. */
+
+static void
+x_erase_phys_cursor (w)
+ struct window *w;
+{
+ struct frame *f = XFRAME (w->frame);
+ struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ int hpos = w->phys_cursor.hpos;
+ int vpos = w->phys_cursor.vpos;
+ int mouse_face_here_p = 0;
+ struct glyph_matrix *active_glyphs = w->current_matrix;
+ struct glyph_row *cursor_row;
+ struct glyph *cursor_glyph;
+ enum draw_glyphs_face hl;
+
+ /* No cursor displayed or row invalidated => nothing to do on the
+ screen. */
+ if (w->phys_cursor_type == NO_CURSOR)
+ goto mark_cursor_off;
+
+ /* VPOS >= active_glyphs->nrows means that window has been resized.
+ Don't bother to erase the cursor. */
+ if (vpos >= active_glyphs->nrows)
+ goto mark_cursor_off;
+
+ /* If row containing cursor is marked invalid, there is nothing we
+ can do. */
+ cursor_row = MATRIX_ROW (active_glyphs, vpos);
+ if (!cursor_row->enabled_p)
+ goto mark_cursor_off;
+
+ /* If row is completely invisible, don't attempt to delete a cursor which
+ isn't there. This may happen if cursor is at top of window, and
+ we switch to a buffer with a header line in that window. */
+ if (cursor_row->visible_height <= 0)
+ goto mark_cursor_off;
+
+ /* This can happen when the new row is shorter than the old one.
+ In this case, either x_draw_glyphs or clear_end_of_line
+ should have cleared the cursor. Note that we wouldn't be
+ able to erase the cursor in this case because we don't have a
+ cursor glyph at hand. */
+ if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
+ goto mark_cursor_off;
+
+ /* If the cursor is in the mouse face area, redisplay that when
+ we clear the cursor. */
+ if (! NILP (dpyinfo->mouse_face_window)
+ && w == XWINDOW (dpyinfo->mouse_face_window)
+ && (vpos > dpyinfo->mouse_face_beg_row
+ || (vpos == dpyinfo->mouse_face_beg_row
+ && hpos >= dpyinfo->mouse_face_beg_col))
+ && (vpos < dpyinfo->mouse_face_end_row
+ || (vpos == dpyinfo->mouse_face_end_row
+ && hpos < dpyinfo->mouse_face_end_col))
+ /* Don't redraw the cursor's spot in mouse face if it is at the
+ end of a line (on a newline). The cursor appears there, but
+ mouse highlighting does not. */
+ && cursor_row->used[TEXT_AREA] > hpos)
+ mouse_face_here_p = 1;
+
+ /* Maybe clear the display under the cursor. */
+ if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
+ {
+ int x;
+ int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
+
+ cursor_glyph = get_phys_cursor_glyph (w);
+ if (cursor_glyph == NULL)
+ goto mark_cursor_off;
+
+ x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
+
+ XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
+ x,
+ WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
+ cursor_row->y)),
+ cursor_glyph->pixel_width,
+ cursor_row->visible_height,
+ 0);
+ }
+
+ /* Erase the cursor by redrawing the character underneath it. */
+ if (mouse_face_here_p)
+ hl = DRAW_MOUSE_FACE;
+ else
+ hl = DRAW_NORMAL_TEXT;
+ x_draw_phys_cursor_glyph (w, cursor_row, hl);
+
+ mark_cursor_off:
+ w->phys_cursor_on_p = 0;
+ w->phys_cursor_type = NO_CURSOR;
+}
+
+
+/* Non-zero if physical cursor of window W is within mouse face. */
+
+static int
+cursor_in_mouse_face_p (w)
+ struct window *w;
+{
+ struct mac_display_info *dpyinfo
+ = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
+ int in_mouse_face = 0;
+
+ if (WINDOWP (dpyinfo->mouse_face_window)
+ && XWINDOW (dpyinfo->mouse_face_window) == w)
+ {
+ int hpos = w->phys_cursor.hpos;
+ int vpos = w->phys_cursor.vpos;
+
+ if (vpos >= dpyinfo->mouse_face_beg_row
+ && vpos <= dpyinfo->mouse_face_end_row
+ && (vpos > dpyinfo->mouse_face_beg_row
+ || hpos >= dpyinfo->mouse_face_beg_col)
+ && (vpos < dpyinfo->mouse_face_end_row
+ || hpos < dpyinfo->mouse_face_end_col
+ || dpyinfo->mouse_face_past_end))
+ in_mouse_face = 1;
+ }
+
+ return in_mouse_face;
+}
+
+
+/* Display or clear cursor of window W. If ON is zero, clear the
+ cursor. If it is non-zero, display the cursor. If ON is nonzero,
+ where to put the cursor is specified by HPOS, VPOS, X and Y. */
+
+void
+x_display_and_set_cursor (w, on, hpos, vpos, x, y)
+ struct window *w;
+ int on, hpos, vpos, x, y;
+{
+ struct frame *f = XFRAME (w->frame);
+ int new_cursor_type;
+ int new_cursor_width;
+ struct glyph_matrix *current_glyphs;
+ struct glyph_row *glyph_row;
+ struct glyph *glyph;
+ int cursor_non_selected;
+ int active_cursor = 1;
+
+ /* This is pointless on invisible frames, and dangerous on garbaged
+ windows and frames; in the latter case, the frame or window may
+ be in the midst of changing its size, and x and y may be off the
+ window. */
+ if (! FRAME_VISIBLE_P (f)
+ || FRAME_GARBAGED_P (f)
+ || vpos >= w->current_matrix->nrows
+ || hpos >= w->current_matrix->matrix_w)
+ return;
+
+ /* If cursor is off and we want it off, return quickly. */
+ if (!on && !w->phys_cursor_on_p)
+ return;
+
+ current_glyphs = w->current_matrix;
+ glyph_row = MATRIX_ROW (current_glyphs, vpos);
+ glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
+
+ /* If cursor row is not enabled, we don't really know where to
+ display the cursor. */
+ if (!glyph_row->enabled_p)
+ {
+ w->phys_cursor_on_p = 0;
+ return;
+ }
+
+ xassert (interrupt_input_blocked);
+
+ /* Set new_cursor_type to the cursor we want to be displayed. In a
+ mini-buffer window, we want the cursor only to appear if we are
+ reading input from this window. For the selected window, we want
+ the cursor type given by the frame parameter. If explicitly
+ marked off, draw no cursor. In all other cases, we want a hollow
+ box cursor. */
+ cursor_non_selected
+ = !NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows,
+ w->buffer));
+ new_cursor_width = -1;
+ if (cursor_in_echo_area
+ && FRAME_HAS_MINIBUF_P (f)
+ && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
+ {
+ if (w == XWINDOW (echo_area_window))
+ new_cursor_type = FRAME_DESIRED_CURSOR (f);
+ else
+ {
+ if (cursor_non_selected)
+ new_cursor_type = HOLLOW_BOX_CURSOR;
+ else
+ new_cursor_type = NO_CURSOR;
+ active_cursor = 0;
+ }
+ }
+ else
+ {
+ if (f != FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame
+ || w != XWINDOW (f->selected_window))
+ {
+ active_cursor = 0;
+
+ if (MINI_WINDOW_P (w)
+ || !cursor_non_selected
+ || NILP (XBUFFER (w->buffer)->cursor_type))
+ new_cursor_type = NO_CURSOR;
+ else
+ new_cursor_type = HOLLOW_BOX_CURSOR;
+ }
+ else
+ {
+ struct buffer *b = XBUFFER (w->buffer);
+
+ if (EQ (b->cursor_type, Qt))
+ new_cursor_type = FRAME_DESIRED_CURSOR (f);
+ else
+ new_cursor_type = x_specified_cursor_type (b->cursor_type,
+ &new_cursor_width);
+ if (w->cursor_off_p)
+ {
+ if (new_cursor_type == FILLED_BOX_CURSOR)
+ new_cursor_type = HOLLOW_BOX_CURSOR;
+ else if (new_cursor_type == BAR_CURSOR && new_cursor_width > 1)
+ new_cursor_width = 1;
+ else
+ new_cursor_type = NO_CURSOR;
+ }
+ }
+ }
+
+ /* If cursor is currently being shown and we don't want it to be or
+ it is in the wrong place, or the cursor type is not what we want,
+ erase it. */
+ if (w->phys_cursor_on_p
+ && (!on
+ || w->phys_cursor.x != x
+ || w->phys_cursor.y != y
+ || new_cursor_type != w->phys_cursor_type
+ || (new_cursor_type == BAR_CURSOR
+ && new_cursor_width != w->phys_cursor_width)))
+ x_erase_phys_cursor (w);
+
+ /* If the cursor is now invisible and we want it to be visible,
+ display it. */
+ if (on && !w->phys_cursor_on_p)
+ {
+ w->phys_cursor_ascent = glyph_row->ascent;
+ w->phys_cursor_height = glyph_row->height;
+
+ /* Set phys_cursor_.* before x_draw_.* is called because some
+ of them may need the information. */
+ w->phys_cursor.x = x;
+ w->phys_cursor.y = glyph_row->y;
+ w->phys_cursor.hpos = hpos;
+ w->phys_cursor.vpos = vpos;
+ w->phys_cursor_type = new_cursor_type;
+ w->phys_cursor_width = new_cursor_width;
+ w->phys_cursor_on_p = 1;
+
+ switch (new_cursor_type)
+ {
+ case HOLLOW_BOX_CURSOR:
+ x_draw_hollow_cursor (w, glyph_row);
+ break;
+
+ case FILLED_BOX_CURSOR:
+ x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
+ break;
+
+ case BAR_CURSOR:
+ x_draw_bar_cursor (w, glyph_row, new_cursor_width);
+ break;
+
+ case NO_CURSOR:
+ break;
+
+ default:
+ abort ();
+ }
+ }
+}
+
+
+/* Display the cursor on window W, or clear it. X and Y are window
+ relative pixel coordinates. HPOS and VPOS are glyph matrix
+ positions. If W is not the selected window, display a hollow
+ cursor. ON non-zero means display the cursor at X, Y which
+ correspond to HPOS, VPOS, otherwise it is cleared. */
+
+void
+x_display_cursor (w, on, hpos, vpos, x, y)
+ struct window *w;
+ int on, hpos, vpos, x, y;
+{
+ BLOCK_INPUT;
+ x_display_and_set_cursor (w, on, hpos, vpos, x, y);
+ UNBLOCK_INPUT;
+}
+
+
+/* Display the cursor on window W, or clear it, according to ON_P.
+ Don't change the cursor's position. */
+
+void
+x_update_cursor (f, on_p)
+ struct frame *f;
+ int on_p;
+{
+ x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
+}
+
+
+/* Call x_update_window_cursor with parameter ON_P on all leaf windows
+ in the window tree rooted at W. */
+
+static void
+x_update_cursor_in_window_tree (w, on_p)
+ struct window *w;
+ int on_p;
+{
+ while (w)
+ {
+ if (!NILP (w->hchild))
+ x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
+ else if (!NILP (w->vchild))
+ x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
+ else
+ x_update_window_cursor (w, on_p);
+
+ w = NILP (w->next) ? 0 : XWINDOW (w->next);
+ }
+}
+
+
+/* Switch the display of W's cursor on or off, according to the value
+ of ON. */
+
+static void
+x_update_window_cursor (w, on)
+ struct window *w;
+ int on;
+{
+ /* Don't update cursor in windows whose frame is in the process
+ of being deleted. */
+ if (w->current_matrix)
+ {
+ BLOCK_INPUT;
+ x_display_and_set_cursor (w, on, w->phys_cursor.hpos,
+ w->phys_cursor.vpos, w->phys_cursor.x,
+ w->phys_cursor.y);
+ UNBLOCK_INPUT;
+ }
+}
+
+
+
+\f
+/* Icons. */
+
+#if 0 /* MAC_TODO: no icon support yet. */
+int
+x_bitmap_icon (f, icon)
+ struct frame *f;
+ Lisp_Object icon;
+{
+ HANDLE hicon;
+
+ if (FRAME_W32_WINDOW (f) == 0)
+ return 1;
+
+ if (NILP (icon))
+ hicon = LoadIcon (hinst, EMACS_CLASS);
+ else if (STRINGP (icon))
+ hicon = LoadImage (NULL, (LPCTSTR) XSTRING (icon)->data, IMAGE_ICON, 0, 0,
+ LR_DEFAULTSIZE | LR_LOADFROMFILE);
+ else if (SYMBOLP (icon))
+ {
+ LPCTSTR name;
+
+ if (EQ (icon, intern ("application")))
+ name = (LPCTSTR) IDI_APPLICATION;
+ else if (EQ (icon, intern ("hand")))
+ name = (LPCTSTR) IDI_HAND;
+ else if (EQ (icon, intern ("question")))
+ name = (LPCTSTR) IDI_QUESTION;
+ else if (EQ (icon, intern ("exclamation")))
+ name = (LPCTSTR) IDI_EXCLAMATION;
+ else if (EQ (icon, intern ("asterisk")))
+ name = (LPCTSTR) IDI_ASTERISK;
+ else if (EQ (icon, intern ("winlogo")))
+ name = (LPCTSTR) IDI_WINLOGO;
+ else
+ return 1;
+
+ hicon = LoadIcon (NULL, name);
+ }
+ else
+ return 1;
+
+ if (hicon == NULL)
+ return 1;
+
+ PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
+ (LPARAM) hicon);
+
+ return 0;
+}
+#endif /* MAC_TODO */
+\f
+/************************************************************************
+ Handling X errors
+ ************************************************************************/
+
+/* Display Error Handling functions not used on W32. Listing them here
+ helps diff stay in step when comparing w32term.c with xterm.c.
+
+x_error_catcher (display, error)
+x_catch_errors (dpy)
+x_catch_errors_unwind (old_val)
+x_check_errors (dpy, format)
+x_had_errors_p (dpy)
+x_clear_errors (dpy)
+x_uncatch_errors (dpy, count)
+x_trace_wire ()
+x_connection_signal (signalnum)
+x_connection_closed (dpy, error_message)
+x_error_quitter (display, error)
+x_error_handler (display, error)
+x_io_error_quitter (display)
+
+ */
+
+\f
+/* Changing the font of the frame. */
+
+/* Give frame F the font named FONTNAME as its default font, and
+ return the full name of that font. FONTNAME may be a wildcard
+ pattern; in that case, we choose some font that fits the pattern.
+ The return value shows which font we chose. */
+
+Lisp_Object
+x_new_font (f, fontname)
+ struct frame *f;
+ register char *fontname;
+{
+ struct font_info *fontp
+ = FS_LOAD_FONT (f, 0, fontname, -1);
+
+ if (!fontp)
+ return Qnil;
+
+ FRAME_FONT (f) = (XFontStruct *) (fontp->font);
+ FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
+ FRAME_FONTSET (f) = -1;
+
+ /* Compute the scroll bar width in character columns. */
+ if (f->scroll_bar_pixel_width > 0)
+ {
+ int wid = FONT_WIDTH (FRAME_FONT (f));
+ f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
+ }
+ else
+ {
+ int wid = FONT_WIDTH (FRAME_FONT (f));
+ f->scroll_bar_cols = (14 + wid - 1) / wid;
+ }
+
+ /* Now make the frame display the given font. */
+ if (FRAME_MAC_WINDOW (f) != 0)
+ {
+ frame_update_line_height (f);
+ if (NILP (tip_frame) || XFRAME (tip_frame) != f)
+ x_set_window_size (f, 0, f->width, f->height);
+ }
+ else
+ /* If we are setting a new frame's font for the first time,
+ there are no faces yet, so this font's height is the line height. */
+ f->output_data.mac->line_height = FONT_HEIGHT (FRAME_FONT (f));
+
+ return build_string (fontp->full_name);
+}
+\f
+/* Give frame F the fontset named FONTSETNAME as its default font, and
+ return the full name of that fontset. FONTSETNAME may be a wildcard
+ pattern; in that case, we choose some fontset that fits the pattern.
+ The return value shows which fontset we chose. */
+
+Lisp_Object
+x_new_fontset (f, fontsetname)
+ struct frame *f;
+ char *fontsetname;
+{
+ int fontset = fs_query_fontset (build_string (fontsetname), 0);
+ Lisp_Object result;
+
+ if (fontset < 0)
+ return Qnil;
+
+ if (FRAME_FONTSET (f) == fontset)
+ /* This fontset is already set in frame F. There's nothing more
+ to do. */
+ return fontset_name (fontset);
+
+ result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
+
+ if (!STRINGP (result))
+ /* Can't load ASCII font. */
+ return Qnil;
+
+ /* Since x_new_font doesn't update any fontset information, do it now. */
+ FRAME_FONTSET(f) = fontset;
+
+ return build_string (fontsetname);
+}
+
+/* Compute actual fringe widths */
+
+void
+x_compute_fringe_widths (f, redraw)
+ struct frame *f;
+ int redraw;
+{
+ int o_left = f->output_data.mac->left_fringe_width;
+ int o_right = f->output_data.mac->right_fringe_width;
+ int o_cols = f->output_data.mac->fringe_cols;
+
+ Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
+ Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
+ int left_fringe_width, right_fringe_width;
+
+ if (!NILP (left_fringe))
+ left_fringe = Fcdr (left_fringe);
+ if (!NILP (right_fringe))
+ right_fringe = Fcdr (right_fringe);
+
+ left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
+ XINT (left_fringe));
+ right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
+ XINT (right_fringe));
+
+ if (left_fringe_width || right_fringe_width)
+ {
+ int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
+ int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
+ int conf_wid = left_wid + right_wid;
+ int font_wid = FONT_WIDTH (f->output_data.mac->font);
+ int cols = (left_wid + right_wid + font_wid-1) / font_wid;
+ int real_wid = cols * font_wid;
+ if (left_wid && right_wid)
+ {
+ if (left_fringe_width < 0)
+ {
+ /* Left fringe width is fixed, adjust right fringe if necessary */
+ f->output_data.mac->left_fringe_width = left_wid;
+ f->output_data.mac->right_fringe_width = real_wid - left_wid;
+ }
+ else if (right_fringe_width < 0)
+ {
+ /* Right fringe width is fixed, adjust left fringe if necessary */
+ f->output_data.mac->left_fringe_width = real_wid - right_wid;
+ f->output_data.mac->right_fringe_width = right_wid;
+ }
+ else
+ {
+ /* Adjust both fringes with an equal amount.
+ Note that we are doing integer arithmetic here, so don't
+ lose a pixel if the total width is an odd number. */
+ int fill = real_wid - conf_wid;
+ f->output_data.mac->left_fringe_width = left_wid + fill/2;
+ f->output_data.mac->right_fringe_width = right_wid + fill - fill/2;
+ }
+ }
+ else if (left_fringe_width)
+ {
+ f->output_data.mac->left_fringe_width = real_wid;
+ f->output_data.mac->right_fringe_width = 0;
+ }
+ else
+ {
+ f->output_data.mac->left_fringe_width = 0;
+ f->output_data.mac->right_fringe_width = real_wid;
+ }
+ f->output_data.mac->fringe_cols = cols;
+ f->output_data.mac->fringes_extra = real_wid;
+ }
+ else
+ {
+ f->output_data.mac->left_fringe_width = 0;
+ f->output_data.mac->right_fringe_width = 0;
+ f->output_data.mac->fringe_cols = 0;
+ f->output_data.mac->fringes_extra = 0;
+ }
+
+ if (redraw && FRAME_VISIBLE_P (f))
+ if (o_left != f->output_data.mac->left_fringe_width ||
+ o_right != f->output_data.mac->right_fringe_width ||
+ o_cols != f->output_data.mac->fringe_cols)
+ redraw_frame (f);
+}
+\f
+/***********************************************************************
+ TODO: W32 Input Methods
+ ***********************************************************************/
+/* Listing missing functions from xterm.c helps diff stay in step.
+
+xim_destroy_callback (xim, client_data, call_data)
+xim_open_dpy (dpyinfo, resource_name)
+struct xim_inst_t
+xim_instantiate_callback (display, client_data, call_data)
+xim_initialize (dpyinfo, resource_name)
+xim_close_dpy (dpyinfo)
+
+ */
+
+\f
+/* Calculate the absolute position in frame F
+ from its current recorded position values and gravity. */
+
+void
+x_calc_absolute_position (f)
+ struct frame *f;
+{
+ Point pt;
+ int flags = f->output_data.mac->size_hint_flags;
+
+ pt.h = pt.v = 0;
+
+ /* Find the position of the outside upper-left corner of
+ the inner window, with respect to the outer window. */
+ if (f->output_data.mac->parent_desc != FRAME_MAC_DISPLAY_INFO (f)->root_window)
+ {
+ GrafPtr savePort;
+ GetPort (&savePort);
+
+#if TARGET_API_MAC_CARBON
+ SetPort (GetWindowPort (FRAME_MAC_WINDOW (f)));
+#else
+ SetPort (FRAME_MAC_WINDOW (f));
+#endif
+
+#if TARGET_API_MAC_CARBON
+ {
+ Rect r;
+
+ GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
+ SetPt(&pt, r.left, r.top);
+ }
+#else /* not TARGET_API_MAC_CARBON */
+ SetPt(&pt, FRAME_MAC_WINDOW (f)->portRect.left, FRAME_MAC_WINDOW (f)->portRect.top);
+#endif /* not TARGET_API_MAC_CARBON */
+ LocalToGlobal (&pt);
+ SetPort (savePort);
+ }
+
+ /* Treat negative positions as relative to the leftmost bottommost
+ position that fits on the screen. */
+ if (flags & XNegative)
+ f->output_data.mac->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
+ - 2 * f->output_data.mac->border_width - pt.h
+ - PIXEL_WIDTH (f)
+ + f->output_data.mac->left_pos);
+ /* NTEMACS_TODO: Subtract menubar height? */
+ if (flags & YNegative)
+ f->output_data.mac->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
+ - 2 * f->output_data.mac->border_width - pt.v
+ - PIXEL_HEIGHT (f)
+ + f->output_data.mac->top_pos);
+ /* The left_pos and top_pos
+ are now relative to the top and left screen edges,
+ so the flags should correspond. */
+ f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
+}
+
+/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
+ to really change the position, and 0 when calling from
+ x_make_frame_visible (in that case, XOFF and YOFF are the current
+ position values). It is -1 when calling from x_set_frame_parameters,
+ which means, do adjust for borders but don't change the gravity. */
+
+void
+x_set_offset (f, xoff, yoff, change_gravity)
+ struct frame *f;
+ register int xoff, yoff;
+ int change_gravity;
+{
+ int modified_top, modified_left;
+
+ if (change_gravity > 0)
+ {
+ f->output_data.mac->top_pos = yoff;
+ f->output_data.mac->left_pos = xoff;
+ f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
+ if (xoff < 0)
+ f->output_data.mac->size_hint_flags |= XNegative;
+ if (yoff < 0)
+ f->output_data.mac->size_hint_flags |= YNegative;
+ f->output_data.mac->win_gravity = NorthWestGravity;
+ }
+ x_calc_absolute_position (f);
+
+ BLOCK_INPUT;
+ x_wm_set_size_hint (f, (long) 0, 0);
+
+ modified_left = f->output_data.mac->left_pos;
+ modified_top = f->output_data.mac->top_pos;
+
+ MoveWindow (f->output_data.mac->mWP, modified_left + 6,
+ modified_top + 42, false);
+
+ UNBLOCK_INPUT;
+}
+
+/* Call this to change the size of frame F's x-window.
+ If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
+ for this size change and subsequent size changes.
+ Otherwise we leave the window gravity unchanged. */
+
+void
+x_set_window_size (f, change_gravity, cols, rows)
+ struct frame *f;
+ int change_gravity;
+ int cols, rows;
+{
+ int pixelwidth, pixelheight;
+
+ BLOCK_INPUT;
+
+ check_frame_size (f, &rows, &cols);
+ f->output_data.mac->vertical_scroll_bar_extra
+ = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
+ ? 0
+ : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.mac->font)));
+
+ x_compute_fringe_widths (f, 0);
+
+ pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
+ pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
+
+ f->output_data.mac->win_gravity = NorthWestGravity;
+ x_wm_set_size_hint (f, (long) 0, 0);
+
+ SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
+
+ /* Now, strictly speaking, we can't be sure that this is accurate,
+ but the window manager will get around to dealing with the size
+ change request eventually, and we'll hear how it went when the
+ ConfigureNotify event gets here.
+
+ We could just not bother storing any of this information here,
+ and let the ConfigureNotify event set everything up, but that
+ might be kind of confusing to the Lisp code, since size changes
+ wouldn't be reported in the frame parameters until some random
+ point in the future when the ConfigureNotify event arrives.
+
+ We pass 1 for DELAY since we can't run Lisp code inside of
+ a BLOCK_INPUT. */
+ change_frame_size (f, rows, cols, 0, 1, 0);
+ PIXEL_WIDTH (f) = pixelwidth;
+ PIXEL_HEIGHT (f) = pixelheight;
+
+ /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
+ receive in the ConfigureNotify event; if we get what we asked
+ for, then the event won't cause the screen to become garbaged, so
+ we have to make sure to do it here. */
+ SET_FRAME_GARBAGED (f);
+
+ XFlush (FRAME_X_DISPLAY (f));
+
+ /* If cursor was outside the new size, mark it as off. */
+ mark_window_cursors_off (XWINDOW (f->root_window));
+
+ /* Clear out any recollection of where the mouse highlighting was,
+ since it might be in a place that's outside the new frame size.
+ Actually checking whether it is outside is a pain in the neck,
+ so don't try--just let the highlighting be done afresh with new size. */
+ cancel_mouse_face (f);
+
+ UNBLOCK_INPUT;
+}
+\f
+/* Mouse warping. */
+
+void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
+
+void
+x_set_mouse_position (f, x, y)
+ struct frame *f;
+ int x, y;
+{
+ int pix_x, pix_y;
+
+ pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.mac->font) / 2;
+ pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.mac->line_height / 2;
+
+ if (pix_x < 0) pix_x = 0;
+ if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
+
+ if (pix_y < 0) pix_y = 0;
+ if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
+
+ x_set_mouse_pixel_position (f, pix_x, pix_y);
+}
+
+void
+x_set_mouse_pixel_position (f, pix_x, pix_y)
+ struct frame *f;
+ int pix_x, pix_y;
+{
+#if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
+ BLOCK_INPUT;
+
+ XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
+ 0, 0, 0, 0, pix_x, pix_y);
+ UNBLOCK_INPUT;
+#endif
+}
+
+\f
+/* focus shifting, raising and lowering. */
+
+void
+x_focus_on_frame (f)
+ struct frame *f;
+{
+#if 0 /* This proves to be unpleasant. */
+ x_raise_frame (f);
+#endif
+#if 0
+ /* I don't think that the ICCCM allows programs to do things like this
+ without the interaction of the window manager. Whatever you end up
+ doing with this code, do it to x_unfocus_frame too. */
+ XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ RevertToPointerRoot, CurrentTime);
+#endif /* ! 0 */
+}
+
+void
+x_unfocus_frame (f)
+ struct frame *f;
+{
+}
+
+/* Raise frame F. */
+void
+x_raise_frame (f)
+ struct frame *f;
+{
+ if (f->async_visible)
+ SelectWindow (FRAME_MAC_WINDOW (f));
+}
+
+/* Lower frame F. */
+void
+x_lower_frame (f)
+ struct frame *f;
+{
+ if (f->async_visible)
+ SendBehind (FRAME_MAC_WINDOW (f), nil);
+}
+
+static void
+XTframe_raise_lower (f, raise_flag)
+ FRAME_PTR f;
+ int raise_flag;
+{
+ if (raise_flag)
+ x_raise_frame (f);
+ else
+ x_lower_frame (f);
+}
+\f
+/* Change of visibility. */
+
+/* This tries to wait until the frame is really visible.
+ However, if the window manager asks the user where to position
+ the frame, this will return before the user finishes doing that.
+ The frame will not actually be visible at that time,
+ but it will become visible later when the window manager
+ finishes with it. */
+
+void
+x_make_frame_visible (f)
+ struct frame *f;
+{
+ Lisp_Object type;
+ int original_top, original_left;
+
+ BLOCK_INPUT;
+
+ if (! FRAME_VISIBLE_P (f))
+ {
+ /* We test FRAME_GARBAGED_P here to make sure we don't
+ call x_set_offset a second time
+ if we get to x_make_frame_visible a second time
+ before the window gets really visible. */
+ if (! FRAME_ICONIFIED_P (f)
+ && ! f->output_data.mac->asked_for_visible)
+ x_set_offset (f, f->output_data.mac->left_pos,
+ f->output_data.mac->top_pos, 0);
+
+ f->output_data.mac->asked_for_visible = 1;
+
+ ShowWindow (FRAME_MAC_WINDOW (f));
+ }
+
+ XFlush (FRAME_MAC_DISPLAY (f));
+
+#if 0 /* MAC_TODO */
+ /* Synchronize to ensure Emacs knows the frame is visible
+ before we do anything else. We do this loop with input not blocked
+ so that incoming events are handled. */
+ {
+ Lisp_Object frame;
+ int count;
+
+ /* This must come after we set COUNT. */
+ UNBLOCK_INPUT;
+
+ XSETFRAME (frame, f);
+
+ /* Wait until the frame is visible. Process X events until a
+ MapNotify event has been seen, or until we think we won't get a
+ MapNotify at all.. */
+ for (count = input_signal_count + 10;
+ input_signal_count < count && !FRAME_VISIBLE_P (f);)
+ {
+ /* Force processing of queued events. */
+ x_sync (f);
+
+ /* Machines that do polling rather than SIGIO have been
+ observed to go into a busy-wait here. So we'll fake an
+ alarm signal to let the handler know that there's something
+ to be read. We used to raise a real alarm, but it seems
+ that the handler isn't always enabled here. This is
+ probably a bug. */
+ if (input_polling_used ())
+ {
+ /* It could be confusing if a real alarm arrives while
+ processing the fake one. Turn it off and let the
+ handler reset it. */
+ extern void poll_for_input_1 P_ ((void));
+ int old_poll_suppress_count = poll_suppress_count;
+ poll_suppress_count = 1;
+ poll_for_input_1 ();
+ poll_suppress_count = old_poll_suppress_count;
+ }
+
+ /* See if a MapNotify event has been processed. */
+ FRAME_SAMPLE_VISIBILITY (f);
+ }
+ }
+#endif /* MAC_TODO */
+}
+
+/* Change from mapped state to withdrawn state. */
+
+/* Make the frame visible (mapped and not iconified). */
+
+void
+x_make_frame_invisible (f)
+ struct frame *f;
+{
+ /* Don't keep the highlight on an invisible frame. */
+ if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
+ FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
+
+ BLOCK_INPUT;
+
+ HideWindow (FRAME_MAC_WINDOW (f));
+
+ /* We can't distinguish this from iconification
+ just by the event that we get from the server.
+ So we can't win using the usual strategy of letting
+ FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
+ and synchronize with the server to make sure we agree. */
+ f->visible = 0;
+ FRAME_ICONIFIED_P (f) = 0;
+ f->async_visible = 0;
+ f->async_iconified = 0;
+
+ UNBLOCK_INPUT;
+}
+
+/* Change window state from mapped to iconified. */
+
+void
+x_iconify_frame (f)
+ struct frame *f;
+{
+#if 0 /* MAC_TODO: really no iconify on Mac */
+ int result;
+ Lisp_Object type;
+
+ /* Don't keep the highlight on an invisible frame. */
+ if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
+ FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
+
+ if (f->async_iconified)
+ return;
+
+ BLOCK_INPUT;
+
+ FRAME_SAMPLE_VISIBILITY (f);
+
+ type = x_icon_type (f);
+ if (!NILP (type))
+ x_bitmap_icon (f, type);
+
+#ifdef USE_X_TOOLKIT
+
+ if (! FRAME_VISIBLE_P (f))
+ {
+ if (! EQ (Vx_no_window_manager, Qt))
+ x_wm_set_window_state (f, IconicState);
+ /* This was XtPopup, but that did nothing for an iconified frame. */
+ XtMapWidget (f->output_data.x->widget);
+ /* The server won't give us any event to indicate
+ that an invisible frame was changed to an icon,
+ so we have to record it here. */
+ f->iconified = 1;
+ f->visible = 1;
+ f->async_iconified = 1;
+ f->async_visible = 0;
+ UNBLOCK_INPUT;
+ return;
+ }
+
+ result = XIconifyWindow (FRAME_X_DISPLAY (f),
+ XtWindow (f->output_data.x->widget),
+ DefaultScreen (FRAME_X_DISPLAY (f)));
+ UNBLOCK_INPUT;
+
+ if (!result)
+ error ("Can't notify window manager of iconification");
+
+ f->async_iconified = 1;
+ f->async_visible = 0;
+
+
+ BLOCK_INPUT;
+ XFlush (FRAME_X_DISPLAY (f));
+ UNBLOCK_INPUT;
+#else /* not USE_X_TOOLKIT */
+
+ /* Make sure the X server knows where the window should be positioned,
+ in case the user deiconifies with the window manager. */
+ if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
+ x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
+
+ /* Since we don't know which revision of X we're running, we'll use both
+ the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
+
+ /* X11R4: send a ClientMessage to the window manager using the
+ WM_CHANGE_STATE type. */
+ {
+ XEvent message;
+
+ message.xclient.window = FRAME_X_WINDOW (f);
+ message.xclient.type = ClientMessage;
+ message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
+ message.xclient.format = 32;
+ message.xclient.data.l[0] = IconicState;
+
+ if (! XSendEvent (FRAME_X_DISPLAY (f),
+ DefaultRootWindow (FRAME_X_DISPLAY (f)),
+ False,
+ SubstructureRedirectMask | SubstructureNotifyMask,
+ &message))
+ {
+ UNBLOCK_INPUT_RESIGNAL;
+ error ("Can't notify window manager of iconification");
+ }
+ }
+
+ /* X11R3: set the initial_state field of the window manager hints to
+ IconicState. */
+ x_wm_set_window_state (f, IconicState);
+
+ if (!FRAME_VISIBLE_P (f))
+ {
+ /* If the frame was withdrawn, before, we must map it. */
+ XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
+ }
+
+ f->async_iconified = 1;
+ f->async_visible = 0;
+
+ XFlush (FRAME_X_DISPLAY (f));
+ UNBLOCK_INPUT;
+#endif /* not USE_X_TOOLKIT */
+#endif /* MAC_TODO */
+}
+
+\f
+/* Destroy the X window of frame F. */
+
+void
+x_destroy_window (f)
+ struct frame *f;
+{
+ struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+
+ BLOCK_INPUT;
+
+ DisposeWindow (FRAME_MAC_WINDOW (f));
+
+ free_frame_menubar (f);
+ free_frame_faces (f);
+
+ xfree (f->output_data.mac);
+ f->output_data.mac = 0;
+ if (f == dpyinfo->x_focus_frame)
+ dpyinfo->x_focus_frame = 0;
+ if (f == dpyinfo->x_focus_event_frame)
+ dpyinfo->x_focus_event_frame = 0;
+ if (f == dpyinfo->x_highlight_frame)
+ dpyinfo->x_highlight_frame = 0;
+
+ dpyinfo->reference_count--;
+
+ if (f == dpyinfo->mouse_face_mouse_frame)
+ {
+ dpyinfo->mouse_face_beg_row
+ = dpyinfo->mouse_face_beg_col = -1;
+ dpyinfo->mouse_face_end_row
+ = dpyinfo->mouse_face_end_col = -1;
+ dpyinfo->mouse_face_window = Qnil;
+ dpyinfo->mouse_face_deferred_gc = 0;
+ dpyinfo->mouse_face_mouse_frame = 0;
+ }
+
+ UNBLOCK_INPUT;
+}
+\f
+/* Setting window manager hints. */
+
+/* Set the normal size hints for the window manager, for frame F.
+ FLAGS is the flags word to use--or 0 meaning preserve the flags
+ that the window now has.
+ If USER_POSITION is nonzero, we set the USPosition
+ flag (this is useful when FLAGS is 0). */
+void
+x_wm_set_size_hint (f, flags, user_position)
+ struct frame *f;
+ long flags;
+ int user_position;
+{
+#if 0 /* MAC_TODO: connect this to the Appearance Manager */
+ XSizeHints size_hints;
+
+#ifdef USE_X_TOOLKIT
+ Arg al[2];
+ int ac = 0;
+ Dimension widget_width, widget_height;
+ Window window = XtWindow (f->output_data.x->widget);
+#else /* not USE_X_TOOLKIT */
+ Window window = FRAME_X_WINDOW (f);
+#endif /* not USE_X_TOOLKIT */
+
+ /* Setting PMaxSize caused various problems. */
+ size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
+
+ size_hints.x = f->output_data.x->left_pos;
+ size_hints.y = f->output_data.x->top_pos;
+
+#ifdef USE_X_TOOLKIT
+ XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
+ XtSetArg (al[ac], XtNheight, &widget_height); ac++;
+ XtGetValues (f->output_data.x->widget, al, ac);
+ size_hints.height = widget_height;
+ size_hints.width = widget_width;
+#else /* not USE_X_TOOLKIT */
+ size_hints.height = PIXEL_HEIGHT (f);
+ size_hints.width = PIXEL_WIDTH (f);
+#endif /* not USE_X_TOOLKIT */
+
+ size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
+ size_hints.height_inc = f->output_data.x->line_height;
+ size_hints.max_width
+ = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
+ size_hints.max_height
+ = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
+
+ /* Calculate the base and minimum sizes.
+
+ (When we use the X toolkit, we don't do it here.
+ Instead we copy the values that the widgets are using, below.) */
+#ifndef USE_X_TOOLKIT
+ {
+ int base_width, base_height;
+ int min_rows = 0, min_cols = 0;
+
+ base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
+ base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
+
+ check_frame_size (f, &min_rows, &min_cols);
+
+ /* The window manager uses the base width hints to calculate the
+ current number of rows and columns in the frame while
+ resizing; min_width and min_height aren't useful for this
+ purpose, since they might not give the dimensions for a
+ zero-row, zero-column frame.
+
+ We use the base_width and base_height members if we have
+ them; otherwise, we set the min_width and min_height members
+ to the size for a zero x zero frame. */
+
+#ifdef HAVE_X11R4
+ size_hints.flags |= PBaseSize;
+ size_hints.base_width = base_width;
+ size_hints.base_height = base_height;
+ size_hints.min_width = base_width + min_cols * size_hints.width_inc;
+ size_hints.min_height = base_height + min_rows * size_hints.height_inc;
+#else
+ size_hints.min_width = base_width;
+ size_hints.min_height = base_height;
+#endif
+ }
+
+ /* If we don't need the old flags, we don't need the old hint at all. */
+ if (flags)
+ {
+ size_hints.flags |= flags;
+ goto no_read;
+ }
+#endif /* not USE_X_TOOLKIT */
+
+ {
+ XSizeHints hints; /* Sometimes I hate X Windows... */
+ long supplied_return;
+ int value;
+
+#ifdef HAVE_X11R4
+ value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
+ &supplied_return);
+#else
+ value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
+#endif
+
+#ifdef USE_X_TOOLKIT
+ size_hints.base_height = hints.base_height;
+ size_hints.base_width = hints.base_width;
+ size_hints.min_height = hints.min_height;
+ size_hints.min_width = hints.min_width;
+#endif
+
+ if (flags)
+ size_hints.flags |= flags;
+ else
+ {
+ if (value == 0)
+ hints.flags = 0;
+ if (hints.flags & PSize)
+ size_hints.flags |= PSize;
+ if (hints.flags & PPosition)
+ size_hints.flags |= PPosition;
+ if (hints.flags & USPosition)
+ size_hints.flags |= USPosition;
+ if (hints.flags & USSize)
+ size_hints.flags |= USSize;
+ }
+ }
+
+#ifndef USE_X_TOOLKIT
+ no_read:
+#endif
+
+#ifdef PWinGravity
+ size_hints.win_gravity = f->output_data.x->win_gravity;
+ size_hints.flags |= PWinGravity;
+
+ if (user_position)
+ {
+ size_hints.flags &= ~ PPosition;
+ size_hints.flags |= USPosition;
+ }
+#endif /* PWinGravity */
+
+#ifdef HAVE_X11R4
+ XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
+#else
+ XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
+#endif
+#endif /* MAC_TODO */
+}
+
+#if 0 /* MAC_TODO: hide application instead of iconify? */
+/* Used for IconicState or NormalState */
+
+void
+x_wm_set_window_state (f, state)
+ struct frame *f;
+ int state;
+{
+#ifdef USE_X_TOOLKIT
+ Arg al[1];
+
+ XtSetArg (al[0], XtNinitialState, state);
+ XtSetValues (f->output_data.x->widget, al, 1);
+#else /* not USE_X_TOOLKIT */
+ Window window = FRAME_X_WINDOW (f);
+
+ f->output_data.x->wm_hints.flags |= StateHint;
+ f->output_data.x->wm_hints.initial_state = state;
+
+ XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
+#endif /* not USE_X_TOOLKIT */
+}
+
+void
+x_wm_set_icon_pixmap (f, pixmap_id)
+ struct frame *f;
+ int pixmap_id;
+{
+ Pixmap icon_pixmap;
+
+#ifndef USE_X_TOOLKIT
+ Window window = FRAME_X_WINDOW (f);
+#endif
+
+ if (pixmap_id > 0)
+ {
+ icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
+ f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
+ }
+ else
+ {
+ /* It seems there is no way to turn off use of an icon pixmap.
+ The following line does it, only if no icon has yet been created,
+ for some window managers. But with mwm it crashes.
+ Some people say it should clear the IconPixmapHint bit in this case,
+ but that doesn't work, and the X consortium said it isn't the
+ right thing at all. Since there is no way to win,
+ best to explicitly give up. */
+#if 0
+ f->output_data.x->wm_hints.icon_pixmap = None;
+#else
+ return;
+#endif
+ }
+
+#ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
+
+ {
+ Arg al[1];
+ XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
+ XtSetValues (f->output_data.x->widget, al, 1);
+ }
+
+#else /* not USE_X_TOOLKIT */
+
+ f->output_data.x->wm_hints.flags |= IconPixmapHint;
+ XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
+
+#endif /* not USE_X_TOOLKIT */
+}
+
+#endif /* MAC_TODO */
+
+void
+x_wm_set_icon_position (f, icon_x, icon_y)
+ struct frame *f;
+ int icon_x, icon_y;
+{
+#if 0 /* MAC_TODO: no icons on Mac */
+#ifdef USE_X_TOOLKIT
+ Window window = XtWindow (f->output_data.x->widget);
+#else
+ Window window = FRAME_X_WINDOW (f);
+#endif
+
+ f->output_data.x->wm_hints.flags |= IconPositionHint;
+ f->output_data.x->wm_hints.icon_x = icon_x;
+ f->output_data.x->wm_hints.icon_y = icon_y;
+
+ XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
+#endif /* MAC_TODO */
+}
+
+\f
+/***********************************************************************
+ Fonts
+ ***********************************************************************/
+
+/* Return a pointer to struct font_info of font FONT_IDX of frame F. */
+
+struct font_info *
+x_get_font_info (f, font_idx)
+ FRAME_PTR f;
+ int font_idx;
+{
+ return (FRAME_MAC_FONT_TABLE (f) + font_idx);
+}
+
+/* the global font name table */
+char **font_name_table = NULL;
+int font_name_table_size = 0;
+int font_name_count = 0;
+
+/* compare two strings ignoring case */
+static int
+stricmp (const char *s, const char *t)
+{
+ for ( ; tolower (*s) == tolower (*t); s++, t++)
+ if (*s == '\0')
+ return 0;
+ return tolower (*s) - tolower (*t);
+}
+
+/* compare two strings ignoring case and handling wildcard */
+static int
+wildstrieq (char *s1, char *s2)
+{
+ if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
+ return true;
+
+ return stricmp (s1, s2) == 0;
+}
+
+/* Assume parameter 1 is fully qualified, no wildcards. */
+static int
+mac_font_pattern_match (fontname, pattern)
+ char * fontname;
+ char * pattern;
+{
+ char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
+ char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
+ char *ptr;
+
+ /* Copy fontname so we can modify it during comparison. */
+ strcpy (font_name_copy, fontname);
+
+ ptr = regex;
+ *ptr++ = '^';
+
+ /* Turn pattern into a regexp and do a regexp match. */
+ for (; *pattern; pattern++)
+ {
+ if (*pattern == '?')
+ *ptr++ = '.';
+ else if (*pattern == '*')
+ {
+ *ptr++ = '.';
+ *ptr++ = '*';
+ }
+ else
+ *ptr++ = *pattern;
+ }
+ *ptr = '$';
+ *(ptr + 1) = '\0';
+
+ return (fast_c_string_match_ignore_case (build_string (regex),
+ font_name_copy) >= 0);
+}
+
+/* Two font specs are considered to match if their foundry, family,
+ weight, slant, and charset match. */
+static int
+mac_font_match (char *mf, char *xf)
+{
+ char m_foundry[50], m_family[50], m_weight[20], m_slant[2], m_charset[20];
+ char x_foundry[50], x_family[50], x_weight[20], x_slant[2], x_charset[20];
+
+ if (sscanf (mf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
+ m_foundry, m_family, m_weight, m_slant, m_charset) != 5)
+ return mac_font_pattern_match (mf, xf);
+
+ if (sscanf (xf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
+ x_foundry, x_family, x_weight, x_slant, x_charset) != 5)
+ return mac_font_pattern_match (mf, xf);
+
+ return (wildstrieq (m_foundry, x_foundry)
+ && wildstrieq (m_family, x_family)
+ && wildstrieq (m_weight, x_weight)
+ && wildstrieq (m_slant, x_slant)
+ && wildstrieq (m_charset, x_charset))
+ || mac_font_pattern_match (mf, xf);
+}
+
+
+static char *
+mac_to_x_fontname (char *name, int size, Style style, short scriptcode)
+{
+ char foundry[32], family[32], cs[32];
+ char xf[255], *result, *p;
+
+ if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
+ {
+ strcpy(foundry, "Apple");
+ strcpy(family, name);
+
+ switch (scriptcode)
+ {
+ case smTradChinese:
+ strcpy(cs, "big5-0");
+ break;
+ case smSimpChinese:
+ strcpy(cs, "gb2312.1980-0");
+ break;
+ case smJapanese:
+ strcpy(cs, "jisx0208.1983-sjis");
+ break;
+ case -smJapanese:
+ /* Each Apple Japanese font is entered into the font table
+ twice: once as a jisx0208.1983-sjis font and once as a
+ jisx0201.1976-0 font. The latter can be used to display
+ the ascii charset and katakana-jisx0201 charset. A
+ negative script code signals that the name of this latter
+ font is being built. */
+ strcpy(cs, "jisx0201.1976-0");
+ break;
+ case smKorean:
+ strcpy(cs, "ksc5601.1989-0");
+ break;
+ default:
+ strcpy(cs, "mac-roman");
+ break;
+ }
+ }
+
+ sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
+ foundry, family, style & bold ? "bold" : "medium",
+ style & italic ? 'i' : 'r', size, size * 10, size * 10, cs);
+
+ result = (char *) xmalloc (strlen (xf) + 1);
+ strcpy (result, xf);
+ for (p = result; *p; p++)
+ *p = tolower(*p);
+ return result;
+}
+
+
+/* Convert an X font spec to the corresponding mac font name, which
+ can then be passed to GetFNum after conversion to a Pascal string.
+ For ordinary Mac fonts, this should just be their names, like
+ "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
+ collection contain their charset designation in their names, like
+ "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
+ names are handled accordingly. */
+static void
+x_font_name_to_mac_font_name (char *xf, char *mf)
+{
+ char foundry[32], family[32], weight[20], slant[2], cs[32];
+
+ strcpy (mf, "");
+
+ if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
+ foundry, family, weight, slant, cs) != 5 &&
+ sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
+ foundry, family, weight, slant, cs) != 5)
+ return;
+
+ if (strcmp (cs, "big5-0") == 0 || strcmp (cs, "gb2312.1980-0") == 0
+ || strcmp (cs, "jisx0208.1983-sjis") == 0
+ || strcmp (cs, "jisx0201.1976-0") == 0
+ || strcmp (cs, "ksc5601.1989-0") == 0 || strcmp (cs, "mac-roman") == 0)
+ strcpy(mf, family);
+ else
+ sprintf(mf, "%s-%s-%s", foundry, family, cs);
+}
+
+
+/* Sets up the table font_name_table to contain the list of all
+ monospace fonts in the system the first time the table is used so
+ that the Resource Manager need not be accessed every time this
+ information is needed. */
+
+static void
+init_font_name_table ()
+{
+#if TARGET_API_MAC_CARBON
+ SInt32 sv;
+
+ if (Gestalt (gestaltSystemVersion, &sv) == noErr && sv >= 0x1000)
+ {
+ FMFontFamilyIterator ffi;
+ FMFontFamilyInstanceIterator ffii;
+ FMFontFamily ff;
+
+ /* Create a dummy instance iterator here to avoid creating and
+ destroying it in the loop. */
+ if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
+ return;
+ /* Create an iterator to enumerate the font families. */
+ if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
+ != noErr)
+ {
+ FMDisposeFontFamilyInstanceIterator (&ffii);
+ return;
+ }
+
+ while (FMGetNextFontFamily (&ffi, &ff) == noErr)
+ {
+ Str255 name;
+ FMFont font;
+ FMFontStyle style;
+ FMFontSize size;
+ SInt16 sc;
+
+ if (FMGetFontFamilyName (ff, name) != noErr)
+ break;
+ p2cstr (name);
+
+ sc = FontToScript (ff);
+
+ /* Point the instance iterator at the current font family. */
+ if (FMResetFontFamilyInstanceIterator(ff, &ffii) != noErr)
+ break;
+
+ while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
+ == noErr)
+ {
+ if (font_name_table_size == 0)
+ {
+ font_name_table_size = 16;
+ font_name_table = (char **)
+ xmalloc (font_name_table_size * sizeof (char *));
+ }
+ else if (font_name_count + 1 >= font_name_table_size)
+ {
+ font_name_table_size += 16;
+ font_name_table = (char **)
+ xrealloc (font_name_table,
+ font_name_table_size * sizeof (char *));
+ }
+ font_name_table[font_name_count++]
+ = mac_to_x_fontname (name, size, style, sc);
+ }
+ }
+
+ /* Dispose of the iterators. */
+ FMDisposeFontFamilyIterator (&ffi);
+ FMDisposeFontFamilyInstanceIterator (&ffii);
+ }
+ else
+ {
+#endif /* TARGET_API_MAC_CARBON */
+ GrafPtr port;
+ SInt16 fontnum, old_fontnum;
+ int num_mac_fonts = CountResources('FOND');
+ int i, j;
+ Handle font_handle, font_handle_2;
+ short id, scriptcode;
+ ResType type;
+ Str32 name;
+ struct FontAssoc *fat;
+ struct AsscEntry *assc_entry;
+
+ GetPort (&port); /* save the current font number used */
+#if TARGET_API_MAC_CARBON
+ old_fontnum = GetPortTextFont (port);
+#else
+ old_fontnum = port->txFont;
+#endif
+
+ for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
+ {
+ font_handle = GetIndResource ('FOND', i);
+ if (!font_handle)
+ continue;
+
+ GetResInfo (font_handle, &id, &type, name);
+ GetFNum (name, &fontnum);
+ p2cstr (name);
+ if (fontnum == 0)
+ continue;
+
+ TextFont (fontnum);
+ scriptcode = FontToScript (fontnum);
+ do
+ {
+ HLock (font_handle);
+
+ if (GetResourceSizeOnDisk (font_handle)
+ >= sizeof (struct FamRec))
+ {
+ fat = (struct FontAssoc *) (*font_handle
+ + sizeof (struct FamRec));
+ assc_entry
+ = (struct AsscEntry *) (*font_handle
+ + sizeof (struct FamRec)
+ + sizeof (struct FontAssoc));
+
+ for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
+ {
+ if (font_name_table_size == 0)
+ {
+ font_name_table_size = 16;
+ font_name_table = (char **)
+ xmalloc (font_name_table_size * sizeof (char *));
+ }
+ else if (font_name_count >= font_name_table_size)
+ {
+ font_name_table_size += 16;
+ font_name_table = (char **)
+ xrealloc (font_name_table,
+ font_name_table_size * sizeof (char *));
+ }
+ font_name_table[font_name_count++]
+ = mac_to_x_fontname (name,
+ assc_entry->fontSize,
+ assc_entry->fontStyle,
+ scriptcode);
+ /* Both jisx0208.1983-sjis and
+ jisx0201.1976-sjis parts are contained in
+ Apple Japanese (SJIS) font. */
+ if (smJapanese == scriptcode)
+ {
+ font_name_table[font_name_count++]
+ = mac_to_x_fontname (name,
+ assc_entry->fontSize,
+ assc_entry->fontStyle,
+ smRoman);
+ }
+ }
+ }
+
+ HUnlock (font_handle);
+ font_handle_2 = GetNextFOND (font_handle);
+ ReleaseResource (font_handle);
+ font_handle = font_handle_2;
+ }
+ while (ResError () == noErr && font_handle);
+ }
+
+ TextFont (old_fontnum);
+#if TARGET_API_MAC_CARBON
+ }
+#endif /* TARGET_API_MAC_CARBON */
+}
+
+
+/* Return a list of at most MAXNAMES font specs matching the one in
+ PATTERN. Note that each '*' in the PATTERN matches exactly one
+ field of the font spec, unlike X in which an '*' in a font spec can
+ match a number of fields. The result is in the Mac implementation
+ all fonts must be specified by a font spec with all 13 fields
+ (although many of these can be "*'s"). */
+
+Lisp_Object
+x_list_fonts (struct frame *f,
+ Lisp_Object pattern,
+ int size,
+ int maxnames)
+{
+ char *ptnstr;
+ Lisp_Object newlist = Qnil;
+ int n_fonts = 0;
+ int i;
+ struct gcpro gcpro1, gcpro2;
+
+ if (font_name_table == NULL) /* Initialize when first used. */
+ init_font_name_table ();
+
+ ptnstr = XSTRING (pattern)->data;
+
+ GCPRO2 (pattern, newlist);
+
+ /* Scan and matching bitmap fonts. */
+ for (i = 0; i < font_name_count; i++)
+ {
+ if (mac_font_pattern_match (font_name_table[i], ptnstr))
+ {
+ newlist = Fcons (build_string (font_name_table[i]), newlist);
+
+ n_fonts++;
+ if (n_fonts >= maxnames)
+ break;
+ }
+ }
+
+ /* MAC_TODO: add code for matching outline fonts here */
+
+ UNGCPRO;
+
+ return newlist;
+}
+
+
+#if GLYPH_DEBUG
+
+/* Check that FONT is valid on frame F. It is if it can be found in F's
+ font table. */
+
+static void
+x_check_font (f, font)
+ struct frame *f;
+ XFontStruct *font;
+{
+ int i;
+ struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+
+ xassert (font != NULL);
+
+ for (i = 0; i < dpyinfo->n_fonts; i++)
+ if (dpyinfo->font_table[i].name
+ && font == dpyinfo->font_table[i].font)
+ break;
+
+ xassert (i < dpyinfo->n_fonts);
+}
+
+#endif /* GLYPH_DEBUG != 0 */
+
+/* Set *W to the minimum width, *H to the minimum font height of FONT.
+ Note: There are (broken) X fonts out there with invalid XFontStruct
+ min_bounds contents. For example, handa@etl.go.jp reports that
+ "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
+ have font->min_bounds.width == 0. */
+
+static INLINE void
+x_font_min_bounds (font, w, h)
+ MacFontStruct *font;
+ int *w, *h;
+{
+ /*
+ * TODO: Windows does not appear to offer min bound, only
+ * average and maximum width, and maximum height.
+ */
+ *h = FONT_HEIGHT (font);
+ *w = FONT_WIDTH (font);
+}
+
+
+/* Compute the smallest character width and smallest font height over
+ all fonts available on frame F. Set the members smallest_char_width
+ and smallest_font_height in F's x_display_info structure to
+ the values computed. Value is non-zero if smallest_font_height or
+ smallest_char_width become smaller than they were before. */
+
+int
+x_compute_min_glyph_bounds (f)
+ struct frame *f;
+{
+ int i;
+ struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+ MacFontStruct *font;
+ int old_width = dpyinfo->smallest_char_width;
+ int old_height = dpyinfo->smallest_font_height;
+
+ dpyinfo->smallest_font_height = 100000;
+ dpyinfo->smallest_char_width = 100000;
+
+ for (i = 0; i < dpyinfo->n_fonts; ++i)
+ if (dpyinfo->font_table[i].name)
+ {
+ struct font_info *fontp = dpyinfo->font_table + i;
+ int w, h;
+
+ font = (MacFontStruct *) fontp->font;
+ xassert (font != (MacFontStruct *) ~0);
+ x_font_min_bounds (font, &w, &h);
+
+ dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
+ dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
+ }
+
+ xassert (dpyinfo->smallest_char_width > 0
+ && dpyinfo->smallest_font_height > 0);
+
+ return (dpyinfo->n_fonts == 1
+ || dpyinfo->smallest_char_width < old_width
+ || dpyinfo->smallest_font_height < old_height);
+}
+
+
+/* Determine whether given string is a fully-specified XLFD: all 14
+ fields are present, none is '*'. */
+
+static int
+is_fully_specified_xlfd (char *p)
+{
+ int i;
+ char *q;
+
+ if (*p != '-')
+ return 0;
+
+ for (i = 0; i < 13; i++)
+ {
+ q = strchr (p + 1, '-');
+ if (q == NULL)
+ return 0;
+ if (q - p == 2 && *(p + 1) == '*')
+ return 0;
+ p = q;
+ }
+
+ if (strchr (p + 1, '-') != NULL)
+ return 0;
+
+ if (*(p + 1) == '*' && *(p + 2) == '\0')
+ return 0;
+
+ return 1;
+}
+
+
+const int kDefaultFontSize = 9;
+
+
+/* XLoadQueryFont creates and returns an internal representation for a
+ font in a MacFontStruct struct. There is really no concept
+ corresponding to "loading" a font on the Mac. But we check its
+ existence and find the font number and all other information for it
+ and store them in the returned MacFontStruct. */
+
+static MacFontStruct *
+XLoadQueryFont (Display *dpy, char *fontname)
+{
+ int i, size, is_two_byte_font, char_width;
+ char *name;
+ GrafPtr port;
+ SInt16 old_fontnum, old_fontsize;
+ Style old_fontface;
+ Str32 mfontname;
+ SInt16 fontnum;
+ Style fontface = normal;
+ MacFontStruct *font;
+ FontInfo the_fontinfo;
+ char s_weight[7], c_slant;
+
+ if (is_fully_specified_xlfd (fontname))
+ name = fontname;
+ else
+ {
+ for (i = 0; i < font_name_count; i++)
+ if (mac_font_pattern_match (font_name_table[i], fontname))
+ break;
+
+ if (i >= font_name_count)
+ return NULL;
+
+ name = font_name_table[i];
+ }
+
+ GetPort (&port); /* save the current font number used */
+#if TARGET_API_MAC_CARBON
+ old_fontnum = GetPortTextFont (port);
+ old_fontsize = GetPortTextSize (port);
+ old_fontface = GetPortTextFace (port);
+#else
+ old_fontnum = port->txFont;
+ old_fontsize = port->txSize;
+ old_fontface = port->txFace;
+#endif
+
+ if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
+ size = kDefaultFontSize;
+
+ if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
+ if (strcmp (s_weight, "bold") == 0)
+ fontface |= bold;
+
+ if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
+ if (c_slant == 'i')
+ fontface |= italic;
+
+ x_font_name_to_mac_font_name (name, mfontname);
+ c2pstr (mfontname);
+ GetFNum (mfontname, &fontnum);
+ if (fontnum == 0)
+ return NULL;
+
+ font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
+
+ font->fontname = (char *) xmalloc (strlen (name) + 1);
+ bcopy (name, font->fontname, strlen (name) + 1);
+
+ font->mac_fontnum = fontnum;
+ font->mac_fontsize = size;
+ font->mac_fontface = fontface;
+ font->mac_scriptcode = FontToScript (fontnum);
+
+ /* Apple Japanese (SJIS) font is listed as both
+ "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
+ (Roman script) in init_font_name_table (). The latter should be
+ treated as a one-byte font. */
+ {
+ char cs[32];
+
+ if (sscanf (name,
+ "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
+ cs) == 1
+ && 0 == strcmp (cs, "mac-roman"))
+ font->mac_scriptcode = smRoman;
+ }
+
+ is_two_byte_font = font->mac_scriptcode == smJapanese ||
+ font->mac_scriptcode == smTradChinese ||
+ font->mac_scriptcode == smSimpChinese ||
+ font->mac_scriptcode == smKorean;
+
+ TextFont (fontnum);
+ TextSize (size);
+ TextFace (fontface);
+
+ GetFontInfo (&the_fontinfo);
+
+ font->ascent = the_fontinfo.ascent;
+ font->descent = the_fontinfo.descent;
+
+ font->min_byte1 = 0;
+ if (is_two_byte_font)
+ font->max_byte1 = 1;
+ else
+ font->max_byte1 = 0;
+ font->min_char_or_byte2 = 0x20;
+ font->max_char_or_byte2 = 0xff;
+
+ if (is_two_byte_font)
+ {
+ /* Use the width of an "ideographic space" of that font because
+ the_fontinfo.widMax returns the wrong width for some fonts. */
+ switch (font->mac_scriptcode)
+ {
+ case smJapanese:
+ char_width = StringWidth("\p\x81\x40");
+ break;
+ case smTradChinese:
+ char_width = StringWidth("\p\xa1\x40");
+ break;
+ case smSimpChinese:
+ char_width = StringWidth("\p\xa1\xa1");
+ break;
+ case smKorean:
+ char_width = StringWidth("\p\xa1\xa1");
+ break;
+ }
+ }
+ else
+ /* Do this instead of use the_fontinfo.widMax, which incorrectly
+ returns 15 for 12-point Monaco! */
+ char_width = CharWidth ('m');
+
+ font->max_bounds.rbearing = char_width;
+ font->max_bounds.lbearing = 0;
+ font->max_bounds.width = char_width;
+ font->max_bounds.ascent = the_fontinfo.ascent;
+ font->max_bounds.descent = the_fontinfo.descent;
+
+ font->min_bounds = font->max_bounds;
+
+ if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
+ font->per_char = NULL;
+ else
+ {
+ font->per_char = (XCharStruct *)
+ xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
+ {
+ int c;
+
+ for (c = 0x20; c <= 0xff; c++)
+ {
+ font->per_char[c - 0x20] = font->max_bounds;
+ font->per_char[c - 0x20].width = CharWidth (c);
+ }
+ }
+ }
+
+ TextFont (old_fontnum); /* restore previous font number, size and face */
+ TextSize (old_fontsize);
+ TextFace (old_fontface);
+
+ return font;
+}
+
+
+/* Load font named FONTNAME of the size SIZE for frame F, and return a
+ pointer to the structure font_info while allocating it dynamically.
+ If SIZE is 0, load any size of font.
+ If loading is failed, return NULL. */
+
+struct font_info *
+x_load_font (f, fontname, size)
+ struct frame *f;
+ register char *fontname;
+ int size;
+{
+ struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+ Lisp_Object font_names;
+
+ /* Get a list of all the fonts that match this name. Once we
+ have a list of matching fonts, we compare them against the fonts
+ we already have by comparing names. */
+ font_names = x_list_fonts (f, build_string (fontname), size, 1);
+
+ if (!NILP (font_names))
+ {
+ Lisp_Object tail;
+ int i;
+
+ for (i = 0; i < dpyinfo->n_fonts; i++)
+ for (tail = font_names; CONSP (tail); tail = XCDR (tail))
+ if (dpyinfo->font_table[i].name
+ && (!strcmp (dpyinfo->font_table[i].name,
+ XSTRING (XCAR (tail))->data)
+ || !strcmp (dpyinfo->font_table[i].full_name,
+ XSTRING (XCAR (tail))->data)))
+ return (dpyinfo->font_table + i);
+ }
+
+ /* Load the font and add it to the table. */
+ {
+ char *full_name;
+ struct MacFontStruct *font;
+ struct font_info *fontp;
+ unsigned long value;
+ int i;
+
+ /* If we have found fonts by x_list_font, load one of them. If
+ not, we still try to load a font by the name given as FONTNAME
+ because XListFonts (called in x_list_font) of some X server has
+ a bug of not finding a font even if the font surely exists and
+ is loadable by XLoadQueryFont. */
+ if (size > 0 && !NILP (font_names))
+ fontname = (char *) XSTRING (XCAR (font_names))->data;
+
+ font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
+ if (!font)
+ return NULL;
+
+ /* Find a free slot in the font table. */
+ for (i = 0; i < dpyinfo->n_fonts; ++i)
+ if (dpyinfo->font_table[i].name == NULL)
+ break;
+
+ /* If no free slot found, maybe enlarge the font table. */
+ if (i == dpyinfo->n_fonts
+ && dpyinfo->n_fonts == dpyinfo->font_table_size)
+ {
+ int sz;
+ dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
+ sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
+ dpyinfo->font_table
+ = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
+ }
+
+ fontp = dpyinfo->font_table + i;
+ if (i == dpyinfo->n_fonts)
+ ++dpyinfo->n_fonts;
+
+ /* Now fill in the slots of *FONTP. */
+ BLOCK_INPUT;
+ fontp->font = font;
+ fontp->font_idx = i;
+ fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
+ bcopy (font->fontname, fontp->name, strlen (font->fontname) + 1);
+
+ fontp->full_name = fontp->name;
+
+ fontp->size = font->max_bounds.width;
+ fontp->height = FONT_HEIGHT (font);
+ {
+ /* For some font, ascent and descent in max_bounds field is
+ larger than the above value. */
+ int max_height = font->max_bounds.ascent + font->max_bounds.descent;
+ if (max_height > fontp->height)
+ fontp->height = max_height;
+ }
+
+ /* The slot `encoding' specifies how to map a character
+ code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
+ the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
+ (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
+ 2:0xA020..0xFF7F). For the moment, we don't know which charset
+ uses this font. So, we set information in fontp->encoding[1]
+ which is never used by any charset. If mapping can't be
+ decided, set FONT_ENCODING_NOT_DECIDED. */
+ if (font->mac_scriptcode == smJapanese)
+ fontp->encoding[1] = 4;
+ else
+ {
+ fontp->encoding[1]
+ = (font->max_byte1 == 0
+ /* 1-byte font */
+ ? (font->min_char_or_byte2 < 0x80
+ ? (font->max_char_or_byte2 < 0x80
+ ? 0 /* 0x20..0x7F */
+ : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
+ : 1) /* 0xA0..0xFF */
+ /* 2-byte font */
+ : (font->min_byte1 < 0x80
+ ? (font->max_byte1 < 0x80
+ ? (font->min_char_or_byte2 < 0x80
+ ? (font->max_char_or_byte2 < 0x80
+ ? 0 /* 0x2020..0x7F7F */
+ : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
+ : 3) /* 0x20A0..0x7FFF */
+ : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
+ : (font->min_char_or_byte2 < 0x80
+ ? (font->max_char_or_byte2 < 0x80
+ ? 2 /* 0xA020..0xFF7F */
+ : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
+ : 1))); /* 0xA0A0..0xFFFF */
+ }
+
+#if 0 /* MAC_TODO: fill these out with more reasonably values */
+ fontp->baseline_offset
+ = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
+ ? (long) value : 0);
+ fontp->relative_compose
+ = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
+ ? (long) value : 0);
+ fontp->default_ascent
+ = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
+ ? (long) value : 0);
+#else
+ fontp->baseline_offset = 0;
+ fontp->relative_compose = 0;
+ fontp->default_ascent = 0;
+#endif
+
+ /* Set global flag fonts_changed_p to non-zero if the font loaded
+ has a character with a smaller width than any other character
+ before, or if the font loaded has a smalle>r height than any
+ other font loaded before. If this happens, it will make a
+ glyph matrix reallocation necessary. */
+ fonts_changed_p = x_compute_min_glyph_bounds (f);
+ UNBLOCK_INPUT;
+ return fontp;
+ }
+}
+
+
+/* Return a pointer to struct font_info of a font named FONTNAME for
+ frame F. If no such font is loaded, return NULL. */
+
+struct font_info *
+x_query_font (f, fontname)
+ struct frame *f;
+ register char *fontname;
+{
+ struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
+ int i;
+
+ for (i = 0; i < dpyinfo->n_fonts; i++)
+ if (dpyinfo->font_table[i].name
+ && (!strcmp (dpyinfo->font_table[i].name, fontname)
+ || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
+ return (dpyinfo->font_table + i);
+ return NULL;
+}
+
+
+/* Find a CCL program for a font specified by FONTP, and set the member
+ `encoder' of the structure. */
+
+void
+x_find_ccl_program (fontp)
+ struct font_info *fontp;
+{
+ Lisp_Object list, elt;
+
+ for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
+ {
+ elt = XCAR (list);
+ if (CONSP (elt)
+ && STRINGP (XCAR (elt))
+ && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
+ >= 0))
+ break;
+ }
+ if (! NILP (list))
+ {
+ struct ccl_program *ccl
+ = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
+
+ if (setup_ccl_program (ccl, XCDR (elt)) < 0)
+ xfree (ccl);
+ else
+ fontp->font_encoder = ccl;
+ }
+}
+
+
+\f
+/***********************************************************************
+ Initialization
+ ***********************************************************************/
+
+#ifdef USE_X_TOOLKIT
+static XrmOptionDescRec emacs_options[] = {
+ {"-geometry", ".geometry", XrmoptionSepArg, NULL},
+ {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
+
+ {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
+ XrmoptionSepArg, NULL},
+ {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
+
+ {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
+ {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
+ {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
+ {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
+ {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
+ {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
+ {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
+};
+#endif /* USE_X_TOOLKIT */
+
+static int x_initialized;
+
+#ifdef MULTI_KBOARD
+/* Test whether two display-name strings agree up to the dot that separates
+ the screen number from the server number. */
+static int
+same_x_server (name1, name2)
+ char *name1, *name2;
+{
+ int seen_colon = 0;
+ unsigned char *system_name = XSTRING (Vsystem_name)->data;
+ int system_name_length = strlen (system_name);
+ int length_until_period = 0;
+
+ while (system_name[length_until_period] != 0
+ && system_name[length_until_period] != '.')
+ length_until_period++;
+
+ /* Treat `unix' like an empty host name. */
+ if (! strncmp (name1, "unix:", 5))
+ name1 += 4;
+ if (! strncmp (name2, "unix:", 5))
+ name2 += 4;
+ /* Treat this host's name like an empty host name. */
+ if (! strncmp (name1, system_name, system_name_length)
+ && name1[system_name_length] == ':')
+ name1 += system_name_length;
+ if (! strncmp (name2, system_name, system_name_length)
+ && name2[system_name_length] == ':')
+ name2 += system_name_length;
+ /* Treat this host's domainless name like an empty host name. */
+ if (! strncmp (name1, system_name, length_until_period)
+ && name1[length_until_period] == ':')
+ name1 += length_until_period;
+ if (! strncmp (name2, system_name, length_until_period)
+ && name2[length_until_period] == ':')
+ name2 += length_until_period;
+
+ for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
+ {
+ if (*name1 == ':')
+ seen_colon++;
+ if (seen_colon && *name1 == '.')
+ return 1;
+ }
+ return (seen_colon
+ && (*name1 == '.' || *name1 == '\0')
+ && (*name2 == '.' || *name2 == '\0'));
+}
+#endif
+
+
+/* The Mac Event loop code */
+
+#ifndef MAC_OSX
+#include <Events.h>
+#include <Quickdraw.h>
+#include <Balloons.h>
+#include <Devices.h>
+#include <Fonts.h>
+#include <Gestalt.h>
+#include <Menus.h>
+#include <Processes.h>
+#include <Sound.h>
+#include <ToolUtils.h>
+#include <TextUtils.h>
+#include <Dialogs.h>
+#include <Script.h>
+#include <Types.h>
+#include <TextEncodingConverter.h>
+#include <Resources.h>
+
+#if __MWERKS__
+#include <unix.h>
+#endif
+#endif /* ! MAC_OSX */
+
+#define M_APPLE 128
+#define I_ABOUT 1
+
+#define WINDOW_RESOURCE 128
+#define TERM_WINDOW_RESOURCE 129
+
+#define DEFAULT_NUM_COLS 80
+
+#define MIN_DOC_SIZE 64
+#define MAX_DOC_SIZE 32767
+
+/* sleep time for WaitNextEvent */
+#define WNE_SLEEP_AT_SUSPEND 10
+#define WNE_SLEEP_AT_RESUME 1
+
+/* true when cannot handle any Mac OS events */
+static int handling_window_update = 0;
+
+/* the flag appl_is_suspended is used both for determining the sleep
+ time to be passed to WaitNextEvent and whether the cursor should be
+ drawn when updating the display. The cursor is turned off when
+ Emacs is suspended. Redrawing it is unnecessary and what needs to
+ be done depends on whether the cursor lies inside or outside the
+ redraw region. So we might as well skip drawing it when Emacs is
+ suspended. */
+static Boolean app_is_suspended = false;
+static long app_sleep_time = WNE_SLEEP_AT_RESUME;
+
+#define EXTRA_STACK_ALLOC (256 * 1024)
+
+#define ARGV_STRING_LIST_ID 129
+#define ABOUT_ALERT_ID 128
+#define RAM_TOO_LARGE_ALERT_ID 129
+
+Boolean terminate_flag = false;
+
+/* true if using command key as meta key */
+Lisp_Object Vmac_command_key_is_meta;
+
+/* convert input from Mac keyboard (assumed to be in Mac Roman coding)
+ to this text encoding */
+int mac_keyboard_text_encoding;
+int current_mac_keyboard_text_encoding = kTextEncodingMacRoman;
+
+/* Set in term/mac-win.el to indicate that event loop can now generate
+ drag and drop events. */
+Lisp_Object Qmac_ready_for_drag_n_drop;
+
+Lisp_Object drag_and_drop_file_list;
+
+Point saved_menu_event_location;
+
+/* Apple Events */
+static void init_required_apple_events(void);
+static pascal OSErr
+do_ae_open_application(const AppleEvent *, AppleEvent *, long);
+static pascal OSErr
+do_ae_print_documents(const AppleEvent *, AppleEvent *, long);
+static pascal OSErr do_ae_open_documents(AppleEvent *, AppleEvent *, long);
+static pascal OSErr do_ae_quit_application(AppleEvent *, AppleEvent *, long);
+
+extern void init_emacs_passwd_dir ();
+extern int emacs_main (int, char **, char **);
+extern void check_alarm ();
+
+extern void initialize_applescript();
+extern void terminate_applescript();
+
+
+static void
+do_get_menus (void)
+{
+ Handle menubar_handle;
+ MenuHandle menu_handle;
+
+ menubar_handle = GetNewMBar (128);
+ if(menubar_handle == NULL)
+ abort ();
+ SetMenuBar (menubar_handle);
+ DrawMenuBar ();
+
+ menu_handle = GetMenuHandle (M_APPLE);
+ if(menu_handle != NULL)
+ AppendResMenu (menu_handle,'DRVR');
+ else
+ abort ();
+}
+
+
+static void
+do_init_managers (void)
+{
+#if !TARGET_API_MAC_CARBON
+ InitGraf (&qd.thePort);
+ InitFonts ();
+ FlushEvents (everyEvent, 0);
+ InitWindows ();
+ InitMenus ();
+ TEInit ();
+ InitDialogs (NULL);
+#endif /* !TARGET_API_MAC_CARBON */
+ InitCursor ();
+
+#if !TARGET_API_MAC_CARBON
+ /* set up some extra stack space for use by emacs */
+ SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
+
+ /* MaxApplZone must be called for AppleScript to execute more
+ complicated scripts */
+ MaxApplZone ();
+ MoreMasters ();
+#endif /* !TARGET_API_MAC_CARBON */
+}
+
+static void
+do_check_ram_size (void)
+{
+ SInt32 physical_ram_size, logical_ram_size;
+
+ if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
+ || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
+ || physical_ram_size > 256 * 1024 * 1024
+ || logical_ram_size > 256 * 1024 * 1024)
+ {
+ StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
+ exit (1);
+ }
+}
+
+static void
+do_window_update (WindowPtr win)
+{
+ struct mac_output *mwp = (mac_output *) GetWRefCon (win);
+ struct frame *f = mwp->mFP;
+
+ if (f)
+ {
+ if (f->async_visible == 0)
+ {
+ f->async_visible = 1;
+ f->async_iconified = 0;
+ SET_FRAME_GARBAGED (f);
+
+ /* An update event is equivalent to MapNotify on X, so report
+ visibility changes properly. */
+ if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
+ /* Force a redisplay sooner or later to update the
+ frame titles in case this is the second frame. */
+ record_asynch_buffer_change ();
+ }
+ else
+ {
+ BeginUpdate (win);
+ handling_window_update = 1;
+
+ expose_frame (f, 0, 0, 0, 0);
+
+ handling_window_update = 0;
+ EndUpdate (win);
+ }
+ }
+}
+
+static int
+is_emacs_window (WindowPtr win)
+{
+ Lisp_Object tail, frame;
+
+ if (!win)
+ return 0;
+
+ FOR_EACH_FRAME (tail, frame)
+ if (FRAME_MAC_P (XFRAME (frame)))
+ if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
+ return 1;
+
+ return 0;
+}
+
+static void
+do_window_activate (WindowPtr win)
+{
+ mac_output *mwp;
+ struct frame *f;
+
+ if (is_emacs_window (win))
+ {
+ mwp = (mac_output *) GetWRefCon (win);
+ f = mwp->mFP;
+
+ if (f)
+ {
+ x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
+ activate_scroll_bars (f);
+ }
+ }
+}
+
+static void
+do_window_deactivate (WindowPtr win)
+{
+ mac_output *mwp;
+ struct frame *f;
+
+ if (is_emacs_window (win))
+ {
+ mwp = (mac_output *) GetWRefCon (win);
+ f = mwp->mFP;
+
+ if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
+ {
+ x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
+ deactivate_scroll_bars (f);
+ }
+ }
+}
+
+static void
+do_app_resume ()
+{
+ WindowPtr wp;
+ mac_output *mwp;
+ struct frame *f;
+
+ wp = FrontWindow();
+ if (is_emacs_window (wp))
+ {
+ mwp = (mac_output *) GetWRefCon (wp);
+ f = mwp->mFP;
+
+ if (f)
+ {
+ x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
+ activate_scroll_bars (f);
+ }
+ }
+
+ app_is_suspended = false;
+ app_sleep_time = WNE_SLEEP_AT_RESUME;
+}
+
+static void
+do_app_suspend ()
+{
+ WindowPtr wp;
+ mac_output *mwp;
+ struct frame *f;
+
+ wp = FrontWindow();
+ if (is_emacs_window (wp))
+ {
+ mwp = (mac_output *) GetWRefCon (wp);
+ f = mwp->mFP;
+
+ if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
+ {
+ x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
+ deactivate_scroll_bars (f);
+ }
+ }
+
+ app_is_suspended = true;
+ app_sleep_time = WNE_SLEEP_AT_SUSPEND;
+}
+
+
+static void
+do_mouse_moved (Point mouse_pos)
+{
+ WindowPtr wp = FrontWindow ();
+ struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
+
+#if TARGET_API_MAC_CARBON
+ SetPort (GetWindowPort (wp));
+#else
+ SetPort (wp);
+#endif
+
+ GlobalToLocal (&mouse_pos);
+
+ note_mouse_movement (f, &mouse_pos);
+}
+
+
+static void
+do_os_event (EventRecord *erp)
+{
+ switch((erp->message >> 24) & 0x000000FF)
+ {
+ case suspendResumeMessage:
+ if((erp->message & resumeFlag) == 1)
+ do_app_resume ();
+ else
+ do_app_suspend ();
+ break;
+
+ case mouseMovedMessage:
+ do_mouse_moved (erp->where);
+ break;
+ }
+}
+
+static void
+do_events (EventRecord *erp)
+{
+ switch (erp->what)
+ {
+ case updateEvt:
+ do_window_update ((WindowPtr) erp->message);
+ break;
+
+ case osEvt:
+ do_os_event (erp);
+ break;
+
+ case activateEvt:
+ if ((erp->modifiers & activeFlag) != 0)
+ do_window_activate ((WindowPtr) erp->message);
+ else
+ do_window_deactivate ((WindowPtr) erp->message);
+ break;
+ }
+}
+
+static void
+do_apple_menu (SInt16 menu_item)
+{
+#if !TARGET_API_MAC_CARBON
+ Str255 item_name;
+ SInt16 da_driver_refnum;
+
+ if (menu_item == I_ABOUT)
+ NoteAlert (ABOUT_ALERT_ID, NULL);
+ else
+ {
+ GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
+ da_driver_refnum = OpenDeskAcc (item_name);
+ }
+#endif /* !TARGET_API_MAC_CARBON */
+}
+
+void
+do_menu_choice (SInt32 menu_choice)
+{
+ SInt16 menu_id, menu_item;
+
+ menu_id = HiWord (menu_choice);
+ menu_item = LoWord (menu_choice);
+
+ if (menu_id == 0)
+ return;
+
+ switch (menu_id)
+ {
+ case M_APPLE:
+ do_apple_menu (menu_item);
+ break;
+
+ default:
+ {
+ WindowPtr wp = FrontWindow ();
+ struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
+ MenuHandle menu = GetMenuHandle (menu_id);
+ if (menu)
+ {
+ UInt32 refcon;
+
+ GetMenuItemRefCon (menu, menu_item, &refcon);
+ menubar_selection_callback (f, refcon);
+ }
+ }
+ }
+
+ HiliteMenu (0);
+}
+
+
+/* Handle drags in size box. Based on code contributed by Ben
+ Mesander and IM - Window Manager A. */
+
+static void
+do_grow_window (WindowPtr w, EventRecord *e)
+{
+ long grow_size;
+ Rect limit_rect;
+ int rows, columns;
+ mac_output *mwp = (mac_output *) GetWRefCon (w);
+ struct frame *f = mwp->mFP;
+
+ SetRect(&limit_rect, MIN_DOC_SIZE, MIN_DOC_SIZE, MAX_DOC_SIZE, MAX_DOC_SIZE);
+
+ grow_size = GrowWindow (w, e->where, &limit_rect);
+
+ /* see if it really changed size */
+ if (grow_size != 0)
+ {
+ rows = PIXEL_TO_CHAR_HEIGHT (f, HiWord (grow_size));
+ columns = PIXEL_TO_CHAR_WIDTH (f, LoWord (grow_size));
+
+ x_set_window_size (f, 0, columns, rows);
+ }
+}
+
+
+/* Handle clicks in zoom box. Calculation of "standard state" based
+ on code in IM - Window Manager A and code contributed by Ben
+ Mesander. The standard state of an Emacs window is 80-characters
+ wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
+
+static void
+do_zoom_window (WindowPtr w, int zoom_in_or_out)
+{
+ GrafPtr save_port;
+ Rect zoom_rect, port_rect;
+ Point top_left;
+ int w_title_height, columns, rows, width, height, dummy, x, y;
+ mac_output *mwp = (mac_output *) GetWRefCon (w);
+ struct frame *f = mwp->mFP;
+
+ GetPort (&save_port);
+
+#if TARGET_API_MAC_CARBON
+ SetPort (GetWindowPort (w));
+#else
+ SetPort (w);
+#endif
+
+ /* Clear window to avoid flicker. */
+#if TARGET_API_MAC_CARBON
+ {
+ Rect r;
+ BitMap bm;
+
+ GetWindowPortBounds (w, &r);
+ EraseRect (&r);
+
+ if (zoom_in_or_out == inZoomOut)
+ {
+ /* calculate height of window's title bar (hard card it for now). */
+ w_title_height = 20 + GetMBarHeight ();
+
+ /* get maximum height of window into zoom_rect.bottom -
+ zoom_rect.top */
+ GetQDGlobalsScreenBits (&bm);
+ zoom_rect = bm.bounds;
+ zoom_rect.top += w_title_height;
+ InsetRect (&zoom_rect, 8, 4); /* not too tight */
+
+ zoom_rect.right = zoom_rect.left
+ + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
+
+ SetWindowStandardState (w, &zoom_rect);
+ }
+ }
+#else /* not TARGET_API_MAC_CARBON */
+ EraseRect (&(w->portRect));
+ if (zoom_in_or_out == inZoomOut)
+ {
+ SetPt (&top_left, w->portRect.left, w->portRect.top);
+ LocalToGlobal (&top_left);
+
+ /* calculate height of window's title bar */
+ w_title_height = top_left.v - 1
+ - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
+
+ /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
+ zoom_rect = qd.screenBits.bounds;
+ zoom_rect.top += w_title_height;
+ InsetRect (&zoom_rect, 8, 4); /* not too tight */
+
+ zoom_rect.right = zoom_rect.left
+ + CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
+
+ (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
+ = zoom_rect;
+ }
+#endif /* not TARGET_API_MAC_CARBON */
+
+ ZoomWindow (w, zoom_in_or_out, w == FrontWindow ());
+
+ /* retrieve window size and update application values */
+#if TARGET_API_MAC_CARBON
+ GetWindowPortBounds (w, &port_rect);
+#else
+ port_rect = w->portRect;
+#endif
+ rows = PIXEL_TO_CHAR_HEIGHT (f, port_rect.bottom - port_rect.top);
+ columns = PIXEL_TO_CHAR_WIDTH (f, port_rect.right - port_rect.left);
+ x_set_window_size (mwp->mFP, 0, columns, rows);
+
+ SetPort (save_port);
+}
+
+
+/* Intialize AppleEvent dispatcher table for the required events. */
+void
+init_required_apple_events ()
+{
+ OSErr err;
+ long result;
+
+ /* Make sure we have apple events before starting. */
+ err = Gestalt (gestaltAppleEventsAttr, &result);
+ if (err != noErr)
+ abort ();
+
+ if (!(result & (1 << gestaltAppleEventsPresent)))
+ abort ();
+
+#if TARGET_API_MAC_CARBON
+ err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
+ NewAEEventHandlerUPP
+ ((AEEventHandlerProcPtr) do_ae_open_application),
+ 0L, false);
+#else
+ err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
+ NewAEEventHandlerProc
+ ((AEEventHandlerProcPtr) do_ae_open_application),
+ 0L, false);
+#endif
+ if (err != noErr)
+ abort ();
+
+#if TARGET_API_MAC_CARBON
+ err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
+ NewAEEventHandlerUPP
+ ((AEEventHandlerProcPtr) do_ae_open_documents),
+ 0L, false);
+#else
+ err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
+ NewAEEventHandlerProc
+ ((AEEventHandlerProcPtr) do_ae_open_documents),
+ 0L, false);
+#endif
+ if (err != noErr)
+ abort ();
+
+#if TARGET_API_MAC_CARBON
+ err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
+ NewAEEventHandlerUPP
+ ((AEEventHandlerProcPtr) do_ae_print_documents),
+ 0L, false);
+#else
+ err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
+ NewAEEventHandlerProc
+ ((AEEventHandlerProcPtr) do_ae_print_documents),
+ 0L, false);
+#endif
+ if (err != noErr)
+ abort ();
+
+#if TARGET_API_MAC_CARBON
+ err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
+ NewAEEventHandlerUPP
+ ((AEEventHandlerProcPtr) do_ae_quit_application),
+ 0L, false);
+#else
+ err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
+ NewAEEventHandlerProc
+ ((AEEventHandlerProcPtr) do_ae_quit_application),
+ 0L, false);
+#endif
+ if (err != noErr)
+ abort ();
+}
+
+
+/* Open Application Apple Event */
+static pascal OSErr
+do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
+{
+ return noErr;
+}
+
+
+/* Defined in mac.c. */
+extern int
+path_from_vol_dir_name (char *, int, short, long, char *);
+
+
+/* Called when we receive an AppleEvent with an ID of
+ "kAEOpenDocuments". This routine gets the direct parameter,
+ extracts the FSSpecs in it, and puts their names on a list. */
+static pascal OSErr
+do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
+{
+ OSErr err, err2;
+ AEDesc the_desc;
+ AEKeyword keyword;
+ DescType actual_type;
+ Size actual_size;
+
+ err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
+ if (err != noErr)
+ goto descriptor_error_exit;
+
+ /* Check to see that we got all of the required parameters from the
+ event descriptor. For an 'odoc' event this should just be the
+ file list. */
+ err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
+ &actual_type, (Ptr) &keyword,
+ sizeof (keyword), &actual_size);
+ /* No error means that we found some unused parameters.
+ errAEDescNotFound means that there are no more parameters. If we
+ get an error code other than that, flag it. */
+ if ((err == noErr) || (err != errAEDescNotFound))
+ {
+ err = errAEEventNotHandled;
+ goto error_exit;
+ }
+ err = noErr;
+
+ /* Got all the parameters we need. Now, go through the direct
+ object list and parse it up. */
+ {
+ long num_files_to_open;
+
+ err = AECountItems (&the_desc, &num_files_to_open);
+ if (err == noErr)
+ {
+ int i;
+
+ /* AE file list is one based so just use that for indexing here. */
+ for (i = 1; (err == noErr) && (i <= num_files_to_open); i++) {
+ FSSpec fs;
+ Str255 path_name, unix_path_name;
+
+ err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
+ (Ptr) &fs, sizeof (fs), &actual_size);
+ if (err != noErr) break;
+
+ if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID,
+ fs.name) &&
+ mac_to_posix_pathname (path_name, unix_path_name, 255))
+ drag_and_drop_file_list = Fcons (build_string (unix_path_name),
+ drag_and_drop_file_list);
+ }
+ }
+ }
+
+error_exit:
+ /* Nuke the coerced file list in any case */
+ err2 = AEDisposeDesc(&the_desc);
+
+descriptor_error_exit:
+ /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
+ return err;
+}
+
+
+/* Print Document Apple Event */
+static pascal OSErr
+do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
+{
+ return errAEEventNotHandled;
+}
+
+
+static pascal OSErr
+do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
+{
+ /* FixMe: Do we need an unwind-protect or something here? And what
+ do we do about unsaved files. Currently just forces quit rather
+ than doing recursive callback to get user input. */
+
+ terminate_flag = true;
+
+ /* Fkill_emacs doesn't return. We have to return. (TI) */
+ return noErr;
+}
+
+
+#if __profile__
+void
+profiler_exit_proc ()
+{
+ ProfilerDump ("\pEmacs.prof");
+ ProfilerTerm ();
+}
+#endif
+
+/* These few functions implement Emacs as a normal Mac application
+ (almost): set up the heap and the Toolbox, handle necessary
+ system events plus a few simple menu events. They also set up
+ Emacs's access to functions defined in the rest of this file.
+ Emacs uses function hooks to perform all its terminal I/O. A
+ complete list of these functions appear in termhooks.h. For what
+ they do, read the comments there and see also w32term.c and
+ xterm.c. What's noticeably missing here is the event loop, which
+ is normally present in most Mac application. After performing the
+ necessary Mac initializations, main passes off control to
+ emacs_main (corresponding to main in emacs.c). Emacs_main calls
+ mac_read_socket (defined further below) to read input. This is
+ where WaitNextEvent is called to process Mac events. This is also
+ where check_alarm in sysdep.c is called to simulate alarm signals.
+ This makes the cursor jump back to its correct position after
+ briefly jumping to that of the matching parenthesis, print useful
+ hints and prompts in the minibuffer after the user stops typing for
+ a wait, etc. */
+
+#if !TARGET_API_MAC_CARBON
+#undef main
+int
+main (void)
+{
+#if __profile__ /* is the profiler on? */
+ if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
+ exit(1);
+#endif
+
+#if __MWERKS__
+ /* set creator and type for files created by MSL */
+ _fcreator = 'EMAx';
+ _ftype = 'TEXT';
+#endif
+
+ do_init_managers ();
+
+ do_get_menus ();
+
+ do_check_ram_size ();
+
+ init_emacs_passwd_dir ();
+
+ init_environ ();
+
+ initialize_applescript ();
+
+ init_required_apple_events ();
+
+ {
+ char **argv;
+ int argc = 0;
+
+ /* set up argv array from STR# resource */
+ get_string_list (&argv, ARGV_STRING_LIST_ID);
+ while (argv[argc])
+ argc++;
+
+ /* free up AppleScript resources on exit */
+ atexit (terminate_applescript);
+
+#if __profile__ /* is the profiler on? */
+ atexit (profiler_exit_proc);
+#endif
+
+ /* 3rd param "envp" never used in emacs_main */
+ (void) emacs_main (argc, argv, 0);
+ }
+
+ /* Never reached - real exit in Fkill_emacs */
+ return 0;
+}
+#endif
+
+/* Table for translating Mac keycode to X keysym values. Contributed
+ by Sudhir Shenoy. */
+static unsigned char keycode_to_xkeysym_table[] = {
+/* 0x00 - 0x3f */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+/* 0x40 */
+ 0, '\xae' /* kp. */, 0, '\xaa' /* kp* */,
+ 0, '\xab' /* kp+ */, 0, '\x7f' /* kp_clr */,
+ 0, 0, 0, '\xaf' /* kp/ */,
+ '\x8d' /* kp_ent */, 0, '\xad' /* kp- */, 0,
+/* 0x50 */
+ 0, '\xbd' /* kp= */, '\xb0' /* kp0 */, '\xb1' /* kp1 */,
+ '\xb2' /* kp2 */, '\xb3' /* kp3 */, '\xb4' /* kp4 */, '\xb5' /* kp5 */,
+ '\xb6' /* kp6 */, '\xb7' /* kp7 */, 0, '\xb8' /* kp8 */,
+ '\xb9' /* kp9 */, 0, 0, 0,
+/* 0x60 */
+ '\xc2' /* F5 */, '\xc3' /* F6 */, '\xc4' /* F7 */, '\xc0' /* F3 */,
+ '\xc5' /* F8 */, '\xc6' /* F9 */, 0, '\xc8' /* F11 */,
+ 0, '\xca' /* F13 */, 0, '\xcb' /* F14 */,
+ 0, '\xc7' /* F10 */, 0, '\xc9' /* F12 */,
+/* 0x70 */
+ 0, '\xcc' /* F15 */, '\x9e' /* ins */, '\x95' /* home */,
+ '\x9a' /* pgup */, '\x9f' /* del */, '\xc1' /* F4 */, '\x9c' /* end */,
+ '\xbf' /* F2 */, '\x9b' /* pgdown */, '\xbe' /* F1 */, '\x51' /* left */,
+ '\x53' /* right */, '\x54' /* down */, '\x52' /* up */, 0
+};
+
+static int
+keycode_to_xkeysym (int keyCode, int *xKeySym)
+{
+ *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
+ return *xKeySym != 0;
+}
+
+/* Emacs calls this whenever it wants to read an input event from the
+ user. */
+int
+XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
+{
+ int count = 0;
+ EventRecord er;
+ int the_modifiers;
+ EventMask event_mask;
+
+#if 0
+ if (interrupt_input_blocked)
+ {
+ interrupt_input_pending = 1;
+ return -1;
+ }
+#endif
+
+ interrupt_input_pending = 0;
+ BLOCK_INPUT;
+
+ /* So people can tell when we have read the available input. */
+ input_signal_count++;
+
+ if (numchars <= 0)
+ abort ();
+
+ /* Don't poll for events to process (specifically updateEvt) if
+ window update currently already in progress. A call to redisplay
+ (in do_window_update) can be preempted by another call to
+ redisplay, causing blank regions to be left on the screen and the
+ cursor to be left at strange places. */
+ if (handling_window_update)
+ {
+ UNBLOCK_INPUT;
+ return 0;
+ }
+
+ if (terminate_flag)
+ Fkill_emacs (make_number (1));
+
+ /* It is necessary to set this (additional) argument slot of an
+ event to nil because keyboard.c protects incompletely processed
+ event from being garbage collected by placing them in the
+ kbd_buffer_gcpro vector. */
+ bufp->arg = Qnil;
+
+ event_mask = everyEvent;
+ if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
+ event_mask -= highLevelEventMask;
+
+ while (WaitNextEvent (event_mask, &er, 0L, NULL) && numchars > 0)
+ switch (er.what)
+ {
+ case mouseDown:
+ case mouseUp:
+ {
+ WindowPtr window_ptr = FrontWindow ();
+ SInt16 part_code;
+
+ if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
+ && er.what == mouseUp)
+ {
+ struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
+ Point mouse_loc = er.where;
+
+ /* Convert to local coordinates of new window. */
+#if TARGET_API_MAC_CARBON
+ SetPort (GetWindowPort (window_ptr));
+#else
+ SetPort (window_ptr);
+#endif
+
+ GlobalToLocal (&mouse_loc);
+
+ bufp->code = 0; /* only one mouse button */
+ bufp->kind = scroll_bar_click;
+ bufp->frame_or_window = tracked_scroll_bar->window;
+ bufp->part = scroll_bar_handle;
+ bufp->modifiers = up_modifier;
+ bufp->timestamp = er.when * (1000 / 60);
+ /* ticks to milliseconds */
+
+ XSETINT (bufp->x, tracked_scroll_bar->left + 2);
+ XSETINT (bufp->y, mouse_loc.v - 24);
+ tracked_scroll_bar->dragging = Qnil;
+ mouse_tracking_in_progress = mouse_tracking_none;
+ tracked_scroll_bar = NULL;
+ count++;
+ bufp++;
+ numchars--;
+ break;
+ }
+
+ part_code = FindWindow (er.where, &window_ptr);
+
+ switch (part_code)
+ {
+ case inMenuBar:
+ {
+ struct frame *f = ((mac_output *)
+ GetWRefCon (FrontWindow ()))->mFP;
+ saved_menu_event_location = er.where;
+ bufp->kind = menu_bar_activate_event;
+ XSETFRAME (bufp->frame_or_window, f);
+ count++;
+ bufp++;
+ numchars--;
+ }
+ break;
+
+ case inContent:
+ if (window_ptr != FrontWindow ())
+ SelectWindow (window_ptr);
+ else
+ {
+ SInt16 control_part_code;
+ ControlHandle ch;
+ struct mac_output *mwp = (mac_output *)
+ GetWRefCon (window_ptr);
+ Point mouse_loc = er.where;
+
+ /* convert to local coordinates of new window */
+#if TARGET_API_MAC_CARBON
+ SetPort (GetWindowPort (window_ptr));
+#else
+ SetPort (window_ptr);
+#endif
+
+ GlobalToLocal (&mouse_loc);
+#if TARGET_API_MAC_CARBON
+ ch = FindControlUnderMouse (mouse_loc, window_ptr,
+ &control_part_code);
+#else
+ control_part_code = FindControl (mouse_loc, window_ptr, &ch);
+#endif
+ bufp->code = 0; /* only one mouse button */
+ XSETINT (bufp->x, mouse_loc.h);
+ XSETINT (bufp->y, mouse_loc.v);
+ bufp->timestamp = er.when * (1000 / 60);
+ /* ticks to milliseconds */
+
+#if TARGET_API_MAC_CARBON
+ if (ch != 0)
+#else
+ if (control_part_code != 0)
+#endif
+ {
+ struct scroll_bar *bar = (struct scroll_bar *)
+ GetControlReference (ch);
+ x_scroll_bar_handle_click (bar, control_part_code, &er,
+ bufp);
+ if (er.what == mouseDown
+ && control_part_code == kControlIndicatorPart)
+ {
+ mouse_tracking_in_progress
+ = mouse_tracking_scroll_bar;
+ tracked_scroll_bar = bar;
+ }
+ else
+ {
+ mouse_tracking_in_progress = mouse_tracking_none;
+ tracked_scroll_bar = NULL;
+ }
+ }
+ else
+ {
+ bufp->kind = mouse_click;
+ XSETFRAME (bufp->frame_or_window, mwp->mFP);
+ if (er.what == mouseDown)
+ mouse_tracking_in_progress
+ = mouse_tracking_mouse_movement;
+ else
+ mouse_tracking_in_progress = mouse_tracking_none;
+ }
+
+ switch (er.what)
+ {
+ case mouseDown:
+ bufp->modifiers = down_modifier;
+ break;
+ case mouseUp:
+ bufp->modifiers = up_modifier;
+ break;
+ }
+
+ count++;
+ bufp++;
+ numchars--;
+ }
+ break;
+
+ case inDrag:
+#if TARGET_API_MAC_CARBON
+ {
+ BitMap bm;
+
+ GetQDGlobalsScreenBits (&bm);
+ DragWindow (window_ptr, er.where, &bm.bounds);
+ }
+#else /* not TARGET_API_MAC_CARBON */
+ DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
+#endif /* not TARGET_API_MAC_CARBON */
+ break;
+
+ case inGoAway:
+ if (TrackGoAway (window_ptr, er.where))
+ {
+ bufp->kind = delete_window_event;
+ XSETFRAME (bufp->frame_or_window,
+ ((mac_output *) GetWRefCon (window_ptr))->mFP);
+ count++;
+ bufp++;
+ numchars--;
+ }
+ break;
+
+ /* window resize handling added --ben */
+ case inGrow:
+ do_grow_window(window_ptr, &er);
+ break;
+
+ /* window zoom handling added --ben */
+ case inZoomIn:
+ case inZoomOut:
+ if (TrackBox (window_ptr, er.where, part_code))
+ do_zoom_window (window_ptr, part_code);
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+
+ case updateEvt:
+ case osEvt:
+ case activateEvt:
+ do_events (&er);
+ break;
+
+ case keyDown:
+ case autoKey:
+ {
+ int keycode = (er.message & keyCodeMask) >> 8;
+ int xkeysym;
+
+ ObscureCursor ();
+
+ if (keycode == 0x33) /* delete key (charCode translated to 0x8) */
+ {
+ bufp->code = 0x7f;
+ bufp->kind = ascii_keystroke;
+ }
+ else if (keycode_to_xkeysym (keycode, &xkeysym))
+ {
+ bufp->code = 0xff00 | xkeysym;
+ bufp->kind = non_ascii_keystroke;
+ }
+ else
+ {
+ if (er.modifiers
+ & (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
+ {
+ /* This code comes from Keyboard Resource, Appendix
+ C of IM - Text. This is necessary since shift is
+ ignored in KCHR table translation when option or
+ command is pressed. */
+ int new_modifiers = er.modifiers & 0xf600;
+ /* mask off option and command */
+ int new_keycode = keycode | new_modifiers;
+ Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
+ unsigned long some_state = 0;
+ bufp->code = KeyTranslate (kchr_ptr, new_keycode,
+ &some_state) & 0xff;
+ }
+ else
+ bufp->code = er.message & charCodeMask;
+ bufp->kind = ascii_keystroke;
+ }
+ }
+
+ /* If variable mac-convert-keyboard-input-to-latin-1 is non-nil,
+ convert non-ASCII characters typed at the Mac keyboard
+ (presumed to be in the Mac Roman encoding) to iso-latin-1
+ encoding before they are passed to Emacs. This enables the
+ Mac keyboard to be used to enter non-ASCII iso-latin-1
+ characters directly. */
+ if (mac_keyboard_text_encoding != kTextEncodingMacRoman
+ && bufp->kind == ascii_keystroke && bufp->code >= 128)
+ {
+ static TECObjectRef converter = NULL;
+ OSStatus the_err = noErr;
+ OSStatus convert_status = noErr;
+
+ if (converter == NULL)
+ {
+ the_err = TECCreateConverter (&converter,
+ kTextEncodingMacRoman,
+ mac_keyboard_text_encoding);
+ current_mac_keyboard_text_encoding
+ = mac_keyboard_text_encoding;
+ }
+ else if (mac_keyboard_text_encoding
+ != current_mac_keyboard_text_encoding)
+ {
+ /* Free the converter for the current encoding before
+ creating a new one. */
+ TECDisposeConverter (converter);
+ the_err = TECCreateConverter (&converter,
+ kTextEncodingMacRoman,
+ mac_keyboard_text_encoding);
+ current_mac_keyboard_text_encoding
+ = mac_keyboard_text_encoding;
+ }
+
+ if (the_err == noErr)
+ {
+ unsigned char ch = bufp->code;
+ ByteCount actual_input_length, actual_output_length;
+ unsigned char outch;
+
+ convert_status = TECConvertText (converter, &ch, 1,
+ &actual_input_length,
+ &outch, 1,
+ &actual_output_length);
+ if (convert_status == noErr
+ && actual_input_length == 1
+ && actual_output_length == 1)
+ bufp->code = outch;
+ }
+ }
+
+ the_modifiers = 0;
+ if (er.modifiers & shiftKey)
+ the_modifiers |= shift_modifier;
+ if (er.modifiers & controlKey)
+ the_modifiers |= ctrl_modifier;
+ /* use option or command key as meta depending on value of
+ mac-command-key-is-meta */
+ if (er.modifiers
+ & (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
+ the_modifiers |= meta_modifier;
+ bufp->modifiers = the_modifiers;
+
+ {
+ mac_output *mwp = (mac_output *) GetWRefCon (FrontWindow ());
+ XSETFRAME (bufp->frame_or_window, mwp->mFP);
+ }
+
+ bufp->timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
+
+ count++;
+ bufp++;
+ numchars--;
+ break;
+
+ case kHighLevelEvent:
+ drag_and_drop_file_list = Qnil;
+
+ AEProcessAppleEvent(&er);
+
+ /* Build a drag_n_drop type event as is done in
+ constuct_drag_n_drop in w32term.c. */
+ if (!NILP (drag_and_drop_file_list))
+ {
+ struct frame *f;
+ WindowPtr wp;
+ Lisp_Object frame;
+
+ wp = FrontWindow ();
+ if (!wp)
+ f = NULL;
+ else
+ f = ((mac_output *) GetWRefCon (wp))->mFP;
+
+ bufp->kind = drag_n_drop;
+ bufp->code = 0;
+ bufp->timestamp = er.when * (1000 / 60);
+ /* ticks to milliseconds */
+ bufp->modifiers = 0;
+
+ XSETINT (bufp->x, 0);
+ XSETINT (bufp->y, 0);
+
+ XSETFRAME (frame, f);
+ bufp->frame_or_window = Fcons (frame, drag_and_drop_file_list);
+
+ /* Regardless of whether Emacs was suspended or in the
+ foreground, ask it to redraw its entire screen.
+ Otherwise parts of the screen can be left in an
+ inconsistent state. */
+ if (wp)
+#if TARGET_API_MAC_CARBON
+ {
+ Rect r;
+
+ GetWindowPortBounds (wp, &r);
+ InvalWindowRect (wp, &r);
+ }
+#else /* not TARGET_API_MAC_CARBON */
+ InvalRect (&(wp->portRect));
+#endif /* not TARGET_API_MAC_CARBON */
+
+ count++;
+ bufp++;
+ numchars--;
+ }
+
+ default:
+ break;
+ }
+
+ /* If the focus was just given to an autoraising frame,
+ raise it now. */
+ /* ??? This ought to be able to handle more than one such frame. */
+ if (pending_autoraise_frame)
+ {
+ x_raise_frame (pending_autoraise_frame);
+ pending_autoraise_frame = 0;
+ }
+
+#if !TARGET_API_MAC_CARBON
+ check_alarm (); /* simulate the handling of a SIGALRM */
+#endif
+
+ {
+ static Point old_mouse_pos = { -1, -1 };
+
+ if (app_is_suspended)
+ {
+ old_mouse_pos.h = -1;
+ old_mouse_pos.v = -1;
+ }
+ else
+ {
+ Point mouse_pos;
+ WindowPtr wp;
+ struct frame *f;
+ Lisp_Object bar;
+ struct scroll_bar *sb;
+
+ wp = FrontWindow ();
+ if (is_emacs_window (wp))
+ {
+ f = ((mac_output *) GetWRefCon (wp))->mFP;
+
+#if TARGET_API_MAC_CARBON
+ SetPort (GetWindowPort (wp));
+#else
+ SetPort (wp);
+#endif
+
+ GetMouse (&mouse_pos);
+
+ if (!EqualPt (mouse_pos, old_mouse_pos))
+ {
+ if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
+ && tracked_scroll_bar)
+ x_scroll_bar_note_movement (tracked_scroll_bar,
+ mouse_pos.v
+ - XINT (tracked_scroll_bar->top),
+ TickCount() * (1000 / 60));
+ else
+ note_mouse_movement (f, &mouse_pos);
+
+ old_mouse_pos = mouse_pos;
+ }
+ }
+ }
+ }
+
+ UNBLOCK_INPUT;
+
+ return count;
+}
+
+
+/* Need to override CodeWarrior's input function so no conversion is
+ done on newlines Otherwise compiled functions in .elc files will be
+ read incorrectly. Defined in ...:MSL C:MSL
+ Common:Source:buffer_io.c. */
+#ifdef __MWERKS__
+void
+__convert_to_newlines (unsigned char * p, size_t * n)
+{
+#pragma unused(p,n)
+}
+
+void
+__convert_from_newlines (unsigned char * p, size_t * n)
+{
+#pragma unused(p,n)
+}
+#endif
+
+
+/* Initialize the struct pointed to by MW to represent a new COLS x
+ ROWS Macintosh window, using font with name FONTNAME and size
+ FONTSIZE. */
+void
+NewMacWindow (FRAME_PTR fp)
+{
+ mac_output *mwp;
+#if TARGET_API_MAC_CARBON
+ static int making_terminal_window = 0;
+#else
+ static int making_terminal_window = 1;
+#endif
+
+ mwp = fp->output_data.mac;
+
+ if (making_terminal_window)
+ {
+ if (!(mwp->mWP = GetNewCWindow (TERM_WINDOW_RESOURCE, NULL,
+ (WindowPtr) -1)))
+ abort ();
+ making_terminal_window = 0;
+ }
+ else
+ if (!(mwp->mWP = GetNewCWindow (WINDOW_RESOURCE, NULL, (WindowPtr) -1)))
+ abort ();
+
+
+ SetWRefCon (mwp->mWP, (long) mwp);
+ /* so that update events can find this mac_output struct */
+ mwp->mFP = fp; /* point back to emacs frame */
+
+#if TARGET_API_MAC_CARBON
+ SetPort (GetWindowPort (mwp->mWP));
+#else
+ SetPort (mwp->mWP);
+#endif
+
+ mwp->fontset = -1;
+
+ SizeWindow (mwp->mWP, mwp->pixel_width, mwp->pixel_height, false);
+ ShowWindow (mwp->mWP);
+
+}
+
+
+void make_mac_frame (struct frame *f)
+{
+ FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
+ FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
+
+ NewMacWindow(f);
+ FRAME_BACKGROUND_PIXEL (f) = 0xffffff;
+ FRAME_FOREGROUND_PIXEL (f) = 0;
+
+ f->output_data.mac->cursor_pixel = 0;
+ f->output_data.mac->border_pixel = 0x00ff00;
+ f->output_data.mac->mouse_pixel = 0xff00ff;
+ f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
+
+ f->output_data.mac->desired_cursor = FILLED_BOX_CURSOR;
+
+ f->output_data.mac->fontset = -1;
+ f->output_data.mac->scroll_bar_foreground_pixel = -1;
+ f->output_data.mac->scroll_bar_background_pixel = -1;
+ f->output_data.mac->left_pos = 4;
+ f->output_data.mac->top_pos = 4;
+ f->output_data.mac->border_width = 0;
+ f->output_data.mac->explicit_parent = 0;
+
+ f->output_data.mac->internal_border_width = 0;
+
+ f->output_method = output_mac;
+
+ f->auto_raise = 1;
+ f->auto_lower = 1;
+
+ f->new_width = 0;
+ f->new_height = 0;
+}
+
+void make_mac_terminal_frame (struct frame *f)
+{
+ Lisp_Object frame;
+
+ XSETFRAME (frame, f);
+
+ f->output_method = output_mac;
+ f->output_data.mac = (struct mac_output *)
+ xmalloc (sizeof (struct mac_output));
+ bzero (f->output_data.mac, sizeof (struct mac_output));
+ f->output_data.mac->fontset = -1;
+ f->output_data.mac->scroll_bar_foreground_pixel = -1;
+ f->output_data.mac->scroll_bar_background_pixel = -1;
+
+ XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
+
+ f->width = 96;
+ f->height = 4;
+
+ make_mac_frame (f);
+
+ x_make_gc (f);
+
+ /* Need to be initialized for unshow_buffer in window.c. */
+ selected_window = f->selected_window;
+
+ Fmodify_frame_parameters (frame,
+ Fcons (Fcons (Qfont,
+ build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
+ Fmodify_frame_parameters (frame,
+ Fcons (Fcons (Qforeground_color,
+ build_string ("black")), Qnil));
+ Fmodify_frame_parameters (frame,
+ Fcons (Fcons (Qbackground_color,
+ build_string ("white")), Qnil));
+}
+
+\f
+/***********************************************************************
+ Initialization
+ ***********************************************************************/
+
+#ifdef USE_X_TOOLKIT
+static XrmOptionDescRec emacs_options[] = {
+ {"-geometry", ".geometry", XrmoptionSepArg, NULL},
+ {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
+
+ {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
+ XrmoptionSepArg, NULL},
+ {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
+
+ {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
+ {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
+ {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
+ {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
+ {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
+ {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
+ {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
+};
+#endif /* USE_X_TOOLKIT */
+
+#ifdef MULTI_KBOARD
+/* Test whether two display-name strings agree up to the dot that separates
+ the screen number from the server number. */
+static int
+same_x_server (name1, name2)
+ char *name1, *name2;
+{
+ int seen_colon = 0;
+ unsigned char *system_name = XSTRING (Vsystem_name)->data;
+ int system_name_length = strlen (system_name);
+ int length_until_period = 0;
+
+ while (system_name[length_until_period] != 0
+ && system_name[length_until_period] != '.')
+ length_until_period++;
+
+ /* Treat `unix' like an empty host name. */
+ if (! strncmp (name1, "unix:", 5))
+ name1 += 4;
+ if (! strncmp (name2, "unix:", 5))
+ name2 += 4;
+ /* Treat this host's name like an empty host name. */
+ if (! strncmp (name1, system_name, system_name_length)
+ && name1[system_name_length] == ':')
+ name1 += system_name_length;
+ if (! strncmp (name2, system_name, system_name_length)
+ && name2[system_name_length] == ':')
+ name2 += system_name_length;
+ /* Treat this host's domainless name like an empty host name. */
+ if (! strncmp (name1, system_name, length_until_period)
+ && name1[length_until_period] == ':')
+ name1 += length_until_period;
+ if (! strncmp (name2, system_name, length_until_period)
+ && name2[length_until_period] == ':')
+ name2 += length_until_period;
+
+ for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
+ {
+ if (*name1 == ':')
+ seen_colon++;
+ if (seen_colon && *name1 == '.')
+ return 1;
+ }
+ return (seen_colon
+ && (*name1 == '.' || *name1 == '\0')
+ && (*name2 == '.' || *name2 == '\0'));
+}
+#endif
+
+int mac_initialized = 0;
+
+void
+mac_initialize_display_info ()
+{
+ struct mac_display_info *dpyinfo = &one_mac_display_info;
+ GDHandle main_device_handle;
+
+ bzero (dpyinfo, sizeof (*dpyinfo));
+
+ /* Put it on x_display_name_list. */
+ x_display_name_list = Fcons (Fcons (build_string ("Mac"), Qnil),
+ x_display_name_list);
+ dpyinfo->name_list_element = XCAR (x_display_name_list);
+
+#if 0
+ dpyinfo->mac_id_name
+ = (char *) xmalloc (XSTRING (Vinvocation_name)->size
+ + XSTRING (Vsystem_name)->size
+ + 2);
+ sprintf (dpyinfo->mac_id_name, "%s@%s",
+ XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
+#else
+ dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
+ strcpy (dpyinfo->mac_id_name, "Mac Display");
+#endif
+
+ main_device_handle = LMGetMainDevice();
+
+ dpyinfo->reference_count = 0;
+ dpyinfo->resx = 75.0;
+ dpyinfo->resy = 75.0;
+ dpyinfo->n_planes = 1;
+ dpyinfo->n_cbits = 16;
+ dpyinfo->height = (**main_device_handle).gdRect.bottom;
+ dpyinfo->width = (**main_device_handle).gdRect.right;
+ dpyinfo->grabbed = 0;
+ dpyinfo->root_window = NULL;
+
+ dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
+ dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
+ dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
+ dpyinfo->mouse_face_window = Qnil;
+}
+
+struct mac_display_info *
+mac_term_init (display_name, xrm_option, resource_name)
+ Lisp_Object display_name;
+ char *xrm_option;
+ char *resource_name;
+{
+ struct mac_display_info *dpyinfo;
+ GDHandle main_device_handle;
+
+ if (!mac_initialized)
+ {
+ mac_initialize ();
+ mac_initialized = 1;
+ }
+
+ mac_initialize_display_info (display_name);
+
+ dpyinfo = &one_mac_display_info;
+
+ main_device_handle = LMGetMainDevice();
+
+ dpyinfo->height = (**main_device_handle).gdRect.bottom;
+ dpyinfo->width = (**main_device_handle).gdRect.right;
+
+ return dpyinfo;
+}
+\f
+/* Set up use of X before we make the first connection. */
+
+static struct redisplay_interface x_redisplay_interface =
+{
+ x_produce_glyphs,
+ x_write_glyphs,
+ x_insert_glyphs,
+ x_clear_end_of_line,
+ x_scroll_run,
+ x_after_update_window_line,
+ x_update_window_begin,
+ x_update_window_end,
+ XTcursor_to,
+ x_flush,
+ x_clear_mouse_face,
+ x_get_glyph_overhangs,
+ x_fix_overlapping_area
+};
+
+void
+mac_initialize ()
+{
+ rif = &x_redisplay_interface;
+
+ clear_frame_hook = x_clear_frame;
+ ins_del_lines_hook = x_ins_del_lines;
+ delete_glyphs_hook = x_delete_glyphs;
+ ring_bell_hook = XTring_bell;
+ reset_terminal_modes_hook = XTreset_terminal_modes;
+ set_terminal_modes_hook = XTset_terminal_modes;
+ update_begin_hook = x_update_begin;
+ update_end_hook = x_update_end;
+ set_terminal_window_hook = XTset_terminal_window;
+ read_socket_hook = XTread_socket;
+ frame_up_to_date_hook = XTframe_up_to_date;
+ mouse_position_hook = XTmouse_position;
+ frame_rehighlight_hook = XTframe_rehighlight;
+ frame_raise_lower_hook = XTframe_raise_lower;
+
+ set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
+ condemn_scroll_bars_hook = XTcondemn_scroll_bars;
+ redeem_scroll_bar_hook = XTredeem_scroll_bar;
+ judge_scroll_bars_hook = XTjudge_scroll_bars;
+
+ estimate_mode_line_height_hook = x_estimate_mode_line_height;
+
+ scroll_region_ok = 1; /* we'll scroll partial frames */
+ char_ins_del_ok = 1;
+ line_ins_del_ok = 1; /* we'll just blt 'em */
+ fast_clear_end_of_line = 1; /* X does this well */
+ memory_below_frame = 0; /* we don't remember what scrolls
+ off the bottom */
+ baud_rate = 19200;
+
+ x_noop_count = 0;
+ last_tool_bar_item = -1;
+ any_help_event_p = 0;
+
+ /* Try to use interrupt input; if we can't, then start polling. */
+ Fset_input_mode (Qt, Qnil, Qt, Qnil);
+
+#ifdef USE_X_TOOLKIT
+ XtToolkitInitialize ();
+ Xt_app_con = XtCreateApplicationContext ();
+ XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
+
+ /* Install an asynchronous timer that processes Xt timeout events
+ every 0.1s. This is necessary because some widget sets use
+ timeouts internally, for example the LessTif menu bar, or the
+ Xaw3d scroll bar. When Xt timouts aren't processed, these
+ widgets don't behave normally. */
+ {
+ EMACS_TIME interval;
+ EMACS_SET_SECS_USECS (interval, 0, 100000);
+ start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
+ }
+#endif
+
+#if USE_TOOLKIT_SCROLL_BARS
+ xaw3d_arrow_scroll = False;
+ xaw3d_pick_top = True;
+#endif
+
+#if 0
+ /* Note that there is no real way portable across R3/R4 to get the
+ original error handler. */
+ XSetErrorHandler (x_error_handler);
+ XSetIOErrorHandler (x_io_error_quitter);
+
+ /* Disable Window Change signals; they are handled by X events. */
+#ifdef SIGWINCH
+ signal (SIGWINCH, SIG_DFL);
+#endif /* ! defined (SIGWINCH) */
+
+ signal (SIGPIPE, x_connection_signal);
+#endif
+
+ mac_initialize_display_info ();
+}
+
+
+void
+syms_of_macterm ()
+{
+#if 0
+ staticpro (&x_error_message_string);
+ x_error_message_string = Qnil;
+#endif
+
+ staticpro (&x_display_name_list);
+ x_display_name_list = Qnil;
+
+ staticpro (&last_mouse_scroll_bar);
+ last_mouse_scroll_bar = Qnil;
+
+ staticpro (&Qvendor_specific_keysyms);
+ Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
+
+ staticpro (&last_mouse_press_frame);
+ last_mouse_press_frame = Qnil;
+
+ Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
+ staticpro (&Qmac_ready_for_drag_n_drop);
+
+ help_echo = Qnil;
+ staticpro (&help_echo);
+ help_echo_object = Qnil;
+ staticpro (&help_echo_object);
+ help_echo_window = Qnil;
+ staticpro (&help_echo_window);
+ previous_help_echo = Qnil;
+ staticpro (&previous_help_echo);
+ help_echo_pos = -1;
+
+ DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
+ doc: /* *Non-nil means autoselect window with mouse pointer. */);
+ x_autoselect_window_p = 0;
+
+ DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
+ doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
+For example, if a block cursor is over a tab, it will be drawn as
+wide as that tab on the display. */);
+ x_stretch_cursor_p = 0;
+
+#if 0 /* TODO: Setting underline position from font properties. */
+ DEFVAR_BOOL ("x-use-underline-position-properties",
+ &x_use_underline_position_properties,
+ doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
+nil means ignore them. If you encounter fonts with bogus
+UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
+to 4.1, set this to nil. */);
+ x_use_underline_position_properties = 1;
+#endif
+
+ DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
+ doc: /* If not nil, Emacs uses toolkit scroll bars. */);
+ Vx_toolkit_scroll_bars = Qt;
+
+ staticpro (&last_mouse_motion_frame);
+ last_mouse_motion_frame = Qnil;
+
+ DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
+ doc: /* Non-nil means that the command key is used as the Emacs meta key.
+Otherwise the option key is used. */);
+ Vmac_command_key_is_meta = Qt;
+
+ DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
+ doc: /* One of the Text Encoding Base constant values defined in the
+Basic Text Constants section of Inside Macintosh - Text Encoding
+Conversion Manager. Its value determines the encoding characters
+typed at the Mac keyboard (presumed to be in the MacRoman encoding)
+will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
+its default value, no conversion takes place. If it is set to
+kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
+characters typed on Mac keyboard are first converted into the
+ISO Latin-1 or ISO Latin-2 encoding, respectively before being
+passed to Emacs. Together with Emacs's set-keyboard-coding-system
+command, this enables the Mac keyboard to be used to enter non-ASCII
+characters directly. */);
+ mac_keyboard_text_encoding = kTextEncodingMacRoman;
+}
--- /dev/null
+/* Display module for Mac OS.
+ Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Contributed by Andrew Choi (akochoi@mac.com). */
+
+#include "macgui.h"
+#include "frame.h"
+
+/* The class of this X application. */
+#define EMACS_CLASS "Emacs"
+
+#define RGB_TO_ULONG(r, g, b) (((r) << 16) | ((g) << 8) | (b))
+
+#define RED_FROM_ULONG(color) ((color) >> 16)
+#define GREEN_FROM_ULONG(color) (((color) >> 8) & 0xff)
+#define BLUE_FROM_ULONG(color) ((color) & 0xff)
+
+#define BLACK_PIX_DEFAULT(f) RGB_TO_ULONG(0,0,0)
+#define WHITE_PIX_DEFAULT(f) RGB_TO_ULONG(255,255,255)
+
+#define FONT_WIDTH(f) ((f)->max_bounds.width)
+#define FONT_HEIGHT(f) ((f)->ascent + (f)->descent)
+#define FONT_BASE(f) ((f)->ascent)
+#define FONT_DESCENT(f) ((f)->descent)
+
+#define FONT_MAX_WIDTH(f) FONT_WIDTH(f) /* fix later */
+
+enum text_cursor_kinds {
+ NO_CURSOR = -1,
+ FILLED_BOX_CURSOR,
+ HOLLOW_BOX_CURSOR,
+ BAR_CURSOR
+};
+
+/* Structure recording bitmaps and reference count.
+ If REFCOUNT is 0 then this record is free to be reused. */
+
+struct mac_bitmap_record
+{
+ char *bitmap_data;
+ int refcount;
+ int height, width;
+};
+
+
+/* For each display (currently only one on mac), we have a structure that
+ records information about it. */
+
+struct mac_display_info
+{
+ /* Chain of all mac_display_info structures. */
+ struct mac_display_info *next;
+
+ /* This is a cons cell of the form (NAME . FONT-LIST-CACHE).
+ The same cons cell also appears in x_display_name_list. */
+ Lisp_Object name_list_element;
+
+ /* Number of frames that are on this display. */
+ int reference_count;
+
+ /* Dots per inch of the screen. */
+ double resx, resy;
+
+ /* Number of planes on this screen. */
+ int n_planes;
+
+ /* Number of bits per pixel on this screen. */
+ int n_cbits;
+
+ /* Dimensions of this screen. */
+ int height, width;
+#if 0
+ int height_in,width_in;
+#endif
+
+ /* Mask of things that cause the mouse to be grabbed. */
+ int grabbed;
+
+#if 0
+ /* Emacs bitmap-id of the default icon bitmap for this frame.
+ Or -1 if none has been allocated yet. */
+ int icon_bitmap_id;
+
+#endif
+ /* The root window of this screen. */
+ Window root_window;
+
+ /* The cursor to use for vertical scroll bars. */
+ struct Cursor *vertical_scroll_bar_cursor;
+
+#if 0
+ /* color palette information. */
+ int has_palette;
+ struct w32_palette_entry * color_list;
+ unsigned num_colors;
+ HPALETTE palette;
+
+ /* deferred action flags checked when starting frame update. */
+ int regen_palette;
+
+ /* Keystroke that has been faked by Emacs and will be ignored when
+ received; value is reset after key is received. */
+ int faked_key;
+
+#endif
+
+ /* A table of all the fonts we have already loaded. */
+ struct font_info *font_table;
+
+ /* The current capacity of font_table. */
+ int font_table_size;
+
+ /* The number of fonts actually stored in the font table.
+ font_table[n] is used and valid iff 0 <= n < n_fonts. 0 <=
+ n_fonts <= font_table_size. and font_table[i].name != 0. */
+ int n_fonts;
+
+ /* Minimum width over all characters in all fonts in font_table. */
+ int smallest_char_width;
+
+ /* Minimum font height over all fonts in font_table. */
+ int smallest_font_height;
+
+ /* Reusable Graphics Context for drawing a cursor in a non-default face. */
+ XGCValues *scratch_cursor_gc;
+
+ /* These variables describe the range of text currently shown in its
+ mouse-face, together with the window they apply to. As long as
+ the mouse stays within this range, we need not redraw anything on
+ its account. Rows and columns are glyph matrix positions in
+ MOUSE_FACE_WINDOW. */
+ int mouse_face_beg_row, mouse_face_beg_col;
+ int mouse_face_beg_x, mouse_face_beg_y;
+ int mouse_face_end_row, mouse_face_end_col;
+ int mouse_face_end_x, mouse_face_end_y;
+ int mouse_face_past_end;
+ Lisp_Object mouse_face_window;
+ int mouse_face_face_id;
+ Lisp_Object mouse_face_overlay;
+
+ /* 1 if a mouse motion event came and we didn't handle it right away because
+ gc was in progress. */
+ int mouse_face_deferred_gc;
+
+ /* FRAME and X, Y position of mouse when last checked for
+ highlighting. X and Y can be negative or out of range for the frame. */
+ struct frame *mouse_face_mouse_frame;
+
+ int mouse_face_mouse_x, mouse_face_mouse_y;
+
+ /* Nonzero means defer mouse-motion highlighting. */
+ int mouse_face_defer;
+
+ /* Nonzero means that the mouse highlight should not be shown. */
+ int mouse_face_hidden;
+
+ int mouse_face_image_state;
+
+ char *mac_id_name;
+
+ /* Pointer to bitmap records. */
+ struct mac_bitmap_record *bitmaps;
+
+ /* Allocated size of bitmaps field. */
+ int bitmaps_size;
+
+ /* Last used bitmap index. */
+ int bitmaps_last;
+
+ /* The frame (if any) which has the window that has keyboard focus.
+ Zero if none. This is examined by Ffocus_frame in w32fns.c. Note
+ that a mere EnterNotify event can set this; if you need to know the
+ last frame specified in a FocusIn or FocusOut event, use
+ w32_focus_event_frame. */
+ struct frame *x_focus_frame;
+
+ /* The last frame mentioned in a FocusIn or FocusOut event. This is
+ separate from w32_focus_frame, because whether or not LeaveNotify
+ events cause us to lose focus depends on whether or not we have
+ received a FocusIn event for it. */
+ struct frame *x_focus_event_frame;
+
+ /* The frame which currently has the visual highlight, and should get
+ keyboard input (other sorts of input have the frame encoded in the
+ event). It points to the focus frame's selected window's
+ frame. It differs from w32_focus_frame when we're using a global
+ minibuffer. */
+ struct frame *x_highlight_frame;
+
+ /* Cache of images. */
+ struct image_cache *image_cache;
+};
+
+#define x_display_info mac_display_info
+
+/* This is a chain of structures for all the X displays currently in use. */
+extern struct x_display_info *x_display_list;
+
+/* This is a chain of structures for all the displays currently in use. */
+extern struct mac_display_info one_mac_display_info;
+
+/* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
+ one for each element of x_display_list and in the same order.
+ NAME is the name of the frame.
+ FONT-LIST-CACHE records previous values returned by x-list-fonts. */
+extern Lisp_Object x_display_name_list;
+
+/* A flag to control how to display unibyte 8-bit character. */
+extern int unibyte_display_via_language_environment;
+
+extern struct x_display_info *x_display_info_for_display P_ ((Display *));
+extern struct x_display_info *x_display_info_for_name P_ ((Lisp_Object));
+
+extern struct mac_display_info *mac_term_init ();
+
+/* When Emacs uses a tty window, tty_display in frame.c points to an
+ x_output struct . */
+struct x_output
+{
+ unsigned long background_pixel;
+ unsigned long foreground_pixel;
+};
+
+/* The collection of data describing a window on the Mac. */
+struct mac_output {
+ /* Placeholder for things accessed through output_data.x. Must
+ appear first. */
+ struct x_output x_compatible;
+
+ /* Menubar "widget" handle. */
+ int menubar_widget;
+
+ Window mWP; /* pointer to QuickDraw window */
+ FRAME_PTR mFP; /* points back to the frame struct */
+
+#if 0
+ int mNumCols; /* number of characters per column */
+ int mNumRows; /* number of characters per row */
+ int mLineHeight; /* height of one line of text in pixels */
+ int mCharWidth; /* width of one character in pixels */
+ int mHomeX; /* X pixel coordinate of lower left
+ corner of character at (0, 0) */
+ int mHomeY; /* Y pixel coordinate of lower left
+ corner of character at (0, 0) */
+ int mHighlight; /* current highlight state (0 = off). */
+ int mTermWinSize; /* num of lines from top of window
+ affected by ins_del_lines; set by
+ set_terminal_window. */
+#endif /* 0 */
+
+#if 0
+ /* stuffs used by xfaces.c */
+ struct face **param_faces;
+ int n_param_faces;
+ struct face **computed_faces;
+ int n_computed_faces;
+ int size_computed_faces;
+#endif
+
+ /* Position of the Mac window (x and y offsets in global coordinates). */
+ int left_pos;
+ int top_pos;
+
+ /* Border width of the W32 window as known by the window system. */
+ int border_width;
+
+ /* Size of the W32 window in pixels. */
+ int pixel_height, pixel_width;
+
+ /* Height of a line, in pixels. */
+ int line_height;
+
+ /* Here are the Graphics Contexts for the default font. */
+ GC normal_gc; /* Normal video */
+ GC reverse_gc; /* Reverse video */
+ GC cursor_gc; /* cursor drawing */
+
+ /* Width of the internal border. This is a line of background color
+ just inside the window's border. When the frame is selected,
+ a highlighting is displayed inside the internal border. */
+ int internal_border_width;
+
+ /* The window used for this frame.
+ May be zero while the frame object is being created
+ and the window has not yet been created. */
+ Window window_desc;
+
+ /* The window that is the parent of this window.
+ Usually this is a window that was made by the window manager,
+ but it can be the root window, and it can be explicitly specified
+ (see the explicit_parent field, below). */
+ Window parent_desc;
+
+ /* Default ASCII font of this frame. */
+ XFontStruct *font;
+
+ /* The baseline offset of the default ASCII font. */
+ int baseline_offset;
+
+ /* If a fontset is specified for this frame instead of font, this
+ value contains an ID of the fontset, else -1. */
+ int fontset;
+
+ /* Pixel values used for various purposes.
+ border_pixel may be -1 meaning use a gray tile. */
+ unsigned long cursor_pixel;
+ unsigned long border_pixel;
+ unsigned long mouse_pixel;
+ unsigned long cursor_foreground_pixel;
+
+ /* Foreground color for scroll bars. A value of -1 means use the
+ default (black for non-toolkit scroll bars). */
+ unsigned long scroll_bar_foreground_pixel;
+
+ /* Background color for scroll bars. A value of -1 means use the
+ default (background color of the frame for non-toolkit scroll
+ bars). */
+ unsigned long scroll_bar_background_pixel;
+
+ /* Descriptor for the cursor in use for this window. */
+ struct Cursor *text_cursor;
+ struct Cursor *nontext_cursor;
+ struct Cursor *modeline_cursor;
+ struct Cursor *cross_cursor;
+ struct Cursor *hourglass_cursor;
+#if 0
+ /* Window whose cursor is hourglass_cursor. This window is temporarily
+ mapped to display a hourglass-cursor. */
+ Window hourglass_window;
+
+ /* Non-zero means hourglass cursor is currently displayed. */
+ unsigned hourglass_p : 1;
+
+ /* Flag to set when the window needs to be completely repainted. */
+ int needs_exposure;
+
+#endif
+
+ /* What kind of text cursor is drawn in this window right now?
+ (If there is no cursor (phys_cursor_x < 0), then this means nothing.) */
+ enum text_cursor_kinds current_cursor;
+
+ /* What kind of text cursor should we draw in the future?
+ This should always be filled_box_cursor or bar_cursor. */
+ enum text_cursor_kinds desired_cursor;
+
+ /* Width of bar cursor (if we are using that). */
+ int cursor_width;
+
+#if 0
+ DWORD dwStyle;
+#endif
+
+ /* The size of the extra width currently allotted for vertical
+ scroll bars, in pixels. */
+ int vertical_scroll_bar_extra;
+
+ /* The extra width currently allotted for the areas in which
+ truncation marks, continuation marks, and overlay arrows are
+ displayed. */
+ int left_fringe_width, right_fringe_width;
+ int fringe_cols, fringes_extra;
+
+ /* This is the gravity value for the specified window position. */
+ int win_gravity;
+
+ /* The geometry flags for this window. */
+ int size_hint_flags;
+
+ /* This is the Emacs structure for the display this frame is on. */
+ /* struct w32_display_info *display_info; */
+
+ /* Nonzero means our parent is another application's window
+ and was explicitly specified. */
+ char explicit_parent;
+
+ /* Nonzero means tried already to make this frame visible. */
+ char asked_for_visible;
+
+ /* Nonzero means menubar is currently active. */
+ char menubar_active;
+
+ /* Nonzero means a menu command is being processed. */
+ char menu_command_in_progress;
+
+ /* Nonzero means menubar is about to become active, but should be
+ brought up to date first. */
+ volatile char pending_menu_activation;
+
+ /* Relief GCs, colors etc. */
+ struct relief
+ {
+ XGCValues *gc;
+ unsigned long pixel;
+ int allocated_p;
+ }
+ black_relief, white_relief;
+
+ /* The background for which the above relief GCs were set up.
+ They are changed only when a different background is involved. */
+ unsigned long relief_background;
+};
+
+typedef struct mac_output mac_output;
+
+/* Return the Mac window used for displaying data in frame F. */
+#define FRAME_MAC_WINDOW(f) ((f)->output_data.mac->mWP)
+
+#define FRAME_FOREGROUND_PIXEL(f) ((f)->output_data.x->foreground_pixel)
+#define FRAME_BACKGROUND_PIXEL(f) ((f)->output_data.x->background_pixel)
+
+#define FRAME_FONT(f) ((f)->output_data.mac->font)
+#define FRAME_FONTSET(f) ((f)->output_data.mac->fontset)
+
+#undef FRAME_INTERNAL_BORDER_WIDTH
+#define FRAME_INTERNAL_BORDER_WIDTH(f) \
+ ((f)->output_data.mac->internal_border_width)
+#define FRAME_LINE_HEIGHT(f) ((f)->output_data.mac->line_height)
+/* Width of the default font of frame F. Must be defined by each
+ terminal specific header. */
+#define FRAME_DEFAULT_FONT_WIDTH(F) FONT_WIDTH (FRAME_FONT (F))
+#define FRAME_BASELINE_OFFSET(f) ((f)->output_data.mac->baseline_offset)
+
+/* This gives the w32_display_info structure for the display F is on. */
+#define FRAME_MAC_DISPLAY_INFO(f) (&one_mac_display_info)
+#define FRAME_X_DISPLAY_INFO(f) (&one_mac_display_info)
+
+/* This is the `Display *' which frame F is on. */
+#define FRAME_MAC_DISPLAY(f) (0)
+
+/* This is the 'font_info *' which frame F has. */
+#define FRAME_MAC_FONT_TABLE(f) (FRAME_MAC_DISPLAY_INFO (f)->font_table)
+
+/* These two really ought to be called FRAME_PIXEL_{WIDTH,HEIGHT}. */
+#define PIXEL_WIDTH(f) ((f)->output_data.mac->pixel_width)
+#define PIXEL_HEIGHT(f) ((f)->output_data.mac->pixel_height)
+
+#define FRAME_DESIRED_CURSOR(f) ((f)->output_data.mac->desired_cursor)
+
+/* Value is the smallest width of any character in any font on frame F. */
+
+#define FRAME_SMALLEST_CHAR_WIDTH(F) \
+ FRAME_MAC_DISPLAY_INFO(F)->smallest_char_width
+
+/* Value is the smallest height of any font on frame F. */
+
+#define FRAME_SMALLEST_FONT_HEIGHT(F) \
+ FRAME_MAC_DISPLAY_INFO(F)->smallest_font_height
+
+/* Return a pointer to the image cache of frame F. */
+
+#define FRAME_X_IMAGE_CACHE(F) FRAME_MAC_DISPLAY_INFO ((F))->image_cache
+
+\f
+/* Total width of fringes reserved for drawing truncation bitmaps,
+ continuation bitmaps and alike. The width is in canonical char
+ units of the frame. This must currently be the case because window
+ sizes aren't pixel values. If it weren't the case, we wouldn't be
+ able to split windows horizontally nicely. */
+
+#define FRAME_X_FRINGE_COLS(F) ((F)->output_data.mac->fringe_cols)
+
+/* Total width of fringes in pixels. */
+
+#define FRAME_X_FRINGE_WIDTH(F) ((F)->output_data.mac->fringes_extra)
+
+/* Pixel-width of the left and right fringe. */
+
+#define FRAME_X_LEFT_FRINGE_WIDTH(F) ((F)->output_data.mac->left_fringe_width)
+#define FRAME_X_RIGHT_FRINGE_WIDTH(F) ((F)->output_data.mac->right_fringe_width)
+
+
+\f
+/* Mac-specific scroll bar stuff. */
+
+/* We represent scroll bars as lisp vectors. This allows us to place
+ references to them in windows without worrying about whether we'll
+ end up with windows referring to dead scroll bars; the garbage
+ collector will free it when its time comes.
+
+ We use struct scroll_bar as a template for accessing fields of the
+ vector. */
+
+struct scroll_bar {
+
+ /* These fields are shared by all vectors. */
+ EMACS_INT size_from_Lisp_Vector_struct;
+ struct Lisp_Vector *next_from_Lisp_Vector_struct;
+
+ /* The window we're a scroll bar for. */
+ Lisp_Object window;
+
+ /* The next and previous in the chain of scroll bars in this frame. */
+ Lisp_Object next, prev;
+
+ /* The Mac control handle of this scroll bar. Since this is a full
+ 32-bit quantity, we store it split into two 32-bit values. */
+ Lisp_Object control_handle_low, control_handle_high;
+
+ /* The position and size of the scroll bar in pixels, relative to the
+ frame. */
+ Lisp_Object top, left, width, height;
+
+ /* The starting and ending positions of the handle, relative to the
+ handle area (i.e. zero is the top position, not
+ SCROLL_BAR_TOP_BORDER). If they're equal, that means the handle
+ hasn't been drawn yet.
+
+ These are not actually the locations where the beginning and end
+ are drawn; in order to keep handles from becoming invisible when
+ editing large files, we establish a minimum height by always
+ drawing handle bottoms VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
+ where they would be normally; the bottom and top are in a
+ different co-ordinate system. */
+ Lisp_Object start, end;
+
+ /* If the scroll bar handle is currently being dragged by the user,
+ this is the number of pixels from the top of the handle to the
+ place where the user grabbed it. If the handle isn't currently
+ being dragged, this is Qnil. */
+ Lisp_Object dragging;
+};
+
+/* The number of elements a vector holding a struct scroll_bar needs. */
+#define SCROLL_BAR_VEC_SIZE \
+ ((sizeof (struct scroll_bar) \
+ - sizeof (EMACS_INT) - sizeof (struct Lisp_Vector *)) \
+ / sizeof (Lisp_Object))
+
+/* Turning a lisp vector value into a pointer to a struct scroll_bar. */
+#define XSCROLL_BAR(vec) ((struct scroll_bar *) XVECTOR (vec))
+
+
+/* Building a 32-bit C integer from two 16-bit lisp integers. */
+#define SCROLL_BAR_PACK(low, high) (XINT (high) << 16 | XINT (low))
+
+/* Setting two lisp integers to the low and high words of a 32-bit C int. */
+#define SCROLL_BAR_UNPACK(low, high, int32) \
+ (XSETINT ((low), (int32) & 0xffff), \
+ XSETINT ((high), ((int32) >> 16) & 0xffff))
+
+
+/* Extract the Mac control handle of the scroll bar from a struct
+ scroll_bar. */
+#define SCROLL_BAR_CONTROL_HANDLE(ptr) \
+ ((ControlHandle) SCROLL_BAR_PACK ((ptr)->control_handle_low, \
+ (ptr)->control_handle_high))
+
+/* Store a Mac control handle in a struct scroll_bar. */
+#define SET_SCROLL_BAR_CONTROL_HANDLE(ptr, id) \
+ (SCROLL_BAR_UNPACK ((ptr)->control_handle_low, \
+ (ptr)->control_handle_high, (int) id))
+
+/* Return the inside width of a vertical scroll bar, given the outside
+ width. */
+#define VERTICAL_SCROLL_BAR_INSIDE_WIDTH(f,width) \
+ ((width) \
+ - VERTICAL_SCROLL_BAR_LEFT_BORDER \
+ - VERTICAL_SCROLL_BAR_RIGHT_BORDER \
+ - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2)
+
+/* Return the length of the rectangle within which the top of the
+ handle must stay. This isn't equivalent to the inside height,
+ because the scroll bar handle has a minimum height.
+
+ This is the real range of motion for the scroll bar, so when we're
+ scaling buffer positions to scroll bar positions, we use this, not
+ VERTICAL_SCROLL_BAR_INSIDE_HEIGHT. */
+#define VERTICAL_SCROLL_BAR_TOP_RANGE(f,height) \
+ (VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, height) \
+ - VERTICAL_SCROLL_BAR_MIN_HANDLE - UP_AND_DOWN_ARROWS)
+
+/* Return the inside height of vertical scroll bar, given the outside
+ height. See VERTICAL_SCROLL_BAR_TOP_RANGE too. */
+#define VERTICAL_SCROLL_BAR_INSIDE_HEIGHT(f,height) \
+ ((height) - VERTICAL_SCROLL_BAR_TOP_BORDER \
+ - VERTICAL_SCROLL_BAR_BOTTOM_BORDER)
+
+
+/* Border widths for scroll bars.
+
+ Scroll bar windows don't have any borders; their border width is
+ set to zero, and we redraw borders ourselves. This makes the code
+ a bit cleaner, since we don't have to convert between outside width
+ (used when relating to the rest of the screen) and inside width
+ (used when sizing and drawing the scroll bar window itself).
+
+ The handle moves up and down/back and forth in a rectangle inset
+ from the edges of the scroll bar. These are widths by which we
+ inset the handle boundaries from the scroll bar edges. */
+#define VERTICAL_SCROLL_BAR_LEFT_BORDER (0)
+#define VERTICAL_SCROLL_BAR_RIGHT_BORDER (0)
+#define VERTICAL_SCROLL_BAR_TOP_BORDER (0)
+#define VERTICAL_SCROLL_BAR_BOTTOM_BORDER (0)
+
+/* Minimum lengths for scroll bar handles, in pixels. */
+#define VERTICAL_SCROLL_BAR_MIN_HANDLE (16)
+
+/* Combined length of up and down arrow boxes in scroll bars, in pixels. */
+#define UP_AND_DOWN_ARROWS (32)
+
+/* Trimming off a few pixels from each side prevents
+ text from glomming up against the scroll bar */
+#define VERTICAL_SCROLL_BAR_WIDTH_TRIM (0)
+
+\f
+/* Manipulating pixel sizes and character sizes.
+ Knowledge of which factors affect the overall size of the window should
+ be hidden in these macros, if that's possible.
+
+ Return the upper/left pixel position of the character cell on frame F
+ at ROW/COL. */
+#define CHAR_TO_PIXEL_ROW(f, row) \
+ ((f)->output_data.mac->internal_border_width \
+ + (row) * (f)->output_data.mac->line_height)
+#define CHAR_TO_PIXEL_COL(f, col) \
+ ((f)->output_data.mac->internal_border_width \
+ + (col) * FONT_WIDTH ((f)->output_data.mac->font))
+
+/* Return the pixel width/height of frame F if it has
+ WIDTH columns/HEIGHT rows. */
+#define CHAR_TO_PIXEL_WIDTH(f, width) \
+ (CHAR_TO_PIXEL_COL (f, width) \
+ + (f)->output_data.mac->vertical_scroll_bar_extra \
+ + (f)->output_data.mac->fringes_extra \
+ + (f)->output_data.mac->internal_border_width)
+#define CHAR_TO_PIXEL_HEIGHT(f, height) \
+ (CHAR_TO_PIXEL_ROW (f, height) \
+ + (f)->output_data.mac->internal_border_width)
+
+
+/* Return the row/column (zero-based) of the character cell containing
+ the pixel on FRAME at ROW/COL. */
+#define PIXEL_TO_CHAR_ROW(f, row) \
+ (((row) - (f)->output_data.mac->internal_border_width) \
+ / (f)->output_data.mac->line_height)
+#define PIXEL_TO_CHAR_COL(f, col) \
+ (((col) - (f)->output_data.mac->internal_border_width) \
+ / FONT_WIDTH ((f)->output_data.mac->font))
+
+/* How many columns/rows of text can we fit in WIDTH/HEIGHT pixels on
+ frame F? */
+#define PIXEL_TO_CHAR_WIDTH(f, width) \
+ (PIXEL_TO_CHAR_COL (f, ((width) \
+ - (f)->output_data.mac->internal_border_width \
+ - (f)->output_data.mac->fringes_extra \
+ - (f)->output_data.mac->vertical_scroll_bar_extra)))
+#define PIXEL_TO_CHAR_HEIGHT(f, height) \
+ (PIXEL_TO_CHAR_ROW (f, ((height) \
+ - (f)->output_data.mac->internal_border_width)))
+
+struct frame * check_x_frame (Lisp_Object);
+
/* Qexit is declared and initialized in eval.c. */
+/* QCfamily is defined in xfaces.c. */
+extern Lisp_Object QCfamily;
+/* QCfilter is defined in keyboard.c. */
+extern Lisp_Object QCfilter;
+
/* a process object is a network connection when its childp field is neither
Qt nor Qnil but is instead a cons cell (HOSTNAME PORTNUM). */
SELECT_TYPE Atemp, Ctemp;
Atemp = input_wait_mask;
+#ifdef MAC_OSX
+ /* On Mac OS X, the SELECT system call always says input is
+ present (for reading) at stdin, even when none is. This
+ causes the the call to SELECT below to return 1 and
+ status_notify not to be called. As a result output of
+ subprocesses are incorrectly discarded. */
+ FD_CLR (0, &Atemp);
+#endif
Ctemp = connect_wait_mask;
EMACS_SET_SECS_USECS (timeout, 0, 0);
if ((select (max (max_process_desc, max_keyboard_desc) + 1,
--- /dev/null
+/* System description header file for Darwin (Mac OS X).
+ Copyright (C) 2001 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+
+/*
+ * Define symbols to identify the version of Unix this is.
+ * Define all the symbols that apply correctly.
+ */
+
+/* #define UNIPLUS */
+/* #define USG5 */
+/* #define USG */
+/* #define HPUX */
+/* #define UMAX */
+/* #define BSD4_1 */
+#define BSD4_2
+/* BSD4_3 and BSD4_4 are already defined in sys/param.h */
+/* #define BSD4_3 */
+/* #define BSD4_4 */
+#define BSD_SYSTEM
+/* #define VMS */
+
+/* MAC_OS is used to conditionally compile code common to both MAC_OS8
+ and MAC_OSX. */
+#ifdef MAC_OSX
+#define MAC_OS
+#endif
+
+/* SYSTEM_TYPE should indicate the kind of system you are using.
+ It sets the Lisp variable system-type. */
+
+#define SYSTEM_TYPE "darwin"
+
+/* NOMULTIPLEJOBS should be defined if your system's shell
+ does not have "job control" (the ability to stop a program,
+ run some other program, then continue the first one). */
+
+/* #define NOMULTIPLEJOBS */
+
+/* Emacs can read input using SIGIO and buffering characters itself,
+ or using CBREAK mode and making C-g cause SIGINT.
+ The choice is controlled by the variable interrupt_input.
+
+ Define INTERRUPT_INPUT to make interrupt_input = 1 the default (use SIGIO)
+
+ Emacs uses the presence or absence of the SIGIO and BROKEN_SIGIO macros
+ to indicate whether or not signal-driven I/O is possible. It uses
+ INTERRUPT_INPUT to decide whether to use it by default.
+
+ SIGIO can be used only on systems that implement it (4.2 and 4.3).
+ CBREAK mode has two disadvantages
+ 1) At least in 4.2, it is impossible to handle the Meta key properly.
+ I hear that in system V this problem does not exist.
+ 2) Control-G causes output to be discarded.
+ I do not know whether this can be fixed in system V.
+
+ Another method of doing input is planned but not implemented.
+ It would have Emacs fork off a separate process
+ to read the input and send it to the true Emacs process
+ through a pipe. */
+
+#define INTERRUPT_INPUT
+
+/* Letter to use in finding device name of first pty,
+ if system supports pty's. 'a' means it is /dev/ptya0 */
+
+#define FIRST_PTY_LETTER 'p'
+
+/*
+ * Define HAVE_TERMIOS if the system provides POSIX-style
+ * functions and macros for terminal control.
+ *
+ * Define HAVE_TERMIO if the system provides sysV-style ioctls
+ * for terminal control.
+ *
+ * Do not define both. HAVE_TERMIOS is preferred, if it is
+ * supported on your system.
+ */
+
+#define HAVE_TERMIOS
+/* #define HAVE_TERMIO */
+
+#define NO_TERMIO
+
+/*
+ * Define HAVE_PTYS if the system supports pty devices.
+ */
+
+#define HAVE_PTYS
+
+/*
+ * Define NONSYSTEM_DIR_LIBRARY to make Emacs emulate
+ * The 4.2 opendir, etc., library functions.
+ */
+
+/* #define NONSYSTEM_DIR_LIBRARY */
+
+/* Define this symbol if your system has the functions bcopy, etc. */
+
+#define BSTRING
+
+/* subprocesses should be defined if you want to
+ have code for asynchronous subprocesses
+ (as used in M-x compile and M-x shell).
+ This is generally OS dependent, and not supported
+ under most USG systems. */
+
+#define subprocesses
+
+/* If your system uses COFF (Common Object File Format) then define the
+ preprocessor symbol "COFF". */
+
+/* #define COFF */
+
+/* define MAIL_USE_FLOCK if the mailer uses flock
+ to interlock access to /usr/spool/mail/$USER.
+ The alternative is that a lock file named
+ /usr/spool/mail/$USER.lock. */
+
+#define MAIL_USE_FLOCK
+
+/* Define CLASH_DETECTION if you want lock files to be written
+ so that Emacs can tell instantly when you try to modify
+ a file that someone else has modified in his Emacs. */
+
+#define CLASH_DETECTION
+
+/* Define this if your operating system declares signal handlers to
+ have a type other than the usual. `The usual' is `void' for ANSI C
+ systems (i.e. when the __STDC__ macro is defined), and `int' for
+ pre-ANSI systems. If you're using GCC on an older system, __STDC__
+ will be defined, but the system's include files will still say that
+ signal returns int or whatever; in situations like that, define
+ this to be what the system's include files want. */
+/* #define SIGTYPE int */
+
+/* If the character used to separate elements of the executable path
+ is not ':', #define this to be the appropriate character constant. */
+/* #define SEPCHAR ':' */
+
+/* Define this if the system can use mmap for buffer text allocation. */
+/* #define USE_MMAP_FOR_BUFFERS 1 */
+
+/* ============================================================ */
+
+/* Here, add any special hacks needed
+ to make Emacs work on this system. For example,
+ you might define certain system call names that don't
+ exist on your system, or that do different things on
+ your system and must be used only through an encapsulation
+ (Which you should place, by convention, in sysdep.c). */
+
+/* Some compilers tend to put everything declared static
+ into the initialized data area, which becomes pure after dumping Emacs.
+ On these systems, you must #define static as nothing to foil this.
+ Note that emacs carefully avoids static vars inside functions. */
+
+/* #define static */
+
+/* If the system's imake configuration file defines `NeedWidePrototypes'
+ as `NO', we must define NARROWPROTO manually. Such a define is
+ generated in the Makefile generated by `xmkmf'. If we don't
+ define NARROWPROTO, we will see the wrong function prototypes
+ for X functions taking float or double parameters. */
+
+/* #define NARROWPROTO 1 */
+
+/* ============================================================ */
+
+/* After adding support for a new system, modify the large case
+ statement in the `configure' script to recognize reasonable
+ configuration names, and add a description of the system to
+ `etc/MACHINES'.
+
+ If you've just fixed a problem in an existing configuration file,
+ you should also check `etc/MACHINES' to make sure its descriptions
+ of known problems in that configuration should be updated. */
+
+
+/* Avoid the use of the name init_process (process.c) because it is
+ also the name of a Mach system call. */
+#define init_process emacs_init_process
+
+/* Fix compilation problem for regex.c. */
+#define __restrict
+
+/* Fix compilation problem for md5.c. */
+#define __attribute__(x)
+
+/* Used in dispnew.c. Copied from freebsd.h. */
+#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_p - (FILE)->_bf._base)
+
+/* Darwin provides POSIX-style getpgrp. */
+#define GETPGRP_NO_ARG
+
+/* System uses OXTABS instead of the expected TAB3. (Copied from
+ bsd386.h.) */
+#define TAB3 OXTABS
+
+/* Darwin ld insists on the use of malloc routines in the System
+ framework. */
+#define SYSTEM_MALLOC
+
+/* Define HAVE_SOCKETS if system supports 4.2-compatible sockets. */
+#define HAVE_SOCKETS
+
+/* Extra initialization calls in main for Mac OS X system type. */
+#define SYMS_SYSTEM syms_of_mac()
+
+/* Definitions for how to dump. Copied from nextstep.h. */
+
+#define UNEXEC unexmacosx.o
+
+#define START_FILES pre-crt0.o
+
+/* start_of_text isn't actually used, so make it compile without error. */
+#define TEXT_START (0)
+
+/* This seems to be right for end_of_text, but it may not be used anyway. */
+#define TEXT_END get_etext()
+
+/* This seems to be right for end_of_data, but it may not be used anyway. */
+#define DATA_END get_edata()
+
+/* Definitions for how to compile & link. */
+
+/* Indicate that we are compiling for Mac OS X and where to find Mac
+ specific headers. */
+#define C_SWITCH_SYSTEM -fpascal-strings -fno-common -DMAC_OSX -I../mac/src
+
+/* Link in the Carbon lib. The -headerpad option tells ld (see man
+ page) to leave room at the end of the header for adding load
+ commands. Needed for dumping. 0x690 is the total size of 30
+ segment load commands (at 56 each). */
+#define LD_SWITCH_SYSTEM_TEMACS -prebind -framework Carbon -lstdc++ -Xlinker -headerpad -Xlinker 690
+
+#define C_SWITCH_SYSTEM_TEMACS -Dtemacs
+
+/* Link this program just by running cc. */
+#define ORDINARY_LINK
+
+/* We don't have a g library, so override the -lg LIBS_DEBUG switch. */
+#define LIBS_DEBUG
+
+/* Adding -lm confuses the dynamic linker, so omit it. */
+#define LIB_MATH
+
+/* Tell src/Makefile.in to create files in the Mac OS X application
+ bundle mac/Emacs.app. */
+#define OTHER_FILES macosx-app
+
+
+/* Define the following so emacs symbols will not conflict with those
+ in the System framework. Otherwise -prebind will not work. */
+
+/* Do not define abort in emacs.c. */
+#define NO_ABORT
+
+/* Do not define matherr in floatfns.c. */
+#define NO_MATHERR
+
+
+/* This prevents a compilation error in xfaces.c: struct kboard * is
+ used in a function protocol the first time this type appears in the
+ file, since MULTI_KBOARD is undefined for the Mac OS X build. */
+#ifndef NOT_C_CODE
+struct kboard;
+#endif
+
+#ifdef temacs
+#define malloc unexec_malloc
+#define realloc unexec_realloc
+#define free unexec_free
+#endif
#include "blockinput.h"
#undef NULL
-#ifdef macintosh
+#ifdef MAC_OS8
/* It is essential to include stdlib.h so that this file picks up
the correct definitions of rand, srand, and RAND_MAX.
Otherwise random numbers will not work correctly. */
/* Nonzero means delete a process right away if it exits (process.c). */
static int delete_exited_processes;
#endif
-#endif /* macintosh */
+#endif /* MAC_OS8 */
#ifdef WINDOWSNT
#define read sys_read
/* Fork a subshell. */
-#ifndef macintosh
+#ifndef MAC_OS8
void
sys_subshell ()
{
synch_process_alive = 0;
#endif /* !VMS */
}
-#endif /* !macintosh */
+#endif /* !MAC_OS8 */
static void
save_signal_handlers (saved_handlers)
{
struct emacs_tty tty;
-#ifdef macintosh
+#ifdef MAC_OS8
/* cus-start.el complains if delete-exited-processes is not defined */
#ifndef subprocesses
DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes,
nil means don't delete them until `list-processes' is run. */);
delete_exited_processes = 0;
#endif
-#endif /* not macintosh */
+#endif /* MAC_OS8 */
#ifdef VMS
#if 0
#ifdef HAVE_X_WINDOWS
#include "xterm.h"
#endif
-#ifdef macintosh
+#ifdef MAC_OS
#include "macterm.h"
#endif
return NULL;
}
+/* These are already defined in the System framework in Mac OS X and
+ cause prebinding to fail. */
+#ifndef MAC_OSX
int
tgetnum (cap)
char *cap;
return NULL;
return tgetst1 (ptr, area);
}
+#endif /* MAC_OSX */
#ifdef IS_EBCDIC_HOST
/* Table, indexed by a character in range 0200 to 0300 with 0200 subtracted,
/* If OSPEED is 0, we use this as the actual baud rate. */
int tputs_baud_rate;
#endif
+
+/* Already defined in the System framework in Mac OS X and causes
+ prebinding to fail. */
+#ifndef MAC_OSX
char PC;
+#endif /* MAC_OSX */
#ifndef emacs
/* Actual baud rate if positive;
#endif /* not emacs */
+/* Already defined in the System framework in Mac OS X and causes
+ prebinding to fail. */
+#ifndef MAC_OSX
void
tputs (str, nlines, outfun)
register char *str;
while (padcount-- > 0)
(*outfun) (PC);
}
+#endif /* MAC_OSX */
\f
/* Finding the termcap entry in the termcap data base. */
0 if the data base is accessible but the type NAME is not defined
in it, and some other value otherwise. */
+/* Already defined in the System framework in Mac OS X and causes
+ prebinding to fail. */
+#ifndef MAC_OSX
int
tgetent (bp, name)
char *bp, *name;
term_entry = bp;
return 1;
}
+#endif /* MAC_OSX */
/* Given file open on FD and buffer BUFP,
scan the file from the beginning until a line is found
return tparam1 (string, outstring, len, NULL, NULL, arg);
}
+/* These are already defined in the System framework in Mac OS X and
+ cause prebinding to fail. */
+#ifndef MAC_OSX
char *BC;
char *UP;
args[1] = hpos;
return tparam1 (cm, tgoto_buf, 50, UP, BC, args);
}
+#endif
static char *
tparam1 (string, outstring, len, up, left, argp)
--- /dev/null
+/* Dump Emacs in Mach-O format for use on Mac OS X.
+ Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Emacs 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 GNU Emacs; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* Contributed by Andrew Choi (akochoi@mac.com). */
+
+/* Documentation note.
+
+ Consult the following documents/files for a description of the
+ Mach-O format: the file loader.h, man pages for Mach-O and ld, old
+ NEXTSTEP documents of the Mach-O format. The tool otool dumps the
+ mach header (-h option) and the load commands (-l option) in a
+ Mach-O file. The tool nm on Mac OS X displays the symbol table in
+ a Mach-O file. For examples of unexec for the Mach-O format, see
+ the file unexnext.c in the GNU Emacs distribution, the file
+ unexdyld.c in the Darwin port of GNU Emacs 20.7, and unexdyld.c in
+ the Darwin port of XEmacs 21.1. Also the Darwin Libc source
+ contains the source code for malloc_freezedry and malloc_jumpstart.
+ Read that to see what they do. This file was written completely
+ from scratch, making use of information from the above sources. */
+
+/* The Mac OS X implementation of unexec makes use of Darwin's `zone'
+ memory allocator. All calls to malloc, realloc, and free in Emacs
+ are redirected to unexec_malloc, unexec_realloc, and unexec_free in
+ this file. When temacs is run, all memory requests are handled in
+ the zone EmacsZone. The Darwin memory allocator library calls
+ maintain the data structures to manage this zone. Dumping writes
+ its contents to data segments of the executable file. When emacs
+ is run, the loader recreates the contents of the zone in memory.
+ However since the initialization routine of the zone memory
+ allocator is run again, this `zone' can no longer be used as a
+ heap. That is why emacs uses the ordinary malloc system call to
+ allocate memory. Also, when a block of memory needs to be
+ reallocated and the new size is larger than the old one, a new
+ block must be obtained by malloc and the old contents copied to
+ it. */
+
+/* Peculiarity of the Mach-O files generated by ld in Mac OS X
+ (possible causes of future bugs if changed).
+
+ The file offset of the start of the __TEXT segment is zero. Since
+ the Mach header and load commands are located at the beginning of a
+ Mach-O file, copying the contents of the __TEXT segment from the
+ input file overwrites them in the output file. Despite this,
+ unexec works fine as written below because the segment load command
+ for __TEXT appears, and is therefore processed, before all other
+ load commands except the segment load command for __PAGEZERO, which
+ remains unchanged.
+
+ Although the file offset of the start of the __TEXT segment is
+ zero, none of the sections it contains actually start there. In
+ fact, the earliest one starts a few hundred bytes beyond the end of
+ the last load command. The linker option -headerpad controls the
+ minimum size of this padding. Its setting can be changed in
+ s/darwin.h. A value of 0x300, e.g., leaves room for about 15
+ additional load commands for the newly created __DATA segments (at
+ 56 bytes each). Unexec fails if there is not enough room for these
+ new segments.
+
+ The __TEXT segment contains the sections __text, __cstring,
+ __picsymbol_stub, and __const and the __DATA segment contains the
+ sections __data, __la_symbol_ptr, __nl_symbol_ptr, __dyld, __bss,
+ and __common. The other segments do not contain any sections.
+ These sections are copied from the input file to the output file,
+ except for __data, __bss, and __common, which are dumped from
+ memory. The types of the sections __bss and __common are changed
+ from S_ZEROFILL to S_REGULAR. Note that the number of sections and
+ their relative order in the input and output files remain
+ unchanged. Otherwise all n_sect fields in the nlist records in the
+ symbol table (specified by the LC_SYMTAB load command) will have to
+ be changed accordingly.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <mach/mach.h>
+#include <mach-o/loader.h>
+#include <objc/malloc.h>
+
+#define VERBOSE 1
+
+/* Size of buffer used to copy data from the input file to the output
+ file in function unexec_copy. */
+#define UNEXEC_COPY_BUFSZ 1024
+
+/* Regions with memory addresses above this value are assumed to be
+ mapped to dynamically loaded libraries and will not be dumped. */
+#define VM_DATA_TOP (20 * 1024 * 1024)
+
+/* Used by malloc_freezedry and malloc_jumpstart. */
+int malloc_cookie;
+
+/* Type of an element on the list of regions to be dumped. */
+struct region_t {
+ vm_address_t address;
+ vm_size_t size;
+ vm_prot_t protection;
+ vm_prot_t max_protection;
+
+ struct region_t *next;
+};
+
+/* Head and tail of the list of regions to be dumped. */
+struct region_t *region_list_head = 0;
+struct region_t *region_list_tail = 0;
+
+/* Pointer to array of load commands. */
+struct load_command **lca;
+
+/* Number of load commands. */
+int nlc;
+
+/* The highest VM address of segments loaded by the input file.
+ Regions with addresses beyond this are assumed to be allocated
+ dynamically and thus require dumping. */
+vm_address_t infile_lc_highest_addr = 0;
+
+/* The lowest file offset used by the all sections in the __TEXT
+ segments. This leaves room at the beginning of the file to store
+ the Mach-O header. Check this value against header size to ensure
+ the added load commands for the new __DATA segments did not
+ overwrite any of the sections in the __TEXT segment. */
+unsigned long text_seg_lowest_offset = 0x10000000;
+
+/* Mach header. */
+struct mach_header mh;
+
+/* Offset at which the next load command should be written. */
+unsigned long curr_header_offset = sizeof (struct mach_header);
+
+/* Current adjustment that needs to be made to offset values because
+ of additional data segments. */
+unsigned long delta = 0;
+
+int infd, outfd;
+
+int in_dumped_exec = 0;
+
+malloc_zone_t *emacs_zone;
+
+/* Read n bytes from infd into memory starting at address dest.
+ Return true if successful, false otherwise. */
+static int
+unexec_read (void *dest, size_t n)
+{
+ return n == read (infd, dest, n);
+}
+
+/* Write n bytes from memory starting at address src to outfd starting
+ at offset dest. Return true if successful, false otherwise. */
+static int
+unexec_write (off_t dest, const void *src, size_t count)
+{
+ if (lseek (outfd, dest, SEEK_SET) != dest)
+ return 0;
+
+ return write (outfd, src, count) == count;
+}
+
+/* Copy n bytes from starting offset src in infd to starting offset
+ dest in outfd. Return true if successful, false otherwise. */
+static int
+unexec_copy (off_t dest, off_t src, ssize_t count)
+{
+ ssize_t bytes_read;
+
+ char buf[UNEXEC_COPY_BUFSZ];
+
+ if (lseek (infd, src, SEEK_SET) != src)
+ return 0;
+
+ if (lseek (outfd, dest, SEEK_SET) != dest)
+ return 0;
+
+ while (count > 0)
+ {
+ bytes_read = read (infd, buf, UNEXEC_COPY_BUFSZ);
+ if (bytes_read <= 0)
+ return 0;
+ if (write (outfd, buf, bytes_read) != bytes_read)
+ return 0;
+ count -= bytes_read;
+ }
+
+ return 1;
+}
+
+/* Debugging and informational messages routines. */
+
+static void
+unexec_error (char *format, ...)
+{
+ va_list ap;
+
+ va_start (ap, format);
+ fprintf (stderr, "unexec: ");
+ vfprintf (stderr, format, ap);
+ fprintf (stderr, "\n");
+ va_end (ap);
+ exit (1);
+}
+
+static void
+print_prot (vm_prot_t prot)
+{
+ if (prot == VM_PROT_NONE)
+ printf ("none");
+ else
+ {
+ putchar (prot & VM_PROT_READ ? 'r' : ' ');
+ putchar (prot & VM_PROT_WRITE ? 'w' : ' ');
+ putchar (prot & VM_PROT_EXECUTE ? 'x' : ' ');
+ putchar (' ');
+ }
+}
+
+static void
+print_region (vm_address_t address, vm_size_t size, vm_prot_t prot,
+ vm_prot_t max_prot)
+{
+ printf ("%#10x %#8x ", address, size);
+ print_prot (prot);
+ putchar (' ');
+ print_prot (max_prot);
+ putchar ('\n');
+}
+
+static void
+print_region_list ()
+{
+ struct region_t *r;
+
+ printf (" address size prot maxp\n");
+
+ for (r = region_list_head; r; r = r->next)
+ print_region (r->address, r->size, r->protection, r->max_protection);
+}
+
+void
+print_regions ()
+{
+ task_t target_task = mach_task_self ();
+ vm_address_t address = (vm_address_t) 0;
+ vm_size_t size;
+ struct vm_region_basic_info info;
+ mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT;
+ mach_port_t object_name;
+
+ printf (" address size prot maxp\n");
+
+ while (vm_region (target_task, &address, &size, VM_REGION_BASIC_INFO,
+ (vm_region_info_t) &info, &info_count, &object_name)
+ == KERN_SUCCESS && info_count == VM_REGION_BASIC_INFO_COUNT)
+ {
+ print_region (address, size, info.protection, info.max_protection);
+
+ if (object_name != MACH_PORT_NULL)
+ mach_port_deallocate (target_task, object_name);
+
+ address += size;
+ }
+}
+
+/* Build the list of regions that need to be dumped. Regions with
+ addresses above VM_DATA_TOP are omitted. Adjacent regions with
+ identical protection are merged. Note that non-writable regions
+ cannot be omitted because they some regions created at run time are
+ read-only. */
+static void
+build_region_list ()
+{
+ task_t target_task = mach_task_self ();
+ vm_address_t address = (vm_address_t) 0;
+ vm_size_t size;
+ struct vm_region_basic_info info;
+ mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT;
+ mach_port_t object_name;
+ struct region_t *r;
+
+#if VERBOSE
+ printf ("--- List of All Regions ---\n");
+ printf (" address size prot maxp\n");
+#endif
+
+ while (vm_region (target_task, &address, &size, VM_REGION_BASIC_INFO,
+ (vm_region_info_t) &info, &info_count, &object_name)
+ == KERN_SUCCESS && info_count == VM_REGION_BASIC_INFO_COUNT)
+ {
+ /* Done when we reach addresses of shared libraries, which are
+ loaded in high memory. */
+ if (address >= VM_DATA_TOP)
+ break;
+
+#if VERBOSE
+ print_region (address, size, info.protection, info.max_protection);
+#endif
+
+ /* If a region immediately follows the previous one (the one
+ most recently added to the list) and has identical
+ protection, merge it with the latter. Otherwise create a
+ new list element for it. */
+ if (region_list_tail
+ && info.protection == region_list_tail->protection
+ && info.max_protection == region_list_tail->max_protection
+ && region_list_tail->address + region_list_tail->size == address)
+ {
+ region_list_tail->size += size;
+ }
+ else
+ {
+ r = (struct region_t *) malloc (sizeof (struct region_t));
+
+ if (!r)
+ unexec_error ("cannot allocate region structure");
+
+ r->address = address;
+ r->size = size;
+ r->protection = info.protection;
+ r->max_protection = info.max_protection;
+
+ r->next = 0;
+ if (region_list_head == 0)
+ {
+ region_list_head = r;
+ region_list_tail = r;
+ }
+ else
+ {
+ region_list_tail->next = r;
+ region_list_tail = r;
+ }
+
+ /* Deallocate (unused) object name returned by
+ vm_region. */
+ if (object_name != MACH_PORT_NULL)
+ mach_port_deallocate (target_task, object_name);
+ }
+
+ address += size;
+ }
+
+ printf ("--- List of Regions to be Dumped ---\n");
+ print_region_list ();
+}
+
+
+#define MAX_UNEXEC_REGIONS 30
+
+int num_unexec_regions;
+vm_range_t unexec_regions[MAX_UNEXEC_REGIONS];
+
+static void
+unexec_regions_recorder (task_t task, void *rr, unsigned type,
+ vm_range_t *ranges, unsigned num)
+{
+ while (num && num_unexec_regions < MAX_UNEXEC_REGIONS)
+ {
+ unexec_regions[num_unexec_regions++] = *ranges;
+ printf ("%#8x (sz: %#8x)\n", ranges->address, ranges->size);
+ ranges++; num--;
+ }
+ if (num_unexec_regions == MAX_UNEXEC_REGIONS)
+ fprintf (stderr, "malloc_freezedry_recorder: too many regions\n");
+}
+
+static kern_return_t
+unexec_reader (task_t task, vm_address_t address, vm_size_t size, void **ptr)
+{
+ *ptr = (void *) address;
+ return KERN_SUCCESS;
+}
+
+void
+find_emacs_zone_regions ()
+{
+ num_unexec_regions = 0;
+
+ emacs_zone->introspect->enumerator (mach_task_self(), 0,
+ MALLOC_PTR_REGION_RANGE_TYPE
+ | MALLOC_ADMIN_REGION_RANGE_TYPE,
+ (vm_address_t) emacs_zone,
+ unexec_reader,
+ unexec_regions_recorder);
+}
+
+
+/* More informational messages routines. */
+
+static void
+print_load_command_name (int lc)
+{
+ switch (lc)
+ {
+ case LC_SEGMENT:
+ printf ("LC_SEGMENT ");
+ break;
+ case LC_LOAD_DYLINKER:
+ printf ("LC_LOAD_DYLINKER ");
+ break;
+ case LC_LOAD_DYLIB:
+ printf ("LC_LOAD_DYLIB ");
+ break;
+ case LC_SYMTAB:
+ printf ("LC_SYMTAB ");
+ break;
+ case LC_DYSYMTAB:
+ printf ("LC_DYSYMTAB ");
+ break;
+ case LC_UNIXTHREAD:
+ printf ("LC_UNIXTHREAD ");
+ break;
+ case LC_PREBOUND_DYLIB:
+ printf ("LC_PREBOUND_DYLIB");
+ break;
+ case LC_TWOLEVEL_HINTS:
+ printf ("LC_TWOLEVEL_HINTS");
+ break;
+ default:
+ printf ("unknown ");
+ }
+}
+
+static void
+print_load_command (struct load_command *lc)
+{
+ print_load_command_name (lc->cmd);
+ printf ("%8d", lc->cmdsize);
+
+ if (lc->cmd == LC_SEGMENT)
+ {
+ struct segment_command *scp;
+ struct section *sectp;
+ int j;
+
+ scp = (struct segment_command *) lc;
+ printf (" %-16.16s %#10x %#8x\n",
+ scp->segname, scp->vmaddr, scp->vmsize);
+
+ sectp = (struct section *) (scp + 1);
+ for (j = 0; j < scp->nsects; j++)
+ {
+ printf (" %-16.16s %#10x %#8x\n",
+ sectp->sectname, sectp->addr, sectp->size);
+ sectp++;
+ }
+ }
+ else
+ printf ("\n");
+}
+
+/* Read header and load commands from input file. Store the latter in
+ the global array lca. Store the total number of load commands in
+ global variable nlc. */
+static void
+read_load_commands ()
+{
+ int n, i, j;
+
+ if (!unexec_read (&mh, sizeof (struct mach_header)))
+ unexec_error ("cannot read mach-o header");
+
+ if (mh.magic != MH_MAGIC)
+ unexec_error ("input file not in Mach-O format");
+
+ if (mh.filetype != MH_EXECUTE)
+ unexec_error ("input Mach-O file is not an executable object file");
+
+#if VERBOSE
+ printf ("--- Header Information ---\n");
+ printf ("Magic = 0x%08x\n", mh.magic);
+ printf ("CPUType = %d\n", mh.cputype);
+ printf ("CPUSubType = %d\n", mh.cpusubtype);
+ printf ("FileType = 0x%x\n", mh.filetype);
+ printf ("NCmds = %d\n", mh.ncmds);
+ printf ("SizeOfCmds = %d\n", mh.sizeofcmds);
+ printf ("Flags = 0x%08x\n", mh.flags);
+#endif
+
+ nlc = mh.ncmds;
+ lca = (struct load_command **) malloc (nlc * sizeof (struct load_command *));
+
+ for (i = 0; i < nlc; i++)
+ {
+ struct load_command lc;
+ /* Load commands are variable-size: so read the command type and
+ size first and then read the rest. */
+ if (!unexec_read (&lc, sizeof (struct load_command)))
+ unexec_error ("cannot read load command");
+ lca[i] = (struct load_command *) malloc (lc.cmdsize);
+ memcpy (lca[i], &lc, sizeof (struct load_command));
+ if (!unexec_read (lca[i] + 1, lc.cmdsize - sizeof (struct load_command)))
+ unexec_error ("cannot read content of load command");
+ if (lc.cmd == LC_SEGMENT)
+ {
+ struct segment_command *scp = (struct segment_command *) lca[i];
+
+ if (scp->vmaddr + scp->vmsize > infile_lc_highest_addr)
+ infile_lc_highest_addr = scp->vmaddr + scp->vmsize;
+
+ if (strncmp (scp->segname, SEG_TEXT, 16) == 0)
+ {
+ struct section *sectp = (struct section *) (scp + 1);
+ int j;
+
+ for (j = 0; j < scp->nsects; j++)
+ if (sectp->offset < text_seg_lowest_offset)
+ text_seg_lowest_offset = sectp->offset;
+ }
+ }
+ }
+
+ printf ("Highest address of load commands in input file: %#8x\n",
+ infile_lc_highest_addr);
+
+ printf ("Lowest offset of all sections in __TEXT segment: %#8x\n",
+ text_seg_lowest_offset);
+
+ printf ("--- List of Load Commands in Input File ---\n");
+ printf ("# cmd cmdsize name address size\n");
+
+ for (i = 0; i < nlc; i++)
+ {
+ printf ("%1d ", i);
+ print_load_command (lca[i]);
+ }
+}
+
+/* Copy a LC_SEGMENT load command other than the __DATA segment from
+ the input file to the output file, adjusting the file offset of the
+ segment and the file offsets of sections contained in it. */
+static void
+copy_segment (struct load_command *lc)
+{
+ struct segment_command *scp = (struct segment_command *) lc;
+ unsigned long old_fileoff = scp->fileoff;
+ struct section *sectp;
+ int j;
+
+ scp->fileoff += delta;
+
+ sectp = (struct section *) (scp + 1);
+ for (j = 0; j < scp->nsects; j++)
+ {
+ sectp->offset += delta;
+ sectp++;
+ }
+
+ printf ("Writing segment %-16.16s at %#8x - %#8x (sz: %#8x)\n",
+ scp->segname, scp->fileoff, scp->fileoff + scp->filesize,
+ scp->filesize);
+
+ if (!unexec_copy (scp->fileoff, old_fileoff, scp->filesize))
+ unexec_error ("cannot copy segment from input to output file");
+ if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
+ unexec_error ("cannot write load command to header");
+
+ curr_header_offset += lc->cmdsize;
+}
+
+/* Copy a LC_SEGMENT load command for the __DATA segment in the input
+ file to the output file. We assume that only one such segment load
+ command exists in the input file and it contains the sections
+ __data, __bss, __common, __la_symbol_ptr, __nl_symbol_ptr, and
+ __dyld. The first three of these should be dumped from memory and
+ the rest should be copied from the input file. Note that the
+ sections __bss and __common contain no data in the input file
+ because their flag fields have the value S_ZEROFILL. Dumping these
+ from memory makes it necessary to adjust file offset fields in
+ subsequently dumped load commands. Then, create new __DATA segment
+ load commands for regions on the region list other than the one
+ corresponding to the __DATA segment in the input file. */
+static void
+copy_data_segment (struct load_command *lc)
+{
+ struct segment_command *scp = (struct segment_command *) lc;
+ struct section *sectp;
+ int j;
+ unsigned long header_offset, file_offset, old_file_offset;
+ struct region_t *r;
+
+ printf ("Writing segment %-16.16s at %#8x - %#8x (sz: %#8x)\n",
+ scp->segname, scp->fileoff, scp->fileoff + scp->filesize,
+ scp->filesize);
+
+ if (delta != 0)
+ unexec_error ("cannot handle multiple DATA segments in input file");
+
+ /* Offsets in the output file for writing the next section structure
+ and segment data block, respectively. */
+ header_offset = curr_header_offset + sizeof (struct segment_command);
+
+ sectp = (struct section *) (scp + 1);
+ for (j = 0; j < scp->nsects; j++)
+ {
+ old_file_offset = sectp->offset;
+ sectp->offset = sectp->addr - scp->vmaddr + scp->fileoff;
+ /* The __data section is dumped from memory. The __bss and
+ __common sections are also dumped from memory but their flag
+ fields require changing (from S_ZEROFILL to S_REGULAR). The
+ other three kinds of sections are just copied from the input
+ file. */
+ if (strncmp (sectp->sectname, SECT_DATA, 16) == 0)
+ {
+ if (!unexec_write (sectp->offset, (void *) sectp->addr, sectp->size))
+ unexec_error ("cannot write section %s", SECT_DATA);
+ if (!unexec_write (header_offset, sectp, sizeof (struct section)))
+ unexec_error ("cannot write section %s's header", SECT_DATA);
+ }
+ else if (strncmp (sectp->sectname, SECT_BSS, 16) == 0
+ || strncmp (sectp->sectname, SECT_COMMON, 16) == 0)
+ {
+ sectp->flags = S_REGULAR;
+ if (!unexec_write (sectp->offset, (void *) sectp->addr, sectp->size))
+ unexec_error ("cannot write section %s", SECT_DATA);
+ if (!unexec_write (header_offset, sectp, sizeof (struct section)))
+ unexec_error ("cannot write section %s's header", SECT_DATA);
+ }
+ else if (strncmp (sectp->sectname, "__la_symbol_ptr", 16) == 0
+ || strncmp (sectp->sectname, "__nl_symbol_ptr", 16) == 0
+ || strncmp (sectp->sectname, "__dyld", 16) == 0
+ || strncmp (sectp->sectname, "__const", 16) == 0)
+ {
+ if (!unexec_copy (sectp->offset, old_file_offset, sectp->size))
+ unexec_error ("cannot copy section %s", sectp->sectname);
+ if (!unexec_write (header_offset, sectp, sizeof (struct section)))
+ unexec_error ("cannot write section %s's header", sectp->sectname);
+ }
+ else
+ unexec_error ("unrecognized section name in __DATA segment");
+
+ printf (" section %-16.16s at %#8x - %#8x (sz: %#8x)\n",
+ sectp->sectname, sectp->offset, sectp->offset + sectp->size,
+ sectp->size);
+
+ header_offset += sizeof (struct section);
+ sectp++;
+ }
+
+ /* The new filesize of the segment is set to its vmsize because data
+ blocks for segments must start at region boundaries. Note that
+ this may leave unused locations at the end of the segment data
+ block because the total of the sizes of all sections in the
+ segment is generally smaller than vmsize. */
+ delta = scp->vmsize - scp->filesize;
+ scp->filesize = scp->vmsize;
+ if (!unexec_write (curr_header_offset, scp, sizeof (struct segment_command)))
+ unexec_error ("cannot write header of __DATA segment");
+ curr_header_offset += lc->cmdsize;
+
+ /* Create new __DATA segment load commands for regions on the region
+ list that do not corresponding to any segment load commands in
+ the input file.
+ */
+ file_offset = scp->fileoff + scp->filesize;
+ for (j = 0; j < num_unexec_regions; j++)
+ {
+ struct segment_command sc;
+
+ sc.cmd = LC_SEGMENT;
+ sc.cmdsize = sizeof (struct segment_command);
+ strncpy (sc.segname, SEG_DATA, 16);
+ sc.vmaddr = unexec_regions[j].address;
+ sc.vmsize = unexec_regions[j].size;
+ sc.fileoff = file_offset;
+ sc.filesize = unexec_regions[j].size;
+ sc.maxprot = VM_PROT_READ | VM_PROT_WRITE;
+ sc.initprot = VM_PROT_READ | VM_PROT_WRITE;
+ sc.nsects = 0;
+ sc.flags = 0;
+
+ printf ("Writing segment %-16.16s at %#8x - %#8x (sz: %#8x)\n",
+ sc.segname, sc.fileoff, sc.fileoff + sc.filesize,
+ sc.filesize);
+
+ if (!unexec_write (sc.fileoff, (void *) sc.vmaddr, sc.vmsize))
+ unexec_error ("cannot write new __DATA segment");
+ delta += sc.filesize;
+ file_offset += sc.filesize;
+
+ if (!unexec_write (curr_header_offset, &sc, sc.cmdsize))
+ unexec_error ("cannot write new __DATA segment's header");
+ curr_header_offset += sc.cmdsize;
+ mh.ncmds++;
+ }
+}
+
+/* Copy a LC_SYMTAB load command from the input file to the output
+ file, adjusting the file offset fields. */
+static void
+copy_symtab (struct load_command *lc)
+{
+ struct symtab_command *stp = (struct symtab_command *) lc;
+
+ stp->symoff += delta;
+ stp->stroff += delta;
+
+ printf ("Writing LC_SYMTAB command\n");
+
+ if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
+ unexec_error ("cannot write symtab command to header");
+
+ curr_header_offset += lc->cmdsize;
+}
+
+/* Copy a LC_DYSYMTAB load command from the input file to the output
+ file, adjusting the file offset fields. */
+static void
+copy_dysymtab (struct load_command *lc)
+{
+ struct dysymtab_command *dstp = (struct dysymtab_command *) lc;
+
+ /* If Mach-O executable is not prebound, relocation entries need
+ fixing up. This is not supported currently. */
+ if (!(mh.flags & MH_PREBOUND) && (dstp->nextrel != 0 || dstp->nlocrel != 0))
+ unexec_error ("cannot handle LC_DYSYMTAB with relocation entries");
+
+ if (dstp->nextrel > 0) {
+ dstp->extreloff += delta;
+ }
+
+ if (dstp->nlocrel > 0) {
+ dstp->locreloff += delta;
+ }
+
+ if (dstp->nindirectsyms > 0)
+ dstp->indirectsymoff += delta;
+
+ printf ("Writing LC_DYSYMTAB command\n");
+
+ if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
+ unexec_error ("cannot write symtab command to header");
+
+ curr_header_offset += lc->cmdsize;
+}
+
+/* Copy other kinds of load commands from the input file to the output
+ file, ones that do not require adjustments of file offsets. */
+static void
+copy_other (struct load_command *lc)
+{
+ printf ("Writing ");
+ print_load_command_name (lc->cmd);
+ printf (" command\n");
+
+ if (!unexec_write (curr_header_offset, lc, lc->cmdsize))
+ unexec_error ("cannot write symtab command to header");
+
+ curr_header_offset += lc->cmdsize;
+}
+
+/* Loop through all load commands and dump them. Then write the Mach
+ header. */
+static void
+dump_it ()
+{
+ int i;
+
+ printf ("--- Load Commands written to Output File ---\n");
+
+ for (i = 0; i < nlc; i++)
+ switch (lca[i]->cmd)
+ {
+ case LC_SEGMENT:
+ {
+ struct segment_command *scp = (struct segment_command *) lca[i];
+ if (strncmp (scp->segname, SEG_DATA, 16) == 0)
+ {
+ copy_data_segment (lca[i]);
+ }
+ else
+ {
+ copy_segment (lca[i]);
+ }
+ }
+ break;
+ case LC_SYMTAB:
+ copy_symtab (lca[i]);
+ break;
+ case LC_DYSYMTAB:
+ copy_dysymtab (lca[i]);
+ break;
+ default:
+ copy_other (lca[i]);
+ break;
+ }
+
+ if (curr_header_offset > text_seg_lowest_offset)
+ unexec_error ("not enough room for load commands for new __DATA segments");
+
+ printf ("%d unused bytes follow Mach-O header\n",
+ text_seg_lowest_offset - curr_header_offset);
+
+ mh.sizeofcmds = curr_header_offset - sizeof (struct mach_header);
+ if (!unexec_write (0, &mh, sizeof (struct mach_header)))
+ unexec_error ("cannot write final header contents");
+}
+
+/* Take a snapshot of Emacs and make a Mach-O format executable file
+ from it. The file names of the output and input files are outfile
+ and infile, respectively. The three other parameters are
+ ignored. */
+void
+unexec (char *outfile, char *infile, void *start_data, void *start_bss,
+ void *entry_address)
+{
+ infd = open (infile, O_RDONLY, 0);
+ if (infd < 0)
+ {
+ unexec_error ("cannot open input file `%s'", infile);
+ }
+
+ outfd = open (outfile, O_WRONLY | O_TRUNC | O_CREAT, 0755);
+ if (outfd < 0)
+ {
+ close (infd);
+ unexec_error ("cannot open output file `%s'", outfile);
+ }
+
+ build_region_list ();
+ read_load_commands ();
+
+ find_emacs_zone_regions ();
+
+ in_dumped_exec = 1;
+
+ dump_it ();
+
+ close (outfd);
+}
+
+
+void
+unexec_init_emacs_zone ()
+{
+ emacs_zone = malloc_create_zone (0, 0);
+ malloc_set_zone_name (emacs_zone, "EmacsZone");
+}
+
+int
+ptr_in_unexec_regions (void *ptr)
+{
+ int i;
+
+ for (i = 0; i < num_unexec_regions; i++)
+ if ((vm_address_t) ptr - unexec_regions[i].address
+ < unexec_regions[i].size)
+ return 1;
+
+ return 0;
+}
+
+void *
+unexec_malloc (size_t size)
+{
+ if (in_dumped_exec)
+ return malloc (size);
+ else
+ return malloc_zone_malloc (emacs_zone, size);
+}
+
+void *
+unexec_realloc (void *old_ptr, size_t new_size)
+{
+ if (in_dumped_exec)
+ if (ptr_in_unexec_regions (old_ptr))
+ {
+ char *p = malloc (new_size);
+ /* 2002-04-15 T. Ikegami <ikegami@adam.uprr.pr>. The original
+ code to get size failed to reallocate read_buffer
+ (lread.c). */
+ int old_size = emacs_zone->size (emacs_zone, old_ptr);
+ int size = new_size > old_size ? old_size : new_size;
+
+ if (size)
+ memcpy (p, old_ptr, size);
+ return p;
+ }
+ else
+ return realloc (old_ptr, new_size);
+ else
+ return malloc_zone_realloc (emacs_zone, old_ptr, new_size);
+}
+
+void
+unexec_free (void *ptr)
+{
+ if (in_dumped_exec)
+ {
+ if (!ptr_in_unexec_regions (ptr))
+ free (ptr);
+ }
+ else
+ malloc_zone_free (emacs_zone, ptr);
+}
#ifdef MSDOS
#include "msdos.h"
#endif
-#ifdef macintosh
+#ifdef MAC_OS
#include "macterm.h"
#endif
#ifdef WINDOWSNT
#include "w32term.h"
#endif
-#ifdef macintosh
+#ifdef MAC_OS
#include "macterm.h"
#endif
#define INFINITY 10000000
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (macintosh)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS)
extern void set_frame_menubar P_ ((struct frame *f, int, int));
extern int pending_menu_activation;
#endif
return 0;
/* The terminal frame is used as the first Emacs frame on the Mac OS. */
-#ifndef macintosh
+#ifndef MAC_OS8
#ifdef HAVE_WINDOW_SYSTEM
/* When Emacs starts, selected_frame may be a visible terminal
frame, even if we run under a window system. If we let this
if (FRAME_WINDOW_P (f)
?
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (macintosh)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS)
FRAME_EXTERNAL_MENU_BAR (f)
#else
FRAME_MENU_BAR_LINES (f) > 0
FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
/* Redisplay the menu bar in case we changed it. */
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (macintosh)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS)
if (FRAME_WINDOW_P (f)
-#if defined (macintosh)
+#if defined (MAC_OS)
/* All frames on Mac OS share the same menubar. So only the
selected frame should be allowed to set it. */
&& f == SELECTED_FRAME ()
if (FRAME_WINDOW_P (f))
{
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (macintosh)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS)
redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
#else
redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
if (FRAME_X_P (f))
return;
#endif
-#ifdef macintosh
+#ifdef MAC_OS
if (FRAME_MAC_P (f))
return;
#endif
#define FONT_WIDTH FONT_MAX_WIDTH
#endif /* WINDOWSNT */
-#ifdef macintosh
+#ifdef MAC_OS
#include "macterm.h"
#define x_display_info mac_display_info
#define check_x check_mac
-
-extern XGCValues *XCreateGC (void *, WindowPtr, unsigned long, XGCValues *);
-
-static INLINE GC
-x_create_gc (f, mask, xgcv)
- struct frame *f;
- unsigned long mask;
- XGCValues *xgcv;
-{
- GC gc;
- gc = XCreateGC (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), mask, xgcv);
- return gc;
-}
-
-static INLINE void
-x_free_gc (f, gc)
- struct frame *f;
- GC gc;
-{
- XFreeGC (FRAME_MAC_DISPLAY (f), gc);
-}
-#endif
+#endif /* MAC_OS */
#include "buffer.h"
#include "dispextern.h"
#endif /* WINDOWSNT */
+#ifdef MAC_OS
+/* Mac OS emulation of GCs */
+
+extern XGCValues *XCreateGC (void *, Window, unsigned long, XGCValues *);
+
+static INLINE GC
+x_create_gc (f, mask, xgcv)
+ struct frame *f;
+ unsigned long mask;
+ XGCValues *xgcv;
+{
+ GC gc;
+ gc = XCreateGC (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), mask, xgcv);
+ return gc;
+}
+
+static INLINE void
+x_free_gc (f, gc)
+ struct frame *f;
+ GC gc;
+{
+ XFreeGC (FRAME_MAC_DISPLAY (f), gc);
+}
+
+#endif /* MAC_OS */
+
/* Like stricmp. Used to compare parts of font names which are in
ISO8859-1. */
else if (FRAME_W32_P (f))
return w32_defined_color (f, color_name, color_def, alloc);
#endif
-#ifdef macintosh
+#ifdef MAC_OS
else if (FRAME_MAC_P (f))
return mac_defined_color (f, color_name, color_def, alloc);
#endif
font height, then for weight, then for slant.' This variable can be
set via set-face-font-sort-order. */
-#ifdef macintosh
+#ifdef MAC_OS
static int font_sort_order[4] = {
XLFD_SWIDTH, XLFD_POINT_SIZE, XLFD_WEIGHT, XLFD_SLANT
};
{
Lisp_Object value = Qnil;
#ifndef WINDOWSNT
-#ifndef macintosh
+#ifndef MAC_OS
CHECK_STRING (resource);
CHECK_STRING (class);
CHECK_LIVE_FRAME (frame);
value = display_x_get_resource (FRAME_X_DISPLAY_INFO (XFRAME (frame)),
resource, class, Qnil, Qnil);
UNBLOCK_INPUT;
-#endif /* not macintosh */
+#endif /* not MAC_OS */
#endif /* not WINDOWSNT */
return value;
}
#ifdef WINDOWSNT
xgcv.font = face->font;
#endif
-#ifdef macintosh
+#ifdef MAC_OS
xgcv.font = face->font;
#endif
mask |= GCFont;
face->fontset = make_fontset_for_ascii_face (f, fontset);
face->font = NULL; /* to force realize_face to load font */
-#ifdef macintosh
+#ifdef MAC_OS
/* Load the font if it is specified in ATTRS. This fixes
changing frame font on the Mac. */
if (STRINGP (attrs[LFACE_FONT_INDEX]))