# HG changeset patch # User Adrian Robert # Date 1216145718 0 # Node ID d45acf0c8d23ddc9a38b92c9f6cefd50e07a6a94 # Parent ff312a846b257ee61661be50d2c62154980162c9 merging Emacs.app (NeXTstep port) diff -r ff312a846b25 -r d45acf0c8d23 ChangeLog --- a/ChangeLog Tue Jul 15 15:45:05 2008 +0000 +++ b/ChangeLog Tue Jul 15 18:15:18 2008 +0000 @@ -1,3 +1,15 @@ +2008-07-15 Adrian Robert + + Changes and additions for NeXTstep windowing system (Cocoa and + GNUstep) support. + + * configure.in: Add support for NS window system: --with-ns (default + off), --enable-ns-app, --enable-cocoa-experimental-ctrl-g; improve add + sparc detection for FreeBSD variants, checks for Cocoa and GNUstep, + disable font backend if window system is "none", not if !HAVE_X11. + * Makefile.in: Add ns-emacs to INFO_FILES, add ns_appdir variable. + (install-arch-dep): Add commands to assemble NS .app package. + 2008-07-10 Dan Nicolaescu * configure.in: Use macppc for Darwin. Remove references to diff -r ff312a846b25 -r d45acf0c8d23 Makefile.in --- a/Makefile.in Tue Jul 15 15:45:05 2008 +0000 +++ b/Makefile.in Tue Jul 15 18:15:18 2008 +0000 @@ -137,7 +137,7 @@ infodir=@infodir@ INFO_FILES=ada-mode autotype calc ccmode cl dbus dired-x ebrowse ediff \ efaq eintr elisp emacs emacs-mime epa erc eshell eudc \ - flymake forms gnus idlwave info message mh-e newsticker \ + flymake forms gnus idlwave info message mh-e newsticker ns-emacs \ nxml-mode org pcl-cvs pgg rcirc reftex remember sasl sc ses \ sieve speedbar tramp vip viper widget woman smtpmail url @@ -167,6 +167,9 @@ # Location to install Emacs.app on Mac OS X carbon_appdir=@carbon_appdir@ +# Location to install Emacs.app under NeXT/Open/GNUstep / Cocoa +ns_appdir=@ns_appdir@ + # Where the etc/emacs.desktop file is to be installed. desktopdir=$(datarootdir)/applications @@ -411,6 +414,14 @@ (cd $(DESTDIR)${carbon_appdir}/Emacs.app; umask 022; tar -xvf - \ && cat > /dev/null))) || exit 1; \ fi + if test "${ns_appdir}" != ""; then \ + umask 022; mkdir -p ${ns_appdir}/Emacs.app; \ + (cd nextstep/build/Emacs.app; (tar -chf - . | \ + (cd ${ns_appdir}/Emacs.app; umask 022; tar -xvf - \ + && cat > /dev/null))) || exit 1; \ + ( cd site-lisp ; tar chf - . ) | \ + ( cd ${datadir}/$(EMACSFULL)/site-lisp ; tar xf - ) \ + fi ## http://lists.gnu.org/archive/html/emacs-devel/2007-10/msg01672.html ## Needs to be the user running install, so configure can't set it. diff -r ff312a846b25 -r d45acf0c8d23 admin/CPP-DEFINES --- a/admin/CPP-DEFINES Tue Jul 15 15:45:05 2008 +0000 +++ b/admin/CPP-DEFINES Tue Jul 15 18:15:18 2008 +0000 @@ -3,7 +3,6 @@ ** Distinguishing OSes ** -MAC_OS Compiling for the `mac' window-system. MAC_OS8 Compiling for Mac OS Classic (v8 or v9). No longer supported, all code using it can be removed. MAC_OSX Compiling for Mac OS X. Not bare Darwin. CYGWIN Compiling the Cygwin port. @@ -23,7 +22,11 @@ ** Distinguishing GUIs ** HAVE_NTGUI Use the native W32 GUI for windows, frames, menus&scrollbars. +MAC_OS Compiling for the `mac' window-system. HAVE_CARBON Compile support for the Carbon GUI. Requires MAC_OS? +HAVE_NS Use the NeXT/OpenStep/Cocoa UI under Mac OS X or GNUstep. +NS_IMPL_GNUSTEP Compile support for GNUSTEP implementation of NS GUI API. +NS_IMPL_COCOA Compile support for Cocoa (Apple) implementation of NS GUI API. HAVE_X11 Compile support for the X11 GUI. HAVE_X_WINDOWS Compile support for X Window system X11 ?? Makefile.in suggests it's equivalent to HAVE_X11 diff -r ff312a846b25 -r d45acf0c8d23 admin/ChangeLog --- a/admin/ChangeLog Tue Jul 15 15:45:05 2008 +0000 +++ b/admin/ChangeLog Tue Jul 15 18:15:18 2008 +0000 @@ -1,3 +1,7 @@ +2008-07-15 Adrian Robert + + * CPP_DEFINES: Add NS port related defines. + 2008-06-16 Glenn Morris * admin.el (set-version): Add doc/lispref/vol1.texi,vol2.texi, diff -r ff312a846b25 -r d45acf0c8d23 configure --- a/configure Tue Jul 15 15:45:05 2008 +0000 +++ b/configure Tue Jul 15 18:15:18 2008 +0000 @@ -734,6 +734,7 @@ machfile opsysfile carbon_appdir +ns_appdir LTLIBOBJS' ac_subst_files='' ac_precious_vars='build_alias @@ -1332,6 +1333,9 @@ --enable-carbon-app[=DIR] specify install directory for Emacs.app on Mac OS X [DIR=/Application] + --enable-ns-app[=DIR] [DIR=/Applications] + specify install directory for Emacs.app under NS + --enable-cocoa-experimental-ctrl-g enable experimental improved ctrl-g recognition --enable-asserts compile code with asserts enabled --enable-maintainer-mode enable make rules and dependencies not useful (and @@ -1367,6 +1371,7 @@ --without-xaw3d don't use Xaw3d --without-xim don't use X11 XIM --with-carbon use Carbon GUI on Mac OS X. This is unsupported! + --with-ns use nextstep (Cocoa or GNUstep) windowing system --without-gpm don't use -lgpm for mouse support on a GNU/Linux console --without-dbus don't compile with D-Bus support @@ -2087,6 +2092,14 @@ fi +# Check whether --with-ns was given. +if test "${with_ns+set}" = set; then + withval=$with_ns; +else + with_ns=no +fi + + # Check whether --with-gpm was given. if test "${with_gpm+set}" = set; then @@ -2155,6 +2168,20 @@ fi +# Check whether --enable-ns-app was given. +if test "${enable_ns_app+set}" = set; then + enableval=$enable_ns_app; ns_appdir_x=${enableval} +fi + + +# Check whether --enable-cocoa-experimental-ctrl-g was given. +if test "${enable_cocoa_experimental_ctrl_g+set}" = set; then + enableval=$enable_cocoa_experimental_ctrl_g; EN_COCOA_EXPERIMENTAL_CTRL_G=yes +else + EN_COCOA_EXPERIMENTAL_CTRL_G=no +fi + + # Check whether --enable-asserts was given. if test "${enable_asserts+set}" = set; then enableval=$enable_asserts; USE_XASSERTS=$enableval @@ -2378,16 +2405,17 @@ case "${canonical}" in ## FreeBSD ports - *-*-freebsd* ) + *-*-*freebsd* ) opsys=freebsd case "${canonical}" in alpha*-*-freebsd*) machine=alpha ;; arm*-*-freebsd*) machine=arm ;; ia64-*-freebsd*) machine=ia64 ;; + sparc-*-freebsd*) machine=sparc ;; sparc64-*-freebsd*) machine=sparc ;; powerpc-*-freebsd*) machine=macppc ;; i[3456]86-*-freebsd*) machine=intel386 ;; - amd64-*-freebsd*|x86_64-*-freebsd*) machine=amdx86-64 ;; + amd64-*-freebsd*|x86_64-*-*freebsd*) machine=amdx86-64 ;; esac ;; @@ -2397,6 +2425,7 @@ case "${canonical}" in alpha*-*-kfreebsd*) machine=alpha ;; ia64-*-kfreebsd*) machine=ia64 ;; + sparc-*-kfreebsd*) machine=sparc ;; sparc64-*-kfreebsd*) machine=sparc ;; powerpc-*-kfreebsd*) machine=macppc ;; i[3456]86-*-kfreebsd*) machine=intel386 ;; @@ -9308,6 +9337,179 @@ window_system=mac fi +HAVE_NS=no +COCOA=no +GNUSTEP=no +tmp_CPPFLAGS="$CPPFLAGS" +tmp_CFLAGS="$CFLAGS" +CPPFLAGS="$CPPFLAGS -x objective-c" +CFLAGS="$CFLAGS -x objective-c" +if test "${with_ns}" != no; then + if test "${opsys}" = darwin; then + COCOA=yes + elif test -f /etc/GNUstep/GNUstep.conf; then + GNUSTEP=yes + GNUSTEP_SYSTEM_HEADERS="$(source /etc/GNUstep/GNUstep.conf; echo $GNUSTEP_SYSTEM_HEADERS)" + GNUSTEP_SYSTEM_LIBRARIES="$(source /etc/GNUstep/GNUstep.conf; echo $GNUSTEP_SYSTEM_LIBRARIES)" + CPPFLAGS="$CPPFLAGS -I${GNUSTEP_SYSTEM_HEADERS}" + CFLAGS="$CFLAGS -I${GNUSTEP_SYSTEM_HEADERS}" + REAL_CFLAGS="$REAL_CFLAGS -I${GNUSTEP_SYSTEM_HEADERS}" + LDFLAGS="$LDFLAGS -L${GNUSTEP_SYSTEM_LIBRARIES}" + fi + if test "${ac_cv_header_AppKit_AppKit_h+set}" = set; then + { echo "$as_me:$LINENO: checking for AppKit/AppKit.h" >&5 +echo $ECHO_N "checking for AppKit/AppKit.h... $ECHO_C" >&6; } +if test "${ac_cv_header_AppKit_AppKit_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_AppKit_AppKit_h" >&5 +echo "${ECHO_T}$ac_cv_header_AppKit_AppKit_h" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking AppKit/AppKit.h usability" >&5 +echo $ECHO_N "checking AppKit/AppKit.h usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err 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 AppKit/AppKit.h presence" >&5 +echo $ECHO_N "checking AppKit/AppKit.h presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -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 && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' 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:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: AppKit/AppKit.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: AppKit/AppKit.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: AppKit/AppKit.h: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: AppKit/AppKit.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: AppKit/AppKit.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: AppKit/AppKit.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: AppKit/AppKit.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: AppKit/AppKit.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: AppKit/AppKit.h: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: AppKit/AppKit.h: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: AppKit/AppKit.h: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: AppKit/AppKit.h: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: AppKit/AppKit.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: AppKit/AppKit.h: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: AppKit/AppKit.h: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: AppKit/AppKit.h: in the future, the compiler will take precedence" >&2;} + + ;; +esac +{ echo "$as_me:$LINENO: checking for AppKit/AppKit.h" >&5 +echo $ECHO_N "checking for AppKit/AppKit.h... $ECHO_C" >&6; } +if test "${ac_cv_header_AppKit_AppKit_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_AppKit_AppKit_h=$ac_header_preproc +fi +{ echo "$as_me:$LINENO: result: $ac_cv_header_AppKit_AppKit_h" >&5 +echo "${ECHO_T}$ac_cv_header_AppKit_AppKit_h" >&6; } + +fi +if test $ac_cv_header_AppKit_AppKit_h = yes; then + HAVE_NS=yes +fi + + +fi +if test "${window_system}" = x11 && test "${HAVE_NS}" = yes; then + if test "${with_ns+set}" != set \ + && test "${ns_appdir_x+set}" != set; then + HAVE_NS=no + fi +fi + +if test "${window_system}" = mac && test "${HAVE_NS}" = yes; then + if test "${with_ns+set}" != set \ + && test "${ns_appdir_x+set}" != set; then + HAVE_NS=no + else + HAVE_CARBON=no + fi +fi +if test "${HAVE_NS}" = yes; then + window_system=nextstep + with_xft=no + with_freetype=no +fi +CFLAGS="$tmp_CFLAGS" +CPPFLAGS="$tmp_CPPFLAGS" + case "${window_system}" in x11 ) HAVE_X_WINDOWS=yes @@ -9321,7 +9523,7 @@ * ) USE_X_TOOLKIT=maybe ;; esac ;; - mac | none ) + nextstep | mac | none ) HAVE_X_WINDOWS=no HAVE_X11=no USE_X_TOOLKIT=none @@ -9396,9 +9598,6 @@ yes ) HAVE_MENUS=yes ;; esac -### Compute the unexec source name from the object name. -UNEXEC_SRC="`echo ${unexec} | sed 's/\.o/.c/'`" - # Do the opsystem or machine files prohibit the use of the GNU malloc? # Assume not, until told otherwise. GNU_MALLOC=yes @@ -12316,6 +12515,12 @@ _ACEOF USE_TOOLKIT_SCROLL_BARS=yes + elif test "${HAVE_NS}" = "yes"; then + cat >>confdefs.h <<\_ACEOF +#define USE_TOOLKIT_SCROLL_BARS 1 +_ACEOF + + USE_TOOLKIT_SCROLL_BARS=yes fi fi @@ -14943,6 +15148,46 @@ # We also have mouse menus. HAVE_MENUS=yes fi +### Use NeXTstep API to implement GUI. +if test "${HAVE_NS}" = "yes"; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_NS 1 +_ACEOF + + ## Specify the install directory + ns_appdir= + if test "${ns_appdir_x}" != ""; then + case ${ns_appdir_x} in + y | ye | yes) ns_appdir=/Applications ;; + * ) ns_appdir=${ns_appdir_x} ;; + esac + fi + if test "${COCOA}" = "yes"; then + +cat >>confdefs.h <<\_ACEOF +#define NS_IMPL_COCOA 1 +_ACEOF + + fi + if test "${EN_COCOA_EXPERIMENTAL_CTRL_G}" = "yes"; then + +cat >>confdefs.h <<\_ACEOF +#define COCOA_EXPERIMENTAL_CTRL_G 1 +_ACEOF + + fi + if test "${GNUSTEP}" = "yes"; then + +cat >>confdefs.h <<\_ACEOF +#define NS_IMPL_GNUSTEP 1 +_ACEOF + + fi + # We also have mouse menus. + HAVE_MENUS=yes +fi + ### Use session management (-lSM -lICE) if available HAVE_X_SM=no @@ -16688,7 +16933,6 @@ # endif #endif -#include #include #ifdef HAVE_UNISTD_H @@ -16837,15 +17081,12 @@ isn't worth using anyway. */ alarm (60); - for (;;) - { - t = (time_t_max << 1) + 1; - if (t <= time_t_max) - break; - time_t_max = t; - } - time_t_min = - ((time_t) ~ (time_t) 0 == (time_t) -1) - time_t_max; - + for (time_t_max = 1; 0 < time_t_max; time_t_max *= 2) + continue; + time_t_max--; + if ((time_t) -1 < 0) + for (time_t_min = -1; (time_t) (time_t_min * 2) < 0; time_t_min *= 2) + continue; delta = time_t_max / 997; /* a suitable prime number */ for (i = 0; i < N_STRINGS; i++) { @@ -16860,12 +17101,10 @@ && mktime_test ((time_t) (60 * 60 * 24)))) return 1; - for (j = 1; ; j <<= 1) + for (j = 1; 0 < j; j *= 2) if (! bigtime_test (j)) return 1; - else if (INT_MAX / 2 < j) - break; - if (! bigtime_test (INT_MAX)) + if (! bigtime_test (j - 1)) return 1; } return ! (irix_6_4_bug () && spring_forward_gap () && year_2050_test ()); @@ -18774,13 +19013,11 @@ cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -#include /* for off_t */ - #include -int -main () -{ -int (*fp) (FILE *, off_t, int) = fseeko; - return fseeko (stdin, 0, 0) && fp (stdin, 0, 0); +#include +int +main () +{ +return fseeko (stdin, 0, 0) && (fseeko) (stdin, 0, 0); ; return 0; } @@ -18820,13 +19057,11 @@ cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #define _LARGEFILE_SOURCE 1 -#include /* for off_t */ - #include -int -main () -{ -int (*fp) (FILE *, off_t, int) = fseeko; - return fseeko (stdin, 0, 0) && fp (stdin, 0, 0); +#include +int +main () +{ +return fseeko (stdin, 0, 0) && (fseeko) (stdin, 0, 0); ; return 0; } @@ -23963,6 +24198,7 @@ + cat >>confdefs.h <<_ACEOF #define EMACS_CONFIGURATION "${canonical}" _ACEOF @@ -24106,12 +24342,11 @@ echo " Does Emacs use -lgpm? ${HAVE_GPM}" echo " Does Emacs use -ldbus? ${HAVE_DBUS}" -if test "${USE_FONT_BACKEND}" = "yes"; then - echo " Does Emacs use -lfreetype? ${HAVE_FREETYPE}" - echo " Does Emacs use -lm17n-flt? ${HAVE_M17N_FLT}" - echo " Does Emacs use -lotf? ${HAVE_LIBOTF}" - echo " Does Emacs use -lxft? ${HAVE_XFT}" -fi +echo " Does Emacs use -lfreetype? ${HAVE_FREETYPE}" +echo " Does Emacs use -lm17n-flt? ${HAVE_M17N_FLT}" +echo " Does Emacs use -lotf? ${HAVE_LIBOTF}" +echo " Does Emacs use -lxft? ${HAVE_XFT}" + echo " Does Emacs use X toolkit scroll bars? ${USE_TOOLKIT_SCROLL_BARS}" echo @@ -24985,10 +25220,11 @@ machfile!$machfile$ac_delim opsysfile!$opsysfile$ac_delim carbon_appdir!$carbon_appdir$ac_delim +ns_appdir!$ns_appdir$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 22; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 23; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 @@ -25449,9 +25685,6 @@ echo source $srcdir/src/.gdbinit > src/.gdbinit fi -# This is how we know whether to re-run configure in certain cases. -touch src/config.stamp - ;; esac diff -r ff312a846b25 -r d45acf0c8d23 configure.in --- a/configure.in Tue Jul 15 15:45:05 2008 +0000 +++ b/configure.in Tue Jul 15 18:15:18 2008 +0000 @@ -21,7 +21,7 @@ dnl You should have received a copy of the GNU General Public License dnl along with GNU Emacs. If not, see . -AC_PREREQ(2.61)dnl +AC_PREREQ(2.61) AC_INIT(emacs, 23.0.60) AC_CONFIG_HEADER(src/config.h:src/config.in) AC_CONFIG_SRCDIR(src/lisp.h) @@ -142,6 +142,7 @@ OPTION_DEFAULT_ON([xaw3d],[don't use Xaw3d]) OPTION_DEFAULT_ON([xim],[don't use X11 XIM]) OPTION_DEFAULT_OFF([carbon],[use Carbon GUI on Mac OS X. This is unsupported!]) +OPTION_DEFAULT_OFF([ns],[use nextstep (Cocoa or GNUstep) windowing system]) OPTION_DEFAULT_ON([gpm],[don't use -lgpm for mouse support on a GNU/Linux console]) OPTION_DEFAULT_ON([dbus],[don't compile with D-Bus support]) @@ -175,6 +176,16 @@ [DIR=/Application]])], [ carbon_appdir_x=${enableval}]) +AC_ARG_ENABLE(ns-app, +[[ --enable-ns-app[=DIR] [DIR=/Applications] + specify install directory for Emacs.app under NS]], +[ ns_appdir_x=${enableval}]) + +AC_ARG_ENABLE(cocoa-experimental-ctrl-g, +[ --enable-cocoa-experimental-ctrl-g enable experimental improved ctrl-g recognition], + EN_COCOA_EXPERIMENTAL_CTRL_G=yes, + EN_COCOA_EXPERIMENTAL_CTRL_G=no) + AC_ARG_ENABLE(asserts, [AS_HELP_STRING([--enable-asserts], [compile code with asserts enabled])], USE_XASSERTS=$enableval, @@ -283,16 +294,17 @@ case "${canonical}" in ## FreeBSD ports - *-*-freebsd* ) + *-*-*freebsd* ) opsys=freebsd case "${canonical}" in alpha*-*-freebsd*) machine=alpha ;; arm*-*-freebsd*) machine=arm ;; ia64-*-freebsd*) machine=ia64 ;; + sparc-*-freebsd*) machine=sparc ;; sparc64-*-freebsd*) machine=sparc ;; powerpc-*-freebsd*) machine=macppc ;; i[3456]86-*-freebsd*) machine=intel386 ;; - amd64-*-freebsd*|x86_64-*-freebsd*) machine=amdx86-64 ;; + amd64-*-freebsd*|x86_64-*-*freebsd*) machine=amdx86-64 ;; esac ;; @@ -302,6 +314,7 @@ case "${canonical}" in alpha*-*-kfreebsd*) machine=alpha ;; ia64-*-kfreebsd*) machine=ia64 ;; + sparc-*-kfreebsd*) machine=sparc ;; sparc64-*-kfreebsd*) machine=sparc ;; powerpc-*-kfreebsd*) machine=macppc ;; i[3456]86-*-kfreebsd*) machine=intel386 ;; @@ -1221,6 +1234,50 @@ window_system=mac fi +HAVE_NS=no +COCOA=no +GNUSTEP=no +tmp_CPPFLAGS="$CPPFLAGS" +tmp_CFLAGS="$CFLAGS" +CPPFLAGS="$CPPFLAGS -x objective-c" +CFLAGS="$CFLAGS -x objective-c" +if test "${with_ns}" != no; then + if test "${opsys}" = darwin; then + COCOA=yes + elif test -f /etc/GNUstep/GNUstep.conf; then + GNUSTEP=yes + GNUSTEP_SYSTEM_HEADERS="$(source /etc/GNUstep/GNUstep.conf; echo $GNUSTEP_SYSTEM_HEADERS)" + GNUSTEP_SYSTEM_LIBRARIES="$(source /etc/GNUstep/GNUstep.conf; echo $GNUSTEP_SYSTEM_LIBRARIES)" + CPPFLAGS="$CPPFLAGS -I${GNUSTEP_SYSTEM_HEADERS}" + CFLAGS="$CFLAGS -I${GNUSTEP_SYSTEM_HEADERS}" + REAL_CFLAGS="$REAL_CFLAGS -I${GNUSTEP_SYSTEM_HEADERS}" + LDFLAGS="$LDFLAGS -L${GNUSTEP_SYSTEM_LIBRARIES}" + fi + AC_CHECK_HEADER(AppKit/AppKit.h, HAVE_NS=yes) +fi +if test "${window_system}" = x11 && test "${HAVE_NS}" = yes; then + if test "${with_ns+set}" != set \ + && test "${ns_appdir_x+set}" != set; then + HAVE_NS=no + fi +fi + +if test "${window_system}" = mac && test "${HAVE_NS}" = yes; then + if test "${with_ns+set}" != set \ + && test "${ns_appdir_x+set}" != set; then + HAVE_NS=no + else + HAVE_CARBON=no + fi +fi +if test "${HAVE_NS}" = yes; then + window_system=nextstep + with_xft=no + with_freetype=no +fi +CFLAGS="$tmp_CFLAGS" +CPPFLAGS="$tmp_CPPFLAGS" + case "${window_system}" in x11 ) HAVE_X_WINDOWS=yes @@ -1238,7 +1295,7 @@ * ) USE_X_TOOLKIT=maybe ;; esac ;; - mac | none ) + nextstep | mac | none ) HAVE_X_WINDOWS=no HAVE_X11=no USE_X_TOOLKIT=none @@ -1710,6 +1767,9 @@ elif test "${HAVE_CARBON}" = "yes"; then AC_DEFINE(USE_TOOLKIT_SCROLL_BARS) USE_TOOLKIT_SCROLL_BARS=yes + elif test "${HAVE_NS}" = "yes"; then + AC_DEFINE(USE_TOOLKIT_SCROLL_BARS) + USE_TOOLKIT_SCROLL_BARS=yes fi fi @@ -2019,6 +2079,30 @@ # We also have mouse menus. HAVE_MENUS=yes fi +### Use NeXTstep API to implement GUI. +if test "${HAVE_NS}" = "yes"; then + AC_DEFINE(HAVE_NS, 1, [Define to 1 if you are using the NeXTstep API, either GNUstep or Cocoa on Mac OS X.]) + ## Specify the install directory + ns_appdir= + if test "${ns_appdir_x}" != ""; then + case ${ns_appdir_x} in + y | ye | yes) ns_appdir=/Applications ;; + * ) ns_appdir=${ns_appdir_x} ;; + esac + fi + if test "${COCOA}" = "yes"; then + AC_DEFINE(NS_IMPL_COCOA, 1, [Define to 1 if you are using NS windowing under MacOS X.]) + fi + if test "${EN_COCOA_EXPERIMENTAL_CTRL_G}" = "yes"; then + AC_DEFINE(COCOA_EXPERIMENTAL_CTRL_G, 1, [Define to 1 if you are trying experimental enhanced Ctrl-g support using NS windowing under MacOS X.]) + fi + if test "${GNUSTEP}" = "yes"; then + AC_DEFINE(NS_IMPL_GNUSTEP, 1, [Define to 1 if you are using NS windowing under GNUstep.]) + fi + # We also have mouse menus. + HAVE_MENUS=yes +fi + ### Use session management (-lSM -lICE) if available HAVE_X_SM=no @@ -2414,6 +2498,7 @@ AC_SUBST(opsysfile) AC_SUBST(GETLOADAVG_LIBS) AC_SUBST(carbon_appdir) +AC_SUBST(ns_appdir) AC_DEFINE_UNQUOTED(EMACS_CONFIGURATION, "${canonical}", [Define to the canonical Emacs configuration name.]) @@ -2503,8 +2588,8 @@ ])dnl AH_BOTTOM([ -/* If we're using any sort of window system, define some consequences. */ -#ifdef HAVE_X_WINDOWS +/* If we're using X11/Carbon/GNUstep, define some consequences. */ +#if defined HAVE_X_WINDOWS || defined(HAVE_CARBON) || defined(HAVE_NS) #define HAVE_WINDOW_SYSTEM #define MULTI_KBOARD #define HAVE_MOUSE @@ -2516,13 +2601,15 @@ #define MULTI_KBOARD #endif -/* If we're using the Carbon API on Mac OS X, define a few more - variables as well. */ -#ifdef HAVE_CARBON -#define HAVE_WINDOW_SYSTEM -#define HAVE_MOUSE +/* Sadly for now, GNUstep dump does not work. */ +#ifdef NS_IMPL_GNUSTEP +#define CANNOT_DUMP #endif +/* PENDING: These are used for the Carbon port only. */ +#undef MAC_OS +#undef MAC_OSX + /* Define USER_FULL_NAME to return a string that is the user's full name. It can assume that the variable `pw' @@ -2575,6 +2662,28 @@ #include config_opsysfile #include config_machfile +/* Set up some defines, C and LD flags for NeXTstep interface on GNUstep. + (There is probably a better place to do this, but right now the Cocoa + side does this in s/darwin.h, following the Carbon port, and we cannot + parallel this exactly since GNUstep is multi-OS. */ +#ifdef HAVE_NS +# ifdef C_SWITCH_SYSTEM +# undef C_SWITCH_SYSTEM +# endif +# ifdef NS_IMPL_GNUSTEP +/* See also .m.o rule in Makefile.in */ +# define C_SWITCH_X_SYSTEM -MMD -MP -D_REENTRANT -fPIC -fno-strict-aliasing +# define LD_SWITCH_SITE -lgnustep-gui -lgnustep-base -lobjc $(CONFIG_SYSTEM_LIBS) -lpthread +# define GNU_OBJC_CFLAGS -fgnu-runtime -Wno-import -fconstant-string-class=NSConstantString -DGNUSTEP_BASE_LIBRARY=1 -DGNU_GUI_LIBRARY=1 -DGNU_RUNTIME=1 -DGSWARN -DGSDIAGNOSE +# define OTHER_FILES ns-app +# else /* COCOA */ +# define C_SWITCH_X_SYSTEM +# define GNU_OBJC_CFLAGS +# endif /* COCOA */ +#endif /* HAVE_NS */ + + + /* If no remapping takes place, static variables cannot be dumped as pure, so don't worry about the `static' keyword. */ #ifdef NO_REMAP diff -r ff312a846b25 -r d45acf0c8d23 doc/emacs/ChangeLog --- a/doc/emacs/ChangeLog Tue Jul 15 15:45:05 2008 +0000 +++ b/doc/emacs/ChangeLog Tue Jul 15 18:15:18 2008 +0000 @@ -1,3 +1,8 @@ +2008-07-15 Adrian Robert + + * ns-emacs.texi: New file, documents features of Emacs port under + NeXTstep windowing. + 2008-07-15 Chong Yidong * entering.texi (Entering Emacs): Update prev node. diff -r ff312a846b25 -r d45acf0c8d23 doc/emacs/ns-emacs.texi --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/emacs/ns-emacs.texi Tue Jul 15 18:15:18 2008 +0000 @@ -0,0 +1,1019 @@ +\input texinfo @c -*-texinfo-*- + +@setfilename ../info/ns-emacs +@settitle Emacs.app + +@iftex +@finalout +@end iftex + +@titlepage +@sp 10 +@center @titlefont{Emacs.app} + +@center (Version 9.0-rc1, April, 2006) + +@sp 2 +@center Carl Edman +@sp 2 +@center Christian Limpach +@sp 2 +@center Scott Bender +@sp 2 +@center Christophe de Dinechin +@sp 2 +@center Adrian Robert +@sp 2 + +@end titlepage + +@unnumbered Distribution +@* +Copyright @copyright{} 1994 Carl Edman.@* +Copyright @copyright{} 1997 Christian Limpach. +Copyright @copyright{} 1997 Scott Bender. +Copyright @copyright{} 2001 Christophe de Dinechin. +Copyright @copyright{} 2005-07 Adrian Robert. + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +@ignore +Permission is granted to process this file through Tex and print the +results, provided the printed document carries copying permission +notice identical to this one except for the removal of this paragraph +(this paragraph not being relevant to the printed manual). + +@end ignore +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the entire +resulting derived work is distributed under the terms of a permission +notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the same conditions as for modified versions. + +@ignore +@menu +* Introduction:: +* Events:: +* Preferences Panel:: +* Preferences:: +* Tips and Tricks:: +* Thanks:: +@end menu +@end ignore + +@node Top, Introduction, (dir), (dir) +@top Emacs.app + +Emacs.app for GNUstep and MacOS X (http://emacs-app.sf.net) is a version of +GNU Emacs CVS unicode-2 branch (currently planned to be released as Emacs 23) +which adds support for the GNUstep and MacOS X systems via the OpenStep APIs +(referred to as "Cocoa" under OS X). Support for NeXTstep, OpenStep, and +Rhapsody systems has been dropped. For those systems, use "Emacs-on-Aqua", +available at http://emacs-on-aqua.sf.net. + +This port leaves most of the core functions of Emacs unchanged and is +fully-compatible with all Emacs Lisp packages, however it has a number of +step-ish features which do not have any equivalent in Emacs's X11 interface. +The design aim was to make it look as similar as possible to an X application +to Emacs Lisp programs and to make it look like a normal GNUstep or MacOS X +application to users. + +(From here on out we refer to this port as "Emacs.app", and the systems +supported by this port as "NeXTstep", "NS", or "OpenStep", because saying +GNUstep / MacOS X is too clumsy. Both systems were derived from the NeXTstep +libraries developed by NeXT, Inc. for its NeXT computer and operating system, +whose APIs were later published as the OpenStep specification. All classes +and functions in these APIs start with the letters 'NS' for this historical +reason.) + +Comments and bug reports relating to the window system interface are welcome. +To report a bug please use the @samp{Help/Report Emacs.app bug...} menu item. +This sends messages to the maintainer. (Note, please include your email +address if you don't usually send email from this machine.) + +Problems and bugs which do not relate to the NS support (i.e. which can be +reproduced even in a dumb terminal or under the Carbon port or X11) should be +reported through the normal Emacs channels. + +Also, please inspect the ``Known Issues'' contained in the README file you may +have received with this distribution or listed at the web site +http://emacs-app.sf.net . + +There is also a developer mailing list for Emacs.app, +. Sign up through the project page at +http://emacs-app.sf.net. A user mailing list will be added in time and if +warranted. + + +@menu +* Introduction:: What you need to know to use and program. +* Events:: How NS window system events are handled. +* Preferences Panel:: Using the Preferences Panel to customize Emacs. +* Customization:: Customization for Emacs.app. +* Tips and Tricks:: Collected hints from Emacs users +* Thanks:: The people who helped create Emacs.app +@end menu + +@node Introduction, Events, Top, Top +@section Introduction + +Despite the size and complexity of GNU Emacs, NeXTstep and the NeXTstep +support code, this manual can be kept mercifully short by saying that +everything written in the Emacs and the Emacs Lisp manuals about GNU Emacs +applies equally to this Emacs except as noted here. + +@itemize @bullet +@item +The ``right-click'' button (usually the right-hand button on a two-button +mouse) is mapped to Mouse-3, instead of Mouse-2 as earlier versions of +Emacs.app. This is for compatibility with X versions of emacs. To get some +of the old behavior back, you can put in your .emacs: + +@lisp +(global-set-key [mouse-3] 'mouse-yank-at-click) +@end lisp + +The other functionality of mouse-3 in a buffer of extending a selection is +available via shift-click as in other NS applications. To pop up a context +menu, + +@item +The Alt or Opt key is bound to the traditional emacs "meta" by default, while +the NS "command" key is bound to 'super', for which a set of keybindings are +set to mimic other NeXTstep applications. (See @ref{Events}.) You can change +either of these bindings using the preferences panel (see @ref{Preferences +Panel}). + +@item +The standard NeXTstep font and color panels are accessible through the Windows +menu, or through the standard Cmd-t and Cmd-C. These are easier to use than +Emacs's own methods for setting these items. To use the color panel, drag +from it to an emacs frame. The foreground (or background, if shift is held +down) of the face at that point will be changed. To finalize settings for +either color or font, choose 'Save Preferences' from under the Help menu. To +discard these settings, create a new frame and close the altered one. + +@item +Opening files / directories and 'Save Buffer As' operated from the menus use +the standard NS file panels. Likewise if you use Cmd-o or Cmd-S. However, +if you use the regular Emacs key combinations Ctrl-x,Ctrl-f and Ctrl-x,w for +these functions, the normal Emacs mode of typing filenames into the minibuffer +is used. + +@item +On GNUstep, in an X-windows environment you need to use Cmd-c instead of one +of the Ctrl-w or Meta-w commands to transfer text to the X primary selection. +(Ordinarily the "clipboard" selection is used, for compatibility with more +modern Gnome and KDE programs.) Likewise, Cmd-y (instead of Ctrl-y) will +yank/paste in the X primary selection instead of the kill-ring / clipboard. + +@item +The @code{window-system} variable can now have the value @code{ns} in addition +to, e.g., @code{x} or @code{nil}. You can use this in your .emacs file: + +If you just want to distinguish between cases in which there is a +window system and in which there isn't, this construct is useful. +@lisp +(if window-system + ... ;;; evaluate if any window system is running + ...) ;;; evaluate only when running on a dumb terminal +@end lisp + +For more detailed control, use this. +@lisp +(cond + ((eq window-system 'ns) ;;; NS specific instructions + ...) + ((eq window-system 'x) ;;; X specific instructions + ...) + (t ;;; Instructions for dumb terminal or other window systems + ...)) +@end lisp + +@item +Likewise, you can detect whether you are running in emacs-23 or an earlier +version with: + +@lisp + (if (eq emacs-major-version '23) ) +@end lisp + +@item +Most NS specific functions begin with 'ns-'. Do "C-h f ns-[TAB]" to list +these. Many of these replace equivalent 'x-' functions, while others perform +uniquely NS things, such as Service invocation. + +@item +There are also NS variables beginning with 'ns-', however in most cases users +need not pay attention to them since the customizability they provide is also +available through the defaults system and preferences panel (see +@ref{Preferences Panel} and @ref{Customization}). + +@item +When Emacs is called by a name which ends in @file{-nw} it will always +start in terminal mode. For example, a user who needs a terminal only +emacs would create a symbolic link from @file{emacs} to @file{emacs-nw}. +When he launches @file{emacs-nw} from the command line, the window +system will never be involved. (Note, as of rc2, terminal mode is still not +working under OS X.) +@end itemize + +@node Events, Preferences Panel, Introduction, Top +@section Events + +Under Emacs.app the NeXTstep command key works as the @dfn{super} modifier +key. In principle users can bind their command keys to whatever function they +want, but to make the transition for NS users easier the default NS startup +files bind the most commonly used NS command keys to work just like they do in +most other NS applications. Some are shown in the menus. Choose "List +Keybindings" from the Help menu and scroll down to the keys labeled starting +with 's-' to see all of them. + +NS applications receive a number of special events which have no X equivalent. +These are sent as specially defined ``keys'' (which don't correspond to any +keyboard stroke combination). Under Emacs these ``key'' events can be bound +to functions just like ordinary keystrokes. Here is a list of these events. + +@table @code +@item ns-open-file +This event occurs when another NeXTstep application requests that Emacs +open a file. A typical reason for this would be a user double-clicking +a file in the Finder. When this event is registered the +name of the file to open is found in the variable @code{ns-input-file}. + +The behaviour of the default binding is controlled by the variable +@code{ns-pop-up-frames}. It's default value @code{'fresh} causes Emacs +to open the new file in the selected frame if the selected buffer is a +scratch buffer. Otherwise Emacs opens a new frame and displays the file +in that. + +To always get a new frame one would change @code{ns-pop-up-frames} to +@code{t}. To get the opposite behaviour (i.e. always putting the file into +the selected frame), change @code{ns-pop-up-frames} to @code{nil}. + +@item ns-open-temp-file +This event occurs when another application requests that Emacs open a +temporary file. The file name is again in @code{ns-input-file}. By +default this is handled by just generating a @code{ns-open-file} event +(which then causes the @code{ns-open-file} function to be called +whatever that may be). + +@lisp +(define-key global-map [ns-open-temp-file] [ns-open-file]) +@end lisp + +@item ns-open-file-line +Some applications (like e.g. ProjectBuilder or gdb) request not only a +particular file, but also a particular line or sequence of lines in the +file. The file name is in @code{ns-input-file}, and +@code{ns-input-line} is either the line or a cons cell the car of which +contains the beginning line and the cdr of which the ending line. + +@lisp +(define-key global-map [ns-open-file-line] 'ns-open-file-select-line) +@end lisp + +@item ns-drag-file +When a user drags files from another application into an Emacs frame +this event is triggered. Here @code{ns-input-file} is a list of all +dragged files. The default binding inserts all the dragged files into +the current buffer. + +@lisp +(define-key global-map [ns-drag-file] 'ns-insert-files) +@end lisp + +@item ns-drag-color +When a user drags a color from the color well (or some other source) +Emacs sees this event and @code{ns-input-color} contains the name of the +dragged color. The default bindings alter the foreground color of the +area the color was dragged onto (or background color if the color was +shift dragged). + +@lisp +(define-key global-map [ns-drag-color] + 'ns-set-foreground-at-mouse) +(define-key global-map [S-ns-drag-color] + 'ns-set-background-at-mouse) +@end lisp + +@item ns-change-font +Emacs.app allows the user to open a standard NS font panel (by default that +function is bound to @kbd{Cmd-t}). When the user selects a font in that +panel this event occurs. @code{ns-input-font} will contain the name of +the selected font and @code{ns-input-fontsize} is its size. The +default binding causes Emacs to adjust the font of the selected frame. + +@lisp +(define-key global-map [ns-change-font] 'ns-respond-to-changefont) +@end lisp + +@item ns-power-off +Finally when the user logs out and Emacs is still running it receives +this event so that it has a chance to save its files before it dies. + +@lisp +(define-key global-map [ns-power-off] + '(lambda () (interactive) (save-buffers-kill-emacs t))) +@end lisp + +@end table + +Emacs.app also allows users to make use of NeXTstep services programatically, +in addition to via the Services menu. On the most basic level programmers can +use the @code{ns-perform-service} to pass arbitrary strings to arbitrary +services and receive the results back. However convenience functions are +automatically provided for all services so there should be no need to use +this. These function names begin with 'ns-service-', and they will either +operate on marked text (replacing it with the result) or take a string +argument and return the result as a string. Type "M-x ns-service-[TAB][TAB]" +to see those currently defined. Note that Emacs may require a restart to +access newly available services. + + +@node Preferences Panel, Customization, Events, Top +@section Preferences Panel + +The Preferences Panel can be used to set or change some of the settings for +Emacs such as the text appearance, cursor settings, and key bindings. + +To save any settings changed through the Preferences Panel, hit OK; +this has the same effect as if you had explicitly chosen Help > Save +Preferences. + +To restore Emacs to use its default settings click Reset to Defaults from +the Preferences Panel. + +Additional GNUstep/OS X preferences may be set from the command line using +the @command{defaults} command. (See @ref{Customization}.) + + +@section Text Rendering Preferences + +Font and color settings can be set using the standard NeXTstep font +and color panels. + +@itemize @bullet +@item +To set the default font used by Emacs click the Default Font... button +to launch the Font Panel. Click on a frame before selecting the font +family, typeface, and size of the default font from the Font Panel. + +Note that the default font will not be changed if a frame hasn't been +selected first. + +@item +To set the default foreground or background color click the +Colors... button to launch the Color Panel. Choose the color you want +using any of the color models (color wheel, sliders, palette, image, +or crayons) available from the Colors toolbar. To apply the color +drag a swatch from the color bar at the top of the panel to text on +an Emacs frame. Holding down shift will change the background color +instead of the foreground. + +@item +To use antialiased text check the Smooth Fonts option. Lighter font +smoothing can be achieved by checking the Use Quickdraw (lighter) +smoothing option. + +@item +To change the line height that text is displayed at drag the Expand +Line Spacing slider. When the slider is set to 0.0 Emacs will use the +same line height as other Mac OS X applications. To increase the line +height (and decrease the number of lines that can be displayed on the +screen) drag the slider towards 1.0. To decrease the line height +(increases the number of lines that can be displayed) drag the slider +towards -1.0. + +After the line spacing setting has been changed Emacs must be restarted +to take account of the change. + +@end itemize + +@section Display Preferences + +The Display Preferences can be used to change the appearance of the +default cursor used by Emacs. + +@itemize @bullet +@item +The Cursor Type radio buttons can be used to select the style used for the cursor: + +@itemize +@item +Box - the cursor is displayed as a box +@item +Underscore - the cursor is displayed as a horizontal bar +@item +Bar - the cursor is displayed as a vertical bar +@item +Hollow - the cursor is displayed as a box with an outline but no fill +@end itemize + +@item +Use the Cursor Blink Rate slider to set the frequency at which the cursor blinks. + +@item +Check the Use System Highlight Color option to use the system default +color for highlighted text. + +@end itemize + +@section Modifier Interpretation Preferences + +The Modifier Preferences can be used to change the behaviour of the +Alt/Opt and Command keys. By default the Alt or Opt key is bound to +the Emacs 'Meta' key, and the Command key is bound to 'super' which +allows the Command key to function in a way similar to other +NeXTstep/OS X applications. + +@itemize @bullet +@item +To re-bind the Alt or Opt key select a keybinding from the Alt/Opt Key +combo box. +@item +To re-bind the Command key select a keybinding from the Command Key +combo box. +@end itemize + + +@node Customization, Tips and Tricks, Preferences Panel, Top +@section Customization + +Under X, resources are used to customize the behavior of Emacs to the needs of +the user. These resources are queried programmatically with the +@code{x-get-resource} function. Under NS defaults fulfill a similar function. +They can be read using the @code{ns-get-resource} function. Calls to +@code{x-get-resource} are automatically mapped to @code{ns-get-resource}. +From the command line, the command `@code{defaults read Emacs}' will show +these resources as of last Emacs quit, and individual resources can be +read/written by commands like `@code{defaults read Emacs Foo}' and +`@code{defaults write Emacs Foo barvalue}'. + +Calling the function @code{ns-save-preferences} in lisp, or selecting ``Save +Options'' from the 'Options' menu will automatically write out the defaults +corresponding to the selected window. + +In addition, it is also possible to set many of the following customizations +by setting the @code{default-frame-alist} in the @file{~/.emacs} file. + +Many of the preferences relating specifically to the NS windowing system (font +rendering, cursor type, etc.) can be set using a @ref{Preferences Panel} +accessed in the standard fashion from the menubar or Cmd-,. It is important +to note that when you hit 'OK' on this panel, @emph{all} NS settings are saved +(including font and colors) just as if you had called +@code{ns-save-preferences}. + +Note that if you use the 'Default Font' button on the Preferences panel, you +must click on a frame before selecting a font, otherwise nothing will happen. +If you pop up the color panel, you must drag colors to a frame for them to +have an effect. (Remember to hold down 'shift' to change background instead +of foreground.) + +This is a listing of some of the more useful defaults (and their default +values). Several of these defaults accept the names of colors as values. For +a list of all available colors pull up the color panel and look at the color +list called ``Emacs''. Emacs also accepts color specifications of the form +@samp{ARGBaarrggbb} where @var{aa}, @var{rr}, @var{gg}, and @var{bb} are two +hexadecimal digits describing the alpha, red, green, and blue content of the +color respectively. @samp{HSBhhssbbaa}, @samp{CMYKccmmyykkaa} and +@samp{GRAYggaa} are the equivalents in @samp{HSB}, @samp{CMYK} and gray +scales. + +@table @samp +@item InternalBorderWidth +Width in pixels of the internal border of the NS frame. This acts to separate +the text area of the window from the fringes, scrollbars, and/or edges. + +@example +defaults write Emacs InternalBorderWidth 2 +@end example + +@item VerticalScrollBars +@samp{YES} or @samp{NO} to enable or disable scroll bars, @samp{left} or +@samp{right} to explicitly set the side. + +@example +defaults write Emacs VerticalScrollBars YES +@end example + +@item Font +Name of the default font to be used for new frames (which can be overriden by +various faces). If this font is not set, Emacs.app will use the system +wide fixed pitch font. For most users the system fixed pitch font will be +@samp{Monaco} which doesn't have any bold or italic versions. (Italic will be +synthesized.) + +@item FontSize +Size of the font to be used for new frames. If not set Emacs for NS will use +the default size of the system wide fixed pitch font. + +@item Foreground +The default foreground (text) color for new frames. + +@example +defaults write Emacs Foreground "Black" +@end example + +@item Background +The default background color for new frames. + +@example +defaults write Emacs Background "White" +@end example + +@item Height +Height in rows of the default window. + +@example +defaults write Emacs Height 48 +@end example + +@item Width +Width in columns of the default window. + +@example +defaults write Emacs Width 80 +@end example + +@item CursorType +Name of the default cursor type for Emacs. Allowed values are +@samp{box}, @samp{hollow}, @samp{underscore}, @samp{bar}, @samp{line} and @samp{no}. + +@example +defaults write Emacs CursorType box +@end example + +@item CursorBlinkRate +Users who want their cursor to blink can set the rate (in seconds) with +this defaults write. Setting it to @samp{NO} disables cursor blinking. + +@example +defaults write Emacs CursorBlinkRate NO +@end example + +@item CursorColor +Name of the default cursor color for Emacs. Of a particular use for this +setting is the @samp{Highlight} "color". When it is the cursor color, +Emacs will draw the cursor using the standard NS highlighting operator. + +@example +defaults write Emacs CursorColor Highlight +@end example + +@item Top +Distance in pixels from the top of the screen of the upper left corner +of the default window. + +@example +defaults write Emacs Top 100 +@end example + +@item Left +Distance in pixels from the left edge of the screen to the upper left +corner of the default window. + +@example +defaults write Emacs Left 100 +@end example + +@item HideOnAutoLaunch +@samp{YES} or @samp{NO} to determine whether Emacs will hide itself when +autolaunched from the dock. + +@example +defaults write Emacs HideOnAutoLaunch NO +@end example + +@item ExpandSpace +This lets you expand or shrink the line height used for displaying text. When +this is set to 0.0, display should look like other NS apps. If you set it +higher than 0, Emacs will spread the text lines apart, less than 0, compress +them together. (With settings below zero parts of characters may be chopped +off in certain fonts.) When using the @ref{Preferences Panel}, this is +controlled by a slider. You must OK the panel and then restart Emacs.app for +this default to take effect. + +When setting this using @code{"defaults write"}, you can either set a floating +point value, or @samp{YES}, which is equivalent 0.5, or @samp{NO}, which is +equivalent to 0.0. + +@example +defaults write Emacs ExpandSpace -0.125 +@end example + +@item GSFontAntiAlias +This turns antialiasing on and off on. Note that, on OS X, even if +antialiasing is on, Emacs will not antialias text of a size below the system +preference setting. + +@example +defaults write Emacs GSFontAntiAlias NO +@end example + +@item UseQuickdrawSmoothing +On OS X 10.3 and higher, this will render fonts using Quickdraw antialiasing, +which is less heavy than the Quartz antialiasing used by default. Whether +this is on or off, the system font size threshold for antialiasing (see above) +is respected. + +@example +defaults write Emacs UseQuickdrawSmoothing YES +@end example + +@item AlternateModifier +This allows you to set the effect of the Alt or Opt key. The default is +@samp{meta}, meaning to use as the Emacs 'meta' key. You can also set this to +@samp{command}, @samp{hyper}, @samp{alt}, or @samp{none}. The last is useful +for Continental users who normally use this key to enter accented and other +special characters. + +@example +defaults write Emacs AlternateModifier "none" +@end example + +@item CommandModifier +This allows you to set the effect of the Command key. The default is +@samp{super}, which is used in a set of keybindings such as @code{s-o} for +``open file'' and @code{s-z} for ``undo'' that are similar to other NeXTstep +applications. On the other hand, some people who use the Alt/Opt key for +accent entry like to set this to @samp{meta} so they still have easy access to +Emacs functionality bound to meta keys. You can also set this, like Alt/Opt, +to @samp{hyper} or @samp{alt}, though there are no bindings to combinations +using these keys by default. The @samp{none} option is not available for the +Command key. + +@example +defaults write Emacs CommandModifier "meta" +@end example + +@item fooFrame +Position and size to use for the frame named @var{foo} when it is +created. The position and size have to be specified as a space +separated list: @samp{top}, @samp{left}, @samp{height} and +@samp{width}. @samp{top} and @samp{left} are expressed in pixels, +@samp{height} is given in rows and @samp{width} is given in columns. +Named frames can be created by e.g. @code{(make-frame '((name +. "FOO")))}. + +@example +defaults write Emacs TestFrame "100 200 30 70" +@end example + +Another default previouly used by many Emacs users is this. + +@example +defaults write Workspace DefaultOpenApp Emacs +@end example + +It caused the NeXTstep Workspace to open files without a registered extension +in Emacs instead of as usual Edit. For this default to work, Emacs needed to +be in the application search path of the Workspace (which usually includes +@file{~/Applications} and @file{~/Applications}). If anyone knows the current +way to do this under OS X please contact the authors. + +@end table + +@node Tips and Tricks, Thanks, Customization, Top +@section Tips and Tricks + +Emacs is an extremely customizable editor. You can make it conform to +virtually any conceivable user idiosyncrasy (and some which are not) by adding +a few well-chosen lines of emacs lisp to your @file{~/.emacs}. Unfortunately +even many experienced C developers are unfamiliar with Emacs Lisp. For that +reason many Emacs.app defaults have been chosen to make it behave as similar +to TextEdit as possible. But there are some customizations which a majority +of users probably would hate as much as a minority would love them. This +section contains a cookbook of such customizations. New contributions by +Emacs users are very welcome. + +@menu +* Grabbing environment variables:: +* Miscellaneous useful variables:: +* Color adjustments:: +* Evaling in the minibuffer:: +* Highlighting matching parentheses:: +* Dealing with X specific packages:: +* Rebinding the numeric keypad:: +* Improving C mode:: +* Custom menu items:: +* Single line scrolling:: +* Open files by dragging to an Emacs window:: +@ignore +* Extended font customization:: +@end ignore +@end menu + +@node Grabbing environment variables, Miscellaneous useful variables, Tips and Tricks, Tips and Tricks +@subsection Grabbing environment variables + +Many programs which may run under Emacs like latex or man depend on the +settings of environment variables. If Emacs is launched from the shell, it +will automatically inherit these environment variables and its subprocesses +will inherit them from it. But if Emacs.app is launched from the Finder it +is not a descendant of any shell, so its environment variables haven't been +set which often causes the subprocesses it launches to behave differently than +they would when launched from the shell. + +To solve this problem for Emacs.app, there are two solutions. First is to +run, from the command line: + +@example +.../Emacs.app/Contents/MacOS/bin/mac-fix-env +@end example + +This will pick up your environment settings and save them into a special file +@file{~/.MacOSX/environment.plist}, which the desktop environment will use to +set the environment for all launched applications. The drawback of this +method is it needs to be run again whenever something changes. + +The other approach is to use the @code{ns-grabenv} command inside Emacs. This +function will run a subshell and copy its environment variables into Emacs. + +Adding this line to your @file{~/.emacs} will grab the csh environment +whenever emacs runs under a window system. + +@lisp +(if window-system (ns-grabenv)) +@end lisp + +If you have a different shell you will have to give @code{ns-grabenv} some +arguments. For zsh you would do this. + +@lisp +(if window-system (ns-grabenv "/usr/bin/zsh" + "source /etc/zshenv" + "source ~/.zshenv")) +@end lisp + +The reason that @code{ns-grabenv} is not done by default is that it adds up +to a second or two to the Emacs startup time. + +@node Miscellaneous useful variables, Color adjustments, Grabbing environment variables, Tips and Tricks +@subsection Miscellaneous useful variables + +This section describes a few variables you might want to set in your +@file{~/.emacs} each of which doesn't warrant its own section. + +There is a conflict between the way the region behaved in emacs in the +pre-GUI days and the way GUI users expect the selection to work. By +default that conflict is resolved by having the former adopt the +behaviour of the latter which most people prefer. However if you are a +die-hard emacs user you may prefer things the other way around and add +this line to your @file{~/.emacs}. Experiment with both settings. + +@lisp +(setq transient-mark-mode nil) +@end lisp + +When you try to move beyond the end of a file Emacs used to add newlines as +needed, however from Emacs-21 on, this was no longer done. If you prefer the +old behavior, this line in your @file{~/.emacs} will restore it. + +@lisp +(setq next-line-add-newlines t) +@end lisp + +By default when you kill a line with text on it, only the text is +removed while the line itself remains. You have to kill twice to really +get rid of the whole line. When this variable is set and you kill a +line while at the beginning of the line it will go at once. + +@lisp +(setq kill-whole-line t) +@end lisp + +Annoyed by the Emacs startup message ? Add this and you start with a +tabula rasa. + +@lisp +(setq inhibit-startup-message t) +@end lisp + +@node Color adjustments, Evaling in the minibuffer, Miscellaneous useful variables, Tips and Tricks +@subsection Color adjustments + +A non-elisp hint: The easiest way to adjust your emacs color scheme is to +bring up a color panel (with @key{Cmd-C}) and drag the color you want over the +emacs face you want to change. Normal dragging will alter the foreground +color. Shift dragging will alter the background color. To make the changes +permanent select the "Save Options" item in the "Options" menu, or run +@code{ns-save-preferences}. Useful in this context is the listing of all +faces obtained by @key{M-x} @code{list-faces-display}. + +@node Evaling in the minibuffer, Highlighting matching parentheses, Color adjustments, Tips and Tricks +@subsection Evaling in the minibuffer + +Often you (at least if you are an elisp hacker) want to quickly evaluate +an elisp expression. To accomodate this desire Emacs provides the +@code{eval-expression} command bound to @key{M-:}. By default it is +disabled to protect novice users from themselves. These commands +re-enable it and turn on an extremely powerful completion facility. + +@lisp +(put 'eval-expression 'disabled nil) + +(define-key read-expression-map "\t" 'lisp-complete-symbol) +@end lisp + +@node Highlighting matching parentheses, Dealing with X specific packages, Evaling in the minibuffer, Tips and Tricks +@subsection Highlighting matching parentheses + +I doubt that there is anybody who doesn't use this already, but just in +case: + +@lisp +(show-paren-mode 't) +@end lisp + +In Emacs.app this is currently enhanced by use of the @code{mic-paren} package +from http://www.docs.uu.se/~mic/emacs.html. + +@node Dealing with X specific packages, Rebinding the numeric keypad, Highlighting matching parentheses, Tips and Tricks +@subsection Dealing with X specific packages + +Some emacs lisp packages explicitly call X specific functions instead of +calling generic functions which call the NS or X versions as appropriate. +Typically such packages will result in error messages like @samp{Symbol's +function definition is void: x-foo-bar}. The proper way of dealing with this +is to have the author fix the code to call the generic functions. Generally +all that requires is removing the @samp{x-} prefix from all function calls. + +However, sometimes that is not possible, or it may be a package internal to +emacs itself. In this case please report a bug to the Emacs.app maintainers +(not the main GNU emacs maintainers). + +A related problem is font names. For historical reasons, Emacs assumes all +font names are given ``X style'', as in ``-adobe-courier-....-iso8859-1''. +Emacs.app tries to work around this as well as possible, and the best thing to +do is never rely on functions to set font names yourself but to always use the +font panel. + +@node Rebinding the numeric keypad, Improving C mode, Dealing with X specific packages, Tips and Tricks +@subsection Rebinding the numeric keypad + +By default in Emacs the numeric keypad keys are bound to the same +characters they are in all other NS applications. But it is easy to +change these bindings to commands many will find more useful. As an +example here is the code which rebinds the numeric keypad for me. + +@lisp +(global-set-key [kp-0] 'other-window) +(global-set-key [kp-1] 'end-of-buffer) +(global-set-key [kp-2] [down]) +(global-set-key [kp-3] 'scroll-up) +(global-set-key [kp-4] [left]) +(global-set-key [kp-5] 'set-mark-command) +(global-set-key [kp-6] [right]) +(global-set-key [kp-7] 'beginning-of-buffer) +(global-set-key [kp-8] [up]) +(global-set-key [kp-9] 'scroll-down) +(global-set-key [kp-decimal] 'yank) +(global-set-key [kp-enter] 'set-mark-command) +(global-set-key [kp-add] 'copy-region-as-kill) +(global-set-key [kp-subtract] 'kill-region) +@end lisp + +On machines with function keys they can be bound as well. This for example +would bind @key{F12} to run gnus. + +@lisp +(global-set-key [f12] 'gnus) +@end lisp + +@node Improving C mode, Custom menu items, Rebinding the numeric keypad, Tips and Tricks +@subsection Improving C mode + +That underscores are considered to break words in C mode has been driving me +insane for a long time. This line fixes the problem. + +@lisp +(modify-syntax-entry ?_ "w" c-mode-syntax-table) +@end lisp + +@node Custom menu items, Single line scrolling, Improving C mode, Tips and Tricks +@subsection Custom menu items + +The tools menu is intended for customization. Adding items to it is +relatively painless as this example illustrates. + +@lisp +(define-key global-map [menu-bar tools www] '("WWW" . w3-use-hotlist)) +@end lisp + +@node Single line scrolling, Open files by dragging to an Emacs window, Custom menu items, Tips and Tricks +@subsection Single line scrolling + +The meta-arrow keys will perform single-line scrolling in Emacs +just like they did in the old NeXT/OpenStep Stuart.app. + +@node Open files by dragging to an Emacs window, , Single line scrolling, Tips and Tricks +@subsection Open files by dragging to an Emacs window + +The default behaviour when a user drags files from another application +into an Emacs frame is to insert the contents of all the dragged files +into the current buffer. To remap the @code{ns-drag-file} event to +open the dragged files in the current frame use the following line: + +@lisp +(define-key global-map [ns-drag-file] 'ns-find-file) +@end lisp + +@ignore +@node Extended font customization, , Single line scrolling, Tips and Tricks +@subsection Extended font customization + +By default Emacs tries to guess the right font when you ask for a bold, +italic or bold-italic face. Unfortunately this fails sometimes, for +example Emacs won't guess that it should use @samp{Courier-Bold} as the +font for the bold face of @samp{Ohlfs}. As an example here is the code +which sets up @samp{Courier-Bold}, @samp{Courier-Oblique} and +@samp{Courier-BoldOblique} as the fonts to be used with @samp{Ohlfs}. + +@lisp +(setq ns-convert-font-trait-alist + '(("Ohlfs" "Courier-Bold" "Courier-Oblique" + "Courier-BoldOblique"))) +@end lisp + +You will still have to set the @samp{DefaultFont}, @samp{BoldFont}, +@samp{ItalicFont} and @samp{Bold-ItalicFont} defaults as Emacs +initializes the default faces before it reads your @file{~/.emacs}. +Also Emacs initializes @code{ns-convert-font-trait-alist} from these +defaults so that normally it's sufficient to set these defaults to get +correct faces. + +@example +defaults write Emacs DefaultFont Ohlfs +defaults write Emacs BoldFont Courier-Bold +defaults write Emacs ItalicFont Courier-Oblique +defaults write Emacs Bold-ItalicFont Courier-BoldOblique +@end example +@end ignore + + +@node Thanks, , Tips and Tricks, Top +@section Thanks +A signficant number of people have been involved in the creation of Emacs.app. +Carl Edman created and maintained Emacs up to +version 4.1 and it's reasonable to say that without his work, Emacs.app +wouldn't exist. Michael Brouwer wrote the original version +(up to and including version 3.x) and was a constant contributor to Emacs.app +version 4 and above. Christian Limpach took over maintenance +and updating at version 4.2, and made substantial contributions in a number of +areas. Scott Bender ported the code to OpenStep and +Rhapsody for version 6.0. Christophe de Dinechin ported the +code to MacOS X for version 7.0 and moved the code base to SourceForge. Leigh +Smith maintained the SourceForge project for a period. +Adrian Robert ported the code to GNUstep +(http://gnustep.org), updated it for post-emacs-20, and maintains it for the +present. + +Also a number of others have contributed code. Steve Nygard + got emacs to dump under OpenStep. The font panel +code was Andrew Athan's work. Joe Reiss + both created the beautiful icons you see +and wrote the popup menu and dialog box code as well as much else. (Actually, +Joe's icon became the one used for the Mac Carbon port..) + +Finally, suggestions from Darcy Brockbank, Timothy Bissell, Scott Byer, David +Griffiths, Scott Hess, Eberhard Mandler, John C. Randolph, and Bradley Taylor +all helped things along at one point or another. Axel Seibert + and Paul J. Sanchez + offered their time and machines to make a binary +release possible. + +The GNUstep port was made possible through the assistance of Adam Fedor, Fred +Kiefer, M. Uli Klusterer, Alexander Malmberg, and Jonas Matton. Gürkan Sengün +made it accessible to a wider community. + +Riccardo Mottola helped with compatibility with MacOS versions 10.1 and 10.2, +and GNUstep on platforms other than Linux. + +Peter Dyballa kept things honest with multilingual support. Rahul Abrol, Adam +Ratcliffe, David M. Cooke, and Carsten Bormann provided various small patches. + +Then there were a number of people who kept up the constant supply of bug +reports, suggested features and praise (which is the main fuel which the +development of a project like this runs) and so helped ensure that this +program is as bug free (hah !) and feature rich as you see it today. First +among them were Hardy Mayer , Gisli Ottarsson +, Anthony Heading , +David Bau , Jamie Zawinski , Martin +Moncrieffe , Simson L. Garfinkel +, Richard Stallman , +Stephen Anderson , Ivo Welch +, Magnus Nordborg , Tom +Epperly , Andreas Koenig +, Yves Arrouye , Anil +Somayaji , Gregor Hoffleit + and doubtlessly many more. + +Finally, let us also thank those few hundred other people on the mailing list +from whom we didn't hear much, but the presence of which assured us that maybe +this project was actually worth doing. +@bye diff -r ff312a846b25 -r d45acf0c8d23 etc/ChangeLog --- a/etc/ChangeLog Tue Jul 15 15:45:05 2008 +0000 +++ b/etc/ChangeLog Tue Jul 15 18:15:18 2008 +0000 @@ -1,3 +1,8 @@ +2008-07-15 Adrian Robert + + * Emacs.clr: New file, add support for X color names to NS display + implementations. + 2008-07-12 Juri Linkov * HELLO: Use more correct IPA characters for English pronunciation. diff -r ff312a846b25 -r d45acf0c8d23 etc/Emacs.clr --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/etc/Emacs.clr Tue Jul 15 18:15:18 2008 +0000 @@ -0,0 +1,758 @@ +757 +0 1.000 0.980 0.980 1.0 snow +0 0.973 0.973 1.000 1.0 ghost white +0 0.973 0.973 1.000 1.0 GhostWhite +0 0.961 0.961 0.961 1.0 white smoke +0 0.961 0.961 0.961 1.0 WhiteSmoke +0 0.863 0.863 0.863 1.0 gainsboro +0 1.000 0.980 0.941 1.0 floral white +0 1.000 0.980 0.941 1.0 FloralWhite +0 0.992 0.961 0.902 1.0 old lace +0 0.992 0.961 0.902 1.0 OldLace +0 0.980 0.941 0.902 1.0 linen +0 0.980 0.922 0.843 1.0 antique white +0 0.980 0.922 0.843 1.0 AntiqueWhite +0 1.000 0.937 0.835 1.0 papaya whip +0 1.000 0.937 0.835 1.0 PapayaWhip +0 1.000 0.922 0.804 1.0 blanched almond +0 1.000 0.922 0.804 1.0 BlanchedAlmond +0 1.000 0.894 0.769 1.0 bisque +0 1.000 0.855 0.725 1.0 peach puff +0 1.000 0.855 0.725 1.0 PeachPuff +0 1.000 0.871 0.678 1.0 navajo white +0 1.000 0.871 0.678 1.0 NavajoWhite +0 1.000 0.894 0.710 1.0 moccasin +0 1.000 0.973 0.863 1.0 cornsilk +0 1.000 1.000 0.941 1.0 ivory +0 1.000 0.980 0.804 1.0 lemon chiffon +0 1.000 0.980 0.804 1.0 LemonChiffon +0 1.000 0.961 0.933 1.0 seashell +0 0.941 1.000 0.941 1.0 honeydew +0 0.961 1.000 0.980 1.0 mint cream +0 0.961 1.000 0.980 1.0 MintCream +0 0.941 1.000 1.000 1.0 azure +0 0.941 0.973 1.000 1.0 alice blue +0 0.941 0.973 1.000 1.0 AliceBlue +0 0.902 0.902 0.980 1.0 lavender +0 1.000 0.941 0.961 1.0 lavender blush +0 1.000 0.941 0.961 1.0 LavenderBlush +0 1.000 0.894 0.882 1.0 misty rose +0 1.000 0.894 0.882 1.0 MistyRose +0 1.000 1.000 1.000 1.0 white +0 0.000 0.000 0.000 1.0 black +0 0.184 0.310 0.310 1.0 dark slate gray +0 0.184 0.310 0.310 1.0 DarkSlateGray +0 0.184 0.310 0.310 1.0 dark slate grey +0 0.184 0.310 0.310 1.0 DarkSlateGrey +0 0.412 0.412 0.412 1.0 dim gray +0 0.412 0.412 0.412 1.0 DimGray +0 0.412 0.412 0.412 1.0 dim grey +0 0.412 0.412 0.412 1.0 DimGrey +0 0.439 0.502 0.565 1.0 slate gray +0 0.439 0.502 0.565 1.0 SlateGray +0 0.439 0.502 0.565 1.0 slate grey +0 0.439 0.502 0.565 1.0 SlateGrey +0 0.467 0.533 0.600 1.0 light slate gray +0 0.467 0.533 0.600 1.0 LightSlateGray +0 0.467 0.533 0.600 1.0 light slate grey +0 0.467 0.533 0.600 1.0 LightSlateGrey +0 0.745 0.745 0.745 1.0 gray +0 0.745 0.745 0.745 1.0 grey +0 0.827 0.827 0.827 1.0 light grey +0 0.827 0.827 0.827 1.0 LightGrey +0 0.827 0.827 0.827 1.0 light gray +0 0.827 0.827 0.827 1.0 LightGray +0 0.098 0.098 0.439 1.0 midnight blue +0 0.098 0.098 0.439 1.0 MidnightBlue +0 0.000 0.000 0.502 1.0 navy +0 0.000 0.000 0.502 1.0 navy blue +0 0.000 0.000 0.502 1.0 NavyBlue +0 0.392 0.584 0.929 1.0 cornflower blue +0 0.392 0.584 0.929 1.0 CornflowerBlue +0 0.282 0.239 0.545 1.0 dark slate blue +0 0.282 0.239 0.545 1.0 DarkSlateBlue +0 0.416 0.353 0.804 1.0 slate blue +0 0.416 0.353 0.804 1.0 SlateBlue +0 0.482 0.408 0.933 1.0 medium slate blue +0 0.482 0.408 0.933 1.0 MediumSlateBlue +0 0.518 0.439 1.000 1.0 light slate blue +0 0.518 0.439 1.000 1.0 LightSlateBlue +0 0.000 0.000 0.804 1.0 medium blue +0 0.000 0.000 0.804 1.0 MediumBlue +0 0.255 0.412 0.882 1.0 royal blue +0 0.255 0.412 0.882 1.0 RoyalBlue +0 0.000 0.000 1.000 1.0 blue +0 0.118 0.565 1.000 1.0 dodger blue +0 0.118 0.565 1.000 1.0 DodgerBlue +0 0.000 0.749 1.000 1.0 deep sky blue +0 0.000 0.749 1.000 1.0 DeepSkyBlue +0 0.529 0.808 0.922 1.0 sky blue +0 0.529 0.808 0.922 1.0 SkyBlue +0 0.529 0.808 0.980 1.0 light sky blue +0 0.529 0.808 0.980 1.0 LightSkyBlue +0 0.275 0.510 0.706 1.0 steel blue +0 0.275 0.510 0.706 1.0 SteelBlue +0 0.690 0.769 0.871 1.0 light steel blue +0 0.690 0.769 0.871 1.0 LightSteelBlue +0 0.678 0.847 0.902 1.0 light blue +0 0.678 0.847 0.902 1.0 LightBlue +0 0.690 0.878 0.902 1.0 powder blue +0 0.690 0.878 0.902 1.0 PowderBlue +0 0.686 0.933 0.933 1.0 pale turquoise +0 0.686 0.933 0.933 1.0 PaleTurquoise +0 0.000 0.808 0.820 1.0 dark turquoise +0 0.000 0.808 0.820 1.0 DarkTurquoise +0 0.282 0.820 0.800 1.0 medium turquoise +0 0.282 0.820 0.800 1.0 MediumTurquoise +0 0.251 0.878 0.816 1.0 turquoise +0 0.000 1.000 1.000 1.0 cyan +0 0.878 1.000 1.000 1.0 light cyan +0 0.878 1.000 1.000 1.0 LightCyan +0 0.373 0.620 0.627 1.0 cadet blue +0 0.373 0.620 0.627 1.0 CadetBlue +0 0.400 0.804 0.667 1.0 medium aquamarine +0 0.400 0.804 0.667 1.0 MediumAquamarine +0 0.498 1.000 0.831 1.0 aquamarine +0 0.000 0.392 0.000 1.0 dark green +0 0.000 0.392 0.000 1.0 DarkGreen +0 0.333 0.420 0.184 1.0 dark olive green +0 0.333 0.420 0.184 1.0 DarkOliveGreen +0 0.561 0.737 0.561 1.0 dark sea green +0 0.561 0.737 0.561 1.0 DarkSeaGreen +0 0.180 0.545 0.341 1.0 sea green +0 0.180 0.545 0.341 1.0 SeaGreen +0 0.235 0.702 0.443 1.0 medium sea green +0 0.235 0.702 0.443 1.0 MediumSeaGreen +0 0.125 0.698 0.667 1.0 light sea green +0 0.125 0.698 0.667 1.0 LightSeaGreen +0 0.596 0.984 0.596 1.0 pale green +0 0.596 0.984 0.596 1.0 PaleGreen +0 0.000 1.000 0.498 1.0 spring green +0 0.000 1.000 0.498 1.0 SpringGreen +0 0.486 0.988 0.000 1.0 lawn green +0 0.486 0.988 0.000 1.0 LawnGreen +0 0.000 1.000 0.000 1.0 green +0 0.498 1.000 0.000 1.0 chartreuse +0 0.000 0.980 0.604 1.0 medium spring green +0 0.000 0.980 0.604 1.0 MediumSpringGreen +0 0.678 1.000 0.184 1.0 green yellow +0 0.678 1.000 0.184 1.0 GreenYellow +0 0.196 0.804 0.196 1.0 lime green +0 0.196 0.804 0.196 1.0 LimeGreen +0 0.604 0.804 0.196 1.0 yellow green +0 0.604 0.804 0.196 1.0 YellowGreen +0 0.133 0.545 0.133 1.0 forest green +0 0.133 0.545 0.133 1.0 ForestGreen +0 0.420 0.557 0.137 1.0 olive drab +0 0.420 0.557 0.137 1.0 OliveDrab +0 0.741 0.718 0.420 1.0 dark khaki +0 0.741 0.718 0.420 1.0 DarkKhaki +0 0.941 0.902 0.549 1.0 khaki +0 0.933 0.910 0.667 1.0 pale goldenrod +0 0.933 0.910 0.667 1.0 PaleGoldenrod +0 0.980 0.980 0.824 1.0 light goldenrod yellow +0 0.980 0.980 0.824 1.0 LightGoldenrodYellow +0 1.000 1.000 0.878 1.0 light yellow +0 1.000 1.000 0.878 1.0 LightYellow +0 1.000 1.000 0.000 1.0 yellow +0 1.000 0.843 0.000 1.0 gold +0 0.933 0.867 0.510 1.0 light goldenrod +0 0.933 0.867 0.510 1.0 LightGoldenrod +0 0.855 0.647 0.125 1.0 goldenrod +0 0.722 0.525 0.043 1.0 dark goldenrod +0 0.722 0.525 0.043 1.0 DarkGoldenrod +0 0.737 0.561 0.561 1.0 rosy brown +0 0.737 0.561 0.561 1.0 RosyBrown +0 0.804 0.361 0.361 1.0 indian red +0 0.804 0.361 0.361 1.0 IndianRed +0 0.545 0.271 0.075 1.0 saddle brown +0 0.545 0.271 0.075 1.0 SaddleBrown +0 0.627 0.322 0.176 1.0 sienna +0 0.804 0.522 0.247 1.0 peru +0 0.871 0.722 0.529 1.0 burlywood +0 0.961 0.961 0.863 1.0 beige +0 0.961 0.871 0.702 1.0 wheat +0 0.957 0.643 0.376 1.0 sandy brown +0 0.957 0.643 0.376 1.0 SandyBrown +0 0.824 0.706 0.549 1.0 tan +0 0.824 0.412 0.118 1.0 chocolate +0 0.698 0.133 0.133 1.0 firebrick +0 0.647 0.165 0.165 1.0 brown +0 0.914 0.588 0.478 1.0 dark salmon +0 0.914 0.588 0.478 1.0 DarkSalmon +0 0.980 0.502 0.447 1.0 salmon +0 1.000 0.627 0.478 1.0 light salmon +0 1.000 0.627 0.478 1.0 LightSalmon +0 1.000 0.647 0.000 1.0 orange +0 1.000 0.549 0.000 1.0 dark orange +0 1.000 0.549 0.000 1.0 DarkOrange +0 1.000 0.498 0.314 1.0 coral +0 0.941 0.502 0.502 1.0 light coral +0 0.941 0.502 0.502 1.0 LightCoral +0 1.000 0.388 0.278 1.0 tomato +0 1.000 0.271 0.000 1.0 orange red +0 1.000 0.271 0.000 1.0 OrangeRed +0 1.000 0.000 0.000 1.0 red +0 1.000 0.412 0.706 1.0 hot pink +0 1.000 0.412 0.706 1.0 HotPink +0 1.000 0.078 0.576 1.0 deep pink +0 1.000 0.078 0.576 1.0 DeepPink +0 1.000 0.753 0.796 1.0 pink +0 1.000 0.714 0.757 1.0 light pink +0 1.000 0.714 0.757 1.0 LightPink +0 0.859 0.439 0.576 1.0 pale violet red +0 0.859 0.439 0.576 1.0 PaleVioletRed +0 0.690 0.188 0.376 1.0 maroon +0 0.780 0.082 0.522 1.0 medium violet red +0 0.780 0.082 0.522 1.0 MediumVioletRed +0 0.816 0.125 0.565 1.0 violet red +0 0.816 0.125 0.565 1.0 VioletRed +0 1.000 0.000 1.000 1.0 magenta +0 0.933 0.510 0.933 1.0 violet +0 0.867 0.627 0.867 1.0 plum +0 0.855 0.439 0.839 1.0 orchid +0 0.729 0.333 0.827 1.0 medium orchid +0 0.729 0.333 0.827 1.0 MediumOrchid +0 0.600 0.196 0.800 1.0 dark orchid +0 0.600 0.196 0.800 1.0 DarkOrchid +0 0.580 0.000 0.827 1.0 dark violet +0 0.580 0.000 0.827 1.0 DarkViolet +0 0.541 0.169 0.886 1.0 blue violet +0 0.541 0.169 0.886 1.0 BlueViolet +0 0.627 0.125 0.941 1.0 purple +0 0.576 0.439 0.859 1.0 medium purple +0 0.576 0.439 0.859 1.0 MediumPurple +0 0.847 0.749 0.847 1.0 thistle +0 1.000 0.980 0.980 1.0 snow1 +0 0.933 0.914 0.914 1.0 snow2 +0 0.804 0.788 0.788 1.0 snow3 +0 0.545 0.537 0.537 1.0 snow4 +0 1.000 0.961 0.933 1.0 seashell1 +0 0.933 0.898 0.871 1.0 seashell2 +0 0.804 0.773 0.749 1.0 seashell3 +0 0.545 0.525 0.510 1.0 seashell4 +0 1.000 0.937 0.859 1.0 AntiqueWhite1 +0 0.933 0.875 0.800 1.0 AntiqueWhite2 +0 0.804 0.753 0.690 1.0 AntiqueWhite3 +0 0.545 0.514 0.471 1.0 AntiqueWhite4 +0 1.000 0.894 0.769 1.0 bisque1 +0 0.933 0.835 0.718 1.0 bisque2 +0 0.804 0.718 0.620 1.0 bisque3 +0 0.545 0.490 0.420 1.0 bisque4 +0 1.000 0.855 0.725 1.0 PeachPuff1 +0 0.933 0.796 0.678 1.0 PeachPuff2 +0 0.804 0.686 0.584 1.0 PeachPuff3 +0 0.545 0.467 0.396 1.0 PeachPuff4 +0 1.000 0.871 0.678 1.0 NavajoWhite1 +0 0.933 0.812 0.631 1.0 NavajoWhite2 +0 0.804 0.702 0.545 1.0 NavajoWhite3 +0 0.545 0.475 0.369 1.0 NavajoWhite4 +0 1.000 0.980 0.804 1.0 LemonChiffon1 +0 0.933 0.914 0.749 1.0 LemonChiffon2 +0 0.804 0.788 0.647 1.0 LemonChiffon3 +0 0.545 0.537 0.439 1.0 LemonChiffon4 +0 1.000 0.973 0.863 1.0 cornsilk1 +0 0.933 0.910 0.804 1.0 cornsilk2 +0 0.804 0.784 0.694 1.0 cornsilk3 +0 0.545 0.533 0.471 1.0 cornsilk4 +0 1.000 1.000 0.941 1.0 ivory1 +0 0.933 0.933 0.878 1.0 ivory2 +0 0.804 0.804 0.757 1.0 ivory3 +0 0.545 0.545 0.514 1.0 ivory4 +0 0.941 1.000 0.941 1.0 honeydew1 +0 0.878 0.933 0.878 1.0 honeydew2 +0 0.757 0.804 0.757 1.0 honeydew3 +0 0.514 0.545 0.514 1.0 honeydew4 +0 1.000 0.941 0.961 1.0 LavenderBlush1 +0 0.933 0.878 0.898 1.0 LavenderBlush2 +0 0.804 0.757 0.773 1.0 LavenderBlush3 +0 0.545 0.514 0.525 1.0 LavenderBlush4 +0 1.000 0.894 0.882 1.0 MistyRose1 +0 0.933 0.835 0.824 1.0 MistyRose2 +0 0.804 0.718 0.710 1.0 MistyRose3 +0 0.545 0.490 0.482 1.0 MistyRose4 +0 0.941 1.000 1.000 1.0 azure1 +0 0.878 0.933 0.933 1.0 azure2 +0 0.757 0.804 0.804 1.0 azure3 +0 0.514 0.545 0.545 1.0 azure4 +0 0.514 0.435 1.000 1.0 SlateBlue1 +0 0.478 0.404 0.933 1.0 SlateBlue2 +0 0.412 0.349 0.804 1.0 SlateBlue3 +0 0.278 0.235 0.545 1.0 SlateBlue4 +0 0.282 0.463 1.000 1.0 RoyalBlue1 +0 0.263 0.431 0.933 1.0 RoyalBlue2 +0 0.227 0.373 0.804 1.0 RoyalBlue3 +0 0.153 0.251 0.545 1.0 RoyalBlue4 +0 0.000 0.000 1.000 1.0 blue1 +0 0.000 0.000 0.933 1.0 blue2 +0 0.000 0.000 0.804 1.0 blue3 +0 0.000 0.000 0.545 1.0 blue4 +0 0.118 0.565 1.000 1.0 DodgerBlue1 +0 0.110 0.525 0.933 1.0 DodgerBlue2 +0 0.094 0.455 0.804 1.0 DodgerBlue3 +0 0.063 0.306 0.545 1.0 DodgerBlue4 +0 0.388 0.722 1.000 1.0 SteelBlue1 +0 0.361 0.675 0.933 1.0 SteelBlue2 +0 0.310 0.580 0.804 1.0 SteelBlue3 +0 0.212 0.392 0.545 1.0 SteelBlue4 +0 0.000 0.749 1.000 1.0 DeepSkyBlue1 +0 0.000 0.698 0.933 1.0 DeepSkyBlue2 +0 0.000 0.604 0.804 1.0 DeepSkyBlue3 +0 0.000 0.408 0.545 1.0 DeepSkyBlue4 +0 0.529 0.808 1.000 1.0 SkyBlue1 +0 0.494 0.753 0.933 1.0 SkyBlue2 +0 0.424 0.651 0.804 1.0 SkyBlue3 +0 0.290 0.439 0.545 1.0 SkyBlue4 +0 0.690 0.886 1.000 1.0 LightSkyBlue1 +0 0.643 0.827 0.933 1.0 LightSkyBlue2 +0 0.553 0.714 0.804 1.0 LightSkyBlue3 +0 0.376 0.482 0.545 1.0 LightSkyBlue4 +0 0.776 0.886 1.000 1.0 SlateGray1 +0 0.725 0.827 0.933 1.0 SlateGray2 +0 0.624 0.714 0.804 1.0 SlateGray3 +0 0.424 0.482 0.545 1.0 SlateGray4 +0 0.792 0.882 1.000 1.0 LightSteelBlue1 +0 0.737 0.824 0.933 1.0 LightSteelBlue2 +0 0.635 0.710 0.804 1.0 LightSteelBlue3 +0 0.431 0.482 0.545 1.0 LightSteelBlue4 +0 0.749 0.937 1.000 1.0 LightBlue1 +0 0.698 0.875 0.933 1.0 LightBlue2 +0 0.604 0.753 0.804 1.0 LightBlue3 +0 0.408 0.514 0.545 1.0 LightBlue4 +0 0.878 1.000 1.000 1.0 LightCyan1 +0 0.820 0.933 0.933 1.0 LightCyan2 +0 0.706 0.804 0.804 1.0 LightCyan3 +0 0.478 0.545 0.545 1.0 LightCyan4 +0 0.733 1.000 1.000 1.0 PaleTurquoise1 +0 0.682 0.933 0.933 1.0 PaleTurquoise2 +0 0.588 0.804 0.804 1.0 PaleTurquoise3 +0 0.400 0.545 0.545 1.0 PaleTurquoise4 +0 0.596 0.961 1.000 1.0 CadetBlue1 +0 0.557 0.898 0.933 1.0 CadetBlue2 +0 0.478 0.773 0.804 1.0 CadetBlue3 +0 0.325 0.525 0.545 1.0 CadetBlue4 +0 0.000 0.961 1.000 1.0 turquoise1 +0 0.000 0.898 0.933 1.0 turquoise2 +0 0.000 0.773 0.804 1.0 turquoise3 +0 0.000 0.525 0.545 1.0 turquoise4 +0 0.000 1.000 1.000 1.0 cyan1 +0 0.000 0.933 0.933 1.0 cyan2 +0 0.000 0.804 0.804 1.0 cyan3 +0 0.000 0.545 0.545 1.0 cyan4 +0 0.592 1.000 1.000 1.0 DarkSlateGray1 +0 0.553 0.933 0.933 1.0 DarkSlateGray2 +0 0.475 0.804 0.804 1.0 DarkSlateGray3 +0 0.322 0.545 0.545 1.0 DarkSlateGray4 +0 0.498 1.000 0.831 1.0 aquamarine1 +0 0.463 0.933 0.776 1.0 aquamarine2 +0 0.400 0.804 0.667 1.0 aquamarine3 +0 0.271 0.545 0.455 1.0 aquamarine4 +0 0.757 1.000 0.757 1.0 DarkSeaGreen1 +0 0.706 0.933 0.706 1.0 DarkSeaGreen2 +0 0.608 0.804 0.608 1.0 DarkSeaGreen3 +0 0.412 0.545 0.412 1.0 DarkSeaGreen4 +0 0.329 1.000 0.624 1.0 SeaGreen1 +0 0.306 0.933 0.580 1.0 SeaGreen2 +0 0.263 0.804 0.502 1.0 SeaGreen3 +0 0.180 0.545 0.341 1.0 SeaGreen4 +0 0.604 1.000 0.604 1.0 PaleGreen1 +0 0.565 0.933 0.565 1.0 PaleGreen2 +0 0.486 0.804 0.486 1.0 PaleGreen3 +0 0.329 0.545 0.329 1.0 PaleGreen4 +0 0.000 1.000 0.498 1.0 SpringGreen1 +0 0.000 0.933 0.463 1.0 SpringGreen2 +0 0.000 0.804 0.400 1.0 SpringGreen3 +0 0.000 0.545 0.271 1.0 SpringGreen4 +0 0.000 1.000 0.000 1.0 green1 +0 0.000 0.933 0.000 1.0 green2 +0 0.000 0.804 0.000 1.0 green3 +0 0.000 0.545 0.000 1.0 green4 +0 0.498 1.000 0.000 1.0 chartreuse1 +0 0.463 0.933 0.000 1.0 chartreuse2 +0 0.400 0.804 0.000 1.0 chartreuse3 +0 0.271 0.545 0.000 1.0 chartreuse4 +0 0.753 1.000 0.243 1.0 OliveDrab1 +0 0.702 0.933 0.227 1.0 OliveDrab2 +0 0.604 0.804 0.196 1.0 OliveDrab3 +0 0.412 0.545 0.133 1.0 OliveDrab4 +0 0.792 1.000 0.439 1.0 DarkOliveGreen1 +0 0.737 0.933 0.408 1.0 DarkOliveGreen2 +0 0.635 0.804 0.353 1.0 DarkOliveGreen3 +0 0.431 0.545 0.239 1.0 DarkOliveGreen4 +0 1.000 0.965 0.561 1.0 khaki1 +0 0.933 0.902 0.522 1.0 khaki2 +0 0.804 0.776 0.451 1.0 khaki3 +0 0.545 0.525 0.306 1.0 khaki4 +0 1.000 0.925 0.545 1.0 LightGoldenrod1 +0 0.933 0.863 0.510 1.0 LightGoldenrod2 +0 0.804 0.745 0.439 1.0 LightGoldenrod3 +0 0.545 0.506 0.298 1.0 LightGoldenrod4 +0 1.000 1.000 0.878 1.0 LightYellow1 +0 0.933 0.933 0.820 1.0 LightYellow2 +0 0.804 0.804 0.706 1.0 LightYellow3 +0 0.545 0.545 0.478 1.0 LightYellow4 +0 1.000 1.000 0.000 1.0 yellow1 +0 0.933 0.933 0.000 1.0 yellow2 +0 0.804 0.804 0.000 1.0 yellow3 +0 0.545 0.545 0.000 1.0 yellow4 +0 1.000 0.843 0.000 1.0 gold1 +0 0.933 0.788 0.000 1.0 gold2 +0 0.804 0.678 0.000 1.0 gold3 +0 0.545 0.459 0.000 1.0 gold4 +0 1.000 0.757 0.145 1.0 goldenrod1 +0 0.933 0.706 0.133 1.0 goldenrod2 +0 0.804 0.608 0.114 1.0 goldenrod3 +0 0.545 0.412 0.078 1.0 goldenrod4 +0 1.000 0.725 0.059 1.0 DarkGoldenrod1 +0 0.933 0.678 0.055 1.0 DarkGoldenrod2 +0 0.804 0.584 0.047 1.0 DarkGoldenrod3 +0 0.545 0.396 0.031 1.0 DarkGoldenrod4 +0 1.000 0.757 0.757 1.0 RosyBrown1 +0 0.933 0.706 0.706 1.0 RosyBrown2 +0 0.804 0.608 0.608 1.0 RosyBrown3 +0 0.545 0.412 0.412 1.0 RosyBrown4 +0 1.000 0.416 0.416 1.0 IndianRed1 +0 0.933 0.388 0.388 1.0 IndianRed2 +0 0.804 0.333 0.333 1.0 IndianRed3 +0 0.545 0.227 0.227 1.0 IndianRed4 +0 1.000 0.510 0.278 1.0 sienna1 +0 0.933 0.475 0.259 1.0 sienna2 +0 0.804 0.408 0.224 1.0 sienna3 +0 0.545 0.278 0.149 1.0 sienna4 +0 1.000 0.827 0.608 1.0 burlywood1 +0 0.933 0.773 0.569 1.0 burlywood2 +0 0.804 0.667 0.490 1.0 burlywood3 +0 0.545 0.451 0.333 1.0 burlywood4 +0 1.000 0.906 0.729 1.0 wheat1 +0 0.933 0.847 0.682 1.0 wheat2 +0 0.804 0.729 0.588 1.0 wheat3 +0 0.545 0.494 0.400 1.0 wheat4 +0 1.000 0.647 0.310 1.0 tan1 +0 0.933 0.604 0.286 1.0 tan2 +0 0.804 0.522 0.247 1.0 tan3 +0 0.545 0.353 0.169 1.0 tan4 +0 1.000 0.498 0.141 1.0 chocolate1 +0 0.933 0.463 0.129 1.0 chocolate2 +0 0.804 0.400 0.114 1.0 chocolate3 +0 0.545 0.271 0.075 1.0 chocolate4 +0 1.000 0.188 0.188 1.0 firebrick1 +0 0.933 0.173 0.173 1.0 firebrick2 +0 0.804 0.149 0.149 1.0 firebrick3 +0 0.545 0.102 0.102 1.0 firebrick4 +0 1.000 0.251 0.251 1.0 brown1 +0 0.933 0.231 0.231 1.0 brown2 +0 0.804 0.200 0.200 1.0 brown3 +0 0.545 0.137 0.137 1.0 brown4 +0 1.000 0.549 0.412 1.0 salmon1 +0 0.933 0.510 0.384 1.0 salmon2 +0 0.804 0.439 0.329 1.0 salmon3 +0 0.545 0.298 0.224 1.0 salmon4 +0 1.000 0.627 0.478 1.0 LightSalmon1 +0 0.933 0.584 0.447 1.0 LightSalmon2 +0 0.804 0.506 0.384 1.0 LightSalmon3 +0 0.545 0.341 0.259 1.0 LightSalmon4 +0 1.000 0.647 0.000 1.0 orange1 +0 0.933 0.604 0.000 1.0 orange2 +0 0.804 0.522 0.000 1.0 orange3 +0 0.545 0.353 0.000 1.0 orange4 +0 1.000 0.498 0.000 1.0 DarkOrange1 +0 0.933 0.463 0.000 1.0 DarkOrange2 +0 0.804 0.400 0.000 1.0 DarkOrange3 +0 0.545 0.271 0.000 1.0 DarkOrange4 +0 1.000 0.447 0.337 1.0 coral1 +0 0.933 0.416 0.314 1.0 coral2 +0 0.804 0.357 0.271 1.0 coral3 +0 0.545 0.243 0.184 1.0 coral4 +0 1.000 0.388 0.278 1.0 tomato1 +0 0.933 0.361 0.259 1.0 tomato2 +0 0.804 0.310 0.224 1.0 tomato3 +0 0.545 0.212 0.149 1.0 tomato4 +0 1.000 0.271 0.000 1.0 OrangeRed1 +0 0.933 0.251 0.000 1.0 OrangeRed2 +0 0.804 0.216 0.000 1.0 OrangeRed3 +0 0.545 0.145 0.000 1.0 OrangeRed4 +0 1.000 0.000 0.000 1.0 red1 +0 0.933 0.000 0.000 1.0 red2 +0 0.804 0.000 0.000 1.0 red3 +0 0.545 0.000 0.000 1.0 red4 +0 1.000 0.078 0.576 1.0 DeepPink1 +0 0.933 0.071 0.537 1.0 DeepPink2 +0 0.804 0.063 0.463 1.0 DeepPink3 +0 0.545 0.039 0.314 1.0 DeepPink4 +0 1.000 0.431 0.706 1.0 HotPink1 +0 0.933 0.416 0.655 1.0 HotPink2 +0 0.804 0.376 0.565 1.0 HotPink3 +0 0.545 0.227 0.384 1.0 HotPink4 +0 1.000 0.710 0.773 1.0 pink1 +0 0.933 0.663 0.722 1.0 pink2 +0 0.804 0.569 0.620 1.0 pink3 +0 0.545 0.388 0.424 1.0 pink4 +0 1.000 0.682 0.725 1.0 LightPink1 +0 0.933 0.635 0.678 1.0 LightPink2 +0 0.804 0.549 0.584 1.0 LightPink3 +0 0.545 0.373 0.396 1.0 LightPink4 +0 1.000 0.510 0.671 1.0 PaleVioletRed1 +0 0.933 0.475 0.624 1.0 PaleVioletRed2 +0 0.804 0.408 0.537 1.0 PaleVioletRed3 +0 0.545 0.278 0.365 1.0 PaleVioletRed4 +0 1.000 0.204 0.702 1.0 maroon1 +0 0.933 0.188 0.655 1.0 maroon2 +0 0.804 0.161 0.565 1.0 maroon3 +0 0.545 0.110 0.384 1.0 maroon4 +0 1.000 0.243 0.588 1.0 VioletRed1 +0 0.933 0.227 0.549 1.0 VioletRed2 +0 0.804 0.196 0.471 1.0 VioletRed3 +0 0.545 0.133 0.322 1.0 VioletRed4 +0 1.000 0.000 1.000 1.0 magenta1 +0 0.933 0.000 0.933 1.0 magenta2 +0 0.804 0.000 0.804 1.0 magenta3 +0 0.545 0.000 0.545 1.0 magenta4 +0 1.000 0.514 0.980 1.0 orchid1 +0 0.933 0.478 0.914 1.0 orchid2 +0 0.804 0.412 0.788 1.0 orchid3 +0 0.545 0.278 0.537 1.0 orchid4 +0 1.000 0.733 1.000 1.0 plum1 +0 0.933 0.682 0.933 1.0 plum2 +0 0.804 0.588 0.804 1.0 plum3 +0 0.545 0.400 0.545 1.0 plum4 +0 0.878 0.400 1.000 1.0 MediumOrchid1 +0 0.820 0.373 0.933 1.0 MediumOrchid2 +0 0.706 0.322 0.804 1.0 MediumOrchid3 +0 0.478 0.216 0.545 1.0 MediumOrchid4 +0 0.749 0.243 1.000 1.0 DarkOrchid1 +0 0.698 0.227 0.933 1.0 DarkOrchid2 +0 0.604 0.196 0.804 1.0 DarkOrchid3 +0 0.408 0.133 0.545 1.0 DarkOrchid4 +0 0.608 0.188 1.000 1.0 purple1 +0 0.569 0.173 0.933 1.0 purple2 +0 0.490 0.149 0.804 1.0 purple3 +0 0.333 0.102 0.545 1.0 purple4 +0 0.671 0.510 1.000 1.0 MediumPurple1 +0 0.624 0.475 0.933 1.0 MediumPurple2 +0 0.537 0.408 0.804 1.0 MediumPurple3 +0 0.365 0.278 0.545 1.0 MediumPurple4 +0 1.000 0.882 1.000 1.0 thistle1 +0 0.933 0.824 0.933 1.0 thistle2 +0 0.804 0.710 0.804 1.0 thistle3 +0 0.545 0.482 0.545 1.0 thistle4 +0 0.000 0.000 0.000 1.0 gray0 +0 0.000 0.000 0.000 1.0 grey0 +0 0.012 0.012 0.012 1.0 gray1 +0 0.012 0.012 0.012 1.0 grey1 +0 0.020 0.020 0.020 1.0 gray2 +0 0.020 0.020 0.020 1.0 grey2 +0 0.031 0.031 0.031 1.0 gray3 +0 0.031 0.031 0.031 1.0 grey3 +0 0.039 0.039 0.039 1.0 gray4 +0 0.039 0.039 0.039 1.0 grey4 +0 0.051 0.051 0.051 1.0 gray5 +0 0.051 0.051 0.051 1.0 grey5 +0 0.059 0.059 0.059 1.0 gray6 +0 0.059 0.059 0.059 1.0 grey6 +0 0.071 0.071 0.071 1.0 gray7 +0 0.071 0.071 0.071 1.0 grey7 +0 0.078 0.078 0.078 1.0 gray8 +0 0.078 0.078 0.078 1.0 grey8 +0 0.090 0.090 0.090 1.0 gray9 +0 0.090 0.090 0.090 1.0 grey9 +0 0.102 0.102 0.102 1.0 gray10 +0 0.102 0.102 0.102 1.0 grey10 +0 0.110 0.110 0.110 1.0 gray11 +0 0.110 0.110 0.110 1.0 grey11 +0 0.122 0.122 0.122 1.0 gray12 +0 0.122 0.122 0.122 1.0 grey12 +0 0.129 0.129 0.129 1.0 gray13 +0 0.129 0.129 0.129 1.0 grey13 +0 0.141 0.141 0.141 1.0 gray14 +0 0.141 0.141 0.141 1.0 grey14 +0 0.149 0.149 0.149 1.0 gray15 +0 0.149 0.149 0.149 1.0 grey15 +0 0.161 0.161 0.161 1.0 gray16 +0 0.161 0.161 0.161 1.0 grey16 +0 0.169 0.169 0.169 1.0 gray17 +0 0.169 0.169 0.169 1.0 grey17 +0 0.180 0.180 0.180 1.0 gray18 +0 0.180 0.180 0.180 1.0 grey18 +0 0.188 0.188 0.188 1.0 gray19 +0 0.188 0.188 0.188 1.0 grey19 +0 0.200 0.200 0.200 1.0 gray20 +0 0.200 0.200 0.200 1.0 grey20 +0 0.212 0.212 0.212 1.0 gray21 +0 0.212 0.212 0.212 1.0 grey21 +0 0.220 0.220 0.220 1.0 gray22 +0 0.220 0.220 0.220 1.0 grey22 +0 0.231 0.231 0.231 1.0 gray23 +0 0.231 0.231 0.231 1.0 grey23 +0 0.239 0.239 0.239 1.0 gray24 +0 0.239 0.239 0.239 1.0 grey24 +0 0.251 0.251 0.251 1.0 gray25 +0 0.251 0.251 0.251 1.0 grey25 +0 0.259 0.259 0.259 1.0 gray26 +0 0.259 0.259 0.259 1.0 grey26 +0 0.271 0.271 0.271 1.0 gray27 +0 0.271 0.271 0.271 1.0 grey27 +0 0.278 0.278 0.278 1.0 gray28 +0 0.278 0.278 0.278 1.0 grey28 +0 0.290 0.290 0.290 1.0 gray29 +0 0.290 0.290 0.290 1.0 grey29 +0 0.302 0.302 0.302 1.0 gray30 +0 0.302 0.302 0.302 1.0 grey30 +0 0.310 0.310 0.310 1.0 gray31 +0 0.310 0.310 0.310 1.0 grey31 +0 0.322 0.322 0.322 1.0 gray32 +0 0.322 0.322 0.322 1.0 grey32 +0 0.329 0.329 0.329 1.0 gray33 +0 0.329 0.329 0.329 1.0 grey33 +0 0.341 0.341 0.341 1.0 gray34 +0 0.341 0.341 0.341 1.0 grey34 +0 0.349 0.349 0.349 1.0 gray35 +0 0.349 0.349 0.349 1.0 grey35 +0 0.361 0.361 0.361 1.0 gray36 +0 0.361 0.361 0.361 1.0 grey36 +0 0.369 0.369 0.369 1.0 gray37 +0 0.369 0.369 0.369 1.0 grey37 +0 0.380 0.380 0.380 1.0 gray38 +0 0.380 0.380 0.380 1.0 grey38 +0 0.388 0.388 0.388 1.0 gray39 +0 0.388 0.388 0.388 1.0 grey39 +0 0.400 0.400 0.400 1.0 gray40 +0 0.400 0.400 0.400 1.0 grey40 +0 0.412 0.412 0.412 1.0 gray41 +0 0.412 0.412 0.412 1.0 grey41 +0 0.420 0.420 0.420 1.0 gray42 +0 0.420 0.420 0.420 1.0 grey42 +0 0.431 0.431 0.431 1.0 gray43 +0 0.431 0.431 0.431 1.0 grey43 +0 0.439 0.439 0.439 1.0 gray44 +0 0.439 0.439 0.439 1.0 grey44 +0 0.451 0.451 0.451 1.0 gray45 +0 0.451 0.451 0.451 1.0 grey45 +0 0.459 0.459 0.459 1.0 gray46 +0 0.459 0.459 0.459 1.0 grey46 +0 0.471 0.471 0.471 1.0 gray47 +0 0.471 0.471 0.471 1.0 grey47 +0 0.478 0.478 0.478 1.0 gray48 +0 0.478 0.478 0.478 1.0 grey48 +0 0.490 0.490 0.490 1.0 gray49 +0 0.490 0.490 0.490 1.0 grey49 +0 0.498 0.498 0.498 1.0 gray50 +0 0.498 0.498 0.498 1.0 grey50 +0 0.510 0.510 0.510 1.0 gray51 +0 0.510 0.510 0.510 1.0 grey51 +0 0.522 0.522 0.522 1.0 gray52 +0 0.522 0.522 0.522 1.0 grey52 +0 0.529 0.529 0.529 1.0 gray53 +0 0.529 0.529 0.529 1.0 grey53 +0 0.541 0.541 0.541 1.0 gray54 +0 0.541 0.541 0.541 1.0 grey54 +0 0.549 0.549 0.549 1.0 gray55 +0 0.549 0.549 0.549 1.0 grey55 +0 0.561 0.561 0.561 1.0 gray56 +0 0.561 0.561 0.561 1.0 grey56 +0 0.569 0.569 0.569 1.0 gray57 +0 0.569 0.569 0.569 1.0 grey57 +0 0.580 0.580 0.580 1.0 gray58 +0 0.580 0.580 0.580 1.0 grey58 +0 0.588 0.588 0.588 1.0 gray59 +0 0.588 0.588 0.588 1.0 grey59 +0 0.600 0.600 0.600 1.0 gray60 +0 0.600 0.600 0.600 1.0 grey60 +0 0.612 0.612 0.612 1.0 gray61 +0 0.612 0.612 0.612 1.0 grey61 +0 0.620 0.620 0.620 1.0 gray62 +0 0.620 0.620 0.620 1.0 grey62 +0 0.631 0.631 0.631 1.0 gray63 +0 0.631 0.631 0.631 1.0 grey63 +0 0.639 0.639 0.639 1.0 gray64 +0 0.639 0.639 0.639 1.0 grey64 +0 0.651 0.651 0.651 1.0 gray65 +0 0.651 0.651 0.651 1.0 grey65 +0 0.659 0.659 0.659 1.0 gray66 +0 0.659 0.659 0.659 1.0 grey66 +0 0.671 0.671 0.671 1.0 gray67 +0 0.671 0.671 0.671 1.0 grey67 +0 0.678 0.678 0.678 1.0 gray68 +0 0.678 0.678 0.678 1.0 grey68 +0 0.690 0.690 0.690 1.0 gray69 +0 0.690 0.690 0.690 1.0 grey69 +0 0.702 0.702 0.702 1.0 gray70 +0 0.702 0.702 0.702 1.0 grey70 +0 0.710 0.710 0.710 1.0 gray71 +0 0.710 0.710 0.710 1.0 grey71 +0 0.722 0.722 0.722 1.0 gray72 +0 0.722 0.722 0.722 1.0 grey72 +0 0.729 0.729 0.729 1.0 gray73 +0 0.729 0.729 0.729 1.0 grey73 +0 0.741 0.741 0.741 1.0 gray74 +0 0.741 0.741 0.741 1.0 grey74 +0 0.749 0.749 0.749 1.0 gray75 +0 0.749 0.749 0.749 1.0 grey75 +0 0.761 0.761 0.761 1.0 gray76 +0 0.761 0.761 0.761 1.0 grey76 +0 0.769 0.769 0.769 1.0 gray77 +0 0.769 0.769 0.769 1.0 grey77 +0 0.780 0.780 0.780 1.0 gray78 +0 0.780 0.780 0.780 1.0 grey78 +0 0.788 0.788 0.788 1.0 gray79 +0 0.788 0.788 0.788 1.0 grey79 +0 0.800 0.800 0.800 1.0 gray80 +0 0.800 0.800 0.800 1.0 grey80 +0 0.812 0.812 0.812 1.0 gray81 +0 0.812 0.812 0.812 1.0 grey81 +0 0.820 0.820 0.820 1.0 gray82 +0 0.820 0.820 0.820 1.0 grey82 +0 0.831 0.831 0.831 1.0 gray83 +0 0.831 0.831 0.831 1.0 grey83 +0 0.839 0.839 0.839 1.0 gray84 +0 0.839 0.839 0.839 1.0 grey84 +0 0.851 0.851 0.851 1.0 gray85 +0 0.851 0.851 0.851 1.0 grey85 +0 0.859 0.859 0.859 1.0 gray86 +0 0.859 0.859 0.859 1.0 grey86 +0 0.871 0.871 0.871 1.0 gray87 +0 0.871 0.871 0.871 1.0 grey87 +0 0.878 0.878 0.878 1.0 gray88 +0 0.878 0.878 0.878 1.0 grey88 +0 0.890 0.890 0.890 1.0 gray89 +0 0.890 0.890 0.890 1.0 grey89 +0 0.898 0.898 0.898 1.0 gray90 +0 0.898 0.898 0.898 1.0 grey90 +0 0.910 0.910 0.910 1.0 gray91 +0 0.910 0.910 0.910 1.0 grey91 +0 0.922 0.922 0.922 1.0 gray92 +0 0.922 0.922 0.922 1.0 grey92 +0 0.929 0.929 0.929 1.0 gray93 +0 0.929 0.929 0.929 1.0 grey93 +0 0.941 0.941 0.941 1.0 gray94 +0 0.941 0.941 0.941 1.0 grey94 +0 0.949 0.949 0.949 1.0 gray95 +0 0.949 0.949 0.949 1.0 grey95 +0 0.961 0.961 0.961 1.0 gray96 +0 0.961 0.961 0.961 1.0 grey96 +0 0.969 0.969 0.969 1.0 gray97 +0 0.969 0.969 0.969 1.0 grey97 +0 0.980 0.980 0.980 1.0 gray98 +0 0.980 0.980 0.980 1.0 grey98 +0 0.988 0.988 0.988 1.0 gray99 +0 0.988 0.988 0.988 1.0 grey99 +0 1.000 1.000 1.000 1.0 gray100 +0 1.000 1.000 1.000 1.0 grey100 +0 0.663 0.663 0.663 1.0 dark grey +0 0.663 0.663 0.663 1.0 DarkGrey +0 0.663 0.663 0.663 1.0 dark gray +0 0.663 0.663 0.663 1.0 DarkGray +0 0.000 0.000 0.545 1.0 dark blue +0 0.000 0.000 0.545 1.0 DarkBlue +0 0.000 0.545 0.545 1.0 dark cyan +0 0.000 0.545 0.545 1.0 DarkCyan +0 0.545 0.000 0.545 1.0 dark magenta +0 0.545 0.000 0.545 1.0 DarkMagenta +0 0.545 0.000 0.000 1.0 dark red +0 0.545 0.000 0.000 1.0 DarkRed +0 0.565 0.933 0.565 1.0 light green +0 0.565 0.933 0.565 1.0 LightGreen +0 0.500 0.500 0.500 1.0 Gray +0 0.500 0.500 0.500 1.0 Grey +0 0.667 0.667 0.667 1.0 Light Gray +0 0.667 0.667 0.667 1.0 Light Grey +0 0.000 0.000 0.000 0.0 Highlight diff -r ff312a846b25 -r d45acf0c8d23 lib-src/.cvsignore --- a/lib-src/.cvsignore Tue Jul 15 15:45:05 2008 +0000 +++ b/lib-src/.cvsignore Tue Jul 15 18:15:18 2008 +0000 @@ -11,6 +11,7 @@ fakemail getopt.h hexl +mac-fix-env make-docfile movemail obj diff -r ff312a846b25 -r d45acf0c8d23 lib-src/ChangeLog --- a/lib-src/ChangeLog Tue Jul 15 15:45:05 2008 +0000 +++ b/lib-src/ChangeLog Tue Jul 15 18:15:18 2008 +0000 @@ -1,3 +1,13 @@ +2008-07-15 Adrian Robert + + * .cvsignore: Add mac-fix-env. + * mac-fix-env.m: New file, automatically update + ~/.MacOSX/environment.plist on OS X systems to expose environment + variables inside Emacs started from icon. + * Makefile.in: Add -universal to CFLAGS on OS X, add mac-fix-env to + programs to build. + * make-docfile.c: Add .m to list of file extensions. + 2008-07-12 Dan Nicolaescu * movemail.c (main): Use int instead of WAITTYPE. diff -r ff312a846b25 -r d45acf0c8d23 lib-src/Makefile.in --- a/lib-src/Makefile.in Tue Jul 15 15:45:05 2008 +0000 +++ b/lib-src/Makefile.in Tue Jul 15 18:15:18 2008 +0000 @@ -144,6 +144,23 @@ #define NOT_C_CODE #include "../src/config.h" +#if defined(COCOA) +/* Build these programs as universal binaries. */ +CFLAGS := $(CFLAGS) -universal +/* Add mac-fix-env for OS X systems running NS version. */ +INSTALLABLES = etags${EXEEXT} ctags${EXEEXT} emacsclient${EXEEXT} b2m${EXEEXT} ebrowse${EXEEXT} mac-fix-env${EXEEXT} +#endif + +/* Some platforms that the GNUstep port runs on put strip options in + INSTALL_PROGRAM which cause errors. But, not being sure all other + platforms are setting this, we will only use the alternative + INSTALL_SCRIPT variable on GNUstep/Cocoa builds. */ +#ifndef HAVE_NS +INSTALL_SCRIPT = @INSTALL_PROGRAM@ +#else +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +#endif + /* Some machines don\'t find the standard C libraries in the usual place. */ #ifndef ORDINARY_LINK #ifndef LIB_STANDARD_LIBSRC @@ -253,12 +270,22 @@ BASE_CFLAGS = C_SWITCH_SYSTEM C_SWITCH_MACHINE -DHAVE_CONFIG_H \ -I. -I../src -I${srcdir} -I${srcdir}/../src ${CPPFLAGS} ${CFLAGS} +.SUFFIXES: .m + /* This is the default compilation command. But we should never rely on it, because some make version failed to find it for getopt.o. Using an explicit command made it work. */ .c.o: ${CC} -c ${CPP_CFLAGS} $< +#ifdef HAVE_NS +.m.o: +#ifdef GNUSTEP + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -fgnu-runtime -Wno-import -fconstant-string-class=NSConstantString $< +#else + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $< +#endif +#endif all: ${DONT_INSTALL} ${UTILITIES} ${INSTALLABLES} ${SCRIPTS} ${INSTALLABLE_SCRIPTS} @@ -455,3 +482,8 @@ update-game-score.o: ${srcdir}/update-game-score.c ../src/config.h $(GETOPT_H) $(CC) -c ${CPP_CFLAGS} ${srcdir}/update-game-score.c \ -DHAVE_SHARED_GAME_DIR="\"$(gamedir)\"" + +#if defined(COCOA) +mac-fix-env: ${srcdir}/mac-fix-env.m + $(CC) -o mac-fix-env ${srcdir}/mac-fix-env.m -prebind -framework Foundation +#endif diff -r ff312a846b25 -r d45acf0c8d23 lib-src/mac-fix-env.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib-src/mac-fix-env.m Tue Jul 15 18:15:18 2008 +0000 @@ -0,0 +1,71 @@ +/* mac-fix-env: A small utility to pick up the shell environment on MacOS X + and insert it into the file ~/.MacOSX/environment.plist + creating if necessary. + Copyright (C) 1989, 1993, 2005, 2008 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 3, 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., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. + + usage: + Run from command line (in Terminal) once or whenever path changes: + + /Applications/Emacs.app/Contents/MacOS/bin/mac-fix-env + + (change initial part to where you installed Emacs). +*/ + +#import +#include + +int main(int argc, char *argv[]) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSMutableDictionary *envPlist; + NSString *file = [[NSHomeDirectory() + stringByAppendingPathComponent:@".MacOSX"] + stringByAppendingPathComponent:@"environment.plist"]; + NSString *path = [NSString stringWithCString: getenv("PATH")]; + + envPlist = [[NSDictionary dictionaryWithContentsOfFile: file] mutableCopy]; + if (envPlist == nil) + { + // create + NSString *dir = [file stringByDeletingLastPathComponent]; + envPlist = [NSMutableDictionary dictionaryWithCapacity: 5]; + + if ([[NSFileManager defaultManager] fileExistsAtPath: dir] == NO) + { + if ([[NSFileManager defaultManager] createDirectoryAtPath:dir + attributes:nil]==NO) + { + NSLog(@":\nCould not create directory at '%@'; aborting.",dir); + return 1; + } + } + } + + [envPlist setObject: path forKey: @"PATH"]; + + if ([envPlist writeToFile: file atomically: YES] == NO) + { + NSLog(@":\nCould not write file at '%@'; aborting.", file); + return 1; + } + + NSLog(@":\nWrote file to '%@'.\nPlease inspect it to make sure PATH is correct.", file); + return 0; +} diff -r ff312a846b25 -r d45acf0c8d23 lib-src/make-docfile.c --- a/lib-src/make-docfile.c Tue Jul 15 15:45:05 2008 +0000 +++ b/lib-src/make-docfile.c Tue Jul 15 18:15:18 2008 +0000 @@ -533,7 +533,7 @@ } /* Read through a c file. If a .o file is named, - the corresponding .c file is read instead. + the corresponding .c or .m file is read instead. Looks for DEFUN constructs such as are defined in ../src/lisp.h. Accepts any word starting DEF... so it finds DEFSIMPLE and DEFPRED. */ @@ -555,6 +555,15 @@ infile = fopen (filename, mode); + if (infile == NULL && extension == 'o') + { + /* try .m */ + filename[strlen (filename) - 1] = 'm'; + infile = fopen (filename, mode); + if (infile == NULL) + filename[strlen (filename) - 1] = 'c'; /* don't confuse people */ + } + /* No error if non-ex input file */ if (infile == NULL) { diff -r ff312a846b25 -r d45acf0c8d23 lisp/ChangeLog --- a/lisp/ChangeLog Tue Jul 15 15:45:05 2008 +0000 +++ b/lisp/ChangeLog Tue Jul 15 18:15:18 2008 +0000 @@ -1,3 +1,42 @@ +2008-07-15 Adrian Robert + * ns-carbon-compat.el: New file: user-visible compatibility of + NeXTstep port with Carbon port. + * ns-grabenv.el: New file: functionality useful on OS X platform to + expose environment variables inside Emacs started from icon. + * Makefile.in: Add above three files. + * cus-edit.el + * cus-face.el + * disp-table.el + * faces.el + * info.el + * mouse.el + * mwheel.el + * simple.el: Add ns to window systems treated as GUIs. + * facemenu.el (facemenu-read-color): Don't require a name match under + NS, to allow numeric color entry. + * frame.el (make-frame-on-display): Follow code for 'x in initializing + 'ns window system if need be. + (various): Add 'ns as described above. + * loadup.el: Load ns-win.el if ns-windowing is active. + * startup.el (command-line-ns-option-alist): New constant to handle NS + windowing system specific command line args analogous to how they are + handled for X windows. + (command-line-1): Use the above where appropriate. + * version.el: Add NS port version. + * woman.el (woman-man.conf-path): Add /usr/share/misc to init path on + Darwin (usually OS X) systems. + (woman-use-own-frame): Include 'ns in list of GUI window systems. + * emulation/viper-util.el (ns-display-color-p) + (ns-color-defined-p): Remove these (caustically-commented) outdated + compensations for a port that was never itself integrated until now. + * gnus/gnus-util.el (gnus-select-frame-set-input-focus): Add support + for NS window system. + * international/mule-cmds.el: Add 'ns to list of special-cased window + systems (probably most of these, x/w32/mac/ns could be changed to + window-system non-nil). + * term/ns-win.el: New file: lisp-side support for NS windowing system. + + 2008-07-14 Jason Rumney * term/w32-win.el (x-handle-switch, x-handle-name-switch) diff -r ff312a846b25 -r d45acf0c8d23 lisp/Makefile.in --- a/lisp/Makefile.in Tue Jul 15 15:45:05 2008 +0000 +++ b/lisp/Makefile.in Tue Jul 15 18:15:18 2008 +0000 @@ -867,6 +867,8 @@ $(lisp)/net/zeroconf.elc \ $(lisp)/newcomment.elc \ $(lisp)/novice.elc \ + $(lisp)/ns-grabenv.elc \ + $(lisp)/ns-carbon-compat.elc \ $(lisp)/nxml/nxml-enc.elc \ $(lisp)/nxml/nxml-glyph.elc \ $(lisp)/nxml/nxml-maint.elc \ @@ -1110,6 +1112,7 @@ $(lisp)/tempo.elc \ $(lisp)/term.elc \ $(lisp)/term/mac-win.elc \ + $(lisp)/term/ns-win.elc \ $(lisp)/term/pc-win.elc \ $(lisp)/term/rxvt.elc \ $(lisp)/term/sun.elc \ diff -r ff312a846b25 -r d45acf0c8d23 lisp/cus-edit.el --- a/lisp/cus-edit.el Tue Jul 15 15:45:05 2008 +0000 +++ b/lisp/cus-edit.el Tue Jul 15 18:15:18 2008 +0000 @@ -2068,7 +2068,7 @@ ;;; The `custom' Widget. (defface custom-button - '((((type x w32 mac) (class color)) ; Like default modeline + '((((type x w32 mac ns) (class color)) ; Like default modeline (:box (:line-width 2 :style released-button) :background "lightgrey" :foreground "black")) (t @@ -2080,7 +2080,7 @@ (put 'custom-button-face 'face-alias 'custom-button) (defface custom-button-mouse - '((((type x w32 mac) (class color)) + '((((type x w32 mac ns) (class color)) (:box (:line-width 2 :style released-button) :background "grey90" :foreground "black")) (t @@ -2102,7 +2102,7 @@ (if custom-raised-buttons 'custom-button-mouse 'highlight)) (defface custom-button-pressed - '((((type x w32 mac) (class color)) + '((((type x w32 mac ns) (class color)) (:box (:line-width 2 :style pressed-button) :background "lightgrey" :foreground "black")) (t @@ -3163,8 +3163,12 @@ w32) (const :format "MAC " :sibling-args (:help-echo "\ -Macintosh OS.") +Macintosh OS (Carbon interface).") mac) + (const :format "NS " + :sibling-args (:help-echo "\ +GNUstep or Macintosh OS Cocoa interface.") + ns) (const :format "DOS " :sibling-args (:help-echo "\ Plain MS-DOS.") diff -r ff312a846b25 -r d45acf0c8d23 lisp/cus-face.el --- a/lisp/cus-face.el Tue Jul 15 15:45:05 2008 +0000 +++ b/lisp/cus-face.el Tue Jul 15 18:15:18 2008 +0000 @@ -44,7 +44,7 @@ ;; Create frame-local faces (dolist (frame (frame-list)) (face-spec-set-2 face frame value) - (when (memq (window-system frame) '(x w32 mac)) + (when (memq (window-system frame) '(x w32 mac ns)) (setq have-window-system t))) ;; When making a face after frames already exist (if have-window-system diff -r ff312a846b25 -r d45acf0c8d23 lisp/disp-table.el --- a/lisp/disp-table.el Tue Jul 15 15:45:05 2008 +0000 +++ b/lisp/disp-table.el Tue Jul 15 18:15:18 2008 +0000 @@ -142,7 +142,7 @@ "Display character C as character SC in the g1 character set. This function assumes that your terminal uses the SO/SI characters; it is meaningless for an X frame." - (if (memq window-system '(x w32 mac)) + (if (memq window-system '(x w32 mac ns)) (error "Cannot use string glyphs in a windowing system")) (or standard-display-table (setq standard-display-table (make-display-table))) @@ -154,7 +154,7 @@ "Display character C as character GC in graphics character set. This function assumes VT100-compatible escapes; it is meaningless for an X frame." - (if (memq window-system '(x w32 mac)) + (if (memq window-system '(x w32 mac ns)) (error "Cannot use string glyphs in a windowing system")) (or standard-display-table (setq standard-display-table (make-display-table))) @@ -243,7 +243,7 @@ (equal (aref standard-display-table 161) [161]))) (progn (standard-display-default 160 255) - (unless (or (memq window-system '(x w32 mac))) + (unless (or (memq window-system '(x w32 mac ns))) (and (terminal-coding-system) (set-terminal-coding-system nil)))) @@ -255,7 +255,7 @@ ;; unless some other has been specified. (if (equal current-language-environment "English") (set-language-environment "latin-1")) - (unless (or noninteractive (memq window-system '(x w32 mac))) + (unless (or noninteractive (memq window-system '(x w32 mac ns))) ;; Send those codes literally to a character-based terminal. ;; If we are using single-byte characters, ;; it doesn't matter which coding system we use. diff -r ff312a846b25 -r d45acf0c8d23 lisp/emulation/viper-util.el --- a/lisp/emulation/viper-util.el Tue Jul 15 15:45:05 2008 +0000 +++ b/lisp/emulation/viper-util.el Tue Jul 15 18:15:18 2008 +0000 @@ -52,14 +52,6 @@ (require 'viper-init) -;; A fix for NeXT Step -;; Should go away, when NS people fix the design flaw, which leaves the -;; two x-* functions undefined. -(if (and (not (fboundp 'x-display-color-p)) (fboundp 'ns-display-color-p)) - (fset 'x-display-color-p (symbol-function 'ns-display-color-p))) -(if (and (not (fboundp 'x-color-defined-p)) (fboundp 'ns-color-defined-p)) - (fset 'x-color-defined-p (symbol-function 'ns-color-defined-p))) - (defalias 'viper-overlay-p (if (featurep 'xemacs) 'extentp 'overlayp)) diff -r ff312a846b25 -r d45acf0c8d23 lisp/facemenu.el --- a/lisp/facemenu.el Tue Jul 15 15:45:05 2008 +0000 +++ b/lisp/facemenu.el Tue Jul 15 18:15:18 2008 +0000 @@ -460,10 +460,11 @@ (defun facemenu-read-color (&optional prompt) "Read a color using the minibuffer." (let* ((completion-ignore-case t) + (require-match (not (eq window-system 'ns))) (col (completing-read (or prompt "Color: ") (or facemenu-color-alist (defined-colors)) - nil t))) + nil require-match))) (if (equal "" col) nil col))) diff -r ff312a846b25 -r d45acf0c8d23 lisp/faces.el --- a/lisp/faces.el Tue Jul 15 15:45:05 2008 +0000 +++ b/lisp/faces.el Tue Jul 15 18:15:18 2008 +0000 @@ -338,7 +338,7 @@ (defun set-face-attributes-from-resources (face frame) "Set attributes of FACE from X resources for FRAME." - (when (memq (framep frame) '(x w32 mac)) + (when (memq (framep frame) '(x w32 mac ns)) (dolist (definition face-x-resources) (let ((attribute (car definition))) (dolist (entry (cdr definition)) @@ -1010,7 +1010,7 @@ ((:height) 'integerp) (:stipple - (and (memq (window-system frame) '(x w32 mac)) + (and (memq (window-system frame) '(x w32 mac ns)) (mapcar #'list (apply #'nconc (mapcar (lambda (dir) @@ -1129,7 +1129,7 @@ ;; explicitly in VALID, using color approximation code ;; in tty-colors.el. (when (and (memq attribute '(:foreground :background)) - (not (memq (window-system frame) '(x w32 mac))) + (not (memq (window-system frame) '(x w32 mac ns))) (not (member new-value '("unspecified" "unspecified-fg" "unspecified-bg")))) @@ -1624,7 +1624,7 @@ The value may be different for frames on different display types. If FRAME doesn't support colors, the value is nil. If FRAME is nil, that stands for the selected frame." - (if (memq (framep (or frame (selected-frame))) '(x w32 mac)) + (if (memq (framep (or frame (selected-frame))) '(x w32 mac ns)) (xw-defined-colors frame) (mapcar 'car (tty-color-alist frame)))) (defalias 'x-defined-colors 'defined-colors) @@ -1638,7 +1638,7 @@ \"unspecified-fg\" or \"unspecified-bg\", the value is nil." (if (member color '(unspecified "unspecified-bg" "unspecified-fg")) nil - (if (member (framep (or frame (selected-frame))) '(x w32 mac)) + (if (member (framep (or frame (selected-frame))) '(x w32 mac ns)) (xw-color-defined-p color frame) (numberp (tty-color-translate color frame))))) (defalias 'x-color-defined-p 'color-defined-p) @@ -1656,7 +1656,7 @@ \"unspecified-fg\" or \"unspecified-bg\", the value is nil." (if (member color '(unspecified "unspecified-fg" "unspecified-bg")) nil - (if (memq (framep (or frame (selected-frame))) '(x w32 mac)) + (if (memq (framep (or frame (selected-frame))) '(x w32 mac ns)) (xw-color-values color frame) (tty-color-values color frame)))) (defalias 'x-color-values 'color-values) @@ -1668,7 +1668,7 @@ 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." - (if (memq (framep-on-display display) '(x w32 mac)) + (if (memq (framep-on-display display) '(x w32 mac ns)) (xw-display-color-p display) (tty-display-color-p display))) (defalias 'x-display-color-p 'display-color-p) @@ -1679,7 +1679,7 @@ "Return non-nil if frames on DISPLAY can display shades of gray." (let ((frame-type (framep-on-display display))) (cond - ((memq frame-type '(x w32 mac)) + ((memq frame-type '(x w32 mac ns)) (x-display-grayscale-p display)) (t (> (tty-color-gray-shades display) 2))))) @@ -2495,7 +2495,7 @@ '((default :box (:line-width 1 :style released-button) :foreground "black") - (((type x w32 mac) (class color)) + (((type x w32 mac ns) (class color)) :background "grey75") (((type x) (class mono)) :background "grey")) diff -r ff312a846b25 -r d45acf0c8d23 lisp/frame.el --- a/lisp/frame.el Tue Jul 15 15:45:05 2008 +0000 +++ b/lisp/frame.el Tue Jul 15 18:15:18 2008 +0000 @@ -610,12 +610,19 @@ "Make a frame on X display DISPLAY. The optional second argument PARAMETERS specifies additional frame parameters." (interactive "sMake frame on display: ") - (or (string-match "\\`[^:]*:[0-9]+\\(\\.[0-9]+\\)?\\'" display) - (error "Invalid display, not HOST:SERVER or HOST:SERVER.SCREEN")) - (when (and (boundp 'x-initialized) (not x-initialized)) - (setq x-display-name display) - (x-initialize-window-system)) - (make-frame `((window-system . x) (display . ,display) . ,parameters))) + (if (featurep 'ns-windowing) + (progn + (when (and (boundp 'ns-initialized) (not ns-initialized)) + (setq ns-display-name display) + (ns-initialize-window-system)) + (make-frame `((window-system . ns) (display . ,display) . ,parameters))) + (progn + (or (string-match "\\`[^:]*:[0-9]+\\(\\.[0-9]+\\)?\\'" display) + (error "Invalid display, not HOST:SERVER or HOST:SERVER.SCREEN")) + (when (and (boundp 'x-initialized) (not x-initialized)) + (setq x-display-name display) + (x-initialize-window-system)) + (make-frame `((window-system . x) (display . ,display) . ,parameters))))) (defun make-frame-on-tty (tty type &optional parameters) "Make a frame on terminal device TTY. @@ -835,7 +842,7 @@ (select-frame frame) (raise-frame frame) ;; Ensure, if possible, that frame gets input focus. - (when (memq (window-system frame) '(x mac w32)) + (when (memq (window-system frame) '(x mac w32 ns)) (x-focus-frame frame)) (when focus-follows-mouse (set-mouse-position (selected-frame) (1- (frame-width)) 0))) @@ -880,7 +887,7 @@ (interactive) (let ((type (framep (selected-frame)))) (cond - ((memq type '(x w32)) (iconify-or-deiconify-frame)) + ((memq type '(x ns w32)) (iconify-or-deiconify-frame)) ((eq type t) (if (controlling-tty-p) (suspend-emacs) @@ -920,7 +927,7 @@ (raise-frame frame) (select-frame frame) ;; Ensure, if possible, that frame gets input focus. - (cond ((memq (window-system frame) '(x w32)) + (cond ((memq (window-system frame) '(x w32 ns)) (x-focus-frame frame))) (when focus-follows-mouse (set-mouse-position frame (1- (frame-width frame)) 0)))) @@ -1157,8 +1164,8 @@ ((eq system-type 'windows-nt) (with-no-warnings (> w32-num-mouse-buttons 0))) - ((memq frame-type '(x mac)) - t) ;; We assume X and Mac *always* have a pointing device + ((memq frame-type '(x mac ns)) + t) ;; We assume X, Mac, NeXTstep *always* have a pointing device (t (or (and (featurep 'xt-mouse) xterm-mouse-mode) @@ -1173,7 +1180,7 @@ Support for popup menus requires that the mouse be available." (and (let ((frame-type (framep-on-display display))) - (memq frame-type '(x w32 pc mac))) + (memq frame-type '(x w32 pc mac ns))) (display-mouse-p display))) (defun display-graphic-p (&optional display) @@ -1183,7 +1190,7 @@ that use a window system such as X, and false for text-only terminals. DISPLAY can be a display name, a frame, or nil (meaning the selected frame's display)." - (not (null (memq (framep-on-display display) '(x w32 mac))))) + (not (null (memq (framep-on-display display) '(x w32 mac ns))))) (defun display-images-p (&optional display) "Return non-nil if DISPLAY can display images. @@ -1211,7 +1218,7 @@ ;; the Windows' DOS Box. (with-no-warnings (not (null dos-windows-version)))) - ((memq frame-type '(x w32 mac)) + ((memq frame-type '(x w32 mac ns)) t) ;; FIXME? (t nil)))) @@ -1222,7 +1229,7 @@ "Return the number of screens associated with DISPLAY." (let ((frame-type (framep-on-display display))) (cond - ((memq frame-type '(x w32 mac)) + ((memq frame-type '(x w32 mac ns)) (x-display-screens display)) (t 1)))) @@ -1234,7 +1241,7 @@ For character terminals, each character counts as a single pixel." (let ((frame-type (framep-on-display display))) (cond - ((memq frame-type '(x w32 mac)) + ((memq frame-type '(x w32 mac ns)) (x-display-pixel-height display)) (t (frame-height (if (framep display) display (selected-frame))))))) @@ -1246,7 +1253,7 @@ For character terminals, each character counts as a single pixel." (let ((frame-type (framep-on-display display))) (cond - ((memq frame-type '(x w32 mac)) + ((memq frame-type '(x w32 mac ns)) (x-display-pixel-width display)) (t (frame-width (if (framep display) display (selected-frame))))))) @@ -1275,7 +1282,7 @@ "Return the height of DISPLAY's screen in millimeters. System values can be overridden by `display-mm-dimensions-alist'. If the information is unavailable, value is nil." - (and (memq (framep-on-display display) '(x w32 mac)) + (and (memq (framep-on-display display) '(x w32 mac ns)) (or (cddr (assoc (or display (frame-parameter nil 'display)) display-mm-dimensions-alist)) (cddr (assoc t display-mm-dimensions-alist)) @@ -1287,7 +1294,7 @@ "Return the width of DISPLAY's screen in millimeters. System values can be overridden by `display-mm-dimensions-alist'. If the information is unavailable, value is nil." - (and (memq (framep-on-display display) '(x w32 mac)) + (and (memq (framep-on-display display) '(x w32 mac ns)) (or (cadr (assoc (or display (frame-parameter nil 'display)) display-mm-dimensions-alist)) (cadr (assoc t display-mm-dimensions-alist)) @@ -1301,7 +1308,7 @@ the question is inapplicable to a certain kind of display." (let ((frame-type (framep-on-display display))) (cond - ((memq frame-type '(x w32 mac)) + ((memq frame-type '(x w32 mac ns)) (x-display-backing-store display)) (t 'not-useful)))) @@ -1312,7 +1319,7 @@ "Return non-nil if DISPLAY's screen supports the SaveUnder feature." (let ((frame-type (framep-on-display display))) (cond - ((memq frame-type '(x w32 mac)) + ((memq frame-type '(x w32 mac ns)) (x-display-save-under display)) (t 'not-useful)))) @@ -1323,7 +1330,7 @@ "Return the number of planes supported by DISPLAY." (let ((frame-type (framep-on-display display))) (cond - ((memq frame-type '(x w32 mac)) + ((memq frame-type '(x w32 mac ns)) (x-display-planes display)) ((eq frame-type 'pc) 4) @@ -1336,7 +1343,7 @@ "Return the number of color cells supported by DISPLAY." (let ((frame-type (framep-on-display display))) (cond - ((memq frame-type '(x w32 mac)) + ((memq frame-type '(x w32 mac ns)) (x-display-color-cells display)) ((eq frame-type 'pc) 16) @@ -1351,7 +1358,7 @@ `static-color', `pseudo-color', `true-color', or `direct-color'." (let ((frame-type (framep-on-display display))) (cond - ((memq frame-type '(x w32 mac)) + ((memq frame-type '(x w32 mac ns)) (x-display-visual-class display)) ((and (memq frame-type '(pc t)) (tty-display-color-p display)) diff -r ff312a846b25 -r d45acf0c8d23 lisp/gnus/gnus-util.el --- a/lisp/gnus/gnus-util.el Tue Jul 15 15:45:05 2008 +0000 +++ b/lisp/gnus/gnus-util.el Tue Jul 15 18:15:18 2008 +0000 @@ -1612,7 +1612,9 @@ (cond ((memq window-system '(x mac)) (x-focus-frame frame)) ((eq window-system 'w32) - (w32-focus-frame frame))) + (w32-focus-frame frame)) + ((eq window-system 'ns) + (ns-focus-frame frame))) (when focus-follows-mouse (set-mouse-position frame (1- (frame-width frame)) 0))))) diff -r ff312a846b25 -r d45acf0c8d23 lisp/info.el --- a/lisp/info.el Tue Jul 15 15:45:05 2008 +0000 +++ b/lisp/info.el Tue Jul 15 18:15:18 2008 +0000 @@ -3893,7 +3893,7 @@ ;; This is a serious problem for trying to handle multiple ;; frame types at once. We want this text to be invisible ;; on frames that can display the font above. - (when (memq (framep (selected-frame)) '(x pc w32 mac)) + (when (memq (framep (selected-frame)) '(x pc w32 mac ns)) (add-text-properties (1- (match-beginning 2)) (match-end 2) '(invisible t front-sticky nil rear-nonsticky t))))) diff -r ff312a846b25 -r d45acf0c8d23 lisp/international/mule-cmds.el --- a/lisp/international/mule-cmds.el Tue Jul 15 15:45:05 2008 +0000 +++ b/lisp/international/mule-cmds.el Tue Jul 15 18:15:18 2008 +0000 @@ -148,7 +148,7 @@ t) (define-key-after set-coding-system-map [set-terminal-coding-system] '(menu-item "For Terminal" set-terminal-coding-system - :enable (null (memq initial-window-system '(x w32 mac))) + :enable (null (memq initial-window-system '(x w32 mac ns))) :help "How to encode terminal output") t) (define-key-after set-coding-system-map [separator-3] diff -r ff312a846b25 -r d45acf0c8d23 lisp/loadup.el --- a/lisp/loadup.el Tue Jul 15 15:45:05 2008 +0000 +++ b/lisp/loadup.el Tue Jul 15 18:15:18 2008 +0000 @@ -212,6 +212,11 @@ (if (featurep 'mac-carbon) (progn (load "term/mac-win"))) +(if (featurep 'ns-windowing) + (progn + (load "emacs-lisp/easymenu") ;; for platform-related menu adjustments + (load "emacs-lisp/easy-mmode") + (load "term/ns-win"))) (if (fboundp 'atan) ; preload some constants and (progn ; floating pt. functions if we have float support. (load "emacs-lisp/float-sup"))) diff -r ff312a846b25 -r d45acf0c8d23 lisp/mouse.el --- a/lisp/mouse.el Tue Jul 15 15:45:05 2008 +0000 +++ b/lisp/mouse.el Tue Jul 15 18:15:18 2008 +0000 @@ -673,7 +673,7 @@ ;; If mark is highlighted, no need to bounce the cursor. ;; On X, we highlight while dragging, thus once again no need to bounce. (or transient-mark-mode - (memq (framep (selected-frame)) '(x pc w32 mac)) + (memq (framep (selected-frame)) '(x pc w32 mac ns)) (sit-for 1)) (push-mark) (set-mark (point)) diff -r ff312a846b25 -r d45acf0c8d23 lisp/mwheel.el --- a/lisp/mwheel.el Tue Jul 15 15:45:05 2008 +0000 +++ b/lisp/mwheel.el Tue Jul 15 18:15:18 2008 +0000 @@ -58,7 +58,7 @@ "22.1") (defcustom mouse-wheel-down-event ;; In the latest versions of XEmacs, we could just use mouse-%s as well. - (if (memq window-system '(w32 mac)) + (if (memq window-system '(w32 mac ns)) 'wheel-up (intern (format (if (featurep 'xemacs) "button%s" "mouse-%s") mouse-wheel-down-button))) @@ -73,7 +73,7 @@ "22.1") (defcustom mouse-wheel-up-event ;; In the latest versions of XEmacs, we could just use mouse-%s as well. - (if (memq window-system '(w32 mac)) + (if (memq window-system '(w32 mac ns)) 'wheel-down (intern (format (if (featurep 'xemacs) "button%s" "mouse-%s") mouse-wheel-up-button))) diff -r ff312a846b25 -r d45acf0c8d23 lisp/ns-carbon-compat.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/ns-carbon-compat.el Tue Jul 15 18:15:18 2008 +0000 @@ -0,0 +1,37 @@ +;;; ns-carbon-compat.el --- +;;; Carbon compatibility layer for Mac users of NS (Cocoa) GUI. +;;; Copyright (C) 2008 Free Software Foundation, Inc. + +;;; Author: Adrian Robert +;;; Keywords: Carbon, MacOSX + +;;; 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, 675 Mass Ave, Cambridge, MA 02139, USA. + +;;; Commentary: + +;; ns-carbon-compat.el: this file is loaded from termp/ns-win.el when +;; run on a Mac OS X system. It sets up a number of aliases and other +;; layers to enable human and machine users (Mac distributions of GNU Emacs) +;; to pretend they are using the Choi/Mitsuharu Carbon port. + +;;; Code: + +(defvaralias 'mac-allow-anti-aliasing 'ns-antialias-text) +(defvaralias 'mac-command-modifier 'ns-command-modifier) +(defvaralias 'mac-control-modifier 'ns-control-modifier) +(defvaralias 'mac-option-modifier 'ns-option-modifier) +(defvaralias 'mac-function-modifier 'ns-function-modifier) diff -r ff312a846b25 -r d45acf0c8d23 lisp/ns-grabenv.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/ns-grabenv.el Tue Jul 15 18:15:18 2008 +0000 @@ -0,0 +1,67 @@ +;;; ns-grabenv.el --- functions to set environment variables by running a subshell +;;; Copyright (C) 1993, 1994, 2005, 2006, 2008 Free Software Foundation, Inc. + +;;; Author: Carl Edman, Christian Limpach, Scott Bender, Christophe de Dinechin, +;;; Adrian Robert +;;; Keywords: terminals + +;;; 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 3, 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., 51 Franklin Street, Fifth Floor, +;;; Boston, MA 02110-1301, USA. + +;;; Idea based on NS 4.2 distribution, this version of code based on +;;; mac-read-environment-vars-from-shell () by David Reitter in Aquamacs dist.. + + +;; utility function +(defun ns-make-command-string (cmdlist) + (let ((str "") + (cmds cmdlist)) + (while cmds + (if (not (eq str "")) (setq str (format "%s ; " str))) + (setq str (format "%s%s" str (car cmds))) + (setq cmds (cdr cmds))) + str)) + + +;;;###autoload +(defun ns-grabenv (&optional shell-path &optional startup) + "Run a shell subprocess, and interpret its output as a series of environment\n\ +variables to insert into the emacs environment. The first optional argument\n\ +gives the path to the shell (defaults to the current setting of\n\ +shell-file-name). The remaining arguments are interpreted as a list of\n\ +commands for it to execute (defaults to \"printenv\")." + (interactive) + (with-temp-buffer + (let ((shell-file-name (if shell-path shell-path shell-file-name)) + (cmd (ns-make-command-string (if startup startup '("printenv"))))) + (shell-command cmd t) + (while (search-forward-regexp "^\\([A-Za-z_0-9]+\\)=\\(.*\\)$" nil t) + (setenv (match-string 1) + (if (equal (match-string 1) "PATH") + (concat (getenv "PATH") ":" (match-string 2)) + (match-string 2))))))) + +(provide 'ns-grabenv) + +;;; ns-grabenv.el ends here + +; (autoload (quote ns-grabenv) "ns-grabenv" "\ +; Run a shell subprocess, and interpret its output as a series of environment +; variables to insert into the emacs environment. The first optional argument +; gives the path to the shell (defaults to the current setting of +; shell-file-name). The remaining arguments are interpreted as a list of +; commands for it to execute (defaults to \"printenv\")." nil nil) diff -r ff312a846b25 -r d45acf0c8d23 lisp/simple.el --- a/lisp/simple.el Tue Jul 15 15:45:05 2008 +0000 +++ b/lisp/simple.el Tue Jul 15 18:15:18 2008 +0000 @@ -5984,7 +5984,7 @@ (set-terminal-parameter nil 'normal-erase-is-backspace (if enabled 1 0)) - (cond ((or (memq window-system '(x w32 mac pc)) + (cond ((or (memq window-system '(x w32 mac ns pc)) (memq system-type '(ms-dos windows-nt))) (let* ((bindings `(([C-delete] [C-backspace]) diff -r ff312a846b25 -r d45acf0c8d23 lisp/startup.el --- a/lisp/startup.el Tue Jul 15 15:45:05 2008 +0000 +++ b/lisp/startup.el Tue Jul 15 18:15:18 2008 +0000 @@ -182,6 +182,72 @@ and VALUE is the value which is given to that frame parameter \(most options use the argument for this, so VALUE is not present).") +(defconst command-line-ns-option-alist + '(("-NSAutoLaunch" 1 ns-ignore-1-arg) + ("-NXAutoLaunch" 1 ns-ignore-1-arg) + ("-macosx" 0 ns-ignore-0-arg) + ("-NSHost" 1 ns-ignore-1-arg) + ("-_NSMachLaunch" 1 ns-ignore-1-arg) + ("-MachLaunch" 1 ns-ignore-1-arg) + ("-NXOpen" 1 ns-ignore-1-arg) + ("-NSOpen" 1 ns-handle-nxopen) + ("-NXOpenTemp" 1 ns-ignore-1-arg) + ("-NSOpenTemp" 1 ns-handle-nxopentemp) + ("-GSFilePath" 1 ns-handle-nxopen) + ;;("-bw" . x-handle-numeric-switch) + ;;("-d" . x-handle-display) + ;;("-display" . x-handle-display) + ("-name" 1 ns-handle-name-switch) + ("-title" 1 ns-handle-switch title) + ("-T" 1 ns-handle-switch title) + ("-r" 0 ns-handle-switch reverse t) + ("-rv" 0 ns-handle-switch reverse t) + ("-reverse" 0 ns-handle-switch reverse t) + ("-fn" 1 ns-handle-switch font) + ("-font" 1 ns-handle-switch font) + ("-ib" 1 ns-handle-numeric-switch internal-border-width) + ;;("-g" . x-handle-geometry) + ;;("-geometry" . x-handle-geometry) + ("-fg" 1 ns-handle-switch foreground-color) + ("-foreground" 1 ns-handle-switch foreground-color) + ("-bg" 1 ns-handle-switch background-color) + ("-background" 1 ns-handle-switch background-color) +; ("-ms" 1 ns-handle-switch mouse-color) + ("-itype" 0 ns-handle-switch icon-type t) + ("-i" 0 ns-handle-switch icon-type t) + ("-iconic" 0 ns-handle-iconic icon-type t) + ;;("-xrm" . x-handle-xrm-switch) + ("-cr" 1 ns-handle-switch cursor-color) + ("-vb" 0 ns-handle-switch vertical-scroll-bars t) + ("-hb" 0 ns-handle-switch horizontal-scroll-bars t) + ("-bd" 1 ns-handle-switch) + ;; ("--border-width" 1 ns-handle-numeric-switch border-width) + ;; ("--display" 1 ns-handle-display) + ("--name" 1 ns-handle-name-switch) + ("--title" 1 ns-handle-switch title) + ("--reverse-video" 0 ns-handle-switch reverse t) + ("--font" 1 ns-handle-switch font) + ("--internal-border" 1 ns-handle-numeric-switch internal-border-width) + ;; ("--geometry" 1 ns-handle-geometry) + ("--foreground-color" 1 ns-handle-switch foreground-color) + ("--background-color" 1 ns-handle-switch background-color) + ("--mouse-color" 1 ns-handle-switch mouse-color) + ("--icon-type" 0 ns-handle-switch icon-type t) + ("--iconic" 0 ns-handle-iconic) + ;; ("--xrm" 1 ns-handle-xrm-switch) + ("--cursor-color" 1 ns-handle-switch cursor-color) + ("--vertical-scroll-bars" 0 ns-handle-switch vertical-scroll-bars t) + ("--border-color" 1 ns-handle-switch border-width)) + "Alist of NS options. +Each element has the form + (NAME NUMARGS HANDLER FRAME-PARAM VALUE) +where NAME is the option name string, NUMARGS is the number of arguments +that the option accepts, HANDLER is a function to call to handle the option. +FRAME-PARAM (optional) is the frame parameter this option specifies, +and VALUE is the value which is given to that frame parameter +\(most options use the argument for this, so VALUE is not present).") + + (defvar before-init-hook nil "Normal hook run after handling urgent options but before loading init files.") @@ -820,7 +886,7 @@ ;; only because all other settings of no-blinking-cursor are here. (unless (or noninteractive emacs-basic-display - (and (memq window-system '(x w32 mac)) + (and (memq window-system '(x w32 mac ns)) (not (member (x-get-resource "cursorBlink" "CursorBlink") '("off" "false"))))) (setq no-blinking-cursor t)) @@ -2021,6 +2087,13 @@ (if (string-match "^--" (car tem)) (push (list (car tem)) longopts))) + ;; Add the long NS options to longopts. + (setq tem command-line-ns-option-alist) + (while tem + (if (string-match "^--" (car (car tem))) + (setq longopts (cons (list (car (car tem))) longopts))) + (setq tem (cdr tem))) + ;; Loop, processing options. (while command-line-args-left (let* ((argi (car command-line-args-left)) @@ -2131,6 +2204,11 @@ (setq command-line-args-left (nthcdr (nth 1 tem) command-line-args-left))) + ((setq tem (assoc argi command-line-ns-option-alist)) + ;; Ignore NS-windows options and their args if not using NS. + (setq command-line-args-left + (nthcdr (nth 1 tem) command-line-args-left))) + ((member argi '("-find-file" "-file" "-visit")) (setq inhibit-startup-screen t) ;; An explicit option to specify visiting a file. diff -r ff312a846b25 -r d45acf0c8d23 lisp/term/ns-win.el --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/term/ns-win.el Tue Jul 15 18:15:18 2008 +0000 @@ -0,0 +1,1608 @@ +;;; ns-win.el --- lisp side of interface with +;;; NeXT/Open/GNUstep/MacOS X window system +;;; Copyright (C) 1993, 1994, 2005, 2006, 2008 Free Software Foundation, Inc. + +;;; Author: Carl Edman, Christian Limpach, Scott Bender, Christophe de Dinechin, +;;; Adrian Robert +;;; Keywords: terminals + +;;; 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 3, 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., 51 Franklin Street, Fifth Floor, +;;; Boston, MA 02110-1301, USA. + +;;; Commentary: + +;; ns-win.el: this file is loaded from ../lisp/startup.el when it recognizes +;; that NS windows are to be used. Command line switches are parsed and those +;; pertaining to NS are processed and removed from the command line. The +;; NS display is opened and hooks are set for popping up the initial window. + +;; startup.el will then examine startup files, and eventually call the hooks +;; which create the first window (s). + +;; A number of other NS convenience functions are defined in this file, +;; which works in close coordination with src/nsfns.m. + +;;; Code: + + +(if (not (featurep 'ns-windowing)) + (error "%s: Loading ns-win.el but not compiled for *Step/OS X" + (invocation-name))) + +;; Documentation-purposes only: actually loaded in loadup.el +(require 'frame) +(require 'mouse) +(require 'faces) +(require 'easymenu) +(require 'menu-bar) +(require 'fontset) + +; Not needed? +;(require 'ispell) + +(defun ns-submit-bug-report () + "Submit via mail a bug report on Emacs 23.0.0 for GNUstep / OS X." + (interactive) + (let ((frame-parameters (frame-parameters)) + (server-vendor (ns-server-vendor)) + (server-version (ns-server-version))) + (reporter-submit-bug-report + "Adrian Robert " + ;;"Christophe de Dinechin " + ;;"Scott Bender " + ;;"Christian Limpach " + ;;"Carl Edman " + (concat "Emacs for GNUstep / OS X " ns-version-string) + '(ns-expand-space ns-cursor-blink-rate ns-alternate-modifier + data-directory frame-parameters window-system window-system-version + server-vendor server-version system-configuration-options)))) + + +;;;; Command line argument handling. + +(defvar ns-invocation-args nil) +(defvar ns-command-line-resources nil) + +;; Handler for switches of the form "-switch value" or "-switch". +(defun ns-handle-switch (switch) + (let ((aelt (assoc switch command-line-ns-option-alist))) + (if aelt + (let ((param (nth 3 aelt)) + (value (nth 4 aelt))) + (if value + (setq default-frame-alist + (cons (cons param value) + default-frame-alist)) + (setq default-frame-alist + (cons (cons param + (car ns-invocation-args)) + default-frame-alist) + ns-invocation-args (cdr ns-invocation-args))))))) + +;; Handler for switches of the form "-switch n" +(defun ns-handle-numeric-switch (switch) + (let ((aelt (assoc switch command-line-ns-option-alist))) + (if aelt + (let ((param (nth 3 aelt))) + (setq default-frame-alist + (cons (cons param + (string-to-number (car ns-invocation-args))) + default-frame-alist) + ns-invocation-args + (cdr ns-invocation-args)))))) + +;; Make -iconic apply only to the initial frame! +(defun ns-handle-iconic (switch) + (setq initial-frame-alist + (cons '(visibility . icon) initial-frame-alist))) + +;; Handle the -name option, set the name of +;; the initial frame. +(defun ns-handle-name-switch (switch) + (or (consp ns-invocation-args) + (error "%s: missing argument to `%s' option" (invocation-name) switch)) + (setq initial-frame-alist (cons (cons 'name (car ns-invocation-args)) + initial-frame-alist) + ns-invocation-args (cdr ns-invocation-args))) + +(defun ns-handle-nxopen (switch) + (setq unread-command-events (append unread-command-events '(ns-open-file)) + ns-input-file (append ns-input-file (list (car ns-invocation-args))) + ns-invocation-args (cdr ns-invocation-args))) + +(defun ns-handle-nxopentemp (switch) + (setq unread-command-events (append unread-command-events '(ns-open-temp-file)) + ns-input-file (append ns-input-file (list (car ns-invocation-args))) + ns-invocation-args (cdr ns-invocation-args))) + +(defun ns-ignore-0-arg (switch) + ) +(defun ns-ignore-1-arg (switch) + (setq ns-invocation-args (cdr ns-invocation-args))) +(defun ns-ignore-2-arg (switch) + (setq ns-invocation-args (cddr ns-invocation-args))) + +(defun ns-handle-args (args) + "Here the NS-related command line options in ARGS are processed, +before the user's startup file is loaded. They are copied to +`ns-invocation-args', from which the NS related things are extracted, first +the switch (e.g., \"-fg\") in the following code, and possible values +\(e.g., \"black\") in the option handler code (e.g., ns-handle-switch). +This function returns ARGS minus the arguments that have been processed." + ;; We use ARGS to accumulate the args that we don't handle here, to return. + (setq ns-invocation-args args + args nil) + (while ns-invocation-args + (let* ((this-switch (car ns-invocation-args)) + (orig-this-switch this-switch) + completion argval aelt handler) + (setq ns-invocation-args (cdr ns-invocation-args)) + ;; Check for long options with attached arguments + ;; and separate out the attached option argument into argval. + (if (string-match "^--[^=]*=" this-switch) + (setq argval (substring this-switch (match-end 0)) + this-switch (substring this-switch 0 (1- (match-end 0))))) + ;; Complete names of long options. + (if (string-match "^--" this-switch) + (progn + (setq completion (try-completion this-switch + command-line-ns-option-alist)) + (if (eq completion t) + ;; Exact match for long option. + nil + (if (stringp completion) + (let ((elt (assoc completion command-line-ns-option-alist))) + ;; Check for abbreviated long option. + (or elt + (error "Option `%s' is ambiguous" this-switch)) + (setq this-switch completion)))))) + (setq aelt (assoc this-switch command-line-ns-option-alist)) + (if aelt (setq handler (nth 2 aelt))) + (if handler + (if argval + (let ((ns-invocation-args + (cons argval ns-invocation-args))) + (funcall handler this-switch)) + (funcall handler this-switch)) + (setq args (cons orig-this-switch args))))) + (nreverse args)) + +(defun x-parse-geometry (geom) + "Parse an NS-style geometry string STRING. +Returns an alist of the form ((top . TOP), (left . LEFT) ... ). +The properties returned may include `top', `left', `height', and `width'." + (if (string-match "\\([0-9]+\\)\\( \\([0-9]+\\)\\( \\([0-9]+\\)\\( \\([0-9]+\\) ?\\)?\\)?\\)?" + geom) + (apply 'append + (list + (list (cons 'top (string-to-number (match-string 1 geom)))) + (if (match-string 3 geom) + (list (cons 'left (string-to-number (match-string 3 geom))))) + (if (match-string 5 geom) + (list (cons 'height (string-to-number (match-string 5 geom))))) + (if (match-string 7 geom) + (list (cons 'width (string-to-number (match-string 7 geom))))))) + '())) + + + +;;;; Keyboard mapping. + +;; These tell read-char how to convert +;; these special chars to ASCII. +(put 'backspace 'ascii-character 127) +(put 'delete 'ascii-character 127) +(put 'tab 'ascii-character ?\t) +(put 'S-tab 'ascii-character (logior 16 ?\t)) +(put 'linefeed 'ascii-character ?\n) +(put 'clear 'ascii-character 12) +(put 'return 'ascii-character 13) +(put 'escape 'ascii-character ?\e) + +;; Map certain keypad keys into ASCII characters +;; that people usually expect. +(define-key function-key-map [backspace] [127]) +(define-key function-key-map [delete] [127]) +(define-key function-key-map [tab] [?\t]) +(define-key function-key-map [S-tab] [25]) +(define-key function-key-map [linefeed] [?\n]) +(define-key function-key-map [clear] [11]) +(define-key function-key-map [return] [13]) +(define-key function-key-map [escape] [?\e]) +(define-key function-key-map [M-backspace] [?\M-\d]) +(define-key function-key-map [M-delete] [?\M-\d]) +(define-key function-key-map [M-tab] [?\M-\t]) +(define-key function-key-map [M-linefeed] [?\M-\n]) +(define-key function-key-map [M-clear] [?\M-\013]) +(define-key function-key-map [M-return] [?\M-\015]) +(define-key function-key-map [M-escape] [?\M-\e]) + + +;; Here are some NeXTSTEP like bindings for command key sequences. +(define-key global-map [?\s-,] 'ns-popup-prefs-panel) +(define-key global-map [?\s-'] 'next-multiframe-window) +(define-key global-map [?\s-`] 'other-frame) +(define-key global-map [?\s--] 'center-line) +(define-key global-map [?\s-:] 'ispell) +(define-key global-map [?\s-\;] 'ispell-next) +(define-key global-map [?\s-?] 'info) +(define-key global-map [?\s-^] 'kill-some-buffers) +(define-key global-map [?\s-&] 'kill-this-buffer) +(define-key global-map [?\s-C] 'ns-popup-color-panel) +(define-key global-map [?\s-D] 'dired) +(define-key global-map [?\s-E] 'edit-abbrevs) +(define-key global-map [?\s-L] 'shell-command) +(define-key global-map [?\s-M] 'manual-entry) +(define-key global-map [?\s-S] 'ns-write-file-using-panel) +(define-key global-map [?\s-a] 'mark-whole-buffer) +(define-key global-map [?\s-c] 'ns-copy-including-secondary) +(define-key global-map [?\s-d] 'isearch-repeat-backward) +(define-key global-map [?\s-e] 'isearch-yank-kill) +(define-key global-map [?\s-f] 'isearch-forward) +(define-key global-map [?\s-g] 'isearch-repeat-forward) +(define-key global-map [?\s-h] 'ns-do-hide-emacs) +(define-key global-map [?\s-H] 'ns-do-hide-others) +(define-key global-map [?\s-j] 'exchange-point-and-mark) +(define-key global-map [?\s-k] 'kill-this-buffer) +(define-key global-map [?\s-l] 'goto-line) +(define-key global-map [?\s-m] 'iconify-frame) +(define-key global-map [?\s-n] 'make-frame) +(define-key global-map [?\s-o] 'ns-open-file-using-panel) +(define-key global-map [?\s-p] 'ns-print-buffer) +(define-key global-map [?\s-q] 'save-buffers-kill-emacs) +(define-key global-map [?\s-s] 'save-buffer) +(define-key global-map [?\s-t] 'ns-popup-font-panel) +(define-key global-map [?\s-u] 'revert-buffer) +(define-key global-map [?\s-v] 'yank) +(define-key global-map [?\s-w] 'delete-frame) +(define-key global-map [?\s-x] 'kill-region) +(define-key global-map [?\s-y] 'ns-paste-secondary) +(define-key global-map [?\s-z] 'undo) +(define-key global-map [?\s-|] 'shell-command-on-region) +(define-key global-map [s-kp-bar] 'shell-command-on-region) +; (as in Terminal.app) +(define-key global-map [s-right] 'ns-next-frame) +(define-key global-map [s-left] 'ns-prev-frame) + +(define-key global-map [home] 'beginning-of-buffer) +(define-key global-map [end] 'end-of-buffer) +(define-key global-map [kp-home] 'beginning-of-buffer) +(define-key global-map [kp-end] 'end-of-buffer) +(define-key global-map [kp-prior] 'scroll-down) +(define-key global-map [kp-next] 'scroll-up) + + +;; Special NeXTSTEP generated events are converted to function keys. Here +;; are the bindings for them. +(define-key global-map [ns-power-off] + '(lambda () (interactive) (save-buffers-kill-emacs t))) +(define-key global-map [ns-open-file] 'ns-find-file) +(define-key global-map [ns-open-temp-file] [ns-open-file]) +(define-key global-map [ns-drag-file] 'ns-insert-file) +(define-key global-map [ns-drag-color] 'ns-set-foreground-at-mouse) +(define-key global-map [S-ns-drag-color] 'ns-set-background-at-mouse) +(define-key global-map [ns-drag-text] 'ns-insert-text) +(define-key global-map [ns-change-font] 'ns-respond-to-change-font) +(define-key global-map [ns-open-file-line] 'ns-open-file-select-line) +(define-key global-map [ns-insert-working-text] 'ns-insert-working-text) +(define-key global-map [ns-delete-working-text] 'ns-delete-working-text) +(define-key global-map [ns-spi-service-call] 'ns-spi-service-call) + + + +;;;; Lisp niceties, most used only under ns-extended-platform-support-mode, +;;;; defined below + +(autoload 'ns-grabenv "ns-grabenv" "Get environment from your shell." t nil) +(load "ns-carbon-compat") + +;; alt-up/down scrolling a la Stuart.app +;; only activated if ns-extended-platform-support is on +(defun up-one () (interactive) (scroll-up 1)) +(defun down-one () (interactive) (scroll-down 1)) +(defun left-one () (interactive) (scroll-left 1)) +(defun right-one () (interactive) (scroll-right 1)) + +;; Toggle some additional NS-like features that may interfere with users' +;; expectations coming from emacs on other platforms. +(define-minor-mode ns-extended-platform-support-mode + "Toggle NS extended platform support features. + When this mode is active (no modeline indicator): + - File menus is altered slightly in keeping with conventions. + - Meta-up, meta-down are bound to scroll window up and down one line. + - Meta-p, Meta-n navigate forwards and backwards in the mark ring." + :init-value nil + :global t + :group 'ns + (if ns-extended-platform-support-mode + (progn + (global-set-key [M-up] 'down-one) + (global-set-key [M-down] 'up-one) + ; These conflict w/word-left, word-right + ;;(global-set-key [M-left] 'left-one) + ;;(global-set-key [M-right] 'right-one) + + (setq scroll-preserve-screen-position t) + (transient-mark-mode 1) + + ;; Change file menu to simplify and add a couple of NS-specific items + (easy-menu-remove-item global-map '("menu-bar") 'file) + (easy-menu-add-item global-map '(menu-bar) + (cons "File" menu-bar-ns-file-menu) 'edit)) + (progn + ; undo everything above + (global-unset-key [M-up]) + (global-unset-key [M-down]) + (setq scroll-preserve-screen-position nil) + (transient-mark-mode 0) + (easy-menu-remove-item global-map '("menu-bar") 'file) + (easy-menu-add-item global-map '(menu-bar) + (cons "File" menu-bar-file-menu) 'edit)))) + + +(defun x-setup-function-keys (frame) + "Set up function Keys for NS for given FRAME." + (unless (terminal-parameter frame 'x-setup-function-keys) + (with-selected-frame frame + (setq interprogram-cut-function 'ns-select-text + interprogram-paste-function 'ns-pasteboard-value) +;;; (let ((map (copy-keymap x-alternatives-map))) +;;; (set-keymap-parent map (keymap-parent local-function-key-map)) +;;; (set-keymap-parent local-function-key-map map)) + (setq system-key-alist + (list + (cons (logior (lsh 0 16) 1) 'ns-power-off) + (cons (logior (lsh 0 16) 2) 'ns-open-file) + (cons (logior (lsh 0 16) 3) 'ns-open-temp-file) + (cons (logior (lsh 0 16) 4) 'ns-drag-file) + (cons (logior (lsh 0 16) 5) 'ns-drag-color) + (cons (logior (lsh 0 16) 6) 'ns-drag-text) + (cons (logior (lsh 0 16) 7) 'ns-change-font) + (cons (logior (lsh 0 16) 8) 'ns-open-file-line) + (cons (logior (lsh 0 16) 9) 'ns-insert-working-text) + (cons (logior (lsh 0 16) 10) 'ns-delete-working-text) + (cons (logior (lsh 0 16) 11) 'ns-spi-service-call) + (cons (logior (lsh 1 16) 32) 'f1) + (cons (logior (lsh 1 16) 33) 'f2) + (cons (logior (lsh 1 16) 34) 'f3) + (cons (logior (lsh 1 16) 35) 'f4) + (cons (logior (lsh 1 16) 36) 'f5) + (cons (logior (lsh 1 16) 37) 'f6) + (cons (logior (lsh 1 16) 38) 'f7) + (cons (logior (lsh 1 16) 39) 'f8) + (cons (logior (lsh 1 16) 40) 'f9) + (cons (logior (lsh 1 16) 41) 'f10) + (cons (logior (lsh 1 16) 42) 'f11) + (cons (logior (lsh 1 16) 43) 'f12) + (cons (logior (lsh 1 16) 44) 'kp-insert) + (cons (logior (lsh 1 16) 45) 'kp-delete) + (cons (logior (lsh 1 16) 46) 'kp-home) + (cons (logior (lsh 1 16) 47) 'kp-end) + (cons (logior (lsh 1 16) 48) 'kp-prior) + (cons (logior (lsh 1 16) 49) 'kp-next) + (cons (logior (lsh 1 16) 50) 'print-screen) + (cons (logior (lsh 1 16) 51) 'scroll-lock) + (cons (logior (lsh 1 16) 52) 'pause) + (cons (logior (lsh 1 16) 53) 'system) + (cons (logior (lsh 1 16) 54) 'break) + (cons (logior (lsh 1 16) 56) 'please-tell-carl-what-this-key-is-called-56) + (cons (logior (lsh 1 16) 61) 'please-tell-carl-what-this-key-is-called-61) + (cons (logior (lsh 1 16) 62) 'please-tell-carl-what-this-key-is-called-62) + (cons (logior (lsh 1 16) 63) 'please-tell-carl-what-this-key-is-called-63) + (cons (logior (lsh 1 16) 64) 'please-tell-carl-what-this-key-is-called-64) + (cons (logior (lsh 1 16) 69) 'please-tell-carl-what-this-key-is-called-69) + (cons (logior (lsh 1 16) 70) 'please-tell-carl-what-this-key-is-called-70) + (cons (logior (lsh 1 16) 71) 'please-tell-carl-what-this-key-is-called-71) + (cons (logior (lsh 1 16) 72) 'please-tell-carl-what-this-key-is-called-72) + (cons (logior (lsh 1 16) 73) 'please-tell-carl-what-this-key-is-called-73) + (cons (logior (lsh 2 16) 3) 'kp-enter) + (cons (logior (lsh 2 16) 9) 'kp-tab) + (cons (logior (lsh 2 16) 28) 'kp-quit) + (cons (logior (lsh 2 16) 35) 'kp-hash) + (cons (logior (lsh 2 16) 42) 'kp-multiply) + (cons (logior (lsh 2 16) 43) 'kp-add) + (cons (logior (lsh 2 16) 44) 'kp-separator) + (cons (logior (lsh 2 16) 45) 'kp-subtract) + (cons (logior (lsh 2 16) 46) 'kp-decimal) + (cons (logior (lsh 2 16) 47) 'kp-divide) + (cons (logior (lsh 2 16) 48) 'kp-0) + (cons (logior (lsh 2 16) 49) 'kp-1) + (cons (logior (lsh 2 16) 50) 'kp-2) + (cons (logior (lsh 2 16) 51) 'kp-3) + (cons (logior (lsh 2 16) 52) 'kp-4) + (cons (logior (lsh 2 16) 53) 'kp-5) + (cons (logior (lsh 2 16) 54) 'kp-6) + (cons (logior (lsh 2 16) 55) 'kp-7) + (cons (logior (lsh 2 16) 56) 'kp-8) + (cons (logior (lsh 2 16) 57) 'kp-9) + (cons (logior (lsh 2 16) 60) 'kp-less) + (cons (logior (lsh 2 16) 61) 'kp-equal) + (cons (logior (lsh 2 16) 62) 'kp-more) + (cons (logior (lsh 2 16) 64) 'kp-at) + (cons (logior (lsh 2 16) 92) 'kp-backslash) + (cons (logior (lsh 2 16) 96) 'kp-backtick) + (cons (logior (lsh 2 16) 124) 'kp-bar) + (cons (logior (lsh 2 16) 126) 'kp-tilde) + (cons (logior (lsh 2 16) 157) 'kp-mu) + (cons (logior (lsh 2 16) 165) 'kp-yen) + (cons (logior (lsh 2 16) 167) 'kp-paragraph) + (cons (logior (lsh 2 16) 172) 'left) + (cons (logior (lsh 2 16) 173) 'up) + (cons (logior (lsh 2 16) 174) 'right) + (cons (logior (lsh 2 16) 175) 'down) + (cons (logior (lsh 2 16) 176) 'kp-ring) + (cons (logior (lsh 2 16) 201) 'kp-square) + (cons (logior (lsh 2 16) 204) 'kp-cube) + (cons (logior (lsh 3 16) 8) 'backspace) + (cons (logior (lsh 3 16) 9) 'tab) + (cons (logior (lsh 3 16) 10) 'linefeed) + (cons (logior (lsh 3 16) 11) 'clear) + (cons (logior (lsh 3 16) 13) 'return) + (cons (logior (lsh 3 16) 18) 'pause) + (cons (logior (lsh 3 16) 25) 'S-tab) + (cons (logior (lsh 3 16) 27) 'escape) + (cons (logior (lsh 3 16) 127) 'delete) + )) + (set-terminal-parameter frame 'x-setup-function-keys t)))) + + + +;;;; Miscellaneous mouse bindings. + +;;; Allow shift-clicks to work just like under NS +(defun mouse-extend-region (event) + "Move point or mark so as to extend region. +This should be bound to a mouse click event type." + (interactive "e") + (mouse-minibuffer-check event) + (let ((posn (event-end event))) + (if (not (windowp (posn-window posn))) + (error "Cursor not in text area of window")) + (select-window (posn-window posn)) + (cond + ((not (numberp (posn-point posn)))) + ((or (not mark-active) (> (abs (- (posn-point posn) (point))) + (abs (- (posn-point posn) (mark))))) + (let ((point-save (point))) + (unwind-protect + (progn + (goto-char (posn-point posn)) + (push-mark nil t t) + (or transient-mark-mode + (sit-for 1))) + (goto-char point-save)))) + (t + (goto-char (posn-point posn)))))) + +(define-key global-map [S-mouse-1] 'mouse-extend-region) +(global-unset-key [S-down-mouse-1]) + + + +; must come after keybindings + +(fmakunbound 'clipboard-yank) +(fmakunbound 'clipboard-kill-ring-save) +(fmakunbound 'clipboard-kill-region) +(fmakunbound 'menu-bar-enable-clipboard) + +;; Add a couple of menus and rearrange some others; easiest just to redo toplvl +;; Note keymap defns must be given last-to-first +(define-key global-map [menu-bar] (make-sparse-keymap "menu-bar")) + +(cond ((eq system-type 'darwin) + (setq menu-bar-final-items '(buffer windows services help-menu))) + ;; otherwise, gnustep + (t + (setq menu-bar-final-items '(buffer windows services hide-app quit)) ) +) + +;; add standard top-level items to GNUstep menu +(cond ((not (eq system-type 'darwin)) + (define-key global-map [menu-bar quit] '("Quit" . save-buffers-kill-emacs)) + (define-key global-map [menu-bar hide-app] '("Hide" . ns-do-hide-emacs)) +)) + +(define-key global-map [menu-bar services] + (cons "Services" (make-sparse-keymap "Services"))) +(define-key global-map [menu-bar windows] (make-sparse-keymap "Windows")) +(define-key global-map [menu-bar buffer] + (cons "Buffers" global-buffers-menu-map)) +;; (cons "Buffers" (make-sparse-keymap "Buffers"))) +(define-key global-map [menu-bar tools] (cons "Tools" menu-bar-tools-menu)) +(define-key global-map [menu-bar options] (cons "Options" menu-bar-options-menu)) +(define-key global-map [menu-bar edit] (cons "Edit" menu-bar-edit-menu)) +(define-key global-map [menu-bar file] (cons "File" menu-bar-file-menu)) + +;; If running under GNUstep, rename "Help" to "Info" +(cond ((eq system-type 'darwin) + (define-key global-map [menu-bar help-menu] + (cons "Help" menu-bar-help-menu))) + (t + (let ((contents (reverse (cdr menu-bar-help-menu)))) + (setq menu-bar-help-menu + (append (list 'keymap) (cdr contents) (list "Info")))) + (define-key global-map [menu-bar help-menu] + (cons "Info" menu-bar-help-menu)))) + + +;;;; Add to help / info menu +(defun info-ns-emacs () + "Jump to ns-emacs info item." + (interactive) + (info "ns-emacs")) + +(define-key menu-bar-help-menu [ns-bug-report] + '("Report Emacs.app bug..." . ns-submit-bug-report)) +(define-key menu-bar-help-menu [info-ns] + '("Emacs.app Manual" . info-ns-emacs)) +(if (not (eq system-type 'darwin)) + ;; in OS X it's in the app menu already + (define-key menu-bar-help-menu [info-panel] + '("About Emacs..." . ns-do-emacs-info-panel))) + + +;;;; File menu, replaces standard under ns-extended-platform-support +(defvar menu-bar-ns-file-menu (make-sparse-keymap "File")) +(define-key menu-bar-ns-file-menu [one-window] + '("Remove Splits" . delete-other-windows)) +(define-key menu-bar-ns-file-menu [split-window] + '("Split Window" . split-window-vertically)) + +(define-key menu-bar-ns-file-menu [separator-print] '("--")) + +(defvar ns-ps-print-menu-map (make-sparse-keymap "Postscript Print")) +(define-key ns-ps-print-menu-map [ps-print-region] + '("Region (B+W)" . ps-print-region)) +(define-key ns-ps-print-menu-map [ps-print-buffer] + '("Buffer (B+W)" . ps-print-buffer)) +(define-key ns-ps-print-menu-map [ps-print-region-faces] + '("Region" . ps-print-region-with-faces)) +(define-key ns-ps-print-menu-map [ps-print-buffer-faces] + '("Buffer" . ns-ps-print-buffer-with-faces)) +(define-key menu-bar-ns-file-menu [postscript-print] + (cons "Postscript Print" ns-ps-print-menu-map)) + +(define-key menu-bar-ns-file-menu [print-region] + '("Print Region" . print-region)) +(define-key menu-bar-ns-file-menu [print-buffer] + '("Print Buffer" . ns-print-buffer)) + +(define-key menu-bar-ns-file-menu [separator-save] '("--")) + +(define-key menu-bar-ns-file-menu [recover-session] + '("Recover Crashed Session" . recover-session)) +(define-key menu-bar-ns-file-menu [revert-buffer] + '("Revert Buffer" . revert-buffer)) +(define-key menu-bar-ns-file-menu [write-file] + '("Save Buffer As..." . ns-write-file-using-panel)) +(define-key menu-bar-ns-file-menu [save-buffer] '("Save Buffer" . save-buffer)) + +(define-key menu-bar-ns-file-menu [kill-buffer] + '("Kill Current Buffer" . kill-this-buffer)) +(define-key menu-bar-ns-file-menu [delete-this-frame] + '("Close Frame" . delete-frame)) + +(define-key menu-bar-ns-file-menu [separator-open] '("--")) + +(define-key menu-bar-ns-file-menu [insert-file] + '("Insert File..." . insert-file)) +(define-key menu-bar-ns-file-menu [dired] + '("Open Directory..." . ns-open-file-using-panel)) +(define-key menu-bar-ns-file-menu [open-file] + '("Open File..." . ns-open-file-using-panel)) +(define-key menu-bar-ns-file-menu [make-frame] + '("New Frame" . make-frame)) + + +;;;; Edit menu: Modify slightly + +; Substitute a Copy function that works better under X (for GNUstep) +(easy-menu-remove-item global-map '("menu-bar" "edit") 'copy) +(define-key-after menu-bar-edit-menu [copy] + '(menu-item "Copy" ns-copy-including-secondary + :enable mark-active + :help "Copy text in region between mark and current position") + 'cut) + +; Change to same precondition as select-and-paste, as we don't have +; 'x-selection-exists-p +(easy-menu-remove-item global-map '("menu-bar" "edit") 'paste) +(define-key-after menu-bar-edit-menu [paste] + '(menu-item "Paste" yank + :enable (and (cdr yank-menu) (not buffer-read-only)) + :help "Paste (yank) text most recently cut/copied") + 'copy) + +; Change text to be more consistent with surrounding menu items 'paste', etc. +(easy-menu-remove-item global-map '("menu-bar" "edit") 'paste-from-menu) +(define-key-after menu-bar-edit-menu [select-paste] + '(menu-item "Select and Paste" yank-menu + :enable (and (cdr yank-menu) (not buffer-read-only)) + :help "Choose a string from the kill ring and paste it") + 'paste) + +; Separate undo item from cut/paste section, add spell for platform consistency +(define-key-after menu-bar-edit-menu [separator-undo] '("--") 'undo) +(define-key-after menu-bar-edit-menu [spell] '("Spell" . ispell-menu-map) 'fill) + + +;;;; Windows menu +(defun menu-bar-select-frame () + (interactive) + (make-frame-visible last-command-event) + (raise-frame last-command-event) + (select-frame last-command-event)) + +(defun menu-bar-update-frames () + ;; If user discards the Windows item, play along. + (and (lookup-key (current-global-map) [menu-bar windows]) + (let ((frames (frame-list)) + (frames-menu (make-sparse-keymap "Select Frame"))) + (setcdr frames-menu + (nconc + (mapcar '(lambda (frame) + (nconc (list frame + (cdr (assq 'name (frame-parameters frame))) + (cons nil nil)) + 'menu-bar-select-frame)) + frames) + (cdr frames-menu))) + (define-key frames-menu [separator-frames] '("--")) + (define-key frames-menu [popup-color-panel] + '("Colors..." . ns-popup-color-panel)) + (define-key frames-menu [popup-font-panel] + '("Font Panel..." . ns-popup-font-panel)) + (define-key frames-menu [separator-arrange] '("--")) + (define-key frames-menu [arrange-all-frames] + '("Arrange All Frames" . ns-arrange-all-frames)) + (define-key frames-menu [arrange-visible-frames] + '("Arrange Visible Frames" . ns-arrange-visible-frames)) + ;; Don't use delete-frame as event name + ;; because that is a special event. + (define-key (current-global-map) [menu-bar windows] + (cons "Windows" frames-menu))))) + +(defun force-menu-bar-update-buffers () + ;; This is a hack to get around fact that we already checked + ;; frame-or-buffer-changed-p and reset it, so menu-bar-update-buffers + ;; does not pick up any change. + (menu-bar-update-buffers t)) + +(add-hook 'menu-bar-update-fab-hook 'menu-bar-update-frames) +(add-hook 'menu-bar-update-fab-hook 'force-menu-bar-update-buffers) + +(defun menu-bar-update-frames-and-buffers () + (if (frame-or-buffer-changed-p) + (run-hooks 'menu-bar-update-fab-hook))) + +(setq menu-bar-update-hook + (delq 'menu-bar-update-buffers menu-bar-update-hook)) +(add-hook 'menu-bar-update-hook 'menu-bar-update-frames-and-buffers) + +(menu-bar-update-frames-and-buffers) + + +;; ns-arrange functions contributed +;; by Eberhard Mandler +(defun ns-arrange-all-frames () + "Arranges all frames according to topline" + (interactive) + (ns-arrange-frames t)) + +(defun ns-arrange-visible-frames () + "Arranges all visible frames according to topline" + (interactive) + (ns-arrange-frames nil)) + +(defun ns-arrange-frames ( vis) + (let ((frame (next-frame)) + (end-frame (selected-frame)) + (inc-x 20) ;relative position of frames + (inc-y 22) + (x-pos 100) ;start position + (y-pos 40) + (done nil)) + (while (not done) ;cycle through all frames + (if (not (or vis (eq (frame-visible-p frame) t))) + (setq x-pos x-pos); do nothing; true case + (set-frame-position frame x-pos y-pos) + (setq x-pos (+ x-pos inc-x)) + (setq y-pos (+ y-pos inc-y)) + (raise-frame frame)) + (select-frame frame) + (setq frame (next-frame)) + (setq done (equal frame end-frame))) + (set-frame-position end-frame x-pos y-pos) + (raise-frame frame) + (select-frame frame))) + + +;;;; Services +(defun ns-define-service (path) + (let ((mapping [menu-bar services]) + (service (mapconcat 'identity path "/")) + (name (intern + (mapconcat '(lambda (s) (if (= s 32) "-" (char-to-string s))) + (mapconcat 'identity (cons "ns-service" path) "-") + "")))) + ;; This defines the function + (eval (append (list 'defun name) + `((arg) + (interactive "p") + (let* ((in-string (if (stringp arg) arg (if mark-active + (buffer-substring (region-beginning) (region-end))))) + (out-string (ns-perform-service (,@service) in-string))) + (cond + ((stringp arg) out-string) + ((and out-string (or (not in-string) + (not (string= in-string out-string)))) + (if mark-active (delete-region (region-beginning) (region-end))) + (insert out-string) + (setq deactivate-mark nil))))))) + (cond + ((lookup-key global-map mapping) + (while (cdr path) + (setq mapping (vconcat mapping (list (intern (car path))))) + (if (not (keymapp (lookup-key global-map mapping))) + (define-key global-map mapping + (cons (car path) (make-sparse-keymap (car path))))) + (setq path (cdr path))) + (setq mapping (vconcat mapping (list (intern (car path))))) + (define-key global-map mapping (cons (car path) name)))) + name)) + +(precompute-menubar-bindings) + +(defun ns-spi-service-call () + "Respond to a service request to Emacs.app." + (interactive) + (cond ((string-equal ns-input-spi-name "open-selection") + (switch-to-buffer (generate-new-buffer "*untitled*")) + (insert ns-input-spi-arg)) + ((string-equal ns-input-spi-name "open-file") + (dnd-open-file ns-input-spi-arg nil)) + ((string-equal ns-input-spi-name "mail-selection") + (compose-mail) + (rfc822-goto-eoh) + (forward-line 1) + (insert ns-input-spi-arg)) + ((string-equal ns-input-spi-name "mail-to") + (compose-mail ns-input-spi-arg)) + (t (error (concat "Service " ns-input-spi-name " not recognized"))))) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + + +;;;; Composed key sequence handling for NS system input methods. +;;;; (On NS systems, input methods are provided for CJK characters, +;;;; etc. which require multiple keystrokes, and during entry a +;;;; partial ("working") result is typically shown in the editing window.) + +(defface ns-working-text-face + '((t :underline t)) + "Face used to highlight working text during compose sequence insert." + :group 'ns) + +(defvar ns-working-overlay nil + "Overlay used to highlight working text during compose sequence insert.") +(make-variable-buffer-local 'ns-working-overlay) +(defvar ns-working-overlay-len 0 + "Length of working text during compose sequence insert.") +(make-variable-buffer-local 'ns-working-overlay-len) + +; Based on mac-win.el 2007/08/26 unicode-2. This will fail if called +; from an "interactive" function. +(defun ns-in-echo-area () + "Whether, for purposes of inserting working composition text, the minibuffer +is currently being used." + (or isearch-mode + (and cursor-in-echo-area (current-message)) + ;; Overlay strings are not shown in some cases. + (get-char-property (point) 'invisible) + (and (not (bobp)) + (or (and (get-char-property (point) 'display) + (eq (get-char-property (1- (point)) 'display) + (get-char-property (point) 'display))) + (and (get-char-property (point) 'composition) + (eq (get-char-property (1- (point)) 'composition) + (get-char-property (point) 'composition))))))) + +; currently not used, doesn't work because the 'interactive' here stays +; for subinvocations +(defun ns-insert-working-text () + (interactive) + (if (ns-in-echo-area) (ns-echo-working-text) (ns-put-working-text))) + +(defun ns-put-working-text () + "Insert contents of ns-working-text as UTF8 string and mark with +ns-working-overlay. Any previously existing working text is cleared first. +The overlay is assigned the face ns-working-text-face." + (interactive) + (if ns-working-overlay (ns-delete-working-text)) + (let ((start (point))) + (insert ns-working-text) + (overlay-put (setq ns-working-overlay (make-overlay start (point) + (current-buffer) nil t)) + 'face 'ns-working-text-face) + (setq ns-working-overlay-len (+ ns-working-overlay-len (- (point) start))))) + +(defun ns-echo-working-text () + "Echo contents of ns-working-text in message display area. +See ns-insert-working-text." + (if ns-working-overlay (ns-unecho-working-text)) + (let* ((msg (current-message)) + (msglen (length msg)) + message-log-max) + (setq ns-working-overlay-len (length ns-working-text)) + (setq msg (concat msg ns-working-text)) + (put-text-property msglen (+ msglen ns-working-overlay-len) 'face 'ns-working-text-face msg) + (message "%s" msg) + (setq ns-working-overlay t))) + +(defun ns-delete-working-text() + "Delete working text and clear ns-working-overlay." + (interactive) + (delete-backward-char ns-working-overlay-len) + (setq ns-working-overlay-len 0) + (delete-overlay ns-working-overlay)) + +(defun ns-unecho-working-text() + "Delete working text from echo area and clear ns-working-overlay." + (let ((msg (current-message)) + message-log-max) + (setq msg (substring msg 0 (- (length msg) ns-working-overlay-len))) + (setq ns-working-overlay-len 0) + (setq ns-working-overlay nil))) + + +;;;; OS X file system Unicode UTF-8 NFD (decomposed form) support +;; Lisp code based on utf-8m.el, by Seiji Zenitani, Eiji Honjoh, and +;; Carsten Bormann. +(if (eq system-type 'darwin) + (progn + + (defun ns-utf8-nfd-post-read-conversion (length) + "Calls ns-convert-utf8-nfd-to-nfc to compose char sequences." + (save-excursion + (save-restriction + (narrow-to-region (point) (+ (point) length)) + (let ((str (buffer-string))) + (delete-region (point-min) (point-max)) + (insert (ns-convert-utf8-nfd-to-nfc str)) + (- (point-max) (point-min)) + )))) + + (define-coding-system 'utf-8-nfd + "UTF-8 NFD (decomposed) encoding." + :coding-type 'utf-8 + :mnemonic ?U + :charset-list '(unicode) + :post-read-conversion 'ns-utf8-nfd-post-read-conversion) + (set-file-name-coding-system 'utf-8-nfd))) + +;; PENDING: disable composition-based display for Indic scripts as it +;; is not working well under NS for some reason +(set-char-table-range composition-function-table + '(#x0900 . #x0DFF) nil) + + +;;;; Inter-app communications support. + +(defun ns-insert-text () + "Insert contents of ns-input-text at point." + (interactive) + (insert ns-input-text) + (setq ns-input-text nil)) + +(defun ns-insert-file () + "Insert contents of file ns-input-file like insert-file but with less +prompting. If file is a directory perform a find-file on it." + (interactive) + (let ((f)) + (setq f (car ns-input-file)) + (setq ns-input-file (cdr ns-input-file)) + (if (file-directory-p f) + (find-file f) + (push-mark (+ (point) (car (cdr (insert-file-contents f)))))))) + +(defvar ns-select-overlay nil + "Overlay used to highlight areas in files requested by NS apps.") +(make-variable-buffer-local 'ns-select-overlay) + +(defun ns-open-file-select-line () + "Brings up a buffer containing file ns-input-file,\n\ +and highlights lines indicated by ns-input-line." + (interactive) + (ns-find-file) + (cond + ((and ns-input-line (buffer-modified-p)) + (if ns-select-overlay + (setq ns-select-overlay (delete-overlay ns-select-overlay))) + (deactivate-mark) + (goto-line (if (consp ns-input-line) + (min (car ns-input-line) (cdr ns-input-line)) + ns-input-line))) + (ns-input-line + (if (not ns-select-overlay) + (overlay-put (setq ns-select-overlay (make-overlay (point-min) (point-min))) + 'face 'highlight)) + (let ((beg (save-excursion + (goto-line (if (consp ns-input-line) + (min (car ns-input-line) (cdr ns-input-line)) + ns-input-line)) + (point))) + (end (save-excursion + (goto-line (+ 1 (if (consp ns-input-line) + (max (car ns-input-line) (cdr ns-input-line)) + ns-input-line))) + (point)))) + (move-overlay ns-select-overlay beg end) + (deactivate-mark) + (goto-char beg))) + (t + (if ns-select-overlay + (setq ns-select-overlay (delete-overlay ns-select-overlay)))))) + +(defun ns-unselect-line () + "Removes any NS highlight a buffer may contain." + (if ns-select-overlay + (setq ns-select-overlay (delete-overlay ns-select-overlay)))) + +(add-hook 'first-change-hook 'ns-unselect-line) + + + +;;;; Preferences handling. + +(defun get-lisp-resource (arg1 arg2) + (let ((res (ns-get-resource arg1 arg2))) + (cond + ((not res) 'unbound) + ((string-equal (upcase res) "YES") t) + ((string-equal (upcase res) "NO") nil) + (t (read res))))) + +(defun ns-save-preferences () + "Set all the defaults." + (interactive) + ;; Global preferences + (ns-set-resource nil "AlternateModifier" (symbol-name ns-alternate-modifier)) + (ns-set-resource nil "CommandModifier" (symbol-name ns-command-modifier)) + (ns-set-resource nil "ControlModifier" (symbol-name ns-control-modifier)) + (ns-set-resource nil "FunctionModifier" (symbol-name ns-function-modifier)) + (ns-set-resource nil "CursorBlinkRate" + (if ns-cursor-blink-rate + (number-to-string ns-cursor-blink-rate) + "NO")) + (ns-set-resource nil "ExpandSpace" + (if ns-expand-space + (number-to-string ns-expand-space) + "NO")) + (ns-set-resource nil "GSFontAntiAlias" (if ns-antialias-text "YES" "NO")) + (ns-set-resource nil "UseQuickdrawSmoothing" + (if ns-use-qd-smoothing "YES" "NO")) + (ns-set-resource nil "UseSystemHighlightColor" + (if ns-use-system-highlight-color "YES" "NO")) + ;; Default frame parameters + (let ((p (frame-parameters))) + (let ((f (assq 'font p))) + (if f (ns-set-resource nil "Font" (ns-font-name (cdr f))))) + (let ((fs (assq 'fontsize p))) + (if fs (ns-set-resource nil "FontSize" (number-to-string (cdr fs))))) + (let ((fgc (assq 'foreground-color p))) + (if fgc (ns-set-resource nil "Foreground" (cdr fgc)))) + (let ((bgc (assq 'background-color p))) + (if bgc (ns-set-resource nil "Background" (cdr bgc)))) + (let ((cc (assq 'cursor-color p))) + (if cc (ns-set-resource nil "CursorColor" (cdr cc)))) + (let ((ct (assq 'cursor-type p))) + (if ct (ns-set-resource nil "CursorType" + (if (symbolp (cdr ct)) (symbol-name (cdr ct)) (cdr ct))))) + (let ((under (assq 'underline p))) + (if under (ns-set-resource nil "Underline" + (cond ((eq (cdr under) t) "YES") + ((eq (cdr under) nil) "NO") + (t (cdr under)))))) + (let ((ibw (assq 'internal-border-width p))) + (if ibw (ns-set-resource nil "InternalBorderWidth" + (number-to-string (cdr ibw))))) + (let ((vsb (assq 'vertical-scroll-bars p))) + (if vsb (ns-set-resource nil "VerticalScrollBars" (cond + ((eq t (cdr vsb)) "YES") + ((eq nil (cdr vsb)) "NO") + ((eq 'left (cdr vsb)) "left") + ((eq 'right (cdr vsb)) "right") + (t nil))))) + (let ((height (assq 'height p))) + (if height (ns-set-resource nil "Height" + (number-to-string (cdr height))))) + (let ((width (assq 'width p))) + (if width (ns-set-resource nil "Width" + (number-to-string (cdr width))))) + (let ((top (assq 'top p))) + (if top (ns-set-resource nil "Top" + (number-to-string (cdr top))))) + (let ((left (assq 'left p))) + (if left (ns-set-resource nil "Left" + (number-to-string (cdr left))))) + ;; These not fully supported + (let ((ar (assq 'auto-raise p))) + (if ar (ns-set-resource nil "AutoRaise" + (if (cdr ar) "YES" "NO")))) + (let ((al (assq 'auto-lower p))) + (if al (ns-set-resource nil "AutoLower" + (if (cdr al) "YES" "NO")))) + (let ((mbl (assq 'menu-bar-lines p))) + (if mbl (ns-set-resource nil "Menus" + (if (cdr mbl) "YES" "NO")))) + ) + (let ((fl (face-list))) + (while (consp fl) + (or (eq 'default (car fl)) + ;; dont save Default* since it causes all created faces to + ;; inherit its values. The properties of the default face + ;; have already been saved from the frame-parameters anyway. + (let* ((name (symbol-name (car fl))) + (font (face-font (car fl))) +; (fontsize (face-fontsize (car fl))) + (foreground (face-foreground (car fl))) + (background (face-background (car fl))) + (underline (face-underline-p (car fl))) + (italic (face-italic-p (car fl))) + (bold (face-bold-p (car fl))) + (stipple (face-stipple (car fl)))) +; (ns-set-resource nil (concat name ".attributeFont") +; (if font font nil)) +; (ns-set-resource nil (concat name ".attributeFontSize") +; (if fontsize (number-to-string fontsize) nil)) + (ns-set-resource nil (concat name ".attributeForeground") + (if foreground foreground nil)) + (ns-set-resource nil (concat name ".attributeBackground") + (if background background nil)) + (ns-set-resource nil (concat name ".attributeUnderline") + (if underline "YES" nil)) + (ns-set-resource nil (concat name ".attributeItalic") + (if italic "YES" nil)) + (ns-set-resource nil (concat name ".attributeBold") + (if bold "YES" nil)) + (and stipple + (or (stringp stipple) + (setq stipple (prin1-to-string stipple)))) + (ns-set-resource nil (concat name ".attributeStipple") + (if stipple stipple nil)))) + (setq fl (cdr fl))))) + +;; call ns-save-preferences when menu-bar-options-save is called +(fset 'menu-bar-options-save-orig (symbol-function 'menu-bar-options-save)) +(defun ns-save-options () + (interactive) + (menu-bar-options-save-orig) + (ns-save-preferences)) +(fset 'menu-bar-options-save (symbol-function 'ns-save-options)) + + +;;;; File handling. + +(defun ns-open-file-using-panel () + "Pop up open-file panel, and load the result in a buffer." + (interactive) + ; prompt dir defaultName isLoad initial + (setq ns-input-file (ns-read-file-name "Select File to Load" nil t nil)) + (if ns-input-file + (and (setq ns-input-file (list ns-input-file)) (ns-find-file)))) + +(defun ns-write-file-using-panel () + "Pop up save-file panel, and save buffer in resulting name." + (interactive) + (let (ns-output-file) + ; prompt dir defaultName isLoad initial + (setq ns-output-file (ns-read-file-name "Save As" nil nil nil)) + (message ns-output-file) + (if ns-output-file (write-file ns-output-file)))) + +(defun ns-find-file () + "Do a find-file with the ns-input-file as argument." + (interactive) + (let ((f) (file) (bufwin1) (bufwin2)) + (setq f (file-truename (car ns-input-file))) + (setq ns-input-file (cdr ns-input-file)) + (setq file (find-file-noselect f)) + (setq bufwin1 (get-buffer-window file 'visible)) + (setq bufwin2 (get-buffer-window "*scratch*" 'visibile)) + (cond + (bufwin1 + (select-frame (window-frame bufwin1)) + (raise-frame (window-frame bufwin1)) + (select-window bufwin1)) + ((and (eq ns-pop-up-frames 'fresh) bufwin2) + (ns-hide-emacs 'activate) + (select-frame (window-frame bufwin2)) + (raise-frame (window-frame bufwin2)) + (select-window bufwin2) + (find-file f)) + (ns-pop-up-frames + (ns-hide-emacs 'activate) + (let ((pop-up-frames t)) (pop-to-buffer file nil))) + (t + (ns-hide-emacs 'activate) + (find-file f))))) + + + +;;;; Frame-related functions. + +;; Don't show the frame name; that's redundant with NS. +(setq-default mode-line-frame-identification '(" ")) + +(defvar ns-pop-up-frames 'fresh + "* Should file opened upon request from the Workspace be opened in a new frame ? +If t, always. If nil, never. Otherwise a new frame is opened +unless the current buffer is a scratch buffer.") + +;; You say tomAYto, I say tomAHto.. +(defvaralias 'ns-option-modifier 'ns-alternate-modifier) + +(defun ns-do-hide-emacs () + (interactive) + (ns-hide-emacs t)) + +(defun ns-do-hide-others () + (interactive) + (ns-hide-others)) + +(defun ns-do-emacs-info-panel () + (interactive) + (ns-emacs-info-panel)) + +(defun ns-next-frame () + "Switch to next visible frame." + (interactive) + (other-frame 1)) +(defun ns-prev-frame () + "Switch to previous visible frame." + (interactive) + (other-frame -1)) + +; If no position specified, make new frame offset by 25 from current. +(add-hook 'before-make-frame-hook + '(lambda () + (let ((left (cdr (assq 'left (frame-parameters)))) + (top (cdr (assq 'top (frame-parameters))))) + (if (consp left) (setq left (cadr left))) + (if (consp top) (setq top (cadr top))) + (cond + ((or (assq 'top parameters) (assq 'left parameters))) + ((or (not left) (not top))) + (t + (setq parameters (cons (cons 'left (+ left 25)) + (cons (cons 'top (+ top 25)) + parameters)))))))) + +; frame will be focused anyway, so select it +(add-hook 'after-make-frame-functions 'select-frame) + +;;; (defun ns-win-suspend-error () +;;; (error "Suspending an emacs running under *Step/OS X makes no sense")) +;;; (add-hook 'suspend-hook 'ns-win-suspend-error) +;;; (substitute-key-definition 'suspend-emacs 'iconify-or-deiconify-frame +;;; global-map) + +;; Based on a function by David Reitter ; +;; see http://lists.gnu.org/archive/html/emacs-devel/2005-09/msg00681.html . +(defun ns-toggle-toolbar (&optional frame) + "Switches the tool bar on and off in frame FRAME. + If FRAME is nil, the change applies to the selected frame." + (interactive) + (modify-frame-parameters frame + (list (cons 'tool-bar-lines + (if (> (or (frame-parameter frame 'tool-bar-lines) 0) 0) + 0 1)) )) + (if (not tool-bar-mode) (tool-bar-mode t))) + +; Redefine from frame.el +(define-minor-mode blink-cursor-mode + "Toggle blinking cursor mode. +With a numeric argument, turn blinking cursor mode on if ARG is positive, +otherwise turn it off. When blinking cursor mode is enabled, the +cursor of the selected window blinks. + +Note that this command is effective only when Emacs +displays through a window system, because then Emacs does its own +cursor display. On a text-only terminal, this is not implemented." + :init-value (not (or noninteractive + no-blinking-cursor + (eq ns-cursor-blink-rate nil))) + :initialize 'custom-initialize-safe-default + :group 'cursor + :global t + (if blink-cursor-mode + (setq ns-cursor-blink-mode t) + (setq ns-cursor-blink-mode nil))) + + + +;;;; Dialog-related functions. + +;; Ask user for confirm before printing. Due to Kevin Rodgers. +(defun ns-print-buffer () + "Interactive front-end to `print-buffer': asks for user confirmation first." + (interactive) + (if (and (interactive-p) + (or (listp last-nonmenu-event) + (and (char-or-string-p (event-basic-type last-command-event)) + (memq 'super (event-modifiers last-command-event))))) + (let ((last-nonmenu-event (if (listp last-nonmenu-event) + last-nonmenu-event + ;; fake it: + `(mouse-1 POSITION 1)))) + (if (y-or-n-p (format "Print buffer %s? " (buffer-name))) + (print-buffer) + (error "Cancelled"))) + (print-buffer))) + +(defun ns-yes-or-no-p (prompt) + "As yes-or-no-p except that NS panel always used for querying." + (interactive) + (setq last-nonmenu-event nil) + (yes-or-no-p prompt)) + + +;;;; Font support. + +(defalias 'x-list-fonts 'ns-list-fonts) +;; Needed for font listing functions under both backend and normal +(setq scalable-fonts-allowed t) + +;; Set to use font panel instead +(defalias 'generate-fontset-menu 'ns-popup-font-panel) +(defalias 'mouse-set-font 'ns-popup-font-panel) + +(defun ns-respond-to-change-font () + "Respond to changeFont: event, expecting ns-input-font and\n\ +ns-input-fontsize of new font." + (interactive) + (modify-frame-parameters (selected-frame) + (list (cons 'font ns-input-font) + (cons 'fontsize ns-input-fontsize))) + (set-frame-font ns-input-font)) + + +;; Default fontset for Mac OS X. This is mainly here to show how a fontset +;; can be set up manually. Ordinarily, fontsets are auto-created whenever +;; a font is chosen by +(defvar ns-standard-fontset-spec +; Only some code supports this so far, so use uglier XLFD version +; "-ns-*-*-*-*-*-10-*-*-*-*-*-fontset-standard,latin:Courier,han:Kai" +"-ns-*-*-*-*-*-10-*-*-*-*-*-fontset-standard,latin:-*-Courier-*-*-*-*-10-*-*-*-*-*-iso10646-1,han:-*-Kai-*-*-*-*-10-*-*-*-*-*-iso10646-1,cyrillic:-*-Trebuchet$MS-*-*-*-*-10-*-*-*-*-*-iso10646-1" + "String of fontset spec of the standard fontset. +This defines a fontset consisting of the Courier and other fonts that +come with OS X\". +See the documentation of `create-fontset-from-fontset-spec for the format.") + +;; Conditional on new-fontset so bootstrapping works on non-GUI compiles +(if (fboundp 'new-fontset) + (progn + ;; Setup the default fontset. + (setup-default-fontset) + ;; Create the standard fontset. + (create-fontset-from-fontset-spec ns-standard-fontset-spec t) +)) + +;(setq default-frame-alist (cons (cons 'font "-ns-*-*-*-*-*-10-*-*-*-*-*-fontset-standard") default-frame-alist)) + +;; add some additional scripts to var we use for fontset generation +(setq script-representative-chars + (cons '(kana #xff8a) + (cons '(symbol #x2295 #x2287 #x25a1) + script-representative-chars))) + + +;;;; Pasteboard support. + +(defun ns-get-pasteboard () + "Returns the value of the pasteboard." + (ns-get-cut-buffer-internal 'PRIMARY)) + +(defun ns-set-pasteboard (string) + "Store STRING into the NS server's pasteboard." + ;; Check the data type of STRING. + (if (not (stringp string)) (error "Nonstring given to pasteboard")) + (ns-store-cut-buffer-internal 'PRIMARY string)) + +;;; We keep track of the last text selected here, so we can check the +;;; current selection against it, and avoid passing back our own text +;;; from ns-pasteboard-value. +(defvar ns-last-selected-text nil) + +;;; Put TEXT, a string, on the pasteboard. +(defun ns-select-text (text &optional push) + ;; Don't send the pasteboard too much text. + ;; It becomes slow, and if really big it causes errors. + (ns-set-pasteboard text) + (setq ns-last-selected-text text)) + +;;; Return the value of the current NS selection. For compatibility +;;; with older NS applications, this checks cut buffer 0 before +;;; retrieving the value of the primary selection. +(defun ns-pasteboard-value () + (let (text) + + ;; Consult the selection, then the cut buffer. Treat empty strings + ;; as if they were unset. + (or text (setq text (ns-get-pasteboard))) + (if (string= text "") (setq text nil)) + + (cond + ((not text) nil) + ((eq text ns-last-selected-text) nil) + ((string= text ns-last-selected-text) + ;; Record the newer string, so subsequent calls can use the `eq' test. + (setq ns-last-selected-text text) + nil) + (t + (setq ns-last-selected-text text))))) + +(defun ns-copy-including-secondary () + (interactive) + (call-interactively 'kill-ring-save) + (ns-store-cut-buffer-internal 'SECONDARY + (buffer-substring (point) (mark t)))) +(defun ns-paste-secondary () + (interactive) + (insert (ns-get-cut-buffer-internal 'SECONDARY))) + +;; PENDING: not sure what to do here.. for now interprog- are set in +;; init-fn-keys, and unsure whether these x- settings have an effect +;;(setq interprogram-cut-function 'ns-select-text +;; interprogram-paste-function 'ns-pasteboard-value) +; these only needed if above not working +(defalias 'x-select-text 'ns-select-text) +(defalias 'x-cut-buffer-or-selection-value 'ns-pasteboard-value) +(defalias 'x-disown-selection-internal 'ns-disown-selection-internal) +(defalias 'x-get-selection-internal 'ns-get-selection-internal) +(defalias 'x-own-selection-internal 'ns-own-selection-internal) + +(set-face-background 'region "ns_selection_color") + + + +;;;; Scrollbar handling. + +(global-set-key [vertical-scroll-bar down-mouse-1] 'ns-handle-scroll-bar-event) +(global-unset-key [vertical-scroll-bar mouse-1]) +(global-unset-key [vertical-scroll-bar drag-mouse-1]) + +(defun ns-scroll-bar-move (event) + "Scroll the frame according to an NS scroller event." + (interactive "e") + (let* ((pos (event-end event)) + (window (nth 0 pos)) + (scale (nth 2 pos))) + (save-excursion + (set-buffer (window-buffer window)) + (cond + ((eq (car scale) (cdr scale)) + (goto-char (point-max))) + ((= (car scale) 0) + (goto-char (point-min))) + (t + (goto-char (+ (point-min) 1 + (scroll-bar-scale scale (- (point-max) (point-min))))))) + (beginning-of-line) + (set-window-start window (point)) + (vertical-motion (/ (window-height window) 2) window)))) + +(defun ns-handle-scroll-bar-event (event) + "Handle scroll bar EVENT to emulate Mac Toolbox style scrolling." + (interactive "e") + (let* ((position (event-start event)) + (bar-part (nth 4 position)) + (window (nth 0 position)) + (old-window (selected-window))) + (cond + ((eq bar-part 'ratio) + (ns-scroll-bar-move event)) + ((eq bar-part 'handle) + (if (eq window (selected-window)) + (track-mouse (ns-scroll-bar-move event)) + ; track-mouse faster for selected window, slower for unselected + (ns-scroll-bar-move event))) + (t + (select-window window) + (cond + ((eq bar-part 'up) + (goto-char (window-start window)) + (scroll-down 1)) + ((eq bar-part 'above-handle) + (scroll-down)) + ((eq bar-part 'below-handle) + (scroll-up)) + ((eq bar-part 'down) + (goto-char (window-start window)) + (scroll-up 1))) + (select-window old-window))))) + + +;;;; Color support. + +(defvar x-colors (ns-list-colors) + "The list of colors defined in non-PANTONE color files.") +(defvar colors x-colors + "The list of colors defined in non-PANTONE color files.") + +(defun ns-defined-colors (&optional frame) + "Return a list of colors supported for a particular frame. +The argument FRAME specifies which frame to try. +The value may be different for frames on different NS displays." + (or frame (setq frame (selected-frame))) + (let ((all-colors x-colors) + (this-color nil) + (defined-colors nil)) + (while all-colors + (setq this-color (car all-colors) + all-colors (cdr all-colors)) +; (and (face-color-supported-p frame this-color t) + (setq defined-colors (cons this-color defined-colors))) +;) + defined-colors)) +(defalias 'x-defined-colors 'ns-defined-colors) +(defalias 'xw-defined-colors 'ns-defined-colors) + +;; Convenience and work-around for fact that set color fns now require named. +(defun ns-set-background-alpha (alpha) + "Sets alpha (opacity) of background. +Set from 0.0 (fully transparent) to 1.0 (fully opaque; default). +Note, tranparency works better on Tiger (10.4) and higher." + (interactive "nSet background alpha to: ") + (let ((bgcolor (cdr (assq 'background-color (frame-parameters))))) + (set-frame-parameter (selected-frame) + 'background-color (ns-set-alpha bgcolor alpha)))) + +;; Functions for color panel + drag +(defun ns-face-at-pos (pos) + (let* ((frame (car pos)) + (frame-pos (cons (cadr pos) (cddr pos))) + (window (window-at (car frame-pos) (cdr frame-pos) frame)) + (window-pos (coordinates-in-window-p frame-pos window)) + (buffer (window-buffer window)) + (edges (window-edges window))) + (cond + ((not window-pos) + nil) + ((eq window-pos 'mode-line) + 'modeline) + ((eq window-pos 'vertical-line) + 'default) + ((consp window-pos) + (save-excursion + (set-buffer buffer) + (let ((p (car (compute-motion (window-start window) + (cons (nth 0 edges) (nth 1 edges)) + (window-end window) + frame-pos + (- (window-width window) 1) + nil + window)))) + (cond + ((eq p (window-point window)) + 'cursor) + ((and mark-active (< (region-beginning) p) (< p (region-end))) + 'region) + (t + (let ((faces (get-char-property p 'face window))) + (if (consp faces) (car faces) faces))))))) + (t + nil)))) + +(defun ns-set-foreground-at-mouse () + "Set the foreground color at the mouse location to ns-input-color." + (interactive) + (let* ((pos (mouse-position)) + (frame (car pos)) + (face (ns-face-at-pos pos))) + (cond + ((eq face 'cursor) + (modify-frame-parameters frame (list (cons 'cursor-color + ns-input-color)))) + ((not face) + (modify-frame-parameters frame (list (cons 'foreground-color + ns-input-color)))) + (t + (set-face-foreground face ns-input-color frame))))) + +(defun ns-set-background-at-mouse () + "Set the background color at the mouse location to ns-input-color." + (interactive) + (let* ((pos (mouse-position)) + (frame (car pos)) + (face (ns-face-at-pos pos))) + (cond + ((eq face 'cursor) + (modify-frame-parameters frame (list (cons 'cursor-color + ns-input-color)))) + ((not face) + (modify-frame-parameters frame (list (cons 'background-color + ns-input-color)))) + (t + (set-face-background face ns-input-color frame))))) + + + +;; Misc aliases +(defalias 'x-display-mm-width 'ns-display-mm-width) +(defalias 'x-display-mm-height 'ns-display-mm-height) +(defalias 'x-display-backing-store 'ns-display-backing-store) +(defalias 'x-display-save-under 'ns-display-save-under) +(defalias 'x-display-visual-class 'ns-display-visual-class) +(defalias 'x-display-screens 'ns-display-screens) +(defalias 'x-focus-frame 'ns-focus-frame) + +;; Set some options to be as NS-like as possible. +(setq frame-title-format t + icon-title-format t) + +;; Set up browser connectivity +(setq browse-url-browser-function 'browse-url-generic) +(cond ((eq system-type 'darwin) + (setq browse-url-generic-program "open")) + ;; otherwise, gnustep + (t + (setq browse-url-generic-program "gopen")) ) + + +(defvar ns-initialized nil + "Non-nil if NS windowing has been initialized.") + +;;; Do the actual NS Windows setup here; the above code just defines +;;; functions and variables that we use now. +(defun ns-initialize-window-system () + "Initialize Emacs for NS (Cocoa / GNUstep) windowing." + + ; PENDING: not needed? + (setq command-line-args (ns-handle-args command-line-args)) + + (ns-open-connection (system-name) nil t) + + (let ((services (ns-list-services))) + (while services + (if (eq (caar services) 'undefined) + (ns-define-service (cdar services)) + (define-key global-map (vector (caar services)) + (ns-define-service (cdar services))) + ) + (setq services (cdr services)))) + + (if (and (eq (get-lisp-resource nil "NXAutoLaunch") t) + (eq (get-lisp-resource nil "HideOnAutoLaunch") t)) + (add-hook 'after-init-hook 'ns-do-hide-emacs)) + + (menu-bar-mode (if (get-lisp-resource nil "Menus") 1 -1)) + (mouse-wheel-mode 1) + + (setq ns-initialized t)) + +(add-to-list 'handle-args-function-alist '(ns . ns-handle-args)) +(add-to-list 'frame-creation-function-alist '(ns . x-create-frame-with-faces)) +(add-to-list 'window-system-initialization-alist '(ns . ns-initialize-window-system)) + + +(provide 'ns-win) + +;;; ns-win.el ends here diff -r ff312a846b25 -r d45acf0c8d23 lisp/version.el --- a/lisp/version.el Tue Jul 15 15:45:05 2008 +0000 +++ b/lisp/version.el Tue Jul 15 18:15:18 2008 +0000 @@ -65,6 +65,8 @@ ((featurep 'gtk) (concat ", GTK+ Version " gtk-version-string)) ((featurep 'x-toolkit) ", X toolkit") + ((featurep 'ns-windowing) + (format ", *Step %s" ns-version-string)) ((boundp 'mac-carbon-version-string) (concat ", Carbon Version " mac-carbon-version-string)) (t "")) diff -r ff312a846b25 -r d45acf0c8d23 lisp/woman.el --- a/lisp/woman.el Tue Jul 15 15:45:05 2008 +0000 +++ b/lisp/woman.el Tue Jul 15 18:15:18 2008 +0000 @@ -545,9 +545,11 @@ (defcustom woman-man.conf-path (let ((path '("/usr/lib" "/etc"))) - (if (eq system-type 'windows-nt) - (mapcar 'woman-Cyg-to-Win path) - path)) + (cond ((eq system-type 'windows-nt) + (mapcar 'woman-Cyg-to-Win path)) + ((eq system-type 'darwin) + (cons "/usr/share/misc" path)) + (t path))) "List of dirs to search and/or files to try for man config file. A trailing separator (`/' for UNIX etc.) on directories is optional, and the filename is used if a directory specified is @@ -860,7 +862,7 @@ (defcustom woman-use-own-frame ; window-system (or (and (fboundp 'display-graphic-p) (display-graphic-p)) ; Emacs 21 - (memq window-system '(x w32))) ; Emacs 20 + (memq window-system '(x w32 ns))) ; Emacs 20 "If non-nil then use a dedicated frame for displaying WoMan windows. Only useful when run on a graphic display such as X or MS-Windows." :type 'boolean diff -r ff312a846b25 -r d45acf0c8d23 nextstep/AUTHORS --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nextstep/AUTHORS Tue Jul 15 18:15:18 2008 +0000 @@ -0,0 +1,42 @@ +In addition to the folks listed in ../AUTHORS responsible for GNU Emacs itself, +the NeXTstep port owes to the following people: + +Carl Edman + original author and maintainer, mainly UI +Michael Brouwer + heavy contributor, input handling and other areas +Christian Limpach + help / maintenance on NeXTstep +Scott Bender + OpenStep, Rhapsody ports +Christophe de Dinechin + MacOS X port +Adrian Robert + GNUstep port*, update Emacs 20 -> 21+ + +Joe Reiss + popup menu, dialog boxes; icons +Andrew Athan + font panel integration +Scott Byer + improved rendering code +Scott Hess + keyboard handling suggestions + +Rahul Abrol + "hide others" patch +Adam Ratcliffe + preferences panel documentation +Peter Dyballa + assistance with non-ASCII rendering and keyboard handling +David M. Cooke + fix to XPM crash bug +Carsten Bormann + initial patch and assistance getting dired working for non-ASCII filenames +Andrew Moore + assistance on ns-mark-nav extension + +(*) +The GNUstep port was made possible through the assistance of Adam Fedor, Fred +Kiefer, M. Uli Klusterer, Alexander Malmberg, Jonas Matton, and Riccardo +Mottola. diff -r ff312a846b25 -r d45acf0c8d23 nextstep/ChangeLog --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nextstep/ChangeLog Tue Jul 15 18:15:18 2008 +0000 @@ -0,0 +1,46 @@ +2008-07-15 Adrian Robert + + New directory with support files to support NeXTstep window system. + + * AUTHORS: New file: contributor information for NS port. + * ChangeLog.nextstep: New file: changelog info to be added to + various directories on merge. + * ChangeLog: New file: recent history of the NS port itself. + * Cocoa: New directory: support files for building .app + package on OS X systems. + * Cocoa/Emacs.base + * Cocoa/Emacs.base/Contents: New directories. + * Cocoa/Emacs.base/Contents/Info.plist + * Cocoa/Emacs.base/Contents/PkgInfo: New files. + * Cocoa/Emacs.base/Contents/Resources: New directory. + * Cocoa/Emacs.base/Contents/Resources/Credits.html: New file: + About popup support. + * Cocoa/Emacs.base/Contents/Resources/Emacs.icns: New file: + copied from Carbon port. + * Cocoa/Emacs.base/Contents/Resources/English.lproj: New + directory. + * Cocoa/Emacs.base/Contents/Resources/English.lproj/InfoPlist.strings: + New file. + * Cocoa/Emacs.base/Contents/Resources/preferences.nib: New + directory. + * Cocoa/Emacs.base/Contents/Resources/preferences.nib/classes.nib + * Cocoa/Emacs.base/Contents/Resources/preferences.nib/info.nib + * Cocoa/Emacs.base/Contents/Resources/preferences.nib/keyedobjects.nib: + New files. + * Cocoa/Emacs.xcodeproj: New directory: build support. + * Cocoa/Emacs.xcodeproj/project.pbxproj: New file. + * GNUstep: New directory: support files for building .app + package on GNUstep systems. + * GNUstep/Resources: New directory. + * GNUstep/Resources/Emacs.desktop + * GNUstep/Resources/Info-gnustep.plist + * GNUstep/Resources/emacs.tiff: New files. + * GNUstep/Resources/preferences.gorm: New directory. + * GNUstep/Resources/preferences.gorm/data.classes + * GNUstep/Resources/preferences.gorm/data.info + * GNUstep/Resources/preferences.gorm/objects.gorm: New + files. + * compile: New file: utility script for building Emacs.app. + * FOR_RELEASE: New file: release tasks specific to NeXTstep + port. + * README.txt: New file: descriptive info for NeXTstep port. diff -r ff312a846b25 -r d45acf0c8d23 nextstep/Cocoa/Emacs.base/Contents/Info.plist --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nextstep/Cocoa/Emacs.base/Contents/Info.plist Tue Jul 15 18:15:18 2008 +0000 @@ -0,0 +1,212 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDocumentTypes + + + CFBundleTypeExtensions + + txt + + CFBundleTypeName + Text + CFBundleTypeRole + Editor + + + CFBundleTypeExtensions + + c + h + + CFBundleTypeName + C + CFBundleTypeRole + Editor + + + CFBundleTypeExtensions + + C + H + cpp + cc + hh + + CFBundleTypeName + C++ + CFBundleTypeRole + Editor + + + CFBundleTypeExtensions + + m + + CFBundleTypeName + Objective C + CFBundleTypeRole + Editor + + + CFBundleTypeExtensions + + el + + CFBundleTypeName + Lisp + CFBundleTypeRole + Editor + + + CFBundleTypeExtensions + + xml + xhtml + xsl + xsd + xsdl + + CFBundleTypeName + XML + CFBundleTypeRole + Editor + + + CFBundleTypeExtensions + + java + + CFBundleTypeName + Java + CFBundleTypeRole + Editor + + + CFBundleTypeExtensions + + tex + ltx + bib + bbl + + CFBundleTypeName + TeX/LaTeX + CFBundleTypeRole + Editor + + + CFBundleTypeExtensions + + * + + CFBundleTypeName + Any + CFBundleTypeOSTypes + + **** + + CFBundleTypeRole + Editor + + + + NSServices + + + NSMenuItem + + default + Emacs.app/New Buffer Containing Selection + + NSMessage + requestService + NSUserData + open-selection + NSPortName + Emacs + NSSendTypes + + NSStringPboardType + + + + NSMenuItem + + default + Emacs.app/Open Selected File + + NSMessage + requestService + NSUserData + open-file + NSPortName + Emacs + NSSendTypes + + NSStringPboardType + + + + NSMenuItem + + default + Emacs.app/Email Selection + + NSMessage + requestService + NSUserData + mail-selection + NSPortName + Emacs + NSSendTypes + + NSStringPboardType + + + + NSMenuItem + + default + Emacs.app/Send Email to Selected Address + + NSMessage + requestService + NSUserData + mail-to + NSPortName + Emacs + NSSendTypes + + NSStringPboardType + + + + + CFBundleExecutable + Emacs + CFBundleGetInfoString + Emacs 23.0.60 (C) Free Software Foundation + CFBundleIconFile + Emacs + CFBundleIdentifier + Emacs + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Emacs + CFBundlePackageType + APPL + CFBundleShortVersionString + Version 23.0.60 + CFBundleSignature + Emcs + CFBundleVersion + NS 9.0 + NSPrincipalClass + EmacsApp + + diff -r ff312a846b25 -r d45acf0c8d23 nextstep/Cocoa/Emacs.base/Contents/PkgInfo --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nextstep/Cocoa/Emacs.base/Contents/PkgInfo Tue Jul 15 18:15:18 2008 +0000 @@ -0,0 +1,1 @@ +APPLEmcs \ No newline at end of file diff -r ff312a846b25 -r d45acf0c8d23 nextstep/Cocoa/Emacs.base/Contents/Resources/Credits.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nextstep/Cocoa/Emacs.base/Contents/Resources/Credits.html Tue Jul 15 18:15:18 2008 +0000 @@ -0,0 +1,1 @@ +http://emacs-app.sf.net diff -r ff312a846b25 -r d45acf0c8d23 nextstep/Cocoa/Emacs.base/Contents/Resources/Emacs.icns Binary file nextstep/Cocoa/Emacs.base/Contents/Resources/Emacs.icns has changed diff -r ff312a846b25 -r d45acf0c8d23 nextstep/Cocoa/Emacs.base/Contents/Resources/English.lproj/InfoPlist.strings --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nextstep/Cocoa/Emacs.base/Contents/Resources/English.lproj/InfoPlist.strings Tue Jul 15 18:15:18 2008 +0000 @@ -0,0 +1,6 @@ +/* Localized versions of Info.plist keys */ + +CFBundleName = "Emacs"; +CFBundleShortVersionString = "Version 23.0.60"; +CFBundleGetInfoString = "Emacs version 23.0.60, GNUstep / MacOS X Cocoa version 9.0"; +NSHumanReadableCopyright = "Copyright 2008 Free Software Foundation."; diff -r ff312a846b25 -r d45acf0c8d23 nextstep/Cocoa/Emacs.base/Contents/Resources/preferences.nib/classes.nib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nextstep/Cocoa/Emacs.base/Contents/Resources/preferences.nib/classes.nib Tue Jul 15 18:15:18 2008 +0000 @@ -0,0 +1,32 @@ +{ + IBClasses = ( + { + ACTIONS = { + cancel = id; + ok = id; + resetToDefaults = id; + runHelp = id; + setColors = id; + setDefaultFont = id; + }; + CLASS = EmacsPrefsController; + LANGUAGE = ObjC; + OUTLETS = { + alternateModMenu = NSPopUpButton; + commandModMenu = NSPopUpButton; + controlModMenu = NSPopUpButton; + cursorBlinkSlider = NSSlider; + cursorTypeMatrix = NSMatrix; + expandSpaceSlider = NSSlider; + functionModMenu = NSPopUpButton; + prefsWindow = NSWindow; + smoothFontsCheck = NSButton; + useQuickdrawCheck = NSButton; + useSysHiliteCheck = NSButton; + }; + SUPERCLASS = NSObject; + }, + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; } + ); + IBVersion = 1; +} \ No newline at end of file diff -r ff312a846b25 -r d45acf0c8d23 nextstep/Cocoa/Emacs.base/Contents/Resources/preferences.nib/info.nib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nextstep/Cocoa/Emacs.base/Contents/Resources/preferences.nib/info.nib Tue Jul 15 18:15:18 2008 +0000 @@ -0,0 +1,46 @@ + + + + + IBDocumentLocation + 196 42 356 240 0 0 1440 878 + IBFramework Version + 446.1 + IBGroupedObjects + + 5 + + 114 + 110 + 111 + 112 + 113 + + 6 + + 183 + 176 + + 7 + + 191 + 184 + + 9 + + 201 + 194 + + + IBLastGroupID + 10 + IBOldestOS + 3 + IBOpenObjects + + 5 + + IBSystem Version + 8R2232 + + diff -r ff312a846b25 -r d45acf0c8d23 nextstep/Cocoa/Emacs.base/Contents/Resources/preferences.nib/keyedobjects.nib Binary file nextstep/Cocoa/Emacs.base/Contents/Resources/preferences.nib/keyedobjects.nib has changed diff -r ff312a846b25 -r d45acf0c8d23 nextstep/Cocoa/Emacs.xcodeproj/project.pbxproj --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nextstep/Cocoa/Emacs.xcodeproj/project.pbxproj Tue Jul 15 18:15:18 2008 +0000 @@ -0,0 +1,848 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 42; + objects = { + +/* Begin PBXBuildFile section */ + 3C15C0EB0902D89500A8542F /* termhooks.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C02F0902D89500A8542F /* termhooks.h */; }; + 3C15C0EC0902D89500A8542F /* termchar.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0300902D89500A8542F /* termchar.h */; }; + 3C15C0EF0902D89500A8542F /* syswait.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0330902D89500A8542F /* syswait.h */; }; + 3C15C0F00902D89500A8542F /* systty.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0340902D89500A8542F /* systty.h */; }; + 3C15C0F10902D89500A8542F /* systime.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0350902D89500A8542F /* systime.h */; }; + 3C15C0F20902D89500A8542F /* syssignal.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0360902D89500A8542F /* syssignal.h */; }; + 3C15C0F30902D89500A8542F /* sysselect.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0370902D89500A8542F /* sysselect.h */; }; + 3C15C0F50902D89500A8542F /* syntax.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0390902D89500A8542F /* syntax.h */; }; + 3C15C0FD0902D89500A8542F /* region-cache.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0410902D89500A8542F /* region-cache.h */; }; + 3C15C0FF0902D89500A8542F /* regex.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0430902D89500A8542F /* regex.h */; }; + 3C15C1020902D89500A8542F /* puresize.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0460902D89500A8542F /* puresize.h */; }; + 3C15C1030902D89500A8542F /* process.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0470902D89500A8542F /* process.h */; }; + 3C15C1080902D89500A8542F /* point.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C04C0902D89500A8542F /* point.h */; }; + 3C15C1090902D89500A8542F /* param.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C04D0902D89500A8542F /* param.h */; }; + 3C15C10B0902D89500A8542F /* nsgui.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C04F0902D89500A8542F /* nsgui.h */; }; + 3C15C10C0902D89500A8542F /* ndir.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0500902D89500A8542F /* ndir.h */; }; + 3C15C1110902D89500A8542F /* mem-limits.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0550902D89500A8542F /* mem-limits.h */; }; + 3C15C1120902D89500A8542F /* md5.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0560902D89500A8542F /* md5.h */; }; + 3C15C1190902D89500A8542F /* macros.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C05D0902D89500A8542F /* macros.h */; }; + 3C15C1220902D89500A8542F /* keymap.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0660902D89500A8542F /* keymap.h */; }; + 3C15C1240902D89500A8542F /* keyboard.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0680902D89500A8542F /* keyboard.h */; }; + 3C15C1270902D89500A8542F /* intervals.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C06B0902D89500A8542F /* intervals.h */; }; + 3C15C12A0902D89500A8542F /* indent.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C06E0902D89500A8542F /* indent.h */; }; + 3C15C1320902D89500A8542F /* category.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0760902D89500A8542F /* category.h */; }; + 3C15C1330902D89500A8542F /* coding.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0770902D89500A8542F /* coding.h */; }; + 3C15C1340902D89500A8542F /* buffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0780902D89500A8542F /* buffer.h */; }; + 3C15C1350902D89500A8542F /* vlimit.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0790902D89500A8542F /* vlimit.h */; }; + 3C15C1450902D89500A8542F /* cm.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0890902D89500A8542F /* cm.h */; }; + 3C15C14E0902D89500A8542F /* uaf.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0920902D89500A8542F /* uaf.h */; }; + 3C15C1510902D89500A8542F /* termopts.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0950902D89500A8542F /* termopts.h */; }; + 3C15C15C0902D89500A8542F /* window.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0A00902D89500A8542F /* window.h */; }; + 3C15C1720902D89500A8542F /* gnu.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0B60902D89500A8542F /* gnu.h */; }; + 3C15C1740902D89500A8542F /* getpagesize.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0B80902D89500A8542F /* getpagesize.h */; }; + 3C15C17B0902D89500A8542F /* disptab.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0BF0902D89500A8542F /* disptab.h */; }; + 3C15C17E0902D89500A8542F /* epaths.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0C20902D89500A8542F /* epaths.h */; }; + 3C15C1810902D89500A8542F /* ccl.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0C50902D89500A8542F /* ccl.h */; }; + 3C15C1830902D89500A8542F /* composite.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0C70902D89500A8542F /* composite.h */; }; + 3C15C1840902D89500A8542F /* charset.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0C80902D89500A8542F /* charset.h */; }; + 3C15C1850902D89500A8542F /* fontset.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0C90902D89500A8542F /* fontset.h */; }; + 3C15C1930902D89500A8542F /* commands.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0D70902D89500A8542F /* commands.h */; }; + 3C15C1950902D89500A8542F /* dispextern.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0D90902D89500A8542F /* dispextern.h */; }; + 3C15C1970902D89500A8542F /* acldef.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0DB0902D89500A8542F /* acldef.h */; }; + 3C15C19A0902D89500A8542F /* character.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0DE0902D89500A8542F /* character.h */; }; + 3C15C19E0902D89500A8542F /* chpdef.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0E20902D89500A8542F /* chpdef.h */; }; + 3C15C1A00902D89500A8542F /* frame.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0E40902D89500A8542F /* frame.h */; }; + 3C15C1A20902D89500A8542F /* atimer.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0E60902D89500A8542F /* atimer.h */; }; + 3C15C1A30902D89500A8542F /* blockinput.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C15C0E70902D89500A8542F /* blockinput.h */; }; + 3C15C1A80902D97100A8542F /* nsimage.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C15C1A70902D97100A8542F /* nsimage.m */; }; + 3C4D6D6B0DE50D2300B20D4E /* font.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C4D6D660DE50D2300B20D4E /* font.c */; }; + 3C4D6D6C0DE50D2300B20D4E /* font.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C4D6D670DE50D2300B20D4E /* font.h */; }; + 3C4D6D6D0DE50D2300B20D4E /* termcap.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C4D6D680DE50D2300B20D4E /* termcap.c */; }; + 3C4D6D6E0DE50D2300B20D4E /* terminal.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C4D6D690DE50D2300B20D4E /* terminal.c */; }; + 3C4D6D6F0DE50D2300B20D4E /* tparam.c in Sources */ = {isa = PBXBuildFile; fileRef = 3C4D6D6A0DE50D2300B20D4E /* tparam.c */; }; + 3C4D6D730DE50D5D00B20D4E /* nsfont.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C4D6D710DE50D5D00B20D4E /* nsfont.m */; }; + 3C7F3C3B07EB3B05003C8A4D /* nsterm.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C7F3C3A07EB3B05003C8A4D /* nsterm.h */; }; + 3CB8E29A0E2CE6BF003F3104 /* preferences.nib in Resources */ = {isa = PBXBuildFile; fileRef = 3CB8E2990E2CE6BF003F3104 /* preferences.nib */; }; + 3CB8E29E0E2CE73A003F3104 /* Emacs.icns in Resources */ = {isa = PBXBuildFile; fileRef = 3CB8E29D0E2CE73A003F3104 /* Emacs.icns */; }; + 3CB8E2A00E2CE7F5003F3104 /* Credits.html in Resources */ = {isa = PBXBuildFile; fileRef = 3CB8E29F0E2CE7F5003F3104 /* Credits.html */; }; + 3CB8E2A70E2CE856003F3104 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3CB8E2A50E2CE856003F3104 /* InfoPlist.strings */; }; + 3CC5430607E2315800C271A9 /* nsfns.m in Sources */ = {isa = PBXBuildFile; fileRef = 090AF67E00C61DCD7F000001 /* nsfns.m */; }; + 3CC5430707E2315800C271A9 /* nsmenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 090AF68000C61DCD7F000001 /* nsmenu.m */; }; + 3CC5430807E2315800C271A9 /* nsselect.m in Sources */ = {isa = PBXBuildFile; fileRef = 090AF68100C61DCD7F000001 /* nsselect.m */; }; + 3CC5430907E2315800C271A9 /* nsterm.m in Sources */ = {isa = PBXBuildFile; fileRef = 090AF68300C61DCD7F000001 /* nsterm.m */; }; + 3CDCED340902E99700B2EF7E /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = 3CDCED330902E99700B2EF7E /* config.h */; }; + 3CDCEDD00902EA8200B2EF7E /* term.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED550902EA8100B2EF7E /* term.c */; }; + 3CDCEDD10902EA8200B2EF7E /* sysdep.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED560902EA8100B2EF7E /* sysdep.c */; }; + 3CDCEDD20902EA8200B2EF7E /* syntax.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED570902EA8100B2EF7E /* syntax.c */; }; + 3CDCEDD40902EA8200B2EF7E /* strftime.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED590902EA8100B2EF7E /* strftime.c */; }; + 3CDCEDD50902EA8200B2EF7E /* sound.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED5A0902EA8100B2EF7E /* sound.c */; }; + 3CDCEDD70902EA8200B2EF7E /* search.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED5C0902EA8100B2EF7E /* search.c */; }; + 3CDCEDD80902EA8200B2EF7E /* scroll.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED5D0902EA8100B2EF7E /* scroll.c */; }; + 3CDCEDD90902EA8200B2EF7E /* region-cache.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED5E0902EA8100B2EF7E /* region-cache.c */; }; + 3CDCEDDA0902EA8200B2EF7E /* regex.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED5F0902EA8100B2EF7E /* regex.c */; }; + 3CDCEDDC0902EA8200B2EF7E /* process.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED610902EA8100B2EF7E /* process.c */; }; + 3CDCEDDD0902EA8200B2EF7E /* print.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED620902EA8100B2EF7E /* print.c */; }; + 3CDCEDDF0902EA8200B2EF7E /* pre-crt0.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED640902EA8100B2EF7E /* pre-crt0.c */; }; + 3CDCEDE20902EA8200B2EF7E /* minibuf.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED670902EA8100B2EF7E /* minibuf.c */; }; + 3CDCEDE30902EA8200B2EF7E /* md5.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED680902EA8100B2EF7E /* md5.c */; }; + 3CDCEDE40902EA8200B2EF7E /* marker.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED690902EA8100B2EF7E /* marker.c */; }; + 3CDCEDE80902EA8200B2EF7E /* macros.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED6D0902EA8100B2EF7E /* macros.c */; }; + 3CDCEDEC0902EA8200B2EF7E /* lread.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED710902EA8100B2EF7E /* lread.c */; }; + 3CDCEDED0902EA8200B2EF7E /* lastfile.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED720902EA8100B2EF7E /* lastfile.c */; }; + 3CDCEDEE0902EA8200B2EF7E /* keymap.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED730902EA8100B2EF7E /* keymap.c */; }; + 3CDCEDEF0902EA8200B2EF7E /* keyboard.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED740902EA8200B2EF7E /* keyboard.c */; }; + 3CDCEDF00902EA8200B2EF7E /* intervals.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED750902EA8200B2EF7E /* intervals.c */; }; + 3CDCEDF10902EA8200B2EF7E /* insdel.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED760902EA8200B2EF7E /* insdel.c */; }; + 3CDCEDF20902EA8200B2EF7E /* indent.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED770902EA8200B2EF7E /* indent.c */; }; + 3CDCEDF30902EA8200B2EF7E /* image.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED780902EA8200B2EF7E /* image.c */; }; + 3CDCEDF50902EA8200B2EF7E /* cmds.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED7A0902EA8200B2EF7E /* cmds.c */; }; + 3CDCEDF60902EA8200B2EF7E /* category.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED7B0902EA8200B2EF7E /* category.c */; }; + 3CDCEDF70902EA8200B2EF7E /* coding.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED7C0902EA8200B2EF7E /* coding.c */; }; + 3CDCEDFE0902EA8200B2EF7E /* unexmacosx.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED830902EA8200B2EF7E /* unexmacosx.c */; }; + 3CDCEE060902EA8200B2EF7E /* buffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED8B0902EA8200B2EF7E /* buffer.c */; }; + 3CDCEE070902EA8200B2EF7E /* character.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED8C0902EA8200B2EF7E /* character.c */; }; + 3CDCEE0D0902EA8200B2EF7E /* undo.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED920902EA8200B2EF7E /* undo.c */; }; + 3CDCEE0F0902EA8200B2EF7E /* textprop.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED940902EA8200B2EF7E /* textprop.c */; }; + 3CDCEE100902EA8200B2EF7E /* terminfo.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED950902EA8200B2EF7E /* terminfo.c */; }; + 3CDCEE170902EA8200B2EF7E /* xfaces.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED9C0902EA8200B2EF7E /* xfaces.c */; }; + 3CDCEE180902EA8200B2EF7E /* xdisp.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED9D0902EA8200B2EF7E /* xdisp.c */; }; + 3CDCEE190902EA8200B2EF7E /* window.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCED9E0902EA8200B2EF7E /* window.c */; }; + 3CDCEE2B0902EA8200B2EF7E /* doprnt.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCEDB00902EA8200B2EF7E /* doprnt.c */; }; + 3CDCEE2C0902EA8200B2EF7E /* doc.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCEDB10902EA8200B2EF7E /* doc.c */; }; + 3CDCEE2D0902EA8200B2EF7E /* dired.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCEDB20902EA8200B2EF7E /* dired.c */; }; + 3CDCEE2E0902EA8200B2EF7E /* data.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCEDB30902EA8200B2EF7E /* data.c */; }; + 3CDCEE2F0902EA8200B2EF7E /* callint.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCEDB40902EA8200B2EF7E /* callint.c */; }; + 3CDCEE310902EA8200B2EF7E /* ccl.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCEDB60902EA8200B2EF7E /* ccl.c */; }; + 3CDCEE320902EA8200B2EF7E /* fontset.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCEDB70902EA8200B2EF7E /* fontset.c */; }; + 3CDCEE330902EA8200B2EF7E /* fns.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCEDB80902EA8200B2EF7E /* fns.c */; }; + 3CDCEE340902EA8200B2EF7E /* floatfns.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCEDB90902EA8200B2EF7E /* floatfns.c */; }; + 3CDCEE360902EA8200B2EF7E /* filemode.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCEDBB0902EA8200B2EF7E /* filemode.c */; }; + 3CDCEE370902EA8200B2EF7E /* filelock.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCEDBC0902EA8200B2EF7E /* filelock.c */; }; + 3CDCEE380902EA8200B2EF7E /* emacs.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCEDBD0902EA8200B2EF7E /* emacs.c */; }; + 3CDCEE390902EA8200B2EF7E /* editfns.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCEDBE0902EA8200B2EF7E /* editfns.c */; }; + 3CDCEE3A0902EA8200B2EF7E /* fileio.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCEDBF0902EA8200B2EF7E /* fileio.c */; }; + 3CDCEE3B0902EA8200B2EF7E /* eval.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCEDC00902EA8200B2EF7E /* eval.c */; }; + 3CDCEE3C0902EA8200B2EF7E /* casetab.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCEDC10902EA8200B2EF7E /* casetab.c */; }; + 3CDCEE3D0902EA8200B2EF7E /* composite.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCEDC20902EA8200B2EF7E /* composite.c */; }; + 3CDCEE3E0902EA8200B2EF7E /* dispnew.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCEDC30902EA8200B2EF7E /* dispnew.c */; }; + 3CDCEE3F0902EA8200B2EF7E /* charset.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCEDC40902EA8200B2EF7E /* charset.c */; }; + 3CDCEE400902EA8200B2EF7E /* alloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCEDC50902EA8200B2EF7E /* alloc.c */; }; + 3CDCEE410902EA8200B2EF7E /* bytecode.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCEDC60902EA8200B2EF7E /* bytecode.c */; }; + 3CDCEE420902EA8200B2EF7E /* callproc.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCEDC70902EA8200B2EF7E /* callproc.c */; }; + 3CDCEE430902EA8200B2EF7E /* cm.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCEDC80902EA8200B2EF7E /* cm.c */; }; + 3CDCEE440902EA8200B2EF7E /* casefiddle.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCEDC90902EA8200B2EF7E /* casefiddle.c */; }; + 3CDCEE450902EA8200B2EF7E /* fringe.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCEDCA0902EA8200B2EF7E /* fringe.c */; }; + 3CDCEE460902EA8200B2EF7E /* frame.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCEDCB0902EA8200B2EF7E /* frame.c */; }; + 3CDCEE470902EA8200B2EF7E /* chartab.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCEDCC0902EA8200B2EF7E /* chartab.c */; }; + 3CDCEE480902EA8200B2EF7E /* atimer.c in Sources */ = {isa = PBXBuildFile; fileRef = 3CDCEDCD0902EA8200B2EF7E /* atimer.c */; }; + 3CFDFC3B08E79A6800B05918 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3CFDFC3A08E79A6800B05918 /* AppKit.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 090AF67E00C61DCD7F000001 /* nsfns.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = nsfns.m; path = ../../src/nsfns.m; sourceTree = ""; }; + 090AF68000C61DCD7F000001 /* nsmenu.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = nsmenu.m; path = ../../src/nsmenu.m; sourceTree = ""; }; + 090AF68100C61DCD7F000001 /* nsselect.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = nsselect.m; path = ../../src/nsselect.m; sourceTree = ""; }; + 090AF68300C61DCD7F000001 /* nsterm.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = nsterm.m; path = ../../src/nsterm.m; sourceTree = ""; }; + 3C15C02F0902D89500A8542F /* termhooks.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = termhooks.h; path = ../../src/termhooks.h; sourceTree = ""; }; + 3C15C0300902D89500A8542F /* termchar.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = termchar.h; path = ../../src/termchar.h; sourceTree = ""; }; + 3C15C0330902D89500A8542F /* syswait.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = syswait.h; path = ../../src/syswait.h; sourceTree = ""; }; + 3C15C0340902D89500A8542F /* systty.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = systty.h; path = ../../src/systty.h; sourceTree = ""; }; + 3C15C0350902D89500A8542F /* systime.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = systime.h; path = ../../src/systime.h; sourceTree = ""; }; + 3C15C0360902D89500A8542F /* syssignal.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = syssignal.h; path = ../../src/syssignal.h; sourceTree = ""; }; + 3C15C0370902D89500A8542F /* sysselect.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = sysselect.h; path = ../../src/sysselect.h; sourceTree = ""; }; + 3C15C0390902D89500A8542F /* syntax.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = syntax.h; path = ../../src/syntax.h; sourceTree = ""; }; + 3C15C0410902D89500A8542F /* region-cache.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = "region-cache.h"; path = "../../src/region-cache.h"; sourceTree = ""; }; + 3C15C0430902D89500A8542F /* regex.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = regex.h; path = ../../src/regex.h; sourceTree = ""; }; + 3C15C0460902D89500A8542F /* puresize.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = puresize.h; path = ../../src/puresize.h; sourceTree = ""; }; + 3C15C0470902D89500A8542F /* process.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = process.h; path = ../../src/process.h; sourceTree = ""; }; + 3C15C04C0902D89500A8542F /* point.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = point.h; path = ../../src/point.h; sourceTree = ""; }; + 3C15C04D0902D89500A8542F /* param.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = param.h; path = ../../src/param.h; sourceTree = ""; }; + 3C15C04F0902D89500A8542F /* nsgui.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = nsgui.h; path = ../../src/nsgui.h; sourceTree = ""; }; + 3C15C0500902D89500A8542F /* ndir.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ndir.h; path = ../../src/ndir.h; sourceTree = ""; }; + 3C15C0550902D89500A8542F /* mem-limits.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = "mem-limits.h"; path = "../../src/mem-limits.h"; sourceTree = ""; }; + 3C15C0560902D89500A8542F /* md5.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = md5.h; path = ../../src/md5.h; sourceTree = ""; }; + 3C15C05D0902D89500A8542F /* macros.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macros.h; path = ../../src/macros.h; sourceTree = ""; }; + 3C15C0660902D89500A8542F /* keymap.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = keymap.h; path = ../../src/keymap.h; sourceTree = ""; }; + 3C15C0680902D89500A8542F /* keyboard.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = keyboard.h; path = ../../src/keyboard.h; sourceTree = ""; }; + 3C15C06B0902D89500A8542F /* intervals.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = intervals.h; path = ../../src/intervals.h; sourceTree = ""; }; + 3C15C06E0902D89500A8542F /* indent.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = indent.h; path = ../../src/indent.h; sourceTree = ""; }; + 3C15C0760902D89500A8542F /* category.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = category.h; path = ../../src/category.h; sourceTree = ""; }; + 3C15C0770902D89500A8542F /* coding.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = coding.h; path = ../../src/coding.h; sourceTree = ""; }; + 3C15C0780902D89500A8542F /* buffer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = buffer.h; path = ../../src/buffer.h; sourceTree = ""; }; + 3C15C0790902D89500A8542F /* vlimit.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = vlimit.h; path = ../../src/vlimit.h; sourceTree = ""; }; + 3C15C0890902D89500A8542F /* cm.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = cm.h; path = ../../src/cm.h; sourceTree = ""; }; + 3C15C0920902D89500A8542F /* uaf.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = uaf.h; path = ../../src/uaf.h; sourceTree = ""; }; + 3C15C0950902D89500A8542F /* termopts.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = termopts.h; path = ../../src/termopts.h; sourceTree = ""; }; + 3C15C0A00902D89500A8542F /* window.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = window.h; path = ../../src/window.h; sourceTree = ""; }; + 3C15C0B60902D89500A8542F /* gnu.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = gnu.h; path = ../../src/gnu.h; sourceTree = ""; }; + 3C15C0B80902D89500A8542F /* getpagesize.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = getpagesize.h; path = ../../src/getpagesize.h; sourceTree = ""; }; + 3C15C0BF0902D89500A8542F /* disptab.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = disptab.h; path = ../../src/disptab.h; sourceTree = ""; }; + 3C15C0C20902D89500A8542F /* epaths.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = epaths.h; path = ../../src/epaths.h; sourceTree = ""; }; + 3C15C0C50902D89500A8542F /* ccl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ccl.h; path = ../../src/ccl.h; sourceTree = ""; }; + 3C15C0C70902D89500A8542F /* composite.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = composite.h; path = ../../src/composite.h; sourceTree = ""; }; + 3C15C0C80902D89500A8542F /* charset.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = charset.h; path = ../../src/charset.h; sourceTree = ""; }; + 3C15C0C90902D89500A8542F /* fontset.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = fontset.h; path = ../../src/fontset.h; sourceTree = ""; }; + 3C15C0D70902D89500A8542F /* commands.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = commands.h; path = ../../src/commands.h; sourceTree = ""; }; + 3C15C0D90902D89500A8542F /* dispextern.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = dispextern.h; path = ../../src/dispextern.h; sourceTree = ""; }; + 3C15C0DB0902D89500A8542F /* acldef.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = acldef.h; path = ../../src/acldef.h; sourceTree = ""; }; + 3C15C0DE0902D89500A8542F /* character.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = character.h; path = ../../src/character.h; sourceTree = ""; }; + 3C15C0E20902D89500A8542F /* chpdef.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = chpdef.h; path = ../../src/chpdef.h; sourceTree = ""; }; + 3C15C0E40902D89500A8542F /* frame.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = frame.h; path = ../../src/frame.h; sourceTree = ""; }; + 3C15C0E60902D89500A8542F /* atimer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = atimer.h; path = ../../src/atimer.h; sourceTree = ""; }; + 3C15C0E70902D89500A8542F /* blockinput.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = blockinput.h; path = ../../src/blockinput.h; sourceTree = ""; }; + 3C15C1A70902D97100A8542F /* nsimage.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = nsimage.m; path = ../../src/nsimage.m; sourceTree = ""; }; + 3C4D6D660DE50D2300B20D4E /* font.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = font.c; path = ../../src/font.c; sourceTree = SOURCE_ROOT; }; + 3C4D6D670DE50D2300B20D4E /* font.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = font.h; path = ../../src/font.h; sourceTree = SOURCE_ROOT; }; + 3C4D6D680DE50D2300B20D4E /* termcap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = termcap.c; path = ../../src/termcap.c; sourceTree = SOURCE_ROOT; }; + 3C4D6D690DE50D2300B20D4E /* terminal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = terminal.c; path = ../../src/terminal.c; sourceTree = SOURCE_ROOT; }; + 3C4D6D6A0DE50D2300B20D4E /* tparam.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tparam.c; path = ../../src/tparam.c; sourceTree = SOURCE_ROOT; }; + 3C4D6D710DE50D5D00B20D4E /* nsfont.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = nsfont.m; path = ../../src/nsfont.m; sourceTree = SOURCE_ROOT; }; + 3C7F3C3A07EB3B05003C8A4D /* nsterm.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = nsterm.h; path = ../../src/nsterm.h; sourceTree = ""; }; + 3CB8E2990E2CE6BF003F3104 /* preferences.nib */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = preferences.nib; path = Emacs.base/Contents/Resources/preferences.nib; sourceTree = ""; }; + 3CB8E29D0E2CE73A003F3104 /* Emacs.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = Emacs.icns; path = Emacs.base/Contents/Resources/Emacs.icns; sourceTree = ""; }; + 3CB8E29F0E2CE7F5003F3104 /* Credits.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; name = Credits.html; path = Emacs.base/Contents/Resources/Credits.html; sourceTree = ""; }; + 3CB8E2A60E2CE856003F3104 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = InfoPlist.strings; sourceTree = ""; }; + 3CC5434C07E2315800C271A9 /* Emacs.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Emacs.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 3CDCED330902E99700B2EF7E /* config.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = config.h; path = ../../src/config.h; sourceTree = ""; }; + 3CDCED550902EA8100B2EF7E /* term.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = term.c; path = ../../src/term.c; sourceTree = ""; }; + 3CDCED560902EA8100B2EF7E /* sysdep.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = sysdep.c; path = ../../src/sysdep.c; sourceTree = ""; }; + 3CDCED570902EA8100B2EF7E /* syntax.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = syntax.c; path = ../../src/syntax.c; sourceTree = ""; }; + 3CDCED590902EA8100B2EF7E /* strftime.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = strftime.c; path = ../../src/strftime.c; sourceTree = ""; }; + 3CDCED5A0902EA8100B2EF7E /* sound.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = sound.c; path = ../../src/sound.c; sourceTree = ""; }; + 3CDCED5C0902EA8100B2EF7E /* search.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = search.c; path = ../../src/search.c; sourceTree = ""; }; + 3CDCED5D0902EA8100B2EF7E /* scroll.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = scroll.c; path = ../../src/scroll.c; sourceTree = ""; }; + 3CDCED5E0902EA8100B2EF7E /* region-cache.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = "region-cache.c"; path = "../../src/region-cache.c"; sourceTree = ""; }; + 3CDCED5F0902EA8100B2EF7E /* regex.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = regex.c; path = ../../src/regex.c; sourceTree = ""; }; + 3CDCED610902EA8100B2EF7E /* process.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = process.c; path = ../../src/process.c; sourceTree = ""; }; + 3CDCED620902EA8100B2EF7E /* print.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = print.c; path = ../../src/print.c; sourceTree = ""; }; + 3CDCED640902EA8100B2EF7E /* pre-crt0.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = "pre-crt0.c"; path = "../../src/pre-crt0.c"; sourceTree = ""; }; + 3CDCED670902EA8100B2EF7E /* minibuf.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = minibuf.c; path = ../../src/minibuf.c; sourceTree = ""; }; + 3CDCED680902EA8100B2EF7E /* md5.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = md5.c; path = ../../src/md5.c; sourceTree = ""; }; + 3CDCED690902EA8100B2EF7E /* marker.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = marker.c; path = ../../src/marker.c; sourceTree = ""; }; + 3CDCED6D0902EA8100B2EF7E /* macros.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = macros.c; path = ../../src/macros.c; sourceTree = ""; }; + 3CDCED710902EA8100B2EF7E /* lread.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = lread.c; path = ../../src/lread.c; sourceTree = ""; }; + 3CDCED720902EA8100B2EF7E /* lastfile.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = lastfile.c; path = ../../src/lastfile.c; sourceTree = ""; }; + 3CDCED730902EA8100B2EF7E /* keymap.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = keymap.c; path = ../../src/keymap.c; sourceTree = ""; }; + 3CDCED740902EA8200B2EF7E /* keyboard.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = keyboard.c; path = ../../src/keyboard.c; sourceTree = ""; }; + 3CDCED750902EA8200B2EF7E /* intervals.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = intervals.c; path = ../../src/intervals.c; sourceTree = ""; }; + 3CDCED760902EA8200B2EF7E /* insdel.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = insdel.c; path = ../../src/insdel.c; sourceTree = ""; }; + 3CDCED770902EA8200B2EF7E /* indent.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = indent.c; path = ../../src/indent.c; sourceTree = ""; }; + 3CDCED780902EA8200B2EF7E /* image.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = image.c; path = ../../src/image.c; sourceTree = ""; }; + 3CDCED7A0902EA8200B2EF7E /* cmds.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = cmds.c; path = ../../src/cmds.c; sourceTree = ""; }; + 3CDCED7B0902EA8200B2EF7E /* category.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = category.c; path = ../../src/category.c; sourceTree = ""; }; + 3CDCED7C0902EA8200B2EF7E /* coding.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = coding.c; path = ../../src/coding.c; sourceTree = ""; }; + 3CDCED830902EA8200B2EF7E /* unexmacosx.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = unexmacosx.c; path = ../../src/unexmacosx.c; sourceTree = ""; }; + 3CDCED8B0902EA8200B2EF7E /* buffer.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = buffer.c; path = ../../src/buffer.c; sourceTree = ""; }; + 3CDCED8C0902EA8200B2EF7E /* character.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = character.c; path = ../../src/character.c; sourceTree = ""; }; + 3CDCED920902EA8200B2EF7E /* undo.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = undo.c; path = ../../src/undo.c; sourceTree = ""; }; + 3CDCED940902EA8200B2EF7E /* textprop.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = textprop.c; path = ../../src/textprop.c; sourceTree = ""; }; + 3CDCED950902EA8200B2EF7E /* terminfo.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = terminfo.c; path = ../../src/terminfo.c; sourceTree = ""; }; + 3CDCED9C0902EA8200B2EF7E /* xfaces.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = xfaces.c; path = ../../src/xfaces.c; sourceTree = ""; }; + 3CDCED9D0902EA8200B2EF7E /* xdisp.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = xdisp.c; path = ../../src/xdisp.c; sourceTree = ""; }; + 3CDCED9E0902EA8200B2EF7E /* window.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = window.c; path = ../../src/window.c; sourceTree = ""; }; + 3CDCEDB00902EA8200B2EF7E /* doprnt.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = doprnt.c; path = ../../src/doprnt.c; sourceTree = ""; }; + 3CDCEDB10902EA8200B2EF7E /* doc.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = doc.c; path = ../../src/doc.c; sourceTree = ""; }; + 3CDCEDB20902EA8200B2EF7E /* dired.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = dired.c; path = ../../src/dired.c; sourceTree = ""; }; + 3CDCEDB30902EA8200B2EF7E /* data.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = data.c; path = ../../src/data.c; sourceTree = ""; }; + 3CDCEDB40902EA8200B2EF7E /* callint.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = callint.c; path = ../../src/callint.c; sourceTree = ""; }; + 3CDCEDB60902EA8200B2EF7E /* ccl.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = ccl.c; path = ../../src/ccl.c; sourceTree = ""; }; + 3CDCEDB70902EA8200B2EF7E /* fontset.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = fontset.c; path = ../../src/fontset.c; sourceTree = ""; }; + 3CDCEDB80902EA8200B2EF7E /* fns.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = fns.c; path = ../../src/fns.c; sourceTree = ""; }; + 3CDCEDB90902EA8200B2EF7E /* floatfns.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = floatfns.c; path = ../../src/floatfns.c; sourceTree = ""; }; + 3CDCEDBB0902EA8200B2EF7E /* filemode.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = filemode.c; path = ../../src/filemode.c; sourceTree = ""; }; + 3CDCEDBC0902EA8200B2EF7E /* filelock.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = filelock.c; path = ../../src/filelock.c; sourceTree = ""; }; + 3CDCEDBD0902EA8200B2EF7E /* emacs.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = emacs.c; path = ../../src/emacs.c; sourceTree = ""; }; + 3CDCEDBE0902EA8200B2EF7E /* editfns.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = editfns.c; path = ../../src/editfns.c; sourceTree = ""; }; + 3CDCEDBF0902EA8200B2EF7E /* fileio.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = fileio.c; path = ../../src/fileio.c; sourceTree = ""; }; + 3CDCEDC00902EA8200B2EF7E /* eval.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = eval.c; path = ../../src/eval.c; sourceTree = ""; }; + 3CDCEDC10902EA8200B2EF7E /* casetab.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = casetab.c; path = ../../src/casetab.c; sourceTree = ""; }; + 3CDCEDC20902EA8200B2EF7E /* composite.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = composite.c; path = ../../src/composite.c; sourceTree = ""; }; + 3CDCEDC30902EA8200B2EF7E /* dispnew.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = dispnew.c; path = ../../src/dispnew.c; sourceTree = ""; }; + 3CDCEDC40902EA8200B2EF7E /* charset.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = charset.c; path = ../../src/charset.c; sourceTree = ""; }; + 3CDCEDC50902EA8200B2EF7E /* alloc.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = alloc.c; path = ../../src/alloc.c; sourceTree = ""; }; + 3CDCEDC60902EA8200B2EF7E /* bytecode.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = bytecode.c; path = ../../src/bytecode.c; sourceTree = ""; }; + 3CDCEDC70902EA8200B2EF7E /* callproc.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = callproc.c; path = ../../src/callproc.c; sourceTree = ""; }; + 3CDCEDC80902EA8200B2EF7E /* cm.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = cm.c; path = ../../src/cm.c; sourceTree = ""; }; + 3CDCEDC90902EA8200B2EF7E /* casefiddle.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = casefiddle.c; path = ../../src/casefiddle.c; sourceTree = ""; }; + 3CDCEDCA0902EA8200B2EF7E /* fringe.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = fringe.c; path = ../../src/fringe.c; sourceTree = ""; }; + 3CDCEDCB0902EA8200B2EF7E /* frame.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = frame.c; path = ../../src/frame.c; sourceTree = ""; }; + 3CDCEDCC0902EA8200B2EF7E /* chartab.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = chartab.c; path = ../../src/chartab.c; sourceTree = ""; }; + 3CDCEDCD0902EA8200B2EF7E /* atimer.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = atimer.c; path = ../../src/atimer.c; sourceTree = ""; }; + 3CFDFC3A08E79A6800B05918 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /Developer/SDKs/MacOSX10.3.9.sdk/System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 3CC5434707E2315800C271A9 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 3CFDFC3B08E79A6800B05918 /* AppKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = { + isa = PBXGroup; + children = ( + 3CFDFC3A08E79A6800B05918 /* AppKit.framework */, + ); + name = "Linked Frameworks"; + sourceTree = ""; + }; + 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + 19C28FACFE9D520D11CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 3CC5434C07E2315800C271A9 /* Emacs.app */, + ); + name = Products; + sourceTree = ""; + }; + 289FC26B00C69A287F000001 /* NeXTStep */ = { + isa = PBXGroup; + children = ( + 3C4D6D710DE50D5D00B20D4E /* nsfont.m */, + 3C15C1A70902D97100A8542F /* nsimage.m */, + 3C15C04F0902D89500A8542F /* nsgui.h */, + 3C7F3C3A07EB3B05003C8A4D /* nsterm.h */, + 090AF67E00C61DCD7F000001 /* nsfns.m */, + 090AF68000C61DCD7F000001 /* nsmenu.m */, + 090AF68100C61DCD7F000001 /* nsselect.m */, + 090AF68300C61DCD7F000001 /* nsterm.m */, + ); + name = NeXTStep; + sourceTree = ""; + }; + 29B97314FDCFA39411CA2CEA /* Emacs */ = { + isa = PBXGroup; + children = ( + 289FC26B00C69A287F000001 /* NeXTStep */, + 3C15C23E0902E6B000A8542F /* emacs-hdr */, + 3CDCED4D0902EA6800B2EF7E /* emacs-src */, + 29B97317FDCFA39411CA2CEA /* Resources */, + 29B97323FDCFA39411CA2CEA /* Frameworks */, + 19C28FACFE9D520D11CA2CBB /* Products */, + ); + name = Emacs; + sourceTree = ""; + }; + 29B97317FDCFA39411CA2CEA /* Resources */ = { + isa = PBXGroup; + children = ( + 3CB8E2A40E2CE856003F3104 /* English.lproj */, + 3CB8E29F0E2CE7F5003F3104 /* Credits.html */, + 3CB8E2990E2CE6BF003F3104 /* preferences.nib */, + 739637F200C4DF3C7F000001 /* Images */, + ); + name = Resources; + sourceTree = ""; + }; + 29B97323FDCFA39411CA2CEA /* Frameworks */ = { + isa = PBXGroup; + children = ( + 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */, + 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */, + ); + name = Frameworks; + sourceTree = ""; + }; + 3C15C23E0902E6B000A8542F /* emacs-hdr */ = { + isa = PBXGroup; + children = ( + 3C4D6D670DE50D2300B20D4E /* font.h */, + 3C15C0DB0902D89500A8542F /* acldef.h */, + 3C15C0E60902D89500A8542F /* atimer.h */, + 3C15C0E70902D89500A8542F /* blockinput.h */, + 3C15C0780902D89500A8542F /* buffer.h */, + 3C15C0760902D89500A8542F /* category.h */, + 3C15C0C50902D89500A8542F /* ccl.h */, + 3C15C0DE0902D89500A8542F /* character.h */, + 3C15C0C80902D89500A8542F /* charset.h */, + 3C15C0E20902D89500A8542F /* chpdef.h */, + 3C15C0890902D89500A8542F /* cm.h */, + 3CDCED330902E99700B2EF7E /* config.h */, + 3C15C0770902D89500A8542F /* coding.h */, + 3C15C0D70902D89500A8542F /* commands.h */, + 3C15C0C70902D89500A8542F /* composite.h */, + 3C15C0D90902D89500A8542F /* dispextern.h */, + 3C15C0BF0902D89500A8542F /* disptab.h */, + 3C15C0C20902D89500A8542F /* epaths.h */, + 3C15C0C90902D89500A8542F /* fontset.h */, + 3C15C0E40902D89500A8542F /* frame.h */, + 3C15C0B80902D89500A8542F /* getpagesize.h */, + 3C15C0B60902D89500A8542F /* gnu.h */, + 3C15C06E0902D89500A8542F /* indent.h */, + 3C15C06B0902D89500A8542F /* intervals.h */, + 3C15C0660902D89500A8542F /* keymap.h */, + 3C15C0680902D89500A8542F /* keyboard.h */, + 3C15C05D0902D89500A8542F /* macros.h */, + 3C15C0560902D89500A8542F /* md5.h */, + 3C15C0550902D89500A8542F /* mem-limits.h */, + 3C15C0500902D89500A8542F /* ndir.h */, + 3C15C04D0902D89500A8542F /* param.h */, + 3C15C04C0902D89500A8542F /* point.h */, + 3C15C0470902D89500A8542F /* process.h */, + 3C15C0460902D89500A8542F /* puresize.h */, + 3C15C0430902D89500A8542F /* regex.h */, + 3C15C0410902D89500A8542F /* region-cache.h */, + 3C15C0390902D89500A8542F /* syntax.h */, + 3C15C0370902D89500A8542F /* sysselect.h */, + 3C15C0330902D89500A8542F /* syswait.h */, + 3C15C0360902D89500A8542F /* syssignal.h */, + 3C15C0350902D89500A8542F /* systime.h */, + 3C15C0340902D89500A8542F /* systty.h */, + 3C15C0300902D89500A8542F /* termchar.h */, + 3C15C02F0902D89500A8542F /* termhooks.h */, + 3C15C0950902D89500A8542F /* termopts.h */, + 3C15C0920902D89500A8542F /* uaf.h */, + 3C15C0790902D89500A8542F /* vlimit.h */, + 3C15C0A00902D89500A8542F /* window.h */, + ); + name = "emacs-hdr"; + sourceTree = ""; + }; + 3CB8E2A40E2CE856003F3104 /* English.lproj */ = { + isa = PBXGroup; + children = ( + 3CB8E2A50E2CE856003F3104 /* InfoPlist.strings */, + ); + name = English.lproj; + path = Emacs.base/Contents/Resources/English.lproj; + sourceTree = ""; + }; + 3CDCED4D0902EA6800B2EF7E /* emacs-src */ = { + isa = PBXGroup; + children = ( + 3C4D6D660DE50D2300B20D4E /* font.c */, + 3C4D6D680DE50D2300B20D4E /* termcap.c */, + 3C4D6D690DE50D2300B20D4E /* terminal.c */, + 3C4D6D6A0DE50D2300B20D4E /* tparam.c */, + 3CDCED550902EA8100B2EF7E /* term.c */, + 3CDCED560902EA8100B2EF7E /* sysdep.c */, + 3CDCED570902EA8100B2EF7E /* syntax.c */, + 3CDCED590902EA8100B2EF7E /* strftime.c */, + 3CDCED5A0902EA8100B2EF7E /* sound.c */, + 3CDCED5C0902EA8100B2EF7E /* search.c */, + 3CDCED5D0902EA8100B2EF7E /* scroll.c */, + 3CDCED5E0902EA8100B2EF7E /* region-cache.c */, + 3CDCED5F0902EA8100B2EF7E /* regex.c */, + 3CDCED610902EA8100B2EF7E /* process.c */, + 3CDCED620902EA8100B2EF7E /* print.c */, + 3CDCED640902EA8100B2EF7E /* pre-crt0.c */, + 3CDCED670902EA8100B2EF7E /* minibuf.c */, + 3CDCED680902EA8100B2EF7E /* md5.c */, + 3CDCED690902EA8100B2EF7E /* marker.c */, + 3CDCED6D0902EA8100B2EF7E /* macros.c */, + 3CDCED710902EA8100B2EF7E /* lread.c */, + 3CDCED720902EA8100B2EF7E /* lastfile.c */, + 3CDCED730902EA8100B2EF7E /* keymap.c */, + 3CDCED740902EA8200B2EF7E /* keyboard.c */, + 3CDCED750902EA8200B2EF7E /* intervals.c */, + 3CDCED760902EA8200B2EF7E /* insdel.c */, + 3CDCED770902EA8200B2EF7E /* indent.c */, + 3CDCED780902EA8200B2EF7E /* image.c */, + 3CDCED7A0902EA8200B2EF7E /* cmds.c */, + 3CDCED7B0902EA8200B2EF7E /* category.c */, + 3CDCED7C0902EA8200B2EF7E /* coding.c */, + 3CDCED830902EA8200B2EF7E /* unexmacosx.c */, + 3CDCED8B0902EA8200B2EF7E /* buffer.c */, + 3CDCED8C0902EA8200B2EF7E /* character.c */, + 3CDCED920902EA8200B2EF7E /* undo.c */, + 3CDCED940902EA8200B2EF7E /* textprop.c */, + 3CDCED950902EA8200B2EF7E /* terminfo.c */, + 3CDCED9C0902EA8200B2EF7E /* xfaces.c */, + 3CDCED9D0902EA8200B2EF7E /* xdisp.c */, + 3CDCED9E0902EA8200B2EF7E /* window.c */, + 3CDCEDB00902EA8200B2EF7E /* doprnt.c */, + 3CDCEDB10902EA8200B2EF7E /* doc.c */, + 3CDCEDB20902EA8200B2EF7E /* dired.c */, + 3CDCEDB30902EA8200B2EF7E /* data.c */, + 3CDCEDB40902EA8200B2EF7E /* callint.c */, + 3CDCEDB60902EA8200B2EF7E /* ccl.c */, + 3CDCEDB70902EA8200B2EF7E /* fontset.c */, + 3CDCEDB80902EA8200B2EF7E /* fns.c */, + 3CDCEDB90902EA8200B2EF7E /* floatfns.c */, + 3CDCEDBB0902EA8200B2EF7E /* filemode.c */, + 3CDCEDBC0902EA8200B2EF7E /* filelock.c */, + 3CDCEDBD0902EA8200B2EF7E /* emacs.c */, + 3CDCEDBE0902EA8200B2EF7E /* editfns.c */, + 3CDCEDBF0902EA8200B2EF7E /* fileio.c */, + 3CDCEDC00902EA8200B2EF7E /* eval.c */, + 3CDCEDC10902EA8200B2EF7E /* casetab.c */, + 3CDCEDC20902EA8200B2EF7E /* composite.c */, + 3CDCEDC30902EA8200B2EF7E /* dispnew.c */, + 3CDCEDC40902EA8200B2EF7E /* charset.c */, + 3CDCEDC50902EA8200B2EF7E /* alloc.c */, + 3CDCEDC60902EA8200B2EF7E /* bytecode.c */, + 3CDCEDC70902EA8200B2EF7E /* callproc.c */, + 3CDCEDC80902EA8200B2EF7E /* cm.c */, + 3CDCEDC90902EA8200B2EF7E /* casefiddle.c */, + 3CDCEDCA0902EA8200B2EF7E /* fringe.c */, + 3CDCEDCB0902EA8200B2EF7E /* frame.c */, + 3CDCEDCC0902EA8200B2EF7E /* chartab.c */, + 3CDCEDCD0902EA8200B2EF7E /* atimer.c */, + ); + name = "emacs-src"; + sourceTree = ""; + }; + 739637F200C4DF3C7F000001 /* Images */ = { + isa = PBXGroup; + children = ( + 3CB8E29D0E2CE73A003F3104 /* Emacs.icns */, + ); + name = Images; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 3CC542FF07E2315800C271A9 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 3C7F3C3B07EB3B05003C8A4D /* nsterm.h in Headers */, + 3C15C0EB0902D89500A8542F /* termhooks.h in Headers */, + 3C15C0EC0902D89500A8542F /* termchar.h in Headers */, + 3C15C0EF0902D89500A8542F /* syswait.h in Headers */, + 3C15C0F00902D89500A8542F /* systty.h in Headers */, + 3C15C0F10902D89500A8542F /* systime.h in Headers */, + 3C15C0F20902D89500A8542F /* syssignal.h in Headers */, + 3C15C0F30902D89500A8542F /* sysselect.h in Headers */, + 3C15C0F50902D89500A8542F /* syntax.h in Headers */, + 3C15C0FD0902D89500A8542F /* region-cache.h in Headers */, + 3C15C0FF0902D89500A8542F /* regex.h in Headers */, + 3C15C1020902D89500A8542F /* puresize.h in Headers */, + 3C15C1030902D89500A8542F /* process.h in Headers */, + 3C15C1080902D89500A8542F /* point.h in Headers */, + 3C15C1090902D89500A8542F /* param.h in Headers */, + 3C15C10B0902D89500A8542F /* nsgui.h in Headers */, + 3C15C10C0902D89500A8542F /* ndir.h in Headers */, + 3C15C1110902D89500A8542F /* mem-limits.h in Headers */, + 3C15C1120902D89500A8542F /* md5.h in Headers */, + 3C15C1190902D89500A8542F /* macros.h in Headers */, + 3C15C1220902D89500A8542F /* keymap.h in Headers */, + 3C15C1240902D89500A8542F /* keyboard.h in Headers */, + 3C15C1270902D89500A8542F /* intervals.h in Headers */, + 3C15C12A0902D89500A8542F /* indent.h in Headers */, + 3C15C1320902D89500A8542F /* category.h in Headers */, + 3C15C1330902D89500A8542F /* coding.h in Headers */, + 3C15C1340902D89500A8542F /* buffer.h in Headers */, + 3C15C1350902D89500A8542F /* vlimit.h in Headers */, + 3C15C1450902D89500A8542F /* cm.h in Headers */, + 3C15C14E0902D89500A8542F /* uaf.h in Headers */, + 3C15C1510902D89500A8542F /* termopts.h in Headers */, + 3C15C15C0902D89500A8542F /* window.h in Headers */, + 3C15C1720902D89500A8542F /* gnu.h in Headers */, + 3C15C1740902D89500A8542F /* getpagesize.h in Headers */, + 3C15C17B0902D89500A8542F /* disptab.h in Headers */, + 3C15C17E0902D89500A8542F /* epaths.h in Headers */, + 3C15C1810902D89500A8542F /* ccl.h in Headers */, + 3C15C1830902D89500A8542F /* composite.h in Headers */, + 3C15C1840902D89500A8542F /* charset.h in Headers */, + 3C15C1850902D89500A8542F /* fontset.h in Headers */, + 3C15C1930902D89500A8542F /* commands.h in Headers */, + 3C15C1950902D89500A8542F /* dispextern.h in Headers */, + 3C15C1970902D89500A8542F /* acldef.h in Headers */, + 3C15C19A0902D89500A8542F /* character.h in Headers */, + 3C15C19E0902D89500A8542F /* chpdef.h in Headers */, + 3C15C1A00902D89500A8542F /* frame.h in Headers */, + 3C15C1A20902D89500A8542F /* atimer.h in Headers */, + 3C15C1A30902D89500A8542F /* blockinput.h in Headers */, + 3CDCED340902E99700B2EF7E /* config.h in Headers */, + 3C4D6D6C0DE50D2300B20D4E /* font.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 3CC542FE07E2315800C271A9 /* Emacs */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3CA115970C825A540007AFC2 /* Build configuration list for PBXNativeTarget "Emacs" */; + buildPhases = ( + 3CC542FF07E2315800C271A9 /* Headers */, + 3CC5430007E2315800C271A9 /* Resources */, + 3CC5430407E2315800C271A9 /* Sources */, + 3CC5434707E2315800C271A9 /* Frameworks */, + 3CC5434907E2315800C271A9 /* Rez */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Emacs; + productInstallPath = "$(HOME)/Applications"; + productName = Emacs; + productReference = 3CC5434C07E2315800C271A9 /* Emacs.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 29B97313FDCFA39411CA2CEA /* Project object */ = { + isa = PBXProject; + buildConfigurationList = 3CA1159B0C825A540007AFC2 /* Build configuration list for PBXProject "Emacs" */; + compatibilityVersion = "Xcode 2.4"; + hasScannedForEncodings = 1; + mainGroup = 29B97314FDCFA39411CA2CEA /* Emacs */; + projectDirPath = ""; + projectRoot = ../..; + targets = ( + 3CC542FE07E2315800C271A9 /* Emacs */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 3CC5430007E2315800C271A9 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3CB8E29A0E2CE6BF003F3104 /* preferences.nib in Resources */, + 3CB8E29E0E2CE73A003F3104 /* Emacs.icns in Resources */, + 3CB8E2A00E2CE7F5003F3104 /* Credits.html in Resources */, + 3CB8E2A70E2CE856003F3104 /* InfoPlist.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXRezBuildPhase section */ + 3CC5434907E2315800C271A9 /* Rez */ = { + isa = PBXRezBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXRezBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 3CC5430407E2315800C271A9 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3CC5430607E2315800C271A9 /* nsfns.m in Sources */, + 3CC5430707E2315800C271A9 /* nsmenu.m in Sources */, + 3CC5430807E2315800C271A9 /* nsselect.m in Sources */, + 3CC5430907E2315800C271A9 /* nsterm.m in Sources */, + 3C15C1A80902D97100A8542F /* nsimage.m in Sources */, + 3CDCEDD00902EA8200B2EF7E /* term.c in Sources */, + 3CDCEDD10902EA8200B2EF7E /* sysdep.c in Sources */, + 3CDCEDD20902EA8200B2EF7E /* syntax.c in Sources */, + 3CDCEDD40902EA8200B2EF7E /* strftime.c in Sources */, + 3CDCEDD50902EA8200B2EF7E /* sound.c in Sources */, + 3CDCEDD70902EA8200B2EF7E /* search.c in Sources */, + 3CDCEDD80902EA8200B2EF7E /* scroll.c in Sources */, + 3CDCEDD90902EA8200B2EF7E /* region-cache.c in Sources */, + 3CDCEDDA0902EA8200B2EF7E /* regex.c in Sources */, + 3CDCEDDC0902EA8200B2EF7E /* process.c in Sources */, + 3CDCEDDD0902EA8200B2EF7E /* print.c in Sources */, + 3CDCEDDF0902EA8200B2EF7E /* pre-crt0.c in Sources */, + 3CDCEDE20902EA8200B2EF7E /* minibuf.c in Sources */, + 3CDCEDE30902EA8200B2EF7E /* md5.c in Sources */, + 3CDCEDE40902EA8200B2EF7E /* marker.c in Sources */, + 3CDCEDE80902EA8200B2EF7E /* macros.c in Sources */, + 3CDCEDEC0902EA8200B2EF7E /* lread.c in Sources */, + 3CDCEDED0902EA8200B2EF7E /* lastfile.c in Sources */, + 3CDCEDEE0902EA8200B2EF7E /* keymap.c in Sources */, + 3CDCEDEF0902EA8200B2EF7E /* keyboard.c in Sources */, + 3CDCEDF00902EA8200B2EF7E /* intervals.c in Sources */, + 3CDCEDF10902EA8200B2EF7E /* insdel.c in Sources */, + 3CDCEDF20902EA8200B2EF7E /* indent.c in Sources */, + 3CDCEDF30902EA8200B2EF7E /* image.c in Sources */, + 3CDCEDF50902EA8200B2EF7E /* cmds.c in Sources */, + 3CDCEDF60902EA8200B2EF7E /* category.c in Sources */, + 3CDCEDF70902EA8200B2EF7E /* coding.c in Sources */, + 3CDCEDFE0902EA8200B2EF7E /* unexmacosx.c in Sources */, + 3CDCEE060902EA8200B2EF7E /* buffer.c in Sources */, + 3CDCEE070902EA8200B2EF7E /* character.c in Sources */, + 3CDCEE0D0902EA8200B2EF7E /* undo.c in Sources */, + 3CDCEE0F0902EA8200B2EF7E /* textprop.c in Sources */, + 3CDCEE100902EA8200B2EF7E /* terminfo.c in Sources */, + 3CDCEE170902EA8200B2EF7E /* xfaces.c in Sources */, + 3CDCEE180902EA8200B2EF7E /* xdisp.c in Sources */, + 3CDCEE190902EA8200B2EF7E /* window.c in Sources */, + 3CDCEE2B0902EA8200B2EF7E /* doprnt.c in Sources */, + 3CDCEE2C0902EA8200B2EF7E /* doc.c in Sources */, + 3CDCEE2D0902EA8200B2EF7E /* dired.c in Sources */, + 3CDCEE2E0902EA8200B2EF7E /* data.c in Sources */, + 3CDCEE2F0902EA8200B2EF7E /* callint.c in Sources */, + 3CDCEE310902EA8200B2EF7E /* ccl.c in Sources */, + 3CDCEE320902EA8200B2EF7E /* fontset.c in Sources */, + 3CDCEE330902EA8200B2EF7E /* fns.c in Sources */, + 3CDCEE340902EA8200B2EF7E /* floatfns.c in Sources */, + 3CDCEE360902EA8200B2EF7E /* filemode.c in Sources */, + 3CDCEE370902EA8200B2EF7E /* filelock.c in Sources */, + 3CDCEE380902EA8200B2EF7E /* emacs.c in Sources */, + 3CDCEE390902EA8200B2EF7E /* editfns.c in Sources */, + 3CDCEE3A0902EA8200B2EF7E /* fileio.c in Sources */, + 3CDCEE3B0902EA8200B2EF7E /* eval.c in Sources */, + 3CDCEE3C0902EA8200B2EF7E /* casetab.c in Sources */, + 3CDCEE3D0902EA8200B2EF7E /* composite.c in Sources */, + 3CDCEE3E0902EA8200B2EF7E /* dispnew.c in Sources */, + 3CDCEE3F0902EA8200B2EF7E /* charset.c in Sources */, + 3CDCEE400902EA8200B2EF7E /* alloc.c in Sources */, + 3CDCEE410902EA8200B2EF7E /* bytecode.c in Sources */, + 3CDCEE420902EA8200B2EF7E /* callproc.c in Sources */, + 3CDCEE430902EA8200B2EF7E /* cm.c in Sources */, + 3CDCEE440902EA8200B2EF7E /* casefiddle.c in Sources */, + 3CDCEE450902EA8200B2EF7E /* fringe.c in Sources */, + 3CDCEE460902EA8200B2EF7E /* frame.c in Sources */, + 3CDCEE470902EA8200B2EF7E /* chartab.c in Sources */, + 3CDCEE480902EA8200B2EF7E /* atimer.c in Sources */, + 3C4D6D6B0DE50D2300B20D4E /* font.c in Sources */, + 3C4D6D6D0DE50D2300B20D4E /* termcap.c in Sources */, + 3C4D6D6E0DE50D2300B20D4E /* terminal.c in Sources */, + 3C4D6D6F0DE50D2300B20D4E /* tparam.c in Sources */, + 3C4D6D730DE50D5D00B20D4E /* nsfont.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 3CB8E2A50E2CE856003F3104 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 3CB8E2A60E2CE856003F3104 /* English */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 3CA115980C825A540007AFC2 /* Development */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = "\"$(SYSTEM_DEVELOPER_DIR)/SDKs/MacOSX10.3.0.sdk/System/Library/Frameworks\""; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_OPTIMIZATION_LEVEL = 1; + GCC_PREPROCESSOR_DEFINITIONS = ( + COCOA, + HAVE_CONFIG_H, + emacs, + ); + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(HOME)/Applications"; + LIBRARY_SEARCH_PATHS = ""; + MACOSX_DEPLOYMENT_TARGET = 10.3; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = "-lncurses"; + PRODUCT_NAME = Emacs; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ""; + WRAPPER_EXTENSION = app; + ZERO_LINK = NO; + }; + name = Development; + }; + 3CA115990C825A540007AFC2 /* Deployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + FRAMEWORK_SEARCH_PATHS = "\"$(SYSTEM_DEVELOPER_DIR)/SDKs/MacOSX10.3.0.sdk/System/Library/Frameworks\""; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_PREPROCESSOR_DEFINITIONS = ( + COCOA, + HAVE_CONFIG_H, + emacs, + ); + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(HOME)/Applications"; + LIBRARY_SEARCH_PATHS = ""; + MACOSX_DEPLOYMENT_TARGET = 10.3; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = "-lncurses"; + PRODUCT_NAME = Emacs; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ""; + WRAPPER_EXTENSION = app; + ZERO_LINK = NO; + }; + name = Deployment; + }; + 3CA1159A0C825A540007AFC2 /* Default */ = { + isa = XCBuildConfiguration; + buildSettings = { + FRAMEWORK_SEARCH_PATHS = "\"$(SYSTEM_DEVELOPER_DIR)/SDKs/MacOSX10.3.0.sdk/System/Library/Frameworks\""; + GCC_PREPROCESSOR_DEFINITIONS = ""; + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = Info.plist; + INSTALL_PATH = "$(HOME)/Applications"; + LIBRARY_SEARCH_PATHS = ""; + MACOSX_DEPLOYMENT_TARGET = 10.3; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + PRODUCT_NAME = Emacs; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = ""; + WRAPPER_EXTENSION = app; + }; + name = Default; + }; + 3CA1159C0C825A540007AFC2 /* Development */ = { + isa = XCBuildConfiguration; + buildSettings = { + MACOSX_DEPLOYMENT_TARGET = 10.3; + SDKROOT = /Developer/SDKs/MacOSX10.3.0.sdk; + }; + name = Development; + }; + 3CA1159D0C825A540007AFC2 /* Deployment */ = { + isa = XCBuildConfiguration; + buildSettings = { + MACOSX_DEPLOYMENT_TARGET = 10.3; + SDKROOT = /Developer/SDKs/MacOSX10.3.0.sdk; + }; + name = Deployment; + }; + 3CA1159E0C825A540007AFC2 /* Default */ = { + isa = XCBuildConfiguration; + buildSettings = { + MACOSX_DEPLOYMENT_TARGET = 10.3; + SDKROOT = /Developer/SDKs/MacOSX10.3.0.sdk; + }; + name = Default; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 3CA115970C825A540007AFC2 /* Build configuration list for PBXNativeTarget "Emacs" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3CA115980C825A540007AFC2 /* Development */, + 3CA115990C825A540007AFC2 /* Deployment */, + 3CA1159A0C825A540007AFC2 /* Default */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Default; + }; + 3CA1159B0C825A540007AFC2 /* Build configuration list for PBXProject "Emacs" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3CA1159C0C825A540007AFC2 /* Development */, + 3CA1159D0C825A540007AFC2 /* Deployment */, + 3CA1159E0C825A540007AFC2 /* Default */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Default; + }; +/* End XCConfigurationList section */ + }; + rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; +} diff -r ff312a846b25 -r d45acf0c8d23 nextstep/FOR-RELEASE --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nextstep/FOR-RELEASE Tue Jul 15 18:15:18 2008 +0000 @@ -0,0 +1,216 @@ +-*- outline -*- + +* NON-SPECIFIC + +** Remove Feval calls relating to insert working text in isearch mode. + +** free_frame_resources, face colors + +** look at nsfont_char_width and nsfont_string_width utils (Dan C.) + +** config improvements (Dan C.) + +* Mac-related: + +** open file:/// URLs + +** finish handle terminate request (user logout) + +** put frame autopositioning into C code somewhere -- if loc = same, offset + +** automap ctrl-mouse-1 to mouse-3 + +** deal with Finder aliases somehow + +** Ctrl-F2 won't pull up menus + + +* Cursor: + +** ns_cursor_blink_rate: when set in preferences, somehow save the option (but + calling custom-save-all from this causes error) + +** cursor nonerase on certain Leopard and Tiger installations + +** if I do: (mouse-avoidance-mode 'banish) and then minimize Emacs, it pops back immediately. + Also, it insists on being on top of other windows if they overlap. + +** cursor-over bugs w/some scripts (move around in HELLO to see) + + +Keyboard: + +On a German (PowerBook?) keyboard alt-` produces the correct ˚, without alt modifier only the message “ is undefined” is produced. Peter Maurer’s Key codes shows: + * Modifier Change: ⇧ 131330/0x20102 + * Key Down/Up event: ⇧ 24/0x18 +[note, this is += key on German KB setting on US keyboard] +[unable to reproduce w/German KB setting -- need German laptop?] + +** numeric keysetting bug + + +* Other: + +** better recog of unicode scripts / Greek / composition + +** Ctrl-g not picked up in all situations get --experimental-ctrl-g in 'compile' working better + +** Exec-dump not working on GNUstep (so slow startup). + +** occasional size too large for screen errors + +** undo for color-drag face customization + + + + +--------- +* DONE + +Try font-backend mechanism (see font.h). + +Auto font substitution? + +ns-option-modifier (alias for ns-alternate-modifier) + +ns-control-modifier, ns-function-modifier (new) + +- Frame bugs: + - create frame on second monitor fails (due to frame-parameters). + +toolbar bugs + +fix cursor disappears on italic text bug + +fix scrollbar erase on Ctrl-l bug + +Menubar emacs-21 compatibility. Make this and command-is-meta + switchable at startup. Switch mouse handling to 3-button compatible. + +mouse button normalization + + +[rc1 released] + + +shift-alt-h does produce Ó (according C-h k), but this glyph is not +always shown completely, it seems to depend on the font used + +[width estimation still off; this character is 211 = 0xD3] + +Another attempt at composite rendering. + +shift-alt-6 does not produce ^ (dead key) but &. +[adding alt continues to pick up the '&' interpretation, but in other + apps this suddenly changes it to a dead key] + +- italic in Courier is still cut off + +- dead keys end isearch w/o allowing typing +[need to insert to minibuffer if that is active] + +When using the Dvorak with Qwerty keyboard shortcuts keyboard layout +(hereon in referred to as Dvorak-Qwerty), keyboard shortcuts +erroneously use the Dvorak layout. e.g. The Qwerty H key becomes D in +Dvorak, but with Dvorak-Qwerty the same key should be used when +hitting Cmd-H to hide an application. In Emacs.app with a +Dvorak-Qwerty layout I must hit Cmd-J (Qwerty J becomes H in Dvorak) +to hide the app. + +- menus + +- consolidate FRAME_INTERNAL_BORDER extension hacks + +- mouse-1 activation problems (buttons, etc.): check keyboard.c HAVE_NS sections + +- clean up bg fill code in font->draw(), and change conditions on when called with bg=yes + +- clean up / optimize the metrics caching -- consider reducing memory load + +- non-encapsulated build + +- test color-drag face customization (accuracy and saving) + +- look at ns-mark-nav replacement + +- gnustep + +- documentation: + - "stipple" images, alpha, color-drag, etc. + - make sure everyone finds it + + +[rc2 released] + +- recheck font width determination for variable-width non-wide fonts + +- resize-drag + +- colored bitmaps (use NSCalibratedRGBColorspace for the bitmap and + add a method setBitmapForegroundColor:color to twiddle the bits + +- resize title printing bug + + +[rc2a released] + +- naming: cursor "line" -> "bar", "bar" -> underscore + +- incorporate Pete's locallisp patch + +- document needed sudo for compile --shared-lisp + + +[patch 20071010_rc2a released] + +- clean up ns-menu-bar.el and try folding into ns-win.el + +- fix jaggedy startup screen w/black bkgrd + +- Pete's fringe weirdness + +- iconification: use shrunk image for non-finder types + +- toolbar updating + + +[patch 20071015_rc2a released] + +- multi-TTY merge + +- terminal mode weird colors (real fix) + +- Frame bugs: + - a full-height frame will be shrunk on defocus, focus + [actually must be over-height, but it's a little overzealous in the + shrinking; probably happens in x_set_window_size] + - adding toolbar on full-height frame requires resize to avoid scrambling + +- Buffers menu brokenness + +- inability to use ARGB colors problem + +- cut buffer in TTY + + +[rc3 released] + +- drop MULTI_KBOARD + +- mic-paren removal (also see http://www.emacswiki.org/cgi-bin/wiki/mic-paren.el) + +- describe-key problem + +- drop need for preload advice (print-buffer workaround) + +- new frame placement ignores parameters [cannot replicate] + +- white text on background alpha + +- Multi-TTY: switching input between tty and GUI frames still needs work. + Once ns_select() and ns_read_socket() are being called, the regular terminal + input route seems ineffective. Furthermore NSApp activate events are not + picked up when attempting to read in terminal mode. + (Tests: make-frame-on-tty /dev/ttyp#, make-frame-on-display) + +- remove ns-yes-or-no-p, try again to improve looks of regular dialog in nsmenu.m diff -r ff312a846b25 -r d45acf0c8d23 nextstep/GNUstep/Emacs.base/Resources/Emacs.desktop --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nextstep/GNUstep/Emacs.base/Resources/Emacs.desktop Tue Jul 15 18:15:18 2008 +0000 @@ -0,0 +1,11 @@ +[Desktop Entry] +Encoding=UTF-8 +Type=Application +Version=9.0 +Categories=GNUstep +Name=Emacs +Comment=GNU Emacs for NeXT/Open/GNUstep and OS X +Icon=emacs.tiff +Exec=openapp Emacs.app +#TryExec=Emacs.app +FilePattern=Emacs.app;Emacs diff -r ff312a846b25 -r d45acf0c8d23 nextstep/GNUstep/Emacs.base/Resources/Info-gnustep.plist --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nextstep/GNUstep/Emacs.base/Resources/Info-gnustep.plist Tue Jul 15 18:15:18 2008 +0000 @@ -0,0 +1,137 @@ +{ + "!" = "Generated by ProjectCenter, do not edit"; + ApplicationDescription = "GNU Emacs for GNUstep / OS X"; + ApplicationIcon = emacs.tiff; + ApplicationName = Emacs; + ApplicationRelease = "9.0"; + Authors = ( + "Adrian Robert (GNUstep)", + "Christophe de Dinechin (MacOS X)", + "Scott Bender (OpenStep)", + "Christian Limpach (NeXTStep)", + "Carl Edman (NeXTStep)", + "..see http://emacs-app.sf.net" + ); + Copyright = "Copyright (C) 2005-2008"; + CopyrightDescription = "Released under the GNU General Public License Version 2"; + FullVersionID = "Emacs 23.0.60 NS 9.0"; + NSExecutable = Emacs; + NSIcon = emacs.tiff; + NSPrincipalClass = NSApplication; + NSRole = Application; + NSTypes = ( + { + NSDocumentClass = ""; + NSHumanReadableName = ""; + NSIcon = ""; + NSName = ""; + NSRole = ""; + NSUnixExtensions = ( + txt + ); + }, + { + NSDocumentClass = ""; + NSHumanReadableName = ""; + NSIcon = ""; + NSName = ""; + NSRole = ""; + NSUnixExtensions = ( + c, + h + ); + }, + { + NSDocumentClass = ""; + NSHumanReadableName = ""; + NSIcon = ""; + NSName = ""; + NSRole = ""; + NSUnixExtensions = ( + m + ); + }, + { + NSDocumentClass = ""; + NSHumanReadableName = ""; + NSIcon = ""; + NSName = ""; + NSRole = ""; + NSUnixExtensions = ( + C, + cpp, + H, + cc + ); + }, + { + NSDocumentClass = ""; + NSHumanReadableName = ""; + NSIcon = ""; + NSName = ""; + NSRole = ""; + NSUnixExtensions = ( + java + ); + }, + { + NSDocumentClass = ""; + NSHumanReadableName = ""; + NSIcon = ""; + NSName = ""; + NSRole = ""; + NSUnixExtensions = ( + el + ); + }, + { + NSDocumentClass = ""; + NSHumanReadableName = ""; + NSIcon = ""; + NSName = ""; + NSRole = ""; + NSUnixExtensions = ( + * + ); + } + ); + NSServices = ( + { + NSPortName = Emacs; + NSMessage = requestService; + NSUserData = open-selection + NSSendTypes = (NSStringPboardType); + NSMenuItem = { + default = "Emacs.app/New Buffer Containing Selection"; + }; + }, + { + NSPortName = Emacs; + NSMessage = requestService; + NSUserData = open-file + NSSendTypes = (NSStringPboardType); + NSMenuItem = { + default = "Emacs.app/Open Selected File"; + }; + }, + { + NSPortName = Emacs; + NSMessage = requestService; + NSUserData = mail-selection + NSSendTypes = (NSStringPboardType); + NSMenuItem = { + default = "Emacs.app/Email Selection"; + }; + }, + { + NSPortName = Emacs; + NSMessage = requestService; + NSUserData = mail-to + NSSendTypes = (NSStringPboardType); + NSMenuItem = { + default = "Emacs.app/Send Email to Selected Address"; + }; + }, + ); + URL = "http://emacs-app.sf.net"; +} \ No newline at end of file diff -r ff312a846b25 -r d45acf0c8d23 nextstep/GNUstep/Emacs.base/Resources/emacs.tiff Binary file nextstep/GNUstep/Emacs.base/Resources/emacs.tiff has changed diff -r ff312a846b25 -r d45acf0c8d23 nextstep/GNUstep/Emacs.base/Resources/preferences.gorm/data.classes --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nextstep/GNUstep/Emacs.base/Resources/preferences.gorm/data.classes Tue Jul 15 18:15:18 2008 +0000 @@ -0,0 +1,31 @@ +{ + "## Comment" = "Do NOT change this file, Gorm maintains it"; + EmacsPrefsController = { + Actions = ( + "cancel:", + "setDefaultFont:", + "ok:", + "resetToDefaults:", + "runHelp:", + "setColors:" + ); + Outlets = ( + alternateModMenu, + cursorBlinkSlider, + cursorTypeMatrix, + prefsWindow, + expandSpaceSlider, + commandModMenu + ); + Super = NSObject; + }; + FirstResponder = { + Actions = ( + "setDefaultFont:", + "resetToDefaults:", + "runHelp:", + "setColors:" + ); + Super = NSObject; + }; +} \ No newline at end of file diff -r ff312a846b25 -r d45acf0c8d23 nextstep/GNUstep/Emacs.base/Resources/preferences.gorm/data.info Binary file nextstep/GNUstep/Emacs.base/Resources/preferences.gorm/data.info has changed diff -r ff312a846b25 -r d45acf0c8d23 nextstep/GNUstep/Emacs.base/Resources/preferences.gorm/objects.gorm Binary file nextstep/GNUstep/Emacs.base/Resources/preferences.gorm/objects.gorm has changed diff -r ff312a846b25 -r d45acf0c8d23 nextstep/README.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nextstep/README.txt Tue Jul 15 18:15:18 2008 +0000 @@ -0,0 +1,321 @@ + +Emacs.app +========= + +This file introduces the NeXTstep-based port of GNU Emacs, known as Emacs.app, + which runs on on many POSIX systems and possibly W32 using the GNUstep + libraries and on MacOS X systems using the Cocoa libraries. The directory + "nextstep" and its subdirectories "Cocoa" and "GNUstep" contain files + relevant to building and running on these systems. + +Those primarily responsible for the port (in chronological order) were: + +Michael Brouwer +Carl Edman +Christian Limpach +Scott Bender +Christophe de Dinechin +Adrian Robert + +See AUTHORS file and "Release History" below for more information. + +GNU Emacs is due to Richard Stallman and company. + +The GNUstep port was made possible through the assistance of Adam Fedor, Fred +Kiefer, M. Uli Klusterer, Alexander Malmberg, Jonas Matton, and Riccardo +Mottola. + +Peter Dyballa assisted in a variety of ways to improve text rendering and +keyboard handling. Adam Ratcliffe documented the Preferences panel. David +M. Cooke contributed fixes to XPM handling. Carsten Bormann helped get dired +working for non-ASCII filenames. + + +Requirements +------------ +MacOS X 10.3 or later +- or - +GNUstep "Startup 0.13" or later +Tested on linux, should work on other systems, perhaps with minor build +tweaking. + + +Compilation +----------- + +Run "./compile" in this directory, which will create a self-contained +Emacs.app under 'build/'. This can be moved anywhere and run. To create a +shared-lisp build, do "sudo ./compile -shared ". Set + to where the lisp will go, for example /usr/local to end up +with /usr/local/shared/emacs/... + +See the script itself for further details, and customizations. + +You can rerun configure and/or run 'make' manually in the top-level or src +directories to refresh nextstep/build/Emacs.app. (Or edit the "compile" +script.) + +On OS X you can also open Cocoa/Emacs.xcodeproj and build it again there. (Note, +ZeroLink currently does not work with Emacs owing to the use of private_extern +in the code as well as some other, unidentifiable problem.) Before doing this +you must run 'compile' once as outlined above, to set up the lisp resources. + +On GNUstep, you CAN'T use ProjectCenter, since PC cannot work with files +outside of its project directory. + + +Usage +----- + +Please use the first entry under the help menu within Emacs.app, do +"M-x info-ns-emacs". + + +Background +---------- + +Internally to emacs, the port and its code are referred to using the term +"NeXTstep", despite the fact that no system or API has been released under +this name in more than 10 years. Here's some background on why.. + +NeXT, Inc. introduced the NeXTstep API with its computer and operating system +in the late 1980's. Later on in collaboration with Sun, this API was +published as a specification called OpenStep. The GNUstep project started in +the early 1990's to provide a free implementation of this API. Later on, +Apple bought NeXT (some would say "NeXT bought Apple") and made OpenStep the +basis of OS X, calling the API "Cocoa". Since then, Cocoa has evolved beyond +the OpenStep specification, and GNUstep has followed it. + +Thus, calling this port "OpenStep" is not technically accurate, and in the +absence of any other determinant, we are using the term "NeXTstep", both +because it signifies the original inspiration that created these APIs, and +because all of the classes and functions still begin with the letters "NS". + +(See http://en.wikipedia.org/wiki/Nextstep) + +This Emacs port was first released in the early 1990's on the NeXT computer, +and was successively updated to OpenStep, Rhapsody, OS X, and then finally +GNUstep, tracking GNU emacs core releases in the meantime. + + +Files specific to the port +-------------------------- + +src/nsfns.m +src/nsfont.m +src/nsgui.h +src/nsimage.m +src/nsmenu.m +src/nsselect.m +src/nsterm.h +src/nsterm.m +lisp/ns-grabenv.el +lisp/ns-carbon-compat.el +lisp/term/ns-win.el +lib-src/mac-fix-env.m +doc/emacs/ns-emacs.texi +etc/Emacs.clr +nextstep/ + + +Files modified for port: + +many -- look for HAVE_NS / NS_IMPL_... #ifdefs + + +Release History +--------------- + +1990-1992 1.0-3.0 (?) Michael Brouwer's socket/terminal communication + based version (GUI ran as a separate process.) + +1993/10/25 3.0.1 Last (?) release of Brouwer version. Supports + NeXTstep 3.x and below. + +1994/04/24 4.0 Carl Edman's version using direct API following + the X-Windows port. NeXTstep 3.x only. + +1995/06/15 4.1 Second (and last) Carl Edman release, based on + Emacs 19.28. + +1996/07/28 4.2 First Christian Limpach release, based on + Emacs 19.29. + +?? 5.0 ?? + +1997/12/?? 6.0b1 Ported to OpenStep by Scott Bender. Updated + to Emacs 20.2. + +?? 6.0b2 (?) Scott Bender: ported to Rhapsody. + +1999/05/?? 6.0b3 Scott Bender: "OS X Server", Emacs 20.3. + +2001/06/25 7.0 Ported to MacOS X (10.1) by Christophe de + Dinechin. Release based on Emacs 20.7. Hosting + moved to SourceForge. + +2002/01/03 7.0.1 Bug fixes. + +2002/08/27 7.0.2 Jaguar (OS X 10.2) support. Added an autoconf + option for sys_nerr being in stdio. Added + libncurses to the build libraries. Fixed a + problem with ns-alternate-is-meta. Changed the + icon color to blue, since Jaguar is yellow. + +2004/10/07 8.0-pre1 Ported to GNUstep by Adrian Robert. + +2004/11/04 8.0-pre2 Restored functionality on OS X (menu code + cleanup). Improved scrollbar handling and + paste from other applications. File icons + obtained properly from NSWorkspace. Dropped + Gorm and Nib files. Background refresh bug + fixed (in GNUstep). Various small fixes and + code cleanups. Now starts up under Art. + +2005/01/27 8.0-pre3 Bold and italic faces supported. Cursor and + mouse highlighting rendering bugs + fixed. Drag/drop and cut/paste interaction + w/external apps fixed. File load/save panels + available. Stability and rendering speed + improvements. Some ObjC and VC mode bugs fixed. + +2005/02/27 8.0-rc1 Dynamic path detection at startup so Emacs.app + can be moved anywhere. Added binary packages + and simplified source installation to running + two scripts. Thorough cleanup of menu code; + now fully functional. Fixed all detected + memory leaks. Minor frame focus and title + bugs fixed. + +2005/03/30 8.0-rc2 "Configure" info directory now uses dynamic + path setting, so info files can go under .app. + Improved select() handling and PTY fixes so + shell mode and tramp run smoothly. + Significant rendering optimizations under + GNUstep, and now works under Art backend. + Non-Latin text rendering works (but not + fontsets), and LEIM is bundled. UTF8 is used + for clipboard interaction. + Arrow cursor now used on scrollbar. + objc-mode and tramp now bundled in site-lisp. + +2005/05/30 8.0-rc3 Fixed bug with parsing of "easymenu" menus. + Many problems with modes such as SLIME, MatLab, + and Planner go away. Improved scrollbar + handling and rendering speed. Color panel + and other bug fixes. mac-fix-env utility. + Font handling improvements (OS X 10.3, 10.4): + - heed 'GSFontAntiAlias' default + - heed system antialiasing threshold + - added 'UseQuickdrawSmoothing' default to + invoke less heavy antialiasing + +2005/07/05 8.0-rc4 Added a Preferences panel. Cleaned up + rendering for synthetic italic fonts. Further + improved menu parsing. Use system highlight + color. Added previous- and next-mark history + navigation commmands bound to M-p,M-n. + Miscellaneous bug fixes. + +2005/08/04 8.0-rc5 All internal string handling changed to UTF-8. + This means menu items, color and color list + names, and a few other things will now display + properly. It does NOT mean UTF-8 filenames + are displayed correctly in the minibuffer. + Also relating to UTF-8, contents of files + using this coding can now be displayed (though + not auto-recognized; add extensions to your + default coding alist). Limited mac-roman + support was also added (also sans recognition). + Certain characters are not displayed properly + due to a translation problem. (UTF-8 based on + work by Otfried Cheong; mac-roman from + emacs-21.) Partial support for "dead-key" + handling now added. Transparency (e.g., M-x + set-background-color ARGB88FFFFFF) improved: + only the background is made transparent. + Cursor drawing glitches fixed. Preferences + handling improved. Fixed some portability + problems on Tiger and Puma. + +2005/09/12 8.0 Bundled ispell on OS X. Minor bug fixes and + stability improvements. Compiles under gcc-4. + +2005/09/26 8.0.1 Correct clipped rendering for synthetic + italics. Include the info directory. + Fix grabenv. Bundle whitespace package. + +2005/10/27 8.0.2 Correct rendering for wide characters during + cursor movement. Fix bungled hack in ispell + bundling. + +2005/11/05 9.0-pre1 Updated to latest Emacs CVS code on unicode-2 + branch (proposed to be released 2006/2007 as + Emacs 23). + +2005/11/11 9.0-pre2 Fix crashes for deiconifying and loading + certain images. Improve vertical font metrics + (fixes inaccurate page up/down, window size, + and partial lines). Support better remapping + of Alt/Opt and remapping of Command. More + insistent defaulting of scrollbar to right. + Modest improvements to build process. + +2006/04/22 9.0-pre2a Stopgap interim release to sync w/latest + unicode-2 CVS. Includes XPM and partial + toolbar support. + +2006/06/08 9.0-pre3 Major upgrade to keyboard handling: + system-selected compositional input methods + should now work, as well as more keys / + keyboards. XPM, toolbar, and tooltip support. + Some improvements to scrollbars, zoom, italic + rendering, pasting, Color panel. Added function + ns-set-background-alpha to work around + inability to customize with numeric colors. + +2006/12/24 9.0-rc1 Reworked font handling and text rendering to + use Kenichi Handa's new font back-end system. + Font sets are now supported and automatically + created when a font is selected. Added recent + X11 colors to Emacs.clr (remove + ~/Library/Colors/Emacs.clr to pick up). Added + ns-option-modifier, ns-control-modifier, + ns-function-modifier customization variables. + Update menus to Emacs 21+ conventions. Right + mouse button now generates mouse-3 events. + Various bug fixes and rendering improvements. + +2007/09/10 9.0-rc2 Improve menubar, popup menu, and scrollbar + behavior, let accented char entry work in + isearch, follow system keymap for shortcut + keys, fix border and box drawing, remove + glitches in modeline drawing, support + overstrike for unavailable bold fonts, fix XPM + related crasher bugs. Incremental font + metrics caching and other performance + improvements. Shared-lisp builds now possible. + +2007/09/20 9.0-rc2a Interim release. New features: composed + character display, colored fringe bitmaps, + colored relief drawing, dynamic resizing, + Bug fixes: popup menu position and selection, + font width calculation, face color adaptation + to background, submenu keyboard navigation. + NOT TESTED ON GNUSTEP. + +2007/11/19 9.0-rc3 Integrated the multi-TTY functionality from + emacs core (however, mixed TTY and GUI + sessions are not working yet). Support 10.5. + Give site-lisp load precedence over lisp and + add a compile option to prefer an additional + directory, use miniaturized miniwindow images + in some cases, rename cursor types for + consistency w/other emacs terms, improved font + selection for symbol scripts. + Bug fixes: fringe and bitmap, frame deletion, + resizing, cursor blink, workspace open-file, + image backgrounds, toolbar item enablement, + context menu positioning. + +2008/07/15 (none) Merge to GNU Emacs CVS trunk. diff -r ff312a846b25 -r d45acf0c8d23 nextstep/compile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nextstep/compile Tue Jul 15 18:15:18 2008 +0000 @@ -0,0 +1,223 @@ +#!/bin/sh + +# This script configures and builds Emacs to the subdirectory ./build . +# +# If --shared-lisp 'install_prefix' is given, lisp files will be installed to +# install_prefix/share/emacs/23.0.0. This option must be run with 'sudo'. +# +# Otherwise (default) lisp will be installed under Emacs.app/Contents/Resources. +# It does this by configuring it to install there, and running "make install". +# +# Some setup is different for GNUstep vs. Cocoa, and it determines which one +# it's on using 'uname'. + +# After it is run, Emacs can be run directly from the .app, which itself +# can be placed anywhere. + +# Further C development can be done using Xcode on OS X (not tested recently), +# or by typing './remake' in the '../src' directory. Further Lisp +# development can be done by either copying the files you modify +# into install location, or running this script again. + + +# Set up path and config variables. + +PREFIX="" +while [ $# -gt 0 ]; do + case "$1" in + --shared-lisp=*) + PREFIX=`echo "$1" | sed s/--shared-lisp=//` + shift + ;; + --enable-local-lisp-path=*) + locallisppath=`echo "$1" | sed s/--enable-local-lisp-path=//` + shift + ;; + *) + echo "Usage: $0 [--shared-lisp='install_root' --enable-local-lisp-path='some path(s)']" + exit + esac +done + +DISTDIR=`pwd`/.. + +#OPTFLAGS='-g -O2' +OPTFLAGS='-g' + +# MAC OS X +if [ `uname` == "Darwin" ]; then + BASEDIR=`pwd`/build/Emacs.app/Contents + BINDIR=${BASEDIR}/MacOS + if [ "x$PREFIX" == "x" ]; then + PREFIX=${BASEDIR}/Resources + fi +# If you want to try experimental enhanced Ctrl-g support, add to NS_CFG_OPTS: +# --enable-cocoa-experimental-ctrl-g +# (See bottom of USAGE.txt) + NS_CFG_OPTS="--with-ns --without-x --without-freetype --prefix=${PREFIX} --exec_prefix=${BASEDIR}/MacOS --libexecdir=${BASEDIR}/MacOS/libexec" +# --enable-cocoa-experimental-ctrl-g" +# MAKE="make -j3" + steve=`/usr/sbin/sysctl hw.ncpu | awk '{print $NF}'` + MAKE="make -j`expr $steve + 1`" + export CC=gcc-4.0 + export MACOSX_DEPLOYMENT_TARGET=10.3 + export MACOSX_DEPLOYMENT_TARGET_ppc=10.3 + export MACOSX_DEPLOYMENT_TARGET_i386=10.4 + export CFLAGS="$OPTFLAGS -arch ppc -arch i386" +# -universal -sdk /Developer/SDKs/MacOSX10.4u.sdk +# -arch ppc -arch i386 -isysroot /Developer/SDKs/MacOSX10.4u.sdk + +# GNUSTEP +else + + # Currently must pass three dirs into Make process via environment variables. + source /etc/GNUstep/GNUstep.conf + if [ "x$GNUSTEP_MAKEFILES" == "x" ]; then + if [ "x$GNUSTEP_SYSTEM_ROOT" == "x" ]; then + echo "Failed to obtain any useful information from /etc/GNUstep/GNUstep.conf." + echo "Please make sure GNUstep is installed on your system." + exit + fi + GNUSTEP_MAKEFILES=${GNUSTEP_SYSTEM_ROOT}/Library/Makefiles + GNUSTEP_SYSTEM_HEADERS=${GNUSTEP_SYSTEM_ROOT}/Library/Headers + GNUSTEP_SYSTEM_LIBRARIES=${GNUSTEP_SYSTEM_ROOT}/Library/Libraries + fi + export GNUSTEP_MAKEFILES + export GNUSTEP_SYSTEM_HEADERS + export GNUSTEP_SYSTEM_LIBRARIES + + BASEDIR=`pwd`/build/Emacs.app + BINDIR=${BASEDIR} + if [ "x${PREFIX}" == "x" ]; then + PREFIX=${BASEDIR}/Resources + fi + NS_CFG_OPTS="--with-ns --without-x --without-freetype --prefix=${PREFIX} --exec-prefix=${BASEDIR} --libexecdir=${BASEDIR}/libexec" +# --enable-cocoa-experimental-ctrl-g + + if [ "x$MAKE" == "x" ]; then + if [ "`gmake 2>&1`" == "gmake: *** No targets specified and no makefile found. Stop." ]; then + MAKE=gmake + else + MAKE=make + fi + export MAKE + CFLAGS="$OPTFLAGS" + export CFLAGS + fi + +# PENDING: Not sure why this is needed + export EMACSLOADPATH="${DISTDIR}/lisp:${DISTDIR}/lisp/emacs-lisp:${DISTDIR}/leim" +fi + +# End variable setup. +############################################################################### + +# Prepare a clean slate +rm -fr build/Emacs.app + +# Configure if needed +cd .. +if [ ! -f Makefile ]; then + echo "./configure ${NS_CFG_OPTS}" +./configure < locallisppath.sed + cat epaths.h-orig | sed -f locallisppath.sed > epaths.h + rm locallisppath.sed + fi) +fi + +# Clean up to avoid DOC-xxx and emacs-xxx out-of-controlness +rm -f ../etc/DOC-* ../src/emacs-* + + +# Go (installs binaries to ./build/Emacs.app, lisp to there or PREFIX) +echo "make install" +$MAKE +status=$? + +if [ -f src/epaths.h-orig ]; then + mv src/epaths.h-orig src/epaths.h +fi + +if [ $status != 0 ]; then + echo "*** Compilation failed. ***" + echo "Please examine the above output to determine what went wrong," + echo "edit the configure options in this script (\'compile\') to fix it, and rerun." +# rm -f leim/changed.misc leim/changed.tit + exit 1 +fi + +$MAKE install +if [ $? != 0 ]; then + echo "*** Compilation succeeded, but .app assembly failed. ***" + echo "Please examine the above output to determine what went wrong," + echo "edit the configure options in this script (\'compile\') to fix it, and rerun." +# rm -f leim/changed.misc leim/changed.tit + exit 1 +fi + +# Move version stuff up to Resources +cd ${BASEDIR}/Resources +if [ -d share/emacs ]; then + # clean up self-contained build + mv -f share/emacs/*/* . +fi + +if [ ! -d info ]; then + # happens on GNUstep, not OS X + mv -f share/info . +fi +rm -fr share + +# Get rid of .el.gz when .elc is present.. purists will complain, but this +# knocks the app size down substantially. +cd lisp +#for f in `find . -name '*.elc' -print | sed -e s/.elc/.{el,el.gz}/` +#do +# rm -f $f +#done + +# Bin cleanup +cd $BINDIR/bin +rm -f emacs emacs-23* + +# Move libexec stuff up, and link it from bin +cd ../libexec +mv -f emacs/*/*/* . +rm -fr emacs +cd ../bin +ln -sf ../libexec/* . + +# On OS X, install the bundled ispell +#if [ `uname` == "Darwin" ]; then +# cd $DISTDIR +# cp ispell-3.3.01/bin/ispell* ${BINDIR}/libexec +# cp -R ispell-3.3.01/lib ${BINDIR}/libexec +#fi + +echo "" +echo "Build successful." +echo "" diff -r ff312a846b25 -r d45acf0c8d23 src/ChangeLog --- a/src/ChangeLog Tue Jul 15 15:45:05 2008 +0000 +++ b/src/ChangeLog Tue Jul 15 18:15:18 2008 +0000 @@ -1,3 +1,134 @@ +2008-07-15 Adrian Robert + + Changes and additions for NeXTstep windowing system (Cocoa and + GNUstep) support. + + * Makefile.in + * config.in: Support defines and build commands for NS port. + * blockinput.h (BLOCK_INPUT, UNBLOCK_INPUT, TOTALLY_UNBLOCK_INPUT) + (UNBLOCK_INPUT_TO): Don't use under NS unless EXPERIMENTAL_CONTROL_G. + * callproc.c (set_initial_environment): Initialize + Vprocess_environment under CANNOT_DUMP (fixes crash when + batch-compiling for bootstrap, due to Chris Hall). + * dispextern.h: Include nsgui.h and add needed typedefs under NS + windowing. + (struct face): Add synth_ital field. + * dispnew.c: Include nsterm.h when compiling under NS windowing. + (init_display): Initialize Vinitial_window_system to "ns" when so + compiled. + * emacs.c: Include GSConfig.h when compiling under GNUstep. + (display_arg): Use under NS. + (main): Under NS, allocate autorelease pool and handle command line + args. Move syms_of_xmenu() call under #ifdef HAVE_X_WINDOWS. + (standard_args): Add NS-specific args. + (shut_down_emacs): Shut down NS terminal if compiled under NS. + * font.c (DEFAULT_ENCODING): New variable. + (font_find_for_lface): Use it. + (syms_of_font): Load syms_of_nsfont under NS. + * font.h: Declare nsfont_driver when compiled under NS. + * fontset.c: When compiling under NS, include nsterm.h. + (fontset_from_font): Autoconstruct fontset under NS. + * frame.c (various): Under NS, include nsterm.h, add Qns window system + symbol, document and use it. + (make_initial_frame): Call init_frame_faces(f) in CANNOT_DUMP case -- + patch to fix crash due to different init order, due to Chris Hall and + Yamamoto Mitsuharu. + (do_switch_frame): When for_deletion under Cocoa, add + Fraise_frame(Qnil). + (x_set_frame_parameters): Ensure font attribute changes are picked up. + (x_get_arg): Allow "yes" and "no" as boolean values. + (syms_of_frame): Declare Qns. Init Vdefault_frame_scroll_bars to + Qright under Cocoa. + (focus-follows-mouse): Default to 0 under NS. + * frame.h (enum output_method): Add output_ns. + (external_tool_bar, external_menu_bar, FRAME_EXTERNAL_TOOLBAR) + (FRAME_EXTERNAL_MENU_BAR): Use under NS. + (FRAME_WINDOW_P): NS-specific definition. + * fringe.c (max_used_fringe_bitmap): Make public. + * getloadavg.c (mach/mach.h): Include it under NeXT descendant OS's. + (getloadavg): Use NeXT code under descendant OS's. + * image.c (includes and header section, x_create_bitmap_from_data) + (x_create_bitmap_from_file, free_bitmap_record, image_background) + (image_background_transparent, x_clear_image_1) + (x_create_x_image_and_pixmap, x_destroy_x_image, x_put_x_image) + (Create_Pixmap_From_Bitmap_Data, xpm_load_image, lookup_rgb_color) + (x_to_xcolors, x_from_xcolors, x_disable_image) + (x_build_heuristic_mask, syms_of_image): Add NS support parallel to + other GUIs, including XPM support using code originally written for + Carbon GUI. + (png_load, jpeg_load, tiff_load, gif_load): Added implementations + using NS API. + (image_ascent): Use font metrics macros instead of direct struct field + access. + * keyboard.c (includes): Add nsterm.h when compiling under NS. + (kbd_buffer_get_event): Handle NS as other GUI windowing systems. + Also, handle NS as GTK for menu bar purposes. + (make_lispy_event): Handle NS as other GUI windowing systems, and as X + toolkit where they differ. + (parse_menu_item): Prefer keybindings using 'super' modifier. Also, + use cachelist, still needed under NS. + * keyboard.h (ENCODE_MENU_STRING, XtPointer, Boolean): Handle as + NTGUI. + (struct widget_value): Define it here for menu.c. + * keymap.c (includes): Include modifier internals. + (lisp_to_mod, modifier_sequence_p): New functions, compiled only under + NS. + (where_is_internal, Fwhere_is_internal): When compiled under NS, add + support for preferring sequences using certain modifiers, specified by + the FIRSTONLY argument. + * lisp.h (hash_remove): Rename to avoid name clash when compiling + under NS GNUstep implementation. + (USE_LSB_TAG): Use it under Cocoa when compiling under NS. + * lread.c (init_lread): Treat NS as HAVE_CARBON for turn_off_warning. + * menu.c: Include nsterm.h under NS. + (single_menu_item, parse_single_submenu, xmalloc_widget_value) + (free_menubar_widget_tree_value, update_submenu_strings) + (find_and_call_menu_selection): Treat NS as X and NT. + (find_and_return_menu_selection): New function, used for popup menus. + * nsgui.h + * nsterm.h + * nsfns.m + * nsimage.m + * nsmenu.m + * nsselect.m + * nsterm.m: New files. + * process.c (wait_reading_process_output): Under NS, call ns_select() + instead of plain select(). + * syntax.c (char_quoted): Under NS, avoid a crash when called near + beginning of buffer. + * sysselect.h (init_process): Rename when compiling under Cocoa to + avoid name conflict. + * termhooks.h (display_info): Add ns_display_info to union. + * terminal.c (Fterminal_live_p): Add ns to terminal types. + * terminfo.c (UP, BC, PC): Don't declare when compiling under NS in + COCOA environment. + * unexnext.c: Update to work with mach API on Mac OS X, and to use new + unexec() signature. (Note, this will dump, but the resulting file + crashes; unexosx is used instead; keeping around for reference and + possible aid in getting dump working under GNUstep.) + * w32gui.h (button_type, widget_value): Remove definitions (now in + keyboard.h). + * window.c: Include nsterm.h when compiling under NS. + * xdisp.c (includes): Include nsterm.h when compiling under NS. + (set_frame_menubar, update_menu_bar, display_menu_bar): Handle NS as + other GUI windowing systems. + (update_tool_bar, redisplay_tool_bar, redisplay_window): Handle NS as + GTK. + (x_consider_frame_title): Under NS, set icon type and frame + modified-state indicator; use ns_set_name_as_filename() when using + formatted title. + (update_window_cursor): Make public when compiling under NS. + (display_hourglass_p, syms_of_xdisp, hourglass_shown_p) + (hourglass_atimer, Vhourglass_delay + * xfaces.c (header section, init_frame_faces, clear_font_table) + (defined_color, unload_color, x_face_list_fonts) + (prepare_face_for_display): Add NS support parallel to other GUIs) + (emulate GCs like other non-X GUIs. + (split_font_name): Don't lowercase font name under NS. + (merge_face_ref, Finternal_set_lisp_face_attribute): Support stippling + under NS. + * s/darwin.h: Add support for compilation under NS. + 2008-07-15 Jason Rumney * w32fns.c (Fx_create_frame): Remove duplicate unwind_protect. diff -r ff312a846b25 -r d45acf0c8d23 src/Makefile.in --- a/src/Makefile.in Tue Jul 15 15:45:05 2008 +0000 +++ b/src/Makefile.in Tue Jul 15 18:15:18 2008 +0000 @@ -112,6 +112,11 @@ #endif #endif +/* Under GNUstep, putting libc on the link line causes problems. */ +#ifdef GNUSTEP +#define LIB_STANDARD +#endif + /* Unless inhibited or changed, use -lg to link for debugging. */ #ifndef LIBS_DEBUG #define LIBS_DEBUG -lg @@ -229,6 +234,15 @@ #endif /* not ORDINARY_LINK */ +#ifdef GNUSTEP +/* Pull in stuff from GNUstep-make. */ +FOUNDATION_LIB=gnu +GUI_LIB=gnu +include $(GNUSTEP_MAKEFILES)/Additional/base.make +include $(GNUSTEP_MAKEFILES)/Additional/gui.make +shared=no +#endif + #ifdef HAVE_DBUS DBUS_CFLAGS = @DBUS_CFLAGS@ DBUS_LIBS = @DBUS_LIBS@ @@ -249,8 +263,11 @@ /* 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 $(MYCPPFLAGS) -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_SOUND} ${RSVG_CFLAGS} ${DBUS_CFLAGS} ${CFLAGS} @FREETYPE_CFLAGS@ @FONTCONFIG_CFLAGS@ @LIBOTF_CFLAGS@ @M17N_FLT_CFLAGS@ +.SUFFIXES: .m .c.o: $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $< +.m.o: + $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) GNU_OBJC_CFLAGS $< #ifndef LIBX11_SYSTEM #define LIBX11_SYSTEM @@ -260,13 +277,8 @@ #define LIB_X11_LIB -lX11 #endif -/* xmenu.c should not be compiled on OSX. */ -#ifndef HAVE_CARBON +#ifdef HAVE_X_WINDOWS XMENU_OBJ = xmenu.o -#endif - -#ifdef HAVE_X_WINDOWS - XOBJ= xterm.o xfns.o xselect.o xrdb.o fontset.o xsmfns.o fringe.o image.o #ifdef HAVE_MENUS @@ -518,6 +530,21 @@ emacsappsrc = ${srcdir}/../mac/Emacs.app/ #endif +#ifdef HAVE_NS +/* Object files for NeXTstep */ +NS_OBJ= nsterm.o nsfns.o nsmenu.o nsselect.o nsimage.o nsfont.o \ + fontset.o fringe.o image.o +emacsapp = $(PWD)/../nextstep/build/Emacs.app/ +FONT_DRIVERS = nsfont.o +#ifdef GNUSTEP +emacsappsrc = ${srcdir}/../nextstep/GNUstep/Emacs.base +emacsbindir = $(emacsapp) +#else +emacsappsrc = ${srcdir}/../nextstep/Cocoa/Emacs.base +emacsbindir = $(emacsapp)/Contents/MacOS/ +#endif /* GNUSTEP */ +#endif /* HAVE_NS */ + #ifdef HAVE_WINDOW_SYSTEM #ifdef HAVE_X_WINDOWS #if defined (HAVE_XFT) @@ -545,7 +572,7 @@ 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) $(MAC_OBJ) $(CYGWIN_OBJ) $(FONT_DRIVERS) + $(MSDOS_OBJ) $(MAC_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_DRIVERS) /* Object files used on some machine or other. These go in the DOC file on all machines @@ -553,6 +580,7 @@ SOME_MACHINE_OBJECTS = dosfns.o msdos.o \ xterm.o xfns.o xmenu.o xselect.o xrdb.o xsmfns.o fringe.o image.o \ mac.o macterm.o macfns.o macmenu.o macselect.o fontset.o \ + nsterm.o nsfns.o nsmenu.o nsselect.o nsimage.o \ w32.o w32console.o w32fns.o w32heap.o w32inevt.o \ w32menu.o w32proc.o w32reg.o w32select.o w32term.o w32xfns.o $(FONT_DRIVERS) @@ -876,6 +904,7 @@ Note that SunOS needs -lm to come before -lc; otherwise, you get duplicated symbols. If the standard libraries were compiled with GCC, we might need gnulib again after them. */ + LIBES = $(LOADLIBES) $(LIBS) $(LIBX) $(LIBSOUND) $(RSVG_LIBS) $(DBUS_LIBS) \ LIBGPM LIBRESOLV LIBS_SYSTEM LIBS_MACHINE LIBS_TERMCAP \ LIBS_DEBUG $(GETLOADAVG_LIBS) \ @@ -910,7 +939,10 @@ @: bootstrap-emacs, so let us replace it. -ln -f emacs${EXEEXT} bootstrap-emacs${EXEEXT} #endif /* ! defined (CANNOT_DUMP) */ +/* XXX: not working under NS currently due to path shenanigans.. */ +#ifndef HAVE_NS -./emacs -q -batch -f list-load-path-shadows +#endif /* We run make-docfile twice because the command line may get too long on some systems. */ @@ -935,9 +967,13 @@ temacs${EXEEXT}: $(LOCALCPP) $(STARTFILES) stamp-oldxmenu ${obj} ${otherobj} OBJECTS_MACHINE prefix-args${EXEEXT} echo "${obj} ${otherobj} " OBJECTS_MACHINE > buildobj.lst +#ifdef GNUSTEP + $(CC) -rdynamic YMF_PASS_LDFLAGS (${TEMACS_LDFLAGS}) -o temacs ${obj} ${otherobj} OBJECTS_MACHINE ${LIBES} +#else $(LD) YMF_PASS_LDFLAGS (${STARTFLAGS} ${TEMACS_LDFLAGS}) $(LDFLAGS) \ -o temacs ${STARTFILES} ${obj} ${otherobj} \ OBJECTS_MACHINE ${LIBES} +#endif /* We do not use ALL_LDFLAGS because LD_SWITCH_SYSTEM and LD_SWITCH_MACHINE often contain options that have to do with using Emacs''s crt0, @@ -1080,7 +1116,7 @@ getloadavg.o: getloadavg.c $(config_h) image.o: image.c frame.h window.h dispextern.h blockinput.h atimer.h \ systime.h xterm.h w32term.h w32gui.h macterm.h macgui.h font.h \ - $(config_h) + nsterm.h nsgui.h $(config_h) indent.o: indent.c frame.h window.h indent.h buffer.h $(config_h) termchar.h \ termopts.h disptab.h region-cache.h character.h category.h composite.h \ dispextern.h keyboard.h @@ -1089,7 +1125,8 @@ keyboard.o: keyboard.c termchar.h termhooks.h termopts.h buffer.h character.h \ commands.h frame.h window.h macros.h disptab.h keyboard.h syssignal.h \ systime.h dispextern.h syntax.h $(INTERVAL_SRC) blockinput.h \ - atimer.h xterm.h puresize.h msdos.h keymap.h w32term.h macterm.h $(config_h) + atimer.h xterm.h puresize.h msdos.h keymap.h w32term.h macterm.h nsterm.h \ + $(config_h) keymap.o: keymap.c buffer.h commands.h keyboard.h termhooks.h blockinput.h \ atimer.h systime.h puresize.h character.h intervals.h keymap.h window.h \ $(config_h) @@ -1155,15 +1192,15 @@ window.o: window.c indent.h commands.h frame.h window.h buffer.h termchar.h \ disptab.h keyboard.h dispextern.h msdos.h composite.h \ keymap.h blockinput.h atimer.h systime.h $(INTERVAL_SRC) \ - xterm.h w32term.h macterm.h $(config_h) + xterm.h w32term.h macterm.h nsterm.h $(config_h) xdisp.o: xdisp.c macros.h commands.h process.h indent.h buffer.h dispextern.h \ coding.h termchar.h frame.h window.h disptab.h termhooks.h character.h \ charset.h $(config_h) keyboard.h $(INTERVAL_SRC) region-cache.h xterm.h \ - w32term.h macterm.h msdos.h composite.h fontset.h blockinput.h atimer.h \ - systime.h keymap.h font.h + w32term.h macterm.h nsterm.h msdos.h composite.h fontset.h blockinput.h \ + atimer.h systime.h keymap.h font.h xfaces.o: xfaces.c dispextern.h frame.h xterm.h buffer.h blockinput.h \ window.h character.h charset.h msdos.h dosfns.h composite.h atimer.h \ - systime.h keyboard.h fontset.h w32term.h macterm.h $(INTERVAL_SRC) \ + systime.h keyboard.h fontset.h w32term.h macterm.h nsterm.h $(INTERVAL_SRC) \ termchar.h termhooks.h font.h $(config_h) xfns.o: xfns.c buffer.h frame.h window.h keyboard.h xterm.h dispextern.h \ $(srcdir)/../lwlib/lwlib.h blockinput.h atimer.h systime.h epaths.h \ @@ -1276,7 +1313,38 @@ ${emacsapp}Contents/MacOS/Emacs: emacs${EXEEXT} mkdir -p ${emacsapp}Contents/MacOS/; cd ${emacsapp}Contents/MacOS/; cp ../../../../src/emacs${EXEEXT} Emacs${EXEEXT} -#endif +#endif /* HAVE_CARBON */ + +#ifdef HAVE_NS +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 \ + xterm.o xselect.o sound.o: nsgui.h +nsfns.o: nsfns.m charset.h nsterm.h nsgui.h frame.h window.h buffer.h \ + dispextern.h nsgui.h fontset.h $(INTERVAL_SRC) keyboard.h blockinput.h \ + atimer.h systime.h epaths.h termhooks.h coding.h systime.h $(config_h) +nsmenu.o: nsmenu.m termhooks.h frame.h window.h dispextern.h \ + nsgui.h keyboard.h blockinput.h atimer.h systime.h buffer.h \ + nsterm.h $(config_h) +nsterm.o: nsterm.m blockinput.h atimer.h systime.h syssignal.h nsterm.h \ + nsgui.h frame.h charset.h ccl.h dispextern.h fontset.h termhooks.h \ + termopts.h termchar.h disptab.h buffer.h window.h keyboard.h \ + $(INTERVAL_SRC) process.h coding.h $(config_h) +nsselect.o: nsselect.m blockinput.h nsterm.h nsgui.h frame.h $(config_h) +nsimage.o: nsimage.m nsterm.h +nsfont.o: nsterm.h dispextern.h frame.h lisp.h $(config_h) + +${emacsapp}: ${emacsappsrc} + mkdir -p ${emacsapp} + ( cd ${emacsappsrc} ; tar cfh - . ) | ( cd ${emacsapp} ; tar xf - ) + +${emacsbindir}Emacs: emacs${EXEEXT} + mkdir -p ${emacsbindir} + cp -f emacs${EXEEXT} ${emacsbindir}Emacs + +ns-app: ${emacsapp} ${emacsbindir}Emacs + +#endif /* HAVE_NS */ mostlyclean: rm -f temacs${EXEEXT} prefix-args${EXEEXT} core *.core \#* *.o libXMenu11.a liblw.a @@ -1285,6 +1353,9 @@ rm -f buildobj.lst clean: mostlyclean rm -f emacs-*.*.*${EXEEXT} emacs${EXEEXT} +#ifdef GNUSTEP + rm -f *.d +#endif /* bootstrap-clean is used to clean up just before a bootstrap. It should remove all files generated during a compilation/bootstrap, but not things like config.status or TAGS. */ diff -r ff312a846b25 -r d45acf0c8d23 src/blockinput.h --- a/src/blockinput.h Tue Jul 15 15:45:05 2008 +0000 +++ b/src/blockinput.h Tue Jul 15 18:15:18 2008 +0000 @@ -59,6 +59,16 @@ extern int pending_atimers; +#if defined HAVE_NS && !defined COCOA_EXPERIMENTAL_CTRL_G +/* NS does not use interrupt-driven input processing (yet), so this is + unneeded and moreover was causing problems. */ +#define BLOCK_INPUT +#define UNBLOCK_INPUT +#define TOTALLY_UNBLOCK_INPUT +#define UNBLOCK_INPUT_TO(LEVEL) + +#else + /* Begin critical section. */ #define BLOCK_INPUT (interrupt_input_blocked++) @@ -115,6 +125,8 @@ } \ while (0) +#endif /* defined HAVE_NS && !defined COCOA_EXPERIMENTAL_CTRL_G */ + #define UNBLOCK_INPUT_RESIGNAL UNBLOCK_INPUT /* In critical section ? */ diff -r ff312a846b25 -r d45acf0c8d23 src/callproc.c --- a/src/callproc.c Tue Jul 15 15:45:05 2008 +0000 +++ b/src/callproc.c Tue Jul 15 18:15:18 2008 +0000 @@ -1587,8 +1587,11 @@ register char **envp; #ifndef CANNOT_DUMP if (initialized) + { +#else + { + Vprocess_environment = Qnil; #endif - { for (envp = environ; *envp; envp++) Vprocess_environment = Fcons (build_string (*envp), Vprocess_environment); diff -r ff312a846b25 -r d45acf0c8d23 src/config.in --- a/src/config.in Tue Jul 15 15:45:05 2008 +0000 +++ b/src/config.in Tue Jul 15 18:15:18 2008 +0000 @@ -30,6 +30,10 @@ /* Define to 1 if the mktime function is broken. */ #undef BROKEN_MKTIME +/* Define to 1 if you are trying experimental enhanced Ctrl-g support using NS + windowing under MacOS X. */ +#undef COCOA_EXPERIMENTAL_CTRL_G + /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP systems. This function is required for `alloca.c' support on those systems. */ @@ -472,6 +476,10 @@ /* Define to 1 if you have the header file. */ #undef HAVE_NLIST_H +/* Define to 1 if you are using the NeXTstep API, either GNUstep or Cocoa on + Mac OS X. */ +#undef HAVE_NS + /* Define to 1 if personality LINUX32 can be set. */ #undef HAVE_PERSONALITY_LINUX32 @@ -798,6 +806,12 @@ /* Define to 1 if you don't have struct exception in math.h. */ #undef NO_MATHERR +/* Define to 1 if you are using NS windowing under MacOS X. */ +#undef NS_IMPL_COCOA + +/* Define to 1 if you are using NS windowing under GNUstep. */ +#undef NS_IMPL_GNUSTEP + /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT @@ -965,8 +979,8 @@ #undef volatile -/* If we're using any sort of window system, define some consequences. */ -#ifdef HAVE_X_WINDOWS +/* If we're using X11/Carbon/GNUstep, define some consequences. */ +#if defined HAVE_X_WINDOWS || defined(HAVE_CARBON) || defined(HAVE_NS) #define HAVE_WINDOW_SYSTEM #define MULTI_KBOARD #define HAVE_MOUSE @@ -978,13 +992,15 @@ #define MULTI_KBOARD #endif -/* If we're using the Carbon API on Mac OS X, define a few more - variables as well. */ -#ifdef HAVE_CARBON -#define HAVE_WINDOW_SYSTEM -#define HAVE_MOUSE +/* Sadly for now, GNUstep dump does not work. */ +#ifdef NS_IMPL_GNUSTEP +#define CANNOT_DUMP #endif +/* PENDING: These are used for the Carbon port only. */ +#undef MAC_OS +#undef MAC_OSX + /* Define USER_FULL_NAME to return a string that is the user's full name. It can assume that the variable `pw' @@ -1037,6 +1053,28 @@ #include config_opsysfile #include config_machfile +/* Set up some defines, C and LD flags for NeXTstep interface on GNUstep. + (There is probably a better place to do this, but right now the Cocoa + side does this in s/darwin.h, following the Carbon port, and we cannot + parallel this exactly since GNUstep is multi-OS. */ +#ifdef HAVE_NS +# ifdef C_SWITCH_SYSTEM +# undef C_SWITCH_SYSTEM +# endif +# ifdef NS_IMPL_GNUSTEP +/* See also .m.o rule in Makefile.in */ +# define C_SWITCH_X_SYSTEM -MMD -MP -D_REENTRANT -fPIC -fno-strict-aliasing +# define LD_SWITCH_SITE -lgnustep-gui -lgnustep-base -lobjc $(CONFIG_SYSTEM_LIBS) -lpthread +# define GNU_OBJC_CFLAGS -fgnu-runtime -Wno-import -fconstant-string-class=NSConstantString -DGNUSTEP_BASE_LIBRARY=1 -DGNU_GUI_LIBRARY=1 -DGNU_RUNTIME=1 -DGSWARN -DGSDIAGNOSE +# define OTHER_FILES ns-app +# else /* COCOA */ +# define C_SWITCH_X_SYSTEM +# define GNU_OBJC_CFLAGS +# endif /* COCOA */ +#endif /* HAVE_NS */ + + + /* If no remapping takes place, static variables cannot be dumped as pure, so don't worry about the `static' keyword. */ #ifdef NO_REMAP diff -r ff312a846b25 -r d45acf0c8d23 src/dispextern.h --- a/src/dispextern.h Tue Jul 15 15:45:05 2008 +0000 +++ b/src/dispextern.h Tue Jul 15 18:15:18 2008 +0000 @@ -69,6 +69,14 @@ typedef XImagePtr XImagePtr_or_DC; #endif +#ifdef HAVE_NS +#include "nsgui.h" +/* following typedef needed to accomodate the MSDOS port, believe it or not */ +typedef struct ns_display_info Display_Info; +typedef Pixmap XImagePtr; +typedef XImagePtr XImagePtr_or_DC; +#endif + #ifndef NativeRectangle #define NativeRectangle int #endif @@ -1563,6 +1571,13 @@ /* If non-zero, use overstrike (to simulate bold-face). */ unsigned overstrike : 1; +/* NOTE: this is not used yet, but eventually this impl should be done + similarly to overstrike */ +#ifdef HAVE_NS + /* If non-zero, use geometric rotation (to simulate italic). */ + unsigned synth_ital : 1; +#endif + /* Next and previous face in hash collision list of face cache. */ struct face *next, *prev; diff -r ff312a846b25 -r d45acf0c8d23 src/dispnew.c --- a/src/dispnew.c Tue Jul 15 15:45:05 2008 +0000 +++ b/src/dispnew.c Tue Jul 15 18:15:18 2008 +0000 @@ -63,6 +63,10 @@ #include "macterm.h" #endif /* MAC_OS */ +#ifdef HAVE_NS +#include "nsterm.h" +#endif + /* Include systime.h after xterm.h to avoid double inclusion of time.h. */ #include "systime.h" @@ -6895,6 +6899,20 @@ } #endif /* MAC_OS */ +#ifdef HAVE_NS + if (!inhibit_window_system +#ifndef CANNOT_DUMP + && initialized +#endif + ) + { + Vinitial_window_system = intern("ns"); + Vwindow_system_version = make_number(10); + adjust_frame_glyphs_initially (); + return; + } +#endif + /* If no window system has been specified, try to use the terminal. */ if (! isatty (0)) { diff -r ff312a846b25 -r d45acf0c8d23 src/emacs.c --- a/src/emacs.c Tue Jul 15 15:45:05 2008 +0000 +++ b/src/emacs.c Tue Jul 15 18:15:18 2008 +0000 @@ -46,6 +46,11 @@ #include "w32heap.h" /* for prototype of sbrk */ #endif +#ifdef NS_IMPL_GNUSTEP +/* At least under Debian, GSConfig is in a subdirectory. --Stef */ +#include +#endif + #include "lisp.h" #include "commands.h" #include "intervals.h" @@ -193,7 +198,7 @@ extern int inherited_pgroup; #endif -#ifdef HAVE_X_WINDOWS +#if defined(HAVE_X_WINDOWS) || defined(HAVE_NS) /* If non-zero, -d was specified, meaning we're using some window system. */ int display_arg; #endif @@ -838,7 +843,7 @@ run_time_remap (argv[0]); #endif -#ifdef MAC_OSX +#if defined (MAC_OSX) || defined (NS_IMPL_COCOA) if (!initialized) unexec_init_emacs_zone (); #endif @@ -1410,6 +1415,38 @@ no_loadup = argmatch (argv, argc, "-nl", "--no-loadup", 6, NULL, &skip_args); +#ifdef HAVE_NS + ns_alloc_autorelease_pool(); + if (!noninteractive) + { + char *tmp; + display_arg = 4; +#ifdef NS_IMPL_COCOA + if (skip_args < argc) + { + if (!strncmp(argv[skip_args], "-psn", 4)) + { + skip_args += 1; + } + else + { + if (skip_args+1 < argc && !strncmp(argv[skip_args+1], "-psn", 4)) + skip_args += 2; + } + } +#endif + /* This used for remote operation.. not fully implemented yet. */ + if (argmatch (argv, argc, "-_NSMachLaunch", 0, 3, &tmp, &skip_args)) + display_arg = 4; + else if (argmatch (argv, argc, "-MachLaunch", 0, 3, &tmp, &skip_args)) + display_arg = 4; + else if (argmatch (argv, argc, "-macosx", 0, 2, NULL, &skip_args)) + display_arg = 4; + else if (argmatch (argv, argc, "-NSHost", 0, 3, &tmp, &skip_args)) + display_arg = 4; + } +#endif /* HAVE_NS */ + #ifdef HAVE_X_WINDOWS /* Stupid kludge to catch command-line display spec. We can't handle this argument entirely in window system dependent code @@ -1487,6 +1524,13 @@ init_mac_osx_environment (); #endif +#ifdef HAVE_NS +#ifndef CANNOT_DUMP + if (initialized) +#endif + ns_init_paths (); +#endif + /* egetenv is a pretty low-level facility, which may get called in many circumstances; it seems flimsy to put off initializing it until calling init_callproc. */ @@ -1588,6 +1632,7 @@ #ifdef HAVE_X_WINDOWS syms_of_xterm (); syms_of_xfns (); + syms_of_xmenu (); syms_of_fontset (); #ifdef HAVE_X_SM syms_of_xsmfns (); @@ -1599,13 +1644,6 @@ syms_of_menu (); -#ifndef HAVE_NTGUI -#ifndef MAC_OS - /* Called before init_window_once for Mac OS Classic. */ - syms_of_xmenu (); -#endif -#endif - #ifdef HAVE_NTGUI syms_of_w32term (); syms_of_w32fns (); @@ -1622,6 +1660,14 @@ syms_of_fontset (); #endif /* MAC_OSX && HAVE_CARBON */ +#ifdef HAVE_NS + syms_of_nsterm (); + syms_of_nsfns (); + syms_of_nsmenu (); + syms_of_nsselect (); + syms_of_fontset (); +#endif /* HAVE_NS */ + #ifdef HAVE_DBUS syms_of_dbusbind (); #endif /* HAVE_DBUS */ @@ -1843,6 +1889,15 @@ { "-color", "--color", 5, 0}, { "-no-splash", "--no-splash", 3, 0 }, { "-no-desktop", "--no-desktop", 3, 0 }, +#ifdef HAVE_NS + { "-NSAutoLaunch", 0, 5, 1 }, + { "-NXAutoLaunch", 0, 5, 1 }, + { "-disable-font-backend", "--disable-font-backend", 65, 0 }, + { "-_NSMachLaunch", 0, 85, 1 }, + { "-MachLaunch", 0, 85, 1 }, + { "-macosx", 0, 85, 0 }, + { "-NSHost", 0, 85, 1 }, +#endif /* These have the same priority as ordinary file name args, so they are not reordered with respect to those. */ { "-L", "--directory", 0, 1 }, @@ -1862,6 +1917,13 @@ { "-visit", "--visit", 0, 1 }, { "-file", "--file", 0, 1 }, { "-insert", "--insert", 0, 1 }, +#ifdef HAVE_NS + { "-NXOpen", 0, 0, 1 }, + { "-NXOpenTemp", 0, 0, 1 }, + { "-NSOpen", 0, 0, 1 }, + { "-NSOpenTemp", 0, 0, 1 }, + { "-GSFilePath", 0, 0, 1 }, +#endif /* This should be processed after ordinary file name args and the like. */ { "-kill", "--kill", -10, 0 }, }; @@ -2158,6 +2220,10 @@ #ifdef MSDOS dos_cleanup (); #endif + +#ifdef HAVE_NS + ns_term_shutdown (sig); +#endif } diff -r ff312a846b25 -r d45acf0c8d23 src/font.c --- a/src/font.c Tue Jul 15 15:45:05 2008 +0000 +++ b/src/font.c Tue Jul 15 18:15:18 2008 +0000 @@ -46,6 +46,10 @@ #include "w32term.h" #endif /* HAVE_NTGUI */ +#ifdef HAVE_NS +#include "nsterm.h" +#endif /* HAVE_NS */ + #ifdef MAC_OS #include "macterm.h" #endif /* MAC_OS */ @@ -57,6 +61,12 @@ /* Important character set strings. */ Lisp_Object Qascii_0, Qiso8859_1, Qiso10646_1, Qunicode_bmp, Qunicode_sip; +#ifdef HAVE_NS +#define DEFAULT_ENCODING Qiso10646_1 +#else +#define DEFAULT_ENCODING Qiso8859_1 +#endif + /* Special vector of zero length. This is repeatedly used by (struct font_driver *)->list when a specified font is not found. */ static Lisp_Object null_vector; @@ -3096,7 +3106,7 @@ registry[0] = AREF (spec, FONT_REGISTRY_INDEX); if (NILP (registry[0])) { - registry[0] = Qiso8859_1; + registry[0] = DEFAULT_ENCODING; registry[1] = Qascii_0; registry[2] = null_vector; } @@ -4948,6 +4958,7 @@ extern void syms_of_bdffont P_ (()); extern void syms_of_w32font P_ (()); extern void syms_of_atmfont P_ (()); +extern void syms_of_nsfont P_ (()); void syms_of_font () @@ -5117,6 +5128,9 @@ #ifdef WINDOWSNT syms_of_w32font (); #endif /* WINDOWSNT */ +#ifdef HAVE_NS + syms_of_nsfont (); +#endif /* HAVE_NS */ #ifdef MAC_OS syms_of_atmfont (); #endif /* MAC_OS */ diff -r ff312a846b25 -r d45acf0c8d23 src/font.h --- a/src/font.h Tue Jul 15 15:45:05 2008 +0000 +++ b/src/font.h Tue Jul 15 18:15:18 2008 +0000 @@ -860,6 +860,9 @@ #ifdef MAC_OS extern struct font_driver atmfont_driver; #endif /* MAC_OS */ +#ifdef HAVE_NS +extern struct font_driver nsfont_driver; +#endif /* HAVE_NS */ #ifndef FONT_DEBUG #define FONT_DEBUG diff -r ff312a846b25 -r d45acf0c8d23 src/fontset.c --- a/src/fontset.c Tue Jul 15 15:45:05 2008 +0000 +++ b/src/fontset.c Tue Jul 15 18:15:18 2008 +0000 @@ -47,6 +47,9 @@ #ifdef WINDOWSNT #include "w32term.h" #endif +#ifdef HAVE_NS +#include "nsterm.h" +#endif #ifdef MAC_OS #include "macterm.h" #endif @@ -1622,6 +1625,11 @@ ASET (font_spec, i, Qnil); Fset_fontset_font (name, Qlatin, font_spec, Qnil, Qnil); Fset_fontset_font (name, Qnil, font_spec, Qnil, Qnil); + +#ifdef HAVE_NS + nsfont_make_fontset_for_font(name, font_object); +#endif + return XINT (FONTSET_ID (fontset)); } diff -r ff312a846b25 -r d45acf0c8d23 src/frame.c --- a/src/frame.c Tue Jul 15 15:45:05 2008 +0000 +++ b/src/frame.c Tue Jul 15 18:15:18 2008 +0000 @@ -32,6 +32,9 @@ #ifdef MAC_OS #include "macterm.h" #endif +#ifdef HAVE_NS +#include "nsterm.h" +#endif #include "buffer.h" /* These help us bind and responding to switch-frame events. */ #include "commands.h" @@ -72,7 +75,7 @@ Lisp_Object Qframep, Qframe_live_p; Lisp_Object Qicon, Qmodeline; Lisp_Object Qonly; -Lisp_Object Qx, Qw32, Qmac, Qpc; +Lisp_Object Qx, Qw32, Qmac, Qpc, Qns; Lisp_Object Qvisible; Lisp_Object Qdisplay_type; Lisp_Object Qbackground_mode; @@ -203,7 +206,8 @@ Value is t for a termcap frame (a character-only terminal), `x' for an Emacs frame that is really an X window, `w32' for an Emacs frame that is a window on MS-Windows display, -`mac' for an Emacs frame on a Macintosh display, +`mac' for an Emacs frame on a Macintosh 8/9 X-Carbon display, +`ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display, `pc' for a direct-write MS-DOS frame. See also `frame-live-p'. */) (object) @@ -224,6 +228,8 @@ return Qpc; case output_mac: return Qmac; + case output_ns: + return Qns; default: abort (); } @@ -551,6 +557,11 @@ FRAME_CAN_HAVE_SCROLL_BARS (f) = 0; FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none; +#ifdef CANNOT_DUMP + if (!noninteractive) + init_frame_faces (f); +#endif + return f; } @@ -880,6 +891,12 @@ Fselect_window (XFRAME (frame)->selected_window, Qnil); +#ifdef NS_IMPL_COCOA + /* term gets no other notification of this */ + if (for_deletion) + Fraise_frame(Qnil); +#endif + /* We want to make sure that the next event generates a frame-switch event to the appropriate frame. This seems kludgy to me, but before you take it out, make sure that evaluating something like @@ -2969,8 +2986,9 @@ old_value = get_frame_param (f, prop); fullscreen_is_being_set |= EQ (prop, Qfullscreen); - +#ifndef HAVE_NS /* PENDING: ensure font attrs change goes through */ if (NILP (Fequal (val, old_value))) +#endif { store_frame_param (f, prop, val); @@ -3949,6 +3967,9 @@ case RES_TYPE_BOOLEAN: tem = Fdowncase (tem); if (!strcmp (SDATA (tem), "on") +#ifdef HAVE_NS + || !strcmp(SDATA(tem), "yes") +#endif || !strcmp (SDATA (tem), "true")) return Qt; else @@ -3964,9 +3985,15 @@ Lisp_Object lower; lower = Fdowncase (tem); if (!strcmp (SDATA (lower), "on") +#ifdef HAVE_NS + || !strcmp(SDATA(lower), "yes") +#endif || !strcmp (SDATA (lower), "true")) return Qt; else if (!strcmp (SDATA (lower), "off") +#ifdef HAVE_NS + || !strcmp(SDATA(lower), "no") +#endif || !strcmp (SDATA (lower), "false")) return Qnil; else @@ -4366,6 +4393,8 @@ staticpro (&Qpc); Qmac = intern ("mac"); staticpro (&Qmac); + Qns = intern ("ns"); + staticpro (&Qns); Qvisible = intern ("visible"); staticpro (&Qvisible); Qbuffer_predicate = intern ("buffer-predicate"); @@ -4473,8 +4502,8 @@ DEFVAR_LISP ("default-frame-scroll-bars", &Vdefault_frame_scroll_bars, doc: /* Default position of scroll bars on this window-system. */); #ifdef HAVE_WINDOW_SYSTEM -#if defined(HAVE_NTGUI) || defined(MAC_OS) - /* MS-Windows has scroll bars on the right by default. */ +#if defined(HAVE_NTGUI) || defined(MAC_OS) || defined(NS_IMPL_COCOA) + /* MS-Windows and Mac OS X have scroll bars on the right by default. */ Vdefault_frame_scroll_bars = Qright; #else Vdefault_frame_scroll_bars = Qleft; @@ -4540,7 +4569,7 @@ handles focus, since there is no way in general for Emacs to find out automatically. */); #ifdef HAVE_WINDOW_SYSTEM -#if defined(HAVE_NTGUI) || defined(MAC_OS) +#if defined(HAVE_NTGUI) || defined(MAC_OS) || defined(HAVE_NS) focus_follows_mouse = 0; #else focus_follows_mouse = 1; diff -r ff312a846b25 -r d45acf0c8d23 src/frame.h --- a/src/frame.h Tue Jul 15 15:45:05 2008 +0000 +++ b/src/frame.h Tue Jul 15 18:15:18 2008 +0000 @@ -50,7 +50,8 @@ output_x_window, output_msdos_raw, output_w32, - output_mac + output_mac, + output_ns }; enum vertical_scroll_bar_type @@ -242,7 +243,7 @@ auto-resize-tool-bar is set to grow-only. */ unsigned minimize_tool_bar_window_p : 1; -#if defined (USE_GTK) || defined (MAC_OS) +#if defined (USE_GTK) || defined (HAVE_NS) || defined (MAC_OS) /* Nonzero means using a tool bar that comes from the toolkit. */ int external_tool_bar; #endif @@ -332,6 +333,7 @@ struct x_output *x; /* xterm.h */ struct w32_output *w32; /* w32term.h */ struct mac_output *mac; /* macterm.h */ + struct ns_output *ns; /* nsterm.h */ EMACS_INT nothing; } output_data; @@ -359,7 +361,7 @@ int menu_bar_lines; #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \ - || defined (USE_GTK) + || defined (HAVE_NS) || defined (USE_GTK) /* Nonzero means using a menu bar that comes from the X toolkit. */ unsigned int external_menu_bar : 1; #endif @@ -519,6 +521,7 @@ #define FRAME_W32_P(f) ((f)->output_method == output_w32) #define FRAME_MSDOS_P(f) ((f)->output_method == output_msdos_raw) #define FRAME_MAC_P(f) ((f)->output_method == output_mac) +#define FRAME_NS_P(f) ((f)->output_method == output_ns) /* FRAME_WINDOW_P tests whether the frame is a window, and is defined to be the predicate for the window system being used. */ @@ -532,6 +535,9 @@ #ifdef MAC_OS #define FRAME_WINDOW_P(f) FRAME_MAC_P (f) #endif +#ifdef HAVE_NS +#define FRAME_WINDOW_P(f) FRAME_NS_P(f) +#endif #ifndef FRAME_WINDOW_P #define FRAME_WINDOW_P(f) (0) #endif @@ -570,7 +576,7 @@ /* Nonzero if this frame should display a tool bar in a way that does not use any text lines. */ -#if defined (USE_GTK) || defined (MAC_OS) +#if defined (USE_GTK) || defined (HAVE_NS) || defined (MAC_OS) #define FRAME_EXTERNAL_TOOL_BAR(f) (f)->external_tool_bar #else #define FRAME_EXTERNAL_TOOL_BAR(f) 0 @@ -589,7 +595,7 @@ /* 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 (MAC_OS) \ - || defined (USE_GTK) + || defined (HAVE_NS) || defined (USE_GTK) #define FRAME_EXTERNAL_MENU_BAR(f) (f)->external_menu_bar #else #define FRAME_EXTERNAL_MENU_BAR(f) 0 @@ -1044,7 +1050,7 @@ extern Lisp_Object Qheight, Qwidth; extern Lisp_Object Qminibuffer, Qmodeline; extern Lisp_Object Qonly; -extern Lisp_Object Qx, Qw32, Qmac, Qpc; +extern Lisp_Object Qx, Qw32, Qmac, Qpc, Qns; extern Lisp_Object Qvisible; extern Lisp_Object Qdisplay_type; extern Lisp_Object Qbackground_mode; diff -r ff312a846b25 -r d45acf0c8d23 src/fringe.c --- a/src/fringe.c Tue Jul 15 15:45:05 2008 +0000 +++ b/src/fringe.c Tue Jul 15 18:15:18 2008 +0000 @@ -482,7 +482,7 @@ static Lisp_Object *fringe_faces; static int max_fringe_bitmaps; -static int max_used_fringe_bitmap = MAX_STANDARD_FRINGE_BITMAPS; +int max_used_fringe_bitmap = MAX_STANDARD_FRINGE_BITMAPS; /* Lookup bitmap number for symbol BITMAP. diff -r ff312a846b25 -r d45acf0c8d23 src/getloadavg.c --- a/src/getloadavg.c Tue Jul 15 15:45:05 2008 +0000 +++ b/src/getloadavg.c Tue Jul 15 18:15:18 2008 +0000 @@ -420,7 +420,7 @@ # define host_self mach_host_self # endif -# ifdef NeXT +# if defined(NeXT) || defined(RHAPSODY) || defined(DARWIN) || defined(MAC_OSX) # ifdef HAVE_MACH_MACH_H # include # else @@ -467,7 +467,7 @@ /* Avoid static vars inside a function since in HPUX they dump as pure. */ -# ifdef NeXT +# if defined(NeXT) || defined(RHAPSODY) || defined(DARWIN) || defined(MAC_OSX) static processor_set_t default_set; static int getloadavg_initialized; # endif /* NeXT */ @@ -647,7 +647,8 @@ # endif /* __NetBSD__ */ -# if !defined (LDAV_DONE) && defined (NeXT) +# if !defined (LDAV_DONE) && ( defined (NeXT) || defined(RHAPSODY) \ + || defined(DARWIN) || defined(MAC_OSX) ) # define LDAV_DONE /* The NeXT code was adapted from iscreen 3.2. */ diff -r ff312a846b25 -r d45acf0c8d23 src/image.c --- a/src/image.c Tue Jul 15 15:45:05 2008 +0000 +++ b/src/image.c Tue Jul 15 18:15:18 2008 +0000 @@ -131,6 +131,32 @@ #endif /* MAC_OS */ +#ifdef HAVE_NS +#include "nsterm.h" +#include +#include + +#undef COLOR_TABLE_SUPPORT + +typedef struct ns_bitmap_record Bitmap_Record; + +#define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y) +#define NO_PIXMAP 0 + +#define RGB_PIXEL_COLOR unsigned long +#define ZPixmap 0 + +#define PIX_MASK_RETAIN 0 +#define PIX_MASK_DRAW 1 + +#define FRAME_X_VISUAL FRAME_NS_DISPLAY_INFO(f)->visual +#define x_defined_color(f, name, color_def, alloc) \ + ns_defined_color (f, name, color_def, alloc, 0) +#define FRAME_X_SCREEN(f) 0 +#define DefaultDepthOfScreen(screen) ns_display_list->n_planes +#endif /* HAVE_NS */ + + /* Search path for bitmap files. */ Lisp_Object Vx_bitmap_file_path; @@ -403,6 +429,33 @@ #endif /* USE_CG_DRAWING */ #endif /* MAC_OS */ +#ifdef HAVE_NS +XImagePtr +XGetImage (Display *display, Pixmap pixmap, int x, int y, + unsigned int width, unsigned int height, + unsigned long plane_mask, int format) +{ + /* PENDING: not sure what this function is supposed to do.. */ + ns_retain_object(pixmap); + return pixmap; +} + +/* use with imgs created by ns_image_for_XPM */ +unsigned long +XGetPixel (XImagePtr ximage, int x, int y) +{ + return ns_get_pixel(ximage, x, y); +} + +/* use with imgs created by ns_image_for_XPM; alpha set to 1; + pixel is assumed to be in form RGB */ +void +XPutPixel (XImagePtr ximage, int x, int y, unsigned long pixel) +{ + ns_put_pixel(ximage, x, y, pixel); +} +#endif /* HAVE_NS */ + /* Functions to access the contents of a bitmap, given an id. */ @@ -519,12 +572,23 @@ return -1; #endif +#ifdef HAVE_NS + void *bitmap = ns_image_from_XBM(bits, width, height); + if (!bitmap) + return -1; +#endif + id = x_allocate_bitmap_record (f); #ifdef MAC_OS dpyinfo->bitmaps[id - 1].bitmap_data = (char *) xmalloc (height * width); bcopy (bits, dpyinfo->bitmaps[id - 1].bitmap_data, height * width); #endif /* MAC_OS */ +#ifdef HAVE_NS + dpyinfo->bitmaps[id - 1].img = bitmap; + dpyinfo->bitmaps[id - 1].depth = 1; +#endif + dpyinfo->bitmaps[id - 1].file = NULL; dpyinfo->bitmaps[id - 1].height = height; dpyinfo->bitmaps[id - 1].width = width; @@ -552,6 +616,8 @@ struct frame *f; Lisp_Object file; { + Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); + #ifdef MAC_OS return -1; /* MAC_TODO : bitmap support */ #endif /* MAC_OS */ @@ -560,8 +626,26 @@ return -1; /* W32_TODO : bitmap support */ #endif /* HAVE_NTGUI */ +#ifdef HAVE_NS + int id; + void *bitmap = ns_image_from_file(file); + + if (!bitmap) + return -1; + + + id = x_allocate_bitmap_record (f); + dpyinfo->bitmaps[id - 1].img = bitmap; + dpyinfo->bitmaps[id - 1].refcount = 1; + dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SBYTES (file) + 1); + dpyinfo->bitmaps[id - 1].depth = 1; + dpyinfo->bitmaps[id - 1].height = ns_image_width(bitmap); + dpyinfo->bitmaps[id - 1].width = ns_image_height(bitmap); + strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file)); + return id; +#endif + #ifdef HAVE_X_WINDOWS - Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); unsigned int width, height; Pixmap bitmap; int xhot, yhot, result, id; @@ -630,6 +714,10 @@ bm->bitmap_data = NULL; #endif /* MAC_OS */ +#ifdef HAVE_NS + ns_release_object(bm->img); +#endif + if (bm->file) { xfree (bm->file); @@ -1407,7 +1495,8 @@ because a typical font is `top-heavy' (due to the presence uppercase letters), so the image placement should err towards being top-heavy too. It also just generally looks better. */ - ascent = (height + face->font->ascent - face->font->descent + 1) / 2; + ascent = (height + FONT_BASE(face->font) + - FONT_DESCENT(face->font) + 1) / 2; #endif /* HAVE_NTGUI */ } else @@ -1476,6 +1565,14 @@ #define Free_Pixmap(display, pixmap) \ DeleteObject (pixmap) +#elif defined (HAVE_NS) + +#define Destroy_Image(ximg, dummy) \ + ns_release_object(ximg) + +#define Free_Pixmap(display, pixmap) \ + ns_release_object(pixmap) + #else #define Destroy_Image(ximg, dummy) \ @@ -1484,7 +1581,7 @@ #define Free_Pixmap(display, pixmap) \ XFreePixmap (display, pixmap) -#endif /* HAVE_NTGUI */ +#endif /* !HAVE_NTGUI && !HAVE_NS */ /* Return the `background' field of IMG. If IMG doesn't have one yet, @@ -1607,6 +1704,10 @@ { Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap); img->pixmap = NO_PIXMAP; +#ifdef HAVE_NS + if (img->background_valid) + ns_free_indexed_color(img->background); +#endif img->background_valid = 0; } @@ -2387,6 +2488,18 @@ return 1; #endif /* MAC_OS */ + +#ifdef HAVE_NS + *pixmap = ns_image_for_XPM(width, height, depth); + if (*pixmap == 0) + { + *ximg = NULL; + image_error ("Unable to allocate NSImage for XPM pixmap", Qnil, Qnil); + return 0; + } + *ximg = *pixmap; + return 1; +#endif } @@ -2412,6 +2525,9 @@ #ifdef MAC_OS XDestroyImage (ximg); #endif /* MAC_OS */ +#ifdef HAVE_NS + ns_release_object(ximg); +#endif /* HAVE_NS */ } } @@ -2446,6 +2562,11 @@ #ifdef MAC_OS xassert (ximg == pixmap); #endif /* MAC_OS */ + +#ifdef HAVE_NS + xassert (ximg == pixmap); + ns_retain_object(ximg); +#endif } @@ -3499,6 +3620,10 @@ /* If colors were specified, transfer the bitmap to a color one. */ if (non_default_colors) convert_mono_to_color_image (f, img, fg, bg); + +#elif defined (HAVE_NS) + img->pixmap = ns_image_from_XBM(data, img->width, img->height); + #else img->pixmap = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f), @@ -3507,7 +3632,7 @@ img->width, img->height, fg, bg, DefaultDepthOfScreen (FRAME_X_SCREEN (f))); -#endif /* HAVE_NTGUI */ +#endif /* !HAVE_NTGUI && !HAVE_NS */ } @@ -3891,13 +4016,13 @@ XPM images ***********************************************************************/ -#if defined (HAVE_XPM) || defined (MAC_OS) +#if defined (HAVE_XPM) || defined (MAC_OS) || defined (HAVE_NS) 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)); -#endif /* HAVE_XPM || MAC_OS */ +#endif /* HAVE_XPM || MAC_OS || HAVE_NS */ #ifdef HAVE_XPM #ifdef HAVE_NTGUI @@ -3920,7 +4045,7 @@ #endif /* HAVE_NTGUI */ #endif /* HAVE_XPM */ -#if defined (HAVE_XPM) || defined (MAC_OS) +#if defined (HAVE_XPM) || defined (MAC_OS) || defined (HAVE_NS) /* The symbol `xpm' identifying XPM-format images. */ Lisp_Object Qxpm; @@ -4247,7 +4372,7 @@ || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value))); } -#endif /* HAVE_XPM || MAC_OS */ +#endif /* HAVE_XPM || MAC_OS || HAVE_NS */ #if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) int @@ -4526,7 +4651,7 @@ #endif /* HAVE_XPM */ -#ifdef MAC_OS +#if defined (MAC_OS) || ( defined (HAVE_NS) && !defined (HAVE_XPM) ) /* XPM support functions for Mac OS where libxpm is not available. Only XPM version 3 (without any extensions) is supported. */ @@ -4884,8 +5009,11 @@ if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap) +#ifndef HAVE_NS || !x_create_x_image_and_pixmap (f, width, height, 1, - &mask_img, &img->mask)) + &mask_img, &img->mask) +#endif + ) { image_error ("Out of memory (%s)", img->spec, Qnil); goto error; @@ -4905,9 +5033,14 @@ XPutPixel (ximg, x, y, (INTEGERP (color_val) ? XINT (color_val) : FRAME_FOREGROUND_PIXEL (f))); +#ifndef HAVE_NS XPutPixel (mask_img, x, y, (!EQ (color_val, Qt) ? PIX_MASK_DRAW : (have_mask = 1, PIX_MASK_RETAIN))); +#else + if (EQ(color_val, Qt)) + ns_set_alpha(ximg, x, y, 0); +#endif } if (y + 1 < height) expect (','); @@ -4922,6 +5055,7 @@ x_put_x_image (f, ximg, img->pixmap, width, height); x_destroy_x_image (ximg); +#ifndef HAVE_NS if (have_mask) { /* Fill in the background_transparent field while we have the @@ -4937,7 +5071,7 @@ Free_Pixmap (FRAME_X_DISPLAY (f), img->mask); img->mask = NO_PIXMAP; } - +#endif return 1; failure: @@ -5003,7 +5137,7 @@ return success_p; } -#endif /* MAC_OS */ +#endif /* MAC_OS || (HAVE_NS && !HAVE_XPM) */ @@ -5273,6 +5407,9 @@ pixel = PALETTERGB (r >> 8, g >> 8, b >> 8); #endif /* HAVE_NTGUI */ +#ifdef HAVE_NS + pixel = RGB_TO_ULONG (r >> 8, g >> 8, b >> 8); +#endif /* HAVE_NS */ return pixel; } @@ -5378,7 +5515,7 @@ p->pixel = GET_PIXEL (ximg, x, y); if (rgb_p) { -#ifdef MAC_OS +#if defined (MAC_OS) || defined (HAVE_NS) p->red = RED16_FROM_ULONG (p->pixel); p->green = GREEN16_FROM_ULONG (p->pixel); p->blue = BLUE16_FROM_ULONG (p->pixel); @@ -5459,8 +5596,8 @@ XColor *colors; { int x, y; - XImagePtr oimg; - Pixmap pixmap; + XImagePtr oimg = NULL; + Pixmap pixmap = NULL; XColor *p; init_color_table (); @@ -5673,6 +5810,8 @@ Display *dpy = FRAME_X_DISPLAY (f); GC gc; +#ifndef HAVE_NS //TODO: NS support, however this not needed for toolbars + #ifdef MAC_OS #define MaskForeground(f) PIX_MASK_DRAW #else @@ -5697,6 +5836,7 @@ img->width - 1, 0); XFreeGC (dpy, gc); } +#endif /* !HAVE_NS */ #else HDC hdc, bmpdc; HGDIOBJ prev; @@ -5762,11 +5902,13 @@ } #ifndef HAVE_NTGUI +#ifndef HAVE_NS /* 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) return 0; +#endif /* !HAVE_NS */ /* Get the X image of IMG->pixmap. */ ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap, 0, 0, @@ -5820,16 +5962,21 @@ #ifndef HAVE_NTGUI for (y = 0; y < img->height; ++y) for (x = 0; x < img->width; ++x) +#ifndef HAVE_NS XPutPixel (mask_img, x, y, (XGetPixel (ximg, x, y) != bg ? PIX_MASK_DRAW : PIX_MASK_RETAIN)); - +#else + if (XGetPixel (ximg, x, y) == bg) + ns_set_alpha(ximg, x, y, 0); +#endif /* HAVE_NS */ +#ifndef HAVE_NS /* Fill in the background_transparent field while we have the mask handy. */ image_background_transparent (img, f, mask_img); /* 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); - +#endif /* !HAVE_NS */ #else for (y = 0; y < img->height; ++y) for (x = 0; x < img->width; ++x) @@ -6280,7 +6427,7 @@ PNG ***********************************************************************/ -#if defined (HAVE_PNG) || defined (MAC_OS) +#if defined (HAVE_PNG) || defined (MAC_OS) || defined (HAVE_NS) /* Function prototypes. */ @@ -6352,7 +6499,7 @@ return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1; } -#endif /* HAVE_PNG || MAC_OS */ +#endif /* HAVE_PNG || MAC_OS || HAVE_NS */ #ifdef HAVE_PNG @@ -6912,6 +7059,17 @@ } #endif /* MAC_OS */ +#ifdef HAVE_NS +static int +png_load (struct frame *f, struct image *img) +{ + return ns_load_image(f, img, + image_spec_value (img->spec, QCfile, NULL), + image_spec_value (img->spec, QCdata, NULL)); +} +#endif /* HAVE_NS */ + + #endif /* !HAVE_PNG */ @@ -6920,7 +7078,7 @@ JPEG ***********************************************************************/ -#if defined (HAVE_JPEG) || defined (MAC_OS) +#if defined (HAVE_JPEG) || defined (MAC_OS) || defined (HAVE_NS) static int jpeg_image_p P_ ((Lisp_Object object)); static int jpeg_load P_ ((struct frame *f, struct image *img)); @@ -6991,7 +7149,7 @@ return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1; } -#endif /* HAVE_JPEG || MAC_OS */ +#endif /* HAVE_JPEG || MAC_OS || HAVE_NS */ #ifdef HAVE_JPEG @@ -7491,6 +7649,16 @@ } #endif /* MAC_OS */ +#ifdef HAVE_NS +static int +jpeg_load (struct frame *f, struct image *img) +{ + return ns_load_image(f, img, + image_spec_value (img->spec, QCfile, NULL), + image_spec_value (img->spec, QCdata, NULL)); +} +#endif /* HAVE_NS */ + #endif /* !HAVE_JPEG */ @@ -7499,7 +7667,7 @@ TIFF ***********************************************************************/ -#if defined (HAVE_TIFF) || defined (MAC_OS) +#if defined (HAVE_TIFF) || defined (MAC_OS) || defined (HAVE_NS) static int tiff_image_p P_ ((Lisp_Object object)); static int tiff_load P_ ((struct frame *f, struct image *img)); @@ -7569,7 +7737,7 @@ return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1; } -#endif /* HAVE_TIFF || MAC_OS */ +#endif /* HAVE_TIFF || MAC_OS || HAVE_NS */ #ifdef HAVE_TIFF @@ -7916,6 +8084,16 @@ } #endif /* MAC_OS */ +#ifdef HAVE_NS +static int +tiff_load (struct frame *f, struct image *img) +{ + return ns_load_image(f, img, + image_spec_value (img->spec, QCfile, NULL), + image_spec_value (img->spec, QCdata, NULL)); +} +#endif /* HAVE_NS */ + #endif /* !HAVE_TIFF */ @@ -7924,7 +8102,7 @@ GIF ***********************************************************************/ -#if defined (HAVE_GIF) || defined (MAC_OS) +#if defined (HAVE_GIF) || defined (MAC_OS) || defined (HAVE_NS) static int gif_image_p P_ ((Lisp_Object object)); static int gif_load P_ ((struct frame *f, struct image *img)); @@ -8553,6 +8731,16 @@ } #endif /* MAC_OS */ +#ifdef HAVE_NS +static int +gif_load (struct frame *f, struct image *img) +{ + return ns_load_image(f, img, + image_spec_value (img->spec, QCfile, NULL), + image_spec_value (img->spec, QCdata, NULL)); +} +#endif /* HAVE_NS */ + #endif /* HAVE_GIF */ @@ -9335,27 +9523,27 @@ if (CONSP (tested)) return XCDR (tested); -#if defined (HAVE_XPM) || defined (MAC_OS) +#if defined (HAVE_XPM) || defined (MAC_OS) || defined (HAVE_NS) if (EQ (type, Qxpm)) return CHECK_LIB_AVAILABLE (&xpm_type, init_xpm_functions, libraries); #endif -#if defined (HAVE_JPEG) || defined (MAC_OS) +#if defined (HAVE_JPEG) || defined (MAC_OS) || defined (HAVE_NS) if (EQ (type, Qjpeg)) return CHECK_LIB_AVAILABLE (&jpeg_type, init_jpeg_functions, libraries); #endif -#if defined (HAVE_TIFF) || defined (MAC_OS) +#if defined (HAVE_TIFF) || defined (MAC_OS) || defined (HAVE_NS) if (EQ (type, Qtiff)) return CHECK_LIB_AVAILABLE (&tiff_type, init_tiff_functions, libraries); #endif -#if defined (HAVE_GIF) || defined (MAC_OS) +#if defined (HAVE_GIF) || defined (MAC_OS) || defined (HAVE_NS) if (EQ (type, Qgif)) return CHECK_LIB_AVAILABLE (&gif_type, init_gif_functions, libraries); #endif -#if defined (HAVE_PNG) || defined (MAC_OS) +#if defined (HAVE_PNG) || defined (MAC_OS) || defined (HAVE_NS) if (EQ (type, Qpng)) return CHECK_LIB_AVAILABLE (&png_type, init_png_functions, libraries); #endif @@ -9480,31 +9668,31 @@ staticpro (&QCpt_height); #endif /* HAVE_GHOSTSCRIPT */ -#if defined (HAVE_XPM) || defined (MAC_OS) +#if defined (HAVE_XPM) || defined (MAC_OS) || defined (HAVE_NS) Qxpm = intern ("xpm"); staticpro (&Qxpm); ADD_IMAGE_TYPE (Qxpm); #endif -#if defined (HAVE_JPEG) || defined (MAC_OS) +#if defined (HAVE_JPEG) || defined (MAC_OS) || defined (HAVE_NS) Qjpeg = intern ("jpeg"); staticpro (&Qjpeg); ADD_IMAGE_TYPE (Qjpeg); #endif -#if defined (HAVE_TIFF) || defined (MAC_OS) +#if defined (HAVE_TIFF) || defined (MAC_OS) || defined (HAVE_NS) Qtiff = intern ("tiff"); staticpro (&Qtiff); ADD_IMAGE_TYPE (Qtiff); #endif -#if defined (HAVE_GIF) || defined (MAC_OS) +#if defined (HAVE_GIF) || defined (MAC_OS) || defined (HAVE_NS) Qgif = intern ("gif"); staticpro (&Qgif); ADD_IMAGE_TYPE (Qgif); #endif -#if defined (HAVE_PNG) || defined (MAC_OS) +#if defined (HAVE_PNG) || defined (MAC_OS) || defined (HAVE_NS) Qpng = intern ("png"); staticpro (&Qpng); ADD_IMAGE_TYPE (Qpng); diff -r ff312a846b25 -r d45acf0c8d23 src/keyboard.c --- a/src/keyboard.c Tue Jul 15 15:45:05 2008 +0000 +++ b/src/keyboard.c Tue Jul 15 18:15:18 2008 +0000 @@ -80,6 +80,11 @@ #include "macterm.h" #endif +#ifdef HAVE_NS +#include "nsterm.h" +extern Lisp_Object Qsuper; +#endif + #ifndef USE_CRT_DLL extern int errno; #endif @@ -4147,7 +4152,8 @@ #endif } -#if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (MAC_OS) +#if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (MAC_OS) \ + || defined (HAVE_NS) else if (event->kind == DELETE_WINDOW_EVENT) { /* Make an event (delete-frame (FRAME)). */ @@ -4156,7 +4162,8 @@ kbd_fetch_ptr = event + 1; } #endif -#if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (MAC_OS) +#if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (MAC_OS) \ + || defined (HAVE_NS) else if (event->kind == ICONIFY_EVENT) { /* Make an event (iconify-frame (FRAME)). */ @@ -4179,7 +4186,7 @@ kbd_fetch_ptr = event + 1; } #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \ - || defined (USE_GTK) + || defined(HAVE_NS) || defined (USE_GTK) else if (event->kind == MENU_BAR_ACTIVATE_EVENT) { kbd_fetch_ptr = event + 1; @@ -4289,7 +4296,7 @@ obj = make_lispy_event (event); #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined(MAC_OS) \ - || defined (USE_GTK) + || defined(HAVE_NS) || defined (USE_GTK) /* If this was a menu selection, then set the flag to inhibit writing to last_nonmenu_event. Don't do this if the event we're returning is (menu-bar), though; that indicates the @@ -5643,7 +5650,7 @@ if (event->kind == MOUSE_CLICK_EVENT) { struct frame *f = XFRAME (event->frame_or_window); -#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) +#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) && ! defined (HAVE_NS) int row, column; #endif @@ -5652,7 +5659,7 @@ if (! FRAME_LIVE_P (f)) return Qnil; -#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) +#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) && ! defined (HAVE_NS) /* EVENT->x and EVENT->y are frame-relative pixel coordinates at this place. Under old redisplay, COLUMN and ROW are set to frame relative glyph coordinates @@ -5712,7 +5719,7 @@ return Fcons (item, Fcons (position, Qnil)); } -#endif /* not USE_X_TOOLKIT && not USE_GTK */ +#endif /* not USE_X_TOOLKIT && not USE_GTK && not HAVE_NS */ position = make_lispy_position (f, &event->x, &event->y, event->timestamp); @@ -6092,7 +6099,7 @@ #endif /* HAVE_MOUSE */ #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \ - || defined (USE_GTK) + || defined(HAVE_NS) || defined (USE_GTK) case MENU_BAR_EVENT: if (EQ (event->arg, event->frame_or_window)) /* This is the prefix key. We translate this to @@ -7305,6 +7312,10 @@ void handle_async_input () { +#ifdef BSD4_1 + extern int select_alarmed; +#endif + interrupt_input_pending = 0; while (1) @@ -7317,6 +7328,9 @@ if (nread <= 0) break; +#ifdef BSD4_1 + select_alarmed = 1; /* Force the select emulator back to life */ +#endif } } @@ -7335,6 +7349,10 @@ signal (signo, input_available_signal); #endif /* USG */ +#ifdef BSD4_1 + sigisheld (SIGIO); +#endif + #ifdef SYNC_INPUT interrupt_input_pending = 1; #else @@ -7348,6 +7366,9 @@ handle_async_input (); #endif +#ifdef BSD4_1 + sigfree (); +#endif errno = old_errno; } #endif /* SIGIO */ @@ -7975,10 +7996,15 @@ /* With the introduction of where_is_cache, the computation of equivalent key bindings is sufficiently fast that we do not need to cache it here any more. */ - /* CHECK_IMPURE (start); - XSETCDR (start, Fcons (Fcons (Qnil, Qnil), XCDR (start))); - cachelist = XCAR (XCDR (start)); */ +/*PENDING: under NS this effect does not hold, perhaps due to the + modifier-preference changes to where-is-internal.. */ +#ifdef HAVE_NS + CHECK_IMPURE (start); + XSETCDR (start, Fcons (Fcons (Qnil, Qnil), XCDR (start))); + cachelist = XCAR (XCDR (start)); +#else cachelist = Fcons (Qnil, Qnil); +#endif newcache = 1; tem = AREF (item_properties, ITEM_PROPERTY_KEYEQ); if (!NILP (keyhint)) @@ -8044,7 +8070,12 @@ && SYMBOLP (XSYMBOL (def)->function) && ! NILP (Fget (def, Qmenu_alias))) def = XSYMBOL (def)->function; +#ifdef HAVE_NS + /* prefer 'super' bindings */ + tem = Fwhere_is_internal (def, Qnil, Qsuper, Qt, Qt); +#else tem = Fwhere_is_internal (def, Qnil, Qt, Qnil, Qt); +#endif XSETCAR (cachelist, tem); if (NILP (tem)) { @@ -8077,7 +8108,7 @@ if (newcache && !NILP (tem)) { tem = concat2 (build_string (" "), tem); - // tem = concat3 (build_string (" ("), tem, build_string (")")); + /* tem = concat3 (build_string (" ("), tem, build_string (")")); */ XSETCDR (cachelist, tem); } diff -r ff312a846b25 -r d45acf0c8d23 src/keyboard.h --- a/src/keyboard.h Tue Jul 15 15:45:05 2008 +0000 +++ b/src/keyboard.h Tue Jul 15 18:15:18 2008 +0000 @@ -314,8 +314,7 @@ confined to an extended version of this with sections of code below using it unconditionally. */ #ifndef HAVE_NTGUI -#ifdef USE_GTK -/* gtk just uses utf-8. */ +#if defined (USE_GTK) || defined (HAVE_NS) # define ENCODE_MENU_STRING(str) ENCODE_UTF_8 (str) #elif defined HAVE_X_I18N #define ENCODE_MENU_STRING(str) ENCODE_SYSTEM (str) @@ -325,6 +324,56 @@ #else /* HAVE_NTGUI */ #define ENCODE_MENU_STRING(str) (str) #endif + +#if defined (HAVE_NS) || defined (HAVE_NTGUI) + +typedef void * XtPointer; +typedef unsigned char Boolean; + +/* Definitions copied from lwlib.h */ + +enum button_type +{ + BUTTON_TYPE_NONE, + BUTTON_TYPE_TOGGLE, + BUTTON_TYPE_RADIO +}; + +/* This structure is based on the one in ../lwlib/lwlib.h, with unused portions + removed. No term uses these. */ +typedef struct _widget_value +{ + /* name of widget */ + Lisp_Object lname; + char* name; + /* value (meaning depend on widget type) */ + char* value; + /* keyboard equivalent. no implications for XtTranslations */ + Lisp_Object lkey; + 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; +#if defined (HAVE_NTGUI) + /* true if menu title */ + Boolean title; +#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; +} widget_value; +#endif + /* Macros for dealing with lispy events. */ diff -r ff312a846b25 -r d45acf0c8d23 src/keymap.c --- a/src/keymap.c Tue Jul 15 15:45:05 2008 +0000 +++ b/src/keymap.c Tue Jul 15 18:15:18 2008 +0000 @@ -111,6 +111,10 @@ extern Lisp_Object Voverriding_local_map; +#ifdef HAVE_NS +extern Lisp_Object Qalt, Qcontrol, Qhyper, Qmeta, Qsuper; +#endif + /* Hash table used to cache a reverse-map to speed up calls to where-is. */ static Lisp_Object where_is_cache; /* Which keymaps are reverse-stored in the cache. */ @@ -2621,6 +2625,41 @@ return 1; } +#ifdef HAVE_NS +int lisp_to_mod(Lisp_Object lmod) +/* ------------------------------------------------------------------------- + Convert lisp symbol to emacs modifier code. + ------------------------------------------------------------------------- */ +{ + if (EQ(lmod, Qmeta)) + return meta_modifier; + else if (EQ(lmod, Qsuper)) + return super_modifier; + else if (EQ(lmod, Qcontrol)) + return ctrl_modifier; + else if (EQ(lmod, Qalt)) + return alt_modifier; + else if (EQ(lmod, Qhyper)) + return hyper_modifier; + return 0; +} + +/* Return non-zero if SEQ starts w/a char modified by given modifier only. */ +static int +modifier_sequence_p (Lisp_Object seq, Lisp_Object modifier) +{ + Lisp_Object idx, elt; + + if (XINT (Flength (seq)) == 0) + return 0; + XSETFASTINT(idx, 0); + elt = Faref(seq, idx); + + return (XUINT(elt) & (CHAR_MODIFIER_MASK ^ shift_modifier)) + == lisp_to_mod(modifier); +} +#endif + /* where-is - finding a command in a set of keymaps. */ @@ -2803,6 +2842,14 @@ we find. */ if (EQ (firstonly, Qnon_ascii)) RETURN_UNGCPRO (sequence); +#ifdef HAVE_NS + /* respond to modifier preference */ + else if ((EQ (firstonly, Qalt) || EQ (firstonly, Qcontrol) + || EQ (firstonly, Qhyper) || EQ (firstonly, Qmeta) + || EQ (firstonly, Qsuper))) + if (modifier_sequence_p(sequence, firstonly)) + RETURN_UNGCPRO (sequence); +#endif else if (!NILP (firstonly) && ascii_sequence_p (sequence)) RETURN_UNGCPRO (sequence); @@ -2836,6 +2883,10 @@ If optional 3rd arg FIRSTONLY is non-nil, return the first key sequence found, rather than a list of all possible key sequences. +#ifdef HAVE_NS +If FIRSTONLY is the symbol for a modifier key, return the first binding found, +that is modified by that modifier only. +#endif If FIRSTONLY is the symbol `non-ascii', return the first binding found, no matter what it is. If FIRSTONLY has another non-nil value, prefer sequences of ASCII characters @@ -2909,10 +2960,19 @@ for (i = n - 1; i >= 0; --i) if (EQ (shadow_lookup (keymaps, defns[i], Qnil), definition)) { - if (ascii_sequence_p (defns[i])) - break; - else if (j < 0) - j = i; +#ifdef HAVE_NS + if ((EQ (firstonly, Qalt) || EQ (firstonly, Qcontrol) + || EQ (firstonly, Qhyper) || EQ (firstonly, Qmeta) + || EQ (firstonly, Qsuper)) + && modifier_sequence_p(defns[i], firstonly)) + break; + else if (EQ (firstonly, Qt) && ascii_sequence_p (defns[i])) +#else + if (ascii_sequence_p (defns[i])) +#endif + break; + else if (j < 0) + j = i; } result = i >= 0 ? defns[i] : (j >= 0 ? defns[j] : Qnil); diff -r ff312a846b25 -r d45acf0c8d23 src/lisp.h --- a/src/lisp.h Tue Jul 15 15:45:05 2008 +0000 +++ b/src/lisp.h Tue Jul 15 18:15:18 2008 +0000 @@ -28,6 +28,11 @@ #define P_(proto) () #endif +#ifdef NS_IMPL_GNUSTEP +/* This conflicts with functions in the GNUstep libraries. */ +#define hash_remove emacs_hash_remove +#endif /* NS_IMPL_GNUSTEP */ + #if 0 /* Define this temporarily to hunt a bug. If defined, the size of strings is redundantly recorded in sdata structures so that it can @@ -157,7 +162,7 @@ #endif /* Let's USE_LSB_TAG on systems where we know malloc returns mult-of-8. */ -#if defined GNU_MALLOC || defined DOUG_LEA_MALLOC || defined __GLIBC__ || defined MAC_OSX +#if defined GNU_MALLOC || defined DOUG_LEA_MALLOC || defined __GLIBC__ || defined MAC_OSX || defined(NS_IMPL_COCOA) /* We also need to be able to specify mult-of-8 alignment on static vars. */ # if defined DECL_ALIGN /* We currently do not support USE_LSB_TAG with a union Lisp_Object. */ diff -r ff312a846b25 -r d45acf0c8d23 src/lread.c --- a/src/lread.c Tue Jul 15 15:45:05 2008 +0000 +++ b/src/lread.c Tue Jul 15 18:15:18 2008 +0000 @@ -4095,7 +4095,7 @@ } #endif -#if (!(defined(WINDOWSNT) || (defined(HAVE_CARBON)))) +#if (!(defined(WINDOWSNT) || (defined(HAVE_CARBON)) || (defined(HAVE_NS)))) /* When Emacs is invoked over network shares on NT, PATH_LOADSEARCH is almost never correct, thereby causing a warning to be printed out that confuses users. Since PATH_LOADSEARCH is always overridden by the @@ -4125,7 +4125,7 @@ } } } -#endif /* !(WINDOWSNT || HAVE_CARBON) */ +#endif /* !(WINDOWSNT || HAVE_CARBON || HAVE_NS) */ /* If the EMACSLOADPATH environment variable is set, use its value. This doesn't apply if we're dumping. */ diff -r ff312a846b25 -r d45acf0c8d23 src/menu.c --- a/src/menu.c Tue Jul 15 15:45:05 2008 +0000 +++ b/src/menu.c Tue Jul 15 18:15:18 2008 +0000 @@ -36,6 +36,10 @@ #include "xterm.h" #endif +#ifdef HAVE_NS +#include "nsterm.h" +#endif + #ifdef USE_GTK #include "gtkutil.h" #endif @@ -440,7 +444,7 @@ XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED], XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]); -#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI) +#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) || defined (HAVE_NTGUI) /* Display a submenu using the toolkit. */ if (! (NILP (map) || NILP (enabled))) { @@ -580,7 +584,7 @@ } -#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI) +#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) || defined (HAVE_NTGUI) /* Allocate a widget_value, blocking input. */ @@ -956,7 +960,71 @@ } } -#endif /* USE_X_TOOLKIT || USE_GTK || HAVE_NTGUI */ +#endif /* USE_X_TOOLKIT || USE_GTK || HAVE_NS || HAVE_NTGUI */ + +#ifdef HAVE_NS +/* As above, but return the menu selection instead of storing in kb buffer. + If keymaps==1, return full prefixes to selection. */ +Lisp_Object +find_and_return_menu_selection (FRAME_PTR f, int keymaps, void *client_data) +{ + Lisp_Object prefix, entry; + int i; + Lisp_Object *subprefix_stack; + int submenu_depth = 0; + + prefix = entry = Qnil; + i = 0; + subprefix_stack = + (Lisp_Object *)alloca(menu_items_used * sizeof (Lisp_Object)); + + 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 ((int) (EMACS_INT)client_data == 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; + } + } +} +#endif void syms_of_menu () diff -r ff312a846b25 -r d45acf0c8d23 src/nsfns.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/nsfns.m Tue Jul 15 18:15:18 2008 +0000 @@ -0,0 +1,2668 @@ +/* Functions for the NeXT/Open/GNUstep and MacOSX window system. + + Copyright (C) 1989, 1992, 1993, 1994, 2005, 2006, 2008 + 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 3, 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., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. + +Originally by Carl Edman +Updated by Christian Limpach (chris@nice.ch) +OpenStep/Rhapsody port by Scott Bender (sbender@harmony-ds.com) +MacOSX/Aqua port by Christophe de Dinechin (descubes@earthlink.net) +GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu) + +*/ + +#include +#include +#include "config.h" +#include "lisp.h" +#include "blockinput.h" +#include "nsterm.h" +#include "window.h" +#include "buffer.h" +#include "keyboard.h" +#include "termhooks.h" +#include "fontset.h" + +#include "character.h" +#include "font.h" + +#if 0 +int fns_trace_num = 1; +#define NSTRACE(x) fprintf (stderr, "%s:%d: [%d] " #x "\n", \ + __FILE__, __LINE__, ++fns_trace_num) +#else +#define NSTRACE(x) +#endif + +#ifdef HAVE_NS + +extern NSArray *ns_send_types, *ns_return_types, *ns_drag_types; + +extern Lisp_Object Qforeground_color; +extern Lisp_Object Qbackground_color; +extern Lisp_Object Qcursor_color; +extern Lisp_Object Qinternal_border_width; +extern Lisp_Object Qvisibility; +extern Lisp_Object Qcursor_type; +extern Lisp_Object Qicon_type; +extern Lisp_Object Qicon_name; +extern Lisp_Object Qicon_left; +extern Lisp_Object Qicon_top; +extern Lisp_Object Qleft; +extern Lisp_Object Qright; +extern Lisp_Object Qtop; +extern Lisp_Object Qdisplay; +extern Lisp_Object Qvertical_scroll_bars; +extern Lisp_Object Qauto_raise; +extern Lisp_Object Qauto_lower; +extern Lisp_Object Qbox; +extern Lisp_Object Qscroll_bar_width; +extern Lisp_Object Qx_resource_name; +extern Lisp_Object Qface_set_after_frame_default; +extern Lisp_Object Qunderline, Qundefined; +extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth; +extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle; + +Lisp_Object Qnone; +Lisp_Object Qns_frame_parameter; +Lisp_Object Qbuffered; +Lisp_Object Qfontsize; + +/* hack for OS X file panels */ +char panelOK = 0; + +/* Alist of elements (REGEXP . IMAGE) for images of icons associated + to frames.*/ +Lisp_Object Vns_icon_type_alist; + +EmacsTooltip *ns_tooltip; + +/* Need forward declaration here to preserve organizational integrity of file */ +Lisp_Object Fns_open_connection (Lisp_Object, Lisp_Object, Lisp_Object); + +extern BOOL ns_in_resize; + + +/* ========================================================================== + + Internal utility functions + + ========================================================================== */ + + +void +check_ns (void) +{ + if (NSApp == nil) + error ("OpenStep is not in use or not initialized"); +} + + +/* Nonzero if we can use mouse menus. */ +int +have_menus_p () +{ + return NSApp != nil; +} + + +/* Extract a frame as a FRAME_PTR, defaulting to the selected frame + and checking validity for NS. */ +static FRAME_PTR +check_ns_frame (Lisp_Object frame) +{ + FRAME_PTR f; + + if (NILP (frame)) + f = SELECTED_FRAME (); + else + { + CHECK_LIVE_FRAME (frame); + f = XFRAME (frame); + } + if (! FRAME_NS_P (f)) + error ("non-NS frame used"); + return f; +} + + +/* Let the user specify an NS display with a frame. + nil stands for the selected frame--or, if that is not an NS frame, + the first NS display on the list. */ +static struct ns_display_info * +check_ns_display_info (Lisp_Object frame) +{ + if (NILP (frame)) + { + struct frame *f = SELECTED_FRAME (); + if (FRAME_NS_P (f) && FRAME_LIVE_P (f) ) + return FRAME_NS_DISPLAY_INFO (f); + else if (ns_display_list != 0) + return ns_display_list; + else + error ("NS windows are not in use or not initialized"); + } + else if (INTEGERP (frame)) + { + struct terminal *t = get_terminal (frame, 1); + + if (t->type != output_ns) + error ("Terminal %d is not an NS display", XINT (frame)); + + return t->display_info.ns; + } + else if (STRINGP (frame)) + return ns_display_info_for_name (frame); + else + { + FRAME_PTR f; + + CHECK_LIVE_FRAME (frame); + f = XFRAME (frame); + if (! FRAME_NS_P (f)) + error ("non-NS frame used"); + return FRAME_NS_DISPLAY_INFO (f); + } + return NULL; /* shut compiler up */ +} + + +static id +ns_get_window (Lisp_Object maybeFrame) +{ + id view =nil, window =nil; + + if (!FRAMEP (maybeFrame) || !FRAME_NS_P (XFRAME (maybeFrame))) + maybeFrame = selected_frame;/*wrong_type_argument (Qframep, maybeFrame); */ + + if (!NILP (maybeFrame)) + view = FRAME_NS_VIEW (XFRAME (maybeFrame)); + if (view) window =[view window]; + + return window; +} + + +static NSScreen * +ns_get_screen (Lisp_Object anythingUnderTheSun) +{ + id window =nil; + NSScreen *screen = 0; + + struct terminal *terminal; + struct ns_display_info *dpyinfo; + struct frame *f = NULL; + Lisp_Object frame; + + if (INTEGERP (anythingUnderTheSun)) { + /* we got a terminal */ + terminal = get_terminal (anythingUnderTheSun, 1); + dpyinfo = terminal->display_info.ns; + f = dpyinfo->ns_focus_frame; + if (!f) + f = dpyinfo->ns_highlight_frame; + + } else if (FRAMEP (anythingUnderTheSun) && + FRAME_NS_P (XFRAME (anythingUnderTheSun))) { + /* we got a frame */ + f = XFRAME (anythingUnderTheSun); + + } else if (STRINGP (anythingUnderTheSun)) { /* FIXME/cl for multi-display */ + } + + if (!f) + f = SELECTED_FRAME (); + if (f) + { + XSETFRAME (frame, f); + window = ns_get_window (frame); + } + + if (window) + screen = [window screen]; + if (!screen) + screen = [NSScreen mainScreen]; + + return screen; +} + + +/* Return the X display structure for the display named NAME. + Open a new connection if necessary. */ +struct ns_display_info * +ns_display_info_for_name (name) + Lisp_Object name; +{ + Lisp_Object names; + struct ns_display_info *dpyinfo; + + CHECK_STRING (name); + + for (dpyinfo = ns_display_list, names = ns_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; + } + + error ("Emacs for OpenStep does not yet support multi-display."); + + Fns_open_connection (name, Qnil, Qnil); + dpyinfo = ns_display_list; + + if (dpyinfo == 0) + error ("OpenStep on %s not responding.\n", XSTRING (name)->data); + + return dpyinfo; +} + + +static Lisp_Object +interpret_services_menu (NSMenu *menu, Lisp_Object prefix, Lisp_Object old) +/* -------------------------------------------------------------------------- + Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side + -------------------------------------------------------------------------- */ +{ + int i, count; + id item; + const char *name; + Lisp_Object nameStr; + unsigned short key; + NSString *keys; + Lisp_Object res; + + count = [menu numberOfItems]; + for (i = 0; ioutput_data.ns->foreground_color release]; + f->output_data.ns->foreground_color = col; + + if (FRAME_NS_VIEW (f)) + { + update_face_from_frame_parameter (f, Qforeground_color, arg); + /*recompute_basic_faces (f); */ + if (FRAME_VISIBLE_P (f)) + redraw_frame (f); + } +} + + +static void +ns_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ + struct face *face; + NSColor *col; + NSView *view = FRAME_NS_VIEW (f); + float alpha; + + if (ns_lisp_to_color (arg, &col)) + { + store_frame_param (f, Qbackground_color, oldval); + error ("Unknown color"); + } + + /* clear the frame; in some instances the NS-internal GC appears not to + update, or it does update and cannot clear old text properly */ + if (FRAME_VISIBLE_P (f)) + ns_clear_frame (f); + + [col retain]; + [f->output_data.ns->background_color release]; + f->output_data.ns->background_color = col; + if (view != nil) + { + [[view window] setBackgroundColor: col]; + alpha = [col alphaComponent]; + +#ifdef NS_IMPL_COCOA + /* the alpha code below only works on 10.4, so we need to do something + else (albeit less good) otherwise. + Check NSApplication.h for useful NSAppKitVersionNumber values. */ + if (NSAppKitVersionNumber < 744.0) + [[view window] setAlphaValue: alpha]; +#endif + + if (alpha != 1.0) + [[view window] setOpaque: NO]; + else + [[view window] setOpaque: YES]; + + face = FRAME_DEFAULT_FACE (f); + if (face) + { + col = NS_FACE_BACKGROUND (face); + face->background = + (EMACS_UINT) [[col colorWithAlphaComponent: alpha] retain]; + [col release]; + + update_face_from_frame_parameter (f, Qbackground_color, arg); + } + + if (FRAME_VISIBLE_P (f)) + redraw_frame (f); + } +} + + +static void +ns_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ + NSColor *col; + + if (ns_lisp_to_color (arg, &col)) + { + store_frame_param (f, Qcursor_color, oldval); + error ("Unknown color"); + } + + [f->output_data.ns->desired_cursor_color release]; + f->output_data.ns->desired_cursor_color = [col retain]; + + if (FRAME_VISIBLE_P (f)) + { + x_update_cursor (f, 0); + x_update_cursor (f, 1); + } + update_face_from_frame_parameter (f, Qcursor_color, arg); +} + + +static void +ns_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ + NSView *view = FRAME_NS_VIEW (f); + NSTRACE (ns_set_icon_name); + + if (ns_in_resize) + return; + + /* see if it's changed */ + 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 (NILP (arg)) + { + if (!NILP (f->title)) + arg = f->title; + else + /* explicit name and no icon-name -> explicit_name */ + if (f->explicit_name) + arg = f->name; + else + { + /* no explicit name and no icon-name -> + name has to be rebuild from icon_title_format */ + windows_or_buffers_changed++; + return; + } + } + + /* Don't change the name if it's already NAME. */ + if ([[view window] miniwindowTitle] && + ([[[view window] miniwindowTitle] + isEqualToString: [NSString stringWithUTF8String: + XSTRING (arg)->data]])) + return; + + [[view window] setMiniwindowTitle: + [NSString stringWithUTF8String: XSTRING (arg)->data]]; +} + + +static void +ns_set_name_iconic (struct frame *f, Lisp_Object name, int explicit) +{ + NSView *view = FRAME_NS_VIEW (f); + NSTRACE (ns_set_name_iconic); + + if (ns_in_resize) + return; + + /* 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) + name = f->name; + + /* title overrides explicit name */ + if (! NILP (f->title)) + name = f->title; + + /* icon_name overrides title and explicit name */ + if (! NILP (f->icon_name)) + name = f->icon_name; + + if (NILP (name)) + name = build_string + ([[[NSProcessInfo processInfo] processName] UTF8String]); + else + CHECK_STRING (name); + + /* Don't change the name if it's already NAME. */ + if ([[view window] miniwindowTitle] && + ([[[view window] miniwindowTitle] + isEqualToString: [NSString stringWithUTF8String: + XSTRING (name)->data]])) + return; + + [[view window] setMiniwindowTitle: + [NSString stringWithUTF8String: XSTRING (name)->data]]; +} + + +static void +ns_set_name (struct frame *f, Lisp_Object name, int explicit) +{ + NSView *view = FRAME_NS_VIEW (f); + NSTRACE (ns_set_name); + + if (ns_in_resize) + return; + + /* 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 (NILP (name)) + name = build_string + ([[[NSProcessInfo processInfo] processName] UTF8String]); + + f->name = name; + + /* title overrides explicit name */ + if (! NILP (f->title)) + name = f->title; + + CHECK_STRING (name); + + /* Don't change the name if it's already NAME. */ + if ([[[view window] title] + isEqualToString: [NSString stringWithUTF8String: + XSTRING (name)->data]]) + return; + [[view window] setTitle: [NSString stringWithUTF8String: + XSTRING (name)->data]]; +} + + +/* 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. */ +static void +ns_explicitly_set_name (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval) +{ + NSTRACE (ns_explicitly_set_name); + ns_set_name_iconic (f, arg, 1); + ns_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 (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval) +{ + NSTRACE (x_implicitly_set_name); + if (FRAME_ICONIFIED_P (f)) + ns_set_name_iconic (f, arg, 0); + else + ns_set_name (f, arg, 0); +} + + +/* 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. */ +static void +ns_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name) +{ + NSTRACE (ns_set_title); + /* Don't change the title if it's already NAME. */ + if (EQ (name, f->title)) + return; + + update_mode_lines = 1; + + f->title = name; +} + + +void +ns_set_name_as_filename (struct frame *f) +{ + NSView *view = FRAME_NS_VIEW (f); + Lisp_Object name; + Lisp_Object buf = XWINDOW (f->selected_window)->buffer; + const char *title; + NSAutoreleasePool *pool; + NSTRACE (ns_set_name_as_filename); + + if (f->explicit_name || ! NILP (f->title) || ns_in_resize) + return; + + BLOCK_INPUT; + pool = [[NSAutoreleasePool alloc] init]; + name =XBUFFER (buf)->filename; + if (NILP (name) || FRAME_ICONIFIED_P (f)) name =XBUFFER (buf)->name; + + if (FRAME_ICONIFIED_P (f) && !NILP (f->icon_name)) + name = f->icon_name; + + if (NILP (name)) + name = build_string + ([[[NSProcessInfo processInfo] processName] UTF8String]); + else + CHECK_STRING (name); + + title = FRAME_ICONIFIED_P (f) ? [[[view window] miniwindowTitle] UTF8String] + : [[[view window] title] UTF8String]; + + if (title && (! strcmp (title, XSTRING (name)->data))) + { + [pool release]; + UNBLOCK_INPUT; + return; + } + + if (! FRAME_ICONIFIED_P (f)) + { +#ifdef NS_IMPL_COCOA + /* work around a bug observed on 10.3 where + setTitleWithRepresentedFilename does not clear out previous state + if given filename does not exist */ + NSString *str = [NSString stringWithUTF8String: XSTRING (name)->data]; + if (![[NSFileManager defaultManager] fileExistsAtPath: str]) + { + [[view window] setTitleWithRepresentedFilename: @""]; + [[view window] setTitle: str]; + } + else + { + [[view window] setTitleWithRepresentedFilename: str]; + } +#else + [[view window] setTitleWithRepresentedFilename: + [NSString stringWithUTF8String: XSTRING (name)->data]]; +#endif + f->name = name; + } + else + { + [[view window] setMiniwindowTitle: + [NSString stringWithUTF8String: XSTRING (name)->data]]; + } + [pool release]; + UNBLOCK_INPUT; +} + + +void +ns_set_doc_edited (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ + NSView *view = FRAME_NS_VIEW (f); + NSAutoreleasePool *pool; + BLOCK_INPUT; + pool = [[NSAutoreleasePool alloc] init]; + [[view window] setDocumentEdited: !NILP (arg)]; + [pool release]; + UNBLOCK_INPUT; +} + + +static void +ns_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) +{ + int nlines; + int olines = FRAME_MENU_BAR_LINES (f); + 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; +/* does for all frames, whereas we just want for one frame + [NSMenu setMenuBarVisible: YES]; */ + } + else + { + if (FRAME_EXTERNAL_MENU_BAR (f) == 1) + free_frame_menubar (f); +/* [NSMenu setMenuBarVisible: NO]; */ + FRAME_EXTERNAL_MENU_BAR (f) = 0; + } +} + + +/* 23: PENDING: there is an erroneous direct call in window.c to this fn */ +void +x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) +{ + ns_set_menu_bar_lines (f, value, oldval); +} + + +/* 23: toolbar support */ +static void +ns_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) +{ + int nlines; + Lisp_Object root_window; + + if (FRAME_MINIBUF_ONLY_P (f)) + return; + + if (INTEGERP (value) && XINT (value) >= 0) + nlines = XFASTINT (value); + else + nlines = 0; + + if (nlines) + { + FRAME_EXTERNAL_TOOL_BAR (f) = 1; + update_frame_tool_bar (f); + } + else + { + if (FRAME_EXTERNAL_TOOL_BAR (f)) + { + free_frame_tool_bar (f); + FRAME_EXTERNAL_TOOL_BAR (f) = 0; + } + } + + x_set_window_size (f, 0, f->text_cols, f->text_lines); +} + + +/* 23: PENDING: there is an erroneous direct call in window.c to this fn */ +void +x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) +{ + ns_set_tool_bar_lines (f, value, oldval); +} + + +void +ns_implicitly_set_icon_type (struct frame *f) +{ + Lisp_Object tem; + EmacsView *view = FRAME_NS_VIEW (f); + id image =nil; + Lisp_Object chain, elt; + NSAutoreleasePool *pool; + BOOL setMini = YES; + + NSTRACE (ns_implicitly_set_icon_type); + + BLOCK_INPUT; + pool = [[NSAutoreleasePool alloc] init]; + if (f->output_data.ns->miniimage + && [[NSString stringWithUTF8String: XSTRING (f->name)->data] + isEqualToString: [(NSImage *)f->output_data.ns->miniimage name]]) + { + [pool release]; + UNBLOCK_INPUT; + return; + } + + tem = assq_no_quit (Qicon_type, f->param_alist); + if (CONSP (tem) && ! NILP (XCDR (tem))) + { + [pool release]; + UNBLOCK_INPUT; + return; + } + + for (chain = Vns_icon_type_alist; + (image = nil) && CONSP (chain); + chain = XCDR (chain)) + { + elt = XCAR (chain); + /* special case: 't' means go by file type */ + if (SYMBOLP (elt) && elt == Qt && XSTRING (f->name)->data[0] == '/') + { + NSString *str = + [NSString stringWithUTF8String: XSTRING (f->name)->data]; + if ([[NSFileManager defaultManager] fileExistsAtPath: str]) + image = [[[NSWorkspace sharedWorkspace] iconForFile: str] retain]; + } + else if (CONSP (elt) && + STRINGP (XCAR (elt)) && + STRINGP (XCDR (elt)) && + fast_string_match (XCAR (elt), f->name) >= 0) + { + image = [EmacsImage allocInitFromFile: XCDR (elt)]; + if (image == nil) + image = [[NSImage imageNamed: + [NSString stringWithUTF8String: + XSTRING (XCDR (elt))->data]] retain]; + } + } + + if (image == nil) + { + image = [[[NSWorkspace sharedWorkspace] iconForFileType: @"text"] retain]; + setMini = NO; + } + + [f->output_data.ns->miniimage release]; + f->output_data.ns->miniimage = image; + [view setMiniwindowImage: setMini]; + [pool release]; + UNBLOCK_INPUT; +} + + +static void +ns_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ + EmacsView *view = FRAME_NS_VIEW (f); + id image = nil; + BOOL setMini = YES; + + NSTRACE (ns_set_icon_type); + + if (!NILP (arg) && SYMBOLP (arg)) + { + arg =build_string (XSTRING (XSYMBOL (arg)->xname)->data); + store_frame_param (f, Qicon_type, arg); + } + + /* do it the implicit way */ + if (NILP (arg)) + { + ns_implicitly_set_icon_type (f); + return; + } + + CHECK_STRING (arg); + + image = [EmacsImage allocInitFromFile: arg]; + if (image == nil) + image =[NSImage imageNamed: [NSString stringWithUTF8String: + XSTRING (arg)->data]]; + + if (image == nil) + { + image = [NSImage imageNamed: @"text"]; + setMini = NO; + } + + f->output_data.ns->miniimage = image; + [view setMiniwindowImage: setMini]; +} + + +/* 23: added Xism; we stub out (we do implement this in ns-win.el) */ +int +XParseGeometry (char *string, int *x, int *y, + unsigned int *width, unsigned int *height) +{ + message1 ("Warning: XParseGeometry not supported under NS.\n"); + return 0; +} + + +/*PENDING: move to nsterm? */ +int +ns_lisp_to_cursor_type (Lisp_Object arg) +{ + char *str; + if (XTYPE (arg) == Lisp_String) + str =XSTRING (arg)->data; + else if (XTYPE (arg) == Lisp_Symbol) + str =XSTRING (XSYMBOL (arg)->xname)->data; + else return -1; + if (!strcmp (str, "box")) return filled_box; + if (!strcmp (str, "hollow")) return hollow_box; + if (!strcmp (str, "underscore")) return underscore; + if (!strcmp (str, "bar")) return bar; + if (!strcmp (str, "no")) return no_highlight; + return -1; +} + + +Lisp_Object +ns_cursor_type_to_lisp (int arg) +{ + switch (arg) + { + case filled_box: return Qbox; + case hollow_box: return intern ("hollow"); + case underscore: return intern ("underscore"); + case bar: return intern ("bar"); + case no_highlight: + default: return intern ("no"); + } +} + + +static void +ns_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ + int val; + + val = ns_lisp_to_cursor_type (arg); + if (val >= 0) + { + f->output_data.ns->desired_cursor =val; + } + else + { + store_frame_param (f, Qcursor_type, oldval); + error ("the `cursor-type' frame parameter should be either `no', `box', \ +`hollow', `underscore' or `bar'."); + } + + update_mode_lines++; +} + + +/* 23: called to set mouse pointer color, but all other terms use it to + initialize pointer types (and don't set the color ;) */ +static void +ns_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ + /* don't think we can do this on NS */ +} + + +static void +ns_icon (struct frame *f, Lisp_Object parms) +/* -------------------------------------------------------------------------- + Strangely-named function to set icon position parameters in frame. + This is irrelevant under OS X, but might be needed under GNUstep, + depending on the window manager used. Note, this is not a standard + frame parameter-setter; it is called directly from x-create-frame. + -------------------------------------------------------------------------- */ +{ + Lisp_Object icon_x, icon_y; + struct ns_display_info *dpyinfo = check_ns_display_info (Qnil); + + f->output_data.ns->icon_top = Qnil; + f->output_data.ns->icon_left = Qnil; + + /* Set the position of the icon. */ + icon_x = x_get_arg (dpyinfo, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER); + icon_y = x_get_arg (dpyinfo, 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); + f->output_data.ns->icon_top = icon_y; + f->output_data.ns->icon_left = icon_x; + } + else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound)) + error ("Both left and top icon corners of icon must be specified"); +} + + +/* 23 Note: commented out ns_... entries are no longer used in 23. + commented out x_... entries have not been implemented yet. + see frame.c for template, also where all generic OK functions are impl */ +frame_parm_handler ns_frame_parm_handlers[] = +{ + x_set_autoraise, /* generic OK */ + x_set_autolower, /* generic OK */ + ns_set_background_color, + 0, /* x_set_border_color, may be impossible under NS */ + 0, /* x_set_border_width, may be impossible under NS */ + ns_set_cursor_color, + ns_set_cursor_type, + x_set_font, /* generic OK */ + ns_set_foreground_color, + ns_set_icon_name, + ns_set_icon_type, + x_set_internal_border_width, /* generic OK */ + ns_set_menu_bar_lines, + ns_set_mouse_color, + ns_explicitly_set_name, + x_set_scroll_bar_width, /* generic OK */ + ns_set_title, + x_set_unsplittable, /* generic OK */ + x_set_vertical_scroll_bars, /* generic OK */ + x_set_visibility, /* generic OK */ + ns_set_tool_bar_lines, + 0, /* x_set_scroll_bar_foreground, will ignore (not possible on NS) */ + 0, /* x_set_scroll_bar_background, will ignore (not possible on NS) */ + x_set_screen_gamma, /* generic OK */ + x_set_line_spacing, /* generic OK, sets f->extra_line_spacing to int */ + x_set_fringe_width, /* generic OK */ + x_set_fringe_width, /* generic OK */ + 0, /* x_set_wait_for_wm, will ignore */ + 0, /* x_set_fullscreen will ignore */ + x_set_font_backend /* generic OK */ +}; + + +DEFUN ("x-create-frame", Fns_create_frame, Sns_create_frame, + 1, 1, 0, + "Make a new NS window, which is called a \"frame\" in Emacs terms.\n\ +Return an Emacs frame object representing the X window.\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.") + (parms) + Lisp_Object parms; +{ + static int desc_ctr = 1; + struct frame *f; + struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; + Lisp_Object frame, tem; + Lisp_Object name; + int minibuffer_only = 0; + int count = specpdl_ptr - specpdl; + Lisp_Object display; + struct ns_display_info *dpyinfo = NULL; + Lisp_Object parent; + struct kboard *kb; + Lisp_Object tfont, tfontsize; + int window_prompting = 0; + int width, height; + + check_ns (); + + display = x_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_STRING); + if (EQ (display, Qunbound)) + display = Qnil; + dpyinfo = check_ns_display_info (display); + + if (!dpyinfo->terminal->name) + error ("Terminal is not live, can't create new frames on it"); + + kb = dpyinfo->terminal->kboard; + + name = x_get_arg (dpyinfo, parms, Qname, 0, 0, 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; + + parent = x_get_arg (dpyinfo, parms, Qparent_id, 0, 0, RES_TYPE_NUMBER); + if (EQ (parent, Qunbound)) + parent = Qnil; + if (! NILP (parent)) + CHECK_NUMBER (parent); + + frame = Qnil; + GCPRO4 (parms, parent, name, frame); + + tem = x_get_arg (dpyinfo, 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); + } + + /* Set the name; the functions to which we pass f expect the name to + be set. */ + if (EQ (name, Qunbound) || NILP (name) || (XTYPE (name) != Lisp_String)) + { + f->name = + build_string ([[[NSProcessInfo processInfo] processName] UTF8String]); + f->explicit_name =0; + } + else + { + f->name = name; + f->explicit_name = 1; + specbind (Qx_resource_name, name); + } + + XSETFRAME (frame, f); + FRAME_CAN_HAVE_SCROLL_BARS (f) = 1; + + f->terminal = dpyinfo->terminal; + f->terminal->reference_count++; + + f->output_method = output_ns; + f->output_data.ns = (struct ns_output *)xmalloc (sizeof *(f->output_data.ns)); + bzero (f->output_data.ns, sizeof (*(f->output_data.ns))); + + FRAME_FONTSET (f) = -1; + + /* record_unwind_protect (unwind_create_frame, frame); safety; maybe later? */ + + f->icon_name = x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title", + RES_TYPE_STRING); + if (EQ (f->icon_name, Qunbound) || (XTYPE (f->icon_name) != Lisp_String)) + f->icon_name = Qnil; + + FRAME_NS_DISPLAY_INFO (f) = dpyinfo; + + f->output_data.ns->window_desc = desc_ctr++; + if (!NILP (parent)) + { + f->output_data.ns->parent_desc = (Window) XFASTINT (parent); + f->output_data.ns->explicit_parent = 1; + } + else + { + f->output_data.ns->parent_desc = FRAME_NS_DISPLAY_INFO (f)->root_window; + f->output_data.ns->explicit_parent = 0; + } + + f->resx = dpyinfo->resx; + f->resy = dpyinfo->resy; + + BLOCK_INPUT; + register_font_driver (&nsfont_driver, f); + x_default_parameter (f, parms, Qfont_backend, Qnil, + "fontBackend", "FontBackend", RES_TYPE_STRING); + + { + /* use for default font name */ + id font = [NSFont userFixedPitchFontOfSize: -1.0]; /* default */ + tfontsize = x_default_parameter (f, parms, Qfontsize, + make_number (0 /*(int)[font pointSize]*/), + "fontSize", "FontSize", RES_TYPE_NUMBER); + tfont = x_default_parameter (f, parms, Qfont, + build_string ([[font fontName] UTF8String]), + "font", "Font", RES_TYPE_STRING); + } + UNBLOCK_INPUT; + + x_default_parameter (f, parms, Qborder_width, make_number (0), + "borderwidth", "BorderWidth", RES_TYPE_NUMBER); + x_default_parameter (f, parms, Qinternal_border_width, make_number (2), + "internalBorderWidth", "InternalBorderWidth", + RES_TYPE_NUMBER); + + /* default scrollbars on right on Mac */ + { + Lisp_Object spos = +#ifdef NS_IMPL_GNUSTEP + Qt; +#else + Qright; +#endif + x_default_parameter (f, parms, Qvertical_scroll_bars, spos, + "verticalScrollBars", "VerticalScrollBars", + RES_TYPE_SYMBOL); + } + 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, Qcursor_color, build_string ("grey"), + "cursorColor", "CursorColor", RES_TYPE_STRING); + /*PENDING: not suppported yet in NS */ + 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); + /* end PENDING */ + + init_frame_faces (f); + + x_default_parameter (f, parms, Qmenu_bar_lines, make_number (0), "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); + +/*PENDING: other terms seem to get away w/o this complexity.. */ + if (NILP (Fassq (Qwidth, parms))) + { + Lisp_Object value = + x_get_arg (dpyinfo, parms, Qwidth, "width", "Width", RES_TYPE_NUMBER); + if (! EQ (value, Qunbound)) + parms = Fcons (Fcons (Qwidth, value), parms); + } + if (NILP (Fassq (Qheight, parms))) + { + Lisp_Object value = + x_get_arg (dpyinfo, parms, Qheight, "height", "Height", + RES_TYPE_NUMBER); + if (! EQ (value, Qunbound)) + parms = Fcons (Fcons (Qheight, value), parms); + } + if (NILP (Fassq (Qleft, parms))) + { + Lisp_Object value = + x_get_arg (dpyinfo, parms, Qleft, "left", "Left", RES_TYPE_NUMBER); + if (! EQ (value, Qunbound)) + parms = Fcons (Fcons (Qleft, value), parms); + } + if (NILP (Fassq (Qtop, parms))) + { + Lisp_Object value = + x_get_arg (dpyinfo, parms, Qtop, "top", "Top", RES_TYPE_NUMBER); + if (! EQ (value, Qunbound)) + parms = Fcons (Fcons (Qtop, value), parms); + } + + window_prompting = x_figure_window_size (f, parms, 1); + + tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN); + f->no_split = minibuffer_only || (!EQ (tem, Qunbound) && !EQ (tem, Qnil)); + + /* NOTE: on other terms, this is done in set_mouse_color, however this + was not getting called under NS */ + f->output_data.ns->text_cursor = [NSCursor IBeamCursor]; + f->output_data.ns->nontext_cursor = [NSCursor arrowCursor]; + f->output_data.ns->modeline_cursor = [NSCursor pointingHandCursor]; + f->output_data.ns->hand_cursor = [NSCursor pointingHandCursor]; + f->output_data.ns->hourglass_cursor = [NSCursor disappearingItemCursor]; + f->output_data.ns->horizontal_drag_cursor = [NSCursor resizeLeftRightCursor]; + FRAME_NS_DISPLAY_INFO (f)->vertical_scroll_bar_cursor = + [NSCursor arrowCursor]; + f->output_data.ns->current_pointer = f->output_data.ns->text_cursor; + + [[EmacsView alloc] initFrameFromEmacs: f]; + + ns_icon (f, parms); + + /* It is now ok to make the frame official even if we get an error below. + The frame needs to be on Vframe_list or making it visible won't work. */ + Vframe_list = Fcons (frame, Vframe_list); + /*FRAME_NS_DISPLAY_INFO (f)->reference_count++; */ + + 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); + x_default_parameter (f, parms, Qicon_type, Qnil, "bitmapIcon", "BitmapIcon", + RES_TYPE_SYMBOL); + x_default_parameter (f, parms, Qauto_raise, Qnil, "autoRaise", "AutoRaise", + RES_TYPE_BOOLEAN); + x_default_parameter (f, parms, Qauto_lower, Qnil, "autoLower", "AutoLower", + RES_TYPE_BOOLEAN); + x_default_parameter (f, parms, Qbuffered, Qt, "buffered", "Buffered", + RES_TYPE_BOOLEAN); + + width = FRAME_COLS (f); + height = FRAME_LINES (f); + + SET_FRAME_COLS (f, 0); + FRAME_LINES (f) = 0; + change_frame_size (f, height, width, 1, 0, 0); + + if (! f->output_data.ns->explicit_parent) + { + tem = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_BOOLEAN); + if (EQ (tem, Qunbound)) + tem = Qnil; + + x_set_visibility (f, tem, Qnil); + if (EQ (tem, Qt)) + [[FRAME_NS_VIEW (f) window] makeKeyWindow]; + } + + if (FRAME_HAS_MINIBUF_P (f) + && (!FRAMEP (kb->Vdefault_minibuffer_frame) + || !FRAME_LIVE_P (XFRAME (kb->Vdefault_minibuffer_frame)))) + kb->Vdefault_minibuffer_frame = frame; + + /* All remaining specified parameters, which have not been "used" + by x_get_arg and friends, now go in the misc. alist of the frame. */ + for (tem = parms; CONSP (tem); tem = XCDR (tem)) + if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem)))) + f->param_alist = Fcons (XCAR (tem), f->param_alist); + + UNGCPRO; + Vwindow_list = Qnil; + + return unbind_to (count, frame); +} + + +/* ========================================================================== + + Lisp definitions + + ========================================================================== */ + +DEFUN ("ns-focus-frame", Fns_focus_frame, Sns_focus_frame, 1, 1, 0, + doc: /* Set the input focus to FRAME. +FRAME nil means use the selected frame. */) + (frame) + Lisp_Object frame; +{ + struct frame *f = check_ns_frame (frame); + struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (f); + + if (dpyinfo->ns_focus_frame != f) + { + EmacsView *view = FRAME_NS_VIEW (f); + BLOCK_INPUT; + [[view window] makeKeyAndOrderFront: view]; + UNBLOCK_INPUT; + } + + return Qnil; +} + + +DEFUN ("ns-popup-prefs-panel", Fns_popup_prefs_panel, Sns_popup_prefs_panel, + 0, 0, "", "Pop up the preferences panel.") + () +{ + check_ns (); + [(EmacsApp *)NSApp showPreferencesWindow: NSApp]; + return Qnil; +} + + +DEFUN ("ns-popup-font-panel", Fns_popup_font_panel, Sns_popup_font_panel, + 0, 1, "", "Pop up the font panel.") + (frame) + Lisp_Object frame; +{ + id fm; + struct frame *f; + + check_ns (); + fm = [NSFontManager new]; + if (NILP (frame)) + f = SELECTED_FRAME (); + else + { + CHECK_FRAME (frame); + f = XFRAME (frame); + } + + [fm setSelectedFont: ((struct nsfont_info *)f->output_data.ns->font)->nsfont + isMultiple: NO]; + [fm orderFrontFontPanel: NSApp]; + return Qnil; +} + + +DEFUN ("ns-popup-color-panel", Fns_popup_color_panel, Sns_popup_color_panel, + 0, 1, "", "Pop up the color panel.") + (frame) + Lisp_Object frame; +{ + struct frame *f; + + check_ns (); + if (NILP (frame)) + f = SELECTED_FRAME (); + else + { + CHECK_FRAME (frame); + f = XFRAME (frame); + } + + [NSApp orderFrontColorPanel: NSApp]; + return Qnil; +} + + +DEFUN ("ns-read-file-name", Fns_read_file_name, Sns_read_file_name, 1, 4, 0, + "As read-file-name except that NS panels are used for querying, and\n\ +args are slightly different. Nil returned if no selection made.\n\ +Set ISLOAD non-nil if file being read for a save.") + (prompt, dir, isLoad, init) + Lisp_Object prompt, dir, isLoad, init; +{ + static id fileDelegate = nil; + int ret; + id panel; + NSString *fname; + + NSString *promptS = NILP (prompt) || !STRINGP (prompt) ? nil : + [NSString stringWithUTF8String: XSTRING (prompt)->data]; + NSString *dirS = NILP (dir) || !STRINGP (dir) ? + [NSString stringWithUTF8String: XSTRING (current_buffer->directory)->data] : + [NSString stringWithUTF8String: XSTRING (dir)->data]; + NSString *initS = NILP (init) || !STRINGP (init) ? nil : + [NSString stringWithUTF8String: XSTRING (init)->data]; + + check_ns (); + + if (fileDelegate == nil) + fileDelegate = [EmacsFileDelegate new]; + + [NSCursor setHiddenUntilMouseMoves: NO]; + + if ([dirS characterAtIndex: 0] == '~') + dirS = [dirS stringByExpandingTildeInPath]; + + panel = NILP (isLoad) ? + [EmacsSavePanel savePanel] : [EmacsOpenPanel openPanel]; + + [panel setTitle: promptS]; + + /* Puma (10.1) does not have */ + if ([panel respondsToSelector: @selector (setAllowsOtherFileTypes:)]) + [panel setAllowsOtherFileTypes: YES]; + + [panel setTreatsFilePackagesAsDirectories: YES]; + [panel setDelegate: fileDelegate]; + + panelOK = 0; + if (NILP (isLoad)) + { + ret = [panel runModalForDirectory: dirS file: initS]; + } + else + { + [panel setCanChooseDirectories: YES]; + ret = [panel runModalForDirectory: dirS file: initS types: nil]; + } + + ret = (ret = NSOKButton) || panelOK; + + fname = [panel filename]; + + [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow]; + + return ret ? build_string ([fname UTF8String]) : Qnil; +} + + +DEFUN ("ns-get-resource", Fns_get_resource, Sns_get_resource, 2, 2, 0, + "Return the value of the property NAME of OWNER from the defaults database.\n\ +If OWNER is nil, Emacs is assumed.") + (owner, name) + Lisp_Object owner, name; +{ + const char *value; + + check_ns (); + if (NILP (owner)) + owner = build_string + ([[[NSProcessInfo processInfo] processName] UTF8String]); + /* CHECK_STRING (owner); this should be just "Emacs" */ + CHECK_STRING (name); +/*fprintf (stderr, "ns-get-resource checking resource '%s'\n", SDATA (name)); */ + + value =[[[NSUserDefaults standardUserDefaults] + objectForKey: [NSString stringWithUTF8String: XSTRING (name)->data]] + UTF8String]; + + if (value) + return build_string (value); +/*fprintf (stderr, "Nothing found for NS resource '%s'.\n", XSTRING (name)->data); */ + return Qnil; +} + + +DEFUN ("ns-set-resource", Fns_set_resource, Sns_set_resource, 3, 3, 0, + "Set property NAME of OWNER to VALUE, from the defaults database.\n\ +If OWNER is nil, Emacs is assumed.\n\ +If VALUE is nil, the default is removed.") + (owner, name, value) + Lisp_Object owner, name, value; +{ + check_ns (); + if (NILP (owner)) + owner = + build_string ([[[NSProcessInfo processInfo] processName] UTF8String]); + CHECK_STRING (owner); + CHECK_STRING (name); + if (NILP (value)) + { + [[NSUserDefaults standardUserDefaults] removeObjectForKey: + [NSString stringWithUTF8String: XSTRING (name)->data]]; + } + else + { + CHECK_STRING (value); + [[NSUserDefaults standardUserDefaults] setObject: + [NSString stringWithUTF8String: XSTRING (value)->data] + forKey: [NSString stringWithUTF8String: + XSTRING (name)->data]]; + } + + return Qnil; +} + + +DEFUN ("ns-set-alpha", Fns_set_alpha, Sns_set_alpha, 2, 2, 0, + "Return a color same as given with alpha set to given value\n\ +from 0 to 1, where 1 is fully opaque.") + (color, alpha) + Lisp_Object color; + Lisp_Object alpha; +{ + NSColor *col; + float a; + + CHECK_STRING (color); + CHECK_NUMBER_OR_FLOAT (alpha); + + if (ns_lisp_to_color (color, &col)) + error ("Unknown color."); + + a = XFLOATINT (alpha); + if (a < 0.0 || a > 1.0) + error ("Alpha value should be between 0 and 1 inclusive."); + + col = [col colorWithAlphaComponent: a]; + return ns_color_to_lisp (col); +} + + +DEFUN ("ns-server-max-request-size", Fns_server_max_request_size, + Sns_server_max_request_size, + 0, 1, 0, + "This function is only present for completeness. It does not return\n\ +a usable result for NS windows.") + (display) + Lisp_Object display; +{ + check_ns (); + /* This function has no real equivalent under NeXTstep. Return nil to + indicate this. */ + return Qnil; +} + + +DEFUN ("ns-server-vendor", Fns_server_vendor, Sns_server_vendor, 0, 1, 0, + "Returns the vendor ID string of the NS 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; +{ + check_ns (); +#ifdef NS_IMPL_GNUSTEP + return build_string ("GNU"); +#else + return build_string ("Apple"); +#endif +} + + +DEFUN ("ns-server-version", Fns_server_version, Sns_server_version, 0, 1, 0, + "Returns the version number of the NS release of display DISPLAY.\n\ +See also the function `ns-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; +{ + /*PENDING: return GUI version on GNUSTEP, ?? on OS X */ + return build_string ("1.0"); +} + + +DEFUN ("ns-display-screens", Fns_display_screens, Sns_display_screens, 0, 1, 0, + "Returns the number of screens on the NS server of display DISPLAY.\n\ +The optional argument DISPLAY specifies which display to ask about.\n\ +DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\ +If omitted or nil, that stands for the selected frame's display.") + (display) + Lisp_Object display; +{ + int num; + + check_ns (); + num = [[NSScreen screens] count]; + + return (num != 0) ? make_number (num) : Qnil; +} + + +DEFUN ("ns-display-mm-height", Fns_display_mm_height, Sns_display_mm_height, + 0, 1, 0, + "Returns the height in millimeters of the NS display DISPLAY.\n\ +The optional argument DISPLAY specifies which display to ask about.\n\ +DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\ +If omitted or nil, that stands for the selected frame's display.") + (display) + Lisp_Object display; +{ + check_ns (); + return make_number ((int) + ([ns_get_screen (display) frame].size.height/(92.0/25.4))); +} + + +DEFUN ("ns-display-mm-width", Fns_display_mm_width, Sns_display_mm_width, + 0, 1, 0, + "Returns the width in millimeters of the NS display DISPLAY.\n\ +The optional argument DISPLAY specifies which display to ask about.\n\ +DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\ +If omitted or nil, that stands for the selected frame's display.") + (display) + Lisp_Object display; +{ + check_ns (); + return make_number ((int) + ([ns_get_screen (display) frame].size.width/(92.0/25.4))); +} + + +DEFUN ("ns-display-backing-store", Fns_display_backing_store, + Sns_display_backing_store, 0, 1, 0, + "Returns an indication of whether NS display DISPLAY does backing store.\n\ +The value may be `buffered', `retained', or `non-retained'.\n\ +The optional argument DISPLAY specifies which display to ask about.\n\ +DISPLAY should be either a frame, display name (a string), or terminal ID.\n\ +If omitted or nil, that stands for the selected frame's display.\n\ +Under NS, this may differ for each frame.") + (display) + Lisp_Object display; +{ + check_ns (); + switch ([ns_get_window (display) backingType]) + { + case NSBackingStoreBuffered: + return intern ("buffered"); + case NSBackingStoreRetained: + return intern ("retained"); + case NSBackingStoreNonretained: + return intern ("non-retained"); + default: + error ("Strange value for backingType parameter of frame"); + } + return Qnil; /* not reached, shut compiler up */ +} + + +DEFUN ("ns-display-visual-class", Fns_display_visual_class, + Sns_display_visual_class, 0, 1, 0, + "Returns the visual class of the NS 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, a display name (a string), or terminal ID.\n\ +If omitted or nil, that stands for the selected frame's display.") + (display) + Lisp_Object display; +{ + NSWindowDepth depth; + check_ns (); + depth = [ns_get_screen (display) depth]; + + if ( depth == NSBestDepth (NSCalibratedWhiteColorSpace, 2, 2, YES, NULL)) + return intern ("static-gray"); + else if (depth == NSBestDepth (NSCalibratedWhiteColorSpace, 8, 8, YES, NULL)) + return intern ("gray-scale"); + else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 8, 8, YES, NULL)) + return intern ("pseudo-color"); + else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 4, 12, NO, NULL)) + return intern ("true-color"); + else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 8, 24, NO, NULL)) + return intern ("direct-color"); + else + /* color mgmt as far as we do it is really handled by NS itself anyway */ + return intern ("direct-color"); +} + + +DEFUN ("ns-display-save-under", Fns_display_save_under, + Sns_display_save_under, 0, 1, 0, + "Returns t if the NS 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, a display name (a string), or terminal ID.\n\ +If omitted or nil, that stands for the selected frame's display.\n\ +Under NS, this may differ for each frame.") + (display) + Lisp_Object display; +{ + check_ns (); + switch ([ns_get_window (display) backingType]) + { + case NSBackingStoreBuffered: + return Qt; + + case NSBackingStoreRetained: + case NSBackingStoreNonretained: + return Qnil; + + default: + error ("Strange value for backingType parameter of frame"); + } + return Qnil; /* not reached, shut compiler up */ +} + + +DEFUN ("ns-open-connection", Fns_open_connection, Sns_open_connection, + 1, 3, 0, "Open a connection to a NS server.\n\ +DISPLAY is the name of the display to connect to.\n\ +Optional arguments XRM-STRING and MUST-SUCCEED are currently ignored.") + (display, resource_string, must_succeed) + Lisp_Object display, resource_string, must_succeed; +{ + struct ns_display_info *dpyinfo; + + CHECK_STRING (display); + + nxatoms_of_nsselect (); + dpyinfo = ns_term_init (display); + if (dpyinfo == 0) + { + if (!NILP (must_succeed)) + fatal ("OpenStep on %s not responding.\n", + XSTRING (display)->data); + else + error ("OpenStep on %s not responding.\n", + XSTRING (display)->data); + } + + /* Register our external input/output types, used for determining + applicable services and also drag/drop eligibility. */ + ns_send_types = [[NSArray arrayWithObject: NSStringPboardType] retain]; + ns_return_types = [[NSArray arrayWithObject: NSStringPboardType] retain]; + ns_drag_types = [[NSArray arrayWithObjects: + NSStringPboardType, + NSTabularTextPboardType, + NSFilenamesPboardType, + NSURLPboardType, + NSColorPboardType, + NSFontPboardType, nil] retain]; + + return Qnil; +} + + +DEFUN ("ns-close-connection", Fns_close_connection, Sns_close_connection, + 1, 1, 0, "Close the connection to the current NS server.\n\ +The second argument DISPLAY is currently ignored, but nil would stand for\n\ +the selected frame's display.") + (display) + Lisp_Object display; +{ + check_ns (); +#ifdef NS_IMPL_COCOA + PSFlush (); +#endif + /*ns_delete_terminal (dpyinfo->terminal); */ + [NSApp terminate: NSApp]; + return Qnil; +} + + +DEFUN ("ns-display-list", Fns_display_list, Sns_display_list, 0, 0, 0, + "Return the list of display names that Emacs has connections to.") + () +{ + Lisp_Object tail, result; + + result = Qnil; + for (tail = ns_display_name_list; CONSP (tail); tail = XCDR (tail)) + result = Fcons (XCAR (XCAR (tail)), result); + + return result; +} + + +DEFUN ("ns-hide-others", Fns_hide_others, Sns_hide_others, + 0, 0, 0, "Hides all applications other than emacs.") + () +{ + check_ns (); + [NSApp hideOtherApplications: NSApp]; + return Qnil; +} + +DEFUN ("ns-hide-emacs", Fns_hide_emacs, Sns_hide_emacs, + 1, 1, 0, "If ON is non-nil, the entire emacs application is hidden.\n\ +Otherwise if emacs is hidden, it is unhidden.\n\ +If ON is equal to 'activate, emacs is unhidden and becomes\n\ +the active application.") + (on) + Lisp_Object on; +{ + check_ns (); + if (EQ (on, intern ("activate"))) + { + [NSApp unhide: NSApp]; + [NSApp activateIgnoringOtherApps: YES]; + } + else if (NILP (on)) + [NSApp unhide: NSApp]; + else + [NSApp hide: NSApp]; + return Qnil; +} + + +DEFUN ("ns-emacs-info-panel", Fns_emacs_info_panel, Sns_emacs_info_panel, + 0, 0, 0, "Shows the 'Info' or 'About' panel for Emacs.") + () +{ + check_ns (); + [NSApp orderFrontStandardAboutPanel: nil]; + return Qnil; +} + + +DEFUN ("x-list-fonts", Fns_list_fonts, Sns_list_fonts, 1, 4, 0, + "Return a list of the names of available fonts matching PATTERN.\n\ +If optional arguments FACE and FRAME are specified, return only fonts\n\ +the same size as FACE on FRAME.\n\ +If optional argument MAX is specified, return at most MAX matches.\n\ +\n\ +PATTERN is a regular expression; FACE is a face name - a symbol.\n\ +\n\ +The return value is a list of strings, suitable as arguments to\n\ +set-face-font.\n\ +\n\ +The font names are _NOT_ X names.") + (pattern, face, frame, max) + Lisp_Object pattern, face, frame, max; +{ + Lisp_Object flist, olist = Qnil, tem; + struct frame *f; + int maxnames; + + /* We can't simply call check_x_frame because this function may be + called before any frame is created. */ + if (NILP (frame)) + f = SELECTED_FRAME (); + else + { + CHECK_LIVE_FRAME (frame); + f = XFRAME (frame); + } + if (! FRAME_WINDOW_P (f)) + { + /* Perhaps we have not yet created any frame. */ + f = NULL; + } + + if (NILP (max)) + maxnames = 4; + else + { + CHECK_NATNUM (max); + maxnames = XFASTINT (max); + } + + /* get XLFD names */ + flist = ns_list_fonts (f, pattern, 0, maxnames); + + /* convert list into regular names */ + for (tem = flist; CONSP (tem); tem = XCDR (tem)) + { + Lisp_Object fname = XCAR (tem); + olist = Fcons (build_string (ns_xlfd_to_fontname (XSTRING (fname)->data)), + olist); + } + + return olist; +} + + +DEFUN ("ns-font-name", Fns_font_name, Sns_font_name, 1, 1, 0, + "Determine font postscript or family name from a font name string or\n\ +XLFD string. If string contains fontset' and not 'fontset-startup' it is\n\ +left alone.") + (name) + Lisp_Object name; +{ + char *nm; + CHECK_STRING (name); + nm = SDATA (name); + + if (nm[0] != '-') + return name; + if (strstr (nm, "fontset") && !strstr (nm, "fontset-startup")) + return name; + + return build_string (ns_xlfd_to_fontname (SDATA (name))); +} + + +DEFUN ("ns-list-colors", Fns_list_colors, Sns_list_colors, 0, 1, 0, + "Return a list of all available colors.\n\ +The optional argument FRAME is currently ignored.") + (frame) + Lisp_Object frame; +{ + Lisp_Object list = Qnil; + NSEnumerator *colorlists; + NSColorList *clist; + + if (!NILP (frame)) + { + CHECK_FRAME (frame); + if (! FRAME_NS_P (XFRAME (frame))) + error ("non-NS frame used in `ns-list-colors'"); + } + + BLOCK_INPUT; + + colorlists = [[NSColorList availableColorLists] objectEnumerator]; + while (clist = [colorlists nextObject]) + { + if ([[clist name] length] < 7 || + [[clist name] rangeOfString: @"PANTONE"].location == 0) + { + NSEnumerator *cnames = [[clist allKeys] reverseObjectEnumerator]; + NSString *cname; + while (cname = [cnames nextObject]) + list = Fcons (build_string ([cname UTF8String]), list); +/* for (i = [[clist allKeys] count] - 1; i >= 0; i--) + list = Fcons (build_string ([[[clist allKeys] objectAtIndex: i] + UTF8String]), list); */ + } + } + + UNBLOCK_INPUT; + + return list; +} + + +DEFUN ("ns-list-services", Fns_list_services, Sns_list_services, 0, 0, 0, + "List NS services by querying NSApp.") + () +{ + Lisp_Object ret = Qnil; + NSMenu *svcs; + id delegate; + + check_ns (); + svcs = [[NSMenu alloc] initWithTitle: @"Services"]; + [NSApp setServicesMenu: svcs]; /* this and next rebuild on <10.4 */ + [NSApp registerServicesMenuSendTypes: ns_send_types + returnTypes: ns_return_types]; + +/* On Tiger, services menu updating was made lazier (waits for user to + actually click on the menu), so we have to force things along: */ +#ifdef NS_IMPL_COCOA + if (NSAppKitVersionNumber >= 744.0) + { + delegate = [svcs delegate]; + if (delegate != nil) + { + if ([delegate respondsToSelector: @selector (menuNeedsUpdate:)]) + [delegate menuNeedsUpdate: svcs]; + if ([delegate respondsToSelector: + @selector (menu:updateItem:atIndex:shouldCancel:)]) + { + int i, len = [delegate numberOfItemsInMenu: svcs]; + for (i =0; idata; + svcName = [NSString stringWithUTF8String: utfStr]; + + pb =[NSPasteboard pasteboardWithUniqueName]; + ns_string_to_pasteboard (pb, send); + + if (NSPerformService (svcName, pb) == NO) + Fsignal (Qquit, Fcons (build_string ("service not available"), Qnil)); + + if ([[pb types] count] == 0) + return build_string (""); + return ns_string_from_pasteboard (pb); +} + + +DEFUN ("ns-convert-utf8-nfd-to-nfc", Fns_convert_utf8_nfd_to_nfc, + Sns_convert_utf8_nfd_to_nfc, 1, 1, 0, + "Composes character sequences in UTF-8 normal form NFD string STR to produce a normal (composed normal form NFC) string.") + (str) + Lisp_Object str; +{ + NSString *utfStr; + + CHECK_STRING (str); + utfStr = [[NSString stringWithUTF8String: XSTRING (str)->data] + precomposedStringWithCanonicalMapping]; + return build_string ([utfStr UTF8String]); +} + + +/* ========================================================================== + + Miscellaneous functions not called through hooks + + ========================================================================== */ + + +/* 23: call in image.c */ +FRAME_PTR +check_x_frame (Lisp_Object frame) +{ + return check_ns_frame (frame); +} + +/* 23: added, due to call in frame.c */ +struct ns_display_info * +check_x_display_info (Lisp_Object frame) +{ + return check_ns_display_info (frame); +} + + +/* 23: new function; we don't have much in the way of flexibility though */ +void +x_set_scroll_bar_default_width (f) + struct frame *f; +{ + int wid = FRAME_COLUMN_WIDTH (f); + FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = NS_SCROLL_BAR_WIDTH_DEFAULT; + FRAME_CONFIG_SCROLL_BAR_COLS (f) = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + + wid - 1) / wid; +} + + +/* 23: terms now impl this instead of x-get-resource directly */ +const char * +x_get_string_resource (XrmDatabase rdb, char *name, char *class) +{ + /* remove appname prefix; PENDING: allow for !="Emacs" */ + char *toCheck = class + (!strncmp (class, "Emacs.", 6) ? 6 : 0); + const char *res; + check_ns (); + + /* Support emacs-20-style face resources for backwards compatibility */ + if (!strncmp (toCheck, "Face", 4)) + toCheck = name + (!strncmp (name, "emacs.", 6) ? 6 : 0); + +/*fprintf (stderr, "Checking '%s'\n", toCheck); */ + + res = [[[NSUserDefaults standardUserDefaults] objectForKey: + [NSString stringWithUTF8String: toCheck]] UTF8String]; + return !res ? NULL : + (!strncasecmp (res, "YES", 3) ? "true" : + (!strncasecmp (res, "NO", 2) ? "false" : res)); +} + + +Lisp_Object +x_get_focus_frame (struct frame *frame) +{ + struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (frame); + Lisp_Object nsfocus; + + if (!dpyinfo->ns_focus_frame) + return Qnil; + + XSETFRAME (nsfocus, dpyinfo->ns_focus_frame); + return nsfocus; +} + + +int +x_pixel_width (struct frame *f) +{ + return FRAME_PIXEL_WIDTH (f); +} + + +int +x_pixel_height (struct frame *f) +{ + return FRAME_PIXEL_HEIGHT (f); +} + + +int +x_char_width (struct frame *f) +{ + return FRAME_COLUMN_WIDTH (f); +} + + +int +x_char_height (struct frame *f) +{ + return FRAME_LINE_HEIGHT (f); +} + + +int +x_screen_planes (struct frame *f) +{ + return FRAME_NS_DISPLAY_INFO (f)->n_planes; +} + + +void +x_sync (Lisp_Object frame) +{ + /* XXX Not implemented XXX */ + return; +} + + + +/* ========================================================================== + + Lisp definitions that, for whatever reason, we can't alias as 'ns-XXX'. + + ========================================================================== */ + + +DEFUN ("xw-color-defined-p", Fns_color_defined_p, Sns_color_defined_p, 1, 2, 0, + "Return t if the current NS display supports the color named COLOR.\n\ +The optional argument FRAME is currently ignored.") + (color, frame) + Lisp_Object color, frame; +{ + NSColor * col; + check_ns (); + return ns_lisp_to_color (color, &col) ? Qnil : Qt; +} + + +DEFUN ("xw-color-values", Fns_color_values, Sns_color_values, 1, 2, 0, + "Return a description of the color named COLOR.\n\ +The value is a list of integer RGBA values--(RED GREEN BLUE ALPHA).\n\ +These values appear to range from 0 to 65280; white is (65280 65280 65280 0).\n\ +The optional argument FRAME is currently ignored.") + (color, frame) + Lisp_Object color, frame; +{ + NSColor * col; + float red, green, blue, alpha; + Lisp_Object rgba[4]; + + check_ns (); + CHECK_STRING (color); + + if (ns_lisp_to_color (color, &col)) + return Qnil; + + [[col colorUsingColorSpaceName: NSCalibratedRGBColorSpace] + getRed: &red green: &green blue: &blue alpha: &alpha]; + rgba[0] = make_number (lrint (red*65280)); + rgba[1] = make_number (lrint (green*65280)); + rgba[2] = make_number (lrint (blue*65280)); + rgba[3] = make_number (lrint (alpha*65280)); + + return Flist (4, rgba); +} + + +DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0, + "Return t if the NS display supports color.\n\ +The optional argument DISPLAY specifies which display to ask about.\n\ +DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\ +If omitted or nil, that stands for the selected frame's display.") + (display) + Lisp_Object display; +{ + NSWindowDepth depth; + NSString *colorSpace; + check_ns (); + depth = [ns_get_screen (display) depth]; + colorSpace = NSColorSpaceFromDepth (depth); + + return [colorSpace isEqualToString: NSDeviceWhiteColorSpace] + || [colorSpace isEqualToString: NSCalibratedWhiteColorSpace] + ? Qnil : Qt; +} + + +DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, + Sx_display_grayscale_p, 0, 1, 0, + "Return t if the NS 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, a display name (a string), or terminal ID.\n\ +If omitted or nil, that stands for the selected frame's display.") + (display) + Lisp_Object display; +{ + NSWindowDepth depth; + check_ns (); + depth = [ns_get_screen (display) depth]; + + return NSBitsPerPixelFromDepth (depth) > 1 ? Qt : Qnil; +} + + +DEFUN ("x-display-pixel-width", Fns_display_pixel_width, Sns_display_pixel_width, + 0, 1, 0, + "Returns the width in pixels of the NS display DISPLAY.\n\ +The optional argument DISPLAY specifies which display to ask about.\n\ +DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\ +If omitted or nil, that stands for the selected frame's display.") + (display) + Lisp_Object display; +{ + check_ns (); + return make_number ((int) [ns_get_screen (display) frame].size.width); +} + + +DEFUN ("x-display-pixel-height", Fns_display_pixel_height, + Sns_display_pixel_height, 0, 1, 0, + "Returns the height in pixels of the NS display DISPLAY.\n\ +The optional argument DISPLAY specifies which display to ask about.\n\ +DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\ +If omitted or nil, that stands for the selected frame's display.") + (display) + Lisp_Object display; +{ + check_ns (); + return make_number ((int) [ns_get_screen (display) frame].size.height); +} + +DEFUN ("display-usable-bounds", Fns_display_usable_bounds, + Sns_display_usable_bounds, 0, 1, 0, + "Returns a list of integers in form (left top width height) describing the \ +usable screen area excluding reserved areas such as the Mac menu and doc, or \ +the Windows task bar.\n \ +The optional argument DISPLAY specifies which display to ask about.\n\ +DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\ +If omitted or nil, that stands for the selected frame's display.") + (display) + Lisp_Object display; +{ + int top; + NSRect vScreen; + + check_ns (); + vScreen = [ns_get_screen (display) visibleFrame]; + top = vScreen.origin.y == 0.0 ? + (int) [ns_get_screen (display) frame].size.height - vScreen.size.height : 0; + + return list4 (make_number ((int) vScreen.origin.x), + make_number (top), + make_number ((int) vScreen.size.width), + make_number ((int) vScreen.size.height)); +} + + +DEFUN ("x-display-planes", Fx_display_planes, Sns_display_planes, + 0, 1, 0, + "Returns the number of bitplanes of the NS display DISPLAY.\n\ +The optional argument DISPLAY specifies which display to ask about.\n\ +DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\ +If omitted or nil, that stands for the selected frame's display.") + (display) + Lisp_Object display; +{ + check_ns (); + return make_number + (NSBitsPerSampleFromDepth ([ns_get_screen (display) depth])); +} + + +DEFUN ("x-display-color-cells", Fns_display_color_cells, + Sns_display_color_cells, 0, 1, 0, + "Returns the number of color cells of the NS display DISPLAY.\n\ +The optional argument DISPLAY specifies which display to ask about.\n\ +DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\ +If omitted or nil, that stands for the selected frame's display.") + (display) + Lisp_Object display; +{ + check_ns (); + struct ns_display_info *dpyinfo = check_ns_display_info (display); + + /* We force 24+ bit depths to 24-bit to prevent an overflow. */ + return make_number (1 << min (dpyinfo->n_planes, 24)); +} + + +/* Unused dummy def needed for compatibility. */ +Lisp_Object tip_frame; + +/*PENDING: move to xdisp or similar */ +static void +compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y) + struct frame *f; + Lisp_Object parms, dx, dy; + int width, height; + int *root_x, *root_y; +{ + Lisp_Object left, top; + EmacsView *view = FRAME_NS_VIEW (f); + NSPoint pt; + + /* Start with user-specified or mouse position. */ + left = Fcdr (Fassq (Qleft, parms)); + if (INTEGERP (left)) + pt.x = XINT (left); + else + pt.x = last_mouse_motion_position.x; + top = Fcdr (Fassq (Qtop, parms)); + if (INTEGERP (top)) + pt.y = XINT (top); + else + pt.y = last_mouse_motion_position.y; + + /* Convert to screen coordinates */ + pt = [view convertPoint: pt toView: nil]; + pt = [[view window] convertBaseToScreen: pt]; + + /* Ensure in bounds. (Note, screen origin = lower left.) */ + if (pt.x + XINT (dx) <= 0) + *root_x = 0; /* Can happen for negative dx */ + else if (pt.x + XINT (dx) + width <= FRAME_NS_DISPLAY_INFO (f)->width) + /* It fits to the right of the pointer. */ + *root_x = pt.x + XINT (dx); + else if (width + XINT (dx) <= pt.x) + /* It fits to the left of the pointer. */ + *root_x = pt.x - width - XINT (dx); + else + /* Put it left justified on the screen -- it ought to fit that way. */ + *root_x = 0; + + if (pt.y - XINT (dy) - height >= 0) + /* It fits below the pointer. */ + *root_y = pt.y - height - XINT (dy); + else if (pt.y + XINT (dy) + height <= FRAME_NS_DISPLAY_INFO (f)->height) + /* It fits above the pointer */ + *root_y = pt.y + XINT (dy); + else + /* Put it on the top. */ + *root_y = FRAME_NS_DISPLAY_INFO (f)->height - height; +} + + +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 PARMS contains a `left' parameter, +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). + +A tooltip's maximum size is specified by `x-max-tooltip-size'. +Text larger than the specified size is clipped. */) + (string, frame, parms, timeout, dx, dy) + Lisp_Object string, frame, parms, timeout, dx, dy; +{ + int root_x, root_y; + struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; + int count = SPECPDL_INDEX (); + struct frame *f; + char *str; + NSSize size; + + specbind (Qinhibit_redisplay, Qt); + + GCPRO4 (string, parms, frame, timeout); + + CHECK_STRING (string); + str = XSTRING (string)->data; + 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); + + BLOCK_INPUT; + if (ns_tooltip == nil) + ns_tooltip = [[EmacsTooltip alloc] init]; + else + Fx_hide_tip (); + + [ns_tooltip setText: str]; + size = [ns_tooltip frame].size; + + /* Move the tooltip window where the mouse pointer is. Resize and + show it. */ + compute_tip_xy (f, parms, dx, dy, (int)size.width, (int)size.height, + &root_x, &root_y); + + [ns_tooltip showAtX: root_x Y: root_y for: XINT (timeout)]; + UNBLOCK_INPUT; + + 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 if tooltip was open, nil otherwise. */) + () +{ + if (ns_tooltip == nil || ![ns_tooltip isActive]) + return Qnil; + [ns_tooltip hide]; + return Qt; +} + + +/* ========================================================================== + + Lisp interface declaration + + ========================================================================== */ + + +void +syms_of_nsfns () +{ + int i; + + Qns_frame_parameter = intern ("ns-frame-parameter"); + staticpro (&Qns_frame_parameter); + Qnone = intern ("none"); + staticpro (&Qnone); + Qbuffered = intern ("bufferd"); + staticpro (&Qbuffered); + Qfontsize = intern ("fontsize"); + staticpro (&Qfontsize); + + DEFVAR_LISP ("ns-icon-type-alist", &Vns_icon_type_alist, + "Alist of elements (REGEXP . IMAGE) for images of icons associated to\n\ +frames. If the title of a frame matches REGEXP, then IMAGE.tiff is\n\ +selected as the image of the icon representing the frame when it's\n\ +miniaturized. If an element is t, then Emacs tries to select an icon\n\ +based on the filetype of the visited file.\n\ +\n\ +The images have to be installed in a folder called English.lproj in the\n\ +Emacs.app folder. You have to restart Emacs after installing new icons.\n\ +\n\ +Example: Install an icon Gnus.tiff and execute the following code\n\ +\n\ + (setq ns-icon-type-alist\n\ + (append ns-icon-type-alist\n\ + '((\"^\\\\*\\\\(Group\\\\*$\\\\|Summary \\\\|Article\\\\*$\\\\)\"\n\ + . \"Gnus\"))))\n\ +\n\ +When you miniaturize a Group, Summary or Article frame, Gnus.tiff will\n\ +be used as the image of the icon representing the frame."); + Vns_icon_type_alist = Fcons (Qt, Qnil); + + defsubr (&Sns_read_file_name); + defsubr (&Sns_get_resource); + defsubr (&Sns_set_resource); + defsubr (&Sxw_display_color_p); /* this and next called directly by C code */ + defsubr (&Sx_display_grayscale_p); + defsubr (&Sns_list_fonts); + defsubr (&Sns_font_name); + defsubr (&Sns_list_colors); + defsubr (&Sns_color_defined_p); + defsubr (&Sns_color_values); + defsubr (&Sns_server_max_request_size); + defsubr (&Sns_server_vendor); + defsubr (&Sns_server_version); + defsubr (&Sns_display_pixel_width); + defsubr (&Sns_display_pixel_height); + defsubr (&Sns_display_usable_bounds); + defsubr (&Sns_display_mm_width); + defsubr (&Sns_display_mm_height); + defsubr (&Sns_display_screens); + defsubr (&Sns_display_planes); + defsubr (&Sns_display_color_cells); + defsubr (&Sns_display_visual_class); + defsubr (&Sns_display_backing_store); + defsubr (&Sns_display_save_under); + defsubr (&Sns_create_frame); + defsubr (&Sns_set_alpha); + defsubr (&Sns_open_connection); + defsubr (&Sns_close_connection); + defsubr (&Sns_display_list); + + defsubr (&Sns_hide_others); + defsubr (&Sns_hide_emacs); + defsubr (&Sns_emacs_info_panel); + defsubr (&Sns_list_services); + defsubr (&Sns_perform_service); + defsubr (&Sns_convert_utf8_nfd_to_nfc); + defsubr (&Sns_focus_frame); + defsubr (&Sns_popup_prefs_panel); + defsubr (&Sns_popup_font_panel); + defsubr (&Sns_popup_color_panel); + + defsubr (&Sx_show_tip); + defsubr (&Sx_hide_tip); + + /* used only in fontset.c */ + check_window_system_func = check_ns; + +} + + + +/* ========================================================================== + + Class implementations + + ========================================================================== */ + + +@implementation EmacsSavePanel +#ifdef NS_IMPL_COCOA +/* -------------------------------------------------------------------------- + These are overridden to intercept on OS X: ending panel restarts NSApp + event loop if it is stopped. Not sure if this is correct behavior, + perhaps should check if running and if so send an appdefined. + -------------------------------------------------------------------------- */ +- (void) ok: (id)sender +{ + [super ok: sender]; + panelOK = 1; + [NSApp stop: self]; +} +- (void) cancel: (id)sender +{ + [super cancel: sender]; + [NSApp stop: self]; +} +#endif +@end + + +@implementation EmacsOpenPanel +#ifdef NS_IMPL_COCOA +/* -------------------------------------------------------------------------- + These are overridden to intercept on OS X: ending panel restarts NSApp + event loop if it is stopped. Not sure if this is correct behavior, + perhaps should check if running and if so send an appdefined. + -------------------------------------------------------------------------- */ +- (void) ok: (id)sender +{ + [super ok: sender]; + panelOK = 1; + [NSApp stop: self]; +} +- (void) cancel: (id)sender +{ + [super cancel: sender]; + [NSApp stop: self]; +} +#endif +@end + + +@implementation EmacsFileDelegate +/* -------------------------------------------------------------------------- + Delegate methods for Open/Save panels + -------------------------------------------------------------------------- */ +- (BOOL)panel: (id)sender isValidFilename: (NSString *)filename +{ + return YES; +} +- (BOOL)panel: (id)sender shouldShowFilename: (NSString *)filename +{ + return YES; +} +- (NSString *)panel: (id)sender userEnteredFilename: (NSString *)filename + confirmed: (BOOL)okFlag +{ + return filename; +} +@end + +#endif diff -r ff312a846b25 -r d45acf0c8d23 src/nsgui.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/nsgui.h Tue Jul 15 18:15:18 2008 +0000 @@ -0,0 +1,208 @@ +/* Definitions and headers for communication on the NeXT/Open/GNUstep API. + Copyright (C) 1995, 2005, 2008 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 3, 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., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. */ + +#ifndef __NSGUI_H__ +#define __NSGUI_H__ + +/* this gets included from a couple of the plain (non-NS) .c files */ +#ifdef __OBJC__ + +#ifdef NS_IMPL_COCOA +#ifdef Z +#warning "Z is defined. If you get a later parse error in a header, check that buffer.h or other files #define-ing Z are not included." +#endif /* Z */ +#define Cursor FooFoo +#undef init_process +#endif /* NS_IMPL_COCOA */ + +#ifdef NS_IMPL_GNUSTEP +#undef hash_remove +#endif + +#import + +#ifdef NS_IMPL_GNUSTEP +#define hash_remove emacs_hash_remove +#endif + +#ifdef NS_IMPL_COCOA +#undef Cursor +#define init_process emacs_init_process +#endif /* NS_IMPL_COCOA */ +#import + +#ifdef NS_IMPL_COCOA +#include +#endif /* NS_IMPL_COCOA */ + +#endif /* __OBJC__ */ + + +/* menu-related */ +#define free_widget_value(wv) xfree (wv) +#define malloc_widget_value() ((widget_value *) memset (xmalloc \ + (sizeof (widget_value)), 0, sizeof (widget_value))) + +/* Emulate XCharStruct. */ +typedef struct _XCharStruct +{ + int rbearing; + int lbearing; + int width; + int ascent; + int descent; +} XCharStruct; + +/* 23: Fake tructure from Xlib.h to represent two-byte characters. */ +#ifndef __OBJC__ +typedef unsigned short unichar; +#endif +typedef unichar XChar2b; + +#define STORE_XCHAR2B(chp, b1, b2) \ + (*(chp) = ((XChar2b)((((b1) & 0x00ff) << 8) | ((b2) & 0x00ff)))) + +#define XCHAR2B_BYTE1(chp) \ + (((*chp) & 0xff00) >> 8) + +#define XCHAR2B_BYTE2(chp) \ + ((*chp) & 0x00ff) + +#define FACE_DEFAULT (~0) + + +/* PENDING: xfaces requires these structures, but the question is are we + forced to use them? */ +typedef struct _XGCValues +{ +#ifdef __OBJC__ + NSColor *foreground; + NSColor *background; + struct ns_font *font; +#else + void *foreground; + void *background; + void *font; +#endif +} XGCValues; + +typedef XGCValues * GC; + +#define GCForeground 0x01 +#define GCBackground 0x02 +#define GCFont 0x03 + +#ifdef __OBJC__ +typedef id Pixmap; +#else +typedef void *Pixmap; +#endif + +#ifdef __OBJC__ +typedef NSCursor * Cursor; +#else +typedef void *Cursor; +#endif + +#define No_Cursor (0) + +#ifdef __OBJC__ +typedef NSColor * Color; +#else +typedef void * Color; +#endif +typedef int Window; +typedef int Display; + +/* Xism */ +typedef Lisp_Object XrmDatabase; + + +/* 23: some sort of attempt to normalize rectangle handling.. seems a bit much + for what is accomplished */ +typedef struct { + int x, y; + unsigned width, height; +} XRectangle; + +#ifndef __OBJC__ +typedef struct _NSPoint { float x, y; } NSPoint; +typedef struct _NSSize { float width, height; } NSSize; +typedef struct _NSRect { NSPoint origin; NSSize size; } NSRect; +#endif + +#define NativeRectangle struct _NSRect + +#define CONVERT_TO_XRECT(xr, nr) \ + ((xr).x = (nr).origin.x, \ + (xr).y = (nr).origin.y, \ + (xr).width = (nr).size.width, \ + (xr).height = (nr).size.height) + +#define CONVERT_FROM_XRECT(xr, nr) \ + ((nr).origin.x = (xr).x, \ + (nr).origin.y = (xr).y, \ + (nr).size.width = (xr).width, \ + (nr).size.height = (xr).height) + +#define STORE_NATIVE_RECT(nr, px, py, pwidth, pheight) \ + ((nr).origin.x = (px), \ + (nr).origin.y = (py), \ + (nr).size.width = (pwidth), \ + (nr).size.height = (pheight)) + + + + +/* This stuff needed by frame.c. */ +#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, max aspect ratios */ +#define PBaseSize (1L << 8) /* program specified base for incrementing */ +#define PWinGravity (1L << 9) /* program specified window gravity */ + +#endif /* __NSGUI_H__ */ diff -r ff312a846b25 -r d45acf0c8d23 src/nsimage.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/nsimage.m Tue Jul 15 18:15:18 2008 +0000 @@ -0,0 +1,480 @@ +/* Image support for the NeXT/Open/GNUstep and MacOSX window system. + Copyright (C) 1989, 1992, 1993, 1994, 2005, 2006, 2008, + 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 3, 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., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. + +Originally by Carl Edman +Updated by Christian Limpach (chris@nice.ch) +OpenStep/Rhapsody port by Scott Bender (sbender@harmony-ds.com) +MacOSX/Aqua port by Christophe de Dinechin (descubes@earthlink.net) +GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu) + +*/ + +#include "config.h" +#include "lisp.h" +#include "dispextern.h" +#include "nsterm.h" +#include "frame.h" + +extern Lisp_Object QCfile, QCdata; + +/* call tracing */ +#if 0 +int image_trace_num = 0; +#define NSTRACE(x) fprintf (stderr, "%s:%d: [%d] " #x "\n", \ + __FILE__, __LINE__, ++image_trace_num) +#else +#define NSTRACE(x) +#endif + + +/* ========================================================================== + + C interface. This allows easy calling from C files. We could just + compile everything as Objective-C, but that might mean slower + compilation and possible difficulties on some platforms.. + + ========================================================================== */ + +void * +ns_image_from_XBM (unsigned char *bits, int width, int height) +{ + NSTRACE (ns_image_from_XBM); + return [[EmacsImage alloc] initFromXBM: bits + width: width height: height + flip: YES]; +} + +void * +ns_image_for_XPM (int width, int height, int depth) +{ + NSTRACE (ns_image_for_XPM); + return [[EmacsImage alloc] initForXPMWithDepth: depth + width: width height: height]; +} + +void * +ns_image_from_file (Lisp_Object file) +{ + NSTRACE (ns_image_from_bitmap_file); + return [EmacsImage allocInitFromFile: file]; +} + +int +ns_load_image (struct frame *f, struct image *img, + Lisp_Object spec_file, Lisp_Object spec_data) +{ + NSTRACE (ns_load_image); + + EmacsImage *eImg; + NSSize size; + + if (NILP (spec_data)) + { + eImg = [EmacsImage allocInitFromFile: spec_file]; + } + else + { + NSData *data = [NSData dataWithBytes: XSTRING (spec_data)->data + length: SBYTES (spec_data)]; + eImg = [[EmacsImage alloc] initWithData: data]; + [eImg setPixmapData]; + } + + if (eImg == nil) + { + add_to_log ("Unable to load image %s", img->spec, Qnil); + return 0; + } + + size = [eImg size]; + img->width = size.width; + img->height = size.height; + + /* 4) set img->pixmap = emacsimage */ + img->pixmap = eImg; + return 1; +} + + +int +ns_image_width (void *img) +{ + return [(id)img size].width; +} + +int +ns_image_height (void *img) +{ + return [(id)img size].height; +} + +unsigned long +ns_get_pixel (void *img, int x, int y) +{ + return [(EmacsImage *)img getPixelAtX: x Y: y]; +} + +void +ns_put_pixel (void *img, int x, int y, unsigned long argb) +{ + unsigned char alpha = (argb >> 24) & 0xFF; + if (alpha == 0) + alpha = 0xFF; + [(EmacsImage *)img setPixelAtX: x Y: y toRed: (argb >> 16) & 0xFF + green: (argb >> 8) & 0xFF blue: (argb & 0xFF) alpha: alpha]; +} + +void +ns_set_alpha (void *img, int x, int y, unsigned char a) +{ + [(EmacsImage *)img setAlphaAtX: x Y: y to: a]; +} + + +/* ========================================================================== + + Class supporting bitmaps and images of various sorts. + + ========================================================================== */ + +@implementation EmacsImage + +static EmacsImage *ImageList = nil; + ++ allocInitFromFile: (Lisp_Object)file +{ + EmacsImage *image = ImageList; + Lisp_Object found; + + /* look for an existing image of the same name */ + while (image != nil && + [[image name] compare: [NSString stringWithUTF8String: SDATA (file)]] + != NSOrderedSame) + image = [image imageListNext]; + + if (image != nil) + { + [image reference]; + return image; + } + + /* Search bitmap-file-path for the file, if appropriate. */ + found = x_find_image_file (file); + if (!STRINGP (found)) + return nil; + + image = [[EmacsImage alloc] initByReferencingFile: + [NSString stringWithUTF8String: SDATA (found)]]; + + if ([image bestRepresentationForDevice: nil] == nil) + { + [image release]; + return nil; + } + + [image setName: [NSString stringWithUTF8String: SDATA (file)]]; + [image reference]; + ImageList = [image imageListSetNext: ImageList]; + + return image; +} + + +- reference +{ + refCount++; + return self; +} + + +- imageListSetNext: (id)arg +{ + imageListNext = arg; + return self; +} + + +- imageListNext +{ + return imageListNext; +} + + +- (void)dealloc +{ + id list = ImageList; + + if (refCount > 1) + { + refCount--; + return; + } + + [stippleMask release]; + + if (list == self) + ImageList = imageListNext; + else + { + while (list != nil && [list imageListNext] != self) + list = [list imageListNext]; + [list imageListSetNext: imageListNext]; + } + + [super dealloc]; +} + + +- initFromXBM: (unsigned char *)bits width: (int)w height: (int)h + flip: (BOOL)flip +{ + return [self initFromSkipXBM: bits width: w height: h flip: flip length: 0]; +} + + +- initFromSkipXBM: (unsigned char *)bits width: (int)w height: (int)h + flip: (BOOL)flip length: (int)length; +{ + int bpr = (w + 7) / 8; + unsigned char *planes[5]; + + [self initWithSize: NSMakeSize (w, h)]; + + bmRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes: NULL + pixelsWide: w pixelsHigh: h + bitsPerSample: 8 samplesPerPixel: 4 + hasAlpha: YES isPlanar: YES + colorSpaceName: NSCalibratedRGBColorSpace + bytesPerRow: w bitsPerPixel: 0]; + + [bmRep getBitmapDataPlanes: planes]; + { + /* pull bits out to set the (bytewise) alpha mask */ + int i, j, k; + unsigned char *s = bits; + unsigned char *alpha = planes[3]; + unsigned char swt[16] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, + 3, 11, 7, 15}; + unsigned char c, bitPat; + + for (j = 0; j < h; j++) + for (i = 0; i < bpr; i++) + { + if (length) + { + unsigned char s1, s2; + while (*s++ != 'x' && s < bits + length); + if (s >= bits + length) + { + [bmRep release]; + return nil; + } +#define hexchar(x) (isdigit (x) ? x - '0' : x - 'a' + 10) + s1 = *s++; + s2 = *s++; + c = hexchar (s1) * 0x10 + hexchar (s2); + } + else + c = *s++; + + bitPat = flip ? swt[c >> 4] | (swt[c & 0xf] << 4) : c ^ 255; + for (k =0; k<8; k++) + { + *alpha++ = (bitPat & 0x80) ? 0xff : 0; + bitPat <<= 1; + } + } + } + + [self addRepresentation: bmRep]; + + bzero (planes[0], w*h); + bzero (planes[1], w*h); + bzero (planes[2], w*h); + [self setXBMColor: [NSColor blackColor]]; + return self; +} + + +/* Set color for a bitmap image (see initFromSkipXBM). Note that the alpha + is used as a mask, so we just memset the entire array. */ +- setXBMColor: (NSColor *)color +{ + NSSize s = [self size]; + int len = (int) s.width * s.height; + unsigned char *planes[5]; + float r, g, b, a; + NSColor *rgbColor; + + if (bmRep == nil || color == nil) + return; + + if ([color colorSpaceName] != NSCalibratedRGBColorSpace) + rgbColor = [color colorUsingColorSpaceName: NSCalibratedRGBColorSpace]; + else + rgbColor = color; + + [rgbColor getRed: &r green: &g blue: &b alpha: &a]; + + [bmRep getBitmapDataPlanes: planes]; + + /* we used to just do this, but Cocoa seems to have a bug when rendering + an alpha-masked image onto a dark background where it bloats the mask */ + /* memset (planes[0..2], r, g, b*0xff, len); */ + { + int i, len = s.width*s.height; + int rr = r * 0xff, gg = g * 0xff, bb = b * 0xff; + for (i =0; i= 3) + [bmRep getBitmapDataPlanes: pixmapData]; + break; + } + } +} + + +/* note; this and next work only for image created with initForXPMWithDepth, + initFromSkipXBM, or where setPixmapData was called successfully */ +/* return ARGB */ +- (unsigned long) getPixelAtX: (int)x Y: (int)y +{ + if (bmRep == nil) + return 0; + + /* this method is faster but won't work for bitmaps */ + if (pixmapData[0] != NULL) + { + int loc = x + y * [self size].width; + return (pixmapData[3][loc] << 24) /* alpha */ + | (pixmapData[0][loc] << 16) | (pixmapData[1][loc] << 8) + | (pixmapData[2][loc]); + } + else if (onTiger) + { + NSColor *color = [bmRep colorAtX: x y: y]; + float r, g, b, a; + [color getRed: &r green: &g blue: &b alpha: &a]; + return ((int)(a * 255.0) << 24) + | ((int)(r * 255.0) << 16) | ((int)(g * 255.0) << 8) + | ((int)(b * 255.0)); + + } + return 0; +} + +- (void) setPixelAtX: (int)x Y: (int)y toRed: (unsigned char)r + green: (unsigned char)g blue: (unsigned char)b + alpha:(unsigned char)a; +{ + if (bmRep == nil) + return; + + if (pixmapData[0] != NULL) + { + int loc = x + y * [self size].width; + pixmapData[0][loc] = r; + pixmapData[1][loc] = g; + pixmapData[2][loc] = b; + pixmapData[3][loc] = a; + } + else if (onTiger) + { + [bmRep setColor: + [NSColor colorWithCalibratedRed: r green: g blue: b alpha: a] + atX: x y: y]; + } +} + +- (void) setAlphaAtX: (int) x Y: (int) y to: (unsigned char) a +{ + if (bmRep == nil) + return; + + if (pixmapData[0] != NULL) + { + int loc = x + y * [self size].width; + + pixmapData[3][loc] = a; + } + else if (onTiger) + { + NSColor *color = [bmRep colorAtX: x y: y]; + color = [color colorWithAlphaComponent: (a / 255.0)]; + [bmRep setColor: color atX: x y: y]; + } +} + +/* returns a pattern color, which is cached here */ +- (NSColor *)stippleMask +{ + if (stippleMask == nil) + stippleMask = [[NSColor colorWithPatternImage: self] retain]; + return stippleMask; +} + +@end diff -r ff312a846b25 -r d45acf0c8d23 src/nsmenu.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/nsmenu.m Tue Jul 15 18:15:18 2008 +0000 @@ -0,0 +1,1948 @@ +/* NeXT/Open/GNUstep and MacOSX Cocoa menu and toolbar module. + Copyright (C) 2007, 2008 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 3, 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, 675 Mass Ave, Cambridge, MA 02139, USA. + +By Adrian Robert, based on code from original nsmenu.m (Carl Edman, +Christian Limpach, Scott Bender, Christophe de Dinechin) and code in the +Carbon version by Yamamoto Mitsuharu. */ + +#include "config.h" +#include "lisp.h" +#include "window.h" +#include "buffer.h" +#include "keymap.h" +#include "coding.h" +#include "commands.h" +#include "blockinput.h" +#include "nsterm.h" +#include "termhooks.h" +#include "keyboard.h" + +/* for profiling */ +#include +#include + +#define MenuStagger 10.0 + +#if 0 +int menu_trace_num = 0; +#define NSTRACE(x) fprintf (stderr, "%s:%d: [%d] " #x "\n", \ + __FILE__, __LINE__, ++menu_trace_num) +#else +#define NSTRACE(x) +#endif + +#if 0 +/* Include lisp -> C common menu parsing code */ +#define ENCODE_MENU_STRING(str) ENCODE_UTF_8 (str) +#include "nsmenu_common.c" +#endif + +extern struct widget_value; + +extern Lisp_Object Qundefined, Qmenu_enable, Qmenu_bar_update_hook; +extern Lisp_Object QCtoggle, QCradio; + +extern Lisp_Object Vmenu_updating_frame; + +Lisp_Object Qdebug_on_next_call; +extern Lisp_Object Voverriding_local_map, Voverriding_local_map_menu_flag, + Qoverriding_local_map, Qoverriding_terminal_local_map; + +extern long context_menu_value; +EmacsMenu *mainMenu, *svcsMenu; + +/* NOTE: toolbar implementation is at end, + following complete menu implementation. */ + + +/* ========================================================================== + + Menu: Externally-called functions + + ========================================================================== */ + + +/*23: PENDING: not currently used, but should normalize with other terms. */ +void +x_activate_menubar (struct frame *f) +{ + fprintf (stderr, "XXX: Received x_activate_menubar event.\n"); +} + + +/* Supposed to discard menubar and free storage. Since we share the + menubar among frames and update its context for the focused window, + there is nothing to do here. */ +void +free_frame_menubar (struct frame *f) +{ + return; +} + + +/* -------------------------------------------------------------------------- + Update menubar. Three cases: + 1) deep_p = 0, submenu = nil: Fresh switch onto a frame -- either set up + just top-level menu strings (OS X), or goto case (2) (GNUstep). + 2) deep_p = 1, submenu = nil: Recompute all submenus. + 3) deep_p = 1, submenu = non-nil: Update contents of a single submenu. + -------------------------------------------------------------------------- */ +/*#define NSMENUPROFILE 1 */ +void +ns_update_menubar (struct frame *f, int deep_p, EmacsMenu *submenu) +{ + NSAutoreleasePool *pool; + id menu = [NSApp mainMenu]; + static EmacsMenu *last_submenu = nil; + BOOL needsSet = NO; + const char *submenuTitle = [[submenu title] UTF8String]; + extern int waiting_for_input; + int owfi; + Lisp_Object items; + widget_value *wv, *first_wv, *prev_wv = 0; + int i; + +#ifdef NSMENUPROFILE + struct timeb tb; + long t; +#endif + + NSTRACE (set_frame_menubar); + + if (f != SELECTED_FRAME ()) + return; + XSETFRAME (Vmenu_updating_frame, f); +/*fprintf (stderr, "ns_update_menubar: frame: %p\tdeep: %d\tsub: %p\n", f, deep_p, submenu); */ + + BLOCK_INPUT; + pool = [[NSAutoreleasePool alloc] init]; + + /* Menu may have been created automatically; if so, discard it. */ + if ([menu isKindOfClass: [EmacsMenu class]] == NO) + { + [menu release]; + menu = nil; + } + + if (menu == nil) + { + menu = [[EmacsMenu alloc] initWithTitle: @"Emacs"]; + needsSet = YES; + } + else + { /* close up anything on there */ + id attMenu = [menu attachedMenu]; + if (attMenu != nil) + [attMenu close]; + } + +#ifdef NSMENUPROFILE + ftime (&tb); + t = -(1000*tb.time+tb.millitm); +#endif + + /* widget_value is a straightforward object translation of emacs's + Byzantine lisp menu structures */ + wv = xmalloc_widget_value (); + wv->name = "Emacs"; + wv->value = 0; + wv->enabled = 1; + wv->button_type = BUTTON_TYPE_NONE; + wv->help = Qnil; + first_wv = wv; + +#ifdef NS_IMPL_GNUSTEP + deep_p = 1; /* until GNUstep NSMenu implements the Panther delegation model */ +#endif + + if (deep_p) + { + /* Fully parse one or more of the submenus. */ + int n = 0; + int *submenu_start, *submenu_end; + int *submenu_top_level_items, *submenu_n_panes; + struct buffer *prev = current_buffer; + Lisp_Object buffer; + int specpdl_count = SPECPDL_INDEX (); + int previous_menu_items_used = f->menu_bar_items_used; + Lisp_Object *previous_items + = (Lisp_Object *) alloca (previous_menu_items_used + * sizeof (Lisp_Object)); + + /* lisp preliminaries */ + buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer; + specbind (Qinhibit_quit, Qt); + specbind (Qdebug_on_next_call, Qnil); + record_unwind_save_match_data (); + if (NILP (Voverriding_local_map_menu_flag)) + { + specbind (Qoverriding_terminal_local_map, Qnil); + specbind (Qoverriding_local_map, Qnil); + } + set_buffer_internal_1 (XBUFFER (buffer)); + + /* PENDING: for some reason this is not needed in other terms, + but some menu updates call Info-extract-pointer which causes + abort-on-error if waiting-for-input. Needs further investigation. */ + owfi = waiting_for_input; + waiting_for_input = 0; + + /* lucid hook and possible reset */ + safe_run_hooks (Qactivate_menubar_hook); + 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)); + + /* Now ready to go */ + items = FRAME_MENU_BAR_ITEMS (f); + + /* 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)); + + /* parse stage 1: extract from lisp */ + save_menu_items (); + + menu_items = f->menu_bar_vector; + menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0; + submenu_start = (int *) alloca (XVECTOR (items)->size * sizeof (int *)); + submenu_end = (int *) alloca (XVECTOR (items)->size * sizeof (int *)); + submenu_n_panes = (int *) alloca (XVECTOR (items)->size * sizeof (int)); + submenu_top_level_items + = (int *) alloca (XVECTOR (items)->size * sizeof (int *)); + 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; + + /* PENDING: we'd like to only parse the needed submenu, but this + was causing crashes in the _common parsing code.. need to make + sure proper initialization done.. */ +/* if (submenu && strcmp (submenuTitle, SDATA (string))) + continue; */ + + submenu_start[i] = menu_items_used; + + menu_items_n_panes = 0; + submenu_top_level_items[i] = parse_single_submenu (key, string, maps); + submenu_n_panes[i] = menu_items_n_panes; + submenu_end[i] = menu_items_used; + n++; + } + + finish_menu_items (); + waiting_for_input = owfi; + + + if (submenu && n == 0) + { + /* should have found a menu for this one but didn't */ + fprintf (stderr, "ERROR: did not find lisp menu for submenu '%s'.\n", + submenuTitle); + discard_menu_items (); + unbind_to (specpdl_count, Qnil); + [pool release]; + UNBLOCK_INPUT; + return; + } + + /* parse stage 2: insert into lucid 'widget_value' structures + [comments in other terms say not to evaluate lisp code here] */ + 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; + + for (i = 0; i < 4*n; i += 4) + { + menu_items_n_panes = submenu_n_panes[i]; + wv = digest_single_submenu (submenu_start[i], submenu_end[i], + submenu_top_level_items[i]); + 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; + } + + set_buffer_internal_1 (prev); + + /* Compare the new menu items with previous, and leave off if no change */ + /* PENDING: following other terms here, but seems like this should be + done before parse stage 2 above, since its results aren't used */ + if (previous_menu_items_used + && (!submenu || (submenu && submenu == last_submenu)) + && menu_items_used == previous_menu_items_used) + { + for (i = 0; i < previous_menu_items_used; i++) + /* PENDING: this ALWAYS fails on Buffers menu items.. something + about their strings causes them to change every time, so we + double-check failures */ + if (!EQ (previous_items[i], XVECTOR (menu_items)->contents[i])) + if (!(STRINGP (previous_items[i]) + && STRINGP (XVECTOR (menu_items)->contents[i]) + && !strcmp (SDATA (previous_items[i]), + SDATA (XVECTOR (menu_items)->contents[i])))) + break; + if (i == previous_menu_items_used) + { + /* No change.. */ + +#ifdef NSMENUPROFILE + ftime (&tb); + t += 1000*tb.time+tb.millitm; + fprintf (stderr, "NO CHANGE! CUTTING OUT after %ld msec.\n", t); +#endif + + free_menubar_widget_value_tree (first_wv); + discard_menu_items (); + unbind_to (specpdl_count, Qnil); + [pool release]; + UNBLOCK_INPUT; + return; + } + } + /* The menu items are different, so store them in the frame */ + /* PENDING: this is not correct for single-submenu case */ + f->menu_bar_vector = menu_items; + f->menu_bar_items_used = menu_items_used; + + /* Calls restore_menu_items, etc., as they were outside */ + unbind_to (specpdl_count, Qnil); + + /* Parse stage 2a: 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; +/* if (submenu && strcmp (submenuTitle, SDATA (string))) + continue; */ + + wv->name = (char *) SDATA (string); + update_submenu_strings (wv->contents); + wv = wv->next; + } + + /* Now, update the NS menu; if we have a submenu, use that, otherwise + create a new menu for each sub and fill it. */ + if (submenu) + { + for (wv = first_wv->contents; wv; wv = wv->next) + { + if (!strcmp (submenuTitle, wv->name)) + { + [submenu fillWithWidgetValue: wv->contents]; + last_submenu = submenu; + break; + } + } + } + else + { + [menu fillWithWidgetValue: first_wv->contents]; + } + + } + else + { + static int n_previous_strings = 0; + static char previous_strings[100][10]; + static struct frame *last_f = NULL; + int n; + Lisp_Object string; + + /* Make widget-value tree w/ just the top level menu bar strings */ + items = FRAME_MENU_BAR_ITEMS (f); + if (NILP (items)) + { + [pool release]; + UNBLOCK_INPUT; + return; + } + + + /* check if no change.. this mechanism is a bit rough, but ready */ + n = XVECTOR (items)->size / 4; + if (f == last_f && n_previous_strings == n) + { + for (i = 0; icontents[4*i+1]; + + if (!string) + continue; + if (NILP (string)) + if (previous_strings[i][0]) + break; + else + continue; + if (strncmp (previous_strings[i], SDATA (string), 10)) + break; + } + + if (i == n) + { + [pool release]; + UNBLOCK_INPUT; + return; + } + } + + [menu clear]; + for (i = 0; i < XVECTOR (items)->size; i += 4) + { + string = XVECTOR (items)->contents[i + 1]; + if (NILP (string)) + break; + + if (n < 100) + strncpy (previous_strings[i/4], SDATA (string), 10); + + wv = xmalloc_widget_value (); + wv->name = (char *) SDATA (string); + wv->value = 0; + wv->enabled = 1; + wv->button_type = BUTTON_TYPE_NONE; + wv->help = Qnil; + wv->call_data = (void *) (EMACS_INT) (-1); + +#ifdef NS_IMPL_COCOA + /* we'll update the real copy under app menu when time comes */ + if (!strcmp ("Services", wv->name)) + { + /* but we need to make sure it will update on demand */ + [svcsMenu setFrame: f]; + [svcsMenu setDelegate: svcsMenu]; + } + else +#endif + [menu addSubmenuWithTitle: wv->name forFrame: f]; + + if (prev_wv) + prev_wv->next = wv; + else + first_wv->contents = wv; + prev_wv = wv; + } + + last_f = f; + if (n < 100) + n_previous_strings = n; + else + n_previous_strings = 0; + + } + free_menubar_widget_value_tree (first_wv); + + +#ifdef NSMENUPROFILE + ftime (&tb); + t += 1000*tb.time+tb.millitm; + fprintf (stderr, "Menu update took %ld msec.\n", t); +#endif + + /* set main menu */ + if (needsSet) + [NSApp setMainMenu: menu]; + + [pool release]; + UNBLOCK_INPUT; + +} + + +/* Main emacs core entry point for menubar menus: called to indicate that the + frame's menus have changed, and the *step representation should be updated + from Lisp. */ +void +set_frame_menubar (struct frame *f, int first_time, int deep_p) +{ + ns_update_menubar (f, deep_p, nil); +} + + +/* Utility (from macmenu.c): is this item a separator? */ +static int +name_is_separator (name) + const char *name; +{ + const 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); +} + + +/* ========================================================================== + + Menu: class implementation + + ========================================================================== */ + + +/* Menu that can define itself from Emacs "widget_value"s and will lazily + update itself when user clicked. Based on Carbon/AppKit implementation + by Yamamoto Mitsuharu. */ +@implementation EmacsMenu + +/* override designated initializer */ +- initWithTitle: (NSString *)title +{ + if (self = [super initWithTitle: title]) + [self setAutoenablesItems: NO]; + return self; +} + + +/* used for top-level */ +- initWithTitle: (NSString *)title frame: (struct frame *)f +{ + [self initWithTitle: title]; + frame = f; +#ifdef NS_IMPL_COCOA + [self setDelegate: self]; +#endif + return self; +} + + +- (void)setFrame: (struct frame *)f +{ + frame = f; +} + + +/* delegate method called when a submenu is being opened: run a 'deep' call + to set_frame_menubar */ +- (void)menuNeedsUpdate: (NSMenu *)menu +{ + NSEvent *event = [[FRAME_NS_VIEW (frame) window] currentEvent]; + /* HACK: Cocoa/Carbon will request update on every keystroke + via IsMenuKeyEvent -> CheckMenusForKeyEvent. These are not needed + since key equivalents are handled through emacs. + On Leopard, even keystroke events generate SystemDefined events, but + their subtype is 8. */ + if ([event type] != NSSystemDefined || [event subtype] == 8) + return; +/*fprintf (stderr, "Updating menu '%s'\n", [[self title] UTF8String]); NSLog (@"%@\n", event); */ + ns_update_menubar (frame, 1, self); +} + + +- (BOOL)performKeyEquivalent: (NSEvent *)theEvent +{ + if (SELECTED_FRAME () && FRAME_NS_P (SELECTED_FRAME ()) + && FRAME_NS_VIEW (SELECTED_FRAME ())) + [FRAME_NS_VIEW (SELECTED_FRAME ()) keyDown: theEvent]; + return YES; +} + + +/* parse a wdiget_value's key rep (examples: 's-p', 's-S', '(C-x C-s)', '') + into an accelerator string */ +-(NSString *)parseKeyEquiv: (char *)key +{ + char *tpos = key; + keyEquivModMask = 0; + /* currently we just parse 'super' combinations; + later we'll set keyEquivModMask */ + if (!key || !strlen (key)) + return @""; + + while (*tpos == ' ' || *tpos == '(') + tpos++; + if (*tpos != 's'/* || tpos[3] != ')'*/) + return @""; + return [NSString stringWithFormat: @"%c", tpos[2]]; +} + +- (id )addItemWithWidgetValue: (void *)wvptr +{ + id item; + widget_value *wv = (widget_value *)wvptr; + + if (name_is_separator (wv->name)) + { + item = [NSMenuItem separatorItem]; + [self addItem: item]; + } + else + { + NSString *title, *keyEq; + title = [NSString stringWithUTF8String: wv->name]; + if (title == nil) + title = @"< ? >"; /* (get out in the open so we know about it) */ + + keyEq = [self parseKeyEquiv: wv->key]; + + item = [self addItemWithTitle: (NSString *)title + action: @selector (menuDown:) + keyEquivalent: keyEq]; + if (keyEquivModMask) + [item setKeyEquivalentModifierMask: keyEquivModMask]; + + [item setEnabled: wv->enabled]; + + /* Draw radio buttons and tickboxes */ + if (wv->selected && (wv->button_type == BUTTON_TYPE_TOGGLE || + wv->button_type == BUTTON_TYPE_RADIO)) + [item setState: NSOnState]; + else + [item setState: NSOffState]; + + [item setTag: (int)wv->call_data]; + } + + return item; +} + + +/* convenience */ +-(void) clear +{ + int n; + + for (n = [self numberOfItems]-1; n >= 0; n--) + { + NSMenuItem *item = [self itemAtIndex: n]; + NSString *title = [item title]; + if (([title length] == 0 || [@"Apple" isEqualToString: title]) + && ![item isSeparatorItem]) + continue; + [self removeItemAtIndex: n]; + } +} + + +- (void)fillWithWidgetValue: (void *)wvptr +{ + widget_value *wv = (widget_value *)wvptr; + + /* clear existing contents */ + [self setMenuChangedMessagesEnabled: NO]; + [self clear]; + + /* add new contents */ + for (; wv != NULL; wv = wv->next) + { + id item = [self addItemWithWidgetValue: wv]; + + if (wv->contents) + { + EmacsMenu *submenu = [[EmacsMenu alloc] initWithTitle: @"Submenu"]; + + [self setSubmenu: submenu forItem: item]; + [submenu fillWithWidgetValue: wv->contents]; + [submenu release]; + [item setAction: nil]; + } + } + + [self setMenuChangedMessagesEnabled: YES]; +#ifdef NS_IMPL_GNUSTEP + if ([[self window] isVisible]) + [self sizeToFit]; +#else + if ([self supermenu] == nil) + [self sizeToFit]; +#endif +} + + +/* adds an empty submenu and returns it */ +- (EmacsMenu *)addSubmenuWithTitle: (char *)title forFrame: (struct frame *)f +{ + NSString *titleStr = [NSString stringWithUTF8String: title]; + id item = + [self addItemWithTitle: titleStr + action: nil /*@selector (menuDown:) */ + keyEquivalent: @""]; + EmacsMenu *submenu = [[EmacsMenu alloc] initWithTitle: titleStr frame: f]; + [self setSubmenu: submenu forItem: item]; + [submenu release]; + return submenu; +} + +/* run a menu in popup mode */ +- (Lisp_Object)runMenuAt: (NSPoint)p forFrame: (struct frame *)f + keymaps: (int)keymaps +{ + EmacsView *view = FRAME_NS_VIEW (f); +/* p = [view convertPoint:p fromView: nil]; */ + p.y = NSHeight ([view frame]) - p.y; + NSEvent *e = [[view window] currentEvent]; + NSEvent *event = [NSEvent mouseEventWithType: NSRightMouseDown + location: p + modifierFlags: 0 + timestamp: [e timestamp] + windowNumber: [[view window] windowNumber] + context: [e context] + eventNumber: 0/*[e eventNumber] */ + clickCount: 1 + pressure: 0]; + long retVal; + + context_menu_value = -1; + [NSMenu popUpContextMenu: self withEvent: event forView: view]; + retVal = context_menu_value; + context_menu_value = 0; + return retVal > 0 ? + find_and_return_menu_selection (f, keymaps, (void *)retVal) : Qnil; +} + +@end /* EmacsMenu */ + + + +/* ========================================================================== + + Context Menu: implementing functions + + ========================================================================== */ + +static Lisp_Object +cleanup_popup_menu (Lisp_Object arg) +{ + discard_menu_items (); + return Qnil; +} + + +static Lisp_Object +ns_popup_menu (Lisp_Object position, Lisp_Object menu) +{ + EmacsMenu *pmenu; + struct frame *f = NULL; + NSPoint p; + Lisp_Object window, x, y, tem, keymap, title; + struct gcpro gcpro1; + int specpdl_count = SPECPDL_INDEX (), specpdl_count2; + char *error_name = NULL; + int keymaps = 0; + widget_value *wv, *first_wv = 0; + + NSTRACE (ns_popup_menu); + + if (!NILP (position)) + { + check_ns (); + + if (EQ (position, Qt) + || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar) + || EQ (XCAR (position), Qtool_bar)))) + { + /* Use the mouse's current position. */ + struct frame *new_f = SELECTED_FRAME (); + + if (FRAME_TERMINAL (new_f)->mouse_position_hook) + (*FRAME_TERMINAL (new_f)->mouse_position_hook) + (&new_f, 0, 0, 0, &x, &y, 0); + if (new_f != 0) + XSETFRAME (window, new_f); + else + { + window = selected_window; + x = make_number (0); + y = make_number (0); + } + } + else + { + CHECK_CONS (position); + tem = Fcar (position); + if (XTYPE (tem) == Lisp_Cons) + { + window = Fcar (Fcdr (position)); + x = Fcar (tem); + y = Fcar (Fcdr (tem)); + } + else + { + tem = Fcar (Fcdr (position)); + window = Fcar (tem); + tem = Fcar (Fcdr (Fcdr (tem))); + x = Fcar (tem); + y = Fcdr (tem); + } + } + + CHECK_NUMBER (x); + CHECK_NUMBER (y); + + if (FRAMEP (window)) + { + f = XFRAME (window); + + p.x = 0; + p.y = 0; + } + else + { + struct window *win = XWINDOW (window); + CHECK_LIVE_WINDOW (window); + f = XFRAME (WINDOW_FRAME (win)); + p.x = FRAME_COLUMN_WIDTH (f) * WINDOW_LEFT_EDGE_COL (win); + p.y = FRAME_LINE_HEIGHT (f) * WINDOW_TOP_EDGE_LINE (win); + } + + p.x += XINT (x); p.y += XINT (y); + + XSETFRAME (Vmenu_updating_frame, f); + } + else + { /* no position given */ + /* PENDING: if called during dump, we need to stop precomputation of + key equivalents (see below) because the keydefs in ns-win.el have + not been loaded yet. */ + if (noninteractive) + return Qnil; + Vmenu_updating_frame = Qnil; + } + + /* now parse the lisp menus */ + record_unwind_protect (unuse_menu_items, Qnil); + 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); + title = NILP (prompt) ? build_string ("Select") : 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 = XCDR (tem)) + { + Lisp_Object prompt; + + maps[i++] = keymap = get_keymap (XCAR (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; + } + + unbind_to (specpdl_count, Qnil); + + /* If no position given, that was a signal to just precompute and cache + key equivalents, which was a side-effect of what we just did. */ + if (NILP (position)) + { + discard_menu_items (); + UNGCPRO; + return Qnil; + } + + record_unwind_protect (cleanup_popup_menu, Qnil); + BLOCK_INPUT; + + /* now parse stage 2 as in ns_update_menubar */ + wv = xmalloc_widget_value (); + wv->name = "contextmenu"; + wv->value = 0; + wv->enabled = 1; + wv->button_type = BUTTON_TYPE_NONE; + wv->help = Qnil; + first_wv = wv; + + specpdl_count2 = SPECPDL_INDEX (); + +#if 0 + /*PENDING: a couple of one-line differences prevent reuse */ + wv = digest_single_submenu (0, menu_items_used, Qnil); +#else + { + widget_value *save_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 = 1; + int i; + + /* 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_MENU_STRING (pane_name); + ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name); + } +#endif + pane_string = (NILP (pane_name) + ? "" : (char *) SDATA (pane_name)); + /* 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_MENU_STRING (item_name); + ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name); + } + + if (STRINGP (descrip) && STRING_MULTIBYTE (descrip)) + { + descrip = ENCODE_MENU_STRING (descrip); + ASET (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 *) SDATA (item_name); + if (!NILP (descrip)) + wv->key = (char *) SDATA (descrip); + wv->value = 0; + /* If this item has a null value, + make the call_data null so that it won't display a box + when the mouse is on it. */ + wv->call_data = + !NILP (def) ? (void *) &XVECTOR (menu_items)->contents[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; + } + } + } +#endif + + 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_MENU_STRING (title); +#endif + + wv_title->name = (char *) SDATA (title); + wv_title->enabled = NULL; + wv_title->button_type = BUTTON_TYPE_NONE; + wv_title->help = Qnil; + wv_title->next = wv_sep; + first_wv->contents = wv_title; + } + + pmenu = [[EmacsMenu alloc] initWithTitle: + [NSString stringWithUTF8String: SDATA (title)]]; + [pmenu fillWithWidgetValue: first_wv->contents]; + free_menubar_widget_value_tree (first_wv); + unbind_to (specpdl_count2, Qnil); + + tem = [pmenu runMenuAt: p forFrame: f keymaps: keymaps]; + [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow]; + + UNBLOCK_INPUT; + unbind_to (specpdl_count, Qnil); + UNGCPRO; + + if (error_name) error (error_name); + return tem; +} + + + + +/* ========================================================================== + + Toolbar: externally-called functions + + ========================================================================== */ + +void +free_frame_tool_bar (FRAME_PTR f) +/* -------------------------------------------------------------------------- + Under NS we just hide the toolbar until it might be needed again. + -------------------------------------------------------------------------- */ +{ + [[FRAME_NS_VIEW (f) toolbar] setVisible: NO]; +} + +void +update_frame_tool_bar (FRAME_PTR f) +/* -------------------------------------------------------------------------- + Update toolbar contents + -------------------------------------------------------------------------- */ +{ + int i; + EmacsToolbar *toolbar = [FRAME_NS_VIEW (f) toolbar]; + + if (NILP (f->tool_bar_lines) || !INTEGERP (f->tool_bar_lines)) + return; + + [toolbar clearActive]; + + /* update EmacsToolbar as in GtkUtils, build items list */ + for (i = 0; i < f->n_tool_bar_items; ++i) + { +#define TOOLPROP(IDX) AREF (f->tool_bar_items, \ + i * TOOL_BAR_ITEM_NSLOTS + (IDX)) + + BOOL enabled_p = !NILP (TOOLPROP (TOOL_BAR_ITEM_ENABLED_P)); + BOOL selected_p = !NILP (TOOLPROP (TOOL_BAR_ITEM_SELECTED_P)); + int idx; + int img_id; + struct image *img; + Lisp_Object image; + Lisp_Object helpObj; + char *helpText; + + /* If image is a vector, choose the image according to the + button state. */ + image = TOOLPROP (TOOL_BAR_ITEM_IMAGES); + if (VECTORP (image)) + { + /* NS toolbar auto-computes disabled and selected images */ + idx = TOOL_BAR_IMAGE_ENABLED_SELECTED; + xassert (ASIZE (image) >= idx); + image = AREF (image, idx); + } + else + { + idx = -1; + } + /* Ignore invalid image specifications. */ + if (!valid_image_p (image)) + { + NSLog (@"Invalid image for toolbar item"); + continue; + } + + img_id = lookup_image (f, image); + img = IMAGE_FROM_ID (f, img_id); + prepare_image_for_display (f, img); + + if (img->load_failed_p || img->pixmap == nil) + { + NSLog (@"Could not prepare toolbar image for display."); + continue; + } + + helpObj = TOOLPROP (TOOL_BAR_ITEM_HELP); + if (NILP (helpObj)) + helpObj = TOOLPROP (TOOL_BAR_ITEM_CAPTION); + helpText = NILP (helpObj) ? "" : (char *)SDATA (helpObj); + + [toolbar addDisplayItemWithImage: img->pixmap idx: i helpText: helpText + enabled: enabled_p]; +#undef TOOLPROP + } + + if (![toolbar isVisible]) + [toolbar setVisible: YES]; + + if ([toolbar changed]) + { + /* inform app that toolbar has changed */ + NSDictionary *dict = [toolbar configurationDictionary]; + NSMutableDictionary *newDict = [dict mutableCopy]; + NSEnumerator *keys = [[dict allKeys] objectEnumerator]; + NSObject *key; + while ((key = [keys nextObject]) != nil) + { + NSObject *val = [dict objectForKey: key]; + if ([val isKindOfClass: [NSArray class]]) + { + [newDict setObject: + [toolbar toolbarDefaultItemIdentifiers: toolbar] + forKey: key]; + break; + } + } + [toolbar setConfigurationFromDictionary: newDict]; + [newDict release]; + } + +} + + +/* ========================================================================== + + Toolbar: class implementation + + ========================================================================== */ + +@implementation EmacsToolbar + +- initForView: (EmacsView *)view withIdentifier: (NSString *)identifier +{ + self = [super initWithIdentifier: identifier]; + emacsView = view; + [self setDisplayMode: NSToolbarDisplayModeIconOnly]; + [self setSizeMode: NSToolbarSizeModeSmall]; + [self setDelegate: self]; + identifierToItem = [[NSMutableDictionary alloc] initWithCapacity: 10]; + activeIdentifiers = [[NSMutableArray alloc] initWithCapacity: 8]; + prevEnablement = enablement = 0L; + return self; +} + +- (void)dealloc +{ + [prevIdentifiers release]; + [activeIdentifiers release]; + [identifierToItem release]; + [super dealloc]; +} + +- (void) clearActive +{ + [prevIdentifiers release]; + prevIdentifiers = [activeIdentifiers copy]; + [activeIdentifiers removeAllObjects]; + prevEnablement = enablement; + enablement = 0L; +} + +- (BOOL) changed +{ + return [activeIdentifiers isEqualToArray: prevIdentifiers] && + enablement == prevEnablement ? NO : YES; +} + +- (void) addDisplayItemWithImage: (EmacsImage *)img idx: (int)idx + helpText: (char *)help enabled: (BOOL)enabled +{ + /* 1) come up w/identifier */ + NSString *identifier = + [NSString stringWithFormat: @"%u", [img hash]]; + + /* 2) create / reuse item */ + NSToolbarItem *item = [identifierToItem objectForKey: identifier]; + if (item == nil) + { + item = [[[NSToolbarItem alloc] initWithItemIdentifier: identifier] + autorelease]; + [item setImage: img]; + [item setToolTip: [NSString stringWithCString: help]]; + [item setTarget: emacsView]; + [item setAction: @selector (toolbarClicked:)]; + } + + [item setTag: idx]; + [item setEnabled: enabled]; + + /* 3) update state */ + [identifierToItem setObject: item forKey: identifier]; + [activeIdentifiers addObject: identifier]; + enablement = (enablement << 1) | (enabled == YES); +} + +/* This overrides super's implementation, which automatically sets + all items to enabled state (for some reason). */ +- (void)validateVisibleItems { } + + +/* delegate methods */ + +- (NSToolbarItem *)toolbar: (NSToolbar *)toolbar + itemForItemIdentifier: (NSString *)itemIdentifier + willBeInsertedIntoToolbar: (BOOL)flag +{ + /* look up NSToolbarItem by identifier and return... */ + return [identifierToItem objectForKey: itemIdentifier]; +} + +- (NSArray *)toolbarDefaultItemIdentifiers: (NSToolbar *)toolbar +{ + /* return entire set.. */ + return activeIdentifiers; +} + +/* for configuration palette (not yet supported) */ +- (NSArray *)toolbarAllowedItemIdentifiers: (NSToolbar *)toolbar +{ + /* return entire set... */ + return [identifierToItem allKeys]; +} + +/* optional and unneeded */ +/* - toolbarWillAddItem: (NSNotification *)notification { } */ +/* - toolbarDidRemoveItem: (NSNotification *)notification { } */ +/* - (NSArray *)toolbarSelectableItemIdentifiers: (NSToolbar *)toolbar */ + +@end /* EmacsToolbar */ + + + +/* ========================================================================== + + Tooltip: class implementation + + ========================================================================== */ + +/* Needed because NeXTstep does not provide enough control over tooltip + display. */ +@implementation EmacsTooltip + +- init +{ + NSColor *col = [NSColor colorWithCalibratedRed: 1.0 green: 1.0 + blue: 0.792 alpha: 0.95]; + NSFont *font = [NSFont toolTipsFontOfSize: 0]; + NSFont *sfont = [font screenFont]; + int height = [sfont ascender] - [sfont descender]; +/*[font boundingRectForFont].size.height; */ + NSRect r = NSMakeRect (0, 0, 100, height+6); + + textField = [[NSTextField alloc] initWithFrame: r]; + [textField setFont: font]; + [textField setBackgroundColor: col]; + + [textField setEditable: NO]; + [textField setSelectable: NO]; + [textField setBordered: YES]; + [textField setBezeled: YES]; + [textField setDrawsBackground: YES]; + + win = [[NSWindow alloc] + initWithContentRect: [textField frame] + styleMask: 0 + backing: NSBackingStoreBuffered + defer: YES]; + [win setReleasedWhenClosed: NO]; + [win setDelegate: self]; + [[win contentView] addSubview: textField]; +/* [win setBackgroundColor: col]; */ + [win setOpaque: NO]; + + return self; +} + +- (void) dealloc +{ + [win close]; + [win release]; + [textField release]; + [super dealloc]; +} + +- (void) setText: (char *)text +{ + NSString *str = [NSString stringWithUTF8String: text]; + NSRect r = [textField frame]; + r.size.width = [[[textField font] screenFont] widthOfString: str] + 8; + [textField setFrame: r]; + [textField setStringValue: str]; +} + +- (void) showAtX: (int)x Y: (int)y for: (int)seconds +{ + NSRect wr = [win frame]; + + wr.origin = NSMakePoint (x, y); + wr.size = [textField frame].size; + + [win setFrame: wr display: YES]; + [win orderFront: self]; + [win display]; + timer = [NSTimer scheduledTimerWithTimeInterval: (float)seconds target: self + selector: @selector (hide) + userInfo: nil repeats: NO]; + [timer retain]; +} + +- (void) hide +{ + [win close]; + if (timer != nil) + { + if ([timer isValid]) + [timer invalidate]; + [timer release]; + timer = nil; + } +} + +- (BOOL) isActive +{ + return timer != nil; +} + +- (NSRect) frame +{ + return [textField frame]; +} + +@end /* EmacsTooltip */ + + + +/* ========================================================================== + + Popup Dialog: implementing functions + + ========================================================================== */ + +Lisp_Object +ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header) +{ + id dialog; + Lisp_Object window, tem; + struct frame *f; + NSPoint p; + BOOL isQ; + + NSTRACE (x-popup-dialog); + + check_ns (); + + isQ = NILP (header); + + if (EQ (position, Qt)) + { + window = selected_window; + } + else if (CONSP (position)) + { + Lisp_Object tem; + tem = Fcar (position); + if (XTYPE (tem) == Lisp_Cons) + window = Fcar (Fcdr (position)); + else + { + tem = Fcar (Fcdr (position)); /* EVENT_START (position) */ + window = Fcar (tem); /* POSN_WINDOW (tem) */ + } + } + else if (FRAMEP (position)) + { + window = position; + } + else + { + CHECK_LIVE_WINDOW (position); + window = position; + } + + if (FRAMEP (window)) + f = XFRAME (window); + else + { + CHECK_LIVE_WINDOW (window); + f = XFRAME (WINDOW_FRAME (XWINDOW (window))); + } + p.x = (int)f->left_pos + ((int)FRAME_COLUMN_WIDTH (f) * f->text_cols)/2; + p.y = (int)f->top_pos + (FRAME_LINE_HEIGHT (f) * f->text_lines)/2; + dialog = [[EmacsDialogPanel alloc] initFromContents: contents + isQuestion: isQ]; + + tem = [dialog runDialogAt: p]; + + [dialog close]; + + [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow]; + return tem; +} + + +/* ========================================================================== + + Popup Dialog: class implementation + + ========================================================================== */ + +@interface FlippedView : NSView +{ +} +@end + +@implementation FlippedView +- (BOOL)isFlipped +{ + return YES; +} +@end + +@implementation EmacsDialogPanel + +#define SPACER 8.0 +#define ICONSIZE 64.0 +#define TEXTHEIGHT 20.0 +#define MINCELLWIDTH 90.0 + +- initWithContentRect: (NSRect)contentRect styleMask: (unsigned int)aStyle + backing: (NSBackingStoreType)backingType defer: (BOOL)flag +{ + NSSize spacing = {SPACER, SPACER}; + NSRect area; + char this_cmd_name[80]; + id cell, tem; + static NSImageView *imgView; + static FlippedView *contentView; + + if (imgView == nil) + { + NSImage *img; + area.origin.x = 3*SPACER; + area.origin.y = 2*SPACER; + area.size.width = ICONSIZE; + area.size.height= ICONSIZE; + img = [[NSImage imageNamed: @"NSApplicationIcon"] copy]; + [img setScalesWhenResized: YES]; + [img setSize: NSMakeSize (ICONSIZE, ICONSIZE)]; + imgView = [[NSImageView alloc] initWithFrame: area]; + [imgView setImage: img]; + [imgView setEditable: NO]; + [img release]; + } + + aStyle = NSTitledWindowMask; + flag = YES; + rows = 0; + cols = 1; + [super initWithContentRect: contentRect styleMask: aStyle + backing: backingType defer: flag]; + contentView = [[FlippedView alloc] initWithFrame: [[self contentView] frame]]; + [self setContentView: contentView]; + + [[self contentView] setAutoresizesSubviews: YES]; + + [[self contentView] addSubview: imgView]; + [self setTitle: @""]; + + area.origin.x += ICONSIZE+2*SPACER; +/* area.origin.y = TEXTHEIGHT; ICONSIZE/2-10+SPACER; */ + area.size.width = 400; + area.size.height= TEXTHEIGHT; + command = [[[NSTextField alloc] initWithFrame: area] autorelease]; + [[self contentView] addSubview: command]; + [command setStringValue: @"Emacs"]; + [command setDrawsBackground: NO]; + [command setBezeled: NO]; + [command setSelectable: NO]; + [command setFont: [NSFont boldSystemFontOfSize: 13.0]]; + +/* area.origin.x = ICONSIZE+2*SPACER; + area.origin.y = TEXTHEIGHT + 2*SPACER; + area.size.width = 400; + area.size.height= 2; + tem = [[[NSBox alloc] initWithFrame: area] autorelease]; + [[self contentView] addSubview: tem]; + [tem setTitlePosition: NSNoTitle]; + [tem setAutoresizingMask: NSViewWidthSizable];*/ + +/* area.origin.x = ICONSIZE+2*SPACER; */ + area.origin.y += TEXTHEIGHT+SPACER; + area.size.width = 400; + area.size.height= TEXTHEIGHT; + title = [[[NSTextField alloc] initWithFrame: area] autorelease]; + [[self contentView] addSubview: title]; + [title setDrawsBackground: NO]; + [title setBezeled: NO]; + [title setSelectable: NO]; + [title setFont: [NSFont systemFontOfSize: 11.0]]; + + cell = [[[NSButtonCell alloc] initTextCell: @""] autorelease]; + [cell setBordered: NO]; + [cell setEnabled: NO]; + [cell setCellAttribute: NSCellIsInsetButton to: 8]; + [cell setBezelStyle: NSRoundedBezelStyle]; + + matrix = [[NSMatrix alloc] initWithFrame: contentRect + mode: NSHighlightModeMatrix + prototype: cell + numberOfRows: 0 + numberOfColumns: 1]; + [[self contentView] addSubview: matrix]; + [matrix release]; + [matrix setFrameOrigin: NSMakePoint (area.origin.x, + area.origin.y + (TEXTHEIGHT+3*SPACER))]; + [matrix setIntercellSpacing: spacing]; + + [self setOneShot: YES]; + [self setReleasedWhenClosed: YES]; + [self setHidesOnDeactivate: YES]; + return self; +} + + +- (BOOL)windowShouldClose: (id)sender +{ + [NSApp stopModalWithCode: Qnil]; + return NO; +} + + +void process_dialog (id window, Lisp_Object list) +{ + Lisp_Object item; + int row = 0; + + for (; XTYPE (list) == Lisp_Cons; list = XCDR (list)) + { + item = XCAR (list); + if (XTYPE (item) == Lisp_String) + { + [window addString: XSTRING (item)->data row: row++]; + } + else if (XTYPE (item) == Lisp_Cons) + { + [window addButton: XSTRING (XCAR (item))->data + value: XCDR (item) row: row++]; + } + else if (NILP (item)) + { + [window addSplit]; + row = 0; + } + } +} + + +- addButton: (char *)str value: (Lisp_Object)val row: (int)row +{ + id cell; + + if (row >= rows) + { + [matrix addRow]; + rows++; + } + cell = [matrix cellAtRow: row column: cols-1]; + [cell setTarget: self]; + [cell setAction: @selector (clicked: )]; + [cell setTitle: [NSString stringWithUTF8String: str]]; + [cell setTag: (int)val]; + [cell setBordered: YES]; + [cell setEnabled: YES]; + + return self; +} + + +- addString: (char *)str row: (int)row +{ + id cell; + + if (row >= rows) + { + [matrix addRow]; + rows++; + } + cell = [matrix cellAtRow: row column: cols-1]; + [cell setTitle: [NSString stringWithUTF8String: str]]; + [cell setBordered: YES]; + [cell setEnabled: NO]; + + return self; +} + + +- addSplit +{ + [matrix addColumn]; + cols++; + return self; +} + + +- clicked: sender +{ + NSArray *sellist = nil; + Lisp_Object seltag; + + sellist = [sender selectedCells]; + if ([sellist count]<1) + return self; + + seltag = (Lisp_Object)[[sellist objectAtIndex: 0] tag]; + if (! EQ (seltag, Qundefined)) + [NSApp stopModalWithCode: seltag]; + return self; +} + + +- initFromContents: (Lisp_Object)contents isQuestion: (BOOL)isQ +{ + Lisp_Object head; + [super init]; + + if (XTYPE (contents) == Lisp_Cons) + { + head = Fcar (contents); + process_dialog (self, Fcdr (contents)); + } + else + head = contents; + + if (XTYPE (head) == Lisp_String) + [title setStringValue: + [NSString stringWithUTF8String: XSTRING (head)->data]]; + else if (isQ == YES) + [title setStringValue: @"Question"]; + else + [title setStringValue: @"Information"]; + + { + int i; + NSRect r, s, t; + + if (cols == 1 && rows > 1) /* Never told where to split */ + { + [matrix addColumn]; + for (i = 0; i t.size.width+t.origin.x) + { + t.origin.x = r.origin.x; + t.size.width = r.size.width; + } + r = [command frame]; + if (r.size.width+r.origin.x > t.size.width+t.origin.x) + { + t.origin.x = r.origin.x; + t.size.width = r.size.width; + } + + r = [self frame]; + s = [(NSView *)[self contentView] frame]; + r.size.width += t.origin.x+t.size.width +2*SPACER-s.size.width; + r.size.height += t.origin.y+t.size.height+SPACER-s.size.height; + [self setFrame: r display: NO]; + } + + return self; +} + + +- (void)dealloc +{ + { [super dealloc]; return; }; +} + + +- (Lisp_Object)runDialogAt: (NSPoint)p +{ + NSEvent *e; + NSModalSession session; + int ret; + + [self center]; /*XXX p ignored? */ + [self orderFront: NSApp]; + + session = [NSApp beginModalSessionForWindow: self]; + while ((ret = [NSApp runModalSession: session]) == NSRunContinuesResponse) + { + (e = [NSApp nextEventMatchingMask: NSAnyEventMask + untilDate: [NSDate distantFuture] + inMode: NSEventTrackingRunLoopMode + dequeue: NO]); +/*fprintf (stderr, "ret = %d\te = %p\n", ret, e); */ + } + [NSApp endModalSession: session]; + + return (Lisp_Object)ret; +} + +@end + + + +/* ========================================================================== + + Lisp definitions + + ========================================================================== */ + +DEFUN ("ns-reset-menu", Fns_reset_menu, Sns_reset_menu, 0, 0, 0, + "Cause the NS menu to be re-calculated.") + () +{ + set_frame_menubar (SELECTED_FRAME (), 1, 0); + return Qnil; +} + + +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\ +\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\ +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\ +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.") + (position, menu) + Lisp_Object position, menu; +{ + return ns_popup_menu (position, menu); +} + + +DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 3, 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 (DIALOG 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.) + +If HEADER is non-nil, the frame title for the box is "Information", +otherwise it is "Question". + +If the user gets rid of the dialog box without making a valid choice, +for instance using the window manager, then this produces a quit and +`x-popup-dialog' does not return. */) + (position, contents, header) + Lisp_Object position, contents, header; +{ + return ns_popup_dialog (position, contents, header); +} + + +/* ========================================================================== + + Lisp interface declaration + + ========================================================================== */ + +void +syms_of_nsmenu () +{ + defsubr (&Sx_popup_menu); + defsubr (&Sx_popup_dialog); + defsubr (&Sns_reset_menu); + staticpro (&menu_items); + menu_items = Qnil; + + Qdebug_on_next_call = intern ("debug-on-next-call"); + staticpro (&Qdebug_on_next_call); +} diff -r ff312a846b25 -r d45acf0c8d23 src/nsselect.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/nsselect.m Tue Jul 15 18:15:18 2008 +0000 @@ -0,0 +1,624 @@ +/* NeXT/Open/GNUstep / MacOSX Cocoa selection processing for emacs. + Copyright (C) 1993, 1994, 2005, 2006, 2008, + 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 3, 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., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. + +Originally by Carl Edman +Updated by Christian Limpach (chris@nice.ch) +OpenStep/Rhapsody port by Scott Bender (sbender@harmony-ds.com) +MacOSX/Aqua port by Christophe de Dinechin (descubes@earthlink.net) +GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu) + +*/ + +#include "config.h" +#include "lisp.h" +#include "nsterm.h" +#include "termhooks.h" + +#define CUT_BUFFER_SUPPORT + +Lisp_Object QPRIMARY, QSECONDARY, QTEXT, QFILE_NAME; + +static Lisp_Object Vns_sent_selection_hooks; +static Lisp_Object Vns_lost_selection_hooks; +static Lisp_Object Vselection_alist; +static Lisp_Object Vselection_converter_alist; + +/* 23: new */ +/* Coding system for communicating with other programs. */ +static Lisp_Object Vselection_coding_system; +/* Coding system for the next communicating with other programs. */ +static Lisp_Object Vnext_selection_coding_system; +static Lisp_Object Qforeign_selection; + +NSString *NXSecondaryPboard; + + + +/* ========================================================================== + + Internal utility functions + + ========================================================================== */ + + +static NSString * +symbol_to_nsstring (Lisp_Object sym) +{ + CHECK_SYMBOL (sym); + if (EQ (sym, QPRIMARY)) return NSGeneralPboard; + if (EQ (sym, QSECONDARY)) return NXSecondaryPboard; + if (EQ (sym, QTEXT)) return NSStringPboardType; + return [NSString stringWithUTF8String: XSTRING (XSYMBOL (sym)->xname)->data]; +} + + +static Lisp_Object +ns_string_to_symbol (NSString *t) +{ + if ([t isEqualToString: NSGeneralPboard]) + return QPRIMARY; + if ([t isEqualToString: NXSecondaryPboard]) + return QSECONDARY; + if ([t isEqualToString: NSStringPboardType]) + return QTEXT; + if ([t isEqualToString: NSFilenamesPboardType]) + return QFILE_NAME; + if ([t isEqualToString: NSTabularTextPboardType]) + return QTEXT; + return intern ([t UTF8String]); +} + + +static Lisp_Object +clean_local_selection_data (Lisp_Object obj) +{ + if (CONSP (obj) + && INTEGERP (XCAR (obj)) + && CONSP (XCDR (obj)) + && INTEGERP (XCAR (XCDR (obj))) + && NILP (XCDR (XCDR (obj)))) + obj = Fcons (XCAR (obj), XCDR (obj)); + + if (CONSP (obj) + && INTEGERP (XCAR (obj)) + && INTEGERP (XCDR (obj))) + { + if (XINT (XCAR (obj)) == 0) + return XCDR (obj); + if (XINT (XCAR (obj)) == -1) + return make_number (- XINT (XCDR (obj))); + } + + if (VECTORP (obj)) + { + int i; + int size = XVECTOR (obj)->size; + Lisp_Object copy; + + if (size == 1) + return clean_local_selection_data (XVECTOR (obj)->contents [0]); + copy = Fmake_vector (size, Qnil); + for (i = 0; i < size; i++) + XVECTOR (copy)->contents [i] + = clean_local_selection_data (XVECTOR (obj)->contents [i]); + return copy; + } + + return obj; +} + + +static void +ns_declare_pasteboard (id pb) +{ + [pb declareTypes: ns_send_types owner: NSApp]; +} + + +static void +ns_undeclare_pasteboard (id pb) +{ + [pb declareTypes: [NSArray array] owner: nil]; +} + + +static void +ns_string_to_pasteboard_internal (id pb, Lisp_Object str, NSString *gtype) +{ + if (EQ (str, Qnil)) + { + [pb declareTypes: [NSArray array] owner: nil]; + } + else + { + char *utfStr; + NSString *type, *nsStr; + NSEnumerator *tenum; + + CHECK_STRING (str); + + utfStr = XSTRING (str)->data; + nsStr = [NSString stringWithUTF8String: utfStr]; + + if (gtype == nil) + { + [pb declareTypes: ns_send_types owner: nil]; + tenum = [ns_send_types objectEnumerator]; + while ( (type = [tenum nextObject]) ) + [pb setString: nsStr forType: type]; + } + else + { + [pb setString: nsStr forType: gtype]; + } + } +} + + +static Lisp_Object +ns_get_local_selection (Lisp_Object selection_name, + Lisp_Object target_type) +{ + Lisp_Object local_value; + Lisp_Object handler_fn, value, type, check; + int count; + + local_value = assq_no_quit (selection_name, Vselection_alist); + + if (NILP (local_value)) return Qnil; + + count = specpdl_ptr - specpdl; + specbind (Qinhibit_quit, Qt); + CHECK_SYMBOL (target_type); + handler_fn = Fcdr (Fassq (target_type, Vselection_converter_alist)); + if (!NILP (handler_fn)) + value =call3 (handler_fn, selection_name, target_type, + XCAR (XCDR (local_value))); + else + value =Qnil; + unbind_to (count, Qnil); + + check =value; + if (CONSP (value) && SYMBOLP (XCAR (value))) + { + type = XCAR (value); + check = XCDR (value); + } + + if (STRINGP (check) || VECTORP (check) || SYMBOLP (check) + || INTEGERP (check) || NILP (value)) + return value; + + if (CONSP (check) + && INTEGERP (XCAR (check)) + && (INTEGERP (XCDR (check))|| + (CONSP (XCDR (check)) + && INTEGERP (XCAR (XCDR (check))) + && NILP (XCDR (XCDR (check)))))) + return value; + + Fsignal (Qquit, Fcons (build_string ( + "invalid data returned by selection-conversion function"), + Fcons (handler_fn, Fcons (value, Qnil)))); +} + + +static Lisp_Object +ns_get_foreign_selection (Lisp_Object symbol, Lisp_Object target) +{ + id pb; + pb =[NSPasteboard pasteboardWithName: symbol_to_nsstring (symbol)]; + return ns_string_from_pasteboard (pb); +} + + +static void +ns_handle_selection_request (struct input_event *event) +{ + id pb =(id)event->x; + NSString *type =(NSString *)event->y; + Lisp_Object selection_name, selection_data, target_symbol, data; + Lisp_Object successful_p, rest; + + selection_name =ns_string_to_symbol ([(NSPasteboard *)pb name]); + target_symbol =ns_string_to_symbol (type); + selection_data = assq_no_quit (selection_name, Vselection_alist); + successful_p =Qnil; + + if (!NILP (selection_data)) + { + data = ns_get_local_selection (selection_name, target_symbol); + if (!NILP (data)) + { + if (STRINGP (data)) + ns_string_to_pasteboard_internal (pb, data, type); + successful_p =Qt; + } + } + + if (!EQ (Vns_sent_selection_hooks, Qunbound)) + { + for (rest =Vns_sent_selection_hooks;CONSP (rest); rest =Fcdr (rest)) + call3 (Fcar (rest), selection_name, target_symbol, successful_p); + } +} + + +static void +ns_handle_selection_clear (struct input_event *event) +{ + id pb = (id)event->x; + Lisp_Object selection_name, selection_data, rest; + + selection_name =ns_string_to_symbol ([(NSPasteboard *)pb name]); + selection_data =assq_no_quit (selection_name, Vselection_alist); + if (NILP (selection_data)) return; + + if (EQ (selection_data, Fcar (Vselection_alist))) + Vselection_alist = Fcdr (Vselection_alist); + else + { + for (rest = Vselection_alist; !NILP (rest); rest = Fcdr (rest)) + if (EQ (selection_data, Fcar (Fcdr (rest)))) + Fsetcdr (rest, Fcdr (Fcdr (rest))); + } + + if (!EQ (Vns_lost_selection_hooks, Qunbound)) + { + for (rest =Vns_lost_selection_hooks;CONSP (rest); rest =Fcdr (rest)) + call1 (Fcar (rest), selection_name); + } +} + + + +/* ========================================================================== + + Functions used externally + + ========================================================================== */ + + +Lisp_Object +ns_string_from_pasteboard (id pb) +{ + NSString *type, *str; + const char *utfStr; + + type = [pb availableTypeFromArray: ns_return_types]; + if (type == nil) + { + Fsignal (Qquit, + Fcons (build_string ("empty or unsupported pasteboard type"), + Qnil)); + return Qnil; + } + + /* get the string */ + if (! (str = [pb stringForType: type])) + { + NSData *data = [pb dataForType: type]; + if (data != nil) + str = [[NSString alloc] initWithData: data + encoding: NSUTF8StringEncoding]; + if (str != nil) + { + [str autorelease]; + } + else + { + Fsignal (Qquit, + Fcons (build_string ("pasteboard doesn't contain valid data"), + Qnil)); + return Qnil; + } + } + + /* assume UTF8 */ + NS_DURING + { + /* EOL conversion: PENDING- is this too simple? */ + NSMutableString *mstr = [[str mutableCopy] autorelease]; + [mstr replaceOccurrencesOfString: @"\r\n" withString: @"\n" + options: NSLiteralSearch range: NSMakeRange (0, [mstr length])]; + [mstr replaceOccurrencesOfString: @"\r" withString: @"\n" + options: NSLiteralSearch range: NSMakeRange (0, [mstr length])]; + + utfStr = [mstr UTF8String]; + if (!utfStr) + utfStr = [mstr cString]; + } + NS_HANDLER + { + message1 ("ns_string_from_pasteboard: UTF8String failed\n"); + utfStr = [str lossyCString]; + } + NS_ENDHANDLER + + return build_string (utfStr); +} + + +void +ns_string_to_pasteboard (id pb, Lisp_Object str) +{ + ns_string_to_pasteboard_internal (pb, str, nil); +} + + + +/* ========================================================================== + + Lisp Defuns + + ========================================================================== */ + + +DEFUN ("ns-own-selection-internal", Fns_own_selection_internal, + Sns_own_selection_internal, 2, 2, 0, "Assert a selection.") + (selection_name, selection_value) + Lisp_Object selection_name, selection_value; +{ + id pb; + Lisp_Object old_value, new_value; + + check_ns (); + CHECK_SYMBOL (selection_name); + if (NILP (selection_value)) + error ("selection-value may not be nil."); + pb =[NSPasteboard pasteboardWithName: symbol_to_nsstring (selection_name)]; + ns_declare_pasteboard (pb); + old_value =assq_no_quit (selection_name, Vselection_alist); + new_value = Fcons (selection_name, Fcons (selection_value, Qnil)); + if (NILP (old_value)) + Vselection_alist =Fcons (new_value, Vselection_alist); + else + Fsetcdr (old_value, Fcdr (new_value)); + /* XXX An evil hack, but a necessary one I fear XXX */ + { + struct input_event ev; + ev.kind = SELECTION_REQUEST_EVENT; + ev.modifiers = 0; + ev.code = 0; + ev.x = (int)pb; + ev.y = (int)NSStringPboardType; + ns_handle_selection_request (&ev); + } + return selection_value; +} + + +DEFUN ("ns-disown-selection-internal", Fns_disown_selection_internal, + Sns_disown_selection_internal, 1, 2, 0, + "If we own the selection SELECTION, disown it.") + (selection_name, time) + Lisp_Object selection_name, time; +{ + id pb; + check_ns (); + CHECK_SYMBOL (selection_name); + if (NILP (assq_no_quit (selection_name, Vselection_alist))) return Qnil; + + pb =[NSPasteboard pasteboardWithName: symbol_to_nsstring (selection_name)]; + ns_undeclare_pasteboard (pb); + return Qt; +} + + +DEFUN ("ns-selection-exists-p", Fns_selection_exists_p, Sns_selection_exists_p, + 0, 1, 0, "Whether there is an owner for the given 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.)\n\ +For convenience, the symbol nil is the same as `PRIMARY',\n\ +and t is the same as `SECONDARY'.)") + (selection) + Lisp_Object selection; +{ + id pb; + NSArray *types; + + check_ns (); + CHECK_SYMBOL (selection); + if (EQ (selection, Qnil)) selection = QPRIMARY; + if (EQ (selection, Qt)) selection = QSECONDARY; + pb =[NSPasteboard pasteboardWithName: symbol_to_nsstring (selection)]; + types =[pb types]; + return ([types count] == 0) ? Qnil : Qt; +} + + +DEFUN ("ns-selection-owner-p", Fns_selection_owner_p, Sns_selection_owner_p, + 0, 1, 0, + "Whether the current Emacs process owns the given 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.)\n\ +For convenience, the symbol nil is the same as `PRIMARY',\n\ +and t is the same as `SECONDARY'.)") + (selection) + Lisp_Object selection; +{ + check_ns (); + CHECK_SYMBOL (selection); + if (EQ (selection, Qnil)) selection = QPRIMARY; + if (EQ (selection, Qt)) selection = QSECONDARY; + return (NILP (Fassq (selection, Vselection_alist))) ? Qnil : Qt; +} + + +DEFUN ("ns-get-selection-internal", Fns_get_selection_internal, + Sns_get_selection_internal, 2, 2, 0, + "Return text selected from some pasteboard.\n\ +SELECTION is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\ +\(Those are literal upper-case symbol names.)\n\ +TYPE is the type of data desired, typically `STRING'.") + (selection_name, target_type) + Lisp_Object selection_name, target_type; +{ + Lisp_Object val; + + check_ns (); + CHECK_SYMBOL (selection_name); + CHECK_SYMBOL (target_type); + val = ns_get_local_selection (selection_name, target_type); + if (NILP (val)) + val = ns_get_foreign_selection (selection_name, target_type); + if (CONSP (val) && SYMBOLP (Fcar (val))) + { + val = Fcdr (val); + if (CONSP (val) && NILP (Fcdr (val))) + val = Fcar (val); + } + val = clean_local_selection_data (val); + return val; +} + + +#ifdef CUT_BUFFER_SUPPORT +DEFUN ("ns-get-cut-buffer-internal", Fns_get_cut_buffer_internal, + Sns_get_cut_buffer_internal, 1, 1, 0, + "Returns the value of the named cut buffer.") + (buffer) + Lisp_Object buffer; +{ + id pb; + check_ns (); + pb =[NSPasteboard pasteboardWithName: symbol_to_nsstring (buffer)]; + return ns_string_from_pasteboard (pb); +} + + +DEFUN ("ns-rotate-cut-buffers-internal", Fns_rotate_cut_buffers_internal, + Sns_rotate_cut_buffers_internal, 1, 1, 0, + "Rotate the values of the cut buffers by the given number of steps;\n\ + positive means move values forward, negative means backward. CURRENTLY NOT IMPLEMENTED UNDER NeXTstep.") + (n) + Lisp_Object n; +{ + /* XXX This function is unimplemented under NeXTstep XXX */ + Fsignal (Qquit, Fcons (build_string ( + "Warning: ns-rotate-cut-buffers-internal not implemented\n"), Qnil)); + return Qnil; +} + + +DEFUN ("ns-store-cut-buffer-internal", Fns_store_cut_buffer_internal, + Sns_store_cut_buffer_internal, 2, 2, 0, + "Sets the value of the named cut buffer (typically CUT_BUFFER0).") + (buffer, string) + Lisp_Object buffer, string; +{ + id pb; + check_ns (); + pb =[NSPasteboard pasteboardWithName: symbol_to_nsstring (buffer)]; + ns_string_to_pasteboard (pb, string); + return Qnil; +} +#endif + + +void +nxatoms_of_nsselect (void) +{ + NXSecondaryPboard = @"Selection"; +} + +void +syms_of_nsselect (void) +{ + QPRIMARY = intern ("PRIMARY"); staticpro (&QPRIMARY); + QSECONDARY = intern ("SECONDARY"); staticpro (&QSECONDARY); + QTEXT = intern ("TEXT"); staticpro (&QTEXT); + QFILE_NAME = intern ("FILE_NAME"); staticpro (&QFILE_NAME); + + defsubr (&Sns_disown_selection_internal); + defsubr (&Sns_get_selection_internal); + defsubr (&Sns_own_selection_internal); + defsubr (&Sns_selection_exists_p); + defsubr (&Sns_selection_owner_p); +#ifdef CUT_BUFFER_SUPPORT + defsubr (&Sns_get_cut_buffer_internal); + defsubr (&Sns_rotate_cut_buffers_internal); + defsubr (&Sns_store_cut_buffer_internal); +#endif + + Vselection_alist = Qnil; + staticpro (&Vselection_alist); + + DEFVAR_LISP ("ns-sent-selection-hooks", &Vns_sent_selection_hooks, + "A list of functions to be called when Emacs answers a selection request.\n\ +The functions are called with four arguments:\n\ + - the selection name (typically `PRIMARY', `SECONDARY', or `CLIPBOARD');\n\ + - the selection-type which Emacs was asked to convert the\n\ + selection into before sending (for example, `STRING' or `LENGTH');\n\ + - a flag indicating success or failure for responding to the request.\n\ +We might have failed (and declined the request) for any number of reasons,\n\ +including being asked for a selection that we no longer own, or being asked\n\ +to convert into a type that we don't know about or that is inappropriate.\n\ +This hook doesn't let you change the behavior of Emacs's selection replies,\n\ +it merely informs you that they have happened."); + Vns_sent_selection_hooks = Qnil; + + DEFVAR_LISP ("selection-converter-alist", &Vselection_converter_alist, + "An alist associating X Windows selection-types with functions.\n\ +These functions are called to convert the selection, with three args:\n\ +the name of the selection (typically `PRIMARY', `SECONDARY', or `CLIPBOARD');\n\ +a desired type to which the selection should be converted;\n\ +and the local selection value (whatever was given to `x-own-selection').\n\ +\n\ +The function should return the value to send to the X server\n\ +\(typically a string). A return value of nil\n\ +means that the conversion could not be done.\n\ +A return value which is the symbol `NULL'\n\ +means that a side-effect was executed,\n\ +and there is no meaningful selection value."); + Vselection_converter_alist = Qnil; + + DEFVAR_LISP ("ns-lost-selection-hooks", &Vns_lost_selection_hooks, + "A list of functions to be called when Emacs loses an X selection.\n\ +\(This happens when some other X client makes its own selection\n\ +or when a Lisp program explicitly clears the selection.)\n\ +The functions are called with one argument, the selection type\n\ +\(a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD')."); + Vns_lost_selection_hooks = Qnil; + +/* 23: { */ + DEFVAR_LISP ("selection-coding-system", &Vselection_coding_system, + doc: /* Coding system for communicating with other programs. +When sending or receiving text via cut_buffer, selection, and clipboard, +the text is encoded or decoded by this coding system. +The default value is determined by the system script code. */); + Vselection_coding_system = Qnil; + + DEFVAR_LISP ("next-selection-coding-system", &Vnext_selection_coding_system, + doc: /* Coding system for the next communication with other programs. +Usually, `selection-coding-system' is used for communicating with +other programs. But, if this variable is set, it is used for the +next communication only. After the communication, this variable is +set to nil. */); + Vnext_selection_coding_system = Qnil; + + Qforeign_selection = intern ("foreign-selection"); + staticpro (&Qforeign_selection); +/* } */ + +} diff -r ff312a846b25 -r d45acf0c8d23 src/nsterm.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/nsterm.h Tue Jul 15 18:15:18 2008 +0000 @@ -0,0 +1,827 @@ +/* Definitions and headers for communication with NeXT/Open/GNUstep API. + Copyright (C) 1989, 1993, 2005, 2008 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 3, 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., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. */ + +#include "dispextern.h" +#include "frame.h" +#include "character.h" +#include "font.h" + +#ifdef HAVE_NS + +#ifdef __OBJC__ + +/* ========================================================================== + + The Emacs application + + ========================================================================== */ + +/* We override sendEvent: as a means to stop/start the event loop */ +@interface EmacsApp : NSApplication +{ +} +- (void)sendEvent: (NSEvent *)theEvent; +- (void)showPreferencesWindow: (id)sender; +@end + + +/* ========================================================================== + + The main Emacs view + + ========================================================================== */ + +@class EmacsToolbar; + +@interface EmacsView : NSView + { + char *old_title; + BOOL windowClosing; + NSString *workingText; + BOOL processingCompose; +@public + struct frame *emacsframe; + int rows, cols; + int scrollbarsNeedingUpdate; + EmacsToolbar *toolbar; + } + +/* AppKit-side interface */ +- menuDown: sender; +- toolbarClicked: (id)item; +- toggleToolbar: (id)sender; +- (void)keyDown: (NSEvent *)theEvent; +- (void)mouseDown: (NSEvent *)theEvent; +- (void)mouseUp: (NSEvent *)theEvent; +- setMiniwindowImage: (BOOL)setMini; + +/* Emacs-side interface */ +- initFrameFromEmacs: (struct frame *) f; +- (void) setRows: (int) r andColumns: (int) c; +- (void) setWindowClosing: (BOOL)closing; +- (EmacsToolbar *) toolbar; +- (void) deleteWorkingText; +@end + + +/* Small utility used for processing resize events under Cocoa. */ +@interface EmacsWindow : NSWindow +{ + NSPoint grabOffset; +} +@end + + +/* ========================================================================== + + The main menu implementation + + ========================================================================== */ + +@interface EmacsMenu : NSMenu +{ + struct frame *frame; + unsigned long keyEquivModMask; +} + +- initWithTitle: (NSString *)title frame: (struct frame *)f; +- (void)setFrame: (struct frame *)f; +- (void)menuNeedsUpdate: (NSMenu *)menu; /* (delegate method) */ +- (NSString *)parseKeyEquiv: (char *)key; +- (id )addItemWithWidgetValue: (void *)wvptr; +- (void)fillWithWidgetValue: (void *)wvptr; +- (EmacsMenu *)addSubmenuWithTitle: (char *)title forFrame: (struct frame *)f; +- (void) clear; +- (Lisp_Object)runMenuAt: (NSPoint)p forFrame: (struct frame *)f + keymaps: (int)keymaps; +@end + + +/* ========================================================================== + + Toolbar + + ========================================================================== */ + +@class EmacsImage; + +@interface EmacsToolbar : NSToolbar + { + EmacsView *emacsView; + NSMutableDictionary *identifierToItem; + NSMutableArray *activeIdentifiers; + NSArray *prevIdentifiers; + unsigned long enablement, prevEnablement; + } +- initForView: (EmacsView *)view withIdentifier: (NSString *)identifier; +- (void) clearActive; +- (BOOL) changed; +- (void) addDisplayItemWithImage: (EmacsImage *)img idx: (int)idx + helpText: (char *)help + enabled: (BOOL)enabled; +/* delegate methods */ +- (NSToolbarItem *)toolbar: (NSToolbar *)toolbar + itemForItemIdentifier: (NSString *)itemIdentifier + willBeInsertedIntoToolbar: (BOOL)flag; +- (NSArray *)toolbarDefaultItemIdentifiers: (NSToolbar *)toolbar; +- (NSArray *)toolbarAllowedItemIdentifiers: (NSToolbar *)toolbar; +@end + + +/* ========================================================================== + + Message / question windows + + ========================================================================== */ + +@interface EmacsDialogPanel : NSPanel + { + NSTextField *command; + NSTextField *title; + NSMatrix *matrix; + int rows, cols; + } +- initFromContents: (Lisp_Object)menu isQuestion: (BOOL)isQ; +- addButton: (char *)str value: (Lisp_Object)val row: (int)row; +- addString: (char *)str row: (int)row; +- addSplit; +- (Lisp_Object)runDialogAt: (NSPoint)p; +@end + +@interface EmacsTooltip : NSObject + { + NSWindow *win; + NSTextField *textField; + NSTimer *timer; + } +- init; +- (void) setText: (char *)text; +- (void) showAtX: (int)x Y: (int)y for: (int)seconds; +- (void) hide; +- (BOOL) isActive; +- (NSRect) frame; +@end + + +/* ========================================================================== + + File open/save panels + This and next override methods to work around OS X behavior of + restarting application loop when user dismisses panel. + + ========================================================================== */ + +@interface EmacsSavePanel : NSSavePanel +{ +} +@end +@interface EmacsOpenPanel : NSOpenPanel +{ +} +@end + +@interface EmacsFileDelegate : NSObject +{ +} +- (BOOL)panel: (id)sender isValidFilename: (NSString *)filename; +- (BOOL)panel: (id)sender shouldShowFilename: (NSString *)filename; +- (NSString *)panel: (id)sender userEnteredFilename: (NSString *)filename + confirmed: (BOOL)okFlag; +@end + + +/* ========================================================================== + + Images and stippling + + ========================================================================== */ + +@interface EmacsImage : NSImage +{ + id imageListNext; + int refCount; + NSBitmapImageRep *bmRep; /* used for accessing pixel data */ + unsigned char *pixmapData[5]; /* shortcut to access pixel data */ + BOOL onTiger; + NSColor *stippleMask; +} ++ allocInitFromFile: (Lisp_Object)file; +- reference; +- imageListSetNext: (id)arg; +- imageListNext; +- (void)dealloc; +- initFromXBM: (unsigned char *)bits width: (int)w height: (int)h + flip: (BOOL)flip; +- initFromSkipXBM: (unsigned char *)bits width: (int)w height: (int)h + flip: (BOOL)flip length: (int)length; +- setXBMColor: (NSColor *)color; +- initForXPMWithDepth: (int)depth width: (int)width height: (int)height; +- (void)setPixmapData; +- (unsigned long)getPixelAtX: (int)x Y: (int)y; +- (void)setPixelAtX: (int)x Y: (int)y toRed: (unsigned char)r + green: (unsigned char)g blue: (unsigned char)b + alpha:(unsigned char)a; +- (void)setAlphaAtX: (int)x Y: (int)y to: (unsigned char)a; +- (NSColor *)stippleMask; +@end + + +/* ========================================================================== + + Scrollbars + + ========================================================================== */ + +@interface EmacsScroller : NSScroller + { + Lisp_Object win; + struct frame *frame; + NSResponder *prevResponder; + + /* offset to the bottom of knob of last mouse down */ + float last_mouse_offset; + float min_portion; + int pixel_height; + int last_hit_part; + + BOOL condemned; + + /* optimize against excessive positioning calls generated by emacs */ + int em_position; + int em_portion; + int em_whole; + } + +- initFrame: (NSRect )r window: (Lisp_Object)win; +- (void)setFrame: (NSRect)r; +- (void)dealloc; + +- setPosition: (int) position portion: (int) portion whole: (int) whole; +- (int) checkSamePosition: (int)position portion: (int)portion + whole: (int)whole; +- (void) getMouseMotionPart: (int *)part window: (Lisp_Object *)window + x: (Lisp_Object *)x y: ( Lisp_Object *)y; +- (void) sendScrollEventAtLoc: (float)loc fromEvent: (NSEvent *)e; +- repeatScroll: (NSTimer *)sender; +- condemn; +- reprieve; +- judge; +@end + + +/* ========================================================================== + + Rendering on Panther and above + + ========================================================================== */ + +#ifdef NS_IMPL_COCOA +/* rendering util */ +@interface EmacsGlyphStorage : NSObject +{ +@public + NSAttributedString *attrStr; + NSMutableDictionary *dict; + CGGlyph *cglyphs; + unsigned long maxChar, maxGlyph; + long i, len; +} +- initWithCapacity: (unsigned long) c; +- (void) setString: (NSString *)str font: (NSFont *)font; +@end +#endif /* NS_IMPL_COCOA */ + + +/* ========================================================================== + + Running the preferences window + + ========================================================================== */ + +@interface EmacsPrefsController : NSObject +{ + struct frame *frame; + IBOutlet NSWindow *prefsWindow; + IBOutlet NSPopUpButton *alternateModMenu; + IBOutlet NSPopUpButton *commandModMenu; +#ifdef NS_IMPL_COCOA + IBOutlet NSPopUpButton *controlModMenu; + IBOutlet NSPopUpButton *functionModMenu; +#endif + IBOutlet NSMatrix *cursorTypeMatrix; + IBOutlet NSSlider *cursorBlinkSlider; + IBOutlet NSSlider *expandSpaceSlider; +#ifdef NS_IMPL_COCOA + IBOutlet NSButton *smoothFontsCheck; + IBOutlet NSButton *useQuickdrawCheck; + IBOutlet NSButton *useSysHiliteCheck; + BOOL prevUseHighlightColor; +#endif + float prevExpandSpace; + float prevBlinkRate; +} +- (IBAction)cancel: (id)sender; +- (IBAction)ok: (id)sender; +- (IBAction)resetToDefaults: (id)sender; +- (IBAction)runHelp: (id)sender; +- (IBAction)setColors: (id)sender; +- (IBAction)setDefaultFont: (id)sender; + +- (void) showForFrame: (struct frame *)f; +- (void) setPanelFromValues; +- (void) setValuesFromPanel; +@end + +extern NSArray *ns_send_types, *ns_return_types; +extern EmacsMenu *mainMenu, *svcsMenu; + +/* Apple removed the declaration, but kept the implementation */ +#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4 +@interface NSApplication (EmacsApp) +- (void)setAppleMenu: (NSMenu *)menu; +@end +#endif + +#endif /* __OBJC__ */ + + + +/* ========================================================================== + + Non-OO stuff + + ========================================================================== */ + +enum ns_cursor_types +{ + no_highlight =0, + filled_box, + hollow_box, + underscore, + bar +}; + + +/* could use list to store these, but rest of emacs has a big infrastructure + for managing a table of bitmap "records" */ +struct ns_bitmap_record +{ +#ifdef __OBJC__ + EmacsImage *img; +#else + void *img; +#endif + char *file; + int refcount; + int height, width, depth; +}; + +/* this to map between emacs color indices and NSColor objects */ +struct ns_color_table +{ + unsigned int size; + unsigned int avail; +#ifdef __OBJC__ + NSColor **colors; + NSMutableSet *empty_indices; +#else + void **items; + void *availIndices; +#endif +}; +#define NS_COLOR_CAPACITY 256 + +#define RGB_TO_ULONG(r, g, b) (((r) << 16) | ((g) << 8) | (b)) +#define ARGB_TO_ULONG(a, r, g, b) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) + +#define ALPHA_FROM_ULONG(color) ((color) >> 24) +#define RED_FROM_ULONG(color) (((color) >> 16) & 0xff) +#define GREEN_FROM_ULONG(color) (((color) >> 8) & 0xff) +#define BLUE_FROM_ULONG(color) ((color) & 0xff) + +/* Do not change `* 0x101' in the following lines to `<< 8'. If + changed, image masks in 1-bit depth will not work. */ +#define RED16_FROM_ULONG(color) (RED_FROM_ULONG(color) * 0x101) +#define GREEN16_FROM_ULONG(color) (GREEN_FROM_ULONG(color) * 0x101) +#define BLUE16_FROM_ULONG(color) (BLUE_FROM_ULONG(color) * 0x101) + +/* this extends font backend font */ +struct nsfont_info +{ + struct font font; + + char *name; /* postscript name, uniquely identifies on NS systems */ + float width; /* this and following metrics stored as float rather than int */ + float height; + float underpos; + float underwidth; + float size; +#ifdef __OBJC__ + NSFont *nsfont; + /* cgfont and synthItal are used only on OS X 10.3+ */ +#if defined (NS_IMPL_COCOA) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3) + CGFontRef cgfont; +#else /* GNUstep or OS X < 10.3 */ + void *cgfont; +#endif +#else /* ! OBJC */ + void *nsfont; + void *cgfont; +#endif + char bold, ital; /* convenience flags */ + char synthItal; + float voffset; /* mean of ascender/descender offsets */ + XCharStruct max_bounds; /* 23 */ + /* we compute glyph codes and metrics on-demand in blocks of 256 indexed + by hibyte, lobyte */ + unsigned short **glyphs; /* map unicode index to glyph */ + struct font_metrics **metrics; +}; + + +/* init'd in ns_initialize_display_info () */ +struct ns_display_info +{ + /* Chain of all ns_display_info structures. */ + struct ns_display_info *next; + + /* The generic display parameters corresponding to this NS display. */ + struct terminal *terminal; + + /* This is a cons cell of the form (NAME . FONT-LIST-CACHE). + The same cons cell also appears in ns_display_name_list. */ + Lisp_Object name_list_element; + + /* The number of fonts loaded. */ + 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; + + struct kboard *kboard; + + /*/23 */ + struct ns_bitmap_record *bitmaps; + int bitmaps_size; + int bitmaps_last; + + /* 23 */ + struct image_cache *image_cache; + + struct ns_color_table *color_table; + + /* 23: Dimensions and DPI resolution of this screen */ + int height, width; + double resx, resy; + + /* 23: Mask of things that cause the mouse to be grabbed */ + int grabbed; + + /* 23 */ + int n_planes; + + /* 23 */ + int color_p; + + /* 23 */ + Window root_window; + + /* 23: Xism */ + XrmDatabase xrdb; + + /* 23: The cursor to use for vertical scroll bars. */ + Cursor vertical_scroll_bar_cursor; + + /* 23: most mouse face stuff moved in here (and reasonably so) */ + int mouse_face_beg_row, mouse_face_beg_col; + int mouse_face_end_row, mouse_face_end_col; + int mouse_face_beg_x, mouse_face_beg_y; + int mouse_face_end_x, mouse_face_end_y; + int mouse_face_past_end; + Lisp_Object mouse_face_window; + int mouse_face_face_id; + int mouse_face_deferred_gc; + Lisp_Object mouse_face_overlay; + FRAME_PTR mouse_face_mouse_frame; + int mouse_face_mouse_x, mouse_face_mouse_y; + int mouse_face_defer; + int mouse_face_hidden; + int mouse_face_image_state; + + /* these are general, but we redefine due to Xism */ + struct frame *ns_highlight_frame; + struct frame *ns_focus_frame; +#define x_highlight_frame ns_highlight_frame +#define x_focus_frame ns_focus_frame +}; + +/* This is a chain of structures for all the NS displays currently in use. */ +extern struct ns_display_info *ns_display_list; +/* handle Xism */ +#define x_display_list ns_display_list + +extern Lisp_Object ns_display_name_list; +extern struct ns_display_info *ns_display_info_for_name (); + +/* 23: PENDING: these functions (we defined in nsfns) are used in various + places, but no prototypes are provided */ +struct ns_display_info *check_x_display_info (Lisp_Object frame); +FRAME_PTR check_x_frame (Lisp_Object frame); + + +struct ns_output +{ +#ifdef __OBJC__ + EmacsView *view; + id miniimage; + NSColor *current_cursor_color; + NSColor *desired_cursor_color; + NSColor *foreground_color; + NSColor *background_color; + EmacsToolbar *toolbar; +#else + void *view; + void *miniimage; + void *current_cursor_color; + void *desired_cursor_color; + void *foreground_color; + void *background_color; + void *toolbar; +#endif + + /* 23: NSCursors init'ed in initFrameFromEmacs */ + Cursor text_cursor; + Cursor nontext_cursor; + Cursor modeline_cursor; + Cursor hand_cursor; + Cursor hourglass_cursor; + Cursor horizontal_drag_cursor; + + /* 23: NS-specific */ + Cursor current_pointer; + + /* 23: lord knows why Emacs needs to know about our Window ids.. */ + Window window_desc, parent_desc; + char explicit_parent; + + struct font *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; /* only used with font_backend */ + + Lisp_Object icon_top; + Lisp_Object icon_left; + enum ns_cursor_types current_cursor, desired_cursor; + unsigned char last_inactive; + + /* The size of the extra width currently allotted for vertical + scroll bars, in pixels. */ + int vertical_scroll_bar_extra; + + /* The height of the titlebar decoration (included in NSWindow's frame). */ + int titlebar_height; + + /* The height of the toolbar if displayed, else 0. */ + int toolbar_height; + + /* This is the Emacs structure for the NS display this frame is on. */ + struct ns_display_info *display_info; +}; + +/* 23: this dummy decl now needed to support TTYs */ +struct x_output +{ + unsigned long background_pixel; + unsigned long foreground_pixel; +}; + + +/* This gives the ns_display_info structure for the display F is on. */ +#define FRAME_NS_DISPLAY_INFO(f) ((f)->output_data.ns->display_info) +/* the primacy of X must be constantly worked with... */ +#define FRAME_X_DISPLAY_INFO(f) ((f)->output_data.ns->display_info) +#define FRAME_X_OUTPUT(f) ((f)->output_data.ns) +#define FRAME_NS_WINDOW(f) ((f)->output_data.ns->window_desc) +#define FRAME_X_WINDOW(f) ((f)->output_data.ns->window_desc) + +/* This is the `Display *' which frame F is on. */ +#define FRAME_NS_DISPLAY(f) (0) +#define FRAME_X_DISPLAY(f) (0) + +#define FRAME_FOREGROUND_COLOR(f) ((f)->output_data.ns->foreground_color) +#define FRAME_BACKGROUND_COLOR(f) ((f)->output_data.ns->background_color) + +#define FRAME_X_IMAGE_CACHE(F) FRAME_NS_DISPLAY_INFO ((F))->image_cache + +#define NS_FACE_FOREGROUND(f) ((f)->foreground) +#define NS_FACE_BACKGROUND(f) ((f)->background) +#define FRAME_NS_TITLEBAR_HEIGHT(f) ((f)->output_data.ns->titlebar_height) +#define FRAME_NS_TOOLBAR_HEIGHT(f) ((f)->output_data.ns->toolbar_height) + +#define FONT_WIDTH(f) ((f)->max_width) +#define FONT_HEIGHT(f) ((f)->height) +/*#define FONT_BASE(f) ((f)->ascent) */ +#define FONT_BASE(f) (((struct nsfont_info *)f)->max_bounds.ascent) +/*#define FONT_DESCENT(f) ((f)->descent) */ +#define FONT_DESCENT(f) (((struct nsfont_info *)f)->max_bounds.descent) + +#define FRAME_DEFAULT_FACE(f) FACE_FROM_ID (f, DEFAULT_FACE_ID) + +#define FRAME_NS_VIEW(f) ((f)->output_data.ns->view) +#define FRAME_CURSOR(f) ((f)->output_data.ns->current_cursor) +#define FRAME_CURSOR_COLOR(f) ((f)->output_data.ns->current_cursor_color) +#define FRAME_NEW_CURSOR_COLOR(f) ((f)->output_data.ns->desired_cursor_color) +#define FRAME_NEW_CURSOR(f) ((f)->output_data.ns->desired_cursor) +#define FRAME_POINTER_TYPE(f) ((f)->output_data.ns->current_pointer) +#define FRAME_LAST_INACTIVE(f) ((f)->output_data.ns->last_inactive) + +#define FRAME_FONT(f) ((f)->output_data.ns->font) + +#ifdef __OBJC__ +#define XNS_SCROLL_BAR(vec) ((id) XSAVE_VALUE (vec)->pointer) +#else +#define XNS_SCROLL_BAR(vec) XSAVE_VALUE (vec)->pointer +#endif + +/* Compute pixel size for vertical scroll bars */ +#define NS_SCROLL_BAR_WIDTH(f) \ +(FRAME_HAS_VERTICAL_SCROLL_BARS (f) \ + ? rint (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0 \ + ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f) \ + : (FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f))) \ + : 0) + +/* Difference btwn char-column-calculated and actual SB widths. + This is only a concern for rendering when SB on left. */ +#define NS_SCROLL_BAR_ADJUST(w, f) \ +(WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w) ? \ + (FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f) \ + - NS_SCROLL_BAR_WIDTH (f)) : 0) + +/*PENDING: fix for GNUstep inconsistent accounting for titlebar */ +#ifdef NS_IMPL_GNUSTEP +#define NS_TOP_POS(f) ((f)->top_pos + 18) +#else +#define NS_TOP_POS(f) ((f)->top_pos) +#endif + +#define FRAME_NS_FONT_TABLE(f) (FRAME_NS_DISPLAY_INFO (f)->font_table) + +#define FRAME_FONTSET(f) ((f)->output_data.ns->fontset) + +/* 23 */ +#define FRAME_SMALLEST_CHAR_WIDTH(f) \ + (FRAME_NS_DISPLAY_INFO (f)->smallest_char_width) +#define FRAME_SMALLEST_FONT_HEIGHT(f) \ + (FRAME_NS_DISPLAY_INFO (f)->smallest_font_height) +#define FONT_TYPE_FOR_UNIBYTE(font, ch) 0 +#define FONT_TYPE_FOR_MULTIBYTE(font, ch) 0 +#define FRAME_BASELINE_OFFSET(f) ((f)->output_data.ns->baseline_offset) +#define BLACK_PIX_DEFAULT(f) 0x000000 +#define WHITE_PIX_DEFAULT(f) 0xFFFFFF + +/* First position where characters can be shown (instead of scrollbar, if + it is on left. */ +#define FIRST_CHAR_POSITION(f) \ + (! (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f)) ? 0 \ + : FRAME_SCROLL_BAR_COLS (f)) + +extern struct ns_display_info *ns_term_init (); +extern void ns_term_shutdown (int sig); + +/* constants for text rendering */ +#define NS_DUMPGLYPH_NORMAL 0 +#define NS_DUMPGLYPH_CURSOR 1 +#define NS_DUMPGLYPH_FOREGROUND 2 +#define NS_DUMPGLYPH_MOUSEFACE 3 + + +/* In nsfont, called from fontset.c */ +extern void nsfont_make_fontset_for_font (Lisp_Object name, + Lisp_Object font_object); + +/* In nsfont, for debugging */ +struct glyph_string; +void dump_glyphstring (struct glyph_string *s); + +/* Implemented in nsterm, published in or needed from nsfns. */ +extern Lisp_Object Qfontsize; +extern Lisp_Object ns_list_fonts (FRAME_PTR f, Lisp_Object pattern, + int size, int maxnames); +extern void ns_clear_frame (struct frame *f); + +#ifdef __OBJC__ +extern const char *ns_font_to_xlfd (NSFont *font); +#endif +extern const char *ns_fontname_to_xlfd (const char *name); +extern const char *ns_xlfd_to_fontname (const char *xlfd); + +extern void check_ns (void); +extern Lisp_Object ns_map_event_to_object (); +extern Lisp_Object ns_string_from_pasteboard (); +extern void ns_string_to_pasteboard (); +extern void nxatoms_of_nsselect (); +extern int ns_lisp_to_cursor_type (); +extern Lisp_Object ns_cursor_type_to_lisp (int arg); +extern Lisp_Object Qnone; + +/* XColor defined in dispextern.h (we use color_def->pixel = NSColor id), but + this causes an #include snafu, so we can't declare it. + extern int ns_defined_color (struct frame *f, char *name, XColor *color_def, + int alloc); */ + +#ifdef __OBJC__ +extern int ns_lisp_to_color (Lisp_Object color, NSColor **col); +extern NSColor *ns_lookup_indexed_color (unsigned long idx, struct frame *f); +extern unsigned long ns_index_color (NSColor *color, struct frame *f); +extern void ns_free_indexed_color (unsigned long idx, struct frame *f); +#endif + +/* C access to ObjC functionality */ +extern void ns_release_object (void *obj); +extern void ns_retain_object (void *obj); +extern void *ns_alloc_autorelease_pool (); +extern void ns_release_autorelease_pool (); + +/* in nsmenu */ +extern void update_frame_tool_bar (FRAME_PTR f); +extern void free_frame_tool_bar (FRAME_PTR f); +extern void find_and_call_menu_selection (FRAME_PTR f, + EMACS_INT menu_bar_items_used, Lisp_Object vector, void *client_data); +extern Lisp_Object find_and_return_menu_selection (FRAME_PTR f, + int keymaps, + void *client_data); +extern Lisp_Object ns_popup_dialog (Lisp_Object position, Lisp_Object contents, + Lisp_Object header); + +/* two more prototypes that should be moved to a more general include file */ +extern void set_frame_menubar (struct frame *f, int first_time, int deep_p); +extern void x_set_window_size (struct frame *f, int change_grav, + int cols, int rows); + +/* From nsimage.m, needed in image.c */ +struct image; +extern void *ns_image_from_XBM (unsigned char *bits, int width, int height); +extern void *ns_image_for_XPM (int width, int height, int depth); +extern void *ns_image_from_file (Lisp_Object file); +extern int ns_load_image (struct frame *f, struct image *img, + Lisp_Object spec_file, Lisp_Object spec_data); +extern int ns_image_width (void *img); +extern int ns_image_height (void *img); +extern unsigned long ns_get_pixel (void *img, int x, int y); +extern void ns_put_pixel (void *img, int x, int y, unsigned long argb); +extern void ns_set_alpha (void *img, int x, int y, unsigned char a); + +/* This in nsterm.m */ +extern unsigned long ns_get_rgb_color (struct frame *f, + float r, float g, float b, float a); +extern NSPoint last_mouse_motion_position; + +#ifdef NS_IMPL_GNUSTEP +extern char gnustep_base_version[]; /* version tracking */ +#endif + +#define MINWIDTH 10 +#define MINHEIGHT 10 + +/* Screen max coordinate + Using larger coordinates causes movewindow/placewindow to abort */ +#define SCREENMAX 16000 + +#define NS_SCROLL_BAR_WIDTH_DEFAULT [EmacsScroller scrollerWidth] +/* This is to match emacs on other platforms, ugly though it is. */ +#define NS_SELECTION_COLOR_DEFAULT @"LightGoldenrod2"; +#define RESIZE_HANDLE_SIZE 12 + +/* Little utility macros */ +#define IN_BOUND(min, x, max) (((x) < (min)) \ + ? (min) : (((x)>(max)) ? (max) : (x))) +#define SCREENMAXBOUND(x) (IN_BOUND (-SCREENMAX, x, SCREENMAX)) + +/* 23: needed somewhere... */ +#define VERTICAL_SCROLL_BAR_WIDTH_TRIM (0) + + +#endif /* HAVE_NS */ diff -r ff312a846b25 -r d45acf0c8d23 src/nsterm.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/nsterm.m Tue Jul 15 18:15:18 2008 +0000 @@ -0,0 +1,6598 @@ +/* NeXT/Open/GNUstep / MacOSX communication module. + Copyright (C) 1989, 1993, 1994, 2005, 2006, 2008, + 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 3, 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., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. + +Originally by Carl Edman +Updated by Christian Limpach (chris@nice.ch) +OpenStep/Rhapsody port by Scott Bender (sbender@harmony-ds.com) +MacOSX/Aqua port by Christophe de Dinechin (descubes@earthlink.net) +GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu) +*/ + +#include +#include +#include +#include + +#include "config.h" +#include "lisp.h" +#include "blockinput.h" +#include "sysselect.h" +#include "nsterm.h" +#include "systime.h" +#include "character.h" +#include "fontset.h" +#include "composite.h" +#include "ccl.h" + +#include "termhooks.h" +#include "termopts.h" +#include "termchar.h" + +#include "window.h" +#include "keyboard.h" + +#include "font.h" + +/* call tracing */ +#if 0 +int term_trace_num = 0; +#define NSTRACE(x) fprintf (stderr, "%s:%d: [%d] " #x "\n", \ + __FILE__, __LINE__, ++term_trace_num) +#else +#define NSTRACE(x) +#endif + + +/* ========================================================================== + + Local declarations + + ========================================================================== */ + +/* Special keycodes that we pass down the event chain */ +#define KEY_NS_POWER_OFF ((1<<28)|(0<<16)|1) +#define KEY_NS_OPEN_FILE ((1<<28)|(0<<16)|2) +#define KEY_NS_OPEN_TEMP_FILE ((1<<28)|(0<<16)|3) +#define KEY_NS_DRAG_FILE ((1<<28)|(0<<16)|4) +#define KEY_NS_DRAG_COLOR ((1<<28)|(0<<16)|5) +#define KEY_NS_DRAG_TEXT ((1<<28)|(0<<16)|6) +#define KEY_NS_CHANGE_FONT ((1<<28)|(0<<16)|7) +#define KEY_NS_OPEN_FILE_LINE ((1<<28)|(0<<16)|8) +#define KEY_NS_INSERT_WORKING_TEXT ((1<<28)|(0<<16)|9) +#define KEY_NS_DELETE_WORKING_TEXT ((1<<28)|(0<<16)|10) +#define KEY_NS_SPI_SERVICE_CALL ((1<<28)|(0<<16)|11) + +/* Convert a symbol indexed with an NSxxx value to a value as defined + in keyboard.c (lispy_function_key). I hope this is a correct way + of doing things... */ +static unsigned convert_ns_to_X_keysym[] = +{ + NSHomeFunctionKey, 0x50, + NSLeftArrowFunctionKey, 0x51, + NSUpArrowFunctionKey, 0x52, + NSRightArrowFunctionKey, 0x53, + NSDownArrowFunctionKey, 0x54, + NSPageUpFunctionKey, 0x55, + NSPageDownFunctionKey, 0x56, + NSEndFunctionKey, 0x57, + NSBeginFunctionKey, 0x58, + NSSelectFunctionKey, 0x60, + NSPrintFunctionKey, 0x61, + NSExecuteFunctionKey, 0x62, + NSInsertFunctionKey, 0x63, + NSUndoFunctionKey, 0x65, + NSRedoFunctionKey, 0x66, + NSMenuFunctionKey, 0x67, + NSFindFunctionKey, 0x68, + NSHelpFunctionKey, 0x6A, + NSBreakFunctionKey, 0x6B, + + NSF1FunctionKey, 0xBE, + NSF2FunctionKey, 0xBF, + NSF3FunctionKey, 0xC0, + NSF4FunctionKey, 0xC1, + NSF5FunctionKey, 0xC2, + NSF6FunctionKey, 0xC3, + NSF7FunctionKey, 0xC4, + NSF8FunctionKey, 0xC5, + NSF9FunctionKey, 0xC6, + NSF10FunctionKey, 0xC7, + NSF11FunctionKey, 0xC8, + NSF12FunctionKey, 0xC9, + NSF13FunctionKey, 0xCA, + NSF14FunctionKey, 0xCB, + NSF15FunctionKey, 0xCC, + + NSBackspaceCharacter, 0x08, /* 8: Not on some KBs. */ + NSDeleteCharacter, 0xFF, /* 127: Big 'delete' key upper right. */ + NSDeleteFunctionKey, 0x9F, /* 63272: Del forw key off main array. */ + + NSTabCharacter, 0x09, + 0x19, 0x09, /* left tab->regular since pass shift */ + NSCarriageReturnCharacter, 0x0D, + NSNewlineCharacter, 0x0D, + NSEnterCharacter, 0x8D, + + 0x1B, 0x1B /* escape */ +}; + + +/* Lisp communications */ +Lisp_Object ns_input_file, ns_input_font, ns_input_fontsize, ns_input_line; +Lisp_Object ns_input_color, ns_input_text, ns_working_text; +Lisp_Object ns_input_spi_name, ns_input_spi_arg; +Lisp_Object Vx_toolkit_scroll_bars; +static Lisp_Object Qmodifier_value; +/*PENDING: unsure why these defined in term files, anyway we need in keymap.c */ +Lisp_Object Qalt, Qcontrol, Qhyper, Qmeta, Qsuper; +extern Lisp_Object Qcursor_color, Qcursor_type, Qns; +extern int lisp_to_mod (Lisp_Object lmod); + + +EmacsPrefsController *prefsController; + +/* Defaults managed through the OpenStep defaults system. These pertain to + the NS interface specifically. Although a customization group could be + created, it's more natural to manage them via defaults. */ + +/* Specifies which emacs modifier should be generated when NS receives + the Alternate modifer. May be Qnone or any of the modifier lisp symbols. */ +Lisp_Object ns_alternate_modifier; + +/* Specifies which emacs modifier should be generated when NS receives + the Command modifer. May be any of the modifier lisp symbols. */ +Lisp_Object ns_command_modifier; + +/* Specifies which emacs modifier should be generated when NS receives + the Control modifer. May be any of the modifier lisp symbols. */ +Lisp_Object ns_control_modifier; + +/* Specifies which emacs modifier should be generated when NS receives + the Function modifer (laptops). May be any of the modifier lisp symbols. */ +Lisp_Object ns_function_modifier; + +/* A floating point value specifying the rate at which to blink the cursor. + YES indicates 0.5, NO indicates no blinking. */ +Lisp_Object ns_cursor_blink_rate; + +/* Used for liason with core emacs cursor-blink-mode. */ +Lisp_Object ns_cursor_blink_mode; + +/* A floating point value specifying vertical stretch (positive) or shrink + (negative) of text line spacing. Zero means default spacing. + YES indicates 0.5, NO indicates 0.0. */ +Lisp_Object ns_expand_space; + +/* Control via default 'GSFontAntiAlias' on OS X and GNUstep. */ +int ns_antialias_text; + +/* On OS X picks up the default NSGlobalDomain AppleAntiAliasingThreshold, + the maximum font size to NOT antialias. On GNUstep there is currently + no way to control this behavior. */ +float ns_antialias_threshold; + +/* Controls use of an undocumented CG function to do Quickdraw-style font + smoothing (less heavy) instead of regular Quartz smoothing. */ +int ns_use_qd_smoothing; + +/* Used to pick up AppleHighlightColor on OS X */ +int ns_use_system_highlight_color; +NSString *ns_selection_color; + + +NSArray *ns_send_types =0, *ns_return_types =0, *ns_drag_types =0; + +/* Display variables */ +struct ns_display_info *ns_display_list; /* Chain of existing displays */ +Lisp_Object ns_display_name_list; +long context_menu_value = 0; + +/* display update */ +NSPoint last_mouse_motion_position; +static NSRect last_mouse_glyph; +static unsigned long last_mouse_movement_time = 0; +static Lisp_Object last_mouse_motion_frame; +static EmacsScroller *last_mouse_scroll_bar = nil; +static struct frame *ns_updating_frame; +static NSView *focus_view = NULL; +static int ns_window_num =0; +static NSRect uRect; +static BOOL gsaved = NO; +BOOL ns_in_resize = NO; +int ns_tmp_flags; /*PENDING */ +struct nsfont_info *ns_tmp_font; /*PENDING */ +/*static int debug_lock = 0; */ + +#ifdef NS_IMPL_COCOA +/* This undocumented Quartz function controls how fonts are anti-aliased. + (Found from code in Mac wxWindows impl, discovered by running `nm' on + the "QD" framework.) + Mode 0 is normal anti-aliasing, mode 1 is no anti-aliasing, and mode 2 is + 4-bit pixel-aligned anti-aliasing (the old QuickDraw standard). */ +extern void CGContextSetFontRenderingMode (CGContextRef cg, int v); +#endif + + +/* event loop */ +static BOOL send_appdefined = YES; +static NSEvent *last_appdefined_event = 0; +static NSTimer *timed_entry = 0; +static NSTimer *fd_entry = nil; +static NSTimer *cursor_blink_entry = nil; +static NSTimer *scroll_repeat_entry = nil; +static fd_set select_readfds, t_readfds; +static struct timeval select_timeout; +static int select_nfds; +static NSAutoreleasePool *outerpool; +static BOOL ns_shutdown_properly = NO; +static struct input_event *emacs_event = NULL; +static struct input_event *q_event_ptr = NULL; +static int n_emacs_events_pending = 0; +static NSMutableArray *ns_pending_files, *ns_pending_service_names, + *ns_pending_service_args; +static BOOL inNsSelect = 0; + +/* Convert modifiers in a NeXTSTEP event to emacs style modifiers. */ +#define NS_FUNCTION_KEY_MASK 0x800000 +#define EV_MODIFIERS(e) \ + ((([e modifierFlags] & NSHelpKeyMask) ? \ + hyper_modifier : 0) \ + | (([e modifierFlags] & NSAlternateKeyMask) ? \ + lisp_to_mod (ns_alternate_modifier) : 0) \ + | (([e modifierFlags] & NSShiftKeyMask) ? \ + shift_modifier : 0) \ + | (([e modifierFlags] & NSControlKeyMask) ? \ + lisp_to_mod (ns_control_modifier) : 0) \ + | (([e modifierFlags] & NS_FUNCTION_KEY_MASK) ? \ + lisp_to_mod (ns_function_modifier) : 0) \ + | (([e modifierFlags] & NSCommandKeyMask) ? \ + lisp_to_mod (ns_command_modifier):0)) + +#define EV_UDMODIFIERS(e) \ + ((([e type] == NSLeftMouseDown) ? down_modifier : 0) \ + | (([e type] == NSRightMouseDown) ? down_modifier : 0) \ + | (([e type] == NSLeftMouseDragged) ? down_modifier : 0) \ + | (([e type] == NSRightMouseDragged) ? down_modifier : 0) \ + | (([e type] == NSLeftMouseUp) ? up_modifier : 0) \ + | (([e type] == NSRightMouseUp) ? up_modifier : 0)) + +#define EV_BUTTON(e) \ + ((([e type] == NSLeftMouseDown) || ([e type] == NSLeftMouseUp)) ? 0 : \ + (([e type] == NSRightMouseDown) || ([e type] == NSRightMouseUp)) ? 2 : 1) + +/* Convert the time field to a timestamp in milliseconds. */ +#ifdef NS_IMPL_GNUSTEP +/* Apple says timestamp is in seconds, but GNUstep seems to be returning msec */ +#define EV_TIMESTAMP(e) ([e timestamp]) +#else +#define EV_TIMESTAMP(e) ([e timestamp] * 1000) +#endif /* not gnustep */ + +/* This is a piece of code which is common to all the event handling + methods. Maybe it should even be a function. */ +#define EV_TRAILER(e) \ + { \ + XSETFRAME (emacs_event->frame_or_window, [NSApp isActive] ? \ + emacsframe : SELECTED_FRAME ()); \ + if (e) emacs_event->timestamp = EV_TIMESTAMP (e); \ + n_emacs_events_pending++; \ + kbd_buffer_store_event_hold (emacs_event, q_event_ptr); \ + EVENT_INIT (*emacs_event); \ + ns_send_appdefined (-1); \ + } + +/*PENDING: get rid of need for these forward declarations */ +static void ns_condemn_scroll_bars (struct frame *f), + ns_judge_scroll_bars (struct frame *f); + +/* unused variables needed for compatibility reasons */ +int x_use_underline_position_properties, x_underline_at_descent_line; +/* PENDING: figure out what to do with underline_minimum_offset. */ + + +/* ========================================================================== + + Utilities + + ========================================================================== */ + + +static Lisp_Object +append2 (Lisp_Object list, Lisp_Object item) +/* -------------------------------------------------------------------------- + Utility to append to a list + -------------------------------------------------------------------------- */ +{ + Lisp_Object array[2]; + array[0] = list; + array[1] = Fcons (item, Qnil); + return Fnconc (2, &array[0]); +} + + +void +ns_init_paths () +/* -------------------------------------------------------------------------- + Used to allow emacs to find its resources under Emacs.app + Called from emacs.c at startup. + -------------------------------------------------------------------------- */ +{ + NSBundle *bundle = [NSBundle mainBundle]; + NSString *binDir = [bundle bundlePath], *resourceDir = [bundle resourcePath]; + NSString *resourcePath, *resourcePaths; + NSRange range; + BOOL onWindows = NO; /* how do I determine this? */ + NSString *pathSeparator = onWindows ? @";" : @":"; + NSFileManager *fileManager = [NSFileManager defaultManager]; + BOOL isDir; +/*NSLog (@"ns_init_paths: '%@'\n%@\n", [[NSBundle mainBundle] bundlePath], [[NSBundle mainBundle] resourcePath]); */ + + /* get bindir from base */ + range = [resourceDir rangeOfString: @"Contents"]; + if (range.location != NSNotFound) + { + binDir = [binDir stringByAppendingPathComponent: @"Contents"]; +#ifdef NS_IMPL_COCOA + binDir = [binDir stringByAppendingPathComponent: @"MacOS"]; +#endif + } + + /* the following based on Andrew Choi's init_mac_osx_environment () */ + if (!getenv ("EMACSLOADPATH")) + { + NSArray *paths = [resourceDir stringsByAppendingPaths: + [NSArray arrayWithObjects: + @"site-lisp", @"lisp", @"leim", nil]]; + NSEnumerator *pathEnum = [paths objectEnumerator]; + resourcePaths = @""; + while (resourcePath = [pathEnum nextObject]) + { + if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir]) + if (isDir) + { + if ([resourcePaths length] > 0) + resourcePaths = + [resourcePaths stringByAppendingString: pathSeparator]; + resourcePaths = + [resourcePaths stringByAppendingString: resourcePath]; + } + } + if ([resourcePaths length] > 0) + setenv ("EMACSLOADPATH", [resourcePaths UTF8String], 1); +/*NSLog (@"loadPath: '%s'\n", resourcePaths); */ + } + + if (!getenv ("EMACSPATH")) + { + NSArray *paths = [binDir stringsByAppendingPaths: + [NSArray arrayWithObjects: @"bin", + @"lib-exec", nil]]; + NSEnumerator *pathEnum = [paths objectEnumerator]; + resourcePaths = @""; + while (resourcePath = [pathEnum nextObject]) + { + if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir]) + if (isDir) + { + if ([resourcePaths length] > 0) + resourcePaths = + [resourcePaths stringByAppendingString: pathSeparator]; + resourcePaths = + [resourcePaths stringByAppendingString: resourcePath]; + } + } + if ([resourcePaths length] > 0) + setenv ("EMACSPATH", [resourcePaths UTF8String], 1); + } + + resourcePath = [resourceDir stringByAppendingPathComponent: @"etc"]; + if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir]) + { + if (isDir) + { + if (!getenv ("EMACSDATA")) + setenv ("EMACSDATA", [resourcePath UTF8String], 1); + if (!getenv ("EMACSDOC")) + setenv ("EMACSDOC", [resourcePath UTF8String], 1); + } + } + + /*PENDING: append to INFOPATH... */ + if (!getenv ("INFOPATH")) + { + resourcePath = [resourceDir stringByAppendingPathComponent: @"info"]; + if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir]) + if (isDir) + setenv ("INFOPATH", [resourcePath UTF8String], 1); + } +} + + +static int +timeval_subtract (struct timeval *result, struct timeval x, struct timeval y) +/* -------------------------------------------------------------------------- + Subtract the `struct timeval' values X and Y, storing the result in RESULT. + Return 1 if the difference is negative, otherwise 0. + -------------------------------------------------------------------------- */ +{ + /* 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; +} + +static void +ns_timeout (int usecs) +/* -------------------------------------------------------------------------- + Blocking timer utility used by ns_ring_bell + -------------------------------------------------------------------------- */ +{ + struct timeval wakeup; + + EMACS_GET_TIME (wakeup); + + /* Compute time to wait until, propagating carry from usecs. */ + wakeup.tv_usec += usecs; + 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); + } +} + + +void +ns_release_object (void *obj) +/* -------------------------------------------------------------------------- + Release an object (callable from C) + -------------------------------------------------------------------------- */ +{ + [(id)obj release]; +} + + +void +ns_retain_object (void *obj) +/* -------------------------------------------------------------------------- + Retain an object (callable from C) + -------------------------------------------------------------------------- */ +{ + [(id)obj retain]; +} + + +void * +ns_alloc_autorelease_pool () +/* -------------------------------------------------------------------------- + Allocate a pool for temporary objects (callable from C) + -------------------------------------------------------------------------- */ +{ + return [[NSAutoreleasePool alloc] init]; +} + + +void +ns_release_autorelease_pool (void *pool) +/* -------------------------------------------------------------------------- + Free a pool and temporary objects it refers to (callable from C) + -------------------------------------------------------------------------- */ +{ + ns_release_object (pool); +} + + + +/* ========================================================================== + + Focus (clipping) and screen update + + ========================================================================== */ + +static NSRect +ns_resize_handle_rect (NSWindow *window) +{ + NSRect r = [window frame]; + r.origin.x = r.size.width - RESIZE_HANDLE_SIZE; + r.origin.y = 0; + r.size.width = r.size.height = RESIZE_HANDLE_SIZE; + return r; +} + + +static void +ns_update_begin (struct frame *f) +/* -------------------------------------------------------------------------- + Prepare for a grouped sequence of drawing calls + 23: external (RIF) call; now split w/ and called before update_window_begin + -------------------------------------------------------------------------- */ +{ + NSView *view = FRAME_NS_VIEW (f); + NSTRACE (ns_update_begin); +/*fprintf (stderr, "\\%p\n", f); */ + + ns_updating_frame = f; + [view lockFocus]; + +#ifdef NS_IMPL_GNUSTEP + uRect = NSMakeRect (0, 0, 0, 0); +#endif +} + + +static void +ns_update_window_begin (struct window *w) +/* -------------------------------------------------------------------------- + Prepare for a grouped sequence of drawing calls + 23: external (RIF) call; now split with and called after update_begin + -------------------------------------------------------------------------- */ +{ + struct frame *f = XFRAME (WINDOW_FRAME (w)); + struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (f); + NSTRACE (ns_update_window_begin); + + updated_window = w; + set_output_cursor (&w->cursor); + + BLOCK_INPUT; + + if (f == dpyinfo->mouse_face_mouse_frame) + { + /* Don't do highlighting for mouse motion during the update. */ + dpyinfo->mouse_face_defer = 1; + + /* If the frame needs to be redrawn, + simply forget about any prior mouse highlighting. */ + if (FRAME_GARBAGED_P (f)) + dpyinfo->mouse_face_window = Qnil; + + /* (further code for mouse faces ifdef'd out in other terms elided) */ + } + + UNBLOCK_INPUT; +} + + +static void +ns_update_window_end (struct window *w, int cursor_on_p, + int mouse_face_overwritten_p) +/* -------------------------------------------------------------------------- + Finished a grouped sequence of drawing calls + 23: external (RIF) call; now split with and called before update_window_end + -------------------------------------------------------------------------- */ +{ + struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (XFRAME (w->frame)); + + /* note: this fn is nearly identical in all terms */ + if (!w->pseudo_window_p) + { + BLOCK_INPUT; + + if (cursor_on_p) + display_and_set_cursor (w, 1, + output_cursor.hpos, output_cursor.vpos, + output_cursor.x, output_cursor.y); + + if (draw_window_fringes (w, 1)) + x_draw_vertical_border (w); + + UNBLOCK_INPUT; + } + + /* If a row with mouse-face was overwritten, arrange for + frame_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; + } + + updated_window = NULL; + NSTRACE (update_window_end); +} + + +static void +ns_update_end (struct frame *f) +/* -------------------------------------------------------------------------- + Finished a grouped sequence of drawing calls + 23: external (RIF) call; now split with and called after update_window_end + -------------------------------------------------------------------------- */ +{ + NSView *view = FRAME_NS_VIEW (f); + +/* if (f == FRAME_NS_DISPLAY_INFO (f)->mouse_face_mouse_frame) */ + FRAME_NS_DISPLAY_INFO (f)->mouse_face_defer = 0; + + BLOCK_INPUT; + +#ifdef NS_IMPL_GNUSTEP + /* trigger flush only in the rectangle we tracked as being drawn */ + [view unlockFocusNeedsFlush: NO]; +/*fprintf (stderr, " (%.0f, %.0f : %.0f x %.0f)", uRect.origin.x, uRect.origin.y, uRect.size.width, uRect.size.height); */ + [view lockFocusInRect: uRect]; +#endif + + [view unlockFocus]; + [[view window] flushWindow]; + + UNBLOCK_INPUT; + ns_updating_frame = NULL; + NSTRACE (ns_update_end); +} + + +static void +ns_flush (struct frame *f) +/* -------------------------------------------------------------------------- + 23: external (RIF) call + NS impl is no-op since currently we flush in ns_update_end and elsewhere + -------------------------------------------------------------------------- */ +{ + NSTRACE (ns_flush); +} + + +static void +ns_focus (struct frame *f, NSRect *r, int n) +/* -------------------------------------------------------------------------- + Internal: Focus on given frame. During small local updates this is used to + draw, however during large updates, ns_update_begin and ns_update_end are + called to wrap the whole thing, in which case these calls are stubbed out. + Except, on GNUstep, we accumulate the rectangle being drawn into, because + the back end won't do this automatically, and will just end up flushing + the entire window. + -------------------------------------------------------------------------- */ +{ + NSTRACE (ns_focus); +#ifdef NS_IMPL_GNUSTEP + NSRect u; + if (n == 2) + u = NSUnionRect (r[0], r[1]); + else if (r) + u = *r; +#endif +/* static int c =0; + fprintf (stderr, "focus: %d", c++); + if (r) fprintf (stderr, " (%.0f, %.0f : %.0f x %.0f)", r->origin.x, r->origin.y, r->size.width, r->size.height); + fprintf (stderr, "\n"); */ + + if (f != ns_updating_frame) + { + NSView *view = FRAME_NS_VIEW (f); + if (view != focus_view) + { + if (focus_view != NULL) + { + [focus_view unlockFocus]; + [[focus_view window] flushWindow]; +/*debug_lock--; */ + } + + if (view) +#ifdef NS_IMPL_GNUSTEP + r ? [view lockFocusInRect: u] : [view lockFocus]; +#else + [view lockFocus]; +#endif + focus_view = view; +/*if (view) debug_lock++; */ + } +#ifdef NS_IMPL_GNUSTEP + else + { + /* more than one rect being drawn into */ + if (view && r) + { + [view unlockFocus]; /* add prev rect to redraw list */ + [view lockFocusInRect: u]; /* focus for draw in new rect */ + } + } +#endif + } +#ifdef NS_IMPL_GNUSTEP + else + { + /* in batch mode, but in GNUstep must still track rectangles explicitly */ + uRect = (r ? NSUnionRect (uRect, u) : [FRAME_NS_VIEW (f) visibleRect]); + } +#endif + + /*23: clipping */ + if (r) + { + [[NSGraphicsContext currentContext] saveGraphicsState]; + if (n == 2) + NSRectClipList (r, 2); + else + NSRectClip (*r); + gsaved = YES; + } +} + + +static void +ns_unfocus (struct frame *f) +/* -------------------------------------------------------------------------- + Internal: Remove focus on given frame + -------------------------------------------------------------------------- */ +{ + NSTRACE (ns_unfocus); + + if (gsaved) + { + [[NSGraphicsContext currentContext] restoreGraphicsState]; + gsaved = NO; + } + + if (f != ns_updating_frame) + { + if (focus_view != NULL) + { + [focus_view unlockFocus]; + [[focus_view window] flushWindow]; + focus_view = NULL; +/*debug_lock--; */ + } + } +} + + +static void +ns_clip_to_row (struct window *w, struct glyph_row *row, int area, GC gc) +/* -------------------------------------------------------------------------- + 23: Internal (but parallels other terms): Focus drawing on given row + -------------------------------------------------------------------------- */ +{ + struct frame *f = XFRAME (WINDOW_FRAME (w)); + NSRect clip_rect; + int window_x, window_y, window_width; + + window_box (w, area, &window_x, &window_y, &window_width, 0); + + clip_rect.origin.x = window_x - FRAME_INTERNAL_BORDER_WIDTH (f); + clip_rect.origin.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y)); + clip_rect.origin.y = max (clip_rect.origin.y, window_y); + clip_rect.size.width = window_width + 2 * FRAME_INTERNAL_BORDER_WIDTH (f); + clip_rect.size.height = row->visible_height; + + /* allow a full-height row at the top when requested + (used to draw fringe all the way through internal border area) */ + if (gc && clip_rect.origin.y < 5) + { + clip_rect.origin.y -= FRAME_INTERNAL_BORDER_WIDTH (f); + clip_rect.size.height += FRAME_INTERNAL_BORDER_WIDTH (f); + } + + /* likewise at bottom */ + if (gc && + FRAME_PIXEL_HEIGHT (f) - (clip_rect.origin.y + clip_rect.size.height) < 5) + clip_rect.size.height += FRAME_INTERNAL_BORDER_WIDTH (f); + + ns_focus (f, &clip_rect, 1); +} + + +static void +ns_ring_bell () +/* -------------------------------------------------------------------------- + "Beep" routine + -------------------------------------------------------------------------- */ +{ + NSTRACE (ns_ring_bell); + if (visible_bell) + { + NSAutoreleasePool *pool; + struct frame *frame = SELECTED_FRAME (); + NSView *view; + + BLOCK_INPUT; + pool = [[NSAutoreleasePool alloc] init]; + + view = FRAME_NS_VIEW (frame); + if (view != nil) + { + NSRect r, surr; + NSPoint dim = NSMakePoint (128, 128); + + r = [view bounds]; + r.origin.x += (r.size.width - dim.x) / 2; + r.origin.y += (r.size.height - dim.y) / 2; + r.size.width = dim.x; + r.size.height = dim.y; + /* PENDING: cacheImageInRect under GNUSTEP does not account for + offset in x_set_window_size, so overestimate (4 fine on Cocoa) */ + surr = NSInsetRect (r, -10, -10); + ns_focus (frame, &surr, 1); + [[view window] cacheImageInRect: surr]; + [ns_lookup_indexed_color (NS_FACE_FOREGROUND + (FRAME_DEFAULT_FACE (frame)), frame) set]; + NSRectFill (r); + [[view window] flushWindow]; + ns_timeout (150000); + [[view window] restoreCachedImage]; + [[view window] flushWindow]; + ns_unfocus (frame); + } + [pool release]; + UNBLOCK_INPUT; + } + else + { + NSBeep (); + } +} + + +static void +ns_reset_terminal_modes (struct terminal *terminal) +/* Externally called as hook */ +{ + NSTRACE (ns_reset_terminal_modes); +} + +static void +ns_set_terminal_modes (struct terminal *terminal) +/* Externally called as hook */ +{ + NSTRACE (ns_set_terminal_modes); +} + + + +/* ========================================================================== + + Frame / window manager related functions + + ========================================================================== */ + + +static void +ns_raise_frame (struct frame *f) +/* -------------------------------------------------------------------------- + Bring window to foreground and make it active + -------------------------------------------------------------------------- */ +{ + NSView *view = FRAME_NS_VIEW (f); + check_ns (); + BLOCK_INPUT; + [[view window] makeKeyAndOrderFront: NSApp]; + UNBLOCK_INPUT; +} + + +static void +ns_lower_frame (struct frame *f) +/* -------------------------------------------------------------------------- + Send window to back + -------------------------------------------------------------------------- */ +{ + NSView *view = FRAME_NS_VIEW (f); + check_ns (); + BLOCK_INPUT; + [[view window] orderBack: NSApp]; + UNBLOCK_INPUT; +} + + +static void +ns_frame_raise_lower (struct frame *f, int raise) +/* -------------------------------------------------------------------------- + External (hook) + -------------------------------------------------------------------------- */ +{ + NSTRACE (ns_frame_raise_lower); + + if (raise) + ns_raise_frame (f); + else + ns_lower_frame (f); +} + + +static void +ns_frame_rehighlight (struct frame *frame) +/* -------------------------------------------------------------------------- + External (hook): called on things like window switching within frame + -------------------------------------------------------------------------- */ +{ + struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (frame); + struct frame *old_highlight = dpyinfo->ns_highlight_frame; + + NSTRACE (ns_frame_rehighlight); + if (dpyinfo->ns_focus_frame) + { + dpyinfo->ns_highlight_frame = + (FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->ns_focus_frame)) + ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->ns_focus_frame)) + : dpyinfo->ns_focus_frame); + if (!FRAME_LIVE_P (dpyinfo->ns_highlight_frame)) + { + FRAME_FOCUS_FRAME (dpyinfo->ns_focus_frame) = Qnil; + dpyinfo->ns_highlight_frame = dpyinfo->ns_focus_frame; + } + } + else + dpyinfo->ns_highlight_frame = 0; + + if (dpyinfo->ns_highlight_frame && + dpyinfo->ns_highlight_frame != old_highlight) + { + /* as of 20080602 the lower and raise are superfluous */ + if (old_highlight) + { + /*ns_lower_frame (old_highlight); */ + x_update_cursor (old_highlight, 1); + } + if (dpyinfo->ns_highlight_frame) + { + /*ns_raise_frame (dpyinfo->ns_highlight_frame); */ + x_update_cursor (dpyinfo->ns_highlight_frame, 1); + } + } +} + + +void +x_make_frame_visible (struct frame *f) +/* -------------------------------------------------------------------------- + External: Show the window (X11 semantics) + -------------------------------------------------------------------------- */ +{ + NSTRACE (x_make_frame_visible); + /* PENDING: at some points in past this was not needed, as the only place that + called this (frame.c:Fraise_frame ()) also called raise_lower; + if this ends up the case again, comment this out again. */ + if (!FRAME_VISIBLE_P (f)) + ns_raise_frame (f); +} + + +void +x_make_frame_invisible (struct frame *f) +/* -------------------------------------------------------------------------- + External: Hide the window (X11 semantics) + -------------------------------------------------------------------------- */ +{ + NSView * view = FRAME_NS_VIEW (f); + NSTRACE (x_make_frame_invisible); + check_ns (); + [[view window] orderOut: NSApp]; +} + + +void +x_iconify_frame (struct frame *f) +/* -------------------------------------------------------------------------- + External: Iconify window + -------------------------------------------------------------------------- */ +{ + NSView * view = FRAME_NS_VIEW (f); + struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (f); + NSTRACE (x_iconify_frame); + check_ns (); + + if (dpyinfo->ns_highlight_frame == f) + dpyinfo->ns_highlight_frame = 0; + + if ([[view window] windowNumber] <= 0) + { + /* the window is still deferred. Make it very small, bring it + on screen and order it out. */ + NSRect s = { { 100, 100}, {0, 0} }; + NSRect t; + t = [[view window] frame]; + [[view window] setFrame: s display: NO]; + [[view window] orderBack: NSApp]; + [[view window] orderOut: NSApp]; + [[view window] setFrame: t display: NO]; + } + [[view window] miniaturize: NSApp]; +} + + +void +x_destroy_window (struct frame *f) +/* -------------------------------------------------------------------------- + External: Delete the window + -------------------------------------------------------------------------- */ +{ + NSView *view = FRAME_NS_VIEW (f); + struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (f); + NSTRACE (x_destroy_window); + check_ns (); + + [(EmacsView *)view setWindowClosing: YES]; /* may not have been informed */ + + BLOCK_INPUT; + + free_frame_menubar (f); + + if (FRAME_FACE_CACHE (f)) + free_frame_faces (f); + + if (f == dpyinfo->ns_focus_frame) + dpyinfo->ns_focus_frame = 0; + if (f == dpyinfo->ns_highlight_frame) + dpyinfo->ns_highlight_frame = 0; + 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; + } + + xfree (f->output_data.ns); + + [[view window] close]; + [view release]; + + ns_window_num--; + UNBLOCK_INPUT; +} + + +void +x_set_offset (struct frame *f, int xoff, int yoff, int change_grav) +/* -------------------------------------------------------------------------- + External: Position the window + -------------------------------------------------------------------------- */ +{ + NSScreen *screen; + NSView *view = FRAME_NS_VIEW (f); + + NSTRACE (x_set_offset); + + BLOCK_INPUT; + + f->left_pos = xoff; + f->top_pos = yoff; +#ifdef NS_IMPL_GNUSTEP + if (xoff < 100) + f->left_pos = 100; /* don't overlap menu */ +#endif + if (view != nil && (screen = [[view window] screen])) + [[view window] setFrameTopLeftPoint: + NSMakePoint (SCREENMAXBOUND (f->left_pos), + SCREENMAXBOUND ([screen frame].size.height + - NS_TOP_POS (f)))]; + UNBLOCK_INPUT; +} + + +void +x_set_window_size (struct frame *f, int change_grav, int cols, int rows) +/* -------------------------------------------------------------------------- + Adjust window pixel size based on given character grid size + Impl is a bit more complex than other terms, need to do some + internal clipping and also pay attention to screen constraints. + -------------------------------------------------------------------------- */ +{ + EmacsView *view = FRAME_NS_VIEW (f); + EmacsToolbar *toolbar = [view toolbar]; + NSWindow *window = [view window]; + NSScreen *screen = [window screen]; + NSRect wr = [window frame]; + int tb = FRAME_EXTERNAL_TOOL_BAR (f); + int pixelwidth, pixelheight; + static int oldRows, oldCols, oldFontWidth, oldFontHeight; + static int oldTB; + static struct frame *oldF; + + NSTRACE (x_set_window_size); + + if (view == nil || + (f == oldF + && rows == oldRows && cols == oldCols + && oldFontWidth == FRAME_COLUMN_WIDTH (f) + && oldFontHeight == FRAME_LINE_HEIGHT (f) + && oldTB == tb)) + return; + +/*fprintf (stderr, "\tsetWindowSize: %d x %d, font size %d x %d\n", cols, rows, FRAME_COLUMN_WIDTH (f), FRAME_LINE_HEIGHT (f)); */ + + BLOCK_INPUT; + + check_frame_size (f, &rows, &cols); + oldF = f; + oldRows = rows; + oldCols = cols; + oldFontWidth = FRAME_COLUMN_WIDTH (f); + oldFontHeight = FRAME_LINE_HEIGHT (f); + oldTB = tb; + + f->scroll_bar_actual_width = NS_SCROLL_BAR_WIDTH (f); + compute_fringe_widths (f, 0); + + pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols); + pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows); + + /* If we have a change in toolbar display, calculate height */ + if (tb) + /* PENDING: GNUstep has not yet implemented the first method below, added + in Panther, however the second is incorrect under Cocoa. */ +#ifdef NS_IMPL_GNUSTEP + FRAME_NS_TOOLBAR_HEIGHT (f) = + NSHeight ([NSWindow frameRectForContentRect: NSMakeRect (0, 0, 0, 0) + styleMask: [window styleMask]]) + - FRAME_NS_TITLEBAR_HEIGHT (f); +#else + FRAME_NS_TOOLBAR_HEIGHT (f) = 32; + /* actually get wrong result here if toolbar not yet displayed + NSHeight ([window frameRectForContentRect: NSMakeRect (0, 0, 0, 0)]) + - FRAME_NS_TITLEBAR_HEIGHT (f); */ +#endif + else + FRAME_NS_TOOLBAR_HEIGHT (f) = 0; + + wr.size.width = pixelwidth + f->border_width; + wr.size.height = pixelheight + FRAME_NS_TITLEBAR_HEIGHT (f) + + FRAME_NS_TOOLBAR_HEIGHT (f); + + /* constrain to screen if we can */ + if (screen) + { + NSSize sz = [screen visibleFrame].size; + NSSize ez = { wr.size.width - sz.width, wr.size.height - sz.height }; + if (ez.width > 0) + { + int cr = ez.width / FRAME_COLUMN_WIDTH (f) + 1; + cols -= cr; + oldCols = cols; + wr.size.width -= cr * FRAME_COLUMN_WIDTH (f); + pixelwidth -= cr * FRAME_COLUMN_WIDTH (f); + } + if (ez.height > 0) + { + int rr = ez.height / FRAME_LINE_HEIGHT (f) + 1; + rows -= rr; + oldRows = rows; + wr.size.height -= rr * FRAME_LINE_HEIGHT (f); + pixelheight -= rr * FRAME_LINE_HEIGHT (f); + } + wr.origin.x = f->left_pos; + wr.origin.y = [screen frame].size.height - NS_TOP_POS (f) + - wr.size.height; + } + + [view setRows: rows andColumns: cols]; + [window setFrame: wr display: YES]; + +/*fprintf (stderr, "\tx_set_window_size %d, %d\t%d, %d\n", cols, rows, pixelwidth, pixelheight); */ + + /* This is a trick to compensate for Emacs' managing the scrollbar area + as a fixed number of standard character columns. Instead of leaving + blank space for the extra, we chopped it off above. Now for + left-hand scrollbars, we shift all rendering to the left by the + difference between the real width and Emacs' imagined one. For + right-hand bars, don't worry about it since the extra is never used. + (Obviously doesn't work for vertically split windows tho..) */ + NSPoint origin = FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f) + ? NSMakePoint (FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f) + - NS_SCROLL_BAR_WIDTH (f), 0) + : NSMakePoint (0, 0); + [view setFrame: NSMakeRect (0, 0, pixelwidth, pixelheight)]; + [view setBoundsOrigin: origin]; + + change_frame_size (f, rows, cols, 0, 1, 0); /* pretend, delay, safe */ + FRAME_PIXEL_WIDTH (f) = pixelwidth; + FRAME_PIXEL_HEIGHT (f) = pixelheight; +/* SET_FRAME_GARBAGED (f); // this short-circuits expose call in drawRect */ + + mark_window_cursors_off (XWINDOW (f->root_window)); + cancel_mouse_face (f); + + UNBLOCK_INPUT; +} + + +/* ========================================================================== + + Color management + + ========================================================================== */ + +NSColor * +ns_lookup_indexed_color (unsigned long idx, struct frame *f) +{ + struct ns_color_table *color_table = FRAME_NS_DISPLAY_INFO (f)->color_table; + return color_table->colors[idx]; +} + + +unsigned long +ns_index_color (NSColor *color, struct frame *f) +{ + struct ns_color_table *color_table = FRAME_NS_DISPLAY_INFO (f)->color_table; + int idx; + NSNumber *index; + + if (!color_table->colors) + { + color_table->size = NS_COLOR_CAPACITY; + color_table->avail = 1; /* skip idx=0 as marker */ + color_table->colors = + (NSColor **)xmalloc (color_table->size * sizeof (NSColor *)); + color_table->empty_indices = [[NSMutableSet alloc] init]; + } + + /* do we already have this color ? */ + { + int i; + for (i = 1; i < color_table->avail; i++) + { + if (color_table->colors[i] && [color_table->colors[i] isEqual: color]) + { + [color_table->colors[i] retain]; + return i; + } + } + } + + if ([color_table->empty_indices count] > 0) + { + index = [color_table->empty_indices anyObject]; + [color_table->empty_indices removeObject: index]; + idx = [index unsignedIntValue]; + } + else + { + if (color_table->avail == color_table->size) + { + color_table->size += NS_COLOR_CAPACITY; + color_table->colors = + (NSColor **)xrealloc (color_table->colors, + color_table->size * sizeof (NSColor *)); + } + idx = color_table->avail++; + index = [NSNumber numberWithUnsignedInt: idx]; + } + + color_table->colors[idx] = color; + [color retain]; +/*fprintf(stderr, "color_table: allocated %d\n",idx);*/ + return idx; +} + + +void +ns_free_indexed_color (unsigned long idx, struct frame *f) +{ + struct ns_color_table *color_table = FRAME_NS_DISPLAY_INFO (f)->color_table; + NSColor *color; + if (!idx) + return; + color = color_table->colors[idx]; + [color release]; + color_table->colors[idx] = nil; + [color_table->empty_indices addObject: [NSNumber numberWithUnsignedInt: idx]]; +/*fprintf(stderr, "color_table: FREED %d\n",idx);*/ +} + + +static int +ns_get_color (const char *name, NSColor **col) +/* -------------------------------------------------------------------------- + Parse a color name +/* -------------------------------------------------------------------------- +/* On *Step, we recognize several color formats, in addition to a catalog + of colors found in the file Emacs.clr. Color formats include: + - #rrggbb or RGBrrggbb where rr, gg, bb specify red, green and blue in hex + - ARGBaarrggbb is similar, with aa being the alpha channel (FF = opaque) + - HSVhhssvv and AHSVaahhssvv are similar for hue, saturation, value + - CMYKccmmyykk is similar for cyan, magenta, yellow, black. */ +{ + NSColor * new = nil; + const char *hex = NULL; + enum { rgb, argb, hsv, ahsv, cmyk, gray } color_space; + NSString *nsname = [NSString stringWithUTF8String: name]; + +/*fprintf (stderr, "ns_get_color: '%s'\n", name); */ + BLOCK_INPUT; + + if ([nsname isEqualToString: @"ns_selection_color"]) + { + nsname = ns_selection_color; + name = [ns_selection_color UTF8String]; + } + + if (name[0] == '0' || name[0] == '1' || name[0] == '.') + { + /* RGB decimal */ + NSScanner *scanner = [NSScanner scannerWithString: nsname]; + float r, g, b; + [scanner scanFloat: &r]; + [scanner scanFloat: &g]; + [scanner scanFloat: &b]; + *col = [NSColor colorWithCalibratedRed: r green: g blue: b alpha: 1.0]; + UNBLOCK_INPUT; + return 0; + } + + /* 23: PENDING: emacs seems to downcase everything before passing it here, + which we can work around, except for GRAY, since gray##, where ## is + decimal between 0 and 99, is also an X11 colorname. */ + if (name[0] == '#') /* X11 format */ + { + hex = name + 1; + color_space = rgb; + } + else if (!memcmp (name, "RGB", 3) || !memcmp (name, "rgb", 3)) + { + hex = name + 3; + color_space = rgb; + } + else if (!memcmp (name, "ARGB", 4) || !memcmp (name, "argb", 4)) + { + hex = name + 4; + color_space = argb; + } + else if (!memcmp (name, "HSV", 3) || !memcmp (name, "hsv", 3)) + { + hex = name + 3; + color_space = hsv; + } + else if (!memcmp (name, "AHSV", 4) || !memcmp (name, "ahsv", 4)) + { + hex = name + 4; + color_space = ahsv; + } + else if (!memcmp (name, "CMYK", 4) || !memcmp (name, "cmyk", 4)) + { + hex = name + 4; + color_space = cmyk; + } + else if (!memcmp (name, "GRAY", 4) /*|| !memcmp (name, "gray", 4)*/) + { + hex = name + 4; + color_space = gray; + } + + /* Direct colors (hex values) */ + if (hex) + { + unsigned int color = 0; + if (sscanf (hex, "%x", &color)) + { + float f1 = ((color >> 24) & 0xff) / 255.0; + float f2 = ((color >> 16) & 0xff) / 255.0; + float f3 = ((color >> 8) & 0xff) / 255.0; + float f4 = ((color ) & 0xff) / 255.0; + + switch (color_space) + { + case rgb: + *col = [NSColor colorWithCalibratedRed: f2 + green: f3 + blue: f4 + alpha: 1.0]; + break; + case argb: + *col = [NSColor colorWithCalibratedRed: f2 + green: f3 + blue: f4 + alpha: f1]; + break; + case hsv: + *col = [NSColor colorWithCalibratedHue: f2 + saturation: f3 + brightness: f4 + alpha: 1.0]; + break; + case ahsv: + *col = [NSColor colorWithCalibratedHue: f2 + saturation: f3 + brightness: f4 + alpha: f1]; + break; + case gray: + *col = [NSColor colorWithCalibratedWhite: f3 alpha: f4]; + break; + case cmyk: + *col = [NSColor colorWithDeviceCyan: f1 + magenta: f2 + yellow: f3 + black: f4 + alpha: 1.0]; + break; + } + *col = [*col colorUsingColorSpaceName: NSCalibratedRGBColorSpace]; + UNBLOCK_INPUT; + return 0; + } + } + + /* Otherwise, color is expected to be from a list */ + { + NSEnumerator *lenum, *cenum; + NSString *name; + NSColorList *clist; +#ifdef NS_IMPL_GNUSTEP + /* PENDING: who is wrong, the requestor or the implementation? */ + if ([nsname compare: @"Highlight" options: NSCaseInsensitiveSearch] + == NSOrderedSame) + nsname = @"highlightColor"; +#endif + if ([nsname compare: @"dark blue" options: NSCaseInsensitiveSearch] + == NSOrderedSame + || [nsname compare: @"darkblue" options: NSCaseInsensitiveSearch] + == NSOrderedSame) + nsname = @"navy blue"; + + lenum = [[NSColorList availableColorLists] objectEnumerator]; + while ( (clist = [lenum nextObject]) && new == nil) + { + cenum = [[clist allKeys] objectEnumerator]; + while ( (name = [cenum nextObject]) && new == nil ) + { + if ([name compare: nsname + options: NSCaseInsensitiveSearch] == NSOrderedSame ) + new = [clist colorWithKey: name]; + } + } + } + + if ( new ) + *col = [new colorUsingColorSpaceName: NSCalibratedRGBColorSpace]; +/* else + NSLog (@"Failed to find color '%@'", nsname); */ + UNBLOCK_INPUT; + return new ? 0 : 1; +} + + +static NSColor * +ns_get_color_default (const char *name, NSColor *dflt) +/* -------------------------------------------------------------------------- + Parse a color or use a default value + -------------------------------------------------------------------------- */ +{ + NSColor * col; + + if (ns_get_color (name, &col)) + return dflt; + else + return col; +} + + +int +ns_lisp_to_color (Lisp_Object color, NSColor **col) +/* -------------------------------------------------------------------------- + Convert a Lisp string object to a NS color + -------------------------------------------------------------------------- */ +{ + NSTRACE (ns_lisp_to_color); + if (XTYPE (color) == Lisp_String) + return ns_get_color (XSTRING (color)->data, col); + else if (XTYPE (color) == Lisp_Symbol) + return ns_get_color (XSTRING (XSYMBOL (color)->xname)->data, col); + return 1; +} + + +Lisp_Object +ns_color_to_lisp (NSColor *col) +/* -------------------------------------------------------------------------- + Convert a color to a lisp string with the RGB equivalent + -------------------------------------------------------------------------- */ +{ + float red, green, blue, alpha, gray; + char buf[1024]; + const char *str; + NSTRACE (ns_color_to_lisp); + + BLOCK_INPUT; + if ([[col colorSpaceName] isEqualToString: NSNamedColorSpace]) + + if ((str =[[col colorNameComponent] UTF8String])) + { + UNBLOCK_INPUT; + return build_string ((char *)str); + } + + [[col colorUsingColorSpaceName: NSCalibratedRGBColorSpace] + getRed: &red green: &green blue: &blue alpha: &alpha]; + if (red ==green && red ==blue) + { + [[col colorUsingColorSpaceName: NSCalibratedWhiteColorSpace] + getWhite: &gray alpha: &alpha]; + snprintf (buf, sizeof (buf), "GRAY%02.2lx%02.2lx", + lrint (gray * 0xff), lrint (alpha * 0xff)); + UNBLOCK_INPUT; + return build_string (buf); + } + + snprintf (buf, sizeof (buf), "ARGB%02.2lx%02.2lx%02.2lx%02.2lx", + lrint (alpha*0xff), + lrint (red*0xff), lrint (green*0xff), lrint (blue*0xff)); + + UNBLOCK_INPUT; + return build_string (buf); +} + + +int +ns_defined_color (struct frame *f, char *name, XColor *color_def, int alloc, + char makeIndex) +/* -------------------------------------------------------------------------- + 23: Return 1 if named color found, and set color_def rgb accordingly. + If makeIndex and alloc are nonzero put the color in the color_table, + and set color_def pixel to the resulting index. + If makeIndex is zero, set color_def pixel to ARGB. + Return 0 if not found + -------------------------------------------------------------------------- */ +{ + NSColor *temp; + float r, g, b, a; + int notFound = ns_get_color (name, &temp); + + NSTRACE (ns_defined_color); + + if (notFound) + return 0; + + if (makeIndex && alloc) + color_def->pixel = ns_index_color(temp, f);//[temp retain]; + + [temp getRed: &r green: &g blue: &b alpha: &a]; + color_def->red = r * 256; + color_def->green = g * 256; + color_def->blue = b * 256; + + if (!makeIndex) + color_def->pixel = + ARGB_TO_ULONG((int)(a*256), + color_def->red, color_def->green, color_def->blue); + + return 1; +} + + +unsigned long +ns_get_rgb_color (struct frame *f, float r, float g, float b, float a) +/* -------------------------------------------------------------------------- + return an autoreleased RGB color + -------------------------------------------------------------------------- */ +{ +/*static int c = 1; fprintf (stderr, "color request %d\n", c++); */ + if (r < 0.0) r = 0.0; + else if (r > 1.0) r = 1.0; + if (g < 0.0) g = 0.0; + else if (g > 1.0) g = 1.0; + if (b < 0.0) b = 0.0; + else if (b > 1.0) b = 1.0; + if (a < 0.0) a = 0.0; + else if (a > 1.0) a = 1.0; + return (unsigned long) ns_index_color( + [NSColor colorWithCalibratedRed: r green: g blue: b alpha: a], f); +} + + + +/* ========================================================================== + + Mouse handling + + ========================================================================== */ + + +void +x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y) +/* -------------------------------------------------------------------------- + Programmatically reposition mouse pointer in pixel coordinates + -------------------------------------------------------------------------- */ +{ + NSTRACE (x_set_mouse_pixel_position); + ns_raise_frame (f); +#if 0 + /*PENDING: this does not work, and what about GNUstep? */ +#ifdef NS_IMPL_COCOA + [FRAME_NS_VIEW (f) lockFocus]; + PSsetmouse ((float)pix_x, (float)pix_y); + [FRAME_NS_VIEW (f) unlockFocus]; +#endif +#endif +} + + +void +x_set_mouse_position (struct frame *f, int h, int v) +/* -------------------------------------------------------------------------- + Programmatically reposition mouse pointer in character coordinates + -------------------------------------------------------------------------- */ +{ + int pix_x, pix_y; + + pix_x = FRAME_COL_TO_PIXEL_X (f, h) + FRAME_COLUMN_WIDTH (f) / 2; + pix_y = FRAME_LINE_TO_PIXEL_Y (f, v) + FRAME_LINE_HEIGHT (f) / 2; + + if (pix_x < 0) pix_x = 0; + if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f); + + if (pix_y < 0) pix_y = 0; + if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f); + + x_set_mouse_pixel_position (f, pix_x, pix_y); +} + + +static int +note_mouse_movement (struct frame *frame, float x, float y) +/* ------------------------------------------------------------------------ + Called by EmacsView on mouseMovement events. Passes on + to emacs mainstream code if we moved off of a rect of interest + known as last_mouse_glyph. + ------------------------------------------------------------------------ */ +{ + NSTRACE (note_mouse_movement); + + XSETFRAME (last_mouse_motion_frame, frame); + + /* Note, this doesn't get called for enter/leave, since we don't have a + position. Those are taken care of in the corresponding NSView methods. */ + + /* has movement gone beyond last rect we were tracking? */ + if (x < last_mouse_glyph.origin.x || + x >= (last_mouse_glyph.origin.x + last_mouse_glyph.size.width) || + y < last_mouse_glyph.origin.y || + y >= (last_mouse_glyph.origin.y + last_mouse_glyph.size.height)) + { + frame->mouse_moved = 1; + note_mouse_highlight (frame, x, y); + remember_mouse_glyph (frame, x, y, &last_mouse_glyph); + return 1; + } + + return 0; +} + + +static void +ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, + enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y, + unsigned long *time) +/* -------------------------------------------------------------------------- + External (hook): inform emacs about mouse position and hit parts. + If a scrollbar is being dragged, set bar_window, part, x, y, time. + x & y should be position in the scrollbar (the whole bar, not the handle) + and length of scrollbar respectively + -------------------------------------------------------------------------- */ +{ + id view; + NSPoint position; + int xchar, ychar; + Lisp_Object frame, tail; + struct frame *f; + struct ns_display_info *dpyinfo; + + NSTRACE (ns_mouse_position); + + if (*fp == NULL) + { + fprintf (stderr, "Warning: ns_mouse_position () called with null *fp.\n"); + return; + } + + dpyinfo = FRAME_NS_DISPLAY_INFO (*fp); + + BLOCK_INPUT; + + if (last_mouse_scroll_bar != nil && insist == 0) + { + /* PENDING: we do not use this path at the moment because drag events will + go directly to the EmacsScroller. Leaving code in for now. */ + [last_mouse_scroll_bar getMouseMotionPart: (int *)part window: bar_window + x: x y: y]; + if (time) *time = last_mouse_movement_time; + last_mouse_scroll_bar = nil; + } + else + { + /* Clear the mouse-moved flag for every frame on this display. */ + FOR_EACH_FRAME (tail, frame) + if (FRAME_NS_P (XFRAME (frame)) + && FRAME_NS_DISPLAY (XFRAME (frame)) == FRAME_NS_DISPLAY (*fp)) + XFRAME (frame)->mouse_moved = 0; + + last_mouse_scroll_bar = nil; + if (last_mouse_frame && FRAME_LIVE_P (last_mouse_frame)) + f = last_mouse_frame; + else + f = dpyinfo->ns_focus_frame ? dpyinfo->ns_focus_frame + : SELECTED_FRAME (); + + if (f && f->output_data.ns) /*PENDING: 2nd check no longer needed? */ + { + view = FRAME_NS_VIEW (*fp); + + position = [[view window] mouseLocationOutsideOfEventStream]; + position = [view convertPoint: position fromView: nil]; + remember_mouse_glyph (f, position.x, position.y, &last_mouse_glyph); +/*fprintf (stderr, "ns_mouse_position: %.0f, %.0f\n", position.x, position.y); */ + + if (bar_window) *bar_window = Qnil; + if (part) *part = 0; /*scroll_bar_handle; */ + + if (x) XSETINT (*x, lrint (position.x)); + if (y) XSETINT (*y, lrint (position.y)); + if (time) *time = last_mouse_movement_time; + *fp = f; + } + } + + UNBLOCK_INPUT; +} + + +static void +ns_frame_up_to_date (struct frame *f) +/* -------------------------------------------------------------------------- + External (hook): Fix up mouse highlighting right after a full update. + Some highlighting was deferred if GC was happening during + note_mouse_highlight (), while other highlighting was deferred for update. + -------------------------------------------------------------------------- */ +{ + NSTRACE (ns_frame_up_to_date); + + if (FRAME_NS_P (f)) + { + struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (f); + if ((dpyinfo->mouse_face_deferred_gc||f ==dpyinfo->mouse_face_mouse_frame) + /*&& 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; + } + } +} + + +void +ns_define_frame_cursor (struct frame *f, Cursor cursor) +/* -------------------------------------------------------------------------- + External (RIF): set frame mouse pointer type. + -------------------------------------------------------------------------- */ +{ + NSTRACE (ns_define_frame_cursor); + if (FRAME_POINTER_TYPE (f) != cursor) + { + EmacsView *view = FRAME_NS_VIEW (f); + FRAME_POINTER_TYPE (f) = cursor; + [[view window] invalidateCursorRectsForView: view]; + } +} + + + +/* ========================================================================== + + Keyboard handling + + ========================================================================== */ + + +static unsigned +ns_convert_key (unsigned code) +/* -------------------------------------------------------------------------- + Internal call used by NSView-keyDown. + -------------------------------------------------------------------------- */ +{ + const unsigned last_keysym = (sizeof (convert_ns_to_X_keysym) + / sizeof (convert_ns_to_X_keysym[0])); + unsigned keysym; + /* An array would be faster, but less easy to read. */ + for (keysym = 0; keysym < last_keysym; keysym += 2) + if (code == convert_ns_to_X_keysym[keysym]) + return 0xFF00 | convert_ns_to_X_keysym[keysym+1]; + return 0; +/* if decide to use keyCode and Carbon table, use this line: + return code > 0xff ? 0 : 0xFF00 | ns_keycode_to_xkeysym_table[code]; */ +} + + +char * +x_get_keysym_name (int keysym) +/* -------------------------------------------------------------------------- + Called by keyboard.c. Not sure if the return val is important, except + that it be unique. + -------------------------------------------------------------------------- */ +{ + static char value[16]; + NSTRACE (x_get_keysym_name); + sprintf (value, "%d", keysym); + return value; +} + + + +/* ========================================================================== + + Block drawing operations + + ========================================================================== */ + + +static void +ns_redraw_scroll_bars (struct frame *f) +{ + int i; + id view; + NSArray *subviews = [[FRAME_NS_VIEW (f) superview] subviews]; + NSTRACE (ns_judge_scroll_bars); + for (i =[subviews count]-1; i >= 0; i--) + { + view = [subviews objectAtIndex: i]; + if (![view isKindOfClass: [EmacsScroller class]]) continue; + [view display]; + } +} + + +void +ns_clear_frame (struct frame *f) +/* -------------------------------------------------------------------------- + External (hook): Erase the entire frame + -------------------------------------------------------------------------- */ +{ + NSView *view = FRAME_NS_VIEW (f); + NSRect r; + + NSTRACE (ns_clear_frame); + if (ns_in_resize) + return; + + /* comes on initial frame because we have + after-make-frame-functions = select-frame */ + if (!FRAME_DEFAULT_FACE (f)) + return; + + mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f))); + + output_cursor.hpos = output_cursor.vpos = 0; + output_cursor.x = -1; + + r = [view bounds]; + + BLOCK_INPUT; + ns_focus (f, &r, 1); + [ns_lookup_indexed_color (NS_FACE_BACKGROUND (FRAME_DEFAULT_FACE (f)), f) set]; + NSRectFill (r); + ns_unfocus (f); + +#ifdef NS_IMPL_COCOA + [[view window] display]; /* redraw resize handle */ +#endif + + /* as of 2006/11 or so this is now needed */ + ns_redraw_scroll_bars (f); + UNBLOCK_INPUT; +} + + +void +ns_clear_frame_area (struct frame *f, int x, int y, int width, int height) +/* -------------------------------------------------------------------------- + 23: External (RIF): Clear section of frame + -------------------------------------------------------------------------- */ +{ + NSRect r = NSMakeRect (x, y, width, height); + NSView *view = FRAME_NS_VIEW (f); + struct face *face = FRAME_DEFAULT_FACE (f); + + if (!view || !face) + return; + + r = NSIntersectionRect (r, [view frame]); + ns_focus (f, &r, 1); + [ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f) set]; + +#ifdef NS_IMPL_COCOA + { + /* clip out the resize handle */ + NSWindow *window = [FRAME_NS_VIEW (f) window]; + NSRect ir = + [view convertRect: ns_resize_handle_rect (window) fromView: nil]; + + ir = NSIntersectionRect (r, ir); + if (NSIsEmptyRect (ir)) + { +#endif + + NSRectFill (r); + +#ifdef NS_IMPL_COCOA + } + else + { + NSRect r1 = r, r2 = r; /* upper and lower non-intersecting */ + r1.size.height -= ir.size.height; + r2.origin.y += r1.size.height; + r2.size.width -= ir.size.width; + r2.size.height = ir.size.height; + NSRectFill (r1); + NSRectFill (r2); + } + } +#endif + + ns_unfocus (f); + return; +} + + +static void +ns_scroll_run (struct window *w, struct run *run) +/* -------------------------------------------------------------------------- + 23: External (RIF): Insert or delete n lines at line vpos + -------------------------------------------------------------------------- */ +{ + struct frame *f = XFRAME (w->frame); + int x, y, width, height, from_y, to_y, bottom_y; + + NSTRACE (ns_scroll_run); + + /* begin copy from other terms */ + /* Get frame-relative bounding box of the text display area of W, + without mode lines. Include in this box the left and right + fringe of W. */ + window_box (w, -1, &x, &y, &width, &height); + + 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; + } + /* end copy from other terms */ + + if (height == 0) + return; + + BLOCK_INPUT; + + updated_window = w; + x_clear_cursor (w); + + { + NSRect srcRect = NSMakeRect (x, from_y, width, height); + NSRect dstRect = NSMakeRect (x, to_y, width, height); + NSPoint dstOrigin = NSMakePoint (x, to_y); + + ns_focus (f, &dstRect, 1); + NSCopyBits (0, srcRect , dstOrigin); + ns_unfocus (f); + } + + UNBLOCK_INPUT; +} + + +static void +ns_after_update_window_line (struct glyph_row *desired_row) +/* -------------------------------------------------------------------------- + 23: External (RIF): preparatory to fringe update after text was updated + -------------------------------------------------------------------------- */ +{ + struct window *w = updated_window; + struct frame *f; + int width, height; + + NSTRACE (ns_after_update_window_line); + + /* begin copy from other terms */ + xassert (w); + + if (!desired_row->mode_line_p && !w->pseudo_window_p) + desired_row->redraw_fringe_bitmaps_p = 1; + + /* When a window has disappeared, make sure that no rest of + full-width rows stays visible in the internal border. + Under NS this is drawn inside the fringes. */ + if (windows_or_buffers_changed + && (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; + /* end copy from other terms */ + + BLOCK_INPUT; + if (!desired_row->full_width_p) + { + int x1 = WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w) + + WINDOW_LEFT_FRINGE_WIDTH (w); + int x2 = WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w) + + FRAME_PIXEL_WIDTH (f) - NS_SCROLL_BAR_WIDTH (f) + - WINDOW_RIGHT_FRINGE_WIDTH (w) + - FRAME_INTERNAL_BORDER_WIDTH (f); + ns_clear_frame_area (f, x1, y, width, height); + ns_clear_frame_area (f, x2, y, width, height); + } + UNBLOCK_INPUT; + } +} + + +static void +ns_shift_glyphs_for_insert (struct frame *f, + int x, int y, int width, int height, + int shift_by) +/* -------------------------------------------------------------------------- + 23: External (RIF): copy an area horizontally, don't worry about clearing src + -------------------------------------------------------------------------- */ +{ + NSRect srcRect = NSMakeRect (x, y, width, height); + NSRect dstRect = NSMakeRect (x+shift_by, y, width, height); + NSPoint dstOrigin = dstRect.origin; + + NSTRACE (ns_shift_glyphs_for_insert); + + ns_focus (f, &dstRect, 1); + NSCopyBits (0, srcRect, dstOrigin); + ns_unfocus (f); +} + + + +/* ========================================================================== + + Character encoding and metrics + + ========================================================================== */ + + +static inline void +ns_compute_glyph_string_overhangs (struct glyph_string *s) +/* -------------------------------------------------------------------------- + 23: External (RIF); compute left/right overhang of whole string and set in s + -------------------------------------------------------------------------- */ +{ + struct face *face = FACE_FROM_ID (s->f, s->first_glyph->face_id); + struct font *font = s->font; /*face->font; */ + + if (s->char2b) + { + struct font_metrics metrics; + unsigned int codes[2]; + codes[0] = *(s->char2b); + codes[1] = *(s->char2b + s->nchars - 1); + + font->driver->text_extents (font, codes, 2, &metrics); + s->left_overhang = -metrics.lbearing; + s->right_overhang = + metrics.rbearing > metrics.width ? metrics.rbearing - metrics.width : 0; + } + else + { + s->left_overhang = 0; + s->right_overhang = ((struct nsfont_info *)font)->ital ? + FONT_HEIGHT (font) * 0.2 : 0; + } +} + + + +/* ========================================================================== + + Fringe and cursor drawing + + ========================================================================== */ + + +extern int max_used_fringe_bitmap; +static void +ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row, + struct draw_fringe_bitmap_params *p) +/* -------------------------------------------------------------------------- + 23: External (RIF); fringe-related + -------------------------------------------------------------------------- */ +{ + struct frame *f = XFRAME (WINDOW_FRAME (w)); + struct face *face = p->face; + int rowY; + static EmacsImage **bimgs = NULL; + static int nBimgs = 0; + /* NS-specific: move internal border inside fringe */ + int x = p->bx < 0 ? p->x : p->bx; + int wd = p->bx < 0 ? p->wd : p->nx; + BOOL fringeOnVeryLeft = + x - WINDOW_LEFT_SCROLL_BAR_COLS (w) * WINDOW_FRAME_COLUMN_WIDTH (w) + - FRAME_INTERNAL_BORDER_WIDTH (f) < 10; + BOOL fringeOnVeryRight = + FRAME_PIXEL_WIDTH (f) - x - wd - FRAME_INTERNAL_BORDER_WIDTH (f) + - WINDOW_RIGHT_SCROLL_BAR_COLS (w) * WINDOW_FRAME_COLUMN_WIDTH (w) < 10; + int xAdjust = FRAME_INTERNAL_BORDER_WIDTH (f) * + (fringeOnVeryLeft ? -1 : (fringeOnVeryRight ? 1 : 0)); + + /* grow bimgs if needed */ + if (nBimgs < max_used_fringe_bitmap) + { + EmacsImage **newBimgs = + xmalloc (max_used_fringe_bitmap * sizeof (EmacsImage *)); + bzero (newBimgs, max_used_fringe_bitmap * sizeof (EmacsImage *)); + + if (nBimgs) + { + bcopy (bimgs, newBimgs, nBimgs * sizeof (EmacsImage *)); + xfree (bimgs); + } + + bimgs = newBimgs; + nBimgs = max_used_fringe_bitmap; + } + + /* Must clip because of partially visible lines. */ + rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y); + if (p->y < rowY) + { + /* Adjust position of "bottom aligned" bitmap on partially + visible last row. */ + int oldY = row->y; + int oldVH = row->visible_height; + row->visible_height = p->h; + row->y -= rowY - p->y; + ns_clip_to_row (w, row, -1, NULL); + row->y = oldY; + row->visible_height = oldVH; + } + else + ns_clip_to_row (w, row, -1, YES); + + if (p->bx >= 0 && !p->overlay_p) + { + int yAdjust = rowY - FRAME_INTERNAL_BORDER_WIDTH (f) < 5 ? + -FRAME_INTERNAL_BORDER_WIDTH (f) : 0; + int yIncr = FRAME_PIXEL_HEIGHT (f) - (p->by+yAdjust + p->ny) < 5 ? + FRAME_INTERNAL_BORDER_WIDTH (f) : 0; + if (yAdjust) + yIncr += FRAME_INTERNAL_BORDER_WIDTH (f); + NSRect r = NSMakeRect (p->bx+xAdjust, p->by+yAdjust, p->nx, p->ny+yIncr); + NSRectClip (r); + [ns_lookup_indexed_color(face->background, f) set]; + NSRectFill (r); + } + + if (p->which) + { + NSRect r = NSMakeRect (p->x+xAdjust, p->y, p->wd, p->h); + NSPoint pt = r.origin; + EmacsImage *img = bimgs[p->which - 1]; + + if (!img) + { + unsigned short *bits = p->bits + p->dh; + int len = 8 * p->h/8; + int i; + unsigned char *cbits = xmalloc (len); + + for (i =0; ih + flip: NO]; + bimgs[p->which - 1] = img; + xfree (cbits); + } + + NSRectClip (r); + /* Since we composite the bitmap instead of just blitting it, we need + to erase the whole background. */ + [ns_lookup_indexed_color(face->background, f) set]; + NSRectFill (r); + pt.y += p->h; + [img setXBMColor: ns_lookup_indexed_color(face->foreground, f)]; + [img compositeToPoint: pt operation: NSCompositeSourceOver]; + } + ns_unfocus (f); +} + + +void +ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, + int x, int y, int cursor_type, int cursor_width, + int on_p, int active_p) +/* -------------------------------------------------------------------------- + External call (RIF): draw cursor + -------------------------------------------------------------------------- */ +{ + NSRect r, s; + int fx, fy, h; + struct frame *f = WINDOW_XFRAME (w); + struct glyph *phys_cursor_glyph; + int overspill; + unsigned char drawGlyph = 0, cursorType, oldCursorType; + + NSTRACE (dumpcursor); + + if (!on_p) + return; + + w->phys_cursor_type = cursor_type; + w->phys_cursor_on_p = 1; + + if (cursor_type == NO_CURSOR) + { + w->phys_cursor_width = 0; + return; + } + + if ((phys_cursor_glyph = get_phys_cursor_glyph (w)) == NULL) + { + if (glyph_row->exact_window_width_line_p + && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA]) + { + glyph_row->cursor_in_fringe_p = 1; + draw_fringe_bitmap (w, glyph_row, 0); + } + return; + } + + get_phys_cursor_geometry (w, glyph_row, phys_cursor_glyph, &fx, &fy, &h); + + r.origin.x = fx, r.origin.y = fy; + r.size.height = h; + r.size.width = w->phys_cursor_width; + + /* PENDING: if we overwrite the internal border area, it does not get erased; + fix by truncating cursor, but better would be to erase properly */ + overspill = r.origin.x + r.size.width - + WINDOW_TEXT_TO_FRAME_PIXEL_X (w, WINDOW_BOX_RIGHT_EDGE_X (w) + - WINDOW_TOTAL_FRINGE_WIDTH (w) - FRAME_INTERNAL_BORDER_WIDTH (f)); + if (overspill > 0) + r.size.width -= overspill; + + /* PENDING: 23: use emacs stored f->cursor_type instead of ns-specific */ + oldCursorType = FRAME_CURSOR (f); + cursorType = FRAME_CURSOR (f) = FRAME_NEW_CURSOR (f); + f->output_data.ns->current_cursor_color = + f->output_data.ns->desired_cursor_color; + + /* PENDING: only needed in rare cases with last-resort font in HELLO.. + should we do this more efficiently? */ + ns_clip_to_row (w, glyph_row, -1, NULL); +/* ns_focus (f, &r, 1); */ + + if (FRAME_LAST_INACTIVE (f)) + { + /* previously hollow box; clear entire area */ + [FRAME_BACKGROUND_COLOR (f) set]; + NSRectFill (r); + drawGlyph = 1; + FRAME_LAST_INACTIVE (f) = NO; + } + + /* prepare to draw */ + if (cursorType == no_highlight || cursor_type == NO_CURSOR) + { + /* clearing for blink: erase the cursor itself */ + [FRAME_BACKGROUND_COLOR (f) set]; + cursorType = oldCursorType; /* just clear what we had before */ + } + else + [FRAME_CURSOR_COLOR (f) set]; + + if (!active_p) + { + /* inactive window: ignore what we just set and use a hollow box */ + cursorType = hollow_box; + [FRAME_CURSOR_COLOR (f) set]; + } + + switch (cursorType) + { + case no_highlight: + break; + case filled_box: + NSRectFill (r); + drawGlyph = 1; + break; + case hollow_box: + NSRectFill (r); + [FRAME_BACKGROUND_COLOR (f) set]; + NSRectFill (NSInsetRect (r, 1, 1)); + [FRAME_CURSOR_COLOR (f) set]; + drawGlyph = 1; + break; + case underscore: + s = r; + s.origin.y += lrint (0.75 * s.size.height); + s.size.height = lrint (s.size.height * 0.25); + NSRectFill (s); + break; + case bar: + s = r; + s.size.width = 1; + NSRectFill (s); + break; + } + ns_unfocus (f); + + /* if needed, draw the character under the cursor */ + if (drawGlyph) + draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR); +} + + +static void +ns_draw_vertical_window_border (struct window *w, int x, int y0, int y1) +/* -------------------------------------------------------------------------- + External (RIF): Draw a vertical line. + -------------------------------------------------------------------------- */ +{ + struct frame *f = XFRAME (WINDOW_FRAME (w)); + struct face *face; + NSRect r = NSMakeRect (x, y0, 2, y1-y0); + + face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID); + if (face) + [ns_lookup_indexed_color(face->foreground, f) set]; + + ns_focus (f, &r, 1); + NSDrawGroove (r, r); + ns_unfocus (f); +} + + +void +show_hourglass (struct atimer *timer) +{ + if (hourglass_shown_p) + return; + + BLOCK_INPUT; + + /*PENDING: add NSProgressIndicator to selected frame (see macfns.c) */ + + hourglass_shown_p = 1; + UNBLOCK_INPUT; +} + + +void +hide_hourglass () +{ + if (!hourglass_shown_p) + return; + + /*PENDING: remove NSProgressIndicator from all frames */ + + hourglass_shown_p = 0; + UNBLOCK_INPUT; +} + + + +/* ========================================================================== + + Glyph drawing operations + + ========================================================================== */ + + +static inline NSRect +/* -------------------------------------------------------------------------- + Under NS we draw internal borders inside fringes, and want full-width + rendering to go all the way to edge. This function makes that correction. + -------------------------------------------------------------------------- */ +ns_fix_rect_ibw (NSRect r, int fibw, int frame_pixel_width) +{ + if (r.origin.y <= fibw+1) + { + r.size.height += r.origin.y; + r.origin.y = 0; + } + if (r.origin.x <= fibw+1) + { + r.size.width += r.origin.x; + r.origin.x = 0; + } + if (frame_pixel_width - (r.origin.x+r.size.width) <= fibw+1) + r.size.width += fibw; + + return r; +} + + +static int +ns_get_glyph_string_clip_rect (struct glyph_string *s, NativeRectangle *nr) +/* -------------------------------------------------------------------------- + Wrapper utility to account for internal border width on full-width lines, + and allow top full-width rows to hit the frame top. nr should be pointer + to two successive NSRects. Number of rects actually used is returned. + -------------------------------------------------------------------------- */ +{ + int n = get_glyph_string_clip_rects (s, nr, 2); + if (s->row->full_width_p) + { + *nr = ns_fix_rect_ibw (*nr, FRAME_INTERNAL_BORDER_WIDTH (s->f), + FRAME_PIXEL_WIDTH (s->f)); + if (n == 2) + *nr = ns_fix_rect_ibw (*(nr+1), FRAME_INTERNAL_BORDER_WIDTH (s->f), + FRAME_PIXEL_WIDTH (s->f)); + } + return n; +} + + +static void +ns_draw_box (NSRect r, float thickness, NSColor *col, char left_p, char right_p) +/* -------------------------------------------------------------------------- + Draw an unfilled rect inside r, optionally leaving left and/or right open. + Note we can't just use an NSDrawRect command, because of the possibility + of some sides not being drawn, and because the rect will be filled. + -------------------------------------------------------------------------- */ +{ + NSRect s = r; + [col set]; + + /* top, bottom */ + s.size.height = thickness; + NSRectFill (s); + s.origin.y += r.size.height - thickness; + NSRectFill (s); + + s.size.height = r.size.height; + s.origin.y = r.origin.y; + + /* left, right (optional) */ + s.size.width = thickness; + if (left_p) + NSRectFill (s); + if (right_p) + { + s.origin.x += r.size.width - thickness; + NSRectFill (s); + } +} + + +static void +ns_draw_relief (NSRect r, int thickness, char raised_p, + char top_p, char bottom_p, char left_p, char right_p, + struct glyph_string *s) +/* -------------------------------------------------------------------------- + Draw a relief rect inside r, optionally leaving some sides open. + Note we can't just use an NSDrawBezel command, because of the possibility + of some sides not being drawn, and because the rect will be filled. + -------------------------------------------------------------------------- */ +{ + static NSColor *baseCol = nil, *lightCol = nil, *darkCol = nil; + NSColor *newBaseCol = nil; + NSRect sr = r; + + NSTRACE (ns_draw_relief); + + /* set up colors */ + + if (s->face->use_box_color_for_shadows_p) + { + newBaseCol = ns_lookup_indexed_color (s->face->box_color, s->f); + } +/* else if (s->first_glyph->type == IMAGE_GLYPH + && s->img->pixmap + && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0)) + { + newBaseCol = IMAGE_BACKGROUND (s->img, s->f, 0); + } */ + else + { + newBaseCol = ns_lookup_indexed_color (s->face->background, s->f); + } + + if (newBaseCol == nil) + newBaseCol = [NSColor grayColor]; + + if (newBaseCol != baseCol) /* PENDING: better check */ + { + [baseCol release]; + baseCol = [newBaseCol retain]; + [lightCol release]; + lightCol = [[baseCol highlightWithLevel: 0.2] retain]; + [darkCol release]; + darkCol = [[baseCol shadowWithLevel: 0.3] retain]; + } + + [(raised_p ? lightCol : darkCol) set]; + + /* TODO: mitering. Using NSBezierPath doesn't work because of color switch. */ + + /* top */ + sr.size.height = thickness; + if (top_p) NSRectFill (sr); + + /* left */ + sr.size.height = r.size.height; + sr.size.width = thickness; + if (left_p) NSRectFill (sr); + + [(raised_p ? darkCol : lightCol) set]; + + /* bottom */ + sr.size.width = r.size.width; + sr.size.height = thickness; + sr.origin.y += r.size.height - thickness; + if (bottom_p) NSRectFill (sr); + + /* right */ + sr.size.height = r.size.height; + sr.origin.y = r.origin.y; + sr.size.width = thickness; + sr.origin.x += r.size.width - thickness; + if (right_p) NSRectFill (sr); +} + + +static void +ns_dumpglyphs_box_or_relief (struct glyph_string *s) +/* -------------------------------------------------------------------------- + Function modeled after x_draw_glyph_string_box (). + Sets up parameters for drawing. + -------------------------------------------------------------------------- */ +{ + int right_x, last_x; + char left_p, right_p; + struct glyph *last_glyph; + NSRect r; + int thickness; + struct face *face; + + if (s->hl == DRAW_MOUSE_FACE) + { + face = FACE_FROM_ID + (s->f, FRAME_NS_DISPLAY_INFO (s->f)->mouse_face_face_id); + if (!face) + face = FACE_FROM_ID (s->f, MOUSE_FACE_ID); + } + else + face = s->face; + + thickness = face->box_line_width; + + NSTRACE (ns_dumpglyphs_box_or_relief); + + last_x = ((s->row->full_width_p && !s->w->pseudo_window_p) + ? WINDOW_RIGHT_EDGE_X (s->w) + : window_box_right (s->w, s->area)); + last_glyph = (s->cmp || s->img + ? s->first_glyph : s->first_glyph + s->nchars-1); + + 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)); + + 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))); + + r = NSMakeRect (s->x, s->y, right_x - s->x + 1, s->height); + + /* expand full-width row over internal borders */ + if (s->row->full_width_p) + r = ns_fix_rect_ibw (r, FRAME_INTERNAL_BORDER_WIDTH (s->f), + FRAME_PIXEL_WIDTH (s->f)); + + if (s->face->box == FACE_SIMPLE_BOX) + { + xassert (s->face->box_color != nil); + ns_draw_box (r, abs (thickness), + ns_lookup_indexed_color (face->box_color, s->f), + left_p, right_p); + } + else + { + ns_draw_relief (r, abs (thickness), s->face->box == FACE_RAISED_BOX, + 1, 1, left_p, right_p, s); + } +} + + +static void +ns_maybe_dumpglyphs_background (struct glyph_string *s, char force_p) +/* -------------------------------------------------------------------------- + Modeled after x_draw_glyph_string_background, which draws BG in + certain cases. Others are left to the text rendering routine. + -------------------------------------------------------------------------- */ +{ + NSTRACE (ns_maybe_dumpglyphs_background); + + if (!s->background_filled_p/* || s->hl == DRAW_MOUSE_FACE*/) + { + int box_line_width = max (s->face->box_line_width, 0); + 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) + { + struct face *face; + if (s->hl == DRAW_MOUSE_FACE) + { + face = FACE_FROM_ID + (s->f, FRAME_NS_DISPLAY_INFO (s->f)->mouse_face_face_id); + if (!face) + face = FACE_FROM_ID (s->f, MOUSE_FACE_ID); + } + else + face = FACE_FROM_ID (s->f, s->first_glyph->face_id); + if (!face->stipple) + [(NS_FACE_BACKGROUND (face) != nil + ? ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f) + : FRAME_BACKGROUND_COLOR (s->f)) set]; + else + { + struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (s->f); + [[dpyinfo->bitmaps[face->stipple-1].img stippleMask] set]; + } + + if (s->hl != DRAW_CURSOR) + { + NSRect r = NSMakeRect (s->x, s->y + box_line_width, + s->background_width, + s->height-2*box_line_width); + + /* expand full-width row over internal borders */ + if (s->row->full_width_p) + { + int fibw = FRAME_INTERNAL_BORDER_WIDTH (s->f); + if (r.origin.y <= fibw+1 + box_line_width) + { + r.size.height += r.origin.y; + r.origin.y = 0; + } + if (r.origin.x <= fibw+1) + { + r.size.width += 2*r.origin.x; + r.origin.x = 0; + } + if (FRAME_PIXEL_WIDTH (s->f) - (r.origin.x + r.size.width) + <= fibw+1) + r.size.width += fibw; + } + + NSRectFill (r); + } + + s->background_filled_p = 1; + } + } +} + + +static void +ns_dumpglyphs_image (struct glyph_string *s, NSRect r) +/* -------------------------------------------------------------------------- + Renders an image and associated borders. + -------------------------------------------------------------------------- */ +{ + EmacsImage *img = s->img->pixmap; + int box_line_vwidth = max (s->face->box_line_width, 0); + int x = s->x, y = s->ybase - image_ascent (s->img, s->face, &s->slice); + int bg_x, bg_y, bg_height; + int th; + char raised_p; + NSRect br; + + NSTRACE (ns_dumpglyphs_image); + + if (s->face->box != FACE_NO_BOX + && s->first_glyph->left_box_line_p && s->slice.x == 0) + x += abs (s->face->box_line_width); + + bg_x = x; + bg_y = s->slice.y == 0 ? s->y : s->y + box_line_vwidth; + bg_height = s->height; + /* other terms have this, but was causing problems w/tabbar mode */ + /* - 2 * box_line_vwidth; */ + + if (s->slice.x == 0) x += s->img->hmargin; + if (s->slice.y == 0) y += s->img->vmargin; + + /* Draw BG: if we need larger area than image itself cleared, do that, + otherwise, since we composite the image under NS (instead of mucking + with its background color), we must clear just the image area. */ + [ns_lookup_indexed_color (NS_FACE_BACKGROUND + (FACE_FROM_ID (s->f, s->first_glyph->face_id)), s->f) set]; + + if (bg_height > s->slice.height || s->img->hmargin || s->img->vmargin + || s->img->mask || s->img->pixmap == 0 || s->width != s->background_width) + { + br = NSMakeRect (bg_x, bg_y, s->background_width, bg_height); + s->background_filled_p = 1; + } + else + { + br = NSMakeRect (x, y, s->slice.width, s->slice.height); + } + + /* expand full-width row over internal borders */ + if (s->row->full_width_p) + { + int fibw = FRAME_INTERNAL_BORDER_WIDTH (s->f); + if (br.origin.y <= fibw+1 + box_line_vwidth) + { + br.size.height += br.origin.y; + br.origin.y = 0; + } + if (br.origin.x <= fibw+1 + box_line_vwidth) + { + br.size.width += br.origin.x; + br.origin.x = 0; + } + if (FRAME_PIXEL_WIDTH (s->f) - (br.origin.x + br.size.width) <= fibw+1) + br.size.width += fibw; + } + + NSRectFill (br); + + /* Draw the image.. do we need to draw placeholder if img ==nil? */ + if (img != nil) + [img compositeToPoint: NSMakePoint (x, y + s->slice.height) + operation: NSCompositeSourceOver]; + + /* Draw relief, if requested */ + if (s->img->relief || s->hl ==DRAW_IMAGE_RAISED || s->hl ==DRAW_IMAGE_SUNKEN) + { + if (s->hl == DRAW_IMAGE_SUNKEN || s->hl == DRAW_IMAGE_RAISED) + { + th = tool_bar_button_relief >= 0 ? + tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF; + raised_p = (s->hl == DRAW_IMAGE_RAISED); + } + else + { + th = abs (s->img->relief); + raised_p = (s->img->relief > 0); + } + + r.origin.x = x - th; + r.origin.y = y - th; + r.size.width = s->slice.width + 2*th-1; + r.size.height = s->slice.height + 2*th-1; + ns_draw_relief (r, th, raised_p, + s->slice.y == 0, + s->slice.y + s->slice.height == s->img->height, + s->slice.x == 0, + s->slice.x + s->slice.width == s->img->width, s); + } +} + + +static void +ns_draw_glyph_string (struct glyph_string *s) +/* -------------------------------------------------------------------------- + External (RIF): Main draw-text call. + -------------------------------------------------------------------------- */ +{ + /*PENDING (optimize): focus for box and contents draw */ + NSRect r[2]; + int n; + char box_drawn_p = 0; + + NSTRACE (ns_draw_glyph_string); + + if (s->next && s->right_overhang && !s->for_overlaps && s->hl != DRAW_CURSOR) + { + xassert (s->next->img == NULL); + n = ns_get_glyph_string_clip_rect (s->next, r); + ns_focus (s->f, r, n); + ns_maybe_dumpglyphs_background (s->next, 1); + ns_unfocus (s->f); + } + + if (!s->for_overlaps && s->face->box != FACE_NO_BOX + && (s->first_glyph->type == CHAR_GLYPH + || s->first_glyph->type == COMPOSITE_GLYPH)) + { + n = ns_get_glyph_string_clip_rect (s, r); + ns_focus (s->f, r, n); + ns_maybe_dumpglyphs_background (s, 1); + ns_dumpglyphs_box_or_relief (s); + ns_unfocus (s->f); + box_drawn_p = 1; + } + + switch (s->first_glyph->type) + { + + case IMAGE_GLYPH: + n = ns_get_glyph_string_clip_rect (s, r); + ns_focus (s->f, r, n); + ns_dumpglyphs_image (s, r[0]); + ns_unfocus (s->f); + break; + + case STRETCH_GLYPH: + if (!s->background_filled_p) + { + *r = NSMakeRect (s->x, s->y, s->background_width, s->height); + + if (!s->row->full_width_p) + { + /* truncate to avoid overwriting fringe and/or scrollbar */ + int overrun = max (0, (s->x + s->background_width) + - (WINDOW_BOX_RIGHT_EDGE_X (s->w) + - WINDOW_RIGHT_FRINGE_WIDTH (s->w))); + r[0].size.width -= overrun; + + /* PENDING: Try to work between problem where a stretch glyph on + a partially-visible bottom row will clear part of the + modeline, and another where list-buffers headers and similar + rows erroneously have visible_height set to 0. Not sure + where this is coming from as other terms seem not to show. */ + r[0].size.height = min (s->height, s->row->visible_height); + } + + /* expand full-width rows over internal borders */ + else + { + r[0] = ns_fix_rect_ibw (r[0], FRAME_INTERNAL_BORDER_WIDTH (s->f), + FRAME_PIXEL_WIDTH (s->f)); + } + + /* NOTE: under NS this is NOT used to draw cursors, but we must avoid + overwriting cursor (usually when cursor on a tab) */ + if (s->hl == DRAW_CURSOR) + { + r[0].origin.x += s->width; + r[0].size.width -= s->width; + } + + ns_focus (s->f, r, 1); + [ns_lookup_indexed_color (NS_FACE_BACKGROUND + (FACE_FROM_ID (s->f, s->first_glyph->face_id)), s->f) set]; + NSRectFill (r[0]); + ns_unfocus (s->f); + s->background_filled_p = 1; + } + break; + + case CHAR_GLYPH: + case COMPOSITE_GLYPH: + n = ns_get_glyph_string_clip_rect (s, r); + ns_focus (s->f, r, n); + + if (s->for_overlaps || s->gidx > 0) + s->background_filled_p = 1; + else /* 1 */ + ns_maybe_dumpglyphs_background + (s, s->first_glyph->type == COMPOSITE_GLYPH); + + ns_tmp_flags = s->hl == DRAW_CURSOR ? NS_DUMPGLYPH_CURSOR : + (s->hl == DRAW_MOUSE_FACE ? NS_DUMPGLYPH_MOUSEFACE : + (s->for_overlaps ? NS_DUMPGLYPH_FOREGROUND : + NS_DUMPGLYPH_NORMAL)); + ns_tmp_font = (struct nsfont_info *)s->face->font; + if (ns_tmp_font == ~0 || ns_tmp_font == NULL) + ns_tmp_font = FRAME_FONT (s->f); + + ns_tmp_font->font.driver->draw + (s, 0, s->nchars, s->x, s->y, + (ns_tmp_flags == NS_DUMPGLYPH_NORMAL && !s->background_filled_p) + || ns_tmp_flags == NS_DUMPGLYPH_MOUSEFACE); + + ns_unfocus (s->f); + break; + + default: + abort (); + } + + /* Draw box if not done already. */ + if (!s->for_overlaps && !box_drawn_p && s->face->box != FACE_NO_BOX) + { + n = ns_get_glyph_string_clip_rect (s, r); + ns_focus (s->f, r, n); + ns_dumpglyphs_box_or_relief (s); + ns_unfocus (s->f); + } + +} + + + +/* ========================================================================== + + Event loop + + ========================================================================== */ + + +static void +ns_send_appdefined (int value) +/* -------------------------------------------------------------------------- + Internal: post an appdefined event which EmacsApp-sendEvent will + recognize and take as a command to halt the event loop. + -------------------------------------------------------------------------- */ +{ + /*NSTRACE (ns_send_appdefined); */ + + /* Only post this event if we haven't already posted one. This will end + the [NXApp run] main loop after having processed all events queued at + this moment. */ + if (send_appdefined) + { + NSEvent *nxev; + + /* We only need one NX_APPDEFINED event to stop NXApp from running. */ + send_appdefined = NO; + + /* Don't need wakeup timer any more */ + if (timed_entry) + { + [timed_entry invalidate]; + [timed_entry release]; + timed_entry = nil; + } + + /* Ditto for file descriptor poller */ + if (fd_entry) + { + [fd_entry invalidate]; + [fd_entry release]; + fd_entry = nil; + } + + nxev = [NSEvent otherEventWithType: NSApplicationDefined + location: NSMakePoint (0, 0) + modifierFlags: 0 + timestamp: 0 + windowNumber: [[NSApp mainWindow] windowNumber] + context: [NSApp context] + subtype: 0 + data1: value + data2: 0]; + + /* Post an application defined event on the event queue. When this is + received the [NXApp run] will return, thus having processed all + events which are currently queued. */ + [NSApp postEvent: nxev atStart: NO]; + } +} + + +static int +ns_read_socket (struct terminal *terminal, int expected, + struct input_event *hold_quit) +/* -------------------------------------------------------------------------- + External (hook): Post an event to ourself and keep reading events until + we read it back again. In effect process all events which were waiting. + 23: Now we have to manage the event buffer ourselves. + -------------------------------------------------------------------------- */ +{ + struct input_event ev; + int nevents; + static NSDate *lastCheck = nil; +/* NSTRACE (ns_read_socket); */ + + if (interrupt_input_blocked) + { + interrupt_input_pending = 1; + return -1; + } + + interrupt_input_pending = 0; + BLOCK_INPUT; + +#ifdef COCOA_EXPERIMENTAL_CTRL_G + /* causes Feval to abort; unclear on why this isn't in calling code */ + ++handling_signal; +#endif + + n_emacs_events_pending = 0; + EVENT_INIT (ev); + emacs_event = &ev; + q_event_ptr = hold_quit; + + /* we manage autorelease pools by allocate/reallocate each time around + the loop; strict nesting is occasionally violated but seems not to + matter.. earlier methods using full nesting caused major memory leaks */ + [outerpool release]; + outerpool = [[NSAutoreleasePool alloc] init]; + + /* If have pending open-file requests, attend to the next one of those. */ + if (ns_pending_files && [ns_pending_files count] != 0 + && [NSApp openFile: [ns_pending_files objectAtIndex: 0]]) + { + [ns_pending_files removeObjectAtIndex: 0]; + } + /* Deal with pending service requests. */ + else if (ns_pending_service_names && [ns_pending_service_names count] != 0 + && [NSApp fulfillService: [ns_pending_service_names objectAtIndex: 0] + withArg: [ns_pending_service_args objectAtIndex: 0]]) + { + [ns_pending_service_names removeObjectAtIndex: 0]; + [ns_pending_service_args removeObjectAtIndex: 0]; + } + else + { + /* Run and wait for events. We must always send one NX_APPDEFINED event + to ourself, otherwise [NXApp run] will never exit. */ + send_appdefined = YES; + + /*PENDING: from termhooks.h: */ + /* XXX Please note that a non-zero value of EXPECTED only means that + there is available input on at least one of the currently opened + terminal devices -- but not necessarily on this device. + Therefore, in most cases EXPECTED should be simply ignored. */ + /* However, if in ns_select, this is called from gobble_input, which + appears to set it correctly for our purposes, and always assuming + !expected causes 100% CPU usage. */ + if (!inNsSelect || !expected) + { + /* Post an application defined event on the event queue. When this is + received the [NXApp run] will return, thus having processed all + events which are currently queued, if any. */ + ns_send_appdefined (-1); + } + + [NSApp run]; + } + + nevents = n_emacs_events_pending; + n_emacs_events_pending = 0; + emacs_event = q_event_ptr = NULL; + +#ifdef COCOA_EXPERIMENTAL_CTRL_G + --handling_signal; +#endif + UNBLOCK_INPUT; + return nevents; +} + + +int +ns_select (int nfds, fd_set *readfds, fd_set *writefds, + fd_set *exceptfds, struct timeval *timeout) +/* -------------------------------------------------------------------------- + Replacement for select, checking for events + -------------------------------------------------------------------------- */ +{ + int result; + double time; + NSEvent *ev; +/* NSTRACE (ns_select); */ + + if (NSApp == nil /* || ([NSApp isActive] == NO && + [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:nil + inMode:NSDefaultRunLoopMode dequeue:NO] == nil) */) + return select (nfds, readfds, writefds, exceptfds, timeout); + + /* Save file descriptor set, which gets overwritten in calls to select () + Note, this is called from process.c, and only readfds is ever set */ + if (readfds) + { + memcpy (&select_readfds, readfds, sizeof (fd_set)); + select_nfds = nfds; + } + else + select_nfds = 0; + + /* Try an initial select for pending data on input files */ + select_timeout.tv_sec = select_timeout.tv_usec = 0; + result = select (nfds, readfds, writefds, exceptfds, &select_timeout); + if (result) + return result; + + /* if (!timeout || timed_entry || fd_entry) + fprintf (stderr, "assertion failed: timeout null or timed_entry/fd_entry non-null in ns_select\n"); */ + + /* set a timeout and run the main AppKit event loop while continuing + to monitor the files */ + time = ((double) timeout->tv_sec) + ((double) timeout->tv_usec)/1000000.0; + timed_entry = [[NSTimer scheduledTimerWithTimeInterval: time + target: NSApp + selector: @selector (timeout_handler:) + userInfo: 0 + repeats: YES] /* for safe removal */ + retain]; + + /* set a periodic task to try the select () again */ + fd_entry = [[NSTimer scheduledTimerWithTimeInterval: 0.1 + target: NSApp + selector: @selector (fd_handler:) + userInfo: 0 + repeats: YES] + retain]; + + if (!NILP (ns_cursor_blink_mode) && !cursor_blink_entry) + { + if (!NUMBERP (ns_cursor_blink_rate)) + ns_cursor_blink_rate = make_float (0.5); + cursor_blink_entry = [[NSTimer + scheduledTimerWithTimeInterval: XFLOATINT (ns_cursor_blink_rate) + target: NSApp + selector: @selector (cursor_blink_handler:) + userInfo: 0 + repeats: YES] + retain]; + } + else if (NILP (ns_cursor_blink_mode) && cursor_blink_entry) + { + if (NUMBERP (ns_cursor_blink_rate)) + ns_cursor_blink_rate = Qnil; + struct ns_display_info *dpyinfo = ns_display_list; /* HACK */ + [cursor_blink_entry invalidate]; + [cursor_blink_entry release]; + cursor_blink_entry = 0; + if (dpyinfo->ns_highlight_frame) + { + Lisp_Object tem = + get_frame_param (dpyinfo->ns_highlight_frame, Qcursor_type); + dpyinfo->ns_highlight_frame->output_data.ns->desired_cursor = + ns_lisp_to_cursor_type (tem); + } + } + + /* Let Application dispatch events until it receives an event of the type + NX_APPDEFINED, which should only be sent by timeout_handler. */ + inNsSelect = 1; + gobble_input (timeout ? 1 : 0); + ev = last_appdefined_event; + inNsSelect = 0; + + if (ev) + { + int t; + if ([ev type] != NSApplicationDefined) + abort (); + + t = [ev data1]; + last_appdefined_event = 0; + + if (t == -2) + { + /* The NX_APPDEFINED event we received was a timeout. */ + return 0; + } + else if (t == -1) + { + /* The NX_APPDEFINED event we received was the result of + at least one real input event arriving. */ + errno = EINTR; + return -1; + } + else + { + /* Received back from select () in fd_handler; copy the results */ + if (readfds) + memcpy (readfds, &select_readfds, sizeof (fd_set)); + return t; + } + } + /* never reached, shut compiler up */ + return 0; +} + + + +/* ========================================================================== + + Scrollbar handling + + ========================================================================== */ + + +static void +ns_set_vertical_scroll_bar (struct window *window, + int portion, int whole, int position) +/* -------------------------------------------------------------------------- + External (hook): Update or add scrollbar + -------------------------------------------------------------------------- */ +{ + Lisp_Object win; + NSRect r, v; + struct frame *f = XFRAME (WINDOW_FRAME (window)); + EmacsView *view = FRAME_NS_VIEW (f); + int window_y, window_height; + BOOL barOnVeryLeft, barOnVeryRight; + int top, left, height, width, sb_width, sb_left; + EmacsScroller *bar; +static int count = 0; + + /* optimization; display engine sends WAY too many of these.. */ + if (!NILP (window->vertical_scroll_bar)) + { + bar = XNS_SCROLL_BAR (window->vertical_scroll_bar); + if ([bar checkSamePosition: position portion: portion whole: whole]) + { + if (view->scrollbarsNeedingUpdate == 0) + { + if (!windows_or_buffers_changed) + return; + } + else + view->scrollbarsNeedingUpdate--; + } + } + + NSTRACE (ns_set_vertical_scroll_bar); + + /* Get dimensions. */ + window_box (window, -1, 0, &window_y, 0, &window_height); + top = window_y; + height = window_height; + width = WINDOW_CONFIG_SCROLL_BAR_COLS (window) * FRAME_COLUMN_WIDTH (f); + left = WINDOW_SCROLL_BAR_AREA_X (window); + + if (top < 5) /* top scrollbar adjustment */ + { + top -= FRAME_INTERNAL_BORDER_WIDTH (f); + height += FRAME_INTERNAL_BORDER_WIDTH (f); + } + + /* allow for displaying a skinnier scrollbar than char area allotted */ + sb_width = (WINDOW_CONFIG_SCROLL_BAR_WIDTH (window) > 0) ? + WINDOW_CONFIG_SCROLL_BAR_WIDTH (window) : width; + + barOnVeryLeft = left < 5; + barOnVeryRight = FRAME_PIXEL_WIDTH (f) - left - width < 5; + sb_left = left + FRAME_INTERNAL_BORDER_WIDTH (f) + * (barOnVeryLeft ? -1 : (barOnVeryRight ? 1 : 0)); + + r = NSMakeRect (sb_left, top, sb_width, height); + /* the parent view is flipped, so we need to flip y value */ + v = [view frame]; + r.origin.y = (v.size.height - r.size.height - r.origin.y); + + XSETWINDOW (win, window); + BLOCK_INPUT; + + /* we want at least 5 lines to display a scrollbar */ + if (WINDOW_TOTAL_LINES (window) < 5) + { + if (!NILP (window->vertical_scroll_bar)) + { + bar = XNS_SCROLL_BAR (window->vertical_scroll_bar); + [bar removeFromSuperview]; + window->vertical_scroll_bar = Qnil; + } + ns_clear_frame_area (f, sb_left, top, width, height); + UNBLOCK_INPUT; + return; + } + + if (NILP (window->vertical_scroll_bar)) + { + ns_clear_frame_area (f, sb_left, top, width, height); + bar = [[EmacsScroller alloc] initFrame: r window: win]; + window->vertical_scroll_bar = make_save_value (bar, 0); + } + else + { + NSRect oldRect; + bar = XNS_SCROLL_BAR (window->vertical_scroll_bar); + oldRect = [bar frame]; + r.size.width = oldRect.size.width; + if (FRAME_LIVE_P (f) && !NSEqualRects (oldRect, r)) + { + if (oldRect.origin.x != r.origin.x) + ns_clear_frame_area (f, sb_left, top, width, height); + [bar setFrame: r]; + } + } + + [bar setPosition: position portion: portion whole: whole]; + UNBLOCK_INPUT; +} + + +static void +ns_condemn_scroll_bars (struct frame *f) +/* -------------------------------------------------------------------------- + External (hook): arrange for all frame's scrollbars to be removed + at next call to judge_scroll_bars, except for those redeemed. + -------------------------------------------------------------------------- */ +{ + int i; + id view; + NSArray *subviews = [[FRAME_NS_VIEW (f) superview] subviews]; + + NSTRACE (ns_condemn_scroll_bars); + + for (i =[subviews count]-1; i >= 0; i--) + { + view = [subviews objectAtIndex: i]; + if ([view isKindOfClass: [EmacsScroller class]]) + [view condemn]; + } +} + + +static void +ns_redeem_scroll_bar (struct window *window) +/* -------------------------------------------------------------------------- + External (hook): arrange to spare this window's scrollbar + at next call to judge_scroll_bars. + -------------------------------------------------------------------------- */ +{ + id bar; + NSTRACE (ns_redeem_scroll_bar); + if (!NILP (window->vertical_scroll_bar)) + { + bar =XNS_SCROLL_BAR (window->vertical_scroll_bar); + [bar reprieve]; + } +} + + +static void +ns_judge_scroll_bars (struct frame *f) +/* -------------------------------------------------------------------------- + External (hook): destroy all scrollbars on frame that weren't + redeemed after call to condemn_scroll_bars. + -------------------------------------------------------------------------- */ +{ + int i; + id view; + NSArray *subviews = [[FRAME_NS_VIEW (f) superview] subviews]; + NSTRACE (ns_judge_scroll_bars); + for (i =[subviews count]-1; i >= 0; i--) + { + view = [subviews objectAtIndex: i]; + if (![view isKindOfClass: [EmacsScroller class]]) continue; + [view judge]; + } +} + + + +/* ========================================================================== + + Miscellaneous, mainly stubbed-out functions added in 23 + + ========================================================================== */ + + +void +x_wm_set_icon_position (struct frame *f, int icon_x, int icon_y) +{ +} + + + +/* ========================================================================== + + Initialization + + ========================================================================== */ + +static Lisp_Object ns_string_to_lispmod (char *s) +/* -------------------------------------------------------------------------- + Convert modifier name to lisp symbol + -------------------------------------------------------------------------- */ +{ + if (!strncmp (SDATA (SYMBOL_NAME (Qmeta)), s, 10)) + return Qmeta; + else if (!strncmp (SDATA (SYMBOL_NAME (Qsuper)), s, 10)) + return Qsuper; + else if (!strncmp (SDATA (SYMBOL_NAME (Qcontrol)), s, 10)) + return Qcontrol; + else if (!strncmp (SDATA (SYMBOL_NAME (Qalt)), s, 10)) + return Qalt; + else if (!strncmp (SDATA (SYMBOL_NAME (Qhyper)), s, 10)) + return Qhyper; + else if (!strncmp (SDATA (SYMBOL_NAME (Qnone)), s, 10)) + return Qnone; + else + return Qnil; +} + + +static Lisp_Object ns_mod_to_lisp (int m) +/* -------------------------------------------------------------------------- + Convert modifier code (see lisp.h) to lisp symbol + -------------------------------------------------------------------------- */ +{ + if (m == CHAR_META) + return Qmeta; + else if (m == CHAR_SUPER) + return Qsuper; + else if (m == CHAR_CTL) + return Qcontrol; + else if (m == CHAR_ALT) + return Qalt; + else if (m == CHAR_HYPER) + return Qhyper; + else /* if (m == 0) */ + return Qnone; +} + + +static void +ns_set_default_prefs () +/* -------------------------------------------------------------------------- + Initialize preference variables to defaults + -------------------------------------------------------------------------- */ +{ + ns_alternate_modifier = Qmeta; + ns_command_modifier = Qsuper; + ns_control_modifier = Qcontrol; + ns_function_modifier = Qnone; + ns_cursor_blink_rate = Qnil; + ns_cursor_blink_mode = Qnil; + ns_expand_space = make_float (0.0); + ns_antialias_text = YES; + ns_antialias_threshold = 10.0; + ns_use_qd_smoothing = NO; + ns_use_system_highlight_color = YES; +} + + +static void +ns_default (const char *parameter, Lisp_Object *result, + Lisp_Object yesval, Lisp_Object noval, + BOOL is_float, BOOL is_modstring) +/* -------------------------------------------------------------------------- + Check a parameter value in user's preferences + -------------------------------------------------------------------------- */ +{ + const char *value; + + if ( (value =[[[NSUserDefaults standardUserDefaults] + stringForKey: [NSString stringWithUTF8String: parameter]] + UTF8String]) ) + { + double f; + char *pos; + if (strcasecmp (value, "YES") == 0) + *result = yesval; + else if (strcasecmp (value, "NO") == 0) + *result = noval; + else if (is_float && (f = strtod (value, &pos), pos != value)) + *result = make_float (f); + else if (is_modstring && value) + *result = ns_string_to_lispmod (value); + else fprintf (stderr, + "Bad value for default \"%s\": \"%s\"\n", parameter, value); + } +} + + +void +ns_initialize_display_info (struct ns_display_info *dpyinfo) +/* -------------------------------------------------------------------------- + Initialize global info and storage for display. + -------------------------------------------------------------------------- */ +{ + NSScreen *screen = [NSScreen mainScreen]; + NSWindowDepth depth = [screen depth]; + + dpyinfo->width = [screen frame].size.width; + dpyinfo->height = [screen frame].size.height; + dpyinfo->resx = 72.27; /* used 75.0, but this makes pt == pixel, expected */ + dpyinfo->resy = 72.27; + dpyinfo->color_p = ![NSDeviceWhiteColorSpace isEqualToString: + NSColorSpaceFromDepth (depth)] + && ![NSCalibratedWhiteColorSpace isEqualToString: + NSColorSpaceFromDepth (depth)]; + dpyinfo->n_planes = NSBitsPerPixelFromDepth (depth); + dpyinfo->image_cache = make_image_cache (); + dpyinfo->color_table = + (struct ns_color_table *)xmalloc (sizeof (struct ns_color_table)); + dpyinfo->color_table->colors = NULL; + dpyinfo->root_window = 42; /* a placeholder.. */ + + dpyinfo->mouse_face_mouse_frame = NULL; + dpyinfo->mouse_face_deferred_gc = 0; + 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 = dpyinfo->mouse_face_overlay = Qnil; + dpyinfo->mouse_face_hidden = 0; + + dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0; + dpyinfo->mouse_face_defer = 0; + + dpyinfo->ns_highlight_frame = dpyinfo->ns_focus_frame = NULL; + + dpyinfo->n_fonts = 0; + dpyinfo->smallest_font_height = 1; + dpyinfo->smallest_char_width = 1; +} + + +/* 23: Needed as new part of display engine; this and next define public + functions in this file (well, many of them, anyway). */ +/* x_... are generic versions in xdisp.c that we, and other terms, get away + with using despite presence in the "system dependent" redisplay + interface. In addition, many of the ns_ methods have code that is + shared with all terms, indicating need for further refactoring. */ +extern frame_parm_handler ns_frame_parm_handlers[]; +static struct redisplay_interface ns_redisplay_interface = +{ + ns_frame_parm_handlers, + x_produce_glyphs, /*generic OK */ + x_write_glyphs, /*generic OK */ + x_insert_glyphs, /*generic OK */ + x_clear_end_of_line, /*generic OK */ + ns_scroll_run, /*23 */ + ns_after_update_window_line, /*23: added */ + ns_update_window_begin, /*23: split from update_begin */ + ns_update_window_end, /*23: split from update_end */ + x_cursor_to, /*generic OK */ + ns_flush, + 0, /* flush_display_optional */ + x_clear_window_mouse_face, /*generic OK */ + x_get_glyph_overhangs, /*23: generic OK */ + x_fix_overlapping_area, /*generic OK */ + ns_draw_fringe_bitmap, /*23 */ + 0, /* define_fringe_bitmap */ /*PENDING: simplify ns_draw_fringe_bitmap? */ + 0, /* destroy_fringe_bitmap */ + ns_compute_glyph_string_overhangs, /*23 */ + ns_draw_glyph_string, /*23: interface to nsfont.m */ + ns_define_frame_cursor, /*23 */ + ns_clear_frame_area, /*23 */ + ns_draw_window_cursor, /*23: revamped ns_dumpcursor */ + ns_draw_vertical_window_border, + ns_shift_glyphs_for_insert +}; + + +static void +ns_delete_display (struct ns_display_info *dpyinfo) +{ + /*PENDING... */ +} + + +/* This function is called when the last frame on a display is deleted. */ +static void +ns_delete_terminal (struct terminal *terminal) +{ + struct ns_display_info *dpyinfo = terminal->display_info.ns; + int i; + + /* Protect against recursive calls. Fdelete_frame in + delete_terminal calls us back when it deletes our last frame. */ + if (!terminal->name) + return; + + BLOCK_INPUT; + + x_destroy_all_bitmaps (dpyinfo); + ns_delete_display (dpyinfo); + UNBLOCK_INPUT; +} + + +static struct terminal * +ns_create_terminal (struct ns_display_info *dpyinfo) +/* -------------------------------------------------------------------------- + Set up use of NS before we make the first connection. + -------------------------------------------------------------------------- */ +{ + struct terminal *terminal; + + NSTRACE (ns_create_terminal); + + terminal = create_terminal (); + + terminal->type = output_ns; + terminal->display_info.ns = dpyinfo; + dpyinfo->terminal = terminal; + + terminal->rif = &ns_redisplay_interface; + + terminal->clear_frame_hook = ns_clear_frame; + terminal->ins_del_lines_hook = 0; /* 23: vestigial? */ + terminal->delete_glyphs_hook = 0; /* 23: vestigial? */ + terminal->ring_bell_hook = ns_ring_bell; + terminal->reset_terminal_modes_hook = ns_reset_terminal_modes; + terminal->set_terminal_modes_hook = ns_set_terminal_modes; + terminal->update_begin_hook = ns_update_begin; + terminal->update_end_hook = ns_update_end; + terminal->set_terminal_window_hook = NULL; /* 23: vestigial? */ + terminal->read_socket_hook = ns_read_socket; + terminal->frame_up_to_date_hook = ns_frame_up_to_date; + terminal->mouse_position_hook = ns_mouse_position; + terminal->frame_rehighlight_hook = ns_frame_rehighlight; + terminal->frame_raise_lower_hook = ns_frame_raise_lower; + + terminal->fullscreen_hook = 0; /*XTfullscreen_hook;//23.50 */ + + terminal->set_vertical_scroll_bar_hook = ns_set_vertical_scroll_bar; + terminal->condemn_scroll_bars_hook = ns_condemn_scroll_bars; + terminal->redeem_scroll_bar_hook = ns_redeem_scroll_bar; + terminal->judge_scroll_bars_hook = ns_judge_scroll_bars; + + terminal->delete_frame_hook = x_destroy_window; + terminal->delete_terminal_hook = ns_delete_terminal; + + terminal->scroll_region_ok = 1; + terminal->char_ins_del_ok = 1; + terminal->line_ins_del_ok = 1; + terminal->fast_clear_end_of_line = 1; + terminal->memory_below_frame = 0; + + return terminal; +} + + +void +ns_initialize () +/* -------------------------------------------------------------------------- + Mainly vestigial under NS now that ns_create_terminal () does most things. + -------------------------------------------------------------------------- */ +{ + baud_rate = 38400; + Fset_input_interrupt_mode (Qt); +} + + +struct ns_display_info * +ns_term_init (Lisp_Object display_name) +/* -------------------------------------------------------------------------- + Start the Application and get things rolling. + -------------------------------------------------------------------------- */ +{ + extern Lisp_Object Fset_input_mode (Lisp_Object, Lisp_Object, + Lisp_Object, Lisp_Object); + struct terminal *terminal; + struct ns_display_info *dpyinfo; + static int ns_initialized = 0; + Lisp_Object tmp; + + NSTRACE (ns_term_init); + + /* count object allocs (About, click icon); on OS X use ObjectAlloc tool */ + /*GSDebugAllocationActive (YES); */ + BLOCK_INPUT; +handling_signal = 0; + + if (!ns_initialized) + { + ns_initialize (); + ns_initialized = 1; + } + + ns_pending_files = [[NSMutableArray alloc] init]; + ns_pending_service_names = [[NSMutableArray alloc] init]; + ns_pending_service_args = [[NSMutableArray alloc] init]; + + /* Start app and create the main menu, window, view. + Needs to be here because ns_initialize_display_info () uses AppKit classes. + The view will then ask the NSApp to stop and return to Emacs. */ + [EmacsApp sharedApplication]; + if (NSApp == nil) + return NULL; + [NSApp setDelegate: NSApp]; + + /* debugging: log all notifications */ + /* [[NSNotificationCenter defaultCenter] addObserver: NSApp + selector: @selector (logNotification:) + name: nil object: nil]; */ + + dpyinfo = (struct ns_display_info *)xmalloc (sizeof (struct ns_display_info)); + bzero (dpyinfo, sizeof (struct ns_display_info)); + + ns_initialize_display_info (dpyinfo); + terminal = ns_create_terminal (dpyinfo); + + terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD)); + init_kboard (terminal->kboard); + terminal->kboard->Vwindow_system = Qns; + terminal->kboard->next_kboard = all_kboards; + all_kboards = terminal->kboard; + /* Don't let the initial kboard remain current longer than necessary. + That would cause problems if a file loaded on startup tries to + prompt in the mini-buffer. */ + if (current_kboard == initial_kboard) + current_kboard = terminal->kboard; + terminal->kboard->reference_count++; + + dpyinfo->next = ns_display_list; + ns_display_list = dpyinfo; + + /* Put it on ns_display_name_list */ + ns_display_name_list = Fcons (Fcons (display_name, Qnil), + ns_display_name_list); +/* ns_display_name_list = Fcons (Fcons (display_name, + Fcons (Qnil, dpyinfo->xrdb)), + ns_display_name_list); */ + dpyinfo->name_list_element = XCAR (ns_display_name_list); + + /* Set the name of the terminal. */ + terminal->name = (char *) xmalloc (SBYTES (display_name) + 1); + strncpy (terminal->name, SDATA (display_name), SBYTES (display_name)); + terminal->name[SBYTES (display_name)] = 0; + + UNBLOCK_INPUT; + + /* Read various user defaults. */ + ns_set_default_prefs (); + ns_default ("AlternateModifier", &ns_alternate_modifier, + Qnil, Qnil, NO, YES); + if (NILP (ns_alternate_modifier)) + ns_alternate_modifier = Qmeta; + ns_default ("CommandModifier", &ns_command_modifier, + Qnil, Qnil, NO, YES); + if (NILP (ns_command_modifier)) + ns_command_modifier = Qsuper; + ns_default ("ControlModifier", &ns_control_modifier, + Qnil, Qnil, NO, YES); + if (NILP (ns_control_modifier)) + ns_control_modifier = Qcontrol; + ns_default ("FunctionModifier", &ns_function_modifier, + Qnil, Qnil, NO, YES); + if (NILP (ns_function_modifier)) + ns_function_modifier = Qnone; + ns_default ("CursorBlinkRate", &ns_cursor_blink_rate, + make_float (0.5), Qnil, YES, NO); + if (NUMBERP (ns_cursor_blink_rate)) + ns_cursor_blink_mode = Qt; + ns_default ("ExpandSpace", &ns_expand_space, + make_float (0.5), make_float (0.0), YES, NO); + ns_default ("GSFontAntiAlias", &ns_antialias_text, + YES, NO, NO, NO); + tmp = Qnil; + ns_default ("AppleAntiAliasingThreshold", &tmp, + make_float (10.0), make_float (6.0), YES, NO); + ns_antialias_threshold = NILP (tmp) ? 10.0 : XFLOATINT (tmp); + ns_default ("UseQuickdrawSmoothing", &ns_use_qd_smoothing, + YES, NO, NO, NO); + ns_default ("UseSystemHighlightColor", &ns_use_system_highlight_color, + YES, NO, NO, NO); + if (ns_use_system_highlight_color == YES) + { + ns_selection_color = [[NSUserDefaults standardUserDefaults] + stringForKey: @"AppleHighlightColor"]; + if (ns_selection_color == nil) + ns_selection_color = NS_SELECTION_COLOR_DEFAULT; + } + else + ns_selection_color = NS_SELECTION_COLOR_DEFAULT; + + { + id cl; + Lisp_Object tem, tem1; + extern Lisp_Object Vsource_directory; + + cl = [NSColorList colorListNamed: @"Emacs"]; + + if ( cl == nil ) + { + /* first try data_dir, then invocation-dir + and finally source-directory/etc */ + tem1 = tem = + Fexpand_file_name (build_string ("Emacs.clr"), Vdata_directory); + if (NILP (Ffile_exists_p (tem))) + { + tem = Fexpand_file_name (build_string ("Emacs.clr"), + Vinvocation_directory); + if (NILP (Ffile_exists_p (tem))) + { + Lisp_Object newdir = + Fexpand_file_name (build_string ("etc/"), + Vsource_directory); + tem = Fexpand_file_name (build_string ("Emacs.clr"), + newdir); + } + } + + cl = [[NSColorList alloc] + initWithName: @"Emacs" + fromFile: [NSString stringWithCString: XSTRING (tem)->data]]; + if (cl ==nil) + fatal ("Could not find %s.\n", XSTRING (tem1)->data); + [cl writeToFile: nil]; + } + } + + { + char c[128]; +#ifdef NS_IMPL_GNUSTEP + strncpy (c, gnustep_base_version, sizeof (c)); +#else + /*PSnextrelease (128, c); */ + snprintf (c, sizeof (c), "%g", NSAppKitVersionNumber); +#endif + Vwindow_system_version = build_string (c); + } + + delete_keyboard_wait_descriptor (0); + +/* Set up OS X app menu */ +#ifdef NS_IMPL_COCOA + { + NSMenu *appMenu; + id item; + /* set up the application menu */ + svcsMenu = [[EmacsMenu alloc] initWithTitle: @"Services"]; + [svcsMenu setAutoenablesItems: NO]; + appMenu = [[EmacsMenu alloc] initWithTitle: @"Emacs"]; + [appMenu setAutoenablesItems: NO]; + mainMenu = [[EmacsMenu alloc] initWithTitle: @""]; + + [appMenu insertItemWithTitle: @"About Emacs" + action: @selector (orderFrontStandardAboutPanel:) + keyEquivalent: @"" + atIndex: 0]; + [appMenu insertItem: [NSMenuItem separatorItem] atIndex: 1]; + [appMenu insertItemWithTitle: @"Preferences..." + action: @selector (showPreferencesWindow:) + keyEquivalent: @"," + atIndex: 2]; + [appMenu insertItem: [NSMenuItem separatorItem] atIndex: 3]; + item = [appMenu insertItemWithTitle: @"Services" + action: @selector (menuDown:) + keyEquivalent: @"" + atIndex: 4]; + [appMenu setSubmenu: svcsMenu forItem: item]; +/* [svcsMenu setSupercell: item]; */ + [appMenu insertItem: [NSMenuItem separatorItem] atIndex: 5]; + [appMenu insertItemWithTitle: @"Hide Emacs" + action: @selector (hide:) + keyEquivalent: @"h" + atIndex: 6]; + item = [appMenu insertItemWithTitle: @"Hide Others" + action: @selector (hideOtherApplications:) + keyEquivalent: @"h" + atIndex: 7]; + [item setKeyEquivalentModifierMask: NSCommandKeyMask | NSAlternateKeyMask]; + [appMenu insertItem: [NSMenuItem separatorItem] atIndex: 8]; + [appMenu insertItemWithTitle: @"Quit Emacs" + action: @selector (terminate:) + keyEquivalent: @"q" + atIndex: 9]; + + item = [mainMenu insertItemWithTitle: @"Emacs" + action: @selector (menuDown:) + keyEquivalent: @"" + atIndex: 0]; + [mainMenu setSubmenu: appMenu forItem: item]; + + [NSApp setMainMenu: mainMenu]; + [NSApp setAppleMenu: appMenu]; + [NSApp setServicesMenu: svcsMenu]; + /* Needed at least on Cocoa, to get dock menu to show windows */ + [NSApp setWindowsMenu: [[NSMenu alloc] init]]; + } +#endif /* MAC OS X menu setup */ + + [NSApp run]; + + return dpyinfo; +} + + +extern Lisp_Object Vauto_save_list_file_name; +void +ns_term_shutdown (int sig) +{ + /* code not reached in emacs.c after this is called by shut_down_emacs: */ + if (STRINGP (Vauto_save_list_file_name)) + unlink (XSTRING (Vauto_save_list_file_name)->data); + + ns_shutdown_properly = YES; + [NSApp terminate: NSApp]; +} + + +void +syms_of_nsterm () +{ + NSTRACE (syms_of_nsterm); + DEFVAR_LISP ("ns-input-file", &ns_input_file, + "The file specified in the last NS event."); + ns_input_file =Qnil; + + DEFVAR_LISP ("ns-input-text", &ns_input_text, + "The data received in the last NS text drag event."); + ns_input_text =Qnil; + + DEFVAR_LISP ("ns-working-text", &ns_working_text, + "String for visualizing working composition sequence."); + ns_working_text =Qnil; + + DEFVAR_LISP ("ns-input-font", &ns_input_font, + "The font specified in the last NS event."); + ns_input_font =Qnil; + + DEFVAR_LISP ("ns-input-fontsize", &ns_input_fontsize, + "The fontsize specified in the last NS event."); + ns_input_fontsize =Qnil; + + DEFVAR_LISP ("ns-input-line", &ns_input_line, + "The line specified in the last NS event."); + ns_input_line =Qnil; + + DEFVAR_LISP ("ns-input-color", &ns_input_color, + "The color specified in the last NS event."); + ns_input_color =Qnil; + + DEFVAR_LISP ("ns-input-spi-name", &ns_input_spi_name, + "The service name specified in the last NS event."); + ns_input_spi_name =Qnil; + + DEFVAR_LISP ("ns-input-spi-arg", &ns_input_spi_arg, + "The service argument specified in the last NS event."); + ns_input_spi_arg =Qnil; + + DEFVAR_LISP ("ns-alternate-modifier", &ns_alternate_modifier, + "This variable describes the behavior of the alternate or option key.\n\ +Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\ +Set to none means that the alternate / option key is not interpreted by Emacs\n\ +at all, allowing it to be used at a lower level for accented character entry."); + + DEFVAR_LISP ("ns-command-modifier", &ns_command_modifier, + "This variable describes the behavior of the command key.\n\ +Set to control, meta, alt, super, or hyper means it is taken to be that key."); + + DEFVAR_LISP ("ns-control-modifier", &ns_control_modifier, + "This variable describes the behavior of the control key.\n\ +Set to control, meta, alt, super, or hyper means it is taken to be that key."); + + DEFVAR_LISP ("ns-function-modifier", &ns_function_modifier, + "This variable describes the behavior of the function key (on laptops).\n\ +Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\ +Set to none means that the function key is not interpreted by Emacs at all,\n\ +allowing it to be used at a lower level for accented character entry."); + + DEFVAR_LISP ("ns-cursor-blink-rate", &ns_cursor_blink_rate, + "Rate at which the Emacs cursor blinks (in seconds).\n\ +Set to nil to disable blinking."); + + DEFVAR_LISP ("ns-cursor-blink-mode", &ns_cursor_blink_mode, + "Internal variable -- use M-x blink-cursor-mode or preferences\n\ +panel to control this setting."); + + DEFVAR_LISP ("ns-expand-space", &ns_expand_space, + "Amount by which spacing between lines is expanded (positive)\n\ +or shrunk (negative). Zero (the default) means standard line height.\n\ +(This variable should only be read, never set.)"); + + DEFVAR_BOOL ("ns-antialias-text", &ns_antialias_text, + "Non-nil (the default) means to render text antialiased. Only has an effect on OS X Panther and above."); + + DEFVAR_BOOL ("ns-use-qd-smoothing", &ns_use_qd_smoothing, + "Whether to render text using QuickDraw (less heavy) antialiasing. Only has an effect on OS X Panther and above. Default is nil (use Quartz smoothing)."); + + DEFVAR_BOOL ("ns-use-system-highlight-color", + &ns_use_system_highlight_color, + "Whether to use the system default (on OS X only) for the highlight color. Nil means to use standard emacs (prior to version 21) 'grey'."); + + staticpro (&ns_display_name_list); + ns_display_name_list = Qnil; + + staticpro (&last_mouse_motion_frame); + last_mouse_motion_frame = Qnil; + +/*23: now apparently we need to tell emacs what modifiers there are.. */ + Qmodifier_value = intern ("modifier-value"); + Qalt = intern ("alt"); + Fput (Qalt, Qmodifier_value, make_number (alt_modifier)); + Qhyper = intern ("hyper"); + Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier)); + Qmeta = intern ("meta"); + Fput (Qmeta, Qmodifier_value, make_number (meta_modifier)); + Qsuper = intern ("super"); + Fput (Qsuper, Qmodifier_value, make_number (super_modifier)); + Qcontrol = intern ("control"); + Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier)); + + /*PENDING: move to common code */ + DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars, + doc: /* If not nil, Emacs uses toolkit scroll bars. */); +#ifdef USE_TOOLKIT_SCROLL_BARS + Vx_toolkit_scroll_bars = Qt; +#else + Vx_toolkit_scroll_bars = Qnil; +#endif + + /* these are unsupported but we need the declarations to avoid whining + messages from cus-start.el */ + DEFVAR_BOOL ("x-use-underline-position-properties", + &x_use_underline_position_properties, + doc: /* NOT SUPPORTED UNDER NS. +*Non-nil means make use of UNDERLINE_POSITION font properties. +A value of 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. + +NOTE: Not supported on Mac yet. */); + x_use_underline_position_properties = 0; + + DEFVAR_BOOL ("x-underline-at-descent-line", + &x_underline_at_descent_line, + doc: /* NOT SUPPORTED UNDER NS. +*Non-nil means to draw the underline at the same place as the descent line. +A value of nil means to draw the underline according to the value of the +variable `x-use-underline-position-properties', which is usually at the +baseline level. The default value is nil. */); + x_underline_at_descent_line = 0; + + /* Tell emacs about this window system. */ + Fprovide (intern ("ns-windowing"), Qnil); + /* PENDING: try to move this back into lisp (ns-win.el loaded too late + right now */ + { + Lisp_Object args[3] = { intern ("ns-version-string"), build_string ("9.0"), + build_string ("NS Window system port version number.") }; + Fdefconst (Flist (3, args)); + } +} + + + +/* ========================================================================== + + EmacsApp implementation + + ========================================================================== */ + + +@implementation EmacsApp + +- (void)logNotification: (NSNotification *)notification +{ + const char *name = [[notification name] UTF8String]; + if (!strstr (name, "Update") && !strstr (name, "NSMenu") + && !strstr (name, "WindowNumber")) + NSLog (@"notification: '%@'", [notification name]); +} + + +- (void)sendEvent: (NSEvent *)theEvent +/* -------------------------------------------------------------------------- + Events posted by ns_send_appdefined interrupt the run loop here + -------------------------------------------------------------------------- */ +{ + int type = [theEvent type]; + NSWindow *window = [theEvent window]; +/* NSTRACE (sendEvent); */ +/*fprintf (stderr, "received event of type %d\n", [theEvent type]); */ + + if (type == NSCursorUpdate && window == nil) + { + fprintf (stderr, "Dropping external cursor update event.\n"); + return; + } + +#ifdef NS_IMPL_COCOA + /* pass mouse down in resize handle and subsequent drags directly to + EmacsWindow so we can generate continuous redisplays */ + if (ns_in_resize) + { + if (type == NSLeftMouseDragged) + { + [window mouseDragged: theEvent]; + return; + } + else if (type == NSLeftMouseUp) + { + [window mouseUp: theEvent]; + return; + } + } + else if (type == NSLeftMouseDown) + { + NSRect r = ns_resize_handle_rect (window); + if (NSPointInRect ([theEvent locationInWindow], r)) + { + ns_in_resize = YES; + [window mouseDown: theEvent]; + return; + } + } +#endif + + if (type == NSApplicationDefined) + { + last_appdefined_event = theEvent; + [self stop: self]; + } + + [super sendEvent: theEvent]; +} + + +- (void)showPreferencesWindow: (id)sender +{ + if (prefsController == nil) + prefsController = [[EmacsPrefsController alloc] init]; + [prefsController showForFrame: SELECTED_FRAME ()]; +} + + +/* ************************************************************************** + + EmacsApp delegate implementation + + ************************************************************************** */ + +- (void)applicationDidFinishLaunching: (NSNotification *)notification +/* -------------------------------------------------------------------------- + When application is loaded, terminate event loop in ns_term_init + -------------------------------------------------------------------------- */ +{ + NSTRACE (applicationDidFinishLaunching); + [NSApp setServicesProvider: NSApp]; + ns_send_appdefined (-2); +} + + +- (void) terminate: (id)sender +{ + BLOCK_INPUT; + if (ns_shutdown_properly) + [super terminate: sender]; + else + { +/* Fkill_emacs (Qnil); */ + ns_shutdown_properly = YES; + Feval (Fcons (intern ("save-buffers-kill-emacs"), Qnil)); + } + UNBLOCK_INPUT; +} + + +- (NSApplicationTerminateReply)applicationShouldTerminate: (id)sender +{ + if (ns_shutdown_properly) + return NSTerminateNow; + + Lisp_Object contents = list3 (build_string ("Exit requested. Would you like to Save Buffers and Exit, or Cancel the request?"), + Fcons (build_string ("Cancel"), Qnil), + Fcons (build_string ("Save and Exit"), Qt)); + Lisp_Object res = ns_popup_dialog (Qt, contents, Qnil); +fprintf (stderr, "res = %d\n", res ==Qt); + if (res == Qt) + { + Feval (Fcons (intern ("save-buffers-kill-emacs"), Qnil)); + return NSTerminateNow; + } + return NSTerminateCancel; +} + + +/* Open a file (used by below, after going into queue read by ns_read_socket) */ +-(BOOL) openFile: (NSString *)fileName +{ + struct frame *emacsframe = SELECTED_FRAME (); + NSEvent *theEvent = [NSApp currentEvent]; + + if (!emacs_event) + return NO; + + emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT; + emacs_event->code = KEY_NS_OPEN_FILE_LINE; + ns_input_file = append2 (ns_input_file, build_string ([fileName UTF8String])); + ns_input_line = Qnil; /* can be start or cons start,end */ + emacs_event->modifiers =0; + EV_TRAILER (theEvent); + + return YES; +} + + +/* Notification from the Workspace to open a file */ +- (BOOL)application: sender openFile: (NSString *)file +{ + [ns_pending_files addObject: file]; + return YES; +} + + +/* Open a file as a temporary file */ +- (BOOL)application: sender openTempFile: (NSString *)file +{ + [ns_pending_files addObject: file]; + return YES; +} + + +/* Notification from the Workspace to open a file noninteractively (?) */ +- (BOOL)application: sender openFileWithoutUI: (NSString *)file +{ + [ns_pending_files addObject: file]; + return YES; +} + + +/* Notification from the Workspace to open multiple files */ +- (void)application: sender openFiles: (NSArray *)fileList +{ + NSEnumerator *files = [fileList objectEnumerator]; + NSString *file; + while ((file = [files nextObject]) != nil) + [ns_pending_files addObject: file]; + return YES; +} + +/*PENDING: these may help w/IO switching btwn terminal and NSApp */ +- (void)applicationDidBecomeActive: (NSNotification *)notification +{ +} +- (void)applicationDidResignActive: (NSNotification *)notification +{ + ns_send_appdefined (-1); +} + + + +/* ========================================================================== + + EmacsApp aux handlers for managing event loop + + ========================================================================== */ + + +- (void)timeout_handler: (NSTimer *)timedEntry +/* -------------------------------------------------------------------------- + The timeout specified to ns_select has passed. + -------------------------------------------------------------------------- */ +{ + /*NSTRACE (timeout_handler); */ + ns_send_appdefined (-2); +} + +extern void update_window_cursor (struct window *w, int on); + +- (void)cursor_blink_handler: (NSTimer *)cursorEntry +/* -------------------------------------------------------------------------- + Flash the cursor + -------------------------------------------------------------------------- */ +{ + struct ns_display_info *dpyinfo = ns_display_list; /*HACK, but OK for now */ + struct frame *f = dpyinfo->ns_highlight_frame; + NSTRACE (cursor_blink_handler); + + if (!f) + return; + if (f->output_data.ns->current_cursor == no_highlight) + { + Lisp_Object tem = get_frame_param (f, Qcursor_type); + f->output_data.ns->desired_cursor = ns_lisp_to_cursor_type (tem); + } + else + { + f->output_data.ns->desired_cursor = no_highlight; + } + update_window_cursor (XWINDOW (FRAME_SELECTED_WINDOW (f)), 1); + /*x_update_cursor (f, 1); */ +} + + +- (void)fd_handler: (NSTimer *) fdEntry +/* -------------------------------------------------------------------------- + Check data waiting on file descriptors and terminate if so + -------------------------------------------------------------------------- */ +{ + int result; + /* NSTRACE (fd_handler); */ + + if (select_nfds == 0) + return; + + memcpy (&t_readfds, &select_readfds, sizeof (fd_set)); + + select_timeout.tv_sec = select_timeout.tv_usec = 0; + result = select (select_nfds, &t_readfds, (SELECT_TYPE *)0, (SELECT_TYPE *)0, + &select_timeout); + if (result) + { + memcpy (&select_readfds, &t_readfds, sizeof (fd_set)); + ns_send_appdefined (result); + } +} + + + +/* ========================================================================== + + Service provision + + ========================================================================== */ + +/* called from system: queue for next pass through event loop */ +- (void)requestService: (NSPasteboard *)pboard + userData: (NSString *)userData + error: (NSString **)error +{ + [ns_pending_service_names addObject: userData]; + [ns_pending_service_args addObject: [NSString stringWithUTF8String: + SDATA (ns_string_from_pasteboard (pboard))]]; +} + + +/* called from ns_read_socket to clear queue */ +- (BOOL)fulfillService: (NSString *)name withArg: (NSString *)arg +{ + struct frame *emacsframe = SELECTED_FRAME (); + NSEvent *theEvent = [NSApp currentEvent]; + + if (!emacs_event) + return NO; + + emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT; + emacs_event->code = KEY_NS_SPI_SERVICE_CALL; + ns_input_spi_name = build_string ([name UTF8String]); + ns_input_spi_arg = build_string ([arg UTF8String]); + emacs_event->modifiers = EV_MODIFIERS (theEvent); + EV_TRAILER (theEvent); + + return YES; +} + + +@end /* EmacsApp */ + + + +/* ========================================================================== + + EmacsView implementation + + ========================================================================== */ + + +@implementation EmacsView + +/* needed to inform when window closed from LISP */ +- (void) setWindowClosing: (BOOL)closing +{ + windowClosing = closing; +} + + +- (void)dealloc +{ + NSTRACE (EmacsView_dealloc); + [toolbar release]; + [super dealloc]; +} + + +/* called on font panel selection */ +- (void)changeFont: (id)sender +{ + NSEvent *e =[[self window] currentEvent]; + struct face *face =FRAME_DEFAULT_FACE (emacsframe); + id newFont; + float size; + + NSTRACE (changeFont); + if (!emacs_event) + return; + + if (newFont = [sender convertFont: + ((struct nsfont_info *)face->font)->nsfont]) + { + emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT; + emacs_event->modifiers = 0; + emacs_event->code = KEY_NS_CHANGE_FONT; + + size = [newFont pointSize]; + /* PENDING: stick w/integer sizes for now. */ +/* if (size == lrint (size)) */ + ns_input_fontsize = make_number (lrint (size)); +/* else + ns_input_fontsize = make_float (size); */ + ns_input_font = build_string ([[newFont familyName] UTF8String]); + EV_TRAILER (e); + } +} + + +- (BOOL)acceptsFirstResponder +{ + NSTRACE (acceptsFirstResponder); + return YES; +} + + +- (void)resetCursorRects +{ + NSRect visible = [self visibleRect]; + NSCursor *currentCursor = FRAME_POINTER_TYPE (emacsframe); + NSTRACE (resetCursorRects); + + if (currentCursor == nil) + currentCursor = [NSCursor arrowCursor]; + + if (!NSIsEmptyRect (visible)) + [self addCursorRect: visible cursor: currentCursor]; + [currentCursor setOnMouseEntered: YES]; +} + + +/*****************************************************************************/ +/* Keyboard handling. */ +#define NS_KEYLOG 0 + +- (void)keyDown: (NSEvent *)theEvent +{ + struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (emacsframe); + int code; + unsigned fnKeysym = 0; + int flags; + static NSMutableArray *nsEvArray; + static BOOL firstTime = YES; + + NSTRACE (keyDown); + + /* Rhapsody and OS X give up and down events for the arrow keys */ + if ([theEvent type] != NSKeyDown) + return; + + if (!emacs_event) + return; + +/*#if defined (COCOA_EXPERIMENTAL_CTRL_G) */ + if (![[self window] isKeyWindow]) + { + /* PENDING: Using NO_SOCK_SIGIO like Carbon causes a condition in which, + when Emacs display updates a different frame from the current one, + and temporarily selects it, then processes some interrupt-driven + input (dispnew.c:3878), OS will send the event to the correct NSWindow, + but for some reason that window has its first responder set to the + NSView most recently updated (I guess), which is not the correct one. + UPDATE: After multi-TTY merge this happens even w/o NO_SOCK_SIGIO */ + if ([[theEvent window] isKindOfClass: [EmacsWindow class]]) + [[(EmacsView *)[theEvent window] delegate] keyDown: theEvent]; + return; + } +/*#endif */ + + if (nsEvArray == nil) + nsEvArray = [[NSMutableArray alloc] initWithCapacity: 1]; + + [NSCursor setHiddenUntilMouseMoves: YES]; + + if (dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)) + { + clear_mouse_face (dpyinfo); + dpyinfo->mouse_face_hidden = 1; + } + + if (!processingCompose) + { + code = ([[theEvent charactersIgnoringModifiers] length] == 0) ? + 0 : [[theEvent charactersIgnoringModifiers] characterAtIndex: 0]; + /* (Carbon way: [theEvent keyCode]) */ + + /* is it a "function key"? */ + fnKeysym = ns_convert_key (code); + if (fnKeysym) + { + /* COUNTERHACK: map 'Delete' on upper-right main KB to 'Backspace', + because Emacs treats Delete and KP-Delete same (in simple.el). */ + if (fnKeysym == 0xFFFF && [theEvent keyCode] == 0x33) + code = 0xFF08; /* backspace */ + else + code = fnKeysym; + } + + /* are there modifiers? */ + emacs_event->modifiers = 0; + flags = [theEvent modifierFlags]; + + if (flags & NSHelpKeyMask) + emacs_event->modifiers |= hyper_modifier; + + if (flags & NSShiftKeyMask) + emacs_event->modifiers |= shift_modifier; + + if (flags & NSCommandKeyMask) + { + emacs_event->modifiers |= lisp_to_mod (ns_command_modifier); + /* if super (default), take input manager's word so things like + dvorak / qwerty layout work */ + if (EQ (ns_command_modifier, Qsuper) + && !fnKeysym + && [[theEvent characters] length] != 0) + { + /* PENDING: the code we get will be unshifted, so if we have + a shift modifier, must convert ourselves */ + if (!(flags & NSShiftKeyMask)) + code = [[theEvent characters] characterAtIndex: 0]; +#if 0 + /* this is ugly and also requires linking w/Carbon framework + (for LMGetKbdType) so for now leave this rare (?) case + undealt with.. in future look into CGEvent methods */ + else + { + long smv = GetScriptManagerVariable (smKeyScript); + Handle uchrHandle = GetResource + ('uchr', GetScriptVariable (smv, smScriptKeys)); + UInt32 dummy = 0; + UCKeyTranslate ((UCKeyboardLayout*)*uchrHandle, + [[theEvent characters] characterAtIndex: 0], + kUCKeyActionDisplay, + (flags & ~NSCommandKeyMask) >> 8, + LMGetKbdType (), kUCKeyTranslateNoDeadKeysMask, + &dummy, 1, &dummy, &code); + code &= 0xFF; + } +#endif + } + } + + if (flags & NSControlKeyMask) + emacs_event->modifiers |= lisp_to_mod (ns_control_modifier); + + if (flags & NS_FUNCTION_KEY_MASK && !fnKeysym) + emacs_event->modifiers |= lisp_to_mod (ns_function_modifier); + + if (flags & NSAlternateKeyMask) /* default = meta */ + { + if (EQ (ns_alternate_modifier, Qnone) && !fnKeysym) + { /* accept pre-interp alt comb */ + if ([[theEvent characters] length] > 0) + code = [[theEvent characters] characterAtIndex: 0]; + /*HACK: clear lone shift modifier to stop next if from firing */ + if (emacs_event->modifiers == shift_modifier) + emacs_event->modifiers = 0; + } + else + emacs_event->modifiers |= lisp_to_mod (ns_alternate_modifier); + } + +/*fprintf (stderr,"code =%x\tfnKey =%x\tflags = %x\tmods = %x\n",code,fnKeysym,flags,emacs_event->modifiers); */ + + /* if it was a function key or had modifiers, pass it directly to emacs */ + if (fnKeysym || (emacs_event->modifiers + && [[theEvent charactersIgnoringModifiers] length] > 0)) +/*[[theEvent characters] length] */ + { + emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT; + if (code < 0x20) + code |= (1<<28)|(3<<16); + else if (code == 0x7f) + code |= (1<<28)|(3<<16); + else if (!fnKeysym) + emacs_event->kind = code > 0xFF + ? MULTIBYTE_CHAR_KEYSTROKE_EVENT : ASCII_KEYSTROKE_EVENT; + + emacs_event->code = code; + EV_TRAILER (theEvent); + return; + } + } + + /* if we get here we should send the key for input manager processing */ + if (firstTime && [[NSInputManager currentInputManager] + wantsToDelayTextChangeNotifications] == NO) + fprintf (stderr, + "Emacs: WARNING: TextInput mgr wants marked text to be permanent!\n"); + firstTime = NO; + + if (NS_KEYLOG && !processingCompose) + fprintf (stderr, "Begin compose sequence.\n"); + + processingCompose = YES; + [nsEvArray addObject: theEvent]; + [self interpretKeyEvents: nsEvArray]; + [nsEvArray removeObject: theEvent]; +} + + +/* implementation (called through super interpretKeyEvents:]). */ + + +/* : called through when done composing */ +- (void)insertText: (id)aString +{ + int code; + int len = [(NSString *)aString length]; + int i; + +if (NS_KEYLOG) NSLog (@"insertText '%@'\tlen = %d", aString, len); + processingCompose = NO; + + if (!emacs_event) + return; + + /* first, clear any working text */ + if (workingText != nil) + [self deleteWorkingText]; + + /* now insert the string as keystrokes */ + for (i =0; imodifiers = 0; + emacs_event->kind = + code > 0xFF ? MULTIBYTE_CHAR_KEYSTROKE_EVENT : ASCII_KEYSTROKE_EVENT; + emacs_event->code = code; + EV_TRAILER ((id)nil); + } +} + + +/* : inserts display of composing characters */ +- (void)setMarkedText: (id)aString selectedRange: (NSRange)selRange +{ + NSString *str = [aString respondsToSelector: @selector (string)] ? + [aString string] : aString; + if (NS_KEYLOG) + NSLog (@"setMarkedText '%@' len =%d range %d from %d", str, [str length], + selRange.length, selRange.location); + + if (workingText != nil) + [self deleteWorkingText]; + if ([str length] == 0) + return; + + if (!emacs_event) + return; + + processingCompose = YES; + workingText = [str copy]; + ns_working_text = build_string ([workingText UTF8String]); + + /* if in "echo area", not true minibuffer, can't show chars in interactive + mode, so call using eval; otherwise we send a key event, which was the + original way this was done */ + if (!EQ (Feval (Fcons (intern ("ns-in-echo-area"), Qnil)), Qnil)) + { + Feval (Fcons (intern ("ns-echo-working-text"), Qnil)); + ns_send_appdefined (-1); + } + else + { + emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT; + emacs_event->code = KEY_NS_INSERT_WORKING_TEXT; + EV_TRAILER ((id)nil); + } +} + + +/* delete display of composing characters [not in ] */ +- (void)deleteWorkingText +{ + if (workingText == nil) + return; + if (NS_KEYLOG) + fprintf (stderr, "deleteWorkingText len =%d\n", [workingText length]); + [workingText release]; + workingText = nil; + processingCompose = NO; + + if (!emacs_event) + return; + + if (!EQ (Feval (Fcons (intern ("ns-in-echo-area"), Qnil)), Qnil)) + { + Feval (Fcons (intern ("ns-unecho-working-text"), Qnil)); + ns_send_appdefined (-1); + } + else + { + emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT; + emacs_event->code = KEY_NS_DELETE_WORKING_TEXT; + EV_TRAILER ((id)nil); + } + } + + +- (BOOL)hasMarkedText +{ + return workingText != nil; +} + +- (NSRange)markedRange +{ + NSRange rng = workingText != nil + ? NSMakeRange (0, [workingText length]) : NSMakeRange (NSNotFound, 0); +if (NS_KEYLOG) NSLog (@"markedRange request"); + return rng; +} + +- (void)unmarkText +{ +if (NS_KEYLOG) NSLog (@"unmark (accept) text"); + [self deleteWorkingText]; + processingCompose = NO; +} + +/* used to position char selection windows, etc. */ +- (NSRect)firstRectForCharacterRange: (NSRange)theRange +{ + NSRect rect; + NSPoint pt; + struct window *win = XWINDOW (FRAME_SELECTED_WINDOW (emacsframe)); +if (NS_KEYLOG) NSLog (@"firstRectForCharRange request"); + + rect.size.width = theRange.length * FRAME_COLUMN_WIDTH (emacsframe); + rect.size.height = FRAME_LINE_HEIGHT (emacsframe); + pt.x = WINDOW_TEXT_TO_FRAME_PIXEL_X (win, win->phys_cursor.x); + pt.y = WINDOW_TO_FRAME_PIXEL_Y (win, win->phys_cursor.y + +FRAME_LINE_HEIGHT (emacsframe)); + + pt = [self convertPoint: pt toView: nil]; + pt = [[self window] convertBaseToScreen: pt]; + rect.origin = pt; + return rect; +} + +- (long)conversationIdentifier +{ + return (long)self; +} + +/*PENDING: below here not yet implemented correctly, but may not be needed */ + +- (void)doCommandBySelector: (SEL)aSelector +{ + if (NS_KEYLOG) NSLog (@"Do command by selector: %@", + NSStringFromSelector (aSelector)); + + if (aSelector == @selector (deleteBackward:)) + { + /* happens when user backspaces over an ongoing composition: + throw a 'delete' into the event queue */ + if (!emacs_event) + return; + emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT; + emacs_event->code = 0xFF08; + EV_TRAILER ((id)nil); + } +} + +- (NSArray *)validAttributesForMarkedText +{ + static NSArray *arr = nil; + if (arr == nil) arr = [NSArray new]; + /* [[NSArray arrayWithObject: NSUnderlineStyleAttributeName] retain]; */ + return arr; +} + +- (NSRange)selectedRange +{ +if (NS_KEYLOG) NSLog (@"selectedRange request"); + return NSMakeRange (NSNotFound, 0); +} + +- (unsigned int)characterIndexForPoint: (NSPoint)thePoint +{ +if (NS_KEYLOG) NSLog (@"characterIndexForPoint request"); + return 0; +} + +- (NSAttributedString *)attributedSubstringFromRange: (NSRange)theRange +{ + static NSAttributedString *str = nil; + if (str == nil) str = [NSAttributedString new]; +if (NS_KEYLOG) NSLog (@"attributedSubstringFromRange request"); + return str; +} + +/* End impl. */ +/*****************************************************************************/ + + +/* This is what happens when the user presses a mouse button. */ +- (void)mouseDown: (NSEvent *)theEvent +{ + NSPoint p = [self convertPoint: [theEvent locationInWindow] fromView: nil]; + Lisp_Object window; + + NSTRACE (mouseDown); + + [self deleteWorkingText]; + + if (!emacs_event) + return; + + last_mouse_frame = emacsframe; + /* appears to be needed to prevent spurious movement events generated on + button clicks */ + last_mouse_frame->mouse_moved = 0; + + if ([theEvent type] == NSScrollWheel) + { + float delta = [theEvent deltaY]; + /* Mac notebooks send wheel events w/delta =0 when trackpad scrolling */ + if (delta == 0) + return; + emacs_event->kind = WHEEL_EVENT; + emacs_event->code = 0; + emacs_event->modifiers = EV_MODIFIERS (theEvent) | + ((delta > 0) ? up_modifier : down_modifier); + } + else + { + emacs_event->kind = MOUSE_CLICK_EVENT; + emacs_event->code = EV_BUTTON (theEvent); + emacs_event->modifiers = EV_MODIFIERS (theEvent) + | EV_UDMODIFIERS (theEvent); + } + XSETINT (emacs_event->x, lrint (p.x)); + XSETINT (emacs_event->y, lrint (p.y)); + EV_TRAILER (theEvent); +} + + +- (void)mouseUp: (NSEvent *)theEvent +{ + NSTRACE (mouseUp); + [self mouseDown: theEvent]; +} + + +- (void)rightMouseDown: (NSEvent *)theEvent +{ + NSTRACE (rightMouseDown); + [self mouseDown: theEvent]; +} + + +- (void)rightMouseUp: (NSEvent *)theEvent +{ + NSTRACE (rightMouseUp); + [self mouseDown: theEvent]; +} + + +- (void) scrollWheel: (NSEvent *)theEvent +{ + NSTRACE (scrollWheel); + [self mouseDown: theEvent]; +} + + +/* Tell emacs the mouse has moved. */ +- (void)mouseMoved: (NSEvent *)e +{ + struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (emacsframe); + Lisp_Object frame; + + NSTRACE (mouseMoved); + + last_mouse_movement_time = EV_TIMESTAMP (e); + last_mouse_motion_position = + [self convertPoint: [e locationInWindow] fromView: nil]; + + /* update any mouse face */ + if (dpyinfo->mouse_face_hidden) + { + dpyinfo->mouse_face_hidden = 0; + clear_mouse_face (dpyinfo); + } + + /* tooltip handling */ + previous_help_echo_string = help_echo_string; + help_echo_string = Qnil; + + if (!note_mouse_movement (emacsframe, last_mouse_motion_position.x, + last_mouse_motion_position.y)) + help_echo_string = previous_help_echo_string; + + XSETFRAME (frame, emacsframe); + if (!NILP (help_echo_string) || !NILP (previous_help_echo_string)) + { + /* NOTE: help_echo_{window,pos,object} are set in xdisp.c + (note_mouse_highlight), which is called through the + note_mouse_movement () call above */ + gen_help_event (help_echo_string, frame, help_echo_window, + help_echo_object, help_echo_pos); + } + else + { + help_echo_string = Qnil; + gen_help_event (Qnil, frame, Qnil, Qnil, 0); + } + + if (emacsframe->mouse_moved && send_appdefined) + ns_send_appdefined (-1); +} + + +- (void)mouseDragged: (NSEvent *)e +{ + NSTRACE (mouseDragged); + [self mouseMoved: e]; +} + + +- (void)rightMouseDragged: (NSEvent *)e +{ + NSTRACE (rightMouseDragged); + [self mouseMoved: e]; +} + + +- (BOOL)windowShouldClose: (id)sender +{ + NSEvent *e =[[self window] currentEvent]; + + NSTRACE (windowShouldClose); + windowClosing = YES; + if (ns_window_num <= 1) + return NO; + if (!emacs_event) + return NO; + emacs_event->kind = DELETE_WINDOW_EVENT; + emacs_event->modifiers = 0; + emacs_event->code = 0; + EV_TRAILER (e); + /* Don't close this window, let this be done from lisp code. */ + return NO; +} + + +- (NSSize)windowWillResize: (NSWindow *)sender toSize: (NSSize)frameSize +/* normalize frame to gridded text size */ +{ + NSTRACE (windowWillResize); +/*fprintf (stderr,"Window will resize: %.0f x %.0f\n",frameSize.width,frameSize.height); */ + + cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe, +#ifdef NS_IMPL_GNUSTEP + frameSize.width + 3); +#else + frameSize.width); +#endif + if (cols < MINWIDTH) + cols = MINWIDTH; + frameSize.width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (emacsframe, cols); + + rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (emacsframe, frameSize.height +#ifdef NS_IMPL_GNUSTEP + - FRAME_NS_TITLEBAR_HEIGHT (emacsframe) + 3 + - FRAME_NS_TOOLBAR_HEIGHT (emacsframe)); +#else + - FRAME_NS_TITLEBAR_HEIGHT (emacsframe) + - FRAME_NS_TOOLBAR_HEIGHT (emacsframe)); +#endif + if (rows < MINHEIGHT) + rows = MINHEIGHT; + frameSize.height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (emacsframe, rows) + + FRAME_NS_TITLEBAR_HEIGHT (emacsframe) + + FRAME_NS_TOOLBAR_HEIGHT (emacsframe); +#ifdef NS_IMPL_COCOA + { + /* this sets window title to have size in it; the wm does this under GS */ + NSRect r = [[self window] frame]; + if (r.size.height == frameSize.height && r.size.width == frameSize.width) + { + if (old_title != 0) + { + xfree (old_title); + old_title = 0; + } + } + else + { + char *size_title; + NSWindow *window = [self window]; + if (old_title == 0) + { + const char *t = [[[self window] title] UTF8String]; + char *pos = strstr (t, " — "); + if (pos) + *pos = '\0'; + old_title = (char *) xmalloc (strlen (t) + 1); + strcpy (old_title, t); + } + size_title = xmalloc (strlen (old_title) + 40); + sprintf (size_title, "%s — (%d x %d)", old_title, cols, rows); + [window setTitle: [NSString stringWithUTF8String: size_title]]; + [window display]; + xfree (size_title); + } + } +#endif /* NS_IMPL_COCOA */ +/*fprintf (stderr," ...size became %.0f x %.0f (%d x %d)\n",frameSize.width,frameSize.height,cols,rows); */ + + return frameSize; +} + + +- (void)windowDidResize: (NSNotification *)notification +{ + NSWindow *theWindow = [notification object]; + +#ifdef NS_IMPL_GNUSTEP + /* in GNUstep, at least currently, it's possible to get a didResize + without getting a willResize.. therefore we need to act as if we got + the willResize now */ + NSSize sz = [theWindow frame].size; + sz = [self windowWillResize: theWindow toSize: sz]; +#endif /* NS_IMPL_GNUSTEP */ + + NSTRACE (windowDidResize); +/*fprintf (stderr,"windowDidResize: %.0f\n",[theWindow frame].size.height); */ + +#ifdef NS_IMPL_COCOA + if (old_title != 0) + { + xfree (old_title); + old_title = 0; + } +#endif /* NS_IMPL_COCOA */ + + if (cols > 0 && rows > 0) + x_set_window_size (emacsframe, 0, cols, rows); + + ns_send_appdefined (-1); + [NSApp stopModal]; +} + + +- (void)windowDidBecomeKey: (NSNotification *)notification +{ + int val = ns_lisp_to_cursor_type (get_frame_param (emacsframe, Qcursor_type)); + struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (emacsframe); + struct frame *old_focus = dpyinfo->ns_focus_frame; + + NSTRACE (windowDidBecomeKey); + + if (emacsframe != old_focus) + dpyinfo->ns_focus_frame = emacsframe; + /*/last_mouse_frame = emacsframe;? */ + + if (val >= 0) + { + FRAME_NEW_CURSOR (emacsframe) = val; +/* x_update_cursor (emacsframe, 1); // will happen in ns_frame_rehighlight */ + } + + ns_frame_rehighlight (emacsframe); + + if (emacs_event) + { + emacs_event->kind = FOCUS_IN_EVENT; + EV_TRAILER ((id)nil); + } +} + + +- (void)windowDidResignKey: (NSNotification *)notification +{ + struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (emacsframe); + NSTRACE (windowDidResignKey); + + if (!windowClosing && [[self window] isVisible] == YES) + { + FRAME_NEW_CURSOR (emacsframe) = hollow_box; + x_update_cursor (emacsframe, 1); + FRAME_LAST_INACTIVE (emacsframe) = YES; + } + + if (dpyinfo->ns_highlight_frame == emacsframe) + dpyinfo->ns_highlight_frame = 0; + if (dpyinfo->ns_focus_frame == emacsframe) + dpyinfo->ns_focus_frame = 0; + + if (dpyinfo->mouse_face_mouse_frame == emacsframe) + { + clear_mouse_face (dpyinfo); + dpyinfo->mouse_face_mouse_frame = 0; + } + + if (emacs_event) + { + [self deleteWorkingText]; + emacs_event->kind = FOCUS_IN_EVENT; + EV_TRAILER ((id)nil); + } +} + + +- (void)windowWillMiniaturize: sender +{ + NSTRACE (windowWillMiniaturize); +} + + +- (BOOL)isFlipped +{ + return YES; +} + + +- (BOOL)isOpaque +{ + return NO; +} + + +- initFrameFromEmacs: (struct frame *)f +{ + NSRect r, wr; + Lisp_Object tem; + NSWindow *win; + NSButton *toggleButton; + int vbextra = NS_SCROLL_BAR_WIDTH (f); + NSSize sz; + NSColor *col; + NSString *name; + + NSTRACE (initFrameFromEmacs); + + windowClosing = NO; + processingCompose = NO; + scrollbarsNeedingUpdate = 0; + +/*fprintf (stderr,"init with %d, %d\n",f->text_cols, f->text_lines); */ + + r = NSMakeRect (0, 0, FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, f->text_cols), + FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, f->text_lines)); + [self initWithFrame: r]; + + FRAME_NS_VIEW (f) = self; + emacsframe = f; + old_title = 0; + + win = [[EmacsWindow alloc] + initWithContentRect: r + styleMask: (NSResizableWindowMask | + NSMiniaturizableWindowMask | + NSClosableWindowMask) + backing: NSBackingStoreBuffered + defer: YES]; + + wr = [win frame]; + f->border_width = wr.size.width - r.size.width; + FRAME_NS_TITLEBAR_HEIGHT (f) = wr.size.height - r.size.height; + + [win setAcceptsMouseMovedEvents: YES]; + [win setDelegate: self]; + [win useOptimizedDrawing: YES]; + + sz.width = FRAME_COLUMN_WIDTH (f); + sz.height = FRAME_LINE_HEIGHT (f); + [win setResizeIncrements: sz]; + + [[win contentView] addSubview: self]; + + if (ns_drag_types) + [self registerForDraggedTypes: ns_drag_types]; + + tem = f->name; + name = [NSString stringWithUTF8String: + NILP (tem) ? (unsigned char *)"Emacs" : XSTRING (tem)->data]; + [win setTitle: name]; + + /* toolbar support */ + toolbar = [[EmacsToolbar alloc] initForView: self withIdentifier: + [NSString stringWithFormat: @"Emacs Frame %d", + ns_window_num]]; + [win setToolbar: toolbar]; + [toolbar setVisible: NO]; +#ifdef NS_IMPL_COCOA + toggleButton = [win standardWindowButton: NSWindowToolbarButton]; + [toggleButton setTarget: self]; + [toggleButton setAction: @selector (toggleToolbar: )]; +#endif + FRAME_NS_TOOLBAR_HEIGHT (f) = 0; + + tem = f->icon_name; + if (!NILP (tem)) + [win setMiniwindowTitle: + [NSString stringWithUTF8String: XSTRING (tem)->data]]; + + { + NSScreen *screen = [win screen]; + + if (screen != 0) + [win setFrameTopLeftPoint: NSMakePoint + (IN_BOUND (-SCREENMAX, f->left_pos, SCREENMAX), + IN_BOUND (-SCREENMAX, + [screen frame].size.height - NS_TOP_POS (f), SCREENMAX))]; + } + + [win makeFirstResponder: self]; + + col = ns_lookup_indexed_color (NS_FACE_BACKGROUND + (FRAME_DEFAULT_FACE (emacsframe)), emacsframe); + [win setBackgroundColor: col]; + if ([col alphaComponent] != 1.0) + [win setOpaque: NO]; + + [self allocateGState]; + + ns_window_num++; + return self; +} + + +- (void)windowDidMove: sender +{ + NSWindow *win = [self window]; + NSRect r = [win frame]; + NSScreen *screen = [win screen]; + NSRect sr = [screen frame]; + + NSTRACE (windowDidMove); + + if (!emacsframe->output_data.ns) + return; + if (screen != nil) + { + emacsframe->left_pos = r.origin.x; /* - sr.origin.x; */ + emacsframe->top_pos = sr.size.height - + (r.origin.y + r.size.height); /* + sr.origin.y; */ + } +} + +#ifdef NS_IMPL_COCOA +/* if we don't do this manually, the window will resize but not move */ +- (BOOL)windowShouldZoom: (NSWindow *)sender toFrame: (NSRect)newFrame +{ + [[self window] setFrame: newFrame display: NO]; + return YES; +} +#endif + +/* Implement this to control size of frame on zoom. +- (NSRect)windowWillUseStandardFrame:(NSWindow *)sender + defaultFrame:(NSRect)defaultFrame; */ + + +- (void)windowDidDeminiaturize: sender +{ + NSTRACE (windowDidDeminiaturize); + if (!emacsframe->output_data.ns) + return; + emacsframe->async_visible = 1; + emacsframe->async_iconified = 0; + windows_or_buffers_changed++; + + if (emacs_event) + { + emacs_event->kind = ICONIFY_EVENT; + EV_TRAILER ((id)nil); + } +} + + +- (void)windowDidExpose: sender +{ + NSTRACE (windowDidExpose); + if (!emacsframe->output_data.ns) + return; + emacsframe->async_visible = 1; + SET_FRAME_GARBAGED (emacsframe); + + if (send_appdefined) + ns_send_appdefined (-1); +} + + +- (void)windowDidMiniaturize: sender +{ + NSTRACE (windowDidMiniaturize); + if (!emacsframe->output_data.ns) + return; + + emacsframe->async_iconified = 1; + + if (emacs_event) + { + emacs_event->kind = ICONIFY_EVENT; + EV_TRAILER ((id)nil); + } +} + + +- (void)mouseEntered: (NSEvent *)theEvent +{ + NSPoint p = [self convertPoint: [theEvent locationInWindow] fromView: nil]; + struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (emacsframe); + NSTRACE (mouseEntered); + + last_mouse_movement_time = EV_TIMESTAMP (theEvent); +} + + +- (void)mouseExited: (NSEvent *)theEvent +{ + NSPoint p = [self convertPoint: [theEvent locationInWindow] fromView: nil]; + NSRect r; + struct ns_display_info *dpyinfo = + emacsframe ? FRAME_NS_DISPLAY_INFO (emacsframe) : NULL; + + NSTRACE (mouseExited); + + if (dpyinfo || !emacsframe) + return; + + last_mouse_movement_time = EV_TIMESTAMP (theEvent); + + if (emacsframe == dpyinfo->mouse_face_mouse_frame) + { + clear_mouse_face (dpyinfo); + dpyinfo->mouse_face_mouse_frame = 0; + } +} + + +- menuDown: sender +{ + NSTRACE (menuDown); + if (context_menu_value == -1) + context_menu_value = [sender tag]; + else + find_and_call_menu_selection (emacsframe, emacsframe->menu_bar_items_used, + emacsframe->menu_bar_vector, [sender tag]); + ns_send_appdefined (-1); + return self; +} + + +- (EmacsToolbar *)toolbar +{ + return toolbar; +} + + +/* this gets called on toolbar button click */ +- toolbarClicked: (id)item +{ + NSEvent *theEvent; + int idx = [item tag] * TOOL_BAR_ITEM_NSLOTS; + + NSTRACE (toolbarClicked); + + if (!emacs_event) + return self; + + /* send first event (for some reason two needed) */ + theEvent =[[self window] currentEvent]; + emacs_event->kind = TOOL_BAR_EVENT; + XSETFRAME (emacs_event->arg, emacsframe); + EV_TRAILER (theEvent); + + emacs_event->kind = TOOL_BAR_EVENT; +/* XSETINT (emacs_event->code, 0); */ + emacs_event->arg = AREF (emacsframe->tool_bar_items, + idx + TOOL_BAR_ITEM_KEY); + emacs_event->modifiers = EV_MODIFIERS (theEvent); + EV_TRAILER (theEvent); + return self; +} + + +- toggleToolbar: (id)sender +{ + Lisp_Object lispFrame; + XSETFRAME (lispFrame, emacsframe); + Feval (Fcons (intern ("ns-toggle-toolbar"), Fcons (lispFrame, Qnil))); + SET_FRAME_GARBAGED (emacsframe); + ns_send_appdefined (-1); +} + + +- (void)drawRect: (NSRect)rect +{ + int x = NSMinX (rect), y = NSMinY (rect); + int width = NSWidth (rect), height = NSHeight (rect); + + NSTRACE (drawRect); + + if (!emacsframe || !emacsframe->output_data.ns) + return; + + if (!ns_in_resize) + ns_clear_frame_area (emacsframe, x, y, width, height); + expose_frame (emacsframe, x, y, width, height); + + emacsframe->async_visible = 1; + emacsframe->async_iconified = 0; + +/* SET_FRAME_GARBAGED (emacsframe); + ns_send_appdefined (-1); */ +} + + +/* NSDraggingDestination protocol methods. Actually this is not really a + protocol, but a category of Object. O well... */ + +-(unsigned int) draggingEntered: (id ) sender +{ + NSTRACE (draggingEntered); + return NSDragOperationGeneric; +} + + +-(BOOL)prepareForDragOperation: (id ) sender +{ + return YES; +} + + +-(BOOL)performDragOperation: (id ) sender +{ + id pb; + int x, y; + NSString *type; + NSEvent *theEvent = [[self window] currentEvent]; + NSPoint position; + + NSTRACE (performDragOperation); + + if (!emacs_event) + return; + + position = [self convertPoint: [sender draggingLocation] fromView: nil]; + x = lrint (position.x); y = lrint (position.y); + + pb = [sender draggingPasteboard]; + type = [pb availableTypeFromArray: ns_drag_types]; + if (type == 0) + { + return NO; + } + else if ([type isEqualToString: NSFilenamesPboardType]) + { + NSArray *files; + NSEnumerator *fenum; + NSString *file; + + if (!(files = [pb propertyListForType: type])) + return NO; + + fenum = [files objectEnumerator]; + while ( (file = [fenum nextObject]) ) + { + emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT; + emacs_event->code = KEY_NS_DRAG_FILE; + XSETINT (emacs_event->x, x); + XSETINT (emacs_event->y, y); + ns_input_file = append2 (ns_input_file, + build_string ([file UTF8String])); + emacs_event->modifiers = EV_MODIFIERS (theEvent); + EV_TRAILER (theEvent); + } + return YES; + } + else if ([type isEqualToString: NSURLPboardType]) + { + NSString *file; + NSURL *fileURL; + + if (!(fileURL = [NSURL URLFromPasteboard: pb]) || + [fileURL isFileURL] == NO) + return NO; + + file = [fileURL path]; + emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT; + emacs_event->code = KEY_NS_DRAG_FILE; + XSETINT (emacs_event->x, x); + XSETINT (emacs_event->y, y); + ns_input_file = append2 (ns_input_file, build_string ([file UTF8String])); + emacs_event->modifiers = EV_MODIFIERS (theEvent); + EV_TRAILER (theEvent); + return YES; + } + else if ([type isEqualToString: NSStringPboardType] + || [type isEqualToString: NSTabularTextPboardType]) + { + NSString *data; + + if (! (data = [pb stringForType: type])) + return NO; + + emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT; + emacs_event->code = KEY_NS_DRAG_TEXT; + XSETINT (emacs_event->x, x); + XSETINT (emacs_event->y, y); + ns_input_text = build_string ([data UTF8String]); + emacs_event->modifiers = EV_MODIFIERS (theEvent); + EV_TRAILER (theEvent); + return YES; + } + else if ([type isEqualToString: NSColorPboardType]) + { + NSColor *c = [NSColor colorFromPasteboard: pb]; + emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT; + emacs_event->code = KEY_NS_DRAG_COLOR; + XSETINT (emacs_event->x, x); + XSETINT (emacs_event->y, y); + ns_input_color = ns_color_to_lisp (c); + emacs_event->modifiers = EV_MODIFIERS (theEvent); + EV_TRAILER (theEvent); + return YES; + } + else if ([type isEqualToString: NSFontPboardType]) + { + /* impl based on GNUstep NSTextView.m */ + NSData *data = [pb dataForType: NSFontPboardType]; + NSDictionary *dict = [NSUnarchiver unarchiveObjectWithData: data]; + NSFont *font = [dict objectForKey: NSFontAttributeName]; + char fontSize[10]; + + if (font == nil) + return NO; + + emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT; + emacs_event->code = KEY_NS_CHANGE_FONT; + XSETINT (emacs_event->x, x); + XSETINT (emacs_event->y, y); + ns_input_font = build_string ([[font fontName] UTF8String]); + snprintf (fontSize, 10, "%f", [font pointSize]); + ns_input_fontsize = build_string (fontSize); + emacs_event->modifiers = EV_MODIFIERS (theEvent); + EV_TRAILER (theEvent); + return YES; + } + else + { + error ("Invalid data type in dragging pasteboard."); + return NO; + } +} + + +- validRequestorForSendType: (NSString *)typeSent + returnType: (NSString *)typeReturned +{ + NSTRACE (validRequestorForSendType); + if ([ns_send_types indexOfObjectIdenticalTo: typeSent] != NSNotFound && + [ns_return_types indexOfObjectIdenticalTo: typeSent] != NSNotFound) + return self; + + return [super validRequestorForSendType: typeSent + returnType: typeReturned]; +} + + +/* setMini =YES means set from internal (gives a finder icon), NO means set nil + (gives a miniaturized version of the window); currently we use the latter for + frames whose active buffer doesn't correspond to any file + (e.g., '*scratch*') */ +- setMiniwindowImage: (BOOL) setMini +{ + id image = [[self window] miniwindowImage]; + NSTRACE (setMiniwindowImage); + + /* NOTE: under Cocoa miniwindowImage always returns nil, documentation + about "AppleDockIconEnabled" notwithstanding, however the set message + below has its effect nonetheless. */ + if (image != emacsframe->output_data.ns->miniimage) + { + if (image && [image isKindOfClass: [EmacsImage class]]) + [image release]; + [[self window] setMiniwindowImage: + setMini ? emacsframe->output_data.ns->miniimage : nil]; + } + + return self; +} + + +- (void) setRows: (int) r andColumns: (int) c +{ + rows = r; + cols = c; +} + +@end /* EmacsView */ + + + +/* ========================================================================== + + EmacsWindow implementation + + ========================================================================== */ + +@implementation EmacsWindow + +/* called only on resize clicks by special case in EmacsApp-sendEvent */ +- (void)mouseDown: (NSEvent *)theEvent +{ + if (ns_in_resize) + { + NSSize size = [[theEvent window] frame].size; + grabOffset = [theEvent locationInWindow]; + grabOffset.x = size.width - grabOffset.x; + } + else + [super mouseDown: theEvent]; +} + + +/* stop resizing */ +- (void)mouseUp: (NSEvent *)theEvent +{ + if (ns_in_resize) + { + struct frame *f = ((EmacsView *)[self delegate])->emacsframe; + ns_in_resize = NO; + ns_set_name_as_filename (f); + [self display]; + ns_send_appdefined (-1); + } + else + [super mouseUp: theEvent]; +} + + +/* send resize events */ +- (void)mouseDragged: (NSEvent *)theEvent +{ + if (ns_in_resize) + { + NSPoint p = [theEvent locationInWindow]; + NSSize size, vettedSize, origSize = [self frame].size; + + size.width = p.x + grabOffset.x; + size.height = origSize.height - p.y + grabOffset.y; + + if (size.width == origSize.width && size.height == origSize.height) + return; + + vettedSize = [[self delegate] windowWillResize: self toSize: size]; + if (vettedSize.width != size.width || vettedSize.height != size.height) + { + [[NSNotificationCenter defaultCenter] + postNotificationName: NSWindowDidResizeNotification + object: self]; + } + } + else + [super mouseDragged: theEvent]; +} + +@end /* EmacsWindow */ + + +/* ========================================================================== + + EmacsScroller implementation + + ========================================================================== */ + + +@implementation EmacsScroller + +/* for repeat button push */ +#define SCROLL_BAR_FIRST_DELAY 0.5 +#define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15) + ++ (float) scrollerWidth +{ + /* PENDING: if we want to allow variable widths, this is the place to do it, + however neither GNUstep nor Cocoa support it very well */ + return [NSScroller scrollerWidth]; +} + + +- initFrame: (NSRect )r window: (Lisp_Object)nwin +{ + NSTRACE (EmacsScroller_initFrame); + + r.size.width = [EmacsScroller scrollerWidth]; + [super initWithFrame: r/*NSMakeRect (0, 0, 0, 0)*/]; + [self setContinuous: YES]; + [self setEnabled: YES]; + + /* Ensure auto resizing of scrollbars occurs within the emacs frame's view + locked against the right, top and bottom edges. */ + [self setAutoresizingMask: NSViewMinXMargin | NSViewHeightSizable]; + + win = nwin; + condemned = NO; + pixel_height = NSHeight (r); + min_portion = 20 / pixel_height; + + frame = XFRAME (XWINDOW (win)->frame); + if (FRAME_LIVE_P (frame)) + { + int i; + EmacsView *view = FRAME_NS_VIEW (frame); + NSView *sview = [[view window] contentView]; + NSArray *subs = [sview subviews]; + + /* disable optimization stopping redraw of other scrollbars */ + view->scrollbarsNeedingUpdate = 0; + for (i =[subs count]-1; i >= 0; i--) + if ([[subs objectAtIndex: i] isKindOfClass: [EmacsScroller class]]) + view->scrollbarsNeedingUpdate++; + [sview addSubview: self]; + } + +/* [self setFrame: r]; */ + + return self; +} + + +- (void)setFrame: (NSRect)newRect +{ + NSTRACE (EmacsScroller_setFrame); +/* BLOCK_INPUT; */ + pixel_height = NSHeight (newRect); + min_portion = 20 / pixel_height; + [super setFrame: newRect]; + [self display]; +/* UNBLOCK_INPUT; */ +} + + +- (void)dealloc +{ + NSTRACE (EmacsScroller_dealloc); + if (!NILP (win)) + XWINDOW (win)->vertical_scroll_bar = Qnil; + [super dealloc]; +} + + +- condemn +{ + NSTRACE (condemn); + condemned =YES; + return self; +} + + +- reprieve +{ + NSTRACE (reprieve); + condemned =NO; + return self; +} + + +- judge +{ + NSTRACE (judge); + if (condemned) + { + BLOCK_INPUT; + /* ensure other scrollbar updates after deletion */ + EmacsView *view = (EmacsView *)FRAME_NS_VIEW (frame); + if (view != nil) + view->scrollbarsNeedingUpdate++; + [self removeFromSuperview]; + [self release]; + UNBLOCK_INPUT; + } + return self; +} + + +- (void)resetCursorRects +{ + NSRect visible = [self visibleRect]; + NSTRACE (resetCursorRects); + + if (!NSIsEmptyRect (visible)) + [self addCursorRect: visible cursor: [NSCursor arrowCursor]]; + [[NSCursor arrowCursor] setOnMouseEntered: YES]; +} + + +- (int) checkSamePosition: (int) position portion: (int) portion + whole: (int) whole +{ + return em_position ==position && em_portion ==portion && em_whole ==whole + && portion != whole; /* needed for resize empty buf */ +} + + +- setPosition: (int)position portion: (int)portion whole: (int)whole +{ + NSTRACE (setPosition); + + em_position = position; + em_portion = portion; + em_whole = whole; + + if (portion >= whole) + [self setFloatValue: 0.0 knobProportion: 1.0]; + else + { + float pos, por; + portion = max ((float)whole*min_portion/pixel_height, portion); + pos = (float)position / (whole - portion); + por = (float)portion/whole; + [self setFloatValue: pos knobProportion: por]; + } +#ifdef NS_IMPL_GNUSTEP + [self display]; +#endif + return self; +} + +/* PENDING: unused at moment (see ns_mouse_position) at the moment because + drag events will go directly to the EmacsScroller. Leaving in for now. */ +-(void)getMouseMotionPart: (int *)part window: (Lisp_Object *)window + x: (Lisp_Object *)x y: ( Lisp_Object *)y +{ + *part = last_hit_part; + *window = win; + XSETINT (*y, pixel_height); + if ([self floatValue] > 0.999) + XSETINT (*x, pixel_height); + else + XSETINT (*x, pixel_height * [self floatValue]); +} + + +/* set up emacs_event */ +- (void) sendScrollEventAtLoc: (float)loc fromEvent: (NSEvent *)e +{ + if (!emacs_event) + return; + + emacs_event->part = last_hit_part; + emacs_event->code = 0; + emacs_event->modifiers = EV_MODIFIERS (e) | down_modifier; + emacs_event->frame_or_window = win; + emacs_event->timestamp = EV_TIMESTAMP (e); + emacs_event->kind = SCROLL_BAR_CLICK_EVENT; + emacs_event->arg = Qnil; + XSETINT (emacs_event->x, loc * pixel_height); + XSETINT (emacs_event->y, pixel_height-20); + + n_emacs_events_pending++; + kbd_buffer_store_event_hold (emacs_event, q_event_ptr); + EVENT_INIT (*emacs_event); + ns_send_appdefined (-1); +} + + +/* called manually thru timer to implement repeated button action w/hold-down */ +- repeatScroll: (NSTimer *)scrollEntry +{ + NSEvent *e = [[self window] currentEvent]; + NSPoint p = [[self window] mouseLocationOutsideOfEventStream]; + BOOL inKnob = [self testPart: p] == NSScrollerKnob; + + /* clear timer if need be */ + if (inKnob || [scroll_repeat_entry timeInterval] == SCROLL_BAR_FIRST_DELAY) + { + [scroll_repeat_entry invalidate]; + [scroll_repeat_entry release]; + scroll_repeat_entry = nil; + + if (inKnob) + return self; + + scroll_repeat_entry = + [[NSTimer scheduledTimerWithTimeInterval: + SCROLL_BAR_CONTINUOUS_DELAY + target: self + selector: @selector (repeatScroll:) + userInfo: 0 + repeats: YES] + retain]; + } + + [self sendScrollEventAtLoc: 0 fromEvent: e]; + return self; +} + + +/* Asynchronous mouse tracking for scroller. This allows us to dispatch + mouseDragged events without going into a modal loop. */ +- (void)mouseDown: (NSEvent *)e +{ + NSRect sr, kr; + /* hitPart is only updated AFTER event is passed on */ + NSScrollerPart part = [self testPart: [e locationInWindow]]; + double inc = 0.0, loc, kloc, pos; + int edge = 0; + + NSTRACE (EmacsScroller_mouseDown); + + switch (part) + { + case NSScrollerDecrementPage: + last_hit_part = scroll_bar_above_handle; inc = -1.0; break; + case NSScrollerIncrementPage: + last_hit_part = scroll_bar_below_handle; inc = 1.0; break; + case NSScrollerDecrementLine: + last_hit_part = scroll_bar_up_arrow; inc = -0.1; break; + case NSScrollerIncrementLine: + last_hit_part = scroll_bar_down_arrow; inc = 0.1; break; + case NSScrollerKnob: + last_hit_part = scroll_bar_handle; break; + case NSScrollerKnobSlot: /* GNUstep-only */ + last_hit_part = scroll_bar_move_ratio; break; + default: /* NSScrollerNoPart? */ + fprintf (stderr, "EmacsScoller-mouseDown: unexpected part %d\n", part); + return; + } + + if (inc != 0.0) + { + pos = 0; /* ignored */ + + /* set a timer to repeat, as we can't let superclass do this modally */ + scroll_repeat_entry = + [[NSTimer scheduledTimerWithTimeInterval: 0.5 + target: self + selector: @selector (repeatScroll:) + userInfo: 0 + repeats: YES] + retain]; + } + else + { + /* handle, or on GNUstep possibly slot */ + NSEvent *fake_event; + + /* compute float loc in slot and mouse offset on knob */ + sr = [self convertRect: [self rectForPart: NSScrollerKnobSlot] + toView: nil]; + loc = NSHeight (sr) - ([e locationInWindow].y - NSMinY (sr)); + if (loc <= 0.0) + { + loc = 0.0; + edge = -1; + } + else if (loc >= NSHeight (sr)) + { + loc = NSHeight (sr); + edge = 1; + } + + if (edge) + kloc = 0.5 * edge; + else + { + kr = [self convertRect: [self rectForPart: NSScrollerKnob] + toView: nil]; + kloc = NSHeight (kr) - ([e locationInWindow].y - NSMinY (kr)); + } + last_mouse_offset = kloc; + + /* if knob, tell emacs a location offset by knob pos + (to indicate top of handle) */ + if (part == NSScrollerKnob) + pos = (loc - last_mouse_offset) / NSHeight (sr); + else + /* else this is a slot click on GNUstep: go straight there */ + pos = loc / NSHeight (sr); + + /* send a fake mouse-up to super to preempt modal -trackKnob: mode */ + fake_event = [NSEvent mouseEventWithType: NSLeftMouseUp + location: [e locationInWindow] + modifierFlags: [e modifierFlags] + timestamp: [e timestamp] + windowNumber: [e windowNumber] + context: [e context] + eventNumber: [e eventNumber] + clickCount: [e clickCount] + pressure: [e pressure]]; + [super mouseUp: fake_event]; + } + + if (part != NSScrollerKnob) + [self sendScrollEventAtLoc: pos fromEvent: e]; +} + + +/* Called as we manually track scroller drags, rather than superclass. */ +- (void)mouseDragged: (NSEvent *)e +{ + NSRect sr; + double loc, pos; + int edge = 0; + + NSTRACE (EmacsScroller_mouseDragged); + + sr = [self convertRect: [self rectForPart: NSScrollerKnobSlot] + toView: nil]; + loc = NSHeight (sr) - ([e locationInWindow].y - NSMinY (sr)); + + if (loc <= 0.0) + { + loc = 0.0; + edge = -1; + } + else if (loc >= NSHeight (sr) + last_mouse_offset) + { + loc = NSHeight (sr) + last_mouse_offset; + edge = 1; + } + + pos = /*(edge ? loc :*/ (loc - last_mouse_offset) / NSHeight (sr); + [self sendScrollEventAtLoc: pos fromEvent: e]; +} + + +- (void)mouseUp: (NSEvent *)e +{ + if (scroll_repeat_entry) + { + [scroll_repeat_entry invalidate]; + [scroll_repeat_entry release]; + scroll_repeat_entry = nil; + } + last_hit_part = 0; +} + + +/* treat scrollwheel events in the bar as though they were in the main window */ +- (void) scrollWheel: (NSEvent *)theEvent +{ + EmacsView *view = (EmacsView *)FRAME_NS_VIEW (frame); + [view mouseDown: theEvent]; +} + +@end /* EmacsScroller */ + + + +/* ========================================================================== + + EmacsPrefsController implementation + + ========================================================================== */ + + +@implementation EmacsPrefsController + +/* in Tiger+, can just do [popup selectItemWithTag: tag]; */ +static void selectItemWithTag (NSPopUpButton *popup, int tag) +{ + NSEnumerator *items = [[popup itemArray] objectEnumerator]; + NSMenuItem *item; + while (item = [items nextObject]) + { + if ([item tag] == tag) + { + [popup selectItem: item]; + return; + } + } +} + +- init +{ + [NSBundle loadNibNamed: @"preferences" owner: self]; + return self; +} + + +- (void) showForFrame: (struct frame *)f +{ + frame = f; + [self setPanelFromValues]; + [prefsWindow makeKeyAndOrderFront: self]; + [prefsWindow display]; +} + + +- (void) setPanelFromValues +{ + int cursorType = + ns_lisp_to_cursor_type (get_frame_param (frame, Qcursor_type)); + prevExpandSpace = XFLOATINT (ns_expand_space); + prevBlinkRate = NILP (ns_cursor_blink_rate) + ? 0 : XFLOATINT (ns_cursor_blink_rate); + +#ifdef NS_IMPL_COCOA + prevUseHighlightColor = ns_use_system_highlight_color; +#endif + + [expandSpaceSlider setFloatValue: prevExpandSpace]; + [cursorBlinkSlider setFloatValue: prevBlinkRate]; + [cursorTypeMatrix selectCellWithTag: (cursorType == filled_box ? 1 : + (cursorType == bar ? 2 : + (cursorType == underscore ? 3 : 4)))]; + selectItemWithTag (alternateModMenu, lisp_to_mod (ns_alternate_modifier)); + selectItemWithTag (commandModMenu, lisp_to_mod (ns_command_modifier)); +#ifdef NS_IMPL_COCOA + selectItemWithTag (controlModMenu, lisp_to_mod (ns_control_modifier)); + selectItemWithTag (functionModMenu, lisp_to_mod (ns_function_modifier)); + [smoothFontsCheck setState: ns_antialias_text ? YES : NO]; + [useQuickdrawCheck setState: ns_use_qd_smoothing ? YES : NO]; + [useSysHiliteCheck setState: prevUseHighlightColor ? YES : NO]; +#endif +} + + +- (void) setValuesFromPanel +{ + int cursorTag = [[cursorTypeMatrix selectedCell] tag]; + int altTag = [[alternateModMenu selectedItem] tag]; + int cmdTag = [[commandModMenu selectedItem] tag]; +#ifdef NS_IMPL_COCOA + int ctrlTag = [[controlModMenu selectedItem] tag]; + int fnTag = [[functionModMenu selectedItem] tag]; +#endif + float blinkRate = [cursorBlinkSlider floatValue]; + float expandSpace = [expandSpaceSlider floatValue]; + Lisp_Object old_cursor_blink_mode; + + if (expandSpace != prevExpandSpace) + { + ns_expand_space = make_float (expandSpace); + /* PENDING: more needed: store needed metrics in nsfont_info, update + frame default font max_bounds and fontp, recompute faces */ +/* FRAME_LINE_HEIGHT (frame) *= (expandSpace / prevExpandSpace); + x_set_window_size (frame, 0, frame->text_cols, frame->text_lines); */ + prevExpandSpace = expandSpace; + } + if (blinkRate != prevBlinkRate) + { + old_cursor_blink_mode = ns_cursor_blink_mode; + if (blinkRate == 0.0) + { + ns_cursor_blink_rate = Qnil; + ns_cursor_blink_mode = Qnil; + } + else + { + ns_cursor_blink_rate = make_float (blinkRate); + ns_cursor_blink_mode = Qt; + } + if (ns_cursor_blink_mode != old_cursor_blink_mode) + Feval (Fcons (intern ("blink-cursor-mode"), Qnil)); + + if (blinkRate != 0.0 && prevBlinkRate != 0.0) + { /* if changed rates, remove blink handler so change picked up */ + struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (frame); + [cursor_blink_entry invalidate]; + [cursor_blink_entry release]; + cursor_blink_entry = 0; + if (dpyinfo->ns_highlight_frame) + { + Lisp_Object tem = + get_frame_param (dpyinfo->ns_highlight_frame, Qcursor_type); + dpyinfo->ns_highlight_frame->output_data.ns->desired_cursor = + ns_lisp_to_cursor_type (tem); + } + } + prevBlinkRate = blinkRate; + } + FRAME_NEW_CURSOR (frame) = + (cursorTag == 1 ? filled_box : + (cursorTag == 2 ? bar : + (cursorTag == 3 ? underscore : hollow_box))); + store_frame_param (frame, Qcursor_type, + ns_cursor_type_to_lisp (FRAME_NEW_CURSOR (frame))); + ns_alternate_modifier = ns_mod_to_lisp (altTag); + ns_command_modifier = ns_mod_to_lisp (cmdTag); +#ifdef NS_IMPL_COCOA + ns_control_modifier = ns_mod_to_lisp (ctrlTag); + ns_function_modifier = ns_mod_to_lisp (fnTag); + ns_antialias_text = [smoothFontsCheck state]; + ns_use_qd_smoothing = [useQuickdrawCheck state]; + ns_use_system_highlight_color = [useSysHiliteCheck state]; + if (ns_use_system_highlight_color != prevUseHighlightColor) + { + prevUseHighlightColor = ns_use_system_highlight_color; + if (ns_use_system_highlight_color == YES) + { + ns_selection_color = [[NSUserDefaults standardUserDefaults] + stringForKey: @"AppleHighlightColor"]; + if (ns_selection_color == nil) + ns_selection_color = NS_SELECTION_COLOR_DEFAULT; + } + else + ns_selection_color = NS_SELECTION_COLOR_DEFAULT; + } +#endif /* NS_IMPL_COCOA */ + Fcall_interactively (intern ("ns-save-preferences"), Qnil, Qnil); +} + + +/* buttons */ +- (IBAction)cancel: (id)sender +{ + [prefsWindow close]; +} + + +- (IBAction)ok: (id)sender +{ + [self setValuesFromPanel]; + [prefsWindow close]; +} + + +- (IBAction)resetToDefaults: (id)sender +{ + ns_set_default_prefs (); + [self setPanelFromValues]; +} + + +- (IBAction)runHelp: (id)sender +{ + Feval (Fcons (intern ("info"), + Fcons (build_string ("(ns-emacs)Preferences Panel"), Qnil))); + SET_FRAME_GARBAGED (frame); + ns_send_appdefined (-1); +} + + +- (IBAction)setColors: (id)sender +{ + Lisp_Object lispFrame; + XSETFRAME (lispFrame, frame); + Fns_popup_color_panel (lispFrame); +} + + +- (IBAction)setDefaultFont: (id)sender +{ + Lisp_Object lispFrame; + XSETFRAME (lispFrame, frame); + Fns_popup_font_panel (lispFrame); +} + +@end /* EmacsPrefsController */ + + + + +/* ========================================================================== + + Font-related functions; these used to be in nsfaces.m + + ========================================================================== */ + + +Lisp_Object +x_new_font (struct frame *f, Lisp_Object font_object, int fontset) +{ + struct font *font = XFONT_OBJECT (font_object); + + if (fontset < 0) + fontset = fontset_from_font (font_object); + FRAME_FONTSET (f) = fontset; + + if (FRAME_FONT (f) == font) + /* This font is already set in frame F. There's nothing more to + do. */ + return font_object; + + FRAME_FONT (f) = font; + + FRAME_BASELINE_OFFSET (f) = font->baseline_offset; + FRAME_COLUMN_WIDTH (f) = font->average_width; + FRAME_SPACE_WIDTH (f) = font->space_width; + FRAME_LINE_HEIGHT (f) = font->height; + + compute_fringe_widths (f, 1); + + /* Compute the scroll bar width in character columns. */ + if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0) + { + int wid = FRAME_COLUMN_WIDTH (f); + FRAME_CONFIG_SCROLL_BAR_COLS (f) + = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid - 1) / wid; + } + else + { + int wid = FRAME_COLUMN_WIDTH (f); + FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid; + } + + /* Now make the frame display the given font. */ + if (FRAME_NS_WINDOW (f) != 0) + x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f)); + + return font_object; +} + + +Lisp_Object +ns_list_fonts (FRAME_PTR f, Lisp_Object pattern, int size, int maxnames) +/* -------------------------------------------------------------------------- + This is used by the xfaces system. It is expected to speak XLFD. + -------------------------------------------------------------------------- */ +{ + Lisp_Object list = Qnil, + rpattern, + key, + tem, + args[2]; + struct re_pattern_buffer *bufp; + id fm = [NSFontManager sharedFontManager]; + NSEnumerator *fenum, *senum; + NSArray *membInfo; + NSString *fontname; + const char *xlfdName; + char *pattFam; + char *patt; + NSString *famName; + + NSTRACE (ns_list_fonts); + + CHECK_STRING (pattern); + patt = XSTRING (pattern)->data; + +#if 0 +/* temporary: for font_backend, we use fontsets, and when these are defined, + the old XLFD-based system is used; eventually this will be replaced by + backend code, but for now we allow specs that are just family names */ + /* if pattern is not XLFD, panic now */ + if (patt[0] != '-') + error ("ns_list_fonts: X font name (XLFD) expected."); + + /* if unicode encoding not requested, also die */ + if (!strstr (patt, "iso10646") && patt[strlen (patt)-3] != '*') + return Qnil; +#endif /* 0 */ + + key = f ? Fcons (pattern, make_number (maxnames)) : Qnil; + tem = f ? XCDR (FRAME_NS_DISPLAY_INFO (f)->name_list_element) : Qnil; + + /* See if we cached the result for this particular query. + The cache is an alist of the form: + ((((PATTERN . MAXNAMES) FONTNAME) ...) ...) + */ + if (f && !NILP (list = Fassoc (key, tem))) + { + list = Fcdr_safe (list); + /* We have a cached list. Don't have to get the list again. */ + if (!NILP (list)) + return list; + } + + if (patt[0] != '-') + pattFam = patt; + else + pattFam = ns_xlfd_to_fontname (patt); + /*PENDING: '*' at beginning matches literally.. */ + if (pattFam[0] == '*') + pattFam[0] = '.'; + + /* must start w/family name, but can have other stuff afterwards + (usually bold and italic specifiers) */ + args[0] = build_string ("^"); + args[1] = build_string (pattFam); + rpattern = Fconcat (2, args); + bufp = compile_pattern (rpattern, 0, Vascii_canon_table, 0, 0); + + list = Qnil; + fenum = [[fm availableFontFamilies] objectEnumerator]; + while ( (famName = [fenum nextObject]) ) + { + NSMutableString *tmp = [famName mutableCopy]; + const char *fname; + NSRange r; + + /* remove spaces, to look like postscript name */ + while ((r = [tmp rangeOfString: @" "]).location != NSNotFound) + [tmp deleteCharactersInRange: r]; + + fname = [tmp UTF8String]; + int len = strlen (fname); + BOOL foundItal; + const char *synthItalFont; + + if (re_search (bufp, fname, len, 0, len, 0) >= 0) + { + /* Found a family. Add all variants. If we have no italic variant, + add a synthItal. */ + senum =[[fm availableMembersOfFontFamily: famName] objectEnumerator]; + foundItal = NO; + synthItalFont = NULL; + while (membInfo = [senum nextObject]) + { + xlfdName = + ns_fontname_to_xlfd ([[membInfo objectAtIndex: 0] UTF8String]); + list = Fcons (build_string (xlfdName), list); + if (!synthItalFont) + { + NSString *synthName = + [[membInfo objectAtIndex: 0] + stringByAppendingString: @"-synthItal"]; + synthItalFont = [synthName UTF8String]; + } + else if ([[membInfo objectAtIndex: 3] intValue] + & NSItalicFontMask) + foundItal = YES; + } + if (foundItal == NO) + { + xlfdName = ns_fontname_to_xlfd (synthItalFont); + list = Fcons (build_string (xlfdName), list); + } + } + [tmp release]; + } + + /* fallback */ + if (XFASTINT (Flength (list)) == 0) + list = Fcons (build_string (ns_fontname_to_xlfd ("Monaco")), list); + + /* store result in cache */ + if (f != NULL) + XCDR_AS_LVALUE (FRAME_NS_DISPLAY_INFO (f)->name_list_element) + = Fcons (Fcons (key, list), + XCDR (FRAME_NS_DISPLAY_INFO (f)->name_list_element)); + return list; +} + + +/* XLFD: -foundry-family-weight-slant-swidth-adstyle-pxlsz-ptSz-resx-resy-spc-avgWidth-rgstry-encoding */ + +const char * +ns_font_to_xlfd (NSFont *nsfont) +/* -------------------------------------------------------------------------- + Convert an NS font name to an X font name (XLFD). + The string returned is temporarily allocated. + -------------------------------------------------------------------------- */ +{ + NSFontManager *mgr = [NSFontManager sharedFontManager]; + NSString *sname = [nsfont /*familyName*/fontName]; + char *famName = [sname UTF8String]; + char *weightStr = [mgr fontNamed: sname hasTraits: NSBoldFontMask] ? + "bold" : "medium"; + char *slantStr = [mgr fontNamed: sname hasTraits: NSItalicFontMask] ? + "i" : "r"; + int size = [nsfont pointSize]; + int aWidth = lrint (10.0 * [nsfont widthOfString: @"a"]); + const char *xlfd; + int i, len; + + /* change '-' to '$' to avoid messing w/XLFD separator */ + for (len =strlen (famName), i =0; i /* GNU Emacs routines to deal with syntax tables; also word and list parsing. Copyright (C) 1985, 1987, 1993, 1994, 1995, 1997, 1998, 1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 @@ -298,6 +299,18 @@ register int quoted = 0; int orig = charpos; +#ifdef HAVE_NS + /* For some reason keeps getting called w/both 1, then segfaulting + due to the definitions of DEC_BOTH and DEC_POS in character.h, + which lead to decrementing below initial address and then examining + character there. Need to investigate further.. */ + if (charpos < 2 || bytepos < 2) + { + //fprintf(stderr,"Returning because charpos = %d, bytepos = %d\n",charpos, bytepos); + return 0; + } +#endif + DEC_BOTH (charpos, bytepos); while (charpos >= beg) diff -r ff312a846b25 -r d45acf0c8d23 src/sysselect.h --- a/src/sysselect.h Tue Jul 15 15:45:05 2008 +0000 +++ b/src/sysselect.h Tue Jul 15 18:15:18 2008 +0000 @@ -18,11 +18,11 @@ along with GNU Emacs. If not, see . */ #ifdef HAVE_SYS_SELECT_H -#if defined (DARWIN) || defined (MAC_OSX) +#if defined (DARWIN) || defined (MAC_OSX) || defined (NS_IMPL_COCOA) #undef init_process #endif #include -#if defined (DARWIN) || defined (MAC_OSX) +#if defined (DARWIN) || defined (MAC_OSX) || defined (NS_IMPL_COCOA) #define init_process emacs_init_process #endif #endif diff -r ff312a846b25 -r d45acf0c8d23 src/termhooks.h --- a/src/termhooks.h Tue Jul 15 15:45:05 2008 +0000 +++ b/src/termhooks.h Tue Jul 15 18:15:18 2008 +0000 @@ -318,6 +318,8 @@ struct mac_display_info; +struct ns_display_info; +struct x_display_info; struct w32_display_info; /* Terminal-local parameters. */ @@ -368,6 +370,7 @@ struct x_display_info *x; /* xterm.h */ struct w32_display_info *w32; /* w32term.h */ struct mac_display_info *mac; /* macterm.h */ + struct ns_display_info *ns; /* nsterm.h */ } display_info; diff -r ff312a846b25 -r d45acf0c8d23 src/terminal.c --- a/src/terminal.c Tue Jul 15 15:45:05 2008 +0000 +++ b/src/terminal.c Tue Jul 15 18:15:18 2008 +0000 @@ -397,6 +397,8 @@ return Qpc; case output_mac: return Qmac; + case output_ns: + return Qns; default: abort (); } diff -r ff312a846b25 -r d45acf0c8d23 src/terminfo.c --- a/src/terminfo.c Tue Jul 15 15:45:05 2008 +0000 +++ b/src/terminfo.c Tue Jul 15 18:15:18 2008 +0000 @@ -24,7 +24,10 @@ so that we do not need to conditionalize the places in Emacs that set them. */ +/* Causes a conflict on OS X 10.3 .*/ +#ifndef NS_IMPL_COCOA char *UP, *BC, PC; +#endif /* Interface to curses/terminfo library. Turns out that all of the terminfo-level routines look diff -r ff312a846b25 -r d45acf0c8d23 src/w32gui.h --- a/src/w32gui.h Tue Jul 15 15:45:05 2008 +0000 +++ b/src/w32gui.h Tue Jul 15 18:15:18 2008 +0000 @@ -21,66 +21,19 @@ #define EMACS_W32GUI_H #include +#include "w32bdf.h" -/* Emulate widget_value from ../lwlib/lwlib.h, modified for Windows. */ -typedef void * XtPointer; -typedef char Boolean; -enum button_type -{ - BUTTON_TYPE_NONE, - BUTTON_TYPE_TOGGLE, - BUTTON_TYPE_RADIO -}; -typedef struct _widget_value +/* Emulate XCharStruct. */ +typedef struct _XCharStruct { - /* name of widget */ - Lisp_Object lname; - char* name; - /* value (meaning depend on widget type) */ - char* value; - /* keyboard equivalent. no implications for XtTranslations */ - Lisp_Object lkey; - 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; + short rbearing; + short lbearing; + short width; + short ascent; + short descent; +} XCharStruct; - /* 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; + /* Local memory management for menus. */ #define local_heap (GetProcessHeap ()) #define local_alloc(n) (HeapAlloc (local_heap, HEAP_ZERO_MEMORY, (n))) @@ -89,6 +42,30 @@ #define malloc_widget_value() ((widget_value *) local_alloc (sizeof (widget_value))) #define free_widget_value(wv) (local_free ((wv))) + +enum w32_char_font_type +{ + UNKNOWN_FONT = 0 /* FONT_TYPE_UNKNOWN */, + ANSI_FONT, + UNICODE_FONT, + BDF_1D_FONT, + BDF_2D_FONT +}; + +typedef struct W32FontStruct { + enum w32_char_font_type font_type; + TEXTMETRIC tm; + HFONT hfont; + bdffont *bdf; + int double_byte_p; + XCharStruct max_bounds; + XCharStruct scratch; + /* Only store info for ascii chars, if not fixed pitch. */ + XCharStruct * per_char; +} W32FontStruct; + +typedef struct W32FontStruct XFontStruct; + /* Emulate X GC's by keeping color and font info in a structure. */ typedef struct _XGCValues { diff -r ff312a846b25 -r d45acf0c8d23 src/window.c --- a/src/window.c Tue Jul 15 15:45:05 2008 +0000 +++ b/src/window.c Tue Jul 15 18:15:18 2008 +0000 @@ -49,6 +49,9 @@ #ifdef MAC_OS #include "macterm.h" #endif +#ifdef HAVE_NS +#include "nsterm.h" +#endif Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p; diff -r ff312a846b25 -r d45acf0c8d23 src/xdisp.c --- a/src/xdisp.c Tue Jul 15 15:45:05 2008 +0000 +++ b/src/xdisp.c Tue Jul 15 18:15:18 2008 +0000 @@ -199,6 +199,9 @@ #ifdef MAC_OS #include "macterm.h" #endif +#ifdef HAVE_NS +#include "nsterm.h" +#endif #include "font.h" @@ -209,7 +212,7 @@ #define INFINITY 10000000 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \ - || defined (USE_GTK) + || defined(HAVE_NS) || defined (USE_GTK) extern void set_frame_menubar P_ ((struct frame *f, int, int)); extern int pending_menu_activation; #endif @@ -861,7 +864,7 @@ int hourglass_shown_p; /* If non-null, an asynchronous timer that, when it expires, displays - an hourglass cursor on all frames. */ + an hourglass cursor on all frames. */ struct atimer *hourglass_atimer; /* Number of seconds to wait before displaying an hourglass cursor. */ @@ -9462,7 +9465,32 @@ if (! STRINGP (f->name) || SBYTES (f->name) != len || bcmp (title, SDATA (f->name), len) != 0) - x_implicitly_set_name (f, make_string (title, len), Qnil); + { +#ifdef HAVE_NS + if (FRAME_NS_P (f)) + { + if (!MINI_WINDOW_P(XWINDOW(f->selected_window))) + { + if (EQ (fmt, Qt)) + ns_set_name_as_filename (f); + else + x_implicitly_set_name (f, make_string(title, len), + Qnil); + } + } + else +#endif + x_implicitly_set_name (f, make_string (title, len), Qnil); + } +#ifdef HAVE_NS + if (FRAME_NS_P (f)) + { + /* do this also for frames with explicit names */ + ns_implicitly_set_icon_type(f); + ns_set_doc_edited(f, Fbuffer_modified_p + (XWINDOW (f->selected_window)->buffer), Qnil); + } +#endif } } @@ -9627,7 +9655,7 @@ if (FRAME_WINDOW_P (f) ? #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \ - || defined (USE_GTK) + || defined (HAVE_NS) || defined (USE_GTK) FRAME_EXTERNAL_MENU_BAR (f) #else FRAME_MENU_BAR_LINES (f) > 0 @@ -9686,10 +9714,10 @@ /* Redisplay the menu bar in case we changed it. */ #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \ - || defined (USE_GTK) + || defined (HAVE_NS) || defined (USE_GTK) if (FRAME_WINDOW_P (f)) - { -#ifdef MAC_OS + { +#if defined (MAC_OS) || defined (HAVE_NS) /* All frames on Mac OS share the same menubar. So only the selected frame should be allowed to set it. */ if (f == SELECTED_FRAME ()) @@ -9700,11 +9728,11 @@ /* On a terminal screen, the menu bar is an ordinary screen line, and this makes it get updated. */ w->update_mode_line = Qt; -#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI || MAC_OS || USE_GTK) */ +#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI || MAC_OS || HAVE_NS || USE_GTK) */ /* In the non-toolkit version, the menu bar is an ordinary screen line, and this makes it get updated. */ w->update_mode_line = Qt; -#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI || MAC_OS || USE_GTK) */ +#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI || MAC_OS || HAVE_NS || USE_GTK) */ unbind_to (count, Qnil); set_buffer_internal_1 (prev); @@ -9815,7 +9843,7 @@ struct frame *f; int save_match_data; { -#if defined (USE_GTK) || USE_MAC_TOOLBAR +#if defined (USE_GTK) || defined (HAVE_NS) || USE_MAC_TOOLBAR int do_update = FRAME_EXTERNAL_TOOL_BAR (f); #else int do_update = WINDOWP (f->tool_bar_window) @@ -10281,7 +10309,7 @@ struct it it; struct glyph_row *row; -#if defined (USE_GTK) || USE_MAC_TOOLBAR +#if defined (USE_GTK) || defined (HAVE_NS) || USE_MAC_TOOLBAR if (FRAME_EXTERNAL_TOOL_BAR (f)) update_frame_tool_bar (f); return 0; @@ -11501,6 +11529,10 @@ /* Resized active mini-window to fit the size of what it is showing if its contents might have changed. */ must_finish = 1; +/* PENDING: this causes all frames to be updated, which seems unnecessary + since only the current frame needs to be considered. This function needs + to be rewritten with two variables, consider_all_windows and + consider_all_frames. */ consider_all_windows_p = 1; ++windows_or_buffers_changed; ++update_mode_lines; @@ -13913,7 +13945,7 @@ if (FRAME_WINDOW_P (f)) { #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \ - || defined (USE_GTK) + || defined (HAVE_NS) || defined (USE_GTK) redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f); #else redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0; @@ -13928,7 +13960,7 @@ #ifdef HAVE_WINDOW_SYSTEM if (FRAME_WINDOW_P (f)) { -#if defined (USE_GTK) || USE_MAC_TOOLBAR +#if defined (USE_GTK) || defined (HAVE_NS) || USE_MAC_TOOLBAR redisplay_tool_bar_p = FRAME_EXTERNAL_TOOL_BAR (f); #else redisplay_tool_bar_p = WINDOWP (f->tool_bar_window) @@ -17072,6 +17104,11 @@ return; #endif +#ifdef HAVE_NS + if (FRAME_NS_P (f)) + return; +#endif /* HAVE_NS */ + #ifdef USE_X_TOOLKIT xassert (!FRAME_WINDOW_P (f)); init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID); @@ -22539,7 +22576,10 @@ /* Switch the display of W's cursor on or off, according to the value of ON. */ -static void +#ifndef HAVE_NS +static +#endif +void update_window_cursor (w, on) struct window *w; int on; diff -r ff312a846b25 -r d45acf0c8d23 src/xfaces.c --- a/src/xfaces.c Tue Jul 15 15:45:05 2008 +0000 +++ b/src/xfaces.c Tue Jul 15 18:15:18 2008 +0000 @@ -244,6 +244,17 @@ #define check_x check_mac #endif /* MAC_OS */ +#ifdef HAVE_NS +#include "nsterm.h" +#undef FRAME_X_DISPLAY_INFO +#define FRAME_X_DISPLAY_INFO FRAME_NS_DISPLAY_INFO +#define x_display_info ns_display_info +#define FRAME_X_FONT_TABLE FRAME_NS_FONT_TABLE +#define check_x check_ns +#define x_list_fonts ns_list_fonts +#define GCGraphicsExposures 0 +#endif /* HAVE_NS */ + #include "buffer.h" #include "dispextern.h" #include "blockinput.h" @@ -556,6 +567,10 @@ extern Lisp_Object w32_list_fonts P_ ((struct frame *, Lisp_Object, int, int)); #endif /* WINDOWSNT */ +#ifdef HAVE_NS +extern Lisp_Object ns_list_fonts P_ ((struct frame *, Lisp_Object, int, int)); +#endif /* HAVE_NS */ + #ifdef USE_X_TOOLKIT static void x_update_menu_appearance P_ ((struct frame *)); @@ -766,6 +781,31 @@ #endif /* WINDOWSNT */ +#ifdef HAVE_NS +/* NS emulation of GCs */ + +static INLINE GC +x_create_gc (f, mask, xgcv) + struct frame *f; + unsigned long mask; + XGCValues *xgcv; +{ + GC gc = xmalloc (sizeof (*gc)); + if (gc) + bcopy(xgcv, gc, sizeof(XGCValues)); + return gc; +} + +static INLINE void +x_free_gc (f, gc) + struct frame *f; + GC gc; +{ + if (gc) + xfree (gc); +} +#endif /* HAVE_NS */ + #ifdef MAC_OS /* Mac OS emulation of GCs */ @@ -872,8 +912,11 @@ #ifdef MAC_OS if (!FRAME_MAC_P (f) || FRAME_MAC_WINDOW (f)) #endif +#ifdef HAVE_NS + if (!FRAME_NS_P (f) || FRAME_NS_WINDOW (f)) +#endif if (!realize_basic_faces (f)) - abort (); + abort (); } @@ -1269,6 +1312,10 @@ else if (FRAME_MAC_P (f)) return mac_defined_color (f, color_name, color_def, alloc); #endif +#ifdef HAVE_NS + else if (FRAME_NS_P (f)) + return ns_defined_color (f, color_name, color_def, alloc, 1); +#endif else abort (); } @@ -1558,6 +1605,7 @@ struct frame *f; struct face *face; { +/* PENDING(NS): need to do something here? */ #ifdef HAVE_X_WINDOWS if (face->colors_copied_bitwise_p) return; @@ -2754,7 +2802,7 @@ } else if (EQ (keyword, QCstipple)) { -#ifdef HAVE_X_WINDOWS +#if defined(HAVE_X_WINDOWS) || defined(HAVE_NS) Lisp_Object pixmap_p = Fbitmap_spec_p (value); if (!NILP (pixmap_p)) to[LFACE_STIPPLE_INDEX] = value; @@ -3262,14 +3310,14 @@ } else if (EQ (attr, QCstipple)) { -#ifdef HAVE_X_WINDOWS +#if defined(HAVE_X_WINDOWS) || defined(HAVE_NS) if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value) && !NILP (value) && NILP (Fbitmap_spec_p (value))) signal_error ("Invalid stipple attribute", value); old_value = LFACE_STIPPLE (lface); LFACE_STIPPLE (lface) = value; -#endif /* HAVE_X_WINDOWS */ +#endif /* HAVE_X_WINDOWS || HAVE_NS */ } else if (EQ (attr, QCwidth)) {